From e4e92660711d8feb62e38dfd30de6949c2394eb2 Mon Sep 17 00:00:00 2001 From: Andre Oppermann Date: Sun, 15 Aug 2010 13:25:18 +0000 Subject: [PATCH] Fix the interaction between 'ICMP fragmentation needed' MTU updates, path MTU discovery and the tcp_minmss limiter for very small MTU's. When the MTU suggested by the gateway via ICMP, or if there isn't any the next smaller step from ip_next_mtu(), is lower than the floor enforced by net.inet.tcp.minmss (default 216) the value is ignored and the default MSS (512) is used instead. However the DF flag in the IP header is still set in tcp_output() preventing fragmentation by the gateway. Fix this by using tcp_minmss as the MSS and clear the DF flag if the suggested MTU is too low. This turns off path MTU dissovery for the remainder of the session and allows fragmentation to be done by the gateway. Only MTU's smaller than 256 are affected. The smallest official MTU specified is for AX.25 packet radio at 256 octets. PR: kern/146628 Tested by: Matthew Luckie MFC after: 1 week --- sys/netinet/tcp_output.c | 4 +++- sys/netinet/tcp_subr.c | 8 +++----- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/sys/netinet/tcp_output.c b/sys/netinet/tcp_output.c index 4327c7e6da5..be8ea534ee0 100644 --- a/sys/netinet/tcp_output.c +++ b/sys/netinet/tcp_output.c @@ -1186,8 +1186,10 @@ timer: * This might not be the best thing to do according to RFC3390 * Section 2. However the tcp hostcache migitates the problem * so it affects only the first tcp connection with a host. + * + * NB: Don't set DF on small MTU/MSS to have a safe fallback. */ - if (V_path_mtu_discovery) + if (V_path_mtu_discovery && tp->t_maxopd > V_tcp_minmss) ip->ip_off |= IP_DF; error = ip_output(m, tp->t_inpcb->inp_options, NULL, diff --git a/sys/netinet/tcp_subr.c b/sys/netinet/tcp_subr.c index b2eaf20f38a..da478b3116b 100644 --- a/sys/netinet/tcp_subr.c +++ b/sys/netinet/tcp_subr.c @@ -1339,11 +1339,9 @@ tcp_ctlinput(int cmd, struct sockaddr *sa, void *vip) if (!mtu) mtu = ip_next_mtu(ip->ip_len, 1); - if (mtu < max(296, V_tcp_minmss - + sizeof(struct tcpiphdr))) - mtu = 0; - if (!mtu) - mtu = V_tcp_mssdflt + if (mtu < V_tcp_minmss + + sizeof(struct tcpiphdr)) + mtu = V_tcp_minmss + sizeof(struct tcpiphdr); /* * Only cache the the MTU if it