[PATCH libnl 10/11] route: Add support for MPLS encap

David Ahern dsahern at gmail.com
Fri Jun 30 09:48:57 PDT 2017


Add support for MPLS lwtunnel encapsulation.

Signed-off-by: David Ahern <dsahern at gmail.com>
---
 Makefile.am                                   |   1 +
 include/netlink-private/route/nexthop-encap.h |   5 +
 include/netlink/route/nexthop.h               |   6 ++
 lib/route/nexthop_encap.c                     |   2 +-
 lib/route/nh_encap_mpls.c                     | 134 ++++++++++++++++++++++++++
 libnl-route-3.sym                             |   1 +
 6 files changed, 148 insertions(+), 1 deletion(-)
 create mode 100644 lib/route/nh_encap_mpls.c

diff --git a/Makefile.am b/Makefile.am
index 26e0f479afba..7b138295be98 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -385,6 +385,7 @@ lib_libnl_route_3_la_SOURCES = \
 	lib/route/netconf.c \
 	lib/route/nexthop.c \
 	lib/route/nexthop_encap.c \
+	lib/route/nh_encap_mpls.c \
 	lib/route/pktloc.c \
 	lib/route/qdisc/blackhole.c \
 	lib/route/qdisc.c \
diff --git a/include/netlink-private/route/nexthop-encap.h b/include/netlink-private/route/nexthop-encap.h
index ba96b0d634a9..dde1bfbec05d 100644
--- a/include/netlink-private/route/nexthop-encap.h
+++ b/include/netlink-private/route/nexthop-encap.h
@@ -27,4 +27,9 @@ int nh_encap_build_msg(struct nl_msg *msg, struct rtnl_nh_encap *rtnh_encap);
 void nh_encap_dump(struct rtnl_nh_encap *rtnh_encap, struct nl_dump_params *dp);
 
 int nh_encap_compare(struct rtnl_nh_encap *a, struct rtnl_nh_encap *b);
+
+/*
+ * MPLS encap
+ */
+extern struct nh_encap_ops mpls_encap_ops;
 #endif
diff --git a/include/netlink/route/nexthop.h b/include/netlink/route/nexthop.h
index 654b84df9f27..5b422ddfa593 100644
--- a/include/netlink/route/nexthop.h
+++ b/include/netlink/route/nexthop.h
@@ -64,6 +64,12 @@ extern struct nl_addr *	rtnl_route_nh_get_via(struct rtnl_nexthop *);
 extern char *		rtnl_route_nh_flags2str(int, char *, size_t);
 extern int		rtnl_route_nh_str2flags(const char *);
 
+/*
+ * nexthop encapsulations
+ */
+extern int		rtnl_route_nh_encap_mpls(struct rtnl_nexthop *nh,
+						 struct nl_addr *addr,
+						 uint8_t ttl);
 #ifdef __cplusplus
 }
 #endif
