[PATCH v9 2/6] ethdev: add RSS type helper APIs

Lukas Sismis
2026-02-01T20:47:05Z

Add a global RSS type string table and helper functions to convert
between RSS type names and values.
Add unit tests for RSS type helper.

Signed-off-by: Lukas Sismis <sismis@dyna-nic.com>
---
app/test/test_ethdev_api.c | 51 ++++++++++++
doc/guides/rel_notes/release_26_03.rst | 6 ++
lib/ethdev/rte_ethdev.c | 107 +++++++++++++++++++++++++
lib/ethdev/rte_ethdev.h | 55 +++++++++++++
4 files changed, 219 insertions(+)

diff --git a/app/test/test_ethdev_api.c b/app/test/test_ethdev_api.c
index 76afd0345c..7c0cde87a6 100644
--- a/app/test/test_ethdev_api.c
+++ b/app/test/test_ethdev_api.c
@@ -2,6 +2,9 @@
* Copyright (C) 2023, Advanced Micro Devices, Inc.
*/

+#include <stdbool.h>
+#include <string.h>
+
#include <rte_log.h>
#include <rte_ethdev.h>

@@ -162,12 +165,60 @@ ethdev_api_queue_status(void)
return TEST_SUCCESS;
}

+static int
+ethdev_api_rss_type_helpers(void)
+{
+ const struct rte_eth_rss_type_info *tbl;
+ const char *zero_name = NULL;
+ unsigned int i;
+ bool has_zero = false;
+ const char *name;
+ uint64_t type;
+
+ tbl = rte_eth_rss_type_info_get();
+ TEST_ASSERT_NOT_NULL(tbl, "rss type table missing");
+
+ for (i = 0; tbl[i].str != NULL; i++) {
+ type = rte_eth_rss_type_from_str(tbl[i].str);
+ TEST_ASSERT_EQUAL(type, tbl[i].rss_type,
+ "rss type mismatch for %s", tbl[i].str);
+
+ if (tbl[i].rss_type == 0 && !has_zero) {
+ has_zero = true;
+ zero_name = tbl[i].str;
+ }
+
+ name = rte_eth_rss_type_to_str(tbl[i].rss_type);
+ TEST_ASSERT_NOT_NULL(name, "rss type name missing for %s",
+ tbl[i].str);
+ TEST_ASSERT_EQUAL(rte_eth_rss_type_from_str(name), tbl[i].rss_type,
+ "rss type round-trip mismatch for %s", name);
+ }
+
+ TEST_ASSERT(tbl[i].str == NULL, "rss type table not NULL terminated");
+ TEST_ASSERT_EQUAL(rte_eth_rss_type_from_str(NULL), 0,
+ "rss type from NULL should be 0");
+ TEST_ASSERT_EQUAL(rte_eth_rss_type_from_str("not-a-type"), 0,
+ "rss type unknown should be 0");
+ name = rte_eth_rss_type_to_str(0);
+ if (has_zero) {
+ TEST_ASSERT_NOT_NULL(name, "rss type 0 should be defined");
+ TEST_ASSERT(strcmp(name, zero_name) == 0,
+ "rss type 0 name mismatch");
+ } else {
+ TEST_ASSERT(name == NULL, "rss type 0 should be NULL");
+ }
+
+ return TEST_SUCCESS;
+}
+
static struct unit_test_suite ethdev_api_testsuite = {
.suite_name = "ethdev API tests",
.setup = NULL,
.teardown = NULL,
.unit_test_cases = {
TEST_CASE(ethdev_api_queue_status),
+ TEST_CASE(ethdev_api_rss_type_helpers),
/* TODO: Add deferred_start queue status test */
TEST_CASES_END() /**< NULL terminate unit test array */
}
diff --git a/doc/guides/rel_notes/release_26_03.rst b/doc/guides/rel_notes/release_26_03.rst
index 15dabee7a1..84cba63d06 100644
--- a/doc/guides/rel_notes/release_26_03.rst
+++ b/doc/guides/rel_notes/release_26_03.rst
@@ -55,6 +55,12 @@ New Features
Also, make sure to start the actual text at the margin.
=======================================================

+* **Added experimental RSS type helper APIs in ethdev.**
+
+ Added new experimental APIs ``rte_eth_rss_type_info_get()``,
+ ``rte_eth_rss_type_from_str()``, and ``rte_eth_rss_type_to_str()`` to
+ convert between RSS type names and values. These helpers provide a global
+ RSS type string table via ``struct rte_eth_rss_type_info``.

Removed Items
-------------
diff --git a/lib/ethdev/rte_ethdev.c b/lib/ethdev/rte_ethdev.c
index 2659e8d9eb..b572bbf321 100644
--- a/lib/ethdev/rte_ethdev.c
+++ b/lib/ethdev/rte_ethdev.c
@@ -5167,6 +5167,113 @@ rte_eth_find_rss_algo(const char *name, uint32_t *algo)
return -EINVAL;
}

