summaryrefslogtreecommitdiff
path: root/src/or/control.c
diff options
context:
space:
mode:
authorKarsten Loesing <karsten.loesing@gmx.net>2013-02-06 14:26:11 +0100
committerKarsten Loesing <karsten.loesing@gmx.net>2013-05-16 14:18:08 +0200
commitdd5ce2157d8c47ffa3686b0579813e7b1aae8069 (patch)
tree0d56a4aec246abf38d06df55655262f942f2e6c1 /src/or/control.c
parentc386d2d6ce4c4f58163acb385c7a5de1da8c5e30 (diff)
downloadtor-dd5ce2157d8c47ffa3686b0579813e7b1aae8069.tar.gz
tor-dd5ce2157d8c47ffa3686b0579813e7b1aae8069.zip
Add new TB_EMPTY event.
Jointly authored with Rob Jansen <jansen@cs.umn.edu>.
Diffstat (limited to 'src/or/control.c')
-rw-r--r--src/or/control.c102
1 files changed, 101 insertions, 1 deletions
diff --git a/src/or/control.c b/src/or/control.c
index 66258775e9..47d08c295e 100644
--- a/src/or/control.c
+++ b/src/or/control.c
@@ -84,7 +84,8 @@
#define EVENT_CONF_CHANGED 0x0019
#define EVENT_CONN_BW 0x001A
#define EVENT_CELL_STATS 0x001B
-#define EVENT_MAX_ 0x001B
+#define EVENT_TB_EMPTY 0x001C
+#define EVENT_MAX_ 0x001C
/* If EVENT_MAX_ ever hits 0x0020, we need to make the mask wider. */
/** Bitfield: The bit 1&lt;&lt;e is set if <b>any</b> open control
@@ -962,6 +963,7 @@ static const struct control_event_t control_event_table[] = {
{ EVENT_CONF_CHANGED, "CONF_CHANGED"},
{ EVENT_CONN_BW, "CONN_BW" },
{ EVENT_CELL_STATS, "CELL_STATS" },
+ { EVENT_TB_EMPTY, "TB_EMPTY" },
{ 0, NULL },
};
@@ -4119,6 +4121,104 @@ control_event_circuit_cell_stats(void)
return 0;
}
+/** Helper: return the time in millis that a given bucket was empty,
+ * capped at the time in millis since last refilling that bucket. Return
+ * 0 if the bucket was not empty during the last refill period. */
+static uint32_t
+bucket_millis_empty(int prev_tokens, uint32_t last_empty_time,
+ uint32_t milliseconds_elapsed)
+{
+ uint32_t result = 0, refilled;
+ if (prev_tokens <= 0) {
+ struct timeval tvnow;
+ tor_gettimeofday_cached(&tvnow);
+ refilled = (uint32_t)((tvnow.tv_sec % 86400L) * 1000L +
+ (uint32_t)tvnow.tv_usec / (uint32_t)1000L);
+ result = (uint32_t)((refilled + 86400L * 1000L - last_empty_time) %
+ (86400L * 1000L));
+ if (result > milliseconds_elapsed)
+ result = milliseconds_elapsed;
+ }
+ return result;
+}
+
+/** Token buckets have been refilled: tell any interested control
+ * connections how global and relay token buckets have changed. */
+int
+control_event_refill_global(int global_read, int prev_global_read,
+ uint32_t global_read_emptied_time,
+ int global_write, int prev_global_write,
+ uint32_t global_write_emptied_time,
+ int relay_read, int prev_relay_read,
+ uint32_t relay_read_emptied_time,
+ int relay_write, int prev_relay_write,
+ uint32_t relay_write_emptied_time,
+ uint32_t milliseconds_elapsed)
+{
+ uint32_t global_read_empty_time, global_write_empty_time,
+ relay_read_empty_time, relay_write_empty_time;
+ if (!get_options()->TestingTorNetwork ||
+ !EVENT_IS_INTERESTING(EVENT_TB_EMPTY))
+ return 0;
+ if (prev_global_read == global_read &&
+ prev_global_write == global_write &&
+ prev_relay_read == relay_read &&
+ prev_relay_write == relay_write)
+ return 0;
+ if (prev_global_read <= 0 && prev_global_write <= 0) {
+ global_read_empty_time = bucket_millis_empty(prev_global_read,
+ global_read_emptied_time, milliseconds_elapsed);
+ global_write_empty_time = bucket_millis_empty(prev_global_write,
+ global_write_emptied_time, milliseconds_elapsed);
+ send_control_event(EVENT_TB_EMPTY, ALL_FORMATS,
+ "650 TB_EMPTY GLOBAL READ=%d WRITTEN=%d "
+ "LAST=%d\r\n",
+ global_read_empty_time, global_write_empty_time,
+ milliseconds_elapsed);
+ }
+ if (prev_relay_read <= 0 && prev_relay_write <= 0) {
+ relay_read_empty_time = bucket_millis_empty(prev_relay_read,
+ relay_read_emptied_time, milliseconds_elapsed);
+ relay_write_empty_time = bucket_millis_empty(prev_relay_write,
+ relay_write_emptied_time, milliseconds_elapsed);
+ send_control_event(EVENT_TB_EMPTY, ALL_FORMATS,
+ "650 TB_EMPTY RELAY READ=%d WRITTEN=%d "
+ "LAST=%d\r\n",
+ relay_read_empty_time, relay_write_empty_time,
+ milliseconds_elapsed);
+ }
+ return 0;
+}
+
+/** Token buckets of a connection have been refilled: tell any interested
+ * control connections how per-connection token buckets have changed. */
+int
+control_event_refill_conn(or_connection_t *or_conn,
+ int prev_read, int prev_write,
+ uint32_t milliseconds_elapsed)
+{
+ uint32_t read_bucket_empty_time, write_bucket_empty_time;
+ if (!get_options()->TestingTorNetwork ||
+ !EVENT_IS_INTERESTING(EVENT_TB_EMPTY))
+ return 0;
+ if (prev_read == or_conn->read_bucket &&
+ prev_write == or_conn->write_bucket)
+ return 0;
+ if (prev_read <= 0 || prev_write <= 0) {
+ read_bucket_empty_time = bucket_millis_empty(prev_read,
+ or_conn->read_emptied_time, milliseconds_elapsed);
+ write_bucket_empty_time = bucket_millis_empty(prev_write,
+ or_conn->write_emptied_time, milliseconds_elapsed);
+ send_control_event(EVENT_TB_EMPTY, ALL_FORMATS,
+ "650 TB_EMPTY ORCONN ID="U64_FORMAT" READ=%d "
+ "WRITTEN=%d LAST=%d\r\n",
+ U64_PRINTF_ARG(or_conn->base_.global_identifier),
+ read_bucket_empty_time, write_bucket_empty_time,
+ milliseconds_elapsed);
+ }
+ return 0;
+}
+
/** A second or more has elapsed: tell any interested control
* connections how much bandwidth we used. */
int