- send_udppacket(n, &packet);
- }
-
- 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(&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, length_t len) {
- if(!packet->data[0]) {
- logger(DEBUG_TRAFFIC, LOG_INFO, "Got MTU probe request %d from %s (%s)", packet->len, n->name, n->hostname);
-
- /* It's a probe request, send back a reply */
-
- /* Type 2 probe replies were introduced in protocol 17.3 */
- if ((n->options >> 24) == 3) {
- uint8_t* data = packet->data;
- *data++ = 2;
- uint16_t len16 = htons(len); memcpy(data, &len16, 2); data += 2;
- struct timeval now;
- gettimeofday(&now, NULL);
- uint32_t sec = htonl(now.tv_sec); memcpy(data, &sec, 4); data += 4;
- uint32_t usec = htonl(now.tv_usec); memcpy(data, &usec, 4); data += 4;
- packet->len = data - packet->data;
- } else {
- /* Legacy protocol: n won't understand type 2 probe replies. */
- 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 {
- length_t probelen = len;
- if (packet->data[0] == 2) {
- if (len < 3)
- logger(DEBUG_TRAFFIC, LOG_WARNING, "Received invalid (too short) MTU probe reply from %s (%s)", n->name, n->hostname);
- else {
- uint16_t probelen16; memcpy(&probelen16, packet->data + 1, 2); probelen = ntohs(probelen16);
- }
- }
- logger(DEBUG_TRAFFIC, LOG_INFO, "Got type %d MTU probe reply %d from %s (%s)", packet->data[0], probelen, n->name, n->hostname);
-
- /* 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 (probelen == 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;
- }
-
- /* If applicable, raise the minimum supported MTU */
-
- if(probelen > n->maxmtu)
- probelen = n->maxmtu;
- if(n->minmtu < probelen)
- n->minmtu = probelen;
-
- /* Calculate RTT and bandwidth.
- The RTT is the time between the MTU probe burst was sent and the first
- reply is received. The bandwidth is measured using the time between the
- arrival of the first and third probe reply (or type 2 probe requests).
- */
-
- struct timeval now, diff;
- gettimeofday(&now, NULL);
- timersub(&now, &n->probe_time, &diff);
-
- struct timeval probe_timestamp = now;
- if (packet->data[0] == 2 && packet->len >= 11) {
- uint32_t sec; memcpy(&sec, packet->data + 3, 4);
- uint32_t usec; memcpy(&usec, packet->data + 7, 4);
- probe_timestamp.tv_sec = ntohl(sec);
- probe_timestamp.tv_usec = ntohl(usec);
- }
-
- n->probe_counter++;
-
- if(n->probe_counter == 1) {
- n->rtt = diff.tv_sec + diff.tv_usec * 1e-6;
- n->probe_time = probe_timestamp;
- } else if(n->probe_counter == 3) {
- struct timeval probe_timestamp_diff;
- timersub(&probe_timestamp, &n->probe_time, &probe_timestamp_diff);
- n->bandwidth = 2.0 * probelen / (probe_timestamp_diff.tv_sec + probe_timestamp_diff.tv_usec * 1e-6);
- logger(DEBUG_TRAFFIC, LOG_DEBUG, "%s (%s) RTT %.2f ms, burst bandwidth %.3f Mbit/s, rx packet loss %.2f %%", n->name, n->hostname, n->rtt * 1e3, n->bandwidth * 8e-6, n->packetloss * 1e2);
- }
- }
-}
-
-static length_t compress_packet(uint8_t *dest, const uint8_t *source, length_t len, int level) {
- if(level == 0) {
- memcpy(dest, source, len);
- return len;
- } else if(level == 10) {
-#ifdef HAVE_LZO
- lzo_uint lzolen = MAXSIZE;
- lzo1x_1_compress(source, len, dest, &lzolen, lzo_wrkmem);
- return lzolen;
-#else
- return -1;
-#endif
- } else if(level < 10) {
-#ifdef HAVE_ZLIB
- unsigned long destlen = MAXSIZE;
- if(compress2(dest, &destlen, source, len, level) == Z_OK)
- return destlen;
- else
-#endif
- return -1;