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