]> git.proxmox.com Git - mirror_iproute2.git/blobdiff - devlink/devlink.c
devlink: Add support for resource/dpipe relation
[mirror_iproute2.git] / devlink / devlink.c
index 96b33e98981389bd2ec5e5b1571c5c4d747c520f..69c3c5d9dd3166b33e0ac71e6c0b94a5802336ee 100644 (file)
@@ -2739,6 +2739,17 @@ struct dpipe_header {
        unsigned int fields_count;
 };
 
+struct dpipe_table {
+       struct list_head list;
+       char *name;
+       unsigned int resource_id;
+       bool resource_valid;
+};
+
+struct dpipe_tables {
+       struct list_head table_list;
+};
+
 struct resource {
        char *name;
        uint64_t size;
@@ -2764,6 +2775,7 @@ struct resource_ctx {
        struct dl *dl;
        int err;
        struct resources *resources;
+       struct dpipe_tables *tables;
        bool print_resources;
        bool pending_change;
 };
@@ -2829,7 +2841,10 @@ struct dpipe_ctx {
        int err;
        struct list_head global_headers;
        struct list_head local_headers;
+       struct dpipe_tables *tables;
+       struct resources *resources;
        bool print_headers;
+       bool print_tables;
 };
 
 static struct dpipe_header *dpipe_header_alloc(unsigned int fields_count)
@@ -2882,25 +2897,49 @@ static void dpipe_header_del(struct dpipe_header *header)
        list_del(&header->list);
 }
 
-static struct dpipe_ctx *dpipe_ctx_alloc(struct dl *dl)
+static struct dpipe_table *dpipe_table_alloc(void)
+{
+       return calloc(1, sizeof(struct dpipe_table));
+}
+
+static void dpipe_table_free(struct dpipe_table *table)
+{
+       free(table);
+}
+
+static struct dpipe_tables *dpipe_tables_alloc(void)
 {
-       struct dpipe_ctx *ctx;
+       struct dpipe_tables *tables;
 
-       ctx = calloc(1, sizeof(struct dpipe_ctx));
-       if (!ctx)
+       tables = calloc(1, sizeof(struct dpipe_tables));
+       if (!tables)
                return NULL;
-       ctx->dl = dl;
-       INIT_LIST_HEAD(&ctx->global_headers);
-       INIT_LIST_HEAD(&ctx->local_headers);
-       return ctx;
+       INIT_LIST_HEAD(&tables->table_list);
+       return tables;
+}
+
+static void dpipe_tables_free(struct dpipe_tables *tables)
+{
+       struct dpipe_table *table, *tmp;
+
+       list_for_each_entry_safe(table, tmp, &tables->table_list, list)
+               dpipe_table_free(table);
+       free(tables);
 }
 
-static void dpipe_ctx_free(struct dpipe_ctx *ctx)
+static int dpipe_ctx_init(struct dpipe_ctx *ctx, struct dl *dl)
 {
-       free(ctx);
+       ctx->tables = dpipe_tables_alloc();
+       if (!ctx->tables)
+               return -ENOMEM;
+
+       ctx->dl = dl;
+       INIT_LIST_HEAD(&ctx->global_headers);
+       INIT_LIST_HEAD(&ctx->local_headers);
+       return 0;
 }
 
-static void dpipe_ctx_clear(struct dpipe_ctx *ctx)
+static void dpipe_ctx_fini(struct dpipe_ctx *ctx)
 {
        struct dpipe_header *header, *tmp;
 
@@ -2916,6 +2955,7 @@ static void dpipe_ctx_clear(struct dpipe_ctx *ctx)
                dpipe_header_clear(header);
                dpipe_header_free(header);
        }
