Skip to contentSkip to conversation

Lightweight tunnels

PATCH In review Thomas Graf 3 participants 8 messages Oct 15, 2015 – Oct 16, 2015

Subsystems (3)
lore
Share & tools
lore
#0 lore raw

cover Lightweight tunnels

Roopa Prabhu (3):
libnetlink: introduce rta_nest and u8,u16,u64 helpers for nesting
within rtattr
lwtunnel: Add encapsulation support to ip route
ip-route man: add usage and description for lwtunnel encap attributes

 include/libnetlink.h   |  10 +++
 include/utils.h        |   3 +
 ip/Makefile            |   2 +-
 ip/iproute.c           |  39 +++++++--
 ip/iproute_lwtunnel.c  | 228 +++++++++++++++++++++++++++++++++++++++++++++++++
 ip/iproute_lwtunnel.h  |   8 ++
 lib/libnetlink.c       |  31 +++++++
 man/man8/ip-route.8.in |  70 ++++++++++++++-
 8 files changed, 384 insertions(+), 7 deletions(-)
 create mode 100644 ip/iproute_lwtunnel.c
 create mode 100644 ip/iproute_lwtunnel.h
Signature · 1 line
2.4.3
#1 lore raw

PATCH 1/3 libnetlink: introduce rta_nest and u8,u16,u64 helpers for nesting within rtattr

From: Roopa Prabhu <[email protected]>

This patch introduces two new api's rta_nest and rta_nest_end to nest attributes inside a rta attribute represented by 'struct rtattr' as required to construct a nexthop. Also adds rta_addattr* variants for u8, u16 and u64 as needed to support encapsulation.

---
 include/libnetlink.h | 10 ++++++++++
 lib/libnetlink.c     | 31 +++++++++++++++++++++++++++++++
 2 files changed, 41 insertions(+)
include/libnetlink.h +10 -0
index 0503dea..407440d 100644
@@ -86,7 +86,10 @@ int addattr_nest_end(struct nlmsghdr *n, struct rtattr *nest);
 struct rtattr *addattr_nest_compat(struct nlmsghdr *n, int maxlen, int type,
 				   const void *data, int len);
 int addattr_nest_compat_end(struct nlmsghdr *n, struct rtattr *nest);
+int rta_addattr8(struct rtattr *rta, int maxlen, int type, __u8 data);
+int rta_addattr16(struct rtattr *rta, int maxlen, int type, __u16 data);
 int rta_addattr32(struct rtattr *rta, int maxlen, int type, __u32 data);
+int rta_addattr64(struct rtattr *rta, int maxlen, int type, __u64 data);
 int rta_addattr_l(struct rtattr *rta, int maxlen, int type,
 		  const void *data, int alen);
 
@@ -98,6 +101,13 @@ int parse_rtattr_byindex(struct rtattr *tb[], int max,
 struct rtattr *parse_rtattr_one(int type, struct rtattr *rta, int len);
 int __parse_rtattr_nested_compat(struct rtattr *tb[], int max, struct rtattr *rta, int len);
 
+struct rtattr *rta_nest(struct rtattr *rta, int maxlen, int type);
+int rta_nest_end(struct rtattr *rta, struct rtattr *nest);
+
+#define RTA_TAIL(rta) \
+		((struct rtattr *) (((void *) (rta)) + \
+				    RTA_ALIGN((rta)->rta_len)))
+
 #define parse_rtattr_nested(tb, max, rta) \
 	(parse_rtattr((tb), (max), RTA_DATA(rta), RTA_PAYLOAD(rta)))
 
lib/libnetlink.c +31 -0
index 46cac34..8430033 100644
@@ -721,6 +721,37 @@ int rta_addattr_l(struct rtattr *rta, int maxlen, int type,
 	return 0;
 }
 
+int rta_addattr8(struct rtattr *rta, int maxlen, int type, __u8 data)
+{
+	return rta_addattr_l(rta, maxlen, type, &data, sizeof(__u8));
+}
+
+int rta_addattr16(struct rtattr *rta, int maxlen, int type, __u16 data)
+{
+	return rta_addattr_l(rta, maxlen, type, &data, sizeof(__u16));
+}
+
+int rta_addattr64(struct rtattr *rta, int maxlen, int type, __u64 data)
+{
+	return rta_addattr_l(rta, maxlen, type, &data, sizeof(__u64));
+}
+
+struct rtattr *rta_nest(struct rtattr *rta, int maxlen, int type)
+{
+	struct rtattr *nest = RTA_TAIL(rta);
+
+	rta_addattr_l(rta, maxlen, type, NULL, 0);
+
+	return nest;
+}
+
+int rta_nest_end(struct rtattr *rta, struct rtattr *nest)
+{
+	nest->rta_len = (void *)RTA_TAIL(rta) - (void *)nest;
+
+	return rta->rta_len;
+}
+
 int parse_rtattr(struct rtattr *tb[], int max, struct rtattr *rta, int len)
 {
 	return parse_rtattr_flags(tb, max, rta, len, 0);
Signature · 1 line
2.4.3
#3 lore raw

PATCH 2/3 lwtunnel: Add encapsulation support to ip route

In reply to Thomas Graf

From: Roopa Prabhu <[email protected]>

This patch adds support to parse and print lwtunnel encapsulation attributes attached to routes for MPLS and IP tunnels.

example:
Add ipv4 route with mpls encap attributes:

Examples:

MPLS:

  $ ip route add 40.1.2.0/30 encap mpls 200 via inet 40.1.1.1 dev eth3
  $ ip route show
  40.1.2.0/30  encap mpls 200 via 40.1.1.1 dev eth3

Add ipv4 multipath route with mpls encap attributes:

  $ ip route add 10.1.1.0/30 nexthop encap mpls 200 via 10.1.1.1 dev eth0 \
		    nexthop encap mpls 700 via  40.1.1.2 dev eth3
  $ ip route show
  10.1.1.0/30
    nexthop encap mpls 200  via 10.1.1.1  dev eth0 weight 1
    nexthop encap mpls 700  via 40.1.1.2  dev eth3 weight 1

IP:

  $ ip route add 10.1.1.1/24 encap ip id 200 dst 20.1.1.1 dev vxlan0
---
 include/utils.h       |   3 +
 ip/Makefile           |   2 +-
 ip/iproute.c          |  39 +++++++--
 ip/iproute_lwtunnel.c | 228 ++++++++++++++++++++++++++++++++++++++++++++++++++
 ip/iproute_lwtunnel.h |   8 ++
 5 files changed, 274 insertions(+), 6 deletions(-)
 create mode 100644 ip/iproute_lwtunnel.c
 create mode 100644 ip/iproute_lwtunnel.h
include/utils.h +3 -0
index f77edeb..1b4cb55 100644
@@ -191,6 +191,9 @@ void print_nlmsg_timestamp(FILE *fp, const struct nlmsghdr *n);
 	__attribute__ ((format (printf, (pos_str), (pos_args))))
 #endif
 
+#define htonll(x) ((1==htonl(1)) ? (x) : ((uint64_t)htonl((x) & 0xFFFFFFFF) << 32) | htonl((x) >> 32))
+#define ntohll(x) ((1==ntohl(1)) ? (x) : ((uint64_t)ntohl((x) & 0xFFFFFFFF) << 32) | ntohl((x) >> 32))
+
 extern int cmdlineno;
 ssize_t getcmdline(char **line, size_t *len, FILE *in);
 int makeargs(char *line, char *argv[], int maxargs);
ip/Makefile +1 -1
index 52b76ef..f3d2987 100644
@@ -7,7 +7,7 @@ IPOBJ=ip.o ipaddress.o ipaddrlabel.o iproute.o iprule.o ipnetns.o \
     iplink_vxlan.o tcp_metrics.o iplink_ipoib.o ipnetconf.o link_ip6tnl.o \
     link_iptnl.o link_gre6.o iplink_bond.o iplink_bond_slave.o iplink_hsr.o \
     iplink_bridge.o iplink_bridge_slave.o ipfou.o iplink_ipvlan.o \
-    iplink_geneve.o iplink_vrf.o
+    iplink_geneve.o iplink_vrf.o iproute_lwtunnel.o
 
 RTMONOBJ=rtmon.o
 
ip/iproute.c +34 -5
index da25548..171bd31 100644
@@ -29,6 +29,7 @@
 #include "rt_names.h"
 #include "utils.h"
 #include "ip_common.h"
+#include "iproute_lwtunnel.h"
 
 #ifndef RTAX_RTTVAR
 #define RTAX_RTTVAR RTAX_HOPS
@@ -76,7 +77,8 @@ static void usage(void)
 	fprintf(stderr, "             [ table TABLE_ID ] [ proto RTPROTO ]\n");
 	fprintf(stderr, "             [ scope SCOPE ] [ metric METRIC ]\n");
 	fprintf(stderr, "INFO_SPEC := NH OPTIONS FLAGS [ nexthop NH ]...\n");
-	fprintf(stderr, "NH := [ via [ FAMILY ] ADDRESS ] [ dev STRING ] [ weight NUMBER ] NHFLAGS\n");
+	fprintf(stderr, "NH := [ encap ENCAPTYPE ENCAPHDR ] [ via [ FAMILY ] ADDRESS ]\n");
+	fprintf(stderr, "	    [ dev STRING ] [ weight NUMBER ] NHFLAGS\n");
 	fprintf(stderr, "FAMILY := [ inet | inet6 | ipx | dnet | mpls | bridge | link ]\n");
 	fprintf(stderr, "OPTIONS := FLAGS [ mtu NUMBER ] [ advmss NUMBER ] [ as [ to ] ADDRESS ]\n");
 	fprintf(stderr, "           [ rtt TIME ] [ rttvar TIME ] [ reordering NUMBER ]\n");
@@ -95,6 +97,8 @@ static void usage(void)
 	fprintf(stderr, "TIME := NUMBER[s|ms]\n");
 	fprintf(stderr, "BOOL := [1|0]\n");
 	fprintf(stderr, "FEATURES := ecn\n");
+	fprintf(stderr, "ENCAPTYPE := [ mpls | ip | ip6 ]\n");
+	fprintf(stderr, "ENCAPHDR := [ MPLSLABEL ]\n");
 	exit(-1);
 }
 
@@ -401,6 +405,10 @@ int print_route(const struct sockaddr_nl *who, struct nlmsghdr *n, void *arg)
 						  abuf, sizeof(abuf))
 			);
 	}
+
+	if (tb[RTA_ENCAP])
+		lwt_print_encap(fp, tb[RTA_ENCAP_TYPE], tb[RTA_ENCAP]);
+
 	if (r->rtm_tos && filter.tosmask != -1) {
 		SPRINT_BUF(b1);
 		fprintf(fp, "tos %s ", rtnl_dsfield_n2a(r->rtm_tos, b1, sizeof(b1)));
@@ -633,6 +641,12 @@ int print_route(const struct sockaddr_nl *who, struct nlmsghdr *n, void *arg)
 				fprintf(fp, "%s\tnexthop", _SL_);
 			if (nh->rtnh_len > sizeof(*nh)) {
 				parse_rtattr(tb, RTA_MAX, RTNH_DATA(nh), nh->rtnh_len - sizeof(*nh));
+
+				if (tb[RTA_ENCAP])
+					lwt_print_encap(fp,
+							tb[RTA_ENCAP_TYPE],
+							tb[RTA_ENCAP]);
+
 				if (tb[RTA_GATEWAY]) {
 					fprintf(fp, " via %s ",
 						format_host(r->rtm_family,
@@ -704,9 +718,8 @@ int print_route(const struct sockaddr_nl *who, struct nlmsghdr *n, void *arg)
 	return 0;
 }
 
-
-static int parse_one_nh(struct rtmsg *r, struct rtattr *rta,
-			struct rtnexthop *rtnh,
+static int parse_one_nh(struct nlmsghdr *n, struct rtmsg *r,
+			struct rtattr *rta, struct rtnexthop *rtnh,
 			int *argcp, char ***argvp)
 {
 	int argc = *argcp;
@@ -753,6 +766,11 @@ static int parse_one_nh(struct rtmsg *r, struct rtattr *rta,
 				invarg("\"realm\" value is invalid\n", *argv);
 			rta_addattr32(rta, 4096, RTA_FLOW, realm);
 			rtnh->rtnh_len += sizeof(struct rtattr) + 4;
+		} else if (strcmp(*argv, "encap") == 0) {
+			int len = rta->rta_len;
+
+			lwt_parse_encap(rta, 4096, &argc, &argv);
+			rtnh->rtnh_len += rta->rta_len - len;
 		} else
 			break;
 	}
@@ -784,7 +802,7 @@ static int parse_nexthops(struct nlmsghdr *n, struct rtmsg *r,
 		memset(rtnh, 0, sizeof(*rtnh));
 		rtnh->rtnh_len = sizeof(*rtnh);
 		rta->rta_len += rtnh->rtnh_len;
-		parse_one_nh(r, rta, rtnh, &argc, &argv);
+		parse_one_nh(n, r, rta, rtnh, &argc, &argv);
 		rtnh = RTNH_NEXT(rtnh);
 	}
 
@@ -1092,6 +1110,17 @@ static int iproute_modify(int cmd, unsigned flags, int argc, char **argv)
 			else if (get_u8(&pref, *argv, 0))
 				invarg("\"pref\" value is invalid\n", *argv);
 			addattr8(&req.n, sizeof(req), RTA_PREF, pref);
+		} else if (strcmp(*argv, "encap") == 0) {
+			char buf[1024];
+			struct rtattr *rta = (void*)buf;
+
+			rta->rta_type = RTA_ENCAP;
+			rta->rta_len = RTA_LENGTH(0);
+
+			lwt_parse_encap(rta, sizeof(buf), &argc, &argv);
+
+			if (rta->rta_len > RTA_LENGTH(0))
+				addraw_l(&req.n, 1024, RTA_DATA(rta), RTA_PAYLOAD(rta));
 		} else {
 			int type;
 			inet_prefix dst;
ip/iproute_lwtunnel.c new file +228 -0

228 lines not on this page · raw message

ip/iproute_lwtunnel.h new file +8 -0
new file mode 100644
index 0000000..b82b58a
@@ -0,0 +1,8 @@
+#ifndef __LWTUNNEL_H__
+#define __LETUNNEL_H__ 1
+
+int lwt_parse_encap(struct rtattr *rta, size_t len, int *argcp, char ***argvp);
+void lwt_print_encap(FILE *fp, struct rtattr *encap_type,
+		     struct rtattr *encap);
+
+#endif
Signature · 1 line
2.4.3
#5 lore raw

PATCH 3/3 ip-route man: add usage and description for lwtunnel encap attributes

In reply to Thomas Graf

From: Roopa Prabhu <[email protected]>

This patch updates ip-route man page with lwtunnel encap usage and description, covering MPLS and IP encapsulation.

---
 man/man8/ip-route.8.in | 70 +++++++++++++++++++++++++++++++++++++++++++++++++-
 1 file changed, 69 insertions(+), 1 deletion(-)
man/man8/ip-route.8.in +69 -1
index 72d8d77..9934a1e 100644
@@ -80,6 +80,8 @@ replace " } "
 
 .ti -8
 .IR NH " := [ "
+.B  encap
+.IR ENCAP " ] [ "
 .B  via
 [
 .IR FAMILY " ] " ADDRESS " ] [ "
@@ -164,6 +166,26 @@ throw " | " unreachable " | " prohibit " | " blackhole " | " nat " ]"
 .IR PREF " := [ "
 .BR low " | " medium " | " high " ]"
 
+.ti -8
+.IR ENCAP " := [ "
+.IR MPLS " | " IP " ]"
+
+.ti -8
+.IR ENCAP_MPLS " := "
+.BR mpls " [ "
+.IR LABEL " ]"
+
+.ti -8
+.IR ENCAP_IP " := "
+.B ip
+.B id
+.IR TUNNEL_ID
+.B  dst
+.IR REMOTE_IP " [ "
+.B tos
+.IR TOS " ] ["
+.B  ttl
+.IR TTL " ]"
 
 .SH DESCRIPTION
 .B ip route
@@ -589,6 +611,48 @@ Discovery messages. Namely:
 - the route has a highest priority
 .sp
 
+.TP
+.BI encap " ENCAPTYPE ENCAPHDR"
+attach tunnel encapsulation attributes to this route.
+.sp
+.I ENCAPTYPE
+is a string specifying the supported encapsulation type. Namely:
+
+.in +8
+.BI mpls
+- encapsulation type MPLS
+.sp
+.BI ip
+- IP encapsulation (Geneve, GRE, VXLAN, ...)
+.sp
+
+.in -8
+.I ENCAPHDR
+is a set of encapsulation attributes specific to the
+.I ENCAPTYPE.
+
+.in +8
+.B mpls
+.in +2
+.I MPLSLABEL
+- mpls label stack with labels separated by
+.I "/"
+.in -2
+.sp
+
+.B ip
+.in +2
+.B id
+.I TUNNEL_ID
+.B  dst
+.IR REMOTE_IP " [ "
+.B tos
+.IR TOS " ] ["
+.B  ttl
+.IR TTL " ]"
+.in -2
+.sp
+
 .in -8
 .RE
 
@@ -847,7 +911,11 @@ ip route add default via 192.168.1.1 dev eth0
 Adds a default route (for all addresses) via the local gateway 192.168.1.1 that can
 be reached on device eth0.
 .RE
-
+.PP
+ip route add 10.1.1.0/30 encap mpls 200/300 via 10.1.1.1 dev eth0
+.RS 4
+Adds an ipv4 route with mpls encapsulation attributes attached to it.
+.RE
 .SH SEE ALSO
 .br
 .BR ip (8)
Signature · 1 line
2.4.3
Acked-by on v1 1/3
#2 lore raw

Re: [PATCH 1/3] libnetlink: introduce rta_nest and u8,u16,u64 helpers for nesting within rtattr

In reply to Thomas Graf
Quoted 9 lines · Thomas Graf

From: Roopa Prabhu <[email protected]>

This patch introduces two new api's rta_nest and rta_nest_end to nest attributes inside a rta attribute represented by 'struct rtattr' as required to construct a nexthop. Also adds rta_addattr* variants for u8, u16 and u64 as needed to support encapsulation.

Signature · 1 line
Jiri Benc
Acked-by on v1 2/3
#4 lore raw

Re: [PATCH 2/3] lwtunnel: Add encapsulation support to ip route

In reply to Thomas Graf
Quoted 24 lines · Thomas Graf

From: Roopa Prabhu <[email protected]>

This patch adds support to parse and print lwtunnel encapsulation attributes attached to routes for MPLS and IP tunnels.

example:
Add ipv4 route with mpls encap attributes:

Examples:

MPLS:

  $ ip route add 40.1.2.0/30 encap mpls 200 via inet 40.1.1.1 dev eth3
  $ ip route show
  40.1.2.0/30  encap mpls 200 via 40.1.1.1 dev eth3

Add ipv4 multipath route with mpls encap attributes:

  $ ip route add 10.1.1.0/30 nexthop encap mpls 200 via 10.1.1.1 dev eth0 \
		    nexthop encap mpls 700 via  40.1.1.2 dev eth3
  $ ip route show
  10.1.1.0/30
    nexthop encap mpls 200  via 10.1.1.1  dev eth0 weight 1
    nexthop encap mpls 700  via 40.1.1.2  dev eth3 weight 1
Quoted 5 lines

IP:

  $ ip route add 10.1.1.1/24 encap ip id 200 dst 20.1.1.1 dev vxlan0
Signature · 1 line
Jiri Benc
Acked-by on v1 3/3
#6 lore raw

Re: [PATCH 3/3] ip-route man: add usage and description for lwtunnel encap attributes

In reply to Thomas Graf
Quoted 7 lines · Thomas Graf

From: Roopa Prabhu <[email protected]>

This patch updates ip-route man page with lwtunnel encap usage and description, covering MPLS and IP encapsulation.

Signature · 1 line
Jiri Benc
#7 lore raw

Re: [PATCH 3/3] ip-route man: add usage and description for lwtunnel encap attributes

In reply to Thomas Graf
Quoted 7 lines · On Thu, 15 Oct 2015 13:13:40 +0200 Thomas Graf <[email protected]> wrote:

From: Roopa Prabhu <[email protected]>

This patch updates ip-route man page with lwtunnel encap usage and description, covering MPLS and IP encapsulation.

I applied all 3 patches. The first one into master (since it might be useful for other code), and other two to net-next.