+/* Global RSS type string table. */
+static const struct rte_eth_rss_type_info rte_eth_rss_type_table[] = {
+ /* Group types */
+ { "all", RTE_ETH_RSS_ETH | RTE_ETH_RSS_VLAN | RTE_ETH_RSS_IP |
+ RTE_ETH_RSS_TCP | RTE_ETH_RSS_UDP | RTE_ETH_RSS_SCTP |
+ RTE_ETH_RSS_L2_PAYLOAD | RTE_ETH_RSS_L2TPV3 |
+ RTE_ETH_RSS_ESP | RTE_ETH_RSS_AH | RTE_ETH_RSS_PFCP |
+ RTE_ETH_RSS_GTPU | RTE_ETH_RSS_ECPRI | RTE_ETH_RSS_MPLS |
+ RTE_ETH_RSS_L2TPV2 | RTE_ETH_RSS_IB_BTH },
+ { "none", 0 },
+ { "ip", RTE_ETH_RSS_IP },
+ { "udp", RTE_ETH_RSS_UDP },
+ { "tcp", RTE_ETH_RSS_TCP },
+ { "sctp", RTE_ETH_RSS_SCTP },
+ { "tunnel", RTE_ETH_RSS_TUNNEL },
+ { "vlan", RTE_ETH_RSS_VLAN },
+
+ /* Individual type */
+ { "ipv4", RTE_ETH_RSS_IPV4 },
+ { "ipv4-frag", RTE_ETH_RSS_FRAG_IPV4 },
+ { "ipv4-tcp", RTE_ETH_RSS_NONFRAG_IPV4_TCP },
+ { "ipv4-udp", RTE_ETH_RSS_NONFRAG_IPV4_UDP },
+ { "ipv4-sctp", RTE_ETH_RSS_NONFRAG_IPV4_SCTP },
+ { "ipv4-other", RTE_ETH_RSS_NONFRAG_IPV4_OTHER },
+ { "ipv6", RTE_ETH_RSS_IPV6 },
+ { "ipv6-frag", RTE_ETH_RSS_FRAG_IPV6 },
+ { "ipv6-tcp", RTE_ETH_RSS_NONFRAG_IPV6_TCP },
+ { "ipv6-udp", RTE_ETH_RSS_NONFRAG_IPV6_UDP },
+ { "ipv6-sctp", RTE_ETH_RSS_NONFRAG_IPV6_SCTP },
+ { "ipv6-other", RTE_ETH_RSS_NONFRAG_IPV6_OTHER },
+ { "l2-payload", RTE_ETH_RSS_L2_PAYLOAD },
+ { "ipv6-ex", RTE_ETH_RSS_IPV6_EX },
+ { "ipv6-tcp-ex", RTE_ETH_RSS_IPV6_TCP_EX },
+ { "ipv6-udp-ex", RTE_ETH_RSS_IPV6_UDP_EX },
+ { "port", RTE_ETH_RSS_PORT },
+ { "vxlan", RTE_ETH_RSS_VXLAN },
+ { "geneve", RTE_ETH_RSS_GENEVE },
+ { "nvgre", RTE_ETH_RSS_NVGRE },
+ { "gtpu", RTE_ETH_RSS_GTPU },
+ { "eth", RTE_ETH_RSS_ETH },
+ { "s-vlan", RTE_ETH_RSS_S_VLAN },
+ { "c-vlan", RTE_ETH_RSS_C_VLAN },
+ { "esp", RTE_ETH_RSS_ESP },
+ { "ah", RTE_ETH_RSS_AH },
+ { "l2tpv3", RTE_ETH_RSS_L2TPV3 },
+ { "pfcp", RTE_ETH_RSS_PFCP },
+ { "pppoe", RTE_ETH_RSS_PPPOE },
+ { "ecpri", RTE_ETH_RSS_ECPRI },
+ { "mpls", RTE_ETH_RSS_MPLS },
+ { "ipv4-chksum", RTE_ETH_RSS_IPV4_CHKSUM },
+ { "l4-chksum", RTE_ETH_RSS_L4_CHKSUM },
+ { "l2tpv2", RTE_ETH_RSS_L2TPV2 },
+ { "l3-pre96", RTE_ETH_RSS_L3_PRE96 },
+ { "l3-pre64", RTE_ETH_RSS_L3_PRE64 },
+ { "l3-pre56", RTE_ETH_RSS_L3_PRE56 },
+ { "l3-pre48", RTE_ETH_RSS_L3_PRE48 },
+ { "l3-pre40", RTE_ETH_RSS_L3_PRE40 },
+ { "l3-pre32", RTE_ETH_RSS_L3_PRE32 },
+ { "l2-dst-only", RTE_ETH_RSS_L2_DST_ONLY },
+ { "l2-src-only", RTE_ETH_RSS_L2_SRC_ONLY },
+ { "l4-dst-only", RTE_ETH_RSS_L4_DST_ONLY },
+ { "l4-src-only", RTE_ETH_RSS_L4_SRC_ONLY },
+ { "l3-dst-only", RTE_ETH_RSS_L3_DST_ONLY },
+ { "l3-src-only", RTE_ETH_RSS_L3_SRC_ONLY },
+ { "ipv6-flow-label", RTE_ETH_RSS_IPV6_FLOW_LABEL },
+ { "ib-bth", RTE_ETH_RSS_IB_BTH },
+ { NULL, 0 },
+};
+
+RTE_EXPORT_EXPERIMENTAL_SYMBOL(rte_eth_rss_type_info_get, 26.03)
+const struct rte_eth_rss_type_info *
+rte_eth_rss_type_info_get(void)
+{
+ return rte_eth_rss_type_table;
+}
+
+RTE_EXPORT_EXPERIMENTAL_SYMBOL(rte_eth_rss_type_from_str, 26.03)
+uint64_t
+rte_eth_rss_type_from_str(const char *str)
+{
+ unsigned int i;
+
+ if (str == NULL)
+ return 0;
+
+ for (i = 0; rte_eth_rss_type_table[i].str != NULL; i++) {
+ if (strcmp(rte_eth_rss_type_table[i].str, str) == 0)
+ return rte_eth_rss_type_table[i].rss_type;
+ }
+
+ return 0;
+}
+
+RTE_EXPORT_EXPERIMENTAL_SYMBOL(rte_eth_rss_type_to_str, 26.03)
+const char *
+rte_eth_rss_type_to_str(uint64_t rss_type)
+{
+ unsigned int i;
+
+ for (i = 0; rte_eth_rss_type_table[i].str != NULL; i++) {
+ if (rte_eth_rss_type_table[i].rss_type == rss_type)
+ return rte_eth_rss_type_table[i].str;
+ }
+
+ return NULL;
+}
+
RTE_EXPORT_SYMBOL(rte_eth_dev_udp_tunnel_port_add)
int
rte_eth_dev_udp_tunnel_port_add(uint16_t port_id,
diff --git a/lib/ethdev/rte_ethdev.h b/lib/ethdev/rte_ethdev.h
index a66c2abbdb..e7bb7384a6 100644
--- a/lib/ethdev/rte_ethdev.h
+++ b/lib/ethdev/rte_ethdev.h
@@ -4889,6 +4889,61 @@ __rte_experimental
int
rte_eth_find_rss_algo(const char *name, uint32_t *algo);

+/**
+ * RSS type name mapping entry.
+ *
+ * The table returned by rte_eth_rss_type_info_get() is terminated by an entry
+ * with a NULL string.
+ */
+struct rte_eth_rss_type_info {
+ const char *str; /**< RSS type name. */
+ uint64_t rss_type; /**< RSS type value (RTE_ETH_RSS_*). */
+};
+
+/**
+ * @warning
+ * @b EXPERIMENTAL: this API may change, or be removed, without prior notice.
+ *
+ * Get the global RSS type string table.
+ *
+ * @return
+ * Pointer to a table of RSS type string mappings terminated by an entry with
+ * a NULL string.
+ */
+__rte_experimental
+const struct rte_eth_rss_type_info *
+rte_eth_rss_type_info_get(void);
+
+/**
+ * @warning
+ * @b EXPERIMENTAL: this API may change, or be removed, without prior notice.
+ *
+ * Convert an RSS type name to its value.
+ *
+ * @param str
+ * RSS type name.
+ * @return
+ * RSS type value (RTE_ETH_RSS_*), or 0 if not found or if str is NULL.
+ */
+__rte_experimental
+uint64_t
+rte_eth_rss_type_from_str(const char *str);
+
+/**
+ * @warning
+ * @b EXPERIMENTAL: this API may change, or be removed, without prior notice.
+ *
+ * Convert an RSS type value to its name.
+ *
+ * @param rss_type
+ * RSS type value (RTE_ETH_RSS_*).
+ * @return
+ * RSS type name, or NULL if the value cannot be recognized.
+ */
+__rte_experimental
+const char *
+rte_eth_rss_type_to_str(uint64_t rss_type);
+
/**
* Add UDP tunneling port for a type of tunnel.
*
--
2.43.7