Adjust the original logic to make it valid for both normal flow and merged flow. Add the logic to update ct flow stats. Add the support of conntrack action.
Signed-off-by: Chaoyong He <chaoyong...@corigine.com> --- drivers/net/nfp/flower/nfp_conntrack.c | 54 ++++++++++++++++-- drivers/net/nfp/flower/nfp_conntrack.h | 3 + drivers/net/nfp/nfp_flow.c | 79 ++++++++++++++++++++++---- drivers/net/nfp/nfp_flow.h | 7 ++- 4 files changed, 126 insertions(+), 17 deletions(-) diff --git a/drivers/net/nfp/flower/nfp_conntrack.c b/drivers/net/nfp/flower/nfp_conntrack.c index d81e2970fb..3df2411ce4 100644 --- a/drivers/net/nfp/flower/nfp_conntrack.c +++ b/drivers/net/nfp/flower/nfp_conntrack.c @@ -39,6 +39,7 @@ struct nfp_ct_flow_entry { struct nfp_flower_representor *repr; struct nfp_ct_zone_entry *ze; struct nfp_initial_flow rule; + struct nfp_fl_stats stats; }; struct nfp_ct_map_entry { @@ -56,6 +57,7 @@ struct nfp_ct_zone_entry { struct nfp_ct_merge_entry { uint64_t cookie[2]; + uint32_t ctx_id; LIST_ENTRY(nfp_ct_merge_entry) pre_ct_list; LIST_ENTRY(nfp_ct_merge_entry) post_ct_list; struct nfp_initial_flow rule; @@ -999,12 +1001,14 @@ nfp_ct_offload_add(struct nfp_flower_representor *repr, cookie = rte_rand(); items = merge_entry->rule.items; actions = merge_entry->rule.actions; - nfp_flow = nfp_flow_process(repr, items, actions, false, cookie, true); + nfp_flow = nfp_flow_process(repr, items, actions, false, cookie, true, true); if (nfp_flow == NULL) { PMD_DRV_LOG(ERR, "Process the merged flow rule failed."); return -EINVAL; } + merge_entry->ctx_id = rte_be_to_cpu_32(nfp_flow->payload.meta->host_ctx_id); + /* Add the flow to hardware */ priv = repr->app_fw_flower->flow_priv; ret = nfp_flower_cmsg_flow_add(repr->app_fw_flower, nfp_flow); @@ -1014,7 +1018,7 @@ nfp_ct_offload_add(struct nfp_flower_representor *repr, } /* Add the flow to flow hash table */ - ret = nfp_flow_table_add(priv, nfp_flow); + ret = nfp_flow_table_add_merge(priv, nfp_flow); if (ret != 0) { PMD_DRV_LOG(ERR, "Add the merged flow to flow table failed."); goto flow_teardown; @@ -1702,14 +1706,14 @@ nfp_ct_flow_setup(struct nfp_flower_representor *representor, if (is_ct_commit_flow(ct)) { return nfp_flow_process(representor, &items[1], actions, - validate_flag, cookie, false); + validate_flag, cookie, false, false); } if (is_post_ct_flow(ct)) { if (nfp_flow_handle_post_ct(ct_item, representor, &items[1], actions, cookie)) { return nfp_flow_process(representor, &items[1], actions, - validate_flag, cookie, false); + validate_flag, cookie, false, false); } PMD_DRV_LOG(ERR, "Handle nfp post ct flow failed."); @@ -1720,7 +1724,7 @@ nfp_ct_flow_setup(struct nfp_flower_representor *representor, if (nfp_flow_handle_pre_ct(ct_item, representor, &items[1], actions, cookie)) { return nfp_flow_process(representor, &items[1], actions, - validate_flag, cookie, false); + validate_flag, cookie, false, false); } PMD_DRV_LOG(ERR, "Handle nfp pre ct flow failed."); @@ -1730,3 +1734,43 @@ nfp_ct_flow_setup(struct nfp_flower_representor *representor, PMD_DRV_LOG(ERR, "Unsupported ct flow type."); return NULL; } + +static inline void +nfp_ct_flow_stats_update(struct nfp_flow_priv *priv, + struct nfp_ct_merge_entry *m_ent) +{ + uint32_t ctx_id; + struct nfp_fl_stats *merge_stats; + + ctx_id = m_ent->ctx_id; + merge_stats = &priv->stats[ctx_id]; + + m_ent->pre_ct_parent->stats.bytes += merge_stats->bytes; + m_ent->pre_ct_parent->stats.pkts += merge_stats->pkts; + m_ent->post_ct_parent->stats.bytes += merge_stats->bytes; + m_ent->post_ct_parent->stats.pkts += merge_stats->pkts; + + merge_stats->bytes = 0; + merge_stats->pkts = 0; +} + +struct nfp_fl_stats * +nfp_ct_flow_stats_get(struct nfp_flow_priv *priv, + struct nfp_ct_map_entry *me) +{ + struct nfp_ct_merge_entry *m_ent; + + rte_spinlock_lock(&priv->stats_lock); + + if (me->fe->type == CT_TYPE_PRE_CT) { + LIST_FOREACH(m_ent, &me->fe->children, pre_ct_list) + nfp_ct_flow_stats_update(priv, m_ent); + } else { + LIST_FOREACH(m_ent, &me->fe->children, post_ct_list) + nfp_ct_flow_stats_update(priv, m_ent); + } + + rte_spinlock_unlock(&priv->stats_lock); + + return &me->fe->stats; +} diff --git a/drivers/net/nfp/flower/nfp_conntrack.h b/drivers/net/nfp/flower/nfp_conntrack.h index 2f47280716..5abab4e984 100644 --- a/drivers/net/nfp/flower/nfp_conntrack.h +++ b/drivers/net/nfp/flower/nfp_conntrack.h @@ -34,4 +34,7 @@ struct rte_flow *nfp_ct_flow_setup(struct nfp_flower_representor *representor, bool validate_flag, uint64_t cookie); +struct nfp_fl_stats *nfp_ct_flow_stats_get(struct nfp_flow_priv *priv, + struct nfp_ct_map_entry *me); + #endif /* __NFP_CONNTRACK_H__ */ diff --git a/drivers/net/nfp/nfp_flow.c b/drivers/net/nfp/nfp_flow.c index a6439679d3..020e31e9de 100644 --- a/drivers/net/nfp/nfp_flow.c +++ b/drivers/net/nfp/nfp_flow.c @@ -310,14 +310,14 @@ nfp_check_mask_add(struct nfp_flow_priv *priv, ret = nfp_mask_table_add(priv, mask_data, mask_len, mask_id); if (ret != 0) return false; - - *meta_flags |= NFP_FL_META_FLAG_MANAGE_MASK; } else { /* mask entry already exist */ mask_entry->ref_cnt++; *mask_id = mask_entry->mask_id; } + *meta_flags |= NFP_FL_META_FLAG_MANAGE_MASK; + return true; } @@ -349,7 +349,7 @@ nfp_check_mask_remove(struct nfp_flow_priv *priv, return true; } -int +static int nfp_flow_table_add(struct nfp_flow_priv *priv, struct rte_flow *nfp_flow) { @@ -396,6 +396,48 @@ nfp_flow_table_search(struct nfp_flow_priv *priv, return flow_find; } +int +nfp_flow_table_add_merge(struct nfp_flow_priv *priv, + struct rte_flow *nfp_flow) +{ + struct rte_flow *flow_find; + + flow_find = nfp_flow_table_search(priv, nfp_flow); + if (flow_find != NULL) { + if (nfp_flow->merge_flag || flow_find->merge_flag) { + flow_find->merge_flag = true; + flow_find->ref_cnt++; + return 0; + } + + PMD_DRV_LOG(ERR, "Add to flow table failed."); + return -EINVAL; + } + + return nfp_flow_table_add(priv, nfp_flow); +} + +static int +nfp_flow_table_delete_merge(struct nfp_flow_priv *priv, + struct rte_flow *nfp_flow) +{ + struct rte_flow *flow_find; + + flow_find = nfp_flow_table_search(priv, nfp_flow); + if (flow_find == NULL) { + PMD_DRV_LOG(ERR, "Can't delete a non-existing flow."); + return -EINVAL; + } + + if (nfp_flow->merge_flag || flow_find->merge_flag) { + flow_find->ref_cnt--; + if (flow_find->ref_cnt > 0) + return 0; + } + + return nfp_flow_table_delete(priv, nfp_flow); +} + static struct rte_flow * nfp_flow_alloc(struct nfp_fl_key_ls *key_layer, uint32_t port_id) { @@ -1082,6 +1124,9 @@ nfp_flow_key_layers_calculate_actions(const struct rte_flow_action actions[], return -ENOTSUP; } break; + case RTE_FLOW_ACTION_TYPE_CONNTRACK: + PMD_DRV_LOG(DEBUG, "RTE_FLOW_ACTION_TYPE_CONNTRACK detected"); + break; default: PMD_DRV_LOG(ERR, "Action type %d not supported.", action->type); return -ENOTSUP; @@ -3626,6 +3671,9 @@ nfp_flow_compile_action(struct nfp_flower_representor *representor, return -EINVAL; position += sizeof(struct nfp_fl_act_meter); break; + case RTE_FLOW_ACTION_TYPE_CONNTRACK: + PMD_DRV_LOG(DEBUG, "Process RTE_FLOW_ACTION_TYPE_CONNTRACK"); + break; default: PMD_DRV_LOG(ERR, "Unsupported action type: %d", action->type); return -ENOTSUP; @@ -3647,7 +3695,8 @@ nfp_flow_process(struct nfp_flower_representor *representor, const struct rte_flow_action actions[], bool validate_flag, uint64_t cookie, - bool install_flag) + bool install_flag, + bool merge_flag) { int ret; char *hash_data; @@ -3684,6 +3733,7 @@ nfp_flow_process(struct nfp_flower_representor *representor, } nfp_flow->install_flag = install_flag; + nfp_flow->merge_flag = merge_flag; nfp_flow_compile_metadata(priv, nfp_flow, &key_layer, stats_ctx, cookie); @@ -3717,7 +3767,7 @@ nfp_flow_process(struct nfp_flower_representor *representor, /* Find the flow in hash table */ flow_find = nfp_flow_table_search(priv, nfp_flow); - if (flow_find != NULL) { + if (flow_find != NULL && !nfp_flow->merge_flag && !flow_find->merge_flag) { PMD_DRV_LOG(ERR, "This flow is already exist."); if (!nfp_check_mask_remove(priv, mask_data, mask_len, &nfp_flow_meta->flags)) { @@ -3774,7 +3824,7 @@ nfp_flow_setup(struct nfp_flower_representor *representor, return nfp_ct_flow_setup(representor, items, actions, ct_item, validate_flag, cookie); - return nfp_flow_process(representor, items, actions, validate_flag, cookie, true); + return nfp_flow_process(representor, items, actions, validate_flag, cookie, true, false); } int @@ -3877,7 +3927,7 @@ nfp_flow_create(struct rte_eth_dev *dev, } /* Add the flow to flow hash table */ - ret = nfp_flow_table_add(priv, nfp_flow); + ret = nfp_flow_table_add_merge(priv, nfp_flow); if (ret != 0) { rte_flow_error_set(error, EINVAL, RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL, "Add flow to the flow table failed."); @@ -3988,7 +4038,7 @@ nfp_flow_destroy(struct rte_eth_dev *dev, } /* Delete the flow from flow hash table */ - ret = nfp_flow_table_delete(priv, nfp_flow); + ret = nfp_flow_table_delete_merge(priv, nfp_flow); if (ret != 0) { rte_flow_error_set(error, EINVAL, RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL, "Delete flow from the flow table failed."); @@ -4047,10 +4097,12 @@ nfp_flow_stats_get(struct rte_eth_dev *dev, void *data) { bool reset; + uint64_t cookie; uint32_t ctx_id; struct rte_flow *flow; struct nfp_flow_priv *priv; struct nfp_fl_stats *stats; + struct nfp_ct_map_entry *me; struct rte_flow_query_count *query; priv = nfp_flow_dev_to_priv(dev); @@ -4064,8 +4116,15 @@ nfp_flow_stats_get(struct rte_eth_dev *dev, reset = query->reset; memset(query, 0, sizeof(*query)); - ctx_id = rte_be_to_cpu_32(nfp_flow->payload.meta->host_ctx_id); - stats = &priv->stats[ctx_id]; + /* Find the flow in ct_map_table */ + cookie = rte_be_to_cpu_64(nfp_flow->payload.meta->host_cookie); + me = nfp_ct_map_table_search(priv, (char *)&cookie, sizeof(uint64_t)); + if (me != NULL) { + stats = nfp_ct_flow_stats_get(priv, me); + } else { + ctx_id = rte_be_to_cpu_32(nfp_flow->payload.meta->host_ctx_id); + stats = &priv->stats[ctx_id]; + } rte_spinlock_lock(&priv->stats_lock); if (stats->pkts != 0 && stats->bytes != 0) { diff --git a/drivers/net/nfp/nfp_flow.h b/drivers/net/nfp/nfp_flow.h index df16cab8b5..ed06eca371 100644 --- a/drivers/net/nfp/nfp_flow.h +++ b/drivers/net/nfp/nfp_flow.h @@ -165,7 +165,9 @@ struct rte_flow { uint32_t port_id; bool install_flag; bool tcp_flag; /**< Used in the SET_TP_* action */ + bool merge_flag; enum nfp_flow_type type; + uint16_t ref_cnt; }; /* Forward declaration */ @@ -181,8 +183,9 @@ struct rte_flow *nfp_flow_process(struct nfp_flower_representor *representor, const struct rte_flow_action actions[], bool validate_flag, uint64_t cookie, - bool install_flag); -int nfp_flow_table_add(struct nfp_flow_priv *priv, + bool install_flag, + bool merge_flag); +int nfp_flow_table_add_merge(struct nfp_flow_priv *priv, struct rte_flow *nfp_flow); int nfp_flow_teardown(struct nfp_flow_priv *priv, struct rte_flow *nfp_flow, -- 2.39.1