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!
This commit is contained in:
wollman 1995-09-20 21:00:59 +00:00
parent 485a0e0b8a
commit e18c331b1e
3 changed files with 108 additions and 12 deletions

View File

@ -31,7 +31,7 @@
* SUCH DAMAGE.
*
* @(#)tcp_output.c 8.3 (Berkeley) 12/30/93
* $Id: tcp_output.c,v 1.11 1995/05/30 08:09:56 rgrimes Exp $
* $Id: tcp_output.c,v 1.12 1995/09/13 17:36:31 wollman Exp $
*/
#include <sys/param.h>
@ -661,16 +661,28 @@ send:
else
#endif
{
#ifdef MTUDISC
struct rtentry *rt;
#endif
((struct ip *)ti)->ip_len = m->m_pkthdr.len;
((struct ip *)ti)->ip_ttl = tp->t_inpcb->inp_ip.ip_ttl; /* XXX */
((struct ip *)ti)->ip_tos = tp->t_inpcb->inp_ip.ip_tos; /* XXX */
#if BSD >= 43
#ifdef MTUDISC
/*
* See if we should do MTU discovery. We do it only if the following
* are true:
* 1) we have a valid route to the destination
* 2) the MTU is not locked (if it is, then discovery has been
* disabled)
*/
if ((rt = tp->t_inpcb->inp_route.ro_rt)
&& rt->rt_flags & RTF_UP
&& !(rt->rt_rmx.rmx_locks & RTV_MTU)) {
((struct ip *)ti)->ip_off |= IP_DF;
}
#endif /* MTUDISC */
error = ip_output(m, tp->t_inpcb->inp_options, &tp->t_inpcb->inp_route,
so->so_options & SO_DONTROUTE, 0);
#else
error = ip_output(m, (struct mbuf *)0, &tp->t_inpcb->inp_route,
so->so_options & SO_DONTROUTE);
#endif
}
if (error) {
out:

View File

@ -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 */

View File

@ -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 */