[dpdk-dev] [PATCH 2/2] net/i40e: enable VF VLAN antispoof

Qi Zhang qi.z.zhang at intel.com
Mon May 28 04:01:10 CEST 2018


Due to hardware limitation, there is no perfect solution to
enable VF vlan antispoof, to enable it means lost something else.
So the solution is to introduce devarg "support-vf-vlan-antispoof"
that turn on the feature to meet customer's specific requirement
while no impact on normal case when it is turned off. Below impact
is expected when support-vf-vlan-antispoof is turned on:

1. Multi-driver is not supported since some global register is
   changed in DPDK driver during init which is no expected by
   kernel driver.

2. Unicast / Multicase promiscuous mode can not be configured
   separately. So, function rte_pmd_i40e_set_vf_unicast_promics
   and rte_pmd_i40e_set_vf_multicast_promisc will fail and
   new funciton rte_pmd_i40e_set_vf_promics is introduced as a
   coarse-grain API.

3. VLAN anti-spoof and Mac anti-spoof are always enable/disable
   together. (rte_eth_set_vf_mac_anti_spoof and
   rte_eth_set_vf_vlan_anti_spoof do the same thing now.)

4. When VLAN/MAC anti-spoof is turned on, vlan tag will be added to
   vlan promisc table, so in the rx path, mac address match will
   be ignored, only vlan will be matched.

Signed-off-by: Qi Zhang <qi.z.zhang at intel.com>
---
 doc/guides/nics/i40e.rst                  |  28 +++++
 drivers/net/i40e/i40e_ethdev.c            |  99 +++++++++++++----
 drivers/net/i40e/i40e_ethdev.h            |   1 +
 drivers/net/i40e/i40e_pf.c                |  30 ++++--
 drivers/net/i40e/rte_pmd_i40e.c           | 171 ++++++++++++++++++++++++++----
 drivers/net/i40e/rte_pmd_i40e.h           |  22 ++++
 drivers/net/i40e/rte_pmd_i40e_version.map |   8 +-
 7 files changed, 309 insertions(+), 50 deletions(-)

diff --git a/doc/guides/nics/i40e.rst b/doc/guides/nics/i40e.rst
index 18549bf5a..ff054f3c4 100644
--- a/doc/guides/nics/i40e.rst
+++ b/doc/guides/nics/i40e.rst
@@ -124,6 +124,34 @@ Runtime Config Options
   will switch PF interrupt from IntN to Int0 to avoid interrupt conflict between
   DPDK and Linux Kernel.
 
+- ``Support VF VLAN anti-spoof`` (default ``disable``)
+
+  This is a work around to enable vlan antispoof on VF to support customer with
+  this specific requirement, the reason not make it as a default config is:
+  due to hardware limitation, when turn on this feature, some global register will
+  be re-write and some device default behaviour will be changed. (see below for
+  more detail). ``devargs`` parameter ``support-vf-vlan-antispoof`` is introduced,
+  for example::
+
+    -w 84:00.0,support-vf-vlan-antispoof=1
+
+  By default its off, when it turn on, will have below impact:
+
+  Multi-driver is not supported since some global register is changed in DPDK driver
+  during init which is no expected by kernel driver.
+
+  Unicast / Multicase promiscuous mode can not be configured separately. So, function
+  ``rte_pmd_i40e_set_vf_unicast_promics`` and ``rte_pmd_i40e_set_vf_multicast_promisc``
+  will fail and new funciton rte_pmd_i40e_set_vf_promics is introduced as a coarse-grain
+  API.
+
+  VLAN anti-spoof and Mac anti-spoof are always enable/disable together.
+  (``rte_eth_set_vf_mac_anti_spoof`` and ``rte_eth_set_vf_vlan_anti_spoof`` now do the
+  same thing).
+
+  When VLAN/MAC anti-spoof is turn on, vlan tag will be added to vlan promisc table, so 
+  in the rx path, mac address match will be ignored, only vlan will be matched.
+
 - ``Support VF Port Representor`` (default ``not enabled``)
 
   The i40e PF PMD supports the creation of VF port representors for the control
