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:
Lorenzo Bianconi 2019-01-18 12:05:39 +01:00 committed by David S. Miller
parent 56cb4e5034
commit cb73ee40b1
3 changed files with 17 additions and 13 deletions

View File

@ -25,6 +25,7 @@
#include <linux/spinlock.h> #include <linux/spinlock.h>
#include <net/protocol.h> #include <net/protocol.h>
#include <net/gre.h> #include <net/gre.h>
#include <net/erspan.h>
#include <net/icmp.h> #include <net/icmp.h>
#include <net/route.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; hdr_len += 4;
} }
tpi->hdr_len = hdr_len; 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; return hdr_len;
} }
EXPORT_SYMBOL(gre_parse_header); EXPORT_SYMBOL(gre_parse_header);

View File

@ -268,20 +268,11 @@ static int erspan_rcv(struct sk_buff *skb, struct tnl_ptk_info *tpi,
int len; int len;
itn = net_generic(net, erspan_net_id); 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); iph = ip_hdr(skb);
ershdr = (struct erspan_base_hdr *)(skb->data + gre_hdr_len); ershdr = (struct erspan_base_hdr *)(skb->data + gre_hdr_len);
ver = ershdr->ver; 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, tunnel = ip_tunnel_lookup(itn, skb->dev->ifindex,
tpi->flags | TUNNEL_KEY, tpi->flags | TUNNEL_KEY,
iph->saddr, iph->daddr, tpi->key); iph->saddr, iph->daddr, tpi->key);

View File

@ -534,13 +534,9 @@ static int ip6erspan_rcv(struct sk_buff *skb, int gre_hdr_len,
struct ip6_tnl *tunnel; struct ip6_tnl *tunnel;
u8 ver; u8 ver;
if (unlikely(!pskb_may_pull(skb, sizeof(*ershdr))))
return PACKET_REJECT;
ipv6h = ipv6_hdr(skb); ipv6h = ipv6_hdr(skb);
ershdr = (struct erspan_base_hdr *)skb->data; ershdr = (struct erspan_base_hdr *)skb->data;
ver = ershdr->ver; ver = ershdr->ver;
tpi->key = cpu_to_be32(get_session_id(ershdr));
tunnel = ip6gre_tunnel_lookup(skb->dev, tunnel = ip6gre_tunnel_lookup(skb->dev,
&ipv6h->saddr, &ipv6h->daddr, tpi->key, &ipv6h->saddr, &ipv6h->daddr, tpi->key,