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;
_______________________________________________
svn-src-all@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/svn-src-all
To unsubscribe, send any mail to "svn-src-all-unsubscr...@freebsd.org"

Reply via email to