summaryrefslogtreecommitdiffstats
path: root/sys/netinet/tcp_timewait.c
diff options
context:
space:
mode:
authorwollman <wollman@FreeBSD.org>1995-09-20 21:00:59 +0000
committerwollman <wollman@FreeBSD.org>1995-09-20 21:00:59 +0000
commite18c331b1e6f91656cba38295f18835adce3f11d (patch)
tree572521b669715309966bebc91e904cbbebae377c /sys/netinet/tcp_timewait.c
parent485a0e0b8aad01680b4766dcbaf62a6d43067b02 (diff)
downloadFreeBSD-src-e18c331b1e6f91656cba38295f18835adce3f11d.zip
FreeBSD-src-e18c331b1e6f91656cba38295f18835adce3f11d.tar.gz
Add support in TCP for Path MTU discovery. This is highly experimental
and gated on `options MTUDISC' in the source. It is also practically untested becausse (sniff!) I don't have easy access to a network with an MTU of less than an Ethernet. If you have a small MTU network, please try it and tell me if it works!
Diffstat (limited to 'sys/netinet/tcp_timewait.c')
-rw-r--r--sys/netinet/tcp_timewait.c48
1 files changed, 45 insertions, 3 deletions
diff --git a/sys/netinet/tcp_timewait.c b/sys/netinet/tcp_timewait.c
index be84884..feec90b 100644
--- a/sys/netinet/tcp_timewait.c
+++ b/sys/netinet/tcp_timewait.c
@@ -479,6 +479,7 @@ tcp_quench(inp, errno)
* When `need fragmentation' ICMP is received, update our idea of the MSS
* 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.
*/
static void
tcp_mtudisc(inp, errno)
@@ -486,11 +487,52 @@ tcp_mtudisc(inp, errno)
int errno;
{
struct tcpcb *tp = intotcpcb(inp);
+ struct rtentry *rt;
+ struct rmxp_tao *taop;
+ struct socket *so = inp->inp_socket;
+ int offered;
+ int mss;
-#if 0
- if (tp)
- ; /* XXX implement */
+ if (tp) {
+ rt = tcp_rtlookup(inp);
+ if (!rt || !rt->rt_rmx.rmx_mtu) {
+ tp->t_maxopd = tp->t_maxseg = tcp_mssdflt;
+ return;
+ }
+ taop = rmx_taop(rt->rt_rmx);
+ offered = taop->tao_mssopt;
+ mss = rt->rt_rmx.rmx_mtu - sizeof(struct tcpiphdr);
+ mss = min(mss, offer);
+ tp->t_maxopd = mss;
+
+ if ((tp->t_flags & (TF_REQ_TSTMP|TF_NOOPT)) == TF_REQ_TSTMP &&
+ (tp->t_flags & TF_RCVD_TSTMP) == TF_RCVD_TSTMP)
+ mss -= TCPOLEN_TSTAMP_APPA;
+ if ((tp->t_flags & (TF_REQ_CC|TF_NOOPT)) == TF_REQ_CC &&
+ (tp->t_flags & TF_RCVD_CC) == TF_RCVD_CC)
+ mss -= TCPOLEN_CC_APPA;
+#if (MCLBYTES & (MCLBYTES - 1)) == 0
+ if (mss > MCLBYTES)
+ mss &= ~(MCLBYTES-1);
+#else
+ if (mss > MCLBYTES)
+ mss = mss / MCLBYTES * MCLBYTES;
#endif
+ if (so->so_snd.sb_hiwat < mss)
+ mss = so->so_snd.sb_hiwat;
+
+ tp->t_maxseg = mss;
+
+ /*
+ * Nudge TCP output. Unfortunately, we have no way to know
+ * which packet that we sent is the failing one, but in the
+ * vast majority of cases we expect that it will be at the
+ * beginning of the window, so this should do the right
+ * thing (I hope).
+ */
+ tp->snd_nxt = tp->snd_una;
+ tcp_output(tp);
+ }
}
#endif /* MTUDISC */
OpenPOWER on IntegriCloud