diff options
author | Mike Perry <mikeperry-git@torproject.org> | 2016-09-22 17:52:25 -0400 |
---|---|---|
committer | Nick Mathewson <nickm@torproject.org> | 2017-05-08 13:49:23 -0400 |
commit | 687a85950afc25010c80cd14539728b3a7ae5675 (patch) | |
tree | 033a575f75d586272f1e332c2d3a3b0f7ec26da1 /src/or | |
parent | ae4d8c9c745b396049c3064b7dc764bbd9a58058 (diff) | |
download | tor-687a85950afc25010c80cd14539728b3a7ae5675.tar.gz tor-687a85950afc25010c80cd14539728b3a7ae5675.zip |
Cache netflow-related consensus parameters.
Checking all of these parameter lists for every single connection every second
seems like it could be an expensive waste.
Updating globally cached versions when there is a new consensus will still
allow us to apply consensus parameter updates to all existing connections
immediately.
Diffstat (limited to 'src/or')
-rw-r--r-- | src/or/channelpadding.c | 148 | ||||
-rw-r--r-- | src/or/channelpadding.h | 1 | ||||
-rw-r--r-- | src/or/main.c | 4 | ||||
-rw-r--r-- | src/or/networkstatus.c | 2 |
4 files changed, 104 insertions, 51 deletions
diff --git a/src/or/channelpadding.c b/src/or/channelpadding.c index 3156051c3b..a84994afc8 100644 --- a/src/or/channelpadding.c +++ b/src/or/channelpadding.c @@ -29,6 +29,87 @@ STATIC int64_t channelpadding_compute_time_until_pad_for_netflow(channel_t *); /** The total number of pending channelpadding timers */ static uint64_t total_timers_pending; +/** These are cached consensus parameters for netflow */ +/** The timeout lower bound that is allowed before sending padding */ +static int consensus_nf_ito_low; +/** The timeout upper bound that is allowed before sending padding */ +static int consensus_nf_ito_high; +/** The timeout lower bound that is allowed before sending reduced padding */ +static int consensus_nf_ito_low_reduced; +/** The timeout upper bound that is allowed before sending reduced padding */ +static int consensus_nf_ito_high_reduced; +/** The connection timeout between relays */ +static int consensus_nf_conntimeout_relays; +/** The connection timeout for client connections */ +static int consensus_nf_conntimeout_clients; +/** Should we pad before circuits are actually used for client data? */ +static int consensus_nf_pad_before_usage; +/** Should we pad relay-to-relay connections? */ +static int consensus_nf_pad_relays; + +/** + * This function is called to update cached consensus parameters every time + * there is a consensus update. This allows us to move the consensus param + * search off of the critical path, so it does not need to be evaluated + * for every single connection, every second. + */ +void +channelpadding_new_consensus_params(networkstatus_t *ns) +{ +#define DFLT_NETFLOW_INACTIVE_KEEPALIVE_LOW 1500 +#define DFLT_NETFLOW_INACTIVE_KEEPALIVE_HIGH 9500 +#define DFLT_NETFLOW_INACTIVE_KEEPALIVE_MIN 0 +#define DFLT_NETFLOW_INACTIVE_KEEPALIVE_MAX 60000 + consensus_nf_ito_low = networkstatus_get_param(ns, "nf_ito_low", + DFLT_NETFLOW_INACTIVE_KEEPALIVE_LOW, + DFLT_NETFLOW_INACTIVE_KEEPALIVE_MIN, + DFLT_NETFLOW_INACTIVE_KEEPALIVE_MAX); + consensus_nf_ito_high = networkstatus_get_param(NULL, "nf_ito_high", + DFLT_NETFLOW_INACTIVE_KEEPALIVE_HIGH, + consensus_nf_ito_low, + DFLT_NETFLOW_INACTIVE_KEEPALIVE_MAX); + +#define DFLT_NETFLOW_REDUCED_KEEPALIVE_LOW 9000 +#define DFLT_NETFLOW_REDUCED_KEEPALIVE_HIGH 14000 +#define DFLT_NETFLOW_REDUCED_KEEPALIVE_MIN 0 +#define DFLT_NETFLOW_REDUCED_KEEPALIVE_MAX 60000 + consensus_nf_ito_low_reduced = + networkstatus_get_param(NULL, "nf_ito_low_reduced", + DFLT_NETFLOW_REDUCED_KEEPALIVE_LOW, + DFLT_NETFLOW_REDUCED_KEEPALIVE_MIN, + DFLT_NETFLOW_REDUCED_KEEPALIVE_MAX); + + consensus_nf_ito_high_reduced = + networkstatus_get_param(NULL, "nf_ito_high_reduced", + DFLT_NETFLOW_REDUCED_KEEPALIVE_HIGH, + consensus_nf_ito_low_reduced, + DFLT_NETFLOW_REDUCED_KEEPALIVE_MAX); + +#define CONNTIMEOUT_RELAYS_DFLT (60*60) // 1 hour +#define CONNTIMEOUT_RELAYS_MIN 60 +#define CONNTIMEOUT_RELAYS_MAX (7*24*60*60) // 1 week + consensus_nf_conntimeout_relays = + networkstatus_get_param(NULL, "nf_conntimeout_relays", + CONNTIMEOUT_RELAYS_DFLT, + CONNTIMEOUT_RELAYS_MIN, + CONNTIMEOUT_RELAYS_MAX); + +#define CIRCTIMEOUT_CLIENTS_DFLT (30*60) // 30 minutes +#define CIRCTIMEOUT_CLIENTS_MIN 60 +#define CIRCTIMEOUT_CLIENTS_MAX (24*60*60) // 24 hours + consensus_nf_conntimeout_clients = + networkstatus_get_param(NULL, "nf_conntimeout_clients", + CIRCTIMEOUT_CLIENTS_DFLT, + CIRCTIMEOUT_CLIENTS_MIN, + CIRCTIMEOUT_CLIENTS_MAX); + + consensus_nf_pad_before_usage = + networkstatus_get_param(NULL, "nf_pad_before_usage", 1, 0, 1); + + consensus_nf_pad_relays = + networkstatus_get_param(NULL, "nf_pad_relays", 0, 0, 1); +} + /** * Get a random netflow inactive timeout keepalive period in milliseconds, * the range for which is determined by consensus parameters, negotiation, @@ -47,21 +128,11 @@ static uint64_t total_timers_pending; * Returns the next timeout period (in milliseconds) after which we should * send a padding packet, or 0 if padding is disabled. */ -#define DFLT_NETFLOW_INACTIVE_KEEPALIVE_LOW 1500 -#define DFLT_NETFLOW_INACTIVE_KEEPALIVE_HIGH 9500 -#define DFLT_NETFLOW_INACTIVE_KEEPALIVE_MIN 0 -#define DFLT_NETFLOW_INACTIVE_KEEPALIVE_MAX 60000 STATIC int channelpadding_get_netflow_inactive_timeout_ms(const channel_t *chan) { - int low_timeout = networkstatus_get_param(NULL, "nf_ito_low", - DFLT_NETFLOW_INACTIVE_KEEPALIVE_LOW, - DFLT_NETFLOW_INACTIVE_KEEPALIVE_MIN, - DFLT_NETFLOW_INACTIVE_KEEPALIVE_MAX); - int high_timeout = networkstatus_get_param(NULL, "nf_ito_high", - DFLT_NETFLOW_INACTIVE_KEEPALIVE_HIGH, - low_timeout, - DFLT_NETFLOW_INACTIVE_KEEPALIVE_MAX); + int low_timeout = consensus_nf_ito_low; + int high_timeout = consensus_nf_ito_high; int X1, X2; if (low_timeout == 0 && low_timeout == high_timeout) @@ -162,12 +233,8 @@ channelpadding_update_padding_for_channel(channel_t *chan, /* Min must not be lower than the current consensus parameter nf_ito_low. */ - chan->padding_timeout_low_ms = MAX(networkstatus_get_param(NULL, - "nf_ito_low", - DFLT_NETFLOW_INACTIVE_KEEPALIVE_LOW, - DFLT_NETFLOW_INACTIVE_KEEPALIVE_MIN, - DFLT_NETFLOW_INACTIVE_KEEPALIVE_MAX), - pad_vars->ito_low_ms); + chan->padding_timeout_low_ms = MAX(consensus_nf_ito_low, + pad_vars->ito_low_ms); /* Max must not be lower than ito_low_ms */ chan->padding_timeout_high_ms = MAX(chan->padding_timeout_low_ms, @@ -399,6 +466,12 @@ channelpadding_compute_time_until_pad_for_netflow(channel_t *chan) uint64_t long_now = monotime_coarse_absolute_msec(); if (!chan->next_padding_time_ms) { + /* If the below line or crypto_rand_int() shows up on a profile, + * we can avoid getting a timeout until we're at least nt_ito_lo + * from a timeout window. That will prevent us from setting timers + * on connections that were active up to 1.5 seconds ago. + * Idle connections should only call this once every 5.5s on average + * though, so that might be a micro-optimization for little gain. */ int64_t padding_timeout = channelpadding_get_netflow_inactive_timeout_ms(chan); @@ -475,14 +548,7 @@ channelpadding_get_channel_idle_timeout(const channel_t *chan, + crypto_rand_int(CONNTIMEOUT_CLIENTS_BASE/2); } else { // Canonical relay-to-relay channels // 45..75min or consensus +/- 25% -#define CONNTIMEOUT_RELAYS_DFLT (60*60) // 1 hour -#define CONNTIMEOUT_RELAYS_MIN 60 -#define CONNTIMEOUT_RELAYS_MAX (7*24*60*60) // 1 week - timeout = networkstatus_get_param(NULL, "nf_conntimeout_relays", - CONNTIMEOUT_RELAYS_DFLT, - CONNTIMEOUT_RELAYS_MIN, - CONNTIMEOUT_RELAYS_MAX); - + timeout = consensus_nf_conntimeout_relays; timeout = 3*timeout/4 + crypto_rand_int(timeout/2); } @@ -522,13 +588,7 @@ channelpadding_get_circuits_available_timeout(void) int timeout = options->CircuitsAvailableTimeout; if (!timeout) { -#define CIRCTIMEOUT_CLIENTS_DFLT (30*60) // 30 minutes -#define CIRCTIMEOUT_CLIENTS_MIN 60 -#define CIRCTIMEOUT_CLIENTS_MAX (24*60*60) // 24 hours - timeout = networkstatus_get_param(NULL, "nf_conntimeout_clients", - CIRCTIMEOUT_CLIENTS_DFLT, - CIRCTIMEOUT_CLIENTS_MIN, - CIRCTIMEOUT_CLIENTS_MAX); + timeout = consensus_nf_conntimeout_clients; /* If ReducedConnectionPadding is set, we want to halve the duration of * the channel idle timeout, since reducing the additional time that @@ -579,21 +639,8 @@ channelpadding_reduce_padding_on_channel(channel_t *chan) channelpadding_send_disable_command(chan); } -#define DFLT_NETFLOW_REDUCED_KEEPALIVE_LOW 9000 -#define DFLT_NETFLOW_REDUCED_KEEPALIVE_HIGH 14000 -#define DFLT_NETFLOW_REDUCED_KEEPALIVE_MIN 0 -#define DFLT_NETFLOW_REDUCED_KEEPALIVE_MAX 60000 - chan->padding_timeout_low_ms = - networkstatus_get_param(NULL, "nf_ito_low_reduced", - DFLT_NETFLOW_REDUCED_KEEPALIVE_LOW, - DFLT_NETFLOW_REDUCED_KEEPALIVE_MIN, - DFLT_NETFLOW_REDUCED_KEEPALIVE_MAX); - - chan->padding_timeout_high_ms = - networkstatus_get_param(NULL, "nf_ito_high_reduced", - DFLT_NETFLOW_REDUCED_KEEPALIVE_HIGH, - chan->padding_timeout_low_ms, - DFLT_NETFLOW_REDUCED_KEEPALIVE_MAX); + chan->padding_timeout_low_ms = consensus_nf_ito_low_reduced; + chan->padding_timeout_high_ms = consensus_nf_ito_high_reduced; log_fn(LOG_INFO,LD_OR, "Reduced padding on channel "U64_FORMAT": lo=%d, hi=%d", @@ -621,7 +668,7 @@ channelpadding_decide_to_pad_channel(channel_t *chan) return CHANNELPADDING_WONTPAD; if (chan->channel_usage == CHANNEL_USED_FOR_FULL_CIRCS) { - if (!networkstatus_get_param(NULL, "nf_pad_before_usage", 1, 0, 1)) + if (!consensus_nf_pad_before_usage) return CHANNELPADDING_WONTPAD; } else if (chan->channel_usage != CHANNEL_USED_FOR_USER_TRAFFIC) { return CHANNELPADDING_WONTPAD; @@ -649,8 +696,7 @@ channelpadding_decide_to_pad_channel(channel_t *chan) /* If nf_pad_relays=1 is set in the consensus, we pad * on *all* idle connections, relay-relay or relay-client. * Otherwise pad only for client+bridge cons */ - if (is_client_channel || - networkstatus_get_param(NULL, "nf_pad_relays", 0, 0, 1)) { + if (is_client_channel || consensus_nf_pad_relays) { int64_t pad_time_ms = channelpadding_compute_time_until_pad_for_netflow(chan); diff --git a/src/or/channelpadding.h b/src/or/channelpadding.h index 07af7a6b46..e08f7a2045 100644 --- a/src/or/channelpadding.h +++ b/src/or/channelpadding.h @@ -33,6 +33,7 @@ int channelpadding_send_enable_command(channel_t *chan, uint16_t low_timeout, int channelpadding_get_circuits_available_timeout(void); unsigned int channelpadding_get_channel_idle_timeout(const channel_t *, int); +void channelpadding_new_consensus_params(networkstatus_t *ns); #endif diff --git a/src/or/main.c b/src/or/main.c index 5bc132a0e3..b729e0b378 100644 --- a/src/or/main.c +++ b/src/or/main.c @@ -3033,6 +3033,10 @@ tor_init(int argc, char *argv[]) /* The options are now initialised */ const or_options_t *options = get_options(); + /* Initialize channelpadding parameters to defaults until we get + * a consensus */ + channelpadding_new_consensus_params(NULL); + /* Initialize predicted ports list after loading options */ predicted_ports_init(); diff --git a/src/or/networkstatus.c b/src/or/networkstatus.c index 76b968a8c8..4107542f56 100644 --- a/src/or/networkstatus.c +++ b/src/or/networkstatus.c @@ -63,6 +63,7 @@ #include "shared_random.h" #include "transports.h" #include "torcert.h" +#include "channelpadding.h" /** Map from lowercase nickname to identity digest of named server, if any. */ static strmap_t *named_server_map = NULL; @@ -1966,6 +1967,7 @@ networkstatus_set_current_consensus(const char *consensus, circuit_build_times_new_consensus_params( get_circuit_build_times_mutable(), c); + channelpadding_new_consensus_params(c); } /* Reset the failure count only if this consensus is actually valid. */ |