[v2,2/2] app/testpmd: add support for generic copy rte flow action

Message ID 20210112050110.1987-3-akozyrev@nvidia.com (mailing list archive)
State Superseded, archived
Delegated to: Thomas Monjalon
Headers
Series ethdev: introduce generic copy rte flow action |

Checks

Context Check Description
ci/checkpatch success coding style OK

Commit Message

Alexander Kozyrev Jan. 12, 2021, 5:01 a.m. UTC
  Add support for the RTE_FLOW_ACTION_COPY_ITEM to the testpmd.
Implement CLI to create the copy_item action and supply all the
needed parameters to copy an arbitrary packet field (as well as
mark, tag or metadata) into another item.

Example of the flow is the following:
flow create 0 egress group 1 pattern eth / ipv4 / udp / end
     actions copy_item dst_type tag dst_index 0 dst_offset 8
     src_type gtp_teid src_index 0 src_offset 0 width 32 / end

This flow copies 32 bits from the first 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.

Signed-off-by: Alexander Kozyrev <akozyrev@nvidia.com>
---
 app/test-pmd/cmdline_flow.c | 156 ++++++++++++++++++++++++++++++++++++
 1 file changed, 156 insertions(+)
  

Comments

Ori Kam Jan. 12, 2021, 2:58 p.m. UTC | #1
Hi Alexander,