diff --git a/lib/route/nexthop_encap.c b/lib/route/nexthop_encap.c
index 9d9307a069d8..849d2e3edf73 100644
--- a/lib/route/nexthop_encap.c
+++ b/lib/route/nexthop_encap.c
@@ -9,7 +9,7 @@ static struct lwtunnel_encap_type {
 	struct nh_encap_ops *ops;
 } lwtunnel_encap_types[__LWTUNNEL_ENCAP_MAX] = {
 	[LWTUNNEL_ENCAP_NONE] = { .name = "none" },
-	[LWTUNNEL_ENCAP_MPLS] = { .name = "mpls" },
+	[LWTUNNEL_ENCAP_MPLS] = { .name = "mpls", .ops = &mpls_encap_ops },
 	[LWTUNNEL_ENCAP_IP]   = { .name = "ip" },
 	[LWTUNNEL_ENCAP_IP6]  = { .name = "ip6" },
 	[LWTUNNEL_ENCAP_ILA]  = { .name = "ila" },
diff --git a/lib/route/nh_encap_mpls.c b/lib/route/nh_encap_mpls.c
new file mode 100644
index 000000000000..5e96289e3f60
--- /dev/null
+++ b/lib/route/nh_encap_mpls.c
@@ -0,0 +1,134 @@
+
+#include <netlink-private/netlink.h>
+#include <netlink-private/types.h>
+#include <netlink-private/route/nexthop-encap.h>
+#include <netlink/route/nexthop.h>
+#include <linux/mpls_iptunnel.h>
+#include <linux/lwtunnel.h>
+
+struct mpls_iptunnel_encap {
+	struct nl_addr *dst;
+	uint8_t ttl;
+};
+
+static void mpls_encap_dump(void *priv, struct nl_dump_params *dp)
+{
+	struct mpls_iptunnel_encap *encap_info = priv;
+	char buf[256];
+
+	nl_dump(dp, "%s ", nl_addr2str(encap_info->dst, buf, sizeof(buf)));
+
+	if (encap_info->ttl)
+		nl_dump(dp, "ttl %u ", encap_info->ttl);
+}
+
+static int mpls_encap_build_msg(struct nl_msg *msg, void *priv)
+{
+	struct mpls_iptunnel_encap *encap_info = priv;
+
+	NLA_PUT_ADDR(msg, MPLS_IPTUNNEL_DST, encap_info->dst);
+	if (encap_info->ttl)
+		NLA_PUT_U8(msg, MPLS_IPTUNNEL_TTL, encap_info->ttl);
+
+	return 0;
+
+nla_put_failure:
+        return -NLE_MSGSIZE;
+}
+
+static void mpls_encap_destructor(void *priv)
+{
+	struct mpls_iptunnel_encap *encap_info = priv;
+
+	nl_addr_put(encap_info->dst);
+}
+
+static struct nla_policy mpls_encap_policy[MPLS_IPTUNNEL_MAX + 1] = {
+	[MPLS_IPTUNNEL_DST]     = { .type = NLA_U32 },
+	[MPLS_IPTUNNEL_TTL]     = { .type = NLA_U8 },
+};
+
+static int mpls_encap_parse_msg(struct nlattr *nla, struct rtnl_nexthop *nh)
+{
+	struct nlattr *tb[MPLS_IPTUNNEL_MAX + 1];
+	struct nl_addr *labels;
+	uint8_t ttl = 0;
+	int err;
+
+
+	err = nla_parse_nested(tb, MPLS_IPTUNNEL_MAX, nla, mpls_encap_policy);
+	if (err)
+		return err;
+
+	if (!tb[MPLS_IPTUNNEL_DST])
+		return -NLE_INVAL;
+
+	labels = nl_addr_alloc_attr(tb[MPLS_IPTUNNEL_DST], AF_MPLS);
+	if (!labels)
+		return -NLE_NOMEM;
+
+	if (tb[MPLS_IPTUNNEL_TTL])
+		ttl = nla_get_u8(tb[MPLS_IPTUNNEL_TTL]);
+
+	err = rtnl_route_nh_encap_mpls(nh, labels, ttl);
+
+	nl_addr_put(labels);
+
+	return err;
+}
+
+static int mpls_encap_compare(void *_a, void *_b)
+{
+	struct mpls_iptunnel_encap *a = _a;
+	struct mpls_iptunnel_encap *b = _b;
+	int diff = 0;
+
+	diff |= (a->ttl != b->ttl);
+	diff |= nl_addr_cmp(a->dst, b->dst);
+
+	return diff;
+}
+
+struct nh_encap_ops mpls_encap_ops = {
+	.encap_type	= LWTUNNEL_ENCAP_MPLS,
+	.build_msg	= mpls_encap_build_msg,
+	.parse_msg	= mpls_encap_parse_msg,
+	.compare	= mpls_encap_compare,
+	.dump		= mpls_encap_dump,
+	.destructor	= mpls_encap_destructor,
+};
+
+int rtnl_route_nh_encap_mpls(struct rtnl_nexthop *nh,
+			     struct nl_addr *addr,
+			     uint8_t ttl)
+{
+	struct mpls_iptunnel_encap *mpls_encap;
+	struct rtnl_nh_encap *rtnh_encap;
+
+	if (!addr)
+		return -NLE_INVAL;
+
+	if (!nl_addr_valid(nl_addr_get_binary_addr(addr),
+			   nl_addr_get_len(addr)))
+		return -NLE_INVAL;
+
+	rtnh_encap = calloc(1, sizeof(*rtnh_encap));
+	if (!rtnh_encap)
+		return -NLE_NOMEM;
+
+	mpls_encap = calloc(1, sizeof(*mpls_encap));
+	if (!mpls_encap) {
+		free(rtnh_encap);
+		return -NLE_NOMEM;
+	}
+
+	mpls_encap->dst = nl_addr_get(addr);
+	mpls_encap->ttl = ttl;
+
+	rtnh_encap->priv = mpls_encap;
+	rtnh_encap->ops = &mpls_encap_ops;
+
+	nh_set_encap(nh, rtnh_encap);
+
+	return 0;
+}
diff --git a/libnl-route-3.sym b/libnl-route-3.sym
index a8f67ad8471f..ab19ae3db731 100644
--- a/libnl-route-3.sym
+++ b/libnl-route-3.sym
@@ -1058,4 +1058,5 @@ libnl_3_4 {
 	rtnl_route_nh_set_via;
 	rtnl_route_nh_get_via;
 	rtnl_route_set_ttl_propagate;
+	rtnl_route_nh_encap_mpls;
 } libnl_3_2_29;
-- 
2.11.0 (Apple Git-81)




More information about the libnl mailing list