netdev.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: Saurabh Mohan <saurabh@cplanenetworks.com>
To: <netdev@vger.kernel.org>, <stephen@networkplumber.org>,
	<davem@davemloft.net>, <pshelar@nicira.com>, <tgraf@suug.ch>
Cc: Saurabh Mohan <saurabh@cplanenetworks.com>
Subject: [PATCH iproute2] Support outside netns for tunnels.
Date: Mon, 4 Jan 2016 10:46:51 -0800	[thread overview]
Message-ID: <1451933211-17330-1-git-send-email-saurabh@cplanenetworks.com> (raw)


This patch enchances a tunnel interface, like gre, to have the tunnel
encap/decap be in the context of a network namespace that is different from 
the namespace of the tunnel interface.

>From userspace this feature may be configured using the new 'onetns' keyword:
ip netns exec custa ip link add dev tun1 type gre local 10.0.0.1 \
 remote 10.0.0.2 onetns outside 

In the above example the tunnel would be in the 'custa' namespace and the 
tunnel endpoints would be in the 'outside' namespace.

Also, proposing the use of netns name 'global' to specify the global namespace.

If this patch set is accepted then I will add support for other tunnels as 
well.

Signed-off-by: Saurabh Mohan <saurabh@cplanenetworks.com>
---
 ip/iptunnel.c | 27 +++++++++++++++++++++++++++
 ip/link_gre.c | 43 +++++++++++++++++++++++++++++++++++++++++++
 ip/link_vti.c | 41 +++++++++++++++++++++++++++++++++++++++++
 3 files changed, 111 insertions(+)

diff --git a/ip/iptunnel.c b/ip/iptunnel.c
index 65a4e6e..8165a38 100644
--- a/ip/iptunnel.c
+++ b/ip/iptunnel.c
@@ -27,6 +27,7 @@
 #include "utils.h"
 #include "ip_common.h"
 #include "tunnel.h"
+#include "namespace.h"
 
 static void usage(void) __attribute__((noreturn));
 
@@ -38,6 +39,7 @@ static void usage(void)
 	fprintf(stderr, "          [ prl-default ADDR ] [ prl-nodefault ADDR ] [ prl-delete ADDR ]\n");
 	fprintf(stderr, "          [ 6rd-prefix ADDR ] [ 6rd-relay_prefix ADDR ] [ 6rd-reset ]\n");
 	fprintf(stderr, "          [ ttl TTL ] [ tos TOS ] [ [no]pmtudisc ] [ dev PHYS_DEV ]\n");
+	fprintf(stderr, "          [ onetns NAME ]\n");
 	fprintf(stderr, "\n");
 	fprintf(stderr, "Where: NAME := STRING\n");
 	fprintf(stderr, "       ADDR := { IP_ADDRESS | any }\n");
@@ -172,6 +174,22 @@ static int parse_args(int argc, char **argv, int cmd, struct ip_tunnel_parm *p)
 					invarg("bad TOS value", *argv);
 				p->iph.tos |= uval;
 			}
+		} else if (strcmp(*argv, "onetns") == 0) {
+			NEXT_ARG();
+			if (strcmp(*argv, "global") == 0)
+				p->o_net.o_netns_flag |=
+					TUNNEL_ONETNS_FLAG_GLOBAL;
+			else {
+				p->o_net.o_netns_fd = netns_get_fd(*argv);
+				if (p->o_net.o_netns_fd < 0)
+					invarg("bad netns name %s\n", *argv);
+				else {
+					p->o_net.o_netns_flag |=
+						TUNNEL_ONETNS_FLAG_NETNS;
+					strncpy(p->o_net.netns, *argv,
+						sizeof(p->o_net.netns));
+				}
+			}
 		} else {
 			if (strcmp(*argv, "name") == 0)
 				NEXT_ARG();
@@ -374,6 +392,11 @@ static void print_tunnel(struct ip_tunnel_parm *p)
 			printf(" okey %u", ntohl(p->o_key));
 	}
 
+	if (p->o_net.o_netns_flag & TUNNEL_ONETNS_FLAG_GLOBAL)
+		printf(" onetns global ");
+	if (p->o_net.o_netns_flag & TUNNEL_ONETNS_FLAG_NETNS)
+		printf(" onetns %s ", p->o_net.netns);
+
 	if (p->i_flags & GRE_SEQ)
 		printf("%s  Drop packets out of sequence.", _SL_);
 	if (p->i_flags & GRE_CSUM)
@@ -401,6 +424,10 @@ static int do_tunnels_list(struct ip_tunnel_parm *p)
 		fprintf(stderr, "/proc/net/dev read error\n");
 		goto end;
 	}