diff --git a/drivers/net/i40e/i40e_ethdev.c b/drivers/net/i40e/i40e_ethdev.c
index f0c17a439..486124dfa 100644
--- a/drivers/net/i40e/i40e_ethdev.c
+++ b/drivers/net/i40e/i40e_ethdev.c
@@ -327,7 +327,7 @@ static int i40e_dev_filter_ctrl(struct rte_eth_dev *dev,
 static int i40e_dev_get_dcb_info(struct rte_eth_dev *dev,
 				  struct rte_eth_dcb_info *dcb_info);
 static int i40e_dev_sync_phy_type(struct i40e_hw *hw);
-static void i40e_configure_registers(struct i40e_hw *hw);
+static void i40e_configure_registers(struct rte_eth_dev *dev);
 static void i40e_hw_init(struct rte_eth_dev *dev);
 static int i40e_config_qinq(struct i40e_hw *hw, struct i40e_vsi *vsi);
 static enum i40e_status_code i40e_aq_del_mirror_rule(struct i40e_hw *hw,
@@ -1097,45 +1097,54 @@ i40e_init_queue_region_conf(struct rte_eth_dev *dev)
 	memset(info, 0, sizeof(struct i40e_queue_regions));
 }
 
-#define ETH_I40E_SUPPORT_MULTI_DRIVER	"support-multi-driver"
+#define ETH_I40E_SUPPORT_MULTI_DRIVER		"support-multi-driver"
+#define ETH_I40E_SUPPORT_VF_VLAN_ANTI_SPOOF	"support-vf-vlan-antispoof"
 
 static int
-i40e_parse_multi_drv_handler(__rte_unused const char *key,
-			       const char *value,
-			       void *opaque)
+i40e_parse_config_handler(__rte_unused const char *key,
+			  const char *value,
+			  void *opaque)
 {
 	struct i40e_pf *pf;
-	unsigned long support_multi_driver;
+	unsigned long flag;
 	char *end;
 
 	pf = (struct i40e_pf *)opaque;
 
 	errno = 0;
-	support_multi_driver = strtoul(value, &end, 10);
+	flag = strtoul(value, &end, 10);
 	if (errno != 0 || end == value || *end != 0) {
 		PMD_DRV_LOG(WARNING, "Wrong global configuration");
 		return -(EINVAL);
 	}
 
-	if (support_multi_driver == 1 || support_multi_driver == 0)
-		pf->support_multi_driver = (bool)support_multi_driver;
-	else
-		PMD_DRV_LOG(WARNING, "%s must be 1 or 0,",
-			    "enable global configuration by default."
-			    ETH_I40E_SUPPORT_MULTI_DRIVER);
+	if (flag == 1 || flag == 0) {
+		if (!strcmp(ETH_I40E_SUPPORT_MULTI_DRIVER, key))
+			pf->support_multi_driver = (bool)flag;
+		else if (!strcmp(ETH_I40E_SUPPORT_VF_VLAN_ANTI_SPOOF, key))
+			pf->support_vf_vlan_antispoof = (bool)flag;
+	} else {
+		PMD_DRV_LOG(WARNING, "%s must be 1 or 0, use default config 0",
+			    key);
+	}
+
 	return 0;
 }
 
 static int
-i40e_support_multi_driver(struct rte_eth_dev *dev)
+i40e_parse_device_args(struct rte_eth_dev *dev)
 {
 	struct i40e_pf *pf = I40E_DEV_PRIVATE_TO_PF(dev->data->dev_private);
 	static const char *const valid_keys[] = {
-		ETH_I40E_SUPPORT_MULTI_DRIVER, NULL};
+		ETH_I40E_SUPPORT_MULTI_DRIVER,
+		ETH_I40E_SUPPORT_VF_VLAN_ANTI_SPOOF,
+		NULL};
 	struct rte_kvargs *kvlist;
 
 	/* Enable global configuration by default */
 	pf->support_multi_driver = false;
+	/* vlan antispoof is not supported by default */
+	pf->support_vf_vlan_antispoof = false;
 
 	if (!dev->device->devargs)
 		return 0;
@@ -1150,7 +1159,18 @@ i40e_support_multi_driver(struct rte_eth_dev *dev)
 			    ETH_I40E_SUPPORT_MULTI_DRIVER);
 
 	if (rte_kvargs_process(kvlist, ETH_I40E_SUPPORT_MULTI_DRIVER,
-			       i40e_parse_multi_drv_handler, pf) < 0) {
+			       i40e_parse_config_handler, pf) < 0) {
+		rte_kvargs_free(kvlist);
+		return -EINVAL;
+	}
+
+	if (rte_kvargs_count(kvlist, ETH_I40E_SUPPORT_VF_VLAN_ANTI_SPOOF) > 1)
+		PMD_DRV_LOG(WARNING, "More than one argument \"%s\" and only "
+			    "the first invalid or last valid one is used !",
+			    ETH_I40E_SUPPORT_VF_VLAN_ANTI_SPOOF);
+
+	if (rte_kvargs_process(kvlist, ETH_I40E_SUPPORT_VF_VLAN_ANTI_SPOOF,
+			       i40e_parse_config_handler, pf) < 0) {
 		rte_kvargs_free(kvlist);
 		return -EINVAL;
 	}
@@ -1236,8 +1256,12 @@ eth_i40e_dev_init(struct rte_eth_dev *dev, void *init_params __rte_unused)
 	hw->bus.func = pci_dev->addr.function;
 	hw->adapter_stopped = 0;
 
-	/* Check if need to support multi-driver */
-	i40e_support_multi_driver(dev);
+	/* check multi driver and vlan anti-spoof in devargs */
+	i40e_parse_device_args(dev);
+
+	/* vf vlan anti spoof is conflict with multi driver support */
+	if (pf->support_multi_driver && pf->support_vf_vlan_antispoof)
+		return -ENOTSUP;
 
 	/* Make sure all is clean before doing PF reset */
 	i40e_clear_hw(hw);
@@ -1316,7 +1340,7 @@ eth_i40e_dev_init(struct rte_eth_dev *dev, void *init_params __rte_unused)
 	 * registers. Note that the workaround can be removed when it is fixed
 	 * in firmware in the future.
 	 */
-	i40e_configure_registers(hw);
+	i40e_configure_registers(dev);
 
 	/* Get hw capabilities */
 	ret = i40e_get_cap(hw);
@@ -2436,6 +2460,13 @@ i40e_dev_promiscuous_enable(struct rte_eth_dev *dev)
 	struct i40e_vsi *vsi = pf->main_vsi;
 	int status;
 
+	if (pf->support_vf_vlan_antispoof) {
+		status = i40e_aq_set_default_vsi(hw, vsi->seid, NULL);
+		if (status != I40E_SUCCESS)
+			PMD_DRV_LOG(ERR, "Failed to enable promiscuous");
+		return;
+	}
+
 	status = i40e_aq_set_vsi_unicast_promiscuous(hw, vsi->seid,
 						     true, NULL, true);
 	if (status != I40E_SUCCESS)
@@ -2456,6 +2487,13 @@ i40e_dev_promiscuous_disable(struct rte_eth_dev *dev)
 	struct i40e_vsi *vsi = pf->main_vsi;
 	int status;
 
+	if (pf->support_vf_vlan_antispoof) {
+		status = i40e_aq_clear_default_vsi(hw, vsi->seid, NULL);
+		if (status != I40E_SUCCESS)
+			PMD_DRV_LOG(ERR, "Failed to disable promiscuous");
+		return;
+	}
+
 	status = i40e_aq_set_vsi_unicast_promiscuous(hw, vsi->seid,
 						     false, NULL, true);
 	if (status != I40E_SUCCESS)
@@ -10006,8 +10044,11 @@ i40e_dev_sync_phy_type(struct i40e_hw *hw)
 }
 
 static void
