netdev.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH iproute2-next 1/3] include: update headers
@ 2015-01-20 10:36 Nicolas Dichtel
  2015-01-20 10:36 ` [PATCH iproute2-next 2/3] ipnetns: allow to get and set netns ids Nicolas Dichtel
                   ` (2 more replies)
  0 siblings, 3 replies; 14+ messages in thread
From: Nicolas Dichtel @ 2015-01-20 10:36 UTC (permalink / raw)
  To: shemminger; +Cc: netdev, Nicolas Dichtel

Signed-off-by: Nicolas Dichtel <nicolas.dichtel@6wind.com>
---
 include/linux/if_link.h       |  1 +
 include/linux/net_namespace.h | 23 +++++++++++++++++++++++
 include/linux/rtnetlink.h     |  5 +++++
 3 files changed, 29 insertions(+)
 create mode 100644 include/linux/net_namespace.h

diff --git a/include/linux/if_link.h b/include/linux/if_link.h
index 167ec34bab73..58e32ace7d2a 100644
--- a/include/linux/if_link.h
+++ b/include/linux/if_link.h
@@ -146,6 +146,7 @@ enum {
 	IFLA_PHYS_PORT_ID,
 	IFLA_CARRIER_CHANGES,
 	IFLA_PHYS_SWITCH_ID,
+	IFLA_LINK_NETNSID,
 	__IFLA_MAX
 };
 
diff --git a/include/linux/net_namespace.h b/include/linux/net_namespace.h
new file mode 100644
index 000000000000..9a92b7e14a19
--- /dev/null
+++ b/include/linux/net_namespace.h
@@ -0,0 +1,23 @@
+/* Copyright (c) 2015 6WIND S.A.
+ * Author: Nicolas Dichtel <nicolas.dichtel@6wind.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ */
+#ifndef _LINUX_NET_NAMESPACE_H_
+#define _LINUX_NET_NAMESPACE_H_
+
+/* Attributes of RTM_NEWNSID/RTM_GETNSID messages */
+enum {
+	NETNSA_NONE,
+#define NETNSA_NSID_NOT_ASSIGNED -1
+	NETNSA_NSID,
+	NETNSA_PID,
+	NETNSA_FD,
+	__NETNSA_MAX,
+};
+
+#define NETNSA_MAX		(__NETNSA_MAX - 1)
+
+#endif /* _LINUX_NET_NAMESPACE_H_ */
diff --git a/include/linux/rtnetlink.h b/include/linux/rtnetlink.h
index 9111053f2250..3eb78105399b 100644
--- a/include/linux/rtnetlink.h
+++ b/include/linux/rtnetlink.h
@@ -132,6 +132,11 @@ enum {
 	RTM_GETMDB = 86,
 #define RTM_GETMDB RTM_GETMDB
 
+	RTM_NEWNSID = 88,
+#define RTM_NEWNSID RTM_NEWNSID
+	RTM_GETNSID = 90,
+#define RTM_GETNSID RTM_GETNSID
+
 	__RTM_MAX,
 #define RTM_MAX		(((__RTM_MAX + 3) & ~3) - 1)
 };
-- 
2.2.2

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

* [PATCH iproute2-next 2/3] ipnetns: allow to get and set netns ids
  2015-01-20 10:36 [PATCH iproute2-next 1/3] include: update headers Nicolas Dichtel
@ 2015-01-20 10:36 ` Nicolas Dichtel
  2015-01-20 10:36 ` [PATCH iproute2-next 3/3] iplink: add support of IFLA_LINK_NETNSID attribute Nicolas Dichtel
  2015-01-28 13:28 ` [PATCH iproute2-next 1/3] include: update headers Nicolas Dichtel
  2 siblings, 0 replies; 14+ messages in thread
From: Nicolas Dichtel @ 2015-01-20 10:36 UTC (permalink / raw)
  To: shemminger; +Cc: netdev, Nicolas Dichtel

The kernel now provides ids for peer netns. This patch implements a new command
'set' to assign an id.
When netns are listed, if an id is assigned, it is now displayed.

Example:
 $ ip netns add foo
 $ ip netns set foo 1
 $ ip netns
 foo (id: 1)
 init_net

Signed-off-by: Nicolas Dichtel <nicolas.dichtel@6wind.com>
---
 include/libnetlink.h |   8 ++++
 ip/ipnetns.c         | 113 ++++++++++++++++++++++++++++++++++++++++++++++++++-
 man/man8/ip-netns.8  |  14 +++++++
 3 files changed, 134 insertions(+), 1 deletion(-)

diff --git a/include/libnetlink.h b/include/libnetlink.h
index d081e54210ea..898275b824d4 100644
--- a/include/libnetlink.h
+++ b/include/libnetlink.h
@@ -158,6 +158,14 @@ extern int rtnl_from_file(FILE *, rtnl_filter_t handler,
 #define NDTA_PAYLOAD(n) NLMSG_PAYLOAD(n,sizeof(struct ndtmsg))
 #endif
 
+#ifndef NETNS_RTA
+#define NETNS_RTA(r) \
+	((struct rtattr*)(((char*)(r)) + NLMSG_ALIGN(sizeof(struct rtgenmsg))))
+#endif
+#ifndef NETNS_PAYLOAD
+#define NETNS_PAYLOAD(n)	NLMSG_PAYLOAD(n,sizeof(struct rtgenmsg))
+#endif
+
 /* User defined nlmsg_type which is used mostly for logging netlink
  * messages from dump file */
 #define NLMSG_TSTAMP	15
diff --git a/ip/ipnetns.c b/ip/ipnetns.c
index 123318eb6adf..8c86673db581 100644
--- a/ip/ipnetns.c
+++ b/ip/ipnetns.c
@@ -15,6 +15,8 @@
 #include <unistd.h>
 #include <ctype.h>
 
+#include <linux/net_namespace.h>
+
 #include "utils.h"
 #include "ip_common.h"
 #include "namespace.h"
@@ -23,6 +25,7 @@ static int usage(void)
 {
 	fprintf(stderr, "Usage: ip netns list\n");
 	fprintf(stderr, "       ip netns add NAME\n");
+	fprintf(stderr, "       ip netns set NAME NETNSID\n");
 	fprintf(stderr, "       ip netns delete NAME\n");
 	fprintf(stderr, "       ip netns identify [PID]\n");
 	fprintf(stderr, "       ip netns pids NAME\n");
@@ -31,10 +34,56 @@ static int usage(void)
 	exit(-1);
 }
 
+static int get_netnsid_from_name(const char *name)
+{
+	struct {
+		struct nlmsghdr n;
+		struct rtgenmsg g;
+		char            buf[1024];
+	} req, answer;
+	struct rtattr *tb[NETNSA_MAX + 1];
+	struct rtgenmsg *rthdr;
+	int len, fd;
+
+	memset(&req, 0, sizeof(req));
+	req.n.nlmsg_len = NLMSG_LENGTH(sizeof(struct rtgenmsg));
+	req.n.nlmsg_flags = NLM_F_REQUEST;
+	req.n.nlmsg_type = RTM_GETNSID;
+	req.g.rtgen_family = AF_UNSPEC;
+
+	fd = netns_get_fd(name);
+	if (fd < 0)
+		return fd;
+
+	addattr32(&req.n, 1024, NETNSA_FD, fd);
+	if (rtnl_talk(&rth, &req.n, 0, 0, &answer.n) < 0) {
+		close(fd);
+		return -2;
+	}
+	close(fd);
+
+	/* Validate message and parse attributes */
+	if (answer.n.nlmsg_type == NLMSG_ERROR)
+		return -1;
+
+	rthdr = NLMSG_DATA(&answer.n);
+	len = answer.n.nlmsg_len - NLMSG_SPACE(sizeof(*rthdr));
+	if (len < 0)
+		return -1;
+
+	parse_rtattr(tb, NETNSA_MAX, NETNS_RTA(rthdr), len);
+
+	if (tb[NETNSA_NSID])
+		return rta_getattr_u32(tb[NETNSA_NSID]);
+
+	return -1;
+}
+
 static int netns_list(int argc, char **argv)
 {
 	struct dirent *entry;
 	DIR *dir;
+	int id;
 
 	dir = opendir(NETNS_RUN_DIR);
 	if (!dir)
@@ -45,7 +94,11 @@ static int netns_list(int argc, char **argv)
 			continue;
 		if (strcmp(entry->d_name, "..") == 0)
 			continue;
-		printf("%s\n", entry->d_name);
+		printf("%s", entry->d_name);
+		id = get_netnsid_from_name(entry->d_name);
+		if (id >= 0)
+			printf(" (id: %d)", id);
+		printf("\n");
 	}
 	closedir(dir);
 	return 0;
@@ -355,6 +408,61 @@ out_delete:
 	return -1;
 }
 
+static int set_netnsid_from_name(const char *name, int nsid)
+{
+	struct {
+		struct nlmsghdr n;
+		struct rtgenmsg g;
+		char            buf[1024];
+	} req;
+	int fd, err = 0;
+
+	memset(&req, 0, sizeof(req));
+	req.n.nlmsg_len = NLMSG_LENGTH(sizeof(struct rtgenmsg));
+	req.n.nlmsg_flags = NLM_F_REQUEST;
+	req.n.nlmsg_type = RTM_NEWNSID;
+	req.g.rtgen_family = AF_UNSPEC;
+
+	fd = netns_get_fd(name);
+	if (fd < 0)
+		return fd;
+
+	addattr32(&req.n, 1024, NETNSA_FD, fd);
+	addattr32(&req.n, 1024, NETNSA_NSID, nsid);
+	if (rtnl_talk(&rth, &req.n, 0, 0, NULL) < 0)
+		err = -2;
+
+	close(fd);
+	return err;
+}
+
+static int netns_set(int argc, char **argv)
+{
+	char netns_path[MAXPATHLEN];
+	const char *name;
+	int netns, nsid;
+
+	if (argc < 1) {
+		fprintf(stderr, "No netns name specified\n");
+		return -1;
+	}
+	if (argc < 2) {
+		fprintf(stderr, "No nsid specified\n");
+		return -1;
+	}
+	name = argv[0];
+	nsid = atoi(argv[1]);
+
+	snprintf(netns_path, sizeof(netns_path), "%s/%s", NETNS_RUN_DIR, name);
+	netns = open(netns_path, O_RDONLY | O_CLOEXEC);
+	if (netns < 0) {
+		fprintf(stderr, "Cannot open network namespace \"%s\": %s\n",
+			name, strerror(errno));
+		return -1;
+	}
+
+	return set_netnsid_from_name(name, nsid);
+}
 
 static int netns_monitor(int argc, char **argv)
 {
@@ -410,6 +518,9 @@ int do_netns(int argc, char **argv)
 	if (matches(*argv, "add") == 0)
 		return netns_add(argc-1, argv+1);
 
+	if (matches(*argv, "set") == 0)
+		return netns_set(argc-1, argv+1);
+
 	if (matches(*argv, "delete") == 0)
 		return netns_delete(argc-1, argv+1);
 
diff --git a/man/man8/ip-netns.8 b/man/man8/ip-netns.8
index 74343ed6b640..95fc5e6b8a45 100644
--- a/man/man8/ip-netns.8
+++ b/man/man8/ip-netns.8
@@ -20,6 +20,10 @@ ip-netns \- process network namespace management
 .I NETNSNAME
 
 .ti -8
+.BR "ip netns" " { " set " } "
+.I NETNSNAME NETNSID
+
+.ti -8
 .BR "ip netns identify"
 .RI "[ " PID " ]"
 
@@ -85,6 +89,16 @@ persists until it has no more users.  ip netns delete may fail if
 the mount point is in use in another mount namespace.
 
 .TP
+.B ip netns set NAME NETNSID - assign an id to a peer network namespace
+.sp
+This command assigns a id to a peer network namespace. This id is valid
+only in the current network namespace.
+This id will be used by the kernel in some netlink messages. If no id is
+assigned when the kernel needs it, it will be automatically assigned by
+the kernel.
+Once it is assigned, it's not possible to change it.
+
+.TP
 .B ip netns identify [PID] - Report network namespaces names for process
 .sp
 This command walks through /var/run/netns and finds all the network
-- 
2.2.2

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

* [PATCH iproute2-next 3/3] iplink: add support of IFLA_LINK_NETNSID attribute
  2015-01-20 10:36 [PATCH iproute2-next 1/3] include: update headers Nicolas Dichtel
  2015-01-20 10:36 ` [PATCH iproute2-next 2/3] ipnetns: allow to get and set netns ids Nicolas Dichtel
