diff options
author | Eric Dumazet <edumazet@google.com> | 2012-09-26 22:14:53 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2012-10-01 17:00:27 -0400 |
commit | 861b650101eb0c627d171eb18de81dddb93d395e (patch) | |
tree | 07c0b874476d6d82f8618c071402e742b1705b66 /net | |
parent | 64c6d08e6490fb18cea09bb03686c149946bd818 (diff) |
tcp: gro: add checksuming helpers
skb with CHECKSUM_NONE cant currently be handled by GRO, and
we notice this deep in GRO stack in tcp[46]_gro_receive()
But there are cases where GRO can be a benefit, even with a lack
of checksums.
This preliminary work is needed to add GRO support
to tunnels.
Signed-off-by: Eric Dumazet <edumazet@google.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net')
-rw-r--r-- | net/ipv4/tcp_ipv4.c | 19 | ||||
-rw-r--r-- | net/ipv6/tcp_ipv6.c | 20 |
2 files changed, 33 insertions, 6 deletions
diff --git a/net/ipv4/tcp_ipv4.c b/net/ipv4/tcp_ipv4.c index 385eb79cf6aa..75735c9a6a9d 100644 --- a/net/ipv4/tcp_ipv4.c +++ b/net/ipv4/tcp_ipv4.c | |||
@@ -2803,6 +2803,8 @@ void tcp4_proc_exit(void) | |||
2803 | struct sk_buff **tcp4_gro_receive(struct sk_buff **head, struct sk_buff *skb) | 2803 | struct sk_buff **tcp4_gro_receive(struct sk_buff **head, struct sk_buff *skb) |
2804 | { | 2804 | { |
2805 | const struct iphdr *iph = skb_gro_network_header(skb); | 2805 | const struct iphdr *iph = skb_gro_network_header(skb); |
2806 | __wsum wsum; | ||
2807 | __sum16 sum; | ||
2806 | 2808 | ||
2807 | switch (skb->ip_summed) { | 2809 | switch (skb->ip_summed) { |
2808 | case CHECKSUM_COMPLETE: | 2810 | case CHECKSUM_COMPLETE: |
@@ -2811,11 +2813,22 @@ struct sk_buff **tcp4_gro_receive(struct sk_buff **head, struct sk_buff *skb) | |||
2811 | skb->ip_summed = CHECKSUM_UNNECESSARY; | 2813 | skb->ip_summed = CHECKSUM_UNNECESSARY; |
2812 | break; | 2814 | break; |
2813 | } | 2815 | } |
2814 | 2816 | flush: | |
2815 | /* fall through */ | ||
2816 | case CHECKSUM_NONE: | ||
2817 | NAPI_GRO_CB(skb)->flush = 1; | 2817 | NAPI_GRO_CB(skb)->flush = 1; |
2818 | return NULL; | 2818 | return NULL; |
2819 | |||
2820 | case CHECKSUM_NONE: | ||
2821 | wsum = csum_tcpudp_nofold(iph->saddr, iph->daddr, | ||
2822 | skb_gro_len(skb), IPPROTO_TCP, 0); | ||
2823 | sum = csum_fold(skb_checksum(skb, | ||
2824 | skb_gro_offset(skb), | ||
2825 | skb_gro_len(skb), | ||
2826 | wsum)); | ||
2827 | if (sum) | ||
2828 | goto flush; | ||
2829 | |||
2830 | skb->ip_summed = CHECKSUM_UNNECESSARY; | ||
2831 | break; | ||
2819 | } | 2832 | } |
2820 | 2833 | ||
2821 | return tcp_gro_receive(head, skb); | 2834 | return tcp_gro_receive(head, skb); |
diff --git a/net/ipv6/tcp_ipv6.c b/net/ipv6/tcp_ipv6.c index d6212d6bc8d8..49c890386ce9 100644 --- a/net/ipv6/tcp_ipv6.c +++ b/net/ipv6/tcp_ipv6.c | |||
@@ -763,6 +763,8 @@ static struct sk_buff **tcp6_gro_receive(struct sk_buff **head, | |||
763 | struct sk_buff *skb) | 763 | struct sk_buff *skb) |
764 | { | 764 | { |
765 | const struct ipv6hdr *iph = skb_gro_network_header(skb); | 765 | const struct ipv6hdr *iph = skb_gro_network_header(skb); |
766 | __wsum wsum; | ||
767 | __sum16 sum; | ||
766 | 768 | ||
767 | switch (skb->ip_summed) { | 769 | switch (skb->ip_summed) { |
768 | case CHECKSUM_COMPLETE: | 770 | case CHECKSUM_COMPLETE: |
@@ -771,11 +773,23 @@ static struct sk_buff **tcp6_gro_receive(struct sk_buff **head, | |||
771 | skb->ip_summed = CHECKSUM_UNNECESSARY; | 773 | skb->ip_summed = CHECKSUM_UNNECESSARY; |
772 | break; | 774 | break; |
773 | } | 775 | } |
774 | 776 | flush: | |
775 | /* fall through */ | ||
776 | case CHECKSUM_NONE: | ||
777 | NAPI_GRO_CB(skb)->flush = 1; | 777 | NAPI_GRO_CB(skb)->flush = 1; |
778 | return NULL; | 778 | return NULL; |
779 | |||
780 | case CHECKSUM_NONE: | ||
781 | wsum = ~csum_unfold(csum_ipv6_magic(&iph->saddr, &iph->daddr, | ||
782 | skb_gro_len(skb), | ||
783 | IPPROTO_TCP, 0)); | ||
784 | sum = csum_fold(skb_checksum(skb, | ||
785 | skb_gro_offset(skb), | ||
786 | skb_gro_len(skb), | ||
787 | wsum)); | ||
788 | if (sum) | ||
789 | goto flush; | ||
790 | |||
791 | skb->ip_summed = CHECKSUM_UNNECESSARY; | ||
792 | break; | ||
779 | } | 793 | } |
780 | 794 | ||
781 | return tcp_gro_receive(head, skb); | 795 | return tcp_gro_receive(head, skb); |