[v2,4/4] net/nfp: add support for merged flows and conntrack stats

Message ID 20231004093602.1278126-5-chaoyong.he@corigine.com (mailing list archive)
State Accepted, archived
Delegated to: Ferruh Yigit
Headers
Series support offload of simple conntrack flow rules |

Checks

Context Check Description
ci/checkpatch success coding style OK
ci/loongarch-compilation success Compilation OK
ci/loongarch-unit-testing success Unit Testing PASS
ci/iol-mellanox-Performance success Performance Testing PASS
ci/iol-broadcom-Performance success Performance Testing PASS
ci/iol-intel-Performance success Performance Testing PASS
ci/iol-broadcom-Functional success Functional Testing PASS
ci/github-robot: build success github build: passed
ci/iol-intel-Functional success Functional Testing PASS
ci/iol-unit-arm64-testing success Testing PASS
ci/iol-unit-amd64-testing success Testing PASS
ci/iol-compile-amd64-testing success Testing PASS
ci/iol-compile-arm64-testing success Testing PASS
ci/iol-sample-apps-testing success Testing PASS

Commit Message

Chaoyong He Oct. 4, 2023, 9:36 a.m. UTC
  Adjust the original logic to make it valid for both normal flow
and merged flow.
Add the logic to update conntrack flow stats.
Add the support of conntrack action.

Signed-off-by: Chaoyong He <chaoyong.he@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(-)
  

Patch

diff --git a/drivers/net/nfp/flower/nfp_conntrack.c b/drivers/net/nfp/flower/nfp_conntrack.c
index 2ea856ebab..aacd4d7dd3 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;
@@ -989,12 +991,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);
@@ -1004,7 +1008,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;
@@ -1692,14 +1696,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.");
@@ -1710,7 +1714,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.");
@@ -1720,3 +1724,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,