diff options
author | Ryan Zezeski <rpz@joyent.com> | 2018-03-21 11:32:37 -0600 |
---|---|---|
committer | Trent Mick <trentm@gmail.com> | 2018-03-21 11:32:37 -0600 |
commit | dfdd41c82e118a3e754f1053348448e15bc06af2 (patch) | |
tree | 0897a7cbc7d20de728c1b1cd667064cc62d3864d | |
parent | 3d280bd5aa877a68b01b0b5dc7cb0f92843e8b41 (diff) | |
download | illumos-joyent-cr6587-OS-6769.tar.gz |
OS-6769 want i40e HW VLAN supportcr6587-OS-6769
-rw-r--r-- | usr/src/uts/common/io/i40e/i40e_gld.c | 64 | ||||
-rw-r--r-- | usr/src/uts/common/io/i40e/i40e_sw.h | 5 | ||||
-rw-r--r-- | usr/src/uts/common/io/mac/mac.c | 78 | ||||
-rw-r--r-- | usr/src/uts/common/io/mac/mac_datapath_setup.c | 20 | ||||
-rw-r--r-- | usr/src/uts/common/sys/mac_impl.h | 7 | ||||
-rw-r--r-- | usr/src/uts/common/sys/mac_provider.h | 32 |
6 files changed, 161 insertions, 45 deletions
diff --git a/usr/src/uts/common/io/i40e/i40e_gld.c b/usr/src/uts/common/io/i40e/i40e_gld.c index ccf814be0b..eea158ccdd 100644 --- a/usr/src/uts/common/io/i40e/i40e_gld.c +++ b/usr/src/uts/common/io/i40e/i40e_gld.c @@ -11,7 +11,7 @@ /* * Copyright 2015 OmniTI Computer Consulting, Inc. All rights reserved. - * Copyright (c) 2018, Joyent, Inc. + * Copyright 2019 Joyent, Inc. * Copyright 2017 Tegile Systems, Inc. All rights reserved. */ @@ -37,13 +37,15 @@ char *i40e_priv_props[] = { }; static int -i40e_group_remove_mac(void *arg, const uint8_t *mac_addr) +i40e_group_remove_macvlan(mac_group_driver_t gdriver, const uint8_t *mac_addr, + uint16_t vid) { - i40e_rx_group_t *rxg = arg; + i40e_rx_group_t *rxg = (i40e_rx_group_t *)gdriver; i40e_t *i40e = rxg->irg_i40e; struct i40e_aqc_remove_macvlan_element_data filt; struct i40e_hw *hw = &i40e->i40e_hw_space; - int ret, i, last; + int ret; + uint_t i, last; i40e_uaddr_t *iua; if (I40E_IS_MULTICAST(mac_addr)) @@ -56,9 +58,13 @@ i40e_group_remove_mac(void *arg, const uint8_t *mac_addr) goto done; } + vid = (vid == MAC_VLAN_UNTAGGED ? 0 : vid); + for (i = 0; i < i40e->i40e_resources.ifr_nmacfilt_used; i++) { - if (bcmp(mac_addr, i40e->i40e_uaddrs[i].iua_mac, - ETHERADDRL) == 0) + iua = &i40e->i40e_uaddrs[i]; + + if (bcmp(mac_addr, iua->iua_mac, ETHERADDRL) == 0 && + vid == iua->iua_vid) break; } @@ -67,20 +73,19 @@ i40e_group_remove_mac(void *arg, const uint8_t *mac_addr) goto done; } - iua = &i40e->i40e_uaddrs[i]; ASSERT(i40e->i40e_resources.ifr_nmacfilt_used > 0); bzero(&filt, sizeof (filt)); bcopy(mac_addr, filt.mac_addr, ETHERADDRL); - filt.flags = I40E_AQC_MACVLAN_DEL_PERFECT_MATCH | - I40E_AQC_MACVLAN_DEL_IGNORE_VLAN; + filt.vlan_tag = vid; + filt.flags = I40E_AQC_MACVLAN_DEL_PERFECT_MATCH; if (i40e_aq_remove_macvlan(hw, iua->iua_vsi, &filt, 1, NULL) != I40E_SUCCESS) { - i40e_error(i40e, "failed to remove mac address " - "%2x:%2x:%2x:%2x:%2x:%2x from unicast filter: %d", + i40e_error(i40e, "failed to remove {MAC,VLAN} filter " + "{%2x:%2x:%2x:%2x:%2x:%2x,%u}: %d", mac_addr[0], mac_addr[1], mac_addr[2], mac_addr[3], - mac_addr[4], mac_addr[5], filt.error_code); + mac_addr[4], mac_addr[5], vid, filt.error_code); ret = EIO; goto done; } @@ -106,12 +111,13 @@ done: } static int -i40e_group_add_mac(void *arg, const uint8_t *mac_addr) +i40e_group_add_macvlan(mac_group_driver_t gdriver, const uint8_t *mac_addr, + uint16_t vid) { - i40e_rx_group_t *rxg = arg; + i40e_rx_group_t *rxg = (i40e_rx_group_t *)gdriver; i40e_t *i40e = rxg->irg_i40e; struct i40e_hw *hw = &i40e->i40e_hw_space; - int i, ret; + int ret; i40e_uaddr_t *iua; struct i40e_aqc_add_macvlan_element_data filt; @@ -130,25 +136,28 @@ i40e_group_add_mac(void *arg, const uint8_t *mac_addr) goto done; } - for (i = 0; i < i40e->i40e_resources.ifr_nmacfilt_used; i++) { - if (bcmp(mac_addr, i40e->i40e_uaddrs[i].iua_mac, - ETHERADDRL) == 0) { + for (uint_t i = 0; i < i40e->i40e_resources.ifr_nmacfilt_used; i++) { + iua = &i40e->i40e_uaddrs[i]; + + if (bcmp(mac_addr, iua->iua_mac, ETHERADDRL) == 0 && + vid == iua->iua_vid) { ret = EEXIST; goto done; } } + vid = (vid == MAC_VLAN_UNTAGGED) ? 0 : vid; bzero(&filt, sizeof (filt)); bcopy(mac_addr, filt.mac_addr, ETHERADDRL); - filt.flags = I40E_AQC_MACVLAN_ADD_PERFECT_MATCH | - I40E_AQC_MACVLAN_ADD_IGNORE_VLAN; + filt.vlan_tag = vid; + filt.flags = I40E_AQC_MACVLAN_ADD_PERFECT_MATCH; if ((ret = i40e_aq_add_macvlan(hw, rxg->irg_vsi_seid, &filt, 1, NULL)) != I40E_SUCCESS) { - i40e_error(i40e, "failed to add mac address " - "%2x:%2x:%2x:%2x:%2x:%2x to unicast filter: %d", + i40e_error(i40e, "failed to add {MAC,VLAN} filter " + "{%2x:%2x:%2x:%2x:%2x:%2x,%u}: %d", mac_addr[0], mac_addr[1], mac_addr[2], mac_addr[3], - mac_addr[4], mac_addr[5], ret); + mac_addr[4], mac_addr[5], vid, ret); ret = EIO; goto done; } @@ -156,6 +165,7 @@ i40e_group_add_mac(void *arg, const uint8_t *mac_addr) iua = &i40e->i40e_uaddrs[i40e->i40e_resources.ifr_nmacfilt_used]; bcopy(mac_addr, iua->iua_mac, ETHERADDRL); iua->iua_vsi = rxg->irg_vsi_seid; + iua->iua_vid = vid; i40e->i40e_resources.ifr_nmacfilt_used++; ASSERT(i40e->i40e_resources.ifr_nmacfilt_used <= i40e->i40e_resources.ifr_nmacfilt); @@ -562,8 +572,12 @@ i40e_fill_rx_group(void *arg, mac_ring_type_t rtype, const int index, infop->mgi_driver = (mac_group_driver_t)rxg; infop->mgi_start = NULL; infop->mgi_stop = NULL; - infop->mgi_addmac = i40e_group_add_mac; - infop->mgi_remmac = i40e_group_remove_mac; + infop->mgi_addmac = NULL; + infop->mgi_remmac = NULL; + infop->mgi_addvlan = NULL; + infop->mgi_remvlan = NULL; + infop->mgi_add_macvlan = i40e_group_add_macvlan; + infop->mgi_rem_macvlan = i40e_group_remove_macvlan; ASSERT(i40e->i40e_num_rx_groups <= I40E_GROUP_MAX); infop->mgi_count = i40e->i40e_num_trqpairs_per_vsi; diff --git a/usr/src/uts/common/io/i40e/i40e_sw.h b/usr/src/uts/common/io/i40e/i40e_sw.h index 7b0ff20c95..27d78ab685 100644 --- a/usr/src/uts/common/io/i40e/i40e_sw.h +++ b/usr/src/uts/common/io/i40e/i40e_sw.h @@ -477,8 +477,9 @@ typedef struct i40e_rx_data { * duplicate that information. */ typedef struct i40e_uaddr { - uint8_t iua_mac[ETHERADDRL]; - int iua_vsi; + uint8_t iua_mac[ETHERADDRL]; + uint16_t iua_vid; + int iua_vsi; } i40e_uaddr_t; typedef struct i40e_maddr { diff --git a/usr/src/uts/common/io/mac/mac.c b/usr/src/uts/common/io/mac/mac.c index e748e6d57b..1e1b521c74 100644 --- a/usr/src/uts/common/io/mac/mac.c +++ b/usr/src/uts/common/io/mac/mac.c @@ -4404,8 +4404,10 @@ mac_init_rings(mac_impl_t *mip, mac_ring_type_t rtype) * MAC addresses. */ if (rtype == MAC_RING_TYPE_RX && - (group_info.mgi_addmac == NULL || - group_info.mgi_remmac == NULL)) { + ((group_info.mgi_addmac == NULL || + group_info.mgi_remmac == NULL) && + (group_info.mgi_add_macvlan == NULL && + group_info.mgi_rem_macvlan == NULL))) { DTRACE_PROBE1(mac__init__rings__no__mac__filter, char *, mip->mi_name); err = EINVAL; @@ -4711,6 +4713,28 @@ mac_group_remmac(mac_group_t *group, const uint8_t *addr) return (group->mrg_info.mgi_remmac(group->mrg_info.mgi_driver, addr)); } +int +mac_group_add_macvlan(mac_group_t *group, const uint8_t *addr, uint16_t vid) +{ + mac_group_info_t *info = &group->mrg_info; + + ASSERT3S(group->mrg_type, ==, MAC_RING_TYPE_RX); + ASSERT3P(info->mgi_add_macvlan, !=, NULL); + + return (info->mgi_add_macvlan(info->mgi_driver, addr, vid)); +} + +int +mac_group_rem_macvlan(mac_group_t *group, const uint8_t *addr, uint16_t vid) +{ + mac_group_info_t *info = &group->mrg_info; + + ASSERT3S(group->mrg_type, ==, MAC_RING_TYPE_RX); + ASSERT3P(info->mgi_rem_macvlan, !=, NULL); + + return (info->mgi_rem_macvlan(info->mgi_driver, addr, vid)); +} + /* * This is the entry point for packets transmitted through the bridge * code. If no bridge is in place, mac_ring_tx() transmits via the tx @@ -5422,6 +5446,12 @@ mac_add_macaddr_vlan(mac_impl_t *mip, mac_group_t *group, uint8_t *addr, goto bail; hw_vlan = B_TRUE; + } else if (MAC_GROUP_HW_MACVLAN(group) && + map->ma_type != MAC_ADDRESS_TYPE_UNICAST_PROMISC) { + if ((err = mac_group_add_macvlan(group, addr, vid)) != 0) + goto bail; + + hw_mac = B_TRUE; } VERIFY3S(map->ma_nusers, >=, 0); @@ -5443,7 +5473,7 @@ mac_add_macaddr_vlan(mac_impl_t *mip, mac_group_t *group, uint8_t *addr, /* * Activate this MAC address by adding it to the reserved group. */ - if (group != NULL) { + if (group != NULL && !MAC_GROUP_HW_MACVLAN(group)) { err = mac_group_addmac(group, (const uint8_t *)addr); /* @@ -5508,7 +5538,7 @@ mac_add_macaddr_vlan(mac_impl_t *mip, mac_group_t *group, uint8_t *addr, } bail: - if (hw_vlan) { + if (hw_vlan && !MAC_GROUP_HW_MACVLAN(group)) { int err2 = mac_group_remvlan(group, vid); if (err2 != 0) { @@ -5546,10 +5576,19 @@ mac_remove_macaddr_vlan(mac_address_t *map, uint16_t vid) VERIFY3P(mvp, !=, NULL); } + /* + * Try to remove the HW filter first. If that fails then + * leave the MAC state alone. + */ if (MAC_GROUP_HW_VLAN(group) && map->ma_type == MAC_ADDRESS_TYPE_UNICAST_CLASSIFIED && - ((err = mac_group_remvlan(group, vid)) != 0)) + ((err = mac_group_remvlan(group, vid)) != 0)) { + return (err); + } else if (MAC_GROUP_HW_MACVLAN(group) && + map->ma_type == MAC_ADDRESS_TYPE_UNICAST_CLASSIFIED && + ((err = mac_group_rem_macvlan(group, map->ma_addr, vid)) != 0)) { return (err); + } if (mvp != NULL) mac_rem_vlan(map, mvp); @@ -5576,7 +5615,8 @@ mac_remove_macaddr_vlan(mac_address_t *map, uint16_t vid) if (group == NULL) return (0); - if ((err = mac_group_remmac(group, map->ma_addr)) != 0) { + if (!MAC_GROUP_HW_MACVLAN(group) && + (err = mac_group_remmac(group, map->ma_addr)) != 0) { if (vid == VLAN_ID_NONE) map->ma_untagged = B_TRUE; else @@ -5663,19 +5703,37 @@ mac_update_macaddr(mac_address_t *map, uint8_t *mac_addr) /* * Need to replace the MAC address associated with a group. */ - err = mac_group_remmac(map->ma_group, map->ma_addr); + if (MAC_GROUP_HW_MACVLAN(map->ma_group)) { + err = mac_group_rem_macvlan(map->ma_group, map->ma_addr, + MAC_VLAN_UNTAGGED); + } else { + err = mac_group_remmac(map->ma_group, map->ma_addr); + } + if (err != 0) return (err); - err = mac_group_addmac(map->ma_group, mac_addr); + if (MAC_GROUP_HW_MACVLAN(map->ma_group)) { + err = mac_group_add_macvlan(map->ma_group, mac_addr, + MAC_VLAN_UNTAGGED); + } else { + err = mac_group_addmac(map->ma_group, mac_addr); + } /* * Failure hints hardware error. The MAC layer needs to * have error notification facility to handle this. * Now, simply try to restore the value. */ - if (err != 0) - (void) mac_group_addmac(map->ma_group, map->ma_addr); + if (err != 0) { + if (MAC_GROUP_HW_MACVLAN(map->ma_group)) { + (void) mac_group_add_macvlan(map->ma_group, + map->ma_addr, MAC_VLAN_UNTAGGED); + } else { + (void) mac_group_addmac(map->ma_group, + map->ma_addr); + } + } break; case MAC_ADDRESS_TYPE_UNICAST_PROMISC: diff --git a/usr/src/uts/common/io/mac/mac_datapath_setup.c b/usr/src/uts/common/io/mac/mac_datapath_setup.c index 3697d888e7..7728ea2c9f 100644 --- a/usr/src/uts/common/io/mac/mac_datapath_setup.c +++ b/usr/src/uts/common/io/mac/mac_datapath_setup.c @@ -20,7 +20,7 @@ */ /* * Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved. - * Copyright 2018 Joyent, Inc. + * Copyright 2019 Joyent, Inc. */ #include <sys/types.h> @@ -2454,20 +2454,25 @@ mac_rx_srs_group_setup(mac_client_impl_t *mcip, flow_entry_t *flent, switch (ring->mr_state) { case MR_INUSE: - case MR_FREE: + case MR_FREE: { + boolean_t hw_vlan; + if (ring->mr_srs != NULL) break; if (ring->mr_state != MR_INUSE) (void) mac_start_ring(ring); + hw_vlan = MAC_GROUP_HW_VLAN(rx_group) || + MAC_GROUP_HW_MACVLAN(rx_group); + /* * If a client requires SW VLAN * filtering or has no unicast address * then we don't create any HW ring * SRSes. */ - if ((!MAC_GROUP_HW_VLAN(rx_group) && - vid != VLAN_ID_NONE) || no_unicast) + if ((!hw_vlan && vid != VLAN_ID_NONE) || + no_unicast) break; /* @@ -2482,6 +2487,7 @@ mac_rx_srs_group_setup(mac_client_impl_t *mcip, flow_entry_t *flent, fanout_type | link_type, mac_rx_deliver, mcip, NULL, ring); break; + } default: cmn_err(CE_PANIC, "srs_setup: mcip = %p " @@ -3107,6 +3113,9 @@ mac_datapath_setup(mac_client_impl_t *mcip, flow_entry_t *flent, * SRSes over the default group. */ if (rgroup != NULL) { + boolean_t hw_vlan = MAC_GROUP_HW_VLAN(rgroup) || + MAC_GROUP_HW_MACVLAN(rgroup); + if (rgroup != default_rgroup) { if (default_rgroup->mrg_state == MAC_GROUP_STATE_RESERVED) { @@ -3143,8 +3152,7 @@ mac_datapath_setup(mac_client_impl_t *mcip, flow_entry_t *flent, * classification. */ if (rgroup->mrg_state == MAC_GROUP_STATE_RESERVED && - ((!MAC_GROUP_HW_VLAN(rgroup) && vid != VLAN_ID_NONE) || - no_unicast)) { + ((!hw_vlan && vid != VLAN_ID_NONE) || no_unicast)) { mac_rx_switch_grp_to_sw(rgroup); } diff --git a/usr/src/uts/common/sys/mac_impl.h b/usr/src/uts/common/sys/mac_impl.h index 26c535fb42..85e2d6001c 100644 --- a/usr/src/uts/common/sys/mac_impl.h +++ b/usr/src/uts/common/sys/mac_impl.h @@ -264,6 +264,11 @@ typedef struct mac_grp_client { ((g)->mrg_info.mgi_addvlan != NULL) && \ ((g)->mrg_info.mgi_remvlan != NULL)) +#define MAC_GROUP_HW_MACVLAN(g) \ + (((g) != NULL) && \ + ((g)->mrg_info.mgi_add_macvlan != NULL) && \ + ((g)->mrg_info.mgi_rem_macvlan != NULL)) + /* * Common ring group data structure for ring control and management. * The entire structure is SL protected. @@ -732,6 +737,8 @@ extern int mac_group_addmac(mac_group_t *, const uint8_t *); extern int mac_group_remmac(mac_group_t *, const uint8_t *); extern int mac_group_addvlan(mac_group_t *, uint16_t); extern int mac_group_remvlan(mac_group_t *, uint16_t); +extern int mac_group_add_macvlan(mac_group_t *, const uint8_t *, uint16_t); +extern int mac_group_rem_macvlan(mac_group_t *, const uint8_t *, uint16_t); extern int mac_rx_group_add_flow(mac_client_impl_t *, flow_entry_t *, mac_group_t *); extern mblk_t *mac_hwring_tx(mac_ring_handle_t, mblk_t *); diff --git a/usr/src/uts/common/sys/mac_provider.h b/usr/src/uts/common/sys/mac_provider.h index 2dea3a4758..7c975b3c6f 100644 --- a/usr/src/uts/common/sys/mac_provider.h +++ b/usr/src/uts/common/sys/mac_provider.h @@ -21,7 +21,7 @@ /* * Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved. - * Copyright (c) 2018, Joyent, Inc. + * Copyright 2019 Joyent, Inc. */ #ifndef _SYS_MAC_PROVIDER_H @@ -437,6 +437,10 @@ typedef int (*mac_add_mac_addr_t)(void *, const uint8_t *); typedef int (*mac_rem_mac_addr_t)(void *, const uint8_t *); typedef int (*mac_add_vlan_filter_t)(mac_group_driver_t, uint16_t); typedef int (*mac_rem_vlan_filter_t)(mac_group_driver_t, uint16_t); +typedef int (*mac_add_mv_filter_t)(mac_group_driver_t, const uint8_t *, + uint16_t); +typedef int (*mac_rem_mv_filter_t)(mac_group_driver_t, const uint8_t *, + uint16_t); struct mac_group_info_s { mac_group_driver_t mgi_driver; /* Driver reference */ @@ -445,11 +449,35 @@ struct mac_group_info_s { uint_t mgi_count; /* Count of rings */ mac_intr_t mgi_intr; /* Optional per-group intr */ - /* Only used for Rx groups */ + /* + * The following six callbacks apply only to Rx groups. There + * are four different possible states for these callbacks. + * + * 1. None of them are set because the driver doesn't + * implement MAC_VIRT_LEVEL1. + * + * 2. Only the mgi_{add,rem}mac callbacks are set because the + * driver only supports unicast address HW filtering/steering. + * + * 3. Both the mgi_{add,rem}mac and mgi_{add,rem}vlan callback + * pairs are set. This driver supports both unicast address + * filtering/steering as well as VLAN filtering/steering. + * However, these filters are programmed separately and + * thus there are two separate callbacks. + * + * 4. Only the mgi_{add,rem}_macvlan callbacks are set. This + * driver supports exact match filtering/steering on + * {MAC,VLAN} tuples. When a driver supports this type of + * API we prefer it over the separate unicast + VLAN API. + * When these callbacks are set the other callbacks should + * be NULL. + */ mac_add_mac_addr_t mgi_addmac; /* Add a MAC address */ mac_rem_mac_addr_t mgi_remmac; /* Remove a MAC address */ mac_add_vlan_filter_t mgi_addvlan; /* Add a VLAN filter */ mac_rem_vlan_filter_t mgi_remvlan; /* Remove a VLAN filter */ + mac_add_mv_filter_t mgi_add_macvlan; /* Add {MAC,VLAN} filter */ + mac_rem_mv_filter_t mgi_rem_macvlan; /* Remove {MAC,VLAN} filter */ }; /* |