All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH net-next v2 0/4] net: support MPLS in IPv4 and UDP
@ 2016-07-07  5:56 Simon Horman
  2016-07-07  5:56 ` [PATCH net-next v2 1/4] tunnels: support MPLS over IPv4 tunnels Simon Horman
                   ` (6 more replies)
  0 siblings, 7 replies; 9+ messages in thread
From: Simon Horman @ 2016-07-07  5:56 UTC (permalink / raw)
  To: David Miller; +Cc: Tom Herbert, netdev, Simon Horman

This short series provides support for MPLS in IPv4 (RFC4023), and by
virtue of FOU, MPLS in UDP (RFC7510).

The changes are as follows:
1. Teach tunnel4.c about AF_MPLS, it already understands AF_INET and
   AF_INET6
2. Enhance IPIP and SIT to handle MPLS. Both already handle IPv4.
   SIT also already handles IPv6.
3. Trivially enhance MPLS to allow routes over SIT and IPIP tunnels.

A corresponding patch set for iproute2 has also been provided.


Changes since v1
* Correct inverted IPIP protocol logic in SIT patch
* Provide usage example below


Sample configuration follows:

* The following creates a tunnel and routes MPLS packets whose outermost
  label is 100 over it. The forwarded packets will have the outermost label
  stack entry, 100, removed and two label stack entries added, the
  outermost having label 200 and the next having label 300.

  The local end-point for the tunnel is 10.0.99.192 and the remote
  endpoint is 10.0.99.193.

  The local address for encapsulated packets is 10.0.98.192 and the
  remote address is 10.0.98.193.

  # Create an MPLS over IPv4 tunnel using the IPIP driver
  ip link add name tun1 type ipip remote 10.0.99.193 local 10.0.99.192 \
	ttl 225 mode mplsip

  # Bring the tunnel up and an add an IPv4 address and route
  ip link set up dev tun1
  ip addr add 10.0.98.192/24 dev tun1

  # Set MPLS route
  # Allow MPLS forwarding of packets recieved on eth0
  echo 1 > /proc/sys/net/mpls/conf/eth0/input
  # Larger than label to be routed (100)
  echo 101 > /proc/sys/net/mpls/platform_labels
  ip -f mpls route add 100 as 200/300 via inet 10.0.98.193


* For FOU (in this case MPLS over UDP) a tunnel may created using:

  # Packets recieved on UDP port 6635 are MPLS over UDP (IP proto 137)
  ip fou add port 6635 ipproto 137
  # Create the tunnel netdev
  ip link add name tun1 type ipip remote 10.0.99.193 local 10.0.99.192 \
	ttl 225 mode mplsip encap fou encap-sport auto encap-dport 6635

  IPv4 address, link and route, and MPLS routing commands are as per
  the MPLS over IPv4 example

* To use the SIT driver instead of the IPIP driver "ipip" may be substituted
  for "sit" in the above examples.

* To create a tunnel that forwards and receives all supported
  inner-protocols "mplsip" may be substituted for "any" in the above
  examples.

  For the IPIP driver this configures both IPv4 and MPLS over IPv4.
  For the SIT driver this configures IPv6, IPv4 and MPLS over IPv4.


Simon Horman (4):
  tunnels: support MPLS over IPv4 tunnels
  sit: support MPLS over IPv4
  ipip: support MPLS over IPv4
  mpls: allow routes on ipip and sit devices

 net/ipv4/ipip.c    | 137 ++++++++++++++++++++++++++++++++++++++++++++++-------
 net/ipv4/tunnel4.c |  77 ++++++++++++++++++++++++++----
 net/ipv6/sit.c     |  93 +++++++++++++++++++++++++++++-------
 net/mpls/af_mpls.c |   6 ++-
 4 files changed, 269 insertions(+), 44 deletions(-)

-- 
2.7.0.rc3.207.g0ac5344

^ permalink raw reply	[flat|nested] 9+ messages in thread

* [PATCH net-next v2 1/4] tunnels: support MPLS over IPv4 tunnels
  2016-07-07  5:56 [PATCH net-next v2 0/4] net: support MPLS in IPv4 and UDP Simon Horman
