[<prev] [next>] [day] [month] [year] [list]
Message-ID: <1451933211-17330-1-git-send-email-saurabh@cplanenetworks.com>
Date: Mon, 4 Jan 2016 10:46:51 -0800
From: Saurabh Mohan <saurabh@...anenetworks.com>
To: <netdev@...r.kernel.org>, <stephen@...workplumber.org>,
<davem@...emloft.net>, <pshelar@...ira.com>, <tgraf@...g.ch>
CC: Saurabh Mohan <saurabh@...anenetworks.com>
Subject: [PATCH iproute2] Support outside netns for tunnels.
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@...anenetworks.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
--
To unsubscribe from this list: send the line "unsubscribe netdev" in
the body of a message to majordomo@...r.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Powered by blists - more mailing lists