DPDK patches and discussions
 help / color / mirror / Atom feed
From: Alexander Kozyrev <akozyrev@nvidia.com>
To: dev@dpdk.org
Cc: viacheslavo@nvidia.com, orika@nvidia.com, thomas@monjalon.net,
	ferruh.yigit@intel.com, andrew.rybchenko@oktetlabs.ru,
	jerinjacobk@gmail.com
Subject: [dpdk-dev] [PATCH v5 2/2] app/testpmd: add support for modify field flow action
Date: Fri, 15 Jan 2021 15:42:46 +0000
Message-ID: <20210115154246.8770-3-akozyrev@nvidia.com> (raw)
In-Reply-To: <20210115154246.8770-1-akozyrev@nvidia.com>

Add support for the RTE_FLOW_ACTION_MODIFY_FIELD to the testpmd.
Implement CLI to create the modify_field action and supply all the
needed parameters to modify an arbitrary packet field (as well as
mark, tag or metadata) with data from another field or immediate
value.

Example of the flow is the following:
flow create 0 egress group 1 pattern eth / ipv4 / udp / end
  actions modify_field op mov dst_type tag dst_level 2 dst_offset 8
          src_type gtp_teid src_level 0 src_offset 0 width 16 / end

This flow copies 16 bits from the second Tag in the Tags array
into the outermost GTP TEID packet header field. 8 bits of the
Tag are skipped as indicated by the dst_offset action parameter.

op, dst_type, src_type and width are the mandatory parameters to
specify. Levels and offset are 0 by default if they are not
overridden by a user. The operation can be mov, add or sub.

Signed-off-by: Alexander Kozyrev <akozyrev@nvidia.com>

---
v1: Initial implementation.
v2: Made dst_type, src_type and width only mandatory parameters.
v3: Reworked to accomodate API change from copy_field to modify_field.
---
 app/test-pmd/cmdline_flow.c | 246 ++++++++++++++++++++++++++++++++++++
 1 file changed, 246 insertions(+)

diff --git a/app/test-pmd/cmdline_flow.c b/app/test-pmd/cmdline_flow.c
index 585cab98b4..62305b7fb7 100644
--- a/app/test-pmd/cmdline_flow.c
+++ b/app/test-pmd/cmdline_flow.c
@@ -408,6 +408,19 @@ enum index {
 	ACTION_SAMPLE_INDEX_VALUE,
 	ACTION_SHARED,
 	SHARED_ACTION_ID2PTR,
+	ACTION_MODIFY_FIELD,
+	ACTION_MODIFY_FIELD_OP,
+	ACTION_MODIFY_FIELD_OP_VALUE,
+	ACTION_MODIFY_FIELD_DST_TYPE,
+	ACTION_MODIFY_FIELD_DST_TYPE_VALUE,
+	ACTION_MODIFY_FIELD_DST_LEVEL,
+	ACTION_MODIFY_FIELD_DST_OFFSET,
+	ACTION_MODIFY_FIELD_SRC_TYPE,
+	ACTION_MODIFY_FIELD_SRC_TYPE_VALUE,
+	ACTION_MODIFY_FIELD_SRC_LEVEL,
+	ACTION_MODIFY_FIELD_SRC_OFFSET,
+	ACTION_MODIFY_FIELD_SRC_VALUE,
+	ACTION_MODIFY_FIELD_WIDTH,
 };
 
 /** Maximum size for pattern in struct rte_flow_item_raw. */
@@ -561,6 +574,22 @@ struct rte_flow_action_count sample_count[RAW_SAMPLE_CONFS_MAX_NUM];
 struct rte_flow_action_port_id sample_port_id[RAW_SAMPLE_CONFS_MAX_NUM];
 struct rte_flow_action_raw_encap sample_encap[RAW_SAMPLE_CONFS_MAX_NUM];
 
+static const char *const modify_field_ops[] = {
+	"mov", "add", "sub", NULL
+};
+
+static const char *const modify_field_ids[] = {
+	"start", "mac_dst", "mac_src",
+	"vlan_type", "vlan_id", "mac_type",
+	"ipv4_dscp", "ipv4_ttl", "ipv4_src", "ipv4_dst",
+	"ipv6_hoplimit", "ipv6_src", "ipv6_dst",
+	"tcp_port_src", "tcp_port_dst",
+	"tcp_seq_num", "tcp_ack_num", "tcp_flags",
+	"udp_port_src", "udp_port_dst",
+	"vxlan_vni", "geneve_vni", "gtp_teid",
+	"tag", "mark", "meta", "value", "pointer", NULL
+};
+
 /** Maximum number of subsequent tokens and arguments on the stack. */
 #define CTX_STACK_SIZE 16
 