+       dpipe_tables_free(ctx->tables);
 }
 
 static const char *dpipe_header_id2s(struct dpipe_ctx *ctx,
@@ -3171,7 +3211,7 @@ static int cmd_dpipe_header_cb(const struct nlmsghdr *nlh, void *data)
 static int cmd_dpipe_headers_show(struct dl *dl)
 {
        struct nlmsghdr *nlh;
-       struct dpipe_ctx *ctx;
+       struct dpipe_ctx ctx = {};
        uint16_t flags = NLM_F_REQUEST | NLM_F_ACK;
        int err;
 
@@ -3181,20 +3221,19 @@ static int cmd_dpipe_headers_show(struct dl *dl)
        if (err)
                return err;
 
-       ctx = dpipe_ctx_alloc(dl);
-       if (!ctx)
-               return -ENOMEM;
+       err = dpipe_ctx_init(&ctx, dl);
+       if (err)
+               return err;
 
-       ctx->print_headers = true;
+       ctx.print_headers = true;
 
        pr_out_section_start(dl, "header");
-       err = _mnlg_socket_sndrcv(dl->nlg, nlh, cmd_dpipe_header_cb, ctx);
+       err = _mnlg_socket_sndrcv(dl->nlg, nlh, cmd_dpipe_header_cb, &ctx);
        if (err)
-               pr_err("error get headers %s\n", strerror(ctx->err));
+               pr_err("error get headers %s\n", strerror(ctx.err));
        pr_out_section_end(dl);
 
-       dpipe_ctx_clear(ctx);
-       dpipe_ctx_free(ctx);
+       dpipe_ctx_fini(&ctx);
        return err;
 }
 
@@ -3451,8 +3490,10 @@ resource_path_print(struct dl *dl, struct resources *resources,
 static int dpipe_table_show(struct dpipe_ctx *ctx, struct nlattr *nl)
 {
        struct nlattr *nla_table[DEVLINK_ATTR_MAX + 1] = {};
+       struct dpipe_table *table;
+       uint32_t resource_units;
        bool counters_enabled;
-       const char *name;
+       bool resource_valid;
        uint32_t size;
        int err;
 
@@ -3468,15 +3509,36 @@ static int dpipe_table_show(struct dpipe_ctx *ctx, struct nlattr *nl)
                return -EINVAL;
        }
 
-       name = mnl_attr_get_str(nla_table[DEVLINK_ATTR_DPIPE_TABLE_NAME]);
+       table = dpipe_table_alloc();
+       if (!table)
+               return -ENOMEM;
+
+       table->name = strdup(mnl_attr_get_str(nla_table[DEVLINK_ATTR_DPIPE_TABLE_NAME]));
        size = mnl_attr_get_u32(nla_table[DEVLINK_ATTR_DPIPE_TABLE_SIZE]);
        counters_enabled = !!mnl_attr_get_u8(nla_table[DEVLINK_ATTR_DPIPE_TABLE_COUNTERS_ENABLED]);
 
-       pr_out_str(ctx->dl, "name", name);
+       resource_valid = !!nla_table[DEVLINK_ATTR_DPIPE_TABLE_RESOURCE_ID];
+       if (resource_valid) {
+               table->resource_id = mnl_attr_get_u64(nla_table[DEVLINK_ATTR_DPIPE_TABLE_RESOURCE_ID]);
+               table->resource_valid = true;
+       }
+
+       list_add_tail(&table->list, &ctx->tables->table_list);
+       if (!ctx->print_tables)
+               return 0;
+
+       pr_out_str(ctx->dl, "name", table->name);
        pr_out_uint(ctx->dl, "size", size);
        pr_out_str(ctx->dl, "counters_enabled",
                   counters_enabled ? "true" : "false");
 
+       if (resource_valid) {
+               resource_units = mnl_attr_get_u32(nla_table[DEVLINK_ATTR_DPIPE_TABLE_RESOURCE_UNITS]);
+               resource_path_print(ctx->dl, ctx->resources,
+                                   table->resource_id);
+               pr_out_uint(ctx->dl, "resource_units", resource_units);
+       }
+
        pr_out_array_start(ctx->dl, "match");
        if (dpipe_table_matches_show(ctx, nla_table[DEVLINK_ATTR_DPIPE_TABLE_MATCHES]))
                goto err_matches_show;
@@ -3501,15 +3563,18 @@ static int dpipe_tables_show(struct dpipe_ctx *ctx, struct nlattr **tb)
        struct nlattr *nla_table;
 
        mnl_attr_for_each_nested(nla_table, nla_tables) {
-               pr_out_handle_start_arr(ctx->dl, tb);
+               if (ctx->print_tables)
+                       pr_out_handle_start_arr(ctx->dl, tb);
                if (dpipe_table_show(ctx, nla_table))
                        goto err_table_show;
-               pr_out_handle_end(ctx->dl);
+               if (ctx->print_tables)
+                       pr_out_handle_end(ctx->dl);
        }
        return 0;
 
 err_table_show:
-       pr_out_handle_end(ctx->dl);
+       if (ctx->print_tables)
+               pr_out_handle_end(ctx->dl);
        return -EINVAL;
 }
 
@@ -3529,39 +3594,68 @@ static int cmd_dpipe_table_show_cb(const struct nlmsghdr *nlh, void *data)
        return MNL_CB_OK;
 }
 
