Skip site navigation (1)Skip section navigation (2)
Date:      Fri, 25 Jan 2019 15:25:53 +0000 (UTC)
From:      Michael Tuexen <tuexen@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-stable@freebsd.org, svn-src-stable-11@freebsd.org
Subject:   svn commit: r343432 - stable/11/sys/netinet
Message-ID:  <201901251525.x0PFPrIe041480@repo.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: tuexen
Date: Fri Jan 25 15:25:53 2019
New Revision: 343432
URL: https://svnweb.freebsd.org/changeset/base/343432

Log:
  MFC r338138:
  
  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@
  Sponsored by:		Netflix, Inc.
  Differential Revision:	https://reviews.freebsd.org/D16796

Modified:
  stable/11/sys/netinet/in_pcb.h
  stable/11/sys/netinet/tcp_input.c
  stable/11/sys/netinet/tcp_subr.c
  stable/11/sys/netinet/tcp_usrreq.c
Directory Properties:
  stable/11/   (props changed)

Modified: stable/11/sys/netinet/in_pcb.h
==============================================================================
--- stable/11/sys/netinet/in_pcb.h	Fri Jan 25 15:21:42 2019	(r343431)
+++ stable/11/sys/netinet/in_pcb.h	Fri Jan 25 15:25:53 2019	(r343432)
@@ -120,6 +120,7 @@ struct in_conninfo {
  * Flags for inc_flags.
  */
 #define	INC_ISIPV6	0x01
+#define	INC_IPV6MINMTU	0x02
 
 #define	inc_isipv6	inc_flags	/* temp compatibility */
 #define	inc_fport	inc_ie.ie_fport

Modified: stable/11/sys/netinet/tcp_input.c
==============================================================================
--- stable/11/sys/netinet/tcp_input.c	Fri Jan 25 15:21:42 2019	(r343431)
+++ stable/11/sys/netinet/tcp_input.c	Fri Jan 25 15:25:53 2019	(r343432)
@@ -1080,6 +1080,8 @@ relocked:
 #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: stable/11/sys/netinet/tcp_subr.c
==============================================================================
--- stable/11/sys/netinet/tcp_subr.c	Fri Jan 25 15:21:42 2019	(r343431)
+++ stable/11/sys/netinet/tcp_subr.c	Fri Jan 25 15:25:53 2019	(r343432)
@@ -2429,6 +2429,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: stable/11/sys/netinet/tcp_usrreq.c
==============================================================================
--- stable/11/sys/netinet/tcp_usrreq.c	Fri Jan 25 15:21:42 2019	(r343431)
+++ stable/11/sys/netinet/tcp_usrreq.c	Fri Jan 25 15:25:53 2019	(r343432)
@@ -1445,6 +1445,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)



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201901251525.x0PFPrIe041480>