DPDK-dev Archive on lore.kernel.org
 help / color / mirror / Atom feed
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


  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