Merge remote branch 'public/cbt-status'

Conflicts:
	ChangeLog
This commit is contained in:
Nick Mathewson 2010-02-20 18:35:19 -05:00
commit 0eb03bc6dd
7 changed files with 451 additions and 146 deletions

View File

@ -22,7 +22,9 @@ Changes in version 0.2.2.9-alpha - 2010-??-??
"memcpyfail".
- Make the DNSPort option work with libevent 2.x. Don't alter the
behaviour for libevent 1.x. Fixes bug 1143. Found by SwissTorExit.
- Emit an GUARD DROPPED event for a case we missed.
- Make more fields in the controller protocol case-insensitive as
documented in control-spec.txt.
o Code simplifications and refactoring:
- Generate our manpage and HTML documentation using Asciidoc. This
@ -35,6 +37,20 @@ Changes in version 0.2.2.9-alpha - 2010-??-??
AUTHORS file had its content merged into the people page on the
website. The roadmaps and design doc can now be found in the
projects directory in svn.
- Enabled various circuit build timeout constants to be controlled
by consensus parameters. Also set better defaults for these
parameters based on experimentation on broadband and simulated
high latency links.
o Minor features:
- The 'EXTENDCIRCUIT' control port command can now be used with
a circ id of 0 and no path. This will cause Tor to build a new
'fast' general purpose circuit using its own path selection
algorithms.
- Added a BUILDTIMEOUT_SET control port event to describe changes
to the circuit build timeout.
- Future-proof the controller protocol a bit by ignoring keyword
arguments we do not recognize.
o Removed features:
- Stop shipping parts of the website and the design paper in the

View File

@ -219,7 +219,7 @@
"INFO" / "NOTICE" / "WARN" / "ERR" / "NEWDESC" / "ADDRMAP" /
"AUTHDIR_NEWDESCS" / "DESCCHANGED" / "STATUS_GENERAL" /
"STATUS_CLIENT" / "STATUS_SERVER" / "GUARD" / "NS" / "STREAM_BW" /
"CLIENTS_SEEN" / "NEWCONSENSUS"
"CLIENTS_SEEN" / "NEWCONSENSUS" / "BUILDTIMEOUT_SET"
Any events *not* listed in the SETEVENTS line are turned off; thus, sending
SETEVENTS with an empty body turns off all event reporting.
@ -606,15 +606,20 @@
3.10. EXTENDCIRCUIT
Sent from the client to the server. The format is:
"EXTENDCIRCUIT" SP CircuitID SP
ServerSpec *("," ServerSpec)
[SP "purpose=" Purpose] CRLF
"EXTENDCIRCUIT" SP CircuitID
[SP ServerSpec *("," ServerSpec)
SP "purpose=" Purpose] CRLF
This request takes one of two forms: either the CircuitID is zero, in
which case it is a request for the server to build a new circuit according
to the specified path, or the CircuitID is nonzero, in which case it is a
request for the server to extend an existing circuit with that ID according
to the specified path.
which case it is a request for the server to build a new circuit,
or the CircuitID is nonzero, in which case it is a request for the
server to extend an existing circuit with that ID according to the
specified path.
If the CircuitID is 0, the controller has the option of providing
a path for Tor to use to build the circuit. If it does not provide
a path, Tor will select one automatically from high capacity nodes
according to path-spec.txt.
If CircuitID is 0 and "purpose=" is specified, then the circuit's
purpose is set. Two choices are recognized: "general" and
@ -1656,6 +1661,38 @@
[First added in 0.2.1.13-alpha]
4.1.16. New circuit buildtime has been set.
The syntax is:
"650" SP "BUILDTIMEOUT_SET" SP Type SP "TOTAL_TIMES=" Total SP
"TIMEOUT_MS=" Timeout SP "XM=" Xm SP "ALPHA=" Alpha SP
"CUTOFF_QUANTILE=" Quantile CRLF
Type = "COMPUTED" / "RESET" / "SUSPENDED" / "DISCARD" / "RESUME"
Total = Integer count of timeouts stored
Timeout = Integer timeout in milliseconds
Xm = Estimated integer Pareto parameter Xm in milliseconds
Alpha = Estimated floating point Paredo paremter alpha
Quantile = Floating point CDF quantile cutoff point for this timeout
A new circuit build timeout time has been set. If Type is "COMPUTED",
Tor has computed the value based on historical data. If Type is "RESET",
initialization or drastic network changes have caused Tor to reset
the timeout back to the default, to relearn again. If Type is
"SUSPENDED", Tor has detected a loss of network connectivity and has
temporarily changed the timeout value to the default until the network
recovers. If type is "DISCARD", Tor has decided to discard timeout
values that likely happened while the network was down. If type is
"RESUME", Tor has decided to resume timeout calculation.
The Total value is the count of circuit build times Tor used in
computing this value. It is capped internally at the maximum number
of build times Tor stores (NCIRCUITS_TO_OBSERVE).
The Timeout itself is provided in milliseconds. Internally, Tor rounds
this value to the nearest second before using it.
[First added in 0.2.2.7-alpha]
5. Implementation notes
5.1. Authentication

View File

