forked from Minki/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
@ -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);
|
||||||
|
@ -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);
|
||||||
|
@ -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,
|
||||||
|
Loading…
Reference in New Issue
Block a user