diff mbox series

[iproute2-next,v2,3/5] devlink: introduce support for netns id for nested handle

Message ID 20230919115644.1157890-4-jiri@resnulli.us (mailing list archive)
State Changes Requested
Delegated to: David Ahern
Headers show
Series expose devlink instances relationships | expand

Checks

Context Check Description
netdev/tree_selection success Not a local patch

Commit Message

Jiri Pirko Sept. 19, 2023, 11:56 a.m. UTC
From: Jiri Pirko <jiri@nvidia.com>

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>
---
v1->v2:
- use previously introduced netns_netnsid_from_name() instead of code
  duplication for the same function.
- s/nesns_name_by_id_func/netns_name_by_id_func/
---
 devlink/devlink.c | 60 +++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 60 insertions(+)

Comments

David Ahern Sept. 19, 2023, 2:03 p.m. UTC | #1
On 9/19/23 5:56 AM, Jiri Pirko wrote:
> @@ -2723,6 +2725,40 @@ static bool should_arr_last_handle_end(struct dl *dl, const char *bus_name,
>  	       !cmp_arr_last_handle(dl, bus_name, dev_name);
>  }
>  
> +struct netns_name_by_id_ctx {
> +	int32_t id;
> +	char *name;
> +	struct rtnl_handle *rth;
> +};
> +
> +static int netns_name_by_id_func(char *nsname, void *arg)
> +{
> +	struct netns_name_by_id_ctx *ctx = arg;
> +	int32_t ret;
> +
> +	ret = netns_netnsid_from_name(ctx->rth, nsname);
> +	if (ret < 0 || ret != ctx->id)
> +		return 0;
> +	ctx->name = strdup(nsname);
> +	return 1;
> +}
> +
> +static char *netns_name_by_id(int32_t id)
> +{
> +	struct rtnl_handle rth;
> +	struct netns_name_by_id_ctx ctx = {
> +		.id = id,
> +		.rth = &rth,
> +	};
> +
> +	if (rtnl_open(&rth, 0) < 0)
> +		return NULL;
> +	netns_foreach(netns_name_by_id_func, &ctx);
> +	rtnl_close(&rth);
> +
> +	return ctx.name;
> +}
> +

The above is not devlink specific, so it should go in lib/namespace.c as
well.

Name wise it should be consistent with the last patch, so either
netns_id_to_name or netns_name_from_id based on the name from the
refactoring in patch 2.


>  static void pr_out_nested_handle(struct nlattr *nla_nested_dl)
>  {
>  	struct nlattr *tb[DEVLINK_ATTR_MAX + 1] = {};
> @@ -2740,6 +2776,30 @@ static void pr_out_nested_handle(struct nlattr *nla_nested_dl)
>  	sprintf(buf, "%s/%s", mnl_attr_get_str(tb[DEVLINK_ATTR_BUS_NAME]),
>  		mnl_attr_get_str(tb[DEVLINK_ATTR_DEV_NAME]));
>  	print_string(PRINT_ANY, "nested_devlink", " nested_devlink %s", buf);
> +
> +	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_by_id(id);
> +
> +			if (name) {
> +				print_string(PRINT_ANY,
> +					     "nested_devlink_netns",
> +					     " nested_devlink_netns %s", name);
> +				free(name);
> +			} else {
> +				print_int(PRINT_ANY,
> +					  "nested_devlink_netnsid",
> +					  " nested_devlink_netnsid %d", id);
> +			}
> +		} else {
> +			print_string(PRINT_FP, NULL,
> +				     " nested_devlink_netnsid %s", "unknown");
> +			print_int(PRINT_JSON,
> +				  "nested_devlink_netnsid", NULL, id);
> +		}

Also, devlink in the name here provides no addititional value (devlink
is the command name) and why add 'nested'? The attribute is just
NETNS_ID, so why not just 'netnsid' here.


