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>


 443 
 444         i_mactype_hash = mod_hash_create_extended("mactype_hash",
 445             MACTYPE_HASHSZ,
 446             mod_hash_null_keydtor, mod_hash_null_valdtor,
 447             mod_hash_bystr, NULL, mod_hash_strkey_cmp, KM_SLEEP);
 448 
 449         /*
 450          * Allocate an id space to manage minor numbers. The range of the
 451          * space will be from MAC_MAX_MINOR+1 to MAC_PRIVATE_MINOR-1.  This
 452          * leaves half of the 32-bit minors available for driver private use.
 453          */
 454         minor_ids = id_space_create("mac_minor_ids", MAC_MAX_MINOR+1,
 455             MAC_PRIVATE_MINOR-1);
 456         ASSERT(minor_ids != NULL);
 457         minor_count = 0;
 458 
 459         /* Let's default to 20 seconds */
 460         mac_logging_interval = 20;
 461         mac_flow_log_enable = B_FALSE;
 462         mac_link_log_enable = B_FALSE;
 463         mac_logging_timer = 0;
 464 
 465         /* Register to be notified of noteworthy pools events */
 466         mac_pool_event_reg.pec_func =  mac_pool_event_cb;
 467         mac_pool_event_reg.pec_arg = NULL;
 468         pool_event_cb_register(&mac_pool_event_reg);
 469 }
 470 
 471 int
 472 mac_fini(void)
 473 {
 474 
 475         if (i_mac_impl_count > 0 || minor_count > 0)
 476                 return (EBUSY);
 477 
 478         pool_event_cb_unregister(&mac_pool_event_reg);
 479 
 480         id_space_destroy(minor_ids);
 481         mac_flow_fini();
 482 
 483         mod_hash_destroy_hash(i_mac_impl_hash);


1098                         return (err);
1099                 }
1100 
1101                 /*
1102                  * Start the default tx ring.
1103                  */
1104                 if (mip->mi_default_tx_ring != NULL) {
1105 
1106                         ring = (mac_ring_t *)mip->mi_default_tx_ring;
1107                         if (ring->mr_state != MR_INUSE) {
1108                                 err = mac_start_ring(ring);
1109                                 if (err != 0) {
1110                                         mip->mi_active--;
1111                                         return (err);
1112                                 }
1113                         }
1114                 }
1115 
1116                 if ((defgrp = MAC_DEFAULT_RX_GROUP(mip)) != NULL) {
1117                         /*
1118                          * Start the default ring, since it will be needed
1119                          * to receive broadcast and multicast traffic for
1120                          * both primary and non-primary MAC clients.

1121                          */
1122                         ASSERT(defgrp->mrg_state == MAC_GROUP_STATE_REGISTERED);
1123                         err = mac_start_group_and_rings(defgrp);
1124                         if (err != 0) {
1125                                 mip->mi_active--;
1126                                 if ((ring != NULL) &&
1127                                     (ring->mr_state == MR_INUSE))
1128                                         mac_stop_ring(ring);
1129                                 return (err);
1130                         }
1131                         mac_set_group_state(defgrp, MAC_GROUP_STATE_SHARED);
1132                 }
1133         }
1134 
1135         return (err);
1136 }
1137 
1138 /*
1139  * Private GLDv3 function to stop a MAC instance.
1140  */


