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>

Split Close
Expand all
Collapse all
          --- old/usr/src/uts/common/io/mac/mac.c
          +++ new/usr/src/uts/common/io/mac/mac.c
↓ open down ↓ 452 lines elided ↑ open up ↑
 453  453           */
 454  454          minor_ids = id_space_create("mac_minor_ids", MAC_MAX_MINOR+1,
 455  455              MAC_PRIVATE_MINOR-1);
 456  456          ASSERT(minor_ids != NULL);
 457  457          minor_count = 0;
 458  458  
 459  459          /* Let's default to 20 seconds */
 460  460          mac_logging_interval = 20;
 461  461          mac_flow_log_enable = B_FALSE;
 462  462          mac_link_log_enable = B_FALSE;
 463      -        mac_logging_timer = 0;
      463 +        mac_logging_timer = NULL;
 464  464  
 465  465          /* Register to be notified of noteworthy pools events */
 466  466          mac_pool_event_reg.pec_func =  mac_pool_event_cb;
 467  467          mac_pool_event_reg.pec_arg = NULL;
 468  468          pool_event_cb_register(&mac_pool_event_reg);
 469  469  }
 470  470  
 471  471  int
 472  472  mac_fini(void)
 473  473  {
↓ open down ↓ 634 lines elided ↑ open up ↑
1108 1108                                  err = mac_start_ring(ring);
1109 1109                                  if (err != 0) {
1110 1110                                          mip->mi_active--;
1111 1111                                          return (err);
1112 1112                                  }
1113 1113                          }
1114 1114                  }
1115 1115  
1116 1116                  if ((defgrp = MAC_DEFAULT_RX_GROUP(mip)) != NULL) {
1117 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.
     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.
1121 1122                           */
1122 1123                          ASSERT(defgrp->mrg_state == MAC_GROUP_STATE_REGISTERED);
1123 1124                          err = mac_start_group_and_rings(defgrp);
1124 1125                          if (err != 0) {
1125 1126                                  mip->mi_active--;
1126 1127                                  if ((ring != NULL) &&
1127 1128                                      (ring->mr_state == MR_INUSE))
1128 1129                                          mac_stop_ring(ring);
1129 1130                                  return (err);
1130 1131                          }
↓ open down ↓ 592 lines elided ↑ open up ↑
1723 1724  
1724 1725  int
1725 1726  mac_hwgroup_remmac(mac_group_handle_t gh, const uint8_t *addr)
1726 1727  {
1727 1728          mac_group_t *group = (mac_group_t *)gh;
1728 1729  
1729 1730          return (mac_group_remmac(group, addr));
1730 1731  }
1731 1732  
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 +/*
1733 1775   * Set the RX group to be shared/reserved. Note that the group must be
1734 1776   * started/stopped outside of this function.
1735 1777   */
1736 1778  void
1737 1779  mac_set_group_state(mac_group_t *grp, mac_group_state_t state)
1738 1780  {
1739 1781          /*
1740 1782           * If there is no change in the group state, just return.
1741 1783           */
1742 1784          if (grp->mrg_state == state)
↓ open down ↓ 664 lines elided ↑ open up ↑
2407 2449           */
2408 2450          if (err == 0)
2409 2451                  i_mac_notify_exit(mip);
2410 2452  
2411 2453          return (err);
2412 2454  }
2413 2455  
2414 2456  /*
2415 2457   * Called when the MAC instance has a non empty flow table, to de-multiplex
2416 2458   * incoming packets to the right flow.
2417      - * The MAC's rw lock is assumed held as a READER.
2418 2459   */
2419 2460  /* ARGSUSED */
2420 2461  static mblk_t *
2421 2462  mac_rx_classify(mac_impl_t *mip, mac_resource_handle_t mrh, mblk_t *mp)
2422 2463  {
2423 2464          flow_entry_t    *flent = NULL;
2424 2465          uint_t          flags = FLOW_INBOUND;
2425 2466          int             err;
2426 2467  
2427 2468          /*
2428      -         * If the mac is a port of an aggregation, pass FLOW_IGNORE_VLAN
     2469 +         * If the MAC is a port of an aggregation, pass FLOW_IGNORE_VLAN
2429 2470           * to mac_flow_lookup() so that the VLAN packets can be successfully
2430 2471           * passed to the non-VLAN aggregation flows.
2431 2472           *
2432 2473           * Note that there is possibly a race between this and
2433 2474           * 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.
     2475 +         * classified to non-VLAN flows of non-aggregation MAC clients. These
     2476 +         * VLAN packets will be then filtered out by the MAC module.
2436 2477           */
2437 2478          if ((mip->mi_state_flags & MIS_EXCLUSIVE) != 0)
2438 2479                  flags |= FLOW_IGNORE_VLAN;
2439 2480  
2440 2481          err = mac_flow_lookup(mip->mi_flow_tab, mp, flags, &flent);
2441 2482          if (err != 0) {
2442 2483                  /* no registered receive function */
2443 2484                  return (mp);
2444 2485          } else {
2445 2486                  mac_client_impl_t       *mcip;
↓ open down ↓ 1622 lines elided ↑ open up ↑
4068 4109                          /* unknown group type */
4069 4110                          DTRACE_PROBE2(mac__init__rings__unknown__type,
4070 4111                              char *, mip->mi_name,
4071 4112                              int, cap_rings->mr_group_type);
4072 4113                          err = EINVAL;
4073 4114                          goto bail;
4074 4115                  }
4075 4116  
4076 4117  
4077 4118                  /*
4078      -                 * Driver must register group->mgi_addmac/remmac() for rx groups
4079      -                 * to support multiple MAC addresses.
     4119 +                 * The driver must register some form of hardware MAC
     4120 +                 * filter in order for Rx groups to support multiple
     4121 +                 * MAC addresses.
4080 4122                   */
4081 4123                  if (rtype == MAC_RING_TYPE_RX &&
4082      -                    ((group_info.mgi_addmac == NULL) ||
4083      -                    (group_info.mgi_remmac == NULL))) {
     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);
4084 4128                          err = EINVAL;
4085 4129                          goto bail;
4086 4130                  }
4087 4131  
4088 4132                  /* Cache driver-supplied information */
4089 4133                  group->mrg_info = group_info;
4090 4134  
4091 4135                  /* Update the group's status and group count. */
4092 4136                  mac_set_group_state(group, MAC_GROUP_STATE_REGISTERED);
4093 4137                  group_free++;
↓ open down ↓ 26 lines elided ↑ open up ↑
4120 4164                  group->mrg_cur_count = 0;
4121 4165                  mac_init_group(mip, group, ring_left, cap_rings);
4122 4166  
4123 4167                  /* The current group size should be equal to ring_left */
4124 4168                  ASSERT(group->mrg_cur_count == ring_left);
4125 4169  
4126 4170                  ring_left = 0;
4127 4171  
4128 4172                  /* Update this group's status */
4129 4173                  mac_set_group_state(group, MAC_GROUP_STATE_REGISTERED);
4130      -        } else
     4174 +        } else {
4131 4175                  group->mrg_rings = NULL;
     4176 +        }