@@ -1306,6 +1335,7 @@ static const enum index next_action[] = {
 	ACTION_AGE,
 	ACTION_SAMPLE,
 	ACTION_SHARED,
+	ACTION_MODIFY_FIELD,
 	ZERO,
 };
 
@@ -1556,6 +1586,21 @@ static const enum index next_action_sample[] = {
 	ZERO,
 };
 
+static const enum index action_modify_field_dst[] = {
+	ACTION_MODIFY_FIELD_DST_LEVEL,
+	ACTION_MODIFY_FIELD_DST_OFFSET,
+	ACTION_MODIFY_FIELD_SRC_TYPE,
+	ZERO,
+};
+
+static const enum index action_modify_field_src[] = {
+	ACTION_MODIFY_FIELD_SRC_LEVEL,
+	ACTION_MODIFY_FIELD_SRC_OFFSET,
+	ACTION_MODIFY_FIELD_SRC_VALUE,
+	ACTION_MODIFY_FIELD_WIDTH,
+	ZERO,
+};
+
 static int parse_set_raw_encap_decap(struct context *, const struct token *,
 				     const char *, unsigned int,
 				     void *, unsigned int);
@@ -1638,6 +1683,14 @@ static int
 parse_vc_action_sample_index(struct context *ctx, const struct token *token,
 				const char *str, unsigned int len, void *buf,
 				unsigned int size);
+static int
+parse_vc_modify_field_op(struct context *ctx, const struct token *token,
+				const char *str, unsigned int len, void *buf,
+				unsigned int size);
+static int
+parse_vc_modify_field_id(struct context *ctx, const struct token *token,
+				const char *str, unsigned int len, void *buf,
+				unsigned int size);
 static int parse_destroy(struct context *, const struct token *,
 			 const char *, unsigned int,
 			 void *, unsigned int);
@@ -1722,6 +1775,10 @@ static int comp_set_raw_index(struct context *, const struct token *,
 			      unsigned int, char *, unsigned int);
 static int comp_set_sample_index(struct context *, const struct token *,
 			      unsigned int, char *, unsigned int);