1713         mip->mi_default_tx_ring = rh;
1714 }
1715 
1716 int
1717 mac_hwgroup_addmac(mac_group_handle_t gh, const uint8_t *addr)
1718 {
1719         mac_group_t *group = (mac_group_t *)gh;
1720 
1721         return (mac_group_addmac(group, addr));
1722 }
1723 
1724 int
1725 mac_hwgroup_remmac(mac_group_handle_t gh, const uint8_t *addr)
1726 {
1727         mac_group_t *group = (mac_group_t *)gh;
1728 
1729         return (mac_group_remmac(group, addr));
1730 }
1731 
1732 /*









































1733  * Set the RX group to be shared/reserved. Note that the group must be
1734  * started/stopped outside of this function.
1735  */
1736 void
1737 mac_set_group_state(mac_group_t *grp, mac_group_state_t state)
1738 {
1739         /*
1740          * If there is no change in the group state, just return.
1741          */
1742         if (grp->mrg_state == state)
1743                 return;
1744 
1745         switch (state) {
1746         case MAC_GROUP_STATE_RESERVED:
1747                 /*
1748                  * Successfully reserved the group.
1749                  *
1750                  * Given that there is an exclusive client controlling this
1751                  * group, we enable the group level polling when available,
1752                  * so that SRSs get to turn on/off individual rings they's


2397 {
2398         mac_impl_t      *mip = (mac_impl_t *)mh;
2399         int err;
2400 
2401         i_mac_perim_enter(mip);
2402         err = i_mac_disable(mip);
2403         i_mac_perim_exit(mip);
2404 
2405         /*
2406          * Clean up notification thread and wait for it to exit.
2407          */
2408         if (err == 0)
2409                 i_mac_notify_exit(mip);
2410 
2411         return (err);
2412 }
2413 
2414 /*
2415  * Called when the MAC instance has a non empty flow table, to de-multiplex
2416  * incoming packets to the right flow.
2417  * The MAC's rw lock is assumed held as a READER.
2418  */
2419 /* ARGSUSED */
2420 static mblk_t *
2421 mac_rx_classify(mac_impl_t *mip, mac_resource_handle_t mrh, mblk_t *mp)
2422 {
2423         flow_entry_t    *flent = NULL;
2424         uint_t          flags = FLOW_INBOUND;
2425         int             err;
2426 
2427         /*
2428          * If the mac is a port of an aggregation, pass FLOW_IGNORE_VLAN
2429          * to mac_flow_lookup() so that the VLAN packets can be successfully
2430          * passed to the non-VLAN aggregation flows.
2431          *
2432          * Note that there is possibly a race between this and
2433          * mac_unicast_remove/add() and VLAN packets could be incorrectly
2434          * classified to non-VLAN flows of non-aggregation mac clients. These
2435          * VLAN packets will be then filtered out by the mac module.
2436          */
2437         if ((mip->mi_state_flags & MIS_EXCLUSIVE) != 0)
2438                 flags |= FLOW_IGNORE_VLAN;
2439 
2440         err = mac_flow_lookup(mip->mi_flow_tab, mp, flags, &flent);
2441         if (err != 0) {
2442                 /* no registered receive function */
2443                 return (mp);
2444         } else {
2445                 mac_client_impl_t       *mcip;
2446 
2447                 /*
2448                  * This flent might just be an additional one on the MAC client,
2449                  * i.e. for classification purposes (different fdesc), however
2450                  * the resources, SRS et. al., are in the mci_flent, so if
2451                  * this isn't the mci_flent, we need to get it.
2452                  */
2453                 if ((mcip = flent->fe_mcip) != NULL &&
2454                     mcip->mci_flent != flent) {
2455                         FLOW_REFRELE(flent);


4058                                 break;
4059                         }
4060                         break;
4061                 case MAC_GROUP_TYPE_STATIC:
4062                         /*
4063                          * Note that an empty group is allowed, e.g., an aggr
4064                          * would start with an empty group.
4065                          */
4066                         break;
4067                 default:
4068                         /* unknown group type */
4069                         DTRACE_PROBE2(mac__init__rings__unknown__type,
4070                             char *, mip->mi_name,
4071                             int, cap_rings->mr_group_type);
4072                         err = EINVAL;
4073                         goto bail;
4074                 }
4075 
4076 
4077                 /*
4078                  * Driver must register group->mgi_addmac/remmac() for rx groups
4079                  * to support multiple MAC addresses.

4080                  */
4081                 if (rtype == MAC_RING_TYPE_RX &&
4082                     ((group_info.mgi_addmac == NULL) ||
4083                     (group_info.mgi_remmac == NULL))) {


4084                         err = EINVAL;
4085                         goto bail;
4086                 }
4087 
4088                 /* Cache driver-supplied information */
4089                 group->mrg_info = group_info;
4090 
4091                 /* Update the group's status and group count. */
4092                 mac_set_group_state(group, MAC_GROUP_STATE_REGISTERED);
4093                 group_free++;
4094 
4095                 group->mrg_rings = NULL;
4096                 group->mrg_cur_count = 0;
4097                 mac_init_group(mip, group, group_info.mgi_count, cap_rings);
4098                 ring_left -= group_info.mgi_count;
4099 
4100                 /* The current group size should be equal to default value */
4101                 ASSERT(group->mrg_cur_count == group_info.mgi_count);
4102         }
4103 


4110         group->mrg_state = MAC_GROUP_STATE_UNINIT;
4111         group->mrg_mh = (mac_handle_t)mip;
4112         group->mrg_next = NULL;
4113 
4114         /*
4115          * If there are ungrouped rings, allocate a continuous buffer for
4116          * remaining resources.
4117          */
4118         if (ring_left != 0) {
4119                 group->mrg_rings = NULL;
4120                 group->mrg_cur_count = 0;
4121                 mac_init_group(mip, group, ring_left, cap_rings);
4122 
4123                 /* The current group size should be equal to ring_left */
4124                 ASSERT(group->mrg_cur_count == ring_left);
4125 
4126                 ring_left = 0;
4127 
4128                 /* Update this group's status */
4129                 mac_set_group_state(group, MAC_GROUP_STATE_REGISTERED);
4130         } else
4131                 group->mrg_rings = NULL;

4132 
4133         ASSERT(ring_left == 0);
4134 
4135 bail:
4136 
4137         /* Cache other important information to finalize the initialization */
4138         switch (rtype) {
4139         case MAC_RING_TYPE_RX:
4140                 mip->mi_rx_group_type = cap_rings->mr_group_type;
4141                 mip->mi_rx_group_count = cap_rings->mr_gnum;
4142                 mip->mi_rx_groups = groups;
4143                 mip->mi_rx_donor_grp = groups;
4144                 if (mip->mi_rx_group_type == MAC_GROUP_TYPE_DYNAMIC) {
4145                         /*
4146                          * The default ring is reserved since it is
4147                          * used for sending the broadcast etc. packets.
4148                          */
4149                         mip->mi_rxrings_avail =
4150                             mip->mi_rx_groups->mrg_cur_count - 1;
4151                         mip->mi_rxrings_rsvd = 1;


4301                 mac_ring_t *ring;
4302 
4303                 if (group->mrg_cur_count == 0)
4304                         continue;
4305 
4306                 ASSERT(group->mrg_rings != NULL);
4307 
4308                 while ((ring = group->mrg_rings) != NULL) {
4309                         group->mrg_rings = ring->mr_next;
4310                         mac_ring_free(mip, ring);
4311                 }
4312         }
4313 
4314         /* Free all the cached rings */
4315         mac_ring_freeall(mip);
4316         /* Free the block of group data strutures */
4317         kmem_free(groups, sizeof (mac_group_t) * (group_count + 1));
4318 }
4319 
4320 /*
































4321  * Associate a MAC address with a receive group.
4322  *
4323  * The return value of this function should always be checked properly, because
4324  * any type of failure could cause unexpected results. A group can be added
4325  * or removed with a MAC address only after it has been reserved. Ideally,
4326  * a successful reservation always leads to calling mac_group_addmac() to
4327  * steer desired traffic. Failure of adding an unicast MAC address doesn't
4328  * always imply that the group is functioning abnormally.
4329  *
4330  * Currently this function is called everywhere, and it reflects assumptions
4331  * about MAC addresses in the implementation. CR 6735196.
4332  */
4333 int
4334 mac_group_addmac(mac_group_t *group, const uint8_t *addr)
4335 {
4336         ASSERT(group->mrg_type == MAC_RING_TYPE_RX);
4337         ASSERT(group->mrg_info.mgi_addmac != NULL);
4338 
4339         return (group->mrg_info.mgi_addmac(group->mrg_info.mgi_driver, addr));
4340 }
4341 
4342 /*
4343  * Remove the association between MAC address and receive group.
4344  */
4345 int
4346 mac_group_remmac(mac_group_t *group, const uint8_t *addr)
4347 {
4348         ASSERT(group->mrg_type == MAC_RING_TYPE_RX);
4349         ASSERT(group->mrg_info.mgi_remmac != NULL);
4350 
4351         return (group->mrg_info.mgi_remmac(group->mrg_info.mgi_driver, addr));
4352 }
4353 
4354 /*
4355  * This is the entry point for packets transmitted through the bridging code.
4356  * If no bridge is in place, MAC_RING_TX transmits using tx ring. The 'rh'
4357  * pointer may be NULL to select the default ring.
4358  */
4359 mblk_t *
4360 mac_bridge_tx(mac_impl_t *mip, mac_ring_handle_t rh, mblk_t *mp)
4361 {
4362         mac_handle_t mh;
4363 
4364         /*
4365          * Once we take a reference on the bridge link, the bridge
4366          * module itself can't unload, so the callback pointers are
4367          * stable.
4368          */
4369         mutex_enter(&mip->mi_bridge_lock);


4504                                     ring->mr_driver, ring->mr_type);
4505                         }
4506                         group->mrg_cur_count--;
4507                         group->mrg_rings = ring->mr_next;
4508 
4509                         ring->mr_gh = NULL;
4510 
4511                         if (driver_call)
4512                                 mac_ring_free(mip, ring);
4513 
4514                         return (ret);
4515                 }
4516         }
4517 
4518         /*
4519          * Set up SRS/SR according to the ring type.
4520          */
4521         switch (ring->mr_type) {
4522         case MAC_RING_TYPE_RX:
4523                 /*
4524                  * Setup SRS on top of the new ring if the group is
4525                  * reserved for someones exclusive use.
4526                  */
4527                 if (group->mrg_state == MAC_GROUP_STATE_RESERVED) {
4528                         mac_client_impl_t *mcip;
4529 
4530                         mcip = MAC_GROUP_ONLY_CLIENT(group);
4531                         /*
4532                          * Even though this group is reserved we migth still
4533                          * have multiple clients, i.e a VLAN shares the
4534                          * group with the primary mac client.
4535                          */
4536                         if (mcip != NULL) {
4537                                 flent = mcip->mci_flent;
4538                                 ASSERT(flent->fe_rx_srs_cnt > 0);
4539                                 mac_rx_srs_group_setup(mcip, flent, SRST_LINK);
4540                                 mac_fanout_setup(mcip, flent,
4541                                     MCIP_RESOURCE_PROPS(mcip), mac_rx_deliver,
4542                                     mcip, NULL, NULL);
4543                         } else {
4544                                 ring->mr_classify_type = MAC_SW_CLASSIFIER;
4545                         }
4546                 }
4547                 break;
4548         case MAC_RING_TYPE_TX:
4549         {
4550                 mac_grp_client_t        *mgcp = group->mrg_clients;
4551                 mac_client_impl_t       *mcip;
4552                 mac_soft_ring_set_t     *mac_srs;
4553                 mac_srs_tx_t            *tx;
4554 
4555                 if (MAC_GROUP_NO_CLIENT(group)) {
4556                         if (ring->mr_state == MR_INUSE)
4557                                 mac_stop_ring(ring);
4558                         ring->mr_flag = 0;
4559                         break;
4560                 }
4561                 /*
4562                  * If the rings are being moved to a group that has
4563                  * clients using it, then add the new rings to the
4564                  * clients SRS.
4565                  */
4566                 while (mgcp != NULL) {
4567                         boolean_t       is_aggr;
4568 
4569                         mcip = mgcp->mgc_client;
4570                         flent = mcip->mci_flent;
4571                         is_aggr = (mcip->mci_state_flags & MCIS_IS_AGGR);
4572                         mac_srs = MCIP_TX_SRS(mcip);
4573                         tx = &mac_srs->srs_tx;
4574                         mac_tx_client_quiesce((mac_client_handle_t)mcip);
4575                         /*
4576                          * If we are  growing from 1 to multiple rings.
4577                          */
4578                         if (tx->st_mode == SRS_TX_BW ||
4579                             tx->st_mode == SRS_TX_SERIALIZE ||
4580                             tx->st_mode == SRS_TX_DEFAULT) {
4581                                 mac_ring_t      *tx_ring = tx->st_arg2;
4582 
4583                                 tx->st_arg2 = NULL;
4584                                 mac_tx_srs_stat_recreate(mac_srs, B_TRUE);
4585                                 mac_tx_srs_add_ring(mac_srs, tx_ring);
4586                                 if (mac_srs->srs_type & SRST_BW_CONTROL) {
4587                                         tx->st_mode = is_aggr ? SRS_TX_BW_AGGR :
4588                                             SRS_TX_BW_FANOUT;
4589                                 } else {
4590                                         tx->st_mode = is_aggr ? SRS_TX_AGGR :
4591                                             SRS_TX_FANOUT;


4695                         mac_client_impl_t *mcip;
4696                         mac_soft_ring_set_t *mac_srs;
4697                         mac_soft_ring_t *sringp;
4698                         mac_srs_tx_t *srs_tx;
4699 
4700                         if (mip->mi_state_flags & MIS_IS_AGGR &&
4701                             mip->mi_default_tx_ring ==
4702                             (mac_ring_handle_t)ring) {
4703                                 /* pick a new default Tx ring */
4704                                 mip->mi_default_tx_ring =
4705                                     (group->mrg_rings != ring) ?
4706                                     (mac_ring_handle_t)group->mrg_rings :
4707                                     (mac_ring_handle_t)(ring->mr_next);
4708                         }
4709                         /* Presently only aggr case comes here */
4710                         if (group->mrg_state != MAC_GROUP_STATE_RESERVED)
4711                                 break;
4712 
4713                         mcip = MAC_GROUP_ONLY_CLIENT(group);
4714                         ASSERT(mcip != NULL);
4715                         ASSERT(mcip->mci_state_flags & MCIS_IS_AGGR);
4716                         mac_srs = MCIP_TX_SRS(mcip);
4717                         ASSERT(mac_srs->srs_tx.st_mode == SRS_TX_AGGR ||
4718                             mac_srs->srs_tx.st_mode == SRS_TX_BW_AGGR);
4719                         srs_tx = &mac_srs->srs_tx;
4720                         /*
4721                          * Wakeup any callers blocked on this
4722                          * Tx ring due to flow control.
4723                          */
4724                         sringp = srs_tx->st_soft_rings[ring->mr_index];
4725                         ASSERT(sringp != NULL);
4726                         mac_tx_invoke_callbacks(mcip, (mac_tx_cookie_t)sringp);
4727                         mac_tx_client_quiesce((mac_client_handle_t)mcip);
4728                         mac_tx_srs_del_ring(mac_srs, ring);
4729                         mac_tx_client_restart((mac_client_handle_t)mcip);
4730                         break;
4731                 }
4732                 ASSERT(ring != (mac_ring_t *)mip->mi_default_tx_ring);
4733                 group_type = mip->mi_tx_group_type;
4734                 cap_rings = &mip->mi_tx_rings_cap;
4735                 /*


4903 /*
4904  * Check whether the MAC address is shared by multiple clients.
4905  */
4906 boolean_t
4907 mac_check_macaddr_shared(mac_address_t *map)
4908 {
4909         ASSERT(MAC_PERIM_HELD((mac_handle_t)map->ma_mip));
4910 
4911         return (map->ma_nusers > 1);
4912 }
4913 
4914 /*
4915  * Remove the specified MAC address from the MAC address list and free it.
4916  */
4917 static void
4918 mac_free_macaddr(mac_address_t *map)
4919 {
4920         mac_impl_t *mip = map->ma_mip;
4921 
4922         ASSERT(MAC_PERIM_HELD((mac_handle_t)mip));
4923         ASSERT(mip->mi_addresses != NULL);
4924 
4925         map = mac_find_macaddr(mip, map->ma_addr);



4926 
4927         ASSERT(map != NULL);
4928         ASSERT(map->ma_nusers == 0);
4929 
4930         if (map == mip->mi_addresses) {
4931                 mip->mi_addresses = map->ma_next;
4932         } else {
4933                 mac_address_t *pre;
4934 
4935                 pre = mip->mi_addresses;
4936                 while (pre->ma_next != map)
4937                         pre = pre->ma_next;
4938                 pre->ma_next = map->ma_next;
4939         }
4940 
4941         kmem_free(map, sizeof (mac_address_t));
4942 }
4943 


























































4944 /*
4945  * Add a MAC address reference for a client. If the desired MAC address
4946  * exists, add a reference to it. Otherwise, add the new address by adding
4947  * it to a reserved group or setting promiscuous mode. Won't try different
4948  * group is the group is non-NULL, so the caller must explictly share
4949  * default group when needed.
4950  *
4951  * Note, the primary MAC address is initialized at registration time, so
4952  * to add it to default group only need to activate it if its reference
4953  * count is still zero. Also, some drivers may not have advertised RINGS
4954  * capability.
4955  */
4956 int
4957 mac_add_macaddr(mac_impl_t *mip, mac_group_t *group, uint8_t *mac_addr,
4958     boolean_t use_hw)
4959 {
4960         mac_address_t *map;

4961         int err = 0;
4962         boolean_t allocated_map = B_FALSE;


4963 
4964         ASSERT(MAC_PERIM_HELD((mac_handle_t)mip));
4965 
4966         map = mac_find_macaddr(mip, mac_addr);
4967 
4968         /*
4969          * If the new MAC address has not been added. Allocate a new one
4970          * and set it up.
4971          */
4972         if (map == NULL) {
4973                 map = kmem_zalloc(sizeof (mac_address_t), KM_SLEEP);
4974                 map->ma_len = mip->mi_type->mt_addr_length;
4975                 bcopy(mac_addr, map->ma_addr, map->ma_len);
4976                 map->ma_nusers = 0;
4977                 map->ma_group = group;
4978                 map->ma_mip = mip;

4979 
4980                 /* add the new MAC address to the head of the address list */
4981                 map->ma_next = mip->mi_addresses;
4982                 mip->mi_addresses = map;
4983 
4984                 allocated_map = B_TRUE;
4985         }
4986 
4987         ASSERT(map->ma_group == NULL || map->ma_group == group);
4988         if (map->ma_group == NULL)
4989                 map->ma_group = group;
4990 







4991         /*
4992          * If the MAC address is already in use, simply account for the
4993          * new client.







4994          */
4995         if (map->ma_nusers++ > 0)















4996                 return (0);
4997 
4998         /*






4999          * Activate this MAC address by adding it to the reserved group.
5000          */
5001         if (group != NULL) {
5002                 err = mac_group_addmac(group, (const uint8_t *)mac_addr);
5003                 if (err == 0) {
















5004                         map->ma_type = MAC_ADDRESS_TYPE_UNICAST_CLASSIFIED;
5005                         return (0);
5006                 }
5007         }
5008 
5009         /*
5010          * The MAC address addition failed. If the client requires a
5011          * hardware classified MAC address, fail the operation.

5012          */
5013         if (use_hw) {
5014                 err = ENOSPC;

5015                 goto bail;
5016         }
5017 
5018         /*
5019          * Try promiscuous mode.
5020          *
5021          * For drivers that don't advertise RINGS capability, do
5022          * nothing for the primary address.
5023          */







5024         if ((group == NULL) &&
5025             (bcmp(map->ma_addr, mip->mi_addr, map->ma_len) == 0)) {
5026                 map->ma_type = MAC_ADDRESS_TYPE_UNICAST_CLASSIFIED;
5027                 return (0);
5028         }
5029 
5030         /*
5031          * Enable promiscuous mode in order to receive traffic
5032          * to the new MAC address.



5033          */
5034         if ((err = i_mac_promisc_set(mip, B_TRUE)) == 0) {
5035                 map->ma_type = MAC_ADDRESS_TYPE_UNICAST_PROMISC;
5036                 return (0);
5037         }
5038 
5039         /*
5040          * Free the MAC address that could not be added. Don't free
5041          * a pre-existing address, it could have been the entry
5042          * for the primary MAC address which was pre-allocated by
5043          * mac_init_macaddr(), and which must remain on the list.
5044          */
5045 bail:
5046         map->ma_nusers--;












5047         if (allocated_map)
5048                 mac_free_macaddr(map);

5049         return (err);
5050 }
5051 
5052 /*
5053  * Remove a reference to a MAC address. This may cause to remove the MAC
5054  * address from an associated group or to turn off promiscuous mode.
5055  * The caller needs to handle the failure properly.
5056  */
5057 int
5058 mac_remove_macaddr(mac_address_t *map)
5059 {

5060         mac_impl_t *mip = map->ma_mip;

5061         int err = 0;
5062 
5063         ASSERT(MAC_PERIM_HELD((mac_handle_t)mip));

5064 
5065         ASSERT(map == mac_find_macaddr(mip, map->ma_addr));






5066 








5067         /*
5068          * If it's not the last client using this MAC address, only update
5069          * the MAC clients count.
5070          */
5071         if (--map->ma_nusers > 0)

5072                 return (0);
5073 
5074         /*
5075          * The MAC address is no longer used by any MAC client, so remove
5076          * it from its associated group, or turn off promiscuous mode
5077          * if it was enabled for the MAC address.
5078          */
5079         switch (map->ma_type) {
5080         case MAC_ADDRESS_TYPE_UNICAST_CLASSIFIED:
5081                 /*
5082                  * Don't free the preset primary address for drivers that
5083                  * don't advertise RINGS capability.
5084                  */
5085                 if (map->ma_group == NULL)
5086                         return (0);
5087 
5088                 err = mac_group_remmac(map->ma_group, map->ma_addr);
5089                 if (err == 0)

























5090                         map->ma_group = NULL;
5091                 break;
5092         case MAC_ADDRESS_TYPE_UNICAST_PROMISC:
5093                 err = i_mac_promisc_set(mip, B_FALSE);
5094                 break;
5095         default:
5096                 ASSERT(B_FALSE);

5097         }
5098 
5099         if (err != 0)
5100                 return (err);
5101 
5102         /*
5103          * We created MAC address for the primary one at registration, so we
5104          * won't free it here. mac_fini_macaddr() will take care of it.
5105          */
5106         if (bcmp(map->ma_addr, mip->mi_addr, map->ma_len) != 0)
5107                 mac_free_macaddr(map);
5108 
5109         return (0);
5110 }
5111 
5112 /*
5113  * Update an existing MAC address. The caller need to make sure that the new
5114  * value has not been used.
5115  */
5116 int


5233 
5234         mip->mi_addresses = map;
5235 }
5236 
5237 /*
5238  * Clean up the primary MAC address. Note, only one primary MAC address
5239  * is allowed. All other MAC addresses must have been freed appropriately.
5240  */
5241 void
5242 mac_fini_macaddr(mac_impl_t *mip)
5243 {
5244         mac_address_t *map = mip->mi_addresses;
5245 
5246         if (map == NULL)
5247                 return;
5248 
5249         /*
5250          * If mi_addresses is initialized, there should be exactly one
5251          * entry left on the list with no users.
5252          */
5253         ASSERT(map->ma_nusers == 0);
5254         ASSERT(map->ma_next == NULL);

5255 
5256         kmem_free(map, sizeof (mac_address_t));
5257         mip->mi_addresses = NULL;
5258 }
5259 
5260 /*
5261  * Logging related functions.
5262  *
5263  * Note that Kernel statistics have been extended to maintain fine
5264  * granularity of statistics viz. hardware lane, software lane, fanout
5265  * stats etc. However, extended accounting continues to support only
5266  * aggregate statistics like before.
5267  */
5268 
5269 /* Write the flow description to a netinfo_t record */
5270 static netinfo_t *
5271 mac_write_flow_desc(flow_entry_t *flent, mac_client_impl_t *mcip)
5272 {
5273         netinfo_t               *ninfo;
5274         net_desc_t              *ndesc;


5796                         mac_flow_log_enable = B_FALSE;
5797                         mac_link_log_enable = B_FALSE;
5798                         break;
5799                 }
5800                 /* FALLTHRU */
5801         case MAC_LOGTYPE_LINK:
5802                 if (!lstate.mi_lenable || mac_flow_log_enable) {
5803                         rw_exit(&i_mac_impl_lock);
5804                         return;
5805                 }
5806                 mac_link_log_enable = B_FALSE;
5807                 break;
5808         default:
5809                 ASSERT(0);
5810         }
5811 
5812         /* Reenable fastpath */
5813         mod_hash_walk(i_mac_impl_hash, i_mac_fastpath_walker, &estate);
5814 
5815         (void) untimeout(mac_logging_timer);
5816         mac_logging_timer = 0;
5817 
5818         /* Write log entries for each mac_impl in the list */
5819         i_mac_log_info(&net_log_list, &lstate);
5820 }
5821 
5822 /*
5823  * Walk the rx and tx SRS/SRs for a flow and update the priority value.
5824  */
5825 void
5826 mac_flow_update_priority(mac_client_impl_t *mcip, flow_entry_t *flent)
5827 {
5828         pri_t                   pri;
5829         int                     count;
5830         mac_soft_ring_set_t     *mac_srs;
5831 
5832         if (flent->fe_rx_srs_cnt <= 0)
5833                 return;
5834 
5835         if (((mac_soft_ring_set_t *)flent->fe_rx_srs[0])->srs_type ==
5836             SRST_FLOW) {


5914         }
5915         /*
5916          * There are clients using this ring, so let's move the clients
5917          * away from using this ring.
5918          */
5919         for (mgcp = group->mrg_clients; mgcp != NULL; mgcp = mgcp->mgc_next) {
5920                 mcip = mgcp->mgc_client;
5921                 mac_tx_client_quiesce((mac_client_handle_t)mcip);
5922                 srs = MCIP_TX_SRS(mcip);
5923                 ASSERT(mac_tx_srs_ring_present(srs, desired_ring));
5924                 mac_tx_invoke_callbacks(mcip,
5925                     (mac_tx_cookie_t)mac_tx_srs_get_soft_ring(srs,
5926                     desired_ring));
5927                 mac_tx_srs_del_ring(srs, desired_ring);
5928                 mac_tx_client_restart((mac_client_handle_t)mcip);
5929         }
5930         return (desired_ring);
5931 }
5932 
5933 /*
5934  * For a reserved group with multiple clients, return the primary client.
5935  */
5936 static mac_client_impl_t *
5937 mac_get_grp_primary(mac_group_t *grp)
5938 {
5939         mac_grp_client_t        *mgcp = grp->mrg_clients;
5940         mac_client_impl_t       *mcip;
5941 
5942         while (mgcp != NULL) {
5943                 mcip = mgcp->mgc_client;
5944                 if (mcip->mci_flent->fe_type & FLOW_PRIMARY_MAC)
5945                         return (mcip);
5946                 mgcp = mgcp->mgc_next;
5947         }
5948         return (NULL);
5949 }
5950 
5951 /*
5952  * Hybrid I/O specifies the ring that should be given to a share.
5953  * If the ring is already used by clients, then we need to release
5954  * the ring back to the default group so that we can give it to


6273         if (share != 0)
6274                 mip->mi_share_capab.ms_sadd(share, new_group->mrg_driver);
6275 
6276 bail:
6277         /* free temporary array of rings */
6278         kmem_free(rings, nrings * sizeof (mac_ring_handle_t));
6279 
6280         return (rv);
6281 }
6282 
6283 void
6284 mac_group_add_client(mac_group_t *grp, mac_client_impl_t *mcip)
6285 {
6286         mac_grp_client_t *mgcp;
6287 
6288         for (mgcp = grp->mrg_clients; mgcp != NULL; mgcp = mgcp->mgc_next) {
6289                 if (mgcp->mgc_client == mcip)
6290                         break;
6291         }
6292 
6293         VERIFY(mgcp == NULL);
6294 
6295         mgcp = kmem_zalloc(sizeof (mac_grp_client_t), KM_SLEEP);
6296         mgcp->mgc_client = mcip;
6297         mgcp->mgc_next = grp->mrg_clients;
6298         grp->mrg_clients = mgcp;
6299 
6300 }
6301 
6302 void
6303 mac_group_remove_client(mac_group_t *grp, mac_client_impl_t *mcip)
6304 {
6305         mac_grp_client_t *mgcp, **pprev;
6306 
6307         for (pprev = &grp->mrg_clients, mgcp = *pprev; mgcp != NULL;
6308             pprev = &mgcp->mgc_next, mgcp = *pprev) {
6309                 if (mgcp->mgc_client == mcip)
6310                         break;
6311         }
6312 
6313         ASSERT(mgcp != NULL);
6314 
6315         *pprev = mgcp->mgc_next;
6316         kmem_free(mgcp, sizeof (mac_grp_client_t));
6317 }
6318 
6319 /*
6320  * mac_reserve_rx_group()
6321  *



















6322  * Finds an available group and exclusively reserves it for a client.
6323  * The group is chosen to suit the flow's resource controls (bandwidth and
6324  * fanout requirements) and the address type.
6325  * If the requestor is the pimary MAC then return the group with the
6326  * largest number of rings, otherwise the default ring when available.
6327  */
6328 mac_group_t *
6329 mac_reserve_rx_group(mac_client_impl_t *mcip, uint8_t *mac_addr, boolean_t move)
6330 {
6331         mac_share_handle_t      share = mcip->mci_share;
6332         mac_impl_t              *mip = mcip->mci_mip;
6333         mac_group_t             *grp = NULL;
6334         int                     i;
6335         int                     err = 0;
6336         mac_address_t           *map;
6337         mac_resource_props_t    *mrp = MCIP_RESOURCE_PROPS(mcip);
6338         int                     nrings;
6339         int                     donor_grp_rcnt;
6340         boolean_t               need_exclgrp = B_FALSE;
6341         int                     need_rings = 0;
6342         mac_group_t             *candidate_grp = NULL;
6343         mac_client_impl_t       *gclient;
6344         mac_resource_props_t    *gmrp;
6345         mac_group_t             *donorgrp = NULL;
6346         boolean_t               rxhw = mrp->mrp_mask & MRP_RX_RINGS;
6347         boolean_t               unspec = mrp->mrp_mask & MRP_RXRINGS_UNSPEC;
6348         boolean_t               isprimary;
6349 
6350         ASSERT(MAC_PERIM_HELD((mac_handle_t)mip));
6351 
6352         isprimary = mcip->mci_flent->fe_type & FLOW_PRIMARY_MAC;
6353 
6354         /*
6355          * Check if a group already has this mac address (case of VLANs)
6356          * unless we are moving this MAC client from one group to another.
6357          */
6358         if (!move && (map = mac_find_macaddr(mip, mac_addr)) != NULL) {
6359                 if (map->ma_group != NULL)
6360                         return (map->ma_group);
6361         }

6362         if (mip->mi_rx_groups == NULL || mip->mi_rx_group_count == 0)
6363                 return (NULL);

6364         /*
6365          * If exclusive open, return NULL which will enable the
6366          * caller to use the default group.
6367          */
6368         if (mcip->mci_state_flags & MCIS_EXCLUSIVE)
6369                 return (NULL);
6370 
6371         /* For dynamic groups default unspecified to 1 */
6372         if (rxhw && unspec &&
6373             mip->mi_rx_group_type == MAC_GROUP_TYPE_DYNAMIC) {
6374                 mrp->mrp_nrxrings = 1;
6375         }

6376         /*
6377          * For static grouping we allow only specifying rings=0 and
6378          * unspecified
6379          */
6380         if (rxhw && mrp->mrp_nrxrings > 0 &&
6381             mip->mi_rx_group_type == MAC_GROUP_TYPE_STATIC) {
6382                 return (NULL);
6383         }

6384         if (rxhw) {
6385                 /*
6386                  * We have explicitly asked for a group (with nrxrings,
6387                  * if unspec).
6388                  */
6389                 if (unspec || mrp->mrp_nrxrings > 0) {
6390                         need_exclgrp = B_TRUE;
6391                         need_rings = mrp->mrp_nrxrings;
6392                 } else if (mrp->mrp_nrxrings == 0) {
6393                         /*
6394                          * We have asked for a software group.
6395                          */
6396                         return (NULL);
6397                 }
6398         } else if (isprimary && mip->mi_nactiveclients == 1 &&
6399             mip->mi_rx_group_type == MAC_GROUP_TYPE_DYNAMIC) {
6400                 /*
6401                  * If the primary is the only active client on this
6402                  * mip and we have not asked for any rings, we give
6403                  * it the default group so that the primary gets to


6425          * For flows requiring HW_RING (unicast flow of other clients), try
6426          * to reserve non-default RX group with the specified number of
6427          * rings, if available.
6428          *
6429          * For flows that have not asked for software or hardware ring,
6430          * try to reserve a non-default group with 1 ring, if available.
6431          */
6432         for (i = 1; i < mip->mi_rx_group_count; i++) {
6433                 grp = &mip->mi_rx_groups[i];
6434 
6435                 DTRACE_PROBE3(rx__group__trying, char *, mip->mi_name,
6436                     int, grp->mrg_index, mac_group_state_t, grp->mrg_state);
6437 
6438                 /*
6439                  * Check if this group could be a candidate group for
6440                  * eviction if we need a group for this MAC client,
6441                  * but there aren't any. A candidate group is one
6442                  * that didn't ask for an exclusive group, but got
6443                  * one and it has enough rings (combined with what
6444                  * the donor group can donate) for the new MAC
6445                  * client
6446                  */
6447                 if (grp->mrg_state >= MAC_GROUP_STATE_RESERVED) {
6448                         /*
6449                          * If the primary/donor group is not the default
6450                          * group, don't bother looking for a candidate group.
6451                          * If we don't have enough rings we will check
6452                          * if the primary group can be vacated.

6453                          */
6454                         if (candidate_grp == NULL &&
6455                             donorgrp == MAC_DEFAULT_RX_GROUP(mip)) {
6456                                 ASSERT(!MAC_GROUP_NO_CLIENT(grp));
6457                                 gclient = MAC_GROUP_ONLY_CLIENT(grp);
6458                                 if (gclient == NULL)
6459                                         gclient = mac_get_grp_primary(grp);
6460                                 ASSERT(gclient != NULL);
6461                                 gmrp = MCIP_RESOURCE_PROPS(gclient);
6462                                 if (gclient->mci_share == 0 &&
6463                                     (gmrp->mrp_mask & MRP_RX_RINGS) == 0 &&
6464                                     (unspec ||
6465                                     (grp->mrg_cur_count + donor_grp_rcnt >=
6466                                     need_rings))) {
6467                                         candidate_grp = grp;
6468                                 }
6469                         }
6470                         continue;
6471                 }
6472                 /*
6473                  * This group could already be SHARED by other multicast
6474                  * flows on this client. In that case, the group would
6475                  * be shared and has already been started.
6476                  */
6477                 ASSERT(grp->mrg_state != MAC_GROUP_STATE_UNINIT);
6478 
6479                 if ((grp->mrg_state == MAC_GROUP_STATE_REGISTERED) &&
6480                     (mac_start_group(grp) != 0)) {
6481                         continue;
6482                 }
6483 


6509                                 if (share != 0) {
6510                                         mac_client_set_rings(
6511                                             (mac_client_handle_t)mcip,
6512                                             grp->mrg_cur_count, -1);
6513                                 }
6514                                 if (mac_is_primary_client(mcip) && !rxhw)
6515                                         mip->mi_rx_donor_grp = grp;
6516                                 break;
6517                         }
6518                 }
6519 
6520                 DTRACE_PROBE3(rx__group__reserve__alloc__rings, char *,
6521                     mip->mi_name, int, grp->mrg_index, int, err);
6522 
6523                 /*
6524                  * It's a dynamic group but the grouping operation
6525                  * failed.
6526                  */
6527                 mac_stop_group(grp);
6528         }

6529         /* We didn't find an exclusive group for this MAC client */
6530         if (i >= mip->mi_rx_group_count) {
6531 
6532                 if (!need_exclgrp)
6533                         return (NULL);
6534 
6535                 /*
6536                  * If we found a candidate group then we switch the
6537                  * MAC client from the candidate_group to the default
6538                  * group and give the group to this MAC client. If
6539                  * we didn't find a candidate_group, check if the
6540                  * primary is in its own group and if it can make way
6541                  * for this MAC client.
6542                  */
6543                 if (candidate_grp == NULL &&
6544                     donorgrp != MAC_DEFAULT_RX_GROUP(mip) &&
6545                     donorgrp->mrg_cur_count >= need_rings) {
6546                         candidate_grp = donorgrp;
6547                 }
6548                 if (candidate_grp != NULL) {
6549                         boolean_t       prim_grp = B_FALSE;
6550 
6551                         /*
6552                          * Switch the MAC client from the candidate group
6553                          * to the default group.. If this group was the
6554                          * donor group, then after the switch we need
6555                          * to update the donor group too.

6556                          */
6557                         grp = candidate_grp;
6558                         gclient = MAC_GROUP_ONLY_CLIENT(grp);
6559                         if (gclient == NULL)
6560                                 gclient = mac_get_grp_primary(grp);
6561                         if (grp == mip->mi_rx_donor_grp)
6562                                 prim_grp = B_TRUE;
6563                         if (mac_rx_switch_group(gclient, grp,
6564                             MAC_DEFAULT_RX_GROUP(mip)) != 0) {
6565                                 return (NULL);
6566                         }
6567                         if (prim_grp) {
6568                                 mip->mi_rx_donor_grp =
6569                                     MAC_DEFAULT_RX_GROUP(mip);
6570                                 donorgrp = MAC_DEFAULT_RX_GROUP(mip);
6571                         }
6572 
6573 
6574                         /*
6575                          * Now give this group with the required rings
6576                          * to this MAC client.
6577                          */
6578                         ASSERT(grp->mrg_state == MAC_GROUP_STATE_REGISTERED);
6579                         if (mac_start_group(grp) != 0)
6580                                 return (NULL);
6581 
6582                         if (mip->mi_rx_group_type != MAC_GROUP_TYPE_DYNAMIC)
6583                                 return (grp);
6584 
6585                         donor_grp_rcnt = donorgrp->mrg_cur_count - 1;
6586                         ASSERT(grp->mrg_cur_count == 0);
6587                         ASSERT(donor_grp_rcnt >= need_rings);
6588                         err = i_mac_group_allocate_rings(mip, MAC_RING_TYPE_RX,
6589                             donorgrp, grp, share, need_rings);
6590                         if (err == 0) {
6591                                 /*
6592                                  * For a share i_mac_group_allocate_rings gets
6593                                  * the rings from the driver, let's populate


6601                                 DTRACE_PROBE2(rx__group__reserved,
6602                                     char *, mip->mi_name, int, grp->mrg_index);
6603                                 return (grp);
6604                         }
6605                         DTRACE_PROBE3(rx__group__reserve__alloc__rings, char *,
6606                             mip->mi_name, int, grp->mrg_index, int, err);
6607                         mac_stop_group(grp);
6608                 }
6609                 return (NULL);
6610         }
6611         ASSERT(grp != NULL);
6612 
6613         DTRACE_PROBE2(rx__group__reserved,
6614             char *, mip->mi_name, int, grp->mrg_index);
6615         return (grp);
6616 }
6617 
6618 /*
6619  * mac_rx_release_group()
6620  *
6621  * This is called when there are no clients left for the group.
6622  * The group is stopped and marked MAC_GROUP_STATE_REGISTERED,
6623  * and if it is a non default group, the shares are removed and
6624  * all rings are assigned back to default group.
6625  */
6626 void
6627 mac_release_rx_group(mac_client_impl_t *mcip, mac_group_t *group)
6628 {
6629         mac_impl_t              *mip = mcip->mci_mip;
6630         mac_ring_t              *ring;
6631 
6632         ASSERT(group != MAC_DEFAULT_RX_GROUP(mip));

6633 
6634         if (mip->mi_rx_donor_grp == group)
6635                 mip->mi_rx_donor_grp = MAC_DEFAULT_RX_GROUP(mip);
6636 
6637         /*
6638          * This is the case where there are no clients left. Any
6639          * SRS etc on this group have also be quiesced.
6640          */
6641         for (ring = group->mrg_rings; ring != NULL; ring = ring->mr_next) {
6642                 if (ring->mr_classify_type == MAC_HW_CLASSIFIER) {
6643                         ASSERT(group->mrg_state == MAC_GROUP_STATE_RESERVED);
6644                         /*
6645                          * Remove the SRS associated with the HW ring.
6646                          * As a result, polling will be disabled.
6647                          */
6648                         ring->mr_srs = NULL;
6649                 }
6650                 ASSERT(group->mrg_state < MAC_GROUP_STATE_RESERVED ||
6651                     ring->mr_state == MR_INUSE);
6652                 if (ring->mr_state == MR_INUSE) {


6664         if (mip->mi_rx_group_type == MAC_GROUP_TYPE_DYNAMIC) {
6665                 mac_ring_t *ring;
6666 
6667                 /*
6668                  * Rings were dynamically allocated to group.
6669                  * Move rings back to default group.
6670                  */
6671                 while ((ring = group->mrg_rings) != NULL) {
6672                         (void) mac_group_mov_ring(mip, mip->mi_rx_donor_grp,
6673                             ring);
6674                 }
6675         }
6676         mac_stop_group(group);
6677         /*
6678          * Possible improvement: See if we can assign the group just released
6679          * to a another client of the mip
6680          */
6681 }
6682 
6683 /*
6684  * When we move the primary's mac address between groups, we need to also
6685  * take all the clients sharing the same mac address along with it (VLANs)
6686  * We remove the mac address for such clients from the group after quiescing
6687  * them. When we add the mac address we restart the client. Note that
6688  * the primary's mac address is removed from the group after all the
6689  * other clients sharing the address are removed. Similarly, the primary's
6690  * mac address is added before all the other client's mac address are
6691  * added. While grp is the group where the clients reside, tgrp is
6692  * the group where the addresses have to be added.
6693  */
6694 static void
6695 mac_rx_move_macaddr_prim(mac_client_impl_t *mcip, mac_group_t *grp,
6696     mac_group_t *tgrp, uint8_t *maddr, boolean_t add)
6697 {
6698         mac_impl_t              *mip = mcip->mci_mip;
6699         mac_grp_client_t        *mgcp = grp->mrg_clients;
6700         mac_client_impl_t       *gmcip;
6701         boolean_t               prim;
6702 
6703         prim = (mcip->mci_state_flags & MCIS_UNICAST_HW) != 0;
6704 
6705         /*
6706          * If the clients are in a non-default group, we just have to
6707          * walk the group's client list. If it is in the default group
6708          * (which will be shared by other clients as well, we need to
6709          * check if the unicast address matches mcip's unicast.
6710          */
6711         while (mgcp != NULL) {
6712                 gmcip = mgcp->mgc_client;
6713                 if (gmcip != mcip &&
6714                     (grp != MAC_DEFAULT_RX_GROUP(mip) ||
6715                     mcip->mci_unicast == gmcip->mci_unicast)) {
6716                         if (!add) {
6717                                 mac_rx_client_quiesce(
6718                                     (mac_client_handle_t)gmcip);
6719                                 (void) mac_remove_macaddr(mcip->mci_unicast);
6720                         } else {
6721                                 (void) mac_add_macaddr(mip, tgrp, maddr, prim);
6722                                 mac_rx_client_restart(
6723                                     (mac_client_handle_t)gmcip);
6724                         }
6725                 }
6726                 mgcp = mgcp->mgc_next;
6727         }
6728 }
6729 
6730 
6731 /*
6732  * Move the MAC address from fgrp to tgrp. If this is the primary client,
6733  * we need to take any VLANs etc. together too.
6734  */
6735 static int
6736 mac_rx_move_macaddr(mac_client_impl_t *mcip, mac_group_t *fgrp,
6737     mac_group_t *tgrp)
6738 {
6739         mac_impl_t              *mip = mcip->mci_mip;
6740         uint8_t                 maddr[MAXMACADDRLEN];
6741         int                     err = 0;
6742         boolean_t               prim;
6743         boolean_t               multiclnt = B_FALSE;

6744 
6745         mac_rx_client_quiesce((mac_client_handle_t)mcip);
6746         ASSERT(mcip->mci_unicast != NULL);
6747         bcopy(mcip->mci_unicast->ma_addr, maddr, mcip->mci_unicast->ma_len);
6748 
6749         prim = (mcip->mci_state_flags & MCIS_UNICAST_HW) != 0;
6750         if (mcip->mci_unicast->ma_nusers > 1) {
6751                 mac_rx_move_macaddr_prim(mcip, fgrp, NULL, maddr, B_FALSE);
6752                 multiclnt = B_TRUE;
6753         }
6754         ASSERT(mcip->mci_unicast->ma_nusers == 1);
6755         err = mac_remove_macaddr(mcip->mci_unicast);











6756         if (err != 0) {
6757                 mac_rx_client_restart((mac_client_handle_t)mcip);
6758                 if (multiclnt) {
6759                         mac_rx_move_macaddr_prim(mcip, fgrp, fgrp, maddr,
6760                             B_TRUE);
6761                 }
6762                 return (err);
6763         }

6764         /*
6765          * Program the H/W Classifier first, if this fails we need
6766          * not proceed with the other stuff.


6767          */
6768         if ((err = mac_add_macaddr(mip, tgrp, maddr, prim)) != 0) {
6769                 /* Revert back the H/W Classifier */
6770                 if ((err = mac_add_macaddr(mip, fgrp, maddr, prim)) != 0) {
6771                         /*
6772                          * This should not fail now since it worked earlier,
6773                          * should we panic?
6774                          */
6775                         cmn_err(CE_WARN,
6776                             "mac_rx_switch_group: switching %p back"
6777                             " to group %p failed!!", (void *)mcip,
6778                             (void *)fgrp);















6779                 }

6780                 mac_rx_client_restart((mac_client_handle_t)mcip);
6781                 if (multiclnt) {
6782                         mac_rx_move_macaddr_prim(mcip, fgrp, fgrp, maddr,
6783                             B_TRUE);
6784                 }
6785                 return (err);
6786         }






6787         mcip->mci_unicast = mac_find_macaddr(mip, maddr);




6788         mac_rx_client_restart((mac_client_handle_t)mcip);
6789         if (multiclnt)
6790                 mac_rx_move_macaddr_prim(mcip, fgrp, tgrp, maddr, B_TRUE);
6791         return (err);
6792 }
6793 
6794 /*
6795  * Switch the MAC client from one group to another. This means we need
6796  * to remove the MAC address from the group, remove the MAC client,
6797  * teardown the SRSs and revert the group state. Then, we add the client
6798  * to the destination group, set the SRSs, and add the MAC address to the
6799  * group.
6800  */
6801 int
6802 mac_rx_switch_group(mac_client_impl_t *mcip, mac_group_t *fgrp,
6803     mac_group_t *tgrp)
6804 {
6805         int                     err;
6806         mac_group_state_t       next_state;
6807         mac_client_impl_t       *group_only_mcip;
6808         mac_client_impl_t       *gmcip;
6809         mac_impl_t              *mip = mcip->mci_mip;
6810         mac_grp_client_t        *mgcp;
6811 
6812         ASSERT(fgrp == mcip->mci_flent->fe_rx_ring_group);
6813 
6814         if ((err = mac_rx_move_macaddr(mcip, fgrp, tgrp)) != 0)
6815                 return (err);
6816 
6817         /*
6818          * The group might be reserved, but SRSs may not be set up, e.g.
6819          * primary and its vlans using a reserved group.
6820          */
6821         if (fgrp->mrg_state == MAC_GROUP_STATE_RESERVED &&
6822             MAC_GROUP_ONLY_CLIENT(fgrp) != NULL) {
6823                 mac_rx_srs_group_teardown(mcip->mci_flent, B_TRUE);
6824         }















6825         if (fgrp != MAC_DEFAULT_RX_GROUP(mip)) {
6826                 mgcp = fgrp->mrg_clients;
6827                 while (mgcp != NULL) {
6828                         gmcip = mgcp->mgc_client;
6829                         mgcp = mgcp->mgc_next;
6830                         mac_group_remove_client(fgrp, gmcip);
6831                         mac_group_add_client(tgrp, gmcip);
6832                         gmcip->mci_flent->fe_rx_ring_group = tgrp;
6833                 }
6834                 mac_release_rx_group(mcip, fgrp);
6835                 ASSERT(MAC_GROUP_NO_CLIENT(fgrp));
6836                 mac_set_group_state(fgrp, MAC_GROUP_STATE_REGISTERED);
6837         } else {
6838                 mac_group_remove_client(fgrp, mcip);
6839                 mac_group_add_client(tgrp, mcip);
6840                 mcip->mci_flent->fe_rx_ring_group = tgrp;

6841                 /*
6842                  * If there are other clients (VLANs) sharing this address
6843                  * we should be here only for the primary.
6844                  */
6845                 if (mcip->mci_unicast->ma_nusers > 1) {
6846                         /*
6847                          * We need to move all the clients that are using
6848                          * this h/w address.
6849                          */
6850                         mgcp = fgrp->mrg_clients;
6851                         while (mgcp != NULL) {
6852                                 gmcip = mgcp->mgc_client;
6853                                 mgcp = mgcp->mgc_next;
6854                                 if (mcip->mci_unicast == gmcip->mci_unicast) {
6855                                         mac_group_remove_client(fgrp, gmcip);
6856                                         mac_group_add_client(tgrp, gmcip);
6857                                         gmcip->mci_flent->fe_rx_ring_group =
6858                                             tgrp;
6859                                 }
6860                         }
6861                 }

6862                 /*
6863                  * The default group will still take the multicast,
6864                  * broadcast traffic etc., so it won't go to
6865                  * MAC_GROUP_STATE_REGISTERED.
6866                  */
6867                 if (fgrp->mrg_state == MAC_GROUP_STATE_RESERVED)
6868                         mac_rx_group_unmark(fgrp, MR_CONDEMNED);
6869                 mac_set_group_state(fgrp, MAC_GROUP_STATE_SHARED);
6870         }

6871         next_state = mac_group_next_state(tgrp, &group_only_mcip,
6872             MAC_DEFAULT_RX_GROUP(mip), B_TRUE);
6873         mac_set_group_state(tgrp, next_state);

6874         /*
6875          * If the destination group is reserved, setup the SRSs etc.

6876          */
6877         if (tgrp->mrg_state == MAC_GROUP_STATE_RESERVED) {
6878                 mac_rx_srs_group_setup(mcip, mcip->mci_flent, SRST_LINK);
6879                 mac_fanout_setup(mcip, mcip->mci_flent,
6880                     MCIP_RESOURCE_PROPS(mcip), mac_rx_deliver, mcip, NULL,
6881                     NULL);
6882                 mac_rx_group_unmark(tgrp, MR_INCIPIENT);
6883         } else {
6884                 mac_rx_switch_grp_to_sw(tgrp);
6885         }

6886         return (0);
6887 }
6888 
6889 /*
6890  * Reserves a TX group for the specified share. Invoked by mac_tx_srs_setup()
6891  * when a share was allocated to the client.
6892  */
6893 mac_group_t *
6894 mac_reserve_tx_group(mac_client_impl_t *mcip, boolean_t move)
6895 {
6896         mac_impl_t              *mip = mcip->mci_mip;
6897         mac_group_t             *grp = NULL;
6898         int                     rv;
6899         int                     i;
6900         int                     err;
6901         mac_group_t             *defgrp;
6902         mac_share_handle_t      share = mcip->mci_share;
6903         mac_resource_props_t    *mrp = MCIP_RESOURCE_PROPS(mcip);
6904         int                     nrings;
6905         int                     defnrings;
6906         boolean_t               need_exclgrp = B_FALSE;
6907         int                     need_rings = 0;
6908         mac_group_t             *candidate_grp = NULL;
6909         mac_client_impl_t       *gclient;
6910         mac_resource_props_t    *gmrp;
6911         boolean_t               txhw = mrp->mrp_mask & MRP_TX_RINGS;
6912         boolean_t               unspec = mrp->mrp_mask & MRP_TXRINGS_UNSPEC;
6913         boolean_t               isprimary;
6914 
6915         isprimary = mcip->mci_flent->fe_type & FLOW_PRIMARY_MAC;

6916         /*
6917          * When we come here for a VLAN on the primary (dladm create-vlan),
6918          * we need to pair it along with the primary (to keep it consistent
6919          * with the RX side). So, we check if the primary is already assigned
6920          * to a group and return the group if so. The other way is also
6921          * true, i.e. the VLAN is already created and now we are plumbing
6922          * the primary.
6923          */
6924         if (!move && isprimary) {
6925                 for (gclient = mip->mi_clients_list; gclient != NULL;
6926                     gclient = gclient->mci_client_next) {
6927                         if (gclient->mci_flent->fe_type & FLOW_PRIMARY_MAC &&
6928                             gclient->mci_flent->fe_tx_ring_group != NULL) {
6929                                 return (gclient->mci_flent->fe_tx_ring_group);
6930                         }
6931                 }
6932         }
6933 
6934         if (mip->mi_tx_groups == NULL || mip->mi_tx_group_count == 0)
6935                 return (NULL);


6977          */
6978         if (isprimary && !need_exclgrp)
6979                 return (NULL);
6980 
6981         nrings = (mrp->mrp_mask & MRP_TX_RINGS) != 0 ? mrp->mrp_ntxrings : 1;
6982         for (i = 0; i <  mip->mi_tx_group_count; i++) {
6983                 grp = &mip->mi_tx_groups[i];
6984                 if ((grp->mrg_state == MAC_GROUP_STATE_RESERVED) ||
6985                     (grp->mrg_state == MAC_GROUP_STATE_UNINIT)) {
6986                         /*
6987                          * Select a candidate for replacement if we don't
6988                          * get an exclusive group. A candidate group is one
6989                          * that didn't ask for an exclusive group, but got
6990                          * one and it has enough rings (combined with what
6991                          * the default group can donate) for the new MAC
6992                          * client.
6993                          */
6994                         if (grp->mrg_state == MAC_GROUP_STATE_RESERVED &&
6995                             candidate_grp == NULL) {
6996                                 gclient = MAC_GROUP_ONLY_CLIENT(grp);
6997                                 if (gclient == NULL)
6998                                         gclient = mac_get_grp_primary(grp);
6999                                 gmrp = MCIP_RESOURCE_PROPS(gclient);
7000                                 if (gclient->mci_share == 0 &&
7001                                     (gmrp->mrp_mask & MRP_TX_RINGS) == 0 &&
7002                                     (unspec ||
7003                                     (grp->mrg_cur_count + defnrings) >=
7004                                     need_rings)) {
7005                                         candidate_grp = grp;
7006                                 }
7007                         }
7008                         continue;
7009                 }
7010                 /*
7011                  * If the default can't donate let's just walk and
7012                  * see if someone can vacate a group, so that we have
7013                  * enough rings for this.
7014                  */
7015                 if (mip->mi_tx_group_type != MAC_GROUP_TYPE_DYNAMIC ||
7016                     nrings <= defnrings) {
7017                         if (grp->mrg_state == MAC_GROUP_STATE_REGISTERED) {
7018                                 rv = mac_start_group(grp);
7019                                 ASSERT(rv == 0);
7020                         }
7021                         break;
7022                 }
7023         }
7024 
7025         /* The default group */
7026         if (i >= mip->mi_tx_group_count) {
7027                 /*
7028                  * If we need an exclusive group and have identified a
7029                  * candidate group we switch the MAC client from the
7030                  * candidate group to the default group and give the
7031                  * candidate group to this client.
7032                  */
7033                 if (need_exclgrp && candidate_grp != NULL) {
7034                         /*
7035                          * Switch the MAC client from the candidate group
7036                          * to the default group.


7037                          */
7038                         grp = candidate_grp;
7039                         gclient = MAC_GROUP_ONLY_CLIENT(grp);
7040                         if (gclient == NULL)
7041                                 gclient = mac_get_grp_primary(grp);
7042                         mac_tx_client_quiesce((mac_client_handle_t)gclient);
7043                         mac_tx_switch_group(gclient, grp, defgrp);
7044                         mac_tx_client_restart((mac_client_handle_t)gclient);
7045 
7046                         /*
7047                          * Give the candidate group with the specified number
7048                          * of rings to this MAC client.
7049                          */
7050                         ASSERT(grp->mrg_state == MAC_GROUP_STATE_REGISTERED);
7051                         rv = mac_start_group(grp);
7052                         ASSERT(rv == 0);
7053 
7054                         if (mip->mi_tx_group_type != MAC_GROUP_TYPE_DYNAMIC)
7055                                 return (grp);
7056 
7057                         ASSERT(grp->mrg_cur_count == 0);
7058                         ASSERT(defgrp->mrg_cur_count > need_rings);
7059 
7060                         err = i_mac_group_allocate_rings(mip, MAC_RING_TYPE_TX,
7061                             defgrp, grp, share, need_rings);


7189     mac_group_t *tgrp)
7190 {
7191         mac_client_impl_t       *group_only_mcip;
7192         mac_impl_t              *mip = mcip->mci_mip;
7193         flow_entry_t            *flent = mcip->mci_flent;
7194         mac_group_t             *defgrp;
7195         mac_grp_client_t        *mgcp;
7196         mac_client_impl_t       *gmcip;
7197         flow_entry_t            *gflent;
7198 
7199         defgrp = MAC_DEFAULT_TX_GROUP(mip);
7200         ASSERT(fgrp == flent->fe_tx_ring_group);
7201 
7202         if (fgrp == defgrp) {
7203                 /*
7204                  * If this is the primary we need to find any VLANs on
7205                  * the primary and move them too.
7206                  */
7207                 mac_group_remove_client(fgrp, mcip);
7208                 mac_tx_dismantle_soft_rings(fgrp, flent);
7209                 if (mcip->mci_unicast->ma_nusers > 1) {
7210                         mgcp = fgrp->mrg_clients;
7211                         while (mgcp != NULL) {
7212                                 gmcip = mgcp->mgc_client;
7213                                 mgcp = mgcp->mgc_next;
7214                                 if (mcip->mci_unicast != gmcip->mci_unicast)
7215                                         continue;
7216                                 mac_tx_client_quiesce(
7217                                     (mac_client_handle_t)gmcip);
7218 
7219                                 gflent = gmcip->mci_flent;
7220                                 mac_group_remove_client(fgrp, gmcip);
7221                                 mac_tx_dismantle_soft_rings(fgrp, gflent);
7222 
7223                                 mac_group_add_client(tgrp, gmcip);
7224                                 gflent->fe_tx_ring_group = tgrp;
7225                                 /* We could directly set this to SHARED */
7226                                 tgrp->mrg_state = mac_group_next_state(tgrp,
7227                                     &group_only_mcip, defgrp, B_FALSE);
7228 
7229                                 mac_tx_srs_group_setup(gmcip, gflent,


7435         mutex_exit(&mip->mi_bridge_lock);
7436         mac_poll_state_change(mh, B_TRUE);
7437         mac_capab_update(mh);
7438 }
7439 
7440 void
7441 mac_no_active(mac_handle_t mh)
7442 {
7443         mac_impl_t *mip = (mac_impl_t *)mh;
7444 
7445         i_mac_perim_enter(mip);
7446         mip->mi_state_flags |= MIS_NO_ACTIVE;
7447         i_mac_perim_exit(mip);
7448 }
7449 
7450 /*
7451  * Walk the primary VLAN clients whenever the primary's rings property
7452  * changes and update the mac_resource_props_t for the VLAN's client.
7453  * We need to do this since we don't support setting these properties
7454  * on the primary's VLAN clients, but the VLAN clients have to
7455  * follow the primary w.r.t the rings property;
7456  */
7457 void
7458 mac_set_prim_vlan_rings(mac_impl_t  *mip, mac_resource_props_t *mrp)
7459 {
7460         mac_client_impl_t       *vmcip;
7461         mac_resource_props_t    *vmrp;
7462 
7463         for (vmcip = mip->mi_clients_list; vmcip != NULL;
7464             vmcip = vmcip->mci_client_next) {
7465                 if (!(vmcip->mci_flent->fe_type & FLOW_PRIMARY_MAC) ||
7466                     mac_client_vid((mac_client_handle_t)vmcip) ==
7467                     VLAN_ID_NONE) {
7468                         continue;
7469                 }
7470                 vmrp = MCIP_RESOURCE_PROPS(vmcip);
7471 
7472                 vmrp->mrp_nrxrings =  mrp->mrp_nrxrings;
7473                 if (mrp->mrp_mask & MRP_RX_RINGS)
7474                         vmrp->mrp_mask |= MRP_RX_RINGS;
7475                 else if (vmrp->mrp_mask & MRP_RX_RINGS)


7584                 start = 1;
7585                 end = mip->mi_rx_group_count;
7586         } else {
7587                 start = 0;
7588                 end = mip->mi_tx_group_count - 1;
7589         }
7590         /*
7591          * If the default doesn't have any rings, lets see if we can
7592          * take rings given to an h/w client that doesn't need it.
7593          * For now, we just see if there is  any one client that can donate
7594          * all the required rings.
7595          */
7596         if (defgrp->mrg_cur_count < (modify + 1)) {
7597                 for (i = start; i < end; i++) {
7598                         if (rx_group) {
7599                                 tgrp = &mip->mi_rx_groups[i];
7600                                 if (tgrp == group || tgrp->mrg_state <
7601                                     MAC_GROUP_STATE_RESERVED) {
7602                                         continue;
7603                                 }
7604                                 mcip = MAC_GROUP_ONLY_CLIENT(tgrp);
7605                                 if (mcip == NULL)
7606                                         mcip = mac_get_grp_primary(tgrp);
7607                                 ASSERT(mcip != NULL);
7608                                 mrp = MCIP_RESOURCE_PROPS(mcip);
7609                                 if ((mrp->mrp_mask & MRP_RX_RINGS) != 0)
7610                                         continue;


7611                                 if ((tgrp->mrg_cur_count +
7612                                     defgrp->mrg_cur_count) < (modify + 1)) {
7613                                         continue;
7614                                 }
7615                                 if (mac_rx_switch_group(mcip, tgrp,
7616                                     defgrp) != 0) {
7617                                         return (ENOSPC);
7618                                 }
7619                         } else {
7620                                 tgrp = &mip->mi_tx_groups[i];
7621                                 if (tgrp == group || tgrp->mrg_state <
7622                                     MAC_GROUP_STATE_RESERVED) {
7623                                         continue;
7624                                 }
7625                                 mcip = MAC_GROUP_ONLY_CLIENT(tgrp);
7626                                 if (mcip == NULL)
7627                                         mcip = mac_get_grp_primary(tgrp);
7628                                 mrp = MCIP_RESOURCE_PROPS(mcip);
7629                                 if ((mrp->mrp_mask & MRP_TX_RINGS) != 0)
7630                                         continue;


7631                                 if ((tgrp->mrg_cur_count +
7632                                     defgrp->mrg_cur_count) < (modify + 1)) {
7633                                         continue;
7634                                 }
7635                                 /* OK, we can switch this to s/w */
7636                                 mac_tx_client_quiesce(
7637                                     (mac_client_handle_t)mcip);
7638                                 mac_tx_switch_group(mcip, tgrp, defgrp);
7639                                 mac_tx_client_restart(
7640                                     (mac_client_handle_t)mcip);
7641                         }
7642                 }
7643                 if (defgrp->mrg_cur_count < (modify + 1))
7644                         return (ENOSPC);
7645         }
7646         if ((rv = i_mac_group_allocate_rings(mip, group->mrg_type, defgrp,
7647             group, mcip->mci_share, modify)) != 0) {
7648                 return (rv);
7649         }
7650         return (0);


7883 
7884         default:
7885                 kmem_free(mpa, sizeof (struct mac_pool_arg));
7886                 pool_unlock();
7887                 return;
7888         }
7889         pool_unlock();
7890 
7891         mpa->mpa_what = what;
7892 
7893         mac_pool_update(mpa);
7894 }
7895 
7896 /*
7897  * Set effective rings property. This could be called from datapath_setup/
7898  * datapath_teardown or set-linkprop.
7899  * If the group is reserved we just go ahead and set the effective rings.
7900  * Additionally, for TX this could mean the default  group has lost/gained
7901  * some rings, so if the default group is reserved, we need to adjust the
7902  * effective rings for the default group clients. For RX, if we are working
7903  * with the non-default group, we just need * to reset the effective props
7904  * for the default group clients.
7905  */
7906 void
7907 mac_set_rings_effective(mac_client_impl_t *mcip)
7908 {
7909         mac_impl_t              *mip = mcip->mci_mip;
7910         mac_group_t             *grp;
7911         mac_group_t             *defgrp;
7912         flow_entry_t            *flent = mcip->mci_flent;
7913         mac_resource_props_t    *emrp = MCIP_EFFECTIVE_PROPS(mcip);
7914         mac_grp_client_t        *mgcp;
7915         mac_client_impl_t       *gmcip;
7916 
7917         grp = flent->fe_rx_ring_group;
7918         if (grp != NULL) {
7919                 defgrp = MAC_DEFAULT_RX_GROUP(mip);
7920                 /*
7921                  * If we have reserved a group, set the effective rings
7922                  * to the ring count in the group.
7923                  */


8013          * Check if the primary is in the default group, if not
8014          * or if it is explicitly configured to be in the default
8015          * group OR set the RX rings property, return.
8016          */
8017         if (flent->fe_rx_ring_group != defgrp || mrp->mrp_mask & MRP_RX_RINGS)
8018                 return (NULL);
8019 
8020         /*
8021          * If the new client needs an exclusive group and we
8022          * don't have another for the primary, return.
8023          */
8024         if (rxhw && mip->mi_rxhwclnt_avail < 2)
8025                 return (NULL);
8026 
8027         mac_addr = flent->fe_flow_desc.fd_dst_mac;
8028         /*
8029          * We call this when we are setting up the datapath for
8030          * the first non-primary.
8031          */
8032         ASSERT(mip->mi_nactiveclients == 2);

8033         /*
8034          * OK, now we have the primary that needs to be relocated.
8035          */
8036         ngrp =  mac_reserve_rx_group(mcip, mac_addr, B_TRUE);
8037         if (ngrp == NULL)
8038                 return (NULL);
8039         if (mac_rx_switch_group(mcip, defgrp, ngrp) != 0) {
8040                 mac_stop_group(ngrp);
8041                 return (NULL);
8042         }
8043         return (mcip);
8044 }
8045 
8046 void
8047 mac_transceiver_init(mac_impl_t *mip)
8048 {
8049         if (mac_capab_get((mac_handle_t)mip, MAC_CAPAB_TRANSCEIVER,
8050             &mip->mi_transceiver)) {
8051                 /*
8052                  * The driver set a flag that we don't know about. In this case,




 443 
 444         i_mactype_hash = mod_hash_create_extended("mactype_hash",
 445             MACTYPE_HASHSZ,
 446             mod_hash_null_keydtor, mod_hash_null_valdtor,
 447             mod_hash_bystr, NULL, mod_hash_strkey_cmp, KM_SLEEP);
 448 
 449         /*
 450          * Allocate an id space to manage minor numbers. The range of the
 451          * space will be from MAC_MAX_MINOR+1 to MAC_PRIVATE_MINOR-1.  This
 452          * leaves half of the 32-bit minors available for driver private use.
 453          */
 454         minor_ids = id_space_create("mac_minor_ids", MAC_MAX_MINOR+1,
 455             MAC_PRIVATE_MINOR-1);
 456         ASSERT(minor_ids != NULL);
 457         minor_count = 0;
 458 
 459         /* Let's default to 20 seconds */
 460         mac_logging_interval = 20;
 461         mac_flow_log_enable = B_FALSE;
 462         mac_link_log_enable = B_FALSE;
 463         mac_logging_timer = NULL;
 464 
 465         /* Register to be notified of noteworthy pools events */
 466         mac_pool_event_reg.pec_func =  mac_pool_event_cb;
 467         mac_pool_event_reg.pec_arg = NULL;
 468         pool_event_cb_register(&mac_pool_event_reg);
 469 }
 470 
 471 int
 472 mac_fini(void)
 473 {
 474 
 475         if (i_mac_impl_count > 0 || minor_count > 0)
 476                 return (EBUSY);
 477 
 478         pool_event_cb_unregister(&mac_pool_event_reg);
 479 
 480         id_space_destroy(minor_ids);
 481         mac_flow_fini();
 482 
 483         mod_hash_destroy_hash(i_mac_impl_hash);


1098                         return (err);
1099                 }
1100 
1101                 /*
1102                  * Start the default tx ring.
1103                  */
1104                 if (mip->mi_default_tx_ring != NULL) {
1105 
1106                         ring = (mac_ring_t *)mip->mi_default_tx_ring;
1107                         if (ring->mr_state != MR_INUSE) {
1108                                 err = mac_start_ring(ring);
1109                                 if (err != 0) {
1110                                         mip->mi_active--;
1111                                         return (err);
1112                                 }
1113                         }
1114                 }
1115 
1116                 if ((defgrp = MAC_DEFAULT_RX_GROUP(mip)) != NULL) {
1117                         /*
1118                          * Start the default group which is responsible
1119                          * for receiving broadcast and multicast
1120                          * traffic for both primary and non-primary
1121                          * MAC clients.
1122                          */
1123                         ASSERT(defgrp->mrg_state == MAC_GROUP_STATE_REGISTERED);
1124                         err = mac_start_group_and_rings(defgrp);
1125                         if (err != 0) {
1126                                 mip->mi_active--;
1127                                 if ((ring != NULL) &&
1128                                     (ring->mr_state == MR_INUSE))
1129                                         mac_stop_ring(ring);
1130                                 return (err);
1131                         }
1132                         mac_set_group_state(defgrp, MAC_GROUP_STATE_SHARED);
1133                 }
1134         }
1135 
1136         return (err);
1137 }
1138 
1139 /*
1140  * Private GLDv3 function to stop a MAC instance.
1141  */


1714         mip->mi_default_tx_ring = rh;
1715 }
1716 
1717 int
1718 mac_hwgroup_addmac(mac_group_handle_t gh, const uint8_t *addr)
1719 {
1720         mac_group_t *group = (mac_group_t *)gh;
1721 
1722         return (mac_group_addmac(group, addr));
1723 }
1724 
1725 int
1726 mac_hwgroup_remmac(mac_group_handle_t gh, const uint8_t *addr)
1727 {
1728         mac_group_t *group = (mac_group_t *)gh;
1729 
1730         return (mac_group_remmac(group, addr));
1731 }
1732 
1733 /*
1734  * Program the group's HW VLAN filter if it has such support.
1735  * Otherwise, the group will implicitly accept tagged traffic and
1736  * there is nothing to do.
1737  */
1738 int
1739 mac_hwgroup_addvlan(mac_group_handle_t gh, uint16_t vid)
1740 {
1741         mac_group_t *group = (mac_group_t *)gh;
1742 
1743         if (!MAC_GROUP_HW_VLAN(group))
1744                 return (0);
1745 
1746         return (mac_group_addvlan(group, vid));
1747 }
1748 
1749 int
1750 mac_hwgroup_remvlan(mac_group_handle_t gh, uint16_t vid)
1751 {
1752         mac_group_t *group = (mac_group_t *)gh;
1753 
1754         if (!MAC_GROUP_HW_VLAN(group))
1755                 return (0);
1756 
1757         return (mac_group_remvlan(group, vid));
1758 }
1759 
1760 /*
1761  * Determine if a MAC has HW VLAN support. This is a private API
1762  * consumed by aggr. In the future it might be nice to have a bitfield
1763  * in mac_capab_rings_t to track which forms of HW filtering are
1764  * supported by the MAC.
1765  */
1766 boolean_t
1767 mac_has_hw_vlan(mac_handle_t mh)
1768 {
1769         mac_impl_t *mip = (mac_impl_t *)mh;
1770 
1771         return (MAC_GROUP_HW_VLAN(mip->mi_rx_groups));
1772 }
1773 
1774 /*
1775  * Set the RX group to be shared/reserved. Note that the group must be
1776  * started/stopped outside of this function.
1777  */
1778 void
1779 mac_set_group_state(mac_group_t *grp, mac_group_state_t state)
1780 {
1781         /*
1782          * If there is no change in the group state, just return.
1783          */
1784         if (grp->mrg_state == state)
1785                 return;
1786 
1787         switch (state) {
1788         case MAC_GROUP_STATE_RESERVED:
1789                 /*
1790                  * Successfully reserved the group.
1791                  *
1792                  * Given that there is an exclusive client controlling this
1793                  * group, we enable the group level polling when available,
1794                  * so that SRSs get to turn on/off individual rings they's


2439 {
2440         mac_impl_t      *mip = (mac_impl_t *)mh;
2441         int err;
2442 
2443         i_mac_perim_enter(mip);
2444         err = i_mac_disable(mip);
2445         i_mac_perim_exit(mip);
2446 
2447         /*
2448          * Clean up notification thread and wait for it to exit.
2449          */
2450         if (err == 0)
2451                 i_mac_notify_exit(mip);
2452 
2453         return (err);
2454 }
2455 
2456 /*
2457  * Called when the MAC instance has a non empty flow table, to de-multiplex
2458  * incoming packets to the right flow.

2459  */
2460 /* ARGSUSED */
2461 static mblk_t *
2462 mac_rx_classify(mac_impl_t *mip, mac_resource_handle_t mrh, mblk_t *mp)
2463 {
2464         flow_entry_t    *flent = NULL;
2465         uint_t          flags = FLOW_INBOUND;
2466         int             err;
2467 
2468         /*
2469          * If the MAC is a port of an aggregation, pass FLOW_IGNORE_VLAN
2470          * to mac_flow_lookup() so that the VLAN packets can be successfully
2471          * passed to the non-VLAN aggregation flows.
2472          *
2473          * Note that there is possibly a race between this and
2474          * mac_unicast_remove/add() and VLAN packets could be incorrectly
2475          * classified to non-VLAN flows of non-aggregation MAC clients. These
2476          * VLAN packets will be then filtered out by the MAC module.
2477          */
2478         if ((mip->mi_state_flags & MIS_EXCLUSIVE) != 0)
2479                 flags |= FLOW_IGNORE_VLAN;
2480 
2481         err = mac_flow_lookup(mip->mi_flow_tab, mp, flags, &flent);
2482         if (err != 0) {
2483                 /* no registered receive function */
2484                 return (mp);
2485         } else {
2486                 mac_client_impl_t       *mcip;
2487 
2488                 /*
2489                  * This flent might just be an additional one on the MAC client,
2490                  * i.e. for classification purposes (different fdesc), however
2491                  * the resources, SRS et. al., are in the mci_flent, so if
2492                  * this isn't the mci_flent, we need to get it.
2493                  */
2494                 if ((mcip = flent->fe_mcip) != NULL &&
2495                     mcip->mci_flent != flent) {
2496                         FLOW_REFRELE(flent);


4099                                 break;
4100                         }
4101                         break;
4102                 case MAC_GROUP_TYPE_STATIC:
4103                         /*
4104                          * Note that an empty group is allowed, e.g., an aggr
4105                          * would start with an empty group.
4106                          */
4107                         break;
4108                 default:
4109                         /* unknown group type */
4110                         DTRACE_PROBE2(mac__init__rings__unknown__type,
4111                             char *, mip->mi_name,
4112                             int, cap_rings->mr_group_type);
4113                         err = EINVAL;
4114                         goto bail;
4115                 }
4116 
4117 
4118                 /*
4119                  * The driver must register some form of hardware MAC
4120                  * filter in order for Rx groups to support multiple
4121                  * MAC addresses.
4122                  */
4123                 if (rtype == MAC_RING_TYPE_RX &&
4124                     (group_info.mgi_addmac == NULL ||
4125                     group_info.mgi_remmac == NULL)) {
4126                         DTRACE_PROBE1(mac__init__rings__no__mac__filter,
4127                             char *, mip->mi_name);
4128                         err = EINVAL;
4129                         goto bail;
4130                 }
4131 
4132                 /* Cache driver-supplied information */
4133                 group->mrg_info = group_info;
4134 
4135                 /* Update the group's status and group count. */
4136                 mac_set_group_state(group, MAC_GROUP_STATE_REGISTERED);
4137                 group_free++;
4138 
4139                 group->mrg_rings = NULL;
4140                 group->mrg_cur_count = 0;
4141                 mac_init_group(mip, group, group_info.mgi_count, cap_rings);
4142                 ring_left -= group_info.mgi_count;
4143 
4144                 /* The current group size should be equal to default value */
4145                 ASSERT(group->mrg_cur_count == group_info.mgi_count);
4146         }
4147 


4154         group->mrg_state = MAC_GROUP_STATE_UNINIT;
4155         group->mrg_mh = (mac_handle_t)mip;
4156         group->mrg_next = NULL;
4157 
4158         /*
4159          * If there are ungrouped rings, allocate a continuous buffer for
4160          * remaining resources.
4161          */
4162         if (ring_left != 0) {
4163                 group->mrg_rings = NULL;
4164                 group->mrg_cur_count = 0;
4165                 mac_init_group(mip, group, ring_left, cap_rings);
4166 
4167                 /* The current group size should be equal to ring_left */
4168                 ASSERT(group->mrg_cur_count == ring_left);
4169 
4170                 ring_left = 0;
4171 
4172                 /* Update this group's status */
4173                 mac_set_group_state(group, MAC_GROUP_STATE_REGISTERED);
4174         } else {
4175                 group->mrg_rings = NULL;
4176         }
4177 
4178         ASSERT(ring_left == 0);
4179 
4180 bail:
4181 
4182         /* Cache other important information to finalize the initialization */
4183         switch (rtype) {
4184         case MAC_RING_TYPE_RX:
4185                 mip->mi_rx_group_type = cap_rings->mr_group_type;
4186                 mip->mi_rx_group_count = cap_rings->mr_gnum;
4187                 mip->mi_rx_groups = groups;
4188                 mip->mi_rx_donor_grp = groups;
4189                 if (mip->mi_rx_group_type == MAC_GROUP_TYPE_DYNAMIC) {
4190                         /*
4191                          * The default ring is reserved since it is
4192                          * used for sending the broadcast etc. packets.
4193                          */
4194                         mip->mi_rxrings_avail =
4195                             mip->mi_rx_groups->mrg_cur_count - 1;
4196                         mip->mi_rxrings_rsvd = 1;


4346                 mac_ring_t *ring;
4347 
4348                 if (group->mrg_cur_count == 0)
4349                         continue;
4350 
4351                 ASSERT(group->mrg_rings != NULL);
4352 
4353                 while ((ring = group->mrg_rings) != NULL) {
4354                         group->mrg_rings = ring->mr_next;
4355                         mac_ring_free(mip, ring);
4356                 }
4357         }
4358 
4359         /* Free all the cached rings */
4360         mac_ring_freeall(mip);
4361         /* Free the block of group data strutures */
4362         kmem_free(groups, sizeof (mac_group_t) * (group_count + 1));
4363 }
4364 
4365 /*
4366  * Associate the VLAN filter to the receive group.
4367  */
4368 int
4369 mac_group_addvlan(mac_group_t *group, uint16_t vlan)
4370 {
4371         VERIFY3S(group->mrg_type, ==, MAC_RING_TYPE_RX);
4372         VERIFY3P(group->mrg_info.mgi_addvlan, !=, NULL);
4373 
4374         if (vlan > VLAN_ID_MAX)
4375                 return (EINVAL);
4376 
4377         vlan = MAC_VLAN_UNTAGGED_VID(vlan);
4378         return (group->mrg_info.mgi_addvlan(group->mrg_info.mgi_driver, vlan));
4379 }
4380 
4381 /*
4382  * Dissociate the VLAN from the receive group.
4383  */
4384 int
4385 mac_group_remvlan(mac_group_t *group, uint16_t vlan)
4386 {
4387         VERIFY3S(group->mrg_type, ==, MAC_RING_TYPE_RX);
4388         VERIFY3P(group->mrg_info.mgi_remvlan, !=, NULL);
4389 
4390         if (vlan > VLAN_ID_MAX)
4391                 return (EINVAL);
4392 
4393         vlan = MAC_VLAN_UNTAGGED_VID(vlan);
4394         return (group->mrg_info.mgi_remvlan(group->mrg_info.mgi_driver, vlan));
4395 }
4396 
4397 /*
4398  * Associate a MAC address with a receive group.
4399  *
4400  * The return value of this function should always be checked properly, because
4401  * any type of failure could cause unexpected results. A group can be added
4402  * or removed with a MAC address only after it has been reserved. Ideally,
4403  * a successful reservation always leads to calling mac_group_addmac() to
4404  * steer desired traffic. Failure of adding an unicast MAC address doesn't
4405  * always imply that the group is functioning abnormally.
4406  *
4407  * Currently this function is called everywhere, and it reflects assumptions
4408  * about MAC addresses in the implementation. CR 6735196.
4409  */
4410 int
4411 mac_group_addmac(mac_group_t *group, const uint8_t *addr)
4412 {
4413         VERIFY3S(group->mrg_type, ==, MAC_RING_TYPE_RX);
4414         VERIFY3P(group->mrg_info.mgi_addmac, !=, NULL);
4415 
4416         return (group->mrg_info.mgi_addmac(group->mrg_info.mgi_driver, addr));
4417 }
4418 
4419 /*
4420  * Remove the association between MAC address and receive group.
4421  */
4422 int
4423 mac_group_remmac(mac_group_t *group, const uint8_t *addr)
4424 {
4425         VERIFY3S(group->mrg_type, ==, MAC_RING_TYPE_RX);
4426         VERIFY3P(group->mrg_info.mgi_remmac, !=, NULL);
4427 
4428         return (group->mrg_info.mgi_remmac(group->mrg_info.mgi_driver, addr));
4429 }
4430 
4431 /*
4432  * This is the entry point for packets transmitted through the bridging code.
4433  * If no bridge is in place, MAC_RING_TX transmits using tx ring. The 'rh'
4434  * pointer may be NULL to select the default ring.
4435  */
4436 mblk_t *
4437 mac_bridge_tx(mac_impl_t *mip, mac_ring_handle_t rh, mblk_t *mp)
4438 {
4439         mac_handle_t mh;
4440 
4441         /*
4442          * Once we take a reference on the bridge link, the bridge
4443          * module itself can't unload, so the callback pointers are
4444          * stable.
4445          */
4446         mutex_enter(&mip->mi_bridge_lock);


4581                                     ring->mr_driver, ring->mr_type);
4582                         }
4583                         group->mrg_cur_count--;
4584                         group->mrg_rings = ring->mr_next;
4585 
4586                         ring->mr_gh = NULL;
4587 
4588                         if (driver_call)
4589                                 mac_ring_free(mip, ring);
4590 
4591                         return (ret);
4592                 }
4593         }
4594 
4595         /*
4596          * Set up SRS/SR according to the ring type.
4597          */
4598         switch (ring->mr_type) {
4599         case MAC_RING_TYPE_RX:
4600                 /*
4601                  * Setup an SRS on top of the new ring if the group is
4602                  * reserved for someone's exclusive use.
4603                  */
4604                 if (group->mrg_state == MAC_GROUP_STATE_RESERVED) {
4605                         mac_client_impl_t *mcip =  MAC_GROUP_ONLY_CLIENT(group);
4606 
4607                         VERIFY3P(mcip, !=, NULL);






4608                         flent = mcip->mci_flent;
4609                         VERIFY3S(flent->fe_rx_srs_cnt, >, 0);
4610                         mac_rx_srs_group_setup(mcip, flent, SRST_LINK);
4611                         mac_fanout_setup(mcip, flent, MCIP_RESOURCE_PROPS(mcip),
4612                             mac_rx_deliver, mcip, NULL, NULL);

4613                 } else {
4614                         ring->mr_classify_type = MAC_SW_CLASSIFIER;
4615                 }

4616                 break;
4617         case MAC_RING_TYPE_TX:
4618         {
4619                 mac_grp_client_t        *mgcp = group->mrg_clients;
4620                 mac_client_impl_t       *mcip;
4621                 mac_soft_ring_set_t     *mac_srs;
4622                 mac_srs_tx_t            *tx;
4623 
4624                 if (MAC_GROUP_NO_CLIENT(group)) {
4625                         if (ring->mr_state == MR_INUSE)
4626                                 mac_stop_ring(ring);
4627                         ring->mr_flag = 0;
4628                         break;
4629                 }
4630                 /*
4631                  * If the rings are being moved to a group that has
4632                  * clients using it, then add the new rings to the
4633                  * clients SRS.
4634                  */
4635                 while (mgcp != NULL) {
4636                         boolean_t       is_aggr;
4637 
4638                         mcip = mgcp->mgc_client;
4639                         flent = mcip->mci_flent;
4640                         is_aggr = (mcip->mci_state_flags & MCIS_IS_AGGR_CLIENT);
4641                         mac_srs = MCIP_TX_SRS(mcip);
4642                         tx = &mac_srs->srs_tx;
4643                         mac_tx_client_quiesce((mac_client_handle_t)mcip);
4644                         /*
4645                          * If we are  growing from 1 to multiple rings.
4646                          */
4647                         if (tx->st_mode == SRS_TX_BW ||
4648                             tx->st_mode == SRS_TX_SERIALIZE ||
4649                             tx->st_mode == SRS_TX_DEFAULT) {
4650                                 mac_ring_t      *tx_ring = tx->st_arg2;
4651 
4652                                 tx->st_arg2 = NULL;
4653                                 mac_tx_srs_stat_recreate(mac_srs, B_TRUE);
4654                                 mac_tx_srs_add_ring(mac_srs, tx_ring);
4655                                 if (mac_srs->srs_type & SRST_BW_CONTROL) {
4656                                         tx->st_mode = is_aggr ? SRS_TX_BW_AGGR :
4657                                             SRS_TX_BW_FANOUT;
4658                                 } else {
4659                                         tx->st_mode = is_aggr ? SRS_TX_AGGR :
4660                                             SRS_TX_FANOUT;


4764                         mac_client_impl_t *mcip;
4765                         mac_soft_ring_set_t *mac_srs;
4766                         mac_soft_ring_t *sringp;
4767                         mac_srs_tx_t *srs_tx;
4768 
4769                         if (mip->mi_state_flags & MIS_IS_AGGR &&
4770                             mip->mi_default_tx_ring ==
4771                             (mac_ring_handle_t)ring) {
4772                                 /* pick a new default Tx ring */
4773                                 mip->mi_default_tx_ring =
4774                                     (group->mrg_rings != ring) ?
4775                                     (mac_ring_handle_t)group->mrg_rings :
4776                                     (mac_ring_handle_t)(ring->mr_next);
4777                         }
4778                         /* Presently only aggr case comes here */
4779                         if (group->mrg_state != MAC_GROUP_STATE_RESERVED)
4780                                 break;
4781 
4782                         mcip = MAC_GROUP_ONLY_CLIENT(group);
4783                         ASSERT(mcip != NULL);
4784                         ASSERT(mcip->mci_state_flags & MCIS_IS_AGGR_CLIENT);
4785                         mac_srs = MCIP_TX_SRS(mcip);
4786                         ASSERT(mac_srs->srs_tx.st_mode == SRS_TX_AGGR ||
4787                             mac_srs->srs_tx.st_mode == SRS_TX_BW_AGGR);
4788                         srs_tx = &mac_srs->srs_tx;
4789                         /*
4790                          * Wakeup any callers blocked on this
4791                          * Tx ring due to flow control.
4792                          */
4793                         sringp = srs_tx->st_soft_rings[ring->mr_index];
4794                         ASSERT(sringp != NULL);
4795                         mac_tx_invoke_callbacks(mcip, (mac_tx_cookie_t)sringp);
4796                         mac_tx_client_quiesce((mac_client_handle_t)mcip);
4797                         mac_tx_srs_del_ring(mac_srs, ring);
4798                         mac_tx_client_restart((mac_client_handle_t)mcip);
4799                         break;
4800                 }
4801                 ASSERT(ring != (mac_ring_t *)mip->mi_default_tx_ring);
4802                 group_type = mip->mi_tx_group_type;
4803                 cap_rings = &mip->mi_tx_rings_cap;
4804                 /*


4972 /*
4973  * Check whether the MAC address is shared by multiple clients.
4974  */
4975 boolean_t
4976 mac_check_macaddr_shared(mac_address_t *map)
4977 {
4978         ASSERT(MAC_PERIM_HELD((mac_handle_t)map->ma_mip));
4979 
4980         return (map->ma_nusers > 1);
4981 }
4982 
4983 /*
4984  * Remove the specified MAC address from the MAC address list and free it.
4985  */
4986 static void
4987 mac_free_macaddr(mac_address_t *map)
4988 {
4989         mac_impl_t *mip = map->ma_mip;
4990 
4991         ASSERT(MAC_PERIM_HELD((mac_handle_t)mip));
4992         VERIFY3P(mip->mi_addresses, !=, NULL);
4993 
4994         VERIFY3P(map, ==, mac_find_macaddr(mip, map->ma_addr));
4995         VERIFY3P(map, !=, NULL);
4996         VERIFY3S(map->ma_nusers, ==, 0);
4997         VERIFY3P(map->ma_vlans, ==, NULL);
4998 



4999         if (map == mip->mi_addresses) {
5000                 mip->mi_addresses = map->ma_next;
5001         } else {
5002                 mac_address_t *pre;
5003 
5004                 pre = mip->mi_addresses;
5005                 while (pre->ma_next != map)
5006                         pre = pre->ma_next;
5007                 pre->ma_next = map->ma_next;
5008         }
5009 
5010         kmem_free(map, sizeof (mac_address_t));
5011 }
5012 
5013 static mac_vlan_t *
5014 mac_find_vlan(mac_address_t *map, uint16_t vid)
5015 {
5016         mac_vlan_t *mvp;
5017 
5018         for (mvp = map->ma_vlans; mvp != NULL; mvp = mvp->mv_next) {
5019                 if (mvp->mv_vid == vid)
5020                         return (mvp);
5021         }
5022 
5023         return (NULL);
5024 }
5025 
5026 static mac_vlan_t *
5027 mac_add_vlan(mac_address_t *map, uint16_t vid)
5028 {
5029         mac_vlan_t *mvp;
5030 
5031         /*
5032          * We should never add the same {addr, VID} tuple more
5033          * than once, but let's be sure.
5034          */
5035         for (mvp = map->ma_vlans; mvp != NULL; mvp = mvp->mv_next)
5036                 VERIFY3U(mvp->mv_vid, !=, vid);
5037 
5038         /* Add the VLAN to the head of the VLAN list. */
5039         mvp = kmem_zalloc(sizeof (mac_vlan_t), KM_SLEEP);
5040         mvp->mv_vid = vid;
5041         mvp->mv_next = map->ma_vlans;
5042         map->ma_vlans = mvp;
5043 
5044         return (mvp);
5045 }
5046 
5047 static void
5048 mac_rem_vlan(mac_address_t *map, mac_vlan_t *mvp)
5049 {
5050         mac_vlan_t *pre;
5051 
5052         if (map->ma_vlans == mvp) {
5053                 map->ma_vlans = mvp->mv_next;
5054         } else {
5055                 pre = map->ma_vlans;
5056                 while (pre->mv_next != mvp) {
5057                         pre = pre->mv_next;
5058 
5059                         /*
5060                          * We've reached the end of the list without
5061                          * finding mvp.
5062                          */
5063                         VERIFY3P(pre, !=, NULL);
5064                 }
5065                 pre->mv_next = mvp->mv_next;
5066         }
5067 
5068         kmem_free(mvp, sizeof (mac_vlan_t));
5069 }
5070 
5071 /*
5072  * Create a new mac_address_t if this is the first use of the address
5073  * or add a VID to an existing address. In either case, the
5074  * mac_address_t acts as a list of {addr, VID} tuples where each tuple
5075  * shares the same addr. If group is non-NULL then attempt to program
5076  * the MAC's HW filters for this group. Otherwise, if group is NULL,
5077  * then the MAC has no rings and there is nothing to program.




5078  */
5079 int
5080 mac_add_macaddr_vlan(mac_impl_t *mip, mac_group_t *group, uint8_t *addr,
5081     uint16_t vid, boolean_t use_hw)
5082 {
5083         mac_address_t   *map;
5084         mac_vlan_t      *mvp;
5085         int             err = 0;
5086         boolean_t       allocated_map = B_FALSE;
5087         boolean_t       hw_mac = B_FALSE;
5088         boolean_t       hw_vlan = B_FALSE;
5089 
5090         ASSERT(MAC_PERIM_HELD((mac_handle_t)mip));
5091 
5092         map = mac_find_macaddr(mip, addr);
5093 
5094         /*
5095          * If this is the first use of this MAC address then allocate
5096          * and initialize a new structure.
5097          */
5098         if (map == NULL) {
5099                 map = kmem_zalloc(sizeof (mac_address_t), KM_SLEEP);
5100                 map->ma_len = mip->mi_type->mt_addr_length;
5101                 bcopy(addr, map->ma_addr, map->ma_len);
5102                 map->ma_nusers = 0;
5103                 map->ma_group = group;
5104                 map->ma_mip = mip;
5105                 map->ma_untagged = B_FALSE;
5106 
5107                 /* Add the new MAC address to the head of the address list. */
5108                 map->ma_next = mip->mi_addresses;
5109                 mip->mi_addresses = map;
5110 
5111                 allocated_map = B_TRUE;
5112         }
5113 
5114         VERIFY(map->ma_group == NULL || map->ma_group == group);
5115         if (map->ma_group == NULL)
5116                 map->ma_group = group;
5117 
5118         if (vid == VLAN_ID_NONE) {
5119                 map->ma_untagged = B_TRUE;
5120                 mvp = NULL;
5121         } else {
5122                 mvp = mac_add_vlan(map, vid);
5123         }
5124 
5125         /*
5126          * Set the VLAN HW filter if:
5127          *
5128          * o the MAC's VLAN HW filtering is enabled, and
5129          * o the address does not currently rely on promisc mode.
5130          *
5131          * This is called even when the client specifies an untagged
5132          * address (VLAN_ID_NONE) because some MAC providers require
5133          * setting additional bits to accept untagged traffic when
5134          * VLAN HW filtering is enabled.
5135          */
5136         if (MAC_GROUP_HW_VLAN(group) &&
5137             map->ma_type != MAC_ADDRESS_TYPE_UNICAST_PROMISC) {
5138                 if ((err = mac_group_addvlan(group, vid)) != 0)
5139                         goto bail;
5140 
5141                 hw_vlan = B_TRUE;
5142         }
5143 
5144         VERIFY3S(map->ma_nusers, >=, 0);
5145         map->ma_nusers++;
5146 
5147         /*
5148          * If this MAC address already has a HW filter then simply
5149          * increment the counter.
5150          */
5151         if (map->ma_nusers > 1)
5152                 return (0);
5153 
5154         /*
5155          * All logic from here on out is executed during initial
5156          * creation only.
5157          */
5158         VERIFY3S(map->ma_nusers, ==, 1);
5159 
5160         /*
5161          * Activate this MAC address by adding it to the reserved group.
5162          */
5163         if (group != NULL) {
5164                 err = mac_group_addmac(group, (const uint8_t *)addr);
5165 
5166                 /*
5167                  * If the driver is out of filters then we can
5168                  * continue and use promisc mode. For any other error,
5169                  * assume the driver is in a state where we can't
5170                  * program the filters or use promisc mode; so we must
5171                  * bail.
5172                  */
5173                 if (err != 0 && err != ENOSPC) {
5174                         map->ma_nusers--;
5175                         goto bail;
5176                 }
5177 
5178                 hw_mac = (err == 0);
5179         }
5180 
5181         if (hw_mac) {
5182                 map->ma_type = MAC_ADDRESS_TYPE_UNICAST_CLASSIFIED;
5183                 return (0);
5184         }

5185 
5186         /*
5187          * The MAC address addition failed. If the client requires a
5188          * hardware classified MAC address, fail the operation. This
5189          * feature is only used by sun4v vsw.
5190          */
5191         if (use_hw && !hw_mac) {
5192                 err = ENOSPC;
5193                 map->ma_nusers--;
5194                 goto bail;
5195         }
5196 
5197         /*
5198          * If we reach this point then either the MAC doesn't have
5199          * RINGS capability or we are out of MAC address HW filters.
5200          * In any case we must put the MAC into promiscuous mode.

5201          */
5202         VERIFY(group == NULL || !hw_mac);
5203 
5204         /*
5205          * The one exception is the primary address. A non-RINGS
5206          * driver filters the primary address by default; promisc mode
5207          * is not needed.
5208          */
5209         if ((group == NULL) &&
5210             (bcmp(map->ma_addr, mip->mi_addr, map->ma_len) == 0)) {
5211                 map->ma_type = MAC_ADDRESS_TYPE_UNICAST_CLASSIFIED;
5212                 return (0);
5213         }
5214 
5215         /*
5216          * Enable promiscuous mode in order to receive traffic to the
5217          * new MAC address. All existing HW filters still send their
5218          * traffic to their respective group/SRSes. But with promisc
5219          * enabled all unknown traffic is delivered to the default
5220          * group where it is SW classified via mac_rx_classify().
5221          */
5222         if ((err = i_mac_promisc_set(mip, B_TRUE)) == 0) {
5223                 map->ma_type = MAC_ADDRESS_TYPE_UNICAST_PROMISC;
5224                 return (0);
5225         }
5226 






5227 bail:
5228         if (hw_vlan) {
5229                 int err2 = mac_group_remvlan(group, vid);
5230 
5231                 if (err2 != 0) {
5232                         cmn_err(CE_WARN, "Failed to remove VLAN %u from group"
5233                             " %d on MAC %s: %d.", vid, group->mrg_index,
5234                             mip->mi_name, err2);
5235                 }
5236         }
5237 
5238         if (mvp != NULL)
5239                 mac_rem_vlan(map, mvp);
5240 
5241         if (allocated_map)
5242                 mac_free_macaddr(map);
5243 
5244         return (err);
5245 }
5246 





5247 int
5248 mac_remove_macaddr_vlan(mac_address_t *map, uint16_t vid)
5249 {
5250         mac_vlan_t      *mvp;
5251         mac_impl_t      *mip = map->ma_mip;
5252         mac_group_t     *group = map->ma_group;
5253         int             err = 0;
5254 
5255         ASSERT(MAC_PERIM_HELD((mac_handle_t)mip));
5256         VERIFY3P(map, ==, mac_find_macaddr(mip, map->ma_addr));
5257 
5258         if (vid == VLAN_ID_NONE) {
5259                 map->ma_untagged = B_FALSE;
5260                 mvp = NULL;
5261         } else {
5262                 mvp = mac_find_vlan(map, vid);
5263                 VERIFY3P(mvp, !=, NULL);
5264         }
5265 
5266         if (MAC_GROUP_HW_VLAN(group) &&
5267             map->ma_type == MAC_ADDRESS_TYPE_UNICAST_CLASSIFIED &&
5268             ((err = mac_group_remvlan(group, vid)) != 0))
5269                 return (err);
5270 
5271         if (mvp != NULL)
5272                 mac_rem_vlan(map, mvp);
5273 
5274         /*
5275          * If it's not the last client using this MAC address, only update
5276          * the MAC clients count.
5277          */
5278         map->ma_nusers--;
5279         if (map->ma_nusers > 0)
5280                 return (0);
5281 
5282         /*
5283          * The MAC address is no longer used by any MAC client, so
5284          * remove it from its associated group. Turn off promiscuous
5285          * mode if this is the last address relying on it.
5286          */
5287         switch (map->ma_type) {
5288         case MAC_ADDRESS_TYPE_UNICAST_CLASSIFIED:
5289                 /*
5290                  * Don't free the preset primary address for drivers that
5291                  * don't advertise RINGS capability.
5292                  */
5293                 if (group == NULL)
5294                         return (0);
5295 
5296                 if ((err = mac_group_remmac(group, map->ma_addr)) != 0) {
5297                         if (vid == VLAN_ID_NONE)
5298                                 map->ma_untagged = B_TRUE;
5299                         else
5300                                 (void) mac_add_vlan(map, vid);
5301 
5302                         /*
5303                          * If we fail to remove the MAC address HW
5304                          * filter but then also fail to re-add the
5305                          * VLAN HW filter then we are in a busted
5306                          * state and should just crash.
5307                          */
5308                         if (MAC_GROUP_HW_VLAN(group)) {
5309                                 int err2;
5310 
5311                                 err2 = mac_group_addvlan(group, vid);
5312                                 if (err2 != 0) {
5313                                         cmn_err(CE_WARN, "Failed to readd VLAN"
5314                                             " %u to group %d on MAC %s: %d.",
5315                                             vid, group->mrg_index, mip->mi_name,
5316                                             err2);
5317                                 }
5318                         }
5319 
5320                         return (err);
5321                 }
5322 
5323                 map->ma_group = NULL;
5324                 break;
5325         case MAC_ADDRESS_TYPE_UNICAST_PROMISC:
5326                 err = i_mac_promisc_set(mip, B_FALSE);
5327                 break;
5328         default:
5329                 panic("Unexpected ma_type 0x%x, file: %s, line %d",
5330                     map->ma_type, __FILE__, __LINE__);
5331         }
5332 
5333         if (err != 0)
5334                 return (err);
5335 
5336         /*
5337          * We created MAC address for the primary one at registration, so we
5338          * won't free it here. mac_fini_macaddr() will take care of it.
5339          */
5340         if (bcmp(map->ma_addr, mip->mi_addr, map->ma_len) != 0)
5341                 mac_free_macaddr(map);
5342 
5343         return (0);
5344 }
5345 
5346 /*
5347  * Update an existing MAC address. The caller need to make sure that the new
5348  * value has not been used.
5349  */
5350 int


5467 
5468         mip->mi_addresses = map;
5469 }
5470 
5471 /*
5472  * Clean up the primary MAC address. Note, only one primary MAC address
5473  * is allowed. All other MAC addresses must have been freed appropriately.
5474  */
5475 void
5476 mac_fini_macaddr(mac_impl_t *mip)
5477 {
5478         mac_address_t *map = mip->mi_addresses;
5479 
5480         if (map == NULL)
5481                 return;
5482 
5483         /*
5484          * If mi_addresses is initialized, there should be exactly one
5485          * entry left on the list with no users.
5486          */
5487         VERIFY3S(map->ma_nusers, ==, 0);
5488         VERIFY3P(map->ma_next, ==, NULL);
5489         VERIFY3P(map->ma_vlans, ==, NULL);
5490 
5491         kmem_free(map, sizeof (mac_address_t));
5492         mip->mi_addresses = NULL;
5493 }
5494 
5495 /*
5496  * Logging related functions.
5497  *
5498  * Note that Kernel statistics have been extended to maintain fine
5499  * granularity of statistics viz. hardware lane, software lane, fanout
5500  * stats etc. However, extended accounting continues to support only
5501  * aggregate statistics like before.
5502  */
5503 
5504 /* Write the flow description to a netinfo_t record */
5505 static netinfo_t *
5506 mac_write_flow_desc(flow_entry_t *flent, mac_client_impl_t *mcip)
5507 {
5508         netinfo_t               *ninfo;
5509         net_desc_t              *ndesc;


6031                         mac_flow_log_enable = B_FALSE;
6032                         mac_link_log_enable = B_FALSE;
6033                         break;
6034                 }
6035                 /* FALLTHRU */
6036         case MAC_LOGTYPE_LINK:
6037                 if (!lstate.mi_lenable || mac_flow_log_enable) {
6038                         rw_exit(&i_mac_impl_lock);
6039                         return;
6040                 }
6041                 mac_link_log_enable = B_FALSE;
6042                 break;
6043         default:
6044                 ASSERT(0);
6045         }
6046 
6047         /* Reenable fastpath */
6048         mod_hash_walk(i_mac_impl_hash, i_mac_fastpath_walker, &estate);
6049 
6050         (void) untimeout(mac_logging_timer);
6051         mac_logging_timer = NULL;
6052 
6053         /* Write log entries for each mac_impl in the list */
6054         i_mac_log_info(&net_log_list, &lstate);
6055 }
6056 
6057 /*
6058  * Walk the rx and tx SRS/SRs for a flow and update the priority value.
6059  */
6060 void
6061 mac_flow_update_priority(mac_client_impl_t *mcip, flow_entry_t *flent)
6062 {
6063         pri_t                   pri;
6064         int                     count;
6065         mac_soft_ring_set_t     *mac_srs;
6066 
6067         if (flent->fe_rx_srs_cnt <= 0)
6068                 return;
6069 
6070         if (((mac_soft_ring_set_t *)flent->fe_rx_srs[0])->srs_type ==
6071             SRST_FLOW) {


6149         }
6150         /*
6151          * There are clients using this ring, so let's move the clients
6152          * away from using this ring.
6153          */
6154         for (mgcp = group->mrg_clients; mgcp != NULL; mgcp = mgcp->mgc_next) {
6155                 mcip = mgcp->mgc_client;
6156                 mac_tx_client_quiesce((mac_client_handle_t)mcip);
6157                 srs = MCIP_TX_SRS(mcip);
6158                 ASSERT(mac_tx_srs_ring_present(srs, desired_ring));
6159                 mac_tx_invoke_callbacks(mcip,
6160                     (mac_tx_cookie_t)mac_tx_srs_get_soft_ring(srs,
6161                     desired_ring));
6162                 mac_tx_srs_del_ring(srs, desired_ring);
6163                 mac_tx_client_restart((mac_client_handle_t)mcip);
6164         }
6165         return (desired_ring);
6166 }
6167 
6168 /*
6169  * For a non-default group with multiple clients, return the primary client.
6170  */
6171 static mac_client_impl_t *
6172 mac_get_grp_primary(mac_group_t *grp)
6173 {
6174         mac_grp_client_t        *mgcp = grp->mrg_clients;
6175         mac_client_impl_t       *mcip;
6176 
6177         while (mgcp != NULL) {
6178                 mcip = mgcp->mgc_client;
6179                 if (mcip->mci_flent->fe_type & FLOW_PRIMARY_MAC)
6180                         return (mcip);
6181                 mgcp = mgcp->mgc_next;
6182         }
6183         return (NULL);
6184 }
6185 
6186 /*
6187  * Hybrid I/O specifies the ring that should be given to a share.
6188  * If the ring is already used by clients, then we need to release
6189  * the ring back to the default group so that we can give it to


6508         if (share != 0)
6509                 mip->mi_share_capab.ms_sadd(share, new_group->mrg_driver);
6510 
6511 bail:
6512         /* free temporary array of rings */
6513         kmem_free(rings, nrings * sizeof (mac_ring_handle_t));
6514 
6515         return (rv);
6516 }
6517 
6518 void
6519 mac_group_add_client(mac_group_t *grp, mac_client_impl_t *mcip)
6520 {
6521         mac_grp_client_t *mgcp;
6522 
6523         for (mgcp = grp->mrg_clients; mgcp != NULL; mgcp = mgcp->mgc_next) {
6524                 if (mgcp->mgc_client == mcip)
6525                         break;
6526         }
6527 
6528         ASSERT(mgcp == NULL);
6529 
6530         mgcp = kmem_zalloc(sizeof (mac_grp_client_t), KM_SLEEP);
6531         mgcp->mgc_client = mcip;
6532         mgcp->mgc_next = grp->mrg_clients;
6533         grp->mrg_clients = mgcp;

6534 }
6535 
6536 void
6537 mac_group_remove_client(mac_group_t *grp, mac_client_impl_t *mcip)
6538 {
6539         mac_grp_client_t *mgcp, **pprev;
6540 
6541         for (pprev = &grp->mrg_clients, mgcp = *pprev; mgcp != NULL;
6542             pprev = &mgcp->mgc_next, mgcp = *pprev) {
6543                 if (mgcp->mgc_client == mcip)
6544                         break;
6545         }
6546 
6547         ASSERT(mgcp != NULL);
6548 
6549         *pprev = mgcp->mgc_next;
6550         kmem_free(mgcp, sizeof (mac_grp_client_t));
6551 }
6552 
6553 /*
6554  * Return true if any client on this group explicitly asked for HW
6555  * rings (of type mask) or have a bound share.
6556  */
6557 static boolean_t
6558 i_mac_clients_hw(mac_group_t *grp, uint32_t mask)
6559 {
6560         mac_grp_client_t        *mgcip;
6561         mac_client_impl_t       *mcip;
6562         mac_resource_props_t    *mrp;
6563 
6564         for (mgcip = grp->mrg_clients; mgcip != NULL; mgcip = mgcip->mgc_next) {
6565                 mcip = mgcip->mgc_client;
6566                 mrp = MCIP_RESOURCE_PROPS(mcip);
6567                 if (mcip->mci_share != 0 || (mrp->mrp_mask & mask) != 0)
6568                         return (B_TRUE);
6569         }
6570 
6571         return (B_FALSE);
6572 }
6573 
6574 /*
6575  * Finds an available group and exclusively reserves it for a client.
6576  * The group is chosen to suit the flow's resource controls (bandwidth and
6577  * fanout requirements) and the address type.
6578  * If the requestor is the pimary MAC then return the group with the
6579  * largest number of rings, otherwise the default ring when available.
6580  */
6581 mac_group_t *
6582 mac_reserve_rx_group(mac_client_impl_t *mcip, uint8_t *mac_addr, boolean_t move)
6583 {
6584         mac_share_handle_t      share = mcip->mci_share;
6585         mac_impl_t              *mip = mcip->mci_mip;
6586         mac_group_t             *grp = NULL;
6587         int                     i;
6588         int                     err = 0;
6589         mac_address_t           *map;
6590         mac_resource_props_t    *mrp = MCIP_RESOURCE_PROPS(mcip);
6591         int                     nrings;
6592         int                     donor_grp_rcnt;
6593         boolean_t               need_exclgrp = B_FALSE;
6594         int                     need_rings = 0;
6595         mac_group_t             *candidate_grp = NULL;
6596         mac_client_impl_t       *gclient;

6597         mac_group_t             *donorgrp = NULL;
6598         boolean_t               rxhw = mrp->mrp_mask & MRP_RX_RINGS;
6599         boolean_t               unspec = mrp->mrp_mask & MRP_RXRINGS_UNSPEC;
6600         boolean_t               isprimary;
6601 
6602         ASSERT(MAC_PERIM_HELD((mac_handle_t)mip));
6603 
6604         isprimary = mcip->mci_flent->fe_type & FLOW_PRIMARY_MAC;
6605 
6606         /*
6607          * Check if a group already has this MAC address (case of VLANs)
6608          * unless we are moving this MAC client from one group to another.
6609          */
6610         if (!move && (map = mac_find_macaddr(mip, mac_addr)) != NULL) {
6611                 if (map->ma_group != NULL)
6612                         return (map->ma_group);
6613         }
6614 
6615         if (mip->mi_rx_groups == NULL || mip->mi_rx_group_count == 0)
6616                 return (NULL);
6617 
6618         /*
6619          * If this client is requesting exclusive MAC access then
6620          * return NULL to ensure the client uses the default group.
6621          */
6622         if (mcip->mci_state_flags & MCIS_EXCLUSIVE)
6623                 return (NULL);
6624 
6625         /* For dynamic groups default unspecified to 1 */
6626         if (rxhw && unspec &&
6627             mip->mi_rx_group_type == MAC_GROUP_TYPE_DYNAMIC) {
6628                 mrp->mrp_nrxrings = 1;
6629         }
6630 
6631         /*
6632          * For static grouping we allow only specifying rings=0 and
6633          * unspecified
6634          */
6635         if (rxhw && mrp->mrp_nrxrings > 0 &&
6636             mip->mi_rx_group_type == MAC_GROUP_TYPE_STATIC) {
6637                 return (NULL);
6638         }
6639 
6640         if (rxhw) {
6641                 /*
6642                  * We have explicitly asked for a group (with nrxrings,
6643                  * if unspec).
6644                  */
6645                 if (unspec || mrp->mrp_nrxrings > 0) {
6646                         need_exclgrp = B_TRUE;
6647                         need_rings = mrp->mrp_nrxrings;
6648                 } else if (mrp->mrp_nrxrings == 0) {
6649                         /*
6650                          * We have asked for a software group.
6651                          */
6652                         return (NULL);
6653                 }
6654         } else if (isprimary && mip->mi_nactiveclients == 1 &&
6655             mip->mi_rx_group_type == MAC_GROUP_TYPE_DYNAMIC) {
6656                 /*
6657                  * If the primary is the only active client on this
6658                  * mip and we have not asked for any rings, we give
6659                  * it the default group so that the primary gets to


6681          * For flows requiring HW_RING (unicast flow of other clients), try
6682          * to reserve non-default RX group with the specified number of
6683          * rings, if available.
6684          *
6685          * For flows that have not asked for software or hardware ring,
6686          * try to reserve a non-default group with 1 ring, if available.
6687          */
6688         for (i = 1; i < mip->mi_rx_group_count; i++) {
6689                 grp = &mip->mi_rx_groups[i];
6690 
6691                 DTRACE_PROBE3(rx__group__trying, char *, mip->mi_name,
6692                     int, grp->mrg_index, mac_group_state_t, grp->mrg_state);
6693 
6694                 /*
6695                  * Check if this group could be a candidate group for
6696                  * eviction if we need a group for this MAC client,
6697                  * but there aren't any. A candidate group is one
6698                  * that didn't ask for an exclusive group, but got
6699                  * one and it has enough rings (combined with what
6700                  * the donor group can donate) for the new MAC
6701                  * client.
6702                  */
6703                 if (grp->mrg_state >= MAC_GROUP_STATE_RESERVED) {
6704                         /*
6705                          * If the donor group is not the default
6706                          * group, don't bother looking for a candidate
6707                          * group. If we don't have enough rings we
6708                          * will check if the primary group can be
6709                          * vacated.
6710                          */
6711                         if (candidate_grp == NULL &&
6712                             donorgrp == MAC_DEFAULT_RX_GROUP(mip)) {
6713                                 if (!i_mac_clients_hw(grp, MRP_RX_RINGS) &&







6714                                     (unspec ||
6715                                     (grp->mrg_cur_count + donor_grp_rcnt >=
6716                                     need_rings))) {
6717                                         candidate_grp = grp;
6718                                 }
6719                         }
6720                         continue;
6721                 }
6722                 /*
6723                  * This group could already be SHARED by other multicast
6724                  * flows on this client. In that case, the group would
6725                  * be shared and has already been started.
6726                  */
6727                 ASSERT(grp->mrg_state != MAC_GROUP_STATE_UNINIT);
6728 
6729                 if ((grp->mrg_state == MAC_GROUP_STATE_REGISTERED) &&
6730                     (mac_start_group(grp) != 0)) {
6731                         continue;
6732                 }
6733 


6759                                 if (share != 0) {
6760                                         mac_client_set_rings(
6761                                             (mac_client_handle_t)mcip,
6762                                             grp->mrg_cur_count, -1);
6763                                 }
6764                                 if (mac_is_primary_client(mcip) && !rxhw)
6765                                         mip->mi_rx_donor_grp = grp;
6766                                 break;
6767                         }
6768                 }
6769 
6770                 DTRACE_PROBE3(rx__group__reserve__alloc__rings, char *,
6771                     mip->mi_name, int, grp->mrg_index, int, err);
6772 
6773                 /*
6774                  * It's a dynamic group but the grouping operation
6775                  * failed.
6776                  */
6777                 mac_stop_group(grp);
6778         }
6779 
6780         /* We didn't find an exclusive group for this MAC client */
6781         if (i >= mip->mi_rx_group_count) {
6782 
6783                 if (!need_exclgrp)
6784                         return (NULL);
6785 
6786                 /*
6787                  * If we found a candidate group then move the
6788                  * existing MAC client from the candidate_group to the
6789                  * default group and give the candidate_group to the
6790                  * new MAC client. If we didn't find a candidate
6791                  * group, then check if the primary is in its own
6792                  * group and if it can make way for this MAC client.
6793                  */
6794                 if (candidate_grp == NULL &&
6795                     donorgrp != MAC_DEFAULT_RX_GROUP(mip) &&
6796                     donorgrp->mrg_cur_count >= need_rings) {
6797                         candidate_grp = donorgrp;
6798                 }
6799                 if (candidate_grp != NULL) {
6800                         boolean_t       prim_grp = B_FALSE;
6801 
6802                         /*
6803                          * Switch the existing MAC client from the
6804                          * candidate group to the default group. If
6805                          * the candidate group is the donor group,
6806                          * then after the switch we need to update the
6807                          * donor group too.
6808                          */
6809                         grp = candidate_grp;
6810                         gclient = grp->mrg_clients->mgc_client;
6811                         VERIFY3P(gclient, !=, NULL);

6812                         if (grp == mip->mi_rx_donor_grp)
6813                                 prim_grp = B_TRUE;
6814                         if (mac_rx_switch_group(gclient, grp,
6815                             MAC_DEFAULT_RX_GROUP(mip)) != 0) {
6816                                 return (NULL);
6817                         }
6818                         if (prim_grp) {
6819                                 mip->mi_rx_donor_grp =
6820                                     MAC_DEFAULT_RX_GROUP(mip);
6821                                 donorgrp = MAC_DEFAULT_RX_GROUP(mip);
6822                         }
6823 

6824                         /*
6825                          * Now give this group with the required rings
6826                          * to this MAC client.
6827                          */
6828                         ASSERT(grp->mrg_state == MAC_GROUP_STATE_REGISTERED);
6829                         if (mac_start_group(grp) != 0)
6830                                 return (NULL);
6831 
6832                         if (mip->mi_rx_group_type != MAC_GROUP_TYPE_DYNAMIC)
6833                                 return (grp);
6834 
6835                         donor_grp_rcnt = donorgrp->mrg_cur_count - 1;
6836                         ASSERT(grp->mrg_cur_count == 0);
6837                         ASSERT(donor_grp_rcnt >= need_rings);
6838                         err = i_mac_group_allocate_rings(mip, MAC_RING_TYPE_RX,
6839                             donorgrp, grp, share, need_rings);
6840                         if (err == 0) {
6841                                 /*
6842                                  * For a share i_mac_group_allocate_rings gets
6843                                  * the rings from the driver, let's populate


6851                                 DTRACE_PROBE2(rx__group__reserved,
6852                                     char *, mip->mi_name, int, grp->mrg_index);
6853                                 return (grp);
6854                         }
6855                         DTRACE_PROBE3(rx__group__reserve__alloc__rings, char *,
6856                             mip->mi_name, int, grp->mrg_index, int, err);
6857                         mac_stop_group(grp);
6858                 }
6859                 return (NULL);
6860         }
6861         ASSERT(grp != NULL);
6862 
6863         DTRACE_PROBE2(rx__group__reserved,
6864             char *, mip->mi_name, int, grp->mrg_index);
6865         return (grp);
6866 }
6867 
6868 /*
6869  * mac_rx_release_group()
6870  *
6871  * Release the group when it has no remaining clients. The group is
6872  * stopped and its shares are removed and all rings are assigned back
6873  * to default group. This should never be called against the default
6874  * group.
6875  */
6876 void
6877 mac_release_rx_group(mac_client_impl_t *mcip, mac_group_t *group)
6878 {
6879         mac_impl_t              *mip = mcip->mci_mip;
6880         mac_ring_t              *ring;
6881 
6882         ASSERT(group != MAC_DEFAULT_RX_GROUP(mip));
6883         ASSERT(MAC_GROUP_NO_CLIENT(group) == B_TRUE);
6884 
6885         if (mip->mi_rx_donor_grp == group)
6886                 mip->mi_rx_donor_grp = MAC_DEFAULT_RX_GROUP(mip);
6887 
6888         /*
6889          * This is the case where there are no clients left. Any
6890          * SRS etc on this group have also be quiesced.
6891          */
6892         for (ring = group->mrg_rings; ring != NULL; ring = ring->mr_next) {
6893                 if (ring->mr_classify_type == MAC_HW_CLASSIFIER) {
6894                         ASSERT(group->mrg_state == MAC_GROUP_STATE_RESERVED);
6895                         /*
6896                          * Remove the SRS associated with the HW ring.
6897                          * As a result, polling will be disabled.
6898                          */
6899                         ring->mr_srs = NULL;
6900                 }
6901                 ASSERT(group->mrg_state < MAC_GROUP_STATE_RESERVED ||
6902                     ring->mr_state == MR_INUSE);
6903                 if (ring->mr_state == MR_INUSE) {


6915         if (mip->mi_rx_group_type == MAC_GROUP_TYPE_DYNAMIC) {
6916                 mac_ring_t *ring;
6917 
6918                 /*
6919                  * Rings were dynamically allocated to group.
6920                  * Move rings back to default group.
6921                  */
6922                 while ((ring = group->mrg_rings) != NULL) {
6923                         (void) mac_group_mov_ring(mip, mip->mi_rx_donor_grp,
6924                             ring);
6925                 }
6926         }
6927         mac_stop_group(group);
6928         /*
6929          * Possible improvement: See if we can assign the group just released
6930          * to a another client of the mip
6931          */
6932 }
6933 
6934 /*
6935  * Move the MAC address from fgrp to tgrp.








6936  */









































6937 static int
6938 mac_rx_move_macaddr(mac_client_impl_t *mcip, mac_group_t *fgrp,
6939     mac_group_t *tgrp)
6940 {
6941         mac_impl_t              *mip = mcip->mci_mip;
6942         uint8_t                 maddr[MAXMACADDRLEN];
6943         int                     err = 0;
6944         uint16_t                vid;
6945         mac_unicast_impl_t      *muip;
6946         boolean_t               use_hw;
6947 
6948         mac_rx_client_quiesce((mac_client_handle_t)mcip);
6949         VERIFY3P(mcip->mci_unicast, !=, NULL);
6950         bcopy(mcip->mci_unicast->ma_addr, maddr, mcip->mci_unicast->ma_len);
6951 
6952         /*
6953          * Does the client require MAC address hardware classifiction?
6954          */
6955         use_hw = (mcip->mci_state_flags & MCIS_UNICAST_HW) != 0;
6956         vid = i_mac_flow_vid(mcip->mci_flent);
6957 
6958         /*
6959          * You can never move an address that is shared by multiple
6960          * clients. mac_datapath_setup() ensures that clients sharing
6961          * an address are placed on the default group. This guarantees
6962          * that a non-default group will only ever have one client and
6963          * thus make full use of HW filters.
6964          */
6965         if (mac_check_macaddr_shared(mcip->mci_unicast))
6966                 return (EINVAL);
6967 
6968         err = mac_remove_macaddr_vlan(mcip->mci_unicast, vid);
6969 
6970         if (err != 0) {
6971                 mac_rx_client_restart((mac_client_handle_t)mcip);




6972                 return (err);
6973         }
6974 
6975         /*
6976          * If this isn't the primary MAC address then the
6977          * mac_address_t has been freed by the last call to
6978          * mac_remove_macaddr_vlan(). In any case, NULL the reference
6979          * to avoid a dangling pointer.
6980          */
6981         mcip->mci_unicast = NULL;
6982 

6983         /*
6984          * We also have to NULL all the mui_map references -- sun4v
6985          * strikes again!
6986          */
6987         rw_enter(&mcip->mci_rw_lock, RW_WRITER);
6988         for (muip = mcip->mci_unicast_list; muip != NULL; muip = muip->mui_next)
6989                 muip->mui_map = NULL;
6990         rw_exit(&mcip->mci_rw_lock);
6991 
6992         /*
6993          * Program the H/W Classifier first, if this fails we need not
6994          * proceed with the other stuff.
6995          */
6996         if ((err = mac_add_macaddr_vlan(mip, tgrp, maddr, vid, use_hw)) != 0) {
6997                 int err2;
6998 
6999                 /* Revert back the H/W Classifier */
7000                 err2 = mac_add_macaddr_vlan(mip, fgrp, maddr, vid, use_hw);
7001 
7002                 if (err2 != 0) {
7003                         cmn_err(CE_WARN, "Failed to revert HW classification"
7004                             " on MAC %s, for client %s: %d.", mip->mi_name,
7005                             mcip->mci_name, err2);
7006                 }
7007 
7008                 mac_rx_client_restart((mac_client_handle_t)mcip);




7009                 return (err);
7010         }
7011 
7012         /*
7013          * Get a reference to the new mac_address_t and update the
7014          * client's reference. Then restart the client and add the
7015          * other clients of this MAC addr (if they exsit).
7016          */
7017         mcip->mci_unicast = mac_find_macaddr(mip, maddr);
7018         rw_enter(&mcip->mci_rw_lock, RW_WRITER);
7019         for (muip = mcip->mci_unicast_list; muip != NULL; muip = muip->mui_next)
7020                 muip->mui_map = mcip->mci_unicast;
7021         rw_exit(&mcip->mci_rw_lock);
7022         mac_rx_client_restart((mac_client_handle_t)mcip);
7023         return (0);


7024 }
7025 
7026 /*
7027  * Switch the MAC client from one group to another. This means we need
7028  * to remove the MAC address from the group, remove the MAC client,
7029  * teardown the SRSs and revert the group state. Then, we add the client
7030  * to the destination group, set the SRSs, and add the MAC address to the
7031  * group.
7032  */
7033 int
7034 mac_rx_switch_group(mac_client_impl_t *mcip, mac_group_t *fgrp,
7035     mac_group_t *tgrp)
7036 {
7037         int                     err;
7038         mac_group_state_t       next_state;
7039         mac_client_impl_t       *group_only_mcip;
7040         mac_client_impl_t       *gmcip;
7041         mac_impl_t              *mip = mcip->mci_mip;
7042         mac_grp_client_t        *mgcp;
7043 
7044         VERIFY3P(fgrp, ==, mcip->mci_flent->fe_rx_ring_group);
7045 
7046         if ((err = mac_rx_move_macaddr(mcip, fgrp, tgrp)) != 0)
7047                 return (err);
7048 
7049         /*
7050          * If the group is marked as reserved and in use by a single
7051          * client, then there is an SRS to teardown.
7052          */
7053         if (fgrp->mrg_state == MAC_GROUP_STATE_RESERVED &&
7054             MAC_GROUP_ONLY_CLIENT(fgrp) != NULL) {
7055                 mac_rx_srs_group_teardown(mcip->mci_flent, B_TRUE);
7056         }
7057 
7058         /*
7059          * If we are moving the client from a non-default group, then
7060          * we know that any additional clients on this group share the
7061          * same MAC address. Since we moved the MAC address filter, we
7062          * need to move these clients too.
7063          *
7064          * If we are moving the client from the default group and its
7065          * MAC address has VLAN clients, then we must move those
7066          * clients as well.
7067          *
7068          * In both cases the idea is the same: we moved the MAC
7069          * address filter to the tgrp, so we must move all clients
7070          * using that MAC address to tgrp as well.
7071          */
7072         if (fgrp != MAC_DEFAULT_RX_GROUP(mip)) {
7073                 mgcp = fgrp->mrg_clients;
7074                 while (mgcp != NULL) {
7075                         gmcip = mgcp->mgc_client;
7076                         mgcp = mgcp->mgc_next;
7077                         mac_group_remove_client(fgrp, gmcip);
7078                         mac_group_add_client(tgrp, gmcip);
7079                         gmcip->mci_flent->fe_rx_ring_group = tgrp;
7080                 }
7081                 mac_release_rx_group(mcip, fgrp);
7082                 VERIFY3B(MAC_GROUP_NO_CLIENT(fgrp), ==, B_TRUE);
7083                 mac_set_group_state(fgrp, MAC_GROUP_STATE_REGISTERED);
7084         } else {
7085                 mac_group_remove_client(fgrp, mcip);
7086                 mac_group_add_client(tgrp, mcip);
7087                 mcip->mci_flent->fe_rx_ring_group = tgrp;
7088 
7089                 /*
7090                  * If there are other clients (VLANs) sharing this address
7091                  * then move them too.
7092                  */
7093                 if (mac_check_macaddr_shared(mcip->mci_unicast)) {
7094                         /*
7095                          * We need to move all the clients that are using
7096                          * this MAC address.
7097                          */
7098                         mgcp = fgrp->mrg_clients;
7099                         while (mgcp != NULL) {
7100                                 gmcip = mgcp->mgc_client;
7101                                 mgcp = mgcp->mgc_next;
7102                                 if (mcip->mci_unicast == gmcip->mci_unicast) {
7103                                         mac_group_remove_client(fgrp, gmcip);
7104                                         mac_group_add_client(tgrp, gmcip);
7105                                         gmcip->mci_flent->fe_rx_ring_group =
7106                                             tgrp;
7107                                 }
7108                         }
7109                 }
7110 
7111                 /*
7112                  * The default group still handles multicast and
7113                  * broadcast traffic; it won't transition to
7114                  * MAC_GROUP_STATE_REGISTERED.
7115                  */
7116                 if (fgrp->mrg_state == MAC_GROUP_STATE_RESERVED)
7117                         mac_rx_group_unmark(fgrp, MR_CONDEMNED);
7118                 mac_set_group_state(fgrp, MAC_GROUP_STATE_SHARED);
7119         }
7120 
7121         next_state = mac_group_next_state(tgrp, &group_only_mcip,
7122             MAC_DEFAULT_RX_GROUP(mip), B_TRUE);
7123         mac_set_group_state(tgrp, next_state);
7124 
7125         /*
7126          * If the destination group is reserved, then setup the SRSes.
7127          * Otherwise make sure to use SW classification.
7128          */
7129         if (tgrp->mrg_state == MAC_GROUP_STATE_RESERVED) {
7130                 mac_rx_srs_group_setup(mcip, mcip->mci_flent, SRST_LINK);
7131                 mac_fanout_setup(mcip, mcip->mci_flent,
7132                     MCIP_RESOURCE_PROPS(mcip), mac_rx_deliver, mcip, NULL,
7133                     NULL);
7134                 mac_rx_group_unmark(tgrp, MR_INCIPIENT);
7135         } else {
7136                 mac_rx_switch_grp_to_sw(tgrp);
7137         }
7138 
7139         return (0);
7140 }
7141 
7142 /*
7143  * Reserves a TX group for the specified share. Invoked by mac_tx_srs_setup()
7144  * when a share was allocated to the client.
7145  */
7146 mac_group_t *
7147 mac_reserve_tx_group(mac_client_impl_t *mcip, boolean_t move)
7148 {
7149         mac_impl_t              *mip = mcip->mci_mip;
7150         mac_group_t             *grp = NULL;
7151         int                     rv;
7152         int                     i;
7153         int                     err;
7154         mac_group_t             *defgrp;
7155         mac_share_handle_t      share = mcip->mci_share;
7156         mac_resource_props_t    *mrp = MCIP_RESOURCE_PROPS(mcip);
7157         int                     nrings;
7158         int                     defnrings;
7159         boolean_t               need_exclgrp = B_FALSE;
7160         int                     need_rings = 0;
7161         mac_group_t             *candidate_grp = NULL;
7162         mac_client_impl_t       *gclient;
7163         mac_resource_props_t    *gmrp;
7164         boolean_t               txhw = mrp->mrp_mask & MRP_TX_RINGS;
7165         boolean_t               unspec = mrp->mrp_mask & MRP_TXRINGS_UNSPEC;
7166         boolean_t               isprimary;
7167 
7168         isprimary = mcip->mci_flent->fe_type & FLOW_PRIMARY_MAC;
7169 
7170         /*
7171          * When we come here for a VLAN on the primary (dladm create-vlan),
7172          * we need to pair it along with the primary (to keep it consistent
7173          * with the RX side). So, we check if the primary is already assigned
7174          * to a group and return the group if so. The other way is also
7175          * true, i.e. the VLAN is already created and now we are plumbing
7176          * the primary.
7177          */
7178         if (!move && isprimary) {
7179                 for (gclient = mip->mi_clients_list; gclient != NULL;
7180                     gclient = gclient->mci_client_next) {
7181                         if (gclient->mci_flent->fe_type & FLOW_PRIMARY_MAC &&
7182                             gclient->mci_flent->fe_tx_ring_group != NULL) {
7183                                 return (gclient->mci_flent->fe_tx_ring_group);
7184                         }
7185                 }
7186         }
7187 
7188         if (mip->mi_tx_groups == NULL || mip->mi_tx_group_count == 0)
7189                 return (NULL);


7231          */
7232         if (isprimary && !need_exclgrp)
7233                 return (NULL);
7234 
7235         nrings = (mrp->mrp_mask & MRP_TX_RINGS) != 0 ? mrp->mrp_ntxrings : 1;
7236         for (i = 0; i <  mip->mi_tx_group_count; i++) {
7237                 grp = &mip->mi_tx_groups[i];
7238                 if ((grp->mrg_state == MAC_GROUP_STATE_RESERVED) ||
7239                     (grp->mrg_state == MAC_GROUP_STATE_UNINIT)) {
7240                         /*
7241                          * Select a candidate for replacement if we don't
7242                          * get an exclusive group. A candidate group is one
7243                          * that didn't ask for an exclusive group, but got
7244                          * one and it has enough rings (combined with what
7245                          * the default group can donate) for the new MAC
7246                          * client.
7247                          */
7248                         if (grp->mrg_state == MAC_GROUP_STATE_RESERVED &&
7249                             candidate_grp == NULL) {
7250                                 gclient = MAC_GROUP_ONLY_CLIENT(grp);
7251                                 VERIFY3P(gclient, !=, NULL);

7252                                 gmrp = MCIP_RESOURCE_PROPS(gclient);
7253                                 if (gclient->mci_share == 0 &&
7254                                     (gmrp->mrp_mask & MRP_TX_RINGS) == 0 &&
7255                                     (unspec ||
7256                                     (grp->mrg_cur_count + defnrings) >=
7257                                     need_rings)) {
7258                                         candidate_grp = grp;
7259                                 }
7260                         }
7261                         continue;
7262                 }
7263                 /*
7264                  * If the default can't donate let's just walk and
7265                  * see if someone can vacate a group, so that we have
7266                  * enough rings for this.
7267                  */
7268                 if (mip->mi_tx_group_type != MAC_GROUP_TYPE_DYNAMIC ||
7269                     nrings <= defnrings) {
7270                         if (grp->mrg_state == MAC_GROUP_STATE_REGISTERED) {
7271                                 rv = mac_start_group(grp);
7272                                 ASSERT(rv == 0);
7273                         }
7274                         break;
7275                 }
7276         }
7277 
7278         /* The default group */
7279         if (i >= mip->mi_tx_group_count) {
7280                 /*
7281                  * If we need an exclusive group and have identified a
7282                  * candidate group we switch the MAC client from the
7283                  * candidate group to the default group and give the
7284                  * candidate group to this client.
7285                  */
7286                 if (need_exclgrp && candidate_grp != NULL) {
7287                         /*
7288                          * Switch the MAC client from the candidate
7289                          * group to the default group. We know the
7290                          * candidate_grp came from a reserved group
7291                          * and thus only has one client.
7292                          */
7293                         grp = candidate_grp;
7294                         gclient = MAC_GROUP_ONLY_CLIENT(grp);
7295                         VERIFY3P(gclient, !=, NULL);

7296                         mac_tx_client_quiesce((mac_client_handle_t)gclient);
7297                         mac_tx_switch_group(gclient, grp, defgrp);
7298                         mac_tx_client_restart((mac_client_handle_t)gclient);
7299 
7300                         /*
7301                          * Give the candidate group with the specified number
7302                          * of rings to this MAC client.
7303                          */
7304                         ASSERT(grp->mrg_state == MAC_GROUP_STATE_REGISTERED);
7305                         rv = mac_start_group(grp);
7306                         ASSERT(rv == 0);
7307 
7308                         if (mip->mi_tx_group_type != MAC_GROUP_TYPE_DYNAMIC)
7309                                 return (grp);
7310 
7311                         ASSERT(grp->mrg_cur_count == 0);
7312                         ASSERT(defgrp->mrg_cur_count > need_rings);
7313 
7314                         err = i_mac_group_allocate_rings(mip, MAC_RING_TYPE_TX,
7315                             defgrp, grp, share, need_rings);


7443     mac_group_t *tgrp)
7444 {
7445         mac_client_impl_t       *group_only_mcip;
7446         mac_impl_t              *mip = mcip->mci_mip;
7447         flow_entry_t            *flent = mcip->mci_flent;
7448         mac_group_t             *defgrp;
7449         mac_grp_client_t        *mgcp;
7450         mac_client_impl_t       *gmcip;
7451         flow_entry_t            *gflent;
7452 
7453         defgrp = MAC_DEFAULT_TX_GROUP(mip);
7454         ASSERT(fgrp == flent->fe_tx_ring_group);
7455 
7456         if (fgrp == defgrp) {
7457                 /*
7458                  * If this is the primary we need to find any VLANs on
7459                  * the primary and move them too.
7460                  */
7461                 mac_group_remove_client(fgrp, mcip);
7462                 mac_tx_dismantle_soft_rings(fgrp, flent);
7463                 if (mac_check_macaddr_shared(mcip->mci_unicast)) {
7464                         mgcp = fgrp->mrg_clients;
7465                         while (mgcp != NULL) {
7466                                 gmcip = mgcp->mgc_client;
7467                                 mgcp = mgcp->mgc_next;
7468                                 if (mcip->mci_unicast != gmcip->mci_unicast)
7469                                         continue;
7470                                 mac_tx_client_quiesce(
7471                                     (mac_client_handle_t)gmcip);
7472 
7473                                 gflent = gmcip->mci_flent;
7474                                 mac_group_remove_client(fgrp, gmcip);
7475                                 mac_tx_dismantle_soft_rings(fgrp, gflent);
7476 
7477                                 mac_group_add_client(tgrp, gmcip);
7478                                 gflent->fe_tx_ring_group = tgrp;
7479                                 /* We could directly set this to SHARED */
7480                                 tgrp->mrg_state = mac_group_next_state(tgrp,
7481                                     &group_only_mcip, defgrp, B_FALSE);
7482 
7483                                 mac_tx_srs_group_setup(gmcip, gflent,


7689         mutex_exit(&mip->mi_bridge_lock);
7690         mac_poll_state_change(mh, B_TRUE);
7691         mac_capab_update(mh);
7692 }
7693 
7694 void
7695 mac_no_active(mac_handle_t mh)
7696 {
7697         mac_impl_t *mip = (mac_impl_t *)mh;
7698 
7699         i_mac_perim_enter(mip);
7700         mip->mi_state_flags |= MIS_NO_ACTIVE;
7701         i_mac_perim_exit(mip);
7702 }
7703 
7704 /*
7705  * Walk the primary VLAN clients whenever the primary's rings property
7706  * changes and update the mac_resource_props_t for the VLAN's client.
7707  * We need to do this since we don't support setting these properties
7708  * on the primary's VLAN clients, but the VLAN clients have to
7709  * follow the primary w.r.t the rings property.
7710  */
7711 void
7712 mac_set_prim_vlan_rings(mac_impl_t  *mip, mac_resource_props_t *mrp)
7713 {
7714         mac_client_impl_t       *vmcip;
7715         mac_resource_props_t    *vmrp;
7716 
7717         for (vmcip = mip->mi_clients_list; vmcip != NULL;
7718             vmcip = vmcip->mci_client_next) {
7719                 if (!(vmcip->mci_flent->fe_type & FLOW_PRIMARY_MAC) ||
7720                     mac_client_vid((mac_client_handle_t)vmcip) ==
7721                     VLAN_ID_NONE) {
7722                         continue;
7723                 }
7724                 vmrp = MCIP_RESOURCE_PROPS(vmcip);
7725 
7726                 vmrp->mrp_nrxrings =  mrp->mrp_nrxrings;
7727                 if (mrp->mrp_mask & MRP_RX_RINGS)
7728                         vmrp->mrp_mask |= MRP_RX_RINGS;
7729                 else if (vmrp->mrp_mask & MRP_RX_RINGS)


7838                 start = 1;
7839                 end = mip->mi_rx_group_count;
7840         } else {
7841                 start = 0;
7842                 end = mip->mi_tx_group_count - 1;
7843         }
7844         /*
7845          * If the default doesn't have any rings, lets see if we can
7846          * take rings given to an h/w client that doesn't need it.
7847          * For now, we just see if there is  any one client that can donate
7848          * all the required rings.
7849          */
7850         if (defgrp->mrg_cur_count < (modify + 1)) {
7851                 for (i = start; i < end; i++) {
7852                         if (rx_group) {
7853                                 tgrp = &mip->mi_rx_groups[i];
7854                                 if (tgrp == group || tgrp->mrg_state <
7855                                     MAC_GROUP_STATE_RESERVED) {
7856                                         continue;
7857                                 }
7858                                 if (i_mac_clients_hw(tgrp, MRP_RX_RINGS))





7859                                         continue;
7860                                 mcip = tgrp->mrg_clients->mgc_client;
7861                                 VERIFY3P(mcip, !=, NULL);
7862                                 if ((tgrp->mrg_cur_count +
7863                                     defgrp->mrg_cur_count) < (modify + 1)) {
7864                                         continue;
7865                                 }
7866                                 if (mac_rx_switch_group(mcip, tgrp,
7867                                     defgrp) != 0) {
7868                                         return (ENOSPC);
7869                                 }
7870                         } else {
7871                                 tgrp = &mip->mi_tx_groups[i];
7872                                 if (tgrp == group || tgrp->mrg_state <
7873                                     MAC_GROUP_STATE_RESERVED) {
7874                                         continue;
7875                                 }
7876                                 if (i_mac_clients_hw(tgrp, MRP_TX_RINGS))




7877                                         continue;
7878                                 mcip = tgrp->mrg_clients->mgc_client;
7879                                 VERIFY3P(mcip, !=, NULL);
7880                                 if ((tgrp->mrg_cur_count +
7881                                     defgrp->mrg_cur_count) < (modify + 1)) {
7882                                         continue;
7883                                 }
7884                                 /* OK, we can switch this to s/w */
7885                                 mac_tx_client_quiesce(
7886                                     (mac_client_handle_t)mcip);
7887                                 mac_tx_switch_group(mcip, tgrp, defgrp);
7888                                 mac_tx_client_restart(
7889                                     (mac_client_handle_t)mcip);
7890                         }
7891                 }
7892                 if (defgrp->mrg_cur_count < (modify + 1))
7893                         return (ENOSPC);
7894         }
7895         if ((rv = i_mac_group_allocate_rings(mip, group->mrg_type, defgrp,
7896             group, mcip->mci_share, modify)) != 0) {
7897                 return (rv);
7898         }
7899         return (0);


8132 
8133         default:
8134                 kmem_free(mpa, sizeof (struct mac_pool_arg));
8135                 pool_unlock();
8136                 return;
8137         }
8138         pool_unlock();
8139 
8140         mpa->mpa_what = what;
8141 
8142         mac_pool_update(mpa);
8143 }
8144 
8145 /*
8146  * Set effective rings property. This could be called from datapath_setup/
8147  * datapath_teardown or set-linkprop.
8148  * If the group is reserved we just go ahead and set the effective rings.
8149  * Additionally, for TX this could mean the default group has lost/gained
8150  * some rings, so if the default group is reserved, we need to adjust the
8151  * effective rings for the default group clients. For RX, if we are working
8152  * with the non-default group, we just need to reset the effective props
8153  * for the default group clients.
8154  */
8155 void
8156 mac_set_rings_effective(mac_client_impl_t *mcip)
8157 {
8158         mac_impl_t              *mip = mcip->mci_mip;
8159         mac_group_t             *grp;
8160         mac_group_t             *defgrp;
8161         flow_entry_t            *flent = mcip->mci_flent;
8162         mac_resource_props_t    *emrp = MCIP_EFFECTIVE_PROPS(mcip);
8163         mac_grp_client_t        *mgcp;
8164         mac_client_impl_t       *gmcip;
8165 
8166         grp = flent->fe_rx_ring_group;
8167         if (grp != NULL) {
8168                 defgrp = MAC_DEFAULT_RX_GROUP(mip);
8169                 /*
8170                  * If we have reserved a group, set the effective rings
8171                  * to the ring count in the group.
8172                  */


8262          * Check if the primary is in the default group, if not
8263          * or if it is explicitly configured to be in the default
8264          * group OR set the RX rings property, return.
8265          */
8266         if (flent->fe_rx_ring_group != defgrp || mrp->mrp_mask & MRP_RX_RINGS)
8267                 return (NULL);
8268 
8269         /*
8270          * If the new client needs an exclusive group and we
8271          * don't have another for the primary, return.
8272          */
8273         if (rxhw && mip->mi_rxhwclnt_avail < 2)
8274                 return (NULL);
8275 
8276         mac_addr = flent->fe_flow_desc.fd_dst_mac;
8277         /*
8278          * We call this when we are setting up the datapath for
8279          * the first non-primary.
8280          */
8281         ASSERT(mip->mi_nactiveclients == 2);
8282 
8283         /*
8284          * OK, now we have the primary that needs to be relocated.
8285          */
8286         ngrp =  mac_reserve_rx_group(mcip, mac_addr, B_TRUE);
8287         if (ngrp == NULL)
8288                 return (NULL);
8289         if (mac_rx_switch_group(mcip, defgrp, ngrp) != 0) {
8290                 mac_stop_group(ngrp);
8291                 return (NULL);
8292         }
8293         return (mcip);
8294 }
8295 
8296 void
8297 mac_transceiver_init(mac_impl_t *mip)
8298 {
8299         if (mac_capab_get((mac_handle_t)mip, MAC_CAPAB_TRANSCEIVER,
8300             &mip->mi_transceiver)) {
8301                 /*
8302                  * The driver set a flag that we don't know about. In this case,