mirror of
https://gitlab.torproject.org/tpo/core/tor.git
synced 2024-11-24 04:13:28 +01:00
Bug #23100: Count all 3 hop circuits for CBT.
This change causes us to count anything once it reaches 3 hops (but not after).
This commit is contained in:
parent
23820a3943
commit
b5d4cd1b41
7
changes/bug23100
Normal file
7
changes/bug23100
Normal file
@ -0,0 +1,7 @@
|
||||
o Minor bugfixes (Performance):
|
||||
- Use hidden service circuits (and other circuits longer than 3 hops)
|
||||
to calculate a circuit build timeout. Previously, Tor only calculated
|
||||
its build timeout based on circuits that planned to be exactly 3 hops
|
||||
long. With this change, we include measurements from all circuits at
|
||||
the point where they complete their third hop. Fixes bug 23100;
|
||||
bugfix on 0.2.2.2-alpha.
|
@ -825,16 +825,25 @@ should_use_create_fast_for_circuit(origin_circuit_t *circ)
|
||||
return networkstatus_get_param(NULL, "usecreatefast", 0, 0, 1);
|
||||
}
|
||||
|
||||
/** Return true if <b>circ</b> is the type of circuit we want to count
|
||||
* timeouts from. In particular, we want it to have not completed yet
|
||||
* (already completing indicates we cannibalized it), and we want it to
|
||||
* have exactly three hops.
|
||||
/**
|
||||
* Return true if <b>circ</b> is the type of circuit we want to count
|
||||
* timeouts from.
|
||||
*
|
||||
* In particular, we want to consider any circuit that plans to build
|
||||
* at least 3 hops (but maybe more), but has 3 or fewer hops built
|
||||
* so far.
|
||||
*
|
||||
* We still want to consider circuits before 3 hops, because we need
|
||||
* to decide if we should convert them to a measurement circuit in
|
||||
* circuit_build_times_handle_completed_hop(), rather than letting
|
||||
* slow circuits get killed right away.
|
||||
*/
|
||||
int
|
||||
circuit_timeout_want_to_count_circ(origin_circuit_t *circ)
|
||||
circuit_timeout_want_to_count_circ(const origin_circuit_t *circ)
|
||||
{
|
||||
return !circ->has_opened
|
||||
&& circ->build_state->desired_path_len == DEFAULT_ROUTE_LEN;
|
||||
&& circ->build_state->desired_path_len >= DEFAULT_ROUTE_LEN
|
||||
&& circuit_get_cpath_opened_len(circ) <= DEFAULT_ROUTE_LEN;
|
||||
}
|
||||
|
||||
/** Decide whether to use a TAP or ntor handshake for connecting to <b>ei</b>
|
||||
@ -938,7 +947,9 @@ circuit_send_next_onion_skin(origin_circuit_t *circ)
|
||||
|
||||
tor_assert(circ->cpath->state == CPATH_STATE_OPEN);
|
||||
tor_assert(circ->base_.state == CIRCUIT_STATE_BUILDING);
|
||||
|
||||
crypt_path_t *hop = onion_next_hop_in_cpath(circ->cpath);
|
||||
circuit_build_times_handle_completed_hop(circ);
|
||||
|
||||
if (hop) {
|
||||
/* Case two: we're on a hop after the first. */
|
||||
@ -1053,38 +1064,6 @@ circuit_build_no_more_hops(origin_circuit_t *circ)
|
||||
* I think I got them right, but more checking would be wise. -NM
|
||||
*/
|
||||
|
||||
if (circuit_timeout_want_to_count_circ(circ)) {
|
||||
struct timeval end;
|
||||
long timediff;
|
||||
tor_gettimeofday(&end);
|
||||
timediff = tv_mdiff(&circ->base_.timestamp_began, &end);
|
||||
|
||||
/*
|
||||
* If the circuit build time is much greater than we would have cut
|
||||
* it off at, we probably had a suspend event along this codepath,
|
||||
* and we should discard the value.
|
||||
*/
|
||||
if (timediff < 0 ||
|
||||
timediff > 2*get_circuit_build_close_time_ms()+1000) {
|
||||
log_notice(LD_CIRC, "Strange value for circuit build time: %ldmsec. "
|
||||
"Assuming clock jump. Purpose %d (%s)", timediff,
|
||||
circ->base_.purpose,
|
||||
circuit_purpose_to_string(circ->base_.purpose));
|
||||
} else if (!circuit_build_times_disabled(get_options())) {
|
||||
/* Only count circuit times if the network is live */
|
||||
if (circuit_build_times_network_check_live(
|
||||
get_circuit_build_times())) {
|
||||
circuit_build_times_add_time(get_circuit_build_times_mutable(),
|
||||
(build_time_t)timediff);
|
||||
circuit_build_times_set_timeout(get_circuit_build_times_mutable());
|
||||
}
|
||||
|
||||
if (circ->base_.purpose != CIRCUIT_PURPOSE_C_MEASURE_TIMEOUT) {
|
||||
circuit_build_times_network_circ_success(
|
||||
get_circuit_build_times_mutable());
|
||||
}
|
||||
}
|
||||
}
|
||||
log_info(LD_CIRC,"circuit built!");
|
||||
circuit_reset_failure_count(0);
|
||||
|
||||
|
@ -27,7 +27,7 @@ int circuit_handle_first_hop(origin_circuit_t *circ);
|
||||
void circuit_n_chan_done(channel_t *chan, int status,
|
||||
int close_origin_circuits);
|
||||
int inform_testing_reachability(void);
|
||||
int circuit_timeout_want_to_count_circ(origin_circuit_t *circ);
|
||||
int circuit_timeout_want_to_count_circ(const origin_circuit_t *circ);
|
||||
int circuit_send_next_onion_skin(origin_circuit_t *circ);
|
||||
void circuit_note_clock_jumped(int seconds_elapsed);
|
||||
int circuit_extend(cell_t *cell, circuit_t *circ);
|
||||
|
@ -1789,6 +1789,25 @@ circuit_get_cpath_len(origin_circuit_t *circ)
|
||||
return n;
|
||||
}
|
||||
|
||||
/** Return the number of opened hops in circuit's path.
|
||||
* If circ has no entries, or is NULL, returns 0. */
|
||||
int
|
||||
circuit_get_cpath_opened_len(origin_circuit_t *circ)
|
||||
{
|
||||
int n = 0;
|
||||
if (circ && circ->cpath) {
|
||||
crypt_path_t *cpath, *cpath_next = NULL;
|
||||
for (cpath = circ->cpath;
|
||||
cpath->state == CPATH_STATE_OPEN
|
||||
&& cpath_next != circ->cpath;
|
||||
cpath = cpath_next) {
|
||||
cpath_next = cpath->next;
|
||||
++n;
|
||||
}
|
||||
}
|
||||
return n;
|
||||
}
|
||||
|
||||
/** Return the <b>hopnum</b>th hop in <b>circ</b>->cpath, or NULL if there
|
||||
* aren't that many hops in the list. <b>hopnum</b> starts at 1.
|
||||
* Returns NULL if <b>hopnum</b> is 0 or negative. */
|
||||
|
@ -58,6 +58,7 @@ void circuit_mark_all_dirty_circs_as_unusable(void);
|
||||
MOCK_DECL(void, circuit_mark_for_close_, (circuit_t *circ, int reason,
|
||||
int line, const char *file));
|
||||
int circuit_get_cpath_len(origin_circuit_t *circ);
|
||||
int circuit_get_cpath_opened_len(origin_circuit_t *);
|
||||
void circuit_clear_cpath(origin_circuit_t *circ);
|
||||
crypt_path_t *circuit_get_cpath_hop(origin_circuit_t *circ, int hopnum);
|
||||
void circuit_get_all_pending_on_channel(smartlist_t *out,
|
||||
|
@ -36,6 +36,7 @@
|
||||
#include "rendclient.h"
|
||||
#include "rendservice.h"
|
||||
#include "statefile.h"
|
||||
#include "circuitlist.h"
|
||||
|
||||
#undef log
|
||||
#include <math.h>
|
||||
@ -610,6 +611,77 @@ circuit_build_times_rewind_history(circuit_build_times_t *cbt, int n)
|
||||
}
|
||||
#endif /* 0 */
|
||||
|
||||
/**
|
||||
* Perform the build time work that needs to be done when a circuit
|
||||
* completes a hop.
|
||||
*
|
||||
* This function decides if we should record a circuit's build time
|
||||
* in our histogram data and other statistics, and if so, records it.
|
||||
* It also will mark circuits that have already timed out as
|
||||
* measurement-only circuits, so they can continue to build but
|
||||
* not get used.
|
||||
*
|
||||
* For this, we want to consider circuits that will eventually make
|
||||
* it to the third hop. For circuits longer than 3 hops, we want to
|
||||
* record their build time when they reach the third hop, but let
|
||||
* them continue (and not count them later). For circuits that are
|
||||
* exactly 3 hops, this will count them when they are completed. We
|
||||
* do this so that CBT is always gathering statistics on circuits
|
||||
* of the same length, regardless of their type.
|
||||
*/
|
||||
void
|
||||
circuit_build_times_handle_completed_hop(origin_circuit_t *circ)
|
||||
{
|
||||
struct timeval end;
|
||||
long timediff;
|
||||
|
||||
/* If circuit build times are disabled, let circuit_expire_building()
|
||||
* handle it.. */
|
||||
if (circuit_build_times_disabled(get_options())) {
|
||||
return;
|
||||
}
|
||||
|
||||
/* Is this a circuit for which the timeout applies in a straight-forward
|
||||
* way? If so, handle it below. If not, just return (and let
|
||||
* circuit_expire_building() eventually take care of it).
|
||||
*/
|
||||
if (!circuit_timeout_want_to_count_circ(circ)) {
|
||||
return;
|
||||
}
|
||||
|
||||
/* If the circuit is built to exactly the DEFAULT_ROUTE_LEN,
|
||||
* add it to our buildtimes. */
|
||||
if (circuit_get_cpath_opened_len(circ) == DEFAULT_ROUTE_LEN) {
|
||||
tor_gettimeofday(&end);
|
||||
timediff = tv_mdiff(&circ->base_.timestamp_began, &end);
|
||||
|
||||
/* If the circuit build time is much greater than we would have cut
|
||||
* it off at, we probably had a suspend event along this codepath,
|
||||
* and we should discard the value.
|
||||
*/
|
||||
if (timediff < 0 ||
|
||||
timediff > 2*get_circuit_build_close_time_ms()+1000) {
|
||||
log_notice(LD_CIRC, "Strange value for circuit build time: %ldmsec. "
|
||||
"Assuming clock jump. Purpose %d (%s)", timediff,
|
||||
circ->base_.purpose,
|
||||
circuit_purpose_to_string(circ->base_.purpose));
|
||||
} else {
|
||||
/* Only count circuit times if the network is live */
|
||||
if (circuit_build_times_network_check_live(
|
||||
get_circuit_build_times())) {
|
||||
circuit_build_times_add_time(get_circuit_build_times_mutable(),
|
||||
(build_time_t)timediff);
|
||||
circuit_build_times_set_timeout(get_circuit_build_times_mutable());
|
||||
}
|
||||
|
||||
if (circ->base_.purpose != CIRCUIT_PURPOSE_C_MEASURE_TIMEOUT) {
|
||||
circuit_build_times_network_circ_success(
|
||||
get_circuit_build_times_mutable());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a new build time value <b>time</b> to the set of build times. Time
|
||||
* units are milliseconds.
|
||||
@ -1285,9 +1357,14 @@ circuit_build_times_network_is_live(circuit_build_times_t *cbt)
|
||||
}
|
||||
|
||||
/**
|
||||
* Called to indicate that we completed a circuit. Because this circuit
|
||||
* Called to indicate that we "completed" a circuit. Because this circuit
|
||||
* succeeded, it doesn't count as a timeout-after-the-first-hop.
|
||||
*
|
||||
* (For the purposes of the cbt code, we consider a circuit "completed" if
|
||||
* it has 3 hops, regardless of its final hop count. We do this because
|
||||
* we're trying to answer the question, "how long should a circuit take to
|
||||
* reach the 3-hop count".)
|
||||
*
|
||||
* This is used by circuit_build_times_network_check_changed() to determine
|
||||
* if we had too many recent timeouts and need to reset our learned timeout
|
||||
* to something higher.
|
||||
|
@ -34,6 +34,7 @@ void circuit_build_times_set_timeout(circuit_build_times_t *cbt);
|
||||
int circuit_build_times_add_time(circuit_build_times_t *cbt,
|
||||
build_time_t time);
|
||||
int circuit_build_times_needs_circuits(const circuit_build_times_t *cbt);
|
||||
void circuit_build_times_handle_completed_hop(origin_circuit_t *circ);
|
||||
|
||||
int circuit_build_times_needs_circuits_now(const circuit_build_times_t *cbt);
|
||||
void circuit_build_times_init(circuit_build_times_t *cbt);
|
||||
|
Loading…
Reference in New Issue
Block a user