From: Mark Bloch <mbloch@nvidia.com>
To: Eric Dumazet <edumazet@google.com>,
Jakub Kicinski <kuba@kernel.org>, Paolo Abeni <pabeni@redhat.com>,
Andrew Lunn <andrew+netdev@lunn.ch>,
"David S. Miller" <davem@davemloft.net>
Cc: Jonathan Corbet <corbet@lwn.net>,
Shuah Khan <skhan@linuxfoundation.org>,
Jiri Pirko <jiri@resnulli.us>, Simon Horman <horms@kernel.org>,
"Saeed Mahameed" <saeedm@nvidia.com>,
Leon Romanovsky <leon@kernel.org>,
Tariq Toukan <tariqt@nvidia.com>, Mark Bloch <mbloch@nvidia.com>,
Andrew Morton <akpm@linux-foundation.org>,
"Borislav Petkov (AMD)" <bp@alien8.de>,
"Randy Dunlap" <rdunlap@infradead.org>,
Dave Hansen <dave.hansen@linux.intel.com>,
Christian Brauner <brauner@kernel.org>,
Petr Mladek <pmladek@suse.com>,
"Peter Zijlstra (Intel)" <peterz@infradead.org>,
Thomas Gleixner <tglx@kernel.org>,
Pawan Gupta <pawan.kumar.gupta@linux.intel.com>,
Dapeng Mi <dapeng1.mi@linux.intel.com>,
Kees Cook <kees@kernel.org>, Marco Elver <elver@google.com>,
Eric Biggers <ebiggers@kernel.org>,
Li RongQing <lirongqing@baidu.com>,
"Paul E. McKenney" <paulmck@kernel.org>,
<linux-doc@vger.kernel.org>, <linux-kernel@vger.kernel.org>,
<netdev@vger.kernel.org>, <linux-rdma@vger.kernel.org>
Subject: [RFC net-next 3/4] devlink: Add runtime parameter boot defaults
Date: Wed, 6 May 2026 15:37:38 +0300 [thread overview]
Message-ID: <20260506123739.1959770-4-mbloch@nvidia.com> (raw)
In-Reply-To: <20260506123739.1959770-1-mbloch@nvidia.com>
Add support for setting devlink device parameters from the devlink=
kernel command line parameter.
The supported syntax is:
devlink=[<handle>]:param:<name>:<value>
Parameter values are parsed according to the registered devlink
parameter type and are applied in runtime configuration mode. Driverinit
and permanent configuration modes are intentionally not part of the
boot-default syntax.
Add a helper that finds a parameter by name, verifies runtime mode
support, converts the string value, runs the parameter validator and
invokes the existing set callback.
Signed-off-by: Mark Bloch <mbloch@nvidia.com>
---
.../admin-guide/kernel-parameters.txt | 2 +
.../networking/devlink/devlink-defaults.rst | 18 ++-
net/devlink/core.c | 110 ++++++++++++------
net/devlink/devl_internal.h | 3 +
net/devlink/param.c | 70 +++++++++++
5 files changed, 165 insertions(+), 38 deletions(-)
diff --git a/Documentation/admin-guide/kernel-parameters.txt b/Documentation/admin-guide/kernel-parameters.txt
index 150202882870..761ae45b8607 100644
--- a/Documentation/admin-guide/kernel-parameters.txt
+++ b/Documentation/admin-guide/kernel-parameters.txt
@@ -1293,9 +1293,11 @@ Kernel parameters
Currently supported settings:
esw:mode:{ legacy | switchdev | switchdev_inactive }
+ param:<name>:<value>
Examples:
devlink=[pci/0000:08:00.0]:esw:mode:switchdev
+ devlink=[pci/0000:08:00.0]:param:flow_steering_mode:smfs
devlink=[pci/0000:08:00.0,pci/0000:08:00.1]:esw:mode:legacy
devlink=[pci/0000:08:00.0]:esw:mode:switchdev,[pci/0000:08:00.1]:esw:mode:switchdev_inactive
diff --git a/Documentation/networking/devlink/devlink-defaults.rst b/Documentation/networking/devlink/devlink-defaults.rst
index 7d6ccaddca86..0d4036e59e88 100644
--- a/Documentation/networking/devlink/devlink-defaults.rst
+++ b/Documentation/networking/devlink/devlink-defaults.rst
@@ -55,13 +55,16 @@ The following syntax rules apply:
* Defaults for the same handle are applied in command-line order.
* The same ``esw`` attribute may be specified only once for a given devlink
handle.
+* The same ``param`` name may be specified only once for a given devlink
+ handle.
* Duplicate entries for the same handle are rejected and all devlink defaults
are ignored.
+* Parameter names and values must not contain ``:`` or ``,``.
Supported defaults
==================
-The supported command is ``esw``:
+The supported commands are ``esw`` and ``param``:
.. list-table::
:widths: 10 25 35
@@ -73,11 +76,16 @@ The supported command is ``esw``:
* - ``esw``
- ``mode:<mode>``
- ``legacy``, ``switchdev``, ``switchdev_inactive``
+ * - ``param``
+ - ``<name>:<value>``
+ - ``<value>`` is parsed according to the registered devlink parameter
+ type. Only runtime devlink parameters are supported.
The ``esw:mode`` default corresponds to the userspace command::
devlink dev eswitch set <handle> mode <value>
+The ``param`` default applies the named devlink parameter in runtime mode.
Examples
========
@@ -90,6 +98,10 @@ Set two PCI devlink instances to legacy mode::
devlink=[pci/0000:08:00.0,pci/0000:08:00.1]:esw:mode:legacy
+Set a runtime devlink device parameter::
+
+ devlink=[pci/0000:08:00.0]:param:flow_steering_mode:smfs
+
Set different modes for different PCI devlink instances::
devlink=[pci/0000:08:00.0]:esw:mode:switchdev,[pci/0000:08:00.1]:esw:mode:switchdev_inactive
@@ -97,3 +109,7 @@ Set different modes for different PCI devlink instances::
The following is invalid because the same handle receives ``esw:mode`` twice::
devlink=[pci/0000:08:00.0]:esw:mode:legacy,[pci/0000:08:00.0]:esw:mode:switchdev
+
+The following is invalid because the same handle receives ``param:x`` twice::
+
+ devlink=[pci/0]:param:x:1,[pci/0]:param:x:2
diff --git a/net/devlink/core.c b/net/devlink/core.c
index 4b404135181c..22990793ab8c 100644
--- a/net/devlink/core.c
+++ b/net/devlink/core.c
@@ -50,6 +50,13 @@ struct devlink_default_node {
struct list_head cmd_list;
};
+struct devlink_default_attr_spec {
+ const char *name;
+ enum devlink_attr attr;
+ int (*value_parse)(const char *value,
+ struct devlink_default_attr_item *attr_item);
+};
+
struct devlink_default_cmd_spec {
const char *name;
enum devlink_command cmd;
@@ -73,13 +80,6 @@ devlink_default_attr_free(struct devlink_default_attr_item *attr)
kfree(attr->value.param.value);
}
-struct devlink_default_attr_spec {
- const char *name;
- enum devlink_attr attr;
- int (*value_parse)(const char *value,
- struct devlink_default_attr_item *attr_item);
-};
-
static int __init
devlink_default_attr_parse(char *str,
const struct devlink_default_attr_spec *attrs,
@@ -153,6 +153,33 @@ devlink_default_esw_attr_parse(char *str,
attr_item);
}
+static int __init
+devlink_default_param_attr_parse(char *str,
+ struct devlink_default_attr_item *attr_item)
+{
+ char *name;
+ char *value;
+
+ attr_item->attr = DEVLINK_ATTR_PARAM;
+
+ name = strsep(&str, ":");
+ value = strsep(&str, ":");
+ if (!name || !*name || !value || !*value || str)
+ return -EINVAL;
+
+ attr_item->value.param.name = kstrdup(name, GFP_KERNEL);
+ if (!attr_item->value.param.name)
+ return -ENOMEM;
+ attr_item->value.param.value = kstrdup(value, GFP_KERNEL);
+ if (!attr_item->value.param.value) {
+ kfree(attr_item->value.param.name);
+ attr_item->value.param.name = NULL;
+ return -ENOMEM;
+ }
+
+ return 0;
+}
+
static int
devlink_default_eswitch_apply(struct devlink *devlink,
const struct devlink_default_attr_item *attr)
@@ -171,6 +198,17 @@ devlink_default_eswitch_apply(struct devlink *devlink,
}
}
+static int
+devlink_default_param_apply(struct devlink *devlink,
+ const struct devlink_default_attr_item *attr)
+{
+ if (attr->attr != DEVLINK_ATTR_PARAM)
+ return -EOPNOTSUPP;
+
+ return devlink_param_set_from_string(devlink, attr->value.param.name,
+ attr->value.param.value);
+}
+
static const struct devlink_default_cmd_spec devlink_default_cmds[] __initconst = {
{
.name = "esw",
@@ -178,52 +216,46 @@ static const struct devlink_default_cmd_spec devlink_default_cmds[] __initconst
.run = devlink_default_eswitch_apply,
.attr_parse = devlink_default_esw_attr_parse,
},
+ {
+ .name = "param",
+ .cmd = DEVLINK_CMD_PARAM_SET,
+ .run = devlink_default_param_apply,
+ .attr_parse = devlink_default_param_attr_parse,
+ },
};
-static const struct devlink_default_cmd_spec *__init
-devlink_default_cmd_spec_find(const char *name)
-{
- size_t i;
-
- for (i = 0; i < ARRAY_SIZE(devlink_default_cmds); i++) {
- if (!strcmp(name, devlink_default_cmds[i].name))
- return &devlink_default_cmds[i];
- }
-
- return NULL;
-}
-
static int __init
devlink_default_cmd_parse(char *str,
struct devlink_default_cmd_item *cmd_item)
{
- const struct devlink_default_cmd_spec *spec;
struct devlink_default_attr_item attr_item = {};
char *cmd_name;
int err;
+ size_t i;
cmd_name = strsep(&str, ":");
if (!cmd_name || !*cmd_name || !str || !*str)
return -EINVAL;
- spec = devlink_default_cmd_spec_find(cmd_name);
- if (!spec)
- return -EINVAL;
-
- err = spec->attr_parse(str, &attr_item);
- if (err) {
- devlink_default_attr_free(&attr_item);
- return err;
- }
- if (cmd_item) {
- cmd_item->cmd = spec->cmd;
- cmd_item->run = spec->run;
- cmd_item->attr = attr_item;
- } else {
- devlink_default_attr_free(&attr_item);
+ for (i = 0; i < ARRAY_SIZE(devlink_default_cmds); i++) {
+ if (!strcmp(cmd_name, devlink_default_cmds[i].name)) {
+ err = devlink_default_cmds[i].attr_parse(str, &attr_item);
+ if (err) {
+ devlink_default_attr_free(&attr_item);
+ return err;
+ }
+ if (cmd_item) {
+ cmd_item->cmd = devlink_default_cmds[i].cmd;
+ cmd_item->run = devlink_default_cmds[i].run;
+ cmd_item->attr = attr_item;
+ } else {
+ devlink_default_attr_free(&attr_item);
+ }
+ return 0;
+ }
}
- return 0;
+ return -EINVAL;
}
static int __init
@@ -369,6 +401,10 @@ devlink_default_cmd_equal(const struct devlink_default_cmd_item *a,
if (a->cmd != b->cmd || a->attr.attr != b->attr.attr)
return false;
+ if (a->cmd == DEVLINK_CMD_PARAM_SET)
+ return !strcmp(a->attr.value.param.name,
+ b->attr.value.param.name);
+
return true;
}
diff --git a/net/devlink/devl_internal.h b/net/devlink/devl_internal.h
index e4e48ee2da5a..bde333c22f18 100644
--- a/net/devlink/devl_internal.h
+++ b/net/devlink/devl_internal.h
@@ -212,6 +212,9 @@ static inline int devlink_nl_put_u64(struct sk_buff *msg, int attrtype, u64 val)
int devlink_nl_put_nested_handle(struct sk_buff *msg, struct net *net,
struct devlink *devlink, int attrtype);
int devlink_nl_msg_reply_and_new(struct sk_buff **msg, struct genl_info *info);
+int devlink_param_set_from_string(struct devlink *devlink,
+ const char *param_name,
+ const char *value_str);
static inline bool devlink_nl_notify_need(struct devlink *devlink)
{
diff --git a/net/devlink/param.c b/net/devlink/param.c
index cf95268da5b0..d2604fe2eee5 100644
--- a/net/devlink/param.c
+++ b/net/devlink/param.c
@@ -4,6 +4,8 @@
* Copyright (c) 2016 Jiri Pirko <jiri@mellanox.com>
*/
+#include <linux/kstrtox.h>
+
#include "devl_internal.h"
static const struct devlink_param devlink_param_generic[] = {
@@ -551,6 +553,74 @@ devlink_param_value_get_from_info(const struct devlink_param *param,
return 0;
}
+static int
+devlink_param_value_get_from_str(const struct devlink_param *param,
+ const char *value_str,
+ union devlink_param_value *value)
+{
+ switch (param->type) {
+ case DEVLINK_PARAM_TYPE_U8:
+ return kstrtou8(value_str, 0, &value->vu8);
+ case DEVLINK_PARAM_TYPE_U16:
+ return kstrtou16(value_str, 0, &value->vu16);
+ case DEVLINK_PARAM_TYPE_U32:
+ return kstrtou32(value_str, 0, &value->vu32);
+ case DEVLINK_PARAM_TYPE_U64:
+ return kstrtou64(value_str, 0, &value->vu64);
+ case DEVLINK_PARAM_TYPE_STRING:
+ if (strscpy(value->vstr, value_str, sizeof(value->vstr)) < 0)
+ return -EINVAL;
+ return 0;
+ case DEVLINK_PARAM_TYPE_BOOL:
+ return kstrtobool(value_str, &value->vbool);
+ }
+
+ return -EINVAL;
+}
+
+int devlink_param_set_from_string(struct devlink *devlink,
+ const char *param_name,
+ const char *value_str)
+{
+ struct devlink_param_gset_ctx ctx;
+ struct devlink_param_item *param_item;
+ const struct devlink_param *param;
+ union devlink_param_value value;
+ int err;
+
+ devl_assert_locked(devlink);
+
+ param_item = devlink_param_find_by_name(&devlink->params, param_name);
+ if (!param_item)
+ return -EINVAL;
+ param = param_item->param;
+
+ if (!devlink_param_cmode_is_supported(param,
+ DEVLINK_PARAM_CMODE_RUNTIME))
+ return -EOPNOTSUPP;
+ if (!param->set)
+ return -EOPNOTSUPP;
+
+ err = devlink_param_value_get_from_str(param, value_str, &value);
+ if (err)
+ return err;
+
+ if (param->validate) {
+ err = param->validate(devlink, param->id, value, NULL);
+ if (err)
+ return err;
+ }
+
+ ctx.val = value;
+ ctx.cmode = DEVLINK_PARAM_CMODE_RUNTIME;
+ err = devlink_param_set(devlink, param, &ctx, NULL);
+ if (err)
+ return err;
+
+ devlink_param_notify(devlink, 0, param_item, DEVLINK_CMD_PARAM_NEW);
+ return 0;
+}
+
static struct devlink_param_item *
devlink_param_get_from_info(struct xarray *params, struct genl_info *info)
{
--
2.34.1
next prev parent reply other threads:[~2026-05-06 12:38 UTC|newest]
Thread overview: 27+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-05-06 12:37 [RFC net-next 0/4] devlink: Add boot-time defaults Mark Bloch
2026-05-06 12:37 ` [RFC net-next 1/4] devlink: Add infrastructure for " Mark Bloch
2026-05-06 12:37 ` [RFC net-next 2/4] devlink: Add eswitch mode boot default Mark Bloch
2026-05-06 12:37 ` Mark Bloch [this message]
2026-05-06 12:37 ` [RFC net-next 4/4] net/mlx5: Apply devlink boot defaults during init Mark Bloch
2026-05-06 15:22 ` [RFC net-next 0/4] devlink: Add boot-time defaults Jiri Pirko
2026-05-06 17:35 ` Mark Bloch
2026-05-07 11:03 ` Jiri Pirko
2026-05-08 17:59 ` Mark Bloch
2026-05-08 18:07 ` Jiri Pirko
2026-05-09 0:52 ` Jakub Kicinski
2026-05-09 7:01 ` Jiri Pirko
2026-05-10 12:31 ` Mark Bloch
2026-05-11 8:07 ` Jiri Pirko
2026-05-11 18:21 ` Parav Pandit
2026-05-12 8:45 ` Jiri Pirko
2026-05-12 13:48 ` Parav Pandit
2026-05-12 14:07 ` Jiri Pirko
2026-05-12 15:25 ` Parav Pandit
2026-05-12 18:35 ` Jiri Pirko
2026-05-13 5:53 ` Mark Bloch
2026-05-13 11:11 ` Jiri Pirko
2026-05-14 12:34 ` Mark Bloch
2026-05-10 16:37 ` Jakub Kicinski
2026-05-11 8:42 ` Jiri Pirko
2026-05-11 23:41 ` Jakub Kicinski
2026-05-12 8:42 ` Jiri Pirko
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=20260506123739.1959770-4-mbloch@nvidia.com \
--to=mbloch@nvidia.com \
--cc=akpm@linux-foundation.org \
--cc=andrew+netdev@lunn.ch \
--cc=bp@alien8.de \
--cc=brauner@kernel.org \
--cc=corbet@lwn.net \
--cc=dapeng1.mi@linux.intel.com \
--cc=dave.hansen@linux.intel.com \
--cc=davem@davemloft.net \
--cc=ebiggers@kernel.org \
--cc=edumazet@google.com \
--cc=elver@google.com \
--cc=horms@kernel.org \
--cc=jiri@resnulli.us \
--cc=kees@kernel.org \
--cc=kuba@kernel.org \
--cc=leon@kernel.org \
--cc=linux-doc@vger.kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-rdma@vger.kernel.org \
--cc=lirongqing@baidu.com \
--cc=netdev@vger.kernel.org \
--cc=pabeni@redhat.com \
--cc=paulmck@kernel.org \
--cc=pawan.kumar.gupta@linux.intel.com \
--cc=peterz@infradead.org \
--cc=pmladek@suse.com \
--cc=rdunlap@infradead.org \
--cc=saeedm@nvidia.com \
--cc=skhan@linuxfoundation.org \
--cc=tariqt@nvidia.com \
--cc=tglx@kernel.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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.