Subject: Re: Quagga Segment Routing implementation progress
From: David Ahern <[email-masked]>
To: Olivier Dugeon <[email-masked]>, Roopa Prabhu <[email-masked]>
Cc: Vivek Venkatraman <[email-masked]>, Renato Westphal <[email-masked]>, Donald Sharp <[email-masked]>, Lou Berger <[email-masked]>, Dinesh Dutt <[email-masked]>, Daniel Walton <[email-masked]>, Alistair Woodman <[email-masked]>, Martin Winter <[email-masked]>
Date: Tue, 13 Sep 2016 15:50:09 -0600

On 9/13/16 10:36 AM, Olivier Dugeon wrote:
> Hi David,
> 
> I would not put any pressure, but as soon s possible will be the best for us. In fact we are preparing a bunch of demos around PCE, OpenDayLight and Segment Routing. So, for the moment we configure compatible label values (i.e. one's which end in 0x03), but if we could have a patch that solve this issue, it will be very good.

With the attached I can shove 4 labels on the packet at the start and each subsequent hop just pops and forwards. I verified that each hop sees the proper labels in the stack. I know Eric has concerns about performance; we'll address those after it is working.

Let me know if this works for you.
From 57cbcd4661e579ef21d25d97b92abfa917440ccb Mon Sep 17 00:00:00 2001
From: David Ahern <[email-masked]>
Date: Tue, 13 Sep 2016 14:46:15 -0700
Subject: [PATCH] net: mpls: handle more than 2 labels - wip

Also fixes gso on mpls forwards

Signed-off-by: David Ahern <[email-masked]>
---
 include/net/mpls_iptunnel.h |  2 +-
 net/mpls/af_mpls.c          | 28 ++++++++++++++++++++++++++++
 net/mpls/internal.h         |  4 ++--
 3 files changed, 31 insertions(+), 3 deletions(-)

diff --git a/include/net/mpls_iptunnel.h b/include/net/mpls_iptunnel.h
index 179253f9dcfd..f042ae5941eb 100644
--- a/include/net/mpls_iptunnel.h
+++ b/include/net/mpls_iptunnel.h
@@ -14,7 +14,7 @@
 #ifndef _NET_MPLS_IPTUNNEL_H
 #define _NET_MPLS_IPTUNNEL_H 1
 
-#define MAX_NEW_LABELS 2
+#include "internal.h"
 
 struct mpls_iptunnel_encap {
 	u32	label[MAX_NEW_LABELS];
diff --git a/net/mpls/af_mpls.c b/net/mpls/af_mpls.c
index 0e4334cbde17..92d495799892 100644
--- a/net/mpls/af_mpls.c
+++ b/net/mpls/af_mpls.c
@@ -244,6 +244,31 @@ static bool mpls_egress(struct mpls_route *rt, struct sk_buff *skb,
 	return success;
 }
 
+static void mpls_find_network_header(struct sk_buff *skb)
+{
+	unsigned char *p = skb_network_header(skb);
+	struct mpls_entry_decoded dec;
+	struct mpls_shim_hdr *hdr;
+	unsigned int net_offset = 0;
+	int i;
+
+	for (i = 0; i < MAX_NEW_LABELS; ++i) {
+		net_offset += sizeof(*hdr);
+		hdr = (struct mpls_shim_hdr *)p;
+
+		dec = mpls_entry_decode(hdr);
+		if (dec.bos) {
+			skb_set_network_header(skb, net_offset);
+			return;
+		}
+
+		p += sizeof(*hdr);
+	}
+
+	if (i == MAX_NEW_LABELS)
+		pr_warn("mpls_forward: failed to find BOS\n");
+}
+
 static int mpls_forward(struct sk_buff *skb, struct net_device *dev,
 			struct packet_type *pt, struct net_device *orig_dev)
 {
@@ -282,6 +307,9 @@ static int mpls_forward(struct sk_buff *skb, struct net_device *dev,
 	skb_pull(skb, sizeof(*hdr));
 	skb_reset_network_header(skb);
 
+	if (!dec.bos)
+		mpls_find_network_header(skb);
+
 	skb_orphan(skb);
 
 	rt = mpls_route_input_rcu(net, dec.label);
diff --git a/net/mpls/internal.h b/net/mpls/internal.h
index 732a5c17e986..9be992473922 100644
--- a/net/mpls/internal.h
+++ b/net/mpls/internal.h
@@ -22,7 +22,7 @@ struct mpls_dev {
 struct sk_buff;
 
 #define LABEL_NOT_SPECIFIED (1 << 20)
-#define MAX_NEW_LABELS 2
+#define MAX_NEW_LABELS 16
 
 /* This maximum ha length copied from the definition of struct neighbour */
 #define VIA_ALEN_ALIGN sizeof(unsigned long)
@@ -42,10 +42,10 @@ enum mpls_payload_type {
 struct mpls_nh { /* next hop label forwarding entry */
 	struct net_device __rcu *nh_dev;
 	unsigned int		nh_flags;
-	u32			nh_label[MAX_NEW_LABELS];
 	u8			nh_labels;
 	u8			nh_via_alen;
 	u8			nh_via_table;
+	u32			nh_label[MAX_NEW_LABELS];
 };
 
 /* The route, nexthops and vias are stored together in the same memory
-- 
2.1.4