Skip to content

Commit

Permalink
ice: Add outer_vlan_ops and VSI specific VLAN ops implementations
Browse files Browse the repository at this point in the history
Add a new outer_vlan_ops member to the ice_vsi structure as outer VLAN
ops are only available when the device is in Double VLAN Mode (DVM).
Depending on the VSI type, the requirements for what operations to
use/allow differ.

By default all VSI's have unsupported inner and outer VSI VLAN ops. This
implementation was chosen to prevent unexpected crashes due to null
pointer dereferences. Instead, if a VSI calls an unsupported op, it will
just return -EOPNOTSUPP.

Add implementations to support modifying outer VLAN fields for VSI
context. This includes the ability to modify VLAN stripping, insertion,
and the port VLAN based on the outer VLAN handling fields of the VSI
context.

These functions should only ever be used if DVM is enabled because that
means the firmware supports the outer VLAN fields in the VSI context. If
the device is in DVM, then always use the outer_vlan_ops, else use the
vlan_ops since the device is in Single VLAN Mode (SVM).

Also, move adding the untagged VLAN 0 filter from ice_vsi_setup() to
ice_vsi_vlan_setup() as the latter function is specific to the PF and
all other VSI types that need an untagged VLAN 0 filter already do this
in their specific flows. Without this change, Flow Director is failing
to initialize because it does not implement any VSI VLAN ops.

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>
  • Loading branch information
