Author: tuexen
Date: Mon May  5 17:30:05 2014
New Revision: 265371
URL: http://svnweb.freebsd.org/changeset/base/265371

Log:
  Fill in csum_data only for UDP or TCP packets. This fixes a bug where
  SCTP were reported to have always a correct checksum if they don't
  contain any ethernet padding.
  
  MFC after: 3 days

Modified:
  head/sys/dev/usb/net/if_smsc.c

Modified: head/sys/dev/usb/net/if_smsc.c
==============================================================================
--- head/sys/dev/usb/net/if_smsc.c      Mon May  5 17:06:40 2014        
(r265370)
+++ head/sys/dev/usb/net/if_smsc.c      Mon May  5 17:30:05 2014        
(r265371)
@@ -86,6 +86,9 @@ __FBSDID("$FreeBSD$");
 #include <net/if.h>
 #include <net/if_var.h>
 
+#include <netinet/in.h>
+#include <netinet/ip.h>
+
 #include "opt_platform.h"
 
 #ifdef FDT
@@ -1025,25 +1028,32 @@ smsc_bulk_read_callback(struct usb_xfer 
                                         *
                                         * Ignore H/W csum for non-IPv4 packets.
                                         */
-                                       if (be16toh(eh->ether_type) == 
ETHERTYPE_IP && pktlen > ETHER_MIN_LEN) {
-                                       
-                                               /* Indicate the UDP/TCP csum 
has been calculated */
-                                               m->m_pkthdr.csum_flags |= 
CSUM_DATA_VALID;
-                                                                               
 
-                                               /* Copy the TCP/UDP checksum 
from the last 2 bytes
-                                                * of the transfer and put in 
the csum_data field.
-                                                */
-                                               usbd_copy_out(pc, (off + 
pktlen),
-                                                                         
&m->m_pkthdr.csum_data, 2);
-                                       
-                                               /* The data is copied in 
network order, but the
-                                                * csum algorithm in the kernel 
expects it to be
-                                                * in host network order.
-                                                */
-                                               m->m_pkthdr.csum_data = 
ntohs(m->m_pkthdr.csum_data);
-                                       
-                                               smsc_dbg_printf(sc, "RX 
checksum offloaded (0x%04x)\n",
-                                                                               
m->m_pkthdr.csum_data);
+                                       if ((be16toh(eh->ether_type) == 
ETHERTYPE_IP) &&
+                                           (pktlen > ETHER_MIN_LEN)) {
+                                               struct ip *ip;
+
+                                               ip = (struct ip *)(eh + 1);
+                                               if ((ip->ip_v == IPVERSION) &&
+                                                   ((ip->ip_p == IPPROTO_TCP) 
||
+                                                    (ip->ip_p == 
IPPROTO_UDP))) {
+                                                       /* Indicate the UDP/TCP 
csum has been calculated */
+                                                       m->m_pkthdr.csum_flags 
|= CSUM_DATA_VALID;
+
+                                                       /* Copy the TCP/UDP 
checksum from the last 2 bytes
+                                                        * of the transfer and 
put in the csum_data field.
+                                                        */
+                                                       usbd_copy_out(pc, (off 
+ pktlen),
+                                                                     
&m->m_pkthdr.csum_data, 2);
+
+                                                       /* The data is copied 
in network order, but the
+                                                        * csum algorithm in 
the kernel expects it to be
+                                                        * in host network 
order.
+                                                        */
+                                                       m->m_pkthdr.csum_data = 
ntohs(m->m_pkthdr.csum_data);
+
+                                                       smsc_dbg_printf(sc, "RX 
checksum offloaded (0x%04x)\n",
+                                                                       
m->m_pkthdr.csum_data);
+                                               }
                                        }
                                        
                                        /* Need to adjust the offset as well or 
we'll be off
_______________________________________________
svn-src-all@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/svn-src-all
To unsubscribe, send any mail to "svn-src-all-unsubscr...@freebsd.org"

Reply via email to