From d5a151a06788c28ac1c50398c6e571d484774f47 Mon Sep 17 00:00:00 2001 From: Mike Perry Date: Tue, 21 Feb 2017 21:28:00 -0500 Subject: Bug 17592: Clean up connection timeout logic. This unifies CircuitIdleTimeout and PredictedCircsRelevanceTime into a single option, and randomizes it. It also gives us control over the default value as well as relay-to-relay connection lifespan through the consensus. Conflicts: src/or/circuituse.c src/or/config.c src/or/main.c src/test/testing_common.c --- src/or/circuitlist.c | 41 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 41 insertions(+) (limited to 'src/or/circuitlist.c') diff --git a/src/or/circuitlist.c b/src/or/circuitlist.c index 54a7db9dbf..1a3b7bb288 100644 --- a/src/or/circuitlist.c +++ b/src/or/circuitlist.c @@ -78,6 +78,7 @@ #include "rephist.h" #include "routerlist.h" #include "routerset.h" +#include "channelpadding.h" #include "ht.h" @@ -814,6 +815,11 @@ init_circuit_base(circuit_t *circ) circ->global_circuitlist_idx = smartlist_len(circuit_get_global_list()) - 1; } +/** If we haven't yet decided on a good timeout value for circuit + * building, we close idle circuits aggressively so we can get more + * data points. */ +#define IDLE_TIMEOUT_WHILE_LEARNING (1*60) + /** Allocate space for a new circuit, initializing with p_circ_id * and p_conn. Add it to the global circuit list. */ @@ -841,6 +847,41 @@ origin_circuit_new(void) circuit_build_times_update_last_circ(get_circuit_build_times_mutable()); + if (! circuit_build_times_disabled(get_options()) && + circuit_build_times_needs_circuits(get_circuit_build_times())) { + /* Circuits should be shorter lived if we need more of them + * for learning a good build timeout */ + circ->circuit_idle_timeout = IDLE_TIMEOUT_WHILE_LEARNING; + } else { + // This should always be larger than the current port prediction time + // remaining, or else we'll end up with the case where a circuit times out + // and another one is built, effectively doubling the timeout window. + // + // We also randomize it by up to 5% more (ie 5% of 0 to 3600 seconds, + // depending on how much circuit prediction time is remaining) so that + // we don't close a bunch of unused circuits all at the same time. + int prediction_time_remaining = + predicted_ports_prediction_time_remaining(time(NULL)); + circ->circuit_idle_timeout = prediction_time_remaining+1+ + crypto_rand_int(1+prediction_time_remaining/20); + + if (circ->circuit_idle_timeout <= 0) { + log_warn(LD_BUG, + "Circuit chose a negative idle timeout of %d based on " + "%d seconds of predictive building remaining.", + circ->circuit_idle_timeout, + prediction_time_remaining); + circ->circuit_idle_timeout = IDLE_TIMEOUT_WHILE_LEARNING; + } + + log_info(LD_CIRC, + "Circuit " U64_FORMAT " chose an idle timeout of %d based on " + "%d seconds of predictive building remaining.", + U64_PRINTF_ARG(circ->global_identifier), + circ->circuit_idle_timeout, + prediction_time_remaining); + } + return circ; } -- cgit v1.2.3-54-g00ecf