svn commit: r309858 - head/sys/netinet

Hiren Panchasara hiren at FreeBSD.org
Sun Dec 11 23:14:48 UTC 2016


Author: hiren
Date: Sun Dec 11 23:14:47 2016
New Revision: 309858
URL: https://svnweb.freebsd.org/changeset/base/309858

Log:
  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.
  
  Reviewed by:	    ae, bz
  MFC after:	    3 weeks
  Sponsored by:	    Limelight Networks

Modified:
  head/sys/netinet/tcp_output.c

Modified: head/sys/netinet/tcp_output.c
==============================================================================
--- head/sys/netinet/tcp_output.c	Sun Dec 11 19:58:13 2016	(r309857)
+++ head/sys/netinet/tcp_output.c	Sun Dec 11 23:14:47 2016	(r309858)
@@ -545,6 +545,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
 	/*
@@ -553,14 +558,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) {
@@ -833,20 +849,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.


More information about the svn-src-head mailing list