-i40e_configure_registers(struct i40e_hw *hw)
+i40e_configure_registers(struct rte_eth_dev *dev)
 {
+	struct i40e_pf *pf = I40E_DEV_PRIVATE_TO_PF(dev->data->dev_private);
+	struct i40e_hw *hw = I40E_DEV_PRIVATE_TO_HW(dev->data->dev_private);
+
 	static struct {
 		uint32_t addr;
 		uint64_t val;
@@ -10076,6 +10117,21 @@ i40e_configure_registers(struct i40e_hw *hw)
 		PMD_DRV_LOG(DEBUG, "Write 0x%"PRIx64" to the address of "
 			"0x%"PRIx32, reg_table[i].val, reg_table[i].addr);
 	}
+
+	if (pf->support_vf_vlan_antispoof) {
+		/**
+		 * To enable vlan antispoof, we need write some undocumented
+		 * glboal registers, cast below spell to trigger the magic.
+		 */
+		i40e_aq_debug_write_register(hw, 0x00269624, 0xa0C38886, NULL);
+		i40e_aq_debug_write_register(hw, 0x00269EA4, 0x00003FE0, NULL);
+		i40e_aq_debug_write_register(hw, 0x002696A4, 0xA0C18886, NULL);
+		i40e_aq_debug_write_register(hw, 0x00269EE4, 0x0FFF1FFF, NULL);
+		i40e_aq_debug_write_register(hw, 0x00269F24, 0x00008000, NULL);
+		i40e_aq_debug_write_register(hw, 0x00269BE8, 0x07000200, NULL);
+		i40e_aq_debug_write_register(hw, 0x0026CDC8, 0x01010000, NULL);
+		i40e_aq_debug_write_register(hw, 0x0026CE08, 0x013F0000, NULL);
+	}
 }
 
 #define I40E_VSI_TSR(_i)            (0x00050800 + ((_i) * 4))
