Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

devlink: Fix excessive stack usage in rate TC bandwidth parsing

The devlink_nl_rate_tc_bw_parse function uses a large stack array for
devlink attributes, which triggers a warning about excessive stack
usage:

net/devlink/rate.c: In function 'devlink_nl_rate_tc_bw_parse':
net/devlink/rate.c:382:1: error: the frame size of 1648 bytes is larger than 1536 bytes [-Werror=frame-larger-than=]

Introduce a separate attribute set specifically for rate TC bandwidth
parsing that only contains the two attributes actually used: index
and bandwidth. This reduces the stack array from DEVLINK_ATTR_MAX
entries to just 2 entries, solving the stack usage issue.

Update devlink selftest to use the new 'index' and 'bw' attribute names
consistent with the YAML spec.

Example usage with ynl with the new spec:

./tools/net/ynl/cli.py --spec Documentation/netlink/specs/devlink.yaml \
--do rate-set --json '{
"bus-name": "pci",
"dev-name": "0000:08:00.0",
"port-index": 1,
"rate-tc-bws": [
{"index": 0, "bw": 50},
{"index": 1, "bw": 50},
{"index": 2, "bw": 0},
{"index": 3, "bw": 0},
{"index": 4, "bw": 0},
{"index": 5, "bw": 0},
{"index": 6, "bw": 0},
{"index": 7, "bw": 0}
]
}'

./tools/net/ynl/cli.py --spec Documentation/netlink/specs/devlink.yaml \
--do rate-get --json '{
"bus-name": "pci",
"dev-name": "0000:08:00.0",
"port-index": 1
}'

output for rate-get:
{'bus-name': 'pci',
'dev-name': '0000:08:00.0',
'port-index': 1,
'rate-tc-bws': [{'bw': 50, 'index': 0},
{'bw': 50, 'index': 1},
{'bw': 0, 'index': 2},
{'bw': 0, 'index': 3},
{'bw': 0, 'index': 4},
{'bw': 0, 'index': 5},
{'bw': 0, 'index': 6},
{'bw': 0, 'index': 7}],
'rate-tx-max': 0,
'rate-tx-priority': 0,
'rate-tx-share': 0,
'rate-tx-weight': 0,
'rate-type': 'leaf'}

Fixes: 566e8f108fc7 ("devlink: Extend devlink rate API with traffic classes bandwidth management")
Reported-by: Arnd Bergmann <arnd@arndb.de>
Closes: https://lore.kernel.org/netdev/20250708160652.1810573-1-arnd@kernel.org/
Reported-by: kernel test robot <lkp@intel.com>
Closes: https://lore.kernel.org/oe-kbuild-all/202507171943.W7DJcs6Y-lkp@intel.com/
Suggested-by: Jakub Kicinski <kuba@kernel.org>
Signed-off-by: Carolina Jubran <cjubran@nvidia.com>
Tested-by: Carolina Jubran <cjubran@nvidia.com>
Signed-off-by: Tariq Toukan <tariqt@nvidia.com>
Reviewed-by: Jiri Pirko <jiri@nvidia.com>
Link: https://patch.msgid.link/1753175609-330621-1-git-send-email-tariqt@nvidia.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>

authored by

Carolina Jubran and committed by
Jakub Kicinski
1bbdb81a 56613001

