Add a global RSS type string table and helper functions to convert
between RSS type names and values. Introduce rte_port_id_t and
rte_queue_id_t typedefs for shared port/queue identifiers, and add
unit tests for RSS type helper round-trips.

Signed-off-by: Lukas Sismis <[email protected]>
---
 app/test/test_ethdev_api.c |  51 ++++++++++++++++++
 lib/ethdev/rte_ethdev.c    | 107 +++++++++++++++++++++++++++++++++++++
 lib/ethdev/rte_ethdev.h    |  60 +++++++++++++++++++++
 3 files changed, 218 insertions(+)

diff --git a/app/test/test_ethdev_api.c b/app/test/test_ethdev_api.c
index 76afd0345c..77fa5f4ffc 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 int32_t
+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/lib/ethdev/rte_ethdev.c b/lib/ethdev/rte_ethdev.c
index 2659e8d9eb..2763a79ea4 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, 25.11)
+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, 25.11)
+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, 25.11)
+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..18355559d5 100644
--- a/lib/ethdev/rte_ethdev.h
+++ b/lib/ethdev/rte_ethdev.h
@@ -168,6 +168,11 @@
 #include <rte_config.h>
 #include <rte_power_intrinsics.h>
 
+/** Ethernet device port identifier type. */
+typedef uint16_t rte_port_id_t;
+/** Ethernet device queue identifier type. */
+typedef uint16_t rte_queue_id_t;
+
 #include "rte_ethdev_trace_fp.h"
 #include "rte_dev_info.h"
 
@@ -4889,6 +4894,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

Reply via email to