DPDK patches and discussions
 help / color / mirror / Atom feed
From: Qi Zhang <qi.z.zhang@intel.com>
To: aman.deep.singh@intel.com, yuying.zhang@intel.com
Cc: dev@dpdk.org, cristian.dumitrescu@intel.com, orika@nvidia.com,
	ferruh.yigit@amd.com, Qi Zhang <qi.z.zhang@intel.com>
Subject: [PATCH v6] app/testpmd: enable cli for programmable action
Date: Wed, 11 Oct 2023 08:03:32 -0400	[thread overview]
Message-ID: <20231011120332.626859-1-qi.z.zhang@intel.com> (raw)
In-Reply-To: <20231005100246.242970-1-qi.z.zhang@intel.com>

Parsing command line for rte_flow_action_prog.

Syntax:

"prog name <name> [arguments <arg_name_0> <arg_value_0> \
 <arg_name_1> <arg_value1> ... end]"

Use parse_string0 to parse name string.
Use parse_hex to parse hex string.
Use struct action_prog_data to store parsed result.

Example:

Action with 2 arguments:

"prog name action0 arguments field0 03FF field1 55AA end"

Action without argument:

"prog name action1"

Signed-off-by: Qi Zhang <qi.z.zhang@intel.com>
---
v6:
- fix typo.

v5:
- complete testpmd document.

v4:
- be more generous on the max size of name and value.

v3:
- refine struct action_prog_data
- enlarge the max size

v2:
- fix title
- minor coding style refine.

 app/test-pmd/cmdline_flow.c                 | 232 ++++++++++++++++++++
 doc/guides/testpmd_app_ug/testpmd_funcs.rst |  17 ++
 2 files changed, 249 insertions(+)

diff --git a/app/test-pmd/cmdline_flow.c b/app/test-pmd/cmdline_flow.c
index 70eef3e34d..d9152f9485 100644
--- a/app/test-pmd/cmdline_flow.c
+++ b/app/test-pmd/cmdline_flow.c
@@ -721,6 +721,13 @@ enum index {
 	ACTION_IPV6_EXT_PUSH,
 	ACTION_IPV6_EXT_PUSH_INDEX,
 	ACTION_IPV6_EXT_PUSH_INDEX_VALUE,
+	ACTION_PROG,
+	ACTION_PROG_NAME,
+	ACTION_PROG_NAME_STRING,
+	ACTION_PROG_ARGUMENTS,
+	ACTION_PROG_ARG_NAME,
+	ACTION_PROG_ARG_VALUE,
+	ACTION_PROG_ARG_END,
 };
 
 /** Maximum size for pattern in struct rte_flow_item_raw. */
@@ -751,6 +758,23 @@ struct action_rss_data {
 	uint16_t queue[ACTION_RSS_QUEUE_NUM];
 };
 
+#define ACTION_PROG_NAME_SIZE_MAX 256
+#define ACTION_PROG_ARG_NUM_MAX 16
+#define ACTION_PROG_ARG_VALUE_SIZE_MAX 64
+
+/** Storage for struct rte_flow_action_prog including external data. */
+struct action_prog_data {
+	struct rte_flow_action_prog conf;
+	struct {
+		char name[ACTION_PROG_NAME_SIZE_MAX];
+		struct rte_flow_action_prog_argument args[ACTION_PROG_ARG_NUM_MAX];
+		struct {
+			char names[ACTION_PROG_NAME_SIZE_MAX];
+			uint8_t value[ACTION_PROG_ARG_VALUE_SIZE_MAX];
+		} arg_data[ACTION_PROG_ARG_NUM_MAX];
+	} data;
+};
+
 /** Maximum data size in struct rte_flow_action_raw_encap. */
 #define ACTION_RAW_ENCAP_MAX_DATA 512
 #define RAW_ENCAP_CONFS_MAX_NUM 8
