From: Mark Wooding Date: Sat, 3 May 2014 19:04:44 +0000 (+0100) Subject: pathmtu/pathmtu.c: Use IP_PMTUDISC_PROBE for sending the lookups. X-Git-Tag: 1.0.0pre16~25 X-Git-Url: https://git.distorted.org.uk/~mdw/tripe/commitdiff_plain/18d5f6eb91b1f8e1f497b0176c07a91aa6492be0?ds=sidebyside pathmtu/pathmtu.c: Use IP_PMTUDISC_PROBE for sending the lookups. Linux's behaviour is very strange if you set IP_PMTUDISC_DO. Suppose we have this situation: host A <-1500-> router B <-1432-> ... <-1500-> host Z We send a 1500-byte probe from A. Router B sends back `fragmentation needed' with maximum size 1432. Linux reports EMSGSIZE back to us, but when we read IP_MTU, we get 1500 again. OK: we send another probe with 1500, for old times' sake, but the write(2) fails with EMSGSIZE. At this point we give up and try binary search. The next size we try is 1038, but write(2) fails again, inexplicably. Subsequent binary search succeeds, so we end up with an MTU of 1037. This is too small for IPv6. Using IP_PMTUDISC_PROBE instead seems to prevent Linux from being hopeless at write(2) time. --- diff --git a/pathmtu/pathmtu.c b/pathmtu/pathmtu.c index 8dac7b11..e8861f70 100644 --- a/pathmtu/pathmtu.c +++ b/pathmtu/pathmtu.c @@ -623,7 +623,7 @@ static int linux_setup(void *stv, int sk, const struct param *pp) st->sk = sk; /* Turn on kernel path-MTU discovery and force DF on. */ - i = IP_PMTUDISC_DO; + i = IP_PMTUDISC_PROBE; if (setsockopt(st->sk, IPPROTO_IP, IP_MTU_DISCOVER, &i, sizeof(i))) return (-1);