4132 4177  
4133 4178          ASSERT(ring_left == 0);
4134 4179  
4135 4180  bail:
4136 4181  
4137 4182          /* Cache other important information to finalize the initialization */
4138 4183          switch (rtype) {
4139 4184          case MAC_RING_TYPE_RX:
4140 4185                  mip->mi_rx_group_type = cap_rings->mr_group_type;
4141 4186                  mip->mi_rx_group_count = cap_rings->mr_gnum;
↓ open down ↓ 169 lines elided ↑ open up ↑
4311 4356                  }
4312 4357          }
4313 4358  
4314 4359          /* Free all the cached rings */
4315 4360          mac_ring_freeall(mip);
4316 4361          /* Free the block of group data strutures */
4317 4362          kmem_free(groups, sizeof (mac_group_t) * (group_count + 1));
4318 4363  }
4319 4364  
4320 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 +/*
4321 4398   * Associate a MAC address with a receive group.
4322 4399   *
4323 4400   * The return value of this function should always be checked properly, because
4324 4401   * any type of failure could cause unexpected results. A group can be added
4325 4402   * or removed with a MAC address only after it has been reserved. Ideally,
4326 4403   * a successful reservation always leads to calling mac_group_addmac() to
4327 4404   * steer desired traffic. Failure of adding an unicast MAC address doesn't
4328 4405   * always imply that the group is functioning abnormally.
4329 4406   *
4330 4407   * Currently this function is called everywhere, and it reflects assumptions
4331 4408   * about MAC addresses in the implementation. CR 6735196.
4332 4409   */
4333 4410  int
4334 4411  mac_group_addmac(mac_group_t *group, const uint8_t *addr)
4335 4412  {
4336      -        ASSERT(group->mrg_type == MAC_RING_TYPE_RX);
4337      -        ASSERT(group->mrg_info.mgi_addmac != NULL);
     4413 +        VERIFY3S(group->mrg_type, ==, MAC_RING_TYPE_RX);
     4414 +        VERIFY3P(group->mrg_info.mgi_addmac, !=, NULL);
4338 4415  
4339 4416          return (group->mrg_info.mgi_addmac(group->mrg_info.mgi_driver, addr));
4340 4417  }
4341 4418  
4342 4419  /*
4343 4420   * Remove the association between MAC address and receive group.
4344 4421   */
4345 4422  int
4346 4423  mac_group_remmac(mac_group_t *group, const uint8_t *addr)
4347 4424  {
4348      -        ASSERT(group->mrg_type == MAC_RING_TYPE_RX);
4349      -        ASSERT(group->mrg_info.mgi_remmac != NULL);
     4425 +        VERIFY3S(group->mrg_type, ==, MAC_RING_TYPE_RX);
     4426 +        VERIFY3P(group->mrg_info.mgi_remmac, !=, NULL);
4350 4427  
4351 4428          return (group->mrg_info.mgi_remmac(group->mrg_info.mgi_driver, addr));
4352 4429  }
4353 4430  
4354 4431  /*
4355 4432   * This is the entry point for packets transmitted through the bridging code.
4356 4433   * If no bridge is in place, MAC_RING_TX transmits using tx ring. The 'rh'
4357 4434   * pointer may be NULL to select the default ring.
4358 4435   */
4359 4436  mblk_t *
↓ open down ↓ 154 lines elided ↑ open up ↑
4514 4591                          return (ret);
4515 4592                  }
4516 4593          }
4517 4594  
4518 4595          /*
4519 4596           * Set up SRS/SR according to the ring type.
4520 4597           */
4521 4598          switch (ring->mr_type) {
4522 4599          case MAC_RING_TYPE_RX:
4523 4600                  /*
4524      -                 * Setup SRS on top of the new ring if the group is
4525      -                 * reserved for someones exclusive use.
     4601 +                 * Setup an SRS on top of the new ring if the group is
     4602 +                 * reserved for someone's exclusive use.
4526 4603                   */
4527 4604                  if (group->mrg_state == MAC_GROUP_STATE_RESERVED) {
4528      -                        mac_client_impl_t *mcip;
     4605 +                        mac_client_impl_t *mcip =  MAC_GROUP_ONLY_CLIENT(group);
4529 4606  
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      -                        }
     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;
4546 4615                  }
4547 4616                  break;
4548 4617          case MAC_RING_TYPE_TX:
4549 4618          {
4550 4619                  mac_grp_client_t        *mgcp = group->mrg_clients;
4551 4620                  mac_client_impl_t       *mcip;
4552 4621                  mac_soft_ring_set_t     *mac_srs;
4553 4622                  mac_srs_tx_t            *tx;
4554 4623  
4555 4624                  if (MAC_GROUP_NO_CLIENT(group)) {
↓ open down ↓ 5 lines elided ↑ open up ↑
4561 4630                  /*
4562 4631                   * If the rings are being moved to a group that has
4563 4632                   * clients using it, then add the new rings to the
4564 4633                   * clients SRS.
4565 4634                   */
4566 4635                  while (mgcp != NULL) {
4567 4636                          boolean_t       is_aggr;
4568 4637  
4569 4638                          mcip = mgcp->mgc_client;
4570 4639                          flent = mcip->mci_flent;
4571      -                        is_aggr = (mcip->mci_state_flags & MCIS_IS_AGGR);
     4640 +                        is_aggr = (mcip->mci_state_flags & MCIS_IS_AGGR_CLIENT);
4572 4641                          mac_srs = MCIP_TX_SRS(mcip);
4573 4642                          tx = &mac_srs->srs_tx;
4574 4643                          mac_tx_client_quiesce((mac_client_handle_t)mcip);
4575 4644                          /*
4576 4645                           * If we are  growing from 1 to multiple rings.
4577 4646                           */
4578 4647                          if (tx->st_mode == SRS_TX_BW ||
4579 4648                              tx->st_mode == SRS_TX_SERIALIZE ||
4580 4649                              tx->st_mode == SRS_TX_DEFAULT) {
4581 4650                                  mac_ring_t      *tx_ring = tx->st_arg2;
↓ open down ↓ 123 lines elided ↑ open up ↑
4705 4774                                      (group->mrg_rings != ring) ?
4706 4775                                      (mac_ring_handle_t)group->mrg_rings :
4707 4776                                      (mac_ring_handle_t)(ring->mr_next);
4708 4777                          }
4709 4778                          /* Presently only aggr case comes here */
4710 4779                          if (group->mrg_state != MAC_GROUP_STATE_RESERVED)
4711 4780                                  break;
4712 4781  
4713 4782                          mcip = MAC_GROUP_ONLY_CLIENT(group);
4714 4783                          ASSERT(mcip != NULL);
4715      -                        ASSERT(mcip->mci_state_flags & MCIS_IS_AGGR);
     4784 +                        ASSERT(mcip->mci_state_flags & MCIS_IS_AGGR_CLIENT);
4716 4785                          mac_srs = MCIP_TX_SRS(mcip);
4717 4786                          ASSERT(mac_srs->srs_tx.st_mode == SRS_TX_AGGR ||
4718 4787                              mac_srs->srs_tx.st_mode == SRS_TX_BW_AGGR);
4719 4788                          srs_tx = &mac_srs->srs_tx;
4720 4789                          /*
4721 4790                           * Wakeup any callers blocked on this
4722 4791                           * Tx ring due to flow control.
4723 4792                           */
4724 4793                          sringp = srs_tx->st_soft_rings[ring->mr_index];
4725 4794                          ASSERT(sringp != NULL);
↓ open down ↓ 187 lines elided ↑ open up ↑
4913 4982  
4914 4983  /*
4915 4984   * Remove the specified MAC address from the MAC address list and free it.
4916 4985   */
4917 4986  static void
4918 4987  mac_free_macaddr(mac_address_t *map)
4919 4988  {
4920 4989          mac_impl_t *mip = map->ma_mip;
4921 4990  
4922 4991          ASSERT(MAC_PERIM_HELD((mac_handle_t)mip));
4923      -        ASSERT(mip->mi_addresses != NULL);
     4992 +        VERIFY3P(mip->mi_addresses, !=, NULL);
4924 4993  
4925      -        map = mac_find_macaddr(mip, map->ma_addr);
     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);
4926 4998  
4927      -        ASSERT(map != NULL);
4928      -        ASSERT(map->ma_nusers == 0);
4929      -
4930 4999          if (map == mip->mi_addresses) {
4931 5000                  mip->mi_addresses = map->ma_next;
4932 5001          } else {
4933 5002                  mac_address_t *pre;
4934 5003  
4935 5004                  pre = mip->mi_addresses;
4936 5005                  while (pre->ma_next != map)
4937 5006                          pre = pre->ma_next;
4938 5007                  pre->ma_next = map->ma_next;
4939 5008          }
4940 5009  
4941 5010          kmem_free(map, sizeof (mac_address_t));
4942 5011  }
4943 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 +
4944 5071  /*
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.
     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.
4955 5078   */
4956 5079  int
4957      -mac_add_macaddr(mac_impl_t *mip, mac_group_t *group, uint8_t *mac_addr,
4958      -    boolean_t use_hw)
     5080 +mac_add_macaddr_vlan(mac_impl_t *mip, mac_group_t *group, uint8_t *addr,
     5081 +    uint16_t vid, boolean_t use_hw)
4959 5082  {
4960      -        mac_address_t *map;
4961      -        int err = 0;
4962      -        boolean_t allocated_map = B_FALSE;
     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;
4963 5089  
4964 5090          ASSERT(MAC_PERIM_HELD((mac_handle_t)mip));
4965 5091  
4966      -        map = mac_find_macaddr(mip, mac_addr);
     5092 +        map = mac_find_macaddr(mip, addr);
4967 5093  
4968 5094          /*
4969      -         * If the new MAC address has not been added. Allocate a new one
4970      -         * and set it up.
     5095 +         * If this is the first use of this MAC address then allocate
     5096 +         * and initialize a new structure.
4971 5097           */
4972 5098          if (map == NULL) {
4973 5099                  map = kmem_zalloc(sizeof (mac_address_t), KM_SLEEP);
4974 5100                  map->ma_len = mip->mi_type->mt_addr_length;
4975      -                bcopy(mac_addr, map->ma_addr, map->ma_len);
     5101 +                bcopy(addr, map->ma_addr, map->ma_len);
4976 5102                  map->ma_nusers = 0;
4977 5103                  map->ma_group = group;
4978 5104                  map->ma_mip = mip;
     5105 +                map->ma_untagged = B_FALSE;
4979 5106  
4980      -                /* add the new MAC address to the head of the address list */
     5107 +                /* Add the new MAC address to the head of the address list. */
4981 5108                  map->ma_next = mip->mi_addresses;
4982 5109                  mip->mi_addresses = map;
4983 5110  
4984 5111                  allocated_map = B_TRUE;
4985 5112          }
4986 5113  
4987      -        ASSERT(map->ma_group == NULL || map->ma_group == group);
     5114 +        VERIFY(map->ma_group == NULL || map->ma_group == group);
4988 5115          if (map->ma_group == NULL)
4989 5116                  map->ma_group = group;
4990 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 +
4991 5125          /*
4992      -         * If the MAC address is already in use, simply account for the
4993      -         * new client.
     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.
4994 5135           */
4995      -        if (map->ma_nusers++ > 0)
     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)
4996 5152                  return (0);
4997 5153  
4998 5154          /*
     5155 +         * All logic from here on out is executed during initial
     5156 +         * creation only.
     5157 +         */
     5158 +        VERIFY3S(map->ma_nusers, ==, 1);
     5159 +
     5160 +        /*
4999 5161           * Activate this MAC address by adding it to the reserved group.
5000 5162           */
5001 5163          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);
     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;
5006 5176                  }
     5177 +
     5178 +                hw_mac = (err == 0);
