Hi,

In my local code,

diff --git a/lib/ethdev/rte_flow.c b/lib/ethdev/rte_flow.c
index 7cf9f6f6f3..7a2721af00 100644
--- a/lib/ethdev/rte_flow.c
+++ b/lib/ethdev/rte_flow.c
@@ -181,9 +181,18 @@ static const struct rte_flow_desc_data 
rte_flow_desc_item[] = {
 static inline size_t
 rte_flow_conv_item_mask_size(const struct rte_flow_item *item)
 {
-       if ((int)item->type >= 0)
+       if ((int)item->type < 0)
+               return sizeof(void *);
+       switch (item->type) {
+       case RTE_FLOW_ITEM_TYPE_RAW:
+               return offsetof(struct rte_flow_item_raw, pattern);
+       case RTE_FLOW_ITEM_TYPE_GENEVE_OPT:
+               return offsetof(struct rte_flow_item_geneve_opt, data);
+       default:
+               if (rte_flow_desc_item[item->type].desc_fn != NULL)
+                       return 0;
                return rte_flow_desc_item[item->type].size;
-       return sizeof(void *);
+       }
 }

// This is the code before my latest change.
> +static inline size_t
> +rte_flow_conv_item_mask_size(const struct rte_flow_item *item) {
> +       if ((int)item->type >= 0)
> +               return rte_flow_desc_item[item->type].size;
> +       return sizeof(void *);
> +}
> +


I didn't understand why the patch I sent is still using the old code.

> -----Original Message-----
> From: Bing Zhao <[email protected]>
> Sent: Wednesday, June 10, 2026 1:27 PM
> To: Slava Ovsiienko <[email protected]>; [email protected]; Raslan
> Darawsheh <[email protected]>; [email protected]
> Cc: Ori Kam <[email protected]>; Dariusz Sosnowski <[email protected]>;
> Suanming Mou <[email protected]>; Matan Azrad <[email protected]>; NBU-
> Contact-Thomas Monjalon (EXTERNAL) <[email protected]>
> Subject: [PATCH v5] ethdev: support inline calculating masked item value
> 
> External email: Use caution opening links or attachments
> 
> 
> In the asynchronous API definition and some drivers, the rte_flow_item
> spec value may not be calculated by the driver due to the reason of speed
> of light rule insertion rate and sometimes the input parameters will be
> copied and changed internally.
> 
> After copying, the spec and last will be protected by the keyword const
> and cannot be changed in the code itself. And also the driver needs some
> extra memory to do the calculation and extra conditions to understand the
> length of each item spec. This is not efficient.
> 
> To solve the issue and support usage of the following fix, a new OP was
> introduced to calculate the spec and last values after applying the mask
> inline.
> 
> Signed-off-by: Bing Zhao <[email protected]>
> Acked-by: Dariusz Sosnowski <[email protected]>
> ---
> v3:
>   - add test code
>   - fix the issue found by AI
> v4: reabse on top of the main
> v5: handle some items separately and add test for them
> ---
>  app/test/test_ethdev_api.c             | 76 ++++++++++++++++++++++++++
>  doc/guides/rel_notes/release_26_07.rst |  6 ++
>  lib/ethdev/rte_flow.c                  | 46 ++++++++++++++--
>  lib/ethdev/rte_flow.h                  | 13 +++++
>  4 files changed, 135 insertions(+), 6 deletions(-)
> 
> diff --git a/app/test/test_ethdev_api.c b/app/test/test_ethdev_api.c index
> 76afd0345c..5cae1cdc1d 100644
> --- a/app/test/test_ethdev_api.c
> +++ b/app/test/test_ethdev_api.c
> @@ -4,6 +4,7 @@
> 
>  #include <rte_log.h>
>  #include <rte_ethdev.h>
> +#include <rte_flow.h>
> 
>  #include <rte_test.h>
>  #include "test.h"
> @@ -15,6 +16,80 @@
>  #define NUM_MBUF 1024
>  #define MBUF_CACHE_SIZE 256
> 
> +static int32_t
> +ethdev_api_flow_conv_pattern_masked(void)
> +{
> +       const struct rte_flow_item_eth spec = {
> +               .hdr.dst_addr.addr_bytes = { 0x01, 0x02, 0x03, 0x04, 0x05,
> 0x06 },
> +               .hdr.src_addr.addr_bytes = { 0x0a, 0x0b, 0x0c, 0x0d, 0x0e,
> 0x0f },
> +               .hdr.ether_type = RTE_BE16(0x1234),
> +       };
> +       const struct rte_flow_item_eth last = {
> +               .hdr.dst_addr.addr_bytes = { 0x11, 0x12, 0x13, 0x14, 0x15,
> 0x16 },
> +               .hdr.src_addr.addr_bytes = { 0x1a, 0x1b, 0x1c, 0x1d, 0x1e,
> 0x1f },
> +               .hdr.ether_type = RTE_BE16(0x5678),
> +       };
> +       const struct rte_flow_item_eth mask = {
> +               .hdr.dst_addr.addr_bytes = { 0xff, 0xff, 0x00, 0x00, 0xff,
> 0xff },
> +               .hdr.src_addr.addr_bytes = { 0xff, 0x00, 0xff, 0x00, 0xff,
> 0x00 },
> +               .hdr.ether_type = RTE_BE16(0xffff),
> +       };
> +       const struct rte_flow_item pattern[] = {
> +               {
> +                       .type = RTE_FLOW_ITEM_TYPE_ETH,
> +                       .spec = &spec,
> +                       .last = &last,
> +                       .mask = &mask,
> +               },
> +               { .type = RTE_FLOW_ITEM_TYPE_END },
> +       };
> +       union {
> +               struct rte_flow_item item;
> +               struct rte_flow_item_eth eth;
> +               double align;
> +               uint8_t raw[256];
> +       } dst;
> +       const struct rte_flow_item *item;
> +       const struct rte_flow_item_eth *conv_spec;
> +       const struct rte_flow_item_eth *conv_last;
> +       int ret;
> +
> +       ret = rte_flow_conv(RTE_FLOW_CONV_OP_PATTERN_MASKED, NULL, 0,
> pattern, NULL);
> +       TEST_ASSERT(ret > 0, "Masked pattern conversion size query
> failed");
> +       TEST_ASSERT((size_t)ret <= sizeof(dst.raw),
> +                   "Masked pattern conversion needs too much storage");
> +
> +       memset(&dst, 0, sizeof(dst));
> +       ret = rte_flow_conv(RTE_FLOW_CONV_OP_PATTERN_MASKED, dst.raw,
> +                           sizeof(dst.raw), pattern, NULL);
> +       TEST_ASSERT(ret > 0, "Masked pattern conversion failed");
> +
> +       item = (const struct rte_flow_item *)dst.raw;
> +       conv_spec = item[0].spec;
> +       conv_last = item[0].last;
> +       TEST_ASSERT_NOT_NULL(conv_spec, "Converted spec must be set");
> +       TEST_ASSERT_NOT_NULL(conv_last, "Converted last must be set");
> +
> +       TEST_ASSERT_EQUAL(conv_spec->hdr.dst_addr.addr_bytes[0], 0x01,
> +                         "Masked spec dst byte 0 mismatch");
> +       TEST_ASSERT_EQUAL(conv_spec->hdr.dst_addr.addr_bytes[2], 0x00,
> +                         "Masked spec dst byte 2 mismatch");
> +       TEST_ASSERT_EQUAL(conv_spec->hdr.src_addr.addr_bytes[1], 0x00,
> +                         "Masked spec src byte 1 mismatch");
> +       TEST_ASSERT_EQUAL(conv_spec->hdr.ether_type, RTE_BE16(0x1234),
> +                         "Masked spec ether type mismatch");
> +       TEST_ASSERT_EQUAL(conv_last->hdr.dst_addr.addr_bytes[0], 0x11,
> +                         "Masked last dst byte 0 mismatch");
> +       TEST_ASSERT_EQUAL(conv_last->hdr.dst_addr.addr_bytes[2], 0x00,
> +                         "Masked last dst byte 2 mismatch");
> +       TEST_ASSERT_EQUAL(conv_last->hdr.src_addr.addr_bytes[1], 0x00,
> +                         "Masked last src byte 1 mismatch");
> +       TEST_ASSERT_EQUAL(conv_last->hdr.ether_type, RTE_BE16(0x5678),
> +                         "Masked last ether type mismatch");
> +
> +       return TEST_SUCCESS;
> +}
> +
>  static int32_t
>  ethdev_api_queue_status(void)
>  {
> @@ -167,6 +242,7 @@ static struct unit_test_suite ethdev_api_testsuite = {
>         .setup = NULL,
>         .teardown = NULL,
>         .unit_test_cases = {
> +               TEST_CASE(ethdev_api_flow_conv_pattern_masked),
>                 TEST_CASE(ethdev_api_queue_status),
>                 /* TODO: Add deferred_start queue status test */
>                 TEST_CASES_END() /**< NULL terminate unit test array */
> diff --git a/doc/guides/rel_notes/release_26_07.rst
> b/doc/guides/rel_notes/release_26_07.rst
> index b5285af5fe..4f5d21d576 100644
> --- a/doc/guides/rel_notes/release_26_07.rst
> +++ b/doc/guides/rel_notes/release_26_07.rst
> @@ -190,6 +190,12 @@ API Changes
>    - ``rte_pmd_mlx5_enable_steering``
>    - ``rte_pmd_mlx5_disable_steering``
> 
> +* ethdev: Added masked pattern conversion.
> +
> +  Added ``RTE_FLOW_CONV_OP_PATTERN_MASKED`` to ``rte_flow_conv()``  to
> + copy an entire pattern while applying each item's mask to its
> + ``spec`` and ``last`` fields.
> +
> 
>  ABI Changes
>  -----------
> diff --git a/lib/ethdev/rte_flow.c b/lib/ethdev/rte_flow.c index
> ec0fe08355..c7a94a1194 100644
> --- a/lib/ethdev/rte_flow.c
> +++ b/lib/ethdev/rte_flow.c
> @@ -178,6 +178,14 @@ static const struct rte_flow_desc_data
> rte_flow_desc_item[] = {
>         MK_FLOW_ITEM(COMPARE, sizeof(struct rte_flow_item_compare)),  };
> 
> +static inline size_t
> +rte_flow_conv_item_mask_size(const struct rte_flow_item *item) {
> +       if ((int)item->type >= 0)
> +               return rte_flow_desc_item[item->type].size;
> +       return sizeof(void *);
> +}
> +
>  /** Generate flow_action[] entry. */
>  #define MK_FLOW_ACTION(t, s) \
>         [RTE_FLOW_ACTION_TYPE_ ## t] = { \ @@ -835,6 +843,8 @@
> rte_flow_conv_action_conf(void *buf, const size_t size,
>   *   RTE_FLOW_ITEM_TYPE_END is encountered.
>   * @param[out] error
>   *   Perform verbose error reporting if not NULL.
> + * @param[in] with_mask
> + *   If true, @p src mask will be applied to spec and last.
>   *
>   * @return
>   *   A positive value representing the number of bytes needed to store
> @@ -847,12 +857,13 @@ rte_flow_conv_pattern(struct rte_flow_item *dst,
>                       const size_t size,
>                       const struct rte_flow_item *src,
>                       unsigned int num,
> +                     bool with_mask,
>                       struct rte_flow_error *error)  {
>         uintptr_t data = (uintptr_t)dst;
>         size_t off;
>         size_t ret;
> -       unsigned int i;
> +       unsigned int i, j;
> 
>         for (i = 0, off = 0; !num || i != num; ++i, ++src, ++dst) {
>                 /**
> @@ -876,15 +887,27 @@ rte_flow_conv_pattern(struct rte_flow_item *dst,
>         src -= num;
>         dst -= num;
>         do {
> +               uint8_t *c_spec = NULL, *c_last = NULL;
> +               const uint8_t *mask = src->mask;
> +               size_t item_mask_size = mask ?
> + rte_flow_conv_item_mask_size(src) : 0;
> +
>                 if (src->spec) {
>                         off = RTE_ALIGN_CEIL(off, sizeof(double));
>                         ret = rte_flow_conv_item_spec
>                                 ((void *)(data + off),
>                                  size > off ? size - off : 0, src,
>                                  RTE_FLOW_CONV_ITEM_SPEC);
> -                       if (size && size >= off + ret)
> +                       if (size && size >= off + ret) {
>                                 dst->spec = (void *)(data + off);
> +                               c_spec = (uint8_t *)(data + off);
> +                       }
>                         off += ret;
> +                       if (with_mask && c_spec && mask) {
> +                               size_t mask_size = RTE_MIN(ret,
> + item_mask_size);
> +
> +                               for (j = 0; j < mask_size; j++)
> +                                       c_spec[j] &= mask[j];
> +                       }
> 
>                 }
>                 if (src->last) {
> @@ -893,9 +916,17 @@ rte_flow_conv_pattern(struct rte_flow_item *dst,
>                                 ((void *)(data + off),
>                                  size > off ? size - off : 0, src,
>                                  RTE_FLOW_CONV_ITEM_LAST);
> -                       if (size && size >= off + ret)
> +                       if (size && size >= off + ret) {
>                                 dst->last = (void *)(data + off);
> +                               c_last = (uint8_t *)(data + off);
> +                       }
>                         off += ret;
> +                       if (with_mask && c_last && mask) {
> +                               size_t mask_size = RTE_MIN(ret,
> + item_mask_size);
> +
> +                               for (j = 0; j < mask_size; j++)
> +                                       c_last[j] &= mask[j];
> +                       }
>                 }
>                 if (src->mask) {
>                         off = RTE_ALIGN_CEIL(off, sizeof(double)); @@ -
> 1042,7 +1073,7 @@ rte_flow_conv_rule(struct rte_flow_conv_rule *dst,
>                 off = RTE_ALIGN_CEIL(off, sizeof(double));
>                 ret = rte_flow_conv_pattern((void *)((uintptr_t)dst +
> off),
>                                             size > off ? size - off : 0,
> -                                           src->pattern_ro, 0, error);
> +                                           src->pattern_ro, 0, false,
> + error);
>                 if (ret < 0)
>                         return ret;
>                 if (size && size >= off + (size_t)ret) @@ -1143,7 +1174,7
> @@ rte_flow_conv(enum rte_flow_conv_op op,
>                 ret = sizeof(*attr);
>                 break;
>         case RTE_FLOW_CONV_OP_ITEM:
> -               ret = rte_flow_conv_pattern(dst, size, src, 1, error);
> +               ret = rte_flow_conv_pattern(dst, size, src, 1, false,
> + error);
>                 break;
>         case RTE_FLOW_CONV_OP_ITEM_MASK:
>                 item = src;
> @@ -1158,7 +1189,7 @@ rte_flow_conv(enum rte_flow_conv_op op,
>                 ret = rte_flow_conv_actions(dst, size, src, 1, error);
>                 break;
>         case RTE_FLOW_CONV_OP_PATTERN:
> -               ret = rte_flow_conv_pattern(dst, size, src, 0, error);
> +               ret = rte_flow_conv_pattern(dst, size, src, 0, false,
> + error);
>                 break;
>         case RTE_FLOW_CONV_OP_ACTIONS:
>                 ret = rte_flow_conv_actions(dst, size, src, 0, error); @@
> -1178,6 +1209,9 @@ rte_flow_conv(enum rte_flow_conv_op op,
>         case RTE_FLOW_CONV_OP_ACTION_NAME_PTR:
>                 ret = rte_flow_conv_name(1, 1, dst, size, src, error);
>                 break;
> +       case RTE_FLOW_CONV_OP_PATTERN_MASKED:
> +               ret = rte_flow_conv_pattern(dst, size, src, 0, true,
> error);
> +               break;
>         default:
>                 ret = rte_flow_error_set
>                 (error, ENOTSUP, RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,
> diff --git a/lib/ethdev/rte_flow.h b/lib/ethdev/rte_flow.h index
> b495409406..959a2f903b 100644
> --- a/lib/ethdev/rte_flow.h
> +++ b/lib/ethdev/rte_flow.h
> @@ -4556,6 +4556,19 @@ enum rte_flow_conv_op {
>          *   @code const char ** @endcode
>          */
>         RTE_FLOW_CONV_OP_ACTION_NAME_PTR,
> +
> +       /**
> +        * Convert an entire pattern.
> +        *
> +        * Duplicates all pattern items at once, applying @p mask to @p
> spec
> +        * and @p last.
> +        *
> +        * - @p src type:
> +        *   @code const struct rte_flow_item * @endcode
> +        * - @p dst type:
> +        *   @code struct rte_flow_item * @endcode
> +        */
> +       RTE_FLOW_CONV_OP_PATTERN_MASKED,
>  };
> 
>  /**
> --
> 2.34.1

Reply via email to