drivers/net: do not use ethdev driver
[dpdk.git] / drivers / net / i40e / i40e_ethdev.c
index 67778ba..ac5e181 100644 (file)
@@ -1,7 +1,7 @@
 /*-
  *   BSD LICENSE
  *
- *   Copyright(c) 2010-2016 Intel Corporation. All rights reserved.
+ *   Copyright(c) 2010-2017 Intel Corporation. All rights reserved.
  *   All rights reserved.
  *
  *   Redistribution and use in source and binary forms, with or without
 #include <inttypes.h>
 #include <assert.h>
 
+#include <rte_eal.h>
 #include <rte_string_fns.h>
 #include <rte_pci.h>
 #include <rte_ether.h>
 #include <rte_ethdev.h>
+#include <rte_ethdev_pci.h>
 #include <rte_memzone.h>
 #include <rte_malloc.h>
 #include <rte_memcpy.h>
@@ -51,6 +53,7 @@
 #include <rte_dev.h>
 #include <rte_eth_ctrl.h>
 #include <rte_tailq.h>
+#include <rte_hash_crc.h>
 
 #include "i40e_logs.h"
 #include "base/i40e_prototype.h"
@@ -62,6 +65,7 @@
 #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"
 #define I40E_DEFAULT_DCB_APP_NUM    1
 #define I40E_DEFAULT_DCB_APP_PRIO   3
 
-#define I40E_INSET_NONE            0x00000000000000000ULL
-
-/* bit0 ~ bit 7 */
-#define I40E_INSET_DMAC            0x0000000000000001ULL
-#define I40E_INSET_SMAC            0x0000000000000002ULL
-#define I40E_INSET_VLAN_OUTER      0x0000000000000004ULL
-#define I40E_INSET_VLAN_INNER      0x0000000000000008ULL
-#define I40E_INSET_VLAN_TUNNEL     0x0000000000000010ULL
-
-/* bit 8 ~ bit 15 */
-#define I40E_INSET_IPV4_SRC        0x0000000000000100ULL
-#define I40E_INSET_IPV4_DST        0x0000000000000200ULL
-#define I40E_INSET_IPV6_SRC        0x0000000000000400ULL
-#define I40E_INSET_IPV6_DST        0x0000000000000800ULL
-#define I40E_INSET_SRC_PORT        0x0000000000001000ULL
-#define I40E_INSET_DST_PORT        0x0000000000002000ULL
-#define I40E_INSET_SCTP_VT         0x0000000000004000ULL
-
-/* bit 16 ~ bit 31 */
-#define I40E_INSET_IPV4_TOS        0x0000000000010000ULL
-#define I40E_INSET_IPV4_PROTO      0x0000000000020000ULL
-#define I40E_INSET_IPV4_TTL        0x0000000000040000ULL
-#define I40E_INSET_IPV6_TC         0x0000000000080000ULL
-#define I40E_INSET_IPV6_FLOW       0x0000000000100000ULL
-#define I40E_INSET_IPV6_NEXT_HDR   0x0000000000200000ULL
-#define I40E_INSET_IPV6_HOP_LIMIT  0x0000000000400000ULL
-#define I40E_INSET_TCP_FLAGS       0x0000000000800000ULL
-
-/* bit 32 ~ bit 47, tunnel fields */
-#define I40E_INSET_TUNNEL_IPV4_DST       0x0000000100000000ULL
-#define I40E_INSET_TUNNEL_IPV6_DST       0x0000000200000000ULL
-#define I40E_INSET_TUNNEL_DMAC           0x0000000400000000ULL
-#define I40E_INSET_TUNNEL_SRC_PORT       0x0000000800000000ULL
-#define I40E_INSET_TUNNEL_DST_PORT       0x0000001000000000ULL
-#define I40E_INSET_TUNNEL_ID             0x0000002000000000ULL
-
-/* bit 48 ~ bit 55 */
-#define I40E_INSET_LAST_ETHER_TYPE 0x0001000000000000ULL
-
-/* bit 56 ~ bit 63, Flex Payload */
-#define I40E_INSET_FLEX_PAYLOAD_W1 0x0100000000000000ULL
-#define I40E_INSET_FLEX_PAYLOAD_W2 0x0200000000000000ULL
-#define I40E_INSET_FLEX_PAYLOAD_W3 0x0400000000000000ULL
-#define I40E_INSET_FLEX_PAYLOAD_W4 0x0800000000000000ULL
-#define I40E_INSET_FLEX_PAYLOAD_W5 0x1000000000000000ULL
-#define I40E_INSET_FLEX_PAYLOAD_W6 0x2000000000000000ULL
-#define I40E_INSET_FLEX_PAYLOAD_W7 0x4000000000000000ULL
-#define I40E_INSET_FLEX_PAYLOAD_W8 0x8000000000000000ULL
-#define I40E_INSET_FLEX_PAYLOAD \
-       (I40E_INSET_FLEX_PAYLOAD_W1 | I40E_INSET_FLEX_PAYLOAD_W2 | \
-       I40E_INSET_FLEX_PAYLOAD_W3 | I40E_INSET_FLEX_PAYLOAD_W4 | \
-       I40E_INSET_FLEX_PAYLOAD_W5 | I40E_INSET_FLEX_PAYLOAD_W6 | \
-       I40E_INSET_FLEX_PAYLOAD_W7 | I40E_INSET_FLEX_PAYLOAD_W8)
-
 /**
  * Below are values for writing un-exposed registers suggested
  * by silicon experts
 #define I40E_INSET_IPV6_HOP_LIMIT_MASK  0x000CFF00UL
 #define I40E_INSET_IPV6_NEXT_HDR_MASK   0x000C00FFUL
 
-#define I40E_GL_SWT_L2TAGCTRL(_i)             (0x001C0A70 + ((_i) * 4))
-#define I40E_GL_SWT_L2TAGCTRL_ETHERTYPE_SHIFT 16
-#define I40E_GL_SWT_L2TAGCTRL_ETHERTYPE_MASK  \
-       I40E_MASK(0xFFFF, I40E_GL_SWT_L2TAGCTRL_ETHERTYPE_SHIFT)
-
 /* PCI offset for querying capability */
 #define PCI_DEV_CAP_REG            0xA4
 /* PCI offset for enabling/disabling Extended Tag */
 /* 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);
@@ -324,6 +278,8 @@ static int i40e_dev_queue_stats_mapping_set(struct rte_eth_dev *dev,
                                            uint16_t queue_id,
                                            uint8_t stat_idx,
                                            uint8_t is_rx);
+static int i40e_fw_version_get(struct rte_eth_dev *dev,
+                               char *fw_version, size_t fw_size);
 static void i40e_dev_info_get(struct rte_eth_dev *dev,
                              struct rte_eth_dev_info *dev_info);
 static int i40e_vlan_filter_set(struct rte_eth_dev *dev,
@@ -373,8 +329,7 @@ static void i40e_stat_update_48(struct i40e_hw *hw,
                               uint64_t *offset,
                               uint64_t *stat);
 static void i40e_pf_config_irq0(struct i40e_hw *hw, bool no_queue);
-static void i40e_dev_interrupt_handler(
-               __rte_unused struct rte_intr_handle *handle, void *param);
+static void i40e_dev_interrupt_handler(void *param);
 static int i40e_res_pool_init(struct i40e_res_pool_info *pool,
                                uint32_t base, uint32_t num);
 static void i40e_res_pool_destroy(struct i40e_res_pool_info *pool);
@@ -406,9 +361,6 @@ static int i40e_dev_udp_tunnel_port_add(struct rte_eth_dev *dev,
 static int i40e_dev_udp_tunnel_port_del(struct rte_eth_dev *dev,
                                        struct rte_eth_udp_tunnel *udp_tunnel);
 static void i40e_filter_input_set_init(struct i40e_pf *pf);
-static int i40e_ethertype_filter_set(struct i40e_pf *pf,
-                       struct rte_eth_ethertype_filter *filter,
-                       bool add);
 static int i40e_ethertype_filter_handle(struct rte_eth_dev *dev,
                                enum rte_filter_op filter_op,
                                void *arg);
@@ -461,6 +413,26 @@ static void i40e_set_default_mac_addr(struct rte_eth_dev *dev,
 
 static int i40e_dev_mtu_set(struct rte_eth_dev *dev, uint16_t mtu);
 
+static int i40e_ethertype_filter_convert(
+       const struct rte_eth_ethertype_filter *input,
+       struct i40e_ethertype_filter *filter);
+static int i40e_sw_ethertype_filter_insert(struct i40e_pf *pf,
+                                  struct i40e_ethertype_filter *filter);
+
+static int i40e_tunnel_filter_convert(
+       struct i40e_aqc_add_rm_cloud_filt_elem_ext *cld_filter,
+       struct i40e_tunnel_filter *tunnel_filter);
+static int i40e_sw_tunnel_filter_insert(struct i40e_pf *pf,
+                               struct i40e_tunnel_filter *tunnel_filter);
+static int i40e_cloud_filter_qinq_create(struct i40e_pf *pf);
+
+static void i40e_ethertype_filter_restore(struct i40e_pf *pf);
+static void i40e_tunnel_filter_restore(struct i40e_pf *pf);
+static void i40e_filter_restore(struct i40e_pf *pf);
+
+int i40e_logtype_init;
+int i40e_logtype_driver;
+
 static const struct rte_pci_id pci_id_i40e_map[] = {
        { RTE_PCI_DEVICE(I40E_INTEL_VENDOR_ID, I40E_DEV_ID_SFP_XL710) },
        { RTE_PCI_DEVICE(I40E_INTEL_VENDOR_ID, I40E_DEV_ID_QEMU) },
@@ -503,6 +475,7 @@ static const struct eth_dev_ops i40e_eth_dev_ops = {
        .stats_reset                  = i40e_dev_stats_reset,
        .xstats_reset                 = i40e_dev_stats_reset,
        .queue_stats_mapping_set      = i40e_dev_queue_stats_mapping_set,
+       .fw_version_get               = i40e_fw_version_get,
        .dev_infos_get                = i40e_dev_info_get,
        .dev_supported_ptypes_get     = i40e_dev_supported_ptypes_get,
        .vlan_filter_set              = i40e_vlan_filter_set,
@@ -520,6 +493,8 @@ static const struct eth_dev_ops i40e_eth_dev_ops = {
        .rx_queue_release             = i40e_dev_rx_queue_release,
        .rx_queue_count               = i40e_dev_rx_queue_count,
        .rx_descriptor_done           = i40e_dev_rx_descriptor_done,
+       .rx_descriptor_status         = i40e_dev_rx_descriptor_status,
+       .tx_descriptor_status         = i40e_dev_tx_descriptor_status,
        .tx_queue_setup               = i40e_dev_tx_queue_setup,
        .tx_queue_release             = i40e_dev_tx_queue_release,
        .dev_led_on                   = i40e_dev_led_on,
@@ -668,17 +643,23 @@ static const struct rte_i40e_xstats_name_off rte_i40e_txq_prio_strings[] = {
 #define I40E_NB_TXQ_PRIO_XSTATS (sizeof(rte_i40e_txq_prio_strings) / \
                sizeof(rte_i40e_txq_prio_strings[0]))
 
-static struct eth_driver rte_i40e_pmd = {
-       .pci_drv = {
-               .id_table = pci_id_i40e_map,
-               .drv_flags = RTE_PCI_DRV_NEED_MAPPING | RTE_PCI_DRV_INTR_LSC |
-                       RTE_PCI_DRV_DETACHABLE,
-               .probe = rte_eth_dev_pci_probe,
-               .remove = rte_eth_dev_pci_remove,
-       },
-       .eth_dev_init = eth_i40e_dev_init,
-       .eth_dev_uninit = eth_i40e_dev_uninit,
-       .dev_private_size = sizeof(struct i40e_adapter),
+static int eth_i40e_pci_probe(struct rte_pci_driver *pci_drv __rte_unused,
+       struct rte_pci_device *pci_dev)
+{
+       return rte_eth_dev_pci_generic_probe(pci_dev,
+               sizeof(struct i40e_adapter), eth_i40e_dev_init);
+}
+
+static int eth_i40e_pci_remove(struct rte_pci_device *pci_dev)
+{
+       return rte_eth_dev_pci_generic_remove(pci_dev, eth_i40e_dev_uninit);
+}
+
+static struct rte_pci_driver rte_i40e_pmd = {
+       .id_table = pci_id_i40e_map,
+       .drv_flags = RTE_PCI_DRV_NEED_MAPPING | RTE_PCI_DRV_INTR_LSC,
+       .probe = eth_i40e_pci_probe,
+       .remove = eth_i40e_pci_remove,
 };
 
 static inline int
@@ -709,8 +690,9 @@ rte_i40e_dev_atomic_write_link_status(struct rte_eth_dev *dev,
        return 0;
 }
 
-RTE_PMD_REGISTER_PCI(net_i40e, rte_i40e_pmd.pci_drv);
+RTE_PMD_REGISTER_PCI(net_i40e, rte_i40e_pmd);
 RTE_PMD_REGISTER_PCI_TABLE(net_i40e, pci_id_i40e_map);
+RTE_PMD_REGISTER_KMOD_DEP(net_i40e, "* igb_uio | uio_pci_generic | vfio");
 
 #ifndef I40E_GLQF_ORT
 #define I40E_GLQF_ORT(_i)    (0x00268900 + ((_i) * 4))
@@ -718,6 +700,9 @@ RTE_PMD_REGISTER_PCI_TABLE(net_i40e, pci_id_i40e_map);
 #ifndef I40E_GLQF_PIT
 #define I40E_GLQF_PIT(_i)    (0x00268C80 + ((_i) * 4))
 #endif
+#ifndef I40E_GLQF_L3_MAP
+#define I40E_GLQF_L3_MAP(_i) (0x0026C700 + ((_i) * 4))
+#endif
 
 static inline void i40e_GLQF_reg_init(struct i40e_hw *hw)
 {
@@ -763,8 +748,8 @@ i40e_add_tx_flow_control_drop_filter(struct i40e_pf *pf)
                                pf->main_vsi_seid, 0,
                                TRUE, NULL, NULL);
        if (ret)
-               PMD_INIT_LOG(ERR, "Failed to add filter to drop flow control "
-                                 " frames from VSIs.");
+               PMD_INIT_LOG(ERR,
+                       "Failed to add filter to drop flow control frames from VSIs.");
 }
 
 static int
@@ -907,7 +892,7 @@ is_floating_veb_supported(struct rte_devargs *devargs)
 static void
 config_floating_veb(struct rte_eth_dev *dev)
 {
-       struct rte_pci_device *pci_dev = dev->pci_dev;
+       struct rte_pci_device *pci_dev = I40E_DEV_TO_PCI(dev);
        struct i40e_pf *pf = I40E_DEV_PRIVATE_TO_PF(dev->data->dev_private);
        struct i40e_hw *hw = I40E_DEV_PRIVATE_TO_HW(dev->data->dev_private);
 
@@ -927,10 +912,145 @@ config_floating_veb(struct rte_eth_dev *dev)
 #define I40E_L2_TAGS_S_TAG_SHIFT 1
 #define I40E_L2_TAGS_S_TAG_MASK I40E_MASK(0x1, I40E_L2_TAGS_S_TAG_SHIFT)
 
+static int
+i40e_init_ethtype_filter_list(struct rte_eth_dev *dev)
+{
+       struct i40e_pf *pf = I40E_DEV_PRIVATE_TO_PF(dev->data->dev_private);
+       struct i40e_ethertype_rule *ethertype_rule = &pf->ethertype;
+       char ethertype_hash_name[RTE_HASH_NAMESIZE];
+       int ret;
+
+       struct rte_hash_parameters ethertype_hash_params = {
+               .name = ethertype_hash_name,
+               .entries = I40E_MAX_ETHERTYPE_FILTER_NUM,
+               .key_len = sizeof(struct i40e_ethertype_filter_input),
+               .hash_func = rte_hash_crc,
+               .hash_func_init_val = 0,
+               .socket_id = rte_socket_id(),
+       };
+
+       /* Initialize ethertype filter rule list and hash */
+       TAILQ_INIT(&ethertype_rule->ethertype_list);
+       snprintf(ethertype_hash_name, RTE_HASH_NAMESIZE,
+                "ethertype_%s", dev->data->name);
+       ethertype_rule->hash_table = rte_hash_create(&ethertype_hash_params);
+       if (!ethertype_rule->hash_table) {
+               PMD_INIT_LOG(ERR, "Failed to create ethertype hash table!");
+               return -EINVAL;
+       }
+       ethertype_rule->hash_map = rte_zmalloc("i40e_ethertype_hash_map",
+                                      sizeof(struct i40e_ethertype_filter *) *
+                                      I40E_MAX_ETHERTYPE_FILTER_NUM,
+                                      0);
+       if (!ethertype_rule->hash_map) {
+               PMD_INIT_LOG(ERR,
+                            "Failed to allocate memory for ethertype hash map!");
+               ret = -ENOMEM;
+               goto err_ethertype_hash_map_alloc;
+       }
+
+       return 0;
+
+err_ethertype_hash_map_alloc:
+       rte_hash_free(ethertype_rule->hash_table);
+
+       return ret;
+}
+
+static int
+i40e_init_tunnel_filter_list(struct rte_eth_dev *dev)
+{
+       struct i40e_pf *pf = I40E_DEV_PRIVATE_TO_PF(dev->data->dev_private);
+       struct i40e_tunnel_rule *tunnel_rule = &pf->tunnel;
+       char tunnel_hash_name[RTE_HASH_NAMESIZE];
+       int ret;
+
+       struct rte_hash_parameters tunnel_hash_params = {
+               .name = tunnel_hash_name,
+               .entries = I40E_MAX_TUNNEL_FILTER_NUM,
+               .key_len = sizeof(struct i40e_tunnel_filter_input),
+               .hash_func = rte_hash_crc,
+               .hash_func_init_val = 0,
+               .socket_id = rte_socket_id(),
+       };
+
+       /* Initialize tunnel filter rule list and hash */
+       TAILQ_INIT(&tunnel_rule->tunnel_list);
+       snprintf(tunnel_hash_name, RTE_HASH_NAMESIZE,
+                "tunnel_%s", dev->data->name);
+       tunnel_rule->hash_table = rte_hash_create(&tunnel_hash_params);
+       if (!tunnel_rule->hash_table) {
+               PMD_INIT_LOG(ERR, "Failed to create tunnel hash table!");
+               return -EINVAL;
+       }
+       tunnel_rule->hash_map = rte_zmalloc("i40e_tunnel_hash_map",
+                                   sizeof(struct i40e_tunnel_filter *) *
+                                   I40E_MAX_TUNNEL_FILTER_NUM,
+                                   0);
+       if (!tunnel_rule->hash_map) {
+               PMD_INIT_LOG(ERR,
+                            "Failed to allocate memory for tunnel hash map!");
+               ret = -ENOMEM;
+               goto err_tunnel_hash_map_alloc;
+       }
+
+       return 0;
+
+err_tunnel_hash_map_alloc:
+       rte_hash_free(tunnel_rule->hash_table);
+
+       return ret;
+}
+
+static int
+i40e_init_fdir_filter_list(struct rte_eth_dev *dev)
+{
+       struct i40e_pf *pf = I40E_DEV_PRIVATE_TO_PF(dev->data->dev_private);
+       struct i40e_fdir_info *fdir_info = &pf->fdir;
+       char fdir_hash_name[RTE_HASH_NAMESIZE];
+       int ret;
+
+       struct rte_hash_parameters fdir_hash_params = {
+               .name = fdir_hash_name,
+               .entries = I40E_MAX_FDIR_FILTER_NUM,
+               .key_len = sizeof(struct rte_eth_fdir_input),
+               .hash_func = rte_hash_crc,
+               .hash_func_init_val = 0,
+               .socket_id = rte_socket_id(),
+       };
+
+       /* Initialize flow director filter rule list and hash */
+       TAILQ_INIT(&fdir_info->fdir_list);
+       snprintf(fdir_hash_name, RTE_HASH_NAMESIZE,
+                "fdir_%s", dev->data->name);
+       fdir_info->hash_table = rte_hash_create(&fdir_hash_params);
+       if (!fdir_info->hash_table) {
+               PMD_INIT_LOG(ERR, "Failed to create fdir hash table!");
+               return -EINVAL;
+       }
+       fdir_info->hash_map = rte_zmalloc("i40e_fdir_hash_map",
+                                         sizeof(struct i40e_fdir_filter *) *
+                                         I40E_MAX_FDIR_FILTER_NUM,
+                                         0);
+       if (!fdir_info->hash_map) {
+               PMD_INIT_LOG(ERR,
+                            "Failed to allocate memory for fdir hash map!");
+               ret = -ENOMEM;
+               goto err_fdir_hash_map_alloc;
+       }
+       return 0;
+
+err_fdir_hash_map_alloc:
+       rte_hash_free(fdir_info->hash_table);
+
+       return ret;
+}
+
 static int
 eth_i40e_dev_init(struct rte_eth_dev *dev)
 {
        struct rte_pci_device *pci_dev;
+       struct rte_intr_handle *intr_handle;
        struct i40e_pf *pf = I40E_DEV_PRIVATE_TO_PF(dev->data->dev_private);
        struct i40e_hw *hw = I40E_DEV_PRIVATE_TO_HW(dev->data->dev_private);
        struct i40e_vsi *vsi;
@@ -943,6 +1063,7 @@ eth_i40e_dev_init(struct rte_eth_dev *dev)
        dev->dev_ops = &i40e_eth_dev_ops;
        dev->rx_pkt_burst = i40e_recv_pkts;
        dev->tx_pkt_burst = i40e_xmit_pkts;
+       dev->tx_pkt_prepare = i40e_prep_pkts;
 
        /* for secondary processes, we don't initialise any further as primary
         * has already done this work. Only check we don't need a different
@@ -952,9 +1073,11 @@ eth_i40e_dev_init(struct rte_eth_dev *dev)
                i40e_set_tx_function(dev);
                return 0;
        }
-       pci_dev = dev->pci_dev;
+       pci_dev = I40E_DEV_TO_PCI(dev);
+       intr_handle = &pci_dev->intr_handle;
 
        rte_eth_copy_pci_info(dev, pci_dev);
+       dev->data->dev_flags |= RTE_ETH_DEV_DETACHABLE;
 
        pf->adapter = I40E_DEV_PRIVATE_TO_ADAPTER(dev->data->dev_private);
        pf->adapter->eth_dev = dev;
@@ -963,8 +1086,8 @@ eth_i40e_dev_init(struct rte_eth_dev *dev)
        hw->back = I40E_PF_TO_ADAPTER(pf);
        hw->hw_addr = (uint8_t *)(pci_dev->mem_resource[0].addr);
        if (!hw->hw_addr) {
-               PMD_INIT_LOG(ERR, "Hardware is not available, "
-                            "as address is NULL");
+               PMD_INIT_LOG(ERR,
+                       "Hardware is not available, as address is NULL");
                return -ENODEV;
        }
 
@@ -1021,6 +1144,12 @@ eth_i40e_dev_init(struct rte_eth_dev *dev)
                     ((hw->nvm.version >> 4) & 0xff),
                     (hw->nvm.version & 0xf), hw->nvm.eetrack);
 
+       /* initialise the L3_MAP register */
+       ret = i40e_aq_debug_write_register(hw, I40E_GLQF_L3_MAP(40),
+                                  0x00000028,  NULL);
+       if (ret)
+               PMD_INIT_LOG(ERR, "Failed to write L3 MAP register %d", ret);
+
        /* Need the special FW version to support floating VEB */
        config_floating_veb(dev);
        /* Clear PXE mode */
@@ -1100,8 +1229,8 @@ eth_i40e_dev_init(struct rte_eth_dev *dev)
        /* Set the global registers with default ether type value */
        ret = i40e_vlan_tpid_set(dev, ETH_VLAN_TYPE_OUTER, ETHER_TYPE_VLAN);
        if (ret != I40E_SUCCESS) {
-               PMD_INIT_LOG(ERR, "Failed to set the default outer "
-                            "VLAN ether type");
+               PMD_INIT_LOG(ERR,
+                       "Failed to set the default outer VLAN ether type");
                goto err_setup_pf_switch;
        }
 
@@ -1137,26 +1266,35 @@ eth_i40e_dev_init(struct rte_eth_dev *dev)
        /* Should be after VSI initialized */
        dev->data->mac_addrs = rte_zmalloc("i40e", len, 0);
        if (!dev->data->mac_addrs) {
-               PMD_INIT_LOG(ERR, "Failed to allocated memory "
-                                       "for storing mac address");
+               PMD_INIT_LOG(ERR,
+                       "Failed to allocated memory for storing mac address");
                goto err_mac_alloc;
        }
        ether_addr_copy((struct ether_addr *)hw->mac.perm_addr,
                                        &dev->data->mac_addrs[0]);
 
+       /* Init dcb to sw mode by default */
+       ret = i40e_dcb_init_configure(dev, TRUE);
+       if (ret != I40E_SUCCESS) {
+               PMD_INIT_LOG(INFO, "Failed to init dcb.");
+               pf->flags &= ~I40E_FLAG_DCB;
+       }
+       /* Update HW struct after DCB configuration */
+       i40e_get_cap(hw);
+
        /* initialize pf host driver to setup SRIOV resource if applicable */
        i40e_pf_host_init(dev);
 
        /* register callback func to eal lib */
-       rte_intr_callback_register(&(pci_dev->intr_handle),
-               i40e_dev_interrupt_handler, (void *)dev);
+       rte_intr_callback_register(intr_handle,
+                                  i40e_dev_interrupt_handler, dev);
 
        /* configure and enable device interrupt */
        i40e_pf_config_irq0(hw, TRUE);
        i40e_pf_enable_irq0(hw);
 
        /* enable uio intr after callback register */
-       rte_intr_enable(&(pci_dev->intr_handle));
+       rte_intr_enable(intr_handle);
        /*
         * Add an ethertype filter to drop all flow control frames transmitted
         * from VSIs. By doing so, we stop VF from sending out PAUSE or PFC
@@ -1172,15 +1310,26 @@ eth_i40e_dev_init(struct rte_eth_dev *dev)
        /* initialize mirror rule list */
        TAILQ_INIT(&pf->mirror_list);
 
-       /* Init dcb to sw mode by default */
-       ret = i40e_dcb_init_configure(dev, TRUE);
-       if (ret != I40E_SUCCESS) {
-               PMD_INIT_LOG(INFO, "Failed to init dcb.");
-               pf->flags &= ~I40E_FLAG_DCB;
-       }
+       ret = i40e_init_ethtype_filter_list(dev);
+       if (ret < 0)
+               goto err_init_ethtype_filter_list;
+       ret = i40e_init_tunnel_filter_list(dev);
+       if (ret < 0)
+               goto err_init_tunnel_filter_list;
+       ret = i40e_init_fdir_filter_list(dev);
+       if (ret < 0)
+               goto err_init_fdir_filter_list;
 
        return 0;
 
+err_init_fdir_filter_list:
+       rte_free(pf->tunnel.hash_table);
+       rte_free(pf->tunnel.hash_map);
+err_init_tunnel_filter_list:
+       rte_free(pf->ethertype.hash_table);
+       rte_free(pf->ethertype.hash_map);
+err_init_ethtype_filter_list:
+       rte_free(dev->data->mac_addrs);
 err_mac_alloc:
        i40e_vsi_release(pf->main_vsi);
 err_setup_pf_switch:
@@ -1200,12 +1349,73 @@ err_sync_phy_type:
        return ret;
 }
 
