Skip site navigation (1)Skip section navigation (2)
Date:      Thu, 8 Nov 2012 01:23:41 +1100 (EST)
From:      Mark Andrews <marka@isc.org>
To:        FreeBSD-gnats-submit@FreeBSD.org
Subject:   kern/173444: IPV6_USE_MIN_MTU and TCP is broken
Message-ID:  <201211071423.qA7ENfHK076243@sex.dv.isc.org>
Resent-Message-ID: <201211071430.qA7EU12Q048205@freefall.freebsd.org>

next in thread | raw e-mail | index | archive | help

>Number:         173444
>Category:       kern
>Synopsis:       IPV6_USE_MIN_MTU and TCP is broken
>Confidential:   no
>Severity:       non-critical
>Priority:       medium
>Responsible:    freebsd-bugs
>State:          open
>Quarter:        
>Keywords:       
>Date-Required:
>Class:          sw-bug
>Submitter-Id:   current-users
>Arrival-Date:   Wed Nov 07 14:30:01 UTC 2012
>Closed-Date:
>Last-Modified:
>Originator:     Mark Andrews
>Release:        FreeBSD 8.3-STABLE i386
>Organization:
ISC
>Environment:
System: FreeBSD sex.dv.isc.org 8.3-STABLE FreeBSD 8.3-STABLE #18: Mon Jun 18 11:57:52 EST 2012 root@sex.dv.isc.org:/usr/obj/usr/src/sys/DEBUG i386


>Description:

Setting IPV6_USE_MIN_MTU to one (1) on a IPv6 TCP socket results
in fragmented IPv6 packets being sent rather than the TCP segment
size being adjusted to reflect the MTU limit on the socket.

00:56:44.177930 IP6 2001:470:1f00:820:218:f3ff:feba:9a37 > 2001:470:1f00:820:6233:4bff:fe01:7585: frag (0|1232) 5555 > 63656: Flags [.], ack 42, win 8211, options [nop,nop,TS val 2829969063 ecr 1028520077], length 1200
00:56:44.177936 IP6 2001:470:1f00:820:218:f3ff:feba:9a37 > 2001:470:1f00:820:6233:4bff:fe01:7585: frag (1232|228)
00:56:44.177953 IP6 2001:470:1f00:820:218:f3ff:feba:9a37 > 2001:470:1f00:820:6233:4bff:fe01:7585: frag (0|1232) 5555 > 63656: Flags [.], ack 42, win 8211, options [nop,nop,TS val 2829969063 ecr 1028520077], length 1200
00:56:44.177957 IP6 2001:470:1f00:820:218:f3ff:feba:9a37 > 2001:470:1f00:820:6233:4bff:fe01:7585: frag (1232|228)
00:56:44.177974 IP6 2001:470:1f00:820:218:f3ff:feba:9a37 > 2001:470:1f00:820:6233:4bff:fe01:7585: frag (0|1232) 5555 > 63656: Flags [.], ack 42, win 8211, options [nop,nop,TS val 2829969063 ecr 1028520077], length 1200

>How-To-Repeat:

Apply the following patch to named and transfer a zone.
[The intent of the patch is to avoid PMTUD issues.  Too
many nameservers are behind load balancers / firewalls that
don't pass PTB messages.]

diff --git a/lib/isc/unix/socket.c b/lib/isc/unix/socket.c
index ffe7e02..6fb8860 100644
--- a/lib/isc/unix/socket.c
+++ b/lib/isc/unix/socket.c
@@ -2262,6 +2264,31 @@ clear_bsdcompat(void) {
 }
 #endif
 
+static void
+use_min_mtu(isc__socket_t *sock) {
+#if !defined(IPV6_USE_MIN_MTU) && !defined(IPV6_MTU)
+	UNUSED(sock);
+#endif
+#ifdef IPV6_USE_MIN_MTU
+	/* use minimum MTU */
+	if (sock->pf == AF_INET6) {
+		int on = 1;
+		(void)setsockopt(sock->fd, IPPROTO_IPV6, IPV6_USE_MIN_MTU,
+				(void *)&on, sizeof(on));
+	}
+#endif
+#if defined(IPV6_MTU)
+	/*
+	 * Use minimum MTU on IPv6 sockets.
+	 */
+	if (sock->pf == AF_INET6) {
+		int mtu = 1280;
+		(void)setsockopt(sock->fd, IPPROTO_IPV6, IPV6_MTU,
+				 &mtu, sizeof(mtu));
+	}
+#endif
+}
+
 static isc_result_t
 opensocket(isc__socketmgr_t *manager, isc__socket_t *sock,
 	   isc__socket_t *dup_socket)
@@ -2426,6 +2453,11 @@ opensocket(isc__socketmgr_t *manager, isc__socket_t *sock,
 	}
 #endif
 
+	/*
+	 * Use minimum mtu if possible.
+	 */
+	use_min_mtu(sock);
+
 #if defined(USE_CMSG) || defined(SO_RCVBUF)
 	if (sock->type == isc_sockettype_udp) {
 
@@ -2490,32 +2522,6 @@ opensocket(isc__socketmgr_t *manager, isc__socket_t *sock,
 		}
 #endif /* IPV6_RECVPKTINFO */
 #endif /* ISC_PLATFORM_HAVEIN6PKTINFO */
-#ifdef IPV6_USE_MIN_MTU        /* RFC 3542, not too common yet*/
-		/* use minimum MTU */
-		if (sock->pf == AF_INET6 &&
-		    setsockopt(sock->fd, IPPROTO_IPV6, IPV6_USE_MIN_MTU,
-			       (void *)&on, sizeof(on)) < 0) {
-			isc__strerror(errno, strbuf, sizeof(strbuf));
-			UNEXPECTED_ERROR(__FILE__, __LINE__,
-					 "setsockopt(%d, IPV6_USE_MIN_MTU) "
-					 "%s: %s", sock->fd,
-					 isc_msgcat_get(isc_msgcat,
-							ISC_MSGSET_GENERAL,
-							ISC_MSG_FAILED,
-							"failed"),
-					 strbuf);
-		}
-#endif
-#if defined(IPV6_MTU)
-		/*
-		 * Use minimum MTU on IPv6 sockets.
-		 */
-		if (sock->pf == AF_INET6) {
-			int mtu = 1280;
-			(void)setsockopt(sock->fd, IPPROTO_IPV6, IPV6_MTU,
-					 &mtu, sizeof(mtu));
-		}
-#endif
 #if defined(IPV6_MTU_DISCOVER) && defined(IPV6_PMTUDISC_DONT)
 		/*
 		 * Turn off Path MTU discovery on IPv6/UDP sockets.
@@ -3313,6 +3319,11 @@ internal_accept(isc_task_t *me, isc_event_t *ev) {
 		NEWCONNSOCK(dev)->connected = 1;
 
 		/*
+		 * Use minimum mtu if possible.
+		 */
+		use_min_mtu(NEWCONNSOCK(dev));
+
+		/*
 		 * Save away the remote address
 		 */
 		dev->address = NEWCONNSOCK(dev)->peer_address;
>Fix:

	The TCP layer should check whether ip6po_minmtu is set on
	the socket and adjust the maxmtu appropriately.  The code
	fragment below should do that but has not been tested.

sys/netinet/tcp_input.c:

        if (isipv6) {
                struct ip6_pktopts *opt;
                maxmtu = tcp_maxmtu6(&inp->inp_inc, mtuflags);
                opt = inp->inp_depend6.inp6_outputopts;
                if (opt && opt->ip6po_minmtu)
                        maxmtu = min(maxmtu, IPV6_MMTU);
                tp->t_maxopd = tp->t_maxseg = V_tcp_v6mssdflt;
        } else



>Release-Note:
>Audit-Trail:
>Unformatted:



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