From 769f9201a68387c2cdf03e1efd28399c93bb2bdf Mon Sep 17 00:00:00 2001 From: Roger Dingledine Date: Fri, 15 Sep 2006 05:30:25 +0000 Subject: [PATCH] Send out a burst of long-range drop cells after we've established that we're reachable. Spread them over 4 circuits, so hopefully a few will be fast. This exercises our bandwidth and bootstraps us quicker. svn:r8399 --- src/or/circuitlist.c | 7 ++++--- src/or/circuituse.c | 53 +++++++++++++++++++++++++++++++++++++++++++++------- src/or/or.h | 7 ++++++- src/or/router.c | 35 ++++++++++++++++++++++++++++++++-- src/or/routerlist.c | 1 + 5 files changed, 90 insertions(+), 13 deletions(-) diff --git a/src/or/circuitlist.c b/src/or/circuitlist.c index 7a8830afe6..d2f98c4260 100644 --- a/src/or/circuitlist.c +++ b/src/or/circuitlist.c @@ -220,7 +220,7 @@ circuit_close_all_marked(void) } } -/** Return the head of the global linked list of circuits. **/ +/** Return the head of the global linked list of circuits. */ circuit_t * _circuit_get_global_list(void) { @@ -650,8 +650,9 @@ circuit_get_by_rend_query_and_purpose(const char *rend_query, uint8_t purpose) } /** Return the first circuit in global_circuitlist after start - * whose rend_pk_digest field is digest and whose purpose is - * purpose. Returns NULL if no circuit is found. + * whose purpose is purpose is purpose, and (if set) whose + * digest matches the rend_pk_digest field. Return NULL if no + * circuit is found. * If start is NULL, begin at the start of the list. * DOCDOC origin. */ diff --git a/src/or/circuituse.c b/src/or/circuituse.c index e4faee31af..db68b674ae 100644 --- a/src/or/circuituse.c +++ b/src/or/circuituse.c @@ -583,8 +583,6 @@ circuit_expire_old_circuits(time_t now) log_debug(LD_CIRC, "Closing n_circ_id %d (dirty %d secs ago, purp %d)", circ->n_circ_id, (int)(now - circ->timestamp_dirty), circ->purpose); - /* (only general and purpose_c circs can get dirty) */ - tor_assert(circ->purpose <= CIRCUIT_PURPOSE_C_REND_JOINED); circuit_mark_for_close(circ, END_CIRC_AT_ORIGIN); } else if (!circ->timestamp_dirty && circ->state == CIRCUIT_STATE_OPEN && @@ -599,14 +597,55 @@ circuit_expire_old_circuits(time_t now) } } -/** A testing circuit has completed. Take whatever stats we want. */ +#define NUM_PARALLEL_TESTING_CIRCS 4 + +static int have_performed_bandwidth_test = 0; + +/** Reset have_performed_bandwidth_test, so we'll start building + * testing circuits again so we can exercise our bandwidth. */ +void +reset_bandwidth_test(void) +{ + have_performed_bandwidth_test = 0; +} + +/** Return 1 if we've already exercised our bandwidth, or if we + * have fewer than NUM_PARALLEL_TESTING_CIRCS testing circuits + * established or on the way. Else return 0. + */ +int +circuit_enough_testing_circs(void) +{ + circuit_t *circ; + int num = 0; + + if (have_performed_bandwidth_test) + return 1; + + for (circ = global_circuitlist; circ; circ = circ->next) { + if (!circ->marked_for_close && CIRCUIT_IS_ORIGIN(circ) && + circ->purpose == CIRCUIT_PURPOSE_TESTING && + circ->state == CIRCUIT_STATE_OPEN) + num++; + } + return num >= NUM_PARALLEL_TESTING_CIRCS; +} + +/** A testing circuit has completed. Take whatever stats we want. + * Noticing reachability is taken care of in onionskin_answer(), + * so there's no need to record anything here. But if we still want + * to do the bandwidth test, and we now have enough testing circuits + * open, do it. + */ static void circuit_testing_opened(origin_circuit_t *circ) { - /* For now, we only use testing circuits to see if our ORPort is - reachable. But we remember reachability in onionskin_answer(), - so there's no need to record anything here. Just close the circ. */ - circuit_mark_for_close(TO_CIRCUIT(circ), END_CIRC_AT_ORIGIN); + if (have_performed_bandwidth_test) { + circuit_mark_for_close(TO_CIRCUIT(circ), END_CIRC_AT_ORIGIN); + } else if (circuit_enough_testing_circs()) { + router_perform_bandwidth_test(NUM_PARALLEL_TESTING_CIRCS, time(NULL)); + have_performed_bandwidth_test = 1; + } } /** A testing circuit has failed to build. Take whatever stats we want. */ diff --git a/src/or/or.h b/src/or/or.h index fffed1dd9f..717d729fb2 100644 --- a/src/or/or.h +++ b/src/or/or.h @@ -1753,6 +1753,10 @@ int circuit_stream_is_being_handled(edge_connection_t *conn, uint16_t port, void circuit_build_needed_circs(time_t now); void circuit_detach_stream(circuit_t *circ, edge_connection_t *conn); void circuit_about_to_close_connection(connection_t *conn); + +void reset_bandwidth_test(void); +int circuit_enough_testing_circs(void); + void circuit_has_opened(origin_circuit_t *circ); void circuit_build_failed(origin_circuit_t *circ); origin_circuit_t *circuit_launch_by_nickname(uint8_t purpose, @@ -2443,13 +2447,14 @@ void consider_testing_reachability(void); void router_orport_found_reachable(void); void router_dirport_found_reachable(void); void server_has_changed_ip(void); -void consider_publishable_server(int force); +void router_perform_bandwidth_test(int num_circs, time_t now); int authdir_mode(or_options_t *options); int clique_mode(or_options_t *options); int server_mode(or_options_t *options); int advertised_server_mode(void); int proxy_mode(or_options_t *options); +void consider_publishable_server(int force); int router_is_clique_mode(routerinfo_t *router); void router_upload_dir_desc_to_dirservers(int force); diff --git a/src/or/router.c b/src/or/router.c index 032069c480..2dbbefa2b8 100644 --- a/src/or/router.c +++ b/src/or/router.c @@ -439,11 +439,13 @@ void consider_testing_reachability(void) { routerinfo_t *me = router_get_my_routerinfo(); + int orport_reachable = !check_whether_orport_reachable(); if (!me) return; - if (!check_whether_orport_reachable()) { - log_info(LD_CIRC, "Testing reachability of my ORPort: %s:%d.", + if (!orport_reachable || !circuit_enough_testing_circs()) { + log_info(LD_CIRC, "Testing %s of my ORPort: %s:%d.", + !orport_reachable ? "reachability" : "bandwidth", me->address, me->or_port); circuit_launch_by_router(CIRCUIT_PURPOSE_TESTING, me, 0, 1, 1); } @@ -488,9 +490,38 @@ server_has_changed_ip(void) stats_n_seconds_working = 0; can_reach_or_port = 0; can_reach_dir_port = 0; + reset_bandwidth_test(); mark_my_descriptor_dirty(); } +/** We have enough testing circuit open. Send a bunch of "drop" + * cells down each of them, to exercise our bandwidth. */ +void +router_perform_bandwidth_test(int num_circs, time_t now) +{ + int num_cells = get_options()->BandwidthRate * 10 / CELL_NETWORK_SIZE; + int max_cells = num_cells < CIRCWINDOW_START ? + num_cells : CIRCWINDOW_START; + int cells_per_circuit = max_cells / num_circs; + origin_circuit_t *circ = NULL; + + while ((circ = circuit_get_next_by_pk_and_purpose(circ, NULL, + CIRCUIT_PURPOSE_TESTING))) { + /* dump cells_per_circuit drop cells onto this circ */ + int i = cells_per_circuit; + if (circ->_base.state != CIRCUIT_STATE_OPEN) + continue; + circ->_base.timestamp_dirty = now; + while (i-- > 0) { + if (connection_edge_send_command(NULL, TO_CIRCUIT(circ), + RELAY_COMMAND_DROP, + NULL, 0, circ->cpath->prev)<0) { + return; /* stop if error */ + } + } + } +} + /** Return true iff we believe ourselves to be an authoritative * directory server. */ diff --git a/src/or/routerlist.c b/src/or/routerlist.c index 577702ec5d..088f74696a 100644 --- a/src/or/routerlist.c +++ b/src/or/routerlist.c @@ -2129,6 +2129,7 @@ add_networkstatus_to_cache(const char *s, /** How far in the future do we allow a network-status to get before removing * it? (seconds) */ #define NETWORKSTATUS_ALLOW_SKEW (24*60*60) + /** Given a string s containing a network status that we received at * arrived_at from source, try to parse it, see if we want to * store it, and put it into our cache as necessary. -- 2.11.4.GIT