All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH iproute2-next 1/2] include: update linux/rtnetlink.h
@ 2015-04-09  8:30 Nicolas Dichtel
  2015-04-09  8:30 ` [PATCH iproute2-next 2/2] netns: allow to dump and monitor nsid Nicolas Dichtel
                   ` (2 more replies)
  0 siblings, 3 replies; 9+ messages in thread
From: Nicolas Dichtel @ 2015-04-09  8:30 UTC (permalink / raw)
  To: shemminger; +Cc: netdev, Nicolas Dichtel

Signed-off-by: Nicolas Dichtel <nicolas.dichtel@6wind.com>
---
 include/linux/rtnetlink.h | 4 ++++
 1 file changed, 4 insertions(+)

diff --git a/include/linux/rtnetlink.h b/include/linux/rtnetlink.h
index 28650a31d77f..702b19b4207e 100644
--- a/include/linux/rtnetlink.h
+++ b/include/linux/rtnetlink.h
@@ -134,6 +134,8 @@ enum {
 
 	RTM_NEWNSID = 88,
 #define RTM_NEWNSID RTM_NEWNSID
+	RTM_DELNSID = 89,
+#define RTM_DELNSID RTM_DELNSID
 	RTM_GETNSID = 90,
 #define RTM_GETNSID RTM_GETNSID
 
@@ -633,6 +635,8 @@ enum rtnetlink_groups {
 #define RTNLGRP_MDB		RTNLGRP_MDB
 	RTNLGRP_MPLS_ROUTE,
 #define RTNLGRP_MPLS_ROUTE	RTNLGRP_MPLS_ROUTE
+	RTNLGRP_NSID,
+#define RTNLGRP_NSID		RTNLGRP_NSID
 	__RTNLGRP_MAX
 };
 #define RTNLGRP_MAX	(__RTNLGRP_MAX - 1)
-- 
2.2.2

^ permalink raw reply related	[flat|nested] 9+ messages in thread

* [PATCH iproute2-next 2/2] netns: allow to dump and monitor nsid
  2015-04-09  8:30 [PATCH iproute2-next 1/2] include: update linux/rtnetlink.h Nicolas Dichtel
@ 2015-04-09  8:30 ` Nicolas Dichtel
  2015-04-09  8:36   ` Vadim Kochan
                     ` (2 more replies)
  2015-04-10 20:24 ` [PATCH iproute2-next 1/2] include: update linux/rtnetlink.h Stephen Hemminger
       [not found] ` <797e9129b12148228f163402c284dce6@HQ1WP-EXMB12.corp.brocade.com>
  2 siblings, 3 replies; 9+ messages in thread
From: Nicolas Dichtel @ 2015-04-09  8:30 UTC (permalink / raw)
  To: shemminger; +Cc: netdev, Nicolas Dichtel

Two commands are added:
 - ip netns list-id
 - ip monitor nsid

A cache is also added to remember the association between the iproute2 netns
name (from /var/run/netns/) and the nsid.
To avoid interfering with the rth socket, a new rtnl socket (rtnsh) is used to
get nsid (we may send rtnl request during listing on rth).

Example:
$ ip netns list-id
nsid 0 (iproute2 netns name: foo)
$ ip monitor nsid
Deleted nsid 0 (iproute2 netns name: foo)
nsid 16 (iproute2 netns name: bar)

Signed-off-by: Nicolas Dichtel <nicolas.dichtel@6wind.com>
---
 include/ll_map.h      |   1 +
 ip/ip_common.h        |   3 +
 ip/ipmonitor.c        |  17 ++++-
 ip/ipnetns.c          | 201 +++++++++++++++++++++++++++++++++++++++++++++++++-
 lib/ll_map.c          |   2 +-
 man/man8/ip-monitor.8 |   2 +-
 man/man8/ip-netns.8   |  10 +++
 7 files changed, 232 insertions(+), 4 deletions(-)

diff --git a/include/ll_map.h b/include/ll_map.h
index 4c78498e7e1e..b98a5714592e 100644
--- a/include/ll_map.h
+++ b/include/ll_map.h
@@ -10,5 +10,6 @@ extern const char *ll_index_to_name(unsigned idx);
 extern const char *ll_idx_n2a(unsigned idx, char *buf);
 extern int ll_index_to_type(unsigned idx);
 extern int ll_index_to_flags(unsigned idx);
+extern unsigned namehash(const char *str);
 
 #endif /* __LL_MAP_H__ */
diff --git a/ip/ip_common.h b/ip/ip_common.h
index 89a495ea1074..b082734d9e0c 100644
--- a/ip/ip_common.h
+++ b/ip/ip_common.h
@@ -34,6 +34,9 @@ extern int print_rule(const struct sockaddr_nl *who,
 		      struct nlmsghdr *n, void *arg);
 extern int print_netconf(const struct sockaddr_nl *who,
 			 struct nlmsghdr *n, void *arg);
+extern void netns_map_init(void);
+extern int print_nsid(const struct sockaddr_nl *who,
+		      struct nlmsghdr *n, void *arg);
 extern int do_ipaddr(int argc, char **argv);
 extern int do_ipaddrlabel(int argc, char **argv);
 extern int do_iproute(int argc, char **argv);
diff --git a/ip/ipmonitor.c b/ip/ipmonitor.c
index 7833a2632927..1205ee1c7039 100644
--- a/ip/ipmonitor.c
+++ b/ip/ipmonitor.c
@@ -32,7 +32,7 @@ static void usage(void)
 	fprintf(stderr, "Usage: ip monitor [ all | LISTofOBJECTS ] [ FILE ]"
 			"[ label ] [dev DEVICE]\n");
 	fprintf(stderr, "LISTofOBJECTS := link | address | route | mroute | prefix |\n");
-	fprintf(stderr, "                 neigh | netconf | rule\n");
+	fprintf(stderr, "                 neigh | netconf | rule | nsid\n");
 	fprintf(stderr, "FILE := file FILENAME\n");
 	exit(-1);
 }
@@ -129,6 +129,12 @@ static int accept_msg(const struct sockaddr_nl *who,
 		print_nlmsg_timestamp(fp, n);
 		return 0;
 	}
+	if (n->nlmsg_type == RTM_NEWNSID || n->nlmsg_type == RTM_DELNSID) {
+		if (prefix_banner)
+			fprintf(fp, "[NSID]");
+		print_nsid(who, n, arg);
+		return 0;
+	}
 	if (n->nlmsg_type != NLMSG_ERROR && n->nlmsg_type != NLMSG_NOOP &&
 	    n->nlmsg_type != NLMSG_DONE) {
 		fprintf(fp, "Unknown message: type=0x%08x(%d) flags=0x%08x(%d)"
@@ -151,6 +157,7 @@ int do_ipmonitor(int argc, char **argv)
 	int lneigh=0;
 	int lnetconf=0;
 	int lrule=0;
+	int lnsid=0;
 	int ifindex=0;
 
 	groups |= nl_mgrp(RTNLGRP_LINK);
@@ -167,6 +174,7 @@ int do_ipmonitor(int argc, char **argv)
 	groups |= nl_mgrp(RTNLGRP_IPV6_NETCONF);
 	groups |= nl_mgrp(RTNLGRP_IPV4_RULE);
 	groups |= nl_mgrp(RTNLGRP_IPV6_RULE);
+	groups |= nl_mgrp(RTNLGRP_NSID);
 
 	rtnl_close(&rth);
 
@@ -200,6 +208,9 @@ int do_ipmonitor(int argc, char **argv)
 		} else if (matches(*argv, "rule") == 0) {
 			lrule = 1;
 			groups = 0;
+		} else if (matches(*argv, "nsid") == 0) {
+			lnsid = 1;
+			groups = 0;
 		} else if (strcmp(*argv, "all") == 0) {
 			prefix_banner=1;
 		} else if (matches(*argv, "help") == 0) {
@@ -264,6 +275,9 @@ int do_ipmonitor(int argc, char **argv)
 		if (!preferred_family || preferred_family == AF_INET6)
 			groups |= nl_mgrp(RTNLGRP_IPV6_RULE);
 	}
+	if (lnsid) {
+		groups |= nl_mgrp(RTNLGRP_NSID);
+	}
 	if (file) {
 		FILE *fp;
 		fp = fopen(file, "r");
@@ -277,6 +291,7 @@ int do_ipmonitor(int argc, char **argv)
 	if (rtnl_open(&rth, groups) < 0)
 		exit(1);
 	ll_init_map(&rth);
+	netns_map_init();
 
 	if (rtnl_listen(&rth, accept_msg, stdout) < 0)
 		exit(2);
diff --git a/ip/ipnetns.c b/ip/ipnetns.c
index 45e234a4d98c..7806335733cf 100644
--- a/ip/ipnetns.c
+++ b/ip/ipnetns.c
@@ -14,10 +14,12 @@
 #include <errno.h>
 #include <unistd.h>
 #include <ctype.h>
+#include <linux/limits.h>
 
 #include <linux/net_namespace.h>
 
 #include "utils.h"
+#include "hlist.h"
 #include "ip_common.h"
 #include "namespace.h"
 
@@ -31,9 +33,13 @@ static int usage(void)
 	fprintf(stderr, "       ip netns pids NAME\n");
 	fprintf(stderr, "       ip [-all] netns exec [NAME] cmd ...\n");
 	fprintf(stderr, "       ip netns monitor\n");
+	fprintf(stderr, "       ip netns list-id\n");
 	exit(-1);
 }
 
+/* This socket is used to get nsid */
+static struct rtnl_handle rtnsh = { .fd = -1 };
+
 #ifdef HAVE_NETNSID
 static int get_netnsid_from_name(const char *name)
 {
@@ -57,7 +63,7 @@ static int get_netnsid_from_name(const char *name)
 		return fd;
 
 	addattr32(&req.n, 1024, NETNSA_FD, fd);
-	if (rtnl_talk(&rth, &req.n, 0, 0, &answer.n) < 0) {
+	if (rtnl_talk(&rtnsh, &req.n, 0, 0, &answer.n) < 0) {
 		close(fd);
 		return -2;
 	}
@@ -86,6 +92,194 @@ static int get_netnsid_from_name(const char *name)
 }
 #endif /* HAVE_NETNSID */
 
+struct nsid_cache {
+	struct hlist_node	nsid_hash;
+	struct hlist_node	name_hash;
+	int			nsid;
+	char			name[NAME_MAX];
+};
+
+#define NSIDMAP_SIZE		128
+#define NSID_HASH_NSID(nsid)	(nsid & (NSIDMAP_SIZE - 1))
+#define NSID_HASH_NAME(name)	(namehash(name) & (NSIDMAP_SIZE - 1))
+
+static struct hlist_head	nsid_head[NSIDMAP_SIZE];
+static struct hlist_head	name_head[NSIDMAP_SIZE];
+
+static struct nsid_cache *netns_map_get_by_nsid(int nsid)
+{
+	uint32_t h = NSID_HASH_NSID(nsid);
+	struct hlist_node *n;
+
+	hlist_for_each(n, &nsid_head[h]) {
+		struct nsid_cache *c = container_of(n, struct nsid_cache,
+						    nsid_hash);
+		if (c->nsid == nsid)
+			return c;
+	}
+
+	return NULL;
+}
+
+static int netns_map_add(int nsid, char *name)
+{
+	struct nsid_cache *c;
+	uint32_t h;
+
+	if (netns_map_get_by_nsid(nsid) != NULL)
+		return -EEXIST;
+
+	c = malloc(sizeof(*c));
+	if (c == NULL) {
+		perror("malloc");
+		return -ENOMEM;
+	}
+	c->nsid = nsid;
+	strcpy(c->name, name);
+
+	h = NSID_HASH_NSID(nsid);
+	hlist_add_head(&c->nsid_hash, &nsid_head[h]);
+
+	h = NSID_HASH_NAME(name);
+	hlist_add_head(&c->name_hash, &name_head[h]);
+
+	return 0;
+}
+
+static void netns_map_del(struct nsid_cache *c)
+{
+	hlist_del(&c->name_hash);
+	hlist_del(&c->nsid_hash);
+	free(c);
+}
+
+void netns_map_init(void)
+{
+	static int initialized;
+	struct dirent *entry;
+	DIR *dir;
+	int nsid;
+
+	if (initialized)
+		return;
+
+	if (rtnl_open(&rtnsh, 0) < 0) {
+		fprintf(stderr, "Cannot open rtnetlink\n");
+		exit(1);
+	}
+
+	dir = opendir(NETNS_RUN_DIR);
+	if (!dir)
+		return;
+
+	while ((entry = readdir(dir)) != NULL) {
+		if (strcmp(entry->d_name, ".") == 0)
+			continue;
+		if (strcmp(entry->d_name, "..") == 0)
+			continue;
+		nsid = get_netnsid_from_name(entry->d_name);
+
+		if (nsid >= 0)
+			netns_map_add(nsid, entry->d_name);
+	}
+	closedir(dir);
+	initialized = 1;
+}
+
+static int netns_get_name(int nsid, char *name)
+{
+	struct dirent *entry;
+	DIR *dir;
+	int id;
+
+	dir = opendir(NETNS_RUN_DIR);
+	if (!dir)
+		return -ENOENT;
+
+	while ((entry = readdir(dir)) != NULL) {
+		if (strcmp(entry->d_name, ".") == 0)
+			continue;
+		if (strcmp(entry->d_name, "..") == 0)
+			continue;
+		id = get_netnsid_from_name(entry->d_name);
+
+		if (nsid == id) {
+			strcpy(name, entry->d_name);
+			closedir(dir);
+			return 0;
+		}
+	}
+	closedir(dir);
+	return -ENOENT;
+}
+
+int print_nsid(const struct sockaddr_nl *who, struct nlmsghdr *n, void *arg)
+{
+	struct rtgenmsg *rthdr = NLMSG_DATA(n);
+	struct rtattr *tb[NETNSA_MAX+1];
+	int len = n->nlmsg_len;
+	FILE *fp = (FILE*)arg;
+	struct nsid_cache *c;
+	char name[NAME_MAX];
+	int nsid;
+
+	if (n->nlmsg_type != RTM_NEWNSID && n->nlmsg_type != RTM_DELNSID)
+		return 0;
+
+	len -= NLMSG_SPACE(sizeof(*rthdr));
+	if (len < 0) {
+		fprintf(stderr, "BUG: wrong nlmsg len %d in %s\n", len,
+			__func__);
+		return -1;
+	}
+
+	parse_rtattr(tb, NETNSA_MAX, NETNS_RTA(rthdr), len);
+	if (tb[NETNSA_NSID] == NULL) {
+		fprintf(stderr, "BUG: NETNSA_NSID is missing %s\n", __func__);
+		return -1;
+	}
+
+	if (n->nlmsg_type == RTM_DELNSID)
+		fprintf(fp, "Deleted ");
+
+	nsid = rta_getattr_u32(tb[NETNSA_NSID]);
+	fprintf(fp, "nsid %u ", nsid);
+
+	c = netns_map_get_by_nsid(nsid);
+	if (c != NULL) {
+		fprintf(fp, "(iproute2 netns name: %s)", c->name);
+		netns_map_del(c);
+	}
+
+	/* During 'ip monitor nsid', no chance to have new nsid in cache. */
+	if (c == NULL && n->nlmsg_type == RTM_NEWNSID)
+		if (netns_get_name(nsid, name) == 0) {
+			fprintf(fp, "(iproute2 netns name: %s)", name);
+			netns_map_add(nsid, name);
+		}
+
+	fprintf(fp, "\n");
+	fflush(fp);
+	return 0;
+}
+
+static int netns_list_id(int argc, char **argv)
+{
+#ifdef HAVE_NETNSID
+	if (rtnl_wilddump_request(&rth, AF_UNSPEC, RTM_GETNSID) < 0) {
+		perror("Cannot send dump request");
+		exit(1);
+	}
+	if (rtnl_dump_filter(&rth, print_nsid, stdout) < 0) {
+		fprintf(stderr, "Dump terminated\n");
+		exit(1);
+	}
+#else
+	fprintf(stderr, "HAVE_NETNSID is not set\n");
+#endif
+	return 0;
+}
+
 static int netns_list(int argc, char **argv)
 {
 	struct dirent *entry;
@@ -532,6 +726,8 @@ static int netns_monitor(int argc, char **argv)
 
 int do_netns(int argc, char **argv)
 {
+	netns_map_init();
+
 	if (argc < 1)
 		return netns_list(0, NULL);
 
@@ -539,6 +735,9 @@ int do_netns(int argc, char **argv)
 	    (matches(*argv, "lst") == 0))
 		return netns_list(argc-1, argv+1);
 
+	if ((matches(*argv, "list-id") == 0))
+		return netns_list_id(argc-1, argv+1);
+
 	if (matches(*argv, "help") == 0)
 		return usage();
 
diff --git a/lib/ll_map.c b/lib/ll_map.c
index db34a2aae7b9..c6f70274416d 100644
--- a/lib/ll_map.c
+++ b/lib/ll_map.c
@@ -52,7 +52,7 @@ static struct ll_cache *ll_get_by_index(unsigned index)
 	return NULL;
 }
 
-static unsigned namehash(const char *str)
+unsigned namehash(const char *str)
 {
 	unsigned hash = 5381;
 
diff --git a/man/man8/ip-monitor.8 b/man/man8/ip-monitor.8
index 5ce8dc736efd..165414688e7b 100644
--- a/man/man8/ip-monitor.8
+++ b/man/man8/ip-monitor.8
@@ -49,7 +49,7 @@ command is the first in the command line and then the object list follows:
 is the list of object types that we want to monitor.
 It may contain
 .BR link ", " address ", " route ", " mroute ", " prefix ", "
-.BR neigh ", " netconf " and " rule "."
+.BR neigh ", " netconf ", "  rule " and " nsid "."
 If no
 .B file
 argument is given,
diff --git a/man/man8/ip-netns.8 b/man/man8/ip-netns.8
index d34cdfe3783a..8d59437e1e9f 100644
--- a/man/man8/ip-netns.8
+++ b/man/man8/ip-netns.8
@@ -42,6 +42,9 @@ ip-netns \- process network namespace management
 .ti -8
 .BR "ip netns monitor"
 
+.ti -8
+.BR "ip netns list-id"
+
 .SH DESCRIPTION
 A network namespace is logically another copy of the network stack,
 with its own routes, firewall rules, and network devices.
@@ -172,6 +175,13 @@ executing.
 This command watches network namespace name addition and deletion events
 and prints a line for each event it sees.
 
+.TP
+.B ip netns list-id - list network namespace ids (nsid)
+.sp
+Network namespace ids are used to identify a peer network namespace. This
+command displays nsid of the current network namespace and provides the
+corresponding iproute2 netns name (from /var/run/netns) if any.
+
 .SH EXAMPLES
 .PP
 ip netns list
-- 
2.2.2

^ permalink raw reply related	[flat|nested] 9+ messages in thread

* Re: [PATCH iproute2-next 2/2] netns: allow to dump and monitor nsid
  2015-04-09  8:30 ` [PATCH iproute2-next 2/2] netns: allow to dump and monitor nsid Nicolas Dichtel
@ 2015-04-09  8:36   ` Vadim Kochan
  2015-04-10 14:03     ` Nicolas Dichtel
  2015-04-09  8:48   ` Vadim Kochan
  2015-04-15 12:23   ` [PATCH v2 iproute2] " Nicolas Dichtel
  2 siblings, 1 reply; 9+ messages in thread
From: Vadim Kochan @ 2015-04-09  8:36 UTC (permalink / raw)
  To: Nicolas Dichtel; +Cc: shemminger, netdev

On Thu, Apr 09, 2015 at 10:30:14AM +0200, Nicolas Dichtel wrote:

Hi,

> diff --git a/ip/ipnetns.c b/ip/ipnetns.c
> index 45e234a4d98c..7806335733cf 100644
> --- a/ip/ipnetns.c
> +++ b/ip/ipnetns.c
> @@ -14,10 +14,12 @@
>  #include <errno.h>
>  #include <unistd.h>
>  #include <ctype.h>
> +#include <linux/limits.h>
>  
>  #include <linux/net_namespace.h>
>  
>  #include "utils.h"
> +#include "hlist.h"
>  #include "ip_common.h"
>  #include "namespace.h"
>  
> @@ -31,9 +33,13 @@ static int usage(void)
>  	fprintf(stderr, "       ip netns pids NAME\n");
>  	fprintf(stderr, "       ip [-all] netns exec [NAME] cmd ...\n");
>  	fprintf(stderr, "       ip netns monitor\n");
> +	fprintf(stderr, "       ip netns list-id\n");
>  	exit(-1);
>  }
>  
> +/* This socket is used to get nsid */
> +static struct rtnl_handle rtnsh = { .fd = -1 };
> +
>  #ifdef HAVE_NETNSID
>  static int get_netnsid_from_name(const char *name)
>  {
> @@ -57,7 +63,7 @@ static int get_netnsid_from_name(const char *name)
>  		return fd;
>  
>  	addattr32(&req.n, 1024, NETNSA_FD, fd);
> -	if (rtnl_talk(&rth, &req.n, 0, 0, &answer.n) < 0) {
> +	if (rtnl_talk(&rtnsh, &req.n, 0, 0, &answer.n) < 0) {
>  		close(fd);
>  		return -2;
>  	}
> @@ -86,6 +92,194 @@ static int get_netnsid_from_name(const char *name)
>  }
>  #endif /* HAVE_NETNSID */
>  
> +struct nsid_cache {
> +	struct hlist_node	nsid_hash;
> +	struct hlist_node	name_hash;
> +	int			nsid;
> +	char			name[NAME_MAX];
> +};
> +
> +#define NSIDMAP_SIZE		128
> +#define NSID_HASH_NSID(nsid)	(nsid & (NSIDMAP_SIZE - 1))
> +#define NSID_HASH_NAME(name)	(namehash(name) & (NSIDMAP_SIZE - 1))
> +
> +static struct hlist_head	nsid_head[NSIDMAP_SIZE];
> +static struct hlist_head	name_head[NSIDMAP_SIZE];
> +
> +static struct nsid_cache *netns_map_get_by_nsid(int nsid)
> +{
> +	uint32_t h = NSID_HASH_NSID(nsid);
> +	struct hlist_node *n;
> +
> +	hlist_for_each(n, &nsid_head[h]) {
> +		struct nsid_cache *c = container_of(n, struct nsid_cache,
> +						    nsid_hash);
> +		if (c->nsid == nsid)
> +			return c;
> +	}
> +
> +	return NULL;
> +}
> +
> +static int netns_map_add(int nsid, char *name)
> +{
> +	struct nsid_cache *c;
> +	uint32_t h;
> +
> +	if (netns_map_get_by_nsid(nsid) != NULL)
> +		return -EEXIST;
> +
> +	c = malloc(sizeof(*c));
> +	if (c == NULL) {
> +		perror("malloc");
> +		return -ENOMEM;
> +	}
> +	c->nsid = nsid;
> +	strcpy(c->name, name);
> +
> +	h = NSID_HASH_NSID(nsid);
> +	hlist_add_head(&c->nsid_hash, &nsid_head[h]);
> +
> +	h = NSID_HASH_NAME(name);
> +	hlist_add_head(&c->name_hash, &name_head[h]);
> +
> +	return 0;
> +}
> +
> +static void netns_map_del(struct nsid_cache *c)
> +{
> +	hlist_del(&c->name_hash);
> +	hlist_del(&c->nsid_hash);
> +	free(c);
> +}
> +
> +void netns_map_init(void)
> +{
> +	static int initialized;
> +	struct dirent *entry;
> +	DIR *dir;
> +	int nsid;
> +
> +	if (initialized)
> +		return;
> +
> +	if (rtnl_open(&rtnsh, 0) < 0) {
> +		fprintf(stderr, "Cannot open rtnetlink\n");
> +		exit(1);
> +	}
> +
> +	dir = opendir(NETNS_RUN_DIR);
> +	if (!dir)
> +		return;
> +
> +	while ((entry = readdir(dir)) != NULL) {
> +		if (strcmp(entry->d_name, ".") == 0)
> +			continue;
> +		if (strcmp(entry->d_name, "..") == 0)
> +			continue;
> +		nsid = get_netnsid_from_name(entry->d_name);
> +
> +		if (nsid >= 0)
> +			netns_map_add(nsid, entry->d_name);
> +	}

May be lib/namespace.c -> netns_foreach will be useful here  ?

> +	closedir(dir);
> +	initialized = 1;
> +}
> +
> +static int netns_get_name(int nsid, char *name)
> +{
> +	struct dirent *entry;
> +	DIR *dir;
> +	int id;
> +
> +	dir = opendir(NETNS_RUN_DIR);
> +	if (!dir)
> +		return -ENOENT;
> +
> +	while ((entry = readdir(dir)) != NULL) {
> +		if (strcmp(entry->d_name, ".") == 0)
> +			continue;
> +		if (strcmp(entry->d_name, "..") == 0)
> +			continue;
> +		id = get_netnsid_from_name(entry->d_name);
> +
> +		if (nsid == id) {
> +			strcpy(name, entry->d_name);
> +			closedir(dir);
> +			return 0;
> +		}
> +	}

And may be here too ?

> +	closedir(dir);
> +	return -ENOENT;
> +}
> +

Regards,
Vadim Kochan

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: [PATCH iproute2-next 2/2] netns: allow to dump and monitor nsid
  2015-04-09  8:30 ` [PATCH iproute2-next 2/2] netns: allow to dump and monitor nsid Nicolas Dichtel
  2015-04-09  8:36   ` Vadim Kochan
@ 2015-04-09  8:48   ` Vadim Kochan
  2015-04-10 14:03     ` Nicolas Dichtel
  2015-04-15 12:23   ` [PATCH v2 iproute2] " Nicolas Dichtel
  2 siblings, 1 reply; 9+ messages in thread
From: Vadim Kochan @ 2015-04-09  8:48 UTC (permalink / raw)
  To: Nicolas Dichtel; +Cc: shemminger, netdev

On Thu, Apr 09, 2015 at 10:30:14AM +0200, Nicolas Dichtel wrote:
> diff --git a/ip/ipnetns.c b/ip/ipnetns.c
> index 45e234a4d98c..7806335733cf 100644
> --- a/ip/ipnetns.c
> +++ b/ip/ipnetns.c
> @@ -14,10 +14,12 @@
>  #include <errno.h>
>  #include <unistd.h>
>  #include <ctype.h>
> +#include <linux/limits.h>
>  
>  #include <linux/net_namespace.h>
>  
>  #include "utils.h"
> +#include "hlist.h"
>  #include "ip_common.h"
>  #include "namespace.h"
>  
> @@ -31,9 +33,13 @@ static int usage(void)
>  	fprintf(stderr, "       ip netns pids NAME\n");
>  	fprintf(stderr, "       ip [-all] netns exec [NAME] cmd ...\n");
>  	fprintf(stderr, "       ip netns monitor\n");
> +	fprintf(stderr, "       ip netns list-id\n");
>  	exit(-1);
>  }
>  
> +/* This socket is used to get nsid */
> +static struct rtnl_handle rtnsh = { .fd = -1 };
> +
>  #ifdef HAVE_NETNSID
>  static int get_netnsid_from_name(const char *name)
>  {
> @@ -57,7 +63,7 @@ static int get_netnsid_from_name(const char *name)
>  		return fd;
>  
>  	addattr32(&req.n, 1024, NETNSA_FD, fd);
> -	if (rtnl_talk(&rth, &req.n, 0, 0, &answer.n) < 0) {
> +	if (rtnl_talk(&rtnsh, &req.n, 0, 0, &answer.n) < 0) {
>  		close(fd);
>  		return -2;
>  	}
> @@ -86,6 +92,194 @@ static int get_netnsid_from_name(const char *name)
>  }
>  #endif /* HAVE_NETNSID */
>  
> +struct nsid_cache {
> +	struct hlist_node	nsid_hash;
> +	struct hlist_node	name_hash;
> +	int			nsid;
> +	char			name[NAME_MAX];
> +};

I am not sure but may be lib/names.c can be used here for caching
netns (name,id) entries here ?
I tried to make it generic when added mapping class id -> name for tc util.

Regards,
Vadim Kochan

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: [PATCH iproute2-next 2/2] netns: allow to dump and monitor nsid
  2015-04-09  8:48   ` Vadim Kochan
@ 2015-04-10 14:03     ` Nicolas Dichtel
  0 siblings, 0 replies; 9+ messages in thread
From: Nicolas Dichtel @ 2015-04-10 14:03 UTC (permalink / raw)
  To: Vadim Kochan; +Cc: shemminger, netdev

Le 09/04/2015 10:48, Vadim Kochan a écrit :
> On Thu, Apr 09, 2015 at 10:30:14AM +0200, Nicolas Dichtel wrote:
[snip]
>> +struct nsid_cache {
>> +	struct hlist_node	nsid_hash;
>> +	struct hlist_node	name_hash;
>> +	int			nsid;
>> +	char			name[NAME_MAX];
>> +};
>
> I am not sure but may be lib/names.c can be used here for caching
> netns (name,id) entries here ?
If I understrand well, the way to get the id is completely different, thus
it needs a lot of changes to use this lib.

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: [PATCH iproute2-next 2/2] netns: allow to dump and monitor nsid
  2015-04-09  8:36   ` Vadim Kochan
@ 2015-04-10 14:03     ` Nicolas Dichtel
  0 siblings, 0 replies; 9+ messages in thread
From: Nicolas Dichtel @ 2015-04-10 14:03 UTC (permalink / raw)
  To: Vadim Kochan; +Cc: shemminger, netdev

Le 09/04/2015 10:36, Vadim Kochan a écrit :
> On Thu, Apr 09, 2015 at 10:30:14AM +0200, Nicolas Dichtel wrote:
[snip]
>> +	dir = opendir(NETNS_RUN_DIR);
>> +	if (!dir)
>> +		return;
>> +
>> +	while ((entry = readdir(dir)) != NULL) {
>> +		if (strcmp(entry->d_name, ".") == 0)
>> +			continue;
>> +		if (strcmp(entry->d_name, "..") == 0)
>> +			continue;
>> +		nsid = get_netnsid_from_name(entry->d_name);
>> +
>> +		if (nsid >= 0)
>> +			netns_map_add(nsid, entry->d_name);
>> +	}
>
> May be lib/namespace.c -> netns_foreach will be useful here  ?
I'm not fully convinced, because to use netns_foreach I need to have
another intermediate function.

[snip]
>> +	dir = opendir(NETNS_RUN_DIR);
>> +	if (!dir)
>> +		return -ENOENT;
>> +
>> +	while ((entry = readdir(dir)) != NULL) {
>> +		if (strcmp(entry->d_name, ".") == 0)
>> +			continue;
>> +		if (strcmp(entry->d_name, "..") == 0)
>> +			continue;
>> +		id = get_netnsid_from_name(entry->d_name);
>> +
>> +		if (nsid == id) {
>> +			strcpy(name, entry->d_name);
>> +			closedir(dir);
>> +			return 0;
>> +		}
>> +	}
>
> And may be here too ?
Same here. And this implies to also define a new structure to pass 'name' and
'nsid' to this new intermediate function. This will make the code more complex
to read.


Regards,
Nicolas

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: [PATCH iproute2-next 1/2] include: update linux/rtnetlink.h
  2015-04-09  8:30 [PATCH iproute2-next 1/2] include: update linux/rtnetlink.h Nicolas Dichtel
  2015-04-09  8:30 ` [PATCH iproute2-next 2/2] netns: allow to dump and monitor nsid Nicolas Dichtel
@ 2015-04-10 20:24 ` Stephen Hemminger
       [not found] ` <797e9129b12148228f163402c284dce6@HQ1WP-EXMB12.corp.brocade.com>
  2 siblings, 0 replies; 9+ messages in thread
From: Stephen Hemminger @ 2015-04-10 20:24 UTC (permalink / raw)
  To: Nicolas Dichtel; +Cc: shemminger, netdev

On Thu,  9 Apr 2015 10:30:13 +0200
Nicolas Dichtel <nicolas.dichtel@6wind.com> wrote:

> Signed-off-by: Nicolas Dichtel <nicolas.dichtel@6wind.com>
> ---
>  include/linux/rtnetlink.h | 4 ++++
>  1 file changed, 4 insertions(+)
> 
> diff --git a/include/linux/rtnetlink.h b/include/linux/rtnetlink.h
> index 28650a31d77f..702b19b4207e 100644
> --- a/include/linux/rtnetlink.h
> +++ b/include/linux/rtnetlink.h
> @@ -134,6 +134,8 @@ enum {
>  
>  	RTM_NEWNSID = 88,
>  #define RTM_NEWNSID RTM_NEWNSID
> +	RTM_DELNSID = 89,
> +#define RTM_DELNSID RTM_DELNSID
>  	RTM_GETNSID = 90,
>  #define RTM_GETNSID RTM_GETNSID
>  
> @@ -633,6 +635,8 @@ enum rtnetlink_groups {
>  #define RTNLGRP_MDB		RTNLGRP_MDB
>  	RTNLGRP_MPLS_ROUTE,
>  #define RTNLGRP_MPLS_ROUTE	RTNLGRP_MPLS_ROUTE
> +	RTNLGRP_NSID,
> +#define RTNLGRP_NSID		RTNLGRP_NSID
>  	__RTNLGRP_MAX
>  };
>  #define RTNLGRP_MAX	(__RTNLGRP_MAX - 1)

Unnecessary, already don on net-next branch

^ permalink raw reply	[flat|nested] 9+ messages in thread

* [PATCH v2 iproute2] netns: allow to dump and monitor nsid
  2015-04-09  8:30 ` [PATCH iproute2-next 2/2] netns: allow to dump and monitor nsid Nicolas Dichtel
  2015-04-09  8:36   ` Vadim Kochan
  2015-04-09  8:48   ` Vadim Kochan
@ 2015-04-15 12:23   ` Nicolas Dichtel
  2 siblings, 0 replies; 9+ messages in thread
From: Nicolas Dichtel @ 2015-04-15 12:23 UTC (permalink / raw)
  To: shemminger; +Cc: netdev, vadim4j, Nicolas Dichtel

Two commands are added:
 - ip netns list-id
 - ip monitor nsid

A cache is also added to remember the association between the iproute2 netns
name (from /var/run/netns/) and the nsid.
To avoid interfering with the rth socket, a new rtnl socket (rtnsh) is used to
get nsid (we may send rtnl request during listing on rth).

Example:
$ ip netns list-id
nsid 0 (iproute2 netns name: foo)
$ ip monitor nsid
Deleted nsid 0 (iproute2 netns name: foo)
nsid 16 (iproute2 netns name: bar)

Signed-off-by: Nicolas Dichtel <nicolas.dichtel@6wind.com>
---

v2: rebase on master after the 4.0 release

 include/ll_map.h      |   1 +
 ip/ip_common.h        |   3 +
 ip/ipmonitor.c        |  17 ++++-
 ip/ipnetns.c          | 202 +++++++++++++++++++++++++++++++++++++++++++++++++-
 lib/ll_map.c          |   2 +-
 man/man8/ip-monitor.8 |   2 +-
 man/man8/ip-netns.8   |  10 +++
 7 files changed, 233 insertions(+), 4 deletions(-)

diff --git a/include/ll_map.h b/include/ll_map.h
index 4c78498e7e1e..b98a5714592e 100644
--- a/include/ll_map.h
+++ b/include/ll_map.h
@@ -10,5 +10,6 @@ extern const char *ll_index_to_name(unsigned idx);
 extern const char *ll_idx_n2a(unsigned idx, char *buf);
 extern int ll_index_to_type(unsigned idx);
 extern int ll_index_to_flags(unsigned idx);
+extern unsigned namehash(const char *str);
 
 #endif /* __LL_MAP_H__ */
diff --git a/ip/ip_common.h b/ip/ip_common.h
index 89a495ea1074..b082734d9e0c 100644
--- a/ip/ip_common.h
+++ b/ip/ip_common.h
@@ -34,6 +34,9 @@ extern int print_rule(const struct sockaddr_nl *who,
 		      struct nlmsghdr *n, void *arg);
 extern int print_netconf(const struct sockaddr_nl *who,
 			 struct nlmsghdr *n, void *arg);
+extern void netns_map_init(void);
+extern int print_nsid(const struct sockaddr_nl *who,
+		      struct nlmsghdr *n, void *arg);
 extern int do_ipaddr(int argc, char **argv);
 extern int do_ipaddrlabel(int argc, char **argv);
 extern int do_iproute(int argc, char **argv);
diff --git a/ip/ipmonitor.c b/ip/ipmonitor.c
index 7833a2632927..1205ee1c7039 100644
--- a/ip/ipmonitor.c
+++ b/ip/ipmonitor.c
@@ -32,7 +32,7 @@ static void usage(void)
 	fprintf(stderr, "Usage: ip monitor [ all | LISTofOBJECTS ] [ FILE ]"
 			"[ label ] [dev DEVICE]\n");
 	fprintf(stderr, "LISTofOBJECTS := link | address | route | mroute | prefix |\n");
-	fprintf(stderr, "                 neigh | netconf | rule\n");
+	fprintf(stderr, "                 neigh | netconf | rule | nsid\n");
 	fprintf(stderr, "FILE := file FILENAME\n");
 	exit(-1);
 }
@@ -129,6 +129,12 @@ static int accept_msg(const struct sockaddr_nl *who,
 		print_nlmsg_timestamp(fp, n);
 		return 0;
 	}
+	if (n->nlmsg_type == RTM_NEWNSID || n->nlmsg_type == RTM_DELNSID) {
+		if (prefix_banner)
+			fprintf(fp, "[NSID]");
+		print_nsid(who, n, arg);
+		return 0;
+	}
 	if (n->nlmsg_type != NLMSG_ERROR && n->nlmsg_type != NLMSG_NOOP &&
 	    n->nlmsg_type != NLMSG_DONE) {
 		fprintf(fp, "Unknown message: type=0x%08x(%d) flags=0x%08x(%d)"
@@ -151,6 +157,7 @@ int do_ipmonitor(int argc, char **argv)
 	int lneigh=0;
 	int lnetconf=0;
 	int lrule=0;
+	int lnsid=0;
 	int ifindex=0;
 
 	groups |= nl_mgrp(RTNLGRP_LINK);
@@ -167,6 +174,7 @@ int do_ipmonitor(int argc, char **argv)
 	groups |= nl_mgrp(RTNLGRP_IPV6_NETCONF);
 	groups |= nl_mgrp(RTNLGRP_IPV4_RULE);
 	groups |= nl_mgrp(RTNLGRP_IPV6_RULE);
+	groups |= nl_mgrp(RTNLGRP_NSID);
 
 	rtnl_close(&rth);
 
@@ -200,6 +208,9 @@ int do_ipmonitor(int argc, char **argv)
 		} else if (matches(*argv, "rule") == 0) {
 			lrule = 1;
 			groups = 0;
+		} else if (matches(*argv, "nsid") == 0) {
+			lnsid = 1;
+			groups = 0;
 		} else if (strcmp(*argv, "all") == 0) {
 			prefix_banner=1;
 		} else if (matches(*argv, "help") == 0) {
@@ -264,6 +275,9 @@ int do_ipmonitor(int argc, char **argv)
 		if (!preferred_family || preferred_family == AF_INET6)
 			groups |= nl_mgrp(RTNLGRP_IPV6_RULE);
 	}
+	if (lnsid) {
+		groups |= nl_mgrp(RTNLGRP_NSID);
+	}
 	if (file) {
 		FILE *fp;
 		fp = fopen(file, "r");
@@ -277,6 +291,7 @@ int do_ipmonitor(int argc, char **argv)
 	if (rtnl_open(&rth, groups) < 0)
 		exit(1);
 	ll_init_map(&rth);
+	netns_map_init();
 
 	if (rtnl_listen(&rth, accept_msg, stdout) < 0)
 		exit(2);
diff --git a/ip/ipnetns.c b/ip/ipnetns.c
index 24df167e9262..8d4144b2031f 100644
--- a/ip/ipnetns.c
+++ b/ip/ipnetns.c
@@ -14,10 +14,12 @@
 #include <errno.h>
 #include <unistd.h>
 #include <ctype.h>
+#include <linux/limits.h>
 
 #include <linux/net_namespace.h>
 
 #include "utils.h"
+#include "hlist.h"
 #include "ip_common.h"
 #include "namespace.h"
 
@@ -31,9 +33,13 @@ static int usage(void)
 	fprintf(stderr, "       ip netns pids NAME\n");
 	fprintf(stderr, "       ip [-all] netns exec [NAME] cmd ...\n");
 	fprintf(stderr, "       ip netns monitor\n");
+	fprintf(stderr, "       ip netns list-id\n");
 	exit(-1);
 }
 
+/* This socket is used to get nsid */
+static struct rtnl_handle rtnsh = { .fd = -1 };
+
 static int have_rtnl_getnsid = -1;
 
 static int ipnetns_accept_msg(const struct sockaddr_nl *who,
@@ -106,7 +112,7 @@ static int get_netnsid_from_name(const char *name)
 		return fd;
 
 	addattr32(&req.n, 1024, NETNSA_FD, fd);
-	if (rtnl_talk(&rth, &req.n, 0, 0, &answer.n) < 0) {
+	if (rtnl_talk(&rtnsh, &req.n, 0, 0, &answer.n) < 0) {
 		close(fd);
 		return -2;
 	}
@@ -129,6 +135,195 @@ static int get_netnsid_from_name(const char *name)
 	return -1;
 }
 
+struct nsid_cache {
+	struct hlist_node	nsid_hash;
+	struct hlist_node	name_hash;
+	int			nsid;
+	char			name[NAME_MAX];
+};
+
+#define NSIDMAP_SIZE		128
+#define NSID_HASH_NSID(nsid)	(nsid & (NSIDMAP_SIZE - 1))
+#define NSID_HASH_NAME(name)	(namehash(name) & (NSIDMAP_SIZE - 1))
+
+static struct hlist_head	nsid_head[NSIDMAP_SIZE];
+static struct hlist_head	name_head[NSIDMAP_SIZE];
+
+static struct nsid_cache *netns_map_get_by_nsid(int nsid)
+{
+	uint32_t h = NSID_HASH_NSID(nsid);
+	struct hlist_node *n;
+
+	hlist_for_each(n, &nsid_head[h]) {
+		struct nsid_cache *c = container_of(n, struct nsid_cache,
+						    nsid_hash);
+		if (c->nsid == nsid)
+			return c;
+	}
+
+	return NULL;
+}
+
+static int netns_map_add(int nsid, char *name)
+{
+	struct nsid_cache *c;
+	uint32_t h;
+
+	if (netns_map_get_by_nsid(nsid) != NULL)
+		return -EEXIST;
+
+	c = malloc(sizeof(*c));
+	if (c == NULL) {
+		perror("malloc");
+		return -ENOMEM;
+	}
+	c->nsid = nsid;
+	strcpy(c->name, name);
+
+	h = NSID_HASH_NSID(nsid);
+	hlist_add_head(&c->nsid_hash, &nsid_head[h]);
+
+	h = NSID_HASH_NAME(name);
+	hlist_add_head(&c->name_hash, &name_head[h]);
+
+	return 0;
+}
+
+static void netns_map_del(struct nsid_cache *c)
+{
+	hlist_del(&c->name_hash);
+	hlist_del(&c->nsid_hash);
+	free(c);
+}
+
+void netns_map_init(void)
+{
+	static int initialized;
+	struct dirent *entry;
+	DIR *dir;
+	int nsid;
+
+	if (initialized || !ipnetns_have_nsid())
+		return;
+
+	if (rtnl_open(&rtnsh, 0) < 0) {
+		fprintf(stderr, "Cannot open rtnetlink\n");
+		exit(1);
+	}
+
+	dir = opendir(NETNS_RUN_DIR);
+	if (!dir)
+		return;
+
+	while ((entry = readdir(dir)) != NULL) {
+		if (strcmp(entry->d_name, ".") == 0)
+			continue;
+		if (strcmp(entry->d_name, "..") == 0)
+			continue;
+		nsid = get_netnsid_from_name(entry->d_name);
+
+		if (nsid >= 0)
+			netns_map_add(nsid, entry->d_name);
+	}
+	closedir(dir);
+	initialized = 1;
+}
+
+static int netns_get_name(int nsid, char *name)
+{
+	struct dirent *entry;
+	DIR *dir;
+	int id;
+
+	dir = opendir(NETNS_RUN_DIR);
+	if (!dir)
+		return -ENOENT;
+
+	while ((entry = readdir(dir)) != NULL) {
+		if (strcmp(entry->d_name, ".") == 0)
+			continue;
+		if (strcmp(entry->d_name, "..") == 0)
+			continue;
+		id = get_netnsid_from_name(entry->d_name);
+
+		if (nsid == id) {
+			strcpy(name, entry->d_name);
+			closedir(dir);
+			return 0;
+		}
+	}
+	closedir(dir);
+	return -ENOENT;
+}
+
+int print_nsid(const struct sockaddr_nl *who, struct nlmsghdr *n, void *arg)
+{
+	struct rtgenmsg *rthdr = NLMSG_DATA(n);
+	struct rtattr *tb[NETNSA_MAX+1];
+	int len = n->nlmsg_len;
+	FILE *fp = (FILE*)arg;
+	struct nsid_cache *c;
+	char name[NAME_MAX];
+	int nsid;
+
+	if (n->nlmsg_type != RTM_NEWNSID && n->nlmsg_type != RTM_DELNSID)
+		return 0;
+
+	len -= NLMSG_SPACE(sizeof(*rthdr));
+	if (len < 0) {
+		fprintf(stderr, "BUG: wrong nlmsg len %d in %s\n", len,
+			__func__);
+		return -1;
+	}
+
+	parse_rtattr(tb, NETNSA_MAX, NETNS_RTA(rthdr), len);
+	if (tb[NETNSA_NSID] == NULL) {
+		fprintf(stderr, "BUG: NETNSA_NSID is missing %s\n", __func__);
+		return -1;
+	}
+
+	if (n->nlmsg_type == RTM_DELNSID)
+		fprintf(fp, "Deleted ");
+
+	nsid = rta_getattr_u32(tb[NETNSA_NSID]);
+	fprintf(fp, "nsid %u ", nsid);
+
+	c = netns_map_get_by_nsid(nsid);
+	if (c != NULL) {
+		fprintf(fp, "(iproute2 netns name: %s)", c->name);
+		netns_map_del(c);
+	}
+
+	/* During 'ip monitor nsid', no chance to have new nsid in cache. */
+	if (c == NULL && n->nlmsg_type == RTM_NEWNSID)
+		if (netns_get_name(nsid, name) == 0) {
+			fprintf(fp, "(iproute2 netns name: %s)", name);
+			netns_map_add(nsid, name);
+		}
+
+	fprintf(fp, "\n");
+	fflush(fp);
+	return 0;
+}
+
+static int netns_list_id(int argc, char **argv)
+{
+	if (!ipnetns_have_nsid()) {
+		fprintf(stderr, "RTM_GETNSID is not supported by the kernel.\n");
+		return -ENOTSUP;
+	}
+
+	if (rtnl_wilddump_request(&rth, AF_UNSPEC, RTM_GETNSID) < 0) {
+		perror("Cannot send dump request");
+		exit(1);
+	}
+	if (rtnl_dump_filter(&rth, print_nsid, stdout) < 0) {
+		fprintf(stderr, "Dump terminated\n");
+		exit(1);
+	}
+	return 0;
+}
+
 static int netns_list(int argc, char **argv)
 {
 	struct dirent *entry;
@@ -577,6 +772,8 @@ static int netns_monitor(int argc, char **argv)
 
 int do_netns(int argc, char **argv)
 {
+	netns_map_init();
+
 	if (argc < 1)
 		return netns_list(0, NULL);
 
@@ -584,6 +781,9 @@ int do_netns(int argc, char **argv)
 	    (matches(*argv, "lst") == 0))
 		return netns_list(argc-1, argv+1);
 
+	if ((matches(*argv, "list-id") == 0))
+		return netns_list_id(argc-1, argv+1);
+
 	if (matches(*argv, "help") == 0)
 		return usage();
 
diff --git a/lib/ll_map.c b/lib/ll_map.c
index db34a2aae7b9..c6f70274416d 100644
--- a/lib/ll_map.c
+++ b/lib/ll_map.c
@@ -52,7 +52,7 @@ static struct ll_cache *ll_get_by_index(unsigned index)
 	return NULL;
 }
 
-static unsigned namehash(const char *str)
+unsigned namehash(const char *str)
 {
 	unsigned hash = 5381;
 
diff --git a/man/man8/ip-monitor.8 b/man/man8/ip-monitor.8
index 1de0ca922449..9663349fe9c7 100644
--- a/man/man8/ip-monitor.8
+++ b/man/man8/ip-monitor.8
@@ -49,7 +49,7 @@ command is the first in the command line and then the object list follows:
 is the list of object types that we want to monitor.
 It may contain
 .BR link ", " address ", " route ", " mroute ", " prefix ", "
-.BR neigh ", " netconf " and " rule "."
+.BR neigh ", " netconf ", "  rule " and " nsid "."
 If no
 .B file
 argument is given,
diff --git a/man/man8/ip-netns.8 b/man/man8/ip-netns.8
index 80a4ad1226d4..c9b0fbc2c163 100644
--- a/man/man8/ip-netns.8
+++ b/man/man8/ip-netns.8
@@ -42,6 +42,9 @@ ip-netns \- process network namespace management
 .ti -8
 .BR "ip netns monitor"
 
+.ti -8
+.BR "ip netns list-id"
+
 .SH DESCRIPTION
 A network namespace is logically another copy of the network stack,
 with its own routes, firewall rules, and network devices.
@@ -178,6 +181,13 @@ executing.
 This command watches network namespace name addition and deletion events
 and prints a line for each event it sees.
 
+.TP
+.B ip netns list-id - list network namespace ids (nsid)
+.sp
+Network namespace ids are used to identify a peer network namespace. This
+command displays nsid of the current network namespace and provides the
+corresponding iproute2 netns name (from /var/run/netns) if any.
+
 .SH EXAMPLES
 .PP
 ip netns list
-- 
2.2.2

^ permalink raw reply related	[flat|nested] 9+ messages in thread

* Re: [PATCH iproute2-next 2/2] netns: allow to dump and monitor nsid
       [not found] ` <797e9129b12148228f163402c284dce6@HQ1WP-EXMB12.corp.brocade.com>
@ 2015-04-20 17:02   ` Stephen Hemminger
  0 siblings, 0 replies; 9+ messages in thread
From: Stephen Hemminger @ 2015-04-20 17:02 UTC (permalink / raw)
  To: Nicolas Dichtel; +Cc: netdev@vger.kernel.org

On Thu, 9 Apr 2015 08:30:14 +0000
Nicolas Dichtel <nicolas.dichtel@6wind.com> wrote:

> Two commands are added:
>  - ip netns list-id
>  - ip monitor nsid
> 
> A cache is also added to remember the association between the iproute2 netns
> name (from /var/run/netns/) and the nsid.
> To avoid interfering with the rth socket, a new rtnl socket (rtnsh) is used to
> get nsid (we may send rtnl request during listing on rth).
> 
> Example:
> $ ip netns list-id
> nsid 0 (iproute2 netns name: foo)
> $ ip monitor nsid
> Deleted nsid 0 (iproute2 netns name: foo)
> nsid 16 (iproute2 netns name: bar)
> 
> Signed-off-by: Nicolas Dichtel <nicolas.dichtel@6wind.com>

Applied with a couple of little style cleanups.

^ permalink raw reply	[flat|nested] 9+ messages in thread

end of thread, other threads:[~2015-04-20 17:02 UTC | newest]

Thread overview: 9+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2015-04-09  8:30 [PATCH iproute2-next 1/2] include: update linux/rtnetlink.h Nicolas Dichtel
2015-04-09  8:30 ` [PATCH iproute2-next 2/2] netns: allow to dump and monitor nsid Nicolas Dichtel
2015-04-09  8:36   ` Vadim Kochan
2015-04-10 14:03     ` Nicolas Dichtel
2015-04-09  8:48   ` Vadim Kochan
2015-04-10 14:03     ` Nicolas Dichtel
2015-04-15 12:23   ` [PATCH v2 iproute2] " Nicolas Dichtel
2015-04-10 20:24 ` [PATCH iproute2-next 1/2] include: update linux/rtnetlink.h Stephen Hemminger
     [not found] ` <797e9129b12148228f163402c284dce6@HQ1WP-EXMB12.corp.brocade.com>
2015-04-20 17:02   ` [PATCH iproute2-next 2/2] netns: allow to dump and monitor nsid Stephen Hemminger

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.