All of lore.kernel.org
 help / color / mirror / Atom feed
From: <psatheesh@marvell.com>
To: Radu Nicolau <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
Date: Wed, 22 Jun 2022 06:52:23 +0530	[thread overview]
Message-ID: <20220622012223.1903350-1-psatheesh@marvell.com> (raw)
In-Reply-To: <20220419082537.270116-1-psatheesh@marvell.com>

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


  parent reply	other threads:[~2022-06-22  1:22 UTC|newest]

Thread overview: 11+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
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 ` psatheesh [this message]
2022-06-23  8:35   ` [dpdk-dev] [PATCH v5] " Zhang, Roy Fan
2022-06-28  8:22     ` Akhil Goyal

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20220622012223.1903350-1-psatheesh@marvell.com \
    --to=psatheesh@marvell.com \
    --cc=dev@dpdk.org \
    --cc=gakhil@marvell.com \
    --cc=radu.nicolau@intel.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.