aboutsummaryrefslogtreecommitdiffstats
path: root/mtu.c
diff options
context:
space:
mode:
authorTimo Teras <timo.teras@iki.fi>2009-03-05 14:49:24 +0200
committerTimo Teras <timo.teras@iki.fi>2009-03-05 14:51:08 +0200
commitca2533ac4521a1386a4e118256243aa32202d538 (patch)
tree9570758fc39a8262e1a62c67c90b5fa82e3b3b5d /mtu.c
parent3a1cb43be3e29b0183b0b33ec97e3d4ca2ac09c8 (diff)
downloadpingu-ca2533ac4521a1386a4e118256243aa32202d538.tar.bz2
pingu-ca2533ac4521a1386a4e118256243aa32202d538.tar.xz
mtu: rework pmtu detection logic
Ok, the earlier method was not good enough: simply getting a PMTU response cannot be used as final result, since there might be routers further away with smaller PMTU or a black hole problem. So we do always a binary search, except the initial guess gets high MTU and pmtu responses make next guess pmtu sized.
Diffstat (limited to 'mtu.c')
-rw-r--r--mtu.c37
1 files changed, 20 insertions, 17 deletions
diff --git a/mtu.c b/mtu.c
index aa1c74b..1709b69 100644
--- a/mtu.c
+++ b/mtu.c
@@ -69,30 +69,33 @@ static int do_ping(int seq, int size)
static int discover_mtu(void)
{
- int seq = 1;
- int low_mtu, high_mtu, try_mtu;
+ int seq = 1, low_mtu, high_mtu, try_mtu, r;
/* Check if the host is up */
if (do_ping(seq++, 0) < 0)
return -1;
- /* Check if there is no PMTU or if PMTU discovery works */
- low_mtu = do_ping(seq++, 1500);
- if (low_mtu == -1) {
- /* Binary search for working MTU */
- for (low_mtu = 68/2, high_mtu = 1500/2; low_mtu < high_mtu; ) {
- try_mtu = low_mtu + (high_mtu - low_mtu + 1) / 2;
- if (do_ping(seq++, try_mtu * 2) == 0)
- low_mtu = try_mtu;
- else
- high_mtu = try_mtu - 1;
+ /* Discover PMTU */
+ low_mtu = 68/2;
+ high_mtu = 1500/2;
+ try_mtu = 1500/2;
+ while (1) {
+ r = do_ping(seq++, try_mtu * 2);
+ if (r > 0 && r < try_mtu) {
+ /* pmtu */
+ high_mtu = r/2;
+ try_mtu = high_mtu;
+ continue;
}
- low_mtu *= 2;
- } else if (low_mtu == 0) {
- low_mtu = 1500;
+ if (r == 0)
+ low_mtu = try_mtu;
+ else
+ high_mtu = try_mtu - 1;
+ if (low_mtu >= high_mtu)
+ return 2 * low_mtu;
+
+ try_mtu = low_mtu + (high_mtu - low_mtu + 1) / 2;
}
-
- return low_mtu;
}
static void do_discover(void)