[PATCH v3 0/1] Introduce MPLS over GRE

STALE3264d

Revision v3 of 6 in this series.

6 messages, 2 authors, 2017-09-27 · open the first message on its own page

[PATCH v3 0/1] Introduce MPLS over GRE

From: Amine Kherbouche <hidden>
Date: 2017-09-27 09:37:38

This series introduces the MPLS over GRE encapsulation (RFC 4023).

Various applications of MPLS make use of label stacks with multiple
entries.  In some cases, it is possible to replace the top label of
the stack with an IP-based encapsulation, thereby, it is possible for
two LSRs that are adjacent on an LSP to be separated by an IP network,
even if that IP network does not provide MPLS.

Changes in v3:
  - remove mpls_forward() function exportation patch.
  - wrap efficiently mpls iptunnel add/del functions and dependent
    function/structure.
  - move mpls_gre_rcv to af_mpls.c file and export it.
  - remove unnecessary functions.
 
Changes in v2:
  - wrap ip tunnel functions under ifdef in mpls file.
  - fix indentation.
  - check return code.

An example of configuration:


         node1                LER1                       LER2                node2
        +-----+             +------+                   +------+             +-----+
        |     |             |      |                   |      |             |     |
        |     |             |      |p3  GRE tunnel   p4|      |             |     |
        |     |p1         p2|      +-------------------+      |p5         p6|     |
        |     +-------------+      +-------------------+      +------------+|     |
        |     |10.100.0.0/24|      |                   |      |10.200.0.0/24|     |
        |     |fd00:100::/64|      |  10.125.0.0/24    |      |fd00:200::/64|     |
        |     |             |      |  fd00:125::/64    |      |             |     |
        |     |             |      |                   |      |             |     |
        |     |             |      |                   |      |             |     |
        |     |             |      |                   |      |             |     |
        |     |             |      |                   |      |             |     |
        +-----+             +------+                   +------+             +-----+


		###	node1	###

ip link set p1 up
ip addr add 10.100.0.1/24 dev p1

		###	LER1	###

ip link set p2 up
ip addr add 10.100.0.2/24 dev p2

ip link set p3 up
ip addr add 10.125.0.1/24 dev p3

modprobe mpls_router
sysctl -w net.mpls.conf.p2.input=1
sysctl -w net.mpls.conf.p3.input=1
sysctl -w net.mpls.platform_labels=1000

ip link add gre1 type gre ttl 64 local 10.125.0.1 remote 10.125.0.2 dev p3
ip link set dev gre1 up

ip -M route add 111 as 222 dev gre1
ip -M route add 555 as 666 via inet 10.100.0.1 dev p2

		###	LER2	###

ip link set p5 up
ip addr add 10.200.0.2/24 dev p5

ip link set p4 up
ip addr add 10.125.0.2/24 dev p4

modprobe mpls_router
sysctl -w net.mpls.conf.p4.input=1
sysctl -w net.mpls.conf.p5.input=1
sysctl -w net.mpls.platform_labels=1000

ip link add gre1 type gre ttl 64 local 10.125.0.2 remote 10.125.0.1 dev p4
ip link set dev gre1 up

ip -M route add 444 as 555 dev gre1
ip -M route add 222 as 333 via inet 10.200.0.1 dev p5

		###	node2	###

ip link set p6 up
ip addr add 10.200.0.1/24 dev p6


Now using this scapy to forge and send packets from the port p1 of node1:

p = Ether(src='de:ed:01:0c:41:09', dst='de:ed:01:2f:3b:ba')
p /= MPLS(s=1, ttl=64, label=111)/Raw(load='\xde')
sendp(p, iface="p1", count=20, inter=0.1)

Amine Kherbouche (1):
  ip_tunnel: add mpls over gre encapsulation

 include/linux/mpls.h           |  2 ++
 include/uapi/linux/if_tunnel.h |  1 +
 net/ipv4/ip_gre.c              | 11 +++++++++
 net/ipv6/ip6_gre.c             | 11 +++++++++
 net/mpls/af_mpls.c             | 52 ++++++++++++++++++++++++++++++++++++++++++
 5 files changed, 77 insertions(+)

-- 
2.1.4

[PATCH v3 1/1] ip_tunnel: add mpls over gre encapsulation

From: Amine Kherbouche <hidden>
Date: 2017-09-27 09:37:39

This commit introduces the MPLSoGRE support (RFC 4023), using ip tunnel
API.

Encap:
  - Add a new iptunnel type mpls.
  - Share tx path: gre type mpls loaded from skb->protocol.

Decap:
  - pull gre hdr and call mpls_forward().