+42 -39
+11 -15
Documentation/netlink/specs/devlink.yaml
··· 853 853 type: nest 854 854 multi-attr: true 855 855 nested-attributes: dl-rate-tc-bws 856 - - 857 - name: rate-tc-index 858 - type: u8 859 - checks: 860 - max: rate-tc-index-max 861 - - 862 - name: rate-tc-bw 863 - type: u32 864 - doc: | 865 - Specifies the bandwidth share assigned to the Traffic Class. 866 - The bandwidth for the traffic class is determined 867 - in proportion to the sum of the shares of all configured classes. 868 856 - 869 857 name: dl-dev-stats 870 858 subset-of: devlink ··· 1259 1271 type: flag 1260 1272 - 1261 1273 name: dl-rate-tc-bws 1262 - subset-of: devlink 1274 + name-prefix: devlink-rate-tc-attr- 1263 1275 attributes: 1264 1276 - 1265 - name: rate-tc-index 1277 + name: index 1278 + type: u8 1279 + checks: 1280 + max: rate-tc-index-max 1266 1281 - 1267 - name: rate-tc-bw 1282 + name: bw 1283 + type: u32 1284 + doc: | 1285 + Specifies the bandwidth share assigned to the Traffic Class. 1286 + The bandwidth for the traffic class is determined 1287 + in proportion to the sum of the shares of all configured classes. 1268 1288 1269 1289 operations: 1270 1290 enum-model: directional
+9 -2
include/uapi/linux/devlink.h
··· 635 635 DEVLINK_ATTR_REGION_DIRECT, /* flag */ 636 636 637 637 DEVLINK_ATTR_RATE_TC_BWS, /* nested */ 638 - DEVLINK_ATTR_RATE_TC_INDEX, /* u8 */ 639 - DEVLINK_ATTR_RATE_TC_BW, /* u32 */ 640 638 641 639 /* Add new attributes above here, update the spec in 642 640 * Documentation/netlink/specs/devlink.yaml and re-generate ··· 643 645 644 646 __DEVLINK_ATTR_MAX, 645 647 DEVLINK_ATTR_MAX = __DEVLINK_ATTR_MAX - 1 648 + }; 649 + 650 + enum devlink_rate_tc_attr { 651 + DEVLINK_RATE_TC_ATTR_UNSPEC, 652 + DEVLINK_RATE_TC_ATTR_INDEX, /* u8 */ 653 + DEVLINK_RATE_TC_ATTR_BW, /* u32 */ 654 + 655 + __DEVLINK_RATE_TC_ATTR_MAX, 656 + DEVLINK_RATE_TC_ATTR_MAX = __DEVLINK_RATE_TC_ATTR_MAX - 1 646 657 }; 647 658 648 659 /* Mapping between internal resource described by the field and system
+10 -10
net/devlink/rate.c
··· 90 90 if (!nla_tc_bw) 91 91 return -EMSGSIZE; 92 92 93 - if (nla_put_u8(msg, DEVLINK_ATTR_RATE_TC_INDEX, i) || 94 - nla_put_u32(msg, DEVLINK_ATTR_RATE_TC_BW, tc_bw[i])) 93 + if (nla_put_u8(msg, DEVLINK_RATE_TC_ATTR_INDEX, i) || 94 + nla_put_u32(msg, DEVLINK_RATE_TC_ATTR_BW, tc_bw[i])) 95 95 goto nla_put_failure; 96 96 97 97 nla_nest_end(msg, nla_tc_bw); ··· 346 346 unsigned long *bitmap, 347 347 struct netlink_ext_ack *extack) 348 348 { 349 - struct nlattr *tb[DEVLINK_ATTR_MAX + 1]; 349 + struct nlattr *tb[DEVLINK_RATE_TC_ATTR_MAX + 1]; 350 350 u8 tc_index; 351 351 int err; 352 352 353 - err = nla_parse_nested(tb, DEVLINK_ATTR_MAX, parent_nest, 353 + err = nla_parse_nested(tb, DEVLINK_RATE_TC_ATTR_MAX, parent_nest, 354 354 devlink_dl_rate_tc_bws_nl_policy, extack); 355 355 if (err) 356 356 return err; 357 357 358 - if (!tb[DEVLINK_ATTR_RATE_TC_INDEX]) { 358 + if (!tb[DEVLINK_RATE_TC_ATTR_INDEX]) { 359 359 NL_SET_ERR_ATTR_MISS(extack, parent_nest, 360 - DEVLINK_ATTR_RATE_TC_INDEX); 360 + DEVLINK_RATE_TC_ATTR_INDEX); 361 361 return -EINVAL; 362 362 } 363 363 364 - tc_index = nla_get_u8(tb[DEVLINK_ATTR_RATE_TC_INDEX]); 364 + tc_index = nla_get_u8(tb[DEVLINK_RATE_TC_ATTR_INDEX]); 365 365 366 - if (!tb[DEVLINK_ATTR_RATE_TC_BW]) { 366 + if (!tb[DEVLINK_RATE_TC_ATTR_BW]) { 367 367 NL_SET_ERR_ATTR_MISS(extack, parent_nest, 368 - DEVLINK_ATTR_RATE_TC_BW); 368 + DEVLINK_RATE_TC_ATTR_BW); 369 369 return -EINVAL; 370 370 } 371 371 ··· 376 376 return -EINVAL; 377 377 } 378 378 379 - tc_bw[tc_index] = nla_get_u32(tb[DEVLINK_ATTR_RATE_TC_BW]); 379 + tc_bw[tc_index] = nla_get_u32(tb[DEVLINK_RATE_TC_ATTR_BW]); 380 380 381 381 return 0; 382 382 }