DPDK patches and discussions
 help / color / mirror / Atom feed
* [dpdk-dev] [PATCH] examples/ipsec-secgw: support more flow patterns and actions
@ 2022-04-19  8:25 psatheesh
  2022-05-24  5:32 ` [dpdk-dev] [PATCH v2] " psatheesh
                   ` (3 more replies)
  0 siblings, 4 replies; 11+ messages in thread
From: psatheesh @ 2022-04-19  8:25 UTC (permalink / raw)
  To: Radu Nicolau, Akhil Goyal; +Cc: dev, Satheesh Paul

From: Satheesh Paul <psatheesh@marvell.com>

Added support to create flows with count, mark and security
actions and mark pattern. The flow configuration can be done
with these pattern and actions in the below format in the
configuration file.

flow [mark <val>] [eth] [ipv4 | ipv6] <src>|<dst> \
     <ipv4_addr_string|ipv6_addr_string> port <val> queue <val> \
     [count] [security] [set_mark <val>]

mark <val>:
     Set RTE_FLOW_ITEM_TYPE_MARK pattern item with value <val>
eth:
     Set RTE_FLOW_ITEM_TYPE_ETH pattern item. This matches all
     ethernet packets.
ipv4 | ipv6 <src>|<dst>:
     Set RTE_FLOW_ITEM_TYPE_IPV4|RTE_FLOW_ITEM_TYPE_IPV6 pattern
     with given ipv4 or ipv6 address as source or destination.
port <val>:
     Create flow rule on port <val>.
queue <val>:
     Set RTE_FLOW_ACTION_TYPE_QUEUE action with queue <val>.
count:
     Set RTE_FLOW_ACTION_TYPE_COUNT action.
security:
     Set RTE_FLOW_ITEM_TYPE_ESP pattern and
     RTE_FLOW_ACTION_TYPE_SECURITY action.
set_mark <val>:
     Set RTE_FLOW_ACTION_TYPE_MARK action with <val> as mark.

Examples:
     flow mark 123 ipv4 dst 192.168.0.0/16 port 0 queue 0 count
     flow eth ipv4 dst 192.168.0.0/16 port 0 queue 0 count
     flow ipv4 dst 192.168.0.0/16 port 0 queue 0 count
     flow ipv4 dst 192.168.0.0/16 port 0 queue 0
     flow port 0 security set_mark 123
     flow ipv4 dst 1.1.0.0/16 port 0 count set_mark 123 security

Signed-off-by: Satheesh Paul <psatheesh@marvell.com>
---
 examples/ipsec-secgw/flow.c        | 280 +++++++++++++++++++++++------
 examples/ipsec-secgw/flow.h        |   1 +
 examples/ipsec-secgw/ipsec-secgw.c |   3 +-
 3 files changed, 233 insertions(+), 51 deletions(-)