Signed-off-by: Amine Kherbouche <redacted>
---
 include/linux/mpls.h           |  2 ++
 include/uapi/linux/if_tunnel.h |  1 +
 net/ipv4/ip_gre.c              | 11 +++++++++
 net/ipv6/ip6_gre.c             | 11 +++++++++
 net/mpls/af_mpls.c             | 52 ++++++++++++++++++++++++++++++++++++++++++
 5 files changed, 77 insertions(+)
diff --git a/include/linux/mpls.h b/include/linux/mpls.h
index 384fb22..57203c1 100644
--- a/include/linux/mpls.h
+++ b/include/linux/mpls.h
@@ -8,4 +8,6 @@
 #define MPLS_TC_MASK		(MPLS_LS_TC_MASK >> MPLS_LS_TC_SHIFT)
 #define MPLS_LABEL_MASK		(MPLS_LS_LABEL_MASK >> MPLS_LS_LABEL_SHIFT)
 
+int mpls_gre_rcv(struct sk_buff *skb, int gre_hdr_len);
+
 #endif  /* _LINUX_MPLS_H */
diff --git a/include/uapi/linux/if_tunnel.h b/include/uapi/linux/if_tunnel.h
index 2e52088..a2f48c0 100644
--- a/include/uapi/linux/if_tunnel.h
+++ b/include/uapi/linux/if_tunnel.h
@@ -84,6 +84,7 @@ enum tunnel_encap_types {
 	TUNNEL_ENCAP_NONE,
 	TUNNEL_ENCAP_FOU,
 	TUNNEL_ENCAP_GUE,
+	TUNNEL_ENCAP_MPLS,
 };
 
 #define TUNNEL_ENCAP_FLAG_CSUM		(1<<0)
diff --git a/net/ipv4/ip_gre.c b/net/ipv4/ip_gre.c
index 9cee986..0a898f4 100644
--- a/net/ipv4/ip_gre.c
+++ b/net/ipv4/ip_gre.c
@@ -32,6 +32,9 @@
 #include <linux/netfilter_ipv4.h>
 #include <linux/etherdevice.h>
 #include <linux/if_ether.h>
+#if IS_ENABLED(CONFIG_MPLS)
+#include <linux/mpls.h>
+#endif
 
 #include <net/sock.h>
 #include <net/ip.h>
@@ -412,6 +415,14 @@ static int gre_rcv(struct sk_buff *skb)
 			return 0;
 	}
 
+	if (unlikely(tpi.proto == htons(ETH_P_MPLS_UC))) {
+#if IS_ENABLED(CONFIG_MPLS)
+		return mpls_gre_rcv(skb, hdr_len);
+#else
+		goto drop;
+#endif
+	}
+
 	if (ipgre_rcv(skb, &tpi, hdr_len) == PACKET_RCVD)
 		return 0;
 
diff --git a/net/ipv6/ip6_gre.c b/net/ipv6/ip6_gre.c
index c82d41e..5a0f5e1 100644
--- a/net/ipv6/ip6_gre.c
+++ b/net/ipv6/ip6_gre.c
@@ -34,6 +34,9 @@
 #include <linux/hash.h>
 #include <linux/if_tunnel.h>
 #include <linux/ip6_tunnel.h>
+#if IS_ENABLED(CONFIG_MPLS)
+#include <linux/mpls.h>
+#endif
 
 #include <net/sock.h>
 #include <net/ip.h>
@@ -476,6 +479,14 @@ static int gre_rcv(struct sk_buff *skb)
 	if (hdr_len < 0)
 		goto drop;
 
+	if (unlikely(tpi.proto == htons(ETH_P_MPLS_UC))) {
+#if IS_ENABLED(CONFIG_MPLS)
+		return mpls_gre_rcv(skb, hdr_len);
+#else
+		goto drop;
+#endif
+	}
+
 	if (iptunnel_pull_header(skb, hdr_len, tpi.proto, false))
 		goto drop;
 
diff --git a/net/mpls/af_mpls.c b/net/mpls/af_mpls.c
index c5b9ce4..53ec7c0 100644
--- a/net/mpls/af_mpls.c
+++ b/net/mpls/af_mpls.c
@@ -16,6 +16,7 @@
 #include <net/arp.h>
 #include <net/ip_fib.h>
 #include <net/netevent.h>
+#include <net/ip_tunnels.h>
 #include <net/netns/generic.h>
 #if IS_ENABLED(CONFIG_IPV6)
 #include <net/ipv6.h>
@@ -39,6 +40,36 @@ static int one = 1;
 static int label_limit = (1 << 20) - 1;
 static int ttl_max = 255;
 
