]> git.ipfire.org Git - thirdparty/iproute2.git/commitdiff
devlink: introduce support for netns id for nested handle
authorJiri Pirko <jiri@nvidia.com>
Tue, 7 Nov 2023 08:06:05 +0000 (09:06 +0100)
committerDavid Ahern <dsahern@kernel.org>
Sat, 11 Nov 2023 17:31:29 +0000 (17:31 +0000)
Nested handle may contain DEVLINK_ATTR_NETNS_ID attribute that indicates
the network namespace where the nested devlink instance resides. Process
this converting to netns name if possible and print to user.

Signed-off-by: Jiri Pirko <jiri@nvidia.com>
Signed-off-by: David Ahern <dsahern@kernel.org>
devlink/devlink.c
include/namespace.h
lib/namespace.c

index f06f3069e80a9f3a3bbec8a181b04fdad107c649..f276026b9ba7edf22b1ce2808a5a2212a4bcf911 100644 (file)
@@ -24,6 +24,7 @@
 #include <linux/genetlink.h>
 #include <linux/devlink.h>
 #include <linux/netlink.h>
+#include <linux/net_namespace.h>
 #include <libmnl/libmnl.h>
 #include <netinet/ether.h>
 #include <sys/select.h>
@@ -722,6 +723,7 @@ static const enum mnl_attr_data_type devlink_policy[DEVLINK_ATTR_MAX + 1] = {
        [DEVLINK_ATTR_LINECARD_SUPPORTED_TYPES] = MNL_TYPE_NESTED,
        [DEVLINK_ATTR_NESTED_DEVLINK] = MNL_TYPE_NESTED,
        [DEVLINK_ATTR_SELFTESTS] = MNL_TYPE_NESTED,
+       [DEVLINK_ATTR_NETNS_ID] = MNL_TYPE_U32,
 };
 
 static const enum mnl_attr_data_type
@@ -2866,7 +2868,26 @@ static void __pr_out_nested_handle(struct dl *dl, struct nlattr *nla_nested_dl,
                return;
        }
 
-       __pr_out_handle_start(dl, tb, false, false);
+       __pr_out_handle_start(dl, tb, tb[DEVLINK_ATTR_NETNS_ID], false);
+       if (tb[DEVLINK_ATTR_NETNS_ID]) {
+               int32_t id = mnl_attr_get_u32(tb[DEVLINK_ATTR_NETNS_ID]);
+
+               if (id >= 0) {
+                       char *name = netns_name_from_id(id);
+
+                       if (name) {
+                               print_string(PRINT_ANY, "netns",
+                                            " netns %s", name);
+                               free(name);
+                       } else {
+                               print_int(PRINT_ANY, "netnsid",
+                                         " netnsid %d", id);
+                       }
+               } else {
+                       print_string(PRINT_FP, NULL, " netnsid %s", "unknown");
+                       print_int(PRINT_JSON, "netnsid", NULL, id);
+               }
+       }
        pr_out_handle_end(dl);
 }
 
index 2843f4bb5742b1d2b1c09fce43bccb8da876304b..86000543f99f51599cea410b5e9ac45908107682 100644 (file)
@@ -60,5 +60,6 @@ struct netns_func {
 };
 
 int netns_id_from_name(struct rtnl_handle *rtnl, const char *name);
+char *netns_name_from_id(int32_t id);
 
 #endif /* __NAMESPACE_H__ */
index f03f4bbabcebc390f909475b918606fdcaf27ec8..d3aeb9658e732c8a74a31060a4084cc6c1e0aa19 100644 (file)
@@ -188,3 +188,37 @@ out:
        free(answer);
        return ret;
 }
+
+struct netns_name_from_id_ctx {
+       int32_t id;
+       char *name;
+       struct rtnl_handle *rth;
+};
+
+static int netns_name_from_id_func(char *nsname, void *arg)
+{
+       struct netns_name_from_id_ctx *ctx = arg;
+       int32_t ret;
+
+       ret = netns_id_from_name(ctx->rth, nsname);
+       if (ret < 0 || ret != ctx->id)
+               return 0;
+       ctx->name = strdup(nsname);
+       return 1;
+}
+
+char *netns_name_from_id(int32_t id)
+{
+       struct rtnl_handle rth;
+       struct netns_name_from_id_ctx ctx = {
+               .id = id,
+               .rth = &rth,
+       };
+
+       if (rtnl_open(&rth, 0) < 0)
+               return NULL;
+       netns_foreach(netns_name_from_id_func, &ctx);
+       rtnl_close(&rth);
+
+       return ctx.name;
+}