diff options
author | Tom Herbert <therbert@google.com> | 2014-09-20 17:52:28 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2014-09-26 00:22:46 -0400 |
commit | d020f8f73318589bf41f864b7f89f95669350873 (patch) | |
tree | d31c3e518fc4ea7dda9bacef18daa8d151f65a73 /net/ipv6/tcpv6_offload.c | |
parent | 2fdbfea5735d3deb30a8782c57f7210cb034e69d (diff) |
tcp: move logic out of tcp_v[64]_gso_send_check
In tcp_v[46]_gso_send_check the TCP checksum is initialized to the
pseudo header checksum using __tcp_v[46]_send_check. We can move this
logic into new tcp[46]_gso_segment functions to be done when
ip_summed != CHECKSUM_PARTIAL (ip_summed == CHECKSUM_PARTIAL should be
the common case, possibly always true when taking GSO path). After this
change tcp_v[46]_gso_send_check is no-op.
Signed-off-by: Tom Herbert <therbert@google.com>
Acked-by: Eric Dumazet <edumazet@google.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/ipv6/tcpv6_offload.c')
-rw-r--r-- | net/ipv6/tcpv6_offload.c | 37 |
1 files changed, 24 insertions, 13 deletions
diff --git a/net/ipv6/tcpv6_offload.c b/net/ipv6/tcpv6_offload.c index dbb3d9262bf6..96253154db3a 100644 --- a/net/ipv6/tcpv6_offload.c +++ b/net/ipv6/tcpv6_offload.c | |||
@@ -17,18 +17,6 @@ | |||
17 | 17 | ||
18 | static int tcp_v6_gso_send_check(struct sk_buff *skb) | 18 | static int tcp_v6_gso_send_check(struct sk_buff *skb) |
19 | { | 19 | { |
20 | const struct ipv6hdr *ipv6h; | ||
21 | struct tcphdr *th; | ||
22 | |||
23 | if (!pskb_may_pull(skb, sizeof(*th))) | ||
24 | return -EINVAL; | ||
25 | |||
26 | ipv6h = ipv6_hdr(skb); | ||
27 | th = tcp_hdr(skb); | ||
28 | |||
29 | th->check = 0; | ||
30 | skb->ip_summed = CHECKSUM_PARTIAL; | ||
31 | __tcp_v6_send_check(skb, &ipv6h->saddr, &ipv6h->daddr); | ||
32 | return 0; | 20 | return 0; |
33 | } | 21 | } |
34 | 22 | ||
@@ -58,10 +46,33 @@ static int tcp6_gro_complete(struct sk_buff *skb, int thoff) | |||
58 | return tcp_gro_complete(skb); | 46 | return tcp_gro_complete(skb); |
59 | } | 47 | } |
60 | 48 | ||
49 | struct sk_buff *tcp6_gso_segment(struct sk_buff *skb, | ||
50 | netdev_features_t features) | ||
51 | { | ||
52 | struct tcphdr *th; | ||
53 | |||
54 | if (!pskb_may_pull(skb, sizeof(*th))) | ||
55 | return ERR_PTR(-EINVAL); | ||
56 | |||
57 | if (unlikely(skb->ip_summed != CHECKSUM_PARTIAL)) { | ||
58 | const struct ipv6hdr *ipv6h = ipv6_hdr(skb); | ||
59 | struct tcphdr *th = tcp_hdr(skb); | ||
60 | |||
61 | /* Set up pseudo header, usually expect stack to have done | ||
62 | * this. | ||
63 | */ | ||
64 | |||
65 | th->check = 0; | ||
66 | skb->ip_summed = CHECKSUM_PARTIAL; | ||
67 | __tcp_v6_send_check(skb, &ipv6h->saddr, &ipv6h->daddr); | ||
68 | } | ||
69 | |||
70 | return tcp_gso_segment(skb, features); | ||
71 | } | ||
61 | static const struct net_offload tcpv6_offload = { | 72 | static const struct net_offload tcpv6_offload = { |
62 | .callbacks = { | 73 | .callbacks = { |
63 | .gso_send_check = tcp_v6_gso_send_check, | 74 | .gso_send_check = tcp_v6_gso_send_check, |
64 | .gso_segment = tcp_gso_segment, | 75 | .gso_segment = tcp6_gso_segment, |
65 | .gro_receive = tcp6_gro_receive, | 76 | .gro_receive = tcp6_gro_receive, |
66 | .gro_complete = tcp6_gro_complete, | 77 | .gro_complete = tcp6_gro_complete, |
67 | }, | 78 | }, |