summaryrefslogtreecommitdiff
path: root/sys
diff options
context:
space:
mode:
authorNiels Provos <provos@cvs.openbsd.org>2000-12-11 19:12:23 +0000
committerNiels Provos <provos@cvs.openbsd.org>2000-12-11 19:12:23 +0000
commit86e85007b500fe54023f94dad0fd3f5d566fc2ba (patch)
tree3d463028574c7d1b21c010df267e8de5dc180941 /sys
parent65e0a41053cfbb1cc7f87321e3296d712f04de65 (diff)
turn off path mtu when icmp needfrag messages get blocked, okay itojun@
Diffstat (limited to 'sys')
-rw-r--r--sys/netinet/ip_icmp.c45
-rw-r--r--sys/netinet/ip_icmp.h4
-rw-r--r--sys/netinet/tcp_timer.c50
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,