Browse Source

Add the ability to count circuit timeouts for guards.

This is purely for informational reasons for debugging.
Mike Perry 11 years ago
parent
commit
954f263ed5
5 changed files with 85 additions and 6 deletions
  1. 67 0
      src/or/circuitbuild.c
  2. 2 0
      src/or/circuituse.c
  3. 12 6
      src/or/entrynodes.c
  4. 2 0
      src/or/entrynodes.h
  5. 2 0
      src/or/or.h

+ 67 - 0
src/or/circuitbuild.c

@@ -1056,6 +1056,53 @@ pathbias_state_to_string(path_state_t state)
   return "unknown";
 }
 
+/**
+ * Decide if the path bias code should count a circuit.
+ *
+ * @returns 1 if we should count it, 0 otherwise.
+ */
+static int
+pathbias_should_count(origin_circuit_t *circ)
+{
+#define PATHBIAS_COUNT_INTERVAL (600)
+  static ratelim_t count_limit =
+    RATELIM_INIT(PATHBIAS_COUNT_INTERVAL);
+  char *rate_msg = NULL;
+
+  /* We can't do path bias accounting without entry guards.
+   * Testing and controller circuits also have no guards. */
+  if (get_options()->UseEntryGuards == 0 ||
+          circ->base_.purpose == CIRCUIT_PURPOSE_TESTING ||
+          circ->base_.purpose == CIRCUIT_PURPOSE_CONTROLLER) {
+    return 0;
+  }
+
+  /* Completely ignore one hop circuits */
+  if (circ->build_state->onehop_tunnel ||
+      circ->build_state->desired_path_len == 1) {
+    /* Check for inconsistency */
+    if (circ->build_state->desired_path_len != 1 ||
+        !circ->build_state->onehop_tunnel) {
+      if ((rate_msg = rate_limit_log(&count_limit, approx_time()))) {
+        log_notice(LD_BUG,
+               "One-hop circuit has length %d. Path state is %s. "
+               "Circuit is a %s currently %s.%s",
+               circ->build_state->desired_path_len,
+               pathbias_state_to_string(circ->path_state),
+               circuit_purpose_to_string(circ->base_.purpose),
+               circuit_state_to_string(circ->base_.state),
+               rate_msg);
+        tor_free(rate_msg);
+      }
+      tor_fragile_assert();
+    }
+    return 0;
+  }
+
+  return 1;
+}
+
+
 /**
  * Check our circuit state to see if this is a successful first hop.
  * If so, record it in the current guard's path bias first_hop count.
@@ -1290,6 +1337,26 @@ pathbias_count_success(origin_circuit_t *circ)
   }
 }
 
+/**
+ * Count timeouts for path bias log messages.
+ *
+ * These counts are purely informational.
+ */
+void
+pathbias_count_timeout(origin_circuit_t *circ)
+{
+  if(!pathbias_should_count(circ)) {
+    return;
+  }
+  entry_guard_t *guard =
+      entry_guard_get_by_id_digest(circ->base_.n_chan->identity_digest);
+
+  if (guard) {
+    guard->timeouts++;
+    entry_guards_changed();
+  }
+}
+
 /** Increment the number of times we successfully extended a circuit to
  * 'guard', first checking if the failure rate is high enough that we should
  * eliminate the guard.  Return -1 if the guard looks no good; return 0 if the

+ 2 - 0
src/or/circuituse.c

@@ -663,6 +663,8 @@ circuit_expire_building(void)
       circuit_mark_for_close(victim, END_CIRC_REASON_MEASUREMENT_EXPIRED);
     else
       circuit_mark_for_close(victim, END_CIRC_REASON_TIMEOUT);
+
+    pathbias_count_timeout(TO_ORIGIN_CIRCUIT(victim));
   }
 }
 

+ 12 - 6
src/or/entrynodes.c

@@ -1021,7 +1021,7 @@ entry_guards_parse_state(or_state_t *state, int set, char **msg)
       digestmap_set(added_by, d, tor_strdup(line->value+HEX_DIGEST_LEN+1));
     } else if (!strcasecmp(line->key, "EntryGuardPathBias")) {
       const or_options_t *options = get_options();
-      unsigned hop_cnt, success_cnt;
+      unsigned hop_cnt, success_cnt, timeouts;
 
       if (!node) {
         *msg = tor_strdup("Unable to parse entry nodes: "
@@ -1029,14 +1029,20 @@ entry_guards_parse_state(or_state_t *state, int set, char **msg)
         break;
       }
 
-      if (tor_sscanf(line->value, "%u %u", &success_cnt, &hop_cnt) != 2) {
-        log_warn(LD_GENERAL, "Unable to parse guard path bias info: "
+      /* First try 3 params, then 2. */
+      if (tor_sscanf(line->value, "%u %u %u", &success_cnt, &hop_cnt,
+                     &timeouts) != 3) {
+        timeouts = 0;
+        if (tor_sscanf(line->value, "%u %u", &success_cnt, &hop_cnt) != 2) {
+          log_warn(LD_GENERAL, "Unable to parse guard path bias info: "
                  "Misformated EntryGuardPathBias %s", escaped(line->value));
-        continue;
+          continue;
+        }
       }
 
       node->first_hops = hop_cnt;
       node->circuit_successes = success_cnt;
+      node->timeouts = timeouts;
       log_info(LD_GENERAL, "Read %u/%u path bias for node %s",
                node->circuit_successes, node->first_hops, node->nickname);
       /* Note: We rely on the < comparison here to allow us to set a 0
@@ -1173,8 +1179,8 @@ entry_guards_update_state(or_state_t *state)
       if (e->first_hops) {
         *next = line = tor_malloc_zero(sizeof(config_line_t));
         line->key = tor_strdup("EntryGuardPathBias");
-        tor_asprintf(&line->value, "%u %u",
-                     e->circuit_successes, e->first_hops);
+        tor_asprintf(&line->value, "%u %u %u",
+                     e->circuit_successes, e->first_hops, e->timeouts);
         next = &(line->next);
       }
 

+ 2 - 0
src/or/entrynodes.h

@@ -47,6 +47,8 @@ typedef struct entry_guard_t {
   unsigned first_hops; /**< Number of first hops this guard has completed */
   unsigned circuit_successes; /**< Number of successfully built circuits using
                                * this guard as first hop. */
+  unsigned timeouts; /**< Number of 'right-censored' timeouts 
+                                   for this guard. */
 } entry_guard_t;
 
 entry_guard_t *entry_guard_get_by_id_digest(const char *digest);

+ 2 - 0
src/or/or.h

@@ -4067,6 +4067,8 @@ typedef struct {
   double close_ms;
 } circuit_build_times_t;
 
+void pathbias_count_timeout(origin_circuit_t *circ);
+
 /********************************* config.c ***************************/
 
 /** An error from options_trial_assign() or options_init_from_string(). */