> +	}
>  }
>  
>  static void __pr_out_handle_start(struct dl *dl, struct nlattr **tb,
Jiri Pirko Sept. 19, 2023, 5:19 p.m. UTC | #2
Tue, Sep 19, 2023 at 04:03:27PM CEST, dsahern@gmail.com wrote:
>On 9/19/23 5:56 AM, Jiri Pirko wrote:
>> @@ -2723,6 +2725,40 @@ static bool should_arr_last_handle_end(struct dl *dl, const char *bus_name,
>>  	       !cmp_arr_last_handle(dl, bus_name, dev_name);
>>  }
>>  
>> +struct netns_name_by_id_ctx {
>> +	int32_t id;
>> +	char *name;
>> +	struct rtnl_handle *rth;
>> +};
>> +
>> +static int netns_name_by_id_func(char *nsname, void *arg)
>> +{
>> +	struct netns_name_by_id_ctx *ctx = arg;
>> +	int32_t ret;
>> +
>> +	ret = netns_netnsid_from_name(ctx->rth, nsname);
>> +	if (ret < 0 || ret != ctx->id)
>> +		return 0;
>> +	ctx->name = strdup(nsname);
>> +	return 1;
>> +}
>> +
>> +static char *netns_name_by_id(int32_t id)
>> +{
>> +	struct rtnl_handle rth;
>> +	struct netns_name_by_id_ctx ctx = {
>> +		.id = id,
>> +		.rth = &rth,
>> +	};
>> +
>> +	if (rtnl_open(&rth, 0) < 0)
>> +		return NULL;
>> +	netns_foreach(netns_name_by_id_func, &ctx);
>> +	rtnl_close(&rth);
>> +
>> +	return ctx.name;
>> +}
>> +
>
>The above is not devlink specific, so it should go in lib/namespace.c as
>well.
>
>Name wise it should be consistent with the last patch, so either
>netns_id_to_name or netns_name_from_id based on the name from the
>refactoring in patch 2.

Okay.

>
>
>>  static void pr_out_nested_handle(struct nlattr *nla_nested_dl)
>>  {
>>  	struct nlattr *tb[DEVLINK_ATTR_MAX + 1] = {};
>> @@ -2740,6 +2776,30 @@ static void pr_out_nested_handle(struct nlattr *nla_nested_dl)
>>  	sprintf(buf, "%s/%s", mnl_attr_get_str(tb[DEVLINK_ATTR_BUS_NAME]),
>>  		mnl_attr_get_str(tb[DEVLINK_ATTR_DEV_NAME]));
>>  	print_string(PRINT_ANY, "nested_devlink", " nested_devlink %s", buf);
>> +
>> +	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_by_id(id);
>> +
>> +			if (name) {
>> +				print_string(PRINT_ANY,
>> +					     "nested_devlink_netns",
>> +					     " nested_devlink_netns %s", name);
>> +				free(name);
>> +			} else {
>> +				print_int(PRINT_ANY,
>> +					  "nested_devlink_netnsid",
>> +					  " nested_devlink_netnsid %d", id);
>> +			}
>> +		} else {
>> +			print_string(PRINT_FP, NULL,
>> +				     " nested_devlink_netnsid %s", "unknown");
>> +			print_int(PRINT_JSON,
>> +				  "nested_devlink_netnsid", NULL, id);
>> +		}
>
>Also, devlink in the name here provides no addititional value (devlink
>is the command name) and why add 'nested'? The attribute is just
>NETNS_ID, so why not just 'netnsid' here.

Well, it is a netnsid of the nested devlink instance, not the object
(e.g. port) itself. Omitting that would be misleading. Any idea how to
do this differently?


>
>
>> +	}
>>  }
>>  
>>  static void __pr_out_handle_start(struct dl *dl, struct nlattr **tb,
>
David Ahern Sept. 19, 2023, 6:48 p.m. UTC | #3
On 9/19/23 11:19 AM, Jiri Pirko wrote:
>>
>>>  static void pr_out_nested_handle(struct nlattr *nla_nested_dl)
>>>  {
>>>  	struct nlattr *tb[DEVLINK_ATTR_MAX + 1] = {};
>>> @@ -2740,6 +2776,30 @@ static void pr_out_nested_handle(struct nlattr *nla_nested_dl)
>>>  	sprintf(buf, "%s/%s", mnl_attr_get_str(tb[DEVLINK_ATTR_BUS_NAME]),
>>>  		mnl_attr_get_str(tb[DEVLINK_ATTR_DEV_NAME]));
>>>  	print_string(PRINT_ANY, "nested_devlink", " nested_devlink %s", buf);
>>> +
>>> +	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_by_id(id);
>>> +
>>> +			if (name) {
>>> +				print_string(PRINT_ANY,
>>> +					     "nested_devlink_netns",
>>> +					     " nested_devlink_netns %s", name);
>>> +				free(name);
>>> +			} else {
>>> +				print_int(PRINT_ANY,
>>> +					  "nested_devlink_netnsid",
>>> +					  " nested_devlink_netnsid %d", id);
>>> +			}
>>> +		} else {
>>> +			print_string(PRINT_FP, NULL,
>>> +				     " nested_devlink_netnsid %s", "unknown");
>>> +			print_int(PRINT_JSON,
>>> +				  "nested_devlink_netnsid", NULL, id);
>>> +		}
>> Also, devlink in the name here provides no addititional value (devlink
>> is the command name) and why add 'nested'? The attribute is just
>> NETNS_ID, so why not just 'netnsid' here.
> Well, it is a netnsid of the nested devlink instance, not the object
> (e.g. port) itself. Omitting that would be misleading. Any idea how to
> do this differently?
> 
> 

The attribute is a namespace id, and the value is a namespace id. Given
that, the name here should be netnsid (or nsid - we did a horrible job
with consistency across iproute2 commands). I have not followed the
kernel patches to understand what you mean by nested devlink instance.
Jiri Pirko Sept. 20, 2023, 7:30 a.m. UTC | #4
Tue, Sep 19, 2023 at 08:48:29PM CEST, dsahern@gmail.com wrote:
>On 9/19/23 11:19 AM, Jiri Pirko wrote:
>>>
>>>>  static void pr_out_nested_handle(struct nlattr *nla_nested_dl)
>>>>  {
>>>>  	struct nlattr *tb[DEVLINK_ATTR_MAX + 1] = {};
>>>> @@ -2740,6 +2776,30 @@ static void pr_out_nested_handle(struct nlattr *nla_nested_dl)
>>>>  	sprintf(buf, "%s/%s", mnl_attr_get_str(tb[DEVLINK_ATTR_BUS_NAME]),
>>>>  		mnl_attr_get_str(tb[DEVLINK_ATTR_DEV_NAME]));
>>>>  	print_string(PRINT_ANY, "nested_devlink", " nested_devlink %s", buf);
>>>> +
>>>> +	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_by_id(id);
>>>> +
>>>> +			if (name) {
>>>> +				print_string(PRINT_ANY,
>>>> +					     "nested_devlink_netns",
>>>> +					     " nested_devlink_netns %s", name);
>>>> +				free(name);
>>>> +			} else {
>>>> +				print_int(PRINT_ANY,
>>>> +					  "nested_devlink_netnsid",
>>>> +					  " nested_devlink_netnsid %d", id);
>>>> +			}
>>>> +		} else {
>>>> +			print_string(PRINT_FP, NULL,
>>>> +				     " nested_devlink_netnsid %s", "unknown");
>>>> +			print_int(PRINT_JSON,
>>>> +				  "nested_devlink_netnsid", NULL, id);
>>>> +		}
>>> Also, devlink in the name here provides no addititional value (devlink
>>> is the command name) and why add 'nested'? The attribute is just
>>> NETNS_ID, so why not just 'netnsid' here.
>> Well, it is a netnsid of the nested devlink instance, not the object
>> (e.g. port) itself. Omitting that would be misleading. Any idea how to
>> do this differently?
>> 
>> 
>
>The attribute is a namespace id, and the value is a namespace id. Given
>that, the name here should be netnsid (or nsid - we did a horrible job
>with consistency across iproute2 commands). I have not followed the
>kernel patches to understand what you mean by nested devlink instance.

Please do that. Again, the netnsid is related to the nested instance.
Therefore I put the "nested_devlink" in the name. Putting just "netnsid"
as you suggest is wrong. Another possibility would be do nest this into
object, but:
1) I didn't find nice way to do that
2) We would break linecards as they expose nested_devlink already

