diff options
author | Timo Teras <timo.teras@iki.fi> | 2009-03-05 14:49:24 +0200 |
---|---|---|
committer | Timo Teras <timo.teras@iki.fi> | 2009-03-05 14:51:08 +0200 |
commit | ca2533ac4521a1386a4e118256243aa32202d538 (patch) | |
tree | 9570758fc39a8262e1a62c67c90b5fa82e3b3b5d | |
parent | 3a1cb43be3e29b0183b0b33ec97e3d4ca2ac09c8 (diff) | |
download | pingu-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.
-rw-r--r-- | mtu.c | 37 |
1 files changed, 20 insertions, 17 deletions
@@ -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) |