net/i40e: move private APIs to a specific file
authorWenzhuo Lu <wenzhuo.lu@intel.com>
Tue, 11 Apr 2017 08:31:23 +0000 (16:31 +0800)
committerFerruh Yigit <ferruh.yigit@intel.com>
Wed, 19 Apr 2017 13:37:37 +0000 (15:37 +0200)
Create a new file rte_pmd_i40e.c for all the private
APIs. Move all the related code to the new file.

Signed-off-by: Wenzhuo Lu <wenzhuo.lu@intel.com>
drivers/net/i40e/Makefile
drivers/net/i40e/i40e_ethdev.c
drivers/net/i40e/i40e_ethdev.h
drivers/net/i40e/rte_pmd_i40e.c [new file with mode: 0644]

index 1f5d133..56f210d 100644 (file)
@@ -108,6 +108,7 @@ SRCS-$(CONFIG_RTE_LIBRTE_I40E_PMD) += i40e_ethdev_vf.c
 SRCS-$(CONFIG_RTE_LIBRTE_I40E_PMD) += i40e_pf.c
 SRCS-$(CONFIG_RTE_LIBRTE_I40E_PMD) += i40e_fdir.c
 SRCS-$(CONFIG_RTE_LIBRTE_I40E_PMD) += i40e_flow.c
+SRCS-$(CONFIG_RTE_LIBRTE_I40E_PMD) += rte_pmd_i40e.c
 
 # vector PMD driver needs SSE4.1 support
 ifeq ($(findstring RTE_MACHINE_CPUFLAG_SSE4_1,$(CFLAGS)),)
index 50e037e..7ba8c70 100644 (file)
@@ -65,7 +65,6 @@
 #include "i40e_rxtx.h"
 #include "i40e_pf.h"
 #include "i40e_regs.h"
-#include "rte_pmd_i40e.h"
 
 #define ETH_I40E_FLOATING_VEB_ARG      "enable_floating_veb"
 #define ETH_I40E_FLOATING_VEB_LIST_ARG "floating_veb_list"
 /* Bit mask of Extended Tag enable/disable */
 #define PCI_DEV_CTRL_EXT_TAG_MASK  (1 << PCI_DEV_CTRL_EXT_TAG_SHIFT)
 
-/* The max bandwidth of i40e is 40Gbps. */
-#define I40E_QOS_BW_MAX 40000
-/* The bandwidth should be the multiple of 50Mbps. */
-#define I40E_QOS_BW_GRANULARITY 50
-/* The min bandwidth weight is 1. */
-#define I40E_QOS_BW_WEIGHT_MIN 1
-/* The max bandwidth weight is 127. */
-#define I40E_QOS_BW_WEIGHT_MAX 127
-
 static int eth_i40e_dev_init(struct rte_eth_dev *eth_dev);
 static int eth_i40e_dev_uninit(struct rte_eth_dev *eth_dev);
 static int i40e_dev_configure(struct rte_eth_dev *dev);
@@ -343,10 +333,6 @@ static struct i40e_veb *i40e_veb_setup(struct i40e_pf *pf,
                                                struct i40e_vsi *vsi);
 static int i40e_pf_config_mq_rx(struct i40e_pf *pf);
 static int i40e_vsi_config_double_vlan(struct i40e_vsi *vsi, int on);
-static inline int i40e_find_all_vlan_for_mac(struct i40e_vsi *vsi,
-                                            struct i40e_macvlan_filter *mv_f,
-                                            int num,
-                                            struct ether_addr *addr);
 static inline int i40e_find_all_mac_for_vlan(struct i40e_vsi *vsi,
                                             struct i40e_macvlan_filter *mv_f,
                                             int num,
@@ -5862,7 +5848,7 @@ done:
        rte_intr_enable(dev->intr_handle);
 }
 
-static int
+int
 i40e_add_macvlan_filters(struct i40e_vsi *vsi,
                         struct i40e_macvlan_filter *filter,
                         int total)
@@ -5936,7 +5922,7 @@ DONE:
        return ret;
 }
 
-static int
+int
 i40e_remove_macvlan_filters(struct i40e_vsi *vsi,
                            struct i40e_macvlan_filter *filter,
                            int total)
@@ -6056,7 +6042,7 @@ i40e_store_vlan_filter(struct i40e_vsi *vsi,
                vsi->vfta[vid_idx] &= ~vid_bit;
 }
 