> -----Original Message-----
> From: dev <dev-bounces@dpdk.org> On Behalf Of Alexander Kozyrev
> Subject: [dpdk-dev] [PATCH v2 2/2] app/testpmd: add support for generic copy
> rte flow action
> 
> Add support for the RTE_FLOW_ACTION_COPY_ITEM to the testpmd.
> Implement CLI to create the copy_item action and supply all the
> needed parameters to copy an arbitrary packet field (as well as
> mark, tag or metadata) into another item.
> 
> Example of the flow is the following:
> flow create 0 egress group 1 pattern eth / ipv4 / udp / end
>      actions copy_item dst_type tag dst_index 0 dst_offset 8
>      src_type gtp_teid src_index 0 src_offset 0 width 32 / end
> 
This is a long command, and for most cases holds to many extra values.
I suggest to allow default values, meaning that the application must
say the src and the dest fields but all the rest of the information can be
extract from those two parameters (offset =0, len(field_type).
If the user request he can add those parameters for more control.

> This flow copies 32 bits from the first 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.
> 
> Signed-off-by: Alexander Kozyrev <akozyrev@nvidia.com>
> ---


Best,
Ori
  

Patch

diff --git a/app/test-pmd/cmdline_flow.c b/app/test-pmd/cmdline_flow.c
index 585cab98b4..1acf8fddf8 100644
--- a/app/test-pmd/cmdline_flow.c
+++ b/app/test-pmd/cmdline_flow.c
@@ -408,6 +408,16 @@  enum index {
 	ACTION_SAMPLE_INDEX_VALUE,
 	ACTION_SHARED,
 	SHARED_ACTION_ID2PTR,
+	ACTION_COPY_ITEM,
+	ACTION_COPY_ITEM_DST_TYPE,
+	ACTION_COPY_ITEM_DST_TYPE_VALUE,
+	ACTION_COPY_ITEM_DST_INDEX,
+	ACTION_COPY_ITEM_DST_OFFSET,
+	ACTION_COPY_ITEM_SRC_TYPE,
+	ACTION_COPY_ITEM_SRC_TYPE_VALUE,
+	ACTION_COPY_ITEM_SRC_INDEX,
+	ACTION_COPY_ITEM_SRC_OFFSET,
+	ACTION_COPY_ITEM_WIDTH,
 };
 
 /** Maximum size for pattern in struct rte_flow_item_raw. */
@@ -561,6 +571,18 @@  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 copy_item_table[] = {
+	"none", "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", NULL
+};
+
 /** Maximum number of subsequent tokens and arguments on the stack. */
 #define CTX_STACK_SIZE 16
 
@@ -1306,6 +1328,7 @@  static const enum index next_action[] = {
 	ACTION_AGE,
 	ACTION_SAMPLE,
 	ACTION_SHARED,
+	ACTION_COPY_ITEM,
 	ZERO,
 };
 
@@ -1638,6 +1661,10 @@  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_copy_item(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 +1749,8 @@  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_copy_item(struct context *, const struct token *,
+			      unsigned int, char *, unsigned int);
 
 /** Token definitions. */
 static const struct token token_list[] = {
@@ -4037,6 +4066,85 @@  static const struct token token_list[] = {
 		.call = parse_vc_action_raw_decap_index,
 		.comp = comp_set_raw_index,
 	},
+	[ACTION_COPY_ITEM] = {
+		.name = "copy_item",
+		.help = "copy data from dst to src item",
+		.priv = PRIV_ACTION(COPY_ITEM,
+			sizeof(struct rte_flow_action_copy_item)),
+		.next = NEXT(NEXT_ENTRY(ACTION_COPY_ITEM_DST_TYPE)),
+		.call = parse_vc,
+	},
+	[ACTION_COPY_ITEM_DST_TYPE] = {
+		.name = "dst_type",
+		.help = "destination item type",
+		.next = NEXT(NEXT_ENTRY(ACTION_COPY_ITEM_DST_INDEX),
+			NEXT_ENTRY(ACTION_COPY_ITEM_DST_TYPE_VALUE)),
+		.call = parse_vc_conf,
+	},
+	[ACTION_COPY_ITEM_DST_TYPE_VALUE] = {
+		.name = "{type}",
+		.help = "destination item type value",
+		.call = parse_vc_copy_item,
+		.comp = comp_set_copy_item,
+	},
+	[ACTION_COPY_ITEM_DST_INDEX] = {
+		.name = "dst_index",
+		.help = "destination item index",
+		.next = NEXT(NEXT_ENTRY(ACTION_COPY_ITEM_DST_OFFSET),
+			NEXT_ENTRY(UNSIGNED)),
+		.args = ARGS(ARGS_ENTRY(struct rte_flow_action_copy_item,
+					dst.index)),
+		.call = parse_vc_conf,
+	},
+	[ACTION_COPY_ITEM_DST_OFFSET] = {
+		.name = "dst_offset",
+		.help = "destination item offset",
+		.next = NEXT(NEXT_ENTRY(ACTION_COPY_ITEM_SRC_TYPE),
+			NEXT_ENTRY(UNSIGNED)),
+		.args = ARGS(ARGS_ENTRY(struct rte_flow_action_copy_item,
+					dst.offset)),
+		.call = parse_vc_conf,
+	},
+	[ACTION_COPY_ITEM_SRC_TYPE] = {
+		.name = "src_type",
+		.help = "source item type",
+		.next = NEXT(NEXT_ENTRY(ACTION_COPY_ITEM_SRC_INDEX),
+			NEXT_ENTRY(ACTION_COPY_ITEM_SRC_TYPE_VALUE)),
+		.call = parse_vc_conf,
+	},
+	[ACTION_COPY_ITEM_SRC_TYPE_VALUE] = {
+		.name = "{type}",
+		.help = "source item type value",
+		.call = parse_vc_copy_item,
+		.comp = comp_set_copy_item,
+	},
+	[ACTION_COPY_ITEM_SRC_INDEX] = {
+		.name = "src_index",
+		.help = "source item type index",
+		.next = NEXT(NEXT_ENTRY(ACTION_COPY_ITEM_SRC_OFFSET),
+			NEXT_ENTRY(UNSIGNED)),
+		.args = ARGS(ARGS_ENTRY(struct rte_flow_action_copy_item,
+					src.index)),
+		.call = parse_vc_conf,
+	},
+	[ACTION_COPY_ITEM_SRC_OFFSET] = {
+		.name = "src_offset",
+		.help = "source item type offset",
+		.next = NEXT(NEXT_ENTRY(ACTION_COPY_ITEM_WIDTH),
+			NEXT_ENTRY(UNSIGNED)),
+		.args = ARGS(ARGS_ENTRY(struct rte_flow_action_copy_item,
+					src.offset)),
+		.call = parse_vc_conf,
+	},
+	[ACTION_COPY_ITEM_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_copy_item,
+					width)),
+		.call = parse_vc_conf,
+	},
 	/* Top level command. */
 	[SET] = {
 		.name = "set",
@@ -5960,6 +6068,36 @@  parse_vc_action_sample_index(struct context *ctx, const struct token *token,
 	return len;
 }
 
+/** Parse tokens for copy_item command. */
+static int
+parse_vc_copy_item(struct context *ctx, const struct token *token,
+			 const char *str, unsigned int len, void *buf,
+			 unsigned int size)
+{
+	struct rte_flow_action_copy_item *action_copy_item;
+	unsigned int i;
+
+	(void)token;
+	(void)buf;
+	(void)size;
+	if (ctx->curr != ACTION_COPY_ITEM_DST_TYPE_VALUE &&
+		ctx->curr != ACTION_COPY_ITEM_SRC_TYPE_VALUE)
+		return -1;
+	for (i = 0; copy_item_table[i]; ++i)
+		if (!strcmp_partial(copy_item_table[i], str, len))
+			break;
+	if (!copy_item_table[i])
+		return -1;
+	if (!ctx->object)
+		return len;
+	action_copy_item = ctx->object;
+	if (ctx->curr == ACTION_COPY_ITEM_DST_TYPE_VALUE)
+		action_copy_item->dst.item = i;
+	else
+		action_copy_item->src.item = i;
+	return len;
+}
+
 /** Parse tokens for destroy command. */
 static int
 parse_destroy(struct context *ctx, const struct token *token,
@@ -7029,6 +7167,24 @@  comp_set_sample_index(struct context *ctx, const struct token *token,
 	return nb;
 }
 
+/** Complete item type for copy_item command. */
+static int
+comp_set_copy_item(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; copy_item_table[idx]; ++idx)
+		;
+	if (!buf)
+		return idx + 1;
+	if (ent < idx)
+		return strlcpy(buf, copy_item_table[ent], size);
+	return -1;
+}
+
 /** Internal context. */
 static struct context cmd_flow_context;