void mtu_probe_h(node_t *n, vpn_packet_t *packet, length_t len) { ifdebug(TRAFFIC) logger(LOG_INFO, "Got MTU probe length %d from %s (%s)", packet->len, n->name, n->hostname); if(!packet->data[0]) { packet->data[0] = 1; 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 n->mtuprobes = 1; } if(len > n->maxmtu) len = n->maxmtu; if(n->minmtu < len) n->minmtu = len; } }
void send_mtu_probe(node_t *n) { vpn_packet_t packet; int len, i; int timeout = 1; n->mtuprobes++; n->mtuevent = NULL; if(!n->status.reachable || !n->status.validkey) { ifdebug(TRAFFIC) logger(LOG_INFO, "Trying to send MTU probe to unreachable or rekeying node %s (%s)", n->name, n->hostname); n->mtuprobes = 0; return; } if(n->mtuprobes > 32) { if(!n->minmtu) { n->mtuprobes = 31; timeout = pinginterval; goto end; } ifdebug(TRAFFIC) logger(LOG_INFO, "%s (%s) did not respond to UDP ping, restarting PMTU discovery", n->name, n->hostname); n->mtuprobes = 1; n->minmtu = 0; n->maxmtu = MTU; } if(n->mtuprobes >= 10 && n->mtuprobes < 32 && !n->minmtu) { ifdebug(TRAFFIC) logger(LOG_INFO, "No response to MTU probes from %s (%s)", n->name, n->hostname); n->mtuprobes = 31; } if(n->mtuprobes == 30 || (n->mtuprobes < 30 && n->minmtu >= n->maxmtu)) { if(n->minmtu > n->maxmtu) n->minmtu = n->maxmtu; else n->maxmtu = n->minmtu; n->mtu = n->minmtu; ifdebug(TRAFFIC) logger(LOG_INFO, "Fixing MTU of %s (%s) to %d after %d probes", n->name, n->hostname, n->mtu, n->mtuprobes); n->mtuprobes = 31; } if(n->mtuprobes == 31) { timeout = pinginterval; goto end; } else if(n->mtuprobes == 32) { timeout = pingtimeout; } 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 { len = n->minmtu + 1 + rand() % (n->maxmtu - n->minmtu); } if(len < 64) len = 64; memset(packet.data, 0, 14); RAND_pseudo_bytes(packet.data + 14, len - 14); packet.len = len; if(i >= 4 && n->mtuprobes <= 10) packet.priority = -1; else packet.priority = 0; ifdebug(TRAFFIC) logger(LOG_INFO, "Sending MTU probe length %d to %s (%s)", len, n->name, n->hostname); send_udppacket(n, &packet); } end: n->mtuevent = new_event(); n->mtuevent->handler = (event_handler_t)send_mtu_probe; n->mtuevent->data = n; n->mtuevent->time = now.tv_sec + timeout; event_add(n->mtuevent); }
static void send_mtu_probe_handler(event_loop_t *loop, void *data) { meshlink_handle_t *mesh = loop->data; node_t *n = data; int timeout = 1; n->mtuprobes++; if(!n->status.reachable || !n->status.validkey) { logger(mesh, MESHLINK_INFO, "Trying to send MTU probe to unreachable or rekeying node %s (%s)", n->name, n->hostname); n->mtuprobes = 0; return; } if(n->mtuprobes > 32) { if(!n->minmtu) { n->mtuprobes = 31; timeout = mesh->pinginterval; goto end; } logger(mesh, MESHLINK_INFO, "%s (%s) did not respond to UDP ping, restarting PMTU discovery", n->name, n->hostname); n->status.udp_confirmed = false; n->mtuprobes = 1; n->minmtu = 0; n->maxmtu = MTU; } if(n->mtuprobes >= 10 && n->mtuprobes < 32 && !n->minmtu) { logger(mesh, MESHLINK_INFO, "No response to MTU probes from %s (%s)", n->name, n->hostname); n->mtuprobes = 31; } if(n->mtuprobes == 30 || (n->mtuprobes < 30 && n->minmtu >= n->maxmtu)) { if(n->minmtu > n->maxmtu) n->minmtu = n->maxmtu; else n->maxmtu = n->minmtu; n->mtu = n->minmtu; logger(mesh, MESHLINK_INFO, "Fixing MTU of %s (%s) to %d after %d probes", n->name, n->hostname, n->mtu, n->mtuprobes); n->mtuprobes = 31; } if(n->mtuprobes == 31) { timeout = mesh->pinginterval; goto end; } else if(n->mtuprobes == 32) { timeout = mesh->pingtimeout; } for(int i = 0; i < 4 + mesh->localdiscovery; i++) { int len; 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 { len = n->minmtu + 1 + rand() % (n->maxmtu - n->minmtu); } if(len < 64) len = 64; vpn_packet_t packet; packet.probe = true; memset(packet.data, 0, 14); randomize(packet.data + 14, len - 14); packet.len = len; n->status.broadcast = i >= 4 && n->mtuprobes <= 10 && n->prevedge; logger(mesh, MESHLINK_DEBUG, "Sending MTU probe length %d to %s (%s)", len, n->name, n->hostname); send_udppacket(mesh, n, &packet); } n->status.broadcast = false; n->probe_counter = 0; gettimeofday(&n->probe_time, NULL); /* Calculate the packet loss of incoming traffic by comparing the rate of packets received to the rate with which the sequence number has increased. */ 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(&mesh->loop, &n->mtutimeout, &(struct timeval){timeout, rand() % 100000});