kern/111384: msk hw checksum problem

Pyun YongHyeon pyunyh at gmail.com
Tue Apr 10 01:21:56 UTC 2007


On Mon, Apr 09, 2007 at 03:26:18PM +0900, To Harald Schmalzbauer wrote:
 > On Sun, Apr 08, 2007 at 09:20:10PM +0000, Harald Schmalzbauer wrote:
 >  > The following reply was made to PR kern/111384; it has been noted by GNATS.
 >  > 
 >  > From: Harald Schmalzbauer <harry at schmalzbauer.de>
 >  > To: FreeBSD-gnats-submit at freebsd.org, freebsd-bugs at freebsd.org
 >  > Cc:  
 >  > Subject: Re: kern/111384: msk hw checksum problem
 >  > Date: Sun, 8 Apr 2007 22:58:12 +0200
 >  > 
 >  >  I did a quick check on 6.2-stable and couldn't see the symptom (no connection 
 >  >  to freeshports). But I haven't captured traffic, so I can't guarantee that 
 >  >  the "TCP checksum mismatch" doesn't aplly to 6.2-stable as well.
 >  >  
 > 
 > Hmm, it's odd that STABLE works wihtout issues. msk(4) in STABLE
 > takes the same code path so it shoud have the issue too if msk(4) in
 > HEAD also has checksum offload issues.
 > 
 > The reason of sending Winwdos probe message comes from the other
 > party' zero window advertisement in SYN + ACK packet. As you know
 > TCP can't send more data except window probing message if it recevied
 > zero window advirtisement.
 > Maybe the other party(www.freshports.org) advertise its window update
 > packet if it received correct window probe message from msk(4).
 > Since msk(4) failed to generate correct TCP cheksum the other party
 > didn't receive the probe message and you've lost connection here.
 > 
 > Anyway I was able to reproduce the issue on HEAD but I have no idea
 > atm. Just padding with zeros to make it 60 bytes frame didn't work and
 > I wonder how it could work in STABLE.
 > 

Please try attached patch and let me know the result.

-- 
Regards,
Pyun YongHyeon
-------------- next part --------------
Index: if_msk.c
===================================================================
RCS file: /home/ncvs/src/sys/dev/msk/if_msk.c,v
retrieving revision 1.12
diff -u -r1.12 if_msk.c
--- if_msk.c	6 Apr 2007 02:02:07 -0000	1.12
+++ if_msk.c	10 Apr 2007 01:19:23 -0000
@@ -131,6 +131,7 @@
 #include <netinet/udp.h>
 
 #include <machine/bus.h>
+#include <machine/in_cksum.h>
 #include <machine/resource.h>
 #include <sys/rman.h>
 
@@ -2647,7 +2648,6 @@
 		 * hardware. However, TSO performance of Yukon II is very
 		 * good such that it's worth to implement it.
 		 */
-		struct ether_vlan_header *evh;
 		struct ether_header *eh;
 		struct ip *ip;
 		struct tcphdr *tcp;
@@ -2669,17 +2669,37 @@
 				*m_head = NULL;
 				return (ENOBUFS);
 			}
-			evh = mtod(m, struct ether_vlan_header *);
-			ip = (struct ip *)(evh + 1);
-		} else
-			ip = (struct ip *)(eh + 1);
+		}
 		m = m_pullup(m, offset + sizeof(struct ip));
 		if (m == NULL) {
 			*m_head = NULL;
 			return (ENOBUFS);
 		}
+		ip = (struct ip *)(mtod(m, char *) + offset);
 		offset += (ip->ip_hl << 2);
 		tcp_offset = offset;
+		/*
+		 * It seems that Yukon II has Tx checksum offload bug for
+		 * small TCP packets that's less than 60 bytes in size
+		 * (e.g. TCP window probe packet, pure ACK packet).
+		 * Common work around like padding with zeros to make the
+		 * frame minimum ethernet frame size didn't work at all.
+		 * Instead of disabling checksum offload completely we
+		 * resort to S/W checksum routine when we encounter short
+		 * TCP frames.
+		 * Short UDP packets appear to be handled correctly by
+		 * Yukon II.
+		 */
+		if (m->m_pkthdr.len < MSK_MIN_FRAMELEN &&
+		    (m->m_pkthdr.csum_flags & CSUM_TCP) != 0) {
+			uint16_t csum;
+
+			csum = in_cksum_skip(m, ntohs(ip->ip_len) + offset -
+			    (ip->ip_hl << 2), offset);
+			*(uint16_t *)(m->m_data + offset +
+			    m->m_pkthdr.csum_data) = csum;
+			m->m_pkthdr.csum_flags &= ~CSUM_TCP;
+		}
 		if ((m->m_pkthdr.csum_flags & CSUM_TSO) != 0) {
 			m = m_pullup(m, offset + sizeof(struct tcphdr));
 			if (m == NULL) {


More information about the freebsd-bugs mailing list