5007 5179          }
5008 5180  
     5181 +        if (hw_mac) {
     5182 +                map->ma_type = MAC_ADDRESS_TYPE_UNICAST_CLASSIFIED;
     5183 +                return (0);
     5184 +        }
     5185 +
5009 5186          /*
5010 5187           * The MAC address addition failed. If the client requires a
5011      -         * hardware classified MAC address, fail the operation.
     5188 +         * hardware classified MAC address, fail the operation. This
     5189 +         * feature is only used by sun4v vsw.
5012 5190           */
5013      -        if (use_hw) {
     5191 +        if (use_hw && !hw_mac) {
5014 5192                  err = ENOSPC;
     5193 +                map->ma_nusers--;
5015 5194                  goto bail;
5016 5195          }
5017 5196  
5018 5197          /*
5019      -         * Try promiscuous mode.
5020      -         *
5021      -         * For drivers that don't advertise RINGS capability, do
5022      -         * nothing for the primary address.
     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.
5023 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 +         */
5024 5209          if ((group == NULL) &&
5025 5210              (bcmp(map->ma_addr, mip->mi_addr, map->ma_len) == 0)) {
5026 5211                  map->ma_type = MAC_ADDRESS_TYPE_UNICAST_CLASSIFIED;
5027 5212                  return (0);
5028 5213          }
5029 5214  
5030 5215          /*
5031      -         * Enable promiscuous mode in order to receive traffic
5032      -         * to the new MAC address.
     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().
5033 5221           */
5034 5222          if ((err = i_mac_promisc_set(mip, B_TRUE)) == 0) {
5035 5223                  map->ma_type = MAC_ADDRESS_TYPE_UNICAST_PROMISC;
5036 5224                  return (0);
5037 5225          }
5038 5226  
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 5227  bail:
5046      -        map->ma_nusers--;
     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 +
5047 5241          if (allocated_map)
5048 5242                  mac_free_macaddr(map);
     5243 +
5049 5244          return (err);
5050 5245  }
5051 5246  
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 5247  int
5058      -mac_remove_macaddr(mac_address_t *map)
     5248 +mac_remove_macaddr_vlan(mac_address_t *map, uint16_t vid)
5059 5249  {
5060      -        mac_impl_t *mip = map->ma_mip;
5061      -        int err = 0;
     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;
5062 5254  
5063 5255          ASSERT(MAC_PERIM_HELD((mac_handle_t)mip));
     5256 +        VERIFY3P(map, ==, mac_find_macaddr(mip, map->ma_addr));
5064 5257  
5065      -        ASSERT(map == mac_find_macaddr(mip, map->ma_addr));
     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 +        }
5066 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 +
5067 5274          /*
5068 5275           * If it's not the last client using this MAC address, only update
5069 5276           * the MAC clients count.
5070 5277           */
5071      -        if (--map->ma_nusers > 0)
     5278 +        map->ma_nusers--;
     5279 +        if (map->ma_nusers > 0)