@ 2016-07-07  5:56 ` Simon Horman
  2016-07-07  5:56 ` [PATCH net-next v2 2/4] sit: support MPLS over IPv4 Simon Horman
                   ` (5 subsequent siblings)
  6 siblings, 0 replies; 9+ messages in thread
From: Simon Horman @ 2016-07-07  5:56 UTC (permalink / raw)
  To: David Miller; +Cc: Tom Herbert, netdev, Simon Horman

Extend tunnel support to MPLS over IPv4.  The implementation extends the
existing differentiation between IPIP and IPv6 over IPv4 to also cover MPLS
over IPv4.

Signed-off-by: Simon Horman <simon.horman@netronome.com>
Reviewed-by: Dinan Gunawardena <dinan.gunawardena@netronome.com>
---
 net/ipv4/tunnel4.c | 77 +++++++++++++++++++++++++++++++++++++++++++++++-------
 1 file changed, 67 insertions(+), 10 deletions(-)

diff --git a/net/ipv4/tunnel4.c b/net/ipv4/tunnel4.c
index 0d0171830620..45cd4253583a 100644
--- a/net/ipv4/tunnel4.c
+++ b/net/ipv4/tunnel4.c
@@ -6,6 +6,7 @@
 #include <linux/init.h>
 #include <linux/module.h>
 #include <linux/mutex.h>
+#include <linux/mpls.h>
 #include <linux/netdevice.h>
 #include <linux/skbuff.h>
 #include <linux/slab.h>
@@ -16,11 +17,14 @@
 
 static struct xfrm_tunnel __rcu *tunnel4_handlers __read_mostly;
 static struct xfrm_tunnel __rcu *tunnel64_handlers __read_mostly;
+static struct xfrm_tunnel __rcu *tunnelmpls4_handlers __read_mostly;
 static DEFINE_MUTEX(tunnel4_mutex);
 
 static inline struct xfrm_tunnel __rcu **fam_handlers(unsigned short family)
 {
-	return (family == AF_INET) ? &tunnel4_handlers : &tunnel64_handlers;
+	return (family == AF_INET) ? &tunnel4_handlers :
+		(family == AF_INET6) ? &tunnel64_handlers :
+		&tunnelmpls4_handlers;
 }
 
 int xfrm4_tunnel_register(struct xfrm_tunnel *handler, unsigned short family)
@@ -125,6 +129,26 @@ drop:
 }
 #endif
 
+#if IS_ENABLED(CONFIG_MPLS)
+static int tunnelmpls4_rcv(struct sk_buff *skb)
+{
+	struct xfrm_tunnel *handler;
+
+	if (!pskb_may_pull(skb, sizeof(struct mpls_label)))
+		goto drop;
+
+	for_each_tunnel_rcu(tunnelmpls4_handlers, handler)
+		if (!handler->handler(skb))
+			return 0;
+
+	icmp_send(skb, ICMP_DEST_UNREACH, ICMP_PORT_UNREACH, 0);
+
+drop:
+	kfree_skb(skb);
+	return 0;
+}
+#endif
+
 static void tunnel4_err(struct sk_buff *skb, u32 info)
 {
 	struct xfrm_tunnel *handler;
@@ -145,6 +169,17 @@ static void tunnel64_err(struct sk_buff *skb, u32 info)
 }
 #endif
 
+#if IS_ENABLED(CONFIG_MPLS)
+static void tunnelmpls4_err(struct sk_buff *skb, u32 info)
+{
+	struct xfrm_tunnel *handler;
+
+	for_each_tunnel_rcu(tunnelmpls4_handlers, handler)
+		if (!handler->err_handler(skb, info))
+			break;
+}
+#endif
+
 static const struct net_protocol tunnel4_protocol = {
 	.handler	=	tunnel4_rcv,
 	.err_handler	=	tunnel4_err,
@@ -161,24 +196,46 @@ static const struct net_protocol tunnel64_protocol = {
 };
 #endif
 
+#if IS_ENABLED(CONFIG_MPLS)
+static const struct net_protocol tunnelmpls4_protocol = {
+	.handler	=	tunnelmpls4_rcv,
+	.err_handler	=	tunnelmpls4_err,
+	.no_policy	=	1,
+	.netns_ok	=	1,
+};
+#endif
+
 static int __init tunnel4_init(void)
 {
-	if (inet_add_protocol(&tunnel4_protocol, IPPROTO_IPIP)) {
-		pr_err("%s: can't add protocol\n", __func__);
-		return -EAGAIN;
-	}
+	if (inet_add_protocol(&tunnel4_protocol, IPPROTO_IPIP))
+		goto err_ipip;
 #if IS_ENABLED(CONFIG_IPV6)
-	if (inet_add_protocol(&tunnel64_protocol, IPPROTO_IPV6)) {
-		pr_err("tunnel64 init: can't add protocol\n");
-		inet_del_protocol(&tunnel4_protocol, IPPROTO_IPIP);
-		return -EAGAIN;
-	}
+	if (inet_add_protocol(&tunnel64_protocol, IPPROTO_IPV6))
+		goto err_ipv6;
+#endif
+#if IS_ENABLED(CONFIG_MPLS)
+	if (inet_add_protocol(&tunnelmpls4_protocol, IPPROTO_MPLS))
+		goto err_mpls;
 #endif
 	return 0;
+
+#if IS_ENABLED(CONFIG_IPV6)
+err_mpls:
+	inet_del_protocol(&tunnel4_protocol, IPPROTO_IPV6);
+#endif
+err_ipv6:
+	inet_del_protocol(&tunnel4_protocol, IPPROTO_IPIP);
+err_ipip:
+	pr_err("%s: can't add protocol\n", __func__);
+	return -EAGAIN;
 }
 
 static void __exit tunnel4_fini(void)
 {
+#if IS_ENABLED(CONFIG_MPLS)
+	if (inet_del_protocol(&tunnelmpls4_protocol, IPPROTO_MPLS))
+		pr_err("tunnelmpls4 close: can't remove protocol\n");
+#endif
 #if IS_ENABLED(CONFIG_IPV6)
 	if (inet_del_protocol(&tunnel64_protocol, IPPROTO_IPV6))
 		pr_err("tunnel64 close: can't remove protocol\n");
-- 
2.7.0.rc3.207.g0ac5344

^ permalink raw reply related	[flat|nested] 9+ messages in thread

* [PATCH net-next v2 2/4] sit: support MPLS over IPv4
  2016-07-07  5:56 [PATCH net-next v2 0/4] net: support MPLS in IPv4 and UDP Simon Horman
  2016-07-07  5:56 ` [PATCH net-next v2 1/4] tunnels: support MPLS over IPv4 tunnels Simon Horman
@ 2016-07-07  5:56 ` Simon Horman
  2016-07-07  5:56 ` [PATCH net-next v2 3/4] ipip: " Simon Horman
                   ` (4 subsequent siblings)
  6 siblings, 0 replies; 9+ messages in thread
From: Simon Horman @ 2016-07-07  5:56 UTC (permalink / raw)
  To: David Miller; +Cc: Tom Herbert, netdev, Simon Horman

Extend the SIT driver to support MPLS over IPv4. This implementation
extends existing support for IPv6 over IPv4 and IPv4 over IPv4.

Signed-off-by: Simon Horman <simon.horman@netronome.com>
Reviewed-by: Dinan Gunawardena <dinan.gunawardena@netronome.com>
---
v2
* Correct inverted logic for IPIP in ipip6_valid_ip_proto()
---
 net/ipv6/sit.c | 93 ++++++++++++++++++++++++++++++++++++++++++++++++----------
 1 file changed, 77 insertions(+), 16 deletions(-)

diff --git a/net/ipv6/sit.c b/net/ipv6/sit.c
index 917a5cd4b8fc..182b6a9be29d 100644
--- a/net/ipv6/sit.c
+++ b/net/ipv6/sit.c
@@ -688,12 +688,19 @@ out:
 	return 0;
 }
 
-static const struct tnl_ptk_info tpi = {
+static const struct tnl_ptk_info ipip_tpi = {
 	/* no tunnel info required for ipip. */
 	.proto = htons(ETH_P_IP),
 };
 
-static int ipip_rcv(struct sk_buff *skb)
+#if IS_ENABLED(CONFIG_MPLS)
+static const struct tnl_ptk_info mplsip_tpi = {
+	/* no tunnel info required for mplsip. */
+	.proto = htons(ETH_P_MPLS_UC),
+};
+#endif
+
+static int sit_tunnel_rcv(struct sk_buff *skb, u8 ipproto)
 {
 	const struct iphdr *iph;
 	struct ip_tunnel *tunnel;
@@ -702,15 +709,23 @@ static int ipip_rcv(struct sk_buff *skb)
 	tunnel = ipip6_tunnel_lookup(dev_net(skb->dev), skb->dev,
 				     iph->saddr, iph->daddr);
 	if (tunnel) {
-		if (tunnel->parms.iph.protocol != IPPROTO_IPIP &&
+		const struct tnl_ptk_info *tpi;
+
+		if (tunnel->parms.iph.protocol != ipproto &&
 		    tunnel->parms.iph.protocol != 0)
 			goto drop;
 
 		if (!xfrm4_policy_check(NULL, XFRM_POLICY_IN, skb))
 			goto drop;
-		if (iptunnel_pull_header(skb, 0, tpi.proto, false))
+#if IS_ENABLED(CONFIG_MPLS)
+		if (ipproto == IPPROTO_MPLS)
+			tpi = &mplsip_tpi;
+		else
+#endif
+			tpi = &ipip_tpi;
+		if (iptunnel_pull_header(skb, 0, tpi->proto, false))
 			goto drop;
-		return ip_tunnel_rcv(tunnel, skb, &tpi, NULL, log_ecn_error);
+		return ip_tunnel_rcv(tunnel, skb, tpi, NULL, log_ecn_error);
 	}
 
 	return 1;
@@ -720,6 +735,18 @@ drop:
 	return 0;
 }
 
+static int ipip_rcv(struct sk_buff *skb)
+{
+	return sit_tunnel_rcv(skb, IPPROTO_IPIP);
+}
+
+#if IS_ENABLED(CONFIG_MPLS)
+static int mplsip_rcv(struct sk_buff *skb)
+{
+	return sit_tunnel_rcv(skb, IPPROTO_MPLS);
+}
+#endif
+
 /*
  * If the IPv6 address comes from 6rd / 6to4 (RFC 3056) addr space this function
  * stores the embedded IPv4 address in v4dst and returns true.
@@ -958,7 +985,8 @@ tx_error:
 	return NETDEV_TX_OK;
 }
 
-static netdev_tx_t ipip_tunnel_xmit(struct sk_buff *skb, struct net_device *dev)
+static netdev_tx_t sit_tunnel_xmit__(struct sk_buff *skb,
+				     struct net_device *dev, u8 ipproto)
 {
 	struct ip_tunnel *tunnel = netdev_priv(dev);
 	const struct iphdr  *tiph = &tunnel->parms.iph;
@@ -966,9 +994,9 @@ static netdev_tx_t ipip_tunnel_xmit(struct sk_buff *skb, struct net_device *dev)
 	if (iptunnel_handle_offloads(skb, SKB_GSO_IPXIP4))
 		goto tx_error;
 
-	skb_set_inner_ipproto(skb, IPPROTO_IPIP);
+	skb_set_inner_ipproto(skb, ipproto);
 
-	ip_tunnel_xmit(skb, dev, tiph, IPPROTO_IPIP);
+	ip_tunnel_xmit(skb, dev, tiph, ipproto);
 	return NETDEV_TX_OK;
 tx_error:
 	kfree_skb(skb);
@@ -981,11 +1009,16 @@ static netdev_tx_t sit_tunnel_xmit(struct sk_buff *skb,
 {
 	switch (skb->protocol) {
 	case htons(ETH_P_IP):
-		ipip_tunnel_xmit(skb, dev);
+		sit_tunnel_xmit__(skb, dev, IPPROTO_IPIP);
 		break;
 	case htons(ETH_P_IPV6):
 		ipip6_tunnel_xmit(skb, dev);
 		break;
+#if IS_ENABLED(CONFIG_MPLS)
+	case htons(ETH_P_MPLS_UC):
+		sit_tunnel_xmit__(skb, dev, IPPROTO_MPLS);
+		break;
+#endif
 	default:
 		goto tx_err;
 	}
@@ -1093,6 +1126,16 @@ static int ipip6_tunnel_update_6rd(struct ip_tunnel *t,
 }
 #endif
 
+bool ipip6_valid_ip_proto(u8 ipproto)
+{
+	return ipproto == IPPROTO_IPV6 ||
+		ipproto == IPPROTO_IPIP ||
+#if IS_ENABLED(CONFIG_MPLS)
+		ipproto == IPPROTO_MPLS ||
+#endif
+		ipproto == 0;
+}
+
 static int
 ipip6_tunnel_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
 {
@@ -1152,9 +1195,7 @@ ipip6_tunnel_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
 			goto done;
 
 		err = -EINVAL;
-		if (p.iph.protocol != IPPROTO_IPV6 &&
-		    p.iph.protocol != IPPROTO_IPIP &&
-		    p.iph.protocol != 0)
+		if (!ipip6_valid_ip_proto(p.iph.protocol))
 			goto done;
 		if (p.iph.version != 4 ||
 		    p.iph.ihl != 5 || (p.iph.frag_off&htons(~IP_DF)))
@@ -1379,9 +1420,7 @@ static int ipip6_validate(struct nlattr *tb[], struct nlattr *data[])
 		return 0;
 
 	proto = nla_get_u8(data[IFLA_IPTUN_PROTO]);
-	if (proto != IPPROTO_IPV6 &&
-	    proto != IPPROTO_IPIP &&
-	    proto != 0)
+	if (!ipip6_valid_ip_proto(proto))
 		return -EINVAL;
 
 	return 0;
@@ -1723,6 +1762,14 @@ static struct xfrm_tunnel ipip_handler __read_mostly = {
 	.priority	=	2,
 };
 
+#if IS_ENABLED(CONFIG_MPLS)
+static struct xfrm_tunnel mplsip_handler __read_mostly = {
+	.handler	=	mplsip_rcv,
+	.err_handler	=	ipip6_err,
+	.priority	=	2,
+};
+#endif
+
 static void __net_exit sit_destroy_tunnels(struct net *net,
 					   struct list_head *head)
 {
@@ -1818,6 +1865,9 @@ static void __exit sit_cleanup(void)
 	rtnl_link_unregister(&sit_link_ops);
 	xfrm4_tunnel_deregister(&sit_handler, AF_INET6);
 	xfrm4_tunnel_deregister(&ipip_handler, AF_INET);
+#if IS_ENABLED(CONFIG_MPLS)
+	xfrm4_tunnel_deregister(&mplsip_handler, AF_MPLS);
+#endif
 
 	unregister_pernet_device(&sit_net_ops);
 	rcu_barrier(); /* Wait for completion of call_rcu()'s */
@@ -1827,7 +1877,7 @@ static int __init sit_init(void)
 {
 	int err;
 
-	pr_info("IPv6 over IPv4 tunneling driver\n");
+	pr_info("IPv6, IPv4 and MPLS over IPv4 tunneling driver\n");
 
 	err = register_pernet_device(&sit_net_ops);
 	if (err < 0)
@@ -1842,6 +1892,13 @@ static int __init sit_init(void)
 		pr_info("%s: can't register ip4ip4\n", __func__);
 		goto xfrm_tunnel4_failed;
 	}
+#if IS_ENABLED(CONFIG_MPLS)
+	err = xfrm4_tunnel_register(&mplsip_handler, AF_MPLS);
+	if (err < 0) {
+		pr_info("%s: can't register mplsip\n", __func__);
+		goto xfrm_tunnel_mpls_failed;
+	}
+#endif
 	err = rtnl_link_register(&sit_link_ops);
 	if (err < 0)
 		goto rtnl_link_failed;
@@ -1850,6 +1907,10 @@ out:
 	return err;
 
 rtnl_link_failed:
+#if IS_ENABLED(CONFIG_MPLS)
+	xfrm4_tunnel_deregister(&mplsip_handler, AF_MPLS);
+xfrm_tunnel_mpls_failed:
+#endif
 	xfrm4_tunnel_deregister(&ipip_handler, AF_INET);
 xfrm_tunnel4_failed:
 	xfrm4_tunnel_deregister(&sit_handler, AF_INET6);
-- 
2.7.0.rc3.207.g0ac5344

^ permalink raw reply related	[flat|nested] 9+ messages in thread

* [PATCH net-next v2 3/4] ipip: support MPLS over IPv4
  2016-07-07  5:56 [PATCH net-next v2 0/4] net: support MPLS in IPv4 and UDP Simon Horman
  2016-07-07  5:56 ` [PATCH net-next v2 1/4] tunnels: support MPLS over IPv4 tunnels Simon Horman
  2016-07-07  5:56 ` [PATCH net-next v2 2/4] sit: support MPLS over IPv4 Simon Horman
@ 2016-07-07  5:56 ` Simon Horman
  2016-07-07  5:56 ` [PATCH net-next v2 4/4] mpls: allow routes on ipip and sit devices Simon Horman
                   ` (3 subsequent siblings)
  6 siblings, 0 replies; 9+ messages in thread
