diff options
author | Andrew Rybchenko <arybchik@FreeBSD.org> | 2015-02-20 07:53:46 +0000 |
---|---|---|
committer | Andrew Rybchenko <arybchik@FreeBSD.org> | 2015-02-20 07:53:46 +0000 |
commit | b2c43c38e76daad3281bc9e889a36e05ef03d21b (patch) | |
tree | 4247f9f57fc3fdc648a5390713f8b4f75eaf024c /sys/dev/sfxge | |
parent | 7f745b2b49629390398fe094648426cedd576115 (diff) | |
download | src-b2c43c38e76daad3281bc9e889a36e05ef03d21b.tar.gz src-b2c43c38e76daad3281bc9e889a36e05ef03d21b.zip |
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)
Notes
Notes:
svn path=/head/; revision=279046
Diffstat (limited to 'sys/dev/sfxge')
-rw-r--r-- | sys/dev/sfxge/sfxge_tx.c | 19 |
1 files changed, 16 insertions, 3 deletions
diff --git a/sys/dev/sfxge/sfxge_tx.c b/sys/dev/sfxge/sfxge_tx.c index 988e119d0012..7a5480ba9ee5 100644 --- a/sys/dev/sfxge/sfxge_tx.c +++ b/sys/dev/sfxge/sfxge_tx.c @@ -865,6 +865,8 @@ static void tso_fini(struct sfxge_txq *txq) 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_state *tso, struct mbuf *mbuf) 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; |