From: Or Har-Toov <[email protected]>

Allow querying devlink resources per-port via the resource-dump dumpit
handler. Both device-level and all ports resources are included in the
reply.

For example:

$ devlink resource show
pci/0000:03:00.0:
  name local_max_SFs size 508 unit entry
  name external_max_SFs size 508 unit entry
pci/0000:03:00.0/196608:
  name max_SFs size 20 unit entry
pci/0000:03:00.1:
  name local_max_SFs size 508 unit entry
  name external_max_SFs size 508 unit entry
pci/0000:03:00.1/262144:
  name max_SFs size 20 unit entry

Signed-off-by: Or Har-Toov <[email protected]>
Reviewed-by: Moshe Shemesh <[email protected]>
Signed-off-by: Tariq Toukan <[email protected]>
---
 net/devlink/devl_internal.h |  5 ++++
 net/devlink/netlink.c       |  2 ++
 net/devlink/resource.c      | 59 ++++++++++++++++++++++++++++++++-----
 3 files changed, 58 insertions(+), 8 deletions(-)

diff --git a/net/devlink/devl_internal.h b/net/devlink/devl_internal.h
index 7dfb7cdd2d23..e4e48ee2da5a 100644
--- a/net/devlink/devl_internal.h
+++ b/net/devlink/devl_internal.h
@@ -164,6 +164,11 @@ struct devlink_nl_dump_state {
                struct {
                        u64 dump_ts;
                };
+               /* DEVLINK_CMD_RESOURCE_DUMP */
+               struct {
+                       u32 index;
+                       bool index_valid;
+               } port_ctx;
        };
 };
 
diff --git a/net/devlink/netlink.c b/net/devlink/netlink.c
index 32ddbe244cb7..ae4afc739678 100644
--- a/net/devlink/netlink.c
+++ b/net/devlink/netlink.c
@@ -370,6 +370,8 @@ static int devlink_nl_inst_iter_dumpit(struct sk_buff *msg,
 
                /* restart sub-object walk for the next instance */
                state->idx = 0;
+               state->port_ctx.index = 0;
+               state->port_ctx.index_valid = false;
        }
 
        if (err != -EMSGSIZE)
diff --git a/net/devlink/resource.c b/net/devlink/resource.c
index 02fb36e25c52..7984eda63eb6 100644
--- a/net/devlink/resource.c
+++ b/net/devlink/resource.c
@@ -328,16 +328,20 @@ int devlink_nl_resource_dump_doit(struct sk_buff *skb, 
struct genl_info *info)
 }
 
 static int
-devlink_nl_resource_dump_one(struct sk_buff *skb, struct devlink *devlink,
-                            struct netlink_callback *cb, int flags)
+devlink_resource_dump_fill_one(struct sk_buff *skb, struct devlink *devlink,
+                              struct devlink_port *devlink_port,
+                              struct netlink_callback *cb, int flags, int *idx)
 {
-       struct devlink_nl_dump_state *state = devlink_dump_state(cb);
+       struct list_head *resource_list;
        struct nlattr *resources_attr;
-       int start_idx = state->idx;
+       int start_idx = *idx;
        void *hdr;
        int err;
 
-       if (list_empty(&devlink->resource_list))
+       resource_list = devlink_port ?
+               &devlink_port->resource_list : &devlink->resource_list;
+
+       if (list_empty(resource_list))
                return 0;
 
        err = -EMSGSIZE;
@@ -348,15 +352,17 @@ devlink_nl_resource_dump_one(struct sk_buff *skb, struct 
devlink *devlink,
 
        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);
        if (!resources_attr)
                goto nla_put_failure;
 
-       err = devlink_resource_list_fill(skb, devlink,
-                                        &devlink->resource_list, &state->idx);
+       err = devlink_resource_list_fill(skb, devlink, resource_list, idx);
        if (err) {
-               if (state->idx == start_idx)
+               if (*idx == start_idx)
                        goto resource_list_cancel;
                nla_nest_end(skb, resources_attr);
                genlmsg_end(skb, hdr);
@@ -373,6 +379,43 @@ devlink_nl_resource_dump_one(struct sk_buff *skb, struct 
devlink *devlink,
        return err;
 }
 
+static int
+devlink_nl_resource_dump_one(struct sk_buff *skb, struct devlink *devlink,
+                            struct netlink_callback *cb, int flags)
+{
+       struct devlink_nl_dump_state *state = devlink_dump_state(cb);
+       struct devlink_port *devlink_port;
+       unsigned long port_idx;
+       int err;
+
+       if (!state->port_ctx.index_valid) {
+               err = devlink_resource_dump_fill_one(skb, devlink, NULL,
+                                                    cb, flags, &state->idx);
+               if (err)
+                       return err;
+               state->idx = 0;
+       }
+
+       /* Check in case port was removed between dump callbacks. */
+       if (state->port_ctx.index_valid &&
+           !xa_load(&devlink->ports, state->port_ctx.index))
+               state->idx = 0;
+       state->port_ctx.index_valid = true;
+       xa_for_each_start(&devlink->ports, port_idx, devlink_port,
+                         state->port_ctx.index) {
+               err = devlink_resource_dump_fill_one(skb, devlink, devlink_port,
+                                                    cb, flags, &state->idx);
+               if (err) {
+                       state->port_ctx.index = port_idx;
+                       return err;
+               }
+               state->idx = 0;
+       }
+       state->port_ctx.index_valid = false;
+       state->port_ctx.index = 0;
+       return 0;
+}
+
 int devlink_nl_resource_dump_dumpit(struct sk_buff *skb,
                                    struct netlink_callback *cb)
 {
-- 
2.44.0


Reply via email to