[Author Prev][Author Next][Thread Prev][Thread Next][Author Index][Thread Index]

[tor-commits] [tor] 16/20: Prop#329 Pool: Handle pre-building and using conflux sets.



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

ahf pushed a commit to branch main
in repository tor.

commit 39c2927d6fffc391bcd724bfddf8b90ac765e145
Author: David Goulet <dgoulet@xxxxxxxxxxxxxx>
AuthorDate: Thu Mar 30 19:42:27 2023 +0000

    Prop#329 Pool: Handle pre-building and using conflux sets.
    
    Signed-off-by: David Goulet <dgoulet@xxxxxxxxxxxxxx>
---
 src/core/or/circuituse.c   |  17 +++++-
 src/core/or/circuituse.h   |   6 +++
 src/core/or/conflux_pool.c | 131 +++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 152 insertions(+), 2 deletions(-)

diff --git a/src/core/or/circuituse.c b/src/core/or/circuituse.c
index 7ea9cddbd9..b10c140253 100644
--- a/src/core/or/circuituse.c
+++ b/src/core/or/circuituse.c
@@ -103,7 +103,7 @@ circuit_matches_with_rend_stream(const edge_connection_t *edge_conn,
 /** Return 1 if <b>circ</b> could be returned by circuit_get_best().
  * Else return 0.
  */
-static int
+int
 circuit_is_acceptable(const origin_circuit_t *origin_circ,
                       const entry_connection_t *conn,
                       int must_be_open, uint8_t purpose,
@@ -338,6 +338,7 @@ circuit_get_best(const entry_connection_t *conn,
 {
   origin_circuit_t *best=NULL;
   struct timeval now;
+  time_t now_sec;
 
   tor_assert(conn);
 
@@ -349,6 +350,14 @@ circuit_get_best(const entry_connection_t *conn,
              purpose == CIRCUIT_PURPOSE_C_REND_JOINED);
 
   tor_gettimeofday(&now);
+  now_sec = now.tv_sec;
+
+  // Prefer pre-built conflux circuits here, if available but only for general
+  // purposes. We don't have onion service conflux support at the moment.
+  if (purpose == CIRCUIT_PURPOSE_C_GENERAL &&
+      (best = conflux_get_circ_for_conn(conn, now_sec))) {
+    return best;
+  }
 
   SMARTLIST_FOREACH_BEGIN(circuit_get_global_list(), circuit_t *, circ) {
     origin_circuit_t *origin_circ;
@@ -357,7 +366,7 @@ circuit_get_best(const entry_connection_t *conn,
     origin_circ = TO_ORIGIN_CIRCUIT(circ);
 
     if (!circuit_is_acceptable(origin_circ,conn,must_be_open,purpose,
-                               need_uptime,need_internal, (time_t)now.tv_sec))
+                               need_uptime,need_internal, now_sec))
       continue;
 
     /* now this is an acceptable circ to hand back. but that doesn't
@@ -1192,6 +1201,10 @@ circuit_predict_and_launch_new(void)
   time_t now = time(NULL);
   int flags = 0;
 
+  /* Attempt to launch predicted conflux circuits. This is outside the HS or
+   * Exit preemptive circuit set. */
+  conflux_predict_new(now);
+
   /* Count how many of each type of circuit we currently have. */
   SMARTLIST_FOREACH_BEGIN(circuit_get_global_list(), circuit_t *, circ) {
     if (!circuit_is_available_for_use(circ))
diff --git a/src/core/or/circuituse.h b/src/core/or/circuituse.h
index cda6d7ee2e..aa572f3212 100644
--- a/src/core/or/circuituse.h
+++ b/src/core/or/circuituse.h
@@ -79,6 +79,12 @@ bool circuit_purpose_is_hs_service(const uint8_t purpose);
 bool circuit_purpose_is_hs_vanguards(const uint8_t purpose);
 
 bool circuit_is_hs_v3(const circuit_t *circ);
+int circuit_is_acceptable(const origin_circuit_t *origin_circ,
+                          const entry_connection_t *conn,
+                          int must_be_open, uint8_t purpose,
+                          int need_uptime, int need_internal,
+                          time_t now);
+
 int circuit_should_use_vanguards(uint8_t);
 void circuit_sent_valid_data(origin_circuit_t *circ, uint16_t relay_body_len);
 void circuit_read_valid_data(origin_circuit_t *circ, uint16_t relay_body_len);
diff --git a/src/core/or/conflux_pool.c b/src/core/or/conflux_pool.c
index c1b522fa67..b9da1fe75a 100644
--- a/src/core/or/conflux_pool.c
+++ b/src/core/or/conflux_pool.c
@@ -916,6 +916,32 @@ link_circuit(circuit_t *circ)
   return err;
 }
 
+/** Launch a brand new set.
+ *
+ * Return true if all legs successfully launched or false if one failed. */
+STATIC bool
+launch_new_set(int num_legs)
+{
+  uint8_t nonce[DIGEST256_LEN];
+
+  /* Brand new nonce for this set. */
+  crypto_rand((char *) nonce, sizeof(nonce));
+
+  /* Launch all legs. */
+  for (int i = 0; i < num_legs; i++) {
+    if (!conflux_launch_leg(nonce)) {
+      /* This function cleans up entirely the unlinked set if a leg is unable
+       * to be launched. The recovery would be complex here. */
+      goto err;
+    }
+  }
+
+  return true;
+
+ err:
+  return false;
+}
+
 static unlinked_circuits_t *
 unlinked_get_or_create(const uint8_t *nonce, bool is_client)
 {
@@ -1215,6 +1241,111 @@ conflux_add_middles_to_exclude_list(const origin_circuit_t *orig_circ,
   }
 }
 
+/** Return the number of unused client linked set. */
+static int
+count_client_usable_sets(void)
+{
+  int count = 0;
+
+  DIGEST256MAP_FOREACH(client_linked_pool, key, conflux_t *, cfx) {
+    conflux_leg_t *leg = smartlist_get(cfx->legs, 0);
+    if (BUG(!leg->circ)) {
+      log_warn(LD_BUG, "Client conflux linked set leg without a circuit");
+      continue;
+    }
+    if (!CONST_TO_ORIGIN_CIRCUIT(leg->circ)->unusable_for_new_conns) {
+      count++;
+    }
+  } DIGEST256MAP_FOREACH_END;
+
+  return count;
+}
+
+/** Determine if we need to launch new conflux circuits for our preemptive
+ * pool.
+ *
+ * This is called once a second from the mainloop from
+ * circuit_predict_and_launch_new(). */
+void
+conflux_predict_new(time_t now)
+{
+  (void) now;
+
+  if (!conflux_is_enabled(NULL)) {
+    return;
+  }
+
+  /* Don't attempt to build a new set if we are above our allowed maximum of
+   * linked sets. */
+  if (digest256map_size(client_linked_pool) >=
+      conflux_params_get_max_linked_set()) {
+    return;
+  }
+
+  /* Count the linked and unlinked to get the total number of sets we have
+   * (will have). */
+  int num_linked = count_client_usable_sets();
+  int num_unlinked = digest256map_size(client_unlinked_pool);
+  int num_set = num_unlinked + num_linked;
+  int max_prebuilt = conflux_params_get_max_prebuilt();
+
+  if (num_set >= max_prebuilt) {
+    return;
+  }
+
+  log_info(LD_CIRC, "Preemptively launching new conflux circuit set(s). "
+                    "We have %d linked and %d unlinked.",
+           num_linked, num_unlinked);
+
+  for (int i = 0; i < (max_prebuilt - num_set); i++) {
+    if (!launch_new_set(conflux_params_get_num_legs_set())) {
+      /* Failing once likely means we'll fail next attempt so stop for now and
+       * we'll try later. */
+      break;
+    }
+  }
+}
+
+/** Return the first circuit from the linked pool that will work with the conn.
+ * If no such circuit exists, return NULL. */
+origin_circuit_t *
+conflux_get_circ_for_conn(const entry_connection_t *conn, time_t now)
+{
+  /* Use conn to check the exit policy of the first circuit
+   * of each set in the linked pool. */
+  tor_assert(conn);
+
+  DIGEST256MAP_FOREACH(client_linked_pool, key, conflux_t *, cfx) {
+    /* Get the first circuit of the set. */
+    conflux_leg_t *leg = smartlist_get(cfx->legs, 0);
+    tor_assert(leg);
+    tor_assert(leg->circ);
+
+    /* Bug on these but we can recover. */
+    if (BUG(leg->circ->purpose != CIRCUIT_PURPOSE_CONFLUX_LINKED)) {
+      continue;
+    }
+    if (BUG(!CIRCUIT_IS_ORIGIN(leg->circ))) {
+      continue;
+    }
+    origin_circuit_t *ocirc = TO_ORIGIN_CIRCUIT(leg->circ);
+
+    /* Make sure the connection conforms with the exit policy and the isolation
+     * flags also allows it. */
+    if (!circuit_is_acceptable(ocirc, conn, 1 /* Must be open */,
+                               CIRCUIT_PURPOSE_CONFLUX_LINKED,
+                               1 /* Need uptime */,
+                               0 /* No need for internal */, now)) {
+      continue;
+    }
+
+    /* Found a circuit that works. */
+    return ocirc;
+  } DIGEST256MAP_FOREACH_END;
+
+  return NULL;
+}
+
 /** The given circuit is conflux pending and has closed. This deletes the leg
  * from the set, attempt to finalize it and relaunch a new leg. If the set is
  * empty after removing this leg, it is deleted. */

-- 
To stop receiving notification emails like this one, please contact
the administrator of this repository.
_______________________________________________
tor-commits mailing list
tor-commits@xxxxxxxxxxxxxxxxxxxx
https://lists.torproject.org/cgi-bin/mailman/listinfo/tor-commits