26 #define CIRCUITSTATS_PRIVATE
57 #define CBT_BIN_TO_MS(bin) ((bin)*CBT_BIN_WIDTH + (CBT_BIN_WIDTH/2))
70 static int unit_tests = 0;
125 int ignore_consensus)
130 int consensus_disabled =
148 int single_onion_disabled = hs_service_allow_non_anonymous_connection(
151 if (consensus_disabled || config_disabled || dirauth_disabled ||
152 state_disabled || single_onion_disabled) {
155 "CircuitBuildTime learning is disabled. "
156 "Consensus=%d, Config=%d, AuthDir=%d, StateFile=%d",
157 consensus_disabled, config_disabled, dirauth_disabled,
164 "CircuitBuildTime learning is not disabled. "
165 "Consensus=%d, Config=%d, AuthDir=%d, StateFile=%d",
166 consensus_disabled, config_disabled, dirauth_disabled,
184 int32_t cbt_maxtimeouts;
188 CBT_MIN_MAX_RECENT_TIMEOUT_COUNT,
189 CBT_MAX_MAX_RECENT_TIMEOUT_COUNT);
193 "circuit_build_times_max_timeouts() called, cbtmaxtimeouts is"
198 return cbt_maxtimeouts;
215 CBT_MIN_NUM_XM_MODES,
216 CBT_MAX_NUM_XM_MODES);
220 "circuit_build_times_default_num_xm_modes() called, cbtnummodes"
239 CBT_MIN_MIN_CIRCUITS_TO_OBSERVE,
240 CBT_MAX_MIN_CIRCUITS_TO_OBSERVE);
244 "circuit_build_times_min_circs_to_observe() called, cbtmincircs"
271 CBT_MIN_QUANTILE_CUTOFF,
272 CBT_MAX_QUANTILE_CUTOFF);
276 "circuit_build_times_quantile_cutoff() called, cbtquantile"
299 CBT_MIN_CLOSE_QUANTILE,
300 CBT_MAX_CLOSE_QUANTILE);
304 "circuit_build_times_close_quantile() called, cbtclosequantile"
309 log_warn(
LD_DIR,
"Consensus parameter cbtclosequantile is "
310 "too small, raising to %d", min);
313 return param / 100.0;
328 CBT_MIN_TEST_FREQUENCY,
329 CBT_MAX_TEST_FREQUENCY);
333 "circuit_build_times_test_frequency() called, cbttestfreq is %d",
352 CBT_MIN_TIMEOUT_MIN_VALUE,
353 CBT_MAX_TIMEOUT_MIN_VALUE);
357 "circuit_build_times_min_timeout() called, cbtmintimeout is %d",
375 CBT_MIN_TIMEOUT_INITIAL_VALUE,
376 CBT_MAX_TIMEOUT_INITIAL_VALUE);
380 "circuit_build_times_initial_timeout() called, "
381 "cbtinitialtimeout is %d",
386 log_warn(
LD_DIR,
"Consensus parameter cbtinitialtimeout is too small, "
387 "raising to %d", min);
406 CBT_MIN_RECENT_CIRCUITS,
407 CBT_MAX_RECENT_CIRCUITS);
411 "circuit_build_times_recent_circuit_count() called, "
412 "cbtrecentcount is %d",
441 int8_t *recent_circs;
443 log_notice(
LD_CIRC,
"The Tor Directory Consensus has changed how "
444 "many circuits we must track to detect network failures "
447 log_notice(
LD_CIRC,
"Upon receiving a consensus directory, "
448 "re-enabling circuit-based network failure detection.");
466 recent_circs = tor_calloc(num,
sizeof(int8_t));
474 if (num < cbt->liveness.num_recent_circs) {
491 "The cbtrecentcircs consensus parameter came back zero! "
492 "This disables adaptive timeouts since we can't keep track of "
493 "any recent circuits.");
527 log_warn(
LD_CIRC,
"Config CircuitBuildTimeout too low. Setting to %ds",
567 memset(cbt, 0,
sizeof(*cbt));
582 cbt_control_event_buildtimeout_set(cbt, BUILDTIMEOUT_SET_EVENT_RESET);
614 for (i = 0; i < n; i++) {
626 "Rewound history by %d places. Current index: %d. "
641 END_CIRC_REASON_TIMEOUT);
651 int first_hop_succeeded = circ->
cpath &&
656 first_hop_succeeded);
712 "Deciding to timeout circuit %"PRIu32
"\n",
727 log_notice(
LD_CIRC,
"Strange value for circuit build time: %ldmsec. "
728 "Assuming clock jump. Purpose %d (%s)", timediff,
758 if (btime <= 0 || btime > CBT_BUILD_TIME_MAX) {
759 log_warn(
LD_BUG,
"Circuit build time is too large (%u)."
760 "This is probably a bug.", btime);
765 log_debug(
LD_CIRC,
"Adding circuit build time %u", btime);
794 return max_build_time;
809 if (min_build_time == CBT_BUILD_TIME_MAX) {
810 log_warn(
LD_CIRC,
"No build times less than CBT_BUILD_TIME_MAX!");
812 return min_build_time;
872 nth_max_bin = tor_calloc(num_modes,
sizeof(
build_time_t));
876 for (
int n = 0; n < num_modes; n++) {
879 if (histogram[i] > histogram[nth_max_bin[n]]) {
885 xm_counts += histogram[nth_max_bin[n]];
886 xm_total += CBT_BIN_TO_MS(nth_max_bin[n])*histogram[nth_max_bin[n]];
889 histogram[nth_max_bin[n]] = 0;
895 if (xm_counts == 0) {
897 "No valid circuit build time data out of %d times, %u modes, "
903 Xm = xm_total / xm_counts;
932 state->CircuitBuildAbandonedCount = 0;
936 state->CircuitBuildAbandonedCount++;
939 for (i = 0; i < nbins; i++) {
941 if (histogram[i] == 0)
continue;
943 line->key = tor_strdup(
"CircuitBuildTimeBin");
945 CBT_BIN_TO_MS(i), histogram[i]);
946 next = &(line->next);
967 uint32_t n = num_times;
969 log_notice(
LD_CIRC,
"The number of circuit times that this Tor version "
970 "uses to calculate build times is less than the number stored "
971 "in your state file. Decreasing the circuit time history from "
972 "%lu to %d.", (
unsigned long)num_times,
977 log_warn(
LD_CIRC,
"For some insane reasons, you had %lu circuit build "
978 "observations in your state file. That's far too many; probably "
979 "there's a bug here.", (
unsigned long)n);
987 raw_times[k] = raw_times[n];
1010 uint32_t loaded_cnt = 0, N = 0;
1022 loaded_times = tor_calloc(state->TotalBuildTimes,
sizeof(
build_time_t));
1027 SPLIT_SKIP_SPACE|SPLIT_IGNORE_BLANK, 0);
1028 if (smartlist_len(args) < 2) {
1029 log_warn(
LD_GENERAL,
"Unable to parse circuit build times: "
1030 "Too few arguments to CircuitBuildTime");
1033 smartlist_free(args);
1036 const char *ms_str = smartlist_get(args,0);
1037 const char *count_str = smartlist_get(args,1);
1042 CBT_BUILD_TIME_MAX, &ok, NULL);
1044 log_warn(
LD_GENERAL,
"Unable to parse circuit build times: "
1045 "Unparsable bin number");
1048 smartlist_free(args);
1052 UINT32_MAX, &ok, NULL);
1054 log_warn(
LD_GENERAL,
"Unable to parse circuit build times: "
1055 "Unparsable bin count");
1058 smartlist_free(args);
1062 if (loaded_cnt+count+ (
unsigned)state->CircuitBuildAbandonedCount
1063 > (
unsigned) state->TotalBuildTimes) {
1065 "Too many build times in state file. "
1066 "Stopping short before %d",
1069 smartlist_free(args);
1073 for (k = 0; k < count; k++) {
1074 loaded_times[loaded_cnt++] = ms;
1078 smartlist_free(args);
1083 "Adding %d timeouts.", state->CircuitBuildAbandonedCount);
1084 for (i=0; i < state->CircuitBuildAbandonedCount; i++) {
1088 if (loaded_cnt != (
unsigned)state->TotalBuildTimes) {
1090 "Corrupt state file? Build times count mismatch. "
1091 "Read %d times, but file says %d", loaded_cnt,
1092 state->TotalBuildTimes);
1107 "Loaded %d/%d values from %d lines in circuit time histogram",
1113 "Corrupt state file? Shuffled build times mismatch. "
1114 "Read %d times, but file says %d", tot_values,
1115 state->TotalBuildTimes);
1125 return err ? -1 : 0;
1142 int n=0,i=0,abandoned_count=0;
1160 if (x[i] < cbt->
Xm) {
1178 log_err(
LD_CIRC,
"Discrepancy in build times count: %d vs %d", n,
1232 if (cbt->
alpha > 0) {
1234 p = pow(1.0-quantile,1.0/cbt->
alpha);
1240 if (ret > INT32_MAX) {
1247 #ifdef TOR_UNIT_TESTS
1254 ret = 1.0-pow(cbt->
Xm/x,cbt->
alpha);
1260 #ifdef TOR_UNIT_TESTS
1269 double q_lo,
double q_hi)
1278 q_hi -= 1.0/(INT32_MAX);
1284 u = q_lo + (q_hi-q_lo)*randval;
1295 #ifdef TOR_UNIT_TESTS
1302 double quantile,
double timeout_ms)
1343 #define CIRCUIT_TIMEOUT_BEFORE_RECHECK_IP (60*3)
1363 "Tor now sees network activity. Restoring circuit build "
1364 "timeout recording. Network was down for %d seconds "
1365 "during %d circuit attempts.",
1366 (
int)time_since_live,
1472 int did_onehop, time_t start_time)
1474 time_t now = time(NULL);
1490 char last_live_buf[ISO_TIME_LEN+1];
1491 char start_time_buf[ISO_TIME_LEN+1];
1492 char now_buf[ISO_TIME_LEN+1];
1497 "A circuit somehow completed a hop while the network was "
1498 "not live. The network was last live at %s, but the circuit "
1499 "launched at %s. It's now %s. This could mean your clock "
1500 "changed.", last_live_buf, start_time_buf, now_buf);
1505 "Tor has not observed any network activity for the past %d "
1506 "seconds. Disabling circuit build timeout recording.",
1513 "Got non-live timeout. Current count is: %d",
1553 int timeout_count=0;
1580 #define MAX_TIMEOUT ((int32_t) (INT32_MAX/2))
1585 log_warn(
LD_CIRC,
"Insanely large circuit build timeout value. "
1586 "(timeout = %fmsec, close = %fmsec)",
1598 cbt_control_event_buildtimeout_set(cbt, BUILDTIMEOUT_SET_EVENT_RESET);
1601 "Your network connection speed appears to have changed. Resetting "
1602 "timeout to %ldms after %d timeouts and %d buildtimes.",
1726 "Circuit build timeout of %dms is beyond the maximum build "
1727 "time we have ever observed. Capping it to %dms.",
1732 if (max_time < INT32_MAX/2 && cbt->close_ms > 2*max_time) {
1734 "Circuit build measurement period of %dms is more than twice "
1735 "the maximum build time we have ever observed. Capping it to "
1736 "%dms.", (
int)cbt->
close_ms, 2*max_time);
1757 double timeout_rate;
1769 log_notice(
LD_CIRC,
"Set buildtimeout to low value %fms. Setting to %dms",
1779 cbt_control_event_buildtimeout_set(cbt, BUILDTIMEOUT_SET_EVENT_COMPUTED);
1785 "Based on %d circuit times, it looks like we don't need to "
1786 "wait so long for circuits to finish. We will now assume a "
1787 "circuit is too slow to use after waiting %ld milliseconds.",
1791 "Circuit timeout data: %fms, %fms, Xm: %d, a: %f, r: %f",
1796 "Based on %d circuit times, it looks like we need to wait "
1797 "longer for circuits to finish. We will now assume a "
1798 "circuit is too slow to use after waiting %ld milliseconds.",
1802 "Circuit timeout data: %fms, %fms, Xm: %d, a: %f, r: %f",
1807 "Set circuit build timeout to %ldms (%fms, %fms, Xm: %d, a: %f,"
1808 " r: %f) based on %d circuit times",
1815 #ifdef TOR_UNIT_TESTS
1819 circuitbuild_running_unit_tests(
void)
int authdir_mode(const or_options_t *options)
Header file for directory authority mode.
int circuit_timeout_want_to_count_circ(const origin_circuit_t *circ)
Header file for circuitbuild.c.
int circuit_any_opened_circuits_cached(void)
const char * circuit_purpose_to_string(uint8_t purpose)
int circuit_get_cpath_opened_len(const origin_circuit_t *circ)
int circuit_event_status(origin_circuit_t *circ, circuit_status_event_t tp, int reason_code)
Header file for circuitlist.c.
#define CIRCUIT_PURPOSE_C_MEASURE_TIMEOUT
int circuit_build_times_needs_circuits_now(const circuit_build_times_t *cbt)
void circuit_build_times_free_timeouts(circuit_build_times_t *cbt)
#define CIRCUIT_TIMEOUT_BEFORE_RECHECK_IP
void circuit_build_times_network_is_live(circuit_build_times_t *cbt)
void circuit_build_times_handle_completed_hop(origin_circuit_t *circ)
void circuit_build_times_set_timeout(circuit_build_times_t *cbt)
double get_circuit_build_timeout_ms(void)
STATIC double circuit_build_times_calculate_timeout(circuit_build_times_t *cbt, double quantile)
int circuit_build_times_parse_state(circuit_build_times_t *cbt, or_state_t *state)
int circuit_build_times_network_check_live(const circuit_build_times_t *cbt)
STATIC int circuit_build_times_network_check_changed(circuit_build_times_t *cbt)
static uint32_t * circuit_build_times_create_histogram(const circuit_build_times_t *cbt, build_time_t *nbins)
int circuit_build_times_disabled_(const or_options_t *options, int ignore_consensus)
void circuit_build_times_count_timeout(circuit_build_times_t *cbt, int did_onehop)
static void circuit_build_times_shuffle_and_store_array(circuit_build_times_t *cbt, build_time_t *raw_times, uint32_t num_times)
const circuit_build_times_t * get_circuit_build_times(void)
double get_circuit_build_close_time_ms(void)
void circuit_build_times_new_consensus_params(circuit_build_times_t *cbt, const networkstatus_t *ns)
double circuit_build_times_timeout_rate(const circuit_build_times_t *cbt)
void circuit_build_times_update_state(const circuit_build_times_t *cbt, or_state_t *state)
void circuit_build_times_mark_circ_as_measurement_only(origin_circuit_t *circ)
void circuit_build_times_init(circuit_build_times_t *cbt)
int32_t circuit_build_times_initial_timeout(void)
STATIC build_time_t circuit_build_times_get_xm(circuit_build_times_t *cbt)
void circuit_build_times_network_circ_success(circuit_build_times_t *cbt)
static circuit_build_times_t circ_times
STATIC int circuit_build_times_update_alpha(circuit_build_times_t *cbt)
static void circuit_build_times_scale_circ_counts(circuit_build_times_t *cbt)
static build_time_t circuit_build_times_max(const circuit_build_times_t *cbt)
static int32_t circuit_build_times_recent_circuit_count(const networkstatus_t *ns)
static void circuit_build_times_network_timeout(circuit_build_times_t *cbt, int did_onehop)
int circuit_build_times_enough_to_compute(const circuit_build_times_t *cbt)
static int32_t circuit_build_times_min_circs_to_observe(void)
int circuit_build_times_count_close(circuit_build_times_t *cbt, int did_onehop, time_t start_time)
int circuit_build_times_disabled(const or_options_t *options)
static double circuit_build_times_close_quantile(void)
circuit_build_times_t * get_circuit_build_times_mutable(void)
double circuit_build_times_quantile_cutoff(void)
static void circuit_build_times_network_close(circuit_build_times_t *cbt, int did_onehop, time_t start_time)
static int32_t circuit_build_times_test_frequency(void)
static int32_t circuit_build_times_max_timeouts(void)
void circuit_build_times_reset(circuit_build_times_t *cbt)
static int32_t circuit_build_times_default_num_xm_modes(void)
static int circuit_build_times_set_timeout_worker(circuit_build_times_t *cbt)
int circuit_build_times_add_time(circuit_build_times_t *cbt, build_time_t btime)
static double circuit_build_times_get_initial_timeout(void)
static int32_t circuit_build_times_min_timeout(void)
double circuit_build_times_close_rate(const circuit_build_times_t *cbt)
int circuit_build_times_needs_circuits(const circuit_build_times_t *cbt)
Header file for circuitstats.c.
#define CBT_NCIRCUITS_TO_OBSERVE
#define CBT_DEFAULT_CLOSE_QUANTILE
#define CBT_SAVE_STATE_EVERY
#define CBT_BUILD_ABANDONED
#define CBT_DEFAULT_TIMEOUT_INITIAL_VALUE
#define CBT_DEFAULT_MIN_CIRCUITS_TO_OBSERVE
#define CBT_DEFAULT_TEST_FREQUENCY
#define CBT_DEFAULT_MAX_RECENT_TIMEOUT_COUNT
#define CBT_DEFAULT_TIMEOUT_MIN_VALUE
#define CBT_DEFAULT_NUM_XM_MODES
#define CBT_DEFAULT_RECENT_CIRCUITS
#define CBT_DEFAULT_QUANTILE_CUTOFF
void circuit_change_purpose(circuit_t *circ, uint8_t new_purpose)
Header file for circuituse.c.
const or_options_t * get_options(void)
Header file for config.c.
int control_event_network_liveness_update(int liveness)
Header file for control_events.c.
Path structures for origin circuits.
Common functions for using (pseudo-)random number generators.
double crypto_rand_double(void)
int crypto_rand_int(unsigned int max)
double tor_mathlog(double d)
long tor_lround(double d)
Header file containing service data for the HS subsystem.
Header file for mainloop.c.
int32_t networkstatus_get_param(const networkstatus_t *ns, const char *param_name, int32_t default_val, int32_t min_val, int32_t max_val)
Header file for networkstatus.c.
Master header file for Tor-specific functionality.
#define DEFAULT_ROUTE_LEN
The or_state_t structure, which represents Tor's state file.
Origin circuit structure.
unsigned long tor_parse_ulong(const char *s, int base, unsigned long min, unsigned long max, int *ok, char **next)
int tor_asprintf(char **strp, const char *fmt,...)
void reschedule_descriptor_update_check(void)
Header for feature/relay/relay_periodic.c.
Header file for router.c.
smartlist_t * smartlist_new(void)
#define SMARTLIST_FOREACH(sl, type, var, cmd)
int smartlist_split_string(smartlist_t *sl, const char *str, const char *sep, int flags, int max)
or_state_t * get_or_state(void)
void or_state_mark_dirty(or_state_t *state, time_t when)
int did_last_state_file_write_fail(void)
int have_computed_timeout
uint32_t num_circ_timeouts
uint32_t num_circ_succeeded
build_time_t circuit_build_times[CBT_NCIRCUITS_TO_OBSERVE]
network_liveness_t liveness
struct timeval timestamp_began
int8_t * timeouts_after_firsthop
int LearnCircuitBuildTimeout
struct config_line_t * BuildtimeHistogram
uint32_t global_identifier
unsigned int relaxed_timeout
void format_local_iso_time(char *buf, time_t t)
void tor_gettimeofday(struct timeval *timeval)
long tv_mdiff(const struct timeval *start, const struct timeval *end)
#define tor_fragile_assert()