aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/or/circuitbuild.c67
-rw-r--r--src/or/circuituse.c2
-rw-r--r--src/or/entrynodes.c18
-rw-r--r--src/or/entrynodes.h2
-rw-r--r--src/or/or.h2
5 files changed, 85 insertions, 6 deletions
diff --git a/src/or/circuitbuild.c b/src/or/circuitbuild.c
index 73018740c..c8c8db396 100644
--- a/src/or/circuitbuild.c
+++ b/src/or/circuitbuild.c
@@ -1057,6 +1057,53 @@ pathbias_state_to_string(path_state_t state)
}
/**
+ * 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
diff --git a/src/or/circuituse.c b/src/or/circuituse.c
index e14f9d03c..77822a36a 100644
--- a/src/or/circuituse.c
+++ b/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));
}
}
diff --git a/src/or/entrynodes.c b/src/or/entrynodes.c
index 8712241f6..d9a06a657 100644
--- a/src/or/entrynodes.c
+++ b/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);
}
diff --git a/src/or/entrynodes.h b/src/or/entrynodes.h
index 4d031c359..b34744183 100644
--- a/src/or/entrynodes.h
+++ b/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);
diff --git a/src/or/or.h b/src/or/or.h
index 195cb2b98..59202104d 100644
--- a/src/or/or.h
+++ b/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(). */