aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorHerbert Xu <herbert@gondor.apana.org.au>2006-03-21 01:43:56 -0500
committerDavid S. Miller <davem@davemloft.net>2006-03-21 01:43:56 -0500
commitcbb042f9e1292434e3cacb90e67d8d381aeac5a9 (patch)
treecc42f42232e56b68111cfebdc175197d8607bdd7
parentecba320f2e95c9a0c35011d1ecb1db4419980536 (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>
-rw-r--r--drivers/net/ppp_generic.c4
-rw-r--r--drivers/net/pppoe.c3
-rw-r--r--include/linux/skbuff.h4
-rw-r--r--net/802/psnap.c3
-rw-r--r--net/8021q/vlan_dev.c6
-rw-r--r--net/bridge/br_netfilter.c6
-rw-r--r--net/core/skbuff.c21
7 files changed, 32 insertions, 15 deletions
diff --git a/drivers/net/ppp_generic.c b/drivers/net/ppp_generic.c
index 0245e40b51a1..f608c12e3e8b 100644
--- a/drivers/net/ppp_generic.c
+++ b/drivers/net/ppp_generic.c
@@ -1691,8 +1691,8 @@ ppp_receive_nonmp_frame(struct ppp *ppp, struct sk_buff *skb)
1691 || ppp->npmode[npi] != NPMODE_PASS) { 1691 || ppp->npmode[npi] != NPMODE_PASS) {
1692 kfree_skb(skb); 1692 kfree_skb(skb);
1693 } else { 1693 } else {
1694 skb_pull(skb, 2); /* chop off protocol */ 1694 /* chop off protocol */
1695 skb_postpull_rcsum(skb, skb->data - 2, 2); 1695 skb_pull_rcsum(skb, 2);
1696 skb->dev = ppp->dev; 1696 skb->dev = ppp->dev;
1697 skb->protocol = htons(npindex_to_ethertype[npi]); 1697 skb->protocol = htons(npindex_to_ethertype[npi]);
1698 skb->mac.raw = skb->data; 1698 skb->mac.raw = skb->data;
diff --git a/drivers/net/pppoe.c b/drivers/net/pppoe.c
index 9369f811075d..475dc930380f 100644
--- a/drivers/net/pppoe.c
+++ b/drivers/net/pppoe.c
@@ -337,8 +337,7 @@ static int pppoe_rcv_core(struct sock *sk, struct sk_buff *skb)
337 if (sk->sk_state & PPPOX_BOUND) { 337 if (sk->sk_state & PPPOX_BOUND) {
338 struct pppoe_hdr *ph = (struct pppoe_hdr *) skb->nh.raw; 338 struct pppoe_hdr *ph = (struct pppoe_hdr *) skb->nh.raw;
339 int len = ntohs(ph->length); 339 int len = ntohs(ph->length);
340 skb_pull(skb, sizeof(struct pppoe_hdr)); 340 skb_pull_rcsum(skb, sizeof(struct pppoe_hdr));
341 skb_postpull_rcsum(skb, ph, sizeof(*ph));
342 if (pskb_trim_rcsum(skb, len)) 341 if (pskb_trim_rcsum(skb, len))
343 goto abort_kfree; 342 goto abort_kfree;
344 343
diff --git a/include/linux/skbuff.h b/include/linux/skbuff.h
index 75c963103b9f..613b9513f8b9 100644
--- a/include/linux/skbuff.h
+++ b/include/linux/skbuff.h
@@ -1159,12 +1159,14 @@ static inline int skb_linearize(struct sk_buff *skb, gfp_t gfp)
1159 */ 1159 */
1160 1160
1161static inline void skb_postpull_rcsum(struct sk_buff *skb, 1161static inline void skb_postpull_rcsum(struct sk_buff *skb,
1162 const void *start, int len) 1162 const void *start, unsigned int len)
1163{ 1163{
1164 if (skb->ip_summed == CHECKSUM_HW) 1164 if (skb->ip_summed == CHECKSUM_HW)
1165 skb->csum = csum_sub(skb->csum, csum_partial(start, len, 0)); 1165 skb->csum = csum_sub(skb->csum, csum_partial(start, len, 0));
1166} 1166}
1167 1167
1168unsigned char *skb_pull_rcsum(struct sk_buff *skb, unsigned int len);
1169
1168/** 1170/**
1169 * pskb_trim_rcsum - trim received skb and update checksum 1171 * pskb_trim_rcsum - trim received skb and update checksum
1170 * @skb: buffer to trim 1172 * @skb: buffer to trim
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 */
1810unsigned 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
1798void __init skb_init(void) 1819void __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",