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:
parent
485a0e0b8a
commit
e18c331b1e
@ -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:
|
||||
|
@ -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 */
|
||||
|
||||
|
@ -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 */
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user