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

[or-cvs] [tor/maint-0.2.2 1/2] Only count timeout data for 3 hop circuits.



Author: Mike Perry <mikeperry-git@xxxxxxxxxx>
Date: Wed, 29 Sep 2010 11:41:27 -0700
Subject: Only count timeout data for 3 hop circuits.
Commit: 5aa4564ab940250fd9a8776d7cbfde8ab4f3cd31

Use 4/3 of this timeout value for 4 hop circuits, and use half of it for
canabalized circuits.
---
 src/or/circuitbuild.c |   29 ++++++++++++++++++----
 src/or/circuitbuild.h |    1 +
 src/or/circuituse.c   |   63 +++++++++++++++++++++++++++++++-----------------
 src/or/or.h           |    6 ++++-
 4 files changed, 71 insertions(+), 28 deletions(-)

diff --git a/src/or/circuitbuild.c b/src/or/circuitbuild.c
index 35d8087..be435b9 100644
--- a/src/or/circuitbuild.c
+++ b/src/or/circuitbuild.c
@@ -1197,6 +1197,11 @@ circuit_build_times_count_close(circuit_build_times_t *cbt,
 /**
  * Update timeout counts to determine if we need to expire
  * our build time history due to excessive timeouts.
+ *
+ * We do not record any actual time values at this stage;
+ * we are only interested in recording the fact that a timeout
+ * happened. We record the time values via
+ * circuit_build_times_count_close() and circuit_build_times_add_time().
  */
 void
 circuit_build_times_count_timeout(circuit_build_times_t *cbt,
@@ -1208,11 +1213,11 @@ circuit_build_times_count_timeout(circuit_build_times_t *cbt,
     return;
   }
 
+  /* Register the fact that a timeout just occurred. */
   circuit_build_times_network_timeout(cbt, did_onehop);
 
   /* If there are a ton of timeouts, we should reset
-   * the circuit build timeout.
-   */
+   * the circuit build timeout. */
   circuit_build_times_network_check_changed(cbt);
 }
 
@@ -1816,6 +1821,18 @@ should_use_create_fast_for_circuit(origin_circuit_t *circ)
   return 1;
 }
 
+/** Return true if <b>circ</b> is the type of circuit we want to count
+ * timeouts from. In particular, we want it to have not completed yet
+ * (already completing indicates we cannibalized it), and we want it to
+ * have exactly three hops.
+ */
+int
+circuit_timeout_want_to_count_circ(origin_circuit_t *circ)
+{
+  return !circ->has_opened
+          && circ->build_state->desired_path_len == DEFAULT_ROUTE_LEN;
+}
+
 /** This is the backbone function for building circuits.
  *
  * If circ's first hop is closed, then we need to build a create
@@ -1889,11 +1906,12 @@ circuit_send_next_onion_skin(origin_circuit_t *circ)
     if (!hop) {
       /* done building the circuit. whew. */
       circuit_set_state(TO_CIRCUIT(circ), CIRCUIT_STATE_OPEN);
-      if (!circ->build_state->onehop_tunnel) {
+      if (circuit_timeout_want_to_count_circ(circ)) {
         struct timeval end;
         long timediff;
         tor_gettimeofday(&end);
         timediff = tv_mdiff(&circ->_base.highres_created, &end);
+
         /*
          * If the circuit build time is much greater than we would have cut
          * it off at, we probably had a suspend event along this codepath,
@@ -1901,9 +1919,10 @@ circuit_send_next_onion_skin(origin_circuit_t *circ)
          */
         if (timediff < 0 || timediff > 2*circ_times.close_ms+1000) {
           log_notice(LD_CIRC, "Strange value for circuit build time: %ldmsec. "
-                              "Assuming clock jump.", timediff);
+                              "Assuming clock jump. Purpose %d", timediff,
+                              circ->_base.purpose);
         } else if (!circuit_build_times_disabled()) {
-          /* Don't count circuit times if the network was not live */
+          /* Only count circuit times if the network is live */
           if (circuit_build_times_network_check_live(&circ_times)) {
             circuit_build_times_add_time(&circ_times, (build_time_t)timediff);
             circuit_build_times_set_timeout(&circ_times);
diff --git a/src/or/circuitbuild.h b/src/or/circuitbuild.h
index f4cc2a9..7cc5c28 100644
--- a/src/or/circuitbuild.h
+++ b/src/or/circuitbuild.h
@@ -24,6 +24,7 @@ origin_circuit_t *circuit_establish_circuit(uint8_t purpose,
 int circuit_handle_first_hop(origin_circuit_t *circ);
 void circuit_n_conn_done(or_connection_t *or_conn, int status);
 int inform_testing_reachability(void);
+int circuit_timeout_want_to_count_circ(origin_circuit_t *circ);
 int circuit_send_next_onion_skin(origin_circuit_t *circ);
 void circuit_note_clock_jumped(int seconds_elapsed);
 int circuit_extend(cell_t *cell, circuit_t *circ);
diff --git a/src/or/circuituse.c b/src/or/circuituse.c
index e9335b1..d9c16c1 100644
--- a/src/or/circuituse.c
+++ b/src/or/circuituse.c
@@ -284,6 +284,8 @@ circuit_expire_building(time_t now)
    * decided on a customized one yet */
   time_t general_cutoff = now - lround(circ_times.timeout_ms/1000);
   time_t begindir_cutoff = now - lround(circ_times.timeout_ms/2000);
+  time_t fourhop_cutoff = now - lround(4*circ_times.timeout_ms/3000);
+  time_t cannibalize_cutoff = now - lround(circ_times.timeout_ms/2000);
   time_t close_cutoff = now - lround(circ_times.close_ms/1000);
   time_t introcirc_cutoff = begindir_cutoff;
   cpath_build_state_t *build_state;
@@ -299,6 +301,11 @@ circuit_expire_building(time_t now)
     build_state = TO_ORIGIN_CIRCUIT(victim)->build_state;
     if (build_state && build_state->onehop_tunnel)
       cutoff = begindir_cutoff;
+    else if (build_state && build_state->desired_path_len == 4
+             && !TO_ORIGIN_CIRCUIT(victim)->has_opened)
+      cutoff = fourhop_cutoff;
+    else if (TO_ORIGIN_CIRCUIT(victim)->has_opened)
+      cutoff = cannibalize_cutoff;
     else if (victim->purpose == CIRCUIT_PURPOSE_C_INTRODUCING)
       cutoff = introcirc_cutoff;
     else if (victim->purpose == CIRCUIT_PURPOSE_C_MEASURE_TIMEOUT)
@@ -378,29 +385,36 @@ circuit_expire_building(time_t now)
         continue;
       }
 
-      /* circuits are allowed to last longer for measurement.
-       * Switch their purpose and wait. */
-      if (victim->purpose != CIRCUIT_PURPOSE_C_MEASURE_TIMEOUT) {
-        victim->purpose = CIRCUIT_PURPOSE_C_MEASURE_TIMEOUT;
-        circuit_build_times_count_timeout(&circ_times,
-                                          first_hop_succeeded);
-        continue;
-      }
+      if (circuit_timeout_want_to_count_circ(TO_ORIGIN_CIRCUIT(victim))) {
+        /* Circuits are allowed to last longer for measurement.
+         * Switch their purpose and wait. */
+        if (victim->purpose != CIRCUIT_PURPOSE_C_MEASURE_TIMEOUT) {
+          victim->purpose = CIRCUIT_PURPOSE_C_MEASURE_TIMEOUT;
+          /* Record this failure to check for too many timeouts
+           * in a row. This function does not record a time value yet
+           * (we do that later); it only counts the fact that we did
+           * have a timeout. */
+          circuit_build_times_count_timeout(&circ_times,
+                                            first_hop_succeeded);
+          continue;
+        }
 
-      /*
-       * If the circuit build time is much greater than we would have cut
-       * it off at, we probably had a suspend event along this codepath,
-       * and we should discard the value.
-       */
-      if (now - victim->timestamp_created > 2*circ_times.close_ms/1000+1) {
-        log_notice(LD_CIRC,
-                   "Extremely large value for circuit build timeout: %lds. "
-                   "Assuming clock jump.",
-                   (long)(now - victim->timestamp_created));
-      } else if (circuit_build_times_count_close(&circ_times,
-                                          first_hop_succeeded,
-                                          victim->timestamp_created)) {
-        circuit_build_times_set_timeout(&circ_times);
+        /*
+         * If the circuit build time is much greater than we would have cut
+         * it off at, we probably had a suspend event along this codepath,
+         * and we should discard the value.
+         */
+        if (now - victim->timestamp_created > 2*circ_times.close_ms/1000+1) {
+          log_notice(LD_CIRC,
+                     "Extremely large value for circuit build timeout: %lds. "
+                     "Assuming clock jump. Purpose %d",
+                     (long)(now - victim->timestamp_created),
+                      victim->purpose);
+        } else if (circuit_build_times_count_close(&circ_times,
+                                            first_hop_succeeded,
+                                            victim->timestamp_created)) {
+          circuit_build_times_set_timeout(&circ_times);
+        }
       }
     }
 
@@ -903,6 +917,11 @@ circuit_has_opened(origin_circuit_t *circ)
 {
   control_event_circuit_status(circ, CIRC_EVENT_BUILT, 0);
 
+  /* Remember that this circuit has finished building. Now if we start
+   * it building again later (e.g. by extending it), we will know not
+   * to consider its build time. */
+  circ->has_opened = 1;
+
   switch (TO_CIRCUIT(circ)->purpose) {
     case CIRCUIT_PURPOSE_C_ESTABLISH_REND:
       rend_client_rendcirc_has_opened(circ);
diff --git a/src/or/or.h b/src/or/or.h
index 6332de8..2399ecf 100644
--- a/src/or/or.h
+++ b/src/or/or.h
@@ -2160,9 +2160,13 @@ typedef struct origin_circuit_t {
    * to the specification? */
   unsigned int remaining_relay_early_cells : 4;
 
-  /** Set if this circuit insanely old and if we already informed the user */
+  /** Set if this circuit is insanely old and we already informed the user */
   unsigned int is_ancient : 1;
 
+  /** Set if this circuit has already been opened. Used to detect
+   * cannibalized circuits. */
+  unsigned int has_opened : 1;
+
   /** What commands were sent over this circuit that decremented the
    * RELAY_EARLY counter? This is for debugging task 878. */
   uint8_t relay_early_commands[MAX_RELAY_EARLY_CELLS_PER_CIRCUIT];
-- 
1.7.1