From 6c53effab88df871c5196b4f026cdac6943283e2 Mon Sep 17 00:00:00 2001 From: Jakub Kicinski Date: Tue, 15 Sep 2026 09:13:33 -0700 Subject: [PATCH 1/9] devlink: fix the enum behind DEVLINK_ATTR_RELOAD_LIMITS DEVLINK_ATTR_RELOAD_LIMITS carries enum devlink_reload_limit, the spec says enum devlink_reload_action. The two are unrelated, and have a different set of values (bits 1, 2 vs bits 0, 1). AFAICT this is a cosmetic change - both DEVLINK_RELOAD_LIMIT_UNSPEC and the out of bounds bit 2 will be rejected either way because drivers don't declare them as supported. User will see either a policy validation failure or "Requested limit is not supported by the driver". While at it annotate the right enum for reload-stats-limit Link: https://patch.msgid.link/20260915161341.1053476-2-kuba@kernel.org Signed-off-by: Jakub Kicinski --- Documentation/netlink/specs/devlink.yaml | 15 ++++++++++++++- net/devlink/netlink_gen.c | 2 +- 2 files changed, 15 insertions(+), 2 deletions(-) diff --git a/Documentation/netlink/specs/devlink.yaml b/Documentation/netlink/specs/devlink.yaml index 38b1190f3d26..d933b205ee86 100644 --- a/Documentation/netlink/specs/devlink.yaml +++ b/Documentation/netlink/specs/devlink.yaml @@ -174,6 +174,18 @@ definitions: value: 1 - name: fw-activate + - + type: enum + name: reload-limit + entries: + - + name: unspec + doc: no constraints + - + name: no-reset + doc: >- + No reset allowed, no down time allowed, no link flap and no + configuration is lost. - type: enum name: param-cmode @@ -775,7 +787,7 @@ attribute-sets: - name: reload-limits type: bitfield32 - enum: reload-action + enum: reload-limit enum-as-flags: true - name: dev-stats @@ -793,6 +805,7 @@ attribute-sets: - name: reload-stats-limit type: u8 + enum: reload-limit - name: reload-stats-value type: u32 diff --git a/net/devlink/netlink_gen.c b/net/devlink/netlink_gen.c index dec00133178d..30f01901b587 100644 --- a/net/devlink/netlink_gen.c +++ b/net/devlink/netlink_gen.c @@ -334,7 +334,7 @@ static const struct nla_policy devlink_reload_nl_policy[DEVLINK_ATTR_INDEX + 1] [DEVLINK_ATTR_DEV_NAME] = { .type = NLA_NUL_STRING, }, [DEVLINK_ATTR_INDEX] = NLA_POLICY_FULL_RANGE(NLA_UINT, &devlink_attr_index_range), [DEVLINK_ATTR_RELOAD_ACTION] = NLA_POLICY_RANGE(NLA_U8, 1, 2), - [DEVLINK_ATTR_RELOAD_LIMITS] = NLA_POLICY_BITFIELD32(6), + [DEVLINK_ATTR_RELOAD_LIMITS] = NLA_POLICY_BITFIELD32(3), [DEVLINK_ATTR_NETNS_PID] = { .type = NLA_U32, }, [DEVLINK_ATTR_NETNS_FD] = { .type = NLA_U32, }, [DEVLINK_ATTR_NETNS_ID] = { .type = NLA_U32, }, From b8ffb7e5b9a1b1ff27b2529b41573d0960df2968 Mon Sep 17 00:00:00 2001 From: Jakub Kicinski Date: Tue, 15 Sep 2026 09:13:34 -0700 Subject: [PATCH 2/9] netlink: specs: devlink: drop the stale port dump reply value The bug the comment describes was fixed by commit 61c43780e944 ("devlink: fix port dump cmd type") two years ago. devlink_nl_port_get_dump_one() fills DEVLINK_CMD_PORT_NEW (7), not DEVLINK_CMD_NEW (3) now. Note that this change is likely a noop. _dictify_ops_directional() picks the "do" section's value when an op has both "do" and "dump". Link: https://patch.msgid.link/20260915161341.1053476-3-kuba@kernel.org Signed-off-by: Jakub Kicinski --- Documentation/netlink/specs/devlink.yaml | 1 - 1 file changed, 1 deletion(-) diff --git a/Documentation/netlink/specs/devlink.yaml b/Documentation/netlink/specs/devlink.yaml index d933b205ee86..0e0791d4e2c7 100644 --- a/Documentation/netlink/specs/devlink.yaml +++ b/Documentation/netlink/specs/devlink.yaml @@ -1401,7 +1401,6 @@ operations: request: attributes: *dev-id-attrs reply: - value: 3 # due to a bug, port dump returns DEVLINK_CMD_NEW attributes: *port-id-attrs - From 6338e31e68551268fa65b5fb1f67eecb3b7a8e3c Mon Sep 17 00:00:00 2001 From: Jakub Kicinski Date: Tue, 15 Sep 2026 09:13:35 -0700 Subject: [PATCH 3/9] netlink: specs: devlink: describe DEVLINK_ATTR_NESTED_DEVLINK The "# TODO: fill in the attributes in between" gap before selftests (176) hides exactly one attribute, DEVLINK_ATTR_NESTED_DEVLINK (175). devlink_nl_fill() calls devlink_nl_nested_fill() unconditionally, which emits one of these per entry in devlink->nested_rels (mlx5, ice). Unlike the other TODO gaps this is a single attribute of an already modelled type, so just fill it in. Link: https://patch.msgid.link/20260915161341.1053476-4-kuba@kernel.org Signed-off-by: Jakub Kicinski --- Documentation/netlink/specs/devlink.yaml | 23 +++++++++++++++++++---- 1 file changed, 19 insertions(+), 4 deletions(-) diff --git a/Documentation/netlink/specs/devlink.yaml b/Documentation/netlink/specs/devlink.yaml index 0e0791d4e2c7..7ec52f81c323 100644 --- a/Documentation/netlink/specs/devlink.yaml +++ b/Documentation/netlink/specs/devlink.yaml @@ -858,13 +858,14 @@ attribute-sets: name: linecard-supported-types type: nest nested-attributes: dl-linecard-supported-types - - # TODO: fill in the attributes in between - + - + name: nested-devlink + type: nest + multi-attr: true + nested-attributes: dl-nested-devlink - name: selftests type: nest - value: 176 nested-attributes: dl-selftest-id - name: rate-tx-priority @@ -1351,6 +1352,19 @@ attribute-sets: - name: index + - + name: dl-nested-devlink + subset-of: devlink + attributes: + - + name: bus-name + - + name: dev-name + - + name: index + - + name: netns-id + operations: enum-model: directional list: @@ -1376,6 +1390,7 @@ operations: - index - reload-failed - dev-stats + - nested-devlink dump: reply: *get-reply From 4ced66fc97bf7f979f76256ee04a180f65261b7e Mon Sep 17 00:00:00 2001 From: Jakub Kicinski Date: Tue, 15 Sep 2026 09:13:36 -0700 Subject: [PATCH 4/9] netlink: specs: devlink: complete the port function nest dl-port-function stops at caps, but the nest also carries DEVLINK_PORT_FN_ATTR_DEVLINK (5) and DEVLINK_PORT_FN_ATTR_MAX_IO_EQS (6) both put by devlink_nl_port_function_attrs_put() on every port-get do and dump. YNL raises Space 'dl-port-function' has no attribute with value '6' for any port reporting max_io_eqs or a nested devlink handle, i.e. for mlx5 SFs and VFs. Commit 5af3e3876d56 ("devlink: Support setting max_io_eqs") added the uAPI value and the hand written policy but never touched the spec. Add the missing attributes, subsequent commit reworks the code to use the YNL-generated policy. Link: https://patch.msgid.link/20260915161341.1053476-5-kuba@kernel.org Signed-off-by: Jakub Kicinski --- Documentation/netlink/specs/devlink.yaml | 8 ++++++++ net/devlink/netlink_gen.c | 11 ++++++++++- net/devlink/netlink_gen.h | 3 ++- 3 files changed, 20 insertions(+), 2 deletions(-) diff --git a/Documentation/netlink/specs/devlink.yaml b/Documentation/netlink/specs/devlink.yaml index 7ec52f81c323..962789dfbfac 100644 --- a/Documentation/netlink/specs/devlink.yaml +++ b/Documentation/netlink/specs/devlink.yaml @@ -992,6 +992,14 @@ attribute-sets: type: bitfield32 enum: port-fn-attr-cap enum-as-flags: true + - + name: devlink + type: nest + nested-attributes: dl-nested-devlink + doc: Handle of the peer devlink instance instantiated for this function. + - + name: max-io-eqs + type: u32 - name: dl-dpipe-tables diff --git a/net/devlink/netlink_gen.c b/net/devlink/netlink_gen.c index 30f01901b587..17d1edcdb935 100644 --- a/net/devlink/netlink_gen.c +++ b/net/devlink/netlink_gen.c @@ -46,17 +46,26 @@ devlink_attr_param_type_validate(const struct nlattr *attr, } /* Common nested types */ +const struct nla_policy devlink_dl_nested_devlink_nl_policy[DEVLINK_ATTR_INDEX + 1] = { + [DEVLINK_ATTR_BUS_NAME] = { .type = NLA_NUL_STRING, }, + [DEVLINK_ATTR_DEV_NAME] = { .type = NLA_NUL_STRING, }, + [DEVLINK_ATTR_INDEX] = NLA_POLICY_FULL_RANGE(NLA_UINT, &devlink_attr_index_range), + [DEVLINK_ATTR_NETNS_ID] = { .type = NLA_U32, }, +}; + const struct nla_policy devlink_dl_parent_dev_nl_policy[DEVLINK_ATTR_INDEX + 1] = { [DEVLINK_ATTR_BUS_NAME] = { .type = NLA_NUL_STRING, }, [DEVLINK_ATTR_DEV_NAME] = { .type = NLA_NUL_STRING, }, [DEVLINK_ATTR_INDEX] = NLA_POLICY_FULL_RANGE(NLA_UINT, &devlink_attr_index_range), }; -const struct nla_policy devlink_dl_port_function_nl_policy[DEVLINK_PORT_FN_ATTR_CAPS + 1] = { +const struct nla_policy devlink_dl_port_function_nl_policy[DEVLINK_PORT_FN_ATTR_MAX_IO_EQS + 1] = { [DEVLINK_PORT_FUNCTION_ATTR_HW_ADDR] = { .type = NLA_BINARY, }, [DEVLINK_PORT_FN_ATTR_STATE] = NLA_POLICY_MAX(NLA_U8, 1), [DEVLINK_PORT_FN_ATTR_OPSTATE] = NLA_POLICY_MAX(NLA_U8, 1), [DEVLINK_PORT_FN_ATTR_CAPS] = NLA_POLICY_BITFIELD32(15), + [DEVLINK_PORT_FN_ATTR_DEVLINK] = NLA_POLICY_NESTED(devlink_dl_nested_devlink_nl_policy), + [DEVLINK_PORT_FN_ATTR_MAX_IO_EQS] = { .type = NLA_U32, }, }; const struct nla_policy devlink_dl_rate_tc_bws_nl_policy[DEVLINK_RATE_TC_ATTR_BW + 1] = { diff --git a/net/devlink/netlink_gen.h b/net/devlink/netlink_gen.h index a70e0e4769aa..75572a9a23f6 100644 --- a/net/devlink/netlink_gen.h +++ b/net/devlink/netlink_gen.h @@ -13,8 +13,9 @@ #include /* Common nested types */ +extern const struct nla_policy devlink_dl_nested_devlink_nl_policy[DEVLINK_ATTR_INDEX + 1]; extern const struct nla_policy devlink_dl_parent_dev_nl_policy[DEVLINK_ATTR_INDEX + 1]; -extern const struct nla_policy devlink_dl_port_function_nl_policy[DEVLINK_PORT_FN_ATTR_CAPS + 1]; +extern const struct nla_policy devlink_dl_port_function_nl_policy[DEVLINK_PORT_FN_ATTR_MAX_IO_EQS + 1]; extern const struct nla_policy devlink_dl_rate_tc_bws_nl_policy[DEVLINK_RATE_TC_ATTR_BW + 1]; extern const struct nla_policy devlink_dl_selftest_id_nl_policy[DEVLINK_ATTR_SELFTEST_ID_FLASH + 1]; From 3ec610a6bb12bcd6f93e8c3eaf14ccbe68558bd4 Mon Sep 17 00:00:00 2001 From: Jakub Kicinski Date: Tue, 15 Sep 2026 09:13:37 -0700 Subject: [PATCH 5/9] devlink: generate the port function policy from the spec devlink has a one huge root attribute set for the whole family, we haven't taken the time to properly define the sub-sets for each command. Do it for port-set so that we can drop the hand written policy used by devlink_port_function_set(). We need this subsetting because within the DEVLINK_ATTR_PORT_FUNCTION nest DEVLINK_PORT_FN_ATTR_OPSTATE and DEVLINK_PORT_FN_ATTR_DEVLINK are output-only so we have to filter them out of the input set. Link: https://patch.msgid.link/20260915161341.1053476-6-kuba@kernel.org Signed-off-by: Jakub Kicinski --- Documentation/netlink/specs/devlink.yaml | 37 +++++++++++++++++++++++- net/devlink/netlink_gen.c | 13 ++------- net/devlink/netlink_gen.h | 3 +- net/devlink/port.c | 19 ++---------- 4 files changed, 42 insertions(+), 30 deletions(-) diff --git a/Documentation/netlink/specs/devlink.yaml b/Documentation/netlink/specs/devlink.yaml index 962789dfbfac..f23466fb27f9 100644 --- a/Documentation/netlink/specs/devlink.yaml +++ b/Documentation/netlink/specs/devlink.yaml @@ -1001,6 +1001,41 @@ attribute-sets: name: max-io-eqs type: u32 + - + name: dl-port-function-set + subset-of: dl-port-function + doc: | + Port function attributes that can be configured; opstate and the + devlink handle are read-only. + attributes: + - + name: hw-addr + - + name: state + - + name: caps + - + name: max-io-eqs + + - + name: dl-port-set + subset-of: devlink + doc: Attributes accepted by the port-set request. + attributes: + - + name: bus-name + - + name: dev-name + - + name: index + - + name: port-index + - + name: port-type + - + name: port-function + nested-attributes: dl-port-function-set + - name: dl-dpipe-tables subset-of: devlink @@ -1429,7 +1464,7 @@ operations: - name: port-set doc: Set devlink port instances. - attribute-set: devlink + attribute-set: dl-port-set dont-validate: [strict] flags: [admin-perm] do: diff --git a/net/devlink/netlink_gen.c b/net/devlink/netlink_gen.c index 17d1edcdb935..43ef6864d462 100644 --- a/net/devlink/netlink_gen.c +++ b/net/devlink/netlink_gen.c @@ -46,25 +46,16 @@ devlink_attr_param_type_validate(const struct nlattr *attr, } /* Common nested types */ -const struct nla_policy devlink_dl_nested_devlink_nl_policy[DEVLINK_ATTR_INDEX + 1] = { - [DEVLINK_ATTR_BUS_NAME] = { .type = NLA_NUL_STRING, }, - [DEVLINK_ATTR_DEV_NAME] = { .type = NLA_NUL_STRING, }, - [DEVLINK_ATTR_INDEX] = NLA_POLICY_FULL_RANGE(NLA_UINT, &devlink_attr_index_range), - [DEVLINK_ATTR_NETNS_ID] = { .type = NLA_U32, }, -}; - const struct nla_policy devlink_dl_parent_dev_nl_policy[DEVLINK_ATTR_INDEX + 1] = { [DEVLINK_ATTR_BUS_NAME] = { .type = NLA_NUL_STRING, }, [DEVLINK_ATTR_DEV_NAME] = { .type = NLA_NUL_STRING, }, [DEVLINK_ATTR_INDEX] = NLA_POLICY_FULL_RANGE(NLA_UINT, &devlink_attr_index_range), }; -const struct nla_policy devlink_dl_port_function_nl_policy[DEVLINK_PORT_FN_ATTR_MAX_IO_EQS + 1] = { +const struct nla_policy devlink_dl_port_function_set_nl_policy[DEVLINK_PORT_FN_ATTR_MAX_IO_EQS + 1] = { [DEVLINK_PORT_FUNCTION_ATTR_HW_ADDR] = { .type = NLA_BINARY, }, [DEVLINK_PORT_FN_ATTR_STATE] = NLA_POLICY_MAX(NLA_U8, 1), - [DEVLINK_PORT_FN_ATTR_OPSTATE] = NLA_POLICY_MAX(NLA_U8, 1), [DEVLINK_PORT_FN_ATTR_CAPS] = NLA_POLICY_BITFIELD32(15), - [DEVLINK_PORT_FN_ATTR_DEVLINK] = NLA_POLICY_NESTED(devlink_dl_nested_devlink_nl_policy), [DEVLINK_PORT_FN_ATTR_MAX_IO_EQS] = { .type = NLA_U32, }, }; @@ -106,7 +97,7 @@ static const struct nla_policy devlink_port_set_nl_policy[DEVLINK_ATTR_INDEX + 1 [DEVLINK_ATTR_INDEX] = NLA_POLICY_FULL_RANGE(NLA_UINT, &devlink_attr_index_range), [DEVLINK_ATTR_PORT_INDEX] = { .type = NLA_U32, }, [DEVLINK_ATTR_PORT_TYPE] = NLA_POLICY_MAX(NLA_U16, 3), - [DEVLINK_ATTR_PORT_FUNCTION] = NLA_POLICY_NESTED(devlink_dl_port_function_nl_policy), + [DEVLINK_ATTR_PORT_FUNCTION] = NLA_POLICY_NESTED(devlink_dl_port_function_set_nl_policy), }; /* DEVLINK_CMD_PORT_NEW - do */ diff --git a/net/devlink/netlink_gen.h b/net/devlink/netlink_gen.h index 75572a9a23f6..99ccacc693b7 100644 --- a/net/devlink/netlink_gen.h +++ b/net/devlink/netlink_gen.h @@ -13,9 +13,8 @@ #include /* Common nested types */ -extern const struct nla_policy devlink_dl_nested_devlink_nl_policy[DEVLINK_ATTR_INDEX + 1]; extern const struct nla_policy devlink_dl_parent_dev_nl_policy[DEVLINK_ATTR_INDEX + 1]; -extern const struct nla_policy devlink_dl_port_function_nl_policy[DEVLINK_PORT_FN_ATTR_MAX_IO_EQS + 1]; +extern const struct nla_policy devlink_dl_port_function_set_nl_policy[DEVLINK_PORT_FN_ATTR_MAX_IO_EQS + 1]; extern const struct nla_policy devlink_dl_rate_tc_bws_nl_policy[DEVLINK_RATE_TC_ATTR_BW + 1]; extern const struct nla_policy devlink_dl_selftest_id_nl_policy[DEVLINK_ATTR_SELFTEST_ID_FLASH + 1]; diff --git a/net/devlink/port.c b/net/devlink/port.c index 1528f2d148df..803429d9a008 100644 --- a/net/devlink/port.c +++ b/net/devlink/port.c @@ -6,19 +6,6 @@ #include "devl_internal.h" -#define DEVLINK_PORT_FN_CAPS_VALID_MASK \ - (_BITUL(__DEVLINK_PORT_FN_ATTR_CAPS_MAX) - 1) - -static const struct nla_policy devlink_function_nl_policy[DEVLINK_PORT_FUNCTION_ATTR_MAX + 1] = { - [DEVLINK_PORT_FUNCTION_ATTR_HW_ADDR] = { .type = NLA_BINARY }, - [DEVLINK_PORT_FN_ATTR_STATE] = - NLA_POLICY_RANGE(NLA_U8, DEVLINK_PORT_FN_STATE_INACTIVE, - DEVLINK_PORT_FN_STATE_ACTIVE), - [DEVLINK_PORT_FN_ATTR_CAPS] = - NLA_POLICY_BITFIELD32(DEVLINK_PORT_FN_CAPS_VALID_MASK), - [DEVLINK_PORT_FN_ATTR_MAX_IO_EQS] = { .type = NLA_U32 }, -}; - #define ASSERT_DEVLINK_PORT_REGISTERED(devlink_port) \ WARN_ON_ONCE(!(devlink_port)->registered) #define ASSERT_DEVLINK_PORT_NOT_REGISTERED(devlink_port) \ @@ -782,11 +769,11 @@ static int devlink_port_function_set(struct devlink_port *port, const struct nlattr *attr, struct netlink_ext_ack *extack) { - struct nlattr *tb[DEVLINK_PORT_FUNCTION_ATTR_MAX + 1]; + struct nlattr *tb[ARRAY_SIZE(devlink_dl_port_function_set_nl_policy)]; int err; - err = nla_parse_nested(tb, DEVLINK_PORT_FUNCTION_ATTR_MAX, attr, - devlink_function_nl_policy, extack); + err = nla_parse_nested(tb, ARRAY_SIZE(tb) - 1, attr, + devlink_dl_port_function_set_nl_policy, extack); if (err < 0) { NL_SET_ERR_MSG(extack, "Fail to parse port function attributes"); return err; From b1380f907cb0e02f12114a2d94a7e20a59fda723 Mon Sep 17 00:00:00 2001 From: Jakub Kicinski Date: Tue, 15 Sep 2026 09:13:38 -0700 Subject: [PATCH 6/9] netlink: specs: devlink: populate multi-attr attrs for region read and line card Three attributes are emitted repeatedly inside their nest: - devlink_nl_region_read_fill() calls devlink_nl_cmd_region_read_chunk_fill() once per 256 byte unit - devlink_nl_region_snapshots_id_put() emits one DEVLINK_ATTR_REGION_SNAPSHOT sub-nest per entry on the region's snapshot list - devlink_nl_linecard_fill() emits one DEVLINK_ATTR_LINECARD_TYPE per linecard->types_count entry In all three cases we're missing the multi-attr properties, and the attributes themselves are missing from the attr list used by C code gen. Link: https://patch.msgid.link/20260915161341.1053476-7-kuba@kernel.org Signed-off-by: Jakub Kicinski --- Documentation/netlink/specs/devlink.yaml | 28 ++++++++++++++++++++---- 1 file changed, 24 insertions(+), 4 deletions(-) diff --git a/Documentation/netlink/specs/devlink.yaml b/Documentation/netlink/specs/devlink.yaml index f23466fb27f9..5c9c672497d4 100644 --- a/Documentation/netlink/specs/devlink.yaml +++ b/Documentation/netlink/specs/devlink.yaml @@ -1264,6 +1264,7 @@ attribute-sets: attributes: - name: region-snapshot + multi-attr: true - name: dl-region-snapshot @@ -1278,6 +1279,7 @@ attribute-sets: attributes: - name: region-chunk + multi-attr: true - name: dl-region-chunk @@ -1360,6 +1362,7 @@ attribute-sets: attributes: - name: linecard-type + multi-attr: true - name: dl-selftest-id @@ -1971,7 +1974,7 @@ operations: post: devlink-nl-post-doit request: value: 42 - attributes: ®ion-id-attrs + attributes: - bus-name - dev-name - index @@ -1979,7 +1982,15 @@ operations: - region-name reply: ®ion-get-reply value: 42 - attributes: *region-id-attrs + attributes: + - bus-name + - dev-name + - index + - port-index + - region-name + - region-size + - region-max-snapshots + - region-snapshots dump: request: attributes: *dev-id-attrs @@ -2045,6 +2056,7 @@ operations: - index - port-index - region-name + - region-chunks - name: port-param-get @@ -2444,14 +2456,22 @@ operations: post: devlink-nl-post-doit request: value: 78 - attributes: &linecard-id-attrs + attributes: - bus-name - dev-name - index - linecard-index reply: &linecard-get-reply value: 80 - attributes: *linecard-id-attrs + attributes: + - bus-name + - dev-name + - index + - linecard-index + - linecard-state + - linecard-type + - linecard-supported-types + - nested-devlink dump: request: attributes: *dev-id-attrs From 150079380e4b13c7ed0e738913937e375259172c Mon Sep 17 00:00:00 2001 From: Jakub Kicinski Date: Tue, 15 Sep 2026 09:13:39 -0700 Subject: [PATCH 7/9] netlink: specs: devlink: describe the netns id in the parent-dev nest devlink_nl_rate_parent_fill() emits DEVLINK_ATTR_PARENT_DEV via devlink_nl_put_nested_handle(), which adds DEVLINK_ATTR_NETNS_ID whenever the parent rate node lives on a devlink instance in another netns. Now that we defined dl-nested-devlink subset, which unlike dl-parent-dev includes netns-id, let's switch to it. The rate APIs input genuinely does not accept the netns-id, so we need to subset them to stick with dl-parent-dev. Fixes: b5f90fd4580ce7 ("devlink: Add parent dev to devlink API") Link: https://patch.msgid.link/20260915161341.1053476-8-kuba@kernel.org Signed-off-by: Jakub Kicinski --- Documentation/netlink/specs/devlink.yaml | 41 ++++++++++++++++++++++-- 1 file changed, 38 insertions(+), 3 deletions(-) diff --git a/Documentation/netlink/specs/devlink.yaml b/Documentation/netlink/specs/devlink.yaml index 5c9c672497d4..5535247faf14 100644 --- a/Documentation/netlink/specs/devlink.yaml +++ b/Documentation/netlink/specs/devlink.yaml @@ -912,7 +912,7 @@ attribute-sets: - name: parent-dev type: nest - nested-attributes: dl-parent-dev + nested-attributes: dl-nested-devlink doc: | Identifies the devlink instance which owns the parent rate node. Used with rate-set and rate-new to parent a rate object to a node on @@ -1390,6 +1390,10 @@ attribute-sets: - name: dl-parent-dev subset-of: devlink + doc: | + Devlink handle accepted as the parent-dev input; the netns id the + kernel reports back is not accepted, the parent is always resolved + in the caller's netns. attributes: - name: bus-name @@ -1398,6 +1402,37 @@ attribute-sets: - name: index + - + name: dl-rate-set + subset-of: devlink + doc: Attributes accepted by the rate-set and rate-new requests. + attributes: + - + name: bus-name + - + name: dev-name + - + name: index + - + name: port-index + - + name: rate-node-name + - + name: rate-tx-share + - + name: rate-tx-max + - + name: rate-tx-priority + - + name: rate-tx-weight + - + name: rate-parent-node-name + - + name: rate-tc-bws + - + name: parent-dev + nested-attributes: dl-parent-dev + - name: dl-nested-devlink subset-of: devlink @@ -2387,7 +2422,7 @@ operations: - name: rate-set doc: Set rate instances. - attribute-set: devlink + attribute-set: dl-rate-set dont-validate: [strict] flags: [admin-perm] do: @@ -2410,7 +2445,7 @@ operations: - name: rate-new doc: Create rate instances. - attribute-set: devlink + attribute-set: dl-rate-set dont-validate: [strict] flags: [admin-perm] do: From 826e2a736e333cb5a13461fa5098d692e84ccea8 Mon Sep 17 00:00:00 2001 From: Jakub Kicinski Date: Tue, 15 Sep 2026 09:13:40 -0700 Subject: [PATCH 8/9] netlink: specs: devlink: add pad to the subsets carrying padded u64s We are missing the pad attribute in a number of subsets. Worse, dl-attr-stats which is a separate attr space doesn't define pad, but reuses the value from the root attr set (DEVLINK_ATTR_PAD). This would break parsing stats on an arch without CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS. Link: https://patch.msgid.link/20260915161341.1053476-9-kuba@kernel.org Signed-off-by: Jakub Kicinski --- Documentation/netlink/specs/devlink.yaml | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/Documentation/netlink/specs/devlink.yaml b/Documentation/netlink/specs/devlink.yaml index 5535247faf14..4fb64e71063d 100644 --- a/Documentation/netlink/specs/devlink.yaml +++ b/Documentation/netlink/specs/devlink.yaml @@ -1065,6 +1065,8 @@ attribute-sets: name: dpipe-table-resource-id - name: dpipe-table-resource-units + - + name: pad - name: dl-dpipe-table-matches @@ -1099,6 +1101,8 @@ attribute-sets: name: dpipe-entry-action-values - name: dpipe-entry-counter + - + name: pad - name: dl-dpipe-entry-match-values @@ -1237,6 +1241,8 @@ attribute-sets: name: resource-unit - name: resource-occ + - + name: pad - name: dl-resource-list @@ -1289,6 +1295,8 @@ attribute-sets: name: region-chunk-data - name: region-chunk-addr + - + name: pad - name: dl-fmsg @@ -1329,6 +1337,8 @@ attribute-sets: name: health-reporter-auto-dump - name: health-reporter-burst-period + - + name: pad - name: dl-attr-stats @@ -1343,6 +1353,10 @@ attribute-sets: - name: stats-rx-dropped type: u64 + - + name: pad + type: pad + value: 61 - name: dl-trap-metadata From 2a22788ba265881eb048f224534b7556815026de Mon Sep 17 00:00:00 2001 From: Jakub Kicinski Date: Tue, 15 Sep 2026 09:13:41 -0700 Subject: [PATCH 9/9] devlink: validate the port index in the rate set request port-index is the only way rate-set can address a leaf (port) rate object, but it was never listed in the request, so the generated policy has no entry for it. The op declares .maxattr = DEVLINK_ATTR_PARENT_DEV, so the attribute still reaches info->attrs[], validated against a zeroed slot - NLA_UNSPEC, length 0 - which GENL_DONT_VALIDATE_STRICT accepts at any length. devlink_port_get_from_attrs() then runs nla_get_u32() on it. Handed a zero-length port-index the kernel reads the four bytes past the payload, which are the next attribute's header, and acts on the port index those spell out. Since we're reading a linear skb the OOB read is still within the same memory allocation, it's just garbage. We also do not echo the garbage back to the user so it's not an info leak either. Hence not treating this is a real bug fix. rate-new is left alone on purpose. It creates rate nodes, resolved by name through devlink_rate_node_get_from_attrs(), and never looks at port-index. Link: https://patch.msgid.link/20260915161341.1053476-10-kuba@kernel.org Signed-off-by: Jakub Kicinski --- Documentation/netlink/specs/devlink.yaml | 1 + net/devlink/netlink_gen.c | 1 + 2 files changed, 2 insertions(+) diff --git a/Documentation/netlink/specs/devlink.yaml b/Documentation/netlink/specs/devlink.yaml index 4fb64e71063d..1de0daa0f921 100644 --- a/Documentation/netlink/specs/devlink.yaml +++ b/Documentation/netlink/specs/devlink.yaml @@ -2447,6 +2447,7 @@ operations: - bus-name - dev-name - index + - port-index - rate-node-name - rate-tx-share - rate-tx-max diff --git a/net/devlink/netlink_gen.c b/net/devlink/netlink_gen.c index 43ef6864d462..9e1b4c081a7b 100644 --- a/net/devlink/netlink_gen.c +++ b/net/devlink/netlink_gen.c @@ -618,6 +618,7 @@ static const struct nla_policy devlink_rate_set_nl_policy[DEVLINK_ATTR_PARENT_DE [DEVLINK_ATTR_BUS_NAME] = { .type = NLA_NUL_STRING, }, [DEVLINK_ATTR_DEV_NAME] = { .type = NLA_NUL_STRING, }, [DEVLINK_ATTR_INDEX] = NLA_POLICY_FULL_RANGE(NLA_UINT, &devlink_attr_index_range), + [DEVLINK_ATTR_PORT_INDEX] = { .type = NLA_U32, }, [DEVLINK_ATTR_RATE_NODE_NAME] = { .type = NLA_NUL_STRING, }, [DEVLINK_ATTR_RATE_TX_SHARE] = { .type = NLA_U64, }, [DEVLINK_ATTR_RATE_TX_MAX] = { .type = NLA_U64, },