diff options
author | Herbert Xu <herbert@gondor.apana.org.au> | 2006-03-21 01:43:56 -0500 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2006-03-21 01:43:56 -0500 |
commit | cbb042f9e1292434e3cacb90e67d8d381aeac5a9 (patch) | |
tree | cc42f42232e56b68111cfebdc175197d8607bdd7 /net | |
parent | ecba320f2e95c9a0c35011d1ecb1db4419980536 (diff) |
[NET]: Replace skb_pull/skb_postpull_rcsum with skb_pull_rcsum
We're now starting to have quite a number of places that do skb_pull
followed immediately by an skb_postpull_rcsum. We can merge these two
operations into one function with skb_pull_rcsum. This makes sense
since most pull operations on receive skb's need to update the
checksum.
I've decided to make this out-of-line since it is fairly big and the
fast path where hardware checksums are enabled need to call
csum_partial anyway.
Since this is a brand new function we get to add an extra check on the
len argument. As it is most callers of skb_pull ignore its return
value which essentially means that there is no check on the len
argument.
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/802/psnap.c | 3 | ||||
-rw-r--r-- | net/8021q/vlan_dev.c | 6 | ||||
-rw-r--r-- | net/bridge/br_netfilter.c | 6 | ||||
-rw-r--r-- | net/core/skbuff.c | 21 |
4 files changed, 26 insertions, 10 deletions
diff --git a/net/802/psnap.c b/net/802/psnap.c index 34e42968b477..97c95eec79ed 100644 --- a/net/802/psnap.c +++ b/net/802/psnap.c | |||
@@ -61,8 +61,7 @@ static int snap_rcv(struct sk_buff *skb, struct net_device *dev, | |||
61 | /* Pass the frame on. */ | 61 | /* Pass the frame on. */ |
62 | u8 *hdr = skb->data; | 62 | u8 *hdr = skb->data; |
63 | skb->h.raw += 5; | 63 | skb->h.raw += 5; |
64 | skb_pull(skb, 5); | 64 | skb_pull_rcsum(skb, 5); |
65 | skb_postpull_rcsum(skb, hdr, 5); | ||
66 | rc = proto->rcvfunc(skb, dev, &snap_packet_type, orig_dev); | 65 | rc = proto->rcvfunc(skb, dev, &snap_packet_type, orig_dev); |
67 | } else { | 66 | } else { |
68 | skb->sk = NULL; | 67 | skb->sk = NULL; |
diff --git a/net/8021q/vlan_dev.c b/net/8021q/vlan_dev.c index 0f604d227da2..da9cfe927158 100644 --- a/net/8021q/vlan_dev.c +++ b/net/8021q/vlan_dev.c | |||
@@ -163,10 +163,8 @@ int vlan_skb_recv(struct sk_buff *skb, struct net_device *dev, | |||
163 | stats->rx_packets++; | 163 | stats->rx_packets++; |
164 | stats->rx_bytes += skb->len; | 164 | stats->rx_bytes += skb->len; |
165 | 165 | ||
166 | skb_pull(skb, VLAN_HLEN); /* take off the VLAN header (4 bytes currently) */ | 166 | /* Take off the VLAN header (4 bytes currently) */ |
167 | 167 | skb_pull_rcsum(skb, VLAN_HLEN); | |
168 | /* Need to correct hardware checksum */ | ||
169 | skb_postpull_rcsum(skb, vhdr, VLAN_HLEN); | ||
170 | 168 | ||
171 | /* Ok, lets check to make sure the device (dev) we | 169 | /* Ok, lets check to make sure the device (dev) we |
172 | * came in on is what this VLAN is attached to. | 170 | * came in on is what this VLAN is attached to. |
diff --git a/net/bridge/br_netfilter.c b/net/bridge/br_netfilter.c index e060aad8624d..6787bc5197f7 100644 --- a/net/bridge/br_netfilter.c +++ b/net/bridge/br_netfilter.c | |||
@@ -425,8 +425,7 @@ static unsigned int br_nf_pre_routing(unsigned int hook, struct sk_buff **pskb, | |||
425 | 425 | ||
426 | if (skb->protocol == __constant_htons(ETH_P_8021Q)) { | 426 | if (skb->protocol == __constant_htons(ETH_P_8021Q)) { |
427 | u8 *vhdr = skb->data; | 427 | u8 *vhdr = skb->data; |
428 | skb_pull(skb, VLAN_HLEN); | 428 | skb_pull_rcsum(skb, VLAN_HLEN); |
429 | skb_postpull_rcsum(skb, vhdr, VLAN_HLEN); | ||
430 | skb->nh.raw += VLAN_HLEN; | 429 | skb->nh.raw += VLAN_HLEN; |
431 | } | 430 | } |
432 | return br_nf_pre_routing_ipv6(hook, skb, in, out, okfn); | 431 | return br_nf_pre_routing_ipv6(hook, skb, in, out, okfn); |
@@ -444,8 +443,7 @@ static unsigned int br_nf_pre_routing(unsigned int hook, struct sk_buff **pskb, | |||
444 | 443 | ||
445 | if (skb->protocol == __constant_htons(ETH_P_8021Q)) { | 444 | if (skb->protocol == __constant_htons(ETH_P_8021Q)) { |
446 | u8 *vhdr = skb->data; | 445 | u8 *vhdr = skb->data; |
447 | skb_pull(skb, VLAN_HLEN); | 446 | skb_pull_rcsum(skb, VLAN_HLEN); |
448 | skb_postpull_rcsum(skb, vhdr, VLAN_HLEN); | ||
449 | skb->nh.raw += VLAN_HLEN; | 447 | skb->nh.raw += VLAN_HLEN; |
450 | } | 448 | } |
451 | 449 | ||
diff --git a/net/core/skbuff.c b/net/core/skbuff.c index 01abf1e8990b..2960c8b82b23 100644 --- a/net/core/skbuff.c +++ b/net/core/skbuff.c | |||
@@ -1795,6 +1795,27 @@ int skb_append_datato_frags(struct sock *sk, struct sk_buff *skb, | |||
1795 | return 0; | 1795 | return 0; |
1796 | } | 1796 | } |
1797 | 1797 | ||
1798 | /** | ||
1799 | * skb_pull_rcsum - pull skb and update receive checksum | ||
1800 | * @skb: buffer to update | ||
1801 | * @start: start of data before pull | ||
1802 | * @len: length of data pulled | ||
1803 | * | ||
1804 | * This function performs an skb_pull on the packet and updates | ||
1805 | * update the CHECKSUM_HW checksum. It should be used on receive | ||
1806 | * path processing instead of skb_pull unless you know that the | ||
1807 | * checksum difference is zero (e.g., a valid IP header) or you | ||
1808 | * are setting ip_summed to CHECKSUM_NONE. | ||
1809 | */ | ||
1810 | unsigned char *skb_pull_rcsum(struct sk_buff *skb, unsigned int len) | ||
1811 | { | ||
1812 | BUG_ON(len > skb->len); | ||
1813 | skb->len -= len; | ||
1814 | BUG_ON(skb->len < skb->data_len); | ||
1815 | skb_postpull_rcsum(skb, skb->data, len); | ||
1816 | return skb->data += len; | ||
1817 | } | ||
1818 | |||
1798 | void __init skb_init(void) | 1819 | void __init skb_init(void) |
1799 | { | 1820 | { |
1800 | skbuff_head_cache = kmem_cache_create("skbuff_head_cache", | 1821 | skbuff_head_cache = kmem_cache_create("skbuff_head_cache", |