Author: hiren
Date: Wed Jan  4 18:03:27 2017
New Revision: 311297
URL: https://svnweb.freebsd.org/changeset/base/311297

Log:
  MFC r309858
  We currently don't do TSO if ip options are present. In case of IPv6, we look 
at
  in6p_options to check that. That is incorrect as we carry ip options in
  in6p_outputopts. Also, just checking for in6p_outputopts being NULL won't
  suffice as we combine ip options and ip header fields both in that one field.
  The commit fixes this by using ip6_optlen() which correctly calculates length
  of only ip options for IPv6.
  
  Sponsored by: Limelight Networks

Modified:
  stable/11/sys/netinet/tcp_output.c
Directory Properties:
  stable/11/   (props changed)

Modified: stable/11/sys/netinet/tcp_output.c
==============================================================================
--- stable/11/sys/netinet/tcp_output.c  Wed Jan  4 17:58:17 2017        
(r311296)
+++ stable/11/sys/netinet/tcp_output.c  Wed Jan  4 18:03:27 2017        
(r311297)
@@ -539,6 +539,11 @@ after_sack_rexmit:
         * (except for the sequence number) for all generated packets.  This
         * makes it impossible to transmit any options which vary per generated
         * segment or packet.
+        *
+        * IPv4 handling has a clear separation of ip options and ip header
+        * flags while IPv6 combines both in in6p_outputopts. ip6_optlen() does
+        * the right thing below to provide length of just ip options and thus
+        * checking for ipoptlen is enough to decide if ip options are present.
         */
 #ifdef IPSEC
        /*
@@ -547,14 +552,25 @@ after_sack_rexmit:
         */
        ipsec_optlen = ipsec_hdrsiz_tcp(tp);
 #endif
+
+#ifdef INET6
+       if (isipv6)
+               ipoptlen = ip6_optlen(tp->t_inpcb);
+       else
+#endif
+       if (tp->t_inpcb->inp_options)
+               ipoptlen = tp->t_inpcb->inp_options->m_len -
+                               offsetof(struct ipoption, ipopt_list);
+       else
+               ipoptlen = 0;
+#ifdef IPSEC
+       ipoptlen += ipsec_optlen;
+#endif
+
        if ((tp->t_flags & TF_TSO) && V_tcp_do_tso && len > tp->t_maxseg &&
            ((tp->t_flags & TF_SIGNATURE) == 0) &&
            tp->rcv_numsacks == 0 && sack_rxmit == 0 &&
-#ifdef IPSEC
-           ipsec_optlen == 0 &&
-#endif
-           tp->t_inpcb->inp_options == NULL &&
-           tp->t_inpcb->in6p_options == NULL)
+           ipoptlen == 0)
                tso = 1;
 
        if (sack_rxmit) {
@@ -825,20 +841,6 @@ send:
                hdrlen += optlen = tcp_addoptions(&to, opt);
        }
 
-#ifdef INET6
-       if (isipv6)
-               ipoptlen = ip6_optlen(tp->t_inpcb);
-       else
-#endif
-       if (tp->t_inpcb->inp_options)
-               ipoptlen = tp->t_inpcb->inp_options->m_len -
-                               offsetof(struct ipoption, ipopt_list);
-       else
-               ipoptlen = 0;
-#ifdef IPSEC
-       ipoptlen += ipsec_optlen;
-#endif
-
        /*
         * Adjust data length if insertion of options will
         * bump the packet length beyond the t_maxseg length.
_______________________________________________
svn-src-all@freebsd.org mailing list
https://lists.freebsd.org/mailman/listinfo/svn-src-all
To unsubscribe, send any mail to "svn-src-all-unsubscr...@freebsd.org"

Reply via email to