diff --git a/examples/ipsec-secgw/flow.c b/examples/ipsec-secgw/flow.c
index 1a1ec7861c..23962f35e7 100644
--- a/examples/ipsec-secgw/flow.c
+++ b/examples/ipsec-secgw/flow.c
@@ -15,7 +15,9 @@
 #define FLOW_RULES_MAX 128
 
 struct flow_rule_entry {
+	uint8_t is_eth;
 	uint8_t is_ipv4;
+	uint8_t is_ipv6;
 	RTE_STD_C11
 	union {
 		struct {
@@ -27,8 +29,15 @@ struct flow_rule_entry {
 			struct rte_flow_item_ipv6 mask;
 		} ipv6;
 	};
+	struct rte_flow_item_mark mark_val;
 	uint16_t port;
 	uint16_t queue;
+	bool is_queue_set;
+	bool enable_count;
+	bool enable_mark;
+	bool set_security_action;
+	bool set_mark_action;
+	uint32_t mark_action_val;
 	struct rte_flow *flow;
 } flow_rule_tbl[FLOW_RULES_MAX];
 
@@ -64,8 +73,9 @@ ipv4_addr_cpy(rte_be32_t *spec, rte_be32_t *mask, char *token,
 	memcpy(mask, &rte_flow_item_ipv4_mask.hdr.src_addr, sizeof(ip));
 
 	*spec = ip.s_addr;
+
 	if (depth < 32)
-		*mask = *mask << (32-depth);
+		*mask = htonl(*mask << (32 - depth));
 
 	return 0;
 }
@@ -124,7 +134,7 @@ parse_flow_tokens(char **tokens, uint32_t n_tokens,
 		  struct parse_status *status)
 {
 	struct flow_rule_entry *rule;
-	uint32_t ti;
+	uint32_t ti = 0;
 
 	if (nb_flow_rule >= FLOW_RULES_MAX) {
 		printf("Too many flow rules\n");
@@ -134,49 +144,73 @@ parse_flow_tokens(char **tokens, uint32_t n_tokens,
 	rule = &flow_rule_tbl[nb_flow_rule];
 	memset(rule, 0, sizeof(*rule));
 
-	if (strcmp(tokens[0], "ipv4") == 0) {
-		rule->is_ipv4 = 1;
-	} else if (strcmp(tokens[0], "ipv6") == 0) {
-		rule->is_ipv4 = 0;
-	} else {
-		APP_CHECK(0, status, "unrecognized input \"%s\"", tokens[0]);
-		return;
-	}
-
-	for (ti = 1; ti < n_tokens; ti++) {
-		if (strcmp(tokens[ti], "src") == 0) {
+	for (ti = 0; ti < n_tokens; ti++) {
+		if (strcmp(tokens[ti], "mark") == 0) {
 			INCREMENT_TOKEN_INDEX(ti, n_tokens, status);
+			if (status->status < 0)
+				return;
+			APP_CHECK_TOKEN_IS_NUM(tokens, ti, status);
 			if (status->status < 0)
 				return;
 
-			if (rule->is_ipv4) {
+			rule->mark_val.id = atoi(tokens[ti]);
+			rule->enable_mark = true;
+			continue;
+		}
+		if (strcmp(tokens[ti], "eth") == 0) {
+			rule->is_eth = true;
+			continue;
+		}
+
+		if (strcmp(tokens[ti], "ipv4") == 0) {
+			rule->is_ipv4 = true;
+			INCREMENT_TOKEN_INDEX(ti, n_tokens, status);
+			if (status->status < 0)
+				return;
+			if (strcmp(tokens[ti], "src") == 0) {
+				INCREMENT_TOKEN_INDEX(ti, n_tokens, status);
+				if (status->status < 0)
+					return;
 				if (ipv4_addr_cpy(&rule->ipv4.spec.hdr.src_addr,
 						  &rule->ipv4.mask.hdr.src_addr,
 						  tokens[ti], status))
 					return;
-			} else {
-				if (ipv6_addr_cpy(rule->ipv6.spec.hdr.src_addr,
-						  rule->ipv6.mask.hdr.src_addr,
+			}
+			if (strcmp(tokens[ti], "dst") == 0) {
+				INCREMENT_TOKEN_INDEX(ti, n_tokens, status);
+				if (status->status < 0)
+					return;
+				if (ipv4_addr_cpy(&rule->ipv4.spec.hdr.src_addr,
+						  &rule->ipv4.mask.hdr.src_addr,
 						  tokens[ti], status))
 					return;
 			}
+			continue;
 		}
-		if (strcmp(tokens[ti], "dst") == 0) {
+		if (strcmp(tokens[ti], "ipv6") == 0) {
+			rule->is_ipv6 = true;
 			INCREMENT_TOKEN_INDEX(ti, n_tokens, status);
 			if (status->status < 0)
 				return;
-
-			if (rule->is_ipv4) {
-				if (ipv4_addr_cpy(&rule->ipv4.spec.hdr.dst_addr,
-						  &rule->ipv4.mask.hdr.dst_addr,
+			if (strcmp(tokens[ti], "src") == 0) {
+				INCREMENT_TOKEN_INDEX(ti, n_tokens, status);
+				if (status->status < 0)
+					return;
+				if (ipv6_addr_cpy(rule->ipv6.spec.hdr.src_addr,
+						  rule->ipv6.mask.hdr.src_addr,
 						  tokens[ti], status))
 					return;
-			} else {
-				if (ipv6_addr_cpy(rule->ipv6.spec.hdr.dst_addr,
-						  rule->ipv6.mask.hdr.dst_addr,
+			}
+			if (strcmp(tokens[ti], "dst") == 0) {
+				INCREMENT_TOKEN_INDEX(ti, n_tokens, status);
+				if (status->status < 0)
+					return;
+				if (ipv6_addr_cpy(rule->ipv6.spec.hdr.src_addr,
+						  rule->ipv6.mask.hdr.src_addr,
 						  tokens[ti], status))
 					return;
 			}
+			continue;
 		}
 
 		if (strcmp(tokens[ti], "port") == 0) {
@@ -188,6 +222,7 @@ parse_flow_tokens(char **tokens, uint32_t n_tokens,
 				return;
 
 			rule->port = atoi(tokens[ti]);
+			continue;
 		}
 
 		if (strcmp(tokens[ti], "queue") == 0) {
@@ -199,50 +234,129 @@ parse_flow_tokens(char **tokens, uint32_t n_tokens,
 				return;
 
 			rule->queue = atoi(tokens[ti]);
+			rule->is_queue_set = true;
+			continue;
+		}
+
+		if (strcmp(tokens[ti], "count") == 0) {
+			rule->enable_count = true;
+			continue;
+		}
+
+		if (strcmp(tokens[ti], "security") == 0) {
+			rule->set_security_action = true;
+			continue;
 		}
+
+		if (strcmp(tokens[ti], "set_mark") == 0) {
+			INCREMENT_TOKEN_INDEX(ti, n_tokens, status);
+			if (status->status < 0)
+				return;
+			APP_CHECK_TOKEN_IS_NUM(tokens, ti, status);
+			if (status->status < 0)
+				return;
+
+			rule->set_mark_action = true;
+			rule->mark_action_val = atoi(tokens[ti]);
+			continue;
+		}
+
+		sprintf(status->parse_msg, "Unrecognized input:%s\n", tokens[ti]);
+		status->status = -1;
+		return;
 	}
+	printf("\n");
 
 	nb_flow_rule++;
 }
 
-#define MAX_RTE_FLOW_PATTERN (3)
-#define MAX_RTE_FLOW_ACTIONS (2)
+#define MAX_RTE_FLOW_PATTERN (4)
+#define MAX_RTE_FLOW_ACTIONS (5)
 
 static void
 flow_init_single(struct flow_rule_entry *rule)
 {
-	struct rte_flow_item pattern[MAX_RTE_FLOW_PATTERN] = {};
 	struct rte_flow_action action[MAX_RTE_FLOW_ACTIONS] = {};
+	struct rte_flow_item pattern[MAX_RTE_FLOW_PATTERN] = {};
+	struct rte_flow_action_queue queue_action;
+	struct rte_flow_action_mark mark_action;
+	int ret, pattern_idx = 0, act_idx = 0;
+	struct rte_flow_item_mark mark_mask;
 	struct rte_flow_attr attr = {};
-	struct rte_flow_error err;
-	int ret;
+	struct rte_flow_error err = {};
 
 	attr.egress = 0;
 	attr.ingress = 1;
 
-	action[0].type = RTE_FLOW_ACTION_TYPE_QUEUE;
-	action[0].conf = &(struct rte_flow_action_queue) {
-				.index = rule->queue,
-	};
-	action[1].type = RTE_FLOW_ACTION_TYPE_END;
+	if (rule->is_queue_set) {
+		queue_action.index = rule->queue;
+		action[act_idx].type = RTE_FLOW_ACTION_TYPE_QUEUE;
+		action[act_idx].conf = &queue_action;
+		act_idx++;
+	}
+
+	if (rule->enable_count) {
+		action[act_idx].type = RTE_FLOW_ACTION_TYPE_COUNT;
+		act_idx++;
+	}
+
+	if (rule->set_security_action) {
+		action[act_idx].type = RTE_FLOW_ACTION_TYPE_SECURITY;
+		action[act_idx].conf = NULL;
+		act_idx++;
+	}
+
+	if (rule->set_mark_action) {
+		mark_action.id = rule->mark_action_val;
+		action[act_idx].type = RTE_FLOW_ACTION_TYPE_MARK;
+		action[act_idx].conf = &mark_action;
+		act_idx++;
+	}
 
-	pattern[0].type = RTE_FLOW_ITEM_TYPE_ETH;
+	action[act_idx].type = RTE_FLOW_ACTION_TYPE_END;
+	action[act_idx].conf = NULL;
+
+	if (rule->enable_mark) {
+		mark_mask.id = UINT32_MAX;
+		pattern[pattern_idx].type = RTE_FLOW_ITEM_TYPE_MARK;
+		pattern[pattern_idx].spec = &rule->mark_val;
+		pattern[pattern_idx].mask = &mark_mask;
+		pattern_idx++;
+	}
+
+	if (rule->is_eth) {
+		pattern[pattern_idx].type = RTE_FLOW_ITEM_TYPE_ETH;
+		pattern_idx++;
+	}
 
 	if (rule->is_ipv4) {
-		pattern[1].type = RTE_FLOW_ITEM_TYPE_IPV4;
-		pattern[1].spec = &rule->ipv4.spec;
-		pattern[1].mask = &rule->ipv4.mask;
-	} else {
-		pattern[1].type = RTE_FLOW_ITEM_TYPE_IPV6;
-		pattern[1].spec = &rule->ipv6.spec;
-		pattern[1].mask = &rule->ipv6.mask;
+		pattern[pattern_idx].type = RTE_FLOW_ITEM_TYPE_IPV4;
+		pattern[pattern_idx].spec = &rule->ipv4.spec;
+		pattern[pattern_idx].mask = &rule->ipv4.mask;
+		pattern_idx++;
+	}
+
+	if (rule->is_ipv6) {
+		pattern[pattern_idx].type = RTE_FLOW_ITEM_TYPE_IPV6;
+		pattern[pattern_idx].spec = &rule->ipv6.spec;
+		pattern[pattern_idx].mask = &rule->ipv6.mask;
+		pattern_idx++;
+	}
+
+	if (rule->set_security_action) {
+		pattern[pattern_idx].type = RTE_FLOW_ITEM_TYPE_ESP;
+		pattern[pattern_idx].spec = NULL;
+		pattern[pattern_idx].mask = NULL;
+		pattern[pattern_idx].last = NULL;
+		pattern_idx++;
 	}
 
-	pattern[2].type = RTE_FLOW_ITEM_TYPE_END;
+	pattern[pattern_idx].type = RTE_FLOW_ITEM_TYPE_END;
 
 	ret = rte_flow_validate(rule->port, &attr, pattern, action, &err);
 	if (ret < 0) {
 		RTE_LOG(ERR, IPSEC, "Flow validation failed %s\n", err.message);
+		rule->flow = 0;
 		return;
 	}
 
@@ -251,6 +365,56 @@ flow_init_single(struct flow_rule_entry *rule)
 		RTE_LOG(ERR, IPSEC, "Flow creation return %s\n", err.message);
 }
 
+void
+flow_print_counters(void)
+{
+	struct rte_flow_query_count count_query;
+	struct rte_flow_action action;
+	struct flow_rule_entry *rule;
+	struct rte_flow_error error;
+	int i = 0, ret = 0;
+
+	action.type = RTE_FLOW_ACTION_TYPE_COUNT;
+
+	for (i = 0; i < nb_flow_rule; i++) {
+		rule = &flow_rule_tbl[i];
+		if (!rule->flow || !rule->enable_count)
+			continue;
+
+		/* Poisoning to make sure PMDs update it in case of error. */
+		memset(&error, 0x55, sizeof(error));
+		memset(&count_query, 0, sizeof(count_query));
+		ret = rte_flow_query(rule->port, rule->flow, &action,
+				     &count_query, &error);
+		if (ret)
+			RTE_LOG(ERR, IPSEC,
+				"Failed to get flow counter "
+				" for port %u, err msg: %s\n",
+				rule->port, error.message);
+
+		printf("Flow #%3d:", i);
+		if (rule->is_ipv4) {
+			printf(" spec ipv4 ");
+			ipv4_hdr_print(&rule->ipv4.spec.hdr);
+		}
+		if (rule->is_ipv6) {
+			printf(" spec ipv6 ");
+			ipv6_hdr_print(&rule->ipv6.spec.hdr);
+		}
+
+		if (rule->set_security_action)
+			printf(" Security action set,");
+
+		if (rule->enable_mark)
+			printf(" Mark Enabled");
+
+		printf(" Port: %d,", rule->port);
+		if (rule->is_queue_set)
+			printf(" Queue: %d", rule->queue);
+		printf(" Hits: %"PRIu64"\n", count_query.hits);
+	}
+}
+
 void
 flow_init(void)
 {
@@ -264,21 +428,37 @@ flow_init(void)
 
 	for (i = 0; i < nb_flow_rule; i++) {
 		rule = &flow_rule_tbl[i];
+		printf("Flow #%3d: ", i);
 		if (rule->is_ipv4) {
-			printf("Flow #%3d: spec ipv4 ", i);
+			printf("spec ipv4 ");
 			ipv4_hdr_print(&rule->ipv4.spec.hdr);
 			printf("\n");
-			printf("           mask ipv4 ");
+			printf(" mask ipv4 ");
 			ipv4_hdr_print(&rule->ipv4.mask.hdr);
-		} else {
-			printf("Flow #%3d: spec ipv6 ", i);
+		}
+		if (rule->is_ipv6) {
+			printf("spec ipv6 ");
 			ipv6_hdr_print(&rule->ipv6.spec.hdr);
 			printf("\n");
-			printf("           mask ipv6 ");
+			printf(" mask ipv6 ");
 			ipv6_hdr_print(&rule->ipv6.mask.hdr);
 		}
 
-		printf("\tPort: %d, Queue: %d", rule->port, rule->queue);
+		if (rule->enable_mark)
+			printf(", Mark enabled");
+
+		printf("\tPort: %d,", rule->port);
+		if (rule->is_queue_set)
+			printf(" Queue: %d,", rule->queue);
+
+		if (rule->set_security_action)
+			printf(" Security action set,");
+
+		if (rule->set_mark_action)
+			printf(" Mark: %d,", rule->mark_action_val);
+
+		if (rule->enable_count)
+			printf(" Counter enabled,");
 
 		if (rule->flow == NULL)
 			printf(" [UNSUPPORTED]");
diff --git a/examples/ipsec-secgw/flow.h b/examples/ipsec-secgw/flow.h
index 1b1b4774e4..9492d06346 100644
--- a/examples/ipsec-secgw/flow.h
+++ b/examples/ipsec-secgw/flow.h
@@ -11,5 +11,6 @@ void parse_flow_tokens(char **tokens, uint32_t n_tokens,
 		       struct parse_status *status);
 
 void flow_init(void);
+void flow_print_counters(void);
 
 #endif /* _FLOW_H_ */
diff --git a/examples/ipsec-secgw/ipsec-secgw.c b/examples/ipsec-secgw/ipsec-secgw.c
index 42b5081840..244453e06e 100644
--- a/examples/ipsec-secgw/ipsec-secgw.c
+++ b/examples/ipsec-secgw/ipsec-secgw.c
@@ -3271,7 +3271,6 @@ ipsec_secgw_telemetry_init(void)
 		"Optional Parameters: int <logical core id>");
 }
 
-
 int32_t
 main(int32_t argc, char **argv)
 {
@@ -3512,6 +3511,8 @@ main(int32_t argc, char **argv)
 		printf(" Done\n");
 	}
 
+	flow_print_counters();
+
 	RTE_ETH_FOREACH_DEV(portid) {
 		if ((enabled_port_mask & (1 << portid)) == 0)
 			continue;
-- 
2.25.4


^ permalink raw reply	[flat|nested] 11+ messages in thread

* [dpdk-dev] [PATCH v2] examples/ipsec-secgw: support more flow patterns and actions
  2022-04-19  8:25 [dpdk-dev] [PATCH] examples/ipsec-secgw: support more flow patterns and actions psatheesh
@ 2022-05-24  5:32 ` psatheesh
  2022-06-03  3:16 ` [dpdk-dev] [PATCH v3] " psatheesh
                   ` (2 subsequent siblings)
  3 siblings, 0 replies; 11+ messages in thread
From: psatheesh @ 2022-05-24  5:32 UTC (permalink / raw)
  To: Radu Nicolau, Akhil Goyal; +Cc: dev, Satheesh Paul

From: Satheesh Paul <psatheesh@marvell.com>

Added support to create flow rules with count, mark and
security actions and mark pattern.

Signed-off-by: Satheesh Paul <psatheesh@marvell.com>
---
v2:
* Updated documentation in ipsec_secgw.rst

 doc/guides/sample_app_ug/ipsec_secgw.rst |  58 ++++-
 examples/ipsec-secgw/flow.c              | 280 +++++++++++++++++++----
 examples/ipsec-secgw/flow.h              |   1 +
 examples/ipsec-secgw/ipsec-secgw.c       |   3 +-
 4 files changed, 288 insertions(+), 54 deletions(-)

diff --git a/doc/guides/sample_app_ug/ipsec_secgw.rst b/doc/guides/sample_app_ug/ipsec_secgw.rst
index d93acf0667..711026d2ef 100644
--- a/doc/guides/sample_app_ug/ipsec_secgw.rst
+++ b/doc/guides/sample_app_ug/ipsec_secgw.rst
@@ -886,16 +886,32 @@ The flow rule syntax is shown as follows:
 
 .. code-block:: console
 
-    flow <ip_ver> <src_ip> <dst_ip> <port> <queue>
-
+    flow <mark> <eth> <ip_ver> <src_ip> <dst_ip> <port> <queue> \
+         <count> <security> <set_mark>
 
 where each options means:
 
+``<mark>``
+
+ * Set RTE_FLOW_ITEM_TYPE_MARK pattern item with the given mark value.
+
+ * Optional: Yes, this pattern is not set by default.
+
+ * Syntax: *mark X*
+
+``<eth>``
+
+ * Set RTE_FLOW_ITEM_TYPE_ETH pattern item. This matches all ethernet packets.
+
+ * Optional: Yes, this pattern is not set by default.
+
+ * Syntax: *eth*
+
 ``<ip_ver>``
 
  * IP protocol version
 
- * Optional: No
+ * Optional: Yes, this pattern is not set by default.
 
  * Available options:
 
@@ -940,6 +956,30 @@ where each options means:
 
  * Syntax: *queue X*
 
+``<count>``
+
+ * Set RTE_FLOW_ACTION_TYPE_COUNT action.
+
+ * Optional: yes, this action is not set by default.
+
+ * Syntax: *count*
+
+``<security>``
+
+ * Set RTE_FLOW_ITEM_TYPE_ESP pattern and RTE_FLOW_ACTION_TYPE_SECURITY action.
+
+ * Optional: yes, this pattern and action are not set by default.
+
+ * Syntax: *security*
+
+``<set_mark>``
+
+ * Set RTE_FLOW_ACTION_TYPE_MARK action with the given mark value.
+
+ * Optional: yes, this action is not set by default.
+
+ * Syntax: *set_mark X*
+
 Example flow rules:
 
 .. code-block:: console
@@ -948,6 +988,18 @@ Example flow rules:
 
     flow ipv6 dst 1111:1111:1111:1111:1111:1111:1111:5555/116 port 1 queue 0
 
+    flow mark 123 ipv4 dst 192.168.0.0/16 port 0 queue 0 count
+
+    flow eth ipv4 dst 192.168.0.0/16 port 0 queue 0 count
+
+    flow ipv4 dst 192.168.0.0/16 port 0 queue 0 count
+
+    flow ipv4 dst 192.168.0.0/16 port 0 queue 0
+
+    flow port 0 security set_mark 123
+
+    flow ipv4 dst 1.1.0.0/16 port 0 count set_mark 123 security
+
 
 Neighbour rule syntax
 ^^^^^^^^^^^^^^^^^^^^^
diff --git a/examples/ipsec-secgw/flow.c b/examples/ipsec-secgw/flow.c
index 1a1ec7861c..23962f35e7 100644
--- a/examples/ipsec-secgw/flow.c
+++ b/examples/ipsec-secgw/flow.c
@@ -15,7 +15,9 @@
 #define FLOW_RULES_MAX 128
 
 struct flow_rule_entry {
+	uint8_t is_eth;
 	uint8_t is_ipv4;
+	uint8_t is_ipv6;
 	RTE_STD_C11
 	union {
 		struct {
@@ -27,8 +29,15 @@ struct flow_rule_entry {
 			struct rte_flow_item_ipv6 mask;
 		} ipv6;
 	};
+	struct rte_flow_item_mark mark_val;
 	uint16_t port;
 	uint16_t queue;
+	bool is_queue_set;
+	bool enable_count;
+	bool enable_mark;
+	bool set_security_action;
+	bool set_mark_action;
+	uint32_t mark_action_val;
 	struct rte_flow *flow;
 } flow_rule_tbl[FLOW_RULES_MAX];
 
@@ -64,8 +73,9 @@ ipv4_addr_cpy(rte_be32_t *spec, rte_be32_t *mask, char *token,
 	memcpy(mask, &rte_flow_item_ipv4_mask.hdr.src_addr, sizeof(ip));
 
 	*spec = ip.s_addr;
+
 	if (depth < 32)
-		*mask = *mask << (32-depth);
+		*mask = htonl(*mask << (32 - depth));
 
 	return 0;
 }
@@ -124,7 +134,7 @@ parse_flow_tokens(char **tokens, uint32_t n_tokens,
 		  struct parse_status *status)
 {
 	struct flow_rule_entry *rule;
-	uint32_t ti;
+	uint32_t ti = 0;
 
 	if (nb_flow_rule >= FLOW_RULES_MAX) {
 		printf("Too many flow rules\n");
@@ -134,49 +144,73 @@ parse_flow_tokens(char **tokens, uint32_t n_tokens,
 	rule = &flow_rule_tbl[nb_flow_rule];
 	memset(rule, 0, sizeof(*rule));
 
-	if (strcmp(tokens[0], "ipv4") == 0) {
-		rule->is_ipv4 = 1;
-	} else if (strcmp(tokens[0], "ipv6") == 0) {
-		rule->is_ipv4 = 0;
-	} else {
-		APP_CHECK(0, status, "unrecognized input \"%s\"", tokens[0]);
-		return;
-	}
-
-	for (ti = 1; ti < n_tokens; ti++) {
-		if (strcmp(tokens[ti], "src") == 0) {
+	for (ti = 0; ti < n_tokens; ti++) {
+		if (strcmp(tokens[ti], "mark") == 0) {
 			INCREMENT_TOKEN_INDEX(ti, n_tokens, status);
+			if (status->status < 0)
+				return;
+			APP_CHECK_TOKEN_IS_NUM(tokens, ti, status);
 			if (status->status < 0)
 				return;
 
-			if (rule->is_ipv4) {
+			rule->mark_val.id = atoi(tokens[ti]);
+			rule->enable_mark = true;
+			continue;
+		}
+		if (strcmp(tokens[ti], "eth") == 0) {
+			rule->is_eth = true;
+			continue;
+		}
+
+		if (strcmp(tokens[ti], "ipv4") == 0) {
+			rule->is_ipv4 = true;
+			INCREMENT_TOKEN_INDEX(ti, n_tokens, status);
+			if (status->status < 0)
+				return;
+			if (strcmp(tokens[ti], "src") == 0) {
+				INCREMENT_TOKEN_INDEX(ti, n_tokens, status);
+				if (status->status < 0)
+					return;
 				if (ipv4_addr_cpy(&rule->ipv4.spec.hdr.src_addr,
 						  &rule->ipv4.mask.hdr.src_addr,
 						  tokens[ti], status))
 					return;
-			} else {
-				if (ipv6_addr_cpy(rule->ipv6.spec.hdr.src_addr,
-						  rule->ipv6.mask.hdr.src_addr,
+			}
+			if (strcmp(tokens[ti], "dst") == 0) {
+				INCREMENT_TOKEN_INDEX(ti, n_tokens, status);
+				if (status->status < 0)
+					return;
+				if (ipv4_addr_cpy(&rule->ipv4.spec.hdr.src_addr,
+						  &rule->ipv4.mask.hdr.src_addr,
 						  tokens[ti], status))
 					return;
 			}
+			continue;
 		}
-		if (strcmp(tokens[ti], "dst") == 0) {
+		if (strcmp(tokens[ti], "ipv6") == 0) {
+			rule->is_ipv6 = true;
 			INCREMENT_TOKEN_INDEX(ti, n_tokens, status);
 			if (status->status < 0)
 				return;
-
-			if (rule->is_ipv4) {
-				if (ipv4_addr_cpy(&rule->ipv4.spec.hdr.dst_addr,
-						  &rule->ipv4.mask.hdr.dst_addr,
+			if (strcmp(tokens[ti], "src") == 0) {
+				INCREMENT_TOKEN_INDEX(ti, n_tokens, status);
+				if (status->status < 0)
+					return;
+				if (ipv6_addr_cpy(rule->ipv6.spec.hdr.src_addr,
+						  rule->ipv6.mask.hdr.src_addr,
 						  tokens[ti], status))
 					return;
-			} else {
-				if (ipv6_addr_cpy(rule->ipv6.spec.hdr.dst_addr,
-						  rule->ipv6.mask.hdr.dst_addr,
+			}
+			if (strcmp(tokens[ti], "dst") == 0) {
+				INCREMENT_TOKEN_INDEX(ti, n_tokens, status);
+				if (status->status < 0)
+					return;
+				if (ipv6_addr_cpy(rule->ipv6.spec.hdr.src_addr,
+						  rule->ipv6.mask.hdr.src_addr,
 						  tokens[ti], status))
 					return;
 			}
+			continue;
 		}
 
 		if (strcmp(tokens[ti], "port") == 0) {
@@ -188,6 +222,7 @@ parse_flow_tokens(char **tokens, uint32_t n_tokens,
 				return;
 
 			rule->port = atoi(tokens[ti]);
+			continue;
 		}
 
 		if (strcmp(tokens[ti], "queue") == 0) {
@@ -199,50 +234,129 @@ parse_flow_tokens(char **tokens, uint32_t n_tokens,
 				return;
 
 			rule->queue = atoi(tokens[ti]);
+			rule->is_queue_set = true;
+			continue;
+		}
+
+		if (strcmp(tokens[ti], "count") == 0) {
+			rule->enable_count = true;
+			continue;
+		}
+
+		if (strcmp(tokens[ti], "security") == 0) {
+			rule->set_security_action = true;
+			continue;
 		}
+
+		if (strcmp(tokens[ti], "set_mark") == 0) {
+			INCREMENT_TOKEN_INDEX(ti, n_tokens, status);
+			if (status->status < 0)
+				return;
+			APP_CHECK_TOKEN_IS_NUM(tokens, ti, status);
+			if (status->status < 0)
+				return;
+
+			rule->set_mark_action = true;
+			rule->mark_action_val = atoi(tokens[ti]);
+			continue;
+		}
+
+		sprintf(status->parse_msg, "Unrecognized input:%s\n", tokens[ti]);
+		status->status = -1;
+		return;
 	}
+	printf("\n");
 
 	nb_flow_rule++;
 }
 
-#define MAX_RTE_FLOW_PATTERN (3)
-#define MAX_RTE_FLOW_ACTIONS (2)
+#define MAX_RTE_FLOW_PATTERN (4)
+#define MAX_RTE_FLOW_ACTIONS (5)
 
 static void
 flow_init_single(struct flow_rule_entry *rule)
 {
-	struct rte_flow_item pattern[MAX_RTE_FLOW_PATTERN] = {};
 	struct rte_flow_action action[MAX_RTE_FLOW_ACTIONS] = {};
+	struct rte_flow_item pattern[MAX_RTE_FLOW_PATTERN] = {};
+	struct rte_flow_action_queue queue_action;
+	struct rte_flow_action_mark mark_action;
+	int ret, pattern_idx = 0, act_idx = 0;
+	struct rte_flow_item_mark mark_mask;
 	struct rte_flow_attr attr = {};
-	struct rte_flow_error err;
-	int ret;
+	struct rte_flow_error err = {};
 
 	attr.egress = 0;
 	attr.ingress = 1;
 
-	action[0].type = RTE_FLOW_ACTION_TYPE_QUEUE;
-	action[0].conf = &(struct rte_flow_action_queue) {
-				.index = rule->queue,
-	};
-	action[1].type = RTE_FLOW_ACTION_TYPE_END;
+	if (rule->is_queue_set) {
+		queue_action.index = rule->queue;
+		action[act_idx].type = RTE_FLOW_ACTION_TYPE_QUEUE;
+		action[act_idx].conf = &queue_action;
+		act_idx++;
+	}
+
+	if (rule->enable_count) {
+		action[act_idx].type = RTE_FLOW_ACTION_TYPE_COUNT;
+		act_idx++;
+	}
+
+	if (rule->set_security_action) {
+		action[act_idx].type = RTE_FLOW_ACTION_TYPE_SECURITY;
+		action[act_idx].conf = NULL;
+		act_idx++;
+	}
+
+	if (rule->set_mark_action) {
+		mark_action.id = rule->mark_action_val;
+		action[act_idx].type = RTE_FLOW_ACTION_TYPE_MARK;
+		action[act_idx].conf = &mark_action;
+		act_idx++;
+	}
 
-	pattern[0].type = RTE_FLOW_ITEM_TYPE_ETH;
+	action[act_idx].type = RTE_FLOW_ACTION_TYPE_END;
+	action[act_idx].conf = NULL;
+
+	if (rule->enable_mark) {
+		mark_mask.id = UINT32_MAX;
+		pattern[pattern_idx].type = RTE_FLOW_ITEM_TYPE_MARK;
+		pattern[pattern_idx].spec = &rule->mark_val;
+		pattern[pattern_idx].mask = &mark_mask;
+		pattern_idx++;
+	}
+
+	if (rule->is_eth) {
+		pattern[pattern_idx].type = RTE_FLOW_ITEM_TYPE_ETH;
+		pattern_idx++;
+	}
 
 	if (rule->is_ipv4) {
-		pattern[1].type = RTE_FLOW_ITEM_TYPE_IPV4;
-		pattern[1].spec = &rule->ipv4.spec;
-		pattern[1].mask = &rule->ipv4.mask;
-	} else {
-		pattern[1].type = RTE_FLOW_ITEM_TYPE_IPV6;
-		pattern[1].spec = &rule->ipv6.spec;
-		pattern[1].mask = &rule->ipv6.mask;
+		pattern[pattern_idx].type = RTE_FLOW_ITEM_TYPE_IPV4;
+		pattern[pattern_idx].spec = &rule->ipv4.spec;
+		pattern[pattern_idx].mask = &rule->ipv4.mask;
+		pattern_idx++;
+	}
+
+	if (rule->is_ipv6) {
+		pattern[pattern_idx].type = RTE_FLOW_ITEM_TYPE_IPV6;
+		pattern[pattern_idx].spec = &rule->ipv6.spec;
+		pattern[pattern_idx].mask = &rule->ipv6.mask;
+		pattern_idx++;
+	}
+
+	if (rule->set_security_action) {
+		pattern[pattern_idx].type = RTE_FLOW_ITEM_TYPE_ESP;
+		pattern[pattern_idx].spec = NULL;
+		pattern[pattern_idx].mask = NULL;
+		pattern[pattern_idx].last = NULL;
+		pattern_idx++;
 	}
 
-	pattern[2].type = RTE_FLOW_ITEM_TYPE_END;
+	pattern[pattern_idx].type = RTE_FLOW_ITEM_TYPE_END;
 
 	ret = rte_flow_validate(rule->port, &attr, pattern, action, &err);
 	if (ret < 0) {
 		RTE_LOG(ERR, IPSEC, "Flow validation failed %s\n", err.message);
+		rule->flow = 0;
 		return;
 	}
 
@@ -251,6 +365,56 @@ flow_init_single(struct flow_rule_entry *rule)
 		RTE_LOG(ERR, IPSEC, "Flow creation return %s\n", err.message);
 }
 
+void
+flow_print_counters(void)
+{
+	struct rte_flow_query_count count_query;
+	struct rte_flow_action action;
+	struct flow_rule_entry *rule;
+	struct rte_flow_error error;
+	int i = 0, ret = 0;
+
+	action.type = RTE_FLOW_ACTION_TYPE_COUNT;
+
+	for (i = 0; i < nb_flow_rule; i++) {
+		rule = &flow_rule_tbl[i];
+		if (!rule->flow || !rule->enable_count)
+			continue;
+
+		/* Poisoning to make sure PMDs update it in case of error. */
+		memset(&error, 0x55, sizeof(error));
+		memset(&count_query, 0, sizeof(count_query));
+		ret = rte_flow_query(rule->port, rule->flow, &action,
+				     &count_query, &error);
+		if (ret)
+			RTE_LOG(ERR, IPSEC,
+				"Failed to get flow counter "
+				" for port %u, err msg: %s\n",
+				rule->port, error.message);
+
+		printf("Flow #%3d:", i);
+		if (rule->is_ipv4) {
+			printf(" spec ipv4 ");
+			ipv4_hdr_print(&rule->ipv4.spec.hdr);
+		}
+		if (rule->is_ipv6) {
+			printf(" spec ipv6 ");
+			ipv6_hdr_print(&rule->ipv6.spec.hdr);
+		}
+
+		if (rule->set_security_action)
+			printf(" Security action set,");
+
+		if (rule->enable_mark)
+			printf(" Mark Enabled");
+
+		printf(" Port: %d,", rule->port);
+		if (rule->is_queue_set)
+			printf(" Queue: %d", rule->queue);
+		printf(" Hits: %"PRIu64"\n", count_query.hits);
+	}
+}
+
 void
 flow_init(void)
 {
@@ -264,21 +428,37 @@ flow_init(void)
 
 	for (i = 0; i < nb_flow_rule; i++) {
 		rule = &flow_rule_tbl[i];
+		printf("Flow #%3d: ", i);
 		if (rule->is_ipv4) {
-			printf("Flow #%3d: spec ipv4 ", i);
+			printf("spec ipv4 ");
 			ipv4_hdr_print(&rule->ipv4.spec.hdr);
 			printf("\n");
-			printf("           mask ipv4 ");
+			printf(" mask ipv4 ");
 			ipv4_hdr_print(&rule->ipv4.mask.hdr);
-		} else {
-			printf("Flow #%3d: spec ipv6 ", i);
+		}
+		if (rule->is_ipv6) {
+			printf("spec ipv6 ");
 			ipv6_hdr_print(&rule->ipv6.spec.hdr);
 			printf("\n");
-			printf("           mask ipv6 ");
+			printf(" mask ipv6 ");
 			ipv6_hdr_print(&rule->ipv6.mask.hdr);
 		}
 
-		printf("\tPort: %d, Queue: %d", rule->port, rule->queue);
+		if (rule->enable_mark)
+			printf(", Mark enabled");
+
+		printf("\tPort: %d,", rule->port);
+		if (rule->is_queue_set)
+			printf(" Queue: %d,", rule->queue);
+
+		if (rule->set_security_action)
+			printf(" Security action set,");
+
+		if (rule->set_mark_action)
+			printf(" Mark: %d,", rule->mark_action_val);
+
+		if (rule->enable_count)
+			printf(" Counter enabled,");
 
 		if (rule->flow == NULL)
 			printf(" [UNSUPPORTED]");
diff --git a/examples/ipsec-secgw/flow.h b/examples/ipsec-secgw/flow.h
index 1b1b4774e4..9492d06346 100644
--- a/examples/ipsec-secgw/flow.h
+++ b/examples/ipsec-secgw/flow.h
@@ -11,5 +11,6 @@ void parse_flow_tokens(char **tokens, uint32_t n_tokens,
 		       struct parse_status *status);
 
 void flow_init(void);
+void flow_print_counters(void);
 
 #endif /* _FLOW_H_ */
diff --git a/examples/ipsec-secgw/ipsec-secgw.c b/examples/ipsec-secgw/ipsec-secgw.c
index 42b5081840..244453e06e 100644
--- a/examples/ipsec-secgw/ipsec-secgw.c
+++ b/examples/ipsec-secgw/ipsec-secgw.c
@@ -3271,7 +3271,6 @@ ipsec_secgw_telemetry_init(void)
 		"Optional Parameters: int <logical core id>");
 }
 
-
 int32_t
 main(int32_t argc, char **argv)
 {
@@ -3512,6 +3511,8 @@ main(int32_t argc, char **argv)
 		printf(" Done\n");
 	}
 
+	flow_print_counters();
+
 	RTE_ETH_FOREACH_DEV(portid) {
 		if ((enabled_port_mask & (1 << portid)) == 0)
 			continue;
-- 
2.35.3


^ permalink raw reply	[flat|nested] 11+ messages in thread

* [dpdk-dev] [PATCH v3] examples/ipsec-secgw: support more flow patterns and actions
  2022-04-19  8:25 [dpdk-dev] [PATCH] examples/ipsec-secgw: support more flow patterns and actions psatheesh
  2022-05-24  5:32 ` [dpdk-dev] [PATCH v2] " psatheesh
@ 2022-06-03  3:16 ` psatheesh
  2022-06-17  9:52   ` Zhang, Roy Fan
  2022-06-17 10:57 ` [dpdk-dev] [PATCH v4] " psatheesh
  2022-06-22  1:22 ` [dpdk-dev] [PATCH v5] " psatheesh
  3 siblings, 1 reply; 11+ messages in thread
From: psatheesh @ 2022-06-03  3:16 UTC (permalink / raw)
  To: Radu Nicolau, Akhil Goyal; +Cc: dev, Satheesh Paul

From: Satheesh Paul <psatheesh@marvell.com>

Added support to create flow rules with count, mark and
security actions and mark pattern.

Signed-off-by: Satheesh Paul <psatheesh@marvell.com>
---
v3:
* Fixed IPv4 and IPv6 dst addr setting in flow pattern spec
v2:
* Updated documentation in ipsec_secgw.rst

 doc/guides/sample_app_ug/ipsec_secgw.rst |  58 ++++-
 examples/ipsec-secgw/flow.c              | 276 +++++++++++++++++++----
 examples/ipsec-secgw/flow.h              |   1 +
 examples/ipsec-secgw/ipsec-secgw.c       |   3 +-
 4 files changed, 286 insertions(+), 52 deletions(-)

diff --git a/doc/guides/sample_app_ug/ipsec_secgw.rst b/doc/guides/sample_app_ug/ipsec_secgw.rst
index d93acf0667..711026d2ef 100644
--- a/doc/guides/sample_app_ug/ipsec_secgw.rst
+++ b/doc/guides/sample_app_ug/ipsec_secgw.rst
@@ -886,16 +886,32 @@ The flow rule syntax is shown as follows:
 
 .. code-block:: console
 
-    flow <ip_ver> <src_ip> <dst_ip> <port> <queue>
-
+    flow <mark> <eth> <ip_ver> <src_ip> <dst_ip> <port> <queue> \
+         <count> <security> <set_mark>
 
 where each options means:
 
+``<mark>``
+
+ * Set RTE_FLOW_ITEM_TYPE_MARK pattern item with the given mark value.
+
+ * Optional: Yes, this pattern is not set by default.
+
+ * Syntax: *mark X*
+
+``<eth>``
+
+ * Set RTE_FLOW_ITEM_TYPE_ETH pattern item. This matches all ethernet packets.
+
+ * Optional: Yes, this pattern is not set by default.
+
+ * Syntax: *eth*
+
 ``<ip_ver>``
 
  * IP protocol version
 
- * Optional: No
+ * Optional: Yes, this pattern is not set by default.
 
  * Available options:
 
@@ -940,6 +956,30 @@ where each options means:
 
  * Syntax: *queue X*
 
+``<count>``
+
+ * Set RTE_FLOW_ACTION_TYPE_COUNT action.
+
+ * Optional: yes, this action is not set by default.
+
+ * Syntax: *count*
+
+``<security>``
+
+ * Set RTE_FLOW_ITEM_TYPE_ESP pattern and RTE_FLOW_ACTION_TYPE_SECURITY action.
+
+ * Optional: yes, this pattern and action are not set by default.
+
+ * Syntax: *security*
+
+``<set_mark>``
+
+ * Set RTE_FLOW_ACTION_TYPE_MARK action with the given mark value.
+
+ * Optional: yes, this action is not set by default.
+
+ * Syntax: *set_mark X*
+
 Example flow rules:
 
 .. code-block:: console
@@ -948,6 +988,18 @@ Example flow rules:
 
     flow ipv6 dst 1111:1111:1111:1111:1111:1111:1111:5555/116 port 1 queue 0
 
+    flow mark 123 ipv4 dst 192.168.0.0/16 port 0 queue 0 count
+
+    flow eth ipv4 dst 192.168.0.0/16 port 0 queue 0 count
+
+    flow ipv4 dst 192.168.0.0/16 port 0 queue 0 count
+
+    flow ipv4 dst 192.168.0.0/16 port 0 queue 0
+
+    flow port 0 security set_mark 123
+
+    flow ipv4 dst 1.1.0.0/16 port 0 count set_mark 123 security
+
 
 Neighbour rule syntax
 ^^^^^^^^^^^^^^^^^^^^^
diff --git a/examples/ipsec-secgw/flow.c b/examples/ipsec-secgw/flow.c
index 1a1ec7861c..2088876999 100644
--- a/examples/ipsec-secgw/flow.c
+++ b/examples/ipsec-secgw/flow.c
@@ -15,7 +15,9 @@
 #define FLOW_RULES_MAX 128
 
 struct flow_rule_entry {
+	uint8_t is_eth;
 	uint8_t is_ipv4;
+	uint8_t is_ipv6;
 	RTE_STD_C11
 	union {
 		struct {
@@ -27,8 +29,15 @@ struct flow_rule_entry {
 			struct rte_flow_item_ipv6 mask;
 		} ipv6;
 	};
+	struct rte_flow_item_mark mark_val;
 	uint16_t port;
 	uint16_t queue;
+	bool is_queue_set;
+	bool enable_count;
+	bool enable_mark;
+	bool set_security_action;
+	bool set_mark_action;
+	uint32_t mark_action_val;
 	struct rte_flow *flow;
 } flow_rule_tbl[FLOW_RULES_MAX];
 
@@ -64,8 +73,9 @@ ipv4_addr_cpy(rte_be32_t *spec, rte_be32_t *mask, char *token,
 	memcpy(mask, &rte_flow_item_ipv4_mask.hdr.src_addr, sizeof(ip));
 
 	*spec = ip.s_addr;
+
 	if (depth < 32)
-		*mask = *mask << (32-depth);
+		*mask = htonl(*mask << (32 - depth));
 
 	return 0;
 }
@@ -124,7 +134,7 @@ parse_flow_tokens(char **tokens, uint32_t n_tokens,
 		  struct parse_status *status)
 {
 	struct flow_rule_entry *rule;
-	uint32_t ti;
+	uint32_t ti = 0;
 
 	if (nb_flow_rule >= FLOW_RULES_MAX) {
 		printf("Too many flow rules\n");
@@ -134,49 +144,73 @@ parse_flow_tokens(char **tokens, uint32_t n_tokens,
 	rule = &flow_rule_tbl[nb_flow_rule];
 	memset(rule, 0, sizeof(*rule));
 
-	if (strcmp(tokens[0], "ipv4") == 0) {
-		rule->is_ipv4 = 1;
-	} else if (strcmp(tokens[0], "ipv6") == 0) {
-		rule->is_ipv4 = 0;
-	} else {
-		APP_CHECK(0, status, "unrecognized input \"%s\"", tokens[0]);
-		return;
-	}
-
-	for (ti = 1; ti < n_tokens; ti++) {
-		if (strcmp(tokens[ti], "src") == 0) {
+	for (ti = 0; ti < n_tokens; ti++) {
+		if (strcmp(tokens[ti], "mark") == 0) {
 			INCREMENT_TOKEN_INDEX(ti, n_tokens, status);
+			if (status->status < 0)
+				return;
+			APP_CHECK_TOKEN_IS_NUM(tokens, ti, status);
 			if (status->status < 0)
 				return;
 
-			if (rule->is_ipv4) {
+			rule->mark_val.id = atoi(tokens[ti]);
+			rule->enable_mark = true;
+			continue;
+		}
+		if (strcmp(tokens[ti], "eth") == 0) {
+			rule->is_eth = true;
+			continue;
+		}
+
+		if (strcmp(tokens[ti], "ipv4") == 0) {
+			rule->is_ipv4 = true;
+			INCREMENT_TOKEN_INDEX(ti, n_tokens, status);
+			if (status->status < 0)
+				return;
+			if (strcmp(tokens[ti], "src") == 0) {
+				INCREMENT_TOKEN_INDEX(ti, n_tokens, status);
+				if (status->status < 0)
+					return;
 				if (ipv4_addr_cpy(&rule->ipv4.spec.hdr.src_addr,
 						  &rule->ipv4.mask.hdr.src_addr,
 						  tokens[ti], status))
 					return;
-			} else {
-				if (ipv6_addr_cpy(rule->ipv6.spec.hdr.src_addr,
-						  rule->ipv6.mask.hdr.src_addr,
+			}
+			if (strcmp(tokens[ti], "dst") == 0) {
+				INCREMENT_TOKEN_INDEX(ti, n_tokens, status);
+				if (status->status < 0)
+					return;
+				if (ipv4_addr_cpy(&rule->ipv4.spec.hdr.dst_addr,
+						  &rule->ipv4.mask.hdr.dst_addr,
 						  tokens[ti], status))
 					return;
 			}
+			continue;
 		}
-		if (strcmp(tokens[ti], "dst") == 0) {
+		if (strcmp(tokens[ti], "ipv6") == 0) {
+			rule->is_ipv6 = true;
 			INCREMENT_TOKEN_INDEX(ti, n_tokens, status);
 			if (status->status < 0)
 				return;
-
-			if (rule->is_ipv4) {
-				if (ipv4_addr_cpy(&rule->ipv4.spec.hdr.dst_addr,
-						  &rule->ipv4.mask.hdr.dst_addr,
+			if (strcmp(tokens[ti], "src") == 0) {
+				INCREMENT_TOKEN_INDEX(ti, n_tokens, status);
+				if (status->status < 0)
+					return;
+				if (ipv6_addr_cpy(rule->ipv6.spec.hdr.src_addr,
+						  rule->ipv6.mask.hdr.src_addr,
 						  tokens[ti], status))
 					return;
-			} else {
+			}
+			if (strcmp(tokens[ti], "dst") == 0) {
+				INCREMENT_TOKEN_INDEX(ti, n_tokens, status);
+				if (status->status < 0)
+					return;
 				if (ipv6_addr_cpy(rule->ipv6.spec.hdr.dst_addr,
 						  rule->ipv6.mask.hdr.dst_addr,
 						  tokens[ti], status))
 					return;
 			}
+			continue;
 		}
 
 		if (strcmp(tokens[ti], "port") == 0) {
@@ -188,6 +222,7 @@ parse_flow_tokens(char **tokens, uint32_t n_tokens,
 				return;
 
 			rule->port = atoi(tokens[ti]);
+			continue;
 		}
 
 		if (strcmp(tokens[ti], "queue") == 0) {
@@ -199,50 +234,129 @@ parse_flow_tokens(char **tokens, uint32_t n_tokens,
 				return;
 
 			rule->queue = atoi(tokens[ti]);
+			rule->is_queue_set = true;
+			continue;
+		}
+
+		if (strcmp(tokens[ti], "count") == 0) {
+			rule->enable_count = true;
+			continue;
+		}
+
+		if (strcmp(tokens[ti], "security") == 0) {
+			rule->set_security_action = true;
+			continue;
 		}
+
+		if (strcmp(tokens[ti], "set_mark") == 0) {
+			INCREMENT_TOKEN_INDEX(ti, n_tokens, status);
+			if (status->status < 0)
+				return;
+			APP_CHECK_TOKEN_IS_NUM(tokens, ti, status);
+			if (status->status < 0)
+				return;
+
+			rule->set_mark_action = true;
+			rule->mark_action_val = atoi(tokens[ti]);
+			continue;
+		}
+
+		sprintf(status->parse_msg, "Unrecognized input:%s\n", tokens[ti]);
+		status->status = -1;
+		return;
 	}
+	printf("\n");
 
 	nb_flow_rule++;
 }
 
-#define MAX_RTE_FLOW_PATTERN (3)
-#define MAX_RTE_FLOW_ACTIONS (2)
+#define MAX_RTE_FLOW_PATTERN (4)
+#define MAX_RTE_FLOW_ACTIONS (5)
 
 static void
 flow_init_single(struct flow_rule_entry *rule)
 {
-	struct rte_flow_item pattern[MAX_RTE_FLOW_PATTERN] = {};
 	struct rte_flow_action action[MAX_RTE_FLOW_ACTIONS] = {};
+	struct rte_flow_item pattern[MAX_RTE_FLOW_PATTERN] = {};
+	struct rte_flow_action_queue queue_action;
+	struct rte_flow_action_mark mark_action;
+	int ret, pattern_idx = 0, act_idx = 0;
+	struct rte_flow_item_mark mark_mask;
 	struct rte_flow_attr attr = {};
-	struct rte_flow_error err;
-	int ret;
+	struct rte_flow_error err = {};
 
 	attr.egress = 0;
 	attr.ingress = 1;
 
-	action[0].type = RTE_FLOW_ACTION_TYPE_QUEUE;
-	action[0].conf = &(struct rte_flow_action_queue) {
-				.index = rule->queue,
-	};
-	action[1].type = RTE_FLOW_ACTION_TYPE_END;
+	if (rule->is_queue_set) {
+		queue_action.index = rule->queue;
+		action[act_idx].type = RTE_FLOW_ACTION_TYPE_QUEUE;
+		action[act_idx].conf = &queue_action;
+		act_idx++;
+	}
+
+	if (rule->enable_count) {
+		action[act_idx].type = RTE_FLOW_ACTION_TYPE_COUNT;
+		act_idx++;
+	}
+
+	if (rule->set_security_action) {
+		action[act_idx].type = RTE_FLOW_ACTION_TYPE_SECURITY;
+		action[act_idx].conf = NULL;
+		act_idx++;
+	}
+
+	if (rule->set_mark_action) {
+		mark_action.id = rule->mark_action_val;
+		action[act_idx].type = RTE_FLOW_ACTION_TYPE_MARK;
+		action[act_idx].conf = &mark_action;
+		act_idx++;
+	}
 
-	pattern[0].type = RTE_FLOW_ITEM_TYPE_ETH;
+	action[act_idx].type = RTE_FLOW_ACTION_TYPE_END;
+	action[act_idx].conf = NULL;
+
+	if (rule->enable_mark) {
+		mark_mask.id = UINT32_MAX;
+		pattern[pattern_idx].type = RTE_FLOW_ITEM_TYPE_MARK;
+		pattern[pattern_idx].spec = &rule->mark_val;
+		pattern[pattern_idx].mask = &mark_mask;
+		pattern_idx++;
+	}
+
+	if (rule->is_eth) {
+		pattern[pattern_idx].type = RTE_FLOW_ITEM_TYPE_ETH;
+		pattern_idx++;
+	}
 
 	if (rule->is_ipv4) {
-		pattern[1].type = RTE_FLOW_ITEM_TYPE_IPV4;
-		pattern[1].spec = &rule->ipv4.spec;
-		pattern[1].mask = &rule->ipv4.mask;
-	} else {
-		pattern[1].type = RTE_FLOW_ITEM_TYPE_IPV6;
-		pattern[1].spec = &rule->ipv6.spec;
-		pattern[1].mask = &rule->ipv6.mask;
+		pattern[pattern_idx].type = RTE_FLOW_ITEM_TYPE_IPV4;
+		pattern[pattern_idx].spec = &rule->ipv4.spec;
+		pattern[pattern_idx].mask = &rule->ipv4.mask;
+		pattern_idx++;
+	}
+
+	if (rule->is_ipv6) {
+		pattern[pattern_idx].type = RTE_FLOW_ITEM_TYPE_IPV6;
+		pattern[pattern_idx].spec = &rule->ipv6.spec;
+		pattern[pattern_idx].mask = &rule->ipv6.mask;
+		pattern_idx++;
+	}
+
+	if (rule->set_security_action) {
+		pattern[pattern_idx].type = RTE_FLOW_ITEM_TYPE_ESP;
+		pattern[pattern_idx].spec = NULL;
+		pattern[pattern_idx].mask = NULL;
+		pattern[pattern_idx].last = NULL;
+		pattern_idx++;
 	}
 
-	pattern[2].type = RTE_FLOW_ITEM_TYPE_END;
+	pattern[pattern_idx].type = RTE_FLOW_ITEM_TYPE_END;
 
 	ret = rte_flow_validate(rule->port, &attr, pattern, action, &err);
 	if (ret < 0) {
 		RTE_LOG(ERR, IPSEC, "Flow validation failed %s\n", err.message);
+		rule->flow = 0;
 		return;
 	}
 
@@ -251,6 +365,56 @@ flow_init_single(struct flow_rule_entry *rule)
 		RTE_LOG(ERR, IPSEC, "Flow creation return %s\n", err.message);
 }
 
+void
+flow_print_counters(void)
+{
+	struct rte_flow_query_count count_query;
+	struct rte_flow_action action;
+	struct flow_rule_entry *rule;
+	struct rte_flow_error error;
+	int i = 0, ret = 0;
+
+	action.type = RTE_FLOW_ACTION_TYPE_COUNT;
+
+	for (i = 0; i < nb_flow_rule; i++) {
+		rule = &flow_rule_tbl[i];
+		if (!rule->flow || !rule->enable_count)
+			continue;
+
+		/* Poisoning to make sure PMDs update it in case of error. */
+		memset(&error, 0x55, sizeof(error));
+		memset(&count_query, 0, sizeof(count_query));
+		ret = rte_flow_query(rule->port, rule->flow, &action,
+				     &count_query, &error);
+		if (ret)
+			RTE_LOG(ERR, IPSEC,
+				"Failed to get flow counter "
+				" for port %u, err msg: %s\n",
+				rule->port, error.message);
+
+		printf("Flow #%3d:", i);
+		if (rule->is_ipv4) {
+			printf(" spec ipv4 ");
+			ipv4_hdr_print(&rule->ipv4.spec.hdr);
+		}
+		if (rule->is_ipv6) {
+			printf(" spec ipv6 ");
+			ipv6_hdr_print(&rule->ipv6.spec.hdr);
+		}
+
+		if (rule->set_security_action)
+			printf(" Security action set,");
+
+		if (rule->enable_mark)
+			printf(" Mark Enabled");
+
+		printf(" Port: %d,", rule->port);
+		if (rule->is_queue_set)
+			printf(" Queue: %d", rule->queue);
+		printf(" Hits: %"PRIu64"\n", count_query.hits);
+	}
+}
+
 void
 flow_init(void)
 {
@@ -264,21 +428,37 @@ flow_init(void)
 
 	for (i = 0; i < nb_flow_rule; i++) {
 		rule = &flow_rule_tbl[i];
+		printf("Flow #%3d: ", i);
 		if (rule->is_ipv4) {
-			printf("Flow #%3d: spec ipv4 ", i);
+			printf("spec ipv4 ");
 			ipv4_hdr_print(&rule->ipv4.spec.hdr);
 			printf("\n");
-			printf("           mask ipv4 ");
+			printf(" mask ipv4 ");
 			ipv4_hdr_print(&rule->ipv4.mask.hdr);
-		} else {
-			printf("Flow #%3d: spec ipv6 ", i);
+		}
+		if (rule->is_ipv6) {
+			printf("spec ipv6 ");
 			ipv6_hdr_print(&rule->ipv6.spec.hdr);
 			printf("\n");
-			printf("           mask ipv6 ");
+			printf(" mask ipv6 ");
 			ipv6_hdr_print(&rule->ipv6.mask.hdr);
 		}
 
-		printf("\tPort: %d, Queue: %d", rule->port, rule->queue);
+		if (rule->enable_mark)
+			printf(", Mark enabled");
+
+		printf("\tPort: %d,", rule->port);
+		if (rule->is_queue_set)
+			printf(" Queue: %d,", rule->queue);
+
+		if (rule->set_security_action)
+			printf(" Security action set,");
+
+		if (rule->set_mark_action)
+			printf(" Mark: %d,", rule->mark_action_val);
+
+		if (rule->enable_count)
+			printf(" Counter enabled,");
 
 		if (rule->flow == NULL)
 			printf(" [UNSUPPORTED]");
diff --git a/examples/ipsec-secgw/flow.h b/examples/ipsec-secgw/flow.h
index 1b1b4774e4..9492d06346 100644
--- a/examples/ipsec-secgw/flow.h
+++ b/examples/ipsec-secgw/flow.h
@@ -11,5 +11,6 @@ void parse_flow_tokens(char **tokens, uint32_t n_tokens,
 		       struct parse_status *status);
 
 void flow_init(void);
+void flow_print_counters(void);
 
 #endif /* _FLOW_H_ */
diff --git a/examples/ipsec-secgw/ipsec-secgw.c b/examples/ipsec-secgw/ipsec-secgw.c
index 42b5081840..244453e06e 100644
--- a/examples/ipsec-secgw/ipsec-secgw.c
+++ b/examples/ipsec-secgw/ipsec-secgw.c
@@ -3271,7 +3271,6 @@ ipsec_secgw_telemetry_init(void)
 		"Optional Parameters: int <logical core id>");
 }
 
-
 int32_t
 main(int32_t argc, char **argv)
 {
@@ -3512,6 +3511,8 @@ main(int32_t argc, char **argv)
 		printf(" Done\n");
 	}
 
+	flow_print_counters();
+
 	RTE_ETH_FOREACH_DEV(portid) {
 		if ((enabled_port_mask & (1 << portid)) == 0)
 			continue;
-- 
2.35.3


^ permalink raw reply	[flat|nested] 11+ messages in thread

* RE: [dpdk-dev] [PATCH v3] examples/ipsec-secgw: support more flow patterns and actions
  2022-06-03  3:16 ` [dpdk-dev] [PATCH v3] " psatheesh
@ 2022-06-17  9:52   ` Zhang, Roy Fan
  2022-06-17 10:59     ` Satheesh Paul Antonysamy
  0 siblings, 1 reply; 11+ messages in thread
From: Zhang, Roy Fan @ 2022-06-17  9:52 UTC (permalink / raw)
  To: psatheesh, Nicolau, Radu, Akhil Goyal; +Cc: dev

Hi,

> -----Original Message-----
> From: psatheesh@marvell.com <psatheesh@marvell.com>
> Sent: Friday, June 3, 2022 4:17 AM
> To: Nicolau, Radu <radu.nicolau@intel.com>; Akhil Goyal <gakhil@marvell.com>
> Cc: dev@dpdk.org; Satheesh Paul <psatheesh@marvell.com>
> Subject: [dpdk-dev] [PATCH v3] examples/ipsec-secgw: support more flow
> patterns and actions
> 
> From: Satheesh Paul <psatheesh@marvell.com>
> 
> Added support to create flow rules with count, mark and
> security actions and mark pattern.
> 
> Signed-off-by: Satheesh Paul <psatheesh@marvell.com>
> ---

<snip>

>  .. code-block:: console
> 
> -    flow <ip_ver> <src_ip> <dst_ip> <port> <queue>
> -
> +    flow <mark> <eth> <ip_ver> <src_ip> <dst_ip> <port> <queue> \
> +         <count> <security> <set_mark>
> 
>  where each options means:
> 
> +``<mark>``
> +
> + * Set RTE_FLOW_ITEM_TYPE_MARK pattern item with the given mark value.
> +
> + * Optional: Yes, this pattern is not set by default.
> +
> + * Syntax: *mark X*
> +

<snip>

> +
> +``<set_mark>``
> +
> + * Set RTE_FLOW_ACTION_TYPE_MARK action with the given mark value.
> +
> + * Optional: yes, this action is not set by default.
> +
> + * Syntax: *set_mark X*
> +
>  Example flow rules:

I feel "mark" and "set_mark" are duplicated?
From the implementation below it looks there are slight difference in between
But we may need better description for both.

> 
>  .. code-block:: console
> @@ -948,6 +988,18 @@ Example flow rules:
> 
>      flow ipv6 dst 1111:1111:1111:1111:1111:1111:1111:5555/116 port 1
> queue 0
> 
> +    flow mark 123 ipv4 dst 192.168.0.0/16 port 0 queue 0 count
> +
> +    flow eth ipv4 dst 192.168.0.0/16 port 0 queue 0 count
> +
> +    flow ipv4 dst 192.168.0.0/16 port 0 queue 0 count
> +
> +    flow ipv4 dst 192.168.0.0/16 port 0 queue 0
> +
> +    flow port 0 security set_mark 123
> +
> +    flow ipv4 dst 1.1.0.0/16 port 0 count set_mark 123 security
> +
> 
>  Neighbour rule syntax
>  ^^^^^^^^^^^^^^^^^^^^^
> diff --git a/examples/ipsec-secgw/flow.c b/examples/ipsec-secgw/flow.c
> index 1a1ec7861c..2088876999 100644
> --- a/examples/ipsec-secgw/flow.c
> +++ b/examples/ipsec-secgw/flow.c
> @@ -15,7 +15,9 @@
>  #define FLOW_RULES_MAX 128
> 
>  struct flow_rule_entry {
> +	uint8_t is_eth;
>  	uint8_t is_ipv4;
> +	uint8_t is_ipv6;
>  	RTE_STD_C11
>  	union {
>  		struct {
> @@ -27,8 +29,15 @@ struct flow_rule_entry {
>  			struct rte_flow_item_ipv6 mask;
>  		} ipv6;
>  	};
> +	struct rte_flow_item_mark mark_val;
>  	uint16_t port;
>  	uint16_t queue;
> +	bool is_queue_set;
> +	bool enable_count;
> +	bool enable_mark;
> +	bool set_security_action;
> +	bool set_mark_action;
> +	uint32_t mark_action_val;
>  	struct rte_flow *flow;
>  } flow_rule_tbl[FLOW_RULES_MAX];
> 
> @@ -64,8 +73,9 @@ ipv4_addr_cpy(rte_be32_t *spec, rte_be32_t *mask, char
> *token,
>  	memcpy(mask, &rte_flow_item_ipv4_mask.hdr.src_addr, sizeof(ip));
> 
>  	*spec = ip.s_addr;
> +
>  	if (depth < 32)
> -		*mask = *mask << (32-depth);
> +		*mask = htonl(*mask << (32 - depth));
> 
>  	return 0;
>  }
> @@ -124,7 +134,7 @@ parse_flow_tokens(char **tokens, uint32_t n_tokens,
>  		  struct parse_status *status)
>  {
>  	struct flow_rule_entry *rule;
> -	uint32_t ti;
> +	uint32_t ti = 0;
> 
>  	if (nb_flow_rule >= FLOW_RULES_MAX) {
>  		printf("Too many flow rules\n");
> @@ -134,49 +144,73 @@ parse_flow_tokens(char **tokens, uint32_t
> n_tokens,
>  	rule = &flow_rule_tbl[nb_flow_rule];
>  	memset(rule, 0, sizeof(*rule));
> 
> -	if (strcmp(tokens[0], "ipv4") == 0) {
> -		rule->is_ipv4 = 1;
> -	} else if (strcmp(tokens[0], "ipv6") == 0) {
> -		rule->is_ipv4 = 0;
> -	} else {
> -		APP_CHECK(0, status, "unrecognized input \"%s\"", tokens[0]);
> -		return;
> -	}
> -
> -	for (ti = 1; ti < n_tokens; ti++) {
> -		if (strcmp(tokens[ti], "src") == 0) {
> +	for (ti = 0; ti < n_tokens; ti++) {
> +		if (strcmp(tokens[ti], "mark") == 0) {
>  			INCREMENT_TOKEN_INDEX(ti, n_tokens, status);
> +			if (status->status < 0)
> +				return;
> +			APP_CHECK_TOKEN_IS_NUM(tokens, ti, status);
>  			if (status->status < 0)
>  				return;
> 
> -			if (rule->is_ipv4) {
> +			rule->mark_val.id = atoi(tokens[ti]);
> +			rule->enable_mark = true;
> +			continue;
> +		}
> +		if (strcmp(tokens[ti], "eth") == 0) {
> +			rule->is_eth = true;
> +			continue;
> +		}
> +
> +		if (strcmp(tokens[ti], "ipv4") == 0) {
> +			rule->is_ipv4 = true;
> +			INCREMENT_TOKEN_INDEX(ti, n_tokens, status);
> +			if (status->status < 0)
> +				return;
> +			if (strcmp(tokens[ti], "src") == 0) {
> +				INCREMENT_TOKEN_INDEX(ti, n_tokens,
> status);
> +				if (status->status < 0)
> +					return;
>  				if (ipv4_addr_cpy(&rule-
> >ipv4.spec.hdr.src_addr,
>  						  &rule-
> >ipv4.mask.hdr.src_addr,
>  						  tokens[ti], status))
>  					return;
> -			} else {
> -				if (ipv6_addr_cpy(rule->ipv6.spec.hdr.src_addr,
> -						  rule->ipv6.mask.hdr.src_addr,
> +			}
> +			if (strcmp(tokens[ti], "dst") == 0) {
> +				INCREMENT_TOKEN_INDEX(ti, n_tokens,
> status);
> +				if (status->status < 0)
> +					return;
> +				if (ipv4_addr_cpy(&rule-
> >ipv4.spec.hdr.dst_addr,
> +						  &rule-
> >ipv4.mask.hdr.dst_addr,
>  						  tokens[ti], status))
>  					return;
>  			}
> +			continue;
>  		}
> -		if (strcmp(tokens[ti], "dst") == 0) {
> +		if (strcmp(tokens[ti], "ipv6") == 0) {
> +			rule->is_ipv6 = true;
>  			INCREMENT_TOKEN_INDEX(ti, n_tokens, status);
>  			if (status->status < 0)
>  				return;
> -
> -			if (rule->is_ipv4) {
> -				if (ipv4_addr_cpy(&rule-
> >ipv4.spec.hdr.dst_addr,
> -						  &rule-
> >ipv4.mask.hdr.dst_addr,
> +			if (strcmp(tokens[ti], "src") == 0) {
> +				INCREMENT_TOKEN_INDEX(ti, n_tokens,
> status);
> +				if (status->status < 0)
> +					return;
> +				if (ipv6_addr_cpy(rule->ipv6.spec.hdr.src_addr,
> +						  rule->ipv6.mask.hdr.src_addr,
>  						  tokens[ti], status))
>  					return;
> -			} else {
> +			}
> +			if (strcmp(tokens[ti], "dst") == 0) {
> +				INCREMENT_TOKEN_INDEX(ti, n_tokens,
> status);
> +				if (status->status < 0)
> +					return;
>  				if (ipv6_addr_cpy(rule->ipv6.spec.hdr.dst_addr,
>  						  rule->ipv6.mask.hdr.dst_addr,
>  						  tokens[ti], status))
>  					return;
>  			}
> +			continue;
>  		}
> 
>  		if (strcmp(tokens[ti], "port") == 0) {
> @@ -188,6 +222,7 @@ parse_flow_tokens(char **tokens, uint32_t n_tokens,
>  				return;
> 
>  			rule->port = atoi(tokens[ti]);
> +			continue;
>  		}
> 
>  		if (strcmp(tokens[ti], "queue") == 0) {
> @@ -199,50 +234,129 @@ parse_flow_tokens(char **tokens, uint32_t
> n_tokens,
>  				return;
> 
>  			rule->queue = atoi(tokens[ti]);
> +			rule->is_queue_set = true;
> +			continue;
> +		}
> +
> +		if (strcmp(tokens[ti], "count") == 0) {
> +			rule->enable_count = true;
> +			continue;
> +		}
> +
> +		if (strcmp(tokens[ti], "security") == 0) {
> +			rule->set_security_action = true;
> +			continue;
>  		}
> +
> +		if (strcmp(tokens[ti], "set_mark") == 0) {
> +			INCREMENT_TOKEN_INDEX(ti, n_tokens, status);
> +			if (status->status < 0)
> +				return;
> +			APP_CHECK_TOKEN_IS_NUM(tokens, ti, status);
> +			if (status->status < 0)
> +				return;
> +
> +			rule->set_mark_action = true;
> +			rule->mark_action_val = atoi(tokens[ti]);
> +			continue;
> +		}
> +
> +		sprintf(status->parse_msg, "Unrecognized input:%s\n",
> tokens[ti]);
> +		status->status = -1;
> +		return;
>  	}
> +	printf("\n");
> 
>  	nb_flow_rule++;
>  }
> 
> -#define MAX_RTE_FLOW_PATTERN (3)
> -#define MAX_RTE_FLOW_ACTIONS (2)
> +#define MAX_RTE_FLOW_PATTERN (4)
> +#define MAX_RTE_FLOW_ACTIONS (5)
> 
>  static void
>  flow_init_single(struct flow_rule_entry *rule)
>  {
> -	struct rte_flow_item pattern[MAX_RTE_FLOW_PATTERN] = {};
>  	struct rte_flow_action action[MAX_RTE_FLOW_ACTIONS] = {};
> +	struct rte_flow_item pattern[MAX_RTE_FLOW_PATTERN] = {};
> +	struct rte_flow_action_queue queue_action;
> +	struct rte_flow_action_mark mark_action;
> +	int ret, pattern_idx = 0, act_idx = 0;
> +	struct rte_flow_item_mark mark_mask;
>  	struct rte_flow_attr attr = {};
> -	struct rte_flow_error err;
> -	int ret;
> +	struct rte_flow_error err = {};
> 
>  	attr.egress = 0;
>  	attr.ingress = 1;
> 
> -	action[0].type = RTE_FLOW_ACTION_TYPE_QUEUE;
> -	action[0].conf = &(struct rte_flow_action_queue) {
> -				.index = rule->queue,
> -	};
> -	action[1].type = RTE_FLOW_ACTION_TYPE_END;
> +	if (rule->is_queue_set) {
> +		queue_action.index = rule->queue;
> +		action[act_idx].type = RTE_FLOW_ACTION_TYPE_QUEUE;
> +		action[act_idx].conf = &queue_action;
> +		act_idx++;
> +	}
> +
> +	if (rule->enable_count) {
> +		action[act_idx].type = RTE_FLOW_ACTION_TYPE_COUNT;
> +		act_idx++;
> +	}
> +
> +	if (rule->set_security_action) {
> +		action[act_idx].type = RTE_FLOW_ACTION_TYPE_SECURITY;
> +		action[act_idx].conf = NULL;
> +		act_idx++;
> +	}
> +
> +	if (rule->set_mark_action) {
> +		mark_action.id = rule->mark_action_val;
> +		action[act_idx].type = RTE_FLOW_ACTION_TYPE_MARK;
> +		action[act_idx].conf = &mark_action;
> +		act_idx++;
> +	}
> 
> -	pattern[0].type = RTE_FLOW_ITEM_TYPE_ETH;
> +	action[act_idx].type = RTE_FLOW_ACTION_TYPE_END;
> +	action[act_idx].conf = NULL;
> +
> +	if (rule->enable_mark) {
> +		mark_mask.id = UINT32_MAX;
> +		pattern[pattern_idx].type = RTE_FLOW_ITEM_TYPE_MARK;
> +		pattern[pattern_idx].spec = &rule->mark_val;
> +		pattern[pattern_idx].mask = &mark_mask;
> +		pattern_idx++;
> +	}
> +
> +	if (rule->is_eth) {
> +		pattern[pattern_idx].type = RTE_FLOW_ITEM_TYPE_ETH;
> +		pattern_idx++;
> +	}
> 
>  	if (rule->is_ipv4) {
> -		pattern[1].type = RTE_FLOW_ITEM_TYPE_IPV4;
> -		pattern[1].spec = &rule->ipv4.spec;
> -		pattern[1].mask = &rule->ipv4.mask;
> -	} else {
> -		pattern[1].type = RTE_FLOW_ITEM_TYPE_IPV6;
> -		pattern[1].spec = &rule->ipv6.spec;
> -		pattern[1].mask = &rule->ipv6.mask;
> +		pattern[pattern_idx].type = RTE_FLOW_ITEM_TYPE_IPV4;
> +		pattern[pattern_idx].spec = &rule->ipv4.spec;
> +		pattern[pattern_idx].mask = &rule->ipv4.mask;
> +		pattern_idx++;
> +	}
> +
> +	if (rule->is_ipv6) {
> +		pattern[pattern_idx].type = RTE_FLOW_ITEM_TYPE_IPV6;
> +		pattern[pattern_idx].spec = &rule->ipv6.spec;
> +		pattern[pattern_idx].mask = &rule->ipv6.mask;
> +		pattern_idx++;
> +	}
> +
> +	if (rule->set_security_action) {
> +		pattern[pattern_idx].type = RTE_FLOW_ITEM_TYPE_ESP;
> +		pattern[pattern_idx].spec = NULL;
> +		pattern[pattern_idx].mask = NULL;
> +		pattern[pattern_idx].last = NULL;
> +		pattern_idx++;
>  	}
> 
> -	pattern[2].type = RTE_FLOW_ITEM_TYPE_END;
> +	pattern[pattern_idx].type = RTE_FLOW_ITEM_TYPE_END;
> 
>  	ret = rte_flow_validate(rule->port, &attr, pattern, action, &err);
>  	if (ret < 0) {
>  		RTE_LOG(ERR, IPSEC, "Flow validation failed %s\n",
> err.message);
> +		rule->flow = 0;
>  		return;
>  	}
> 
> @@ -251,6 +365,56 @@ flow_init_single(struct flow_rule_entry *rule)
>  		RTE_LOG(ERR, IPSEC, "Flow creation return %s\n",
> err.message);
>  }
> 
> +void
> +flow_print_counters(void)
> +{
> +	struct rte_flow_query_count count_query;
> +	struct rte_flow_action action;
> +	struct flow_rule_entry *rule;
> +	struct rte_flow_error error;
> +	int i = 0, ret = 0;
> +
> +	action.type = RTE_FLOW_ACTION_TYPE_COUNT;
> +
> +	for (i = 0; i < nb_flow_rule; i++) {
> +		rule = &flow_rule_tbl[i];
> +		if (!rule->flow || !rule->enable_count)
> +			continue;
> +
> +		/* Poisoning to make sure PMDs update it in case of error. */
> +		memset(&error, 0x55, sizeof(error));
> +		memset(&count_query, 0, sizeof(count_query));
> +		ret = rte_flow_query(rule->port, rule->flow, &action,
> +				     &count_query, &error);
> +		if (ret)
> +			RTE_LOG(ERR, IPSEC,
> +				"Failed to get flow counter "
> +				" for port %u, err msg: %s\n",
> +				rule->port, error.message);
> +
> +		printf("Flow #%3d:", i);
> +		if (rule->is_ipv4) {
> +			printf(" spec ipv4 ");
> +			ipv4_hdr_print(&rule->ipv4.spec.hdr);
> +		}
> +		if (rule->is_ipv6) {
> +			printf(" spec ipv6 ");
> +			ipv6_hdr_print(&rule->ipv6.spec.hdr);
> +		}
> +
> +		if (rule->set_security_action)
> +			printf(" Security action set,");
> +
> +		if (rule->enable_mark)
> +			printf(" Mark Enabled");
> +
> +		printf(" Port: %d,", rule->port);
> +		if (rule->is_queue_set)
> +			printf(" Queue: %d", rule->queue);
> +		printf(" Hits: %"PRIu64"\n", count_query.hits);
> +	}
> +}
> +
>  void
>  flow_init(void)
>  {
> @@ -264,21 +428,37 @@ flow_init(void)
> 
>  	for (i = 0; i < nb_flow_rule; i++) {
>  		rule = &flow_rule_tbl[i];
> +		printf("Flow #%3d: ", i);
>  		if (rule->is_ipv4) {
> -			printf("Flow #%3d: spec ipv4 ", i);
> +			printf("spec ipv4 ");
>  			ipv4_hdr_print(&rule->ipv4.spec.hdr);
>  			printf("\n");
> -			printf("           mask ipv4 ");
> +			printf(" mask ipv4 ");
>  			ipv4_hdr_print(&rule->ipv4.mask.hdr);
> -		} else {
> -			printf("Flow #%3d: spec ipv6 ", i);
> +		}
> +		if (rule->is_ipv6) {
> +			printf("spec ipv6 ");
>  			ipv6_hdr_print(&rule->ipv6.spec.hdr);
>  			printf("\n");
> -			printf("           mask ipv6 ");
> +			printf(" mask ipv6 ");
>  			ipv6_hdr_print(&rule->ipv6.mask.hdr);
>  		}
> 
> -		printf("\tPort: %d, Queue: %d", rule->port, rule->queue);
> +		if (rule->enable_mark)
> +			printf(", Mark enabled");
> +
> +		printf("\tPort: %d,", rule->port);
> +		if (rule->is_queue_set)
> +			printf(" Queue: %d,", rule->queue);
> +
> +		if (rule->set_security_action)
> +			printf(" Security action set,");
> +
> +		if (rule->set_mark_action)
> +			printf(" Mark: %d,", rule->mark_action_val);
> +
> +		if (rule->enable_count)
> +			printf(" Counter enabled,");
> 
>  		if (rule->flow == NULL)
>  			printf(" [UNSUPPORTED]");
> diff --git a/examples/ipsec-secgw/flow.h b/examples/ipsec-secgw/flow.h
> index 1b1b4774e4..9492d06346 100644
> --- a/examples/ipsec-secgw/flow.h
> +++ b/examples/ipsec-secgw/flow.h
> @@ -11,5 +11,6 @@ void parse_flow_tokens(char **tokens, uint32_t n_tokens,
>  		       struct parse_status *status);
> 
>  void flow_init(void);
> +void flow_print_counters(void);
> 
>  #endif /* _FLOW_H_ */
> diff --git a/examples/ipsec-secgw/ipsec-secgw.c b/examples/ipsec-secgw/ipsec-
> secgw.c
> index 42b5081840..244453e06e 100644
> --- a/examples/ipsec-secgw/ipsec-secgw.c
> +++ b/examples/ipsec-secgw/ipsec-secgw.c
> @@ -3271,7 +3271,6 @@ ipsec_secgw_telemetry_init(void)
>  		"Optional Parameters: int <logical core id>");
>  }
> 
> -
>  int32_t
>  main(int32_t argc, char **argv)
>  {
> @@ -3512,6 +3511,8 @@ main(int32_t argc, char **argv)
>  		printf(" Done\n");
>  	}
> 
> +	flow_print_counters();
> +
>  	RTE_ETH_FOREACH_DEV(portid) {
>  		if ((enabled_port_mask & (1 << portid)) == 0)
>  			continue;
> --
> 2.35.3


^ permalink raw reply	[flat|nested] 11+ messages in thread

* [dpdk-dev] [PATCH v4] examples/ipsec-secgw: support more flow patterns and actions
  2022-04-19  8:25 [dpdk-dev] [PATCH] examples/ipsec-secgw: support more flow patterns and actions psatheesh
  2022-05-24  5:32 ` [dpdk-dev] [PATCH v2] " psatheesh
  2022-06-03  3:16 ` [dpdk-dev] [PATCH v3] " psatheesh
@ 2022-06-17 10:57 ` psatheesh
  2022-06-21 12:53   ` Akhil Goyal
  2022-06-21 17:25   ` Akhil Goyal
  2022-06-22  1:22 ` [dpdk-dev] [PATCH v5] " psatheesh
  3 siblings, 2 replies; 11+ messages in thread
From: psatheesh @ 2022-06-17 10:57 UTC (permalink / raw)
  To: Radu Nicolau, Akhil Goyal; +Cc: dev, Satheesh Paul

From: Satheesh Paul <psatheesh@marvell.com>

Added support to create flow rules with count, mark and
security actions and mark pattern.

Signed-off-by: Satheesh Paul <psatheesh@marvell.com>
---
v4:
* Added more description in documenation for flow rule options.
v3:
* Fixed IPv4 and IPv6 dst addr setting in flow pattern spec
v2:
* Updated documentation in ipsec_secgw.rst

 doc/guides/sample_app_ug/ipsec_secgw.rst |  63 +++++-
 examples/ipsec-secgw/flow.c              | 276 +++++++++++++++++++----
 examples/ipsec-secgw/flow.h              |   1 +
 examples/ipsec-secgw/ipsec-secgw.c       |   3 +-
 4 files changed, 291 insertions(+), 52 deletions(-)

diff --git a/doc/guides/sample_app_ug/ipsec_secgw.rst b/doc/guides/sample_app_ug/ipsec_secgw.rst
index d93acf0667..bf9032d138 100644
--- a/doc/guides/sample_app_ug/ipsec_secgw.rst
+++ b/doc/guides/sample_app_ug/ipsec_secgw.rst
@@ -886,16 +886,35 @@ The flow rule syntax is shown as follows:
 
 .. code-block:: console
 
-    flow <ip_ver> <src_ip> <dst_ip> <port> <queue>
-
+    flow <mark> <eth> <ip_ver> <src_ip> <dst_ip> <port> <queue> \
+         <count> <security> <set_mark>
 
 where each options means:
 
+``<mark>``
+
+ * Set RTE_FLOW_ITEM_TYPE_MARK pattern item in the flow rule with the given
+   mark value. This option can be used to match an arbitrary integer value
+   which was set using the RTE_FLOW_ACTION_TYPE_MARK action (see ``<set_mark>``)
+   in a previously matched rule.
+
+ * Optional: Yes, this pattern is not set by default.
+
+ * Syntax: *mark X*
+
+``<eth>``
+
+ * Set RTE_FLOW_ITEM_TYPE_ETH pattern item. This matches all ethernet packets.
+
+ * Optional: Yes, this pattern is not set by default.
+
+ * Syntax: *eth*
+
 ``<ip_ver>``
 
  * IP protocol version
 
- * Optional: No
+ * Optional: Yes, this pattern is not set by default.
 
  * Available options:
 
@@ -940,6 +959,32 @@ where each options means:
 
  * Syntax: *queue X*
 
+``<count>``
+
+ * Set RTE_FLOW_ACTION_TYPE_COUNT action.
+
+ * Optional: yes, this action is not set by default.
+
+ * Syntax: *count*
+
+``<security>``
+
+ * Set RTE_FLOW_ITEM_TYPE_ESP pattern and RTE_FLOW_ACTION_TYPE_SECURITY action.
+
+ * Optional: yes, this pattern and action are not set by default.
+
+ * Syntax: *security*
+
+``<set_mark>``
+
+ * Set RTE_FLOW_ACTION_TYPE_MARK action in the flow rule with the given mark
+   value. This option can be used to set the given integer value(mark) to
+   packets and set RTE_MBUF_F_RX_FDIR and RTE_MBUF_F_RX_FDIR_ID mbuf flags.
+
+ * Optional: yes, this action is not set by default.
+
+ * Syntax: *set_mark X*
+
 Example flow rules:
 
 .. code-block:: console
@@ -948,6 +993,18 @@ Example flow rules:
 
     flow ipv6 dst 1111:1111:1111:1111:1111:1111:1111:5555/116 port 1 queue 0
 
+    flow mark 123 ipv4 dst 192.168.0.0/16 port 0 queue 0 count
+
+    flow eth ipv4 dst 192.168.0.0/16 port 0 queue 0 count
+
+    flow ipv4 dst 192.168.0.0/16 port 0 queue 0 count
+
+    flow ipv4 dst 192.168.0.0/16 port 0 queue 0
+
+    flow port 0 security set_mark 123
+
+    flow ipv4 dst 1.1.0.0/16 port 0 count set_mark 123 security
+
 
 Neighbour rule syntax
 ^^^^^^^^^^^^^^^^^^^^^
diff --git a/examples/ipsec-secgw/flow.c b/examples/ipsec-secgw/flow.c
index 1a1ec7861c..2088876999 100644
--- a/examples/ipsec-secgw/flow.c
+++ b/examples/ipsec-secgw/flow.c
@@ -15,7 +15,9 @@
 #define FLOW_RULES_MAX 128
 
 struct flow_rule_entry {
+	uint8_t is_eth;
 	uint8_t is_ipv4;
+	uint8_t is_ipv6;
 	RTE_STD_C11
 	union {
 		struct {
@@ -27,8 +29,15 @@ struct flow_rule_entry {
 			struct rte_flow_item_ipv6 mask;
 		} ipv6;
 	};
+	struct rte_flow_item_mark mark_val;
 	uint16_t port;
 	uint16_t queue;
+	bool is_queue_set;
+	bool enable_count;
+	bool enable_mark;
+	bool set_security_action;
+	bool set_mark_action;
+	uint32_t mark_action_val;
 	struct rte_flow *flow;
 } flow_rule_tbl[FLOW_RULES_MAX];
 
@@ -64,8 +73,9 @@ ipv4_addr_cpy(rte_be32_t *spec, rte_be32_t *mask, char *token,
 	memcpy(mask, &rte_flow_item_ipv4_mask.hdr.src_addr, sizeof(ip));
 
 	*spec = ip.s_addr;
+
 	if (depth < 32)
-		*mask = *mask << (32-depth);
+		*mask = htonl(*mask << (32 - depth));
 
 	return 0;
 }
@@ -124,7 +134,7 @@ parse_flow_tokens(char **tokens, uint32_t n_tokens,
 		  struct parse_status *status)
 {
 	struct flow_rule_entry *rule;
-	uint32_t ti;
+	uint32_t ti = 0;
 
 	if (nb_flow_rule >= FLOW_RULES_MAX) {
 		printf("Too many flow rules\n");
@@ -134,49 +144,73 @@ parse_flow_tokens(char **tokens, uint32_t n_tokens,
 	rule = &flow_rule_tbl[nb_flow_rule];
 	memset(rule, 0, sizeof(*rule));
 
-	if (strcmp(tokens[0], "ipv4") == 0) {
-		rule->is_ipv4 = 1;
-	} else if (strcmp(tokens[0], "ipv6") == 0) {
-		rule->is_ipv4 = 0;
-	} else {
-		APP_CHECK(0, status, "unrecognized input \"%s\"", tokens[0]);
-		return;
-	}
-
-	for (ti = 1; ti < n_tokens; ti++) {
-		if (strcmp(tokens[ti], "src") == 0) {
+	for (ti = 0; ti < n_tokens; ti++) {
+		if (strcmp(tokens[ti], "mark") == 0) {
 			INCREMENT_TOKEN_INDEX(ti, n_tokens, status);
+			if (status->status < 0)
+				return;
+			APP_CHECK_TOKEN_IS_NUM(tokens, ti, status);
 			if (status->status < 0)
 				return;
 
-			if (rule->is_ipv4) {
+			rule->mark_val.id = atoi(tokens[ti]);
+			rule->enable_mark = true;
+			continue;
+		}
+		if (strcmp(tokens[ti], "eth") == 0) {
+			rule->is_eth = true;
+			continue;
+		}
+
+		if (strcmp(tokens[ti], "ipv4") == 0) {
+			rule->is_ipv4 = true;
+			INCREMENT_TOKEN_INDEX(ti, n_tokens, status);
+			if (status->status < 0)
+				return;
+			if (strcmp(tokens[ti], "src") == 0) {
+				INCREMENT_TOKEN_INDEX(ti, n_tokens, status);
+				if (status->status < 0)
+					return;
 				if (ipv4_addr_cpy(&rule->ipv4.spec.hdr.src_addr,
 						  &rule->ipv4.mask.hdr.src_addr,
 						  tokens[ti], status))
 					return;
-			} else {
-				if (ipv6_addr_cpy(rule->ipv6.spec.hdr.src_addr,
-						  rule->ipv6.mask.hdr.src_addr,
+			}
+			if (strcmp(tokens[ti], "dst") == 0) {
+				INCREMENT_TOKEN_INDEX(ti, n_tokens, status);
+				if (status->status < 0)
+					return;
+				if (ipv4_addr_cpy(&rule->ipv4.spec.hdr.dst_addr,
+						  &rule->ipv4.mask.hdr.dst_addr,
 						  tokens[ti], status))
 					return;
 			}
+			continue;
 		}
-		if (strcmp(tokens[ti], "dst") == 0) {
+		if (strcmp(tokens[ti], "ipv6") == 0) {
+			rule->is_ipv6 = true;
 			INCREMENT_TOKEN_INDEX(ti, n_tokens, status);
 			if (status->status < 0)
 				return;
-
-			if (rule->is_ipv4) {
-				if (ipv4_addr_cpy(&rule->ipv4.spec.hdr.dst_addr,
-						  &rule->ipv4.mask.hdr.dst_addr,
+			if (strcmp(tokens[ti], "src") == 0) {
+				INCREMENT_TOKEN_INDEX(ti, n_tokens, status);
+				if (status->status < 0)
+					return;
+				if (ipv6_addr_cpy(rule->ipv6.spec.hdr.src_addr,
+						  rule->ipv6.mask.hdr.src_addr,
 						  tokens[ti], status))
 					return;
-			} else {
+			}
+			if (strcmp(tokens[ti], "dst") == 0) {
+				INCREMENT_TOKEN_INDEX(ti, n_tokens, status);
+				if (status->status < 0)
+					return;
 				if (ipv6_addr_cpy(rule->ipv6.spec.hdr.dst_addr,
 						  rule->ipv6.mask.hdr.dst_addr,
 						  tokens[ti], status))
 					return;
 			}
+			continue;
 		}
 
 		if (strcmp(tokens[ti], "port") == 0) {
@@ -188,6 +222,7 @@ parse_flow_tokens(char **tokens, uint32_t n_tokens,
 				return;
 
 			rule->port = atoi(tokens[ti]);
+			continue;
 		}
 
 		if (strcmp(tokens[ti], "queue") == 0) {
@@ -199,50 +234,129 @@ parse_flow_tokens(char **tokens, uint32_t n_tokens,
 				return;
 
 			rule->queue = atoi(tokens[ti]);
+			rule->is_queue_set = true;
+			continue;
+		}
+
+		if (strcmp(tokens[ti], "count") == 0) {
+			rule->enable_count = true;
+			continue;
+		}
+
+		if (strcmp(tokens[ti], "security") == 0) {
+			rule->set_security_action = true;
+			continue;
 		}
+
+		if (strcmp(tokens[ti], "set_mark") == 0) {
+			INCREMENT_TOKEN_INDEX(ti, n_tokens, status);
+			if (status->status < 0)
+				return;
+			APP_CHECK_TOKEN_IS_NUM(tokens, ti, status);
+			if (status->status < 0)
+				return;
+
+			rule->set_mark_action = true;
+			rule->mark_action_val = atoi(tokens[ti]);
+			continue;
+		}
+
+		sprintf(status->parse_msg, "Unrecognized input:%s\n", tokens[ti]);
+		status->status = -1;
+		return;
 	}
+	printf("\n");
 
 	nb_flow_rule++;
 }
 
-#define MAX_RTE_FLOW_PATTERN (3)
-#define MAX_RTE_FLOW_ACTIONS (2)
+#define MAX_RTE_FLOW_PATTERN (4)
+#define MAX_RTE_FLOW_ACTIONS (5)
 
 static void
 flow_init_single(struct flow_rule_entry *rule)
 {
-	struct rte_flow_item pattern[MAX_RTE_FLOW_PATTERN] = {};
 	struct rte_flow_action action[MAX_RTE_FLOW_ACTIONS] = {};
+	struct rte_flow_item pattern[MAX_RTE_FLOW_PATTERN] = {};
+	struct rte_flow_action_queue queue_action;
+	struct rte_flow_action_mark mark_action;
+	int ret, pattern_idx = 0, act_idx = 0;
+	struct rte_flow_item_mark mark_mask;
 	struct rte_flow_attr attr = {};
-	struct rte_flow_error err;
-	int ret;
+	struct rte_flow_error err = {};
 
 	attr.egress = 0;
 	attr.ingress = 1;
 
-	action[0].type = RTE_FLOW_ACTION_TYPE_QUEUE;
-	action[0].conf = &(struct rte_flow_action_queue) {
-				.index = rule->queue,
-	};
-	action[1].type = RTE_FLOW_ACTION_TYPE_END;
+	if (rule->is_queue_set) {
+		queue_action.index = rule->queue;
+		action[act_idx].type = RTE_FLOW_ACTION_TYPE_QUEUE;
+		action[act_idx].conf = &queue_action;
+		act_idx++;
+	}
+
+	if (rule->enable_count) {
+		action[act_idx].type = RTE_FLOW_ACTION_TYPE_COUNT;
+		act_idx++;
+	}
+
+	if (rule->set_security_action) {
+		action[act_idx].type = RTE_FLOW_ACTION_TYPE_SECURITY;
+		action[act_idx].conf = NULL;
+		act_idx++;
+	}
+
+	if (rule->set_mark_action) {
+		mark_action.id = rule->mark_action_val;
+		action[act_idx].type = RTE_FLOW_ACTION_TYPE_MARK;
+		action[act_idx].conf = &mark_action;
+		act_idx++;
+	}
 
-	pattern[0].type = RTE_FLOW_ITEM_TYPE_ETH;
+	action[act_idx].type = RTE_FLOW_ACTION_TYPE_END;
+	action[act_idx].conf = NULL;
+
+	if (rule->enable_mark) {
+		mark_mask.id = UINT32_MAX;
+		pattern[pattern_idx].type = RTE_FLOW_ITEM_TYPE_MARK;
+		pattern[pattern_idx].spec = &rule->mark_val;
+		pattern[pattern_idx].mask = &mark_mask;
+		pattern_idx++;
+	}
+
+	if (rule->is_eth) {
+		pattern[pattern_idx].type = RTE_FLOW_ITEM_TYPE_ETH;
+		pattern_idx++;
+	}
 
 	if (rule->is_ipv4) {
-		pattern[1].type = RTE_FLOW_ITEM_TYPE_IPV4;
-		pattern[1].spec = &rule->ipv4.spec;
-		pattern[1].mask = &rule->ipv4.mask;
-	} else {
-		pattern[1].type = RTE_FLOW_ITEM_TYPE_IPV6;
-		pattern[1].spec = &rule->ipv6.spec;
-		pattern[1].mask = &rule->ipv6.mask;
+		pattern[pattern_idx].type = RTE_FLOW_ITEM_TYPE_IPV4;
+		pattern[pattern_idx].spec = &rule->ipv4.spec;
+		pattern[pattern_idx].mask = &rule->ipv4.mask;
+		pattern_idx++;
+	}
+
+	if (rule->is_ipv6) {
+		pattern[pattern_idx].type = RTE_FLOW_ITEM_TYPE_IPV6;
+		pattern[pattern_idx].spec = &rule->ipv6.spec;
+		pattern[pattern_idx].mask = &rule->ipv6.mask;
+		pattern_idx++;
+	}
+
+	if (rule->set_security_action) {
+		pattern[pattern_idx].type = RTE_FLOW_ITEM_TYPE_ESP;
+		pattern[pattern_idx].spec = NULL;
+		pattern[pattern_idx].mask = NULL;
+		pattern[pattern_idx].last = NULL;
+		pattern_idx++;
 	}
 
-	pattern[2].type = RTE_FLOW_ITEM_TYPE_END;
+	pattern[pattern_idx].type = RTE_FLOW_ITEM_TYPE_END;
 
 	ret = rte_flow_validate(rule->port, &attr, pattern, action, &err);
 	if (ret < 0) {
 		RTE_LOG(ERR, IPSEC, "Flow validation failed %s\n", err.message);
+		rule->flow = 0;
 		return;
 	}
 
@@ -251,6 +365,56 @@ flow_init_single(struct flow_rule_entry *rule)
 		RTE_LOG(ERR, IPSEC, "Flow creation return %s\n", err.message);
 }
 
+void
+flow_print_counters(void)
+{
+	struct rte_flow_query_count count_query;
+	struct rte_flow_action action;
+	struct flow_rule_entry *rule;
+	struct rte_flow_error error;
+	int i = 0, ret = 0;
+
+	action.type = RTE_FLOW_ACTION_TYPE_COUNT;
+
+	for (i = 0; i < nb_flow_rule; i++) {
+		rule = &flow_rule_tbl[i];
+		if (!rule->flow || !rule->enable_count)
+			continue;
+
+		/* Poisoning to make sure PMDs update it in case of error. */
+		memset(&error, 0x55, sizeof(error));
+		memset(&count_query, 0, sizeof(count_query));
+		ret = rte_flow_query(rule->port, rule->flow, &action,
+				     &count_query, &error);
+		if (ret)
+			RTE_LOG(ERR, IPSEC,
+				"Failed to get flow counter "
+				" for port %u, err msg: %s\n",
+				rule->port, error.message);
+
+		printf("Flow #%3d:", i);
+		if (rule->is_ipv4) {
+			printf(" spec ipv4 ");
+			ipv4_hdr_print(&rule->ipv4.spec.hdr);
+		}
+		if (rule->is_ipv6) {
+			printf(" spec ipv6 ");
+			ipv6_hdr_print(&rule->ipv6.spec.hdr);
+		}
+
+		if (rule->set_security_action)
+			printf(" Security action set,");
+
+		if (rule->enable_mark)
+			printf(" Mark Enabled");
+
+		printf(" Port: %d,", rule->port);
+		if (rule->is_queue_set)
+			printf(" Queue: %d", rule->queue);
+		printf(" Hits: %"PRIu64"\n", count_query.hits);
+	}
+}
+
 void
 flow_init(void)
 {
@@ -264,21 +428,37 @@ flow_init(void)
 
 	for (i = 0; i < nb_flow_rule; i++) {
 		rule = &flow_rule_tbl[i];
+		printf("Flow #%3d: ", i);
 		if (rule->is_ipv4) {
-			printf("Flow #%3d: spec ipv4 ", i);
+			printf("spec ipv4 ");
 			ipv4_hdr_print(&rule->ipv4.spec.hdr);
 			printf("\n");
-			printf("           mask ipv4 ");
+			printf(" mask ipv4 ");
 			ipv4_hdr_print(&rule->ipv4.mask.hdr);
-		} else {
-			printf("Flow #%3d: spec ipv6 ", i);
+		}
+		if (rule->is_ipv6) {
+			printf("spec ipv6 ");
 			ipv6_hdr_print(&rule->ipv6.spec.hdr);
 			printf("\n");
-			printf("           mask ipv6 ");
+			printf(" mask ipv6 ");
 			ipv6_hdr_print(&rule->ipv6.mask.hdr);
 		}
 
-		printf("\tPort: %d, Queue: %d", rule->port, rule->queue);
+		if (rule->enable_mark)
+			printf(", Mark enabled");
+
+		printf("\tPort: %d,", rule->port);
+		if (rule->is_queue_set)
+			printf(" Queue: %d,", rule->queue);
+
+		if (rule->set_security_action)
+			printf(" Security action set,");
+
+		if (rule->set_mark_action)
+			printf(" Mark: %d,", rule->mark_action_val);
+
+		if (rule->enable_count)
+			printf(" Counter enabled,");
 
 		if (rule->flow == NULL)
 			printf(" [UNSUPPORTED]");
diff --git a/examples/ipsec-secgw/flow.h b/examples/ipsec-secgw/flow.h
index 1b1b4774e4..9492d06346 100644
--- a/examples/ipsec-secgw/flow.h
+++ b/examples/ipsec-secgw/flow.h
@@ -11,5 +11,6 @@ void parse_flow_tokens(char **tokens, uint32_t n_tokens,
 		       struct parse_status *status);
 
 void flow_init(void);
+void flow_print_counters(void);
 
 #endif /* _FLOW_H_ */
diff --git a/examples/ipsec-secgw/ipsec-secgw.c b/examples/ipsec-secgw/ipsec-secgw.c
index 42b5081840..244453e06e 100644
--- a/examples/ipsec-secgw/ipsec-secgw.c
+++ b/examples/ipsec-secgw/ipsec-secgw.c
@@ -3271,7 +3271,6 @@ ipsec_secgw_telemetry_init(void)
 		"Optional Parameters: int <logical core id>");
 }
 
-
 int32_t
 main(int32_t argc, char **argv)
 {
@@ -3512,6 +3511,8 @@ main(int32_t argc, char **argv)
 		printf(" Done\n");
 	}
 
+	flow_print_counters();
+
 	RTE_ETH_FOREACH_DEV(portid) {
 		if ((enabled_port_mask & (1 << portid)) == 0)
 			continue;
-- 
2.35.3


^ permalink raw reply	[flat|nested] 11+ messages in thread

* RE: [dpdk-dev] [PATCH v3] examples/ipsec-secgw: support more flow patterns and actions
  2022-06-17  9:52   ` Zhang, Roy Fan
@ 2022-06-17 10:59     ` Satheesh Paul Antonysamy
  0 siblings, 0 replies; 11+ messages in thread
From: Satheesh Paul Antonysamy @ 2022-06-17 10:59 UTC (permalink / raw)
  To: Zhang, Roy Fan, Nicolau, Radu, Akhil Goyal; +Cc: dev

Hi,

Please find reply inline.

Thanks,
Satheesh.

-----Original Message-----
From: Zhang, Roy Fan <roy.fan.zhang@intel.com> 
Sent: 17 June 2022 03:22 PM
To: Satheesh Paul Antonysamy <psatheesh@marvell.com>; Nicolau, Radu <radu.nicolau@intel.com>; Akhil Goyal <gakhil@marvell.com>
Cc: dev@dpdk.org
Subject: [EXT] RE: [dpdk-dev] [PATCH v3] examples/ipsec-secgw: support more flow patterns and actions

External Email

----------------------------------------------------------------------
Hi,

> -----Original Message-----
> From: psatheesh@marvell.com <psatheesh@marvell.com>
> Sent: Friday, June 3, 2022 4:17 AM
> To: Nicolau, Radu <radu.nicolau@intel.com>; Akhil Goyal 
> <gakhil@marvell.com>
> Cc: dev@dpdk.org; Satheesh Paul <psatheesh@marvell.com>
> Subject: [dpdk-dev] [PATCH v3] examples/ipsec-secgw: support more flow 
> patterns and actions
> 
> From: Satheesh Paul <psatheesh@marvell.com>
> 
> Added support to create flow rules with count, mark and security 
> actions and mark pattern.
> 
> Signed-off-by: Satheesh Paul <psatheesh@marvell.com>
> ---

<snip>

>  .. code-block:: console
> 
> -    flow <ip_ver> <src_ip> <dst_ip> <port> <queue>
> -
> +    flow <mark> <eth> <ip_ver> <src_ip> <dst_ip> <port> <queue> \
> +         <count> <security> <set_mark>
> 
>  where each options means:
> 
> +``<mark>``
> +
> + * Set RTE_FLOW_ITEM_TYPE_MARK pattern item with the given mark value.
> +
> + * Optional: Yes, this pattern is not set by default.
> +
> + * Syntax: *mark X*
> +

<snip>

> +
> +``<set_mark>``
> +
> + * Set RTE_FLOW_ACTION_TYPE_MARK action with the given mark value.
> +
> + * Optional: yes, this action is not set by default.
> +
> + * Syntax: *set_mark X*
> +
>  Example flow rules:

> I feel "mark" and "set_mark" are duplicated?
> From the implementation below it looks there are slight difference in between But we may need better description for both.

Ack. I have added some more description and sent v4 patch.

> 
>  .. code-block:: console
> @@ -948,6 +988,18 @@ Example flow rules:
> 
>      flow ipv6 dst 1111:1111:1111:1111:1111:1111:1111:5555/116 port 1 
> queue 0
> 
> +    flow mark 123 ipv4 dst 192.168.0.0/16 port 0 queue 0 count
> +
> +    flow eth ipv4 dst 192.168.0.0/16 port 0 queue 0 count
> +
> +    flow ipv4 dst 192.168.0.0/16 port 0 queue 0 count
> +
> +    flow ipv4 dst 192.168.0.0/16 port 0 queue 0
> +
> +    flow port 0 security set_mark 123
> +
> +    flow ipv4 dst 1.1.0.0/16 port 0 count set_mark 123 security
> +
> 
>  Neighbour rule syntax
>  ^^^^^^^^^^^^^^^^^^^^^
> diff --git a/examples/ipsec-secgw/flow.c b/examples/ipsec-secgw/flow.c 
> index 1a1ec7861c..2088876999 100644
> --- a/examples/ipsec-secgw/flow.c
> +++ b/examples/ipsec-secgw/flow.c
> @@ -15,7 +15,9 @@
>  #define FLOW_RULES_MAX 128
> 
>  struct flow_rule_entry {
> +	uint8_t is_eth;
>  	uint8_t is_ipv4;
> +	uint8_t is_ipv6;
>  	RTE_STD_C11
>  	union {
>  		struct {
> @@ -27,8 +29,15 @@ struct flow_rule_entry {
>  			struct rte_flow_item_ipv6 mask;
>  		} ipv6;
>  	};
> +	struct rte_flow_item_mark mark_val;
>  	uint16_t port;
>  	uint16_t queue;
> +	bool is_queue_set;
> +	bool enable_count;
> +	bool enable_mark;
> +	bool set_security_action;
> +	bool set_mark_action;
> +	uint32_t mark_action_val;
>  	struct rte_flow *flow;
>  } flow_rule_tbl[FLOW_RULES_MAX];
> 
> @@ -64,8 +73,9 @@ ipv4_addr_cpy(rte_be32_t *spec, rte_be32_t *mask, 
> char *token,
>  	memcpy(mask, &rte_flow_item_ipv4_mask.hdr.src_addr, sizeof(ip));
> 
>  	*spec = ip.s_addr;
> +
>  	if (depth < 32)
> -		*mask = *mask << (32-depth);
> +		*mask = htonl(*mask << (32 - depth));
> 
>  	return 0;
>  }
> @@ -124,7 +134,7 @@ parse_flow_tokens(char **tokens, uint32_t n_tokens,
>  		  struct parse_status *status)
>  {
>  	struct flow_rule_entry *rule;
> -	uint32_t ti;
> +	uint32_t ti = 0;
> 
>  	if (nb_flow_rule >= FLOW_RULES_MAX) {
>  		printf("Too many flow rules\n");
> @@ -134,49 +144,73 @@ parse_flow_tokens(char **tokens, uint32_t 
> n_tokens,
>  	rule = &flow_rule_tbl[nb_flow_rule];
>  	memset(rule, 0, sizeof(*rule));
> 
> -	if (strcmp(tokens[0], "ipv4") == 0) {
> -		rule->is_ipv4 = 1;
> -	} else if (strcmp(tokens[0], "ipv6") == 0) {
> -		rule->is_ipv4 = 0;
> -	} else {
> -		APP_CHECK(0, status, "unrecognized input \"%s\"", tokens[0]);
> -		return;
> -	}
> -
> -	for (ti = 1; ti < n_tokens; ti++) {
> -		if (strcmp(tokens[ti], "src") == 0) {
> +	for (ti = 0; ti < n_tokens; ti++) {
> +		if (strcmp(tokens[ti], "mark") == 0) {
>  			INCREMENT_TOKEN_INDEX(ti, n_tokens, status);
> +			if (status->status < 0)
> +				return;
> +			APP_CHECK_TOKEN_IS_NUM(tokens, ti, status);
>  			if (status->status < 0)
>  				return;
> 
> -			if (rule->is_ipv4) {
> +			rule->mark_val.id = atoi(tokens[ti]);
> +			rule->enable_mark = true;
> +			continue;
> +		}
> +		if (strcmp(tokens[ti], "eth") == 0) {
> +			rule->is_eth = true;
> +			continue;
> +		}
> +
> +		if (strcmp(tokens[ti], "ipv4") == 0) {
> +			rule->is_ipv4 = true;
> +			INCREMENT_TOKEN_INDEX(ti, n_tokens, status);
> +			if (status->status < 0)
> +				return;
> +			if (strcmp(tokens[ti], "src") == 0) {
> +				INCREMENT_TOKEN_INDEX(ti, n_tokens,
> status);
> +				if (status->status < 0)
> +					return;
>  				if (ipv4_addr_cpy(&rule-
> >ipv4.spec.hdr.src_addr,
>  						  &rule-
> >ipv4.mask.hdr.src_addr,
>  						  tokens[ti], status))
>  					return;
> -			} else {
> -				if (ipv6_addr_cpy(rule->ipv6.spec.hdr.src_addr,
> -						  rule->ipv6.mask.hdr.src_addr,
> +			}
> +			if (strcmp(tokens[ti], "dst") == 0) {
> +				INCREMENT_TOKEN_INDEX(ti, n_tokens,
> status);
> +				if (status->status < 0)
> +					return;
> +				if (ipv4_addr_cpy(&rule-
> >ipv4.spec.hdr.dst_addr,
> +						  &rule-
> >ipv4.mask.hdr.dst_addr,
>  						  tokens[ti], status))
>  					return;
>  			}
> +			continue;
>  		}
> -		if (strcmp(tokens[ti], "dst") == 0) {
> +		if (strcmp(tokens[ti], "ipv6") == 0) {
> +			rule->is_ipv6 = true;
>  			INCREMENT_TOKEN_INDEX(ti, n_tokens, status);
>  			if (status->status < 0)
>  				return;
> -
> -			if (rule->is_ipv4) {
> -				if (ipv4_addr_cpy(&rule-
> >ipv4.spec.hdr.dst_addr,
> -						  &rule-
> >ipv4.mask.hdr.dst_addr,
> +			if (strcmp(tokens[ti], "src") == 0) {
> +				INCREMENT_TOKEN_INDEX(ti, n_tokens,
> status);
> +				if (status->status < 0)
> +					return;
> +				if (ipv6_addr_cpy(rule->ipv6.spec.hdr.src_addr,
> +						  rule->ipv6.mask.hdr.src_addr,
>  						  tokens[ti], status))
>  					return;
> -			} else {
> +			}
> +			if (strcmp(tokens[ti], "dst") == 0) {
> +				INCREMENT_TOKEN_INDEX(ti, n_tokens,
> status);
> +				if (status->status < 0)
> +					return;
>  				if (ipv6_addr_cpy(rule->ipv6.spec.hdr.dst_addr,
>  						  rule->ipv6.mask.hdr.dst_addr,
>  						  tokens[ti], status))
>  					return;
>  			}
> +			continue;
>  		}
> 
>  		if (strcmp(tokens[ti], "port") == 0) { @@ -188,6 +222,7 @@ 
> parse_flow_tokens(char **tokens, uint32_t n_tokens,
>  				return;
> 
>  			rule->port = atoi(tokens[ti]);
> +			continue;
>  		}
> 
>  		if (strcmp(tokens[ti], "queue") == 0) { @@ -199,50 +234,129 @@ 
> parse_flow_tokens(char **tokens, uint32_t n_tokens,
>  				return;
> 
>  			rule->queue = atoi(tokens[ti]);
> +			rule->is_queue_set = true;
> +			continue;
> +		}
> +
> +		if (strcmp(tokens[ti], "count") == 0) {
> +			rule->enable_count = true;
> +			continue;
> +		}
> +
> +		if (strcmp(tokens[ti], "security") == 0) {
> +			rule->set_security_action = true;
> +			continue;
>  		}
> +
> +		if (strcmp(tokens[ti], "set_mark") == 0) {
> +			INCREMENT_TOKEN_INDEX(ti, n_tokens, status);
> +			if (status->status < 0)
> +				return;
> +			APP_CHECK_TOKEN_IS_NUM(tokens, ti, status);
> +			if (status->status < 0)
> +				return;
> +
> +			rule->set_mark_action = true;
> +			rule->mark_action_val = atoi(tokens[ti]);
> +			continue;
> +		}
> +
> +		sprintf(status->parse_msg, "Unrecognized input:%s\n",
> tokens[ti]);
> +		status->status = -1;
> +		return;
>  	}
> +	printf("\n");
> 
>  	nb_flow_rule++;
>  }
> 
> -#define MAX_RTE_FLOW_PATTERN (3)
> -#define MAX_RTE_FLOW_ACTIONS (2)
> +#define MAX_RTE_FLOW_PATTERN (4)
> +#define MAX_RTE_FLOW_ACTIONS (5)
> 
>  static void
>  flow_init_single(struct flow_rule_entry *rule)  {
> -	struct rte_flow_item pattern[MAX_RTE_FLOW_PATTERN] = {};
>  	struct rte_flow_action action[MAX_RTE_FLOW_ACTIONS] = {};
> +	struct rte_flow_item pattern[MAX_RTE_FLOW_PATTERN] = {};
> +	struct rte_flow_action_queue queue_action;
> +	struct rte_flow_action_mark mark_action;
> +	int ret, pattern_idx = 0, act_idx = 0;
> +	struct rte_flow_item_mark mark_mask;
>  	struct rte_flow_attr attr = {};
> -	struct rte_flow_error err;
> -	int ret;
> +	struct rte_flow_error err = {};
> 
>  	attr.egress = 0;
>  	attr.ingress = 1;
> 
> -	action[0].type = RTE_FLOW_ACTION_TYPE_QUEUE;
> -	action[0].conf = &(struct rte_flow_action_queue) {
> -				.index = rule->queue,
> -	};
> -	action[1].type = RTE_FLOW_ACTION_TYPE_END;
> +	if (rule->is_queue_set) {
> +		queue_action.index = rule->queue;
> +		action[act_idx].type = RTE_FLOW_ACTION_TYPE_QUEUE;
> +		action[act_idx].conf = &queue_action;
> +		act_idx++;
> +	}
> +
> +	if (rule->enable_count) {
> +		action[act_idx].type = RTE_FLOW_ACTION_TYPE_COUNT;
> +		act_idx++;
> +	}
> +
> +	if (rule->set_security_action) {
> +		action[act_idx].type = RTE_FLOW_ACTION_TYPE_SECURITY;
> +		action[act_idx].conf = NULL;
> +		act_idx++;
> +	}
> +
> +	if (rule->set_mark_action) {
> +		mark_action.id = rule->mark_action_val;
> +		action[act_idx].type = RTE_FLOW_ACTION_TYPE_MARK;
> +		action[act_idx].conf = &mark_action;
> +		act_idx++;
> +	}
> 
> -	pattern[0].type = RTE_FLOW_ITEM_TYPE_ETH;
> +	action[act_idx].type = RTE_FLOW_ACTION_TYPE_END;
> +	action[act_idx].conf = NULL;
> +
> +	if (rule->enable_mark) {
> +		mark_mask.id = UINT32_MAX;
> +		pattern[pattern_idx].type = RTE_FLOW_ITEM_TYPE_MARK;
> +		pattern[pattern_idx].spec = &rule->mark_val;
> +		pattern[pattern_idx].mask = &mark_mask;
> +		pattern_idx++;
> +	}
> +
> +	if (rule->is_eth) {
> +		pattern[pattern_idx].type = RTE_FLOW_ITEM_TYPE_ETH;
> +		pattern_idx++;
> +	}
> 
>  	if (rule->is_ipv4) {
> -		pattern[1].type = RTE_FLOW_ITEM_TYPE_IPV4;
> -		pattern[1].spec = &rule->ipv4.spec;
> -		pattern[1].mask = &rule->ipv4.mask;
> -	} else {
> -		pattern[1].type = RTE_FLOW_ITEM_TYPE_IPV6;
> -		pattern[1].spec = &rule->ipv6.spec;
> -		pattern[1].mask = &rule->ipv6.mask;
> +		pattern[pattern_idx].type = RTE_FLOW_ITEM_TYPE_IPV4;
> +		pattern[pattern_idx].spec = &rule->ipv4.spec;
> +		pattern[pattern_idx].mask = &rule->ipv4.mask;
> +		pattern_idx++;
> +	}
> +
> +	if (rule->is_ipv6) {
> +		pattern[pattern_idx].type = RTE_FLOW_ITEM_TYPE_IPV6;
> +		pattern[pattern_idx].spec = &rule->ipv6.spec;
> +		pattern[pattern_idx].mask = &rule->ipv6.mask;
> +		pattern_idx++;
> +	}
> +
> +	if (rule->set_security_action) {
> +		pattern[pattern_idx].type = RTE_FLOW_ITEM_TYPE_ESP;
> +		pattern[pattern_idx].spec = NULL;
> +		pattern[pattern_idx].mask = NULL;
> +		pattern[pattern_idx].last = NULL;
> +		pattern_idx++;
>  	}
> 
> -	pattern[2].type = RTE_FLOW_ITEM_TYPE_END;
> +	pattern[pattern_idx].type = RTE_FLOW_ITEM_TYPE_END;
> 
>  	ret = rte_flow_validate(rule->port, &attr, pattern, action, &err);
>  	if (ret < 0) {
>  		RTE_LOG(ERR, IPSEC, "Flow validation failed %s\n", err.message);
> +		rule->flow = 0;
>  		return;
>  	}
> 
> @@ -251,6 +365,56 @@ flow_init_single(struct flow_rule_entry *rule)
>  		RTE_LOG(ERR, IPSEC, "Flow creation return %s\n", err.message);  }
> 
> +void
> +flow_print_counters(void)
> +{
> +	struct rte_flow_query_count count_query;
> +	struct rte_flow_action action;
> +	struct flow_rule_entry *rule;
> +	struct rte_flow_error error;
> +	int i = 0, ret = 0;
> +
> +	action.type = RTE_FLOW_ACTION_TYPE_COUNT;
> +
> +	for (i = 0; i < nb_flow_rule; i++) {
> +		rule = &flow_rule_tbl[i];
> +		if (!rule->flow || !rule->enable_count)
> +			continue;
> +
> +		/* Poisoning to make sure PMDs update it in case of error. */
> +		memset(&error, 0x55, sizeof(error));
> +		memset(&count_query, 0, sizeof(count_query));
> +		ret = rte_flow_query(rule->port, rule->flow, &action,
> +				     &count_query, &error);
> +		if (ret)
> +			RTE_LOG(ERR, IPSEC,
> +				"Failed to get flow counter "
> +				" for port %u, err msg: %s\n",
> +				rule->port, error.message);
> +
> +		printf("Flow #%3d:", i);
> +		if (rule->is_ipv4) {
> +			printf(" spec ipv4 ");
> +			ipv4_hdr_print(&rule->ipv4.spec.hdr);
> +		}
> +		if (rule->is_ipv6) {
> +			printf(" spec ipv6 ");
> +			ipv6_hdr_print(&rule->ipv6.spec.hdr);
> +		}
> +
> +		if (rule->set_security_action)
> +			printf(" Security action set,");
> +
> +		if (rule->enable_mark)
> +			printf(" Mark Enabled");
> +
> +		printf(" Port: %d,", rule->port);
> +		if (rule->is_queue_set)
> +			printf(" Queue: %d", rule->queue);
> +		printf(" Hits: %"PRIu64"\n", count_query.hits);
> +	}
> +}
> +
>  void
>  flow_init(void)
>  {
> @@ -264,21 +428,37 @@ flow_init(void)
> 
>  	for (i = 0; i < nb_flow_rule; i++) {
>  		rule = &flow_rule_tbl[i];
> +		printf("Flow #%3d: ", i);
>  		if (rule->is_ipv4) {
> -			printf("Flow #%3d: spec ipv4 ", i);
> +			printf("spec ipv4 ");
>  			ipv4_hdr_print(&rule->ipv4.spec.hdr);
>  			printf("\n");
> -			printf("           mask ipv4 ");
> +			printf(" mask ipv4 ");
>  			ipv4_hdr_print(&rule->ipv4.mask.hdr);
> -		} else {
> -			printf("Flow #%3d: spec ipv6 ", i);
> +		}
> +		if (rule->is_ipv6) {
> +			printf("spec ipv6 ");
>  			ipv6_hdr_print(&rule->ipv6.spec.hdr);
>  			printf("\n");
> -			printf("           mask ipv6 ");
> +			printf(" mask ipv6 ");
>  			ipv6_hdr_print(&rule->ipv6.mask.hdr);
>  		}
> 
> -		printf("\tPort: %d, Queue: %d", rule->port, rule->queue);
> +		if (rule->enable_mark)
> +			printf(", Mark enabled");
> +
> +		printf("\tPort: %d,", rule->port);
> +		if (rule->is_queue_set)
> +			printf(" Queue: %d,", rule->queue);
> +
> +		if (rule->set_security_action)
> +			printf(" Security action set,");
> +
> +		if (rule->set_mark_action)
> +			printf(" Mark: %d,", rule->mark_action_val);
> +
> +		if (rule->enable_count)
> +			printf(" Counter enabled,");
> 
>  		if (rule->flow == NULL)
>  			printf(" [UNSUPPORTED]");
> diff --git a/examples/ipsec-secgw/flow.h b/examples/ipsec-secgw/flow.h 
> index 1b1b4774e4..9492d06346 100644
> --- a/examples/ipsec-secgw/flow.h
> +++ b/examples/ipsec-secgw/flow.h
> @@ -11,5 +11,6 @@ void parse_flow_tokens(char **tokens, uint32_t n_tokens,
>  		       struct parse_status *status);
> 
>  void flow_init(void);
> +void flow_print_counters(void);
> 
>  #endif /* _FLOW_H_ */
> diff --git a/examples/ipsec-secgw/ipsec-secgw.c 
> b/examples/ipsec-secgw/ipsec- secgw.c index 42b5081840..244453e06e 
> 100644
> --- a/examples/ipsec-secgw/ipsec-secgw.c
> +++ b/examples/ipsec-secgw/ipsec-secgw.c
> @@ -3271,7 +3271,6 @@ ipsec_secgw_telemetry_init(void)
>  		"Optional Parameters: int <logical core id>");  }
> 
> -
>  int32_t
>  main(int32_t argc, char **argv)
>  {
> @@ -3512,6 +3511,8 @@ main(int32_t argc, char **argv)
>  		printf(" Done\n");
>  	}
> 
> +	flow_print_counters();
> +
>  	RTE_ETH_FOREACH_DEV(portid) {
>  		if ((enabled_port_mask & (1 << portid)) == 0)
>  			continue;
> --
> 2.35.3


^ permalink raw reply	[flat|nested] 11+ messages in thread

* RE: [dpdk-dev] [PATCH v4] examples/ipsec-secgw: support more flow patterns and actions
  2022-06-17 10:57 ` [dpdk-dev] [PATCH v4] " psatheesh
@ 2022-06-21 12:53   ` Akhil Goyal
  2022-06-21 17:25   ` Akhil Goyal
  1 sibling, 0 replies; 11+ messages in thread
From: Akhil Goyal @ 2022-06-21 12:53 UTC (permalink / raw)
  To: Satheesh Paul Antonysamy, Radu Nicolau, Konstantin Ananyev, Fan Zhang
  Cc: dev, Satheesh Paul Antonysamy

> 
> From: Satheesh Paul <psatheesh@marvell.com>
> 
> Added support to create flow rules with count, mark and
> security actions and mark pattern.
> 
> Signed-off-by: Satheesh Paul <psatheesh@marvell.com>
> ---
Acked-by: Akhil Goyal <gakhil@marvell.com>



^ permalink raw reply	[flat|nested] 11+ messages in thread

* RE: [dpdk-dev] [PATCH v4] examples/ipsec-secgw: support more flow patterns and actions
  2022-06-17 10:57 ` [dpdk-dev] [PATCH v4] " psatheesh
  2022-06-21 12:53   ` Akhil Goyal
@ 2022-06-21 17:25   ` Akhil Goyal
  1 sibling, 0 replies; 11+ messages in thread
From: Akhil Goyal @ 2022-06-21 17:25 UTC (permalink / raw)
  To: Satheesh Paul Antonysamy, Radu Nicolau; +Cc: dev, Satheesh Paul Antonysamy

> From: Satheesh Paul <psatheesh@marvell.com>
> 
> Added support to create flow rules with count, mark and
> security actions and mark pattern.
> 
> Signed-off-by: Satheesh Paul <psatheesh@marvell.com>
> ---
> v4:
> * Added more description in documenation for flow rule options.
> v3:
> * Fixed IPv4 and IPv6 dst addr setting in flow pattern spec
> v2:
> * Updated documentation in ipsec_secgw.rst
> 
Please rebase this patch. It does not apply cleanly.

^ permalink raw reply	[flat|nested] 11+ messages in thread

* [dpdk-dev] [PATCH v5] examples/ipsec-secgw: support more flow patterns and actions
  2022-04-19  8:25 [dpdk-dev] [PATCH] examples/ipsec-secgw: support more flow patterns and actions psatheesh
                   ` (2 preceding siblings ...)
  2022-06-17 10:57 ` [dpdk-dev] [PATCH v4] " psatheesh
@ 2022-06-22  1:22 ` psatheesh
  2022-06-23  8:35   ` Zhang, Roy Fan
  3 siblings, 1 reply; 11+ messages in thread
From: psatheesh @ 2022-06-22  1:22 UTC (permalink / raw)
  To: Radu Nicolau, Akhil Goyal; +Cc: dev, Satheesh Paul

From: Satheesh Paul <psatheesh@marvell.com>

Added support to create flow rules with count, mark and
security actions and mark pattern.

Signed-off-by: Satheesh Paul <psatheesh@marvell.com>
---
v5:
* Rebased the patch.
v4:
* Added more description in documenation for flow rule options.
v3:
* Fixed IPv4 and IPv6 dst addr setting in flow pattern spec.
v2:
* Updated documentation in ipsec_secgw.rst.

 doc/guides/sample_app_ug/ipsec_secgw.rst |  63 +++++-
 examples/ipsec-secgw/flow.c              | 274 +++++++++++++++++++----
 examples/ipsec-secgw/flow.h              |   1 +
 examples/ipsec-secgw/ipsec-secgw.c       |   3 +-
 4 files changed, 290 insertions(+), 51 deletions(-)

diff --git a/doc/guides/sample_app_ug/ipsec_secgw.rst b/doc/guides/sample_app_ug/ipsec_secgw.rst
index 94197a34f0..7032da8d0d 100644
--- a/doc/guides/sample_app_ug/ipsec_secgw.rst
+++ b/doc/guides/sample_app_ug/ipsec_secgw.rst
@@ -890,16 +890,35 @@ The flow rule syntax is shown as follows:
 
 .. code-block:: console
 
-    flow <ip_ver> <src_ip> <dst_ip> <port> <queue>
-
+    flow <mark> <eth> <ip_ver> <src_ip> <dst_ip> <port> <queue> \
+         <count> <security> <set_mark>
 
 where each options means:
 
+``<mark>``
+
+ * Set RTE_FLOW_ITEM_TYPE_MARK pattern item in the flow rule with the given
+   mark value. This option can be used to match an arbitrary integer value
+   which was set using the RTE_FLOW_ACTION_TYPE_MARK action (see ``<set_mark>``)
+   in a previously matched rule.
+
+ * Optional: Yes, this pattern is not set by default.
+
+ * Syntax: *mark X*
+
+``<eth>``
+
+ * Set RTE_FLOW_ITEM_TYPE_ETH pattern item. This matches all ethernet packets.
+
+ * Optional: Yes, this pattern is not set by default.
+
+ * Syntax: *eth*
+
 ``<ip_ver>``
 
  * IP protocol version
 
- * Optional: No
+ * Optional: Yes, this pattern is not set by default.
 
  * Available options:
 
@@ -944,6 +963,32 @@ where each options means:
 
  * Syntax: *queue X*
 
+``<count>``
+
+ * Set RTE_FLOW_ACTION_TYPE_COUNT action.
+
+ * Optional: yes, this action is not set by default.
+
+ * Syntax: *count*
+
+``<security>``
+
+ * Set RTE_FLOW_ITEM_TYPE_ESP pattern and RTE_FLOW_ACTION_TYPE_SECURITY action.
+
+ * Optional: yes, this pattern and action are not set by default.
+
+ * Syntax: *security*
+
+``<set_mark>``
+
+ * Set RTE_FLOW_ACTION_TYPE_MARK action in the flow rule with the given mark
+   value. This option can be used to set the given integer value(mark) to
+   packets and set RTE_MBUF_F_RX_FDIR and RTE_MBUF_F_RX_FDIR_ID mbuf flags.
+
+ * Optional: yes, this action is not set by default.
+
+ * Syntax: *set_mark X*
+
 Example flow rules:
 
 .. code-block:: console
@@ -952,6 +997,18 @@ Example flow rules:
 
     flow ipv6 dst 1111:1111:1111:1111:1111:1111:1111:5555/116 port 1 queue 0
 
+    flow mark 123 ipv4 dst 192.168.0.0/16 port 0 queue 0 count
+
+    flow eth ipv4 dst 192.168.0.0/16 port 0 queue 0 count
+
+    flow ipv4 dst 192.168.0.0/16 port 0 queue 0 count
+
+    flow ipv4 dst 192.168.0.0/16 port 0 queue 0
+
+    flow port 0 security set_mark 123
+
+    flow ipv4 dst 1.1.0.0/16 port 0 count set_mark 123 security
+
 
 Neighbour rule syntax
 ^^^^^^^^^^^^^^^^^^^^^
diff --git a/examples/ipsec-secgw/flow.c b/examples/ipsec-secgw/flow.c
index c217b9e475..aee97b2fc4 100644
--- a/examples/ipsec-secgw/flow.c
+++ b/examples/ipsec-secgw/flow.c
@@ -15,7 +15,9 @@
 #define FLOW_RULES_MAX 128
 
 struct flow_rule_entry {
+	uint8_t is_eth;
 	uint8_t is_ipv4;
+	uint8_t is_ipv6;
 	RTE_STD_C11
 	union {
 		struct {
@@ -27,8 +29,15 @@ struct flow_rule_entry {
 			struct rte_flow_item_ipv6 mask;
 		} ipv6;
 	};
+	struct rte_flow_item_mark mark_val;
 	uint16_t port;
 	uint16_t queue;
+	bool is_queue_set;
+	bool enable_count;
+	bool enable_mark;
+	bool set_security_action;
+	bool set_mark_action;
+	uint32_t mark_action_val;
 	struct rte_flow *flow;
 } flow_rule_tbl[FLOW_RULES_MAX];
 
@@ -64,8 +73,9 @@ ipv4_addr_cpy(rte_be32_t *spec, rte_be32_t *mask, char *token,
 	memcpy(mask, &rte_flow_item_ipv4_mask.hdr.src_addr, sizeof(ip));
 
 	*spec = ip.s_addr;
+
 	if (depth < 32)
-		*mask = *mask << (32-depth);
+		*mask = htonl(*mask << (32 - depth));
 
 	return 0;
 }
@@ -124,7 +134,7 @@ parse_flow_tokens(char **tokens, uint32_t n_tokens,
 		  struct parse_status *status)
 {
 	struct flow_rule_entry *rule;
-	uint32_t ti;
+	uint32_t ti = 0;
 
 	if (nb_flow_rule >= FLOW_RULES_MAX) {
 		printf("Too many flow rules\n");
@@ -134,49 +144,73 @@ parse_flow_tokens(char **tokens, uint32_t n_tokens,
 	rule = &flow_rule_tbl[nb_flow_rule];
 	memset(rule, 0, sizeof(*rule));
 
-	if (strcmp(tokens[0], "ipv4") == 0) {
-		rule->is_ipv4 = 1;
-	} else if (strcmp(tokens[0], "ipv6") == 0) {
-		rule->is_ipv4 = 0;
-	} else {
-		APP_CHECK(0, status, "unrecognized input \"%s\"", tokens[0]);
-		return;
-	}
-
-	for (ti = 1; ti < n_tokens; ti++) {
-		if (strcmp(tokens[ti], "src") == 0) {
+	for (ti = 0; ti < n_tokens; ti++) {
+		if (strcmp(tokens[ti], "mark") == 0) {
 			INCREMENT_TOKEN_INDEX(ti, n_tokens, status);
+			if (status->status < 0)
+				return;
+			APP_CHECK_TOKEN_IS_NUM(tokens, ti, status);
 			if (status->status < 0)
 				return;
 
-			if (rule->is_ipv4) {
+			rule->mark_val.id = atoi(tokens[ti]);
+			rule->enable_mark = true;
+			continue;
+		}
+		if (strcmp(tokens[ti], "eth") == 0) {
+			rule->is_eth = true;
+			continue;
+		}
+
+		if (strcmp(tokens[ti], "ipv4") == 0) {
+			rule->is_ipv4 = true;
+			INCREMENT_TOKEN_INDEX(ti, n_tokens, status);
+			if (status->status < 0)
+				return;
+			if (strcmp(tokens[ti], "src") == 0) {
+				INCREMENT_TOKEN_INDEX(ti, n_tokens, status);
+				if (status->status < 0)
+					return;
 				if (ipv4_addr_cpy(&rule->ipv4.spec.hdr.src_addr,
 						  &rule->ipv4.mask.hdr.src_addr,
 						  tokens[ti], status))
 					return;
-			} else {
-				if (ipv6_addr_cpy(rule->ipv6.spec.hdr.src_addr,
-						  rule->ipv6.mask.hdr.src_addr,
+			}
+			if (strcmp(tokens[ti], "dst") == 0) {
+				INCREMENT_TOKEN_INDEX(ti, n_tokens, status);
+				if (status->status < 0)
+					return;
+				if (ipv4_addr_cpy(&rule->ipv4.spec.hdr.dst_addr,
+						  &rule->ipv4.mask.hdr.dst_addr,
 						  tokens[ti], status))
 					return;
 			}
+			continue;
 		}
-		if (strcmp(tokens[ti], "dst") == 0) {
+		if (strcmp(tokens[ti], "ipv6") == 0) {
+			rule->is_ipv6 = true;
 			INCREMENT_TOKEN_INDEX(ti, n_tokens, status);
 			if (status->status < 0)
 				return;
-
-			if (rule->is_ipv4) {
-				if (ipv4_addr_cpy(&rule->ipv4.spec.hdr.dst_addr,
-						  &rule->ipv4.mask.hdr.dst_addr,
+			if (strcmp(tokens[ti], "src") == 0) {
+				INCREMENT_TOKEN_INDEX(ti, n_tokens, status);
+				if (status->status < 0)
+					return;
+				if (ipv6_addr_cpy(rule->ipv6.spec.hdr.src_addr,
+						  rule->ipv6.mask.hdr.src_addr,
 						  tokens[ti], status))
 					return;
-			} else {
+			}
+			if (strcmp(tokens[ti], "dst") == 0) {
+				INCREMENT_TOKEN_INDEX(ti, n_tokens, status);
+				if (status->status < 0)
+					return;
 				if (ipv6_addr_cpy(rule->ipv6.spec.hdr.dst_addr,
 						  rule->ipv6.mask.hdr.dst_addr,
 						  tokens[ti], status))
 					return;
 			}
+			continue;
 		}
 
 		if (strcmp(tokens[ti], "port") == 0) {
@@ -188,6 +222,7 @@ parse_flow_tokens(char **tokens, uint32_t n_tokens,
 				return;
 
 			rule->port = atoi(tokens[ti]);
+			continue;
 		}
 
 		if (strcmp(tokens[ti], "queue") == 0) {
@@ -199,50 +234,129 @@ parse_flow_tokens(char **tokens, uint32_t n_tokens,
 				return;
 
 			rule->queue = atoi(tokens[ti]);
+			rule->is_queue_set = true;
+			continue;
+		}
+
+		if (strcmp(tokens[ti], "count") == 0) {
+			rule->enable_count = true;
+			continue;
+		}
+
+		if (strcmp(tokens[ti], "security") == 0) {
+			rule->set_security_action = true;
+			continue;
 		}
+		if (strcmp(tokens[ti], "set_mark") == 0) {
+			INCREMENT_TOKEN_INDEX(ti, n_tokens, status);
+			if (status->status < 0)
+				return;
+			APP_CHECK_TOKEN_IS_NUM(tokens, ti, status);
+			if (status->status < 0)
+				return;
+
+			rule->set_mark_action = true;
+			rule->mark_action_val = atoi(tokens[ti]);
+			continue;
+		}
+
+		sprintf(status->parse_msg, "Unrecognized input:%s\n",
+			tokens[ti]);
+		status->status = -1;
+		return;
 	}
+	printf("\n");
 
 	nb_flow_rule++;
 }
 
-#define MAX_RTE_FLOW_PATTERN (3)
-#define MAX_RTE_FLOW_ACTIONS (2)
+#define MAX_RTE_FLOW_PATTERN (4)
+#define MAX_RTE_FLOW_ACTIONS (5)
 
 static void
 flow_init_single(struct flow_rule_entry *rule)
 {
-	struct rte_flow_item pattern[MAX_RTE_FLOW_PATTERN] = {};
 	struct rte_flow_action action[MAX_RTE_FLOW_ACTIONS] = {};
+	struct rte_flow_item pattern[MAX_RTE_FLOW_PATTERN] = {};
+	struct rte_flow_action_queue queue_action;
+	struct rte_flow_action_mark mark_action;
+	int ret, pattern_idx = 0, act_idx = 0;
+	struct rte_flow_item_mark mark_mask;
 	struct rte_flow_attr attr = {};
 	struct rte_flow_error err = {};
-	int ret;
 
 	attr.egress = 0;
 	attr.ingress = 1;
 
-	action[0].type = RTE_FLOW_ACTION_TYPE_QUEUE;
-	action[0].conf = &(struct rte_flow_action_queue) {
-				.index = rule->queue,
-	};
-	action[1].type = RTE_FLOW_ACTION_TYPE_END;
+	if (rule->is_queue_set) {
+		queue_action.index = rule->queue;
+		action[act_idx].type = RTE_FLOW_ACTION_TYPE_QUEUE;
+		action[act_idx].conf = &queue_action;
+		act_idx++;
+	}
 
-	pattern[0].type = RTE_FLOW_ITEM_TYPE_ETH;
+	if (rule->enable_count) {
+		action[act_idx].type = RTE_FLOW_ACTION_TYPE_COUNT;
+		act_idx++;
+	}
+
+	if (rule->set_security_action) {
+		action[act_idx].type = RTE_FLOW_ACTION_TYPE_SECURITY;
+		action[act_idx].conf = NULL;
+		act_idx++;
+	}
+
+	if (rule->set_mark_action) {
+		mark_action.id = rule->mark_action_val;
+		action[act_idx].type = RTE_FLOW_ACTION_TYPE_MARK;
+		action[act_idx].conf = &mark_action;
+		act_idx++;
+	}
+
+	action[act_idx].type = RTE_FLOW_ACTION_TYPE_END;
+	action[act_idx].conf = NULL;
+
+	if (rule->enable_mark) {
+		mark_mask.id = UINT32_MAX;
+		pattern[pattern_idx].type = RTE_FLOW_ITEM_TYPE_MARK;
+		pattern[pattern_idx].spec = &rule->mark_val;
+		pattern[pattern_idx].mask = &mark_mask;
+		pattern_idx++;
+	}
+
+	if (rule->is_eth) {
+		pattern[pattern_idx].type = RTE_FLOW_ITEM_TYPE_ETH;
+		pattern_idx++;
+	}
 
 	if (rule->is_ipv4) {
-		pattern[1].type = RTE_FLOW_ITEM_TYPE_IPV4;
-		pattern[1].spec = &rule->ipv4.spec;
-		pattern[1].mask = &rule->ipv4.mask;
-	} else {
-		pattern[1].type = RTE_FLOW_ITEM_TYPE_IPV6;
-		pattern[1].spec = &rule->ipv6.spec;
-		pattern[1].mask = &rule->ipv6.mask;
+		pattern[pattern_idx].type = RTE_FLOW_ITEM_TYPE_IPV4;
+		pattern[pattern_idx].spec = &rule->ipv4.spec;
+		pattern[pattern_idx].mask = &rule->ipv4.mask;
+		pattern_idx++;
+	}
+
+	if (rule->is_ipv6) {
+		pattern[pattern_idx].type = RTE_FLOW_ITEM_TYPE_IPV6;
+		pattern[pattern_idx].spec = &rule->ipv6.spec;
+		pattern[pattern_idx].mask = &rule->ipv6.mask;
+		pattern_idx++;
 	}
 
-	pattern[2].type = RTE_FLOW_ITEM_TYPE_END;
+	if (rule->set_security_action) {
+		pattern[pattern_idx].type = RTE_FLOW_ITEM_TYPE_ESP;
+		pattern[pattern_idx].spec = NULL;
+		pattern[pattern_idx].mask = NULL;
+		pattern[pattern_idx].last = NULL;
+		pattern_idx++;
+	}
+
+	pattern[pattern_idx].type = RTE_FLOW_ITEM_TYPE_END;
 
 	ret = rte_flow_validate(rule->port, &attr, pattern, action, &err);
 	if (ret < 0) {
 		RTE_LOG(ERR, IPSEC, "Flow validation failed %s\n", err.message);
+		rule->flow = 0;
 		return;
 	}
 
@@ -251,6 +365,56 @@ flow_init_single(struct flow_rule_entry *rule)
 		RTE_LOG(ERR, IPSEC, "Flow creation return %s\n", err.message);
 }
 
+void
+flow_print_counters(void)
+{
+	struct rte_flow_query_count count_query;
+	struct rte_flow_action action;
+	struct flow_rule_entry *rule;
+	struct rte_flow_error error;
+	int i = 0, ret = 0;
+
+	action.type = RTE_FLOW_ACTION_TYPE_COUNT;
+
+	for (i = 0; i < nb_flow_rule; i++) {
+		rule = &flow_rule_tbl[i];
+		if (!rule->flow || !rule->enable_count)
+			continue;
+
+		/* Poisoning to make sure PMDs update it in case of error. */
+		memset(&error, 0x55, sizeof(error));
+		memset(&count_query, 0, sizeof(count_query));
+		ret = rte_flow_query(rule->port, rule->flow, &action,
+				     &count_query, &error);
+		if (ret)
+			RTE_LOG(ERR, IPSEC,
+				"Failed to get flow counter "
+				" for port %u, err msg: %s\n",
+				rule->port, error.message);
+
+		printf("Flow #%3d:", i);
+		if (rule->is_ipv4) {
+			printf(" spec ipv4 ");
+			ipv4_hdr_print(&rule->ipv4.spec.hdr);
+		}
+		if (rule->is_ipv6) {
+			printf(" spec ipv6 ");
+			ipv6_hdr_print(&rule->ipv6.spec.hdr);
+		}
+
+		if (rule->set_security_action)
+			printf(" Security action set,");
+
+		if (rule->enable_mark)
+			printf(" Mark Enabled");
+
+		printf(" Port: %d,", rule->port);
+		if (rule->is_queue_set)
+			printf(" Queue: %d", rule->queue);
+		printf(" Hits: %"PRIu64"\n", count_query.hits);
+	}
+}
+
 void
 flow_init(void)
 {
@@ -264,21 +428,37 @@ flow_init(void)
 
 	for (i = 0; i < nb_flow_rule; i++) {
 		rule = &flow_rule_tbl[i];
+		printf("Flow #%3d: ", i);
 		if (rule->is_ipv4) {
-			printf("Flow #%3d: spec ipv4 ", i);
+			printf("spec ipv4 ");
 			ipv4_hdr_print(&rule->ipv4.spec.hdr);
 			printf("\n");
-			printf("           mask ipv4 ");
+			printf(" mask ipv4 ");
 			ipv4_hdr_print(&rule->ipv4.mask.hdr);
-		} else {
-			printf("Flow #%3d: spec ipv6 ", i);
+		}
+		if (rule->is_ipv6) {
+			printf("spec ipv6 ");
 			ipv6_hdr_print(&rule->ipv6.spec.hdr);
 			printf("\n");
-			printf("           mask ipv6 ");
+			printf(" mask ipv6 ");
 			ipv6_hdr_print(&rule->ipv6.mask.hdr);
 		}
 
-		printf("\tPort: %d, Queue: %d", rule->port, rule->queue);
+		if (rule->enable_mark)
+			printf(", Mark enabled");
+
+		printf("\tPort: %d,", rule->port);
+		if (rule->is_queue_set)
+			printf(" Queue: %d,", rule->queue);
+
+		if (rule->set_security_action)
+			printf(" Security action set,");
+
+		if (rule->set_mark_action)
+			printf(" Mark: %d,", rule->mark_action_val);
+
+		if (rule->enable_count)
+			printf(" Counter enabled,");
 
 		if (rule->flow == NULL)
 			printf(" [UNSUPPORTED]");
diff --git a/examples/ipsec-secgw/flow.h b/examples/ipsec-secgw/flow.h
index 1b1b4774e4..9492d06346 100644
--- a/examples/ipsec-secgw/flow.h
+++ b/examples/ipsec-secgw/flow.h
@@ -11,5 +11,6 @@ void parse_flow_tokens(char **tokens, uint32_t n_tokens,
 		       struct parse_status *status);
 
 void flow_init(void);
+void flow_print_counters(void);
 
 #endif /* _FLOW_H_ */
diff --git a/examples/ipsec-secgw/ipsec-secgw.c b/examples/ipsec-secgw/ipsec-secgw.c
index 25255e053c..fb97b67465 100644
--- a/examples/ipsec-secgw/ipsec-secgw.c
+++ b/examples/ipsec-secgw/ipsec-secgw.c
@@ -2875,7 +2875,6 @@ ipsec_secgw_telemetry_init(void)
 		"Optional Parameters: int <logical core id>");
 }
 
-
 int32_t
 main(int32_t argc, char **argv)
 {
@@ -3131,6 +3130,8 @@ main(int32_t argc, char **argv)
 		printf(" Done\n");
 	}
 
+	flow_print_counters();
+
 	RTE_ETH_FOREACH_DEV(portid) {
 		if ((enabled_port_mask & (1 << portid)) == 0)
 			continue;
-- 
2.35.3


^ permalink raw reply	[flat|nested] 11+ messages in thread

* RE: [dpdk-dev] [PATCH v5] examples/ipsec-secgw: support more flow patterns and actions
  2022-06-22  1:22 ` [dpdk-dev] [PATCH v5] " psatheesh
@ 2022-06-23  8:35   ` Zhang, Roy Fan
  2022-06-28  8:22     ` Akhil Goyal
  0 siblings, 1 reply; 11+ messages in thread
From: Zhang, Roy Fan @ 2022-06-23  8:35 UTC (permalink / raw)
  To: psatheesh, Nicolau, Radu, Akhil Goyal; +Cc: dev

> -----Original Message-----
> From: psatheesh@marvell.com <psatheesh@marvell.com>
> Sent: Wednesday, June 22, 2022 2:22 AM
> To: Nicolau, Radu <radu.nicolau@intel.com>; Akhil Goyal <gakhil@marvell.com>
> Cc: dev@dpdk.org; Satheesh Paul <psatheesh@marvell.com>
> Subject: [dpdk-dev] [PATCH v5] examples/ipsec-secgw: support more flow
> patterns and actions
> 
> From: Satheesh Paul <psatheesh@marvell.com>
> 
> Added support to create flow rules with count, mark and
> security actions and mark pattern.
> 
> Signed-off-by: Satheesh Paul <psatheesh@marvell.com>
> ---
Acked-by: Fan Zhang <roy.fan.zhang@intel.com>

^ permalink raw reply	[flat|nested] 11+ messages in thread

* RE: [dpdk-dev] [PATCH v5] examples/ipsec-secgw: support more flow patterns and actions
  2022-06-23  8:35   ` Zhang, Roy Fan
@ 2022-06-28  8:22     ` Akhil Goyal
  0 siblings, 0 replies; 11+ messages in thread
From: Akhil Goyal @ 2022-06-28  8:22 UTC (permalink / raw)
  To: Zhang, Roy Fan, Satheesh Paul Antonysamy, Nicolau, Radu; +Cc: dev

> > From: Satheesh Paul <psatheesh@marvell.com>
> >
> > Added support to create flow rules with count, mark and
> > security actions and mark pattern.
> >
> > Signed-off-by: Satheesh Paul <psatheesh@marvell.com>
> > ---
> Acked-by: Fan Zhang <roy.fan.zhang@intel.com>

Acked-by: Akhil Goyal <gakhil@marvell.com>

Applied to dpdk-next-crypto

^ permalink raw reply	[flat|nested] 11+ messages in thread

end of thread, other threads:[~2022-06-28  8:22 UTC | newest]

Thread overview: 11+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2022-04-19  8:25 [dpdk-dev] [PATCH] examples/ipsec-secgw: support more flow patterns and actions psatheesh
2022-05-24  5:32 ` [dpdk-dev] [PATCH v2] " psatheesh
2022-06-03  3:16 ` [dpdk-dev] [PATCH v3] " psatheesh
2022-06-17  9:52   ` Zhang, Roy Fan
2022-06-17 10:59     ` Satheesh Paul Antonysamy
2022-06-17 10:57 ` [dpdk-dev] [PATCH v4] " psatheesh
2022-06-21 12:53   ` Akhil Goyal
2022-06-21 17:25   ` Akhil Goyal
2022-06-22  1:22 ` [dpdk-dev] [PATCH v5] " psatheesh
2022-06-23  8:35   ` Zhang, Roy Fan
2022-06-28  8:22     ` Akhil Goyal

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).