Detect increases in PMTU.
authorGuus Sliepen <guus@tinc-vpn.org>
Thu, 31 Jan 2013 14:58:33 +0000 (15:58 +0100)
committerGuus Sliepen <guus@tinc-vpn.org>
Thu, 31 Jan 2013 14:58:33 +0000 (15:58 +0100)
Tinc never restarts PMTU discovery unless a node becomes unreachable. However,
it can be that the PMTU was very low during the initial discovery, but has
increased later. To detect this, tinc now tries to send an extra packet every
PingInterval, with a size slightly higher than the currently known PMTU. If
this packet is succesfully received back, we partially restart PMTU discovery
to find out the new maximum.

src/net_packet.c

index 2780f5184e410ba81d5f17297f8ffdc0773a9012..c2092480584b90c91cd0ea431bd3ee6ec9ec1aab 100644 (file)
@@ -70,11 +70,15 @@ bool localdiscovery = false;
    mtuprobes ==    32: send 1 burst, sleep pingtimeout second
    mtuprobes ==    33: no response from other side, restart PMTU discovery process
 
-   Probes are sent in batches of three, with random sizes between the lower and
-   upper boundaries for the MTU thus far discovered.
+   Probes are sent in batches of at least three, with random sizes between the
+   lower and upper boundaries for the MTU thus far discovered.
 
-   In case local discovery is enabled, a fourth packet is added to each batch,
+   After the initial discovery, a fourth packet is added to each batch with a
+   size larger than the currently known PMTU, to test if the PMTU has increased.
+
+   In case local discovery is enabled, another packet is added to each batch,
    which will be broadcast to the local network.
+
 */
 
 void send_mtu_probe(node_t *n) {
@@ -126,11 +130,16 @@ void send_mtu_probe(node_t *n) {
                timeout = pingtimeout;
        }
 
-       for(i = 0; i < 3 + localdiscovery; i++) {
-               if(n->maxmtu <= n->minmtu)
+       for(i = 0; i < 4 + localdiscovery; i++) {
+               if(i == 0) {
+                       if(n->mtuprobes < 30 || n->maxmtu + 8 >= MTU)
+                               continue;
+                       len = n->maxmtu + 8;
+               } else if(n->maxmtu <= n->minmtu) {
                        len = n->maxmtu;
-               else
+               } else {
                        len = n->minmtu + 1 + rand() % (n->maxmtu - n->minmtu);
+               }
 
                if(len < 64)
                        len = 64;
@@ -138,7 +147,7 @@ void send_mtu_probe(node_t *n) {
                memset(packet.data, 0, 14);
                RAND_pseudo_bytes(packet.data + 14, len - 14);
                packet.len = len;
-               if(i >= 3 && n->mtuprobes <= 10)
+               if(i >= 4 && n->mtuprobes <= 10)
                        packet.priority = -1;
                else
                        packet.priority = 0;
@@ -164,6 +173,13 @@ void mtu_probe_h(node_t *n, vpn_packet_t *packet, length_t len) {
                send_udppacket(n, packet);
        } else {
                if(n->mtuprobes > 30) {
+                       if (len == n->maxmtu + 8) {
+                               ifdebug(TRAFFIC) logger(LOG_INFO, "Increase in PMTU to %s (%s) detected, restarting PMTU discovery", n->name, n->hostname);
+                               n->maxmtu = MTU;
+                               n->mtuprobes = 10;
+                               return;
+                       }
+
                        if(n->minmtu)
                                n->mtuprobes = 30;
                        else