5072 5280                  return (0);
5073 5281  
5074 5282          /*
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.
     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.
5078 5286           */
5079 5287          switch (map->ma_type) {
5080 5288          case MAC_ADDRESS_TYPE_UNICAST_CLASSIFIED:
5081 5289                  /*
5082 5290                   * Don't free the preset primary address for drivers that
5083 5291                   * don't advertise RINGS capability.
5084 5292                   */
5085      -                if (map->ma_group == NULL)
     5293 +                if (group == NULL)
5086 5294                          return (0);
5087 5295  
5088      -                err = mac_group_remmac(map->ma_group, map->ma_addr);
5089      -                if (err == 0)
5090      -                        map->ma_group = NULL;
     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;
5091 5324                  break;
5092 5325          case MAC_ADDRESS_TYPE_UNICAST_PROMISC:
5093 5326                  err = i_mac_promisc_set(mip, B_FALSE);
5094 5327                  break;
5095 5328          default:
5096      -                ASSERT(B_FALSE);
     5329 +                panic("Unexpected ma_type 0x%x, file: %s, line %d",
     5330 +                    map->ma_type, __FILE__, __LINE__);
5097 5331          }
5098 5332  
5099 5333          if (err != 0)
5100 5334                  return (err);
5101 5335  
5102 5336          /*
5103 5337           * We created MAC address for the primary one at registration, so we
5104 5338           * won't free it here. mac_fini_macaddr() will take care of it.
5105 5339           */
5106 5340          if (bcmp(map->ma_addr, mip->mi_addr, map->ma_len) != 0)
↓ open down ↓ 136 lines elided ↑ open up ↑
5243 5477  {
5244 5478          mac_address_t *map = mip->mi_addresses;
5245 5479  
5246 5480          if (map == NULL)
5247 5481                  return;
5248 5482  
5249 5483          /*
5250 5484           * If mi_addresses is initialized, there should be exactly one
5251 5485           * entry left on the list with no users.
5252 5486           */
5253      -        ASSERT(map->ma_nusers == 0);
5254      -        ASSERT(map->ma_next == NULL);
     5487 +        VERIFY3S(map->ma_nusers, ==, 0);
     5488 +        VERIFY3P(map->ma_next, ==, NULL);
     5489 +        VERIFY3P(map->ma_vlans, ==, NULL);
5255 5490  
5256 5491          kmem_free(map, sizeof (mac_address_t));
5257 5492          mip->mi_addresses = NULL;
5258 5493  }
5259 5494  
5260 5495  /*
5261 5496   * Logging related functions.
5262 5497   *
5263 5498   * Note that Kernel statistics have been extended to maintain fine
5264 5499   * granularity of statistics viz. hardware lane, software lane, fanout
↓ open down ↓ 541 lines elided ↑ open up ↑
5806 6041                  mac_link_log_enable = B_FALSE;
5807 6042                  break;
5808 6043          default:
5809 6044                  ASSERT(0);
5810 6045          }
5811 6046  
5812 6047          /* Reenable fastpath */
5813 6048          mod_hash_walk(i_mac_impl_hash, i_mac_fastpath_walker, &estate);
5814 6049  
5815 6050          (void) untimeout(mac_logging_timer);
5816      -        mac_logging_timer = 0;
     6051 +        mac_logging_timer = NULL;