-static void
+void
 i40e_set_vlan_filter(struct i40e_vsi *vsi,
                     uint16_t vlan_id, bool on)
 {
@@ -6092,7 +6078,7 @@ i40e_set_vlan_filter(struct i40e_vsi *vsi,
  * Find all vlan options for specific mac addr,
  * return with actual vlan found.
  */
-static inline int
+int
 i40e_find_all_vlan_for_mac(struct i40e_vsi *vsi,
                           struct i40e_macvlan_filter *mv_f,
                           int num, struct ether_addr *addr)
@@ -10733,1658 +10719,10 @@ is_device_supported(struct rte_eth_dev *dev, struct rte_pci_driver *drv)
        return true;
 }
 
-int
-rte_pmd_i40e_ping_vfs(uint8_t port, uint16_t vf)
-{
-       struct rte_eth_dev *dev;
-       struct i40e_pf *pf;
-
-       RTE_ETH_VALID_PORTID_OR_ERR_RET(port, -ENODEV);
-
-       dev = &rte_eth_devices[port];
-
-       if (!is_device_supported(dev, &rte_i40e_pmd))
-               return -ENOTSUP;
-
-       pf = I40E_DEV_PRIVATE_TO_PF(dev->data->dev_private);
-
-       if (vf >= pf->vf_num || !pf->vfs) {
-               PMD_DRV_LOG(ERR, "Invalid argument.");
-               return -EINVAL;
-       }
-
-       i40e_notify_vf_link_status(dev, &pf->vfs[vf]);
-
-       return 0;
-}
-
-int
-rte_pmd_i40e_set_vf_mac_anti_spoof(uint8_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;
-       struct i40e_vsi_context ctxt;
-       int ret;
-
-       RTE_ETH_VALID_PORTID_OR_ERR_RET(port, -ENODEV);
-
-       dev = &rte_eth_devices[port];
-
-       if (!is_device_supported(dev, &rte_i40e_pmd))
-               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;
-       }
-
-       /* 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)) {
-               if (on) {
-                       if ((vsi->info.sec_flags &
-                            I40E_AQ_VSI_SEC_FLAG_ENABLE_MAC_CHK) ==
-                           I40E_AQ_VSI_SEC_FLAG_ENABLE_MAC_CHK)
-                               return 0; /* already on */
-               } else {
-                       if ((vsi->info.sec_flags &
-                            I40E_AQ_VSI_SEC_FLAG_ENABLE_MAC_CHK) == 0)
-                               return 0; /* already off */
-               }
-       }
-
-       vsi->info.valid_sections = cpu_to_le16(I40E_AQ_VSI_PROP_SECURITY_VALID);
-       if (on)
-               vsi->info.sec_flags |= I40E_AQ_VSI_SEC_FLAG_ENABLE_MAC_CHK;
-       else
-               vsi->info.sec_flags &= ~I40E_AQ_VSI_SEC_FLAG_ENABLE_MAC_CHK;
-
-       memset(&ctxt, 0, sizeof(ctxt));
-       (void)rte_memcpy(&ctxt.info, &vsi->info, sizeof(vsi->info));
-       ctxt.seid = vsi->seid;
-
-       hw = I40E_VSI_TO_HW(vsi);
-       ret = i40e_aq_update_vsi_params(hw, &ctxt, NULL);
-       if (ret != I40E_SUCCESS) {
-               ret = -ENOTSUP;
-               PMD_DRV_LOG(ERR, "Failed to update VSI params");
-       }
-
-       return ret;
-}
-
-static int
-i40e_add_rm_all_vlan_filter(struct i40e_vsi *vsi, uint8_t add)
-{
-       uint32_t j, k;
-       uint16_t vlan_id;
-       struct i40e_hw *hw = I40E_VSI_TO_HW(vsi);
-       struct i40e_aqc_add_remove_vlan_element_data vlan_data = {0};
-       int ret;
-
-       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;
-
-                       vlan_data.vlan_tag = rte_cpu_to_le_16(vlan_id);
-                       if (add)
-                               ret = i40e_aq_add_vlan(hw, vsi->seid,
-                                                      &vlan_data, 1, NULL);
-                       else
-                               ret = i40e_aq_remove_vlan(hw, vsi->seid,
-                                                         &vlan_data, 1, NULL);
-                       if (ret != I40E_SUCCESS) {
-                               PMD_DRV_LOG(ERR,
-                                           "Failed to add/rm vlan filter");
-                               return ret;
-                       }
-               }
-       }
-
-       return I40E_SUCCESS;
-}
-
-int
-rte_pmd_i40e_set_vf_vlan_anti_spoof(uint8_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;
-       struct i40e_vsi_context ctxt;
-       int ret;
-
-       RTE_ETH_VALID_PORTID_OR_ERR_RET(port, -ENODEV);
-
-       dev = &rte_eth_devices[port];
-
-       if (!is_device_supported(dev, &rte_i40e_pmd))
-               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;
-       }
-
-       /* Check if it has been already on or off */
-       if (vsi->vlan_anti_spoof_on == on)
-               return 0; /* already on or off */
-
-       vsi->vlan_anti_spoof_on = on;
-       if (!vsi->vlan_filter_on) {
-               ret = i40e_add_rm_all_vlan_filter(vsi, on);
-               if (ret) {
-                       PMD_DRV_LOG(ERR, "Failed to add/remove VLAN filters.");
-                       return -ENOTSUP;
-               }
-       }
-
-       vsi->info.valid_sections = cpu_to_le16(I40E_AQ_VSI_PROP_SECURITY_VALID);
-       if (on)
-               vsi->info.sec_flags |= I40E_AQ_VSI_SEC_FLAG_ENABLE_VLAN_CHK;
-       else
-               vsi->info.sec_flags &= ~I40E_AQ_VSI_SEC_FLAG_ENABLE_VLAN_CHK;
-
-       memset(&ctxt, 0, sizeof(ctxt));
-       (void)rte_memcpy(&ctxt.info, &vsi->info, sizeof(vsi->info));
-       ctxt.seid = vsi->seid;
-
-       hw = I40E_VSI_TO_HW(vsi);
-       ret = i40e_aq_update_vsi_params(hw, &ctxt, NULL);
-       if (ret != I40E_SUCCESS) {
-               ret = -ENOTSUP;
-               PMD_DRV_LOG(ERR, "Failed to update VSI params");
-       }
-
-       return ret;
-}
-
-static int
-i40e_vsi_rm_mac_filter(struct i40e_vsi *vsi)
-{
-       struct i40e_mac_filter *f;
-       struct i40e_macvlan_filter *mv_f;
-       int i, vlan_num;
-       enum rte_mac_filter_type filter_type;
-       int ret = I40E_SUCCESS;
-       void *temp;
-
-       /* remove all the MACs */
-       TAILQ_FOREACH_SAFE(f, &vsi->mac_list, next, temp) {
-               vlan_num = vsi->vlan_num;
-               filter_type = f->mac_info.filter_type;
-               if (filter_type == RTE_MACVLAN_PERFECT_MATCH ||
-                   filter_type == RTE_MACVLAN_HASH_MATCH) {
-                       if (vlan_num == 0) {
-                               PMD_DRV_LOG(ERR, "VLAN number shouldn't be 0");
-                               return I40E_ERR_PARAM;
-                       }
-               } else if (filter_type == RTE_MAC_PERFECT_MATCH ||
-                          filter_type == RTE_MAC_HASH_MATCH)
-                       vlan_num = 1;
-
-               mv_f = rte_zmalloc("macvlan_data", vlan_num * sizeof(*mv_f), 0);
-               if (!mv_f) {
-                       PMD_DRV_LOG(ERR, "failed to allocate memory");
-                       return I40E_ERR_NO_MEMORY;
-               }
-
-               for (i = 0; i < vlan_num; i++) {
-                       mv_f[i].filter_type = filter_type;
-                       (void)rte_memcpy(&mv_f[i].macaddr,
-                                        &f->mac_info.mac_addr,
-                                        ETH_ADDR_LEN);
-               }
-               if (filter_type == RTE_MACVLAN_PERFECT_MATCH ||
-                   filter_type == RTE_MACVLAN_HASH_MATCH) {
-                       ret = i40e_find_all_vlan_for_mac(vsi, mv_f, vlan_num,
-                                                        &f->mac_info.mac_addr);
-                       if (ret != I40E_SUCCESS) {
-                               rte_free(mv_f);
-                               return ret;
-                       }
-               }
-
-               ret = i40e_remove_macvlan_filters(vsi, mv_f, vlan_num);
-               if (ret != I40E_SUCCESS) {
-                       rte_free(mv_f);
-                       return ret;
-               }
-
-               rte_free(mv_f);
-               ret = I40E_SUCCESS;
-       }
-
-       return ret;
-}
-
-static int
-i40e_vsi_restore_mac_filter(struct i40e_vsi *vsi)
-{
-       struct i40e_mac_filter *f;
-       struct i40e_macvlan_filter *mv_f;
-       int i, vlan_num = 0;
-       int ret = I40E_SUCCESS;
-       void *temp;
-
-       /* restore all the MACs */
-       TAILQ_FOREACH_SAFE(f, &vsi->mac_list, next, temp) {
-               if ((f->mac_info.filter_type == RTE_MACVLAN_PERFECT_MATCH) ||
-                   (f->mac_info.filter_type == RTE_MACVLAN_HASH_MATCH)) {
-                       /**
-                        * If vlan_num is 0, that's the first time to add mac,
-                        * set mask for vlan_id 0.
-                        */
-                       if (vsi->vlan_num == 0) {
-                               i40e_set_vlan_filter(vsi, 0, 1);
-                               vsi->vlan_num = 1;
-                       }
-                       vlan_num = vsi->vlan_num;
-               } else if ((f->mac_info.filter_type == RTE_MAC_PERFECT_MATCH) ||
-                          (f->mac_info.filter_type == RTE_MAC_HASH_MATCH))
-                       vlan_num = 1;
-
-               mv_f = rte_zmalloc("macvlan_data", vlan_num * sizeof(*mv_f), 0);
-               if (!mv_f) {
-                       PMD_DRV_LOG(ERR, "failed to allocate memory");
-                       return I40E_ERR_NO_MEMORY;
-               }
-
-               for (i = 0; i < vlan_num; i++) {
-                       mv_f[i].filter_type = f->mac_info.filter_type;
-                       (void)rte_memcpy(&mv_f[i].macaddr,
-                                        &f->mac_info.mac_addr,
-                                        ETH_ADDR_LEN);
-               }
-
-               if (f->mac_info.filter_type == RTE_MACVLAN_PERFECT_MATCH ||
-                   f->mac_info.filter_type == RTE_MACVLAN_HASH_MATCH) {
-                       ret = i40e_find_all_vlan_for_mac(vsi, mv_f, vlan_num,
-                                                        &f->mac_info.mac_addr);
-                       if (ret != I40E_SUCCESS) {
-                               rte_free(mv_f);
-                               return ret;
-                       }
-               }
-
-               ret = i40e_add_macvlan_filters(vsi, mv_f, vlan_num);
-               if (ret != I40E_SUCCESS) {
-                       rte_free(mv_f);
-                       return ret;
-               }
-
-               rte_free(mv_f);
-               ret = I40E_SUCCESS;
-       }
-
-       return ret;
-}
-
-static int
-i40e_vsi_set_tx_loopback(struct i40e_vsi *vsi, uint8_t on)
+bool
+is_i40e_supported(struct rte_eth_dev *dev)
 {
-       struct i40e_vsi_context ctxt;
-       struct i40e_hw *hw;
-       int ret;
-
-       if (!vsi)
-               return -EINVAL;
-
-       hw = I40E_VSI_TO_HW(vsi);
-
-       /* Use the FW API if FW >= v5.0 */
-       if (hw->aq.fw_maj_ver < 5) {
-               PMD_INIT_LOG(ERR, "FW < v5.0, cannot enable loopback");
-               return -ENOTSUP;
-       }
-
-       /* Check if it has been already on or off */
-       if (vsi->info.valid_sections &
-               rte_cpu_to_le_16(I40E_AQ_VSI_PROP_SWITCH_VALID)) {
-               if (on) {
-                       if ((vsi->info.switch_id &
-                            I40E_AQ_VSI_SW_ID_FLAG_ALLOW_LB) ==
-                           I40E_AQ_VSI_SW_ID_FLAG_ALLOW_LB)
-                               return 0; /* already on */
-               } else {
-                       if ((vsi->info.switch_id &
-                            I40E_AQ_VSI_SW_ID_FLAG_ALLOW_LB) == 0)
-                               return 0; /* already off */
-               }
-       }
-
-       /* remove all the MAC and VLAN first */
-       ret = i40e_vsi_rm_mac_filter(vsi);
-       if (ret) {
-               PMD_INIT_LOG(ERR, "Failed to remove MAC filters.");
-               return ret;
-       }
-       if (vsi->vlan_anti_spoof_on || vsi->vlan_filter_on) {
-               ret = i40e_add_rm_all_vlan_filter(vsi, 0);
-               if (ret) {
-                       PMD_INIT_LOG(ERR, "Failed to remove VLAN filters.");
-                       return ret;
-               }
-       }
-
-       vsi->info.valid_sections = cpu_to_le16(I40E_AQ_VSI_PROP_SWITCH_VALID);
-       if (on)
-               vsi->info.switch_id |= I40E_AQ_VSI_SW_ID_FLAG_ALLOW_LB;
-       else
-               vsi->info.switch_id &= ~I40E_AQ_VSI_SW_ID_FLAG_ALLOW_LB;
-
-       memset(&ctxt, 0, sizeof(ctxt));
-       (void)rte_memcpy(&ctxt.info, &vsi->info, sizeof(vsi->info));
-       ctxt.seid = vsi->seid;
-
-       ret = i40e_aq_update_vsi_params(hw, &ctxt, NULL);
-       if (ret != I40E_SUCCESS) {
-               PMD_DRV_LOG(ERR, "Failed to update VSI params");
-               return ret;
-       }
-
-       /* add all the MAC and VLAN back */
-       ret = i40e_vsi_restore_mac_filter(vsi);
-       if (ret)
-               return ret;
-       if (vsi->vlan_anti_spoof_on || vsi->vlan_filter_on) {
-               ret = i40e_add_rm_all_vlan_filter(vsi, 1);
-               if (ret)
-                       return ret;
-       }
-
-       return ret;
-}
-
-int
-rte_pmd_i40e_set_tx_loopback(uint8_t port, uint8_t on)
-{
-       struct rte_eth_dev *dev;
-       struct i40e_pf *pf;
-       struct i40e_pf_vf *vf;
-       struct i40e_vsi *vsi;
-       uint16_t vf_id;
-       int ret;
-
-       RTE_ETH_VALID_PORTID_OR_ERR_RET(port, -ENODEV);
-
-       dev = &rte_eth_devices[port];
-
-       if (!is_device_supported(dev, &rte_i40e_pmd))
-               return -ENOTSUP;
-
-       pf = I40E_DEV_PRIVATE_TO_PF(dev->data->dev_private);
-
-       /* setup PF TX loopback */
-       vsi = pf->main_vsi;
-       ret = i40e_vsi_set_tx_loopback(vsi, on);
-       if (ret)
-               return -ENOTSUP;
-
-       /* setup TX loopback for all the VFs */
-       if (!pf->vfs) {
-               /* if no VF, do nothing. */
-               return 0;
-       }
-
-       for (vf_id = 0; vf_id < pf->vf_num; vf_id++) {
-               vf = &pf->vfs[vf_id];
-               vsi = vf->vsi;
-
-               ret = i40e_vsi_set_tx_loopback(vsi, on);
-               if (ret)
-                       return -ENOTSUP;
-       }
-
-       return ret;
-}
-
-int
-rte_pmd_i40e_set_vf_unicast_promisc(uint8_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_device_supported(dev, &rte_i40e_pmd))
-               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;
-       }
-
-       hw = I40E_VSI_TO_HW(vsi);
-
-       ret = i40e_aq_set_vsi_unicast_promiscuous(hw, vsi->seid,
-                                                 on, NULL, true);
-       if (ret != I40E_SUCCESS) {
-               ret = -ENOTSUP;
-               PMD_DRV_LOG(ERR, "Failed to set unicast promiscuous mode");
-       }
-
-       return ret;
-}
-
-int
-rte_pmd_i40e_set_vf_multicast_promisc(uint8_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_device_supported(dev, &rte_i40e_pmd))
-               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;
-       }
-
-       hw = I40E_VSI_TO_HW(vsi);
-
-       ret = i40e_aq_set_vsi_multicast_promiscuous(hw, vsi->seid,
-                                                   on, NULL);
-       if (ret != I40E_SUCCESS) {
-               ret = -ENOTSUP;
-               PMD_DRV_LOG(ERR, "Failed to set multicast promiscuous mode");
-       }
-
-       return ret;
-}
-
-int
-rte_pmd_i40e_set_vf_mac_addr(uint8_t port, uint16_t vf_id,
-                            struct ether_addr *mac_addr)
-{
-       struct i40e_mac_filter *f;
-       struct rte_eth_dev *dev;
-       struct i40e_pf_vf *vf;
-       struct i40e_vsi *vsi;
-       struct i40e_pf *pf;
-       void *temp;
-
-       if (i40e_validate_mac_addr((u8 *)mac_addr) != I40E_SUCCESS)
-               return -EINVAL;
-
-       RTE_ETH_VALID_PORTID_OR_ERR_RET(port, -ENODEV);
-
-       dev = &rte_eth_devices[port];
-
-       if (!is_device_supported(dev, &rte_i40e_pmd))
-               return -ENOTSUP;
-
-       pf = I40E_DEV_PRIVATE_TO_PF(dev->data->dev_private);
-
-       if (vf_id >= pf->vf_num || !pf->vfs)
-               return -EINVAL;
-
-       vf = &pf->vfs[vf_id];
-       vsi = vf->vsi;
-       if (!vsi) {
-               PMD_DRV_LOG(ERR, "Invalid VSI.");
-               return -EINVAL;
-       }
-
-       ether_addr_copy(mac_addr, &vf->mac_addr);
-
-       /* Remove all existing mac */
-       TAILQ_FOREACH_SAFE(f, &vsi->mac_list, next, temp)
-               i40e_vsi_delete_mac(vsi, &f->mac_info.mac_addr);
-
-       return 0;
-}
-
-/* Set vlan strip on/off for specific VF from host */
-int
-rte_pmd_i40e_set_vf_vlan_stripq(uint8_t port, uint16_t vf_id, uint8_t on)
-{
-       struct rte_eth_dev *dev;
-       struct i40e_pf *pf;
-       struct i40e_vsi *vsi;
-       int ret;
-
-       RTE_ETH_VALID_PORTID_OR_ERR_RET(port, -ENODEV);
-
-       dev = &rte_eth_devices[port];
-
-       if (!is_device_supported(dev, &rte_i40e_pmd))
-               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)
-               return -EINVAL;
-
-       ret = i40e_vsi_config_vlan_stripping(vsi, !!on);
-       if (ret != I40E_SUCCESS) {
-               ret = -ENOTSUP;
-               PMD_DRV_LOG(ERR, "Failed to set VLAN stripping!");
-       }
-
-       return ret;
-}
-
-int rte_pmd_i40e_set_vf_vlan_insert(uint8_t port, uint16_t vf_id,
-                                   uint16_t vlan_id)
-{
-       struct rte_eth_dev *dev;
-       struct i40e_pf *pf;
-       struct i40e_hw *hw;
-       struct i40e_vsi *vsi;
-       struct i40e_vsi_context ctxt;
-       int ret;
-
-       RTE_ETH_VALID_PORTID_OR_ERR_RET(port, -ENODEV);
-
-       if (vlan_id > ETHER_MAX_VLAN_ID) {
-               PMD_DRV_LOG(ERR, "Invalid VLAN ID.");
-               return -EINVAL;
-       }
-
-       dev = &rte_eth_devices[port];
-
-       if (!is_device_supported(dev, &rte_i40e_pmd))
-               return -ENOTSUP;
-
-       pf = I40E_DEV_PRIVATE_TO_PF(dev->data->dev_private);
-       hw = I40E_PF_TO_HW(pf);
-
-       /**
-        * return -ENODEV if SRIOV not enabled, VF number not configured
-        * or no queue assigned.
-        */
-       if (!hw->func_caps.sr_iov_1_1 || pf->vf_num == 0 ||
-           pf->vf_nb_qps == 0)
-               return -ENODEV;
-
-       if (vf_id >= pf->vf_num || !pf->vfs) {
-               PMD_DRV_LOG(ERR, "Invalid VF ID.");
-               return -EINVAL;
-       }
-
-       vsi = pf->vfs[vf_id].vsi;
-       if (!vsi) {
-               PMD_DRV_LOG(ERR, "Invalid VSI.");
-               return -EINVAL;
-       }
-
-       vsi->info.valid_sections = cpu_to_le16(I40E_AQ_VSI_PROP_VLAN_VALID);
-       vsi->info.pvid = vlan_id;
-       if (vlan_id > 0)
-               vsi->info.port_vlan_flags |= I40E_AQ_VSI_PVLAN_INSERT_PVID;
-       else
-               vsi->info.port_vlan_flags &= ~I40E_AQ_VSI_PVLAN_INSERT_PVID;
-
-       memset(&ctxt, 0, sizeof(ctxt));
-       (void)rte_memcpy(&ctxt.info, &vsi->info, sizeof(vsi->info));
-       ctxt.seid = vsi->seid;
-
-       hw = I40E_VSI_TO_HW(vsi);
-       ret = i40e_aq_update_vsi_params(hw, &ctxt, NULL);
-       if (ret != I40E_SUCCESS) {
-               ret = -ENOTSUP;
-               PMD_DRV_LOG(ERR, "Failed to update VSI params");
-       }
-
-       return ret;
-}
-
-int rte_pmd_i40e_set_vf_broadcast(uint8_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;
-       struct i40e_mac_filter_info filter;
-       struct ether_addr broadcast = {
-               .addr_bytes = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff} };
-       int ret;
-
-       RTE_ETH_VALID_PORTID_OR_ERR_RET(port, -ENODEV);
-
-       if (on > 1) {
-               PMD_DRV_LOG(ERR, "on should be 0 or 1.");
-               return -EINVAL;
-       }
-
-       dev = &rte_eth_devices[port];
-
-       if (!is_device_supported(dev, &rte_i40e_pmd))
-               return -ENOTSUP;
-
-       pf = I40E_DEV_PRIVATE_TO_PF(dev->data->dev_private);
-       hw = I40E_PF_TO_HW(pf);
-
-       if (vf_id >= pf->vf_num || !pf->vfs) {
-               PMD_DRV_LOG(ERR, "Invalid VF ID.");
-               return -EINVAL;
-       }
-
-       /**
-        * return -ENODEV if SRIOV not enabled, VF number not configured
-        * or no queue assigned.
-        */
-       if (!hw->func_caps.sr_iov_1_1 || pf->vf_num == 0 ||
-           pf->vf_nb_qps == 0) {
-               PMD_DRV_LOG(ERR, "SRIOV is not enabled or no queue.");
-               return -ENODEV;
-       }
-
-       vsi = pf->vfs[vf_id].vsi;
-       if (!vsi) {
-               PMD_DRV_LOG(ERR, "Invalid VSI.");
-               return -EINVAL;
-       }
-
-       if (on) {
-               (void)rte_memcpy(&filter.mac_addr, &broadcast, ETHER_ADDR_LEN);
-               filter.filter_type = RTE_MACVLAN_PERFECT_MATCH;
-               ret = i40e_vsi_add_mac(vsi, &filter);
-       } else {
-               ret = i40e_vsi_delete_mac(vsi, &broadcast);
-       }
-
-       if (ret != I40E_SUCCESS && ret != I40E_ERR_PARAM) {
-               ret = -ENOTSUP;
-               PMD_DRV_LOG(ERR, "Failed to set VSI broadcast");
-       } else {
-               ret = 0;
-       }
-
-       return ret;
-}
-
-int rte_pmd_i40e_set_vf_vlan_tag(uint8_t port, uint16_t vf_id, uint8_t on)
-{
-       struct rte_eth_dev *dev;
-       struct i40e_pf *pf;
-       struct i40e_hw *hw;
-       struct i40e_vsi *vsi;
-       struct i40e_vsi_context ctxt;
-       int ret;
-
-       RTE_ETH_VALID_PORTID_OR_ERR_RET(port, -ENODEV);
-
-       if (on > 1) {
-               PMD_DRV_LOG(ERR, "on should be 0 or 1.");
-               return -EINVAL;
-       }
-
-       dev = &rte_eth_devices[port];
-
-       if (!is_device_supported(dev, &rte_i40e_pmd))
-               return -ENOTSUP;
-
-       pf = I40E_DEV_PRIVATE_TO_PF(dev->data->dev_private);
-       hw = I40E_PF_TO_HW(pf);
-
-       /**
-        * return -ENODEV if SRIOV not enabled, VF number not configured
-        * or no queue assigned.
-        */
-       if (!hw->func_caps.sr_iov_1_1 || pf->vf_num == 0 ||
-           pf->vf_nb_qps == 0) {
-               PMD_DRV_LOG(ERR, "SRIOV is not enabled or no queue.");
-               return -ENODEV;
-       }
-
-       if (vf_id >= pf->vf_num || !pf->vfs) {
-               PMD_DRV_LOG(ERR, "Invalid VF ID.");
-               return -EINVAL;
-       }
-
-       vsi = pf->vfs[vf_id].vsi;
-       if (!vsi) {
-               PMD_DRV_LOG(ERR, "Invalid VSI.");
-               return -EINVAL;
-       }
-
-       vsi->info.valid_sections = cpu_to_le16(I40E_AQ_VSI_PROP_VLAN_VALID);
-       if (on) {
-               vsi->info.port_vlan_flags |= I40E_AQ_VSI_PVLAN_MODE_TAGGED;
-               vsi->info.port_vlan_flags &= ~I40E_AQ_VSI_PVLAN_MODE_UNTAGGED;
-       } else {
-               vsi->info.port_vlan_flags |= I40E_AQ_VSI_PVLAN_MODE_UNTAGGED;
-               vsi->info.port_vlan_flags &= ~I40E_AQ_VSI_PVLAN_MODE_TAGGED;
-       }
-
-       memset(&ctxt, 0, sizeof(ctxt));
-       (void)rte_memcpy(&ctxt.info, &vsi->info, sizeof(vsi->info));
-       ctxt.seid = vsi->seid;
-
-       hw = I40E_VSI_TO_HW(vsi);
-       ret = i40e_aq_update_vsi_params(hw, &ctxt, NULL);
-       if (ret != I40E_SUCCESS) {
-               ret = -ENOTSUP;
-               PMD_DRV_LOG(ERR, "Failed to update VSI params");
-       }
-
-       return ret;
-}
-
-static int
-i40e_vlan_filter_count(struct i40e_vsi *vsi)
-{
-       uint32_t j, k;
-       uint16_t vlan_id;
-       int count = 0;
-
-       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;
-
-                       count++;
-               }
-       }
-
-       return count;
-}
-
-int rte_pmd_i40e_set_vf_vlan_filter(uint8_t port, uint16_t vlan_id,
-                                   uint64_t vf_mask, uint8_t on)
-{
-       struct rte_eth_dev *dev;
-       struct i40e_pf *pf;
-       struct i40e_hw *hw;
-       struct i40e_vsi *vsi;
-       uint16_t vf_idx;
-       int ret = I40E_SUCCESS;
-
-       RTE_ETH_VALID_PORTID_OR_ERR_RET(port, -ENODEV);
-
-       dev = &rte_eth_devices[port];
-
-       if (!is_device_supported(dev, &rte_i40e_pmd))
-               return -ENOTSUP;
-
-       if (vlan_id > ETHER_MAX_VLAN_ID || !vlan_id) {
-               PMD_DRV_LOG(ERR, "Invalid VLAN ID.");
-               return -EINVAL;
-       }
-
-       if (vf_mask == 0) {
-               PMD_DRV_LOG(ERR, "No VF.");
-               return -EINVAL;
-       }
-
-       if (on > 1) {
-               PMD_DRV_LOG(ERR, "on is should be 0 or 1.");
-               return -EINVAL;
-       }
-
-       pf = I40E_DEV_PRIVATE_TO_PF(dev->data->dev_private);
-       hw = I40E_PF_TO_HW(pf);
-
-       /**
-        * return -ENODEV if SRIOV not enabled, VF number not configured
-        * or no queue assigned.
-        */
-       if (!hw->func_caps.sr_iov_1_1 || pf->vf_num == 0 ||
-           pf->vf_nb_qps == 0) {
-               PMD_DRV_LOG(ERR, "SRIOV is not enabled or no queue.");
-               return -ENODEV;
-       }
-
-       for (vf_idx = 0; vf_idx < pf->vf_num && ret == I40E_SUCCESS; vf_idx++) {
-               if (vf_mask & ((uint64_t)(1ULL << vf_idx))) {
-                       vsi = pf->vfs[vf_idx].vsi;
-                       if (on) {
-                               if (!vsi->vlan_filter_on) {
-                                       vsi->vlan_filter_on = true;
-                                       i40e_aq_set_vsi_vlan_promisc(hw,
-                                                                    vsi->seid,
-                                                                    false,
-                                                                    NULL);
-                                       if (!vsi->vlan_anti_spoof_on)
-                                               i40e_add_rm_all_vlan_filter(
-                                                       vsi, true);
-                               }
-                               ret = i40e_vsi_add_vlan(vsi, vlan_id);
-                       } else {
-                               ret = i40e_vsi_delete_vlan(vsi, vlan_id);
-
-                               if (!i40e_vlan_filter_count(vsi)) {
-                                       vsi->vlan_filter_on = false;
-                                       i40e_aq_set_vsi_vlan_promisc(hw,
-                                                                    vsi->seid,
-                                                                    true,
-                                                                    NULL);
-                               }
-                       }
-               }
-       }
-
-       if (ret != I40E_SUCCESS) {
-               ret = -ENOTSUP;
-               PMD_DRV_LOG(ERR, "Failed to set VF VLAN filter, on = %d", on);
-       }
-
-       return ret;
-}
-
-int
-rte_pmd_i40e_get_vf_stats(uint8_t port,
-                         uint16_t vf_id,
-                         struct rte_eth_stats *stats)
-{
-       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_device_supported(dev, &rte_i40e_pmd))
-               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 VF ID.");
-               return -EINVAL;
-       }
-
-       vsi = pf->vfs[vf_id].vsi;
-       if (!vsi) {
-               PMD_DRV_LOG(ERR, "Invalid VSI.");
-               return -EINVAL;
-       }
-
-       i40e_update_vsi_stats(vsi);
-
-       stats->ipackets = vsi->eth_stats.rx_unicast +
-                       vsi->eth_stats.rx_multicast +
-                       vsi->eth_stats.rx_broadcast;
-       stats->opackets = vsi->eth_stats.tx_unicast +
-                       vsi->eth_stats.tx_multicast +
-                       vsi->eth_stats.tx_broadcast;
-       stats->ibytes   = vsi->eth_stats.rx_bytes;
-       stats->obytes   = vsi->eth_stats.tx_bytes;
-       stats->ierrors  = vsi->eth_stats.rx_discards;
-       stats->oerrors  = vsi->eth_stats.tx_errors + vsi->eth_stats.tx_discards;
-
-       return 0;
-}
-
-int
-rte_pmd_i40e_reset_vf_stats(uint8_t port,
-                           uint16_t vf_id)
-{
-       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_device_supported(dev, &rte_i40e_pmd))
-               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 VF ID.");
-               return -EINVAL;
-       }
-
-       vsi = pf->vfs[vf_id].vsi;
-       if (!vsi) {
-               PMD_DRV_LOG(ERR, "Invalid VSI.");
-               return -EINVAL;
-       }
-
-       vsi->offset_loaded = false;
-       i40e_update_vsi_stats(vsi);
-
-       return 0;
-}
-
-int
-rte_pmd_i40e_set_vf_max_bw(uint8_t port, uint16_t vf_id, uint32_t bw)
-{
-       struct rte_eth_dev *dev;
-       struct i40e_pf *pf;
-       struct i40e_vsi *vsi;
-       struct i40e_hw *hw;
-       int ret = 0;
-       int i;
-
-       RTE_ETH_VALID_PORTID_OR_ERR_RET(port, -ENODEV);
-
-       dev = &rte_eth_devices[port];
-
-       if (!is_device_supported(dev, &rte_i40e_pmd))
-               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 VF ID.");
-               return -EINVAL;
-       }
-
-       vsi = pf->vfs[vf_id].vsi;
-       if (!vsi) {
-               PMD_DRV_LOG(ERR, "Invalid VSI.");
-               return -EINVAL;
-       }
-
-       if (bw > I40E_QOS_BW_MAX) {
-               PMD_DRV_LOG(ERR, "Bandwidth should not be larger than %dMbps.",
-                           I40E_QOS_BW_MAX);
-               return -EINVAL;
-       }
-
-       if (bw % I40E_QOS_BW_GRANULARITY) {
-               PMD_DRV_LOG(ERR, "Bandwidth should be the multiple of %dMbps.",
-                           I40E_QOS_BW_GRANULARITY);
-               return -EINVAL;
-       }
-
-       bw /= I40E_QOS_BW_GRANULARITY;
-
-       hw = I40E_VSI_TO_HW(vsi);
-
-       /* No change. */
-       if (bw == vsi->bw_info.bw_limit) {
-               PMD_DRV_LOG(INFO,
-                           "No change for VF max bandwidth. Nothing to do.");
-               return 0;
-       }
-
-       /**
-        * VF bandwidth limitation and TC bandwidth limitation cannot be
-        * enabled in parallel, quit if TC bandwidth limitation is enabled.
-        *
-        * If bw is 0, means disable bandwidth limitation. Then no need to
-        * check TC bandwidth limitation.
-        */
-       if (bw) {
-               for (i = 0; i < I40E_MAX_TRAFFIC_CLASS; i++) {
-                       if ((vsi->enabled_tc & BIT_ULL(i)) &&
-                           vsi->bw_info.bw_ets_credits[i])
-                               break;
-               }
-               if (i != I40E_MAX_TRAFFIC_CLASS) {
-                       PMD_DRV_LOG(ERR,
-                                   "TC max bandwidth has been set on this VF,"
-                                   " please disable it first.");
-                       return -EINVAL;
-               }
-       }
-
-       ret = i40e_aq_config_vsi_bw_limit(hw, vsi->seid, (uint16_t)bw, 0, NULL);
-       if (ret) {
-               PMD_DRV_LOG(ERR,
-                           "Failed to set VF %d bandwidth, err(%d).",
-                           vf_id, ret);
-               return -EINVAL;
-       }
-
-       /* Store the configuration. */
-       vsi->bw_info.bw_limit = (uint16_t)bw;
-       vsi->bw_info.bw_max = 0;
-
-       return 0;
-}
-
-int
-rte_pmd_i40e_set_vf_tc_bw_alloc(uint8_t port, uint16_t vf_id,
-                               uint8_t tc_num, uint8_t *bw_weight)
-{
-       struct rte_eth_dev *dev;
-       struct i40e_pf *pf;
-       struct i40e_vsi *vsi;
-       struct i40e_hw *hw;
-       struct i40e_aqc_configure_vsi_tc_bw_data tc_bw;
-       int ret = 0;
-       int i, j;
-       uint16_t sum;
-       bool b_change = false;
-
-       RTE_ETH_VALID_PORTID_OR_ERR_RET(port, -ENODEV);
-
-       dev = &rte_eth_devices[port];
-
-       if (!is_device_supported(dev, &rte_i40e_pmd))
-               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 VF ID.");
-               return -EINVAL;
-       }
-
-       vsi = pf->vfs[vf_id].vsi;
-       if (!vsi) {
-               PMD_DRV_LOG(ERR, "Invalid VSI.");
-               return -EINVAL;
-       }
-
-       if (tc_num > I40E_MAX_TRAFFIC_CLASS) {
-               PMD_DRV_LOG(ERR, "TCs should be no more than %d.",
-                           I40E_MAX_TRAFFIC_CLASS);
-               return -EINVAL;
-       }
-
-       sum = 0;
-       for (i = 0; i < I40E_MAX_TRAFFIC_CLASS; i++) {
-               if (vsi->enabled_tc & BIT_ULL(i))
-                       sum++;
-       }
-       if (sum != tc_num) {
-               PMD_DRV_LOG(ERR,
-                           "Weight should be set for all %d enabled TCs.",
-                           sum);
-               return -EINVAL;
-       }
-
-       sum = 0;
-       for (i = 0; i < tc_num; i++) {
-               if (!bw_weight[i]) {
-                       PMD_DRV_LOG(ERR,
-                                   "The weight should be 1 at least.");
-                       return -EINVAL;
-               }
-               sum += bw_weight[i];
-       }
-       if (sum != 100) {
-               PMD_DRV_LOG(ERR,
-                           "The summary of the TC weight should be 100.");
-               return -EINVAL;
-       }
-
-       /**
-        * Create the configuration for all the TCs.
-        */
-       memset(&tc_bw, 0, sizeof(tc_bw));
-       tc_bw.tc_valid_bits = vsi->enabled_tc;
-       j = 0;
-       for (i = 0; i < I40E_MAX_TRAFFIC_CLASS; i++) {
-               if (vsi->enabled_tc & BIT_ULL(i)) {
-                       if (bw_weight[j] !=
-                               vsi->bw_info.bw_ets_share_credits[i])
-                               b_change = true;
-
-                       tc_bw.tc_bw_credits[i] = bw_weight[j];
-                       j++;
-               }
-       }
-
-       /* No change. */
-       if (!b_change) {
-               PMD_DRV_LOG(INFO,
-                           "No change for TC allocated bandwidth."
-                           " Nothing to do.");
-               return 0;
-       }
-
-       hw = I40E_VSI_TO_HW(vsi);
-
-       ret = i40e_aq_config_vsi_tc_bw(hw, vsi->seid, &tc_bw, NULL);
-       if (ret) {
-               PMD_DRV_LOG(ERR,
-                           "Failed to set VF %d TC bandwidth weight, err(%d).",
-                           vf_id, ret);
-               return -EINVAL;
-       }
-
-       /* Store the configuration. */
-       j = 0;
-       for (i = 0; i < I40E_MAX_TRAFFIC_CLASS; i++) {
-               if (vsi->enabled_tc & BIT_ULL(i)) {
-                       vsi->bw_info.bw_ets_share_credits[i] = bw_weight[j];
-                       j++;
-               }
-       }
-
-       return 0;
-}
-
-int
-rte_pmd_i40e_set_vf_tc_max_bw(uint8_t port, uint16_t vf_id,
-                             uint8_t tc_no, uint32_t bw)
-{
-       struct rte_eth_dev *dev;
-       struct i40e_pf *pf;
-       struct i40e_vsi *vsi;
-       struct i40e_hw *hw;
-       struct i40e_aqc_configure_vsi_ets_sla_bw_data tc_bw;
-       int ret = 0;
-       int i;
-
-       RTE_ETH_VALID_PORTID_OR_ERR_RET(port, -ENODEV);
-
-       dev = &rte_eth_devices[port];
-
-       if (!is_device_supported(dev, &rte_i40e_pmd))
-               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 VF ID.");
-               return -EINVAL;
-       }
-
-       vsi = pf->vfs[vf_id].vsi;
-       if (!vsi) {
-               PMD_DRV_LOG(ERR, "Invalid VSI.");
-               return -EINVAL;
-       }
-
-       if (bw > I40E_QOS_BW_MAX) {
-               PMD_DRV_LOG(ERR, "Bandwidth should not be larger than %dMbps.",
-                           I40E_QOS_BW_MAX);
-               return -EINVAL;
-       }
-
-       if (bw % I40E_QOS_BW_GRANULARITY) {
-               PMD_DRV_LOG(ERR, "Bandwidth should be the multiple of %dMbps.",
-                           I40E_QOS_BW_GRANULARITY);
-               return -EINVAL;
-       }
-
-       bw /= I40E_QOS_BW_GRANULARITY;
-
-       if (tc_no >= I40E_MAX_TRAFFIC_CLASS) {
-               PMD_DRV_LOG(ERR, "TC No. should be less than %d.",
-                           I40E_MAX_TRAFFIC_CLASS);
-               return -EINVAL;
-       }
-
-       hw = I40E_VSI_TO_HW(vsi);
-
-       if (!(vsi->enabled_tc & BIT_ULL(tc_no))) {
-               PMD_DRV_LOG(ERR, "VF %d TC %d isn't enabled.",
-                           vf_id, tc_no);
-               return -EINVAL;
-       }
-
-       /* No change. */
-       if (bw == vsi->bw_info.bw_ets_credits[tc_no]) {
-               PMD_DRV_LOG(INFO,
-                           "No change for TC max bandwidth. Nothing to do.");
-               return 0;
-       }
-
-       /**
-        * VF bandwidth limitation and TC bandwidth limitation cannot be
-        * enabled in parallel, disable VF bandwidth limitation if it's
-        * enabled.
-        * If bw is 0, means disable bandwidth limitation. Then no need to
-        * care about VF bandwidth limitation configuration.
-        */
-       if (bw && vsi->bw_info.bw_limit) {
-               ret = i40e_aq_config_vsi_bw_limit(hw, vsi->seid, 0, 0, NULL);
-               if (ret) {
-                       PMD_DRV_LOG(ERR,
-                                   "Failed to disable VF(%d)"
-                                   " bandwidth limitation, err(%d).",
-                                   vf_id, ret);
-                       return -EINVAL;
-               }
-
-               PMD_DRV_LOG(INFO,
-                           "VF max bandwidth is disabled according"
-                           " to TC max bandwidth setting.");
-       }
-
-       /**
-        * Get all the TCs' info to create a whole picture.
-        * Because the incremental change isn't permitted.
-        */
-       memset(&tc_bw, 0, sizeof(tc_bw));
-       tc_bw.tc_valid_bits = vsi->enabled_tc;
-       for (i = 0; i < I40E_MAX_TRAFFIC_CLASS; i++) {
-               if (vsi->enabled_tc & BIT_ULL(i)) {
-                       tc_bw.tc_bw_credits[i] =
-                               rte_cpu_to_le_16(
-                                       vsi->bw_info.bw_ets_credits[i]);
-               }
-       }
-       tc_bw.tc_bw_credits[tc_no] = rte_cpu_to_le_16((uint16_t)bw);
-
-       ret = i40e_aq_config_vsi_ets_sla_bw_limit(hw, vsi->seid, &tc_bw, NULL);
-       if (ret) {
-               PMD_DRV_LOG(ERR,
-                           "Failed to set VF %d TC %d max bandwidth, err(%d).",
-                           vf_id, tc_no, ret);
-               return -EINVAL;
-       }
-
-       /* Store the configuration. */
-       vsi->bw_info.bw_ets_credits[tc_no] = (uint16_t)bw;
-
-       return 0;
-}
-
-int
-rte_pmd_i40e_set_tc_strict_prio(uint8_t port, uint8_t tc_map)
-{
-       struct rte_eth_dev *dev;
-       struct i40e_pf *pf;
-       struct i40e_vsi *vsi;
-       struct i40e_veb *veb;
-       struct i40e_hw *hw;
-       struct i40e_aqc_configure_switching_comp_ets_data ets_data;
-       int i;
-       int ret;
-
-       RTE_ETH_VALID_PORTID_OR_ERR_RET(port, -ENODEV);
-
-       dev = &rte_eth_devices[port];
-
-       if (!is_device_supported(dev, &rte_i40e_pmd))
-               return -ENOTSUP;
-
-       pf = I40E_DEV_PRIVATE_TO_PF(dev->data->dev_private);
-
-       vsi = pf->main_vsi;
-       if (!vsi) {
-               PMD_DRV_LOG(ERR, "Invalid VSI.");
-               return -EINVAL;
-       }
-
-       veb = vsi->veb;
-       if (!veb) {
-               PMD_DRV_LOG(ERR, "Invalid VEB.");
-               return -EINVAL;
-       }
-
-       if ((tc_map & veb->enabled_tc) != tc_map) {
-               PMD_DRV_LOG(ERR,
-                           "TC bitmap isn't the subset of enabled TCs 0x%x.",
-                           veb->enabled_tc);
-               return -EINVAL;
-       }
-
-       if (tc_map == veb->strict_prio_tc) {
-               PMD_DRV_LOG(INFO, "No change for TC bitmap. Nothing to do.");
-               return 0;
-       }
-
-       hw = I40E_VSI_TO_HW(vsi);
-
-       /* Disable DCBx if it's the first time to set strict priority. */
-       if (!veb->strict_prio_tc) {
-               ret = i40e_aq_stop_lldp(hw, true, NULL);
-               if (ret)
-                       PMD_DRV_LOG(INFO,
-                                   "Failed to disable DCBx as it's already"
-                                   " disabled.");
-               else
-                       PMD_DRV_LOG(INFO,
-                                   "DCBx is disabled according to strict"
-                                   " priority setting.");
-       }
-
-       memset(&ets_data, 0, sizeof(ets_data));
-       ets_data.tc_valid_bits = veb->enabled_tc;
-       ets_data.seepage = I40E_AQ_ETS_SEEPAGE_EN_MASK;
-       ets_data.tc_strict_priority_flags = tc_map;
-       /* Get all TCs' bandwidth. */
-       for (i = 0; i < I40E_MAX_TRAFFIC_CLASS; i++) {
-               if (veb->enabled_tc & BIT_ULL(i)) {
-                       /* For rubust, if bandwidth is 0, use 1 instead. */
-                       if (veb->bw_info.bw_ets_share_credits[i])
-                               ets_data.tc_bw_share_credits[i] =
-                                       veb->bw_info.bw_ets_share_credits[i];
-                       else
-                               ets_data.tc_bw_share_credits[i] =
-                                       I40E_QOS_BW_WEIGHT_MIN;
-               }
-       }
-
-       if (!veb->strict_prio_tc)
-               ret = i40e_aq_config_switch_comp_ets(
-                       hw, veb->uplink_seid,
-                       &ets_data, i40e_aqc_opc_enable_switching_comp_ets,
-                       NULL);
-       else if (tc_map)
-               ret = i40e_aq_config_switch_comp_ets(
-                       hw, veb->uplink_seid,
-                       &ets_data, i40e_aqc_opc_modify_switching_comp_ets,
-                       NULL);
-       else
-               ret = i40e_aq_config_switch_comp_ets(
-                       hw, veb->uplink_seid,
-                       &ets_data, i40e_aqc_opc_disable_switching_comp_ets,
-                       NULL);
-
-       if (ret) {
-               PMD_DRV_LOG(ERR,
-                           "Failed to set TCs' strict priority mode."
-                           " err (%d)", ret);
-               return -EINVAL;
-       }
-
-       veb->strict_prio_tc = tc_map;
-
-       /* Enable DCBx again, if all the TCs' strict priority disabled. */
-       if (!tc_map) {
-               ret = i40e_aq_start_lldp(hw, NULL);
-               if (ret) {
-                       PMD_DRV_LOG(ERR,
-                                   "Failed to enable DCBx, err(%d).", ret);
-                       return -EINVAL;
-               }
-
-               PMD_DRV_LOG(INFO,
-                           "DCBx is enabled again according to strict"
-                           " priority setting.");
-       }
-
-       return ret;
-}
-
-#define I40E_PROFILE_INFO_SIZE 48
-#define I40E_MAX_PROFILE_NUM 16
-
-static void
-i40e_generate_profile_info_sec(char *name, struct i40e_ddp_version *version,
-                              uint32_t track_id, uint8_t *profile_info_sec,
-                              bool add)
-{
-       struct i40e_profile_section_header *sec = NULL;
-       struct i40e_profile_info *pinfo;
-
-       sec = (struct i40e_profile_section_header *)profile_info_sec;
-       sec->tbl_size = 1;
-       sec->data_end = sizeof(struct i40e_profile_section_header) +
-               sizeof(struct i40e_profile_info);
-       sec->section.type = SECTION_TYPE_INFO;
-       sec->section.offset = sizeof(struct i40e_profile_section_header);
-       sec->section.size = sizeof(struct i40e_profile_info);
-       pinfo = (struct i40e_profile_info *)(profile_info_sec +
-                                            sec->section.offset);
-       pinfo->track_id = track_id;
-       memcpy(pinfo->name, name, I40E_DDP_NAME_SIZE);
-       memcpy(&pinfo->version, version, sizeof(struct i40e_ddp_version));
-       if (add)
-               pinfo->op = I40E_DDP_ADD_TRACKID;
-       else
-               pinfo->op = I40E_DDP_REMOVE_TRACKID;
-}
-
-static enum i40e_status_code
-i40e_add_rm_profile_info(struct i40e_hw *hw, uint8_t *profile_info_sec)
-{
-       enum i40e_status_code status = I40E_SUCCESS;
-       struct i40e_profile_section_header *sec;
-       uint32_t track_id;
-       uint32_t offset = 0;
-       uint32_t info = 0;
-
-       sec = (struct i40e_profile_section_header *)profile_info_sec;
-       track_id = ((struct i40e_profile_info *)(profile_info_sec +
-                                        sec->section.offset))->track_id;
-
-       status = i40e_aq_write_ddp(hw, (void *)sec, sec->data_end,
-                                  track_id, &offset, &info, NULL);
-       if (status)
-               PMD_DRV_LOG(ERR, "Failed to add/remove profile info: "
-                           "offset %d, info %d",
-                           offset, info);
-
-       return status;
-}
-
-#define I40E_PROFILE_INFO_SIZE 48
-#define I40E_MAX_PROFILE_NUM 16
-
-/* Check if the profile info exists */
-static int
-i40e_check_profile_info(uint8_t port, uint8_t *profile_info_sec)
-{
-       struct rte_eth_dev *dev = &rte_eth_devices[port];
-       struct i40e_hw *hw = I40E_DEV_PRIVATE_TO_HW(dev->data->dev_private);
-       uint8_t *buff;
-       struct rte_pmd_i40e_profile_list *p_list;
-       struct rte_pmd_i40e_profile_info *pinfo, *p;
-       uint32_t i;
-       int ret;
-
-       buff = rte_zmalloc("pinfo_list",
-                          (I40E_PROFILE_INFO_SIZE * I40E_MAX_PROFILE_NUM + 4),
-                          0);
-       if (!buff) {
-               PMD_DRV_LOG(ERR, "failed to allocate memory");
-               return -1;
-       }
-
-       ret = i40e_aq_get_ddp_list(hw, (void *)buff,
-                     (I40E_PROFILE_INFO_SIZE * I40E_MAX_PROFILE_NUM + 4),
-                     0, NULL);
-       if (ret) {
-               PMD_DRV_LOG(ERR, "Failed to get profile info list.");
-               rte_free(buff);
-               return -1;
-       }
-       p_list = (struct rte_pmd_i40e_profile_list *)buff;
-       pinfo = (struct rte_pmd_i40e_profile_info *)(profile_info_sec +
-                            sizeof(struct i40e_profile_section_header));
-       for (i = 0; i < p_list->p_count; i++) {
-               p = &p_list->p_info[i];
-               if ((pinfo->track_id == p->track_id) &&
-                   !memcmp(&pinfo->version, &p->version,
-                           sizeof(struct i40e_ddp_version)) &&
-                   !memcmp(&pinfo->name, &p->name,
-                           I40E_DDP_NAME_SIZE)) {
-                       PMD_DRV_LOG(INFO, "Profile exists.");
-                       rte_free(buff);
-                       return 1;
-               }
-       }
-
-       rte_free(buff);
-       return 0;
-}
-
-int
-rte_pmd_i40e_process_ddp_package(uint8_t port, uint8_t *buff,
-                                uint32_t size,
-                                enum rte_pmd_i40e_package_op op)
-{
-       struct rte_eth_dev *dev;
-       struct i40e_hw *hw;
-       struct i40e_package_header *pkg_hdr;
-       struct i40e_generic_seg_header *profile_seg_hdr;
-       struct i40e_generic_seg_header *metadata_seg_hdr;
-       uint32_t track_id;
-       uint8_t *profile_info_sec;
-       int is_exist;
-       enum i40e_status_code status = I40E_SUCCESS;
-
-       RTE_ETH_VALID_PORTID_OR_ERR_RET(port, -ENODEV);
-
-       dev = &rte_eth_devices[port];
-
-       if (!is_device_supported(dev, &rte_i40e_pmd))
-               return -ENOTSUP;
-
-       hw = I40E_DEV_PRIVATE_TO_HW(dev->data->dev_private);
-
-       if (size < (sizeof(struct i40e_package_header) +
-                   sizeof(struct i40e_metadata_segment) +
-                   sizeof(uint32_t) * 2)) {
-               PMD_DRV_LOG(ERR, "Buff is invalid.");
-               return -EINVAL;
-       }
-
-       pkg_hdr = (struct i40e_package_header *)buff;
-
-       if (!pkg_hdr) {
-               PMD_DRV_LOG(ERR, "Failed to fill the package structure");
-               return -EINVAL;
-       }
-
-       if (pkg_hdr->segment_count < 2) {
-               PMD_DRV_LOG(ERR, "Segment_count should be 2 at least.");
-               return -EINVAL;
-       }
-
-       /* Find metadata segment */
-       metadata_seg_hdr = i40e_find_segment_in_package(SEGMENT_TYPE_METADATA,
-                                                       pkg_hdr);
-       if (!metadata_seg_hdr) {
-               PMD_DRV_LOG(ERR, "Failed to find metadata segment header");
-               return -EINVAL;
-       }
-       track_id = ((struct i40e_metadata_segment *)metadata_seg_hdr)->track_id;
-
-       /* Find profile segment */
-       profile_seg_hdr = i40e_find_segment_in_package(SEGMENT_TYPE_I40E,
-                                                      pkg_hdr);
-       if (!profile_seg_hdr) {
-               PMD_DRV_LOG(ERR, "Failed to find profile segment header");
-               return -EINVAL;
-       }
-
-       profile_info_sec = rte_zmalloc("i40e_profile_info",
-                              sizeof(struct i40e_profile_section_header) +
-                              sizeof(struct i40e_profile_info),
-                              0);
-       if (!profile_info_sec) {
-               PMD_DRV_LOG(ERR, "Failed to allocate memory");
-               return -EINVAL;
-       }
-
-       if (op == RTE_PMD_I40E_PKG_OP_WR_ADD) {
-               /* Check if the profile exists */
-               i40e_generate_profile_info_sec(
-                    ((struct i40e_profile_segment *)profile_seg_hdr)->name,
-                    &((struct i40e_profile_segment *)profile_seg_hdr)->version,
-                    track_id, profile_info_sec, 1);
-               is_exist = i40e_check_profile_info(port, profile_info_sec);
-               if (is_exist > 0) {
-                       PMD_DRV_LOG(ERR, "Profile already exists.");
-                       rte_free(profile_info_sec);
-                       return 1;
-               } else if (is_exist < 0) {
-                       PMD_DRV_LOG(ERR, "Failed to check profile.");
-                       rte_free(profile_info_sec);
-                       return -EINVAL;
-               }
-
-               /* Write profile to HW */
-               status = i40e_write_profile(hw,
-                                (struct i40e_profile_segment *)profile_seg_hdr,
-                                track_id);
-               if (status) {
-                       PMD_DRV_LOG(ERR, "Failed to write profile.");
-                       rte_free(profile_info_sec);
-                       return status;
-               }
-
-               /* Add profile info to info list */
-               status = i40e_add_rm_profile_info(hw, profile_info_sec);
-               if (status)
-                       PMD_DRV_LOG(ERR, "Failed to add profile info.");
-       } else
-               PMD_DRV_LOG(ERR, "Operation not supported.");
-
-       rte_free(profile_info_sec);
-       return status;
-}
-
-int
-rte_pmd_i40e_get_ddp_list(uint8_t port, uint8_t *buff, uint32_t size)
-{
-       struct rte_eth_dev *dev;
-       struct i40e_hw *hw;
-       enum i40e_status_code status = I40E_SUCCESS;
-
-       RTE_ETH_VALID_PORTID_OR_ERR_RET(port, -ENODEV);
-
-       dev = &rte_eth_devices[port];
-
-       if (!is_device_supported(dev, &rte_i40e_pmd))
-               return -ENOTSUP;
-
-       if (size < (I40E_PROFILE_INFO_SIZE * I40E_MAX_PROFILE_NUM + 4))
-               return -EINVAL;
-
-       hw = I40E_DEV_PRIVATE_TO_HW(dev->data->dev_private);
-
-       status = i40e_aq_get_ddp_list(hw, (void *)buff,
-                                     size, 0, NULL);
-
-       return status;
+       return is_device_supported(dev, &rte_i40e_pmd);
 }
 
 /* Create a QinQ cloud filter
index 69c6684..c745e9b 100644 (file)
@@ -869,6 +869,17 @@ int i40e_dev_consistent_tunnel_filter_set(struct i40e_pf *pf,
                                  struct i40e_tunnel_filter_conf *tunnel_filter,
                                  uint8_t add);
 int i40e_fdir_flush(struct rte_eth_dev *dev);
+int i40e_find_all_vlan_for_mac(struct i40e_vsi *vsi,
+                              struct i40e_macvlan_filter *mv_f,
+                              int num, struct ether_addr *addr);
+int i40e_remove_macvlan_filters(struct i40e_vsi *vsi,
+                               struct i40e_macvlan_filter *filter,
+                               int total);
+void i40e_set_vlan_filter(struct i40e_vsi *vsi, uint16_t vlan_id, bool on);
+int i40e_add_macvlan_filters(struct i40e_vsi *vsi,
+                            struct i40e_macvlan_filter *filter,
+                            int total);
+bool is_i40e_supported(struct rte_eth_dev *dev);
 
 #define I40E_DEV_TO_PCI(eth_dev) \
        RTE_DEV_TO_PCI((eth_dev)->device)
diff --git a/drivers/net/i40e/rte_pmd_i40e.c b/drivers/net/i40e/rte_pmd_i40e.c
new file mode 100644 (file)
index 0000000..cee067b
--- /dev/null
@@ -0,0 +1,1707 @@
+/*-
+ *   BSD LICENSE
+ *
+ *   Copyright(c) 2010-2017 Intel Corporation. All rights reserved.
+ *   All rights reserved.
+ *
+ *   Redistribution and use in source and binary forms, with or without
+ *   modification, are permitted provided that the following conditions
+ *   are met:
+ *
+ *     * Redistributions of source code must retain the above copyright
+ *       notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above copyright
+ *       notice, this list of conditions and the following disclaimer in
+ *       the documentation and/or other materials provided with the
+ *       distribution.
+ *     * Neither the name of Intel Corporation nor the names of its
+ *       contributors may be used to endorse or promote products derived
+ *       from this software without specific prior written permission.
+ *
+ *   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ *   "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ *   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ *   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ *   OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ *   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ *   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ *   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ *   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ *   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ *   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <rte_malloc.h>
+#include <rte_tailq.h>
+
+#include "base/i40e_prototype.h"
+#include "i40e_ethdev.h"
+#include "i40e_pf.h"
+#include "rte_pmd_i40e.h"
+
+/* The max bandwidth of i40e is 40Gbps. */
+#define I40E_QOS_BW_MAX 40000
+/* The bandwidth should be the multiple of 50Mbps. */
+#define I40E_QOS_BW_GRANULARITY 50
+/* The min bandwidth weight is 1. */
+#define I40E_QOS_BW_WEIGHT_MIN 1
+/* The max bandwidth weight is 127. */
+#define I40E_QOS_BW_WEIGHT_MAX 127
+
+int
+rte_pmd_i40e_ping_vfs(uint8_t port, uint16_t vf)
+{
+       struct rte_eth_dev *dev;
+       struct i40e_pf *pf;
+
+       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 >= pf->vf_num || !pf->vfs) {
+               PMD_DRV_LOG(ERR, "Invalid argument.");
+               return -EINVAL;
+       }
+
+       i40e_notify_vf_link_status(dev, &pf->vfs[vf]);
+
+       return 0;
+}
+
+int
+rte_pmd_i40e_set_vf_mac_anti_spoof(uint8_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;
+       struct i40e_vsi_context ctxt;
+       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;
+       }
+
+       /* 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)) {
+               if (on) {
+                       if ((vsi->info.sec_flags &
+                            I40E_AQ_VSI_SEC_FLAG_ENABLE_MAC_CHK) ==
+                           I40E_AQ_VSI_SEC_FLAG_ENABLE_MAC_CHK)
+                               return 0; /* already on */
+               } else {
+                       if ((vsi->info.sec_flags &
+                            I40E_AQ_VSI_SEC_FLAG_ENABLE_MAC_CHK) == 0)
+                               return 0; /* already off */
+               }
+       }
+
+       vsi->info.valid_sections = cpu_to_le16(I40E_AQ_VSI_PROP_SECURITY_VALID);
+       if (on)
+               vsi->info.sec_flags |= I40E_AQ_VSI_SEC_FLAG_ENABLE_MAC_CHK;
+       else
+               vsi->info.sec_flags &= ~I40E_AQ_VSI_SEC_FLAG_ENABLE_MAC_CHK;
+
+       memset(&ctxt, 0, sizeof(ctxt));
+       (void)rte_memcpy(&ctxt.info, &vsi->info, sizeof(vsi->info));
+       ctxt.seid = vsi->seid;
+
+       hw = I40E_VSI_TO_HW(vsi);
+       ret = i40e_aq_update_vsi_params(hw, &ctxt, NULL);
+       if (ret != I40E_SUCCESS) {
+               ret = -ENOTSUP;
+               PMD_DRV_LOG(ERR, "Failed to update VSI params");
+       }
+
+       return ret;
+}
+
+static int
+i40e_add_rm_all_vlan_filter(struct i40e_vsi *vsi, uint8_t add)
+{
+       uint32_t j, k;
+       uint16_t vlan_id;
+       struct i40e_hw *hw = I40E_VSI_TO_HW(vsi);
+       struct i40e_aqc_add_remove_vlan_element_data vlan_data = {0};
+       int ret;
+
+       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;
+
+                       vlan_data.vlan_tag = rte_cpu_to_le_16(vlan_id);
+                       if (add)
+                               ret = i40e_aq_add_vlan(hw, vsi->seid,
+                                                      &vlan_data, 1, NULL);
+                       else
+                               ret = i40e_aq_remove_vlan(hw, vsi->seid,
+                                                         &vlan_data, 1, NULL);
+                       if (ret != I40E_SUCCESS) {
+                               PMD_DRV_LOG(ERR,
+                                           "Failed to add/rm vlan filter");
+                               return ret;
+                       }
+               }
+       }
+
+       return I40E_SUCCESS;
+}
+
+int
+rte_pmd_i40e_set_vf_vlan_anti_spoof(uint8_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;
+       struct i40e_vsi_context ctxt;
+       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;
+       }
+
+       /* Check if it has been already on or off */
+       if (vsi->vlan_anti_spoof_on == on)
+               return 0; /* already on or off */
+
+       vsi->vlan_anti_spoof_on = on;
+       if (!vsi->vlan_filter_on) {
+               ret = i40e_add_rm_all_vlan_filter(vsi, on);
+               if (ret) {
+                       PMD_DRV_LOG(ERR, "Failed to add/remove VLAN filters.");
+                       return -ENOTSUP;
+               }
+       }
+
+       vsi->info.valid_sections = cpu_to_le16(I40E_AQ_VSI_PROP_SECURITY_VALID);
+       if (on)
+               vsi->info.sec_flags |= I40E_AQ_VSI_SEC_FLAG_ENABLE_VLAN_CHK;
+       else
+               vsi->info.sec_flags &= ~I40E_AQ_VSI_SEC_FLAG_ENABLE_VLAN_CHK;
+
+       memset(&ctxt, 0, sizeof(ctxt));
+       (void)rte_memcpy(&ctxt.info, &vsi->info, sizeof(vsi->info));
+       ctxt.seid = vsi->seid;
+
+       hw = I40E_VSI_TO_HW(vsi);
+       ret = i40e_aq_update_vsi_params(hw, &ctxt, NULL);
+       if (ret != I40E_SUCCESS) {
+               ret = -ENOTSUP;
+               PMD_DRV_LOG(ERR, "Failed to update VSI params");
+       }
+
+       return ret;
+}
+
+static int
+i40e_vsi_rm_mac_filter(struct i40e_vsi *vsi)
+{
+       struct i40e_mac_filter *f;
+       struct i40e_macvlan_filter *mv_f;
+       int i, vlan_num;
+       enum rte_mac_filter_type filter_type;
+       int ret = I40E_SUCCESS;
+       void *temp;
+
+       /* remove all the MACs */
+       TAILQ_FOREACH_SAFE(f, &vsi->mac_list, next, temp) {
+               vlan_num = vsi->vlan_num;
+               filter_type = f->mac_info.filter_type;
+               if (filter_type == RTE_MACVLAN_PERFECT_MATCH ||
+                   filter_type == RTE_MACVLAN_HASH_MATCH) {
+                       if (vlan_num == 0) {
+                               PMD_DRV_LOG(ERR, "VLAN number shouldn't be 0");
+                               return I40E_ERR_PARAM;
+                       }
+               } else if (filter_type == RTE_MAC_PERFECT_MATCH ||
+                          filter_type == RTE_MAC_HASH_MATCH)
+                       vlan_num = 1;
+
+               mv_f = rte_zmalloc("macvlan_data", vlan_num * sizeof(*mv_f), 0);
+               if (!mv_f) {
+                       PMD_DRV_LOG(ERR, "failed to allocate memory");
+                       return I40E_ERR_NO_MEMORY;
+               }
+
+               for (i = 0; i < vlan_num; i++) {
+                       mv_f[i].filter_type = filter_type;
+                       (void)rte_memcpy(&mv_f[i].macaddr,
+                                        &f->mac_info.mac_addr,
+                                        ETH_ADDR_LEN);
+               }
+               if (filter_type == RTE_MACVLAN_PERFECT_MATCH ||
+                   filter_type == RTE_MACVLAN_HASH_MATCH) {
+                       ret = i40e_find_all_vlan_for_mac(vsi, mv_f, vlan_num,
+                                                        &f->mac_info.mac_addr);
+                       if (ret != I40E_SUCCESS) {
+                               rte_free(mv_f);
+                               return ret;
+                       }
+               }
+
+               ret = i40e_remove_macvlan_filters(vsi, mv_f, vlan_num);
+               if (ret != I40E_SUCCESS) {
+                       rte_free(mv_f);
+                       return ret;
+               }
+
+               rte_free(mv_f);
+               ret = I40E_SUCCESS;
+       }
+
+       return ret;
+}
+
+static int
+i40e_vsi_restore_mac_filter(struct i40e_vsi *vsi)
+{
+       struct i40e_mac_filter *f;
+       struct i40e_macvlan_filter *mv_f;
+       int i, vlan_num = 0;
+       int ret = I40E_SUCCESS;
+       void *temp;
+
+       /* restore all the MACs */
+       TAILQ_FOREACH_SAFE(f, &vsi->mac_list, next, temp) {
+               if ((f->mac_info.filter_type == RTE_MACVLAN_PERFECT_MATCH) ||
+                   (f->mac_info.filter_type == RTE_MACVLAN_HASH_MATCH)) {
+                       /**
+                        * If vlan_num is 0, that's the first time to add mac,
+                        * set mask for vlan_id 0.
+                        */
+                       if (vsi->vlan_num == 0) {
+                               i40e_set_vlan_filter(vsi, 0, 1);
+                               vsi->vlan_num = 1;
+                       }
+                       vlan_num = vsi->vlan_num;
+               } else if ((f->mac_info.filter_type == RTE_MAC_PERFECT_MATCH) ||
+                          (f->mac_info.filter_type == RTE_MAC_HASH_MATCH))
+                       vlan_num = 1;
+
+               mv_f = rte_zmalloc("macvlan_data", vlan_num * sizeof(*mv_f), 0);
+               if (!mv_f) {
+                       PMD_DRV_LOG(ERR, "failed to allocate memory");
+                       return I40E_ERR_NO_MEMORY;
+               }
+
+               for (i = 0; i < vlan_num; i++) {
+                       mv_f[i].filter_type = f->mac_info.filter_type;
+                       (void)rte_memcpy(&mv_f[i].macaddr,
+                                        &f->mac_info.mac_addr,
+                                        ETH_ADDR_LEN);
+               }
+
+               if (f->mac_info.filter_type == RTE_MACVLAN_PERFECT_MATCH ||
+                   f->mac_info.filter_type == RTE_MACVLAN_HASH_MATCH) {
+                       ret = i40e_find_all_vlan_for_mac(vsi, mv_f, vlan_num,
+                                                        &f->mac_info.mac_addr);
+                       if (ret != I40E_SUCCESS) {
+                               rte_free(mv_f);
+                               return ret;
+                       }
+               }
+
+               ret = i40e_add_macvlan_filters(vsi, mv_f, vlan_num);
+               if (ret != I40E_SUCCESS) {
+                       rte_free(mv_f);
+                       return ret;
+               }
+
+               rte_free(mv_f);
+               ret = I40E_SUCCESS;
+       }
+
+       return ret;
+}
+
+static int
+i40e_vsi_set_tx_loopback(struct i40e_vsi *vsi, uint8_t on)
+{
+       struct i40e_vsi_context ctxt;
+       struct i40e_hw *hw;
+       int ret;
+
+       if (!vsi)
+               return -EINVAL;
+
+       hw = I40E_VSI_TO_HW(vsi);
+
+       /* Use the FW API if FW >= v5.0 */
+       if (hw->aq.fw_maj_ver < 5) {
+               PMD_INIT_LOG(ERR, "FW < v5.0, cannot enable loopback");
+               return -ENOTSUP;
+       }
+
+       /* Check if it has been already on or off */
+       if (vsi->info.valid_sections &
+               rte_cpu_to_le_16(I40E_AQ_VSI_PROP_SWITCH_VALID)) {
+               if (on) {
+                       if ((vsi->info.switch_id &
+                            I40E_AQ_VSI_SW_ID_FLAG_ALLOW_LB) ==
+                           I40E_AQ_VSI_SW_ID_FLAG_ALLOW_LB)
+                               return 0; /* already on */
+               } else {
+                       if ((vsi->info.switch_id &
+                            I40E_AQ_VSI_SW_ID_FLAG_ALLOW_LB) == 0)
+                               return 0; /* already off */
+               }
+       }
+
+       /* remove all the MAC and VLAN first */
+       ret = i40e_vsi_rm_mac_filter(vsi);
+       if (ret) {
+               PMD_INIT_LOG(ERR, "Failed to remove MAC filters.");
+               return ret;
+       }
+       if (vsi->vlan_anti_spoof_on || vsi->vlan_filter_on) {
+               ret = i40e_add_rm_all_vlan_filter(vsi, 0);
+               if (ret) {
+                       PMD_INIT_LOG(ERR, "Failed to remove VLAN filters.");
+                       return ret;
+               }
+       }
+
+       vsi->info.valid_sections = cpu_to_le16(I40E_AQ_VSI_PROP_SWITCH_VALID);
+       if (on)
+               vsi->info.switch_id |= I40E_AQ_VSI_SW_ID_FLAG_ALLOW_LB;
+       else
+               vsi->info.switch_id &= ~I40E_AQ_VSI_SW_ID_FLAG_ALLOW_LB;
+
+       memset(&ctxt, 0, sizeof(ctxt));
+       (void)rte_memcpy(&ctxt.info, &vsi->info, sizeof(vsi->info));
+       ctxt.seid = vsi->seid;
+
+       ret = i40e_aq_update_vsi_params(hw, &ctxt, NULL);
+       if (ret != I40E_SUCCESS) {
+               PMD_DRV_LOG(ERR, "Failed to update VSI params");
+               return ret;
+       }
+
+       /* add all the MAC and VLAN back */
+       ret = i40e_vsi_restore_mac_filter(vsi);
+       if (ret)
+               return ret;
+       if (vsi->vlan_anti_spoof_on || vsi->vlan_filter_on) {
+               ret = i40e_add_rm_all_vlan_filter(vsi, 1);
+               if (ret)
+                       return ret;
+       }
+
+       return ret;
+}
+
+int
+rte_pmd_i40e_set_tx_loopback(uint8_t port, uint8_t on)
+{
+       struct rte_eth_dev *dev;
+       struct i40e_pf *pf;
+       struct i40e_pf_vf *vf;
+       struct i40e_vsi *vsi;
+       uint16_t vf_id;
+       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);
+
+       /* setup PF TX loopback */
+       vsi = pf->main_vsi;
+       ret = i40e_vsi_set_tx_loopback(vsi, on);
+       if (ret)
+               return -ENOTSUP;
+
+       /* setup TX loopback for all the VFs */
+       if (!pf->vfs) {
+               /* if no VF, do nothing. */
+               return 0;
+       }
+
+       for (vf_id = 0; vf_id < pf->vf_num; vf_id++) {
+               vf = &pf->vfs[vf_id];
+               vsi = vf->vsi;
+
+               ret = i40e_vsi_set_tx_loopback(vsi, on);
+               if (ret)
+                       return -ENOTSUP;
+       }
+
+       return ret;
+}
+
+int
+rte_pmd_i40e_set_vf_unicast_promisc(uint8_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;
+       }
+
+       hw = I40E_VSI_TO_HW(vsi);
+
+       ret = i40e_aq_set_vsi_unicast_promiscuous(hw, vsi->seid,
+                                                 on, NULL, true);
+       if (ret != I40E_SUCCESS) {
+               ret = -ENOTSUP;
+               PMD_DRV_LOG(ERR, "Failed to set unicast promiscuous mode");
+       }
+
+       return ret;
+}
+
+int
+rte_pmd_i40e_set_vf_multicast_promisc(uint8_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;
+       }
+
+       hw = I40E_VSI_TO_HW(vsi);
+
+       ret = i40e_aq_set_vsi_multicast_promiscuous(hw, vsi->seid,
+                                                   on, NULL);
+       if (ret != I40E_SUCCESS) {
+               ret = -ENOTSUP;
+               PMD_DRV_LOG(ERR, "Failed to set multicast promiscuous mode");
+       }
+
+       return ret;
+}
+
+int
+rte_pmd_i40e_set_vf_mac_addr(uint8_t port, uint16_t vf_id,
+                            struct ether_addr *mac_addr)
+{
+       struct i40e_mac_filter *f;
+       struct rte_eth_dev *dev;
+       struct i40e_pf_vf *vf;
+       struct i40e_vsi *vsi;
+       struct i40e_pf *pf;
+       void *temp;
+
+       if (i40e_validate_mac_addr((u8 *)mac_addr) != I40E_SUCCESS)
+               return -EINVAL;
+
+       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)
+               return -EINVAL;
+
+       vf = &pf->vfs[vf_id];
+       vsi = vf->vsi;
+       if (!vsi) {
+               PMD_DRV_LOG(ERR, "Invalid VSI.");
+               return -EINVAL;
+       }
+
+       ether_addr_copy(mac_addr, &vf->mac_addr);
+
+       /* Remove all existing mac */
+       TAILQ_FOREACH_SAFE(f, &vsi->mac_list, next, temp)
+               i40e_vsi_delete_mac(vsi, &f->mac_info.mac_addr);
+
+       return 0;
+}
+
+/* Set vlan strip on/off for specific VF from host */
+int
+rte_pmd_i40e_set_vf_vlan_stripq(uint8_t port, uint16_t vf_id, uint8_t on)
+{
+       struct rte_eth_dev *dev;
+       struct i40e_pf *pf;
+       struct i40e_vsi *vsi;
+       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)
+               return -EINVAL;
+
+       ret = i40e_vsi_config_vlan_stripping(vsi, !!on);
+       if (ret != I40E_SUCCESS) {
+               ret = -ENOTSUP;
+               PMD_DRV_LOG(ERR, "Failed to set VLAN stripping!");
+       }
+
+       return ret;
+}
+
+int rte_pmd_i40e_set_vf_vlan_insert(uint8_t port, uint16_t vf_id,
+                                   uint16_t vlan_id)
+{
+       struct rte_eth_dev *dev;
+       struct i40e_pf *pf;
+       struct i40e_hw *hw;
+       struct i40e_vsi *vsi;
+       struct i40e_vsi_context ctxt;
+       int ret;
+
+       RTE_ETH_VALID_PORTID_OR_ERR_RET(port, -ENODEV);
+
+       if (vlan_id > ETHER_MAX_VLAN_ID) {
+               PMD_DRV_LOG(ERR, "Invalid VLAN ID.");
+               return -EINVAL;
+       }
+
+       dev = &rte_eth_devices[port];
+
+       if (!is_i40e_supported(dev))
+               return -ENOTSUP;
+
+       pf = I40E_DEV_PRIVATE_TO_PF(dev->data->dev_private);
+       hw = I40E_PF_TO_HW(pf);
+
+       /**
+        * return -ENODEV if SRIOV not enabled, VF number not configured
+        * or no queue assigned.
+        */
+       if (!hw->func_caps.sr_iov_1_1 || pf->vf_num == 0 ||
+           pf->vf_nb_qps == 0)
+               return -ENODEV;
+
+       if (vf_id >= pf->vf_num || !pf->vfs) {
+               PMD_DRV_LOG(ERR, "Invalid VF ID.");
+               return -EINVAL;
+       }
+
+       vsi = pf->vfs[vf_id].vsi;
+       if (!vsi) {
+               PMD_DRV_LOG(ERR, "Invalid VSI.");
+               return -EINVAL;
+       }
+
+       vsi->info.valid_sections = cpu_to_le16(I40E_AQ_VSI_PROP_VLAN_VALID);
+       vsi->info.pvid = vlan_id;
+       if (vlan_id > 0)
+               vsi->info.port_vlan_flags |= I40E_AQ_VSI_PVLAN_INSERT_PVID;
+       else
+               vsi->info.port_vlan_flags &= ~I40E_AQ_VSI_PVLAN_INSERT_PVID;
+
+       memset(&ctxt, 0, sizeof(ctxt));
+       (void)rte_memcpy(&ctxt.info, &vsi->info, sizeof(vsi->info));
+       ctxt.seid = vsi->seid;
+
+       hw = I40E_VSI_TO_HW(vsi);
+       ret = i40e_aq_update_vsi_params(hw, &ctxt, NULL);
+       if (ret != I40E_SUCCESS) {
+               ret = -ENOTSUP;
+               PMD_DRV_LOG(ERR, "Failed to update VSI params");
+       }
+
+       return ret;
+}
+
+int rte_pmd_i40e_set_vf_broadcast(uint8_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;
+       struct i40e_mac_filter_info filter;
+       struct ether_addr broadcast = {
+               .addr_bytes = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff} };
+       int ret;
+
+       RTE_ETH_VALID_PORTID_OR_ERR_RET(port, -ENODEV);
+
+       if (on > 1) {
+               PMD_DRV_LOG(ERR, "on should be 0 or 1.");
+               return -EINVAL;
+       }
+
+       dev = &rte_eth_devices[port];
+
+       if (!is_i40e_supported(dev))
+               return -ENOTSUP;
+
+       pf = I40E_DEV_PRIVATE_TO_PF(dev->data->dev_private);
+       hw = I40E_PF_TO_HW(pf);
+
+       if (vf_id >= pf->vf_num || !pf->vfs) {
+               PMD_DRV_LOG(ERR, "Invalid VF ID.");
+               return -EINVAL;
+       }
+
+       /**
+        * return -ENODEV if SRIOV not enabled, VF number not configured
+        * or no queue assigned.
+        */
+       if (!hw->func_caps.sr_iov_1_1 || pf->vf_num == 0 ||
+           pf->vf_nb_qps == 0) {
+               PMD_DRV_LOG(ERR, "SRIOV is not enabled or no queue.");
+               return -ENODEV;
+       }
+
+       vsi = pf->vfs[vf_id].vsi;
+       if (!vsi) {
+               PMD_DRV_LOG(ERR, "Invalid VSI.");
+               return -EINVAL;
+       }
+
+       if (on) {
+               (void)rte_memcpy(&filter.mac_addr, &broadcast, ETHER_ADDR_LEN);
+               filter.filter_type = RTE_MACVLAN_PERFECT_MATCH;
+               ret = i40e_vsi_add_mac(vsi, &filter);
+       } else {
+               ret = i40e_vsi_delete_mac(vsi, &broadcast);
+       }
+
+       if (ret != I40E_SUCCESS && ret != I40E_ERR_PARAM) {
+               ret = -ENOTSUP;
+               PMD_DRV_LOG(ERR, "Failed to set VSI broadcast");
+       } else {
+               ret = 0;
+       }
+
+       return ret;
+}
+
+int rte_pmd_i40e_set_vf_vlan_tag(uint8_t port, uint16_t vf_id, uint8_t on)
+{
+       struct rte_eth_dev *dev;
+       struct i40e_pf *pf;
+       struct i40e_hw *hw;
+       struct i40e_vsi *vsi;
+       struct i40e_vsi_context ctxt;
+       int ret;
+
+       RTE_ETH_VALID_PORTID_OR_ERR_RET(port, -ENODEV);
+
+       if (on > 1) {
+               PMD_DRV_LOG(ERR, "on should be 0 or 1.");
+               return -EINVAL;
+       }
+
+       dev = &rte_eth_devices[port];
+
+       if (!is_i40e_supported(dev))
+               return -ENOTSUP;
+
+       pf = I40E_DEV_PRIVATE_TO_PF(dev->data->dev_private);
+       hw = I40E_PF_TO_HW(pf);
+
+       /**
+        * return -ENODEV if SRIOV not enabled, VF number not configured
+        * or no queue assigned.
+        */
+       if (!hw->func_caps.sr_iov_1_1 || pf->vf_num == 0 ||
+           pf->vf_nb_qps == 0) {
+               PMD_DRV_LOG(ERR, "SRIOV is not enabled or no queue.");
+               return -ENODEV;
+       }
+
+       if (vf_id >= pf->vf_num || !pf->vfs) {
+               PMD_DRV_LOG(ERR, "Invalid VF ID.");
+               return -EINVAL;
+       }
+
+       vsi = pf->vfs[vf_id].vsi;
+       if (!vsi) {
+               PMD_DRV_LOG(ERR, "Invalid VSI.");
+               return -EINVAL;
+       }
+
+       vsi->info.valid_sections = cpu_to_le16(I40E_AQ_VSI_PROP_VLAN_VALID);
+       if (on) {
+               vsi->info.port_vlan_flags |= I40E_AQ_VSI_PVLAN_MODE_TAGGED;
+               vsi->info.port_vlan_flags &= ~I40E_AQ_VSI_PVLAN_MODE_UNTAGGED;
+       } else {
+               vsi->info.port_vlan_flags |= I40E_AQ_VSI_PVLAN_MODE_UNTAGGED;
+               vsi->info.port_vlan_flags &= ~I40E_AQ_VSI_PVLAN_MODE_TAGGED;
+       }
+
+       memset(&ctxt, 0, sizeof(ctxt));
+       (void)rte_memcpy(&ctxt.info, &vsi->info, sizeof(vsi->info));
+       ctxt.seid = vsi->seid;
+
+       hw = I40E_VSI_TO_HW(vsi);
+       ret = i40e_aq_update_vsi_params(hw, &ctxt, NULL);
+       if (ret != I40E_SUCCESS) {
+               ret = -ENOTSUP;
+               PMD_DRV_LOG(ERR, "Failed to update VSI params");
+       }
+
+       return ret;
+}
+
+static int
+i40e_vlan_filter_count(struct i40e_vsi *vsi)
+{
+       uint32_t j, k;
+       uint16_t vlan_id;
+       int count = 0;
+
+       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;
+
+                       count++;
+               }
+       }
+
+       return count;
+}
+
+int rte_pmd_i40e_set_vf_vlan_filter(uint8_t port, uint16_t vlan_id,
+                                   uint64_t vf_mask, uint8_t on)
+{
+       struct rte_eth_dev *dev;
+       struct i40e_pf *pf;
+       struct i40e_hw *hw;
+       struct i40e_vsi *vsi;
+       uint16_t vf_idx;
+       int ret = I40E_SUCCESS;
+
+       RTE_ETH_VALID_PORTID_OR_ERR_RET(port, -ENODEV);
+
+       dev = &rte_eth_devices[port];
+
+       if (!is_i40e_supported(dev))
+               return -ENOTSUP;
+
+       if (vlan_id > ETHER_MAX_VLAN_ID || !vlan_id) {
+               PMD_DRV_LOG(ERR, "Invalid VLAN ID.");
+               return -EINVAL;
+       }
+
+       if (vf_mask == 0) {
+               PMD_DRV_LOG(ERR, "No VF.");
+               return -EINVAL;
+       }
+
+       if (on > 1) {
+               PMD_DRV_LOG(ERR, "on is should be 0 or 1.");
+               return -EINVAL;
+       }
+
+       pf = I40E_DEV_PRIVATE_TO_PF(dev->data->dev_private);
+       hw = I40E_PF_TO_HW(pf);
+
+       /**
+        * return -ENODEV if SRIOV not enabled, VF number not configured
+        * or no queue assigned.
+        */
+       if (!hw->func_caps.sr_iov_1_1 || pf->vf_num == 0 ||
+           pf->vf_nb_qps == 0) {
+               PMD_DRV_LOG(ERR, "SRIOV is not enabled or no queue.");
+               return -ENODEV;
+       }
+
+       for (vf_idx = 0; vf_idx < pf->vf_num && ret == I40E_SUCCESS; vf_idx++) {
+               if (vf_mask & ((uint64_t)(1ULL << vf_idx))) {
+                       vsi = pf->vfs[vf_idx].vsi;
+                       if (on) {
+                               if (!vsi->vlan_filter_on) {
+                                       vsi->vlan_filter_on = true;
+                                       i40e_aq_set_vsi_vlan_promisc(hw,
+                                                                    vsi->seid,
+                                                                    false,
+                                                                    NULL);
+                                       if (!vsi->vlan_anti_spoof_on)
+                                               i40e_add_rm_all_vlan_filter(
+                                                       vsi, true);
+                               }
+                               ret = i40e_vsi_add_vlan(vsi, vlan_id);
+                       } else {
+                               ret = i40e_vsi_delete_vlan(vsi, vlan_id);
+
+                               if (!i40e_vlan_filter_count(vsi)) {
+                                       vsi->vlan_filter_on = false;
+                                       i40e_aq_set_vsi_vlan_promisc(hw,
+                                                                    vsi->seid,
+                                                                    true,
+                                                                    NULL);
+                               }
+                       }
+               }
+       }
+
+       if (ret != I40E_SUCCESS) {
+               ret = -ENOTSUP;
+               PMD_DRV_LOG(ERR, "Failed to set VF VLAN filter, on = %d", on);
+       }
+
+       return ret;
+}
+
+int
+rte_pmd_i40e_get_vf_stats(uint8_t port,
+                         uint16_t vf_id,
+                         struct rte_eth_stats *stats)
+{
+       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 VF ID.");
+               return -EINVAL;
+       }
+
+       vsi = pf->vfs[vf_id].vsi;
+       if (!vsi) {
+               PMD_DRV_LOG(ERR, "Invalid VSI.");
+               return -EINVAL;
+       }
+
+       i40e_update_vsi_stats(vsi);
+
+       stats->ipackets = vsi->eth_stats.rx_unicast +
+                       vsi->eth_stats.rx_multicast +
+                       vsi->eth_stats.rx_broadcast;
+       stats->opackets = vsi->eth_stats.tx_unicast +
+                       vsi->eth_stats.tx_multicast +
+                       vsi->eth_stats.tx_broadcast;
+       stats->ibytes   = vsi->eth_stats.rx_bytes;
+       stats->obytes   = vsi->eth_stats.tx_bytes;
+       stats->ierrors  = vsi->eth_stats.rx_discards;
+       stats->oerrors  = vsi->eth_stats.tx_errors + vsi->eth_stats.tx_discards;
+
+       return 0;
+}
+
+int
+rte_pmd_i40e_reset_vf_stats(uint8_t port,
+                           uint16_t vf_id)
+{
+       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 VF ID.");
+               return -EINVAL;
+       }
+
+       vsi = pf->vfs[vf_id].vsi;
+       if (!vsi) {
+               PMD_DRV_LOG(ERR, "Invalid VSI.");
+               return -EINVAL;
+       }
+
+       vsi->offset_loaded = false;
+       i40e_update_vsi_stats(vsi);
+
+       return 0;
+}
+
+int
+rte_pmd_i40e_set_vf_max_bw(uint8_t port, uint16_t vf_id, uint32_t bw)
+{
+       struct rte_eth_dev *dev;
+       struct i40e_pf *pf;
+       struct i40e_vsi *vsi;
+       struct i40e_hw *hw;
+       int ret = 0;
+       int i;
+
+       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 VF ID.");
+               return -EINVAL;
+       }
+
+       vsi = pf->vfs[vf_id].vsi;
+       if (!vsi) {
+               PMD_DRV_LOG(ERR, "Invalid VSI.");
+               return -EINVAL;
+       }
+
+       if (bw > I40E_QOS_BW_MAX) {
+               PMD_DRV_LOG(ERR, "Bandwidth should not be larger than %dMbps.",
+                           I40E_QOS_BW_MAX);
+               return -EINVAL;
+       }
+
+       if (bw % I40E_QOS_BW_GRANULARITY) {
+               PMD_DRV_LOG(ERR, "Bandwidth should be the multiple of %dMbps.",
+                           I40E_QOS_BW_GRANULARITY);
+               return -EINVAL;
+       }
+
+       bw /= I40E_QOS_BW_GRANULARITY;
+
+       hw = I40E_VSI_TO_HW(vsi);
+
+       /* No change. */
+       if (bw == vsi->bw_info.bw_limit) {
+               PMD_DRV_LOG(INFO,
+                           "No change for VF max bandwidth. Nothing to do.");
+               return 0;
+       }
+
+       /**
+        * VF bandwidth limitation and TC bandwidth limitation cannot be
+        * enabled in parallel, quit if TC bandwidth limitation is enabled.
+        *
+        * If bw is 0, means disable bandwidth limitation. Then no need to
+        * check TC bandwidth limitation.
+        */
+       if (bw) {
+               for (i = 0; i < I40E_MAX_TRAFFIC_CLASS; i++) {
+                       if ((vsi->enabled_tc & BIT_ULL(i)) &&
+                           vsi->bw_info.bw_ets_credits[i])
+                               break;
+               }
+               if (i != I40E_MAX_TRAFFIC_CLASS) {
+                       PMD_DRV_LOG(ERR,
+                                   "TC max bandwidth has been set on this VF,"
+                                   " please disable it first.");
+                       return -EINVAL;
+               }
+       }
+
+       ret = i40e_aq_config_vsi_bw_limit(hw, vsi->seid, (uint16_t)bw, 0, NULL);
+       if (ret) {
+               PMD_DRV_LOG(ERR,
+                           "Failed to set VF %d bandwidth, err(%d).",
+                           vf_id, ret);
+               return -EINVAL;
+       }
+
+       /* Store the configuration. */
+       vsi->bw_info.bw_limit = (uint16_t)bw;
+       vsi->bw_info.bw_max = 0;
+
+       return 0;
+}
+
+int
+rte_pmd_i40e_set_vf_tc_bw_alloc(uint8_t port, uint16_t vf_id,
+                               uint8_t tc_num, uint8_t *bw_weight)
+{
+       struct rte_eth_dev *dev;
+       struct i40e_pf *pf;
+       struct i40e_vsi *vsi;
+       struct i40e_hw *hw;
+       struct i40e_aqc_configure_vsi_tc_bw_data tc_bw;
+       int ret = 0;
+       int i, j;
+       uint16_t sum;
+       bool b_change = false;
+
+       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 VF ID.");
+               return -EINVAL;
+       }
+
+       vsi = pf->vfs[vf_id].vsi;
+       if (!vsi) {
+               PMD_DRV_LOG(ERR, "Invalid VSI.");
+               return -EINVAL;
+       }
+
+       if (tc_num > I40E_MAX_TRAFFIC_CLASS) {
+               PMD_DRV_LOG(ERR, "TCs should be no more than %d.",
+                           I40E_MAX_TRAFFIC_CLASS);
+               return -EINVAL;
+       }
+
+       sum = 0;
+       for (i = 0; i < I40E_MAX_TRAFFIC_CLASS; i++) {
+               if (vsi->enabled_tc & BIT_ULL(i))
+                       sum++;
+       }
+       if (sum != tc_num) {
+               PMD_DRV_LOG(ERR,
+                           "Weight should be set for all %d enabled TCs.",
+                           sum);
+               return -EINVAL;
+       }
+
+       sum = 0;
+       for (i = 0; i < tc_num; i++) {
+               if (!bw_weight[i]) {
+                       PMD_DRV_LOG(ERR,
+                                   "The weight should be 1 at least.");
+                       return -EINVAL;
+               }
+               sum += bw_weight[i];
+       }
+       if (sum != 100) {
+               PMD_DRV_LOG(ERR,
+                           "The summary of the TC weight should be 100.");
+               return -EINVAL;
+       }
+
+       /**
+        * Create the configuration for all the TCs.
+        */
+       memset(&tc_bw, 0, sizeof(tc_bw));
+       tc_bw.tc_valid_bits = vsi->enabled_tc;
+       j = 0;
+       for (i = 0; i < I40E_MAX_TRAFFIC_CLASS; i++) {
+               if (vsi->enabled_tc & BIT_ULL(i)) {
+                       if (bw_weight[j] !=
+                               vsi->bw_info.bw_ets_share_credits[i])
+                               b_change = true;
+
+                       tc_bw.tc_bw_credits[i] = bw_weight[j];
+                       j++;
+               }
+       }
+
+       /* No change. */
+       if (!b_change) {
+               PMD_DRV_LOG(INFO,
+                           "No change for TC allocated bandwidth."
+                           " Nothing to do.");
+               return 0;
+       }
+
+       hw = I40E_VSI_TO_HW(vsi);
+
+       ret = i40e_aq_config_vsi_tc_bw(hw, vsi->seid, &tc_bw, NULL);
+       if (ret) {
+               PMD_DRV_LOG(ERR,
+                           "Failed to set VF %d TC bandwidth weight, err(%d).",
+                           vf_id, ret);
+               return -EINVAL;
+       }
+
+       /* Store the configuration. */
+       j = 0;
+       for (i = 0; i < I40E_MAX_TRAFFIC_CLASS; i++) {
+               if (vsi->enabled_tc & BIT_ULL(i)) {
+                       vsi->bw_info.bw_ets_share_credits[i] = bw_weight[j];
+                       j++;
+               }
+       }
+
+       return 0;
+}
+
+int
+rte_pmd_i40e_set_vf_tc_max_bw(uint8_t port, uint16_t vf_id,
+                             uint8_t tc_no, uint32_t bw)
+{
+       struct rte_eth_dev *dev;
+       struct i40e_pf *pf;
+       struct i40e_vsi *vsi;
+       struct i40e_hw *hw;
+       struct i40e_aqc_configure_vsi_ets_sla_bw_data tc_bw;
+       int ret = 0;
+       int i;
+
+       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 VF ID.");
+               return -EINVAL;
+       }
+
+       vsi = pf->vfs[vf_id].vsi;
+       if (!vsi) {
+               PMD_DRV_LOG(ERR, "Invalid VSI.");
+               return -EINVAL;
+       }
+
+       if (bw > I40E_QOS_BW_MAX) {
+               PMD_DRV_LOG(ERR, "Bandwidth should not be larger than %dMbps.",
+                           I40E_QOS_BW_MAX);
+               return -EINVAL;
+       }
+
+       if (bw % I40E_QOS_BW_GRANULARITY) {
+               PMD_DRV_LOG(ERR, "Bandwidth should be the multiple of %dMbps.",
+                           I40E_QOS_BW_GRANULARITY);
+               return -EINVAL;
+       }
+
+       bw /= I40E_QOS_BW_GRANULARITY;
+
+       if (tc_no >= I40E_MAX_TRAFFIC_CLASS) {
+               PMD_DRV_LOG(ERR, "TC No. should be less than %d.",
+                           I40E_MAX_TRAFFIC_CLASS);
+               return -EINVAL;
+       }
+
+       hw = I40E_VSI_TO_HW(vsi);
+
+       if (!(vsi->enabled_tc & BIT_ULL(tc_no))) {
+               PMD_DRV_LOG(ERR, "VF %d TC %d isn't enabled.",
+                           vf_id, tc_no);
+               return -EINVAL;
+       }
+
+       /* No change. */
+       if (bw == vsi->bw_info.bw_ets_credits[tc_no]) {
+               PMD_DRV_LOG(INFO,
+                           "No change for TC max bandwidth. Nothing to do.");
+               return 0;
+       }
+
+       /**
+        * VF bandwidth limitation and TC bandwidth limitation cannot be
+        * enabled in parallel, disable VF bandwidth limitation if it's
+        * enabled.
+        * If bw is 0, means disable bandwidth limitation. Then no need to
+        * care about VF bandwidth limitation configuration.
+        */
+       if (bw && vsi->bw_info.bw_limit) {
+               ret = i40e_aq_config_vsi_bw_limit(hw, vsi->seid, 0, 0, NULL);
+               if (ret) {
+                       PMD_DRV_LOG(ERR,
+                                   "Failed to disable VF(%d)"
+                                   " bandwidth limitation, err(%d).",
+                                   vf_id, ret);
+                       return -EINVAL;
+               }
+
+               PMD_DRV_LOG(INFO,
+                           "VF max bandwidth is disabled according"
+                           " to TC max bandwidth setting.");
+       }
+
+       /**
+        * Get all the TCs' info to create a whole picture.
+        * Because the incremental change isn't permitted.
+        */
+       memset(&tc_bw, 0, sizeof(tc_bw));
+       tc_bw.tc_valid_bits = vsi->enabled_tc;
+       for (i = 0; i < I40E_MAX_TRAFFIC_CLASS; i++) {
+               if (vsi->enabled_tc & BIT_ULL(i)) {
+                       tc_bw.tc_bw_credits[i] =
+                               rte_cpu_to_le_16(
+                                       vsi->bw_info.bw_ets_credits[i]);
+               }
+       }
+       tc_bw.tc_bw_credits[tc_no] = rte_cpu_to_le_16((uint16_t)bw);
+
+       ret = i40e_aq_config_vsi_ets_sla_bw_limit(hw, vsi->seid, &tc_bw, NULL);
+       if (ret) {
+               PMD_DRV_LOG(ERR,
+                           "Failed to set VF %d TC %d max bandwidth, err(%d).",
+                           vf_id, tc_no, ret);
+               return -EINVAL;
+       }
+
+       /* Store the configuration. */
+       vsi->bw_info.bw_ets_credits[tc_no] = (uint16_t)bw;
+
+       return 0;
+}
+
+int
+rte_pmd_i40e_set_tc_strict_prio(uint8_t port, uint8_t tc_map)
+{
+       struct rte_eth_dev *dev;
+       struct i40e_pf *pf;
+       struct i40e_vsi *vsi;
+       struct i40e_veb *veb;
+       struct i40e_hw *hw;
+       struct i40e_aqc_configure_switching_comp_ets_data ets_data;
+       int i;
+       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);
+
+       vsi = pf->main_vsi;
+       if (!vsi) {
+               PMD_DRV_LOG(ERR, "Invalid VSI.");
+               return -EINVAL;
+       }
+
+       veb = vsi->veb;
+       if (!veb) {
+               PMD_DRV_LOG(ERR, "Invalid VEB.");
+               return -EINVAL;
+       }
+
+       if ((tc_map & veb->enabled_tc) != tc_map) {
+               PMD_DRV_LOG(ERR,
+                           "TC bitmap isn't the subset of enabled TCs 0x%x.",
+                           veb->enabled_tc);
+               return -EINVAL;
+       }
+
+       if (tc_map == veb->strict_prio_tc) {
+               PMD_DRV_LOG(INFO, "No change for TC bitmap. Nothing to do.");
+               return 0;
+       }
+
+       hw = I40E_VSI_TO_HW(vsi);
+
+       /* Disable DCBx if it's the first time to set strict priority. */
+       if (!veb->strict_prio_tc) {
+               ret = i40e_aq_stop_lldp(hw, true, NULL);
+               if (ret)
+                       PMD_DRV_LOG(INFO,
+                                   "Failed to disable DCBx as it's already"
+                                   " disabled.");
+               else
+                       PMD_DRV_LOG(INFO,
+                                   "DCBx is disabled according to strict"
+                                   " priority setting.");
+       }
+
+       memset(&ets_data, 0, sizeof(ets_data));
+       ets_data.tc_valid_bits = veb->enabled_tc;
+       ets_data.seepage = I40E_AQ_ETS_SEEPAGE_EN_MASK;
+       ets_data.tc_strict_priority_flags = tc_map;
+       /* Get all TCs' bandwidth. */
+       for (i = 0; i < I40E_MAX_TRAFFIC_CLASS; i++) {
+               if (veb->enabled_tc & BIT_ULL(i)) {
+                       /* For rubust, if bandwidth is 0, use 1 instead. */
+                       if (veb->bw_info.bw_ets_share_credits[i])
+                               ets_data.tc_bw_share_credits[i] =
+                                       veb->bw_info.bw_ets_share_credits[i];
+                       else
+                               ets_data.tc_bw_share_credits[i] =
+                                       I40E_QOS_BW_WEIGHT_MIN;
+               }
+       }
+
+       if (!veb->strict_prio_tc)
+               ret = i40e_aq_config_switch_comp_ets(
+                       hw, veb->uplink_seid,
+                       &ets_data, i40e_aqc_opc_enable_switching_comp_ets,
+                       NULL);
+       else if (tc_map)
+               ret = i40e_aq_config_switch_comp_ets(
+                       hw, veb->uplink_seid,
+                       &ets_data, i40e_aqc_opc_modify_switching_comp_ets,
+                       NULL);
+       else
+               ret = i40e_aq_config_switch_comp_ets(
+                       hw, veb->uplink_seid,
+                       &ets_data, i40e_aqc_opc_disable_switching_comp_ets,
+                       NULL);
+
+       if (ret) {
+               PMD_DRV_LOG(ERR,
+                           "Failed to set TCs' strict priority mode."
+                           " err (%d)", ret);
+               return -EINVAL;
+       }
+
+       veb->strict_prio_tc = tc_map;
+
+       /* Enable DCBx again, if all the TCs' strict priority disabled. */
+       if (!tc_map) {
+               ret = i40e_aq_start_lldp(hw, NULL);
+               if (ret) {
+                       PMD_DRV_LOG(ERR,
+                                   "Failed to enable DCBx, err(%d).", ret);
+                       return -EINVAL;
+               }
+
+               PMD_DRV_LOG(INFO,
+                           "DCBx is enabled again according to strict"
+                           " priority setting.");
+       }
+
+       return ret;
+}
+
+#define I40E_PROFILE_INFO_SIZE 48
+#define I40E_MAX_PROFILE_NUM 16
+
+static void
+i40e_generate_profile_info_sec(char *name, struct i40e_ddp_version *version,
+                              uint32_t track_id, uint8_t *profile_info_sec,
+                              bool add)
+{
+       struct i40e_profile_section_header *sec = NULL;
+       struct i40e_profile_info *pinfo;
+
+       sec = (struct i40e_profile_section_header *)profile_info_sec;
+       sec->tbl_size = 1;
+       sec->data_end = sizeof(struct i40e_profile_section_header) +
+               sizeof(struct i40e_profile_info);
+       sec->section.type = SECTION_TYPE_INFO;
+       sec->section.offset = sizeof(struct i40e_profile_section_header);
+       sec->section.size = sizeof(struct i40e_profile_info);
+       pinfo = (struct i40e_profile_info *)(profile_info_sec +
+                                            sec->section.offset);
+       pinfo->track_id = track_id;
+       memcpy(pinfo->name, name, I40E_DDP_NAME_SIZE);
+       memcpy(&pinfo->version, version, sizeof(struct i40e_ddp_version));
+       if (add)
+               pinfo->op = I40E_DDP_ADD_TRACKID;
+       else
+               pinfo->op = I40E_DDP_REMOVE_TRACKID;
+}
+
+static enum i40e_status_code
+i40e_add_rm_profile_info(struct i40e_hw *hw, uint8_t *profile_info_sec)
+{
+       enum i40e_status_code status = I40E_SUCCESS;
+       struct i40e_profile_section_header *sec;
+       uint32_t track_id;
+       uint32_t offset = 0;
+       uint32_t info = 0;
+
+       sec = (struct i40e_profile_section_header *)profile_info_sec;
+       track_id = ((struct i40e_profile_info *)(profile_info_sec +
+                                        sec->section.offset))->track_id;
+
+       status = i40e_aq_write_ddp(hw, (void *)sec, sec->data_end,
+                                  track_id, &offset, &info, NULL);
+       if (status)
+               PMD_DRV_LOG(ERR, "Failed to add/remove profile info: "
+                           "offset %d, info %d",
+                           offset, info);
+
+       return status;
+}
+
+#define I40E_PROFILE_INFO_SIZE 48
+#define I40E_MAX_PROFILE_NUM 16
+
+/* Check if the profile info exists */
+static int
+i40e_check_profile_info(uint8_t port, uint8_t *profile_info_sec)
+{
+       struct rte_eth_dev *dev = &rte_eth_devices[port];
+       struct i40e_hw *hw = I40E_DEV_PRIVATE_TO_HW(dev->data->dev_private);
+       uint8_t *buff;
+       struct rte_pmd_i40e_profile_list *p_list;
+       struct rte_pmd_i40e_profile_info *pinfo, *p;
+       uint32_t i;
+       int ret;
+
+       buff = rte_zmalloc("pinfo_list",
+                          (I40E_PROFILE_INFO_SIZE * I40E_MAX_PROFILE_NUM + 4),
+                          0);
+       if (!buff) {
+               PMD_DRV_LOG(ERR, "failed to allocate memory");
+               return -1;
+       }
+
+       ret = i40e_aq_get_ddp_list(
+               hw, (void *)buff,
+               (I40E_PROFILE_INFO_SIZE * I40E_MAX_PROFILE_NUM + 4),
+               0, NULL);
+       if (ret) {
+               PMD_DRV_LOG(ERR, "Failed to get profile info list.");
+               rte_free(buff);
+               return -1;
+       }
+       p_list = (struct rte_pmd_i40e_profile_list *)buff;
+       pinfo = (struct rte_pmd_i40e_profile_info *)(profile_info_sec +
+                            sizeof(struct i40e_profile_section_header));
+       for (i = 0; i < p_list->p_count; i++) {
+               p = &p_list->p_info[i];
+               if ((pinfo->track_id == p->track_id) &&
+                   !memcmp(&pinfo->version, &p->version,
+                           sizeof(struct i40e_ddp_version)) &&
+                   !memcmp(&pinfo->name, &p->name,
+                           I40E_DDP_NAME_SIZE)) {
+                       PMD_DRV_LOG(INFO, "Profile exists.");
+                       rte_free(buff);
+                       return 1;
+               }
+       }
+
+       rte_free(buff);
+       return 0;
+}
+
+int
+rte_pmd_i40e_process_ddp_package(uint8_t port, uint8_t *buff,
+                                uint32_t size,
+                                enum rte_pmd_i40e_package_op op)
+{
+       struct rte_eth_dev *dev;
+       struct i40e_hw *hw;
+       struct i40e_package_header *pkg_hdr;
+       struct i40e_generic_seg_header *profile_seg_hdr;
+       struct i40e_generic_seg_header *metadata_seg_hdr;
+       uint32_t track_id;
+       uint8_t *profile_info_sec;
+       int is_exist;
+       enum i40e_status_code status = I40E_SUCCESS;
+
+       RTE_ETH_VALID_PORTID_OR_ERR_RET(port, -ENODEV);
+
+       dev = &rte_eth_devices[port];
+
+       if (!is_i40e_supported(dev))
+               return -ENOTSUP;
+
+       hw = I40E_DEV_PRIVATE_TO_HW(dev->data->dev_private);
+
+       if (size < (sizeof(struct i40e_package_header) +
+                   sizeof(struct i40e_metadata_segment) +
+                   sizeof(uint32_t) * 2)) {
+               PMD_DRV_LOG(ERR, "Buff is invalid.");
+               return -EINVAL;
+       }
+
+       pkg_hdr = (struct i40e_package_header *)buff;
+
+       if (!pkg_hdr) {
+               PMD_DRV_LOG(ERR, "Failed to fill the package structure");
+               return -EINVAL;
+       }
+
+       if (pkg_hdr->segment_count < 2) {
+               PMD_DRV_LOG(ERR, "Segment_count should be 2 at least.");
+               return -EINVAL;
+       }
+
+       /* Find metadata segment */
+       metadata_seg_hdr = i40e_find_segment_in_package(SEGMENT_TYPE_METADATA,
+                                                       pkg_hdr);
+       if (!metadata_seg_hdr) {
+               PMD_DRV_LOG(ERR, "Failed to find metadata segment header");
+               return -EINVAL;
+       }
+       track_id = ((struct i40e_metadata_segment *)metadata_seg_hdr)->track_id;
+
+       /* Find profile segment */
+       profile_seg_hdr = i40e_find_segment_in_package(SEGMENT_TYPE_I40E,
+                                                      pkg_hdr);
+       if (!profile_seg_hdr) {
+               PMD_DRV_LOG(ERR, "Failed to find profile segment header");
+               return -EINVAL;
+       }
+
+       profile_info_sec = rte_zmalloc(
+               "i40e_profile_info",
+               sizeof(struct i40e_profile_section_header) +
+               sizeof(struct i40e_profile_info),
+               0);
+       if (!profile_info_sec) {
+               PMD_DRV_LOG(ERR, "Failed to allocate memory");
+               return -EINVAL;
+       }
+
+       if (op == RTE_PMD_I40E_PKG_OP_WR_ADD) {
+               /* Check if the profile exists */
+               i40e_generate_profile_info_sec(
+                    ((struct i40e_profile_segment *)profile_seg_hdr)->name,
+                    &((struct i40e_profile_segment *)profile_seg_hdr)->version,
+                    track_id, profile_info_sec, 1);
+               is_exist = i40e_check_profile_info(port, profile_info_sec);
+               if (is_exist > 0) {
+                       PMD_DRV_LOG(ERR, "Profile already exists.");
+                       rte_free(profile_info_sec);
+                       return 1;
+               } else if (is_exist < 0) {
+                       PMD_DRV_LOG(ERR, "Failed to check profile.");
+                       rte_free(profile_info_sec);
+                       return -EINVAL;
+               }
+
+               /* Write profile to HW */
+               status = i40e_write_profile(
+                               hw,
+                               (struct i40e_profile_segment *)profile_seg_hdr,
+                               track_id);
+               if (status) {
+                       PMD_DRV_LOG(ERR, "Failed to write profile.");
+                       rte_free(profile_info_sec);
+                       return status;
+               }
+
+               /* Add profile info to info list */
+               status = i40e_add_rm_profile_info(hw, profile_info_sec);
+               if (status)
+                       PMD_DRV_LOG(ERR, "Failed to add profile info.");
+       } else {
+               PMD_DRV_LOG(ERR, "Operation not supported.");
+       }
+
+       rte_free(profile_info_sec);
+       return status;
+}
+
+int
+rte_pmd_i40e_get_ddp_list(uint8_t port, uint8_t *buff, uint32_t size)
+{
+       struct rte_eth_dev *dev;
+       struct i40e_hw *hw;
+       enum i40e_status_code status = I40E_SUCCESS;
+
+       RTE_ETH_VALID_PORTID_OR_ERR_RET(port, -ENODEV);
+
+       dev = &rte_eth_devices[port];
+
+       if (!is_i40e_supported(dev))
+               return -ENOTSUP;
+
+       if (size < (I40E_PROFILE_INFO_SIZE * I40E_MAX_PROFILE_NUM + 4))
+               return -EINVAL;
+
+       hw = I40E_DEV_PRIVATE_TO_HW(dev->data->dev_private);
+
+       status = i40e_aq_get_ddp_list(hw, (void *)buff,
+                                     size, 0, NULL);
+
+       return status;
+}