From: Chenmin Sun Date: Fri, 17 Jul 2020 17:36:55 +0000 (+0800) Subject: net/i40e: support flow director space tracking X-Git-Url: http://git.droids-corp.org/?a=commitdiff_plain;h=f97d6192d511efccdcb45b0a2cc8e2fa07c97258;p=dpdk.git net/i40e: support flow director space tracking 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 Reviewed-by: Jingjing Wu --- diff --git a/drivers/net/i40e/i40e_ethdev.c b/drivers/net/i40e/i40e_ethdev.c index 393b5320f5..dca84a1f10 100644 --- a/drivers/net/i40e/i40e_ethdev.c +++ b/drivers/net/i40e/i40e_ethdev.c @@ -26,6 +26,7 @@ #include #include #include +#include #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; diff --git a/drivers/net/i40e/i40e_ethdev.h b/drivers/net/i40e/i40e_ethdev.h index 31ca05de98..eb505c7997 100644 --- a/drivers/net/i40e/i40e_ethdev.h +++ b/drivers/net/i40e/i40e_ethdev.h @@ -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); diff --git a/drivers/net/i40e/i40e_fdir.c b/drivers/net/i40e/i40e_fdir.c index 71eb31fb8b..c37343f8f8 100644 --- a/drivers/net/i40e/i40e_fdir.c +++ b/drivers/net/i40e/i40e_fdir.c @@ -21,6 +21,7 @@ #include #include #include +#include #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); } diff --git a/drivers/net/i40e/i40e_flow.c b/drivers/net/i40e/i40e_flow.c index 7cd537340d..1f2da79265 100644 --- a/drivers/net/i40e/i40e_flow.c +++ b/drivers/net/i40e/i40e_flow.c @@ -17,6 +17,7 @@ #include #include #include +#include #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; diff --git a/drivers/net/i40e/i40e_rxtx.c b/drivers/net/i40e/i40e_rxtx.c index 2d2efb71a5..d21fbeaca2 100644 --- a/drivers/net/i40e/i40e_rxtx.c +++ b/drivers/net/i40e/i40e_rxtx.c @@ -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.