aboutsummaryrefslogtreecommitdiffstats
path: root/net/ipv6/raw.c
diff options
context:
space:
mode:
authorHerbert Xu <herbert@gondor.apana.org.au>2005-11-10 16:01:24 -0500
committerDavid S. Miller <davem@davemloft.net>2005-11-10 16:01:24 -0500
commitfb286bb2990a107009dbf25f6ffebeb7df77f9be (patch)
tree0eede2c37f1b3831e59601933eebf6b82be75ffc /net/ipv6/raw.c
parent1064e944d03eb7a72c0fa11236d5e69cfd877a71 (diff)
[NET]: Detect hardware rx checksum faults correctly
Here is the patch that introduces the generic skb_checksum_complete which also checks for hardware RX checksum faults. If that happens, it'll call netdev_rx_csum_fault which currently prints out a stack trace with the device name. In future it can turn off RX checksum. I've converted every spot under net/ that does RX checksum checks to use skb_checksum_complete or __skb_checksum_complete with the exceptions of: * Those places where checksums are done bit by bit. These will call netdev_rx_csum_fault directly. * The following have not been completely checked/converted: ipmr ip_vs netfilter dccp This patch is based on patches and suggestions from Stephen Hemminger and David S. Miller. Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/ipv6/raw.c')
-rw-r--r--net/ipv6/raw.c42
1 files changed, 16 insertions, 26 deletions
diff --git a/net/ipv6/raw.c b/net/ipv6/raw.c
index 651c79b41eeb..8e9628f1c4c5 100644
--- a/net/ipv6/raw.c
+++ b/net/ipv6/raw.c
@@ -298,13 +298,10 @@ void rawv6_err(struct sock *sk, struct sk_buff *skb,
298static inline int rawv6_rcv_skb(struct sock * sk, struct sk_buff * skb) 298static inline int rawv6_rcv_skb(struct sock * sk, struct sk_buff * skb)
299{ 299{
300 if ((raw6_sk(sk)->checksum || sk->sk_filter) && 300 if ((raw6_sk(sk)->checksum || sk->sk_filter) &&
301 skb->ip_summed != CHECKSUM_UNNECESSARY) { 301 skb_checksum_complete(skb)) {
302 if ((unsigned short)csum_fold(skb_checksum(skb, 0, skb->len, skb->csum))) { 302 /* FIXME: increment a raw6 drops counter here */
303 /* FIXME: increment a raw6 drops counter here */ 303 kfree_skb(skb);
304 kfree_skb(skb); 304 return 0;
305 return 0;
306 }
307 skb->ip_summed = CHECKSUM_UNNECESSARY;
308 } 305 }
309 306
310 /* Charge it to the socket. */ 307 /* Charge it to the socket. */
@@ -337,32 +334,25 @@ int rawv6_rcv(struct sock *sk, struct sk_buff *skb)
337 if (!rp->checksum) 334 if (!rp->checksum)
338 skb->ip_summed = CHECKSUM_UNNECESSARY; 335 skb->ip_summed = CHECKSUM_UNNECESSARY;
339 336
340 if (skb->ip_summed != CHECKSUM_UNNECESSARY) { 337 if (skb->ip_summed == CHECKSUM_HW) {
341 if (skb->ip_summed == CHECKSUM_HW) { 338 skb_postpull_rcsum(skb, skb->nh.raw,
342 skb_postpull_rcsum(skb, skb->nh.raw, 339 skb->h.raw - skb->nh.raw);
343 skb->h.raw - skb->nh.raw); 340 if (!csum_ipv6_magic(&skb->nh.ipv6h->saddr,
341 &skb->nh.ipv6h->daddr,
342 skb->len, inet->num, skb->csum))
344 skb->ip_summed = CHECKSUM_UNNECESSARY; 343 skb->ip_summed = CHECKSUM_UNNECESSARY;
345 if (csum_ipv6_magic(&skb->nh.ipv6h->saddr,
346 &skb->nh.ipv6h->daddr,
347 skb->len, inet->num, skb->csum)) {
348 LIMIT_NETDEBUG(KERN_DEBUG "raw v6 hw csum failure.\n");
349 skb->ip_summed = CHECKSUM_NONE;
350 }
351 }
352 if (skb->ip_summed == CHECKSUM_NONE)
353 skb->csum = ~csum_ipv6_magic(&skb->nh.ipv6h->saddr,
354 &skb->nh.ipv6h->daddr,
355 skb->len, inet->num, 0);
356 } 344 }
345 if (skb->ip_summed != CHECKSUM_UNNECESSARY)
346 skb->csum = ~csum_ipv6_magic(&skb->nh.ipv6h->saddr,
347 &skb->nh.ipv6h->daddr,
348 skb->len, inet->num, 0);
357 349
358 if (inet->hdrincl) { 350 if (inet->hdrincl) {
359 if (skb->ip_summed != CHECKSUM_UNNECESSARY && 351 if (skb_checksum_complete(skb)) {
360 (unsigned short)csum_fold(skb_checksum(skb, 0, skb->len, skb->csum))) {
361 /* FIXME: increment a raw6 drops counter here */ 352 /* FIXME: increment a raw6 drops counter here */
362 kfree_skb(skb); 353 kfree_skb(skb);
363 return 0; 354 return 0;
364 } 355 }
365 skb->ip_summed = CHECKSUM_UNNECESSARY;
366 } 356 }
367 357
368 rawv6_rcv_skb(sk, skb); 358 rawv6_rcv_skb(sk, skb);
@@ -407,7 +397,7 @@ static int rawv6_recvmsg(struct kiocb *iocb, struct sock *sk,
407 if (skb->ip_summed==CHECKSUM_UNNECESSARY) { 397 if (skb->ip_summed==CHECKSUM_UNNECESSARY) {
408 err = skb_copy_datagram_iovec(skb, 0, msg->msg_iov, copied); 398 err = skb_copy_datagram_iovec(skb, 0, msg->msg_iov, copied);
409 } else if (msg->msg_flags&MSG_TRUNC) { 399 } else if (msg->msg_flags&MSG_TRUNC) {
410 if ((unsigned short)csum_fold(skb_checksum(skb, 0, skb->len, skb->csum))) 400 if (__skb_checksum_complete(skb))
411 goto csum_copy_err; 401 goto csum_copy_err;
412 err = skb_copy_datagram_iovec(skb, 0, msg->msg_iov, copied); 402 err = skb_copy_datagram_iovec(skb, 0, msg->msg_iov, copied);
413 } else { 403 } else {