Skip site navigation (1)Skip section navigation (2)
Date:      Fri, 20 Feb 2015 07:53:47 +0000 (UTC)
From:      Andrew Rybchenko <arybchik@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org
Subject:   svn commit: r279046 - head/sys/dev/sfxge
Message-ID:  <201502200753.t1K7rlRX009202@svn.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: arybchik
Date: Fri Feb 20 07:53:46 2015
New Revision: 279046
URL: https://svnweb.freebsd.org/changeset/base/279046

Log:
  sfxge: handle fragmented TCP header in mbuf
  
  TCP header is fragmented in the case of VLAN tagged IPv6 traffic without
  HW VLAN tagging.
  
  Sponsored by:   Solarflare Communications, Inc.
  Approved by:    gnn (mentor)

Modified:
  head/sys/dev/sfxge/sfxge_tx.c

Modified: head/sys/dev/sfxge/sfxge_tx.c
==============================================================================
--- head/sys/dev/sfxge/sfxge_tx.c	Fri Feb 20 06:19:23 2015	(r279045)
+++ head/sys/dev/sfxge/sfxge_tx.c	Fri Feb 20 07:53:46 2015	(r279046)
@@ -865,6 +865,8 @@ static void tso_fini(struct sfxge_txq *t
 static void tso_start(struct sfxge_tso_state *tso, struct mbuf *mbuf)
 {
 	struct ether_header *eh = mtod(mbuf, struct ether_header *);
+	const struct tcphdr *th;
+	struct tcphdr th_copy;
 
 	tso->mbuf = mbuf;
 
@@ -892,13 +894,24 @@ static void tso_start(struct sfxge_tso_s
 		tso->tcph_off = tso->nh_off + sizeof(struct ip6_hdr);
 	}
 
-	tso->header_len = tso->tcph_off + 4 * tso_tcph(tso)->th_off;
+	KASSERT(mbuf->m_len >= tso->tcph_off,
+		("network header is fragmented in mbuf"));
+	/* We need TCP header including flags (window is the next) */
+	if (mbuf->m_len < tso->tcph_off + offsetof(struct tcphdr, th_win)) {
+		m_copydata(tso->mbuf, tso->tcph_off, sizeof(th_copy),
+			   (caddr_t)&th_copy);
+		th = &th_copy;
+	} else {
+		th = tso_tcph(tso);
+	}
+
+	tso->header_len = tso->tcph_off + 4 * th->th_off;
 	tso->seg_size = mbuf->m_pkthdr.tso_segsz;
 
-	tso->seqnum = ntohl(tso_tcph(tso)->th_seq);
+	tso->seqnum = ntohl(th->th_seq);
 
 	/* These flags must not be duplicated */
-	KASSERT(!(tso_tcph(tso)->th_flags & (TH_URG | TH_SYN | TH_RST)),
+	KASSERT(!(th->th_flags & (TH_URG | TH_SYN | TH_RST)),
 		("incompatible TCP flag on TSO packet"));
 
 	tso->out_len = mbuf->m_pkthdr.len - tso->header_len;



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