+static void
+i40e_rm_ethtype_filter_list(struct i40e_pf *pf)
+{
+       struct i40e_ethertype_filter *p_ethertype;
+       struct i40e_ethertype_rule *ethertype_rule;
+
+       ethertype_rule = &pf->ethertype;
+       /* Remove all ethertype filter rules and hash */
+       if (ethertype_rule->hash_map)
+               rte_free(ethertype_rule->hash_map);
+       if (ethertype_rule->hash_table)
+               rte_hash_free(ethertype_rule->hash_table);
+
+       while ((p_ethertype = TAILQ_FIRST(&ethertype_rule->ethertype_list))) {
+               TAILQ_REMOVE(&ethertype_rule->ethertype_list,
+                            p_ethertype, rules);
+               rte_free(p_ethertype);
+       }
+}
+
+static void
+i40e_rm_tunnel_filter_list(struct i40e_pf *pf)
+{
+       struct i40e_tunnel_filter *p_tunnel;
+       struct i40e_tunnel_rule *tunnel_rule;
+
+       tunnel_rule = &pf->tunnel;
+       /* Remove all tunnel director rules and hash */
+       if (tunnel_rule->hash_map)
+               rte_free(tunnel_rule->hash_map);
+       if (tunnel_rule->hash_table)
+               rte_hash_free(tunnel_rule->hash_table);
+
+       while ((p_tunnel = TAILQ_FIRST(&tunnel_rule->tunnel_list))) {
+               TAILQ_REMOVE(&tunnel_rule->tunnel_list, p_tunnel, rules);
+               rte_free(p_tunnel);
+       }
+}
+
+static void
+i40e_rm_fdir_filter_list(struct i40e_pf *pf)
+{
+       struct i40e_fdir_filter *p_fdir;
+       struct i40e_fdir_info *fdir_info;
+
+       fdir_info = &pf->fdir;
+       /* Remove all flow director rules and hash */
+       if (fdir_info->hash_map)
+               rte_free(fdir_info->hash_map);
+       if (fdir_info->hash_table)
+               rte_hash_free(fdir_info->hash_table);
+
+       while ((p_fdir = TAILQ_FIRST(&fdir_info->fdir_list))) {
+               TAILQ_REMOVE(&fdir_info->fdir_list, p_fdir, rules);
+               rte_free(p_fdir);
+       }
+}
+
 static int
 eth_i40e_dev_uninit(struct rte_eth_dev *dev)
 {
+       struct i40e_pf *pf;
        struct rte_pci_device *pci_dev;
+       struct rte_intr_handle *intr_handle;
        struct i40e_hw *hw;
        struct i40e_filter_control_settings settings;
+       struct rte_flow *p_flow;
        int ret;
        uint8_t aq_fail = 0;
 
@@ -1214,8 +1424,10 @@ eth_i40e_dev_uninit(struct rte_eth_dev *dev)
        if (rte_eal_process_type() != RTE_PROC_PRIMARY)
                return 0;
 
+       pf = I40E_DEV_PRIVATE_TO_PF(dev->data->dev_private);
        hw = I40E_DEV_PRIVATE_TO_HW(dev->data->dev_private);
-       pci_dev = dev->pci_dev;
+       pci_dev = I40E_DEV_TO_PCI(dev);
+       intr_handle = &pci_dev->intr_handle;
 
        if (hw->adapter_stopped == 0)
                i40e_dev_close(dev);
@@ -1245,11 +1457,21 @@ eth_i40e_dev_uninit(struct rte_eth_dev *dev)
        dev->data->mac_addrs = NULL;
 
        /* disable uio intr before callback unregister */
-       rte_intr_disable(&(pci_dev->intr_handle));
+       rte_intr_disable(intr_handle);
 
        /* register callback func to eal lib */
-       rte_intr_callback_unregister(&(pci_dev->intr_handle),
-               i40e_dev_interrupt_handler, (void *)dev);
+       rte_intr_callback_unregister(intr_handle,
+                                    i40e_dev_interrupt_handler, dev);
+
+       i40e_rm_ethtype_filter_list(pf);
+       i40e_rm_tunnel_filter_list(pf);
+       i40e_rm_fdir_filter_list(pf);
+
+       /* Remove all flows */
+       while ((p_flow = TAILQ_FIRST(&pf->flow_list))) {
+               TAILQ_REMOVE(&pf->flow_list, p_flow, node);
+               rte_free(p_flow);
+       }
 
        return 0;
 }
@@ -1315,6 +1537,8 @@ i40e_dev_configure(struct rte_eth_dev *dev)
                }
        }
 
+       TAILQ_INIT(&pf->flow_list);
+
        return 0;
 
 err_dcb:
