Messages in this thread Patch in this message |  | | From | Mark Bloch <> | | Subject | [RFC net-next 2/4] devlink: Add eswitch mode boot default | | Date | Wed, 6 May 2026 15:37:37 +0300 |
| |
Add support for configuring the devlink eswitch mode from the devlink= kernel command line parameter.
The supported syntax is:
devlink=[<handle>]:esw:mode:<mode>
where <mode> is one of legacy, switchdev or switchdev_inactive. The default is applied through the existing eswitch_mode_set() devlink operation, matching the userspace devlink eswitch set command.
Document the devlink= syntax and the eswitch mode default.
Signed-off-by: Mark Bloch <mbloch@nvidia.com> --- .../admin-guide/kernel-parameters.txt | 24 ++++ .../networking/devlink/devlink-defaults.rst | 99 +++++++++++++++ Documentation/networking/devlink/index.rst | 1 + net/devlink/core.c | 114 ++++++++++++++++++ 4 files changed, 238 insertions(+) create mode 100644 Documentation/networking/devlink/devlink-defaults.rst
diff --git a/Documentation/admin-guide/kernel-parameters.txt b/Documentation/admin-guide/kernel-parameters.txt index 7834ee927310..150202882870 100644 --- a/Documentation/admin-guide/kernel-parameters.txt +++ b/Documentation/admin-guide/kernel-parameters.txt @@ -1278,6 +1278,30 @@ Kernel parameters dell_smm_hwmon.fan_max= [HW] Maximum configurable fan speed. + devlink= [NET] + Format: + <entry>[,<entry>...] + + <entry>: + [<handle>[,<handle>...]]:<cmd>:<cmd-options> + + <handle>: + <bus-name>/<dev-name> + + Configure default devlink settings for matching + devlink instances during device initialization. + + Currently supported settings: + esw:mode:{ legacy | switchdev | switchdev_inactive } + + Examples: + devlink=[pci/0000:08:00.0]:esw:mode:switchdev + 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 + + See Documentation/networking/devlink/devlink-defaults.rst + for the full syntax and duplicate handling rules. + dfltcc= [HW,S390] Format: { on | off | def_only | inf_only | always } on: s390 zlib hardware support for compression on diff --git a/Documentation/networking/devlink/devlink-defaults.rst b/Documentation/networking/devlink/devlink-defaults.rst new file mode 100644 index 000000000000..7d6ccaddca86 --- /dev/null +++ b/Documentation/networking/devlink/devlink-defaults.rst @@ -0,0 +1,99 @@ +.. SPDX-License-Identifier: GPL-2.0 + +================ +Devlink Defaults +================ + +Devlink defaults allow selected devlink settings to be provided on the +kernel command line and applied to matching devlink instances during device +initialization. + +The devlink device is selected by its devlink handle. For PCI devices this is +the same handle shown by ``devlink dev show``, for example +``pci/0000:08:00.0``. + +Kernel command line syntax +========================== + +Defaults are specified with the ``devlink=`` kernel command line parameter. + +The general syntax is:: + + devlink=<default>[,<default>...] + +Each default has the following form:: + + [<handle-list>]:<cmd>:<cmd-options> + +``<handle-list>`` is one or more devlink handles:: + + <bus-name>/<dev-name>[,<bus-name>/<dev-name>...] + +All handles in the same ``[]`` list receive the same command setting. + +Multiple defaults may be specified by separating complete defaults with a +comma after the value:: + + devlink=[pci/0000:08:00.0]:esw:mode:switchdev,[pci/0000:08:00.1]:esw:mode:legacy + +Syntax rules +------------ + +The following syntax rules apply: + +* Specify all defaults in one ``devlink=`` parameter. Repeated ``devlink=`` + parameters are not accumulated. +* The ``devlink=`` value is limited by the kernel command line size. +* Whitespace is not allowed within the parameter value. +* ``<bus-name>`` and ``<dev-name>`` must not be empty. +* ``<bus-name>`` must not contain ``:``. +* ``<dev-name>`` may contain ``:``. This allows PCI names such as + ``0000:08:00.0``. +* Handles must not contain whitespace, ``[``, ``]`` or more than one ``/``. +* A comma inside ``[]`` separates handles. +* A comma after the ``<value>`` separates defaults. +* 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. +* Duplicate entries for the same handle are rejected and all devlink defaults + are ignored. + +Supported defaults +================== + +The supported command is ``esw``: + +.. list-table:: + :widths: 10 25 35 + :header-rows: 1 + + * - Command + - Options + - Values + * - ``esw`` + - ``mode:<mode>`` + - ``legacy``, ``switchdev``, ``switchdev_inactive`` + +The ``esw:mode`` default corresponds to the userspace command:: + + devlink dev eswitch set <handle> mode <value> + + +Examples +======== + +Set one PCI devlink instance to switchdev mode:: + + devlink=[pci/0000:08:00.0]:esw:mode:switchdev + +Set two PCI devlink instances to legacy mode:: + + devlink=[pci/0000:08:00.0,pci/0000:08:00.1]:esw:mode:legacy + +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 + +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 diff --git a/Documentation/networking/devlink/index.rst b/Documentation/networking/devlink/index.rst index f7ba7dcf477d..0d27a7008b14 100644 --- a/Documentation/networking/devlink/index.rst +++ b/Documentation/networking/devlink/index.rst @@ -56,6 +56,7 @@ general. :maxdepth: 1 devlink-dpipe + devlink-defaults devlink-eswitch-attr devlink-flash devlink-health diff --git a/net/devlink/core.c b/net/devlink/core.c index 2421a1f8dbb7..4b404135181c 100644 --- a/net/devlink/core.c +++ b/net/devlink/core.c @@ -73,9 +73,123 @@ 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, + size_t attrs_count, + struct devlink_default_attr_item *attr_item) +{ + char *attr_name; + char *value; + size_t i; + + attr_name = strsep(&str, ":"); + if (!attr_name || !*attr_name || !str || !*str) + return -EINVAL; + + value = str; + for (i = 0; i < attrs_count; i++) { + if (!strcmp(attr_name, attrs[i].name)) { + attr_item->attr = attrs[i].attr; + return attrs[i].value_parse(value, attr_item); + } + } + + return -EINVAL; +} + +static int __init +devlink_default_esw_mode_to_value(const char *str, + enum devlink_eswitch_mode *mode) +{ + if (!strcmp(str, "legacy")) { + *mode = DEVLINK_ESWITCH_MODE_LEGACY; + return 0; + } + if (!strcmp(str, "switchdev")) { + *mode = DEVLINK_ESWITCH_MODE_SWITCHDEV; + return 0; + } + if (!strcmp(str, "switchdev_inactive")) { + *mode = DEVLINK_ESWITCH_MODE_SWITCHDEV_INACTIVE; + return 0; + } + + return -EINVAL; +} + +static int __init +devlink_default_esw_mode_parse(const char *str, + struct devlink_default_attr_item *attr_item) +{ + enum devlink_eswitch_mode mode; + int err; + + err = devlink_default_esw_mode_to_value(str, &mode); + if (err) + return err; + + attr_item->value.eswitch_mode = mode; + return 0; +} + +static const struct devlink_default_attr_spec devlink_default_esw_attrs[] __initconst = { + { "mode", DEVLINK_ATTR_ESWITCH_MODE, devlink_default_esw_mode_parse }, +}; + +static int __init +devlink_default_esw_attr_parse(char *str, + struct devlink_default_attr_item *attr_item) +{ + return devlink_default_attr_parse(str, devlink_default_esw_attrs, + ARRAY_SIZE(devlink_default_esw_attrs), + attr_item); +} + +static int +devlink_default_eswitch_apply(struct devlink *devlink, + const struct devlink_default_attr_item *attr) +{ + const struct devlink_ops *ops = devlink->ops; + + switch (attr->attr) { + case DEVLINK_ATTR_ESWITCH_MODE: + if (!ops->eswitch_mode_set) + return -EOPNOTSUPP; + + return ops->eswitch_mode_set(devlink, attr->value.eswitch_mode, + NULL); + default: + return -EOPNOTSUPP; + } +} + +static const struct devlink_default_cmd_spec devlink_default_cmds[] __initconst = { + { + .name = "esw", + .cmd = DEVLINK_CMD_ESWITCH_SET, + .run = devlink_default_eswitch_apply, + .attr_parse = devlink_default_esw_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; } -- 2.34.1
|  |