aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@g5.osdl.org>2005-11-10 17:46:07 -0500
committerLinus Torvalds <torvalds@g5.osdl.org>2005-11-10 17:46:07 -0500
commit985834a1c3a2e9639145bd8ea16af6e25f2143ad (patch)
tree3a37e487882d1c6b1b8101ef160afb26405b1647
parentb8cbfa692485bf7568eda3d2f37545a76efb7c93 (diff)
parentf3b84ec2a67bbfbe44cf907203ee99b23b38fc30 (diff)
Merge master.kernel.org:/pub/scm/linux/kernel/git/davem/net-2.6
-rw-r--r--Documentation/networking/dccp.txt56
-rw-r--r--MAINTAINERS2
-rw-r--r--drivers/atm/horizon.c4
-rw-r--r--drivers/net/bnx2.c16
-rw-r--r--include/linux/if_ether.h4
-rw-r--r--include/linux/netdevice.h7
-rw-r--r--include/linux/skbuff.h27
-rw-r--r--include/net/tcp.h3
-rw-r--r--net/core/datagram.c21
-rw-r--r--net/core/dev.c12
-rw-r--r--net/core/netpoll.c18
-rw-r--r--net/ipv4/icmp.c6
-rw-r--r--net/ipv4/igmp.c19
-rw-r--r--net/ipv4/ip_gre.c15
-rw-r--r--net/ipv4/netfilter/ip_conntrack_proto_icmp.c11
-rw-r--r--net/ipv4/tcp_ipv4.c24
-rw-r--r--net/ipv4/udp.c7
-rw-r--r--net/ipv6/icmp.c21
-rw-r--r--net/ipv6/raw.c42
-rw-r--r--net/ipv6/tcp_ipv6.c20
-rw-r--r--net/ipv6/udp.c25
-rw-r--r--net/rxrpc/transport.c15
-rw-r--r--net/sunrpc/socklib.c5
-rw-r--r--net/sunrpc/svcsock.c9
24 files changed, 240 insertions, 149 deletions
diff --git a/Documentation/networking/dccp.txt b/Documentation/networking/dccp.txt
new file mode 100644
index 000000000000..c45daabd3bfe
--- /dev/null
+++ b/Documentation/networking/dccp.txt
@@ -0,0 +1,56 @@
1DCCP protocol
2============
3
4Last updated: 10 November 2005
5
6Contents
7========
8
9- Introduction
10- Missing features
11- Socket options
12- Notes
13
14Introduction
15============
16
17Datagram Congestion Control Protocol (DCCP) is an unreliable, connection
18based protocol designed to solve issues present in UDP and TCP particularly
19for real time and multimedia traffic.
20
21It has a base protocol and pluggable congestion control IDs (CCIDs).
22
23It is at draft RFC status and the homepage for DCCP as a protocol is at:
24 http://www.icir.org/kohler/dcp/
25
26Missing features
27================
28
29The DCCP implementation does not currently have all the features that are in
30the draft RFC.
31
32In particular the following are missing:
33- CCID2 support
34- feature negotiation
35
36When testing against other implementations it appears that elapsed time
37options are not coded compliant to the specification.
38
39Socket options
40==============
41
42DCCP_SOCKOPT_PACKET_SIZE is used for CCID3 to set default packet size for
43calculations.
44
45DCCP_SOCKOPT_SERVICE sets the service. This is compulsory as per the
46specification. If you don't set it you will get EPROTO.
47
48Notes
49=====
50
51SELinux does not yet have support for DCCP. You will need to turn it off or
52else you will get EACCES.
53
54DCCP does not travel through NAT successfully at present. This is because
55the checksum covers the psuedo-header as per TCP and UDP. It should be
56relatively trivial to add Linux NAT support for DCCP.
diff --git a/MAINTAINERS b/MAINTAINERS
index 5541f9970b87..0b03a88e88be 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -707,7 +707,7 @@ DCCP PROTOCOL
707P: Arnaldo Carvalho de Melo 707P: Arnaldo Carvalho de Melo
708M: acme@mandriva.com 708M: acme@mandriva.com
709L: dccp@vger.kernel.org 709L: dccp@vger.kernel.org
710W: http://www.wlug.org.nz/DCCP 710W: http://linux-net.osdl.org/index.php/DCCP
711S: Maintained 711S: Maintained
712 712
713DECnet NETWORK LAYER 713DECnet NETWORK LAYER
diff --git a/drivers/atm/horizon.c b/drivers/atm/horizon.c
index 0cded0468003..821c81e8cd38 100644
--- a/drivers/atm/horizon.c
+++ b/drivers/atm/horizon.c
@@ -1511,8 +1511,8 @@ static inline short setup_idle_tx_channel (hrz_dev * dev, hrz_vcc * vcc) {
1511 // a.k.a. prepare the channel and remember that we have done so. 1511 // a.k.a. prepare the channel and remember that we have done so.
1512 1512
1513 tx_ch_desc * tx_desc = &memmap->tx_descs[tx_channel]; 1513 tx_ch_desc * tx_desc = &memmap->tx_descs[tx_channel];
1514 u16 rd_ptr; 1514 u32 rd_ptr;
1515 u16 wr_ptr; 1515 u32 wr_ptr;
1516 u16 channel = vcc->channel; 1516 u16 channel = vcc->channel;
1517 1517
1518 unsigned long flags; 1518 unsigned long flags;
diff --git a/drivers/net/bnx2.c b/drivers/net/bnx2.c
index 8f464271664d..49fa1e4413fa 100644
--- a/drivers/net/bnx2.c
+++ b/drivers/net/bnx2.c
@@ -2707,7 +2707,7 @@ bnx2_init_nvram(struct bnx2 *bp)
2707 2707
2708 if (j == entry_count) { 2708 if (j == entry_count) {
2709 bp->flash_info = NULL; 2709 bp->flash_info = NULL;
2710 printk(KERN_ALERT "Unknown flash/EEPROM type.\n"); 2710 printk(KERN_ALERT PFX "Unknown flash/EEPROM type.\n");
2711 rc = -ENODEV; 2711 rc = -ENODEV;
2712 } 2712 }
2713 2713
@@ -3903,6 +3903,8 @@ bnx2_test_loopback(struct bnx2 *bp)
3903 3903
3904 pkt_size = 1514; 3904 pkt_size = 1514;
3905 skb = dev_alloc_skb(pkt_size); 3905 skb = dev_alloc_skb(pkt_size);
3906 if (!skb)
3907 return -ENOMEM;
3906 packet = skb_put(skb, pkt_size); 3908 packet = skb_put(skb, pkt_size);
3907 memcpy(packet, bp->mac_addr, 6); 3909 memcpy(packet, bp->mac_addr, 6);
3908 memset(packet + 6, 0x0, 8); 3910 memset(packet + 6, 0x0, 8);
@@ -4798,11 +4800,7 @@ bnx2_get_eeprom(struct net_device *dev, struct ethtool_eeprom *eeprom,
4798 struct bnx2 *bp = dev->priv; 4800 struct bnx2 *bp = dev->priv;
4799 int rc; 4801 int rc;
4800 4802
4801 if (eeprom->offset > bp->flash_info->total_size) 4803 /* parameters already validated in ethtool_get_eeprom */
4802 return -EINVAL;
4803
4804 if ((eeprom->offset + eeprom->len) > bp->flash_info->total_size)
4805 eeprom->len = bp->flash_info->total_size - eeprom->offset;
4806 4804
4807 rc = bnx2_nvram_read(bp, eeprom->offset, eebuf, eeprom->len); 4805 rc = bnx2_nvram_read(bp, eeprom->offset, eebuf, eeprom->len);
4808 4806
@@ -4816,11 +4814,7 @@ bnx2_set_eeprom(struct net_device *dev, struct ethtool_eeprom *eeprom,
4816 struct bnx2 *bp = dev->priv; 4814 struct bnx2 *bp = dev->priv;
4817 int rc; 4815 int rc;
4818 4816
4819 if (eeprom->offset > bp->flash_info->total_size) 4817 /* parameters already validated in ethtool_set_eeprom */
4820 return -EINVAL;
4821
4822 if ((eeprom->offset + eeprom->len) > bp->flash_info->total_size)
4823 eeprom->len = bp->flash_info->total_size - eeprom->offset;
4824 4818
4825 rc = bnx2_nvram_write(bp, eeprom->offset, eebuf, eeprom->len); 4819 rc = bnx2_nvram_write(bp, eeprom->offset, eebuf, eeprom->len);
4826 4820
diff --git a/include/linux/if_ether.h b/include/linux/if_ether.h
index d21c305c6c64..fe26d431de87 100644
--- a/include/linux/if_ether.h
+++ b/include/linux/if_ether.h
@@ -21,6 +21,8 @@
21#ifndef _LINUX_IF_ETHER_H 21#ifndef _LINUX_IF_ETHER_H
22#define _LINUX_IF_ETHER_H 22#define _LINUX_IF_ETHER_H
23 23
24#include <linux/types.h>
25
24/* 26/*
25 * IEEE 802.3 Ethernet magic constants. The frame sizes omit the preamble 27 * IEEE 802.3 Ethernet magic constants. The frame sizes omit the preamble
26 * and FCS/CRC (frame check sequence). 28 * and FCS/CRC (frame check sequence).
@@ -100,7 +102,7 @@
100struct ethhdr { 102struct ethhdr {
101 unsigned char h_dest[ETH_ALEN]; /* destination eth addr */ 103 unsigned char h_dest[ETH_ALEN]; /* destination eth addr */
102 unsigned char h_source[ETH_ALEN]; /* source ether addr */ 104 unsigned char h_source[ETH_ALEN]; /* source ether addr */
103 unsigned short h_proto; /* packet type ID field */ 105 __be16 h_proto; /* packet type ID field */
104} __attribute__((packed)); 106} __attribute__((packed));
105 107
106#ifdef __KERNEL__ 108#ifdef __KERNEL__
diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h
index c6efce4a04a4..936f8b76114e 100644
--- a/include/linux/netdevice.h
+++ b/include/linux/netdevice.h
@@ -927,6 +927,13 @@ extern int netdev_max_backlog;
927extern int weight_p; 927extern int weight_p;
928extern int netdev_set_master(struct net_device *dev, struct net_device *master); 928extern int netdev_set_master(struct net_device *dev, struct net_device *master);
929extern int skb_checksum_help(struct sk_buff *skb, int inward); 929extern int skb_checksum_help(struct sk_buff *skb, int inward);
930#ifdef CONFIG_BUG
931extern void netdev_rx_csum_fault(struct net_device *dev);
932#else
933static inline void netdev_rx_csum_fault(struct net_device *dev)
934{
935}
936#endif
930/* rx skb timestamps */ 937/* rx skb timestamps */
931extern void net_enable_timestamp(void); 938extern void net_enable_timestamp(void);
932extern void net_disable_timestamp(void); 939extern void net_disable_timestamp(void);
diff --git a/include/linux/skbuff.h b/include/linux/skbuff.h
index 83010231db99..0a8ea8b35816 100644
--- a/include/linux/skbuff.h
+++ b/include/linux/skbuff.h
@@ -1236,8 +1236,7 @@ extern unsigned int datagram_poll(struct file *file, struct socket *sock,
1236extern int skb_copy_datagram_iovec(const struct sk_buff *from, 1236extern int skb_copy_datagram_iovec(const struct sk_buff *from,
1237 int offset, struct iovec *to, 1237 int offset, struct iovec *to,
1238 int size); 1238 int size);
1239extern int skb_copy_and_csum_datagram_iovec(const 1239extern int skb_copy_and_csum_datagram_iovec(struct sk_buff *skb,
1240 struct sk_buff *skb,
1241 int hlen, 1240 int hlen,
1242 struct iovec *iov); 1241 struct iovec *iov);
1243extern void skb_free_datagram(struct sock *sk, struct sk_buff *skb); 1242extern void skb_free_datagram(struct sock *sk, struct sk_buff *skb);
@@ -1305,6 +1304,30 @@ static inline void skb_set_timestamp(struct sk_buff *skb, const struct timeval *
1305 1304
1306extern void __net_timestamp(struct sk_buff *skb); 1305extern void __net_timestamp(struct sk_buff *skb);
1307 1306
1307extern unsigned int __skb_checksum_complete(struct sk_buff *skb);
1308
1309/**
1310 * skb_checksum_complete - Calculate checksum of an entire packet
1311 * @skb: packet to process
1312 *
1313 * This function calculates the checksum over the entire packet plus
1314 * the value of skb->csum. The latter can be used to supply the
1315 * checksum of a pseudo header as used by TCP/UDP. It returns the
1316 * checksum.
1317 *
1318 * For protocols that contain complete checksums such as ICMP/TCP/UDP,
1319 * this function can be used to verify that checksum on received
1320 * packets. In that case the function should return zero if the
1321 * checksum is correct. In particular, this function will return zero
1322 * if skb->ip_summed is CHECKSUM_UNNECESSARY which indicates that the
1323 * hardware has already verified the correctness of the checksum.
1324 */
1325static inline unsigned int skb_checksum_complete(struct sk_buff *skb)
1326{
1327 return skb->ip_summed != CHECKSUM_UNNECESSARY &&
1328 __skb_checksum_complete(skb);
1329}
1330
1308#ifdef CONFIG_NETFILTER 1331#ifdef CONFIG_NETFILTER
1309static inline void nf_conntrack_put(struct nf_conntrack *nfct) 1332static inline void nf_conntrack_put(struct nf_conntrack *nfct)
1310{ 1333{
diff --git a/include/net/tcp.h b/include/net/tcp.h
index c24339c4e310..96cc3b434e40 100644
--- a/include/net/tcp.h
+++ b/include/net/tcp.h
@@ -27,6 +27,7 @@
27#include <linux/slab.h> 27#include <linux/slab.h>
28#include <linux/cache.h> 28#include <linux/cache.h>
29#include <linux/percpu.h> 29#include <linux/percpu.h>
30#include <linux/skbuff.h>
30 31
31#include <net/inet_connection_sock.h> 32#include <net/inet_connection_sock.h>
32#include <net/inet_timewait_sock.h> 33#include <net/inet_timewait_sock.h>
@@ -852,7 +853,7 @@ static __inline__ u16 tcp_v4_check(struct tcphdr *th, int len,
852 853
853static __inline__ int __tcp_checksum_complete(struct sk_buff *skb) 854static __inline__ int __tcp_checksum_complete(struct sk_buff *skb)
854{ 855{
855 return (unsigned short)csum_fold(skb_checksum(skb, 0, skb->len, skb->csum)); 856 return __skb_checksum_complete(skb);
856} 857}
857 858
858static __inline__ int tcp_checksum_complete(struct sk_buff *skb) 859static __inline__ int tcp_checksum_complete(struct sk_buff *skb)
diff --git a/net/core/datagram.c b/net/core/datagram.c
index d219435d086c..1bcfef51ac58 100644
--- a/net/core/datagram.c
+++ b/net/core/datagram.c
@@ -350,6 +350,20 @@ fault:
350 return -EFAULT; 350 return -EFAULT;
351} 351}
352 352
353unsigned int __skb_checksum_complete(struct sk_buff *skb)
354{
355 unsigned int sum;
356
357 sum = (u16)csum_fold(skb_checksum(skb, 0, skb->len, skb->csum));
358 if (likely(!sum)) {
359 if (unlikely(skb->ip_summed == CHECKSUM_HW))
360 netdev_rx_csum_fault(skb->dev);
361 skb->ip_summed = CHECKSUM_UNNECESSARY;
362 }
363 return sum;
364}
365EXPORT_SYMBOL(__skb_checksum_complete);
366
353/** 367/**
354 * skb_copy_and_csum_datagram_iovec - Copy and checkum skb to user iovec. 368 * skb_copy_and_csum_datagram_iovec - Copy and checkum skb to user iovec.
355 * @skb: skbuff 369 * @skb: skbuff
@@ -363,7 +377,7 @@ fault:
363 * -EFAULT - fault during copy. Beware, in this case iovec 377 * -EFAULT - fault during copy. Beware, in this case iovec
364 * can be modified! 378 * can be modified!
365 */ 379 */
366int skb_copy_and_csum_datagram_iovec(const struct sk_buff *skb, 380int skb_copy_and_csum_datagram_iovec(struct sk_buff *skb,
367 int hlen, struct iovec *iov) 381 int hlen, struct iovec *iov)
368{ 382{
369 unsigned int csum; 383 unsigned int csum;
@@ -376,8 +390,7 @@ int skb_copy_and_csum_datagram_iovec(const struct sk_buff *skb,
376 iov++; 390 iov++;
377 391
378 if (iov->iov_len < chunk) { 392 if (iov->iov_len < chunk) {
379 if ((unsigned short)csum_fold(skb_checksum(skb, 0, chunk + hlen, 393 if (__skb_checksum_complete(skb))
380 skb->csum)))
381 goto csum_error; 394 goto csum_error;
382 if (skb_copy_datagram_iovec(skb, hlen, iov, chunk)) 395 if (skb_copy_datagram_iovec(skb, hlen, iov, chunk))
383 goto fault; 396 goto fault;
@@ -388,6 +401,8 @@ int skb_copy_and_csum_datagram_iovec(const struct sk_buff *skb,
388 goto fault; 401 goto fault;
389 if ((unsigned short)csum_fold(csum)) 402 if ((unsigned short)csum_fold(csum))
390 goto csum_error; 403 goto csum_error;
404 if (unlikely(skb->ip_summed == CHECKSUM_HW))
405 netdev_rx_csum_fault(skb->dev);
391 iov->iov_len -= chunk; 406 iov->iov_len -= chunk;
392 iov->iov_base += chunk; 407 iov->iov_base += chunk;
393 } 408 }
diff --git a/net/core/dev.c b/net/core/dev.c
index 8d1541595277..0b48e294aafe 100644
--- a/net/core/dev.c
+++ b/net/core/dev.c
@@ -1108,6 +1108,18 @@ out:
1108 return ret; 1108 return ret;
1109} 1109}
1110 1110
1111/* Take action when hardware reception checksum errors are detected. */
1112#ifdef CONFIG_BUG
1113void netdev_rx_csum_fault(struct net_device *dev)
1114{
1115 if (net_ratelimit()) {
1116 printk(KERN_ERR "%s: hw csum failure.\n", dev->name);
1117 dump_stack();
1118 }
1119}
1120EXPORT_SYMBOL(netdev_rx_csum_fault);
1121#endif
1122
1111#ifdef CONFIG_HIGHMEM 1123#ifdef CONFIG_HIGHMEM
1112/* Actually, we should eliminate this check as soon as we know, that: 1124/* Actually, we should eliminate this check as soon as we know, that:
1113 * 1. IOMMU is present and allows to map all the memory. 1125 * 1. IOMMU is present and allows to map all the memory.
diff --git a/net/core/netpoll.c b/net/core/netpoll.c
index 802fe11efad0..49424a42a2c0 100644
--- a/net/core/netpoll.c
+++ b/net/core/netpoll.c
@@ -101,16 +101,20 @@ void netpoll_queue(struct sk_buff *skb)
101static int checksum_udp(struct sk_buff *skb, struct udphdr *uh, 101static int checksum_udp(struct sk_buff *skb, struct udphdr *uh,
102 unsigned short ulen, u32 saddr, u32 daddr) 102 unsigned short ulen, u32 saddr, u32 daddr)
103{ 103{
104 if (uh->check == 0) 104 unsigned int psum;
105
106 if (uh->check == 0 || skb->ip_summed == CHECKSUM_UNNECESSARY)
105 return 0; 107 return 0;
106 108
107 if (skb->ip_summed == CHECKSUM_HW) 109 psum = csum_tcpudp_nofold(saddr, daddr, ulen, IPPROTO_UDP, 0);
108 return csum_tcpudp_magic( 110
109 saddr, daddr, ulen, IPPROTO_UDP, skb->csum); 111 if (skb->ip_summed == CHECKSUM_HW &&
112 !(u16)csum_fold(csum_add(psum, skb->csum)))
113 return 0;
110 114
111 skb->csum = csum_tcpudp_nofold(saddr, daddr, ulen, IPPROTO_UDP, 0); 115 skb->csum = psum;
112 116
113 return csum_fold(skb_checksum(skb, 0, skb->len, skb->csum)); 117 return __skb_checksum_complete(skb);
114} 118}
115 119
116/* 120/*
@@ -489,7 +493,7 @@ int __netpoll_rx(struct sk_buff *skb)
489 493
490 if (ulen != len) 494 if (ulen != len)
491 goto out; 495 goto out;
492 if (checksum_udp(skb, uh, ulen, iph->saddr, iph->daddr) < 0) 496 if (checksum_udp(skb, uh, ulen, iph->saddr, iph->daddr))
493 goto out; 497 goto out;
494 if (np->local_ip && np->local_ip != ntohl(iph->daddr)) 498 if (np->local_ip && np->local_ip != ntohl(iph->daddr))
495 goto out; 499 goto out;
diff --git a/net/ipv4/icmp.c b/net/ipv4/icmp.c
index 175e093ec564..e3eceecd0496 100644
--- a/net/ipv4/icmp.c
+++ b/net/ipv4/icmp.c
@@ -934,11 +934,11 @@ int icmp_rcv(struct sk_buff *skb)
934 case CHECKSUM_HW: 934 case CHECKSUM_HW:
935 if (!(u16)csum_fold(skb->csum)) 935 if (!(u16)csum_fold(skb->csum))
936 break; 936 break;
937 LIMIT_NETDEBUG(KERN_DEBUG "icmp v4 hw csum failure\n"); 937 /* fall through */
938 case CHECKSUM_NONE: 938 case CHECKSUM_NONE:
939 if ((u16)csum_fold(skb_checksum(skb, 0, skb->len, 0))) 939 skb->csum = 0;
940 if (__skb_checksum_complete(skb))
940 goto error; 941 goto error;
941 default:;
942 } 942 }
943 943
944 if (!pskb_pull(skb, sizeof(struct icmphdr))) 944 if (!pskb_pull(skb, sizeof(struct icmphdr)))
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
917drop:
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;
diff --git a/net/ipv4/ip_gre.c b/net/ipv4/ip_gre.c
index 896ce3f8f53a..4e9c74b54b15 100644
--- a/net/ipv4/ip_gre.c
+++ b/net/ipv4/ip_gre.c
@@ -577,15 +577,16 @@ static int ipgre_rcv(struct sk_buff *skb)
577 goto drop_nolock; 577 goto drop_nolock;
578 578
579 if (flags&GRE_CSUM) { 579 if (flags&GRE_CSUM) {
580 if (skb->ip_summed == CHECKSUM_HW) { 580 switch (skb->ip_summed) {
581 case CHECKSUM_HW:
581 csum = (u16)csum_fold(skb->csum); 582 csum = (u16)csum_fold(skb->csum);
582 if (csum) 583 if (!csum)
583 skb->ip_summed = CHECKSUM_NONE; 584 break;
584 } 585 /* fall through */
585 if (skb->ip_summed == CHECKSUM_NONE) { 586 case CHECKSUM_NONE:
586 skb->csum = skb_checksum(skb, 0, skb->len, 0); 587 skb->csum = 0;
588 csum = __skb_checksum_complete(skb);
587 skb->ip_summed = CHECKSUM_HW; 589 skb->ip_summed = CHECKSUM_HW;
588 csum = (u16)csum_fold(skb->csum);
589 } 590 }
590 offset += 4; 591 offset += 4;
591 } 592 }
diff --git a/net/ipv4/netfilter/ip_conntrack_proto_icmp.c b/net/ipv4/netfilter/ip_conntrack_proto_icmp.c
index 5198f3a1e2cd..e4d6b268e8c4 100644
--- a/net/ipv4/netfilter/ip_conntrack_proto_icmp.c
+++ b/net/ipv4/netfilter/ip_conntrack_proto_icmp.c
@@ -13,6 +13,7 @@
13#include <linux/in.h> 13#include <linux/in.h>
14#include <linux/icmp.h> 14#include <linux/icmp.h>
15#include <linux/seq_file.h> 15#include <linux/seq_file.h>
16#include <linux/skbuff.h>
16#include <net/ip.h> 17#include <net/ip.h>
17#include <net/checksum.h> 18#include <net/checksum.h>
18#include <linux/netfilter.h> 19#include <linux/netfilter.h>
@@ -230,19 +231,15 @@ icmp_error(struct sk_buff *skb, enum ip_conntrack_info *ctinfo,
230 case CHECKSUM_HW: 231 case CHECKSUM_HW:
231 if (!(u16)csum_fold(skb->csum)) 232 if (!(u16)csum_fold(skb->csum))
232 break; 233 break;
233 if (LOG_INVALID(IPPROTO_ICMP)) 234 /* fall through */
234 nf_log_packet(PF_INET, 0, skb, NULL, NULL, NULL,
235 "ip_ct_icmp: bad HW ICMP checksum ");
236 return -NF_ACCEPT;
237 case CHECKSUM_NONE: 235 case CHECKSUM_NONE:
238 if ((u16)csum_fold(skb_checksum(skb, 0, skb->len, 0))) { 236 skb->csum = 0;
237 if (__skb_checksum_complete(skb)) {
239 if (LOG_INVALID(IPPROTO_ICMP)) 238 if (LOG_INVALID(IPPROTO_ICMP))
240 nf_log_packet(PF_INET, 0, skb, NULL, NULL, NULL, 239 nf_log_packet(PF_INET, 0, skb, NULL, NULL, NULL,
241 "ip_ct_icmp: bad ICMP checksum "); 240 "ip_ct_icmp: bad ICMP checksum ");
242 return -NF_ACCEPT; 241 return -NF_ACCEPT;
243 } 242 }
244 default:
245 break;
246 } 243 }
247 244
248checksum_skipped: 245checksum_skipped:
diff --git a/net/ipv4/tcp_ipv4.c b/net/ipv4/tcp_ipv4.c
index 634dabb558fd..ac1fcf5b4ebc 100644
--- a/net/ipv4/tcp_ipv4.c
+++ b/net/ipv4/tcp_ipv4.c
@@ -1110,24 +1110,18 @@ static struct sock *tcp_v4_hnd_req(struct sock *sk, struct sk_buff *skb)
1110static int tcp_v4_checksum_init(struct sk_buff *skb) 1110static int tcp_v4_checksum_init(struct sk_buff *skb)
1111{ 1111{
1112 if (skb->ip_summed == CHECKSUM_HW) { 1112 if (skb->ip_summed == CHECKSUM_HW) {
1113 skb->ip_summed = CHECKSUM_UNNECESSARY;
1114 if (!tcp_v4_check(skb->h.th, skb->len, skb->nh.iph->saddr, 1113 if (!tcp_v4_check(skb->h.th, skb->len, skb->nh.iph->saddr,
1115 skb->nh.iph->daddr, skb->csum)) 1114 skb->nh.iph->daddr, skb->csum)) {
1115 skb->ip_summed = CHECKSUM_UNNECESSARY;
1116 return 0; 1116 return 0;
1117 1117 }
1118 LIMIT_NETDEBUG(KERN_DEBUG "hw tcp v4 csum failed\n");
1119 skb->ip_summed = CHECKSUM_NONE;
1120 } 1118 }
1119
1120 skb->csum = csum_tcpudp_nofold(skb->nh.iph->saddr, skb->nh.iph->daddr,
1121 skb->len, IPPROTO_TCP, 0);
1122
1121 if (skb->len <= 76) { 1123 if (skb->len <= 76) {
1122 if (tcp_v4_check(skb->h.th, skb->len, skb->nh.iph->saddr, 1124 return __skb_checksum_complete(skb);
1123 skb->nh.iph->daddr,
1124 skb_checksum(skb, 0, skb->len, 0)))
1125 return -1;
1126 skb->ip_summed = CHECKSUM_UNNECESSARY;
1127 } else {
1128 skb->csum = ~tcp_v4_check(skb->h.th, skb->len,
1129 skb->nh.iph->saddr,
1130 skb->nh.iph->daddr, 0);
1131 } 1125 }
1132 return 0; 1126 return 0;
1133} 1127}
@@ -1219,7 +1213,7 @@ int tcp_v4_rcv(struct sk_buff *skb)
1219 * provided case of th->doff==0 is elimineted. 1213 * provided case of th->doff==0 is elimineted.
1220 * So, we defer the checks. */ 1214 * So, we defer the checks. */
1221 if ((skb->ip_summed != CHECKSUM_UNNECESSARY && 1215 if ((skb->ip_summed != CHECKSUM_UNNECESSARY &&
1222 tcp_v4_checksum_init(skb) < 0)) 1216 tcp_v4_checksum_init(skb)))
1223 goto bad_packet; 1217 goto bad_packet;
1224 1218
1225 th = skb->h.th; 1219 th = skb->h.th;
diff --git a/net/ipv4/udp.c b/net/ipv4/udp.c
index e0bd1013cb0d..2422a5f7195d 100644
--- a/net/ipv4/udp.c
+++ b/net/ipv4/udp.c
@@ -761,7 +761,7 @@ int udp_ioctl(struct sock *sk, int cmd, unsigned long arg)
761 761
762static __inline__ int __udp_checksum_complete(struct sk_buff *skb) 762static __inline__ int __udp_checksum_complete(struct sk_buff *skb)
763{ 763{
764 return (unsigned short)csum_fold(skb_checksum(skb, 0, skb->len, skb->csum)); 764 return __skb_checksum_complete(skb);
765} 765}
766 766
767static __inline__ int udp_checksum_complete(struct sk_buff *skb) 767static __inline__ int udp_checksum_complete(struct sk_buff *skb)
@@ -1100,11 +1100,8 @@ static int udp_checksum_init(struct sk_buff *skb, struct udphdr *uh,
1100 if (uh->check == 0) { 1100 if (uh->check == 0) {
1101 skb->ip_summed = CHECKSUM_UNNECESSARY; 1101 skb->ip_summed = CHECKSUM_UNNECESSARY;
1102 } else if (skb->ip_summed == CHECKSUM_HW) { 1102 } else if (skb->ip_summed == CHECKSUM_HW) {
1103 skb->ip_summed = CHECKSUM_UNNECESSARY;
1104 if (!udp_check(uh, ulen, saddr, daddr, skb->csum)) 1103 if (!udp_check(uh, ulen, saddr, daddr, skb->csum))
1105 return 0; 1104 skb->ip_summed = CHECKSUM_UNNECESSARY;
1106 LIMIT_NETDEBUG(KERN_DEBUG "udp v4 hw csum failure.\n");
1107 skb->ip_summed = CHECKSUM_NONE;
1108 } 1105 }
1109 if (skb->ip_summed != CHECKSUM_UNNECESSARY) 1106 if (skb->ip_summed != CHECKSUM_UNNECESSARY)
1110 skb->csum = csum_tcpudp_nofold(saddr, daddr, ulen, IPPROTO_UDP, 0); 1107 skb->csum = csum_tcpudp_nofold(saddr, daddr, ulen, IPPROTO_UDP, 0);
diff --git a/net/ipv6/icmp.c b/net/ipv6/icmp.c
index 23e540365a14..1bdf0fb8bf8a 100644
--- a/net/ipv6/icmp.c
+++ b/net/ipv6/icmp.c
@@ -585,17 +585,16 @@ static int icmpv6_rcv(struct sk_buff **pskb, unsigned int *nhoffp)
585 daddr = &skb->nh.ipv6h->daddr; 585 daddr = &skb->nh.ipv6h->daddr;
586 586
587 /* Perform checksum. */ 587 /* Perform checksum. */
588 if (skb->ip_summed == CHECKSUM_HW) { 588 switch (skb->ip_summed) {
589 skb->ip_summed = CHECKSUM_UNNECESSARY; 589 case CHECKSUM_HW:
590 if (csum_ipv6_magic(saddr, daddr, skb->len, IPPROTO_ICMPV6, 590 if (!csum_ipv6_magic(saddr, daddr, skb->len, IPPROTO_ICMPV6,
591 skb->csum)) { 591 skb->csum))
592 LIMIT_NETDEBUG(KERN_DEBUG "ICMPv6 hw checksum failed\n"); 592 break;
593 skb->ip_summed = CHECKSUM_NONE; 593 /* fall through */
594 } 594 case CHECKSUM_NONE:
595 } 595 skb->csum = ~csum_ipv6_magic(saddr, daddr, skb->len,
596 if (skb->ip_summed == CHECKSUM_NONE) { 596 IPPROTO_ICMPV6, 0);
597 if (csum_ipv6_magic(saddr, daddr, skb->len, IPPROTO_ICMPV6, 597 if (__skb_checksum_complete(skb)) {
598 skb_checksum(skb, 0, skb->len, 0))) {
599 LIMIT_NETDEBUG(KERN_DEBUG "ICMPv6 checksum failed [%04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x > %04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x]\n", 598 LIMIT_NETDEBUG(KERN_DEBUG "ICMPv6 checksum failed [%04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x > %04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x]\n",
600 NIP6(*saddr), NIP6(*daddr)); 599 NIP6(*saddr), NIP6(*daddr));
601 goto discard_it; 600 goto discard_it;
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 {
diff --git a/net/ipv6/tcp_ipv6.c b/net/ipv6/tcp_ipv6.c
index d746d3b27efb..62c0e5bd931c 100644
--- a/net/ipv6/tcp_ipv6.c
+++ b/net/ipv6/tcp_ipv6.c
@@ -1401,20 +1401,18 @@ out:
1401static int tcp_v6_checksum_init(struct sk_buff *skb) 1401static int tcp_v6_checksum_init(struct sk_buff *skb)
1402{ 1402{
1403 if (skb->ip_summed == CHECKSUM_HW) { 1403 if (skb->ip_summed == CHECKSUM_HW) {
1404 skb->ip_summed = CHECKSUM_UNNECESSARY;
1405 if (!tcp_v6_check(skb->h.th,skb->len,&skb->nh.ipv6h->saddr, 1404 if (!tcp_v6_check(skb->h.th,skb->len,&skb->nh.ipv6h->saddr,
1406 &skb->nh.ipv6h->daddr,skb->csum)) 1405 &skb->nh.ipv6h->daddr,skb->csum)) {
1406 skb->ip_summed = CHECKSUM_UNNECESSARY;
1407 return 0; 1407 return 0;
1408 LIMIT_NETDEBUG(KERN_DEBUG "hw tcp v6 csum failed\n"); 1408 }
1409 } 1409 }
1410
1411 skb->csum = ~tcp_v6_check(skb->h.th,skb->len,&skb->nh.ipv6h->saddr,
1412 &skb->nh.ipv6h->daddr, 0);
1413
1410 if (skb->len <= 76) { 1414 if (skb->len <= 76) {
1411 if (tcp_v6_check(skb->h.th,skb->len,&skb->nh.ipv6h->saddr, 1415 return __skb_checksum_complete(skb);
1412 &skb->nh.ipv6h->daddr,skb_checksum(skb, 0, skb->len, 0)))
1413 return -1;
1414 skb->ip_summed = CHECKSUM_UNNECESSARY;
1415 } else {
1416 skb->csum = ~tcp_v6_check(skb->h.th,skb->len,&skb->nh.ipv6h->saddr,
1417 &skb->nh.ipv6h->daddr,0);
1418 } 1416 }
1419 return 0; 1417 return 0;
1420} 1418}
@@ -1575,7 +1573,7 @@ static int tcp_v6_rcv(struct sk_buff **pskb, unsigned int *nhoffp)
1575 goto discard_it; 1573 goto discard_it;
1576 1574
1577 if ((skb->ip_summed != CHECKSUM_UNNECESSARY && 1575 if ((skb->ip_summed != CHECKSUM_UNNECESSARY &&
1578 tcp_v6_checksum_init(skb) < 0)) 1576 tcp_v6_checksum_init(skb)))
1579 goto bad_packet; 1577 goto bad_packet;
1580 1578
1581 th = skb->h.th; 1579 th = skb->h.th;
diff --git a/net/ipv6/udp.c b/net/ipv6/udp.c
index bf9519341fd3..e671153b47b2 100644
--- a/net/ipv6/udp.c
+++ b/net/ipv6/udp.c
@@ -248,7 +248,7 @@ try_again:
248 err = skb_copy_datagram_iovec(skb, sizeof(struct udphdr), msg->msg_iov, 248 err = skb_copy_datagram_iovec(skb, sizeof(struct udphdr), msg->msg_iov,
249 copied); 249 copied);
250 } else if (msg->msg_flags&MSG_TRUNC) { 250 } else if (msg->msg_flags&MSG_TRUNC) {
251 if ((unsigned short)csum_fold(skb_checksum(skb, 0, skb->len, skb->csum))) 251 if (__skb_checksum_complete(skb))
252 goto csum_copy_err; 252 goto csum_copy_err;
253 err = skb_copy_datagram_iovec(skb, sizeof(struct udphdr), msg->msg_iov, 253 err = skb_copy_datagram_iovec(skb, sizeof(struct udphdr), msg->msg_iov,
254 copied); 254 copied);
@@ -363,13 +363,10 @@ static inline int udpv6_queue_rcv_skb(struct sock * sk, struct sk_buff *skb)
363 return -1; 363 return -1;
364 } 364 }
365 365
366 if (skb->ip_summed != CHECKSUM_UNNECESSARY) { 366 if (skb_checksum_complete(skb)) {
367 if ((unsigned short)csum_fold(skb_checksum(skb, 0, skb->len, skb->csum))) { 367 UDP6_INC_STATS_BH(UDP_MIB_INERRORS);
368 UDP6_INC_STATS_BH(UDP_MIB_INERRORS); 368 kfree_skb(skb);
369 kfree_skb(skb); 369 return 0;
370 return 0;
371 }
372 skb->ip_summed = CHECKSUM_UNNECESSARY;
373 } 370 }
374 371
375 if (sock_queue_rcv_skb(sk,skb)<0) { 372 if (sock_queue_rcv_skb(sk,skb)<0) {
@@ -491,13 +488,10 @@ static int udpv6_rcv(struct sk_buff **pskb, unsigned int *nhoffp)
491 uh = skb->h.uh; 488 uh = skb->h.uh;
492 } 489 }
493 490
494 if (skb->ip_summed==CHECKSUM_HW) { 491 if (skb->ip_summed == CHECKSUM_HW &&
492 !csum_ipv6_magic(saddr, daddr, ulen, IPPROTO_UDP, skb->csum))
495 skb->ip_summed = CHECKSUM_UNNECESSARY; 493 skb->ip_summed = CHECKSUM_UNNECESSARY;
496 if (csum_ipv6_magic(saddr, daddr, ulen, IPPROTO_UDP, skb->csum)) { 494
497 LIMIT_NETDEBUG(KERN_DEBUG "udp v6 hw csum failure.\n");
498 skb->ip_summed = CHECKSUM_NONE;
499 }
500 }
501 if (skb->ip_summed != CHECKSUM_UNNECESSARY) 495 if (skb->ip_summed != CHECKSUM_UNNECESSARY)
502 skb->csum = ~csum_ipv6_magic(saddr, daddr, ulen, IPPROTO_UDP, 0); 496 skb->csum = ~csum_ipv6_magic(saddr, daddr, ulen, IPPROTO_UDP, 0);
503 497
@@ -521,8 +515,7 @@ static int udpv6_rcv(struct sk_buff **pskb, unsigned int *nhoffp)
521 if (!xfrm6_policy_check(NULL, XFRM_POLICY_IN, skb)) 515 if (!xfrm6_policy_check(NULL, XFRM_POLICY_IN, skb))
522 goto discard; 516 goto discard;
523 517
524 if (skb->ip_summed != CHECKSUM_UNNECESSARY && 518 if (skb_checksum_complete(skb))
525 (unsigned short)csum_fold(skb_checksum(skb, 0, skb->len, skb->csum)))
526 goto discard; 519 goto discard;
527 UDP6_INC_STATS_BH(UDP_MIB_NOPORTS); 520 UDP6_INC_STATS_BH(UDP_MIB_NOPORTS);
528 521
diff --git a/net/rxrpc/transport.c b/net/rxrpc/transport.c
index 122c086ee2db..dbe6105e83a5 100644
--- a/net/rxrpc/transport.c
+++ b/net/rxrpc/transport.c
@@ -23,6 +23,7 @@
23#include <linux/in.h> 23#include <linux/in.h>
24#include <linux/in6.h> 24#include <linux/in6.h>
25#include <linux/icmp.h> 25#include <linux/icmp.h>
26#include <linux/skbuff.h>
26#include <net/sock.h> 27#include <net/sock.h>
27#include <net/ip.h> 28#include <net/ip.h>
28#if defined(CONFIG_IPV6) || defined (CONFIG_IPV6_MODULE) 29#if defined(CONFIG_IPV6) || defined (CONFIG_IPV6_MODULE)
@@ -475,15 +476,11 @@ void rxrpc_trans_receive_packet(struct rxrpc_transport *trans)
475 476
476 /* we'll probably need to checksum it (didn't call 477 /* we'll probably need to checksum it (didn't call
477 * sock_recvmsg) */ 478 * sock_recvmsg) */
478 if (pkt->ip_summed != CHECKSUM_UNNECESSARY) { 479 if (skb_checksum_complete(pkt)) {
479 if ((unsigned short) 480 kfree_skb(pkt);
480 csum_fold(skb_checksum(pkt, 0, pkt->len, 481 rxrpc_krxiod_queue_transport(trans);
481 pkt->csum))) { 482 _leave(" CSUM failed");
482 kfree_skb(pkt); 483 return;
483 rxrpc_krxiod_queue_transport(trans);
484 _leave(" CSUM failed");
485 return;
486 }
487 } 484 }
488 485
489 addr = pkt->nh.iph->saddr; 486 addr = pkt->nh.iph->saddr;
diff --git a/net/sunrpc/socklib.c b/net/sunrpc/socklib.c
index 8f97e90f36c8..eb330d4f66d6 100644
--- a/net/sunrpc/socklib.c
+++ b/net/sunrpc/socklib.c
@@ -6,6 +6,9 @@
6 * Copyright (C) 1995, 1996 Olaf Kirch <okir@monad.swb.de> 6 * Copyright (C) 1995, 1996 Olaf Kirch <okir@monad.swb.de>
7 */ 7 */
8 8
9#include <linux/compiler.h>
10#include <linux/netdevice.h>
11#include <linux/skbuff.h>
9#include <linux/types.h> 12#include <linux/types.h>
10#include <linux/pagemap.h> 13#include <linux/pagemap.h>
11#include <linux/udp.h> 14#include <linux/udp.h>
@@ -165,6 +168,8 @@ int csum_partial_copy_to_xdr(struct xdr_buf *xdr, struct sk_buff *skb)
165 return -1; 168 return -1;
166 if ((unsigned short)csum_fold(desc.csum)) 169 if ((unsigned short)csum_fold(desc.csum))
167 return -1; 170 return -1;
171 if (unlikely(skb->ip_summed == CHECKSUM_HW))
172 netdev_rx_csum_fault(skb->dev);
168 return 0; 173 return 0;
169no_checksum: 174no_checksum:
170 if (xdr_partial_copy_from_skb(xdr, 0, &desc, skb_read_bits) < 0) 175 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 f16e7cdd6150..e50e7cf43737 100644
--- a/net/sunrpc/svcsock.c
+++ b/net/sunrpc/svcsock.c
@@ -623,12 +623,9 @@ svc_udp_recvfrom(struct svc_rqst *rqstp)
623 /* we can use it in-place */ 623 /* we can use it in-place */
624 rqstp->rq_arg.head[0].iov_base = skb->data + sizeof(struct udphdr); 624 rqstp->rq_arg.head[0].iov_base = skb->data + sizeof(struct udphdr);
625 rqstp->rq_arg.head[0].iov_len = len; 625 rqstp->rq_arg.head[0].iov_len = len;
626 if (skb->ip_summed != CHECKSUM_UNNECESSARY) { 626 if (skb_checksum_complete(skb)) {
627 if ((unsigned short)csum_fold(skb_checksum(skb, 0, skb->len, skb->csum))) { 627 skb_free_datagram(svsk->sk_sk, skb);
628 skb_free_datagram(svsk->sk_sk, skb); 628 return 0;
629 return 0;
630 }
631 skb->ip_summed = CHECKSUM_UNNECESSARY;
632 } 629 }
633 rqstp->rq_skbuff = skb; 630 rqstp->rq_skbuff = skb;
634 } 631 }