aboutsummaryrefslogtreecommitdiffstats
path: root/net
diff options
context:
space:
mode:
authorHerbert Xu <herbert@gondor.apana.org.au>2007-10-15 04:47:15 -0400
committerDavid S. Miller <davem@sunset.davemloft.net>2007-10-15 15:26:34 -0400
commita030847e9f0eed2a080f6114381c649a7aa43d25 (patch)
tree60beb818cf95e16ab598b8177355eba845fc5015 /net
parent172a863f2bfbacf4b6bfc06db219b946a058ce1a (diff)
[NET]: Avoid copying TCP packets unnecessarily
TCP packets all have writable heads, that is, even though it's cloned, it is writable up to the end of the TCP header. This patch makes skb_checksum_help aware of this fact by using skb_clone_writable and avoiding a copy for TCP. I've also modified the BUG_ON tests to be unsigned. The only case where this makes a difference is if csum_start points to a location before skb->data. Since skb->data should always include the header where the checksum field is (and all currently callers adhere to that), this change is safe and may uncover bugs later. Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net')
-rw-r--r--net/core/dev.c21
1 files changed, 10 insertions, 11 deletions
diff --git a/net/core/dev.c b/net/core/dev.c
index 39aba4862f21..38b03da5c1ca 100644
--- a/net/core/dev.c
+++ b/net/core/dev.c
@@ -1362,22 +1362,21 @@ int skb_checksum_help(struct sk_buff *skb)
1362 goto out_set_summed; 1362 goto out_set_summed;
1363 } 1363 }
1364 1364
1365 if (skb_cloned(skb)) { 1365 offset = skb->csum_start - skb_headroom(skb);
1366 BUG_ON(offset >= skb_headlen(skb));
1367 csum = skb_checksum(skb, offset, skb->len - offset, 0);
1368
1369 offset += skb->csum_offset;
1370 BUG_ON(offset + sizeof(__sum16) > skb_headlen(skb));
1371
1372 if (skb_cloned(skb) &&
1373 !skb_clone_writable(skb, offset + sizeof(__sum16))) {
1366 ret = pskb_expand_head(skb, 0, 0, GFP_ATOMIC); 1374 ret = pskb_expand_head(skb, 0, 0, GFP_ATOMIC);
1367 if (ret) 1375 if (ret)
1368 goto out; 1376 goto out;
1369 } 1377 }
1370 1378
1371 offset = skb->csum_start - skb_headroom(skb); 1379 *(__sum16 *)(skb->data + offset) = csum_fold(csum);
1372 BUG_ON(offset > (int)skb->len);
1373 csum = skb_checksum(skb, offset, skb->len-offset, 0);
1374
1375 offset = skb_headlen(skb) - offset;
1376 BUG_ON(offset <= 0);
1377 BUG_ON(skb->csum_offset + 2 > offset);
1378
1379 *(__sum16 *)(skb->head + skb->csum_start + skb->csum_offset) =
1380 csum_fold(csum);
1381out_set_summed: 1380out_set_summed:
1382 skb->ip_summed = CHECKSUM_NONE; 1381 skb->ip_summed = CHECKSUM_NONE;
1383out: 1382out: