Skip site navigation (1)Skip section navigation (2)
Date:      Mon, 22 Nov 2010 16:43:06 +0000 (UTC)
From:      Andrew Gallatin <gallatin@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org
Subject:   svn commit: r215686 - head/sys/dev/mxge
Message-ID:  <201011221643.oAMGh691098023@svn.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: gallatin
Date: Mon Nov 22 16:43:05 2010
New Revision: 215686
URL: http://svn.freebsd.org/changeset/base/215686

Log:
  Fix a TSO checksum bug on mxge(4):
  
  The Myri10GE NIC will assume all TSO frames contain partial checksum,
  and will emit TSO segments with bad TCP checksums if a TSO frame
  contains a full checksum.  The mxge driver takes care to make sure
  that TSO is disabled when checksum offload is disabled for this
  reason.  However, modules that modify packet contents (like pf) may
  end up completing a checksum on a TSO frame, leading to the NIC emitting
  TSO segments with bad checksums.
  
  To workaround this, restore the partial checksum in the mxge driver
  when we're fed a TSO frame with a full checksum.
  
  Reported by: Bob Healey
  
  MFC after:	3 days

Modified:
  head/sys/dev/mxge/if_mxge.c

Modified: head/sys/dev/mxge/if_mxge.c
==============================================================================
--- head/sys/dev/mxge/if_mxge.c	Mon Nov 22 16:10:54 2010	(r215685)
+++ head/sys/dev/mxge/if_mxge.c	Mon Nov 22 16:43:05 2010	(r215686)
@@ -1855,9 +1855,20 @@ mxge_encap_tso(struct mxge_slice_state *
 
 	tcp = (struct tcphdr *)((char *)ip + (ip->ip_hl << 2));
 	cum_len = -(ip_off + ((ip->ip_hl + tcp->th_off) << 2));
+	cksum_offset = ip_off + (ip->ip_hl << 2);
 
 	/* TSO implies checksum offload on this hardware */
-	cksum_offset = ip_off + (ip->ip_hl << 2);
+	if (__predict_false((m->m_pkthdr.csum_flags & (CSUM_TCP)) == 0)) {
+		/*
+		 * If packet has full TCP csum, replace it with pseudo hdr
+		 * sum that the NIC expects, otherwise the NIC will emit
+		 * packets with bad TCP checksums.
+		 */
+		m->m_pkthdr.csum_flags = CSUM_TCP;
+		m->m_pkthdr.csum_data = offsetof(struct tcphdr, th_sum);
+		tcp->th_sum = in_pseudo(ip->ip_src.s_addr, ip->ip_dst.s_addr,
+			htons(IPPROTO_TCP + (m->m_pkthdr.len - cksum_offset)));		
+	}
 	flags = MXGEFW_FLAGS_TSO_HDR | MXGEFW_FLAGS_FIRST;
 
 	



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201011221643.oAMGh691098023>