5817 6052  
5818 6053          /* Write log entries for each mac_impl in the list */
5819 6054          i_mac_log_info(&net_log_list, &lstate);
5820 6055  }
5821 6056  
5822 6057  /*
5823 6058   * Walk the rx and tx SRS/SRs for a flow and update the priority value.
5824 6059   */
5825 6060  void
5826 6061  mac_flow_update_priority(mac_client_impl_t *mcip, flow_entry_t *flent)
↓ open down ↓ 97 lines elided ↑ open up ↑
5924 6159                  mac_tx_invoke_callbacks(mcip,
5925 6160                      (mac_tx_cookie_t)mac_tx_srs_get_soft_ring(srs,
5926 6161                      desired_ring));
5927 6162                  mac_tx_srs_del_ring(srs, desired_ring);
5928 6163                  mac_tx_client_restart((mac_client_handle_t)mcip);
5929 6164          }
5930 6165          return (desired_ring);
5931 6166  }
5932 6167  
5933 6168  /*
5934      - * For a reserved group with multiple clients, return the primary client.
     6169 + * For a non-default group with multiple clients, return the primary client.
5935 6170   */
5936 6171  static mac_client_impl_t *
5937 6172  mac_get_grp_primary(mac_group_t *grp)
5938 6173  {
5939 6174          mac_grp_client_t        *mgcp = grp->mrg_clients;
5940 6175          mac_client_impl_t       *mcip;
5941 6176  
5942 6177          while (mgcp != NULL) {
5943 6178                  mcip = mgcp->mgc_client;
5944 6179                  if (mcip->mci_flent->fe_type & FLOW_PRIMARY_MAC)
↓ open down ↓ 338 lines elided ↑ open up ↑
6283 6518  void
6284 6519  mac_group_add_client(mac_group_t *grp, mac_client_impl_t *mcip)
6285 6520  {
6286 6521          mac_grp_client_t *mgcp;
6287 6522  
6288 6523          for (mgcp = grp->mrg_clients; mgcp != NULL; mgcp = mgcp->mgc_next) {
6289 6524                  if (mgcp->mgc_client == mcip)
6290 6525                          break;
6291 6526          }
6292 6527  
6293      -        VERIFY(mgcp == NULL);
     6528 +        ASSERT(mgcp == NULL);
6294 6529  
6295 6530          mgcp = kmem_zalloc(sizeof (mac_grp_client_t), KM_SLEEP);
6296 6531          mgcp->mgc_client = mcip;
6297 6532          mgcp->mgc_next = grp->mrg_clients;
6298 6533          grp->mrg_clients = mgcp;
6299      -
6300 6534  }
6301 6535  
6302 6536  void
6303 6537  mac_group_remove_client(mac_group_t *grp, mac_client_impl_t *mcip)
6304 6538  {
6305 6539          mac_grp_client_t *mgcp, **pprev;
6306 6540  
6307 6541          for (pprev = &grp->mrg_clients, mgcp = *pprev; mgcp != NULL;
6308 6542              pprev = &mgcp->mgc_next, mgcp = *pprev) {
6309 6543                  if (mgcp->mgc_client == mcip)
6310 6544                          break;
6311 6545          }
6312 6546  
6313 6547          ASSERT(mgcp != NULL);
6314 6548  
6315 6549          *pprev = mgcp->mgc_next;
6316 6550          kmem_free(mgcp, sizeof (mac_grp_client_t));
6317 6551  }
6318 6552  
6319 6553  /*
6320      - * mac_reserve_rx_group()
6321      - *
     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 +/*
6322 6575   * Finds an available group and exclusively reserves it for a client.
6323 6576   * The group is chosen to suit the flow's resource controls (bandwidth and
6324 6577   * fanout requirements) and the address type.
6325 6578   * If the requestor is the pimary MAC then return the group with the
6326 6579   * largest number of rings, otherwise the default ring when available.
6327 6580   */
6328 6581  mac_group_t *
6329 6582  mac_reserve_rx_group(mac_client_impl_t *mcip, uint8_t *mac_addr, boolean_t move)
6330 6583  {
6331 6584          mac_share_handle_t      share = mcip->mci_share;
↓ open down ↓ 2 lines elided ↑ open up ↑
6334 6587          int                     i;
6335 6588          int                     err = 0;
6336 6589          mac_address_t           *map;
6337 6590          mac_resource_props_t    *mrp = MCIP_RESOURCE_PROPS(mcip);
6338 6591          int                     nrings;
6339 6592          int                     donor_grp_rcnt;
6340 6593          boolean_t               need_exclgrp = B_FALSE;
6341 6594          int                     need_rings = 0;
6342 6595          mac_group_t             *candidate_grp = NULL;
6343 6596          mac_client_impl_t       *gclient;
6344      -        mac_resource_props_t    *gmrp;
6345 6597          mac_group_t             *donorgrp = NULL;
6346 6598          boolean_t               rxhw = mrp->mrp_mask & MRP_RX_RINGS;
6347 6599          boolean_t               unspec = mrp->mrp_mask & MRP_RXRINGS_UNSPEC;
6348 6600          boolean_t               isprimary;
6349 6601  
6350 6602          ASSERT(MAC_PERIM_HELD((mac_handle_t)mip));
6351 6603  
6352 6604          isprimary = mcip->mci_flent->fe_type & FLOW_PRIMARY_MAC;
6353 6605  
6354 6606          /*
6355      -         * Check if a group already has this mac address (case of VLANs)
     6607 +         * Check if a group already has this MAC address (case of VLANs)
6356 6608           * unless we are moving this MAC client from one group to another.
6357 6609           */
6358 6610          if (!move && (map = mac_find_macaddr(mip, mac_addr)) != NULL) {
6359 6611                  if (map->ma_group != NULL)
6360 6612                          return (map->ma_group);
6361 6613          }
     6614 +
6362 6615          if (mip->mi_rx_groups == NULL || mip->mi_rx_group_count == 0)
6363 6616                  return (NULL);
     6617 +
6364 6618          /*
6365      -         * If exclusive open, return NULL which will enable the
6366      -         * caller to use the default group.
     6619 +         * If this client is requesting exclusive MAC access then
     6620 +         * return NULL to ensure the client uses the default group.
6367 6621           */
6368 6622          if (mcip->mci_state_flags & MCIS_EXCLUSIVE)
6369 6623                  return (NULL);
6370 6624  
6371 6625          /* For dynamic groups default unspecified to 1 */
6372 6626          if (rxhw && unspec &&
6373 6627              mip->mi_rx_group_type == MAC_GROUP_TYPE_DYNAMIC) {
6374 6628                  mrp->mrp_nrxrings = 1;
6375 6629          }
     6630 +
6376 6631          /*
6377 6632           * For static grouping we allow only specifying rings=0 and
6378 6633           * unspecified
6379 6634           */
6380 6635          if (rxhw && mrp->mrp_nrxrings > 0 &&
6381 6636              mip->mi_rx_group_type == MAC_GROUP_TYPE_STATIC) {
6382 6637                  return (NULL);
6383 6638          }
     6639 +
6384 6640          if (rxhw) {
6385 6641                  /*
6386 6642                   * We have explicitly asked for a group (with nrxrings,
6387 6643                   * if unspec).
6388 6644                   */
6389 6645                  if (unspec || mrp->mrp_nrxrings > 0) {
6390 6646                          need_exclgrp = B_TRUE;
6391 6647                          need_rings = mrp->mrp_nrxrings;
6392 6648                  } else if (mrp->mrp_nrxrings == 0) {
6393 6649                          /*
↓ open down ↓ 41 lines elided ↑ open up ↑
6435 6691                  DTRACE_PROBE3(rx__group__trying, char *, mip->mi_name,
6436 6692                      int, grp->mrg_index, mac_group_state_t, grp->mrg_state);
6437 6693  
6438 6694                  /*
6439 6695                   * Check if this group could be a candidate group for
6440 6696                   * eviction if we need a group for this MAC client,
6441 6697                   * but there aren't any. A candidate group is one
6442 6698                   * that didn't ask for an exclusive group, but got
6443 6699                   * one and it has enough rings (combined with what
6444 6700                   * the donor group can donate) for the new MAC
6445      -                 * client
     6701 +                 * client.
6446 6702                   */
6447 6703                  if (grp->mrg_state >= MAC_GROUP_STATE_RESERVED) {
6448 6704                          /*
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.
     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.
6453 6710                           */
6454 6711                          if (candidate_grp == NULL &&
6455 6712                              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 &&
     6713 +                                if (!i_mac_clients_hw(grp, MRP_RX_RINGS) &&
6464 6714                                      (unspec ||
6465 6715                                      (grp->mrg_cur_count + donor_grp_rcnt >=
6466 6716                                      need_rings))) {
6467 6717                                          candidate_grp = grp;
6468 6718                                  }
6469 6719                          }
6470 6720                          continue;
6471 6721                  }
6472 6722                  /*
6473 6723                   * This group could already be SHARED by other multicast
↓ open down ↓ 45 lines elided ↑ open up ↑
6519 6769  
6520 6770                  DTRACE_PROBE3(rx__group__reserve__alloc__rings, char *,
6521 6771                      mip->mi_name, int, grp->mrg_index, int, err);
6522 6772  
6523 6773                  /*
6524 6774                   * It's a dynamic group but the grouping operation
6525 6775                   * failed.
6526 6776                   */
6527 6777                  mac_stop_group(grp);
6528 6778          }
     6779 +
6529 6780          /* We didn't find an exclusive group for this MAC client */
6530 6781          if (i >= mip->mi_rx_group_count) {
6531 6782  
6532 6783                  if (!need_exclgrp)
6533 6784                          return (NULL);
6534 6785  
6535 6786                  /*
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.
     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.
6542 6793                   */
6543 6794                  if (candidate_grp == NULL &&
6544 6795                      donorgrp != MAC_DEFAULT_RX_GROUP(mip) &&
6545 6796                      donorgrp->mrg_cur_count >= need_rings) {
6546 6797                          candidate_grp = donorgrp;
6547 6798                  }
6548 6799                  if (candidate_grp != NULL) {
6549 6800                          boolean_t       prim_grp = B_FALSE;
6550 6801  
6551 6802                          /*
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.
     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.
6556 6808                           */
6557 6809                          grp = candidate_grp;
6558      -                        gclient = MAC_GROUP_ONLY_CLIENT(grp);
6559      -                        if (gclient == NULL)
6560      -                                gclient = mac_get_grp_primary(grp);
     6810 +                        gclient = grp->mrg_clients->mgc_client;
     6811 +                        VERIFY3P(gclient, !=, NULL);
6561 6812                          if (grp == mip->mi_rx_donor_grp)
6562 6813                                  prim_grp = B_TRUE;
6563 6814                          if (mac_rx_switch_group(gclient, grp,
6564 6815                              MAC_DEFAULT_RX_GROUP(mip)) != 0) {
6565 6816                                  return (NULL);
6566 6817                          }
6567 6818                          if (prim_grp) {
6568 6819                                  mip->mi_rx_donor_grp =
6569 6820                                      MAC_DEFAULT_RX_GROUP(mip);
6570 6821                                  donorgrp = MAC_DEFAULT_RX_GROUP(mip);
6571 6822                          }
6572 6823  
6573      -
6574 6824                          /*
6575 6825                           * Now give this group with the required rings
6576 6826                           * to this MAC client.
6577 6827                           */
6578 6828                          ASSERT(grp->mrg_state == MAC_GROUP_STATE_REGISTERED);
6579 6829                          if (mac_start_group(grp) != 0)
6580 6830                                  return (NULL);
6581 6831  
6582 6832                          if (mip->mi_rx_group_type != MAC_GROUP_TYPE_DYNAMIC)
6583 6833                                  return (grp);
↓ open down ↓ 27 lines elided ↑ open up ↑
6611 6861          ASSERT(grp != NULL);
6612 6862  
6613 6863          DTRACE_PROBE2(rx__group__reserved,
6614 6864              char *, mip->mi_name, int, grp->mrg_index);
6615 6865          return (grp);
6616 6866  }
6617 6867  
6618 6868  /*
6619 6869   * mac_rx_release_group()
6620 6870   *
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.
     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.
6625 6875   */
6626 6876  void
6627 6877  mac_release_rx_group(mac_client_impl_t *mcip, mac_group_t *group)
6628 6878  {
6629 6879          mac_impl_t              *mip = mcip->mci_mip;
6630 6880          mac_ring_t              *ring;
6631 6881  
6632 6882          ASSERT(group != MAC_DEFAULT_RX_GROUP(mip));
     6883 +        ASSERT(MAC_GROUP_NO_CLIENT(group) == B_TRUE);
6633 6884  
6634 6885          if (mip->mi_rx_donor_grp == group)
6635 6886                  mip->mi_rx_donor_grp = MAC_DEFAULT_RX_GROUP(mip);
6636 6887  
6637 6888          /*
6638 6889           * This is the case where there are no clients left. Any
6639 6890           * SRS etc on this group have also be quiesced.
6640 6891           */
6641 6892          for (ring = group->mrg_rings; ring != NULL; ring = ring->mr_next) {
6642 6893                  if (ring->mr_classify_type == MAC_HW_CLASSIFIER) {
↓ open down ↓ 31 lines elided ↑ open up ↑
6674 6925                  }
6675 6926          }
6676 6927          mac_stop_group(group);
6677 6928          /*
6678 6929           * Possible improvement: See if we can assign the group just released
6679 6930           * to a another client of the mip
6680 6931           */
6681 6932  }
6682 6933  
6683 6934  /*
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.
     6935 + * Move the MAC address from fgrp to tgrp.
6693 6936   */
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 6937  static int
6736 6938  mac_rx_move_macaddr(mac_client_impl_t *mcip, mac_group_t *fgrp,
6737 6939      mac_group_t *tgrp)
6738 6940  {
6739 6941          mac_impl_t              *mip = mcip->mci_mip;
6740 6942          uint8_t                 maddr[MAXMACADDRLEN];
6741 6943          int                     err = 0;
6742      -        boolean_t               prim;
6743      -        boolean_t               multiclnt = B_FALSE;
     6944 +        uint16_t                vid;
     6945 +        mac_unicast_impl_t      *muip;
     6946 +        boolean_t               use_hw;
6744 6947  
6745 6948          mac_rx_client_quiesce((mac_client_handle_t)mcip);
6746      -        ASSERT(mcip->mci_unicast != NULL);
     6949 +        VERIFY3P(mcip->mci_unicast, !=, NULL);
6747 6950          bcopy(mcip->mci_unicast->ma_addr, maddr, mcip->mci_unicast->ma_len);
6748 6951  
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);
     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 +
6756 6970          if (err != 0) {
6757 6971                  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 6972                  return (err);
6763 6973          }
     6974 +
6764 6975          /*
6765      -         * Program the H/W Classifier first, if this fails we need
6766      -         * not proceed with the other stuff.
     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.
6767 6980           */
6768      -        if ((err = mac_add_macaddr(mip, tgrp, maddr, prim)) != 0) {
     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 +
6769 6999                  /* 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);
     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);
6779 7006                  }
     7007 +
6780 7008                  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 7009                  return (err);
6786 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 +         */
6787 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);
6788 7022          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);
     7023 +        return (0);
6792 7024  }
6793 7025  
6794 7026  /*
6795 7027   * Switch the MAC client from one group to another. This means we need
6796 7028   * to remove the MAC address from the group, remove the MAC client,
6797 7029   * teardown the SRSs and revert the group state. Then, we add the client
6798 7030   * to the destination group, set the SRSs, and add the MAC address to the
6799 7031   * group.
6800 7032   */
6801 7033  int
6802 7034  mac_rx_switch_group(mac_client_impl_t *mcip, mac_group_t *fgrp,
6803 7035      mac_group_t *tgrp)
6804 7036  {
6805 7037          int                     err;
6806 7038          mac_group_state_t       next_state;
6807 7039          mac_client_impl_t       *group_only_mcip;
6808 7040          mac_client_impl_t       *gmcip;
6809 7041          mac_impl_t              *mip = mcip->mci_mip;
6810 7042          mac_grp_client_t        *mgcp;
6811 7043  
6812      -        ASSERT(fgrp == mcip->mci_flent->fe_rx_ring_group);
     7044 +        VERIFY3P(fgrp, ==, mcip->mci_flent->fe_rx_ring_group);
6813 7045  
6814 7046          if ((err = mac_rx_move_macaddr(mcip, fgrp, tgrp)) != 0)
6815 7047                  return (err);
6816 7048  
6817 7049          /*
6818      -         * The group might be reserved, but SRSs may not be set up, e.g.
6819      -         * primary and its vlans using a reserved group.
     7050 +         * If the group is marked as reserved and in use by a single
     7051 +         * client, then there is an SRS to teardown.
6820 7052           */
6821 7053          if (fgrp->mrg_state == MAC_GROUP_STATE_RESERVED &&
6822 7054              MAC_GROUP_ONLY_CLIENT(fgrp) != NULL) {
6823 7055                  mac_rx_srs_group_teardown(mcip->mci_flent, B_TRUE);
6824 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 +         */
6825 7072          if (fgrp != MAC_DEFAULT_RX_GROUP(mip)) {
6826 7073                  mgcp = fgrp->mrg_clients;
6827 7074                  while (mgcp != NULL) {
6828 7075                          gmcip = mgcp->mgc_client;
6829 7076                          mgcp = mgcp->mgc_next;
6830 7077                          mac_group_remove_client(fgrp, gmcip);
6831 7078                          mac_group_add_client(tgrp, gmcip);
6832 7079                          gmcip->mci_flent->fe_rx_ring_group = tgrp;
6833 7080                  }
6834 7081                  mac_release_rx_group(mcip, fgrp);
6835      -                ASSERT(MAC_GROUP_NO_CLIENT(fgrp));
     7082 +                VERIFY3B(MAC_GROUP_NO_CLIENT(fgrp), ==, B_TRUE);
6836 7083                  mac_set_group_state(fgrp, MAC_GROUP_STATE_REGISTERED);
6837 7084          } else {
6838 7085                  mac_group_remove_client(fgrp, mcip);
6839 7086                  mac_group_add_client(tgrp, mcip);
6840 7087                  mcip->mci_flent->fe_rx_ring_group = tgrp;
     7088 +
6841 7089                  /*
6842 7090                   * If there are other clients (VLANs) sharing this address
6843      -                 * we should be here only for the primary.
     7091 +                 * then move them too.
6844 7092                   */
6845      -                if (mcip->mci_unicast->ma_nusers > 1) {
     7093 +                if (mac_check_macaddr_shared(mcip->mci_unicast)) {
6846 7094                          /*
6847 7095                           * We need to move all the clients that are using
6848      -                         * this h/w address.
     7096 +                         * this MAC address.
6849 7097                           */
6850 7098                          mgcp = fgrp->mrg_clients;
6851 7099                          while (mgcp != NULL) {
6852 7100                                  gmcip = mgcp->mgc_client;
6853 7101                                  mgcp = mgcp->mgc_next;
6854 7102                                  if (mcip->mci_unicast == gmcip->mci_unicast) {
6855 7103                                          mac_group_remove_client(fgrp, gmcip);
6856 7104                                          mac_group_add_client(tgrp, gmcip);
6857 7105                                          gmcip->mci_flent->fe_rx_ring_group =
6858 7106                                              tgrp;
6859 7107                                  }
6860 7108                          }
6861 7109                  }
     7110 +
6862 7111                  /*
6863      -                 * The default group will still take the multicast,
6864      -                 * broadcast traffic etc., so it won't go to
     7112 +                 * The default group still handles multicast and
     7113 +                 * broadcast traffic; it won't transition to
6865 7114                   * MAC_GROUP_STATE_REGISTERED.
6866 7115                   */
6867 7116                  if (fgrp->mrg_state == MAC_GROUP_STATE_RESERVED)
6868 7117                          mac_rx_group_unmark(fgrp, MR_CONDEMNED);
6869 7118                  mac_set_group_state(fgrp, MAC_GROUP_STATE_SHARED);
6870 7119          }
     7120 +
6871 7121          next_state = mac_group_next_state(tgrp, &group_only_mcip,
6872 7122              MAC_DEFAULT_RX_GROUP(mip), B_TRUE);
6873 7123          mac_set_group_state(tgrp, next_state);
     7124 +
6874 7125          /*
6875      -         * If the destination group is reserved, setup the SRSs etc.
     7126 +         * If the destination group is reserved, then setup the SRSes.
     7127 +         * Otherwise make sure to use SW classification.
6876 7128           */
6877 7129          if (tgrp->mrg_state == MAC_GROUP_STATE_RESERVED) {
6878 7130                  mac_rx_srs_group_setup(mcip, mcip->mci_flent, SRST_LINK);
6879 7131                  mac_fanout_setup(mcip, mcip->mci_flent,
6880 7132                      MCIP_RESOURCE_PROPS(mcip), mac_rx_deliver, mcip, NULL,
6881 7133                      NULL);
6882 7134                  mac_rx_group_unmark(tgrp, MR_INCIPIENT);
6883 7135          } else {
6884 7136                  mac_rx_switch_grp_to_sw(tgrp);
6885 7137          }
     7138 +
6886 7139          return (0);
6887 7140  }
6888 7141  
6889 7142  /*
6890 7143   * Reserves a TX group for the specified share. Invoked by mac_tx_srs_setup()
6891 7144   * when a share was allocated to the client.
6892 7145   */
6893 7146  mac_group_t *
6894 7147  mac_reserve_tx_group(mac_client_impl_t *mcip, boolean_t move)
6895 7148  {
↓ open down ↓ 10 lines elided ↑ open up ↑
6906 7159          boolean_t               need_exclgrp = B_FALSE;
6907 7160          int                     need_rings = 0;
6908 7161          mac_group_t             *candidate_grp = NULL;
6909 7162          mac_client_impl_t       *gclient;
6910 7163          mac_resource_props_t    *gmrp;
6911 7164          boolean_t               txhw = mrp->mrp_mask & MRP_TX_RINGS;
6912 7165          boolean_t               unspec = mrp->mrp_mask & MRP_TXRINGS_UNSPEC;
6913 7166          boolean_t               isprimary;
6914 7167  
6915 7168          isprimary = mcip->mci_flent->fe_type & FLOW_PRIMARY_MAC;
     7169 +
6916 7170          /*
6917 7171           * When we come here for a VLAN on the primary (dladm create-vlan),
6918 7172           * we need to pair it along with the primary (to keep it consistent
6919 7173           * with the RX side). So, we check if the primary is already assigned
6920 7174           * to a group and return the group if so. The other way is also
6921 7175           * true, i.e. the VLAN is already created and now we are plumbing
6922 7176           * the primary.
6923 7177           */
6924 7178          if (!move && isprimary) {
6925 7179                  for (gclient = mip->mi_clients_list; gclient != NULL;
↓ open down ↓ 61 lines elided ↑ open up ↑
6987 7241                           * Select a candidate for replacement if we don't
6988 7242                           * get an exclusive group. A candidate group is one
6989 7243                           * that didn't ask for an exclusive group, but got
6990 7244                           * one and it has enough rings (combined with what
6991 7245                           * the default group can donate) for the new MAC
6992 7246                           * client.
6993 7247                           */
6994 7248                          if (grp->mrg_state == MAC_GROUP_STATE_RESERVED &&
6995 7249                              candidate_grp == NULL) {
6996 7250                                  gclient = MAC_GROUP_ONLY_CLIENT(grp);
6997      -                                if (gclient == NULL)
6998      -                                        gclient = mac_get_grp_primary(grp);
     7251 +                                VERIFY3P(gclient, !=, NULL);
6999 7252                                  gmrp = MCIP_RESOURCE_PROPS(gclient);
7000 7253                                  if (gclient->mci_share == 0 &&
7001 7254                                      (gmrp->mrp_mask & MRP_TX_RINGS) == 0 &&
7002 7255                                      (unspec ||
7003 7256                                      (grp->mrg_cur_count + defnrings) >=
7004 7257                                      need_rings)) {
7005 7258                                          candidate_grp = grp;
7006 7259                                  }
7007 7260                          }
7008 7261                          continue;
↓ open down ↓ 16 lines elided ↑ open up ↑
7025 7278          /* The default group */
7026 7279          if (i >= mip->mi_tx_group_count) {
7027 7280                  /*
7028 7281                   * If we need an exclusive group and have identified a
7029 7282                   * candidate group we switch the MAC client from the
7030 7283                   * candidate group to the default group and give the
7031 7284                   * candidate group to this client.
7032 7285                   */
7033 7286                  if (need_exclgrp && candidate_grp != NULL) {
7034 7287                          /*
7035      -                         * Switch the MAC client from the candidate group
7036      -                         * to the default group.
     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.
7037 7292                           */
7038 7293                          grp = candidate_grp;
7039 7294                          gclient = MAC_GROUP_ONLY_CLIENT(grp);
7040      -                        if (gclient == NULL)
7041      -                                gclient = mac_get_grp_primary(grp);
     7295 +                        VERIFY3P(gclient, !=, NULL);
7042 7296                          mac_tx_client_quiesce((mac_client_handle_t)gclient);
7043 7297                          mac_tx_switch_group(gclient, grp, defgrp);
7044 7298                          mac_tx_client_restart((mac_client_handle_t)gclient);
7045 7299  
7046 7300                          /*
7047 7301                           * Give the candidate group with the specified number
7048 7302                           * of rings to this MAC client.
7049 7303                           */
7050 7304                          ASSERT(grp->mrg_state == MAC_GROUP_STATE_REGISTERED);
7051 7305                          rv = mac_start_group(grp);
↓ open down ↓ 147 lines elided ↑ open up ↑
7199 7453          defgrp = MAC_DEFAULT_TX_GROUP(mip);
7200 7454          ASSERT(fgrp == flent->fe_tx_ring_group);
7201 7455  
7202 7456          if (fgrp == defgrp) {
7203 7457                  /*
7204 7458                   * If this is the primary we need to find any VLANs on
7205 7459                   * the primary and move them too.
7206 7460                   */
7207 7461                  mac_group_remove_client(fgrp, mcip);
7208 7462                  mac_tx_dismantle_soft_rings(fgrp, flent);
7209      -                if (mcip->mci_unicast->ma_nusers > 1) {
     7463 +                if (mac_check_macaddr_shared(mcip->mci_unicast)) {
7210 7464                          mgcp = fgrp->mrg_clients;
7211 7465                          while (mgcp != NULL) {
7212 7466                                  gmcip = mgcp->mgc_client;
7213 7467                                  mgcp = mgcp->mgc_next;
7214 7468                                  if (mcip->mci_unicast != gmcip->mci_unicast)
7215 7469                                          continue;
7216 7470                                  mac_tx_client_quiesce(
7217 7471                                      (mac_client_handle_t)gmcip);
7218 7472  
7219 7473                                  gflent = gmcip->mci_flent;
↓ open down ↓ 225 lines elided ↑ open up ↑
7445 7699          i_mac_perim_enter(mip);
7446 7700          mip->mi_state_flags |= MIS_NO_ACTIVE;
7447 7701          i_mac_perim_exit(mip);
7448 7702  }
7449 7703  
7450 7704  /*
7451 7705   * Walk the primary VLAN clients whenever the primary's rings property
7452 7706   * changes and update the mac_resource_props_t for the VLAN's client.
7453 7707   * We need to do this since we don't support setting these properties
7454 7708   * on the primary's VLAN clients, but the VLAN clients have to
7455      - * follow the primary w.r.t the rings property;
     7709 + * follow the primary w.r.t the rings property.
7456 7710   */
7457 7711  void
7458 7712  mac_set_prim_vlan_rings(mac_impl_t  *mip, mac_resource_props_t *mrp)
7459 7713  {
7460 7714          mac_client_impl_t       *vmcip;
7461 7715          mac_resource_props_t    *vmrp;
7462 7716  
7463 7717          for (vmcip = mip->mi_clients_list; vmcip != NULL;
7464 7718              vmcip = vmcip->mci_client_next) {
7465 7719                  if (!(vmcip->mci_flent->fe_type & FLOW_PRIMARY_MAC) ||
↓ open down ↓ 128 lines elided ↑ open up ↑
7594 7848           * all the required rings.
7595 7849           */
7596 7850          if (defgrp->mrg_cur_count < (modify + 1)) {
7597 7851                  for (i = start; i < end; i++) {
7598 7852                          if (rx_group) {
7599 7853                                  tgrp = &mip->mi_rx_groups[i];
7600 7854                                  if (tgrp == group || tgrp->mrg_state <
7601 7855                                      MAC_GROUP_STATE_RESERVED) {
7602 7856                                          continue;
7603 7857                                  }
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)
     7858 +                                if (i_mac_clients_hw(tgrp, MRP_RX_RINGS))
7610 7859                                          continue;
     7860 +                                mcip = tgrp->mrg_clients->mgc_client;
     7861 +                                VERIFY3P(mcip, !=, NULL);
7611 7862                                  if ((tgrp->mrg_cur_count +
7612 7863                                      defgrp->mrg_cur_count) < (modify + 1)) {
7613 7864                                          continue;
7614 7865                                  }
7615 7866                                  if (mac_rx_switch_group(mcip, tgrp,
7616 7867                                      defgrp) != 0) {
7617 7868                                          return (ENOSPC);
7618 7869                                  }
7619 7870                          } else {
7620 7871                                  tgrp = &mip->mi_tx_groups[i];
7621 7872                                  if (tgrp == group || tgrp->mrg_state <
7622 7873                                      MAC_GROUP_STATE_RESERVED) {
7623 7874                                          continue;
7624 7875                                  }
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)
     7876 +                                if (i_mac_clients_hw(tgrp, MRP_TX_RINGS))
7630 7877                                          continue;
     7878 +                                mcip = tgrp->mrg_clients->mgc_client;
     7879 +                                VERIFY3P(mcip, !=, NULL);
7631 7880                                  if ((tgrp->mrg_cur_count +
7632 7881                                      defgrp->mrg_cur_count) < (modify + 1)) {
7633 7882                                          continue;
7634 7883                                  }
7635 7884                                  /* OK, we can switch this to s/w */
7636 7885                                  mac_tx_client_quiesce(
7637 7886                                      (mac_client_handle_t)mcip);
7638 7887                                  mac_tx_switch_group(mcip, tgrp, defgrp);
7639 7888                                  mac_tx_client_restart(
7640 7889                                      (mac_client_handle_t)mcip);
↓ open down ↓ 249 lines elided ↑ open up ↑
7890 8139  
7891 8140          mpa->mpa_what = what;
7892 8141  
7893 8142          mac_pool_update(mpa);
7894 8143  }
7895 8144  
7896 8145  /*
7897 8146   * Set effective rings property. This could be called from datapath_setup/
7898 8147   * datapath_teardown or set-linkprop.
7899 8148   * 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
     8149 + * Additionally, for TX this could mean the default group has lost/gained
7901 8150   * some rings, so if the default group is reserved, we need to adjust the
7902 8151   * 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
     8152 + * with the non-default group, we just need to reset the effective props
7904 8153   * for the default group clients.
7905 8154   */
7906 8155  void
7907 8156  mac_set_rings_effective(mac_client_impl_t *mcip)
7908 8157  {
7909 8158          mac_impl_t              *mip = mcip->mci_mip;
7910 8159          mac_group_t             *grp;
7911 8160          mac_group_t             *defgrp;
7912 8161          flow_entry_t            *flent = mcip->mci_flent;
7913 8162          mac_resource_props_t    *emrp = MCIP_EFFECTIVE_PROPS(mcip);
↓ open down ↓ 109 lines elided ↑ open up ↑
8023 8272           */
8024 8273          if (rxhw && mip->mi_rxhwclnt_avail < 2)
8025 8274                  return (NULL);
8026 8275  
8027 8276          mac_addr = flent->fe_flow_desc.fd_dst_mac;
8028 8277          /*
8029 8278           * We call this when we are setting up the datapath for
8030 8279           * the first non-primary.
8031 8280           */
8032 8281          ASSERT(mip->mi_nactiveclients == 2);
     8282 +
8033 8283          /*
8034 8284           * OK, now we have the primary that needs to be relocated.
8035 8285           */
8036 8286          ngrp =  mac_reserve_rx_group(mcip, mac_addr, B_TRUE);
8037 8287          if (ngrp == NULL)
8038 8288                  return (NULL);
8039 8289          if (mac_rx_switch_group(mcip, defgrp, ngrp) != 0) {
8040 8290                  mac_stop_group(ngrp);
8041 8291                  return (NULL);
8042 8292          }
↓ open down ↓ 212 lines elided ↑ open up ↑
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX