+ if(n->received > n->prev_received)
+ n->packetloss = 1.0 - (n->received - n->prev_received) / (float)(n->received_seqno - n->prev_received_seqno);
+ else
+ n->packetloss = n->received_seqno <= n->prev_received_seqno;
+
+ n->prev_received_seqno = n->received_seqno;
+ n->prev_received = n->received;
+
+end:
+ timeout_set(&n->mtutimeout, &(struct timeval){timeout, rand() % 100000});
+}
+
+void send_mtu_probe(node_t *n) {
+ timeout_add(&n->mtutimeout, send_mtu_probe_handler, n, &(struct timeval){1, 0});
+ send_mtu_probe_handler(n);
+}
+
+static void mtu_probe_h(node_t *n, vpn_packet_t *packet, uint16_t len) {
+ logger(DEBUG_TRAFFIC, LOG_INFO, "Got MTU probe length %d from %s (%s)", packet->len, n->name, n->hostname);
+
+ if(!packet->data[0]) {
+ /* It's a probe request, send back a reply */
+
+ packet->data[0] = 1;
+
+ /* Temporarily set udp_confirmed, so that the reply is sent
+ back exactly the way it came in. */
+
+ bool udp_confirmed = n->status.udp_confirmed;
+ n->status.udp_confirmed = true;
+ send_udppacket(n, packet);
+ n->status.udp_confirmed = udp_confirmed;
+ } else {
+ /* It's a valid reply: now we know bidirectional communication
+ is possible using the address and socket that the reply
+ packet used. */
+
+ n->status.udp_confirmed = true;
+
+ /* If we haven't established the PMTU yet, restart the discovery process. */
+
+ if(n->mtuprobes > 30) {
+ if (len == n->maxmtu + 8) {
+ logger(DEBUG_TRAFFIC, 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
+ n->mtuprobes = 1;