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.zh...@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

Reply via email to