+static int comp_set_modify_field_op(struct context *, const struct token *,
+			      unsigned int, char *, unsigned int);
+static int comp_set_modify_field_id(struct context *, const struct token *,
+			      unsigned int, char *, unsigned int);
 
 /** Token definitions. */
 static const struct token token_list[] = {
@@ -4037,6 +4094,103 @@ static const struct token token_list[] = {
 		.call = parse_vc_action_raw_decap_index,
 		.comp = comp_set_raw_index,
 	},
+	[ACTION_MODIFY_FIELD] = {
+		.name = "modify_field",
+		.help = "modify destination field with data from source field",
+		.priv = PRIV_ACTION(MODIFY_FIELD,
+			sizeof(struct rte_flow_action_modify_field)),
+		.next = NEXT(NEXT_ENTRY(ACTION_MODIFY_FIELD_OP)),
+		.call = parse_vc,
+	},
+	[ACTION_MODIFY_FIELD_OP] = {
+		.name = "op",
+		.help = "operation type",
+		.next = NEXT(NEXT_ENTRY(ACTION_MODIFY_FIELD_DST_TYPE),
+			NEXT_ENTRY(ACTION_MODIFY_FIELD_OP_VALUE)),
+		.call = parse_vc_conf,
+	},
+	[ACTION_MODIFY_FIELD_OP_VALUE] = {
+		.name = "{operation}",
+		.help = "operation type value",
+		.call = parse_vc_modify_field_op,
+		.comp = comp_set_modify_field_op,
+	},
+	[ACTION_MODIFY_FIELD_DST_TYPE] = {
+		.name = "dst_type",
+		.help = "destination field type",
+		.next = NEXT(action_modify_field_dst,
+			NEXT_ENTRY(ACTION_MODIFY_FIELD_DST_TYPE_VALUE)),
+		.call = parse_vc_conf,
+	},
+	[ACTION_MODIFY_FIELD_DST_TYPE_VALUE] = {
+		.name = "{dst_type}",
+		.help = "destination field type value",
+		.call = parse_vc_modify_field_id,
+		.comp = comp_set_modify_field_id,
+	},
+	[ACTION_MODIFY_FIELD_DST_LEVEL] = {
+		.name = "dst_level",
+		.help = "destination field level",
+		.next = NEXT(action_modify_field_dst, NEXT_ENTRY(UNSIGNED)),
+		.args = ARGS(ARGS_ENTRY(struct rte_flow_action_modify_field,
+					dst.level)),
+		.call = parse_vc_conf,
+	},
+	[ACTION_MODIFY_FIELD_DST_OFFSET] = {
+		.name = "dst_offset",
+		.help = "destination field bit offset",
+		.next = NEXT(action_modify_field_dst, NEXT_ENTRY(UNSIGNED)),
+		.args = ARGS(ARGS_ENTRY(struct rte_flow_action_modify_field,
+					dst.offset)),
+		.call = parse_vc_conf,
+	},
+	[ACTION_MODIFY_FIELD_SRC_TYPE] = {
+		.name = "src_type",
+		.help = "source field type",
+		.next = NEXT(action_modify_field_src,
+			NEXT_ENTRY(ACTION_MODIFY_FIELD_SRC_TYPE_VALUE)),
+		.call = parse_vc_conf,
+	},
+	[ACTION_MODIFY_FIELD_SRC_TYPE_VALUE] = {
+		.name = "{src_type}",
+		.help = "source field type value",
+		.call = parse_vc_modify_field_id,
+		.comp = comp_set_modify_field_id,
+	},
+	[ACTION_MODIFY_FIELD_SRC_LEVEL] = {
+		.name = "src_level",
+		.help = "source field level",
+		.next = NEXT(action_modify_field_src, NEXT_ENTRY(UNSIGNED)),
+		.args = ARGS(ARGS_ENTRY(struct rte_flow_action_modify_field,
+					src.level)),
+		.call = parse_vc_conf,
+	},
+	[ACTION_MODIFY_FIELD_SRC_OFFSET] = {
+		.name = "src_offset",
+		.help = "source field bit offset",
+		.next = NEXT(action_modify_field_src, NEXT_ENTRY(UNSIGNED)),
+		.args = ARGS(ARGS_ENTRY(struct rte_flow_action_modify_field,
+					src.offset)),
+		.call = parse_vc_conf,
+	},
+	[ACTION_MODIFY_FIELD_SRC_VALUE] = {
+		.name = "src_value",
+		.help = "source immediate value",
+		.next = NEXT(NEXT_ENTRY(ACTION_MODIFY_FIELD_WIDTH),
+			NEXT_ENTRY(UNSIGNED)),
+		.args = ARGS(ARGS_ENTRY(struct rte_flow_action_modify_field,
+					src.value)),
+		.call = parse_vc_conf,
+	},
+	[ACTION_MODIFY_FIELD_WIDTH] = {
+		.name = "width",
+		.help = "number of bits to copy",
+		.next = NEXT(NEXT_ENTRY(ACTION_NEXT),
+			NEXT_ENTRY(UNSIGNED)),
+		.args = ARGS(ARGS_ENTRY(struct rte_flow_action_modify_field,
+					width)),
+		.call = parse_vc_conf,
+	},
 	/* Top level command. */
 	[SET] = {
 		.name = "set",
@@ -5960,6 +6114,62 @@ parse_vc_action_sample_index(struct context *ctx, const struct token *token,
 	return len;
 }
 
+/** Parse operation for modify_field command. */
+static int
+parse_vc_modify_field_op(struct context *ctx, const struct token *token,
+			 const char *str, unsigned int len, void *buf,
+			 unsigned int size)
+{
+	struct rte_flow_action_modify_field *action_modify_field;
+	unsigned int i;
+
+	(void)token;
+	(void)buf;
+	(void)size;
+	if (ctx->curr != ACTION_MODIFY_FIELD_OP_VALUE)
+		return -1;
+	for (i = 0; modify_field_ops[i]; ++i)
+		if (!strcmp_partial(modify_field_ops[i], str, len))
+			break;
+	if (!modify_field_ops[i])
+		return -1;
+	if (!ctx->object)
+		return len;
+	action_modify_field = ctx->object;
+	action_modify_field->operation = (enum rte_flow_modify_op)i;
+	return len;
+}
+
+/** Parse id for modify_field command. */
+static int
+parse_vc_modify_field_id(struct context *ctx, const struct token *token,
+			 const char *str, unsigned int len, void *buf,
+			 unsigned int size)
+{
+	struct rte_flow_action_modify_field *action_modify_field;
+	unsigned int i;
+
+	(void)token;
+	(void)buf;
+	(void)size;
+	if (ctx->curr != ACTION_MODIFY_FIELD_DST_TYPE_VALUE &&
+		ctx->curr != ACTION_MODIFY_FIELD_SRC_TYPE_VALUE)
+		return -1;
+	for (i = 0; modify_field_ids[i]; ++i)
+		if (!strcmp_partial(modify_field_ids[i], str, len))
+			break;
+	if (!modify_field_ids[i])
+		return -1;
+	if (!ctx->object)
+		return len;
+	action_modify_field = ctx->object;
+	if (ctx->curr == ACTION_MODIFY_FIELD_DST_TYPE_VALUE)
+		action_modify_field->dst.field = (enum rte_flow_field_id)i;
+	else
+		action_modify_field->src.field = (enum rte_flow_field_id)i;
+	return len;
+}
+
 /** Parse tokens for destroy command. */
 static int
 parse_destroy(struct context *ctx, const struct token *token,
@@ -7029,6 +7239,42 @@ comp_set_sample_index(struct context *ctx, const struct token *token,
 	return nb;
 }
 
+/** Complete operation for modify_field command. */
+static int
+comp_set_modify_field_op(struct context *ctx, const struct token *token,
+		   unsigned int ent, char *buf, unsigned int size)
+{
+	uint16_t idx = 0;
+
+	RTE_SET_USED(ctx);
+	RTE_SET_USED(token);
+	for (idx = 0; modify_field_ops[idx]; ++idx)
+		;
+	if (!buf)
+		return idx + 1;
+	if (ent < idx)
+		return strlcpy(buf, modify_field_ops[ent], size);
+	return -1;
+}
+
+/** Complete field id for modify_field command. */
+static int
+comp_set_modify_field_id(struct context *ctx, const struct token *token,
+		   unsigned int ent, char *buf, unsigned int size)
+{
+	uint16_t idx = 0;
+
+	RTE_SET_USED(ctx);
+	RTE_SET_USED(token);
+	for (idx = 0; modify_field_ids[idx]; ++idx)
+		;
+	if (!buf)
+		return idx + 1;
+	if (ent < idx)
+		return strlcpy(buf, modify_field_ids[ent], size);
+	return -1;
+}
+
 /** Internal context. */
 static struct context cmd_flow_context;
 
-- 
2.24.1


  parent reply	other threads:[~2021-01-15 15:43 UTC|newest]

Thread overview: 48+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2021-01-08  6:32 [dpdk-dev] [PATCH] ethdev: introduce generic copy rte " Alexander Kozyrev
2021-01-10  8:00 ` Ori Kam
2021-01-10  9:36   ` Asaf Penso
2021-01-12 14:15   ` Alexander Kozyrev
2021-01-12 14:52     ` Ori Kam
2021-01-12 15:13       ` Ori Kam
2021-01-12 17:19         ` Alexander Kozyrev
2021-01-12  5:01 ` [dpdk-dev] [PATCH v2 0/2] generic copy rte flow action support Alexander Kozyrev
2021-01-12  5:01   ` [dpdk-dev] [PATCH v2 1/2] ethdev: introduce generic copy rte flow action Alexander Kozyrev
2021-01-12  5:01   ` [dpdk-dev] [PATCH v2 2/2] app/testpmd: add support for " Alexander Kozyrev
2021-01-12 14:58     ` Ori Kam
2021-01-13  3:38   ` [dpdk-dev] [PATCH v3 0/2] generic copy rte flow action support Alexander Kozyrev
2021-01-13  3:38     ` [dpdk-dev] [PATCH v3 1/2] ethdev: introduce generic copy rte flow action Alexander Kozyrev
2021-01-13 11:12       ` Ori Kam
2021-01-13  3:38     ` [dpdk-dev] [PATCH v3 2/2] app/testpmd: add support for " Alexander Kozyrev
2021-01-13 17:07     ` [dpdk-dev] [PATCH v4 0/2] generic copy rte flow action support Alexander Kozyrev
2021-01-13 17:07       ` [dpdk-dev] [PATCH v4 1/2] ethdev: introduce generic copy rte flow action Alexander Kozyrev
2021-01-14 12:22         ` Ori Kam
2021-01-13 17:07       ` [dpdk-dev] [PATCH v4 2/2] app/testpmd: add support for " Alexander Kozyrev
2021-01-14 15:18         ` Ori Kam
2021-01-15 15:37           ` Alexander Kozyrev
2021-01-15 15:42       ` [dpdk-dev] [PATCH v5 0/2] generic modify rte flow action support Alexander Kozyrev
2021-01-15 15:42         ` [dpdk-dev] [PATCH v5 1/2] ethdev: introduce generic modify rte flow action Alexander Kozyrev
2021-01-15 18:03           ` Ori Kam
2021-01-17  9:23             ` Slava Ovsiienko
2021-01-15 15:42         ` Alexander Kozyrev [this message]
2021-01-15 18:04           ` [dpdk-dev] [PATCH v5 2/2] app/testpmd: add support for modify field " Ori Kam
2021-01-16  4:44         ` [dpdk-dev] [PATCH v6 0/2] generic modify rte flow action support Alexander Kozyrev
2021-01-16  4:44           ` [dpdk-dev] [PATCH v6 1/2] ethdev: introduce generic modify rte flow action Alexander Kozyrev
2021-01-16  4:44           ` [dpdk-dev] [PATCH v6 2/2] app/testpmd: add support for modify field " Alexander Kozyrev
2021-01-16  4:50           ` [dpdk-dev] [PATCH v7 0/2] generic modify rte flow action support Alexander Kozyrev
2021-01-16  4:50             ` [dpdk-dev] [PATCH v7 1/2] ethdev: introduce generic modify rte flow action Alexander Kozyrev
2021-01-17 23:15               ` Thomas Monjalon
2021-01-18 16:03                 ` Alexander Kozyrev
2021-01-16  4:50             ` [dpdk-dev] [PATCH v7 2/2] app/testpmd: add support for modify field " Alexander Kozyrev
2021-01-18 16:18             ` [dpdk-dev] [PATCH v8 0/2] generic modify rte flow action support Alexander Kozyrev
2021-01-18 16:18               ` [dpdk-dev] [PATCH v8 1/2] ethdev: introduce generic modify rte flow action Alexander Kozyrev
2021-01-18 17:51                 ` Thomas Monjalon
2021-01-18 16:18               ` [dpdk-dev] [PATCH v8 2/2] app/testpmd: add support for modify field " Alexander Kozyrev
2021-01-18 20:05               ` [dpdk-dev] [PATCH v8 0/2] generic modify rte flow action support Ajit Khaparde
2021-01-18 21:40               ` [dpdk-dev] [PATCH v9 " Alexander Kozyrev
2021-01-18 21:40                 ` [dpdk-dev] [PATCH v9 1/2] ethdev: introduce generic modify rte flow action Alexander Kozyrev
2021-01-18 21:40                 ` [dpdk-dev] [PATCH v9 2/2] app/testpmd: add support for modify field " Alexander Kozyrev
2021-01-19  1:21                 ` [dpdk-dev] [PATCH v9 0/2] generic modify rte flow action support Ferruh Yigit
2021-01-14 13:59 ` [dpdk-dev] [PATCH] ethdev: introduce generic copy rte flow action Jerin Jacob
2021-01-14 15:02   ` Ori Kam
2021-01-15 14:00     ` Jerin Jacob
2021-01-15 15:33       ` Alexander Kozyrev

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=20210115154246.8770-3-akozyrev@nvidia.com \
    --to=akozyrev@nvidia.com \
    --cc=andrew.rybchenko@oktetlabs.ru \
    --cc=dev@dpdk.org \
    --cc=ferruh.yigit@intel.com \
    --cc=jerinjacobk@gmail.com \
    --cc=orika@nvidia.com \
    --cc=thomas@monjalon.net \
    --cc=viacheslavo@nvidia.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

DPDK patches and discussions

This inbox may be cloned and mirrored by anyone:

	git clone --mirror https://inbox.dpdk.org/dev/0 dev/git/0.git

	# If you have public-inbox 1.1+ installed, you may
	# initialize and index your mirror using the following commands:
	public-inbox-init -V2 dev dev/ https://inbox.dpdk.org/dev \
		dev@dpdk.org
	public-inbox-index dev

Example config snippet for mirrors.
Newsgroup available over NNTP:
	nntp://inbox.dpdk.org/inbox.dpdk.dev


AGPL code for this site: git clone https://public-inbox.org/public-inbox.git