summaryrefslogtreecommitdiff
path: root/src/or/relay.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/or/relay.c')
-rw-r--r--src/or/relay.c94
1 files changed, 72 insertions, 22 deletions
diff --git a/src/or/relay.c b/src/or/relay.c
index 76577848f3..c81b8311a0 100644
--- a/src/or/relay.c
+++ b/src/or/relay.c
@@ -533,13 +533,11 @@ relay_send_command_from_edge(uint16_t stream_id, circuit_t *circ,
log_debug(LD_OR,"delivering %d cell %s.", relay_command,
cell_direction == CELL_DIRECTION_OUT ? "forward" : "backward");
-#ifdef ENABLE_DIRREQ_STATS
/* If we are sending an END cell and this circuit is used for a tunneled
* directory request, advance its state. */
if (relay_command == RELAY_COMMAND_END && circ->dirreq_id)
geoip_change_dirreq_state(circ->dirreq_id, DIRREQ_TUNNELED,
DIRREQ_END_CELL_SENT);
-#endif
if (cell_direction == CELL_DIRECTION_OUT && circ->n_conn) {
/* if we're using relaybandwidthrate, this conn wants priority */
@@ -1047,7 +1045,6 @@ connection_edge_process_relay_cell(cell_t *cell, circuit_t *circ,
"Begin cell for known stream. Dropping.");
return 0;
}
-#ifdef ENABLE_DIRREQ_STATS
if (rh.command == RELAY_COMMAND_BEGIN_DIR) {
/* Assign this circuit and its app-ward OR connection a unique ID,
* so that we can measure download times. The local edge and dir
@@ -1057,7 +1054,6 @@ connection_edge_process_relay_cell(cell_t *cell, circuit_t *circ,
circ->dirreq_id = ++next_id;
TO_CONN(TO_OR_CIRCUIT(circ)->p_conn)->dirreq_id = circ->dirreq_id;
}
-#endif
return connection_exit_begin_conn(cell, circ);
case RELAY_COMMAND_DATA:
@@ -1529,6 +1525,10 @@ static int total_cells_allocated = 0;
/** A memory pool to allocate packed_cell_t objects. */
static mp_pool_t *cell_pool = NULL;
+/** Memory pool to allocate insertion_time_elem_t objects used for cell
+ * statistics. */
+static mp_pool_t *it_pool = NULL;
+
/** Allocate structures to hold cells. */
void
init_cell_pool(void)
@@ -1537,7 +1537,8 @@ init_cell_pool(void)
cell_pool = mp_pool_new(sizeof(packed_cell_t), 128*1024);
}
-/** Free all storage used to hold cells. */
+/** Free all storage used to hold cells (and insertion times if we measure
+ * cell statistics). */
void
free_cell_pool(void)
{
@@ -1546,6 +1547,10 @@ free_cell_pool(void)
mp_pool_destroy(cell_pool);
cell_pool = NULL;
}
+ if (it_pool) {
+ mp_pool_destroy(it_pool);
+ it_pool = NULL;
+ }
}
/** Free excess storage in cell pool. */
@@ -1621,11 +1626,35 @@ void
cell_queue_append_packed_copy(cell_queue_t *queue, const cell_t *cell)
{
packed_cell_t *copy = packed_cell_copy(cell);
-#ifdef ENABLE_BUFFER_STATS
- /* Remember the exact time when this cell was put in the queue. */
- if (get_options()->CellStatistics)
- tor_gettimeofday(&copy->packed_timeval);
-#endif
+ /* Remember the time when this cell was put in the queue. */
+ if (get_options()->CellStatistics) {
+ struct timeval now;
+ uint32_t added;
+ insertion_time_queue_t *it_queue = queue->insertion_times;
+ if (!it_pool)
+ it_pool = mp_pool_new(sizeof(insertion_time_elem_t), 1024);
+ tor_gettimeofday(&now);
+#define SECONDS_IN_A_DAY 86400L
+ added = (now.tv_sec % SECONDS_IN_A_DAY) * 100L + now.tv_usec / 10000L;
+ if (!it_queue) {
+ it_queue = tor_malloc_zero(sizeof(insertion_time_queue_t));
+ queue->insertion_times = it_queue;
+ }
+ if (it_queue->last && it_queue->last->insertion_time == added) {
+ it_queue->last->counter++;
+ } else {
+ insertion_time_elem_t *elem = mp_pool_get(it_pool);
+ elem->next = NULL;
+ elem->insertion_time = added;
+ elem->counter = 1;
+ if (it_queue->last) {
+ it_queue->last->next = elem;
+ it_queue->last = elem;
+ } else {
+ it_queue->first = it_queue->last = elem;
+ }
+ }
+ }
cell_queue_append(queue, copy);
}
@@ -1642,6 +1671,14 @@ cell_queue_clear(cell_queue_t *queue)
}
queue->head = queue->tail = NULL;
queue->n = 0;
+ if (queue->insertion_times) {
+ while (queue->insertion_times->first) {
+ insertion_time_elem_t *elem = queue->insertion_times->first;
+ queue->insertion_times->first = elem->next;
+ mp_pool_release(elem);
+ }
+ tor_free(queue->insertion_times);
+ }
}
/** Extract and return the cell at the head of <b>queue</b>; return NULL if
@@ -1835,28 +1872,41 @@ connection_or_flush_from_first_active_circuit(or_connection_t *conn, int max,
packed_cell_t *cell = cell_queue_pop(queue);
tor_assert(*next_circ_on_conn_p(circ,conn));
-#ifdef ENABLE_BUFFER_STATS
/* Calculate the exact time that this cell has spent in the queue. */
if (get_options()->CellStatistics && !CIRCUIT_IS_ORIGIN(circ)) {
- struct timeval flushed_from_queue;
+ struct timeval now;
+ uint32_t flushed;
uint32_t cell_waiting_time;
- or_circuit_t *orcirc = TO_OR_CIRCUIT(circ);
- tor_gettimeofday(&flushed_from_queue);
- cell_waiting_time = (uint32_t)
- tv_mdiff(&cell->packed_timeval, &flushed_from_queue);
-
- orcirc->total_cell_waiting_time += cell_waiting_time;
- orcirc->processed_cells++;
+ insertion_time_queue_t *it_queue = queue->insertion_times;
+ tor_gettimeofday(&now);
+ flushed = (now.tv_sec % SECONDS_IN_A_DAY) * 100L +
+ now.tv_usec / 10000L;
+ if (!it_queue || !it_queue->first) {
+ log_warn(LD_BUG, "Cannot determine insertion time of cell.");
+ } else {
+ or_circuit_t *orcirc = TO_OR_CIRCUIT(circ);
+ insertion_time_elem_t *elem = it_queue->first;
+ cell_waiting_time = (flushed * 10L + SECONDS_IN_A_DAY * 1000L -
+ elem->insertion_time * 10L) % (SECONDS_IN_A_DAY * 1000L);
+#undef SECONDS_IN_A_DAY
+ elem->counter--;
+ if (elem->counter < 1) {
+ it_queue->first = elem->next;
+ if (elem == it_queue->last)
+ it_queue->last = NULL;
+ mp_pool_release(elem);
+ }
+ orcirc->total_cell_waiting_time += cell_waiting_time;
+ orcirc->processed_cells++;
+ }
}
-#endif
-#ifdef ENABLE_DIRREQ_STATS
+
/* If we just flushed our queue and this circuit is used for a
* tunneled directory request, possibly advance its state. */
if (queue->n == 0 && TO_CONN(conn)->dirreq_id)
geoip_change_dirreq_state(TO_CONN(conn)->dirreq_id,
DIRREQ_TUNNELED,
DIRREQ_CIRC_QUEUE_FLUSHED);
-#endif
connection_write_to_buf(cell->body, CELL_NETWORK_SIZE, TO_CONN(conn));