From: Simon Horman @ 2016-07-07  5:56 UTC (permalink / raw)
  To: David Miller; +Cc: Tom Herbert, netdev, Simon Horman

Extend the IPIP driver to support MPLS over IPv4. The implementation is an
extension of existing support for IPv4 over IPv4 and is based of multiple
inner-protocol support for the SIT driver.

Signed-off-by: Simon Horman <simon.horman@netronome.com>
Reviewed-by: Dinan Gunawardena <dinan.gunawardena@netronome.com>
---
 net/ipv4/ipip.c | 137 +++++++++++++++++++++++++++++++++++++++++++++++++-------
 1 file changed, 121 insertions(+), 16 deletions(-)

diff --git a/net/ipv4/ipip.c b/net/ipv4/ipip.c
index 978370132f29..4ae3f8e6c6cc 100644
--- a/net/ipv4/ipip.c
+++ b/net/ipv4/ipip.c
@@ -148,14 +148,14 @@ static int ipip_err(struct sk_buff *skb, u32 info)
 
 	if (type == ICMP_DEST_UNREACH && code == ICMP_FRAG_NEEDED) {
 		ipv4_update_pmtu(skb, dev_net(skb->dev), info,
-				 t->parms.link, 0, IPPROTO_IPIP, 0);
+				 t->parms.link, 0, iph->protocol, 0);
 		err = 0;
 		goto out;
 	}
 
 	if (type == ICMP_REDIRECT) {
 		ipv4_redirect(skb, dev_net(skb->dev), t->parms.link, 0,
-			      IPPROTO_IPIP, 0);
+			      iph->protocol, 0);
 		err = 0;
 		goto out;
 	}
@@ -177,12 +177,19 @@ out:
 	return err;
 }
 
