aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorDavid Goulet <dgoulet@torproject.org>2020-07-10 13:12:22 -0400
committerDavid Goulet <dgoulet@torproject.org>2020-07-10 13:12:22 -0400
commit063cdb3142f380ca1167f50d42fb61c2687dbef6 (patch)
tree66f1c5c1defd823a127f7b0a8e1635ba80b19566 /src
parent6fb1637255122dc3660486cf731c0f4640fd98db (diff)
parentfae19df98581ee5128faca704e384a5eeefc5966 (diff)
downloadtor-063cdb3142f380ca1167f50d42fb61c2687dbef6.tar.gz
tor-063cdb3142f380ca1167f50d42fb61c2687dbef6.zip
Merge branch 'tor-gitlab/mr/39'
Diffstat (limited to 'src')
-rw-r--r--src/core/mainloop/connection.c7
-rw-r--r--src/core/mainloop/mainloop.c3
-rw-r--r--src/feature/relay/relay_config.c5
-rw-r--r--src/feature/stats/connstats.c283
-rw-r--r--src/feature/stats/connstats.h25
-rw-r--r--src/feature/stats/include.am2
-rw-r--r--src/feature/stats/rephist.c223
-rw-r--r--src/feature/stats/rephist.h8
-rw-r--r--src/test/test_stats.c45
9 files changed, 346 insertions, 255 deletions
diff --git a/src/core/mainloop/connection.c b/src/core/mainloop/connection.c
index 2f3c70365a..1d53e077d1 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"
@@ -3362,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)
- rep_hist_note_or_conn_bytes(conn->global_identifier, num_read,
- num_written, now);
+ conn_stats_note_or_conn_bytes(conn->global_identifier, num_read,
+ 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/core/mainloop/mainloop.c b/src/core/mainloop/mainloop.c
index e4e17f6b76..3bf9be566b 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"
@@ -1950,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 bd1c1e8fe8..7cb7f2ccfd 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"
@@ -1307,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) {
@@ -1337,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
new file mode 100644
index 0000000000..f0c786efb3
--- /dev/null
+++ b/src/feature/stats/connstats.c
@@ -0,0 +1,283 @@
+/* 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, 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"
+#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
+conn_stats_init(time_t now)
+{
+ start_of_conn_stats_interval = now;
+}
+
+/** 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
+ * 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;
+
+/** 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. */
+ 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. */
+ 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. */
+ uint32_t both_read_and_written;
+} 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. */
+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 */
+ 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
+ * bytes in the current BIDI_INTERVAL second interval. */
+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;
+}
+
+/** Hashtable helper: compute a digest for the key of @a entry. */
+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
+conn_stats_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
+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();
+}
+
+/** Stop collecting connection stats in a way that we can re-start doing
+ * so in conn_stats_init(). */
+void
+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;
+ for (ptr = HT_START(bidimap, &bidi_map); ptr; ptr = next) {
+ ent = *ptr;
+ 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.",
+ counts.below_threshold, counts.mostly_read, counts.mostly_written,
+ counts.both_read_and_written);
+}
+
+/** We read <b>num_read</b> bytes and wrote <b>num_written</b> from/to OR
+ * connection <b>conn_id</b> in second <b>when</b>. If this is the first
+ * observation in a new interval, sum up the last observations. Add bytes
+ * 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,
+ bool is_ipv6)
+{
+ 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) {
+ collect_period_statistics();
+ while (when >= bidi_next_interval)
+ bidi_next_interval += BIDI_INTERVAL;
+ }
+ /* 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;
+ 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);
+ }
+ }
+}
+
+/** Return a newly allocated string containing the connection statistics
+ * until <b>now</b>, or NULL if we're not collecting conn stats. Caller must
+ * ensure start_of_conn_stats_interval is in the past. */
+char *
+conn_stats_format(time_t now)
+{
+ 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_at, now);
+ tor_asprintf(&result,
+ "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,
+ counts.mostly_read,
+ counts.mostly_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;
+}
+
+/** 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
+conn_stats_save(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 = conn_stats_format(now);
+
+ /* Reset counters. */
+ conn_stats_reset(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..1a03d0748b
--- /dev/null
+++ b/src/feature/stats/connstats.h
@@ -0,0 +1,25 @@
+/* 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 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,
+ 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);
+void conn_stats_terminate(void);
+void conn_stats_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..b6730e1226 100644
--- a/src/feature/stats/rephist.c
+++ b/src/feature/stats/rephist.c
@@ -43,9 +43,6 @@
* <li>Descriptor serving statistics, used by directory caches to track
* how many descriptors they've served.
*
- * <li>Connection statistics, used by relays to track one-way and
- * bidirectional connections.
- *
* <li>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 <b>num_read</b> bytes and wrote <b>num_written</b> from/to OR
- * connection <b>conn_id</b> in second <b>when</b>. 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 <b>now</b>, 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.
@@ -2360,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/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..f0715c2e45 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"
@@ -111,37 +112,41 @@ 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, false);
+ 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);
- tt_str_op("conn-bi-direct 2010-08-12 13:27:30 (86400 s) 0,0,1,0\n",OP_EQ, s);
+ conn_stats_init(now);
+ 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"
+ "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. */
- 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, 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. */
- 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);
- tt_str_op("conn-bi-direct 2010-08-12 13:27:30 (86400 s) 0,0,0,0\n",OP_EQ, s);
+ conn_stats_init(now);
+ 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"
+ "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