diff options
Diffstat (limited to 'net/ipv4/tcp_offload.c')
-rw-r--r-- | net/ipv4/tcp_offload.c | 40 |
1 files changed, 20 insertions, 20 deletions
diff --git a/net/ipv4/tcp_offload.c b/net/ipv4/tcp_offload.c index a2b68a108eae..2658a27f540d 100644 --- a/net/ipv4/tcp_offload.c +++ b/net/ipv4/tcp_offload.c | |||
@@ -240,7 +240,7 @@ int tcp_gro_complete(struct sk_buff *skb) | |||
240 | { | 240 | { |
241 | struct tcphdr *th = tcp_hdr(skb); | 241 | struct tcphdr *th = tcp_hdr(skb); |
242 | 242 | ||
243 | skb->csum_start = skb_transport_header(skb) - skb->head; | 243 | skb->csum_start = (unsigned char *)th - skb->head; |
244 | skb->csum_offset = offsetof(struct tcphdr, check); | 244 | skb->csum_offset = offsetof(struct tcphdr, check); |
245 | skb->ip_summed = CHECKSUM_PARTIAL; | 245 | skb->ip_summed = CHECKSUM_PARTIAL; |
246 | 246 | ||
@@ -272,45 +272,45 @@ static int tcp_v4_gso_send_check(struct sk_buff *skb) | |||
272 | 272 | ||
273 | static struct sk_buff **tcp4_gro_receive(struct sk_buff **head, struct sk_buff *skb) | 273 | static struct sk_buff **tcp4_gro_receive(struct sk_buff **head, struct sk_buff *skb) |
274 | { | 274 | { |
275 | /* Use the IP hdr immediately proceeding for this transport */ | ||
275 | const struct iphdr *iph = skb_gro_network_header(skb); | 276 | const struct iphdr *iph = skb_gro_network_header(skb); |
276 | __wsum wsum; | 277 | __wsum wsum; |
277 | __sum16 sum; | 278 | |
279 | /* Don't bother verifying checksum if we're going to flush anyway. */ | ||
280 | if (NAPI_GRO_CB(skb)->flush) | ||
281 | goto skip_csum; | ||
282 | |||
283 | wsum = skb->csum; | ||
278 | 284 | ||
279 | switch (skb->ip_summed) { | 285 | switch (skb->ip_summed) { |
286 | case CHECKSUM_NONE: | ||
287 | wsum = skb_checksum(skb, skb_gro_offset(skb), skb_gro_len(skb), | ||
288 | 0); | ||
289 | |||
290 | /* fall through */ | ||
291 | |||
280 | case CHECKSUM_COMPLETE: | 292 | case CHECKSUM_COMPLETE: |
281 | if (!tcp_v4_check(skb_gro_len(skb), iph->saddr, iph->daddr, | 293 | if (!tcp_v4_check(skb_gro_len(skb), iph->saddr, iph->daddr, |
282 | skb->csum)) { | 294 | wsum)) { |
283 | skb->ip_summed = CHECKSUM_UNNECESSARY; | 295 | skb->ip_summed = CHECKSUM_UNNECESSARY; |
284 | break; | 296 | break; |
285 | } | 297 | } |
286 | flush: | 298 | |
287 | NAPI_GRO_CB(skb)->flush = 1; | 299 | NAPI_GRO_CB(skb)->flush = 1; |
288 | return NULL; | 300 | return NULL; |
289 | |||
290 | case CHECKSUM_NONE: | ||
291 | wsum = csum_tcpudp_nofold(iph->saddr, iph->daddr, | ||
292 | skb_gro_len(skb), IPPROTO_TCP, 0); | ||
293 | sum = csum_fold(skb_checksum(skb, | ||
294 | skb_gro_offset(skb), | ||
295 | skb_gro_len(skb), | ||
296 | wsum)); | ||
297 | if (sum) | ||
298 | goto flush; | ||
299 | |||
300 | skb->ip_summed = CHECKSUM_UNNECESSARY; | ||
301 | break; | ||
302 | } | 301 | } |
303 | 302 | ||
303 | skip_csum: | ||
304 | return tcp_gro_receive(head, skb); | 304 | return tcp_gro_receive(head, skb); |
305 | } | 305 | } |
306 | 306 | ||
307 | static int tcp4_gro_complete(struct sk_buff *skb) | 307 | static int tcp4_gro_complete(struct sk_buff *skb, int thoff) |
308 | { | 308 | { |
309 | const struct iphdr *iph = ip_hdr(skb); | 309 | const struct iphdr *iph = ip_hdr(skb); |
310 | struct tcphdr *th = tcp_hdr(skb); | 310 | struct tcphdr *th = tcp_hdr(skb); |
311 | 311 | ||
312 | th->check = ~tcp_v4_check(skb->len - skb_transport_offset(skb), | 312 | th->check = ~tcp_v4_check(skb->len - thoff, iph->saddr, |
313 | iph->saddr, iph->daddr, 0); | 313 | iph->daddr, 0); |
314 | skb_shinfo(skb)->gso_type = SKB_GSO_TCPV4; | 314 | skb_shinfo(skb)->gso_type = SKB_GSO_TCPV4; |
315 | 315 | ||
316 | return tcp_gro_complete(skb); | 316 | return tcp_gro_complete(skb); |