From fb286bb2990a107009dbf25f6ffebeb7df77f9be Mon Sep 17 00:00:00 2001 From: Herbert Xu Date: Thu, 10 Nov 2005 13:01:24 -0800 Subject: [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 Signed-off-by: David S. Miller --- net/sunrpc/socklib.c | 5 +++++ net/sunrpc/svcsock.c | 9 +++------ 2 files changed, 8 insertions(+), 6 deletions(-) (limited to 'net/sunrpc') diff --git a/net/sunrpc/socklib.c b/net/sunrpc/socklib.c index 8f97e90..eb330d4 100644 --- a/net/sunrpc/socklib.c +++ b/net/sunrpc/socklib.c @@ -6,6 +6,9 @@ * Copyright (C) 1995, 1996 Olaf Kirch */ +#include +#include +#include #include #include #include @@ -165,6 +168,8 @@ int csum_partial_copy_to_xdr(struct xdr_buf *xdr, struct sk_buff *skb) return -1; if ((unsigned short)csum_fold(desc.csum)) return -1; + if (unlikely(skb->ip_summed == CHECKSUM_HW)) + netdev_rx_csum_fault(skb->dev); return 0; no_checksum: if (xdr_partial_copy_from_skb(xdr, 0, &desc, skb_read_bits) < 0) diff --git a/net/sunrpc/svcsock.c b/net/sunrpc/svcsock.c index f16e7cd..e50e7cf 100644 --- a/net/sunrpc/svcsock.c +++ b/net/sunrpc/svcsock.c @@ -623,12 +623,9 @@ svc_udp_recvfrom(struct svc_rqst *rqstp) /* we can use it in-place */ rqstp->rq_arg.head[0].iov_base = skb->data + sizeof(struct udphdr); rqstp->rq_arg.head[0].iov_len = len; - if (skb->ip_summed != CHECKSUM_UNNECESSARY) { - if ((unsigned short)csum_fold(skb_checksum(skb, 0, skb->len, skb->csum))) { - skb_free_datagram(svsk->sk_sk, skb); - return 0; - } - skb->ip_summed = CHECKSUM_UNNECESSARY; + if (skb_checksum_complete(skb)) { + skb_free_datagram(svsk->sk_sk, skb); + return 0; } rqstp->rq_skbuff = skb; } -- cgit v1.1