diff options
author | wollman <wollman@FreeBSD.org> | 1995-09-18 15:51:40 +0000 |
---|---|---|
committer | wollman <wollman@FreeBSD.org> | 1995-09-18 15:51:40 +0000 |
commit | ea496cc61fd7886ad990ab3876ac97ea2530a3bd (patch) | |
tree | a92a58dd9752cf0410e2259213d11cb51ddbbe3f /sys | |
parent | 6b2ee7716a791402c70fcb7985e3e55f11fda156 (diff) | |
download | FreeBSD-src-ea496cc61fd7886ad990ab3876ac97ea2530a3bd.zip FreeBSD-src-ea496cc61fd7886ad990ab3876ac97ea2530a3bd.tar.gz |
Initial back-end support for IP MTU discovery, gated on MTUDISC. The support
for TCP has yet to be written.
Diffstat (limited to 'sys')
-rw-r--r-- | sys/netinet/in_rmx.c | 10 | ||||
-rw-r--r-- | sys/netinet/ip_icmp.c | 82 | ||||
-rw-r--r-- | sys/netinet/ip_var.h | 5 | ||||
-rw-r--r-- | sys/netinet/tcp_subr.c | 30 | ||||
-rw-r--r-- | sys/netinet/tcp_timewait.c | 30 |
5 files changed, 152 insertions, 5 deletions
diff --git a/sys/netinet/in_rmx.c b/sys/netinet/in_rmx.c index 4768362..42cf46d 100644 --- a/sys/netinet/in_rmx.c +++ b/sys/netinet/in_rmx.c @@ -26,7 +26,7 @@ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $Id: in_rmx.c,v 1.14 1995/06/21 19:48:53 wollman Exp $ + * $Id: in_rmx.c,v 1.15 1995/07/10 15:39:10 wollman Exp $ */ /* @@ -64,7 +64,9 @@ #include <netinet/tcp_seq.h> #include <netinet/tcp_timer.h> #include <netinet/tcp_var.h> +#ifndef MTUDISC #include <netinet/tcpip.h> +#endif /* not MTUDISC */ #define RTPRF_OURS RTF_PROTO3 /* set on routes we manage */ @@ -104,16 +106,22 @@ in_addroute(void *v_arg, void *n_arg, struct radix_node_head *head, if (!rt->rt_rmx.rmx_recvpipe && !(rt->rt_rmx.rmx_locks & RTV_RPIPE)) rt->rt_rmx.rmx_recvpipe = tcp_recvspace; +#ifndef MTUDISC /* * Finally, set an MTU, again duplicating logic in TCP. * The in_localaddr() business will go away when we have * proper PMTU discovery. */ +#endif /* not MTUDISC */ if (!rt->rt_rmx.rmx_mtu && !(rt->rt_rmx.rmx_locks & RTV_MTU) && rt->rt_ifp) +#ifndef MTUDISC rt->rt_rmx.rmx_mtu = (in_localaddr(sin->sin_addr) ? rt->rt_ifp->if_mtu : tcp_mssdflt + sizeof(struct tcpiphdr)); +#else /* MTUDISC */ + rt->rt_rmx.rmx_mtu = rt->rt_ifp->if_mtu; +#endif /* MTUDISC */ return rn_addroute(v_arg, n_arg, head, treenodes); } diff --git a/sys/netinet/ip_icmp.c b/sys/netinet/ip_icmp.c index 14b763e..507d770 100644 --- a/sys/netinet/ip_icmp.c +++ b/sys/netinet/ip_icmp.c @@ -31,7 +31,7 @@ * SUCH DAMAGE. * * @(#)ip_icmp.c 8.2 (Berkeley) 1/4/94 - * $Id: ip_icmp.c,v 1.8 1995/07/10 16:16:00 wollman Exp $ + * $Id: ip_icmp.c,v 1.9 1995/08/29 17:49:04 wollman Exp $ */ #include <sys/param.h> @@ -302,6 +302,46 @@ icmp_input(m, hlen) printf("deliver to protocol %d\n", icp->icmp_ip.ip_p); #endif icmpsrc.sin_addr = icp->icmp_ip.ip_dst; +#ifdef MTUDISC + /* + * MTU discovery: + * If we got a needfrag and there is a host route to the + * original destination, and the MTU is not locked, then + * set the MTU in the route to the suggested new value + * (if given) and then notify as usual. The ULPs will + * notice that the MTU has changed and adapt accordingly. + * If no new MTU was suggested, then we guess a new one + * less than the current value. If the new MTU is + * unreasonably small (arbitrarily set at 296), then + * we reset the MTU to the interface value and enable the + * lock bit, indicating that we are no longer doing MTU + * discovery. + */ + if (code == PRC_MSGSIZE) { + struct rtentry *rt; + int mtu; + + rt = rtalloc1((struct sockaddr *)&icmpsrc, 0, + RTF_CLONING | RTF_PRCLONING); + if (rt && (rt->rt_flags & RTF_HOST) + && !(rt->rt_rmx.rmx_locks & RTV_MTU)) { + mtu = ntohs(icp->icmp_nextmtu); + if (!mtu) + mtu = ip_next_mtu(rt->rt_rmx.rmx_mtu, + 1); + if (!mtu || mtu < 296) { + rt->rt_rmx.rmx_mtu = + rt->rt_ifp->if_mtu; + rt->rt_rmx.rmx_locks |= RTV_MTU; + } else if (rt->rt_rmx.rmx_mtu > mtu) { + rt->rt_rmx.rmx_mtu = mtu; + } + } + if (rt) + RTFREE(rt); + } + +#endif /* MTUDISC */ ctlfunc = inetsw[ip_protox[icp->icmp_ip.ip_p]].pr_ctlinput; if (ctlfunc) (*ctlfunc)(code, (struct sockaddr *)&icmpsrc, @@ -612,3 +652,43 @@ icmp_sysctl(name, namelen, oldp, oldlenp, newp, newlen) } /* NOTREACHED */ } + +#ifdef MTUDISC +/* + * Return the next larger or smaller MTU plateau (table from RFC 1191) + * given current value MTU. If DIR is less than zero, a larger plateau + * is returned; otherwise, a smaller value is returned. + */ +int +ip_next_mtu(mtu, dir) + int mtu; + int dir; +{ + static int mtutab[] = { + 65535, 32000, 17914, 8166, 4352, 2002, 1492, 1006, 508, 296, + 68, 0 + }; + int i; + + for (i = 0; i < (sizeof mtutab) / (sizeof mtutab[0]); i++) { + if (mtu >= mtutab[i]) + break; + } + + if (dir < 0) { + if (i == 0) { + return 0; + } else { + return mtutab[i - 1]; + } + } else { + if (mtutab[i] == 0) { + return 0; + } else if(mtu > mtutab[i]) { + return mtutab[i]; + } else { + return mtutab[i + 1]; + } + } +} +#endif /* MTUDISC */ diff --git a/sys/netinet/ip_var.h b/sys/netinet/ip_var.h index 028939a..6863f9e 100644 --- a/sys/netinet/ip_var.h +++ b/sys/netinet/ip_var.h @@ -31,7 +31,7 @@ * SUCH DAMAGE. * * @(#)ip_var.h 8.1 (Berkeley) 6/10/93 - * $Id: ip_var.h,v 1.12 1995/06/28 05:13:02 davidg Exp $ + * $Id: ip_var.h,v 1.13 1995/07/26 18:05:16 wollman Exp $ */ #ifndef _NETINET_IP_VAR_H_ @@ -175,6 +175,9 @@ int ip_getmoptions __P((int, struct ip_moptions *, struct mbuf **)); void ip_init __P((void)); extern int (*ip_mforward) __P((struct ip *, struct ifnet *, struct mbuf *, struct ip_moptions *)); +#ifdef MTUDISC +int ip_next_mtu __P((int, int)); +#endif /* MTUDISC */ int ip_optcopy __P((struct ip *, struct ip *)); int ip_output __P((struct mbuf *, struct mbuf *, struct route *, int, struct ip_moptions *)); diff --git a/sys/netinet/tcp_subr.c b/sys/netinet/tcp_subr.c index cf0fc40..be84884 100644 --- a/sys/netinet/tcp_subr.c +++ b/sys/netinet/tcp_subr.c @@ -31,7 +31,7 @@ * SUCH DAMAGE. * * @(#)tcp_subr.c 8.1 (Berkeley) 6/10/93 - * $Id: tcp_subr.c,v 1.12 1995/06/19 16:45:33 wollman Exp $ + * $Id: tcp_subr.c,v 1.13 1995/06/29 18:11:23 wollman Exp $ */ #include <sys/param.h> @@ -429,6 +429,10 @@ tcp_notify(inp, error) sowwakeup(so); } +#ifdef MTUDISC +static void tcp_mtudisc __P((struct inpcb *, int)); +#endif /* MTUDISC */ + void tcp_ctlinput(cmd, sa, ip) int cmd; @@ -440,6 +444,10 @@ tcp_ctlinput(cmd, sa, ip) if (cmd == PRC_QUENCH) notify = tcp_quench; +#ifdef MTUDISC + else if (cmd == PRC_MSGSIZE) + notify = tcp_mtudisc; +#endif /* MTUDISC */ else if (!PRC_IS_REDIRECT(cmd) && ((unsigned)cmd > PRC_NCMDS || inetctlerrmap[cmd] == 0)) return; @@ -466,6 +474,26 @@ tcp_quench(inp, errno) tp->snd_cwnd = tp->t_maxseg; } +#ifdef MTUDISC +/* + * 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. + */ +static void +tcp_mtudisc(inp, errno) + struct inpcb *inp; + int errno; +{ + struct tcpcb *tp = intotcpcb(inp); + +#if 0 + if (tp) + ; /* XXX implement */ +#endif +} +#endif /* MTUDISC */ + /* * Look-up the routing entry to the peer of this inpcb. If no route * is found and it cannot be allocated the return NULL. This routine diff --git a/sys/netinet/tcp_timewait.c b/sys/netinet/tcp_timewait.c index cf0fc40..be84884 100644 --- a/sys/netinet/tcp_timewait.c +++ b/sys/netinet/tcp_timewait.c @@ -31,7 +31,7 @@ * SUCH DAMAGE. * * @(#)tcp_subr.c 8.1 (Berkeley) 6/10/93 - * $Id: tcp_subr.c,v 1.12 1995/06/19 16:45:33 wollman Exp $ + * $Id: tcp_subr.c,v 1.13 1995/06/29 18:11:23 wollman Exp $ */ #include <sys/param.h> @@ -429,6 +429,10 @@ tcp_notify(inp, error) sowwakeup(so); } +#ifdef MTUDISC +static void tcp_mtudisc __P((struct inpcb *, int)); +#endif /* MTUDISC */ + void tcp_ctlinput(cmd, sa, ip) int cmd; @@ -440,6 +444,10 @@ tcp_ctlinput(cmd, sa, ip) if (cmd == PRC_QUENCH) notify = tcp_quench; +#ifdef MTUDISC + else if (cmd == PRC_MSGSIZE) + notify = tcp_mtudisc; +#endif /* MTUDISC */ else if (!PRC_IS_REDIRECT(cmd) && ((unsigned)cmd > PRC_NCMDS || inetctlerrmap[cmd] == 0)) return; @@ -466,6 +474,26 @@ tcp_quench(inp, errno) tp->snd_cwnd = tp->t_maxseg; } +#ifdef MTUDISC +/* + * 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. + */ +static void +tcp_mtudisc(inp, errno) + struct inpcb *inp; + int errno; +{ + struct tcpcb *tp = intotcpcb(inp); + +#if 0 + if (tp) + ; /* XXX implement */ +#endif +} +#endif /* MTUDISC */ + /* * Look-up the routing entry to the peer of this inpcb. If no route * is found and it cannot be allocated the return NULL. This routine |