mirror of
https://gitlab.torproject.org/tpo/core/tor.git
synced 2025-02-24 22:58:50 +01:00
Separate cpuworker queues by handshake type
Now we prioritize ntor create cells over tap create cells. Starts to address ticket 9574.
This commit is contained in:
parent
a60d21a85d
commit
87a18514ef
1 changed files with 37 additions and 16 deletions
|
@ -28,6 +28,7 @@
|
|||
typedef struct onion_queue_t {
|
||||
TOR_TAILQ_ENTRY(onion_queue_t) next;
|
||||
or_circuit_t *circ;
|
||||
uint16_t handshake_type;
|
||||
create_cell_t *onionskin;
|
||||
time_t when_added;
|
||||
} onion_queue_t;
|
||||
|
@ -35,11 +36,16 @@ typedef struct onion_queue_t {
|
|||
/** 5 seconds on the onion queue til we just send back a destroy */
|
||||
#define ONIONQUEUE_WAIT_CUTOFF 5
|
||||
|
||||
/** Queue of circuits waiting for CPU workers, or NULL if the list is empty.*/
|
||||
TOR_TAILQ_HEAD(onion_queue_head_t, onion_queue_t) ol_list =
|
||||
TOR_TAILQ_HEAD_INITIALIZER(ol_list);
|
||||
/** Array of queues of circuits waiting for CPU workers. An element is NULL
|
||||
* if that queue is empty.*/
|
||||
TOR_TAILQ_HEAD(onion_queue_head_t, onion_queue_t)
|
||||
ol_list[MAX_ONION_HANDSHAKE_TYPE+1] = {
|
||||
TOR_TAILQ_HEAD_INITIALIZER(ol_list[0]), /* tap */
|
||||
TOR_TAILQ_HEAD_INITIALIZER(ol_list[1]), /* fast */
|
||||
TOR_TAILQ_HEAD_INITIALIZER(ol_list[2]), /* ntor */
|
||||
};
|
||||
|
||||
/** Number of entries of each type currently in ol_list. */
|
||||
/** Number of entries of each type currently in each element of ol_list[]. */
|
||||
static int ol_entries[MAX_ONION_HANDSHAKE_TYPE+1];
|
||||
|
||||
static void onion_queue_entry_remove(onion_queue_t *victim);
|
||||
|
@ -60,8 +66,7 @@ have_room_for_onionskin(uint16_t type)
|
|||
int num_cpus;
|
||||
uint64_t tap_usec, ntor_usec;
|
||||
/* If we've got fewer than 50 entries, we always have room for one more. */
|
||||
if (ol_entries[ONION_HANDSHAKE_TYPE_TAP] +
|
||||
ol_entries[ONION_HANDSHAKE_TYPE_NTOR] < 50)
|
||||
if (ol_entries[type] < 50)
|
||||
return 1;
|
||||
num_cpus = get_num_cpus(options);
|
||||
/* Compute how many microseconds we'd expect to need to clear all
|
||||
|
@ -72,10 +77,17 @@ have_room_for_onionskin(uint16_t type)
|
|||
ntor_usec = estimated_usec_for_onionskins(
|
||||
ol_entries[ONION_HANDSHAKE_TYPE_NTOR],
|
||||
ONION_HANDSHAKE_TYPE_NTOR) / num_cpus;
|
||||
|
||||
/* See whether that exceeds MaxOnionQueueDelay. If so, we can't queue
|
||||
* this. */
|
||||
if ((tap_usec + ntor_usec) / 1000 > (uint64_t)options->MaxOnionQueueDelay)
|
||||
if (type == ONION_HANDSHAKE_TYPE_NTOR &&
|
||||
ntor_usec / 1000 > (uint64_t)options->MaxOnionQueueDelay)
|
||||
return 0;
|
||||
|
||||
if (type == ONION_HANDSHAKE_TYPE_TAP &&
|
||||
(tap_usec + ntor_usec) / 1000 > (uint64_t)options->MaxOnionQueueDelay)
|
||||
return 0;
|
||||
|
||||
#ifdef CURVE25519_ENABLED
|
||||
/* If we support the ntor handshake, then don't let TAP handshakes use
|
||||
* more than 2/3 of the space on the queue. */
|
||||
|
@ -100,6 +112,7 @@ onion_pending_add(or_circuit_t *circ, create_cell_t *onionskin)
|
|||
|
||||
tmp = tor_malloc_zero(sizeof(onion_queue_t));
|
||||
tmp->circ = circ;
|
||||
tmp->handshake_type = onionskin->handshake_type;
|
||||
tmp->onionskin = onionskin;
|
||||
tmp->when_added = now;
|
||||
|
||||
|
@ -108,7 +121,8 @@ onion_pending_add(or_circuit_t *circ, create_cell_t *onionskin)
|
|||
static ratelim_t last_warned =
|
||||
RATELIM_INIT(WARN_TOO_MANY_CIRC_CREATIONS_INTERVAL);
|
||||
char *m;
|
||||
if ((m = rate_limit_log(&last_warned, approx_time()))) {
|
||||
if (onionskin->handshake_type == ONION_HANDSHAKE_TYPE_NTOR &&
|
||||
(m = rate_limit_log(&last_warned, approx_time()))) {
|
||||
log_warn(LD_GENERAL,
|
||||
"Your computer is too slow to handle this many circuit "
|
||||
"creation requests! Please consider using the "
|
||||
|
@ -122,11 +136,11 @@ onion_pending_add(or_circuit_t *circ, create_cell_t *onionskin)
|
|||
|
||||
++ol_entries[onionskin->handshake_type];
|
||||
circ->onionqueue_entry = tmp;
|
||||
TOR_TAILQ_INSERT_TAIL(&ol_list, tmp, next);
|
||||
TOR_TAILQ_INSERT_TAIL(&ol_list[onionskin->handshake_type], tmp, next);
|
||||
|
||||
/* cull elderly requests. */
|
||||
while (1) {
|
||||
onion_queue_t *head = TOR_TAILQ_FIRST(&ol_list);
|
||||
onion_queue_t *head = TOR_TAILQ_FIRST(&ol_list[onionskin->handshake_type]);
|
||||
if (now - head->when_added < (time_t)ONIONQUEUE_WAIT_CUTOFF)
|
||||
break;
|
||||
|
||||
|
@ -140,14 +154,18 @@ onion_pending_add(or_circuit_t *circ, create_cell_t *onionskin)
|
|||
return 0;
|
||||
}
|
||||
|
||||
/** Remove the first item from ol_list and return it, or return
|
||||
* NULL if the list is empty.
|
||||
/** Remove the highest priority item from ol_list[] and return it, or
|
||||
* return NULL if the lists are empty.
|
||||
*/
|
||||
or_circuit_t *
|
||||
onion_next_task(create_cell_t **onionskin_out)
|
||||
{
|
||||
or_circuit_t *circ;
|
||||
onion_queue_t *head = TOR_TAILQ_FIRST(&ol_list);
|
||||
|
||||
/* skip ol_list[ONION_HANDSHAKE_TYPE_FAST] since we know it'll be empty */
|
||||
onion_queue_t *head = TOR_TAILQ_FIRST(&ol_list[ONION_HANDSHAKE_TYPE_NTOR]);
|
||||
if (!head)
|
||||
head = TOR_TAILQ_FIRST(&ol_list[ONION_HANDSHAKE_TYPE_TAP]);
|
||||
|
||||
if (!head)
|
||||
return NULL; /* no onions pending, we're done */
|
||||
|
@ -186,7 +204,7 @@ onion_pending_remove(or_circuit_t *circ)
|
|||
static void
|
||||
onion_queue_entry_remove(onion_queue_t *victim)
|
||||
{
|
||||
TOR_TAILQ_REMOVE(&ol_list, victim, next);
|
||||
TOR_TAILQ_REMOVE(&ol_list[victim->handshake_type], victim, next);
|
||||
|
||||
if (victim->circ)
|
||||
victim->circ->onionqueue_entry = NULL;
|
||||
|
@ -204,8 +222,11 @@ void
|
|||
clear_pending_onions(void)
|
||||
{
|
||||
onion_queue_t *victim;
|
||||
while ((victim = TOR_TAILQ_FIRST(&ol_list))) {
|
||||
onion_queue_entry_remove(victim);
|
||||
int i;
|
||||
for (i=0; i<=MAX_ONION_HANDSHAKE_TYPE; i++) {
|
||||
while ((victim = TOR_TAILQ_FIRST(&ol_list[i]))) {
|
||||
onion_queue_entry_remove(victim);
|
||||
}
|
||||
}
|
||||
memset(ol_entries, 0, sizeof(ol_entries));
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue