summaryrefslogtreecommitdiffstats
path: root/net
diff options
context:
space:
mode:
authorHerbert Xu <herbert@gondor.apana.org.au>2009-01-17 20:46:16 +0100
committerDavid S. Miller <davem@davemloft.net>2009-01-20 23:44:01 +0100
commitebad18e93fbc6bc63ee734edbc0eb38ac6b919c0 (patch)
treefb8eb7b04eb3b304f0a104b1c3d2ffa5642dc55a /net
parentvia-velocity: fix hot spin (diff)
downloadlinux-ebad18e93fbc6bc63ee734edbc0eb38ac6b919c0.tar.xz
linux-ebad18e93fbc6bc63ee734edbc0eb38ac6b919c0.zip
gro: Fix handling of complete checksums in IPv6
We need to perform skb_postpull_rcsum after pulling the IPv6 header in order to maintain the correctness of the complete checksum. This patch also adds a missing iph reload after pulling. Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net')
-rw-r--r--net/ipv6/af_inet6.c7
1 files changed, 7 insertions, 0 deletions
diff --git a/net/ipv6/af_inet6.c b/net/ipv6/af_inet6.c
index 94f74f5b0cbf..c802bc1658a8 100644
--- a/net/ipv6/af_inet6.c
+++ b/net/ipv6/af_inet6.c
@@ -797,6 +797,7 @@ static struct sk_buff **ipv6_gro_receive(struct sk_buff **head,
unsigned int nlen;
int flush = 1;
int proto;
+ __wsum csum;
if (unlikely(!pskb_may_pull(skb, sizeof(*iph))))
goto out;
@@ -808,6 +809,7 @@ static struct sk_buff **ipv6_gro_receive(struct sk_buff **head,
rcu_read_lock();
proto = ipv6_gso_pull_exthdrs(skb, iph->nexthdr);
+ iph = ipv6_hdr(skb);
IPV6_GRO_CB(skb)->proto = proto;
ops = rcu_dereference(inet6_protos[proto]);
if (!ops || !ops->gro_receive)
@@ -839,8 +841,13 @@ static struct sk_buff **ipv6_gro_receive(struct sk_buff **head,
NAPI_GRO_CB(skb)->flush |= flush;
+ csum = skb->csum;
+ skb_postpull_rcsum(skb, iph, skb_network_header_len(skb));
+
pp = ops->gro_receive(head, skb);
+ skb->csum = csum;
+
out_unlock:
rcu_read_unlock();