All of lore.kernel.org
 help / color / mirror / Atom feed
From: Wenzhuo Lu <wenzhuo.lu@intel.com>
To: dev@dpdk.org
Cc: Wenzhuo Lu <wenzhuo.lu@intel.com>
Subject: [PATCH 1/2] net/i40e: move private APIs to a specific file
Date: Tue, 11 Apr 2017 16:31:23 +0800	[thread overview]
Message-ID: <1491899484-28777-2-git-send-email-wenzhuo.lu@intel.com> (raw)
In-Reply-To: <1491899484-28777-1-git-send-email-wenzhuo.lu@intel.com>

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       |    1 +
 drivers/net/i40e/i40e_ethdev.c  | 1676 +-------------------------------------
 drivers/net/i40e/i40e_ethdev.h  |   11 +
 drivers/net/i40e/rte_pmd_i40e.c | 1707 +++++++++++++++++++++++++++++++++++++++
 4 files changed, 1726 insertions(+), 1669 deletions(-)
 create mode 100644 drivers/net/i40e/rte_pmd_i40e.c

diff --git a/drivers/net/i40e/Makefile b/drivers/net/i40e/Makefile
index 1f5d133..56f210d 100644
--- a/drivers/net/i40e/Makefile
+++ b/drivers/net/i40e/Makefile
@@ -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)),)
diff --git a/drivers/net/i40e/i40e_ethdev.c b/drivers/net/i40e/i40e_ethdev.c
index 8d25f8c..f11c8c1 100644
--- a/drivers/net/i40e/i40e_ethdev.c
+++ b/drivers/net/i40e/i40e_ethdev.c
@@ -64,7 +64,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"
@@ -244,15 +243,6 @@
 /* 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);
@@ -342,10 +332,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,
@@ -5854,7 +5840,7 @@ struct i40e_vsi *
 	rte_intr_enable(dev->intr_handle);
 }
 
-static int
+int
 i40e_add_macvlan_filters(struct i40e_vsi *vsi,
 			 struct i40e_macvlan_filter *filter,
 			 int total)
@@ -5928,7 +5914,7 @@ struct i40e_vsi *
 	return ret;
 }
 
-static int
+int
 i40e_remove_macvlan_filters(struct i40e_vsi *vsi,
 			    struct i40e_macvlan_filter *filter,
 			    int total)
@@ -6048,7 +6034,7 @@ struct i40e_vsi *
 		vsi->vfta[vid_idx] &= ~vid_bit;
 }
 
-static void
+void
 i40e_set_vlan_filter(struct i40e_vsi *vsi,
 		     uint16_t vlan_id, bool on)
 {
@@ -6084,7 +6070,7 @@ struct i40e_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)
@@ -10690,1658 +10676,10 @@ static void i40e_set_default_mac_addr(struct rte_eth_dev *dev,
 	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
diff --git a/drivers/net/i40e/i40e_ethdev.h b/drivers/net/i40e/i40e_ethdev.h
index 69c6684..c745e9b 100644
--- a/drivers/net/i40e/i40e_ethdev.h
+++ b/drivers/net/i40e/i40e_ethdev.h
@@ -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
index 0000000..cee067b
--- /dev/null
+++ b/drivers/net/i40e/rte_pmd_i40e.c
@@ -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;
+}
-- 
1.9.3

  reply	other threads:[~2017-04-11  8:31 UTC|newest]

Thread overview: 4+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2017-04-11  8:31 [PATCH 0/2] move private APIs to a specific files Wenzhuo Lu
2017-04-11  8:31 ` Wenzhuo Lu [this message]
2017-04-11  8:31 ` [PATCH 2/2] net/ixgbe: move private APIs to a specific file Wenzhuo Lu
2017-04-11 12:10 ` [PATCH 0/2] move private APIs to a specific files Ferruh Yigit

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=1491899484-28777-2-git-send-email-wenzhuo.lu@intel.com \
    --to=wenzhuo.lu@intel.com \
    --cc=dev@dpdk.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.