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 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
|
* Return true if <b>circ</b> is the type of circuit we want to count
|
||||||
* (already completing indicates we cannibalized it), and we want it to
|
* timeouts from.
|
||||||
* have exactly three hops.
|
*
|
||||||
|
* 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
|
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
|
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>
|
/** 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->cpath->state == CPATH_STATE_OPEN);
|
||||||
tor_assert(circ->base_.state == CIRCUIT_STATE_BUILDING);
|
tor_assert(circ->base_.state == CIRCUIT_STATE_BUILDING);
|
||||||
|
|
||||||
crypt_path_t *hop = onion_next_hop_in_cpath(circ->cpath);
|
crypt_path_t *hop = onion_next_hop_in_cpath(circ->cpath);
|
||||||
|
circuit_build_times_handle_completed_hop(circ);
|
||||||
|
|
||||||
if (hop) {
|
if (hop) {
|
||||||
/* Case two: we're on a hop after the first. */
|
/* 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
|
* 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!");
|
log_info(LD_CIRC,"circuit built!");
|
||||||
circuit_reset_failure_count(0);
|
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,
|
void circuit_n_chan_done(channel_t *chan, int status,
|
||||||
int close_origin_circuits);
|
int close_origin_circuits);
|
||||||
int inform_testing_reachability(void);
|
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);
|
int circuit_send_next_onion_skin(origin_circuit_t *circ);
|
||||||
void circuit_note_clock_jumped(int seconds_elapsed);
|
void circuit_note_clock_jumped(int seconds_elapsed);
|
||||||
int circuit_extend(cell_t *cell, circuit_t *circ);
|
int circuit_extend(cell_t *cell, circuit_t *circ);
|
||||||
|
@ -1789,6 +1789,25 @@ circuit_get_cpath_len(origin_circuit_t *circ)
|
|||||||
return n;
|
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
|
/** 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.
|
* aren't that many hops in the list. <b>hopnum</b> starts at 1.
|
||||||
* Returns NULL if <b>hopnum</b> is 0 or negative. */
|
* 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,
|
MOCK_DECL(void, circuit_mark_for_close_, (circuit_t *circ, int reason,
|
||||||
int line, const char *file));
|
int line, const char *file));
|
||||||
int circuit_get_cpath_len(origin_circuit_t *circ);
|
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);
|
void circuit_clear_cpath(origin_circuit_t *circ);
|
||||||
crypt_path_t *circuit_get_cpath_hop(origin_circuit_t *circ, int hopnum);
|
crypt_path_t *circuit_get_cpath_hop(origin_circuit_t *circ, int hopnum);
|
||||||
void circuit_get_all_pending_on_channel(smartlist_t *out,
|
void circuit_get_all_pending_on_channel(smartlist_t *out,
|
||||||
|
@ -36,6 +36,7 @@
|
|||||||
#include "rendclient.h"
|
#include "rendclient.h"
|
||||||
#include "rendservice.h"
|
#include "rendservice.h"
|
||||||
#include "statefile.h"
|
#include "statefile.h"
|
||||||
|
#include "circuitlist.h"
|
||||||
|
|
||||||
#undef log
|
#undef log
|
||||||
#include <math.h>
|
#include <math.h>
|
||||||
@ -610,6 +611,77 @@ circuit_build_times_rewind_history(circuit_build_times_t *cbt, int n)
|
|||||||
}
|
}
|
||||||
#endif /* 0 */
|
#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
|
* Add a new build time value <b>time</b> to the set of build times. Time
|
||||||
* units are milliseconds.
|
* 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.
|
* 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
|
* 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
|
* if we had too many recent timeouts and need to reset our learned timeout
|
||||||
* to something higher.
|
* 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,
|
int circuit_build_times_add_time(circuit_build_times_t *cbt,
|
||||||
build_time_t time);
|
build_time_t time);
|
||||||
int circuit_build_times_needs_circuits(const circuit_build_times_t *cbt);
|
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);
|
int circuit_build_times_needs_circuits_now(const circuit_build_times_t *cbt);
|
||||||
void circuit_build_times_init(circuit_build_times_t *cbt);
|
void circuit_build_times_init(circuit_build_times_t *cbt);
|
||||||
|
Loading…
Reference in New Issue
Block a user