diff --git a/include/n2n_define.h b/include/n2n_define.h index b71d748..252b873 100644 --- a/include/n2n_define.h +++ b/include/n2n_define.h @@ -48,6 +48,9 @@ #define SWEEP_TIME 30 /* sec, indicates the value after which we have to sort the hash list of supernodes in edges * and when we send out packets to query selection-relevant informations from supernodes. */ +#define NUMBER_SN_PINGS_INITIAL 15 /* number of supernodes to concurrently ping during bootstrap and immediately afterwards */ +#define NUMBER_SN_PINGS_REGULAR 5 /* number of supernodes to concurrently ping during regular edge operation */ + /* Timeouts used in re_register_and_purge_supernodes. LAST_SEEN_SN_ACTIVE and LAST_SEEN_SN_INACTIVE * values should be at least 3*SOCKET_TIMEOUT_INTERVAL_SECS apart. */ #define LAST_SEEN_SN_ACTIVE 20 /* sec, indicates supernodes that are proven to be active */ diff --git a/include/n2n_typedefs.h b/include/n2n_typedefs.h index 5b8fff2..2113e0f 100644 --- a/include/n2n_typedefs.h +++ b/include/n2n_typedefs.h @@ -601,6 +601,7 @@ typedef struct n2n_edge_conf { n2n_auth_t auth; filter_rule_t *network_traffic_filter_rules; int metric; /**< Network interface metric (Windows only). */ + uint8_t number_max_sn_pings; /**< Number of maximum concurrently allowed supernode pings. */ } n2n_edge_conf_t; diff --git a/src/edge.c b/src/edge.c index e61b88c..f52c5d3 100644 --- a/src/edge.c +++ b/src/edge.c @@ -962,6 +962,8 @@ int main (int argc, char* argv[]) { if(runlevel == 0) { /* PING to all known supernodes */ last_action = now_time; eee->sn_pong = 0; + // (re-)initialize the number of max concurrent pings (decreases by calling send_query_peer) + eee->conf.number_max_sn_pings = NUMBER_SN_PINGS_INITIAL; send_query_peer(eee, null_mac); traceEvent(TRACE_NORMAL, "Send PING to supernodes."); runlevel++; @@ -975,8 +977,7 @@ int main (int argc, char* argv[]) { eee->curr_sn = eee->conf.supernodes; traceEvent(TRACE_NORMAL, "Received first PONG from supernode [%s].", eee->curr_sn->ip_addr); runlevel++; - } - if(last_action <= (now_time - BOOTSTRAP_TIMEOUT)) { + } else if(last_action <= (now_time - BOOTSTRAP_TIMEOUT)) { // timeout runlevel--; // skip waiting for answer to direcly go to send PING again @@ -1017,8 +1018,7 @@ int main (int argc, char* argv[]) { runlevel++; traceEvent(TRACE_NORMAL, "Received REGISTER_SUPER_ACK from supernode for IP address asignment."); // it should be from curr_sn, but we can't determine definitely here, so no details to output - } - if(last_action <= (now_time - BOOTSTRAP_TIMEOUT)) { + } else if(last_action <= (now_time - BOOTSTRAP_TIMEOUT)) { // timeout, so try next supernode if(eee->curr_sn->hh.next) eee->curr_sn = eee->curr_sn->hh.next; @@ -1065,6 +1065,11 @@ int main (int argc, char* argv[]) { } seek_answer = 1; } + // allow a higher number of pings for first regular round of ping + // to quicker get an inital 'supernode selection criterion overview' + eee->conf.number_max_sn_pings = NUMBER_SN_PINGS_INITIAL; + // do not immediately ping again, allow some time + eee->last_sweep = now_time - SWEEP_TIME + 2 * BOOTSTRAP_TIMEOUT; eee->sn_wait = 1; eee->last_register_req = 0; eee->last_sup = 0; /* to allow gratuitous arp packet after regular REGISTER_SUPER_ACK */ diff --git a/src/edge_utils.c b/src/edge_utils.c index 52b44ca..306e0f4 100644 --- a/src/edge_utils.c +++ b/src/edge_utils.c @@ -770,6 +770,10 @@ void send_query_peer (n2n_edge_t * eee, n2n_QUERY_PEER_t query = {{0}}; struct peer_info *peer, *tmp; uint8_t tmp_pkt[N2N_PKT_BUF_SIZE]; + int n_o_pings = 0; + int n_o_top_sn = 0; + int n_o_rest_sn = 0; + int n_o_skip_sn = 0; cmn.ttl = N2N_DEFAULT_TTL; cmn.pc = n2n_query_peer; @@ -806,7 +810,32 @@ void send_query_peer (n2n_edge_t * eee, time_stamp ()); } + n_o_pings = eee->conf.number_max_sn_pings; + eee->conf.number_max_sn_pings = NUMBER_SN_PINGS_REGULAR; + + // ping the 'floor(n/2)' top supernodes and 'ceiling(n/2)' of the remaining + n_o_top_sn = n_o_pings >> 1; + n_o_rest_sn = (n_o_pings + 1) >> 1; + + // skip a random number of supernodes between top and remaining + n_o_skip_sn = HASH_COUNT(eee->conf.supernodes) - n_o_pings; + n_o_skip_sn = (n_o_skip_sn < 0) ? 0 : n2n_rand_sqr(n_o_skip_sn); + HASH_ITER(hh, eee->conf.supernodes, peer, tmp) { + if(n_o_top_sn) { + n_o_top_sn--; + // fall through (send to top supernode) + } else if(n_o_skip_sn) { + n_o_skip_sn--; + // skip (do not send) + continue; + } else if(n_o_rest_sn) { + n_o_rest_sn--; + // fall through (send to remaining supernode) + } else { + // done with the remaining (do not send anymore) + break; + } sendto_sock(eee->udp_sock, pktbuf, idx, &(peer->sock)); } }