diff options
Diffstat (limited to 'src/or/relay.c')
-rw-r--r-- | src/or/relay.c | 121 |
1 files changed, 110 insertions, 11 deletions
diff --git a/src/or/relay.c b/src/or/relay.c index d12850d183..7947ca373a 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 */ |