svn commit: r232346 - user/andre/tcp_workqueue/sys/netinet

Andre Oppermann andre at FreeBSD.org
Thu Mar 1 16:40:13 UTC 2012


Author: andre
Date: Thu Mar  1 16:40:12 2012
New Revision: 232346
URL: http://svn.freebsd.org/changeset/base/232346

Log:
  Work around a bug in path MTU discovery where it never managages to update
  to the new and lower MTU when the tcp hostcache is full.
  
  When an ICMP fragmentation needed message comes in, it is dispatched through
  tcp_ctlinput() which determines the tcp connection it belongs to and then
  updates the tcp hostcache with the new MTU.  After that tcp_mtudisc() is
  called, recalculates the MSS from tcp hostcache for this connection and
  resends some data.
  
  If the tcp hostcache is full, the update with the new MTU fails and the
  MSS recalculation doesn't take the MTU reduction into consideration which
  leads to a too large segment to be sent causing an ICMP message again...
  
  The workaround abuses the errno field in tcp_mtudisc() to communicate the
  new MTU directly and to have it included in the MSS recalculation in any
  case and independent of the tcp hostcache.

Modified:
  user/andre/tcp_workqueue/sys/netinet/tcp_subr.c

Modified: user/andre/tcp_workqueue/sys/netinet/tcp_subr.c
==============================================================================
--- user/andre/tcp_workqueue/sys/netinet/tcp_subr.c	Thu Mar  1 16:18:39 2012	(r232345)
+++ user/andre/tcp_workqueue/sys/netinet/tcp_subr.c	Thu Mar  1 16:40:12 2012	(r232346)
@@ -1410,9 +1410,14 @@ tcp_ctlinput(int cmd, struct sockaddr *s
 					     */
 					    if (mtu <= tcp_maxmtu(&inc, NULL))
 						tcp_hc_updatemtu(&inc, mtu);
-					}
-
-					inp = (*notify)(inp, inetctlerrmap[cmd]);
+					    /*
+					     * Communicated the new MTU
+					     * directly to tcp_mtudisc().
+					     */
+					    inp = (*notify)(inp, mtu);
+					} else
+					    inp = (*notify)(inp,
+							inetctlerrmap[cmd]);
 				}
 			}
 			if (inp != NULL)
@@ -1656,12 +1661,15 @@ tcp_drop_syn_sent(struct inpcb *inp, int
  * based on the new value in the route.  Also nudge TCP to send something,
  * since we know the packet we just sent was dropped.
  * This duplicates some code in the tcp_mss() function in tcp_input.c.
+ *
+ * XXX: errno is abused to directly communicate the new MTU.
  */
 struct inpcb *
 tcp_mtudisc(struct inpcb *inp, int errno)
 {
 	struct tcpcb *tp;
 	struct socket *so;
+	int mtu;
 
 	INP_WLOCK_ASSERT(inp);
 	if ((inp->inp_flags & INP_TIMEWAIT) ||
@@ -1671,7 +1679,12 @@ tcp_mtudisc(struct inpcb *inp, int errno
 	tp = intotcpcb(inp);
 	KASSERT(tp != NULL, ("tcp_mtudisc: tp == NULL"));
 
-	tcp_mss_update(tp, -1, NULL, NULL);
+	/* Extract the MTU from errno for IPv4. */
+	if (errno > PRC_NCMDS)
+		mtu = errno;
+	else
+		mtu = -1:
+	tcp_mss_update(tp, mtu, NULL, NULL);
   
 	so = inp->inp_socket;
 	SOCKBUF_LOCK(&so->so_snd);


More information about the svn-src-user mailing list