[ovs-dev,ERSPAN,RFC,10/25] compat/erspan: refactor existing erspan code

Message ID 1521756461-3870-11-git-send-email-gvrose8192@gmail.com
State New
Headers show
Series
  • Introduce ERSPAN for OVS
Related show

Commit Message

Gregory Rose March 22, 2018, 10:07 p.m.
From: William Tu <u9012063@gmail.com>

Upstream commit:
    commit 1d7e2ed22f8d9171fa8b629754022f22115b3f03
    Author: William Tu <u9012063@gmail.com>
    Date:   Wed Dec 13 16:38:55 2017 -0800

    net: erspan: refactor existing erspan code

    The patch refactors the existing erspan implementation in order
    to support erspan version 2, which has additional metadata.  So, in
    stead of having one 'struct erspanhdr' holding erspan version 1,
    breaks it into 'struct erspan_base_hdr' and 'struct erspan_metadata'.

    Signed-off-by: William Tu <u9012063@gmail.com>
    Signed-off-by: David S. Miller <davem@davemloft.net>

Partial of the upstream commit.  While doing backports it is pretty
much impossible to fully reconstitute all upstream commits but we're
doing our best.  Other parts of this commit are introduced in the
upcoming monster patch for ip6 gre support.

Cc: William Tu <u9012063@gmail.com>
Signed-off-by: Greg Rose <gvrose8192@gmail.com>
---
 datapath/linux/compat/ip_gre.c | 29 ++++++++++++++++++-----------
 1 file changed, 18 insertions(+), 11 deletions(-)

Patch

diff --git a/datapath/linux/compat/ip_gre.c b/datapath/linux/compat/ip_gre.c
index c4abc6f..eeea4bb 100644
--- a/datapath/linux/compat/ip_gre.c
+++ b/datapath/linux/compat/ip_gre.c
@@ -136,36 +136,43 @@  static int erspan_rcv(struct sk_buff *skb, struct tnl_ptk_info *tpi,
 		      int gre_hdr_len)
 {
 	struct net *net = dev_net(skb->dev);
-	struct metadata_dst tun_dst;
+	struct metadata_dst tun_dst = NULL;
+	struct erspan_base_hdr *ershdr;
+	struct erspan_metadata *pkt_md;
 	struct ip_tunnel_net *itn;
 	struct ip_tunnel *tunnel;
-	struct erspanhdr *ershdr;
 	const struct iphdr *iph;
-	__be32 index;
+	int ver;
 	int len;
 
 	itn = net_generic(net, erspan_net_id);
 	iph = ip_hdr(skb);
 	len = gre_hdr_len + sizeof(*ershdr);
 
+	/* Check based hdr len */
 	if (unlikely(!pskb_may_pull(skb, len)))
 		return -ENOMEM;
 
 	iph = ip_hdr(skb);
-	ershdr = (struct erspanhdr *)(skb->data + gre_hdr_len);
+	ershdr = (struct erspan_base_hdr *)(skb->data + gre_hdr_len);
+	ver = (ntohs(ershdr->ver_vlan) & VER_MASK) >> VER_OFFSET;
 
 	/* The original GRE header does not have key field,
 	 * Use ERSPAN 10-bit session ID as key.
 	 */
 	tpi->key = cpu_to_be32(ntohs(ershdr->session_id) & ID_MASK);
-	index = ershdr->md.index;
+	pkt_md = (struct erspan_metadata *)(ershdr + 1);
 	tunnel = ip_tunnel_lookup(itn, skb->dev->ifindex,
 				  tpi->flags | TUNNEL_KEY,
 				  iph->saddr, iph->daddr, tpi->key);
 
 	if (tunnel) {
+		len = gre_hdr_len + erspan_hdr_len(ver);
+		if (unlikely(!pskb_may_pull(skb, len)))
+			return -ENOMEM;
+
 		if (__iptunnel_pull_header(skb,
-					   gre_hdr_len + sizeof(*ershdr),
+					   len,
 					   htons(ETH_P_TEB),
 					   false, false) < 0)
 			goto drop;
@@ -187,12 +194,12 @@  static int erspan_rcv(struct sk_buff *skb, struct tnl_ptk_info *tpi,
 			if (!md)
 				return PACKET_REJECT;
 
-			md->index = index;
+			memcpy(md, pkt_md, sizeof(*md));
 			info = &tun_dst.u.tun_info;
 			info->key.tun_flags |= TUNNEL_ERSPAN_OPT;
 			info->options_len = sizeof(*md);
 		} else {
-			tunnel->index = ntohl(index);
+			tunnel->index = ntohl(pkt_md->u.index);
 		}
 
 		skb_reset_mac_header(skb);
@@ -533,7 +540,7 @@  static void erspan_fb_xmit(struct sk_buff *skb, struct net_device *dev,
 	key = &tun_info->key;
 
 	/* ERSPAN has fixed 8 byte GRE header */
-	tunnel_hlen = 8 + sizeof(struct erspanhdr);
+	tunnel_hlen = 8 + sizeof(struct erspan_base_hdr) + ERSPAN_V1_MDSIZE;
 
 	rt = prepare_fb_xmit(skb, dev, &fl, tunnel_hlen);
 	if (!rt)
@@ -552,7 +559,7 @@  static void erspan_fb_xmit(struct sk_buff *skb, struct net_device *dev,
 		goto err_free_rt;
 
 	erspan_build_header(skb, tunnel_id_to_key32(key->tun_id),
-			    ntohl(md->index), truncate, true);
+			    ntohl(md->u.index), truncate, true);
 
 	tpi.flags = (TUNNEL_KEY | TUNNEL_CSUM | TUNNEL_SEQ);
 	tpi.proto = htons(ETH_P_ERSPAN);
@@ -826,7 +833,7 @@  static int erspan_tunnel_init(struct net_device *dev)
 	tunnel->tun_hlen = 8;
 	tunnel->parms.iph.protocol = IPPROTO_GRE;
 	tunnel->hlen = tunnel->tun_hlen + tunnel->encap_hlen +
-		       sizeof(struct erspanhdr);
+		       sizeof(struct erspan_base_hdr) + ERSPAN_V1_MDSIZE;
 	t_hlen = tunnel->hlen + sizeof(struct iphdr);
 
 	dev->needed_headroom = LL_MAX_HEADER + t_hlen + 4;