DPDK patches and discussions
 help / color / mirror / Atom feed
* [PATCH 0/2] ethdev: add RTE_FLOW_ITEM_TYPE_COMPARE
@ 2023-12-14  3:12 Suanming Mou
  2023-12-14  3:12 ` [PATCH 1/2] " Suanming Mou
                   ` (6 more replies)
  0 siblings, 7 replies; 66+ messages in thread
From: Suanming Mou @ 2023-12-14  3:12 UTC (permalink / raw)
  To: orika; +Cc: dev, rasland

The new item type is added for the case user wants to match traffic
based on packet field compare result with other fields or immediate
value.

e.g. take advantage the compare item user will be able to accumulate
a IPv4/TCP packet's TCP data_offset and IPv4 IHL field to a tag
register, then compare the tag register with IPv4 header total length
to understand the packet has payload or not.

The supported operations can be as below:
 - RTE_FLOW_ITEM_COMPARE_EQ (equal)
 - RTE_FLOW_ITEM_COMPARE_NE (not equal)
 - RTE_FLOW_ITEM_COMPARE_LT (less than)
 - RTE_FLOW_ITEM_COMPARE_LE (less than or equal)
 - RTE_FLOW_ITEM_COMPARE_GT (great than)
 - RTE_FLOW_ITEM_COMPARE_GE (great than or equal)

As the two struct ``rte_flow_action_modify_data`` and
``rte_flow_field_data`` share the same information, the struct
``rte_flow_action_modify_data`` will be converge to the name more
generic struct ``rte_flow_field_data`` in next release as well.

Suanming Mou (2):
  ethdev: add RTE_FLOW_ITEM_TYPE_COMPARE
  net/mlx5: add compare item support

 app/test-pmd/cmdline_flow.c                 | 416 +++++++++++++++++++-
 doc/guides/nics/features/default.ini        |   1 +
 doc/guides/nics/features/mlx5.ini           |   1 +
 doc/guides/nics/mlx5.rst                    |   7 +
 doc/guides/prog_guide/rte_flow.rst          |   7 +
 doc/guides/rel_notes/release_24_03.rst      |   7 +-
 doc/guides/testpmd_app_ug/testpmd_funcs.rst |   6 +
 drivers/net/mlx5/mlx5_flow.h                |   3 +
 drivers/net/mlx5/mlx5_flow_hw.c             |  73 ++++
 lib/ethdev/rte_flow.c                       |   1 +
 lib/ethdev/rte_flow.h                       | 230 ++++++++---
 11 files changed, 690 insertions(+), 62 deletions(-)

-- 
2.34.1


^ permalink raw reply	[flat|nested] 66+ messages in thread

* [PATCH 1/2] ethdev: add RTE_FLOW_ITEM_TYPE_COMPARE
  2023-12-14  3:12 [PATCH 0/2] ethdev: add RTE_FLOW_ITEM_TYPE_COMPARE Suanming Mou
@ 2023-12-14  3:12 ` Suanming Mou
  2023-12-14  3:12 ` [PATCH 2/2] net/mlx5: add compare item support Suanming Mou
                   ` (5 subsequent siblings)
  6 siblings, 0 replies; 66+ messages in thread
From: Suanming Mou @ 2023-12-14  3:12 UTC (permalink / raw)
  To: orika, Aman Singh, Yuying Zhang, Thomas Monjalon, Ferruh Yigit,
	Andrew Rybchenko
  Cc: dev, rasland

The new item type is added for the case user wants to match traffic
based on packet field compare result with other fields or immediate
value.

e.g. take advantage the compare item user will be able to accumulate
a IPv4/TCP packet's TCP data_offset and IPv4 IHL field to a tag
register, then compare the tag register with IPv4 header total length
to understand the packet has payload or not.

The supported operations can be as below:
 - RTE_FLOW_ITEM_COMPARE_EQ (equal)
 - RTE_FLOW_ITEM_COMPARE_NE (not equal)
 - RTE_FLOW_ITEM_COMPARE_LT (less than)
 - RTE_FLOW_ITEM_COMPARE_LE (less than or equal)
 - RTE_FLOW_ITEM_COMPARE_GT (great than)
 - RTE_FLOW_ITEM_COMPARE_GE (great than or equal)

As the two struct ``rte_flow_action_modify_data`` and
``rte_flow_field_data`` share the same information, the struct
``rte_flow_action_modify_data`` will be converge to the name more
generic struct ``rte_flow_field_data`` in next release as well.

Signed-off-by: Suanming Mou <suanmingm@nvidia.com>
---
 app/test-pmd/cmdline_flow.c                 | 416 +++++++++++++++++++-
 doc/guides/nics/features/default.ini        |   1 +
 doc/guides/prog_guide/rte_flow.rst          |   7 +
 doc/guides/rel_notes/release_24_03.rst      |   5 +
 doc/guides/testpmd_app_ug/testpmd_funcs.rst |   6 +
 lib/ethdev/rte_flow.c                       |   1 +
 lib/ethdev/rte_flow.h                       | 230 ++++++++---
 7 files changed, 605 insertions(+), 61 deletions(-)

diff --git a/app/test-pmd/cmdline_flow.c b/app/test-pmd/cmdline_flow.c
index ce71818705..4f448ff8ec 100644
--- a/app/test-pmd/cmdline_flow.c
+++ b/app/test-pmd/cmdline_flow.c
@@ -543,6 +543,28 @@ enum index {
 	ITEM_PTYPE,
 	ITEM_PTYPE_VALUE,
 	ITEM_NSH,
+	ITEM_COMPARE,
+	ITEM_COMPARE_OP,
+	ITEM_COMPARE_OP_VALUE,
+	ITEM_COMPARE_FIELD_A_TYPE,
+	ITEM_COMPARE_FIELD_A_TYPE_VALUE,
+	ITEM_COMPARE_FIELD_A_LEVEL,
+	ITEM_COMPARE_FIELD_A_LEVEL_VALUE,
+	ITEM_COMPARE_FIELD_A_TAG_INDEX,
+	ITEM_COMPARE_FIELD_A_TYPE_ID,
+	ITEM_COMPARE_FIELD_A_CLASS_ID,
+	ITEM_COMPARE_FIELD_A_OFFSET,
+	ITEM_COMPARE_FIELD_B_TYPE,
+	ITEM_COMPARE_FIELD_B_TYPE_VALUE,
+	ITEM_COMPARE_FIELD_B_LEVEL,
+	ITEM_COMPARE_FIELD_B_LEVEL_VALUE,
+	ITEM_COMPARE_FIELD_B_TAG_INDEX,
+	ITEM_COMPARE_FIELD_B_TYPE_ID,
+	ITEM_COMPARE_FIELD_B_CLASS_ID,
+	ITEM_COMPARE_FIELD_B_OFFSET,
+	ITEM_COMPARE_FIELD_B_VALUE,
+	ITEM_COMPARE_FIELD_B_POINTER,
+	ITEM_COMPARE_FIELD_WIDTH,
 
 	/* Validate/create actions. */
 	ACTIONS,
@@ -740,13 +762,17 @@ enum index {
 #define ITEM_RAW_SIZE \
 	(sizeof(struct rte_flow_item_raw) + ITEM_RAW_PATTERN_SIZE)
 
-/** Maximum size for external pattern in struct rte_flow_action_modify_data. */
-#define ACTION_MODIFY_PATTERN_SIZE 32
+static const char *const compare_ops[] = {
+	"eq", "ne", "lt", "le", "gt", "ge", NULL
+};
+
+/** Maximum size for external pattern in struct rte_flow_field_data. */
+#define FLOW_FIELD_PATTERN_SIZE 32
 
 /** Storage size for struct rte_flow_action_modify_field including pattern. */
 #define ACTION_MODIFY_SIZE \
 	(sizeof(struct rte_flow_action_modify_field) + \
-	ACTION_MODIFY_PATTERN_SIZE)
+	FLOW_FIELD_PATTERN_SIZE)
 
 /** Maximum number of queue indices in struct rte_flow_action_rss. */
 #define ACTION_RSS_QUEUE_NUM 128
@@ -940,7 +966,7 @@ static const char *const modify_field_ops[] = {
 	"set", "add", "sub", NULL
 };
 
-static const char *const modify_field_ids[] = {
+static const char *const flow_field_ids[] = {
 	"start", "mac_dst", "mac_src",
 	"vlan_type", "vlan_id", "mac_type",
 	"ipv4_dscp", "ipv4_ttl", "ipv4_src", "ipv4_dst",
@@ -1590,6 +1616,7 @@ static const enum index next_item[] = {
 	ITEM_IB_BTH,
 	ITEM_PTYPE,
 	ITEM_NSH,
+	ITEM_COMPARE,
 	END_SET,
 	ZERO,
 };
@@ -2121,6 +2148,38 @@ static const enum index item_nsh[] = {
 	ZERO,
 };
 
+static const enum index item_compare_field[] = {
+	ITEM_COMPARE_OP,
+	ITEM_COMPARE_FIELD_A_TYPE,
+	ITEM_COMPARE_FIELD_B_TYPE,
+	ITEM_NEXT,
+	ZERO,
+};
+
+static const enum index compare_field_a[] = {
+	ITEM_COMPARE_FIELD_A_TYPE,
+	ITEM_COMPARE_FIELD_A_LEVEL,
+	ITEM_COMPARE_FIELD_A_TAG_INDEX,
+	ITEM_COMPARE_FIELD_A_TYPE_ID,
+	ITEM_COMPARE_FIELD_A_CLASS_ID,
+	ITEM_COMPARE_FIELD_A_OFFSET,
+	ITEM_COMPARE_FIELD_B_TYPE,
+	ZERO,
+};
+
+static const enum index compare_field_b[] = {
+	ITEM_COMPARE_FIELD_B_TYPE,
+	ITEM_COMPARE_FIELD_B_LEVEL,
+	ITEM_COMPARE_FIELD_B_TAG_INDEX,
+	ITEM_COMPARE_FIELD_B_TYPE_ID,
+	ITEM_COMPARE_FIELD_B_CLASS_ID,
+	ITEM_COMPARE_FIELD_B_OFFSET,
+	ITEM_COMPARE_FIELD_B_VALUE,
+	ITEM_COMPARE_FIELD_B_POINTER,
+	ITEM_COMPARE_FIELD_WIDTH,
+	ZERO,
+};
+
 static const enum index next_action[] = {
 	ACTION_END,
 	ACTION_VOID,
@@ -2863,6 +2922,24 @@ comp_quota_update_name(struct context *ctx, const struct token *token,
 static int
 comp_qu_mode_name(struct context *ctx, const struct token *token,
 		  unsigned int ent, char *buf, unsigned int size);
+static int
+comp_set_compare_field_id(struct context *ctx, const struct token *token,
+			  unsigned int ent, char *buf, unsigned int size);
+static int
+comp_set_compare_op(struct context *ctx, const struct token *token,
+		    unsigned int ent, char *buf, unsigned int size);
+static int
+parse_vc_compare_op(struct context *ctx, const struct token *token,
+			 const char *str, unsigned int len, void *buf,
+			 unsigned int size);
+static int
+parse_vc_compare_field_id(struct context *ctx, const struct token *token,
+			  const char *str, unsigned int len, void *buf,
+			  unsigned int size);
+static int
+parse_vc_compare_field_level(struct context *ctx, const struct token *token,
+			     const char *str, unsigned int len, void *buf,
+			     unsigned int size);
 
 struct indlst_conf {
 	uint32_t id;
@@ -5982,6 +6059,174 @@ static const struct token token_list[] = {
 		.next = NEXT(item_nsh),
 		.call = parse_vc,
 	},
+	[ITEM_COMPARE] = {
+		.name = "compare",
+		.help = "match with the comparison result",
+		.priv = PRIV_ITEM(COMPARE, sizeof(struct rte_flow_item_compare)),
+		.next = NEXT(NEXT_ENTRY(ITEM_COMPARE_OP)),
+		.call = parse_vc,
+	},
+	[ITEM_COMPARE_OP] = {
+		.name = "op",
+		.help = "operation type",
+		.next = NEXT(item_compare_field,
+			NEXT_ENTRY(ITEM_COMPARE_OP_VALUE), item_param),
+		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_compare, operation)),
+	},
+	[ITEM_COMPARE_OP_VALUE] = {
+		.name = "{operation}",
+		.help = "operation type value",
+		.call = parse_vc_compare_op,
+		.comp = comp_set_compare_op,
+	},
+	[ITEM_COMPARE_FIELD_A_TYPE] = {
+		.name = "a_type",
+		.help = "compared field type",
+		.next = NEXT(compare_field_a,
+			NEXT_ENTRY(ITEM_COMPARE_FIELD_A_TYPE_VALUE), item_param),
+		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_compare, a.field)),
+	},
+	[ITEM_COMPARE_FIELD_A_TYPE_VALUE] = {
+		.name = "{a_type}",
+		.help = "compared field type value",
+		.call = parse_vc_compare_field_id,
+		.comp = comp_set_compare_field_id,
+	},
+	[ITEM_COMPARE_FIELD_A_LEVEL] = {
+		.name = "a_level",
+		.help = "compared field level",
+		.next = NEXT(compare_field_a,
+			     NEXT_ENTRY(ITEM_COMPARE_FIELD_A_LEVEL_VALUE), item_param),
+		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_compare, a.level)),
+	},
+	[ITEM_COMPARE_FIELD_A_LEVEL_VALUE] = {
+		.name = "{a_level}",
+		.help = "compared field level value",
+		.call = parse_vc_compare_field_level,
+		.comp = comp_none,
+	},
+	[ITEM_COMPARE_FIELD_A_TAG_INDEX] = {
+		.name = "a_tag_index",
+		.help = "compared field tag array",
+		.next = NEXT(compare_field_a,
+			     NEXT_ENTRY(COMMON_UNSIGNED), item_param),
+		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_compare,
+					a.tag_index)),
+	},
+	[ITEM_COMPARE_FIELD_A_TYPE_ID] = {
+		.name = "a_type_id",
+		.help = "compared field type ID",
+		.next = NEXT(compare_field_a,
+			     NEXT_ENTRY(COMMON_UNSIGNED), item_param),
+		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_compare,
+					a.type)),
+	},
+	[ITEM_COMPARE_FIELD_A_CLASS_ID] = {
+		.name = "a_class",
+		.help = "compared field class ID",
+		.next = NEXT(compare_field_a,
+			     NEXT_ENTRY(COMMON_UNSIGNED), item_param),
+		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_compare,
+					     a.class_id)),
+	},
+	[ITEM_COMPARE_FIELD_A_OFFSET] = {
+		.name = "a_offset",
+		.help = "compared field bit offset",
+		.next = NEXT(compare_field_a,
+			     NEXT_ENTRY(COMMON_UNSIGNED), item_param),
+		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_compare,
+					a.offset)),
+	},
+	[ITEM_COMPARE_FIELD_B_TYPE] = {
+		.name = "b_type",
+		.help = "comparator field type",
+		.next = NEXT(compare_field_b,
+			NEXT_ENTRY(ITEM_COMPARE_FIELD_B_TYPE_VALUE), item_param),
+		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_compare,
+					b.field)),
+	},
+	[ITEM_COMPARE_FIELD_B_TYPE_VALUE] = {
+		.name = "{b_type}",
+		.help = "comparator field type value",
+		.call = parse_vc_compare_field_id,
+		.comp = comp_set_compare_field_id,
+	},
+	[ITEM_COMPARE_FIELD_B_LEVEL] = {
+		.name = "b_level",
+		.help = "comparator field level",
+		.next = NEXT(compare_field_b,
+			     NEXT_ENTRY(ITEM_COMPARE_FIELD_B_LEVEL_VALUE), item_param),
+		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_compare,
+					b.level)),
+	},
+	[ITEM_COMPARE_FIELD_B_LEVEL_VALUE] = {
+		.name = "{b_level}",
+		.help = "comparator field level value",
+		.call = parse_vc_compare_field_level,
+		.comp = comp_none,
+	},
+	[ITEM_COMPARE_FIELD_B_TAG_INDEX] = {
+		.name = "b_tag_index",
+		.help = "comparator field tag array",
+		.next = NEXT(compare_field_b,
+			     NEXT_ENTRY(COMMON_UNSIGNED), item_param),
+		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_compare,
+					b.tag_index)),
+	},
+	[ITEM_COMPARE_FIELD_B_TYPE_ID] = {
+		.name = "b_type_id",
+		.help = "comparator field type ID",
+		.next = NEXT(compare_field_b,
+			     NEXT_ENTRY(COMMON_UNSIGNED), item_param),
+		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_compare,
+					b.type)),
+	},
+	[ITEM_COMPARE_FIELD_B_CLASS_ID] = {
+		.name = "b_class",
+		.help = "comparator field class ID",
+		.next = NEXT(compare_field_b,
+			     NEXT_ENTRY(COMMON_UNSIGNED), item_param),
+		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_compare,
+					     b.class_id)),
+	},
+	[ITEM_COMPARE_FIELD_B_OFFSET] = {
+		.name = "b_offset",
+		.help = "comparator field bit offset",
+		.next = NEXT(compare_field_b,
+			     NEXT_ENTRY(COMMON_UNSIGNED), item_param),
+		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_compare,
+					b.offset)),
+	},
+	[ITEM_COMPARE_FIELD_B_VALUE] = {
+		.name = "b_value",
+		.help = "comparator immediate value",
+		.next = NEXT(compare_field_b,
+			     NEXT_ENTRY(COMMON_HEX), item_param),
+		.args = ARGS(ARGS_ENTRY_ARB(0, 0),
+			     ARGS_ENTRY_ARB(0, 0),
+			     ARGS_ENTRY(struct rte_flow_item_compare,
+					b.value)),
+	},
+	[ITEM_COMPARE_FIELD_B_POINTER] = {
+		.name = "b_ptr",
+		.help = "pointer to comparator immediate value",
+		.next = NEXT(compare_field_b,
+			     NEXT_ENTRY(COMMON_HEX), item_param),
+		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_compare,
+					b.pvalue),
+			     ARGS_ENTRY_ARB(0, 0),
+			     ARGS_ENTRY_ARB
+				(sizeof(struct rte_flow_item_compare),
+				 FLOW_FIELD_PATTERN_SIZE)),
+	},
+	[ITEM_COMPARE_FIELD_WIDTH] = {
+		.name = "width",
+		.help = "number of bits to compare",
+		.next = NEXT(item_compare_field,
+			NEXT_ENTRY(COMMON_UNSIGNED), item_param),
+		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_compare,
+					width)),
+	},
 
 	/* Validate/create actions. */
 	[ACTIONS] = {
@@ -6961,7 +7206,7 @@ static const struct token token_list[] = {
 			     ARGS_ENTRY_ARB(0, 0),
 			     ARGS_ENTRY_ARB
 				(sizeof(struct rte_flow_action_modify_field),
-				 ACTION_MODIFY_PATTERN_SIZE)),
+				 FLOW_FIELD_PATTERN_SIZE)),
 		.call = parse_vc_conf,
 	},
 	[ACTION_MODIFY_FIELD_WIDTH] = {
@@ -8404,6 +8649,122 @@ parse_vc_item_l2tpv2_type(struct context *ctx, const struct token *token,
 	return len;
 }
 
+/** Parse operation for compare match item. */
+static int
+parse_vc_compare_op(struct context *ctx, const struct token *token,
+			 const char *str, unsigned int len, void *buf,
+			 unsigned int size)
+{
+	struct rte_flow_item_compare *compare_item;
+	unsigned int i;
+
+	(void)token;
+	(void)buf;
+	(void)size;
+	if (ctx->curr != ITEM_COMPARE_OP_VALUE)
+		return -1;
+	for (i = 0; compare_ops[i]; ++i)
+		if (!strcmp_partial(compare_ops[i], str, len))
+			break;
+	if (!compare_ops[i])
+		return -1;
+	if (!ctx->object)
+		return len;
+	compare_item = ctx->object;
+	compare_item->operation = (enum rte_flow_item_compare_op)i;
+	return len;
+}
+
+/** Parse id for compare match item. */
+static int
+parse_vc_compare_field_id(struct context *ctx, const struct token *token,
+			  const char *str, unsigned int len, void *buf,
+			  unsigned int size)
+{
+	struct rte_flow_item_compare *compare_item;
+	unsigned int i;
+
+	(void)token;
+	(void)buf;
+	(void)size;
+	if (ctx->curr != ITEM_COMPARE_FIELD_A_TYPE_VALUE &&
+		ctx->curr != ITEM_COMPARE_FIELD_B_TYPE_VALUE)
+		return -1;
+	for (i = 0; flow_field_ids[i]; ++i)
+		if (!strcmp_partial(flow_field_ids[i], str, len))
+			break;
+	if (!flow_field_ids[i])
+		return -1;
+	if (!ctx->object)
+		return len;
+	compare_item = ctx->object;
+	if (ctx->curr == ITEM_COMPARE_FIELD_A_TYPE_VALUE)
+		compare_item->a.field = (enum rte_flow_field_id)i;
+	else
+		compare_item->b.field = (enum rte_flow_field_id)i;
+	return len;
+}
+
+/** Parse level for compare match item. */
+static int
+parse_vc_compare_field_level(struct context *ctx, const struct token *token,
+			     const char *str, unsigned int len, void *buf,
+			     unsigned int size)
+{
+	struct rte_flow_item_compare *compare_item;
+	struct flex_item *fp = NULL;
+	uint32_t val;
+	struct buffer *out = buf;
+	char *end;
+
+	(void)token;
+	(void)size;
+	if (ctx->curr != ITEM_COMPARE_FIELD_A_LEVEL_VALUE &&
+		ctx->curr != ITEM_COMPARE_FIELD_B_LEVEL_VALUE)
+		return -1;
+	if (!ctx->object)
+		return len;
+	compare_item = ctx->object;
+	errno = 0;
+	val = strtoumax(str, &end, 0);
+	if (errno || (size_t)(end - str) != len)
+		return -1;
+	/* No need to validate action template mask value */
+	if (out->args.vc.masks) {
+		if (ctx->curr == ITEM_COMPARE_FIELD_A_LEVEL_VALUE)
+			compare_item->a.level = val;
+		else
+			compare_item->b.level = val;
+		return len;
+	}
+	if ((ctx->curr == ITEM_COMPARE_FIELD_A_LEVEL_VALUE &&
+		compare_item->a.field == RTE_FLOW_FIELD_FLEX_ITEM) ||
+		(ctx->curr == ITEM_COMPARE_FIELD_B_LEVEL_VALUE &&
+		compare_item->b.field == RTE_FLOW_FIELD_FLEX_ITEM)) {
+		if (val >= FLEX_MAX_PARSERS_NUM) {
+			printf("Bad flex item handle\n");
+			return -1;
+		}
+		fp = flex_items[ctx->port][val];
+		if (!fp) {
+			printf("Bad flex item handle\n");
+			return -1;
+		}
+	}
+	if (ctx->curr == ITEM_COMPARE_FIELD_A_LEVEL_VALUE) {
+		if (compare_item->a.field != RTE_FLOW_FIELD_FLEX_ITEM)
+			compare_item->a.level = val;
+		else
+			compare_item->a.flex_handle = fp->flex_handle;
+	} else if (ctx->curr == ITEM_COMPARE_FIELD_B_LEVEL_VALUE) {
+		if (compare_item->b.field != RTE_FLOW_FIELD_FLEX_ITEM)
+			compare_item->b.level = val;
+		else
+			compare_item->b.flex_handle = fp->flex_handle;
+	}
+	return len;
+}
+
 /** Parse meter color action type. */
 static int
 parse_vc_action_meter_color_type(struct context *ctx, const struct token *token,
@@ -9773,10 +10134,10 @@ parse_vc_modify_field_id(struct context *ctx, const struct token *token,
 	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))
+	for (i = 0; flow_field_ids[i]; ++i)
+		if (!strcmp_partial(flow_field_ids[i], str, len))
 			break;
-	if (!modify_field_ids[i])
+	if (!flow_field_ids[i])
 		return -1;
 	if (!ctx->object)
 		return len;
@@ -11890,6 +12251,39 @@ comp_rule_id(struct context *ctx, const struct token *token,
 	return i;
 }
 
+/** Complete operation for compare match item. */
+static int
+comp_set_compare_op(struct context *ctx, const struct token *token,
+		    unsigned int ent, char *buf, unsigned int size)
+{
+	RTE_SET_USED(ctx);
+	RTE_SET_USED(token);
+	if (!buf)
+		return RTE_DIM(compare_ops);
+	if (ent < RTE_DIM(compare_ops) - 1)
+		return strlcpy(buf, compare_ops[ent], size);
+	return -1;
+}
+
+/** Complete field id for compare match item. */
+static int
+comp_set_compare_field_id(struct context *ctx, const struct token *token,
+			  unsigned int ent, char *buf, unsigned int size)
+{
+	const char *name;
+
+	RTE_SET_USED(token);
+	if (!buf)
+		return RTE_DIM(flow_field_ids);
+	if (ent >= RTE_DIM(flow_field_ids) - 1)
+		return -1;
+	name = flow_field_ids[ent];
+	if (ctx->curr == ITEM_COMPARE_FIELD_B_TYPE ||
+	    (strcmp(name, "pointer") && strcmp(name, "value")))
+		return strlcpy(buf, name, size);
+	return -1;
+}
+
 /** Complete type field for RSS action. */
 static int
 comp_vc_action_rss_type(struct context *ctx, const struct token *token,
@@ -12003,10 +12397,10 @@ comp_set_modify_field_id(struct context *ctx, const struct token *token,
 
 	RTE_SET_USED(token);
 	if (!buf)
-		return RTE_DIM(modify_field_ids);
-	if (ent >= RTE_DIM(modify_field_ids) - 1)
+		return RTE_DIM(flow_field_ids);
+	if (ent >= RTE_DIM(flow_field_ids) - 1)
 		return -1;
-	name = modify_field_ids[ent];
+	name = flow_field_ids[ent];
 	if (ctx->curr == ACTION_MODIFY_FIELD_SRC_TYPE ||
 	    (strcmp(name, "pointer") && strcmp(name, "value")))
 		return strlcpy(buf, name, size);
diff --git a/doc/guides/nics/features/default.ini b/doc/guides/nics/features/default.ini
index 806cb033ff..565338731f 100644
--- a/doc/guides/nics/features/default.ini
+++ b/doc/guides/nics/features/default.ini
@@ -87,6 +87,7 @@ aggr_affinity        =
 ah                   =
 any                  =
 arp_eth_ipv4         =
+compare              =
 conntrack            =
 ecpri                =
 esp                  =
diff --git a/doc/guides/prog_guide/rte_flow.rst b/doc/guides/prog_guide/rte_flow.rst
index 627b845bfb..5afdd1dc0c 100644
--- a/doc/guides/prog_guide/rte_flow.rst
+++ b/doc/guides/prog_guide/rte_flow.rst
@@ -1573,6 +1573,13 @@ Matches the packet type as defined in rte_mbuf_ptype.
 
 - ``packet_type``: L2/L3/L4 and tunnel information.
 
+Item: ``COMPARE``
+^^^^^^^^^^^^^^^^^
+
+Matches the comparison result between packet fields or value.
+
+- ``compare``: Comparison information.
+
 Actions
 ~~~~~~~
 
diff --git a/doc/guides/rel_notes/release_24_03.rst b/doc/guides/rel_notes/release_24_03.rst
index 2c0e2930cc..71ebd67dbd 100644
--- a/doc/guides/rel_notes/release_24_03.rst
+++ b/doc/guides/rel_notes/release_24_03.rst
@@ -55,6 +55,11 @@ New Features
      Also, make sure to start the actual text at the margin.
      =======================================================
 
+* **Added compare flow matching criteria.**
+
+  Added ``RTE_FLOW_ITEM_TYPE_COMPARE`` to allow matching on compare
+  result between the packet fields or value.
+
 * **Updated NVIDIA mlx5 driver.**
 
   * Added support for accumulating from src field to dst field.
diff --git a/doc/guides/testpmd_app_ug/testpmd_funcs.rst b/doc/guides/testpmd_app_ug/testpmd_funcs.rst
index 447e28e694..220b396295 100644
--- a/doc/guides/testpmd_app_ug/testpmd_funcs.rst
+++ b/doc/guides/testpmd_app_ug/testpmd_funcs.rst
@@ -3841,6 +3841,12 @@ This section lists supported pattern items and their attributes, if any.
 
         - ``packet_type {unsigned}``: packet type.
 
+- ``compare``: match the comparison result between packet fields or value.
+
+        - ``op {string}``: comparison operation type.
+        - ``a_type {string}``: compared field.
+        - ``b_type {string}``: comparator field.
+        - ``width {unsigned}``: comparison width.
 
 Actions list
 ^^^^^^^^^^^^
diff --git a/lib/ethdev/rte_flow.c b/lib/ethdev/rte_flow.c
index 549e329558..88cf003b2b 100644
--- a/lib/ethdev/rte_flow.c
+++ b/lib/ethdev/rte_flow.c
@@ -167,6 +167,7 @@ static const struct rte_flow_desc_data rte_flow_desc_item[] = {
 	MK_FLOW_ITEM(TX_QUEUE, sizeof(struct rte_flow_item_tx_queue)),
 	MK_FLOW_ITEM(IB_BTH, sizeof(struct rte_flow_item_ib_bth)),
 	MK_FLOW_ITEM(PTYPE, sizeof(struct rte_flow_item_ptype)),
+	MK_FLOW_ITEM(COMPARE, sizeof(struct rte_flow_item_compare)),
 };
 
 /** Generate flow_action[] entry. */
diff --git a/lib/ethdev/rte_flow.h b/lib/ethdev/rte_flow.h
index affdc8121b..59ef6394e7 100644
--- a/lib/ethdev/rte_flow.h
+++ b/lib/ethdev/rte_flow.h
@@ -704,6 +704,13 @@ enum rte_flow_item_type {
 	 *
 	 */
 	RTE_FLOW_ITEM_TYPE_PTYPE,
+
+	/**
+	 * Matches the packet with compare result.
+	 *
+	 * See struct rte_flow_item_compare.
+	 */
+	RTE_FLOW_ITEM_TYPE_COMPARE,
 };
 
 /**
@@ -2336,6 +2343,177 @@ static const struct rte_flow_item_ptype rte_flow_item_ptype_mask = {
 };
 #endif
 
+/**
+ * Field IDs for packet field.
+ */
+enum rte_flow_field_id {
+	RTE_FLOW_FIELD_START = 0,	/**< Start of a packet. */
+	RTE_FLOW_FIELD_MAC_DST,		/**< Destination MAC Address. */
+	RTE_FLOW_FIELD_MAC_SRC,		/**< Source MAC Address. */
+	RTE_FLOW_FIELD_VLAN_TYPE,	/**< VLAN Tag Identifier. */
+	RTE_FLOW_FIELD_VLAN_ID,		/**< VLAN Identifier. */
+	RTE_FLOW_FIELD_MAC_TYPE,	/**< EtherType. */
+	RTE_FLOW_FIELD_IPV4_DSCP,	/**< IPv4 DSCP. */
+	RTE_FLOW_FIELD_IPV4_TTL,	/**< IPv4 Time To Live. */
+	RTE_FLOW_FIELD_IPV4_SRC,	/**< IPv4 Source Address. */
+	RTE_FLOW_FIELD_IPV4_DST,	/**< IPv4 Destination Address. */
+	RTE_FLOW_FIELD_IPV6_DSCP,	/**< IPv6 DSCP. */
+	RTE_FLOW_FIELD_IPV6_HOPLIMIT,	/**< IPv6 Hop Limit. */
+	RTE_FLOW_FIELD_IPV6_SRC,	/**< IPv6 Source Address. */
+	RTE_FLOW_FIELD_IPV6_DST,	/**< IPv6 Destination Address. */
+	RTE_FLOW_FIELD_TCP_PORT_SRC,	/**< TCP Source Port Number. */
+	RTE_FLOW_FIELD_TCP_PORT_DST,	/**< TCP Destination Port Number. */
+	RTE_FLOW_FIELD_TCP_SEQ_NUM,	/**< TCP Sequence Number. */
+	RTE_FLOW_FIELD_TCP_ACK_NUM,	/**< TCP Acknowledgment Number. */
+	RTE_FLOW_FIELD_TCP_FLAGS,	/**< TCP Flags. */
+	RTE_FLOW_FIELD_UDP_PORT_SRC,	/**< UDP Source Port Number. */
+	RTE_FLOW_FIELD_UDP_PORT_DST,	/**< UDP Destination Port Number. */
+	RTE_FLOW_FIELD_VXLAN_VNI,	/**< VXLAN Network Identifier. */
+	RTE_FLOW_FIELD_GENEVE_VNI,	/**< GENEVE Network Identifier. */
+	RTE_FLOW_FIELD_GTP_TEID,	/**< GTP Tunnel Endpoint Identifier. */
+	RTE_FLOW_FIELD_TAG,		/**< Tag value. */
+	RTE_FLOW_FIELD_MARK,		/**< Mark value. */
+	RTE_FLOW_FIELD_META,		/**< Metadata value. */
+	RTE_FLOW_FIELD_POINTER,		/**< Memory pointer. */
+	RTE_FLOW_FIELD_VALUE,		/**< Immediate value. */
+	RTE_FLOW_FIELD_IPV4_ECN,	/**< IPv4 ECN. */
+	RTE_FLOW_FIELD_IPV6_ECN,	/**< IPv6 ECN. */
+	RTE_FLOW_FIELD_GTP_PSC_QFI,	/**< GTP QFI. */
+	RTE_FLOW_FIELD_METER_COLOR,	/**< Meter color marker. */
+	RTE_FLOW_FIELD_IPV6_PROTO,	/**< IPv6 next header. */
+	RTE_FLOW_FIELD_FLEX_ITEM,	/**< Flex item. */
+	RTE_FLOW_FIELD_HASH_RESULT,	/**< Hash result. */
+	RTE_FLOW_FIELD_GENEVE_OPT_TYPE,	/**< GENEVE option type. */
+	RTE_FLOW_FIELD_GENEVE_OPT_CLASS,/**< GENEVE option class. */
+	RTE_FLOW_FIELD_GENEVE_OPT_DATA,	/**< GENEVE option data. */
+	RTE_FLOW_FIELD_MPLS,		/**< MPLS header. */
+	RTE_FLOW_FIELD_TCP_DATA_OFFSET,	/**< TCP data offset. */
+	RTE_FLOW_FIELD_IPV4_IHL,	/**< IPv4 IHL. */
+	RTE_FLOW_FIELD_IPV4_TOTAL_LEN,	/**< IPv4 total length. */
+	RTE_FLOW_FIELD_IPV6_PAYLOAD_LEN	/**< IPv6 payload length. */
+};
+
+/**
+ * @warning
+ * @b EXPERIMENTAL: this structure may change without prior notice
+ *
+ * Field description for packet field.
+ */
+struct rte_flow_field_data {
+	enum rte_flow_field_id field; /**< Field or memory type ID. */
+	union {
+		struct {
+			/** Encapsulation level and tag index or flex item handle. */
+			union {
+				struct {
+					/**
+					 * Packet encapsulation level containing
+					 * the field related with.
+					 *
+					 * - @p 0 requests the default behavior.
+					 *   Depending on the packet type, it
+					 *   can mean outermost, innermost or
+					 *   anything in between.
+					 *
+					 *   It basically stands for the
+					 *   innermost encapsulation level.
+					 *   Modification can be performed
+					 *   according to PMD and device
+					 *   capabilities.
+					 *
+					 * - @p 1 requests modification to be
+					 *   performed on the outermost packet
+					 *   encapsulation level.
+					 *
+					 * - @p 2 and subsequent values request
+					 *   modification to be performed on
+					 *   the specified inner packet
+					 *   encapsulation level, from
+					 *   outermost to innermost (lower to
+					 *   higher values).
+					 *
+					 * Values other than @p 0 are not
+					 * necessarily supported.
+					 *
+					 * @note that for MPLS field,
+					 * encapsulation level also include
+					 * tunnel since MPLS may appear in
+					 * outer, inner or tunnel.
+					 */
+					uint8_t level;
+					union {
+						/**
+						 * Tag index array inside
+						 * encapsulation level.
+						 * Used for VLAN, MPLS or TAG types.
+						 */
+						uint8_t tag_index;
+						/**
+						 * Geneve option identifier.
+						 * Relevant only for
+						 * RTE_FLOW_FIELD_GENEVE_OPT_XXXX
+						 * type.
+						 */
+						struct {
+							/**
+							 * Geneve option type.
+							 */
+							uint8_t type;
+							/**
+							 * Geneve option class.
+							 */
+							rte_be16_t class_id;
+						};
+					};
+				};
+				struct rte_flow_item_flex_handle *flex_handle;
+			};
+			/** Number of bits to skip from a field. */
+			uint32_t offset;
+		};
+		/**
+		 * Immediate value for RTE_FLOW_FIELD_VALUE, presented in the
+		 * same byte order and length as in relevant rte_flow_item_xxx.
+		 * The immediate source bitfield offset is inherited from
+		 * the destination's one.
+		 */
+		uint8_t value[16];
+		/**
+		 * Memory address for RTE_FLOW_FIELD_POINTER, memory layout
+		 * should be the same as for relevant field in the
+		 * rte_flow_item_xxx structure.
+		 */
+		void *pvalue;
+	};
+};
+
+/**
+ * Expected operation types for compare item.
+ */
+enum rte_flow_item_compare_op {
+	RTE_FLOW_ITEM_COMPARE_EQ,	/* Compare result equal. */
+	RTE_FLOW_ITEM_COMPARE_NE,	/* Compare result not equal. */
+	RTE_FLOW_ITEM_COMPARE_LT,	/* Compare result less than. */
+	RTE_FLOW_ITEM_COMPARE_LE,	/* Compare result less than or equal. */
+	RTE_FLOW_ITEM_COMPARE_GT,	/* Compare result great than. */
+	RTE_FLOW_ITEM_COMPARE_GE,	/* Compare result great than or equal. */
+};
+
+/**
+ *
+ * RTE_FLOW_ITEM_TYPE_COMPARE
+ *
+ * Matches the packet with compare result.
+ *
+ * The operation means a compare with b result.
+ */
+struct rte_flow_item_compare {
+	enum rte_flow_item_compare_op operation; /* The compare operation. */
+	struct rte_flow_field_data a;		 /* Field be compared.  */
+	struct rte_flow_field_data b;		 /* Field as comparator. */
+	uint32_t width;				 /* Compare width. */
+};
+
 /**
  * Action types.
  *
@@ -3857,56 +4035,8 @@ struct rte_flow_action_ethdev {
 };
 
 /**
- * Field IDs for MODIFY_FIELD action.
- */
-enum rte_flow_field_id {
-	RTE_FLOW_FIELD_START = 0,	/**< Start of a packet. */
-	RTE_FLOW_FIELD_MAC_DST,		/**< Destination MAC Address. */
-	RTE_FLOW_FIELD_MAC_SRC,		/**< Source MAC Address. */
-	RTE_FLOW_FIELD_VLAN_TYPE,	/**< VLAN Tag Identifier. */
-	RTE_FLOW_FIELD_VLAN_ID,		/**< VLAN Identifier. */
-	RTE_FLOW_FIELD_MAC_TYPE,	/**< EtherType. */
-	RTE_FLOW_FIELD_IPV4_DSCP,	/**< IPv4 DSCP. */
-	RTE_FLOW_FIELD_IPV4_TTL,	/**< IPv4 Time To Live. */
-	RTE_FLOW_FIELD_IPV4_SRC,	/**< IPv4 Source Address. */
-	RTE_FLOW_FIELD_IPV4_DST,	/**< IPv4 Destination Address. */
-	RTE_FLOW_FIELD_IPV6_DSCP,	/**< IPv6 DSCP. */
-	RTE_FLOW_FIELD_IPV6_HOPLIMIT,	/**< IPv6 Hop Limit. */
-	RTE_FLOW_FIELD_IPV6_SRC,	/**< IPv6 Source Address. */
-	RTE_FLOW_FIELD_IPV6_DST,	/**< IPv6 Destination Address. */
-	RTE_FLOW_FIELD_TCP_PORT_SRC,	/**< TCP Source Port Number. */
-	RTE_FLOW_FIELD_TCP_PORT_DST,	/**< TCP Destination Port Number. */
-	RTE_FLOW_FIELD_TCP_SEQ_NUM,	/**< TCP Sequence Number. */
-	RTE_FLOW_FIELD_TCP_ACK_NUM,	/**< TCP Acknowledgment Number. */
-	RTE_FLOW_FIELD_TCP_FLAGS,	/**< TCP Flags. */
-	RTE_FLOW_FIELD_UDP_PORT_SRC,	/**< UDP Source Port Number. */
-	RTE_FLOW_FIELD_UDP_PORT_DST,	/**< UDP Destination Port Number. */
-	RTE_FLOW_FIELD_VXLAN_VNI,	/**< VXLAN Network Identifier. */
-	RTE_FLOW_FIELD_GENEVE_VNI,	/**< GENEVE Network Identifier. */
-	RTE_FLOW_FIELD_GTP_TEID,	/**< GTP Tunnel Endpoint Identifier. */
-	RTE_FLOW_FIELD_TAG,		/**< Tag value. */
-	RTE_FLOW_FIELD_MARK,		/**< Mark value. */
-	RTE_FLOW_FIELD_META,		/**< Metadata value. */
-	RTE_FLOW_FIELD_POINTER,		/**< Memory pointer. */
-	RTE_FLOW_FIELD_VALUE,		/**< Immediate value. */
-	RTE_FLOW_FIELD_IPV4_ECN,	/**< IPv4 ECN. */
-	RTE_FLOW_FIELD_IPV6_ECN,	/**< IPv6 ECN. */
-	RTE_FLOW_FIELD_GTP_PSC_QFI,	/**< GTP QFI. */
-	RTE_FLOW_FIELD_METER_COLOR,	/**< Meter color marker. */
-	RTE_FLOW_FIELD_IPV6_PROTO,	/**< IPv6 next header. */
-	RTE_FLOW_FIELD_FLEX_ITEM,	/**< Flex item. */
-	RTE_FLOW_FIELD_HASH_RESULT,	/**< Hash result. */
-	RTE_FLOW_FIELD_GENEVE_OPT_TYPE,	/**< GENEVE option type. */
-	RTE_FLOW_FIELD_GENEVE_OPT_CLASS,/**< GENEVE option class. */
-	RTE_FLOW_FIELD_GENEVE_OPT_DATA,	/**< GENEVE option data. */
-	RTE_FLOW_FIELD_MPLS,		/**< MPLS header. */
-	RTE_FLOW_FIELD_TCP_DATA_OFFSET,	/**< TCP data offset. */
-	RTE_FLOW_FIELD_IPV4_IHL,	/**< IPv4 IHL. */
-	RTE_FLOW_FIELD_IPV4_TOTAL_LEN,	/**< IPv4 total length. */
-	RTE_FLOW_FIELD_IPV6_PAYLOAD_LEN	/**< IPv6 payload length. */
-};
-
-/**
+ * @deprecated
+ * @see rte_flow_field_data
  * @warning
  * @b EXPERIMENTAL: this structure may change without prior notice
  *
-- 
2.34.1


^ permalink raw reply	[flat|nested] 66+ messages in thread

* [PATCH 2/2] net/mlx5: add compare item support
  2023-12-14  3:12 [PATCH 0/2] ethdev: add RTE_FLOW_ITEM_TYPE_COMPARE Suanming Mou
  2023-12-14  3:12 ` [PATCH 1/2] " Suanming Mou
@ 2023-12-14  3:12 ` Suanming Mou
  2023-12-19  1:33 ` [PATCH v2 0/3] [PATCH 0/2] ethdev: add RTE_FLOW_ITEM_TYPE_COMPARE Suanming Mou
                   ` (4 subsequent siblings)
  6 siblings, 0 replies; 66+ messages in thread
From: Suanming Mou @ 2023-12-14  3:12 UTC (permalink / raw)
  To: orika, Dariusz Sosnowski, Viacheslav Ovsiienko, Matan Azrad; +Cc: dev, rasland

The compare item allows adding flow match with comparison
result. This commit adds compare item support to the pmd
code.

Due to HW limitation:
 - Only HWS supported.
 - Only 32-bit comparison is supported.
 - Only single compare flow is supported in the flow table.
 - Only match with compare result between packet fields is
supported.

Signed-off-by: Suanming Mou <suanmingm@nvidia.com>
---
 doc/guides/nics/features/mlx5.ini      |  1 +
 doc/guides/nics/mlx5.rst               |  7 +++
 doc/guides/rel_notes/release_24_03.rst |  2 +-
 drivers/net/mlx5/mlx5_flow.h           |  3 ++
 drivers/net/mlx5/mlx5_flow_hw.c        | 73 ++++++++++++++++++++++++++
 5 files changed, 85 insertions(+), 1 deletion(-)

diff --git a/doc/guides/nics/features/mlx5.ini b/doc/guides/nics/features/mlx5.ini
index 0739fe9d63..00e9348fc6 100644
--- a/doc/guides/nics/features/mlx5.ini
+++ b/doc/guides/nics/features/mlx5.ini
@@ -56,6 +56,7 @@ Usage doc            = Y
 
 [rte_flow items]
 aggr_affinity        = Y
+compare              = Y
 conntrack            = Y
 ecpri                = Y
 esp                  = Y
diff --git a/doc/guides/nics/mlx5.rst b/doc/guides/nics/mlx5.rst
index 6b52fb93c5..18b40bc22d 100644
--- a/doc/guides/nics/mlx5.rst
+++ b/doc/guides/nics/mlx5.rst
@@ -778,6 +778,13 @@ Limitations
   The flow engine of a process cannot move from active to standby mode
   if preceding active application rules are still present and vice versa.
 
+- Match with compare result item (``RTE_FLOW_ITEM_TYPE_COMPARE``):
+
+  - Only supported in HW steering(``dv_flow_en`` = 2) mode.
+  - Only single flow is supported to the flow table.
+  - Only 32-bit comparison is supported.
+  - Only match with compare result between packet fields is supported.
+
 
 Statistics
 ----------
diff --git a/doc/guides/rel_notes/release_24_03.rst b/doc/guides/rel_notes/release_24_03.rst
index 71ebd67dbd..5693ea4628 100644
--- a/doc/guides/rel_notes/release_24_03.rst
+++ b/doc/guides/rel_notes/release_24_03.rst
@@ -63,7 +63,7 @@ New Features
 * **Updated NVIDIA mlx5 driver.**
 
   * Added support for accumulating from src field to dst field.
-
+  * Added support for comparing result between packet fields or value.
 
 Removed Items
 -------------
diff --git a/drivers/net/mlx5/mlx5_flow.h b/drivers/net/mlx5/mlx5_flow.h
index 120609c595..9c9bdc3f6a 100644
--- a/drivers/net/mlx5/mlx5_flow.h
+++ b/drivers/net/mlx5/mlx5_flow.h
@@ -277,6 +277,9 @@ enum mlx5_feature_name {
 /* NSH ITEM */
 #define MLX5_FLOW_ITEM_NSH (1ull << 53)
 
+/* COMPARE ITEM */
+#define MLX5_FLOW_ITEM_COMPARE (1ull << 54)
+
 /* Outer Masks. */
 #define MLX5_FLOW_LAYER_OUTER_L3 \
 	(MLX5_FLOW_LAYER_OUTER_L3_IPV4 | MLX5_FLOW_LAYER_OUTER_L3_IPV6)
diff --git a/drivers/net/mlx5/mlx5_flow_hw.c b/drivers/net/mlx5/mlx5_flow_hw.c
index c4a90a3690..82d7fa006f 100644
--- a/drivers/net/mlx5/mlx5_flow_hw.c
+++ b/drivers/net/mlx5/mlx5_flow_hw.c
@@ -426,6 +426,9 @@ flow_hw_matching_item_flags_get(const struct rte_flow_item items[])
 		case RTE_FLOW_ITEM_TYPE_GTP:
 			last_item = MLX5_FLOW_LAYER_GTP;
 			break;
+		case RTE_FLOW_ITEM_TYPE_COMPARE:
+			last_item = MLX5_FLOW_ITEM_COMPARE;
+			break;
 		default:
 			break;
 		}
@@ -4390,6 +4393,8 @@ flow_hw_table_create(struct rte_eth_dev *dev,
 			rte_errno = EINVAL;
 			goto it_error;
 		}
+		if (item_templates[i]->item_flags & MLX5_FLOW_ITEM_COMPARE)
+			matcher_attr.mode = MLX5DR_MATCHER_RESOURCE_MODE_HTABLE;
 		ret = __atomic_fetch_add(&item_templates[i]->refcnt, 1,
 					 __ATOMIC_RELAXED) + 1;
 		if (ret <= 1) {
@@ -6670,6 +6675,66 @@ flow_hw_prepend_item(const struct rte_flow_item *items,
 	return copied_items;
 }
 
+static inline bool
+flow_hw_item_compare_field_supported(enum rte_flow_field_id field)
+{
+	switch (field) {
+	case RTE_FLOW_FIELD_TAG:
+	case RTE_FLOW_FIELD_META:
+	case RTE_FLOW_FIELD_VALUE:
+		return true;
+	default:
+		break;
+	}
+	return false;
+}
+
+static int
+flow_hw_validate_item_compare(const struct rte_flow_item *item,
+			      struct rte_flow_error *error)
+{
+	const struct rte_flow_item_compare *comp_m = item->mask;
+	const struct rte_flow_item_compare *comp_v = item->spec;
+
+	if (unlikely(!comp_m))
+		return rte_flow_error_set(error, EINVAL,
+				   RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
+				   NULL,
+				   "compare item mask is missing");
+	if (comp_m->width != UINT32_MAX)
+		return rte_flow_error_set(error, EINVAL,
+				   RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
+				   NULL,
+				   "compare item only support full mask");
+	if (!flow_hw_item_compare_field_supported(comp_m->a.field) ||
+	    !flow_hw_item_compare_field_supported(comp_m->b.field))
+		return rte_flow_error_set(error, ENOTSUP,
+				   RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
+				   NULL,
+				   "compare item field not support");
+	if (comp_m->a.field == RTE_FLOW_FIELD_VALUE &&
+	    comp_m->b.field == RTE_FLOW_FIELD_VALUE)
+		return rte_flow_error_set(error, EINVAL,
+				   RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
+				   NULL,
+				   "compare between value is not valid");
+	if (comp_v) {
+		if (comp_v->operation != comp_m->operation ||
+		    comp_v->a.field != comp_m->a.field ||
+		    comp_v->b.field != comp_m->b.field)
+			return rte_flow_error_set(error, EINVAL,
+					   RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
+					   NULL,
+					   "compare item spec/mask not matching");
+		if ((comp_v->width & comp_m->width) != 32)
+			return rte_flow_error_set(error, EINVAL,
+					   RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
+					   NULL,
+					   "compare item only support full mask");
+	}
+	return 0;
+}
+
 static int
 flow_hw_pattern_validate(struct rte_eth_dev *dev,
 			 const struct rte_flow_pattern_template_attr *attr,
@@ -6680,6 +6745,7 @@ flow_hw_pattern_validate(struct rte_eth_dev *dev,
 	int i, tag_idx;
 	bool items_end = false;
 	uint32_t tag_bitmap = 0;
+	int ret;
 
 	if (!attr->ingress && !attr->egress && !attr->transfer)
 		return rte_flow_error_set(error, EINVAL, RTE_FLOW_ERROR_TYPE_ATTR, NULL,
@@ -6817,6 +6883,13 @@ flow_hw_pattern_validate(struct rte_eth_dev *dev,
 							  " attribute");
 			break;
 		}
+		case RTE_FLOW_ITEM_TYPE_COMPARE:
+		{
+			ret = flow_hw_validate_item_compare(&items[i], error);
+			if (ret)
+				return ret;
+			break;
+		}
 		case RTE_FLOW_ITEM_TYPE_VOID:
 		case RTE_FLOW_ITEM_TYPE_ETH:
 		case RTE_FLOW_ITEM_TYPE_VLAN:
-- 
2.34.1


^ permalink raw reply	[flat|nested] 66+ messages in thread

* [PATCH v2 0/3] [PATCH 0/2] ethdev: add RTE_FLOW_ITEM_TYPE_COMPARE
  2023-12-14  3:12 [PATCH 0/2] ethdev: add RTE_FLOW_ITEM_TYPE_COMPARE Suanming Mou
  2023-12-14  3:12 ` [PATCH 1/2] " Suanming Mou
  2023-12-14  3:12 ` [PATCH 2/2] net/mlx5: add compare item support Suanming Mou
@ 2023-12-19  1:33 ` Suanming Mou
  2023-12-19  1:33   ` [PATCH v2 1/3] ethdev: rename action modify field data structure Suanming Mou
                     ` (3 more replies)
  2024-02-01  2:30 ` [PATCH v4 0/3] ethdev: add RTE_FLOW_ITEM_TYPE_COMPARE Suanming Mou
                   ` (3 subsequent siblings)
  6 siblings, 4 replies; 66+ messages in thread
From: Suanming Mou @ 2023-12-19  1:33 UTC (permalink / raw)
  Cc: dev, orika

The new item type is added for the case user wants to match traffic
based on packet field compare result with other fields or immediate
value.

e.g. take advantage the compare item user will be able to accumulate
a IPv4/TCP packet's TCP data_offset and IPv4 IHL field to a tag
register, then compare the tag register with IPv4 header total length
to understand the packet has payload or not.

The supported operations can be as below:
 - RTE_FLOW_ITEM_COMPARE_EQ (equal)
 - RTE_FLOW_ITEM_COMPARE_NE (not equal)
 - RTE_FLOW_ITEM_COMPARE_LT (less than)
 - RTE_FLOW_ITEM_COMPARE_LE (less than or equal)
 - RTE_FLOW_ITEM_COMPARE_GT (great than)
 - RTE_FLOW_ITEM_COMPARE_GE (great than or equal)


V2:
 - Since modify field data struct is experiment, rename modify
   field data directly instead of adding new flow field struct.

Suanming Mou (3):
  ethdev: rename action modify field data structure
  ethdev: add compare item
  net/mlx5: add compare item support

 app/test-pmd/cmdline_flow.c                 | 416 +++++++++++++++++++-
 doc/guides/nics/features/default.ini        |   1 +
 doc/guides/nics/features/mlx5.ini           |   1 +
 doc/guides/nics/mlx5.rst                    |   7 +
 doc/guides/prog_guide/rte_flow.rst          |   9 +-
 doc/guides/rel_notes/release_24_03.rst      |   7 +-
 doc/guides/testpmd_app_ug/testpmd_funcs.rst |   6 +
 drivers/net/mlx5/mlx5_flow.c                |   4 +-
 drivers/net/mlx5/mlx5_flow.h                |   9 +-
 drivers/net/mlx5/mlx5_flow_dv.c             |  10 +-
 drivers/net/mlx5/mlx5_flow_hw.c             |  73 ++++
 lib/ethdev/rte_flow.c                       |   1 +
 lib/ethdev/rte_flow.h                       | 326 ++++++++-------
 13 files changed, 701 insertions(+), 169 deletions(-)

-- 
2.34.1


^ permalink raw reply	[flat|nested] 66+ messages in thread

* [PATCH v2 1/3] ethdev: rename action modify field data structure
  2023-12-19  1:33 ` [PATCH v2 0/3] [PATCH 0/2] ethdev: add RTE_FLOW_ITEM_TYPE_COMPARE Suanming Mou
@ 2023-12-19  1:33   ` Suanming Mou
  2024-01-09 14:07     ` Ori Kam
  2023-12-19  1:33   ` [PATCH v2 2/3] ethdev: add compare item Suanming Mou
                     ` (2 subsequent siblings)
  3 siblings, 1 reply; 66+ messages in thread
From: Suanming Mou @ 2023-12-19  1:33 UTC (permalink / raw)
  To: Ori Kam, Aman Singh, Yuying Zhang, Dariusz Sosnowski,
	Viacheslav Ovsiienko, Matan Azrad, Thomas Monjalon, Ferruh Yigit,
	Andrew Rybchenko
  Cc: dev

Current rte_flow_action_modify_data struct describes the pkt
field perfectly and is used only in action.

It is planned to be used for item as well. This commit renames
it to "rte_flow_field_data" making it compatible to be used by item.

Signed-off-by: Suanming Mou <suanmingm@nvidia.com>
---
 app/test-pmd/cmdline_flow.c        |  2 +-
 doc/guides/prog_guide/rte_flow.rst |  2 +-
 drivers/net/mlx5/mlx5_flow.c       |  4 ++--
 drivers/net/mlx5/mlx5_flow.h       |  6 +++---
 drivers/net/mlx5/mlx5_flow_dv.c    | 10 +++++-----
 lib/ethdev/rte_flow.h              |  8 ++++----
 6 files changed, 16 insertions(+), 16 deletions(-)

diff --git a/app/test-pmd/cmdline_flow.c b/app/test-pmd/cmdline_flow.c
index ce71818705..3725e955c7 100644
--- a/app/test-pmd/cmdline_flow.c
+++ b/app/test-pmd/cmdline_flow.c
@@ -740,7 +740,7 @@ enum index {
 #define ITEM_RAW_SIZE \
 	(sizeof(struct rte_flow_item_raw) + ITEM_RAW_PATTERN_SIZE)
 
-/** Maximum size for external pattern in struct rte_flow_action_modify_data. */
+/** Maximum size for external pattern in struct rte_flow_field_data. */
 #define ACTION_MODIFY_PATTERN_SIZE 32
 
 /** Storage size for struct rte_flow_action_modify_field including pattern. */
diff --git a/doc/guides/prog_guide/rte_flow.rst b/doc/guides/prog_guide/rte_flow.rst
index 627b845bfb..bf25c849fb 100644
--- a/doc/guides/prog_guide/rte_flow.rst
+++ b/doc/guides/prog_guide/rte_flow.rst
@@ -3171,7 +3171,7 @@ destination offset as ``48``, and provide immediate value ``0xXXXX85XX``.
    | ``width``     | number of bits to use   |
    +---------------+-------------------------+
 
-.. _table_rte_flow_action_modify_data:
+.. _table_rte_flow_field_data:
 
 .. table:: destination/source field definition
 
diff --git a/drivers/net/mlx5/mlx5_flow.c b/drivers/net/mlx5/mlx5_flow.c
index 85e8c77c81..5788a7fb57 100644
--- a/drivers/net/mlx5/mlx5_flow.c
+++ b/drivers/net/mlx5/mlx5_flow.c
@@ -2493,7 +2493,7 @@ mlx5_validate_action_ct(struct rte_eth_dev *dev,
  * Validate the level value for modify field action.
  *
  * @param[in] data
- *   Pointer to the rte_flow_action_modify_data structure either src or dst.
+ *   Pointer to the rte_flow_field_data structure either src or dst.
  * @param[out] error
  *   Pointer to error structure.
  *
@@ -2501,7 +2501,7 @@ mlx5_validate_action_ct(struct rte_eth_dev *dev,
  *   0 on success, a negative errno value otherwise and rte_errno is set.
  */
 int
-flow_validate_modify_field_level(const struct rte_flow_action_modify_data *data,
+flow_validate_modify_field_level(const struct rte_flow_field_data *data,
 				 struct rte_flow_error *error)
 {
 	if (data->level == 0)
diff --git a/drivers/net/mlx5/mlx5_flow.h b/drivers/net/mlx5/mlx5_flow.h
index 120609c595..8e2034473c 100644
--- a/drivers/net/mlx5/mlx5_flow.h
+++ b/drivers/net/mlx5/mlx5_flow.h
@@ -1121,7 +1121,7 @@ flow_items_to_tunnel(const struct rte_flow_item items[])
  *   Tag array index.
  */
 static inline uint8_t
-flow_tag_index_get(const struct rte_flow_action_modify_data *data)
+flow_tag_index_get(const struct rte_flow_field_data *data)
 {
 	return data->tag_index ? data->tag_index : data->level;
 }
@@ -2523,7 +2523,7 @@ int mlx5_flow_validate_action_default_miss(uint64_t action_flags,
 				const struct rte_flow_attr *attr,
 				struct rte_flow_error *error);
 int flow_validate_modify_field_level
-			(const struct rte_flow_action_modify_data *data,
+			(const struct rte_flow_field_data *data,
 			 struct rte_flow_error *error);
 int mlx5_flow_item_acceptable(const struct rte_flow_item *item,
 			      const uint8_t *mask,
@@ -2828,7 +2828,7 @@ size_t flow_dv_get_item_hdr_len(const enum rte_flow_item_type item_type);
 int flow_dv_convert_encap_data(const struct rte_flow_item *items, uint8_t *buf,
 			   size_t *size, struct rte_flow_error *error);
 void mlx5_flow_field_id_to_modify_info
-		(const struct rte_flow_action_modify_data *data,
+		(const struct rte_flow_field_data *data,
 		 struct field_modify_info *info, uint32_t *mask,
 		 uint32_t width, struct rte_eth_dev *dev,
 		 const struct rte_flow_attr *attr, struct rte_flow_error *error);
diff --git a/drivers/net/mlx5/mlx5_flow_dv.c b/drivers/net/mlx5/mlx5_flow_dv.c
index 1c3d557d4a..9627e124a9 100644
--- a/drivers/net/mlx5/mlx5_flow_dv.c
+++ b/drivers/net/mlx5/mlx5_flow_dv.c
@@ -1446,7 +1446,7 @@ flow_modify_info_mask_32_masked(uint32_t length, uint32_t off, uint32_t post_mas
 }
 
 static __rte_always_inline enum mlx5_modification_field
-mlx5_mpls_modi_field_get(const struct rte_flow_action_modify_data *data)
+mlx5_mpls_modi_field_get(const struct rte_flow_field_data *data)
 {
 	return MLX5_MODI_IN_MPLS_LABEL_0 + data->tag_index;
 }
@@ -1454,7 +1454,7 @@ mlx5_mpls_modi_field_get(const struct rte_flow_action_modify_data *data)
 static void
 mlx5_modify_flex_item(const struct rte_eth_dev *dev,
 		      const struct mlx5_flex_item *flex,
-		      const struct rte_flow_action_modify_data *data,
+		      const struct rte_flow_field_data *data,
 		      struct field_modify_info *info,
 		      uint32_t *mask, uint32_t width)
 {
@@ -1578,7 +1578,7 @@ mlx5_modify_flex_item(const struct rte_eth_dev *dev,
 
 void
 mlx5_flow_field_id_to_modify_info
-		(const struct rte_flow_action_modify_data *data,
+		(const struct rte_flow_field_data *data,
 		 struct field_modify_info *info, uint32_t *mask,
 		 uint32_t width, struct rte_eth_dev *dev,
 		 const struct rte_flow_attr *attr, struct rte_flow_error *error)
@@ -5329,8 +5329,8 @@ flow_dv_validate_action_modify_field(struct rte_eth_dev *dev,
 	struct mlx5_sh_config *config = &priv->sh->config;
 	struct mlx5_hca_attr *hca_attr = &priv->sh->cdev->config.hca_attr;
 	const struct rte_flow_action_modify_field *conf = action->conf;
-	const struct rte_flow_action_modify_data *src_data = &conf->src;
-	const struct rte_flow_action_modify_data *dst_data = &conf->dst;
+	const struct rte_flow_field_data *src_data = &conf->src;
+	const struct rte_flow_field_data *dst_data = &conf->dst;
 	uint32_t dst_width, src_width, width = conf->width;
 
 	ret = flow_dv_validate_action_modify_hdr(action_flags, action, error);
diff --git a/lib/ethdev/rte_flow.h b/lib/ethdev/rte_flow.h
index affdc8121b..40f6dcaacd 100644
--- a/lib/ethdev/rte_flow.h
+++ b/lib/ethdev/rte_flow.h
@@ -3910,9 +3910,9 @@ enum rte_flow_field_id {
  * @warning
  * @b EXPERIMENTAL: this structure may change without prior notice
  *
- * Field description for MODIFY_FIELD action.
+ * Field description for packet field.
  */
-struct rte_flow_action_modify_data {
+struct rte_flow_field_data {
 	enum rte_flow_field_id field; /**< Field or memory type ID. */
 	union {
 		struct {
@@ -4021,8 +4021,8 @@ enum rte_flow_modify_op {
  */
 struct rte_flow_action_modify_field {
 	enum rte_flow_modify_op operation; /**< Operation to perform. */
-	struct rte_flow_action_modify_data dst; /**< Destination field. */
-	struct rte_flow_action_modify_data src; /**< Source field. */
+	struct rte_flow_field_data dst; /**< Destination field. */
+	struct rte_flow_field_data src; /**< Source field. */
 	uint32_t width; /**< Number of bits to use from a source field. */
 };
 
-- 
2.34.1


^ permalink raw reply	[flat|nested] 66+ messages in thread

* [PATCH v2 2/3] ethdev: add compare item
  2023-12-19  1:33 ` [PATCH v2 0/3] [PATCH 0/2] ethdev: add RTE_FLOW_ITEM_TYPE_COMPARE Suanming Mou
  2023-12-19  1:33   ` [PATCH v2 1/3] ethdev: rename action modify field data structure Suanming Mou
@ 2023-12-19  1:33   ` Suanming Mou
  2024-01-09 14:26     ` Ori Kam
  2024-01-12  8:11     ` Andrew Rybchenko
  2023-12-19  1:33   ` [PATCH v2 3/3] net/mlx5: add compare item support Suanming Mou
  2024-01-15  9:13   ` [PATCH v3 0/3] ethdev: add RTE_FLOW_ITEM_TYPE_COMPARE Suanming Mou
  3 siblings, 2 replies; 66+ messages in thread
From: Suanming Mou @ 2023-12-19  1:33 UTC (permalink / raw)
  To: Ori Kam, Aman Singh, Yuying Zhang, Thomas Monjalon, Ferruh Yigit,
	Andrew Rybchenko
  Cc: dev

The new item type is added for the case user wants to match traffic
based on packet field compare result with other fields or immediate
value.

e.g. take advantage the compare item user will be able to accumulate
a IPv4/TCP packet's TCP data_offset and IPv4 IHL field to a tag
register, then compare the tag register with IPv4 header total length
to understand the packet has payload or not.

The supported operations can be as below:
 - RTE_FLOW_ITEM_COMPARE_EQ (equal)
 - RTE_FLOW_ITEM_COMPARE_NE (not equal)
 - RTE_FLOW_ITEM_COMPARE_LT (less than)
 - RTE_FLOW_ITEM_COMPARE_LE (less than or equal)
 - RTE_FLOW_ITEM_COMPARE_GT (great than)
 - RTE_FLOW_ITEM_COMPARE_GE (great than or equal)

Signed-off-by: Suanming Mou <suanmingm@nvidia.com>
---
 app/test-pmd/cmdline_flow.c                 | 414 +++++++++++++++++++-
 doc/guides/nics/features/default.ini        |   1 +
 doc/guides/prog_guide/rte_flow.rst          |   7 +
 doc/guides/rel_notes/release_24_03.rst      |   5 +
 doc/guides/testpmd_app_ug/testpmd_funcs.rst |   6 +
 lib/ethdev/rte_flow.c                       |   1 +
 lib/ethdev/rte_flow.h                       | 322 ++++++++-------
 7 files changed, 602 insertions(+), 154 deletions(-)

diff --git a/app/test-pmd/cmdline_flow.c b/app/test-pmd/cmdline_flow.c
index 3725e955c7..4f448ff8ec 100644
--- a/app/test-pmd/cmdline_flow.c
+++ b/app/test-pmd/cmdline_flow.c
@@ -543,6 +543,28 @@ enum index {
 	ITEM_PTYPE,
 	ITEM_PTYPE_VALUE,
 	ITEM_NSH,
+	ITEM_COMPARE,
+	ITEM_COMPARE_OP,
+	ITEM_COMPARE_OP_VALUE,
+	ITEM_COMPARE_FIELD_A_TYPE,
+	ITEM_COMPARE_FIELD_A_TYPE_VALUE,
+	ITEM_COMPARE_FIELD_A_LEVEL,
+	ITEM_COMPARE_FIELD_A_LEVEL_VALUE,
+	ITEM_COMPARE_FIELD_A_TAG_INDEX,
+	ITEM_COMPARE_FIELD_A_TYPE_ID,
+	ITEM_COMPARE_FIELD_A_CLASS_ID,
+	ITEM_COMPARE_FIELD_A_OFFSET,
+	ITEM_COMPARE_FIELD_B_TYPE,
+	ITEM_COMPARE_FIELD_B_TYPE_VALUE,
+	ITEM_COMPARE_FIELD_B_LEVEL,
+	ITEM_COMPARE_FIELD_B_LEVEL_VALUE,
+	ITEM_COMPARE_FIELD_B_TAG_INDEX,
+	ITEM_COMPARE_FIELD_B_TYPE_ID,
+	ITEM_COMPARE_FIELD_B_CLASS_ID,
+	ITEM_COMPARE_FIELD_B_OFFSET,
+	ITEM_COMPARE_FIELD_B_VALUE,
+	ITEM_COMPARE_FIELD_B_POINTER,
+	ITEM_COMPARE_FIELD_WIDTH,
 
 	/* Validate/create actions. */
 	ACTIONS,
@@ -740,13 +762,17 @@ enum index {
 #define ITEM_RAW_SIZE \
 	(sizeof(struct rte_flow_item_raw) + ITEM_RAW_PATTERN_SIZE)
 
+static const char *const compare_ops[] = {
+	"eq", "ne", "lt", "le", "gt", "ge", NULL
+};
+
 /** Maximum size for external pattern in struct rte_flow_field_data. */
-#define ACTION_MODIFY_PATTERN_SIZE 32
+#define FLOW_FIELD_PATTERN_SIZE 32
 
 /** Storage size for struct rte_flow_action_modify_field including pattern. */
 #define ACTION_MODIFY_SIZE \
 	(sizeof(struct rte_flow_action_modify_field) + \
-	ACTION_MODIFY_PATTERN_SIZE)
+	FLOW_FIELD_PATTERN_SIZE)
 
 /** Maximum number of queue indices in struct rte_flow_action_rss. */
 #define ACTION_RSS_QUEUE_NUM 128
@@ -940,7 +966,7 @@ static const char *const modify_field_ops[] = {
 	"set", "add", "sub", NULL
 };
 
-static const char *const modify_field_ids[] = {
+static const char *const flow_field_ids[] = {
 	"start", "mac_dst", "mac_src",
 	"vlan_type", "vlan_id", "mac_type",
 	"ipv4_dscp", "ipv4_ttl", "ipv4_src", "ipv4_dst",
@@ -1590,6 +1616,7 @@ static const enum index next_item[] = {
 	ITEM_IB_BTH,
 	ITEM_PTYPE,
 	ITEM_NSH,
+	ITEM_COMPARE,
 	END_SET,
 	ZERO,
 };
@@ -2121,6 +2148,38 @@ static const enum index item_nsh[] = {
 	ZERO,
 };
 
+static const enum index item_compare_field[] = {
+	ITEM_COMPARE_OP,
+	ITEM_COMPARE_FIELD_A_TYPE,
+	ITEM_COMPARE_FIELD_B_TYPE,
+	ITEM_NEXT,
+	ZERO,
+};
+
+static const enum index compare_field_a[] = {
+	ITEM_COMPARE_FIELD_A_TYPE,
+	ITEM_COMPARE_FIELD_A_LEVEL,
+	ITEM_COMPARE_FIELD_A_TAG_INDEX,
+	ITEM_COMPARE_FIELD_A_TYPE_ID,
+	ITEM_COMPARE_FIELD_A_CLASS_ID,
+	ITEM_COMPARE_FIELD_A_OFFSET,
+	ITEM_COMPARE_FIELD_B_TYPE,
+	ZERO,
+};
+
+static const enum index compare_field_b[] = {
+	ITEM_COMPARE_FIELD_B_TYPE,
+	ITEM_COMPARE_FIELD_B_LEVEL,
+	ITEM_COMPARE_FIELD_B_TAG_INDEX,
+	ITEM_COMPARE_FIELD_B_TYPE_ID,
+	ITEM_COMPARE_FIELD_B_CLASS_ID,
+	ITEM_COMPARE_FIELD_B_OFFSET,
+	ITEM_COMPARE_FIELD_B_VALUE,
+	ITEM_COMPARE_FIELD_B_POINTER,
+	ITEM_COMPARE_FIELD_WIDTH,
+	ZERO,
+};
+
 static const enum index next_action[] = {
 	ACTION_END,
 	ACTION_VOID,
@@ -2863,6 +2922,24 @@ comp_quota_update_name(struct context *ctx, const struct token *token,
 static int
 comp_qu_mode_name(struct context *ctx, const struct token *token,
 		  unsigned int ent, char *buf, unsigned int size);
+static int
+comp_set_compare_field_id(struct context *ctx, const struct token *token,
+			  unsigned int ent, char *buf, unsigned int size);
+static int
+comp_set_compare_op(struct context *ctx, const struct token *token,
+		    unsigned int ent, char *buf, unsigned int size);
+static int
+parse_vc_compare_op(struct context *ctx, const struct token *token,
+			 const char *str, unsigned int len, void *buf,
+			 unsigned int size);
+static int
+parse_vc_compare_field_id(struct context *ctx, const struct token *token,
+			  const char *str, unsigned int len, void *buf,
+			  unsigned int size);
+static int
+parse_vc_compare_field_level(struct context *ctx, const struct token *token,
+			     const char *str, unsigned int len, void *buf,
+			     unsigned int size);
 
 struct indlst_conf {
 	uint32_t id;
@@ -5982,6 +6059,174 @@ static const struct token token_list[] = {
 		.next = NEXT(item_nsh),
 		.call = parse_vc,
 	},
+	[ITEM_COMPARE] = {
+		.name = "compare",
+		.help = "match with the comparison result",
+		.priv = PRIV_ITEM(COMPARE, sizeof(struct rte_flow_item_compare)),
+		.next = NEXT(NEXT_ENTRY(ITEM_COMPARE_OP)),
+		.call = parse_vc,
+	},
+	[ITEM_COMPARE_OP] = {
+		.name = "op",
+		.help = "operation type",
+		.next = NEXT(item_compare_field,
+			NEXT_ENTRY(ITEM_COMPARE_OP_VALUE), item_param),
+		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_compare, operation)),
+	},
+	[ITEM_COMPARE_OP_VALUE] = {
+		.name = "{operation}",
+		.help = "operation type value",
+		.call = parse_vc_compare_op,
+		.comp = comp_set_compare_op,
+	},
+	[ITEM_COMPARE_FIELD_A_TYPE] = {
+		.name = "a_type",
+		.help = "compared field type",
+		.next = NEXT(compare_field_a,
+			NEXT_ENTRY(ITEM_COMPARE_FIELD_A_TYPE_VALUE), item_param),
+		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_compare, a.field)),
+	},
+	[ITEM_COMPARE_FIELD_A_TYPE_VALUE] = {
+		.name = "{a_type}",
+		.help = "compared field type value",
+		.call = parse_vc_compare_field_id,
+		.comp = comp_set_compare_field_id,
+	},
+	[ITEM_COMPARE_FIELD_A_LEVEL] = {
+		.name = "a_level",
+		.help = "compared field level",
+		.next = NEXT(compare_field_a,
+			     NEXT_ENTRY(ITEM_COMPARE_FIELD_A_LEVEL_VALUE), item_param),
+		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_compare, a.level)),
+	},
+	[ITEM_COMPARE_FIELD_A_LEVEL_VALUE] = {
+		.name = "{a_level}",
+		.help = "compared field level value",
+		.call = parse_vc_compare_field_level,
+		.comp = comp_none,
+	},
+	[ITEM_COMPARE_FIELD_A_TAG_INDEX] = {
+		.name = "a_tag_index",
+		.help = "compared field tag array",
+		.next = NEXT(compare_field_a,
+			     NEXT_ENTRY(COMMON_UNSIGNED), item_param),
+		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_compare,
+					a.tag_index)),
+	},
+	[ITEM_COMPARE_FIELD_A_TYPE_ID] = {
+		.name = "a_type_id",
+		.help = "compared field type ID",
+		.next = NEXT(compare_field_a,
+			     NEXT_ENTRY(COMMON_UNSIGNED), item_param),
+		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_compare,
+					a.type)),
+	},
+	[ITEM_COMPARE_FIELD_A_CLASS_ID] = {
+		.name = "a_class",
+		.help = "compared field class ID",
+		.next = NEXT(compare_field_a,
+			     NEXT_ENTRY(COMMON_UNSIGNED), item_param),
+		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_compare,
+					     a.class_id)),
+	},
+	[ITEM_COMPARE_FIELD_A_OFFSET] = {
+		.name = "a_offset",
+		.help = "compared field bit offset",
+		.next = NEXT(compare_field_a,
+			     NEXT_ENTRY(COMMON_UNSIGNED), item_param),
+		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_compare,
+					a.offset)),
+	},
+	[ITEM_COMPARE_FIELD_B_TYPE] = {
+		.name = "b_type",
+		.help = "comparator field type",
+		.next = NEXT(compare_field_b,
+			NEXT_ENTRY(ITEM_COMPARE_FIELD_B_TYPE_VALUE), item_param),
+		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_compare,
+					b.field)),
+	},
+	[ITEM_COMPARE_FIELD_B_TYPE_VALUE] = {
+		.name = "{b_type}",
+		.help = "comparator field type value",
+		.call = parse_vc_compare_field_id,
+		.comp = comp_set_compare_field_id,
+	},
+	[ITEM_COMPARE_FIELD_B_LEVEL] = {
+		.name = "b_level",
+		.help = "comparator field level",
+		.next = NEXT(compare_field_b,
+			     NEXT_ENTRY(ITEM_COMPARE_FIELD_B_LEVEL_VALUE), item_param),
+		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_compare,
+					b.level)),
+	},
+	[ITEM_COMPARE_FIELD_B_LEVEL_VALUE] = {
+		.name = "{b_level}",
+		.help = "comparator field level value",
+		.call = parse_vc_compare_field_level,
+		.comp = comp_none,
+	},
+	[ITEM_COMPARE_FIELD_B_TAG_INDEX] = {
+		.name = "b_tag_index",
+		.help = "comparator field tag array",
+		.next = NEXT(compare_field_b,
+			     NEXT_ENTRY(COMMON_UNSIGNED), item_param),
+		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_compare,
+					b.tag_index)),
+	},
+	[ITEM_COMPARE_FIELD_B_TYPE_ID] = {
+		.name = "b_type_id",
+		.help = "comparator field type ID",
+		.next = NEXT(compare_field_b,
+			     NEXT_ENTRY(COMMON_UNSIGNED), item_param),
+		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_compare,
+					b.type)),
+	},
+	[ITEM_COMPARE_FIELD_B_CLASS_ID] = {
+		.name = "b_class",
+		.help = "comparator field class ID",
+		.next = NEXT(compare_field_b,
+			     NEXT_ENTRY(COMMON_UNSIGNED), item_param),
+		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_compare,
+					     b.class_id)),
+	},
+	[ITEM_COMPARE_FIELD_B_OFFSET] = {
+		.name = "b_offset",
+		.help = "comparator field bit offset",
+		.next = NEXT(compare_field_b,
+			     NEXT_ENTRY(COMMON_UNSIGNED), item_param),
+		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_compare,
+					b.offset)),
+	},
+	[ITEM_COMPARE_FIELD_B_VALUE] = {
+		.name = "b_value",
+		.help = "comparator immediate value",
+		.next = NEXT(compare_field_b,
+			     NEXT_ENTRY(COMMON_HEX), item_param),
+		.args = ARGS(ARGS_ENTRY_ARB(0, 0),
+			     ARGS_ENTRY_ARB(0, 0),
+			     ARGS_ENTRY(struct rte_flow_item_compare,
+					b.value)),
+	},
+	[ITEM_COMPARE_FIELD_B_POINTER] = {
+		.name = "b_ptr",
+		.help = "pointer to comparator immediate value",
+		.next = NEXT(compare_field_b,
+			     NEXT_ENTRY(COMMON_HEX), item_param),
+		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_compare,
+					b.pvalue),
+			     ARGS_ENTRY_ARB(0, 0),
+			     ARGS_ENTRY_ARB
+				(sizeof(struct rte_flow_item_compare),
+				 FLOW_FIELD_PATTERN_SIZE)),
+	},
+	[ITEM_COMPARE_FIELD_WIDTH] = {
+		.name = "width",
+		.help = "number of bits to compare",
+		.next = NEXT(item_compare_field,
+			NEXT_ENTRY(COMMON_UNSIGNED), item_param),
+		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_compare,
+					width)),
+	},
 
 	/* Validate/create actions. */
 	[ACTIONS] = {
@@ -6961,7 +7206,7 @@ static const struct token token_list[] = {
 			     ARGS_ENTRY_ARB(0, 0),
 			     ARGS_ENTRY_ARB
 				(sizeof(struct rte_flow_action_modify_field),
-				 ACTION_MODIFY_PATTERN_SIZE)),
+				 FLOW_FIELD_PATTERN_SIZE)),
 		.call = parse_vc_conf,
 	},
 	[ACTION_MODIFY_FIELD_WIDTH] = {
@@ -8404,6 +8649,122 @@ parse_vc_item_l2tpv2_type(struct context *ctx, const struct token *token,
 	return len;
 }
 
+/** Parse operation for compare match item. */
+static int
+parse_vc_compare_op(struct context *ctx, const struct token *token,
+			 const char *str, unsigned int len, void *buf,
+			 unsigned int size)
+{
+	struct rte_flow_item_compare *compare_item;
+	unsigned int i;
+
+	(void)token;
+	(void)buf;
+	(void)size;
+	if (ctx->curr != ITEM_COMPARE_OP_VALUE)
+		return -1;
+	for (i = 0; compare_ops[i]; ++i)
+		if (!strcmp_partial(compare_ops[i], str, len))
+			break;
+	if (!compare_ops[i])
+		return -1;
+	if (!ctx->object)
+		return len;
+	compare_item = ctx->object;
+	compare_item->operation = (enum rte_flow_item_compare_op)i;
+	return len;
+}
+
+/** Parse id for compare match item. */
+static int
+parse_vc_compare_field_id(struct context *ctx, const struct token *token,
+			  const char *str, unsigned int len, void *buf,
+			  unsigned int size)
+{
+	struct rte_flow_item_compare *compare_item;
+	unsigned int i;
+
+	(void)token;
+	(void)buf;
+	(void)size;
+	if (ctx->curr != ITEM_COMPARE_FIELD_A_TYPE_VALUE &&
+		ctx->curr != ITEM_COMPARE_FIELD_B_TYPE_VALUE)
+		return -1;
+	for (i = 0; flow_field_ids[i]; ++i)
+		if (!strcmp_partial(flow_field_ids[i], str, len))
+			break;
+	if (!flow_field_ids[i])
+		return -1;
+	if (!ctx->object)
+		return len;
+	compare_item = ctx->object;
+	if (ctx->curr == ITEM_COMPARE_FIELD_A_TYPE_VALUE)
+		compare_item->a.field = (enum rte_flow_field_id)i;
+	else
+		compare_item->b.field = (enum rte_flow_field_id)i;
+	return len;
+}
+
+/** Parse level for compare match item. */
+static int
+parse_vc_compare_field_level(struct context *ctx, const struct token *token,
+			     const char *str, unsigned int len, void *buf,
+			     unsigned int size)
+{
+	struct rte_flow_item_compare *compare_item;
+	struct flex_item *fp = NULL;
+	uint32_t val;
+	struct buffer *out = buf;
+	char *end;
+
+	(void)token;
+	(void)size;
+	if (ctx->curr != ITEM_COMPARE_FIELD_A_LEVEL_VALUE &&
+		ctx->curr != ITEM_COMPARE_FIELD_B_LEVEL_VALUE)
+		return -1;
+	if (!ctx->object)
+		return len;
+	compare_item = ctx->object;
+	errno = 0;
+	val = strtoumax(str, &end, 0);
+	if (errno || (size_t)(end - str) != len)
+		return -1;
+	/* No need to validate action template mask value */
+	if (out->args.vc.masks) {
+		if (ctx->curr == ITEM_COMPARE_FIELD_A_LEVEL_VALUE)
+			compare_item->a.level = val;
+		else
+			compare_item->b.level = val;
+		return len;
+	}
+	if ((ctx->curr == ITEM_COMPARE_FIELD_A_LEVEL_VALUE &&
+		compare_item->a.field == RTE_FLOW_FIELD_FLEX_ITEM) ||
+		(ctx->curr == ITEM_COMPARE_FIELD_B_LEVEL_VALUE &&
+		compare_item->b.field == RTE_FLOW_FIELD_FLEX_ITEM)) {
+		if (val >= FLEX_MAX_PARSERS_NUM) {
+			printf("Bad flex item handle\n");
+			return -1;
+		}
+		fp = flex_items[ctx->port][val];
+		if (!fp) {
+			printf("Bad flex item handle\n");
+			return -1;
+		}
+	}
+	if (ctx->curr == ITEM_COMPARE_FIELD_A_LEVEL_VALUE) {
+		if (compare_item->a.field != RTE_FLOW_FIELD_FLEX_ITEM)
+			compare_item->a.level = val;
+		else
+			compare_item->a.flex_handle = fp->flex_handle;
+	} else if (ctx->curr == ITEM_COMPARE_FIELD_B_LEVEL_VALUE) {
+		if (compare_item->b.field != RTE_FLOW_FIELD_FLEX_ITEM)
+			compare_item->b.level = val;
+		else
+			compare_item->b.flex_handle = fp->flex_handle;
+	}
+	return len;
+}
+
 /** Parse meter color action type. */
 static int
 parse_vc_action_meter_color_type(struct context *ctx, const struct token *token,
@@ -9773,10 +10134,10 @@ parse_vc_modify_field_id(struct context *ctx, const struct token *token,
 	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))
+	for (i = 0; flow_field_ids[i]; ++i)
+		if (!strcmp_partial(flow_field_ids[i], str, len))
 			break;
-	if (!modify_field_ids[i])
+	if (!flow_field_ids[i])
 		return -1;
 	if (!ctx->object)
 		return len;
@@ -11890,6 +12251,39 @@ comp_rule_id(struct context *ctx, const struct token *token,
 	return i;
 }
 
+/** Complete operation for compare match item. */
+static int
+comp_set_compare_op(struct context *ctx, const struct token *token,
+		    unsigned int ent, char *buf, unsigned int size)
+{
+	RTE_SET_USED(ctx);
+	RTE_SET_USED(token);
+	if (!buf)
+		return RTE_DIM(compare_ops);
+	if (ent < RTE_DIM(compare_ops) - 1)
+		return strlcpy(buf, compare_ops[ent], size);
+	return -1;
+}
+
+/** Complete field id for compare match item. */
+static int
+comp_set_compare_field_id(struct context *ctx, const struct token *token,
+			  unsigned int ent, char *buf, unsigned int size)
+{
+	const char *name;
+
+	RTE_SET_USED(token);
+	if (!buf)
+		return RTE_DIM(flow_field_ids);
+	if (ent >= RTE_DIM(flow_field_ids) - 1)
+		return -1;
+	name = flow_field_ids[ent];
+	if (ctx->curr == ITEM_COMPARE_FIELD_B_TYPE ||
+	    (strcmp(name, "pointer") && strcmp(name, "value")))
+		return strlcpy(buf, name, size);
+	return -1;
+}
+
 /** Complete type field for RSS action. */
 static int
 comp_vc_action_rss_type(struct context *ctx, const struct token *token,
@@ -12003,10 +12397,10 @@ comp_set_modify_field_id(struct context *ctx, const struct token *token,
 
 	RTE_SET_USED(token);
 	if (!buf)
-		return RTE_DIM(modify_field_ids);
-	if (ent >= RTE_DIM(modify_field_ids) - 1)
+		return RTE_DIM(flow_field_ids);
+	if (ent >= RTE_DIM(flow_field_ids) - 1)
 		return -1;
-	name = modify_field_ids[ent];
+	name = flow_field_ids[ent];
 	if (ctx->curr == ACTION_MODIFY_FIELD_SRC_TYPE ||
 	    (strcmp(name, "pointer") && strcmp(name, "value")))
 		return strlcpy(buf, name, size);
diff --git a/doc/guides/nics/features/default.ini b/doc/guides/nics/features/default.ini
index 806cb033ff..565338731f 100644
--- a/doc/guides/nics/features/default.ini
+++ b/doc/guides/nics/features/default.ini
@@ -87,6 +87,7 @@ aggr_affinity        =
 ah                   =
 any                  =
 arp_eth_ipv4         =
+compare              =
 conntrack            =
 ecpri                =
 esp                  =
diff --git a/doc/guides/prog_guide/rte_flow.rst b/doc/guides/prog_guide/rte_flow.rst
index bf25c849fb..b720157d18 100644
--- a/doc/guides/prog_guide/rte_flow.rst
+++ b/doc/guides/prog_guide/rte_flow.rst
@@ -1573,6 +1573,13 @@ Matches the packet type as defined in rte_mbuf_ptype.
 
 - ``packet_type``: L2/L3/L4 and tunnel information.
 
+Item: ``COMPARE``
+^^^^^^^^^^^^^^^^^
+
+Matches the comparison result between packet fields or value.
+
+- ``compare``: Comparison information.
+
 Actions
 ~~~~~~~
 
diff --git a/doc/guides/rel_notes/release_24_03.rst b/doc/guides/rel_notes/release_24_03.rst
index 2c0e2930cc..71ebd67dbd 100644
--- a/doc/guides/rel_notes/release_24_03.rst
+++ b/doc/guides/rel_notes/release_24_03.rst
@@ -55,6 +55,11 @@ New Features
      Also, make sure to start the actual text at the margin.
      =======================================================
 
+* **Added compare flow matching criteria.**
+
+  Added ``RTE_FLOW_ITEM_TYPE_COMPARE`` to allow matching on compare
+  result between the packet fields or value.
+
 * **Updated NVIDIA mlx5 driver.**
 
   * Added support for accumulating from src field to dst field.
diff --git a/doc/guides/testpmd_app_ug/testpmd_funcs.rst b/doc/guides/testpmd_app_ug/testpmd_funcs.rst
index 447e28e694..220b396295 100644
--- a/doc/guides/testpmd_app_ug/testpmd_funcs.rst
+++ b/doc/guides/testpmd_app_ug/testpmd_funcs.rst
@@ -3841,6 +3841,12 @@ This section lists supported pattern items and their attributes, if any.
 
         - ``packet_type {unsigned}``: packet type.
 
+- ``compare``: match the comparison result between packet fields or value.
+
+        - ``op {string}``: comparison operation type.
+        - ``a_type {string}``: compared field.
+        - ``b_type {string}``: comparator field.
+        - ``width {unsigned}``: comparison width.
 
 Actions list
 ^^^^^^^^^^^^
diff --git a/lib/ethdev/rte_flow.c b/lib/ethdev/rte_flow.c
index 549e329558..88cf003b2b 100644
--- a/lib/ethdev/rte_flow.c
+++ b/lib/ethdev/rte_flow.c
@@ -167,6 +167,7 @@ static const struct rte_flow_desc_data rte_flow_desc_item[] = {
 	MK_FLOW_ITEM(TX_QUEUE, sizeof(struct rte_flow_item_tx_queue)),
 	MK_FLOW_ITEM(IB_BTH, sizeof(struct rte_flow_item_ib_bth)),
 	MK_FLOW_ITEM(PTYPE, sizeof(struct rte_flow_item_ptype)),
+	MK_FLOW_ITEM(COMPARE, sizeof(struct rte_flow_item_compare)),
 };
 
 /** Generate flow_action[] entry. */
diff --git a/lib/ethdev/rte_flow.h b/lib/ethdev/rte_flow.h
index 40f6dcaacd..8506184a76 100644
--- a/lib/ethdev/rte_flow.h
+++ b/lib/ethdev/rte_flow.h
@@ -704,6 +704,13 @@ enum rte_flow_item_type {
 	 *
 	 */
 	RTE_FLOW_ITEM_TYPE_PTYPE,
+
+	/**
+	 * Matches the packet with compare result.
+	 *
+	 * See struct rte_flow_item_compare.
+	 */
+	RTE_FLOW_ITEM_TYPE_COMPARE,
 };
 
 /**
@@ -2336,6 +2343,177 @@ static const struct rte_flow_item_ptype rte_flow_item_ptype_mask = {
 };
 #endif
 
+/**
+ * Field IDs for packet field.
+ */
+enum rte_flow_field_id {
+	RTE_FLOW_FIELD_START = 0,	/**< Start of a packet. */
+	RTE_FLOW_FIELD_MAC_DST,		/**< Destination MAC Address. */
+	RTE_FLOW_FIELD_MAC_SRC,		/**< Source MAC Address. */
+	RTE_FLOW_FIELD_VLAN_TYPE,	/**< VLAN Tag Identifier. */
+	RTE_FLOW_FIELD_VLAN_ID,		/**< VLAN Identifier. */
+	RTE_FLOW_FIELD_MAC_TYPE,	/**< EtherType. */
+	RTE_FLOW_FIELD_IPV4_DSCP,	/**< IPv4 DSCP. */
+	RTE_FLOW_FIELD_IPV4_TTL,	/**< IPv4 Time To Live. */
+	RTE_FLOW_FIELD_IPV4_SRC,	/**< IPv4 Source Address. */
+	RTE_FLOW_FIELD_IPV4_DST,	/**< IPv4 Destination Address. */
+	RTE_FLOW_FIELD_IPV6_DSCP,	/**< IPv6 DSCP. */
+	RTE_FLOW_FIELD_IPV6_HOPLIMIT,	/**< IPv6 Hop Limit. */
+	RTE_FLOW_FIELD_IPV6_SRC,	/**< IPv6 Source Address. */
+	RTE_FLOW_FIELD_IPV6_DST,	/**< IPv6 Destination Address. */
+	RTE_FLOW_FIELD_TCP_PORT_SRC,	/**< TCP Source Port Number. */
+	RTE_FLOW_FIELD_TCP_PORT_DST,	/**< TCP Destination Port Number. */
+	RTE_FLOW_FIELD_TCP_SEQ_NUM,	/**< TCP Sequence Number. */
+	RTE_FLOW_FIELD_TCP_ACK_NUM,	/**< TCP Acknowledgment Number. */
+	RTE_FLOW_FIELD_TCP_FLAGS,	/**< TCP Flags. */
+	RTE_FLOW_FIELD_UDP_PORT_SRC,	/**< UDP Source Port Number. */
+	RTE_FLOW_FIELD_UDP_PORT_DST,	/**< UDP Destination Port Number. */
+	RTE_FLOW_FIELD_VXLAN_VNI,	/**< VXLAN Network Identifier. */
+	RTE_FLOW_FIELD_GENEVE_VNI,	/**< GENEVE Network Identifier. */
+	RTE_FLOW_FIELD_GTP_TEID,	/**< GTP Tunnel Endpoint Identifier. */
+	RTE_FLOW_FIELD_TAG,		/**< Tag value. */
+	RTE_FLOW_FIELD_MARK,		/**< Mark value. */
+	RTE_FLOW_FIELD_META,		/**< Metadata value. */
+	RTE_FLOW_FIELD_POINTER,		/**< Memory pointer. */
+	RTE_FLOW_FIELD_VALUE,		/**< Immediate value. */
+	RTE_FLOW_FIELD_IPV4_ECN,	/**< IPv4 ECN. */
+	RTE_FLOW_FIELD_IPV6_ECN,	/**< IPv6 ECN. */
+	RTE_FLOW_FIELD_GTP_PSC_QFI,	/**< GTP QFI. */
+	RTE_FLOW_FIELD_METER_COLOR,	/**< Meter color marker. */
+	RTE_FLOW_FIELD_IPV6_PROTO,	/**< IPv6 next header. */
+	RTE_FLOW_FIELD_FLEX_ITEM,	/**< Flex item. */
+	RTE_FLOW_FIELD_HASH_RESULT,	/**< Hash result. */
+	RTE_FLOW_FIELD_GENEVE_OPT_TYPE,	/**< GENEVE option type. */
+	RTE_FLOW_FIELD_GENEVE_OPT_CLASS,/**< GENEVE option class. */
+	RTE_FLOW_FIELD_GENEVE_OPT_DATA,	/**< GENEVE option data. */
+	RTE_FLOW_FIELD_MPLS,		/**< MPLS header. */
+	RTE_FLOW_FIELD_TCP_DATA_OFFSET,	/**< TCP data offset. */
+	RTE_FLOW_FIELD_IPV4_IHL,	/**< IPv4 IHL. */
+	RTE_FLOW_FIELD_IPV4_TOTAL_LEN,	/**< IPv4 total length. */
+	RTE_FLOW_FIELD_IPV6_PAYLOAD_LEN	/**< IPv6 payload length. */
+};
+
+/**
+ * @warning
+ * @b EXPERIMENTAL: this structure may change without prior notice
+ *
+ * Field description for packet field.
+ */
+struct rte_flow_field_data {
+	enum rte_flow_field_id field; /**< Field or memory type ID. */
+	union {
+		struct {
+			/** Encapsulation level and tag index or flex item handle. */
+			union {
+				struct {
+					/**
+					 * Packet encapsulation level containing
+					 * the field to modify.
+					 *
+					 * - @p 0 requests the default behavior.
+					 *   Depending on the packet type, it
+					 *   can mean outermost, innermost or
+					 *   anything in between.
+					 *
+					 *   It basically stands for the
+					 *   innermost encapsulation level.
+					 *   Modification can be performed
+					 *   according to PMD and device
+					 *   capabilities.
+					 *
+					 * - @p 1 requests modification to be
+					 *   performed on the outermost packet
+					 *   encapsulation level.
+					 *
+					 * - @p 2 and subsequent values request
+					 *   modification to be performed on
+					 *   the specified inner packet
+					 *   encapsulation level, from
+					 *   outermost to innermost (lower to
+					 *   higher values).
+					 *
+					 * Values other than @p 0 are not
+					 * necessarily supported.
+					 *
+					 * @note that for MPLS field,
+					 * encapsulation level also include
+					 * tunnel since MPLS may appear in
+					 * outer, inner or tunnel.
+					 */
+					uint8_t level;
+					union {
+						/**
+						 * Tag index array inside
+						 * encapsulation level.
+						 * Used for VLAN, MPLS or TAG types.
+						 */
+						uint8_t tag_index;
+						/**
+						 * Geneve option identifier.
+						 * Relevant only for
+						 * RTE_FLOW_FIELD_GENEVE_OPT_XXXX
+						 * modification type.
+						 */
+						struct {
+							/**
+							 * Geneve option type.
+							 */
+							uint8_t type;
+							/**
+							 * Geneve option class.
+							 */
+							rte_be16_t class_id;
+						};
+					};
+				};
+				struct rte_flow_item_flex_handle *flex_handle;
+			};
+			/** Number of bits to skip from a field. */
+			uint32_t offset;
+		};
+		/**
+		 * Immediate value for RTE_FLOW_FIELD_VALUE, presented in the
+		 * same byte order and length as in relevant rte_flow_item_xxx.
+		 * The immediate source bitfield offset is inherited from
+		 * the destination's one.
+		 */
+		uint8_t value[16];
+		/**
+		 * Memory address for RTE_FLOW_FIELD_POINTER, memory layout
+		 * should be the same as for relevant field in the
+		 * rte_flow_item_xxx structure.
+		 */
+		void *pvalue;
+	};
+};
+
+/**
+ * Expected operation types for compare item.
+ */
+enum rte_flow_item_compare_op {
+	RTE_FLOW_ITEM_COMPARE_EQ,	/* Compare result equal. */
+	RTE_FLOW_ITEM_COMPARE_NE,	/* Compare result not equal. */
+	RTE_FLOW_ITEM_COMPARE_LT,	/* Compare result less than. */
+	RTE_FLOW_ITEM_COMPARE_LE,	/* Compare result less than or equal. */
+	RTE_FLOW_ITEM_COMPARE_GT,	/* Compare result great than. */
+	RTE_FLOW_ITEM_COMPARE_GE,	/* Compare result great than or equal. */
+};
+
+/**
+ *
+ * RTE_FLOW_ITEM_TYPE_COMPARE
+ *
+ * Matches the packet with compare result.
+ *
+ * The operation means a compare with b result.
+ */
+struct rte_flow_item_compare {
+	enum rte_flow_item_compare_op operation; /* The compare operation. */
+	struct rte_flow_field_data a;		 /* Field be compared.  */
+	struct rte_flow_field_data b;		 /* Field as comparator. */
+	uint32_t width;				 /* Compare width. */
+};
+
 /**
  * Action types.
  *
@@ -3856,150 +4034,6 @@ struct rte_flow_action_ethdev {
 	uint16_t port_id; /**< ethdev port ID */
 };
 
-/**
- * Field IDs for MODIFY_FIELD action.
- */
-enum rte_flow_field_id {
-	RTE_FLOW_FIELD_START = 0,	/**< Start of a packet. */
-	RTE_FLOW_FIELD_MAC_DST,		/**< Destination MAC Address. */
-	RTE_FLOW_FIELD_MAC_SRC,		/**< Source MAC Address. */
-	RTE_FLOW_FIELD_VLAN_TYPE,	/**< VLAN Tag Identifier. */
-	RTE_FLOW_FIELD_VLAN_ID,		/**< VLAN Identifier. */
-	RTE_FLOW_FIELD_MAC_TYPE,	/**< EtherType. */
-	RTE_FLOW_FIELD_IPV4_DSCP,	/**< IPv4 DSCP. */
-	RTE_FLOW_FIELD_IPV4_TTL,	/**< IPv4 Time To Live. */
-	RTE_FLOW_FIELD_IPV4_SRC,	/**< IPv4 Source Address. */
-	RTE_FLOW_FIELD_IPV4_DST,	/**< IPv4 Destination Address. */
-	RTE_FLOW_FIELD_IPV6_DSCP,	/**< IPv6 DSCP. */
-	RTE_FLOW_FIELD_IPV6_HOPLIMIT,	/**< IPv6 Hop Limit. */
-	RTE_FLOW_FIELD_IPV6_SRC,	/**< IPv6 Source Address. */
-	RTE_FLOW_FIELD_IPV6_DST,	/**< IPv6 Destination Address. */
-	RTE_FLOW_FIELD_TCP_PORT_SRC,	/**< TCP Source Port Number. */
-	RTE_FLOW_FIELD_TCP_PORT_DST,	/**< TCP Destination Port Number. */
-	RTE_FLOW_FIELD_TCP_SEQ_NUM,	/**< TCP Sequence Number. */
-	RTE_FLOW_FIELD_TCP_ACK_NUM,	/**< TCP Acknowledgment Number. */
-	RTE_FLOW_FIELD_TCP_FLAGS,	/**< TCP Flags. */
-	RTE_FLOW_FIELD_UDP_PORT_SRC,	/**< UDP Source Port Number. */
-	RTE_FLOW_FIELD_UDP_PORT_DST,	/**< UDP Destination Port Number. */
-	RTE_FLOW_FIELD_VXLAN_VNI,	/**< VXLAN Network Identifier. */
-	RTE_FLOW_FIELD_GENEVE_VNI,	/**< GENEVE Network Identifier. */
-	RTE_FLOW_FIELD_GTP_TEID,	/**< GTP Tunnel Endpoint Identifier. */
-	RTE_FLOW_FIELD_TAG,		/**< Tag value. */
-	RTE_FLOW_FIELD_MARK,		/**< Mark value. */
-	RTE_FLOW_FIELD_META,		/**< Metadata value. */
-	RTE_FLOW_FIELD_POINTER,		/**< Memory pointer. */
-	RTE_FLOW_FIELD_VALUE,		/**< Immediate value. */
-	RTE_FLOW_FIELD_IPV4_ECN,	/**< IPv4 ECN. */
-	RTE_FLOW_FIELD_IPV6_ECN,	/**< IPv6 ECN. */
-	RTE_FLOW_FIELD_GTP_PSC_QFI,	/**< GTP QFI. */
-	RTE_FLOW_FIELD_METER_COLOR,	/**< Meter color marker. */
-	RTE_FLOW_FIELD_IPV6_PROTO,	/**< IPv6 next header. */
-	RTE_FLOW_FIELD_FLEX_ITEM,	/**< Flex item. */
-	RTE_FLOW_FIELD_HASH_RESULT,	/**< Hash result. */
-	RTE_FLOW_FIELD_GENEVE_OPT_TYPE,	/**< GENEVE option type. */
-	RTE_FLOW_FIELD_GENEVE_OPT_CLASS,/**< GENEVE option class. */
-	RTE_FLOW_FIELD_GENEVE_OPT_DATA,	/**< GENEVE option data. */
-	RTE_FLOW_FIELD_MPLS,		/**< MPLS header. */
-	RTE_FLOW_FIELD_TCP_DATA_OFFSET,	/**< TCP data offset. */
-	RTE_FLOW_FIELD_IPV4_IHL,	/**< IPv4 IHL. */
-	RTE_FLOW_FIELD_IPV4_TOTAL_LEN,	/**< IPv4 total length. */
-	RTE_FLOW_FIELD_IPV6_PAYLOAD_LEN	/**< IPv6 payload length. */
-};
-
-/**
- * @warning
- * @b EXPERIMENTAL: this structure may change without prior notice
- *
- * Field description for packet field.
- */
-struct rte_flow_field_data {
-	enum rte_flow_field_id field; /**< Field or memory type ID. */
-	union {
-		struct {
-			/** Encapsulation level and tag index or flex item handle. */
-			union {
-				struct {
-					/**
-					 * Packet encapsulation level containing
-					 * the field to modify.
-					 *
-					 * - @p 0 requests the default behavior.
-					 *   Depending on the packet type, it
-					 *   can mean outermost, innermost or
-					 *   anything in between.
-					 *
-					 *   It basically stands for the
-					 *   innermost encapsulation level.
-					 *   Modification can be performed
-					 *   according to PMD and device
-					 *   capabilities.
-					 *
-					 * - @p 1 requests modification to be
-					 *   performed on the outermost packet
-					 *   encapsulation level.
-					 *
-					 * - @p 2 and subsequent values request
-					 *   modification to be performed on
-					 *   the specified inner packet
-					 *   encapsulation level, from
-					 *   outermost to innermost (lower to
-					 *   higher values).
-					 *
-					 * Values other than @p 0 are not
-					 * necessarily supported.
-					 *
-					 * @note that for MPLS field,
-					 * encapsulation level also include
-					 * tunnel since MPLS may appear in
-					 * outer, inner or tunnel.
-					 */
-					uint8_t level;
-					union {
-						/**
-						 * Tag index array inside
-						 * encapsulation level.
-						 * Used for VLAN, MPLS or TAG types.
-						 */
-						uint8_t tag_index;
-						/**
-						 * Geneve option identifier.
-						 * Relevant only for
-						 * RTE_FLOW_FIELD_GENEVE_OPT_XXXX
-						 * modification type.
-						 */
-						struct {
-							/**
-							 * Geneve option type.
-							 */
-							uint8_t type;
-							/**
-							 * Geneve option class.
-							 */
-							rte_be16_t class_id;
-						};
-					};
-				};
-				struct rte_flow_item_flex_handle *flex_handle;
-			};
-			/** Number of bits to skip from a field. */
-			uint32_t offset;
-		};
-		/**
-		 * Immediate value for RTE_FLOW_FIELD_VALUE, presented in the
-		 * same byte order and length as in relevant rte_flow_item_xxx.
-		 * The immediate source bitfield offset is inherited from
-		 * the destination's one.
-		 */
-		uint8_t value[16];
-		/**
-		 * Memory address for RTE_FLOW_FIELD_POINTER, memory layout
-		 * should be the same as for relevant field in the
-		 * rte_flow_item_xxx structure.
-		 */
-		void *pvalue;
-	};
-};
-
 /**
  * Operation types for MODIFY_FIELD action.
  */
-- 
2.34.1


^ permalink raw reply	[flat|nested] 66+ messages in thread

* [PATCH v2 3/3] net/mlx5: add compare item support
  2023-12-19  1:33 ` [PATCH v2 0/3] [PATCH 0/2] ethdev: add RTE_FLOW_ITEM_TYPE_COMPARE Suanming Mou
  2023-12-19  1:33   ` [PATCH v2 1/3] ethdev: rename action modify field data structure Suanming Mou
  2023-12-19  1:33   ` [PATCH v2 2/3] ethdev: add compare item Suanming Mou
@ 2023-12-19  1:33   ` Suanming Mou
  2024-01-09 14:28     ` Ori Kam
  2024-01-15  9:13   ` [PATCH v3 0/3] ethdev: add RTE_FLOW_ITEM_TYPE_COMPARE Suanming Mou
  3 siblings, 1 reply; 66+ messages in thread
From: Suanming Mou @ 2023-12-19  1:33 UTC (permalink / raw)
  To: Dariusz Sosnowski, Viacheslav Ovsiienko, Ori Kam, Matan Azrad; +Cc: dev

The compare item allows adding flow match with comparison
result. This commit adds compare item support to the PMD
code.

Due to HW limitation:
 - Only HWS supported.
 - Only 32-bit comparison is supported.
 - Only single compare flow is supported in the flow table.
 - Only match with compare result between packet fields is
    supported.

Signed-off-by: Suanming Mou <suanmingm@nvidia.com>
---
 doc/guides/nics/features/mlx5.ini      |  1 +
 doc/guides/nics/mlx5.rst               |  7 +++
 doc/guides/rel_notes/release_24_03.rst |  2 +-
 drivers/net/mlx5/mlx5_flow.h           |  3 ++
 drivers/net/mlx5/mlx5_flow_hw.c        | 73 ++++++++++++++++++++++++++
 5 files changed, 85 insertions(+), 1 deletion(-)

diff --git a/doc/guides/nics/features/mlx5.ini b/doc/guides/nics/features/mlx5.ini
index 0739fe9d63..00e9348fc6 100644
--- a/doc/guides/nics/features/mlx5.ini
+++ b/doc/guides/nics/features/mlx5.ini
@@ -56,6 +56,7 @@ Usage doc            = Y
 
 [rte_flow items]
 aggr_affinity        = Y
+compare              = Y
 conntrack            = Y
 ecpri                = Y
 esp                  = Y
diff --git a/doc/guides/nics/mlx5.rst b/doc/guides/nics/mlx5.rst
index 6b52fb93c5..18b40bc22d 100644
--- a/doc/guides/nics/mlx5.rst
+++ b/doc/guides/nics/mlx5.rst
@@ -778,6 +778,13 @@ Limitations
   The flow engine of a process cannot move from active to standby mode
   if preceding active application rules are still present and vice versa.
 
+- Match with compare result item (``RTE_FLOW_ITEM_TYPE_COMPARE``):
+
+  - Only supported in HW steering(``dv_flow_en`` = 2) mode.
+  - Only single flow is supported to the flow table.
+  - Only 32-bit comparison is supported.
+  - Only match with compare result between packet fields is supported.
+
 
 Statistics
 ----------
diff --git a/doc/guides/rel_notes/release_24_03.rst b/doc/guides/rel_notes/release_24_03.rst
index 71ebd67dbd..5693ea4628 100644
--- a/doc/guides/rel_notes/release_24_03.rst
+++ b/doc/guides/rel_notes/release_24_03.rst
@@ -63,7 +63,7 @@ New Features
 * **Updated NVIDIA mlx5 driver.**
 
   * Added support for accumulating from src field to dst field.
-
+  * Added support for comparing result between packet fields or value.
 
 Removed Items
 -------------
diff --git a/drivers/net/mlx5/mlx5_flow.h b/drivers/net/mlx5/mlx5_flow.h
index 8e2034473c..6698de2a3e 100644
--- a/drivers/net/mlx5/mlx5_flow.h
+++ b/drivers/net/mlx5/mlx5_flow.h
@@ -277,6 +277,9 @@ enum mlx5_feature_name {
 /* NSH ITEM */
 #define MLX5_FLOW_ITEM_NSH (1ull << 53)
 
+/* COMPARE ITEM */
+#define MLX5_FLOW_ITEM_COMPARE (1ull << 54)
+
 /* Outer Masks. */
 #define MLX5_FLOW_LAYER_OUTER_L3 \
 	(MLX5_FLOW_LAYER_OUTER_L3_IPV4 | MLX5_FLOW_LAYER_OUTER_L3_IPV6)
diff --git a/drivers/net/mlx5/mlx5_flow_hw.c b/drivers/net/mlx5/mlx5_flow_hw.c
index c4a90a3690..82d7fa006f 100644
--- a/drivers/net/mlx5/mlx5_flow_hw.c
+++ b/drivers/net/mlx5/mlx5_flow_hw.c
@@ -426,6 +426,9 @@ flow_hw_matching_item_flags_get(const struct rte_flow_item items[])
 		case RTE_FLOW_ITEM_TYPE_GTP:
 			last_item = MLX5_FLOW_LAYER_GTP;
 			break;
+		case RTE_FLOW_ITEM_TYPE_COMPARE:
+			last_item = MLX5_FLOW_ITEM_COMPARE;
+			break;
 		default:
 			break;
 		}
@@ -4390,6 +4393,8 @@ flow_hw_table_create(struct rte_eth_dev *dev,
 			rte_errno = EINVAL;
 			goto it_error;
 		}
+		if (item_templates[i]->item_flags & MLX5_FLOW_ITEM_COMPARE)
+			matcher_attr.mode = MLX5DR_MATCHER_RESOURCE_MODE_HTABLE;
 		ret = __atomic_fetch_add(&item_templates[i]->refcnt, 1,
 					 __ATOMIC_RELAXED) + 1;
 		if (ret <= 1) {
@@ -6670,6 +6675,66 @@ flow_hw_prepend_item(const struct rte_flow_item *items,
 	return copied_items;
 }
 
+static inline bool
+flow_hw_item_compare_field_supported(enum rte_flow_field_id field)
+{
+	switch (field) {
+	case RTE_FLOW_FIELD_TAG:
+	case RTE_FLOW_FIELD_META:
+	case RTE_FLOW_FIELD_VALUE:
+		return true;
+	default:
+		break;
+	}
+	return false;
+}
+
+static int
+flow_hw_validate_item_compare(const struct rte_flow_item *item,
+			      struct rte_flow_error *error)
+{
+	const struct rte_flow_item_compare *comp_m = item->mask;
+	const struct rte_flow_item_compare *comp_v = item->spec;
+
+	if (unlikely(!comp_m))
+		return rte_flow_error_set(error, EINVAL,
+				   RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
+				   NULL,
+				   "compare item mask is missing");
+	if (comp_m->width != UINT32_MAX)
+		return rte_flow_error_set(error, EINVAL,
+				   RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
+				   NULL,
+				   "compare item only support full mask");
+	if (!flow_hw_item_compare_field_supported(comp_m->a.field) ||
+	    !flow_hw_item_compare_field_supported(comp_m->b.field))
+		return rte_flow_error_set(error, ENOTSUP,
+				   RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
+				   NULL,
+				   "compare item field not support");
+	if (comp_m->a.field == RTE_FLOW_FIELD_VALUE &&
+	    comp_m->b.field == RTE_FLOW_FIELD_VALUE)
+		return rte_flow_error_set(error, EINVAL,
+				   RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
+				   NULL,
+				   "compare between value is not valid");
+	if (comp_v) {
+		if (comp_v->operation != comp_m->operation ||
+		    comp_v->a.field != comp_m->a.field ||
+		    comp_v->b.field != comp_m->b.field)
+			return rte_flow_error_set(error, EINVAL,
+					   RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
+					   NULL,
+					   "compare item spec/mask not matching");
+		if ((comp_v->width & comp_m->width) != 32)
+			return rte_flow_error_set(error, EINVAL,
+					   RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
+					   NULL,
+					   "compare item only support full mask");
+	}
+	return 0;
+}
+
 static int
 flow_hw_pattern_validate(struct rte_eth_dev *dev,
 			 const struct rte_flow_pattern_template_attr *attr,
@@ -6680,6 +6745,7 @@ flow_hw_pattern_validate(struct rte_eth_dev *dev,
 	int i, tag_idx;
 	bool items_end = false;
 	uint32_t tag_bitmap = 0;
+	int ret;
 
 	if (!attr->ingress && !attr->egress && !attr->transfer)
 		return rte_flow_error_set(error, EINVAL, RTE_FLOW_ERROR_TYPE_ATTR, NULL,
@@ -6817,6 +6883,13 @@ flow_hw_pattern_validate(struct rte_eth_dev *dev,
 							  " attribute");
 			break;
 		}
+		case RTE_FLOW_ITEM_TYPE_COMPARE:
+		{
+			ret = flow_hw_validate_item_compare(&items[i], error);
+			if (ret)
+				return ret;
+			break;
+		}
 		case RTE_FLOW_ITEM_TYPE_VOID:
 		case RTE_FLOW_ITEM_TYPE_ETH:
 		case RTE_FLOW_ITEM_TYPE_VLAN:
-- 
2.34.1


^ permalink raw reply	[flat|nested] 66+ messages in thread

* RE: [PATCH v2 1/3] ethdev: rename action modify field data structure
  2023-12-19  1:33   ` [PATCH v2 1/3] ethdev: rename action modify field data structure Suanming Mou
@ 2024-01-09 14:07     ` Ori Kam
  2024-01-12  8:03       ` Andrew Rybchenko
  0 siblings, 1 reply; 66+ messages in thread
From: Ori Kam @ 2024-01-09 14:07 UTC (permalink / raw)
  To: Suanming Mou, Aman Singh, Yuying Zhang, Dariusz Sosnowski,
	Slava Ovsiienko, Matan Azrad,
	NBU-Contact-Thomas Monjalon (EXTERNAL),
	Ferruh Yigit, Andrew Rybchenko
  Cc: dev



> -----Original Message-----
> From: Suanming Mou <suanmingm@nvidia.com>
> Sent: Tuesday, December 19, 2023 3:34 AM
> 
> Current rte_flow_action_modify_data struct describes the pkt
> field perfectly and is used only in action.
> 
> It is planned to be used for item as well. This commit renames
> it to "rte_flow_field_data" making it compatible to be used by item.
> 
> Signed-off-by: Suanming Mou <suanmingm@nvidia.com>
> ---

Acked-by: Ori Kam <orika@nvidia.com>
Best,
Ori


^ permalink raw reply	[flat|nested] 66+ messages in thread

* RE: [PATCH v2 2/3] ethdev: add compare item
  2023-12-19  1:33   ` [PATCH v2 2/3] ethdev: add compare item Suanming Mou
@ 2024-01-09 14:26     ` Ori Kam
  2024-01-12  8:11     ` Andrew Rybchenko
  1 sibling, 0 replies; 66+ messages in thread
From: Ori Kam @ 2024-01-09 14:26 UTC (permalink / raw)
  To: Suanming Mou, Aman Singh, Yuying Zhang,
	NBU-Contact-Thomas Monjalon (EXTERNAL),
	Ferruh Yigit, Andrew Rybchenko
  Cc: dev



> -----Original Message-----
> From: Suanming Mou <suanmingm@nvidia.com>
> Sent: Tuesday, December 19, 2023 3:34 AM
> 
> The new item type is added for the case user wants to match traffic
> based on packet field compare result with other fields or immediate
> value.
> 
> e.g. take advantage the compare item user will be able to accumulate
> a IPv4/TCP packet's TCP data_offset and IPv4 IHL field to a tag
> register, then compare the tag register with IPv4 header total length
> to understand the packet has payload or not.
> 
> The supported operations can be as below:
>  - RTE_FLOW_ITEM_COMPARE_EQ (equal)
>  - RTE_FLOW_ITEM_COMPARE_NE (not equal)
>  - RTE_FLOW_ITEM_COMPARE_LT (less than)
>  - RTE_FLOW_ITEM_COMPARE_LE (less than or equal)
>  - RTE_FLOW_ITEM_COMPARE_GT (great than)
>  - RTE_FLOW_ITEM_COMPARE_GE (great than or equal)
> 
> Signed-off-by: Suanming Mou <suanmingm@nvidia.com>
> ---

Acked-by: Ori Kam <orika@nvidia.com>
Best,
Ori

^ permalink raw reply	[flat|nested] 66+ messages in thread

* RE: [PATCH v2 3/3] net/mlx5: add compare item support
  2023-12-19  1:33   ` [PATCH v2 3/3] net/mlx5: add compare item support Suanming Mou
@ 2024-01-09 14:28     ` Ori Kam
  0 siblings, 0 replies; 66+ messages in thread
From: Ori Kam @ 2024-01-09 14:28 UTC (permalink / raw)
  To: Suanming Mou, Dariusz Sosnowski, Slava Ovsiienko, Matan Azrad; +Cc: dev



> -----Original Message-----
> From: Suanming Mou <suanmingm@nvidia.com>
> Sent: Tuesday, December 19, 2023 3:34 AM
> The compare item allows adding flow match with comparison
> result. This commit adds compare item support to the PMD
> code.
> 
> Due to HW limitation:
>  - Only HWS supported.
>  - Only 32-bit comparison is supported.
>  - Only single compare flow is supported in the flow table.
>  - Only match with compare result between packet fields is
>     supported.
> 
> Signed-off-by: Suanming Mou <suanmingm@nvidia.com>
> ---

Acked-by: Ori Kam <orika@nvidia.com>
Best
Ori

^ permalink raw reply	[flat|nested] 66+ messages in thread

* Re: [PATCH v2 1/3] ethdev: rename action modify field data structure
  2024-01-09 14:07     ` Ori Kam
@ 2024-01-12  8:03       ` Andrew Rybchenko
  0 siblings, 0 replies; 66+ messages in thread
From: Andrew Rybchenko @ 2024-01-12  8:03 UTC (permalink / raw)
  To: Ori Kam, Suanming Mou, Aman Singh, Yuying Zhang,
	Dariusz Sosnowski, Slava Ovsiienko, Matan Azrad,
	NBU-Contact-Thomas Monjalon (EXTERNAL),
	Ferruh Yigit
  Cc: dev

On 1/9/24 17:07, Ori Kam wrote:
> 
> 
>> -----Original Message-----
>> From: Suanming Mou <suanmingm@nvidia.com>
>> Sent: Tuesday, December 19, 2023 3:34 AM
>>
>> Current rte_flow_action_modify_data struct describes the pkt
>> field perfectly and is used only in action.
>>
>> It is planned to be used for item as well. This commit renames
>> it to "rte_flow_field_data" making it compatible to be used by item.
>>
>> Signed-off-by: Suanming Mou <suanmingm@nvidia.com>
>> ---
> 
> Acked-by: Ori Kam <orika@nvidia.com>
> Best,
> Ori
> 

Acked-by: Andrew Rybchenko <andrew.rybchenko@oktetlabs.ru>


^ permalink raw reply	[flat|nested] 66+ messages in thread

* Re: [PATCH v2 2/3] ethdev: add compare item
  2023-12-19  1:33   ` [PATCH v2 2/3] ethdev: add compare item Suanming Mou
  2024-01-09 14:26     ` Ori Kam
@ 2024-01-12  8:11     ` Andrew Rybchenko
  2024-01-15  8:14       ` Suanming Mou
  1 sibling, 1 reply; 66+ messages in thread
From: Andrew Rybchenko @ 2024-01-12  8:11 UTC (permalink / raw)
  To: Suanming Mou, Ori Kam, Aman Singh, Yuying Zhang, Thomas Monjalon,
	Ferruh Yigit
  Cc: dev

On 12/19/23 04:33, Suanming Mou wrote:
> The new item type is added for the case user wants to match traffic
> based on packet field compare result with other fields or immediate
> value.
> 
> e.g. take advantage the compare item user will be able to accumulate
> a IPv4/TCP packet's TCP data_offset and IPv4 IHL field to a tag
> register, then compare the tag register with IPv4 header total length
> to understand the packet has payload or not.
> 
> The supported operations can be as below:
>   - RTE_FLOW_ITEM_COMPARE_EQ (equal)
>   - RTE_FLOW_ITEM_COMPARE_NE (not equal)
>   - RTE_FLOW_ITEM_COMPARE_LT (less than)
>   - RTE_FLOW_ITEM_COMPARE_LE (less than or equal)
>   - RTE_FLOW_ITEM_COMPARE_GT (great than)
>   - RTE_FLOW_ITEM_COMPARE_GE (great than or equal)
> 
> Signed-off-by: Suanming Mou <suanmingm@nvidia.com>

Just one nit below, anyway
Acked-by: Andrew Rybchenko <andrew.rybchenko@oktetlabs.ru>

I dislike that many line of code are moved, but it looks like
it is better than keeping them in place and break order in the
file.

> diff --git a/doc/guides/testpmd_app_ug/testpmd_funcs.rst b/doc/guides/testpmd_app_ug/testpmd_funcs.rst
> index 447e28e694..220b396295 100644
> --- a/doc/guides/testpmd_app_ug/testpmd_funcs.rst
> +++ b/doc/guides/testpmd_app_ug/testpmd_funcs.rst
> @@ -3841,6 +3841,12 @@ This section lists supported pattern items and their attributes, if any.
>   
>           - ``packet_type {unsigned}``: packet type.
>   
> +- ``compare``: match the comparison result between packet fields or value.
> +
> +        - ``op {string}``: comparison operation type.
> +        - ``a_type {string}``: compared field.
> +        - ``b_type {string}``: comparator field.
> +        - ``width {unsigned}``: comparison width.

Missing one more empty line before the next section.

>   
>   Actions list
>   ^^^^^^^^^^^^

[snip]


^ permalink raw reply	[flat|nested] 66+ messages in thread

* RE: [PATCH v2 2/3] ethdev: add compare item
  2024-01-12  8:11     ` Andrew Rybchenko
@ 2024-01-15  8:14       ` Suanming Mou
  0 siblings, 0 replies; 66+ messages in thread
From: Suanming Mou @ 2024-01-15  8:14 UTC (permalink / raw)
  To: Andrew Rybchenko, Ori Kam, Aman Singh, Yuying Zhang,
	NBU-Contact-Thomas Monjalon (EXTERNAL),
	Ferruh Yigit
  Cc: dev

Hi,

> -----Original Message-----
> From: Andrew Rybchenko <andrew.rybchenko@oktetlabs.ru>
> Sent: Friday, January 12, 2024 4:11 PM
> To: Suanming Mou <suanmingm@nvidia.com>; Ori Kam <orika@nvidia.com>;
> Aman Singh <aman.deep.singh@intel.com>; Yuying Zhang
> <yuying.zhang@intel.com>; NBU-Contact-Thomas Monjalon (EXTERNAL)
> <thomas@monjalon.net>; Ferruh Yigit <ferruh.yigit@amd.com>
> Cc: dev@dpdk.org
> Subject: Re: [PATCH v2 2/3] ethdev: add compare item
> 
> On 12/19/23 04:33, Suanming Mou wrote:
> > The new item type is added for the case user wants to match traffic
> > based on packet field compare result with other fields or immediate
> > value.
> >
> > e.g. take advantage the compare item user will be able to accumulate a
> > IPv4/TCP packet's TCP data_offset and IPv4 IHL field to a tag
> > register, then compare the tag register with IPv4 header total length
> > to understand the packet has payload or not.
> >
> > The supported operations can be as below:
> >   - RTE_FLOW_ITEM_COMPARE_EQ (equal)
> >   - RTE_FLOW_ITEM_COMPARE_NE (not equal)
> >   - RTE_FLOW_ITEM_COMPARE_LT (less than)
> >   - RTE_FLOW_ITEM_COMPARE_LE (less than or equal)
> >   - RTE_FLOW_ITEM_COMPARE_GT (great than)
> >   - RTE_FLOW_ITEM_COMPARE_GE (great than or equal)
> >
> > Signed-off-by: Suanming Mou <suanmingm@nvidia.com>
> 
> Just one nit below, anyway
> Acked-by: Andrew Rybchenko <andrew.rybchenko@oktetlabs.ru>
> 
> I dislike that many line of code are moved, but it looks like it is better than keeping
> them in place and break order in the file.

These only change once but will keep the file be clean for the coming days.
Anyway, if there are others suggest that as well, I will change. Thanks.

> 
> > diff --git a/doc/guides/testpmd_app_ug/testpmd_funcs.rst
> > b/doc/guides/testpmd_app_ug/testpmd_funcs.rst
> > index 447e28e694..220b396295 100644
> > --- a/doc/guides/testpmd_app_ug/testpmd_funcs.rst
> > +++ b/doc/guides/testpmd_app_ug/testpmd_funcs.rst
> > @@ -3841,6 +3841,12 @@ This section lists supported pattern items and their
> attributes, if any.
> >
> >           - ``packet_type {unsigned}``: packet type.
> >
> > +- ``compare``: match the comparison result between packet fields or value.
> > +
> > +        - ``op {string}``: comparison operation type.
> > +        - ``a_type {string}``: compared field.
> > +        - ``b_type {string}``: comparator field.
> > +        - ``width {unsigned}``: comparison width.
> 
> Missing one more empty line before the next section.

Thanks, will update.

> 
> >
> >   Actions list
> >   ^^^^^^^^^^^^
> 
> [snip]


^ permalink raw reply	[flat|nested] 66+ messages in thread

* [PATCH v3 0/3] ethdev: add RTE_FLOW_ITEM_TYPE_COMPARE
  2023-12-19  1:33 ` [PATCH v2 0/3] [PATCH 0/2] ethdev: add RTE_FLOW_ITEM_TYPE_COMPARE Suanming Mou
                     ` (2 preceding siblings ...)
  2023-12-19  1:33   ` [PATCH v2 3/3] net/mlx5: add compare item support Suanming Mou
@ 2024-01-15  9:13   ` Suanming Mou
  2024-01-15  9:13     ` [PATCH v3 1/3] ethdev: rename action modify field data structure Suanming Mou
                       ` (2 more replies)
  3 siblings, 3 replies; 66+ messages in thread
From: Suanming Mou @ 2024-01-15  9:13 UTC (permalink / raw)
  To: orika; +Cc: dev

The new item type is added for the case user wants to match traffic
based on packet field compare result with other fields or immediate
value.

e.g. take advantage the compare item user will be able to accumulate
a IPv4/TCP packet's TCP data_offset and IPv4 IHL field to a tag
register, then compare the tag register with IPv4 header total length
to understand the packet has payload or not.

The supported operations can be as below:
 - RTE_FLOW_ITEM_COMPARE_EQ (equal)
 - RTE_FLOW_ITEM_COMPARE_NE (not equal)
 - RTE_FLOW_ITEM_COMPARE_LT (less than)
 - RTE_FLOW_ITEM_COMPARE_LE (less than or equal)
 - RTE_FLOW_ITEM_COMPARE_GT (great than)
 - RTE_FLOW_ITEM_COMPARE_GE (great than or equal)

V3:
 - fix code style missing empty line in rte_flow.rst.
 - fix missing the ABI change release notes.

V2:
 - Since modify field data struct is experiment, rename modify
   field data directly instead of adding new flow field struct.

Suanming Mou (3):
  ethdev: rename action modify field data structure
  ethdev: add compare item
  net/mlx5: add compare item support

 app/test-pmd/cmdline_flow.c                 | 416 +++++++++++++++++++-
 doc/guides/nics/features/default.ini        |   1 +
 doc/guides/nics/features/mlx5.ini           |   1 +
 doc/guides/nics/mlx5.rst                    |   7 +
 doc/guides/prog_guide/rte_flow.rst          |   9 +-
 doc/guides/rel_notes/release_24_03.rst      |   8 +-
 doc/guides/testpmd_app_ug/testpmd_funcs.rst |   7 +
 drivers/net/mlx5/mlx5_flow.c                |   4 +-
 drivers/net/mlx5/mlx5_flow.h                |   9 +-
 drivers/net/mlx5/mlx5_flow_dv.c             |  10 +-
 drivers/net/mlx5/mlx5_flow_hw.c             |  73 ++++
 lib/ethdev/rte_flow.c                       |   1 +
 lib/ethdev/rte_flow.h                       | 326 ++++++++-------
 13 files changed, 703 insertions(+), 169 deletions(-)

-- 
2.34.1


^ permalink raw reply	[flat|nested] 66+ messages in thread

* [PATCH v3 1/3] ethdev: rename action modify field data structure
  2024-01-15  9:13   ` [PATCH v3 0/3] ethdev: add RTE_FLOW_ITEM_TYPE_COMPARE Suanming Mou
@ 2024-01-15  9:13     ` Suanming Mou
  2024-01-30 17:19       ` Ferruh Yigit
  2024-01-15  9:13     ` [PATCH v3 2/3] ethdev: add compare item Suanming Mou
  2024-01-15  9:13     ` [PATCH v3 3/3] net/mlx5: add compare item support Suanming Mou
  2 siblings, 1 reply; 66+ messages in thread
From: Suanming Mou @ 2024-01-15  9:13 UTC (permalink / raw)
  To: orika, Aman Singh, Yuying Zhang, Dariusz Sosnowski,
	Viacheslav Ovsiienko, Matan Azrad, Thomas Monjalon, Ferruh Yigit,
	Andrew Rybchenko
  Cc: dev

Current rte_flow_action_modify_data struct describes the pkt
field perfectly and is used only in action.

It is planned to be used for item as well. This commit renames
it to "rte_flow_field_data" making it compatible to be used by item.

Signed-off-by: Suanming Mou <suanmingm@nvidia.com>
Acked-by: Ori Kam <orika@nvidia.com>
Acked-by: Andrew Rybchenko <andrew.rybchenko@oktetlabs.ru>
---
 app/test-pmd/cmdline_flow.c            |  2 +-
 doc/guides/prog_guide/rte_flow.rst     |  2 +-
 doc/guides/rel_notes/release_24_03.rst |  1 +
 drivers/net/mlx5/mlx5_flow.c           |  4 ++--
 drivers/net/mlx5/mlx5_flow.h           |  6 +++---
 drivers/net/mlx5/mlx5_flow_dv.c        | 10 +++++-----
 lib/ethdev/rte_flow.h                  |  8 ++++----
 7 files changed, 17 insertions(+), 16 deletions(-)

diff --git a/app/test-pmd/cmdline_flow.c b/app/test-pmd/cmdline_flow.c
index ce71818705..3725e955c7 100644
--- a/app/test-pmd/cmdline_flow.c
+++ b/app/test-pmd/cmdline_flow.c
@@ -740,7 +740,7 @@ enum index {
 #define ITEM_RAW_SIZE \
 	(sizeof(struct rte_flow_item_raw) + ITEM_RAW_PATTERN_SIZE)
 
-/** Maximum size for external pattern in struct rte_flow_action_modify_data. */
+/** Maximum size for external pattern in struct rte_flow_field_data. */
 #define ACTION_MODIFY_PATTERN_SIZE 32
 
 /** Storage size for struct rte_flow_action_modify_field including pattern. */
diff --git a/doc/guides/prog_guide/rte_flow.rst b/doc/guides/prog_guide/rte_flow.rst
index 627b845bfb..bf25c849fb 100644
--- a/doc/guides/prog_guide/rte_flow.rst
+++ b/doc/guides/prog_guide/rte_flow.rst
@@ -3171,7 +3171,7 @@ destination offset as ``48``, and provide immediate value ``0xXXXX85XX``.
    | ``width``     | number of bits to use   |
    +---------------+-------------------------+
 
-.. _table_rte_flow_action_modify_data:
+.. _table_rte_flow_field_data:
 
 .. table:: destination/source field definition
 
diff --git a/doc/guides/rel_notes/release_24_03.rst b/doc/guides/rel_notes/release_24_03.rst
index 2c0e2930cc..a691e794f4 100644
--- a/doc/guides/rel_notes/release_24_03.rst
+++ b/doc/guides/rel_notes/release_24_03.rst
@@ -106,6 +106,7 @@ ABI Changes
 
 * No ABI change that would break compatibility with 23.11.
 
+* ethdev: Rename the experimental ``struct rte_flow_action_modify_data`` to be ``struct rte_flow_field_data``
 
 Known Issues
 ------------
diff --git a/drivers/net/mlx5/mlx5_flow.c b/drivers/net/mlx5/mlx5_flow.c
index 85e8c77c81..5788a7fb57 100644
--- a/drivers/net/mlx5/mlx5_flow.c
+++ b/drivers/net/mlx5/mlx5_flow.c
@@ -2493,7 +2493,7 @@ mlx5_validate_action_ct(struct rte_eth_dev *dev,
  * Validate the level value for modify field action.
  *
  * @param[in] data
- *   Pointer to the rte_flow_action_modify_data structure either src or dst.
+ *   Pointer to the rte_flow_field_data structure either src or dst.
  * @param[out] error
  *   Pointer to error structure.
  *
@@ -2501,7 +2501,7 @@ mlx5_validate_action_ct(struct rte_eth_dev *dev,
  *   0 on success, a negative errno value otherwise and rte_errno is set.
  */
 int
-flow_validate_modify_field_level(const struct rte_flow_action_modify_data *data,
+flow_validate_modify_field_level(const struct rte_flow_field_data *data,
 				 struct rte_flow_error *error)
 {
 	if (data->level == 0)
diff --git a/drivers/net/mlx5/mlx5_flow.h b/drivers/net/mlx5/mlx5_flow.h
index 120609c595..8e2034473c 100644
--- a/drivers/net/mlx5/mlx5_flow.h
+++ b/drivers/net/mlx5/mlx5_flow.h
@@ -1121,7 +1121,7 @@ flow_items_to_tunnel(const struct rte_flow_item items[])
  *   Tag array index.
  */
 static inline uint8_t
-flow_tag_index_get(const struct rte_flow_action_modify_data *data)
+flow_tag_index_get(const struct rte_flow_field_data *data)
 {
 	return data->tag_index ? data->tag_index : data->level;
 }
@@ -2523,7 +2523,7 @@ int mlx5_flow_validate_action_default_miss(uint64_t action_flags,
 				const struct rte_flow_attr *attr,
 				struct rte_flow_error *error);
 int flow_validate_modify_field_level
-			(const struct rte_flow_action_modify_data *data,
+			(const struct rte_flow_field_data *data,
 			 struct rte_flow_error *error);
 int mlx5_flow_item_acceptable(const struct rte_flow_item *item,
 			      const uint8_t *mask,
@@ -2828,7 +2828,7 @@ size_t flow_dv_get_item_hdr_len(const enum rte_flow_item_type item_type);
 int flow_dv_convert_encap_data(const struct rte_flow_item *items, uint8_t *buf,
 			   size_t *size, struct rte_flow_error *error);
 void mlx5_flow_field_id_to_modify_info
-		(const struct rte_flow_action_modify_data *data,
+		(const struct rte_flow_field_data *data,
 		 struct field_modify_info *info, uint32_t *mask,
 		 uint32_t width, struct rte_eth_dev *dev,
 		 const struct rte_flow_attr *attr, struct rte_flow_error *error);
diff --git a/drivers/net/mlx5/mlx5_flow_dv.c b/drivers/net/mlx5/mlx5_flow_dv.c
index 97f55003c3..e4bfcc76f7 100644
--- a/drivers/net/mlx5/mlx5_flow_dv.c
+++ b/drivers/net/mlx5/mlx5_flow_dv.c
@@ -1446,7 +1446,7 @@ flow_modify_info_mask_32_masked(uint32_t length, uint32_t off, uint32_t post_mas
 }
 
 static __rte_always_inline enum mlx5_modification_field
-mlx5_mpls_modi_field_get(const struct rte_flow_action_modify_data *data)
+mlx5_mpls_modi_field_get(const struct rte_flow_field_data *data)
 {
 	return MLX5_MODI_IN_MPLS_LABEL_0 + data->tag_index;
 }
@@ -1454,7 +1454,7 @@ mlx5_mpls_modi_field_get(const struct rte_flow_action_modify_data *data)
 static void
 mlx5_modify_flex_item(const struct rte_eth_dev *dev,
 		      const struct mlx5_flex_item *flex,
-		      const struct rte_flow_action_modify_data *data,
+		      const struct rte_flow_field_data *data,
 		      struct field_modify_info *info,
 		      uint32_t *mask, uint32_t width)
 {
@@ -1578,7 +1578,7 @@ mlx5_modify_flex_item(const struct rte_eth_dev *dev,
 
 void
 mlx5_flow_field_id_to_modify_info
-		(const struct rte_flow_action_modify_data *data,
+		(const struct rte_flow_field_data *data,
 		 struct field_modify_info *info, uint32_t *mask,
 		 uint32_t width, struct rte_eth_dev *dev,
 		 const struct rte_flow_attr *attr, struct rte_flow_error *error)
@@ -5329,8 +5329,8 @@ flow_dv_validate_action_modify_field(struct rte_eth_dev *dev,
 	struct mlx5_sh_config *config = &priv->sh->config;
 	struct mlx5_hca_attr *hca_attr = &priv->sh->cdev->config.hca_attr;
 	const struct rte_flow_action_modify_field *conf = action->conf;
-	const struct rte_flow_action_modify_data *src_data = &conf->src;
-	const struct rte_flow_action_modify_data *dst_data = &conf->dst;
+	const struct rte_flow_field_data *src_data = &conf->src;
+	const struct rte_flow_field_data *dst_data = &conf->dst;
 	uint32_t dst_width, src_width, width = conf->width;
 
 	ret = flow_dv_validate_action_modify_hdr(action_flags, action, error);
diff --git a/lib/ethdev/rte_flow.h b/lib/ethdev/rte_flow.h
index affdc8121b..40f6dcaacd 100644
--- a/lib/ethdev/rte_flow.h
+++ b/lib/ethdev/rte_flow.h
@@ -3910,9 +3910,9 @@ enum rte_flow_field_id {
  * @warning
  * @b EXPERIMENTAL: this structure may change without prior notice
  *
- * Field description for MODIFY_FIELD action.
+ * Field description for packet field.
  */
-struct rte_flow_action_modify_data {
+struct rte_flow_field_data {
 	enum rte_flow_field_id field; /**< Field or memory type ID. */
 	union {
 		struct {
@@ -4021,8 +4021,8 @@ enum rte_flow_modify_op {
  */
 struct rte_flow_action_modify_field {
 	enum rte_flow_modify_op operation; /**< Operation to perform. */
-	struct rte_flow_action_modify_data dst; /**< Destination field. */
-	struct rte_flow_action_modify_data src; /**< Source field. */
+	struct rte_flow_field_data dst; /**< Destination field. */
+	struct rte_flow_field_data src; /**< Source field. */
 	uint32_t width; /**< Number of bits to use from a source field. */
 };
 
-- 
2.34.1


^ permalink raw reply	[flat|nested] 66+ messages in thread

* [PATCH v3 2/3] ethdev: add compare item
  2024-01-15  9:13   ` [PATCH v3 0/3] ethdev: add RTE_FLOW_ITEM_TYPE_COMPARE Suanming Mou
  2024-01-15  9:13     ` [PATCH v3 1/3] ethdev: rename action modify field data structure Suanming Mou
@ 2024-01-15  9:13     ` Suanming Mou
  2024-01-30 17:33       ` Ferruh Yigit
  2024-01-15  9:13     ` [PATCH v3 3/3] net/mlx5: add compare item support Suanming Mou
  2 siblings, 1 reply; 66+ messages in thread
From: Suanming Mou @ 2024-01-15  9:13 UTC (permalink / raw)
  To: orika, Aman Singh, Yuying Zhang, Thomas Monjalon, Ferruh Yigit,
	Andrew Rybchenko
  Cc: dev

The new item type is added for the case user wants to match traffic
based on packet field compare result with other fields or immediate
value.

e.g. take advantage the compare item user will be able to accumulate
a IPv4/TCP packet's TCP data_offset and IPv4 IHL field to a tag
register, then compare the tag register with IPv4 header total length
to understand the packet has payload or not.

The supported operations can be as below:
 - RTE_FLOW_ITEM_COMPARE_EQ (equal)
 - RTE_FLOW_ITEM_COMPARE_NE (not equal)
 - RTE_FLOW_ITEM_COMPARE_LT (less than)
 - RTE_FLOW_ITEM_COMPARE_LE (less than or equal)
 - RTE_FLOW_ITEM_COMPARE_GT (great than)
 - RTE_FLOW_ITEM_COMPARE_GE (great than or equal)

Signed-off-by: Suanming Mou <suanmingm@nvidia.com>
Acked-by: Ori Kam <orika@nvidia.com>
Acked-by: Andrew Rybchenko <andrew.rybchenko@oktetlabs.ru>
---
 app/test-pmd/cmdline_flow.c                 | 414 +++++++++++++++++++-
 doc/guides/nics/features/default.ini        |   1 +
 doc/guides/prog_guide/rte_flow.rst          |   7 +
 doc/guides/rel_notes/release_24_03.rst      |   5 +
 doc/guides/testpmd_app_ug/testpmd_funcs.rst |   7 +
 lib/ethdev/rte_flow.c                       |   1 +
 lib/ethdev/rte_flow.h                       | 322 ++++++++-------
 7 files changed, 603 insertions(+), 154 deletions(-)

diff --git a/app/test-pmd/cmdline_flow.c b/app/test-pmd/cmdline_flow.c
index 3725e955c7..4f448ff8ec 100644
--- a/app/test-pmd/cmdline_flow.c
+++ b/app/test-pmd/cmdline_flow.c
@@ -543,6 +543,28 @@ enum index {
 	ITEM_PTYPE,
 	ITEM_PTYPE_VALUE,
 	ITEM_NSH,
+	ITEM_COMPARE,
+	ITEM_COMPARE_OP,
+	ITEM_COMPARE_OP_VALUE,
+	ITEM_COMPARE_FIELD_A_TYPE,
+	ITEM_COMPARE_FIELD_A_TYPE_VALUE,
+	ITEM_COMPARE_FIELD_A_LEVEL,
+	ITEM_COMPARE_FIELD_A_LEVEL_VALUE,
+	ITEM_COMPARE_FIELD_A_TAG_INDEX,
+	ITEM_COMPARE_FIELD_A_TYPE_ID,
+	ITEM_COMPARE_FIELD_A_CLASS_ID,
+	ITEM_COMPARE_FIELD_A_OFFSET,
+	ITEM_COMPARE_FIELD_B_TYPE,
+	ITEM_COMPARE_FIELD_B_TYPE_VALUE,
+	ITEM_COMPARE_FIELD_B_LEVEL,
+	ITEM_COMPARE_FIELD_B_LEVEL_VALUE,
+	ITEM_COMPARE_FIELD_B_TAG_INDEX,
+	ITEM_COMPARE_FIELD_B_TYPE_ID,
+	ITEM_COMPARE_FIELD_B_CLASS_ID,
+	ITEM_COMPARE_FIELD_B_OFFSET,
+	ITEM_COMPARE_FIELD_B_VALUE,
+	ITEM_COMPARE_FIELD_B_POINTER,
+	ITEM_COMPARE_FIELD_WIDTH,
 
 	/* Validate/create actions. */
 	ACTIONS,
@@ -740,13 +762,17 @@ enum index {
 #define ITEM_RAW_SIZE \
 	(sizeof(struct rte_flow_item_raw) + ITEM_RAW_PATTERN_SIZE)
 
+static const char *const compare_ops[] = {
+	"eq", "ne", "lt", "le", "gt", "ge", NULL
+};
+
 /** Maximum size for external pattern in struct rte_flow_field_data. */
-#define ACTION_MODIFY_PATTERN_SIZE 32
+#define FLOW_FIELD_PATTERN_SIZE 32
 
 /** Storage size for struct rte_flow_action_modify_field including pattern. */
 #define ACTION_MODIFY_SIZE \
 	(sizeof(struct rte_flow_action_modify_field) + \
-	ACTION_MODIFY_PATTERN_SIZE)
+	FLOW_FIELD_PATTERN_SIZE)
 
 /** Maximum number of queue indices in struct rte_flow_action_rss. */
 #define ACTION_RSS_QUEUE_NUM 128
@@ -940,7 +966,7 @@ static const char *const modify_field_ops[] = {
 	"set", "add", "sub", NULL
 };
 
-static const char *const modify_field_ids[] = {
+static const char *const flow_field_ids[] = {
 	"start", "mac_dst", "mac_src",
 	"vlan_type", "vlan_id", "mac_type",
 	"ipv4_dscp", "ipv4_ttl", "ipv4_src", "ipv4_dst",
@@ -1590,6 +1616,7 @@ static const enum index next_item[] = {
 	ITEM_IB_BTH,
 	ITEM_PTYPE,
 	ITEM_NSH,
+	ITEM_COMPARE,
 	END_SET,
 	ZERO,
 };
@@ -2121,6 +2148,38 @@ static const enum index item_nsh[] = {
 	ZERO,
 };
 
+static const enum index item_compare_field[] = {
+	ITEM_COMPARE_OP,
+	ITEM_COMPARE_FIELD_A_TYPE,
+	ITEM_COMPARE_FIELD_B_TYPE,
+	ITEM_NEXT,
+	ZERO,
+};
+
+static const enum index compare_field_a[] = {
+	ITEM_COMPARE_FIELD_A_TYPE,
+	ITEM_COMPARE_FIELD_A_LEVEL,
+	ITEM_COMPARE_FIELD_A_TAG_INDEX,
+	ITEM_COMPARE_FIELD_A_TYPE_ID,
+	ITEM_COMPARE_FIELD_A_CLASS_ID,
+	ITEM_COMPARE_FIELD_A_OFFSET,
+	ITEM_COMPARE_FIELD_B_TYPE,
+	ZERO,
+};
+
+static const enum index compare_field_b[] = {
+	ITEM_COMPARE_FIELD_B_TYPE,
+	ITEM_COMPARE_FIELD_B_LEVEL,
+	ITEM_COMPARE_FIELD_B_TAG_INDEX,
+	ITEM_COMPARE_FIELD_B_TYPE_ID,
+	ITEM_COMPARE_FIELD_B_CLASS_ID,
+	ITEM_COMPARE_FIELD_B_OFFSET,
+	ITEM_COMPARE_FIELD_B_VALUE,
+	ITEM_COMPARE_FIELD_B_POINTER,
+	ITEM_COMPARE_FIELD_WIDTH,
+	ZERO,
+};
+
 static const enum index next_action[] = {
 	ACTION_END,
 	ACTION_VOID,
@@ -2863,6 +2922,24 @@ comp_quota_update_name(struct context *ctx, const struct token *token,
 static int
 comp_qu_mode_name(struct context *ctx, const struct token *token,
 		  unsigned int ent, char *buf, unsigned int size);
+static int
+comp_set_compare_field_id(struct context *ctx, const struct token *token,
+			  unsigned int ent, char *buf, unsigned int size);
+static int
+comp_set_compare_op(struct context *ctx, const struct token *token,
+		    unsigned int ent, char *buf, unsigned int size);
+static int
+parse_vc_compare_op(struct context *ctx, const struct token *token,
+			 const char *str, unsigned int len, void *buf,
+			 unsigned int size);
+static int
+parse_vc_compare_field_id(struct context *ctx, const struct token *token,
+			  const char *str, unsigned int len, void *buf,
+			  unsigned int size);
+static int
+parse_vc_compare_field_level(struct context *ctx, const struct token *token,
+			     const char *str, unsigned int len, void *buf,
+			     unsigned int size);
 
 struct indlst_conf {
 	uint32_t id;
@@ -5982,6 +6059,174 @@ static const struct token token_list[] = {
 		.next = NEXT(item_nsh),
 		.call = parse_vc,
 	},
+	[ITEM_COMPARE] = {
+		.name = "compare",
+		.help = "match with the comparison result",
+		.priv = PRIV_ITEM(COMPARE, sizeof(struct rte_flow_item_compare)),
+		.next = NEXT(NEXT_ENTRY(ITEM_COMPARE_OP)),
+		.call = parse_vc,
+	},
+	[ITEM_COMPARE_OP] = {
+		.name = "op",
+		.help = "operation type",
+		.next = NEXT(item_compare_field,
+			NEXT_ENTRY(ITEM_COMPARE_OP_VALUE), item_param),
+		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_compare, operation)),
+	},
+	[ITEM_COMPARE_OP_VALUE] = {
+		.name = "{operation}",
+		.help = "operation type value",
+		.call = parse_vc_compare_op,
+		.comp = comp_set_compare_op,
+	},
+	[ITEM_COMPARE_FIELD_A_TYPE] = {
+		.name = "a_type",
+		.help = "compared field type",
+		.next = NEXT(compare_field_a,
+			NEXT_ENTRY(ITEM_COMPARE_FIELD_A_TYPE_VALUE), item_param),
+		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_compare, a.field)),
+	},
+	[ITEM_COMPARE_FIELD_A_TYPE_VALUE] = {
+		.name = "{a_type}",
+		.help = "compared field type value",
+		.call = parse_vc_compare_field_id,
+		.comp = comp_set_compare_field_id,
+	},
+	[ITEM_COMPARE_FIELD_A_LEVEL] = {
+		.name = "a_level",
+		.help = "compared field level",
+		.next = NEXT(compare_field_a,
+			     NEXT_ENTRY(ITEM_COMPARE_FIELD_A_LEVEL_VALUE), item_param),
+		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_compare, a.level)),
+	},
+	[ITEM_COMPARE_FIELD_A_LEVEL_VALUE] = {
+		.name = "{a_level}",
+		.help = "compared field level value",
+		.call = parse_vc_compare_field_level,
+		.comp = comp_none,
+	},
+	[ITEM_COMPARE_FIELD_A_TAG_INDEX] = {
+		.name = "a_tag_index",
+		.help = "compared field tag array",
+		.next = NEXT(compare_field_a,
+			     NEXT_ENTRY(COMMON_UNSIGNED), item_param),
+		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_compare,
+					a.tag_index)),
+	},
+	[ITEM_COMPARE_FIELD_A_TYPE_ID] = {
+		.name = "a_type_id",
+		.help = "compared field type ID",
+		.next = NEXT(compare_field_a,
+			     NEXT_ENTRY(COMMON_UNSIGNED), item_param),
+		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_compare,
+					a.type)),
+	},
+	[ITEM_COMPARE_FIELD_A_CLASS_ID] = {
+		.name = "a_class",
+		.help = "compared field class ID",
+		.next = NEXT(compare_field_a,
+			     NEXT_ENTRY(COMMON_UNSIGNED), item_param),
+		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_compare,
+					     a.class_id)),
+	},
+	[ITEM_COMPARE_FIELD_A_OFFSET] = {
+		.name = "a_offset",
+		.help = "compared field bit offset",
+		.next = NEXT(compare_field_a,
+			     NEXT_ENTRY(COMMON_UNSIGNED), item_param),
+		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_compare,
+					a.offset)),
+	},
+	[ITEM_COMPARE_FIELD_B_TYPE] = {
+		.name = "b_type",
+		.help = "comparator field type",
+		.next = NEXT(compare_field_b,
+			NEXT_ENTRY(ITEM_COMPARE_FIELD_B_TYPE_VALUE), item_param),
+		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_compare,
+					b.field)),
+	},
+	[ITEM_COMPARE_FIELD_B_TYPE_VALUE] = {
+		.name = "{b_type}",
+		.help = "comparator field type value",
+		.call = parse_vc_compare_field_id,
+		.comp = comp_set_compare_field_id,
+	},
+	[ITEM_COMPARE_FIELD_B_LEVEL] = {
+		.name = "b_level",
+		.help = "comparator field level",
+		.next = NEXT(compare_field_b,
+			     NEXT_ENTRY(ITEM_COMPARE_FIELD_B_LEVEL_VALUE), item_param),
+		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_compare,
+					b.level)),
+	},
+	[ITEM_COMPARE_FIELD_B_LEVEL_VALUE] = {
+		.name = "{b_level}",
+		.help = "comparator field level value",
+		.call = parse_vc_compare_field_level,
+		.comp = comp_none,
+	},
+	[ITEM_COMPARE_FIELD_B_TAG_INDEX] = {
+		.name = "b_tag_index",
+		.help = "comparator field tag array",
+		.next = NEXT(compare_field_b,
+			     NEXT_ENTRY(COMMON_UNSIGNED), item_param),
+		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_compare,
+					b.tag_index)),
+	},
+	[ITEM_COMPARE_FIELD_B_TYPE_ID] = {
+		.name = "b_type_id",
+		.help = "comparator field type ID",
+		.next = NEXT(compare_field_b,
+			     NEXT_ENTRY(COMMON_UNSIGNED), item_param),
+		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_compare,
+					b.type)),
+	},
+	[ITEM_COMPARE_FIELD_B_CLASS_ID] = {
+		.name = "b_class",
+		.help = "comparator field class ID",
+		.next = NEXT(compare_field_b,
+			     NEXT_ENTRY(COMMON_UNSIGNED), item_param),
+		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_compare,
+					     b.class_id)),
+	},
+	[ITEM_COMPARE_FIELD_B_OFFSET] = {
+		.name = "b_offset",
+		.help = "comparator field bit offset",
+		.next = NEXT(compare_field_b,
+			     NEXT_ENTRY(COMMON_UNSIGNED), item_param),
+		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_compare,
+					b.offset)),
+	},
+	[ITEM_COMPARE_FIELD_B_VALUE] = {
+		.name = "b_value",
+		.help = "comparator immediate value",
+		.next = NEXT(compare_field_b,
+			     NEXT_ENTRY(COMMON_HEX), item_param),
+		.args = ARGS(ARGS_ENTRY_ARB(0, 0),
+			     ARGS_ENTRY_ARB(0, 0),
+			     ARGS_ENTRY(struct rte_flow_item_compare,
+					b.value)),
+	},
+	[ITEM_COMPARE_FIELD_B_POINTER] = {
+		.name = "b_ptr",
+		.help = "pointer to comparator immediate value",
+		.next = NEXT(compare_field_b,
+			     NEXT_ENTRY(COMMON_HEX), item_param),
+		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_compare,
+					b.pvalue),
+			     ARGS_ENTRY_ARB(0, 0),
+			     ARGS_ENTRY_ARB
+				(sizeof(struct rte_flow_item_compare),
+				 FLOW_FIELD_PATTERN_SIZE)),
+	},
+	[ITEM_COMPARE_FIELD_WIDTH] = {
+		.name = "width",
+		.help = "number of bits to compare",
+		.next = NEXT(item_compare_field,
+			NEXT_ENTRY(COMMON_UNSIGNED), item_param),
+		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_compare,
+					width)),
+	},
 
 	/* Validate/create actions. */
 	[ACTIONS] = {
@@ -6961,7 +7206,7 @@ static const struct token token_list[] = {
 			     ARGS_ENTRY_ARB(0, 0),
 			     ARGS_ENTRY_ARB
 				(sizeof(struct rte_flow_action_modify_field),
-				 ACTION_MODIFY_PATTERN_SIZE)),
+				 FLOW_FIELD_PATTERN_SIZE)),
 		.call = parse_vc_conf,
 	},
 	[ACTION_MODIFY_FIELD_WIDTH] = {
@@ -8404,6 +8649,122 @@ parse_vc_item_l2tpv2_type(struct context *ctx, const struct token *token,
 	return len;
 }
 
+/** Parse operation for compare match item. */
+static int
+parse_vc_compare_op(struct context *ctx, const struct token *token,
+			 const char *str, unsigned int len, void *buf,
+			 unsigned int size)
+{
+	struct rte_flow_item_compare *compare_item;
+	unsigned int i;
+
+	(void)token;
+	(void)buf;
+	(void)size;
+	if (ctx->curr != ITEM_COMPARE_OP_VALUE)
+		return -1;
+	for (i = 0; compare_ops[i]; ++i)
+		if (!strcmp_partial(compare_ops[i], str, len))
+			break;
+	if (!compare_ops[i])
+		return -1;
+	if (!ctx->object)
+		return len;
+	compare_item = ctx->object;
+	compare_item->operation = (enum rte_flow_item_compare_op)i;
+	return len;
+}
+
+/** Parse id for compare match item. */
+static int
+parse_vc_compare_field_id(struct context *ctx, const struct token *token,
+			  const char *str, unsigned int len, void *buf,
+			  unsigned int size)
+{
+	struct rte_flow_item_compare *compare_item;
+	unsigned int i;
+
+	(void)token;
+	(void)buf;
+	(void)size;
+	if (ctx->curr != ITEM_COMPARE_FIELD_A_TYPE_VALUE &&
+		ctx->curr != ITEM_COMPARE_FIELD_B_TYPE_VALUE)
+		return -1;
+	for (i = 0; flow_field_ids[i]; ++i)
+		if (!strcmp_partial(flow_field_ids[i], str, len))
+			break;
+	if (!flow_field_ids[i])
+		return -1;
+	if (!ctx->object)
+		return len;
+	compare_item = ctx->object;
+	if (ctx->curr == ITEM_COMPARE_FIELD_A_TYPE_VALUE)
+		compare_item->a.field = (enum rte_flow_field_id)i;
+	else
+		compare_item->b.field = (enum rte_flow_field_id)i;
+	return len;
+}
+
+/** Parse level for compare match item. */
+static int
+parse_vc_compare_field_level(struct context *ctx, const struct token *token,
+			     const char *str, unsigned int len, void *buf,
+			     unsigned int size)
+{
+	struct rte_flow_item_compare *compare_item;
+	struct flex_item *fp = NULL;
+	uint32_t val;
+	struct buffer *out = buf;
+	char *end;
+
+	(void)token;
+	(void)size;
+	if (ctx->curr != ITEM_COMPARE_FIELD_A_LEVEL_VALUE &&
+		ctx->curr != ITEM_COMPARE_FIELD_B_LEVEL_VALUE)
+		return -1;
+	if (!ctx->object)
+		return len;
+	compare_item = ctx->object;
+	errno = 0;
+	val = strtoumax(str, &end, 0);
+	if (errno || (size_t)(end - str) != len)
+		return -1;
+	/* No need to validate action template mask value */
+	if (out->args.vc.masks) {
+		if (ctx->curr == ITEM_COMPARE_FIELD_A_LEVEL_VALUE)
+			compare_item->a.level = val;
+		else
+			compare_item->b.level = val;
+		return len;
+	}
+	if ((ctx->curr == ITEM_COMPARE_FIELD_A_LEVEL_VALUE &&
+		compare_item->a.field == RTE_FLOW_FIELD_FLEX_ITEM) ||
+		(ctx->curr == ITEM_COMPARE_FIELD_B_LEVEL_VALUE &&
+		compare_item->b.field == RTE_FLOW_FIELD_FLEX_ITEM)) {
+		if (val >= FLEX_MAX_PARSERS_NUM) {
+			printf("Bad flex item handle\n");
+			return -1;
+		}
+		fp = flex_items[ctx->port][val];
+		if (!fp) {
+			printf("Bad flex item handle\n");
+			return -1;
+		}
+	}
+	if (ctx->curr == ITEM_COMPARE_FIELD_A_LEVEL_VALUE) {
+		if (compare_item->a.field != RTE_FLOW_FIELD_FLEX_ITEM)
+			compare_item->a.level = val;
+		else
+			compare_item->a.flex_handle = fp->flex_handle;
+	} else if (ctx->curr == ITEM_COMPARE_FIELD_B_LEVEL_VALUE) {
+		if (compare_item->b.field != RTE_FLOW_FIELD_FLEX_ITEM)
+			compare_item->b.level = val;
+		else
+			compare_item->b.flex_handle = fp->flex_handle;
+	}
+	return len;
+}
+
 /** Parse meter color action type. */
 static int
 parse_vc_action_meter_color_type(struct context *ctx, const struct token *token,
@@ -9773,10 +10134,10 @@ parse_vc_modify_field_id(struct context *ctx, const struct token *token,
 	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))
+	for (i = 0; flow_field_ids[i]; ++i)
+		if (!strcmp_partial(flow_field_ids[i], str, len))
 			break;
-	if (!modify_field_ids[i])
+	if (!flow_field_ids[i])
 		return -1;
 	if (!ctx->object)
 		return len;
@@ -11890,6 +12251,39 @@ comp_rule_id(struct context *ctx, const struct token *token,
 	return i;
 }
 
+/** Complete operation for compare match item. */
+static int
+comp_set_compare_op(struct context *ctx, const struct token *token,
+		    unsigned int ent, char *buf, unsigned int size)
+{
+	RTE_SET_USED(ctx);
+	RTE_SET_USED(token);
+	if (!buf)
+		return RTE_DIM(compare_ops);
+	if (ent < RTE_DIM(compare_ops) - 1)
+		return strlcpy(buf, compare_ops[ent], size);
+	return -1;
+}
+
+/** Complete field id for compare match item. */
+static int
+comp_set_compare_field_id(struct context *ctx, const struct token *token,
+			  unsigned int ent, char *buf, unsigned int size)
+{
+	const char *name;
+
+	RTE_SET_USED(token);
+	if (!buf)
+		return RTE_DIM(flow_field_ids);
+	if (ent >= RTE_DIM(flow_field_ids) - 1)
+		return -1;
+	name = flow_field_ids[ent];
+	if (ctx->curr == ITEM_COMPARE_FIELD_B_TYPE ||
+	    (strcmp(name, "pointer") && strcmp(name, "value")))
+		return strlcpy(buf, name, size);
+	return -1;
+}
+
 /** Complete type field for RSS action. */
 static int
 comp_vc_action_rss_type(struct context *ctx, const struct token *token,
@@ -12003,10 +12397,10 @@ comp_set_modify_field_id(struct context *ctx, const struct token *token,
 
 	RTE_SET_USED(token);
 	if (!buf)
-		return RTE_DIM(modify_field_ids);
-	if (ent >= RTE_DIM(modify_field_ids) - 1)
+		return RTE_DIM(flow_field_ids);
+	if (ent >= RTE_DIM(flow_field_ids) - 1)
 		return -1;
-	name = modify_field_ids[ent];
+	name = flow_field_ids[ent];
 	if (ctx->curr == ACTION_MODIFY_FIELD_SRC_TYPE ||
 	    (strcmp(name, "pointer") && strcmp(name, "value")))
 		return strlcpy(buf, name, size);
diff --git a/doc/guides/nics/features/default.ini b/doc/guides/nics/features/default.ini
index 806cb033ff..565338731f 100644
--- a/doc/guides/nics/features/default.ini
+++ b/doc/guides/nics/features/default.ini
@@ -87,6 +87,7 @@ aggr_affinity        =
 ah                   =
 any                  =
 arp_eth_ipv4         =
+compare              =
 conntrack            =
 ecpri                =
 esp                  =
diff --git a/doc/guides/prog_guide/rte_flow.rst b/doc/guides/prog_guide/rte_flow.rst
index bf25c849fb..b720157d18 100644
--- a/doc/guides/prog_guide/rte_flow.rst
+++ b/doc/guides/prog_guide/rte_flow.rst
@@ -1573,6 +1573,13 @@ Matches the packet type as defined in rte_mbuf_ptype.
 
 - ``packet_type``: L2/L3/L4 and tunnel information.
 
+Item: ``COMPARE``
+^^^^^^^^^^^^^^^^^
+
+Matches the comparison result between packet fields or value.
+
+- ``compare``: Comparison information.
+
 Actions
 ~~~~~~~
 
diff --git a/doc/guides/rel_notes/release_24_03.rst b/doc/guides/rel_notes/release_24_03.rst
index a691e794f4..8c8c661218 100644
--- a/doc/guides/rel_notes/release_24_03.rst
+++ b/doc/guides/rel_notes/release_24_03.rst
@@ -55,6 +55,11 @@ New Features
      Also, make sure to start the actual text at the margin.
      =======================================================
 
+* **Added compare flow matching criteria.**
+
+  Added ``RTE_FLOW_ITEM_TYPE_COMPARE`` to allow matching on compare
+  result between the packet fields or value.
+
 * **Updated NVIDIA mlx5 driver.**
 
   * Added support for accumulating from src field to dst field.
diff --git a/doc/guides/testpmd_app_ug/testpmd_funcs.rst b/doc/guides/testpmd_app_ug/testpmd_funcs.rst
index 447e28e694..2d96deae75 100644
--- a/doc/guides/testpmd_app_ug/testpmd_funcs.rst
+++ b/doc/guides/testpmd_app_ug/testpmd_funcs.rst
@@ -3841,6 +3841,13 @@ This section lists supported pattern items and their attributes, if any.
 
         - ``packet_type {unsigned}``: packet type.
 
+- ``compare``: match the comparison result between packet fields or value.
+
+        - ``op {string}``: comparison operation type.
+        - ``a_type {string}``: compared field.
+        - ``b_type {string}``: comparator field.
+        - ``width {unsigned}``: comparison width.
+
 
 Actions list
 ^^^^^^^^^^^^
diff --git a/lib/ethdev/rte_flow.c b/lib/ethdev/rte_flow.c
index 549e329558..88cf003b2b 100644
--- a/lib/ethdev/rte_flow.c
+++ b/lib/ethdev/rte_flow.c
@@ -167,6 +167,7 @@ static const struct rte_flow_desc_data rte_flow_desc_item[] = {
 	MK_FLOW_ITEM(TX_QUEUE, sizeof(struct rte_flow_item_tx_queue)),
 	MK_FLOW_ITEM(IB_BTH, sizeof(struct rte_flow_item_ib_bth)),
 	MK_FLOW_ITEM(PTYPE, sizeof(struct rte_flow_item_ptype)),
+	MK_FLOW_ITEM(COMPARE, sizeof(struct rte_flow_item_compare)),
 };
 
 /** Generate flow_action[] entry. */
diff --git a/lib/ethdev/rte_flow.h b/lib/ethdev/rte_flow.h
index 40f6dcaacd..8506184a76 100644
--- a/lib/ethdev/rte_flow.h
+++ b/lib/ethdev/rte_flow.h
@@ -704,6 +704,13 @@ enum rte_flow_item_type {
 	 *
 	 */
 	RTE_FLOW_ITEM_TYPE_PTYPE,
+
+	/**
+	 * Matches the packet with compare result.
+	 *
+	 * See struct rte_flow_item_compare.
+	 */
+	RTE_FLOW_ITEM_TYPE_COMPARE,
 };
 
 /**
@@ -2336,6 +2343,177 @@ static const struct rte_flow_item_ptype rte_flow_item_ptype_mask = {
 };
 #endif
 
+/**
+ * Field IDs for packet field.
+ */
+enum rte_flow_field_id {
+	RTE_FLOW_FIELD_START = 0,	/**< Start of a packet. */
+	RTE_FLOW_FIELD_MAC_DST,		/**< Destination MAC Address. */
+	RTE_FLOW_FIELD_MAC_SRC,		/**< Source MAC Address. */
+	RTE_FLOW_FIELD_VLAN_TYPE,	/**< VLAN Tag Identifier. */
+	RTE_FLOW_FIELD_VLAN_ID,		/**< VLAN Identifier. */
+	RTE_FLOW_FIELD_MAC_TYPE,	/**< EtherType. */
+	RTE_FLOW_FIELD_IPV4_DSCP,	/**< IPv4 DSCP. */
+	RTE_FLOW_FIELD_IPV4_TTL,	/**< IPv4 Time To Live. */
+	RTE_FLOW_FIELD_IPV4_SRC,	/**< IPv4 Source Address. */
+	RTE_FLOW_FIELD_IPV4_DST,	/**< IPv4 Destination Address. */
+	RTE_FLOW_FIELD_IPV6_DSCP,	/**< IPv6 DSCP. */
+	RTE_FLOW_FIELD_IPV6_HOPLIMIT,	/**< IPv6 Hop Limit. */
+	RTE_FLOW_FIELD_IPV6_SRC,	/**< IPv6 Source Address. */
+	RTE_FLOW_FIELD_IPV6_DST,	/**< IPv6 Destination Address. */
+	RTE_FLOW_FIELD_TCP_PORT_SRC,	/**< TCP Source Port Number. */
+	RTE_FLOW_FIELD_TCP_PORT_DST,	/**< TCP Destination Port Number. */
+	RTE_FLOW_FIELD_TCP_SEQ_NUM,	/**< TCP Sequence Number. */
+	RTE_FLOW_FIELD_TCP_ACK_NUM,	/**< TCP Acknowledgment Number. */
+	RTE_FLOW_FIELD_TCP_FLAGS,	/**< TCP Flags. */
+	RTE_FLOW_FIELD_UDP_PORT_SRC,	/**< UDP Source Port Number. */
+	RTE_FLOW_FIELD_UDP_PORT_DST,	/**< UDP Destination Port Number. */
+	RTE_FLOW_FIELD_VXLAN_VNI,	/**< VXLAN Network Identifier. */
+	RTE_FLOW_FIELD_GENEVE_VNI,	/**< GENEVE Network Identifier. */
+	RTE_FLOW_FIELD_GTP_TEID,	/**< GTP Tunnel Endpoint Identifier. */
+	RTE_FLOW_FIELD_TAG,		/**< Tag value. */
+	RTE_FLOW_FIELD_MARK,		/**< Mark value. */
+	RTE_FLOW_FIELD_META,		/**< Metadata value. */
+	RTE_FLOW_FIELD_POINTER,		/**< Memory pointer. */
+	RTE_FLOW_FIELD_VALUE,		/**< Immediate value. */
+	RTE_FLOW_FIELD_IPV4_ECN,	/**< IPv4 ECN. */
+	RTE_FLOW_FIELD_IPV6_ECN,	/**< IPv6 ECN. */
+	RTE_FLOW_FIELD_GTP_PSC_QFI,	/**< GTP QFI. */
+	RTE_FLOW_FIELD_METER_COLOR,	/**< Meter color marker. */
+	RTE_FLOW_FIELD_IPV6_PROTO,	/**< IPv6 next header. */
+	RTE_FLOW_FIELD_FLEX_ITEM,	/**< Flex item. */
+	RTE_FLOW_FIELD_HASH_RESULT,	/**< Hash result. */
+	RTE_FLOW_FIELD_GENEVE_OPT_TYPE,	/**< GENEVE option type. */
+	RTE_FLOW_FIELD_GENEVE_OPT_CLASS,/**< GENEVE option class. */
+	RTE_FLOW_FIELD_GENEVE_OPT_DATA,	/**< GENEVE option data. */
+	RTE_FLOW_FIELD_MPLS,		/**< MPLS header. */
+	RTE_FLOW_FIELD_TCP_DATA_OFFSET,	/**< TCP data offset. */
+	RTE_FLOW_FIELD_IPV4_IHL,	/**< IPv4 IHL. */
+	RTE_FLOW_FIELD_IPV4_TOTAL_LEN,	/**< IPv4 total length. */
+	RTE_FLOW_FIELD_IPV6_PAYLOAD_LEN	/**< IPv6 payload length. */
+};
+
+/**
+ * @warning
+ * @b EXPERIMENTAL: this structure may change without prior notice
+ *
+ * Field description for packet field.
+ */
+struct rte_flow_field_data {
+	enum rte_flow_field_id field; /**< Field or memory type ID. */
+	union {
+		struct {
+			/** Encapsulation level and tag index or flex item handle. */
+			union {
+				struct {
+					/**
+					 * Packet encapsulation level containing
+					 * the field to modify.
+					 *
+					 * - @p 0 requests the default behavior.
+					 *   Depending on the packet type, it
+					 *   can mean outermost, innermost or
+					 *   anything in between.
+					 *
+					 *   It basically stands for the
+					 *   innermost encapsulation level.
+					 *   Modification can be performed
+					 *   according to PMD and device
+					 *   capabilities.
+					 *
+					 * - @p 1 requests modification to be
+					 *   performed on the outermost packet
+					 *   encapsulation level.
+					 *
+					 * - @p 2 and subsequent values request
+					 *   modification to be performed on
+					 *   the specified inner packet
+					 *   encapsulation level, from
+					 *   outermost to innermost (lower to
+					 *   higher values).
+					 *
+					 * Values other than @p 0 are not
+					 * necessarily supported.
+					 *
+					 * @note that for MPLS field,
+					 * encapsulation level also include
+					 * tunnel since MPLS may appear in
+					 * outer, inner or tunnel.
+					 */
+					uint8_t level;
+					union {
+						/**
+						 * Tag index array inside
+						 * encapsulation level.
+						 * Used for VLAN, MPLS or TAG types.
+						 */
+						uint8_t tag_index;
+						/**
+						 * Geneve option identifier.
+						 * Relevant only for
+						 * RTE_FLOW_FIELD_GENEVE_OPT_XXXX
+						 * modification type.
+						 */
+						struct {
+							/**
+							 * Geneve option type.
+							 */
+							uint8_t type;
+							/**
+							 * Geneve option class.
+							 */
+							rte_be16_t class_id;
+						};
+					};
+				};
+				struct rte_flow_item_flex_handle *flex_handle;
+			};
+			/** Number of bits to skip from a field. */
+			uint32_t offset;
+		};
+		/**
+		 * Immediate value for RTE_FLOW_FIELD_VALUE, presented in the
+		 * same byte order and length as in relevant rte_flow_item_xxx.
+		 * The immediate source bitfield offset is inherited from
+		 * the destination's one.
+		 */
+		uint8_t value[16];
+		/**
+		 * Memory address for RTE_FLOW_FIELD_POINTER, memory layout
+		 * should be the same as for relevant field in the
+		 * rte_flow_item_xxx structure.
+		 */
+		void *pvalue;
+	};
+};
+
+/**
+ * Expected operation types for compare item.
+ */
+enum rte_flow_item_compare_op {
+	RTE_FLOW_ITEM_COMPARE_EQ,	/* Compare result equal. */
+	RTE_FLOW_ITEM_COMPARE_NE,	/* Compare result not equal. */
+	RTE_FLOW_ITEM_COMPARE_LT,	/* Compare result less than. */
+	RTE_FLOW_ITEM_COMPARE_LE,	/* Compare result less than or equal. */
+	RTE_FLOW_ITEM_COMPARE_GT,	/* Compare result great than. */
+	RTE_FLOW_ITEM_COMPARE_GE,	/* Compare result great than or equal. */
+};
+
+/**
+ *
+ * RTE_FLOW_ITEM_TYPE_COMPARE
+ *
+ * Matches the packet with compare result.
+ *
+ * The operation means a compare with b result.
+ */
+struct rte_flow_item_compare {
+	enum rte_flow_item_compare_op operation; /* The compare operation. */
+	struct rte_flow_field_data a;		 /* Field be compared.  */
+	struct rte_flow_field_data b;		 /* Field as comparator. */
+	uint32_t width;				 /* Compare width. */
+};
+
 /**
  * Action types.
  *
@@ -3856,150 +4034,6 @@ struct rte_flow_action_ethdev {
 	uint16_t port_id; /**< ethdev port ID */
 };
 
-/**
- * Field IDs for MODIFY_FIELD action.
- */
-enum rte_flow_field_id {
-	RTE_FLOW_FIELD_START = 0,	/**< Start of a packet. */
-	RTE_FLOW_FIELD_MAC_DST,		/**< Destination MAC Address. */
-	RTE_FLOW_FIELD_MAC_SRC,		/**< Source MAC Address. */
-	RTE_FLOW_FIELD_VLAN_TYPE,	/**< VLAN Tag Identifier. */
-	RTE_FLOW_FIELD_VLAN_ID,		/**< VLAN Identifier. */
-	RTE_FLOW_FIELD_MAC_TYPE,	/**< EtherType. */
-	RTE_FLOW_FIELD_IPV4_DSCP,	/**< IPv4 DSCP. */
-	RTE_FLOW_FIELD_IPV4_TTL,	/**< IPv4 Time To Live. */
-	RTE_FLOW_FIELD_IPV4_SRC,	/**< IPv4 Source Address. */
-	RTE_FLOW_FIELD_IPV4_DST,	/**< IPv4 Destination Address. */
-	RTE_FLOW_FIELD_IPV6_DSCP,	/**< IPv6 DSCP. */
-	RTE_FLOW_FIELD_IPV6_HOPLIMIT,	/**< IPv6 Hop Limit. */
-	RTE_FLOW_FIELD_IPV6_SRC,	/**< IPv6 Source Address. */
-	RTE_FLOW_FIELD_IPV6_DST,	/**< IPv6 Destination Address. */
-	RTE_FLOW_FIELD_TCP_PORT_SRC,	/**< TCP Source Port Number. */
-	RTE_FLOW_FIELD_TCP_PORT_DST,	/**< TCP Destination Port Number. */
-	RTE_FLOW_FIELD_TCP_SEQ_NUM,	/**< TCP Sequence Number. */
-	RTE_FLOW_FIELD_TCP_ACK_NUM,	/**< TCP Acknowledgment Number. */
-	RTE_FLOW_FIELD_TCP_FLAGS,	/**< TCP Flags. */
-	RTE_FLOW_FIELD_UDP_PORT_SRC,	/**< UDP Source Port Number. */
-	RTE_FLOW_FIELD_UDP_PORT_DST,	/**< UDP Destination Port Number. */
-	RTE_FLOW_FIELD_VXLAN_VNI,	/**< VXLAN Network Identifier. */
-	RTE_FLOW_FIELD_GENEVE_VNI,	/**< GENEVE Network Identifier. */
-	RTE_FLOW_FIELD_GTP_TEID,	/**< GTP Tunnel Endpoint Identifier. */
-	RTE_FLOW_FIELD_TAG,		/**< Tag value. */
-	RTE_FLOW_FIELD_MARK,		/**< Mark value. */
-	RTE_FLOW_FIELD_META,		/**< Metadata value. */
-	RTE_FLOW_FIELD_POINTER,		/**< Memory pointer. */
-	RTE_FLOW_FIELD_VALUE,		/**< Immediate value. */
-	RTE_FLOW_FIELD_IPV4_ECN,	/**< IPv4 ECN. */
-	RTE_FLOW_FIELD_IPV6_ECN,	/**< IPv6 ECN. */
-	RTE_FLOW_FIELD_GTP_PSC_QFI,	/**< GTP QFI. */
-	RTE_FLOW_FIELD_METER_COLOR,	/**< Meter color marker. */
-	RTE_FLOW_FIELD_IPV6_PROTO,	/**< IPv6 next header. */
-	RTE_FLOW_FIELD_FLEX_ITEM,	/**< Flex item. */
-	RTE_FLOW_FIELD_HASH_RESULT,	/**< Hash result. */
-	RTE_FLOW_FIELD_GENEVE_OPT_TYPE,	/**< GENEVE option type. */
-	RTE_FLOW_FIELD_GENEVE_OPT_CLASS,/**< GENEVE option class. */
-	RTE_FLOW_FIELD_GENEVE_OPT_DATA,	/**< GENEVE option data. */
-	RTE_FLOW_FIELD_MPLS,		/**< MPLS header. */
-	RTE_FLOW_FIELD_TCP_DATA_OFFSET,	/**< TCP data offset. */
-	RTE_FLOW_FIELD_IPV4_IHL,	/**< IPv4 IHL. */
-	RTE_FLOW_FIELD_IPV4_TOTAL_LEN,	/**< IPv4 total length. */
-	RTE_FLOW_FIELD_IPV6_PAYLOAD_LEN	/**< IPv6 payload length. */
-};
-
-/**
- * @warning
- * @b EXPERIMENTAL: this structure may change without prior notice
- *
- * Field description for packet field.
- */
-struct rte_flow_field_data {
-	enum rte_flow_field_id field; /**< Field or memory type ID. */
-	union {
-		struct {
-			/** Encapsulation level and tag index or flex item handle. */
-			union {
-				struct {
-					/**
-					 * Packet encapsulation level containing
-					 * the field to modify.
-					 *
-					 * - @p 0 requests the default behavior.
-					 *   Depending on the packet type, it
-					 *   can mean outermost, innermost or
-					 *   anything in between.
-					 *
-					 *   It basically stands for the
-					 *   innermost encapsulation level.
-					 *   Modification can be performed
-					 *   according to PMD and device
-					 *   capabilities.
-					 *
-					 * - @p 1 requests modification to be
-					 *   performed on the outermost packet
-					 *   encapsulation level.
-					 *
-					 * - @p 2 and subsequent values request
-					 *   modification to be performed on
-					 *   the specified inner packet
-					 *   encapsulation level, from
-					 *   outermost to innermost (lower to
-					 *   higher values).
-					 *
-					 * Values other than @p 0 are not
-					 * necessarily supported.
-					 *
-					 * @note that for MPLS field,
-					 * encapsulation level also include
-					 * tunnel since MPLS may appear in
-					 * outer, inner or tunnel.
-					 */
-					uint8_t level;
-					union {
-						/**
-						 * Tag index array inside
-						 * encapsulation level.
-						 * Used for VLAN, MPLS or TAG types.
-						 */
-						uint8_t tag_index;
-						/**
-						 * Geneve option identifier.
-						 * Relevant only for
-						 * RTE_FLOW_FIELD_GENEVE_OPT_XXXX
-						 * modification type.
-						 */
-						struct {
-							/**
-							 * Geneve option type.
-							 */
-							uint8_t type;
-							/**
-							 * Geneve option class.
-							 */
-							rte_be16_t class_id;
-						};
-					};
-				};
-				struct rte_flow_item_flex_handle *flex_handle;
-			};
-			/** Number of bits to skip from a field. */
-			uint32_t offset;
-		};
-		/**
-		 * Immediate value for RTE_FLOW_FIELD_VALUE, presented in the
-		 * same byte order and length as in relevant rte_flow_item_xxx.
-		 * The immediate source bitfield offset is inherited from
-		 * the destination's one.
-		 */
-		uint8_t value[16];
-		/**
-		 * Memory address for RTE_FLOW_FIELD_POINTER, memory layout
-		 * should be the same as for relevant field in the
-		 * rte_flow_item_xxx structure.
-		 */
-		void *pvalue;
-	};
-};
-
 /**
  * Operation types for MODIFY_FIELD action.
  */
-- 
2.34.1


^ permalink raw reply	[flat|nested] 66+ messages in thread

* [PATCH v3 3/3] net/mlx5: add compare item support
  2024-01-15  9:13   ` [PATCH v3 0/3] ethdev: add RTE_FLOW_ITEM_TYPE_COMPARE Suanming Mou
  2024-01-15  9:13     ` [PATCH v3 1/3] ethdev: rename action modify field data structure Suanming Mou
  2024-01-15  9:13     ` [PATCH v3 2/3] ethdev: add compare item Suanming Mou
@ 2024-01-15  9:13     ` Suanming Mou
  2 siblings, 0 replies; 66+ messages in thread
From: Suanming Mou @ 2024-01-15  9:13 UTC (permalink / raw)
  To: orika, Dariusz Sosnowski, Viacheslav Ovsiienko, Matan Azrad; +Cc: dev

The compare item allows adding flow match with comparison
result. This commit adds compare item support to the PMD
code.

Due to HW limitation:
 - Only HWS supported.
 - Only 32-bit comparison is supported.
 - Only single compare flow is supported in the flow table.
 - Only match with compare result between packet fields is
    supported.

Signed-off-by: Suanming Mou <suanmingm@nvidia.com>
Acked-by: Ori Kam <orika@nvidia.com>
---
 doc/guides/nics/features/mlx5.ini      |  1 +
 doc/guides/nics/mlx5.rst               |  7 +++
 doc/guides/rel_notes/release_24_03.rst |  2 +-
 drivers/net/mlx5/mlx5_flow.h           |  3 ++
 drivers/net/mlx5/mlx5_flow_hw.c        | 73 ++++++++++++++++++++++++++
 5 files changed, 85 insertions(+), 1 deletion(-)

diff --git a/doc/guides/nics/features/mlx5.ini b/doc/guides/nics/features/mlx5.ini
index 0739fe9d63..00e9348fc6 100644
--- a/doc/guides/nics/features/mlx5.ini
+++ b/doc/guides/nics/features/mlx5.ini
@@ -56,6 +56,7 @@ Usage doc            = Y
 
 [rte_flow items]
 aggr_affinity        = Y
+compare              = Y
 conntrack            = Y
 ecpri                = Y
 esp                  = Y
diff --git a/doc/guides/nics/mlx5.rst b/doc/guides/nics/mlx5.rst
index 7bfd6c6aeb..1bb7d0665d 100644
--- a/doc/guides/nics/mlx5.rst
+++ b/doc/guides/nics/mlx5.rst
@@ -780,6 +780,13 @@ Limitations
   The flow engine of a process cannot move from active to standby mode
   if preceding active application rules are still present and vice versa.
 
+- Match with compare result item (``RTE_FLOW_ITEM_TYPE_COMPARE``):
+
+  - Only supported in HW steering(``dv_flow_en`` = 2) mode.
+  - Only single flow is supported to the flow table.
+  - Only 32-bit comparison is supported.
+  - Only match with compare result between packet fields is supported.
+
 
 Statistics
 ----------
diff --git a/doc/guides/rel_notes/release_24_03.rst b/doc/guides/rel_notes/release_24_03.rst
index 8c8c661218..ef9c5d55a1 100644
--- a/doc/guides/rel_notes/release_24_03.rst
+++ b/doc/guides/rel_notes/release_24_03.rst
@@ -63,7 +63,7 @@ New Features
 * **Updated NVIDIA mlx5 driver.**
 
   * Added support for accumulating from src field to dst field.
-
+  * Added support for comparing result between packet fields or value.
 
 Removed Items
 -------------
diff --git a/drivers/net/mlx5/mlx5_flow.h b/drivers/net/mlx5/mlx5_flow.h
index 8e2034473c..6698de2a3e 100644
--- a/drivers/net/mlx5/mlx5_flow.h
+++ b/drivers/net/mlx5/mlx5_flow.h
@@ -277,6 +277,9 @@ enum mlx5_feature_name {
 /* NSH ITEM */
 #define MLX5_FLOW_ITEM_NSH (1ull << 53)
 
+/* COMPARE ITEM */
+#define MLX5_FLOW_ITEM_COMPARE (1ull << 54)
+
 /* Outer Masks. */
 #define MLX5_FLOW_LAYER_OUTER_L3 \
 	(MLX5_FLOW_LAYER_OUTER_L3_IPV4 | MLX5_FLOW_LAYER_OUTER_L3_IPV6)
diff --git a/drivers/net/mlx5/mlx5_flow_hw.c b/drivers/net/mlx5/mlx5_flow_hw.c
index c4a90a3690..82d7fa006f 100644
--- a/drivers/net/mlx5/mlx5_flow_hw.c
+++ b/drivers/net/mlx5/mlx5_flow_hw.c
@@ -426,6 +426,9 @@ flow_hw_matching_item_flags_get(const struct rte_flow_item items[])
 		case RTE_FLOW_ITEM_TYPE_GTP:
 			last_item = MLX5_FLOW_LAYER_GTP;
 			break;
+		case RTE_FLOW_ITEM_TYPE_COMPARE:
+			last_item = MLX5_FLOW_ITEM_COMPARE;
+			break;
 		default:
 			break;
 		}
@@ -4390,6 +4393,8 @@ flow_hw_table_create(struct rte_eth_dev *dev,
 			rte_errno = EINVAL;
 			goto it_error;
 		}
+		if (item_templates[i]->item_flags & MLX5_FLOW_ITEM_COMPARE)
+			matcher_attr.mode = MLX5DR_MATCHER_RESOURCE_MODE_HTABLE;
 		ret = __atomic_fetch_add(&item_templates[i]->refcnt, 1,
 					 __ATOMIC_RELAXED) + 1;
 		if (ret <= 1) {
@@ -6670,6 +6675,66 @@ flow_hw_prepend_item(const struct rte_flow_item *items,
 	return copied_items;
 }
 
+static inline bool
+flow_hw_item_compare_field_supported(enum rte_flow_field_id field)
+{
+	switch (field) {
+	case RTE_FLOW_FIELD_TAG:
+	case RTE_FLOW_FIELD_META:
+	case RTE_FLOW_FIELD_VALUE:
+		return true;
+	default:
+		break;
+	}
+	return false;
+}
+
+static int
+flow_hw_validate_item_compare(const struct rte_flow_item *item,
+			      struct rte_flow_error *error)
+{
+	const struct rte_flow_item_compare *comp_m = item->mask;
+	const struct rte_flow_item_compare *comp_v = item->spec;
+
+	if (unlikely(!comp_m))
+		return rte_flow_error_set(error, EINVAL,
+				   RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
+				   NULL,
+				   "compare item mask is missing");
+	if (comp_m->width != UINT32_MAX)
+		return rte_flow_error_set(error, EINVAL,
+				   RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
+				   NULL,
+				   "compare item only support full mask");
+	if (!flow_hw_item_compare_field_supported(comp_m->a.field) ||
+	    !flow_hw_item_compare_field_supported(comp_m->b.field))
+		return rte_flow_error_set(error, ENOTSUP,
+				   RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
+				   NULL,
+				   "compare item field not support");
+	if (comp_m->a.field == RTE_FLOW_FIELD_VALUE &&
+	    comp_m->b.field == RTE_FLOW_FIELD_VALUE)
+		return rte_flow_error_set(error, EINVAL,
+				   RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
+				   NULL,
+				   "compare between value is not valid");
+	if (comp_v) {
+		if (comp_v->operation != comp_m->operation ||
+		    comp_v->a.field != comp_m->a.field ||
+		    comp_v->b.field != comp_m->b.field)
+			return rte_flow_error_set(error, EINVAL,
+					   RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
+					   NULL,
+					   "compare item spec/mask not matching");
+		if ((comp_v->width & comp_m->width) != 32)
+			return rte_flow_error_set(error, EINVAL,
+					   RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
+					   NULL,
+					   "compare item only support full mask");
+	}
+	return 0;
+}
+
 static int
 flow_hw_pattern_validate(struct rte_eth_dev *dev,
 			 const struct rte_flow_pattern_template_attr *attr,
@@ -6680,6 +6745,7 @@ flow_hw_pattern_validate(struct rte_eth_dev *dev,
 	int i, tag_idx;
 	bool items_end = false;
 	uint32_t tag_bitmap = 0;
+	int ret;
 
 	if (!attr->ingress && !attr->egress && !attr->transfer)
 		return rte_flow_error_set(error, EINVAL, RTE_FLOW_ERROR_TYPE_ATTR, NULL,
@@ -6817,6 +6883,13 @@ flow_hw_pattern_validate(struct rte_eth_dev *dev,
 							  " attribute");
 			break;
 		}
+		case RTE_FLOW_ITEM_TYPE_COMPARE:
+		{
+			ret = flow_hw_validate_item_compare(&items[i], error);
+			if (ret)
+				return ret;
+			break;
+		}
 		case RTE_FLOW_ITEM_TYPE_VOID:
 		case RTE_FLOW_ITEM_TYPE_ETH:
 		case RTE_FLOW_ITEM_TYPE_VLAN:
-- 
2.34.1


^ permalink raw reply	[flat|nested] 66+ messages in thread

* Re: [PATCH v3 1/3] ethdev: rename action modify field data structure
  2024-01-15  9:13     ` [PATCH v3 1/3] ethdev: rename action modify field data structure Suanming Mou
@ 2024-01-30 17:19       ` Ferruh Yigit
  2024-01-31  2:57         ` Suanming Mou
  0 siblings, 1 reply; 66+ messages in thread
From: Ferruh Yigit @ 2024-01-30 17:19 UTC (permalink / raw)
  To: Suanming Mou, orika, Aman Singh, Yuying Zhang, Dariusz Sosnowski,
	Viacheslav Ovsiienko, Matan Azrad, Thomas Monjalon,
	Andrew Rybchenko
  Cc: dev

On 1/15/2024 9:13 AM, Suanming Mou wrote:
> Current rte_flow_action_modify_data struct describes the pkt
> field perfectly and is used only in action.
> 
> It is planned to be used for item as well. This commit renames
> it to "rte_flow_field_data" making it compatible to be used by item.
> 

ack to rename struct to use in pattern.

> Signed-off-by: Suanming Mou <suanmingm@nvidia.com>
> Acked-by: Ori Kam <orika@nvidia.com>
> Acked-by: Andrew Rybchenko <andrew.rybchenko@oktetlabs.ru>
> ---
>  app/test-pmd/cmdline_flow.c            |  2 +-
>  doc/guides/prog_guide/rte_flow.rst     |  2 +-
>  doc/guides/rel_notes/release_24_03.rst |  1 +
>  drivers/net/mlx5/mlx5_flow.c           |  4 ++--
>  drivers/net/mlx5/mlx5_flow.h           |  6 +++---
>  drivers/net/mlx5/mlx5_flow_dv.c        | 10 +++++-----
>  lib/ethdev/rte_flow.h                  |  8 ++++----
>  7 files changed, 17 insertions(+), 16 deletions(-)
> 
> diff --git a/app/test-pmd/cmdline_flow.c b/app/test-pmd/cmdline_flow.c
> index ce71818705..3725e955c7 100644
> --- a/app/test-pmd/cmdline_flow.c
> +++ b/app/test-pmd/cmdline_flow.c
> @@ -740,7 +740,7 @@ enum index {
>  #define ITEM_RAW_SIZE \
>  	(sizeof(struct rte_flow_item_raw) + ITEM_RAW_PATTERN_SIZE)
>  
> -/** Maximum size for external pattern in struct rte_flow_action_modify_data. */
> +/** Maximum size for external pattern in struct rte_flow_field_data. */
>  #define ACTION_MODIFY_PATTERN_SIZE 32
>  

What do you think to update 'ACTION_MODIFY_PATTERN_SIZE' here too,
instead of next patch?

<...>

> diff --git a/lib/ethdev/rte_flow.h b/lib/ethdev/rte_flow.h
> index affdc8121b..40f6dcaacd 100644
> --- a/lib/ethdev/rte_flow.h
> +++ b/lib/ethdev/rte_flow.h
> @@ -3910,9 +3910,9 @@ enum rte_flow_field_id {
>   * @warning
>   * @b EXPERIMENTAL: this structure may change without prior notice
>   *
> - * Field description for MODIFY_FIELD action.
> + * Field description for packet field.
>

New note is not very helpful, how can we make it more useful?

Does it make sense to keep 'MODIFY_FIELD' and add 'COMPARE ITEM' in next
patch, to clarify the intended usage for the struct, otherwise it is too
generic.


^ permalink raw reply	[flat|nested] 66+ messages in thread

* Re: [PATCH v3 2/3] ethdev: add compare item
  2024-01-15  9:13     ` [PATCH v3 2/3] ethdev: add compare item Suanming Mou
@ 2024-01-30 17:33       ` Ferruh Yigit
  2024-01-31  2:47         ` Suanming Mou
  0 siblings, 1 reply; 66+ messages in thread
From: Ferruh Yigit @ 2024-01-30 17:33 UTC (permalink / raw)
  To: Suanming Mou, orika, Aman Singh, Yuying Zhang, Thomas Monjalon,
	Andrew Rybchenko
  Cc: dev

On 1/15/2024 9:13 AM, Suanming Mou wrote:
> The new item type is added for the case user wants to match traffic
> based on packet field compare result with other fields or immediate
> value.
> 
> e.g. take advantage the compare item user will be able to accumulate
> a IPv4/TCP packet's TCP data_offset and IPv4 IHL field to a tag
> register, then compare the tag register with IPv4 header total length
> to understand the packet has payload or not.
> 

ack, above sample makes it easier to understand.

This patch is adding testpmd commands, can you please provide some
sample commands in commit log?
The more samples are better, as far as I remember there was a testpmd
documentation that documents the sample usages, can you please check for it?

> The supported operations can be as below:
>  - RTE_FLOW_ITEM_COMPARE_EQ (equal)
>  - RTE_FLOW_ITEM_COMPARE_NE (not equal)
>  - RTE_FLOW_ITEM_COMPARE_LT (less than)
>  - RTE_FLOW_ITEM_COMPARE_LE (less than or equal)
>  - RTE_FLOW_ITEM_COMPARE_GT (great than)
>  - RTE_FLOW_ITEM_COMPARE_GE (great than or equal)
> 
> Signed-off-by: Suanming Mou <suanmingm@nvidia.com>
> Acked-by: Ori Kam <orika@nvidia.com>
> Acked-by: Andrew Rybchenko <andrew.rybchenko@oktetlabs.ru>

<...>

>  
> -static const char *const modify_field_ids[] = {
> +static const char *const flow_field_ids[] = {
>

I wonder if this rename should be in previous patch, as it does the
logical change of the modify action specific fields to more generic fields.

<...>

> diff --git a/doc/guides/rel_notes/release_24_03.rst b/doc/guides/rel_notes/release_24_03.rst
> index a691e794f4..8c8c661218 100644
> --- a/doc/guides/rel_notes/release_24_03.rst
> +++ b/doc/guides/rel_notes/release_24_03.rst
> @@ -55,6 +55,11 @@ New Features
>       Also, make sure to start the actual text at the margin.
>       =======================================================
>  
> +* **Added compare flow matching criteria.**
> +
> +  Added ``RTE_FLOW_ITEM_TYPE_COMPARE`` to allow matching on compare
> +  result between the packet fields or value.
> +
>  * **Updated NVIDIA mlx5 driver.**
>  
>    * Added support for accumulating from src field to dst field.
>

I guess you are rebasing on some internal repo, because above NVIDIA
note doesn't exist in upstream repo. Can you please rebase on latest
next-net, this also helps to resolve conflict with random action in
upstream repo.

<...>

> +/**
> + * Field IDs for packet field.
> + */
> +enum rte_flow_field_id {
> +	RTE_FLOW_FIELD_START = 0,	/**< Start of a packet. */
> +	RTE_FLOW_FIELD_MAC_DST,		/**< Destination MAC Address. */
> +	RTE_FLOW_FIELD_MAC_SRC,		/**< Source MAC Address. */
> +	RTE_FLOW_FIELD_VLAN_TYPE,	/**< VLAN Tag Identifier. */
> +	RTE_FLOW_FIELD_VLAN_ID,		/**< VLAN Identifier. */
> +	RTE_FLOW_FIELD_MAC_TYPE,	/**< EtherType. */
> +	RTE_FLOW_FIELD_IPV4_DSCP,	/**< IPv4 DSCP. */
> +	RTE_FLOW_FIELD_IPV4_TTL,	/**< IPv4 Time To Live. */
> +	RTE_FLOW_FIELD_IPV4_SRC,	/**< IPv4 Source Address. */
> +	RTE_FLOW_FIELD_IPV4_DST,	/**< IPv4 Destination Address. */
> +	RTE_FLOW_FIELD_IPV6_DSCP,	/**< IPv6 DSCP. */
> +	RTE_FLOW_FIELD_IPV6_HOPLIMIT,	/**< IPv6 Hop Limit. */
> +	RTE_FLOW_FIELD_IPV6_SRC,	/**< IPv6 Source Address. */
> +	RTE_FLOW_FIELD_IPV6_DST,	/**< IPv6 Destination Address. */
> +	RTE_FLOW_FIELD_TCP_PORT_SRC,	/**< TCP Source Port Number. */
> +	RTE_FLOW_FIELD_TCP_PORT_DST,	/**< TCP Destination Port Number. */
> +	RTE_FLOW_FIELD_TCP_SEQ_NUM,	/**< TCP Sequence Number. */
> +	RTE_FLOW_FIELD_TCP_ACK_NUM,	/**< TCP Acknowledgment Number. */
> +	RTE_FLOW_FIELD_TCP_FLAGS,	/**< TCP Flags. */
> +	RTE_FLOW_FIELD_UDP_PORT_SRC,	/**< UDP Source Port Number. */
> +	RTE_FLOW_FIELD_UDP_PORT_DST,	/**< UDP Destination Port Number. */
> +	RTE_FLOW_FIELD_VXLAN_VNI,	/**< VXLAN Network Identifier. */
> +	RTE_FLOW_FIELD_GENEVE_VNI,	/**< GENEVE Network Identifier. */
> +	RTE_FLOW_FIELD_GTP_TEID,	/**< GTP Tunnel Endpoint Identifier. */
> +	RTE_FLOW_FIELD_TAG,		/**< Tag value. */
> +	RTE_FLOW_FIELD_MARK,		/**< Mark value. */
> +	RTE_FLOW_FIELD_META,		/**< Metadata value. */
> +	RTE_FLOW_FIELD_POINTER,		/**< Memory pointer. */
> +	RTE_FLOW_FIELD_VALUE,		/**< Immediate value. */
> +	RTE_FLOW_FIELD_IPV4_ECN,	/**< IPv4 ECN. */
> +	RTE_FLOW_FIELD_IPV6_ECN,	/**< IPv6 ECN. */
> +	RTE_FLOW_FIELD_GTP_PSC_QFI,	/**< GTP QFI. */
> +	RTE_FLOW_FIELD_METER_COLOR,	/**< Meter color marker. */
> +	RTE_FLOW_FIELD_IPV6_PROTO,	/**< IPv6 next header. */
> +	RTE_FLOW_FIELD_FLEX_ITEM,	/**< Flex item. */
> +	RTE_FLOW_FIELD_HASH_RESULT,	/**< Hash result. */
> +	RTE_FLOW_FIELD_GENEVE_OPT_TYPE,	/**< GENEVE option type. */
> +	RTE_FLOW_FIELD_GENEVE_OPT_CLASS,/**< GENEVE option class. */
> +	RTE_FLOW_FIELD_GENEVE_OPT_DATA,	/**< GENEVE option data. */
> +	RTE_FLOW_FIELD_MPLS,		/**< MPLS header. */
> +	RTE_FLOW_FIELD_TCP_DATA_OFFSET,	/**< TCP data offset. */
> +	RTE_FLOW_FIELD_IPV4_IHL,	/**< IPv4 IHL. */
> +	RTE_FLOW_FIELD_IPV4_TOTAL_LEN,	/**< IPv4 total length. */
> +	RTE_FLOW_FIELD_IPV6_PAYLOAD_LEN	/**< IPv6 payload length. */
> +};
> +

+1 to move the structs to keep the proper order, but not sure if it is
better to do this in previous patch or this one.

> +/**
> + * @warning
> + * @b EXPERIMENTAL: this structure may change without prior notice
> + *
> + * Field description for packet field.
> + */
> +struct rte_flow_field_data {
> +	enum rte_flow_field_id field; /**< Field or memory type ID. */
> +	union {
> +		struct {
> +			/** Encapsulation level and tag index or flex item handle. */
> +			union {
> +				struct {
> +					/**
> +					 * Packet encapsulation level containing
> +					 * the field to modify.
> +					 *
> +					 * - @p 0 requests the default behavior.
> +					 *   Depending on the packet type, it
> +					 *   can mean outermost, innermost or
> +					 *   anything in between.
> +					 *
> +					 *   It basically stands for the
> +					 *   innermost encapsulation level.
> +					 *   Modification can be performed
> +					 *   according to PMD and device
> +					 *   capabilities.
> +					 *
> +					 * - @p 1 requests modification to be
> +					 *   performed on the outermost packet
> +					 *   encapsulation level.
> +					 *
> +					 * - @p 2 and subsequent values request
> +					 *   modification to be performed on
> +					 *   the specified inner packet
> +					 *   encapsulation level, from
> +					 *   outermost to innermost (lower to
> +					 *   higher values).
> +					 *
> +					 * Values other than @p 0 are not
> +					 * necessarily supported.
> +					 *
> +					 * @note that for MPLS field,
> +					 * encapsulation level also include
> +					 * tunnel since MPLS may appear in
> +					 * outer, inner or tunnel.
> +					 */
> +					uint8_t level;
> +					union {
> +						/**
> +						 * Tag index array inside
> +						 * encapsulation level.
> +						 * Used for VLAN, MPLS or TAG types.
> +						 */
> +						uint8_t tag_index;
> +						/**
> +						 * Geneve option identifier.
> +						 * Relevant only for
> +						 * RTE_FLOW_FIELD_GENEVE_OPT_XXXX
> +						 * modification type.
> +						 */
> +						struct {
> +							/**
> +							 * Geneve option type.
> +							 */
> +							uint8_t type;
> +							/**
> +							 * Geneve option class.
> +							 */
> +							rte_be16_t class_id;
> +						};
> +					};
> +				};
> +				struct rte_flow_item_flex_handle *flex_handle;
> +			};
> +			/** Number of bits to skip from a field. */
> +			uint32_t offset;
> +		};
> +		/**
> +		 * Immediate value for RTE_FLOW_FIELD_VALUE, presented in the
> +		 * same byte order and length as in relevant rte_flow_item_xxx.
> +		 * The immediate source bitfield offset is inherited from
> +		 * the destination's one.
> +		 */
> +		uint8_t value[16];
> +		/**
> +		 * Memory address for RTE_FLOW_FIELD_POINTER, memory layout
> +		 * should be the same as for relevant field in the
> +		 * rte_flow_item_xxx structure.
> +		 */
> +		void *pvalue;
> +	};
> +};
> +
>

I am aware that you are just moving the above struct, but it is nested
too much which is making it hard to read.

As you are touching it, can we extract some structs and make this struct
less nested, what do you think?
Of course it needs to be done in separate patch, as a
preperation/clean-up patch before moving it around.

<...>

> +/**
> + *
> + * RTE_FLOW_ITEM_TYPE_COMPARE
> + *
> + * Matches the packet with compare result.
> + *
> + * The operation means a compare with b result.
> + */
> +struct rte_flow_item_compare {
> +	enum rte_flow_item_compare_op operation; /* The compare operation. */
> +	struct rte_flow_field_data a;		 /* Field be compared.  */
> +	struct rte_flow_field_data b;		 /* Field as comparator. */
>

Variable names 'a' and 'b' are not descriptive although it may be OK
since there is no significance to the values, but other option can be
'first' and 'second', but overall not strong opinion.


^ permalink raw reply	[flat|nested] 66+ messages in thread

* RE: [PATCH v3 2/3] ethdev: add compare item
  2024-01-30 17:33       ` Ferruh Yigit
@ 2024-01-31  2:47         ` Suanming Mou
  2024-01-31 15:56           ` Ori Kam
  0 siblings, 1 reply; 66+ messages in thread
From: Suanming Mou @ 2024-01-31  2:47 UTC (permalink / raw)
  To: Ferruh Yigit, Ori Kam, Aman Singh, Yuying Zhang,
	NBU-Contact-Thomas Monjalon (EXTERNAL),
	Andrew Rybchenko
  Cc: dev

Hi,

> -----Original Message-----
> From: Ferruh Yigit <ferruh.yigit@amd.com>
> Sent: Wednesday, January 31, 2024 1:34 AM
> To: Suanming Mou <suanmingm@nvidia.com>; Ori Kam <orika@nvidia.com>;
> Aman Singh <aman.deep.singh@intel.com>; Yuying Zhang
> <yuying.zhang@intel.com>; NBU-Contact-Thomas Monjalon (EXTERNAL)
> <thomas@monjalon.net>; Andrew Rybchenko
> <andrew.rybchenko@oktetlabs.ru>
> Cc: dev@dpdk.org
> Subject: Re: [PATCH v3 2/3] ethdev: add compare item
> 
> On 1/15/2024 9:13 AM, Suanming Mou wrote:
> > The new item type is added for the case user wants to match traffic
> > based on packet field compare result with other fields or immediate
> > value.
> >
> > e.g. take advantage the compare item user will be able to accumulate a
> > IPv4/TCP packet's TCP data_offset and IPv4 IHL field to a tag
> > register, then compare the tag register with IPv4 header total length
> > to understand the packet has payload or not.
> >
> 
> ack, above sample makes it easier to understand.
> 
> This patch is adding testpmd commands, can you please provide some sample
> commands in commit log?
> The more samples are better, as far as I remember there was a testpmd
> documentation that documents the sample usages, can you please check for it?

Yes, I think we have something to do in "testpmd_funcs.rst", will update.

> 
> > The supported operations can be as below:
> >  - RTE_FLOW_ITEM_COMPARE_EQ (equal)
> >  - RTE_FLOW_ITEM_COMPARE_NE (not equal)
> >  - RTE_FLOW_ITEM_COMPARE_LT (less than)
> >  - RTE_FLOW_ITEM_COMPARE_LE (less than or equal)
> >  - RTE_FLOW_ITEM_COMPARE_GT (great than)
> >  - RTE_FLOW_ITEM_COMPARE_GE (great than or equal)
> >
> > Signed-off-by: Suanming Mou <suanmingm@nvidia.com>
> > Acked-by: Ori Kam <orika@nvidia.com>
> > Acked-by: Andrew Rybchenko <andrew.rybchenko@oktetlabs.ru>
> 
> <...>
> 
> >
> > -static const char *const modify_field_ids[] = {
> > +static const char *const flow_field_ids[] = {
> >
> 
> I wonder if this rename should be in previous patch, as it does the logical change
> of the modify action specific fields to more generic fields.

Agree, will adjust.

> 
> <...>
> 
> > diff --git a/doc/guides/rel_notes/release_24_03.rst
> > b/doc/guides/rel_notes/release_24_03.rst
> > index a691e794f4..8c8c661218 100644
> > --- a/doc/guides/rel_notes/release_24_03.rst
> > +++ b/doc/guides/rel_notes/release_24_03.rst
> > @@ -55,6 +55,11 @@ New Features
> >       Also, make sure to start the actual text at the margin.
> >       =======================================================
> >
> > +* **Added compare flow matching criteria.**
> > +
> > +  Added ``RTE_FLOW_ITEM_TYPE_COMPARE`` to allow matching on compare
> > + result between the packet fields or value.
> > +
> >  * **Updated NVIDIA mlx5 driver.**
> >
> >    * Added support for accumulating from src field to dst field.
> >
> 
> I guess you are rebasing on some internal repo, because above NVIDIA note
> doesn't exist in upstream repo. Can you please rebase on latest next-net, this also
> helps to resolve conflict with random action in upstream repo.

Will rebase and update.

> 
> <...>
> 
> > +/**
> > + * Field IDs for packet field.
> > + */
> > +enum rte_flow_field_id {
> > +	RTE_FLOW_FIELD_START = 0,	/**< Start of a packet. */
> > +	RTE_FLOW_FIELD_MAC_DST,		/**< Destination MAC Address.
> */
> > +	RTE_FLOW_FIELD_MAC_SRC,		/**< Source MAC Address. */
> > +	RTE_FLOW_FIELD_VLAN_TYPE,	/**< VLAN Tag Identifier. */
> > +	RTE_FLOW_FIELD_VLAN_ID,		/**< VLAN Identifier. */
> > +	RTE_FLOW_FIELD_MAC_TYPE,	/**< EtherType. */
> > +	RTE_FLOW_FIELD_IPV4_DSCP,	/**< IPv4 DSCP. */
> > +	RTE_FLOW_FIELD_IPV4_TTL,	/**< IPv4 Time To Live. */
> > +	RTE_FLOW_FIELD_IPV4_SRC,	/**< IPv4 Source Address. */
> > +	RTE_FLOW_FIELD_IPV4_DST,	/**< IPv4 Destination Address. */
> > +	RTE_FLOW_FIELD_IPV6_DSCP,	/**< IPv6 DSCP. */
> > +	RTE_FLOW_FIELD_IPV6_HOPLIMIT,	/**< IPv6 Hop Limit. */
> > +	RTE_FLOW_FIELD_IPV6_SRC,	/**< IPv6 Source Address. */
> > +	RTE_FLOW_FIELD_IPV6_DST,	/**< IPv6 Destination Address. */
> > +	RTE_FLOW_FIELD_TCP_PORT_SRC,	/**< TCP Source Port Number.
> */
> > +	RTE_FLOW_FIELD_TCP_PORT_DST,	/**< TCP Destination Port
> Number. */
> > +	RTE_FLOW_FIELD_TCP_SEQ_NUM,	/**< TCP Sequence Number. */
> > +	RTE_FLOW_FIELD_TCP_ACK_NUM,	/**< TCP Acknowledgment
> Number. */
> > +	RTE_FLOW_FIELD_TCP_FLAGS,	/**< TCP Flags. */
> > +	RTE_FLOW_FIELD_UDP_PORT_SRC,	/**< UDP Source Port Number.
> */
> > +	RTE_FLOW_FIELD_UDP_PORT_DST,	/**< UDP Destination Port
> Number. */
> > +	RTE_FLOW_FIELD_VXLAN_VNI,	/**< VXLAN Network Identifier. */
> > +	RTE_FLOW_FIELD_GENEVE_VNI,	/**< GENEVE Network
> Identifier. */
> > +	RTE_FLOW_FIELD_GTP_TEID,	/**< GTP Tunnel Endpoint Identifier. */
> > +	RTE_FLOW_FIELD_TAG,		/**< Tag value. */
> > +	RTE_FLOW_FIELD_MARK,		/**< Mark value. */
> > +	RTE_FLOW_FIELD_META,		/**< Metadata value. */
> > +	RTE_FLOW_FIELD_POINTER,		/**< Memory pointer. */
> > +	RTE_FLOW_FIELD_VALUE,		/**< Immediate value. */
> > +	RTE_FLOW_FIELD_IPV4_ECN,	/**< IPv4 ECN. */
> > +	RTE_FLOW_FIELD_IPV6_ECN,	/**< IPv6 ECN. */
> > +	RTE_FLOW_FIELD_GTP_PSC_QFI,	/**< GTP QFI. */
> > +	RTE_FLOW_FIELD_METER_COLOR,	/**< Meter color marker. */
> > +	RTE_FLOW_FIELD_IPV6_PROTO,	/**< IPv6 next header. */
> > +	RTE_FLOW_FIELD_FLEX_ITEM,	/**< Flex item. */
> > +	RTE_FLOW_FIELD_HASH_RESULT,	/**< Hash result. */
> > +	RTE_FLOW_FIELD_GENEVE_OPT_TYPE,	/**< GENEVE option type. */
> > +	RTE_FLOW_FIELD_GENEVE_OPT_CLASS,/**< GENEVE option class. */
> > +	RTE_FLOW_FIELD_GENEVE_OPT_DATA,	/**< GENEVE option data. */
> > +	RTE_FLOW_FIELD_MPLS,		/**< MPLS header. */
> > +	RTE_FLOW_FIELD_TCP_DATA_OFFSET,	/**< TCP data offset. */
> > +	RTE_FLOW_FIELD_IPV4_IHL,	/**< IPv4 IHL. */
> > +	RTE_FLOW_FIELD_IPV4_TOTAL_LEN,	/**< IPv4 total length. */
> > +	RTE_FLOW_FIELD_IPV6_PAYLOAD_LEN	/**< IPv6 payload length. */
> > +};
> > +
> 
> +1 to move the structs to keep the proper order, but not sure if it is
> better to do this in previous patch or this one.

The previous patch is just for renaming, I assume moving the struct is too much in previous patch, what do you think?

> 
> > +/**
> > + * @warning
> > + * @b EXPERIMENTAL: this structure may change without prior notice
> > + *
> > + * Field description for packet field.
> > + */
> > +struct rte_flow_field_data {
> > +	enum rte_flow_field_id field; /**< Field or memory type ID. */
> > +	union {
> > +		struct {
> > +			/** Encapsulation level and tag index or flex item
> handle. */
> > +			union {
> > +				struct {
> > +					/**
> > +					 * Packet encapsulation level containing
> > +					 * the field to modify.
> > +					 *
> > +					 * - @p 0 requests the default behavior.
> > +					 *   Depending on the packet type, it
> > +					 *   can mean outermost, innermost or
> > +					 *   anything in between.
> > +					 *
> > +					 *   It basically stands for the
> > +					 *   innermost encapsulation level.
> > +					 *   Modification can be performed
> > +					 *   according to PMD and device
> > +					 *   capabilities.
> > +					 *
> > +					 * - @p 1 requests modification to be
> > +					 *   performed on the outermost packet
> > +					 *   encapsulation level.
> > +					 *
> > +					 * - @p 2 and subsequent values
> request
> > +					 *   modification to be performed on
> > +					 *   the specified inner packet
> > +					 *   encapsulation level, from
> > +					 *   outermost to innermost (lower to
> > +					 *   higher values).
> > +					 *
> > +					 * Values other than @p 0 are not
> > +					 * necessarily supported.
> > +					 *
> > +					 * @note that for MPLS field,
> > +					 * encapsulation level also include
> > +					 * tunnel since MPLS may appear in
> > +					 * outer, inner or tunnel.
> > +					 */
> > +					uint8_t level;
> > +					union {
> > +						/**
> > +						 * Tag index array inside
> > +						 * encapsulation level.
> > +						 * Used for VLAN, MPLS or TAG
> types.
> > +						 */
> > +						uint8_t tag_index;
> > +						/**
> > +						 * Geneve option identifier.
> > +						 * Relevant only for
> > +						 *
> RTE_FLOW_FIELD_GENEVE_OPT_XXXX
> > +						 * modification type.
> > +						 */
> > +						struct {
> > +							/**
> > +							 * Geneve option type.
> > +							 */
> > +							uint8_t type;
> > +							/**
> > +							 * Geneve option class.
> > +							 */
> > +							rte_be16_t class_id;
> > +						};
> > +					};
> > +				};
> > +				struct rte_flow_item_flex_handle *flex_handle;
> > +			};
> > +			/** Number of bits to skip from a field. */
> > +			uint32_t offset;
> > +		};
> > +		/**
> > +		 * Immediate value for RTE_FLOW_FIELD_VALUE, presented in
> the
> > +		 * same byte order and length as in relevant rte_flow_item_xxx.
> > +		 * The immediate source bitfield offset is inherited from
> > +		 * the destination's one.
> > +		 */
> > +		uint8_t value[16];
> > +		/**
> > +		 * Memory address for RTE_FLOW_FIELD_POINTER, memory
> layout
> > +		 * should be the same as for relevant field in the
> > +		 * rte_flow_item_xxx structure.
> > +		 */
> > +		void *pvalue;
> > +	};
> > +};
> > +
> >
> 
> I am aware that you are just moving the above struct, but it is nested too much
> which is making it hard to read.
> 
> As you are touching it, can we extract some structs and make this struct less
> nested, what do you think?
> Of course it needs to be done in separate patch, as a preperation/clean-up patch
> before moving it around.

Agree the struct maybe a bit nested. But not sure how it was discussed before during the last new member was added... @Ori, Do you have any idea about this?

And if it is really expected, I believe another new thread is worth for that change,  better not be in that series.
Need to discuss the new struct name and other stuff. What do you think? 

> 
> <...>
> 
> > +/**
> > + *
> > + * RTE_FLOW_ITEM_TYPE_COMPARE
> > + *
> > + * Matches the packet with compare result.
> > + *
> > + * The operation means a compare with b result.
> > + */
> > +struct rte_flow_item_compare {
> > +	enum rte_flow_item_compare_op operation; /* The compare operation.
> */
> > +	struct rte_flow_field_data a;		 /* Field be compared.  */
> > +	struct rte_flow_field_data b;		 /* Field as comparator. */
> >
> 
> Variable names 'a' and 'b' are not descriptive although it may be OK since there is
> no significance to the values, but other option can be 'first' and 'second', but
> overall not strong opinion.

Yes, thanks for the suggestion, in fact we also discussed about the name a lot, finally we choose the widely used 'a' and 'b'

Thanks


^ permalink raw reply	[flat|nested] 66+ messages in thread

* RE: [PATCH v3 1/3] ethdev: rename action modify field data structure
  2024-01-30 17:19       ` Ferruh Yigit
@ 2024-01-31  2:57         ` Suanming Mou
  2024-02-01 10:56           ` Ferruh Yigit
  0 siblings, 1 reply; 66+ messages in thread
From: Suanming Mou @ 2024-01-31  2:57 UTC (permalink / raw)
  To: Ferruh Yigit, Ori Kam, Aman Singh, Yuying Zhang,
	Dariusz Sosnowski, Slava Ovsiienko, Matan Azrad,
	NBU-Contact-Thomas Monjalon (EXTERNAL),
	Andrew Rybchenko
  Cc: dev

Hi,

> -----Original Message-----
> From: Ferruh Yigit <ferruh.yigit@amd.com>
> Sent: Wednesday, January 31, 2024 1:19 AM
> To: Suanming Mou <suanmingm@nvidia.com>; Ori Kam <orika@nvidia.com>;
> Aman Singh <aman.deep.singh@intel.com>; Yuying Zhang
> <yuying.zhang@intel.com>; Dariusz Sosnowski <dsosnowski@nvidia.com>; Slava
> Ovsiienko <viacheslavo@nvidia.com>; Matan Azrad <matan@nvidia.com>; NBU-
> Contact-Thomas Monjalon (EXTERNAL) <thomas@monjalon.net>; Andrew
> Rybchenko <andrew.rybchenko@oktetlabs.ru>
> Cc: dev@dpdk.org
> Subject: Re: [PATCH v3 1/3] ethdev: rename action modify field data structure
> 
> On 1/15/2024 9:13 AM, Suanming Mou wrote:
> > Current rte_flow_action_modify_data struct describes the pkt field
> > perfectly and is used only in action.
> >
> > It is planned to be used for item as well. This commit renames it to
> > "rte_flow_field_data" making it compatible to be used by item.
> >
> 
> ack to rename struct to use in pattern.
> 
> > Signed-off-by: Suanming Mou <suanmingm@nvidia.com>
> > Acked-by: Ori Kam <orika@nvidia.com>
> > Acked-by: Andrew Rybchenko <andrew.rybchenko@oktetlabs.ru>
> > ---
> >  app/test-pmd/cmdline_flow.c            |  2 +-
> >  doc/guides/prog_guide/rte_flow.rst     |  2 +-
> >  doc/guides/rel_notes/release_24_03.rst |  1 +
> >  drivers/net/mlx5/mlx5_flow.c           |  4 ++--
> >  drivers/net/mlx5/mlx5_flow.h           |  6 +++---
> >  drivers/net/mlx5/mlx5_flow_dv.c        | 10 +++++-----
> >  lib/ethdev/rte_flow.h                  |  8 ++++----
> >  7 files changed, 17 insertions(+), 16 deletions(-)
> >
> > diff --git a/app/test-pmd/cmdline_flow.c b/app/test-pmd/cmdline_flow.c
> > index ce71818705..3725e955c7 100644
> > --- a/app/test-pmd/cmdline_flow.c
> > +++ b/app/test-pmd/cmdline_flow.c
> > @@ -740,7 +740,7 @@ enum index {
> >  #define ITEM_RAW_SIZE \
> >  	(sizeof(struct rte_flow_item_raw) + ITEM_RAW_PATTERN_SIZE)
> >
> > -/** Maximum size for external pattern in struct
> > rte_flow_action_modify_data. */
> > +/** Maximum size for external pattern in struct rte_flow_field_data.
> > +*/
> >  #define ACTION_MODIFY_PATTERN_SIZE 32
> >
> 
> What do you think to update 'ACTION_MODIFY_PATTERN_SIZE' here too, instead
> of next patch?

Agree.

> 
> <...>
> 
> > diff --git a/lib/ethdev/rte_flow.h b/lib/ethdev/rte_flow.h index
> > affdc8121b..40f6dcaacd 100644
> > --- a/lib/ethdev/rte_flow.h
> > +++ b/lib/ethdev/rte_flow.h
> > @@ -3910,9 +3910,9 @@ enum rte_flow_field_id {
> >   * @warning
> >   * @b EXPERIMENTAL: this structure may change without prior notice
> >   *
> > - * Field description for MODIFY_FIELD action.
> > + * Field description for packet field.
> >
> 
> New note is not very helpful, how can we make it more useful?
> 
> Does it make sense to keep 'MODIFY_FIELD' and add 'COMPARE ITEM' in next
> patch, to clarify the intended usage for the struct, otherwise it is too generic.

OK, sorry, the purpose is to make it generic. So next time if other ITEM or ACTION need that field, it can be used directly.
Otherwise, it feels like it can only be used by 'MODIFY_FIELD' and 'COMPARE_ITEM', what do you think?


^ permalink raw reply	[flat|nested] 66+ messages in thread

* RE: [PATCH v3 2/3] ethdev: add compare item
  2024-01-31  2:47         ` Suanming Mou
@ 2024-01-31 15:56           ` Ori Kam
  2024-01-31 16:46             ` Ferruh Yigit
  0 siblings, 1 reply; 66+ messages in thread
From: Ori Kam @ 2024-01-31 15:56 UTC (permalink / raw)
  To: Suanming Mou, Ferruh Yigit, Aman Singh, Yuying Zhang,
	NBU-Contact-Thomas Monjalon (EXTERNAL),
	Andrew Rybchenko
  Cc: dev

Hi

> -----Original Message-----
> From: Suanming Mou <suanmingm@nvidia.com>
> Sent: Wednesday, January 31, 2024 4:48 AM
> 
> Hi,
> 
> > -----Original Message-----
> > From: Ferruh Yigit <ferruh.yigit@amd.com>
> > Sent: Wednesday, January 31, 2024 1:34 AM
> > To: Suanming Mou <suanmingm@nvidia.com>; Ori Kam
> <orika@nvidia.com>;
> > Aman Singh <aman.deep.singh@intel.com>; Yuying Zhang
> > <yuying.zhang@intel.com>; NBU-Contact-Thomas Monjalon (EXTERNAL)
> > <thomas@monjalon.net>; Andrew Rybchenko
> > <andrew.rybchenko@oktetlabs.ru>
> > Cc: dev@dpdk.org
> > Subject: Re: [PATCH v3 2/3] ethdev: add compare item
> >
> > On 1/15/2024 9:13 AM, Suanming Mou wrote:
> > > The new item type is added for the case user wants to match traffic
> > > based on packet field compare result with other fields or immediate
> > > value.
> > >
> > > e.g. take advantage the compare item user will be able to accumulate a
> > > IPv4/TCP packet's TCP data_offset and IPv4 IHL field to a tag
> > > register, then compare the tag register with IPv4 header total length
> > > to understand the packet has payload or not.
> > >
> >
> > ack, above sample makes it easier to understand.
> >
> > This patch is adding testpmd commands, can you please provide some
> sample
> > commands in commit log?
> > The more samples are better, as far as I remember there was a testpmd
> > documentation that documents the sample usages, can you please check
> for it?

[Snip ..]

> >
> > > +/**
> > > + * @warning
> > > + * @b EXPERIMENTAL: this structure may change without prior notice
> > > + *
> > > + * Field description for packet field.
> > > + */
> > > +struct rte_flow_field_data {
> > > +	enum rte_flow_field_id field; /**< Field or memory type ID. */
> > > +	union {
> > > +		struct {
> > > +			/** Encapsulation level and tag index or flex item
> > handle. */
> > > +			union {
> > > +				struct {
> > > +					/**
> > > +					 * Packet encapsulation level
> containing
> > > +					 * the field to modify.
> > > +					 *
> > > +					 * - @p 0 requests the default
> behavior.
> > > +					 *   Depending on the packet type, it
> > > +					 *   can mean outermost, innermost
> or
> > > +					 *   anything in between.
> > > +					 *
> > > +					 *   It basically stands for the
> > > +					 *   innermost encapsulation level.
> > > +					 *   Modification can be performed
> > > +					 *   according to PMD and device
> > > +					 *   capabilities.
> > > +					 *
> > > +					 * - @p 1 requests modification to be
> > > +					 *   performed on the outermost
> packet
> > > +					 *   encapsulation level.
> > > +					 *
> > > +					 * - @p 2 and subsequent values
> > request
> > > +					 *   modification to be performed on
> > > +					 *   the specified inner packet
> > > +					 *   encapsulation level, from
> > > +					 *   outermost to innermost (lower to
> > > +					 *   higher values).
> > > +					 *
> > > +					 * Values other than @p 0 are not
> > > +					 * necessarily supported.
> > > +					 *
> > > +					 * @note that for MPLS field,
> > > +					 * encapsulation level also include
> > > +					 * tunnel since MPLS may appear in
> > > +					 * outer, inner or tunnel.
> > > +					 */
> > > +					uint8_t level;
> > > +					union {
> > > +						/**
> > > +						 * Tag index array inside
> > > +						 * encapsulation level.
> > > +						 * Used for VLAN, MPLS or
> TAG
> > types.
> > > +						 */
> > > +						uint8_t tag_index;
> > > +						/**
> > > +						 * Geneve option identifier.
> > > +						 * Relevant only for
> > > +						 *
> > RTE_FLOW_FIELD_GENEVE_OPT_XXXX
> > > +						 * modification type.
> > > +						 */
> > > +						struct {
> > > +							/**
> > > +							 * Geneve option
> type.
> > > +							 */
> > > +							uint8_t type;
> > > +							/**
> > > +							 * Geneve option
> class.
> > > +							 */
> > > +							rte_be16_t class_id;
> > > +						};
> > > +					};
> > > +				};
> > > +				struct rte_flow_item_flex_handle
> *flex_handle;
> > > +			};
> > > +			/** Number of bits to skip from a field. */
> > > +			uint32_t offset;
> > > +		};
> > > +		/**
> > > +		 * Immediate value for RTE_FLOW_FIELD_VALUE, presented
> in
> > the
> > > +		 * same byte order and length as in relevant
> rte_flow_item_xxx.
> > > +		 * The immediate source bitfield offset is inherited from
> > > +		 * the destination's one.
> > > +		 */
> > > +		uint8_t value[16];
> > > +		/**
> > > +		 * Memory address for RTE_FLOW_FIELD_POINTER, memory
> > layout
> > > +		 * should be the same as for relevant field in the
> > > +		 * rte_flow_item_xxx structure.
> > > +		 */
> > > +		void *pvalue;
> > > +	};
> > > +};
> > > +
> > >
> >
> > I am aware that you are just moving the above struct, but it is nested too
> much
> > which is making it hard to read.
> >
> > As you are touching it, can we extract some structs and make this struct less
> > nested, what do you think?
> > Of course it needs to be done in separate patch, as a preperation/clean-up
> patch
> > before moving it around.
> 
> Agree the struct maybe a bit nested. But not sure how it was discussed
> before during the last new member was added... @Ori, Do you have any idea
> about this?
> 

As far as I remember, it was never discussed, 

I think for this series we should keep it as is, and revise it later.

Best,
Ori
> And if it is really expected, I believe another new thread is worth for that
> change,  better not be in that series.
> Need to discuss the new struct name and other stuff. What do you think?
> 
> >
> > <...>
> >
> > > +/**
> > > + *
> > > + * RTE_FLOW_ITEM_TYPE_COMPARE
> > > + *
> > > + * Matches the packet with compare result.
> > > + *
> > > + * The operation means a compare with b result.
> > > + */
> > > +struct rte_flow_item_compare {
> > > +	enum rte_flow_item_compare_op operation; /* The compare
> operation.
> > */
> > > +	struct rte_flow_field_data a;		 /* Field be compared.  */
> > > +	struct rte_flow_field_data b;		 /* Field as comparator. */
> > >
> >
> > Variable names 'a' and 'b' are not descriptive although it may be OK since
> there is
> > no significance to the values, but other option can be 'first' and 'second',
> but
> > overall not strong opinion.
> 
> Yes, thanks for the suggestion, in fact we also discussed about the name a lot,
> finally we choose the widely used 'a' and 'b'
> 
> Thanks


^ permalink raw reply	[flat|nested] 66+ messages in thread

* Re: [PATCH v3 2/3] ethdev: add compare item
  2024-01-31 15:56           ` Ori Kam
@ 2024-01-31 16:46             ` Ferruh Yigit
  2024-01-31 17:43               ` Ori Kam
  2024-02-01  0:31               ` Suanming Mou
  0 siblings, 2 replies; 66+ messages in thread
From: Ferruh Yigit @ 2024-01-31 16:46 UTC (permalink / raw)
  To: Ori Kam, Suanming Mou, Aman Singh, Yuying Zhang,
	NBU-Contact-Thomas Monjalon (EXTERNAL),
	Andrew Rybchenko
  Cc: dev

On 1/31/2024 3:56 PM, Ori Kam wrote:
> Hi
> 
>> -----Original Message-----
>> From: Suanming Mou <suanmingm@nvidia.com>
>> Sent: Wednesday, January 31, 2024 4:48 AM
>>
>> Hi,
>>
>>> -----Original Message-----
>>> From: Ferruh Yigit <ferruh.yigit@amd.com>
>>> Sent: Wednesday, January 31, 2024 1:34 AM
>>> To: Suanming Mou <suanmingm@nvidia.com>; Ori Kam
>> <orika@nvidia.com>;
>>> Aman Singh <aman.deep.singh@intel.com>; Yuying Zhang
>>> <yuying.zhang@intel.com>; NBU-Contact-Thomas Monjalon (EXTERNAL)
>>> <thomas@monjalon.net>; Andrew Rybchenko
>>> <andrew.rybchenko@oktetlabs.ru>
>>> Cc: dev@dpdk.org
>>> Subject: Re: [PATCH v3 2/3] ethdev: add compare item
>>>
>>> On 1/15/2024 9:13 AM, Suanming Mou wrote:
>>>> The new item type is added for the case user wants to match traffic
>>>> based on packet field compare result with other fields or immediate
>>>> value.
>>>>
>>>> e.g. take advantage the compare item user will be able to accumulate a
>>>> IPv4/TCP packet's TCP data_offset and IPv4 IHL field to a tag
>>>> register, then compare the tag register with IPv4 header total length
>>>> to understand the packet has payload or not.
>>>>
>>>
>>> ack, above sample makes it easier to understand.
>>>
>>> This patch is adding testpmd commands, can you please provide some
>> sample
>>> commands in commit log?
>>> The more samples are better, as far as I remember there was a testpmd
>>> documentation that documents the sample usages, can you please check
>> for it?
> 
> [Snip ..]
> 
>>>
>>>> +/**
>>>> + * @warning
>>>> + * @b EXPERIMENTAL: this structure may change without prior notice
>>>> + *
>>>> + * Field description for packet field.
>>>> + */
>>>> +struct rte_flow_field_data {
>>>> +	enum rte_flow_field_id field; /**< Field or memory type ID. */
>>>> +	union {
>>>> +		struct {
>>>> +			/** Encapsulation level and tag index or flex item
>>> handle. */
>>>> +			union {
>>>> +				struct {
>>>> +					/**
>>>> +					 * Packet encapsulation level
>> containing
>>>> +					 * the field to modify.
>>>> +					 *
>>>> +					 * - @p 0 requests the default
>> behavior.
>>>> +					 *   Depending on the packet type, it
>>>> +					 *   can mean outermost, innermost
>> or
>>>> +					 *   anything in between.
>>>> +					 *
>>>> +					 *   It basically stands for the
>>>> +					 *   innermost encapsulation level.
>>>> +					 *   Modification can be performed
>>>> +					 *   according to PMD and device
>>>> +					 *   capabilities.
>>>> +					 *
>>>> +					 * - @p 1 requests modification to be
>>>> +					 *   performed on the outermost
>> packet
>>>> +					 *   encapsulation level.
>>>> +					 *
>>>> +					 * - @p 2 and subsequent values
>>> request
>>>> +					 *   modification to be performed on
>>>> +					 *   the specified inner packet
>>>> +					 *   encapsulation level, from
>>>> +					 *   outermost to innermost (lower to
>>>> +					 *   higher values).
>>>> +					 *
>>>> +					 * Values other than @p 0 are not
>>>> +					 * necessarily supported.
>>>> +					 *
>>>> +					 * @note that for MPLS field,
>>>> +					 * encapsulation level also include
>>>> +					 * tunnel since MPLS may appear in
>>>> +					 * outer, inner or tunnel.
>>>> +					 */
>>>> +					uint8_t level;
>>>> +					union {
>>>> +						/**
>>>> +						 * Tag index array inside
>>>> +						 * encapsulation level.
>>>> +						 * Used for VLAN, MPLS or
>> TAG
>>> types.
>>>> +						 */
>>>> +						uint8_t tag_index;
>>>> +						/**
>>>> +						 * Geneve option identifier.
>>>> +						 * Relevant only for
>>>> +						 *
>>> RTE_FLOW_FIELD_GENEVE_OPT_XXXX
>>>> +						 * modification type.
>>>> +						 */
>>>> +						struct {
>>>> +							/**
>>>> +							 * Geneve option
>> type.
>>>> +							 */
>>>> +							uint8_t type;
>>>> +							/**
>>>> +							 * Geneve option
>> class.
>>>> +							 */
>>>> +							rte_be16_t class_id;
>>>> +						};
>>>> +					};
>>>> +				};
>>>> +				struct rte_flow_item_flex_handle
>> *flex_handle;
>>>> +			};
>>>> +			/** Number of bits to skip from a field. */
>>>> +			uint32_t offset;
>>>> +		};
>>>> +		/**
>>>> +		 * Immediate value for RTE_FLOW_FIELD_VALUE, presented
>> in
>>> the
>>>> +		 * same byte order and length as in relevant
>> rte_flow_item_xxx.
>>>> +		 * The immediate source bitfield offset is inherited from
>>>> +		 * the destination's one.
>>>> +		 */
>>>> +		uint8_t value[16];
>>>> +		/**
>>>> +		 * Memory address for RTE_FLOW_FIELD_POINTER, memory
>>> layout
>>>> +		 * should be the same as for relevant field in the
>>>> +		 * rte_flow_item_xxx structure.
>>>> +		 */
>>>> +		void *pvalue;
>>>> +	};
>>>> +};
>>>> +
>>>>
>>>
>>> I am aware that you are just moving the above struct, but it is nested too
>> much
>>> which is making it hard to read.
>>>
>>> As you are touching it, can we extract some structs and make this struct less
>>> nested, what do you think?
>>> Of course it needs to be done in separate patch, as a preperation/clean-up
>> patch
>>> before moving it around.
>>
>> Agree the struct maybe a bit nested. But not sure how it was discussed
>> before during the last new member was added... @Ori, Do you have any idea
>> about this?
>>
> 
> As far as I remember, it was never discussed, 
> 
> I think for this series we should keep it as is, and revise it later.
> 

If you don't want to make this set more complex with this, that is OK as
long as it is addressed at some point.

> Best,
> Ori
>> And if it is really expected, I believe another new thread is worth for that
>> change,  better not be in that series.
>> Need to discuss the new struct name and other stuff. What do you think?
>>
>>>
>>> <...>
>>>
>>>> +/**
>>>> + *
>>>> + * RTE_FLOW_ITEM_TYPE_COMPARE
>>>> + *
>>>> + * Matches the packet with compare result.
>>>> + *
>>>> + * The operation means a compare with b result.
>>>> + */
>>>> +struct rte_flow_item_compare {
>>>> +	enum rte_flow_item_compare_op operation; /* The compare
>> operation.
>>> */
>>>> +	struct rte_flow_field_data a;		 /* Field be compared.  */
>>>> +	struct rte_flow_field_data b;		 /* Field as comparator. */
>>>>
>>>
>>> Variable names 'a' and 'b' are not descriptive although it may be OK since
>> there is
>>> no significance to the values, but other option can be 'first' and 'second',
>> but
>>> overall not strong opinion.
>>
>> Yes, thanks for the suggestion, in fact we also discussed about the name a lot,
>> finally we choose the widely used 'a' and 'b'
>>
>> Thanks
> 


^ permalink raw reply	[flat|nested] 66+ messages in thread

* RE: [PATCH v3 2/3] ethdev: add compare item
  2024-01-31 16:46             ` Ferruh Yigit
@ 2024-01-31 17:43               ` Ori Kam
  2024-01-31 17:54                 ` Ferruh Yigit
  2024-02-01  0:31               ` Suanming Mou
  1 sibling, 1 reply; 66+ messages in thread
From: Ori Kam @ 2024-01-31 17:43 UTC (permalink / raw)
  To: Ferruh Yigit, Suanming Mou, Aman Singh, Yuying Zhang,
	NBU-Contact-Thomas Monjalon (EXTERNAL),
	Andrew Rybchenko
  Cc: dev



> -----Original Message-----
> From: Ferruh Yigit <ferruh.yigit@amd.com>
> Sent: Wednesday, January 31, 2024 6:46 PM
> Subject: Re: [PATCH v3 2/3] ethdev: add compare item
> 
> On 1/31/2024 3:56 PM, Ori Kam wrote:
> > Hi
> >
> >> -----Original Message-----
> >> From: Suanming Mou <suanmingm@nvidia.com>
> >> Sent: Wednesday, January 31, 2024 4:48 AM
> >>
> >> Hi,
> >>
> >>> -----Original Message-----
> >>> From: Ferruh Yigit <ferruh.yigit@amd.com>
> >>> Sent: Wednesday, January 31, 2024 1:34 AM
> >>> To: Suanming Mou <suanmingm@nvidia.com>; Ori Kam
> >> <orika@nvidia.com>;
> >>> Aman Singh <aman.deep.singh@intel.com>; Yuying Zhang
> >>> <yuying.zhang@intel.com>; NBU-Contact-Thomas Monjalon (EXTERNAL)
> >>> <thomas@monjalon.net>; Andrew Rybchenko
> >>> <andrew.rybchenko@oktetlabs.ru>
> >>> Cc: dev@dpdk.org
> >>> Subject: Re: [PATCH v3 2/3] ethdev: add compare item
> >>>
> >>> On 1/15/2024 9:13 AM, Suanming Mou wrote:
> >>>> The new item type is added for the case user wants to match traffic
> >>>> based on packet field compare result with other fields or immediate
> >>>> value.
> >>>>
> >>>> e.g. take advantage the compare item user will be able to accumulate a
> >>>> IPv4/TCP packet's TCP data_offset and IPv4 IHL field to a tag
> >>>> register, then compare the tag register with IPv4 header total length
> >>>> to understand the packet has payload or not.
> >>>>
> >>>
> >>> ack, above sample makes it easier to understand.
> >>>
> >>> This patch is adding testpmd commands, can you please provide some
> >> sample
> >>> commands in commit log?
> >>> The more samples are better, as far as I remember there was a testpmd
> >>> documentation that documents the sample usages, can you please check
> >> for it?
> >
> > [Snip ..]
> >
> >>>
> >>>> +/**
> >>>> + * @warning
> >>>> + * @b EXPERIMENTAL: this structure may change without prior notice
> >>>> + *
> >>>> + * Field description for packet field.
> >>>> + */
> >>>> +struct rte_flow_field_data {
> >>>> +	enum rte_flow_field_id field; /**< Field or memory type ID. */
> >>>> +	union {
> >>>> +		struct {
> >>>> +			/** Encapsulation level and tag index or flex item
> >>> handle. */
> >>>> +			union {
> >>>> +				struct {
> >>>> +					/**
> >>>> +					 * Packet encapsulation level
> >> containing
> >>>> +					 * the field to modify.
> >>>> +					 *
> >>>> +					 * - @p 0 requests the default
> >> behavior.
> >>>> +					 *   Depending on the packet type, it
> >>>> +					 *   can mean outermost, innermost
> >> or
> >>>> +					 *   anything in between.
> >>>> +					 *
> >>>> +					 *   It basically stands for the
> >>>> +					 *   innermost encapsulation level.
> >>>> +					 *   Modification can be performed
> >>>> +					 *   according to PMD and device
> >>>> +					 *   capabilities.
> >>>> +					 *
> >>>> +					 * - @p 1 requests modification to be
> >>>> +					 *   performed on the outermost
> >> packet
> >>>> +					 *   encapsulation level.
> >>>> +					 *
> >>>> +					 * - @p 2 and subsequent values
> >>> request
> >>>> +					 *   modification to be performed on
> >>>> +					 *   the specified inner packet
> >>>> +					 *   encapsulation level, from
> >>>> +					 *   outermost to innermost (lower to
> >>>> +					 *   higher values).
> >>>> +					 *
> >>>> +					 * Values other than @p 0 are not
> >>>> +					 * necessarily supported.
> >>>> +					 *
> >>>> +					 * @note that for MPLS field,
> >>>> +					 * encapsulation level also include
> >>>> +					 * tunnel since MPLS may appear in
> >>>> +					 * outer, inner or tunnel.
> >>>> +					 */
> >>>> +					uint8_t level;
> >>>> +					union {
> >>>> +						/**
> >>>> +						 * Tag index array inside
> >>>> +						 * encapsulation level.
> >>>> +						 * Used for VLAN, MPLS or
> >> TAG
> >>> types.
> >>>> +						 */
> >>>> +						uint8_t tag_index;
> >>>> +						/**
> >>>> +						 * Geneve option identifier.
> >>>> +						 * Relevant only for
> >>>> +						 *
> >>> RTE_FLOW_FIELD_GENEVE_OPT_XXXX
> >>>> +						 * modification type.
> >>>> +						 */
> >>>> +						struct {
> >>>> +							/**
> >>>> +							 * Geneve option
> >> type.
> >>>> +							 */
> >>>> +							uint8_t type;
> >>>> +							/**
> >>>> +							 * Geneve option
> >> class.
> >>>> +							 */
> >>>> +							rte_be16_t class_id;
> >>>> +						};
> >>>> +					};
> >>>> +				};
> >>>> +				struct rte_flow_item_flex_handle
> >> *flex_handle;
> >>>> +			};
> >>>> +			/** Number of bits to skip from a field. */
> >>>> +			uint32_t offset;
> >>>> +		};
> >>>> +		/**
> >>>> +		 * Immediate value for RTE_FLOW_FIELD_VALUE, presented
> >> in
> >>> the
> >>>> +		 * same byte order and length as in relevant
> >> rte_flow_item_xxx.
> >>>> +		 * The immediate source bitfield offset is inherited from
> >>>> +		 * the destination's one.
> >>>> +		 */
> >>>> +		uint8_t value[16];
> >>>> +		/**
> >>>> +		 * Memory address for RTE_FLOW_FIELD_POINTER, memory
> >>> layout
> >>>> +		 * should be the same as for relevant field in the
> >>>> +		 * rte_flow_item_xxx structure.
> >>>> +		 */
> >>>> +		void *pvalue;
> >>>> +	};
> >>>> +};
> >>>> +
> >>>>
> >>>
> >>> I am aware that you are just moving the above struct, but it is nested too
> >> much
> >>> which is making it hard to read.
> >>>
> >>> As you are touching it, can we extract some structs and make this struct
> less
> >>> nested, what do you think?
> >>> Of course it needs to be done in separate patch, as a preperation/clean-
> up
> >> patch
> >>> before moving it around.
> >>
> >> Agree the struct maybe a bit nested. But not sure how it was discussed
> >> before during the last new member was added... @Ori, Do you have any
> idea
> >> about this?
> >>
> >
> > As far as I remember, it was never discussed,
> >
> > I think for this series we should keep it as is, and revise it later.
> >
> 
> If you don't want to make this set more complex with this, that is OK as
> long as it is addressed at some point.

Agree,
If you have suggestions, I will be more than happy to hear.

> 
> > Best,
> > Ori
> >> And if it is really expected, I believe another new thread is worth for that
> >> change,  better not be in that series.
> >> Need to discuss the new struct name and other stuff. What do you think?
> >>
> >>>
> >>> <...>
> >>>
> >>>> +/**
> >>>> + *
> >>>> + * RTE_FLOW_ITEM_TYPE_COMPARE
> >>>> + *
> >>>> + * Matches the packet with compare result.
> >>>> + *
> >>>> + * The operation means a compare with b result.
> >>>> + */
> >>>> +struct rte_flow_item_compare {
> >>>> +	enum rte_flow_item_compare_op operation; /* The compare
> >> operation.
> >>> */
> >>>> +	struct rte_flow_field_data a;		 /* Field be compared.  */
> >>>> +	struct rte_flow_field_data b;		 /* Field as comparator. */
> >>>>
> >>>
> >>> Variable names 'a' and 'b' are not descriptive although it may be OK since
> >> there is
> >>> no significance to the values, but other option can be 'first' and 'second',
> >> but
> >>> overall not strong opinion.
> >>
> >> Yes, thanks for the suggestion, in fact we also discussed about the name a
> lot,
> >> finally we choose the widely used 'a' and 'b'
> >>
> >> Thanks
> >


^ permalink raw reply	[flat|nested] 66+ messages in thread

* Re: [PATCH v3 2/3] ethdev: add compare item
  2024-01-31 17:43               ` Ori Kam
@ 2024-01-31 17:54                 ` Ferruh Yigit
  2024-02-01  6:51                   ` Ori Kam
  0 siblings, 1 reply; 66+ messages in thread
From: Ferruh Yigit @ 2024-01-31 17:54 UTC (permalink / raw)
  To: Ori Kam, Suanming Mou, Aman Singh, Yuying Zhang,
	NBU-Contact-Thomas Monjalon (EXTERNAL),
	Andrew Rybchenko
  Cc: dev

On 1/31/2024 5:43 PM, Ori Kam wrote:
> 
> 
>> -----Original Message-----
>> From: Ferruh Yigit <ferruh.yigit@amd.com>
>> Sent: Wednesday, January 31, 2024 6:46 PM
>> Subject: Re: [PATCH v3 2/3] ethdev: add compare item
>>
>> On 1/31/2024 3:56 PM, Ori Kam wrote:
>>> Hi
>>>
>>>> -----Original Message-----
>>>> From: Suanming Mou <suanmingm@nvidia.com>
>>>> Sent: Wednesday, January 31, 2024 4:48 AM
>>>>
>>>> Hi,
>>>>
>>>>> -----Original Message-----
>>>>> From: Ferruh Yigit <ferruh.yigit@amd.com>
>>>>> Sent: Wednesday, January 31, 2024 1:34 AM
>>>>> To: Suanming Mou <suanmingm@nvidia.com>; Ori Kam
>>>> <orika@nvidia.com>;
>>>>> Aman Singh <aman.deep.singh@intel.com>; Yuying Zhang
>>>>> <yuying.zhang@intel.com>; NBU-Contact-Thomas Monjalon (EXTERNAL)
>>>>> <thomas@monjalon.net>; Andrew Rybchenko
>>>>> <andrew.rybchenko@oktetlabs.ru>
>>>>> Cc: dev@dpdk.org
>>>>> Subject: Re: [PATCH v3 2/3] ethdev: add compare item
>>>>>
>>>>> On 1/15/2024 9:13 AM, Suanming Mou wrote:
>>>>>> The new item type is added for the case user wants to match traffic
>>>>>> based on packet field compare result with other fields or immediate
>>>>>> value.
>>>>>>
>>>>>> e.g. take advantage the compare item user will be able to accumulate a
>>>>>> IPv4/TCP packet's TCP data_offset and IPv4 IHL field to a tag
>>>>>> register, then compare the tag register with IPv4 header total length
>>>>>> to understand the packet has payload or not.
>>>>>>
>>>>>
>>>>> ack, above sample makes it easier to understand.
>>>>>
>>>>> This patch is adding testpmd commands, can you please provide some
>>>> sample
>>>>> commands in commit log?
>>>>> The more samples are better, as far as I remember there was a testpmd
>>>>> documentation that documents the sample usages, can you please check
>>>> for it?
>>>
>>> [Snip ..]
>>>
>>>>>
>>>>>> +/**
>>>>>> + * @warning
>>>>>> + * @b EXPERIMENTAL: this structure may change without prior notice
>>>>>> + *
>>>>>> + * Field description for packet field.
>>>>>> + */
>>>>>> +struct rte_flow_field_data {
>>>>>> +	enum rte_flow_field_id field; /**< Field or memory type ID. */
>>>>>> +	union {
>>>>>> +		struct {
>>>>>> +			/** Encapsulation level and tag index or flex item
>>>>> handle. */
>>>>>> +			union {
>>>>>> +				struct {
>>>>>> +					/**
>>>>>> +					 * Packet encapsulation level
>>>> containing
>>>>>> +					 * the field to modify.
>>>>>> +					 *
>>>>>> +					 * - @p 0 requests the default
>>>> behavior.
>>>>>> +					 *   Depending on the packet type, it
>>>>>> +					 *   can mean outermost, innermost
>>>> or
>>>>>> +					 *   anything in between.
>>>>>> +					 *
>>>>>> +					 *   It basically stands for the
>>>>>> +					 *   innermost encapsulation level.
>>>>>> +					 *   Modification can be performed
>>>>>> +					 *   according to PMD and device
>>>>>> +					 *   capabilities.
>>>>>> +					 *
>>>>>> +					 * - @p 1 requests modification to be
>>>>>> +					 *   performed on the outermost
>>>> packet
>>>>>> +					 *   encapsulation level.
>>>>>> +					 *
>>>>>> +					 * - @p 2 and subsequent values
>>>>> request
>>>>>> +					 *   modification to be performed on
>>>>>> +					 *   the specified inner packet
>>>>>> +					 *   encapsulation level, from
>>>>>> +					 *   outermost to innermost (lower to
>>>>>> +					 *   higher values).
>>>>>> +					 *
>>>>>> +					 * Values other than @p 0 are not
>>>>>> +					 * necessarily supported.
>>>>>> +					 *
>>>>>> +					 * @note that for MPLS field,
>>>>>> +					 * encapsulation level also include
>>>>>> +					 * tunnel since MPLS may appear in
>>>>>> +					 * outer, inner or tunnel.
>>>>>> +					 */
>>>>>> +					uint8_t level;
>>>>>> +					union {
>>>>>> +						/**
>>>>>> +						 * Tag index array inside
>>>>>> +						 * encapsulation level.
>>>>>> +						 * Used for VLAN, MPLS or
>>>> TAG
>>>>> types.
>>>>>> +						 */
>>>>>> +						uint8_t tag_index;
>>>>>> +						/**
>>>>>> +						 * Geneve option identifier.
>>>>>> +						 * Relevant only for
>>>>>> +						 *
>>>>> RTE_FLOW_FIELD_GENEVE_OPT_XXXX
>>>>>> +						 * modification type.
>>>>>> +						 */
>>>>>> +						struct {
>>>>>> +							/**
>>>>>> +							 * Geneve option
>>>> type.
>>>>>> +							 */
>>>>>> +							uint8_t type;
>>>>>> +							/**
>>>>>> +							 * Geneve option
>>>> class.
>>>>>> +							 */
>>>>>> +							rte_be16_t class_id;
>>>>>> +						};
>>>>>> +					};
>>>>>> +				};
>>>>>> +				struct rte_flow_item_flex_handle
>>>> *flex_handle;
>>>>>> +			};
>>>>>> +			/** Number of bits to skip from a field. */
>>>>>> +			uint32_t offset;
>>>>>> +		};
>>>>>> +		/**
>>>>>> +		 * Immediate value for RTE_FLOW_FIELD_VALUE, presented
>>>> in
>>>>> the
>>>>>> +		 * same byte order and length as in relevant
>>>> rte_flow_item_xxx.
>>>>>> +		 * The immediate source bitfield offset is inherited from
>>>>>> +		 * the destination's one.
>>>>>> +		 */
>>>>>> +		uint8_t value[16];
>>>>>> +		/**
>>>>>> +		 * Memory address for RTE_FLOW_FIELD_POINTER, memory
>>>>> layout
>>>>>> +		 * should be the same as for relevant field in the
>>>>>> +		 * rte_flow_item_xxx structure.
>>>>>> +		 */
>>>>>> +		void *pvalue;
>>>>>> +	};
>>>>>> +};
>>>>>> +
>>>>>>
>>>>>
>>>>> I am aware that you are just moving the above struct, but it is nested too
>>>> much
>>>>> which is making it hard to read.
>>>>>
>>>>> As you are touching it, can we extract some structs and make this struct
>> less
>>>>> nested, what do you think?
>>>>> Of course it needs to be done in separate patch, as a preperation/clean-
>> up
>>>> patch
>>>>> before moving it around.
>>>>
>>>> Agree the struct maybe a bit nested. But not sure how it was discussed
>>>> before during the last new member was added... @Ori, Do you have any
>> idea
>>>> about this?
>>>>
>>>
>>> As far as I remember, it was never discussed,
>>>
>>> I think for this series we should keep it as is, and revise it later.
>>>
>>
>> If you don't want to make this set more complex with this, that is OK as
>> long as it is addressed at some point.
> 
> Agree,
> If you have suggestions, I will be more than happy to hear.
> 

For the struct?
Simply extracting the inner structs as named structs to reduce the
nested structs, does this make sense?



^ permalink raw reply	[flat|nested] 66+ messages in thread

* RE: [PATCH v3 2/3] ethdev: add compare item
  2024-01-31 16:46             ` Ferruh Yigit
  2024-01-31 17:43               ` Ori Kam
@ 2024-02-01  0:31               ` Suanming Mou
  1 sibling, 0 replies; 66+ messages in thread
From: Suanming Mou @ 2024-02-01  0:31 UTC (permalink / raw)
  To: Ferruh Yigit, Ori Kam, Aman Singh, Yuying Zhang,
	NBU-Contact-Thomas Monjalon (EXTERNAL),
	Andrew Rybchenko
  Cc: dev



> -----Original Message-----
> From: Ferruh Yigit <ferruh.yigit@amd.com>
> Sent: Thursday, February 1, 2024 12:46 AM
> To: Ori Kam <orika@nvidia.com>; Suanming Mou <suanmingm@nvidia.com>;
> Aman Singh <aman.deep.singh@intel.com>; Yuying Zhang
> <yuying.zhang@intel.com>; NBU-Contact-Thomas Monjalon (EXTERNAL)
> <thomas@monjalon.net>; Andrew Rybchenko
> <andrew.rybchenko@oktetlabs.ru>
> Cc: dev@dpdk.org
> Subject: Re: [PATCH v3 2/3] ethdev: add compare item
> 
> On 1/31/2024 3:56 PM, Ori Kam wrote:
> > Hi
> >
> >> -----Original Message-----
> >> From: Suanming Mou <suanmingm@nvidia.com>
> >> Sent: Wednesday, January 31, 2024 4:48 AM
> >>
> >> Hi,
> >>
> >>> -----Original Message-----
> >>> From: Ferruh Yigit <ferruh.yigit@amd.com>
> >>> Sent: Wednesday, January 31, 2024 1:34 AM
> >>> To: Suanming Mou <suanmingm@nvidia.com>; Ori Kam
> >> <orika@nvidia.com>;
> >>> Aman Singh <aman.deep.singh@intel.com>; Yuying Zhang
> >>> <yuying.zhang@intel.com>; NBU-Contact-Thomas Monjalon (EXTERNAL)
> >>> <thomas@monjalon.net>; Andrew Rybchenko
> >>> <andrew.rybchenko@oktetlabs.ru>
> >>> Cc: dev@dpdk.org
> >>> Subject: Re: [PATCH v3 2/3] ethdev: add compare item
> >>>
> >>> On 1/15/2024 9:13 AM, Suanming Mou wrote:
> >>>> The new item type is added for the case user wants to match traffic
> >>>> based on packet field compare result with other fields or immediate
> >>>> value.
> >>>>
> >>>> e.g. take advantage the compare item user will be able to
> >>>> accumulate a IPv4/TCP packet's TCP data_offset and IPv4 IHL field
> >>>> to a tag register, then compare the tag register with IPv4 header
> >>>> total length to understand the packet has payload or not.
> >>>>
> >>>
> >>> ack, above sample makes it easier to understand.
> >>>
> >>> This patch is adding testpmd commands, can you please provide some
> >> sample
> >>> commands in commit log?
> >>> The more samples are better, as far as I remember there was a
> >>> testpmd documentation that documents the sample usages, can you
> >>> please check
> >> for it?
> >
> > [Snip ..]
> >
> >>>
> >>>> +/**
> >>>> + * @warning
> >>>> + * @b EXPERIMENTAL: this structure may change without prior notice
> >>>> + *
> >>>> + * Field description for packet field.
> >>>> + */
> >>>> +struct rte_flow_field_data {
> >>>> +	enum rte_flow_field_id field; /**< Field or memory type ID. */
> >>>> +	union {
> >>>> +		struct {
> >>>> +			/** Encapsulation level and tag index or flex item
> >>> handle. */
> >>>> +			union {
> >>>> +				struct {
> >>>> +					/**
> >>>> +					 * Packet encapsulation level
> >> containing
> >>>> +					 * the field to modify.
> >>>> +					 *
> >>>> +					 * - @p 0 requests the default
> >> behavior.
> >>>> +					 *   Depending on the packet type, it
> >>>> +					 *   can mean outermost, innermost
> >> or
> >>>> +					 *   anything in between.
> >>>> +					 *
> >>>> +					 *   It basically stands for the
> >>>> +					 *   innermost encapsulation level.
> >>>> +					 *   Modification can be performed
> >>>> +					 *   according to PMD and device
> >>>> +					 *   capabilities.
> >>>> +					 *
> >>>> +					 * - @p 1 requests modification to be
> >>>> +					 *   performed on the outermost
> >> packet
> >>>> +					 *   encapsulation level.
> >>>> +					 *
> >>>> +					 * - @p 2 and subsequent values
> >>> request
> >>>> +					 *   modification to be performed on
> >>>> +					 *   the specified inner packet
> >>>> +					 *   encapsulation level, from
> >>>> +					 *   outermost to innermost (lower to
> >>>> +					 *   higher values).
> >>>> +					 *
> >>>> +					 * Values other than @p 0 are not
> >>>> +					 * necessarily supported.
> >>>> +					 *
> >>>> +					 * @note that for MPLS field,
> >>>> +					 * encapsulation level also include
> >>>> +					 * tunnel since MPLS may appear in
> >>>> +					 * outer, inner or tunnel.
> >>>> +					 */
> >>>> +					uint8_t level;
> >>>> +					union {
> >>>> +						/**
> >>>> +						 * Tag index array inside
> >>>> +						 * encapsulation level.
> >>>> +						 * Used for VLAN, MPLS or
> >> TAG
> >>> types.
> >>>> +						 */
> >>>> +						uint8_t tag_index;
> >>>> +						/**
> >>>> +						 * Geneve option identifier.
> >>>> +						 * Relevant only for
> >>>> +						 *
> >>> RTE_FLOW_FIELD_GENEVE_OPT_XXXX
> >>>> +						 * modification type.
> >>>> +						 */
> >>>> +						struct {
> >>>> +							/**
> >>>> +							 * Geneve option
> >> type.
> >>>> +							 */
> >>>> +							uint8_t type;
> >>>> +							/**
> >>>> +							 * Geneve option
> >> class.
> >>>> +							 */
> >>>> +							rte_be16_t class_id;
> >>>> +						};
> >>>> +					};
> >>>> +				};
> >>>> +				struct rte_flow_item_flex_handle
> >> *flex_handle;
> >>>> +			};
> >>>> +			/** Number of bits to skip from a field. */
> >>>> +			uint32_t offset;
> >>>> +		};
> >>>> +		/**
> >>>> +		 * Immediate value for RTE_FLOW_FIELD_VALUE, presented
> >> in
> >>> the
> >>>> +		 * same byte order and length as in relevant
> >> rte_flow_item_xxx.
> >>>> +		 * The immediate source bitfield offset is inherited from
> >>>> +		 * the destination's one.
> >>>> +		 */
> >>>> +		uint8_t value[16];
> >>>> +		/**
> >>>> +		 * Memory address for RTE_FLOW_FIELD_POINTER, memory
> >>> layout
> >>>> +		 * should be the same as for relevant field in the
> >>>> +		 * rte_flow_item_xxx structure.
> >>>> +		 */
> >>>> +		void *pvalue;
> >>>> +	};
> >>>> +};
> >>>> +
> >>>>
> >>>
> >>> I am aware that you are just moving the above struct, but it is
> >>> nested too
> >> much
> >>> which is making it hard to read.
> >>>
> >>> As you are touching it, can we extract some structs and make this
> >>> struct less nested, what do you think?
> >>> Of course it needs to be done in separate patch, as a
> >>> preperation/clean-up
> >> patch
> >>> before moving it around.
> >>
> >> Agree the struct maybe a bit nested. But not sure how it was
> >> discussed before during the last new member was added... @Ori, Do you
> >> have any idea about this?
> >>
> >
> > As far as I remember, it was never discussed,
> >
> > I think for this series we should keep it as is, and revise it later.
> >
> 
> If you don't want to make this set more complex with this, that is OK as long
> as it is addressed at some point.

OK, thanks. As it is addressed, will update v4 soon.

> 
> > Best,
> > Ori
> >> And if it is really expected, I believe another new thread is worth
> >> for that change,  better not be in that series.
> >> Need to discuss the new struct name and other stuff. What do you think?
> >>
> >>>
> >>> <...>
> >>>
> >>>> +/**
> >>>> + *
> >>>> + * RTE_FLOW_ITEM_TYPE_COMPARE
> >>>> + *
> >>>> + * Matches the packet with compare result.
> >>>> + *
> >>>> + * The operation means a compare with b result.
> >>>> + */
> >>>> +struct rte_flow_item_compare {
> >>>> +	enum rte_flow_item_compare_op operation; /* The compare
> >> operation.
> >>> */
> >>>> +	struct rte_flow_field_data a;		 /* Field be compared.  */
> >>>> +	struct rte_flow_field_data b;		 /* Field as comparator. */
> >>>>
> >>>
> >>> Variable names 'a' and 'b' are not descriptive although it may be OK
> >>> since
> >> there is
> >>> no significance to the values, but other option can be 'first' and
> >>> 'second',
> >> but
> >>> overall not strong opinion.
> >>
> >> Yes, thanks for the suggestion, in fact we also discussed about the
> >> name a lot, finally we choose the widely used 'a' and 'b'
> >>
> >> Thanks
> >


^ permalink raw reply	[flat|nested] 66+ messages in thread

* [PATCH v4 0/3] ethdev: add RTE_FLOW_ITEM_TYPE_COMPARE
  2023-12-14  3:12 [PATCH 0/2] ethdev: add RTE_FLOW_ITEM_TYPE_COMPARE Suanming Mou
                   ` (2 preceding siblings ...)
  2023-12-19  1:33 ` [PATCH v2 0/3] [PATCH 0/2] ethdev: add RTE_FLOW_ITEM_TYPE_COMPARE Suanming Mou
@ 2024-02-01  2:30 ` Suanming Mou
  2024-02-01  2:30   ` [PATCH v4 1/3] ethdev: rename action modify field data structure Suanming Mou
                     ` (2 more replies)
  2024-02-01 12:29 ` [PATCH v5 0/3] ethdev: add RTE_FLOW_ITEM_TYPE_COMPARE Suanming Mou
                   ` (2 subsequent siblings)
  6 siblings, 3 replies; 66+ messages in thread
From: Suanming Mou @ 2024-02-01  2:30 UTC (permalink / raw)
  To: ferruh.yigit; +Cc: dev, orika

The new item type is added for the case user wants to match traffic
based on packet field compare result with other fields or immediate
value.

e.g. take advantage the compare item user will be able to accumulate
a IPv4/TCP packet's TCP data_offset and IPv4 IHL field to a tag
register, then compare the tag register with IPv4 header total length
to understand the packet has payload or not.

The supported operations can be as below:
 - RTE_FLOW_ITEM_COMPARE_EQ (equal)
 - RTE_FLOW_ITEM_COMPARE_NE (not equal)
 - RTE_FLOW_ITEM_COMPARE_LT (less than)
 - RTE_FLOW_ITEM_COMPARE_LE (less than or equal)
 - RTE_FLOW_ITEM_COMPARE_GT (great than)
 - RTE_FLOW_ITEM_COMPARE_GE (great than or equal)

V4:
 - rebase on top of the latest version.
 - move ACTION_MODIFY_PATTERN_SIZE and modify_field_ids rename
   to first patch.
 - add comparison flow create sample in testpmd_funcs.rst.

V3:
 - fix code style missing empty line in rte_flow.rst.
 - fix missing the ABI change release notes.

V2:
 - Since modify field data struct is experiment, rename modify
   field data directly instead of adding new flow field struct.

Suanming Mou (3):
  ethdev: rename action modify field data structure
  ethdev: add compare item
  net/mlx5: add compare item support

 app/test-pmd/cmdline_flow.c                 | 416 +++++++++++++++++++-
 doc/guides/nics/features/default.ini        |   1 +
 doc/guides/nics/features/mlx5.ini           |   1 +
 doc/guides/nics/mlx5.rst                    |   7 +
 doc/guides/prog_guide/rte_flow.rst          |   9 +-
 doc/guides/rel_notes/release_24_03.rst      |   8 +
 doc/guides/testpmd_app_ug/testpmd_funcs.rst |  24 ++
 drivers/net/mlx5/mlx5_flow.c                |   4 +-
 drivers/net/mlx5/mlx5_flow.h                |  11 +-
 drivers/net/mlx5/mlx5_flow_dv.c             |  12 +-
 drivers/net/mlx5/mlx5_flow_geneve.c         |   2 +-
 drivers/net/mlx5/mlx5_flow_hw.c             |  75 +++-
 lib/ethdev/rte_flow.c                       |   1 +
 lib/ethdev/rte_flow.h                       | 328 ++++++++-------
 14 files changed, 725 insertions(+), 174 deletions(-)

-- 
2.34.1


^ permalink raw reply	[flat|nested] 66+ messages in thread

* [PATCH v4 1/3] ethdev: rename action modify field data structure
  2024-02-01  2:30 ` [PATCH v4 0/3] ethdev: add RTE_FLOW_ITEM_TYPE_COMPARE Suanming Mou
@ 2024-02-01  2:30   ` Suanming Mou
  2024-02-01  2:30   ` [PATCH v4 2/3] ethdev: add compare item Suanming Mou
  2024-02-01  2:30   ` [PATCH v4 3/3] net/mlx5: add compare item support Suanming Mou
  2 siblings, 0 replies; 66+ messages in thread
From: Suanming Mou @ 2024-02-01  2:30 UTC (permalink / raw)
  To: ferruh.yigit, Ori Kam, Aman Singh, Yuying Zhang, Matan Azrad,
	Viacheslav Ovsiienko, Thomas Monjalon, Andrew Rybchenko
  Cc: dev

Current rte_flow_action_modify_data struct describes the pkt
field perfectly and is used only in action.

It is planned to be used for item as well. This commit renames
it to "rte_flow_field_data" making it compatible to be used by item.

Signed-off-by: Suanming Mou <suanmingm@nvidia.com>
Acked-by: Ori Kam <orika@nvidia.com>
Acked-by: Andrew Rybchenko <andrew.rybchenko@oktetlabs.ru>
---
 app/test-pmd/cmdline_flow.c            | 22 +++++++++++-----------
 doc/guides/prog_guide/rte_flow.rst     |  2 +-
 doc/guides/rel_notes/release_24_03.rst |  1 +
 drivers/net/mlx5/mlx5_flow.c           |  4 ++--
 drivers/net/mlx5/mlx5_flow.h           |  8 ++++----
 drivers/net/mlx5/mlx5_flow_dv.c        | 12 ++++++------
 drivers/net/mlx5/mlx5_flow_geneve.c    |  2 +-
 lib/ethdev/rte_flow.h                  |  8 ++++----
 8 files changed, 30 insertions(+), 29 deletions(-)

diff --git a/app/test-pmd/cmdline_flow.c b/app/test-pmd/cmdline_flow.c
index 4062879552..4741ec679d 100644
--- a/app/test-pmd/cmdline_flow.c
+++ b/app/test-pmd/cmdline_flow.c
@@ -745,13 +745,13 @@ enum index {
 #define ITEM_RAW_SIZE \
 	(sizeof(struct rte_flow_item_raw) + ITEM_RAW_PATTERN_SIZE)
 
-/** Maximum size for external pattern in struct rte_flow_action_modify_data. */
-#define ACTION_MODIFY_PATTERN_SIZE 32
+/** Maximum size for external pattern in struct rte_flow_field_data. */
+#define FLOW_FIELD_PATTERN_SIZE 32
 
 /** Storage size for struct rte_flow_action_modify_field including pattern. */
 #define ACTION_MODIFY_SIZE \
 	(sizeof(struct rte_flow_action_modify_field) + \
-	ACTION_MODIFY_PATTERN_SIZE)
+	FLOW_FIELD_PATTERN_SIZE)
 
 /** Maximum number of queue indices in struct rte_flow_action_rss. */
 #define ACTION_RSS_QUEUE_NUM 128
@@ -945,7 +945,7 @@ static const char *const modify_field_ops[] = {
 	"set", "add", "sub", NULL
 };
 
-static const char *const modify_field_ids[] = {
+static const char *const flow_field_ids[] = {
 	"start", "mac_dst", "mac_src",
 	"vlan_type", "vlan_id", "mac_type",
 	"ipv4_dscp", "ipv4_ttl", "ipv4_src", "ipv4_dst",
@@ -7016,7 +7016,7 @@ static const struct token token_list[] = {
 			     ARGS_ENTRY_ARB(0, 0),
 			     ARGS_ENTRY_ARB
 				(sizeof(struct rte_flow_action_modify_field),
-				 ACTION_MODIFY_PATTERN_SIZE)),
+				 FLOW_FIELD_PATTERN_SIZE)),
 		.call = parse_vc_conf,
 	},
 	[ACTION_MODIFY_FIELD_WIDTH] = {
@@ -9828,10 +9828,10 @@ parse_vc_modify_field_id(struct context *ctx, const struct token *token,
 	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))
+	for (i = 0; flow_field_ids[i]; ++i)
+		if (!strcmp_partial(flow_field_ids[i], str, len))
 			break;
-	if (!modify_field_ids[i])
+	if (!flow_field_ids[i])
 		return -1;
 	if (!ctx->object)
 		return len;
@@ -12058,10 +12058,10 @@ comp_set_modify_field_id(struct context *ctx, const struct token *token,
 
 	RTE_SET_USED(token);
 	if (!buf)
-		return RTE_DIM(modify_field_ids);
-	if (ent >= RTE_DIM(modify_field_ids) - 1)
+		return RTE_DIM(flow_field_ids);
+	if (ent >= RTE_DIM(flow_field_ids) - 1)
 		return -1;
-	name = modify_field_ids[ent];
+	name = flow_field_ids[ent];
 	if (ctx->curr == ACTION_MODIFY_FIELD_SRC_TYPE ||
 	    (strcmp(name, "pointer") && strcmp(name, "value")))
 		return strlcpy(buf, name, size);
diff --git a/doc/guides/prog_guide/rte_flow.rst b/doc/guides/prog_guide/rte_flow.rst
index 900fdaefb6..f936a9ba19 100644
--- a/doc/guides/prog_guide/rte_flow.rst
+++ b/doc/guides/prog_guide/rte_flow.rst
@@ -3185,7 +3185,7 @@ destination offset as ``48``, and provide immediate value ``0xXXXX85XX``.
    | ``width``     | number of bits to use   |
    +---------------+-------------------------+
 
-.. _table_rte_flow_action_modify_data:
+.. _table_rte_flow_field_data:
 
 .. table:: destination/source field definition
 
diff --git a/doc/guides/rel_notes/release_24_03.rst b/doc/guides/rel_notes/release_24_03.rst
index 2b91217943..b676683b42 100644
--- a/doc/guides/rel_notes/release_24_03.rst
+++ b/doc/guides/rel_notes/release_24_03.rst
@@ -140,6 +140,7 @@ ABI Changes
 
 * No ABI change that would break compatibility with 23.11.
 
+* ethdev: Rename the experimental ``struct rte_flow_action_modify_data`` to be ``struct rte_flow_field_data``
 
 Known Issues
 ------------
diff --git a/drivers/net/mlx5/mlx5_flow.c b/drivers/net/mlx5/mlx5_flow.c
index 5159e8e773..40376c99ba 100644
--- a/drivers/net/mlx5/mlx5_flow.c
+++ b/drivers/net/mlx5/mlx5_flow.c
@@ -2493,7 +2493,7 @@ mlx5_validate_action_ct(struct rte_eth_dev *dev,
  * Validate the level value for modify field action.
  *
  * @param[in] data
- *   Pointer to the rte_flow_action_modify_data structure either src or dst.
+ *   Pointer to the rte_flow_field_data structure either src or dst.
  * @param[out] error
  *   Pointer to error structure.
  *
@@ -2501,7 +2501,7 @@ mlx5_validate_action_ct(struct rte_eth_dev *dev,
  *   0 on success, a negative errno value otherwise and rte_errno is set.
  */
 int
-flow_validate_modify_field_level(const struct rte_flow_action_modify_data *data,
+flow_validate_modify_field_level(const struct rte_flow_field_data *data,
 				 struct rte_flow_error *error)
 {
 	if (data->level == 0)
diff --git a/drivers/net/mlx5/mlx5_flow.h b/drivers/net/mlx5/mlx5_flow.h
index c9cc942d80..3f0699e986 100644
--- a/drivers/net/mlx5/mlx5_flow.h
+++ b/drivers/net/mlx5/mlx5_flow.h
@@ -1127,7 +1127,7 @@ flow_items_to_tunnel(const struct rte_flow_item items[])
  *   Tag array index.
  */
 static inline uint8_t
-flow_tag_index_get(const struct rte_flow_action_modify_data *data)
+flow_tag_index_get(const struct rte_flow_field_data *data)
 {
 	return data->tag_index ? data->tag_index : data->level;
 }
@@ -1839,7 +1839,7 @@ int mlx5_flow_geneve_tlv_option_validate(struct mlx5_priv *priv,
 					 const struct rte_flow_item *geneve_opt,
 					 struct rte_flow_error *error);
 int mlx5_geneve_opt_modi_field_get(struct mlx5_priv *priv,
-				   const struct rte_flow_action_modify_data *data);
+				   const struct rte_flow_field_data *data);
 
 struct mlx5_geneve_tlv_options_mng;
 int mlx5_geneve_tlv_option_register(struct mlx5_priv *priv,
@@ -2612,7 +2612,7 @@ int mlx5_flow_validate_action_default_miss(uint64_t action_flags,
 				const struct rte_flow_attr *attr,
 				struct rte_flow_error *error);
 int flow_validate_modify_field_level
-			(const struct rte_flow_action_modify_data *data,
+			(const struct rte_flow_field_data *data,
 			 struct rte_flow_error *error);
 int mlx5_flow_item_acceptable(const struct rte_flow_item *item,
 			      const uint8_t *mask,
@@ -2919,7 +2919,7 @@ size_t flow_dv_get_item_hdr_len(const enum rte_flow_item_type item_type);
 int flow_dv_convert_encap_data(const struct rte_flow_item *items, uint8_t *buf,
 			   size_t *size, struct rte_flow_error *error);
 void mlx5_flow_field_id_to_modify_info
-		(const struct rte_flow_action_modify_data *data,
+		(const struct rte_flow_field_data *data,
 		 struct field_modify_info *info, uint32_t *mask,
 		 uint32_t width, struct rte_eth_dev *dev,
 		 const struct rte_flow_attr *attr, struct rte_flow_error *error);
diff --git a/drivers/net/mlx5/mlx5_flow_dv.c b/drivers/net/mlx5/mlx5_flow_dv.c
index 6998be107f..a4ed7b1444 100644
--- a/drivers/net/mlx5/mlx5_flow_dv.c
+++ b/drivers/net/mlx5/mlx5_flow_dv.c
@@ -1460,14 +1460,14 @@ flow_modify_info_mask_32_masked(uint32_t length, uint32_t off, uint32_t post_mas
 }
 
 static __rte_always_inline enum mlx5_modification_field
-mlx5_mpls_modi_field_get(const struct rte_flow_action_modify_data *data)
+mlx5_mpls_modi_field_get(const struct rte_flow_field_data *data)
 {
 	return MLX5_MODI_IN_MPLS_LABEL_0 + data->tag_index;
 }
 
 static __rte_always_inline int
 flow_geneve_opt_modi_field_get(struct mlx5_priv *priv,
-			       const struct rte_flow_action_modify_data *data)
+			       const struct rte_flow_field_data *data)
 {
 #ifdef HAVE_MLX5_HWS_SUPPORT
 	return mlx5_geneve_opt_modi_field_get(priv, data);
@@ -1483,7 +1483,7 @@ flow_geneve_opt_modi_field_get(struct mlx5_priv *priv,
 static void
 mlx5_modify_flex_item(const struct rte_eth_dev *dev,
 		      const struct mlx5_flex_item *flex,
-		      const struct rte_flow_action_modify_data *data,
+		      const struct rte_flow_field_data *data,
 		      struct field_modify_info *info,
 		      uint32_t *mask, uint32_t width)
 {
@@ -1613,7 +1613,7 @@ mlx5_dv_modify_ipv6_traffic_class_supported(struct mlx5_priv *priv)
 
 void
 mlx5_flow_field_id_to_modify_info
-		(const struct rte_flow_action_modify_data *data,
+		(const struct rte_flow_field_data *data,
 		 struct field_modify_info *info, uint32_t *mask,
 		 uint32_t width, struct rte_eth_dev *dev,
 		 const struct rte_flow_attr *attr, struct rte_flow_error *error)
@@ -5441,8 +5441,8 @@ flow_dv_validate_action_modify_field(struct rte_eth_dev *dev,
 	struct mlx5_sh_config *config = &priv->sh->config;
 	struct mlx5_hca_attr *hca_attr = &priv->sh->cdev->config.hca_attr;
 	const struct rte_flow_action_modify_field *conf = action->conf;
-	const struct rte_flow_action_modify_data *src_data = &conf->src;
-	const struct rte_flow_action_modify_data *dst_data = &conf->dst;
+	const struct rte_flow_field_data *src_data = &conf->src;
+	const struct rte_flow_field_data *dst_data = &conf->dst;
 	uint32_t dst_width, src_width, width = conf->width;
 
 	ret = flow_dv_validate_action_modify_hdr(action_flags, action, error);
diff --git a/drivers/net/mlx5/mlx5_flow_geneve.c b/drivers/net/mlx5/mlx5_flow_geneve.c
index d5847a60e9..d8086d333f 100644
--- a/drivers/net/mlx5/mlx5_flow_geneve.c
+++ b/drivers/net/mlx5/mlx5_flow_geneve.c
@@ -326,7 +326,7 @@ mlx5_get_geneve_option_modify_field_id(const void *dr_ctx, uint8_t type,
  */
 int
 mlx5_geneve_opt_modi_field_get(struct mlx5_priv *priv,
-			       const struct rte_flow_action_modify_data *data)
+			       const struct rte_flow_field_data *data)
 {
 	uint16_t class = data->class_id;
 	uint8_t type = data->type;
diff --git a/lib/ethdev/rte_flow.h b/lib/ethdev/rte_flow.h
index 1267c146e5..d9965043e7 100644
--- a/lib/ethdev/rte_flow.h
+++ b/lib/ethdev/rte_flow.h
@@ -3940,9 +3940,9 @@ enum rte_flow_field_id {
  * @warning
  * @b EXPERIMENTAL: this structure may change without prior notice
  *
- * Field description for MODIFY_FIELD action.
+ * Field description for packet field.
  */
-struct rte_flow_action_modify_data {
+struct rte_flow_field_data {
 	enum rte_flow_field_id field; /**< Field or memory type ID. */
 	union {
 		struct {
@@ -4051,8 +4051,8 @@ enum rte_flow_modify_op {
  */
 struct rte_flow_action_modify_field {
 	enum rte_flow_modify_op operation; /**< Operation to perform. */
-	struct rte_flow_action_modify_data dst; /**< Destination field. */
-	struct rte_flow_action_modify_data src; /**< Source field. */
+	struct rte_flow_field_data dst; /**< Destination field. */
+	struct rte_flow_field_data src; /**< Source field. */
 	uint32_t width; /**< Number of bits to use from a source field. */
 };
 
-- 
2.34.1


^ permalink raw reply	[flat|nested] 66+ messages in thread

* [PATCH v4 2/3] ethdev: add compare item
  2024-02-01  2:30 ` [PATCH v4 0/3] ethdev: add RTE_FLOW_ITEM_TYPE_COMPARE Suanming Mou
  2024-02-01  2:30   ` [PATCH v4 1/3] ethdev: rename action modify field data structure Suanming Mou
@ 2024-02-01  2:30   ` Suanming Mou
  2024-02-01  2:30   ` [PATCH v4 3/3] net/mlx5: add compare item support Suanming Mou
  2 siblings, 0 replies; 66+ messages in thread
From: Suanming Mou @ 2024-02-01  2:30 UTC (permalink / raw)
  To: ferruh.yigit, Ori Kam, Aman Singh, Yuying Zhang, Thomas Monjalon,
	Andrew Rybchenko
  Cc: dev

The new item type is added for the case user wants to match traffic
based on packet field compare result with other fields or immediate
value.

e.g. take advantage the compare item user will be able to accumulate
a IPv4/TCP packet's TCP data_offset and IPv4 IHL field to a tag
register, then compare the tag register with IPv4 header total length
to understand the packet has payload or not.

The supported operations can be as below:
 - RTE_FLOW_ITEM_COMPARE_EQ (equal)
 - RTE_FLOW_ITEM_COMPARE_NE (not equal)
 - RTE_FLOW_ITEM_COMPARE_LT (less than)
 - RTE_FLOW_ITEM_COMPARE_LE (less than or equal)
 - RTE_FLOW_ITEM_COMPARE_GT (great than)
 - RTE_FLOW_ITEM_COMPARE_GE (great than or equal)

A sample for create the comparison flow:
flow pattern_template 0 create ingress pattern_template_id 1 template \
	compare op mask le a_type mask tag a_tag_index mask 1 b_type \
	mask tag b_tag_index mask 2 width mask 0xffffffff / end
flow actions_template 0 create ingress actions_template_id 1 template \
	count / drop / end mask count / drop  / end
flow template_table 0 create table_id 1 group 2 priority 1  ingress \
	rules_number 1 pattern_template 1 actions_template 1
flow queue 0 create 0 template_table 1 pattern_template 0 \
	actions_template 0 postpone no pattern compare op is le \
	a_type is tag a_tag_index is 1 b_type is tag b_tag_index is 2 \
	width is 32 / end actions count / drop / end

Signed-off-by: Suanming Mou <suanmingm@nvidia.com>
Acked-by: Ori Kam <orika@nvidia.com>
Acked-by: Andrew Rybchenko <andrew.rybchenko@oktetlabs.ru>
---
 app/test-pmd/cmdline_flow.c                 | 394 ++++++++++++++++++++
 doc/guides/nics/features/default.ini        |   1 +
 doc/guides/prog_guide/rte_flow.rst          |   7 +
 doc/guides/rel_notes/release_24_03.rst      |   5 +
 doc/guides/testpmd_app_ug/testpmd_funcs.rst |  24 ++
 lib/ethdev/rte_flow.c                       |   1 +
 lib/ethdev/rte_flow.h                       | 324 +++++++++-------
 7 files changed, 611 insertions(+), 145 deletions(-)

diff --git a/app/test-pmd/cmdline_flow.c b/app/test-pmd/cmdline_flow.c
index 4741ec679d..d62c490f96 100644
--- a/app/test-pmd/cmdline_flow.c
+++ b/app/test-pmd/cmdline_flow.c
@@ -548,6 +548,28 @@ enum index {
 	ITEM_PTYPE,
 	ITEM_PTYPE_VALUE,
 	ITEM_NSH,
+	ITEM_COMPARE,
+	ITEM_COMPARE_OP,
+	ITEM_COMPARE_OP_VALUE,
+	ITEM_COMPARE_FIELD_A_TYPE,
+	ITEM_COMPARE_FIELD_A_TYPE_VALUE,
+	ITEM_COMPARE_FIELD_A_LEVEL,
+	ITEM_COMPARE_FIELD_A_LEVEL_VALUE,
+	ITEM_COMPARE_FIELD_A_TAG_INDEX,
+	ITEM_COMPARE_FIELD_A_TYPE_ID,
+	ITEM_COMPARE_FIELD_A_CLASS_ID,
+	ITEM_COMPARE_FIELD_A_OFFSET,
+	ITEM_COMPARE_FIELD_B_TYPE,
+	ITEM_COMPARE_FIELD_B_TYPE_VALUE,
+	ITEM_COMPARE_FIELD_B_LEVEL,
+	ITEM_COMPARE_FIELD_B_LEVEL_VALUE,
+	ITEM_COMPARE_FIELD_B_TAG_INDEX,
+	ITEM_COMPARE_FIELD_B_TYPE_ID,
+	ITEM_COMPARE_FIELD_B_CLASS_ID,
+	ITEM_COMPARE_FIELD_B_OFFSET,
+	ITEM_COMPARE_FIELD_B_VALUE,
+	ITEM_COMPARE_FIELD_B_POINTER,
+	ITEM_COMPARE_FIELD_WIDTH,
 
 	/* Validate/create actions. */
 	ACTIONS,
@@ -745,6 +767,10 @@ enum index {
 #define ITEM_RAW_SIZE \
 	(sizeof(struct rte_flow_item_raw) + ITEM_RAW_PATTERN_SIZE)
 
+static const char *const compare_ops[] = {
+	"eq", "ne", "lt", "le", "gt", "ge", NULL
+};
+
 /** Maximum size for external pattern in struct rte_flow_field_data. */
 #define FLOW_FIELD_PATTERN_SIZE 32
 
@@ -1597,6 +1623,7 @@ static const enum index next_item[] = {
 	ITEM_IB_BTH,
 	ITEM_PTYPE,
 	ITEM_NSH,
+	ITEM_COMPARE,
 	END_SET,
 	ZERO,
 };
@@ -2137,6 +2164,38 @@ static const enum index item_nsh[] = {
 	ZERO,
 };
 
+static const enum index item_compare_field[] = {
+	ITEM_COMPARE_OP,
+	ITEM_COMPARE_FIELD_A_TYPE,
+	ITEM_COMPARE_FIELD_B_TYPE,
+	ITEM_NEXT,
+	ZERO,
+};
+
+static const enum index compare_field_a[] = {
+	ITEM_COMPARE_FIELD_A_TYPE,
+	ITEM_COMPARE_FIELD_A_LEVEL,
+	ITEM_COMPARE_FIELD_A_TAG_INDEX,
+	ITEM_COMPARE_FIELD_A_TYPE_ID,
+	ITEM_COMPARE_FIELD_A_CLASS_ID,
+	ITEM_COMPARE_FIELD_A_OFFSET,
+	ITEM_COMPARE_FIELD_B_TYPE,
+	ZERO,
+};
+
+static const enum index compare_field_b[] = {
+	ITEM_COMPARE_FIELD_B_TYPE,
+	ITEM_COMPARE_FIELD_B_LEVEL,
+	ITEM_COMPARE_FIELD_B_TAG_INDEX,
+	ITEM_COMPARE_FIELD_B_TYPE_ID,
+	ITEM_COMPARE_FIELD_B_CLASS_ID,
+	ITEM_COMPARE_FIELD_B_OFFSET,
+	ITEM_COMPARE_FIELD_B_VALUE,
+	ITEM_COMPARE_FIELD_B_POINTER,
+	ITEM_COMPARE_FIELD_WIDTH,
+	ZERO,
+};
+
 static const enum index next_action[] = {
 	ACTION_END,
 	ACTION_VOID,
@@ -2879,6 +2938,24 @@ comp_quota_update_name(struct context *ctx, const struct token *token,
 static int
 comp_qu_mode_name(struct context *ctx, const struct token *token,
 		  unsigned int ent, char *buf, unsigned int size);
+static int
+comp_set_compare_field_id(struct context *ctx, const struct token *token,
+			  unsigned int ent, char *buf, unsigned int size);
+static int
+comp_set_compare_op(struct context *ctx, const struct token *token,
+		    unsigned int ent, char *buf, unsigned int size);
+static int
+parse_vc_compare_op(struct context *ctx, const struct token *token,
+			 const char *str, unsigned int len, void *buf,
+			 unsigned int size);
+static int
+parse_vc_compare_field_id(struct context *ctx, const struct token *token,
+			  const char *str, unsigned int len, void *buf,
+			  unsigned int size);
+static int
+parse_vc_compare_field_level(struct context *ctx, const struct token *token,
+			     const char *str, unsigned int len, void *buf,
+			     unsigned int size);
 
 struct indlst_conf {
 	uint32_t id;
@@ -6037,6 +6114,174 @@ static const struct token token_list[] = {
 		.next = NEXT(item_nsh),
 		.call = parse_vc,
 	},
+	[ITEM_COMPARE] = {
+		.name = "compare",
+		.help = "match with the comparison result",
+		.priv = PRIV_ITEM(COMPARE, sizeof(struct rte_flow_item_compare)),
+		.next = NEXT(NEXT_ENTRY(ITEM_COMPARE_OP)),
+		.call = parse_vc,
+	},
+	[ITEM_COMPARE_OP] = {
+		.name = "op",
+		.help = "operation type",
+		.next = NEXT(item_compare_field,
+			NEXT_ENTRY(ITEM_COMPARE_OP_VALUE), item_param),
+		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_compare, operation)),
+	},
+	[ITEM_COMPARE_OP_VALUE] = {
+		.name = "{operation}",
+		.help = "operation type value",
+		.call = parse_vc_compare_op,
+		.comp = comp_set_compare_op,
+	},
+	[ITEM_COMPARE_FIELD_A_TYPE] = {
+		.name = "a_type",
+		.help = "compared field type",
+		.next = NEXT(compare_field_a,
+			NEXT_ENTRY(ITEM_COMPARE_FIELD_A_TYPE_VALUE), item_param),
+		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_compare, a.field)),
+	},
+	[ITEM_COMPARE_FIELD_A_TYPE_VALUE] = {
+		.name = "{a_type}",
+		.help = "compared field type value",
+		.call = parse_vc_compare_field_id,
+		.comp = comp_set_compare_field_id,
+	},
+	[ITEM_COMPARE_FIELD_A_LEVEL] = {
+		.name = "a_level",
+		.help = "compared field level",
+		.next = NEXT(compare_field_a,
+			     NEXT_ENTRY(ITEM_COMPARE_FIELD_A_LEVEL_VALUE), item_param),
+		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_compare, a.level)),
+	},
+	[ITEM_COMPARE_FIELD_A_LEVEL_VALUE] = {
+		.name = "{a_level}",
+		.help = "compared field level value",
+		.call = parse_vc_compare_field_level,
+		.comp = comp_none,
+	},
+	[ITEM_COMPARE_FIELD_A_TAG_INDEX] = {
+		.name = "a_tag_index",
+		.help = "compared field tag array",
+		.next = NEXT(compare_field_a,
+			     NEXT_ENTRY(COMMON_UNSIGNED), item_param),
+		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_compare,
+					a.tag_index)),
+	},
+	[ITEM_COMPARE_FIELD_A_TYPE_ID] = {
+		.name = "a_type_id",
+		.help = "compared field type ID",
+		.next = NEXT(compare_field_a,
+			     NEXT_ENTRY(COMMON_UNSIGNED), item_param),
+		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_compare,
+					a.type)),
+	},
+	[ITEM_COMPARE_FIELD_A_CLASS_ID] = {
+		.name = "a_class",
+		.help = "compared field class ID",
+		.next = NEXT(compare_field_a,
+			     NEXT_ENTRY(COMMON_UNSIGNED), item_param),
+		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_compare,
+					     a.class_id)),
+	},
+	[ITEM_COMPARE_FIELD_A_OFFSET] = {
+		.name = "a_offset",
+		.help = "compared field bit offset",
+		.next = NEXT(compare_field_a,
+			     NEXT_ENTRY(COMMON_UNSIGNED), item_param),
+		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_compare,
+					a.offset)),
+	},
+	[ITEM_COMPARE_FIELD_B_TYPE] = {
+		.name = "b_type",
+		.help = "comparator field type",
+		.next = NEXT(compare_field_b,
+			NEXT_ENTRY(ITEM_COMPARE_FIELD_B_TYPE_VALUE), item_param),
+		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_compare,
+					b.field)),
+	},
+	[ITEM_COMPARE_FIELD_B_TYPE_VALUE] = {
+		.name = "{b_type}",
+		.help = "comparator field type value",
+		.call = parse_vc_compare_field_id,
+		.comp = comp_set_compare_field_id,
+	},
+	[ITEM_COMPARE_FIELD_B_LEVEL] = {
+		.name = "b_level",
+		.help = "comparator field level",
+		.next = NEXT(compare_field_b,
+			     NEXT_ENTRY(ITEM_COMPARE_FIELD_B_LEVEL_VALUE), item_param),
+		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_compare,
+					b.level)),
+	},
+	[ITEM_COMPARE_FIELD_B_LEVEL_VALUE] = {
+		.name = "{b_level}",
+		.help = "comparator field level value",
+		.call = parse_vc_compare_field_level,
+		.comp = comp_none,
+	},
+	[ITEM_COMPARE_FIELD_B_TAG_INDEX] = {
+		.name = "b_tag_index",
+		.help = "comparator field tag array",
+		.next = NEXT(compare_field_b,
+			     NEXT_ENTRY(COMMON_UNSIGNED), item_param),
+		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_compare,
+					b.tag_index)),
+	},
+	[ITEM_COMPARE_FIELD_B_TYPE_ID] = {
+		.name = "b_type_id",
+		.help = "comparator field type ID",
+		.next = NEXT(compare_field_b,
+			     NEXT_ENTRY(COMMON_UNSIGNED), item_param),
+		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_compare,
+					b.type)),
+	},
+	[ITEM_COMPARE_FIELD_B_CLASS_ID] = {
+		.name = "b_class",
+		.help = "comparator field class ID",
+		.next = NEXT(compare_field_b,
+			     NEXT_ENTRY(COMMON_UNSIGNED), item_param),
+		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_compare,
+					     b.class_id)),
+	},
+	[ITEM_COMPARE_FIELD_B_OFFSET] = {
+		.name = "b_offset",
+		.help = "comparator field bit offset",
+		.next = NEXT(compare_field_b,
+			     NEXT_ENTRY(COMMON_UNSIGNED), item_param),
+		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_compare,
+					b.offset)),
+	},
+	[ITEM_COMPARE_FIELD_B_VALUE] = {
+		.name = "b_value",
+		.help = "comparator immediate value",
+		.next = NEXT(compare_field_b,
+			     NEXT_ENTRY(COMMON_HEX), item_param),
+		.args = ARGS(ARGS_ENTRY_ARB(0, 0),
+			     ARGS_ENTRY_ARB(0, 0),
+			     ARGS_ENTRY(struct rte_flow_item_compare,
+					b.value)),
+	},
+	[ITEM_COMPARE_FIELD_B_POINTER] = {
+		.name = "b_ptr",
+		.help = "pointer to comparator immediate value",
+		.next = NEXT(compare_field_b,
+			     NEXT_ENTRY(COMMON_HEX), item_param),
+		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_compare,
+					b.pvalue),
+			     ARGS_ENTRY_ARB(0, 0),
+			     ARGS_ENTRY_ARB
+				(sizeof(struct rte_flow_item_compare),
+				 FLOW_FIELD_PATTERN_SIZE)),
+	},
+	[ITEM_COMPARE_FIELD_WIDTH] = {
+		.name = "width",
+		.help = "number of bits to compare",
+		.next = NEXT(item_compare_field,
+			NEXT_ENTRY(COMMON_UNSIGNED), item_param),
+		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_compare,
+					width)),
+	},
 
 	/* Validate/create actions. */
 	[ACTIONS] = {
@@ -8459,6 +8704,122 @@ parse_vc_item_l2tpv2_type(struct context *ctx, const struct token *token,
 	return len;
 }
 
+/** Parse operation for compare match item. */
+static int
+parse_vc_compare_op(struct context *ctx, const struct token *token,
+			 const char *str, unsigned int len, void *buf,
+			 unsigned int size)
+{
+	struct rte_flow_item_compare *compare_item;
+	unsigned int i;
+
+	(void)token;
+	(void)buf;
+	(void)size;
+	if (ctx->curr != ITEM_COMPARE_OP_VALUE)
+		return -1;
+	for (i = 0; compare_ops[i]; ++i)
+		if (!strcmp_partial(compare_ops[i], str, len))
+			break;
+	if (!compare_ops[i])
+		return -1;
+	if (!ctx->object)
+		return len;
+	compare_item = ctx->object;
+	compare_item->operation = (enum rte_flow_item_compare_op)i;
+	return len;
+}
+
+/** Parse id for compare match item. */
+static int
+parse_vc_compare_field_id(struct context *ctx, const struct token *token,
+			  const char *str, unsigned int len, void *buf,
+			  unsigned int size)
+{
+	struct rte_flow_item_compare *compare_item;
+	unsigned int i;
+
+	(void)token;
+	(void)buf;
+	(void)size;
+	if (ctx->curr != ITEM_COMPARE_FIELD_A_TYPE_VALUE &&
+		ctx->curr != ITEM_COMPARE_FIELD_B_TYPE_VALUE)
+		return -1;
+	for (i = 0; flow_field_ids[i]; ++i)
+		if (!strcmp_partial(flow_field_ids[i], str, len))
+			break;
+	if (!flow_field_ids[i])
+		return -1;
+	if (!ctx->object)
+		return len;
+	compare_item = ctx->object;
+	if (ctx->curr == ITEM_COMPARE_FIELD_A_TYPE_VALUE)
+		compare_item->a.field = (enum rte_flow_field_id)i;
+	else
+		compare_item->b.field = (enum rte_flow_field_id)i;
+	return len;
+}
+
+/** Parse level for compare match item. */
+static int
+parse_vc_compare_field_level(struct context *ctx, const struct token *token,
+			     const char *str, unsigned int len, void *buf,
+			     unsigned int size)
+{
+	struct rte_flow_item_compare *compare_item;
+	struct flex_item *fp = NULL;
+	uint32_t val;
+	struct buffer *out = buf;
+	char *end;
+
+	(void)token;
+	(void)size;
+	if (ctx->curr != ITEM_COMPARE_FIELD_A_LEVEL_VALUE &&
+		ctx->curr != ITEM_COMPARE_FIELD_B_LEVEL_VALUE)
+		return -1;
+	if (!ctx->object)
+		return len;
+	compare_item = ctx->object;
+	errno = 0;
+	val = strtoumax(str, &end, 0);
+	if (errno || (size_t)(end - str) != len)
+		return -1;
+	/* No need to validate action template mask value */
+	if (out->args.vc.masks) {
+		if (ctx->curr == ITEM_COMPARE_FIELD_A_LEVEL_VALUE)
+			compare_item->a.level = val;
+		else
+			compare_item->b.level = val;
+		return len;
+	}
+	if ((ctx->curr == ITEM_COMPARE_FIELD_A_LEVEL_VALUE &&
+		compare_item->a.field == RTE_FLOW_FIELD_FLEX_ITEM) ||
+		(ctx->curr == ITEM_COMPARE_FIELD_B_LEVEL_VALUE &&
+		compare_item->b.field == RTE_FLOW_FIELD_FLEX_ITEM)) {
+		if (val >= FLEX_MAX_PARSERS_NUM) {
+			printf("Bad flex item handle\n");
+			return -1;
+		}
+		fp = flex_items[ctx->port][val];
+		if (!fp) {
+			printf("Bad flex item handle\n");
+			return -1;
+		}
+	}
+	if (ctx->curr == ITEM_COMPARE_FIELD_A_LEVEL_VALUE) {
+		if (compare_item->a.field != RTE_FLOW_FIELD_FLEX_ITEM)
+			compare_item->a.level = val;
+		else
+			compare_item->a.flex_handle = fp->flex_handle;
+	} else if (ctx->curr == ITEM_COMPARE_FIELD_B_LEVEL_VALUE) {
+		if (compare_item->b.field != RTE_FLOW_FIELD_FLEX_ITEM)
+			compare_item->b.level = val;
+		else
+			compare_item->b.flex_handle = fp->flex_handle;
+	}
+	return len;
+}
+
 /** Parse meter color action type. */
 static int
 parse_vc_action_meter_color_type(struct context *ctx, const struct token *token,
@@ -11945,6 +12306,39 @@ comp_rule_id(struct context *ctx, const struct token *token,
 	return i;
 }
 
+/** Complete operation for compare match item. */
+static int
+comp_set_compare_op(struct context *ctx, const struct token *token,
+		    unsigned int ent, char *buf, unsigned int size)
+{
+	RTE_SET_USED(ctx);
+	RTE_SET_USED(token);
+	if (!buf)
+		return RTE_DIM(compare_ops);
+	if (ent < RTE_DIM(compare_ops) - 1)
+		return strlcpy(buf, compare_ops[ent], size);
+	return -1;
+}
+
+/** Complete field id for compare match item. */
+static int
+comp_set_compare_field_id(struct context *ctx, const struct token *token,
+			  unsigned int ent, char *buf, unsigned int size)
+{
+	const char *name;
+
+	RTE_SET_USED(token);
+	if (!buf)
+		return RTE_DIM(flow_field_ids);
+	if (ent >= RTE_DIM(flow_field_ids) - 1)
+		return -1;
+	name = flow_field_ids[ent];
+	if (ctx->curr == ITEM_COMPARE_FIELD_B_TYPE ||
+	    (strcmp(name, "pointer") && strcmp(name, "value")))
+		return strlcpy(buf, name, size);
+	return -1;
+}
+
 /** Complete type field for RSS action. */
 static int
 comp_vc_action_rss_type(struct context *ctx, const struct token *token,
diff --git a/doc/guides/nics/features/default.ini b/doc/guides/nics/features/default.ini
index 5115963136..1ded1d5de1 100644
--- a/doc/guides/nics/features/default.ini
+++ b/doc/guides/nics/features/default.ini
@@ -88,6 +88,7 @@ aggr_affinity        =
 ah                   =
 any                  =
 arp_eth_ipv4         =
+compare              =
 conntrack            =
 ecpri                =
 esp                  =
diff --git a/doc/guides/prog_guide/rte_flow.rst b/doc/guides/prog_guide/rte_flow.rst
index f936a9ba19..dc038e2c39 100644
--- a/doc/guides/prog_guide/rte_flow.rst
+++ b/doc/guides/prog_guide/rte_flow.rst
@@ -1587,6 +1587,13 @@ the packet.
 
 - ``value``: Specific value to match.
 
+Item: ``COMPARE``
+^^^^^^^^^^^^^^^^^
+
+Matches the comparison result between packet fields or value.
+
+- ``compare``: Comparison information.
+
 Actions
 ~~~~~~~
 
diff --git a/doc/guides/rel_notes/release_24_03.rst b/doc/guides/rel_notes/release_24_03.rst
index b676683b42..0d6d26b438 100644
--- a/doc/guides/rel_notes/release_24_03.rst
+++ b/doc/guides/rel_notes/release_24_03.rst
@@ -70,6 +70,11 @@ New Features
   * Added a fath path function ``rte_eth_tx_queue_count`` to get the number of used
     descriptors of a Tx queue.
 
+* **Added compare flow matching criteria.**
+
+  Added ``RTE_FLOW_ITEM_TYPE_COMPARE`` to allow matching on compare
+  result between the packet fields or value.
+
 
 * **Updated NVIDIA mlx5 driver.**
 
diff --git a/doc/guides/testpmd_app_ug/testpmd_funcs.rst b/doc/guides/testpmd_app_ug/testpmd_funcs.rst
index 38ab421547..d8e4f3f529 100644
--- a/doc/guides/testpmd_app_ug/testpmd_funcs.rst
+++ b/doc/guides/testpmd_app_ug/testpmd_funcs.rst
@@ -3859,6 +3859,13 @@ This section lists supported pattern items and their attributes, if any.
 
         - ``packet_type {unsigned}``: packet type.
 
+- ``compare``: match the comparison result between packet fields or value.
+
+        - ``op {string}``: comparison operation type.
+        - ``a_type {string}``: compared field.
+        - ``b_type {string}``: comparator field.
+        - ``width {unsigned}``: comparison width.
+
 
 Actions list
 ^^^^^^^^^^^^
@@ -5323,6 +5330,23 @@ 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 match with comparison rule
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+Match with comparsion rule can be created as following using ``compare``.
+
+::
+
+    testpmd> flow pattern_template 0 create ingress pattern_template_id 1 template compare op mask le
+             a_type mask tag a_tag_index mask 1 b_type mask tag b_tag_index mask 2 width mask 0xffffffff / end
+    testpmd> flow actions_template 0 create ingress actions_template_id 1 template count / drop / end
+             mask count / drop  / end
+    testpmd> flow template_table 0 create table_id 1 group 2 priority 1  ingress rules_number 1
+             pattern_template 1 actions_template 1
+    testpmd> flow queue 0 create 0 template_table 1 pattern_template 0 actions_template 0 postpone no
+             pattern compare op is le a_type is tag a_tag_index is 1 b_type is tag b_tag_index is 2 width is 32 / end
+	     actions count / drop / end
+
 BPF Functions
 --------------
 
diff --git a/lib/ethdev/rte_flow.c b/lib/ethdev/rte_flow.c
index 3f58d792f9..5f63529f9f 100644
--- a/lib/ethdev/rte_flow.c
+++ b/lib/ethdev/rte_flow.c
@@ -170,6 +170,7 @@ static const struct rte_flow_desc_data rte_flow_desc_item[] = {
 	MK_FLOW_ITEM(TX_QUEUE, sizeof(struct rte_flow_item_tx_queue)),
 	MK_FLOW_ITEM(IB_BTH, sizeof(struct rte_flow_item_ib_bth)),
 	MK_FLOW_ITEM(PTYPE, sizeof(struct rte_flow_item_ptype)),
+	MK_FLOW_ITEM(COMPARE, sizeof(struct rte_flow_item_compare)),
 };
 
 /** Generate flow_action[] entry. */
diff --git a/lib/ethdev/rte_flow.h b/lib/ethdev/rte_flow.h
index d9965043e7..df9acdb8a8 100644
--- a/lib/ethdev/rte_flow.h
+++ b/lib/ethdev/rte_flow.h
@@ -714,6 +714,13 @@ enum rte_flow_item_type {
 	 * @see struct rte_flow_item_random.
 	 */
 	RTE_FLOW_ITEM_TYPE_RANDOM,
+
+	/**
+	 * Matches the packet with compare result.
+	 *
+	 * See struct rte_flow_item_compare.
+	 */
+	RTE_FLOW_ITEM_TYPE_COMPARE,
 };
 
 /**
@@ -2365,6 +2372,178 @@ static const struct rte_flow_item_ptype rte_flow_item_ptype_mask = {
 };
 #endif
 
+/**
+ * Field IDs for packet field.
+ */
+enum rte_flow_field_id {
+	RTE_FLOW_FIELD_START = 0,	/**< Start of a packet. */
+	RTE_FLOW_FIELD_MAC_DST,		/**< Destination MAC Address. */
+	RTE_FLOW_FIELD_MAC_SRC,		/**< Source MAC Address. */
+	RTE_FLOW_FIELD_VLAN_TYPE,	/**< VLAN Tag Identifier. */
+	RTE_FLOW_FIELD_VLAN_ID,		/**< VLAN Identifier. */
+	RTE_FLOW_FIELD_MAC_TYPE,	/**< EtherType. */
+	RTE_FLOW_FIELD_IPV4_DSCP,	/**< IPv4 DSCP. */
+	RTE_FLOW_FIELD_IPV4_TTL,	/**< IPv4 Time To Live. */
+	RTE_FLOW_FIELD_IPV4_SRC,	/**< IPv4 Source Address. */
+	RTE_FLOW_FIELD_IPV4_DST,	/**< IPv4 Destination Address. */
+	RTE_FLOW_FIELD_IPV6_DSCP,	/**< IPv6 DSCP. */
+	RTE_FLOW_FIELD_IPV6_HOPLIMIT,	/**< IPv6 Hop Limit. */
+	RTE_FLOW_FIELD_IPV6_SRC,	/**< IPv6 Source Address. */
+	RTE_FLOW_FIELD_IPV6_DST,	/**< IPv6 Destination Address. */
+	RTE_FLOW_FIELD_TCP_PORT_SRC,	/**< TCP Source Port Number. */
+	RTE_FLOW_FIELD_TCP_PORT_DST,	/**< TCP Destination Port Number. */
+	RTE_FLOW_FIELD_TCP_SEQ_NUM,	/**< TCP Sequence Number. */
+	RTE_FLOW_FIELD_TCP_ACK_NUM,	/**< TCP Acknowledgment Number. */
+	RTE_FLOW_FIELD_TCP_FLAGS,	/**< TCP Flags. */
+	RTE_FLOW_FIELD_UDP_PORT_SRC,	/**< UDP Source Port Number. */
+	RTE_FLOW_FIELD_UDP_PORT_DST,	/**< UDP Destination Port Number. */
+	RTE_FLOW_FIELD_VXLAN_VNI,	/**< VXLAN Network Identifier. */
+	RTE_FLOW_FIELD_GENEVE_VNI,	/**< GENEVE Network Identifier. */
+	RTE_FLOW_FIELD_GTP_TEID,	/**< GTP Tunnel Endpoint Identifier. */
+	RTE_FLOW_FIELD_TAG,		/**< Tag value. */
+	RTE_FLOW_FIELD_MARK,		/**< Mark value. */
+	RTE_FLOW_FIELD_META,		/**< Metadata value. */
+	RTE_FLOW_FIELD_POINTER,		/**< Memory pointer. */
+	RTE_FLOW_FIELD_VALUE,		/**< Immediate value. */
+	RTE_FLOW_FIELD_IPV4_ECN,	/**< IPv4 ECN. */
+	RTE_FLOW_FIELD_IPV6_ECN,	/**< IPv6 ECN. */
+	RTE_FLOW_FIELD_GTP_PSC_QFI,	/**< GTP QFI. */
+	RTE_FLOW_FIELD_METER_COLOR,	/**< Meter color marker. */
+	RTE_FLOW_FIELD_IPV6_PROTO,	/**< IPv6 next header. */
+	RTE_FLOW_FIELD_FLEX_ITEM,	/**< Flex item. */
+	RTE_FLOW_FIELD_HASH_RESULT,	/**< Hash result. */
+	RTE_FLOW_FIELD_GENEVE_OPT_TYPE,	/**< GENEVE option type. */
+	RTE_FLOW_FIELD_GENEVE_OPT_CLASS,/**< GENEVE option class. */
+	RTE_FLOW_FIELD_GENEVE_OPT_DATA,	/**< GENEVE option data. */
+	RTE_FLOW_FIELD_MPLS,		/**< MPLS header. */
+	RTE_FLOW_FIELD_TCP_DATA_OFFSET,	/**< TCP data offset. */
+	RTE_FLOW_FIELD_IPV4_IHL,	/**< IPv4 IHL. */
+	RTE_FLOW_FIELD_IPV4_TOTAL_LEN,	/**< IPv4 total length. */
+	RTE_FLOW_FIELD_IPV6_PAYLOAD_LEN,/**< IPv6 payload length. */
+	RTE_FLOW_FIELD_RANDOM		/**< Random value. */
+};
+
+/**
+ * @warning
+ * @b EXPERIMENTAL: this structure may change without prior notice
+ *
+ * Field description for packet field.
+ */
+struct rte_flow_field_data {
+	enum rte_flow_field_id field; /**< Field or memory type ID. */
+	union {
+		struct {
+			/** Encapsulation level and tag index or flex item handle. */
+			union {
+				struct {
+					/**
+					 * Packet encapsulation level containing
+					 * the field to modify.
+					 *
+					 * - @p 0 requests the default behavior.
+					 *   Depending on the packet type, it
+					 *   can mean outermost, innermost or
+					 *   anything in between.
+					 *
+					 *   It basically stands for the
+					 *   innermost encapsulation level.
+					 *   Modification can be performed
+					 *   according to PMD and device
+					 *   capabilities.
+					 *
+					 * - @p 1 requests modification to be
+					 *   performed on the outermost packet
+					 *   encapsulation level.
+					 *
+					 * - @p 2 and subsequent values request
+					 *   modification to be performed on
+					 *   the specified inner packet
+					 *   encapsulation level, from
+					 *   outermost to innermost (lower to
+					 *   higher values).
+					 *
+					 * Values other than @p 0 are not
+					 * necessarily supported.
+					 *
+					 * @note that for MPLS field,
+					 * encapsulation level also include
+					 * tunnel since MPLS may appear in
+					 * outer, inner or tunnel.
+					 */
+					uint8_t level;
+					union {
+						/**
+						 * Tag index array inside
+						 * encapsulation level.
+						 * Used for VLAN, MPLS or TAG types.
+						 */
+						uint8_t tag_index;
+						/**
+						 * Geneve option identifier.
+						 * Relevant only for
+						 * RTE_FLOW_FIELD_GENEVE_OPT_XXXX
+						 * modification type.
+						 */
+						struct {
+							/**
+							 * Geneve option type.
+							 */
+							uint8_t type;
+							/**
+							 * Geneve option class.
+							 */
+							rte_be16_t class_id;
+						};
+					};
+				};
+				struct rte_flow_item_flex_handle *flex_handle;
+			};
+			/** Number of bits to skip from a field. */
+			uint32_t offset;
+		};
+		/**
+		 * Immediate value for RTE_FLOW_FIELD_VALUE, presented in the
+		 * same byte order and length as in relevant rte_flow_item_xxx.
+		 * The immediate source bitfield offset is inherited from
+		 * the destination's one.
+		 */
+		uint8_t value[16];
+		/**
+		 * Memory address for RTE_FLOW_FIELD_POINTER, memory layout
+		 * should be the same as for relevant field in the
+		 * rte_flow_item_xxx structure.
+		 */
+		void *pvalue;
+	};
+};
+
+/**
+ * Expected operation types for compare item.
+ */
+enum rte_flow_item_compare_op {
+	RTE_FLOW_ITEM_COMPARE_EQ,	/* Compare result equal. */
+	RTE_FLOW_ITEM_COMPARE_NE,	/* Compare result not equal. */
+	RTE_FLOW_ITEM_COMPARE_LT,	/* Compare result less than. */
+	RTE_FLOW_ITEM_COMPARE_LE,	/* Compare result less than or equal. */
+	RTE_FLOW_ITEM_COMPARE_GT,	/* Compare result great than. */
+	RTE_FLOW_ITEM_COMPARE_GE,	/* Compare result great than or equal. */
+};
+
+/**
+ *
+ * RTE_FLOW_ITEM_TYPE_COMPARE
+ *
+ * Matches the packet with compare result.
+ *
+ * The operation means a compare with b result.
+ */
+struct rte_flow_item_compare {
+	enum rte_flow_item_compare_op operation; /* The compare operation. */
+	struct rte_flow_field_data a;		 /* Field be compared.  */
+	struct rte_flow_field_data b;		 /* Field as comparator. */
+	uint32_t width;				 /* Compare width. */
+};
+
 /**
  * Action types.
  *
@@ -3885,151 +4064,6 @@ struct rte_flow_action_ethdev {
 	uint16_t port_id; /**< ethdev port ID */
 };
 
-/**
- * Field IDs for MODIFY_FIELD action.
- */
-enum rte_flow_field_id {
-	RTE_FLOW_FIELD_START = 0,	/**< Start of a packet. */
-	RTE_FLOW_FIELD_MAC_DST,		/**< Destination MAC Address. */
-	RTE_FLOW_FIELD_MAC_SRC,		/**< Source MAC Address. */
-	RTE_FLOW_FIELD_VLAN_TYPE,	/**< VLAN Tag Identifier. */
-	RTE_FLOW_FIELD_VLAN_ID,		/**< VLAN Identifier. */
-	RTE_FLOW_FIELD_MAC_TYPE,	/**< EtherType. */
-	RTE_FLOW_FIELD_IPV4_DSCP,	/**< IPv4 DSCP. */
-	RTE_FLOW_FIELD_IPV4_TTL,	/**< IPv4 Time To Live. */
-	RTE_FLOW_FIELD_IPV4_SRC,	/**< IPv4 Source Address. */
-	RTE_FLOW_FIELD_IPV4_DST,	/**< IPv4 Destination Address. */
-	RTE_FLOW_FIELD_IPV6_DSCP,	/**< IPv6 DSCP. */
-	RTE_FLOW_FIELD_IPV6_HOPLIMIT,	/**< IPv6 Hop Limit. */
-	RTE_FLOW_FIELD_IPV6_SRC,	/**< IPv6 Source Address. */
-	RTE_FLOW_FIELD_IPV6_DST,	/**< IPv6 Destination Address. */
-	RTE_FLOW_FIELD_TCP_PORT_SRC,	/**< TCP Source Port Number. */
-	RTE_FLOW_FIELD_TCP_PORT_DST,	/**< TCP Destination Port Number. */
-	RTE_FLOW_FIELD_TCP_SEQ_NUM,	/**< TCP Sequence Number. */
-	RTE_FLOW_FIELD_TCP_ACK_NUM,	/**< TCP Acknowledgment Number. */
-	RTE_FLOW_FIELD_TCP_FLAGS,	/**< TCP Flags. */
-	RTE_FLOW_FIELD_UDP_PORT_SRC,	/**< UDP Source Port Number. */
-	RTE_FLOW_FIELD_UDP_PORT_DST,	/**< UDP Destination Port Number. */
-	RTE_FLOW_FIELD_VXLAN_VNI,	/**< VXLAN Network Identifier. */
-	RTE_FLOW_FIELD_GENEVE_VNI,	/**< GENEVE Network Identifier. */
-	RTE_FLOW_FIELD_GTP_TEID,	/**< GTP Tunnel Endpoint Identifier. */
-	RTE_FLOW_FIELD_TAG,		/**< Tag value. */
-	RTE_FLOW_FIELD_MARK,		/**< Mark value. */
-	RTE_FLOW_FIELD_META,		/**< Metadata value. */
-	RTE_FLOW_FIELD_POINTER,		/**< Memory pointer. */
-	RTE_FLOW_FIELD_VALUE,		/**< Immediate value. */
-	RTE_FLOW_FIELD_IPV4_ECN,	/**< IPv4 ECN. */
-	RTE_FLOW_FIELD_IPV6_ECN,	/**< IPv6 ECN. */
-	RTE_FLOW_FIELD_GTP_PSC_QFI,	/**< GTP QFI. */
-	RTE_FLOW_FIELD_METER_COLOR,	/**< Meter color marker. */
-	RTE_FLOW_FIELD_IPV6_PROTO,	/**< IPv6 next header. */
-	RTE_FLOW_FIELD_FLEX_ITEM,	/**< Flex item. */
-	RTE_FLOW_FIELD_HASH_RESULT,	/**< Hash result. */
-	RTE_FLOW_FIELD_GENEVE_OPT_TYPE,	/**< GENEVE option type. */
-	RTE_FLOW_FIELD_GENEVE_OPT_CLASS,/**< GENEVE option class. */
-	RTE_FLOW_FIELD_GENEVE_OPT_DATA,	/**< GENEVE option data. */
-	RTE_FLOW_FIELD_MPLS,		/**< MPLS header. */
-	RTE_FLOW_FIELD_TCP_DATA_OFFSET,	/**< TCP data offset. */
-	RTE_FLOW_FIELD_IPV4_IHL,	/**< IPv4 IHL. */
-	RTE_FLOW_FIELD_IPV4_TOTAL_LEN,	/**< IPv4 total length. */
-	RTE_FLOW_FIELD_IPV6_PAYLOAD_LEN,/**< IPv6 payload length. */
-	RTE_FLOW_FIELD_RANDOM		/**< Random value. */
-};
-
-/**
- * @warning
- * @b EXPERIMENTAL: this structure may change without prior notice
- *
- * Field description for packet field.
- */
-struct rte_flow_field_data {
-	enum rte_flow_field_id field; /**< Field or memory type ID. */
-	union {
-		struct {
-			/** Encapsulation level and tag index or flex item handle. */
-			union {
-				struct {
-					/**
-					 * Packet encapsulation level containing
-					 * the field to modify.
-					 *
-					 * - @p 0 requests the default behavior.
-					 *   Depending on the packet type, it
-					 *   can mean outermost, innermost or
-					 *   anything in between.
-					 *
-					 *   It basically stands for the
-					 *   innermost encapsulation level.
-					 *   Modification can be performed
-					 *   according to PMD and device
-					 *   capabilities.
-					 *
-					 * - @p 1 requests modification to be
-					 *   performed on the outermost packet
-					 *   encapsulation level.
-					 *
-					 * - @p 2 and subsequent values request
-					 *   modification to be performed on
-					 *   the specified inner packet
-					 *   encapsulation level, from
-					 *   outermost to innermost (lower to
-					 *   higher values).
-					 *
-					 * Values other than @p 0 are not
-					 * necessarily supported.
-					 *
-					 * @note that for MPLS field,
-					 * encapsulation level also include
-					 * tunnel since MPLS may appear in
-					 * outer, inner or tunnel.
-					 */
-					uint8_t level;
-					union {
-						/**
-						 * Tag index array inside
-						 * encapsulation level.
-						 * Used for VLAN, MPLS or TAG types.
-						 */
-						uint8_t tag_index;
-						/**
-						 * Geneve option identifier.
-						 * Relevant only for
-						 * RTE_FLOW_FIELD_GENEVE_OPT_XXXX
-						 * modification type.
-						 */
-						struct {
-							/**
-							 * Geneve option type.
-							 */
-							uint8_t type;
-							/**
-							 * Geneve option class.
-							 */
-							rte_be16_t class_id;
-						};
-					};
-				};
-				struct rte_flow_item_flex_handle *flex_handle;
-			};
-			/** Number of bits to skip from a field. */
-			uint32_t offset;
-		};
-		/**
-		 * Immediate value for RTE_FLOW_FIELD_VALUE, presented in the
-		 * same byte order and length as in relevant rte_flow_item_xxx.
-		 * The immediate source bitfield offset is inherited from
-		 * the destination's one.
-		 */
-		uint8_t value[16];
-		/**
-		 * Memory address for RTE_FLOW_FIELD_POINTER, memory layout
-		 * should be the same as for relevant field in the
-		 * rte_flow_item_xxx structure.
-		 */
-		void *pvalue;
-	};
-};
-
 /**
  * Operation types for MODIFY_FIELD action.
  */
-- 
2.34.1


^ permalink raw reply	[flat|nested] 66+ messages in thread

* [PATCH v4 3/3] net/mlx5: add compare item support
  2024-02-01  2:30 ` [PATCH v4 0/3] ethdev: add RTE_FLOW_ITEM_TYPE_COMPARE Suanming Mou
  2024-02-01  2:30   ` [PATCH v4 1/3] ethdev: rename action modify field data structure Suanming Mou
  2024-02-01  2:30   ` [PATCH v4 2/3] ethdev: add compare item Suanming Mou
@ 2024-02-01  2:30   ` Suanming Mou
  2 siblings, 0 replies; 66+ messages in thread
From: Suanming Mou @ 2024-02-01  2:30 UTC (permalink / raw)
  To: ferruh.yigit, Matan Azrad, Viacheslav Ovsiienko, Ori Kam; +Cc: dev

The compare item allows adding flow match with comparison
result. This commit adds compare item support to the PMD
code.

Due to HW limitation:
 - Only HWS supported.
 - Only 32-bit comparison is supported.
 - Only single compare flow is supported in the flow table.
 - Only match with compare result between packet fields is
    supported.

Signed-off-by: Suanming Mou <suanmingm@nvidia.com>
Acked-by: Ori Kam <orika@nvidia.com>
---
 doc/guides/nics/features/mlx5.ini      |  1 +
 doc/guides/nics/mlx5.rst               |  7 +++
 doc/guides/rel_notes/release_24_03.rst |  2 +
 drivers/net/mlx5/mlx5_flow.h           |  3 ++
 drivers/net/mlx5/mlx5_flow_hw.c        | 75 +++++++++++++++++++++++++-
 5 files changed, 86 insertions(+), 2 deletions(-)

diff --git a/doc/guides/nics/features/mlx5.ini b/doc/guides/nics/features/mlx5.ini
index 6261b7d657..30027f2ba1 100644
--- a/doc/guides/nics/features/mlx5.ini
+++ b/doc/guides/nics/features/mlx5.ini
@@ -56,6 +56,7 @@ Usage doc            = Y
 
 [rte_flow items]
 aggr_affinity        = Y
+compare              = Y
 conntrack            = Y
 ecpri                = Y
 esp                  = Y
diff --git a/doc/guides/nics/mlx5.rst b/doc/guides/nics/mlx5.rst
index 6e1e2df79a..fa013b03bb 100644
--- a/doc/guides/nics/mlx5.rst
+++ b/doc/guides/nics/mlx5.rst
@@ -816,6 +816,13 @@ Limitations
   The flow engine of a process cannot move from active to standby mode
   if preceding active application rules are still present and vice versa.
 
+- Match with compare result item (``RTE_FLOW_ITEM_TYPE_COMPARE``):
+
+  - Only supported in HW steering(``dv_flow_en`` = 2) mode.
+  - Only single flow is supported to the flow table.
+  - Only 32-bit comparison is supported.
+  - Only match with compare result between packet fields is supported.
+
 
 Statistics
 ----------
diff --git a/doc/guides/rel_notes/release_24_03.rst b/doc/guides/rel_notes/release_24_03.rst
index 0d6d26b438..4e2cba8024 100644
--- a/doc/guides/rel_notes/release_24_03.rst
+++ b/doc/guides/rel_notes/release_24_03.rst
@@ -96,6 +96,8 @@ New Features
   * Added HW steering support for modify field ``RTE_FLOW_FIELD_GENEVE_OPT_CLASS`` flow action.
   * Added HW steering support for modify field ``RTE_FLOW_FIELD_GENEVE_OPT_DATA`` flow action.
 
+  * Added support for comparing result between packet fields or value.
+
 
 Removed Items
 -------------
diff --git a/drivers/net/mlx5/mlx5_flow.h b/drivers/net/mlx5/mlx5_flow.h
index 3f0699e986..8641cf0537 100644
--- a/drivers/net/mlx5/mlx5_flow.h
+++ b/drivers/net/mlx5/mlx5_flow.h
@@ -280,6 +280,9 @@ enum mlx5_feature_name {
 /* Random ITEM */
 #define MLX5_FLOW_ITEM_RANDOM (1ull << 54)
 
+/* COMPARE ITEM */
+#define MLX5_FLOW_ITEM_COMPARE (1ull << 55)
+
 /* Outer Masks. */
 #define MLX5_FLOW_LAYER_OUTER_L3 \
 	(MLX5_FLOW_LAYER_OUTER_L3_IPV4 | MLX5_FLOW_LAYER_OUTER_L3_IPV6)
diff --git a/drivers/net/mlx5/mlx5_flow_hw.c b/drivers/net/mlx5/mlx5_flow_hw.c
index 7510715189..471e8e4d17 100644
--- a/drivers/net/mlx5/mlx5_flow_hw.c
+++ b/drivers/net/mlx5/mlx5_flow_hw.c
@@ -426,6 +426,9 @@ flow_hw_matching_item_flags_get(const struct rte_flow_item items[])
 		case RTE_FLOW_ITEM_TYPE_GTP:
 			last_item = MLX5_FLOW_LAYER_GTP;
 			break;
+		case RTE_FLOW_ITEM_TYPE_COMPARE:
+			last_item = MLX5_FLOW_ITEM_COMPARE;
+			break;
 		default:
 			break;
 		}
@@ -4401,6 +4404,8 @@ flow_hw_table_create(struct rte_eth_dev *dev,
 			rte_errno = EINVAL;
 			goto it_error;
 		}
+		if (item_templates[i]->item_flags & MLX5_FLOW_ITEM_COMPARE)
+			matcher_attr.mode = MLX5DR_MATCHER_RESOURCE_MODE_HTABLE;
 		ret = __atomic_fetch_add(&item_templates[i]->refcnt, 1,
 					 __ATOMIC_RELAXED) + 1;
 		if (ret <= 1) {
@@ -6712,6 +6717,66 @@ flow_hw_prepend_item(const struct rte_flow_item *items,
 	return copied_items;
 }
 
+static inline bool
+flow_hw_item_compare_field_supported(enum rte_flow_field_id field)
+{
+	switch (field) {
+	case RTE_FLOW_FIELD_TAG:
+	case RTE_FLOW_FIELD_META:
+	case RTE_FLOW_FIELD_VALUE:
+		return true;
+	default:
+		break;
+	}
+	return false;
+}
+
+static int
+flow_hw_validate_item_compare(const struct rte_flow_item *item,
+			      struct rte_flow_error *error)
+{
+	const struct rte_flow_item_compare *comp_m = item->mask;
+	const struct rte_flow_item_compare *comp_v = item->spec;
+
+	if (unlikely(!comp_m))
+		return rte_flow_error_set(error, EINVAL,
+				   RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
+				   NULL,
+				   "compare item mask is missing");
+	if (comp_m->width != UINT32_MAX)
+		return rte_flow_error_set(error, EINVAL,
+				   RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
+				   NULL,
+				   "compare item only support full mask");
+	if (!flow_hw_item_compare_field_supported(comp_m->a.field) ||
+	    !flow_hw_item_compare_field_supported(comp_m->b.field))
+		return rte_flow_error_set(error, ENOTSUP,
+				   RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
+				   NULL,
+				   "compare item field not support");
+	if (comp_m->a.field == RTE_FLOW_FIELD_VALUE &&
+	    comp_m->b.field == RTE_FLOW_FIELD_VALUE)
+		return rte_flow_error_set(error, EINVAL,
+				   RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
+				   NULL,
+				   "compare between value is not valid");
+	if (comp_v) {
+		if (comp_v->operation != comp_m->operation ||
+		    comp_v->a.field != comp_m->a.field ||
+		    comp_v->b.field != comp_m->b.field)
+			return rte_flow_error_set(error, EINVAL,
+					   RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
+					   NULL,
+					   "compare item spec/mask not matching");
+		if ((comp_v->width & comp_m->width) != 32)
+			return rte_flow_error_set(error, EINVAL,
+					   RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
+					   NULL,
+					   "compare item only support full mask");
+	}
+	return 0;
+}
+
 static int
 flow_hw_pattern_validate(struct rte_eth_dev *dev,
 			 const struct rte_flow_pattern_template_attr *attr,
@@ -6722,6 +6787,7 @@ flow_hw_pattern_validate(struct rte_eth_dev *dev,
 	int i, tag_idx;
 	bool items_end = false;
 	uint32_t tag_bitmap = 0;
+	int ret;
 
 	if (!attr->ingress && !attr->egress && !attr->transfer)
 		return rte_flow_error_set(error, EINVAL, RTE_FLOW_ERROR_TYPE_ATTR, NULL,
@@ -6861,8 +6927,6 @@ flow_hw_pattern_validate(struct rte_eth_dev *dev,
 		}
 		case RTE_FLOW_ITEM_TYPE_GENEVE_OPT:
 		{
-			int ret;
-
 			ret = mlx5_flow_geneve_tlv_option_validate(priv,
 								   &items[i],
 								   error);
@@ -6870,6 +6934,13 @@ flow_hw_pattern_validate(struct rte_eth_dev *dev,
 				return ret;
 			break;
 		}
+		case RTE_FLOW_ITEM_TYPE_COMPARE:
+		{
+			ret = flow_hw_validate_item_compare(&items[i], error);
+			if (ret)
+				return ret;
+			break;
+		}
 		case RTE_FLOW_ITEM_TYPE_VOID:
 		case RTE_FLOW_ITEM_TYPE_ETH:
 		case RTE_FLOW_ITEM_TYPE_VLAN:
-- 
2.34.1


^ permalink raw reply	[flat|nested] 66+ messages in thread

* RE: [PATCH v3 2/3] ethdev: add compare item
  2024-01-31 17:54                 ` Ferruh Yigit
@ 2024-02-01  6:51                   ` Ori Kam
  0 siblings, 0 replies; 66+ messages in thread
From: Ori Kam @ 2024-02-01  6:51 UTC (permalink / raw)
  To: Ferruh Yigit, Suanming Mou, Aman Singh, Yuying Zhang,
	NBU-Contact-Thomas Monjalon (EXTERNAL),
	Andrew Rybchenko
  Cc: dev



> -----Original Message-----
> From: Ferruh Yigit <ferruh.yigit@amd.com>
> Sent: Wednesday, January 31, 2024 7:54 PM
> 
> On 1/31/2024 5:43 PM, Ori Kam wrote:
> >
> >
> >> -----Original Message-----
> >> From: Ferruh Yigit <ferruh.yigit@amd.com>
> >> Sent: Wednesday, January 31, 2024 6:46 PM
> >> Subject: Re: [PATCH v3 2/3] ethdev: add compare item
> >>
> >> On 1/31/2024 3:56 PM, Ori Kam wrote:
> >>> Hi
> >>>
> >>>> -----Original Message-----
> >>>> From: Suanming Mou <suanmingm@nvidia.com>
> >>>> Sent: Wednesday, January 31, 2024 4:48 AM
> >>>>
> >>>> Hi,
> >>>>
> >>>>> -----Original Message-----
> >>>>> From: Ferruh Yigit <ferruh.yigit@amd.com>
> >>>>> Sent: Wednesday, January 31, 2024 1:34 AM
> >>>>> To: Suanming Mou <suanmingm@nvidia.com>; Ori Kam
> >>>> <orika@nvidia.com>;
> >>>>> Aman Singh <aman.deep.singh@intel.com>; Yuying Zhang
> >>>>> <yuying.zhang@intel.com>; NBU-Contact-Thomas Monjalon
> (EXTERNAL)
> >>>>> <thomas@monjalon.net>; Andrew Rybchenko
> >>>>> <andrew.rybchenko@oktetlabs.ru>
> >>>>> Cc: dev@dpdk.org
> >>>>> Subject: Re: [PATCH v3 2/3] ethdev: add compare item
> >>>>>
> >>>>> On 1/15/2024 9:13 AM, Suanming Mou wrote:
> >>>>>> The new item type is added for the case user wants to match traffic
> >>>>>> based on packet field compare result with other fields or immediate
> >>>>>> value.
> >>>>>>
> >>>>>> e.g. take advantage the compare item user will be able to accumulate
> a
> >>>>>> IPv4/TCP packet's TCP data_offset and IPv4 IHL field to a tag
> >>>>>> register, then compare the tag register with IPv4 header total length
> >>>>>> to understand the packet has payload or not.
> >>>>>>
> >>>>>
> >>>>> ack, above sample makes it easier to understand.
> >>>>>
> >>>>> This patch is adding testpmd commands, can you please provide some
> >>>> sample
> >>>>> commands in commit log?
> >>>>> The more samples are better, as far as I remember there was a
> testpmd
> >>>>> documentation that documents the sample usages, can you please
> check
> >>>> for it?
> >>>
> >>> [Snip ..]
> >>>
> >>>>>
> >>>>>> +/**
> >>>>>> + * @warning
> >>>>>> + * @b EXPERIMENTAL: this structure may change without prior
> notice
> >>>>>> + *
> >>>>>> + * Field description for packet field.
> >>>>>> + */
> >>>>>> +struct rte_flow_field_data {
> >>>>>> +	enum rte_flow_field_id field; /**< Field or memory type ID.
> */
> >>>>>> +	union {
> >>>>>> +		struct {
> >>>>>> +			/** Encapsulation level and tag index or flex
> item
> >>>>> handle. */
> >>>>>> +			union {
> >>>>>> +				struct {
> >>>>>> +					/**
> >>>>>> +					 * Packet encapsulation level
> >>>> containing
> >>>>>> +					 * the field to modify.
> >>>>>> +					 *
> >>>>>> +					 * - @p 0 requests the default
> >>>> behavior.
> >>>>>> +					 *   Depending on the packet
> type, it
> >>>>>> +					 *   can mean outermost,
> innermost
> >>>> or
> >>>>>> +					 *   anything in between.
> >>>>>> +					 *
> >>>>>> +					 *   It basically stands for the
> >>>>>> +					 *   innermost encapsulation
> level.
> >>>>>> +					 *   Modification can be
> performed
> >>>>>> +					 *   according to PMD and
> device
> >>>>>> +					 *   capabilities.
> >>>>>> +					 *
> >>>>>> +					 * - @p 1 requests
> modification to be
> >>>>>> +					 *   performed on the
> outermost
> >>>> packet
> >>>>>> +					 *   encapsulation level.
> >>>>>> +					 *
> >>>>>> +					 * - @p 2 and subsequent
> values
> >>>>> request
> >>>>>> +					 *   modification to be
> performed on
> >>>>>> +					 *   the specified inner packet
> >>>>>> +					 *   encapsulation level, from
> >>>>>> +					 *   outermost to innermost
> (lower to
> >>>>>> +					 *   higher values).
> >>>>>> +					 *
> >>>>>> +					 * Values other than @p 0 are
> not
> >>>>>> +					 * necessarily supported.
> >>>>>> +					 *
> >>>>>> +					 * @note that for MPLS field,
> >>>>>> +					 * encapsulation level also
> include
> >>>>>> +					 * tunnel since MPLS may
> appear in
> >>>>>> +					 * outer, inner or tunnel.
> >>>>>> +					 */
> >>>>>> +					uint8_t level;
> >>>>>> +					union {
> >>>>>> +						/**
> >>>>>> +						 * Tag index array
> inside
> >>>>>> +						 * encapsulation level.
> >>>>>> +						 * Used for VLAN,
> MPLS or
> >>>> TAG
> >>>>> types.
> >>>>>> +						 */
> >>>>>> +						uint8_t tag_index;
> >>>>>> +						/**
> >>>>>> +						 * Geneve option
> identifier.
> >>>>>> +						 * Relevant only for
> >>>>>> +						 *
> >>>>> RTE_FLOW_FIELD_GENEVE_OPT_XXXX
> >>>>>> +						 * modification type.
> >>>>>> +						 */
> >>>>>> +						struct {
> >>>>>> +							/**
> >>>>>> +							 * Geneve
> option
> >>>> type.
> >>>>>> +							 */
> >>>>>> +							uint8_t type;
> >>>>>> +							/**
> >>>>>> +							 * Geneve
> option
> >>>> class.
> >>>>>> +							 */
> >>>>>> +							rte_be16_t
> class_id;
> >>>>>> +						};
> >>>>>> +					};
> >>>>>> +				};
> >>>>>> +				struct rte_flow_item_flex_handle
> >>>> *flex_handle;
> >>>>>> +			};
> >>>>>> +			/** Number of bits to skip from a field. */
> >>>>>> +			uint32_t offset;
> >>>>>> +		};
> >>>>>> +		/**
> >>>>>> +		 * Immediate value for RTE_FLOW_FIELD_VALUE,
> presented
> >>>> in
> >>>>> the
> >>>>>> +		 * same byte order and length as in relevant
> >>>> rte_flow_item_xxx.
> >>>>>> +		 * The immediate source bitfield offset is inherited
> from
> >>>>>> +		 * the destination's one.
> >>>>>> +		 */
> >>>>>> +		uint8_t value[16];
> >>>>>> +		/**
> >>>>>> +		 * Memory address for RTE_FLOW_FIELD_POINTER,
> memory
> >>>>> layout
> >>>>>> +		 * should be the same as for relevant field in the
> >>>>>> +		 * rte_flow_item_xxx structure.
> >>>>>> +		 */
> >>>>>> +		void *pvalue;
> >>>>>> +	};
> >>>>>> +};
> >>>>>> +
> >>>>>>
> >>>>>
> >>>>> I am aware that you are just moving the above struct, but it is nested
> too
> >>>> much
> >>>>> which is making it hard to read.
> >>>>>
> >>>>> As you are touching it, can we extract some structs and make this
> struct
> >> less
> >>>>> nested, what do you think?
> >>>>> Of course it needs to be done in separate patch, as a
> preperation/clean-
> >> up
> >>>> patch
> >>>>> before moving it around.
> >>>>
> >>>> Agree the struct maybe a bit nested. But not sure how it was discussed
> >>>> before during the last new member was added... @Ori, Do you have
> any
> >> idea
> >>>> about this?
> >>>>
> >>>
> >>> As far as I remember, it was never discussed,
> >>>
> >>> I think for this series we should keep it as is, and revise it later.
> >>>
> >>
> >> If you don't want to make this set more complex with this, that is OK as
> >> long as it is addressed at some point.
> >
> > Agree,
> > If you have suggestions, I will be more than happy to hear.
> >
> 
> For the struct?
> Simply extracting the inner structs as named structs to reduce the
> nested structs, does this make sense?
> 
Yes that make sense.

^ permalink raw reply	[flat|nested] 66+ messages in thread

* Re: [PATCH v3 1/3] ethdev: rename action modify field data structure
  2024-01-31  2:57         ` Suanming Mou
@ 2024-02-01 10:56           ` Ferruh Yigit
  2024-02-01 11:09             ` Suanming Mou
  0 siblings, 1 reply; 66+ messages in thread
From: Ferruh Yigit @ 2024-02-01 10:56 UTC (permalink / raw)
  To: Suanming Mou, Ori Kam, Aman Singh, Yuying Zhang,
	Dariusz Sosnowski, Slava Ovsiienko, Matan Azrad,
	NBU-Contact-Thomas Monjalon (EXTERNAL),
	Andrew Rybchenko
  Cc: dev

On 1/31/2024 2:57 AM, Suanming Mou wrote:
> Hi,
> 
>> -----Original Message-----
>> From: Ferruh Yigit <ferruh.yigit@amd.com>
>> Sent: Wednesday, January 31, 2024 1:19 AM
>> To: Suanming Mou <suanmingm@nvidia.com>; Ori Kam <orika@nvidia.com>;
>> Aman Singh <aman.deep.singh@intel.com>; Yuying Zhang
>> <yuying.zhang@intel.com>; Dariusz Sosnowski <dsosnowski@nvidia.com>; Slava
>> Ovsiienko <viacheslavo@nvidia.com>; Matan Azrad <matan@nvidia.com>; NBU-
>> Contact-Thomas Monjalon (EXTERNAL) <thomas@monjalon.net>; Andrew
>> Rybchenko <andrew.rybchenko@oktetlabs.ru>
>> Cc: dev@dpdk.org
>> Subject: Re: [PATCH v3 1/3] ethdev: rename action modify field data structure
>>
>> On 1/15/2024 9:13 AM, Suanming Mou wrote:
>>> Current rte_flow_action_modify_data struct describes the pkt field
>>> perfectly and is used only in action.
>>>
>>> It is planned to be used for item as well. This commit renames it to
>>> "rte_flow_field_data" making it compatible to be used by item.
>>>
>>
>> ack to rename struct to use in pattern.
>>
>>> Signed-off-by: Suanming Mou <suanmingm@nvidia.com>
>>> Acked-by: Ori Kam <orika@nvidia.com>
>>> Acked-by: Andrew Rybchenko <andrew.rybchenko@oktetlabs.ru>
>>> ---
>>>  app/test-pmd/cmdline_flow.c            |  2 +-
>>>  doc/guides/prog_guide/rte_flow.rst     |  2 +-
>>>  doc/guides/rel_notes/release_24_03.rst |  1 +
>>>  drivers/net/mlx5/mlx5_flow.c           |  4 ++--
>>>  drivers/net/mlx5/mlx5_flow.h           |  6 +++---
>>>  drivers/net/mlx5/mlx5_flow_dv.c        | 10 +++++-----
>>>  lib/ethdev/rte_flow.h                  |  8 ++++----
>>>  7 files changed, 17 insertions(+), 16 deletions(-)
>>>
>>> diff --git a/app/test-pmd/cmdline_flow.c b/app/test-pmd/cmdline_flow.c
>>> index ce71818705..3725e955c7 100644
>>> --- a/app/test-pmd/cmdline_flow.c
>>> +++ b/app/test-pmd/cmdline_flow.c
>>> @@ -740,7 +740,7 @@ enum index {
>>>  #define ITEM_RAW_SIZE \
>>>  	(sizeof(struct rte_flow_item_raw) + ITEM_RAW_PATTERN_SIZE)
>>>
>>> -/** Maximum size for external pattern in struct
>>> rte_flow_action_modify_data. */
>>> +/** Maximum size for external pattern in struct rte_flow_field_data.
>>> +*/
>>>  #define ACTION_MODIFY_PATTERN_SIZE 32
>>>
>>
>> What do you think to update 'ACTION_MODIFY_PATTERN_SIZE' here too, instead
>> of next patch?
> 
> Agree.
> 
>>
>> <...>
>>
>>> diff --git a/lib/ethdev/rte_flow.h b/lib/ethdev/rte_flow.h index
>>> affdc8121b..40f6dcaacd 100644
>>> --- a/lib/ethdev/rte_flow.h
>>> +++ b/lib/ethdev/rte_flow.h
>>> @@ -3910,9 +3910,9 @@ enum rte_flow_field_id {
>>>   * @warning
>>>   * @b EXPERIMENTAL: this structure may change without prior notice
>>>   *
>>> - * Field description for MODIFY_FIELD action.
>>> + * Field description for packet field.
>>>
>>
>> New note is not very helpful, how can we make it more useful?
>>
>> Does it make sense to keep 'MODIFY_FIELD' and add 'COMPARE ITEM' in next
>> patch, to clarify the intended usage for the struct, otherwise it is too generic.
> 
> OK, sorry, the purpose is to make it generic. So next time if other ITEM or ACTION need that field, it can be used directly.
> Otherwise, it feels like it can only be used by 'MODIFY_FIELD' and 'COMPARE_ITEM', what do you think?
> 

I don't have an intention to limit its usage, but to clarify usage for
whoever checks the document.

"Field description for packet field." doesn't say what exactly it is and
cause confusion.

Perhaps wording can be changed to say two possible usages are for
'MODIFY_FIELD' and 'COMPARE_ITEM'?


^ permalink raw reply	[flat|nested] 66+ messages in thread

* RE: [PATCH v3 1/3] ethdev: rename action modify field data structure
  2024-02-01 10:56           ` Ferruh Yigit
@ 2024-02-01 11:09             ` Suanming Mou
  2024-02-01 11:20               ` Ferruh Yigit
  0 siblings, 1 reply; 66+ messages in thread
From: Suanming Mou @ 2024-02-01 11:09 UTC (permalink / raw)
  To: Ferruh Yigit, Ori Kam, Aman Singh, Yuying Zhang,
	Dariusz Sosnowski, Slava Ovsiienko, Matan Azrad,
	NBU-Contact-Thomas Monjalon (EXTERNAL),
	Andrew Rybchenko
  Cc: dev



> -----Original Message-----
> From: Ferruh Yigit <ferruh.yigit@amd.com>
> Sent: Thursday, February 1, 2024 6:56 PM
> To: Suanming Mou <suanmingm@nvidia.com>; Ori Kam <orika@nvidia.com>;
> Aman Singh <aman.deep.singh@intel.com>; Yuying Zhang
> <yuying.zhang@intel.com>; Dariusz Sosnowski <dsosnowski@nvidia.com>; Slava
> Ovsiienko <viacheslavo@nvidia.com>; Matan Azrad <matan@nvidia.com>; NBU-
> Contact-Thomas Monjalon (EXTERNAL) <thomas@monjalon.net>; Andrew
> Rybchenko <andrew.rybchenko@oktetlabs.ru>
> Cc: dev@dpdk.org
> Subject: Re: [PATCH v3 1/3] ethdev: rename action modify field data structure
> 
> On 1/31/2024 2:57 AM, Suanming Mou wrote:
> > Hi,
> >
> >> -----Original Message-----
> >> From: Ferruh Yigit <ferruh.yigit@amd.com>
> >> Sent: Wednesday, January 31, 2024 1:19 AM
> >> To: Suanming Mou <suanmingm@nvidia.com>; Ori Kam <orika@nvidia.com>;
> >> Aman Singh <aman.deep.singh@intel.com>; Yuying Zhang
> >> <yuying.zhang@intel.com>; Dariusz Sosnowski <dsosnowski@nvidia.com>;
> >> Slava Ovsiienko <viacheslavo@nvidia.com>; Matan Azrad
> >> <matan@nvidia.com>; NBU- Contact-Thomas Monjalon (EXTERNAL)
> >> <thomas@monjalon.net>; Andrew Rybchenko
> >> <andrew.rybchenko@oktetlabs.ru>
> >> Cc: dev@dpdk.org
> >> Subject: Re: [PATCH v3 1/3] ethdev: rename action modify field data
> >> structure
> >>
> >> On 1/15/2024 9:13 AM, Suanming Mou wrote:
> >>> Current rte_flow_action_modify_data struct describes the pkt field
> >>> perfectly and is used only in action.
> >>>
> >>> It is planned to be used for item as well. This commit renames it to
> >>> "rte_flow_field_data" making it compatible to be used by item.
> >>>
> >>
> >> ack to rename struct to use in pattern.
> >>
> >>> Signed-off-by: Suanming Mou <suanmingm@nvidia.com>
> >>> Acked-by: Ori Kam <orika@nvidia.com>
> >>> Acked-by: Andrew Rybchenko <andrew.rybchenko@oktetlabs.ru>
> >>> ---
> >>>  app/test-pmd/cmdline_flow.c            |  2 +-
> >>>  doc/guides/prog_guide/rte_flow.rst     |  2 +-
> >>>  doc/guides/rel_notes/release_24_03.rst |  1 +
> >>>  drivers/net/mlx5/mlx5_flow.c           |  4 ++--
> >>>  drivers/net/mlx5/mlx5_flow.h           |  6 +++---
> >>>  drivers/net/mlx5/mlx5_flow_dv.c        | 10 +++++-----
> >>>  lib/ethdev/rte_flow.h                  |  8 ++++----
> >>>  7 files changed, 17 insertions(+), 16 deletions(-)
> >>>
> >>> diff --git a/app/test-pmd/cmdline_flow.c
> >>> b/app/test-pmd/cmdline_flow.c index ce71818705..3725e955c7 100644
> >>> --- a/app/test-pmd/cmdline_flow.c
> >>> +++ b/app/test-pmd/cmdline_flow.c
> >>> @@ -740,7 +740,7 @@ enum index {
> >>>  #define ITEM_RAW_SIZE \
> >>>  	(sizeof(struct rte_flow_item_raw) + ITEM_RAW_PATTERN_SIZE)
> >>>
> >>> -/** Maximum size for external pattern in struct
> >>> rte_flow_action_modify_data. */
> >>> +/** Maximum size for external pattern in struct rte_flow_field_data.
> >>> +*/
> >>>  #define ACTION_MODIFY_PATTERN_SIZE 32
> >>>
> >>
> >> What do you think to update 'ACTION_MODIFY_PATTERN_SIZE' here too,
> >> instead of next patch?
> >
> > Agree.
> >
> >>
> >> <...>
> >>
> >>> diff --git a/lib/ethdev/rte_flow.h b/lib/ethdev/rte_flow.h index
> >>> affdc8121b..40f6dcaacd 100644
> >>> --- a/lib/ethdev/rte_flow.h
> >>> +++ b/lib/ethdev/rte_flow.h
> >>> @@ -3910,9 +3910,9 @@ enum rte_flow_field_id {
> >>>   * @warning
> >>>   * @b EXPERIMENTAL: this structure may change without prior notice
> >>>   *
> >>> - * Field description for MODIFY_FIELD action.
> >>> + * Field description for packet field.
> >>>
> >>
> >> New note is not very helpful, how can we make it more useful?
> >>
> >> Does it make sense to keep 'MODIFY_FIELD' and add 'COMPARE ITEM' in
> >> next patch, to clarify the intended usage for the struct, otherwise it is too
> generic.
> >
> > OK, sorry, the purpose is to make it generic. So next time if other ITEM or
> ACTION need that field, it can be used directly.
> > Otherwise, it feels like it can only be used by 'MODIFY_FIELD' and
> 'COMPARE_ITEM', what do you think?
> >
> 
> I don't have an intention to limit its usage, but to clarify usage for whoever checks
> the document.
> 
> "Field description for packet field." doesn't say what exactly it is and cause
> confusion.
> 
> Perhaps wording can be changed to say two possible usages are for
> 'MODIFY_FIELD' and 'COMPARE_ITEM'?

Sounds good, OK, I will update.

BTW, I saw the patch apply failed, seems it is due to Raslan's branch has some extra features than your branch.
So I just want to know is it OK? Or should I still base on your branch? When will the branches be synced.


^ permalink raw reply	[flat|nested] 66+ messages in thread

* Re: [PATCH v3 1/3] ethdev: rename action modify field data structure
  2024-02-01 11:09             ` Suanming Mou
@ 2024-02-01 11:20               ` Ferruh Yigit
  2024-02-01 11:39                 ` Suanming Mou
  0 siblings, 1 reply; 66+ messages in thread
From: Ferruh Yigit @ 2024-02-01 11:20 UTC (permalink / raw)
  To: Suanming Mou, Ori Kam, Aman Singh, Yuying Zhang,
	Dariusz Sosnowski, Slava Ovsiienko, Matan Azrad,
	NBU-Contact-Thomas Monjalon (EXTERNAL),
	Andrew Rybchenko
  Cc: dev

On 2/1/2024 11:09 AM, Suanming Mou wrote:
> 
> 
>> -----Original Message-----
>> From: Ferruh Yigit <ferruh.yigit@amd.com>
>> Sent: Thursday, February 1, 2024 6:56 PM
>> To: Suanming Mou <suanmingm@nvidia.com>; Ori Kam <orika@nvidia.com>;
>> Aman Singh <aman.deep.singh@intel.com>; Yuying Zhang
>> <yuying.zhang@intel.com>; Dariusz Sosnowski <dsosnowski@nvidia.com>; Slava
>> Ovsiienko <viacheslavo@nvidia.com>; Matan Azrad <matan@nvidia.com>; NBU-
>> Contact-Thomas Monjalon (EXTERNAL) <thomas@monjalon.net>; Andrew
>> Rybchenko <andrew.rybchenko@oktetlabs.ru>
>> Cc: dev@dpdk.org
>> Subject: Re: [PATCH v3 1/3] ethdev: rename action modify field data structure
>>
>> On 1/31/2024 2:57 AM, Suanming Mou wrote:
>>> Hi,
>>>
>>>> -----Original Message-----
>>>> From: Ferruh Yigit <ferruh.yigit@amd.com>
>>>> Sent: Wednesday, January 31, 2024 1:19 AM
>>>> To: Suanming Mou <suanmingm@nvidia.com>; Ori Kam <orika@nvidia.com>;
>>>> Aman Singh <aman.deep.singh@intel.com>; Yuying Zhang
>>>> <yuying.zhang@intel.com>; Dariusz Sosnowski <dsosnowski@nvidia.com>;
>>>> Slava Ovsiienko <viacheslavo@nvidia.com>; Matan Azrad
>>>> <matan@nvidia.com>; NBU- Contact-Thomas Monjalon (EXTERNAL)
>>>> <thomas@monjalon.net>; Andrew Rybchenko
>>>> <andrew.rybchenko@oktetlabs.ru>
>>>> Cc: dev@dpdk.org
>>>> Subject: Re: [PATCH v3 1/3] ethdev: rename action modify field data
>>>> structure
>>>>
>>>> On 1/15/2024 9:13 AM, Suanming Mou wrote:
>>>>> Current rte_flow_action_modify_data struct describes the pkt field
>>>>> perfectly and is used only in action.
>>>>>
>>>>> It is planned to be used for item as well. This commit renames it to
>>>>> "rte_flow_field_data" making it compatible to be used by item.
>>>>>
>>>>
>>>> ack to rename struct to use in pattern.
>>>>
>>>>> Signed-off-by: Suanming Mou <suanmingm@nvidia.com>
>>>>> Acked-by: Ori Kam <orika@nvidia.com>
>>>>> Acked-by: Andrew Rybchenko <andrew.rybchenko@oktetlabs.ru>
>>>>> ---
>>>>>  app/test-pmd/cmdline_flow.c            |  2 +-
>>>>>  doc/guides/prog_guide/rte_flow.rst     |  2 +-
>>>>>  doc/guides/rel_notes/release_24_03.rst |  1 +
>>>>>  drivers/net/mlx5/mlx5_flow.c           |  4 ++--
>>>>>  drivers/net/mlx5/mlx5_flow.h           |  6 +++---
>>>>>  drivers/net/mlx5/mlx5_flow_dv.c        | 10 +++++-----
>>>>>  lib/ethdev/rte_flow.h                  |  8 ++++----
>>>>>  7 files changed, 17 insertions(+), 16 deletions(-)
>>>>>
>>>>> diff --git a/app/test-pmd/cmdline_flow.c
>>>>> b/app/test-pmd/cmdline_flow.c index ce71818705..3725e955c7 100644
>>>>> --- a/app/test-pmd/cmdline_flow.c
>>>>> +++ b/app/test-pmd/cmdline_flow.c
>>>>> @@ -740,7 +740,7 @@ enum index {
>>>>>  #define ITEM_RAW_SIZE \
>>>>>  	(sizeof(struct rte_flow_item_raw) + ITEM_RAW_PATTERN_SIZE)
>>>>>
>>>>> -/** Maximum size for external pattern in struct
>>>>> rte_flow_action_modify_data. */
>>>>> +/** Maximum size for external pattern in struct rte_flow_field_data.
>>>>> +*/
>>>>>  #define ACTION_MODIFY_PATTERN_SIZE 32
>>>>>
>>>>
>>>> What do you think to update 'ACTION_MODIFY_PATTERN_SIZE' here too,
>>>> instead of next patch?
>>>
>>> Agree.
>>>
>>>>
>>>> <...>
>>>>
>>>>> diff --git a/lib/ethdev/rte_flow.h b/lib/ethdev/rte_flow.h index
>>>>> affdc8121b..40f6dcaacd 100644
>>>>> --- a/lib/ethdev/rte_flow.h
>>>>> +++ b/lib/ethdev/rte_flow.h
>>>>> @@ -3910,9 +3910,9 @@ enum rte_flow_field_id {
>>>>>   * @warning
>>>>>   * @b EXPERIMENTAL: this structure may change without prior notice
>>>>>   *
>>>>> - * Field description for MODIFY_FIELD action.
>>>>> + * Field description for packet field.
>>>>>
>>>>
>>>> New note is not very helpful, how can we make it more useful?
>>>>
>>>> Does it make sense to keep 'MODIFY_FIELD' and add 'COMPARE ITEM' in
>>>> next patch, to clarify the intended usage for the struct, otherwise it is too
>> generic.
>>>
>>> OK, sorry, the purpose is to make it generic. So next time if other ITEM or
>> ACTION need that field, it can be used directly.
>>> Otherwise, it feels like it can only be used by 'MODIFY_FIELD' and
>> 'COMPARE_ITEM', what do you think?
>>>
>>
>> I don't have an intention to limit its usage, but to clarify usage for whoever checks
>> the document.
>>
>> "Field description for packet field." doesn't say what exactly it is and cause
>> confusion.
>>
>> Perhaps wording can be changed to say two possible usages are for
>> 'MODIFY_FIELD' and 'COMPARE_ITEM'?
> 
> Sounds good, OK, I will update.
> 
> BTW, I saw the patch apply failed, seems it is due to Raslan's branch has some extra features than your branch.
> So I just want to know is it OK? Or should I still base on your branch? When will the branches be synced.
> 

Thanks.

Can you please rebase next version on next-net, this way we can benefit
from CI checks?


^ permalink raw reply	[flat|nested] 66+ messages in thread

* RE: [PATCH v3 1/3] ethdev: rename action modify field data structure
  2024-02-01 11:20               ` Ferruh Yigit
@ 2024-02-01 11:39                 ` Suanming Mou
  0 siblings, 0 replies; 66+ messages in thread
From: Suanming Mou @ 2024-02-01 11:39 UTC (permalink / raw)
  To: Ferruh Yigit, Ori Kam, Aman Singh, Yuying Zhang,
	Dariusz Sosnowski, Slava Ovsiienko, Matan Azrad,
	NBU-Contact-Thomas Monjalon (EXTERNAL),
	Andrew Rybchenko
  Cc: dev



> -----Original Message-----
> From: Ferruh Yigit <ferruh.yigit@amd.com>
> Sent: Thursday, February 1, 2024 7:21 PM
> To: Suanming Mou <suanmingm@nvidia.com>; Ori Kam <orika@nvidia.com>;
> Aman Singh <aman.deep.singh@intel.com>; Yuying Zhang
> <yuying.zhang@intel.com>; Dariusz Sosnowski <dsosnowski@nvidia.com>; Slava
> Ovsiienko <viacheslavo@nvidia.com>; Matan Azrad <matan@nvidia.com>; NBU-
> Contact-Thomas Monjalon (EXTERNAL) <thomas@monjalon.net>; Andrew
> Rybchenko <andrew.rybchenko@oktetlabs.ru>
> Cc: dev@dpdk.org
> Subject: Re: [PATCH v3 1/3] ethdev: rename action modify field data structure
> 
> On 2/1/2024 11:09 AM, Suanming Mou wrote:
> >
> >
> >> -----Original Message-----
> >> From: Ferruh Yigit <ferruh.yigit@amd.com>
> >> Sent: Thursday, February 1, 2024 6:56 PM
> >> To: Suanming Mou <suanmingm@nvidia.com>; Ori Kam <orika@nvidia.com>;
> >> Aman Singh <aman.deep.singh@intel.com>; Yuying Zhang
> >> <yuying.zhang@intel.com>; Dariusz Sosnowski <dsosnowski@nvidia.com>;
> >> Slava Ovsiienko <viacheslavo@nvidia.com>; Matan Azrad
> >> <matan@nvidia.com>; NBU- Contact-Thomas Monjalon (EXTERNAL)
> >> <thomas@monjalon.net>; Andrew Rybchenko
> >> <andrew.rybchenko@oktetlabs.ru>
> >> Cc: dev@dpdk.org
> >> Subject: Re: [PATCH v3 1/3] ethdev: rename action modify field data
> >> structure
> >>
> >> On 1/31/2024 2:57 AM, Suanming Mou wrote:
> >>> Hi,
> >>>
> >>>> -----Original Message-----
> >>>> From: Ferruh Yigit <ferruh.yigit@amd.com>
> >>>> Sent: Wednesday, January 31, 2024 1:19 AM
> >>>> To: Suanming Mou <suanmingm@nvidia.com>; Ori Kam
> >>>> <orika@nvidia.com>; Aman Singh <aman.deep.singh@intel.com>; Yuying
> >>>> Zhang <yuying.zhang@intel.com>; Dariusz Sosnowski
> >>>> <dsosnowski@nvidia.com>; Slava Ovsiienko <viacheslavo@nvidia.com>;
> >>>> Matan Azrad <matan@nvidia.com>; NBU- Contact-Thomas Monjalon
> >>>> (EXTERNAL) <thomas@monjalon.net>; Andrew Rybchenko
> >>>> <andrew.rybchenko@oktetlabs.ru>
> >>>> Cc: dev@dpdk.org
> >>>> Subject: Re: [PATCH v3 1/3] ethdev: rename action modify field data
> >>>> structure
> >>>>
> >>>> On 1/15/2024 9:13 AM, Suanming Mou wrote:
> >>>>> Current rte_flow_action_modify_data struct describes the pkt field
> >>>>> perfectly and is used only in action.
> >>>>>
> >>>>> It is planned to be used for item as well. This commit renames it
> >>>>> to "rte_flow_field_data" making it compatible to be used by item.
> >>>>>
> >>>>
> >>>> ack to rename struct to use in pattern.
> >>>>
> >>>>> Signed-off-by: Suanming Mou <suanmingm@nvidia.com>
> >>>>> Acked-by: Ori Kam <orika@nvidia.com>
> >>>>> Acked-by: Andrew Rybchenko <andrew.rybchenko@oktetlabs.ru>
> >>>>> ---
> >>>>>  app/test-pmd/cmdline_flow.c            |  2 +-
> >>>>>  doc/guides/prog_guide/rte_flow.rst     |  2 +-
> >>>>>  doc/guides/rel_notes/release_24_03.rst |  1 +
> >>>>>  drivers/net/mlx5/mlx5_flow.c           |  4 ++--
> >>>>>  drivers/net/mlx5/mlx5_flow.h           |  6 +++---
> >>>>>  drivers/net/mlx5/mlx5_flow_dv.c        | 10 +++++-----
> >>>>>  lib/ethdev/rte_flow.h                  |  8 ++++----
> >>>>>  7 files changed, 17 insertions(+), 16 deletions(-)
> >>>>>
> >>>>> diff --git a/app/test-pmd/cmdline_flow.c
> >>>>> b/app/test-pmd/cmdline_flow.c index ce71818705..3725e955c7 100644
> >>>>> --- a/app/test-pmd/cmdline_flow.c
> >>>>> +++ b/app/test-pmd/cmdline_flow.c
> >>>>> @@ -740,7 +740,7 @@ enum index {
> >>>>>  #define ITEM_RAW_SIZE \
> >>>>>  	(sizeof(struct rte_flow_item_raw) + ITEM_RAW_PATTERN_SIZE)
> >>>>>
> >>>>> -/** Maximum size for external pattern in struct
> >>>>> rte_flow_action_modify_data. */
> >>>>> +/** Maximum size for external pattern in struct rte_flow_field_data.
> >>>>> +*/
> >>>>>  #define ACTION_MODIFY_PATTERN_SIZE 32
> >>>>>
> >>>>
> >>>> What do you think to update 'ACTION_MODIFY_PATTERN_SIZE' here too,
> >>>> instead of next patch?
> >>>
> >>> Agree.
> >>>
> >>>>
> >>>> <...>
> >>>>
> >>>>> diff --git a/lib/ethdev/rte_flow.h b/lib/ethdev/rte_flow.h index
> >>>>> affdc8121b..40f6dcaacd 100644
> >>>>> --- a/lib/ethdev/rte_flow.h
> >>>>> +++ b/lib/ethdev/rte_flow.h
> >>>>> @@ -3910,9 +3910,9 @@ enum rte_flow_field_id {
> >>>>>   * @warning
> >>>>>   * @b EXPERIMENTAL: this structure may change without prior notice
> >>>>>   *
> >>>>> - * Field description for MODIFY_FIELD action.
> >>>>> + * Field description for packet field.
> >>>>>
> >>>>
> >>>> New note is not very helpful, how can we make it more useful?
> >>>>
> >>>> Does it make sense to keep 'MODIFY_FIELD' and add 'COMPARE ITEM' in
> >>>> next patch, to clarify the intended usage for the struct, otherwise
> >>>> it is too
> >> generic.
> >>>
> >>> OK, sorry, the purpose is to make it generic. So next time if other
> >>> ITEM or
> >> ACTION need that field, it can be used directly.
> >>> Otherwise, it feels like it can only be used by 'MODIFY_FIELD' and
> >> 'COMPARE_ITEM', what do you think?
> >>>
> >>
> >> I don't have an intention to limit its usage, but to clarify usage
> >> for whoever checks the document.
> >>
> >> "Field description for packet field." doesn't say what exactly it is
> >> and cause confusion.
> >>
> >> Perhaps wording can be changed to say two possible usages are for
> >> 'MODIFY_FIELD' and 'COMPARE_ITEM'?
> >
> > Sounds good, OK, I will update.
> >
> > BTW, I saw the patch apply failed, seems it is due to Raslan's branch has some
> extra features than your branch.
> > So I just want to know is it OK? Or should I still base on your branch? When will
> the branches be synced.
> >
> 
> Thanks.
> 
> Can you please rebase next version on next-net, this way we can benefit from CI
> checks?

OK, got it.


^ permalink raw reply	[flat|nested] 66+ messages in thread

* [PATCH v5 0/3] ethdev: add RTE_FLOW_ITEM_TYPE_COMPARE
  2023-12-14  3:12 [PATCH 0/2] ethdev: add RTE_FLOW_ITEM_TYPE_COMPARE Suanming Mou
                   ` (3 preceding siblings ...)
  2024-02-01  2:30 ` [PATCH v4 0/3] ethdev: add RTE_FLOW_ITEM_TYPE_COMPARE Suanming Mou
@ 2024-02-01 12:29 ` Suanming Mou
  2024-02-01 12:29   ` [PATCH v5 1/3] ethdev: rename action modify field data structure Suanming Mou
                     ` (3 more replies)
  2024-02-02  0:42 ` [PATCH v6 " Suanming Mou
  2024-02-06  2:06 ` [PATCH v7 0/4] ethdev: add RTE_FLOW_ITEM_TYPE_COMPARE Suanming Mou
  6 siblings, 4 replies; 66+ messages in thread
From: Suanming Mou @ 2024-02-01 12:29 UTC (permalink / raw)
  To: ferruh.yigit; +Cc: dev, orika

The new item type is added for the case user wants to match traffic
based on packet field compare result with other fields or immediate
value.

e.g. take advantage the compare item user will be able to accumulate
a IPv4/TCP packet's TCP data_offset and IPv4 IHL field to a tag
register, then compare the tag register with IPv4 header total length
to understand the packet has payload or not.

The supported operations can be as below:
 - RTE_FLOW_ITEM_COMPARE_EQ (equal)
 - RTE_FLOW_ITEM_COMPARE_NE (not equal)
 - RTE_FLOW_ITEM_COMPARE_LT (less than)
 - RTE_FLOW_ITEM_COMPARE_LE (less than or equal)
 - RTE_FLOW_ITEM_COMPARE_GT (great than)
 - RTE_FLOW_ITEM_COMPARE_GE (great than or equal)

V5:
 - rebase on top of next-net
 - add sample detail for rte_flow_field.

V4:
 - rebase on top of the latest version.
 - move ACTION_MODIFY_PATTERN_SIZE and modify_field_ids rename
   to first patch.
 - add comparison flow create sample in testpmd_funcs.rst.

V3:
 - fix code style missing empty line in rte_flow.rst.
 - fix missing the ABI change release notes.

V2:
 - Since modify field data struct is experiment, rename modify
   field data directly instead of adding new flow field struct.


Suanming Mou (3):
  ethdev: rename action modify field data structure
  ethdev: add compare item
  net/mlx5: add compare item support

 app/test-pmd/cmdline_flow.c                 | 416 +++++++++++++++++++-
 doc/guides/nics/features/default.ini        |   1 +
 doc/guides/nics/features/mlx5.ini           |   1 +
 doc/guides/nics/mlx5.rst                    |   7 +
 doc/guides/prog_guide/rte_flow.rst          |   9 +-
 doc/guides/rel_notes/release_24_03.rst      |   8 +
 doc/guides/testpmd_app_ug/testpmd_funcs.rst |  24 ++
 drivers/net/mlx5/mlx5_flow.c                |   4 +-
 drivers/net/mlx5/mlx5_flow.h                |   9 +-
 drivers/net/mlx5/mlx5_flow_dv.c             |  10 +-
 drivers/net/mlx5/mlx5_flow_hw.c             |  73 ++++
 lib/ethdev/rte_flow.c                       |   1 +
 lib/ethdev/rte_flow.h                       | 332 +++++++++-------
 13 files changed, 726 insertions(+), 169 deletions(-)

-- 
2.34.1


^ permalink raw reply	[flat|nested] 66+ messages in thread

* [PATCH v5 1/3] ethdev: rename action modify field data structure
  2024-02-01 12:29 ` [PATCH v5 0/3] ethdev: add RTE_FLOW_ITEM_TYPE_COMPARE Suanming Mou
@ 2024-02-01 12:29   ` Suanming Mou
  2024-02-01 18:57     ` Ferruh Yigit
  2024-02-01 12:29   ` [PATCH v5 2/3] ethdev: add compare item Suanming Mou
                     ` (2 subsequent siblings)
  3 siblings, 1 reply; 66+ messages in thread
From: Suanming Mou @ 2024-02-01 12:29 UTC (permalink / raw)
  To: ferruh.yigit, Ori Kam, Aman Singh, Yuying Zhang,
	Dariusz Sosnowski, Viacheslav Ovsiienko, Matan Azrad,
	Thomas Monjalon, Andrew Rybchenko
  Cc: dev

Current rte_flow_action_modify_data struct describes the pkt
field perfectly and is used only in action.

It is planned to be used for item as well. This commit renames
it to "rte_flow_field_data" making it compatible to be used by item.

Signed-off-by: Suanming Mou <suanmingm@nvidia.com>
Acked-by: Ori Kam <orika@nvidia.com>
Acked-by: Andrew Rybchenko <andrew.rybchenko@oktetlabs.ru>
---
 app/test-pmd/cmdline_flow.c            | 22 +++++++++++-----------
 doc/guides/prog_guide/rte_flow.rst     |  2 +-
 doc/guides/rel_notes/release_24_03.rst |  1 +
 drivers/net/mlx5/mlx5_flow.c           |  4 ++--
 drivers/net/mlx5/mlx5_flow.h           |  6 +++---
 drivers/net/mlx5/mlx5_flow_dv.c        | 10 +++++-----
 lib/ethdev/rte_flow.h                  | 12 ++++++++----
 7 files changed, 31 insertions(+), 26 deletions(-)

diff --git a/app/test-pmd/cmdline_flow.c b/app/test-pmd/cmdline_flow.c
index 359c187b3c..972c6ae490 100644
--- a/app/test-pmd/cmdline_flow.c
+++ b/app/test-pmd/cmdline_flow.c
@@ -742,13 +742,13 @@ enum index {
 #define ITEM_RAW_SIZE \
 	(sizeof(struct rte_flow_item_raw) + ITEM_RAW_PATTERN_SIZE)
 
-/** Maximum size for external pattern in struct rte_flow_action_modify_data. */
-#define ACTION_MODIFY_PATTERN_SIZE 32
+/** Maximum size for external pattern in struct rte_flow_field_data. */
+#define FLOW_FIELD_PATTERN_SIZE 32
 
 /** Storage size for struct rte_flow_action_modify_field including pattern. */
 #define ACTION_MODIFY_SIZE \
 	(sizeof(struct rte_flow_action_modify_field) + \
-	ACTION_MODIFY_PATTERN_SIZE)
+	FLOW_FIELD_PATTERN_SIZE)
 
 /** Maximum number of queue indices in struct rte_flow_action_rss. */
 #define ACTION_RSS_QUEUE_NUM 128
@@ -942,7 +942,7 @@ static const char *const modify_field_ops[] = {
 	"set", "add", "sub", NULL
 };
 
-static const char *const modify_field_ids[] = {
+static const char *const flow_field_ids[] = {
 	"start", "mac_dst", "mac_src",
 	"vlan_type", "vlan_id", "mac_type",
 	"ipv4_dscp", "ipv4_ttl", "ipv4_src", "ipv4_dst",
@@ -6986,7 +6986,7 @@ static const struct token token_list[] = {
 			     ARGS_ENTRY_ARB(0, 0),
 			     ARGS_ENTRY_ARB
 				(sizeof(struct rte_flow_action_modify_field),
-				 ACTION_MODIFY_PATTERN_SIZE)),
+				 FLOW_FIELD_PATTERN_SIZE)),
 		.call = parse_vc_conf,
 	},
 	[ACTION_MODIFY_FIELD_WIDTH] = {
@@ -9798,10 +9798,10 @@ parse_vc_modify_field_id(struct context *ctx, const struct token *token,
 	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))
+	for (i = 0; flow_field_ids[i]; ++i)
+		if (!strcmp_partial(flow_field_ids[i], str, len))
 			break;
-	if (!modify_field_ids[i])
+	if (!flow_field_ids[i])
 		return -1;
 	if (!ctx->object)
 		return len;
@@ -12028,10 +12028,10 @@ comp_set_modify_field_id(struct context *ctx, const struct token *token,
 
 	RTE_SET_USED(token);
 	if (!buf)
-		return RTE_DIM(modify_field_ids);
-	if (ent >= RTE_DIM(modify_field_ids) - 1)
+		return RTE_DIM(flow_field_ids);
+	if (ent >= RTE_DIM(flow_field_ids) - 1)
 		return -1;
-	name = modify_field_ids[ent];
+	name = flow_field_ids[ent];
 	if (ctx->curr == ACTION_MODIFY_FIELD_SRC_TYPE ||
 	    (strcmp(name, "pointer") && strcmp(name, "value")))
 		return strlcpy(buf, name, size);
diff --git a/doc/guides/prog_guide/rte_flow.rst b/doc/guides/prog_guide/rte_flow.rst
index 900fdaefb6..f936a9ba19 100644
--- a/doc/guides/prog_guide/rte_flow.rst
+++ b/doc/guides/prog_guide/rte_flow.rst
@@ -3185,7 +3185,7 @@ destination offset as ``48``, and provide immediate value ``0xXXXX85XX``.
    | ``width``     | number of bits to use   |
    +---------------+-------------------------+
 
-.. _table_rte_flow_action_modify_data:
+.. _table_rte_flow_field_data:
 
 .. table:: destination/source field definition
 
diff --git a/doc/guides/rel_notes/release_24_03.rst b/doc/guides/rel_notes/release_24_03.rst
index 84d3144215..efeda6ea97 100644
--- a/doc/guides/rel_notes/release_24_03.rst
+++ b/doc/guides/rel_notes/release_24_03.rst
@@ -124,6 +124,7 @@ ABI Changes
 
 * No ABI change that would break compatibility with 23.11.
 
+* ethdev: Rename the experimental ``struct rte_flow_action_modify_data`` to be ``struct rte_flow_field_data``
 
 Known Issues
 ------------
diff --git a/drivers/net/mlx5/mlx5_flow.c b/drivers/net/mlx5/mlx5_flow.c
index 85e8c77c81..5788a7fb57 100644
--- a/drivers/net/mlx5/mlx5_flow.c
+++ b/drivers/net/mlx5/mlx5_flow.c
@@ -2493,7 +2493,7 @@ mlx5_validate_action_ct(struct rte_eth_dev *dev,
  * Validate the level value for modify field action.
  *
  * @param[in] data
- *   Pointer to the rte_flow_action_modify_data structure either src or dst.
+ *   Pointer to the rte_flow_field_data structure either src or dst.
  * @param[out] error
  *   Pointer to error structure.
  *
@@ -2501,7 +2501,7 @@ mlx5_validate_action_ct(struct rte_eth_dev *dev,
  *   0 on success, a negative errno value otherwise and rte_errno is set.
  */
 int
-flow_validate_modify_field_level(const struct rte_flow_action_modify_data *data,
+flow_validate_modify_field_level(const struct rte_flow_field_data *data,
 				 struct rte_flow_error *error)
 {
 	if (data->level == 0)
diff --git a/drivers/net/mlx5/mlx5_flow.h b/drivers/net/mlx5/mlx5_flow.h
index 6dde9de688..ecfb04ead2 100644
--- a/drivers/net/mlx5/mlx5_flow.h
+++ b/drivers/net/mlx5/mlx5_flow.h
@@ -1121,7 +1121,7 @@ flow_items_to_tunnel(const struct rte_flow_item items[])
  *   Tag array index.
  */
 static inline uint8_t
-flow_tag_index_get(const struct rte_flow_action_modify_data *data)
+flow_tag_index_get(const struct rte_flow_field_data *data)
 {
 	return data->tag_index ? data->tag_index : data->level;
 }
@@ -2523,7 +2523,7 @@ int mlx5_flow_validate_action_default_miss(uint64_t action_flags,
 				const struct rte_flow_attr *attr,
 				struct rte_flow_error *error);
 int flow_validate_modify_field_level
-			(const struct rte_flow_action_modify_data *data,
+			(const struct rte_flow_field_data *data,
 			 struct rte_flow_error *error);
 int mlx5_flow_item_acceptable(const struct rte_flow_item *item,
 			      const uint8_t *mask,
@@ -2828,7 +2828,7 @@ size_t flow_dv_get_item_hdr_len(const enum rte_flow_item_type item_type);
 int flow_dv_convert_encap_data(const struct rte_flow_item *items, uint8_t *buf,
 			   size_t *size, struct rte_flow_error *error);
 void mlx5_flow_field_id_to_modify_info
-		(const struct rte_flow_action_modify_data *data,
+		(const struct rte_flow_field_data *data,
 		 struct field_modify_info *info, uint32_t *mask,
 		 uint32_t width, struct rte_eth_dev *dev,
 		 const struct rte_flow_attr *attr, struct rte_flow_error *error);
diff --git a/drivers/net/mlx5/mlx5_flow_dv.c b/drivers/net/mlx5/mlx5_flow_dv.c
index 115d730317..52620be262 100644
--- a/drivers/net/mlx5/mlx5_flow_dv.c
+++ b/drivers/net/mlx5/mlx5_flow_dv.c
@@ -1441,7 +1441,7 @@ flow_modify_info_mask_32_masked(uint32_t length, uint32_t off, uint32_t post_mas
 }
 
 static __rte_always_inline enum mlx5_modification_field
-mlx5_mpls_modi_field_get(const struct rte_flow_action_modify_data *data)
+mlx5_mpls_modi_field_get(const struct rte_flow_field_data *data)
 {
 	return MLX5_MODI_IN_MPLS_LABEL_0 + data->tag_index;
 }
@@ -1449,7 +1449,7 @@ mlx5_mpls_modi_field_get(const struct rte_flow_action_modify_data *data)
 static void
 mlx5_modify_flex_item(const struct rte_eth_dev *dev,
 		      const struct mlx5_flex_item *flex,
-		      const struct rte_flow_action_modify_data *data,
+		      const struct rte_flow_field_data *data,
 		      struct field_modify_info *info,
 		      uint32_t *mask, uint32_t width)
 {
@@ -1573,7 +1573,7 @@ mlx5_modify_flex_item(const struct rte_eth_dev *dev,
 
 void
 mlx5_flow_field_id_to_modify_info
-		(const struct rte_flow_action_modify_data *data,
+		(const struct rte_flow_field_data *data,
 		 struct field_modify_info *info, uint32_t *mask,
 		 uint32_t width, struct rte_eth_dev *dev,
 		 const struct rte_flow_attr *attr, struct rte_flow_error *error)
@@ -5284,8 +5284,8 @@ flow_dv_validate_action_modify_field(struct rte_eth_dev *dev,
 	struct mlx5_sh_config *config = &priv->sh->config;
 	struct mlx5_hca_attr *hca_attr = &priv->sh->cdev->config.hca_attr;
 	const struct rte_flow_action_modify_field *conf = action->conf;
-	const struct rte_flow_action_modify_data *src_data = &conf->src;
-	const struct rte_flow_action_modify_data *dst_data = &conf->dst;
+	const struct rte_flow_field_data *src_data = &conf->src;
+	const struct rte_flow_field_data *dst_data = &conf->dst;
 	uint32_t dst_width, src_width, width = conf->width;
 
 	ret = flow_dv_validate_action_modify_hdr(action_flags, action, error);
diff --git a/lib/ethdev/rte_flow.h b/lib/ethdev/rte_flow.h
index 1267c146e5..a143ecb194 100644
--- a/lib/ethdev/rte_flow.h
+++ b/lib/ethdev/rte_flow.h
@@ -3887,6 +3887,8 @@ struct rte_flow_action_ethdev {
 
 /**
  * Field IDs for MODIFY_FIELD action.
+ * e.g. the packet field IDs used in RTE_FLOW_ACTION_TYPE_MODIFY_FIELD
+ * and RTE_FLOW_ITEM_TYPE_COMPARE.
  */
 enum rte_flow_field_id {
 	RTE_FLOW_FIELD_START = 0,	/**< Start of a packet. */
@@ -3940,9 +3942,11 @@ enum rte_flow_field_id {
  * @warning
  * @b EXPERIMENTAL: this structure may change without prior notice
  *
- * Field description for MODIFY_FIELD action.
+ * Field description for packet field.
+ * e.g. the packet fields used in RTE_FLOW_ACTION_TYPE_MODIFY_FIELD
+ * and RTE_FLOW_ITEM_TYPE_COMPARE.
  */
-struct rte_flow_action_modify_data {
+struct rte_flow_field_data {
 	enum rte_flow_field_id field; /**< Field or memory type ID. */
 	union {
 		struct {
@@ -4051,8 +4055,8 @@ enum rte_flow_modify_op {
  */
 struct rte_flow_action_modify_field {
 	enum rte_flow_modify_op operation; /**< Operation to perform. */
-	struct rte_flow_action_modify_data dst; /**< Destination field. */
-	struct rte_flow_action_modify_data src; /**< Source field. */
+	struct rte_flow_field_data dst; /**< Destination field. */
+	struct rte_flow_field_data src; /**< Source field. */
 	uint32_t width; /**< Number of bits to use from a source field. */
 };
 
-- 
2.34.1


^ permalink raw reply	[flat|nested] 66+ messages in thread

* [PATCH v5 2/3] ethdev: add compare item
  2024-02-01 12:29 ` [PATCH v5 0/3] ethdev: add RTE_FLOW_ITEM_TYPE_COMPARE Suanming Mou
  2024-02-01 12:29   ` [PATCH v5 1/3] ethdev: rename action modify field data structure Suanming Mou
@ 2024-02-01 12:29   ` Suanming Mou
  2024-02-01 18:57     ` Ferruh Yigit
  2024-02-01 12:29   ` [PATCH v5 3/3] net/mlx5: add compare item support Suanming Mou
  2024-02-01 18:56   ` [PATCH v5 0/3] ethdev: add RTE_FLOW_ITEM_TYPE_COMPARE Ferruh Yigit
  3 siblings, 1 reply; 66+ messages in thread
From: Suanming Mou @ 2024-02-01 12:29 UTC (permalink / raw)
  To: ferruh.yigit, Ori Kam, Aman Singh, Yuying Zhang, Thomas Monjalon,
	Andrew Rybchenko
  Cc: dev

The new item type is added for the case user wants to match traffic
based on packet field compare result with other fields or immediate
value.

e.g. take advantage the compare item user will be able to accumulate
a IPv4/TCP packet's TCP data_offset and IPv4 IHL field to a tag
register, then compare the tag register with IPv4 header total length
to understand the packet has payload or not.

The supported operations can be as below:
 - RTE_FLOW_ITEM_COMPARE_EQ (equal)
 - RTE_FLOW_ITEM_COMPARE_NE (not equal)
 - RTE_FLOW_ITEM_COMPARE_LT (less than)
 - RTE_FLOW_ITEM_COMPARE_LE (less than or equal)
 - RTE_FLOW_ITEM_COMPARE_GT (great than)
 - RTE_FLOW_ITEM_COMPARE_GE (great than or equal)

A sample for create the comparison flow:
flow pattern_template 0 create ingress pattern_template_id 1 template \
	compare op mask le a_type mask tag a_tag_index mask 1 b_type \
	mask tag b_tag_index mask 2 width mask 0xffffffff / end
flow actions_template 0 create ingress actions_template_id 1 template \
	count / drop / end mask count / drop  / end
flow template_table 0 create table_id 1 group 2 priority 1  ingress \
	rules_number 1 pattern_template 1 actions_template 1
flow queue 0 create 0 template_table 1 pattern_template 0 \
	actions_template 0 postpone no pattern compare op is le \
	a_type is tag a_tag_index is 1 b_type is tag b_tag_index is 2 \
	width is 32 / end actions count / drop / end

Signed-off-by: Suanming Mou <suanmingm@nvidia.com>
Acked-by: Ori Kam <orika@nvidia.com>
Acked-by: Andrew Rybchenko <andrew.rybchenko@oktetlabs.ru>
---
 app/test-pmd/cmdline_flow.c                 | 394 ++++++++++++++++++++
 doc/guides/nics/features/default.ini        |   1 +
 doc/guides/prog_guide/rte_flow.rst          |   7 +
 doc/guides/rel_notes/release_24_03.rst      |   5 +
 doc/guides/testpmd_app_ug/testpmd_funcs.rst |  24 ++
 lib/ethdev/rte_flow.c                       |   1 +
 lib/ethdev/rte_flow.h                       | 332 +++++++++--------
 7 files changed, 615 insertions(+), 149 deletions(-)

diff --git a/app/test-pmd/cmdline_flow.c b/app/test-pmd/cmdline_flow.c
index 972c6ae490..69b14c6eb1 100644
--- a/app/test-pmd/cmdline_flow.c
+++ b/app/test-pmd/cmdline_flow.c
@@ -545,6 +545,28 @@ enum index {
 	ITEM_PTYPE,
 	ITEM_PTYPE_VALUE,
 	ITEM_NSH,
+	ITEM_COMPARE,
+	ITEM_COMPARE_OP,
+	ITEM_COMPARE_OP_VALUE,
+	ITEM_COMPARE_FIELD_A_TYPE,
+	ITEM_COMPARE_FIELD_A_TYPE_VALUE,
+	ITEM_COMPARE_FIELD_A_LEVEL,
+	ITEM_COMPARE_FIELD_A_LEVEL_VALUE,
+	ITEM_COMPARE_FIELD_A_TAG_INDEX,
+	ITEM_COMPARE_FIELD_A_TYPE_ID,
+	ITEM_COMPARE_FIELD_A_CLASS_ID,
+	ITEM_COMPARE_FIELD_A_OFFSET,
+	ITEM_COMPARE_FIELD_B_TYPE,
+	ITEM_COMPARE_FIELD_B_TYPE_VALUE,
+	ITEM_COMPARE_FIELD_B_LEVEL,
+	ITEM_COMPARE_FIELD_B_LEVEL_VALUE,
+	ITEM_COMPARE_FIELD_B_TAG_INDEX,
+	ITEM_COMPARE_FIELD_B_TYPE_ID,
+	ITEM_COMPARE_FIELD_B_CLASS_ID,
+	ITEM_COMPARE_FIELD_B_OFFSET,
+	ITEM_COMPARE_FIELD_B_VALUE,
+	ITEM_COMPARE_FIELD_B_POINTER,
+	ITEM_COMPARE_FIELD_WIDTH,
 
 	/* Validate/create actions. */
 	ACTIONS,
@@ -742,6 +764,10 @@ enum index {
 #define ITEM_RAW_SIZE \
 	(sizeof(struct rte_flow_item_raw) + ITEM_RAW_PATTERN_SIZE)
 
+static const char *const compare_ops[] = {
+	"eq", "ne", "lt", "le", "gt", "ge", NULL
+};
+
 /** Maximum size for external pattern in struct rte_flow_field_data. */
 #define FLOW_FIELD_PATTERN_SIZE 32
 
@@ -1594,6 +1620,7 @@ static const enum index next_item[] = {
 	ITEM_IB_BTH,
 	ITEM_PTYPE,
 	ITEM_NSH,
+	ITEM_COMPARE,
 	END_SET,
 	ZERO,
 };
@@ -2131,6 +2158,38 @@ static const enum index item_nsh[] = {
 	ZERO,
 };
 
+static const enum index item_compare_field[] = {
+	ITEM_COMPARE_OP,
+	ITEM_COMPARE_FIELD_A_TYPE,
+	ITEM_COMPARE_FIELD_B_TYPE,
+	ITEM_NEXT,
+	ZERO,
+};
+
+static const enum index compare_field_a[] = {
+	ITEM_COMPARE_FIELD_A_TYPE,
+	ITEM_COMPARE_FIELD_A_LEVEL,
+	ITEM_COMPARE_FIELD_A_TAG_INDEX,
+	ITEM_COMPARE_FIELD_A_TYPE_ID,
+	ITEM_COMPARE_FIELD_A_CLASS_ID,
+	ITEM_COMPARE_FIELD_A_OFFSET,
+	ITEM_COMPARE_FIELD_B_TYPE,
+	ZERO,
+};
+
+static const enum index compare_field_b[] = {
+	ITEM_COMPARE_FIELD_B_TYPE,
+	ITEM_COMPARE_FIELD_B_LEVEL,
+	ITEM_COMPARE_FIELD_B_TAG_INDEX,
+	ITEM_COMPARE_FIELD_B_TYPE_ID,
+	ITEM_COMPARE_FIELD_B_CLASS_ID,
+	ITEM_COMPARE_FIELD_B_OFFSET,
+	ITEM_COMPARE_FIELD_B_VALUE,
+	ITEM_COMPARE_FIELD_B_POINTER,
+	ITEM_COMPARE_FIELD_WIDTH,
+	ZERO,
+};
+
 static const enum index next_action[] = {
 	ACTION_END,
 	ACTION_VOID,
@@ -2873,6 +2932,24 @@ comp_quota_update_name(struct context *ctx, const struct token *token,
 static int
 comp_qu_mode_name(struct context *ctx, const struct token *token,
 		  unsigned int ent, char *buf, unsigned int size);
+static int
+comp_set_compare_field_id(struct context *ctx, const struct token *token,
+			  unsigned int ent, char *buf, unsigned int size);
+static int
+comp_set_compare_op(struct context *ctx, const struct token *token,
+		    unsigned int ent, char *buf, unsigned int size);
+static int
+parse_vc_compare_op(struct context *ctx, const struct token *token,
+			 const char *str, unsigned int len, void *buf,
+			 unsigned int size);
+static int
+parse_vc_compare_field_id(struct context *ctx, const struct token *token,
+			  const char *str, unsigned int len, void *buf,
+			  unsigned int size);
+static int
+parse_vc_compare_field_level(struct context *ctx, const struct token *token,
+			     const char *str, unsigned int len, void *buf,
+			     unsigned int size);
 
 struct indlst_conf {
 	uint32_t id;
@@ -6007,6 +6084,174 @@ static const struct token token_list[] = {
 		.next = NEXT(item_nsh),
 		.call = parse_vc,
 	},
+	[ITEM_COMPARE] = {
+		.name = "compare",
+		.help = "match with the comparison result",
+		.priv = PRIV_ITEM(COMPARE, sizeof(struct rte_flow_item_compare)),
+		.next = NEXT(NEXT_ENTRY(ITEM_COMPARE_OP)),
+		.call = parse_vc,
+	},
+	[ITEM_COMPARE_OP] = {
+		.name = "op",
+		.help = "operation type",
+		.next = NEXT(item_compare_field,
+			NEXT_ENTRY(ITEM_COMPARE_OP_VALUE), item_param),
+		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_compare, operation)),
+	},
+	[ITEM_COMPARE_OP_VALUE] = {
+		.name = "{operation}",
+		.help = "operation type value",
+		.call = parse_vc_compare_op,
+		.comp = comp_set_compare_op,
+	},
+	[ITEM_COMPARE_FIELD_A_TYPE] = {
+		.name = "a_type",
+		.help = "compared field type",
+		.next = NEXT(compare_field_a,
+			NEXT_ENTRY(ITEM_COMPARE_FIELD_A_TYPE_VALUE), item_param),
+		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_compare, a.field)),
+	},
+	[ITEM_COMPARE_FIELD_A_TYPE_VALUE] = {
+		.name = "{a_type}",
+		.help = "compared field type value",
+		.call = parse_vc_compare_field_id,
+		.comp = comp_set_compare_field_id,
+	},
+	[ITEM_COMPARE_FIELD_A_LEVEL] = {
+		.name = "a_level",
+		.help = "compared field level",
+		.next = NEXT(compare_field_a,
+			     NEXT_ENTRY(ITEM_COMPARE_FIELD_A_LEVEL_VALUE), item_param),
+		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_compare, a.level)),
+	},
+	[ITEM_COMPARE_FIELD_A_LEVEL_VALUE] = {
+		.name = "{a_level}",
+		.help = "compared field level value",
+		.call = parse_vc_compare_field_level,
+		.comp = comp_none,
+	},
+	[ITEM_COMPARE_FIELD_A_TAG_INDEX] = {
+		.name = "a_tag_index",
+		.help = "compared field tag array",
+		.next = NEXT(compare_field_a,
+			     NEXT_ENTRY(COMMON_UNSIGNED), item_param),
+		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_compare,
+					a.tag_index)),
+	},
+	[ITEM_COMPARE_FIELD_A_TYPE_ID] = {
+		.name = "a_type_id",
+		.help = "compared field type ID",
+		.next = NEXT(compare_field_a,
+			     NEXT_ENTRY(COMMON_UNSIGNED), item_param),
+		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_compare,
+					a.type)),
+	},
+	[ITEM_COMPARE_FIELD_A_CLASS_ID] = {
+		.name = "a_class",
+		.help = "compared field class ID",
+		.next = NEXT(compare_field_a,
+			     NEXT_ENTRY(COMMON_UNSIGNED), item_param),
+		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_compare,
+					     a.class_id)),
+	},
+	[ITEM_COMPARE_FIELD_A_OFFSET] = {
+		.name = "a_offset",
+		.help = "compared field bit offset",
+		.next = NEXT(compare_field_a,
+			     NEXT_ENTRY(COMMON_UNSIGNED), item_param),
+		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_compare,
+					a.offset)),
+	},
+	[ITEM_COMPARE_FIELD_B_TYPE] = {
+		.name = "b_type",
+		.help = "comparator field type",
+		.next = NEXT(compare_field_b,
+			NEXT_ENTRY(ITEM_COMPARE_FIELD_B_TYPE_VALUE), item_param),
+		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_compare,
+					b.field)),
+	},
+	[ITEM_COMPARE_FIELD_B_TYPE_VALUE] = {
+		.name = "{b_type}",
+		.help = "comparator field type value",
+		.call = parse_vc_compare_field_id,
+		.comp = comp_set_compare_field_id,
+	},
+	[ITEM_COMPARE_FIELD_B_LEVEL] = {
+		.name = "b_level",
+		.help = "comparator field level",
+		.next = NEXT(compare_field_b,
+			     NEXT_ENTRY(ITEM_COMPARE_FIELD_B_LEVEL_VALUE), item_param),
+		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_compare,
+					b.level)),
+	},
+	[ITEM_COMPARE_FIELD_B_LEVEL_VALUE] = {
+		.name = "{b_level}",
+		.help = "comparator field level value",
+		.call = parse_vc_compare_field_level,
+		.comp = comp_none,
+	},
+	[ITEM_COMPARE_FIELD_B_TAG_INDEX] = {
+		.name = "b_tag_index",
+		.help = "comparator field tag array",
+		.next = NEXT(compare_field_b,
+			     NEXT_ENTRY(COMMON_UNSIGNED), item_param),
+		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_compare,
+					b.tag_index)),
+	},
+	[ITEM_COMPARE_FIELD_B_TYPE_ID] = {
+		.name = "b_type_id",
+		.help = "comparator field type ID",
+		.next = NEXT(compare_field_b,
+			     NEXT_ENTRY(COMMON_UNSIGNED), item_param),
+		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_compare,
+					b.type)),
+	},
+	[ITEM_COMPARE_FIELD_B_CLASS_ID] = {
+		.name = "b_class",
+		.help = "comparator field class ID",
+		.next = NEXT(compare_field_b,
+			     NEXT_ENTRY(COMMON_UNSIGNED), item_param),
+		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_compare,
+					     b.class_id)),
+	},
+	[ITEM_COMPARE_FIELD_B_OFFSET] = {
+		.name = "b_offset",
+		.help = "comparator field bit offset",
+		.next = NEXT(compare_field_b,
+			     NEXT_ENTRY(COMMON_UNSIGNED), item_param),
+		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_compare,
+					b.offset)),
+	},
+	[ITEM_COMPARE_FIELD_B_VALUE] = {
+		.name = "b_value",
+		.help = "comparator immediate value",
+		.next = NEXT(compare_field_b,
+			     NEXT_ENTRY(COMMON_HEX), item_param),
+		.args = ARGS(ARGS_ENTRY_ARB(0, 0),
+			     ARGS_ENTRY_ARB(0, 0),
+			     ARGS_ENTRY(struct rte_flow_item_compare,
+					b.value)),
+	},
+	[ITEM_COMPARE_FIELD_B_POINTER] = {
+		.name = "b_ptr",
+		.help = "pointer to comparator immediate value",
+		.next = NEXT(compare_field_b,
+			     NEXT_ENTRY(COMMON_HEX), item_param),
+		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_compare,
+					b.pvalue),
+			     ARGS_ENTRY_ARB(0, 0),
+			     ARGS_ENTRY_ARB
+				(sizeof(struct rte_flow_item_compare),
+				 FLOW_FIELD_PATTERN_SIZE)),
+	},
+	[ITEM_COMPARE_FIELD_WIDTH] = {
+		.name = "width",
+		.help = "number of bits to compare",
+		.next = NEXT(item_compare_field,
+			NEXT_ENTRY(COMMON_UNSIGNED), item_param),
+		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_compare,
+					width)),
+	},
 
 	/* Validate/create actions. */
 	[ACTIONS] = {
@@ -8429,6 +8674,122 @@ parse_vc_item_l2tpv2_type(struct context *ctx, const struct token *token,
 	return len;
 }
 
+/** Parse operation for compare match item. */
+static int
+parse_vc_compare_op(struct context *ctx, const struct token *token,
+			 const char *str, unsigned int len, void *buf,
+			 unsigned int size)
+{
+	struct rte_flow_item_compare *compare_item;
+	unsigned int i;
+
+	(void)token;
+	(void)buf;
+	(void)size;
+	if (ctx->curr != ITEM_COMPARE_OP_VALUE)
+		return -1;
+	for (i = 0; compare_ops[i]; ++i)
+		if (!strcmp_partial(compare_ops[i], str, len))
+			break;
+	if (!compare_ops[i])
+		return -1;
+	if (!ctx->object)
+		return len;
+	compare_item = ctx->object;
+	compare_item->operation = (enum rte_flow_item_compare_op)i;
+	return len;
+}
+
+/** Parse id for compare match item. */
+static int
+parse_vc_compare_field_id(struct context *ctx, const struct token *token,
+			  const char *str, unsigned int len, void *buf,
+			  unsigned int size)
+{
+	struct rte_flow_item_compare *compare_item;
+	unsigned int i;
+
+	(void)token;
+	(void)buf;
+	(void)size;
+	if (ctx->curr != ITEM_COMPARE_FIELD_A_TYPE_VALUE &&
+		ctx->curr != ITEM_COMPARE_FIELD_B_TYPE_VALUE)
+		return -1;
+	for (i = 0; flow_field_ids[i]; ++i)
+		if (!strcmp_partial(flow_field_ids[i], str, len))
+			break;
+	if (!flow_field_ids[i])
+		return -1;
+	if (!ctx->object)
+		return len;
+	compare_item = ctx->object;
+	if (ctx->curr == ITEM_COMPARE_FIELD_A_TYPE_VALUE)
+		compare_item->a.field = (enum rte_flow_field_id)i;
+	else
+		compare_item->b.field = (enum rte_flow_field_id)i;
+	return len;
+}
+
+/** Parse level for compare match item. */
+static int
+parse_vc_compare_field_level(struct context *ctx, const struct token *token,
+			     const char *str, unsigned int len, void *buf,
+			     unsigned int size)
+{
+	struct rte_flow_item_compare *compare_item;
+	struct flex_item *fp = NULL;
+	uint32_t val;
+	struct buffer *out = buf;
+	char *end;
+
+	(void)token;
+	(void)size;
+	if (ctx->curr != ITEM_COMPARE_FIELD_A_LEVEL_VALUE &&
+		ctx->curr != ITEM_COMPARE_FIELD_B_LEVEL_VALUE)
+		return -1;
+	if (!ctx->object)
+		return len;
+	compare_item = ctx->object;
+	errno = 0;
+	val = strtoumax(str, &end, 0);
+	if (errno || (size_t)(end - str) != len)
+		return -1;
+	/* No need to validate action template mask value */
+	if (out->args.vc.masks) {
+		if (ctx->curr == ITEM_COMPARE_FIELD_A_LEVEL_VALUE)
+			compare_item->a.level = val;
+		else
+			compare_item->b.level = val;
+		return len;
+	}
+	if ((ctx->curr == ITEM_COMPARE_FIELD_A_LEVEL_VALUE &&
+		compare_item->a.field == RTE_FLOW_FIELD_FLEX_ITEM) ||
+		(ctx->curr == ITEM_COMPARE_FIELD_B_LEVEL_VALUE &&
+		compare_item->b.field == RTE_FLOW_FIELD_FLEX_ITEM)) {
+		if (val >= FLEX_MAX_PARSERS_NUM) {
+			printf("Bad flex item handle\n");
+			return -1;
+		}
+		fp = flex_items[ctx->port][val];
+		if (!fp) {
+			printf("Bad flex item handle\n");
+			return -1;
+		}
+	}
+	if (ctx->curr == ITEM_COMPARE_FIELD_A_LEVEL_VALUE) {
+		if (compare_item->a.field != RTE_FLOW_FIELD_FLEX_ITEM)
+			compare_item->a.level = val;
+		else
+			compare_item->a.flex_handle = fp->flex_handle;
+	} else if (ctx->curr == ITEM_COMPARE_FIELD_B_LEVEL_VALUE) {
+		if (compare_item->b.field != RTE_FLOW_FIELD_FLEX_ITEM)
+			compare_item->b.level = val;
+		else
+			compare_item->b.flex_handle = fp->flex_handle;
+	}
+	return len;
+}
+
 /** Parse meter color action type. */
 static int
 parse_vc_action_meter_color_type(struct context *ctx, const struct token *token,
@@ -11915,6 +12276,39 @@ comp_rule_id(struct context *ctx, const struct token *token,
 	return i;
 }
 
+/** Complete operation for compare match item. */
+static int
+comp_set_compare_op(struct context *ctx, const struct token *token,
+		    unsigned int ent, char *buf, unsigned int size)
+{
+	RTE_SET_USED(ctx);
+	RTE_SET_USED(token);
+	if (!buf)
+		return RTE_DIM(compare_ops);
+	if (ent < RTE_DIM(compare_ops) - 1)
+		return strlcpy(buf, compare_ops[ent], size);
+	return -1;
+}
+
+/** Complete field id for compare match item. */
+static int
+comp_set_compare_field_id(struct context *ctx, const struct token *token,
+			  unsigned int ent, char *buf, unsigned int size)
+{
+	const char *name;
+
+	RTE_SET_USED(token);
+	if (!buf)
+		return RTE_DIM(flow_field_ids);
+	if (ent >= RTE_DIM(flow_field_ids) - 1)
+		return -1;
+	name = flow_field_ids[ent];
+	if (ctx->curr == ITEM_COMPARE_FIELD_B_TYPE ||
+	    (strcmp(name, "pointer") && strcmp(name, "value")))
+		return strlcpy(buf, name, size);
+	return -1;
+}
+
 /** Complete type field for RSS action. */
 static int
 comp_vc_action_rss_type(struct context *ctx, const struct token *token,
diff --git a/doc/guides/nics/features/default.ini b/doc/guides/nics/features/default.ini
index 5115963136..1ded1d5de1 100644
--- a/doc/guides/nics/features/default.ini
+++ b/doc/guides/nics/features/default.ini
@@ -88,6 +88,7 @@ aggr_affinity        =
 ah                   =
 any                  =
 arp_eth_ipv4         =
+compare              =
 conntrack            =
 ecpri                =
 esp                  =
diff --git a/doc/guides/prog_guide/rte_flow.rst b/doc/guides/prog_guide/rte_flow.rst
index f936a9ba19..dc038e2c39 100644
--- a/doc/guides/prog_guide/rte_flow.rst
+++ b/doc/guides/prog_guide/rte_flow.rst
@@ -1587,6 +1587,13 @@ the packet.
 
 - ``value``: Specific value to match.
 
+Item: ``COMPARE``
+^^^^^^^^^^^^^^^^^
+
+Matches the comparison result between packet fields or value.
+
+- ``compare``: Comparison information.
+
 Actions
 ~~~~~~~
 
diff --git a/doc/guides/rel_notes/release_24_03.rst b/doc/guides/rel_notes/release_24_03.rst
index efeda6ea97..ffceab59e4 100644
--- a/doc/guides/rel_notes/release_24_03.rst
+++ b/doc/guides/rel_notes/release_24_03.rst
@@ -70,6 +70,11 @@ New Features
   * Added a fath path function ``rte_eth_tx_queue_count`` to get the number of used
     descriptors of a Tx queue.
 
+* **Added compare flow matching criteria.**
+
+  Added ``RTE_FLOW_ITEM_TYPE_COMPARE`` to allow matching on compare
+  result between the packet fields or value.
+
 * **Updated Atomic Rules' Arkville PMD.**
 
   * Added support for Atomic Rules' TK242 packet-capture family of devices
diff --git a/doc/guides/testpmd_app_ug/testpmd_funcs.rst b/doc/guides/testpmd_app_ug/testpmd_funcs.rst
index ab18a80b30..c79d8929f5 100644
--- a/doc/guides/testpmd_app_ug/testpmd_funcs.rst
+++ b/doc/guides/testpmd_app_ug/testpmd_funcs.rst
@@ -3856,6 +3856,13 @@ This section lists supported pattern items and their attributes, if any.
 
         - ``packet_type {unsigned}``: packet type.
 
+- ``compare``: match the comparison result between packet fields or value.
+
+        - ``op {string}``: comparison operation type.
+        - ``a_type {string}``: compared field.
+        - ``b_type {string}``: comparator field.
+        - ``width {unsigned}``: comparison width.
+
 
 Actions list
 ^^^^^^^^^^^^
@@ -5320,6 +5327,23 @@ 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 match with comparison rule
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+Match with comparsion rule can be created as following using ``compare``.
+
+::
+
+    testpmd> flow pattern_template 0 create ingress pattern_template_id 1 template compare op mask le
+             a_type mask tag a_tag_index mask 1 b_type mask tag b_tag_index mask 2 width mask 0xffffffff / end
+    testpmd> flow actions_template 0 create ingress actions_template_id 1 template count / drop / end
+             mask count / drop  / end
+    testpmd> flow template_table 0 create table_id 1 group 2 priority 1  ingress rules_number 1
+             pattern_template 1 actions_template 1
+    testpmd> flow queue 0 create 0 template_table 1 pattern_template 0 actions_template 0 postpone no
+             pattern compare op is le a_type is tag a_tag_index is 1 b_type is tag b_tag_index is 2 width is 32 / end
+	     actions count / drop / end
+
 BPF Functions
 --------------
 
diff --git a/lib/ethdev/rte_flow.c b/lib/ethdev/rte_flow.c
index 3f58d792f9..5f63529f9f 100644
--- a/lib/ethdev/rte_flow.c
+++ b/lib/ethdev/rte_flow.c
@@ -170,6 +170,7 @@ static const struct rte_flow_desc_data rte_flow_desc_item[] = {
 	MK_FLOW_ITEM(TX_QUEUE, sizeof(struct rte_flow_item_tx_queue)),
 	MK_FLOW_ITEM(IB_BTH, sizeof(struct rte_flow_item_ib_bth)),
 	MK_FLOW_ITEM(PTYPE, sizeof(struct rte_flow_item_ptype)),
+	MK_FLOW_ITEM(COMPARE, sizeof(struct rte_flow_item_compare)),
 };
 
 /** Generate flow_action[] entry. */
diff --git a/lib/ethdev/rte_flow.h b/lib/ethdev/rte_flow.h
index a143ecb194..d906288f2c 100644
--- a/lib/ethdev/rte_flow.h
+++ b/lib/ethdev/rte_flow.h
@@ -714,6 +714,13 @@ enum rte_flow_item_type {
 	 * @see struct rte_flow_item_random.
 	 */
 	RTE_FLOW_ITEM_TYPE_RANDOM,
+
+	/**
+	 * Matches the packet with compare result.
+	 *
+	 * See struct rte_flow_item_compare.
+	 */
+	RTE_FLOW_ITEM_TYPE_COMPARE,
 };
 
 /**
@@ -2365,6 +2372,182 @@ static const struct rte_flow_item_ptype rte_flow_item_ptype_mask = {
 };
 #endif
 
+/**
+ * Field IDs for packet field.
+ * e.g. the packet field IDs used in RTE_FLOW_ACTION_TYPE_MODIFY_FIELD
+ * and RTE_FLOW_ITEM_TYPE_COMPARE.
+ */
+enum rte_flow_field_id {
+	RTE_FLOW_FIELD_START = 0,	/**< Start of a packet. */
+	RTE_FLOW_FIELD_MAC_DST,		/**< Destination MAC Address. */
+	RTE_FLOW_FIELD_MAC_SRC,		/**< Source MAC Address. */
+	RTE_FLOW_FIELD_VLAN_TYPE,	/**< VLAN Tag Identifier. */
+	RTE_FLOW_FIELD_VLAN_ID,		/**< VLAN Identifier. */
+	RTE_FLOW_FIELD_MAC_TYPE,	/**< EtherType. */
+	RTE_FLOW_FIELD_IPV4_DSCP,	/**< IPv4 DSCP. */
+	RTE_FLOW_FIELD_IPV4_TTL,	/**< IPv4 Time To Live. */
+	RTE_FLOW_FIELD_IPV4_SRC,	/**< IPv4 Source Address. */
+	RTE_FLOW_FIELD_IPV4_DST,	/**< IPv4 Destination Address. */
+	RTE_FLOW_FIELD_IPV6_DSCP,	/**< IPv6 DSCP. */
+	RTE_FLOW_FIELD_IPV6_HOPLIMIT,	/**< IPv6 Hop Limit. */
+	RTE_FLOW_FIELD_IPV6_SRC,	/**< IPv6 Source Address. */
+	RTE_FLOW_FIELD_IPV6_DST,	/**< IPv6 Destination Address. */
+	RTE_FLOW_FIELD_TCP_PORT_SRC,	/**< TCP Source Port Number. */
+	RTE_FLOW_FIELD_TCP_PORT_DST,	/**< TCP Destination Port Number. */
+	RTE_FLOW_FIELD_TCP_SEQ_NUM,	/**< TCP Sequence Number. */
+	RTE_FLOW_FIELD_TCP_ACK_NUM,	/**< TCP Acknowledgment Number. */
+	RTE_FLOW_FIELD_TCP_FLAGS,	/**< TCP Flags. */
+	RTE_FLOW_FIELD_UDP_PORT_SRC,	/**< UDP Source Port Number. */
+	RTE_FLOW_FIELD_UDP_PORT_DST,	/**< UDP Destination Port Number. */
+	RTE_FLOW_FIELD_VXLAN_VNI,	/**< VXLAN Network Identifier. */
+	RTE_FLOW_FIELD_GENEVE_VNI,	/**< GENEVE Network Identifier. */
+	RTE_FLOW_FIELD_GTP_TEID,	/**< GTP Tunnel Endpoint Identifier. */
+	RTE_FLOW_FIELD_TAG,		/**< Tag value. */
+	RTE_FLOW_FIELD_MARK,		/**< Mark value. */
+	RTE_FLOW_FIELD_META,		/**< Metadata value. */
+	RTE_FLOW_FIELD_POINTER,		/**< Memory pointer. */
+	RTE_FLOW_FIELD_VALUE,		/**< Immediate value. */
+	RTE_FLOW_FIELD_IPV4_ECN,	/**< IPv4 ECN. */
+	RTE_FLOW_FIELD_IPV6_ECN,	/**< IPv6 ECN. */
+	RTE_FLOW_FIELD_GTP_PSC_QFI,	/**< GTP QFI. */
+	RTE_FLOW_FIELD_METER_COLOR,	/**< Meter color marker. */
+	RTE_FLOW_FIELD_IPV6_PROTO,	/**< IPv6 next header. */
+	RTE_FLOW_FIELD_FLEX_ITEM,	/**< Flex item. */
+	RTE_FLOW_FIELD_HASH_RESULT,	/**< Hash result. */
+	RTE_FLOW_FIELD_GENEVE_OPT_TYPE,	/**< GENEVE option type. */
+	RTE_FLOW_FIELD_GENEVE_OPT_CLASS,/**< GENEVE option class. */
+	RTE_FLOW_FIELD_GENEVE_OPT_DATA,	/**< GENEVE option data. */
+	RTE_FLOW_FIELD_MPLS,		/**< MPLS header. */
+	RTE_FLOW_FIELD_TCP_DATA_OFFSET,	/**< TCP data offset. */
+	RTE_FLOW_FIELD_IPV4_IHL,	/**< IPv4 IHL. */
+	RTE_FLOW_FIELD_IPV4_TOTAL_LEN,	/**< IPv4 total length. */
+	RTE_FLOW_FIELD_IPV6_PAYLOAD_LEN,/**< IPv6 payload length. */
+	RTE_FLOW_FIELD_RANDOM		/**< Random value. */
+};
+
+/**
+ * @warning
+ * @b EXPERIMENTAL: this structure may change without prior notice
+ *
+ * Field description for packet field.
+ * e.g. the packet fields used in RTE_FLOW_ACTION_TYPE_MODIFY_FIELD
+ * and RTE_FLOW_ITEM_TYPE_COMPARE.
+ */
+struct rte_flow_field_data {
+	enum rte_flow_field_id field; /**< Field or memory type ID. */
+	union {
+		struct {
+			/** Encapsulation level and tag index or flex item handle. */
+			union {
+				struct {
+					/**
+					 * Packet encapsulation level containing
+					 * the field to modify.
+					 *
+					 * - @p 0 requests the default behavior.
+					 *   Depending on the packet type, it
+					 *   can mean outermost, innermost or
+					 *   anything in between.
+					 *
+					 *   It basically stands for the
+					 *   innermost encapsulation level.
+					 *   Modification can be performed
+					 *   according to PMD and device
+					 *   capabilities.
+					 *
+					 * - @p 1 requests modification to be
+					 *   performed on the outermost packet
+					 *   encapsulation level.
+					 *
+					 * - @p 2 and subsequent values request
+					 *   modification to be performed on
+					 *   the specified inner packet
+					 *   encapsulation level, from
+					 *   outermost to innermost (lower to
+					 *   higher values).
+					 *
+					 * Values other than @p 0 are not
+					 * necessarily supported.
+					 *
+					 * @note that for MPLS field,
+					 * encapsulation level also include
+					 * tunnel since MPLS may appear in
+					 * outer, inner or tunnel.
+					 */
+					uint8_t level;
+					union {
+						/**
+						 * Tag index array inside
+						 * encapsulation level.
+						 * Used for VLAN, MPLS or TAG types.
+						 */
+						uint8_t tag_index;
+						/**
+						 * Geneve option identifier.
+						 * Relevant only for
+						 * RTE_FLOW_FIELD_GENEVE_OPT_XXXX
+						 * modification type.
+						 */
+						struct {
+							/**
+							 * Geneve option type.
+							 */
+							uint8_t type;
+							/**
+							 * Geneve option class.
+							 */
+							rte_be16_t class_id;
+						};
+					};
+				};
+				struct rte_flow_item_flex_handle *flex_handle;
+			};
+			/** Number of bits to skip from a field. */
+			uint32_t offset;
+		};
+		/**
+		 * Immediate value for RTE_FLOW_FIELD_VALUE, presented in the
+		 * same byte order and length as in relevant rte_flow_item_xxx.
+		 * The immediate source bitfield offset is inherited from
+		 * the destination's one.
+		 */
+		uint8_t value[16];
+		/**
+		 * Memory address for RTE_FLOW_FIELD_POINTER, memory layout
+		 * should be the same as for relevant field in the
+		 * rte_flow_item_xxx structure.
+		 */
+		void *pvalue;
+	};
+};
+
+/**
+ * Expected operation types for compare item.
+ */
+enum rte_flow_item_compare_op {
+	RTE_FLOW_ITEM_COMPARE_EQ,	/* Compare result equal. */
+	RTE_FLOW_ITEM_COMPARE_NE,	/* Compare result not equal. */
+	RTE_FLOW_ITEM_COMPARE_LT,	/* Compare result less than. */
+	RTE_FLOW_ITEM_COMPARE_LE,	/* Compare result less than or equal. */
+	RTE_FLOW_ITEM_COMPARE_GT,	/* Compare result great than. */
+	RTE_FLOW_ITEM_COMPARE_GE,	/* Compare result great than or equal. */
+};
+
+/**
+ *
+ * RTE_FLOW_ITEM_TYPE_COMPARE
+ *
+ * Matches the packet with compare result.
+ *
+ * The operation means a compare with b result.
+ */
+struct rte_flow_item_compare {
+	enum rte_flow_item_compare_op operation; /* The compare operation. */
+	struct rte_flow_field_data a;		 /* Field be compared.  */
+	struct rte_flow_field_data b;		 /* Field as comparator. */
+	uint32_t width;				 /* Compare width. */
+};
+
 /**
  * Action types.
  *
@@ -3885,155 +4068,6 @@ struct rte_flow_action_ethdev {
 	uint16_t port_id; /**< ethdev port ID */
 };
 
-/**
- * Field IDs for MODIFY_FIELD action.
- * e.g. the packet field IDs used in RTE_FLOW_ACTION_TYPE_MODIFY_FIELD
- * and RTE_FLOW_ITEM_TYPE_COMPARE.
- */
-enum rte_flow_field_id {
-	RTE_FLOW_FIELD_START = 0,	/**< Start of a packet. */
-	RTE_FLOW_FIELD_MAC_DST,		/**< Destination MAC Address. */
-	RTE_FLOW_FIELD_MAC_SRC,		/**< Source MAC Address. */
-	RTE_FLOW_FIELD_VLAN_TYPE,	/**< VLAN Tag Identifier. */
-	RTE_FLOW_FIELD_VLAN_ID,		/**< VLAN Identifier. */
-	RTE_FLOW_FIELD_MAC_TYPE,	/**< EtherType. */
-	RTE_FLOW_FIELD_IPV4_DSCP,	/**< IPv4 DSCP. */
-	RTE_FLOW_FIELD_IPV4_TTL,	/**< IPv4 Time To Live. */
-	RTE_FLOW_FIELD_IPV4_SRC,	/**< IPv4 Source Address. */
-	RTE_FLOW_FIELD_IPV4_DST,	/**< IPv4 Destination Address. */
-	RTE_FLOW_FIELD_IPV6_DSCP,	/**< IPv6 DSCP. */
-	RTE_FLOW_FIELD_IPV6_HOPLIMIT,	/**< IPv6 Hop Limit. */
-	RTE_FLOW_FIELD_IPV6_SRC,	/**< IPv6 Source Address. */
-	RTE_FLOW_FIELD_IPV6_DST,	/**< IPv6 Destination Address. */
-	RTE_FLOW_FIELD_TCP_PORT_SRC,	/**< TCP Source Port Number. */
-	RTE_FLOW_FIELD_TCP_PORT_DST,	/**< TCP Destination Port Number. */
-	RTE_FLOW_FIELD_TCP_SEQ_NUM,	/**< TCP Sequence Number. */
-	RTE_FLOW_FIELD_TCP_ACK_NUM,	/**< TCP Acknowledgment Number. */
-	RTE_FLOW_FIELD_TCP_FLAGS,	/**< TCP Flags. */
-	RTE_FLOW_FIELD_UDP_PORT_SRC,	/**< UDP Source Port Number. */
-	RTE_FLOW_FIELD_UDP_PORT_DST,	/**< UDP Destination Port Number. */
-	RTE_FLOW_FIELD_VXLAN_VNI,	/**< VXLAN Network Identifier. */
-	RTE_FLOW_FIELD_GENEVE_VNI,	/**< GENEVE Network Identifier. */
-	RTE_FLOW_FIELD_GTP_TEID,	/**< GTP Tunnel Endpoint Identifier. */
-	RTE_FLOW_FIELD_TAG,		/**< Tag value. */
-	RTE_FLOW_FIELD_MARK,		/**< Mark value. */
-	RTE_FLOW_FIELD_META,		/**< Metadata value. */
-	RTE_FLOW_FIELD_POINTER,		/**< Memory pointer. */
-	RTE_FLOW_FIELD_VALUE,		/**< Immediate value. */
-	RTE_FLOW_FIELD_IPV4_ECN,	/**< IPv4 ECN. */
-	RTE_FLOW_FIELD_IPV6_ECN,	/**< IPv6 ECN. */
-	RTE_FLOW_FIELD_GTP_PSC_QFI,	/**< GTP QFI. */
-	RTE_FLOW_FIELD_METER_COLOR,	/**< Meter color marker. */
-	RTE_FLOW_FIELD_IPV6_PROTO,	/**< IPv6 next header. */
-	RTE_FLOW_FIELD_FLEX_ITEM,	/**< Flex item. */
-	RTE_FLOW_FIELD_HASH_RESULT,	/**< Hash result. */
-	RTE_FLOW_FIELD_GENEVE_OPT_TYPE,	/**< GENEVE option type. */
-	RTE_FLOW_FIELD_GENEVE_OPT_CLASS,/**< GENEVE option class. */
-	RTE_FLOW_FIELD_GENEVE_OPT_DATA,	/**< GENEVE option data. */
-	RTE_FLOW_FIELD_MPLS,		/**< MPLS header. */
-	RTE_FLOW_FIELD_TCP_DATA_OFFSET,	/**< TCP data offset. */
-	RTE_FLOW_FIELD_IPV4_IHL,	/**< IPv4 IHL. */
-	RTE_FLOW_FIELD_IPV4_TOTAL_LEN,	/**< IPv4 total length. */
-	RTE_FLOW_FIELD_IPV6_PAYLOAD_LEN,/**< IPv6 payload length. */
-	RTE_FLOW_FIELD_RANDOM		/**< Random value. */
-};
-
-/**
- * @warning
- * @b EXPERIMENTAL: this structure may change without prior notice
- *
- * Field description for packet field.
- * e.g. the packet fields used in RTE_FLOW_ACTION_TYPE_MODIFY_FIELD
- * and RTE_FLOW_ITEM_TYPE_COMPARE.
- */
-struct rte_flow_field_data {
-	enum rte_flow_field_id field; /**< Field or memory type ID. */
-	union {
-		struct {
-			/** Encapsulation level and tag index or flex item handle. */
-			union {
-				struct {
-					/**
-					 * Packet encapsulation level containing
-					 * the field to modify.
-					 *
-					 * - @p 0 requests the default behavior.
-					 *   Depending on the packet type, it
-					 *   can mean outermost, innermost or
-					 *   anything in between.
-					 *
-					 *   It basically stands for the
-					 *   innermost encapsulation level.
-					 *   Modification can be performed
-					 *   according to PMD and device
-					 *   capabilities.
-					 *
-					 * - @p 1 requests modification to be
-					 *   performed on the outermost packet
-					 *   encapsulation level.
-					 *
-					 * - @p 2 and subsequent values request
-					 *   modification to be performed on
-					 *   the specified inner packet
-					 *   encapsulation level, from
-					 *   outermost to innermost (lower to
-					 *   higher values).
-					 *
-					 * Values other than @p 0 are not
-					 * necessarily supported.
-					 *
-					 * @note that for MPLS field,
-					 * encapsulation level also include
-					 * tunnel since MPLS may appear in
-					 * outer, inner or tunnel.
-					 */
-					uint8_t level;
-					union {
-						/**
-						 * Tag index array inside
-						 * encapsulation level.
-						 * Used for VLAN, MPLS or TAG types.
-						 */
-						uint8_t tag_index;
-						/**
-						 * Geneve option identifier.
-						 * Relevant only for
-						 * RTE_FLOW_FIELD_GENEVE_OPT_XXXX
-						 * modification type.
-						 */
-						struct {
-							/**
-							 * Geneve option type.
-							 */
-							uint8_t type;
-							/**
-							 * Geneve option class.
-							 */
-							rte_be16_t class_id;
-						};
-					};
-				};
-				struct rte_flow_item_flex_handle *flex_handle;
-			};
-			/** Number of bits to skip from a field. */
-			uint32_t offset;
-		};
-		/**
-		 * Immediate value for RTE_FLOW_FIELD_VALUE, presented in the
-		 * same byte order and length as in relevant rte_flow_item_xxx.
-		 * The immediate source bitfield offset is inherited from
-		 * the destination's one.
-		 */
-		uint8_t value[16];
-		/**
-		 * Memory address for RTE_FLOW_FIELD_POINTER, memory layout
-		 * should be the same as for relevant field in the
-		 * rte_flow_item_xxx structure.
-		 */
-		void *pvalue;
-	};
-};
-
 /**
  * Operation types for MODIFY_FIELD action.
  */
-- 
2.34.1


^ permalink raw reply	[flat|nested] 66+ messages in thread

* [PATCH v5 3/3] net/mlx5: add compare item support
  2024-02-01 12:29 ` [PATCH v5 0/3] ethdev: add RTE_FLOW_ITEM_TYPE_COMPARE Suanming Mou
  2024-02-01 12:29   ` [PATCH v5 1/3] ethdev: rename action modify field data structure Suanming Mou
  2024-02-01 12:29   ` [PATCH v5 2/3] ethdev: add compare item Suanming Mou
@ 2024-02-01 12:29   ` Suanming Mou
  2024-02-01 18:57     ` Ferruh Yigit
  2024-02-01 18:56   ` [PATCH v5 0/3] ethdev: add RTE_FLOW_ITEM_TYPE_COMPARE Ferruh Yigit
  3 siblings, 1 reply; 66+ messages in thread
From: Suanming Mou @ 2024-02-01 12:29 UTC (permalink / raw)
  To: ferruh.yigit, Dariusz Sosnowski, Viacheslav Ovsiienko, Ori Kam,
	Matan Azrad
  Cc: dev

The compare item allows adding flow match with comparison
result. This commit adds compare item support to the PMD
code.

Due to HW limitation:
 - Only HWS supported.
 - Only 32-bit comparison is supported.
 - Only single compare flow is supported in the flow table.
 - Only match with compare result between packet fields is
    supported.

Signed-off-by: Suanming Mou <suanmingm@nvidia.com>
Acked-by: Ori Kam <orika@nvidia.com>
---
 doc/guides/nics/features/mlx5.ini      |  1 +
 doc/guides/nics/mlx5.rst               |  7 +++
 doc/guides/rel_notes/release_24_03.rst |  2 +
 drivers/net/mlx5/mlx5_flow.h           |  3 ++
 drivers/net/mlx5/mlx5_flow_hw.c        | 73 ++++++++++++++++++++++++++
 5 files changed, 86 insertions(+)

diff --git a/doc/guides/nics/features/mlx5.ini b/doc/guides/nics/features/mlx5.ini
index 0739fe9d63..00e9348fc6 100644
--- a/doc/guides/nics/features/mlx5.ini
+++ b/doc/guides/nics/features/mlx5.ini
@@ -56,6 +56,7 @@ Usage doc            = Y
 
 [rte_flow items]
 aggr_affinity        = Y
+compare              = Y
 conntrack            = Y
 ecpri                = Y
 esp                  = Y
diff --git a/doc/guides/nics/mlx5.rst b/doc/guides/nics/mlx5.rst
index 6b52fb93c5..18b40bc22d 100644
--- a/doc/guides/nics/mlx5.rst
+++ b/doc/guides/nics/mlx5.rst
@@ -778,6 +778,13 @@ Limitations
   The flow engine of a process cannot move from active to standby mode
   if preceding active application rules are still present and vice versa.
 
+- Match with compare result item (``RTE_FLOW_ITEM_TYPE_COMPARE``):
+
+  - Only supported in HW steering(``dv_flow_en`` = 2) mode.
+  - Only single flow is supported to the flow table.
+  - Only 32-bit comparison is supported.
+  - Only match with compare result between packet fields is supported.
+
 
 Statistics
 ----------
diff --git a/doc/guides/rel_notes/release_24_03.rst b/doc/guides/rel_notes/release_24_03.rst
index ffceab59e4..91b2cafb00 100644
--- a/doc/guides/rel_notes/release_24_03.rst
+++ b/doc/guides/rel_notes/release_24_03.rst
@@ -80,6 +80,8 @@ New Features
   * Added support for Atomic Rules' TK242 packet-capture family of devices
     with PCI IDs: ``0x1024, 0x1025, 0x1026``.
 
+  * Added support for comparing result between packet fields or value.
+
 
 Removed Items
 -------------
diff --git a/drivers/net/mlx5/mlx5_flow.h b/drivers/net/mlx5/mlx5_flow.h
index ecfb04ead2..f0a11949e6 100644
--- a/drivers/net/mlx5/mlx5_flow.h
+++ b/drivers/net/mlx5/mlx5_flow.h
@@ -277,6 +277,9 @@ enum mlx5_feature_name {
 /* NSH ITEM */
 #define MLX5_FLOW_ITEM_NSH (1ull << 53)
 
+/* COMPARE ITEM */
+#define MLX5_FLOW_ITEM_COMPARE (1ull << 54)
+
 /* Outer Masks. */
 #define MLX5_FLOW_LAYER_OUTER_L3 \
 	(MLX5_FLOW_LAYER_OUTER_L3_IPV4 | MLX5_FLOW_LAYER_OUTER_L3_IPV6)
diff --git a/drivers/net/mlx5/mlx5_flow_hw.c b/drivers/net/mlx5/mlx5_flow_hw.c
index da873ae2e2..f21c22131c 100644
--- a/drivers/net/mlx5/mlx5_flow_hw.c
+++ b/drivers/net/mlx5/mlx5_flow_hw.c
@@ -426,6 +426,9 @@ flow_hw_matching_item_flags_get(const struct rte_flow_item items[])
 		case RTE_FLOW_ITEM_TYPE_GTP:
 			last_item = MLX5_FLOW_LAYER_GTP;
 			break;
+		case RTE_FLOW_ITEM_TYPE_COMPARE:
+			last_item = MLX5_FLOW_ITEM_COMPARE;
+			break;
 		default:
 			break;
 		}
@@ -4386,6 +4389,8 @@ flow_hw_table_create(struct rte_eth_dev *dev,
 			rte_errno = EINVAL;
 			goto it_error;
 		}
+		if (item_templates[i]->item_flags & MLX5_FLOW_ITEM_COMPARE)
+			matcher_attr.mode = MLX5DR_MATCHER_RESOURCE_MODE_HTABLE;
 		ret = __atomic_fetch_add(&item_templates[i]->refcnt, 1,
 					 __ATOMIC_RELAXED) + 1;
 		if (ret <= 1) {
@@ -6634,6 +6639,66 @@ flow_hw_prepend_item(const struct rte_flow_item *items,
 	return copied_items;
 }
 
+static inline bool
+flow_hw_item_compare_field_supported(enum rte_flow_field_id field)
+{
+	switch (field) {
+	case RTE_FLOW_FIELD_TAG:
+	case RTE_FLOW_FIELD_META:
+	case RTE_FLOW_FIELD_VALUE:
+		return true;
+	default:
+		break;
+	}
+	return false;
+}
+
+static int
+flow_hw_validate_item_compare(const struct rte_flow_item *item,
+			      struct rte_flow_error *error)
+{
+	const struct rte_flow_item_compare *comp_m = item->mask;
+	const struct rte_flow_item_compare *comp_v = item->spec;
+
+	if (unlikely(!comp_m))
+		return rte_flow_error_set(error, EINVAL,
+				   RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
+				   NULL,
+				   "compare item mask is missing");
+	if (comp_m->width != UINT32_MAX)
+		return rte_flow_error_set(error, EINVAL,
+				   RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
+				   NULL,
+				   "compare item only support full mask");
+	if (!flow_hw_item_compare_field_supported(comp_m->a.field) ||
+	    !flow_hw_item_compare_field_supported(comp_m->b.field))
+		return rte_flow_error_set(error, ENOTSUP,
+				   RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
+				   NULL,
+				   "compare item field not support");
+	if (comp_m->a.field == RTE_FLOW_FIELD_VALUE &&
+	    comp_m->b.field == RTE_FLOW_FIELD_VALUE)
+		return rte_flow_error_set(error, EINVAL,
+				   RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
+				   NULL,
+				   "compare between value is not valid");
+	if (comp_v) {
+		if (comp_v->operation != comp_m->operation ||
+		    comp_v->a.field != comp_m->a.field ||
+		    comp_v->b.field != comp_m->b.field)
+			return rte_flow_error_set(error, EINVAL,
+					   RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
+					   NULL,
+					   "compare item spec/mask not matching");
+		if ((comp_v->width & comp_m->width) != 32)
+			return rte_flow_error_set(error, EINVAL,
+					   RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
+					   NULL,
+					   "compare item only support full mask");
+	}
+	return 0;
+}
+
 static int
 flow_hw_pattern_validate(struct rte_eth_dev *dev,
 			 const struct rte_flow_pattern_template_attr *attr,
@@ -6644,6 +6709,7 @@ flow_hw_pattern_validate(struct rte_eth_dev *dev,
 	int i, tag_idx;
 	bool items_end = false;
 	uint32_t tag_bitmap = 0;
+	int ret;
 
 	if (!attr->ingress && !attr->egress && !attr->transfer)
 		return rte_flow_error_set(error, EINVAL, RTE_FLOW_ERROR_TYPE_ATTR, NULL,
@@ -6781,6 +6847,13 @@ flow_hw_pattern_validate(struct rte_eth_dev *dev,
 							  " attribute");
 			break;
 		}
+		case RTE_FLOW_ITEM_TYPE_COMPARE:
+		{
+			ret = flow_hw_validate_item_compare(&items[i], error);
+			if (ret)
+				return ret;
+			break;
+		}
 		case RTE_FLOW_ITEM_TYPE_VOID:
 		case RTE_FLOW_ITEM_TYPE_ETH:
 		case RTE_FLOW_ITEM_TYPE_VLAN:
-- 
2.34.1


^ permalink raw reply	[flat|nested] 66+ messages in thread

* Re: [PATCH v5 0/3] ethdev: add RTE_FLOW_ITEM_TYPE_COMPARE
  2024-02-01 12:29 ` [PATCH v5 0/3] ethdev: add RTE_FLOW_ITEM_TYPE_COMPARE Suanming Mou
                     ` (2 preceding siblings ...)
  2024-02-01 12:29   ` [PATCH v5 3/3] net/mlx5: add compare item support Suanming Mou
@ 2024-02-01 18:56   ` Ferruh Yigit
  2024-02-02  0:32     ` Suanming Mou
  3 siblings, 1 reply; 66+ messages in thread
From: Ferruh Yigit @ 2024-02-01 18:56 UTC (permalink / raw)
  To: Suanming Mou; +Cc: dev, orika

On 2/1/2024 12:29 PM, Suanming Mou wrote:
> The new item type is added for the case user wants to match traffic
> based on packet field compare result with other fields or immediate
> value.
> 
> e.g. take advantage the compare item user will be able to accumulate
> a IPv4/TCP packet's TCP data_offset and IPv4 IHL field to a tag
> register, then compare the tag register with IPv4 header total length
> to understand the packet has payload or not.
> 
> The supported operations can be as below:
>  - RTE_FLOW_ITEM_COMPARE_EQ (equal)
>  - RTE_FLOW_ITEM_COMPARE_NE (not equal)
>  - RTE_FLOW_ITEM_COMPARE_LT (less than)
>  - RTE_FLOW_ITEM_COMPARE_LE (less than or equal)
>  - RTE_FLOW_ITEM_COMPARE_GT (great than)
>  - RTE_FLOW_ITEM_COMPARE_GE (great than or equal)
> 
> V5:
>  - rebase on top of next-net
>  - add sample detail for rte_flow_field.
> 
> V4:
>  - rebase on top of the latest version.
>  - move ACTION_MODIFY_PATTERN_SIZE and modify_field_ids rename
>    to first patch.
>  - add comparison flow create sample in testpmd_funcs.rst.
> 
> V3:
>  - fix code style missing empty line in rte_flow.rst.
>  - fix missing the ABI change release notes.
> 
> V2:
>  - Since modify field data struct is experiment, rename modify
>    field data directly instead of adding new flow field struct.
> 
> 
> Suanming Mou (3):
>   ethdev: rename action modify field data structure
>   ethdev: add compare item
>   net/mlx5: add compare item support
> 

Mostly looks good, please find comments on a few minor issues on patches.


^ permalink raw reply	[flat|nested] 66+ messages in thread

* Re: [PATCH v5 1/3] ethdev: rename action modify field data structure
  2024-02-01 12:29   ` [PATCH v5 1/3] ethdev: rename action modify field data structure Suanming Mou
@ 2024-02-01 18:57     ` Ferruh Yigit
  0 siblings, 0 replies; 66+ messages in thread
From: Ferruh Yigit @ 2024-02-01 18:57 UTC (permalink / raw)
  To: Suanming Mou, Ori Kam, Aman Singh, Yuying Zhang,
	Dariusz Sosnowski, Viacheslav Ovsiienko, Matan Azrad,
	Thomas Monjalon, Andrew Rybchenko
  Cc: dev

On 2/1/2024 12:29 PM, Suanming Mou wrote:
> Current rte_flow_action_modify_data struct describes the pkt
> field perfectly and is used only in action.
> 
> It is planned to be used for item as well. This commit renames
> it to "rte_flow_field_data" making it compatible to be used by item.
> 
> Signed-off-by: Suanming Mou <suanmingm@nvidia.com>
> Acked-by: Ori Kam <orika@nvidia.com>
> Acked-by: Andrew Rybchenko <andrew.rybchenko@oktetlabs.ru>

<...>

> diff --git a/doc/guides/rel_notes/release_24_03.rst b/doc/guides/rel_notes/release_24_03.rst
> index 84d3144215..efeda6ea97 100644
> --- a/doc/guides/rel_notes/release_24_03.rst
> +++ b/doc/guides/rel_notes/release_24_03.rst
> @@ -124,6 +124,7 @@ ABI Changes
>  
>  * No ABI change that would break compatibility with 23.11.
>  
> +* ethdev: Rename the experimental ``struct rte_flow_action_modify_data`` to be ``struct rte_flow_field_data``
>  

Please put one more empty line after your change, to have two empty
lines before next section.

<...>

> diff --git a/lib/ethdev/rte_flow.h b/lib/ethdev/rte_flow.h
> index 1267c146e5..a143ecb194 100644
> --- a/lib/ethdev/rte_flow.h
> +++ b/lib/ethdev/rte_flow.h
> @@ -3887,6 +3887,8 @@ struct rte_flow_action_ethdev {
>  
>  /**
>   * Field IDs for MODIFY_FIELD action.
> + * e.g. the packet field IDs used in RTE_FLOW_ACTION_TYPE_MODIFY_FIELD
> + * and RTE_FLOW_ITEM_TYPE_COMPARE.
>

In this patch there is no RTE_FLOW_ITEM_TYPE_COMPARE yet, can you please
update to have RTE_FLOW_ACTION_TYPE_MODIFY_FIELD in this patch and add
RTE_FLOW_ITEM_TYPE_COMPARE in next patch?


>   */
>  enum rte_flow_field_id {
>  	RTE_FLOW_FIELD_START = 0,	/**< Start of a packet. */
> @@ -3940,9 +3942,11 @@ enum rte_flow_field_id {
>   * @warning
>   * @b EXPERIMENTAL: this structure may change without prior notice
>   *
> - * Field description for MODIFY_FIELD action.
> + * Field description for packet field.
> + * e.g. the packet fields used in RTE_FLOW_ACTION_TYPE_MODIFY_FIELD
> + * and RTE_FLOW_ITEM_TYPE_COMPARE.
>

Same here, can you please mention from RTE_FLOW_ITEM_TYPE_COMPARE in
next patch.


^ permalink raw reply	[flat|nested] 66+ messages in thread

* Re: [PATCH v5 2/3] ethdev: add compare item
  2024-02-01 12:29   ` [PATCH v5 2/3] ethdev: add compare item Suanming Mou
@ 2024-02-01 18:57     ` Ferruh Yigit
  0 siblings, 0 replies; 66+ messages in thread
From: Ferruh Yigit @ 2024-02-01 18:57 UTC (permalink / raw)
  To: Suanming Mou, Ori Kam, Aman Singh, Yuying Zhang, Thomas Monjalon,
	Andrew Rybchenko
  Cc: dev

On 2/1/2024 12:29 PM, Suanming Mou wrote:
>  Actions list
>  ^^^^^^^^^^^^
> @@ -5320,6 +5327,23 @@ 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 match with comparison rule
> +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
> +
> +Match with comparsion rule can be created as following using ``compare``.
> +

s/comparsion/comparison/

^ permalink raw reply	[flat|nested] 66+ messages in thread

* Re: [PATCH v5 3/3] net/mlx5: add compare item support
  2024-02-01 12:29   ` [PATCH v5 3/3] net/mlx5: add compare item support Suanming Mou
@ 2024-02-01 18:57     ` Ferruh Yigit
  0 siblings, 0 replies; 66+ messages in thread
From: Ferruh Yigit @ 2024-02-01 18:57 UTC (permalink / raw)
  To: Suanming Mou, Dariusz Sosnowski, Viacheslav Ovsiienko, Ori Kam,
	Matan Azrad
  Cc: dev

On 2/1/2024 12:29 PM, Suanming Mou wrote:
> diff --git a/doc/guides/rel_notes/release_24_03.rst b/doc/guides/rel_notes/release_24_03.rst
> index ffceab59e4..91b2cafb00 100644
> --- a/doc/guides/rel_notes/release_24_03.rst
> +++ b/doc/guides/rel_notes/release_24_03.rst
> @@ -80,6 +80,8 @@ New Features
>    * Added support for Atomic Rules' TK242 packet-capture family of devices
>      with PCI IDs: ``0x1024, 0x1025, 0x1026``.
>  
> +  * Added support for comparing result between packet fields or value.
> +
>  

Above update is under 'Atomic Rule' block, I guess something went wrong
during git rebase, can you please check?

^ permalink raw reply	[flat|nested] 66+ messages in thread

* RE: [PATCH v5 0/3] ethdev: add RTE_FLOW_ITEM_TYPE_COMPARE
  2024-02-01 18:56   ` [PATCH v5 0/3] ethdev: add RTE_FLOW_ITEM_TYPE_COMPARE Ferruh Yigit
@ 2024-02-02  0:32     ` Suanming Mou
  0 siblings, 0 replies; 66+ messages in thread
From: Suanming Mou @ 2024-02-02  0:32 UTC (permalink / raw)
  To: Ferruh Yigit; +Cc: dev, Ori Kam



> -----Original Message-----
> From: Ferruh Yigit <ferruh.yigit@amd.com>
> Sent: Friday, February 2, 2024 2:56 AM
> To: Suanming Mou <suanmingm@nvidia.com>
> Cc: dev@dpdk.org; Ori Kam <orika@nvidia.com>
> Subject: Re: [PATCH v5 0/3] ethdev: add RTE_FLOW_ITEM_TYPE_COMPARE
> 
> On 2/1/2024 12:29 PM, Suanming Mou wrote:
> > The new item type is added for the case user wants to match traffic
> > based on packet field compare result with other fields or immediate
> > value.
> >
> > e.g. take advantage the compare item user will be able to accumulate a
> > IPv4/TCP packet's TCP data_offset and IPv4 IHL field to a tag
> > register, then compare the tag register with IPv4 header total length
> > to understand the packet has payload or not.
> >
> > The supported operations can be as below:
> >  - RTE_FLOW_ITEM_COMPARE_EQ (equal)
> >  - RTE_FLOW_ITEM_COMPARE_NE (not equal)
> >  - RTE_FLOW_ITEM_COMPARE_LT (less than)
> >  - RTE_FLOW_ITEM_COMPARE_LE (less than or equal)
> >  - RTE_FLOW_ITEM_COMPARE_GT (great than)
> >  - RTE_FLOW_ITEM_COMPARE_GE (great than or equal)
> >
> > V5:
> >  - rebase on top of next-net
> >  - add sample detail for rte_flow_field.
> >
> > V4:
> >  - rebase on top of the latest version.
> >  - move ACTION_MODIFY_PATTERN_SIZE and modify_field_ids rename
> >    to first patch.
> >  - add comparison flow create sample in testpmd_funcs.rst.
> >
> > V3:
> >  - fix code style missing empty line in rte_flow.rst.
> >  - fix missing the ABI change release notes.
> >
> > V2:
> >  - Since modify field data struct is experiment, rename modify
> >    field data directly instead of adding new flow field struct.
> >
> >
> > Suanming Mou (3):
> >   ethdev: rename action modify field data structure
> >   ethdev: add compare item
> >   net/mlx5: add compare item support
> >
> 
> Mostly looks good, please find comments on a few minor issues on patches.

Sure, thanks.


^ permalink raw reply	[flat|nested] 66+ messages in thread

* [PATCH v6 0/3] ethdev: add RTE_FLOW_ITEM_TYPE_COMPARE
  2023-12-14  3:12 [PATCH 0/2] ethdev: add RTE_FLOW_ITEM_TYPE_COMPARE Suanming Mou
                   ` (4 preceding siblings ...)
  2024-02-01 12:29 ` [PATCH v5 0/3] ethdev: add RTE_FLOW_ITEM_TYPE_COMPARE Suanming Mou
@ 2024-02-02  0:42 ` Suanming Mou
  2024-02-02  0:42   ` [PATCH v6 1/3] ethdev: rename action modify field data structure Suanming Mou
                     ` (2 more replies)
  2024-02-06  2:06 ` [PATCH v7 0/4] ethdev: add RTE_FLOW_ITEM_TYPE_COMPARE Suanming Mou
  6 siblings, 3 replies; 66+ messages in thread
From: Suanming Mou @ 2024-02-02  0:42 UTC (permalink / raw)
  To: ferruh.yigit; +Cc: dev, orika

The new item type is added for the case user wants to match traffic
based on packet field compare result with other fields or immediate
value.

e.g. take advantage the compare item user will be able to accumulate
a IPv4/TCP packet's TCP data_offset and IPv4 IHL field to a tag
register, then compare the tag register with IPv4 header total length
to understand the packet has payload or not.

The supported operations can be as below:
 - RTE_FLOW_ITEM_COMPARE_EQ (equal)
 - RTE_FLOW_ITEM_COMPARE_NE (not equal)
 - RTE_FLOW_ITEM_COMPARE_LT (less than)
 - RTE_FLOW_ITEM_COMPARE_LE (less than or equal)
 - RTE_FLOW_ITEM_COMPARE_GT (great than)
 - RTE_FLOW_ITEM_COMPARE_GE (great than or equal)

V6:
 - fix typo and style issue.
 - adjust flow_field description.

V5:
 - rebase on top of next-net
 - add sample detail for rte_flow_field.

V4:
 - rebase on top of the latest version.
 - move ACTION_MODIFY_PATTERN_SIZE and modify_field_ids rename
   to first patch.
 - add comparison flow create sample in testpmd_funcs.rst.

V3:
 - fix code style missing empty line in rte_flow.rst.
 - fix missing the ABI change release notes.

V2:
 - Since modify field data struct is experiment, rename modify
   field data directly instead of adding new flow field struct.


Suanming Mou (3):
  ethdev: rename action modify field data structure
  ethdev: add compare item
  net/mlx5: add compare item support

 app/test-pmd/cmdline_flow.c                 | 416 +++++++++++++++++++-
 doc/guides/nics/features/default.ini        |   1 +
 doc/guides/nics/features/mlx5.ini           |   1 +
 doc/guides/nics/mlx5.rst                    |   7 +
 doc/guides/prog_guide/rte_flow.rst          |   9 +-
 doc/guides/rel_notes/release_24_03.rst      |   9 +
 doc/guides/testpmd_app_ug/testpmd_funcs.rst |  24 ++
 drivers/net/mlx5/mlx5_flow.c                |   4 +-
 drivers/net/mlx5/mlx5_flow.h                |   9 +-
 drivers/net/mlx5/mlx5_flow_dv.c             |  10 +-
 drivers/net/mlx5/mlx5_flow_hw.c             |  73 ++++
 lib/ethdev/rte_flow.c                       |   1 +
 lib/ethdev/rte_flow.h                       | 332 +++++++++-------
 13 files changed, 727 insertions(+), 169 deletions(-)

-- 
2.34.1


^ permalink raw reply	[flat|nested] 66+ messages in thread

* [PATCH v6 1/3] ethdev: rename action modify field data structure
  2024-02-02  0:42 ` [PATCH v6 " Suanming Mou
@ 2024-02-02  0:42   ` Suanming Mou
  2024-02-05 11:23     ` Thomas Monjalon
  2024-02-02  0:42   ` [PATCH v6 2/3] ethdev: add compare item Suanming Mou
  2024-02-02  0:42   ` [PATCH v6 3/3] net/mlx5: add compare item support Suanming Mou
  2 siblings, 1 reply; 66+ messages in thread
From: Suanming Mou @ 2024-02-02  0:42 UTC (permalink / raw)
  To: ferruh.yigit, Ori Kam, Aman Singh, Yuying Zhang,
	Dariusz Sosnowski, Viacheslav Ovsiienko, Matan Azrad,
	Thomas Monjalon, Andrew Rybchenko
  Cc: dev

Current rte_flow_action_modify_data struct describes the pkt
field perfectly and is used only in action.

It is planned to be used for item as well. This commit renames
it to "rte_flow_field_data" making it compatible to be used by item.

Signed-off-by: Suanming Mou <suanmingm@nvidia.com>
Acked-by: Ori Kam <orika@nvidia.com>
Acked-by: Andrew Rybchenko <andrew.rybchenko@oktetlabs.ru>
---
 app/test-pmd/cmdline_flow.c            | 22 +++++++++++-----------
 doc/guides/prog_guide/rte_flow.rst     |  2 +-
 doc/guides/rel_notes/release_24_03.rst |  2 ++
 drivers/net/mlx5/mlx5_flow.c           |  4 ++--
 drivers/net/mlx5/mlx5_flow.h           |  6 +++---
 drivers/net/mlx5/mlx5_flow_dv.c        | 10 +++++-----
 lib/ethdev/rte_flow.h                  | 10 ++++++----
 7 files changed, 30 insertions(+), 26 deletions(-)

diff --git a/app/test-pmd/cmdline_flow.c b/app/test-pmd/cmdline_flow.c
index 4d26e81d26..35030b5c47 100644
--- a/app/test-pmd/cmdline_flow.c
+++ b/app/test-pmd/cmdline_flow.c
@@ -744,13 +744,13 @@ enum index {
 #define ITEM_RAW_SIZE \
 	(sizeof(struct rte_flow_item_raw) + ITEM_RAW_PATTERN_SIZE)
 
-/** Maximum size for external pattern in struct rte_flow_action_modify_data. */
-#define ACTION_MODIFY_PATTERN_SIZE 32
+/** Maximum size for external pattern in struct rte_flow_field_data. */
+#define FLOW_FIELD_PATTERN_SIZE 32
 
 /** Storage size for struct rte_flow_action_modify_field including pattern. */
 #define ACTION_MODIFY_SIZE \
 	(sizeof(struct rte_flow_action_modify_field) + \
-	ACTION_MODIFY_PATTERN_SIZE)
+	FLOW_FIELD_PATTERN_SIZE)
 
 /** Maximum number of queue indices in struct rte_flow_action_rss. */
 #define ACTION_RSS_QUEUE_NUM 128
@@ -944,7 +944,7 @@ static const char *const modify_field_ops[] = {
 	"set", "add", "sub", NULL
 };
 
-static const char *const modify_field_ids[] = {
+static const char *const flow_field_ids[] = {
 	"start", "mac_dst", "mac_src",
 	"vlan_type", "vlan_id", "mac_type",
 	"ipv4_dscp", "ipv4_ttl", "ipv4_src", "ipv4_dst",
@@ -6995,7 +6995,7 @@ static const struct token token_list[] = {
 			     ARGS_ENTRY_ARB(0, 0),
 			     ARGS_ENTRY_ARB
 				(sizeof(struct rte_flow_action_modify_field),
-				 ACTION_MODIFY_PATTERN_SIZE)),
+				 FLOW_FIELD_PATTERN_SIZE)),
 		.call = parse_vc_conf,
 	},
 	[ACTION_MODIFY_FIELD_WIDTH] = {
@@ -9821,10 +9821,10 @@ parse_vc_modify_field_id(struct context *ctx, const struct token *token,
 	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))
+	for (i = 0; flow_field_ids[i]; ++i)
+		if (!strcmp_partial(flow_field_ids[i], str, len))
 			break;
-	if (!modify_field_ids[i])
+	if (!flow_field_ids[i])
 		return -1;
 	if (!ctx->object)
 		return len;
@@ -12051,10 +12051,10 @@ comp_set_modify_field_id(struct context *ctx, const struct token *token,
 
 	RTE_SET_USED(token);
 	if (!buf)
-		return RTE_DIM(modify_field_ids);
-	if (ent >= RTE_DIM(modify_field_ids) - 1)
+		return RTE_DIM(flow_field_ids);
+	if (ent >= RTE_DIM(flow_field_ids) - 1)
 		return -1;
-	name = modify_field_ids[ent];
+	name = flow_field_ids[ent];
 	if (ctx->curr == ACTION_MODIFY_FIELD_SRC_TYPE ||
 	    (strcmp(name, "pointer") && strcmp(name, "value")))
 		return strlcpy(buf, name, size);
diff --git a/doc/guides/prog_guide/rte_flow.rst b/doc/guides/prog_guide/rte_flow.rst
index 7af329bd93..9192d6ab01 100644
--- a/doc/guides/prog_guide/rte_flow.rst
+++ b/doc/guides/prog_guide/rte_flow.rst
@@ -3185,7 +3185,7 @@ destination offset as ``48``, and provide immediate value ``0xXXXX85XX``.
    | ``width``     | number of bits to use   |
    +---------------+-------------------------+
 
-.. _table_rte_flow_action_modify_data:
+.. _table_rte_flow_field_data:
 
 .. table:: destination/source field definition
 
diff --git a/doc/guides/rel_notes/release_24_03.rst b/doc/guides/rel_notes/release_24_03.rst
index 84d3144215..5f3ceeccab 100644
--- a/doc/guides/rel_notes/release_24_03.rst
+++ b/doc/guides/rel_notes/release_24_03.rst
@@ -124,6 +124,8 @@ ABI Changes
 
 * No ABI change that would break compatibility with 23.11.
 
+* ethdev: Rename the experimental ``struct rte_flow_action_modify_data`` to be ``struct rte_flow_field_data``
+
 
 Known Issues
 ------------
diff --git a/drivers/net/mlx5/mlx5_flow.c b/drivers/net/mlx5/mlx5_flow.c
index 85e8c77c81..5788a7fb57 100644
--- a/drivers/net/mlx5/mlx5_flow.c
+++ b/drivers/net/mlx5/mlx5_flow.c
@@ -2493,7 +2493,7 @@ mlx5_validate_action_ct(struct rte_eth_dev *dev,
  * Validate the level value for modify field action.
  *
  * @param[in] data
- *   Pointer to the rte_flow_action_modify_data structure either src or dst.
+ *   Pointer to the rte_flow_field_data structure either src or dst.
  * @param[out] error
  *   Pointer to error structure.
  *
@@ -2501,7 +2501,7 @@ mlx5_validate_action_ct(struct rte_eth_dev *dev,
  *   0 on success, a negative errno value otherwise and rte_errno is set.
  */
 int
-flow_validate_modify_field_level(const struct rte_flow_action_modify_data *data,
+flow_validate_modify_field_level(const struct rte_flow_field_data *data,
 				 struct rte_flow_error *error)
 {
 	if (data->level == 0)
diff --git a/drivers/net/mlx5/mlx5_flow.h b/drivers/net/mlx5/mlx5_flow.h
index 6dde9de688..ecfb04ead2 100644
--- a/drivers/net/mlx5/mlx5_flow.h
+++ b/drivers/net/mlx5/mlx5_flow.h
@@ -1121,7 +1121,7 @@ flow_items_to_tunnel(const struct rte_flow_item items[])
  *   Tag array index.
  */
 static inline uint8_t
-flow_tag_index_get(const struct rte_flow_action_modify_data *data)
+flow_tag_index_get(const struct rte_flow_field_data *data)
 {
 	return data->tag_index ? data->tag_index : data->level;
 }
@@ -2523,7 +2523,7 @@ int mlx5_flow_validate_action_default_miss(uint64_t action_flags,
 				const struct rte_flow_attr *attr,
 				struct rte_flow_error *error);
 int flow_validate_modify_field_level
-			(const struct rte_flow_action_modify_data *data,
+			(const struct rte_flow_field_data *data,
 			 struct rte_flow_error *error);
 int mlx5_flow_item_acceptable(const struct rte_flow_item *item,
 			      const uint8_t *mask,
@@ -2828,7 +2828,7 @@ size_t flow_dv_get_item_hdr_len(const enum rte_flow_item_type item_type);
 int flow_dv_convert_encap_data(const struct rte_flow_item *items, uint8_t *buf,
 			   size_t *size, struct rte_flow_error *error);
 void mlx5_flow_field_id_to_modify_info
-		(const struct rte_flow_action_modify_data *data,
+		(const struct rte_flow_field_data *data,
 		 struct field_modify_info *info, uint32_t *mask,
 		 uint32_t width, struct rte_eth_dev *dev,
 		 const struct rte_flow_attr *attr, struct rte_flow_error *error);
diff --git a/drivers/net/mlx5/mlx5_flow_dv.c b/drivers/net/mlx5/mlx5_flow_dv.c
index 115d730317..52620be262 100644
--- a/drivers/net/mlx5/mlx5_flow_dv.c
+++ b/drivers/net/mlx5/mlx5_flow_dv.c
@@ -1441,7 +1441,7 @@ flow_modify_info_mask_32_masked(uint32_t length, uint32_t off, uint32_t post_mas
 }
 
 static __rte_always_inline enum mlx5_modification_field
-mlx5_mpls_modi_field_get(const struct rte_flow_action_modify_data *data)
+mlx5_mpls_modi_field_get(const struct rte_flow_field_data *data)
 {
 	return MLX5_MODI_IN_MPLS_LABEL_0 + data->tag_index;
 }
@@ -1449,7 +1449,7 @@ mlx5_mpls_modi_field_get(const struct rte_flow_action_modify_data *data)
 static void
 mlx5_modify_flex_item(const struct rte_eth_dev *dev,
 		      const struct mlx5_flex_item *flex,
-		      const struct rte_flow_action_modify_data *data,
+		      const struct rte_flow_field_data *data,
 		      struct field_modify_info *info,
 		      uint32_t *mask, uint32_t width)
 {
@@ -1573,7 +1573,7 @@ mlx5_modify_flex_item(const struct rte_eth_dev *dev,
 
 void
 mlx5_flow_field_id_to_modify_info
-		(const struct rte_flow_action_modify_data *data,
+		(const struct rte_flow_field_data *data,
 		 struct field_modify_info *info, uint32_t *mask,
 		 uint32_t width, struct rte_eth_dev *dev,
 		 const struct rte_flow_attr *attr, struct rte_flow_error *error)
@@ -5284,8 +5284,8 @@ flow_dv_validate_action_modify_field(struct rte_eth_dev *dev,
 	struct mlx5_sh_config *config = &priv->sh->config;
 	struct mlx5_hca_attr *hca_attr = &priv->sh->cdev->config.hca_attr;
 	const struct rte_flow_action_modify_field *conf = action->conf;
-	const struct rte_flow_action_modify_data *src_data = &conf->src;
-	const struct rte_flow_action_modify_data *dst_data = &conf->dst;
+	const struct rte_flow_field_data *src_data = &conf->src;
+	const struct rte_flow_field_data *dst_data = &conf->dst;
 	uint32_t dst_width, src_width, width = conf->width;
 
 	ret = flow_dv_validate_action_modify_hdr(action_flags, action, error);
diff --git a/lib/ethdev/rte_flow.h b/lib/ethdev/rte_flow.h
index 1dded812ec..5e66b2af1d 100644
--- a/lib/ethdev/rte_flow.h
+++ b/lib/ethdev/rte_flow.h
@@ -3894,6 +3894,7 @@ struct rte_flow_action_ethdev {
 
 /**
  * Field IDs for MODIFY_FIELD action.
+ * e.g. the packet field IDs used in RTE_FLOW_ACTION_TYPE_MODIFY_FIELD.
  */
 enum rte_flow_field_id {
 	RTE_FLOW_FIELD_START = 0,	/**< Start of a packet. */
@@ -3947,9 +3948,10 @@ enum rte_flow_field_id {
  * @warning
  * @b EXPERIMENTAL: this structure may change without prior notice
  *
- * Field description for MODIFY_FIELD action.
+ * Field description for packet field.
+ * e.g. the packet fields used in RTE_FLOW_ACTION_TYPE_MODIFY_FIELD.
  */
-struct rte_flow_action_modify_data {
+struct rte_flow_field_data {
 	enum rte_flow_field_id field; /**< Field or memory type ID. */
 	union {
 		struct {
@@ -4058,8 +4060,8 @@ enum rte_flow_modify_op {
  */
 struct rte_flow_action_modify_field {
 	enum rte_flow_modify_op operation; /**< Operation to perform. */
-	struct rte_flow_action_modify_data dst; /**< Destination field. */
-	struct rte_flow_action_modify_data src; /**< Source field. */
+	struct rte_flow_field_data dst; /**< Destination field. */
+	struct rte_flow_field_data src; /**< Source field. */
 	uint32_t width; /**< Number of bits to use from a source field. */
 };
 
-- 
2.34.1


^ permalink raw reply	[flat|nested] 66+ messages in thread

* [PATCH v6 2/3] ethdev: add compare item
  2024-02-02  0:42 ` [PATCH v6 " Suanming Mou
  2024-02-02  0:42   ` [PATCH v6 1/3] ethdev: rename action modify field data structure Suanming Mou
@ 2024-02-02  0:42   ` Suanming Mou
  2024-02-05 13:00     ` Thomas Monjalon
  2024-02-02  0:42   ` [PATCH v6 3/3] net/mlx5: add compare item support Suanming Mou
  2 siblings, 1 reply; 66+ messages in thread
From: Suanming Mou @ 2024-02-02  0:42 UTC (permalink / raw)
  To: ferruh.yigit, Ori Kam, Aman Singh, Yuying Zhang, Thomas Monjalon,
	Andrew Rybchenko
  Cc: dev

The new item type is added for the case user wants to match traffic
based on packet field compare result with other fields or immediate
value.

e.g. take advantage the compare item user will be able to accumulate
a IPv4/TCP packet's TCP data_offset and IPv4 IHL field to a tag
register, then compare the tag register with IPv4 header total length
to understand the packet has payload or not.

The supported operations can be as below:
 - RTE_FLOW_ITEM_COMPARE_EQ (equal)
 - RTE_FLOW_ITEM_COMPARE_NE (not equal)
 - RTE_FLOW_ITEM_COMPARE_LT (less than)
 - RTE_FLOW_ITEM_COMPARE_LE (less than or equal)
 - RTE_FLOW_ITEM_COMPARE_GT (great than)
 - RTE_FLOW_ITEM_COMPARE_GE (great than or equal)

A sample for create the comparison flow:
flow pattern_template 0 create ingress pattern_template_id 1 template \
	compare op mask le a_type mask tag a_tag_index mask 1 b_type \
	mask tag b_tag_index mask 2 width mask 0xffffffff / end
flow actions_template 0 create ingress actions_template_id 1 template \
	count / drop / end mask count / drop  / end
flow template_table 0 create table_id 1 group 2 priority 1  ingress \
	rules_number 1 pattern_template 1 actions_template 1
flow queue 0 create 0 template_table 1 pattern_template 0 \
	actions_template 0 postpone no pattern compare op is le \
	a_type is tag a_tag_index is 1 b_type is tag b_tag_index is 2 \
	width is 32 / end actions count / drop / end

Signed-off-by: Suanming Mou <suanmingm@nvidia.com>
Acked-by: Ori Kam <orika@nvidia.com>
Acked-by: Andrew Rybchenko <andrew.rybchenko@oktetlabs.ru>
---
 app/test-pmd/cmdline_flow.c                 | 394 ++++++++++++++++++++
 doc/guides/nics/features/default.ini        |   1 +
 doc/guides/prog_guide/rte_flow.rst          |   7 +
 doc/guides/rel_notes/release_24_03.rst      |   5 +
 doc/guides/testpmd_app_ug/testpmd_funcs.rst |  24 ++
 lib/ethdev/rte_flow.c                       |   1 +
 lib/ethdev/rte_flow.h                       | 330 ++++++++--------
 7 files changed, 615 insertions(+), 147 deletions(-)

diff --git a/app/test-pmd/cmdline_flow.c b/app/test-pmd/cmdline_flow.c
index 35030b5c47..06f8c82342 100644
--- a/app/test-pmd/cmdline_flow.c
+++ b/app/test-pmd/cmdline_flow.c
@@ -545,6 +545,28 @@ enum index {
 	ITEM_PTYPE,
 	ITEM_PTYPE_VALUE,
 	ITEM_NSH,
+	ITEM_COMPARE,
+	ITEM_COMPARE_OP,
+	ITEM_COMPARE_OP_VALUE,
+	ITEM_COMPARE_FIELD_A_TYPE,
+	ITEM_COMPARE_FIELD_A_TYPE_VALUE,
+	ITEM_COMPARE_FIELD_A_LEVEL,
+	ITEM_COMPARE_FIELD_A_LEVEL_VALUE,
+	ITEM_COMPARE_FIELD_A_TAG_INDEX,
+	ITEM_COMPARE_FIELD_A_TYPE_ID,
+	ITEM_COMPARE_FIELD_A_CLASS_ID,
+	ITEM_COMPARE_FIELD_A_OFFSET,
+	ITEM_COMPARE_FIELD_B_TYPE,
+	ITEM_COMPARE_FIELD_B_TYPE_VALUE,
+	ITEM_COMPARE_FIELD_B_LEVEL,
+	ITEM_COMPARE_FIELD_B_LEVEL_VALUE,
+	ITEM_COMPARE_FIELD_B_TAG_INDEX,
+	ITEM_COMPARE_FIELD_B_TYPE_ID,
+	ITEM_COMPARE_FIELD_B_CLASS_ID,
+	ITEM_COMPARE_FIELD_B_OFFSET,
+	ITEM_COMPARE_FIELD_B_VALUE,
+	ITEM_COMPARE_FIELD_B_POINTER,
+	ITEM_COMPARE_FIELD_WIDTH,
 
 	/* Validate/create actions. */
 	ACTIONS,
@@ -744,6 +766,10 @@ enum index {
 #define ITEM_RAW_SIZE \
 	(sizeof(struct rte_flow_item_raw) + ITEM_RAW_PATTERN_SIZE)
 
+static const char *const compare_ops[] = {
+	"eq", "ne", "lt", "le", "gt", "ge", NULL
+};
+
 /** Maximum size for external pattern in struct rte_flow_field_data. */
 #define FLOW_FIELD_PATTERN_SIZE 32
 
@@ -1596,6 +1622,7 @@ static const enum index next_item[] = {
 	ITEM_IB_BTH,
 	ITEM_PTYPE,
 	ITEM_NSH,
+	ITEM_COMPARE,
 	END_SET,
 	ZERO,
 };
@@ -2133,6 +2160,38 @@ static const enum index item_nsh[] = {
 	ZERO,
 };
 
+static const enum index item_compare_field[] = {
+	ITEM_COMPARE_OP,
+	ITEM_COMPARE_FIELD_A_TYPE,
+	ITEM_COMPARE_FIELD_B_TYPE,
+	ITEM_NEXT,
+	ZERO,
+};
+
+static const enum index compare_field_a[] = {
+	ITEM_COMPARE_FIELD_A_TYPE,
+	ITEM_COMPARE_FIELD_A_LEVEL,
+	ITEM_COMPARE_FIELD_A_TAG_INDEX,
+	ITEM_COMPARE_FIELD_A_TYPE_ID,
+	ITEM_COMPARE_FIELD_A_CLASS_ID,
+	ITEM_COMPARE_FIELD_A_OFFSET,
+	ITEM_COMPARE_FIELD_B_TYPE,
+	ZERO,
+};
+
+static const enum index compare_field_b[] = {
+	ITEM_COMPARE_FIELD_B_TYPE,
+	ITEM_COMPARE_FIELD_B_LEVEL,
+	ITEM_COMPARE_FIELD_B_TAG_INDEX,
+	ITEM_COMPARE_FIELD_B_TYPE_ID,
+	ITEM_COMPARE_FIELD_B_CLASS_ID,
+	ITEM_COMPARE_FIELD_B_OFFSET,
+	ITEM_COMPARE_FIELD_B_VALUE,
+	ITEM_COMPARE_FIELD_B_POINTER,
+	ITEM_COMPARE_FIELD_WIDTH,
+	ZERO,
+};
+
 static const enum index next_action[] = {
 	ACTION_END,
 	ACTION_VOID,
@@ -2882,6 +2941,24 @@ comp_quota_update_name(struct context *ctx, const struct token *token,
 static int
 comp_qu_mode_name(struct context *ctx, const struct token *token,
 		  unsigned int ent, char *buf, unsigned int size);
+static int
+comp_set_compare_field_id(struct context *ctx, const struct token *token,
+			  unsigned int ent, char *buf, unsigned int size);
+static int
+comp_set_compare_op(struct context *ctx, const struct token *token,
+		    unsigned int ent, char *buf, unsigned int size);
+static int
+parse_vc_compare_op(struct context *ctx, const struct token *token,
+			 const char *str, unsigned int len, void *buf,
+			 unsigned int size);
+static int
+parse_vc_compare_field_id(struct context *ctx, const struct token *token,
+			  const char *str, unsigned int len, void *buf,
+			  unsigned int size);
+static int
+parse_vc_compare_field_level(struct context *ctx, const struct token *token,
+			     const char *str, unsigned int len, void *buf,
+			     unsigned int size);
 
 struct indlst_conf {
 	uint32_t id;
@@ -6016,6 +6093,174 @@ static const struct token token_list[] = {
 		.next = NEXT(item_nsh),
 		.call = parse_vc,
 	},
+	[ITEM_COMPARE] = {
+		.name = "compare",
+		.help = "match with the comparison result",
+		.priv = PRIV_ITEM(COMPARE, sizeof(struct rte_flow_item_compare)),
+		.next = NEXT(NEXT_ENTRY(ITEM_COMPARE_OP)),
+		.call = parse_vc,
+	},
+	[ITEM_COMPARE_OP] = {
+		.name = "op",
+		.help = "operation type",
+		.next = NEXT(item_compare_field,
+			NEXT_ENTRY(ITEM_COMPARE_OP_VALUE), item_param),
+		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_compare, operation)),
+	},
+	[ITEM_COMPARE_OP_VALUE] = {
+		.name = "{operation}",
+		.help = "operation type value",
+		.call = parse_vc_compare_op,
+		.comp = comp_set_compare_op,
+	},
+	[ITEM_COMPARE_FIELD_A_TYPE] = {
+		.name = "a_type",
+		.help = "compared field type",
+		.next = NEXT(compare_field_a,
+			NEXT_ENTRY(ITEM_COMPARE_FIELD_A_TYPE_VALUE), item_param),
+		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_compare, a.field)),
+	},
+	[ITEM_COMPARE_FIELD_A_TYPE_VALUE] = {
+		.name = "{a_type}",
+		.help = "compared field type value",
+		.call = parse_vc_compare_field_id,
+		.comp = comp_set_compare_field_id,
+	},
+	[ITEM_COMPARE_FIELD_A_LEVEL] = {
+		.name = "a_level",
+		.help = "compared field level",
+		.next = NEXT(compare_field_a,
+			     NEXT_ENTRY(ITEM_COMPARE_FIELD_A_LEVEL_VALUE), item_param),
+		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_compare, a.level)),
+	},
+	[ITEM_COMPARE_FIELD_A_LEVEL_VALUE] = {
+		.name = "{a_level}",
+		.help = "compared field level value",
+		.call = parse_vc_compare_field_level,
+		.comp = comp_none,
+	},
+	[ITEM_COMPARE_FIELD_A_TAG_INDEX] = {
+		.name = "a_tag_index",
+		.help = "compared field tag array",
+		.next = NEXT(compare_field_a,
+			     NEXT_ENTRY(COMMON_UNSIGNED), item_param),
+		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_compare,
+					a.tag_index)),
+	},
+	[ITEM_COMPARE_FIELD_A_TYPE_ID] = {
+		.name = "a_type_id",
+		.help = "compared field type ID",
+		.next = NEXT(compare_field_a,
+			     NEXT_ENTRY(COMMON_UNSIGNED), item_param),
+		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_compare,
+					a.type)),
+	},
+	[ITEM_COMPARE_FIELD_A_CLASS_ID] = {
+		.name = "a_class",
+		.help = "compared field class ID",
+		.next = NEXT(compare_field_a,
+			     NEXT_ENTRY(COMMON_UNSIGNED), item_param),
+		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_compare,
+					     a.class_id)),
+	},
+	[ITEM_COMPARE_FIELD_A_OFFSET] = {
+		.name = "a_offset",
+		.help = "compared field bit offset",
+		.next = NEXT(compare_field_a,
+			     NEXT_ENTRY(COMMON_UNSIGNED), item_param),
+		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_compare,
+					a.offset)),
+	},
+	[ITEM_COMPARE_FIELD_B_TYPE] = {
+		.name = "b_type",
+		.help = "comparator field type",
+		.next = NEXT(compare_field_b,
+			NEXT_ENTRY(ITEM_COMPARE_FIELD_B_TYPE_VALUE), item_param),
+		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_compare,
+					b.field)),
+	},
+	[ITEM_COMPARE_FIELD_B_TYPE_VALUE] = {
+		.name = "{b_type}",
+		.help = "comparator field type value",
+		.call = parse_vc_compare_field_id,
+		.comp = comp_set_compare_field_id,
+	},
+	[ITEM_COMPARE_FIELD_B_LEVEL] = {
+		.name = "b_level",
+		.help = "comparator field level",
+		.next = NEXT(compare_field_b,
+			     NEXT_ENTRY(ITEM_COMPARE_FIELD_B_LEVEL_VALUE), item_param),
+		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_compare,
+					b.level)),
+	},
+	[ITEM_COMPARE_FIELD_B_LEVEL_VALUE] = {
+		.name = "{b_level}",
+		.help = "comparator field level value",
+		.call = parse_vc_compare_field_level,
+		.comp = comp_none,
+	},
+	[ITEM_COMPARE_FIELD_B_TAG_INDEX] = {
+		.name = "b_tag_index",
+		.help = "comparator field tag array",
+		.next = NEXT(compare_field_b,
+			     NEXT_ENTRY(COMMON_UNSIGNED), item_param),
+		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_compare,
+					b.tag_index)),
+	},
+	[ITEM_COMPARE_FIELD_B_TYPE_ID] = {
+		.name = "b_type_id",
+		.help = "comparator field type ID",
+		.next = NEXT(compare_field_b,
+			     NEXT_ENTRY(COMMON_UNSIGNED), item_param),
+		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_compare,
+					b.type)),
+	},
+	[ITEM_COMPARE_FIELD_B_CLASS_ID] = {
+		.name = "b_class",
+		.help = "comparator field class ID",
+		.next = NEXT(compare_field_b,
+			     NEXT_ENTRY(COMMON_UNSIGNED), item_param),
+		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_compare,
+					     b.class_id)),
+	},
+	[ITEM_COMPARE_FIELD_B_OFFSET] = {
+		.name = "b_offset",
+		.help = "comparator field bit offset",
+		.next = NEXT(compare_field_b,
+			     NEXT_ENTRY(COMMON_UNSIGNED), item_param),
+		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_compare,
+					b.offset)),
+	},
+	[ITEM_COMPARE_FIELD_B_VALUE] = {
+		.name = "b_value",
+		.help = "comparator immediate value",
+		.next = NEXT(compare_field_b,
+			     NEXT_ENTRY(COMMON_HEX), item_param),
+		.args = ARGS(ARGS_ENTRY_ARB(0, 0),
+			     ARGS_ENTRY_ARB(0, 0),
+			     ARGS_ENTRY(struct rte_flow_item_compare,
+					b.value)),
+	},
+	[ITEM_COMPARE_FIELD_B_POINTER] = {
+		.name = "b_ptr",
+		.help = "pointer to comparator immediate value",
+		.next = NEXT(compare_field_b,
+			     NEXT_ENTRY(COMMON_HEX), item_param),
+		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_compare,
+					b.pvalue),
+			     ARGS_ENTRY_ARB(0, 0),
+			     ARGS_ENTRY_ARB
+				(sizeof(struct rte_flow_item_compare),
+				 FLOW_FIELD_PATTERN_SIZE)),
+	},
+	[ITEM_COMPARE_FIELD_WIDTH] = {
+		.name = "width",
+		.help = "number of bits to compare",
+		.next = NEXT(item_compare_field,
+			NEXT_ENTRY(COMMON_UNSIGNED), item_param),
+		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_compare,
+					width)),
+	},
 
 	/* Validate/create actions. */
 	[ACTIONS] = {
@@ -8452,6 +8697,122 @@ parse_vc_item_l2tpv2_type(struct context *ctx, const struct token *token,
 	return len;
 }
 
+/** Parse operation for compare match item. */
+static int
+parse_vc_compare_op(struct context *ctx, const struct token *token,
+			 const char *str, unsigned int len, void *buf,
+			 unsigned int size)
+{
+	struct rte_flow_item_compare *compare_item;
+	unsigned int i;
+
+	(void)token;
+	(void)buf;
+	(void)size;
+	if (ctx->curr != ITEM_COMPARE_OP_VALUE)
+		return -1;
+	for (i = 0; compare_ops[i]; ++i)
+		if (!strcmp_partial(compare_ops[i], str, len))
+			break;
+	if (!compare_ops[i])
+		return -1;
+	if (!ctx->object)
+		return len;
+	compare_item = ctx->object;
+	compare_item->operation = (enum rte_flow_item_compare_op)i;
+	return len;
+}
+
+/** Parse id for compare match item. */
+static int
+parse_vc_compare_field_id(struct context *ctx, const struct token *token,
+			  const char *str, unsigned int len, void *buf,
+			  unsigned int size)
+{
+	struct rte_flow_item_compare *compare_item;
+	unsigned int i;
+
+	(void)token;
+	(void)buf;
+	(void)size;
+	if (ctx->curr != ITEM_COMPARE_FIELD_A_TYPE_VALUE &&
+		ctx->curr != ITEM_COMPARE_FIELD_B_TYPE_VALUE)
+		return -1;
+	for (i = 0; flow_field_ids[i]; ++i)
+		if (!strcmp_partial(flow_field_ids[i], str, len))
+			break;
+	if (!flow_field_ids[i])
+		return -1;
+	if (!ctx->object)
+		return len;
+	compare_item = ctx->object;
+	if (ctx->curr == ITEM_COMPARE_FIELD_A_TYPE_VALUE)
+		compare_item->a.field = (enum rte_flow_field_id)i;
+	else
+		compare_item->b.field = (enum rte_flow_field_id)i;
+	return len;
+}
+
+/** Parse level for compare match item. */
+static int
+parse_vc_compare_field_level(struct context *ctx, const struct token *token,
+			     const char *str, unsigned int len, void *buf,
+			     unsigned int size)
+{
+	struct rte_flow_item_compare *compare_item;
+	struct flex_item *fp = NULL;
+	uint32_t val;
+	struct buffer *out = buf;
+	char *end;
+
+	(void)token;
+	(void)size;
+	if (ctx->curr != ITEM_COMPARE_FIELD_A_LEVEL_VALUE &&
+		ctx->curr != ITEM_COMPARE_FIELD_B_LEVEL_VALUE)
+		return -1;
+	if (!ctx->object)
+		return len;
+	compare_item = ctx->object;
+	errno = 0;
+	val = strtoumax(str, &end, 0);
+	if (errno || (size_t)(end - str) != len)
+		return -1;
+	/* No need to validate action template mask value */
+	if (out->args.vc.masks) {
+		if (ctx->curr == ITEM_COMPARE_FIELD_A_LEVEL_VALUE)
+			compare_item->a.level = val;
+		else
+			compare_item->b.level = val;
+		return len;
+	}
+	if ((ctx->curr == ITEM_COMPARE_FIELD_A_LEVEL_VALUE &&
+		compare_item->a.field == RTE_FLOW_FIELD_FLEX_ITEM) ||
+		(ctx->curr == ITEM_COMPARE_FIELD_B_LEVEL_VALUE &&
+		compare_item->b.field == RTE_FLOW_FIELD_FLEX_ITEM)) {
+		if (val >= FLEX_MAX_PARSERS_NUM) {
+			printf("Bad flex item handle\n");
+			return -1;
+		}
+		fp = flex_items[ctx->port][val];
+		if (!fp) {
+			printf("Bad flex item handle\n");
+			return -1;
+		}
+	}
+	if (ctx->curr == ITEM_COMPARE_FIELD_A_LEVEL_VALUE) {
+		if (compare_item->a.field != RTE_FLOW_FIELD_FLEX_ITEM)
+			compare_item->a.level = val;
+		else
+			compare_item->a.flex_handle = fp->flex_handle;
+	} else if (ctx->curr == ITEM_COMPARE_FIELD_B_LEVEL_VALUE) {
+		if (compare_item->b.field != RTE_FLOW_FIELD_FLEX_ITEM)
+			compare_item->b.level = val;
+		else
+			compare_item->b.flex_handle = fp->flex_handle;
+	}
+	return len;
+}
+
 /** Parse meter color action type. */
 static int
 parse_vc_action_meter_color_type(struct context *ctx, const struct token *token,
@@ -11938,6 +12299,39 @@ comp_rule_id(struct context *ctx, const struct token *token,
 	return i;
 }
 
+/** Complete operation for compare match item. */
+static int
+comp_set_compare_op(struct context *ctx, const struct token *token,
+		    unsigned int ent, char *buf, unsigned int size)
+{
+	RTE_SET_USED(ctx);
+	RTE_SET_USED(token);
+	if (!buf)
+		return RTE_DIM(compare_ops);
+	if (ent < RTE_DIM(compare_ops) - 1)
+		return strlcpy(buf, compare_ops[ent], size);
+	return -1;
+}
+
+/** Complete field id for compare match item. */
+static int
+comp_set_compare_field_id(struct context *ctx, const struct token *token,
+			  unsigned int ent, char *buf, unsigned int size)
+{
+	const char *name;
+
+	RTE_SET_USED(token);
+	if (!buf)
+		return RTE_DIM(flow_field_ids);
+	if (ent >= RTE_DIM(flow_field_ids) - 1)
+		return -1;
+	name = flow_field_ids[ent];
+	if (ctx->curr == ITEM_COMPARE_FIELD_B_TYPE ||
+	    (strcmp(name, "pointer") && strcmp(name, "value")))
+		return strlcpy(buf, name, size);
+	return -1;
+}
+
 /** Complete type field for RSS action. */
 static int
 comp_vc_action_rss_type(struct context *ctx, const struct token *token,
diff --git a/doc/guides/nics/features/default.ini b/doc/guides/nics/features/default.ini
index a21168ba21..2488942db6 100644
--- a/doc/guides/nics/features/default.ini
+++ b/doc/guides/nics/features/default.ini
@@ -88,6 +88,7 @@ aggr_affinity        =
 ah                   =
 any                  =
 arp_eth_ipv4         =
+compare              =
 conntrack            =
 ecpri                =
 esp                  =
diff --git a/doc/guides/prog_guide/rte_flow.rst b/doc/guides/prog_guide/rte_flow.rst
index 9192d6ab01..34dc06ec66 100644
--- a/doc/guides/prog_guide/rte_flow.rst
+++ b/doc/guides/prog_guide/rte_flow.rst
@@ -1587,6 +1587,13 @@ the packet.
 
 - ``value``: Specific value to match.
 
+Item: ``COMPARE``
+^^^^^^^^^^^^^^^^^
+
+Matches the comparison result between packet fields or value.
+
+- ``compare``: Comparison information.
+
 Actions
 ~~~~~~~
 
diff --git a/doc/guides/rel_notes/release_24_03.rst b/doc/guides/rel_notes/release_24_03.rst
index 5f3ceeccab..7a2dc32943 100644
--- a/doc/guides/rel_notes/release_24_03.rst
+++ b/doc/guides/rel_notes/release_24_03.rst
@@ -70,6 +70,11 @@ New Features
   * Added a fath path function ``rte_eth_tx_queue_count`` to get the number of used
     descriptors of a Tx queue.
 
+* **Added compare flow matching criteria.**
+
+  Added ``RTE_FLOW_ITEM_TYPE_COMPARE`` to allow matching on compare
+  result between the packet fields or value.
+
 * **Updated Atomic Rules' Arkville PMD.**
 
   * Added support for Atomic Rules' TK242 packet-capture family of devices
diff --git a/doc/guides/testpmd_app_ug/testpmd_funcs.rst b/doc/guides/testpmd_app_ug/testpmd_funcs.rst
index 0eaccbea4b..53923ad7cc 100644
--- a/doc/guides/testpmd_app_ug/testpmd_funcs.rst
+++ b/doc/guides/testpmd_app_ug/testpmd_funcs.rst
@@ -3856,6 +3856,13 @@ This section lists supported pattern items and their attributes, if any.
 
         - ``packet_type {unsigned}``: packet type.
 
+- ``compare``: match the comparison result between packet fields or value.
+
+        - ``op {string}``: comparison operation type.
+        - ``a_type {string}``: compared field.
+        - ``b_type {string}``: comparator field.
+        - ``width {unsigned}``: comparison width.
+
 
 Actions list
 ^^^^^^^^^^^^
@@ -5324,6 +5331,23 @@ 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 match with comparison rule
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+Match with comparison rule can be created as following using ``compare``.
+
+::
+
+    testpmd> flow pattern_template 0 create ingress pattern_template_id 1 template compare op mask le
+             a_type mask tag a_tag_index mask 1 b_type mask tag b_tag_index mask 2 width mask 0xffffffff / end
+    testpmd> flow actions_template 0 create ingress actions_template_id 1 template count / drop / end
+             mask count / drop  / end
+    testpmd> flow template_table 0 create table_id 1 group 2 priority 1  ingress rules_number 1
+             pattern_template 1 actions_template 1
+    testpmd> flow queue 0 create 0 template_table 1 pattern_template 0 actions_template 0 postpone no
+             pattern compare op is le a_type is tag a_tag_index is 1 b_type is tag b_tag_index is 2 width is 32 / end
+	     actions count / drop / end
+
 BPF Functions
 --------------
 
diff --git a/lib/ethdev/rte_flow.c b/lib/ethdev/rte_flow.c
index 156545454c..b06da0cc00 100644
--- a/lib/ethdev/rte_flow.c
+++ b/lib/ethdev/rte_flow.c
@@ -170,6 +170,7 @@ static const struct rte_flow_desc_data rte_flow_desc_item[] = {
 	MK_FLOW_ITEM(TX_QUEUE, sizeof(struct rte_flow_item_tx_queue)),
 	MK_FLOW_ITEM(IB_BTH, sizeof(struct rte_flow_item_ib_bth)),
 	MK_FLOW_ITEM(PTYPE, sizeof(struct rte_flow_item_ptype)),
+	MK_FLOW_ITEM(COMPARE, sizeof(struct rte_flow_item_compare)),
 };
 
 /** Generate flow_action[] entry. */
diff --git a/lib/ethdev/rte_flow.h b/lib/ethdev/rte_flow.h
index 5e66b2af1d..b1b8bdd6f9 100644
--- a/lib/ethdev/rte_flow.h
+++ b/lib/ethdev/rte_flow.h
@@ -714,6 +714,13 @@ enum rte_flow_item_type {
 	 * @see struct rte_flow_item_random.
 	 */
 	RTE_FLOW_ITEM_TYPE_RANDOM,
+
+	/**
+	 * Matches the packet with compare result.
+	 *
+	 * See struct rte_flow_item_compare.
+	 */
+	RTE_FLOW_ITEM_TYPE_COMPARE,
 };
 
 /**
@@ -2365,6 +2372,182 @@ static const struct rte_flow_item_ptype rte_flow_item_ptype_mask = {
 };
 #endif
 
+/**
+ * Field IDs for packet field.
+ * e.g. the packet field IDs used in RTE_FLOW_ACTION_TYPE_MODIFY_FIELD
+ * and RTE_FLOW_ITEM_TYPE_COMPARE.
+ */
+enum rte_flow_field_id {
+	RTE_FLOW_FIELD_START = 0,	/**< Start of a packet. */
+	RTE_FLOW_FIELD_MAC_DST,		/**< Destination MAC Address. */
+	RTE_FLOW_FIELD_MAC_SRC,		/**< Source MAC Address. */
+	RTE_FLOW_FIELD_VLAN_TYPE,	/**< VLAN Tag Identifier. */
+	RTE_FLOW_FIELD_VLAN_ID,		/**< VLAN Identifier. */
+	RTE_FLOW_FIELD_MAC_TYPE,	/**< EtherType. */
+	RTE_FLOW_FIELD_IPV4_DSCP,	/**< IPv4 DSCP. */
+	RTE_FLOW_FIELD_IPV4_TTL,	/**< IPv4 Time To Live. */
+	RTE_FLOW_FIELD_IPV4_SRC,	/**< IPv4 Source Address. */
+	RTE_FLOW_FIELD_IPV4_DST,	/**< IPv4 Destination Address. */
+	RTE_FLOW_FIELD_IPV6_DSCP,	/**< IPv6 DSCP. */
+	RTE_FLOW_FIELD_IPV6_HOPLIMIT,	/**< IPv6 Hop Limit. */
+	RTE_FLOW_FIELD_IPV6_SRC,	/**< IPv6 Source Address. */
+	RTE_FLOW_FIELD_IPV6_DST,	/**< IPv6 Destination Address. */
+	RTE_FLOW_FIELD_TCP_PORT_SRC,	/**< TCP Source Port Number. */
+	RTE_FLOW_FIELD_TCP_PORT_DST,	/**< TCP Destination Port Number. */
+	RTE_FLOW_FIELD_TCP_SEQ_NUM,	/**< TCP Sequence Number. */
+	RTE_FLOW_FIELD_TCP_ACK_NUM,	/**< TCP Acknowledgment Number. */
+	RTE_FLOW_FIELD_TCP_FLAGS,	/**< TCP Flags. */
+	RTE_FLOW_FIELD_UDP_PORT_SRC,	/**< UDP Source Port Number. */
+	RTE_FLOW_FIELD_UDP_PORT_DST,	/**< UDP Destination Port Number. */
+	RTE_FLOW_FIELD_VXLAN_VNI,	/**< VXLAN Network Identifier. */
+	RTE_FLOW_FIELD_GENEVE_VNI,	/**< GENEVE Network Identifier. */
+	RTE_FLOW_FIELD_GTP_TEID,	/**< GTP Tunnel Endpoint Identifier. */
+	RTE_FLOW_FIELD_TAG,		/**< Tag value. */
+	RTE_FLOW_FIELD_MARK,		/**< Mark value. */
+	RTE_FLOW_FIELD_META,		/**< Metadata value. */
+	RTE_FLOW_FIELD_POINTER,		/**< Memory pointer. */
+	RTE_FLOW_FIELD_VALUE,		/**< Immediate value. */
+	RTE_FLOW_FIELD_IPV4_ECN,	/**< IPv4 ECN. */
+	RTE_FLOW_FIELD_IPV6_ECN,	/**< IPv6 ECN. */
+	RTE_FLOW_FIELD_GTP_PSC_QFI,	/**< GTP QFI. */
+	RTE_FLOW_FIELD_METER_COLOR,	/**< Meter color marker. */
+	RTE_FLOW_FIELD_IPV6_PROTO,	/**< IPv6 next header. */
+	RTE_FLOW_FIELD_FLEX_ITEM,	/**< Flex item. */
+	RTE_FLOW_FIELD_HASH_RESULT,	/**< Hash result. */
+	RTE_FLOW_FIELD_GENEVE_OPT_TYPE,	/**< GENEVE option type. */
+	RTE_FLOW_FIELD_GENEVE_OPT_CLASS,/**< GENEVE option class. */
+	RTE_FLOW_FIELD_GENEVE_OPT_DATA,	/**< GENEVE option data. */
+	RTE_FLOW_FIELD_MPLS,		/**< MPLS header. */
+	RTE_FLOW_FIELD_TCP_DATA_OFFSET,	/**< TCP data offset. */
+	RTE_FLOW_FIELD_IPV4_IHL,	/**< IPv4 IHL. */
+	RTE_FLOW_FIELD_IPV4_TOTAL_LEN,	/**< IPv4 total length. */
+	RTE_FLOW_FIELD_IPV6_PAYLOAD_LEN,/**< IPv6 payload length. */
+	RTE_FLOW_FIELD_RANDOM		/**< Random value. */
+};
+
+/**
+ * @warning
+ * @b EXPERIMENTAL: this structure may change without prior notice
+ *
+ * Field description for packet field.
+ * e.g. the packet fields used in RTE_FLOW_ACTION_TYPE_MODIFY_FIELD
+ * and RTE_FLOW_ITEM_TYPE_COMPARE.
+ */
+struct rte_flow_field_data {
+	enum rte_flow_field_id field; /**< Field or memory type ID. */
+	union {
+		struct {
+			/** Encapsulation level and tag index or flex item handle. */
+			union {
+				struct {
+					/**
+					 * Packet encapsulation level containing
+					 * the field to modify.
+					 *
+					 * - @p 0 requests the default behavior.
+					 *   Depending on the packet type, it
+					 *   can mean outermost, innermost or
+					 *   anything in between.
+					 *
+					 *   It basically stands for the
+					 *   innermost encapsulation level.
+					 *   Modification can be performed
+					 *   according to PMD and device
+					 *   capabilities.
+					 *
+					 * - @p 1 requests modification to be
+					 *   performed on the outermost packet
+					 *   encapsulation level.
+					 *
+					 * - @p 2 and subsequent values request
+					 *   modification to be performed on
+					 *   the specified inner packet
+					 *   encapsulation level, from
+					 *   outermost to innermost (lower to
+					 *   higher values).
+					 *
+					 * Values other than @p 0 are not
+					 * necessarily supported.
+					 *
+					 * @note that for MPLS field,
+					 * encapsulation level also include
+					 * tunnel since MPLS may appear in
+					 * outer, inner or tunnel.
+					 */
+					uint8_t level;
+					union {
+						/**
+						 * Tag index array inside
+						 * encapsulation level.
+						 * Used for VLAN, MPLS or TAG types.
+						 */
+						uint8_t tag_index;
+						/**
+						 * Geneve option identifier.
+						 * Relevant only for
+						 * RTE_FLOW_FIELD_GENEVE_OPT_XXXX
+						 * modification type.
+						 */
+						struct {
+							/**
+							 * Geneve option type.
+							 */
+							uint8_t type;
+							/**
+							 * Geneve option class.
+							 */
+							rte_be16_t class_id;
+						};
+					};
+				};
+				struct rte_flow_item_flex_handle *flex_handle;
+			};
+			/** Number of bits to skip from a field. */
+			uint32_t offset;
+		};
+		/**
+		 * Immediate value for RTE_FLOW_FIELD_VALUE, presented in the
+		 * same byte order and length as in relevant rte_flow_item_xxx.
+		 * The immediate source bitfield offset is inherited from
+		 * the destination's one.
+		 */
+		uint8_t value[16];
+		/**
+		 * Memory address for RTE_FLOW_FIELD_POINTER, memory layout
+		 * should be the same as for relevant field in the
+		 * rte_flow_item_xxx structure.
+		 */
+		void *pvalue;
+	};
+};
+
+/**
+ * Expected operation types for compare item.
+ */
+enum rte_flow_item_compare_op {
+	RTE_FLOW_ITEM_COMPARE_EQ,	/* Compare result equal. */
+	RTE_FLOW_ITEM_COMPARE_NE,	/* Compare result not equal. */
+	RTE_FLOW_ITEM_COMPARE_LT,	/* Compare result less than. */
+	RTE_FLOW_ITEM_COMPARE_LE,	/* Compare result less than or equal. */
+	RTE_FLOW_ITEM_COMPARE_GT,	/* Compare result great than. */
+	RTE_FLOW_ITEM_COMPARE_GE,	/* Compare result great than or equal. */
+};
+
+/**
+ *
+ * RTE_FLOW_ITEM_TYPE_COMPARE
+ *
+ * Matches the packet with compare result.
+ *
+ * The operation means a compare with b result.
+ */
+struct rte_flow_item_compare {
+	enum rte_flow_item_compare_op operation; /* The compare operation. */
+	struct rte_flow_field_data a;		 /* Field be compared.  */
+	struct rte_flow_field_data b;		 /* Field as comparator. */
+	uint32_t width;				 /* Compare width. */
+};
+
 /**
  * Action types.
  *
@@ -3892,153 +4075,6 @@ struct rte_flow_action_ethdev {
 	uint16_t port_id; /**< ethdev port ID */
 };
 
-/**
- * Field IDs for MODIFY_FIELD action.
- * e.g. the packet field IDs used in RTE_FLOW_ACTION_TYPE_MODIFY_FIELD.
- */
-enum rte_flow_field_id {
-	RTE_FLOW_FIELD_START = 0,	/**< Start of a packet. */
-	RTE_FLOW_FIELD_MAC_DST,		/**< Destination MAC Address. */
-	RTE_FLOW_FIELD_MAC_SRC,		/**< Source MAC Address. */
-	RTE_FLOW_FIELD_VLAN_TYPE,	/**< VLAN Tag Identifier. */
-	RTE_FLOW_FIELD_VLAN_ID,		/**< VLAN Identifier. */
-	RTE_FLOW_FIELD_MAC_TYPE,	/**< EtherType. */
-	RTE_FLOW_FIELD_IPV4_DSCP,	/**< IPv4 DSCP. */
-	RTE_FLOW_FIELD_IPV4_TTL,	/**< IPv4 Time To Live. */
-	RTE_FLOW_FIELD_IPV4_SRC,	/**< IPv4 Source Address. */
-	RTE_FLOW_FIELD_IPV4_DST,	/**< IPv4 Destination Address. */
-	RTE_FLOW_FIELD_IPV6_DSCP,	/**< IPv6 DSCP. */
-	RTE_FLOW_FIELD_IPV6_HOPLIMIT,	/**< IPv6 Hop Limit. */
-	RTE_FLOW_FIELD_IPV6_SRC,	/**< IPv6 Source Address. */
-	RTE_FLOW_FIELD_IPV6_DST,	/**< IPv6 Destination Address. */
-	RTE_FLOW_FIELD_TCP_PORT_SRC,	/**< TCP Source Port Number. */
-	RTE_FLOW_FIELD_TCP_PORT_DST,	/**< TCP Destination Port Number. */
-	RTE_FLOW_FIELD_TCP_SEQ_NUM,	/**< TCP Sequence Number. */
-	RTE_FLOW_FIELD_TCP_ACK_NUM,	/**< TCP Acknowledgment Number. */
-	RTE_FLOW_FIELD_TCP_FLAGS,	/**< TCP Flags. */
-	RTE_FLOW_FIELD_UDP_PORT_SRC,	/**< UDP Source Port Number. */
-	RTE_FLOW_FIELD_UDP_PORT_DST,	/**< UDP Destination Port Number. */
-	RTE_FLOW_FIELD_VXLAN_VNI,	/**< VXLAN Network Identifier. */
-	RTE_FLOW_FIELD_GENEVE_VNI,	/**< GENEVE Network Identifier. */
-	RTE_FLOW_FIELD_GTP_TEID,	/**< GTP Tunnel Endpoint Identifier. */
-	RTE_FLOW_FIELD_TAG,		/**< Tag value. */
-	RTE_FLOW_FIELD_MARK,		/**< Mark value. */
-	RTE_FLOW_FIELD_META,		/**< Metadata value. */
-	RTE_FLOW_FIELD_POINTER,		/**< Memory pointer. */
-	RTE_FLOW_FIELD_VALUE,		/**< Immediate value. */
-	RTE_FLOW_FIELD_IPV4_ECN,	/**< IPv4 ECN. */
-	RTE_FLOW_FIELD_IPV6_ECN,	/**< IPv6 ECN. */
-	RTE_FLOW_FIELD_GTP_PSC_QFI,	/**< GTP QFI. */
-	RTE_FLOW_FIELD_METER_COLOR,	/**< Meter color marker. */
-	RTE_FLOW_FIELD_IPV6_PROTO,	/**< IPv6 next header. */
-	RTE_FLOW_FIELD_FLEX_ITEM,	/**< Flex item. */
-	RTE_FLOW_FIELD_HASH_RESULT,	/**< Hash result. */
-	RTE_FLOW_FIELD_GENEVE_OPT_TYPE,	/**< GENEVE option type. */
-	RTE_FLOW_FIELD_GENEVE_OPT_CLASS,/**< GENEVE option class. */
-	RTE_FLOW_FIELD_GENEVE_OPT_DATA,	/**< GENEVE option data. */
-	RTE_FLOW_FIELD_MPLS,		/**< MPLS header. */
-	RTE_FLOW_FIELD_TCP_DATA_OFFSET,	/**< TCP data offset. */
-	RTE_FLOW_FIELD_IPV4_IHL,	/**< IPv4 IHL. */
-	RTE_FLOW_FIELD_IPV4_TOTAL_LEN,	/**< IPv4 total length. */
-	RTE_FLOW_FIELD_IPV6_PAYLOAD_LEN,/**< IPv6 payload length. */
-	RTE_FLOW_FIELD_RANDOM		/**< Random value. */
-};
-
-/**
- * @warning
- * @b EXPERIMENTAL: this structure may change without prior notice
- *
- * Field description for packet field.
- * e.g. the packet fields used in RTE_FLOW_ACTION_TYPE_MODIFY_FIELD.
- */
-struct rte_flow_field_data {
-	enum rte_flow_field_id field; /**< Field or memory type ID. */
-	union {
-		struct {
-			/** Encapsulation level and tag index or flex item handle. */
-			union {
-				struct {
-					/**
-					 * Packet encapsulation level containing
-					 * the field to modify.
-					 *
-					 * - @p 0 requests the default behavior.
-					 *   Depending on the packet type, it
-					 *   can mean outermost, innermost or
-					 *   anything in between.
-					 *
-					 *   It basically stands for the
-					 *   innermost encapsulation level.
-					 *   Modification can be performed
-					 *   according to PMD and device
-					 *   capabilities.
-					 *
-					 * - @p 1 requests modification to be
-					 *   performed on the outermost packet
-					 *   encapsulation level.
-					 *
-					 * - @p 2 and subsequent values request
-					 *   modification to be performed on
-					 *   the specified inner packet
-					 *   encapsulation level, from
-					 *   outermost to innermost (lower to
-					 *   higher values).
-					 *
-					 * Values other than @p 0 are not
-					 * necessarily supported.
-					 *
-					 * @note that for MPLS field,
-					 * encapsulation level also include
-					 * tunnel since MPLS may appear in
-					 * outer, inner or tunnel.
-					 */
-					uint8_t level;
-					union {
-						/**
-						 * Tag index array inside
-						 * encapsulation level.
-						 * Used for VLAN, MPLS or TAG types.
-						 */
-						uint8_t tag_index;
-						/**
-						 * Geneve option identifier.
-						 * Relevant only for
-						 * RTE_FLOW_FIELD_GENEVE_OPT_XXXX
-						 * modification type.
-						 */
-						struct {
-							/**
-							 * Geneve option type.
-							 */
-							uint8_t type;
-							/**
-							 * Geneve option class.
-							 */
-							rte_be16_t class_id;
-						};
-					};
-				};
-				struct rte_flow_item_flex_handle *flex_handle;
-			};
-			/** Number of bits to skip from a field. */
-			uint32_t offset;
-		};
-		/**
-		 * Immediate value for RTE_FLOW_FIELD_VALUE, presented in the
-		 * same byte order and length as in relevant rte_flow_item_xxx.
-		 * The immediate source bitfield offset is inherited from
-		 * the destination's one.
-		 */
-		uint8_t value[16];
-		/**
-		 * Memory address for RTE_FLOW_FIELD_POINTER, memory layout
-		 * should be the same as for relevant field in the
-		 * rte_flow_item_xxx structure.
-		 */
-		void *pvalue;
-	};
-};
-
 /**
  * Operation types for MODIFY_FIELD action.
  */
-- 
2.34.1


^ permalink raw reply	[flat|nested] 66+ messages in thread

* [PATCH v6 3/3] net/mlx5: add compare item support
  2024-02-02  0:42 ` [PATCH v6 " Suanming Mou
  2024-02-02  0:42   ` [PATCH v6 1/3] ethdev: rename action modify field data structure Suanming Mou
  2024-02-02  0:42   ` [PATCH v6 2/3] ethdev: add compare item Suanming Mou
@ 2024-02-02  0:42   ` Suanming Mou
  2 siblings, 0 replies; 66+ messages in thread
From: Suanming Mou @ 2024-02-02  0:42 UTC (permalink / raw)
  To: ferruh.yigit, Dariusz Sosnowski, Viacheslav Ovsiienko, Ori Kam,
	Matan Azrad
  Cc: dev

The compare item allows adding flow match with comparison
result. This commit adds compare item support to the PMD
code.

Due to HW limitation:
 - Only HWS supported.
 - Only 32-bit comparison is supported.
 - Only single compare flow is supported in the flow table.
 - Only match with compare result between packet fields is
    supported.

Signed-off-by: Suanming Mou <suanmingm@nvidia.com>
Acked-by: Ori Kam <orika@nvidia.com>
---
 doc/guides/nics/features/mlx5.ini      |  1 +
 doc/guides/nics/mlx5.rst               |  7 +++
 doc/guides/rel_notes/release_24_03.rst |  2 +
 drivers/net/mlx5/mlx5_flow.h           |  3 ++
 drivers/net/mlx5/mlx5_flow_hw.c        | 73 ++++++++++++++++++++++++++
 5 files changed, 86 insertions(+)

diff --git a/doc/guides/nics/features/mlx5.ini b/doc/guides/nics/features/mlx5.ini
index 0739fe9d63..00e9348fc6 100644
--- a/doc/guides/nics/features/mlx5.ini
+++ b/doc/guides/nics/features/mlx5.ini
@@ -56,6 +56,7 @@ Usage doc            = Y
 
 [rte_flow items]
 aggr_affinity        = Y
+compare              = Y
 conntrack            = Y
 ecpri                = Y
 esp                  = Y
diff --git a/doc/guides/nics/mlx5.rst b/doc/guides/nics/mlx5.rst
index 6b52fb93c5..18b40bc22d 100644
--- a/doc/guides/nics/mlx5.rst
+++ b/doc/guides/nics/mlx5.rst
@@ -778,6 +778,13 @@ Limitations
   The flow engine of a process cannot move from active to standby mode
   if preceding active application rules are still present and vice versa.
 
+- Match with compare result item (``RTE_FLOW_ITEM_TYPE_COMPARE``):
+
+  - Only supported in HW steering(``dv_flow_en`` = 2) mode.
+  - Only single flow is supported to the flow table.
+  - Only 32-bit comparison is supported.
+  - Only match with compare result between packet fields is supported.
+
 
 Statistics
 ----------
diff --git a/doc/guides/rel_notes/release_24_03.rst b/doc/guides/rel_notes/release_24_03.rst
index 7a2dc32943..cb126407fd 100644
--- a/doc/guides/rel_notes/release_24_03.rst
+++ b/doc/guides/rel_notes/release_24_03.rst
@@ -80,6 +80,8 @@ New Features
   * Added support for Atomic Rules' TK242 packet-capture family of devices
     with PCI IDs: ``0x1024, 0x1025, 0x1026``.
 
+  * Added support for comparing result between packet fields or value.
+
 
 Removed Items
 -------------
diff --git a/drivers/net/mlx5/mlx5_flow.h b/drivers/net/mlx5/mlx5_flow.h
index ecfb04ead2..f0a11949e6 100644
--- a/drivers/net/mlx5/mlx5_flow.h
+++ b/drivers/net/mlx5/mlx5_flow.h
@@ -277,6 +277,9 @@ enum mlx5_feature_name {
 /* NSH ITEM */
 #define MLX5_FLOW_ITEM_NSH (1ull << 53)
 
+/* COMPARE ITEM */
+#define MLX5_FLOW_ITEM_COMPARE (1ull << 54)
+
 /* Outer Masks. */
 #define MLX5_FLOW_LAYER_OUTER_L3 \
 	(MLX5_FLOW_LAYER_OUTER_L3_IPV4 | MLX5_FLOW_LAYER_OUTER_L3_IPV6)
diff --git a/drivers/net/mlx5/mlx5_flow_hw.c b/drivers/net/mlx5/mlx5_flow_hw.c
index da873ae2e2..f21c22131c 100644
--- a/drivers/net/mlx5/mlx5_flow_hw.c
+++ b/drivers/net/mlx5/mlx5_flow_hw.c
@@ -426,6 +426,9 @@ flow_hw_matching_item_flags_get(const struct rte_flow_item items[])
 		case RTE_FLOW_ITEM_TYPE_GTP:
 			last_item = MLX5_FLOW_LAYER_GTP;
 			break;
+		case RTE_FLOW_ITEM_TYPE_COMPARE:
+			last_item = MLX5_FLOW_ITEM_COMPARE;
+			break;
 		default:
 			break;
 		}
@@ -4386,6 +4389,8 @@ flow_hw_table_create(struct rte_eth_dev *dev,
 			rte_errno = EINVAL;
 			goto it_error;
 		}
+		if (item_templates[i]->item_flags & MLX5_FLOW_ITEM_COMPARE)
+			matcher_attr.mode = MLX5DR_MATCHER_RESOURCE_MODE_HTABLE;
 		ret = __atomic_fetch_add(&item_templates[i]->refcnt, 1,
 					 __ATOMIC_RELAXED) + 1;
 		if (ret <= 1) {
@@ -6634,6 +6639,66 @@ flow_hw_prepend_item(const struct rte_flow_item *items,
 	return copied_items;
 }
 
+static inline bool
+flow_hw_item_compare_field_supported(enum rte_flow_field_id field)
+{
+	switch (field) {
+	case RTE_FLOW_FIELD_TAG:
+	case RTE_FLOW_FIELD_META:
+	case RTE_FLOW_FIELD_VALUE:
+		return true;
+	default:
+		break;
+	}
+	return false;
+}
+
+static int
+flow_hw_validate_item_compare(const struct rte_flow_item *item,
+			      struct rte_flow_error *error)
+{
+	const struct rte_flow_item_compare *comp_m = item->mask;
+	const struct rte_flow_item_compare *comp_v = item->spec;
+
+	if (unlikely(!comp_m))
+		return rte_flow_error_set(error, EINVAL,
+				   RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
+				   NULL,
+				   "compare item mask is missing");
+	if (comp_m->width != UINT32_MAX)
+		return rte_flow_error_set(error, EINVAL,
+				   RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
+				   NULL,
+				   "compare item only support full mask");
+	if (!flow_hw_item_compare_field_supported(comp_m->a.field) ||
+	    !flow_hw_item_compare_field_supported(comp_m->b.field))
+		return rte_flow_error_set(error, ENOTSUP,
+				   RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
+				   NULL,
+				   "compare item field not support");
+	if (comp_m->a.field == RTE_FLOW_FIELD_VALUE &&
+	    comp_m->b.field == RTE_FLOW_FIELD_VALUE)
+		return rte_flow_error_set(error, EINVAL,
+				   RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
+				   NULL,
+				   "compare between value is not valid");
+	if (comp_v) {
+		if (comp_v->operation != comp_m->operation ||
+		    comp_v->a.field != comp_m->a.field ||
+		    comp_v->b.field != comp_m->b.field)
+			return rte_flow_error_set(error, EINVAL,
+					   RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
+					   NULL,
+					   "compare item spec/mask not matching");
+		if ((comp_v->width & comp_m->width) != 32)
+			return rte_flow_error_set(error, EINVAL,
+					   RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
+					   NULL,
+					   "compare item only support full mask");
+	}
+	return 0;
+}
+
 static int
 flow_hw_pattern_validate(struct rte_eth_dev *dev,
 			 const struct rte_flow_pattern_template_attr *attr,
@@ -6644,6 +6709,7 @@ flow_hw_pattern_validate(struct rte_eth_dev *dev,
 	int i, tag_idx;
 	bool items_end = false;
 	uint32_t tag_bitmap = 0;
+	int ret;
 
 	if (!attr->ingress && !attr->egress && !attr->transfer)
 		return rte_flow_error_set(error, EINVAL, RTE_FLOW_ERROR_TYPE_ATTR, NULL,
@@ -6781,6 +6847,13 @@ flow_hw_pattern_validate(struct rte_eth_dev *dev,
 							  " attribute");
 			break;
 		}
+		case RTE_FLOW_ITEM_TYPE_COMPARE:
+		{
+			ret = flow_hw_validate_item_compare(&items[i], error);
+			if (ret)
+				return ret;
+			break;
+		}
 		case RTE_FLOW_ITEM_TYPE_VOID:
 		case RTE_FLOW_ITEM_TYPE_ETH:
 		case RTE_FLOW_ITEM_TYPE_VLAN:
-- 
2.34.1


^ permalink raw reply	[flat|nested] 66+ messages in thread

* Re: [PATCH v6 1/3] ethdev: rename action modify field data structure
  2024-02-02  0:42   ` [PATCH v6 1/3] ethdev: rename action modify field data structure Suanming Mou
@ 2024-02-05 11:23     ` Thomas Monjalon
  2024-02-05 11:49       ` Suanming Mou
  0 siblings, 1 reply; 66+ messages in thread
From: Thomas Monjalon @ 2024-02-05 11:23 UTC (permalink / raw)
  To: Suanming Mou
  Cc: ferruh.yigit, Ori Kam, Aman Singh, Yuying Zhang,
	Dariusz Sosnowski, Viacheslav Ovsiienko, Matan Azrad,
	Andrew Rybchenko, dev

02/02/2024 01:42, Suanming Mou:
> --- a/doc/guides/rel_notes/release_24_03.rst
> +++ b/doc/guides/rel_notes/release_24_03.rst
> @@ -124,6 +124,8 @@ ABI Changes
>  
>  * No ABI change that would break compatibility with 23.11.
>  
> +* ethdev: Rename the experimental ``struct rte_flow_action_modify_data`` to be ``struct rte_flow_field_data``

It should be in API change section.
Please us past tense as recommened in comments in the file.

> --- a/lib/ethdev/rte_flow.h
> +++ b/lib/ethdev/rte_flow.h
> @@ -3894,6 +3894,7 @@ struct rte_flow_action_ethdev {
>  
>  /**
>   * Field IDs for MODIFY_FIELD action.
> + * e.g. the packet field IDs used in RTE_FLOW_ACTION_TYPE_MODIFY_FIELD.

Better to give the full name in the first line,
so no need to add a second line of comment.

[...]
> - * Field description for MODIFY_FIELD action.
> + * Field description for packet field.
> + * e.g. the packet fields used in RTE_FLOW_ACTION_TYPE_MODIFY_FIELD.

Same here, can be one simple line with full name.




^ permalink raw reply	[flat|nested] 66+ messages in thread

* RE: [PATCH v6 1/3] ethdev: rename action modify field data structure
  2024-02-05 11:23     ` Thomas Monjalon
@ 2024-02-05 11:49       ` Suanming Mou
  2024-02-05 12:39         ` Thomas Monjalon
  0 siblings, 1 reply; 66+ messages in thread
From: Suanming Mou @ 2024-02-05 11:49 UTC (permalink / raw)
  To: NBU-Contact-Thomas Monjalon (EXTERNAL)
  Cc: ferruh.yigit, Ori Kam, Aman Singh, Yuying Zhang,
	Dariusz Sosnowski, Slava Ovsiienko, Matan Azrad,
	Andrew Rybchenko, dev

Hi Thomas,

> -----Original Message-----
> From: Thomas Monjalon <thomas@monjalon.net>
> Sent: Monday, February 5, 2024 7:23 PM
> To: Suanming Mou <suanmingm@nvidia.com>
> Cc: ferruh.yigit@amd.com; Ori Kam <orika@nvidia.com>; Aman Singh
> <aman.deep.singh@intel.com>; Yuying Zhang <yuying.zhang@intel.com>; Dariusz
> Sosnowski <dsosnowski@nvidia.com>; Slava Ovsiienko
> <viacheslavo@nvidia.com>; Matan Azrad <matan@nvidia.com>; Andrew
> Rybchenko <andrew.rybchenko@oktetlabs.ru>; dev@dpdk.org
> Subject: Re: [PATCH v6 1/3] ethdev: rename action modify field data structure
> 
> 02/02/2024 01:42, Suanming Mou:
> > --- a/doc/guides/rel_notes/release_24_03.rst
> > +++ b/doc/guides/rel_notes/release_24_03.rst
> > @@ -124,6 +124,8 @@ ABI Changes
> >
> >  * No ABI change that would break compatibility with 23.11.
> >
> > +* ethdev: Rename the experimental ``struct
> > +rte_flow_action_modify_data`` to be ``struct rte_flow_field_data``
> 
> It should be in API change section.
> Please us past tense as recommened in comments in the file.
OK.

> 
> > --- a/lib/ethdev/rte_flow.h
> > +++ b/lib/ethdev/rte_flow.h
> > @@ -3894,6 +3894,7 @@ struct rte_flow_action_ethdev {
> >
> >  /**
> >   * Field IDs for MODIFY_FIELD action.
> > + * e.g. the packet field IDs used in RTE_FLOW_ACTION_TYPE_MODIFY_FIELD.
> 
> Better to give the full name in the first line, so no need to add a second line of
> comment.

So maybe " Field IDs for packet field, used by RTE_FLOW_ACTION_TYPE_MODIFY_FIELD."?
But when COMPARE item to be added. It will be " Field IDs for packet field, used by RTE_FLOW_ACTION_TYPE_MODIFY_FIELD and RTE_FLOW_ITEM_TYPE_COMPARE."  And I assume that will still need a second line since it is too long.

> 
> [...]
> > - * Field description for MODIFY_FIELD action.
> > + * Field description for packet field.
> > + * e.g. the packet fields used in RTE_FLOW_ACTION_TYPE_MODIFY_FIELD.
> 
> Same here, can be one simple line with full name.
> 
> 


^ permalink raw reply	[flat|nested] 66+ messages in thread

* Re: [PATCH v6 1/3] ethdev: rename action modify field data structure
  2024-02-05 11:49       ` Suanming Mou
@ 2024-02-05 12:39         ` Thomas Monjalon
  2024-02-05 12:53           ` Suanming Mou
  0 siblings, 1 reply; 66+ messages in thread
From: Thomas Monjalon @ 2024-02-05 12:39 UTC (permalink / raw)
  To: Suanming Mou
  Cc: dev, ferruh.yigit, Ori Kam, Aman Singh, Yuying Zhang,
	Dariusz Sosnowski, Slava Ovsiienko, Matan Azrad,
	Andrew Rybchenko, dev

> > > --- a/lib/ethdev/rte_flow.h
> > > +++ b/lib/ethdev/rte_flow.h
> > > @@ -3894,6 +3894,7 @@ struct rte_flow_action_ethdev {
> > >
> > >  /**
> > >   * Field IDs for MODIFY_FIELD action.
> > > + * e.g. the packet field IDs used in RTE_FLOW_ACTION_TYPE_MODIFY_FIELD.
> > 
> > Better to give the full name in the first line, so no need to add a second line of
> > comment.
> 
> So maybe " Field IDs for packet field, used by RTE_FLOW_ACTION_TYPE_MODIFY_FIELD."?

Yes, or just
"Packet header field IDs, used by RTE_FLOW_ACTION_TYPE_MODIFY_FIELD."

> But when COMPARE item to be added. It will be " Field IDs for packet field, used by RTE_FLOW_ACTION_TYPE_MODIFY_FIELD and RTE_FLOW_ITEM_TYPE_COMPARE."  And I assume that will still need a second line since it is too long.

Yes no problem, I'm just trying to have something concise while being explicit and easy to read.




^ permalink raw reply	[flat|nested] 66+ messages in thread

* RE: [PATCH v6 1/3] ethdev: rename action modify field data structure
  2024-02-05 12:39         ` Thomas Monjalon
@ 2024-02-05 12:53           ` Suanming Mou
  0 siblings, 0 replies; 66+ messages in thread
From: Suanming Mou @ 2024-02-05 12:53 UTC (permalink / raw)
  To: NBU-Contact-Thomas Monjalon (EXTERNAL)
  Cc: dev, ferruh.yigit, Ori Kam, Aman Singh, Yuying Zhang,
	Dariusz Sosnowski, Slava Ovsiienko, Matan Azrad,
	Andrew Rybchenko, dev

Hi,

> -----Original Message-----
> From: Thomas Monjalon <thomas@monjalon.net>
> Sent: Monday, February 5, 2024 8:39 PM
> To: Suanming Mou <suanmingm@nvidia.com>
> Cc: dev@dpdk.org; ferruh.yigit@amd.com; Ori Kam <orika@nvidia.com>; Aman
> Singh <aman.deep.singh@intel.com>; Yuying Zhang <yuying.zhang@intel.com>;
> Dariusz Sosnowski <dsosnowski@nvidia.com>; Slava Ovsiienko
> <viacheslavo@nvidia.com>; Matan Azrad <matan@nvidia.com>; Andrew
> Rybchenko <andrew.rybchenko@oktetlabs.ru>; dev@dpdk.org
> Subject: Re: [PATCH v6 1/3] ethdev: rename action modify field data structure
> 
> > > > --- a/lib/ethdev/rte_flow.h
> > > > +++ b/lib/ethdev/rte_flow.h
> > > > @@ -3894,6 +3894,7 @@ struct rte_flow_action_ethdev {
> > > >
> > > >  /**
> > > >   * Field IDs for MODIFY_FIELD action.
> > > > + * e.g. the packet field IDs used in
> RTE_FLOW_ACTION_TYPE_MODIFY_FIELD.
> > >
> > > Better to give the full name in the first line, so no need to add a
> > > second line of comment.
> >
> > So maybe " Field IDs for packet field, used by
> RTE_FLOW_ACTION_TYPE_MODIFY_FIELD."?
> 
> Yes, or just
> "Packet header field IDs, used by RTE_FLOW_ACTION_TYPE_MODIFY_FIELD."
> 
> > But when COMPARE item to be added. It will be " Field IDs for packet field, used
> by RTE_FLOW_ACTION_TYPE_MODIFY_FIELD and
> RTE_FLOW_ITEM_TYPE_COMPARE."  And I assume that will still need a second
> line since it is too long.
> 
> Yes no problem, I'm just trying to have something concise while being explicit and
> easy to read.

Got it, thanks. Will update.

> 
> 


^ permalink raw reply	[flat|nested] 66+ messages in thread

* Re: [PATCH v6 2/3] ethdev: add compare item
  2024-02-02  0:42   ` [PATCH v6 2/3] ethdev: add compare item Suanming Mou
@ 2024-02-05 13:00     ` Thomas Monjalon
  2024-02-05 13:28       ` Suanming Mou
  0 siblings, 1 reply; 66+ messages in thread
From: Thomas Monjalon @ 2024-02-05 13:00 UTC (permalink / raw)
  To: Suanming Mou
  Cc: ferruh.yigit, Ori Kam, Aman Singh, Yuying Zhang, Andrew Rybchenko, dev

02/02/2024 01:42, Suanming Mou:
> --- a/doc/guides/rel_notes/release_24_03.rst
> +++ b/doc/guides/rel_notes/release_24_03.rst
> +* **Added compare flow matching criteria.**

Suggestion:
"Added flow matching with various comparisons."
Not sure how to illustrate the idea.

> +  Added ``RTE_FLOW_ITEM_TYPE_COMPARE`` to allow matching on compare

s/compare/comparison/

> +  result between the packet fields or value.

remove "the"


> --- a/lib/ethdev/rte_flow.h
> +++ b/lib/ethdev/rte_flow.h
> +	/**
> +	 * Matches the packet with compare result.

Match packet with various comparison types.

> +	 *
> +	 * See struct rte_flow_item_compare.
> +	 */
> +	RTE_FLOW_ITEM_TYPE_COMPARE,
>  };
>  
>  /**
> @@ -2365,6 +2372,182 @@ static const struct rte_flow_item_ptype rte_flow_item_ptype_mask = {
>  };
>  #endif
>  
> +/**
> + * Field IDs for packet field.
> + * e.g. the packet field IDs used in RTE_FLOW_ACTION_TYPE_MODIFY_FIELD
> + * and RTE_FLOW_ITEM_TYPE_COMPARE.
> + */
> +enum rte_flow_field_id {
> +	RTE_FLOW_FIELD_START = 0,	/**< Start of a packet. */
> +	RTE_FLOW_FIELD_MAC_DST,		/**< Destination MAC Address. */
> +	RTE_FLOW_FIELD_MAC_SRC,		/**< Source MAC Address. */
> +	RTE_FLOW_FIELD_VLAN_TYPE,	/**< VLAN Tag Identifier. */
> +	RTE_FLOW_FIELD_VLAN_ID,		/**< VLAN Identifier. */
> +	RTE_FLOW_FIELD_MAC_TYPE,	/**< EtherType. */
> +	RTE_FLOW_FIELD_IPV4_DSCP,	/**< IPv4 DSCP. */
> +	RTE_FLOW_FIELD_IPV4_TTL,	/**< IPv4 Time To Live. */
> +	RTE_FLOW_FIELD_IPV4_SRC,	/**< IPv4 Source Address. */
> +	RTE_FLOW_FIELD_IPV4_DST,	/**< IPv4 Destination Address. */
> +	RTE_FLOW_FIELD_IPV6_DSCP,	/**< IPv6 DSCP. */
> +	RTE_FLOW_FIELD_IPV6_HOPLIMIT,	/**< IPv6 Hop Limit. */
> +	RTE_FLOW_FIELD_IPV6_SRC,	/**< IPv6 Source Address. */
> +	RTE_FLOW_FIELD_IPV6_DST,	/**< IPv6 Destination Address. */
> +	RTE_FLOW_FIELD_TCP_PORT_SRC,	/**< TCP Source Port Number. */
> +	RTE_FLOW_FIELD_TCP_PORT_DST,	/**< TCP Destination Port Number. */
> +	RTE_FLOW_FIELD_TCP_SEQ_NUM,	/**< TCP Sequence Number. */
> +	RTE_FLOW_FIELD_TCP_ACK_NUM,	/**< TCP Acknowledgment Number. */
> +	RTE_FLOW_FIELD_TCP_FLAGS,	/**< TCP Flags. */
> +	RTE_FLOW_FIELD_UDP_PORT_SRC,	/**< UDP Source Port Number. */
> +	RTE_FLOW_FIELD_UDP_PORT_DST,	/**< UDP Destination Port Number. */
> +	RTE_FLOW_FIELD_VXLAN_VNI,	/**< VXLAN Network Identifier. */
> +	RTE_FLOW_FIELD_GENEVE_VNI,	/**< GENEVE Network Identifier. */
> +	RTE_FLOW_FIELD_GTP_TEID,	/**< GTP Tunnel Endpoint Identifier. */
> +	RTE_FLOW_FIELD_TAG,		/**< Tag value. */
> +	RTE_FLOW_FIELD_MARK,		/**< Mark value. */
> +	RTE_FLOW_FIELD_META,		/**< Metadata value. */
> +	RTE_FLOW_FIELD_POINTER,		/**< Memory pointer. */
> +	RTE_FLOW_FIELD_VALUE,		/**< Immediate value. */
> +	RTE_FLOW_FIELD_IPV4_ECN,	/**< IPv4 ECN. */
> +	RTE_FLOW_FIELD_IPV6_ECN,	/**< IPv6 ECN. */
> +	RTE_FLOW_FIELD_GTP_PSC_QFI,	/**< GTP QFI. */
> +	RTE_FLOW_FIELD_METER_COLOR,	/**< Meter color marker. */
> +	RTE_FLOW_FIELD_IPV6_PROTO,	/**< IPv6 next header. */
> +	RTE_FLOW_FIELD_FLEX_ITEM,	/**< Flex item. */
> +	RTE_FLOW_FIELD_HASH_RESULT,	/**< Hash result. */
> +	RTE_FLOW_FIELD_GENEVE_OPT_TYPE,	/**< GENEVE option type. */
> +	RTE_FLOW_FIELD_GENEVE_OPT_CLASS,/**< GENEVE option class. */
> +	RTE_FLOW_FIELD_GENEVE_OPT_DATA,	/**< GENEVE option data. */
> +	RTE_FLOW_FIELD_MPLS,		/**< MPLS header. */
> +	RTE_FLOW_FIELD_TCP_DATA_OFFSET,	/**< TCP data offset. */
> +	RTE_FLOW_FIELD_IPV4_IHL,	/**< IPv4 IHL. */
> +	RTE_FLOW_FIELD_IPV4_TOTAL_LEN,	/**< IPv4 total length. */
> +	RTE_FLOW_FIELD_IPV6_PAYLOAD_LEN,/**< IPv6 payload length. */
> +	RTE_FLOW_FIELD_RANDOM		/**< Random value. */
> +};

You should use spaces for aligmnent of the comments.

[...]
> +struct rte_flow_field_data {
> +	enum rte_flow_field_id field; /**< Field or memory type ID. */
> +	union {
> +		struct {
> +			/** Encapsulation level and tag index or flex item handle. */
> +			union {
> +				struct {
> +					/**
> +					 * Packet encapsulation level containing
> +					 * the field to modify.
> +					 *
> +					 * - @p 0 requests the default behavior.
> +					 *   Depending on the packet type, it
> +					 *   can mean outermost, innermost or
> +					 *   anything in between.
> +					 *
> +					 *   It basically stands for the
> +					 *   innermost encapsulation level.
> +					 *   Modification can be performed
> +					 *   according to PMD and device
> +					 *   capabilities.
> +					 *
> +					 * - @p 1 requests modification to be
> +					 *   performed on the outermost packet
> +					 *   encapsulation level.
> +					 *
> +					 * - @p 2 and subsequent values request
> +					 *   modification to be performed on
> +					 *   the specified inner packet
> +					 *   encapsulation level, from
> +					 *   outermost to innermost (lower to
> +					 *   higher values).
> +					 *
> +					 * Values other than @p 0 are not
> +					 * necessarily supported.
> +					 *
> +					 * @note that for MPLS field,
> +					 * encapsulation level also include
> +					 * tunnel since MPLS may appear in
> +					 * outer, inner or tunnel.
> +					 */
> +					uint8_t level;
> +					union {
> +						/**
> +						 * Tag index array inside
> +						 * encapsulation level.
> +						 * Used for VLAN, MPLS or TAG types.
> +						 */
> +						uint8_t tag_index;
> +						/**
> +						 * Geneve option identifier.
> +						 * Relevant only for
> +						 * RTE_FLOW_FIELD_GENEVE_OPT_XXXX
> +						 * modification type.
> +						 */
> +						struct {
> +							/**
> +							 * Geneve option type.
> +							 */
> +							uint8_t type;
> +							/**
> +							 * Geneve option class.
> +							 */
> +							rte_be16_t class_id;
> +						};
> +					};
> +				};
> +				struct rte_flow_item_flex_handle *flex_handle;
> +			};
> +			/** Number of bits to skip from a field. */
> +			uint32_t offset;
> +		};
> +		/**
> +		 * Immediate value for RTE_FLOW_FIELD_VALUE, presented in the
> +		 * same byte order and length as in relevant rte_flow_item_xxx.
> +		 * The immediate source bitfield offset is inherited from
> +		 * the destination's one.
> +		 */
> +		uint8_t value[16];
> +		/**
> +		 * Memory address for RTE_FLOW_FIELD_POINTER, memory layout
> +		 * should be the same as for relevant field in the
> +		 * rte_flow_item_xxx structure.
> +		 */
> +		void *pvalue;
> +	};
> +};
> +
> +/**
> + * Expected operation types for compare item.
> + */
> +enum rte_flow_item_compare_op {
> +	RTE_FLOW_ITEM_COMPARE_EQ,	/* Compare result equal. */
> +	RTE_FLOW_ITEM_COMPARE_NE,	/* Compare result not equal. */
> +	RTE_FLOW_ITEM_COMPARE_LT,	/* Compare result less than. */
> +	RTE_FLOW_ITEM_COMPARE_LE,	/* Compare result less than or equal. */
> +	RTE_FLOW_ITEM_COMPARE_GT,	/* Compare result great than. */
> +	RTE_FLOW_ITEM_COMPARE_GE,	/* Compare result great than or equal. */
> +};

It's a pity we cannot easily what changed because it moved.
Maybe make the move in a separate patch before changing it?



^ permalink raw reply	[flat|nested] 66+ messages in thread

* RE: [PATCH v6 2/3] ethdev: add compare item
  2024-02-05 13:00     ` Thomas Monjalon
@ 2024-02-05 13:28       ` Suanming Mou
  2024-02-05 14:09         ` Thomas Monjalon
  0 siblings, 1 reply; 66+ messages in thread
From: Suanming Mou @ 2024-02-05 13:28 UTC (permalink / raw)
  To: NBU-Contact-Thomas Monjalon (EXTERNAL)
  Cc: ferruh.yigit, Ori Kam, Aman Singh, Yuying Zhang, Andrew Rybchenko, dev

Hi Thomas,

> -----Original Message-----
> From: Thomas Monjalon <thomas@monjalon.net>
> Sent: Monday, February 5, 2024 9:01 PM
> To: Suanming Mou <suanmingm@nvidia.com>
> Cc: ferruh.yigit@amd.com; Ori Kam <orika@nvidia.com>; Aman Singh
> <aman.deep.singh@intel.com>; Yuying Zhang <yuying.zhang@intel.com>;
> Andrew Rybchenko <andrew.rybchenko@oktetlabs.ru>; dev@dpdk.org
> Subject: Re: [PATCH v6 2/3] ethdev: add compare item
> 
> 02/02/2024 01:42, Suanming Mou:
> > --- a/doc/guides/rel_notes/release_24_03.rst
> > +++ b/doc/guides/rel_notes/release_24_03.rst
> > +* **Added compare flow matching criteria.**
> 
> Suggestion:
> "Added flow matching with various comparisons."
> Not sure how to illustrate the idea.

What about " Added flow matching with various comparison results." ?

> 
> > +  Added ``RTE_FLOW_ITEM_TYPE_COMPARE`` to allow matching on compare
> 
> s/compare/comparison/
> 
> > +  result between the packet fields or value.
> 
> remove "the"
> 
> 
> > --- a/lib/ethdev/rte_flow.h
> > +++ b/lib/ethdev/rte_flow.h
> > +	/**
> > +	 * Matches the packet with compare result.
> 
> Match packet with various comparison types.
> 
> > +	 *
> > +	 * See struct rte_flow_item_compare.
> > +	 */
> > +	RTE_FLOW_ITEM_TYPE_COMPARE,
> >  };
> >
> >  /**
> > @@ -2365,6 +2372,182 @@ static const struct rte_flow_item_ptype
> > rte_flow_item_ptype_mask = {  };  #endif
> >
> > +/**
> > + * Field IDs for packet field.
> > + * e.g. the packet field IDs used in
> > +RTE_FLOW_ACTION_TYPE_MODIFY_FIELD
> > + * and RTE_FLOW_ITEM_TYPE_COMPARE.
> > + */
> > +enum rte_flow_field_id {
> > +	RTE_FLOW_FIELD_START = 0,	/**< Start of a packet. */
> > +	RTE_FLOW_FIELD_MAC_DST,		/**< Destination MAC Address.
> */
> > +	RTE_FLOW_FIELD_MAC_SRC,		/**< Source MAC Address. */
> > +	RTE_FLOW_FIELD_VLAN_TYPE,	/**< VLAN Tag Identifier. */
> > +	RTE_FLOW_FIELD_VLAN_ID,		/**< VLAN Identifier. */
> > +	RTE_FLOW_FIELD_MAC_TYPE,	/**< EtherType. */
> > +	RTE_FLOW_FIELD_IPV4_DSCP,	/**< IPv4 DSCP. */
> > +	RTE_FLOW_FIELD_IPV4_TTL,	/**< IPv4 Time To Live. */
> > +	RTE_FLOW_FIELD_IPV4_SRC,	/**< IPv4 Source Address. */
> > +	RTE_FLOW_FIELD_IPV4_DST,	/**< IPv4 Destination Address. */
> > +	RTE_FLOW_FIELD_IPV6_DSCP,	/**< IPv6 DSCP. */
> > +	RTE_FLOW_FIELD_IPV6_HOPLIMIT,	/**< IPv6 Hop Limit. */
> > +	RTE_FLOW_FIELD_IPV6_SRC,	/**< IPv6 Source Address. */
> > +	RTE_FLOW_FIELD_IPV6_DST,	/**< IPv6 Destination Address. */
> > +	RTE_FLOW_FIELD_TCP_PORT_SRC,	/**< TCP Source Port Number.
> */
> > +	RTE_FLOW_FIELD_TCP_PORT_DST,	/**< TCP Destination Port
> Number. */
> > +	RTE_FLOW_FIELD_TCP_SEQ_NUM,	/**< TCP Sequence Number. */
> > +	RTE_FLOW_FIELD_TCP_ACK_NUM,	/**< TCP Acknowledgment
> Number. */
> > +	RTE_FLOW_FIELD_TCP_FLAGS,	/**< TCP Flags. */
> > +	RTE_FLOW_FIELD_UDP_PORT_SRC,	/**< UDP Source Port Number.
> */
> > +	RTE_FLOW_FIELD_UDP_PORT_DST,	/**< UDP Destination Port
> Number. */
> > +	RTE_FLOW_FIELD_VXLAN_VNI,	/**< VXLAN Network Identifier. */
> > +	RTE_FLOW_FIELD_GENEVE_VNI,	/**< GENEVE Network
> Identifier. */
> > +	RTE_FLOW_FIELD_GTP_TEID,	/**< GTP Tunnel Endpoint Identifier. */
> > +	RTE_FLOW_FIELD_TAG,		/**< Tag value. */
> > +	RTE_FLOW_FIELD_MARK,		/**< Mark value. */
> > +	RTE_FLOW_FIELD_META,		/**< Metadata value. */
> > +	RTE_FLOW_FIELD_POINTER,		/**< Memory pointer. */
> > +	RTE_FLOW_FIELD_VALUE,		/**< Immediate value. */
> > +	RTE_FLOW_FIELD_IPV4_ECN,	/**< IPv4 ECN. */
> > +	RTE_FLOW_FIELD_IPV6_ECN,	/**< IPv6 ECN. */
> > +	RTE_FLOW_FIELD_GTP_PSC_QFI,	/**< GTP QFI. */
> > +	RTE_FLOW_FIELD_METER_COLOR,	/**< Meter color marker. */
> > +	RTE_FLOW_FIELD_IPV6_PROTO,	/**< IPv6 next header. */
> > +	RTE_FLOW_FIELD_FLEX_ITEM,	/**< Flex item. */
> > +	RTE_FLOW_FIELD_HASH_RESULT,	/**< Hash result. */
> > +	RTE_FLOW_FIELD_GENEVE_OPT_TYPE,	/**< GENEVE option type. */
> > +	RTE_FLOW_FIELD_GENEVE_OPT_CLASS,/**< GENEVE option class. */
> > +	RTE_FLOW_FIELD_GENEVE_OPT_DATA,	/**< GENEVE option data. */
> > +	RTE_FLOW_FIELD_MPLS,		/**< MPLS header. */
> > +	RTE_FLOW_FIELD_TCP_DATA_OFFSET,	/**< TCP data offset. */
> > +	RTE_FLOW_FIELD_IPV4_IHL,	/**< IPv4 IHL. */
> > +	RTE_FLOW_FIELD_IPV4_TOTAL_LEN,	/**< IPv4 total length. */
> > +	RTE_FLOW_FIELD_IPV6_PAYLOAD_LEN,/**< IPv6 payload length. */
> > +	RTE_FLOW_FIELD_RANDOM		/**< Random value. */
> > +};
> 
> You should use spaces for aligmnent of the comments.

Sorry, the original code is not using spaces. 
Anyway, never mind, since I touched that, let me format them with spaces.

> 
> [...]
> > +struct rte_flow_field_data {
> > +	enum rte_flow_field_id field; /**< Field or memory type ID. */
> > +	union {
> > +		struct {
> > +			/** Encapsulation level and tag index or flex item
> handle. */
> > +			union {
> > +				struct {
> > +					/**
> > +					 * Packet encapsulation level containing
> > +					 * the field to modify.
> > +					 *
> > +					 * - @p 0 requests the default behavior.
> > +					 *   Depending on the packet type, it
> > +					 *   can mean outermost, innermost or
> > +					 *   anything in between.
> > +					 *
> > +					 *   It basically stands for the
> > +					 *   innermost encapsulation level.
> > +					 *   Modification can be performed
> > +					 *   according to PMD and device
> > +					 *   capabilities.
> > +					 *
> > +					 * - @p 1 requests modification to be
> > +					 *   performed on the outermost packet
> > +					 *   encapsulation level.
> > +					 *
> > +					 * - @p 2 and subsequent values
> request
> > +					 *   modification to be performed on
> > +					 *   the specified inner packet
> > +					 *   encapsulation level, from
> > +					 *   outermost to innermost (lower to
> > +					 *   higher values).
> > +					 *
> > +					 * Values other than @p 0 are not
> > +					 * necessarily supported.
> > +					 *
> > +					 * @note that for MPLS field,
> > +					 * encapsulation level also include
> > +					 * tunnel since MPLS may appear in
> > +					 * outer, inner or tunnel.
> > +					 */
> > +					uint8_t level;
> > +					union {
> > +						/**
> > +						 * Tag index array inside
> > +						 * encapsulation level.
> > +						 * Used for VLAN, MPLS or TAG
> types.
> > +						 */
> > +						uint8_t tag_index;
> > +						/**
> > +						 * Geneve option identifier.
> > +						 * Relevant only for
> > +						 *
> RTE_FLOW_FIELD_GENEVE_OPT_XXXX
> > +						 * modification type.
> > +						 */
> > +						struct {
> > +							/**
> > +							 * Geneve option type.
> > +							 */
> > +							uint8_t type;
> > +							/**
> > +							 * Geneve option class.
> > +							 */
> > +							rte_be16_t class_id;
> > +						};
> > +					};
> > +				};
> > +				struct rte_flow_item_flex_handle *flex_handle;
> > +			};
> > +			/** Number of bits to skip from a field. */
> > +			uint32_t offset;
> > +		};
> > +		/**
> > +		 * Immediate value for RTE_FLOW_FIELD_VALUE, presented in
> the
> > +		 * same byte order and length as in relevant rte_flow_item_xxx.
> > +		 * The immediate source bitfield offset is inherited from
> > +		 * the destination's one.
> > +		 */
> > +		uint8_t value[16];
> > +		/**
> > +		 * Memory address for RTE_FLOW_FIELD_POINTER, memory
> layout
> > +		 * should be the same as for relevant field in the
> > +		 * rte_flow_item_xxx structure.
> > +		 */
> > +		void *pvalue;
> > +	};
> > +};
> > +
> > +/**
> > + * Expected operation types for compare item.
> > + */
> > +enum rte_flow_item_compare_op {
> > +	RTE_FLOW_ITEM_COMPARE_EQ,	/* Compare result equal. */
> > +	RTE_FLOW_ITEM_COMPARE_NE,	/* Compare result not equal. */
> > +	RTE_FLOW_ITEM_COMPARE_LT,	/* Compare result less than. */
> > +	RTE_FLOW_ITEM_COMPARE_LE,	/* Compare result less than or
> equal. */
> > +	RTE_FLOW_ITEM_COMPARE_GT,	/* Compare result great than.
> */
> > +	RTE_FLOW_ITEM_COMPARE_GE,	/* Compare result great than or
> equal. */
> > +};
> 
> It's a pity we cannot easily what changed because it moved.
> Maybe make the move in a separate patch before changing it?


Since you are the second one concern about that, I will split the move to a separate patch before.

> 


^ permalink raw reply	[flat|nested] 66+ messages in thread

* Re: [PATCH v6 2/3] ethdev: add compare item
  2024-02-05 13:28       ` Suanming Mou
@ 2024-02-05 14:09         ` Thomas Monjalon
  2024-02-06  1:26           ` Suanming Mou
  0 siblings, 1 reply; 66+ messages in thread
From: Thomas Monjalon @ 2024-02-05 14:09 UTC (permalink / raw)
  To: Suanming Mou
  Cc: ferruh.yigit, Ori Kam, Aman Singh, Yuying Zhang, Andrew Rybchenko, dev

05/02/2024 14:28, Suanming Mou:
> From: Thomas Monjalon <thomas@monjalon.net>
> > 02/02/2024 01:42, Suanming Mou:
> > > --- a/doc/guides/rel_notes/release_24_03.rst
> > > +++ b/doc/guides/rel_notes/release_24_03.rst
> > > +* **Added compare flow matching criteria.**
> > 
> > Suggestion:
> > "Added flow matching with various comparisons."
> > Not sure how to illustrate the idea.
> 
> What about " Added flow matching with various comparison results." ?

I am thinking we are comparing packet fields,
and you say we match comparison results,
which at the end is the same :)

I feel not talking about results is clearer but I may be wrong.
You choose.



^ permalink raw reply	[flat|nested] 66+ messages in thread

* RE: [PATCH v6 2/3] ethdev: add compare item
  2024-02-05 14:09         ` Thomas Monjalon
@ 2024-02-06  1:26           ` Suanming Mou
  0 siblings, 0 replies; 66+ messages in thread
From: Suanming Mou @ 2024-02-06  1:26 UTC (permalink / raw)
  To: NBU-Contact-Thomas Monjalon (EXTERNAL)
  Cc: ferruh.yigit, Ori Kam, Aman Singh, Yuying Zhang, Andrew Rybchenko, dev



> -----Original Message-----
> From: Thomas Monjalon <thomas@monjalon.net>
> Sent: Monday, February 5, 2024 10:09 PM
> To: Suanming Mou <suanmingm@nvidia.com>
> Cc: ferruh.yigit@amd.com; Ori Kam <orika@nvidia.com>; Aman Singh
> <aman.deep.singh@intel.com>; Yuying Zhang <yuying.zhang@intel.com>;
> Andrew Rybchenko <andrew.rybchenko@oktetlabs.ru>; dev@dpdk.org
> Subject: Re: [PATCH v6 2/3] ethdev: add compare item
> 
> 05/02/2024 14:28, Suanming Mou:
> > From: Thomas Monjalon <thomas@monjalon.net>
> > > 02/02/2024 01:42, Suanming Mou:
> > > > --- a/doc/guides/rel_notes/release_24_03.rst
> > > > +++ b/doc/guides/rel_notes/release_24_03.rst
> > > > +* **Added compare flow matching criteria.**
> > >
> > > Suggestion:
> > > "Added flow matching with various comparisons."
> > > Not sure how to illustrate the idea.
> >
> > What about " Added flow matching with various comparison results." ?
> 
> I am thinking we are comparing packet fields, and you say we match comparison
> results, which at the end is the same :)
> 
> I feel not talking about results is clearer but I may be wrong.
> You choose.

OK, thanks, I prefer to keep results since user will be able to specify the comparison result.

> 


^ permalink raw reply	[flat|nested] 66+ messages in thread

* [PATCH v7 0/4] ethdev: add RTE_FLOW_ITEM_TYPE_COMPARE
  2023-12-14  3:12 [PATCH 0/2] ethdev: add RTE_FLOW_ITEM_TYPE_COMPARE Suanming Mou
                   ` (5 preceding siblings ...)
  2024-02-02  0:42 ` [PATCH v6 " Suanming Mou
@ 2024-02-06  2:06 ` Suanming Mou
  2024-02-06  2:06   ` [PATCH v7 1/4] ethdev: rename action modify field data structure Suanming Mou
                     ` (4 more replies)
  6 siblings, 5 replies; 66+ messages in thread
From: Suanming Mou @ 2024-02-06  2:06 UTC (permalink / raw)
  To: thomas, ferruh.yigit; +Cc: dev, orika

The new item type is added for the case user wants to match traffic
based on packet field compare result with other fields or immediate
value.

e.g. take advantage the compare item user will be able to accumulate
a IPv4/TCP packet's TCP data_offset and IPv4 IHL field to a tag
register, then compare the tag register with IPv4 header total length
to understand the packet has payload or not.

The supported operations can be as below:
 - RTE_FLOW_ITEM_COMPARE_EQ (equal)
 - RTE_FLOW_ITEM_COMPARE_NE (not equal)
 - RTE_FLOW_ITEM_COMPARE_LT (less than)
 - RTE_FLOW_ITEM_COMPARE_LE (less than or equal)
 - RTE_FLOW_ITEM_COMPARE_GT (great than)
 - RTE_FLOW_ITEM_COMPARE_GE (great than or equal)

V7:
 - Moved release notes to API.
 - Optimize comment descriptions.

V6:
 - fix typo and style issue.
 - adjust flow_field description.

V5:
 - rebase on top of next-net
 - add sample detail for rte_flow_field.

V4:
 - rebase on top of the latest version.
 - move ACTION_MODIFY_PATTERN_SIZE and modify_field_ids rename
   to first patch.
 - add comparison flow create sample in testpmd_funcs.rst.

V3:
 - fix code style missing empty line in rte_flow.rst.
 - fix missing the ABI change release notes.

V2:
 - Since modify field data struct is experiment, rename modify
   field data directly instead of adding new flow field struct.


Suanming Mou (4):
  ethdev: rename action modify field data structure
  ethdev: move flow field data structures
  ethdev: add compare item
  net/mlx5: add compare item support

 app/test-pmd/cmdline_flow.c                 | 416 +++++++++++++++++++-
 doc/guides/nics/features/default.ini        |   1 +
 doc/guides/nics/features/mlx5.ini           |   1 +
 doc/guides/nics/mlx5.rst                    |   7 +
 doc/guides/prog_guide/rte_flow.rst          |   9 +-
 doc/guides/rel_notes/release_24_03.rst      |  10 +
 doc/guides/testpmd_app_ug/testpmd_funcs.rst |  24 ++
 drivers/net/mlx5/mlx5_flow.c                |   4 +-
 drivers/net/mlx5/mlx5_flow.h                |   9 +-
 drivers/net/mlx5/mlx5_flow_dv.c             |  10 +-
 drivers/net/mlx5/mlx5_flow_hw.c             |  73 ++++
 lib/ethdev/rte_flow.c                       |   1 +
 lib/ethdev/rte_flow.h                       | 330 +++++++++-------
 13 files changed, 726 insertions(+), 169 deletions(-)

-- 
2.34.1


^ permalink raw reply	[flat|nested] 66+ messages in thread

* [PATCH v7 1/4] ethdev: rename action modify field data structure
  2024-02-06  2:06 ` [PATCH v7 0/4] ethdev: add RTE_FLOW_ITEM_TYPE_COMPARE Suanming Mou
@ 2024-02-06  2:06   ` Suanming Mou
  2024-02-06 21:23     ` Ferruh Yigit
  2024-02-06  2:06   ` [PATCH v7 2/4] ethdev: move flow field data structures Suanming Mou
                     ` (3 subsequent siblings)
  4 siblings, 1 reply; 66+ messages in thread
From: Suanming Mou @ 2024-02-06  2:06 UTC (permalink / raw)
  To: thomas, ferruh.yigit, Ori Kam, Aman Singh, Yuying Zhang,
	Dariusz Sosnowski, Viacheslav Ovsiienko, Matan Azrad,
	Andrew Rybchenko
  Cc: dev

Current rte_flow_action_modify_data struct describes the pkt
field perfectly and is used only in action.

It is planned to be used for item as well. This commit renames
it to "rte_flow_field_data" making it compatible to be used by item.

Signed-off-by: Suanming Mou <suanmingm@nvidia.com>
Acked-by: Ori Kam <orika@nvidia.com>
Acked-by: Andrew Rybchenko <andrew.rybchenko@oktetlabs.ru>
---
 app/test-pmd/cmdline_flow.c            | 22 +++++++++++-----------
 doc/guides/prog_guide/rte_flow.rst     |  2 +-
 doc/guides/rel_notes/release_24_03.rst |  3 +++
 drivers/net/mlx5/mlx5_flow.c           |  4 ++--
 drivers/net/mlx5/mlx5_flow.h           |  6 +++---
 drivers/net/mlx5/mlx5_flow_dv.c        | 10 +++++-----
 lib/ethdev/rte_flow.h                  | 10 +++++-----
 7 files changed, 30 insertions(+), 27 deletions(-)

diff --git a/app/test-pmd/cmdline_flow.c b/app/test-pmd/cmdline_flow.c
index 4d26e81d26..35030b5c47 100644
--- a/app/test-pmd/cmdline_flow.c
+++ b/app/test-pmd/cmdline_flow.c
@@ -744,13 +744,13 @@ enum index {
 #define ITEM_RAW_SIZE \
 	(sizeof(struct rte_flow_item_raw) + ITEM_RAW_PATTERN_SIZE)
 
-/** Maximum size for external pattern in struct rte_flow_action_modify_data. */
-#define ACTION_MODIFY_PATTERN_SIZE 32
+/** Maximum size for external pattern in struct rte_flow_field_data. */
+#define FLOW_FIELD_PATTERN_SIZE 32
 
 /** Storage size for struct rte_flow_action_modify_field including pattern. */
 #define ACTION_MODIFY_SIZE \
 	(sizeof(struct rte_flow_action_modify_field) + \
-	ACTION_MODIFY_PATTERN_SIZE)
+	FLOW_FIELD_PATTERN_SIZE)
 
 /** Maximum number of queue indices in struct rte_flow_action_rss. */
 #define ACTION_RSS_QUEUE_NUM 128
@@ -944,7 +944,7 @@ static const char *const modify_field_ops[] = {
 	"set", "add", "sub", NULL
 };
 
-static const char *const modify_field_ids[] = {
+static const char *const flow_field_ids[] = {
 	"start", "mac_dst", "mac_src",
 	"vlan_type", "vlan_id", "mac_type",
 	"ipv4_dscp", "ipv4_ttl", "ipv4_src", "ipv4_dst",
@@ -6995,7 +6995,7 @@ static const struct token token_list[] = {
 			     ARGS_ENTRY_ARB(0, 0),
 			     ARGS_ENTRY_ARB
 				(sizeof(struct rte_flow_action_modify_field),
-				 ACTION_MODIFY_PATTERN_SIZE)),
+				 FLOW_FIELD_PATTERN_SIZE)),
 		.call = parse_vc_conf,
 	},
 	[ACTION_MODIFY_FIELD_WIDTH] = {
@@ -9821,10 +9821,10 @@ parse_vc_modify_field_id(struct context *ctx, const struct token *token,
 	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))
+	for (i = 0; flow_field_ids[i]; ++i)
+		if (!strcmp_partial(flow_field_ids[i], str, len))
 			break;
-	if (!modify_field_ids[i])
+	if (!flow_field_ids[i])
 		return -1;
 	if (!ctx->object)
 		return len;
@@ -12051,10 +12051,10 @@ comp_set_modify_field_id(struct context *ctx, const struct token *token,
 
 	RTE_SET_USED(token);
 	if (!buf)
-		return RTE_DIM(modify_field_ids);
-	if (ent >= RTE_DIM(modify_field_ids) - 1)
+		return RTE_DIM(flow_field_ids);
+	if (ent >= RTE_DIM(flow_field_ids) - 1)
 		return -1;
-	name = modify_field_ids[ent];
+	name = flow_field_ids[ent];
 	if (ctx->curr == ACTION_MODIFY_FIELD_SRC_TYPE ||
 	    (strcmp(name, "pointer") && strcmp(name, "value")))
 		return strlcpy(buf, name, size);
diff --git a/doc/guides/prog_guide/rte_flow.rst b/doc/guides/prog_guide/rte_flow.rst
index 7af329bd93..9192d6ab01 100644
--- a/doc/guides/prog_guide/rte_flow.rst
+++ b/doc/guides/prog_guide/rte_flow.rst
@@ -3185,7 +3185,7 @@ destination offset as ``48``, and provide immediate value ``0xXXXX85XX``.
    | ``width``     | number of bits to use   |
    +---------------+-------------------------+
 
-.. _table_rte_flow_action_modify_data:
+.. _table_rte_flow_field_data:
 
 .. table:: destination/source field definition
 
diff --git a/doc/guides/rel_notes/release_24_03.rst b/doc/guides/rel_notes/release_24_03.rst
index 84d3144215..222a091e8b 100644
--- a/doc/guides/rel_notes/release_24_03.rst
+++ b/doc/guides/rel_notes/release_24_03.rst
@@ -106,6 +106,9 @@ API Changes
 
 * gso: ``rte_gso_segment`` now returns -ENOTSUP for unknown protocols.
 
+* ethdev: Renamed structure ``rte_flow_action_modify_data`` to be
+  ``rte_flow_field_data`` for more generic usage.
+
 
 ABI Changes
 -----------
diff --git a/drivers/net/mlx5/mlx5_flow.c b/drivers/net/mlx5/mlx5_flow.c
index 85e8c77c81..5788a7fb57 100644
--- a/drivers/net/mlx5/mlx5_flow.c
+++ b/drivers/net/mlx5/mlx5_flow.c
@@ -2493,7 +2493,7 @@ mlx5_validate_action_ct(struct rte_eth_dev *dev,
  * Validate the level value for modify field action.
  *
  * @param[in] data
- *   Pointer to the rte_flow_action_modify_data structure either src or dst.
+ *   Pointer to the rte_flow_field_data structure either src or dst.
  * @param[out] error
  *   Pointer to error structure.
  *
@@ -2501,7 +2501,7 @@ mlx5_validate_action_ct(struct rte_eth_dev *dev,
  *   0 on success, a negative errno value otherwise and rte_errno is set.
  */
 int
-flow_validate_modify_field_level(const struct rte_flow_action_modify_data *data,
+flow_validate_modify_field_level(const struct rte_flow_field_data *data,
 				 struct rte_flow_error *error)
 {
 	if (data->level == 0)
diff --git a/drivers/net/mlx5/mlx5_flow.h b/drivers/net/mlx5/mlx5_flow.h
index 6dde9de688..ecfb04ead2 100644
--- a/drivers/net/mlx5/mlx5_flow.h
+++ b/drivers/net/mlx5/mlx5_flow.h
@@ -1121,7 +1121,7 @@ flow_items_to_tunnel(const struct rte_flow_item items[])
  *   Tag array index.
  */
 static inline uint8_t
-flow_tag_index_get(const struct rte_flow_action_modify_data *data)
+flow_tag_index_get(const struct rte_flow_field_data *data)
 {
 	return data->tag_index ? data->tag_index : data->level;
 }
@@ -2523,7 +2523,7 @@ int mlx5_flow_validate_action_default_miss(uint64_t action_flags,
 				const struct rte_flow_attr *attr,
 				struct rte_flow_error *error);
 int flow_validate_modify_field_level
-			(const struct rte_flow_action_modify_data *data,
+			(const struct rte_flow_field_data *data,
 			 struct rte_flow_error *error);
 int mlx5_flow_item_acceptable(const struct rte_flow_item *item,
 			      const uint8_t *mask,
@@ -2828,7 +2828,7 @@ size_t flow_dv_get_item_hdr_len(const enum rte_flow_item_type item_type);
 int flow_dv_convert_encap_data(const struct rte_flow_item *items, uint8_t *buf,
 			   size_t *size, struct rte_flow_error *error);
 void mlx5_flow_field_id_to_modify_info
-		(const struct rte_flow_action_modify_data *data,
+		(const struct rte_flow_field_data *data,
 		 struct field_modify_info *info, uint32_t *mask,
 		 uint32_t width, struct rte_eth_dev *dev,
 		 const struct rte_flow_attr *attr, struct rte_flow_error *error);
diff --git a/drivers/net/mlx5/mlx5_flow_dv.c b/drivers/net/mlx5/mlx5_flow_dv.c
index 115d730317..52620be262 100644
--- a/drivers/net/mlx5/mlx5_flow_dv.c
+++ b/drivers/net/mlx5/mlx5_flow_dv.c
@@ -1441,7 +1441,7 @@ flow_modify_info_mask_32_masked(uint32_t length, uint32_t off, uint32_t post_mas
 }
 
 static __rte_always_inline enum mlx5_modification_field
-mlx5_mpls_modi_field_get(const struct rte_flow_action_modify_data *data)
+mlx5_mpls_modi_field_get(const struct rte_flow_field_data *data)
 {
 	return MLX5_MODI_IN_MPLS_LABEL_0 + data->tag_index;
 }
@@ -1449,7 +1449,7 @@ mlx5_mpls_modi_field_get(const struct rte_flow_action_modify_data *data)
 static void
 mlx5_modify_flex_item(const struct rte_eth_dev *dev,
 		      const struct mlx5_flex_item *flex,
-		      const struct rte_flow_action_modify_data *data,
+		      const struct rte_flow_field_data *data,
 		      struct field_modify_info *info,
 		      uint32_t *mask, uint32_t width)
 {
@@ -1573,7 +1573,7 @@ mlx5_modify_flex_item(const struct rte_eth_dev *dev,
 
 void
 mlx5_flow_field_id_to_modify_info
-		(const struct rte_flow_action_modify_data *data,
+		(const struct rte_flow_field_data *data,
 		 struct field_modify_info *info, uint32_t *mask,
 		 uint32_t width, struct rte_eth_dev *dev,
 		 const struct rte_flow_attr *attr, struct rte_flow_error *error)
@@ -5284,8 +5284,8 @@ flow_dv_validate_action_modify_field(struct rte_eth_dev *dev,
 	struct mlx5_sh_config *config = &priv->sh->config;
 	struct mlx5_hca_attr *hca_attr = &priv->sh->cdev->config.hca_attr;
 	const struct rte_flow_action_modify_field *conf = action->conf;
-	const struct rte_flow_action_modify_data *src_data = &conf->src;
-	const struct rte_flow_action_modify_data *dst_data = &conf->dst;
+	const struct rte_flow_field_data *src_data = &conf->src;
+	const struct rte_flow_field_data *dst_data = &conf->dst;
 	uint32_t dst_width, src_width, width = conf->width;
 
 	ret = flow_dv_validate_action_modify_hdr(action_flags, action, error);
diff --git a/lib/ethdev/rte_flow.h b/lib/ethdev/rte_flow.h
index 1dded812ec..eb46cfe09e 100644
--- a/lib/ethdev/rte_flow.h
+++ b/lib/ethdev/rte_flow.h
@@ -3893,7 +3893,7 @@ struct rte_flow_action_ethdev {
 };
 
 /**
- * Field IDs for MODIFY_FIELD action.
+ * Packet header field IDs, used by RTE_FLOW_ACTION_TYPE_MODIFY_FIELD.
  */
 enum rte_flow_field_id {
 	RTE_FLOW_FIELD_START = 0,	/**< Start of a packet. */
@@ -3947,9 +3947,9 @@ enum rte_flow_field_id {
  * @warning
  * @b EXPERIMENTAL: this structure may change without prior notice
  *
- * Field description for MODIFY_FIELD action.
+ * Packet header field descriptions, used by RTE_FLOW_ACTION_TYPE_MODIFY_FIELD.
  */
-struct rte_flow_action_modify_data {
+struct rte_flow_field_data {
 	enum rte_flow_field_id field; /**< Field or memory type ID. */
 	union {
 		struct {
@@ -4058,8 +4058,8 @@ enum rte_flow_modify_op {
  */
 struct rte_flow_action_modify_field {
 	enum rte_flow_modify_op operation; /**< Operation to perform. */
-	struct rte_flow_action_modify_data dst; /**< Destination field. */
-	struct rte_flow_action_modify_data src; /**< Source field. */
+	struct rte_flow_field_data dst; /**< Destination field. */
+	struct rte_flow_field_data src; /**< Source field. */
 	uint32_t width; /**< Number of bits to use from a source field. */
 };
 
-- 
2.34.1


^ permalink raw reply	[flat|nested] 66+ messages in thread

* [PATCH v7 2/4] ethdev: move flow field data structures
  2024-02-06  2:06 ` [PATCH v7 0/4] ethdev: add RTE_FLOW_ITEM_TYPE_COMPARE Suanming Mou
  2024-02-06  2:06   ` [PATCH v7 1/4] ethdev: rename action modify field data structure Suanming Mou
@ 2024-02-06  2:06   ` Suanming Mou
  2024-02-06 21:23     ` Ferruh Yigit
  2024-02-06  2:06   ` [PATCH v7 3/4] ethdev: add compare item Suanming Mou
                     ` (2 subsequent siblings)
  4 siblings, 1 reply; 66+ messages in thread
From: Suanming Mou @ 2024-02-06  2:06 UTC (permalink / raw)
  To: thomas, ferruh.yigit, Ori Kam, Andrew Rybchenko; +Cc: dev

As flow field relevant data structures will be used by both actions and
items, this commit moves the relevant data structures up to item parts.

Signed-off-by: Suanming Mou <suanmingm@nvidia.com>
---
 lib/ethdev/rte_flow.h | 290 +++++++++++++++++++++---------------------
 1 file changed, 145 insertions(+), 145 deletions(-)

diff --git a/lib/ethdev/rte_flow.h b/lib/ethdev/rte_flow.h
index eb46cfe09e..958eb01a80 100644
--- a/lib/ethdev/rte_flow.h
+++ b/lib/ethdev/rte_flow.h
@@ -2365,6 +2365,151 @@ static const struct rte_flow_item_ptype rte_flow_item_ptype_mask = {
 };
 #endif
 
+/**
+ * Packet header field IDs, used by RTE_FLOW_ACTION_TYPE_MODIFY_FIELD.
+ */
+enum rte_flow_field_id {
+	RTE_FLOW_FIELD_START = 0,       /**< Start of a packet. */
+	RTE_FLOW_FIELD_MAC_DST,         /**< Destination MAC Address. */
+	RTE_FLOW_FIELD_MAC_SRC,         /**< Source MAC Address. */
+	RTE_FLOW_FIELD_VLAN_TYPE,       /**< VLAN Tag Identifier. */
+	RTE_FLOW_FIELD_VLAN_ID,         /**< VLAN Identifier. */
+	RTE_FLOW_FIELD_MAC_TYPE,        /**< EtherType. */
+	RTE_FLOW_FIELD_IPV4_DSCP,       /**< IPv4 DSCP. */
+	RTE_FLOW_FIELD_IPV4_TTL,        /**< IPv4 Time To Live. */
+	RTE_FLOW_FIELD_IPV4_SRC,        /**< IPv4 Source Address. */
+	RTE_FLOW_FIELD_IPV4_DST,        /**< IPv4 Destination Address. */
+	RTE_FLOW_FIELD_IPV6_DSCP,       /**< IPv6 DSCP. */
+	RTE_FLOW_FIELD_IPV6_HOPLIMIT,   /**< IPv6 Hop Limit. */
+	RTE_FLOW_FIELD_IPV6_SRC,        /**< IPv6 Source Address. */
+	RTE_FLOW_FIELD_IPV6_DST,        /**< IPv6 Destination Address. */
+	RTE_FLOW_FIELD_TCP_PORT_SRC,    /**< TCP Source Port Number. */
+	RTE_FLOW_FIELD_TCP_PORT_DST,    /**< TCP Destination Port Number. */
+	RTE_FLOW_FIELD_TCP_SEQ_NUM,     /**< TCP Sequence Number. */
+	RTE_FLOW_FIELD_TCP_ACK_NUM,     /**< TCP Acknowledgment Number. */
+	RTE_FLOW_FIELD_TCP_FLAGS,       /**< TCP Flags. */
+	RTE_FLOW_FIELD_UDP_PORT_SRC,    /**< UDP Source Port Number. */
+	RTE_FLOW_FIELD_UDP_PORT_DST,    /**< UDP Destination Port Number. */
+	RTE_FLOW_FIELD_VXLAN_VNI,       /**< VXLAN Network Identifier. */
+	RTE_FLOW_FIELD_GENEVE_VNI,      /**< GENEVE Network Identifier. */
+	RTE_FLOW_FIELD_GTP_TEID,        /**< GTP Tunnel Endpoint Identifier. */
+	RTE_FLOW_FIELD_TAG,             /**< Tag value. */
+	RTE_FLOW_FIELD_MARK,            /**< Mark value. */
+	RTE_FLOW_FIELD_META,            /**< Metadata value. */
+	RTE_FLOW_FIELD_POINTER,         /**< Memory pointer. */
+	RTE_FLOW_FIELD_VALUE,           /**< Immediate value. */
+	RTE_FLOW_FIELD_IPV4_ECN,        /**< IPv4 ECN. */
+	RTE_FLOW_FIELD_IPV6_ECN,        /**< IPv6 ECN. */
+	RTE_FLOW_FIELD_GTP_PSC_QFI,     /**< GTP QFI. */
+	RTE_FLOW_FIELD_METER_COLOR,     /**< Meter color marker. */
+	RTE_FLOW_FIELD_IPV6_PROTO,      /**< IPv6 next header. */
+	RTE_FLOW_FIELD_FLEX_ITEM,       /**< Flex item. */
+	RTE_FLOW_FIELD_HASH_RESULT,     /**< Hash result. */
+	RTE_FLOW_FIELD_GENEVE_OPT_TYPE, /**< GENEVE option type. */
+	RTE_FLOW_FIELD_GENEVE_OPT_CLASS,/**< GENEVE option class. */
+	RTE_FLOW_FIELD_GENEVE_OPT_DATA, /**< GENEVE option data. */
+	RTE_FLOW_FIELD_MPLS,            /**< MPLS header. */
+	RTE_FLOW_FIELD_TCP_DATA_OFFSET, /**< TCP data offset. */
+	RTE_FLOW_FIELD_IPV4_IHL,        /**< IPv4 IHL. */
+	RTE_FLOW_FIELD_IPV4_TOTAL_LEN,  /**< IPv4 total length. */
+	RTE_FLOW_FIELD_IPV6_PAYLOAD_LEN,/**< IPv6 payload length. */
+	RTE_FLOW_FIELD_RANDOM           /**< Random value. */
+};
+
+/**
+ * @warning
+ * @b EXPERIMENTAL: this structure may change without prior notice
+ *
+ * Packet header field descriptions, used by RTE_FLOW_ACTION_TYPE_MODIFY_FIELD.
+ */
+struct rte_flow_field_data {
+	enum rte_flow_field_id field; /**< Field or memory type ID. */
+	union {
+		struct {
+			/** Encapsulation level and tag index or flex item handle. */
+			union {
+				struct {
+					/**
+					 * Packet encapsulation level containing
+					 * the field to modify.
+					 *
+					 * - @p 0 requests the default behavior.
+					 *   Depending on the packet type, it
+					 *   can mean outermost, innermost or
+					 *   anything in between.
+					 *
+					 *   It basically stands for the
+					 *   innermost encapsulation level.
+					 *   Modification can be performed
+					 *   according to PMD and device
+					 *   capabilities.
+					 *
+					 * - @p 1 requests modification to be
+					 *   performed on the outermost packet
+					 *   encapsulation level.
+					 *
+					 * - @p 2 and subsequent values request
+					 *   modification to be performed on
+					 *   the specified inner packet
+					 *   encapsulation level, from
+					 *   outermost to innermost (lower to
+					 *   higher values).
+					 *
+					 * Values other than @p 0 are not
+					 * necessarily supported.
+					 *
+					 * @note that for MPLS field,
+					 * encapsulation level also include
+					 * tunnel since MPLS may appear in
+					 * outer, inner or tunnel.
+					 */
+					uint8_t level;
+					union {
+						/**
+						 * Tag index array inside
+						 * encapsulation level.
+						 * Used for VLAN, MPLS or TAG types.
+						 */
+						uint8_t tag_index;
+						/**
+						 * Geneve option identifier.
+						 * Relevant only for
+						 * RTE_FLOW_FIELD_GENEVE_OPT_XXXX
+						 * modification type.
+						 */
+						struct {
+							/**
+							 * Geneve option type.
+							 */
+							uint8_t type;
+							/**
+							 * Geneve option class.
+							 */
+							rte_be16_t class_id;
+						};
+					};
+				};
+				struct rte_flow_item_flex_handle *flex_handle;
+			};
+			/** Number of bits to skip from a field. */
+			uint32_t offset;
+		};
+		/**
+		 * Immediate value for RTE_FLOW_FIELD_VALUE, presented in the
+		 * same byte order and length as in relevant rte_flow_item_xxx.
+		 * The immediate source bitfield offset is inherited from
+		 * the destination's one.
+		 */
+		uint8_t value[16];
+		/**
+		 * Memory address for RTE_FLOW_FIELD_POINTER, memory layout
+		 * should be the same as for relevant field in the
+		 * rte_flow_item_xxx structure.
+		 */
+		void *pvalue;
+	};
+};
+
 /**
  * Action types.
  *
@@ -3892,151 +4037,6 @@ struct rte_flow_action_ethdev {
 	uint16_t port_id; /**< ethdev port ID */
 };
 
-/**
- * Packet header field IDs, used by RTE_FLOW_ACTION_TYPE_MODIFY_FIELD.
- */
-enum rte_flow_field_id {
-	RTE_FLOW_FIELD_START = 0,	/**< Start of a packet. */
-	RTE_FLOW_FIELD_MAC_DST,		/**< Destination MAC Address. */
-	RTE_FLOW_FIELD_MAC_SRC,		/**< Source MAC Address. */
-	RTE_FLOW_FIELD_VLAN_TYPE,	/**< VLAN Tag Identifier. */
-	RTE_FLOW_FIELD_VLAN_ID,		/**< VLAN Identifier. */
-	RTE_FLOW_FIELD_MAC_TYPE,	/**< EtherType. */
-	RTE_FLOW_FIELD_IPV4_DSCP,	/**< IPv4 DSCP. */
-	RTE_FLOW_FIELD_IPV4_TTL,	/**< IPv4 Time To Live. */
-	RTE_FLOW_FIELD_IPV4_SRC,	/**< IPv4 Source Address. */
-	RTE_FLOW_FIELD_IPV4_DST,	/**< IPv4 Destination Address. */
-	RTE_FLOW_FIELD_IPV6_DSCP,	/**< IPv6 DSCP. */
-	RTE_FLOW_FIELD_IPV6_HOPLIMIT,	/**< IPv6 Hop Limit. */
-	RTE_FLOW_FIELD_IPV6_SRC,	/**< IPv6 Source Address. */
-	RTE_FLOW_FIELD_IPV6_DST,	/**< IPv6 Destination Address. */
-	RTE_FLOW_FIELD_TCP_PORT_SRC,	/**< TCP Source Port Number. */
-	RTE_FLOW_FIELD_TCP_PORT_DST,	/**< TCP Destination Port Number. */
-	RTE_FLOW_FIELD_TCP_SEQ_NUM,	/**< TCP Sequence Number. */
-	RTE_FLOW_FIELD_TCP_ACK_NUM,	/**< TCP Acknowledgment Number. */
-	RTE_FLOW_FIELD_TCP_FLAGS,	/**< TCP Flags. */
-	RTE_FLOW_FIELD_UDP_PORT_SRC,	/**< UDP Source Port Number. */
-	RTE_FLOW_FIELD_UDP_PORT_DST,	/**< UDP Destination Port Number. */
-	RTE_FLOW_FIELD_VXLAN_VNI,	/**< VXLAN Network Identifier. */
-	RTE_FLOW_FIELD_GENEVE_VNI,	/**< GENEVE Network Identifier. */
-	RTE_FLOW_FIELD_GTP_TEID,	/**< GTP Tunnel Endpoint Identifier. */
-	RTE_FLOW_FIELD_TAG,		/**< Tag value. */
-	RTE_FLOW_FIELD_MARK,		/**< Mark value. */
-	RTE_FLOW_FIELD_META,		/**< Metadata value. */
-	RTE_FLOW_FIELD_POINTER,		/**< Memory pointer. */
-	RTE_FLOW_FIELD_VALUE,		/**< Immediate value. */
-	RTE_FLOW_FIELD_IPV4_ECN,	/**< IPv4 ECN. */
-	RTE_FLOW_FIELD_IPV6_ECN,	/**< IPv6 ECN. */
-	RTE_FLOW_FIELD_GTP_PSC_QFI,	/**< GTP QFI. */
-	RTE_FLOW_FIELD_METER_COLOR,	/**< Meter color marker. */
-	RTE_FLOW_FIELD_IPV6_PROTO,	/**< IPv6 next header. */
-	RTE_FLOW_FIELD_FLEX_ITEM,	/**< Flex item. */
-	RTE_FLOW_FIELD_HASH_RESULT,	/**< Hash result. */
-	RTE_FLOW_FIELD_GENEVE_OPT_TYPE,	/**< GENEVE option type. */
-	RTE_FLOW_FIELD_GENEVE_OPT_CLASS,/**< GENEVE option class. */
-	RTE_FLOW_FIELD_GENEVE_OPT_DATA,	/**< GENEVE option data. */
-	RTE_FLOW_FIELD_MPLS,		/**< MPLS header. */
-	RTE_FLOW_FIELD_TCP_DATA_OFFSET,	/**< TCP data offset. */
-	RTE_FLOW_FIELD_IPV4_IHL,	/**< IPv4 IHL. */
-	RTE_FLOW_FIELD_IPV4_TOTAL_LEN,	/**< IPv4 total length. */
-	RTE_FLOW_FIELD_IPV6_PAYLOAD_LEN,/**< IPv6 payload length. */
-	RTE_FLOW_FIELD_RANDOM		/**< Random value. */
-};
-
-/**
- * @warning
- * @b EXPERIMENTAL: this structure may change without prior notice
- *
- * Packet header field descriptions, used by RTE_FLOW_ACTION_TYPE_MODIFY_FIELD.
- */
-struct rte_flow_field_data {
-	enum rte_flow_field_id field; /**< Field or memory type ID. */
-	union {
-		struct {
-			/** Encapsulation level and tag index or flex item handle. */
-			union {
-				struct {
-					/**
-					 * Packet encapsulation level containing
-					 * the field to modify.
-					 *
-					 * - @p 0 requests the default behavior.
-					 *   Depending on the packet type, it
-					 *   can mean outermost, innermost or
-					 *   anything in between.
-					 *
-					 *   It basically stands for the
-					 *   innermost encapsulation level.
-					 *   Modification can be performed
-					 *   according to PMD and device
-					 *   capabilities.
-					 *
-					 * - @p 1 requests modification to be
-					 *   performed on the outermost packet
-					 *   encapsulation level.
-					 *
-					 * - @p 2 and subsequent values request
-					 *   modification to be performed on
-					 *   the specified inner packet
-					 *   encapsulation level, from
-					 *   outermost to innermost (lower to
-					 *   higher values).
-					 *
-					 * Values other than @p 0 are not
-					 * necessarily supported.
-					 *
-					 * @note that for MPLS field,
-					 * encapsulation level also include
-					 * tunnel since MPLS may appear in
-					 * outer, inner or tunnel.
-					 */
-					uint8_t level;
-					union {
-						/**
-						 * Tag index array inside
-						 * encapsulation level.
-						 * Used for VLAN, MPLS or TAG types.
-						 */
-						uint8_t tag_index;
-						/**
-						 * Geneve option identifier.
-						 * Relevant only for
-						 * RTE_FLOW_FIELD_GENEVE_OPT_XXXX
-						 * modification type.
-						 */
-						struct {
-							/**
-							 * Geneve option type.
-							 */
-							uint8_t type;
-							/**
-							 * Geneve option class.
-							 */
-							rte_be16_t class_id;
-						};
-					};
-				};
-				struct rte_flow_item_flex_handle *flex_handle;
-			};
-			/** Number of bits to skip from a field. */
-			uint32_t offset;
-		};
-		/**
-		 * Immediate value for RTE_FLOW_FIELD_VALUE, presented in the
-		 * same byte order and length as in relevant rte_flow_item_xxx.
-		 * The immediate source bitfield offset is inherited from
-		 * the destination's one.
-		 */
-		uint8_t value[16];
-		/**
-		 * Memory address for RTE_FLOW_FIELD_POINTER, memory layout
-		 * should be the same as for relevant field in the
-		 * rte_flow_item_xxx structure.
-		 */
-		void *pvalue;
-	};
-};
-
 /**
  * Operation types for MODIFY_FIELD action.
  */
-- 
2.34.1


^ permalink raw reply	[flat|nested] 66+ messages in thread

* [PATCH v7 3/4] ethdev: add compare item
  2024-02-06  2:06 ` [PATCH v7 0/4] ethdev: add RTE_FLOW_ITEM_TYPE_COMPARE Suanming Mou
  2024-02-06  2:06   ` [PATCH v7 1/4] ethdev: rename action modify field data structure Suanming Mou
  2024-02-06  2:06   ` [PATCH v7 2/4] ethdev: move flow field data structures Suanming Mou
@ 2024-02-06  2:06   ` Suanming Mou
  2024-02-06 21:24     ` Ferruh Yigit
  2024-02-06  2:06   ` [PATCH v7 4/4] net/mlx5: add compare item support Suanming Mou
  2024-02-06 21:24   ` [PATCH v7 0/4] ethdev: add RTE_FLOW_ITEM_TYPE_COMPARE Ferruh Yigit
  4 siblings, 1 reply; 66+ messages in thread
From: Suanming Mou @ 2024-02-06  2:06 UTC (permalink / raw)
  To: thomas, ferruh.yigit, Ori Kam, Aman Singh, Yuying Zhang,
	Andrew Rybchenko
  Cc: dev

The new item type is added for the case user wants to match traffic
based on packet field compare result with other fields or immediate
value.

e.g. take advantage the compare item user will be able to accumulate
a IPv4/TCP packet's TCP data_offset and IPv4 IHL field to a tag
register, then compare the tag register with IPv4 header total length
to understand the packet has payload or not.

The supported operations can be as below:
 - RTE_FLOW_ITEM_COMPARE_EQ (equal)
 - RTE_FLOW_ITEM_COMPARE_NE (not equal)
 - RTE_FLOW_ITEM_COMPARE_LT (less than)
 - RTE_FLOW_ITEM_COMPARE_LE (less than or equal)
 - RTE_FLOW_ITEM_COMPARE_GT (great than)
 - RTE_FLOW_ITEM_COMPARE_GE (great than or equal)

A sample for create the comparison flow:
flow pattern_template 0 create ingress pattern_template_id 1 template \
	compare op mask le a_type mask tag a_tag_index mask 1 b_type \
	mask tag b_tag_index mask 2 width mask 0xffffffff / end
flow actions_template 0 create ingress actions_template_id 1 template \
	count / drop / end mask count / drop  / end
flow template_table 0 create table_id 1 group 2 priority 1  ingress \
	rules_number 1 pattern_template 1 actions_template 1
flow queue 0 create 0 template_table 1 pattern_template 0 \
	actions_template 0 postpone no pattern compare op is le \
	a_type is tag a_tag_index is 1 b_type is tag b_tag_index is 2 \
	width is 32 / end actions count / drop / end

Signed-off-by: Suanming Mou <suanmingm@nvidia.com>
Acked-by: Ori Kam <orika@nvidia.com>
Acked-by: Andrew Rybchenko <andrew.rybchenko@oktetlabs.ru>
---
 app/test-pmd/cmdline_flow.c                 | 394 ++++++++++++++++++++
 doc/guides/nics/features/default.ini        |   1 +
 doc/guides/prog_guide/rte_flow.rst          |   7 +
 doc/guides/rel_notes/release_24_03.rst      |   5 +
 doc/guides/testpmd_app_ug/testpmd_funcs.rst |  24 ++
 lib/ethdev/rte_flow.c                       |   1 +
 lib/ethdev/rte_flow.h                       |  40 +-
 7 files changed, 470 insertions(+), 2 deletions(-)

diff --git a/app/test-pmd/cmdline_flow.c b/app/test-pmd/cmdline_flow.c
index 35030b5c47..06f8c82342 100644
--- a/app/test-pmd/cmdline_flow.c
+++ b/app/test-pmd/cmdline_flow.c
@@ -545,6 +545,28 @@ enum index {
 	ITEM_PTYPE,
 	ITEM_PTYPE_VALUE,
 	ITEM_NSH,
+	ITEM_COMPARE,
+	ITEM_COMPARE_OP,
+	ITEM_COMPARE_OP_VALUE,
+	ITEM_COMPARE_FIELD_A_TYPE,
+	ITEM_COMPARE_FIELD_A_TYPE_VALUE,
+	ITEM_COMPARE_FIELD_A_LEVEL,
+	ITEM_COMPARE_FIELD_A_LEVEL_VALUE,
+	ITEM_COMPARE_FIELD_A_TAG_INDEX,
+	ITEM_COMPARE_FIELD_A_TYPE_ID,
+	ITEM_COMPARE_FIELD_A_CLASS_ID,
+	ITEM_COMPARE_FIELD_A_OFFSET,
+	ITEM_COMPARE_FIELD_B_TYPE,
+	ITEM_COMPARE_FIELD_B_TYPE_VALUE,
+	ITEM_COMPARE_FIELD_B_LEVEL,
+	ITEM_COMPARE_FIELD_B_LEVEL_VALUE,
+	ITEM_COMPARE_FIELD_B_TAG_INDEX,
+	ITEM_COMPARE_FIELD_B_TYPE_ID,
+	ITEM_COMPARE_FIELD_B_CLASS_ID,
+	ITEM_COMPARE_FIELD_B_OFFSET,
+	ITEM_COMPARE_FIELD_B_VALUE,
+	ITEM_COMPARE_FIELD_B_POINTER,
+	ITEM_COMPARE_FIELD_WIDTH,
 
 	/* Validate/create actions. */
 	ACTIONS,
@@ -744,6 +766,10 @@ enum index {
 #define ITEM_RAW_SIZE \
 	(sizeof(struct rte_flow_item_raw) + ITEM_RAW_PATTERN_SIZE)
 
+static const char *const compare_ops[] = {
+	"eq", "ne", "lt", "le", "gt", "ge", NULL
+};
+
 /** Maximum size for external pattern in struct rte_flow_field_data. */
 #define FLOW_FIELD_PATTERN_SIZE 32
 
@@ -1596,6 +1622,7 @@ static const enum index next_item[] = {
 	ITEM_IB_BTH,
 	ITEM_PTYPE,
 	ITEM_NSH,
+	ITEM_COMPARE,
 	END_SET,
 	ZERO,
 };
@@ -2133,6 +2160,38 @@ static const enum index item_nsh[] = {
 	ZERO,
 };
 
+static const enum index item_compare_field[] = {
+	ITEM_COMPARE_OP,
+	ITEM_COMPARE_FIELD_A_TYPE,
+	ITEM_COMPARE_FIELD_B_TYPE,
+	ITEM_NEXT,
+	ZERO,
+};
+
+static const enum index compare_field_a[] = {
+	ITEM_COMPARE_FIELD_A_TYPE,
+	ITEM_COMPARE_FIELD_A_LEVEL,
+	ITEM_COMPARE_FIELD_A_TAG_INDEX,
+	ITEM_COMPARE_FIELD_A_TYPE_ID,
+	ITEM_COMPARE_FIELD_A_CLASS_ID,
+	ITEM_COMPARE_FIELD_A_OFFSET,
+	ITEM_COMPARE_FIELD_B_TYPE,
+	ZERO,
+};
+
+static const enum index compare_field_b[] = {
+	ITEM_COMPARE_FIELD_B_TYPE,
+	ITEM_COMPARE_FIELD_B_LEVEL,
+	ITEM_COMPARE_FIELD_B_TAG_INDEX,
+	ITEM_COMPARE_FIELD_B_TYPE_ID,
+	ITEM_COMPARE_FIELD_B_CLASS_ID,
+	ITEM_COMPARE_FIELD_B_OFFSET,
+	ITEM_COMPARE_FIELD_B_VALUE,
+	ITEM_COMPARE_FIELD_B_POINTER,
+	ITEM_COMPARE_FIELD_WIDTH,
+	ZERO,
+};
+
 static const enum index next_action[] = {
 	ACTION_END,
 	ACTION_VOID,
@@ -2882,6 +2941,24 @@ comp_quota_update_name(struct context *ctx, const struct token *token,
 static int
 comp_qu_mode_name(struct context *ctx, const struct token *token,
 		  unsigned int ent, char *buf, unsigned int size);
+static int
+comp_set_compare_field_id(struct context *ctx, const struct token *token,
+			  unsigned int ent, char *buf, unsigned int size);
+static int
+comp_set_compare_op(struct context *ctx, const struct token *token,
+		    unsigned int ent, char *buf, unsigned int size);
+static int
+parse_vc_compare_op(struct context *ctx, const struct token *token,
+			 const char *str, unsigned int len, void *buf,
+			 unsigned int size);
+static int
+parse_vc_compare_field_id(struct context *ctx, const struct token *token,
+			  const char *str, unsigned int len, void *buf,
+			  unsigned int size);
+static int
+parse_vc_compare_field_level(struct context *ctx, const struct token *token,
+			     const char *str, unsigned int len, void *buf,
+			     unsigned int size);
 
 struct indlst_conf {
 	uint32_t id;
@@ -6016,6 +6093,174 @@ static const struct token token_list[] = {
 		.next = NEXT(item_nsh),
 		.call = parse_vc,
 	},
+	[ITEM_COMPARE] = {
+		.name = "compare",
+		.help = "match with the comparison result",
+		.priv = PRIV_ITEM(COMPARE, sizeof(struct rte_flow_item_compare)),
+		.next = NEXT(NEXT_ENTRY(ITEM_COMPARE_OP)),
+		.call = parse_vc,
+	},
+	[ITEM_COMPARE_OP] = {
+		.name = "op",
+		.help = "operation type",
+		.next = NEXT(item_compare_field,
+			NEXT_ENTRY(ITEM_COMPARE_OP_VALUE), item_param),
+		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_compare, operation)),
+	},
+	[ITEM_COMPARE_OP_VALUE] = {
+		.name = "{operation}",
+		.help = "operation type value",
+		.call = parse_vc_compare_op,
+		.comp = comp_set_compare_op,
+	},
+	[ITEM_COMPARE_FIELD_A_TYPE] = {
+		.name = "a_type",
+		.help = "compared field type",
+		.next = NEXT(compare_field_a,
+			NEXT_ENTRY(ITEM_COMPARE_FIELD_A_TYPE_VALUE), item_param),
+		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_compare, a.field)),
+	},
+	[ITEM_COMPARE_FIELD_A_TYPE_VALUE] = {
+		.name = "{a_type}",
+		.help = "compared field type value",
+		.call = parse_vc_compare_field_id,
+		.comp = comp_set_compare_field_id,
+	},
+	[ITEM_COMPARE_FIELD_A_LEVEL] = {
+		.name = "a_level",
+		.help = "compared field level",
+		.next = NEXT(compare_field_a,
+			     NEXT_ENTRY(ITEM_COMPARE_FIELD_A_LEVEL_VALUE), item_param),
+		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_compare, a.level)),
+	},
+	[ITEM_COMPARE_FIELD_A_LEVEL_VALUE] = {
+		.name = "{a_level}",
+		.help = "compared field level value",
+		.call = parse_vc_compare_field_level,
+		.comp = comp_none,
+	},
+	[ITEM_COMPARE_FIELD_A_TAG_INDEX] = {
+		.name = "a_tag_index",
+		.help = "compared field tag array",
+		.next = NEXT(compare_field_a,
+			     NEXT_ENTRY(COMMON_UNSIGNED), item_param),
+		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_compare,
+					a.tag_index)),
+	},
+	[ITEM_COMPARE_FIELD_A_TYPE_ID] = {
+		.name = "a_type_id",
+		.help = "compared field type ID",
+		.next = NEXT(compare_field_a,
+			     NEXT_ENTRY(COMMON_UNSIGNED), item_param),
+		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_compare,
+					a.type)),
+	},
+	[ITEM_COMPARE_FIELD_A_CLASS_ID] = {
+		.name = "a_class",
+		.help = "compared field class ID",
+		.next = NEXT(compare_field_a,
+			     NEXT_ENTRY(COMMON_UNSIGNED), item_param),
+		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_compare,
+					     a.class_id)),
+	},
+	[ITEM_COMPARE_FIELD_A_OFFSET] = {
+		.name = "a_offset",
+		.help = "compared field bit offset",
+		.next = NEXT(compare_field_a,
+			     NEXT_ENTRY(COMMON_UNSIGNED), item_param),
+		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_compare,
+					a.offset)),
+	},
+	[ITEM_COMPARE_FIELD_B_TYPE] = {
+		.name = "b_type",
+		.help = "comparator field type",
+		.next = NEXT(compare_field_b,
+			NEXT_ENTRY(ITEM_COMPARE_FIELD_B_TYPE_VALUE), item_param),
+		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_compare,
+					b.field)),
+	},
+	[ITEM_COMPARE_FIELD_B_TYPE_VALUE] = {
+		.name = "{b_type}",
+		.help = "comparator field type value",
+		.call = parse_vc_compare_field_id,
+		.comp = comp_set_compare_field_id,
+	},
+	[ITEM_COMPARE_FIELD_B_LEVEL] = {
+		.name = "b_level",
+		.help = "comparator field level",
+		.next = NEXT(compare_field_b,
+			     NEXT_ENTRY(ITEM_COMPARE_FIELD_B_LEVEL_VALUE), item_param),
+		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_compare,
+					b.level)),
+	},
+	[ITEM_COMPARE_FIELD_B_LEVEL_VALUE] = {
+		.name = "{b_level}",
+		.help = "comparator field level value",
+		.call = parse_vc_compare_field_level,
+		.comp = comp_none,
+	},
+	[ITEM_COMPARE_FIELD_B_TAG_INDEX] = {
+		.name = "b_tag_index",
+		.help = "comparator field tag array",
+		.next = NEXT(compare_field_b,
+			     NEXT_ENTRY(COMMON_UNSIGNED), item_param),
+		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_compare,
+					b.tag_index)),
+	},
+	[ITEM_COMPARE_FIELD_B_TYPE_ID] = {
+		.name = "b_type_id",
+		.help = "comparator field type ID",
+		.next = NEXT(compare_field_b,
+			     NEXT_ENTRY(COMMON_UNSIGNED), item_param),
+		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_compare,
+					b.type)),
+	},
+	[ITEM_COMPARE_FIELD_B_CLASS_ID] = {
+		.name = "b_class",
+		.help = "comparator field class ID",
+		.next = NEXT(compare_field_b,
+			     NEXT_ENTRY(COMMON_UNSIGNED), item_param),
+		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_compare,
+					     b.class_id)),
+	},
+	[ITEM_COMPARE_FIELD_B_OFFSET] = {
+		.name = "b_offset",
+		.help = "comparator field bit offset",
+		.next = NEXT(compare_field_b,
+			     NEXT_ENTRY(COMMON_UNSIGNED), item_param),
+		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_compare,
+					b.offset)),
+	},
+	[ITEM_COMPARE_FIELD_B_VALUE] = {
+		.name = "b_value",
+		.help = "comparator immediate value",
+		.next = NEXT(compare_field_b,
+			     NEXT_ENTRY(COMMON_HEX), item_param),
+		.args = ARGS(ARGS_ENTRY_ARB(0, 0),
+			     ARGS_ENTRY_ARB(0, 0),
+			     ARGS_ENTRY(struct rte_flow_item_compare,
+					b.value)),
+	},
+	[ITEM_COMPARE_FIELD_B_POINTER] = {
+		.name = "b_ptr",
+		.help = "pointer to comparator immediate value",
+		.next = NEXT(compare_field_b,
+			     NEXT_ENTRY(COMMON_HEX), item_param),
+		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_compare,
+					b.pvalue),
+			     ARGS_ENTRY_ARB(0, 0),
+			     ARGS_ENTRY_ARB
+				(sizeof(struct rte_flow_item_compare),
+				 FLOW_FIELD_PATTERN_SIZE)),
+	},
+	[ITEM_COMPARE_FIELD_WIDTH] = {
+		.name = "width",
+		.help = "number of bits to compare",
+		.next = NEXT(item_compare_field,
+			NEXT_ENTRY(COMMON_UNSIGNED), item_param),
+		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_compare,
+					width)),
+	},
 
 	/* Validate/create actions. */
 	[ACTIONS] = {
@@ -8452,6 +8697,122 @@ parse_vc_item_l2tpv2_type(struct context *ctx, const struct token *token,
 	return len;
 }
 
+/** Parse operation for compare match item. */
+static int
+parse_vc_compare_op(struct context *ctx, const struct token *token,
+			 const char *str, unsigned int len, void *buf,
+			 unsigned int size)
+{
+	struct rte_flow_item_compare *compare_item;
+	unsigned int i;
+
+	(void)token;
+	(void)buf;
+	(void)size;
+	if (ctx->curr != ITEM_COMPARE_OP_VALUE)
+		return -1;
+	for (i = 0; compare_ops[i]; ++i)
+		if (!strcmp_partial(compare_ops[i], str, len))
+			break;
+	if (!compare_ops[i])
+		return -1;
+	if (!ctx->object)
+		return len;
+	compare_item = ctx->object;
+	compare_item->operation = (enum rte_flow_item_compare_op)i;
+	return len;
+}
+
+/** Parse id for compare match item. */
+static int
+parse_vc_compare_field_id(struct context *ctx, const struct token *token,
+			  const char *str, unsigned int len, void *buf,
+			  unsigned int size)
+{
+	struct rte_flow_item_compare *compare_item;
+	unsigned int i;
+
+	(void)token;
+	(void)buf;
+	(void)size;
+	if (ctx->curr != ITEM_COMPARE_FIELD_A_TYPE_VALUE &&
+		ctx->curr != ITEM_COMPARE_FIELD_B_TYPE_VALUE)
+		return -1;
+	for (i = 0; flow_field_ids[i]; ++i)
+		if (!strcmp_partial(flow_field_ids[i], str, len))
+			break;
+	if (!flow_field_ids[i])
+		return -1;
+	if (!ctx->object)
+		return len;
+	compare_item = ctx->object;
+	if (ctx->curr == ITEM_COMPARE_FIELD_A_TYPE_VALUE)
+		compare_item->a.field = (enum rte_flow_field_id)i;
+	else
+		compare_item->b.field = (enum rte_flow_field_id)i;
+	return len;
+}
+
+/** Parse level for compare match item. */
+static int
+parse_vc_compare_field_level(struct context *ctx, const struct token *token,
+			     const char *str, unsigned int len, void *buf,
+			     unsigned int size)
+{
+	struct rte_flow_item_compare *compare_item;
+	struct flex_item *fp = NULL;
+	uint32_t val;
+	struct buffer *out = buf;
+	char *end;
+
+	(void)token;
+	(void)size;
+	if (ctx->curr != ITEM_COMPARE_FIELD_A_LEVEL_VALUE &&
+		ctx->curr != ITEM_COMPARE_FIELD_B_LEVEL_VALUE)
+		return -1;
+	if (!ctx->object)
+		return len;
+	compare_item = ctx->object;
+	errno = 0;
+	val = strtoumax(str, &end, 0);
+	if (errno || (size_t)(end - str) != len)
+		return -1;
+	/* No need to validate action template mask value */
+	if (out->args.vc.masks) {
+		if (ctx->curr == ITEM_COMPARE_FIELD_A_LEVEL_VALUE)
+			compare_item->a.level = val;
+		else
+			compare_item->b.level = val;
+		return len;
+	}
+	if ((ctx->curr == ITEM_COMPARE_FIELD_A_LEVEL_VALUE &&
+		compare_item->a.field == RTE_FLOW_FIELD_FLEX_ITEM) ||
+		(ctx->curr == ITEM_COMPARE_FIELD_B_LEVEL_VALUE &&
+		compare_item->b.field == RTE_FLOW_FIELD_FLEX_ITEM)) {
+		if (val >= FLEX_MAX_PARSERS_NUM) {
+			printf("Bad flex item handle\n");
+			return -1;
+		}
+		fp = flex_items[ctx->port][val];
+		if (!fp) {
+			printf("Bad flex item handle\n");
+			return -1;
+		}
+	}
+	if (ctx->curr == ITEM_COMPARE_FIELD_A_LEVEL_VALUE) {
+		if (compare_item->a.field != RTE_FLOW_FIELD_FLEX_ITEM)
+			compare_item->a.level = val;
+		else
+			compare_item->a.flex_handle = fp->flex_handle;
+	} else if (ctx->curr == ITEM_COMPARE_FIELD_B_LEVEL_VALUE) {
+		if (compare_item->b.field != RTE_FLOW_FIELD_FLEX_ITEM)
+			compare_item->b.level = val;
+		else
+			compare_item->b.flex_handle = fp->flex_handle;
+	}
+	return len;
+}
+
 /** Parse meter color action type. */
 static int
 parse_vc_action_meter_color_type(struct context *ctx, const struct token *token,
@@ -11938,6 +12299,39 @@ comp_rule_id(struct context *ctx, const struct token *token,
 	return i;
 }
 
+/** Complete operation for compare match item. */
+static int
+comp_set_compare_op(struct context *ctx, const struct token *token,
+		    unsigned int ent, char *buf, unsigned int size)
+{
+	RTE_SET_USED(ctx);
+	RTE_SET_USED(token);
+	if (!buf)
+		return RTE_DIM(compare_ops);
+	if (ent < RTE_DIM(compare_ops) - 1)
+		return strlcpy(buf, compare_ops[ent], size);
+	return -1;
+}
+
+/** Complete field id for compare match item. */
+static int
+comp_set_compare_field_id(struct context *ctx, const struct token *token,
+			  unsigned int ent, char *buf, unsigned int size)
+{
+	const char *name;
+
+	RTE_SET_USED(token);
+	if (!buf)
+		return RTE_DIM(flow_field_ids);
+	if (ent >= RTE_DIM(flow_field_ids) - 1)
+		return -1;
+	name = flow_field_ids[ent];
+	if (ctx->curr == ITEM_COMPARE_FIELD_B_TYPE ||
+	    (strcmp(name, "pointer") && strcmp(name, "value")))
+		return strlcpy(buf, name, size);
+	return -1;
+}
+
 /** Complete type field for RSS action. */
 static int
 comp_vc_action_rss_type(struct context *ctx, const struct token *token,
diff --git a/doc/guides/nics/features/default.ini b/doc/guides/nics/features/default.ini
index a21168ba21..2488942db6 100644
--- a/doc/guides/nics/features/default.ini
+++ b/doc/guides/nics/features/default.ini
@@ -88,6 +88,7 @@ aggr_affinity        =
 ah                   =
 any                  =
 arp_eth_ipv4         =
+compare              =
 conntrack            =
 ecpri                =
 esp                  =
diff --git a/doc/guides/prog_guide/rte_flow.rst b/doc/guides/prog_guide/rte_flow.rst
index 9192d6ab01..34dc06ec66 100644
--- a/doc/guides/prog_guide/rte_flow.rst
+++ b/doc/guides/prog_guide/rte_flow.rst
@@ -1587,6 +1587,13 @@ the packet.
 
 - ``value``: Specific value to match.
 
+Item: ``COMPARE``
+^^^^^^^^^^^^^^^^^
+
+Matches the comparison result between packet fields or value.
+
+- ``compare``: Comparison information.
+
 Actions
 ~~~~~~~
 
diff --git a/doc/guides/rel_notes/release_24_03.rst b/doc/guides/rel_notes/release_24_03.rst
index 222a091e8b..59eda27606 100644
--- a/doc/guides/rel_notes/release_24_03.rst
+++ b/doc/guides/rel_notes/release_24_03.rst
@@ -70,6 +70,11 @@ New Features
   * Added a fath path function ``rte_eth_tx_queue_count`` to get the number of used
     descriptors of a Tx queue.
 
+* **Added flow matching with various comparison results.**
+
+  Added ``RTE_FLOW_ITEM_TYPE_COMPARE`` to allow matching on comparison
+  result between packet fields or value.
+
 * **Updated Atomic Rules' Arkville PMD.**
 
   * Added support for Atomic Rules' TK242 packet-capture family of devices
diff --git a/doc/guides/testpmd_app_ug/testpmd_funcs.rst b/doc/guides/testpmd_app_ug/testpmd_funcs.rst
index 0eaccbea4b..53923ad7cc 100644
--- a/doc/guides/testpmd_app_ug/testpmd_funcs.rst
+++ b/doc/guides/testpmd_app_ug/testpmd_funcs.rst
@@ -3856,6 +3856,13 @@ This section lists supported pattern items and their attributes, if any.
 
         - ``packet_type {unsigned}``: packet type.
 
+- ``compare``: match the comparison result between packet fields or value.
+
+        - ``op {string}``: comparison operation type.
+        - ``a_type {string}``: compared field.
+        - ``b_type {string}``: comparator field.
+        - ``width {unsigned}``: comparison width.
+
 
 Actions list
 ^^^^^^^^^^^^
@@ -5324,6 +5331,23 @@ 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 match with comparison rule
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+Match with comparison rule can be created as following using ``compare``.
+
+::
+
+    testpmd> flow pattern_template 0 create ingress pattern_template_id 1 template compare op mask le
+             a_type mask tag a_tag_index mask 1 b_type mask tag b_tag_index mask 2 width mask 0xffffffff / end
+    testpmd> flow actions_template 0 create ingress actions_template_id 1 template count / drop / end
+             mask count / drop  / end
+    testpmd> flow template_table 0 create table_id 1 group 2 priority 1  ingress rules_number 1
+             pattern_template 1 actions_template 1
+    testpmd> flow queue 0 create 0 template_table 1 pattern_template 0 actions_template 0 postpone no
+             pattern compare op is le a_type is tag a_tag_index is 1 b_type is tag b_tag_index is 2 width is 32 / end
+	     actions count / drop / end
+
 BPF Functions
 --------------
 
diff --git a/lib/ethdev/rte_flow.c b/lib/ethdev/rte_flow.c
index 156545454c..b06da0cc00 100644
--- a/lib/ethdev/rte_flow.c
+++ b/lib/ethdev/rte_flow.c
@@ -170,6 +170,7 @@ static const struct rte_flow_desc_data rte_flow_desc_item[] = {
 	MK_FLOW_ITEM(TX_QUEUE, sizeof(struct rte_flow_item_tx_queue)),
 	MK_FLOW_ITEM(IB_BTH, sizeof(struct rte_flow_item_ib_bth)),
 	MK_FLOW_ITEM(PTYPE, sizeof(struct rte_flow_item_ptype)),
+	MK_FLOW_ITEM(COMPARE, sizeof(struct rte_flow_item_compare)),
 };
 
 /** Generate flow_action[] entry. */
diff --git a/lib/ethdev/rte_flow.h b/lib/ethdev/rte_flow.h
index 958eb01a80..09c1b13381 100644
--- a/lib/ethdev/rte_flow.h
+++ b/lib/ethdev/rte_flow.h
@@ -714,6 +714,13 @@ enum rte_flow_item_type {
 	 * @see struct rte_flow_item_random.
 	 */
 	RTE_FLOW_ITEM_TYPE_RANDOM,
+
+	/**
+	 * Match packet with various comparison types.
+	 *
+	 * See struct rte_flow_item_compare.
+	 */
+	RTE_FLOW_ITEM_TYPE_COMPARE,
 };
 
 /**
@@ -2366,7 +2373,8 @@ static const struct rte_flow_item_ptype rte_flow_item_ptype_mask = {
 #endif
 
 /**
- * Packet header field IDs, used by RTE_FLOW_ACTION_TYPE_MODIFY_FIELD.
+ * Packet header field IDs, used by RTE_FLOW_ACTION_TYPE_MODIFY_FIELD
+ * and RTE_FLOW_ITEM_TYPE_COMPARE.
  */
 enum rte_flow_field_id {
 	RTE_FLOW_FIELD_START = 0,       /**< Start of a packet. */
@@ -2420,7 +2428,8 @@ enum rte_flow_field_id {
  * @warning
  * @b EXPERIMENTAL: this structure may change without prior notice
  *
- * Packet header field descriptions, used by RTE_FLOW_ACTION_TYPE_MODIFY_FIELD.
+ * Packet header field descriptions, used by RTE_FLOW_ACTION_TYPE_MODIFY_FIELD
+ * and RTE_FLOW_ITEM_TYPE_COMPARE.
  */
 struct rte_flow_field_data {
 	enum rte_flow_field_id field; /**< Field or memory type ID. */
@@ -2510,6 +2519,33 @@ struct rte_flow_field_data {
 	};
 };
 
+/**
+ * Expected operation types for compare item.
+ */
+enum rte_flow_item_compare_op {
+	RTE_FLOW_ITEM_COMPARE_EQ,	/* Compare result equal. */
+	RTE_FLOW_ITEM_COMPARE_NE,	/* Compare result not equal. */
+	RTE_FLOW_ITEM_COMPARE_LT,	/* Compare result less than. */
+	RTE_FLOW_ITEM_COMPARE_LE,	/* Compare result less than or equal. */
+	RTE_FLOW_ITEM_COMPARE_GT,	/* Compare result great than. */
+	RTE_FLOW_ITEM_COMPARE_GE,	/* Compare result great than or equal. */
+};
+
+/**
+ *
+ * RTE_FLOW_ITEM_TYPE_COMPARE
+ *
+ * Matches the packet with compare result.
+ *
+ * The operation means a compare with b result.
+ */
+struct rte_flow_item_compare {
+	enum rte_flow_item_compare_op operation; /* The compare operation. */
+	struct rte_flow_field_data a;		 /* Field be compared.  */
+	struct rte_flow_field_data b;		 /* Field as comparator. */
+	uint32_t width;				 /* Compare width. */
+};
+
 /**
  * Action types.
  *
-- 
2.34.1


^ permalink raw reply	[flat|nested] 66+ messages in thread

* [PATCH v7 4/4] net/mlx5: add compare item support
  2024-02-06  2:06 ` [PATCH v7 0/4] ethdev: add RTE_FLOW_ITEM_TYPE_COMPARE Suanming Mou
                     ` (2 preceding siblings ...)
  2024-02-06  2:06   ` [PATCH v7 3/4] ethdev: add compare item Suanming Mou
@ 2024-02-06  2:06   ` Suanming Mou
  2024-02-06 21:23     ` Ferruh Yigit
  2024-02-06 21:24   ` [PATCH v7 0/4] ethdev: add RTE_FLOW_ITEM_TYPE_COMPARE Ferruh Yigit
  4 siblings, 1 reply; 66+ messages in thread
From: Suanming Mou @ 2024-02-06  2:06 UTC (permalink / raw)
  To: thomas, ferruh.yigit, Dariusz Sosnowski, Viacheslav Ovsiienko,
	Ori Kam, Matan Azrad
  Cc: dev

The compare item allows adding flow match with comparison
result. This commit adds compare item support to the PMD
code.

Due to HW limitation:
 - Only HWS supported.
 - Only 32-bit comparison is supported.
 - Only single compare flow is supported in the flow table.
 - Only match with compare result between packet fields is
    supported.

Signed-off-by: Suanming Mou <suanmingm@nvidia.com>
Acked-by: Ori Kam <orika@nvidia.com>
---
 doc/guides/nics/features/mlx5.ini      |  1 +
 doc/guides/nics/mlx5.rst               |  7 +++
 doc/guides/rel_notes/release_24_03.rst |  2 +
 drivers/net/mlx5/mlx5_flow.h           |  3 ++
 drivers/net/mlx5/mlx5_flow_hw.c        | 73 ++++++++++++++++++++++++++
 5 files changed, 86 insertions(+)

diff --git a/doc/guides/nics/features/mlx5.ini b/doc/guides/nics/features/mlx5.ini
index 0739fe9d63..00e9348fc6 100644
--- a/doc/guides/nics/features/mlx5.ini
+++ b/doc/guides/nics/features/mlx5.ini
@@ -56,6 +56,7 @@ Usage doc            = Y
 
 [rte_flow items]
 aggr_affinity        = Y
+compare              = Y
 conntrack            = Y
 ecpri                = Y
 esp                  = Y
diff --git a/doc/guides/nics/mlx5.rst b/doc/guides/nics/mlx5.rst
index 6b52fb93c5..18b40bc22d 100644
--- a/doc/guides/nics/mlx5.rst
+++ b/doc/guides/nics/mlx5.rst
@@ -778,6 +778,13 @@ Limitations
   The flow engine of a process cannot move from active to standby mode
   if preceding active application rules are still present and vice versa.
 
+- Match with compare result item (``RTE_FLOW_ITEM_TYPE_COMPARE``):
+
+  - Only supported in HW steering(``dv_flow_en`` = 2) mode.
+  - Only single flow is supported to the flow table.
+  - Only 32-bit comparison is supported.
+  - Only match with compare result between packet fields is supported.
+
 
 Statistics
 ----------
diff --git a/doc/guides/rel_notes/release_24_03.rst b/doc/guides/rel_notes/release_24_03.rst
index 59eda27606..01d2d6d043 100644
--- a/doc/guides/rel_notes/release_24_03.rst
+++ b/doc/guides/rel_notes/release_24_03.rst
@@ -80,6 +80,8 @@ New Features
   * Added support for Atomic Rules' TK242 packet-capture family of devices
     with PCI IDs: ``0x1024, 0x1025, 0x1026``.
 
+  * Added support for comparing result between packet fields or value.
+
 
 Removed Items
 -------------
diff --git a/drivers/net/mlx5/mlx5_flow.h b/drivers/net/mlx5/mlx5_flow.h
index ecfb04ead2..f0a11949e6 100644
--- a/drivers/net/mlx5/mlx5_flow.h
+++ b/drivers/net/mlx5/mlx5_flow.h
@@ -277,6 +277,9 @@ enum mlx5_feature_name {
 /* NSH ITEM */
 #define MLX5_FLOW_ITEM_NSH (1ull << 53)
 
+/* COMPARE ITEM */
+#define MLX5_FLOW_ITEM_COMPARE (1ull << 54)
+
 /* Outer Masks. */
 #define MLX5_FLOW_LAYER_OUTER_L3 \
 	(MLX5_FLOW_LAYER_OUTER_L3_IPV4 | MLX5_FLOW_LAYER_OUTER_L3_IPV6)
diff --git a/drivers/net/mlx5/mlx5_flow_hw.c b/drivers/net/mlx5/mlx5_flow_hw.c
index da873ae2e2..f21c22131c 100644
--- a/drivers/net/mlx5/mlx5_flow_hw.c
+++ b/drivers/net/mlx5/mlx5_flow_hw.c
@@ -426,6 +426,9 @@ flow_hw_matching_item_flags_get(const struct rte_flow_item items[])
 		case RTE_FLOW_ITEM_TYPE_GTP:
 			last_item = MLX5_FLOW_LAYER_GTP;
 			break;
+		case RTE_FLOW_ITEM_TYPE_COMPARE:
+			last_item = MLX5_FLOW_ITEM_COMPARE;
+			break;
 		default:
 			break;
 		}
@@ -4386,6 +4389,8 @@ flow_hw_table_create(struct rte_eth_dev *dev,
 			rte_errno = EINVAL;
 			goto it_error;
 		}
+		if (item_templates[i]->item_flags & MLX5_FLOW_ITEM_COMPARE)
+			matcher_attr.mode = MLX5DR_MATCHER_RESOURCE_MODE_HTABLE;
 		ret = __atomic_fetch_add(&item_templates[i]->refcnt, 1,
 					 __ATOMIC_RELAXED) + 1;
 		if (ret <= 1) {
@@ -6634,6 +6639,66 @@ flow_hw_prepend_item(const struct rte_flow_item *items,
 	return copied_items;
 }
 
+static inline bool
+flow_hw_item_compare_field_supported(enum rte_flow_field_id field)
+{
+	switch (field) {
+	case RTE_FLOW_FIELD_TAG:
+	case RTE_FLOW_FIELD_META:
+	case RTE_FLOW_FIELD_VALUE:
+		return true;
+	default:
+		break;
+	}
+	return false;
+}
+
+static int
+flow_hw_validate_item_compare(const struct rte_flow_item *item,
+			      struct rte_flow_error *error)
+{
+	const struct rte_flow_item_compare *comp_m = item->mask;
+	const struct rte_flow_item_compare *comp_v = item->spec;
+
+	if (unlikely(!comp_m))
+		return rte_flow_error_set(error, EINVAL,
+				   RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
+				   NULL,
+				   "compare item mask is missing");
+	if (comp_m->width != UINT32_MAX)
+		return rte_flow_error_set(error, EINVAL,
+				   RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
+				   NULL,
+				   "compare item only support full mask");
+	if (!flow_hw_item_compare_field_supported(comp_m->a.field) ||
+	    !flow_hw_item_compare_field_supported(comp_m->b.field))
+		return rte_flow_error_set(error, ENOTSUP,
+				   RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
+				   NULL,
+				   "compare item field not support");
+	if (comp_m->a.field == RTE_FLOW_FIELD_VALUE &&
+	    comp_m->b.field == RTE_FLOW_FIELD_VALUE)
+		return rte_flow_error_set(error, EINVAL,
+				   RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
+				   NULL,
+				   "compare between value is not valid");
+	if (comp_v) {
+		if (comp_v->operation != comp_m->operation ||
+		    comp_v->a.field != comp_m->a.field ||
+		    comp_v->b.field != comp_m->b.field)
+			return rte_flow_error_set(error, EINVAL,
+					   RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
+					   NULL,
+					   "compare item spec/mask not matching");
+		if ((comp_v->width & comp_m->width) != 32)
+			return rte_flow_error_set(error, EINVAL,
+					   RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
+					   NULL,
+					   "compare item only support full mask");
+	}
+	return 0;
+}
+
 static int
 flow_hw_pattern_validate(struct rte_eth_dev *dev,
 			 const struct rte_flow_pattern_template_attr *attr,
@@ -6644,6 +6709,7 @@ flow_hw_pattern_validate(struct rte_eth_dev *dev,
 	int i, tag_idx;
 	bool items_end = false;
 	uint32_t tag_bitmap = 0;
+	int ret;
 
 	if (!attr->ingress && !attr->egress && !attr->transfer)
 		return rte_flow_error_set(error, EINVAL, RTE_FLOW_ERROR_TYPE_ATTR, NULL,
@@ -6781,6 +6847,13 @@ flow_hw_pattern_validate(struct rte_eth_dev *dev,
 							  " attribute");
 			break;
 		}
+		case RTE_FLOW_ITEM_TYPE_COMPARE:
+		{
+			ret = flow_hw_validate_item_compare(&items[i], error);
+			if (ret)
+				return ret;
+			break;
+		}
 		case RTE_FLOW_ITEM_TYPE_VOID:
 		case RTE_FLOW_ITEM_TYPE_ETH:
 		case RTE_FLOW_ITEM_TYPE_VLAN:
-- 
2.34.1


^ permalink raw reply	[flat|nested] 66+ messages in thread

* Re: [PATCH v7 1/4] ethdev: rename action modify field data structure
  2024-02-06  2:06   ` [PATCH v7 1/4] ethdev: rename action modify field data structure Suanming Mou
@ 2024-02-06 21:23     ` Ferruh Yigit
  0 siblings, 0 replies; 66+ messages in thread
From: Ferruh Yigit @ 2024-02-06 21:23 UTC (permalink / raw)
  To: Suanming Mou, thomas, Ori Kam, Aman Singh, Yuying Zhang,
	Dariusz Sosnowski, Viacheslav Ovsiienko, Matan Azrad,
	Andrew Rybchenko
  Cc: dev

On 2/6/2024 2:06 AM, Suanming Mou wrote:
> Current rte_flow_action_modify_data struct describes the pkt
> field perfectly and is used only in action.
> 
> It is planned to be used for item as well. This commit renames
> it to "rte_flow_field_data" making it compatible to be used by item.
> 
> Signed-off-by: Suanming Mou <suanmingm@nvidia.com>
> Acked-by: Ori Kam <orika@nvidia.com>
> Acked-by: Andrew Rybchenko <andrew.rybchenko@oktetlabs.ru>
>

Acked-by: Ferruh Yigit <ferruh.yigit@amd.com>

^ permalink raw reply	[flat|nested] 66+ messages in thread

* Re: [PATCH v7 2/4] ethdev: move flow field data structures
  2024-02-06  2:06   ` [PATCH v7 2/4] ethdev: move flow field data structures Suanming Mou
@ 2024-02-06 21:23     ` Ferruh Yigit
  0 siblings, 0 replies; 66+ messages in thread
From: Ferruh Yigit @ 2024-02-06 21:23 UTC (permalink / raw)
  To: Suanming Mou, thomas, Ori Kam, Andrew Rybchenko; +Cc: dev

On 2/6/2024 2:06 AM, Suanming Mou wrote:
> As flow field relevant data structures will be used by both actions and
> items, this commit moves the relevant data structures up to item parts.
> 
> Signed-off-by: Suanming Mou <suanmingm@nvidia.com>
>

Acked-by: Ferruh Yigit <ferruh.yigit@amd.com>

^ permalink raw reply	[flat|nested] 66+ messages in thread

* Re: [PATCH v7 4/4] net/mlx5: add compare item support
  2024-02-06  2:06   ` [PATCH v7 4/4] net/mlx5: add compare item support Suanming Mou
@ 2024-02-06 21:23     ` Ferruh Yigit
  0 siblings, 0 replies; 66+ messages in thread
From: Ferruh Yigit @ 2024-02-06 21:23 UTC (permalink / raw)
  To: Suanming Mou, thomas, Dariusz Sosnowski, Viacheslav Ovsiienko,
	Ori Kam, Matan Azrad
  Cc: dev

On 2/6/2024 2:06 AM, Suanming Mou wrote:
> @@ -80,6 +80,8 @@ New Features
>    * Added support for Atomic Rules' TK242 packet-capture family of devices
>      with PCI IDs: ``0x1024, 0x1025, 0x1026``.
>  
> +  * Added support for comparing result between packet fields or value.
> +
>  

Comment in v5 seems not addressed, above is still under wrong block.

Adding "* **Updated NVIDIA mlx5 driver.**" while merging.


^ permalink raw reply	[flat|nested] 66+ messages in thread

* Re: [PATCH v7 0/4] ethdev: add RTE_FLOW_ITEM_TYPE_COMPARE
  2024-02-06  2:06 ` [PATCH v7 0/4] ethdev: add RTE_FLOW_ITEM_TYPE_COMPARE Suanming Mou
                     ` (3 preceding siblings ...)
  2024-02-06  2:06   ` [PATCH v7 4/4] net/mlx5: add compare item support Suanming Mou
@ 2024-02-06 21:24   ` Ferruh Yigit
  4 siblings, 0 replies; 66+ messages in thread
From: Ferruh Yigit @ 2024-02-06 21:24 UTC (permalink / raw)
  To: Suanming Mou, thomas; +Cc: dev, orika

On 2/6/2024 2:06 AM, Suanming Mou wrote:
> The new item type is added for the case user wants to match traffic
> based on packet field compare result with other fields or immediate
> value.
> 
> e.g. take advantage the compare item user will be able to accumulate
> a IPv4/TCP packet's TCP data_offset and IPv4 IHL field to a tag
> register, then compare the tag register with IPv4 header total length
> to understand the packet has payload or not.
> 
> The supported operations can be as below:
>  - RTE_FLOW_ITEM_COMPARE_EQ (equal)
>  - RTE_FLOW_ITEM_COMPARE_NE (not equal)
>  - RTE_FLOW_ITEM_COMPARE_LT (less than)
>  - RTE_FLOW_ITEM_COMPARE_LE (less than or equal)
>  - RTE_FLOW_ITEM_COMPARE_GT (great than)
>  - RTE_FLOW_ITEM_COMPARE_GE (great than or equal)
> 
> V7:
>  - Moved release notes to API.
>  - Optimize comment descriptions.
> 
> V6:
>  - fix typo and style issue.
>  - adjust flow_field description.
> 
> V5:
>  - rebase on top of next-net
>  - add sample detail for rte_flow_field.
> 
> V4:
>  - rebase on top of the latest version.
>  - move ACTION_MODIFY_PATTERN_SIZE and modify_field_ids rename
>    to first patch.
>  - add comparison flow create sample in testpmd_funcs.rst.
> 
> V3:
>  - fix code style missing empty line in rte_flow.rst.
>  - fix missing the ABI change release notes.
> 
> V2:
>  - Since modify field data struct is experiment, rename modify
>    field data directly instead of adding new flow field struct.
> 
> 
> Suanming Mou (4):
>   ethdev: rename action modify field data structure
>   ethdev: move flow field data structures
>   ethdev: add compare item
>   net/mlx5: add compare item support
>

Series applied to dpdk-next-net/main, thanks.


^ permalink raw reply	[flat|nested] 66+ messages in thread

* Re: [PATCH v7 3/4] ethdev: add compare item
  2024-02-06  2:06   ` [PATCH v7 3/4] ethdev: add compare item Suanming Mou
@ 2024-02-06 21:24     ` Ferruh Yigit
  0 siblings, 0 replies; 66+ messages in thread
From: Ferruh Yigit @ 2024-02-06 21:24 UTC (permalink / raw)
  To: Suanming Mou, thomas, Ori Kam, Aman Singh, Yuying Zhang,
	Andrew Rybchenko
  Cc: dev

On 2/6/2024 2:06 AM, Suanming Mou wrote:
> The new item type is added for the case user wants to match traffic
> based on packet field compare result with other fields or immediate
> value.
> 
> e.g. take advantage the compare item user will be able to accumulate
> a IPv4/TCP packet's TCP data_offset and IPv4 IHL field to a tag
> register, then compare the tag register with IPv4 header total length
> to understand the packet has payload or not.
> 
> The supported operations can be as below:
>  - RTE_FLOW_ITEM_COMPARE_EQ (equal)
>  - RTE_FLOW_ITEM_COMPARE_NE (not equal)
>  - RTE_FLOW_ITEM_COMPARE_LT (less than)
>  - RTE_FLOW_ITEM_COMPARE_LE (less than or equal)
>  - RTE_FLOW_ITEM_COMPARE_GT (great than)
>  - RTE_FLOW_ITEM_COMPARE_GE (great than or equal)
> 
> A sample for create the comparison flow:
> flow pattern_template 0 create ingress pattern_template_id 1 template \
> 	compare op mask le a_type mask tag a_tag_index mask 1 b_type \
> 	mask tag b_tag_index mask 2 width mask 0xffffffff / end
> flow actions_template 0 create ingress actions_template_id 1 template \
> 	count / drop / end mask count / drop  / end
> flow template_table 0 create table_id 1 group 2 priority 1  ingress \
> 	rules_number 1 pattern_template 1 actions_template 1
> flow queue 0 create 0 template_table 1 pattern_template 0 \
> 	actions_template 0 postpone no pattern compare op is le \
> 	a_type is tag a_tag_index is 1 b_type is tag b_tag_index is 2 \
> 	width is 32 / end actions count / drop / end
> 
> Signed-off-by: Suanming Mou <suanmingm@nvidia.com>
> Acked-by: Ori Kam <orika@nvidia.com>
> Acked-by: Andrew Rybchenko <andrew.rybchenko@oktetlabs.ru>
>

Acked-by: Ferruh Yigit <ferruh.yigit@amd.com>


^ permalink raw reply	[flat|nested] 66+ messages in thread

end of thread, other threads:[~2024-02-06 21:24 UTC | newest]

Thread overview: 66+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2023-12-14  3:12 [PATCH 0/2] ethdev: add RTE_FLOW_ITEM_TYPE_COMPARE Suanming Mou
2023-12-14  3:12 ` [PATCH 1/2] " Suanming Mou
2023-12-14  3:12 ` [PATCH 2/2] net/mlx5: add compare item support Suanming Mou
2023-12-19  1:33 ` [PATCH v2 0/3] [PATCH 0/2] ethdev: add RTE_FLOW_ITEM_TYPE_COMPARE Suanming Mou
2023-12-19  1:33   ` [PATCH v2 1/3] ethdev: rename action modify field data structure Suanming Mou
2024-01-09 14:07     ` Ori Kam
2024-01-12  8:03       ` Andrew Rybchenko
2023-12-19  1:33   ` [PATCH v2 2/3] ethdev: add compare item Suanming Mou
2024-01-09 14:26     ` Ori Kam
2024-01-12  8:11     ` Andrew Rybchenko
2024-01-15  8:14       ` Suanming Mou
2023-12-19  1:33   ` [PATCH v2 3/3] net/mlx5: add compare item support Suanming Mou
2024-01-09 14:28     ` Ori Kam
2024-01-15  9:13   ` [PATCH v3 0/3] ethdev: add RTE_FLOW_ITEM_TYPE_COMPARE Suanming Mou
2024-01-15  9:13     ` [PATCH v3 1/3] ethdev: rename action modify field data structure Suanming Mou
2024-01-30 17:19       ` Ferruh Yigit
2024-01-31  2:57         ` Suanming Mou
2024-02-01 10:56           ` Ferruh Yigit
2024-02-01 11:09             ` Suanming Mou
2024-02-01 11:20               ` Ferruh Yigit
2024-02-01 11:39                 ` Suanming Mou
2024-01-15  9:13     ` [PATCH v3 2/3] ethdev: add compare item Suanming Mou
2024-01-30 17:33       ` Ferruh Yigit
2024-01-31  2:47         ` Suanming Mou
2024-01-31 15:56           ` Ori Kam
2024-01-31 16:46             ` Ferruh Yigit
2024-01-31 17:43               ` Ori Kam
2024-01-31 17:54                 ` Ferruh Yigit
2024-02-01  6:51                   ` Ori Kam
2024-02-01  0:31               ` Suanming Mou
2024-01-15  9:13     ` [PATCH v3 3/3] net/mlx5: add compare item support Suanming Mou
2024-02-01  2:30 ` [PATCH v4 0/3] ethdev: add RTE_FLOW_ITEM_TYPE_COMPARE Suanming Mou
2024-02-01  2:30   ` [PATCH v4 1/3] ethdev: rename action modify field data structure Suanming Mou
2024-02-01  2:30   ` [PATCH v4 2/3] ethdev: add compare item Suanming Mou
2024-02-01  2:30   ` [PATCH v4 3/3] net/mlx5: add compare item support Suanming Mou
2024-02-01 12:29 ` [PATCH v5 0/3] ethdev: add RTE_FLOW_ITEM_TYPE_COMPARE Suanming Mou
2024-02-01 12:29   ` [PATCH v5 1/3] ethdev: rename action modify field data structure Suanming Mou
2024-02-01 18:57     ` Ferruh Yigit
2024-02-01 12:29   ` [PATCH v5 2/3] ethdev: add compare item Suanming Mou
2024-02-01 18:57     ` Ferruh Yigit
2024-02-01 12:29   ` [PATCH v5 3/3] net/mlx5: add compare item support Suanming Mou
2024-02-01 18:57     ` Ferruh Yigit
2024-02-01 18:56   ` [PATCH v5 0/3] ethdev: add RTE_FLOW_ITEM_TYPE_COMPARE Ferruh Yigit
2024-02-02  0:32     ` Suanming Mou
2024-02-02  0:42 ` [PATCH v6 " Suanming Mou
2024-02-02  0:42   ` [PATCH v6 1/3] ethdev: rename action modify field data structure Suanming Mou
2024-02-05 11:23     ` Thomas Monjalon
2024-02-05 11:49       ` Suanming Mou
2024-02-05 12:39         ` Thomas Monjalon
2024-02-05 12:53           ` Suanming Mou
2024-02-02  0:42   ` [PATCH v6 2/3] ethdev: add compare item Suanming Mou
2024-02-05 13:00     ` Thomas Monjalon
2024-02-05 13:28       ` Suanming Mou
2024-02-05 14:09         ` Thomas Monjalon
2024-02-06  1:26           ` Suanming Mou
2024-02-02  0:42   ` [PATCH v6 3/3] net/mlx5: add compare item support Suanming Mou
2024-02-06  2:06 ` [PATCH v7 0/4] ethdev: add RTE_FLOW_ITEM_TYPE_COMPARE Suanming Mou
2024-02-06  2:06   ` [PATCH v7 1/4] ethdev: rename action modify field data structure Suanming Mou
2024-02-06 21:23     ` Ferruh Yigit
2024-02-06  2:06   ` [PATCH v7 2/4] ethdev: move flow field data structures Suanming Mou
2024-02-06 21:23     ` Ferruh Yigit
2024-02-06  2:06   ` [PATCH v7 3/4] ethdev: add compare item Suanming Mou
2024-02-06 21:24     ` Ferruh Yigit
2024-02-06  2:06   ` [PATCH v7 4/4] net/mlx5: add compare item support Suanming Mou
2024-02-06 21:23     ` Ferruh Yigit
2024-02-06 21:24   ` [PATCH v7 0/4] ethdev: add RTE_FLOW_ITEM_TYPE_COMPARE Ferruh Yigit

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).