4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
7 *
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
12 *
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 *
19 * CDDL HEADER END
20 */
21
22 /*
23 * Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved.
24 * Copyright (c) 2014, Joyent, Inc. All rights reserved.
25 * Copyright 2017 RackTop Systems.
26 */
27
28 /*
29 * - General Introduction:
30 *
31 * This file contains the implementation of the MAC client kernel
32 * API and related code. The MAC client API allows a kernel module
33 * to gain access to a MAC instance (physical NIC, link aggregation, etc).
34 * It allows a MAC client to associate itself with a MAC address,
35 * VLANs, callback functions for data traffic and for promiscuous mode.
36 * The MAC client API is also used to specify the properties associated
37 * with a MAC client, such as bandwidth limits, priority, CPUS, etc.
38 * These properties are further used to determine the hardware resources
39 * to allocate to the various MAC clients.
40 *
41 * - Primary MAC clients:
42 *
43 * The MAC client API refers to "primary MAC clients". A primary MAC
44 * client is a client which "owns" the primary MAC address of
848 flow_entry_t *flent = mcip->mci_flent;
849 mac_address_t *map = mcip->mci_unicast;
850 flow_desc_t flow_desc;
851
852 ASSERT(MAC_PERIM_HELD((mac_handle_t)mip));
853 ASSERT(flent != NULL);
854
855 mac_flow_get_desc(flent, &flow_desc);
856 ASSERT(flow_desc.fd_mask & FLOW_LINK_DST);
857
858 bcopy(map->ma_addr, flow_desc.fd_dst_mac, map->ma_len);
859 mac_flow_set_desc(flent, &flow_desc);
860
861 /*
862 * The v6 local and SLAAC addrs (used by mac protection) need to be
863 * regenerated because our mac address has changed.
864 */
865 mac_protect_update_mac_token(mcip);
866
867 /*
868 * A MAC client could have one MAC address but multiple
869 * VLANs. In that case update the flow entries corresponding
870 * to all VLANs of the MAC client.
871 */
872 for (flent = mcip->mci_flent_list; flent != NULL;
873 flent = flent->fe_client_next) {
874 mac_flow_get_desc(flent, &flow_desc);
875 if (!(flent->fe_type & FLOW_PRIMARY_MAC ||
876 flent->fe_type & FLOW_VNIC_MAC))
877 continue;
878
879 bcopy(map->ma_addr, flow_desc.fd_dst_mac, map->ma_len);
880 mac_flow_set_desc(flent, &flow_desc);
881 }
882 }
883
884 /*
885 * Update all clients that share the same unicast address.
886 */
887 void
888 mac_unicast_update_clients(mac_impl_t *mip, mac_address_t *map)
889 {
890 mac_client_impl_t *mcip;
1008 {
1009 mac_impl_t *mip = (mac_impl_t *)mh;
1010 mac_address_t *map;
1011 int err;
1012
1013 /* verify the address validity */
1014 if (!mac_unicst_verify(mh, addr, mip->mi_type->mt_addr_length))
1015 return (EINVAL);
1016
1017 i_mac_perim_enter(mip);
1018
1019 /*
1020 * If the new value is the same as the current primary address value,
1021 * there's nothing to do.
1022 */
1023 if (bcmp(addr, mip->mi_addr, mip->mi_type->mt_addr_length) == 0) {
1024 i_mac_perim_exit(mip);
1025 return (0);
1026 }
1027
1028 if (mac_find_macaddr(mip, (uint8_t *)addr) != 0) {
1029 i_mac_perim_exit(mip);
1030 return (EBUSY);
1031 }
1032
1033 map = mac_find_macaddr(mip, mip->mi_addr);
1034 ASSERT(map != NULL);
1035
1036 /*
1037 * Update the MAC address.
1038 */
1039 if (mip->mi_state_flags & MIS_IS_AGGR) {
1040 mac_capab_aggr_t aggr_cap;
1041
1042 /*
1043 * If the mac is an aggregation, other than the unicast
1044 * addresses programming, aggr must be informed about this
1045 * primary unicst address change to change its mac address
1046 * policy to be user-specified.
1047 */
1048 ASSERT(map->ma_type == MAC_ADDRESS_TYPE_UNICAST_CLASSIFIED);
1049 VERIFY(i_mac_capab_get(mh, MAC_CAPAB_AGGR, &aggr_cap));
1050 err = aggr_cap.mca_unicst(mip->mi_driver, addr);
1051 if (err == 0)
1052 bcopy(addr, map->ma_addr, map->ma_len);
1053 } else {
1054 err = mac_update_macaddr(map, (uint8_t *)addr);
1055 }
1056
1057 if (err != 0) {
1058 i_mac_perim_exit(mip);
1059 return (err);
1060 }
1061
1062 mac_unicast_update_clients(mip, map);
1063
1064 /*
1065 * Save the new primary MAC address in mac_impl_t.
1357 mcip->mci_rx_arg = NULL;
1358 mcip->mci_rx_p_fn = NULL;
1359 mcip->mci_rx_p_arg = NULL;
1360 mcip->mci_p_unicast_list = NULL;
1361 mcip->mci_direct_rx_fn = NULL;
1362 mcip->mci_direct_rx_arg = NULL;
1363 mcip->mci_vidcache = MCIP_VIDCACHE_INVALID;
1364
1365 mcip->mci_unicast_list = NULL;
1366
1367 if ((flags & MAC_OPEN_FLAGS_IS_VNIC) != 0)
1368 mcip->mci_state_flags |= MCIS_IS_VNIC;
1369
1370 if ((flags & MAC_OPEN_FLAGS_EXCLUSIVE) != 0)
1371 mcip->mci_state_flags |= MCIS_EXCLUSIVE;
1372
1373 if ((flags & MAC_OPEN_FLAGS_IS_AGGR_PORT) != 0)
1374 mcip->mci_state_flags |= MCIS_IS_AGGR_PORT;
1375
1376 if (mip->mi_state_flags & MIS_IS_AGGR)
1377 mcip->mci_state_flags |= MCIS_IS_AGGR;
1378
1379 if ((flags & MAC_OPEN_FLAGS_USE_DATALINK_NAME) != 0) {
1380 datalink_id_t linkid;
1381
1382 ASSERT(name == NULL);
1383 if ((err = dls_devnet_macname2linkid(mip->mi_name,
1384 &linkid)) != 0) {
1385 goto done;
1386 }
1387 if ((err = dls_mgmt_get_linkinfo(linkid, mcip->mci_name, NULL,
1388 NULL, NULL)) != 0) {
1389 /*
1390 * Use mac name if dlmgmtd is not available.
1391 */
1392 if (err == EBADF) {
1393 (void) strlcpy(mcip->mci_name, mip->mi_name,
1394 sizeof (mcip->mci_name));
1395 err = 0;
1396 } else {
1397 goto done;
1522 /*
1523 * MAC clients must remove the unicast addresses and promisc callbacks
1524 * they added before issuing a mac_client_close().
1525 */
1526 ASSERT(mcip->mci_unicast_list == NULL);
1527 ASSERT(mcip->mci_promisc_list == NULL);
1528 ASSERT(mcip->mci_tx_notify_cb_list == NULL);
1529
1530 i_mac_share_free(mcip);
1531 mac_protect_fini(mcip);
1532 mac_client_remove(mcip);
1533
1534 i_mac_perim_exit(mip);
1535 mcip->mci_subflow_tab = NULL;
1536 mcip->mci_state_flags = 0;
1537 mcip->mci_tx_flag = 0;
1538 kmem_cache_free(mac_client_impl_cache, mch);
1539 }
1540
1541 /*
1542 * Set the rx bypass receive callback.
1543 */
1544 boolean_t
1545 mac_rx_bypass_set(mac_client_handle_t mch, mac_direct_rx_t rx_fn, void *arg1)
1546 {
1547 mac_client_impl_t *mcip = (mac_client_impl_t *)mch;
1548 mac_impl_t *mip = mcip->mci_mip;
1549
1550 ASSERT(MAC_PERIM_HELD((mac_handle_t)mip));
1551
1552 /*
1553 * If the mac_client is a VLAN, we should not do DLS bypass and
1554 * instead let the packets come up via mac_rx_deliver so the vlan
1555 * header can be stripped.
1556 */
1557 if (mcip->mci_nvids > 0)
1558 return (B_FALSE);
1559
1560 /*
1561 * These are not accessed directly in the data path, and hence
1562 * don't need any protection
1563 */
1564 mcip->mci_direct_rx_fn = rx_fn;
1565 mcip->mci_direct_rx_arg = arg1;
1566 return (B_TRUE);
1567 }
1568
1569 /*
1570 * Enable/Disable rx bypass. By default, bypass is assumed to be enabled.
1571 */
1572 void
1573 mac_rx_bypass_enable(mac_client_handle_t mch)
1574 {
1575 ((mac_client_impl_t *)mch)->mci_state_flags &= ~MCIS_RX_BYPASS_DISABLE;
1576 }
1577
1591 mac_client_impl_t *mcip = (mac_client_impl_t *)mch;
1592 mac_impl_t *mip = mcip->mci_mip;
1593 mac_impl_t *umip = mcip->mci_upper_mip;
1594
1595 /*
1596 * Instead of adding an extra set of locks and refcnts in
1597 * the datapath at the mac client boundary, we temporarily quiesce
1598 * the SRS and related entities. We then change the receive function
1599 * without interference from any receive data thread and then reenable
1600 * the data flow subsequently.
1601 */
1602 i_mac_perim_enter(mip);
1603 mac_rx_client_quiesce(mch);
1604
1605 mcip->mci_rx_fn = rx_fn;
1606 mcip->mci_rx_arg = arg;
1607 mac_rx_client_restart(mch);
1608 i_mac_perim_exit(mip);
1609
1610 /*
1611 * If we're changing the rx function on the primary mac of a vnic,
1612 * make sure any secondary macs on the vnic are updated as well.
1613 */
1614 if (umip != NULL) {
1615 ASSERT((umip->mi_state_flags & MIS_IS_VNIC) != 0);
1616 mac_vnic_secondary_update(umip);
1617 }
1618 }
1619
1620 /*
1621 * Reset the receive callback for the specified MAC client.
1622 */
1623 void
1624 mac_rx_clear(mac_client_handle_t mch)
1625 {
1626 mac_rx_set(mch, mac_pkt_drop, NULL);
1627 }
1628
1629 void
1630 mac_secondary_dup(mac_client_handle_t smch, mac_client_handle_t dmch)
1631 {
1632 mac_client_impl_t *smcip = (mac_client_impl_t *)smch;
1770 defgrp->
1771 mrg_cur_count - 1;
1772 }
1773 } else {
1774 cmrp->mrp_nrxrings = 1;
1775 }
1776 (void) mac_group_ring_modify(mcip,
1777 group, defgrp);
1778 } else {
1779 /*
1780 * If this is a static group, we
1781 * need to release the group. The
1782 * client will remain in the same
1783 * group till some other client
1784 * needs this group.
1785 */
1786 MAC_RX_GRP_RELEASED(mip);
1787 }
1788 /* Let check if we can give this an excl group */
1789 } else if (group == defgrp) {
1790 ngrp = mac_reserve_rx_group(mcip, mac_addr,
1791 B_TRUE);
1792 /* Couldn't give it a group, that's fine */
1793 if (ngrp == NULL)
1794 return (0);
1795 /* Switch to H/W */
1796 if (mac_rx_switch_group(mcip, defgrp, ngrp) !=
1797 0) {
1798 mac_stop_group(ngrp);
1799 return (0);
1800 }
1801 }
1802 /*
1803 * If the client is in the default group, we will
1804 * just clear the MRP_RX_RINGS and leave it as
1805 * it rather than look for an exclusive group
1806 * for it.
1807 */
1808 return (0);
1809 }
1810
1811 if (group == defgrp && ((mrp->mrp_nrxrings > 0) || unspec)) {
1812 ngrp = mac_reserve_rx_group(mcip, mac_addr, B_TRUE);
1813 if (ngrp == NULL)
1814 return (ENOSPC);
1815
1816 /* Switch to H/W */
1817 if (mac_rx_switch_group(mcip, defgrp, ngrp) != 0) {
1818 mac_release_rx_group(mcip, ngrp);
1819 return (ENOSPC);
1820 }
1821 MAC_RX_GRP_RESERVED(mip);
1822 if (mip->mi_rx_group_type == MAC_GROUP_TYPE_DYNAMIC)
1823 MAC_RX_RING_RESERVED(mip, ngrp->mrg_cur_count);
1824 } else if (group != defgrp && !unspec &&
1825 mrp->mrp_nrxrings == 0) {
1826 /* Switch to S/W */
1827 ringcnt = group->mrg_cur_count;
1828 if (mac_rx_switch_group(mcip, group, defgrp) != 0)
1829 return (ENOSPC);
1830 if (tmrp->mrp_mask & MRP_RX_RINGS) {
1831 MAC_RX_GRP_RELEASED(mip);
2149 * from the SRS code, we'll keep them for now. They're currently
2150 * consumed by mac_datapath_setup() to create the SRS.
2151 * That code should be eventually moved out of
2152 * mac_datapath_setup() and moved to a mac_srs_create()
2153 * function of some sort to keep things clean.
2154 *
2155 * Also, there's no reason why the SRS for the primary MAC
2156 * client should be different than any other MAC client. Until
2157 * this is cleaned-up, we support only one MAC unicast address
2158 * per client.
2159 *
2160 * We set FLOW_PRIMARY_MAC for the primary MAC address,
2161 * FLOW_VNIC for everything else.
2162 */
2163 if (is_primary)
2164 flent_flags = FLOW_PRIMARY_MAC;
2165 else
2166 flent_flags = FLOW_VNIC_MAC;
2167
2168 /*
2169 * For the first flow we use the mac client's name - mci_name, for
2170 * subsequent ones we just create a name with the vid. This is
2171 * so that we can add these flows to the same flow table. This is
2172 * fine as the flow name (except for the one with the mac client's
2173 * name) is not visible. When the first flow is removed, we just replace
2174 * its fdesc with another from the list, so we will still retain the
2175 * flent with the MAC client's flow name.
2176 */
2177 if (first_flow) {
2178 bcopy(mcip->mci_name, flowname, MAXFLOWNAMELEN);
2179 } else {
2180 (void) sprintf(flowname, "%s%u", mcip->mci_name, vid);
2181 flent_flags = FLOW_NO_STATS;
2182 }
2183
2184 if ((err = mac_flow_create(&flow_desc, mrp, flowname, NULL,
2185 flent_flags, flent)) != 0)
2186 return (err);
2187
2188 mac_misc_stat_create(*flent);
2189 FLOW_MARK(*flent, FE_INCIPIENT);
2190 (*flent)->fe_mcip = mcip;
2191
2192 /*
2310 if ((err = mac_unicast_flow_create(mcip, mac_addr, vid,
2311 isprimary, B_TRUE, &flent, mrp)) != 0)
2312 goto bail;
2313
2314 mip->mi_nactiveclients++;
2315 nactiveclients_added = B_TRUE;
2316
2317 /*
2318 * This will allocate the RX ring group if possible for the
2319 * flow and program the software classifier as needed.
2320 */
2321 if ((err = mac_datapath_setup(mcip, flent, SRST_LINK)) != 0)
2322 goto bail;
2323
2324 if (no_unicast)
2325 goto done_setup;
2326 /*
2327 * The unicast MAC address must have been added successfully.
2328 */
2329 ASSERT(mcip->mci_unicast != NULL);
2330 /*
2331 * Push down the sub-flows that were defined on this link
2332 * hitherto. The flows are added to the active flow table
2333 * and SRS, softrings etc. are created as needed.
2334 */
2335 mac_link_init_flows((mac_client_handle_t)mcip);
2336 } else {
2337 mac_address_t *map = mcip->mci_unicast;
2338
2339 ASSERT(!no_unicast);
2340 /*
2341 * A unicast flow already exists for that MAC client,
2342 * this flow must be the same mac address but with
2343 * different VID. It has been checked by mac_addr_in_use().
2344 *
2345 * We will use the SRS etc. from the mci_flent. Note that
2346 * We don't need to create kstat for this as except for
2347 * the fdesc, everything will be used from in the 1st flent.
2348 */
2349
2350 if (bcmp(mac_addr, map->ma_addr, map->ma_len) != 0) {
2351 err = EINVAL;
2352 goto bail;
2353 }
2354
2355 if ((err = mac_unicast_flow_create(mcip, mac_addr, vid,
2356 isprimary, B_FALSE, &flent, NULL)) != 0) {
2357 goto bail;
2358 }
2359 if ((err = mac_flow_add(mip->mi_flow_tab, flent)) != 0) {
2360 FLOW_FINAL_REFRELE(flent);
2361 goto bail;
2362 }
2363
2364 /* update the multicast group for this vid */
2365 mac_client_bcast_refresh(mcip, mac_client_update_mcast,
2366 (void *)flent, B_TRUE);
2367
2368 }
2369
2458 * In no case can a client use the PVID for the MAC, if the MAC has one set.
2459 */
2460 int
2461 i_mac_unicast_add(mac_client_handle_t mch, uint8_t *mac_addr, uint16_t flags,
2462 mac_unicast_handle_t *mah, uint16_t vid, mac_diag_t *diag)
2463 {
2464 mac_client_impl_t *mcip = (mac_client_impl_t *)mch;
2465 mac_impl_t *mip = mcip->mci_mip;
2466 int err;
2467 uint_t mac_len = mip->mi_type->mt_addr_length;
2468 boolean_t check_dups = !(flags & MAC_UNICAST_NODUPCHECK);
2469 boolean_t fastpath_disabled = B_FALSE;
2470 boolean_t is_primary = (flags & MAC_UNICAST_PRIMARY);
2471 boolean_t is_unicast_hw = (flags & MAC_UNICAST_HW);
2472 mac_resource_props_t *mrp;
2473 boolean_t passive_client = B_FALSE;
2474 mac_unicast_impl_t *muip;
2475 boolean_t is_vnic_primary =
2476 (flags & MAC_UNICAST_VNIC_PRIMARY);
2477
2478 /* when VID is non-zero, the underlying MAC can not be VNIC */
2479 ASSERT(!((mip->mi_state_flags & MIS_IS_VNIC) && (vid != 0)));
2480
2481 /*
2482 * Can't unicast add if the client asked only for minimal datapath
2483 * setup.
2484 */
2485 if (mcip->mci_state_flags & MCIS_NO_UNICAST_ADDR)
2486 return (ENOTSUP);
2487
2488 /*
2489 * Check for an attempted use of the current Port VLAN ID, if enabled.
2490 * No client may use it.
2491 */
2492 if (mip->mi_pvid != 0 && vid == mip->mi_pvid)
2493 return (EBUSY);
2494
2495 /*
2496 * Check whether it's the primary client and flag it.
2497 */
2498 if (!(mcip->mci_state_flags & MCIS_IS_VNIC) && is_primary && vid == 0)
2499 mcip->mci_flags |= MAC_CLIENT_FLAGS_PRIMARY;
2500
2501 /*
2502 * is_vnic_primary is true when we come here as a VLAN VNIC
2503 * which uses the primary mac client's address but with a non-zero
2504 * VID. In this case the MAC address is not specified by an upper
2505 * MAC client.
2506 */
2507 if ((mcip->mci_state_flags & MCIS_IS_VNIC) && is_primary &&
2508 !is_vnic_primary) {
2509 /*
2510 * The address is being set by the upper MAC client
2511 * of a VNIC. The MAC address was already set by the
2512 * VNIC driver during VNIC creation.
2513 *
2514 * Note: a VNIC has only one MAC address. We return
2515 * the MAC unicast address handle of the lower MAC client
2516 * corresponding to the VNIC. We allocate a new entry
2517 * which is flagged appropriately, so that mac_unicast_remove()
2518 * doesn't attempt to free the original entry that
2519 * was allocated by the VNIC driver.
2520 */
2521 ASSERT(mcip->mci_unicast != NULL);
2522
2523 /* Check for VLAN flags, if present */
2535 * is added only once unless we have the
2536 * MAC_CLIENT_FLAGS_MULTI_PRIMARY set (and this is not
2537 * a passive MAC client).
2538 */
2539 if ((mcip->mci_flags & MAC_CLIENT_FLAGS_VNIC_PRIMARY) != 0) {
2540 if ((mcip->mci_flags &
2541 MAC_CLIENT_FLAGS_MULTI_PRIMARY) == 0 ||
2542 (mcip->mci_flags &
2543 MAC_CLIENT_FLAGS_PASSIVE_PRIMARY) != 0) {
2544 return (EBUSY);
2545 }
2546 mcip->mci_flags |= MAC_CLIENT_FLAGS_PASSIVE_PRIMARY;
2547 passive_client = B_TRUE;
2548 }
2549
2550 mcip->mci_flags |= MAC_CLIENT_FLAGS_VNIC_PRIMARY;
2551
2552 /*
2553 * Create a handle for vid 0.
2554 */
2555 ASSERT(vid == 0);
2556 muip = kmem_zalloc(sizeof (mac_unicast_impl_t), KM_SLEEP);
2557 muip->mui_vid = vid;
2558 *mah = (mac_unicast_handle_t)muip;
2559 /*
2560 * This will be used by the caller to defer setting the
2561 * rx functions.
2562 */
2563 if (passive_client)
2564 return (EAGAIN);
2565 return (0);
2566 }
2567
2568 /* primary MAC clients cannot be opened on top of anchor VNICs */
2569 if ((is_vnic_primary || is_primary) &&
2570 i_mac_capab_get((mac_handle_t)mip, MAC_CAPAB_ANCHOR_VNIC, NULL)) {
2571 return (ENXIO);
2572 }
2573
2574 /*
2575 * If this is a VNIC/VLAN, disable softmac fast-path.
2576 */
2577 if (mcip->mci_state_flags & MCIS_IS_VNIC) {
2578 err = mac_fastpath_disable((mac_handle_t)mip);
2579 if (err != 0)
2580 return (err);
2581 fastpath_disabled = B_TRUE;
2582 }
2583
2584 /*
2585 * Return EBUSY if:
2586 * - there is an exclusively active mac client exists.
2587 * - this is an exclusive active mac client but
2588 * a. there is already active mac clients exist, or
2589 * b. fastpath streams are already plumbed on this legacy device
2590 * - the mac creator has disallowed active mac clients.
2591 */
2592 if (mip->mi_state_flags & (MIS_EXCLUSIVE|MIS_NO_ACTIVE)) {
2593 if (fastpath_disabled)
2594 mac_fastpath_enable((mac_handle_t)mip);
2595 return (EBUSY);
2603 if ((mip->mi_state_flags & MIS_LEGACY) &&
2604 !(mip->mi_capab_legacy.ml_active_set(mip->mi_driver))) {
2605 return (EBUSY);
2606 }
2607 mip->mi_state_flags |= MIS_EXCLUSIVE;
2608 }
2609
2610 mrp = kmem_zalloc(sizeof (*mrp), KM_SLEEP);
2611 if (is_primary && !(mcip->mci_state_flags & (MCIS_IS_VNIC |
2612 MCIS_IS_AGGR_PORT))) {
2613 /*
2614 * Apply the property cached in the mac_impl_t to the primary
2615 * mac client. If the mac client is a VNIC or an aggregation
2616 * port, its property should be set in the mcip when the
2617 * VNIC/aggr was created.
2618 */
2619 mac_get_resources((mac_handle_t)mip, mrp);
2620 (void) mac_client_set_resources(mch, mrp);
2621 } else if (mcip->mci_state_flags & MCIS_IS_VNIC) {
2622 /*
2623 * This is a primary VLAN client, we don't support
2624 * specifying rings property for this as it inherits the
2625 * rings property from its MAC.
2626 */
2627 if (is_vnic_primary) {
2628 mac_resource_props_t *vmrp;
2629
2630 vmrp = MCIP_RESOURCE_PROPS(mcip);
2631 if (vmrp->mrp_mask & MRP_RX_RINGS ||
2632 vmrp->mrp_mask & MRP_TX_RINGS) {
2633 if (fastpath_disabled)
2634 mac_fastpath_enable((mac_handle_t)mip);
2635 kmem_free(mrp, sizeof (*mrp));
2636 return (ENOTSUP);
2637 }
2638 /*
2639 * Additionally we also need to inherit any
2640 * rings property from the MAC.
2641 */
2642 mac_get_resources((mac_handle_t)mip, mrp);
2643 if (mrp->mrp_mask & MRP_RX_RINGS) {
2644 vmrp->mrp_mask |= MRP_RX_RINGS;
2645 vmrp->mrp_nrxrings = mrp->mrp_nrxrings;
2967 mac_fastpath_enable((mac_handle_t)mip);
2968 mac_stop((mac_handle_t)mip);
2969 }
2970
2971 /*
2972 * Remove a MAC address which was previously added by mac_unicast_add().
2973 */
2974 int
2975 mac_unicast_remove(mac_client_handle_t mch, mac_unicast_handle_t mah)
2976 {
2977 mac_client_impl_t *mcip = (mac_client_impl_t *)mch;
2978 mac_unicast_impl_t *muip = (mac_unicast_impl_t *)mah;
2979 mac_unicast_impl_t *pre;
2980 mac_impl_t *mip = mcip->mci_mip;
2981 flow_entry_t *flent;
2982 uint16_t mui_vid;
2983
2984 i_mac_perim_enter(mip);
2985 if (mcip->mci_flags & MAC_CLIENT_FLAGS_VNIC_PRIMARY) {
2986 /*
2987 * Called made by the upper MAC client of a VNIC.
2988 * There's nothing much to do, the unicast address will
2989 * be removed by the VNIC driver when the VNIC is deleted,
2990 * but let's ensure that all our transmit is done before
2991 * the client does a mac_client_stop lest it trigger an
2992 * assert in the driver.
2993 */
2994 ASSERT(muip->mui_vid == 0);
2995
2996 mac_tx_client_flush(mcip);
2997
2998 if ((mcip->mci_flags & MAC_CLIENT_FLAGS_PASSIVE_PRIMARY) != 0) {
2999 mcip->mci_flags &= ~MAC_CLIENT_FLAGS_PASSIVE_PRIMARY;
3000 if (mcip->mci_rx_p_fn != NULL) {
3001 mac_rx_set(mch, mcip->mci_rx_p_fn,
3002 mcip->mci_rx_p_arg);
3003 mcip->mci_rx_p_fn = NULL;
3004 mcip->mci_rx_p_arg = NULL;
3005 }
3006 kmem_free(muip, sizeof (mac_unicast_impl_t));
3007 i_mac_perim_exit(mip);
3008 return (0);
3009 }
3010 mcip->mci_flags &= ~MAC_CLIENT_FLAGS_VNIC_PRIMARY;
3011
3012 if (mcip->mci_state_flags & MCIS_TAG_DISABLE)
3013 mcip->mci_state_flags &= ~MCIS_TAG_DISABLE;
3014
3038
3039 mcip->mci_p_unicast_list = NULL;
3040 mcip->mci_rx_p_fn = NULL;
3041 mcip->mci_rx_p_arg = NULL;
3042
3043 mcip->mci_state_flags &= ~MCIS_UNICAST_HW;
3044
3045 if (mcip->mci_state_flags & MCIS_TAG_DISABLE)
3046 mcip->mci_state_flags &= ~MCIS_TAG_DISABLE;
3047
3048 if (mcip->mci_state_flags & MCIS_STRIP_DISABLE)
3049 mcip->mci_state_flags &= ~MCIS_STRIP_DISABLE;
3050
3051 if (mcip->mci_state_flags & MCIS_DISABLE_TX_VID_CHECK)
3052 mcip->mci_state_flags &= ~MCIS_DISABLE_TX_VID_CHECK;
3053
3054 kmem_free(muip, sizeof (mac_unicast_impl_t));
3055 i_mac_perim_exit(mip);
3056 return (0);
3057 }
3058 /*
3059 * Remove the VID from the list of client's VIDs.
3060 */
3061 pre = mcip->mci_unicast_list;
3062 if (muip == pre) {
3063 mcip->mci_unicast_list = muip->mui_next;
3064 } else {
3065 while ((pre->mui_next != NULL) && (pre->mui_next != muip))
3066 pre = pre->mui_next;
3067 ASSERT(pre->mui_next == muip);
3068 rw_enter(&mcip->mci_rw_lock, RW_WRITER);
3069 pre->mui_next = muip->mui_next;
3070 rw_exit(&mcip->mci_rw_lock);
3071 }
3072
3073 if (!mac_client_single_rcvr(mcip)) {
3074 /*
3075 * This MAC client is shared by more than one unicast
3076 * addresses, so we will just remove the flent
3077 * corresponding to the address being removed. We don't invoke
3078 * mac_rx_classify_flow_rem() since the additional flow is
3079 * not associated with its own separate set of SRS and rings,
3080 * and these constructs are still needed for the remaining
3081 * flows.
3082 */
3083 flent = mac_client_get_flow(mcip, muip);
3084 ASSERT(flent != NULL);
3085
3086 /*
3087 * The first one is disappearing, need to make sure
3088 * we replace it with another from the list of
3089 * shared clients.
3090 */
3091 if (flent == mcip->mci_flent)
3092 flent = mac_client_swap_mciflent(mcip);
3093 mac_client_remove_flow_from_list(mcip, flent);
3094 mac_flow_remove(mip->mi_flow_tab, flent, B_FALSE);
3095 mac_flow_wait(flent, FLOW_DRIVER_UPCALL);
3096
3097 /*
3098 * The multicast groups that were added by the client so
3099 * far must be removed from the brodcast domain corresponding
3100 * to the VID being removed.
3101 */
3102 mac_client_bcast_refresh(mcip, mac_client_update_mcast,
3103 (void *)flent, B_FALSE);
3104
3105 if (mip->mi_type->mt_brdcst_addr != NULL) {
3106 mac_bcast_delete(mcip, mip->mi_type->mt_brdcst_addr,
3107 muip->mui_vid);
3108 }
3109
3110 FLOW_FINAL_REFRELE(flent);
3111 ASSERT(!(mcip->mci_state_flags & MCIS_EXCLUSIVE));
3112 /*
3113 * Enable fastpath if this is a VNIC or a VLAN.
3114 */
3115 if (mcip->mci_state_flags & MCIS_IS_VNIC)
3116 mac_fastpath_enable((mac_handle_t)mip);
3117 mac_stop((mac_handle_t)mip);
3118 i_mac_perim_exit(mip);
3119 return (0);
3120 }
3121
3122 mui_vid = muip->mui_vid;
3123 mac_client_datapath_teardown(mch, muip, flent);
3124
3125 if ((mcip->mci_flags & MAC_CLIENT_FLAGS_PRIMARY) && mui_vid == 0) {
3126 mcip->mci_flags &= ~MAC_CLIENT_FLAGS_PRIMARY;
3127 } else {
3128 i_mac_perim_exit(mip);
3129 return (0);
3130 }
3131
3132 /*
3133 * If we are removing the primary, check if we have a passive primary
3134 * client that we need to activate now.
3135 */
3136 mcip = mac_get_passive_primary_client(mip);
3137 if (mcip != NULL) {
3138 mac_resource_props_t *mrp;
3139 mac_unicast_impl_t *muip;
3140
3141 mcip->mci_flags &= ~MAC_CLIENT_FLAGS_PASSIVE_PRIMARY;
3142 mrp = kmem_zalloc(sizeof (*mrp), KM_SLEEP);
3143
3144 /*
3145 * Apply the property cached in the mac_impl_t to the
|
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
7 *
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
12 *
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 *
19 * CDDL HEADER END
20 */
21
22 /*
23 * Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved.
24 * Copyright 2018 Joyent, Inc.
25 * Copyright 2017 RackTop Systems.
26 */
27
28 /*
29 * - General Introduction:
30 *
31 * This file contains the implementation of the MAC client kernel
32 * API and related code. The MAC client API allows a kernel module
33 * to gain access to a MAC instance (physical NIC, link aggregation, etc).
34 * It allows a MAC client to associate itself with a MAC address,
35 * VLANs, callback functions for data traffic and for promiscuous mode.
36 * The MAC client API is also used to specify the properties associated
37 * with a MAC client, such as bandwidth limits, priority, CPUS, etc.
38 * These properties are further used to determine the hardware resources
39 * to allocate to the various MAC clients.
40 *
41 * - Primary MAC clients:
42 *
43 * The MAC client API refers to "primary MAC clients". A primary MAC
44 * client is a client which "owns" the primary MAC address of
848 flow_entry_t *flent = mcip->mci_flent;
849 mac_address_t *map = mcip->mci_unicast;
850 flow_desc_t flow_desc;
851
852 ASSERT(MAC_PERIM_HELD((mac_handle_t)mip));
853 ASSERT(flent != NULL);
854
855 mac_flow_get_desc(flent, &flow_desc);
856 ASSERT(flow_desc.fd_mask & FLOW_LINK_DST);
857
858 bcopy(map->ma_addr, flow_desc.fd_dst_mac, map->ma_len);
859 mac_flow_set_desc(flent, &flow_desc);
860
861 /*
862 * The v6 local and SLAAC addrs (used by mac protection) need to be
863 * regenerated because our mac address has changed.
864 */
865 mac_protect_update_mac_token(mcip);
866
867 /*
868 * When there are multiple VLANs sharing the same MAC address,
869 * each gets its own MAC client, except when running on sun4v
870 * vsw. In that case the mci_flent_list is used to place
871 * multiple VLAN flows on one MAC client. If we ever get rid
872 * of vsw then this code can go, but until then we need to
873 * update all flow entries.
874 */
875 for (flent = mcip->mci_flent_list; flent != NULL;
876 flent = flent->fe_client_next) {
877 mac_flow_get_desc(flent, &flow_desc);
878 if (!(flent->fe_type & FLOW_PRIMARY_MAC ||
879 flent->fe_type & FLOW_VNIC_MAC))
880 continue;
881
882 bcopy(map->ma_addr, flow_desc.fd_dst_mac, map->ma_len);
883 mac_flow_set_desc(flent, &flow_desc);
884 }
885 }
886
887 /*
888 * Update all clients that share the same unicast address.
889 */
890 void
891 mac_unicast_update_clients(mac_impl_t *mip, mac_address_t *map)
892 {
893 mac_client_impl_t *mcip;
1011 {
1012 mac_impl_t *mip = (mac_impl_t *)mh;
1013 mac_address_t *map;
1014 int err;
1015
1016 /* verify the address validity */
1017 if (!mac_unicst_verify(mh, addr, mip->mi_type->mt_addr_length))
1018 return (EINVAL);
1019
1020 i_mac_perim_enter(mip);
1021
1022 /*
1023 * If the new value is the same as the current primary address value,
1024 * there's nothing to do.
1025 */
1026 if (bcmp(addr, mip->mi_addr, mip->mi_type->mt_addr_length) == 0) {
1027 i_mac_perim_exit(mip);
1028 return (0);
1029 }
1030
1031 if (mac_find_macaddr(mip, (uint8_t *)addr) != NULL) {
1032 i_mac_perim_exit(mip);
1033 return (EBUSY);
1034 }
1035
1036 map = mac_find_macaddr(mip, mip->mi_addr);
1037 ASSERT(map != NULL);
1038
1039 /*
1040 * Update the MAC address.
1041 */
1042 if (mip->mi_state_flags & MIS_IS_AGGR) {
1043 mac_capab_aggr_t aggr_cap;
1044
1045 /*
1046 * If the MAC is an aggregation, other than the unicast
1047 * addresses programming, aggr must be informed about this
1048 * primary unicst address change to change its MAC address
1049 * policy to be user-specified.
1050 */
1051 ASSERT(map->ma_type == MAC_ADDRESS_TYPE_UNICAST_CLASSIFIED);
1052 VERIFY(i_mac_capab_get(mh, MAC_CAPAB_AGGR, &aggr_cap));
1053 err = aggr_cap.mca_unicst(mip->mi_driver, addr);
1054 if (err == 0)
1055 bcopy(addr, map->ma_addr, map->ma_len);
1056 } else {
1057 err = mac_update_macaddr(map, (uint8_t *)addr);
1058 }
1059
1060 if (err != 0) {
1061 i_mac_perim_exit(mip);
1062 return (err);
1063 }
1064
1065 mac_unicast_update_clients(mip, map);
1066
1067 /*
1068 * Save the new primary MAC address in mac_impl_t.
1360 mcip->mci_rx_arg = NULL;
1361 mcip->mci_rx_p_fn = NULL;
1362 mcip->mci_rx_p_arg = NULL;
1363 mcip->mci_p_unicast_list = NULL;
1364 mcip->mci_direct_rx_fn = NULL;
1365 mcip->mci_direct_rx_arg = NULL;
1366 mcip->mci_vidcache = MCIP_VIDCACHE_INVALID;
1367
1368 mcip->mci_unicast_list = NULL;
1369
1370 if ((flags & MAC_OPEN_FLAGS_IS_VNIC) != 0)
1371 mcip->mci_state_flags |= MCIS_IS_VNIC;
1372
1373 if ((flags & MAC_OPEN_FLAGS_EXCLUSIVE) != 0)
1374 mcip->mci_state_flags |= MCIS_EXCLUSIVE;
1375
1376 if ((flags & MAC_OPEN_FLAGS_IS_AGGR_PORT) != 0)
1377 mcip->mci_state_flags |= MCIS_IS_AGGR_PORT;
1378
1379 if (mip->mi_state_flags & MIS_IS_AGGR)
1380 mcip->mci_state_flags |= MCIS_IS_AGGR_CLIENT;
1381
1382 if ((flags & MAC_OPEN_FLAGS_USE_DATALINK_NAME) != 0) {
1383 datalink_id_t linkid;
1384
1385 ASSERT(name == NULL);
1386 if ((err = dls_devnet_macname2linkid(mip->mi_name,
1387 &linkid)) != 0) {
1388 goto done;
1389 }
1390 if ((err = dls_mgmt_get_linkinfo(linkid, mcip->mci_name, NULL,
1391 NULL, NULL)) != 0) {
1392 /*
1393 * Use mac name if dlmgmtd is not available.
1394 */
1395 if (err == EBADF) {
1396 (void) strlcpy(mcip->mci_name, mip->mi_name,
1397 sizeof (mcip->mci_name));
1398 err = 0;
1399 } else {
1400 goto done;
1525 /*
1526 * MAC clients must remove the unicast addresses and promisc callbacks
1527 * they added before issuing a mac_client_close().
1528 */
1529 ASSERT(mcip->mci_unicast_list == NULL);
1530 ASSERT(mcip->mci_promisc_list == NULL);
1531 ASSERT(mcip->mci_tx_notify_cb_list == NULL);
1532
1533 i_mac_share_free(mcip);
1534 mac_protect_fini(mcip);
1535 mac_client_remove(mcip);
1536
1537 i_mac_perim_exit(mip);
1538 mcip->mci_subflow_tab = NULL;
1539 mcip->mci_state_flags = 0;
1540 mcip->mci_tx_flag = 0;
1541 kmem_cache_free(mac_client_impl_cache, mch);
1542 }
1543
1544 /*
1545 * Set the Rx bypass receive callback and return B_TRUE. Return
1546 * B_FALSE if it's not possible to enable bypass.
1547 */
1548 boolean_t
1549 mac_rx_bypass_set(mac_client_handle_t mch, mac_direct_rx_t rx_fn, void *arg1)
1550 {
1551 mac_client_impl_t *mcip = (mac_client_impl_t *)mch;
1552 mac_impl_t *mip = mcip->mci_mip;
1553
1554 ASSERT(MAC_PERIM_HELD((mac_handle_t)mip));
1555
1556 /*
1557 * If the client has more than one VLAN then process packets
1558 * through DLS. This should happen only when sun4v vsw is on
1559 * the scene.
1560 */
1561 if (mcip->mci_nvids > 1)
1562 return (B_FALSE);
1563
1564 /*
1565 * These are not accessed directly in the data path, and hence
1566 * don't need any protection
1567 */
1568 mcip->mci_direct_rx_fn = rx_fn;
1569 mcip->mci_direct_rx_arg = arg1;
1570 return (B_TRUE);
1571 }
1572
1573 /*
1574 * Enable/Disable rx bypass. By default, bypass is assumed to be enabled.
1575 */
1576 void
1577 mac_rx_bypass_enable(mac_client_handle_t mch)
1578 {
1579 ((mac_client_impl_t *)mch)->mci_state_flags &= ~MCIS_RX_BYPASS_DISABLE;
1580 }
1581
1595 mac_client_impl_t *mcip = (mac_client_impl_t *)mch;
1596 mac_impl_t *mip = mcip->mci_mip;
1597 mac_impl_t *umip = mcip->mci_upper_mip;
1598
1599 /*
1600 * Instead of adding an extra set of locks and refcnts in
1601 * the datapath at the mac client boundary, we temporarily quiesce
1602 * the SRS and related entities. We then change the receive function
1603 * without interference from any receive data thread and then reenable
1604 * the data flow subsequently.
1605 */
1606 i_mac_perim_enter(mip);
1607 mac_rx_client_quiesce(mch);
1608
1609 mcip->mci_rx_fn = rx_fn;
1610 mcip->mci_rx_arg = arg;
1611 mac_rx_client_restart(mch);
1612 i_mac_perim_exit(mip);
1613
1614 /*
1615 * If we're changing the Rx function on the primary MAC of a VNIC,
1616 * make sure any secondary addresses on the VNIC are updated as well.
1617 */
1618 if (umip != NULL) {
1619 ASSERT((umip->mi_state_flags & MIS_IS_VNIC) != 0);
1620 mac_vnic_secondary_update(umip);
1621 }
1622 }
1623
1624 /*
1625 * Reset the receive callback for the specified MAC client.
1626 */
1627 void
1628 mac_rx_clear(mac_client_handle_t mch)
1629 {
1630 mac_rx_set(mch, mac_pkt_drop, NULL);
1631 }
1632
1633 void
1634 mac_secondary_dup(mac_client_handle_t smch, mac_client_handle_t dmch)
1635 {
1636 mac_client_impl_t *smcip = (mac_client_impl_t *)smch;
1774 defgrp->
1775 mrg_cur_count - 1;
1776 }
1777 } else {
1778 cmrp->mrp_nrxrings = 1;
1779 }
1780 (void) mac_group_ring_modify(mcip,
1781 group, defgrp);
1782 } else {
1783 /*
1784 * If this is a static group, we
1785 * need to release the group. The
1786 * client will remain in the same
1787 * group till some other client
1788 * needs this group.
1789 */
1790 MAC_RX_GRP_RELEASED(mip);
1791 }
1792 /* Let check if we can give this an excl group */
1793 } else if (group == defgrp) {
1794 /*
1795 * If multiple clients share an
1796 * address then they must stay on the
1797 * default group.
1798 */
1799 if (mac_check_macaddr_shared(mcip->mci_unicast))
1800 return (0);
1801
1802 ngrp = mac_reserve_rx_group(mcip, mac_addr,
1803 B_TRUE);
1804 /* Couldn't give it a group, that's fine */
1805 if (ngrp == NULL)
1806 return (0);
1807 /* Switch to H/W */
1808 if (mac_rx_switch_group(mcip, defgrp, ngrp) !=
1809 0) {
1810 mac_stop_group(ngrp);
1811 return (0);
1812 }
1813 }
1814 /*
1815 * If the client is in the default group, we will
1816 * just clear the MRP_RX_RINGS and leave it as
1817 * it rather than look for an exclusive group
1818 * for it.
1819 */
1820 return (0);
1821 }
1822
1823 if (group == defgrp && ((mrp->mrp_nrxrings > 0) || unspec)) {
1824 /*
1825 * We are requesting Rx rings. Try to reserve
1826 * a non-default group.
1827 *
1828 * If multiple clients share an address then
1829 * they must stay on the default group.
1830 */
1831 if (mac_check_macaddr_shared(mcip->mci_unicast))
1832 return (EINVAL);
1833
1834 ngrp = mac_reserve_rx_group(mcip, mac_addr, B_TRUE);
1835 if (ngrp == NULL)
1836 return (ENOSPC);
1837
1838 /* Switch to H/W */
1839 if (mac_rx_switch_group(mcip, defgrp, ngrp) != 0) {
1840 mac_release_rx_group(mcip, ngrp);
1841 return (ENOSPC);
1842 }
1843 MAC_RX_GRP_RESERVED(mip);
1844 if (mip->mi_rx_group_type == MAC_GROUP_TYPE_DYNAMIC)
1845 MAC_RX_RING_RESERVED(mip, ngrp->mrg_cur_count);
1846 } else if (group != defgrp && !unspec &&
1847 mrp->mrp_nrxrings == 0) {
1848 /* Switch to S/W */
1849 ringcnt = group->mrg_cur_count;
1850 if (mac_rx_switch_group(mcip, group, defgrp) != 0)
1851 return (ENOSPC);
1852 if (tmrp->mrp_mask & MRP_RX_RINGS) {
1853 MAC_RX_GRP_RELEASED(mip);
2171 * from the SRS code, we'll keep them for now. They're currently
2172 * consumed by mac_datapath_setup() to create the SRS.
2173 * That code should be eventually moved out of
2174 * mac_datapath_setup() and moved to a mac_srs_create()
2175 * function of some sort to keep things clean.
2176 *
2177 * Also, there's no reason why the SRS for the primary MAC
2178 * client should be different than any other MAC client. Until
2179 * this is cleaned-up, we support only one MAC unicast address
2180 * per client.
2181 *
2182 * We set FLOW_PRIMARY_MAC for the primary MAC address,
2183 * FLOW_VNIC for everything else.
2184 */
2185 if (is_primary)
2186 flent_flags = FLOW_PRIMARY_MAC;
2187 else
2188 flent_flags = FLOW_VNIC_MAC;
2189
2190 /*
2191 * For the first flow we use the MAC client's name - mci_name, for
2192 * subsequent ones we just create a name with the VID. This is
2193 * so that we can add these flows to the same flow table. This is
2194 * fine as the flow name (except for the one with the MAC client's
2195 * name) is not visible. When the first flow is removed, we just replace
2196 * its fdesc with another from the list, so we will still retain the
2197 * flent with the MAC client's flow name.
2198 */
2199 if (first_flow) {
2200 bcopy(mcip->mci_name, flowname, MAXFLOWNAMELEN);
2201 } else {
2202 (void) sprintf(flowname, "%s%u", mcip->mci_name, vid);
2203 flent_flags = FLOW_NO_STATS;
2204 }
2205
2206 if ((err = mac_flow_create(&flow_desc, mrp, flowname, NULL,
2207 flent_flags, flent)) != 0)
2208 return (err);
2209
2210 mac_misc_stat_create(*flent);
2211 FLOW_MARK(*flent, FE_INCIPIENT);
2212 (*flent)->fe_mcip = mcip;
2213
2214 /*
2332 if ((err = mac_unicast_flow_create(mcip, mac_addr, vid,
2333 isprimary, B_TRUE, &flent, mrp)) != 0)
2334 goto bail;
2335
2336 mip->mi_nactiveclients++;
2337 nactiveclients_added = B_TRUE;
2338
2339 /*
2340 * This will allocate the RX ring group if possible for the
2341 * flow and program the software classifier as needed.
2342 */
2343 if ((err = mac_datapath_setup(mcip, flent, SRST_LINK)) != 0)
2344 goto bail;
2345
2346 if (no_unicast)
2347 goto done_setup;
2348 /*
2349 * The unicast MAC address must have been added successfully.
2350 */
2351 ASSERT(mcip->mci_unicast != NULL);
2352
2353 /*
2354 * Push down the sub-flows that were defined on this link
2355 * hitherto. The flows are added to the active flow table
2356 * and SRS, softrings etc. are created as needed.
2357 */
2358 mac_link_init_flows((mac_client_handle_t)mcip);
2359 } else {
2360 mac_address_t *map = mcip->mci_unicast;
2361
2362 ASSERT(!no_unicast);
2363 /*
2364 * A unicast flow already exists for that MAC client
2365 * so this flow must be the same MAC address but with
2366 * a different VID. It has been checked by
2367 * mac_addr_in_use().
2368 *
2369 * We will use the SRS etc. from the initial
2370 * mci_flent. We don't need to create a kstat for
2371 * this, as except for the fdesc, everything will be
2372 * used from the first flent.
2373 *
2374 * The only time we should see multiple flents on the
2375 * same MAC client is on the sun4v vsw. If we removed
2376 * that code we should be able to remove the entire
2377 * notion of multiple flents on a MAC client (this
2378 * doesn't affect sub/user flows because they have
2379 * their own list unrelated to mci_flent_list).
2380 */
2381 if (bcmp(mac_addr, map->ma_addr, map->ma_len) != 0) {
2382 err = EINVAL;
2383 goto bail;
2384 }
2385
2386 if ((err = mac_unicast_flow_create(mcip, mac_addr, vid,
2387 isprimary, B_FALSE, &flent, NULL)) != 0) {
2388 goto bail;
2389 }
2390 if ((err = mac_flow_add(mip->mi_flow_tab, flent)) != 0) {
2391 FLOW_FINAL_REFRELE(flent);
2392 goto bail;
2393 }
2394
2395 /* update the multicast group for this vid */
2396 mac_client_bcast_refresh(mcip, mac_client_update_mcast,
2397 (void *)flent, B_TRUE);
2398
2399 }
2400
2489 * In no case can a client use the PVID for the MAC, if the MAC has one set.
2490 */
2491 int
2492 i_mac_unicast_add(mac_client_handle_t mch, uint8_t *mac_addr, uint16_t flags,
2493 mac_unicast_handle_t *mah, uint16_t vid, mac_diag_t *diag)
2494 {
2495 mac_client_impl_t *mcip = (mac_client_impl_t *)mch;
2496 mac_impl_t *mip = mcip->mci_mip;
2497 int err;
2498 uint_t mac_len = mip->mi_type->mt_addr_length;
2499 boolean_t check_dups = !(flags & MAC_UNICAST_NODUPCHECK);
2500 boolean_t fastpath_disabled = B_FALSE;
2501 boolean_t is_primary = (flags & MAC_UNICAST_PRIMARY);
2502 boolean_t is_unicast_hw = (flags & MAC_UNICAST_HW);
2503 mac_resource_props_t *mrp;
2504 boolean_t passive_client = B_FALSE;
2505 mac_unicast_impl_t *muip;
2506 boolean_t is_vnic_primary =
2507 (flags & MAC_UNICAST_VNIC_PRIMARY);
2508
2509 /*
2510 * When the VID is non-zero the underlying MAC cannot be a
2511 * VNIC. I.e., dladm create-vlan cannot take a VNIC as
2512 * argument, only the primary MAC client.
2513 */
2514 ASSERT(!((mip->mi_state_flags & MIS_IS_VNIC) && (vid != VLAN_ID_NONE)));
2515
2516 /*
2517 * Can't unicast add if the client asked only for minimal datapath
2518 * setup.
2519 */
2520 if (mcip->mci_state_flags & MCIS_NO_UNICAST_ADDR)
2521 return (ENOTSUP);
2522
2523 /*
2524 * Check for an attempted use of the current Port VLAN ID, if enabled.
2525 * No client may use it.
2526 */
2527 if (mip->mi_pvid != VLAN_ID_NONE && vid == mip->mi_pvid)
2528 return (EBUSY);
2529
2530 /*
2531 * Check whether it's the primary client and flag it.
2532 */
2533 if (!(mcip->mci_state_flags & MCIS_IS_VNIC) && is_primary &&
2534 vid == VLAN_ID_NONE)
2535 mcip->mci_flags |= MAC_CLIENT_FLAGS_PRIMARY;
2536
2537 /*
2538 * is_vnic_primary is true when we come here as a VLAN VNIC
2539 * which uses the primary MAC client's address but with a non-zero
2540 * VID. In this case the MAC address is not specified by an upper
2541 * MAC client.
2542 */
2543 if ((mcip->mci_state_flags & MCIS_IS_VNIC) && is_primary &&
2544 !is_vnic_primary) {
2545 /*
2546 * The address is being set by the upper MAC client
2547 * of a VNIC. The MAC address was already set by the
2548 * VNIC driver during VNIC creation.
2549 *
2550 * Note: a VNIC has only one MAC address. We return
2551 * the MAC unicast address handle of the lower MAC client
2552 * corresponding to the VNIC. We allocate a new entry
2553 * which is flagged appropriately, so that mac_unicast_remove()
2554 * doesn't attempt to free the original entry that
2555 * was allocated by the VNIC driver.
2556 */
2557 ASSERT(mcip->mci_unicast != NULL);
2558
2559 /* Check for VLAN flags, if present */
2571 * is added only once unless we have the
2572 * MAC_CLIENT_FLAGS_MULTI_PRIMARY set (and this is not
2573 * a passive MAC client).
2574 */
2575 if ((mcip->mci_flags & MAC_CLIENT_FLAGS_VNIC_PRIMARY) != 0) {
2576 if ((mcip->mci_flags &
2577 MAC_CLIENT_FLAGS_MULTI_PRIMARY) == 0 ||
2578 (mcip->mci_flags &
2579 MAC_CLIENT_FLAGS_PASSIVE_PRIMARY) != 0) {
2580 return (EBUSY);
2581 }
2582 mcip->mci_flags |= MAC_CLIENT_FLAGS_PASSIVE_PRIMARY;
2583 passive_client = B_TRUE;
2584 }
2585
2586 mcip->mci_flags |= MAC_CLIENT_FLAGS_VNIC_PRIMARY;
2587
2588 /*
2589 * Create a handle for vid 0.
2590 */
2591 ASSERT(vid == VLAN_ID_NONE);
2592 muip = kmem_zalloc(sizeof (mac_unicast_impl_t), KM_SLEEP);
2593 muip->mui_vid = vid;
2594 *mah = (mac_unicast_handle_t)muip;
2595 /*
2596 * This will be used by the caller to defer setting the
2597 * rx functions.
2598 */
2599 if (passive_client)
2600 return (EAGAIN);
2601 return (0);
2602 }
2603
2604 /* primary MAC clients cannot be opened on top of anchor VNICs */
2605 if ((is_vnic_primary || is_primary) &&
2606 i_mac_capab_get((mac_handle_t)mip, MAC_CAPAB_ANCHOR_VNIC, NULL)) {
2607 return (ENXIO);
2608 }
2609
2610 /*
2611 * If this is a VNIC/VLAN, disable softmac fast-path. This is
2612 * only relevant to legacy devices which use softmac to
2613 * interface with GLDv3.
2614 */
2615 if (mcip->mci_state_flags & MCIS_IS_VNIC) {
2616 err = mac_fastpath_disable((mac_handle_t)mip);
2617 if (err != 0)
2618 return (err);
2619 fastpath_disabled = B_TRUE;
2620 }
2621
2622 /*
2623 * Return EBUSY if:
2624 * - there is an exclusively active mac client exists.
2625 * - this is an exclusive active mac client but
2626 * a. there is already active mac clients exist, or
2627 * b. fastpath streams are already plumbed on this legacy device
2628 * - the mac creator has disallowed active mac clients.
2629 */
2630 if (mip->mi_state_flags & (MIS_EXCLUSIVE|MIS_NO_ACTIVE)) {
2631 if (fastpath_disabled)
2632 mac_fastpath_enable((mac_handle_t)mip);
2633 return (EBUSY);
2641 if ((mip->mi_state_flags & MIS_LEGACY) &&
2642 !(mip->mi_capab_legacy.ml_active_set(mip->mi_driver))) {
2643 return (EBUSY);
2644 }
2645 mip->mi_state_flags |= MIS_EXCLUSIVE;
2646 }
2647
2648 mrp = kmem_zalloc(sizeof (*mrp), KM_SLEEP);
2649 if (is_primary && !(mcip->mci_state_flags & (MCIS_IS_VNIC |
2650 MCIS_IS_AGGR_PORT))) {
2651 /*
2652 * Apply the property cached in the mac_impl_t to the primary
2653 * mac client. If the mac client is a VNIC or an aggregation
2654 * port, its property should be set in the mcip when the
2655 * VNIC/aggr was created.
2656 */
2657 mac_get_resources((mac_handle_t)mip, mrp);
2658 (void) mac_client_set_resources(mch, mrp);
2659 } else if (mcip->mci_state_flags & MCIS_IS_VNIC) {
2660 /*
2661 * This is a VLAN client sharing the address of the
2662 * primary MAC client; i.e., one created via dladm
2663 * create-vlan. We don't support specifying ring
2664 * properties for this type of client as it inherits
2665 * these from the primary MAC client.
2666 */
2667 if (is_vnic_primary) {
2668 mac_resource_props_t *vmrp;
2669
2670 vmrp = MCIP_RESOURCE_PROPS(mcip);
2671 if (vmrp->mrp_mask & MRP_RX_RINGS ||
2672 vmrp->mrp_mask & MRP_TX_RINGS) {
2673 if (fastpath_disabled)
2674 mac_fastpath_enable((mac_handle_t)mip);
2675 kmem_free(mrp, sizeof (*mrp));
2676 return (ENOTSUP);
2677 }
2678 /*
2679 * Additionally we also need to inherit any
2680 * rings property from the MAC.
2681 */
2682 mac_get_resources((mac_handle_t)mip, mrp);
2683 if (mrp->mrp_mask & MRP_RX_RINGS) {
2684 vmrp->mrp_mask |= MRP_RX_RINGS;
2685 vmrp->mrp_nrxrings = mrp->mrp_nrxrings;
3007 mac_fastpath_enable((mac_handle_t)mip);
3008 mac_stop((mac_handle_t)mip);
3009 }
3010
3011 /*
3012 * Remove a MAC address which was previously added by mac_unicast_add().
3013 */
3014 int
3015 mac_unicast_remove(mac_client_handle_t mch, mac_unicast_handle_t mah)
3016 {
3017 mac_client_impl_t *mcip = (mac_client_impl_t *)mch;
3018 mac_unicast_impl_t *muip = (mac_unicast_impl_t *)mah;
3019 mac_unicast_impl_t *pre;
3020 mac_impl_t *mip = mcip->mci_mip;
3021 flow_entry_t *flent;
3022 uint16_t mui_vid;
3023
3024 i_mac_perim_enter(mip);
3025 if (mcip->mci_flags & MAC_CLIENT_FLAGS_VNIC_PRIMARY) {
3026 /*
3027 * Call made by the upper MAC client of a VNIC.
3028 * There's nothing much to do, the unicast address will
3029 * be removed by the VNIC driver when the VNIC is deleted,
3030 * but let's ensure that all our transmit is done before
3031 * the client does a mac_client_stop lest it trigger an
3032 * assert in the driver.
3033 */
3034 ASSERT(muip->mui_vid == VLAN_ID_NONE);
3035
3036 mac_tx_client_flush(mcip);
3037
3038 if ((mcip->mci_flags & MAC_CLIENT_FLAGS_PASSIVE_PRIMARY) != 0) {
3039 mcip->mci_flags &= ~MAC_CLIENT_FLAGS_PASSIVE_PRIMARY;
3040 if (mcip->mci_rx_p_fn != NULL) {
3041 mac_rx_set(mch, mcip->mci_rx_p_fn,
3042 mcip->mci_rx_p_arg);
3043 mcip->mci_rx_p_fn = NULL;
3044 mcip->mci_rx_p_arg = NULL;
3045 }
3046 kmem_free(muip, sizeof (mac_unicast_impl_t));
3047 i_mac_perim_exit(mip);
3048 return (0);
3049 }
3050 mcip->mci_flags &= ~MAC_CLIENT_FLAGS_VNIC_PRIMARY;
3051
3052 if (mcip->mci_state_flags & MCIS_TAG_DISABLE)
3053 mcip->mci_state_flags &= ~MCIS_TAG_DISABLE;
3054
3078
3079 mcip->mci_p_unicast_list = NULL;
3080 mcip->mci_rx_p_fn = NULL;
3081 mcip->mci_rx_p_arg = NULL;
3082
3083 mcip->mci_state_flags &= ~MCIS_UNICAST_HW;
3084
3085 if (mcip->mci_state_flags & MCIS_TAG_DISABLE)
3086 mcip->mci_state_flags &= ~MCIS_TAG_DISABLE;
3087
3088 if (mcip->mci_state_flags & MCIS_STRIP_DISABLE)
3089 mcip->mci_state_flags &= ~MCIS_STRIP_DISABLE;
3090
3091 if (mcip->mci_state_flags & MCIS_DISABLE_TX_VID_CHECK)
3092 mcip->mci_state_flags &= ~MCIS_DISABLE_TX_VID_CHECK;
3093
3094 kmem_free(muip, sizeof (mac_unicast_impl_t));
3095 i_mac_perim_exit(mip);
3096 return (0);
3097 }
3098
3099 /*
3100 * Remove the VID from the list of client's VIDs.
3101 */
3102 pre = mcip->mci_unicast_list;
3103 if (muip == pre) {
3104 mcip->mci_unicast_list = muip->mui_next;
3105 } else {
3106 while ((pre->mui_next != NULL) && (pre->mui_next != muip))
3107 pre = pre->mui_next;
3108 ASSERT(pre->mui_next == muip);
3109 rw_enter(&mcip->mci_rw_lock, RW_WRITER);
3110 pre->mui_next = muip->mui_next;
3111 rw_exit(&mcip->mci_rw_lock);
3112 }
3113
3114 if (!mac_client_single_rcvr(mcip)) {
3115 /*
3116 * This MAC client is shared by more than one unicast
3117 * addresses, so we will just remove the flent
3118 * corresponding to the address being removed. We don't invoke
3119 * mac_rx_classify_flow_rem() since the additional flow is
3120 * not associated with its own separate set of SRS and rings,
3121 * and these constructs are still needed for the remaining
3122 * flows.
3123 */
3124 flent = mac_client_get_flow(mcip, muip);
3125 VERIFY3P(flent, !=, NULL);
3126
3127 /*
3128 * The first one is disappearing, need to make sure
3129 * we replace it with another from the list of
3130 * shared clients.
3131 */
3132 if (flent == mcip->mci_flent)
3133 flent = mac_client_swap_mciflent(mcip);
3134 mac_client_remove_flow_from_list(mcip, flent);
3135 mac_flow_remove(mip->mi_flow_tab, flent, B_FALSE);
3136 mac_flow_wait(flent, FLOW_DRIVER_UPCALL);
3137
3138 /*
3139 * The multicast groups that were added by the client so
3140 * far must be removed from the brodcast domain corresponding
3141 * to the VID being removed.
3142 */
3143 mac_client_bcast_refresh(mcip, mac_client_update_mcast,
3144 (void *)flent, B_FALSE);
3145
3146 if (mip->mi_type->mt_brdcst_addr != NULL) {
3147 mac_bcast_delete(mcip, mip->mi_type->mt_brdcst_addr,
3148 muip->mui_vid);
3149 }
3150
3151 FLOW_FINAL_REFRELE(flent);
3152 ASSERT(!(mcip->mci_state_flags & MCIS_EXCLUSIVE));
3153
3154 /*
3155 * Enable fastpath if this is a VNIC or a VLAN.
3156 */
3157 if (mcip->mci_state_flags & MCIS_IS_VNIC)
3158 mac_fastpath_enable((mac_handle_t)mip);
3159 mac_stop((mac_handle_t)mip);
3160 i_mac_perim_exit(mip);
3161 return (0);
3162 }
3163
3164 mui_vid = muip->mui_vid;
3165 mac_client_datapath_teardown(mch, muip, flent);
3166
3167 if ((mcip->mci_flags & MAC_CLIENT_FLAGS_PRIMARY) &&
3168 mui_vid == VLAN_ID_NONE) {
3169 mcip->mci_flags &= ~MAC_CLIENT_FLAGS_PRIMARY;
3170 } else {
3171 i_mac_perim_exit(mip);
3172 return (0);
3173 }
3174
3175 /*
3176 * If we are removing the primary, check if we have a passive primary
3177 * client that we need to activate now.
3178 */
3179 mcip = mac_get_passive_primary_client(mip);
3180 if (mcip != NULL) {
3181 mac_resource_props_t *mrp;
3182 mac_unicast_impl_t *muip;
3183
3184 mcip->mci_flags &= ~MAC_CLIENT_FLAGS_PASSIVE_PRIMARY;
3185 mrp = kmem_zalloc(sizeof (*mrp), KM_SLEEP);
3186
3187 /*
3188 * Apply the property cached in the mac_impl_t to the
|