ice: Add ability for PF admin to enable VF VLAN pruning
authorBrett Creeley <brett.creeley@intel.com>
Thu, 2 Dec 2021 16:38:52 +0000 (08:38 -0800)
committerTony Nguyen <anthony.l.nguyen@intel.com>
Wed, 9 Feb 2022 17:24:45 +0000 (09:24 -0800)
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>
drivers/net/ethernet/intel/ice/ice.h
drivers/net/ethernet/intel/ice/ice_ethtool.c
drivers/net/ethernet/intel/ice/ice_vf_vsi_vlan_ops.c
drivers/net/ethernet/intel/ice/ice_virtchnl_pf.c

index 55f32fca619b6470d1464fa4e03e564a584aa4ac..6a710c209707c07b3acd796a68d378b88ca226fe 100644 (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 */
 };
index e2e3ef7fba7fc217768548f235a71f47c6c729cf..28ead0b4712fae319d65749564f54d40128c3c33 100644 (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;
index 4be29f97365c11e6ae8c0c5d89ae551d921d81d0..39f2d36cabba3b7acecc259867bfc9512b343a90 100644 (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;
index 9c43a7c8a45f4e3ef46f40d3ee72fbecd670b49c..02a8c15d2bf3353627cab802154f9b390818be8e 100644 (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) {