diff options
Diffstat (limited to 'src/or/circuitbuild.c')
-rw-r--r-- | src/or/circuitbuild.c | 118 |
1 files changed, 74 insertions, 44 deletions
diff --git a/src/or/circuitbuild.c b/src/or/circuitbuild.c index b1335cc24c..f244aeaff0 100644 --- a/src/or/circuitbuild.c +++ b/src/or/circuitbuild.c @@ -290,7 +290,7 @@ circuit_build_times_init(circuit_build_times_t *cbt) } /** - * Rewind our timeout history by n timeout positions. + * Rewind our build time history by n positions. */ static void circuit_build_times_rewind_history(circuit_build_times_t *cbt, int n) @@ -317,7 +317,7 @@ circuit_build_times_rewind_history(circuit_build_times_t *cbt, int n) } /** - * Add a new timeout value <b>time</b> to the set of build times. Time + * Add a new build time value <b>time</b> to the set of build times. Time * units are milliseconds. * * circuit_build_times <b>cbt</a> is a circular array, so loop around when @@ -359,7 +359,7 @@ circuit_build_times_max(circuit_build_times_t *cbt) build_time_t max_build_time = 0; for (i = 0; i < CBT_NCIRCUITS_TO_OBSERVE; i++) { if (cbt->circuit_build_times[i] > max_build_time - && cbt->circuit_build_times[i] != CBT_BUILD_TIMEOUT) + && cbt->circuit_build_times[i] != CBT_BUILD_ABANDONED) max_build_time = cbt->circuit_build_times[i]; } return max_build_time; @@ -407,7 +407,7 @@ circuit_build_times_create_histogram(circuit_build_times_t *cbt, // calculate histogram for (i = 0; i < CBT_NCIRCUITS_TO_OBSERVE; i++) { if (cbt->circuit_build_times[i] == 0 - || cbt->circuit_build_times[i] == CBT_BUILD_TIMEOUT) + || cbt->circuit_build_times[i] == CBT_BUILD_ABANDONED) continue; /* 0 <-> uninitialized */ c = (cbt->circuit_build_times[i] / CBT_BIN_WIDTH); @@ -489,11 +489,11 @@ circuit_build_times_update_state(circuit_build_times_t *cbt, *next = NULL; state->TotalBuildTimes = cbt->total_build_times; - state->CircuitBuildTimeoutCount = 0; + state->CircuitBuildAbandonedCount = 0; for (i = 0; i < CBT_NCIRCUITS_TO_OBSERVE; i++) { - if (cbt->circuit_build_times[i] == CBT_BUILD_TIMEOUT) - state->CircuitBuildTimeoutCount++; + if (cbt->circuit_build_times[i] == CBT_BUILD_ABANDONED) + state->CircuitBuildAbandonedCount++; } for (i = 0; i < nbins; i++) { @@ -567,7 +567,7 @@ circuit_build_times_filter_timeouts(circuit_build_times_t *cbt) if (cbt->circuit_build_times[i] > max_timeout) { build_time_t replaced = cbt->circuit_build_times[i]; num_filtered++; - cbt->circuit_build_times[i] = CBT_BUILD_TIMEOUT; + cbt->circuit_build_times[i] = CBT_BUILD_ABANDONED; log_debug(LD_CIRC, "Replaced timeout %d with %d", replaced, cbt->circuit_build_times[i]); @@ -644,7 +644,7 @@ circuit_build_times_parse_state(circuit_build_times_t *cbt, break; } - if (loaded_cnt+count+state->CircuitBuildTimeoutCount + if (loaded_cnt+count+state->CircuitBuildAbandonedCount > state->TotalBuildTimes) { log_warn(LD_CIRC, "Too many build times in state file. " @@ -665,9 +665,9 @@ circuit_build_times_parse_state(circuit_build_times_t *cbt, } log_info(LD_CIRC, - "Adding %d timeouts.", state->CircuitBuildTimeoutCount); - for (i=0; i < state->CircuitBuildTimeoutCount; i++) { - loaded_times[loaded_cnt++] = CBT_BUILD_TIMEOUT; + "Adding %d timeouts.", state->CircuitBuildAbandonedCount); + for (i=0; i < state->CircuitBuildAbandonedCount; i++) { + loaded_times[loaded_cnt++] = CBT_BUILD_ABANDONED; } if (loaded_cnt != state->TotalBuildTimes) { @@ -693,7 +693,7 @@ circuit_build_times_parse_state(circuit_build_times_t *cbt, circuit_build_times_set_timeout(cbt); - if (!state->CircuitBuildTimeoutCount && cbt->total_build_times) { + if (!state->CircuitBuildAbandonedCount && cbt->total_build_times) { circuit_build_times_filter_timeouts(cbt); } @@ -715,7 +715,7 @@ circuit_build_times_update_alpha(circuit_build_times_t *cbt) { build_time_t *x=cbt->circuit_build_times; double a = 0; - int n=0,i=0,timeout_count=0; + int n=0,i=0,abandoned_count=0; build_time_t max_time=0; /* http://en.wikipedia.org/wiki/Pareto_distribution#Parameter_estimation */ @@ -732,8 +732,8 @@ circuit_build_times_update_alpha(circuit_build_times_t *cbt) if (x[i] < cbt->Xm) { a += tor_mathlog(cbt->Xm); - } else if (x[i] == CBT_BUILD_TIMEOUT) { - timeout_count++; + } else if (x[i] == CBT_BUILD_ABANDONED) { + abandoned_count++; } else { a += tor_mathlog(x[i]); if (x[i] > max_time) @@ -750,13 +750,13 @@ circuit_build_times_update_alpha(circuit_build_times_t *cbt) tor_assert(max_time > 0); - a += timeout_count*tor_mathlog(max_time); + a += abandoned_count*tor_mathlog(max_time); a -= n*tor_mathlog(cbt->Xm); // Estimator comes from Eq #4 in: // "Bayesian estimation based on trimmed samples from Pareto populations" // by Arturo J. Fernández. We are right-censored only. - a = (n-timeout_count)/a; + a = (n-abandoned_count)/a; cbt->alpha = a; } @@ -907,16 +907,27 @@ circuit_build_times_network_circ_success(circuit_build_times_t *cbt) } /** - * A circuit just timed out. If there has been no recent network activity - * at all, but this circuit was launched back when we thought the network - * was live, increment the number of "nonlive" circuit timeouts. - * - * Also distinguish between whether it failed before the first hop - * and record that in our history for later deciding if the network has - * changed. + * A circuit just timed out. If it failed after the first hop, record it + * in our history for later deciding if the network speed has changed. */ static void circuit_build_times_network_timeout(circuit_build_times_t *cbt, + int did_onehop) +{ + if (did_onehop) { + cbt->liveness.timeouts_after_firsthop[cbt->liveness.after_firsthop_idx]=1; + cbt->liveness.after_firsthop_idx++; + cbt->liveness.after_firsthop_idx %= cbt->liveness.num_recent_circs; + } +} + +/** + * A circuit was just forcibly closed. If there has been no recent network + * activity at all, but this circuit was launched back when we thought the + * network was live, increment the number of "nonlive" circuit timeouts. + */ +static void +circuit_build_times_network_close(circuit_build_times_t *cbt, int did_onehop, time_t start_time) { time_t now = time(NULL); @@ -940,11 +951,6 @@ circuit_build_times_network_timeout(circuit_build_times_t *cbt, start_time, now); } cbt->liveness.nonlive_timeouts++; - } else if (did_onehop) { - /* 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 %= cbt->liveness.num_recent_circs; } } @@ -1010,8 +1016,6 @@ circuit_build_times_network_check_live(circuit_build_times_t *cbt) * Also resets the entire timeout history in this case and causes us * to restart the process of building test circuits and estimating a * new timeout. - * - * XXX: All this may have been broken by the close_ms change! */ int circuit_build_times_network_check_changed(circuit_build_times_t *cbt) @@ -1091,7 +1095,7 @@ circuit_build_times_timeout_rate(const circuit_build_times_t *cbt) * update our timeout estimate. */ int -circuit_build_times_add_timeout(circuit_build_times_t *cbt, +circuit_build_times_count_close(circuit_build_times_t *cbt, int did_onehop, time_t start_time) { @@ -1101,22 +1105,38 @@ circuit_build_times_add_timeout(circuit_build_times_t *cbt, return 0; } - // XXX: All this has changed due to close_ms - circuit_build_times_network_timeout(cbt, did_onehop, start_time); + /* Record this force-close to help determine if the network is dead */ + circuit_build_times_network_close(cbt, did_onehop, start_time); /* Only count timeouts if network is live.. */ if (!circuit_build_times_network_check_live(cbt)) { return 0; } - /* If there are a ton of timeouts, we should reduce - * the circuit build timeout */ - if (circuit_build_times_network_check_changed(cbt)) { - return 0; + circuit_build_times_add_time(cbt, CBT_BUILD_ABANDONED); + return 1; +} + +/** + * Update timeout counts to determine if we need to expire + * our build time history due to excessive timeouts. + */ +void +circuit_build_times_count_timeout(circuit_build_times_t *cbt, + int did_onehop) +{ + if (circuit_build_times_disabled()) { + cbt->close_ms = cbt->timeout_ms + = circuit_build_times_get_initial_timeout(); + return; } - circuit_build_times_add_time(cbt, CBT_BUILD_TIMEOUT); - return 1; + circuit_build_times_network_timeout(cbt, did_onehop); + + /* If there are a ton of timeouts, we should reset + * the circuit build timeout. + */ + circuit_build_times_network_check_changed(cbt); } /** @@ -1804,9 +1824,15 @@ circuit_send_next_onion_skin(origin_circuit_t *circ) log_notice(LD_CIRC, "Strange value for circuit build time: %ldmsec. " "Assuming clock jump.", timediff); } 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); + /* Don't count circuit times if the network was not live */ + if (circuit_build_times_network_check_live(&circ_times)) { + circuit_build_times_add_time(&circ_times, (build_time_t)timediff); + circuit_build_times_set_timeout(&circ_times); + } + + if (circ->_base.purpose != CIRCUIT_PURPOSE_C_MEASURE_TIMEOUT) { + circuit_build_times_network_circ_success(&circ_times); + } } } log_info(LD_CIRC,"circuit built!"); @@ -1829,6 +1855,10 @@ circuit_send_next_onion_skin(origin_circuit_t *circ) } circuit_rep_hist_note_result(circ); circuit_has_opened(circ); /* do other actions as necessary */ + + /* We're done with measurement circuits here. Just close them */ + if (circ->_base.purpose == CIRCUIT_PURPOSE_C_MEASURE_TIMEOUT) + circuit_mark_for_close(TO_CIRCUIT(circ), END_CIRC_REASON_FINISHED); return 0; } |