svn commit: r338138 - head/sys/netinet
Michael Tuexen
tuexen at FreeBSD.org
Tue Aug 21 14:12:31 UTC 2018
Author: tuexen
Date: Tue Aug 21 14:12:30 2018
New Revision: 338138
URL: https://svnweb.freebsd.org/changeset/base/338138
Log:
Enabling the IPPROTO_IPV6 level socket option IPV6_USE_MIN_MTU on a TCP
socket resulted in sending fragmented IPV6 packets.
This is fixes by reducing the MSS to the appropriate value. In addtion,
if the socket option is set before the handshake happens, announce this
MSS to the peer. This is not stricly required, but done since TCP
is conservative.
PR: 173444
Reviewed by: bz@, rrs@
MFC after: 1 month
Sponsored by: Netflix, Inc.
Differential Revision: https://reviews.freebsd.org/D16796
Modified:
head/sys/netinet/in_pcb.h
head/sys/netinet/tcp_input.c
head/sys/netinet/tcp_subr.c
head/sys/netinet/tcp_usrreq.c
Modified: head/sys/netinet/in_pcb.h
==============================================================================
--- head/sys/netinet/in_pcb.h Tue Aug 21 14:07:36 2018 (r338137)
+++ head/sys/netinet/in_pcb.h Tue Aug 21 14:12:30 2018 (r338138)
@@ -122,6 +122,7 @@ struct in_conninfo {
* Flags for inc_flags.
*/
#define INC_ISIPV6 0x01
+#define INC_IPV6MINMTU 0x02
#define inc_fport inc_ie.ie_fport
#define inc_lport inc_ie.ie_lport
Modified: head/sys/netinet/tcp_input.c
==============================================================================
--- head/sys/netinet/tcp_input.c Tue Aug 21 14:07:36 2018 (r338137)
+++ head/sys/netinet/tcp_input.c Tue Aug 21 14:12:30 2018 (r338138)
@@ -1051,6 +1051,8 @@ findpcb:
#ifdef INET6
if (isipv6) {
inc.inc_flags |= INC_ISIPV6;
+ if (inp->inp_inc.inc_flags & INC_IPV6MINMTU)
+ inc.inc_flags |= INC_IPV6MINMTU;
inc.inc6_faddr = ip6->ip6_src;
inc.inc6_laddr = ip6->ip6_dst;
} else
Modified: head/sys/netinet/tcp_subr.c
==============================================================================
--- head/sys/netinet/tcp_subr.c Tue Aug 21 14:07:36 2018 (r338137)
+++ head/sys/netinet/tcp_subr.c Tue Aug 21 14:12:30 2018 (r338138)
@@ -2865,6 +2865,9 @@ tcp_maxmtu6(struct in_conninfo *inc, struct tcp_ifcap
KASSERT(inc != NULL, ("tcp_maxmtu6 with NULL in_conninfo pointer"));
+ if (inc->inc_flags & INC_IPV6MINMTU)
+ return (IPV6_MMTU);
+
if (!IN6_IS_ADDR_UNSPECIFIED(&inc->inc6_faddr)) {
in6_splitscope(&inc->inc6_faddr, &dst6, &scopeid);
if (fib6_lookup_nh_ext(inc->inc_fibnum, &dst6, scopeid, 0,
Modified: head/sys/netinet/tcp_usrreq.c
==============================================================================
--- head/sys/netinet/tcp_usrreq.c Tue Aug 21 14:07:36 2018 (r338137)
+++ head/sys/netinet/tcp_usrreq.c Tue Aug 21 14:12:30 2018 (r338138)
@@ -1584,6 +1584,42 @@ tcp_ctloutput(struct socket *so, struct sockopt *sopt)
if (inp->inp_vflag & INP_IPV6PROTO) {
INP_WUNLOCK(inp);
error = ip6_ctloutput(so, sopt);
+ /*
+ * In case of the IPV6_USE_MIN_MTU socket option,
+ * the INC_IPV6MINMTU flag to announce a corresponding
+ * MSS during the initial handshake.
+ * If the TCP connection is not in the front states,
+ * just reduce the MSS being used.
+ * This avoids the sending of TCP segments which will
+ * be fragmented at the IPv6 layer.
+ */
+ if ((error == 0) &&
+ (sopt->sopt_dir == SOPT_SET) &&
+ (sopt->sopt_level == IPPROTO_IPV6) &&
+ (sopt->sopt_name == IPV6_USE_MIN_MTU)) {
+ INP_WLOCK(inp);
+ if ((inp->inp_flags &
+ (INP_TIMEWAIT | INP_DROPPED))) {
+ INP_WUNLOCK(inp);
+ return (ECONNRESET);
+ }
+ inp->inp_inc.inc_flags |= INC_IPV6MINMTU;
+ tp = intotcpcb(inp);
+ if ((tp->t_state >= TCPS_SYN_SENT) &&
+ (inp->inp_inc.inc_flags & INC_ISIPV6)) {
+ struct ip6_pktopts *opt;
+
+ opt = inp->in6p_outputopts;
+ if ((opt != NULL) &&
+ (opt->ip6po_minmtu ==
+ IP6PO_MINMTU_ALL)) {
+ if (tp->t_maxseg > TCP6_MSS) {
+ tp->t_maxseg = TCP6_MSS;
+ }
+ }
+ }
+ INP_WUNLOCK(inp);
+ }
}
#endif /* INET6 */
#if defined(INET6) && defined(INET)
More information about the svn-src-head
mailing list