IDK :/
Jiri Pirko Sept. 29, 2023, 11:30 a.m. UTC | #5
Wed, Sep 20, 2023 at 09:30:01AM CEST, jiri@resnulli.us wrote:
>Tue, Sep 19, 2023 at 08:48:29PM CEST, dsahern@gmail.com wrote:
>>On 9/19/23 11:19 AM, Jiri Pirko wrote:
>>>>
>>>>>  static void pr_out_nested_handle(struct nlattr *nla_nested_dl)
>>>>>  {
>>>>>  	struct nlattr *tb[DEVLINK_ATTR_MAX + 1] = {};
>>>>> @@ -2740,6 +2776,30 @@ static void pr_out_nested_handle(struct nlattr *nla_nested_dl)
>>>>>  	sprintf(buf, "%s/%s", mnl_attr_get_str(tb[DEVLINK_ATTR_BUS_NAME]),
>>>>>  		mnl_attr_get_str(tb[DEVLINK_ATTR_DEV_NAME]));
>>>>>  	print_string(PRINT_ANY, "nested_devlink", " nested_devlink %s", buf);
>>>>> +
>>>>> +	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_by_id(id);
>>>>> +
>>>>> +			if (name) {
>>>>> +				print_string(PRINT_ANY,
>>>>> +					     "nested_devlink_netns",
>>>>> +					     " nested_devlink_netns %s", name);
>>>>> +				free(name);
>>>>> +			} else {
>>>>> +				print_int(PRINT_ANY,
>>>>> +					  "nested_devlink_netnsid",
>>>>> +					  " nested_devlink_netnsid %d", id);
>>>>> +			}
>>>>> +		} else {
>>>>> +			print_string(PRINT_FP, NULL,
>>>>> +				     " nested_devlink_netnsid %s", "unknown");
>>>>> +			print_int(PRINT_JSON,
>>>>> +				  "nested_devlink_netnsid", NULL, id);
>>>>> +		}
>>>> Also, devlink in the name here provides no addititional value (devlink
>>>> is the command name) and why add 'nested'? The attribute is just
>>>> NETNS_ID, so why not just 'netnsid' here.
>>> Well, it is a netnsid of the nested devlink instance, not the object
>>> (e.g. port) itself. Omitting that would be misleading. Any idea how to
>>> do this differently?
>>> 
>>> 
>>
>>The attribute is a namespace id, and the value is a namespace id. Given
>>that, the name here should be netnsid (or nsid - we did a horrible job
>>with consistency across iproute2 commands). I have not followed the
>>kernel patches to understand what you mean by nested devlink instance.
>
>Please do that. Again, the netnsid is related to the nested instance.
>Therefore I put the "nested_devlink" in the name. Putting just "netnsid"
>as you suggest is wrong. Another possibility would be do nest this into
>object, but:
>1) I didn't find nice way to do that
>2) We would break linecards as they expose nested_devlink already

