From 50bf2520b33eb9f477c1b8989264667c5b587a01 Mon Sep 17 00:00:00 2001 From: Nick Mathewson Date: Fri, 10 Jul 2020 09:07:23 -0400 Subject: Split bidi connection-stats code into a new C file. --- src/core/mainloop/connection.c | 1 + src/core/mainloop/mainloop.c | 1 + src/feature/relay/relay_config.c | 1 + src/feature/stats/connstats.c | 235 +++++++++++++++++++++++++++++++++++++++ src/feature/stats/connstats.h | 24 ++++ src/feature/stats/include.am | 2 + src/feature/stats/rephist.c | 221 +----------------------------------- src/feature/stats/rephist.h | 8 -- src/test/test_stats.c | 1 + 9 files changed, 266 insertions(+), 228 deletions(-) create mode 100644 src/feature/stats/connstats.c create mode 100644 src/feature/stats/connstats.h diff --git a/src/core/mainloop/connection.c b/src/core/mainloop/connection.c index 2f3c70365a..2d6f02fc6f 100644 --- a/src/core/mainloop/connection.c +++ b/src/core/mainloop/connection.c @@ -105,6 +105,7 @@ #include "feature/relay/routermode.h" #include "feature/rend/rendclient.h" #include "feature/rend/rendcommon.h" +#include "feature/stats/connstats.h" #include "feature/stats/rephist.h" #include "feature/stats/bwhist.h" #include "lib/crypt_ops/crypto_util.h" diff --git a/src/core/mainloop/mainloop.c b/src/core/mainloop/mainloop.c index e4e17f6b76..edea036fac 100644 --- a/src/core/mainloop/mainloop.c +++ b/src/core/mainloop/mainloop.c @@ -95,6 +95,7 @@ #include "feature/rend/rendservice.h" #include "feature/stats/geoip_stats.h" #include "feature/stats/predict_ports.h" +#include "feature/stats/connstats.h" #include "feature/stats/rephist.h" #include "lib/buf/buffers.h" #include "lib/crypt_ops/crypto_rand.h" diff --git a/src/feature/relay/relay_config.c b/src/feature/relay/relay_config.c index bd1c1e8fe8..4ba83d4bc8 100644 --- a/src/feature/relay/relay_config.c +++ b/src/feature/relay/relay_config.c @@ -36,6 +36,7 @@ #include "feature/nodelist/nickname.h" #include "feature/stats/geoip_stats.h" #include "feature/stats/predict_ports.h" +#include "feature/stats/connstats.h" #include "feature/stats/rephist.h" #include "feature/dirauth/authmode.h" diff --git a/src/feature/stats/connstats.c b/src/feature/stats/connstats.c new file mode 100644 index 0000000000..f8df26ecc1 --- /dev/null +++ b/src/feature/stats/connstats.c @@ -0,0 +1,235 @@ +/* Copyright (c) 2001 Matej Pfajfar. + * Copyright (c) 2001-2004, Roger Dingledine. + * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson. + * Copyright (c) 2007-2020, The Tor Project, Inc. */ +/* See LICENSE for licensing information */ + +/** + * @file connstats.c + * @brief Count bidirectional vs one-way connections. + * + * Connection statistics, used by relays to count connections, and track + * one-way and bidirectional connections. + **/ + +#include "orconfig.h" +#include "core/or/or.h" +#include "feature/stats/connstats.h" +#include "app/config/config.h" + +/** Start of the current connection stats interval or 0 if we're not + * collecting connection statistics. */ +static time_t start_of_conn_stats_interval; + +/** Initialize connection stats. */ +void +rep_hist_conn_stats_init(time_t now) +{ + start_of_conn_stats_interval = now; +} + +/* Count connections that we read and wrote less than these many bytes + * from/to as below threshold. */ +#define BIDI_THRESHOLD 20480 + +/* Count connections that we read or wrote at least this factor as many + * bytes from/to than we wrote or read to/from as mostly reading or + * writing. */ +#define BIDI_FACTOR 10 + +/* Interval length in seconds for considering read and written bytes for + * connection stats. */ +#define BIDI_INTERVAL 10 + +/** Start of next BIDI_INTERVAL second interval. */ +static time_t bidi_next_interval = 0; + +/** Number of connections that we read and wrote less than BIDI_THRESHOLD + * bytes from/to in BIDI_INTERVAL seconds. */ +static uint32_t below_threshold = 0; + +/** Number of connections that we read at least BIDI_FACTOR times more + * bytes from than we wrote to in BIDI_INTERVAL seconds. */ +static uint32_t mostly_read = 0; + +/** Number of connections that we wrote at least BIDI_FACTOR times more + * bytes to than we read from in BIDI_INTERVAL seconds. */ +static uint32_t mostly_written = 0; + +/** Number of connections that we read and wrote at least BIDI_THRESHOLD + * bytes from/to, but not BIDI_FACTOR times more in either direction in + * BIDI_INTERVAL seconds. */ +static uint32_t both_read_and_written = 0; + +/** Entry in a map from connection ID to the number of read and written + * bytes on this connection in a BIDI_INTERVAL second interval. */ +typedef struct bidi_map_entry_t { + HT_ENTRY(bidi_map_entry_t) node; + uint64_t conn_id; /**< Connection ID */ + size_t read; /**< Number of read bytes */ + size_t written; /**< Number of written bytes */ +} bidi_map_entry_t; + +/** Map of OR connections together with the number of read and written + * bytes in the current BIDI_INTERVAL second interval. */ +static HT_HEAD(bidimap, bidi_map_entry_t) bidi_map = + HT_INITIALIZER(); + +static int +bidi_map_ent_eq(const bidi_map_entry_t *a, const bidi_map_entry_t *b) +{ + return a->conn_id == b->conn_id; +} + +/* DOCDOC bidi_map_ent_hash */ +static unsigned +bidi_map_ent_hash(const bidi_map_entry_t *entry) +{ + return (unsigned) entry->conn_id; +} + +HT_PROTOTYPE(bidimap, bidi_map_entry_t, node, bidi_map_ent_hash, + bidi_map_ent_eq); +HT_GENERATE2(bidimap, bidi_map_entry_t, node, bidi_map_ent_hash, + bidi_map_ent_eq, 0.6, tor_reallocarray_, tor_free_); + +/** Release all storage held in connstats.c */ +void +bidi_map_free_all(void) +{ + bidi_map_entry_t **ptr, **next, *ent; + for (ptr = HT_START(bidimap, &bidi_map); ptr; ptr = next) { + ent = *ptr; + next = HT_NEXT_RMV(bidimap, &bidi_map, ptr); + tor_free(ent); + } + HT_CLEAR(bidimap, &bidi_map); +} + +/** Reset counters for conn statistics. */ +void +rep_hist_reset_conn_stats(time_t now) +{ + start_of_conn_stats_interval = now; + below_threshold = 0; + mostly_read = 0; + mostly_written = 0; + both_read_and_written = 0; + bidi_map_free_all(); +} + +/** Stop collecting connection stats in a way that we can re-start doing + * so in rep_hist_conn_stats_init(). */ +void +rep_hist_conn_stats_term(void) +{ + rep_hist_reset_conn_stats(0); +} + +/** We read num_read bytes and wrote num_written from/to OR + * connection conn_id in second when. If this is the first + * observation in a new interval, sum up the last observations. Add bytes + * for this connection. */ +void +rep_hist_note_or_conn_bytes(uint64_t conn_id, size_t num_read, + size_t num_written, time_t when) +{ + if (!start_of_conn_stats_interval) + return; + /* Initialize */ + if (bidi_next_interval == 0) + bidi_next_interval = when + BIDI_INTERVAL; + /* Sum up last period's statistics */ + if (when >= bidi_next_interval) { + bidi_map_entry_t **ptr, **next, *ent; + for (ptr = HT_START(bidimap, &bidi_map); ptr; ptr = next) { + ent = *ptr; + if (ent->read + ent->written < BIDI_THRESHOLD) + below_threshold++; + else if (ent->read >= ent->written * BIDI_FACTOR) + mostly_read++; + else if (ent->written >= ent->read * BIDI_FACTOR) + mostly_written++; + else + both_read_and_written++; + next = HT_NEXT_RMV(bidimap, &bidi_map, ptr); + tor_free(ent); + } + while (when >= bidi_next_interval) + bidi_next_interval += BIDI_INTERVAL; + log_info(LD_GENERAL, "%d below threshold, %d mostly read, " + "%d mostly written, %d both read and written.", + below_threshold, mostly_read, mostly_written, + both_read_and_written); + } + /* Add this connection's bytes. */ + if (num_read > 0 || num_written > 0) { + bidi_map_entry_t *entry, lookup; + lookup.conn_id = conn_id; + entry = HT_FIND(bidimap, &bidi_map, &lookup); + if (entry) { + entry->written += num_written; + entry->read += num_read; + } else { + entry = tor_malloc_zero(sizeof(bidi_map_entry_t)); + entry->conn_id = conn_id; + entry->written = num_written; + entry->read = num_read; + HT_INSERT(bidimap, &bidi_map, entry); + } + } +} + +/** Return a newly allocated string containing the connection statistics + * until now, or NULL if we're not collecting conn stats. Caller must + * ensure start_of_conn_stats_interval is in the past. */ +char * +rep_hist_format_conn_stats(time_t now) +{ + char *result, written[ISO_TIME_LEN+1]; + + if (!start_of_conn_stats_interval) + return NULL; /* Not initialized. */ + + tor_assert(now >= start_of_conn_stats_interval); + + format_iso_time(written, now); + tor_asprintf(&result, "conn-bi-direct %s (%d s) %d,%d,%d,%d\n", + written, + (unsigned) (now - start_of_conn_stats_interval), + below_threshold, + mostly_read, + mostly_written, + both_read_and_written); + return result; +} + +/** If 24 hours have passed since the beginning of the current conn stats + * period, write conn stats to $DATADIR/stats/conn-stats (possibly + * overwriting an existing file) and reset counters. Return when we would + * next want to write conn stats or 0 if we never want to write. */ +time_t +rep_hist_conn_stats_write(time_t now) +{ + char *str = NULL; + + if (!start_of_conn_stats_interval) + return 0; /* Not initialized. */ + if (start_of_conn_stats_interval + WRITE_STATS_INTERVAL > now) + goto done; /* Not ready to write */ + + /* Generate history string. */ + str = rep_hist_format_conn_stats(now); + + /* Reset counters. */ + rep_hist_reset_conn_stats(now); + + /* Try to write to disk. */ + if (!check_or_create_data_subdir("stats")) { + write_to_data_subdir("stats", "conn-stats", str, "connection statistics"); + } + + done: + tor_free(str); + return start_of_conn_stats_interval + WRITE_STATS_INTERVAL; +} diff --git a/src/feature/stats/connstats.h b/src/feature/stats/connstats.h new file mode 100644 index 0000000000..2abe8d7362 --- /dev/null +++ b/src/feature/stats/connstats.h @@ -0,0 +1,24 @@ +/* Copyright (c) 2001 Matej Pfajfar. + * Copyright (c) 2001-2004, Roger Dingledine. + * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson. + * Copyright (c) 2007-2020, The Tor Project, Inc. */ +/* See LICENSE for licensing information */ + +/** + * @file connstats.h + * @brief Header for feature/stats/connstats.c + **/ + +#ifndef TOR_FEATURE_STATS_CONNSTATS_H +#define TOR_FEATURE_STATS_CONNSTATS_H + +void rep_hist_conn_stats_init(time_t now); +void rep_hist_note_or_conn_bytes(uint64_t conn_id, size_t num_read, + size_t num_written, time_t when); +void rep_hist_reset_conn_stats(time_t now); +char *rep_hist_format_conn_stats(time_t now); +time_t rep_hist_conn_stats_write(time_t now); +void rep_hist_conn_stats_term(void); +void bidi_map_free_all(void); + +#endif /* !defined(TOR_FEATURE_STATS_CONNSTATS_H) */ diff --git a/src/feature/stats/include.am b/src/feature/stats/include.am index 32e760a08b..bc13882f4b 100644 --- a/src/feature/stats/include.am +++ b/src/feature/stats/include.am @@ -2,6 +2,7 @@ # ADD_C_FILE: INSERT SOURCES HERE. LIBTOR_APP_A_SOURCES += \ src/feature/stats/bwhist.c \ + src/feature/stats/connstats.c \ src/feature/stats/geoip_stats.c \ src/feature/stats/rephist.c \ src/feature/stats/predict_ports.c @@ -9,6 +10,7 @@ LIBTOR_APP_A_SOURCES += \ # ADD_C_FILE: INSERT HEADERS HERE. noinst_HEADERS += \ src/feature/stats/bwhist.h \ + src/feature/stats/connstats.h \ src/feature/stats/geoip_stats.h \ src/feature/stats/rephist.h \ src/feature/stats/predict_ports.h diff --git a/src/feature/stats/rephist.c b/src/feature/stats/rephist.c index 6f409a46fc..5535a3ab0f 100644 --- a/src/feature/stats/rephist.c +++ b/src/feature/stats/rephist.c @@ -43,9 +43,6 @@ *
  • Descriptor serving statistics, used by directory caches to track * how many descriptors they've served. * - *
  • Connection statistics, used by relays to track one-way and - * bidirectional connections. - * *
  • Onion handshake statistics, used by relays to count how many * TAP and ntor handshakes they've handled. * @@ -78,6 +75,7 @@ #include "feature/nodelist/networkstatus.h" #include "feature/nodelist/nodelist.h" #include "feature/stats/predict_ports.h" +#include "feature/stats/connstats.h" #include "feature/stats/rephist.h" #include "lib/container/order.h" #include "lib/crypt_ops/crypto_rand.h" @@ -1648,223 +1646,6 @@ rep_hist_note_desc_served(const char * desc) /*** Connection statistics ***/ -/** Start of the current connection stats interval or 0 if we're not - * collecting connection statistics. */ -static time_t start_of_conn_stats_interval; - -/** Initialize connection stats. */ -void -rep_hist_conn_stats_init(time_t now) -{ - start_of_conn_stats_interval = now; -} - -/* Count connections that we read and wrote less than these many bytes - * from/to as below threshold. */ -#define BIDI_THRESHOLD 20480 - -/* Count connections that we read or wrote at least this factor as many - * bytes from/to than we wrote or read to/from as mostly reading or - * writing. */ -#define BIDI_FACTOR 10 - -/* Interval length in seconds for considering read and written bytes for - * connection stats. */ -#define BIDI_INTERVAL 10 - -/** Start of next BIDI_INTERVAL second interval. */ -static time_t bidi_next_interval = 0; - -/** Number of connections that we read and wrote less than BIDI_THRESHOLD - * bytes from/to in BIDI_INTERVAL seconds. */ -static uint32_t below_threshold = 0; - -/** Number of connections that we read at least BIDI_FACTOR times more - * bytes from than we wrote to in BIDI_INTERVAL seconds. */ -static uint32_t mostly_read = 0; - -/** Number of connections that we wrote at least BIDI_FACTOR times more - * bytes to than we read from in BIDI_INTERVAL seconds. */ -static uint32_t mostly_written = 0; - -/** Number of connections that we read and wrote at least BIDI_THRESHOLD - * bytes from/to, but not BIDI_FACTOR times more in either direction in - * BIDI_INTERVAL seconds. */ -static uint32_t both_read_and_written = 0; - -/** Entry in a map from connection ID to the number of read and written - * bytes on this connection in a BIDI_INTERVAL second interval. */ -typedef struct bidi_map_entry_t { - HT_ENTRY(bidi_map_entry_t) node; - uint64_t conn_id; /**< Connection ID */ - size_t read; /**< Number of read bytes */ - size_t written; /**< Number of written bytes */ -} bidi_map_entry_t; - -/** Map of OR connections together with the number of read and written - * bytes in the current BIDI_INTERVAL second interval. */ -static HT_HEAD(bidimap, bidi_map_entry_t) bidi_map = - HT_INITIALIZER(); - -static int -bidi_map_ent_eq(const bidi_map_entry_t *a, const bidi_map_entry_t *b) -{ - return a->conn_id == b->conn_id; -} - -/* DOCDOC bidi_map_ent_hash */ -static unsigned -bidi_map_ent_hash(const bidi_map_entry_t *entry) -{ - return (unsigned) entry->conn_id; -} - -HT_PROTOTYPE(bidimap, bidi_map_entry_t, node, bidi_map_ent_hash, - bidi_map_ent_eq); -HT_GENERATE2(bidimap, bidi_map_entry_t, node, bidi_map_ent_hash, - bidi_map_ent_eq, 0.6, tor_reallocarray_, tor_free_); - -/* DOCDOC bidi_map_free */ -static void -bidi_map_free_all(void) -{ - bidi_map_entry_t **ptr, **next, *ent; - for (ptr = HT_START(bidimap, &bidi_map); ptr; ptr = next) { - ent = *ptr; - next = HT_NEXT_RMV(bidimap, &bidi_map, ptr); - tor_free(ent); - } - HT_CLEAR(bidimap, &bidi_map); -} - -/** Reset counters for conn statistics. */ -void -rep_hist_reset_conn_stats(time_t now) -{ - start_of_conn_stats_interval = now; - below_threshold = 0; - mostly_read = 0; - mostly_written = 0; - both_read_and_written = 0; - bidi_map_free_all(); -} - -/** Stop collecting connection stats in a way that we can re-start doing - * so in rep_hist_conn_stats_init(). */ -void -rep_hist_conn_stats_term(void) -{ - rep_hist_reset_conn_stats(0); -} - -/** We read num_read bytes and wrote num_written from/to OR - * connection conn_id in second when. If this is the first - * observation in a new interval, sum up the last observations. Add bytes - * for this connection. */ -void -rep_hist_note_or_conn_bytes(uint64_t conn_id, size_t num_read, - size_t num_written, time_t when) -{ - if (!start_of_conn_stats_interval) - return; - /* Initialize */ - if (bidi_next_interval == 0) - bidi_next_interval = when + BIDI_INTERVAL; - /* Sum up last period's statistics */ - if (when >= bidi_next_interval) { - bidi_map_entry_t **ptr, **next, *ent; - for (ptr = HT_START(bidimap, &bidi_map); ptr; ptr = next) { - ent = *ptr; - if (ent->read + ent->written < BIDI_THRESHOLD) - below_threshold++; - else if (ent->read >= ent->written * BIDI_FACTOR) - mostly_read++; - else if (ent->written >= ent->read * BIDI_FACTOR) - mostly_written++; - else - both_read_and_written++; - next = HT_NEXT_RMV(bidimap, &bidi_map, ptr); - tor_free(ent); - } - while (when >= bidi_next_interval) - bidi_next_interval += BIDI_INTERVAL; - log_info(LD_GENERAL, "%d below threshold, %d mostly read, " - "%d mostly written, %d both read and written.", - below_threshold, mostly_read, mostly_written, - both_read_and_written); - } - /* Add this connection's bytes. */ - if (num_read > 0 || num_written > 0) { - bidi_map_entry_t *entry, lookup; - lookup.conn_id = conn_id; - entry = HT_FIND(bidimap, &bidi_map, &lookup); - if (entry) { - entry->written += num_written; - entry->read += num_read; - } else { - entry = tor_malloc_zero(sizeof(bidi_map_entry_t)); - entry->conn_id = conn_id; - entry->written = num_written; - entry->read = num_read; - HT_INSERT(bidimap, &bidi_map, entry); - } - } -} - -/** Return a newly allocated string containing the connection statistics - * until now, or NULL if we're not collecting conn stats. Caller must - * ensure start_of_conn_stats_interval is in the past. */ -char * -rep_hist_format_conn_stats(time_t now) -{ - char *result, written[ISO_TIME_LEN+1]; - - if (!start_of_conn_stats_interval) - return NULL; /* Not initialized. */ - - tor_assert(now >= start_of_conn_stats_interval); - - format_iso_time(written, now); - tor_asprintf(&result, "conn-bi-direct %s (%d s) %d,%d,%d,%d\n", - written, - (unsigned) (now - start_of_conn_stats_interval), - below_threshold, - mostly_read, - mostly_written, - both_read_and_written); - return result; -} - -/** If 24 hours have passed since the beginning of the current conn stats - * period, write conn stats to $DATADIR/stats/conn-stats (possibly - * overwriting an existing file) and reset counters. Return when we would - * next want to write conn stats or 0 if we never want to write. */ -time_t -rep_hist_conn_stats_write(time_t now) -{ - char *str = NULL; - - if (!start_of_conn_stats_interval) - return 0; /* Not initialized. */ - if (start_of_conn_stats_interval + WRITE_STATS_INTERVAL > now) - goto done; /* Not ready to write */ - - /* Generate history string. */ - str = rep_hist_format_conn_stats(now); - - /* Reset counters. */ - rep_hist_reset_conn_stats(now); - - /* Try to write to disk. */ - if (!check_or_create_data_subdir("stats")) { - write_to_data_subdir("stats", "conn-stats", str, "connection statistics"); - } - - done: - tor_free(str); - return start_of_conn_stats_interval + WRITE_STATS_INTERVAL; -} - /** Internal statistics to track how many requests of each type of * handshake we've received, and how many we've assigned to cpuworkers. * Useful for seeing trends in cpu load. diff --git a/src/feature/stats/rephist.h b/src/feature/stats/rephist.h index cdedfdca63..c9ebc5c328 100644 --- a/src/feature/stats/rephist.h +++ b/src/feature/stats/rephist.h @@ -56,14 +56,6 @@ void rep_hist_note_desc_served(const char * desc); void rep_hist_desc_stats_term(void); time_t rep_hist_desc_stats_write(time_t now); -void rep_hist_conn_stats_init(time_t now); -void rep_hist_note_or_conn_bytes(uint64_t conn_id, size_t num_read, - size_t num_written, time_t when); -void rep_hist_reset_conn_stats(time_t now); -char *rep_hist_format_conn_stats(time_t now); -time_t rep_hist_conn_stats_write(time_t now); -void rep_hist_conn_stats_term(void); - void rep_hist_note_circuit_handshake_requested(uint16_t type); void rep_hist_note_circuit_handshake_assigned(uint16_t type); void rep_hist_log_circuit_handshake_stats(time_t now); diff --git a/src/test/test_stats.c b/src/test/test_stats.c index 291473ebc9..c8a76e27d9 100644 --- a/src/test/test_stats.c +++ b/src/test/test_stats.c @@ -39,6 +39,7 @@ #include "test/test.h" #include "core/mainloop/mainloop.h" #include "lib/memarea/memarea.h" +#include "feature/stats/connstats.h" #include "feature/stats/rephist.h" #include "app/config/statefile.h" -- cgit v1.2.3-54-g00ecf From 3f2de0bcca301785c5f1911354f2d3f4d5ba1708 Mon Sep 17 00:00:00 2001 From: Nick Mathewson Date: Fri, 10 Jul 2020 09:11:12 -0400 Subject: Change connstats.c identifers to start with conn_stats This is an automated commit, generated by this command: ./scripts/maint/rename_c_identifier.py \ rep_hist_conn_stats_init conn_stats_init \ rep_hist_note_or_conn_bytes conn_stats_note_or_conn_bytes \ rep_hist_reset_conn_stats conn_stats_reset \ rep_hist_format_conn_stats conn_stats_format \ rep_hist_conn_stats_write conn_stats_save \ rep_hist_conn_stats_term conn_stats_terminate \ bidi_map_free_all conn_stats_free_all --- src/core/mainloop/connection.c | 2 +- src/core/mainloop/mainloop.c | 2 +- src/feature/relay/relay_config.c | 4 ++-- src/feature/stats/connstats.c | 24 ++++++++++++------------ src/feature/stats/connstats.h | 14 +++++++------- src/feature/stats/rephist.c | 2 +- src/test/test_stats.c | 36 ++++++++++++++++++------------------ 7 files changed, 42 insertions(+), 42 deletions(-) diff --git a/src/core/mainloop/connection.c b/src/core/mainloop/connection.c index 2d6f02fc6f..0d2e6a220b 100644 --- a/src/core/mainloop/connection.c +++ b/src/core/mainloop/connection.c @@ -3364,7 +3364,7 @@ record_num_bytes_transferred_impl(connection_t *conn, return; if (conn->type == CONN_TYPE_OR) - rep_hist_note_or_conn_bytes(conn->global_identifier, num_read, + conn_stats_note_or_conn_bytes(conn->global_identifier, num_read, num_written, now); const bool is_ipv6 = (conn->socket_family == AF_INET6); diff --git a/src/core/mainloop/mainloop.c b/src/core/mainloop/mainloop.c index edea036fac..3bf9be566b 100644 --- a/src/core/mainloop/mainloop.c +++ b/src/core/mainloop/mainloop.c @@ -1951,7 +1951,7 @@ write_stats_file_callback(time_t now, const or_options_t *options) next_time_to_write_stats_files = next_write; } if (options->ConnDirectionStatistics) { - time_t next_write = rep_hist_conn_stats_write(now); + time_t next_write = conn_stats_save(now); if (next_write && next_write < next_time_to_write_stats_files) next_time_to_write_stats_files = next_write; } diff --git a/src/feature/relay/relay_config.c b/src/feature/relay/relay_config.c index 4ba83d4bc8..7cb7f2ccfd 100644 --- a/src/feature/relay/relay_config.c +++ b/src/feature/relay/relay_config.c @@ -1308,7 +1308,7 @@ options_act_relay_stats(const or_options_t *old_options, } if ((!old_options || !old_options->ConnDirectionStatistics) && options->ConnDirectionStatistics) { - rep_hist_conn_stats_init(now); + conn_stats_init(now); } if ((!old_options || !old_options->HiddenServiceStatistics) && options->HiddenServiceStatistics) { @@ -1338,7 +1338,7 @@ options_act_relay_stats(const or_options_t *old_options, rep_hist_exit_stats_term(); if (old_options && old_options->ConnDirectionStatistics && !options->ConnDirectionStatistics) - rep_hist_conn_stats_term(); + conn_stats_terminate(); return 0; } diff --git a/src/feature/stats/connstats.c b/src/feature/stats/connstats.c index f8df26ecc1..32987ecf95 100644 --- a/src/feature/stats/connstats.c +++ b/src/feature/stats/connstats.c @@ -23,7 +23,7 @@ static time_t start_of_conn_stats_interval; /** Initialize connection stats. */ void -rep_hist_conn_stats_init(time_t now) +conn_stats_init(time_t now) { start_of_conn_stats_interval = now; } @@ -95,7 +95,7 @@ HT_GENERATE2(bidimap, bidi_map_entry_t, node, bidi_map_ent_hash, /** Release all storage held in connstats.c */ void -bidi_map_free_all(void) +conn_stats_free_all(void) { bidi_map_entry_t **ptr, **next, *ent; for (ptr = HT_START(bidimap, &bidi_map); ptr; ptr = next) { @@ -108,22 +108,22 @@ bidi_map_free_all(void) /** Reset counters for conn statistics. */ void -rep_hist_reset_conn_stats(time_t now) +conn_stats_reset(time_t now) { start_of_conn_stats_interval = now; below_threshold = 0; mostly_read = 0; mostly_written = 0; both_read_and_written = 0; - bidi_map_free_all(); + conn_stats_free_all(); } /** Stop collecting connection stats in a way that we can re-start doing - * so in rep_hist_conn_stats_init(). */ + * so in conn_stats_init(). */ void -rep_hist_conn_stats_term(void) +conn_stats_terminate(void) { - rep_hist_reset_conn_stats(0); + conn_stats_reset(0); } /** We read num_read bytes and wrote num_written from/to OR @@ -131,7 +131,7 @@ rep_hist_conn_stats_term(void) * observation in a new interval, sum up the last observations. Add bytes * for this connection. */ void -rep_hist_note_or_conn_bytes(uint64_t conn_id, size_t num_read, +conn_stats_note_or_conn_bytes(uint64_t conn_id, size_t num_read, size_t num_written, time_t when) { if (!start_of_conn_stats_interval) @@ -184,7 +184,7 @@ rep_hist_note_or_conn_bytes(uint64_t conn_id, size_t num_read, * until now, or NULL if we're not collecting conn stats. Caller must * ensure start_of_conn_stats_interval is in the past. */ char * -rep_hist_format_conn_stats(time_t now) +conn_stats_format(time_t now) { char *result, written[ISO_TIME_LEN+1]; @@ -209,7 +209,7 @@ rep_hist_format_conn_stats(time_t now) * overwriting an existing file) and reset counters. Return when we would * next want to write conn stats or 0 if we never want to write. */ time_t -rep_hist_conn_stats_write(time_t now) +conn_stats_save(time_t now) { char *str = NULL; @@ -219,10 +219,10 @@ rep_hist_conn_stats_write(time_t now) goto done; /* Not ready to write */ /* Generate history string. */ - str = rep_hist_format_conn_stats(now); + str = conn_stats_format(now); /* Reset counters. */ - rep_hist_reset_conn_stats(now); + conn_stats_reset(now); /* Try to write to disk. */ if (!check_or_create_data_subdir("stats")) { diff --git a/src/feature/stats/connstats.h b/src/feature/stats/connstats.h index 2abe8d7362..26ff74cfd3 100644 --- a/src/feature/stats/connstats.h +++ b/src/feature/stats/connstats.h @@ -12,13 +12,13 @@ #ifndef TOR_FEATURE_STATS_CONNSTATS_H #define TOR_FEATURE_STATS_CONNSTATS_H -void rep_hist_conn_stats_init(time_t now); -void rep_hist_note_or_conn_bytes(uint64_t conn_id, size_t num_read, +void conn_stats_init(time_t now); +void conn_stats_note_or_conn_bytes(uint64_t conn_id, size_t num_read, size_t num_written, time_t when); -void rep_hist_reset_conn_stats(time_t now); -char *rep_hist_format_conn_stats(time_t now); -time_t rep_hist_conn_stats_write(time_t now); -void rep_hist_conn_stats_term(void); -void bidi_map_free_all(void); +void conn_stats_reset(time_t now); +char *conn_stats_format(time_t now); +time_t conn_stats_save(time_t now); +void conn_stats_terminate(void); +void conn_stats_free_all(void); #endif /* !defined(TOR_FEATURE_STATS_CONNSTATS_H) */ diff --git a/src/feature/stats/rephist.c b/src/feature/stats/rephist.c index 5535a3ab0f..b6730e1226 100644 --- a/src/feature/stats/rephist.c +++ b/src/feature/stats/rephist.c @@ -2141,7 +2141,7 @@ rep_hist_free_all(void) tor_free(exit_bytes_written); tor_free(exit_streams); predicted_ports_free_all(); - bidi_map_free_all(); + conn_stats_free_all(); if (circuits_for_buffer_stats) { SMARTLIST_FOREACH(circuits_for_buffer_stats, circ_buffer_stats_t *, s, diff --git a/src/test/test_stats.c b/src/test/test_stats.c index c8a76e27d9..288757229a 100644 --- a/src/test/test_stats.c +++ b/src/test/test_stats.c @@ -112,36 +112,36 @@ test_stats(void *arg) /* Continue with testing connection statistics; we shouldn't collect * conn stats without initializing them. */ - rep_hist_note_or_conn_bytes(1, 20, 400, now); - s = rep_hist_format_conn_stats(now + 86400); + conn_stats_note_or_conn_bytes(1, 20, 400, now); + s = conn_stats_format(now + 86400); tt_ptr_op(s, OP_EQ, NULL); /* Initialize stats, note bytes, and generate history string. */ - rep_hist_conn_stats_init(now); - rep_hist_note_or_conn_bytes(1, 30000, 400000, now); - rep_hist_note_or_conn_bytes(1, 30000, 400000, now + 5); - rep_hist_note_or_conn_bytes(2, 400000, 30000, now + 10); - rep_hist_note_or_conn_bytes(2, 400000, 30000, now + 15); - s = rep_hist_format_conn_stats(now + 86400); + conn_stats_init(now); + conn_stats_note_or_conn_bytes(1, 30000, 400000, now); + conn_stats_note_or_conn_bytes(1, 30000, 400000, now + 5); + conn_stats_note_or_conn_bytes(2, 400000, 30000, now + 10); + conn_stats_note_or_conn_bytes(2, 400000, 30000, now + 15); + s = conn_stats_format(now + 86400); tt_str_op("conn-bi-direct 2010-08-12 13:27:30 (86400 s) 0,0,1,0\n",OP_EQ, s); tor_free(s); /* Stop collecting stats, add some bytes, and ensure we don't generate * a history string. */ - rep_hist_conn_stats_term(); - rep_hist_note_or_conn_bytes(2, 400000, 30000, now + 15); - s = rep_hist_format_conn_stats(now + 86400); + conn_stats_terminate(); + conn_stats_note_or_conn_bytes(2, 400000, 30000, now + 15); + s = conn_stats_format(now + 86400); tt_ptr_op(s, OP_EQ, NULL); /* Re-start stats, add some bytes, reset stats, and see what history we * get when observing no bytes at all. */ - rep_hist_conn_stats_init(now); - rep_hist_note_or_conn_bytes(1, 30000, 400000, now); - rep_hist_note_or_conn_bytes(1, 30000, 400000, now + 5); - rep_hist_note_or_conn_bytes(2, 400000, 30000, now + 10); - rep_hist_note_or_conn_bytes(2, 400000, 30000, now + 15); - rep_hist_reset_conn_stats(now); - s = rep_hist_format_conn_stats(now + 86400); + conn_stats_init(now); + conn_stats_note_or_conn_bytes(1, 30000, 400000, now); + conn_stats_note_or_conn_bytes(1, 30000, 400000, now + 5); + conn_stats_note_or_conn_bytes(2, 400000, 30000, now + 10); + conn_stats_note_or_conn_bytes(2, 400000, 30000, now + 15); + conn_stats_reset(now); + s = conn_stats_format(now + 86400); tt_str_op("conn-bi-direct 2010-08-12 13:27:30 (86400 s) 0,0,0,0\n",OP_EQ, s); tor_free(s); -- cgit v1.2.3-54-g00ecf From 515cc49cb7fce62db8256f2729e4473015574d1a Mon Sep 17 00:00:00 2001 From: Nick Mathewson Date: Fri, 10 Jul 2020 09:17:18 -0400 Subject: connstats: add and clarify some documentation. --- src/feature/stats/connstats.c | 19 ++++++++++++------- 1 file changed, 12 insertions(+), 7 deletions(-) diff --git a/src/feature/stats/connstats.c b/src/feature/stats/connstats.c index 32987ecf95..82b1adcd9c 100644 --- a/src/feature/stats/connstats.c +++ b/src/feature/stats/connstats.c @@ -8,8 +8,12 @@ * @file connstats.c * @brief Count bidirectional vs one-way connections. * - * Connection statistics, used by relays to count connections, and track - * one-way and bidirectional connections. + * Connection statistics, use to track one-way and bidirectional connections. + * + * Note that this code counts concurrent connections in each + * BIDI_INTERVAL-second interval, not total connections. It can tell you what + * fraction of connections are bidirectional at each time, not necessarily + * what number are bidirectional. **/ #include "orconfig.h" @@ -28,16 +32,16 @@ conn_stats_init(time_t now) start_of_conn_stats_interval = now; } -/* Count connections that we read and wrote less than these many bytes - * from/to as below threshold. */ +/** Count connections on which we read and wrote less than this many bytes + * as "below threshold." */ #define BIDI_THRESHOLD 20480 -/* Count connections that we read or wrote at least this factor as many +/** Count connections that we read or wrote at least this factor as many * bytes from/to than we wrote or read to/from as mostly reading or * writing. */ #define BIDI_FACTOR 10 -/* Interval length in seconds for considering read and written bytes for +/** Interval length in seconds for considering read and written bytes for * connection stats. */ #define BIDI_INTERVAL 10 @@ -75,13 +79,14 @@ typedef struct bidi_map_entry_t { static HT_HEAD(bidimap, bidi_map_entry_t) bidi_map = HT_INITIALIZER(); +/** Hashtable helper: return true if @a a and @a b have the same key. */ static int bidi_map_ent_eq(const bidi_map_entry_t *a, const bidi_map_entry_t *b) { return a->conn_id == b->conn_id; } -/* DOCDOC bidi_map_ent_hash */ +/** Hashtable helper: compute a digest for the key of @a entry. */ static unsigned bidi_map_ent_hash(const bidi_map_entry_t *entry) { -- cgit v1.2.3-54-g00ecf From 0b5e19d22312291d5c9f8a5e8f8f3e6ad2ef4920 Mon Sep 17 00:00:00 2001 From: Nick Mathewson Date: Fri, 10 Jul 2020 09:32:30 -0400 Subject: connstats: extract connection type counts into a structure. --- src/feature/stats/connstats.c | 58 +++++++++++++++++++++++-------------------- src/feature/stats/connstats.h | 2 +- 2 files changed, 32 insertions(+), 28 deletions(-) diff --git a/src/feature/stats/connstats.c b/src/feature/stats/connstats.c index 82b1adcd9c..2879a3018a 100644 --- a/src/feature/stats/connstats.c +++ b/src/feature/stats/connstats.c @@ -48,22 +48,28 @@ conn_stats_init(time_t now) /** Start of next BIDI_INTERVAL second interval. */ static time_t bidi_next_interval = 0; -/** Number of connections that we read and wrote less than BIDI_THRESHOLD - * bytes from/to in BIDI_INTERVAL seconds. */ -static uint32_t below_threshold = 0; +/** A single grouped set of connection type counts. */ +typedef struct conn_counts_t { + /** Number of connections that we read and wrote less than BIDI_THRESHOLD + * bytes from/to in BIDI_INTERVAL seconds. */ + uint32_t below_threshold; -/** Number of connections that we read at least BIDI_FACTOR times more - * bytes from than we wrote to in BIDI_INTERVAL seconds. */ -static uint32_t mostly_read = 0; + /** Number of connections that we read at least BIDI_FACTOR times more + * bytes from than we wrote to in BIDI_INTERVAL seconds. */ + uint32_t mostly_read; -/** Number of connections that we wrote at least BIDI_FACTOR times more - * bytes to than we read from in BIDI_INTERVAL seconds. */ -static uint32_t mostly_written = 0; + /** Number of connections that we wrote at least BIDI_FACTOR times more + * bytes to than we read from in BIDI_INTERVAL seconds. */ + uint32_t mostly_written; -/** Number of connections that we read and wrote at least BIDI_THRESHOLD - * bytes from/to, but not BIDI_FACTOR times more in either direction in - * BIDI_INTERVAL seconds. */ -static uint32_t both_read_and_written = 0; + /** Number of connections that we read and wrote at least BIDI_THRESHOLD + * bytes from/to, but not BIDI_FACTOR times more in either direction in + * BIDI_INTERVAL seconds. */ + uint32_t both_read_and_written; +} conn_counts_t ; + +/** A collection of connection counts, over all OR connections. */ +static conn_counts_t counts; /** Entry in a map from connection ID to the number of read and written * bytes on this connection in a BIDI_INTERVAL second interval. */ @@ -116,10 +122,7 @@ void conn_stats_reset(time_t now) { start_of_conn_stats_interval = now; - below_threshold = 0; - mostly_read = 0; - mostly_written = 0; - both_read_and_written = 0; + memset(&counts, 0, sizeof(counts)); conn_stats_free_all(); } @@ -147,16 +150,17 @@ conn_stats_note_or_conn_bytes(uint64_t conn_id, size_t num_read, /* Sum up last period's statistics */ if (when >= bidi_next_interval) { bidi_map_entry_t **ptr, **next, *ent; + conn_counts_t *cnt = &counts; for (ptr = HT_START(bidimap, &bidi_map); ptr; ptr = next) { ent = *ptr; if (ent->read + ent->written < BIDI_THRESHOLD) - below_threshold++; + cnt->below_threshold++; else if (ent->read >= ent->written * BIDI_FACTOR) - mostly_read++; + cnt->mostly_read++; else if (ent->written >= ent->read * BIDI_FACTOR) - mostly_written++; + cnt->mostly_written++; else - both_read_and_written++; + cnt->both_read_and_written++; next = HT_NEXT_RMV(bidimap, &bidi_map, ptr); tor_free(ent); } @@ -164,8 +168,8 @@ conn_stats_note_or_conn_bytes(uint64_t conn_id, size_t num_read, bidi_next_interval += BIDI_INTERVAL; log_info(LD_GENERAL, "%d below threshold, %d mostly read, " "%d mostly written, %d both read and written.", - below_threshold, mostly_read, mostly_written, - both_read_and_written); + cnt->below_threshold, cnt->mostly_read, cnt->mostly_written, + cnt->both_read_and_written); } /* Add this connection's bytes. */ if (num_read > 0 || num_written > 0) { @@ -202,10 +206,10 @@ conn_stats_format(time_t now) tor_asprintf(&result, "conn-bi-direct %s (%d s) %d,%d,%d,%d\n", written, (unsigned) (now - start_of_conn_stats_interval), - below_threshold, - mostly_read, - mostly_written, - both_read_and_written); + counts.below_threshold, + counts.mostly_read, + counts.mostly_written, + counts.both_read_and_written); return result; } diff --git a/src/feature/stats/connstats.h b/src/feature/stats/connstats.h index 26ff74cfd3..43b6549741 100644 --- a/src/feature/stats/connstats.h +++ b/src/feature/stats/connstats.h @@ -14,7 +14,7 @@ void conn_stats_init(time_t now); void conn_stats_note_or_conn_bytes(uint64_t conn_id, size_t num_read, - size_t num_written, time_t when); + size_t num_written, time_t when); void conn_stats_reset(time_t now); char *conn_stats_format(time_t now); time_t conn_stats_save(time_t now); -- cgit v1.2.3-54-g00ecf From 54141d66e27a47719fe81a886d5e92d2b730f374 Mon Sep 17 00:00:00 2001 From: Nick Mathewson Date: Fri, 10 Jul 2020 09:36:07 -0400 Subject: connstats: extract functions for summarizing a connection's status --- src/feature/stats/connstats.c | 58 +++++++++++++++++++++++++++++-------------- 1 file changed, 39 insertions(+), 19 deletions(-) diff --git a/src/feature/stats/connstats.c b/src/feature/stats/connstats.c index 2879a3018a..7d7c67361d 100644 --- a/src/feature/stats/connstats.c +++ b/src/feature/stats/connstats.c @@ -134,6 +134,44 @@ conn_stats_terminate(void) conn_stats_reset(0); } +/** + * Record a single entry @a ent in the counts structure @cnt. + */ +static void +add_entry_to_count(conn_counts_t *cnt, const bidi_map_entry_t *ent) +{ + if (ent->read + ent->written < BIDI_THRESHOLD) + cnt->below_threshold++; + else if (ent->read >= ent->written * BIDI_FACTOR) + cnt->mostly_read++; + else if (ent->written >= ent->read * BIDI_FACTOR) + cnt->mostly_written++; + else + cnt->both_read_and_written++; +} + +/** + * Count all the connection information we've received during the current + * period in 'bidimap', and store that information in the appropriate count + * structures. + **/ +static void +collect_period_statistics(void) +{ + bidi_map_entry_t **ptr, **next, *ent; + conn_counts_t *cnt = &counts; + for (ptr = HT_START(bidimap, &bidi_map); ptr; ptr = next) { + ent = *ptr; + add_entry_to_count(cnt, ent); + next = HT_NEXT_RMV(bidimap, &bidi_map, ptr); + tor_free(ent); + } + log_info(LD_GENERAL, "%d below threshold, %d mostly read, " + "%d mostly written, %d both read and written.", + cnt->below_threshold, cnt->mostly_read, cnt->mostly_written, + cnt->both_read_and_written); +} + /** We read num_read bytes and wrote num_written from/to OR * connection conn_id in second when. If this is the first * observation in a new interval, sum up the last observations. Add bytes @@ -149,27 +187,9 @@ conn_stats_note_or_conn_bytes(uint64_t conn_id, size_t num_read, bidi_next_interval = when + BIDI_INTERVAL; /* Sum up last period's statistics */ if (when >= bidi_next_interval) { - bidi_map_entry_t **ptr, **next, *ent; - conn_counts_t *cnt = &counts; - for (ptr = HT_START(bidimap, &bidi_map); ptr; ptr = next) { - ent = *ptr; - if (ent->read + ent->written < BIDI_THRESHOLD) - cnt->below_threshold++; - else if (ent->read >= ent->written * BIDI_FACTOR) - cnt->mostly_read++; - else if (ent->written >= ent->read * BIDI_FACTOR) - cnt->mostly_written++; - else - cnt->both_read_and_written++; - next = HT_NEXT_RMV(bidimap, &bidi_map, ptr); - tor_free(ent); - } + collect_period_statistics(); while (when >= bidi_next_interval) bidi_next_interval += BIDI_INTERVAL; - log_info(LD_GENERAL, "%d below threshold, %d mostly read, " - "%d mostly written, %d both read and written.", - cnt->below_threshold, cnt->mostly_read, cnt->mostly_written, - cnt->both_read_and_written); } /* Add this connection's bytes. */ if (num_read > 0 || num_written > 0) { -- cgit v1.2.3-54-g00ecf From dbdf8bebde8b0f18009c7e9c6e89406f241ad0e6 Mon Sep 17 00:00:00 2001 From: Nick Mathewson Date: Fri, 10 Jul 2020 09:47:55 -0400 Subject: Collect IPv6 bidi connection statistics --- src/core/mainloop/connection.c | 4 ++-- src/feature/stats/connstats.c | 37 +++++++++++++++++++++++++++---------- src/feature/stats/connstats.h | 3 ++- src/test/test_stats.c | 28 ++++++++++++++++------------ 4 files changed, 47 insertions(+), 25 deletions(-) diff --git a/src/core/mainloop/connection.c b/src/core/mainloop/connection.c index 0d2e6a220b..1d53e077d1 100644 --- a/src/core/mainloop/connection.c +++ b/src/core/mainloop/connection.c @@ -3363,11 +3363,11 @@ record_num_bytes_transferred_impl(connection_t *conn, if (!connection_is_rate_limited(conn)) return; + const bool is_ipv6 = (conn->socket_family == AF_INET6); if (conn->type == CONN_TYPE_OR) conn_stats_note_or_conn_bytes(conn->global_identifier, num_read, - num_written, now); + num_written, now, is_ipv6); - const bool is_ipv6 = (conn->socket_family == AF_INET6); if (num_read > 0) { bwhist_note_bytes_read(num_read, now, is_ipv6); } diff --git a/src/feature/stats/connstats.c b/src/feature/stats/connstats.c index 7d7c67361d..73bc8d7ccc 100644 --- a/src/feature/stats/connstats.c +++ b/src/feature/stats/connstats.c @@ -70,6 +70,8 @@ typedef struct conn_counts_t { /** A collection of connection counts, over all OR connections. */ static conn_counts_t counts; +/** A collection of connection counts, over IPv6 OR connections only. */ +static conn_counts_t counts_ipv6; /** Entry in a map from connection ID to the number of read and written * bytes on this connection in a BIDI_INTERVAL second interval. */ @@ -78,6 +80,7 @@ typedef struct bidi_map_entry_t { uint64_t conn_id; /**< Connection ID */ size_t read; /**< Number of read bytes */ size_t written; /**< Number of written bytes */ + bool is_ipv6; /**< True if this is an IPv6 connection */ } bidi_map_entry_t; /** Map of OR connections together with the number of read and written @@ -123,6 +126,7 @@ conn_stats_reset(time_t now) { start_of_conn_stats_interval = now; memset(&counts, 0, sizeof(counts)); + memset(&counts_ipv6, 0, sizeof(counts_ipv6)); conn_stats_free_all(); } @@ -159,17 +163,18 @@ static void collect_period_statistics(void) { bidi_map_entry_t **ptr, **next, *ent; - conn_counts_t *cnt = &counts; for (ptr = HT_START(bidimap, &bidi_map); ptr; ptr = next) { ent = *ptr; - add_entry_to_count(cnt, ent); + add_entry_to_count(&counts, ent); + if (ent->is_ipv6) + add_entry_to_count(&counts_ipv6, ent); next = HT_NEXT_RMV(bidimap, &bidi_map, ptr); tor_free(ent); } log_info(LD_GENERAL, "%d below threshold, %d mostly read, " "%d mostly written, %d both read and written.", - cnt->below_threshold, cnt->mostly_read, cnt->mostly_written, - cnt->both_read_and_written); + counts.below_threshold, counts.mostly_read, counts.mostly_written, + counts.both_read_and_written); } /** We read num_read bytes and wrote num_written from/to OR @@ -178,7 +183,8 @@ collect_period_statistics(void) * for this connection. */ void conn_stats_note_or_conn_bytes(uint64_t conn_id, size_t num_read, - size_t num_written, time_t when) + size_t num_written, time_t when, + bool is_ipv6) { if (!start_of_conn_stats_interval) return; @@ -199,11 +205,13 @@ conn_stats_note_or_conn_bytes(uint64_t conn_id, size_t num_read, if (entry) { entry->written += num_written; entry->read += num_read; + entry->is_ipv6 |= is_ipv6; } else { entry = tor_malloc_zero(sizeof(bidi_map_entry_t)); entry->conn_id = conn_id; entry->written = num_written; entry->read = num_read; + entry->is_ipv6 = is_ipv6; HT_INSERT(bidimap, &bidi_map, entry); } } @@ -215,21 +223,30 @@ conn_stats_note_or_conn_bytes(uint64_t conn_id, size_t num_read, char * conn_stats_format(time_t now) { - char *result, written[ISO_TIME_LEN+1]; + char *result, written_at[ISO_TIME_LEN+1]; if (!start_of_conn_stats_interval) return NULL; /* Not initialized. */ tor_assert(now >= start_of_conn_stats_interval); - format_iso_time(written, now); - tor_asprintf(&result, "conn-bi-direct %s (%d s) %d,%d,%d,%d\n", - written, + format_iso_time(written_at, now); + tor_asprintf(&result, + "conn-bi-direct %s (%d s) %d,%d,%d,%d\n" + "ipv6-conn-bi-direct %s (%d s) %d,%d,%d,%d\n", + written_at, (unsigned) (now - start_of_conn_stats_interval), counts.below_threshold, counts.mostly_read, counts.mostly_written, - counts.both_read_and_written); + counts.both_read_and_written, + written_at, + (unsigned) (now - start_of_conn_stats_interval), + counts_ipv6.below_threshold, + counts_ipv6.mostly_read, + counts_ipv6.mostly_written, + counts_ipv6.both_read_and_written); + return result; } diff --git a/src/feature/stats/connstats.h b/src/feature/stats/connstats.h index 43b6549741..1a03d0748b 100644 --- a/src/feature/stats/connstats.h +++ b/src/feature/stats/connstats.h @@ -14,7 +14,8 @@ void conn_stats_init(time_t now); void conn_stats_note_or_conn_bytes(uint64_t conn_id, size_t num_read, - size_t num_written, time_t when); + size_t num_written, time_t when, + bool is_ipv6); void conn_stats_reset(time_t now); char *conn_stats_format(time_t now); time_t conn_stats_save(time_t now); diff --git a/src/test/test_stats.c b/src/test/test_stats.c index 288757229a..f0715c2e45 100644 --- a/src/test/test_stats.c +++ b/src/test/test_stats.c @@ -112,37 +112,41 @@ test_stats(void *arg) /* Continue with testing connection statistics; we shouldn't collect * conn stats without initializing them. */ - conn_stats_note_or_conn_bytes(1, 20, 400, now); + conn_stats_note_or_conn_bytes(1, 20, 400, now, false); s = conn_stats_format(now + 86400); tt_ptr_op(s, OP_EQ, NULL); /* Initialize stats, note bytes, and generate history string. */ conn_stats_init(now); - conn_stats_note_or_conn_bytes(1, 30000, 400000, now); - conn_stats_note_or_conn_bytes(1, 30000, 400000, now + 5); - conn_stats_note_or_conn_bytes(2, 400000, 30000, now + 10); - conn_stats_note_or_conn_bytes(2, 400000, 30000, now + 15); + conn_stats_note_or_conn_bytes(1, 30000, 400000, now, false); + conn_stats_note_or_conn_bytes(1, 30000, 400000, now + 5, false); + conn_stats_note_or_conn_bytes(2, 400000, 30000, now + 10, true); + conn_stats_note_or_conn_bytes(2, 400000, 30000, now + 15, true); s = conn_stats_format(now + 86400); - tt_str_op("conn-bi-direct 2010-08-12 13:27:30 (86400 s) 0,0,1,0\n",OP_EQ, s); + tt_str_op("conn-bi-direct 2010-08-12 13:27:30 (86400 s) 0,0,1,0\n" + "ipv6-conn-bi-direct 2010-08-12 13:27:30 (86400 s) 0,0,0,0\n", + OP_EQ, s); tor_free(s); /* Stop collecting stats, add some bytes, and ensure we don't generate * a history string. */ conn_stats_terminate(); - conn_stats_note_or_conn_bytes(2, 400000, 30000, now + 15); + conn_stats_note_or_conn_bytes(2, 400000, 30000, now + 15, true); s = conn_stats_format(now + 86400); tt_ptr_op(s, OP_EQ, NULL); /* Re-start stats, add some bytes, reset stats, and see what history we * get when observing no bytes at all. */ conn_stats_init(now); - conn_stats_note_or_conn_bytes(1, 30000, 400000, now); - conn_stats_note_or_conn_bytes(1, 30000, 400000, now + 5); - conn_stats_note_or_conn_bytes(2, 400000, 30000, now + 10); - conn_stats_note_or_conn_bytes(2, 400000, 30000, now + 15); + conn_stats_note_or_conn_bytes(1, 30000, 400000, now, false); + conn_stats_note_or_conn_bytes(1, 30000, 400000, now + 5, false); + conn_stats_note_or_conn_bytes(2, 400000, 30000, now + 10, true); + conn_stats_note_or_conn_bytes(2, 400000, 30000, now + 15, true); conn_stats_reset(now); s = conn_stats_format(now + 86400); - tt_str_op("conn-bi-direct 2010-08-12 13:27:30 (86400 s) 0,0,0,0\n",OP_EQ, s); + tt_str_op("conn-bi-direct 2010-08-12 13:27:30 (86400 s) 0,0,0,0\n" + "ipv6-conn-bi-direct 2010-08-12 13:27:30 (86400 s) 0,0,0,0\n", + OP_EQ, s); tor_free(s); /* Continue with testing buffer statistics; we shouldn't collect buffer -- cgit v1.2.3-54-g00ecf From 0f60a1d33c64ec71eea3ea95e2a87e32dd74421c Mon Sep 17 00:00:00 2001 From: Nick Mathewson Date: Fri, 10 Jul 2020 09:50:04 -0400 Subject: connstats: use correct formatter for uint32_t. We have had no reports of negative counts here, so it is probably safe not to backport this. --- src/feature/stats/connstats.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/feature/stats/connstats.c b/src/feature/stats/connstats.c index 73bc8d7ccc..f0c786efb3 100644 --- a/src/feature/stats/connstats.c +++ b/src/feature/stats/connstats.c @@ -232,8 +232,10 @@ conn_stats_format(time_t now) format_iso_time(written_at, now); tor_asprintf(&result, - "conn-bi-direct %s (%d s) %d,%d,%d,%d\n" - "ipv6-conn-bi-direct %s (%d s) %d,%d,%d,%d\n", + "conn-bi-direct %s (%d s) " + "%"PRIu32",%"PRIu32",%"PRIu32",%"PRIu32"\n" + "ipv6-conn-bi-direct %s (%d s) " + "%"PRIu32",%"PRIu32",%"PRIu32",%"PRIu32"\n", written_at, (unsigned) (now - start_of_conn_stats_interval), counts.below_threshold, -- cgit v1.2.3-54-g00ecf From fae19df98581ee5128faca704e384a5eeefc5966 Mon Sep 17 00:00:00 2001 From: Nick Mathewson Date: Fri, 10 Jul 2020 09:52:35 -0400 Subject: Changes file for ipv6 bidi (ticket 33264) --- changes/ticket33264 | 4 ++++ 1 file changed, 4 insertions(+) create mode 100644 changes/ticket33264 diff --git a/changes/ticket33264 b/changes/ticket33264 new file mode 100644 index 0000000000..c72ea1c57a --- /dev/null +++ b/changes/ticket33264 @@ -0,0 +1,4 @@ + o Minor features (statistics, ipv6): + - Relays now publish IPv6-specific counts of single-direction + versus bidirectional relay connections. + Closes ticket 33264. -- cgit v1.2.3-54-g00ecf