diff options
author | Niels Provos <provos@cvs.openbsd.org> | 2000-12-11 19:12:23 +0000 |
---|---|---|
committer | Niels Provos <provos@cvs.openbsd.org> | 2000-12-11 19:12:23 +0000 |
commit | 86e85007b500fe54023f94dad0fd3f5d566fc2ba (patch) | |
tree | 3d463028574c7d1b21c010df267e8de5dc180941 /sys | |
parent | 65e0a41053cfbb1cc7f87321e3296d712f04de65 (diff) |
turn off path mtu when icmp needfrag messages get blocked, okay itojun@
Diffstat (limited to 'sys')
-rw-r--r-- | sys/netinet/ip_icmp.c | 45 | ||||
-rw-r--r-- | sys/netinet/ip_icmp.h | 4 | ||||
-rw-r--r-- | sys/netinet/tcp_timer.c | 50 |
3 files changed, 74 insertions, 25 deletions
diff --git a/sys/netinet/ip_icmp.c b/sys/netinet/ip_icmp.c index bd317ee070d..6946c82df2c 100644 --- a/sys/netinet/ip_icmp.c +++ b/sys/netinet/ip_icmp.c @@ -1,4 +1,4 @@ -/* $OpenBSD: ip_icmp.c,v 1.30 2000/10/17 22:33:51 provos Exp $ */ +/* $OpenBSD: ip_icmp.c,v 1.31 2000/12/11 19:12:22 provos Exp $ */ /* $NetBSD: ip_icmp.c,v 1.19 1996/02/13 23:42:22 christos Exp $ */ /* @@ -747,23 +747,15 @@ icmp_sysctl(name, namelen, oldp, oldlenp, newp, newlen) /* NOTREACHED */ } -void -icmp_mtudisc(icp) - struct icmp *icp; +struct rtentry * +icmp_mtudisc_clone(struct sockaddr *dst) { struct rtentry *rt; - struct sockaddr *dst = sintosa(&icmpsrc); - u_long mtu = ntohs(icp->icmp_nextmtu); /* Why a long? IPv6 */ - int error; - - /* Table of common MTUs: */ + int error; - static u_short mtu_table[] = {65535, 65280, 32000, 17914, 9180, 8166, - 4352, 2002, 1492, 1006, 508, 296, 68, 0}; - rt = rtalloc1(dst, 1); if (rt == 0) - return; + return (NULL); /* If we didn't get a host route, allocate one */ @@ -777,7 +769,7 @@ icmp_mtudisc(icp) if (error) { rtfree(rt); rtfree(nrt); - return; + return (NULL); } nrt->rt_rmx = rt->rt_rmx; rtfree(rt); @@ -786,9 +778,29 @@ icmp_mtudisc(icp) error = rt_timer_add(rt, icmp_mtudisc_timeout, ip_mtudisc_timeout_q); if (error) { rtfree(rt); - return; + return (NULL); } + return (rt); +} + +void +icmp_mtudisc(icp) + struct icmp *icp; +{ + struct rtentry *rt; + struct sockaddr *dst = sintosa(&icmpsrc); + u_long mtu = ntohs(icp->icmp_nextmtu); /* Why a long? IPv6 */ + + /* Table of common MTUs: */ + + static u_short mtu_table[] = {65535, 65280, 32000, 17914, 9180, 8166, + 4352, 2002, 1492, 1006, 508, 296, 68, 0}; + + rt = icmp_mtudisc_clone(dst); + if (rt == 0) + return; + if (mtu == 0) { int i = 0; @@ -831,8 +843,7 @@ icmp_mtudisc(icp) rt->rt_rmx.rmx_mtu = mtu; } - if (rt) - rtfree(rt); + rtfree(rt); } void diff --git a/sys/netinet/ip_icmp.h b/sys/netinet/ip_icmp.h index 387e3b1b2c0..11436f34dca 100644 --- a/sys/netinet/ip_icmp.h +++ b/sys/netinet/ip_icmp.h @@ -1,4 +1,4 @@ -/* $OpenBSD: ip_icmp.h,v 1.10 2000/10/10 15:16:02 provos Exp $ */ +/* $OpenBSD: ip_icmp.h,v 1.11 2000/12/11 19:12:22 provos Exp $ */ /* $NetBSD: ip_icmp.h,v 1.10 1996/02/13 23:42:28 christos Exp $ */ /* @@ -186,5 +186,7 @@ void icmp_input __P((struct mbuf *, ...)); void icmp_reflect __P((struct mbuf *)); void icmp_send __P((struct mbuf *, struct mbuf *)); int icmp_sysctl __P((int *, u_int, void *, size_t *, void *, size_t)); +struct rtentry * + icmp_mtudisc_clone(struct sockaddr *); void icmp_mtudisc __P((struct icmp *)); #endif diff --git a/sys/netinet/tcp_timer.c b/sys/netinet/tcp_timer.c index 4f7b1726439..c1e08b91f27 100644 --- a/sys/netinet/tcp_timer.c +++ b/sys/netinet/tcp_timer.c @@ -1,4 +1,4 @@ -/* $OpenBSD: tcp_timer.c,v 1.17 2000/09/18 22:06:38 provos Exp $ */ +/* $OpenBSD: tcp_timer.c,v 1.18 2000/12/11 19:12:22 provos Exp $ */ /* $NetBSD: tcp_timer.c,v 1.14 1996/02/13 23:44:09 christos Exp $ */ /* @@ -60,6 +60,7 @@ #include <netinet/tcp_timer.h> #include <netinet/tcp_var.h> #include <netinet/tcpip.h> +#include <netinet/ip_icmp.h> #include <dev/rndvar.h> int tcp_keepidle = TCPTV_KEEP_IDLE; @@ -236,7 +237,7 @@ tcp_timers(tp, timer) rto * tcp_backoff[tp->t_rxtshift], tp->t_rttmin, TCPTV_REXMTMAX); tp->t_timer[TCPT_REXMT] = tp->t_rxtcur; -#if 0 + /* * If we are losing and we are trying path MTU discovery, * try turning it off. This will avoid black holes in @@ -245,15 +246,50 @@ tcp_timers(tp, timer) * lots more sophisticated searching to find the right * value here... */ - if (ip_mtudisc && tp->t_rxtshift > TCP_MAXRXTSHIFT / 6) { + if (ip_mtudisc && tp->t_inpcb && + tp->t_rxtshift > TCP_MAXRXTSHIFT / 6) { + struct inpcb *inp = tp->t_inpcb; struct rtentry *rt = NULL; + struct sockaddr_in sin; - if (tp->t_inpcb) - rt = in_pcbrtentry(tp->t_inpcb); - /* XXX: Black hole recovery code goes here */ - } + rt = in_pcbrtentry(inp); + /* Check if path MTU discovery is disabled already */ + if (rt && (rt->rt_flags & RTF_HOST) && + (rt->rt_rmx.rmx_locks & RTV_MTU)) + goto out; + + rt = NULL; + switch(tp->pf) { +#ifdef INET6 + case PF_INET6: + /* + * We can not turn off path MTU for IPv6. + * Do nothing for now, maybe lower to + * minimum MTU. + */ + break; #endif + case PF_INET: + bzero(&sin, sizeof(struct sockaddr_in)); + sin.sin_family = AF_INET; + sin.sin_len = sizeof(struct sockaddr_in); + sin.sin_addr = inp->inp_faddr; + rt = icmp_mtudisc_clone(sintosa(&sin)); + break; + } + if (rt != NULL) { + /* Disable path MTU discovery */ + if ((rt->rt_rmx.rmx_locks & RTV_MTU) == 0) { + rt->rt_rmx.rmx_locks |= RTV_MTU; + in_rtchange(inp, 0); + } + + rtfree(rt); + } + out: + } + /* * If losing, let the lower level know and try for * a better route. Also, if we backed off this far, |