aboutsummaryrefslogtreecommitdiffstats
path: root/net/ipv4/tcp_offload.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/ipv4/tcp_offload.c')
-rw-r--r--net/ipv4/tcp_offload.c40
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
273static struct sk_buff **tcp4_gro_receive(struct sk_buff **head, struct sk_buff *skb) 273static 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 }
286flush: 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
303skip_csum:
304 return tcp_gro_receive(head, skb); 304 return tcp_gro_receive(head, skb);
305} 305}
306 306
307static int tcp4_gro_complete(struct sk_buff *skb) 307static 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);