ice: Add ability for PF admin to enable VF VLAN pruning

VFs by default are able to see all tagged traffic regardless of trust
and VLAN filters. Based on legacy devices (i.e. ixgbe, i40e), customers
expect VFs to receive all VLAN tagged traffic with a matching
destination MAC.

Add an ethtool private flag 'vf-vlan-pruning' and set the default to
off so VFs will receive all VLAN traffic directed towards them. When
the flag is turned on, VF will only be able to receive untagged
traffic or traffic with VLAN tags it has created interfaces for.

Also, the flag cannot be changed while any VFs are allocated. This was
done to simplify the implementation. So, if this flag is needed, then
the PF admin must enable it. If the user tries to enable the flag while
VFs are active, then print an unsupported message with the
vf-vlan-pruning flag included. In case multiple flags were specified, this
makes it clear to the user which flag failed.

Signed-off-by: Brett Creeley <brett.creeley@intel.com>
Tested-by: Gurucharan G <gurucharanx.g@intel.com>
Signed-off-by: Tony Nguyen <anthony.l.nguyen@intel.com>
This commit is contained in:
Brett Creeley 2021-12-02 08:38:52 -08:00 committed by Tony Nguyen
parent cbc8b5645a
commit f1da5a0866
4 changed files with 40 additions and 2 deletions

View File

@ -485,6 +485,7 @@ enum ice_pf_flags {
ICE_FLAG_LEGACY_RX,
ICE_FLAG_VF_TRUE_PROMISC_ENA,
ICE_FLAG_MDD_AUTO_RESET_VF,
ICE_FLAG_VF_VLAN_PRUNING,
ICE_FLAG_LINK_LENIENT_MODE_ENA,
ICE_PF_FLAGS_NBITS /* must be last */
};

View File

@ -164,6 +164,7 @@ static const struct ice_priv_flag ice_gstrings_priv_flags[] = {
ICE_PRIV_FLAG("vf-true-promisc-support",
ICE_FLAG_VF_TRUE_PROMISC_ENA),
ICE_PRIV_FLAG("mdd-auto-reset-vf", ICE_FLAG_MDD_AUTO_RESET_VF),
ICE_PRIV_FLAG("vf-vlan-pruning", ICE_FLAG_VF_VLAN_PRUNING),
ICE_PRIV_FLAG("legacy-rx", ICE_FLAG_LEGACY_RX),
};
@ -1295,6 +1296,14 @@ static int ice_set_priv_flags(struct net_device *netdev, u32 flags)
change_bit(ICE_FLAG_VF_TRUE_PROMISC_ENA, pf->flags);
ret = -EAGAIN;
}
if (test_bit(ICE_FLAG_VF_VLAN_PRUNING, change_flags) &&
pf->num_alloc_vfs) {
dev_err(dev, "vf-vlan-pruning: VLAN pruning cannot be changed while VFs are active.\n");
/* toggle bit back to previous state */
change_bit(ICE_FLAG_VF_VLAN_PRUNING, pf->flags);
ret = -EOPNOTSUPP;
}
ethtool_exit:
clear_bit(ICE_FLAG_ETHTOOL_CTXT, pf->flags);
return ret;

View File