@@ -1335,7 +1559,8 @@ void
 i40e_vsi_queues_unbind_intr(struct i40e_vsi *vsi)
 {
        struct rte_eth_dev *dev = vsi->adapter->eth_dev;
-       struct rte_intr_handle *intr_handle = &dev->pci_dev->intr_handle;
+       struct rte_pci_device *pci_dev = I40E_DEV_TO_PCI(dev);
+       struct rte_intr_handle *intr_handle = &pci_dev->intr_handle;
        struct i40e_hw *hw = I40E_VSI_TO_HW(vsi);
        uint16_t msix_vect = vsi->msix_intr;
        uint16_t i;
@@ -1448,7 +1673,8 @@ void
 i40e_vsi_queues_bind_intr(struct i40e_vsi *vsi)
 {
        struct rte_eth_dev *dev = vsi->adapter->eth_dev;
-       struct rte_intr_handle *intr_handle = &dev->pci_dev->intr_handle;
+       struct rte_pci_device *pci_dev = I40E_DEV_TO_PCI(dev);
+       struct rte_intr_handle *intr_handle = &pci_dev->intr_handle;
        struct i40e_hw *hw = I40E_VSI_TO_HW(vsi);
        uint16_t msix_vect = vsi->msix_intr;
        uint16_t nb_msix = RTE_MIN(vsi->nb_msix, intr_handle->nb_efd);
@@ -1519,7 +1745,8 @@ static void
 i40e_vsi_enable_queues_intr(struct i40e_vsi *vsi)
 {
        struct rte_eth_dev *dev = vsi->adapter->eth_dev;
-       struct rte_intr_handle *intr_handle = &dev->pci_dev->intr_handle;
+       struct rte_pci_device *pci_dev = I40E_DEV_TO_PCI(dev);
+       struct rte_intr_handle *intr_handle = &pci_dev->intr_handle;
        struct i40e_hw *hw = I40E_VSI_TO_HW(vsi);
        uint16_t interval = i40e_calc_itr_interval(\
                RTE_LIBRTE_I40E_ITR_INTERVAL);
@@ -1550,7 +1777,8 @@ static void
 i40e_vsi_disable_queues_intr(struct i40e_vsi *vsi)
 {
        struct rte_eth_dev *dev = vsi->adapter->eth_dev;
-       struct rte_intr_handle *intr_handle = &dev->pci_dev->intr_handle;
+       struct rte_pci_device *pci_dev = I40E_DEV_TO_PCI(dev);
+       struct rte_intr_handle *intr_handle = &pci_dev->intr_handle;
        struct i40e_hw *hw = I40E_VSI_TO_HW(vsi);
        uint16_t msix_intr, i;
 
@@ -1628,6 +1856,8 @@ i40e_phy_conf_link(struct i40e_hw *hw,
 
        /* use get_phy_abilities_resp value for the rest */
        phy_conf.phy_type = phy_ab.phy_type;
+       phy_conf.phy_type_ext = phy_ab.phy_type_ext;
+       phy_conf.fec_config = phy_ab.fec_cfg_curr_mod_ext_info;
        phy_conf.eee_capability = phy_ab.eee_capability;
        phy_conf.eeer = phy_ab.eeer_val;
        phy_conf.low_power_ctrl = phy_ab.d3_lpan;
@@ -1653,8 +1883,7 @@ i40e_apply_link_speed(struct rte_eth_dev *dev)
        struct rte_eth_conf *conf = &dev->data->dev_conf;
 
        speed = i40e_parse_link_speeds(conf->link_speeds);
-       if (!I40E_PHY_TYPE_SUPPORT_25G(hw->phy.phy_types))
-               abilities |= I40E_AQ_PHY_ENABLE_ATOMIC_LINK;
+       abilities |= I40E_AQ_PHY_ENABLE_ATOMIC_LINK;
        if (!(conf->link_speeds & ETH_LINK_SPEED_FIXED))
                abilities |= I40E_AQ_PHY_AN_ENABLED;
        abilities |= I40E_AQ_PHY_LINK_ENABLED;
@@ -1675,8 +1904,10 @@ i40e_dev_start(struct rte_eth_dev *dev)
        struct i40e_hw *hw = I40E_DEV_PRIVATE_TO_HW(dev->data->dev_private);
        struct i40e_vsi *main_vsi = pf->main_vsi;
        int ret, i;
-       struct rte_intr_handle *intr_handle = &dev->pci_dev->intr_handle;
+       struct rte_pci_device *pci_dev = I40E_DEV_TO_PCI(dev);
+       struct rte_intr_handle *intr_handle = &pci_dev->intr_handle;
        uint32_t intr_vector = 0;
+       struct i40e_vsi *vsi;
 
        hw->adapter_stopped = 0;
 
@@ -1692,8 +1923,9 @@ i40e_dev_start(struct rte_eth_dev *dev)
             !RTE_ETH_DEV_SRIOV(dev).active) &&
            dev->data->dev_conf.intr_conf.rxq != 0) {
                intr_vector = dev->data->nb_rx_queues;
-               if (rte_intr_efd_enable(intr_handle, intr_vector))
-                       return -1;
+               ret = rte_intr_efd_enable(intr_handle, intr_vector);
+               if (ret)
+                       return ret;
        }
 
        if (rte_intr_dp_is_en(intr_handle) && !intr_handle->intr_vec) {
@@ -1702,8 +1934,9 @@ i40e_dev_start(struct rte_eth_dev *dev)
                                    dev->data->nb_rx_queues * sizeof(int),
                                    0);
                if (!intr_handle->intr_vec) {
-                       PMD_INIT_LOG(ERR, "Failed to allocate %d rx_queues"
-                                    " intr_vec\n", dev->data->nb_rx_queues);
+                       PMD_INIT_LOG(ERR,
+                               "Failed to allocate %d rx_queues intr_vec",
+                               dev->data->nb_rx_queues);
                        return -ENOMEM;
                }
        }
@@ -1753,6 +1986,15 @@ i40e_dev_start(struct rte_eth_dev *dev)
                        PMD_DRV_LOG(INFO, "fail to set vsi broadcast");
        }
 
+       /* Enable the VLAN promiscuous mode. */
+       if (pf->vfs) {
+               for (i = 0; i < pf->vf_num; i++) {
+                       vsi = pf->vfs[i].vsi;
+                       i40e_aq_set_vsi_vlan_promisc(hw, vsi->seid,
+                                                    true, NULL);
+               }
+       }
+
        /* Apply link configure */
        if (dev->data->dev_conf.link_speeds & ~(ETH_LINK_SPEED_100M |
                                ETH_LINK_SPEED_1G | ETH_LINK_SPEED_10G |
@@ -1776,8 +2018,8 @@ i40e_dev_start(struct rte_eth_dev *dev)
                i40e_pf_enable_irq0(hw);
 
                if (dev->data->dev_conf.intr_conf.lsc != 0)
-                       PMD_INIT_LOG(INFO, "lsc won't enable because of"
-                                    " no intr multiplex\n");
+                       PMD_INIT_LOG(INFO,
+                               "lsc won't enable because of no intr multiplex");
        } else if (dev->data->dev_conf.intr_conf.lsc != 0) {
                ret = i40e_aq_set_phy_int_mask(hw,
                                               ~(I40E_AQ_EVENT_LINK_UPDOWN |
@@ -1793,6 +2035,8 @@ i40e_dev_start(struct rte_eth_dev *dev)
        /* enable uio intr after callback register */
        rte_intr_enable(intr_handle);
 
+       i40e_filter_restore(pf);
+
        return I40E_SUCCESS;
 
 err_up:
@@ -1808,7 +2052,8 @@ i40e_dev_stop(struct rte_eth_dev *dev)
        struct i40e_pf *pf = I40E_DEV_PRIVATE_TO_PF(dev->data->dev_private);
        struct i40e_vsi *main_vsi = pf->main_vsi;
        struct i40e_mirror_rule *p_mirror;
-       struct rte_intr_handle *intr_handle = &dev->pci_dev->intr_handle;
+       struct rte_pci_device *pci_dev = I40E_DEV_TO_PCI(dev);
+       struct rte_intr_handle *intr_handle = &pci_dev->intr_handle;
        int i;
 
        /* Disable all queues */
@@ -1859,6 +2104,8 @@ i40e_dev_close(struct rte_eth_dev *dev)
 {
        struct i40e_pf *pf = I40E_DEV_PRIVATE_TO_PF(dev->data->dev_private);
        struct i40e_hw *hw = I40E_DEV_PRIVATE_TO_HW(dev->data->dev_private);
+       struct rte_pci_device *pci_dev = I40E_DEV_TO_PCI(dev);
+       struct rte_intr_handle *intr_handle = &pci_dev->intr_handle;
        uint32_t reg;
        int i;
 
@@ -1870,23 +2117,22 @@ i40e_dev_close(struct rte_eth_dev *dev)
 
        /* Disable interrupt */
        i40e_pf_disable_irq0(hw);
-       rte_intr_disable(&(dev->pci_dev->intr_handle));
+       rte_intr_disable(intr_handle);
 
        /* shutdown and destroy the HMC */
        i40e_shutdown_lan_hmc(hw);
 
-       /* release all the existing VSIs and VEBs */
-       i40e_fdir_teardown(pf);
-       i40e_vsi_release(pf->main_vsi);
-
        for (i = 0; i < pf->nb_cfg_vmdq_vsi; i++) {
                i40e_vsi_release(pf->vmdq[i].vsi);
                pf->vmdq[i].vsi = NULL;
        }
-
        rte_free(pf->vmdq);
        pf->vmdq = NULL;
 
+       /* release all the existing VSIs and VEBs */
+       i40e_fdir_teardown(pf);
+       i40e_vsi_release(pf->main_vsi);
+
        /* shutdown the adminq */
        i40e_aq_queue_shutdown(hw, true);
        i40e_shutdown_adminq(hw);
@@ -1990,8 +2236,7 @@ i40e_dev_set_link_down(struct rte_eth_dev *dev)
        uint8_t abilities = 0;
        struct i40e_hw *hw = I40E_DEV_PRIVATE_TO_HW(dev->data->dev_private);
 
-       if (!I40E_PHY_TYPE_SUPPORT_25G(hw->phy.phy_types))
-               abilities = I40E_AQ_PHY_ENABLE_ATOMIC_LINK;
+       abilities = I40E_AQ_PHY_ENABLE_ATOMIC_LINK;
        return i40e_phy_conf_link(hw, abilities, speed);
 }
 
@@ -2025,11 +2270,11 @@ i40e_dev_link_update(struct rte_eth_dev *dev,
                }
 
                link.link_status = link_status.link_info & I40E_AQ_LINK_UP;
-               if (!wait_to_complete)
+               if (!wait_to_complete || link.link_status)
                        break;
 
                rte_delay_ms(CHECK_INTERVAL);
-       } while (!link.link_status && rep_cnt--);
+       } while (--rep_cnt);
 
        if (!link.link_status)
                goto out;
@@ -2532,6 +2777,7 @@ i40e_dev_xstats_get(struct rte_eth_dev *dev, struct rte_eth_xstat *xstats,
        for (i = 0; i < I40E_NB_ETH_XSTATS; i++) {
                xstats[count].value = *(uint64_t *)(((char *)&hw_stats->eth) +
                        rte_i40e_stats_strings[i].offset);
+               xstats[count].id = count;
                count++;
        }
 
@@ -2539,6 +2785,7 @@ i40e_dev_xstats_get(struct rte_eth_dev *dev, struct rte_eth_xstat *xstats,
        for (i = 0; i < I40E_NB_HW_PORT_XSTATS; i++) {
                xstats[count].value = *(uint64_t *)(((char *)hw_stats) +
                        rte_i40e_hw_port_strings[i].offset);
+               xstats[count].id = count;
                count++;
        }
 
@@ -2548,6 +2795,7 @@ i40e_dev_xstats_get(struct rte_eth_dev *dev, struct rte_eth_xstat *xstats,
                                *(uint64_t *)(((char *)hw_stats) +
                                rte_i40e_rxq_prio_strings[i].offset +
                                (sizeof(uint64_t) * prio));
+                       xstats[count].id = count;
                        count++;
                }
        }
@@ -2558,6 +2806,7 @@ i40e_dev_xstats_get(struct rte_eth_dev *dev, struct rte_eth_xstat *xstats,
                                *(uint64_t *)(((char *)hw_stats) +
                                rte_i40e_txq_prio_strings[i].offset +
                                (sizeof(uint64_t) * prio));
+                       xstats[count].id = count;
                        count++;
                }
        }
@@ -2576,19 +2825,49 @@ i40e_dev_queue_stats_mapping_set(__rte_unused struct rte_eth_dev *dev,
        return -ENOSYS;
 }
 
+static int
+i40e_fw_version_get(struct rte_eth_dev *dev, char *fw_version, size_t fw_size)
+{
+       struct i40e_hw *hw = I40E_DEV_PRIVATE_TO_HW(dev->data->dev_private);
+       u32 full_ver;
+       u8 ver, patch;
+       u16 build;
+       int ret;
+
+       full_ver = hw->nvm.oem_ver;
+       ver = (u8)(full_ver >> 24);
+       build = (u16)((full_ver >> 8) & 0xffff);
+       patch = (u8)(full_ver & 0xff);
+
+       ret = snprintf(fw_version, fw_size,
+                "%d.%d%d 0x%08x %d.%d.%d",
+                ((hw->nvm.version >> 12) & 0xf),
+                ((hw->nvm.version >> 4) & 0xff),
+                (hw->nvm.version & 0xf), hw->nvm.eetrack,
+                ver, build, patch);
+
+       ret += 1; /* add the size of '\0' */
+       if (fw_size < (u32)ret)
+               return ret;
+       else
+               return 0;
+}
+
 static void
 i40e_dev_info_get(struct rte_eth_dev *dev, struct rte_eth_dev_info *dev_info)
 {
        struct i40e_pf *pf = I40E_DEV_PRIVATE_TO_PF(dev->data->dev_private);
        struct i40e_hw *hw = I40E_DEV_PRIVATE_TO_HW(dev->data->dev_private);
        struct i40e_vsi *vsi = pf->main_vsi;
+       struct rte_pci_device *pci_dev = I40E_DEV_TO_PCI(dev);
 
+       dev_info->pci_dev = pci_dev;
        dev_info->max_rx_queues = vsi->nb_qps;
        dev_info->max_tx_queues = vsi->nb_qps;
        dev_info->min_rx_bufsize = I40E_BUF_SIZE_MIN;
        dev_info->max_rx_pktlen = I40E_FRAME_SIZE_MAX;
        dev_info->max_mac_addrs = vsi->max_macaddrs;
-       dev_info->max_vfs = dev->pci_dev->max_vfs;
+       dev_info->max_vfs = pci_dev->max_vfs;
        dev_info->rx_offload_capa =
                DEV_RX_OFFLOAD_VLAN_STRIP |
                DEV_RX_OFFLOAD_QINQ_STRIP |
@@ -2645,6 +2924,8 @@ i40e_dev_info_get(struct rte_eth_dev *dev, struct rte_eth_dev_info *dev_info)
                .nb_max = I40E_MAX_RING_DESC,
                .nb_min = I40E_MIN_RING_DESC,
                .nb_align = I40E_ALIGN_RING_DESC,
+               .nb_seg_max = I40E_TX_MAX_SEG,
+               .nb_mtu_seg_max = I40E_TX_MAX_MTU_SEG,
        };
 
        if (pf->flags & I40E_FLAG_VMDQ) {
@@ -2705,7 +2986,7 @@ i40e_vlan_tpid_set(struct rte_eth_dev *dev,
                else {
                        ret = -EINVAL;
                        PMD_DRV_LOG(ERR,
-                               "Unsupported vlan type in single vlan.\n");
+                               "Unsupported vlan type in single vlan.");
                        return ret;
                }
                break;
@@ -2717,13 +2998,15 @@ i40e_vlan_tpid_set(struct rte_eth_dev *dev,
        ret = i40e_aq_debug_read_register(hw, I40E_GL_SWT_L2TAGCTRL(reg_id),
                                          &reg_r, NULL);
        if (ret != I40E_SUCCESS) {
-               PMD_DRV_LOG(ERR, "Fail to debug read from "
-                           "I40E_GL_SWT_L2TAGCTRL[%d]", reg_id);
+               PMD_DRV_LOG(ERR,
+                          "Fail to debug read from I40E_GL_SWT_L2TAGCTRL[%d]",
+                          reg_id);
                ret = -EIO;
                return ret;
        }
-       PMD_DRV_LOG(DEBUG, "Debug read from I40E_GL_SWT_L2TAGCTRL[%d]: "
-                   "0x%08"PRIx64"", reg_id, reg_r);
+       PMD_DRV_LOG(DEBUG,
+               "Debug read from I40E_GL_SWT_L2TAGCTRL[%d]: 0x%08"PRIx64,
+               reg_id, reg_r);
 
        reg_w = reg_r & (~(I40E_GL_SWT_L2TAGCTRL_ETHERTYPE_MASK));
        reg_w |= ((uint64_t)tpid << I40E_GL_SWT_L2TAGCTRL_ETHERTYPE_SHIFT);
@@ -2737,12 +3020,14 @@ i40e_vlan_tpid_set(struct rte_eth_dev *dev,
                                           reg_w, NULL);
        if (ret != I40E_SUCCESS) {
                ret = -EIO;
-               PMD_DRV_LOG(ERR, "Fail to debug write to "
-                           "I40E_GL_SWT_L2TAGCTRL[%d]", reg_id);
+               PMD_DRV_LOG(ERR,
+                       "Fail to debug write to I40E_GL_SWT_L2TAGCTRL[%d]",
+                       reg_id);
                return ret;
        }
-       PMD_DRV_LOG(DEBUG, "Debug write 0x%08"PRIx64" to "
-                   "I40E_GL_SWT_L2TAGCTRL[%d]", reg_w, reg_id);
+       PMD_DRV_LOG(DEBUG,
+               "Debug write 0x%08"PRIx64" to I40E_GL_SWT_L2TAGCTRL[%d]",
+               reg_w, reg_id);
 
        return ret;
 }
@@ -2886,8 +3171,9 @@ i40e_flow_ctrl_set(struct rte_eth_dev *dev, struct rte_eth_fc_conf *fc_conf)
        max_high_water = I40E_RXPBSIZE >> I40E_KILOSHIFT;
        if ((fc_conf->high_water > max_high_water) ||
                        (fc_conf->high_water < fc_conf->low_water)) {
-               PMD_INIT_LOG(ERR, "Invalid high/low water setup value in KB, "
-                       "High_water must <= %d.", max_high_water);
+               PMD_INIT_LOG(ERR,
+                       "Invalid high/low water setup value in KB, High_water must be <= %d.",
+                       max_high_water);
                return -EINVAL;
        }
 
@@ -3059,8 +3345,8 @@ i40e_macaddr_remove(struct rte_eth_dev *dev, uint32_t index)
                                /* No VMDQ pool enabled or configured */
                                if (!(pf->flags & I40E_FLAG_VMDQ) ||
                                        (i > pf->nb_cfg_vmdq_vsi)) {
-                                       PMD_DRV_LOG(ERR, "No VMDQ pool enabled"
-                                                       "/configured");
+                                       PMD_DRV_LOG(ERR,
+                                               "No VMDQ pool enabled/configured");
                                        return;
                                }
                                vsi = pf->vmdq[i - 1].vsi;
@@ -3261,9 +3547,9 @@ i40e_dev_rss_reta_update(struct rte_eth_dev *dev,
 
        if (reta_size != lut_size ||
                reta_size > ETH_RSS_RETA_SIZE_512) {
-               PMD_DRV_LOG(ERR, "The size of hash lookup table configured "
-                       "(%d) doesn't match the number hardware can supported "
-                                       "(%d)\n", reta_size, lut_size);
+               PMD_DRV_LOG(ERR,
+                       "The size of hash lookup table configured (%d) doesn't match the number hardware can supported (%d)",
+                       reta_size, lut_size);
                return -EINVAL;
        }
 
@@ -3302,9 +3588,9 @@ i40e_dev_rss_reta_query(struct rte_eth_dev *dev,
 
        if (reta_size != lut_size ||
                reta_size > ETH_RSS_RETA_SIZE_512) {
-               PMD_DRV_LOG(ERR, "The size of hash lookup table configured "
-                       "(%d) doesn't match the number hardware can supported "
-                                       "(%d)\n", reta_size, lut_size);
+               PMD_DRV_LOG(ERR,
+                       "The size of hash lookup table configured (%d) doesn't match the number hardware can supported (%d)",
+                       reta_size, lut_size);
                return -EINVAL;
        }
 
@@ -3359,8 +3645,9 @@ i40e_allocate_dma_mem_d(__attribute__((unused)) struct i40e_hw *hw,
        mem->va = mz->addr;
        mem->pa = rte_mem_phy2mch(mz->memseg_id, mz->phys_addr);
        mem->zone = (const void *)mz;
-       PMD_DRV_LOG(DEBUG, "memzone %s allocated with physical address: "
-                   "%"PRIu64, mz->name, mem->pa);
+       PMD_DRV_LOG(DEBUG,
+               "memzone %s allocated with physical address: %"PRIu64,
+               mz->name, mem->pa);
 
        return I40E_SUCCESS;
 }
@@ -3377,9 +3664,9 @@ i40e_free_dma_mem_d(__attribute__((unused)) struct i40e_hw *hw,
        if (!mem)
                return I40E_ERR_PARAM;
 
-       PMD_DRV_LOG(DEBUG, "memzone %s to be freed with physical address: "
-                   "%"PRIu64, ((const struct rte_memzone *)mem->zone)->name,
-                   mem->pa);
+       PMD_DRV_LOG(DEBUG,
+               "memzone %s to be freed with physical address: %"PRIu64,
+               ((const struct rte_memzone *)mem->zone)->name, mem->pa);
        rte_memzone_free((const struct rte_memzone *)mem->zone);
        mem->zone = NULL;
        mem->va = NULL;
@@ -3490,9 +3777,10 @@ i40e_pf_parameter_init(struct rte_eth_dev *dev)
 {
        struct i40e_pf *pf = I40E_DEV_PRIVATE_TO_PF(dev->data->dev_private);
        struct i40e_hw *hw = I40E_PF_TO_HW(pf);
+       struct rte_pci_device *pci_dev = I40E_DEV_TO_PCI(dev);
        uint16_t qp_count = 0, vsi_count = 0;
 
-       if (dev->pci_dev->max_vfs && !hw->func_caps.sr_iov_1_1) {
+       if (pci_dev->max_vfs && !hw->func_caps.sr_iov_1_1) {
                PMD_INIT_LOG(ERR, "HW configuration doesn't support SRIOV");
                return -EINVAL;
        }
@@ -3533,13 +3821,13 @@ i40e_pf_parameter_init(struct rte_eth_dev *dev)
 
        /* VF queue/VSI allocation */
        pf->vf_qp_offset = pf->lan_qp_offset + pf->lan_nb_qps;
-       if (hw->func_caps.sr_iov_1_1 && dev->pci_dev->max_vfs) {
+       if (hw->func_caps.sr_iov_1_1 && pci_dev->max_vfs) {
                pf->flags |= I40E_FLAG_SRIOV;
                pf->vf_nb_qps = RTE_LIBRTE_I40E_QUEUE_NUM_PER_VF;
-               pf->vf_num = dev->pci_dev->max_vfs;
-               PMD_DRV_LOG(DEBUG, "%u VF VSIs, %u queues per VF VSI, "
-                           "in total %u queues", pf->vf_num, pf->vf_nb_qps,
-                           pf->vf_nb_qps * pf->vf_num);
+               pf->vf_num = pci_dev->max_vfs;
+               PMD_DRV_LOG(DEBUG,
+                       "%u VF VSIs, %u queues per VF VSI, in total %u queues",
+                       pf->vf_num, pf->vf_nb_qps, pf->vf_nb_qps * pf->vf_num);
        } else {
                pf->vf_nb_qps = 0;
                pf->vf_num = 0;
@@ -3567,14 +3855,13 @@ i40e_pf_parameter_init(struct rte_eth_dev *dev)
                        if (pf->max_nb_vmdq_vsi) {
                                pf->flags |= I40E_FLAG_VMDQ;
                                pf->vmdq_nb_qps = pf->vmdq_nb_qp_max;
-                               PMD_DRV_LOG(DEBUG, "%u VMDQ VSIs, %u queues "
-                                           "per VMDQ VSI, in total %u queues",
-                                           pf->max_nb_vmdq_vsi,
-                                           pf->vmdq_nb_qps, pf->vmdq_nb_qps *
-                                           pf->max_nb_vmdq_vsi);
+                               PMD_DRV_LOG(DEBUG,
+                                       "%u VMDQ VSIs, %u queues per VMDQ VSI, in total %u queues",
+                                       pf->max_nb_vmdq_vsi, pf->vmdq_nb_qps,
+                                       pf->vmdq_nb_qps * pf->max_nb_vmdq_vsi);
                        } else {
-                               PMD_DRV_LOG(INFO, "No enough queues left for "
-                                           "VMDq");
+                               PMD_DRV_LOG(INFO,
+                                       "No enough queues left for VMDq");
                        }
                } else {
                        PMD_DRV_LOG(INFO, "No queue or VSI left for VMDq");
@@ -3587,15 +3874,15 @@ i40e_pf_parameter_init(struct rte_eth_dev *dev)
                pf->flags |= I40E_FLAG_DCB;
 
        if (qp_count > hw->func_caps.num_tx_qp) {
-               PMD_DRV_LOG(ERR, "Failed to allocate %u queues, which exceeds "
-                           "the hardware maximum %u", qp_count,
-                           hw->func_caps.num_tx_qp);
+               PMD_DRV_LOG(ERR,
+                       "Failed to allocate %u queues, which exceeds the hardware maximum %u",
+                       qp_count, hw->func_caps.num_tx_qp);
                return -EINVAL;
        }
        if (vsi_count > hw->func_caps.num_vsis) {
-               PMD_DRV_LOG(ERR, "Failed to allocate %u VSIs, which exceeds "
-                           "the hardware maximum %u", vsi_count,
-                           hw->func_caps.num_vsis);
+               PMD_DRV_LOG(ERR,
+                       "Failed to allocate %u VSIs, which exceeds the hardware maximum %u",
+                       vsi_count, hw->func_caps.num_vsis);
                return -EINVAL;
        }
 
@@ -3841,8 +4128,8 @@ i40e_res_pool_alloc(struct i40e_res_pool_info *pool,
                 */
                entry = rte_zmalloc("res_pool", sizeof(*entry), 0);
                if (entry == NULL) {
-                       PMD_DRV_LOG(ERR, "Failed to allocate memory for "
-                                   "resource pool");
+                       PMD_DRV_LOG(ERR,
+                               "Failed to allocate memory for resource pool");
                        return -ENOMEM;
                }
                entry->base = valid_entry->base;
@@ -3882,9 +4169,9 @@ validate_tcmap_parameter(struct i40e_vsi *vsi, uint8_t enabled_tcmap)
        }
 
        if (!bitmap_is_subset(hw->func_caps.enabled_tcmap, enabled_tcmap)) {
-               PMD_DRV_LOG(ERR, "Enabled TC map 0x%x not applicable to "
-                           "HW support 0x%x", hw->func_caps.enabled_tcmap,
-                           enabled_tcmap);
+               PMD_DRV_LOG(ERR,
+                       "Enabled TC map 0x%x not applicable to HW support 0x%x",
+                       hw->func_caps.enabled_tcmap, enabled_tcmap);
                return I40E_NOT_SUPPORTED;
        }
        return I40E_SUCCESS;
@@ -4102,12 +4389,13 @@ i40e_veb_setup(struct i40e_pf *pf, struct i40e_vsi *vsi)
                            hw->aq.asq_last_status);
                goto fail;
        }
+       veb->enabled_tc = I40E_DEFAULT_TCMAP;
 
        /* get statistics index */
        ret = i40e_aq_get_veb_parameters(hw, veb->seid, NULL, NULL,
                                &veb->stats_idx, NULL, NULL, NULL);
        if (ret != I40E_SUCCESS) {
-               PMD_DRV_LOG(ERR, "Get veb statics index failed, aq_err: %d",
+               PMD_DRV_LOG(ERR, "Get veb statistics index failed, aq_err: %d",
                            hw->aq.asq_last_status);
                goto fail;
        }
@@ -4136,6 +4424,9 @@ i40e_vsi_release(struct i40e_vsi *vsi)
        if (!vsi)
                return I40E_SUCCESS;
 
+       if (!vsi->adapter)
+               return -EFAULT;
+
        user_param = vsi->user_param;
 
        pf = I40E_VSI_TO_PF(vsi);
@@ -4226,8 +4517,8 @@ i40e_update_default_filter_setting(struct i40e_vsi *vsi)
                struct i40e_mac_filter *f;
                struct ether_addr *mac;
 
-               PMD_DRV_LOG(WARNING, "Cannot remove the default "
-                           "macvlan filter");
+               PMD_DRV_LOG(WARNING,
+                       "Cannot remove the default macvlan filter");
                /* It needs to add the permanent mac into mac list */
                f = rte_zmalloc("macv_filter", sizeof(*f), 0);
                if (f == NULL) {
@@ -4277,8 +4568,9 @@ i40e_vsi_get_bw_config(struct i40e_vsi *vsi)
        ret = i40e_aq_query_vsi_ets_sla_config(hw, vsi->seid,
                                        &ets_sla_config, NULL);
        if (ret != I40E_SUCCESS) {
-               PMD_DRV_LOG(ERR, "VSI failed to get TC bandwdith "
-                           "configuration %u", hw->aq.asq_last_status);
+               PMD_DRV_LOG(ERR,
+                       "VSI failed to get TC bandwdith configuration %u",
+                       hw->aq.asq_last_status);
                return ret;
        }
 
@@ -4345,7 +4637,7 @@ i40e_enable_pf_lb(struct i40e_pf *pf)
 
        ret = i40e_aq_update_vsi_params(hw, &ctxt, NULL);
        if (ret)
-               PMD_DRV_LOG(ERR, "update vsi switch failed, aq_err=%d\n",
+               PMD_DRV_LOG(ERR, "update vsi switch failed, aq_err=%d",
                            hw->aq.asq_last_status);
 }
 
@@ -4366,14 +4658,14 @@ i40e_vsi_setup(struct i40e_pf *pf,
 
        if (type != I40E_VSI_MAIN && type != I40E_VSI_SRIOV &&
            uplink_vsi == NULL) {
-               PMD_DRV_LOG(ERR, "VSI setup failed, "
-                           "VSI link shouldn't be NULL");
+               PMD_DRV_LOG(ERR,
+                       "VSI setup failed, VSI link shouldn't be NULL");
                return NULL;
        }
 
        if (type == I40E_VSI_MAIN && uplink_vsi != NULL) {
-               PMD_DRV_LOG(ERR, "VSI setup failed, MAIN VSI "
-                           "uplink VSI should be NULL");
+               PMD_DRV_LOG(ERR,
+                       "VSI setup failed, MAIN VSI uplink VSI should be NULL");
                return NULL;
        }
 
@@ -4417,6 +4709,8 @@ i40e_vsi_setup(struct i40e_pf *pf,
        vsi->max_macaddrs = I40E_NUM_MACADDR_MAX;
        vsi->parent_vsi = uplink_vsi ? uplink_vsi : pf->main_vsi;
        vsi->user_param = user_param;
+       vsi->vlan_anti_spoof_on = 0;
+       vsi->vlan_filter_on = 0;
        /* Allocate queues */
        switch (vsi->type) {
        case I40E_VSI_MAIN  :
@@ -4524,8 +4818,8 @@ i40e_vsi_setup(struct i40e_pf *pf,
                ret = i40e_vsi_config_tc_queue_mapping(vsi, &ctxt.info,
                                                I40E_DEFAULT_TCMAP);
                if (ret != I40E_SUCCESS) {
-                       PMD_DRV_LOG(ERR, "Failed to configure "
-                                   "TC queue mapping");
+                       PMD_DRV_LOG(ERR,
+                               "Failed to configure TC queue mapping");
                        goto fail_msix_alloc;
                }
                ctxt.seid = vsi->seid;
@@ -4593,13 +4887,14 @@ i40e_vsi_setup(struct i40e_pf *pf,
                        rte_cpu_to_le_16(I40E_AQ_VSI_PROP_VLAN_VALID);
                ctxt.info.port_vlan_flags |= I40E_AQ_VSI_PVLAN_MODE_ALL;
                ret = i40e_vsi_config_tc_queue_mapping(vsi, &ctxt.info,
-                                               I40E_DEFAULT_TCMAP);
+                                               hw->func_caps.enabled_tcmap);
                if (ret != I40E_SUCCESS) {
-                       PMD_DRV_LOG(ERR, "Failed to configure "
-                                   "TC queue mapping");
+                       PMD_DRV_LOG(ERR,
+                               "Failed to configure TC queue mapping");
                        goto fail_msix_alloc;
                }
-               ctxt.info.up_enable_bits = I40E_DEFAULT_TCMAP;
+
+               ctxt.info.up_enable_bits = hw->func_caps.enabled_tcmap;
                ctxt.info.valid_sections |=
                        rte_cpu_to_le_16(I40E_AQ_VSI_PROP_SCHED_VALID);
                /**
@@ -4638,8 +4933,8 @@ i40e_vsi_setup(struct i40e_pf *pf,
                ret = i40e_vsi_config_tc_queue_mapping(vsi, &ctxt.info,
                                                I40E_DEFAULT_TCMAP);
                if (ret != I40E_SUCCESS) {
-                       PMD_DRV_LOG(ERR, "Failed to configure "
-                                       "TC queue mapping");
+                       PMD_DRV_LOG(ERR,
+                               "Failed to configure TC queue mapping");
                        goto fail_msix_alloc;
                }
                ctxt.info.up_enable_bits = I40E_DEFAULT_TCMAP;
@@ -4656,8 +4951,8 @@ i40e_vsi_setup(struct i40e_pf *pf,
                ret = i40e_vsi_config_tc_queue_mapping(vsi, &ctxt.info,
                                                I40E_DEFAULT_TCMAP);
                if (ret != I40E_SUCCESS) {
-                       PMD_DRV_LOG(ERR, "Failed to configure "
-                                       "TC queue mapping.");
+                       PMD_DRV_LOG(ERR,
+                               "Failed to configure TC queue mapping.");
                        goto fail_msix_alloc;
                }
                ctxt.info.up_enable_bits = I40E_DEFAULT_TCMAP;
@@ -4920,8 +5215,9 @@ i40e_pf_setup(struct i40e_pf *pf)
                /* make queue allocated first, let FDIR use queue pair 0*/
                ret = i40e_res_pool_alloc(&pf->qp_pool, I40E_DEFAULT_QP_NUM_FDIR);
                if (ret != I40E_FDIR_QUEUE_ID) {
-                       PMD_DRV_LOG(ERR, "queue allocation fails for FDIR :"
-                                   " ret =%d", ret);
+                       PMD_DRV_LOG(ERR,
+                               "queue allocation fails for FDIR: ret =%d",
+                               ret);
                        pf->flags &= ~I40E_FLAG_FDIR;
                }
        }
@@ -4940,12 +5236,12 @@ i40e_pf_setup(struct i40e_pf *pf)
        else if (hw->func_caps.rss_table_size == ETH_RSS_RETA_SIZE_512)
                settings.hash_lut_size = I40E_HASH_LUT_SIZE_512;
        else {
-               PMD_DRV_LOG(ERR, "Hash lookup table size (%u) not supported\n",
-                                               hw->func_caps.rss_table_size);
+               PMD_DRV_LOG(ERR, "Hash lookup table size (%u) not supported",
+                       hw->func_caps.rss_table_size);
                return I40E_ERR_PARAM;
        }
-       PMD_DRV_LOG(INFO, "Hardware capability of hash lookup table "
-                       "size: %u\n", hw->func_caps.rss_table_size);
+       PMD_DRV_LOG(INFO, "Hardware capability of hash lookup table size: %u",
+               hw->func_caps.rss_table_size);
        pf->hash_lut_size = hw->func_caps.rss_table_size;
 
        /* Enable ethtype and macvlan filters */
@@ -5195,8 +5491,8 @@ i40e_dev_rx_init(struct i40e_pf *pf)
 
                ret = i40e_rx_queue_init(rxq);
                if (ret != I40E_SUCCESS) {
-                       PMD_DRV_LOG(ERR, "Failed to do RX queue "
-                                   "initialization");
+                       PMD_DRV_LOG(ERR,
+                               "Failed to do RX queue initialization");
                        break;
                }
        }
@@ -5480,8 +5776,9 @@ i40e_dev_handle_aq_msg(struct rte_eth_dev *dev)
                ret = i40e_clean_arq_element(hw, &info, &pending);
 
                if (ret != I40E_SUCCESS) {
-                       PMD_DRV_LOG(INFO, "Failed to read msg from AdminQ, "
-                                   "aq_err: %u", hw->aq.asq_last_status);
+                       PMD_DRV_LOG(INFO,
+                               "Failed to read msg from AdminQ, aq_err: %u",
+                               hw->aq.asq_last_status);
                        break;
                }
                opcode = rte_le_to_cpu_16(info.desc.opcode);
@@ -5526,8 +5823,7 @@ i40e_dev_handle_aq_msg(struct rte_eth_dev *dev)
  *  void
  */
 static void
-i40e_dev_interrupt_handler(__rte_unused struct rte_intr_handle *handle,
-                          void *param)
+i40e_dev_interrupt_handler(void *param)
 {
        struct rte_eth_dev *dev = (struct rte_eth_dev *)param;
        struct i40e_hw *hw = I40E_DEV_PRIVATE_TO_HW(dev->data->dev_private);
@@ -5544,7 +5840,6 @@ i40e_dev_interrupt_handler(__rte_unused struct rte_intr_handle *handle,
                PMD_DRV_LOG(INFO, "No interrupt event");
                goto done;
        }
-#ifdef RTE_LIBRTE_I40E_DEBUG_DRIVER
        if (icr0 & I40E_PFINT_ICR0_ECC_ERR_MASK)
                PMD_DRV_LOG(ERR, "ICR0: unrecoverable ECC error");
        if (icr0 & I40E_PFINT_ICR0_MAL_DETECT_MASK)
@@ -5559,7 +5854,6 @@ i40e_dev_interrupt_handler(__rte_unused struct rte_intr_handle *handle,
                PMD_DRV_LOG(ERR, "ICR0: HMC error");
        if (icr0 & I40E_PFINT_ICR0_PE_CRITERR_MASK)
                PMD_DRV_LOG(ERR, "ICR0: protocol engine critical error");
-#endif /* RTE_LIBRTE_I40E_DEBUG_DRIVER */
 
        if (icr0 & I40E_PFINT_ICR0_VFLR_MASK) {
                PMD_DRV_LOG(INFO, "ICR0: VF reset detected");
@@ -5573,7 +5867,7 @@ i40e_dev_interrupt_handler(__rte_unused struct rte_intr_handle *handle,
 done:
        /* Enable interrupt */
        i40e_pf_enable_irq0(hw);
-       rte_intr_enable(&(dev->pci_dev->intr_handle));
+       rte_intr_enable(dev->intr_handle);
 }
 
 static int
@@ -5626,7 +5920,7 @@ i40e_add_macvlan_filters(struct i40e_vsi *vsi,
                                flags = I40E_AQC_MACVLAN_ADD_HASH_MATCH;
                                break;
                        default:
-                               PMD_DRV_LOG(ERR, "Invalid MAC match type\n");
+                               PMD_DRV_LOG(ERR, "Invalid MAC match type");
                                ret = I40E_ERR_PARAM;
                                goto DONE;
                        }
@@ -5701,7 +5995,7 @@ i40e_remove_macvlan_filters(struct i40e_vsi *vsi,
                                flags = I40E_AQC_MACVLAN_DEL_HASH_MATCH;
                                break;
                        default:
-                               PMD_DRV_LOG(ERR, "Invalid MAC filter type\n");
+                               PMD_DRV_LOG(ERR, "Invalid MAC filter type");
                                ret = I40E_ERR_PARAM;
                                goto DONE;
                        }
@@ -5756,14 +6050,11 @@ i40e_find_vlan_filter(struct i40e_vsi *vsi,
 }
 
 static void
-i40e_set_vlan_filter(struct i40e_vsi *vsi,
-                        uint16_t vlan_id, bool on)
+i40e_store_vlan_filter(struct i40e_vsi *vsi,
+                      uint16_t vlan_id, bool on)
 {
        uint32_t vid_idx, vid_bit;
 
-       if (vlan_id > ETH_VLAN_ID_MAX)
-               return;
-
        vid_idx = I40E_VFTA_IDX(vlan_id);
        vid_bit = I40E_VFTA_BIT(vlan_id);
 
@@ -5773,6 +6064,38 @@ i40e_set_vlan_filter(struct i40e_vsi *vsi,
                vsi->vfta[vid_idx] &= ~vid_bit;
 }
 
+static void
+i40e_set_vlan_filter(struct i40e_vsi *vsi,
+                    uint16_t vlan_id, bool on)
+{
+       struct i40e_hw *hw = I40E_VSI_TO_HW(vsi);
+       struct i40e_aqc_add_remove_vlan_element_data vlan_data = {0};
+       int ret;
+
+       if (vlan_id > ETH_VLAN_ID_MAX)
+               return;
+
+       i40e_store_vlan_filter(vsi, vlan_id, on);
+
+       if ((!vsi->vlan_anti_spoof_on && !vsi->vlan_filter_on) || !vlan_id)
+               return;
+
+       vlan_data.vlan_tag = rte_cpu_to_le_16(vlan_id);
+
+       if (on) {
+               ret = i40e_aq_add_vlan(hw, vsi->seid,
+                                      &vlan_data, 1, NULL);
+               if (ret != I40E_SUCCESS)
+                       PMD_DRV_LOG(ERR, "Failed to add vlan filter");
+       } else {
+               ret = i40e_aq_remove_vlan(hw, vsi->seid,
+                                         &vlan_data, 1, NULL);
+               if (ret != I40E_SUCCESS)
+                       PMD_DRV_LOG(ERR,
+                                   "Failed to remove vlan filter");
+       }
+}
+
 /**
  * Find all vlan options for specific mac addr,
  * return with actual vlan found.
@@ -5798,8 +6121,8 @@ i40e_find_all_vlan_for_mac(struct i40e_vsi *vsi,
                        for (k = 0; k < I40E_UINT32_BIT_SIZE; k++) {
                                if (vsi->vfta[j] & (1 << k)) {
                                        if (i > num - 1) {
-                                               PMD_DRV_LOG(ERR, "vlan number "
-                                                           "not match");
+                                               PMD_DRV_LOG(ERR,
+                                                       "vlan number doesn't match");
                                                return I40E_ERR_PARAM;
                                        }
                                        (void)rte_memcpy(&mv_f[i].macaddr,
@@ -5844,7 +6167,7 @@ i40e_find_all_mac_for_vlan(struct i40e_vsi *vsi,
 static int
 i40e_vsi_remove_all_macvlan_filter(struct i40e_vsi *vsi)
 {
-       int i, num;
+       int i, j, num;
        struct i40e_mac_filter *f;
        struct i40e_macvlan_filter *mv_f;
        int ret = I40E_SUCCESS;
@@ -5869,6 +6192,7 @@ i40e_vsi_remove_all_macvlan_filter(struct i40e_vsi *vsi)
                TAILQ_FOREACH(f, &vsi->mac_list, next) {
                        (void)rte_memcpy(&mv_f[i].macaddr,
                                &f->mac_info.mac_addr, ETH_ADDR_LEN);
+                       mv_f[i].filter_type = f->mac_info.filter_type;
                        mv_f[i].vlan_id = 0;
                        i++;
                }
@@ -5878,6 +6202,8 @@ i40e_vsi_remove_all_macvlan_filter(struct i40e_vsi *vsi)
                                        vsi->vlan_num, &f->mac_info.mac_addr);
                        if (ret != I40E_SUCCESS)
                                goto DONE;
+                       for (j = i; j < i + vsi->vlan_num; j++)
+                               mv_f[j].filter_type = f->mac_info.filter_type;
                        i += vsi->vlan_num;
                }
        }
@@ -6089,7 +6415,7 @@ i40e_vsi_delete_mac(struct i40e_vsi *vsi, struct ether_addr *addr)
        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\n");
+                       PMD_DRV_LOG(ERR, "VLAN number shouldn't be 0");
                        return I40E_ERR_PARAM;
                }
        } else if (filter_type == RTE_MAC_PERFECT_MATCH ||
@@ -6198,18 +6524,14 @@ i40e_parse_hena(uint64_t flags)
                rss_hf |= ETH_RSS_FRAG_IPV4;
        if (flags & (1ULL << I40E_FILTER_PCTYPE_NONF_IPV4_TCP))
                rss_hf |= ETH_RSS_NONFRAG_IPV4_TCP;
-#ifdef X722_SUPPORT
        if (flags & (1ULL << I40E_FILTER_PCTYPE_NONF_IPV4_TCP_SYN_NO_ACK))
                rss_hf |= ETH_RSS_NONFRAG_IPV4_TCP;
-#endif
        if (flags & (1ULL << I40E_FILTER_PCTYPE_NONF_IPV4_UDP))
                rss_hf |= ETH_RSS_NONFRAG_IPV4_UDP;
-#ifdef X722_SUPPORT
        if (flags & (1ULL << I40E_FILTER_PCTYPE_NONF_UNICAST_IPV4_UDP))
                rss_hf |= ETH_RSS_NONFRAG_IPV4_UDP;
        if (flags & (1ULL << I40E_FILTER_PCTYPE_NONF_MULTICAST_IPV4_UDP))
                rss_hf |= ETH_RSS_NONFRAG_IPV4_UDP;
-#endif
        if (flags & (1ULL << I40E_FILTER_PCTYPE_NONF_IPV4_SCTP))
                rss_hf |= ETH_RSS_NONFRAG_IPV4_SCTP;
        if (flags & (1ULL << I40E_FILTER_PCTYPE_NONF_IPV4_OTHER))
@@ -6218,18 +6540,14 @@ i40e_parse_hena(uint64_t flags)
                rss_hf |= ETH_RSS_FRAG_IPV6;
        if (flags & (1ULL << I40E_FILTER_PCTYPE_NONF_IPV6_TCP))
                rss_hf |= ETH_RSS_NONFRAG_IPV6_TCP;
-#ifdef X722_SUPPORT
        if (flags & (1ULL << I40E_FILTER_PCTYPE_NONF_IPV6_TCP_SYN_NO_ACK))
                rss_hf |= ETH_RSS_NONFRAG_IPV6_TCP;
-#endif
        if (flags & (1ULL << I40E_FILTER_PCTYPE_NONF_IPV6_UDP))
                rss_hf |= ETH_RSS_NONFRAG_IPV6_UDP;
-#ifdef X722_SUPPORT
        if (flags & (1ULL << I40E_FILTER_PCTYPE_NONF_UNICAST_IPV6_UDP))
                rss_hf |= ETH_RSS_NONFRAG_IPV6_UDP;
        if (flags & (1ULL << I40E_FILTER_PCTYPE_NONF_MULTICAST_IPV6_UDP))
                rss_hf |= ETH_RSS_NONFRAG_IPV6_UDP;
-#endif
        if (flags & (1ULL << I40E_FILTER_PCTYPE_NONF_IPV6_SCTP))
                rss_hf |= ETH_RSS_NONFRAG_IPV6_SCTP;
        if (flags & (1ULL << I40E_FILTER_PCTYPE_NONF_IPV6_OTHER))
@@ -6280,8 +6598,7 @@ i40e_set_rss_key(struct i40e_vsi *vsi, uint8_t *key, uint8_t key_len)
 
                ret = i40e_aq_set_rss_key(hw, vsi->vsi_id, key_dw);
                if (ret)
-                       PMD_INIT_LOG(ERR, "Failed to configure RSS key "
-                                    "via AQ");
+                       PMD_INIT_LOG(ERR, "Failed to configure RSS key via AQ");
        } else {
                uint32_t *hash_key = (uint32_t *)key;
                uint16_t i;
@@ -6427,7 +6744,95 @@ i40e_dev_get_filter_type(uint16_t filter_type, uint16_t *flag)
        return 0;
 }
 
+/* Convert tunnel filter structure */
+static int
+i40e_tunnel_filter_convert(
+       struct i40e_aqc_add_rm_cloud_filt_elem_ext *cld_filter,
+       struct i40e_tunnel_filter *tunnel_filter)
+{
+       ether_addr_copy((struct ether_addr *)&cld_filter->element.outer_mac,
+                       (struct ether_addr *)&tunnel_filter->input.outer_mac);
+       ether_addr_copy((struct ether_addr *)&cld_filter->element.inner_mac,
+                       (struct ether_addr *)&tunnel_filter->input.inner_mac);
+       tunnel_filter->input.inner_vlan = cld_filter->element.inner_vlan;
+       if ((rte_le_to_cpu_16(cld_filter->element.flags) &
+            I40E_AQC_ADD_CLOUD_FLAGS_IPV6) ==
+           I40E_AQC_ADD_CLOUD_FLAGS_IPV6)
+               tunnel_filter->input.ip_type = I40E_TUNNEL_IPTYPE_IPV6;
+       else
+               tunnel_filter->input.ip_type = I40E_TUNNEL_IPTYPE_IPV4;
+       tunnel_filter->input.flags = cld_filter->element.flags;
+       tunnel_filter->input.tenant_id = cld_filter->element.tenant_id;
+       tunnel_filter->queue = cld_filter->element.queue_number;
+       rte_memcpy(tunnel_filter->input.general_fields,
+                  cld_filter->general_fields,
+                  sizeof(cld_filter->general_fields));
+
+       return 0;
+}
+
+/* Check if there exists the tunnel filter */
+struct i40e_tunnel_filter *
+i40e_sw_tunnel_filter_lookup(struct i40e_tunnel_rule *tunnel_rule,
+                            const struct i40e_tunnel_filter_input *input)
+{
+       int ret;
+
+       ret = rte_hash_lookup(tunnel_rule->hash_table, (const void *)input);
+       if (ret < 0)
+               return NULL;
+
+       return tunnel_rule->hash_map[ret];
+}
+
+/* Add a tunnel filter into the SW list */
 static int
+i40e_sw_tunnel_filter_insert(struct i40e_pf *pf,
+                            struct i40e_tunnel_filter *tunnel_filter)
+{
+       struct i40e_tunnel_rule *rule = &pf->tunnel;
+       int ret;
+
+       ret = rte_hash_add_key(rule->hash_table, &tunnel_filter->input);
+       if (ret < 0) {
+               PMD_DRV_LOG(ERR,
+                           "Failed to insert tunnel filter to hash table %d!",
+                           ret);
+               return ret;
+       }
+       rule->hash_map[ret] = tunnel_filter;
+
+       TAILQ_INSERT_TAIL(&rule->tunnel_list, tunnel_filter, rules);
+
+       return 0;
+}
+
+/* Delete a tunnel filter from the SW list */
+int
+i40e_sw_tunnel_filter_del(struct i40e_pf *pf,
+                         struct i40e_tunnel_filter_input *input)
+{
+       struct i40e_tunnel_rule *rule = &pf->tunnel;
+       struct i40e_tunnel_filter *tunnel_filter;
+       int ret;
+
+       ret = rte_hash_del_key(rule->hash_table, input);
+       if (ret < 0) {
+               PMD_DRV_LOG(ERR,
+                           "Failed to delete tunnel filter to hash table %d!",
+                           ret);
+               return ret;
+       }
+       tunnel_filter = rule->hash_map[ret];
+       rule->hash_map[ret] = NULL;
+
+       TAILQ_REMOVE(&rule->tunnel_list, tunnel_filter, rules);
+       rte_free(tunnel_filter);
+
+       return 0;
+}
+
+int
 i40e_dev_tunnel_filter_set(struct i40e_pf *pf,
                        struct rte_eth_tunnel_filter_conf *tunnel_filter,
                        uint8_t add)
@@ -6440,37 +6845,44 @@ i40e_dev_tunnel_filter_set(struct i40e_pf *pf,
        int val, ret = 0;
        struct i40e_hw *hw = I40E_PF_TO_HW(pf);
        struct i40e_vsi *vsi = pf->main_vsi;
-       struct i40e_aqc_add_remove_cloud_filters_element_data  *cld_filter;
-       struct i40e_aqc_add_remove_cloud_filters_element_data  *pfilter;
+       struct i40e_aqc_add_rm_cloud_filt_elem_ext *cld_filter;
+       struct i40e_aqc_add_rm_cloud_filt_elem_ext *pfilter;
+       struct i40e_tunnel_rule *tunnel_rule = &pf->tunnel;
+       struct i40e_tunnel_filter *tunnel, *node;
+       struct i40e_tunnel_filter check_filter; /* Check if filter exists */
 
        cld_filter = rte_zmalloc("tunnel_filter",
-               sizeof(struct i40e_aqc_add_remove_cloud_filters_element_data),
-               0);
+                        sizeof(struct i40e_aqc_add_rm_cloud_filt_elem_ext),
+       0);
 
        if (NULL == cld_filter) {
                PMD_DRV_LOG(ERR, "Failed to alloc memory.");
-               return -EINVAL;
+               return -ENOMEM;
        }
        pfilter = cld_filter;
 
-       ether_addr_copy(&tunnel_filter->outer_mac, (struct ether_addr*)&pfilter->outer_mac);
-       ether_addr_copy(&tunnel_filter->inner_mac, (struct ether_addr*)&pfilter->inner_mac);
+       ether_addr_copy(&tunnel_filter->outer_mac,
+                       (struct ether_addr *)&pfilter->element.outer_mac);
+       ether_addr_copy(&tunnel_filter->inner_mac,
+                       (struct ether_addr *)&pfilter->element.inner_mac);
 
-       pfilter->inner_vlan = rte_cpu_to_le_16(tunnel_filter->inner_vlan);
+       pfilter->element.inner_vlan =
+               rte_cpu_to_le_16(tunnel_filter->inner_vlan);
        if (tunnel_filter->ip_type == RTE_TUNNEL_IPTYPE_IPV4) {
                ip_type = I40E_AQC_ADD_CLOUD_FLAGS_IPV4;
                ipv4_addr = rte_be_to_cpu_32(tunnel_filter->ip_addr.ipv4_addr);
-               rte_memcpy(&pfilter->ipaddr.v4.data,
+               rte_memcpy(&pfilter->element.ipaddr.v4.data,
                                &rte_cpu_to_le_32(ipv4_addr),
-                               sizeof(pfilter->ipaddr.v4.data));
+                               sizeof(pfilter->element.ipaddr.v4.data));
        } else {
                ip_type = I40E_AQC_ADD_CLOUD_FLAGS_IPV6;
                for (i = 0; i < 4; i++) {
                        convert_ipv6[i] =
                        rte_cpu_to_le_32(rte_be_to_cpu_32(tunnel_filter->ip_addr.ipv6_addr[i]));
                }
-               rte_memcpy(&pfilter->ipaddr.v6.data, &convert_ipv6,
-                               sizeof(pfilter->ipaddr.v6.data));
+               rte_memcpy(&pfilter->element.ipaddr.v6.data,
+                          &convert_ipv6,
+                          sizeof(pfilter->element.ipaddr.v6.data));
        }
 
        /* check tunneled type */
@@ -6492,23 +6904,369 @@ i40e_dev_tunnel_filter_set(struct i40e_pf *pf,
        }
 
        val = i40e_dev_get_filter_type(tunnel_filter->filter_type,
-                                               &pfilter->flags);
+                                      &pfilter->element.flags);
        if (val < 0) {
                rte_free(cld_filter);
                return -EINVAL;
        }
 
-       pfilter->flags |= rte_cpu_to_le_16(
+       pfilter->element.flags |= rte_cpu_to_le_16(
                I40E_AQC_ADD_CLOUD_FLAGS_TO_QUEUE |
                ip_type | (tun_type << I40E_AQC_ADD_CLOUD_TNL_TYPE_SHIFT));
-       pfilter->tenant_id = rte_cpu_to_le_32(tunnel_filter->tenant_id);
-       pfilter->queue_number = rte_cpu_to_le_16(tunnel_filter->queue_id);
+       pfilter->element.tenant_id = rte_cpu_to_le_32(tunnel_filter->tenant_id);
+       pfilter->element.queue_number =
+               rte_cpu_to_le_16(tunnel_filter->queue_id);
+
+       /* Check if there is the filter in SW list */
+       memset(&check_filter, 0, sizeof(check_filter));
+       i40e_tunnel_filter_convert(cld_filter, &check_filter);
+       node = i40e_sw_tunnel_filter_lookup(tunnel_rule, &check_filter.input);
+       if (add && node) {
+               PMD_DRV_LOG(ERR, "Conflict with existing tunnel rules!");
+               return -EINVAL;
+       }
 
-       if (add)
-               ret = i40e_aq_add_cloud_filters(hw, vsi->seid, cld_filter, 1);
-       else
-               ret = i40e_aq_remove_cloud_filters(hw, vsi->seid,
-                                               cld_filter, 1);
+       if (!add && !node) {
+               PMD_DRV_LOG(ERR, "There's no corresponding tunnel filter!");
+               return -EINVAL;
+       }
+
+       if (add) {
+               ret = i40e_aq_add_cloud_filters(hw,
+                                       vsi->seid, &cld_filter->element, 1);
+               if (ret < 0) {
+                       PMD_DRV_LOG(ERR, "Failed to add a tunnel filter.");
+                       return -ENOTSUP;
+               }
+               tunnel = rte_zmalloc("tunnel_filter", sizeof(*tunnel), 0);
+               rte_memcpy(tunnel, &check_filter, sizeof(check_filter));
+               ret = i40e_sw_tunnel_filter_insert(pf, tunnel);
+       } else {
+               ret = i40e_aq_remove_cloud_filters(hw, vsi->seid,
+                                                  &cld_filter->element, 1);
+               if (ret < 0) {
+                       PMD_DRV_LOG(ERR, "Failed to delete a tunnel filter.");
+                       return -ENOTSUP;
+               }
+               ret = i40e_sw_tunnel_filter_del(pf, &node->input);
+       }
+
+       rte_free(cld_filter);
+       return ret;
+}
+
+#define I40E_AQC_REPLACE_CLOUD_CMD_INPUT_TR_WORD0 0x48
+#define I40E_TR_VXLAN_GRE_KEY_MASK             0x4
+#define I40E_TR_GENEVE_KEY_MASK                        0x8
+#define I40E_TR_GENERIC_UDP_TUNNEL_MASK                0x40
+#define I40E_TR_GRE_KEY_MASK                   0x400
+#define I40E_TR_GRE_KEY_WITH_XSUM_MASK         0x800
+#define I40E_TR_GRE_NO_KEY_MASK                        0x8000
+
+static enum
+i40e_status_code i40e_replace_mpls_l1_filter(struct i40e_pf *pf)
+{
+       struct i40e_aqc_replace_cloud_filters_cmd  filter_replace;
+       struct i40e_aqc_replace_cloud_filters_cmd_buf  filter_replace_buf;
+       struct i40e_hw *hw = I40E_PF_TO_HW(pf);
+       enum i40e_status_code status = I40E_SUCCESS;
+
+       memset(&filter_replace, 0,
+              sizeof(struct i40e_aqc_replace_cloud_filters_cmd));
+       memset(&filter_replace_buf, 0,
+              sizeof(struct i40e_aqc_replace_cloud_filters_cmd_buf));
+
+       /* create L1 filter */
+       filter_replace.old_filter_type =
+               I40E_AQC_REPLACE_CLOUD_CMD_INPUT_FV_IMAC;
+       filter_replace.new_filter_type = I40E_AQC_ADD_L1_FILTER_TEID_MPLS;
+       filter_replace.tr_bit = 0;
+
+       /* Prepare the buffer, 3 entries */
+       filter_replace_buf.data[0] =
+               I40E_AQC_REPLACE_CLOUD_CMD_INPUT_FV_TEID_WORD0;
+       filter_replace_buf.data[0] |=
+               I40E_AQC_REPLACE_CLOUD_CMD_INPUT_VALIDATED;
+       filter_replace_buf.data[2] = 0xFF;
+       filter_replace_buf.data[3] = 0xFF;
+       filter_replace_buf.data[4] =
+               I40E_AQC_REPLACE_CLOUD_CMD_INPUT_FV_TEID_WORD1;
+       filter_replace_buf.data[4] |=
+               I40E_AQC_REPLACE_CLOUD_CMD_INPUT_VALIDATED;
+       filter_replace_buf.data[7] = 0xF0;
+       filter_replace_buf.data[8]
+               = I40E_AQC_REPLACE_CLOUD_CMD_INPUT_TR_WORD0;
+       filter_replace_buf.data[8] |=
+               I40E_AQC_REPLACE_CLOUD_CMD_INPUT_VALIDATED;
+       filter_replace_buf.data[10] = I40E_TR_VXLAN_GRE_KEY_MASK |
+               I40E_TR_GENEVE_KEY_MASK |
+               I40E_TR_GENERIC_UDP_TUNNEL_MASK;
+       filter_replace_buf.data[11] = (I40E_TR_GRE_KEY_MASK |
+               I40E_TR_GRE_KEY_WITH_XSUM_MASK |
+               I40E_TR_GRE_NO_KEY_MASK) >> 8;
+
+       status = i40e_aq_replace_cloud_filters(hw, &filter_replace,
+                                              &filter_replace_buf);
+       return status;
+}
+
+static enum
+i40e_status_code i40e_replace_mpls_cloud_filter(struct i40e_pf *pf)
+{
+       struct i40e_aqc_replace_cloud_filters_cmd  filter_replace;
+       struct i40e_aqc_replace_cloud_filters_cmd_buf  filter_replace_buf;
+       struct i40e_hw *hw = I40E_PF_TO_HW(pf);
+       enum i40e_status_code status = I40E_SUCCESS;
+
+       /* For MPLSoUDP */
+       memset(&filter_replace, 0,
+              sizeof(struct i40e_aqc_replace_cloud_filters_cmd));
+       memset(&filter_replace_buf, 0,
+              sizeof(struct i40e_aqc_replace_cloud_filters_cmd_buf));
+       filter_replace.valid_flags = I40E_AQC_REPLACE_CLOUD_FILTER |
+               I40E_AQC_MIRROR_CLOUD_FILTER;
+       filter_replace.old_filter_type = I40E_AQC_ADD_CLOUD_FILTER_IIP;
+       filter_replace.new_filter_type =
+               I40E_AQC_ADD_CLOUD_FILTER_TEID_MPLSoUDP;
+       /* Prepare the buffer, 2 entries */
+       filter_replace_buf.data[0] = I40E_AQC_REPLACE_CLOUD_CMD_INPUT_FV_STAG;
+       filter_replace_buf.data[0] |=
+               I40E_AQC_REPLACE_CLOUD_CMD_INPUT_VALIDATED;
+       filter_replace_buf.data[4] = I40E_AQC_ADD_L1_FILTER_TEID_MPLS;
+       filter_replace_buf.data[4] |=
+               I40E_AQC_REPLACE_CLOUD_CMD_INPUT_VALIDATED;
+       status = i40e_aq_replace_cloud_filters(hw, &filter_replace,
+                                              &filter_replace_buf);
+       if (status < 0)
+               return status;
+
+       /* For MPLSoGRE */
+       memset(&filter_replace, 0,
+              sizeof(struct i40e_aqc_replace_cloud_filters_cmd));
+       memset(&filter_replace_buf, 0,
+              sizeof(struct i40e_aqc_replace_cloud_filters_cmd_buf));
+
+       filter_replace.valid_flags = I40E_AQC_REPLACE_CLOUD_FILTER |
+               I40E_AQC_MIRROR_CLOUD_FILTER;
+       filter_replace.old_filter_type = I40E_AQC_ADD_CLOUD_FILTER_IMAC;
+       filter_replace.new_filter_type =
+               I40E_AQC_ADD_CLOUD_FILTER_TEID_MPLSoGRE;
+       /* Prepare the buffer, 2 entries */
+       filter_replace_buf.data[0] = I40E_AQC_REPLACE_CLOUD_CMD_INPUT_FV_STAG;
+       filter_replace_buf.data[0] |=
+               I40E_AQC_REPLACE_CLOUD_CMD_INPUT_VALIDATED;
+       filter_replace_buf.data[4] = I40E_AQC_ADD_L1_FILTER_TEID_MPLS;
+       filter_replace_buf.data[4] |=
+               I40E_AQC_REPLACE_CLOUD_CMD_INPUT_VALIDATED;
+
+       status = i40e_aq_replace_cloud_filters(hw, &filter_replace,
+                                              &filter_replace_buf);
+       return status;
+}
+
+int
+i40e_dev_consistent_tunnel_filter_set(struct i40e_pf *pf,
+                     struct i40e_tunnel_filter_conf *tunnel_filter,
+                     uint8_t add)
+{
+       uint16_t ip_type;
+       uint32_t ipv4_addr;
+       uint8_t i, tun_type = 0;
+       /* internal variable to convert ipv6 byte order */
+       uint32_t convert_ipv6[4];
+       int val, ret = 0;
+       struct i40e_pf_vf *vf = NULL;
+       struct i40e_hw *hw = I40E_PF_TO_HW(pf);
+       struct i40e_vsi *vsi;
+       struct i40e_aqc_add_rm_cloud_filt_elem_ext *cld_filter;
+       struct i40e_aqc_add_rm_cloud_filt_elem_ext *pfilter;
+       struct i40e_tunnel_rule *tunnel_rule = &pf->tunnel;
+       struct i40e_tunnel_filter *tunnel, *node;
+       struct i40e_tunnel_filter check_filter; /* Check if filter exists */
+       uint32_t teid_le;
+       bool big_buffer = 0;
+
+       cld_filter = rte_zmalloc("tunnel_filter",
+                        sizeof(struct i40e_aqc_add_rm_cloud_filt_elem_ext),
+                        0);
+
+       if (cld_filter == NULL) {
+               PMD_DRV_LOG(ERR, "Failed to alloc memory.");
+               return -ENOMEM;
+       }
+       pfilter = cld_filter;
+
+       ether_addr_copy(&tunnel_filter->outer_mac,
+                       (struct ether_addr *)&pfilter->element.outer_mac);
+       ether_addr_copy(&tunnel_filter->inner_mac,
+                       (struct ether_addr *)&pfilter->element.inner_mac);
+
+       pfilter->element.inner_vlan =
+               rte_cpu_to_le_16(tunnel_filter->inner_vlan);
+       if (tunnel_filter->ip_type == I40E_TUNNEL_IPTYPE_IPV4) {
+               ip_type = I40E_AQC_ADD_CLOUD_FLAGS_IPV4;
+               ipv4_addr = rte_be_to_cpu_32(tunnel_filter->ip_addr.ipv4_addr);
+               rte_memcpy(&pfilter->element.ipaddr.v4.data,
+                               &rte_cpu_to_le_32(ipv4_addr),
+                               sizeof(pfilter->element.ipaddr.v4.data));
+       } else {
+               ip_type = I40E_AQC_ADD_CLOUD_FLAGS_IPV6;
+               for (i = 0; i < 4; i++) {
+                       convert_ipv6[i] =
+                       rte_cpu_to_le_32(rte_be_to_cpu_32(
+                                        tunnel_filter->ip_addr.ipv6_addr[i]));
+               }
+               rte_memcpy(&pfilter->element.ipaddr.v6.data,
+                          &convert_ipv6,
+                          sizeof(pfilter->element.ipaddr.v6.data));
+       }
+
+       /* check tunneled type */
+       switch (tunnel_filter->tunnel_type) {
+       case I40E_TUNNEL_TYPE_VXLAN:
+               tun_type = I40E_AQC_ADD_CLOUD_TNL_TYPE_VXLAN;
+               break;
+       case I40E_TUNNEL_TYPE_NVGRE:
+               tun_type = I40E_AQC_ADD_CLOUD_TNL_TYPE_NVGRE_OMAC;
+               break;
+       case I40E_TUNNEL_TYPE_IP_IN_GRE:
+               tun_type = I40E_AQC_ADD_CLOUD_TNL_TYPE_IP;
+               break;
+       case I40E_TUNNEL_TYPE_MPLSoUDP:
+               if (!pf->mpls_replace_flag) {
+                       i40e_replace_mpls_l1_filter(pf);
+                       i40e_replace_mpls_cloud_filter(pf);
+                       pf->mpls_replace_flag = 1;
+               }
+               teid_le = rte_cpu_to_le_32(tunnel_filter->tenant_id);
+               pfilter->general_fields[I40E_AQC_ADD_CLOUD_FV_FLU_0X11_WORD0] =
+                       teid_le >> 4;
+               pfilter->general_fields[I40E_AQC_ADD_CLOUD_FV_FLU_0X11_WORD1] =
+                       (teid_le & 0xF) << 12;
+               pfilter->general_fields[I40E_AQC_ADD_CLOUD_FV_FLU_0X11_WORD2] =
+                       0x40;
+               big_buffer = 1;
+               tun_type = I40E_AQC_ADD_CLOUD_TNL_TYPE_MPLSoUDP;
+               break;
+       case I40E_TUNNEL_TYPE_MPLSoGRE:
+               if (!pf->mpls_replace_flag) {
+                       i40e_replace_mpls_l1_filter(pf);
+                       i40e_replace_mpls_cloud_filter(pf);
+                       pf->mpls_replace_flag = 1;
+               }
+               teid_le = rte_cpu_to_le_32(tunnel_filter->tenant_id);
+               pfilter->general_fields[I40E_AQC_ADD_CLOUD_FV_FLU_0X11_WORD0] =
+                       teid_le >> 4;
+               pfilter->general_fields[I40E_AQC_ADD_CLOUD_FV_FLU_0X11_WORD1] =
+                       (teid_le & 0xF) << 12;
+               pfilter->general_fields[I40E_AQC_ADD_CLOUD_FV_FLU_0X11_WORD2] =
+                       0x0;
+               big_buffer = 1;
+               tun_type = I40E_AQC_ADD_CLOUD_TNL_TYPE_MPLSoGRE;
+               break;
+       case I40E_TUNNEL_TYPE_QINQ:
+               if (!pf->qinq_replace_flag) {
+                       ret = i40e_cloud_filter_qinq_create(pf);
+                       if (ret < 0)
+                               PMD_DRV_LOG(ERR,
+                                       "Failed to create a qinq tunnel filter.");
+                       pf->qinq_replace_flag = 1;
+               }
+               /*      Add in the General fields the values of
+                *      the Outer and Inner VLAN
+                *      Big Buffer should be set, see changes in
+                *      i40e_aq_add_cloud_filters
+                */
+               pfilter->general_fields[0] = tunnel_filter->inner_vlan;
+               pfilter->general_fields[1] = tunnel_filter->outer_vlan;
+               big_buffer = 1;
+               break;
+       default:
+               /* Other tunnel types is not supported. */
+               PMD_DRV_LOG(ERR, "tunnel type is not supported.");
+               rte_free(cld_filter);
+               return -EINVAL;
+       }
+
+       if (tunnel_filter->tunnel_type == I40E_TUNNEL_TYPE_MPLSoUDP)
+               pfilter->element.flags =
+                       I40E_AQC_ADD_CLOUD_FILTER_TEID_MPLSoUDP;
+       else if (tunnel_filter->tunnel_type == I40E_TUNNEL_TYPE_MPLSoGRE)
+               pfilter->element.flags =
+                       I40E_AQC_ADD_CLOUD_FILTER_TEID_MPLSoGRE;
+       else if (tunnel_filter->tunnel_type == I40E_TUNNEL_TYPE_QINQ)
+               pfilter->element.flags |=
+                       I40E_AQC_ADD_CLOUD_FILTER_CUSTOM_QINQ;
+       else {
+               val = i40e_dev_get_filter_type(tunnel_filter->filter_type,
+                                               &pfilter->element.flags);
+               if (val < 0) {
+                       rte_free(cld_filter);
+                       return -EINVAL;
+               }
+       }
+
+       pfilter->element.flags |= rte_cpu_to_le_16(
+               I40E_AQC_ADD_CLOUD_FLAGS_TO_QUEUE |
+               ip_type | (tun_type << I40E_AQC_ADD_CLOUD_TNL_TYPE_SHIFT));
+       pfilter->element.tenant_id = rte_cpu_to_le_32(tunnel_filter->tenant_id);
+       pfilter->element.queue_number =
+               rte_cpu_to_le_16(tunnel_filter->queue_id);
+
+       if (!tunnel_filter->is_to_vf)
+               vsi = pf->main_vsi;
+       else {
+               if (tunnel_filter->vf_id >= pf->vf_num) {
+                       PMD_DRV_LOG(ERR, "Invalid argument.");
+                       return -EINVAL;
+               }
+               vf = &pf->vfs[tunnel_filter->vf_id];
+               vsi = vf->vsi;
+       }
+
+       /* Check if there is the filter in SW list */
+       memset(&check_filter, 0, sizeof(check_filter));
+       i40e_tunnel_filter_convert(cld_filter, &check_filter);
+       check_filter.is_to_vf = tunnel_filter->is_to_vf;
+       check_filter.vf_id = tunnel_filter->vf_id;
+       node = i40e_sw_tunnel_filter_lookup(tunnel_rule, &check_filter.input);
+       if (add && node) {
+               PMD_DRV_LOG(ERR, "Conflict with existing tunnel rules!");
+               return -EINVAL;
+       }
+
+       if (!add && !node) {
+               PMD_DRV_LOG(ERR, "There's no corresponding tunnel filter!");
+               return -EINVAL;
+       }
+
+       if (add) {
+               if (big_buffer)
+                       ret = i40e_aq_add_cloud_filters_big_buffer(hw,
+                                                  vsi->seid, cld_filter, 1);
+               else
+                       ret = i40e_aq_add_cloud_filters(hw,
+                                       vsi->seid, &cld_filter->element, 1);
+               if (ret < 0) {
+                       PMD_DRV_LOG(ERR, "Failed to add a tunnel filter.");
+                       return -ENOTSUP;
+               }
+               tunnel = rte_zmalloc("tunnel_filter", sizeof(*tunnel), 0);
+               rte_memcpy(tunnel, &check_filter, sizeof(check_filter));
+               ret = i40e_sw_tunnel_filter_insert(pf, tunnel);
+       } else {
+               if (big_buffer)
+                       ret = i40e_aq_remove_cloud_filters_big_buffer(
+                               hw, vsi->seid, cld_filter, 1);
+               else
+                       ret = i40e_aq_remove_cloud_filters(hw, vsi->seid,
+                                                  &cld_filter->element, 1);
+               if (ret < 0) {
+                       PMD_DRV_LOG(ERR, "Failed to delete a tunnel filter.");
+                       return -ENOTSUP;
+               }
+               ret = i40e_sw_tunnel_filter_del(pf, &node->input);
+       }
 
        rte_free(cld_filter);
        return ret;
@@ -6545,8 +7303,9 @@ i40e_add_vxlan_port(struct i40e_pf *pf, uint16_t port)
        /* Now check if there is space to add the new port */
        idx = i40e_get_vxlan_port_idx(pf, 0);
        if (idx < 0) {
-               PMD_DRV_LOG(ERR, "Maximum number of UDP ports reached,"
-                       "not adding port %d", port);
+               PMD_DRV_LOG(ERR,
+                       "Maximum number of UDP ports reached, not adding port %d",
+                       port);
                return -ENOSPC;
        }
 
@@ -6785,7 +7544,7 @@ i40e_dev_set_gre_key_len(struct i40e_hw *hw, uint8_t len)
        int ret = -EINVAL;
 
        val = I40E_READ_REG(hw, I40E_GL_PRS_FVBM(2));
-       PMD_DRV_LOG(DEBUG, "Read original GL_PRS_FVBM with 0x%08x\n", val);
+       PMD_DRV_LOG(DEBUG, "Read original GL_PRS_FVBM with 0x%08x", val);
 
        if (len == 3) {
                reg = val | I40E_GL_PRS_FVBM_MSK_ENA;
@@ -6804,7 +7563,7 @@ i40e_dev_set_gre_key_len(struct i40e_hw *hw, uint8_t len)
        } else {
                ret = 0;
        }
-       PMD_DRV_LOG(DEBUG, "Read modified GL_PRS_FVBM with 0x%08x\n",
+       PMD_DRV_LOG(DEBUG, "Read modified GL_PRS_FVBM with 0x%08x",
                    I40E_READ_REG(hw, I40E_GL_PRS_FVBM(2)));
 
        return ret;
@@ -6917,15 +7676,15 @@ i40e_set_symmetric_hash_enable_per_port(struct i40e_hw *hw, uint8_t enable)
 
        if (enable > 0) {
                if (reg & I40E_PRTQF_CTL_0_HSYM_ENA_MASK) {
-                       PMD_DRV_LOG(INFO, "Symmetric hash has already "
-                                                       "been enabled");
+                       PMD_DRV_LOG(INFO,
+                               "Symmetric hash has already been enabled");
                        return;
                }
                reg |= I40E_PRTQF_CTL_0_HSYM_ENA_MASK;
        } else {
                if (!(reg & I40E_PRTQF_CTL_0_HSYM_ENA_MASK)) {
-                       PMD_DRV_LOG(INFO, "Symmetric hash has already "
-                                                       "been disabled");
+                       PMD_DRV_LOG(INFO,
+                               "Symmetric hash has already been disabled");
                        return;
                }
                reg &= ~I40E_PRTQF_CTL_0_HSYM_ENA_MASK;
@@ -7049,16 +7808,16 @@ i40e_set_hash_filter_global_config(struct i40e_hw *hw,
        if (g_cfg->hash_func == RTE_ETH_HASH_FUNCTION_TOEPLITZ) {
                /* Toeplitz */
                if (reg & I40E_GLQF_CTL_HTOEP_MASK) {
-                       PMD_DRV_LOG(DEBUG, "Hash function already set to "
-                                                               "Toeplitz");
+                       PMD_DRV_LOG(DEBUG,
+                               "Hash function already set to Toeplitz");
                        goto out;
                }
                reg |= I40E_GLQF_CTL_HTOEP_MASK;
        } else if (g_cfg->hash_func == RTE_ETH_HASH_FUNCTION_SIMPLE_XOR) {
                /* Simple XOR */
                if (!(reg & I40E_GLQF_CTL_HTOEP_MASK)) {
-                       PMD_DRV_LOG(DEBUG, "Hash function already set to "
-                                                       "Simple XOR");
+                       PMD_DRV_LOG(DEBUG,
+                               "Hash function already set to Simple XOR");
                        goto out;
                }
                reg &= ~I40E_GLQF_CTL_HTOEP_MASK;
@@ -7101,7 +7860,6 @@ i40e_get_valid_input_set(enum i40e_filter_pctype pctype,
                        I40E_INSET_IPV4_SRC | I40E_INSET_IPV4_DST |
                        I40E_INSET_SRC_PORT | I40E_INSET_DST_PORT |
                        I40E_INSET_FLEX_PAYLOAD,
-#ifdef X722_SUPPORT
                [I40E_FILTER_PCTYPE_NONF_UNICAST_IPV4_UDP] =
                        I40E_INSET_DMAC | I40E_INSET_SMAC |
                        I40E_INSET_VLAN_OUTER | I40E_INSET_VLAN_INNER |
@@ -7120,7 +7878,6 @@ i40e_get_valid_input_set(enum i40e_filter_pctype pctype,
                        I40E_INSET_IPV4_SRC | I40E_INSET_IPV4_DST |
                        I40E_INSET_SRC_PORT | I40E_INSET_DST_PORT |
                        I40E_INSET_FLEX_PAYLOAD,
-#endif
                [I40E_FILTER_PCTYPE_NONF_IPV4_TCP] =
                        I40E_INSET_DMAC | I40E_INSET_SMAC |
                        I40E_INSET_VLAN_OUTER | I40E_INSET_VLAN_INNER |
@@ -7130,7 +7887,6 @@ i40e_get_valid_input_set(enum i40e_filter_pctype pctype,
                        I40E_INSET_IPV4_SRC | I40E_INSET_IPV4_DST |
                        I40E_INSET_SRC_PORT | I40E_INSET_DST_PORT |
                        I40E_INSET_TCP_FLAGS | I40E_INSET_FLEX_PAYLOAD,
-#ifdef X722_SUPPORT
                [I40E_FILTER_PCTYPE_NONF_IPV4_TCP_SYN_NO_ACK] =
                        I40E_INSET_DMAC | I40E_INSET_SMAC |
                        I40E_INSET_VLAN_OUTER | I40E_INSET_VLAN_INNER |
@@ -7140,7 +7896,6 @@ i40e_get_valid_input_set(enum i40e_filter_pctype pctype,
                        I40E_INSET_IPV4_SRC | I40E_INSET_IPV4_DST |
                        I40E_INSET_SRC_PORT | I40E_INSET_DST_PORT |
                        I40E_INSET_TCP_FLAGS | I40E_INSET_FLEX_PAYLOAD,
-#endif
                [I40E_FILTER_PCTYPE_NONF_IPV4_SCTP] =
                        I40E_INSET_DMAC | I40E_INSET_SMAC |
                        I40E_INSET_VLAN_OUTER | I40E_INSET_VLAN_INNER |
@@ -7174,7 +7929,6 @@ i40e_get_valid_input_set(enum i40e_filter_pctype pctype,
                        I40E_INSET_IPV6_HOP_LIMIT | I40E_INSET_IPV6_SRC |
                        I40E_INSET_IPV6_DST | I40E_INSET_SRC_PORT |
                        I40E_INSET_DST_PORT | I40E_INSET_FLEX_PAYLOAD,
-#ifdef X722_SUPPORT
                [I40E_FILTER_PCTYPE_NONF_UNICAST_IPV6_UDP] =
                        I40E_INSET_DMAC | I40E_INSET_SMAC |
                        I40E_INSET_VLAN_OUTER | I40E_INSET_VLAN_INNER |
@@ -7193,7 +7947,6 @@ i40e_get_valid_input_set(enum i40e_filter_pctype pctype,
                        I40E_INSET_IPV6_DST | I40E_INSET_SRC_PORT |
                        I40E_INSET_DST_PORT | I40E_INSET_TCP_FLAGS |
                        I40E_INSET_FLEX_PAYLOAD,
-#endif
                [I40E_FILTER_PCTYPE_NONF_IPV6_TCP] =
                        I40E_INSET_DMAC | I40E_INSET_SMAC |
                        I40E_INSET_VLAN_OUTER | I40E_INSET_VLAN_INNER |
@@ -7203,7 +7956,6 @@ i40e_get_valid_input_set(enum i40e_filter_pctype pctype,
                        I40E_INSET_IPV6_DST | I40E_INSET_SRC_PORT |
                        I40E_INSET_DST_PORT | I40E_INSET_TCP_FLAGS |
                        I40E_INSET_FLEX_PAYLOAD,
-#ifdef X722_SUPPORT
                [I40E_FILTER_PCTYPE_NONF_IPV6_TCP_SYN_NO_ACK] =
                        I40E_INSET_DMAC | I40E_INSET_SMAC |
                        I40E_INSET_VLAN_OUTER | I40E_INSET_VLAN_INNER |
@@ -7213,7 +7965,6 @@ i40e_get_valid_input_set(enum i40e_filter_pctype pctype,
                        I40E_INSET_IPV6_DST | I40E_INSET_SRC_PORT |
                        I40E_INSET_DST_PORT | I40E_INSET_TCP_FLAGS |
                        I40E_INSET_FLEX_PAYLOAD,
-#endif
                [I40E_FILTER_PCTYPE_NONF_IPV6_SCTP] =
                        I40E_INSET_DMAC | I40E_INSET_SMAC |
                        I40E_INSET_VLAN_OUTER | I40E_INSET_VLAN_INNER |
@@ -7253,7 +8004,6 @@ i40e_get_valid_input_set(enum i40e_filter_pctype pctype,
                I40E_INSET_IPV4_SRC | I40E_INSET_IPV4_DST |
                I40E_INSET_IPV4_TOS | I40E_INSET_IPV4_TTL |
                I40E_INSET_SRC_PORT | I40E_INSET_DST_PORT,
-#ifdef X722_SUPPORT
                [I40E_FILTER_PCTYPE_NONF_UNICAST_IPV4_UDP] =
                I40E_INSET_VLAN_OUTER | I40E_INSET_VLAN_INNER |
                I40E_INSET_IPV4_SRC | I40E_INSET_IPV4_DST |
@@ -7264,19 +8014,16 @@ i40e_get_valid_input_set(enum i40e_filter_pctype pctype,
                I40E_INSET_IPV4_SRC | I40E_INSET_IPV4_DST |
                I40E_INSET_IPV4_TOS | I40E_INSET_IPV4_TTL |
                I40E_INSET_SRC_PORT | I40E_INSET_DST_PORT,
-#endif
                [I40E_FILTER_PCTYPE_NONF_IPV4_TCP] =
                I40E_INSET_VLAN_OUTER | I40E_INSET_VLAN_INNER |
                I40E_INSET_IPV4_SRC | I40E_INSET_IPV4_DST |
                I40E_INSET_IPV4_TOS | I40E_INSET_IPV4_TTL |
                I40E_INSET_SRC_PORT | I40E_INSET_DST_PORT,
-#ifdef X722_SUPPORT
                [I40E_FILTER_PCTYPE_NONF_IPV4_TCP_SYN_NO_ACK] =
                I40E_INSET_VLAN_OUTER | I40E_INSET_VLAN_INNER |
                I40E_INSET_IPV4_SRC | I40E_INSET_IPV4_DST |
                I40E_INSET_IPV4_TOS | I40E_INSET_IPV4_TTL |
                I40E_INSET_SRC_PORT | I40E_INSET_DST_PORT,
-#endif
                [I40E_FILTER_PCTYPE_NONF_IPV4_SCTP] =
                I40E_INSET_VLAN_OUTER | I40E_INSET_VLAN_INNER |
                I40E_INSET_IPV4_SRC | I40E_INSET_IPV4_DST |
@@ -7298,7 +8045,6 @@ i40e_get_valid_input_set(enum i40e_filter_pctype pctype,
                I40E_INSET_IPV6_SRC | I40E_INSET_IPV6_DST |
                I40E_INSET_IPV6_TC | I40E_INSET_IPV6_HOP_LIMIT |
                I40E_INSET_SRC_PORT | I40E_INSET_DST_PORT,
-#ifdef X722_SUPPORT
                [I40E_FILTER_PCTYPE_NONF_UNICAST_IPV6_UDP] =
                I40E_INSET_VLAN_OUTER | I40E_INSET_VLAN_INNER |
                I40E_INSET_IPV6_SRC | I40E_INSET_IPV6_DST |
@@ -7309,19 +8055,16 @@ i40e_get_valid_input_set(enum i40e_filter_pctype pctype,
                I40E_INSET_IPV6_SRC | I40E_INSET_IPV6_DST |
                I40E_INSET_IPV6_TC | I40E_INSET_IPV6_HOP_LIMIT |
                I40E_INSET_SRC_PORT | I40E_INSET_DST_PORT,
-#endif
                [I40E_FILTER_PCTYPE_NONF_IPV6_TCP] =
                I40E_INSET_VLAN_OUTER | I40E_INSET_VLAN_INNER |
                I40E_INSET_IPV6_SRC | I40E_INSET_IPV6_DST |
                I40E_INSET_IPV6_TC | I40E_INSET_IPV6_HOP_LIMIT |
                I40E_INSET_SRC_PORT | I40E_INSET_DST_PORT,
-#ifdef X722_SUPPORT
                [I40E_FILTER_PCTYPE_NONF_IPV6_TCP_SYN_NO_ACK] =
                I40E_INSET_VLAN_OUTER | I40E_INSET_VLAN_INNER |
                I40E_INSET_IPV6_SRC | I40E_INSET_IPV6_DST |
                I40E_INSET_IPV6_TC | I40E_INSET_IPV6_HOP_LIMIT |
                I40E_INSET_SRC_PORT | I40E_INSET_DST_PORT,
-#endif
                [I40E_FILTER_PCTYPE_NONF_IPV6_SCTP] =
                I40E_INSET_VLAN_OUTER | I40E_INSET_VLAN_INNER |
                I40E_INSET_IPV6_SRC | I40E_INSET_IPV6_DST |
@@ -7365,7 +8108,7 @@ i40e_validate_input_set(enum i40e_filter_pctype pctype,
 }
 
 /* default input set fields combination per pctype */
-static uint64_t
+uint64_t
 i40e_get_default_input_set(uint16_t pctype)
 {
        static const uint64_t default_inset_table[] = {
@@ -7374,22 +8117,18 @@ i40e_get_default_input_set(uint16_t pctype)
                [I40E_FILTER_PCTYPE_NONF_IPV4_UDP] =
                        I40E_INSET_IPV4_SRC | I40E_INSET_IPV4_DST |
                        I40E_INSET_SRC_PORT | I40E_INSET_DST_PORT,
-#ifdef X722_SUPPORT
                [I40E_FILTER_PCTYPE_NONF_UNICAST_IPV4_UDP] =
                        I40E_INSET_IPV4_SRC | I40E_INSET_IPV4_DST |
                        I40E_INSET_SRC_PORT | I40E_INSET_DST_PORT,
                [I40E_FILTER_PCTYPE_NONF_MULTICAST_IPV4_UDP] =
                        I40E_INSET_IPV4_SRC | I40E_INSET_IPV4_DST |
                        I40E_INSET_SRC_PORT | I40E_INSET_DST_PORT,
-#endif
                [I40E_FILTER_PCTYPE_NONF_IPV4_TCP] =
                        I40E_INSET_IPV4_SRC | I40E_INSET_IPV4_DST |
                        I40E_INSET_SRC_PORT | I40E_INSET_DST_PORT,
-#ifdef X722_SUPPORT
                [I40E_FILTER_PCTYPE_NONF_IPV4_TCP_SYN_NO_ACK] =
                        I40E_INSET_IPV4_SRC | I40E_INSET_IPV4_DST |
                        I40E_INSET_SRC_PORT | I40E_INSET_DST_PORT,
-#endif
                [I40E_FILTER_PCTYPE_NONF_IPV4_SCTP] =
                        I40E_INSET_IPV4_SRC | I40E_INSET_IPV4_DST |
                        I40E_INSET_SRC_PORT | I40E_INSET_DST_PORT |
@@ -7401,22 +8140,18 @@ i40e_get_default_input_set(uint16_t pctype)
                [I40E_FILTER_PCTYPE_NONF_IPV6_UDP] =
                        I40E_INSET_IPV6_SRC | I40E_INSET_IPV6_DST |
                        I40E_INSET_SRC_PORT | I40E_INSET_DST_PORT,
-#ifdef X722_SUPPORT
                [I40E_FILTER_PCTYPE_NONF_UNICAST_IPV6_UDP] =
                        I40E_INSET_IPV6_SRC | I40E_INSET_IPV6_DST |
                        I40E_INSET_SRC_PORT | I40E_INSET_DST_PORT,
                [I40E_FILTER_PCTYPE_NONF_MULTICAST_IPV6_UDP] =
                        I40E_INSET_IPV6_SRC | I40E_INSET_IPV6_DST |
                        I40E_INSET_SRC_PORT | I40E_INSET_DST_PORT,
-#endif
                [I40E_FILTER_PCTYPE_NONF_IPV6_TCP] =
                        I40E_INSET_IPV6_SRC | I40E_INSET_IPV6_DST |
                        I40E_INSET_SRC_PORT | I40E_INSET_DST_PORT,
-#ifdef X722_SUPPORT
                [I40E_FILTER_PCTYPE_NONF_IPV6_TCP_SYN_NO_ACK] =
                        I40E_INSET_IPV6_SRC | I40E_INSET_IPV6_DST |
                        I40E_INSET_SRC_PORT | I40E_INSET_DST_PORT,
-#endif
                [I40E_FILTER_PCTYPE_NONF_IPV6_SCTP] =
                        I40E_INSET_IPV6_SRC | I40E_INSET_IPV6_DST |
                        I40E_INSET_SRC_PORT | I40E_INSET_DST_PORT |
@@ -7672,10 +8407,10 @@ i40e_check_write_reg(struct i40e_hw *hw, uint32_t addr, uint32_t val)
 {
        uint32_t reg = i40e_read_rx_ctl(hw, addr);
 
-       PMD_DRV_LOG(DEBUG, "[0x%08x] original: 0x%08x\n", addr, reg);
+       PMD_DRV_LOG(DEBUG, "[0x%08x] original: 0x%08x", addr, reg);
        if (reg != val)
                i40e_write_rx_ctl(hw, addr, val);
-       PMD_DRV_LOG(DEBUG, "[0x%08x] after: 0x%08x\n", addr,
+       PMD_DRV_LOG(DEBUG, "[0x%08x] after: 0x%08x", addr,
                    (uint32_t)i40e_read_rx_ctl(hw, addr));
 }
 
@@ -7986,16 +8721,95 @@ i40e_hash_filter_ctrl(struct rte_eth_dev *dev,
        return ret;
 }
 
+/* Convert ethertype filter structure */
+static int
+i40e_ethertype_filter_convert(const struct rte_eth_ethertype_filter *input,
+                             struct i40e_ethertype_filter *filter)
+{
+       rte_memcpy(&filter->input.mac_addr, &input->mac_addr, ETHER_ADDR_LEN);
+       filter->input.ether_type = input->ether_type;
+       filter->flags = input->flags;
+       filter->queue = input->queue;
+
+       return 0;
+}
+
+/* Check if there exists the ehtertype filter */
+struct i40e_ethertype_filter *
+i40e_sw_ethertype_filter_lookup(struct i40e_ethertype_rule *ethertype_rule,
+                               const struct i40e_ethertype_filter_input *input)
+{
+       int ret;
+
+       ret = rte_hash_lookup(ethertype_rule->hash_table, (const void *)input);
+       if (ret < 0)
+               return NULL;
+
+       return ethertype_rule->hash_map[ret];
+}
+
+/* Add ethertype filter in SW list */
+static int
+i40e_sw_ethertype_filter_insert(struct i40e_pf *pf,
+                               struct i40e_ethertype_filter *filter)
+{
+       struct i40e_ethertype_rule *rule = &pf->ethertype;
+       int ret;
+
+       ret = rte_hash_add_key(rule->hash_table, &filter->input);
+       if (ret < 0) {
+               PMD_DRV_LOG(ERR,
+                           "Failed to insert ethertype filter"
+                           " to hash table %d!",
+                           ret);
+               return ret;
+       }
+       rule->hash_map[ret] = filter;
+
+       TAILQ_INSERT_TAIL(&rule->ethertype_list, filter, rules);
+
+       return 0;
+}
+
+/* Delete ethertype filter in SW list */
+int
+i40e_sw_ethertype_filter_del(struct i40e_pf *pf,
+                            struct i40e_ethertype_filter_input *input)
+{
+       struct i40e_ethertype_rule *rule = &pf->ethertype;
+       struct i40e_ethertype_filter *filter;
+       int ret;
+
+       ret = rte_hash_del_key(rule->hash_table, input);
+       if (ret < 0) {
+               PMD_DRV_LOG(ERR,
+                           "Failed to delete ethertype filter"
+                           " to hash table %d!",
+                           ret);
+               return ret;
+       }
+       filter = rule->hash_map[ret];
+       rule->hash_map[ret] = NULL;
+
+       TAILQ_REMOVE(&rule->ethertype_list, filter, rules);
+       rte_free(filter);
+
+       return 0;
+}
+
 /*
  * Configure ethertype filter, which can director packet by filtering
  * with mac address and ether_type or only ether_type
  */
-static int
+int
 i40e_ethertype_filter_set(struct i40e_pf *pf,
                        struct rte_eth_ethertype_filter *filter,
                        bool add)
 {
        struct i40e_hw *hw = I40E_PF_TO_HW(pf);
+       struct i40e_ethertype_rule *ethertype_rule = &pf->ethertype;
+       struct i40e_ethertype_filter *ethertype_filter, *node;
+       struct i40e_ethertype_filter check_filter;
        struct i40e_control_filter_stats stats;
        uint16_t flags = 0;
        int ret;
@@ -8006,13 +8820,29 @@ i40e_ethertype_filter_set(struct i40e_pf *pf,
        }
        if (filter->ether_type == ETHER_TYPE_IPv4 ||
                filter->ether_type == ETHER_TYPE_IPv6) {
-               PMD_DRV_LOG(ERR, "unsupported ether_type(0x%04x) in"
-                       " control packet filter.", filter->ether_type);
+               PMD_DRV_LOG(ERR,
+                       "unsupported ether_type(0x%04x) in control packet filter.",
+                       filter->ether_type);
                return -EINVAL;
        }
        if (filter->ether_type == ETHER_TYPE_VLAN)
-               PMD_DRV_LOG(WARNING, "filter vlan ether_type in first tag is"
-                       " not supported.");
+               PMD_DRV_LOG(WARNING,
+                       "filter vlan ether_type in first tag is not supported.");
+
+       /* Check if there is the filter in SW list */
+       memset(&check_filter, 0, sizeof(check_filter));
+       i40e_ethertype_filter_convert(filter, &check_filter);
+       node = i40e_sw_ethertype_filter_lookup(ethertype_rule,
+                                              &check_filter.input);
+       if (add && node) {
+               PMD_DRV_LOG(ERR, "Conflict with existing ethertype rules!");
+               return -EINVAL;
+       }
+
+       if (!add && !node) {
+               PMD_DRV_LOG(ERR, "There's no corresponding ethertype filter!");
+               return -EINVAL;
+       }
 
        if (!(filter->flags & RTE_ETHTYPE_FLAGS_MAC))
                flags |= I40E_AQC_ADD_CONTROL_PACKET_FLAGS_IGNORE_MAC;
@@ -8027,14 +8857,25 @@ i40e_ethertype_filter_set(struct i40e_pf *pf,
                        pf->main_vsi->seid,
                        filter->queue, add, &stats, NULL);
 
-       PMD_DRV_LOG(INFO, "add/rem control packet filter, return %d,"
-                        " mac_etype_used = %u, etype_used = %u,"
-                        " mac_etype_free = %u, etype_free = %u\n",
-                        ret, stats.mac_etype_used, stats.etype_used,
-                        stats.mac_etype_free, stats.etype_free);
+       PMD_DRV_LOG(INFO,
+               "add/rem control packet filter, return %d, mac_etype_used = %u, etype_used = %u, mac_etype_free = %u, etype_free = %u",
+               ret, stats.mac_etype_used, stats.etype_used,
+               stats.mac_etype_free, stats.etype_free);
        if (ret < 0)
                return -ENOSYS;
-       return 0;
+
+       /* Add or delete a filter in SW list */
+       if (add) {
+               ethertype_filter = rte_zmalloc("ethertype_filter",
+                                      sizeof(*ethertype_filter), 0);
+               rte_memcpy(ethertype_filter, &check_filter,
+                          sizeof(check_filter));
+               ret = i40e_sw_ethertype_filter_insert(pf, ethertype_filter);
+       } else {
+               ret = i40e_sw_ethertype_filter_del(pf, &node->input);
+       }
+
+       return ret;
 }
 
 /*
@@ -8069,7 +8910,7 @@ i40e_ethertype_filter_handle(struct rte_eth_dev *dev,
                        FALSE);
                break;
        default:
-               PMD_DRV_LOG(ERR, "unsupported operation %u\n", filter_op);
+               PMD_DRV_LOG(ERR, "unsupported operation %u", filter_op);
                ret = -ENOSYS;
                break;
        }
@@ -8107,6 +8948,11 @@ i40e_dev_filter_ctrl(struct rte_eth_dev *dev,
        case RTE_ETH_FILTER_FDIR:
                ret = i40e_fdir_ctrl_func(dev, filter_op, arg);
                break;
+       case RTE_ETH_FILTER_GENERIC:
+               if (filter_op != RTE_ETH_FILTER_GET)
+                       return -EINVAL;
+               *(const void **)arg = &i40e_flow_ops;
+               break;
        default:
                PMD_DRV_LOG(WARNING, "Filter type (%d) not supported",
                                                        filter_type);
@@ -8124,10 +8970,11 @@ i40e_dev_filter_ctrl(struct rte_eth_dev *dev,
 static void
 i40e_enable_extended_tag(struct rte_eth_dev *dev)
 {
+       struct rte_pci_device *pci_dev = I40E_DEV_TO_PCI(dev);
        uint32_t buf = 0;
        int ret;
 
-       ret = rte_eal_pci_read_config(dev->pci_dev, &buf, sizeof(buf),
+       ret = rte_eal_pci_read_config(pci_dev, &buf, sizeof(buf),
                                      PCI_DEV_CAP_REG);
        if (ret < 0) {
                PMD_DRV_LOG(ERR, "Failed to read PCI offset 0x%x",
@@ -8140,7 +8987,7 @@ i40e_enable_extended_tag(struct rte_eth_dev *dev)
        }
 
        buf = 0;
-       ret = rte_eal_pci_read_config(dev->pci_dev, &buf, sizeof(buf),
+       ret = rte_eal_pci_read_config(pci_dev, &buf, sizeof(buf),
                                      PCI_DEV_CTRL_REG);
        if (ret < 0) {
                PMD_DRV_LOG(ERR, "Failed to read PCI offset 0x%x",
@@ -8152,7 +8999,7 @@ i40e_enable_extended_tag(struct rte_eth_dev *dev)
                return;
        }
        buf |= PCI_DEV_CTRL_EXT_TAG_MASK;
-       ret = rte_eal_pci_write_config(dev->pci_dev, &buf, sizeof(buf),
+       ret = rte_eal_pci_write_config(pci_dev, &buf, sizeof(buf),
                                       PCI_DEV_CTRL_REG);
        if (ret < 0) {
                PMD_DRV_LOG(ERR, "Failed to write PCI offset 0x%x",
@@ -8215,18 +9062,14 @@ i40e_pctype_to_flowtype(enum i40e_filter_pctype pctype)
                [I40E_FILTER_PCTYPE_FRAG_IPV4] = RTE_ETH_FLOW_FRAG_IPV4,
                [I40E_FILTER_PCTYPE_NONF_IPV4_UDP] =
                        RTE_ETH_FLOW_NONFRAG_IPV4_UDP,
-#ifdef X722_SUPPORT
                [I40E_FILTER_PCTYPE_NONF_UNICAST_IPV4_UDP] =
                        RTE_ETH_FLOW_NONFRAG_IPV4_UDP,
                [I40E_FILTER_PCTYPE_NONF_MULTICAST_IPV4_UDP] =
                        RTE_ETH_FLOW_NONFRAG_IPV4_UDP,
-#endif
                [I40E_FILTER_PCTYPE_NONF_IPV4_TCP] =
                        RTE_ETH_FLOW_NONFRAG_IPV4_TCP,
-#ifdef X722_SUPPORT
                [I40E_FILTER_PCTYPE_NONF_IPV4_TCP_SYN_NO_ACK] =
                        RTE_ETH_FLOW_NONFRAG_IPV4_TCP,
-#endif
                [I40E_FILTER_PCTYPE_NONF_IPV4_SCTP] =
                        RTE_ETH_FLOW_NONFRAG_IPV4_SCTP,
                [I40E_FILTER_PCTYPE_NONF_IPV4_OTHER] =
@@ -8234,18 +9077,14 @@ i40e_pctype_to_flowtype(enum i40e_filter_pctype pctype)
                [I40E_FILTER_PCTYPE_FRAG_IPV6] = RTE_ETH_FLOW_FRAG_IPV6,
                [I40E_FILTER_PCTYPE_NONF_IPV6_UDP] =
                        RTE_ETH_FLOW_NONFRAG_IPV6_UDP,
-#ifdef X722_SUPPORT
                [I40E_FILTER_PCTYPE_NONF_UNICAST_IPV6_UDP] =
                        RTE_ETH_FLOW_NONFRAG_IPV6_UDP,
                [I40E_FILTER_PCTYPE_NONF_MULTICAST_IPV6_UDP] =
                        RTE_ETH_FLOW_NONFRAG_IPV6_UDP,
-#endif
                [I40E_FILTER_PCTYPE_NONF_IPV6_TCP] =
                        RTE_ETH_FLOW_NONFRAG_IPV6_TCP,
-#ifdef X722_SUPPORT
                [I40E_FILTER_PCTYPE_NONF_IPV6_TCP_SYN_NO_ACK] =
                        RTE_ETH_FLOW_NONFRAG_IPV6_TCP,
-#endif
                [I40E_FILTER_PCTYPE_NONF_IPV6_SCTP] =
                        RTE_ETH_FLOW_NONFRAG_IPV6_SCTP,
                [I40E_FILTER_PCTYPE_NONF_IPV6_OTHER] =
@@ -8275,6 +9114,10 @@ i40e_pctype_to_flowtype(enum i40e_filter_pctype pctype)
 #define I40E_GL_SWR_PRI_JOIN_MAP_2_VALUE 0x011f0200
 #define I40E_GL_SWR_PRI_JOIN_MAP_2       0x26CE08
 
+/* For X722 */
+#define I40E_X722_GL_SWR_PRI_JOIN_MAP_0_VALUE 0x20000200
+#define I40E_X722_GL_SWR_PRI_JOIN_MAP_2_VALUE 0x013F0200
+
 /* For X710 */
 #define I40E_GL_SWR_PM_UP_THR_EF_VALUE   0x03030303
 /* For XL710 */
@@ -8297,7 +9140,6 @@ i40e_dev_sync_phy_type(struct i40e_hw *hw)
        return 0;
 }
 
-
 static void
 i40e_configure_registers(struct i40e_hw *hw)
 {
@@ -8305,8 +9147,8 @@ i40e_configure_registers(struct i40e_hw *hw)
                uint32_t addr;
                uint64_t val;
        } reg_table[] = {
-               {I40E_GL_SWR_PRI_JOIN_MAP_0, I40E_GL_SWR_PRI_JOIN_MAP_0_VALUE},
-               {I40E_GL_SWR_PRI_JOIN_MAP_2, I40E_GL_SWR_PRI_JOIN_MAP_2_VALUE},
+               {I40E_GL_SWR_PRI_JOIN_MAP_0, 0},
+               {I40E_GL_SWR_PRI_JOIN_MAP_2, 0},
                {I40E_GL_SWR_PM_UP_THR, 0}, /* Compute value dynamically */
        };
        uint64_t reg;
@@ -8314,6 +9156,24 @@ i40e_configure_registers(struct i40e_hw *hw)
        int ret;
 
        for (i = 0; i < RTE_DIM(reg_table); i++) {
+               if (reg_table[i].addr == I40E_GL_SWR_PRI_JOIN_MAP_0) {
+                       if (hw->mac.type == I40E_MAC_X722) /* For X722 */
+                               reg_table[i].val =
+                                       I40E_X722_GL_SWR_PRI_JOIN_MAP_0_VALUE;
+                       else /* For X710/XL710/XXV710 */
+                               reg_table[i].val =
+                                       I40E_GL_SWR_PRI_JOIN_MAP_0_VALUE;
+               }
+
+               if (reg_table[i].addr == I40E_GL_SWR_PRI_JOIN_MAP_2) {
+                       if (hw->mac.type == I40E_MAC_X722) /* For X722 */
+                               reg_table[i].val =
+                                       I40E_X722_GL_SWR_PRI_JOIN_MAP_2_VALUE;
+                       else /* For X710/XL710/XXV710 */
+                               reg_table[i].val =
+                                       I40E_GL_SWR_PRI_JOIN_MAP_2_VALUE;
+               }
+
                if (reg_table[i].addr == I40E_GL_SWR_PM_UP_THR) {
                        if (I40E_PHY_TYPE_SUPPORT_40G(hw->phy.phy_types) || /* For XL710 */
                            I40E_PHY_TYPE_SUPPORT_25G(hw->phy.phy_types)) /* For XXV710 */
@@ -8339,9 +9199,9 @@ i40e_configure_registers(struct i40e_hw *hw)
                ret = i40e_aq_debug_write_register(hw, reg_table[i].addr,
                                                reg_table[i].val, NULL);
                if (ret < 0) {
-                       PMD_DRV_LOG(ERR, "Failed to write 0x%"PRIx64" to the "
-                               "address of 0x%"PRIx32, reg_table[i].val,
-                                                       reg_table[i].addr);
+                       PMD_DRV_LOG(ERR,
+                               "Failed to write 0x%"PRIx64" to the address of 0x%"PRIx32,
+                               reg_table[i].val, reg_table[i].addr);
                        break;
                }
                PMD_DRV_LOG(DEBUG, "Write 0x%"PRIx64" to the address of "
@@ -8386,8 +9246,9 @@ i40e_config_qinq(struct i40e_hw *hw, struct i40e_vsi *vsi)
                                                   I40E_VSI_L2TAGSTXVALID(
                                                   vsi->vsi_id), reg, NULL);
                if (ret < 0) {
-                       PMD_DRV_LOG(ERR, "Failed to update "
-                               "VSI_L2TAGSTXVALID[%d]", vsi->vsi_id);
+                       PMD_DRV_LOG(ERR,
+                               "Failed to update VSI_L2TAGSTXVALID[%d]",
+                               vsi->vsi_id);
                        return I40E_ERR_CONFIG;
                }
        }
@@ -8438,11 +9299,10 @@ i40e_aq_add_mirror_rule(struct i40e_hw *hw,
 
        rte_memcpy(&desc.params.raw, &cmd, sizeof(cmd));
        status = i40e_asq_send_command(hw, &desc, entries, buff_len, NULL);
-       PMD_DRV_LOG(INFO, "i40e_aq_add_mirror_rule, aq_status %d,"
-                        "rule_id = %u"
-                        " mirror_rules_used = %u, mirror_rules_free = %u,",
-                        hw->aq.asq_last_status, resp->rule_id,
-                        resp->mirror_rules_used, resp->mirror_rules_free);
+       PMD_DRV_LOG(INFO,
+               "i40e_aq_add_mirror_rule, aq_status %d, rule_id = %u mirror_rules_used = %u, mirror_rules_free = %u,",
+               hw->aq.asq_last_status, resp->rule_id,
+               resp->mirror_rules_used, resp->mirror_rules_free);
        *rule_id = rte_le_to_cpu_16(resp->rule_id);
 
        return status;
@@ -8520,8 +9380,8 @@ i40e_mirror_rule_set(struct rte_eth_dev *dev,
        PMD_DRV_LOG(DEBUG, "i40e_mirror_rule_set: sw_id = %d.", sw_id);
 
        if (pf->main_vsi->veb == NULL || pf->vfs == NULL) {
-               PMD_DRV_LOG(ERR, "mirror rule can not be configured"
-                       " without veb or vfs.");
+               PMD_DRV_LOG(ERR,
+                       "mirror rule can not be configured without veb or vfs.");
                return -ENOSYS;
        }
        if (pf->nb_mirror_rule > I40E_MAX_MIRROR_RULES) {
@@ -8553,9 +9413,9 @@ i40e_mirror_rule_set(struct rte_eth_dev *dev,
                                        mirr_rule->entries,
                                        mirr_rule->num_entries, mirr_rule->id);
                        if (ret < 0) {
-                               PMD_DRV_LOG(ERR, "failed to remove mirror rule:"
-                                                  " ret = %d, aq_err = %d.",
-                                                  ret, hw->aq.asq_last_status);
+                               PMD_DRV_LOG(ERR,
+                                       "failed to remove mirror rule: ret = %d, aq_err = %d.",
+                                       ret, hw->aq.asq_last_status);
                                return -ENOSYS;
                        }
                        TAILQ_REMOVE(&pf->mirror_list, mirr_rule, rules);
@@ -8644,9 +9504,9 @@ i40e_mirror_rule_set(struct rte_eth_dev *dev,
                                      mirr_rule->rule_type, mirr_rule->entries,
                                      j, &rule_id);
        if (ret < 0) {
-               PMD_DRV_LOG(ERR, "failed to add mirror rule:"
-                                  " ret = %d, aq_err = %d.",
-                                  ret, hw->aq.asq_last_status);
+               PMD_DRV_LOG(ERR,
+                       "failed to add mirror rule: ret = %d, aq_err = %d.",
+                       ret, hw->aq.asq_last_status);
                rte_free(mirr_rule);
                return -ENOSYS;
        }
@@ -8698,9 +9558,9 @@ i40e_mirror_rule_reset(struct rte_eth_dev *dev, uint8_t sw_id)
                                mirr_rule->entries,
                                mirr_rule->num_entries, mirr_rule->id);
                if (ret < 0) {
-                       PMD_DRV_LOG(ERR, "failed to remove mirror rule:"
-                                          " status = %d, aq_err = %d.",
-                                          ret, hw->aq.asq_last_status);
+                       PMD_DRV_LOG(ERR,
+                               "failed to remove mirror rule: status = %d, aq_err = %d.",
+                               ret, hw->aq.asq_last_status);
                        return -ENOSYS;
                }
                TAILQ_REMOVE(&pf->mirror_list, mirr_rule, rules);
@@ -9132,9 +9992,9 @@ i40e_config_switch_comp_tc(struct i40e_veb *veb, uint8_t tc_map)
        ret = i40e_aq_config_switch_comp_bw_config(hw, veb->seid,
                                                   &veb_bw, NULL);
        if (ret) {
-               PMD_INIT_LOG(ERR, "AQ command Config switch_comp BW allocation"
-                                 " per TC failed = %d",
-                                 hw->aq.asq_last_status);
+               PMD_INIT_LOG(ERR,
+                       "AQ command Config switch_comp BW allocation per TC failed = %d",
+                       hw->aq.asq_last_status);
                return ret;
        }
 
@@ -9142,16 +10002,18 @@ i40e_config_switch_comp_tc(struct i40e_veb *veb, uint8_t tc_map)
        ret = i40e_aq_query_switch_comp_ets_config(hw, veb->seid,
                                                   &ets_query, NULL);
        if (ret != I40E_SUCCESS) {
-               PMD_DRV_LOG(ERR, "Failed to get switch_comp ETS"
-                                " configuration %u", hw->aq.asq_last_status);
+               PMD_DRV_LOG(ERR,
+                       "Failed to get switch_comp ETS configuration %u",
+                       hw->aq.asq_last_status);
                return ret;
        }
        memset(&bw_query, 0, sizeof(bw_query));
        ret = i40e_aq_query_switch_comp_bw_config(hw, veb->seid,
                                                  &bw_query, NULL);
        if (ret != I40E_SUCCESS) {
-               PMD_DRV_LOG(ERR, "Failed to get switch_comp bandwidth"
-                                " configuration %u", hw->aq.asq_last_status);
+               PMD_DRV_LOG(ERR,
+                       "Failed to get switch_comp bandwidth configuration %u",
+                       hw->aq.asq_last_status);
                return ret;
        }
 
@@ -9216,8 +10078,8 @@ i40e_vsi_config_tc(struct i40e_vsi *vsi, uint8_t tc_map)
        }
        ret = i40e_aq_config_vsi_tc_bw(hw, vsi->seid, &bw_data, NULL);
        if (ret) {
-               PMD_INIT_LOG(ERR, "AQ command Config VSI BW allocation"
-                       " per TC failed = %d",
+               PMD_INIT_LOG(ERR,
+                       "AQ command Config VSI BW allocation per TC failed = %d",
                        hw->aq.asq_last_status);
                goto out;
        }
@@ -9238,9 +10100,8 @@ i40e_vsi_config_tc(struct i40e_vsi *vsi, uint8_t tc_map)
        /* Update the VSI after updating the VSI queue-mapping information */
        ret = i40e_aq_update_vsi_params(hw, &ctxt, NULL);
        if (ret) {
-               PMD_INIT_LOG(ERR, "Failed to configure "
-                           "TC queue mapping = %d",
-                           hw->aq.asq_last_status);
+               PMD_INIT_LOG(ERR, "Failed to configure TC queue mapping = %d",
+                       hw->aq.asq_last_status);
                goto out;
        }
        /* update the local VSI info with updated queue map */
@@ -9292,8 +10153,8 @@ i40e_dcb_hw_configure(struct i40e_pf *pf,
        /* Use the FW API if FW > v4.4*/
        if (!(((hw->aq.fw_maj_ver == 4) && (hw->aq.fw_min_ver >= 4)) ||
              (hw->aq.fw_maj_ver >= 5))) {
-               PMD_INIT_LOG(ERR, "FW < v4.4, can not use FW LLDP API"
-                                 " to configure DCB");
+               PMD_INIT_LOG(ERR,
+                       "FW < v4.4, can not use FW LLDP API to configure DCB");
                return I40E_ERR_FIRMWARE_API_VERSION;
        }
 
@@ -9308,8 +10169,7 @@ i40e_dcb_hw_configure(struct i40e_pf *pf,
        old_cfg->etsrec = old_cfg->etscfg;
        ret = i40e_set_dcb_config(hw);
        if (ret) {
-               PMD_INIT_LOG(ERR,
-                        "Set DCB Config failed, err %s aq_err %s\n",
+               PMD_INIT_LOG(ERR, "Set DCB Config failed, err %s aq_err %s",
                         i40e_stat_str(hw, ret),
                         i40e_aq_str(hw, hw->aq.asq_last_status));
                return ret;
@@ -9341,7 +10201,7 @@ i40e_dcb_hw_configure(struct i40e_pf *pf,
                ret = i40e_config_switch_comp_tc(main_vsi->veb, tc_map);
                if (ret)
                        PMD_INIT_LOG(WARNING,
-                                "Failed configuring TC for VEB seid=%d\n",
+                                "Failed configuring TC for VEB seid=%d",
                                 main_vsi->veb->seid);
        }
        /* Update each VSI */
@@ -9359,8 +10219,8 @@ i40e_dcb_hw_configure(struct i40e_pf *pf,
                                                         I40E_DEFAULT_TCMAP);
                        if (ret)
                                PMD_INIT_LOG(WARNING,
-                                        "Failed configuring TC for VSI seid=%d\n",
-                                        vsi_list->vsi->seid);
+                                       "Failed configuring TC for VSI seid=%d",
+                                       vsi_list->vsi->seid);
                        /* continue */
                }
        }
@@ -9379,7 +10239,7 @@ i40e_dcb_init_configure(struct rte_eth_dev *dev, bool sw_dcb)
 {
        struct i40e_pf *pf = I40E_DEV_PRIVATE_TO_PF(dev->data->dev_private);
        struct i40e_hw *hw = I40E_DEV_PRIVATE_TO_HW(dev->data->dev_private);
-       int ret = 0;
+       int i, ret = 0;
 
        if ((pf->flags & I40E_FLAG_DCB) == 0) {
                PMD_INIT_LOG(ERR, "HW doesn't support DCB");
@@ -9406,11 +10266,16 @@ i40e_dcb_init_configure(struct rte_eth_dev *dev, bool sw_dcb)
                        hw->local_dcbx_config.etscfg.tcbwtable[0] = 100;
                        hw->local_dcbx_config.etscfg.tsatable[0] =
                                                I40E_IEEE_TSA_ETS;
+                       /* all UPs mapping to TC0 */
+                       for (i = 0; i < I40E_MAX_USER_PRIORITY; i++)
+                               hw->local_dcbx_config.etscfg.prioritytable[i] = 0;
                        hw->local_dcbx_config.etsrec =
                                hw->local_dcbx_config.etscfg;
                        hw->local_dcbx_config.pfc.willing = 0;
                        hw->local_dcbx_config.pfc.pfccap =
                                                I40E_MAX_TRAFFIC_CLASS;
+                       hw->local_dcbx_config.pfc.pfcenable =
+                                               I40E_DEFAULT_TCMAP;
                        /* FW needs one App to configure HW */
                        hw->local_dcbx_config.numapps = 1;
                        hw->local_dcbx_config.app[0].selector =
@@ -9420,15 +10285,15 @@ i40e_dcb_init_configure(struct rte_eth_dev *dev, bool sw_dcb)
                                                I40E_APP_PROTOID_FCOE;
                        ret = i40e_set_dcb_config(hw);
                        if (ret) {
-                               PMD_INIT_LOG(ERR, "default dcb config fails."
-                                       " err = %d, aq_err = %d.", ret,
-                                         hw->aq.asq_last_status);
+                               PMD_INIT_LOG(ERR,
+                                       "default dcb config fails. err = %d, aq_err = %d.",
+                                       ret, hw->aq.asq_last_status);
                                return -ENOSYS;
                        }
                } else {
-                       PMD_INIT_LOG(ERR, "DCB initialization in FW fails,"
-                                         " err = %d, aq_err = %d.", ret,
-                                         hw->aq.asq_last_status);
+                       PMD_INIT_LOG(ERR,
+                               "DCB initialization in FW fails, err = %d, aq_err = %d.",
+                               ret, hw->aq.asq_last_status);
                        return -ENOTSUP;
                }
        } else {
@@ -9439,14 +10304,14 @@ i40e_dcb_init_configure(struct rte_eth_dev *dev, bool sw_dcb)
                ret = i40e_init_dcb(hw);
                if (!ret) {
                        if (hw->dcbx_status == I40E_DCBX_STATUS_DISABLED) {
-                               PMD_INIT_LOG(ERR, "HW doesn't support"
-                                                 " DCBX offload.");
+                               PMD_INIT_LOG(ERR,
+                                       "HW doesn't support DCBX offload.");
                                return -ENOTSUP;
                        }
                } else {
-                       PMD_INIT_LOG(ERR, "DCBX configuration failed, err = %d,"
-                                         " aq_err = %d.", ret,
-                                         hw->aq.asq_last_status);
+                       PMD_INIT_LOG(ERR,
+                               "DCBX configuration failed, err = %d, aq_err = %d.",
+                               ret, hw->aq.asq_last_status);
                        return -ENOTSUP;
                }
        }
@@ -9555,7 +10420,8 @@ i40e_dev_get_dcb_info(struct rte_eth_dev *dev,
 static int
 i40e_dev_rx_queue_intr_enable(struct rte_eth_dev *dev, uint16_t queue_id)
 {
-       struct rte_intr_handle *intr_handle = &dev->pci_dev->intr_handle;
+       struct rte_pci_device *pci_dev = I40E_DEV_TO_PCI(dev);
+       struct rte_intr_handle *intr_handle = &pci_dev->intr_handle;
        struct i40e_hw *hw = I40E_DEV_PRIVATE_TO_HW(dev->data->dev_private);
        uint16_t interval =
                i40e_calc_itr_interval(RTE_LIBRTE_I40E_ITR_INTERVAL);
@@ -9580,7 +10446,7 @@ i40e_dev_rx_queue_intr_enable(struct rte_eth_dev *dev, uint16_t queue_id)
                                I40E_PFINT_DYN_CTLN_INTERVAL_SHIFT));
 
        I40E_WRITE_FLUSH(hw);
-       rte_intr_enable(&dev->pci_dev->intr_handle);
+       rte_intr_enable(&pci_dev->intr_handle);
 
        return 0;
 }
@@ -9588,7 +10454,8 @@ i40e_dev_rx_queue_intr_enable(struct rte_eth_dev *dev, uint16_t queue_id)
 static int
 i40e_dev_rx_queue_intr_disable(struct rte_eth_dev *dev, uint16_t queue_id)
 {
-       struct rte_intr_handle *intr_handle = &dev->pci_dev->intr_handle;
+       struct rte_pci_device *pci_dev = I40E_DEV_TO_PCI(dev);
+       struct rte_intr_handle *intr_handle = &pci_dev->intr_handle;
        struct i40e_hw *hw = I40E_DEV_PRIVATE_TO_HW(dev->data->dev_private);
        uint16_t msix_intr;
 
@@ -9720,8 +10587,7 @@ i40e_dev_mtu_set(struct rte_eth_dev *dev, uint16_t mtu)
 
        /* mtu setting is forbidden if port is start */
        if (dev_data->dev_started) {
-               PMD_DRV_LOG(ERR,
-                           "port %d must be stopped before configuration\n",
+               PMD_DRV_LOG(ERR, "port %d must be stopped before configuration",
                            dev_data->port_id);
                return -EBUSY;
        }
@@ -9735,3 +10601,1878 @@ i40e_dev_mtu_set(struct rte_eth_dev *dev, uint16_t mtu)
 
        return ret;
 }
+
+/* Restore ethertype filter */
+static void
+i40e_ethertype_filter_restore(struct i40e_pf *pf)
+{
+       struct i40e_hw *hw = I40E_PF_TO_HW(pf);
+       struct i40e_ethertype_filter_list
+               *ethertype_list = &pf->ethertype.ethertype_list;
+       struct i40e_ethertype_filter *f;
+       struct i40e_control_filter_stats stats;
+       uint16_t flags;
+
+       TAILQ_FOREACH(f, ethertype_list, rules) {
+               flags = 0;
+               if (!(f->flags & RTE_ETHTYPE_FLAGS_MAC))
+                       flags |= I40E_AQC_ADD_CONTROL_PACKET_FLAGS_IGNORE_MAC;
+               if (f->flags & RTE_ETHTYPE_FLAGS_DROP)
+                       flags |= I40E_AQC_ADD_CONTROL_PACKET_FLAGS_DROP;
+               flags |= I40E_AQC_ADD_CONTROL_PACKET_FLAGS_TO_QUEUE;
+
+               memset(&stats, 0, sizeof(stats));
+               i40e_aq_add_rem_control_packet_filter(hw,
+                                           f->input.mac_addr.addr_bytes,
+                                           f->input.ether_type,
+                                           flags, pf->main_vsi->seid,
+                                           f->queue, 1, &stats, NULL);
+       }
+       PMD_DRV_LOG(INFO, "Ethertype filter:"
+                   " mac_etype_used = %u, etype_used = %u,"
+                   " mac_etype_free = %u, etype_free = %u",
+                   stats.mac_etype_used, stats.etype_used,
+                   stats.mac_etype_free, stats.etype_free);
+}
+
+/* Restore tunnel filter */
+static void
+i40e_tunnel_filter_restore(struct i40e_pf *pf)
+{
+       struct i40e_hw *hw = I40E_PF_TO_HW(pf);
+       struct i40e_vsi *vsi;
+       struct i40e_pf_vf *vf;
+       struct i40e_tunnel_filter_list
+               *tunnel_list = &pf->tunnel.tunnel_list;
+       struct i40e_tunnel_filter *f;
+       struct i40e_aqc_add_rm_cloud_filt_elem_ext cld_filter;
+       bool big_buffer = 0;
+
+       TAILQ_FOREACH(f, tunnel_list, rules) {
+               if (!f->is_to_vf)
+                       vsi = pf->main_vsi;
+               else {
+                       vf = &pf->vfs[f->vf_id];
+                       vsi = vf->vsi;
+               }
+               memset(&cld_filter, 0, sizeof(cld_filter));
+               ether_addr_copy((struct ether_addr *)&f->input.outer_mac,
+                       (struct ether_addr *)&cld_filter.element.outer_mac);
+               ether_addr_copy((struct ether_addr *)&f->input.inner_mac,
+                       (struct ether_addr *)&cld_filter.element.inner_mac);
+               cld_filter.element.inner_vlan = f->input.inner_vlan;
+               cld_filter.element.flags = f->input.flags;
+               cld_filter.element.tenant_id = f->input.tenant_id;
+               cld_filter.element.queue_number = f->queue;
+               rte_memcpy(cld_filter.general_fields,
+                          f->input.general_fields,
+                          sizeof(f->input.general_fields));
+
+               if (((f->input.flags &
+                    I40E_AQC_ADD_CLOUD_FILTER_TEID_MPLSoUDP) ==
+                    I40E_AQC_ADD_CLOUD_FILTER_TEID_MPLSoUDP) ||
+                   ((f->input.flags &
+                    I40E_AQC_ADD_CLOUD_FILTER_TEID_MPLSoGRE) ==
+                    I40E_AQC_ADD_CLOUD_FILTER_TEID_MPLSoGRE) ||
+                   ((f->input.flags &
+                    I40E_AQC_ADD_CLOUD_FILTER_CUSTOM_QINQ) ==
+                    I40E_AQC_ADD_CLOUD_FILTER_CUSTOM_QINQ))
+                       big_buffer = 1;
+
+               if (big_buffer)
+                       i40e_aq_add_cloud_filters_big_buffer(hw,
+                                            vsi->seid, &cld_filter, 1);
+               else
+                       i40e_aq_add_cloud_filters(hw, vsi->seid,
+                                                 &cld_filter.element, 1);
+       }
+}
+
+static void
+i40e_filter_restore(struct i40e_pf *pf)
+{
+       i40e_ethertype_filter_restore(pf);
+       i40e_tunnel_filter_restore(pf);
+       i40e_fdir_filter_restore(pf);
+}
+
+static bool
+is_device_supported(struct rte_eth_dev *dev, struct rte_pci_driver *drv)
+{
+       if (strcmp(dev->data->drv_name,
+                  drv->driver.name))
+               return false;
+
+       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)
+{
+       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;
+}
+
+/* Create a QinQ cloud filter
+ *
+ * The Fortville NIC has limited resources for tunnel filters,
+ * so we can only reuse existing filters.
+ *
+ * In step 1 we define which Field Vector fields can be used for
+ * filter types.
+ * As we do not have the inner tag defined as a field,
+ * we have to define it first, by reusing one of L1 entries.
+ *
+ * In step 2 we are replacing one of existing filter types with
+ * a new one for QinQ.
+ * As we reusing L1 and replacing L2, some of the default filter
+ * types will disappear,which depends on L1 and L2 entries we reuse.
+ *
+ * Step 1: Create L1 filter of outer vlan (12b) + inner vlan (12b)
+ *
+ * 1.  Create L1 filter of outer vlan (12b) which will be in use
+ *             later when we define the cloud filter.
+ *     a.      Valid_flags.replace_cloud = 0
+ *     b.      Old_filter = 10 (Stag_Inner_Vlan)
+ *     c.      New_filter = 0x10
+ *     d.      TR bit = 0xff (optional, not used here)
+ *     e.      Buffer – 2 entries:
+ *             i.      Byte 0 = 8 (outer vlan FV index).
+ *                     Byte 1 = 0 (rsv)
+ *                     Byte 2-3 = 0x0fff
+ *             ii.     Byte 0 = 37 (inner vlan FV index).
+ *                     Byte 1 =0 (rsv)
+ *                     Byte 2-3 = 0x0fff
+ *
+ * Step 2:
+ * 2.  Create cloud filter using two L1 filters entries: stag and
+ *             new filter(outer vlan+ inner vlan)
+ *     a.      Valid_flags.replace_cloud = 1
+ *     b.      Old_filter = 1 (instead of outer IP)
+ *     c.      New_filter = 0x10
+ *     d.      Buffer – 2 entries:
+ *             i.      Byte 0 = 0x80 | 7 (valid | Stag).
+ *                     Byte 1-3 = 0 (rsv)
+ *             ii.     Byte 8 = 0x80 | 0x10 (valid | new l1 filter step1)
+ *                     Byte 9-11 = 0 (rsv)
+ */
+static int
+i40e_cloud_filter_qinq_create(struct i40e_pf *pf)
+{
+       int ret = -ENOTSUP;
+       struct i40e_aqc_replace_cloud_filters_cmd  filter_replace;
+       struct i40e_aqc_replace_cloud_filters_cmd_buf  filter_replace_buf;
+       struct i40e_hw *hw = I40E_PF_TO_HW(pf);
+
+       /* Init */
+       memset(&filter_replace, 0,
+              sizeof(struct i40e_aqc_replace_cloud_filters_cmd));
+       memset(&filter_replace_buf, 0,
+              sizeof(struct i40e_aqc_replace_cloud_filters_cmd_buf));
+
+       /* create L1 filter */
+       filter_replace.old_filter_type =
+               I40E_AQC_REPLACE_CLOUD_CMD_INPUT_FV_STAG_IVLAN;
+       filter_replace.new_filter_type = I40E_AQC_ADD_CLOUD_FILTER_CUSTOM_QINQ;
+       filter_replace.tr_bit = 0;
+
+       /* Prepare the buffer, 2 entries */
+       filter_replace_buf.data[0] = I40E_AQC_REPLACE_CLOUD_CMD_INPUT_FV_VLAN;
+       filter_replace_buf.data[0] |=
+               I40E_AQC_REPLACE_CLOUD_CMD_INPUT_VALIDATED;
+       /* Field Vector 12b mask */
+       filter_replace_buf.data[2] = 0xff;
+       filter_replace_buf.data[3] = 0x0f;
+       filter_replace_buf.data[4] =
+               I40E_AQC_REPLACE_CLOUD_CMD_INPUT_FV_INNER_VLAN;
+       filter_replace_buf.data[4] |=
+               I40E_AQC_REPLACE_CLOUD_CMD_INPUT_VALIDATED;
+       /* Field Vector 12b mask */
+       filter_replace_buf.data[6] = 0xff;
+       filter_replace_buf.data[7] = 0x0f;
+       ret = i40e_aq_replace_cloud_filters(hw, &filter_replace,
+                       &filter_replace_buf);
+       if (ret != I40E_SUCCESS)
+               return ret;
+
+       /* Apply the second L2 cloud filter */
+       memset(&filter_replace, 0,
+              sizeof(struct i40e_aqc_replace_cloud_filters_cmd));
+       memset(&filter_replace_buf, 0,
+              sizeof(struct i40e_aqc_replace_cloud_filters_cmd_buf));
+
+       /* create L2 filter, input for L2 filter will be L1 filter  */
+       filter_replace.valid_flags = I40E_AQC_REPLACE_CLOUD_FILTER;
+       filter_replace.old_filter_type = I40E_AQC_ADD_CLOUD_FILTER_OIP;
+       filter_replace.new_filter_type = I40E_AQC_ADD_CLOUD_FILTER_CUSTOM_QINQ;
+
+       /* Prepare the buffer, 2 entries */
+       filter_replace_buf.data[0] = I40E_AQC_REPLACE_CLOUD_CMD_INPUT_FV_STAG;
+       filter_replace_buf.data[0] |=
+               I40E_AQC_REPLACE_CLOUD_CMD_INPUT_VALIDATED;
+       filter_replace_buf.data[4] = I40E_AQC_ADD_CLOUD_FILTER_CUSTOM_QINQ;
+       filter_replace_buf.data[4] |=
+               I40E_AQC_REPLACE_CLOUD_CMD_INPUT_VALIDATED;
+       ret = i40e_aq_replace_cloud_filters(hw, &filter_replace,
+                       &filter_replace_buf);
+       return ret;
+}
+
+RTE_INIT(i40e_init_log);
+static void
+i40e_init_log(void)
+{
+       i40e_logtype_init = rte_log_register("pmd.i40e.init");
+       if (i40e_logtype_init >= 0)
+               rte_log_set_level(i40e_logtype_init, RTE_LOG_NOTICE);
+       i40e_logtype_driver = rte_log_register("pmd.i40e.driver");
+       if (i40e_logtype_driver >= 0)
+               rte_log_set_level(i40e_logtype_driver, RTE_LOG_NOTICE);
+}