From cb31978adb3d92d304df0c2a408d9f5f75891667 Mon Sep 17 00:00:00 2001 From: Roger Dingledine Date: Fri, 23 Apr 2010 18:35:11 -0400 Subject: [PATCH 1/2] close idle dir-fetch circs early --- changes/close_begindir_circs | 7 +++++ src/or/circuituse.c | 53 ++++++++++++++++++++++++++++++++++-- src/or/main.c | 4 +++ src/or/or.h | 2 ++ 4 files changed, 63 insertions(+), 3 deletions(-) create mode 100644 changes/close_begindir_circs diff --git a/changes/close_begindir_circs b/changes/close_begindir_circs new file mode 100644 index 0000000000..3b1ee879c5 --- /dev/null +++ b/changes/close_begindir_circs @@ -0,0 +1,7 @@ + o Major bugfixes: + - Relays now close idle circuits early if it looks like they were + intended for directory fetches. Such circuits are unlikely to + be re-used, and tens of thousands of them were piling up at the + fast relays, causing the relays to run out of sockets and memory. + Bugfix on 0.2.0.22-rc (where clients started tunneling their + directory fetches over TLS). diff --git a/src/or/circuituse.c b/src/or/circuituse.c index 6ae2769a60..827c4bbf2b 100644 --- a/src/or/circuituse.c +++ b/src/or/circuituse.c @@ -17,7 +17,7 @@ extern circuit_t *global_circuitlist; /* from circuitlist.c */ /********* END VARIABLES ************/ -static void circuit_expire_old_circuits(time_t now); +static void circuit_expire_old_circuits_clientside(time_t now); static void circuit_increment_failure_count(void); /** Return 1 if circ could be returned by circuit_get_best(). @@ -544,7 +544,7 @@ circuit_build_needed_circs(time_t now) time_to_new_circuit = now + options->NewCircuitPeriod; if (proxy_mode(get_options())) addressmap_clean(now); - circuit_expire_old_circuits(now); + circuit_expire_old_circuits_clientside(now); #if 0 /* disable for now, until predict-and-launch-new can cull leftovers */ circ = circuit_get_youngest_clean_open(CIRCUIT_PURPOSE_C_GENERAL); @@ -628,7 +628,7 @@ circuit_detach_stream(circuit_t *circ, edge_connection_t *conn) * for too long and has no streams on it: mark it for close. */ static void -circuit_expire_old_circuits(time_t now) +circuit_expire_old_circuits_clientside(time_t now) { circuit_t *circ; time_t cutoff = now - get_options()->CircuitIdleTimeout; @@ -660,6 +660,53 @@ circuit_expire_old_circuits(time_t now) } } +/** How long do we wait before killing circuits with the properties + * described below? + * + * Probably we could choose a number here as low as 5 to 10 seconds, + * since these circs are used for begindir, and a) generally you either + * ask another begindir question right after or you don't for a long time, + * b) clients at least through 0.2.1.x choose from the whole set of + * directory mirrors at each choice, and c) re-establishing a one-hop + * circuit via create-fast is a light operation assuming the TLS conn is + * still there. + * + * I expect "b" to go away one day when we move to using directory + * guards, but I think "a" and "c" are good enough reasons that a low + * number is safe even then. + */ +#define IDLE_ONE_HOP_CIRC_TIMEOUT 60 + +/** Find each non-origin circuit that has been unused for too long, + * has no streams on it, used a create_fast, and ends here: mark it + * for close. + */ +void +circuit_expire_old_circuits_serverside(time_t now) +{ + circuit_t *circ; + or_circuit_t *or_circ; + time_t cutoff = now - IDLE_ONE_HOP_CIRC_TIMEOUT; + + for (circ = global_circuitlist; circ; circ = circ->next) { + if (circ->marked_for_close || CIRCUIT_IS_ORIGIN(circ)) + continue; + or_circ = TO_OR_CIRCUIT(circ); + /* If the circuit has been idle for too long, and there are no streams + * on it, and it ends here, and it used a create_fast, mark it for close. + */ + if (or_circ->is_first_hop && !circ->n_conn && + !or_circ->n_streams && !or_circ->resolving_streams && + or_circ->p_conn && + or_circ->p_conn->timestamp_last_added_nonpadding <= cutoff) { + log_info(LD_CIRC, "Closing circ_id %d (empty %d secs ago)", + or_circ->p_circ_id, + (int)(now - or_circ->p_conn->timestamp_last_added_nonpadding)); + circuit_mark_for_close(circ, END_CIRC_REASON_FINISHED); + } + } +} + /** Number of testing circuits we want open before testing our bandwidth. */ #define NUM_PARALLEL_TESTING_CIRCS 4 diff --git a/src/or/main.c b/src/or/main.c index 9b57ce8728..04364bbe10 100644 --- a/src/or/main.c +++ b/src/or/main.c @@ -1058,6 +1058,10 @@ run_scheduled_events(time_t now) if (have_dir_info && !we_are_hibernating()) circuit_build_needed_circs(now); + /* every 10 seconds, but not at the same second as other such events */ + if (now % 10 == 5) + circuit_expire_old_circuits_serverside(now); + /** 5. We do housekeeping for each connection... */ connection_or_set_bad_connections(); for (i=0;i Date: Wed, 21 Apr 2010 21:35:18 -0400 Subject: [PATCH 2/2] finally get rid of "clique mode" --- changes/kill_clique_mode | 4 ++++ src/or/main.c | 12 ++++-------- src/or/or.h | 2 -- src/or/router.c | 24 ------------------------ 4 files changed, 8 insertions(+), 34 deletions(-) create mode 100644 changes/kill_clique_mode diff --git a/changes/kill_clique_mode b/changes/kill_clique_mode new file mode 100644 index 0000000000..82283a8ea7 --- /dev/null +++ b/changes/kill_clique_mode @@ -0,0 +1,4 @@ + o Minor features: + - Finally get rid of the deprecated and now harmful notion of + "clique mode", where directory authorities maintain TLS connections + to every other relay. diff --git a/src/or/main.c b/src/or/main.c index 04364bbe10..321fc5a16f 100644 --- a/src/or/main.c +++ b/src/or/main.c @@ -727,7 +727,6 @@ run_connection_housekeeping(int i, time_t now) /* If we haven't written to an OR connection for a while, then either nuke the connection or send a keepalive, depending. */ if (now >= conn->timestamp_lastwritten + options->KeepalivePeriod) { - routerinfo_t *router = router_get_by_digest(or_conn->identity_digest); int maxCircuitlessPeriod = options->MaxCircuitDirtiness*3/2; if (!connection_state_is_open(conn)) { /* We never managed to actually get this connection open and happy. */ @@ -743,14 +742,11 @@ run_connection_housekeeping(int i, time_t now) conn->s,conn->address, conn->port); connection_mark_for_close(conn); conn->hold_open_until_flushed = 1; - } else if (!clique_mode(options) && !or_conn->n_circuits && + } else if (!or_conn->n_circuits && now >= or_conn->timestamp_last_added_nonpadding + - maxCircuitlessPeriod && - (!router || !server_mode(options) || - !router_is_clique_mode(router))) { + maxCircuitlessPeriod) { log_info(LD_OR,"Expiring non-used OR connection to fd %d (%s:%d) " - "[Not in clique mode].", - conn->s,conn->address, conn->port); + "[idle].", conn->s,conn->address, conn->port); connection_mark_for_close(conn); conn->hold_open_until_flushed = 1; } else if ( @@ -1605,7 +1601,7 @@ dumpmemusage(int severity) tor_log_mallinfo(severity); } -/** Write all statistics to the log, with log level 'severity'. Called +/** Write all statistics to the log, with log level severity. Called * in response to a SIGUSR1. */ static void dumpstats(int severity) diff --git a/src/or/or.h b/src/or/or.h index 97f94d0178..a2a6d380d6 100644 --- a/src/or/or.h +++ b/src/or/or.h @@ -4229,13 +4229,11 @@ int authdir_mode_publishes_statuses(or_options_t *options); int authdir_mode_tests_reachability(or_options_t *options); int authdir_mode_bridge(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); void mark_my_descriptor_dirty_if_older_than(time_t when); void mark_my_descriptor_dirty(void); diff --git a/src/or/router.c b/src/or/router.c index 6db9a7c0a8..8661e7a224 100644 --- a/src/or/router.c +++ b/src/or/router.c @@ -952,16 +952,6 @@ authdir_mode_bridge(or_options_t *options) { return authdir_mode(options) && options->BridgeAuthoritativeDir != 0; } -/** Return true iff we once tried to stay connected to all ORs at once. - * FFFF this function, and the notion of staying connected to ORs, is - * nearly obsolete. One day there will be a proposal for getting rid of - * it. - */ -int -clique_mode(or_options_t *options) -{ - return authdir_mode_tests_reachability(options); -} /** Return true iff we are trying to be a server. */ @@ -1055,20 +1045,6 @@ consider_publishable_server(int force) } } -/* - * Clique maintenance -- to be phased out. - */ - -/** Return true iff we believe this OR tries to keep connections open - * to all other ORs. */ -int -router_is_clique_mode(routerinfo_t *router) -{ - if (router_digest_is_trusted_dir(router->cache_info.identity_digest)) - return 1; - return 0; -} - /* * OR descriptor generation. */