diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/or/circuitlist.c | 4 | ||||
-rw-r--r-- | src/or/config.c | 67 | ||||
-rw-r--r-- | src/or/connection.c | 8 | ||||
-rw-r--r-- | src/or/connection_edge.c | 9 | ||||
-rw-r--r-- | src/or/directory.c | 4 | ||||
-rw-r--r-- | src/or/geoip.c | 253 | ||||
-rw-r--r-- | src/or/main.c | 47 | ||||
-rw-r--r-- | src/or/or.h | 77 | ||||
-rw-r--r-- | src/or/relay.c | 94 | ||||
-rw-r--r-- | src/or/rephist.c | 274 | ||||
-rw-r--r-- | src/or/router.c | 147 | ||||
-rw-r--r-- | src/or/routerparse.c | 50 | ||||
-rw-r--r-- | src/or/test.c | 6 |
13 files changed, 651 insertions, 389 deletions
diff --git a/src/or/circuitlist.c b/src/or/circuitlist.c index 5a20e7ebd..065559620 100644 --- a/src/or/circuitlist.c +++ b/src/or/circuitlist.c @@ -447,11 +447,9 @@ circuit_free(circuit_t *circ) rend_data_free(ocirc->rend_data); } else { or_circuit_t *ocirc = TO_OR_CIRCUIT(circ); -#ifdef ENABLE_BUFFER_STATS /* Remember cell statistics for this circuit before deallocating. */ if (get_options()->CellStatistics) - add_circ_to_buffer_stats(circ, time(NULL)); -#endif + rep_hist_buffer_stats_add_circ(circ, time(NULL)); mem = ocirc; memlen = sizeof(or_circuit_t); tor_assert(circ->magic == OR_CIRCUIT_MAGIC); diff --git a/src/or/config.c b/src/or/config.c index 7944aa100..b7317c75d 100644 --- a/src/or/config.c +++ b/src/or/config.c @@ -188,12 +188,10 @@ static config_var_t _option_vars[] = { V(DirPort, UINT, "0"), V(DirPortFrontPage, FILENAME, NULL), OBSOLETE("DirPostPeriod"), -#ifdef ENABLE_DIRREQ_STATS OBSOLETE("DirRecordUsageByCountry"), OBSOLETE("DirRecordUsageGranularity"), OBSOLETE("DirRecordUsageRetainIPs"), OBSOLETE("DirRecordUsageSaveInterval"), -#endif V(DirReqStatistics, BOOL, "0"), VAR("DirServer", LINELIST, DirServers, NULL), V(DNSPort, UINT, "0"), @@ -210,6 +208,7 @@ static config_var_t _option_vars[] = { V(ExitPolicy, LINELIST, NULL), V(ExitPolicyRejectPrivate, BOOL, "1"), V(ExitPortStatistics, BOOL, "0"), + V(ExtraInfoStatistics, BOOL, "0"), V(FallbackNetworkstatusFile, FILENAME, SHARE_DATADIR PATH_SEPARATOR "tor" PATH_SEPARATOR "fallback-consensus"), V(FascistFirewall, BOOL, "0"), @@ -1413,47 +1412,13 @@ options_act(or_options_t *old_options) tor_free(actual_fname); } - if (options->DirReqStatistics) { -#ifdef ENABLE_DIRREQ_STATS + if (options->DirReqStatistics && !geoip_is_loaded()) { /* Check if GeoIP database could be loaded. */ - if (!geoip_is_loaded()) { - log_warn(LD_CONFIG, "Configured to measure directory request " - "statistics, but no GeoIP database found!"); - return -1; - } - log_notice(LD_CONFIG, "Configured to count directory requests by " - "country and write aggregate statistics to disk. Check the " - "dirreq-stats file in your data directory that will first " - "be written in 24 hours from now."); -#else - log_warn(LD_CONFIG, "DirReqStatistics enabled, but Tor was built " - "without support for directory request statistics."); -#endif + log_warn(LD_CONFIG, "Configured to measure directory request " + "statistics, but no GeoIP database found!"); + return -1; } -#ifdef ENABLE_EXIT_STATS - if (options->ExitPortStatistics) - log_notice(LD_CONFIG, "Configured to measure exit port statistics. " - "Look for the exit-stats file that will first be written to " - "the data directory in 24 hours from now."); -#else - if (options->ExitPortStatistics) - log_warn(LD_CONFIG, "ExitPortStatistics enabled, but Tor was built " - "without port statistics support."); -#endif - -#ifdef ENABLE_BUFFER_STATS - if (options->CellStatistics) - log_notice(LD_CONFIG, "Configured to measure cell statistics. Look " - "for the buffer-stats file that will first be written to " - "the data directory in 24 hours from now."); -#else - if (options->CellStatistics) - log_warn(LD_CONFIG, "CellStatistics enabled, but Tor was built " - "without cell statistics support."); -#endif - -#ifdef ENABLE_ENTRY_STATS if (options->EntryStatistics) { if (should_record_bridge_info(options)) { /* Don't allow measuring statistics on entry guards when configured @@ -1466,17 +1431,9 @@ options_act(or_options_t *old_options) log_warn(LD_CONFIG, "Configured to measure entry node statistics, " "but no GeoIP database found!"); return -1; - } else - log_notice(LD_CONFIG, "Configured to measure entry node " - "statistics. Look for the entry-stats file that will " - "first be written to the data directory in 24 hours " - "from now."); + } } -#else - if (options->EntryStatistics) - log_warn(LD_CONFIG, "EntryStatistics enabled, but Tor was built " - "without entry node statistics support."); -#endif + /* Check if we need to parse and add the EntryNodes config option. */ if (options->EntryNodes && (!old_options || @@ -3861,6 +3818,16 @@ options_transition_allowed(or_options_t *old, or_options_t *new_val, return -1; } + if (old->CellStatistics != new_val->CellStatistics || + old->DirReqStatistics != new_val->DirReqStatistics || + old->EntryStatistics != new_val->EntryStatistics || + old->ExitPortStatistics != new_val->ExitPortStatistics) { + *msg = tor_strdup("While Tor is running, changing either " + "CellStatistics, DirReqStatistics, EntryStatistics, " + "or ExitPortStatistics is not allowed."); + return -1; + } + return 0; } diff --git a/src/or/connection.c b/src/or/connection.c index fac56593b..49c94c111 100644 --- a/src/or/connection.c +++ b/src/or/connection.c @@ -2054,12 +2054,12 @@ connection_buckets_decrement(connection_t *conn, time_t now, if (num_read > 0) { if (conn->type == CONN_TYPE_EXIT) - rep_hist_note_exit_bytes_read(conn->port, num_read, now); + rep_hist_note_exit_bytes_read(conn->port, num_read); rep_hist_note_bytes_read(num_read, now); } if (num_written > 0) { if (conn->type == CONN_TYPE_EXIT) - rep_hist_note_exit_bytes_written(conn->port, num_written, now); + rep_hist_note_exit_bytes_written(conn->port, num_written); rep_hist_note_bytes_written(num_written, now); } @@ -2652,13 +2652,13 @@ connection_handle_write(connection_t *conn, int force) /* else open, or closing */ result = flush_buf_tls(or_conn->tls, conn->outbuf, max_to_write, &conn->outbuf_flushlen); -#ifdef ENABLE_DIRREQ_STATS + /* If we just flushed the last bytes, check if this tunneled dir * request is done. */ if (buf_datalen(conn->outbuf) == 0 && conn->dirreq_id) geoip_change_dirreq_state(conn->dirreq_id, DIRREQ_TUNNELED, DIRREQ_OR_CONN_BUFFER_FLUSHED); -#endif + switch (result) { CASE_TOR_TLS_ERROR_ANY: case TOR_TLS_CLOSE: diff --git a/src/or/connection_edge.c b/src/or/connection_edge.c index 04fffd9f5..f25202725 100644 --- a/src/or/connection_edge.c +++ b/src/or/connection_edge.c @@ -333,7 +333,7 @@ connection_edge_finished_connecting(edge_connection_t *edge_conn) escaped_safe_str(conn->address),conn->port, safe_str(fmt_addr(&conn->addr))); - rep_hist_note_exit_stream_opened(conn->port, approx_time()); + rep_hist_note_exit_stream_opened(conn->port); conn->state = EXIT_CONN_STATE_OPEN; connection_watch_events(conn, READ_EVENT); /* stop writing, keep reading */ @@ -2544,11 +2544,11 @@ connection_exit_begin_conn(cell_t *cell, circuit_t *circ) log_debug(LD_EXIT,"Creating new exit connection."); n_stream = edge_connection_new(CONN_TYPE_EXIT, AF_INET); -#ifdef ENABLE_DIRREQ_STATS + /* Remember the tunneled request ID in the new edge connection, so that * we can measure download times. */ TO_CONN(n_stream)->dirreq_id = circ->dirreq_id; -#endif + n_stream->_base.purpose = EXIT_PURPOSE_CONNECT; n_stream->stream_id = rh.stream_id; @@ -2785,11 +2785,10 @@ connection_exit_connect_dir(edge_connection_t *exitconn) dirconn->_base.purpose = DIR_PURPOSE_SERVER; dirconn->_base.state = DIR_CONN_STATE_SERVER_COMMAND_WAIT; -#ifdef ENABLE_DIRREQ_STATS /* Note that the new dir conn belongs to the same tunneled request as * the edge conn, so that we can measure download times. */ TO_CONN(dirconn)->dirreq_id = TO_CONN(exitconn)->dirreq_id; -#endif + connection_link_connections(TO_CONN(dirconn), TO_CONN(exitconn)); if (connection_add(TO_CONN(exitconn))<0) { diff --git a/src/or/directory.c b/src/or/directory.c index 3a72b9432..d37da18e6 100644 --- a/src/or/directory.c +++ b/src/or/directory.c @@ -2573,7 +2573,6 @@ directory_handle_command_get(dir_connection_t *conn, const char *headers, goto done; } -#ifdef ENABLE_DIRREQ_STATS { struct in_addr in; if (tor_inet_aton((TO_CONN(conn))->address, &in)) { @@ -2589,7 +2588,6 @@ directory_handle_command_get(dir_connection_t *conn, const char *headers, DIRREQ_DIRECT); } } -#endif // note_request(request_type,dlen); (void) request_type; @@ -3221,7 +3219,6 @@ connection_dir_finished_flushing(dir_connection_t *conn) tor_assert(conn); tor_assert(conn->_base.type == CONN_TYPE_DIR); -#ifdef ENABLE_DIRREQ_STATS /* Note that we have finished writing the directory response. For direct * connections this means we're done, for tunneled connections its only * an intermediate step. */ @@ -3232,7 +3229,6 @@ connection_dir_finished_flushing(dir_connection_t *conn) geoip_change_dirreq_state(TO_CONN(conn)->global_identifier, DIRREQ_DIRECT, DIRREQ_FLUSHING_DIR_CONN_FINISHED); -#endif switch (conn->_base.state) { case DIR_CONN_STATE_CLIENT_SENDING: log_debug(LD_DIR,"client finished sending command."); diff --git a/src/or/geoip.c b/src/or/geoip.c index c61ac3c5f..befc3d9e0 100644 --- a/src/or/geoip.c +++ b/src/or/geoip.c @@ -12,8 +12,6 @@ #include "ht.h" static void clear_geoip_db(void); -static void dump_geoip_stats(void); -static void dump_entry_stats(void); /** An entry from the GeoIP file: maps an IP range to a country. */ typedef struct geoip_entry_t { @@ -347,7 +345,6 @@ geoip_determine_shares(time_t now) last_time_determined_shares = now; } -#ifdef ENABLE_DIRREQ_STATS /** Calculate which fraction of v2 and v3 directory requests aimed at caches * have been sent to us since the last call of this function up to time * <b>now</b>. Set *<b>v2_share_out</b> and *<b>v3_share_out</b> to the @@ -367,7 +364,23 @@ geoip_get_mean_shares(time_t now, double *v2_share_out, share_seconds = 0; return 0; } -#endif + +/* Rotate period of v2 and v3 network status requests. */ +static void +rotate_request_period(void) +{ + SMARTLIST_FOREACH(geoip_countries, geoip_country_t *, c, { + memmove(&c->n_v2_ns_requests[0], &c->n_v2_ns_requests[1], + sizeof(uint32_t)*(REQUEST_HIST_LEN-1)); + memmove(&c->n_v3_ns_requests[0], &c->n_v3_ns_requests[1], + sizeof(uint32_t)*(REQUEST_HIST_LEN-1)); + c->n_v2_ns_requests[REQUEST_HIST_LEN-1] = 0; + c->n_v3_ns_requests[REQUEST_HIST_LEN-1] = 0; + }); + current_request_period_starts += REQUEST_HIST_PERIOD; + if (n_old_request_periods < REQUEST_HIST_LEN-1) + ++n_old_request_periods; +} /** Note that we've seen a client connect from the IP <b>addr</b> (host order) * at time <b>now</b>. Ignored by all but bridges and directories if @@ -379,55 +392,37 @@ geoip_note_client_seen(geoip_client_action_t action, or_options_t *options = get_options(); clientmap_entry_t lookup, *ent; if (action == GEOIP_CLIENT_CONNECT) { -#ifdef ENABLE_ENTRY_STATS - if (!options->EntryStatistics) + /* Only remember statistics as entry guard or as bridge. */ + if (!options->EntryStatistics || + (!(options->BridgeRelay && options->BridgeRecordUsageByCountry))) return; -#else - if (!(options->BridgeRelay && options->BridgeRecordUsageByCountry)) - return; -#endif /* Did we recently switch from bridge to relay or back? */ if (client_history_starts > now) return; } else { -#ifndef ENABLE_DIRREQ_STATS - return; -#else if (options->BridgeRelay || options->BridgeAuthoritativeDir || !options->DirReqStatistics) return; -#endif } - /* Rotate the current request period. */ - while (current_request_period_starts + REQUEST_HIST_PERIOD < now) { - if (!geoip_countries) - geoip_countries = smartlist_create(); - if (!current_request_period_starts) { - current_request_period_starts = now; - break; + /* As a bridge that doesn't rotate request periods every 24 hours, + * possibly rotate now. */ + if (options->BridgeRelay) { + while (current_request_period_starts + REQUEST_HIST_PERIOD < now) { + if (!geoip_countries) + geoip_countries = smartlist_create(); + if (!current_request_period_starts) { + current_request_period_starts = now; + break; + } + /* Also discard all items in the client history that are too old. + * (This only works here because bridge and directory stats are + * independent. Otherwise, we'd only want to discard those items + * with action GEOIP_CLIENT_NETWORKSTATUS{_V2}.) */ + geoip_remove_old_clients(current_request_period_starts); + /* Now rotate request period */ + rotate_request_period(); } - /* Also discard all items in the client history that are too old. - * (This only works here because bridge and directory stats are - * independent. Otherwise, we'd only want to discard those items - * with action GEOIP_CLIENT_NETWORKSTATUS{_V2}.) */ - geoip_remove_old_clients(current_request_period_starts); - /* Before rotating, write the current stats to disk. */ - dump_geoip_stats(); - if (get_options()->EntryStatistics) - dump_entry_stats(); - /* Now rotate request period */ - SMARTLIST_FOREACH(geoip_countries, geoip_country_t *, c, { - memmove(&c->n_v2_ns_requests[0], &c->n_v2_ns_requests[1], - sizeof(uint32_t)*(REQUEST_HIST_LEN-1)); - memmove(&c->n_v3_ns_requests[0], &c->n_v3_ns_requests[1], - sizeof(uint32_t)*(REQUEST_HIST_LEN-1)); - c->n_v2_ns_requests[REQUEST_HIST_LEN-1] = 0; - c->n_v3_ns_requests[REQUEST_HIST_LEN-1] = 0; - }); - current_request_period_starts += REQUEST_HIST_PERIOD; - if (n_old_request_periods < REQUEST_HIST_LEN-1) - ++n_old_request_periods; } lookup.ipaddr = addr; @@ -495,7 +490,6 @@ geoip_remove_old_clients(time_t cutoff) client_history_starts = cutoff; } -#ifdef ENABLE_DIRREQ_STATS /** How many responses are we giving to clients requesting v2 network * statuses? */ static uint32_t ns_v2_responses[GEOIP_NS_RESPONSE_NUM]; @@ -503,7 +497,6 @@ static uint32_t ns_v2_responses[GEOIP_NS_RESPONSE_NUM]; /** How many responses are we giving to clients requesting v3 network * statuses? */ static uint32_t ns_v3_responses[GEOIP_NS_RESPONSE_NUM]; -#endif /** Note that we've rejected a client's request for a v2 or v3 network * status, encoded in <b>action</b> for reason <b>reason</b> at time @@ -512,7 +505,6 @@ void geoip_note_ns_response(geoip_client_action_t action, geoip_ns_response_t response) { -#ifdef ENABLE_DIRREQ_STATS static int arrays_initialized = 0; if (!get_options()->DirReqStatistics) return; @@ -528,10 +520,6 @@ geoip_note_ns_response(geoip_client_action_t action, ns_v3_responses[response]++; else ns_v2_responses[response]++; -#else - (void) action; - (void) response; -#endif } /** Do not mention any country from which fewer than this number of IPs have @@ -709,7 +697,6 @@ geoip_change_dirreq_state(uint64_t dirreq_id, dirreq_type_t type, } } -#ifdef ENABLE_DIRREQ_STATS /** Return a newly allocated comma-separated string containing statistics * on network status downloads. The string contains the number of completed * requests, timeouts, and still running requests as well as the download @@ -811,25 +798,18 @@ geoip_get_dirreq_history(geoip_client_action_t action, smartlist_free(dirreq_completed); return result; } -#endif /** How long do we have to have observed per-country request history before we * are willing to talk about it? */ #define GEOIP_MIN_OBSERVATION_TIME (12*60*60) -/** Return a newly allocated comma-separated string containing entries for all - * the countries from which we've seen enough clients connect. The entry - * format is cc=num where num is the number of IPs we've seen connecting from - * that country, and cc is a lowercased country code. Returns NULL if we don't - * want to export geoip data yet. */ -char * -geoip_get_client_history(time_t now, geoip_client_action_t action) +/** Helper for geoip_get_client_history_dirreq() and + * geoip_get_client_history_bridge(). */ +static char * +geoip_get_client_history(time_t now, geoip_client_action_t action, + int min_observation_time, unsigned granularity) { char *result = NULL; - int min_observation_time = GEOIP_MIN_OBSERVATION_TIME; -#ifdef ENABLE_DIRREQ_STATS - min_observation_time = DIR_RECORD_USAGE_MIN_OBSERVATION_TIME; -#endif if (!geoip_is_loaded()) return NULL; if (client_history_starts < (now - min_observation_time)) { @@ -841,10 +821,6 @@ geoip_get_client_history(time_t now, geoip_client_action_t action) clientmap_entry_t **ent; unsigned *counts = tor_malloc_zero(sizeof(unsigned)*n_countries); unsigned total = 0; - unsigned granularity = IP_GRANULARITY; -#ifdef ENABLE_DIRREQ_STATS - granularity = DIR_RECORD_USAGE_GRANULARITY; -#endif HT_FOREACH(ent, clientmap, &client_history) { int country; if ((*ent)->action != (int)action) @@ -900,6 +876,34 @@ geoip_get_client_history(time_t now, geoip_client_action_t action) return result; } +/** Return a newly allocated comma-separated string containing entries for + * all the countries from which we've seen enough clients connect as a + * directory. The entry format is cc=num where num is the number of IPs + * we've seen connecting from that country, and cc is a lowercased country + * code. Returns NULL if we don't want to export geoip data yet. */ +char * +geoip_get_client_history_dirreq(time_t now, + geoip_client_action_t action) +{ + return geoip_get_client_history(now, action, + DIR_RECORD_USAGE_MIN_OBSERVATION_TIME, + DIR_RECORD_USAGE_GRANULARITY); +} + +/** Return a newly allocated comma-separated string containing entries for + * all the countries from which we've seen enough clients connect as a + * bridge. The entry format is cc=num where num is the number of IPs + * we've seen connecting from that country, and cc is a lowercased country + * code. Returns NULL if we don't want to export geoip data yet. */ +char * +geoip_get_client_history_bridge(time_t now, + geoip_client_action_t action) +{ + return geoip_get_client_history(now, action, + GEOIP_MIN_OBSERVATION_TIME, + IP_GRANULARITY); +} + /** Return a newly allocated string holding the per-country request history * for <b>action</b> in a format suitable for an extra-info document, or NULL * on failure. */ @@ -910,10 +914,6 @@ geoip_get_request_history(time_t now, geoip_client_action_t action) char *result; unsigned granularity = IP_GRANULARITY; int min_observation_time = GEOIP_MIN_OBSERVATION_TIME; -#ifdef ENABLE_DIRREQ_STATS - granularity = DIR_RECORD_USAGE_GRANULARITY; - min_observation_time = DIR_RECORD_USAGE_MIN_OBSERVATION_TIME; -#endif if (client_history_starts >= (now - min_observation_time)) return NULL; @@ -955,16 +955,23 @@ geoip_get_request_history(time_t now, geoip_client_action_t action) return result; } -/** Store all our geoip statistics into $DATADIR/dirreq-stats. */ -static void -dump_geoip_stats(void) +/** Start time of directory request stats. */ +static time_t start_of_dirreq_stats_interval; + +/** Initialize directory request stats. */ +void +geoip_dirreq_stats_init(time_t now) +{ + start_of_dirreq_stats_interval = now; +} + +/** Write dirreq statistics to $DATADIR/stats/dirreq-stats. */ +void +geoip_dirreq_stats_write(time_t now) { -#ifdef ENABLE_DIRREQ_STATS - time_t now = time(NULL); - time_t request_start; - char *filename = get_datadir_fname("dirreq-stats"); + char *statsdir = NULL, *filename = NULL; char *data_v2 = NULL, *data_v3 = NULL; - char since[ISO_TIME_LEN+1], written[ISO_TIME_LEN+1]; + char written[ISO_TIME_LEN+1]; open_file_t *open_file = NULL; double v2_share = 0.0, v3_share = 0.0; FILE *out; @@ -973,28 +980,33 @@ dump_geoip_stats(void) if (!get_options()->DirReqStatistics) goto done; - data_v2 = geoip_get_client_history(now, GEOIP_CLIENT_NETWORKSTATUS_V2); - data_v3 = geoip_get_client_history(now, GEOIP_CLIENT_NETWORKSTATUS); - format_iso_time(since, geoip_get_history_start()); + /* Discard all items in the client history that are too old. */ + geoip_remove_old_clients(start_of_dirreq_stats_interval); + + statsdir = get_datadir_fname("stats"); + if (check_private_dir(statsdir, CPD_CREATE) < 0) + goto done; + filename = get_datadir_fname("stats"PATH_SEPARATOR"dirreq-stats"); + data_v2 = geoip_get_client_history_dirreq(now, + GEOIP_CLIENT_NETWORKSTATUS_V2); + data_v3 = geoip_get_client_history_dirreq(now, + GEOIP_CLIENT_NETWORKSTATUS); format_iso_time(written, now); out = start_writing_to_stdio_file(filename, OPEN_FLAGS_APPEND, 0600, &open_file); if (!out) goto done; - if (fprintf(out, "written %s\nstarted-at %s\nns-ips %s\nns-v2-ips %s\n", - written, since, + if (fprintf(out, "dirreq-stats-end %s (%d s)\ndirreq-v3-ips %s\n" + "dirreq-v2-ips %s\n", written, + (unsigned) (now - start_of_dirreq_stats_interval), data_v3 ? data_v3 : "", data_v2 ? data_v2 : "") < 0) goto done; tor_free(data_v2); tor_free(data_v3); - request_start = current_request_period_starts - - (n_old_request_periods * REQUEST_HIST_PERIOD); - format_iso_time(since, request_start); data_v2 = geoip_get_request_history(now, GEOIP_CLIENT_NETWORKSTATUS_V2); data_v3 = geoip_get_request_history(now, GEOIP_CLIENT_NETWORKSTATUS); - if (fprintf(out, "requests-start %s\nn-ns-reqs %s\nn-v2-ns-reqs %s\n", - since, + if (fprintf(out, "dirreq-v3-reqs %s\ndirreq-v2-reqs %s\n", data_v3 ? data_v3 : "", data_v2 ? data_v2 : "") < 0) goto done; #define RESPONSE_GRANULARITY 8 @@ -1005,7 +1017,7 @@ dump_geoip_stats(void) ns_v3_responses[i], RESPONSE_GRANULARITY); } #undef RESPONSE_GRANULARITY - if (fprintf(out, "n-ns-resp ok=%u,not-enough-sigs=%u,unavailable=%u," + if (fprintf(out, "dirreq-v3-resp ok=%u,not-enough-sigs=%u,unavailable=%u," "not-found=%u,not-modified=%u,busy=%u\n", ns_v3_responses[GEOIP_SUCCESS], ns_v3_responses[GEOIP_REJECT_NOT_ENOUGH_SIGS], @@ -1014,7 +1026,7 @@ dump_geoip_stats(void) ns_v3_responses[GEOIP_REJECT_NOT_MODIFIED], ns_v3_responses[GEOIP_REJECT_BUSY]) < 0) goto done; - if (fprintf(out, "n-v2-ns-resp ok=%u,unavailable=%u," + if (fprintf(out, "dirreq-v2-resp ok=%u,unavailable=%u," "not-found=%u,not-modified=%u,busy=%u\n", ns_v2_responses[GEOIP_SUCCESS], ns_v2_responses[GEOIP_REJECT_UNAVAILABLE], @@ -1025,9 +1037,9 @@ dump_geoip_stats(void) memset(ns_v2_responses, 0, sizeof(ns_v2_responses)); memset(ns_v3_responses, 0, sizeof(ns_v3_responses)); if (!geoip_get_mean_shares(now, &v2_share, &v3_share)) { - if (fprintf(out, "v2-ns-share %0.2lf%%\n", v2_share*100) < 0) + if (fprintf(out, "dirreq-v2-share %0.2lf%%\n", v2_share*100) < 0) goto done; - if (fprintf(out, "v3-ns-share %0.2lf%%\n", v3_share*100) < 0) + if (fprintf(out, "dirreq-v3-share %0.2lf%%\n", v3_share*100) < 0) goto done; } @@ -1035,7 +1047,7 @@ dump_geoip_stats(void) DIRREQ_DIRECT); data_v3 = geoip_get_dirreq_history(GEOIP_CLIENT_NETWORKSTATUS, DIRREQ_DIRECT); - if (fprintf(out, "ns-direct-dl %s\nns-v2-direct-dl %s\n", + if (fprintf(out, "dirreq-v3-direct-dl %s\ndirreq-v2-direct-dl %s\n", data_v3 ? data_v3 : "", data_v2 ? data_v2 : "") < 0) goto done; tor_free(data_v2); @@ -1044,53 +1056,78 @@ dump_geoip_stats(void) DIRREQ_TUNNELED); data_v3 = geoip_get_dirreq_history(GEOIP_CLIENT_NETWORKSTATUS, DIRREQ_TUNNELED); - if (fprintf(out, "ns-tunneled-dl %s\nns-v2-tunneled-dl %s\n", + if (fprintf(out, "dirreq-v3-tunneled-dl %s\ndirreq-v2-tunneled-dl %s\n", data_v3 ? data_v3 : "", data_v2 ? data_v2 : "") < 0) goto done; finish_writing_to_file(open_file); open_file = NULL; + + /* Rotate request period */ + rotate_request_period(); + + start_of_dirreq_stats_interval = now; + done: if (open_file) abort_writing_to_file(open_file); tor_free(filename); + tor_free(statsdir); tor_free(data_v2); tor_free(data_v3); -#endif } -/** Store all our geoip statistics as entry guards into - * $DATADIR/entry-stats. */ -static void -dump_entry_stats(void) +/** Start time of entry stats. */ +static time_t start_of_entry_stats_interval; + +/** Initialize entry stats. */ +void +geoip_entry_stats_init(time_t now) +{ + start_of_entry_stats_interval = now; +} + +/** Write entry statistics to $DATADIR/stats/entry-stats. */ +void +geoip_entry_stats_write(time_t now) { -#ifdef ENABLE_ENTRY_STATS - time_t now = time(NULL); - char *filename = get_datadir_fname("entry-stats"); + char *statsdir = NULL, *filename = NULL; char *data = NULL; - char since[ISO_TIME_LEN+1], written[ISO_TIME_LEN+1]; + char written[ISO_TIME_LEN+1]; open_file_t *open_file = NULL; FILE *out; - data = geoip_get_client_history(now, GEOIP_CLIENT_CONNECT); - format_iso_time(since, geoip_get_history_start()); + if (!get_options()->EntryStatistics) + goto done; + + /* Discard all items in the client history that are too old. */ + geoip_remove_old_clients(start_of_entry_stats_interval); + + statsdir = get_datadir_fname("stats"); + if (check_private_dir(statsdir, CPD_CREATE) < 0) + goto done; + filename = get_datadir_fname("stats"PATH_SEPARATOR"entry-stats"); + data = geoip_get_client_history_dirreq(now, GEOIP_CLIENT_CONNECT); format_iso_time(written, now); out = start_writing_to_stdio_file(filename, OPEN_FLAGS_APPEND, 0600, &open_file); if (!out) goto done; - if (fprintf(out, "written %s\nstarted-at %s\nips %s\n", - written, since, data ? data : "") < 0) + if (fprintf(out, "entry-stats-end %s (%u s)\nentry-ips %s\n", + written, (unsigned) (now - start_of_entry_stats_interval), + data ? data : "") < 0) goto done; + start_of_entry_stats_interval = now; + finish_writing_to_file(open_file); open_file = NULL; done: if (open_file) abort_writing_to_file(open_file); tor_free(filename); + tor_free(statsdir); tor_free(data); -#endif } /** Helper used to implement GETINFO ip-to-country/... controller command. */ diff --git a/src/or/main.c b/src/or/main.c index 52cc0282b..5701727ad 100644 --- a/src/or/main.c +++ b/src/or/main.c @@ -830,9 +830,7 @@ run_scheduled_events(time_t now) static time_t time_to_clean_caches = 0; static time_t time_to_recheck_bandwidth = 0; static time_t time_to_check_for_expired_networkstatus = 0; -#ifdef ENABLE_BUFFER_STATS - static time_t time_to_dump_buffer_stats = 0; -#endif + static time_t time_to_write_stats_files = 0; static time_t time_to_retry_dns_init = 0; or_options_t *options = get_options(); int i; @@ -960,13 +958,44 @@ run_scheduled_events(time_t now) time_to_check_for_expired_networkstatus = now + CHECK_EXPIRED_NS_INTERVAL; } -#ifdef ENABLE_BUFFER_STATS - if (time_to_dump_buffer_stats < now) { - if (get_options()->CellStatistics && time_to_dump_buffer_stats) - dump_buffer_stats(); - time_to_dump_buffer_stats = now + DUMP_BUFFER_STATS_INTERVAL; + /* 1g. Check whether we should write statistics to disk. + */ + if (time_to_write_stats_files >= 0 && time_to_write_stats_files < now) { +#define WRITE_STATS_INTERVAL (24*60*60) + if (options->CellStatistics || options->DirReqStatistics || + options->EntryStatistics || options->ExitPortStatistics) { + if (!time_to_write_stats_files) { + /* Initialize stats. */ + if (options->CellStatistics) + rep_hist_buffer_stats_init(now); + if (options->DirReqStatistics) + geoip_dirreq_stats_init(now); + if (options->EntryStatistics) + geoip_entry_stats_init(now); + if (options->ExitPortStatistics) + rep_hist_exit_stats_init(now); + log_notice(LD_CONFIG, "Configured to measure statistics. Look for " + "the *-stats files that will first be written to the " + "data directory in %d hours from now.", + WRITE_STATS_INTERVAL / (60 * 60)); + time_to_write_stats_files = now + WRITE_STATS_INTERVAL; + } else { + /* Write stats to disk. */ + time_to_write_stats_files += WRITE_STATS_INTERVAL; + if (options->CellStatistics) + rep_hist_buffer_stats_write(time_to_write_stats_files); + if (options->DirReqStatistics) + geoip_dirreq_stats_write(time_to_write_stats_files); + if (options->EntryStatistics) + geoip_entry_stats_write(time_to_write_stats_files); + if (options->ExitPortStatistics) + rep_hist_exit_stats_write(time_to_write_stats_files); + } + } else { + /* Never write stats to disk */ + time_to_write_stats_files = -1; + } } -#endif /* Remove old information from rephist and the rend cache. */ if (time_to_clean_caches < now) { diff --git a/src/or/or.h b/src/or/or.h index 1aa40af61..aaae9053e 100644 --- a/src/or/or.h +++ b/src/or/or.h @@ -20,12 +20,6 @@ #ifndef INSTRUMENT_DOWNLOADS #define INSTRUMENT_DOWNLOADS 1 #endif -#ifndef ENABLE_DIRREQ_STATS -#define ENABLE_DIRREQ_STATS 1 -#endif -#ifndef ENABLE_BUFFER_STATS -#define ENABLE_BUFFER_STATS 1 -#endif #endif #ifdef MS_WINDOWS @@ -854,17 +848,30 @@ typedef struct var_cell_t { typedef struct packed_cell_t { struct packed_cell_t *next; /**< Next cell queued on this circuit. */ char body[CELL_NETWORK_SIZE]; /**< Cell as packed for network. */ -#ifdef ENABLE_BUFFER_STATS - struct timeval packed_timeval; /**< When was this cell packed? */ -#endif } packed_cell_t; +/** Number of cells added to a circuit queue including their insertion + * time on 10 millisecond detail; used for buffer statistics. */ +typedef struct insertion_time_elem_t { + struct insertion_time_elem_t *next; /**< Next element in queue. */ + uint32_t insertion_time; /**< When were cells inserted (in 10 ms steps + * starting at 0:00 of the current day)? */ + unsigned counter; /**< How many cells were inserted? */ +} insertion_time_elem_t; + +/** Queue of insertion times. */ +typedef struct insertion_time_queue_t { + struct insertion_time_elem_t *first; /**< First element in queue. */ + struct insertion_time_elem_t *last; /**< Last element in queue. */ +} insertion_time_queue_t; + /** A queue of cells on a circuit, waiting to be added to the * or_connection_t's outbuf. */ typedef struct cell_queue_t { packed_cell_t *head; /**< The first cell, or NULL if the queue is empty. */ packed_cell_t *tail; /**< The last cell, or NULL if the queue is empty. */ int n; /**< The number of cells in the queue. */ + insertion_time_queue_t *insertion_times; /**< Insertion times of cells. */ } cell_queue_t; /** Beginning of a RELAY cell payload. */ @@ -991,11 +998,8 @@ typedef struct connection_t { * to the evdns_server_port is uses to listen to and answer connections. */ struct evdns_server_port *dns_server_port; -#ifdef ENABLE_DIRREQ_STATS /** Unique ID for measuring tunneled network status requests. */ uint64_t dirreq_id; -#endif - } connection_t; /** Stores flags and information related to the portion of a v2 Tor OR @@ -1985,10 +1989,9 @@ typedef struct circuit_t { * linked to an OR connection. */ struct circuit_t *prev_active_on_n_conn; struct circuit_t *next; /**< Next circuit in linked list of all circuits. */ -#ifdef ENABLE_DIRREQ_STATS + /** Unique ID for measuring tunneled network status requests. */ uint64_t dirreq_id; -#endif } circuit_t; /** Largest number of relay_early cells that we can send on a given @@ -2112,7 +2115,6 @@ typedef struct or_circuit_t { /** True iff this circuit was made with a CREATE_FAST cell. */ unsigned int is_first_hop : 1; -#ifdef ENABLE_BUFFER_STATS /** Number of cells that were removed from circuit queue; reset every * time when writing buffer stats to disk. */ uint32_t processed_cells; @@ -2121,7 +2123,6 @@ typedef struct or_circuit_t { * exit-ward queues of this circuit; reset every time when writing * buffer stats to disk. */ uint64_t total_cell_waiting_time; -#endif } or_circuit_t; /** Convert a circuit subtype to a circuit_t.*/ @@ -2558,6 +2559,9 @@ typedef struct { /** If true, the user wants us to collect statistics as entry node. */ int EntryStatistics; + /** If true, include statistics file contents in extra-info documents. */ + int ExtraInfoStatistics; + /** If true, do not believe anybody who tells us that a domain resolves * to an internal address, or that an internal address has a PTR mapping. * Helps avoid some cross-site attacks. */ @@ -3697,15 +3701,11 @@ int dnsserv_launch_request(const char *name, int is_reverse); * leaking information. */ #define DIR_RECORD_USAGE_GRANULARITY 8 /** Time interval: Flush geoip data to disk this often. */ -#define DIR_RECORD_USAGE_RETAIN_IPS (24*60*60) +#define DIR_ENTRY_RECORD_USAGE_RETAIN_IPS (24*60*60) /** How long do we have to have observed per-country request history before * we are willing to talk about it? */ #define DIR_RECORD_USAGE_MIN_OBSERVATION_TIME (24*60*60) -/** Time interval: Flush geoip data to disk this often when measuring on an - * entry guard. */ -#define ENTRY_RECORD_USAGE_RETAIN_IPS (24*60*60) - #ifdef GEOIP_PRIVATE int geoip_parse_entry(const char *line); #endif @@ -3752,7 +3752,10 @@ typedef enum { void geoip_note_ns_response(geoip_client_action_t action, geoip_ns_response_t response); time_t geoip_get_history_start(void); -char *geoip_get_client_history(time_t now, geoip_client_action_t action); +char *geoip_get_client_history_dirreq(time_t now, + geoip_client_action_t action); +char *geoip_get_client_history_bridge(time_t now, + geoip_client_action_t action); char *geoip_get_request_history(time_t now, geoip_client_action_t action); int getinfo_helper_geoip(control_connection_t *control_conn, const char *question, char **answer); @@ -3792,6 +3795,11 @@ void geoip_start_dirreq(uint64_t dirreq_id, size_t response_size, void geoip_change_dirreq_state(uint64_t dirreq_id, dirreq_type_t type, dirreq_state_t new_state); +void geoip_dirreq_stats_init(time_t now); +void geoip_dirreq_stats_write(time_t now); +void geoip_entry_stats_init(time_t now); +void geoip_entry_stats_write(time_t now); + /********************************* hibernate.c **********************/ int accounting_parse_options(or_options_t *options, int validate_only); @@ -4133,17 +4141,11 @@ void rep_hist_note_extend_failed(const char *from_name, const char *to_name); void rep_hist_dump_stats(time_t now, int severity); void rep_hist_note_bytes_read(size_t num_bytes, time_t when); void rep_hist_note_bytes_written(size_t num_bytes, time_t when); -#ifdef ENABLE_EXIT_STATS -void rep_hist_note_exit_bytes_read(uint16_t port, size_t num_bytes, - time_t now); -void rep_hist_note_exit_bytes_written(uint16_t port, size_t num_bytes, - time_t now); -void rep_hist_note_exit_stream_opened(uint16_t port, time_t now); -#else -#define rep_hist_note_exit_bytes_read(p,n,t) STMT_NIL -#define rep_hist_note_exit_bytes_written(p,n,t) STMT_NIL -#define rep_hist_note_exit_stream_opened(p,t) STMT_NIL -#endif +void rep_hist_note_exit_bytes_read(uint16_t port, size_t num_bytes); +void rep_hist_note_exit_bytes_written(uint16_t port, size_t num_bytes); +void rep_hist_note_exit_stream_opened(uint16_t port); +void rep_hist_exit_stats_init(time_t now); +void rep_hist_exit_stats_write(time_t now); int rep_hist_bandwidth_assess(void); char *rep_hist_get_bandwidth_lines(int for_extrainfo); void rep_hist_update_state(or_state_t *state); @@ -4195,11 +4197,10 @@ void hs_usage_note_fetch_successful(const char *service_id, time_t now); void hs_usage_write_statistics_to_file(time_t now); void hs_usage_free_all(void); -#ifdef ENABLE_BUFFER_STATS -#define DUMP_BUFFER_STATS_INTERVAL (24*60*60) -void add_circ_to_buffer_stats(circuit_t *circ, time_t end_of_interval); -void dump_buffer_stats(void); -#endif +void rep_hist_buffer_stats_init(time_t now); +void rep_hist_buffer_stats_add_circ(circuit_t *circ, + time_t end_of_interval); +void rep_hist_buffer_stats_write(time_t now); /********************************* rendclient.c ***************************/ diff --git a/src/or/relay.c b/src/or/relay.c index 76577848f..c81b8311a 100644 --- a/src/or/relay.c +++ b/src/or/relay.c @@ -533,13 +533,11 @@ relay_send_command_from_edge(uint16_t stream_id, circuit_t *circ, log_debug(LD_OR,"delivering %d cell %s.", relay_command, cell_direction == CELL_DIRECTION_OUT ? "forward" : "backward"); -#ifdef ENABLE_DIRREQ_STATS /* If we are sending an END cell and this circuit is used for a tunneled * directory request, advance its state. */ if (relay_command == RELAY_COMMAND_END && circ->dirreq_id) geoip_change_dirreq_state(circ->dirreq_id, DIRREQ_TUNNELED, DIRREQ_END_CELL_SENT); -#endif if (cell_direction == CELL_DIRECTION_OUT && circ->n_conn) { /* if we're using relaybandwidthrate, this conn wants priority */ @@ -1047,7 +1045,6 @@ connection_edge_process_relay_cell(cell_t *cell, circuit_t *circ, "Begin cell for known stream. Dropping."); return 0; } -#ifdef ENABLE_DIRREQ_STATS if (rh.command == RELAY_COMMAND_BEGIN_DIR) { /* Assign this circuit and its app-ward OR connection a unique ID, * so that we can measure download times. The local edge and dir @@ -1057,7 +1054,6 @@ connection_edge_process_relay_cell(cell_t *cell, circuit_t *circ, circ->dirreq_id = ++next_id; TO_CONN(TO_OR_CIRCUIT(circ)->p_conn)->dirreq_id = circ->dirreq_id; } -#endif return connection_exit_begin_conn(cell, circ); case RELAY_COMMAND_DATA: @@ -1529,6 +1525,10 @@ static int total_cells_allocated = 0; /** A memory pool to allocate packed_cell_t objects. */ static mp_pool_t *cell_pool = NULL; +/** Memory pool to allocate insertion_time_elem_t objects used for cell + * statistics. */ +static mp_pool_t *it_pool = NULL; + /** Allocate structures to hold cells. */ void init_cell_pool(void) @@ -1537,7 +1537,8 @@ init_cell_pool(void) cell_pool = mp_pool_new(sizeof(packed_cell_t), 128*1024); } -/** Free all storage used to hold cells. */ +/** Free all storage used to hold cells (and insertion times if we measure + * cell statistics). */ void free_cell_pool(void) { @@ -1546,6 +1547,10 @@ free_cell_pool(void) mp_pool_destroy(cell_pool); cell_pool = NULL; } + if (it_pool) { + mp_pool_destroy(it_pool); + it_pool = NULL; + } } /** Free excess storage in cell pool. */ @@ -1621,11 +1626,35 @@ void cell_queue_append_packed_copy(cell_queue_t *queue, const cell_t *cell) { packed_cell_t *copy = packed_cell_copy(cell); -#ifdef ENABLE_BUFFER_STATS - /* Remember the exact time when this cell was put in the queue. */ - if (get_options()->CellStatistics) - tor_gettimeofday(©->packed_timeval); -#endif + /* Remember the time when this cell was put in the queue. */ + if (get_options()->CellStatistics) { + struct timeval now; + uint32_t added; + insertion_time_queue_t *it_queue = queue->insertion_times; + if (!it_pool) + it_pool = mp_pool_new(sizeof(insertion_time_elem_t), 1024); + tor_gettimeofday(&now); +#define SECONDS_IN_A_DAY 86400L + added = (now.tv_sec % SECONDS_IN_A_DAY) * 100L + now.tv_usec / 10000L; + if (!it_queue) { + it_queue = tor_malloc_zero(sizeof(insertion_time_queue_t)); + queue->insertion_times = it_queue; + } + if (it_queue->last && it_queue->last->insertion_time == added) { + it_queue->last->counter++; + } else { + insertion_time_elem_t *elem = mp_pool_get(it_pool); + elem->next = NULL; + elem->insertion_time = added; + elem->counter = 1; + if (it_queue->last) { + it_queue->last->next = elem; + it_queue->last = elem; + } else { + it_queue->first = it_queue->last = elem; + } + } + } cell_queue_append(queue, copy); } @@ -1642,6 +1671,14 @@ cell_queue_clear(cell_queue_t *queue) } queue->head = queue->tail = NULL; queue->n = 0; + if (queue->insertion_times) { + while (queue->insertion_times->first) { + insertion_time_elem_t *elem = queue->insertion_times->first; + queue->insertion_times->first = elem->next; + mp_pool_release(elem); + } + tor_free(queue->insertion_times); + } } /** Extract and return the cell at the head of <b>queue</b>; return NULL if @@ -1835,28 +1872,41 @@ connection_or_flush_from_first_active_circuit(or_connection_t *conn, int max, packed_cell_t *cell = cell_queue_pop(queue); tor_assert(*next_circ_on_conn_p(circ,conn)); -#ifdef ENABLE_BUFFER_STATS /* Calculate the exact time that this cell has spent in the queue. */ if (get_options()->CellStatistics && !CIRCUIT_IS_ORIGIN(circ)) { - struct timeval flushed_from_queue; + struct timeval now; + uint32_t flushed; uint32_t cell_waiting_time; - or_circuit_t *orcirc = TO_OR_CIRCUIT(circ); - tor_gettimeofday(&flushed_from_queue); - cell_waiting_time = (uint32_t) - tv_mdiff(&cell->packed_timeval, &flushed_from_queue); - - orcirc->total_cell_waiting_time += cell_waiting_time; - orcirc->processed_cells++; + insertion_time_queue_t *it_queue = queue->insertion_times; + tor_gettimeofday(&now); + flushed = (now.tv_sec % SECONDS_IN_A_DAY) * 100L + + now.tv_usec / 10000L; + if (!it_queue || !it_queue->first) { + log_warn(LD_BUG, "Cannot determine insertion time of cell."); + } else { + or_circuit_t *orcirc = TO_OR_CIRCUIT(circ); + insertion_time_elem_t *elem = it_queue->first; + cell_waiting_time = (flushed * 10L + SECONDS_IN_A_DAY * 1000L - + elem->insertion_time * 10L) % (SECONDS_IN_A_DAY * 1000L); +#undef SECONDS_IN_A_DAY + elem->counter--; + if (elem->counter < 1) { + it_queue->first = elem->next; + if (elem == it_queue->last) + it_queue->last = NULL; + mp_pool_release(elem); + } + orcirc->total_cell_waiting_time += cell_waiting_time; + orcirc->processed_cells++; + } } -#endif -#ifdef ENABLE_DIRREQ_STATS + /* If we just flushed our queue and this circuit is used for a * tunneled directory request, possibly advance its state. */ if (queue->n == 0 && TO_CONN(conn)->dirreq_id) geoip_change_dirreq_state(TO_CONN(conn)->dirreq_id, DIRREQ_TUNNELED, DIRREQ_CIRC_QUEUE_FLUSHED); -#endif connection_write_to_buf(cell->body, CELL_NETWORK_SIZE, TO_CONN(conn)); diff --git a/src/or/rephist.c b/src/or/rephist.c index c0b9ae14a..8d78ac26c 100644 --- a/src/or/rephist.c +++ b/src/or/rephist.c @@ -1320,10 +1320,7 @@ rep_hist_note_bytes_read(size_t num_bytes, time_t when) add_obs(read_array, when, num_bytes); } -#ifdef ENABLE_EXIT_STATS /* Some constants */ -/** How long are the intervals for measuring exit stats? */ -#define EXIT_STATS_INTERVAL_SEC (24 * 60 * 60) /** To what multiple should byte numbers be rounded up? */ #define EXIT_STATS_ROUND_UP_BYTES 1024 /** To what multiple should stream counts be rounded up? */ @@ -1337,118 +1334,137 @@ rep_hist_note_bytes_read(size_t num_bytes, time_t when) /* The following data structures are arrays and no fancy smartlists or maps, * so that all write operations can be done in constant time. This comes at * the price of some memory (1.25 MB) and linear complexity when writing - * stats. */ + * stats for measuring relays. */ /** Number of bytes read in current period by exit port */ -static uint64_t exit_bytes_read[EXIT_STATS_NUM_PORTS]; +static uint64_t *exit_bytes_read = NULL; /** Number of bytes written in current period by exit port */ -static uint64_t exit_bytes_written[EXIT_STATS_NUM_PORTS]; +static uint64_t *exit_bytes_written = NULL; /** Number of streams opened in current period by exit port */ -static uint32_t exit_streams[EXIT_STATS_NUM_PORTS]; +static uint32_t *exit_streams = NULL; /** When does the current exit stats period end? */ -static time_t end_of_current_exit_stats_period = 0; +static time_t start_of_exit_stats_interval; -/** Write exit stats for the current period to disk and reset counters. */ -static void -write_exit_stats(time_t when) +/** Initialize exit port stats. */ +void +rep_hist_exit_stats_init(time_t now) +{ + start_of_exit_stats_interval = now; + exit_bytes_read = tor_malloc_zero(EXIT_STATS_NUM_PORTS * + sizeof(uint64_t)); + exit_bytes_written = tor_malloc_zero(EXIT_STATS_NUM_PORTS * + sizeof(uint64_t)); + exit_streams = tor_malloc_zero(EXIT_STATS_NUM_PORTS * + sizeof(uint32_t)); +} + +/** Write exit stats to $DATADIR/stats/exit-stats and reset counters. */ +void +rep_hist_exit_stats_write(time_t now) { char t[ISO_TIME_LEN+1]; int r, i, comma; uint64_t *b, total_bytes, threshold_bytes, other_bytes; uint32_t other_streams; - char *filename = get_datadir_fname("exit-stats"); + char *statsdir = NULL, *filename = NULL; open_file_t *open_file = NULL; FILE *out = NULL; - log_debug(LD_HIST, "Considering writing exit port statistics to disk.."); - while (when > end_of_current_exit_stats_period) { - format_iso_time(t, end_of_current_exit_stats_period); - log_info(LD_HIST, "Writing exit port statistics to disk for period " - "ending at %s.", t); - - if (!open_file) { - out = start_writing_to_stdio_file(filename, OPEN_FLAGS_APPEND, - 0600, &open_file); - if (!out) { - log_warn(LD_HIST, "Couldn't open '%s'.", filename); - goto done; - } - } + if (!exit_streams) + return; /* Not initialized */ - /* written yyyy-mm-dd HH:MM:SS (n s) */ - if (fprintf(out, "written %s (%d s)\n", t, EXIT_STATS_INTERVAL_SEC) < 0) + statsdir = get_datadir_fname("stats"); + if (check_private_dir(statsdir, CPD_CREATE) < 0) + goto done; + filename = get_datadir_fname("stats"PATH_SEPARATOR"exit-stats"); + format_iso_time(t, now); + log_info(LD_HIST, "Writing exit port statistics to disk for period " + "ending at %s.", t); + + if (!open_file) { + out = start_writing_to_stdio_file(filename, OPEN_FLAGS_APPEND, + 0600, &open_file); + if (!out) { + log_warn(LD_HIST, "Couldn't open '%s'.", filename); goto done; - - /* Count the total number of bytes, so that we can attribute all - * observations below a threshold of 1 / EXIT_STATS_THRESHOLD_RECIPROCAL - * of all bytes to a special port 'other'. */ - total_bytes = 0; - for (i = 1; i < EXIT_STATS_NUM_PORTS; i++) { - total_bytes += exit_bytes_read[i]; - total_bytes += exit_bytes_written[i]; } - threshold_bytes = total_bytes / EXIT_STATS_THRESHOLD_RECIPROCAL; - - /* kibibytes-(read|written) port=kibibytes,.. */ - for (r = 0; r < 2; r++) { - b = r ? exit_bytes_read : exit_bytes_written; - tor_assert(b); - if (fprintf(out, "%s ", - r ? "kibibytes-read" : "kibibytes-written")<0) - goto done; - - comma = 0; - other_bytes = 0; - for (i = 1; i < EXIT_STATS_NUM_PORTS; i++) { - if (b[i] > 0) { - if (exit_bytes_read[i] + exit_bytes_written[i] > threshold_bytes) { - uint64_t num = round_uint64_to_next_multiple_of(b[i], - EXIT_STATS_ROUND_UP_BYTES); - num /= 1024; - if (fprintf(out, "%s%d="U64_FORMAT, - comma++ ? "," : "", i, - U64_PRINTF_ARG(num)) < 0) - goto done; - } else - other_bytes += b[i]; - } - } - other_bytes = round_uint64_to_next_multiple_of(other_bytes, - EXIT_STATS_ROUND_UP_BYTES); - other_bytes /= 1024; - if (fprintf(out, "%sother="U64_FORMAT"\n", - comma ? "," : "", U64_PRINTF_ARG(other_bytes))<0) - goto done; - } - /* streams-opened port=num,.. */ - if (fprintf(out, "streams-opened ")<0) + } + + /* written yyyy-mm-dd HH:MM:SS (n s) */ + if (fprintf(out, "exit-stats-end %s (%d s)\n", t, + (unsigned) (now - start_of_exit_stats_interval)) < 0) + goto done; + + /* Count the total number of bytes, so that we can attribute all + * observations below a threshold of 1 / EXIT_STATS_THRESHOLD_RECIPROCAL + * of all bytes to a special port 'other'. */ + total_bytes = 0; + for (i = 1; i < EXIT_STATS_NUM_PORTS; i++) { + total_bytes += exit_bytes_read[i]; + total_bytes += exit_bytes_written[i]; + } + threshold_bytes = total_bytes / EXIT_STATS_THRESHOLD_RECIPROCAL; + + /* exit-kibibytes-(read|written) port=kibibytes,.. */ + for (r = 0; r < 2; r++) { + b = r ? exit_bytes_read : exit_bytes_written; + tor_assert(b); + if (fprintf(out, "%s ", + r ? "exit-kibibytes-read" + : "exit-kibibytes-written") < 0) goto done; + comma = 0; - other_streams = 0; + other_bytes = 0; for (i = 1; i < EXIT_STATS_NUM_PORTS; i++) { - if (exit_streams[i] > 0) { + if (b[i] > 0) { if (exit_bytes_read[i] + exit_bytes_written[i] > threshold_bytes) { - uint32_t num = round_uint32_to_next_multiple_of(exit_streams[i], - EXIT_STATS_ROUND_UP_STREAMS); - if (fprintf(out, "%s%d=%u", - comma++ ? "," : "", i, num)<0) + uint64_t num = round_uint64_to_next_multiple_of(b[i], + EXIT_STATS_ROUND_UP_BYTES); + num /= 1024; + if (fprintf(out, "%s%d="U64_FORMAT, + comma++ ? "," : "", i, + U64_PRINTF_ARG(num)) < 0) goto done; } else - other_streams += exit_streams[i]; + other_bytes += b[i]; } } - other_streams = round_uint32_to_next_multiple_of(other_streams, - EXIT_STATS_ROUND_UP_STREAMS); - if (fprintf(out, "%sother=%u\n", - comma ? "," : "", other_streams)<0) + other_bytes = round_uint64_to_next_multiple_of(other_bytes, + EXIT_STATS_ROUND_UP_BYTES); + other_bytes /= 1024; + if (fprintf(out, "%sother="U64_FORMAT"\n", + comma ? "," : "", U64_PRINTF_ARG(other_bytes))<0) goto done; - /* Reset counters */ - memset(exit_bytes_read, 0, sizeof(exit_bytes_read)); - memset(exit_bytes_written, 0, sizeof(exit_bytes_written)); - memset(exit_streams, 0, sizeof(exit_streams)); - end_of_current_exit_stats_period += EXIT_STATS_INTERVAL_SEC; } + /* exit-streams-opened port=num,.. */ + if (fprintf(out, "exit-streams-opened ") < 0) + goto done; + comma = 0; + other_streams = 0; + for (i = 1; i < EXIT_STATS_NUM_PORTS; i++) { + if (exit_streams[i] > 0) { + if (exit_bytes_read[i] + exit_bytes_written[i] > threshold_bytes) { + uint32_t num = round_uint32_to_next_multiple_of(exit_streams[i], + EXIT_STATS_ROUND_UP_STREAMS); + if (fprintf(out, "%s%d=%u", + comma++ ? "," : "", i, num)<0) + goto done; + } else + other_streams += exit_streams[i]; + } + } + other_streams = round_uint32_to_next_multiple_of(other_streams, + EXIT_STATS_ROUND_UP_STREAMS); + if (fprintf(out, "%sother=%u\n", + comma ? "," : "", other_streams)<0) + goto done; + /* Reset counters */ + memset(exit_bytes_read, 0, sizeof(exit_bytes_read)); + memset(exit_bytes_written, 0, sizeof(exit_bytes_written)); + memset(exit_streams, 0, sizeof(exit_streams)); + start_of_exit_stats_interval = now; if (open_file) finish_writing_to_file(open_file); @@ -1457,63 +1473,48 @@ write_exit_stats(time_t when) if (open_file) abort_writing_to_file(open_file); tor_free(filename); -} - -/** Prepare to add an exit stats observation at second <b>when</b> by - * checking whether this observation lies in the current observation - * period; if not, shift the current period forward by one until the - * reported event fits it and write all results in between to disk. */ -static void -add_exit_obs(time_t when) -{ - if (when > end_of_current_exit_stats_period) { - if (end_of_current_exit_stats_period) - write_exit_stats(when); - else - end_of_current_exit_stats_period = when + EXIT_STATS_INTERVAL_SEC; - } + tor_free(statsdir); } /** Note that we wrote <b>num_bytes</b> to an exit connection to - * <b>port</b> in second <b>when</b>. */ + * <b>port</b>. */ void -rep_hist_note_exit_bytes_written(uint16_t port, size_t num_bytes, - time_t when) +rep_hist_note_exit_bytes_written(uint16_t port, size_t num_bytes) { if (!get_options()->ExitPortStatistics) return; - add_exit_obs(when); + if (!exit_bytes_written) + return; /* Not initialized */ exit_bytes_written[port] += num_bytes; log_debug(LD_HIST, "Written %lu bytes to exit connection to port %d.", (unsigned long)num_bytes, port); } /** Note that we read <b>num_bytes</b> from an exit connection to - * <b>port</b> in second <b>when</b>. */ + * <b>port</b>. */ void -rep_hist_note_exit_bytes_read(uint16_t port, size_t num_bytes, - time_t when) +rep_hist_note_exit_bytes_read(uint16_t port, size_t num_bytes) { if (!get_options()->ExitPortStatistics) return; - add_exit_obs(when); + if (!exit_bytes_read) + return; /* Not initialized */ exit_bytes_read[port] += num_bytes; log_debug(LD_HIST, "Read %lu bytes from exit connection to port %d.", (unsigned long)num_bytes, port); } -/** Note that we opened an exit stream to <b>port</b> in second - * <b>when</b>. */ +/** Note that we opened an exit stream to <b>port</b>. */ void -rep_hist_note_exit_stream_opened(uint16_t port, time_t when) +rep_hist_note_exit_stream_opened(uint16_t port) { if (!get_options()->ExitPortStatistics) return; - add_exit_obs(when); + if (!exit_streams) + return; /* Not initialized */ exit_streams[port]++; log_debug(LD_HIST, "Opened exit stream to port %d", port); } -#endif /** Helper: Return the largest value in b->maxima. (This is equal to the * most bandwidth used in any NUM_SECS_ROLLING_MEASURE period for the last @@ -2049,6 +2050,9 @@ rep_hist_free_all(void) tor_free(read_array); tor_free(write_array); tor_free(last_stability_doc); + tor_free(exit_bytes_read); + tor_free(exit_bytes_written); + tor_free(exit_streams); built_last_stability_doc_at = 0; predicted_ports_free(); } @@ -2603,9 +2607,15 @@ hs_usage_write_statistics_to_file(time_t now) /*** cell statistics ***/ -#ifdef ENABLE_BUFFER_STATS /** Start of the current buffer stats interval. */ -time_t start_of_buffer_stats_interval; +static time_t start_of_buffer_stats_interval; + +/** Initialize buffer stats. */ +void +rep_hist_buffer_stats_init(time_t now) +{ + start_of_buffer_stats_interval = now; +} typedef struct circ_buffer_stats_t { uint32_t processed_cells; @@ -2621,7 +2631,7 @@ smartlist_t *circuits_for_buffer_stats = NULL; * <b>end_of_interval</b> and reset cell counters in case the circuit * remains open in the next measurement interval. */ void -add_circ_to_buffer_stats(circuit_t *circ, time_t end_of_interval) +rep_hist_buffer_stats_add_circ(circuit_t *circ, time_t end_of_interval) { circ_buffer_stats_t *stat; time_t start_of_interval; @@ -2667,12 +2677,11 @@ _buffer_stats_compare_entries(const void **_a, const void **_b) return 0; } -/** Append buffer statistics to local file. */ +/** Write buffer statistics to $DATADIR/stats/buffer-stats. */ void -dump_buffer_stats(void) +rep_hist_buffer_stats_write(time_t now) { - time_t now = time(NULL); - char *filename; + char *statsdir = NULL, *filename = NULL; char written[ISO_TIME_LEN+1]; open_file_t *open_file = NULL; FILE *out; @@ -2686,7 +2695,7 @@ dump_buffer_stats(void) circuit_t *circ; /* add current circuits to stats */ for (circ = _circuit_get_global_list(); circ; circ = circ->next) - add_circ_to_buffer_stats(circ, now); + rep_hist_buffer_stats_add_circ(circ, now); /* calculate deciles */ memset(processed_cells, 0, SHARES * sizeof(int)); memset(circs_in_share, 0, SHARES * sizeof(int)); @@ -2711,14 +2720,17 @@ dump_buffer_stats(void) stat, tor_free(stat)); smartlist_clear(circuits_for_buffer_stats); /* write to file */ - filename = get_datadir_fname("buffer-stats"); + statsdir = get_datadir_fname("stats"); + if (check_private_dir(statsdir, CPD_CREATE) < 0) + goto done; + filename = get_datadir_fname("stats"PATH_SEPARATOR"buffer-stats"); out = start_writing_to_stdio_file(filename, OPEN_FLAGS_APPEND, 0600, &open_file); if (!out) goto done; format_iso_time(written, now); - if (fprintf(out, "written %s (%d s)\n", written, - DUMP_BUFFER_STATS_INTERVAL) < 0) + if (fprintf(out, "cell-stats-end %s (%d s)\n", written, + (unsigned) (now - start_of_buffer_stats_interval)) < 0) goto done; for (i = 0; i < SHARES; i++) { tor_snprintf(buf, sizeof(buf), "%d", !circs_in_share[i] ? 0 : @@ -2726,7 +2738,7 @@ dump_buffer_stats(void) smartlist_add(str_build, tor_strdup(buf)); } str = smartlist_join_strings(str_build, ",", 0, NULL); - if (fprintf(out, "processed-cells %s\n", str) < 0) + if (fprintf(out, "cell-processed-cells %s\n", str) < 0) goto done; tor_free(str); SMARTLIST_FOREACH(str_build, char *, c, tor_free(c)); @@ -2737,7 +2749,7 @@ dump_buffer_stats(void) smartlist_add(str_build, tor_strdup(buf)); } str = smartlist_join_strings(str_build, ",", 0, NULL); - if (fprintf(out, "queued-cells %s\n", str) < 0) + if (fprintf(out, "cell-queued-cells %s\n", str) < 0) goto done; tor_free(str); SMARTLIST_FOREACH(str_build, char *, c, tor_free(c)); @@ -2748,13 +2760,13 @@ dump_buffer_stats(void) smartlist_add(str_build, tor_strdup(buf)); } str = smartlist_join_strings(str_build, ",", 0, NULL); - if (fprintf(out, "time-in-queue %s\n", str) < 0) + if (fprintf(out, "cell-time-in-queue %s\n", str) < 0) goto done; tor_free(str); SMARTLIST_FOREACH(str_build, char *, c, tor_free(c)); smartlist_free(str_build); str_build = NULL; - if (fprintf(out, "number-of-circuits-per-share %d\n", + if (fprintf(out, "cell-circuits-per-decile %d\n", (number_of_circuits + SHARES - 1) / SHARES) < 0) goto done; finish_writing_to_file(open_file); @@ -2763,6 +2775,7 @@ dump_buffer_stats(void) if (open_file) abort_writing_to_file(open_file); tor_free(filename); + tor_free(statsdir); if (str_build) { SMARTLIST_FOREACH(str_build, char *, c, tor_free(c)); smartlist_free(str_build); @@ -2770,5 +2783,4 @@ dump_buffer_stats(void) tor_free(str); #undef SHARES } -#endif diff --git a/src/or/router.c b/src/or/router.c index f2747f514..ea7a430fa 100644 --- a/src/or/router.c +++ b/src/or/router.c @@ -1269,6 +1269,7 @@ router_rebuild_descriptor(int force) uint32_t addr; char platform[256]; int hibernating = we_are_hibernating(); + size_t ei_size; or_options_t *options = get_options(); if (desc_clean_since && !force) @@ -1382,9 +1383,10 @@ router_rebuild_descriptor(int force) ei->cache_info.published_on = ri->cache_info.published_on; memcpy(ei->cache_info.identity_digest, ri->cache_info.identity_digest, DIGEST_LEN); - ei->cache_info.signed_descriptor_body = tor_malloc(8192); - if (extrainfo_dump_to_string(ei->cache_info.signed_descriptor_body, 8192, - ei, get_identity_key()) < 0) { + ei_size = options->ExtraInfoStatistics ? MAX_EXTRAINFO_UPLOAD_SIZE : 8192; + ei->cache_info.signed_descriptor_body = tor_malloc(ei_size); + if (extrainfo_dump_to_string(ei->cache_info.signed_descriptor_body, + ei_size, ei, get_identity_key()) < 0) { log_warn(LD_BUG, "Couldn't generate extra-info descriptor."); extrainfo_free(ei); return -1; @@ -1822,6 +1824,57 @@ router_dump_router_to_string(char *s, size_t maxlen, routerinfo_t *router, return (int)written+1; } +/** Load the contents of <b>filename</b>, find the last line starting with + * <b>end_line</b>, ensure that its timestamp is not more than 25 hours in + * the past or more than 1 hour in the future with respect to <b>now</b>, + * and write the file contents starting with that line to **<b>out</b>. + * Return 1 for success, 0 if the file does not exist or does not contain + * a line matching these criteria, or -1 for failure. */ +static int +load_stats_file(const char *filename, const char *end_line, time_t now, + char **out) +{ + int r = -1; + char *fname = get_datadir_fname(filename); + char *contents, *start = NULL, *tmp, timestr[ISO_TIME_LEN+1]; + time_t written; + switch (file_status(fname)) { + case FN_FILE: + /* X022 Find an alternative to reading the whole file to memory. */ + if ((contents = read_file_to_str(fname, 0, NULL))) { + tmp = strstr(contents, end_line); + /* Find last block starting with end_line */ + while (tmp) { + start = tmp; + tmp = strstr(tmp + 1, end_line); + } + if (!start) + goto notfound; + if (strlen(start) < strlen(end_line) + 1 + sizeof(timestr)) + goto notfound; + strlcpy(timestr, start + 1 + strlen(end_line), sizeof(timestr)); + if (parse_iso_time(timestr, &written) < 0) + goto notfound; + if (written < now - (25*60*60) || written > now + (1*60*60)) + goto notfound; + *out = tor_strdup(start); + r = 1; + } + notfound: + tor_free(contents); + break; + case FN_NOENT: + r = 0; + break; + case FN_ERROR: + case FN_DIR: + default: + break; + } + tor_free(fname); + return r; +} + /** Write the contents of <b>extrainfo</b> to the <b>maxlen</b>-byte string * <b>s</b>, signing them with <b>ident_key</b>. Return 0 on success, * negative on failure. */ @@ -1836,6 +1889,7 @@ extrainfo_dump_to_string(char *s, size_t maxlen, extrainfo_t *extrainfo, char *bandwidth_usage; int result; size_t len; + static int write_stats_to_extrainfo = 1; base16_encode(identity, sizeof(identity), extrainfo->cache_info.identity_digest, DIGEST_LEN); @@ -1847,6 +1901,61 @@ extrainfo_dump_to_string(char *s, size_t maxlen, extrainfo_t *extrainfo, "published %s\n%s", extrainfo->nickname, identity, published, bandwidth_usage); + + if (options->ExtraInfoStatistics && write_stats_to_extrainfo) { + char *contents = NULL; + time_t since = time(NULL) - (24*60*60); + log_info(LD_GENERAL, "Adding stats to extra-info descriptor."); + if (options->DirReqStatistics && + load_stats_file("stats"PATH_SEPARATOR"dirreq-stats", + "dirreq-stats-end", since, &contents) > 0) { + int pos = strlen(s); + if (strlcpy(s + pos, contents, maxlen - strlen(s)) != + strlen(contents)) { + log_warn(LD_DIR, "Could not write dirreq-stats to extra-info " + "descriptor."); + s[pos] = '\0'; + } + tor_free(contents); + } + if (options->EntryStatistics && + load_stats_file("stats"PATH_SEPARATOR"entry-stats", + "entry-stats-end", since, &contents) > 0) { + int pos = strlen(s); + if (strlcpy(s + pos, contents, maxlen - strlen(s)) != + strlen(contents)) { + log_warn(LD_DIR, "Could not write entry-stats to extra-info " + "descriptor."); + s[pos] = '\0'; + } + tor_free(contents); + } + if (options->CellStatistics && + load_stats_file("stats"PATH_SEPARATOR"buffer-stats", + "cell-stats-end", since, &contents) > 0) { + int pos = strlen(s); + if (strlcpy(s + pos, contents, maxlen - strlen(s)) != + strlen(contents)) { + log_warn(LD_DIR, "Could not write buffer-stats to extra-info " + "descriptor."); + s[pos] = '\0'; + } + tor_free(contents); + } + if (options->ExitPortStatistics && + load_stats_file("stats"PATH_SEPARATOR"exit-stats", + "exit-stats-end", since, &contents) > 0) { + int pos = strlen(s); + if (strlcpy(s + pos, contents, maxlen - strlen(s)) != + strlen(contents)) { + log_warn(LD_DIR, "Could not write exit-stats to extra-info " + "descriptor."); + s[pos] = '\0'; + } + tor_free(contents); + } + } + tor_free(bandwidth_usage); if (result<0) return -1; @@ -1875,7 +1984,6 @@ extrainfo_dump_to_string(char *s, size_t maxlen, extrainfo_t *extrainfo, if (router_append_dirobj_signature(s+len, maxlen-len, digest, ident_key)<0) return -1; -#ifdef DEBUG_ROUTER_DUMP_ROUTER_TO_STRING { char *cp, *s_dup; extrainfo_t *ei_tmp; @@ -1890,7 +1998,24 @@ extrainfo_dump_to_string(char *s, size_t maxlen, extrainfo_t *extrainfo, tor_free(s_dup); extrainfo_free(ei_tmp); } -#endif + + if (options->ExtraInfoStatistics && write_stats_to_extrainfo) { + char *cp, *s_dup; + extrainfo_t *ei_tmp; + cp = s_dup = tor_strdup(s); + ei_tmp = extrainfo_parse_entry_from_string(cp, NULL, 1, NULL); + if (!ei_tmp) { + log_warn(LD_GENERAL, + "We just generated an extra-info descriptor with " + "statistics that we can't parse. Not adding statistics to " + "this or any future extra-info descriptors. Descriptor " + "was:\n%s", s); + write_stats_to_extrainfo = 0; + extrainfo_dump_to_string(s, maxlen, extrainfo, ident_key); + } + tor_free(s_dup); + extrainfo_free(ei_tmp); + } return (int)strlen(s)+1; } @@ -1905,13 +2030,9 @@ char * extrainfo_get_client_geoip_summary(time_t now) { static time_t last_purged_at = 0; - int geoip_purge_interval = 48*60*60; -#ifdef ENABLE_DIRREQ_STATS - geoip_purge_interval = DIR_RECORD_USAGE_RETAIN_IPS; -#endif -#ifdef ENABLE_ENTRY_STATS - geoip_purge_interval = ENTRY_RECORD_USAGE_RETAIN_IPS; -#endif + int geoip_purge_interval = + (get_options()->DirReqStatistics || get_options()->EntryStatistics) ? + DIR_ENTRY_RECORD_USAGE_RETAIN_IPS : 48*60*60; if (now > last_purged_at+geoip_purge_interval) { /* (Note that this also discards items in the client history with * action GEOIP_CLIENT_NETWORKSTATUS{_V2}, which doesn't matter @@ -1920,7 +2041,7 @@ extrainfo_get_client_geoip_summary(time_t now) geoip_remove_old_clients(now-geoip_purge_interval); last_purged_at = now; } - return geoip_get_client_history(now, GEOIP_CLIENT_CONNECT); + return geoip_get_client_history_bridge(now, GEOIP_CLIENT_CONNECT); } /** Return true iff <b>s</b> is a legally valid server nickname. */ diff --git a/src/or/routerparse.c b/src/or/routerparse.c index 9736c4e00..8fecd9ab4 100644 --- a/src/or/routerparse.c +++ b/src/or/routerparse.c @@ -62,6 +62,31 @@ typedef enum { K_HIDDEN_SERVICE_DIR, K_ALLOW_SINGLE_HOP_EXITS, + K_DIRREQ_END, + K_DIRREQ_V2_IPS, + K_DIRREQ_V3_IPS, + K_DIRREQ_V2_REQS, + K_DIRREQ_V3_REQS, + K_DIRREQ_V2_SHARE, + K_DIRREQ_V3_SHARE, + K_DIRREQ_V2_RESP, + K_DIRREQ_V3_RESP, + K_DIRREQ_V2_DIR, + K_DIRREQ_V3_DIR, + K_DIRREQ_V2_TUN, + K_DIRREQ_V3_TUN, + K_ENTRY_END, + K_ENTRY_IPS, + K_CELL_END, + K_CELL_PROCESSED, + K_CELL_QUEUED, + K_CELL_TIME, + K_CELL_CIRCS, + K_EXIT_END, + K_EXIT_WRITTEN, + K_EXIT_READ, + K_EXIT_OPENED, + K_DIR_KEY_CERTIFICATE_VERSION, K_DIR_IDENTITY_KEY, K_DIR_KEY_PUBLISHED, @@ -257,6 +282,31 @@ static token_rule_t extrainfo_token_table[] = { T0N("opt", K_OPT, CONCAT_ARGS, OBJ_OK ), T01("read-history", K_READ_HISTORY, ARGS, NO_OBJ ), T01("write-history", K_WRITE_HISTORY, ARGS, NO_OBJ ), + T01("dirreq-stats-end", K_DIRREQ_END, ARGS, NO_OBJ ), + T01("dirreq-v2-ips", K_DIRREQ_V2_IPS, ARGS, NO_OBJ ), + T01("dirreq-v3-ips", K_DIRREQ_V3_IPS, ARGS, NO_OBJ ), + T01("dirreq-v2-reqs", K_DIRREQ_V2_REQS, ARGS, NO_OBJ ), + T01("dirreq-v3-reqs", K_DIRREQ_V3_REQS, ARGS, NO_OBJ ), + T01("dirreq-v2-share", K_DIRREQ_V2_SHARE, ARGS, NO_OBJ ), + T01("dirreq-v3-share", K_DIRREQ_V3_SHARE, ARGS, NO_OBJ ), + T01("dirreq-v2-resp", K_DIRREQ_V2_RESP, ARGS, NO_OBJ ), + T01("dirreq-v3-resp", K_DIRREQ_V3_RESP, ARGS, NO_OBJ ), + T01("dirreq-v2-direct-dl", K_DIRREQ_V2_DIR, ARGS, NO_OBJ ), + T01("dirreq-v3-direct-dl", K_DIRREQ_V3_DIR, ARGS, NO_OBJ ), + T01("dirreq-v2-tunneled-dl", K_DIRREQ_V2_TUN, ARGS, NO_OBJ ), + T01("dirreq-v3-tunneled-dl", K_DIRREQ_V3_TUN, ARGS, NO_OBJ ), + T01("entry-stats-end", K_ENTRY_END, ARGS, NO_OBJ ), + T01("entry-ips", K_ENTRY_IPS, ARGS, NO_OBJ ), + T01("cell-stats-end", K_CELL_END, ARGS, NO_OBJ ), + T01("cell-processed-cells", K_CELL_PROCESSED, ARGS, NO_OBJ ), + T01("cell-queued-cells", K_CELL_QUEUED, ARGS, NO_OBJ ), + T01("cell-time-in-queue", K_CELL_TIME, ARGS, NO_OBJ ), + T01("cell-circuits-per-decile", K_CELL_CIRCS, ARGS, NO_OBJ ), + T01("exit-stats-end", K_EXIT_END, ARGS, NO_OBJ ), + T01("exit-kibibytes-written", K_EXIT_WRITTEN, ARGS, NO_OBJ ), + T01("exit-kibibytes-read", K_EXIT_READ, ARGS, NO_OBJ ), + T01("exit-streams-opened", K_EXIT_OPENED, ARGS, NO_OBJ ), + T1_START( "extra-info", K_EXTRA_INFO, GE(2), NO_OBJ ), END_OF_TABLE diff --git a/src/or/test.c b/src/or/test.c index 0f121a84b..d4afdeeb3 100644 --- a/src/or/test.c +++ b/src/or/test.c @@ -4774,14 +4774,16 @@ test_geoip(void) /* and 17 observations in ZZ... */ for (i=110; i < 127; ++i) geoip_note_client_seen(GEOIP_CLIENT_CONNECT, i, now); - s = geoip_get_client_history(now+5*24*60*60, GEOIP_CLIENT_CONNECT); + s = geoip_get_client_history_bridge(now+5*24*60*60, + GEOIP_CLIENT_CONNECT); test_assert(s); test_streq("zz=24,ab=16,xy=8", s); tor_free(s); /* Now clear out all the AB observations. */ geoip_remove_old_clients(now-6000); - s = geoip_get_client_history(now+5*24*60*60, GEOIP_CLIENT_CONNECT); + s = geoip_get_client_history_bridge(now+5*24*60*60, + GEOIP_CLIENT_CONNECT); test_assert(s); test_streq("zz=24,xy=8", s); |