aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorHiren Panchasara <hiren@FreeBSD.org>2016-12-11 23:14:47 +0000
committerHiren Panchasara <hiren@FreeBSD.org>2016-12-11 23:14:47 +0000
commitb6ff672460ec0910c453d7de047119dd6d34db19 (patch)
tree4cad0f22fba109a1855c6dda59bd4281e053cc14
parent2823b6467ac5bf7c82485778ebe9237d8abf8381 (diff)
downloadsrc-b6ff672460ec0910c453d7de047119dd6d34db19.tar.gz
src-b6ff672460ec0910c453d7de047119dd6d34db19.zip
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
Notes
Notes: svn path=/head/; revision=309858
-rw-r--r--sys/netinet/tcp_output.c40
1 files changed, 21 insertions, 19 deletions
diff --git a/sys/netinet/tcp_output.c b/sys/netinet/tcp_output.c
index fd549944022c..6b187dd810d6 100644
--- a/sys/netinet/tcp_output.c
+++ b/sys/netinet/tcp_output.c
@@ -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.