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 v5] app/testpmd: enable cli for programmable action
Date: Wed, 11 Oct 2023 07:58:41 -0400 [thread overview]
Message-ID: <20231011115841.626763-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>
---
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
+ - ``aguments [{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
next prev parent reply other threads:[~2023-10-11 3:38 UTC|newest]
Thread overview: 21+ messages / expand[flat|nested] mbox.gz Atom feed top
2023-10-05 10:02 [PATCH 1/2] app/testpmd: enable cli for programmable action 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 ` Qi Zhang [this message]
2023-10-11 12:03 ` [PATCH v6] " Qi Zhang
2024-02-08 1:10 ` Ferruh Yigit
2024-04-18 15:39 ` Ferruh Yigit
2024-10-07 18:12 ` Stephen Hemminger
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=20231011115841.626763-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 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.