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