Print this page
11490 SRS ring polling disabled for VLANs
11491 Want DLS bypass for VLAN traffic
11492 add VLVF bypass to ixgbe core
2869 duplicate packets with vnics over aggrs
11489 DLS stat delete and aggr kstat can deadlock
Portions contributed by: Theo Schlossnagle <jesus@omniti.com>
Reviewed by: Patrick Mooney <patrick.mooney@joyent.com>
Reviewed by: Robert Mustacchi <rm@joyent.com>
Reviewed by: Dan McDonald <danmcd@joyent.com>


   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