/* Find out specific VLAN filter */
static struct ice_vlan_filter *
-ice_find_vlan_filter(struct ice_vsi *vsi, uint16_t vlan_id)
+ice_find_vlan_filter(struct ice_vsi *vsi, struct ice_vlan *vlan)
{
struct ice_vlan_filter *f;
TAILQ_FOREACH(f, &vsi->vlan_list, next) {
- if (vlan_id == f->vlan_info.vlan_id)
+ if (vlan->tpid == f->vlan_info.vlan.tpid &&
+ vlan->vid == f->vlan_info.vlan.vid)
return f;
}
}
static int
-ice_add_vlan_filter(struct ice_vsi *vsi, uint16_t vlan_id)
+ice_add_vlan_filter(struct ice_vsi *vsi, struct ice_vlan *vlan)
{
struct ice_fltr_list_entry *v_list_itr = NULL;
struct ice_vlan_filter *f;
struct ice_hw *hw;
int ret = 0;
- if (!vsi || vlan_id > RTE_ETHER_MAX_VLAN_ID)
+ if (!vsi || vlan->vid > RTE_ETHER_MAX_VLAN_ID)
return -EINVAL;
hw = ICE_VSI_TO_HW(vsi);
/* If it's added and configured, return. */
- f = ice_find_vlan_filter(vsi, vlan_id);
+ f = ice_find_vlan_filter(vsi, vlan);
if (f) {
PMD_DRV_LOG(INFO, "This VLAN filter already exists.");
return 0;
ret = -ENOMEM;
goto DONE;
}
- v_list_itr->fltr_info.l_data.vlan.vlan_id = vlan_id;
+ v_list_itr->fltr_info.l_data.vlan.vlan_id = vlan->vid;
+ v_list_itr->fltr_info.l_data.vlan.tpid = vlan->tpid;
+ v_list_itr->fltr_info.l_data.vlan.tpid_valid = true;
v_list_itr->fltr_info.src_id = ICE_SRC_ID_VSI;
v_list_itr->fltr_info.fltr_act = ICE_FWD_TO_VSI;
v_list_itr->fltr_info.lkup_type = ICE_SW_LKUP_VLAN;
ret = -ENOMEM;
goto DONE;
}
- f->vlan_info.vlan_id = vlan_id;
+ f->vlan_info.vlan.tpid = vlan->tpid;
+ f->vlan_info.vlan.vid = vlan->vid;
TAILQ_INSERT_TAIL(&vsi->vlan_list, f, next);
vsi->vlan_num++;
}
static int
-ice_remove_vlan_filter(struct ice_vsi *vsi, uint16_t vlan_id)
+ice_remove_vlan_filter(struct ice_vsi *vsi, struct ice_vlan *vlan)
{
struct ice_fltr_list_entry *v_list_itr = NULL;
struct ice_vlan_filter *f;
struct ice_hw *hw;
int ret = 0;
- /**
- * Vlan 0 is the generic filter for untagged packets
- * and can't be removed.
- */
- if (!vsi || vlan_id == 0 || vlan_id > RTE_ETHER_MAX_VLAN_ID)
+ if (!vsi || vlan->vid > RTE_ETHER_MAX_VLAN_ID)
return -EINVAL;
hw = ICE_VSI_TO_HW(vsi);
/* Can't find it, return an error */
- f = ice_find_vlan_filter(vsi, vlan_id);
+ f = ice_find_vlan_filter(vsi, vlan);
if (!f)
return -EINVAL;
goto DONE;
}
- v_list_itr->fltr_info.l_data.vlan.vlan_id = vlan_id;
+ v_list_itr->fltr_info.l_data.vlan.vlan_id = vlan->vid;
+ v_list_itr->fltr_info.l_data.vlan.tpid = vlan->tpid;
+ v_list_itr->fltr_info.l_data.vlan.tpid_valid = true;
v_list_itr->fltr_info.src_id = ICE_SRC_ID_VSI;
v_list_itr->fltr_info.fltr_act = ICE_FWD_TO_VSI;
v_list_itr->fltr_info.lkup_type = ICE_SW_LKUP_VLAN;
return 0;
TAILQ_FOREACH(v_f, &vsi->vlan_list, next) {
- ret = ice_remove_vlan_filter(vsi, v_f->vlan_info.vlan_id);
+ ret = ice_remove_vlan_filter(vsi, &v_f->vlan_info.vlan);
if (ret != ICE_SUCCESS) {
ret = -EINVAL;
goto DONE;
vsi_ctx.info.inner_vlan_flags |= ICE_AQ_VSI_INNER_VLAN_EMODE_NOTHING;
vsi_ctx.info.q_opt_rss = ICE_AQ_VSI_Q_OPT_RSS_LUT_PF |
ICE_AQ_VSI_Q_OPT_RSS_TPLZ;
+ if (ice_is_dvm_ena(hw)) {
+ vsi_ctx.info.outer_vlan_flags =
+ (ICE_AQ_VSI_OUTER_VLAN_TX_MODE_ALL <<
+ ICE_AQ_VSI_OUTER_VLAN_TX_MODE_S) &
+ ICE_AQ_VSI_OUTER_VLAN_TX_MODE_M;
+ vsi_ctx.info.outer_vlan_flags |=
+ (ICE_AQ_VSI_OUTER_TAG_VLAN_8100 <<
+ ICE_AQ_VSI_OUTER_TAG_TYPE_S) &
+ ICE_AQ_VSI_OUTER_TAG_TYPE_M;
+ }
/* FDIR */
cfg = ICE_AQ_VSI_PROP_SECURITY_VALID |
else
package_type = ICE_PKG_TYPE_UNKNOWN;
- PMD_INIT_LOG(NOTICE, "Active package is: %d.%d.%d.%d, %s",
+ PMD_INIT_LOG(NOTICE, "Active package is: %d.%d.%d.%d, %s (%s VLAN mode)",
hw->active_pkg_ver.major, hw->active_pkg_ver.minor,
hw->active_pkg_ver.update, hw->active_pkg_ver.draft,
- hw->active_pkg_name);
+ hw->active_pkg_name,
+ ice_is_dvm_ena(hw) ? "double" : "single");
return package_type;
}
ice_vlan_filter_set(struct rte_eth_dev *dev, uint16_t vlan_id, int on)
{
struct ice_pf *pf = ICE_DEV_PRIVATE_TO_PF(dev->data->dev_private);
+ struct ice_vlan vlan = ICE_VLAN(RTE_ETHER_TYPE_VLAN, vlan_id);
struct ice_vsi *vsi = pf->main_vsi;
int ret;
PMD_INIT_FUNC_TRACE();
+ /**
+ * Vlan 0 is the generic filter for untagged packets
+ * and can't be removed or added by user.
+ */
+ if (vlan_id == 0)
+ return 0;
+
if (on) {
- ret = ice_add_vlan_filter(vsi, vlan_id);
+ ret = ice_add_vlan_filter(vsi, &vlan);
if (ret < 0) {
PMD_DRV_LOG(ERR, "Failed to add vlan filter");
return -EINVAL;
}
} else {
- ret = ice_remove_vlan_filter(vsi, vlan_id);
+ ret = ice_remove_vlan_filter(vsi, &vlan);
if (ret < 0) {
PMD_DRV_LOG(ERR, "Failed to remove vlan filter");
return -EINVAL;
return 0;
}
+/* 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.
+ */
+static int
+ice_vsi_add_vlan_zero(struct ice_vsi *vsi)
+{
+ struct ice_vlan vlan;
+ int err;
+
+ vlan = ICE_VLAN(0, 0);
+ err = ice_add_vlan_filter(vsi, &vlan);
+ if (err) {
+ PMD_DRV_LOG(DEBUG, "Failed to add VLAN ID 0");
+ return err;
+ }
+
+ /* in SVM both VLAN 0 filters are identical */
+ if (!ice_is_dvm_ena(&vsi->adapter->hw))
+ return 0;
+
+ vlan = ICE_VLAN(RTE_ETHER_TYPE_VLAN, 0);
+ err = ice_add_vlan_filter(vsi, &vlan);
+ if (err) {
+ PMD_DRV_LOG(DEBUG, "Failed to add VLAN ID 0 in double VLAN mode");
+ return err;
+ }
+
+ return 0;
+}
+
+/*
+ * Delete the VLAN 0 filters in the same manner that they were added in
+ * ice_vsi_add_vlan_zero.
+ */
+static int
+ice_vsi_del_vlan_zero(struct ice_vsi *vsi)
+{
+ struct ice_vlan vlan;
+ int err;
+
+ vlan = ICE_VLAN(0, 0);
+ err = ice_remove_vlan_filter(vsi, &vlan);
+ if (err) {
+ PMD_DRV_LOG(DEBUG, "Failed to remove VLAN ID 0");
+ return err;
+ }
+
+ /* in SVM both VLAN 0 filters are identical */
+ if (!ice_is_dvm_ena(&vsi->adapter->hw))
+ return 0;
+
+ vlan = ICE_VLAN(RTE_ETHER_TYPE_VLAN, 0);
+ err = ice_remove_vlan_filter(vsi, &vlan);
+ if (err) {
+ PMD_DRV_LOG(DEBUG, "Failed to remove VLAN ID 0 in double VLAN mode");
+ return err;
+ }
+
+ return 0;
+}
+
/* Configure vlan filter on or off */
static int
ice_vsi_config_vlan_filter(struct ice_vsi *vsi, bool on)
/* consist with other drivers, allow untagged packet when vlan filter on */
if (on)
- ret = ice_add_vlan_filter(vsi, 0);
+ ret = ice_vsi_add_vlan_zero(vsi);
else
- ret = ice_remove_vlan_filter(vsi, 0);
+ ret = ice_vsi_del_vlan_zero(vsi);
return 0;
}