+0100 From: Daniel Schall <tinc-devel at mon-clan.de> Date: Thu, 6 Jan 2011 17:00:35 +0100 Subject: [PATCH] Improved PMTU discovery diff --git a/lib/dropin.c b/lib/dropin.c index 52fb5b8..2b803b1 100644 --- a/lib/dropin.c +++ b/lib/dropin.c @@ -165,8 +165,8 @@ #endif =20 #ifdef HAVE_MINGW -int usleep(long usec) { - Sleep(usec / 1000); - return 0; -} +//int usleep(long usec) { +// Sleep(usec / 1000); +// return 0; +//} #endif diff --git a/lib/dropin.h b/lib/dropin.h index d5cf6d2..61326fe 100644 --- a/lib/dropin.h +++ b/lib/dropin.h @@ -42,7 +42,7 @@ #endif =20 #ifdef HAVE_MINGW -extern int usleep(long); +//extern int usleep(long); #endif =20 #endif /* __DROPIN_H__ */ diff --git a/src/net.c b/src/net.c index 08e3cad..9d170d0 100644 --- a/src/net.c +++ b/src/net.c @@ -280,6 +280,9 @@ int result, i; socklen_t len =3D sizeof(result); vpn_packet_t packet; + packet.flag_bits =3D 0; + packet.flags.compress =3D 1; + static int errors =3D 0; =20 /* check input from kernel */ diff --git a/src/net.h b/src/net.h index ab6bd41..7e05d09 100644 --- a/src/net.h +++ b/src/net.h @@ -79,11 +79,16 @@ typedef struct vpn_packet_t { length_t len; /* the actual number of bytes in the `data' field */ int priority; /* priority or TOS */ - struct { - uint32_t local:1; /* is this packet sent to a local interface? */ - uint32_t pmtud:1; /* is this packet used for PMTU discovery? */ - uint32_t unused:30; /* unused bits */ - } flags; + union { + struct { + uint32_t local:1; /* is this packet sent to a local interface? */ + uint32_t pmtud:1; /* is this packet used for PMTU discovery? */ + uint32_t pmtur:1; /* is this packet used for PMTU reply? */ + uint32_t compress:1; /* is this packet compressed? */ + uint32_t unused:28; /* unused bits */ + } flags; + uint32_t flag_bits; /* to easily zero out and access flag bits */ + }; uint32_t seqno; /* 32 bits sequence number (network byte order of course) */ uint8_t data[MAXSIZE]; } vpn_packet_t; diff --git a/src/net_packet.c b/src/net_packet.c index 5556326..4258599 100644 --- a/src/net_packet.c +++ b/src/net_packet.c @@ -72,7 +72,9 @@ =20 void send_mtu_probe(node_t *n) { vpn_packet_t packet; - memset(&packet.flags, 0, sizeof(packet.flags)); + packet.flag_bits =3D 0; + packet.flags.pmtud =3D 1; + int len, i; int timeout =3D 1; =09 @@ -120,21 +122,22 @@ timeout =3D pingtimeout; } =20 - for(i =3D 0; i < 3; i++) { + const int nbPackets =3D 3; + for(i =3D 0; i < nbPackets; i++) { if(n->maxmtu <=3D n->minmtu) len =3D n->maxmtu; else - len =3D n->minmtu + 1 + rand() % (n->maxmtu - n->minmtu); + len =3D n->minmtu + 1 + (n->maxmtu + 1 - n->minmtu) / (double) nbPackets * i; =20 if(len < 64) len =3D 64; =09 - memset(packet.data, 0, 14); - RAND_pseudo_bytes(packet.data + 14, len - 14); + //RAND_pseudo_bytes(packet.data, len); + memset(packet.data, 0x0, len); packet.len =3D len; packet.priority =3D 0; =20 - ifdebug(TRAFFIC) logger(LOG_INFO, "Sending MTU probe length %d to %s (%s)", len, n->name, n->hostname); + ifdebug(TRAFFIC) logger(LOG_INFO, "Sending MTU probe length %d to %s (%s) from interval [%d - %d]", len, n->name, n->hostname, n->minmtu, n->maxmtu); =20 send_udppacket(n, &packet); } @@ -147,24 +150,26 @@ event_add(n->mtuevent); } =20 -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); +void mtu_probe_h(node_t *n, vpn_packet_t *packet) { + length_t len =3D packet->len; + ifdebug(TRAFFIC) logger(LOG_INFO, "Got PMTU %s (length %d) from %s (%s)", (packet->flags.pmtur) ? "reply" : "probe", packet->len, n->name, n->hostname); =20 - if(!packet->data[0]) { - packet->data[0] =3D 1; - send_udppacket(n, packet); - } else { - if(n->mtuprobes > 30) { - if(n->minmtu) - n->mtuprobes =3D 30; - else - n->mtuprobes =3D 1; + if(n->mtuprobes > 30) { + if(n->minmtu) + n->mtuprobes =3D 30; + else + n->mtuprobes =3D 1; } + if(len > n->maxmtu) + len =3D n->maxmtu; + if(n->minmtu < len) + n->minmtu =3D len; =20 - if(len > n->maxmtu) - len =3D n->maxmtu; - if(n->minmtu < len) - n->minmtu =3D len; + if(!packet->flags.pmtur) { + /* PMTU Probe --> reply */ + + packet->flags.pmtur =3D 1; + send_udppacket(n, packet); } } =20 @@ -264,11 +269,12 @@ =20 /* Remove flags */ =20 - inpkt->len -=3D sizeof(inpkt->flags); + inpkt->flag_bits =3D ntohl(inpkt->flag_bits); + inpkt->len -=3D sizeof(inpkt->flag_bits); =20 /* Check packet length */ =20 - if(inpkt->len < sizeof(inpkt->seqno) + n->inmaclength) { + if(inpkt->len < sizeof(inpkt->flag_bits) + sizeof(inpkt->seqno) + n->inmaclength) { ifdebug(TRAFFIC) logger(LOG_DEBUG, "Got too short packet from %s (%s)", n->name, n->hostname); return; @@ -302,6 +308,7 @@ return; } =09 + outpkt->flag_bits =3D inpkt->flag_bits; outpkt->len =3D outlen + outpad; inpkt =3D outpkt; } @@ -346,9 +353,7 @@ =20 /* Decompress the packet */ =20 - length_t origlen =3D inpkt->len; - - if(n->incompression) { + if(n->incompression && inpkt->flags.compress) { outpkt =3D pkt[nextpkt++]; =20 if((outpkt->len =3D uncompress_packet(outpkt->data, inpkt->data, inpkt->len, n->incompression)) < 0) { @@ -357,22 +362,21 @@ return; } =20 + outpkt->flag_bits =3D inpkt->flag_bits; inpkt =3D outpkt; - - origlen -=3D MTU/64 + 20; } =20 inpkt->priority =3D 0; =20 - if(!inpkt->data[12] && !inpkt->data[13]) - mtu_probe_h(n, inpkt, origlen); + if(inpkt->flags.pmtud) + mtu_probe_h(n, inpkt); else receive_packet(n, inpkt); } =20 void receive_tcppacket(connection_t *c, char *buffer, int len) { vpn_packet_t outpkt; - memset(&outpkt.flags, 0, sizeof(outpkt.flags)); + outpkt.flag_bits =3D 0; =20 outpkt.len =3D len; if(c->options & OPTION_TCPONLY) @@ -420,10 +424,12 @@ return; } =20 - if(n->options & OPTION_PMTU_DISCOVERY && inpkt->len > n->minmtu && (inpkt->data[12] | inpkt->data[13])) { + /* Decide to send using UDP or TCP */ + + if(n->options & OPTION_PMTU_DISCOVERY && inpkt->len > n->minmtu && !origpkt->flags.pmtud) { ifdebug(TRAFFIC) logger(LOG_INFO, - "Packet for %s (%s) larger than minimum MTU, forwarding via %s", - n->name, n->hostname, n !=3D n->nexthop ? n->nexthop->name : "TCP"); + "Packet for %s (%s) larger than minimum MTU (=3D%d), forwarding via %s", + n->name, n->hostname, n->minmtu, n !=3D n->nexthop ? n->nexthop->name : "TCP"); =20 if(n !=3D n->nexthop) send_packet(n->nexthop, origpkt); @@ -438,7 +444,7 @@ =20 /* Compress the packet */ =20 - if(n->outcompression) { + if(n->outcompression && inpkt->flags.compress) { outpkt =3D pkt[nextpkt++]; =20 if((outpkt->len =3D compress_packet(outpkt->data, inpkt->data, inpkt->len, n->outcompression)) < 0) { @@ -447,7 +453,12 @@ return; } =20 - inpkt =3D outpkt; + if(outpkt->len < inpkt->len) { + outpkt->flag_bits =3D inpkt->flag_bits; + inpkt =3D outpkt; + }else{ + outpkt->flags.compress =3D 0; + } } =20 /* Add sequence number */ @@ -469,6 +480,7 @@ goto end; } =20 + outpkt->flag_bits =3D inpkt->flag_bits; outpkt->len =3D outlen + outpad; inpkt =3D outpkt; } @@ -483,7 +495,8 @@ =20 /* Add flags (not encrypted) */ =20 - inpkt->len +=3D sizeof(inpkt->flags); + inpkt->len +=3D sizeof(inpkt->flag_bits); + inpkt->flag_bits =3D htonl(inpkt->flag_bits); =20 /* Determine which socket we have to use */ =20 @@ -506,7 +519,7 @@ } #endif =20 - if(sendto(listen_socket[sock].udp, (char *) &inpkt->seqno, inpkt->len, 0, &(n->address.sa), SALEN(n->address.sa)) < 0 && !sockwouldblock(sockerrno)) { + if(sendto(listen_socket[sock].udp, (char *) &inpkt->flags, inpkt->len, 0, &(n->address.sa), SALEN(n->address.sa)) < 0 && !sockwouldblock(sockerrno)) { if(sockmsgsize(sockerrno)) { if(n->maxmtu >=3D origlen) n->maxmtu =3D origlen - 1; diff --git a/src/process.c b/src/process.c index 0007943..073f5c0 100644 --- a/src/process.c +++ b/src/process.c @@ -494,10 +494,10 @@ saved_debug_level =3D -1; } else { logger(LOG_NOTICE, - "Temporarily setting debug level to 5. Kill me with SIGINT again to go back to level %d.", - debug_level); + "Temporarily setting debug level to %d. Kill me with SIGINT again to go back to level %d.", + DEBUG_SCARY_THINGS, debug_level); saved_debug_level =3D debug_level; - debug_level =3D 5; + debug_level =3D DEBUG_SCARY_THINGS; } } =20 diff --git a/src/protocol.h b/src/protocol.h index 2aed26d..251e847 100644 --- a/src/protocol.h +++ b/src/protocol.h @@ -25,7 +25,7 @@ incompatible version have different protocols. */ =20 -#define PROT_CURRENT 17 +#define PROT_CURRENT 18 =20 /* Silly Windows */ =20 diff --git a/src/protocol_key.c b/src/protocol_key.c index e2e4be5..1dc694d 100644 --- a/src/protocol_key.c +++ b/src/protocol_key.c @@ -310,8 +310,16 @@ update_node_udp(from, &sa); } =20 - if(from->options & OPTION_PMTU_DISCOVERY && !from->mtuevent) - send_mtu_probe(from); - + if(from->options & OPTION_PMTU_DISCOVERY && !from->mtuevent) { + //if(strcmp(from->name, myself->name) > 0) { + // // delay mtu discovery to prevent synchronous bursts + // from->mtuevent =3D new_event(); + // from->mtuevent->handler =3D (event_handler_t)send_mtu_probe; + // from->mtuevent->data =3D from; + // from->mtuevent->time =3D now + 1; + // event_add(from->mtuevent); + //}else + send_mtu_probe(from); + } return true; } diff --git a/src/route.c b/src/route.c index 1caf738..b1a6389 100644 --- a/src/route.c +++ b/src/route.c @@ -317,6 +317,7 @@ static void fragment_ipv4_packet(node_t *dest, vpn_packet_t *packet) { struct ip ip; vpn_packet_t fragment; + fragment.flag_bits =3D packet->flag_bits; int len, maxlen, todo; uint8_t *offset; uint16_t ip_off, origf; ------=_NextPart_000_0001_01CBADF1.BD635B80--