+#if IS_ENABLED(CONFIG_NET_IP_TUNNEL)
+size_t ipgre_mpls_encap_hlen(struct ip_tunnel_encap *e)
+{
+	return sizeof(struct mpls_shim_hdr);
+}
+
+static const struct ip_tunnel_encap_ops mpls_iptun_ops = {
+	.encap_hlen	= ipgre_mpls_encap_hlen,
+};
+
+static int ipgre_tunnel_encap_add_mpls_ops(void)
+{
+	return ip_tunnel_encap_add_ops(&mpls_iptun_ops, TUNNEL_ENCAP_MPLS);
+}
+
+static void ipgre_tunnel_encap_del_mpls_ops(void)
+{
+	ip_tunnel_encap_del_ops(&mpls_iptun_ops, TUNNEL_ENCAP_MPLS);
+}
+#else
+static int ipgre_tunnel_encap_add_mpls_ops(void)
+{
+	return 0;
+}
+
+static void ipgre_tunnel_encap_del_mpls_ops(void)
+{
+}
+#endif
+
 static void rtmsg_lfib(int event, u32 label, struct mpls_route *rt,
 		       struct nlmsghdr *nlh, struct net *net, u32 portid,
 		       unsigned int nlm_flags);
@@ -443,6 +474,22 @@ static int mpls_forward(struct sk_buff *skb, struct net_device *dev,
 	return NET_RX_DROP;
 }
 
+int mpls_gre_rcv(struct sk_buff *skb, int gre_hdr_len)
+{
+	if (unlikely(!pskb_may_pull(skb, gre_hdr_len)))
+		goto drop;
+
+	/* Pop GRE hdr and reset the skb */
+	skb_pull(skb, gre_hdr_len);
+	skb_reset_network_header(skb);
+
+	return mpls_forward(skb, skb->dev, NULL, NULL);
+drop:
+	kfree_skb(skb);
+	return NET_RX_DROP;
+}
+EXPORT_SYMBOL(mpls_gre_rcv);
+
 static struct packet_type mpls_packet_type __read_mostly = {
 	.type = cpu_to_be16(ETH_P_MPLS_UC),
 	.func = mpls_forward,
@@ -2485,6 +2532,10 @@ static int __init mpls_init(void)
 		      0);
 	rtnl_register(PF_MPLS, RTM_GETNETCONF, mpls_netconf_get_devconf,
 		      mpls_netconf_dump_devconf, 0);
+	err = ipgre_tunnel_encap_add_mpls_ops();
+	if (err)
+		pr_err("Can't add mpls over gre tunnel ops\n");
+
 	err = 0;
 out:
 	return err;
@@ -2502,6 +2553,7 @@ static void __exit mpls_exit(void)
 	dev_remove_pack(&mpls_packet_type);
 	unregister_netdevice_notifier(&mpls_dev_notifier);
 	unregister_pernet_subsys(&mpls_net_ops);
+	ipgre_tunnel_encap_del_mpls_ops();
 }
 module_exit(mpls_exit);
 
-- 
2.1.4

Re: [PATCH v3 1/1] ip_tunnel: add mpls over gre encapsulation

From: Roopa Prabhu <hidden>
Date: 2017-09-27 15:36:12

On Wed, Sep 27, 2017 at 2:37 AM, Amine Kherbouche
[off-list ref] wrote:
quoted hunk
This commit introduces the MPLSoGRE support (RFC 4023), using ip tunnel
API.

Encap:
  - Add a new iptunnel type mpls.
  - Share tx path: gre type mpls loaded from skb->protocol.

Decap:
  - pull gre hdr and call mpls_forward().

Signed-off-by: Amine Kherbouche <redacted>
---
 include/linux/mpls.h           |  2 ++
 include/uapi/linux/if_tunnel.h |  1 +
 net/ipv4/ip_gre.c              | 11 +++++++++
 net/ipv6/ip6_gre.c             | 11 +++++++++
 net/mpls/af_mpls.c             | 52 ++++++++++++++++++++++++++++++++++++++++++
 5 files changed, 77 insertions(+)
diff --git a/include/linux/mpls.h b/include/linux/mpls.h
index 384fb22..57203c1 100644
--- a/include/linux/mpls.h
+++ b/include/linux/mpls.h
@@ -8,4 +8,6 @@
 #define MPLS_TC_MASK           (MPLS_LS_TC_MASK >> MPLS_LS_TC_SHIFT)
 #define MPLS_LABEL_MASK                (MPLS_LS_LABEL_MASK >> MPLS_LS_LABEL_SHIFT)

+int mpls_gre_rcv(struct sk_buff *skb, int gre_hdr_len);
+
 #endif  /* _LINUX_MPLS_H */
