From owner-svn-src-user@FreeBSD.ORG Thu Mar 1 16:40:13 2012 Return-Path: Delivered-To: svn-src-user@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id 519361065670; Thu, 1 Mar 2012 16:40:13 +0000 (UTC) (envelope-from andre@FreeBSD.org) Received: from svn.freebsd.org (svn.freebsd.org [IPv6:2001:4f8:fff6::2c]) by mx1.freebsd.org (Postfix) with ESMTP id 22CC98FC0C; Thu, 1 Mar 2012 16:40:13 +0000 (UTC) Received: from svn.freebsd.org (localhost [127.0.0.1]) by svn.freebsd.org (8.14.4/8.14.4) with ESMTP id q21GeCO3087191; Thu, 1 Mar 2012 16:40:12 GMT (envelope-from andre@svn.freebsd.org) Received: (from andre@localhost) by svn.freebsd.org (8.14.4/8.14.4/Submit) id q21GeCgb087189; Thu, 1 Mar 2012 16:40:12 GMT (envelope-from andre@svn.freebsd.org) Message-Id: <201203011640.q21GeCgb087189@svn.freebsd.org> From: Andre Oppermann Date: Thu, 1 Mar 2012 16:40:12 +0000 (UTC) To: src-committers@freebsd.org, svn-src-user@freebsd.org X-SVN-Group: user MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Cc: Subject: svn commit: r232346 - user/andre/tcp_workqueue/sys/netinet X-BeenThere: svn-src-user@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: "SVN commit messages for the experimental " user" src tree" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Thu, 01 Mar 2012 16:40:13 -0000 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);