Did you have a chance to check this? I have v3 ready for submission with
the other changes you requested.

Thanks!


>
>IDK :/
David Ahern Oct. 3, 2023, 4:37 p.m. UTC | #6
On 9/29/23 5:30 AM, Jiri Pirko wrote:
>>> The attribute is a namespace id, and the value is a namespace id. Given
>>> that, the name here should be netnsid (or nsid - we did a horrible job
>>> with consistency across iproute2 commands). I have not followed the
>>> kernel patches to understand what you mean by nested devlink instance.
>>
>> Please do that. Again, the netnsid is related to the nested instance.
>> Therefore I put the "nested_devlink" in the name. Putting just "netnsid"
>> as you suggest is wrong. Another possibility would be do nest this into
>> object, but:
>> 1) I didn't find nice way to do that
>> 2) We would break linecards as they expose nested_devlink already

well, that just shows I make mistakes as a reviewer. These really long
command lines are really taxing.
Jiri Pirko Oct. 3, 2023, 5:17 p.m. UTC | #7
Tue, Oct 03, 2023 at 06:37:31PM CEST, dsahern@gmail.com wrote:
>On 9/29/23 5:30 AM, Jiri Pirko wrote:
>>>> The attribute is a namespace id, and the value is a namespace id. Given
>>>> that, the name here should be netnsid (or nsid - we did a horrible job
>>>> with consistency across iproute2 commands). I have not followed the
>>>> kernel patches to understand what you mean by nested devlink instance.
>>>
>>> Please do that. Again, the netnsid is related to the nested instance.
>>> Therefore I put the "nested_devlink" in the name. Putting just "netnsid"
>>> as you suggest is wrong. Another possibility would be do nest this into
>>> object, but:
>>> 1) I didn't find nice way to do that
>>> 2) We would break linecards as they expose nested_devlink already
>
>well, that just shows I make mistakes as a reviewer. These really long
>command lines are really taxing.

So what do you suggest?
David Ahern Oct. 4, 2023, 3:20 p.m. UTC | #8
On 10/3/23 11:17 AM, Jiri Pirko wrote:
> Tue, Oct 03, 2023 at 06:37:31PM CEST, dsahern@gmail.com wrote:
>> On 9/29/23 5:30 AM, Jiri Pirko wrote:
>>>>> The attribute is a namespace id, and the value is a namespace id. Given
>>>>> that, the name here should be netnsid (or nsid - we did a horrible job
>>>>> with consistency across iproute2 commands). I have not followed the
>>>>> kernel patches to understand what you mean by nested devlink instance.
>>>>
>>>> Please do that. Again, the netnsid is related to the nested instance.
>>>> Therefore I put the "nested_devlink" in the name. Putting just "netnsid"
>>>> as you suggest is wrong. Another possibility would be do nest this into
>>>> object, but:
>>>> 1) I didn't find nice way to do that
>>>> 2) We would break linecards as they expose nested_devlink already
>>
>> well, that just shows I make mistakes as a reviewer. These really long
>> command lines are really taxing.
> 
> So what do you suggest?

