Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
54 changes: 34 additions & 20 deletions usr/src/uts/common/io/i40e/i40e_gld.c
Original file line number Diff line number Diff line change
Expand Up @@ -40,13 +40,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))
Expand All @@ -59,9 +61,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;
}

Expand All @@ -70,20 +76,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 "
"%02x:%02x:%02x:%02x:%02x:%02x from unicast filter: %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;
}
Expand All @@ -109,12 +114,13 @@ i40e_group_remove_mac(void *arg, const uint8_t *mac_addr)
}

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;

Expand All @@ -133,32 +139,36 @@ 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 "
"%02x:%02x:%02x:%02x:%02x:%02x to unicast filter: %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;
}

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);
Expand Down Expand Up @@ -582,8 +592,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;

ASSERT3U(i40e->i40e_num_rx_groups, <=, I40E_MAX_NUM_RX_GROUPS);
infop->mgi_count = i40e->i40e_num_trqpairs_per_vsi;
Expand Down
5 changes: 3 additions & 2 deletions usr/src/uts/common/io/i40e/i40e_sw.h
Original file line number Diff line number Diff line change
Expand Up @@ -482,8 +482,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 {
Expand Down
78 changes: 68 additions & 10 deletions usr/src/uts/common/io/mac/mac.c
Original file line number Diff line number Diff line change
Expand Up @@ -4446,8 +4446,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;
Expand Down Expand Up @@ -4753,6 +4755,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
Expand Down Expand Up @@ -5490,6 +5514,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);
Expand All @@ -5511,7 +5541,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);

/*
Expand Down Expand Up @@ -5581,7 +5611,7 @@ mac_add_macaddr_vlan(mac_impl_t *mip, mac_group_t *group, uint8_t *addr,
map->ma_nusers = 0;

bail:
if (hw_vlan) {
if (hw_vlan && !MAC_GROUP_HW_MACVLAN(group)) {
int err2 = mac_group_remvlan(group, vid);

if (err2 != 0) {
Expand Down Expand Up @@ -5619,10 +5649,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);
Expand Down Expand Up @@ -5651,7 +5690,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
Expand Down Expand Up @@ -5750,19 +5790,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:
Expand Down
20 changes: 14 additions & 6 deletions usr/src/uts/common/io/mac/mac_datapath_setup.c
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@
*/
/*
* Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved.
* Copyright 2018 Joyent, Inc.
* Copyright 2019 Joyent, Inc.
* Copyright 2020 RackTop Systems.
*/

Expand Down Expand Up @@ -2451,20 +2451,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;

/*
Expand All @@ -2479,6 +2484,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 "
Expand Down Expand Up @@ -3104,6 +3110,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) {
Expand Down Expand Up @@ -3140,8 +3149,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);
}

Expand Down
7 changes: 7 additions & 0 deletions usr/src/uts/common/sys/mac_impl.h
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down Expand Up @@ -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 *);
Expand Down
Loading