aboutsummaryrefslogtreecommitdiffstats
path: root/include
diff options
context:
space:
mode:
authorDavid S. Miller <davem@davemloft.net>2013-11-15 21:11:16 -0500
committerDavid S. Miller <davem@davemloft.net>2013-11-15 21:11:16 -0500
commit018c5bba052b3a383d83cf0c756da0e7bc748397 (patch)
tree5baf9a09e9619cf10d0e399e4ba347eab32b5afb /include
parentf52ed89971adbe79b6438c459814034707b8ab91 (diff)
net: Handle CHECKSUM_COMPLETE more adequately in pskb_trim_rcsum().
Currently pskb_trim_rcsum() just balks on CHECKSUM_COMPLETE packets and remarks them as CHECKSUM_NONE, forcing a software checksum validation later. We have all of the mechanics available to fixup the skb->csum value, even for complicated fragmented packets, via the helpers skb_checksum() and csum_sub(). So just use them. Based upon a suggestion by Herbert Xu. Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'include')
-rw-r--r--include/linux/skbuff.h39
1 files changed, 21 insertions, 18 deletions
diff --git a/include/linux/skbuff.h b/include/linux/skbuff.h
index 215b5ea1cb30..bec1cc7d5e3c 100644
--- a/include/linux/skbuff.h
+++ b/include/linux/skbuff.h
@@ -2263,24 +2263,6 @@ static inline void skb_postpull_rcsum(struct sk_buff *skb,
2263 2263
2264unsigned char *skb_pull_rcsum(struct sk_buff *skb, unsigned int len); 2264unsigned char *skb_pull_rcsum(struct sk_buff *skb, unsigned int len);
2265 2265
2266/**
2267 * pskb_trim_rcsum - trim received skb and update checksum
2268 * @skb: buffer to trim
2269 * @len: new length
2270 *
2271 * This is exactly the same as pskb_trim except that it ensures the
2272 * checksum of received packets are still valid after the operation.
2273 */
2274
2275static inline int pskb_trim_rcsum(struct sk_buff *skb, unsigned int len)
2276{
2277 if (likely(len >= skb->len))
2278 return 0;
2279 if (skb->ip_summed == CHECKSUM_COMPLETE)
2280 skb->ip_summed = CHECKSUM_NONE;
2281 return __pskb_trim(skb, len);
2282}
2283
2284#define skb_queue_walk(queue, skb) \ 2266#define skb_queue_walk(queue, skb) \
2285 for (skb = (queue)->next; \ 2267 for (skb = (queue)->next; \
2286 skb != (struct sk_buff *)(queue); \ 2268 skb != (struct sk_buff *)(queue); \
@@ -2378,6 +2360,27 @@ __wsum __skb_checksum(const struct sk_buff *skb, int offset, int len,
2378__wsum skb_checksum(const struct sk_buff *skb, int offset, int len, 2360__wsum skb_checksum(const struct sk_buff *skb, int offset, int len,
2379 __wsum csum); 2361 __wsum csum);
2380 2362
2363/**
2364 * pskb_trim_rcsum - trim received skb and update checksum
2365 * @skb: buffer to trim
2366 * @len: new length
2367 *
2368 * This is exactly the same as pskb_trim except that it ensures the
2369 * checksum of received packets are still valid after the operation.
2370 */
2371
2372static inline int pskb_trim_rcsum(struct sk_buff *skb, unsigned int len)
2373{
2374 if (likely(len >= skb->len))
2375 return 0;
2376 if (skb->ip_summed == CHECKSUM_COMPLETE) {
2377 __wsum adj = skb_checksum(skb, len, skb->len - len, 0);
2378
2379 skb->csum = csum_sub(skb->csum, adj);
2380 }
2381 return __pskb_trim(skb, len);
2382}
2383
2381static inline void *skb_header_pointer(const struct sk_buff *skb, int offset, 2384static inline void *skb_header_pointer(const struct sk_buff *skb, int offset,
2382 int len, void *buffer) 2385 int len, void *buffer)
2383{ 2386{