+static int cmd_resource_dump_cb(const struct nlmsghdr *nlh, void *data);
+
 static int cmd_dpipe_table_show(struct dl *dl)
 {
        struct nlmsghdr *nlh;
-       struct dpipe_ctx *ctx;
+       struct dpipe_ctx dpipe_ctx = {};
+       struct resource_ctx resource_ctx = {};
        uint16_t flags = NLM_F_REQUEST;
        int err;
 
-       ctx = dpipe_ctx_alloc(dl);
-       if (!ctx)
-               return -ENOMEM;
-
        err = dl_argv_parse(dl, DL_OPT_HANDLE, DL_OPT_DPIPE_TABLE_NAME);
        if (err)
-               goto out;
+               return err;
 
        nlh = mnlg_msg_prepare(dl->nlg, DEVLINK_CMD_DPIPE_HEADERS_GET, flags);
+
+       err = dpipe_ctx_init(&dpipe_ctx, dl);
+       if (err)
+               return err;
+
+       dpipe_ctx.print_tables = true;
+
        dl_opts_put(nlh, dl);
-       err = _mnlg_socket_sndrcv(dl->nlg, nlh, cmd_dpipe_header_cb, ctx);
+       err = _mnlg_socket_sndrcv(dl->nlg, nlh, cmd_dpipe_header_cb,
+                                 &dpipe_ctx);
        if (err) {
-               pr_err("error get headers %s\n", strerror(ctx->err));
-               goto out;
+               pr_err("error get headers %s\n", strerror(dpipe_ctx.err));
+               goto err_headers_get;
+       }
+
+       err = resource_ctx_init(&resource_ctx, dl);
+       if (err)
+               goto err_resource_ctx_init;
+
+       resource_ctx.print_resources = false;
+       nlh = mnlg_msg_prepare(dl->nlg, DEVLINK_CMD_RESOURCE_DUMP, flags);
+       dl_opts_put(nlh, dl);
+       err = _mnlg_socket_sndrcv(dl->nlg, nlh, cmd_resource_dump_cb,
+                                 &resource_ctx);
+       if (err) {
+               pr_err("error get resources %s\n", strerror(resource_ctx.err));
+               goto err_resource_dump;
        }
 
+       dpipe_ctx.resources = resource_ctx.resources;
        flags = NLM_F_REQUEST | NLM_F_ACK;
        nlh = mnlg_msg_prepare(dl->nlg, DEVLINK_CMD_DPIPE_TABLE_GET, flags);
        dl_opts_put(nlh, dl);
 
        pr_out_section_start(dl, "table");
-       _mnlg_socket_sndrcv(dl->nlg, nlh, cmd_dpipe_table_show_cb, ctx);
+       _mnlg_socket_sndrcv(dl->nlg, nlh, cmd_dpipe_table_show_cb, &dpipe_ctx);
        pr_out_section_end(dl);
-out:
-       dpipe_ctx_clear(ctx);
-       dpipe_ctx_free(ctx);
+
+       resource_ctx_fini(&resource_ctx);
+       dpipe_ctx_fini(&dpipe_ctx);
+       return 0;
+
+err_resource_dump:
+       resource_ctx_fini(&resource_ctx);
+err_resource_ctx_init:
+err_headers_get:
+       dpipe_ctx_fini(&dpipe_ctx);
        return err;
 }
 
@@ -3929,13 +4023,13 @@ static int cmd_dpipe_table_entry_dump_cb(const struct nlmsghdr *nlh, void *data)
 static int cmd_dpipe_table_dump(struct dl *dl)
 {
        struct nlmsghdr *nlh;
-       struct dpipe_ctx *ctx;
+       struct dpipe_ctx ctx = {};
        uint16_t flags = NLM_F_REQUEST;
        int err;
 
-       ctx = dpipe_ctx_alloc(dl);
-       if (!ctx)
-               return -ENOMEM;
+       err = dpipe_ctx_init(&ctx, dl);
+       if (err)
+               return err;
 
        err = dl_argv_parse(dl, DL_OPT_HANDLE | DL_OPT_DPIPE_TABLE_NAME, 0);
        if (err)
@@ -3943,9 +4037,9 @@ static int cmd_dpipe_table_dump(struct dl *dl)
 
        nlh = mnlg_msg_prepare(dl->nlg, DEVLINK_CMD_DPIPE_HEADERS_GET, flags);
        dl_opts_put(nlh, dl);
-       err = _mnlg_socket_sndrcv(dl->nlg, nlh, cmd_dpipe_header_cb, ctx);
+       err = _mnlg_socket_sndrcv(dl->nlg, nlh, cmd_dpipe_header_cb, &ctx);
        if (err) {
-               pr_err("error get headers %s\n", strerror(ctx->err));
+               pr_err("error get headers %s\n", strerror(ctx.err));
                goto out;
        }
 
@@ -3954,11 +4048,10 @@ static int cmd_dpipe_table_dump(struct dl *dl)
        dl_opts_put(nlh, dl);
 
        pr_out_section_start(dl, "table_entry");
-       _mnlg_socket_sndrcv(dl->nlg, nlh, cmd_dpipe_table_entry_dump_cb, ctx);
+       _mnlg_socket_sndrcv(dl->nlg, nlh, cmd_dpipe_table_entry_dump_cb, &ctx);
        pr_out_section_end(dl);
 out:
-       dpipe_ctx_clear(ctx);
-       dpipe_ctx_free(ctx);
+       dpipe_ctx_fini(&ctx);
        return err;
 }
 
