diff options
author | Roger Dingledine <arma@torproject.org> | 2013-09-03 20:40:16 -0400 |
---|---|---|
committer | Roger Dingledine <arma@torproject.org> | 2013-09-04 23:21:45 -0400 |
commit | 7acc7c3dc6299438f7d5e6ebc6cb64f2ea3b5fa6 (patch) | |
tree | e7d72868eb1890ab1fd189f56f243d9c896dc8f5 | |
parent | 16b5c609a4a4e9d6c25767cebb434746228de210 (diff) | |
download | tor-7acc7c3dc6299438f7d5e6ebc6cb64f2ea3b5fa6.tar tor-7acc7c3dc6299438f7d5e6ebc6cb64f2ea3b5fa6.tar.gz |
do a lopsided round-robin between the onion queues
that way tap won't starve entirely, but we'll still handle ntor requests
quicker.
-rw-r--r-- | src/or/onion.c | 43 |
1 files changed, 38 insertions, 5 deletions
diff --git a/src/or/onion.c b/src/or/onion.c index 0b0489104..639481bfe 100644 --- a/src/or/onion.c +++ b/src/or/onion.c @@ -165,6 +165,42 @@ onion_pending_add(or_circuit_t *circ, create_cell_t *onionskin) return 0; } +/** Return a fairness parameter, to prefer processing NTOR style + * handshakes but still slowly drain the TAP queue so we don't starve + * it entirely. */ +static int +num_ntors_per_tap(void) +{ +#define NUM_NTORS_PER_TAP 5 + return NUM_NTORS_PER_TAP; +} + +/** Choose which onion queue we'll pull from next. If one is empty choose + * the other; if they both have elements, load balance across them but + * favoring NTOR. */ +static uint16_t +decide_next_handshake_type(void) +{ + /* The number of times we've chosen ntor lately when both were available. */ + static int recently_chosen_ntors = 0; + + if (!ol_entries[ONION_HANDSHAKE_TYPE_NTOR]) + return ONION_HANDSHAKE_TYPE_TAP; /* no ntors? try tap */ + + if (!ol_entries[ONION_HANDSHAKE_TYPE_TAP]) + return ONION_HANDSHAKE_TYPE_NTOR; /* no taps? try ntor */ + + /* They both have something queued. Pick ntor if we haven't done that + * too much lately. */ + if (++recently_chosen_ntors <= num_ntors_per_tap()) { + return ONION_HANDSHAKE_TYPE_NTOR; + } + + /* Else, it's time to let tap have its turn. */ + recently_chosen_ntors = 0; + return ONION_HANDSHAKE_TYPE_TAP; +} + /** Remove the highest priority item from ol_list[] and return it, or * return NULL if the lists are empty. */ @@ -172,11 +208,8 @@ or_circuit_t * onion_next_task(create_cell_t **onionskin_out) { or_circuit_t *circ; - - /* 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]); + uint16_t handshake_to_choose = decide_next_handshake_type(); + onion_queue_t *head = TOR_TAILQ_FIRST(&ol_list[handshake_to_choose]); if (!head) return NULL; /* no onions pending, we're done */ |