devlink: Add port-specific option to resource dump doit

Allow querying devlink resources per-port via the resource-dump doit
handler. When a port-index attribute is provided, only that port's
resources are returned. When no port-index is given, only device-level
resources are returned, preserving backward compatibility.

Signed-off-by: Or Har-Toov <ohartoov@nvidia.com>
Reviewed-by: Moshe Shemesh <moshe@nvidia.com>
Signed-off-by: Tariq Toukan <tariqt@nvidia.com>
Link: https://patch.msgid.link/20260407194107.148063-8-tariqt@nvidia.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
This commit is contained in:
Or Har-Toov 2026-04-07 22:41:02 +03:00 committed by Jakub Kicinski
parent 810b76394d
commit 7511ff14f3
4 changed files with 24 additions and 7 deletions

View File

@ -1757,19 +1757,21 @@ operations:
attribute-set: devlink
dont-validate: [strict]
do:
pre: devlink-nl-pre-doit
pre: devlink-nl-pre-doit-port-optional
post: devlink-nl-post-doit
request:
attributes:
- bus-name
- dev-name
- index
- port-index
reply: &resource-dump-reply
value: 36
attributes:
- bus-name
- dev-name
- index
- port-index
- resource-list
dump:
request:

View File

@ -309,6 +309,7 @@ static const struct nla_policy devlink_resource_dump_do_nl_policy[DEVLINK_ATTR_I
[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_CMD_RESOURCE_DUMP - dump */
@ -962,7 +963,7 @@ const struct genl_split_ops devlink_nl_ops[75] = {
{
.cmd = DEVLINK_CMD_RESOURCE_DUMP,
.validate = GENL_DONT_VALIDATE_STRICT,
.pre_doit = devlink_nl_pre_doit,
.pre_doit = devlink_nl_pre_doit_port_optional,
.doit = devlink_nl_resource_dump_doit,
.post_doit = devlink_nl_post_doit,
.policy = devlink_resource_dump_do_nl_policy,

View File

@ -24,11 +24,11 @@ int devlink_nl_pre_doit(const struct genl_split_ops *ops, struct sk_buff *skb,
struct genl_info *info);
int devlink_nl_pre_doit_port(const struct genl_split_ops *ops,
struct sk_buff *skb, struct genl_info *info);
int devlink_nl_pre_doit_dev_lock(const struct genl_split_ops *ops,
struct sk_buff *skb, struct genl_info *info);
int devlink_nl_pre_doit_port_optional(const struct genl_split_ops *ops,
struct sk_buff *skb,
struct genl_info *info);
int devlink_nl_pre_doit_dev_lock(const struct genl_split_ops *ops,
struct sk_buff *skb, struct genl_info *info);
void
devlink_nl_post_doit(const struct genl_split_ops *ops, struct sk_buff *skb,
struct genl_info *info);

View File

@ -251,8 +251,10 @@ static int devlink_resource_list_fill(struct sk_buff *skb,
static int devlink_resource_fill(struct genl_info *info,
enum devlink_command cmd, int flags)
{
struct devlink_port *devlink_port = info->user_ptr[1];
struct devlink *devlink = info->user_ptr[0];
struct devlink_resource *resource;
struct list_head *resource_list;
struct nlattr *resources_attr;
struct sk_buff *skb = NULL;
struct nlmsghdr *nlh;
@ -261,7 +263,9 @@ static int devlink_resource_fill(struct genl_info *info,
int i;
int err;
resource = list_first_entry(&devlink->resource_list,
resource_list = devlink_port ?
&devlink_port->resource_list : &devlink->resource_list;
resource = list_first_entry(resource_list,
struct devlink_resource, list);
start_again:
err = devlink_nl_msg_reply_and_new(&skb, info);
@ -277,6 +281,9 @@ static int devlink_resource_fill(struct genl_info *info,
if (devlink_nl_put_handle(skb, devlink))
goto nla_put_failure;
if (devlink_port &&
nla_put_u32(skb, DEVLINK_ATTR_PORT_INDEX, devlink_port->index))
goto nla_put_failure;
resources_attr = nla_nest_start_noflag(skb,
DEVLINK_ATTR_RESOURCE_LIST);
@ -285,7 +292,7 @@ static int devlink_resource_fill(struct genl_info *info,
incomplete = false;
i = 0;
list_for_each_entry_from(resource, &devlink->resource_list, list) {
list_for_each_entry_from(resource, resource_list, list) {
err = devlink_resource_put(devlink, skb, resource);
if (err) {
if (!i)
@ -319,9 +326,16 @@ static int devlink_resource_fill(struct genl_info *info,
int devlink_nl_resource_dump_doit(struct sk_buff *skb, struct genl_info *info)
{
struct devlink_port *devlink_port = info->user_ptr[1];
struct devlink *devlink = info->user_ptr[0];
struct list_head *resource_list;
if (list_empty(&devlink->resource_list))
if (info->attrs[DEVLINK_ATTR_PORT_INDEX] && !devlink_port)
return -ENODEV;
resource_list = devlink_port ?
&devlink_port->resource_list : &devlink->resource_list;
if (list_empty(resource_list))
return -EOPNOTSUPP;
return devlink_resource_fill(info, DEVLINK_CMD_RESOURCE_DUMP, 0);