@@ -4113,7 +4206,9 @@ static void resource_show(struct resource *resource,
                          struct resource_ctx *ctx)
 {
        struct resource *child_resource;
+       struct dpipe_table *table;
        struct dl *dl = ctx->dl;
+       bool array = false;
 
        pr_out_str(dl, "name", resource->name);
        if (dl->verbose)
@@ -4131,6 +4226,27 @@ static void resource_show(struct resource *resource,
                pr_out_uint(dl, "size_gran", resource->size_gran);
        }
 
+       list_for_each_entry(table, &ctx->tables->table_list, list)
+               if (table->resource_id == resource->id &&
+                   table->resource_valid)
+                       array = true;
+
+       if (array)
+               pr_out_array_start(dl, "dpipe_tables");
+       else
+               pr_out_str(dl, "dpipe_tables", "none");
+
+       list_for_each_entry(table, &ctx->tables->table_list, list) {
+               if (table->resource_id != resource->id ||
+                   !table->resource_valid)
+                       continue;
+               pr_out_entry_start(dl);
+               pr_out_str(dl, "table_name", table->name);
+               pr_out_entry_end(dl);
+       }
+       if (array)
+               pr_out_array_end(dl);
+
        if (list_empty(&resource->resource_list))
                return;
 
@@ -4191,25 +4307,45 @@ static int cmd_resource_dump_cb(const struct nlmsghdr *nlh, void *data)
 static int cmd_resource_show(struct dl *dl)
 {
        struct nlmsghdr *nlh;
-       struct resource_ctx ctx = {};
+       struct dpipe_ctx dpipe_ctx = {};
+       struct resource_ctx resource_ctx = {};
        int err;
 
-       nlh = mnlg_msg_prepare(dl->nlg, DEVLINK_CMD_RESOURCE_DUMP,
-                              NLM_F_REQUEST | NLM_F_ACK);
-
-       err = dl_argv_parse_put(nlh, dl, DL_OPT_HANDLE, 0);
+       err = dl_argv_parse(dl, DL_OPT_HANDLE, 0);
        if (err)
                return err;
 
-       err = resource_ctx_init(&ctx, dl);
+       nlh = mnlg_msg_prepare(dl->nlg, DEVLINK_CMD_DPIPE_TABLE_GET,
+                              NLM_F_REQUEST);
+       dl_opts_put(nlh, dl);
+
+       err = dpipe_ctx_init(&dpipe_ctx, dl);
        if (err)
                return err;
 
-       ctx.print_resources = true;
+       err = _mnlg_socket_sndrcv(dl->nlg, nlh, cmd_dpipe_table_show_cb,
+                                 &dpipe_ctx);
+       if (err) {
+               pr_err("error get tables %s\n", strerror(dpipe_ctx.err));
+               goto out;
+       }
+
+       err = resource_ctx_init(&resource_ctx, dl);
+       if (err)
+               goto out;
+
+       resource_ctx.print_resources = true;
+       resource_ctx.tables = dpipe_ctx.tables;
+       nlh = mnlg_msg_prepare(dl->nlg, DEVLINK_CMD_RESOURCE_DUMP,
+                              NLM_F_REQUEST | NLM_F_ACK);
+       dl_opts_put(nlh, dl);
        pr_out_section_start(dl, "resources");
-       err = _mnlg_socket_sndrcv(dl->nlg, nlh, cmd_resource_dump_cb, &ctx);
+       err = _mnlg_socket_sndrcv(dl->nlg, nlh, cmd_resource_dump_cb,
+                                 &resource_ctx);
        pr_out_section_end(dl);
-       resource_ctx_fini(&ctx);
+       resource_ctx_fini(&resource_ctx);
+out:
+       dpipe_ctx_fini(&dpipe_ctx);
        return err;
 }