summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--usr/src/uts/common/io/i40e/i40e_gld.c64
-rw-r--r--usr/src/uts/common/io/i40e/i40e_sw.h5
-rw-r--r--usr/src/uts/common/io/mac/mac.c78
-rw-r--r--usr/src/uts/common/io/mac/mac_datapath_setup.c20
-rw-r--r--usr/src/uts/common/sys/mac_impl.h7
-rw-r--r--usr/src/uts/common/sys/mac_provider.h32
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 */
};
/*