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

Message ID 20180528020110.37713-3-qi.z.zhang@intel.com (mailing list archive)
State Rejected, archived
Delegated to: Qi Zhang
Headers

Checks

Context Check Description
ci/checkpatch warning coding style issues
ci/Intel-compilation fail Compilation issues

Commit Message

Qi Zhang May 28, 2018, 2:01 a.m. UTC
  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@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(-)
  

Patch

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;