Device arguments naming a NUMA socket are common, and every driver that
takes one open codes the same range check against RTE_MAX_NUMA_NODES.
They do not agree on what the range is: dlb2 accepts RTE_MAX_NUMA_NODES
itself, and turbo_sw and bbdev_null check only the upper bound, so a
negative socket id is taken as valid.

Add a handler for these:

    rte_kvargs_handle_socket_id

It stores through an int and accepts -1, which is SOCKET_ID_ANY, through
RTE_MAX_NUMA_NODES - 1.

The bound is the compile time maximum rather than the sockets present on
the running system, which is what the open coded checks used. Validating
against rte_socket_count() would also make kvargs depend on EAL, which
depends on kvargs in turn.

SOCKET_ID_ANY is spelled as a literal -1 rather than included from
rte_memory.h for the same reason. The value is part of the ABI.

No handler is added for lcore ids. There is no caller for one: the
drivers that take a core argument either parse a list, as crypto/scheduler
does with its coremask, or dispatch many keys through one shared handler,
as mlx5 does with service_core. One can be added when a user appears.

Nor is one added for queue ids or queue counts. Those look similar but
are not: some drivers count from one and others from zero, and the useful
bound is nearly always a hardware limit well below
RTE_MAX_QUEUES_PER_PORT, which rte_kvargs_to_uint() already covers.

Signed-off-by: Stephen Hemminger <[email protected]>
---
 app/test/test_kvargs.c                 | 31 ++++++++++++++++++++++++++
 doc/guides/rel_notes/release_26_11.rst |  2 ++
 lib/kvargs/rte_kvargs.c                | 18 +++++++++++++++
 lib/kvargs/rte_kvargs.h                | 27 ++++++++++++++++++++++
 4 files changed, 78 insertions(+)

diff --git a/app/test/test_kvargs.c b/app/test/test_kvargs.c
index b74dfd6acb..f05c7918e9 100644
--- a/app/test/test_kvargs.c
+++ b/app/test/test_kvargs.c
@@ -515,6 +515,36 @@ test_handle_bool(void)
        return TEST_SUCCESS;
 }
 
