Fine-tune the MTU discovery multiplier for the maxmtu < MTU case.
authorEtienne Dechamps <etienne@edechamps.fr>
Wed, 31 Dec 2014 16:21:08 +0000 (16:21 +0000)
committerEtienne Dechamps <etienne@edechamps.fr>
Fri, 2 Jan 2015 09:55:54 +0000 (09:55 +0000)
The original multiplier constant for the MTU discovery algorithm, 0.97,
assumes a somewhat pessmistic scenario where we don't get any help from
the OS - i.e. maxmtu never changes. This can happen if IP_MTU is not
usable and the OS doesn't reject overly large packets.

However, in most systems the OS will, in fact, contribute to the MTU
discovery process. In these situations, an actual MTU equal to maxmtu
is quite likely (as opposed to the maxmtu = 1518 case where that is
highly unlikely, unless the physical network supports jumbo frames).
It therefore makes sense to use a multiplier of 1 - that will make the
first probe length equal to maxmtu.

The best results are obtained if the OS supports the getsockopt(IP_MTU)
call, and its result is accurate. In that case, tinc will typically fix
the MTU after one single probe(!), like so:

    Using system-provided maximum tinc MTU for foobar (1.2.3.4 port 655): 1442
    Sending UDP probe length 1442 to foobar (1.2.3.4 port 655)
    Got type 2 UDP probe reply 1442 from foobar (1.2.3.4 port 655)
    Fixing MTU of foobar (1.2.3.4 port 655) to 1442 after 1 probes

src/net_packet.c

index 34bdd26..84d4915 100644 (file)
@@ -998,8 +998,11 @@ static void try_mtu(node_t *n) {
                /* This magic value was determined using math simulations.
                   It will result in a 1329-byte first probe, followed (if there was a reply) by a 1407-byte probe.
                   Since 1407 is just below the range of tinc MTUs over typical networks,
-                  this fine-tuning allows tinc to cover a lot of ground very quickly. */
-               const float multiplier = 0.97;
+                  this fine-tuning allows tinc to cover a lot of ground very quickly.
+                  This fine-tuning is only valid for maxmtu = MTU; if maxmtu is smaller,
+                  then it's better to use a multiplier of 1. Indeed, this leads to an interesting scenario
+                  if choose_initial_maxmtu() returns the actual MTU value - it will get confirmed with one single probe. */
+               const float multiplier = (n->maxmtu == MTU) ? 0.97 : 1;
 
                const float cycle_position = probes_per_cycle - (n->mtuprobes % probes_per_cycle) - 1;
                const length_t minmtu = MAX(n->minmtu, 512);