+	if (p->o_net.o_netns_flag & TUNNEL_ONETNS_FLAG_GLOBAL)
+		printf(" onetns global ");
+	if (p->o_net.o_netns_flag & TUNNEL_ONETNS_FLAG_NETNS)
+		printf(" onetns %s ", p->o_net.netns);
 
 	while (fgets(buf, sizeof(buf), fp) != NULL) {
 		char name[IFNAMSIZ];
diff --git a/ip/link_gre.c b/ip/link_gre.c
index c85741f..4f51aa4 100644
--- a/ip/link_gre.c
+++ b/ip/link_gre.c
@@ -22,6 +22,7 @@
 #include "utils.h"
 #include "ip_common.h"
 #include "tunnel.h"
+#include "namespace.h"
 
 static void print_usage(FILE *f)
 {
@@ -32,6 +33,7 @@ static void print_usage(FILE *f)
 	fprintf(f, "          [ noencap ] [ encap { fou | gue | none } ]\n");
 	fprintf(f, "          [ encap-sport PORT ] [ encap-dport PORT ]\n");
 	fprintf(f, "          [ [no]encap-csum ] [ [no]encap-csum6 ] [ [no]encap-remcsum ]\n");
+	fprintf(f, "          [ onetns NAME ]\n");
 	fprintf(f, "\n");
 	fprintf(f, "Where: NAME := STRING\n");
 	fprintf(f, "       ADDR := { IP_ADDRESS | any }\n");
@@ -75,6 +77,9 @@ static int gre_parse_opt(struct link_util *lu, int argc, char **argv,
 	__u16 encapsport = 0;
 	__u16 encapdport = 0;
 	__u8 metadata = 0;
+	__u32 o_netns = 0;
+	__u8 o_netns_flag = 0;
+	char netns_name[NAME_MAX];
 
 	if (!(n->nlmsg_flags & NLM_F_CREATE)) {
 		memset(&req, 0, sizeof(req));
@@ -152,6 +157,14 @@ get_failed:
 
 		if (greinfo[IFLA_GRE_COLLECT_METADATA])
 			metadata = 1;
+		if (greinfo[IFLA_GRE_ONETNS_FLAGS])
+			o_netns_flag = rta_getattr_u8(
+						greinfo[IFLA_GRE_ONETNS_FLAGS]);
+		if (greinfo[IFLA_GRE_ONETNS_FD])
+			o_netns = rta_getattr_u32(greinfo[IFLA_GRE_ONETNS_FD]);
+		if (greinfo[IFLA_GRE_ONETNS_NAME])
+			netns_name[0] = '\0';
+
 	}
 
 	while (argc > 0) {
@@ -297,6 +310,21 @@ get_failed:
 			encapflags |= ~TUNNEL_ENCAP_FLAG_REMCSUM;
 		} else if (strcmp(*argv, "external") == 0) {
 			metadata = 1;
+		} else if (strcmp(*argv, "onetns") == 0) {
+			NEXT_ARG();
+			if (strcmp(*argv, "global") == 0)
+				o_netns_flag |= TUNNEL_ONETNS_FLAG_GLOBAL;
+			else {
+				o_netns = netns_get_fd(*argv);
+				if (o_netns < 0)
+					invarg("invalid onetns %s\n", *argv);
+				else {
+					o_netns_flag |=
+						TUNNEL_ONETNS_FLAG_NETNS;
+					strncpy(netns_name, *argv,
+						sizeof(netns_name));
+				}
+			}
 		} else
 			usage();
 		argc--; argv++;
@@ -333,6 +361,9 @@ get_failed:
 	addattr16(n, 1024, IFLA_GRE_ENCAP_DPORT, htons(encapdport));
 	if (metadata)
 		addattr_l(n, 1024, IFLA_GRE_COLLECT_METADATA, NULL, 0);
+	addattr8(n, 1024, IFLA_IPTUN_ONETNS_FLAGS, o_netns_flag);
+	addattr_l(n, 1024, IFLA_GRE_ONETNS_FD, &o_netns, 1);
+	addattrstrz(n, 1024, IFLA_GRE_ONETNS_NAME, netns_name);
 
 	return 0;
 }
@@ -345,6 +376,7 @@ static void gre_print_opt(struct link_util *lu, FILE *f, struct rtattr *tb[])
 	const char *remote = "any";
 	unsigned iflags = 0;
 	unsigned oflags = 0;
+	__u8 o_netns_flag = 0;
 
 	if (!tb)
 		return;
@@ -466,6 +498,17 @@ static void gre_print_opt(struct link_util *lu, FILE *f, struct rtattr *tb[])
 		else
 			fputs("noencap-remcsum ", f);
 	}
+	if (tb[IFLA_GRE_ONETNS_FLAGS]) {
+		o_netns_flag = rta_getattr_u8(tb[IFLA_GRE_ONETNS_FLAGS]);
+		if (o_netns_flag & TUNNEL_ONETNS_FLAG_GLOBAL)
+			fprintf(f, "onetns global ");
+	}
+	if ((o_netns_flag & TUNNEL_ONETNS_FLAG_NETNS) &&
+	    tb[IFLA_GRE_ONETNS_NAME]) {
+		const char *name = rta_getattr_str(tb[IFLA_GRE_ONETNS_NAME]);
+
+		fprintf(f, "onetns %s ", name);
+	}
 }
 
 static void gre_print_help(struct link_util *lu, int argc, char **argv,
diff --git a/ip/link_vti.c b/ip/link_vti.c
index f3fea33..7f6d4ae 100644
--- a/ip/link_vti.c
+++ b/ip/link_vti.c
@@ -30,6 +30,7 @@ static void print_usage(FILE *f)
 	fprintf(f, "          type { vti } [ remote ADDR ] [ local ADDR ]\n");
 	fprintf(f, "          [ [i|o]key KEY ]\n");
 	fprintf(f, "          [ dev PHYS_DEV ]\n");
+	fprintf(f, "          [ onetns NAME ]\n");
 	fprintf(f, "\n");
 	fprintf(f, "Where: NAME := STRING\n");
 	fprintf(f, "       ADDR := { IP_ADDRESS }\n");
@@ -61,6 +62,9 @@ static int vti_parse_opt(struct link_util *lu, int argc, char **argv,
 	unsigned daddr = 0;
 	unsigned link = 0;
 	int len;
+	__u32 o_netns = 0;
+	__u8  o_netns_flag = 0;
+	char netns_name[NAME_MAX];
 
 	if (!(n->nlmsg_flags & NLM_F_CREATE)) {
 		memset(&req, 0, sizeof(req));
@@ -110,6 +114,13 @@ get_failed:
 
 		if (vtiinfo[IFLA_VTI_LINK])
 			link = *(__u8 *)RTA_DATA(vtiinfo[IFLA_VTI_LINK]);
+		if (vtiinfo[IFLA_VTI_ONETNS_FLAGS])
+			o_netns_flag = rta_getattr_u8(
+					    vtiinfo[IFLA_VTI_ONETNS_FLAGS]);
+		if (vtiinfo[IFLA_VTI_ONETNS_FD])
+			o_netns = rta_getattr_u32(vtiinfo[IFLA_VTI_ONETNS_FD]);
+		if (vtiinfo[IFLA_VTI_ONETNS_NAME])
+			netns_name[0] = '\0';
 	}
 
 	while (argc > 0) {
@@ -181,6 +192,21 @@ get_failed:
 					*argv);
 				exit(-1);
 			}
+		} else if (strcmp(*argv, "onetns") == 0) {
+			NEXT_ARG();
+			if (strcmp(*argv, "global") == 0)
+				o_netns_flag |= TUNNEL_ONETNS_FLAG_GLOBAL;
+			else {
+				o_netns = netns_get_fd(*argv);
+				if (o_netns < 0)
+					invarg("invalid onetns %s\n", *argv);
+				else {
+					o_netns_flag |=
+						TUNNEL_ONETNS_FLAG_NETNS;
+					strncpy(netns_name, *argv,
+						sizeof(netns_name));
+				}
+			}
 		} else
 			usage();
 		argc--; argv++;
