[PATCH 3.14 59/87] net-gre-gro: Fix a bug that breaks the forwarding path

Greg Kroah-Hartman
2014-07-26T19:02:33Z

From: Jerry Chu <hkchu@google.com>

[ Upstream commit c3caf1192f904de2f1381211f564537235d50de3 ]

Fixed a bug that was introduced by my GRE-GRO patch
(bf5a755f5e9186406bbf50f4087100af5bd68e40 net-gre-gro: Add GRE
support to the GRO stack) that breaks the forwarding path
because various GSO related fields were not set. The bug will
cause on the egress path either the GSO code to fail, or a
GRE-TSO capable (NETIF_F_GSO_GRE) NICs to choke. The following
fix has been tested for both cases.

Signed-off-by: H.K. Jerry Chu <hkchu@google.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
net/core/dev.c | 2 ++
net/ipv4/af_inet.c | 3 +++
net/ipv4/gre_offload.c | 3 +++
net/ipv4/tcp_offload.c | 2 +-
net/ipv6/tcpv6_offload.c | 2 +-
5 files changed, 10 insertions(+), 2 deletions(-)

--- a/net/core/dev.c
+++ b/net/core/dev.c
@@ -4058,6 +4058,8 @@ static void napi_reuse_skb(struct napi_s
skb->vlan_tci = 0;
skb->dev = napi->dev;
skb->skb_iif = 0;
+ skb->encapsulation = 0;
+ skb_shinfo(skb)->gso_type = 0;
skb->truesize = SKB_TRUESIZE(skb_end_offset(skb));

napi->skb = skb;
--- a/net/ipv4/af_inet.c
+++ b/net/ipv4/af_inet.c
@@ -1434,6 +1434,9 @@ static int inet_gro_complete(struct sk_b
int proto = iph->protocol;
int err = -ENOSYS;

+ if (skb->encapsulation)
+ skb_set_inner_network_header(skb, nhoff);
+
csum_replace2(&iph->check, iph->tot_len, newlen);
iph->tot_len = newlen;

--- a/net/ipv4/gre_offload.c
+++ b/net/ipv4/gre_offload.c
@@ -255,6 +255,9 @@ static int gre_gro_complete(struct sk_bu
int err = -ENOENT;
__be16 type;

+ skb->encapsulation = 1;
+ skb_shinfo(skb)->gso_type = SKB_GSO_GRE;
+
type = greh->protocol;
if (greh->flags & GRE_KEY)
grehlen += GRE_HEADER_SECTION;
--- a/net/ipv4/tcp_offload.c
+++ b/net/ipv4/tcp_offload.c
@@ -310,7 +310,7 @@ static int tcp4_gro_complete(struct sk_b

th->check = ~tcp_v4_check(skb->len - thoff, iph->saddr,
iph->daddr, 0);
- skb_shinfo(skb)->gso_type = SKB_GSO_TCPV4;
+ skb_shinfo(skb)->gso_type |= SKB_GSO_TCPV4;

return tcp_gro_complete(skb);
}
--- a/net/ipv6/tcpv6_offload.c
+++ b/net/ipv6/tcpv6_offload.c
@@ -73,7 +73,7 @@ static int tcp6_gro_complete(struct sk_b

th->check = ~tcp_v6_check(skb->len - thoff, &iph->saddr,
&iph->daddr, 0);
- skb_shinfo(skb)->gso_type = SKB_GSO_TCPV6;
+ skb_shinfo(skb)->gso_type |= SKB_GSO_TCPV6;

return tcp_gro_complete(skb);
}