+static int
+test_handle_socket_id(void)
+{
+       char buf[32];
+
+       /* SOCKET_ID_ANY is a valid socket id, anything below it is not. */
+       CHECK_GOOD(rte_kvargs_handle_socket_id, int, "-1", -1);
+       CHECK_GOOD(rte_kvargs_handle_socket_id, int, "0", 0);
+       CHECK_BAD(rte_kvargs_handle_socket_id, int, "-2");
+       CHECK_BAD(rte_kvargs_handle_socket_id, int, "");
+       CHECK_BAD(rte_kvargs_handle_socket_id, int, "1x");
+
+       /* The last valid value, and the first one past it. */
+       {
+               int socket = 0x5a;
+
+               snprintf(buf, sizeof(buf), "%d", RTE_MAX_NUMA_NODES - 1);
+               TEST_ASSERT_SUCCESS(handle_one(rte_kvargs_handle_socket_id, buf,
+                                              &socket), "socket id %s 
rejected", buf);
+               TEST_ASSERT_EQUAL(socket, RTE_MAX_NUMA_NODES - 1, "wrong socket 
id");
+
+               snprintf(buf, sizeof(buf), "%d", RTE_MAX_NUMA_NODES);
+               TEST_ASSERT_FAIL(handle_one(rte_kvargs_handle_socket_id, buf,
+                                           &socket), "socket id %s accepted", 
buf);
+               TEST_ASSERT_EQUAL(socket, RTE_MAX_NUMA_NODES - 1, "target 
clobbered");
+       }
+
+       return TEST_SUCCESS;
+}
+
 static int
 test_kvargs_to_range(void)
 {
@@ -574,6 +604,7 @@ static struct unit_test_suite kvargs_test_suite  = {
                TEST_CASE(test_handle_unsigned),
                TEST_CASE(test_handle_signed),
                TEST_CASE(test_handle_bool),
+               TEST_CASE(test_handle_socket_id),
                TEST_CASE(test_kvargs_to_range),
                TEST_CASES_END() /**< NULL terminate unit test array */
        }
diff --git a/doc/guides/rel_notes/release_26_11.rst 
b/doc/guides/rel_notes/release_26_11.rst
index c175fe089b..dbf7923b66 100644
--- a/doc/guides/rel_notes/release_26_11.rst
+++ b/doc/guides/rel_notes/release_26_11.rst
@@ -68,6 +68,8 @@ New Features
   * ``rte_kvargs_handle_i8``, ``rte_kvargs_handle_i16``,
     ``rte_kvargs_handle_i32``, ``rte_kvargs_handle_i64``,
     ``rte_kvargs_handle_int`` and ``rte_kvargs_handle_long``
+  * ``rte_kvargs_handle_socket_id``, which accepts ``SOCKET_ID_ANY``
+    through ``RTE_MAX_NUMA_NODES`` - 1
   * ``rte_kvargs_handle_bool``, accepting ``1``, ``y``, ``yes``, ``on``,
     ``true`` and their negative counterparts. A bare ``key`` means true;
     an empty ``key=`` is rejected.
diff --git a/lib/kvargs/rte_kvargs.c b/lib/kvargs/rte_kvargs.c
index c3bd199f3e..3f45ea519b 100644
--- a/lib/kvargs/rte_kvargs.c
+++ b/lib/kvargs/rte_kvargs.c
@@ -749,3 +749,21 @@ rte_kvargs_handle_bool(const char *key, const char *value, 
void *opaque)
 
        return -EINVAL;
 }
+
+RTE_EXPORT_EXPERIMENTAL_SYMBOL(rte_kvargs_handle_socket_id, 26.11)
+int
+rte_kvargs_handle_socket_id(const char *key, const char *value, void *opaque)
+{
+       int64_t val;
+       int ret;
+
+       /* SOCKET_ID_ANY, which is -1, is a valid socket id. It is spelled
+        * out here rather than included from EAL, which kvargs sits below.
+        */
+       ret = kvargs_store_int(key, value, opaque, -1,
+                              RTE_MAX_NUMA_NODES - 1, &val);
+       if (ret == 0)
+               *(int *)opaque = (int)val;
+
+       return ret;
+}
diff --git a/lib/kvargs/rte_kvargs.h b/lib/kvargs/rte_kvargs.h
index 118cf3c79b..acc15607bc 100644
--- a/lib/kvargs/rte_kvargs.h
+++ b/lib/kvargs/rte_kvargs.h
@@ -359,6 +359,33 @@ int rte_kvargs_handle_size(const char *key, const char 
*value, void *opaque);
 __rte_experimental
 int rte_kvargs_handle_bool(const char *key, const char *value, void *opaque);
 
+/**
+ * @warning
+ * @b EXPERIMENTAL: this API may change without prior notice.
+ *
+ * Convert a key/value pair to a NUMA socket id.
+ *
+ * Accepts -1, which is SOCKET_ID_ANY, through RTE_MAX_NUMA_NODES - 1.
+ * The bound is the compile time maximum rather than the set of sockets
+ * present on the running system, matching what drivers checked before
+ * this helper existed.
+ *
+ * @param key
+ *   The key, used for error reporting only. May be NULL.
+ * @param value
+ *   The value to convert.
+ * @param opaque
+ *   Pointer to an ``int`` to store the result into. On error it is left
+ *   unmodified.
+ *
+ * @return
+ *   - 0 on success.
+ *   - -EINVAL if the value is malformed, or if @p opaque is NULL.
+ *   - -ERANGE if the value is not a valid socket id.
+ */
+__rte_experimental
+int rte_kvargs_handle_socket_id(const char *key, const char *value, void 
*opaque);
+
 /**
  * @warning
  * @b EXPERIMENTAL: this API may change without prior notice.
-- 
2.53.0

Reply via email to