aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRoger Dingledine <arma@torproject.org>2013-09-03 20:40:16 -0400
committerRoger Dingledine <arma@torproject.org>2013-09-04 23:21:45 -0400
commit7acc7c3dc6299438f7d5e6ebc6cb64f2ea3b5fa6 (patch)
treee7d72868eb1890ab1fd189f56f243d9c896dc8f5
parent16b5c609a4a4e9d6c25767cebb434746228de210 (diff)
downloadtor-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.c43
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 */