diff options
author | Herbert Xu <herbert@gondor.apana.org.au> | 2006-07-08 16:34:56 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2006-07-08 16:34:56 -0400 |
commit | a430a43d087545c96542ee64573237919109d370 (patch) | |
tree | 653b630298505d5a65e2e094868d83014e4b0dc4 /net/ipv4/tcp_ipv4.c | |
parent | 89114afd435a486deb8583e89f490fc274444d18 (diff) |
[NET] gso: Fix up GSO packets with broken checksums
Certain subsystems in the stack (e.g., netfilter) can break the partial
checksum on GSO packets. Until they're fixed, this patch allows this to
work by recomputing the partial checksums through the GSO mechanism.
Once they've all been converted to update the partial checksum instead of
clearing it, this workaround can be removed.
Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/ipv4/tcp_ipv4.c')
-rw-r--r-- | net/ipv4/tcp_ipv4.c | 18 |
1 files changed, 18 insertions, 0 deletions
diff --git a/net/ipv4/tcp_ipv4.c b/net/ipv4/tcp_ipv4.c index 5a886e6efbbe..a891133f00e4 100644 --- a/net/ipv4/tcp_ipv4.c +++ b/net/ipv4/tcp_ipv4.c | |||
@@ -496,6 +496,24 @@ void tcp_v4_send_check(struct sock *sk, int len, struct sk_buff *skb) | |||
496 | } | 496 | } |
497 | } | 497 | } |
498 | 498 | ||
499 | int tcp_v4_gso_send_check(struct sk_buff *skb) | ||
500 | { | ||
501 | struct iphdr *iph; | ||
502 | struct tcphdr *th; | ||
503 | |||
504 | if (!pskb_may_pull(skb, sizeof(*th))) | ||
505 | return -EINVAL; | ||
506 | |||
507 | iph = skb->nh.iph; | ||
508 | th = skb->h.th; | ||
509 | |||
510 | th->check = 0; | ||
511 | th->check = ~tcp_v4_check(th, skb->len, iph->saddr, iph->daddr, 0); | ||
512 | skb->csum = offsetof(struct tcphdr, check); | ||
513 | skb->ip_summed = CHECKSUM_HW; | ||
514 | return 0; | ||
515 | } | ||
516 | |||
499 | /* | 517 | /* |
500 | * This routine will send an RST to the other tcp. | 518 | * This routine will send an RST to the other tcp. |
501 | * | 519 | * |