@ -79,6 +79,111 @@ static int onion_append_hop(crypt_path_t **head_ptr, extend_info_t *choice);
static void entry_guards_changed(void);
static int32_t
circuit_build_times_max_timeouts(void)
{
int32_t num = networkstatus_get_param(NULL, "cbtmaxtimeouts",
CBT_DEFAULT_MAX_RECENT_TIMEOUT_COUNT);
return num;
}
static int32_t
circuit_build_times_min_circs_to_observe(void)
{
int32_t num = networkstatus_get_param(NULL, "cbtmincircs",
CBT_DEFAULT_MIN_CIRCUITS_TO_OBSERVE);
return num;
}
double
circuit_build_times_quantile_cutoff(void)
{
int32_t num = networkstatus_get_param(NULL, "cbtquantile",
CBT_DEFAULT_QUANTILE_CUTOFF);
return num/100.0;
}
static int32_t
circuit_build_times_test_frequency(void)
{
int32_t num = networkstatus_get_param(NULL, "cbttestfreq",
CBT_DEFAULT_TEST_FREQUENCY);
return num;
}
static int32_t
circuit_build_times_min_timeout(void)
{
int32_t num = networkstatus_get_param(NULL, "cbtmintimeout",
CBT_DEFAULT_TIMEOUT_MIN_VALUE);
return num;
}
int32_t
circuit_build_times_initial_timeout(void)
{
int32_t num = networkstatus_get_param(NULL, "cbtinitialtimeout",
CBT_DEFAULT_TIMEOUT_INITIAL_VALUE);
return num;
}
static int32_t
circuit_build_times_recent_circuit_count(void)
{
int32_t num = networkstatus_get_param(NULL, "cbtrecentcount",
CBT_DEFAULT_RECENT_CIRCUITS);
return num;
}
/**
* This function is called when we get a consensus update.
*
* It checks to see if we have changed any consensus parameters
* that require reallocation or discard of previous stats.
*/
void
circuit_build_times_new_consensus_params(circuit_build_times_t *cbt,
networkstatus_t *ns)
{
int32_t num = networkstatus_get_param(ns, "cbtrecentcount",
CBT_DEFAULT_RECENT_CIRCUITS);
if (num != cbt->liveness.num_recent_circs) {
int8_t *recent_circs;
log_notice(LD_CIRC, "Changing recent timeout size from %d to %d",
cbt->liveness.num_recent_circs, num);
tor_assert(num > 0);
tor_assert(cbt->liveness.timeouts_after_firsthop);
/*
* Technically this is a circular array that we are reallocating
* and memcopying. However, since it only consists of either 1s
* or 0s, and is only used in a statistical test to determine when
* we should discard our history after a sufficient number of 1's
* have been reached, it is fine if order is not preserved or
* elements are lost.
*
* cbtrecentcount should only be changing in cases of severe network
* distress anyway, so memory correctness here is paramount over
* doing acrobatics to preserve the array.
*/
recent_circs = tor_malloc_zero(sizeof(int8_t)*num);
memcpy(recent_circs, cbt->liveness.timeouts_after_firsthop,
sizeof(int8_t)*MIN(num, cbt->liveness.num_recent_circs));
// Adjust the index if it needs it.
if (num < cbt->liveness.num_recent_circs) {
cbt->liveness.after_firsthop_idx = MIN(num-1,
cbt->liveness.after_firsthop_idx);
}
tor_free(cbt->liveness.timeouts_after_firsthop);
cbt->liveness.timeouts_after_firsthop = recent_circs;
cbt->liveness.num_recent_circs = num;
}
}
/** Make a note that we're running unit tests (rather than running Tor
* itself), so we avoid clobbering our state file. */
void
@ -96,13 +201,13 @@ circuit_build_times_get_initial_timeout(void)
double timeout;
if (!unit_tests && get_options()->CircuitBuildTimeout) {
timeout = get_options()->CircuitBuildTimeout*1000;
if (timeout < BUILD_TIMEOUT_MIN_VALUE) {
if (timeout < circuit_build_times_min_timeout()) {
log_warn(LD_CIRC, "Config CircuitBuildTimeout too low. Setting to %ds",
BUILD_TIMEOUT_MIN_VALUE/1000);
timeout = BUILD_TIMEOUT_MIN_VALUE;
circuit_build_times_min_timeout()/1000);
timeout = circuit_build_times_min_timeout();
}
} else {
timeout = BUILD_TIMEOUT_INITIAL_VALUE;
timeout = circuit_build_times_initial_timeout();
}
return timeout;
}
@ -133,7 +238,11 @@ void
circuit_build_times_init(circuit_build_times_t *cbt)
{
memset(cbt, 0, sizeof(*cbt));
cbt->liveness.num_recent_circs = circuit_build_times_recent_circuit_count();
cbt->liveness.timeouts_after_firsthop = tor_malloc_zero(sizeof(int8_t)*
cbt->liveness.num_recent_circs);
cbt->timeout_ms = circuit_build_times_get_initial_timeout();
control_event_buildtimeout_set(cbt, BUILDTIMEOUT_SET_EVENT_RESET);
}
/**
@ -161,10 +270,11 @@ circuit_build_times_rewind_history(circuit_build_times_t *cbt, int n)
}
cbt->build_times_idx -= n;
cbt->build_times_idx %= NCIRCUITS_TO_OBSERVE;
cbt->build_times_idx %= CBT_NCIRCUITS_TO_OBSERVE;
for (i = 0; i < n; i++) {
cbt->circuit_build_times[(i+cbt->build_times_idx)%NCIRCUITS_TO_OBSERVE]=0;
cbt->circuit_build_times[(i+cbt->build_times_idx)
%CBT_NCIRCUITS_TO_OBSERVE]=0;
}
if (cbt->total_build_times > n) {
@ -188,7 +298,7 @@ circuit_build_times_rewind_history(circuit_build_times_t *cbt, int n)
int
circuit_build_times_add_time(circuit_build_times_t *cbt, build_time_t time)
{
tor_assert(time <= BUILD_TIME_MAX);
tor_assert(time <= CBT_BUILD_TIME_MAX);
if (time <= 0) {
log_warn(LD_CIRC, "Circuit build time is %u!", time);
return -1;
@ -198,11 +308,11 @@ circuit_build_times_add_time(circuit_build_times_t *cbt, build_time_t time)
log_info(LD_CIRC, "Adding circuit build time %u", time);
cbt->circuit_build_times[cbt->build_times_idx] = time;
cbt->build_times_idx = (cbt->build_times_idx + 1) % NCIRCUITS_TO_OBSERVE;
if (cbt->total_build_times < NCIRCUITS_TO_OBSERVE)
cbt->build_times_idx = (cbt->build_times_idx + 1) % CBT_NCIRCUITS_TO_OBSERVE;
if (cbt->total_build_times < CBT_NCIRCUITS_TO_OBSERVE)
cbt->total_build_times++;
if ((cbt->total_build_times % BUILD_TIMES_SAVE_STATE_EVERY) == 0) {
if ((cbt->total_build_times % CBT_SAVE_STATE_EVERY) == 0) {
/* Save state every n circuit builds */
if (!unit_tests && !get_options()->AvoidDiskWrites)
or_state_mark_dirty(get_or_state(), 0);
@ -219,7 +329,7 @@ circuit_build_times_max(circuit_build_times_t *cbt)
{
int i = 0;
build_time_t max_build_time = 0;
for (i = 0; i < NCIRCUITS_TO_OBSERVE; i++) {
for (i = 0; i < CBT_NCIRCUITS_TO_OBSERVE; i++) {
if (cbt->circuit_build_times[i] > max_build_time)
max_build_time = cbt->circuit_build_times[i];
}
@ -232,14 +342,14 @@ build_time_t
circuit_build_times_min(circuit_build_times_t *cbt)
{
int i = 0;
build_time_t min_build_time = BUILD_TIME_MAX;
for (i = 0; i < NCIRCUITS_TO_OBSERVE; i++) {
build_time_t min_build_time = CBT_BUILD_TIME_MAX;
for (i = 0; i < CBT_NCIRCUITS_TO_OBSERVE; i++) {
if (cbt->circuit_build_times[i] && /* 0 <-> uninitialized */
cbt->circuit_build_times[i] < min_build_time)
min_build_time = cbt->circuit_build_times[i];
}
if (min_build_time == BUILD_TIME_MAX) {
log_warn(LD_CIRC, "No build times less than BUILD_TIME_MAX!");
if (min_build_time == CBT_BUILD_TIME_MAX) {
log_warn(LD_CIRC, "No build times less than CBT_BUILD_TIME_MAX!");
}
return min_build_time;
}
@ -249,7 +359,7 @@ circuit_build_times_min(circuit_build_times_t *cbt)
* Calculate and return a histogram for the set of build times.
*
* Returns an allocated array of histrogram bins representing
* the frequency of index*BUILDTIME_BIN_WIDTH millisecond
* the frequency of index*CBT_BIN_WIDTH millisecond
* build times. Also outputs the number of bins in nbins.
*
* The return value must be freed by the caller.
@ -262,14 +372,14 @@ circuit_build_times_create_histogram(circuit_build_times_t *cbt,
build_time_t max_build_time = circuit_build_times_max(cbt);
int i, c;
*nbins = 1 + (max_build_time / BUILDTIME_BIN_WIDTH);
*nbins = 1 + (max_build_time / CBT_BIN_WIDTH);
histogram = tor_malloc_zero(*nbins * sizeof(build_time_t));
// calculate histogram
for (i = 0; i < NCIRCUITS_TO_OBSERVE; i++) {
for (i = 0; i < CBT_NCIRCUITS_TO_OBSERVE; i++) {
if (cbt->circuit_build_times[i] == 0) continue; /* 0 <-> uninitialized */
c = (cbt->circuit_build_times[i] / BUILDTIME_BIN_WIDTH);
c = (cbt->circuit_build_times[i] / CBT_BIN_WIDTH);
histogram[c]++;
}
@ -277,7 +387,7 @@ circuit_build_times_create_histogram(circuit_build_times_t *cbt,
}
/**
* Return the most frequent build time (rounded to BUILDTIME_BIN_WIDTH ms).
* Return the most frequent build time (rounded to CBT_BIN_WIDTH ms).
*
* Ties go in favor of the slower time.
*/
@ -295,7 +405,7 @@ circuit_build_times_mode(circuit_build_times_t *cbt)
tor_free(histogram);
return max_bin*BUILDTIME_BIN_WIDTH+BUILDTIME_BIN_WIDTH/2;
return max_bin*CBT_BIN_WIDTH+CBT_BIN_WIDTH/2;
}
/**
@ -326,7 +436,7 @@ circuit_build_times_update_state(circuit_build_times_t *cbt,
line->key = tor_strdup("CircuitBuildTimeBin");
line->value = tor_malloc(25);
tor_snprintf(line->value, 25, "%d %d",
i*BUILDTIME_BIN_WIDTH+BUILDTIME_BIN_WIDTH/2, histogram[i]);
i*CBT_BIN_WIDTH+CBT_BIN_WIDTH/2, histogram[i]);
next = &(line->next);
}
@ -349,9 +459,9 @@ circuit_build_times_shuffle_and_store_array(circuit_build_times_t *cbt,
int num_times)
{
int n = num_times;
if (num_times > NCIRCUITS_TO_OBSERVE) {
if (num_times > CBT_NCIRCUITS_TO_OBSERVE) {
log_notice(LD_CIRC, "Decreasing circuit_build_times size from %d to %d",
num_times, NCIRCUITS_TO_OBSERVE);
num_times, CBT_NCIRCUITS_TO_OBSERVE);
}
/* This code can only be run on a compact array */
@ -362,9 +472,9 @@ circuit_build_times_shuffle_and_store_array(circuit_build_times_t *cbt,
raw_times[n] = tmp;
}
/* Since the times are now shuffled, take a random NCIRCUITS_TO_OBSERVE
* subset (ie the first NCIRCUITS_TO_OBSERVE values) */
for (n = 0; n < MIN(num_times, NCIRCUITS_TO_OBSERVE); n++) {
/* Since the times are now shuffled, take a random CBT_NCIRCUITS_TO_OBSERVE
* subset (ie the first CBT_NCIRCUITS_TO_OBSERVE values) */
for (n = 0; n < MIN(num_times, CBT_NCIRCUITS_TO_OBSERVE); n++) {
circuit_build_times_add_time(cbt, raw_times[n]);
}
}
@ -406,7 +516,7 @@ circuit_build_times_parse_state(circuit_build_times_t *cbt,
build_time_t ms;
int ok;
ms = (build_time_t)tor_parse_ulong(ms_str, 0, 0,
BUILD_TIME_MAX, &ok, NULL);
CBT_BUILD_TIME_MAX, &ok, NULL);
if (!ok) {
*msg = tor_strdup("Unable to parse circuit build times: "
"Unparsable bin number");
@ -452,7 +562,7 @@ circuit_build_times_parse_state(circuit_build_times_t *cbt,
circuit_build_times_shuffle_and_store_array(cbt, loaded_times, loaded_cnt);
/* Verify that we didn't overwrite any indexes */
for (i=0; i < NCIRCUITS_TO_OBSERVE; i++) {
for (i=0; i < CBT_NCIRCUITS_TO_OBSERVE; i++) {
if (!cbt->circuit_build_times[i])
break;
tot_values++;
@ -461,7 +571,7 @@ circuit_build_times_parse_state(circuit_build_times_t *cbt,
"Loaded %d/%d values from %d lines in circuit time histogram",
tot_values, cbt->total_build_times, N);
tor_assert(cbt->total_build_times == tot_values);
tor_assert(cbt->total_build_times <= NCIRCUITS_TO_OBSERVE);
tor_assert(cbt->total_build_times <= CBT_NCIRCUITS_TO_OBSERVE);
circuit_build_times_set_timeout(cbt);
tor_free(loaded_times);
return *msg ? -1 : 0;
@ -488,7 +598,7 @@ circuit_build_times_update_alpha(circuit_build_times_t *cbt)
* and less frechet-like. */
cbt->Xm = circuit_build_times_mode(cbt);
for (i=0; i< NCIRCUITS_TO_OBSERVE; i++) {
for (i=0; i< CBT_NCIRCUITS_TO_OBSERVE; i++) {
if (!x[i]) {
continue;
}
@ -593,19 +703,22 @@ void
circuit_build_times_add_timeout_worker(circuit_build_times_t *cbt,
double quantile_cutoff)
{
// XXX: This may be failing when the number of samples is small?
// Keep getting values for the largest timeout bucket over and over
// again... Probably because alpha is very very large in that case..
build_time_t gentime = circuit_build_times_generate_sample(cbt,
quantile_cutoff, MAX_SYNTHETIC_QUANTILE);
quantile_cutoff, CBT_MAX_SYNTHETIC_QUANTILE);
if (gentime < (build_time_t)tor_lround(cbt->timeout_ms)) {
log_warn(LD_CIRC,
"Generated a synthetic timeout LESS than the current timeout: "
"%ums vs %lfms using Xm: %d a: %lf, q: %lf",
gentime, cbt->timeout_ms, cbt->Xm, cbt->alpha, quantile_cutoff);
} else if (gentime > BUILD_TIME_MAX) {
} else if (gentime > CBT_BUILD_TIME_MAX) {
log_info(LD_CIRC,
"Generated a synthetic timeout larger than the max: %u",
gentime);
gentime = BUILD_TIME_MAX;
gentime = CBT_BUILD_TIME_MAX;
} else {
log_info(LD_CIRC, "Generated synthetic circuit build time %u for timeout",
gentime);
@ -649,7 +762,7 @@ circuit_build_times_count_pretimeouts(circuit_build_times_t *cbt)
((double)cbt->pre_timeouts)/
(cbt->pre_timeouts+cbt->total_build_times);
/* Make sure it doesn't exceed the synthetic max */
timeout_quantile *= MAX_SYNTHETIC_QUANTILE;
timeout_quantile *= CBT_MAX_SYNTHETIC_QUANTILE;
cbt->Xm = circuit_build_times_mode(cbt);
tor_assert(cbt->Xm > 0);
/* Use current timeout to get an estimate on alpha */
@ -669,7 +782,7 @@ int
circuit_build_times_needs_circuits(circuit_build_times_t *cbt)
{
/* Return true if < MIN_CIRCUITS_TO_OBSERVE */
if (cbt->total_build_times < MIN_CIRCUITS_TO_OBSERVE)
if (cbt->total_build_times < circuit_build_times_min_circs_to_observe())
return 1;
return 0;
}
@ -682,11 +795,14 @@ int
circuit_build_times_needs_circuits_now(circuit_build_times_t *cbt)
{
return circuit_build_times_needs_circuits(cbt) &&
approx_time()-cbt->last_circ_at > BUILD_TIMES_TEST_FREQUENCY;
approx_time()-cbt->last_circ_at > circuit_build_times_test_frequency();
}
/**
* Called to indicate that the network showed some signs of liveness.
*
* This function is called every time we receive a cell. Avoid
* syscalls, events, and other high-intensity work.
*/
void
circuit_build_times_network_is_live(circuit_build_times_t *cbt)
@ -705,7 +821,7 @@ circuit_build_times_network_circ_success(circuit_build_times_t *cbt)
{
cbt->liveness.timeouts_after_firsthop[cbt->liveness.after_firsthop_idx] = 0;
cbt->liveness.after_firsthop_idx++;
cbt->liveness.after_firsthop_idx %= RECENT_CIRCUITS;
cbt->liveness.after_firsthop_idx %= cbt->liveness.num_recent_circs;
}
/**
@ -736,7 +852,7 @@ circuit_build_times_network_timeout(circuit_build_times_t *cbt,
/* Count a one-hop timeout */
cbt->liveness.timeouts_after_firsthop[cbt->liveness.after_firsthop_idx]=1;
cbt->liveness.after_firsthop_idx++;
cbt->liveness.after_firsthop_idx %= RECENT_CIRCUITS;
cbt->liveness.after_firsthop_idx %= cbt->liveness.num_recent_circs;
}
}
@ -751,7 +867,7 @@ int
circuit_build_times_network_check_live(circuit_build_times_t *cbt)
{
time_t now = approx_time();
if (cbt->liveness.nonlive_timeouts >= NETWORK_NONLIVE_DISCARD_COUNT) {
if (cbt->liveness.nonlive_timeouts >= CBT_NETWORK_NONLIVE_DISCARD_COUNT) {
if (!cbt->liveness.nonlive_discarded) {
cbt->liveness.nonlive_discarded = 1;
log_notice(LD_CIRC, "Network is no longer live (too many recent "
@ -759,10 +875,13 @@ circuit_build_times_network_check_live(circuit_build_times_t *cbt)
(long int)(now - cbt->liveness.network_last_live));
/* Only discard NETWORK_NONLIVE_TIMEOUT_COUNT-1 because we stopped
* counting after that */
circuit_build_times_rewind_history(cbt, NETWORK_NONLIVE_TIMEOUT_COUNT-1);
circuit_build_times_rewind_history(cbt,
CBT_NETWORK_NONLIVE_TIMEOUT_COUNT-1);
control_event_buildtimeout_set(cbt, BUILDTIMEOUT_SET_EVENT_DISCARD);
}
return 0;
} else if (cbt->liveness.nonlive_timeouts >= NETWORK_NONLIVE_TIMEOUT_COUNT) {
} else if (cbt->liveness.nonlive_timeouts >=
CBT_NETWORK_NONLIVE_TIMEOUT_COUNT) {
if (cbt->timeout_ms < circuit_build_times_get_initial_timeout()) {
log_notice(LD_CIRC,
"Network is flaky. No activity for %ld seconds. "
@ -770,9 +889,17 @@ circuit_build_times_network_check_live(circuit_build_times_t *cbt)
(long int)(now - cbt->liveness.network_last_live),
tor_lround(circuit_build_times_get_initial_timeout()/1000));
cbt->timeout_ms = circuit_build_times_get_initial_timeout();
cbt->liveness.net_suspended = 1;
control_event_buildtimeout_set(cbt, BUILDTIMEOUT_SET_EVENT_SUSPENDED);
}
return 0;
} else if (cbt->liveness.net_suspended) {
log_notice(LD_CIRC,
"Network activity has resumed. "
"Resuming circuit timeout calculations.");
cbt->liveness.net_suspended = 0;
control_event_buildtimeout_set(cbt, BUILDTIMEOUT_SET_EVENT_RESUME);
}
return 1;
@ -796,19 +923,20 @@ circuit_build_times_network_check_changed(circuit_build_times_t *cbt)
/* how many of our recent circuits made it to the first hop but then
* timed out? */
for (i = 0; i < RECENT_CIRCUITS; i++) {
for (i = 0; i < cbt->liveness.num_recent_circs; i++) {
timeout_count += cbt->liveness.timeouts_after_firsthop[i];
}
/* If 80% of our recent circuits are timing out after the first hop,
* we need to re-estimate a new initial alpha and timeout. */
if (timeout_count < MAX_RECENT_TIMEOUT_COUNT) {
if (timeout_count < circuit_build_times_max_timeouts()) {
return 0;
}
circuit_build_times_reset(cbt);
memset(cbt->liveness.timeouts_after_firsthop, 0,
sizeof(cbt->liveness.timeouts_after_firsthop));
sizeof(*cbt->liveness.timeouts_after_firsthop)*
cbt->liveness.num_recent_circs);
cbt->liveness.after_firsthop_idx = 0;
/* Check to see if this has happened before. If so, double the timeout
@ -819,6 +947,8 @@ circuit_build_times_network_check_changed(circuit_build_times_t *cbt)
cbt->timeout_ms = circuit_build_times_get_initial_timeout();
}
control_event_buildtimeout_set(cbt, BUILDTIMEOUT_SET_EVENT_RESET);
log_notice(LD_CIRC,
"Network connection speed appears to have changed. Resetting "
"timeout to %lds after %d timeouts and %d buildtimes.",
@ -857,13 +987,14 @@ circuit_build_times_add_timeout(circuit_build_times_t *cbt,
cbt->pre_timeouts++;
log_info(LD_CIRC,
"Not enough circuits yet to calculate a new build timeout."
" Need %d more.",
MIN_CIRCUITS_TO_OBSERVE-cbt->total_build_times);
" Need %d more.", circuit_build_times_min_circs_to_observe()
- cbt->total_build_times);
return 0;
}
circuit_build_times_count_pretimeouts(cbt);
circuit_build_times_add_timeout_worker(cbt, BUILDTIMEOUT_QUANTILE_CUTOFF);
circuit_build_times_add_timeout_worker(cbt,
circuit_build_times_quantile_cutoff());
return 1;
}
@ -875,7 +1006,7 @@ circuit_build_times_add_timeout(circuit_build_times_t *cbt,
void
circuit_build_times_set_timeout(circuit_build_times_t *cbt)
{
if (cbt->total_build_times < MIN_CIRCUITS_TO_OBSERVE) {
if (cbt->total_build_times < circuit_build_times_min_circs_to_observe()) {
return;
}
@ -883,16 +1014,18 @@ circuit_build_times_set_timeout(circuit_build_times_t *cbt)
circuit_build_times_update_alpha(cbt);
cbt->timeout_ms = circuit_build_times_calculate_timeout(cbt,
BUILDTIMEOUT_QUANTILE_CUTOFF);
circuit_build_times_quantile_cutoff());
cbt->have_computed_timeout = 1;
if (cbt->timeout_ms < BUILD_TIMEOUT_MIN_VALUE) {
if (cbt->timeout_ms < circuit_build_times_min_timeout()) {
log_warn(LD_CIRC, "Set buildtimeout to low value %lfms. Setting to %dms",
cbt->timeout_ms, BUILD_TIMEOUT_MIN_VALUE);
cbt->timeout_ms = BUILD_TIMEOUT_MIN_VALUE;
cbt->timeout_ms, circuit_build_times_min_timeout());
cbt->timeout_ms = circuit_build_times_min_timeout();
}
control_event_buildtimeout_set(cbt, BUILDTIMEOUT_SET_EVENT_COMPUTED);
log_info(LD_CIRC,
"Set circuit build timeout to %lds (%lfms, Xm: %d, a: %lf) "
"based on %d circuit times", tor_lround(cbt->timeout_ms/1000),
@ -3296,6 +3429,7 @@ entry_guard_register_connect_status(const char *digest, int succeeded,
"Removing from the list. %d/%d entry guards usable/new.",
entry->nickname, buf,
num_live_entry_guards()-1, smartlist_len(entry_guards)-1);
control_event_guard(entry->nickname, entry->identity, "DROPPED");
entry_guard_free(entry);
smartlist_del_keeporder(entry_guards, idx);
log_entry_guards(LOG_INFO);

View File

@ -43,7 +43,8 @@
#define EVENT_STREAM_BANDWIDTH_USED 0x0014
#define EVENT_CLIENTS_SEEN 0x0015
#define EVENT_NEWCONSENSUS 0x0016
#define _EVENT_MAX 0x0016
#define EVENT_BUILDTIMEOUT_SET 0x0017
#define _EVENT_MAX 0x0017
/* If _EVENT_MAX ever hits 0x0020, we need to make the mask wider. */
/** Bitfield: The bit 1&lt;&lt;e is set if <b>any</b> open control
@ -922,6 +923,8 @@ handle_control_setevents(control_connection_t *conn, uint32_t len,
event_code = EVENT_CLIENTS_SEEN;
else if (!strcasecmp(ev, "NEWCONSENSUS"))
event_code = EVENT_NEWCONSENSUS;
else if (!strcasecmp(ev, "BUILDTIMEOUT_SET"))
event_code = EVENT_BUILDTIMEOUT_SET;
else {
connection_printf_to_buf(conn, "552 Unrecognized event \"%s\"\r\n",
ev);
@ -2000,12 +2003,12 @@ handle_control_getinfo(control_connection_t *conn, uint32_t len,
static uint8_t
circuit_purpose_from_string(const char *string)
{
if (!strcmpstart(string, "purpose="))
if (!strcasecmpstart(string, "purpose="))
string += strlen("purpose=");
if (!strcmp(string, "general"))
if (!strcasecmp(string, "general"))
return CIRCUIT_PURPOSE_C_GENERAL;
else if (!strcmp(string, "controller"))
else if (!strcasecmp(string, "controller"))
return CIRCUIT_PURPOSE_CONTROLLER;
else
return CIRCUIT_PURPOSE_UNKNOWN;
@ -2037,6 +2040,31 @@ getargs_helper(const char *command, control_connection_t *conn,
return NULL;
}
/** Helper. Return the first element of <b>sl</b> at index <b>start_at</b> or
* higher that starts with <b>prefix</b>, case-insensitive. Return NULL if no
* such element exists. */
static const char *
find_element_starting_with(smartlist_t *sl, int start_at, const char *prefix)
{
int i;
for (i = start_at; i < smartlist_len(sl); ++i) {
const char *elt = smartlist_get(sl, i);
if (!strcasecmpstart(elt, prefix))
return elt;
}
return NULL;
}
/** Helper. Return true iff s is an argument that we should treat as a
* key-value pair. */
static int
is_keyval_pair(const char *s)
{
/* An argument is a key-value pair if it has an =, and it isn't of the form
* $fingeprint=name */
return strchr(s, '=') && s[0] != '$';
}
/** Called when we get an EXTENDCIRCUIT message. Try to extend the listed
* circuit, and report success or failure. */
static int
@ -2052,27 +2080,49 @@ handle_control_extendcircuit(control_connection_t *conn, uint32_t len,
router_nicknames = smartlist_create();
args = getargs_helper("EXTENDCIRCUIT", conn, body, 2, -1);
args = getargs_helper("EXTENDCIRCUIT", conn, body, 1, -1);
if (!args)
goto done;
zero_circ = !strcmp("0", (char*)smartlist_get(args,0));
if (zero_circ) {
const char *purp = find_element_starting_with(args, 1, "PURPOSE=");
if (purp) {
intended_purpose = circuit_purpose_from_string(purp);
if (intended_purpose == CIRCUIT_PURPOSE_UNKNOWN) {
connection_printf_to_buf(conn, "552 Unknown purpose \"%s\"\r\n", purp);
SMARTLIST_FOREACH(args, char *, cp, tor_free(cp));
smartlist_free(args);
}
}
if ((smartlist_len(args) == 1) ||
(smartlist_len(args) >= 2 && is_keyval_pair(smartlist_get(args, 1)))) {
// "EXTENDCIRCUIT 0" || EXTENDCIRCUIT 0 foo=bar"
circ = circuit_launch_by_router(intended_purpose, NULL,
CIRCLAUNCH_NEED_CAPACITY);
if (!circ) {
connection_write_str_to_buf("551 Couldn't start circuit\r\n", conn);
} else {
connection_printf_to_buf(conn, "250 EXTENDED %lu\r\n",
(unsigned long)circ->global_identifier);
}
goto done;
}
// "EXTENDCIRCUIT 0 router1,router2" ||
// "EXTENDCIRCUIT 0 router1,router2 PURPOSE=foo"
}
if (!zero_circ && !(circ = get_circ(smartlist_get(args,0)))) {
connection_printf_to_buf(conn, "552 Unknown circuit \"%s\"\r\n",
(char*)smartlist_get(args, 0));
goto done;
}
smartlist_split_string(router_nicknames, smartlist_get(args,1), ",", 0, 0);
if (zero_circ && smartlist_len(args)>2) {
char *purp = smartlist_get(args,2);
intended_purpose = circuit_purpose_from_string(purp);
if (intended_purpose == CIRCUIT_PURPOSE_UNKNOWN) {
connection_printf_to_buf(conn, "552 Unknown purpose \"%s\"\r\n", purp);
SMARTLIST_FOREACH(args, char *, cp, tor_free(cp));
smartlist_free(args);
goto done;
}
}
SMARTLIST_FOREACH(args, char *, cp, tor_free(cp));
smartlist_free(args);
if (!zero_circ && !circ) {
@ -2162,7 +2212,7 @@ handle_control_setcircuitpurpose(control_connection_t *conn,
}
{
char *purp = smartlist_get(args,1);
const char *purp = find_element_starting_with(args,1,"PURPOSE=");
new_purpose = circuit_purpose_from_string(purp);
if (new_purpose == CIRCUIT_PURPOSE_UNKNOWN) {
connection_printf_to_buf(conn, "552 Unknown purpose \"%s\"\r\n", purp);
@ -2207,9 +2257,9 @@ handle_control_attachstream(control_connection_t *conn, uint32_t len,
} else if (!zero_circ && !(circ = get_circ(smartlist_get(args, 1)))) {
connection_printf_to_buf(conn, "552 Unknown circuit \"%s\"\r\n",
(char*)smartlist_get(args, 1));
} else if (circ && smartlist_len(args) > 2) {
char *hopstring = smartlist_get(args, 2);
if (!strcasecmpstart(hopstring, "HOP=")) {
} else if (circ) {
const char *hopstring = find_element_starting_with(args,2,"HOP=");
if (hopstring) {
hopstring += strlen("HOP=");
hop = (int) tor_parse_ulong(hopstring, 10, 0, INT_MAX,
&hop_line_ok, NULL);
@ -2317,9 +2367,9 @@ handle_control_postdescriptor(control_connection_t *conn, uint32_t len,
}
} else if (!strcasecmpstart(option, "cache=")) {
option += strlen("cache=");
if (!strcmp(option, "no"))
if (!strcasecmp(option, "no"))
cache = 0;
else if (!strcmp(option, "yes"))
else if (!strcasecmp(option, "yes"))
cache = 1;
else {
connection_printf_to_buf(conn, "552 Unknown cache request \"%s\"\r\n",
@ -2501,17 +2551,17 @@ handle_control_resolve(control_connection_t *conn, uint32_t len,
args = smartlist_create();
smartlist_split_string(args, body, " ",
SPLIT_SKIP_SPACE|SPLIT_IGNORE_BLANK, 0);
if (smartlist_len(args) &&
!strcasecmp(smartlist_get(args, 0), "mode=reverse")) {
char *cp = smartlist_get(args, 0);
smartlist_del_keeporder(args, 0);
tor_free(cp);
is_reverse = 1;
{
const char *modearg = find_element_starting_with(args, 0, "mode=");
if (modearg && !strcasecmp(modearg, "mode=reverse"))
is_reverse = 1;
}
failed = smartlist_create();
SMARTLIST_FOREACH(args, const char *, arg, {
if (dnsserv_launch_request(arg, is_reverse)<0)
smartlist_add(failed, (char*)arg);
if (!is_keyval_pair(arg)) {
if (dnsserv_launch_request(arg, is_reverse)<0)
smartlist_add(failed, (char*)arg);
}
});
send_control_done(conn);
@ -3440,6 +3490,51 @@ control_event_newconsensus(const networkstatus_t *consensus)
consensus->routerstatus_list, EVENT_NEWCONSENSUS, "NEWCONSENSUS");
}
/** Called when we compute a new circuitbuildtimeout */
int
control_event_buildtimeout_set(const circuit_build_times_t *cbt,
buildtimeout_set_event_t type)
{
const char *type_string = NULL;
double qnt = circuit_build_times_quantile_cutoff();
if (!control_event_is_interesting(EVENT_BUILDTIMEOUT_SET))
return 0;
switch (type) {
case BUILDTIMEOUT_SET_EVENT_COMPUTED:
type_string = "COMPUTED";
break;
case BUILDTIMEOUT_SET_EVENT_RESET:
type_string = "RESET";
qnt = 1.0;
break;
case BUILDTIMEOUT_SET_EVENT_SUSPENDED:
type_string = "SUSPENDED";
qnt = 1.0;
break;
case BUILDTIMEOUT_SET_EVENT_DISCARD:
type_string = "DISCARD";
qnt = 1.0;
break;
case BUILDTIMEOUT_SET_EVENT_RESUME:
type_string = "RESUME";
break;
default:
type_string = "UNKNOWN";
break;
}
send_control_event(EVENT_BUILDTIMEOUT_SET, ALL_FORMATS,
"650 BUILDTIMEOUT_SET %s TOTAL_TIMES=%lu "
"TIMEOUT_MS=%lu XM=%lu ALPHA=%lf CUTOFF_QUANTILE=%lf\r\n",
type_string, (unsigned long)cbt->total_build_times,
(unsigned long)cbt->timeout_ms,
(unsigned long)cbt->Xm, cbt->alpha, qnt);
return 0;
}
/** Called when a single local_routerstatus_t has changed: Sends an NS event
* to any controller that cares. */
int

View File

@ -1680,6 +1680,7 @@ networkstatus_set_current_consensus(const char *consensus,
dirvote_recalculate_timing(get_options(), now);
routerstatus_list_update_named_server_map();
cell_ewma_set_scale_factor(get_options(), current_consensus);
circuit_build_times_new_consensus_params(&circ_times, current_consensus);
}
if (!from_cache) {

View File

@ -3002,49 +3002,27 @@ void entry_guards_free_all(void);
/* Circuit Build Timeout "public" functions and structures. */
/** Total size of the circuit timeout history to accumulate.
* 1000 is approx 2.5 days worth of continual-use circuits. */
#define CBT_NCIRCUITS_TO_OBSERVE 1000
/** Maximum quantile to use to generate synthetic timeouts.
* We want to stay a bit short of 1.0, because longtail is
* loooooooooooooooooooooooooooooooooooooooooooooooooooong. */
#define MAX_SYNTHETIC_QUANTILE 0.985
/** Minimum circuits before estimating a timeout */
#define MIN_CIRCUITS_TO_OBSERVE 500
/** Total size of the circuit timeout history to accumulate.
* 5000 is approx 1.5 weeks worth of continual-use circuits. */
#define NCIRCUITS_TO_OBSERVE 5000
#define CBT_MAX_SYNTHETIC_QUANTILE 0.985
/** Width of the histogram bins in milliseconds */
#define BUILDTIME_BIN_WIDTH ((build_time_t)50)
/** Cutoff point on the CDF for our timeout estimation.
* TODO: This should be moved to the consensus */
#define BUILDTIMEOUT_QUANTILE_CUTOFF 0.8
#define CBT_BIN_WIDTH ((build_time_t)50)
/** A build_time_t is milliseconds */
typedef uint32_t build_time_t;
#define BUILD_TIME_MAX ((build_time_t)(INT32_MAX))
/** Lowest allowable value for CircuitBuildTimeout in milliseconds */
#define BUILD_TIMEOUT_MIN_VALUE (3*1000)
/** Initial circuit build timeout in milliseconds */
#define BUILD_TIMEOUT_INITIAL_VALUE (60*1000)
/** How often in seconds should we build a test circuit */
#define BUILD_TIMES_TEST_FREQUENCY 60
#define CBT_BUILD_TIME_MAX ((build_time_t)(INT32_MAX))
/** Save state every 10 circuits */
#define BUILD_TIMES_SAVE_STATE_EVERY 10
#define CBT_SAVE_STATE_EVERY 10
/* Circuit Build Timeout network liveness constants */
/**
* How many circuits count as recent when considering if the
* connection has gone gimpy or changed.
*/
#define RECENT_CIRCUITS 20
/**
* Have we received a cell in the last N circ attempts?
*
@ -3053,7 +3031,7 @@ typedef uint32_t build_time_t;
* at which point we switch back to computing the timeout from
* our saved history.
*/
#define NETWORK_NONLIVE_TIMEOUT_COUNT (RECENT_CIRCUITS*3/20)
#define CBT_NETWORK_NONLIVE_TIMEOUT_COUNT (3)
/**
* This tells us when to toss out the last streak of N timeouts.
@ -3061,7 +3039,15 @@ typedef uint32_t build_time_t;
* If instead we start getting cells, we switch back to computing the timeout
* from our saved history.
*/
#define NETWORK_NONLIVE_DISCARD_COUNT (NETWORK_NONLIVE_TIMEOUT_COUNT*2)
#define CBT_NETWORK_NONLIVE_DISCARD_COUNT (CBT_NETWORK_NONLIVE_TIMEOUT_COUNT*2)
/* Circuit build times consensus parameters */
/**
* How many circuits count as recent when considering if the
* connection has gone gimpy or changed.
*/
#define CBT_DEFAULT_RECENT_CIRCUITS 20
/**
* Maximum count of timeouts that finish the first hop in the past
@ -3070,10 +3056,28 @@ typedef uint32_t build_time_t;
* This tells us to abandon timeout history and set
* the timeout back to BUILD_TIMEOUT_INITIAL_VALUE.
*/
#define MAX_RECENT_TIMEOUT_COUNT (RECENT_CIRCUITS*4/5)
#define CBT_DEFAULT_MAX_RECENT_TIMEOUT_COUNT (CBT_DEFAULT_RECENT_CIRCUITS*9/10)
#if MAX_RECENT_TIMEOUT_COUNT < 1 || NETWORK_NONLIVE_DISCARD_COUNT < 1 || \
NETWORK_NONLIVE_TIMEOUT_COUNT < 1
/** Minimum circuits before estimating a timeout */
#define CBT_DEFAULT_MIN_CIRCUITS_TO_OBSERVE 100
/** Cutoff percentile on the CDF for our timeout estimation. */
#define CBT_DEFAULT_QUANTILE_CUTOFF 80
double circuit_build_times_quantile_cutoff(void);
/** How often in seconds should we build a test circuit */
#define CBT_DEFAULT_TEST_FREQUENCY 60
/** Lowest allowable value for CircuitBuildTimeout in milliseconds */
#define CBT_DEFAULT_TIMEOUT_MIN_VALUE (2*1000)
/** Initial circuit build timeout in milliseconds */
#define CBT_DEFAULT_TIMEOUT_INITIAL_VALUE (60*1000)
int32_t circuit_build_times_initial_timeout(void);
#if CBT_DEFAULT_MAX_RECENT_TIMEOUT_COUNT < 1 || \
CBT_NETWORK_NONLIVE_DISCARD_COUNT < 1 || \
CBT_NETWORK_NONLIVE_TIMEOUT_COUNT < 1
#error "RECENT_CIRCUITS is set too low."
#endif
@ -3087,18 +3091,22 @@ typedef struct {
int nonlive_discarded;
/** Circular array of circuits that have made it to the first hop. Slot is
* 1 if circuit timed out, 0 if circuit succeeded */
int8_t timeouts_after_firsthop[RECENT_CIRCUITS];
int8_t *timeouts_after_firsthop;
/** Number of elements allocated for the above array */
int num_recent_circs;
/** Index into circular array. */
int after_firsthop_idx;
/** The network is not live. Timeout gathering is suspended */
int net_suspended;
} network_liveness_t;
/** Structure for circuit build times history */
typedef struct {
/** The circular array of recorded build times in milliseconds */
build_time_t circuit_build_times[NCIRCUITS_TO_OBSERVE];
build_time_t circuit_build_times[CBT_NCIRCUITS_TO_OBSERVE];
/** Current index in the circuit_build_times circular array */
int build_times_idx;
/** Total number of build times accumulated. Maxes at NCIRCUITS_TO_OBSERVE */
/** Total number of build times accumulated. Max CBT_NCIRCUITS_TO_OBSERVE */
int total_build_times;
/** Information about the state of our local network connection */
network_liveness_t liveness;
@ -3130,6 +3138,8 @@ int circuit_build_times_add_time(circuit_build_times_t *cbt,
int circuit_build_times_needs_circuits(circuit_build_times_t *cbt);
int circuit_build_times_needs_circuits_now(circuit_build_times_t *cbt);
void circuit_build_times_init(circuit_build_times_t *cbt);
void circuit_build_times_new_consensus_params(circuit_build_times_t *cbt,
networkstatus_t *ns);
#ifdef CIRCUIT_PRIVATE
double circuit_build_times_calculate_timeout(circuit_build_times_t *cbt,
@ -3583,6 +3593,15 @@ typedef enum or_conn_status_event_t {
OR_CONN_EVENT_NEW = 4,
} or_conn_status_event_t;
/** Used to indicate the type of a buildtime event */
typedef enum buildtimeout_set_event_t {
BUILDTIMEOUT_SET_EVENT_COMPUTED = 0,
BUILDTIMEOUT_SET_EVENT_RESET = 1,
BUILDTIMEOUT_SET_EVENT_SUSPENDED = 2,
BUILDTIMEOUT_SET_EVENT_DISCARD = 3,
BUILDTIMEOUT_SET_EVENT_RESUME = 4
} buildtimeout_set_event_t;
void control_update_global_event_mask(void);
void control_adjust_event_log_severity(void);
@ -3648,6 +3667,8 @@ int control_event_server_status(int severity, const char *format, ...)
CHECK_PRINTF(2,3);
int control_event_guard(const char *nickname, const char *digest,
const char *status);
int control_event_buildtimeout_set(const circuit_build_times_t *cbt,
buildtimeout_set_event_t type);
int init_cookie_authentication(int enabled);
smartlist_t *decode_hashed_passwords(config_line_t *passwords);

View File

@ -479,11 +479,12 @@ test_circuit_timeout(void)
circuitbuild_running_unit_tests();
#define timeout0 (build_time_t)(30*1000.0)
initial.Xm = 750;
circuit_build_times_initial_alpha(&initial, BUILDTIMEOUT_QUANTILE_CUTOFF,
circuit_build_times_initial_alpha(&initial,
CBT_DEFAULT_QUANTILE_CUTOFF/100.0,
timeout0);
do {
int n = 0;
for (i=0; i < MIN_CIRCUITS_TO_OBSERVE; i++) {
for (i=0; i < CBT_DEFAULT_MIN_CIRCUITS_TO_OBSERVE; i++) {
if (circuit_build_times_add_time(&estimate,
circuit_build_times_generate_sample(&initial, 0, 1)) == 0) {
n++;
@ -491,23 +492,23 @@ test_circuit_timeout(void)
}
circuit_build_times_update_alpha(&estimate);
timeout1 = circuit_build_times_calculate_timeout(&estimate,
BUILDTIMEOUT_QUANTILE_CUTOFF);
CBT_DEFAULT_QUANTILE_CUTOFF/100.0);
circuit_build_times_set_timeout(&estimate);
log_warn(LD_CIRC, "Timeout is %lf, Xm is %d", timeout1, estimate.Xm);
/* XXX: 5% distribution error may not be the right metric */
} while (fabs(circuit_build_times_cdf(&initial, timeout0) -
circuit_build_times_cdf(&initial, timeout1)) > 0.05
/* 5% error */
&& estimate.total_build_times < NCIRCUITS_TO_OBSERVE);
&& estimate.total_build_times < CBT_NCIRCUITS_TO_OBSERVE);
test_assert(estimate.total_build_times < NCIRCUITS_TO_OBSERVE);
test_assert(estimate.total_build_times < CBT_NCIRCUITS_TO_OBSERVE);
circuit_build_times_update_state(&estimate, &state);
test_assert(circuit_build_times_parse_state(&final, &state, &msg) == 0);
circuit_build_times_update_alpha(&final);
timeout2 = circuit_build_times_calculate_timeout(&final,
BUILDTIMEOUT_QUANTILE_CUTOFF);
CBT_DEFAULT_QUANTILE_CUTOFF/100.0);
circuit_build_times_set_timeout(&final);
log_warn(LD_CIRC, "Timeout is %lf, Xm is %d", timeout2, final.Xm);
@ -519,19 +520,19 @@ test_circuit_timeout(void)
int build_times_idx = 0;
int total_build_times = 0;
final.timeout_ms = BUILD_TIMEOUT_INITIAL_VALUE;
estimate.timeout_ms = BUILD_TIMEOUT_INITIAL_VALUE;
final.timeout_ms = CBT_DEFAULT_TIMEOUT_INITIAL_VALUE;
estimate.timeout_ms = CBT_DEFAULT_TIMEOUT_INITIAL_VALUE;
for (i = 0; i < RECENT_CIRCUITS*2; i++) {
for (i = 0; i < CBT_DEFAULT_RECENT_CIRCUITS*2; i++) {
circuit_build_times_network_circ_success(&estimate);
circuit_build_times_add_time(&estimate,
circuit_build_times_generate_sample(&estimate, 0,
BUILDTIMEOUT_QUANTILE_CUTOFF));
CBT_DEFAULT_QUANTILE_CUTOFF/100.0));
estimate.have_computed_timeout = 1;
circuit_build_times_network_circ_success(&estimate);
circuit_build_times_add_time(&final,
circuit_build_times_generate_sample(&final, 0,
BUILDTIMEOUT_QUANTILE_CUTOFF));
CBT_DEFAULT_QUANTILE_CUTOFF/100.0));
final.have_computed_timeout = 1;
}
@ -544,7 +545,7 @@ test_circuit_timeout(void)
build_times_idx = estimate.build_times_idx;
total_build_times = estimate.total_build_times;
for (i = 0; i < NETWORK_NONLIVE_TIMEOUT_COUNT; i++) {
for (i = 0; i < CBT_NETWORK_NONLIVE_TIMEOUT_COUNT; i++) {
test_assert(circuit_build_times_network_check_live(&estimate));
test_assert(circuit_build_times_network_check_live(&final));
@ -559,12 +560,12 @@ test_circuit_timeout(void)
test_assert(!circuit_build_times_network_check_live(&estimate));
test_assert(!circuit_build_times_network_check_live(&final));
for ( ; i < NETWORK_NONLIVE_DISCARD_COUNT; i++) {
for ( ; i < CBT_NETWORK_NONLIVE_DISCARD_COUNT; i++) {
if (circuit_build_times_add_timeout(&estimate, 0,
(time_t)(approx_time()-estimate.timeout_ms/1000.0-1)))
estimate.have_computed_timeout = 1;
if (i < NETWORK_NONLIVE_DISCARD_COUNT-1) {
if (i < CBT_NETWORK_NONLIVE_DISCARD_COUNT-1) {
if (circuit_build_times_add_timeout(&final, 0,
(time_t)(approx_time()-final.timeout_ms/1000.0-1)))
final.have_computed_timeout = 1;
@ -587,11 +588,11 @@ test_circuit_timeout(void)
circuit_build_times_network_is_live(&estimate);
circuit_build_times_network_is_live(&final);
for (i = 0; i < MAX_RECENT_TIMEOUT_COUNT; i++) {
for (i = 0; i < CBT_DEFAULT_MAX_RECENT_TIMEOUT_COUNT; i++) {
if (circuit_build_times_add_timeout(&estimate, 1, approx_time()-1))
estimate.have_computed_timeout = 1;
if (i < MAX_RECENT_TIMEOUT_COUNT-1) {
if (i < CBT_DEFAULT_MAX_RECENT_TIMEOUT_COUNT-1) {
if (circuit_build_times_add_timeout(&final, 1, approx_time()-1))
final.have_computed_timeout = 1;
}
@ -599,7 +600,7 @@ test_circuit_timeout(void)
test_assert(estimate.liveness.after_firsthop_idx == 0);
test_assert(final.liveness.after_firsthop_idx ==
MAX_RECENT_TIMEOUT_COUNT-1);
CBT_DEFAULT_MAX_RECENT_TIMEOUT_COUNT-1);
test_assert(circuit_build_times_network_check_live(&estimate));
test_assert(circuit_build_times_network_check_live(&final));