From: Stephen Hemminger <stephen@networkplumber.org>
To: dev@dpdk.org
Cc: Stephen Hemminger <stephen@networkplumber.org>
Subject: [PATCH v2 01/61] kvargs: add numeric conversion helpers
Date: Tue, 29 Sep 2026 09:36:04 -0700 [thread overview]
Message-ID: <20260929163800.1108305-2-stephen@networkplumber.org> (raw)
In-Reply-To: <20260929163800.1108305-1-stephen@networkplumber.org>
Drivers which take numeric values in devargs each open code the
conversion from string to integer, and often get it wrong.
A survey of the tree finds at least fifteen separate
implementations of "parse an unsigned integer devarg", of which two are
exported from lib/ and byte for byte identical to each other.
The recurring bugs are:
- atoi() is used, so overflow is undefined and nothing is validated;
- errno is checked without being reset first, so an unrelated earlier
failure rejects a valid value;
- errno is checked but endptr is not, so "foo" is silently accepted
as zero;
- endptr is checked but errno is not, so an overflowing value is
accepted as ULLONG_MAX;
- the result is stored into a narrower type with no range check, so
nb_desc=65537 silently becomes 1;
- strtoul() is used for an unsigned target, so a leading '-' is
accepted and wrapped around, and dev_caps_mask=-1 enables
everything;
- the value is dereferenced without checking for NULL, so a key given
with no value segfaults;
- base 0 is passed, so a leading zero unexpectedly selects octal.
Add a set of helpers matching arg_handler_t, so they can be passed
straight to rte_kvargs_process(), covering the integer types drivers
actually store into. Each validates the whole string and only writes
the target on success, so a caller supplied default survives a bad
argument.
Add rte_kvargs_handle_bool for on/off style arguments. It accepts the
word forms which only sfc supports today, and treats a key given
without a value as true.
Where a driver needs a range narrower than the target type, expose the
underlying rte_kvargs_to_uint and rte_kvargs_to_int.
Octal is deliberately not supported: no driver documents it, and
reading "010" as eight has been a recurring surprise.
Signed-off-by: Stephen Hemminger <stephen@networkplumber.org>
---
app/test/test_kvargs.c | 221 +++++++++++++
doc/guides/prog_guide/devargs.rst | 18 +
doc/guides/rel_notes/release_26_11.rst | 20 ++
lib/kvargs/rte_kvargs.c | 441 +++++++++++++++++++++++++
lib/kvargs/rte_kvargs.h | 186 +++++++++++
5 files changed, 886 insertions(+)
diff --git a/app/test/test_kvargs.c b/app/test/test_kvargs.c
index a14b75948a..b74dfd6acb 100644
--- a/app/test/test_kvargs.c
+++ b/app/test/test_kvargs.c
@@ -2,6 +2,8 @@
* Copyright 2014 6WIND S.A.
*/
+#include <errno.h>
+#include <stdint.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
@@ -328,6 +330,221 @@ static int test_invalid_kvargs(void)
return -1;
}
+/* Check the numeric conversion helpers on a value passed through kvargs. */
+static int
+handle_one(arg_handler_t handler, const char *value, void *opaque)
+{
+ struct rte_kvargs *kvlist;
+ char args[128];
+ int ret;
+
+ if (value != NULL)
+ snprintf(args, sizeof(args), "k=%s", value);
+ else
+ snprintf(args, sizeof(args), "k");
+
+ kvlist = rte_kvargs_parse(args, NULL);
+ if (kvlist == NULL)
+ return -1;
+
+ ret = rte_kvargs_process_opt(kvlist, "k", handler, opaque);
+ rte_kvargs_free(kvlist);
+
+ /* rte_kvargs_process_opt() flattens the handler error to -1. */
+ return ret;
+}
+
+/* A handler must accept a good value, and leave the target alone otherwise. */
+#define CHECK_GOOD(handler, type, str, expected) do { \
+ type v = (type)0x5a; \
+ TEST_ASSERT_SUCCESS(handle_one(handler, str, &v), \
+ "%s rejected \"%s\"", #handler, str); \
+ TEST_ASSERT_EQUAL(v, (type)(expected), \
+ "%s(\"%s\") gave the wrong value", #handler, str); \
+} while (0)
+
+#define CHECK_BAD(handler, type, str) do { \
+ type v = (type)0x5a; \
+ TEST_ASSERT_FAIL(handle_one(handler, str, &v), \
+ "%s accepted \"%s\"", #handler, str); \
+ TEST_ASSERT_EQUAL(v, (type)0x5a, \
+ "%s clobbered the target on \"%s\"", #handler, str); \
+} while (0)
+
+static int
+test_handle_unsigned(void)
+{
+ CHECK_GOOD(rte_kvargs_handle_u8, uint8_t, "0", 0);
+ CHECK_GOOD(rte_kvargs_handle_u8, uint8_t, "255", 255);
+ CHECK_GOOD(rte_kvargs_handle_u8, uint8_t, "0xff", 255);
+ CHECK_GOOD(rte_kvargs_handle_u8, uint8_t, "0XFF", 255);
+ CHECK_GOOD(rte_kvargs_handle_u8, uint8_t, "+7", 7);
+ /* A leading zero must not select octal. */
+ CHECK_GOOD(rte_kvargs_handle_u8, uint8_t, "010", 10);
+ CHECK_BAD(rte_kvargs_handle_u8, uint8_t, "256");
+ CHECK_BAD(rte_kvargs_handle_u8, uint8_t, "-1");
+
+ CHECK_GOOD(rte_kvargs_handle_u16, uint16_t, "65535", 65535);
+ CHECK_BAD(rte_kvargs_handle_u16, uint16_t, "65536");
+
+ CHECK_GOOD(rte_kvargs_handle_u32, uint32_t, "4294967295", UINT32_MAX);
+ CHECK_BAD(rte_kvargs_handle_u32, uint32_t, "4294967296");
+
+ CHECK_GOOD(rte_kvargs_handle_u64, uint64_t, "18446744073709551615",
+ UINT64_MAX);
+ CHECK_GOOD(rte_kvargs_handle_u64, uint64_t, "0xffffffffffffffff",
+ UINT64_MAX);
+ CHECK_BAD(rte_kvargs_handle_u64, uint64_t, "18446744073709551616");
+
+ CHECK_GOOD(rte_kvargs_handle_uint, unsigned int, "42", 42);
+ CHECK_GOOD(rte_kvargs_handle_size, size_t, "42", 42);
+
+ /* Malformed values, rejected for every width. */
+ CHECK_BAD(rte_kvargs_handle_u32, uint32_t, "");
+ CHECK_BAD(rte_kvargs_handle_u32, uint32_t, "abc");
+ CHECK_BAD(rte_kvargs_handle_u32, uint32_t, "12abc");
+ CHECK_BAD(rte_kvargs_handle_u32, uint32_t, "12 34");
+ CHECK_BAD(rte_kvargs_handle_u32, uint32_t, "0x");
+ CHECK_BAD(rte_kvargs_handle_u32, uint32_t, "0x0x10");
+ CHECK_BAD(rte_kvargs_handle_u32, uint32_t, "0X0X10");
+ CHECK_BAD(rte_kvargs_handle_u32, uint32_t, "--1");
+ CHECK_BAD(rte_kvargs_handle_u32, uint32_t, "+-1");
+ /* strtoull() would skip the space and negate what follows. */
+ CHECK_BAD(rte_kvargs_handle_u32, uint32_t, "+ 1");
+ CHECK_BAD(rte_kvargs_handle_u32, uint32_t, "- 1");
+ CHECK_BAD(rte_kvargs_handle_u32, uint32_t, "+ -1");
+ /* Trailing white space is fine, though. */
+ CHECK_GOOD(rte_kvargs_handle_u32, uint32_t, " 12 ", 12);
+
+ /* A key with no value at all. */
+ {
+ uint32_t v = 0x5a;
+
+ TEST_ASSERT_FAIL(handle_one(rte_kvargs_handle_u32, NULL, &v),
+ "u32 accepted a key with no value");
+ TEST_ASSERT_EQUAL(v, 0x5aU, "target clobbered");
+ }
+
+ return TEST_SUCCESS;
+}
+
+static int
+test_handle_signed(void)
+{
+ CHECK_GOOD(rte_kvargs_handle_i8, int8_t, "-128", -128);
+ CHECK_GOOD(rte_kvargs_handle_i8, int8_t, "127", 127);
+ CHECK_BAD(rte_kvargs_handle_i8, int8_t, "-129");
+ CHECK_BAD(rte_kvargs_handle_i8, int8_t, "128");
+
+ CHECK_GOOD(rte_kvargs_handle_i16, int16_t, "-32768", -32768);
+ CHECK_BAD(rte_kvargs_handle_i16, int16_t, "32768");
+
+ CHECK_GOOD(rte_kvargs_handle_i32, int32_t, "-2147483648", INT32_MIN);
+ CHECK_BAD(rte_kvargs_handle_i32, int32_t, "2147483648");
+
+ /* INT64_MIN has a magnitude one past INT64_MAX. */
+ CHECK_GOOD(rte_kvargs_handle_i64, int64_t, "-9223372036854775808",
+ INT64_MIN);
+ CHECK_GOOD(rte_kvargs_handle_i64, int64_t, "9223372036854775807",
+ INT64_MAX);
+ CHECK_BAD(rte_kvargs_handle_i64, int64_t, "9223372036854775808");
+ CHECK_BAD(rte_kvargs_handle_i64, int64_t, "-9223372036854775809");
+
+ /* A sign in front of a hex value. */
+ CHECK_GOOD(rte_kvargs_handle_i32, int32_t, "-0x10", -16);
+ CHECK_BAD(rte_kvargs_handle_i32, int32_t, "-0x0x10");
+
+ CHECK_GOOD(rte_kvargs_handle_int, int, "-1", -1);
+ CHECK_GOOD(rte_kvargs_handle_int, int, "+1", 1);
+ CHECK_BAD(rte_kvargs_handle_int, int, "");
+ CHECK_BAD(rte_kvargs_handle_int, int, "1x");
+ CHECK_BAD(rte_kvargs_handle_int, int, "-");
+ CHECK_BAD(rte_kvargs_handle_int, int, "- 1");
+ CHECK_BAD(rte_kvargs_handle_int, int, "--1");
+
+ CHECK_GOOD(rte_kvargs_handle_long, long, "-1", -1);
+ CHECK_GOOD(rte_kvargs_handle_long, long, "+1", 1);
+ CHECK_BAD(rte_kvargs_handle_long, long, "");
+ CHECK_BAD(rte_kvargs_handle_long, long, "1x");
+
+ CHECK_GOOD(rte_kvargs_handle_ulong, unsigned long, "1", 1);
+ CHECK_GOOD(rte_kvargs_handle_ulong, unsigned long, "0x10", 16);
+ CHECK_BAD(rte_kvargs_handle_ulong, unsigned long, "-1");
+ CHECK_BAD(rte_kvargs_handle_ulong, unsigned long, "1x");
+
+ return TEST_SUCCESS;
+}
+
+static int
+test_handle_bool(void)
+{
+ static const char * const yes[] = {
+ "1", "y", "Y", "yes", "YES", "on", "On", "true", "TRUE",
+ };
+ static const char * const no[] = {
+ "0", "n", "N", "no", "NO", "off", "Off", "false", "FALSE",
+ };
+ unsigned int i;
+ bool v;
+
+ for (i = 0; i < RTE_DIM(yes); i++) {
+ v = false;
+ TEST_ASSERT_SUCCESS(handle_one(rte_kvargs_handle_bool, yes[i], &v),
+ "bool rejected \"%s\"", yes[i]);
+ TEST_ASSERT(v, "\"%s\" should be true", yes[i]);
+ }
+
+ for (i = 0; i < RTE_DIM(no); i++) {
+ v = true;
+ TEST_ASSERT_SUCCESS(handle_one(rte_kvargs_handle_bool, no[i], &v),
+ "bool rejected \"%s\"", no[i]);
+ TEST_ASSERT(!v, "\"%s\" should be false", no[i]);
+ }
+
+ /* A bare key is enough to enable the option. */
+ v = false;
+ TEST_ASSERT_SUCCESS(handle_one(rte_kvargs_handle_bool, NULL, &v),
+ "bool rejected a key with no value");
+ TEST_ASSERT(v, "a key with no value should be true");
+
+ /* But a blank value is not a missing one. */
+ CHECK_BAD(rte_kvargs_handle_bool, bool, "");
+ CHECK_BAD(rte_kvargs_handle_bool, bool, "2");
+ CHECK_BAD(rte_kvargs_handle_bool, bool, "yep");
+
+ return TEST_SUCCESS;
+}
+
+static int
+test_kvargs_to_range(void)
+{
+ uint64_t u = 0x5a;
+ int64_t s = 0x5a;
+
+ TEST_ASSERT_SUCCESS(rte_kvargs_to_uint("10", 0, 10, &u), "10 in [0,10]");
+ TEST_ASSERT_EQUAL(u, 10U, "wrong value");
+
+ TEST_ASSERT_EQUAL(rte_kvargs_to_uint("11", 0, 10, &u), -ERANGE,
+ "11 should be out of [0,10]");
+ TEST_ASSERT_EQUAL(u, 10U, "target clobbered on range error");
+
+ TEST_ASSERT_EQUAL(rte_kvargs_to_uint("0", 1, 10, &u), -ERANGE,
+ "0 should be out of [1,10]");
+ TEST_ASSERT_EQUAL(rte_kvargs_to_uint(NULL, 0, 10, &u), -EINVAL,
+ "NULL should be rejected");
+ TEST_ASSERT_EQUAL(rte_kvargs_to_uint("x", 0, 10, &u), -EINVAL,
+ "\"x\" should be rejected");
+ TEST_ASSERT_EQUAL(rte_kvargs_to_uint("5", 0, 10, NULL), -EINVAL,
+ "a NULL result should be rejected");
+
+ TEST_ASSERT_SUCCESS(rte_kvargs_to_int("-5", -10, 10, &s), "-5 in [-10,10]");
+ TEST_ASSERT_EQUAL(s, -5, "wrong value");
+ TEST_ASSERT_EQUAL(rte_kvargs_to_int("-11", -10, 10, &s), -ERANGE,
+ "-11 should be out of [-10,10]");
+
+ return TEST_SUCCESS;
+}
+
static struct unit_test_suite kvargs_test_suite = {
.suite_name = "Kvargs Unit Test Suite",
.setup = NULL,
@@ -354,6 +571,10 @@ static struct unit_test_suite kvargs_test_suite = {
TEST_CASE(test_parse_empty_elements),
TEST_CASE(test_parse_with_only_key),
TEST_CASE(test_invalid_kvargs),
+ TEST_CASE(test_handle_unsigned),
+ TEST_CASE(test_handle_signed),
+ TEST_CASE(test_handle_bool),
+ TEST_CASE(test_kvargs_to_range),
TEST_CASES_END() /**< NULL terminate unit test array */
}
};
diff --git a/doc/guides/prog_guide/devargs.rst b/doc/guides/prog_guide/devargs.rst
index c8a7224aa0..b73ad20cf6 100644
--- a/doc/guides/prog_guide/devargs.rst
+++ b/doc/guides/prog_guide/devargs.rst
@@ -248,6 +248,24 @@ PMD drivers can parse devargs using the kvargs library:
return 0;
}
+Rather than writing a handler for each numeric argument, use the
+conversion handlers provided by kvargs, which do the range checking:
+
+.. code-block:: c
+
+ uint16_t queues = 1;
+ bool scalar = false;
+
+ rte_kvargs_process(kvlist, "queues", rte_kvargs_handle_u16, &queues);
+ rte_kvargs_process_opt(kvlist, "scalar", rte_kvargs_handle_bool, &scalar);
+
+Boolean arguments accept ``1``, ``y``, ``yes``, ``on`` and ``true``,
+case insensitively, and their negative counterparts. A bare ``scalar``
+with no value means true, but reaches the handler only through
+rte_kvargs_process_opt(); rte_kvargs_process() rejects a missing value
+first. An empty ``scalar=`` is rejected, since that is what an unset
+shell variable expands to.
+
For Ethernet devices, use ``rte_eth_devargs_parse()``
to parse standard Ethernet arguments like representors:
diff --git a/doc/guides/rel_notes/release_26_11.rst b/doc/guides/rel_notes/release_26_11.rst
index e027c7a27f..5cfe3d4265 100644
--- a/doc/guides/rel_notes/release_26_11.rst
+++ b/doc/guides/rel_notes/release_26_11.rst
@@ -138,6 +138,26 @@ New Features
Added ``rte_bbdev_queue_stats_get()`` function to retrieve statistics
for a specific queue, complementing the existing device-level statistics API.
+* **Added numeric conversion helpers to kvargs.**
+
+ Added a set of ``arg_handler_t`` compatible helpers which convert a device
+ argument value into a numeric variable, so that drivers no longer need to
+ open code the conversion and its validation:
+
+ * ``rte_kvargs_handle_u8``, ``rte_kvargs_handle_u16``,
+ ``rte_kvargs_handle_u32``, ``rte_kvargs_handle_u64``,
+ ``rte_kvargs_handle_uint``, ``rte_kvargs_handle_ulong``
+ and ``rte_kvargs_handle_size``
+ * ``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_bool``, accepting ``1``, ``y``, ``yes``, ``on``,
+ ``true`` and their negative counterparts. A bare ``key`` means true;
+ an empty ``key=`` is rejected.
+
+ Added ``rte_kvargs_to_uint`` and ``rte_kvargs_to_int`` for the cases where
+ a driver needs a narrower range than the target type allows.
+
Removed Items
-------------
diff --git a/lib/kvargs/rte_kvargs.c b/lib/kvargs/rte_kvargs.c
index 4e3198b33f..3b961a19a8 100644
--- a/lib/kvargs/rte_kvargs.c
+++ b/lib/kvargs/rte_kvargs.c
@@ -3,15 +3,28 @@
* Copyright(c) 2014 6WIND S.A.
*/
+#include <ctype.h>
+#include <errno.h>
+#include <inttypes.h>
+#include <limits.h>
#include <string.h>
#include <stdlib.h>
#include <stdbool.h>
+#include <stdint.h>
#include <eal_export.h>
+#include <rte_common.h>
+#include <rte_log.h>
#include <rte_os_shim.h>
#include "rte_kvargs.h"
+RTE_LOG_REGISTER_DEFAULT(kvargs_logtype, INFO);
+#define RTE_LOGTYPE_KVARGS kvargs_logtype
+
+#define KVARGS_LOG(level, ...) \
+ RTE_LOG_LINE(level, KVARGS, __VA_ARGS__)
+
/*
* Receive a string with a list of arguments following the pattern
* key=value,key=value,... and insert them into the list.
@@ -309,3 +322,431 @@ rte_kvargs_parse_delim(const char *args, const char * const valid_keys[],
free(copy);
return kvlist;
}
+
+/*
+ * Determine the base of a numeric value and skip over its prefix.
+ *
+ * Only decimal and 0x/0X hexadecimal are recognized. Octal is deliberately
+ * not supported: no driver documents it, and silently reading "010" as eight
+ * has been a recurring source of surprise.
+ *
+ * Returns the base, and advances *str past the "0x" prefix if there is one.
+ * Returns 0 if what follows the prefix is a second one: strtoull() would
+ * strip that itself, making "0x0x10" sixteen rather than the garbage it is.
+ */
+static int
+kvargs_get_base(const char **str)
+{
+ const char *s = *str;
+
+ if (s[0] == '0' && (s[1] == 'x' || s[1] == 'X') &&
+ isxdigit((unsigned char)s[2])) {
+ s += 2;
+ if (s[0] == '0' && (s[1] == 'x' || s[1] == 'X'))
+ return 0;
+ *str = s;
+ return 16;
+ }
+
+ return 10;
+}
+
+/* Skip trailing white space, and tell whether anything else is left. */
+static bool
+kvargs_at_end(const char *str)
+{
+ while (isspace((unsigned char)*str))
+ str++;
+
+ return *str == '\0';
+}
+
+/*
+ * Consume an optional sign, and report whether it was negative.
+ *
+ * strtoull() skips white space and a sign of its own, and negates on '-',
+ * so the sign has to be taken away from it: it is handled here and anything
+ * that follows must be a digit or an 0x prefix. That rejects "+-1" and
+ * "- 1", which strtoull() would otherwise accept.
+ */
+static bool
+kvargs_get_sign(const char **str)
+{
+ const char *s = *str;
+ bool negative;
+
+ while (isspace((unsigned char)*s))
+ s++;
+
+ negative = (*s == '-');
+ if (*s == '-' || *s == '+')
+ s++;
+
+ *str = s;
+ return negative;
+}
+
+RTE_EXPORT_EXPERIMENTAL_SYMBOL(rte_kvargs_to_uint, 26.11)
+int
+rte_kvargs_to_uint(const char *value, uint64_t min, uint64_t max,
+ uint64_t *result)
+{
+ const char *str = value;
+ unsigned long long val;
+ char *endptr;
+ int base;
+
+ if (str == NULL || result == NULL)
+ return -EINVAL;
+
+ /* "-1" would otherwise be silently wrapped around to UINT64_MAX. */
+ if (kvargs_get_sign(&str))
+ return -EINVAL;
+
+ base = kvargs_get_base(&str);
+ if (base == 0)
+ return -EINVAL; /* doubled 0x prefix */
+
+ /* Nothing may sit between the sign and the digits. */
+ if (!isxdigit((unsigned char)*str))
+ return -EINVAL;
+
+ errno = 0;
+ val = strtoull(str, &endptr, base);
+ if (endptr == str)
+ return -EINVAL; /* no digits in this base */
+ if (errno == ERANGE)
+ return -ERANGE;
+ if (errno != 0)
+ return -EINVAL;
+ if (!kvargs_at_end(endptr))
+ return -EINVAL; /* trailing garbage */
+
+ if (val < min || val > max)
+ return -ERANGE;
+
+ *result = val;
+ return 0;
+}
+
+RTE_EXPORT_EXPERIMENTAL_SYMBOL(rte_kvargs_to_int, 26.11)
+int
+rte_kvargs_to_int(const char *value, int64_t min, int64_t max, int64_t *result)
+{
+ const char *str = value;
+ unsigned long long mag;
+ char *endptr;
+ bool negative;
+ int64_t val;
+ int base;
+
+ if (str == NULL || result == NULL)
+ return -EINVAL;
+
+ negative = kvargs_get_sign(&str);
+ base = kvargs_get_base(&str);
+ if (base == 0)
+ return -EINVAL; /* doubled 0x prefix */
+
+ /* Nothing may sit between the sign and the digits. */
+ if (!isxdigit((unsigned char)*str))
+ return -EINVAL;
+
+ /*
+ * The sign is consumed above, so that the 0x prefix can be found
+ * behind it, and the magnitude is parsed unsigned. Letting strtoll()
+ * do the whole job instead would reject INT64_MIN, whose magnitude is
+ * one past INT64_MAX.
+ */
+ errno = 0;
+ mag = strtoull(str, &endptr, base);
+ if (endptr == str)
+ return -EINVAL;
+ if (errno == ERANGE)
+ return -ERANGE;
+ if (errno != 0)
+ return -EINVAL;
+ if (!kvargs_at_end(endptr))
+ return -EINVAL;
+
+ if (negative) {
+ if (mag > (unsigned long long)INT64_MAX + 1)
+ return -ERANGE;
+ /* Negate in unsigned space; -INT64_MIN would overflow. */
+ val = (int64_t)(-(uint64_t)mag);
+ } else {
+ if (mag > INT64_MAX)
+ return -ERANGE;
+ val = (int64_t)mag;
+ }
+
+ if (val < min || val > max)
+ return -ERANGE;
+
+ *result = val;
+ return 0;
+}
+
+/*
+ * The typed handlers below share this shape: convert with a range matching
+ * the target type, then store. The target is written only on success, so a
+ * caller-supplied default survives a bad argument.
+ */
+static int
+kvargs_store_uint(const char *key, const char *value, void *opaque,
+ uint64_t max, uint64_t *val)
+{
+ int ret;
+
+ if (opaque == NULL)
+ return -EINVAL;
+
+ ret = rte_kvargs_to_uint(value, 0, max, val);
+ if (ret < 0)
+ KVARGS_LOG(ERR, "invalid value \"%s\" for key \"%s\", expected 0..%" PRIu64,
+ value != NULL ? value : "", key != NULL ? key : "", max);
+
+ return ret;
+}
+
+static int
+kvargs_store_int(const char *key, const char *value, void *opaque,
+ int64_t min, int64_t max, int64_t *val)
+{
+ int ret;
+
+ if (opaque == NULL)
+ return -EINVAL;
+
+ ret = rte_kvargs_to_int(value, min, max, val);
+ if (ret < 0)
+ KVARGS_LOG(ERR,
+ "invalid value \"%s\" for key \"%s\", expected %" PRId64 "..%" PRId64,
+ value != NULL ? value : "", key != NULL ? key : "",
+ min, max);
+
+ return ret;
+}
+
+RTE_EXPORT_EXPERIMENTAL_SYMBOL(rte_kvargs_handle_u8, 26.11)
+int
+rte_kvargs_handle_u8(const char *key, const char *value, void *opaque)
+{
+ uint64_t val;
+ int ret;
+
+ ret = kvargs_store_uint(key, value, opaque, UINT8_MAX, &val);
+ if (ret == 0)
+ *(uint8_t *)opaque = (uint8_t)val;
+
+ return ret;
+}
+
+RTE_EXPORT_EXPERIMENTAL_SYMBOL(rte_kvargs_handle_u16, 26.11)
+int
+rte_kvargs_handle_u16(const char *key, const char *value, void *opaque)
+{
+ uint64_t val;
+ int ret;
+
+ ret = kvargs_store_uint(key, value, opaque, UINT16_MAX, &val);
+ if (ret == 0)
+ *(uint16_t *)opaque = (uint16_t)val;
+
+ return ret;
+}
+
+RTE_EXPORT_EXPERIMENTAL_SYMBOL(rte_kvargs_handle_u32, 26.11)
+int
+rte_kvargs_handle_u32(const char *key, const char *value, void *opaque)
+{
+ uint64_t val;
+ int ret;
+
+ ret = kvargs_store_uint(key, value, opaque, UINT32_MAX, &val);
+ if (ret == 0)
+ *(uint32_t *)opaque = (uint32_t)val;
+
+ return ret;
+}
+
+RTE_EXPORT_EXPERIMENTAL_SYMBOL(rte_kvargs_handle_u64, 26.11)
+int
+rte_kvargs_handle_u64(const char *key, const char *value, void *opaque)
+{
+ uint64_t val;
+ int ret;
+
+ ret = kvargs_store_uint(key, value, opaque, UINT64_MAX, &val);
+ if (ret == 0)
+ *(uint64_t *)opaque = (uint64_t)val;
+
+ return ret;
+}
+
+RTE_EXPORT_EXPERIMENTAL_SYMBOL(rte_kvargs_handle_uint, 26.11)
+int
+rte_kvargs_handle_uint(const char *key, const char *value, void *opaque)
+{
+ uint64_t val;
+ int ret;
+
+ ret = kvargs_store_uint(key, value, opaque, UINT_MAX, &val);
+ if (ret == 0)
+ *(unsigned int *)opaque = (unsigned int)val;
+
+ return ret;
+}
+
+RTE_EXPORT_EXPERIMENTAL_SYMBOL(rte_kvargs_handle_size, 26.11)
+int
+rte_kvargs_handle_size(const char *key, const char *value, void *opaque)
+{
+ uint64_t val;
+ int ret;
+
+ ret = kvargs_store_uint(key, value, opaque, SIZE_MAX, &val);
+ if (ret == 0)
+ *(size_t *)opaque = (size_t)val;
+
+ return ret;
+}
+
+RTE_EXPORT_EXPERIMENTAL_SYMBOL(rte_kvargs_handle_i8, 26.11)
+int
+rte_kvargs_handle_i8(const char *key, const char *value, void *opaque)
+{
+ int64_t val;
+ int ret;
+
+ ret = kvargs_store_int(key, value, opaque, INT8_MIN, INT8_MAX, &val);
+ if (ret == 0)
+ *(int8_t *)opaque = (int8_t)val;
+
+ return ret;
+}
+
+RTE_EXPORT_EXPERIMENTAL_SYMBOL(rte_kvargs_handle_i16, 26.11)
+int
+rte_kvargs_handle_i16(const char *key, const char *value, void *opaque)
+{
+ int64_t val;
+ int ret;
+
+ ret = kvargs_store_int(key, value, opaque, INT16_MIN, INT16_MAX, &val);
+ if (ret == 0)
+ *(int16_t *)opaque = (int16_t)val;
+
+ return ret;
+}
+
+RTE_EXPORT_EXPERIMENTAL_SYMBOL(rte_kvargs_handle_i32, 26.11)
+int
+rte_kvargs_handle_i32(const char *key, const char *value, void *opaque)
+{
+ int64_t val;
+ int ret;
+
+ ret = kvargs_store_int(key, value, opaque, INT32_MIN, INT32_MAX, &val);
+ if (ret == 0)
+ *(int32_t *)opaque = (int32_t)val;
+
+ return ret;
+}
+
+RTE_EXPORT_EXPERIMENTAL_SYMBOL(rte_kvargs_handle_i64, 26.11)
+int
+rte_kvargs_handle_i64(const char *key, const char *value, void *opaque)
+{
+ int64_t val;
+ int ret;
+
+ ret = kvargs_store_int(key, value, opaque, INT64_MIN, INT64_MAX, &val);
+ if (ret == 0)
+ *(int64_t *)opaque = (int64_t)val;
+
+ return ret;
+}
+
+RTE_EXPORT_EXPERIMENTAL_SYMBOL(rte_kvargs_handle_int, 26.11)
+int
+rte_kvargs_handle_int(const char *key, const char *value, void *opaque)
+{
+ int64_t val;
+ int ret;
+
+ ret = kvargs_store_int(key, value, opaque, INT_MIN, INT_MAX, &val);
+ if (ret == 0)
+ *(int *)opaque = (int)val;
+
+ return ret;
+}
+
+RTE_EXPORT_EXPERIMENTAL_SYMBOL(rte_kvargs_handle_long, 26.11)
+int
+rte_kvargs_handle_long(const char *key, const char *value, void *opaque)
+{
+ int64_t val;
+ int ret;
+
+ ret = kvargs_store_int(key, value, opaque, LONG_MIN, LONG_MAX, &val);
+ if (ret == 0)
+ *(long *)opaque = (long)val;
+
+ return ret;
+}
+
+RTE_EXPORT_EXPERIMENTAL_SYMBOL(rte_kvargs_handle_ulong, 26.11)
+int
+rte_kvargs_handle_ulong(const char *key, const char *value, void *opaque)
+{
+ uint64_t val;
+ int ret;
+
+ ret = kvargs_store_uint(key, value, opaque, ULONG_MAX, &val);
+ if (ret == 0)
+ *(unsigned long *)opaque = (unsigned long)val;
+
+ return ret;
+}
+
+static const char * const kvargs_true[] = { "1", "y", "yes", "on", "true" };
+static const char * const kvargs_false[] = { "0", "n", "no", "off", "false" };
+
+RTE_EXPORT_EXPERIMENTAL_SYMBOL(rte_kvargs_handle_bool, 26.11)
+int
+rte_kvargs_handle_bool(const char *key, const char *value, void *opaque)
+{
+ unsigned int i;
+
+ if (opaque == NULL)
+ return -EINVAL;
+
+ /* A bare key means true; only rte_kvargs_process_opt() allows it.
+ * An empty value is a blank value, not a missing one, so it is
+ * rejected below.
+ */
+ if (value == NULL) {
+ *(bool *)opaque = true;
+ return 0;
+ }
+
+ for (i = 0; i < RTE_DIM(kvargs_true); i++) {
+ if (strcasecmp(value, kvargs_true[i]) == 0) {
+ *(bool *)opaque = true;
+ return 0;
+ }
+ }
+
+ for (i = 0; i < RTE_DIM(kvargs_false); i++) {
+ if (strcasecmp(value, kvargs_false[i]) == 0) {
+ *(bool *)opaque = false;
+ return 0;
+ }
+ }
+
+ KVARGS_LOG(ERR, "invalid value \"%s\" for key \"%s\", expected a boolean",
+ value, key != NULL ? key : "");
+
+ return -EINVAL;
+}
diff --git a/lib/kvargs/rte_kvargs.h b/lib/kvargs/rte_kvargs.h
index 73fa1e621b..118cf3c79b 100644
--- a/lib/kvargs/rte_kvargs.h
+++ b/lib/kvargs/rte_kvargs.h
@@ -21,6 +21,10 @@
* ethernet devices at initialization for arguments parsing.
*/
+#include <stdint.h>
+
+#include <rte_compat.h>
+
#ifdef __cplusplus
extern "C" {
#endif
@@ -230,6 +234,188 @@ int rte_kvargs_process_opt(const struct rte_kvargs *kvlist,
unsigned rte_kvargs_count(const struct rte_kvargs *kvlist,
const char *key_match);
+/**
+ * @warning
+ * @b EXPERIMENTAL: this API may change without prior notice.
+ *
+ * Handlers to convert a key/value pair into a numeric type.
+ *
+ * The functions below all match the ``arg_handler_t`` prototype, so they can
+ * be passed directly to rte_kvargs_process():
+ *
+ * @code
+ * uint16_t nb_desc = DEFAULT_NB_DESC;
+ *
+ * ret = rte_kvargs_process(kvlist, "nb_desc",
+ * rte_kvargs_handle_u16, &nb_desc);
+ * @endcode
+ *
+ * The value string is accepted only if it represents the whole number, that
+ * is:
+ *
+ * - it is not NULL and not empty;
+ * - it is decimal, or hexadecimal with a ``0x`` or ``0X`` prefix;
+ * - it has no trailing characters other than white space;
+ * - it does not overflow the target type.
+ *
+ * A leading ``+`` or ``-`` sign is accepted. The unsigned handlers reject a
+ * negative value rather than wrapping it around, which is what strtoul()
+ * would otherwise do.
+ *
+ * Note that a leading zero does @b not select octal, so ``010`` is ten and
+ * not eight.
+ *
+ * @param key
+ * The key, used for error reporting only. May be NULL.
+ * @param value
+ * The value to convert.
+ * @param opaque
+ * Pointer to the variable to store the result into. The pointed-to type
+ * must match the handler: for example rte_kvargs_handle_u16() requires a
+ * ``uint16_t *``. On error the variable is left unmodified.
+ *
+ * @return
+ * - 0 on success.
+ * - -EINVAL if the value is missing or malformed, or if @p opaque is NULL.
+ * - -ERANGE if the value does not fit in the target type.
+ */
+__rte_experimental
+int rte_kvargs_handle_u8(const char *key, const char *value, void *opaque);
+
+/** Convert a value to uint16_t. See rte_kvargs_handle_u8(). */
+__rte_experimental
+int rte_kvargs_handle_u16(const char *key, const char *value, void *opaque);
+
+/** Convert a value to uint32_t. See rte_kvargs_handle_u8(). */
+__rte_experimental
+int rte_kvargs_handle_u32(const char *key, const char *value, void *opaque);
+
+/** Convert a value to uint64_t. See rte_kvargs_handle_u8(). */
+__rte_experimental
+int rte_kvargs_handle_u64(const char *key, const char *value, void *opaque);
+
+/** Convert a value to int8_t. See rte_kvargs_handle_u8(). */
+__rte_experimental
+int rte_kvargs_handle_i8(const char *key, const char *value, void *opaque);
+
+/** Convert a value to int16_t. See rte_kvargs_handle_u8(). */
+__rte_experimental
+int rte_kvargs_handle_i16(const char *key, const char *value, void *opaque);
+
+/** Convert a value to int32_t. See rte_kvargs_handle_u8(). */
+__rte_experimental
+int rte_kvargs_handle_i32(const char *key, const char *value, void *opaque);
+
+/** Convert a value to int64_t. See rte_kvargs_handle_u8(). */
+__rte_experimental
+int rte_kvargs_handle_i64(const char *key, const char *value, void *opaque);
+
+/** Convert a value to unsigned int. See rte_kvargs_handle_u8(). */
+__rte_experimental
+int rte_kvargs_handle_uint(const char *key, const char *value, void *opaque);
+
+/** Convert a value to int. See rte_kvargs_handle_u8(). */
+__rte_experimental
+int rte_kvargs_handle_int(const char *key, const char *value, void *opaque);
+
+/** Convert a value to long. See rte_kvargs_handle_u8(). */
+__rte_experimental
+int rte_kvargs_handle_long(const char *key, const char *value, void *opaque);
+
+/** Convert a value to unsigned long. See rte_kvargs_handle_u8(). */
+__rte_experimental
+int rte_kvargs_handle_ulong(const char *key, const char *value, void *opaque);
+
+/** Convert a value to size_t. See rte_kvargs_handle_u8(). */
+__rte_experimental
+int rte_kvargs_handle_size(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 boolean.
+ *
+ * Accepts, case insensitively, ``1``, ``y``, ``yes``, ``on`` and ``true``
+ * for true; ``0``, ``n``, ``no``, ``off`` and ``false`` for false.
+ *
+ * A key given without a value, as in ``key``, is treated as true. Use
+ * rte_kvargs_process_opt() rather than rte_kvargs_process() to support
+ * that form, since the latter rejects a missing value before the handler
+ * is called. An empty value, as in ``key=``, is rejected.
+ *
+ * @param key
+ * The key, used for error reporting only. May be NULL.
+ * @param value
+ * The value to convert. NULL means true.
+ * @param opaque
+ * Pointer to a ``bool`` 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.
+ */
+__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 string to an unsigned integer, checking it against a range.
+ *
+ * This is the underlying conversion used by the rte_kvargs_handle_*()
+ * unsigned handlers. It is meant for drivers which need a range narrower
+ * than the target type, or which parse a value obtained from
+ * rte_kvargs_get() rather than from a handler.
+ *
+ * @param value
+ * The string to convert. Must be non-NULL and non-empty. See
+ * rte_kvargs_handle_u8() for the accepted syntax.
+ * @param min
+ * Smallest acceptable value, inclusive.
+ * @param max
+ * Largest acceptable value, inclusive.
+ * @param result
+ * Where to store the converted value. Left unmodified on error.
+ *
+ * @return
+ * - 0 on success.
+ * - -EINVAL if the value is missing or malformed, or if @p result is NULL.
+ * - -ERANGE if the value is outside [@p min, @p max].
+ */
+__rte_experimental
+int rte_kvargs_to_uint(const char *value, uint64_t min, uint64_t max,
+ uint64_t *result);
+
+/**
+ * @warning
+ * @b EXPERIMENTAL: this API may change without prior notice.
+ *
+ * Convert a string to a signed integer, checking it against a range.
+ *
+ * This is the signed counterpart of rte_kvargs_to_uint().
+ *
+ * @param value
+ * The string to convert. Must be non-NULL and non-empty. See
+ * rte_kvargs_handle_u8() for the accepted syntax.
+ * @param min
+ * Smallest acceptable value, inclusive.
+ * @param max
+ * Largest acceptable value, inclusive.
+ * @param result
+ * Where to store the converted value. Left unmodified on error.
+ *
+ * @return
+ * - 0 on success.
+ * - -EINVAL if the value is missing or malformed, or if @p result is NULL.
+ * - -ERANGE if the value is outside [@p min, @p max].
+ */
+__rte_experimental
+int rte_kvargs_to_int(const char *value, int64_t min, int64_t max,
+ int64_t *result);
+
#ifdef __cplusplus
}
#endif
--
2.53.0
next prev parent reply other threads:[~2026-09-29 16:38 UTC|newest]
Thread overview: 198+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-09-14 5:46 [PATCH 00/62] kvargs: add numeric conversion helpers and use them Stephen Hemminger
2026-09-14 5:46 ` [PATCH 01/62] net/txgbe: fix FDIR devarg integer width Stephen Hemminger
2026-09-14 5:46 ` [PATCH 02/62] kvargs: add numeric conversion helpers Stephen Hemminger
2026-09-14 5:46 ` [PATCH 03/62] kvargs: add a socket ID handler Stephen Hemminger
2026-09-14 5:46 ` [PATCH 04/62] kvargs: add hexadecimal conversion helpers Stephen Hemminger
2026-09-14 5:46 ` [PATCH 05/62] eal: validate memory size arguments Stephen Hemminger
2026-09-14 5:46 ` [PATCH 06/62] net/null: use kvargs numeric helpers Stephen Hemminger
2026-09-14 5:46 ` [PATCH 07/62] net/vhost: " Stephen Hemminger
2026-09-14 5:46 ` [PATCH 08/62] vdpa/ifc: " Stephen Hemminger
2026-09-14 5:46 ` [PATCH 09/62] net/softnic: " Stephen Hemminger
2026-09-14 5:46 ` [PATCH 10/62] dma/skeleton: " Stephen Hemminger
2026-09-14 5:46 ` [PATCH 11/62] raw/skeleton: " Stephen Hemminger
2026-09-14 5:46 ` [PATCH 12/62] baseband/null: " Stephen Hemminger
2026-09-14 5:46 ` [PATCH 13/62] net/memif: " Stephen Hemminger
2026-09-14 5:46 ` [PATCH 14/62] net/af_packet: " Stephen Hemminger
2026-09-14 5:46 ` [PATCH 15/62] net/pcap: " Stephen Hemminger
2026-09-14 5:46 ` [PATCH 16/62] net/ring: " Stephen Hemminger
2026-09-14 5:46 ` [PATCH 17/62] net/af_xdp: " Stephen Hemminger
2026-09-14 5:46 ` [PATCH 18/62] net/ark: " Stephen Hemminger
2026-09-14 5:46 ` [PATCH 19/62] net/failsafe: " Stephen Hemminger
2026-09-14 5:46 ` [PATCH 20/62] net/virtio: " Stephen Hemminger
2026-09-14 5:46 ` [PATCH 21/62] net/bonding: " Stephen Hemminger
2026-09-14 5:46 ` [PATCH 22/62] net/ena: " Stephen Hemminger
2026-09-14 5:46 ` [PATCH 23/62] net/netvsc: " Stephen Hemminger
2026-09-14 12:43 ` [EXTERNAL] " Wei Hu
2026-09-14 5:46 ` [PATCH 24/62] net/ice: " Stephen Hemminger
2026-09-14 5:46 ` [PATCH 25/62] net/iavf: " Stephen Hemminger
2026-09-14 5:46 ` [PATCH 26/62] net/i40e: " Stephen Hemminger
2026-09-14 5:46 ` [PATCH 27/62] net/idpf: " Stephen Hemminger
2026-09-14 5:46 ` [PATCH 28/62] net/cpfl: " Stephen Hemminger
2026-09-14 5:47 ` [PATCH 29/62] net/ixgbe: " Stephen Hemminger
2026-09-14 5:47 ` [PATCH 30/62] net/txgbe: " Stephen Hemminger
2026-09-14 5:47 ` [PATCH 31/62] net/octeontx: " Stephen Hemminger
2026-09-14 5:47 ` [PATCH 32/62] net/octeon_ep: " Stephen Hemminger
2026-09-14 5:47 ` [PATCH 33/62] net/qede: " Stephen Hemminger
2026-09-14 5:47 ` [PATCH 34/62] net/nfb: " Stephen Hemminger
2026-09-14 14:44 ` Martin Spinler
2026-09-14 5:47 ` [PATCH 35/62] net/thunderx: " Stephen Hemminger
2026-09-14 5:47 ` [PATCH 36/62] net/i40e: propagate VF queue number parse errors Stephen Hemminger
2026-09-14 5:47 ` [PATCH 37/62] net/cnxk: use kvargs numeric helpers Stephen Hemminger
2026-09-14 5:47 ` [PATCH 38/62] net/xsc: " Stephen Hemminger
2026-09-14 5:47 ` [PATCH 39/62] net/hns3: " Stephen Hemminger
2026-09-14 5:47 ` [PATCH 40/62] net/enetc: " Stephen Hemminger
2026-09-14 5:47 ` [PATCH 41/62] event/dlb2: " Stephen Hemminger
2026-09-14 5:47 ` [PATCH 42/62] net/nfp: " Stephen Hemminger
2026-09-14 5:47 ` [PATCH 43/62] drivers/crypto: " Stephen Hemminger
2026-09-14 5:47 ` [PATCH 44/62] event/sw: " Stephen Hemminger
2026-09-14 5:47 ` [PATCH 45/62] net/bnxt: " Stephen Hemminger
2026-09-14 5:47 ` [PATCH 46/62] net/bnxt: propagate devargs parsing errors Stephen Hemminger
2026-09-14 5:47 ` [PATCH 47/62] net/mlx4: use kvargs numeric helpers Stephen Hemminger
2026-09-14 5:47 ` [PATCH 48/62] net/sfc: " Stephen Hemminger
2026-09-14 5:47 ` [PATCH 49/62] crypto/mvsam: " Stephen Hemminger
2026-09-14 5:47 ` [PATCH 50/62] ml/cnxk: use kvargs numeric helpers in cn10k Stephen Hemminger
2026-09-14 5:47 ` [PATCH 51/62] ml/cnxk: use kvargs numeric helpers in mvtvm Stephen Hemminger
2026-09-14 5:47 ` [PATCH 52/62] event/opdl: use kvargs numeric helpers Stephen Hemminger
2026-09-14 5:47 ` [PATCH 53/62] mempool/cnxk: " Stephen Hemminger
2026-09-14 5:47 ` [PATCH 54/62] event/octeontx: " Stephen Hemminger
2026-09-14 5:47 ` [PATCH 55/62] baseband/turbo_sw: " Stephen Hemminger
2026-09-14 5:47 ` [PATCH 56/62] baseband/la12xx: " Stephen Hemminger
2026-09-14 5:47 ` [PATCH 57/62] dma/hisi_acc: " Stephen Hemminger
2026-09-14 5:47 ` [PATCH 58/62] crypto/virtio: " Stephen Hemminger
2026-09-14 5:47 ` [PATCH 59/62] net/ice: use kvargs hex helper for debug mask Stephen Hemminger
2026-09-14 5:47 ` [PATCH 60/62] net/hns3: use kvargs hex helper for capability mask Stephen Hemminger
2026-09-14 5:47 ` [PATCH 61/62] net/cxgbe: use kvargs numeric helpers Stephen Hemminger
2026-09-14 5:47 ` [PATCH 62/62] doc: note kvargs devargs conversion in release notes Stephen Hemminger
2026-09-29 16:36 ` [PATCH v2 00/61] kvargs: add numeric conversion helpers Stephen Hemminger
2026-09-29 16:36 ` Stephen Hemminger [this message]
2026-09-30 0:49 ` [PATCH v2 01/61] " fengchengwen
2026-09-29 16:36 ` [PATCH v2 02/61] kvargs: add a socket ID handler Stephen Hemminger
2026-09-30 1:01 ` fengchengwen
2026-09-29 16:36 ` [PATCH v2 03/61] kvargs: add hexadecimal conversion helpers Stephen Hemminger
2026-09-30 1:07 ` fengchengwen
2026-09-29 16:36 ` [PATCH v2 04/61] eal: validate memory size arguments Stephen Hemminger
2026-09-29 16:36 ` [PATCH v2 05/61] net/null: use kvargs numeric helpers Stephen Hemminger
2026-09-29 16:36 ` [PATCH v2 06/61] net/vhost: " Stephen Hemminger
2026-09-29 16:36 ` [PATCH v2 07/61] vdpa/ifc: " Stephen Hemminger
2026-09-29 16:36 ` [PATCH v2 08/61] net/softnic: " Stephen Hemminger
2026-09-29 16:36 ` [PATCH v2 09/61] dma/skeleton: " Stephen Hemminger
2026-09-29 16:36 ` [PATCH v2 10/61] raw/skeleton: " Stephen Hemminger
2026-09-29 16:36 ` [PATCH v2 11/61] baseband/null: " Stephen Hemminger
2026-09-29 16:36 ` [PATCH v2 12/61] net/memif: " Stephen Hemminger
2026-09-29 16:36 ` [PATCH v2 13/61] net/af_packet: " Stephen Hemminger
2026-09-29 16:36 ` [PATCH v2 14/61] net/pcap: " Stephen Hemminger
2026-09-29 16:36 ` [PATCH v2 15/61] net/ring: " Stephen Hemminger
2026-09-29 16:36 ` [PATCH v2 16/61] net/af_xdp: " Stephen Hemminger
2026-09-29 16:36 ` [PATCH v2 17/61] net/ark: " Stephen Hemminger
2026-09-29 16:36 ` [PATCH v2 18/61] net/failsafe: " Stephen Hemminger
2026-09-29 16:36 ` [PATCH v2 19/61] net/virtio: " Stephen Hemminger
2026-09-29 16:36 ` [PATCH v2 20/61] net/bonding: " Stephen Hemminger
2026-09-29 16:36 ` [PATCH v2 21/61] net/ena: " Stephen Hemminger
2026-09-29 16:36 ` [PATCH v2 22/61] net/netvsc: " Stephen Hemminger
2026-09-29 16:36 ` [PATCH v2 23/61] net/ice: " Stephen Hemminger
2026-09-29 16:36 ` [PATCH v2 24/61] net/iavf: " Stephen Hemminger
2026-09-29 16:36 ` [PATCH v2 25/61] net/i40e: " Stephen Hemminger
2026-09-29 16:36 ` [PATCH v2 26/61] net/idpf: " Stephen Hemminger
2026-09-29 16:36 ` [PATCH v2 27/61] net/cpfl: " Stephen Hemminger
2026-09-29 16:36 ` [PATCH v2 28/61] net/ixgbe: " Stephen Hemminger
2026-09-29 16:36 ` [PATCH v2 29/61] net/txgbe: " Stephen Hemminger
2026-09-29 16:36 ` [PATCH v2 30/61] net/octeontx: " Stephen Hemminger
2026-09-29 16:36 ` [PATCH v2 31/61] net/octeon_ep: " Stephen Hemminger
2026-09-29 16:36 ` [PATCH v2 32/61] net/qede: " Stephen Hemminger
2026-09-29 16:36 ` [PATCH v2 33/61] net/nfb: " Stephen Hemminger
2026-09-29 16:36 ` [PATCH v2 34/61] net/thunderx: " Stephen Hemminger
2026-09-29 16:36 ` [PATCH v2 35/61] net/i40e: propagate VF queue number parse errors Stephen Hemminger
2026-09-29 16:36 ` [PATCH v2 36/61] net/cnxk: use kvargs numeric helpers Stephen Hemminger
2026-09-29 16:36 ` [PATCH v2 37/61] net/xsc: " Stephen Hemminger
2026-09-29 16:36 ` [PATCH v2 38/61] net/hns3: " Stephen Hemminger
2026-09-29 16:36 ` [PATCH v2 39/61] net/enetc: " Stephen Hemminger
2026-09-29 16:36 ` [PATCH v2 40/61] event/dlb2: " Stephen Hemminger
2026-09-29 16:36 ` [PATCH v2 41/61] net/nfp: " Stephen Hemminger
2026-09-29 16:36 ` [PATCH v2 42/61] drivers/crypto: " Stephen Hemminger
2026-09-29 16:36 ` [PATCH v2 43/61] event/sw: " Stephen Hemminger
2026-09-29 16:36 ` [PATCH v2 44/61] net/bnxt: " Stephen Hemminger
2026-09-29 16:36 ` [PATCH v2 45/61] net/bnxt: propagate devargs parsing errors Stephen Hemminger
2026-09-29 16:36 ` [PATCH v2 46/61] net/mlx4: use kvargs numeric helpers Stephen Hemminger
2026-09-29 16:36 ` [PATCH v2 47/61] net/sfc: " Stephen Hemminger
2026-09-29 16:36 ` [PATCH v2 48/61] crypto/mvsam: " Stephen Hemminger
2026-09-29 16:36 ` [PATCH v2 49/61] ml/cnxk: use kvargs numeric helpers in cn10k Stephen Hemminger
2026-09-29 16:36 ` [PATCH v2 50/61] ml/cnxk: use kvargs numeric helpers in mvtvm Stephen Hemminger
2026-09-29 16:36 ` [PATCH v2 51/61] event/opdl: use kvargs numeric helpers Stephen Hemminger
2026-09-29 16:36 ` [PATCH v2 52/61] mempool/cnxk: " Stephen Hemminger
2026-09-29 16:36 ` [PATCH v2 53/61] event/octeontx: " Stephen Hemminger
2026-09-29 16:36 ` [PATCH v2 54/61] baseband/turbo_sw: " Stephen Hemminger
2026-09-29 16:36 ` [PATCH v2 55/61] baseband/la12xx: " Stephen Hemminger
2026-09-29 16:36 ` [PATCH v2 56/61] dma/hisi_acc: " Stephen Hemminger
2026-09-29 16:37 ` [PATCH v2 57/61] crypto/virtio: " Stephen Hemminger
2026-09-29 16:37 ` [PATCH v2 58/61] net/ice: use kvargs hex helper for debug mask Stephen Hemminger
2026-09-29 16:37 ` [PATCH v2 59/61] net/hns3: use kvargs hex helper for capability mask Stephen Hemminger
2026-09-29 16:37 ` [PATCH v2 60/61] net/cxgbe: use kvargs numeric helpers Stephen Hemminger
2026-09-29 16:37 ` [PATCH v2 61/61] doc: note kvargs devargs conversion in release notes Stephen Hemminger
2026-09-30 1:14 ` [PATCH v2 00/61] kvargs: add numeric conversion helpers fengchengwen
2026-09-30 15:21 ` Stephen Hemminger
2026-09-30 22:40 ` [PATCH v3 00/65] " Stephen Hemminger
2026-09-30 22:40 ` [PATCH v3 01/65] net/ring: make numa node signed Stephen Hemminger
2026-09-30 22:40 ` [PATCH v3 02/65] kvargs: add numeric conversion helpers Stephen Hemminger
2026-09-30 22:40 ` [PATCH v3 03/65] kvargs: add a socket ID handler Stephen Hemminger
2026-09-30 22:40 ` [PATCH v3 04/65] kvargs: add hexadecimal conversion helpers Stephen Hemminger
2026-09-30 22:40 ` [PATCH v3 05/65] eal: validate memory size arguments Stephen Hemminger
2026-09-30 22:40 ` [PATCH v3 06/65] net/null: use kvargs numeric helpers Stephen Hemminger
2026-09-30 22:40 ` [PATCH v3 07/65] net/vhost: " Stephen Hemminger
2026-09-30 22:40 ` [PATCH v3 08/65] vdpa/ifc: " Stephen Hemminger
2026-09-30 22:40 ` [PATCH v3 09/65] net/softnic: " Stephen Hemminger
2026-09-30 22:40 ` [PATCH v3 10/65] dma/skeleton: " Stephen Hemminger
2026-09-30 22:40 ` [PATCH v3 11/65] raw/skeleton: " Stephen Hemminger
2026-09-30 22:40 ` [PATCH v3 12/65] baseband/null: " Stephen Hemminger
2026-09-30 22:40 ` [PATCH v3 13/65] net/memif: " Stephen Hemminger
2026-09-30 22:40 ` [PATCH v3 14/65] net/af_packet: " Stephen Hemminger
2026-09-30 22:40 ` [PATCH v3 15/65] net/pcap: " Stephen Hemminger
2026-09-30 22:40 ` [PATCH v3 16/65] net/ring: " Stephen Hemminger
2026-09-30 22:40 ` [PATCH v3 17/65] net/af_xdp: " Stephen Hemminger
2026-09-30 22:40 ` [PATCH v3 18/65] net/ark: " Stephen Hemminger
2026-09-30 22:40 ` [PATCH v3 19/65] net/failsafe: " Stephen Hemminger
2026-09-30 22:40 ` [PATCH v3 20/65] net/virtio: " Stephen Hemminger
2026-09-30 22:40 ` [PATCH v3 21/65] net/bonding: " Stephen Hemminger
2026-09-30 22:40 ` [PATCH v3 22/65] net/ena: " Stephen Hemminger
2026-09-30 22:40 ` [PATCH v3 23/65] net/netvsc: " Stephen Hemminger
2026-09-30 22:40 ` [PATCH v3 24/65] net/ice: " Stephen Hemminger
2026-09-30 22:40 ` [PATCH v3 25/65] net/iavf: " Stephen Hemminger
2026-09-30 22:40 ` [PATCH v3 26/65] net/i40e: " Stephen Hemminger
2026-09-30 22:40 ` [PATCH v3 27/65] net/idpf: " Stephen Hemminger
2026-09-30 22:40 ` [PATCH v3 28/65] net/cpfl: " Stephen Hemminger
2026-09-30 22:40 ` [PATCH v3 29/65] net/ixgbe: " Stephen Hemminger
2026-09-30 22:40 ` [PATCH v3 30/65] net/txgbe: " Stephen Hemminger
2026-09-30 22:40 ` [PATCH v3 31/65] net/octeontx: " Stephen Hemminger
2026-09-30 22:40 ` [PATCH v3 32/65] net/octeon_ep: " Stephen Hemminger
2026-09-30 22:40 ` [PATCH v3 33/65] net/qede: " Stephen Hemminger
2026-09-30 22:40 ` [PATCH v3 34/65] net/nfb: " Stephen Hemminger
2026-09-30 22:40 ` [PATCH v3 35/65] net/thunderx: " Stephen Hemminger
2026-09-30 22:40 ` [PATCH v3 36/65] net/i40e: propagate VF queue number parse errors Stephen Hemminger
2026-09-30 22:40 ` [PATCH v3 37/65] net/cnxk: use kvargs numeric helpers Stephen Hemminger
2026-09-30 22:40 ` [PATCH v3 38/65] net/xsc: " Stephen Hemminger
2026-09-30 22:40 ` [PATCH v3 39/65] net/hns3: " Stephen Hemminger
2026-09-30 22:40 ` [PATCH v3 40/65] net/enetc: " Stephen Hemminger
2026-09-30 22:40 ` [PATCH v3 41/65] event/dlb2: " Stephen Hemminger
2026-09-30 22:41 ` [PATCH v3 42/65] net/nfp: " Stephen Hemminger
2026-09-30 22:41 ` [PATCH v3 43/65] drivers/crypto: " Stephen Hemminger
2026-09-30 22:41 ` [PATCH v3 44/65] event/sw: " Stephen Hemminger
2026-09-30 22:41 ` [PATCH v3 45/65] net/bnxt: " Stephen Hemminger
2026-09-30 22:41 ` [PATCH v3 46/65] net/bnxt: propagate devargs parsing errors Stephen Hemminger
2026-09-30 22:41 ` [PATCH v3 47/65] net/mlx4: use kvargs numeric helpers Stephen Hemminger
2026-09-30 22:41 ` [PATCH v3 48/65] net/sfc: " Stephen Hemminger
2026-09-30 22:41 ` [PATCH v3 49/65] crypto/mvsam: " Stephen Hemminger
2026-09-30 22:41 ` [PATCH v3 50/65] ml/cnxk: use kvargs numeric helpers in cn10k Stephen Hemminger
2026-09-30 22:41 ` [PATCH v3 51/65] ml/cnxk: use kvargs numeric helpers in mvtvm Stephen Hemminger
2026-09-30 22:41 ` [PATCH v3 52/65] event/opdl: use kvargs numeric helpers Stephen Hemminger
2026-09-30 22:41 ` [PATCH v3 53/65] mempool/cnxk: " Stephen Hemminger
2026-09-30 22:41 ` [PATCH v3 54/65] event/octeontx: " Stephen Hemminger
2026-09-30 22:41 ` [PATCH v3 55/65] baseband/turbo_sw: " Stephen Hemminger
2026-09-30 22:41 ` [PATCH v3 56/65] baseband/la12xx: " Stephen Hemminger
2026-09-30 22:41 ` [PATCH v3 57/65] dma/hisi_acc: " Stephen Hemminger
2026-09-30 22:41 ` [PATCH v3 58/65] crypto/virtio: " Stephen Hemminger
2026-09-30 22:41 ` [PATCH v3 59/65] net/ice: use kvargs hex helper for debug mask Stephen Hemminger
2026-09-30 22:41 ` [PATCH v3 60/65] net/hns3: use kvargs hex helper for capability mask Stephen Hemminger
2026-09-30 22:41 ` [PATCH v3 61/65] net/cxgbe: use kvargs numeric helpers Stephen Hemminger
2026-09-30 22:41 ` [PATCH v3 62/65] kvargs: add range conversion handlers Stephen Hemminger
2026-09-30 22:41 ` [PATCH v3 63/65] event/sw: use kvargs range handlers Stephen Hemminger
2026-09-30 22:41 ` [PATCH v3 64/65] net/cnxk: " Stephen Hemminger
2026-09-30 22:41 ` [PATCH v3 65/65] doc: note kvargs devargs conversion in release notes Stephen Hemminger
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20260929163800.1108305-2-stephen@networkplumber.org \
--to=stephen@networkplumber.org \
--cc=dev@dpdk.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox