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