Configure minimum reconnect timeouts.
authorTomislav Čohar <tomislav.cohar@gmail.com>
Tue, 26 Aug 2014 22:25:12 +0000 (00:25 +0200)
committerGuus Sliepen <guus@tinc-vpn.org>
Wed, 27 Aug 2014 08:42:17 +0000 (10:42 +0200)
Enable the configuration of minimum reconnect timeout via a
configuration directive "MinTimeout". This functionality is missing in
the default tinc stable distribution. The minimum timeout is, in code,
set to 0 seconds. This patch makes it configurable.

You might ask yourself why is that needed at all ?

Well, we've been using tinc with success for quite some time in a cross DC
setup. Tinc is used to create a virtual network switch and to connect our
distributed database nodes into a virtual local network. Our database nodes
exchange information, synchronize and do failover over the created
tinc-backed network.

Every now and then, when a node has a physical networking issue and is
unreachable by some or all neighboring nodes, tinc will relay traffic over
reachable neighboring nodes and thus save our cluster. But, sometimes,
especially when BGP route changes take place, minor outages of physical
connectivity towards some nodes may cause tinc to become as reliable as
packet-loss is :).

Tinc is fast, it can and does re-establish a lost connection in a jiffy,
but it cannot detect the reason for the loss of the connection. A
re-established connection might last for a few seconds (ping timeout) to
get lost again just because the packet loss is huge at that time. Then it
reconnects again and the story repeats itself.

This process keeps repeating until the physical network stabilizes. Packet
loss on a physical link means disaster in a database replication scenario.
In such cases it is better for tinc to remain disconnected from the
unreachable/destabilized nodes for some time and relay traffic over the
reachable (unaffected) nodes then to use an unreliable route.

This patch enables us to slow down the re-connection process and eliminate
application level issues we had.

src/conf.h
src/net_setup.c
src/net_socket.c

index 3a040c7b74cdb9b5502210e764b59d6e13ecc059..59c081c107a96b78e1f2e02440ba38bef0fa8a17 100644 (file)
@@ -38,6 +38,7 @@ extern avl_tree_t *config_tree;
 extern int pinginterval;
 extern int pingtimeout;
 extern int maxtimeout;
+extern int mintimeout;
 extern bool bypass_security;
 extern char *confbase;
 extern char *netname;
index b11744354a438305d62048ad4da8250549f23f95..a00a32109d9a3080c0a8ae6b13f5fa9151315c2a 100644 (file)
@@ -553,6 +553,18 @@ static bool setup_myself(void) {
        } else
                maxtimeout = 900;
 
+       if(get_config_int(lookup_config(config_tree, "MinTimeout"), &mintimeout)) {
+                       if(mintimeout < 0) {
+                               logger(LOG_ERR, "Bogus minimum timeout!");
+                               return false;
+                       }
+                       if(mintimeout > maxtimeout) {
+                               logger(LOG_WARNING, "Minimum timeout (%d s) cannot be larger than maximum timeout (%d s). Correcting !", mintimeout, maxtimeout );
+                               mintimeout=maxtimeout;
+                       }
+               } else
+                       mintimeout = 0;
+
        if(get_config_int(lookup_config(config_tree, "UDPRcvBuf"), &udp_rcvbuf)) {
                if(udp_rcvbuf <= 0) {
                        logger(LOG_ERR, "UDPRcvBuf cannot be negative!");
index 9a67bb3cebb63e1c0529c09fc50f21c6f83e5094..948ce0112e9953eeb20a9c4d6054a4bf64aed25f 100644 (file)
@@ -40,6 +40,7 @@
 #endif
 
 int addressfamily = AF_UNSPEC;
+int mintimeout = 0;
 int maxtimeout = 900;
 int seconds_till_retry = 5;
 int udp_rcvbuf = 0;
@@ -273,6 +274,9 @@ int setup_vpn_in_socket(const sockaddr_t *sa) {
 void retry_outgoing(outgoing_t *outgoing) {
        outgoing->timeout += 5;
 
+       if(outgoing->timeout < mintimeout)
+               outgoing->timeout = mintimeout;
+
        if(outgoing->timeout > maxtimeout)
                outgoing->timeout = maxtimeout;