net/ixgbe: store L2 tunnel filter
[dpdk.git] / drivers / net / ixgbe / ixgbe_ethdev.c
index baffc71..f3dc3ed 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
@@ -60,6 +60,7 @@
 #include <rte_malloc.h>
 #include <rte_random.h>
 #include <rte_dev.h>
+#include <rte_hash_crc.h>
 
 #include "ixgbe_logs.h"
 #include "base/ixgbe_api.h"
@@ -165,6 +166,10 @@ enum ixgbevf_xcast_modes {
 
 static int eth_ixgbe_dev_init(struct rte_eth_dev *eth_dev);
 static int eth_ixgbe_dev_uninit(struct rte_eth_dev *eth_dev);
+static int ixgbe_fdir_filter_init(struct rte_eth_dev *eth_dev);
+static int ixgbe_fdir_filter_uninit(struct rte_eth_dev *eth_dev);
+static int ixgbe_l2_tn_filter_init(struct rte_eth_dev *eth_dev);
+static int ixgbe_l2_tn_filter_uninit(struct rte_eth_dev *eth_dev);
 static int  ixgbe_dev_configure(struct rte_eth_dev *dev);
 static int  ixgbe_dev_start(struct rte_eth_dev *dev);
 static void ixgbe_dev_stop(struct rte_eth_dev *dev);
@@ -193,6 +198,8 @@ static int ixgbe_dev_queue_stats_mapping_set(struct rte_eth_dev *eth_dev,
                                             uint16_t queue_id,
                                             uint8_t stat_idx,
                                             uint8_t is_rx);
+static int ixgbe_fw_version_get(struct rte_eth_dev *dev, char *fw_version,
+                                size_t fw_size);
 static void ixgbe_dev_info_get(struct rte_eth_dev *dev,
                               struct rte_eth_dev_info *dev_info);
 static const uint32_t *ixgbe_dev_supported_ptypes_get(struct rte_eth_dev *dev);
@@ -231,9 +238,11 @@ static int ixgbe_dev_rss_reta_query(struct rte_eth_dev *dev,
                        uint16_t reta_size);
 static void ixgbe_dev_link_status_print(struct rte_eth_dev *dev);
 static int ixgbe_dev_lsc_interrupt_setup(struct rte_eth_dev *dev);
+static int ixgbe_dev_macsec_interrupt_setup(struct rte_eth_dev *dev);
 static int ixgbe_dev_rxq_interrupt_setup(struct rte_eth_dev *dev);
 static int ixgbe_dev_interrupt_get_status(struct rte_eth_dev *dev);
-static int ixgbe_dev_interrupt_action(struct rte_eth_dev *dev);
+static int ixgbe_dev_interrupt_action(struct rte_eth_dev *dev,
+                                     struct rte_intr_handle *handle);
 static void ixgbe_dev_interrupt_handler(struct rte_intr_handle *handle,
                void *param);
 static void ixgbe_dev_interrupt_delayed_handler(void *param);
@@ -243,6 +252,7 @@ static void ixgbe_remove_rar(struct rte_eth_dev *dev, uint32_t index);
 static void ixgbe_set_default_mac_addr(struct rte_eth_dev *dev,
                                           struct ether_addr *mac_addr);
 static void ixgbe_dcb_init(struct ixgbe_hw *hw, struct ixgbe_dcb_config *dcb_config);
+static int is_ixgbe_pmd(const char *driver_name);
 
 /* For Virtual Function support */
 static int eth_ixgbevf_dev_init(struct rte_eth_dev *eth_dev);
@@ -276,12 +286,6 @@ static void ixgbevf_dev_allmulticast_disable(struct rte_eth_dev *dev);
 static int ixgbe_uc_hash_table_set(struct rte_eth_dev *dev, struct
                ether_addr * mac_addr, uint8_t on);
 static int ixgbe_uc_all_hash_table_set(struct rte_eth_dev *dev, uint8_t on);
-static int  ixgbe_set_pool_rx_mode(struct rte_eth_dev *dev,  uint16_t pool,
-               uint16_t rx_mask, uint8_t on);
-static int ixgbe_set_pool_rx(struct rte_eth_dev *dev, uint16_t pool, uint8_t on);
-static int ixgbe_set_pool_tx(struct rte_eth_dev *dev, uint16_t pool, uint8_t on);
-static int ixgbe_set_pool_vlan_filter(struct rte_eth_dev *dev, uint16_t vlan,
-               uint64_t pool_mask, uint8_t vlan_on);
 static int ixgbe_mirror_rule_set(struct rte_eth_dev *dev,
                struct rte_eth_mirror_conf *mirror_conf,
                uint8_t rule_id, uint8_t on);
@@ -297,8 +301,6 @@ static void ixgbe_configure_msix(struct rte_eth_dev *dev);
 
 static int ixgbe_set_queue_rate_limit(struct rte_eth_dev *dev,
                uint16_t queue_idx, uint16_t tx_rate);
-static int ixgbe_set_vf_rate_limit(struct rte_eth_dev *dev, uint16_t vf,
-               uint16_t tx_rate, uint64_t q_msk);
 
 static void ixgbevf_add_mac_addr(struct rte_eth_dev *dev,
                                 struct ether_addr *mac_addr,
@@ -517,6 +519,8 @@ static const struct rte_eth_desc_lim tx_desc_lim = {
        .nb_max = IXGBE_MAX_RING_DESC,
        .nb_min = IXGBE_MIN_RING_DESC,
        .nb_align = IXGBE_TXD_ALIGN,
+       .nb_seg_max = IXGBE_TX_MAX_SEG,
+       .nb_mtu_seg_max = IXGBE_TX_MAX_SEG,
 };
 
 static const struct eth_dev_ops ixgbe_eth_dev_ops = {
@@ -537,6 +541,7 @@ static const struct eth_dev_ops ixgbe_eth_dev_ops = {
        .xstats_reset         = ixgbe_dev_xstats_reset,
        .xstats_get_names     = ixgbe_dev_xstats_get_names,
        .queue_stats_mapping_set = ixgbe_dev_queue_stats_mapping_set,
+       .fw_version_get       = ixgbe_fw_version_get,
        .dev_infos_get        = ixgbe_dev_info_get,
        .dev_supported_ptypes_get = ixgbe_dev_supported_ptypes_get,
        .mtu_set              = ixgbe_dev_mtu_set,
@@ -568,12 +573,7 @@ static const struct eth_dev_ops ixgbe_eth_dev_ops = {
        .uc_all_hash_table_set  = ixgbe_uc_all_hash_table_set,
        .mirror_rule_set      = ixgbe_mirror_rule_set,
        .mirror_rule_reset    = ixgbe_mirror_rule_reset,
-       .set_vf_rx_mode       = ixgbe_set_pool_rx_mode,
-       .set_vf_rx            = ixgbe_set_pool_rx,
-       .set_vf_tx            = ixgbe_set_pool_tx,
-       .set_vf_vlan_filter   = ixgbe_set_pool_vlan_filter,
        .set_queue_rate_limit = ixgbe_set_queue_rate_limit,
-       .set_vf_rate_limit    = ixgbe_set_vf_rate_limit,
        .reta_update          = ixgbe_dev_rss_reta_update,
        .reta_query           = ixgbe_dev_rss_reta_query,
 #ifdef RTE_NIC_BYPASS
@@ -744,6 +744,51 @@ static const struct rte_ixgbe_xstats_name_off rte_ixgbe_stats_strings[] = {
 #define IXGBE_NB_HW_STATS (sizeof(rte_ixgbe_stats_strings) / \
                           sizeof(rte_ixgbe_stats_strings[0]))
 
+/* MACsec statistics */
+static const struct rte_ixgbe_xstats_name_off rte_ixgbe_macsec_strings[] = {
+       {"out_pkts_untagged", offsetof(struct ixgbe_macsec_stats,
+               out_pkts_untagged)},
+       {"out_pkts_encrypted", offsetof(struct ixgbe_macsec_stats,
+               out_pkts_encrypted)},
+       {"out_pkts_protected", offsetof(struct ixgbe_macsec_stats,
+               out_pkts_protected)},
+       {"out_octets_encrypted", offsetof(struct ixgbe_macsec_stats,
+               out_octets_encrypted)},
+       {"out_octets_protected", offsetof(struct ixgbe_macsec_stats,
+               out_octets_protected)},
+       {"in_pkts_untagged", offsetof(struct ixgbe_macsec_stats,
+               in_pkts_untagged)},
+       {"in_pkts_badtag", offsetof(struct ixgbe_macsec_stats,
+               in_pkts_badtag)},
+       {"in_pkts_nosci", offsetof(struct ixgbe_macsec_stats,
+               in_pkts_nosci)},
+       {"in_pkts_unknownsci", offsetof(struct ixgbe_macsec_stats,
+               in_pkts_unknownsci)},
+       {"in_octets_decrypted", offsetof(struct ixgbe_macsec_stats,
+               in_octets_decrypted)},
+       {"in_octets_validated", offsetof(struct ixgbe_macsec_stats,
+               in_octets_validated)},
+       {"in_pkts_unchecked", offsetof(struct ixgbe_macsec_stats,
+               in_pkts_unchecked)},
+       {"in_pkts_delayed", offsetof(struct ixgbe_macsec_stats,
+               in_pkts_delayed)},
+       {"in_pkts_late", offsetof(struct ixgbe_macsec_stats,
+               in_pkts_late)},
+       {"in_pkts_ok", offsetof(struct ixgbe_macsec_stats,
+               in_pkts_ok)},
+       {"in_pkts_invalid", offsetof(struct ixgbe_macsec_stats,
+               in_pkts_invalid)},
+       {"in_pkts_notvalid", offsetof(struct ixgbe_macsec_stats,
+               in_pkts_notvalid)},
+       {"in_pkts_unusedsa", offsetof(struct ixgbe_macsec_stats,
+               in_pkts_unusedsa)},
+       {"in_pkts_notusingsa", offsetof(struct ixgbe_macsec_stats,
+               in_pkts_notusingsa)},
+};
+
+#define IXGBE_NB_MACSEC_STATS (sizeof(rte_ixgbe_macsec_strings) / \
+                          sizeof(rte_ixgbe_macsec_strings[0]))
+
 /* Per-queue statistics */
 static const struct rte_ixgbe_xstats_name_off rte_ixgbe_rxq_strings[] = {
        {"mbuf_allocation_errors", offsetof(struct ixgbe_hw_stats, rnbc)},
@@ -1083,7 +1128,8 @@ ixgbe_swfw_lock_reset(struct ixgbe_hw *hw)
 static int
 eth_ixgbe_dev_init(struct rte_eth_dev *eth_dev)
 {
-       struct rte_pci_device *pci_dev;
+       struct rte_pci_device *pci_dev = IXGBE_DEV_TO_PCI(eth_dev);
+       struct rte_intr_handle *intr_handle = &pci_dev->intr_handle;
        struct ixgbe_hw *hw =
                IXGBE_DEV_PRIVATE_TO_HW(eth_dev->data->dev_private);
        struct ixgbe_vfta *shadow_vfta =
@@ -1103,6 +1149,7 @@ eth_ixgbe_dev_init(struct rte_eth_dev *eth_dev)
        eth_dev->dev_ops = &ixgbe_eth_dev_ops;
        eth_dev->rx_pkt_burst = &ixgbe_recv_pkts;
        eth_dev->tx_pkt_burst = &ixgbe_xmit_pkts;
+       eth_dev->tx_pkt_prepare = &ixgbe_prep_pkts;
 
        /*
         * For secondary processes, we don't initialise any further as primary
@@ -1127,9 +1174,9 @@ eth_ixgbe_dev_init(struct rte_eth_dev *eth_dev)
 
                return 0;
        }
-       pci_dev = eth_dev->pci_dev;
 
        rte_eth_copy_pci_info(eth_dev, pci_dev);
+       eth_dev->data->dev_flags = RTE_ETH_DEV_DETACHABLE;
 
        /* Vendor and Device ID need to be set before init of shared code */
        hw->device_id = pci_dev->id.device_id;
@@ -1272,28 +1319,35 @@ eth_ixgbe_dev_init(struct rte_eth_dev *eth_dev)
                     eth_dev->data->port_id, pci_dev->id.vendor_id,
                     pci_dev->id.device_id);
 
-       rte_intr_callback_register(&pci_dev->intr_handle,
-                                  ixgbe_dev_interrupt_handler,
-                                  (void *)eth_dev);
+       rte_intr_callback_register(intr_handle,
+                                  ixgbe_dev_interrupt_handler, eth_dev);
 
        /* enable uio/vfio intr/eventfd mapping */
-       rte_intr_enable(&pci_dev->intr_handle);
+       rte_intr_enable(intr_handle);
 
        /* enable support intr */
        ixgbe_enable_intr(eth_dev);
 
+       /* initialize filter info */
+       memset(filter_info, 0,
+              sizeof(struct ixgbe_filter_info));
+
        /* initialize 5tuple filter list */
        TAILQ_INIT(&filter_info->fivetuple_list);
-       memset(filter_info->fivetuple_mask, 0,
-              sizeof(uint32_t) * IXGBE_5TUPLE_ARRAY_SIZE);
 
+       /* initialize flow director filter list & hash */
+       ixgbe_fdir_filter_init(eth_dev);
+
+       /* initialize l2 tunnel filter list & hash */
+       ixgbe_l2_tn_filter_init(eth_dev);
        return 0;
 }
 
 static int
 eth_ixgbe_dev_uninit(struct rte_eth_dev *eth_dev)
 {
-       struct rte_pci_device *pci_dev;
+       struct rte_pci_device *pci_dev = IXGBE_DEV_TO_PCI(eth_dev);
+       struct rte_intr_handle *intr_handle = &pci_dev->intr_handle;
        struct ixgbe_hw *hw;
 
        PMD_INIT_FUNC_TRACE();
@@ -1302,7 +1356,6 @@ eth_ixgbe_dev_uninit(struct rte_eth_dev *eth_dev)
                return -EPERM;
 
        hw = IXGBE_DEV_PRIVATE_TO_HW(eth_dev->data->dev_private);
-       pci_dev = eth_dev->pci_dev;
 
        if (hw->adapter_stopped == 0)
                ixgbe_dev_close(eth_dev);
@@ -1315,9 +1368,9 @@ eth_ixgbe_dev_uninit(struct rte_eth_dev *eth_dev)
        ixgbe_swfw_lock_reset(hw);
 
        /* disable uio intr before callback unregister */
-       rte_intr_disable(&(pci_dev->intr_handle));
-       rte_intr_callback_unregister(&(pci_dev->intr_handle),
-               ixgbe_dev_interrupt_handler, (void *)eth_dev);
+       rte_intr_disable(intr_handle);
+       rte_intr_callback_unregister(intr_handle,
+                                    ixgbe_dev_interrupt_handler, eth_dev);
 
        /* uninitialize PF if max_vfs not zero */
        ixgbe_pf_host_uninit(eth_dev);
@@ -1328,9 +1381,125 @@ eth_ixgbe_dev_uninit(struct rte_eth_dev *eth_dev)
        rte_free(eth_dev->data->hash_mac_addrs);
        eth_dev->data->hash_mac_addrs = NULL;
 
+       /* remove all the fdir filters & hash */
+       ixgbe_fdir_filter_uninit(eth_dev);
+
+       /* remove all the L2 tunnel filters & hash */
+       ixgbe_l2_tn_filter_uninit(eth_dev);
+
+       return 0;
+}
+
+static int ixgbe_fdir_filter_uninit(struct rte_eth_dev *eth_dev)
+{
+       struct ixgbe_hw_fdir_info *fdir_info =
+               IXGBE_DEV_PRIVATE_TO_FDIR_INFO(eth_dev->data->dev_private);
+       struct ixgbe_fdir_filter *fdir_filter;
+
+               if (fdir_info->hash_map)
+               rte_free(fdir_info->hash_map);
+       if (fdir_info->hash_handle)
+               rte_hash_free(fdir_info->hash_handle);
+
+       while ((fdir_filter = TAILQ_FIRST(&fdir_info->fdir_list))) {
+               TAILQ_REMOVE(&fdir_info->fdir_list,
+                            fdir_filter,
+                            entries);
+               rte_free(fdir_filter);
+       }
+
+       return 0;
+}
+
+static int ixgbe_l2_tn_filter_uninit(struct rte_eth_dev *eth_dev)
+{
+       struct ixgbe_l2_tn_info *l2_tn_info =
+               IXGBE_DEV_PRIVATE_TO_L2_TN_INFO(eth_dev->data->dev_private);
+       struct ixgbe_l2_tn_filter *l2_tn_filter;
+
+       if (l2_tn_info->hash_map)
+               rte_free(l2_tn_info->hash_map);
+       if (l2_tn_info->hash_handle)
+               rte_hash_free(l2_tn_info->hash_handle);
+
+       while ((l2_tn_filter = TAILQ_FIRST(&l2_tn_info->l2_tn_list))) {
+               TAILQ_REMOVE(&l2_tn_info->l2_tn_list,
+                            l2_tn_filter,
+                            entries);
+               rte_free(l2_tn_filter);
+       }
+
+       return 0;
+}
+
+static int ixgbe_fdir_filter_init(struct rte_eth_dev *eth_dev)
+{
+       struct ixgbe_hw_fdir_info *fdir_info =
+               IXGBE_DEV_PRIVATE_TO_FDIR_INFO(eth_dev->data->dev_private);
+       char fdir_hash_name[RTE_HASH_NAMESIZE];
+       struct rte_hash_parameters fdir_hash_params = {
+               .name = fdir_hash_name,
+               .entries = IXGBE_MAX_FDIR_FILTER_NUM,
+               .key_len = sizeof(union ixgbe_atr_input),
+               .hash_func = rte_hash_crc,
+               .hash_func_init_val = 0,
+               .socket_id = rte_socket_id(),
+       };
+
+       TAILQ_INIT(&fdir_info->fdir_list);
+       snprintf(fdir_hash_name, RTE_HASH_NAMESIZE,
+                "fdir_%s", eth_dev->data->name);
+       fdir_info->hash_handle = rte_hash_create(&fdir_hash_params);
+       if (!fdir_info->hash_handle) {
+               PMD_INIT_LOG(ERR, "Failed to create fdir hash table!");
+               return -EINVAL;
+       }
+       fdir_info->hash_map = rte_zmalloc("ixgbe",
+                                         sizeof(struct ixgbe_fdir_filter *) *
+                                         IXGBE_MAX_FDIR_FILTER_NUM,
+                                         0);
+       if (!fdir_info->hash_map) {
+               PMD_INIT_LOG(ERR,
+                            "Failed to allocate memory for fdir hash map!");
+               return -ENOMEM;
+       }
        return 0;
 }
 
+static int ixgbe_l2_tn_filter_init(struct rte_eth_dev *eth_dev)
+{
+       struct ixgbe_l2_tn_info *l2_tn_info =
+               IXGBE_DEV_PRIVATE_TO_L2_TN_INFO(eth_dev->data->dev_private);
+       char l2_tn_hash_name[RTE_HASH_NAMESIZE];
+       struct rte_hash_parameters l2_tn_hash_params = {
+               .name = l2_tn_hash_name,
+               .entries = IXGBE_MAX_L2_TN_FILTER_NUM,
+               .key_len = sizeof(struct ixgbe_l2_tn_key),
+               .hash_func = rte_hash_crc,
+               .hash_func_init_val = 0,
+               .socket_id = rte_socket_id(),
+       };
+
+       TAILQ_INIT(&l2_tn_info->l2_tn_list);
+       snprintf(l2_tn_hash_name, RTE_HASH_NAMESIZE,
+                "l2_tn_%s", eth_dev->data->name);
+       l2_tn_info->hash_handle = rte_hash_create(&l2_tn_hash_params);
+       if (!l2_tn_info->hash_handle) {
+               PMD_INIT_LOG(ERR, "Failed to create L2 TN hash table!");
+               return -EINVAL;
+       }
+       l2_tn_info->hash_map = rte_zmalloc("ixgbe",
+                                  sizeof(struct ixgbe_l2_tn_filter *) *
+                                  IXGBE_MAX_L2_TN_FILTER_NUM,
+                                  0);
+       if (!l2_tn_info->hash_map) {
+               PMD_INIT_LOG(ERR,
+                       "Failed to allocate memory for L2 TN hash map!");
+               return -ENOMEM;
+       }
+
+       return 0;
+}
 /*
  * Negotiate mailbox API version with the PF.
  * After reset API version is always set to the basic one (ixgbe_mbox_api_10).
@@ -1381,7 +1550,8 @@ eth_ixgbevf_dev_init(struct rte_eth_dev *eth_dev)
 {
        int diag;
        uint32_t tc, tcs;
-       struct rte_pci_device *pci_dev;
+       struct rte_pci_device *pci_dev = IXGBE_DEV_TO_PCI(eth_dev);
+       struct rte_intr_handle *intr_handle = &pci_dev->intr_handle;
        struct ixgbe_hw *hw =
                IXGBE_DEV_PRIVATE_TO_HW(eth_dev->data->dev_private);
        struct ixgbe_vfta *shadow_vfta =
@@ -1419,9 +1589,8 @@ eth_ixgbevf_dev_init(struct rte_eth_dev *eth_dev)
                return 0;
        }
 
-       pci_dev = eth_dev->pci_dev;
-
        rte_eth_copy_pci_info(eth_dev, pci_dev);
+       eth_dev->data->dev_flags = RTE_ETH_DEV_DETACHABLE;
 
        hw->device_id = pci_dev->id.device_id;
        hw->vendor_id = pci_dev->id.vendor_id;
@@ -1513,10 +1682,9 @@ eth_ixgbevf_dev_init(struct rte_eth_dev *eth_dev)
                return -EIO;
        }
 
-       rte_intr_callback_register(&pci_dev->intr_handle,
-                                  ixgbevf_dev_interrupt_handler,
-                                  (void *)eth_dev);
-       rte_intr_enable(&pci_dev->intr_handle);
+       rte_intr_callback_register(intr_handle,
+                                  ixgbevf_dev_interrupt_handler, eth_dev);
+       rte_intr_enable(intr_handle);
        ixgbevf_intr_enable(hw);
 
        PMD_INIT_LOG(DEBUG, "port %d vendorID=0x%x deviceID=0x%x mac.type=%s",
@@ -1531,8 +1699,9 @@ eth_ixgbevf_dev_init(struct rte_eth_dev *eth_dev)
 static int
 eth_ixgbevf_dev_uninit(struct rte_eth_dev *eth_dev)
 {
+       struct rte_pci_device *pci_dev = IXGBE_DEV_TO_PCI(eth_dev);
+       struct rte_intr_handle *intr_handle = &pci_dev->intr_handle;
        struct ixgbe_hw *hw;
-       struct rte_pci_device *pci_dev = eth_dev->pci_dev;
 
        PMD_INIT_FUNC_TRACE();
 
@@ -1554,10 +1723,9 @@ eth_ixgbevf_dev_uninit(struct rte_eth_dev *eth_dev)
        rte_free(eth_dev->data->mac_addrs);
        eth_dev->data->mac_addrs = NULL;
 
-       rte_intr_disable(&pci_dev->intr_handle);
-       rte_intr_callback_unregister(&pci_dev->intr_handle,
-                                    ixgbevf_dev_interrupt_handler,
-                                    (void *)eth_dev);
+       rte_intr_disable(intr_handle);
+       rte_intr_callback_unregister(intr_handle,
+                                    ixgbevf_dev_interrupt_handler, eth_dev);
 
        return 0;
 }
@@ -1565,8 +1733,7 @@ eth_ixgbevf_dev_uninit(struct rte_eth_dev *eth_dev)
 static struct eth_driver rte_ixgbe_pmd = {
        .pci_drv = {
                .id_table = pci_id_ixgbe_map,
-               .drv_flags = RTE_PCI_DRV_NEED_MAPPING | RTE_PCI_DRV_INTR_LSC |
-                       RTE_PCI_DRV_DETACHABLE,
+               .drv_flags = RTE_PCI_DRV_NEED_MAPPING | RTE_PCI_DRV_INTR_LSC,
                .probe = rte_eth_dev_pci_probe,
                .remove = rte_eth_dev_pci_remove,
        },
@@ -1581,7 +1748,7 @@ static struct eth_driver rte_ixgbe_pmd = {
 static struct eth_driver rte_ixgbevf_pmd = {
        .pci_drv = {
                .id_table = pci_id_ixgbevf_map,
-               .drv_flags = RTE_PCI_DRV_NEED_MAPPING | RTE_PCI_DRV_DETACHABLE,
+               .drv_flags = RTE_PCI_DRV_NEED_MAPPING,
                .probe = rte_eth_dev_pci_probe,
                .remove = rte_eth_dev_pci_remove,
        },
@@ -1947,6 +2114,8 @@ ixgbe_vmdq_vlan_hw_filter_enable(struct rte_eth_dev *dev)
 static int
 ixgbe_check_vf_rss_rxq_num(struct rte_eth_dev *dev, uint16_t nb_rx_q)
 {
+       struct rte_pci_device *pci_dev = IXGBE_DEV_TO_PCI(dev);
+
        switch (nb_rx_q) {
        case 1:
        case 2:
@@ -1960,7 +2129,7 @@ ixgbe_check_vf_rss_rxq_num(struct rte_eth_dev *dev, uint16_t nb_rx_q)
        }
 
        RTE_ETH_DEV_SRIOV(dev).nb_q_per_pool = nb_rx_q;
-       RTE_ETH_DEV_SRIOV(dev).def_pool_q_idx = dev->pci_dev->max_vfs * nb_rx_q;
+       RTE_ETH_DEV_SRIOV(dev).def_pool_q_idx = pci_dev->max_vfs * nb_rx_q;
 
        return 0;
 }
@@ -2191,7 +2360,8 @@ ixgbe_dev_start(struct rte_eth_dev *dev)
                IXGBE_DEV_PRIVATE_TO_HW(dev->data->dev_private);
        struct ixgbe_vf_info *vfinfo =
                *IXGBE_DEV_PRIVATE_TO_P_VFDATA(dev->data->dev_private);
-       struct rte_intr_handle *intr_handle = &dev->pci_dev->intr_handle;
+       struct rte_pci_device *pci_dev = IXGBE_DEV_TO_PCI(dev);
+       struct rte_intr_handle *intr_handle = &pci_dev->intr_handle;
        uint32_t intr_vector = 0;
        int err, link_up = 0, negotiate = 0;
        uint32_t speed = 0;
@@ -2291,10 +2461,11 @@ ixgbe_dev_start(struct rte_eth_dev *dev)
 
        /* Restore vf rate limit */
        if (vfinfo != NULL) {
-               for (vf = 0; vf < dev->pci_dev->max_vfs; vf++)
+               for (vf = 0; vf < pci_dev->max_vfs; vf++)
                        for (idx = 0; idx < IXGBE_MAX_QUEUE_NUM_PER_VF; idx++)
                                if (vfinfo[vf].tx_rate[idx] != 0)
-                                       ixgbe_set_vf_rate_limit(dev, vf,
+                                       rte_pmd_ixgbe_set_vf_rate_limit(
+                                               dev->data->port_id, vf,
                                                vfinfo[vf].tx_rate[idx],
                                                1 << idx);
        }
@@ -2366,10 +2537,10 @@ skip_link_setup:
                /* check if lsc interrupt is enabled */
                if (dev->data->dev_conf.intr_conf.lsc != 0)
                        ixgbe_dev_lsc_interrupt_setup(dev);
+               ixgbe_dev_macsec_interrupt_setup(dev);
        } else {
                rte_intr_callback_unregister(intr_handle,
-                                            ixgbe_dev_interrupt_handler,
-                                            (void *)dev);
+                                            ixgbe_dev_interrupt_handler, dev);
                if (dev->data->dev_conf.intr_conf.lsc != 0)
                        PMD_INIT_LOG(INFO, "lsc won't enable because of"
                                     " no intr multiplex\n");
@@ -2408,7 +2579,8 @@ ixgbe_dev_stop(struct rte_eth_dev *dev)
        struct ixgbe_filter_info *filter_info =
                IXGBE_DEV_PRIVATE_TO_FILTER_INFO(dev->data->dev_private);
        struct ixgbe_5tuple_filter *p_5tuple, *p_5tuple_next;
-       struct rte_intr_handle *intr_handle = &dev->pci_dev->intr_handle;
+       struct rte_pci_device *pci_dev = IXGBE_DEV_TO_PCI(dev);
+       struct rte_intr_handle *intr_handle = &pci_dev->intr_handle;
        int vf;
 
        PMD_INIT_FUNC_TRACE();
@@ -2423,8 +2595,7 @@ ixgbe_dev_stop(struct rte_eth_dev *dev)
        /* stop adapter */
        ixgbe_stop_adapter(hw);
 
-       for (vf = 0; vfinfo != NULL &&
-                    vf < dev->pci_dev->max_vfs; vf++)
+       for (vf = 0; vfinfo != NULL && vf < pci_dev->max_vfs; vf++)
                vfinfo[vf].clear_to_send = false;
 
        if (hw->mac.ops.get_media_type(hw) == ixgbe_media_type_copper) {
@@ -2557,6 +2728,7 @@ ixgbe_dev_close(struct rte_eth_dev *dev)
 static void
 ixgbe_read_stats_registers(struct ixgbe_hw *hw,
                           struct ixgbe_hw_stats *hw_stats,
+                          struct ixgbe_macsec_stats *macsec_stats,
                           uint64_t *total_missed_rx, uint64_t *total_qbrc,
                           uint64_t *total_qprc, uint64_t *total_qprdc)
 {
@@ -2564,9 +2736,9 @@ ixgbe_read_stats_registers(struct ixgbe_hw *hw,
        uint32_t delta_gprc = 0;
        unsigned i;
        /* Workaround for RX byte count not including CRC bytes when CRC
-+       * strip is enabled. CRC bytes are removed from counters when crc_strip
+        * strip is enabled. CRC bytes are removed from counters when crc_strip
         * is disabled.
-+       */
+        */
        int crc_strip = (IXGBE_READ_REG(hw, IXGBE_HLREG0) &
                        IXGBE_HLREG0_RXCRCSTRP);
 
@@ -2726,6 +2898,40 @@ ixgbe_read_stats_registers(struct ixgbe_hw *hw,
        /* Flow Director Stats registers */
        hw_stats->fdirmatch += IXGBE_READ_REG(hw, IXGBE_FDIRMATCH);
        hw_stats->fdirmiss += IXGBE_READ_REG(hw, IXGBE_FDIRMISS);
+
+       /* MACsec Stats registers */
+       macsec_stats->out_pkts_untagged += IXGBE_READ_REG(hw, IXGBE_LSECTXUT);
+       macsec_stats->out_pkts_encrypted +=
+               IXGBE_READ_REG(hw, IXGBE_LSECTXPKTE);
+       macsec_stats->out_pkts_protected +=
+               IXGBE_READ_REG(hw, IXGBE_LSECTXPKTP);
+       macsec_stats->out_octets_encrypted +=
+               IXGBE_READ_REG(hw, IXGBE_LSECTXOCTE);
+       macsec_stats->out_octets_protected +=
+               IXGBE_READ_REG(hw, IXGBE_LSECTXOCTP);
+       macsec_stats->in_pkts_untagged += IXGBE_READ_REG(hw, IXGBE_LSECRXUT);
+       macsec_stats->in_pkts_badtag += IXGBE_READ_REG(hw, IXGBE_LSECRXBAD);
+       macsec_stats->in_pkts_nosci += IXGBE_READ_REG(hw, IXGBE_LSECRXNOSCI);
+       macsec_stats->in_pkts_unknownsci +=
+               IXGBE_READ_REG(hw, IXGBE_LSECRXUNSCI);
+       macsec_stats->in_octets_decrypted +=
+               IXGBE_READ_REG(hw, IXGBE_LSECRXOCTD);
+       macsec_stats->in_octets_validated +=
+               IXGBE_READ_REG(hw, IXGBE_LSECRXOCTV);
+       macsec_stats->in_pkts_unchecked += IXGBE_READ_REG(hw, IXGBE_LSECRXUNCH);
+       macsec_stats->in_pkts_delayed += IXGBE_READ_REG(hw, IXGBE_LSECRXDELAY);
+       macsec_stats->in_pkts_late += IXGBE_READ_REG(hw, IXGBE_LSECRXLATE);
+       for (i = 0; i < 2; i++) {
+               macsec_stats->in_pkts_ok +=
+                       IXGBE_READ_REG(hw, IXGBE_LSECRXOK(i));
+               macsec_stats->in_pkts_invalid +=
+                       IXGBE_READ_REG(hw, IXGBE_LSECRXINV(i));
+               macsec_stats->in_pkts_notvalid +=
+                       IXGBE_READ_REG(hw, IXGBE_LSECRXNV(i));
+       }
+       macsec_stats->in_pkts_unusedsa += IXGBE_READ_REG(hw, IXGBE_LSECRXUNSA);
+       macsec_stats->in_pkts_notusingsa +=
+               IXGBE_READ_REG(hw, IXGBE_LSECRXNUSA);
 }
 
 /*
@@ -2738,6 +2944,9 @@ ixgbe_dev_stats_get(struct rte_eth_dev *dev, struct rte_eth_stats *stats)
                        IXGBE_DEV_PRIVATE_TO_HW(dev->data->dev_private);
        struct ixgbe_hw_stats *hw_stats =
                        IXGBE_DEV_PRIVATE_TO_STATS(dev->data->dev_private);
+       struct ixgbe_macsec_stats *macsec_stats =
+                       IXGBE_DEV_PRIVATE_TO_MACSEC_STATS(
+                               dev->data->dev_private);
        uint64_t total_missed_rx, total_qbrc, total_qprc, total_qprdc;
        unsigned i;
 
@@ -2746,8 +2955,8 @@ ixgbe_dev_stats_get(struct rte_eth_dev *dev, struct rte_eth_stats *stats)
        total_qprc = 0;
        total_qprdc = 0;
 
-       ixgbe_read_stats_registers(hw, hw_stats, &total_missed_rx, &total_qbrc,
-                       &total_qprc, &total_qprdc);
+       ixgbe_read_stats_registers(hw, hw_stats, macsec_stats, &total_missed_rx,
+                       &total_qbrc, &total_qprc, &total_qprdc);
 
        if (stats == NULL)
                return;
@@ -2799,7 +3008,7 @@ ixgbe_dev_stats_reset(struct rte_eth_dev *dev)
 /* This function calculates the number of xstats based on the current config */
 static unsigned
 ixgbe_xstats_calc_num(void) {
-       return IXGBE_NB_HW_STATS +
+       return IXGBE_NB_HW_STATS + IXGBE_NB_MACSEC_STATS +
                (IXGBE_NB_RXQ_PRIO_STATS * IXGBE_NB_RXQ_PRIO_VALUES) +
                (IXGBE_NB_TXQ_PRIO_STATS * IXGBE_NB_TXQ_PRIO_VALUES);
 }
@@ -2826,6 +3035,15 @@ static int ixgbe_dev_xstats_get_names(__rte_unused struct rte_eth_dev *dev,
                        count++;
                }
 
+               /* MACsec Stats */
+               for (i = 0; i < IXGBE_NB_MACSEC_STATS; i++) {
+                       snprintf(xstats_names[count].name,
+                               sizeof(xstats_names[count].name),
+                               "%s",
+                               rte_ixgbe_macsec_strings[i].name);
+                       count++;
+               }
+
                /* RX Priority Stats */
                for (stat = 0; stat < IXGBE_NB_RXQ_PRIO_STATS; stat++) {
                        for (i = 0; i < IXGBE_NB_RXQ_PRIO_VALUES; i++) {
@@ -2875,6 +3093,9 @@ ixgbe_dev_xstats_get(struct rte_eth_dev *dev, struct rte_eth_xstat *xstats,
                        IXGBE_DEV_PRIVATE_TO_HW(dev->data->dev_private);
        struct ixgbe_hw_stats *hw_stats =
                        IXGBE_DEV_PRIVATE_TO_STATS(dev->data->dev_private);
+       struct ixgbe_macsec_stats *macsec_stats =
+                       IXGBE_DEV_PRIVATE_TO_MACSEC_STATS(
+                               dev->data->dev_private);
        uint64_t total_missed_rx, total_qbrc, total_qprc, total_qprdc;
        unsigned i, stat, count = 0;
 
@@ -2888,8 +3109,8 @@ ixgbe_dev_xstats_get(struct rte_eth_dev *dev, struct rte_eth_xstat *xstats,
        total_qprc = 0;
        total_qprdc = 0;
 
-       ixgbe_read_stats_registers(hw, hw_stats, &total_missed_rx, &total_qbrc,
-                                  &total_qprc, &total_qprdc);
+       ixgbe_read_stats_registers(hw, hw_stats, macsec_stats, &total_missed_rx,
+                       &total_qbrc, &total_qprc, &total_qprdc);
 
        /* If this is a reset xstats is NULL, and we have cleared the
         * registers by reading them.
@@ -2902,6 +3123,15 @@ ixgbe_dev_xstats_get(struct rte_eth_dev *dev, struct rte_eth_xstat *xstats,
        for (i = 0; i < IXGBE_NB_HW_STATS; i++) {
                xstats[count].value = *(uint64_t *)(((char *)hw_stats) +
                                rte_ixgbe_stats_strings[i].offset);
+               xstats[count].id = count;
+               count++;
+       }
+
+       /* MACsec Stats */
+       for (i = 0; i < IXGBE_NB_MACSEC_STATS; i++) {
+               xstats[count].value = *(uint64_t *)(((char *)macsec_stats) +
+                               rte_ixgbe_macsec_strings[i].offset);
+               xstats[count].id = count;
                count++;
        }
 
@@ -2911,6 +3141,7 @@ ixgbe_dev_xstats_get(struct rte_eth_dev *dev, struct rte_eth_xstat *xstats,
                        xstats[count].value = *(uint64_t *)(((char *)hw_stats) +
                                        rte_ixgbe_rxq_strings[stat].offset +
                                        (sizeof(uint64_t) * i));
+                       xstats[count].id = count;
                        count++;
                }
        }
@@ -2921,6 +3152,7 @@ ixgbe_dev_xstats_get(struct rte_eth_dev *dev, struct rte_eth_xstat *xstats,
                        xstats[count].value = *(uint64_t *)(((char *)hw_stats) +
                                        rte_ixgbe_txq_strings[stat].offset +
                                        (sizeof(uint64_t) * i));
+                       xstats[count].id = count;
                        count++;
                }
        }
@@ -2932,6 +3164,9 @@ ixgbe_dev_xstats_reset(struct rte_eth_dev *dev)
 {
        struct ixgbe_hw_stats *stats =
                        IXGBE_DEV_PRIVATE_TO_STATS(dev->data->dev_private);
+       struct ixgbe_macsec_stats *macsec_stats =
+                       IXGBE_DEV_PRIVATE_TO_MACSEC_STATS(
+                               dev->data->dev_private);
 
        unsigned count = ixgbe_xstats_calc_num();
 
@@ -2940,6 +3175,7 @@ ixgbe_dev_xstats_reset(struct rte_eth_dev *dev)
 
        /* Reset software totals */
        memset(stats, 0, sizeof(*stats));
+       memset(macsec_stats, 0, sizeof(*macsec_stats));
 }
 
 static void
@@ -3028,12 +3264,35 @@ ixgbevf_dev_stats_reset(struct rte_eth_dev *dev)
        hw_stats->vfgotc = 0;
 }
 
+static int
+ixgbe_fw_version_get(struct rte_eth_dev *dev, char *fw_version, size_t fw_size)
+{
+       struct ixgbe_hw *hw = IXGBE_DEV_PRIVATE_TO_HW(dev->data->dev_private);
+       u16 eeprom_verh, eeprom_verl;
+       u32 etrack_id;
+       int ret;
+
+       ixgbe_read_eeprom(hw, 0x2e, &eeprom_verh);
+       ixgbe_read_eeprom(hw, 0x2d, &eeprom_verl);
+
+       etrack_id = (eeprom_verh << 16) | eeprom_verl;
+       ret = snprintf(fw_version, fw_size, "0x%08x", etrack_id);
+
+       ret += 1; /* add the size of '\0' */
+       if (fw_size < (u32)ret)
+               return ret;
+       else
+               return 0;
+}
+
 static void
 ixgbe_dev_info_get(struct rte_eth_dev *dev, struct rte_eth_dev_info *dev_info)
 {
+       struct rte_pci_device *pci_dev = IXGBE_DEV_TO_PCI(dev);
        struct ixgbe_hw *hw = IXGBE_DEV_PRIVATE_TO_HW(dev->data->dev_private);
        struct rte_eth_conf *dev_conf = &dev->data->dev_conf;
 
+       dev_info->pci_dev = pci_dev;
        dev_info->max_rx_queues = (uint16_t)hw->mac.max_rx_queues;
        dev_info->max_tx_queues = (uint16_t)hw->mac.max_tx_queues;
        if (RTE_ETH_DEV_SRIOV(dev).active == 0) {
@@ -3049,7 +3308,7 @@ ixgbe_dev_info_get(struct rte_eth_dev *dev, struct rte_eth_dev_info *dev_info)
        dev_info->max_rx_pktlen = 15872; /* includes CRC, cf MAXFRS register */
        dev_info->max_mac_addrs = hw->mac.num_rar_entries;
        dev_info->max_hash_mac_addrs = IXGBE_VMDQ_NUM_UC_MAC;
-       dev_info->max_vfs = dev->pci_dev->max_vfs;
+       dev_info->max_vfs = pci_dev->max_vfs;
        if (hw->mac.type == ixgbe_mac_82598EB)
                dev_info->max_vmdq_pools = ETH_16_POOLS;
        else
@@ -3070,6 +3329,10 @@ ixgbe_dev_info_get(struct rte_eth_dev *dev, struct rte_eth_dev_info *dev_info)
            !RTE_ETH_DEV_SRIOV(dev).active)
                dev_info->rx_offload_capa |= DEV_RX_OFFLOAD_TCP_LRO;
 
+       if (hw->mac.type == ixgbe_mac_82599EB ||
+           hw->mac.type == ixgbe_mac_X540)
+               dev_info->rx_offload_capa |= DEV_RX_OFFLOAD_MACSEC_STRIP;
+
        if (hw->mac.type == ixgbe_mac_X550 ||
            hw->mac.type == ixgbe_mac_X550EM_x ||
            hw->mac.type == ixgbe_mac_X550EM_a)
@@ -3083,6 +3346,10 @@ ixgbe_dev_info_get(struct rte_eth_dev *dev, struct rte_eth_dev_info *dev_info)
                DEV_TX_OFFLOAD_SCTP_CKSUM  |
                DEV_TX_OFFLOAD_TCP_TSO;
 
+       if (hw->mac.type == ixgbe_mac_82599EB ||
+           hw->mac.type == ixgbe_mac_X540)
+               dev_info->tx_offload_capa |= DEV_TX_OFFLOAD_MACSEC_INSERT;
+
        if (hw->mac.type == ixgbe_mac_X550 ||
            hw->mac.type == ixgbe_mac_X550EM_x ||
            hw->mac.type == ixgbe_mac_X550EM_a)
@@ -3163,15 +3430,17 @@ static void
 ixgbevf_dev_info_get(struct rte_eth_dev *dev,
                     struct rte_eth_dev_info *dev_info)
 {
+       struct rte_pci_device *pci_dev = IXGBE_DEV_TO_PCI(dev);
        struct ixgbe_hw *hw = IXGBE_DEV_PRIVATE_TO_HW(dev->data->dev_private);
 
+       dev_info->pci_dev = pci_dev;
        dev_info->max_rx_queues = (uint16_t)hw->mac.max_rx_queues;
        dev_info->max_tx_queues = (uint16_t)hw->mac.max_tx_queues;
        dev_info->min_rx_bufsize = 1024; /* cf BSIZEPACKET in SRRCTL reg */
        dev_info->max_rx_pktlen = 15872; /* includes CRC, cf MAXFRS reg */
        dev_info->max_mac_addrs = hw->mac.num_rar_entries;
        dev_info->max_hash_mac_addrs = IXGBE_VMDQ_NUM_UC_MAC;
-       dev_info->max_vfs = dev->pci_dev->max_vfs;
+       dev_info->max_vfs = pci_dev->max_vfs;
        if (hw->mac.type == ixgbe_mac_82598EB)
                dev_info->max_vmdq_pools = ETH_16_POOLS;
        else
@@ -3378,6 +3647,28 @@ ixgbe_dev_rxq_interrupt_setup(struct rte_eth_dev *dev)
        return 0;
 }
 
+/**
+ * It clears the interrupt causes and enables the interrupt.
+ * It will be called once only during nic initialized.
+ *
+ * @param dev
+ *  Pointer to struct rte_eth_dev.
+ *
+ * @return
+ *  - On success, zero.
+ *  - On failure, a negative value.
+ */
+static int
+ixgbe_dev_macsec_interrupt_setup(struct rte_eth_dev *dev)
+{
+       struct ixgbe_interrupt *intr =
+               IXGBE_DEV_PRIVATE_TO_INTR(dev->data->dev_private);
+
+       intr->mask |= IXGBE_EICR_LINKSEC;
+
+       return 0;
+}
+
 /*
  * It reads ICR and sets flag (IXGBE_EICR_LSC) for the link_update.
  *
@@ -3412,6 +3703,9 @@ ixgbe_dev_interrupt_get_status(struct rte_eth_dev *dev)
        if (eicr & IXGBE_EICR_MAILBOX)
                intr->flags |= IXGBE_FLAG_MAILBOX;
 
+       if (eicr & IXGBE_EICR_LINKSEC)
+               intr->flags |= IXGBE_FLAG_MACSEC;
+
        if (hw->mac.type ==  ixgbe_mac_X550EM_x &&
            hw->phy.type == ixgbe_phy_x550em_ext_t &&
            (eicr & IXGBE_EICR_GPI_SDP0_X550EM_x))
@@ -3433,6 +3727,7 @@ ixgbe_dev_interrupt_get_status(struct rte_eth_dev *dev)
 static void
 ixgbe_dev_link_status_print(struct rte_eth_dev *dev)
 {
+       struct rte_pci_device *pci_dev = IXGBE_DEV_TO_PCI(dev);
        struct rte_eth_link link;
 
        memset(&link, 0, sizeof(link));
@@ -3448,10 +3743,10 @@ ixgbe_dev_link_status_print(struct rte_eth_dev *dev)
                                (int)(dev->data->port_id));
        }
        PMD_INIT_LOG(DEBUG, "PCI Address: " PCI_PRI_FMT,
-                               dev->pci_dev->addr.domain,
-                               dev->pci_dev->addr.bus,
-                               dev->pci_dev->addr.devid,
-                               dev->pci_dev->addr.function);
+                               pci_dev->addr.domain,
+                               pci_dev->addr.bus,
+                               pci_dev->addr.devid,
+                               pci_dev->addr.function);
 }
 
 /*
@@ -3465,7 +3760,8 @@ ixgbe_dev_link_status_print(struct rte_eth_dev *dev)
  *  - On failure, a negative value.
  */
 static int
-ixgbe_dev_interrupt_action(struct rte_eth_dev *dev)
+ixgbe_dev_interrupt_action(struct rte_eth_dev *dev,
+                          struct rte_intr_handle *intr_handle)
 {
        struct ixgbe_interrupt *intr =
                IXGBE_DEV_PRIVATE_TO_INTR(dev->data->dev_private);
@@ -3515,7 +3811,7 @@ ixgbe_dev_interrupt_action(struct rte_eth_dev *dev)
        } else {
                PMD_DRV_LOG(DEBUG, "enable intr immediately");
                ixgbe_enable_intr(dev);
-               rte_intr_enable(&(dev->pci_dev->intr_handle));
+               rte_intr_enable(intr_handle);
        }
 
 
@@ -3540,6 +3836,8 @@ static void
 ixgbe_dev_interrupt_delayed_handler(void *param)
 {
        struct rte_eth_dev *dev = (struct rte_eth_dev *)param;
+       struct rte_pci_device *pci_dev = IXGBE_DEV_TO_PCI(dev);
+       struct rte_intr_handle *intr_handle = &pci_dev->intr_handle;
        struct ixgbe_interrupt *intr =
                IXGBE_DEV_PRIVATE_TO_INTR(dev->data->dev_private);
        struct ixgbe_hw *hw =
@@ -3562,9 +3860,15 @@ ixgbe_dev_interrupt_delayed_handler(void *param)
                _rte_eth_dev_callback_process(dev, RTE_ETH_EVENT_INTR_LSC, NULL);
        }
 
+       if (intr->flags & IXGBE_FLAG_MACSEC) {
+               _rte_eth_dev_callback_process(dev, RTE_ETH_EVENT_MACSEC,
+                                             NULL);
+               intr->flags &= ~IXGBE_FLAG_MACSEC;
+       }
+
        PMD_DRV_LOG(DEBUG, "enable intr in delayed handler S[%08x]", eicr);
        ixgbe_enable_intr(dev);
-       rte_intr_enable(&(dev->pci_dev->intr_handle));
+       rte_intr_enable(intr_handle);
 }
 
 /**
@@ -3580,13 +3884,13 @@ ixgbe_dev_interrupt_delayed_handler(void *param)
  *  void
  */
 static void
-ixgbe_dev_interrupt_handler(__rte_unused struct rte_intr_handle *handle,
+ixgbe_dev_interrupt_handler(struct rte_intr_handle *handle,
                            void *param)
 {
        struct rte_eth_dev *dev = (struct rte_eth_dev *)param;
 
        ixgbe_dev_interrupt_get_status(dev);
-       ixgbe_dev_interrupt_action(dev);
+       ixgbe_dev_interrupt_action(dev, handle);
 }
 
 static int
@@ -4048,6 +4352,18 @@ ixgbe_set_default_mac_addr(struct rte_eth_dev *dev, struct ether_addr *addr)
        ixgbe_add_rar(dev, addr, 0, 0);
 }
 
+static int
+is_ixgbe_pmd(const char *driver_name)
+{
+       if (!strstr(driver_name, "ixgbe"))
+               return -ENOTSUP;
+
+       if (strstr(driver_name, "ixgbe_vf"))
+               return -ENOTSUP;
+
+       return 0;
+}
+
 int
 rte_pmd_ixgbe_set_vf_mac_addr(uint8_t port, uint16_t vf,
                struct ether_addr *mac_addr)
@@ -4064,6 +4380,9 @@ rte_pmd_ixgbe_set_vf_mac_addr(uint8_t port, uint16_t vf,
        dev = &rte_eth_devices[port];
        rte_eth_dev_info_get(port, &dev_info);
 
+       if (is_ixgbe_pmd(dev_info.driver_name) != 0)
+               return -ENOTSUP;
+
        if (vf >= dev_info.max_vfs)
                return -EINVAL;
 
@@ -4196,7 +4515,8 @@ ixgbevf_dev_start(struct rte_eth_dev *dev)
        struct ixgbe_hw *hw =
                IXGBE_DEV_PRIVATE_TO_HW(dev->data->dev_private);
        uint32_t intr_vector = 0;
-       struct rte_intr_handle *intr_handle = &dev->pci_dev->intr_handle;
+       struct rte_pci_device *pci_dev = IXGBE_DEV_TO_PCI(dev);
+       struct rte_intr_handle *intr_handle = &pci_dev->intr_handle;
 
        int err, mask = 0;
 
@@ -4259,7 +4579,8 @@ static void
 ixgbevf_dev_stop(struct rte_eth_dev *dev)
 {
        struct ixgbe_hw *hw = IXGBE_DEV_PRIVATE_TO_HW(dev->data->dev_private);
-       struct rte_intr_handle *intr_handle = &dev->pci_dev->intr_handle;
+       struct rte_pci_device *pci_dev = IXGBE_DEV_TO_PCI(dev);
+       struct rte_intr_handle *intr_handle = &pci_dev->intr_handle;
 
        PMD_INIT_FUNC_TRACE();
 
@@ -4401,14 +4722,14 @@ ixgbevf_vlan_offload_set(struct rte_eth_dev *dev, int mask)
 }
 
 static int
-ixgbe_vmdq_mode_check(struct ixgbe_hw *hw)
+ixgbe_vt_check(struct ixgbe_hw *hw)
 {
        uint32_t reg_val;
 
-       /* we only need to do this if VMDq is enabled */
+       /* if Virtualization Technology is enabled */
        reg_val = IXGBE_READ_REG(hw, IXGBE_VT_CTL);
        if (!(reg_val & IXGBE_VT_CTL_VT_ENABLE)) {
-               PMD_INIT_LOG(ERR, "VMDq must be enabled for this setting");
+               PMD_INIT_LOG(ERR, "VT must be enabled for this setting");
                return -1;
        }
 
@@ -4546,132 +4867,6 @@ ixgbe_convert_vm_rx_mask_to_val(uint16_t rx_mask, uint32_t orig_val)
        return new_val;
 }
 
-static int
-ixgbe_set_pool_rx_mode(struct rte_eth_dev *dev, uint16_t pool,
-                              uint16_t rx_mask, uint8_t on)
-{
-       int val = 0;
-
-       struct ixgbe_hw *hw =
-               IXGBE_DEV_PRIVATE_TO_HW(dev->data->dev_private);
-       uint32_t vmolr = IXGBE_READ_REG(hw, IXGBE_VMOLR(pool));
-
-       if (hw->mac.type == ixgbe_mac_82598EB) {
-               PMD_INIT_LOG(ERR, "setting VF receive mode set should be done"
-                            " on 82599 hardware and newer");
-               return -ENOTSUP;
-       }
-       if (ixgbe_vmdq_mode_check(hw) < 0)
-               return -ENOTSUP;
-
-       val = ixgbe_convert_vm_rx_mask_to_val(rx_mask, val);
-
-       if (on)
-               vmolr |= val;
-       else
-               vmolr &= ~val;
-
-       IXGBE_WRITE_REG(hw, IXGBE_VMOLR(pool), vmolr);
-
-       return 0;
-}
-
-static int
-ixgbe_set_pool_rx(struct rte_eth_dev *dev, uint16_t pool, uint8_t on)
-{
-       uint32_t reg, addr;
-       uint32_t val;
-       const uint8_t bit1 = 0x1;
-
-       struct ixgbe_hw *hw =
-               IXGBE_DEV_PRIVATE_TO_HW(dev->data->dev_private);
-
-       if (ixgbe_vmdq_mode_check(hw) < 0)
-               return -ENOTSUP;
-
-       if (pool >= ETH_64_POOLS)
-               return -EINVAL;
-
-       /* for pool >= 32, set bit in PFVFRE[1], otherwise PFVFRE[0] */
-       if (pool >= 32) {
-               addr = IXGBE_VFRE(1);
-               val = bit1 << (pool - 32);
-       } else {
-               addr = IXGBE_VFRE(0);
-               val = bit1 << pool;
-       }
-
-       reg = IXGBE_READ_REG(hw, addr);
-
-       if (on)
-               reg |= val;
-       else
-               reg &= ~val;
-
-       IXGBE_WRITE_REG(hw, addr, reg);
-
-       return 0;
-}
-
-static int
-ixgbe_set_pool_tx(struct rte_eth_dev *dev, uint16_t pool, uint8_t on)
-{
-       uint32_t reg, addr;
-       uint32_t val;
-       const uint8_t bit1 = 0x1;
-
-       struct ixgbe_hw *hw =
-               IXGBE_DEV_PRIVATE_TO_HW(dev->data->dev_private);
-
-       if (ixgbe_vmdq_mode_check(hw) < 0)
-               return -ENOTSUP;
-
-       if (pool >= ETH_64_POOLS)
-               return -EINVAL;
-
-       /* for pool >= 32, set bit in PFVFTE[1], otherwise PFVFTE[0] */
-       if (pool >= 32) {
-               addr = IXGBE_VFTE(1);
-               val = bit1 << (pool - 32);
-       } else {
-               addr = IXGBE_VFTE(0);
-               val = bit1 << pool;
-       }
-
-       reg = IXGBE_READ_REG(hw, addr);
-
-       if (on)
-               reg |= val;
-       else
-               reg &= ~val;
-
-       IXGBE_WRITE_REG(hw, addr, reg);
-
-       return 0;
-}
-
-static int
-ixgbe_set_pool_vlan_filter(struct rte_eth_dev *dev, uint16_t vlan,
-                       uint64_t pool_mask, uint8_t vlan_on)
-{
-       int ret = 0;
-       uint16_t pool_idx;
-       struct ixgbe_hw *hw =
-               IXGBE_DEV_PRIVATE_TO_HW(dev->data->dev_private);
-
-       if (ixgbe_vmdq_mode_check(hw) < 0)
-               return -ENOTSUP;
-       for (pool_idx = 0; pool_idx < ETH_64_POOLS; pool_idx++) {
-               if (pool_mask & ((uint64_t)(1ULL << pool_idx))) {
-                       ret = hw->mac.ops.set_vfta(hw, vlan, pool_idx,
-                                                  vlan_on, false);
-                       if (ret < 0)
-                               return ret;
-               }
-       }
-
-       return ret;
-}
 
 int
 rte_pmd_ixgbe_set_vf_vlan_anti_spoof(uint8_t port, uint16_t vf, uint8_t on)
@@ -4686,6 +4881,9 @@ rte_pmd_ixgbe_set_vf_vlan_anti_spoof(uint8_t port, uint16_t vf, uint8_t on)
        dev = &rte_eth_devices[port];
        rte_eth_dev_info_get(port, &dev_info);
 
+       if (is_ixgbe_pmd(dev_info.driver_name) != 0)
+               return -ENOTSUP;
+
        if (vf >= dev_info.max_vfs)
                return -EINVAL;
 
@@ -4713,6 +4911,9 @@ rte_pmd_ixgbe_set_vf_mac_anti_spoof(uint8_t port, uint16_t vf, uint8_t on)
        dev = &rte_eth_devices[port];
        rte_eth_dev_info_get(port, &dev_info);
 
+       if (is_ixgbe_pmd(dev_info.driver_name) != 0)
+               return -ENOTSUP;
+
        if (vf >= dev_info.max_vfs)
                return -EINVAL;
 
@@ -4739,10 +4940,13 @@ rte_pmd_ixgbe_set_vf_vlan_insert(uint8_t port, uint16_t vf, uint16_t vlan_id)
        dev = &rte_eth_devices[port];
        rte_eth_dev_info_get(port, &dev_info);
 
+       if (is_ixgbe_pmd(dev_info.driver_name) != 0)
+               return -ENOTSUP;
+
        if (vf >= dev_info.max_vfs)
                return -EINVAL;
 
-       if (vlan_id > 4095)
+       if (vlan_id > ETHER_MAX_VLAN_ID)
                return -EINVAL;
 
        hw = IXGBE_DEV_PRIVATE_TO_HW(dev->data->dev_private);
@@ -4765,10 +4969,15 @@ rte_pmd_ixgbe_set_tx_loopback(uint8_t port, uint8_t on)
        struct ixgbe_hw *hw;
        uint32_t ctrl;
        struct rte_eth_dev *dev;
+       struct rte_eth_dev_info dev_info;
 
        RTE_ETH_VALID_PORTID_OR_ERR_RET(port, -ENODEV);
 
        dev = &rte_eth_devices[port];
+       rte_eth_dev_info_get(port, &dev_info);
+
+       if (is_ixgbe_pmd(dev_info.driver_name) != 0)
+               return -ENOTSUP;
 
        if (on > 1)
                return -EINVAL;
@@ -4794,10 +5003,15 @@ rte_pmd_ixgbe_set_all_queues_drop_en(uint8_t port, uint8_t on)
        int i;
        int num_queues = (int)(IXGBE_QDE_IDX_MASK >> IXGBE_QDE_IDX_SHIFT);
        struct rte_eth_dev *dev;
+       struct rte_eth_dev_info dev_info;
 
        RTE_ETH_VALID_PORTID_OR_ERR_RET(port, -ENODEV);
 
        dev = &rte_eth_devices[port];
+       rte_eth_dev_info_get(port, &dev_info);
+
+       if (is_ixgbe_pmd(dev_info.driver_name) != 0)
+               return -ENOTSUP;
 
        if (on > 1)
                return -EINVAL;
@@ -4826,6 +5040,9 @@ rte_pmd_ixgbe_set_vf_split_drop_en(uint8_t port, uint16_t vf, uint8_t on)
        dev = &rte_eth_devices[port];
        rte_eth_dev_info_get(port, &dev_info);
 
+       if (is_ixgbe_pmd(dev_info.driver_name) != 0)
+               return -ENOTSUP;
+
        /* only support VF's 0 to 63 */
        if ((vf >= dev_info.max_vfs) || (vf > 63))
                return -EINVAL;
@@ -4858,6 +5075,9 @@ rte_pmd_ixgbe_set_vf_vlan_stripq(uint8_t port, uint16_t vf, uint8_t on)
        dev = &rte_eth_devices[port];
        rte_eth_dev_info_get(port, &dev_info);
 
+       if (is_ixgbe_pmd(dev_info.driver_name) != 0)
+               return -ENOTSUP;
+
        if (vf >= dev_info.max_vfs)
                return -EINVAL;
 
@@ -4883,29 +5103,294 @@ rte_pmd_ixgbe_set_vf_vlan_stripq(uint8_t port, uint16_t vf, uint8_t on)
        return 0;
 }
 
-#define IXGBE_MRCTL_VPME  0x01 /* Virtual Pool Mirroring. */
-#define IXGBE_MRCTL_UPME  0x02 /* Uplink Port Mirroring. */
-#define IXGBE_MRCTL_DPME  0x04 /* Downlink Port Mirroring. */
-#define IXGBE_MRCTL_VLME  0x08 /* VLAN Mirroring. */
-#define IXGBE_INVALID_MIRROR_TYPE(mirror_type) \
-       ((mirror_type) & ~(uint8_t)(ETH_MIRROR_VIRTUAL_POOL_UP | \
-       ETH_MIRROR_UPLINK_PORT | ETH_MIRROR_DOWNLINK_PORT | ETH_MIRROR_VLAN))
-
-static int
-ixgbe_mirror_rule_set(struct rte_eth_dev *dev,
-                       struct rte_eth_mirror_conf *mirror_conf,
-                       uint8_t rule_id, uint8_t on)
+int
+rte_pmd_ixgbe_set_vf_rxmode(uint8_t port, uint16_t vf, uint16_t rx_mask, uint8_t on)
 {
-       uint32_t mr_ctl, vlvf;
-       uint32_t mp_lsb = 0;
-       uint32_t mv_msb = 0;
-       uint32_t mv_lsb = 0;
-       uint32_t mp_msb = 0;
-       uint8_t i = 0;
-       int reg_index = 0;
-       uint64_t vlan_mask = 0;
-
-       const uint8_t pool_mask_offset = 32;
+       int val = 0;
+       struct rte_eth_dev *dev;
+       struct rte_eth_dev_info dev_info;
+       struct ixgbe_hw *hw;
+       uint32_t vmolr;
+
+       RTE_ETH_VALID_PORTID_OR_ERR_RET(port, -ENODEV);
+
+       dev = &rte_eth_devices[port];
+       rte_eth_dev_info_get(port, &dev_info);
+
+       if (is_ixgbe_pmd(dev_info.driver_name) != 0)
+               return -ENOTSUP;
+
+       if (vf >= dev_info.max_vfs)
+               return -EINVAL;
+
+       if (on > 1)
+               return -EINVAL;
+
+       hw = IXGBE_DEV_PRIVATE_TO_HW(dev->data->dev_private);
+       vmolr = IXGBE_READ_REG(hw, IXGBE_VMOLR(vf));
+
+       if (hw->mac.type == ixgbe_mac_82598EB) {
+               PMD_INIT_LOG(ERR, "setting VF receive mode set should be done"
+                            " on 82599 hardware and newer");
+               return -ENOTSUP;
+       }
+       if (ixgbe_vt_check(hw) < 0)
+               return -ENOTSUP;
+
+       val = ixgbe_convert_vm_rx_mask_to_val(rx_mask, val);
+
+       if (on)
+               vmolr |= val;
+       else
+               vmolr &= ~val;
+
+       IXGBE_WRITE_REG(hw, IXGBE_VMOLR(vf), vmolr);
+
+       return 0;
+}
+
+int
+rte_pmd_ixgbe_set_vf_rx(uint8_t port, uint16_t vf, uint8_t on)
+{
+       struct rte_eth_dev *dev;
+       struct rte_eth_dev_info dev_info;
+       uint32_t reg, addr;
+       uint32_t val;
+       const uint8_t bit1 = 0x1;
+       struct ixgbe_hw *hw;
+
+       RTE_ETH_VALID_PORTID_OR_ERR_RET(port, -ENODEV);
+
+       dev = &rte_eth_devices[port];
+       rte_eth_dev_info_get(port, &dev_info);
+
+       if (is_ixgbe_pmd(dev_info.driver_name) != 0)
+               return -ENOTSUP;
+
+       if (vf >= dev_info.max_vfs)
+               return -EINVAL;
+
+       if (on > 1)
+               return -EINVAL;
+
+       hw = IXGBE_DEV_PRIVATE_TO_HW(dev->data->dev_private);
+
+       if (ixgbe_vt_check(hw) < 0)
+               return -ENOTSUP;
+
+       /* for vf >= 32, set bit in PFVFRE[1], otherwise PFVFRE[0] */
+       if (vf >= 32) {
+               addr = IXGBE_VFRE(1);
+               val = bit1 << (vf - 32);
+       } else {
+               addr = IXGBE_VFRE(0);
+               val = bit1 << vf;
+       }
+
+       reg = IXGBE_READ_REG(hw, addr);
+
+       if (on)
+               reg |= val;
+       else
+               reg &= ~val;
+
+       IXGBE_WRITE_REG(hw, addr, reg);
+
+       return 0;
+}
+
+int
+rte_pmd_ixgbe_set_vf_tx(uint8_t port, uint16_t vf, uint8_t on)
+{
+       struct rte_eth_dev *dev;
+       struct rte_eth_dev_info dev_info;
+       uint32_t reg, addr;
+       uint32_t val;
+       const uint8_t bit1 = 0x1;
+
+       struct ixgbe_hw *hw;
+
+       RTE_ETH_VALID_PORTID_OR_ERR_RET(port, -ENODEV);
+
+       dev = &rte_eth_devices[port];
+       rte_eth_dev_info_get(port, &dev_info);
+
+       if (is_ixgbe_pmd(dev_info.driver_name) != 0)
+               return -ENOTSUP;
+
+       if (vf >= dev_info.max_vfs)
+               return -EINVAL;
+
+       if (on > 1)
+               return -EINVAL;
+
+       hw = IXGBE_DEV_PRIVATE_TO_HW(dev->data->dev_private);
+       if (ixgbe_vt_check(hw) < 0)
+               return -ENOTSUP;
+
+       /* for vf >= 32, set bit in PFVFTE[1], otherwise PFVFTE[0] */
+       if (vf >= 32) {
+               addr = IXGBE_VFTE(1);
+               val = bit1 << (vf - 32);
+       } else {
+               addr = IXGBE_VFTE(0);
+               val = bit1 << vf;
+       }
+
+       reg = IXGBE_READ_REG(hw, addr);
+
+       if (on)
+               reg |= val;
+       else
+               reg &= ~val;
+
+       IXGBE_WRITE_REG(hw, addr, reg);
+
+       return 0;
+}
+
+int
+rte_pmd_ixgbe_set_vf_vlan_filter(uint8_t port, uint16_t vlan,
+                       uint64_t vf_mask, uint8_t vlan_on)
+{
+       struct rte_eth_dev *dev;
+       struct rte_eth_dev_info dev_info;
+       int ret = 0;
+       uint16_t vf_idx;
+       struct ixgbe_hw *hw;
+
+       RTE_ETH_VALID_PORTID_OR_ERR_RET(port, -ENODEV);
+
+       dev = &rte_eth_devices[port];
+       rte_eth_dev_info_get(port, &dev_info);
+
+       if (is_ixgbe_pmd(dev_info.driver_name) != 0)
+               return -ENOTSUP;
+
+       if ((vlan > ETHER_MAX_VLAN_ID) || (vf_mask == 0))
+               return -EINVAL;
+
+       hw = IXGBE_DEV_PRIVATE_TO_HW(dev->data->dev_private);
+       if (ixgbe_vt_check(hw) < 0)
+               return -ENOTSUP;
+
+       for (vf_idx = 0; vf_idx < 64; vf_idx++) {
+               if (vf_mask & ((uint64_t)(1ULL << vf_idx))) {
+                       ret = hw->mac.ops.set_vfta(hw, vlan, vf_idx,
+                                                  vlan_on, false);
+                       if (ret < 0)
+                               return ret;
+               }
+       }
+
+       return ret;
+}
+
+int rte_pmd_ixgbe_set_vf_rate_limit(uint8_t port, uint16_t vf,
+       uint16_t tx_rate, uint64_t q_msk)
+{
+       struct rte_eth_dev *dev;
+       struct rte_eth_dev_info dev_info;
+       struct ixgbe_hw *hw;
+       struct ixgbe_vf_info *vfinfo;
+       struct rte_eth_link link;
+       uint8_t  nb_q_per_pool;
+       uint32_t queue_stride;
+       uint32_t queue_idx, idx = 0, vf_idx;
+       uint32_t queue_end;
+       uint16_t total_rate = 0;
+       struct rte_pci_device *pci_dev;
+
+       RTE_ETH_VALID_PORTID_OR_ERR_RET(port, -ENODEV);
+
+       dev = &rte_eth_devices[port];
+       rte_eth_dev_info_get(port, &dev_info);
+       rte_eth_link_get_nowait(port, &link);
+
+       if (is_ixgbe_pmd(dev_info.driver_name) != 0)
+               return -ENOTSUP;
+
+       if (vf >= dev_info.max_vfs)
+               return -EINVAL;
+
+       if (tx_rate > link.link_speed)
+               return -EINVAL;
+
+       if (q_msk == 0)
+               return 0;
+
+       pci_dev = IXGBE_DEV_TO_PCI(dev);
+       hw = IXGBE_DEV_PRIVATE_TO_HW(dev->data->dev_private);
+       vfinfo = *(IXGBE_DEV_PRIVATE_TO_P_VFDATA(dev->data->dev_private));
+       nb_q_per_pool = RTE_ETH_DEV_SRIOV(dev).nb_q_per_pool;
+       queue_stride = IXGBE_MAX_RX_QUEUE_NUM / RTE_ETH_DEV_SRIOV(dev).active;
+       queue_idx = vf * queue_stride;
+       queue_end = queue_idx + nb_q_per_pool - 1;
+       if (queue_end >= hw->mac.max_tx_queues)
+               return -EINVAL;
+
+       if (vfinfo) {
+               for (vf_idx = 0; vf_idx < pci_dev->max_vfs; vf_idx++) {
+                       if (vf_idx == vf)
+                               continue;
+                       for (idx = 0; idx < RTE_DIM(vfinfo[vf_idx].tx_rate);
+                               idx++)
+                               total_rate += vfinfo[vf_idx].tx_rate[idx];
+               }
+       } else {
+               return -EINVAL;
+       }
+
+       /* Store tx_rate for this vf. */
+       for (idx = 0; idx < nb_q_per_pool; idx++) {
+               if (((uint64_t)0x1 << idx) & q_msk) {
+                       if (vfinfo[vf].tx_rate[idx] != tx_rate)
+                               vfinfo[vf].tx_rate[idx] = tx_rate;
+                       total_rate += tx_rate;
+               }
+       }
+
+       if (total_rate > dev->data->dev_link.link_speed) {
+               /* Reset stored TX rate of the VF if it causes exceed
+                * link speed.
+                */
+               memset(vfinfo[vf].tx_rate, 0, sizeof(vfinfo[vf].tx_rate));
+               return -EINVAL;
+       }
+
+       /* Set RTTBCNRC of each queue/pool for vf X  */
+       for (; queue_idx <= queue_end; queue_idx++) {
+               if (0x1 & q_msk)
+                       ixgbe_set_queue_rate_limit(dev, queue_idx, tx_rate);
+               q_msk = q_msk >> 1;
+       }
+
+       return 0;
+}
+
+#define IXGBE_MRCTL_VPME  0x01 /* Virtual Pool Mirroring. */
+#define IXGBE_MRCTL_UPME  0x02 /* Uplink Port Mirroring. */
+#define IXGBE_MRCTL_DPME  0x04 /* Downlink Port Mirroring. */
+#define IXGBE_MRCTL_VLME  0x08 /* VLAN Mirroring. */
+#define IXGBE_INVALID_MIRROR_TYPE(mirror_type) \
+       ((mirror_type) & ~(uint8_t)(ETH_MIRROR_VIRTUAL_POOL_UP | \
+       ETH_MIRROR_UPLINK_PORT | ETH_MIRROR_DOWNLINK_PORT | ETH_MIRROR_VLAN))
+
+static int
+ixgbe_mirror_rule_set(struct rte_eth_dev *dev,
+                       struct rte_eth_mirror_conf *mirror_conf,
+                       uint8_t rule_id, uint8_t on)
+{
+       uint32_t mr_ctl, vlvf;
+       uint32_t mp_lsb = 0;
+       uint32_t mv_msb = 0;
+       uint32_t mv_lsb = 0;
+       uint32_t mp_msb = 0;
+       uint8_t i = 0;
+       int reg_index = 0;
+       uint64_t vlan_mask = 0;
+
+       const uint8_t pool_mask_offset = 32;
        const uint8_t vlan_mask_offset = 32;
        const uint8_t dst_pool_offset = 8;
        const uint8_t rule_mr_offset  = 4;
@@ -4917,7 +5402,7 @@ ixgbe_mirror_rule_set(struct rte_eth_dev *dev,
                IXGBE_DEV_PRIVATE_TO_HW(dev->data->dev_private);
        uint8_t mirror_type = 0;
 
-       if (ixgbe_vmdq_mode_check(hw) < 0)
+       if (ixgbe_vt_check(hw) < 0)
                return -ENOTSUP;
 
        if (rule_id >= IXGBE_MAX_MIRROR_RULES)
@@ -5038,7 +5523,7 @@ ixgbe_mirror_rule_reset(struct rte_eth_dev *dev, uint8_t rule_id)
        struct ixgbe_mirror_info *mr_info =
                (IXGBE_DEV_PRIVATE_TO_PFDATA(dev->data->dev_private));
 
-       if (ixgbe_vmdq_mode_check(hw) < 0)
+       if (ixgbe_vt_check(hw) < 0)
                return -ENOTSUP;
 
        memset(&mr_info->mr_conf[rule_id], 0,
@@ -5061,6 +5546,8 @@ ixgbe_mirror_rule_reset(struct rte_eth_dev *dev, uint8_t rule_id)
 static int
 ixgbevf_dev_rx_queue_intr_enable(struct rte_eth_dev *dev, uint16_t queue_id)
 {
+       struct rte_pci_device *pci_dev = IXGBE_DEV_TO_PCI(dev);
+       struct rte_intr_handle *intr_handle = &pci_dev->intr_handle;
        uint32_t mask;
        struct ixgbe_hw *hw =
                IXGBE_DEV_PRIVATE_TO_HW(dev->data->dev_private);
@@ -5070,7 +5557,7 @@ ixgbevf_dev_rx_queue_intr_enable(struct rte_eth_dev *dev, uint16_t queue_id)
        RTE_SET_USED(queue_id);
        IXGBE_WRITE_REG(hw, IXGBE_VTEIMS, mask);
 
-       rte_intr_enable(&dev->pci_dev->intr_handle);
+       rte_intr_enable(intr_handle);
 
        return 0;
 }
@@ -5093,6 +5580,8 @@ ixgbevf_dev_rx_queue_intr_disable(struct rte_eth_dev *dev, uint16_t queue_id)
 static int
 ixgbe_dev_rx_queue_intr_enable(struct rte_eth_dev *dev, uint16_t queue_id)
 {
+       struct rte_pci_device *pci_dev = IXGBE_DEV_TO_PCI(dev);
+       struct rte_intr_handle *intr_handle = &pci_dev->intr_handle;
        uint32_t mask;
        struct ixgbe_hw *hw =
                IXGBE_DEV_PRIVATE_TO_HW(dev->data->dev_private);
@@ -5112,7 +5601,7 @@ ixgbe_dev_rx_queue_intr_enable(struct rte_eth_dev *dev, uint16_t queue_id)
                mask &= (1 << (queue_id - 32));
                IXGBE_WRITE_REG(hw, IXGBE_EIMS_EX(1), mask);
        }
-       rte_intr_enable(&dev->pci_dev->intr_handle);
+       rte_intr_enable(intr_handle);
 
        return 0;
 }
@@ -5216,7 +5705,8 @@ ixgbe_set_ivar_map(struct ixgbe_hw *hw, int8_t direction,
 static void
 ixgbevf_configure_msix(struct rte_eth_dev *dev)
 {
-       struct rte_intr_handle *intr_handle = &dev->pci_dev->intr_handle;
+       struct rte_pci_device *pci_dev = IXGBE_DEV_TO_PCI(dev);
+       struct rte_intr_handle *intr_handle = &pci_dev->intr_handle;
        struct ixgbe_hw *hw =
                IXGBE_DEV_PRIVATE_TO_HW(dev->data->dev_private);
        uint32_t q_idx;
@@ -5249,7 +5739,8 @@ ixgbevf_configure_msix(struct rte_eth_dev *dev)
 static void
 ixgbe_configure_msix(struct rte_eth_dev *dev)
 {
-       struct rte_intr_handle *intr_handle = &dev->pci_dev->intr_handle;
+       struct rte_pci_device *pci_dev = IXGBE_DEV_TO_PCI(dev);
+       struct rte_intr_handle *intr_handle = &pci_dev->intr_handle;
        struct ixgbe_hw *hw =
                IXGBE_DEV_PRIVATE_TO_HW(dev->data->dev_private);
        uint32_t queue_id, base = IXGBE_MISC_VEC_ID;
@@ -5364,61 +5855,6 @@ static int ixgbe_set_queue_rate_limit(struct rte_eth_dev *dev,
        return 0;
 }
 
-static int ixgbe_set_vf_rate_limit(struct rte_eth_dev *dev, uint16_t vf,
-       uint16_t tx_rate, uint64_t q_msk)
-{
-       struct ixgbe_hw *hw = IXGBE_DEV_PRIVATE_TO_HW(dev->data->dev_private);
-       struct ixgbe_vf_info *vfinfo =
-               *(IXGBE_DEV_PRIVATE_TO_P_VFDATA(dev->data->dev_private));
-       uint8_t  nb_q_per_pool = RTE_ETH_DEV_SRIOV(dev).nb_q_per_pool;
-       uint32_t queue_stride =
-               IXGBE_MAX_RX_QUEUE_NUM / RTE_ETH_DEV_SRIOV(dev).active;
-       uint32_t queue_idx = vf * queue_stride, idx = 0, vf_idx;
-       uint32_t queue_end = queue_idx + nb_q_per_pool - 1;
-       uint16_t total_rate = 0;
-
-       if (queue_end >= hw->mac.max_tx_queues)
-               return -EINVAL;
-
-       if (vfinfo != NULL) {
-               for (vf_idx = 0; vf_idx < dev->pci_dev->max_vfs; vf_idx++) {
-                       if (vf_idx == vf)
-                               continue;
-                       for (idx = 0; idx < RTE_DIM(vfinfo[vf_idx].tx_rate);
-                               idx++)
-                               total_rate += vfinfo[vf_idx].tx_rate[idx];
-               }
-       } else
-               return -EINVAL;
-
-       /* Store tx_rate for this vf. */
-       for (idx = 0; idx < nb_q_per_pool; idx++) {
-               if (((uint64_t)0x1 << idx) & q_msk) {
-                       if (vfinfo[vf].tx_rate[idx] != tx_rate)
-                               vfinfo[vf].tx_rate[idx] = tx_rate;
-                       total_rate += tx_rate;
-               }
-       }
-
-       if (total_rate > dev->data->dev_link.link_speed) {
-               /*
-                * Reset stored TX rate of the VF if it causes exceed
-                * link speed.
-                */
-               memset(vfinfo[vf].tx_rate, 0, sizeof(vfinfo[vf].tx_rate));
-               return -EINVAL;
-       }
-
-       /* Set RTTBCNRC of each queue/pool for vf X  */
-       for (; queue_idx <= queue_end; queue_idx++) {
-               if (0x1 & q_msk)
-                       ixgbe_set_queue_rate_limit(dev, queue_idx, tx_rate);
-               q_msk = q_msk >> 1;
-       }
-
-       return 0;
-}
-
 static void
 ixgbevf_add_mac_addr(struct rte_eth_dev *dev, struct ether_addr *mac_addr,
                     __attribute__((unused)) uint32_t index,
@@ -5509,15 +5945,18 @@ ixgbe_syn_filter_set(struct rte_eth_dev *dev,
                        bool add)
 {
        struct ixgbe_hw *hw = IXGBE_DEV_PRIVATE_TO_HW(dev->data->dev_private);
+       struct ixgbe_filter_info *filter_info =
+               IXGBE_DEV_PRIVATE_TO_FILTER_INFO(dev->data->dev_private);
+       uint32_t syn_info;
        uint32_t synqf;
 
        if (filter->queue >= IXGBE_MAX_RX_QUEUE_NUM)
                return -EINVAL;
 
-       synqf = IXGBE_READ_REG(hw, IXGBE_SYNQF);
+       syn_info = filter_info->syn_info;
 
        if (add) {
-               if (synqf & IXGBE_SYN_FILTER_ENABLE)
+               if (syn_info & IXGBE_SYN_FILTER_ENABLE)
                        return -EINVAL;
                synqf = (uint32_t)(((filter->queue << IXGBE_SYN_FILTER_QUEUE_SHIFT) &
                        IXGBE_SYN_FILTER_QUEUE) | IXGBE_SYN_FILTER_ENABLE);
@@ -5527,10 +5966,13 @@ ixgbe_syn_filter_set(struct rte_eth_dev *dev,
                else
                        synqf &= ~IXGBE_SYN_FILTER_SYNQFP;
        } else {
-               if (!(synqf & IXGBE_SYN_FILTER_ENABLE))
+               synqf = IXGBE_READ_REG(hw, IXGBE_SYNQF);
+               if (!(syn_info & IXGBE_SYN_FILTER_ENABLE))
                        return -ENOENT;
                synqf &= ~(IXGBE_SYN_FILTER_QUEUE | IXGBE_SYN_FILTER_ENABLE);
        }
+
+       filter_info->syn_info = synqf;
        IXGBE_WRITE_REG(hw, IXGBE_SYNQF, synqf);
        IXGBE_WRITE_FLUSH(hw);
        return 0;
@@ -7044,12 +7486,104 @@ ixgbe_e_tag_filter_add(struct rte_eth_dev *dev,
        return -EINVAL;
 }
 
+static inline struct ixgbe_l2_tn_filter *
+ixgbe_l2_tn_filter_lookup(struct ixgbe_l2_tn_info *l2_tn_info,
+                         struct ixgbe_l2_tn_key *key)
+{
+       int ret;
+
+       ret = rte_hash_lookup(l2_tn_info->hash_handle, (const void *)key);
+       if (ret < 0)
+               return NULL;
+
+       return l2_tn_info->hash_map[ret];
+}
+
+static inline int
+ixgbe_insert_l2_tn_filter(struct ixgbe_l2_tn_info *l2_tn_info,
+                         struct ixgbe_l2_tn_filter *l2_tn_filter)
+{
+       int ret;
+
+       ret = rte_hash_add_key(l2_tn_info->hash_handle,
+                              &l2_tn_filter->key);
+
+       if (ret < 0) {
+               PMD_DRV_LOG(ERR,
+                           "Failed to insert L2 tunnel filter"
+                           " to hash table %d!",
+                           ret);
+               return ret;
+       }
+
+       l2_tn_info->hash_map[ret] = l2_tn_filter;
+
+       TAILQ_INSERT_TAIL(&l2_tn_info->l2_tn_list, l2_tn_filter, entries);
+
+       return 0;
+}
+
+static inline int
+ixgbe_remove_l2_tn_filter(struct ixgbe_l2_tn_info *l2_tn_info,
+                         struct ixgbe_l2_tn_key *key)
+{
+       int ret;
+       struct ixgbe_l2_tn_filter *l2_tn_filter;
+
+       ret = rte_hash_del_key(l2_tn_info->hash_handle, key);
+
+       if (ret < 0) {
+               PMD_DRV_LOG(ERR,
+                           "No such L2 tunnel filter to delete %d!",
+                           ret);
+               return ret;
+       }
+
+       l2_tn_filter = l2_tn_info->hash_map[ret];
+       l2_tn_info->hash_map[ret] = NULL;
+
+       TAILQ_REMOVE(&l2_tn_info->l2_tn_list, l2_tn_filter, entries);
+       rte_free(l2_tn_filter);
+
+       return 0;
+}
+
 /* Add l2 tunnel filter */
 static int
 ixgbe_dev_l2_tunnel_filter_add(struct rte_eth_dev *dev,
                               struct rte_eth_l2_tunnel_conf *l2_tunnel)
 {
-       int ret = 0;
+       int ret;
+       struct ixgbe_l2_tn_info *l2_tn_info =
+               IXGBE_DEV_PRIVATE_TO_L2_TN_INFO(dev->data->dev_private);
+       struct ixgbe_l2_tn_key key;
+       struct ixgbe_l2_tn_filter *node;
+
+       key.l2_tn_type = l2_tunnel->l2_tunnel_type;
+       key.tn_id = l2_tunnel->tunnel_id;
+
+       node = ixgbe_l2_tn_filter_lookup(l2_tn_info, &key);
+
+       if (node) {
+               PMD_DRV_LOG(ERR, "The L2 tunnel filter already exists!");
+               return -EINVAL;
+       }
+
+       node = rte_zmalloc("ixgbe_l2_tn",
+                          sizeof(struct ixgbe_l2_tn_filter),
+                          0);
+       if (!node)
+               return -ENOMEM;
+
+       (void)rte_memcpy(&node->key,
+                        &key,
+                        sizeof(struct ixgbe_l2_tn_key));
+       node->pool = l2_tunnel->pool;
+       ret = ixgbe_insert_l2_tn_filter(l2_tn_info, node);
+       if (ret < 0) {
+               rte_free(node);
+               return ret;
+       }
 
        switch (l2_tunnel->l2_tunnel_type) {
        case RTE_L2_TUNNEL_TYPE_E_TAG:
@@ -7061,6 +7595,9 @@ ixgbe_dev_l2_tunnel_filter_add(struct rte_eth_dev *dev,
                break;
        }
 
+       if (ret < 0)
+               (void)ixgbe_remove_l2_tn_filter(l2_tn_info, &key);
+
        return ret;
 }
 
@@ -7069,7 +7606,16 @@ static int
 ixgbe_dev_l2_tunnel_filter_del(struct rte_eth_dev *dev,
                               struct rte_eth_l2_tunnel_conf *l2_tunnel)
 {
-       int ret = 0;
+       int ret;
+       struct ixgbe_l2_tn_info *l2_tn_info =
+               IXGBE_DEV_PRIVATE_TO_L2_TN_INFO(dev->data->dev_private);
+       struct ixgbe_l2_tn_key key;
+
+       key.l2_tn_type = l2_tunnel->l2_tunnel_type;
+       key.tn_id = l2_tunnel->tunnel_id;
+       ret = ixgbe_remove_l2_tn_filter(l2_tn_info, &key);
+       if (ret < 0)
+               return ret;
 
        switch (l2_tunnel->l2_tunnel_type) {
        case RTE_L2_TUNNEL_TYPE_E_TAG:
@@ -7095,7 +7641,7 @@ ixgbe_dev_l2_tunnel_filter_handle(struct rte_eth_dev *dev,
                                  enum rte_filter_op filter_op,
                                  void *arg)
 {
-       int ret = 0;
+       int ret;
 
        if (filter_op == RTE_ETH_FILTER_NOP)
                return 0;
@@ -7194,15 +7740,16 @@ ixgbe_e_tag_insertion_en_dis(struct rte_eth_dev *dev,
                             struct rte_eth_l2_tunnel_conf *l2_tunnel,
                             bool en)
 {
+       struct rte_pci_device *pci_dev = IXGBE_DEV_TO_PCI(dev);
        int ret = 0;
        uint32_t vmtir, vmvir;
        struct ixgbe_hw *hw = IXGBE_DEV_PRIVATE_TO_HW(dev->data->dev_private);
 
-       if (l2_tunnel->vf_id >= dev->pci_dev->max_vfs) {
+       if (l2_tunnel->vf_id >= pci_dev->max_vfs) {
                PMD_DRV_LOG(ERR,
                            "VF id %u should be less than %u",
                            l2_tunnel->vf_id,
-                           dev->pci_dev->max_vfs);
+                           pci_dev->max_vfs);
                return -EINVAL;
        }
 
@@ -7592,6 +8139,330 @@ ixgbevf_dev_interrupt_handler(__rte_unused struct rte_intr_handle *handle,
        ixgbevf_dev_interrupt_action(dev);
 }
 
+/**
+ *  ixgbe_disable_sec_tx_path_generic - Stops the transmit data path
+ *  @hw: pointer to hardware structure
+ *
+ *  Stops the transmit data path and waits for the HW to internally empty
+ *  the Tx security block
+ **/
+int ixgbe_disable_sec_tx_path_generic(struct ixgbe_hw *hw)
+{
+#define IXGBE_MAX_SECTX_POLL 40
+
+       int i;
+       int sectxreg;
+
+       sectxreg = IXGBE_READ_REG(hw, IXGBE_SECTXCTRL);
+       sectxreg |= IXGBE_SECTXCTRL_TX_DIS;
+       IXGBE_WRITE_REG(hw, IXGBE_SECTXCTRL, sectxreg);
+       for (i = 0; i < IXGBE_MAX_SECTX_POLL; i++) {
+               sectxreg = IXGBE_READ_REG(hw, IXGBE_SECTXSTAT);
+               if (sectxreg & IXGBE_SECTXSTAT_SECTX_RDY)
+                       break;
+               /* Use interrupt-safe sleep just in case */
+               usec_delay(1000);
+       }
+
+       /* For informational purposes only */
+       if (i >= IXGBE_MAX_SECTX_POLL)
+               PMD_DRV_LOG(DEBUG, "Tx unit being enabled before security "
+                        "path fully disabled.  Continuing with init.\n");
+
+       return IXGBE_SUCCESS;
+}
+
+/**
+ *  ixgbe_enable_sec_tx_path_generic - Enables the transmit data path
+ *  @hw: pointer to hardware structure
+ *
+ *  Enables the transmit data path.
+ **/
+int ixgbe_enable_sec_tx_path_generic(struct ixgbe_hw *hw)
+{
+       uint32_t sectxreg;
+
+       sectxreg = IXGBE_READ_REG(hw, IXGBE_SECTXCTRL);
+       sectxreg &= ~IXGBE_SECTXCTRL_TX_DIS;
+       IXGBE_WRITE_REG(hw, IXGBE_SECTXCTRL, sectxreg);
+       IXGBE_WRITE_FLUSH(hw);
+
+       return IXGBE_SUCCESS;
+}
+
+int
+rte_pmd_ixgbe_macsec_enable(uint8_t port, uint8_t en, uint8_t rp)
+{
+       struct ixgbe_hw *hw;
+       struct rte_eth_dev *dev;
+       uint32_t ctrl;
+
+       RTE_ETH_VALID_PORTID_OR_ERR_RET(port, -ENODEV);
+
+       dev = &rte_eth_devices[port];
+       hw = IXGBE_DEV_PRIVATE_TO_HW(dev->data->dev_private);
+
+       /* Stop the data paths */
+       if (ixgbe_disable_sec_rx_path(hw) != IXGBE_SUCCESS)
+               return -ENOTSUP;
+       /*
+        * Workaround:
+        * As no ixgbe_disable_sec_rx_path equivalent is
+        * implemented for tx in the base code, and we are
+        * not allowed to modify the base code in DPDK, so
+        * just call the hand-written one directly for now.
+        * The hardware support has been checked by
+        * ixgbe_disable_sec_rx_path().
+        */
+       ixgbe_disable_sec_tx_path_generic(hw);
+
+       /* Enable Ethernet CRC (required by MACsec offload) */
+       ctrl = IXGBE_READ_REG(hw, IXGBE_HLREG0);
+       ctrl |= IXGBE_HLREG0_TXCRCEN | IXGBE_HLREG0_RXCRCSTRP;
+       IXGBE_WRITE_REG(hw, IXGBE_HLREG0, ctrl);
+
+       /* Enable the TX and RX crypto engines */
+       ctrl = IXGBE_READ_REG(hw, IXGBE_SECTXCTRL);
+       ctrl &= ~IXGBE_SECTXCTRL_SECTX_DIS;
+       IXGBE_WRITE_REG(hw, IXGBE_SECTXCTRL, ctrl);
+
+       ctrl = IXGBE_READ_REG(hw, IXGBE_SECRXCTRL);
+       ctrl &= ~IXGBE_SECRXCTRL_SECRX_DIS;
+       IXGBE_WRITE_REG(hw, IXGBE_SECRXCTRL, ctrl);
+
+       ctrl = IXGBE_READ_REG(hw, IXGBE_SECTXMINIFG);
+       ctrl &= ~IXGBE_SECTX_MINSECIFG_MASK;
+       ctrl |= 0x3;
+       IXGBE_WRITE_REG(hw, IXGBE_SECTXMINIFG, ctrl);
+
+       /* Enable SA lookup */
+       ctrl = IXGBE_READ_REG(hw, IXGBE_LSECTXCTRL);
+       ctrl &= ~IXGBE_LSECTXCTRL_EN_MASK;
+       ctrl |= en ? IXGBE_LSECTXCTRL_AUTH_ENCRYPT :
+                    IXGBE_LSECTXCTRL_AUTH;
+       ctrl |= IXGBE_LSECTXCTRL_AISCI;
+       ctrl &= ~IXGBE_LSECTXCTRL_PNTHRSH_MASK;
+       ctrl |= IXGBE_MACSEC_PNTHRSH & IXGBE_LSECTXCTRL_PNTHRSH_MASK;
+       IXGBE_WRITE_REG(hw, IXGBE_LSECTXCTRL, ctrl);
+
+       ctrl = IXGBE_READ_REG(hw, IXGBE_LSECRXCTRL);
+       ctrl &= ~IXGBE_LSECRXCTRL_EN_MASK;
+       ctrl |= IXGBE_LSECRXCTRL_STRICT << IXGBE_LSECRXCTRL_EN_SHIFT;
+       ctrl &= ~IXGBE_LSECRXCTRL_PLSH;
+       if (rp)
+               ctrl |= IXGBE_LSECRXCTRL_RP;
+       else
+               ctrl &= ~IXGBE_LSECRXCTRL_RP;
+       IXGBE_WRITE_REG(hw, IXGBE_LSECRXCTRL, ctrl);
+
+       /* Start the data paths */
+       ixgbe_enable_sec_rx_path(hw);
+       /*
+        * Workaround:
+        * As no ixgbe_enable_sec_rx_path equivalent is
+        * implemented for tx in the base code, and we are
+        * not allowed to modify the base code in DPDK, so
+        * just call the hand-written one directly for now.
+        */
+       ixgbe_enable_sec_tx_path_generic(hw);
+
+       return 0;
+}
+
+int
+rte_pmd_ixgbe_macsec_disable(uint8_t port)
+{
+       struct ixgbe_hw *hw;
+       struct rte_eth_dev *dev;
+       uint32_t ctrl;
+
+       RTE_ETH_VALID_PORTID_OR_ERR_RET(port, -ENODEV);
+
+       dev = &rte_eth_devices[port];
+       hw = IXGBE_DEV_PRIVATE_TO_HW(dev->data->dev_private);
+
+       /* Stop the data paths */
+       if (ixgbe_disable_sec_rx_path(hw) != IXGBE_SUCCESS)
+               return -ENOTSUP;
+       /*
+        * Workaround:
+        * As no ixgbe_disable_sec_rx_path equivalent is
+        * implemented for tx in the base code, and we are
+        * not allowed to modify the base code in DPDK, so
+        * just call the hand-written one directly for now.
+        * The hardware support has been checked by
+        * ixgbe_disable_sec_rx_path().
+        */
+       ixgbe_disable_sec_tx_path_generic(hw);
+
+       /* Disable the TX and RX crypto engines */
+       ctrl = IXGBE_READ_REG(hw, IXGBE_SECTXCTRL);
+       ctrl |= IXGBE_SECTXCTRL_SECTX_DIS;
+       IXGBE_WRITE_REG(hw, IXGBE_SECTXCTRL, ctrl);
+
+       ctrl = IXGBE_READ_REG(hw, IXGBE_SECRXCTRL);
+       ctrl |= IXGBE_SECRXCTRL_SECRX_DIS;
+       IXGBE_WRITE_REG(hw, IXGBE_SECRXCTRL, ctrl);
+
+       /* Disable SA lookup */
+       ctrl = IXGBE_READ_REG(hw, IXGBE_LSECTXCTRL);
+       ctrl &= ~IXGBE_LSECTXCTRL_EN_MASK;
+       ctrl |= IXGBE_LSECTXCTRL_DISABLE;
+       IXGBE_WRITE_REG(hw, IXGBE_LSECTXCTRL, ctrl);
+
+       ctrl = IXGBE_READ_REG(hw, IXGBE_LSECRXCTRL);
+       ctrl &= ~IXGBE_LSECRXCTRL_EN_MASK;
+       ctrl |= IXGBE_LSECRXCTRL_DISABLE << IXGBE_LSECRXCTRL_EN_SHIFT;
+       IXGBE_WRITE_REG(hw, IXGBE_LSECRXCTRL, ctrl);
+
+       /* Start the data paths */
+       ixgbe_enable_sec_rx_path(hw);
+       /*
+        * Workaround:
+        * As no ixgbe_enable_sec_rx_path equivalent is
+        * implemented for tx in the base code, and we are
+        * not allowed to modify the base code in DPDK, so
+        * just call the hand-written one directly for now.
+        */
+       ixgbe_enable_sec_tx_path_generic(hw);
+
+       return 0;
+}
+
+int
+rte_pmd_ixgbe_macsec_config_txsc(uint8_t port, uint8_t *mac)
+{
+       struct ixgbe_hw *hw;
+       struct rte_eth_dev *dev;
+       uint32_t ctrl;
+
+       RTE_ETH_VALID_PORTID_OR_ERR_RET(port, -ENODEV);
+
+       dev = &rte_eth_devices[port];
+       hw = IXGBE_DEV_PRIVATE_TO_HW(dev->data->dev_private);
+
+       ctrl = mac[0] | (mac[1] << 8) | (mac[2] << 16) | (mac[3] << 24);
+       IXGBE_WRITE_REG(hw, IXGBE_LSECTXSCL, ctrl);
+
+       ctrl = mac[4] | (mac[5] << 8);
+       IXGBE_WRITE_REG(hw, IXGBE_LSECTXSCH, ctrl);
+
+       return 0;
+}
+
+int
+rte_pmd_ixgbe_macsec_config_rxsc(uint8_t port, uint8_t *mac, uint16_t pi)
+{
+       struct ixgbe_hw *hw;
+       struct rte_eth_dev *dev;
+       uint32_t ctrl;
+
+       RTE_ETH_VALID_PORTID_OR_ERR_RET(port, -ENODEV);
+
+       dev = &rte_eth_devices[port];
+       hw = IXGBE_DEV_PRIVATE_TO_HW(dev->data->dev_private);
+
+       ctrl = mac[0] | (mac[1] << 8) | (mac[2] << 16) | (mac[3] << 24);
+       IXGBE_WRITE_REG(hw, IXGBE_LSECRXSCL, ctrl);
+
+       pi = rte_cpu_to_be_16(pi);
+       ctrl = mac[4] | (mac[5] << 8) | (pi << 16);
+       IXGBE_WRITE_REG(hw, IXGBE_LSECRXSCH, ctrl);
+
+       return 0;
+}
+
+int
+rte_pmd_ixgbe_macsec_select_txsa(uint8_t port, uint8_t idx, uint8_t an,
+                                uint32_t pn, uint8_t *key)
+{
+       struct ixgbe_hw *hw;
+       struct rte_eth_dev *dev;
+       uint32_t ctrl, i;
+
+       RTE_ETH_VALID_PORTID_OR_ERR_RET(port, -ENODEV);
+
+       dev = &rte_eth_devices[port];
+       hw = IXGBE_DEV_PRIVATE_TO_HW(dev->data->dev_private);
+
+       if (idx != 0 && idx != 1)
+               return -EINVAL;
+
+       if (an >= 4)
+               return -EINVAL;
+
+       hw = IXGBE_DEV_PRIVATE_TO_HW(dev->data->dev_private);
+
+       /* Set the PN and key */
+       pn = rte_cpu_to_be_32(pn);
+       if (idx == 0) {
+               IXGBE_WRITE_REG(hw, IXGBE_LSECTXPN0, pn);
+
+               for (i = 0; i < 4; i++) {
+                       ctrl = (key[i * 4 + 0] <<  0) |
+                              (key[i * 4 + 1] <<  8) |
+                              (key[i * 4 + 2] << 16) |
+                              (key[i * 4 + 3] << 24);
+                       IXGBE_WRITE_REG(hw, IXGBE_LSECTXKEY0(i), ctrl);
+               }
+       } else {
+               IXGBE_WRITE_REG(hw, IXGBE_LSECTXPN1, pn);
+
+               for (i = 0; i < 4; i++) {
+                       ctrl = (key[i * 4 + 0] <<  0) |
+                              (key[i * 4 + 1] <<  8) |
+                              (key[i * 4 + 2] << 16) |
+                              (key[i * 4 + 3] << 24);
+                       IXGBE_WRITE_REG(hw, IXGBE_LSECTXKEY1(i), ctrl);
+               }
+       }
+
+       /* Set AN and select the SA */
+       ctrl = (an << idx * 2) | (idx << 4);
+       IXGBE_WRITE_REG(hw, IXGBE_LSECTXSA, ctrl);
+
+       return 0;
+}
+
+int
+rte_pmd_ixgbe_macsec_select_rxsa(uint8_t port, uint8_t idx, uint8_t an,
+                                uint32_t pn, uint8_t *key)
+{
+       struct ixgbe_hw *hw;
+       struct rte_eth_dev *dev;
+       uint32_t ctrl, i;
+
+       RTE_ETH_VALID_PORTID_OR_ERR_RET(port, -ENODEV);
+
+       dev = &rte_eth_devices[port];
+       hw = IXGBE_DEV_PRIVATE_TO_HW(dev->data->dev_private);
+
+       if (idx != 0 && idx != 1)
+               return -EINVAL;
+
+       if (an >= 4)
+               return -EINVAL;
+
+       /* Set the PN */
+       pn = rte_cpu_to_be_32(pn);
+       IXGBE_WRITE_REG(hw, IXGBE_LSECRXPN(idx), pn);
+
+       /* Set the key */
+       for (i = 0; i < 4; i++) {
+               ctrl = (key[i * 4 + 0] <<  0) |
+                      (key[i * 4 + 1] <<  8) |
+                      (key[i * 4 + 2] << 16) |
+                      (key[i * 4 + 3] << 24);
+               IXGBE_WRITE_REG(hw, IXGBE_LSECRXKEY(idx, i), ctrl);
+       }
+
+       /* Set the AN and validate the SA */
+       ctrl = an | (1 << 2);
+       IXGBE_WRITE_REG(hw, IXGBE_LSECRXSA(idx), ctrl);
+
+       return 0;
+}
+
 RTE_PMD_REGISTER_PCI(net_ixgbe, rte_ixgbe_pmd.pci_drv);
 RTE_PMD_REGISTER_PCI_TABLE(net_ixgbe, pci_id_ixgbe_map);
 RTE_PMD_REGISTER_KMOD_DEP(net_ixgbe, "* igb_uio | uio_pci_generic | vfio");