Commit 29e0d708 authored by Mike Perry's avatar Mike Perry
Browse files

Bug 1296: Add option+logic to disable CBT learning.

There are now four ways that CBT can be disabled:

1. Network-wide, with the cbtdisabled consensus param.
2. Via config, with "LearnCircuitBuildTimeout 0"
3. Via config, with "AuthoritativeDirectory 1"
4. Via a state file write failure.
parent 0a6191cf
......@@ -382,6 +382,12 @@ of their choices.
construction. If these parameters are not present in the consensus,
the listed default values should be used instead.
cbtdisabled
Default: 0
Effect: If non-zero, all CircuitBuildTime learning code should be
disabled and history should be discarded. For use in
emergency situations only.
cbtrecentcount
Default: 20
Effect: This is the number of circuit build times to keep track of
......
......@@ -419,9 +419,16 @@ The following options are useful only for clients (that is, if
fingerprint to look up the bridge descriptor at the bridge authority, if
it's provided and if UpdateBridgesFromAuthority is set too.
**LearnCircuitBuildTimeout** **0**|**1**::
If 0, CircuitBuildTimeout adaptive learning is disabled. (Default: 1)
**CircuitBuildTimeout** __NUM__::
Try for at most NUM seconds when building circuits. If the circuit isn't
open in that time, give up on it. (Default: 1 minute.)
open in that time, give up on it. If LearnCircuitBuildTimeout is 1, this
value serves as the initial value to use before a timeout is learned. If
LearnCircuitBuildTimeout is 0, this value is the only value used.
(Default: 60 seconds.)
**CircuitIdleTimeout** __NUM__::
If we have kept a clean (never used) circuit around for NUM seconds, then
......
......@@ -81,6 +81,28 @@ static int onion_append_hop(crypt_path_t **head_ptr, extend_info_t *choice);
static void entry_guards_changed(void);
static int
circuit_build_times_disabled(void)
{
int consensus_disabled = networkstatus_get_param(NULL, "cbtdisabled",
0);
int config_disabled = !get_options()->LearnCircuitBuildTimeout;
int dirauth_disabled = get_options()->AuthoritativeDir;
int state_disabled = (get_or_state()->LastWritten == -1);
if (consensus_disabled || config_disabled || dirauth_disabled ||
state_disabled) {
log_info(LD_CIRC,
"CircuitBuildTime learning is disabled. "
"Consensus=%d, Config=%d, AuthDir=%d, StateFile=%d",
consensus_disabled, config_disabled, dirauth_disabled,
state_disabled);
return 1;
} else {
return 0;
}
}
static int32_t
circuit_build_times_max_timeouts(void)
{
......@@ -531,11 +553,16 @@ circuit_build_times_parse_state(circuit_build_times_t *cbt,
uint32_t loaded_cnt = 0, N = 0;
config_line_t *line;
int i;
build_time_t *loaded_times = tor_malloc(sizeof(build_time_t)
* state->TotalBuildTimes);
build_time_t *loaded_times;
circuit_build_times_init(cbt);
*msg = NULL;
if (circuit_build_times_disabled()) {
return 0;
}
loaded_times = tor_malloc(sizeof(build_time_t)*state->TotalBuildTimes);
for (line = state->BuildtimeHistogram; line; line = line->next) {
smartlist_t *args = smartlist_create();
smartlist_split_string(args, line->value, " ",
......@@ -1020,6 +1047,11 @@ circuit_build_times_add_timeout(circuit_build_times_t *cbt,
int did_onehop,
time_t start_time)
{
if (circuit_build_times_disabled()) {
cbt->timeout_ms = circuit_build_times_get_initial_timeout();
return 0;
}
circuit_build_times_network_timeout(cbt, did_onehop, start_time);
/* Only count timeouts if network is live.. */
......@@ -1769,7 +1801,7 @@ circuit_send_next_onion_skin(origin_circuit_t *circ)
if (timediff < 0 || timediff > 2*circ_times.timeout_ms+1000) {
log_notice(LD_CIRC, "Strange value for circuit build time: %ld. "
"Assuming clock jump.", timediff);
} else {
} else if (!circuit_build_times_disabled()) {
circuit_build_times_add_time(&circ_times, (build_time_t)timediff);
circuit_build_times_network_circ_success(&circ_times);
circuit_build_times_set_timeout(&circ_times);
......
......@@ -167,6 +167,7 @@ static config_var_t _option_vars[] = {
V(BridgeRecordUsageByCountry, BOOL, "1"),
V(BridgeRelay, BOOL, "0"),
V(CellStatistics, BOOL, "0"),
V(LearnCircuitBuildTimeout, BOOL, "1"),
V(CircuitBuildTimeout, INTERVAL, "0"),
V(CircuitIdleTimeout, INTERVAL, "1 hour"),
V(CircuitStreamTimeout, INTERVAL, "0"),
......@@ -4982,7 +4983,6 @@ or_state_save(time_t now)
if (accounting_is_enabled(get_options()))
accounting_run_housekeeping(now);
global_state->LastWritten = time(NULL);
tor_free(global_state->TorVersion);
tor_asprintf(&global_state->TorVersion, "Tor %s", get_version());
......@@ -4997,10 +4997,13 @@ or_state_save(time_t now)
fname = get_datadir_fname("state");
if (write_str_to_file(fname, contents, 0)<0) {
log_warn(LD_FS, "Unable to write state to file \"%s\"", fname);
global_state->LastWritten = -1;
tor_free(fname);
tor_free(contents);
return -1;
}
global_state->LastWritten = time(NULL);
log_info(LD_GENERAL, "Saved state to \"%s\"", fname);
tor_free(fname);
tor_free(contents);
......
......@@ -2496,9 +2496,12 @@ typedef struct {
* connections alive? */
int SocksTimeout; /**< How long do we let a socks connection wait
* unattached before we fail it? */
int CircuitBuildTimeout; /**< If non-zero, cull non-open circuits that
* were born at least this many seconds ago. If
* zero, use the internal adaptive algorithm. */
int LearnCircuitBuildTimeout; /**< If non-zero, we attempt to learn a value
* for CircuitBuildTimeout based on timeout
* history */
int CircuitBuildTimeout; /**< Cull non-open circuits that were born at
* least this many seconds ago. Used until
* adaptive algorithm learns a new value. */
int CircuitIdleTimeout; /**< Cull open clean circuits that were born
* at least this many seconds ago. */
int CircuitStreamTimeout; /**< If non-zero, detach streams from circuits
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment