forked from mirrors/linux
		
	net: ip_gre: use erspan key field for tunnel lookup
Use ERSPAN key header field as tunnel key in gre_parse_header routine
since ERSPAN protocol sets the key field of the external GRE header to
0 resulting in a tunnel lookup fail in ip6gre_err.
In addition remove key field parsing and pskb_may_pull check in
erspan_rcv and ip6erspan_rcv
Fixes: 5a963eb61b ("ip6_gre: Add ERSPAN native tunnel support")
Signed-off-by: Lorenzo Bianconi <lorenzo.bianconi@redhat.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
			
			
This commit is contained in:
		
							parent
							
								
									56cb4e5034
								
							
						
					
					
						commit
						cb73ee40b1
					
				
					 3 changed files with 17 additions and 13 deletions
				
			
		|  | @ -25,6 +25,7 @@ | |||
| #include <linux/spinlock.h> | ||||
| #include <net/protocol.h> | ||||
| #include <net/gre.h> | ||||
| #include <net/erspan.h> | ||||
| 
 | ||||
| #include <net/icmp.h> | ||||
| #include <net/route.h> | ||||
|  | @ -119,6 +120,22 @@ int gre_parse_header(struct sk_buff *skb, struct tnl_ptk_info *tpi, | |||
| 			hdr_len += 4; | ||||
| 	} | ||||
| 	tpi->hdr_len = hdr_len; | ||||
| 
 | ||||
| 	/* ERSPAN ver 1 and 2 protocol sets GRE key field
 | ||||
| 	 * to 0 and sets the configured key in the | ||||
| 	 * inner erspan header field | ||||
| 	 */ | ||||
| 	if (greh->protocol == htons(ETH_P_ERSPAN) || | ||||
| 	    greh->protocol == htons(ETH_P_ERSPAN2)) { | ||||
| 		struct erspan_base_hdr *ershdr; | ||||
| 
 | ||||
| 		if (!pskb_may_pull(skb, nhs + hdr_len + sizeof(*ershdr))) | ||||
| 			return -EINVAL; | ||||
| 
 | ||||
| 		ershdr = (struct erspan_base_hdr *)options; | ||||
| 		tpi->key = cpu_to_be32(get_session_id(ershdr)); | ||||
| 	} | ||||
| 
 | ||||
| 	return hdr_len; | ||||
| } | ||||
| EXPORT_SYMBOL(gre_parse_header); | ||||
|  |  | |||
|  | @ -268,20 +268,11 @@ static int erspan_rcv(struct sk_buff *skb, struct tnl_ptk_info *tpi, | |||
| 	int len; | ||||
| 
 | ||||
| 	itn = net_generic(net, erspan_net_id); | ||||
| 	len = gre_hdr_len + sizeof(*ershdr); | ||||
| 
 | ||||
| 	/* Check based hdr len */ | ||||
| 	if (unlikely(!pskb_may_pull(skb, len))) | ||||
| 		return PACKET_REJECT; | ||||
| 
 | ||||
| 	iph = ip_hdr(skb); | ||||
| 	ershdr = (struct erspan_base_hdr *)(skb->data + gre_hdr_len); | ||||
| 	ver = ershdr->ver; | ||||
| 
 | ||||
| 	/* The original GRE header does not have key field,
 | ||||
| 	 * Use ERSPAN 10-bit session ID as key. | ||||
| 	 */ | ||||
| 	tpi->key = cpu_to_be32(get_session_id(ershdr)); | ||||
| 	tunnel = ip_tunnel_lookup(itn, skb->dev->ifindex, | ||||
| 				  tpi->flags | TUNNEL_KEY, | ||||
| 				  iph->saddr, iph->daddr, tpi->key); | ||||
|  |  | |||
|  | @ -534,13 +534,9 @@ static int ip6erspan_rcv(struct sk_buff *skb, int gre_hdr_len, | |||
| 	struct ip6_tnl *tunnel; | ||||
| 	u8 ver; | ||||
| 
 | ||||
| 	if (unlikely(!pskb_may_pull(skb, sizeof(*ershdr)))) | ||||
| 		return PACKET_REJECT; | ||||
| 
 | ||||
| 	ipv6h = ipv6_hdr(skb); | ||||
| 	ershdr = (struct erspan_base_hdr *)skb->data; | ||||
| 	ver = ershdr->ver; | ||||
| 	tpi->key = cpu_to_be32(get_session_id(ershdr)); | ||||
| 
 | ||||
| 	tunnel = ip6gre_tunnel_lookup(skb->dev, | ||||
| 				      &ipv6h->saddr, &ipv6h->daddr, tpi->key, | ||||
|  |  | |||
		Loading…
	
		Reference in a new issue
	
	 Lorenzo Bianconi
						Lorenzo Bianconi