aboutsummaryrefslogtreecommitdiff
path: root/src/or/relay.c
diff options
context:
space:
mode:
authorKarsten Loesing <karsten.loesing@gmx.net>2013-10-28 11:30:49 +0100
committerKarsten Loesing <karsten.loesing@gmx.net>2013-10-28 12:09:42 +0100
commit2e0fad542cccddf9ad8b8dbaeba8b1e825c09ff4 (patch)
treef4639f6ed8b224087e665373ba147df1fd53144d /src/or/relay.c
parent49278cd68a0d84727ae1131e677bc3481b3e2fc7 (diff)
parente46de82c97e694d3bfa399af48b9de9365e264bd (diff)
downloadtor-2e0fad542cccddf9ad8b8dbaeba8b1e825c09ff4.tar
tor-2e0fad542cccddf9ad8b8dbaeba8b1e825c09ff4.tar.gz
Merge branch 'morestats4' into morestats5
Conflicts: doc/tor.1.txt src/or/config.c src/or/connection.h src/or/control.c src/or/control.h src/or/or.h src/or/relay.c src/or/relay.h src/test/test.c
Diffstat (limited to 'src/or/relay.c')
-rw-r--r--src/or/relay.c121
1 files changed, 110 insertions, 11 deletions
diff --git a/src/or/relay.c b/src/or/relay.c
index d12850d18..7947ca373 100644
--- a/src/or/relay.c
+++ b/src/or/relay.c
@@ -2050,6 +2050,10 @@ static mp_pool_t *cell_pool = NULL;
* statistics. */
static mp_pool_t *it_pool = NULL;
+/** Memory pool to allocate insertion_command_elem_t objects used for cell
+ * statistics if CELL_STATS events are enabled. */
+static mp_pool_t *ic_pool = NULL;
+
/** Allocate structures to hold cells. */
void
init_cell_pool(void)
@@ -2058,8 +2062,8 @@ init_cell_pool(void)
cell_pool = mp_pool_new(sizeof(packed_cell_t), 128*1024);
}
-/** Free all storage used to hold cells (and insertion times if we measure
- * cell statistics). */
+/** Free all storage used to hold cells (and insertion times/commands if we
+ * measure cell statistics and/or if CELL_STATS events are enabled). */
void
free_cell_pool(void)
{
@@ -2072,6 +2076,10 @@ free_cell_pool(void)
mp_pool_destroy(it_pool);
it_pool = NULL;
}
+ if (ic_pool) {
+ mp_pool_destroy(ic_pool);
+ ic_pool = NULL;
+ }
}
/** Free excess storage in cell pool. */
@@ -2144,14 +2152,68 @@ cell_queue_append(cell_queue_t *queue, packed_cell_t *cell)
++queue->n;
}
-/** Append a newly allocated copy of <b>cell</b> to the end of <b>queue</b> */
+/** Append command of type <b>command</b> in direction to <b>queue</b> for
+ * CELL_STATS event. */
+static void
+cell_command_queue_append(cell_queue_t *queue, uint8_t command)
+{
+ insertion_command_queue_t *ic_queue = queue->insertion_commands;
+ if (!ic_pool)
+ ic_pool = mp_pool_new(sizeof(insertion_command_elem_t), 1024);
+ if (!ic_queue) {
+ ic_queue = tor_malloc_zero(sizeof(insertion_command_queue_t));
+ queue->insertion_commands = ic_queue;
+ }
+ if (ic_queue->last && ic_queue->last->command == command) {
+ ic_queue->last->counter++;
+ } else {
+ insertion_command_elem_t *elem = mp_pool_get(ic_pool);
+ elem->next = NULL;
+ elem->command = command;
+ elem->counter = 1;
+ if (ic_queue->last) {
+ ic_queue->last->next = elem;
+ ic_queue->last = elem;
+ } else {
+ ic_queue->first = ic_queue->last = elem;
+ }
+ }
+}
+
+/** Retrieve oldest command from <b>queue</b> and write it to
+ * <b>command</b> for CELL_STATS event. Return 0 for success, -1
+ * otherwise. */
+static int
+cell_command_queue_pop(uint8_t *command, cell_queue_t *queue)
+{
+ int res = -1;
+ insertion_command_queue_t *ic_queue = queue->insertion_commands;
+ if (ic_queue && ic_queue->first) {
+ insertion_command_elem_t *ic_elem = ic_queue->first;
+ ic_elem->counter--;
+ if (ic_elem->counter < 1) {
+ ic_queue->first = ic_elem->next;
+ if (ic_elem == ic_queue->last)
+ ic_queue->last = NULL;
+ mp_pool_release(ic_elem);
+ }
+ *command = ic_elem->command;
+ res = 0;
+ }
+ return res;
+}
+
+/** Append a newly allocated copy of <b>cell</b> to the end of the
+ * <b>exitward</b> (or app-ward) <b>queue</b> of <b>circ</b>. */
void
-cell_queue_append_packed_copy(cell_queue_t *queue, const cell_t *cell,
+cell_queue_append_packed_copy(circuit_t *circ, cell_queue_t *queue,
+ int exitward, const cell_t *cell,
int wide_circ_ids, int use_stats)
{
packed_cell_t *copy = packed_cell_copy(cell, wide_circ_ids);
/* Remember the time when this cell was put in the queue. */
- if (get_options()->CellStatistics && use_stats) {
+ if ((get_options()->CellStatistics ||
+ get_options()->TestingEnableCellStatsEvent) && use_stats) {
struct timeval now;
uint32_t added;
insertion_time_queue_t *it_queue = queue->insertion_times;
@@ -2180,6 +2242,18 @@ cell_queue_append_packed_copy(cell_queue_t *queue, const cell_t *cell,
}
}
}
+ /* Remember that we added a cell to the queue, and remember the cell
+ * command. */
+ if (get_options()->TestingEnableCellStatsEvent) {
+ testing_cell_stats_entry_t *ent =
+ tor_malloc_zero(sizeof(testing_cell_stats_entry_t));
+ ent->command = cell->command;
+ ent->exitward = exitward;
+ if (!circ->testing_cell_stats)
+ circ->testing_cell_stats = smartlist_new();
+ smartlist_add(circ->testing_cell_stats, ent);
+ cell_command_queue_append(queue, cell->command);
+ }
cell_queue_append(queue, copy);
}
@@ -2421,7 +2495,8 @@ channel_flush_from_first_active_circuit(channel_t *chan, int max)
cell = cell_queue_pop(queue);
/* Calculate the exact time that this cell has spent in the queue. */
- if (get_options()->CellStatistics && !CIRCUIT_IS_ORIGIN(circ)) {
+ if (get_options()->CellStatistics ||
+ get_options()->TestingEnableCellStatsEvent) {
struct timeval tvnow;
uint32_t flushed;
uint32_t cell_waiting_time;
@@ -2435,7 +2510,6 @@ channel_flush_from_first_active_circuit(channel_t *chan, int max)
"recently enabled.");
} else {
insertion_time_elem_t *elem = it_queue->first;
- or_circ = TO_OR_CIRCUIT(circ);
cell_waiting_time =
(uint32_t)((flushed * 10L + SECONDS_IN_A_DAY * 1000L -
elem->insertion_time * 10L) %
@@ -2448,8 +2522,30 @@ channel_flush_from_first_active_circuit(channel_t *chan, int max)
it_queue->last = NULL;
mp_pool_release(elem);
}
- or_circ->total_cell_waiting_time += cell_waiting_time;
- or_circ->processed_cells++;
+ if (get_options()->CellStatistics && !CIRCUIT_IS_ORIGIN(circ)) {
+ or_circ = TO_OR_CIRCUIT(circ);
+ or_circ->total_cell_waiting_time += cell_waiting_time;
+ or_circ->processed_cells++;
+ }
+ if (get_options()->TestingEnableCellStatsEvent) {
+ uint8_t command;
+ if (cell_command_queue_pop(&command, queue) < 0) {
+ log_info(LD_GENERAL, "Cannot determine command of cell. "
+ "Looks like the CELL_STATS event was "
+ "recently enabled.");
+ } else {
+ testing_cell_stats_entry_t *ent =
+ tor_malloc_zero(sizeof(testing_cell_stats_entry_t));
+ ent->command = command;
+ ent->waiting_time = (unsigned int)cell_waiting_time / 10;
+ ent->removed = 1;
+ if (circ->n_chan == chan)
+ ent->exitward = 1;
+ if (!circ->testing_cell_stats)
+ circ->testing_cell_stats = smartlist_new();
+ smartlist_add(circ->testing_cell_stats, ent);
+ }
+ }
}
}
@@ -2524,10 +2620,12 @@ append_cell_to_circuit_queue(circuit_t *circ, channel_t *chan,
uint32_t tgt_max_middle_cells, p_len, n_len, tmp, hard_max_middle_cells;
#endif
+ int exitward;
if (circ->marked_for_close)
return;
- if (direction == CELL_DIRECTION_OUT) {
+ exitward = (direction == CELL_DIRECTION_OUT);
+ if (exitward) {
queue = &circ->n_chan_cells;
streams_blocked = circ->streams_blocked_on_n_chan;
} else {
@@ -2618,7 +2716,8 @@ append_cell_to_circuit_queue(circuit_t *circ, channel_t *chan,
}
#endif
- cell_queue_append_packed_copy(queue, cell, chan->wide_circ_ids, 1);
+ cell_queue_append_packed_copy(circ, queue, exitward, cell,
+ chan->wide_circ_ids, 1);
if (PREDICT_UNLIKELY(cell_queues_check_size())) {
/* We ran the OOM handler */