That you learn how to make up shorter names, leveraging established
abbreviations for example. This one new parameter is 22 chars. How do
you expect these command lines and responses to fit on a reasonable
width terminal? I have been saying this now for many years about devlink
commands - excessively long attribute names combined with duplicate
terms in a command line. Not user friendly.
Jiri Pirko Oct. 5, 2023, 7:22 a.m. UTC | #9
Wed, Oct 04, 2023 at 05:20:46PM CEST, dsahern@gmail.com wrote:
>On 10/3/23 11:17 AM, Jiri Pirko wrote:
>> Tue, Oct 03, 2023 at 06:37:31PM CEST, dsahern@gmail.com wrote:
>>> On 9/29/23 5:30 AM, Jiri Pirko wrote:
>>>>>> The attribute is a namespace id, and the value is a namespace id. Given
>>>>>> that, the name here should be netnsid (or nsid - we did a horrible job
>>>>>> with consistency across iproute2 commands). I have not followed the
>>>>>> kernel patches to understand what you mean by nested devlink instance.
>>>>>
>>>>> Please do that. Again, the netnsid is related to the nested instance.
>>>>> Therefore I put the "nested_devlink" in the name. Putting just "netnsid"
>>>>> as you suggest is wrong. Another possibility would be do nest this into
>>>>> object, but:
>>>>> 1) I didn't find nice way to do that
>>>>> 2) We would break linecards as they expose nested_devlink already
>>>
>>> well, that just shows I make mistakes as a reviewer. These really long
>>> command lines are really taxing.
>> 
>> So what do you suggest?
>
>That you learn how to make up shorter names, leveraging established
>abbreviations for example. This one new parameter is 22 chars. How do
>you expect these command lines and responses to fit on a reasonable
>width terminal? I have been saying this now for many years about devlink
>commands - excessively long attribute names combined with duplicate
>terms in a command line. Not user friendly.

The problem is not the length, the problem is how to group nested
devlink handle and netnsid. Anyway..
diff mbox series

Patch

diff --git a/devlink/devlink.c b/devlink/devlink.c
index d1795f616ca0..cf5d466bfc9d 100644
--- a/devlink/devlink.c
+++ b/devlink/devlink.c
@@ -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
@@ -2723,6 +2725,40 @@  static bool should_arr_last_handle_end(struct dl *dl, const char *bus_name,
 	       !cmp_arr_last_handle(dl, bus_name, dev_name);
 }
 
+struct netns_name_by_id_ctx {
+	int32_t id;
+	char *name;
+	struct rtnl_handle *rth;
+};
+
+static int netns_name_by_id_func(char *nsname, void *arg)
+{
+	struct netns_name_by_id_ctx *ctx = arg;
+	int32_t ret;
+
+	ret = netns_netnsid_from_name(ctx->rth, nsname);
+	if (ret < 0 || ret != ctx->id)
+		return 0;
+	ctx->name = strdup(nsname);
+	return 1;
+}
+
+static char *netns_name_by_id(int32_t id)
+{
+	struct rtnl_handle rth;
+	struct netns_name_by_id_ctx ctx = {
+		.id = id,
+		.rth = &rth,
+	};
+
+	if (rtnl_open(&rth, 0) < 0)
+		return NULL;
+	netns_foreach(netns_name_by_id_func, &ctx);
+	rtnl_close(&rth);
+
+	return ctx.name;
+}
+
 static void pr_out_nested_handle(struct nlattr *nla_nested_dl)
 {
 	struct nlattr *tb[DEVLINK_ATTR_MAX + 1] = {};
@@ -2740,6 +2776,30 @@  static void pr_out_nested_handle(struct nlattr *nla_nested_dl)
 	sprintf(buf, "%s/%s", mnl_attr_get_str(tb[DEVLINK_ATTR_BUS_NAME]),
 		mnl_attr_get_str(tb[DEVLINK_ATTR_DEV_NAME]));
 	print_string(PRINT_ANY, "nested_devlink", " nested_devlink %s", buf);
+
+	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_by_id(id);
+
+			if (name) {
+				print_string(PRINT_ANY,
+					     "nested_devlink_netns",
+					     " nested_devlink_netns %s", name);
+				free(name);
+			} else {
+				print_int(PRINT_ANY,
+					  "nested_devlink_netnsid",
+					  " nested_devlink_netnsid %d", id);
+			}
+		} else {
+			print_string(PRINT_FP, NULL,
+				     " nested_devlink_netnsid %s", "unknown");
+			print_int(PRINT_JSON,
+				  "nested_devlink_netnsid", NULL, id);
+		}
+	}
 }
 
 static void __pr_out_handle_start(struct dl *dl, struct nlattr **tb,