net/txgbe: add flow director filter init and uninit
authorJiawen Wu <jiawenwu@trustnetic.com>
Fri, 18 Dec 2020 09:36:42 +0000 (17:36 +0800)
committerFerruh Yigit <ferruh.yigit@intel.com>
Wed, 13 Jan 2021 17:51:58 +0000 (18:51 +0100)
Add flow director filter init and uninit operations.

Signed-off-by: Jiawen Wu <jiawenwu@trustnetic.com>
drivers/net/txgbe/base/txgbe_type.h
drivers/net/txgbe/txgbe_ethdev.c
drivers/net/txgbe/txgbe_ethdev.h

index 69aa899..b9d31ab 100644 (file)
@@ -67,6 +67,35 @@ enum {
 
 #define TXGBE_ATR_HASH_MASK                    0x7fff
 
+/* Flow Director ATR input struct. */
+struct txgbe_atr_input {
+       /*
+        * Byte layout in order, all values with MSB first:
+        *
+        * vm_pool      - 1 byte
+        * flow_type    - 1 byte
+        * vlan_id      - 2 bytes
+        * src_ip       - 16 bytes
+        * inner_mac    - 6 bytes
+        * cloud_mode   - 2 bytes
+        * tni_vni      - 4 bytes
+        * dst_ip       - 16 bytes
+        * src_port     - 2 bytes
+        * dst_port     - 2 bytes
+        * flex_bytes   - 2 bytes
+        * bkt_hash     - 2 bytes
+        */
+       u8 vm_pool;
+       u8 flow_type;
+       __be16 pkt_type;
+       __be32 dst_ip[4];
+       __be32 src_ip[4];
+       __be16 src_port;
+       __be16 dst_port;
+       __be16 flex_bytes;
+       __be16 bkt_hash;
+};
+
 enum txgbe_eeprom_type {
        txgbe_eeprom_unknown = 0,
        txgbe_eeprom_spi,
index 777e16a..eadb44a 100644 (file)
@@ -88,6 +88,8 @@ static const struct reg_info *txgbe_regs_others[] = {
                                txgbe_regs_diagnostic,
                                NULL};
 
+static int txgbe_fdir_filter_init(struct rte_eth_dev *eth_dev);
+static int txgbe_fdir_filter_uninit(struct rte_eth_dev *eth_dev);
 static int txgbe_l2_tn_filter_init(struct rte_eth_dev *eth_dev);
 static int txgbe_l2_tn_filter_uninit(struct rte_eth_dev *eth_dev);
 static int  txgbe_dev_set_link_up(struct rte_eth_dev *dev);
@@ -690,6 +692,9 @@ eth_txgbe_dev_init(struct rte_eth_dev *eth_dev, void *init_params __rte_unused)
        /* initialize 5tuple filter list */
        TAILQ_INIT(&filter_info->fivetuple_list);
 
+       /* initialize flow director filter list & hash */
+       txgbe_fdir_filter_init(eth_dev);
+
        /* initialize l2 tunnel filter list & hash */
        txgbe_l2_tn_filter_init(eth_dev);
 
@@ -729,6 +734,26 @@ static int txgbe_ntuple_filter_uninit(struct rte_eth_dev *eth_dev)
        return 0;
 }
 
+static int txgbe_fdir_filter_uninit(struct rte_eth_dev *eth_dev)
+{
+       struct txgbe_hw_fdir_info *fdir_info = TXGBE_DEV_FDIR(eth_dev);
+       struct txgbe_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 txgbe_l2_tn_filter_uninit(struct rte_eth_dev *eth_dev)
 {
        struct txgbe_l2_tn_info *l2_tn_info = TXGBE_DEV_L2_TN(eth_dev);
@@ -749,6 +774,41 @@ static int txgbe_l2_tn_filter_uninit(struct rte_eth_dev *eth_dev)
        return 0;
 }
 
+static int txgbe_fdir_filter_init(struct rte_eth_dev *eth_dev)
+{
+       struct txgbe_hw_fdir_info *fdir_info = TXGBE_DEV_FDIR(eth_dev);
+       char fdir_hash_name[RTE_HASH_NAMESIZE];
+       struct rte_hash_parameters fdir_hash_params = {
+               .name = fdir_hash_name,
+               .entries = TXGBE_MAX_FDIR_FILTER_NUM,
+               .key_len = sizeof(struct txgbe_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", TDEV_NAME(eth_dev));
+       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("txgbe",
+                                         sizeof(struct txgbe_fdir_filter *) *
+                                         TXGBE_MAX_FDIR_FILTER_NUM,
+                                         0);
+       if (!fdir_info->hash_map) {
+               PMD_INIT_LOG(ERR,
+                            "Failed to allocate memory for fdir hash map!");
+               return -ENOMEM;
+       }
+       fdir_info->mask_added = FALSE;
+
+       return 0;
+}
+
 static int txgbe_l2_tn_filter_init(struct rte_eth_dev *eth_dev)
 {
        struct txgbe_l2_tn_info *l2_tn_info = TXGBE_DEV_L2_TN(eth_dev);
@@ -1866,6 +1926,9 @@ txgbe_dev_close(struct rte_eth_dev *dev)
        rte_free(dev->data->hash_mac_addrs);
        dev->data->hash_mac_addrs = NULL;
 
+       /* remove all the fdir filters & hash */
+       txgbe_fdir_filter_uninit(dev);
+
        /* remove all the L2 tunnel filters & hash */
        txgbe_l2_tn_filter_uninit(dev);
 
index 224f31b..77269e9 100644 (file)
 #define TXGBE_MISC_VEC_ID               RTE_INTR_VEC_ZERO_OFFSET
 #define TXGBE_RX_VEC_START              RTE_INTR_VEC_RXTX_OFFSET
 
+#define TXGBE_MAX_FDIR_FILTER_NUM       (1024 * 32)
 #define TXGBE_MAX_L2_TN_FILTER_NUM      128
 
+/*
+ * Information about the fdir mode.
+ */
+struct txgbe_hw_fdir_mask {
+       uint16_t vlan_tci_mask;
+       uint32_t src_ipv4_mask;
+       uint32_t dst_ipv4_mask;
+       uint16_t src_ipv6_mask;
+       uint16_t dst_ipv6_mask;
+       uint16_t src_port_mask;
+       uint16_t dst_port_mask;
+       uint16_t flex_bytes_mask;
+       uint8_t  mac_addr_byte_mask;
+       uint32_t tunnel_id_mask;
+       uint8_t  tunnel_type_mask;
+};
+
+struct txgbe_fdir_filter {
+       TAILQ_ENTRY(txgbe_fdir_filter) entries;
+       struct txgbe_atr_input input; /* key of fdir filter*/
+       uint32_t fdirflags; /* drop or forward */
+       uint32_t fdirhash; /* hash value for fdir */
+       uint8_t queue; /* assigned rx queue */
+};
+
+/* list of fdir filters */
+TAILQ_HEAD(txgbe_fdir_filter_list, txgbe_fdir_filter);
+
+struct txgbe_hw_fdir_info {
+       struct txgbe_hw_fdir_mask mask;
+       uint8_t     flex_bytes_offset;
+       uint16_t    collision;
+       uint16_t    free;
+       uint16_t    maxhash;
+       uint8_t     maxlen;
+       uint64_t    add;
+       uint64_t    remove;
+       uint64_t    f_add;
+       uint64_t    f_remove;
+       struct txgbe_fdir_filter_list fdir_list; /* filter list*/
+       /* store the pointers of the filters, index is the hash value. */
+       struct txgbe_fdir_filter **hash_map;
+       struct rte_hash *hash_handle; /* cuckoo hash handler */
+       bool mask_added; /* If already got mask from consistent filter */
+};
+
 /* structure for interrupt relative data */
 struct txgbe_interrupt {
        uint32_t flags;
@@ -208,6 +255,7 @@ struct txgbe_bw_conf {
 struct txgbe_adapter {
        struct txgbe_hw             hw;
        struct txgbe_hw_stats       stats;
+       struct txgbe_hw_fdir_info   fdir;
        struct txgbe_interrupt      intr;
        struct txgbe_stat_mappings  stat_mappings;
        struct txgbe_vfta           shadow_vfta;
@@ -240,6 +288,9 @@ struct txgbe_adapter {
 #define TXGBE_DEV_INTR(dev) \
        (&((struct txgbe_adapter *)(dev)->data->dev_private)->intr)
 
+#define TXGBE_DEV_FDIR(dev) \
+       (&((struct txgbe_adapter *)(dev)->data->dev_private)->fdir)
+
 #define TXGBE_DEV_STAT_MAPPINGS(dev) \
        (&((struct txgbe_adapter *)(dev)->data->dev_private)->stat_mappings)