From 3c67735720904319d5cd2c1b90303729183b0981 Mon Sep 17 00:00:00 2001 From: thorkill Date: Thu, 23 Jul 2015 17:58:39 +0200 Subject: [PATCH] Make autoconnect faster When AutoConnect is enabled tinc tries to connect to other nodes picking them at random. This may be sane default behavior but it may take ages if only few nodes have defined Address in thier config. Proposed solution to this problem: - Filter out nodes without known address in periodic_handler I have added new node->status.has_known_address bool - On update_node_udp() update this flag --- src/net.c | 37 +++++++++++++++++++++++-------------- src/net_setup.c | 3 +++ src/node.c | 5 ++++- src/node.h | 4 +++- 4 files changed, 33 insertions(+), 16 deletions(-) diff --git a/src/net.c b/src/net.c index 1167b908..d1c3569a 100644 --- a/src/net.c +++ b/src/net.c @@ -209,15 +209,14 @@ static void periodic_handler(void *data) { and we are not already trying to make one, create an outgoing connection to this node. */ - int r = rand() % node_tree->count; - int i = 0; + splay_tree_t *tmp_node_tree; + + tmp_node_tree = splay_alloc_tree((splay_compare_t) node_compare, NULL); for splay_each(node_t, n, node_tree) { - if(i++ != r) - continue; - if(n->connection) - break; + if(!n->status.has_known_address || n->connection) + continue; bool found = false; @@ -227,16 +226,26 @@ static void periodic_handler(void *data) { break; } } - - if(!found) { - logger(DEBUG_CONNECTIONS, LOG_INFO, "Autoconnecting to %s", n->name); - outgoing_t *outgoing = xzalloc(sizeof *outgoing); - outgoing->name = xstrdup(n->name); - list_insert_tail(outgoing_list, outgoing); - setup_outgoing_connection(outgoing); + if (!found) + splay_insert(tmp_node_tree, n); } - break; + + int r = rand() % tmp_node_tree->count; + int i = 0; + + for splay_each(node_t, n, tmp_node_tree) { + + if(i++ != r) + continue; + + + logger(DEBUG_CONNECTIONS, LOG_INFO, "Autoconnecting to %s", n->name); + outgoing_t *outgoing = xzalloc(sizeof *outgoing); + outgoing->name = xstrdup(n->name); + list_insert_tail(outgoing_list, outgoing); + setup_outgoing_connection(outgoing); } + splay_delete_tree(tmp_node_tree); } else if(nc > 3) { /* Too many active connections, try to remove one. Choose a random outgoing connection to a node diff --git a/src/net_setup.c b/src/net_setup.c index 09580739..63853de5 100644 --- a/src/net_setup.c +++ b/src/net_setup.c @@ -398,6 +398,9 @@ void load_all_subnets(void) { } } + if (lookup_config(config_tree, "Address")) + n->status.has_known_address = true; + exit_configuration(&config_tree); } diff --git a/src/node.c b/src/node.c index e3fbeeda..9597aaf8 100644 --- a/src/node.c +++ b/src/node.c @@ -39,7 +39,7 @@ static hash_t *node_id_cache; node_t *myself; -static int node_compare(const node_t *a, const node_t *b) { +int node_compare(const node_t *a, const node_t *b) { return strcmp(a->name, b->name); } @@ -175,6 +175,9 @@ void update_node_udp(node_t *n, const sockaddr_t *sa) { free(n->hostname); n->hostname = sockaddr2hostname(&n->address); logger(DEBUG_PROTOCOL, LOG_DEBUG, "UDP address of %s set to %s", n->name, n->hostname); + n->status.has_known_address = true; + } else { + n->status.has_known_address = false; } /* invalidate UDP information - note that this is a security feature as well to make sure diff --git a/src/node.h b/src/node.h index 02e2a6d6..73170226 100644 --- a/src/node.h +++ b/src/node.h @@ -40,7 +40,8 @@ typedef struct node_status_t { unsigned int send_locally:1; /* 1 if the next UDP packet should be sent on the local network */ unsigned int udppacket:1; /* 1 if the most recently received packet was UDP */ unsigned int validkey_in; /* 1 if we have sent a valid key to him */ - unsigned int unused:22; + unsigned int has_known_address; /* 1 if this node has Address in node's config */ + unsigned int unused:21; } node_status_t; typedef struct node_t { @@ -116,6 +117,7 @@ extern splay_tree_t *node_tree; extern void init_nodes(void); extern void exit_nodes(void); +extern int node_compare(const node_t *, const node_t *); extern node_t *new_node(void) __attribute__ ((__malloc__)); extern void free_node(node_t *); extern void node_add(node_t *);