[v6,2/3] ethdev: add compare item

Message ID 20240202004234.503097-3-suanmingm@nvidia.com (mailing list archive)
State Superseded, archived
Delegated to: Ferruh Yigit
Headers
Series ethdev: add RTE_FLOW_ITEM_TYPE_COMPARE |

Checks

Context Check Description
ci/checkpatch success coding style OK

Commit Message

Suanming Mou Feb. 2, 2024, 12:42 a.m. UTC
  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(-)
  

Comments

Thomas Monjalon Feb. 5, 2024, 1 p.m. UTC | #1
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?
  
Suanming Mou Feb. 5, 2024, 1:28 p.m. UTC | #2
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.

>
  
Thomas Monjalon Feb. 5, 2024, 2:09 p.m. UTC | #3
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.
  
Suanming Mou Feb. 6, 2024, 1:26 a.m. UTC | #4
> -----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.

>
  

Patch

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.
  */