@@ -12390,4 +12446,5 @@ i40e_init_log(void)
 
 RTE_PMD_REGISTER_PARAM_STRING(net_i40e,
 			      QUEUE_NUM_PER_VF_ARG "=1|2|4|8|16"
-			      ETH_I40E_SUPPORT_MULTI_DRIVER "=1");
+			      ETH_I40E_SUPPORT_MULTI_DRIVER "=1"
+			      ETH_I40E_SUPPORT_VF_VLAN_ANTI_SPOOF "=1");
diff --git a/drivers/net/i40e/i40e_ethdev.h b/drivers/net/i40e/i40e_ethdev.h
index 12c0645a7..b06d6051b 100644
--- a/drivers/net/i40e/i40e_ethdev.h
+++ b/drivers/net/i40e/i40e_ethdev.h
@@ -960,6 +960,7 @@ struct i40e_pf {
 	bool qinq_replace_flag;  /* QINQ filter replace is done */
 	struct i40e_tm_conf tm_conf;
 	bool support_multi_driver; /* 1 - support multiple driver */
+	bool support_vf_vlan_antispoof; /* 1 - support vf's vlan antispoof */
 
 	/* Dynamic Device Personalization */
 	bool gtp_support; /* 1 - support GTP-C and GTP-U */
diff --git a/drivers/net/i40e/i40e_pf.c b/drivers/net/i40e/i40e_pf.c
index dd3962d38..cb6dac10a 100644
--- a/drivers/net/i40e/i40e_pf.c
+++ b/drivers/net/i40e/i40e_pf.c
@@ -1009,15 +1009,31 @@ i40e_pf_host_process_cmd_config_promisc_mode(
 
 	if (promisc->flags & FLAG_VF_UNICAST_PROMISC)
 		unicast = TRUE;
-	ret = i40e_aq_set_vsi_unicast_promiscuous(hw,
-			vf->vsi->seid, unicast, NULL, true);
-	if (ret != I40E_SUCCESS)
-		goto send_msg;
-
 	if (promisc->flags & FLAG_VF_MULTICAST_PROMISC)
 		multicast = TRUE;
-	ret = i40e_aq_set_vsi_multicast_promiscuous(hw, vf->vsi->seid,
-						multicast, NULL);
+
+	if (vf->pf->support_vf_vlan_antispoof) {
+		if (unicast && multicast)
+			ret = i40e_aq_set_default_vsi(hw, vf->vsi->seid, NULL);
+		else if (!unicast && !multicast)
+			ret = i40e_aq_clear_default_vsi(hw,
+							vf->vsi->seid,
+							NULL);
+		else
+			ret = I40E_ERR_DEVICE_NOT_SUPPORTED;
+
+		if (ret != I40E_SUCCESS)
+			PMD_DRV_LOG(ERR,
+				    "Failed to enable/disable promiscuous");
+	} else {
+		ret = i40e_aq_set_vsi_unicast_promiscuous(hw,
+				vf->vsi->seid, unicast, NULL, true);
+		if (ret != I40E_SUCCESS)
+			goto send_msg;
+
+		ret = i40e_aq_set_vsi_multicast_promiscuous(hw, vf->vsi->seid,
+							multicast, NULL);
+	}
 
 send_msg:
 	i40e_pf_host_send_msg_to_vf(vf,
diff --git a/drivers/net/i40e/rte_pmd_i40e.c b/drivers/net/i40e/rte_pmd_i40e.c
index e5e4c44ba..171bdc82c 100644
--- a/drivers/net/i40e/rte_pmd_i40e.c
+++ b/drivers/net/i40e/rte_pmd_i40e.c
@@ -37,36 +37,71 @@ rte_pmd_i40e_ping_vfs(uint16_t port, uint16_t vf)
 	return 0;
 }
 
-int
-rte_pmd_i40e_set_vf_mac_anti_spoof(uint16_t port, uint16_t vf_id, uint8_t on)
+static int
+set_vlan_promisc(struct i40e_hw *hw,
+		 uint16_t seid,
+		 uint16_t vid,
+		 bool enable)
 {
-	struct rte_eth_dev *dev;
-	struct i40e_pf *pf;
-	struct i40e_vsi *vsi;
-	struct i40e_hw *hw;
-	struct i40e_vsi_context ctxt;
-	int ret;
+	struct i40e_aq_desc desc;
+	struct i40e_aqc_set_vsi_promiscuous_modes *cmd =
+		(struct i40e_aqc_set_vsi_promiscuous_modes *)&desc.params.raw;
 
-	RTE_ETH_VALID_PORTID_OR_ERR_RET(port, -ENODEV);
+	i40e_fill_default_direct_cmd_desc(&desc,
+	i40e_aqc_opc_set_vsi_promiscuous_modes);
 
-	dev = &rte_eth_devices[port];
+	if (enable)
+		cmd->promiscuous_flags = CPU_TO_LE16(0x8011);
 
-	if (!is_i40e_supported(dev))
-		return -ENOTSUP;
+	cmd->valid_flags = CPU_TO_LE16(0x8011);
+	cmd->seid = CPU_TO_LE16(seid);
+	cmd->vlan_tag = CPU_TO_LE16(vid | 0x8000);
 
-	pf = I40E_DEV_PRIVATE_TO_PF(dev->data->dev_private);
+	return i40e_asq_send_command(hw, &desc, NULL, 0, NULL);
+}
 
-	if (vf_id >= pf->vf_num || !pf->vfs) {
-		PMD_DRV_LOG(ERR, "Invalid argument.");
-		return -EINVAL;
-	}
+static int
+set_all_vlan_promisc(struct i40e_vsi *vsi, uint8_t enable)
+{
+	struct i40e_hw *hw = I40E_VSI_TO_HW(vsi);
+	uint32_t j, k;
+	uint16_t vlan_id;
+	int ret;
 
-	vsi = pf->vfs[vf_id].vsi;
-	if (!vsi) {
-		PMD_DRV_LOG(ERR, "Invalid VSI.");
-		return -EINVAL;
+	for (j = 0; j < I40E_VFTA_SIZE; j++) {
+		if (!vsi->vfta[j])
+			continue;
+
+		for (k = 0; k < I40E_UINT32_BIT_SIZE; k++) {
+			if (!(vsi->vfta[j] & (1 << k)))
+				continue;
+
+			vlan_id = j * I40E_UINT32_BIT_SIZE + k;
+				if (!vlan_id)
+					continue;
+
+			ret = set_vlan_promisc(hw, vsi->seid, vlan_id, enable);
+			if (ret != I40E_SUCCESS) {
+				PMD_DRV_LOG(ERR,
+					"Failed to set vlan antispoof: vid=%d",
+					vlan_id);
+				return ret;
+			}
+		}
 	}
 
+	return I40E_SUCCESS;
+}
+
+static int
+_i40e_set_vf_mac_anti_spoof(struct i40e_pf *pf,
+			    struct i40e_vsi *vsi,
+			    uint8_t on)
+{
+	struct i40e_hw *hw;
+	struct i40e_vsi_context ctxt;
+	int ret;
+
 	/* Check if it has been already on or off */
 	if (vsi->info.valid_sections &
 		rte_cpu_to_le_16(I40E_AQ_VSI_PROP_SECURITY_VALID)) {
@@ -88,6 +123,11 @@ rte_pmd_i40e_set_vf_mac_anti_spoof(uint16_t port, uint16_t vf_id, uint8_t on)
 	else
 		vsi->info.sec_flags &= ~I40E_AQ_VSI_SEC_FLAG_ENABLE_MAC_CHK;
 
+	if (pf->support_vf_vlan_antispoof) {
+		vsi->vlan_anti_spoof_on = on;
+		set_all_vlan_promisc(vsi, on);
+	}
+
 	memset(&ctxt, 0, sizeof(ctxt));
 	rte_memcpy(&ctxt.info, &vsi->info, sizeof(vsi->info));
 	ctxt.seid = vsi->seid;
@@ -103,6 +143,36 @@ rte_pmd_i40e_set_vf_mac_anti_spoof(uint16_t port, uint16_t vf_id, uint8_t on)
 }
 
 int
+rte_pmd_i40e_set_vf_mac_anti_spoof(uint16_t port, uint16_t vf_id, uint8_t on)
+{
+	struct rte_eth_dev *dev;
+	struct i40e_pf *pf;
+	struct i40e_vsi *vsi;
+
+	RTE_ETH_VALID_PORTID_OR_ERR_RET(port, -ENODEV);
+
+	dev = &rte_eth_devices[port];
+
+	if (!is_i40e_supported(dev))
+		return -ENOTSUP;
+
+	pf = I40E_DEV_PRIVATE_TO_PF(dev->data->dev_private);
+
+	if (vf_id >= pf->vf_num || !pf->vfs) {
+		PMD_DRV_LOG(ERR, "Invalid argument.");
+		return -EINVAL;
+	}
+
+	vsi = pf->vfs[vf_id].vsi;
+	if (!vsi) {
+		PMD_DRV_LOG(ERR, "Invalid VSI.");
+		return -EINVAL;
+	}
+
+	return _i40e_set_vf_mac_anti_spoof(pf, vsi, on);
+}
+
+int
 rte_pmd_i40e_set_vf_vlan_anti_spoof(uint16_t port, uint16_t vf_id, uint8_t on)
 {
 	struct rte_eth_dev *dev;
@@ -132,6 +202,9 @@ rte_pmd_i40e_set_vf_vlan_anti_spoof(uint16_t port, uint16_t vf_id, uint8_t on)
 		return -EINVAL;
 	}
 
+	if (pf->support_vf_vlan_antispoof)
+		return _i40e_set_vf_mac_anti_spoof(pf, vsi, on);
+
 	/* Check if it has been already on or off */
 	if (vsi->vlan_anti_spoof_on == on)
 		return 0; /* already on or off */
@@ -384,6 +457,53 @@ rte_pmd_i40e_set_tx_loopback(uint16_t port, uint8_t on)
 }
 
 int
+rte_pmd_i40e_set_vf_promisc(uint16_t port, uint16_t vf_id, uint8_t on)
+{
+	struct rte_eth_dev *dev;
+	struct i40e_pf *pf;
+	struct i40e_vsi *vsi;
+	struct i40e_hw *hw;
+	int ret;
+
+	RTE_ETH_VALID_PORTID_OR_ERR_RET(port, -ENODEV);
+
+	dev = &rte_eth_devices[port];
+
+	if (!is_i40e_supported(dev))
+		return -ENOTSUP;
+
+	pf = I40E_DEV_PRIVATE_TO_PF(dev->data->dev_private);
+
+	if (vf_id >= pf->vf_num || !pf->vfs) {
+		PMD_DRV_LOG(ERR, "Invalid argument.");
+		return -EINVAL;
+	}
+
+	vsi = pf->vfs[vf_id].vsi;
+	if (!vsi) {
+		PMD_DRV_LOG(ERR, "Invalid VSI.");
+		return -EINVAL;
+	}
+
+	if (!pf->support_vf_vlan_antispoof)
+		return -ENOTSUP;
+
+	hw = I40E_VSI_TO_HW(vsi);
+
+	if (on)
+		ret = i40e_aq_set_default_vsi(hw, vsi->seid, NULL);
+	else
+		ret = i40e_aq_clear_default_vsi(hw, vsi->seid, NULL);
+
+	if (ret != I40E_SUCCESS) {
+		ret = -ENOTSUP;
+		PMD_DRV_LOG(ERR, "Failed to set promiscuous mode");
+	}
+
+	return ret;
+}
+
+int
 rte_pmd_i40e_set_vf_unicast_promisc(uint16_t port, uint16_t vf_id, uint8_t on)
 {
 	struct rte_eth_dev *dev;
@@ -412,6 +532,9 @@ rte_pmd_i40e_set_vf_unicast_promisc(uint16_t port, uint16_t vf_id, uint8_t on)
 		return -EINVAL;
 	}
 
+	if (pf->support_vf_vlan_antispoof)
+		return -ENOTSUP;
+
 	hw = I40E_VSI_TO_HW(vsi);
 
 	ret = i40e_aq_set_vsi_unicast_promiscuous(hw, vsi->seid,
@@ -453,6 +576,9 @@ rte_pmd_i40e_set_vf_multicast_promisc(uint16_t port, uint16_t vf_id, uint8_t on)
 		return -EINVAL;
 	}
 
+	if (pf->support_vf_vlan_antispoof)
+		return -ENOTSUP;
+
 	hw = I40E_VSI_TO_HW(vsi);
 
 	ret = i40e_aq_set_vsi_multicast_promiscuous(hw, vsi->seid,
@@ -840,6 +966,9 @@ int rte_pmd_i40e_set_vf_vlan_filter(uint16_t port, uint16_t vlan_id,
 				ret = i40e_vsi_add_vlan(vsi, vlan_id);
 			else
 				ret = i40e_vsi_delete_vlan(vsi, vlan_id);
+			if (vsi->vlan_anti_spoof_on)
+				ret = set_vlan_promisc(hw, vsi->seid,
+						       vlan_id, on);
 		}
 	}
 
diff --git a/drivers/net/i40e/rte_pmd_i40e.h b/drivers/net/i40e/rte_pmd_i40e.h
index be4a6024a..9e99d60b4 100644
--- a/drivers/net/i40e/rte_pmd_i40e.h
+++ b/drivers/net/i40e/rte_pmd_i40e.h
@@ -395,6 +395,26 @@ int rte_pmd_i40e_set_tx_loopback(uint16_t port,
 				 uint8_t on);
 
 /**
+ * Enable/Disable VF promiscuous mode.
+ *
+ * @param port
+ *    The port identifier of the Ethernet device.
+ * @param vf_id
+ *    VF on which to set.
+ * @param on
+ *    1 - Enable.
+ *    0 - Disable.
+ * @return
+ *   - (0) if successful.
+ *   - (-ENODEV) if *port* invalid.
+ *   - (-EINVAL) if bad parameter.
+ *   - (-ENOTSUP) if support-vf-anti-spoof is off.
+ */
+int rte_pmd_i40e_set_vf_promisc(uint16_t port,
+				uint16_t vf_id,
+				uint8_t on);
+
+/**
  * Enable/Disable VF unicast promiscuous mode.
  *
  * @param port
@@ -408,6 +428,7 @@ int rte_pmd_i40e_set_tx_loopback(uint16_t port,
  *   - (0) if successful.
  *   - (-ENODEV) if *port* invalid.
  *   - (-EINVAL) if bad parameter.
+ *   - (-ENOTSUP) if support-vf-anti-spoof is on.
  */
 int rte_pmd_i40e_set_vf_unicast_promisc(uint16_t port,
 					uint16_t vf_id,
@@ -427,6 +448,7 @@ int rte_pmd_i40e_set_vf_unicast_promisc(uint16_t port,
  *   - (0) if successful.
  *   - (-ENODEV) if *port* invalid.
  *   - (-EINVAL) if bad parameter.
+ *   - (-ENOTSUP) if support-vf-anti-spoof is on.
  */
 int rte_pmd_i40e_set_vf_multicast_promisc(uint16_t port,
 					  uint16_t vf_id,
diff --git a/drivers/net/i40e/rte_pmd_i40e_version.map b/drivers/net/i40e/rte_pmd_i40e_version.map
index cccd5768c..3df095c73 100644
--- a/drivers/net/i40e/rte_pmd_i40e_version.map
+++ b/drivers/net/i40e/rte_pmd_i40e_version.map
@@ -64,4 +64,10 @@ DPDK_18.02 {
 
 	rte_pmd_i40e_inset_get;
 	rte_pmd_i40e_inset_set;
-} DPDK_17.11;
\ No newline at end of file
+} DPDK_17.11;
+
+DPDK_18.08 {
+	global:
+
+	rte_pmd_i40e_set_vf_promisc;
+} DPDK_18.2;
-- 
2.13.6



More information about the dev mailing list