[tor-commits] [tor] 04/05: relay: Cache onion queue parameters on consensus change

gitolite role git at cupani.torproject.org
Wed Nov 9 20:30:20 UTC 2022


This is an automated email from the git hooks/post-receive script.

dgoulet pushed a commit to branch main
in repository tor.

commit 780ca741f3738877ad577f84fcebf6874427b2bc
Author: David Goulet <dgoulet at torproject.org>
AuthorDate: Wed Nov 9 15:10:19 2022 -0500

    relay: Cache onion queue parameters on consensus change
    
    This is part of the fast path so we need to cache consensus parameters
    instead of querying it everytime we need to learn a value.
    
    Part of #40704
    
    Signed-off-by: David Goulet <dgoulet at torproject.org>
---
 src/feature/nodelist/networkstatus.c |   2 +
 src/feature/relay/onion_queue.c      | 115 ++++++++++++++++++++---------------
 src/feature/relay/onion_queue.h      |   2 +
 3 files changed, 71 insertions(+), 48 deletions(-)

diff --git a/src/feature/nodelist/networkstatus.c b/src/feature/nodelist/networkstatus.c
index fa1e38dac0..af3bde83a5 100644
--- a/src/feature/nodelist/networkstatus.c
+++ b/src/feature/nodelist/networkstatus.c
@@ -84,6 +84,7 @@
 #include "feature/nodelist/routerlist.h"
 #include "feature/nodelist/torcert.h"
 #include "feature/relay/dns.h"
+#include "feature/relay/onion_queue.h"
 #include "feature/relay/routermode.h"
 #include "lib/crypt_ops/crypto_rand.h"
 #include "lib/crypt_ops/crypto_util.h"