@@ -192,6 +218,9 @@ get_failed:
 	addattr_l(n, 1024, IFLA_VTI_REMOTE, &daddr, 4);
 	if (link)
 		addattr32(n, 1024, IFLA_VTI_LINK, link);
+	addattr8(n, 1024, IFLA_IPTUN_ONETNS_FLAGS, o_netns_flag);
+	addattr_l(n, 1024, IFLA_VTI_ONETNS_FD, &o_netns, 1);
+	addattrstrz(n, 1024, IFLA_VTI_ONETNS_NAME, netns_name);
 
 	return 0;
 }
@@ -202,6 +231,7 @@ static void vti_print_opt(struct link_util *lu, FILE *f, struct rtattr *tb[])
 	char s2[64];
 	const char *local = "any";
 	const char *remote = "any";
+	__u8 o_netns_flag = 0;
 
 	if (!tb)
 		return;
@@ -243,6 +273,17 @@ static void vti_print_opt(struct link_util *lu, FILE *f, struct rtattr *tb[])
 		inet_ntop(AF_INET, RTA_DATA(tb[IFLA_VTI_OKEY]), s2, sizeof(s2));
 		fprintf(f, "okey %s ", s2);
 	}
+	if (tb[IFLA_VTI_ONETNS_FLAGS]) {
+		o_netns_flag = rta_getattr_u8(tb[IFLA_VTI_ONETNS_FLAGS]);
+		if (o_netns_flag & TUNNEL_ONETNS_FLAG_GLOBAL)
+			fprintf(f, "onetns global ");
+	}
+	if ((o_netns_flag & TUNNEL_ONETNS_FLAG_NETNS) &&
+	    tb[IFLA_VTI_ONETNS_NAME]) {
+		const char *name = rta_getattr_str(tb[IFLA_VTI_ONETNS_NAME]);
+
+		fprintf(f, "onetns %s ", name);
+	}
 }
 
 static void vti_print_help(struct link_util *lu, int argc, char **argv,
-- 
1.9.1

                 reply	other threads:[~2016-01-04 19:01 UTC|newest]

Thread overview: [no followups] expand[flat|nested]  mbox.gz  Atom feed

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=1451933211-17330-1-git-send-email-saurabh@cplanenetworks.com \
    --to=saurabh@cplanenetworks.com \
    --cc=davem@davemloft.net \
    --cc=netdev@vger.kernel.org \
    --cc=pshelar@nicira.com \
    --cc=stephen@networkplumber.org \
    --cc=tgraf@suug.ch \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
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).