[PATCH v4 6/6] ethdev: add flow item structure size query
Anatoly Burakov
anatoly.burakov at intel.com
Tue Oct 27 10:50:13 CET 2026
Add RTE_FLOW_CONV_OP_ITEM_SIZE to retrieve the fixed specification
structure size for a flow item type using the existing descriptor table.
Also defensively reject descriptor entries without names in item and
action name lookups and in item default-mask lookups. The preceding
descriptor fixes fill the existing gaps; these checks keep future gaps
from returning NULL names or passing NULL to strlcpy().
Extend the flow conversion unit test to cover the new operation.
Signed-off-by: Anatoly Burakov <anatoly.burakov at intel.com>
---
app/test/test_ethdev_flow_conv.c | 92 ++++++++++++++++++++++++++
doc/guides/rel_notes/release_26_11.rst | 8 ++-
lib/ethdev/rte_flow.c | 27 +++++++-
lib/ethdev/rte_flow.h | 18 +++++
4 files changed, 140 insertions(+), 5 deletions(-)
diff --git a/app/test/test_ethdev_flow_conv.c b/app/test/test_ethdev_flow_conv.c
index 39a59dd07a1..fcf483702d5 100644
--- a/app/test/test_ethdev_flow_conv.c
+++ b/app/test/test_ethdev_flow_conv.c
@@ -21,6 +21,92 @@
/* Guaranteed to be out of range of every descriptor table. */
#define BOGUS_TYPE INT32_MAX
+static int
+item_size(int type, size_t *size, struct rte_flow_error *error)
+{
+ return rte_flow_conv(RTE_FLOW_CONV_OP_ITEM_SIZE, size, sizeof(*size),
+ RTE_CAST_PTR(const void *, type), error);
+}
+
+static int
+test_flow_conv_item_size(void)
+{
+ struct rte_flow_error error;
+ size_t size;
+ int ret;
+
+ struct {
+ int type;
+ size_t expected;
+ } const known[] = {
+ { RTE_FLOW_ITEM_TYPE_END, 0 },
+ { RTE_FLOW_ITEM_TYPE_VOID, 0 },
+ { RTE_FLOW_ITEM_TYPE_INVERT, 0 },
+ { RTE_FLOW_ITEM_TYPE_ETH, sizeof(struct rte_flow_item_eth) },
+ { RTE_FLOW_ITEM_TYPE_IPV4, sizeof(struct rte_flow_item_ipv4) },
+ { RTE_FLOW_ITEM_TYPE_GRE_KEY, sizeof(rte_be32_t) },
+ { RTE_FLOW_ITEM_TYPE_GTPC, sizeof(struct rte_flow_item_gtp) },
+ { RTE_FLOW_ITEM_TYPE_MACSEC,
+ sizeof(struct rte_flow_item_macsec) },
+ { RTE_FLOW_ITEM_TYPE_COMPARE,
+ sizeof(struct rte_flow_item_compare) },
+ };
+
+ for (unsigned int i = 0; i < RTE_DIM(known); i++) {
+ size = SIZE_MAX;
+ ret = item_size(known[i].type, &size, &error);
+ TEST_ASSERT_EQUAL(ret, (int)sizeof(size_t),
+ "item type %d: unexpected return %d",
+ known[i].type, ret);
+ TEST_ASSERT_EQUAL(size, known[i].expected,
+ "item type %d: size %zu, expected %zu",
+ known[i].type, size, known[i].expected);
+ }
+
+ return TEST_SUCCESS;
+}
+
+static int
+test_flow_conv_item_size_errors(void)
+{
+ struct rte_flow_error error;
+ size_t size;
+ int ret;
+
+ /* Out of range type. */
+ memset(&error, 0, sizeof(error));
+ rte_errno = 0;
+ ret = item_size(BOGUS_TYPE, &size, &error);
+ TEST_ASSERT_EQUAL(ret, -EINVAL, "unexpected return %d", ret);
+ TEST_ASSERT_EQUAL(rte_errno, EINVAL, "rte_errno %d", rte_errno);
+ TEST_ASSERT_EQUAL(error.type, RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
+ "unexpected error type %d", error.type);
+ TEST_ASSERT_NOT_NULL(error.message, "error message not set");
+
+ /* PMD private type. */
+ rte_errno = 0;
+ ret = item_size(-1, &size, &error);
+ TEST_ASSERT_EQUAL(ret, -EINVAL, "unexpected return %d", ret);
+ TEST_ASSERT_EQUAL(rte_errno, EINVAL, "rte_errno %d", rte_errno);
+
+ /* Destination too small: nothing written, size still reported. */
+ size = SIZE_MAX;
+ ret = rte_flow_conv(RTE_FLOW_CONV_OP_ITEM_SIZE, &size,
+ sizeof(size) - 1,
+ RTE_CAST_PTR(const void *, RTE_FLOW_ITEM_TYPE_ETH), &error);
+ TEST_ASSERT_EQUAL(ret, (int)sizeof(size_t), "unexpected return %d",
+ ret);
+ TEST_ASSERT_EQUAL(size, SIZE_MAX, "destination was written");
+
+ /* NULL destination with zero size is a pure size query. */
+ ret = rte_flow_conv(RTE_FLOW_CONV_OP_ITEM_SIZE, NULL, 0,
+ RTE_CAST_PTR(const void *, RTE_FLOW_ITEM_TYPE_ETH), &error);
+ TEST_ASSERT_EQUAL(ret, (int)sizeof(size_t), "unexpected return %d",
+ ret);
+
+ return TEST_SUCCESS;
+}
+
static int
test_flow_conv_item_name(void)
{
@@ -158,6 +244,7 @@ test_flow_conv_tables_complete(void)
{
struct rte_flow_error error;
const char *name;
+ size_t size;
int ret;
for (int type = 0; type <= LAST_ITEM_TYPE; type++) {
@@ -167,6 +254,9 @@ test_flow_conv_tables_complete(void)
TEST_ASSERT_EQUAL(ret, (int)sizeof(const char **),
"item type %d has no descriptor", type);
TEST_ASSERT_NOT_NULL(name, "item type %d has no name", type);
+ ret = item_size(type, &size, &error);
+ TEST_ASSERT_EQUAL(ret, (int)sizeof(size_t),
+ "item type %d (%s) has no size", type, name);
}
for (int type = 0; type <= LAST_ACTION_TYPE; type++) {
@@ -399,6 +489,8 @@ static struct unit_test_suite flow_conv_testsuite = {
.setup = NULL,
.teardown = NULL,
.unit_test_cases = {
+ TEST_CASE(test_flow_conv_item_size),
+ TEST_CASE(test_flow_conv_item_size_errors),
TEST_CASE(test_flow_conv_item_name),
TEST_CASE(test_flow_conv_action_name),
TEST_CASE(test_flow_conv_item_default_mask),
diff --git a/doc/guides/rel_notes/release_26_11.rst b/doc/guides/rel_notes/release_26_11.rst
index 9259954c0f7..f3755bf7ab5 100644
--- a/doc/guides/rel_notes/release_26_11.rst
+++ b/doc/guides/rel_notes/release_26_11.rst
@@ -113,10 +113,12 @@ New Features
loss of lock and Tx fault flags.
The SFF-8472 decoder also reports the Rx loss of signal and Tx fault state.
-* **Added flow item default mask lookup.**
+* **Added flow item default mask and size lookup.**
- Added ``RTE_FLOW_CONV_OP_ITEM_DEFAULT_MASK_PTR`` conversion operation
- to ``rte_flow_conv()`` to retrieve the default mask of a flow item type.
+ Added ``RTE_FLOW_CONV_OP_ITEM_DEFAULT_MASK_PTR`` and
+ ``RTE_FLOW_CONV_OP_ITEM_SIZE`` conversion operations
+ to ``rte_flow_conv()`` to retrieve the default mask
+ and the specification structure size of a flow item type.
* **Added internal ethdev flow graph parser helper API.**
diff --git a/lib/ethdev/rte_flow.c b/lib/ethdev/rte_flow.c
index cee0acbd568..ae08e100fa2 100644
--- a/lib/ethdev/rte_flow.c
+++ b/lib/ethdev/rte_flow.c
@@ -1183,7 +1183,7 @@ rte_flow_conv_name(int is_action,
const struct desc_info *const info = &info_rep[!!is_action];
unsigned int type = (uintptr_t)src;
- if (type >= info->num)
+ if (type >= info->num || info->data[type].name == NULL)
return rte_flow_error_set
(error, EINVAL, RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,
"unknown object type to retrieve the name of");
@@ -1203,7 +1203,8 @@ rte_flow_conv_item_default_mask(void *dst,
{
unsigned int type = (uintptr_t)src;
- if (type >= RTE_DIM(rte_flow_desc_item))
+ if (type >= RTE_DIM(rte_flow_desc_item) ||
+ rte_flow_desc_item[type].name == NULL)
return rte_flow_error_set
(error, EINVAL, RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,
"unknown item type to retrieve the default mask of");
@@ -1212,6 +1213,25 @@ rte_flow_conv_item_default_mask(void *dst,
return sizeof(const void **);
}
+/** Retrieve the specification structure size of a flow item type. */
+static int
+rte_flow_conv_item_size(void *dst,
+ const size_t size,
+ const void *src,
+ struct rte_flow_error *error)
+{
+ unsigned int type = (uintptr_t)src;
+
+ if (type >= RTE_DIM(rte_flow_desc_item) ||
+ rte_flow_desc_item[type].name == NULL)
+ return rte_flow_error_set
+ (error, EINVAL, RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,
+ "unknown item type to retrieve the size of");
+ if (size >= sizeof(size_t))
+ *(size_t *)dst = rte_flow_desc_item[type].size;
+ return sizeof(size_t);
+}
+
/** Helper function to convert flow API objects. */
RTE_EXPORT_SYMBOL(rte_flow_conv)
int
@@ -1276,6 +1296,9 @@ rte_flow_conv(enum rte_flow_conv_op op,
case RTE_FLOW_CONV_OP_ITEM_DEFAULT_MASK_PTR:
ret = rte_flow_conv_item_default_mask(dst, size, src, error);
break;
+ case RTE_FLOW_CONV_OP_ITEM_SIZE:
+ ret = rte_flow_conv_item_size(dst, size, src, 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 df8101e4395..ff1ffd03e73 100644
--- a/lib/ethdev/rte_flow.h
+++ b/lib/ethdev/rte_flow.h
@@ -4426,6 +4426,24 @@ enum rte_flow_conv_op {
* @code const void ** @endcode
*/
RTE_FLOW_CONV_OP_ITEM_DEFAULT_MASK_PTR,
+
+ /**
+ * Retrieve the fixed size of an item specification structure.
+ *
+ * Writes the size of the item specification structure to @p dst,
+ * or zero for known item types without one. Does not include
+ * variable-length or externally referenced data (for example, RAW
+ * pattern bytes). Unknown and PMD-private item types return an error.
+ *
+ * No output is written if @p size is smaller than sizeof(size_t).
+ * The return value is sizeof(size_t), not the item structure size.
+ *
+ * - @p src type:
+ * @code (const void *)(uintptr_t)enum rte_flow_item_type @endcode
+ * - @p dst type:
+ * @code size_t * @endcode
+ */
+ RTE_FLOW_CONV_OP_ITEM_SIZE,
};
/**
--
2.52.0
More information about the dev
mailing list