diff options
author | Herbert Xu <herbert@gondor.apana.org.au> | 2005-11-10 16:01:24 -0500 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2005-11-10 16:01:24 -0500 |
commit | fb286bb2990a107009dbf25f6ffebeb7df77f9be (patch) | |
tree | 0eede2c37f1b3831e59601933eebf6b82be75ffc /net/ipv4/igmp.c | |
parent | 1064e944d03eb7a72c0fa11236d5e69cfd877a71 (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/ipv4/igmp.c')
-rw-r--r-- | net/ipv4/igmp.c | 19 |
1 files changed, 14 insertions, 5 deletions
diff --git a/net/ipv4/igmp.c b/net/ipv4/igmp.c index c6247fc84060..c04607b49212 100644 --- a/net/ipv4/igmp.c +++ b/net/ipv4/igmp.c | |||
@@ -872,11 +872,18 @@ int igmp_rcv(struct sk_buff *skb) | |||
872 | return 0; | 872 | return 0; |
873 | } | 873 | } |
874 | 874 | ||
875 | if (!pskb_may_pull(skb, sizeof(struct igmphdr)) || | 875 | if (!pskb_may_pull(skb, sizeof(struct igmphdr))) |
876 | (u16)csum_fold(skb_checksum(skb, 0, len, 0))) { | 876 | goto drop; |
877 | in_dev_put(in_dev); | 877 | |
878 | kfree_skb(skb); | 878 | switch (skb->ip_summed) { |
879 | return 0; | 879 | case CHECKSUM_HW: |
880 | if (!(u16)csum_fold(skb->csum)) | ||
881 | break; | ||
882 | /* fall through */ | ||
883 | case CHECKSUM_NONE: | ||
884 | skb->csum = 0; | ||
885 | if (__skb_checksum_complete(skb)) | ||
886 | goto drop; | ||
880 | } | 887 | } |
881 | 888 | ||
882 | ih = skb->h.igmph; | 889 | ih = skb->h.igmph; |
@@ -906,6 +913,8 @@ int igmp_rcv(struct sk_buff *skb) | |||
906 | default: | 913 | default: |
907 | NETDEBUG(KERN_DEBUG "New IGMP type=%d, why we do not know about it?\n", ih->type); | 914 | NETDEBUG(KERN_DEBUG "New IGMP type=%d, why we do not know about it?\n", ih->type); |
908 | } | 915 | } |
916 | |||
917 | drop: | ||
909 | in_dev_put(in_dev); | 918 | in_dev_put(in_dev); |
910 | kfree_skb(skb); | 919 | kfree_skb(skb); |
911 | return 0; | 920 | return 0; |