Brett Creeley authored and Tony Nguyen committed Feb 9, 2022
1 parent 7bd527a commit c31af68
Show file tree
Hide file tree
Showing 16 changed files with 813 additions and 86 deletions.
9 changes: 7 additions & 2 deletions drivers/net/ethernet/intel/ice/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ ice-y := ice_main.o \
ice_txrx_lib.o \
ice_txrx.o \
ice_fltr.o \
ice_pf_vsi_vlan_ops.o \
ice_vsi_vlan_ops.o \
ice_vsi_vlan_lib.o \
ice_fdir.o \
Expand All @@ -31,8 +32,12 @@ ice-y := ice_main.o \
ice_ethtool.o \
ice_repr.o \
ice_tc_lib.o
ice-$(CONFIG_PCI_IOV) += ice_virtchnl_allowlist.o
ice-$(CONFIG_PCI_IOV) += ice_virtchnl_pf.o ice_sriov.o ice_virtchnl_fdir.o
ice-$(CONFIG_PCI_IOV) += \
ice_virtchnl_allowlist.o \
ice_virtchnl_fdir.o \
ice_sriov.o \
ice_vf_vsi_vlan_ops.o \
ice_virtchnl_pf.o
ice-$(CONFIG_PTP_1588_CLOCK) += ice_ptp.o ice_ptp_hw.o
ice-$(CONFIG_DCB) += ice_dcb.o ice_dcb_nl.o ice_dcb_lib.o
ice-$(CONFIG_RFS_ACCEL) += ice_arfs.o
Expand Down
3 changes: 2 additions & 1 deletion drivers/net/ethernet/intel/ice/ice.h
Original file line number Diff line number Diff line change
Expand Up @@ -369,7 +369,8 @@ struct ice_vsi {
u8 irqs_ready:1;
u8 current_isup:1; /* Sync 'link up' logging */
u8 stat_offsets_loaded:1;
struct ice_vsi_vlan_ops vlan_ops;
struct ice_vsi_vlan_ops inner_vlan_ops;
struct ice_vsi_vlan_ops outer_vlan_ops;
u16 num_vlan;

/* queue information */
Expand Down
5 changes: 4 additions & 1 deletion drivers/net/ethernet/intel/ice/ice_eswitch.c
Original file line number Diff line number Diff line change
Expand Up @@ -115,9 +115,12 @@ static int ice_eswitch_setup_env(struct ice_pf *pf)
struct ice_vsi *uplink_vsi = pf->switchdev.uplink_vsi;
struct net_device *uplink_netdev = uplink_vsi->netdev;
struct ice_vsi *ctrl_vsi = pf->switchdev.control_vsi;
struct ice_vsi_vlan_ops *vlan_ops;
bool rule_added = false;

ctrl_vsi->vlan_ops.dis_stripping(ctrl_vsi);
vlan_ops = ice_get_compat_vsi_vlan_ops(ctrl_vsi);
if (vlan_ops->dis_stripping(ctrl_vsi))
return -ENODEV;

ice_remove_vsi_fltr(&pf->hw, uplink_vsi->idx);

Expand Down
111 changes: 99 additions & 12 deletions drivers/net/ethernet/intel/ice/ice_lib.c
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
#include "ice_fltr.h"
#include "ice_dcb_lib.h"
#include "ice_devlink.h"
#include "ice_vsi_vlan_ops.h"

/**
* ice_vsi_type_str - maps VSI type enum to string equivalents
Expand Down Expand Up @@ -2458,17 +2459,6 @@ ice_vsi_setup(struct ice_pf *pf, struct ice_port_info *pi,
if (ret)
goto unroll_vector_base;

/* Always add VLAN ID 0 switch rule by default. This is needed
* in order to allow all untagged and 0 tagged priority traffic
* if Rx VLAN pruning is enabled. Also there are cases where we
* don't get the call to add VLAN 0 via ice_vlan_rx_add_vid()
* so this handles those cases (i.e. adding the PF to a bridge
* without the 8021q module loaded).
*/
ret = ice_vsi_add_vlan_zero(vsi);
if (ret)
goto unroll_clear_rings;

ice_vsi_map_rings_to_vectors(vsi);

/* ICE_VSI_CTRL does not need RSS so skip RSS processing */
Expand Down Expand Up @@ -3918,13 +3908,110 @@ int ice_set_link(struct ice_vsi *vsi, bool ena)
/**
* ice_vsi_add_vlan_zero - add VLAN 0 filter(s) for this VSI
* @vsi: VSI used to add VLAN filters
*
* In Single VLAN Mode (SVM), single VLAN filters via ICE_SW_LKUP_VLAN are based
* on the inner VLAN ID, so the VLAN TPID (i.e. 0x8100 or 0x888a8) doesn't
* matter. In Double VLAN Mode (DVM), outer/single VLAN filters via
* ICE_SW_LKUP_VLAN are based on the outer/single VLAN ID + VLAN TPID.
*
* For both modes add a VLAN 0 + no VLAN TPID filter to handle untagged traffic
* when VLAN pruning is enabled. Also, this handles VLAN 0 priority tagged
* traffic in SVM, since the VLAN TPID isn't part of filtering.
*
* If DVM is enabled then an explicit VLAN 0 + VLAN TPID filter needs to be
* added to allow VLAN 0 priority tagged traffic in DVM, since the VLAN TPID is
* part of filtering.
*/
int ice_vsi_add_vlan_zero(struct ice_vsi *vsi)
{
struct ice_vsi_vlan_ops *vlan_ops = ice_get_compat_vsi_vlan_ops(vsi);
struct ice_vlan vlan;
int err;

vlan = ICE_VLAN(0, 0, 0);
err = vlan_ops->add_vlan(vsi, &vlan);
if (err && err != -EEXIST)
return err;

/* in SVM both VLAN 0 filters are identical */
if (!ice_is_dvm_ena(&vsi->back->hw))
return 0;

vlan = ICE_VLAN(ETH_P_8021Q, 0, 0);
err = vlan_ops->add_vlan(vsi, &vlan);
if (err && err != -EEXIST)
return err;

return 0;
}

/**
* ice_vsi_del_vlan_zero - delete VLAN 0 filter(s) for this VSI
* @vsi: VSI used to add VLAN filters
*
* Delete the VLAN 0 filters in the same manner that they were added in
* ice_vsi_add_vlan_zero.
*/
int ice_vsi_del_vlan_zero(struct ice_vsi *vsi)
{
struct ice_vsi_vlan_ops *vlan_ops = ice_get_compat_vsi_vlan_ops(vsi);
struct ice_vlan vlan;
int err;

vlan = ICE_VLAN(0, 0, 0);
return vsi->vlan_ops.add_vlan(vsi, &vlan);
err = vlan_ops->del_vlan(vsi, &vlan);
if (err && err != -EEXIST)
return err;

/* in SVM both VLAN 0 filters are identical */
if (!ice_is_dvm_ena(&vsi->back->hw))
return 0;

vlan = ICE_VLAN(ETH_P_8021Q, 0, 0);
err = vlan_ops->del_vlan(vsi, &vlan);
if (err && err != -EEXIST)
return err;

return 0;
}

/**
* ice_vsi_num_zero_vlans - get number of VLAN 0 filters based on VLAN mode
* @vsi: VSI used to get the VLAN mode
*
* If DVM is enabled then 2 VLAN 0 filters are added, else if SVM is enabled
* then 1 VLAN 0 filter is added. See ice_vsi_add_vlan_zero for more details.
*/
static u16 ice_vsi_num_zero_vlans(struct ice_vsi *vsi)
{
#define ICE_DVM_NUM_ZERO_VLAN_FLTRS 2
#define ICE_SVM_NUM_ZERO_VLAN_FLTRS 1
/* no VLAN 0 filter is created when a port VLAN is active */
if (vsi->type == ICE_VSI_VF &&
ice_vf_is_port_vlan_ena(&vsi->back->vf[vsi->vf_id]))
return 0;
if (ice_is_dvm_ena(&vsi->back->hw))
return ICE_DVM_NUM_ZERO_VLAN_FLTRS;
else
return ICE_SVM_NUM_ZERO_VLAN_FLTRS;
}

/**
* ice_vsi_has_non_zero_vlans - check if VSI has any non-zero VLANs
* @vsi: VSI used to determine if any non-zero VLANs have been added
*/
bool ice_vsi_has_non_zero_vlans(struct ice_vsi *vsi)
{
return (vsi->num_vlan > ice_vsi_num_zero_vlans(vsi));
}

/**
* ice_vsi_num_non_zero_vlans - get the number of non-zero VLANs for this VSI
* @vsi: VSI used to get the number of non-zero VLANs added
*/
u16 ice_vsi_num_non_zero_vlans(struct ice_vsi *vsi)
{
return (vsi->num_vlan - ice_vsi_num_zero_vlans(vsi));
}

/**
Expand Down
3 changes: 3 additions & 0 deletions drivers/net/ethernet/intel/ice/ice_lib.h
Original file line number Diff line number Diff line change
Expand Up @@ -123,6 +123,9 @@ void ice_vsi_ctx_set_allow_override(struct ice_vsi_ctx *ctx);

void ice_vsi_ctx_clear_allow_override(struct ice_vsi_ctx *ctx);
int ice_vsi_add_vlan_zero(struct ice_vsi *vsi);
int ice_vsi_del_vlan_zero(struct ice_vsi *vsi);
bool ice_vsi_has_non_zero_vlans(struct ice_vsi *vsi);
u16 ice_vsi_num_non_zero_vlans(struct ice_vsi *vsi);
bool ice_is_feature_supported(struct ice_pf *pf, enum ice_feature f);
void ice_clear_feature_support(struct ice_pf *pf, enum ice_feature f);
void ice_init_feature_support(struct ice_pf *pf);
Expand Down
Loading

0 comments on commit c31af68

Please sign in to comment.