@ -43,7 +43,6 @@ void ice_vf_vsi_init_vlan_ops(struct ice_vsi *vsi)
/* outer VLAN ops regardless of port VLAN config */
vlan_ops->add_vlan = ice_vsi_add_vlan;
vlan_ops->ena_rx_filtering = ice_vsi_ena_rx_vlan_filtering;
vlan_ops->dis_rx_filtering = ice_vsi_dis_rx_vlan_filtering;
vlan_ops->ena_tx_filtering = ice_vsi_ena_tx_vlan_filtering;
vlan_ops->dis_tx_filtering = ice_vsi_dis_tx_vlan_filtering;
@ -51,6 +50,8 @@ void ice_vf_vsi_init_vlan_ops(struct ice_vsi *vsi)
if (ice_vf_is_port_vlan_ena(vf)) {
/* setup outer VLAN ops */
vlan_ops->set_port_vlan = ice_vsi_set_outer_port_vlan;
vlan_ops->ena_rx_filtering =
ice_vsi_ena_rx_vlan_filtering;
/* setup inner VLAN ops */
vlan_ops = &vsi->inner_vlan_ops;
@ -61,6 +62,12 @@ void ice_vf_vsi_init_vlan_ops(struct ice_vsi *vsi)
vlan_ops->ena_insertion = ice_vsi_ena_inner_insertion;
vlan_ops->dis_insertion = ice_vsi_dis_inner_insertion;
} else {
if (!test_bit(ICE_FLAG_VF_VLAN_PRUNING, pf->flags))
vlan_ops->ena_rx_filtering = noop_vlan;
else
vlan_ops->ena_rx_filtering =
ice_vsi_ena_rx_vlan_filtering;
vlan_ops->del_vlan = ice_vsi_del_vlan;
vlan_ops->ena_stripping = ice_vsi_ena_outer_stripping;
vlan_ops->dis_stripping = ice_vsi_dis_outer_stripping;
@ -80,14 +87,21 @@ void ice_vf_vsi_init_vlan_ops(struct ice_vsi *vsi)
/* inner VLAN ops regardless of port VLAN config */
vlan_ops->add_vlan = ice_vsi_add_vlan;
vlan_ops->ena_rx_filtering = ice_vsi_ena_rx_vlan_filtering;
vlan_ops->dis_rx_filtering = ice_vsi_dis_rx_vlan_filtering;
vlan_ops->ena_tx_filtering = ice_vsi_ena_tx_vlan_filtering;
vlan_ops->dis_tx_filtering = ice_vsi_dis_tx_vlan_filtering;
if (ice_vf_is_port_vlan_ena(vf)) {
vlan_ops->set_port_vlan = ice_vsi_set_inner_port_vlan;
vlan_ops->ena_rx_filtering =
ice_vsi_ena_rx_vlan_filtering;
} else {
if (!test_bit(ICE_FLAG_VF_VLAN_PRUNING, pf->flags))
vlan_ops->ena_rx_filtering = noop_vlan;
else
vlan_ops->ena_rx_filtering =
ice_vsi_ena_rx_vlan_filtering;
vlan_ops->del_vlan = ice_vsi_del_vlan;
vlan_ops->ena_stripping = ice_vsi_ena_inner_stripping;
vlan_ops->dis_stripping = ice_vsi_dis_inner_stripping;

View File

@ -807,6 +807,11 @@ static int ice_vf_rebuild_host_vlan_cfg(struct ice_vf *vf, struct ice_vsi *vsi)
return err;
}
err = vlan_ops->ena_rx_filtering(vsi);
if (err)
dev_warn(dev, "failed to enable Rx VLAN filtering for VF %d VSI %d during VF rebuild, error %d\n",
vf->vf_id, vsi->idx, err);
return 0;
}
@ -1793,6 +1798,7 @@ static void ice_vc_notify_vf_reset(struct ice_vf *vf)
*/
static int ice_init_vf_vsi_res(struct ice_vf *vf)
{
struct ice_vsi_vlan_ops *vlan_ops;
struct ice_pf *pf = vf->pf;
u8 broadcast[ETH_ALEN];
struct ice_vsi *vsi;
@ -1813,6 +1819,14 @@ static int ice_init_vf_vsi_res(struct ice_vf *vf)
goto release_vsi;
}
vlan_ops = ice_get_compat_vsi_vlan_ops(vsi);
err = vlan_ops->ena_rx_filtering(vsi);
if (err) {
dev_warn(dev, "Failed to enable Rx VLAN filtering for VF %d\n",
vf->vf_id);
goto release_vsi;
}
eth_broadcast_addr(broadcast);
err = ice_fltr_add_mac(vsi, broadcast, ICE_FWD_TO_VSI);
if (err) {