All of lore.kernel.org
 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 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.