@ 2015-01-20 10:36 ` Nicolas Dichtel
  2015-01-28 13:28 ` [PATCH iproute2-next 1/3] include: update headers Nicolas Dichtel
  2 siblings, 0 replies; 14+ messages in thread
From: Nicolas Dichtel @ 2015-01-20 10:36 UTC (permalink / raw)
  To: shemminger; +Cc: netdev, Nicolas Dichtel

This new attribute is now advertised by the kernel for x-netns interfaces.
It's also possible to set it when an interface is created (and thus creating a
x-netns interface with one single message).

Example:
 $ ip netns add foo
 $ ip netns add bar
 $ ip -n foo netns set bar 15
 $ ip -n foo link add ipip1 link-netnsid 15 type ipip remote 10.16.0.121 local 10.16.0.249
 $ ip -n foo link ls ipip1
 3: ipip1@NONE: <POINTOPOINT,NOARP> mtu 1480 qdisc noop state DOWN mode DEFAULT group default
     link/ipip 10.16.0.249 peer 10.16.0.121 link-netnsid 15

Signed-off-by: Nicolas Dichtel <nicolas.dichtel@6wind.com>
---
 ip/ipaddress.c | 10 ++++++++++
 ip/iplink.c    | 10 ++++++++++
 2 files changed, 20 insertions(+)

diff --git a/ip/ipaddress.c b/ip/ipaddress.c
index d5e863dd1f12..2d867da4b10a 100644
--- a/ip/ipaddress.c
+++ b/ip/ipaddress.c
@@ -28,6 +28,7 @@
 #include <linux/netdevice.h>
 #include <linux/if_arp.h>
 #include <linux/sockios.h>
+#include <linux/net_namespace.h>
 
 #include "rt_names.h"
 #include "utils.h"
@@ -678,6 +679,15 @@ int print_linkinfo(const struct sockaddr_nl *who,
 		}
 	}
 
+	if (tb[IFLA_LINK_NETNSID]) {
+		int id = *(int*)RTA_DATA(tb[IFLA_LINK_NETNSID]);
+
+		if (id >= 0)
+			fprintf(fp, " link-netnsid %d", id);
+		else
+			fprintf(fp, " link-netnsid unknown");
+	}
+
 	if (tb[IFLA_PROMISCUITY] && show_details)
 		fprintf(fp, " promiscuity %u ",
 			*(int*)RTA_DATA(tb[IFLA_PROMISCUITY]));
diff --git a/ip/iplink.c b/ip/iplink.c
index c93d1dc3d5f6..5893ee401cf9 100644
--- a/ip/iplink.c
+++ b/ip/iplink.c
@@ -72,6 +72,7 @@ void iplink_usage(void)
 	fprintf(stderr, "	                  [ mtu MTU ]\n");
 	fprintf(stderr, "	                  [ netns PID ]\n");
 	fprintf(stderr, "	                  [ netns NAME ]\n");
+	fprintf(stderr, "                         [ link-netnsid ID ]\n");
 	fprintf(stderr, "			  [ alias NAME ]\n");
 	fprintf(stderr, "	                  [ vf NUM [ mac LLADDR ]\n");
 	fprintf(stderr, "				   [ vlan VLANID [ qos VLAN-QOS ] ]\n");
