Commit ca3a1b85 authored by Yossi Kuperman's avatar Yossi Kuperman Committed by Steffen Klassert

esp6_offload: Fix IP6CB(skb)->nhoff for ESP GRO

IP6CB(skb)->nhoff is the offset of the nexthdr field in an IPv6
header, unless there are extension headers present, in which case
nhoff points to the nexthdr field of the last extension header.

In non-GRO code path, nhoff is set by ipv6_rcv before any XFRM code
is executed. Conversely, in GRO code path (when esp6_offload is loaded),
nhoff is not set. The following functions fail to read the correct value
and eventually the packet is dropped:

    xfrm6_transport_finish
    xfrm6_tunnel_input
    xfrm6_rcv_tnl

Set nhoff to the proper offset of nexthdr in esp6_gro_receive.

Fixes: 7785bba2 ("esp: Add a software GRO codepath")
Signed-off-by: default avatarYossi Kuperman <yossiku@mellanox.com>
Signed-off-by: default avatarSteffen Klassert <steffen.klassert@secunet.com>
parent 7c88e21a
...@@ -30,6 +30,25 @@ ...@@ -30,6 +30,25 @@
#include <net/ipv6.h> #include <net/ipv6.h>
#include <linux/icmpv6.h> #include <linux/icmpv6.h>
static __u16 esp6_nexthdr_esp_offset(struct ipv6hdr *ipv6_hdr, int nhlen)
{
int off = sizeof(struct ipv6hdr);
struct ipv6_opt_hdr *exthdr;
if (likely(ipv6_hdr->nexthdr == NEXTHDR_ESP))
return offsetof(struct ipv6hdr, nexthdr);
while (off < nhlen) {
exthdr = (void *)ipv6_hdr + off;
if (exthdr->nexthdr == NEXTHDR_ESP)
return off;
off += ipv6_optlen(exthdr);
}
return 0;
}
static struct sk_buff **esp6_gro_receive(struct sk_buff **head, static struct sk_buff **esp6_gro_receive(struct sk_buff **head,
struct sk_buff *skb) struct sk_buff *skb)
{ {
...@@ -38,6 +57,7 @@ static struct sk_buff **esp6_gro_receive(struct sk_buff **head, ...@@ -38,6 +57,7 @@ static struct sk_buff **esp6_gro_receive(struct sk_buff **head,
struct xfrm_state *x; struct xfrm_state *x;
__be32 seq; __be32 seq;
__be32 spi; __be32 spi;
int nhoff;
int err; int err;
skb_pull(skb, offset); skb_pull(skb, offset);
...@@ -72,6 +92,11 @@ static struct sk_buff **esp6_gro_receive(struct sk_buff **head, ...@@ -72,6 +92,11 @@ static struct sk_buff **esp6_gro_receive(struct sk_buff **head,
xo->flags |= XFRM_GRO; xo->flags |= XFRM_GRO;
nhoff = esp6_nexthdr_esp_offset(ipv6_hdr(skb), offset);
if (!nhoff)
goto out;
IP6CB(skb)->nhoff = nhoff;
XFRM_TUNNEL_SKB_CB(skb)->tunnel.ip6 = NULL; XFRM_TUNNEL_SKB_CB(skb)->tunnel.ip6 = NULL;
XFRM_SPI_SKB_CB(skb)->family = AF_INET6; XFRM_SPI_SKB_CB(skb)->family = AF_INET6;
XFRM_SPI_SKB_CB(skb)->daddroff = offsetof(struct ipv6hdr, daddr); XFRM_SPI_SKB_CB(skb)->daddroff = offsetof(struct ipv6hdr, daddr);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment