]> Pileus Git - ~andy/linux/commitdiff
tcp: gro: add checksuming helpers
authorEric Dumazet <edumazet@google.com>
Thu, 27 Sep 2012 02:14:53 +0000 (02:14 +0000)
committerDavid S. Miller <davem@davemloft.net>
Mon, 1 Oct 2012 21:00:27 +0000 (17:00 -0400)
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>
net/ipv4/tcp_ipv4.c
net/ipv6/tcp_ipv6.c

index 385eb79cf6aadc0825e5889f793897ba6463df1f..75735c9a6a9df2bf4026266c8c30d92bd474092c 100644 (file)
@@ -2803,6 +2803,8 @@ void tcp4_proc_exit(void)
 struct sk_buff **tcp4_gro_receive(struct sk_buff **head, struct sk_buff *skb)
 {
        const struct iphdr *iph = skb_gro_network_header(skb);
+       __wsum wsum;
+       __sum16 sum;
 
        switch (skb->ip_summed) {
        case CHECKSUM_COMPLETE:
@@ -2811,11 +2813,22 @@ struct sk_buff **tcp4_gro_receive(struct sk_buff **head, struct sk_buff *skb)
                        skb->ip_summed = CHECKSUM_UNNECESSARY;
                        break;
                }
-
-               /* fall through */
-       case CHECKSUM_NONE:
+flush:
                NAPI_GRO_CB(skb)->flush = 1;
                return NULL;
+
+       case CHECKSUM_NONE:
+               wsum = csum_tcpudp_nofold(iph->saddr, iph->daddr,
+                                         skb_gro_len(skb), IPPROTO_TCP, 0);
+               sum = csum_fold(skb_checksum(skb,
+                                            skb_gro_offset(skb),
+                                            skb_gro_len(skb),
+                                            wsum));
+               if (sum)
+                       goto flush;
+
+               skb->ip_summed = CHECKSUM_UNNECESSARY;
+               break;
        }
 
        return tcp_gro_receive(head, skb);
index d6212d6bc8d89a5a3429329e78ee36fb4c384d2d..49c890386ce9ba6b76e401191d7d64484da7a238 100644 (file)
@@ -763,6 +763,8 @@ static struct sk_buff **tcp6_gro_receive(struct sk_buff **head,
                                         struct sk_buff *skb)
 {
        const struct ipv6hdr *iph = skb_gro_network_header(skb);
+       __wsum wsum;
+       __sum16 sum;
 
        switch (skb->ip_summed) {
        case CHECKSUM_COMPLETE:
@@ -771,11 +773,23 @@ static struct sk_buff **tcp6_gro_receive(struct sk_buff **head,
                        skb->ip_summed = CHECKSUM_UNNECESSARY;
                        break;
                }
-
-               /* fall through */
-       case CHECKSUM_NONE:
+flush:
                NAPI_GRO_CB(skb)->flush = 1;
                return NULL;
+
+       case CHECKSUM_NONE:
+               wsum = ~csum_unfold(csum_ipv6_magic(&iph->saddr, &iph->daddr,
+                                                   skb_gro_len(skb),
+                                                   IPPROTO_TCP, 0));
+               sum = csum_fold(skb_checksum(skb,
+                                            skb_gro_offset(skb),
+                                            skb_gro_len(skb),
+                                            wsum));
+               if (sum)
+                       goto flush;
+
+               skb->ip_summed = CHECKSUM_UNNECESSARY;
+               break;
        }
 
        return tcp_gro_receive(head, skb);