@@ -386,6 +387,7 @@ int iplink_parse(int argc, char **argv, struct iplink_req *req,
 	int numtxqueues = -1;
 	int numrxqueues = -1;
 	int dev_index = 0;
+	int link_netnsid = -1;
 
 	*group = -1;
 	ret = argc;
@@ -588,6 +590,14 @@ int iplink_parse(int argc, char **argv, struct iplink_req *req,
 			addattr8(&req->n, sizeof(*req), IFLA_INET6_ADDR_GEN_MODE, mode);
 			addattr_nest_end(&req->n, afs6);
 			addattr_nest_end(&req->n, afs);
+		} else if (matches(*argv, "link-netnsid") == 0) {
+			NEXT_ARG();
+			if (link_netnsid != -1)
+				duparg("link-netnsid", *argv);
+			if (get_integer(&link_netnsid, *argv, 0))
+				invarg("Invalid \"link-netnsid\" value\n", *argv);
+			addattr32(&req->n, sizeof(*req), IFLA_LINK_NETNSID,
+				  link_netnsid);
 		} else {
 			if (strcmp(*argv, "dev") == 0) {
 				NEXT_ARG();
-- 
2.2.2

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

* Re: [PATCH iproute2-next 1/3] include: update headers
  2015-01-20 10:36 [PATCH iproute2-next 1/3] include: update headers Nicolas Dichtel
  2015-01-20 10:36 ` [PATCH iproute2-next 2/3] ipnetns: allow to get and set netns ids Nicolas Dichtel
  2015-01-20 10:36 ` [PATCH iproute2-next 3/3] iplink: add support of IFLA_LINK_NETNSID attribute Nicolas Dichtel
@ 2015-01-28 13:28 ` Nicolas Dichtel
  2015-01-28 14:15   ` [PATCH v2 iproute2-next 1/4] " Nicolas Dichtel
  2 siblings, 1 reply; 14+ messages in thread
From: Nicolas Dichtel @ 2015-01-28 13:28 UTC (permalink / raw)
  To: shemminger; +Cc: netdev

Le 20/01/2015 11:36, Nicolas Dichtel a écrit :
> Signed-off-by: Nicolas Dichtel <nicolas.dichtel@6wind.com>
> ---
Please drop this series, I will send a v2.

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

* [PATCH v2 iproute2-next 1/4] include: update headers
  2015-01-28 13:28 ` [PATCH iproute2-next 1/3] include: update headers Nicolas Dichtel
@ 2015-01-28 14:15   ` Nicolas Dichtel
  2015-01-28 14:15     ` [PATCH v2 iproute2-next 2/4] ipnetns: allow to get and set netns ids Nicolas Dichtel
                       ` (3 more replies)
  0 siblings, 4 replies; 14+ messages in thread
From: Nicolas Dichtel @ 2015-01-28 14:15 UTC (permalink / raw)
  To: shemminger; +Cc: netdev, Nicolas Dichtel

Copy from sanitized headers.

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

v2: took last headers from net-next

 include/linux/if_link.h       |  4 ++++
 include/linux/neighbour.h     |  1 +
 include/linux/net_namespace.h | 23 +++++++++++++++++++++++
 include/linux/rtnetlink.h     |  5 +++++
 4 files changed, 33 insertions(+)
 create mode 100644 include/linux/net_namespace.h

diff --git a/include/linux/if_link.h b/include/linux/if_link.h
index 167ec34bab73..ac64724c9425 100644
--- a/include/linux/if_link.h
+++ b/include/linux/if_link.h
@@ -146,6 +146,7 @@ enum {
 	IFLA_PHYS_PORT_ID,
 	IFLA_CARRIER_CHANGES,
 	IFLA_PHYS_SWITCH_ID,
+	IFLA_LINK_NETNSID,
 	__IFLA_MAX
 };
 
@@ -368,6 +369,9 @@ enum {
 	IFLA_VXLAN_UDP_CSUM,
 	IFLA_VXLAN_UDP_ZERO_CSUM6_TX,
 	IFLA_VXLAN_UDP_ZERO_CSUM6_RX,
+	IFLA_VXLAN_REMCSUM_TX,
+	IFLA_VXLAN_REMCSUM_RX,
+	IFLA_VXLAN_GBP,
 	__IFLA_VXLAN_MAX
 };
 #define IFLA_VXLAN_MAX	(__IFLA_VXLAN_MAX - 1)
diff --git a/include/linux/neighbour.h b/include/linux/neighbour.h
index f3d77f9f1e0b..3873a35509aa 100644
--- a/include/linux/neighbour.h
+++ b/include/linux/neighbour.h
@@ -25,6 +25,7 @@ enum {
 	NDA_VNI,
 	NDA_IFINDEX,
 	NDA_MASTER,
+	NDA_LINK_NETNSID,
 	__NDA_MAX
 };
 
diff --git a/include/linux/net_namespace.h b/include/linux/net_namespace.h
new file mode 100644
index 000000000000..9a92b7e14a19
--- /dev/null
+++ b/include/linux/net_namespace.h
@@ -0,0 +1,23 @@
+/* Copyright (c) 2015 6WIND S.A.
+ * Author: Nicolas Dichtel <nicolas.dichtel@6wind.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ */
+#ifndef _LINUX_NET_NAMESPACE_H_
+#define _LINUX_NET_NAMESPACE_H_
+
+/* Attributes of RTM_NEWNSID/RTM_GETNSID messages */
+enum {
+	NETNSA_NONE,
+#define NETNSA_NSID_NOT_ASSIGNED -1
+	NETNSA_NSID,
+	NETNSA_PID,
+	NETNSA_FD,
+	__NETNSA_MAX,
+};
+
+#define NETNSA_MAX		(__NETNSA_MAX - 1)
+
+#endif /* _LINUX_NET_NAMESPACE_H_ */
diff --git a/include/linux/rtnetlink.h b/include/linux/rtnetlink.h
index 9111053f2250..3eb78105399b 100644
--- a/include/linux/rtnetlink.h
+++ b/include/linux/rtnetlink.h
@@ -132,6 +132,11 @@ enum {
 	RTM_GETMDB = 86,
 #define RTM_GETMDB RTM_GETMDB
 
+	RTM_NEWNSID = 88,
+#define RTM_NEWNSID RTM_NEWNSID
+	RTM_GETNSID = 90,
+#define RTM_GETNSID RTM_GETNSID
+
 	__RTM_MAX,
 #define RTM_MAX		(((__RTM_MAX + 3) & ~3) - 1)
 };
-- 
2.2.2

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

* [PATCH v2 iproute2-next 2/4] ipnetns: allow to get and set netns ids
  2015-01-28 14:15   ` [PATCH v2 iproute2-next 1/4] " Nicolas Dichtel
@ 2015-01-28 14:15     ` Nicolas Dichtel
  2015-01-28 14:15     ` [PATCH v2 iproute2-next 3/4] iplink: add support of IFLA_LINK_NETNSID attribute Nicolas Dichtel
                       ` (2 subsequent siblings)
  3 siblings, 0 replies; 14+ messages in thread
From: Nicolas Dichtel @ 2015-01-28 14:15 UTC (permalink / raw)
  To: shemminger; +Cc: netdev, Nicolas Dichtel

The kernel now provides ids for peer netns. This patch implements a new command
'set' to assign an id.
When netns are listed, if an id is assigned, it is now displayed.

Example:
 $ ip netns add foo
 $ ip netns set foo 1
 $ ip netns
 foo (id: 1)
 init_net

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

v2: no change

 include/libnetlink.h |   8 ++++
 ip/ipnetns.c         | 113 ++++++++++++++++++++++++++++++++++++++++++++++++++-
 man/man8/ip-netns.8  |  14 +++++++
 3 files changed, 134 insertions(+), 1 deletion(-)

diff --git a/include/libnetlink.h b/include/libnetlink.h
index d081e54210ea..898275b824d4 100644
--- a/include/libnetlink.h
+++ b/include/libnetlink.h
@@ -158,6 +158,14 @@ extern int rtnl_from_file(FILE *, rtnl_filter_t handler,
 #define NDTA_PAYLOAD(n) NLMSG_PAYLOAD(n,sizeof(struct ndtmsg))
 #endif
 
+#ifndef NETNS_RTA
+#define NETNS_RTA(r) \
+	((struct rtattr*)(((char*)(r)) + NLMSG_ALIGN(sizeof(struct rtgenmsg))))
+#endif
+#ifndef NETNS_PAYLOAD
+#define NETNS_PAYLOAD(n)	NLMSG_PAYLOAD(n,sizeof(struct rtgenmsg))
+#endif
+
 /* User defined nlmsg_type which is used mostly for logging netlink
  * messages from dump file */
 #define NLMSG_TSTAMP	15
diff --git a/ip/ipnetns.c b/ip/ipnetns.c
index 123318eb6adf..8c86673db581 100644
--- a/ip/ipnetns.c
+++ b/ip/ipnetns.c
@@ -15,6 +15,8 @@
 #include <unistd.h>
 #include <ctype.h>
 
+#include <linux/net_namespace.h>
+
 #include "utils.h"
 #include "ip_common.h"
 #include "namespace.h"
@@ -23,6 +25,7 @@ static int usage(void)
 {
 	fprintf(stderr, "Usage: ip netns list\n");
 	fprintf(stderr, "       ip netns add NAME\n");
+	fprintf(stderr, "       ip netns set NAME NETNSID\n");
 	fprintf(stderr, "       ip netns delete NAME\n");
 	fprintf(stderr, "       ip netns identify [PID]\n");
 	fprintf(stderr, "       ip netns pids NAME\n");
@@ -31,10 +34,56 @@ static int usage(void)
 	exit(-1);
 }
 
+static int get_netnsid_from_name(const char *name)
+{
+	struct {
+		struct nlmsghdr n;
+		struct rtgenmsg g;
+		char            buf[1024];
+	} req, answer;
+	struct rtattr *tb[NETNSA_MAX + 1];
+	struct rtgenmsg *rthdr;
+	int len, fd;
+
+	memset(&req, 0, sizeof(req));
+	req.n.nlmsg_len = NLMSG_LENGTH(sizeof(struct rtgenmsg));
+	req.n.nlmsg_flags = NLM_F_REQUEST;
+	req.n.nlmsg_type = RTM_GETNSID;
+	req.g.rtgen_family = AF_UNSPEC;
+
+	fd = netns_get_fd(name);
+	if (fd < 0)
+		return fd;
+
+	addattr32(&req.n, 1024, NETNSA_FD, fd);
+	if (rtnl_talk(&rth, &req.n, 0, 0, &answer.n) < 0) {
+		close(fd);
+		return -2;
+	}
+	close(fd);
+
+	/* Validate message and parse attributes */
+	if (answer.n.nlmsg_type == NLMSG_ERROR)
+		return -1;
+
+	rthdr = NLMSG_DATA(&answer.n);
+	len = answer.n.nlmsg_len - NLMSG_SPACE(sizeof(*rthdr));
+	if (len < 0)
+		return -1;
+
+	parse_rtattr(tb, NETNSA_MAX, NETNS_RTA(rthdr), len);
+
+	if (tb[NETNSA_NSID])
+		return rta_getattr_u32(tb[NETNSA_NSID]);
+
+	return -1;
+}
+
 static int netns_list(int argc, char **argv)
 {
 	struct dirent *entry;
 	DIR *dir;
+	int id;
 
 	dir = opendir(NETNS_RUN_DIR);
 	if (!dir)
@@ -45,7 +94,11 @@ static int netns_list(int argc, char **argv)
 			continue;
 		if (strcmp(entry->d_name, "..") == 0)
 			continue;
-		printf("%s\n", entry->d_name);
+		printf("%s", entry->d_name);
+		id = get_netnsid_from_name(entry->d_name);
+		if (id >= 0)
+			printf(" (id: %d)", id);
+		printf("\n");
 	}
 	closedir(dir);
 	return 0;
@@ -355,6 +408,61 @@ out_delete:
 	return -1;
 }
 
+static int set_netnsid_from_name(const char *name, int nsid)
+{
+	struct {
+		struct nlmsghdr n;
+		struct rtgenmsg g;
+		char            buf[1024];
+	} req;
+	int fd, err = 0;
+
+	memset(&req, 0, sizeof(req));
+	req.n.nlmsg_len = NLMSG_LENGTH(sizeof(struct rtgenmsg));
+	req.n.nlmsg_flags = NLM_F_REQUEST;
+	req.n.nlmsg_type = RTM_NEWNSID;
+	req.g.rtgen_family = AF_UNSPEC;
+
+	fd = netns_get_fd(name);
+	if (fd < 0)
+		return fd;
+
+	addattr32(&req.n, 1024, NETNSA_FD, fd);
+	addattr32(&req.n, 1024, NETNSA_NSID, nsid);
+	if (rtnl_talk(&rth, &req.n, 0, 0, NULL) < 0)
+		err = -2;
+
+	close(fd);
+	return err;
+}
+
+static int netns_set(int argc, char **argv)
+{
+	char netns_path[MAXPATHLEN];
+	const char *name;
+	int netns, nsid;
+
+	if (argc < 1) {
+		fprintf(stderr, "No netns name specified\n");
+		return -1;
+	}
+	if (argc < 2) {
+		fprintf(stderr, "No nsid specified\n");
+		return -1;
+	}
+	name = argv[0];
+	nsid = atoi(argv[1]);
+
+	snprintf(netns_path, sizeof(netns_path), "%s/%s", NETNS_RUN_DIR, name);
+	netns = open(netns_path, O_RDONLY | O_CLOEXEC);
+	if (netns < 0) {
+		fprintf(stderr, "Cannot open network namespace \"%s\": %s\n",
+			name, strerror(errno));
+		return -1;
+	}
+
+	return set_netnsid_from_name(name, nsid);
+}
 
 static int netns_monitor(int argc, char **argv)
 {
@@ -410,6 +518,9 @@ int do_netns(int argc, char **argv)
 	if (matches(*argv, "add") == 0)
 		return netns_add(argc-1, argv+1);
 
+	if (matches(*argv, "set") == 0)
+		return netns_set(argc-1, argv+1);
+
 	if (matches(*argv, "delete") == 0)
 		return netns_delete(argc-1, argv+1);
 
diff --git a/man/man8/ip-netns.8 b/man/man8/ip-netns.8
index 74343ed6b640..95fc5e6b8a45 100644
--- a/man/man8/ip-netns.8
+++ b/man/man8/ip-netns.8
@@ -20,6 +20,10 @@ ip-netns \- process network namespace management
 .I NETNSNAME
 
 .ti -8
+.BR "ip netns" " { " set " } "
+.I NETNSNAME NETNSID
+
+.ti -8
 .BR "ip netns identify"
 .RI "[ " PID " ]"
 
@@ -85,6 +89,16 @@ persists until it has no more users.  ip netns delete may fail if
 the mount point is in use in another mount namespace.
 
 .TP
+.B ip netns set NAME NETNSID - assign an id to a peer network namespace
+.sp
+This command assigns a id to a peer network namespace. This id is valid
+only in the current network namespace.
+This id will be used by the kernel in some netlink messages. If no id is
+assigned when the kernel needs it, it will be automatically assigned by
+the kernel.
+Once it is assigned, it's not possible to change it.
+
+.TP
 .B ip netns identify [PID] - Report network namespaces names for process
 .sp
 This command walks through /var/run/netns and finds all the network
-- 
2.2.2

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

* [PATCH v2 iproute2-next 3/4] iplink: add support of IFLA_LINK_NETNSID attribute
  2015-01-28 14:15   ` [PATCH v2 iproute2-next 1/4] " Nicolas Dichtel
  2015-01-28 14:15     ` [PATCH v2 iproute2-next 2/4] ipnetns: allow to get and set netns ids Nicolas Dichtel
@ 2015-01-28 14:15     ` Nicolas Dichtel
  2015-01-28 14:15     ` [PATCH v2 iproute2-next 4/4] bridge/fdb: display link netns id Nicolas Dichtel
  2015-02-05 18:26     ` [PATCH v2 iproute2-next 1/4] include: update headers Stephen Hemminger
  3 siblings, 0 replies; 14+ messages in thread
From: Nicolas Dichtel @ 2015-01-28 14:15 UTC (permalink / raw)
  To: shemminger; +Cc: netdev, Nicolas Dichtel

This new attribute is now advertised by the kernel for x-netns interfaces.
It's also possible to set it when an interface is created (and thus creating a
x-netns interface with one single message).

Example:
 $ ip netns add foo
 $ ip netns add bar
 $ ip -n foo netns set bar 15
 $ ip -n foo link add ipip1 link-netnsid 15 type ipip remote 10.16.0.121 local 10.16.0.249
 $ ip -n foo link ls ipip1
 3: ipip1@NONE: <POINTOPOINT,NOARP> mtu 1480 qdisc noop state DOWN mode DEFAULT group default
     link/ipip 10.16.0.249 peer 10.16.0.121 link-netnsid 15

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

v2: don't try to convert IFLA_LINK to the devname when IFLA_LINK_NETNSID is set

 ip/ipaddress.c | 20 +++++++++++++++++---
 ip/iplink.c    | 10 ++++++++++
 2 files changed, 27 insertions(+), 3 deletions(-)

diff --git a/ip/ipaddress.c b/ip/ipaddress.c
index d5e863dd1f12..8bc28b8a12c8 100644
--- a/ip/ipaddress.c
+++ b/ip/ipaddress.c
@@ -28,6 +28,7 @@
 #include <linux/netdevice.h>
 #include <linux/if_arp.h>
 #include <linux/sockios.h>
+#include <linux/net_namespace.h>
 
 #include "rt_names.h"
 #include "utils.h"
@@ -614,9 +615,13 @@ int print_linkinfo(const struct sockaddr_nl *who,
 		if (iflink == 0)
 			fprintf(fp, "@NONE: ");
 		else {
-			fprintf(fp, "@%s: ", ll_idx_n2a(iflink, b1));
-			m_flag = ll_index_to_flags(iflink);
-			m_flag = !(m_flag & IFF_UP);
+			if (tb[IFLA_LINK_NETNSID])
+				fprintf(fp, "@if%d: ", iflink);
+			else {
+				fprintf(fp, "@%s: ", ll_idx_n2a(iflink, b1));
+				m_flag = ll_index_to_flags(iflink);
+				m_flag = !(m_flag & IFF_UP);
+			}
 		}
 	} else {
 		fprintf(fp, ": ");
@@ -678,6 +683,15 @@ int print_linkinfo(const struct sockaddr_nl *who,
 		}
 	}
 
+	if (tb[IFLA_LINK_NETNSID]) {
+		int id = *(int*)RTA_DATA(tb[IFLA_LINK_NETNSID]);
+
+		if (id >= 0)
+			fprintf(fp, " link-netnsid %d", id);
+		else
+			fprintf(fp, " link-netnsid unknown");
+	}
+
 	if (tb[IFLA_PROMISCUITY] && show_details)
 		fprintf(fp, " promiscuity %u ",
 			*(int*)RTA_DATA(tb[IFLA_PROMISCUITY]));
diff --git a/ip/iplink.c b/ip/iplink.c
index c93d1dc3d5f6..5893ee401cf9 100644
--- a/ip/iplink.c
+++ b/ip/iplink.c
@@ -72,6 +72,7 @@ void iplink_usage(void)
 	fprintf(stderr, "	                  [ mtu MTU ]\n");
 	fprintf(stderr, "	                  [ netns PID ]\n");
 	fprintf(stderr, "	                  [ netns NAME ]\n");
+	fprintf(stderr, "                         [ link-netnsid ID ]\n");
 	fprintf(stderr, "			  [ alias NAME ]\n");
 	fprintf(stderr, "	                  [ vf NUM [ mac LLADDR ]\n");
 	fprintf(stderr, "				   [ vlan VLANID [ qos VLAN-QOS ] ]\n");
@@ -386,6 +387,7 @@ int iplink_parse(int argc, char **argv, struct iplink_req *req,
 	int numtxqueues = -1;
 	int numrxqueues = -1;
 	int dev_index = 0;
+	int link_netnsid = -1;
 
 	*group = -1;
 	ret = argc;
@@ -588,6 +590,14 @@ int iplink_parse(int argc, char **argv, struct iplink_req *req,
 			addattr8(&req->n, sizeof(*req), IFLA_INET6_ADDR_GEN_MODE, mode);
 			addattr_nest_end(&req->n, afs6);
 			addattr_nest_end(&req->n, afs);
+		} else if (matches(*argv, "link-netnsid") == 0) {
+			NEXT_ARG();
+			if (link_netnsid != -1)
+				duparg("link-netnsid", *argv);
+			if (get_integer(&link_netnsid, *argv, 0))
+				invarg("Invalid \"link-netnsid\" value\n", *argv);
+			addattr32(&req->n, sizeof(*req), IFLA_LINK_NETNSID,
+				  link_netnsid);
 		} else {
 			if (strcmp(*argv, "dev") == 0) {
 				NEXT_ARG();
-- 
2.2.2

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

* [PATCH v2 iproute2-next 4/4] bridge/fdb: display link netns id
  2015-01-28 14:15   ` [PATCH v2 iproute2-next 1/4] " Nicolas Dichtel
  2015-01-28 14:15     ` [PATCH v2 iproute2-next 2/4] ipnetns: allow to get and set netns ids Nicolas Dichtel
  2015-01-28 14:15     ` [PATCH v2 iproute2-next 3/4] iplink: add support of IFLA_LINK_NETNSID attribute Nicolas Dichtel
@ 2015-01-28 14:15     ` Nicolas Dichtel
  2015-02-05 18:26     ` [PATCH v2 iproute2-next 1/4] include: update headers Stephen Hemminger
  3 siblings, 0 replies; 14+ messages in thread
From: Nicolas Dichtel @ 2015-01-28 14:15 UTC (permalink / raw)
  To: shemminger; +Cc: netdev, Nicolas Dichtel

When this attribute is set, it means that the i/o part of the related netdevice
is in another netns.

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

v2: new in the series

 bridge/fdb.c | 6 +++++-
 1 file changed, 5 insertions(+), 1 deletion(-)

diff --git a/bridge/fdb.c b/bridge/fdb.c
index c01a5020de63..6941edd90f90 100644
--- a/bridge/fdb.c
+++ b/bridge/fdb.c
@@ -131,12 +131,16 @@ int print_fdb(const struct sockaddr_nl *who, struct nlmsghdr *n, void *arg)
 		if (ifindex) {
 			char ifname[IF_NAMESIZE];
 
-			if (if_indextoname(ifindex, ifname))
+			if (!tb[NDA_LINK_NETNSID] &&
+			    if_indextoname(ifindex, ifname))
 				fprintf(fp, "via %s ", ifname);
 			else
 				fprintf(fp, "via ifindex %u ", ifindex);
 		}
 	}
+	if (tb[NDA_LINK_NETNSID])
+		fprintf(fp, "link-netnsid %d ",
+			rta_getattr_u32(tb[NDA_LINK_NETNSID]));
 
 	if (show_stats && tb[NDA_CACHEINFO]) {
 		struct nda_cacheinfo *ci = RTA_DATA(tb[NDA_CACHEINFO]);
-- 
2.2.2

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

* Re: [PATCH v2 iproute2-next 1/4] include: update headers
  2015-01-28 14:15   ` [PATCH v2 iproute2-next 1/4] " Nicolas Dichtel
                       ` (2 preceding siblings ...)
  2015-01-28 14:15     ` [PATCH v2 iproute2-next 4/4] bridge/fdb: display link netns id Nicolas Dichtel
@ 2015-02-05 18:26     ` Stephen Hemminger
  2015-02-06  9:02       ` Nicolas Dichtel
  3 siblings, 1 reply; 14+ messages in thread
From: Stephen Hemminger @ 2015-02-05 18:26 UTC (permalink / raw)
  To: Nicolas Dichtel; +Cc: shemminger, netdev

On Wed, 28 Jan 2015 15:15:47 +0100
Nicolas Dichtel <nicolas.dichtel@6wind.com> wrote:

> Copy from sanitized headers.
> 
> Signed-off-by: Nicolas Dichtel <nicolas.dichtel@6wind.com>
> ---
> 
> v2: took last headers from net-next
> 
>  include/linux/if_link.h       |  4 ++++
>  include/linux/neighbour.h     |  1 +
>  include/linux/net_namespace.h | 23 +++++++++++++++++++++++
>  include/linux/rtnetlink.h     |  5 +++++
>  4 files changed, 33 insertions(+)
>  create mode 100644 include/linux/net_namespace.h

All kernel headers for iproute2 must come from the result of:
  $ make headers_install

Please submit a patch to net-next which makes net_namespace.h
(from include/uapi/linux/net_namespace.h) get correctly installed into
usr/include/linux/net_namespace.h

The file is missing from include/uapi/linux/Kbuild

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

* Re: [PATCH v2 iproute2-next 1/4] include: update headers
  2015-02-05 18:26     ` [PATCH v2 iproute2-next 1/4] include: update headers Stephen Hemminger
@ 2015-02-06  9:02       ` Nicolas Dichtel
  2015-02-17 16:30         ` [PATCH v3 iproute2 " Nicolas Dichtel
  0 siblings, 1 reply; 14+ messages in thread
From: Nicolas Dichtel @ 2015-02-06  9:02 UTC (permalink / raw)
  To: Stephen Hemminger; +Cc: shemminger, netdev

Le 05/02/2015 19:26, Stephen Hemminger a écrit :
> On Wed, 28 Jan 2015 15:15:47 +0100
> Nicolas Dichtel <nicolas.dichtel@6wind.com> wrote:
>
>> Copy from sanitized headers.
>>
>> Signed-off-by: Nicolas Dichtel <nicolas.dichtel@6wind.com>
>> ---
>>
>> v2: took last headers from net-next
>>
>>   include/linux/if_link.h       |  4 ++++
>>   include/linux/neighbour.h     |  1 +
>>   include/linux/net_namespace.h | 23 +++++++++++++++++++++++
>>   include/linux/rtnetlink.h     |  5 +++++
>>   4 files changed, 33 insertions(+)
>>   create mode 100644 include/linux/net_namespace.h
>
> All kernel headers for iproute2 must come from the result of:
>    $ make headers_install
I've done this.

>
> Please submit a patch to net-next which makes net_namespace.h
> (from include/uapi/linux/net_namespace.h) get correctly installed into
> usr/include/linux/net_namespace.h
>
> The file is missing from include/uapi/linux/Kbuild
Hmm, I'm probably missing something (with net-next):
$ git grep net_namespace.h include/uapi/linux/Kbuild
include/uapi/linux/Kbuild:header-y += net_namespace.h
$ rm -rf usr/include/
$ make headers_install
$ find usr/include/ -name net_namespace.h
usr/include/linux/net_namespace.h

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

* [PATCH v3 iproute2 1/4] include: update headers
  2015-02-06  9:02       ` Nicolas Dichtel
@ 2015-02-17 16:30         ` Nicolas Dichtel
  2015-02-17 16:30           ` [PATCH v3 iproute2 2/4] ipnetns: allow to get and set netns ids Nicolas Dichtel
                             ` (2 more replies)
  0 siblings, 3 replies; 14+ messages in thread
From: Nicolas Dichtel @ 2015-02-17 16:30 UTC (permalink / raw)
  To: shemminger; +Cc: netdev, Nicolas Dichtel

Copy from sanitized headers.

Signed-off-by: Nicolas Dichtel <nicolas.dichtel@6wind.com>
---
v3: rebase on master branch
v2: took last headers from net-next

 include/linux/net_namespace.h | 23 +++++++++++++++++++++++
 1 file changed, 23 insertions(+)
 create mode 100644 include/linux/net_namespace.h

diff --git a/include/linux/net_namespace.h b/include/linux/net_namespace.h
new file mode 100644
index 000000000000..9a92b7e14a19
--- /dev/null
+++ b/include/linux/net_namespace.h
@@ -0,0 +1,23 @@
+/* Copyright (c) 2015 6WIND S.A.
+ * Author: Nicolas Dichtel <nicolas.dichtel@6wind.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ */
+#ifndef _LINUX_NET_NAMESPACE_H_
+#define _LINUX_NET_NAMESPACE_H_
+
+/* Attributes of RTM_NEWNSID/RTM_GETNSID messages */
+enum {
+	NETNSA_NONE,
+#define NETNSA_NSID_NOT_ASSIGNED -1
+	NETNSA_NSID,
+	NETNSA_PID,
+	NETNSA_FD,
+	__NETNSA_MAX,
+};
+
+#define NETNSA_MAX		(__NETNSA_MAX - 1)
+
+#endif /* _LINUX_NET_NAMESPACE_H_ */
-- 
2.2.2

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

* [PATCH v3 iproute2 2/4] ipnetns: allow to get and set netns ids
  2015-02-17 16:30         ` [PATCH v3 iproute2 " Nicolas Dichtel
@ 2015-02-17 16:30           ` Nicolas Dichtel
  2015-02-17 16:30           ` [PATCH v3 iproute2 3/4] iplink: add support of IFLA_LINK_NETNSID attribute Nicolas Dichtel
  2015-02-17 16:30           ` [PATCH v3 iproute2 4/4] bridge/fdb: display link netns id Nicolas Dichtel
  2 siblings, 0 replies; 14+ messages in thread
From: Nicolas Dichtel @ 2015-02-17 16:30 UTC (permalink / raw)
  To: shemminger; +Cc: netdev, Nicolas Dichtel

The kernel now provides ids for peer netns. This patch implements a new command
'set' to assign an id.
When netns are listed, if an id is assigned, it is now displayed.

Example:
 $ ip netns add foo
 $ ip netns set foo 1
 $ ip netns
 foo (id: 1)
 init_net

Signed-off-by: Nicolas Dichtel <nicolas.dichtel@6wind.com>
---
v3: rebase on master branch
v2: no change

 include/libnetlink.h |   8 ++++
 ip/ipnetns.c         | 113 ++++++++++++++++++++++++++++++++++++++++++++++++++-
 man/man8/ip-netns.8  |  14 +++++++
 3 files changed, 134 insertions(+), 1 deletion(-)

diff --git a/include/libnetlink.h b/include/libnetlink.h
index d081e54210ea..898275b824d4 100644
--- a/include/libnetlink.h
+++ b/include/libnetlink.h
@@ -158,6 +158,14 @@ extern int rtnl_from_file(FILE *, rtnl_filter_t handler,
 #define NDTA_PAYLOAD(n) NLMSG_PAYLOAD(n,sizeof(struct ndtmsg))
 #endif
 
+#ifndef NETNS_RTA
+#define NETNS_RTA(r) \
+	((struct rtattr*)(((char*)(r)) + NLMSG_ALIGN(sizeof(struct rtgenmsg))))
+#endif
+#ifndef NETNS_PAYLOAD
+#define NETNS_PAYLOAD(n)	NLMSG_PAYLOAD(n,sizeof(struct rtgenmsg))
+#endif
+
 /* User defined nlmsg_type which is used mostly for logging netlink
  * messages from dump file */
 #define NLMSG_TSTAMP	15
diff --git a/ip/ipnetns.c b/ip/ipnetns.c
index e4038ea72d71..5a213dcf46cd 100644
--- a/ip/ipnetns.c
+++ b/ip/ipnetns.c
@@ -15,6 +15,8 @@
 #include <unistd.h>
 #include <ctype.h>
 
+#include <linux/net_namespace.h>
+
 #include "utils.h"
 #include "ip_common.h"
 #include "namespace.h"
@@ -23,6 +25,7 @@ static int usage(void)
 {
 	fprintf(stderr, "Usage: ip netns list\n");
 	fprintf(stderr, "       ip netns add NAME\n");
+	fprintf(stderr, "       ip netns set NAME NETNSID\n");
 	fprintf(stderr, "       ip [-all] netns delete [NAME]\n");
 	fprintf(stderr, "       ip netns identify [PID]\n");
 	fprintf(stderr, "       ip netns pids NAME\n");
@@ -31,10 +34,56 @@ static int usage(void)
 	exit(-1);
 }
 
+static int get_netnsid_from_name(const char *name)
+{
+	struct {
+		struct nlmsghdr n;
+		struct rtgenmsg g;
+		char            buf[1024];
+	} req, answer;
+	struct rtattr *tb[NETNSA_MAX + 1];
+	struct rtgenmsg *rthdr;
+	int len, fd;
+
+	memset(&req, 0, sizeof(req));
+	req.n.nlmsg_len = NLMSG_LENGTH(sizeof(struct rtgenmsg));
+	req.n.nlmsg_flags = NLM_F_REQUEST;
+	req.n.nlmsg_type = RTM_GETNSID;
+	req.g.rtgen_family = AF_UNSPEC;
+
+	fd = netns_get_fd(name);
+	if (fd < 0)
+		return fd;
+
+	addattr32(&req.n, 1024, NETNSA_FD, fd);
+	if (rtnl_talk(&rth, &req.n, 0, 0, &answer.n) < 0) {
+		close(fd);
+		return -2;
+	}
+	close(fd);
+
+	/* Validate message and parse attributes */
+	if (answer.n.nlmsg_type == NLMSG_ERROR)
+		return -1;
+
+	rthdr = NLMSG_DATA(&answer.n);
+	len = answer.n.nlmsg_len - NLMSG_SPACE(sizeof(*rthdr));
+	if (len < 0)
+		return -1;
+
+	parse_rtattr(tb, NETNSA_MAX, NETNS_RTA(rthdr), len);
+
+	if (tb[NETNSA_NSID])
+		return rta_getattr_u32(tb[NETNSA_NSID]);
+
+	return -1;
+}
+
 static int netns_list(int argc, char **argv)
 {
 	struct dirent *entry;
 	DIR *dir;
+	int id;
 
 	dir = opendir(NETNS_RUN_DIR);
 	if (!dir)
@@ -45,7 +94,11 @@ static int netns_list(int argc, char **argv)
 			continue;
 		if (strcmp(entry->d_name, "..") == 0)
 			continue;
-		printf("%s\n", entry->d_name);
+		printf("%s", entry->d_name);
+		id = get_netnsid_from_name(entry->d_name);
+		if (id >= 0)
+			printf(" (id: %d)", id);
+		printf("\n");
 	}
 	closedir(dir);
 	return 0;
@@ -375,6 +428,61 @@ out_delete:
 	return -1;
 }
 
+static int set_netnsid_from_name(const char *name, int nsid)
+{
+	struct {
+		struct nlmsghdr n;
+		struct rtgenmsg g;
+		char            buf[1024];
+	} req;
+	int fd, err = 0;
+
+	memset(&req, 0, sizeof(req));
+	req.n.nlmsg_len = NLMSG_LENGTH(sizeof(struct rtgenmsg));
+	req.n.nlmsg_flags = NLM_F_REQUEST;
+	req.n.nlmsg_type = RTM_NEWNSID;
+	req.g.rtgen_family = AF_UNSPEC;
+
+	fd = netns_get_fd(name);
+	if (fd < 0)
+		return fd;
+
+	addattr32(&req.n, 1024, NETNSA_FD, fd);
+	addattr32(&req.n, 1024, NETNSA_NSID, nsid);
+	if (rtnl_talk(&rth, &req.n, 0, 0, NULL) < 0)
+		err = -2;
+
+	close(fd);
+	return err;
+}
+
+static int netns_set(int argc, char **argv)
+{
+	char netns_path[MAXPATHLEN];
+	const char *name;
+	int netns, nsid;
+
+	if (argc < 1) {
+		fprintf(stderr, "No netns name specified\n");
+		return -1;
+	}
+	if (argc < 2) {
+		fprintf(stderr, "No nsid specified\n");
+		return -1;
+	}
+	name = argv[0];
+	nsid = atoi(argv[1]);
+
+	snprintf(netns_path, sizeof(netns_path), "%s/%s", NETNS_RUN_DIR, name);
+	netns = open(netns_path, O_RDONLY | O_CLOEXEC);
+	if (netns < 0) {
+		fprintf(stderr, "Cannot open network namespace \"%s\": %s\n",
+			name, strerror(errno));
+		return -1;
+	}
+
+	return set_netnsid_from_name(name, nsid);
+}
 
 static int netns_monitor(int argc, char **argv)
 {
@@ -430,6 +538,9 @@ int do_netns(int argc, char **argv)
 	if (matches(*argv, "add") == 0)
 		return netns_add(argc-1, argv+1);
 
+	if (matches(*argv, "set") == 0)
+		return netns_set(argc-1, argv+1);
+
 	if (matches(*argv, "delete") == 0)
 		return netns_delete(argc-1, argv+1);
 
diff --git a/man/man8/ip-netns.8 b/man/man8/ip-netns.8
index 8e6999c0abcb..28a9544143e5 100644
--- a/man/man8/ip-netns.8
+++ b/man/man8/ip-netns.8
@@ -24,6 +24,10 @@ ip-netns \- process network namespace management
 .RI "[ " NETNSNAME " ]"
 
 .ti -8
+.BR "ip netns" " { " set " } "
+.I NETNSNAME NETNSID
+
+.ti -8
 .BR "ip netns identify"
 .RI "[ " PID " ]"
 
@@ -93,6 +97,16 @@ If
 option was specified then all the network namespace names will be removed.
 
 .TP
+.B ip netns set NAME NETNSID - assign an id to a peer network namespace
+.sp
+This command assigns a id to a peer network namespace. This id is valid
+only in the current network namespace.
+This id will be used by the kernel in some netlink messages. If no id is
+assigned when the kernel needs it, it will be automatically assigned by
+the kernel.
+Once it is assigned, it's not possible to change it.
+
+.TP
 .B ip netns identify [PID] - Report network namespaces names for process
 .sp
 This command walks through /var/run/netns and finds all the network
-- 
2.2.2

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

* [PATCH v3 iproute2 3/4] iplink: add support of IFLA_LINK_NETNSID attribute
  2015-02-17 16:30         ` [PATCH v3 iproute2 " Nicolas Dichtel
  2015-02-17 16:30           ` [PATCH v3 iproute2 2/4] ipnetns: allow to get and set netns ids Nicolas Dichtel
@ 2015-02-17 16:30           ` Nicolas Dichtel
  2015-02-17 16:30           ` [PATCH v3 iproute2 4/4] bridge/fdb: display link netns id Nicolas Dichtel
  2 siblings, 0 replies; 14+ messages in thread
From: Nicolas Dichtel @ 2015-02-17 16:30 UTC (permalink / raw)
  To: shemminger; +Cc: netdev, Nicolas Dichtel

This new attribute is now advertised by the kernel for x-netns interfaces.
It's also possible to set it when an interface is created (and thus creating a
x-netns interface with one single message).

Example:
 $ ip netns add foo
 $ ip netns add bar
 $ ip -n foo netns set bar 15
 $ ip -n foo link add ipip1 link-netnsid 15 type ipip remote 10.16.0.121 local 10.16.0.249
 $ ip -n foo link ls ipip1
 3: ipip1@NONE: <POINTOPOINT,NOARP> mtu 1480 qdisc noop state DOWN mode DEFAULT group default
     link/ipip 10.16.0.249 peer 10.16.0.121 link-netnsid 15

Signed-off-by: Nicolas Dichtel <nicolas.dichtel@6wind.com>
---
v3: rebase on master branch
v2: don't try to convert IFLA_LINK to the devname when IFLA_LINK_NETNSID is set

 ip/ipaddress.c | 20 +++++++++++++++++---
 ip/iplink.c    | 10 ++++++++++
 2 files changed, 27 insertions(+), 3 deletions(-)

diff --git a/ip/ipaddress.c b/ip/ipaddress.c
index 3730424ad8cd..99a6ab5977e3 100644
--- a/ip/ipaddress.c
+++ b/ip/ipaddress.c
@@ -28,6 +28,7 @@
 #include <linux/netdevice.h>
 #include <linux/if_arp.h>
 #include <linux/sockios.h>
+#include <linux/net_namespace.h>
 
 #include "rt_names.h"
 #include "utils.h"
@@ -614,9 +615,13 @@ int print_linkinfo(const struct sockaddr_nl *who,
 		if (iflink == 0)
 			fprintf(fp, "@NONE: ");
 		else {
-			fprintf(fp, "@%s: ", ll_idx_n2a(iflink, b1));
-			m_flag = ll_index_to_flags(iflink);
-			m_flag = !(m_flag & IFF_UP);
+			if (tb[IFLA_LINK_NETNSID])
+				fprintf(fp, "@if%d: ", iflink);
+			else {
+				fprintf(fp, "@%s: ", ll_idx_n2a(iflink, b1));
+				m_flag = ll_index_to_flags(iflink);
+				m_flag = !(m_flag & IFF_UP);
+			}
 		}
 	} else {
 		fprintf(fp, ": ");
@@ -678,6 +683,15 @@ int print_linkinfo(const struct sockaddr_nl *who,
 		}
 	}
 
+	if (tb[IFLA_LINK_NETNSID]) {
+		int id = *(int*)RTA_DATA(tb[IFLA_LINK_NETNSID]);
+
+		if (id >= 0)
+			fprintf(fp, " link-netnsid %d", id);
+		else
+			fprintf(fp, " link-netnsid unknown");
+	}
+
 	if (tb[IFLA_PROMISCUITY] && show_details)
 		fprintf(fp, " promiscuity %u ",
 			*(int*)RTA_DATA(tb[IFLA_PROMISCUITY]));
diff --git a/ip/iplink.c b/ip/iplink.c
index c93d1dc3d5f6..5893ee401cf9 100644
--- a/ip/iplink.c
+++ b/ip/iplink.c
@@ -72,6 +72,7 @@ void iplink_usage(void)
 	fprintf(stderr, "	                  [ mtu MTU ]\n");
 	fprintf(stderr, "	                  [ netns PID ]\n");
 	fprintf(stderr, "	                  [ netns NAME ]\n");
+	fprintf(stderr, "                         [ link-netnsid ID ]\n");
 	fprintf(stderr, "			  [ alias NAME ]\n");
 	fprintf(stderr, "	                  [ vf NUM [ mac LLADDR ]\n");
 	fprintf(stderr, "				   [ vlan VLANID [ qos VLAN-QOS ] ]\n");
@@ -386,6 +387,7 @@ int iplink_parse(int argc, char **argv, struct iplink_req *req,
 	int numtxqueues = -1;
 	int numrxqueues = -1;
 	int dev_index = 0;
+	int link_netnsid = -1;
 
 	*group = -1;
 	ret = argc;
@@ -588,6 +590,14 @@ int iplink_parse(int argc, char **argv, struct iplink_req *req,
 			addattr8(&req->n, sizeof(*req), IFLA_INET6_ADDR_GEN_MODE, mode);
 			addattr_nest_end(&req->n, afs6);
 			addattr_nest_end(&req->n, afs);
+		} else if (matches(*argv, "link-netnsid") == 0) {
+			NEXT_ARG();
+			if (link_netnsid != -1)
+				duparg("link-netnsid", *argv);
+			if (get_integer(&link_netnsid, *argv, 0))
+				invarg("Invalid \"link-netnsid\" value\n", *argv);
+			addattr32(&req->n, sizeof(*req), IFLA_LINK_NETNSID,
+				  link_netnsid);
 		} else {
 			if (strcmp(*argv, "dev") == 0) {
 				NEXT_ARG();
-- 
2.2.2

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

* [PATCH v3 iproute2 4/4] bridge/fdb: display link netns id
  2015-02-17 16:30         ` [PATCH v3 iproute2 " Nicolas Dichtel
  2015-02-17 16:30           ` [PATCH v3 iproute2 2/4] ipnetns: allow to get and set netns ids Nicolas Dichtel
  2015-02-17 16:30           ` [PATCH v3 iproute2 3/4] iplink: add support of IFLA_LINK_NETNSID attribute Nicolas Dichtel
@ 2015-02-17 16:30           ` Nicolas Dichtel
  2 siblings, 0 replies; 14+ messages in thread
From: Nicolas Dichtel @ 2015-02-17 16:30 UTC (permalink / raw)
  To: shemminger; +Cc: netdev, Nicolas Dichtel

When this attribute is set, it means that the i/o part of the related netdevice
is in another netns.

Signed-off-by: Nicolas Dichtel <nicolas.dichtel@6wind.com>
---
v3: rebase on master branch
v2: new in the series

 bridge/fdb.c | 6 +++++-
 1 file changed, 5 insertions(+), 1 deletion(-)

diff --git a/bridge/fdb.c b/bridge/fdb.c
index c01a5020de63..6941edd90f90 100644
--- a/bridge/fdb.c
+++ b/bridge/fdb.c
@@ -131,12 +131,16 @@ int print_fdb(const struct sockaddr_nl *who, struct nlmsghdr *n, void *arg)
 		if (ifindex) {
 			char ifname[IF_NAMESIZE];
 
-			if (if_indextoname(ifindex, ifname))
+			if (!tb[NDA_LINK_NETNSID] &&
+			    if_indextoname(ifindex, ifname))
 				fprintf(fp, "via %s ", ifname);
 			else
 				fprintf(fp, "via ifindex %u ", ifindex);
 		}
 	}
+	if (tb[NDA_LINK_NETNSID])
+		fprintf(fp, "link-netnsid %d ",
+			rta_getattr_u32(tb[NDA_LINK_NETNSID]));
 
 	if (show_stats && tb[NDA_CACHEINFO]) {
 		struct nda_cacheinfo *ci = RTA_DATA(tb[NDA_CACHEINFO]);
-- 
2.2.2

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

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

Thread overview: 14+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2015-01-20 10:36 [PATCH iproute2-next 1/3] include: update headers Nicolas Dichtel
2015-01-20 10:36 ` [PATCH iproute2-next 2/3] ipnetns: allow to get and set netns ids Nicolas Dichtel
2015-01-20 10:36 ` [PATCH iproute2-next 3/3] iplink: add support of IFLA_LINK_NETNSID attribute Nicolas Dichtel
2015-01-28 13:28 ` [PATCH iproute2-next 1/3] include: update headers Nicolas Dichtel
2015-01-28 14:15   ` [PATCH v2 iproute2-next 1/4] " Nicolas Dichtel
2015-01-28 14:15     ` [PATCH v2 iproute2-next 2/4] ipnetns: allow to get and set netns ids Nicolas Dichtel
2015-01-28 14:15     ` [PATCH v2 iproute2-next 3/4] iplink: add support of IFLA_LINK_NETNSID attribute Nicolas Dichtel
2015-01-28 14:15     ` [PATCH v2 iproute2-next 4/4] bridge/fdb: display link netns id Nicolas Dichtel
2015-02-05 18:26     ` [PATCH v2 iproute2-next 1/4] include: update headers Stephen Hemminger
2015-02-06  9:02       ` Nicolas Dichtel
2015-02-17 16:30         ` [PATCH v3 iproute2 " Nicolas Dichtel
2015-02-17 16:30           ` [PATCH v3 iproute2 2/4] ipnetns: allow to get and set netns ids Nicolas Dichtel
2015-02-17 16:30           ` [PATCH v3 iproute2 3/4] iplink: add support of IFLA_LINK_NETNSID attribute Nicolas Dichtel
2015-02-17 16:30           ` [PATCH v3 iproute2 4/4] bridge/fdb: display link netns id Nicolas Dichtel

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).