@@ -1670,6 +1671,7 @@ notify_before_networkstatus_changes(const networkstatus_t *old_c,
   hs_dos_consensus_has_changed(new_c);
   rep_hist_consensus_has_changed(new_c);
   cpuworker_consensus_has_changed(new_c);
+  onion_consensus_has_changed(new_c);
 }
 
 /* Called after a new consensus has been put in the global state. It is safe
diff --git a/src/feature/relay/onion_queue.c b/src/feature/relay/onion_queue.c
index 5897ee8a48..6d1a6de15c 100644
--- a/src/feature/relay/onion_queue.c
+++ b/src/feature/relay/onion_queue.c
@@ -38,6 +38,22 @@
 #include "core/or/or_circuit_st.h"
 #include "core/or/channel.h"
 
+/** Onion queue default, max and min. */
+
+/* In seconds. */
+#define ONION_QUEUE_WAIT_CUTOFF_DEFAULT 5
+#define ONION_QUEUE_WAIT_CUTOFF_MIN 0
+#define ONION_QUEUE_WAIT_CUTOFF_MAX INT32_MAX
+
+/* In msec. */
+#define ONION_QUEUE_MAX_DELAY_DEFAULT 1750
+#define ONION_QUEUE_MAX_DELAY_MIN 1
+#define ONION_QUEUE_MAX_DELAY_MAX INT32_MAX
+
+#define NUM_NTORS_PER_TAP_DEFAULT 10
+#define NUM_NTORS_PER_TAP_MIN 1
+#define NUM_NTORS_PER_TAP_MAX 100000
+
 /** Type for a linked list of circuits that are waiting for a free CPU worker
  * to process a waiting onion handshake. */
 typedef struct onion_queue_t {
@@ -65,40 +81,36 @@ static onion_queue_head_t ol_list[MAX_QUEUE_IDX+1] =
 /** Number of entries of each type currently in each element of ol_list[]. */
 static int ol_entries[MAX_QUEUE_IDX+1];
 
-static int num_ntors_per_tap(void);
 static void onion_queue_entry_remove(onion_queue_t *victim);
 
-/** Return the onion queue wait cutoff value from the consensus parameter. */
-static time_t
-get_onionqueue_wait_cutoff(void)
+/** Consensus parameters. */
+static int32_t ns_num_ntors_per_tap = NUM_NTORS_PER_TAP_DEFAULT;
+static time_t ns_onion_queue_wait_cutoff = ONION_QUEUE_WAIT_CUTOFF_DEFAULT;
+static uint32_t ns_onion_queue_max_delay = ONION_QUEUE_MAX_DELAY_DEFAULT;
+
+/** Return the number of ntors per tap from the cached parameter. */
+static inline int32_t
+get_num_ntors_per_tap(void)
 {
-/* In seconds. */
-#define ONION_QUEUE_WAIT_CUTOFF_DEFAULT 5
-#define ONION_QUEUE_WAIT_CUTOFF_MIN 0
-#define ONION_QUEUE_WAIT_CUTOFF_MAX INT32_MAX
-  return networkstatus_get_param(NULL, "onion_queue_wait_cutoff",
-                                 ONION_QUEUE_WAIT_CUTOFF_DEFAULT,
-                                 ONION_QUEUE_WAIT_CUTOFF_MIN,
-                                 ONION_QUEUE_WAIT_CUTOFF_MAX);
+  return ns_num_ntors_per_tap;
 }
 
-/** Return the max onion queue delay value either from the torrc options (if
- * the user explicitly set it) else from the consensus parameter. */
-static uint64_t
-get_max_onion_queue_delay(const or_options_t *options)
+/** Return the onion queue wait cutoff value from the cached parameter. */
+static inline time_t
+get_onion_queue_wait_cutoff(void)
 {
-#define MAX_ONION_QUEUE_DELAY_DEFAULT 1750 /* msec */
-#define MAX_ONION_QUEUE_DELAY_MIN 1 /* msec */
-#define MAX_ONION_QUEUE_DELAY_MAX INT32_MAX /* msec */
+  return ns_onion_queue_wait_cutoff;
+}
 
+/** Return the max onion queue delay value either from the torrc options (if
+ * the user explicitly set it) else from the cached parameter. */
+static inline uint32_t
+get_onion_queue_max_delay(const or_options_t *options)
+{
   if (options && options->MaxOnionQueueDelay > 0) {
     return options->MaxOnionQueueDelay;
   }
-
-  return networkstatus_get_param(NULL, "MaxOnionQueueDelay",
-                                 MAX_ONION_QUEUE_DELAY_DEFAULT,
-                                 MAX_ONION_QUEUE_DELAY_MIN,
-                                 MAX_ONION_QUEUE_DELAY_MAX);
+  return ns_onion_queue_max_delay;
 }
 
 /**
@@ -141,7 +153,7 @@ have_room_for_onionskin(uint16_t type)
   if (ol_entries[type] < 50)
     return 1;
   num_cpus = get_num_cpus(options);
-  max_onion_queue_delay = get_max_onion_queue_delay(options);
+  max_onion_queue_delay = get_onion_queue_max_delay(options);
 
   /* Compute how many microseconds we'd expect to need to clear all
    * onionskins in various combinations of the queues. */
@@ -160,14 +172,14 @@ have_room_for_onionskin(uint16_t type)
    * process while draining the ntor queue? */
   tap_during_ntor_usec  = estimated_usec_for_onionskins(
     MIN(ol_entries[ONION_HANDSHAKE_TYPE_TAP],
-        ol_entries[ONION_HANDSHAKE_TYPE_NTOR] / num_ntors_per_tap()),
+        ol_entries[ONION_HANDSHAKE_TYPE_NTOR] / get_num_ntors_per_tap()),
                                     ONION_HANDSHAKE_TYPE_TAP) / num_cpus;
 
   /* How long would it take to process the ntor cells that we expect to
    * process while draining the tap queue? */
   ntor_during_tap_usec  = estimated_usec_for_onionskins(
     MIN(ol_entries[ONION_HANDSHAKE_TYPE_NTOR],
-        ol_entries[ONION_HANDSHAKE_TYPE_TAP] * num_ntors_per_tap()),
+        ol_entries[ONION_HANDSHAKE_TYPE_TAP] * get_num_ntors_per_tap()),
                                     ONION_HANDSHAKE_TYPE_NTOR) / num_cpus;
 
   /* See whether that exceeds MaxOnionQueueDelay. If so, we can't queue
@@ -253,7 +265,7 @@ onion_pending_add(or_circuit_t *circ, create_cell_t *onionskin)
   /* cull elderly requests. */
   while (1) {
     onion_queue_t *head = TOR_TAILQ_FIRST(&ol_list[queue_idx]);
-    if (now - head->when_added < get_onionqueue_wait_cutoff())
+    if (now - head->when_added < get_onion_queue_wait_cutoff())
       break;
 
     circ = head->circ;
@@ -268,24 +280,6 @@ 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 DEFAULT_NUM_NTORS_PER_TAP 10
-#define MIN_NUM_NTORS_PER_TAP 1
-#define MAX_NUM_NTORS_PER_TAP 100000
-
-  int result = networkstatus_get_param(NULL, "NumNTorsPerTAP",
-                                       DEFAULT_NUM_NTORS_PER_TAP,
-                                       MIN_NUM_NTORS_PER_TAP,
-                                       MAX_NUM_NTORS_PER_TAP);
-  tor_assert(result > 0);
-  return result;
-}
-
 /** 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. */
