diff options
author | Herbert Xu <herbert@gondor.apana.org.au> | 2010-04-10 22:15:53 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2010-04-11 18:29:08 -0400 |
commit | 419f9f896074ce8b21e88066e6f3515f18e5641c (patch) | |
tree | ad00f641e9648298581fdece6e3a4f96a78e0af3 /net/ipv4/tcp_ipv4.c | |
parent | 871039f02f8ec4ab2e5e9010718caa8e085786f1 (diff) |
tcp: Handle CHECKSUM_PARTIAL for SYNACK packets for IPv4
tcp: Handle CHECKSUM_PARTIAL for SYNACK packets for IPv4
This patch moves the common code between tcp_v4_send_check and
tcp_v4_gso_send_check into a new function __tcp_v4_send_check.
It then uses the new function in tcp_v4_send_synack so that it
handles CHECKSUM_PARTIAL properly.
Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
Tested-by: Yinghai <yinghai.lu@oracle.com>
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 | 31 |
1 files changed, 14 insertions, 17 deletions
diff --git a/net/ipv4/tcp_ipv4.c b/net/ipv4/tcp_ipv4.c index 3c23e70885f4..aebfd28c5089 100644 --- a/net/ipv4/tcp_ipv4.c +++ b/net/ipv4/tcp_ipv4.c | |||
@@ -519,26 +519,31 @@ out: | |||
519 | sock_put(sk); | 519 | sock_put(sk); |
520 | } | 520 | } |
521 | 521 | ||
522 | /* This routine computes an IPv4 TCP checksum. */ | 522 | static void __tcp_v4_send_check(struct sk_buff *skb, |
523 | void tcp_v4_send_check(struct sock *sk, int len, struct sk_buff *skb) | 523 | __be32 saddr, __be32 daddr) |
524 | { | 524 | { |
525 | struct inet_sock *inet = inet_sk(sk); | ||
526 | struct tcphdr *th = tcp_hdr(skb); | 525 | struct tcphdr *th = tcp_hdr(skb); |
527 | 526 | ||
528 | if (skb->ip_summed == CHECKSUM_PARTIAL) { | 527 | if (skb->ip_summed == CHECKSUM_PARTIAL) { |
529 | th->check = ~tcp_v4_check(len, inet->inet_saddr, | 528 | th->check = ~tcp_v4_check(skb->len, saddr, daddr, 0); |
530 | inet->inet_daddr, 0); | ||
531 | skb->csum_start = skb_transport_header(skb) - skb->head; | 529 | skb->csum_start = skb_transport_header(skb) - skb->head; |
532 | skb->csum_offset = offsetof(struct tcphdr, check); | 530 | skb->csum_offset = offsetof(struct tcphdr, check); |
533 | } else { | 531 | } else { |
534 | th->check = tcp_v4_check(len, inet->inet_saddr, | 532 | th->check = tcp_v4_check(skb->len, saddr, daddr, |
535 | inet->inet_daddr, | ||
536 | csum_partial(th, | 533 | csum_partial(th, |
537 | th->doff << 2, | 534 | th->doff << 2, |
538 | skb->csum)); | 535 | skb->csum)); |
539 | } | 536 | } |
540 | } | 537 | } |
541 | 538 | ||
539 | /* This routine computes an IPv4 TCP checksum. */ | ||
540 | void tcp_v4_send_check(struct sock *sk, int len, struct sk_buff *skb) | ||
541 | { | ||
542 | struct inet_sock *inet = inet_sk(sk); | ||
543 | |||
544 | __tcp_v4_send_check(skb, inet->inet_saddr, inet->inet_daddr); | ||
545 | } | ||
546 | |||
542 | int tcp_v4_gso_send_check(struct sk_buff *skb) | 547 | int tcp_v4_gso_send_check(struct sk_buff *skb) |
543 | { | 548 | { |
544 | const struct iphdr *iph; | 549 | const struct iphdr *iph; |
@@ -551,10 +556,8 @@ int tcp_v4_gso_send_check(struct sk_buff *skb) | |||
551 | th = tcp_hdr(skb); | 556 | th = tcp_hdr(skb); |
552 | 557 | ||
553 | th->check = 0; | 558 | th->check = 0; |
554 | th->check = ~tcp_v4_check(skb->len, iph->saddr, iph->daddr, 0); | ||
555 | skb->csum_start = skb_transport_header(skb) - skb->head; | ||
556 | skb->csum_offset = offsetof(struct tcphdr, check); | ||
557 | skb->ip_summed = CHECKSUM_PARTIAL; | 559 | skb->ip_summed = CHECKSUM_PARTIAL; |
560 | __tcp_v4_send_check(skb, iph->saddr, iph->daddr); | ||
558 | return 0; | 561 | return 0; |
559 | } | 562 | } |
560 | 563 | ||
@@ -763,13 +766,7 @@ static int tcp_v4_send_synack(struct sock *sk, struct dst_entry *dst, | |||
763 | skb = tcp_make_synack(sk, dst, req, rvp); | 766 | skb = tcp_make_synack(sk, dst, req, rvp); |
764 | 767 | ||
765 | if (skb) { | 768 | if (skb) { |
766 | struct tcphdr *th = tcp_hdr(skb); | 769 | __tcp_v4_send_check(skb, ireq->loc_addr, ireq->rmt_addr); |
767 | |||
768 | th->check = tcp_v4_check(skb->len, | ||
769 | ireq->loc_addr, | ||
770 | ireq->rmt_addr, | ||
771 | csum_partial(th, skb->len, | ||
772 | skb->csum)); | ||
773 | 770 | ||
774 | err = ip_build_and_send_pkt(skb, sk, ireq->loc_addr, | 771 | err = ip_build_and_send_pkt(skb, sk, ireq->loc_addr, |
775 | ireq->rmt_addr, | 772 | ireq->rmt_addr, |