diff options
author | Roger Dingledine <arma@torproject.org> | 2010-09-29 17:21:43 -0400 |
---|---|---|
committer | Roger Dingledine <arma@torproject.org> | 2010-09-29 17:21:43 -0400 |
commit | 355fc63790bedfd00c062d6aa8d60f00307dc03f (patch) | |
tree | 4d8f31bc6d0658ea08e9651bde3655dc8b3e266d /src/or | |
parent | 50720a9a4f8ea4433f3696d42d2f640ad970b285 (diff) | |
parent | 48cd096276590e40540bc255b2610931351b14cb (diff) | |
download | tor-355fc63790bedfd00c062d6aa8d60f00307dc03f.tar.gz tor-355fc63790bedfd00c062d6aa8d60f00307dc03f.zip |
Merge branch 'maint-0.2.2'
Diffstat (limited to 'src/or')
-rw-r--r-- | src/or/circuitbuild.c | 29 | ||||
-rw-r--r-- | src/or/circuitbuild.h | 1 | ||||
-rw-r--r-- | src/or/circuitlist.c | 2 | ||||
-rw-r--r-- | src/or/circuituse.c | 71 | ||||
-rw-r--r-- | src/or/or.h | 10 | ||||
-rw-r--r-- | src/or/reasons.c | 2 |
6 files changed, 85 insertions, 30 deletions
diff --git a/src/or/circuitbuild.c b/src/or/circuitbuild.c index 2b4540bf3b..fde2e7f494 100644 --- a/src/or/circuitbuild.c +++ b/src/or/circuitbuild.c @@ -1197,6 +1197,11 @@ circuit_build_times_count_close(circuit_build_times_t *cbt, /** * Update timeout counts to determine if we need to expire * our build time history due to excessive timeouts. + * + * We do not record any actual time values at this stage; + * we are only interested in recording the fact that a timeout + * happened. We record the time values via + * circuit_build_times_count_close() and circuit_build_times_add_time(). */ void circuit_build_times_count_timeout(circuit_build_times_t *cbt, @@ -1208,11 +1213,11 @@ circuit_build_times_count_timeout(circuit_build_times_t *cbt, return; } + /* Register the fact that a timeout just occurred. */ circuit_build_times_network_timeout(cbt, did_onehop); /* If there are a ton of timeouts, we should reset - * the circuit build timeout. - */ + * the circuit build timeout. */ circuit_build_times_network_check_changed(cbt); } @@ -1816,6 +1821,18 @@ should_use_create_fast_for_circuit(origin_circuit_t *circ) return 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. + */ +int +circuit_timeout_want_to_count_circ(origin_circuit_t *circ) +{ + return !circ->has_opened + && circ->build_state->desired_path_len == DEFAULT_ROUTE_LEN; +} + /** This is the backbone function for building circuits. * * If circ's first hop is closed, then we need to build a create @@ -1889,11 +1906,12 @@ circuit_send_next_onion_skin(origin_circuit_t *circ) if (!hop) { /* done building the circuit. whew. */ circuit_set_state(TO_CIRCUIT(circ), CIRCUIT_STATE_OPEN); - if (!circ->build_state->onehop_tunnel) { + if (circuit_timeout_want_to_count_circ(circ)) { struct timeval end; long timediff; tor_gettimeofday(&end); timediff = tv_mdiff(&circ->_base.highres_created, &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, @@ -1901,9 +1919,10 @@ circuit_send_next_onion_skin(origin_circuit_t *circ) */ if (timediff < 0 || timediff > 2*circ_times.close_ms+1000) { log_notice(LD_CIRC, "Strange value for circuit build time: %ldmsec. " - "Assuming clock jump.", timediff); + "Assuming clock jump. Purpose %d", timediff, + circ->_base.purpose); } else if (!circuit_build_times_disabled()) { - /* Don't count circuit times if the network was not live */ + /* Only count circuit times if the network is 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); diff --git a/src/or/circuitbuild.h b/src/or/circuitbuild.h index 033dd79c4c..9a8e4c3879 100644 --- a/src/or/circuitbuild.h +++ b/src/or/circuitbuild.h @@ -24,6 +24,7 @@ origin_circuit_t *circuit_establish_circuit(uint8_t purpose, int circuit_handle_first_hop(origin_circuit_t *circ); void circuit_n_conn_done(or_connection_t *or_conn, int status); int inform_testing_reachability(void); +int circuit_timeout_want_to_count_circ(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); diff --git a/src/or/circuitlist.c b/src/or/circuitlist.c index fa800db1a4..fb4b69be0d 100644 --- a/src/or/circuitlist.c +++ b/src/or/circuitlist.c @@ -368,7 +368,7 @@ circuit_purpose_to_controller_string(uint8_t purpose) case CIRCUIT_PURPOSE_TESTING: return "TESTING"; case CIRCUIT_PURPOSE_C_MEASURE_TIMEOUT: - return "EXPIRED"; + return "MEASURE_TIMEOUT"; case CIRCUIT_PURPOSE_CONTROLLER: return "CONTROLLER"; diff --git a/src/or/circuituse.c b/src/or/circuituse.c index f369678ab0..1fbe5a82b9 100644 --- a/src/or/circuituse.c +++ b/src/or/circuituse.c @@ -284,6 +284,8 @@ circuit_expire_building(time_t now) * decided on a customized one yet */ time_t general_cutoff = now - lround(circ_times.timeout_ms/1000); time_t begindir_cutoff = now - lround(circ_times.timeout_ms/2000); + time_t fourhop_cutoff = now - lround(4*circ_times.timeout_ms/3000); + time_t cannibalize_cutoff = now - lround(circ_times.timeout_ms/2000); time_t close_cutoff = now - lround(circ_times.close_ms/1000); time_t introcirc_cutoff = begindir_cutoff; cpath_build_state_t *build_state; @@ -299,6 +301,11 @@ circuit_expire_building(time_t now) build_state = TO_ORIGIN_CIRCUIT(victim)->build_state; if (build_state && build_state->onehop_tunnel) cutoff = begindir_cutoff; + else if (build_state && build_state->desired_path_len == 4 + && !TO_ORIGIN_CIRCUIT(victim)->has_opened) + cutoff = fourhop_cutoff; + else if (TO_ORIGIN_CIRCUIT(victim)->has_opened) + cutoff = cannibalize_cutoff; else if (victim->purpose == CIRCUIT_PURPOSE_C_INTRODUCING) cutoff = introcirc_cutoff; else if (victim->purpose == CIRCUIT_PURPOSE_C_MEASURE_TIMEOUT) @@ -378,29 +385,39 @@ circuit_expire_building(time_t now) continue; } - /* circuits are allowed to last longer for measurement. - * Switch their purpose and wait. */ - if (victim->purpose != CIRCUIT_PURPOSE_C_MEASURE_TIMEOUT) { - victim->purpose = CIRCUIT_PURPOSE_C_MEASURE_TIMEOUT; - circuit_build_times_count_timeout(&circ_times, - first_hop_succeeded); - continue; - } + if (circuit_timeout_want_to_count_circ(TO_ORIGIN_CIRCUIT(victim))) { + /* Circuits are allowed to last longer for measurement. + * Switch their purpose and wait. */ + if (victim->purpose != CIRCUIT_PURPOSE_C_MEASURE_TIMEOUT) { + control_event_circuit_status(TO_ORIGIN_CIRCUIT(victim), + CIRC_EVENT_FAILED, + END_CIRC_REASON_TIMEOUT); + victim->purpose = CIRCUIT_PURPOSE_C_MEASURE_TIMEOUT; + /* Record this failure to check for too many timeouts + * in a row. This function does not record a time value yet + * (we do that later); it only counts the fact that we did + * have a timeout. */ + circuit_build_times_count_timeout(&circ_times, + first_hop_succeeded); + continue; + } - /* - * 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 (now - victim->timestamp_created > 2*circ_times.close_ms/1000+1) { - log_notice(LD_CIRC, - "Extremely large value for circuit build timeout: %lds. " - "Assuming clock jump.", - (long)(now - victim->timestamp_created)); - } else if (circuit_build_times_count_close(&circ_times, - first_hop_succeeded, - victim->timestamp_created)) { - circuit_build_times_set_timeout(&circ_times); + /* + * 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 (now - victim->timestamp_created > 2*circ_times.close_ms/1000+1) { + log_notice(LD_CIRC, + "Extremely large value for circuit build timeout: %lds. " + "Assuming clock jump. Purpose %d", + (long)(now - victim->timestamp_created), + victim->purpose); + } else if (circuit_build_times_count_close(&circ_times, + first_hop_succeeded, + victim->timestamp_created)) { + circuit_build_times_set_timeout(&circ_times); + } } } @@ -416,7 +433,10 @@ circuit_expire_building(time_t now) circuit_state_to_string(victim->state), victim->purpose); circuit_log_path(LOG_INFO,LD_CIRC,TO_ORIGIN_CIRCUIT(victim)); - circuit_mark_for_close(victim, END_CIRC_REASON_TIMEOUT); + if (victim->purpose == CIRCUIT_PURPOSE_C_MEASURE_TIMEOUT) + circuit_mark_for_close(victim, END_CIRC_REASON_MEASUREMENT_EXPIRED); + else + circuit_mark_for_close(victim, END_CIRC_REASON_TIMEOUT); } } @@ -903,6 +923,11 @@ circuit_has_opened(origin_circuit_t *circ) { control_event_circuit_status(circ, CIRC_EVENT_BUILT, 0); + /* Remember that this circuit has finished building. Now if we start + * it building again later (e.g. by extending it), we will know not + * to consider its build time. */ + circ->has_opened = 1; + switch (TO_CIRCUIT(circ)->purpose) { case CIRCUIT_PURPOSE_C_ESTABLISH_REND: rend_client_rendcirc_has_opened(circ); diff --git a/src/or/or.h b/src/or/or.h index 8913dbc83d..3eb6adde6b 100644 --- a/src/or/or.h +++ b/src/or/or.h @@ -623,6 +623,10 @@ typedef enum { /* Negative reasons are internal: we never send them in a DESTROY or TRUNCATE * call; they only go to the controller for tracking */ +/** Our post-timeout circuit time measurement period expired. + * We must give up now */ +#define END_CIRC_REASON_MEASUREMENT_EXPIRED -3 + /** We couldn't build a path for this circuit. */ #define END_CIRC_REASON_NOPATH -2 /** Catch-all "other" reason for closing origin circuits. */ @@ -2237,9 +2241,13 @@ typedef struct origin_circuit_t { * to the specification? */ unsigned int remaining_relay_early_cells : 4; - /** Set if this circuit insanely old and if we already informed the user */ + /** Set if this circuit is insanely old and we already informed the user */ unsigned int is_ancient : 1; + /** Set if this circuit has already been opened. Used to detect + * cannibalized circuits. */ + unsigned int has_opened : 1; + /** What commands were sent over this circuit that decremented the * RELAY_EARLY counter? This is for debugging task 878. */ uint8_t relay_early_commands[MAX_RELAY_EARLY_CELLS_PER_CIRCUIT]; diff --git a/src/or/reasons.c b/src/or/reasons.c index ade9a3abfc..aa7972be5b 100644 --- a/src/or/reasons.c +++ b/src/or/reasons.c @@ -334,6 +334,8 @@ circuit_end_reason_to_control_string(int reason) return "NOPATH"; case END_CIRC_REASON_NOSUCHSERVICE: return "NOSUCHSERVICE"; + case END_CIRC_REASON_MEASUREMENT_EXPIRED: + return "MEASUREMENT_EXPIRED"; default: log_warn(LD_BUG, "Unrecognized reason code %d", (int)reason); return NULL; |