net/i40e: support flow director space tracking
authorChenmin Sun <chenmin.sun@intel.com>
Fri, 17 Jul 2020 17:36:55 +0000 (01:36 +0800)
committerFerruh Yigit <ferruh.yigit@intel.com>
Tue, 21 Jul 2020 11:54:54 +0000 (13:54 +0200)
This patch introduces a FDIR flow management for guaranteed/shared
space tracking.
The fdir space is reported by the
i40e_hw_capabilities.fd_filters_guaranteed and fd_filters_best_effort.
The fdir space is managed by hardware and now is tracking in software.
The management algorithm is controlled by the GLQF_CTL.INVALPRIO.
Detailed implementation please check in the datasheet and the
description of struct i40e_fdir_info.fdir_invalprio.

This patch changes the global register GLQF_CTL. Therefore, when devarg
``support-multi-driver`` is set, the patch will not take effect to
avoid affecting the normal behavior of other i40e drivers, e.g., Linux
kernel driver.

Signed-off-by: Chenmin Sun <chenmin.sun@intel.com>
Reviewed-by: Jingjing Wu <jingjing.wu@intel.com>
drivers/net/i40e/i40e_ethdev.c
drivers/net/i40e/i40e_ethdev.h
drivers/net/i40e/i40e_fdir.c
drivers/net/i40e/i40e_flow.c
drivers/net/i40e/i40e_rxtx.c

index 393b532..dca84a1 100644 (file)
@@ -26,6 +26,7 @@
 #include <rte_dev.h>
 #include <rte_tailq.h>
 #include <rte_hash_crc.h>
+#include <rte_bitmap.h>
 
 #include "i40e_logs.h"
 #include "base/i40e_prototype.h"
@@ -1045,8 +1046,11 @@ 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_hw *hw = I40E_PF_TO_HW(pf);
        struct i40e_fdir_info *fdir_info = &pf->fdir;
        char fdir_hash_name[RTE_HASH_NAMESIZE];
+       uint32_t alloc = hw->func_caps.fd_filters_guaranteed;
+       uint32_t best = hw->func_caps.fd_filters_best_effort;
        int ret;
 
        struct rte_hash_parameters fdir_hash_params = {
@@ -1067,6 +1071,7 @@ i40e_init_fdir_filter_list(struct rte_eth_dev *dev)
                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,
@@ -1077,6 +1082,15 @@ i40e_init_fdir_filter_list(struct rte_eth_dev *dev)
                ret = -ENOMEM;
                goto err_fdir_hash_map_alloc;
        }
+
+       fdir_info->fdir_space_size = alloc + best;
+       fdir_info->fdir_actual_cnt = 0;
+       fdir_info->fdir_guarantee_total_space = alloc;
+       fdir_info->fdir_guarantee_free_space =
+               fdir_info->fdir_guarantee_total_space;
+
+       PMD_DRV_LOG(INFO, "FDIR guarantee space: %u, best_effort space %u.", alloc, best);
+
        return 0;
 
 err_fdir_hash_map_alloc:
@@ -1101,6 +1115,30 @@ i40e_init_customized_info(struct i40e_pf *pf)
        pf->esp_support = false;
 }
 