diff --git a/include/uapi/linux/if_tunnel.h b/include/uapi/linux/if_tunnel.h
index 2e52088..a2f48c0 100644
--- a/include/uapi/linux/if_tunnel.h
+++ b/include/uapi/linux/if_tunnel.h
@@ -84,6 +84,7 @@ enum tunnel_encap_types {
        TUNNEL_ENCAP_NONE,
        TUNNEL_ENCAP_FOU,
        TUNNEL_ENCAP_GUE,
+       TUNNEL_ENCAP_MPLS,
 };

 #define TUNNEL_ENCAP_FLAG_CSUM         (1<<0)
diff --git a/net/ipv4/ip_gre.c b/net/ipv4/ip_gre.c
index 9cee986..0a898f4 100644
--- a/net/ipv4/ip_gre.c
+++ b/net/ipv4/ip_gre.c
@@ -32,6 +32,9 @@
 #include <linux/netfilter_ipv4.h>
 #include <linux/etherdevice.h>
 #include <linux/if_ether.h>
+#if IS_ENABLED(CONFIG_MPLS)
+#include <linux/mpls.h>
+#endif

 #include <net/sock.h>
 #include <net/ip.h>
@@ -412,6 +415,14 @@ static int gre_rcv(struct sk_buff *skb)
                        return 0;
        }

+       if (unlikely(tpi.proto == htons(ETH_P_MPLS_UC))) {
+#if IS_ENABLED(CONFIG_MPLS)
+               return mpls_gre_rcv(skb, hdr_len);
+#else
+               goto drop;
+#endif
+       }
+
Amine, one small nit here.., if you define mpls_gre_rcv in gre header
(like you had initially), you could do the below...

#if IS_ENABLED(CONFIG_MPLS)
mpls_gre_rcv()
{
     /* real func */
}
#else
mpls_gre_rcv()
{
    kfree_skb(skb)
    return NET_RX_DROP
}
#endif

and the check in gre_rcv() reduces to

if (unlikely(tpi.proto == htons(ETH_P_MPLS_UC)))
        return mpls_gre_rcv(skb, hdr_len);

Which looks much cleaner.

Other than that, looks great. pls add my Acked-by: Roopa Prabhu
[off-list ref] to your next version.

thanks!

Re: [PATCH v3 1/1] ip_tunnel: add mpls over gre encapsulation

From: Amine Kherbouche <hidden>
Date: 2017-09-27 16:08:36


On 09/27/2017 05:36 PM, Roopa Prabhu wrote:
Amine, one small nit here.., if you define mpls_gre_rcv in gre header
(like you had initially), you could do the below...

#if IS_ENABLED(CONFIG_MPLS)
mpls_gre_rcv()
{
     /* real func */
}
#else
mpls_gre_rcv()
{
    kfree_skb(skb)
    return NET_RX_DROP
}
#endif

and the check in gre_rcv() reduces to

if (unlikely(tpi.proto == htons(ETH_P_MPLS_UC)))
        return mpls_gre_rcv(skb, hdr_len);

Which looks much cleaner.
If I do that, do I have to add back the patch that export mpls_forward() 
or just merge it with this one ?

Re: [PATCH v3 1/1] ip_tunnel: add mpls over gre encapsulation

From: Roopa Prabhu <hidden>
Date: 2017-09-27 16:20:08

On Wed, Sep 27, 2017 at 9:08 AM, Amine Kherbouche
[off-list ref] wrote:

On 09/27/2017 05:36 PM, Roopa Prabhu wrote:
quoted
Amine, one small nit here.., if you define mpls_gre_rcv in gre header
(like you had initially), you could do the below...

#if IS_ENABLED(CONFIG_MPLS)
mpls_gre_rcv()
{
     /* real func */
}
#else
mpls_gre_rcv()
{
    kfree_skb(skb)
    return NET_RX_DROP
}
#endif

and the check in gre_rcv() reduces to

if (unlikely(tpi.proto == htons(ETH_P_MPLS_UC)))
        return mpls_gre_rcv(skb, hdr_len);

Which looks much cleaner.

If I do that, do I have to add back the patch that export mpls_forward() or
just merge it with this one ?
I think its better to bring the patch back in.

Re: [PATCH v3 1/1] ip_tunnel: add mpls over gre encapsulation

From: Amine Kherbouche <hidden>
Date: 2017-09-27 16:24:43


On 09/27/2017 06:20 PM, Roopa Prabhu wrote:
I think its better to bring the patch back in.
Sounds good, ok
Keyboard shortcuts
hback out one level
jnext message in thread
kprevious message in thread
ldrill in
Escclose help / fold thread tree
?toggle this help