From: Long Wu <long...@corigine.com> The firmware rules limitation is enlarged to 2056(8 Eth + 1024 IPv4 + 1024 IPv6 rules). So enlarge the flow rules limitation and add more precise checks to flow count.
Signed-off-by: Long Wu <long...@corigine.com> Reviewed-by: Chaoyong He <chaoyong...@corigine.com> Reviewed-by: Peng Zhang <peng.zh...@corigine.com> --- drivers/net/nfp/nfp_net_common.h | 16 +++++- drivers/net/nfp/nfp_net_flow.c | 87 +++++++++++++++++++++++++++++--- 2 files changed, 94 insertions(+), 9 deletions(-) diff --git a/drivers/net/nfp/nfp_net_common.h b/drivers/net/nfp/nfp_net_common.h index 8e3e219261..6db849eb07 100644 --- a/drivers/net/nfp/nfp_net_common.h +++ b/drivers/net/nfp/nfp_net_common.h @@ -165,12 +165,24 @@ struct nfp_pf_dev { bool speed_updated; }; -#define NFP_NET_FLOW_LIMIT 1024 +#define NFP_NET_ETH_FLOW_LIMIT 8 +#define NFP_NET_IPV4_FLOW_LIMIT 1024 +#define NFP_NET_IPV6_FLOW_LIMIT 1024 + +#define NFP_NET_FLOW_LIMIT ((NFP_NET_ETH_FLOW_LIMIT) + \ + (NFP_NET_IPV4_FLOW_LIMIT) + \ + (NFP_NET_IPV6_FLOW_LIMIT)) + +struct nfp_net_flow_count { + uint16_t eth_count; + uint16_t ipv4_count; + uint16_t ipv6_count; +}; struct nfp_net_priv { uint32_t hash_seed; /**< Hash seed for hash tables in this structure. */ struct rte_hash *flow_table; /**< Hash table to store flow rules. */ - uint16_t flow_count; /**< Flow count in hash table */ + struct nfp_net_flow_count flow_count; /**< Flow count in hash table */ bool flow_position[NFP_NET_FLOW_LIMIT]; /**< Flow position array */ }; diff --git a/drivers/net/nfp/nfp_net_flow.c b/drivers/net/nfp/nfp_net_flow.c index b0d1a57d99..74dd67abd4 100644 --- a/drivers/net/nfp/nfp_net_flow.c +++ b/drivers/net/nfp/nfp_net_flow.c @@ -178,7 +178,8 @@ nfp_net_flow_free(struct nfp_net_priv *priv, static int nfp_net_flow_calculate_items(const struct rte_flow_item items[], - uint32_t *match_len) + uint32_t *match_len, + uint32_t *item_type) { int ret = -EINVAL; const struct rte_flow_item *item; @@ -188,15 +189,18 @@ nfp_net_flow_calculate_items(const struct rte_flow_item items[], case RTE_FLOW_ITEM_TYPE_ETH: PMD_DRV_LOG(DEBUG, "RTE_FLOW_ITEM_TYPE_ETH detected"); *match_len = sizeof(struct nfp_net_cmsg_match_eth); + *item_type = RTE_FLOW_ITEM_TYPE_ETH; ret = 0; break; case RTE_FLOW_ITEM_TYPE_IPV4: PMD_DRV_LOG(DEBUG, "RTE_FLOW_ITEM_TYPE_IPV4 detected"); *match_len = sizeof(struct nfp_net_cmsg_match_v4); + *item_type = RTE_FLOW_ITEM_TYPE_IPV4; return 0; case RTE_FLOW_ITEM_TYPE_IPV6: PMD_DRV_LOG(DEBUG, "RTE_FLOW_ITEM_TYPE_IPV6 detected"); *match_len = sizeof(struct nfp_net_cmsg_match_v6); + *item_type = RTE_FLOW_ITEM_TYPE_IPV6; return 0; default: PMD_DRV_LOG(ERR, "Can't calculate match length"); @@ -643,6 +647,66 @@ nfp_net_flow_process_priority(struct rte_flow *nfp_flow, } } +static int +nfp_net_flow_check_count(struct nfp_net_flow_count *flow_count, + uint32_t item_type) +{ + int ret = 0; + + switch (item_type) { + case RTE_FLOW_ITEM_TYPE_ETH: + if (flow_count->eth_count >= NFP_NET_ETH_FLOW_LIMIT) + ret = -ENOSPC; + break; + case RTE_FLOW_ITEM_TYPE_IPV4: + if (flow_count->ipv4_count >= NFP_NET_IPV4_FLOW_LIMIT) + ret = -ENOSPC; + break; + case RTE_FLOW_ITEM_TYPE_IPV6: + if (flow_count->ipv6_count >= NFP_NET_IPV6_FLOW_LIMIT) + ret = -ENOSPC; + break; + default: + ret = -ENOTSUP; + break; + } + + return ret; +} + +static int +nfp_net_flow_calculate_count(struct rte_flow *nfp_flow, + struct nfp_net_flow_count *flow_count, + bool delete_flag) +{ + uint16_t *count; + + switch (nfp_flow->payload.cmsg_type) { + case NFP_NET_CFG_MBOX_CMD_FS_ADD_V4: + case NFP_NET_CFG_MBOX_CMD_FS_DEL_V4: + count = &flow_count->ipv4_count; + break; + case NFP_NET_CFG_MBOX_CMD_FS_ADD_V6: + case NFP_NET_CFG_MBOX_CMD_FS_DEL_V6: + count = &flow_count->ipv6_count; + break; + case NFP_NET_CFG_MBOX_CMD_FS_ADD_ETHTYPE: + case NFP_NET_CFG_MBOX_CMD_FS_DEL_ETHTYPE: + count = &flow_count->eth_count; + break; + default: + PMD_DRV_LOG(ERR, "Flow count calculate failed."); + return -EINVAL; + } + + if (delete_flag) + (*count)--; + else + (*count)++; + + return 0; +} + static struct rte_flow * nfp_net_flow_setup(struct rte_eth_dev *dev, const struct rte_flow_attr *attr, @@ -652,6 +716,7 @@ nfp_net_flow_setup(struct rte_eth_dev *dev, int ret; char *hash_data; uint32_t port_id; + uint32_t item_type; uint32_t action_len; struct nfp_net_hw *hw; uint32_t match_len = 0; @@ -666,12 +731,18 @@ nfp_net_flow_setup(struct rte_eth_dev *dev, app_fw_nic = NFP_PRIV_TO_APP_FW_NIC(hw_priv->pf_dev->app_fw_priv); priv = app_fw_nic->ports[hw->idx]->priv; - ret = nfp_net_flow_calculate_items(items, &match_len); + ret = nfp_net_flow_calculate_items(items, &match_len, &item_type); if (ret != 0) { PMD_DRV_LOG(ERR, "Key layers calculate failed."); return NULL; } + ret = nfp_net_flow_check_count(&priv->flow_count, item_type); + if (ret != 0) { + PMD_DRV_LOG(ERR, "Flow count check failed."); + return NULL; + } + action_len = sizeof(struct nfp_net_cmsg_action); port_id = ((struct nfp_net_hw *)dev->data->dev_private)->nfp_idx; @@ -705,7 +776,11 @@ nfp_net_flow_setup(struct rte_eth_dev *dev, goto free_flow; } - priv->flow_count++; + ret = nfp_net_flow_calculate_count(nfp_flow, &priv->flow_count, false); + if (ret != 0) { + PMD_DRV_LOG(ERR, "NFP flow calculate count failed."); + goto free_flow; + } nfp_net_flow_process_priority(nfp_flow, match_len); @@ -719,11 +794,9 @@ nfp_net_flow_setup(struct rte_eth_dev *dev, static int nfp_net_flow_teardown(struct nfp_net_priv *priv, - __rte_unused struct rte_flow *nfp_flow) + struct rte_flow *nfp_flow) { - priv->flow_count--; - - return 0; + return nfp_net_flow_calculate_count(nfp_flow, &priv->flow_count, true); } static int -- 2.39.1