+static void
+i40e_init_filter_invalidation(struct i40e_pf *pf)
+{
+       struct i40e_hw *hw = I40E_PF_TO_HW(pf);
+       struct i40e_fdir_info *fdir_info = &pf->fdir;
+       uint32_t glqf_ctl_reg = 0;
+
+       glqf_ctl_reg = i40e_read_rx_ctl(hw, I40E_GLQF_CTL);
+       if (!pf->support_multi_driver) {
+               fdir_info->fdir_invalprio = 1;
+               glqf_ctl_reg |= I40E_GLQF_CTL_INVALPRIO_MASK;
+               PMD_DRV_LOG(INFO, "FDIR INVALPRIO set to guaranteed first");
+               i40e_write_rx_ctl(hw, I40E_GLQF_CTL, glqf_ctl_reg);
+       } else {
+               if (glqf_ctl_reg & I40E_GLQF_CTL_INVALPRIO_MASK) {
+                       fdir_info->fdir_invalprio = 1;
+                       PMD_DRV_LOG(INFO, "FDIR INVALPRIO is: guaranteed first");
+               } else {
+                       fdir_info->fdir_invalprio = 0;
+                       PMD_DRV_LOG(INFO, "FDIR INVALPRIO is: shared first");
+               }
+       }
+}
+
 void
 i40e_init_queue_region_conf(struct rte_eth_dev *dev)
 {
@@ -1654,6 +1692,9 @@ eth_i40e_dev_init(struct rte_eth_dev *dev, void *init_params __rte_unused)
        /* Initialize customized information */
        i40e_init_customized_info(pf);
 
+       /* Initialize the filter invalidation configuration */
+       i40e_init_filter_invalidation(pf);
+
        ret = i40e_init_ethtype_filter_list(dev);
        if (ret < 0)
                goto err_init_ethtype_filter_list;
index 31ca05d..eb505c7 100644 (file)
@@ -698,6 +698,30 @@ struct i40e_fdir_info {
        struct i40e_fdir_filter **hash_map;
        struct rte_hash *hash_table;
 
+       /*
+        * Priority ordering at filter invalidation(destroying a flow) between
+        * "best effort" space and "guaranteed" space.
+        *
+        * 0 = At filter invalidation, the hardware first tries to increment the
+        * "best effort" space. The "guaranteed" space is incremented only when
+        * the global "best effort" space is at it max value or the "best effort"
+        * space of the PF is at its max value.
+        * 1 = At filter invalidation, the hardware first tries to increment its
+        * "guaranteed" space. The "best effort" space is incremented only when
+        * it is already at its max value.
+        */
+       uint32_t fdir_invalprio;
+       /* the total size of the fdir, this number is the sum of the guaranteed +
+        * shared space
+        */
+       uint32_t fdir_space_size;
+       /* the actual number of the fdir rules in hardware, initialized as 0 */
+       uint32_t fdir_actual_cnt;
+       /* the free guaranteed space of the fdir */
+       uint32_t fdir_guarantee_free_space;
+       /* the fdir total guaranteed space */
+       uint32_t fdir_guarantee_total_space;
+
        /* Mark if flex pit and mask is set */
        bool flex_pit_flag[I40E_MAX_FLXPLD_LAYER];
        bool flex_mask_flag[I40E_FILTER_PCTYPE_MAX];
@@ -1335,8 +1359,8 @@ int i40e_add_del_fdir_filter(struct rte_eth_dev *dev,
                             const struct rte_eth_fdir_filter *filter,
                             bool add);
 int i40e_flow_add_del_fdir_filter(struct rte_eth_dev *dev,
-                                 const struct i40e_fdir_filter_conf *filter,
-                                 bool add);
+                             const struct i40e_fdir_filter_conf *filter,
+                             bool add);
 int i40e_dev_tunnel_filter_set(struct i40e_pf *pf,
                               struct rte_eth_tunnel_filter_conf *tunnel_filter,
                               uint8_t add);
index 71eb31f..c37343f 100644 (file)
@@ -21,6 +21,7 @@
 #include <rte_tcp.h>
 #include <rte_sctp.h>
 #include <rte_hash_crc.h>
+#include <rte_bitmap.h>
 
 #include "i40e_logs.h"
 #include "base/i40e_type.h"
@@ -244,6 +245,10 @@ i40e_fdir_setup(struct i40e_pf *pf)
        pf->fdir.dma_addr = mz->iova;
 
        pf->fdir.match_counter_index = I40E_COUNTER_INDEX_FDIR(hw->pf_id);
+       pf->fdir.fdir_actual_cnt = 0;
+       pf->fdir.fdir_guarantee_free_space =
+               pf->fdir.fdir_guarantee_total_space;
+
        PMD_DRV_LOG(INFO, "FDIR setup successfully, with programming queue %u.",
                    vsi->base_queue);
        return I40E_SUCCESS;
@@ -1762,6 +1767,11 @@ i40e_flow_add_del_fdir_filter(struct rte_eth_dev *dev,
        }
 
        if (add) {
+               fdir_info->fdir_actual_cnt++;
+               if (fdir_info->fdir_invalprio == 1 &&
+                               fdir_info->fdir_guarantee_free_space > 0)
+                       fdir_info->fdir_guarantee_free_space--;
+
                fdir_filter = rte_zmalloc("fdir_filter",
                                          sizeof(*fdir_filter), 0);
                if (fdir_filter == NULL) {
@@ -1774,6 +1784,12 @@ i40e_flow_add_del_fdir_filter(struct rte_eth_dev *dev,
                if (ret < 0)
                        rte_free(fdir_filter);
        } else {
+               fdir_info->fdir_actual_cnt--;
+               if (fdir_info->fdir_invalprio == 1 &&
+                               fdir_info->fdir_guarantee_free_space <
+                               fdir_info->fdir_guarantee_total_space)
+                       fdir_info->fdir_guarantee_free_space++;
+
                ret = i40e_sw_fdir_filter_del(pf, &node->fdir.input);
        }
 
index 7cd5373..1f2da79 100644 (file)
@@ -17,6 +17,7 @@
 #include <rte_malloc.h>
 #include <rte_tailq.h>
 #include <rte_flow_driver.h>
+#include <rte_bitmap.h>
 
 #include "i40e_logs.h"
 #include "base/i40e_type.h"
@@ -5601,6 +5602,10 @@ i40e_flow_flush_fdir_filter(struct i40e_pf *pf)
                        }
                }
 
+               fdir_info->fdir_actual_cnt = 0;
+               fdir_info->fdir_guarantee_free_space =
+                       fdir_info->fdir_guarantee_total_space;
+
                for (pctype = I40E_FILTER_PCTYPE_NONF_IPV4_UDP;
                     pctype <= I40E_FILTER_PCTYPE_L2_PAYLOAD; pctype++)
                        pf->fdir.inset_flag[pctype] = 0;
index 2d2efb7..d21fbea 100644 (file)
@@ -2989,6 +2989,7 @@ i40e_fdir_setup_tx_resources(struct i40e_pf *pf)
 
        txq->tx_ring_phys_addr = tz->iova;
        txq->tx_ring = (struct i40e_tx_desc *)tz->addr;
+
        /*
         * don't need to allocate software ring and reset for the fdir
         * program queue just set the queue has been configured.