@@ -309,7 +303,7 @@ decide_next_handshake_type(void)
      * once tap is rare. We should reevaluate whether we like this decision
      * once tap gets more rare. */
     if (ol_entries[ONION_HANDSHAKE_TYPE_NTOR] &&
-        recently_chosen_ntors <= num_ntors_per_tap())
+        recently_chosen_ntors <= get_num_ntors_per_tap())
       ++recently_chosen_ntors;
 
     return ONION_HANDSHAKE_TYPE_NTOR; /* no taps? try ntor */
@@ -317,7 +311,7 @@ decide_next_handshake_type(void)
 
   /* They both have something queued. Pick ntor if we haven't done that
    * too much lately. */
-  if (++recently_chosen_ntors <= num_ntors_per_tap()) {
+  if (++recently_chosen_ntors <= get_num_ntors_per_tap()) {
     return ONION_HANDSHAKE_TYPE_NTOR;
   }
 
@@ -427,3 +421,28 @@ clear_pending_onions(void)
   }
   memset(ol_entries, 0, sizeof(ol_entries));
 }
+
+/** Consensus has changed, update the cached parameters. */
+void
+onion_consensus_has_changed(const networkstatus_t *ns)
+{
+  tor_assert(ns);
+
+  ns_onion_queue_max_delay =
+    networkstatus_get_param(ns, "MaxOnionQueueDelay",
+                            ONION_QUEUE_MAX_DELAY_DEFAULT,
+                            ONION_QUEUE_MAX_DELAY_MIN,
+                            ONION_QUEUE_MAX_DELAY_MAX);
+
+  ns_onion_queue_wait_cutoff =
+    networkstatus_get_param(ns, "onion_queue_wait_cutoff",
+                            ONION_QUEUE_WAIT_CUTOFF_DEFAULT,
+                            ONION_QUEUE_WAIT_CUTOFF_MIN,
+                            ONION_QUEUE_WAIT_CUTOFF_MAX);
+
+  ns_num_ntors_per_tap =
+    networkstatus_get_param(ns, "NumNTorsPerTAP",
+                            NUM_NTORS_PER_TAP_DEFAULT,
+                            NUM_NTORS_PER_TAP_MIN,
+                            NUM_NTORS_PER_TAP_MAX);
+}
diff --git a/src/feature/relay/onion_queue.h b/src/feature/relay/onion_queue.h
index 5ac1b1b280..0c2b97c2b0 100644
--- a/src/feature/relay/onion_queue.h
+++ b/src/feature/relay/onion_queue.h
@@ -14,6 +14,8 @@
 
 struct create_cell_t;
 
+void onion_consensus_has_changed(const networkstatus_t *ns);
+
 int onion_pending_add(or_circuit_t *circ, struct create_cell_t *onionskin);
 or_circuit_t *onion_next_task(struct create_cell_t **onionskin_out);
 int onion_num_pending(uint16_t handshake_type);

-- 
To stop receiving notification emails like this one, please contact
the administrator of this repository.


More information about the tor-commits mailing list