@@ -2178,6 +2202,7 @@ static const enum index next_action[] = {
 	ACTION_QUOTA_QU,
 	ACTION_IPV6_EXT_REMOVE,
 	ACTION_IPV6_EXT_PUSH,
+	ACTION_PROG,
 	ZERO,
 };
 
@@ -2519,6 +2544,13 @@ static const enum index action_represented_port[] = {
 	ZERO,
 };
 
+static const enum index action_prog[] = {
+	ACTION_PROG_NAME,
+	ACTION_PROG_ARGUMENTS,
+	ACTION_NEXT,
+	ZERO,
+};
+
 static int parse_set_raw_encap_decap(struct context *, const struct token *,
 				     const char *, unsigned int,
 				     void *, unsigned int);
@@ -2795,6 +2827,18 @@ static int
 parse_qu_mode_name(struct context *ctx, const struct token *token,
 		   const char *str, unsigned int len, void *buf,
 		   unsigned int size);
+static int
+parse_vc_action_prog(struct context *, const struct token *,
+		     const char *, unsigned int, void *,
+		     unsigned int);
+static int
+parse_vc_action_prog_arg_name(struct context *, const struct token *,
+			      const char *, unsigned int, void *,
+			      unsigned int);
+static int
+parse_vc_action_prog_arg_value(struct context *, const struct token *,
+			       const char *, unsigned int, void *,
+			       unsigned int);
 static int comp_none(struct context *, const struct token *,
 		     unsigned int, char *, unsigned int);
 static int comp_boolean(struct context *, const struct token *,
@@ -7543,6 +7587,48 @@ static const struct token token_list[] = {
 		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_tx_queue,
 					tx_queue)),
 	},
+	[ACTION_PROG] = {
+		.name = "prog",
+		.help = "match a programmable action",
+		.priv = PRIV_ACTION(PROG, sizeof(struct action_prog_data)),
+		.next = NEXT(action_prog),
+		.call = parse_vc_action_prog,
+	},
+	[ACTION_PROG_NAME] = {
+		.name = "name",
+		.help = "programble action name",
+		.next = NEXT(action_prog, NEXT_ENTRY(ACTION_PROG_NAME_STRING)),
+		.args = ARGS(ARGS_ENTRY(struct action_prog_data, data.name)),
+	},
+	[ACTION_PROG_NAME_STRING] = {
+		.name = "{string}",
+		.type = "STRING",
+		.help = "programmable action name string",
+		.call = parse_string0,
+	},
+	[ACTION_PROG_ARGUMENTS] = {
+		.name = "arguments",
+		.help = "programmable action name",
+		.next = NEXT(action_prog, NEXT_ENTRY(ACTION_PROG_ARG_NAME)),
+		.call = parse_vc_conf,
+	},
+	[ACTION_PROG_ARG_NAME] = {
+		.name = "{string}",
+		.help = "programmable action argument name",
+		.next = NEXT(NEXT_ENTRY(ACTION_PROG_ARG_VALUE)),
+		.call = parse_vc_action_prog_arg_name,
+	},
+	[ACTION_PROG_ARG_VALUE] = {
+		.name = "{hex}",
+		.help = "programmable action argument value",
+		.next = NEXT(NEXT_ENTRY(ACTION_PROG_ARG_END, ACTION_PROG_ARG_NAME)),
+		.call = parse_vc_action_prog_arg_value,
+	},
+	[ACTION_PROG_ARG_END] = {
+		.name = "end",
+		.help = "end of the programmable action arguments",
+	},
+
 };
 
 /** Remove and return last entry from argument stack. */
@@ -11700,6 +11786,152 @@ parse_qu_mode_name(struct context *ctx, const struct token *token,
 				   (uint32_t *)&out->args.ia.qu_mode);
 }
 
+/** Parse prog action. */
+static int
+parse_vc_action_prog(struct context *ctx, const struct token *token,
+		     const char *str, unsigned int len,
+		     void *buf, unsigned int size)
+{
+	struct buffer *out = buf;
+	struct rte_flow_action *action;
+	struct action_prog_data *action_prog_data;
+	uint16_t i;
+	int ret;
+
+	ret = parse_vc(ctx, token, str, len, buf, size);
+	if (ret < 0)
+		return ret;
+
+	if (!out)
+		return ret;
+
+	if (!out->args.vc.actions_n)
+		return -1;
+
+	action = &out->args.vc.actions[out->args.vc.actions_n - 1];
+	ctx->object = out->args.vc.data;
+	action_prog_data = ctx->object;
+	*action_prog_data = (struct action_prog_data) {
+		.conf = (struct rte_flow_action_prog) {
+			.args_num = 0,
+			.name = action_prog_data->data.name,
+			.args = action_prog_data->data.args,
+		},
+	};
+
+	for (i = 0; i < ACTION_PROG_ARG_NUM_MAX; ++i)
+		action_prog_data->data.args[i].name = action_prog_data->data.arg_data[i].names;
+	action->conf = &action_prog_data->conf;
+
+	return ret;
+}
+
+static int
+parse_vc_action_prog_arg_name(struct context *ctx, const struct token *token,
+			      const char *str, unsigned int len,
+			      void *buf, unsigned int size)
+{
+	struct action_prog_data *action_prog_data;
+	struct buffer *out = buf;
+	const struct arg *arg;
+	uint32_t i;
+	int ret;
+
+	(void)token;
+	(void)buf;
+	(void)size;
+	if (ctx->curr != ACTION_PROG_ARG_NAME)
+		return -1;
+
+	if (!out)
+		return len;
+
+	action_prog_data = (void *)out->args.vc.data;
+	i = action_prog_data->conf.args_num;
+
+	if (i >= ACTION_PROG_ARG_NUM_MAX)
+		return -1;
+
+	arg = ARGS_ENTRY_ARB(offsetof(struct action_prog_data,
+				      data.arg_data[i].names),
+			     ACTION_PROG_NAME_SIZE_MAX);
+
+	if (push_args(ctx, arg))
+		return -1;
+
+	ret = parse_string0(ctx, token, str, len, NULL, 0);
+	if (ret < 0) {
+		pop_args(ctx);
+		return -1;
+	}
+
+	return len;
+}
+
+static int
+parse_vc_action_prog_arg_value(struct context *ctx, const struct token *token,
+			       const char *str, unsigned int len,
+			       void *buf, unsigned int size)
+{
+	struct action_prog_data *action_prog_data;
+	const struct arg *arg_addr;
+	const struct arg *arg_size;
+	const struct arg *arg_data;
+	struct buffer *out = buf;
+	uint32_t i;
+	int ret;
+
+	(void)token;
+	(void)buf;
+	(void)size;
+	if (ctx->curr != ACTION_PROG_ARG_VALUE)
+		return -1;
+
+	if (!out)
+		return len;
+
+	action_prog_data = (void *)out->args.vc.data;
+	i = action_prog_data->conf.args_num;
+
+	arg_addr  = ARGS_ENTRY_ARB(offsetof(struct action_prog_data,
+					    data.args[i].value),
+				   sizeof(action_prog_data->data.args[i].value));
+
+	arg_size = ARGS_ENTRY_ARB(offsetof(struct action_prog_data,
+					   data.args[i].size),
+				   sizeof(action_prog_data->data.args[i].size));
+
+	arg_data = ARGS_ENTRY_ARB(offsetof(struct action_prog_data,
+					   data.arg_data[i].value),
+				  ACTION_PROG_ARG_VALUE_SIZE_MAX);
+
+	if (push_args(ctx, arg_addr))
+		return -1;
+
+	if (push_args(ctx, arg_size)) {
+		pop_args(ctx);
+		return -1;
+	}
+
+	if (push_args(ctx, arg_data)) {
+		pop_args(ctx);
+		pop_args(ctx);
+		return -1;
+	}
+
+	ret = parse_hex(ctx, token, str, len, NULL, 0);
+	if (ret < 0) {
+		pop_args(ctx);
+		pop_args(ctx);
+		pop_args(ctx);
+		return -1;
+	}
+
+	action_prog_data->conf.args_num++;
+
+	return len;
+}
+
 /** No completion. */
 static int
 comp_none(struct context *ctx, const struct token *token,
diff --git a/doc/guides/testpmd_app_ug/testpmd_funcs.rst b/doc/guides/testpmd_app_ug/testpmd_funcs.rst
index 67968ecb7f..84be67625a 100644
--- a/doc/guides/testpmd_app_ug/testpmd_funcs.rst
+++ b/doc/guides/testpmd_app_ug/testpmd_funcs.rst
@@ -4108,6 +4108,14 @@ This section lists supported actions and their attributes, if any.
   - ``mtr_init_color {value}``: initial color value (green/yellow/red)
   - ``mtr_state {unsigned}``: meter state (disabled/enabled)
 
+- ``prog``: Set a Programmable Action that aligns with the current device
+  configuration, typically intended for use with a P4 programmable device.
+
+  - ``name {string}``: The name of a Programmable Action schema
+  - ``arguments [{string} {hex string} [...]] end``: It is optional, the names
+    and values of each argument for the Programmable Action in a list, the
+    name is represented as {string} and value is represented as {hex string}
+
 Destroying flow rules
 ~~~~~~~~~~~~~~~~~~~~~
 
@@ -5262,6 +5270,15 @@ A RAW rule can be created as following using ``pattern_hex`` key and mask.
              pattern_hex mask 0000000000000000000000000000000000000000000000000000ffffffff / end actions
              queue index 4 / end
 
+Sample Programmable Action rule
+
+A rule use Programmable Action to perform a customized tunnel header encap for specific IP packets.
+
+::
+
+    testpmd> flow create 0 ingress pattern eth / ipv4 src is 1.2.3.4 / end actions prog name cust_tun_encap
+             arguments tunn_id 55AA meta0 2E meta1 9000 end / end
+
 BPF Functions
 --------------
 
-- 
2.31.1


  parent reply	other threads:[~2023-10-11  3:43 UTC|newest]

Thread overview: 20+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2023-10-05 10:02 [PATCH 1/2] " Qi Zhang
2023-10-05 11:42 ` [PATCH v2] " Qi Zhang
2023-10-05  4:32   ` Stephen Hemminger
2023-10-06  2:37     ` Zhang, Qi Z
2023-10-06 11:07 ` [PATCH v3] " Qi Zhang
2023-10-06 12:35   ` Dumitrescu, Cristian
2023-10-07  1:50     ` Zhang, Qi Z
2023-10-07 10:47 ` [PATCH v4] " Qi Zhang
2023-10-08  0:06   ` Dumitrescu, Cristian
2023-10-10 10:49   ` Ferruh Yigit
2023-10-11  2:24     ` Zhang, Qi Z
2023-10-11 10:20       ` Ferruh Yigit
2023-10-11 13:19         ` Zhang, Qi Z
2023-10-12  0:04           ` Zhang, Qi Z
2023-10-12  1:32             ` Stephen Hemminger
2023-10-27 11:06               ` Zhang, Qi Z
2023-10-11 11:58 ` [PATCH v5] " Qi Zhang
2023-10-11 12:03 ` Qi Zhang [this message]
2024-02-08  1:10   ` [PATCH v6] " Ferruh Yigit
2024-04-18 15:39     ` Ferruh Yigit

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=20231011120332.626859-1-qi.z.zhang@intel.com \
    --to=qi.z.zhang@intel.com \
    --cc=aman.deep.singh@intel.com \
    --cc=cristian.dumitrescu@intel.com \
    --cc=dev@dpdk.org \
    --cc=ferruh.yigit@amd.com \
    --cc=orika@nvidia.com \
    --cc=yuying.zhang@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 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).