-static const struct tnl_ptk_info tpi = {
+static const struct tnl_ptk_info ipip_tpi = {
 	/* no tunnel info required for ipip. */
 	.proto = htons(ETH_P_IP),
 };
 
-static int ipip_rcv(struct sk_buff *skb)
+#if IS_ENABLED(CONFIG_MPLS)
+static const struct tnl_ptk_info mplsip_tpi = {
+	/* no tunnel info required for mplsip. */
+	.proto = htons(ETH_P_MPLS_UC),
+};
+#endif
+
+static int ipip_tunnel_rcv(struct sk_buff *skb, u8 ipproto)
 {
 	struct net *net = dev_net(skb->dev);
 	struct ip_tunnel_net *itn = net_generic(net, ipip_net_id);
@@ -193,11 +200,23 @@ static int ipip_rcv(struct sk_buff *skb)
 	tunnel = ip_tunnel_lookup(itn, skb->dev->ifindex, TUNNEL_NO_KEY,
 			iph->saddr, iph->daddr, 0);
 	if (tunnel) {
+		const struct tnl_ptk_info *tpi;
+
+		if (tunnel->parms.iph.protocol != ipproto &&
+		    tunnel->parms.iph.protocol != 0)
+			goto drop;
+
 		if (!xfrm4_policy_check(NULL, XFRM_POLICY_IN, skb))
 			goto drop;
-		if (iptunnel_pull_header(skb, 0, tpi.proto, false))
+#if IS_ENABLED(CONFIG_MPLS)
+		if (ipproto == IPPROTO_MPLS)
+			tpi = &mplsip_tpi;
+		else
+#endif
+			tpi = &ipip_tpi;
+		if (iptunnel_pull_header(skb, 0, tpi->proto, false))
 			goto drop;
-		return ip_tunnel_rcv(tunnel, skb, &tpi, NULL, log_ecn_error);
+		return ip_tunnel_rcv(tunnel, skb, tpi, NULL, log_ecn_error);
 	}
 
 	return -1;
@@ -207,24 +226,51 @@ drop:
 	return 0;
 }
 
+static int ipip_rcv(struct sk_buff *skb)
+{
+	return ipip_tunnel_rcv(skb, IPPROTO_IPIP);
+}
+
+#if IS_ENABLED(CONFIG_MPLS)
+static int mplsip_rcv(struct sk_buff *skb)
+{
+	return ipip_tunnel_rcv(skb, IPPROTO_MPLS);
+}
+#endif
+
 /*
  *	This function assumes it is being called from dev_queue_xmit()
  *	and that skb is filled properly by that function.
  */
-static netdev_tx_t ipip_tunnel_xmit(struct sk_buff *skb, struct net_device *dev)
+static netdev_tx_t ipip_tunnel_xmit(struct sk_buff *skb,
+				    struct net_device *dev)
 {
 	struct ip_tunnel *tunnel = netdev_priv(dev);
 	const struct iphdr  *tiph = &tunnel->parms.iph;
+	u8 ipproto;
+
+	switch (skb->protocol) {
+	case htons(ETH_P_IP):
+		ipproto = IPPROTO_IPIP;
+		break;
+#if IS_ENABLED(CONFIG_MPLS)
+	case htons(ETH_P_MPLS_UC):
+		ipproto = IPPROTO_MPLS;
+		break;
+#endif
+	default:
+		goto tx_error;
+	}
 
-	if (unlikely(skb->protocol != htons(ETH_P_IP)))
+	if (tiph->protocol != ipproto && tiph->protocol != 0)
 		goto tx_error;
 
 	if (iptunnel_handle_offloads(skb, SKB_GSO_IPXIP4))
 		goto tx_error;
 
-	skb_set_inner_ipproto(skb, IPPROTO_IPIP);
+	skb_set_inner_ipproto(skb, ipproto);
 
-	ip_tunnel_xmit(skb, dev, tiph, tiph->protocol);
+	ip_tunnel_xmit(skb, dev, tiph, ipproto);
 	return NETDEV_TX_OK;
 
 tx_error:
@@ -234,6 +280,20 @@ tx_error:
 	return NETDEV_TX_OK;
 }
 
+static bool ipip_tunnel_ioctl_verify_protocol(u8 ipproto)
+{
+	switch (ipproto) {
+	case 0:
+	case IPPROTO_IPIP:
+#if IS_ENABLED(CONFIG_MPLS)
+	case IPPROTO_MPLS:
+#endif
+		return true;
+	}
+
+	return false;
+}
+
 static int
 ipip_tunnel_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
 {
@@ -244,7 +304,8 @@ ipip_tunnel_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
 		return -EFAULT;
 
 	if (cmd == SIOCADDTUNNEL || cmd == SIOCCHGTUNNEL) {
-		if (p.iph.version != 4 || p.iph.protocol != IPPROTO_IPIP ||
+		if (p.iph.version != 4 ||
+		    !ipip_tunnel_ioctl_verify_protocol(p.iph.protocol) ||
 		    p.iph.ihl != 5 || (p.iph.frag_off&htons(~IP_DF)))
 			return -EINVAL;
 	}
@@ -301,10 +362,23 @@ static int ipip_tunnel_init(struct net_device *dev)
 
 	tunnel->tun_hlen = 0;
 	tunnel->hlen = tunnel->tun_hlen + tunnel->encap_hlen;
-	tunnel->parms.iph.protocol = IPPROTO_IPIP;
 	return ip_tunnel_init(dev);
 }
 
+static int ipip_tunnel_validate(struct nlattr *tb[], struct nlattr *data[])
+{
+	u8 proto;
+
+	if (!data || !data[IFLA_IPTUN_PROTO])
+		return 0;
+
+	proto = nla_get_u8(data[IFLA_IPTUN_PROTO]);
+	if (proto != IPPROTO_IPIP && proto != IPPROTO_MPLS && proto != 0)
+		return -EINVAL;
+
+	return 0;
+}
+
 static void ipip_netlink_parms(struct nlattr *data[],
 			       struct ip_tunnel_parm *parms)
 {
@@ -335,6 +409,9 @@ static void ipip_netlink_parms(struct nlattr *data[],
 	if (data[IFLA_IPTUN_TOS])
 		parms->iph.tos = nla_get_u8(data[IFLA_IPTUN_TOS]);
 
+	if (data[IFLA_IPTUN_PROTO])
+		parms->iph.protocol = nla_get_u8(data[IFLA_IPTUN_PROTO]);
+
 	if (!data[IFLA_IPTUN_PMTUDISC] || nla_get_u8(data[IFLA_IPTUN_PMTUDISC]))
 		parms->iph.frag_off = htons(IP_DF);
 }
@@ -427,6 +504,8 @@ static size_t ipip_get_size(const struct net_device *dev)
 		nla_total_size(1) +
 		/* IFLA_IPTUN_TOS */
 		nla_total_size(1) +
+		/* IFLA_IPTUN_PROTO */
+		nla_total_size(1) +
 		/* IFLA_IPTUN_PMTUDISC */
 		nla_total_size(1) +
 		/* IFLA_IPTUN_ENCAP_TYPE */
@@ -450,6 +529,7 @@ static int ipip_fill_info(struct sk_buff *skb, const struct net_device *dev)
 	    nla_put_in_addr(skb, IFLA_IPTUN_REMOTE, parm->iph.daddr) ||
 	    nla_put_u8(skb, IFLA_IPTUN_TTL, parm->iph.ttl) ||
 	    nla_put_u8(skb, IFLA_IPTUN_TOS, parm->iph.tos) ||
+	    nla_put_u8(skb, IFLA_IPTUN_PROTO, parm->iph.protocol) ||
 	    nla_put_u8(skb, IFLA_IPTUN_PMTUDISC,
 		       !!(parm->iph.frag_off & htons(IP_DF))))
 		goto nla_put_failure;
@@ -476,6 +556,7 @@ static const struct nla_policy ipip_policy[IFLA_IPTUN_MAX + 1] = {
 	[IFLA_IPTUN_REMOTE]		= { .type = NLA_U32 },
 	[IFLA_IPTUN_TTL]		= { .type = NLA_U8 },
 	[IFLA_IPTUN_TOS]		= { .type = NLA_U8 },
+	[IFLA_IPTUN_PROTO]		= { .type = NLA_U8 },
 	[IFLA_IPTUN_PMTUDISC]		= { .type = NLA_U8 },
 	[IFLA_IPTUN_ENCAP_TYPE]		= { .type = NLA_U16 },
 	[IFLA_IPTUN_ENCAP_FLAGS]	= { .type = NLA_U16 },
@@ -489,6 +570,7 @@ static struct rtnl_link_ops ipip_link_ops __read_mostly = {
 	.policy		= ipip_policy,
 	.priv_size	= sizeof(struct ip_tunnel),
 	.setup		= ipip_tunnel_setup,
+	.validate	= ipip_tunnel_validate,
 	.newlink	= ipip_newlink,
 	.changelink	= ipip_changelink,
 	.dellink	= ip_tunnel_dellink,
@@ -503,6 +585,14 @@ static struct xfrm_tunnel ipip_handler __read_mostly = {
 	.priority	=	1,
 };
 
+#if IS_ENABLED(CONFIG_MPLS)
+static struct xfrm_tunnel mplsip_handler __read_mostly = {
+	.handler	=	mplsip_rcv,
+	.err_handler	=	ipip_err,
+	.priority	=	1,
+};
+#endif
+
 static int __net_init ipip_init_net(struct net *net)
 {
 	return ip_tunnel_init_net(net, ipip_net_id, &ipip_link_ops, "tunl0");
@@ -525,7 +615,7 @@ static int __init ipip_init(void)
 {
 	int err;
 
-	pr_info("ipip: IPv4 over IPv4 tunneling driver\n");
+	pr_info("ipip: IPv4 and MPLS over IPv4 tunneling driver\n");
 
 	err = register_pernet_device(&ipip_net_ops);
 	if (err < 0)
@@ -533,8 +623,15 @@ static int __init ipip_init(void)
 	err = xfrm4_tunnel_register(&ipip_handler, AF_INET);
 	if (err < 0) {
 		pr_info("%s: can't register tunnel\n", __func__);
-		goto xfrm_tunnel_failed;
+		goto xfrm_tunnel_ipip_failed;
+	}
+#if IS_ENABLED(CONFIG_MPLS)
+	err = xfrm4_tunnel_register(&mplsip_handler, AF_MPLS);
+	if (err < 0) {
+		pr_info("%s: can't register tunnel\n", __func__);
+		goto xfrm_tunnel_mplsip_failed;
 	}
+#endif
 	err = rtnl_link_register(&ipip_link_ops);
 	if (err < 0)
 		goto rtnl_link_failed;
@@ -543,8 +640,13 @@ out:
 	return err;
 
 rtnl_link_failed:
+#if IS_ENABLED(CONFIG_MPLS)
+	xfrm4_tunnel_deregister(&mplsip_handler, AF_INET);
+xfrm_tunnel_mplsip_failed:
+
+#endif
 	xfrm4_tunnel_deregister(&ipip_handler, AF_INET);
-xfrm_tunnel_failed:
+xfrm_tunnel_ipip_failed:
 	unregister_pernet_device(&ipip_net_ops);
 	goto out;
 }
@@ -554,7 +656,10 @@ static void __exit ipip_fini(void)
 	rtnl_link_unregister(&ipip_link_ops);
 	if (xfrm4_tunnel_deregister(&ipip_handler, AF_INET))
 		pr_info("%s: can't deregister tunnel\n", __func__);
-
+#if IS_ENABLED(CONFIG_MPLS)
+	if (xfrm4_tunnel_deregister(&mplsip_handler, AF_MPLS))
+		pr_info("%s: can't deregister tunnel\n", __func__);
+#endif
 	unregister_pernet_device(&ipip_net_ops);
 }
 
-- 
2.7.0.rc3.207.g0ac5344

^ permalink raw reply related	[flat|nested] 9+ messages in thread

* [PATCH net-next v2 4/4] mpls: allow routes on ipip and sit devices
  2016-07-07  5:56 [PATCH net-next v2 0/4] net: support MPLS in IPv4 and UDP Simon Horman
                   ` (2 preceding siblings ...)
  2016-07-07  5:56 ` [PATCH net-next v2 3/4] ipip: " Simon Horman
@ 2016-07-07  5:56 ` Simon Horman
  2016-07-07  9:30 ` [PATCH net-next v2 0/4] net: support MPLS in IPv4 and UDP Thomas Morin
                   ` (2 subsequent siblings)
  6 siblings, 0 replies; 9+ messages in thread
From: Simon Horman @ 2016-07-07  5:56 UTC (permalink / raw)
  To: David Miller; +Cc: Tom Herbert, netdev, Simon Horman

Allow MPLS routes on IPIP and SIT devices now that they
support forwarding MPLS packets.

Signed-off-by: Simon Horman <simon.horman@netronome.com>
Reviewed-by: Dinan Gunawardena <dinan.gunawardena@netronome.com>
---
 net/mpls/af_mpls.c | 6 ++++--
 1 file changed, 4 insertions(+), 2 deletions(-)

diff --git a/net/mpls/af_mpls.c b/net/mpls/af_mpls.c
index e9beaa58573c..5c161e7759b5 100644
--- a/net/mpls/af_mpls.c
+++ b/net/mpls/af_mpls.c
@@ -1009,10 +1009,12 @@ static int mpls_dev_notify(struct notifier_block *this, unsigned long event,
 	unsigned int flags;
 
 	if (event == NETDEV_REGISTER) {
-		/* For now just support Ethernet and IPGRE devices */
+		/* For now just support Ethernet, IPGRE, SIT and IPIP devices */
 		if (dev->type == ARPHRD_ETHER ||
 		    dev->type == ARPHRD_LOOPBACK ||
-		    dev->type == ARPHRD_IPGRE) {
+		    dev->type == ARPHRD_IPGRE ||
+		    dev->type == ARPHRD_SIT ||
+		    dev->type == ARPHRD_TUNNEL) {
 			mdev = mpls_add_dev(dev);
 			if (IS_ERR(mdev))
 				return notifier_from_errno(PTR_ERR(mdev));
-- 
2.7.0.rc3.207.g0ac5344

^ permalink raw reply related	[flat|nested] 9+ messages in thread

* Re: [PATCH net-next v2 0/4] net: support MPLS in IPv4 and UDP
  2016-07-07  5:56 [PATCH net-next v2 0/4] net: support MPLS in IPv4 and UDP Simon Horman
                   ` (3 preceding siblings ...)
  2016-07-07  5:56 ` [PATCH net-next v2 4/4] mpls: allow routes on ipip and sit devices Simon Horman
@ 2016-07-07  9:30 ` Thomas Morin
  2016-07-08 11:25 ` Manish Chopra
  2016-07-09 21:47 ` David Miller
  6 siblings, 0 replies; 9+ messages in thread
From: Thomas Morin @ 2016-07-07  9:30 UTC (permalink / raw)
  To: Simon Horman, David Miller; +Cc: Tom Herbert, netdev

Hi Simon,

Great to see this being supported!

Something that would be a nice improvement would be a way to control the 
outer IP destination in the route nexthop, rather than via a tunnel 
interface remote IP which has the drawback of requiring one tunnel per 
remote endpoint, with the associated scaling issue and the book-keeping 
related to creating/deleting them.

Tom had suggested to me that it could be done in the lwtunnel framework, 
which seems indeed to make sense.

Best,

-Thomas

PS: two side notes on your sample configuration:
- I guess it should be "echo 1 > /proc/sys/net/mpls/conf/tun1/input" 
instead of "echo 1 > /proc/sys/net/mpls/conf/eth0/input"
- couldn't you skip "ip addr .. dev tun1", and just do "ip -f mpls route 
add 100 as 200/300 dev tun1" ?


2016-07-07, Simon Horman:
> This short series provides support for MPLS in IPv4 (RFC4023), and by
> virtue of FOU, MPLS in UDP (RFC7510).
>
> The changes are as follows:
> 1. Teach tunnel4.c about AF_MPLS, it already understands AF_INET and
>    AF_INET6
> 2. Enhance IPIP and SIT to handle MPLS. Both already handle IPv4.
>    SIT also already handles IPv6.
> 3. Trivially enhance MPLS to allow routes over SIT and IPIP tunnels.
>
> A corresponding patch set for iproute2 has also been provided.
>
>
> Changes since v1
> * Correct inverted IPIP protocol logic in SIT patch
> * Provide usage example below
>
>
> Sample configuration follows:
>
> * The following creates a tunnel and routes MPLS packets whose outermost
>   label is 100 over it. The forwarded packets will have the outermost label
>   stack entry, 100, removed and two label stack entries added, the
>   outermost having label 200 and the next having label 300.
>
>   The local end-point for the tunnel is 10.0.99.192 and the remote
>   endpoint is 10.0.99.193.
>
>   The local address for encapsulated packets is 10.0.98.192 and the
>   remote address is 10.0.98.193.
>
>   # Create an MPLS over IPv4 tunnel using the IPIP driver
>   ip link add name tun1 type ipip remote 10.0.99.193 local 10.0.99.192 \
> 	ttl 225 mode mplsip
>
>   # Bring the tunnel up and an add an IPv4 address and route
>   ip link set up dev tun1
>   ip addr add 10.0.98.192/24 dev tun1
>
>   # Set MPLS route
>   # Allow MPLS forwarding of packets recieved on eth0
>   echo 1 > /proc/sys/net/mpls/conf/eth0/input
>   # Larger than label to be routed (100)
>   echo 101 > /proc/sys/net/mpls/platform_labels
>   ip -f mpls route add 100 as 200/300 via inet 10.0.98.193
>
>
> * For FOU (in this case MPLS over UDP) a tunnel may created using:
>
>   # Packets recieved on UDP port 6635 are MPLS over UDP (IP proto 137)
>   ip fou add port 6635 ipproto 137
>   # Create the tunnel netdev
>   ip link add name tun1 type ipip remote 10.0.99.193 local 10.0.99.192 \
> 	ttl 225 mode mplsip encap fou encap-sport auto encap-dport 6635
>
>   IPv4 address, link and route, and MPLS routing commands are as per
>   the MPLS over IPv4 example
>
> * To use the SIT driver instead of the IPIP driver "ipip" may be substituted
>   for "sit" in the above examples.
>
> * To create a tunnel that forwards and receives all supported
>   inner-protocols "mplsip" may be substituted for "any" in the above
>   examples.
>
>   For the IPIP driver this configures both IPv4 and MPLS over IPv4.
>   For the SIT driver this configures IPv6, IPv4 and MPLS over IPv4.
>
>
> Simon Horman (4):
>   tunnels: support MPLS over IPv4 tunnels
>   sit: support MPLS over IPv4
>   ipip: support MPLS over IPv4
>   mpls: allow routes on ipip and sit devices
>
>  net/ipv4/ipip.c    | 137 ++++++++++++++++++++++++++++++++++++++++++++++-------
>  net/ipv4/tunnel4.c |  77 ++++++++++++++++++++++++++----
>  net/ipv6/sit.c     |  93 +++++++++++++++++++++++++++++-------
>  net/mpls/af_mpls.c |   6 ++-
>  4 files changed, 269 insertions(+), 44 deletions(-)
>

^ permalink raw reply	[flat|nested] 9+ messages in thread

* RE: [PATCH net-next v2 0/4] net: support MPLS in IPv4 and UDP
  2016-07-07  5:56 [PATCH net-next v2 0/4] net: support MPLS in IPv4 and UDP Simon Horman
                   ` (4 preceding siblings ...)
  2016-07-07  9:30 ` [PATCH net-next v2 0/4] net: support MPLS in IPv4 and UDP Thomas Morin
@ 2016-07-08 11:25 ` Manish Chopra
  2016-07-09 21:47 ` David Miller
  6 siblings, 0 replies; 9+ messages in thread
From: Manish Chopra @ 2016-07-08 11:25 UTC (permalink / raw)
  To: Simon Horman, David Miller; +Cc: Tom Herbert, netdev

> -----Original Message-----
> From: netdev-owner@vger.kernel.org [mailto:netdev-owner@vger.kernel.org]
> On Behalf Of Simon Horman
> Sent: Thursday, July 07, 2016 11:26 AM
> To: David Miller <davem@davemloft.net>
> Cc: Tom Herbert <tom@herbertland.com>; netdev <netdev@vger.kernel.org>;
> Simon Horman <simon.horman@netronome.com>
> Subject: [PATCH net-next v2 0/4] net: support MPLS in IPv4 and UDP
> 
> This short series provides support for MPLS in IPv4 (RFC4023), and by
> virtue of FOU, MPLS in UDP (RFC7510).
> 
> The changes are as follows:
> 1. Teach tunnel4.c about AF_MPLS, it already understands AF_INET and
>    AF_INET6
> 2. Enhance IPIP and SIT to handle MPLS. Both already handle IPv4.
>    SIT also already handles IPv6.
> 3. Trivially enhance MPLS to allow routes over SIT and IPIP tunnels.
> 
> A corresponding patch set for iproute2 has also been provided.
> 
> 
> Changes since v1
> * Correct inverted IPIP protocol logic in SIT patch
> * Provide usage example below
> 
> 
> Sample configuration follows:
> 
> * The following creates a tunnel and routes MPLS packets whose outermost
>   label is 100 over it. The forwarded packets will have the outermost label
>   stack entry, 100, removed and two label stack entries added, the
>   outermost having label 200 and the next having label 300.
> 
>   The local end-point for the tunnel is 10.0.99.192 and the remote
>   endpoint is 10.0.99.193.
> 
>   The local address for encapsulated packets is 10.0.98.192 and the
>   remote address is 10.0.98.193.
> 
>   # Create an MPLS over IPv4 tunnel using the IPIP driver
>   ip link add name tun1 type ipip remote 10.0.99.193 local 10.0.99.192 \
> 	ttl 225 mode mplsip
> 
>   # Bring the tunnel up and an add an IPv4 address and route
>   ip link set up dev tun1
>   ip addr add 10.0.98.192/24 dev tun1
> 
>   # Set MPLS route
>   # Allow MPLS forwarding of packets recieved on eth0
>   echo 1 > /proc/sys/net/mpls/conf/eth0/input
>   # Larger than label to be routed (100)
>   echo 101 > /proc/sys/net/mpls/platform_labels
>   ip -f mpls route add 100 as 200/300 via inet 10.0.98.193
> 
> 
> * For FOU (in this case MPLS over UDP) a tunnel may created using:
> 
>   # Packets recieved on UDP port 6635 are MPLS over UDP (IP proto 137)
>   ip fou add port 6635 ipproto 137
>   # Create the tunnel netdev
>   ip link add name tun1 type ipip remote 10.0.99.193 local 10.0.99.192 \
> 	ttl 225 mode mplsip encap fou encap-sport auto encap-dport 6635
> 
>   IPv4 address, link and route, and MPLS routing commands are as per
>   the MPLS over IPv4 example
> 
> * To use the SIT driver instead of the IPIP driver "ipip" may be substituted
>   for "sit" in the above examples.
> 
> * To create a tunnel that forwards and receives all supported
>   inner-protocols "mplsip" may be substituted for "any" in the above
>   examples.
> 
>   For the IPIP driver this configures both IPv4 and MPLS over IPv4.
>   For the SIT driver this configures IPv6, IPv4 and MPLS over IPv4.
> 
> 

Hi Simon, I have questions in general for how to test MPLS in Linux [Earlier, I have asked the same on this forum but unfortunately, no one responded :-( ]
Saw your patches on MPLS with tunnels and hope that you might be the one to ask regarding this :-)

As I see usage examples above - I think this can be tested using just two linux hosts connected back to back [without any router/switch being present in between]. Right ?
Basically, In similar context, I want to test MPLS packets/traffic between just two base NIC driver interfaces connected back to back [Please see below configuration I have],
but so far I am not able to achieve such configuration which can drive MPLS traffic through the hardware [I don't even know if it's possible to achieve or not in this topology,
couldn't find anything related to this ].

Host A                                     Host B
########|                 	|########
        Eth0  <===========> Eth1
########|                	|########
IP: 192.168.44.20           IP: 192.168.44.21    

If there is such possible configuration using iproute2 , please let me know. I appreciate your help for this.

Thanks,
Manish

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: [PATCH net-next v2 0/4] net: support MPLS in IPv4 and UDP
  2016-07-07  5:56 [PATCH net-next v2 0/4] net: support MPLS in IPv4 and UDP Simon Horman
                   ` (5 preceding siblings ...)
  2016-07-08 11:25 ` Manish Chopra
@ 2016-07-09 21:47 ` David Miller
  2016-07-10  0:12   ` Simon Horman
  6 siblings, 1 reply; 9+ messages in thread
From: David Miller @ 2016-07-09 21:47 UTC (permalink / raw)
  To: simon.horman; +Cc: tom, netdev

From: Simon Horman <simon.horman@netronome.com>
Date: Thu,  7 Jul 2016 07:56:11 +0200

> This short series provides support for MPLS in IPv4 (RFC4023), and by
> virtue of FOU, MPLS in UDP (RFC7510).

Series applied, thanks Simon.

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: [PATCH net-next v2 0/4] net: support MPLS in IPv4 and UDP
  2016-07-09 21:47 ` David Miller
@ 2016-07-10  0:12   ` Simon Horman
  0 siblings, 0 replies; 9+ messages in thread
From: Simon Horman @ 2016-07-10  0:12 UTC (permalink / raw)
  To: David Miller; +Cc: tom, netdev

On Sat, Jul 09, 2016 at 05:47:32PM -0400, David Miller wrote:
> From: Simon Horman <simon.horman@netronome.com>
> Date: Thu,  7 Jul 2016 07:56:11 +0200
> 
> > This short series provides support for MPLS in IPv4 (RFC4023), and by
> > virtue of FOU, MPLS in UDP (RFC7510).
> 
> Series applied, thanks Simon.

Thanks.

It looks like I messed up the error path in
"tunnels: support MPLS over IPv4 tunnels" as flagged by the
kbuild test robot.

I'll get a fix for that to you soon.

^ permalink raw reply	[flat|nested] 9+ messages in thread

end of thread, other threads:[~2016-07-10  0:12 UTC | newest]

Thread overview: 9+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2016-07-07  5:56 [PATCH net-next v2 0/4] net: support MPLS in IPv4 and UDP Simon Horman
2016-07-07  5:56 ` [PATCH net-next v2 1/4] tunnels: support MPLS over IPv4 tunnels Simon Horman
2016-07-07  5:56 ` [PATCH net-next v2 2/4] sit: support MPLS over IPv4 Simon Horman
2016-07-07  5:56 ` [PATCH net-next v2 3/4] ipip: " Simon Horman
2016-07-07  5:56 ` [PATCH net-next v2 4/4] mpls: allow routes on ipip and sit devices Simon Horman
2016-07-07  9:30 ` [PATCH net-next v2 0/4] net: support MPLS in IPv4 and UDP Thomas Morin
2016-07-08 11:25 ` Manish Chopra
2016-07-09 21:47 ` David Miller
2016-07-10  0:12   ` Simon Horman

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.