summaryrefslogtreecommitdiffstats
path: root/sys/dev/mxge/if_mxge.c
diff options
context:
space:
mode:
authorgallatin <gallatin@FreeBSD.org>2010-11-22 16:43:05 +0000
committergallatin <gallatin@FreeBSD.org>2010-11-22 16:43:05 +0000
commit40b50edac393cf5770259c50d9e268b957a76878 (patch)
tree141cd7364b750b878b87b62547eed3f35568858a /sys/dev/mxge/if_mxge.c
parentaf24e6ed9f9d097a94dbfa0841e8de86046ecdfa (diff)
downloadFreeBSD-src-40b50edac393cf5770259c50d9e268b957a76878.zip
FreeBSD-src-40b50edac393cf5770259c50d9e268b957a76878.tar.gz
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
Diffstat (limited to 'sys/dev/mxge/if_mxge.c')
-rw-r--r--sys/dev/mxge/if_mxge.c13
1 files changed, 12 insertions, 1 deletions
diff --git a/sys/dev/mxge/if_mxge.c b/sys/dev/mxge/if_mxge.c
index 789b436..abc3aa2 100644
--- a/sys/dev/mxge/if_mxge.c
+++ b/sys/dev/mxge/if_mxge.c
@@ -1855,9 +1855,20 @@ mxge_encap_tso(struct mxge_slice_state *ss, struct mbuf *m,
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;
OpenPOWER on IntegriCloud