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

[or-cvs] [tor/master 4/8] Move CBT params into consensus.



Author: Mike Perry <mikeperry-git@xxxxxxxxxx>
Date: Thu, 21 Jan 2010 16:10:02 -0800
Subject: Move CBT params into consensus.
Commit: 2258125e1af78983c2735e7f2b3d90690b45b328

---
 src/or/circuitbuild.c  |  200 +++++++++++++++++++++++++++++++++++-------------
 src/or/control.c       |    6 +-
 src/or/networkstatus.c |    1 +
 src/or/or.h            |   84 +++++++++++---------
 src/test/test.c        |   35 +++++----
 5 files changed, 215 insertions(+), 111 deletions(-)

diff --git a/src/or/circuitbuild.c b/src/or/circuitbuild.c
index c73f98b..4ef6bfa 100644
--- a/src/or/circuitbuild.c
+++ b/src/or/circuitbuild.c
@@ -79,6 +79,92 @@ static int onion_append_hop(crypt_path_t **head_ptr, extend_info_t *choice);
 
 static void entry_guards_changed(void);
 
+static int32_t
+circuit_build_times_max_timeouts(void)
+{
+  int32_t num = networkstatus_get_param(NULL, "cbtmaxtimeouts",
+          CBT_DEFAULT_MAX_RECENT_TIMEOUT_COUNT);
+  return num;
+}
+
+static int32_t
+circuit_build_times_min_circs_to_observe(void)
+{
+  int32_t num = networkstatus_get_param(NULL, "cbtmincircs",
+                CBT_DEFAULT_MIN_CIRCUITS_TO_OBSERVE);
+  return num;
+}
+
+double
+circuit_build_times_quantile_cutoff(void)
+{
+  int32_t num = networkstatus_get_param(NULL, "cbtquantile",
+                CBT_DEFAULT_QUANTILE_CUTOFF);
+  return num/100.0;
+}
+
+static int32_t
+circuit_build_times_test_frequency(void)
+{
+  int32_t num = networkstatus_get_param(NULL, "cbttestfreq",
+                CBT_DEFAULT_TEST_FREQUENCY);
+  return num;
+}
+
+static int32_t
+circuit_build_times_min_timeout(void)
+{
+  int32_t num = networkstatus_get_param(NULL, "cbtmintimeout",
+                CBT_DEFAULT_TIMEOUT_MIN_VALUE);
+  return num;
+}
+
+int32_t
+circuit_build_times_initial_timeout(void)
+{
+  int32_t num = networkstatus_get_param(NULL, "cbtinitialtimeout",
+                CBT_DEFAULT_TIMEOUT_INITIAL_VALUE);
+  return num;
+}
+
+static int32_t
+circuit_build_times_recent_circuit_count(void)
+{
+  int32_t num = networkstatus_get_param(NULL, "cbtrecentcount",
+                CBT_DEFAULT_RECENT_CIRCUITS);
+  return num;
+}
+
+void
+circuit_build_times_new_consensus_params(circuit_build_times_t *cbt,
+                                         networkstatus_t *ns)
+{
+  int32_t num = networkstatus_get_param(ns, "cbtrecentcount",
+                   CBT_DEFAULT_RECENT_CIRCUITS);
+
+  if (num != cbt->liveness.num_recent_circs) {
+    int8_t *recent_circs;
+    log_notice(LD_CIRC, "Changing recent timeout size from %d to %d",
+               cbt->liveness.num_recent_circs, num);
+
+    tor_assert(num > 0);
+    tor_assert(cbt->liveness.timeouts_after_firsthop);
+    recent_circs = tor_malloc_zero(sizeof(int8_t)*num);
+    memcpy(recent_circs, cbt->liveness.timeouts_after_firsthop,
+           sizeof(int8_t)*MIN(num, cbt->liveness.num_recent_circs));
+
+    // Adjust the index if it needs it.
+    if (num < cbt->liveness.num_recent_circs) {
+      cbt->liveness.after_firsthop_idx = MIN(num-1,
+              cbt->liveness.after_firsthop_idx);
+    }
+
+    tor_free(cbt->liveness.timeouts_after_firsthop);
+    cbt->liveness.timeouts_after_firsthop = recent_circs;
+    cbt->liveness.num_recent_circs = num;
+  }
+}
+
 /** Make a note that we're running unit tests (rather than running Tor
  * itself), so we avoid clobbering our state file. */
 void
@@ -96,13 +182,13 @@ circuit_build_times_get_initial_timeout(void)
   double timeout;
   if (!unit_tests && get_options()->CircuitBuildTimeout) {
     timeout = get_options()->CircuitBuildTimeout*1000;
-    if (timeout < BUILD_TIMEOUT_MIN_VALUE) {
+    if (timeout < circuit_build_times_min_timeout()) {
       log_warn(LD_CIRC, "Config CircuitBuildTimeout too low. Setting to %ds",
-               BUILD_TIMEOUT_MIN_VALUE/1000);
-      timeout = BUILD_TIMEOUT_MIN_VALUE;
+               circuit_build_times_min_timeout()/1000);
+      timeout = circuit_build_times_min_timeout();
     }
   } else {
-    timeout = BUILD_TIMEOUT_INITIAL_VALUE;
+    timeout = circuit_build_times_initial_timeout();
   }
   return timeout;
 }
@@ -133,6 +219,9 @@ void
 circuit_build_times_init(circuit_build_times_t *cbt)
 {
   memset(cbt, 0, sizeof(*cbt));
+  cbt->liveness.num_recent_circs = circuit_build_times_recent_circuit_count();
+  cbt->liveness.timeouts_after_firsthop = tor_malloc_zero(sizeof(int8_t)*
+                                      cbt->liveness.num_recent_circs);
   cbt->timeout_ms = circuit_build_times_get_initial_timeout();
   control_event_buildtimeout_set(cbt, BUILDTIMEOUT_SET_EVENT_RESET);
 }
@@ -162,10 +251,11 @@ circuit_build_times_rewind_history(circuit_build_times_t *cbt, int n)
   }
 
   cbt->build_times_idx -= n;
-  cbt->build_times_idx %= NCIRCUITS_TO_OBSERVE;
+  cbt->build_times_idx %= CBT_NCIRCUITS_TO_OBSERVE;
 
   for (i = 0; i < n; i++) {
-    cbt->circuit_build_times[(i+cbt->build_times_idx)%NCIRCUITS_TO_OBSERVE]=0;
+    cbt->circuit_build_times[(i+cbt->build_times_idx)
+                             %CBT_NCIRCUITS_TO_OBSERVE]=0;
   }
 
   if (cbt->total_build_times > n) {
@@ -189,7 +279,7 @@ circuit_build_times_rewind_history(circuit_build_times_t *cbt, int n)
 int
 circuit_build_times_add_time(circuit_build_times_t *cbt, build_time_t time)
 {
-  tor_assert(time <= BUILD_TIME_MAX);
+  tor_assert(time <= CBT_BUILD_TIME_MAX);
   if (time <= 0) {
     log_warn(LD_CIRC, "Circuit build time is %u!", time);
     return -1;
@@ -199,11 +289,11 @@ circuit_build_times_add_time(circuit_build_times_t *cbt, build_time_t time)
   log_info(LD_CIRC, "Adding circuit build time %u", time);
 
   cbt->circuit_build_times[cbt->build_times_idx] = time;
-  cbt->build_times_idx = (cbt->build_times_idx + 1) % NCIRCUITS_TO_OBSERVE;
-  if (cbt->total_build_times < NCIRCUITS_TO_OBSERVE)
+  cbt->build_times_idx = (cbt->build_times_idx + 1) % CBT_NCIRCUITS_TO_OBSERVE;
+  if (cbt->total_build_times < CBT_NCIRCUITS_TO_OBSERVE)
     cbt->total_build_times++;
 
-  if ((cbt->total_build_times % BUILD_TIMES_SAVE_STATE_EVERY) == 0) {
+  if ((cbt->total_build_times % CBT_SAVE_STATE_EVERY) == 0) {
     /* Save state every n circuit builds */
     if (!unit_tests && !get_options()->AvoidDiskWrites)
       or_state_mark_dirty(get_or_state(), 0);
@@ -220,7 +310,7 @@ circuit_build_times_max(circuit_build_times_t *cbt)
 {
   int i = 0;
   build_time_t max_build_time = 0;
-  for (i = 0; i < NCIRCUITS_TO_OBSERVE; i++) {
+  for (i = 0; i < CBT_NCIRCUITS_TO_OBSERVE; i++) {
     if (cbt->circuit_build_times[i] > max_build_time)
       max_build_time = cbt->circuit_build_times[i];
   }
@@ -233,14 +323,14 @@ build_time_t
 circuit_build_times_min(circuit_build_times_t *cbt)
 {
   int i = 0;
-  build_time_t min_build_time = BUILD_TIME_MAX;
-  for (i = 0; i < NCIRCUITS_TO_OBSERVE; i++) {
+  build_time_t min_build_time = CBT_BUILD_TIME_MAX;
+  for (i = 0; i < CBT_NCIRCUITS_TO_OBSERVE; i++) {
     if (cbt->circuit_build_times[i] && /* 0 <-> uninitialized */
         cbt->circuit_build_times[i] < min_build_time)
       min_build_time = cbt->circuit_build_times[i];
   }
-  if (min_build_time == BUILD_TIME_MAX) {
-    log_warn(LD_CIRC, "No build times less than BUILD_TIME_MAX!");
+  if (min_build_time == CBT_BUILD_TIME_MAX) {
+    log_warn(LD_CIRC, "No build times less than CBT_BUILD_TIME_MAX!");
   }
   return min_build_time;
 }
@@ -250,7 +340,7 @@ circuit_build_times_min(circuit_build_times_t *cbt)
  * Calculate and return a histogram for the set of build times.
  *
  * Returns an allocated array of histrogram bins representing
- * the frequency of index*BUILDTIME_BIN_WIDTH millisecond
+ * the frequency of index*CBT_BIN_WIDTH millisecond
  * build times. Also outputs the number of bins in nbins.
  *
  * The return value must be freed by the caller.
@@ -263,14 +353,14 @@ circuit_build_times_create_histogram(circuit_build_times_t *cbt,
   build_time_t max_build_time = circuit_build_times_max(cbt);
   int i, c;
 
-  *nbins = 1 + (max_build_time / BUILDTIME_BIN_WIDTH);
+  *nbins = 1 + (max_build_time / CBT_BIN_WIDTH);
   histogram = tor_malloc_zero(*nbins * sizeof(build_time_t));
 
   // calculate histogram
-  for (i = 0; i < NCIRCUITS_TO_OBSERVE; i++) {
+  for (i = 0; i < CBT_NCIRCUITS_TO_OBSERVE; i++) {
     if (cbt->circuit_build_times[i] == 0) continue; /* 0 <-> uninitialized */
 
-    c = (cbt->circuit_build_times[i] / BUILDTIME_BIN_WIDTH);
+    c = (cbt->circuit_build_times[i] / CBT_BIN_WIDTH);
     histogram[c]++;
   }
 
@@ -278,7 +368,7 @@ circuit_build_times_create_histogram(circuit_build_times_t *cbt,
 }
 
 /**
- * Return the most frequent build time (rounded to BUILDTIME_BIN_WIDTH ms).
+ * Return the most frequent build time (rounded to CBT_BIN_WIDTH ms).
  *
  * Ties go in favor of the slower time.
  */
@@ -296,7 +386,7 @@ circuit_build_times_mode(circuit_build_times_t *cbt)
 
   tor_free(histogram);
 
-  return max_bin*BUILDTIME_BIN_WIDTH+BUILDTIME_BIN_WIDTH/2;
+  return max_bin*CBT_BIN_WIDTH+CBT_BIN_WIDTH/2;
 }
 
 /**
@@ -327,7 +417,7 @@ circuit_build_times_update_state(circuit_build_times_t *cbt,
     line->key = tor_strdup("CircuitBuildTimeBin");
     line->value = tor_malloc(25);
     tor_snprintf(line->value, 25, "%d %d",
-            i*BUILDTIME_BIN_WIDTH+BUILDTIME_BIN_WIDTH/2, histogram[i]);
+            i*CBT_BIN_WIDTH+CBT_BIN_WIDTH/2, histogram[i]);
     next = &(line->next);
   }
 
@@ -350,9 +440,9 @@ circuit_build_times_shuffle_and_store_array(circuit_build_times_t *cbt,
                                             int num_times)
 {
   int n = num_times;
-  if (num_times > NCIRCUITS_TO_OBSERVE) {
+  if (num_times > CBT_NCIRCUITS_TO_OBSERVE) {
     log_notice(LD_CIRC, "Decreasing circuit_build_times size from %d to %d",
-               num_times, NCIRCUITS_TO_OBSERVE);
+               num_times, CBT_NCIRCUITS_TO_OBSERVE);
   }
 
   /* This code can only be run on a compact array */
@@ -363,9 +453,9 @@ circuit_build_times_shuffle_and_store_array(circuit_build_times_t *cbt,
     raw_times[n] = tmp;
   }
 
-  /* Since the times are now shuffled, take a random NCIRCUITS_TO_OBSERVE
-   * subset (ie the first NCIRCUITS_TO_OBSERVE values) */
-  for (n = 0; n < MIN(num_times, NCIRCUITS_TO_OBSERVE); n++) {
+  /* Since the times are now shuffled, take a random CBT_NCIRCUITS_TO_OBSERVE
+   * subset (ie the first CBT_NCIRCUITS_TO_OBSERVE values) */
+  for (n = 0; n < MIN(num_times, CBT_NCIRCUITS_TO_OBSERVE); n++) {
     circuit_build_times_add_time(cbt, raw_times[n]);
   }
 }
@@ -407,7 +497,7 @@ circuit_build_times_parse_state(circuit_build_times_t *cbt,
       build_time_t ms;
       int ok;
       ms = (build_time_t)tor_parse_ulong(ms_str, 0, 0,
-                                         BUILD_TIME_MAX, &ok, NULL);
+                                         CBT_BUILD_TIME_MAX, &ok, NULL);
       if (!ok) {
         *msg = tor_strdup("Unable to parse circuit build times: "
                           "Unparsable bin number");
@@ -453,7 +543,7 @@ circuit_build_times_parse_state(circuit_build_times_t *cbt,
   circuit_build_times_shuffle_and_store_array(cbt, loaded_times, loaded_cnt);
 
   /* Verify that we didn't overwrite any indexes */
-  for (i=0; i < NCIRCUITS_TO_OBSERVE; i++) {
+  for (i=0; i < CBT_NCIRCUITS_TO_OBSERVE; i++) {
     if (!cbt->circuit_build_times[i])
       break;
     tot_values++;
@@ -462,7 +552,7 @@ circuit_build_times_parse_state(circuit_build_times_t *cbt,
            "Loaded %d/%d values from %d lines in circuit time histogram",
            tot_values, cbt->total_build_times, N);
   tor_assert(cbt->total_build_times == tot_values);
-  tor_assert(cbt->total_build_times <= NCIRCUITS_TO_OBSERVE);
+  tor_assert(cbt->total_build_times <= CBT_NCIRCUITS_TO_OBSERVE);
   circuit_build_times_set_timeout(cbt);
   tor_free(loaded_times);
   return *msg ? -1 : 0;
@@ -489,7 +579,7 @@ circuit_build_times_update_alpha(circuit_build_times_t *cbt)
    * and less frechet-like. */
   cbt->Xm = circuit_build_times_mode(cbt);
 
-  for (i=0; i< NCIRCUITS_TO_OBSERVE; i++) {
+  for (i=0; i< CBT_NCIRCUITS_TO_OBSERVE; i++) {
     if (!x[i]) {
       continue;
     }
@@ -598,18 +688,18 @@ circuit_build_times_add_timeout_worker(circuit_build_times_t *cbt,
   // Keep getting values for the largest timeout bucket over and over
   // again... Probably because alpha is very very large in that case..
   build_time_t gentime = circuit_build_times_generate_sample(cbt,
-              quantile_cutoff, MAX_SYNTHETIC_QUANTILE);
+              quantile_cutoff, CBT_MAX_SYNTHETIC_QUANTILE);
 
   if (gentime < (build_time_t)tor_lround(cbt->timeout_ms)) {
     log_warn(LD_CIRC,
              "Generated a synthetic timeout LESS than the current timeout: "
              "%ums vs %lfms using Xm: %d a: %lf, q: %lf",
              gentime, cbt->timeout_ms, cbt->Xm, cbt->alpha, quantile_cutoff);
-  } else if (gentime > BUILD_TIME_MAX) {
+  } else if (gentime > CBT_BUILD_TIME_MAX) {
     log_info(LD_CIRC,
              "Generated a synthetic timeout larger than the max: %u",
              gentime);
-    gentime = BUILD_TIME_MAX;
+    gentime = CBT_BUILD_TIME_MAX;
   } else {
     log_info(LD_CIRC, "Generated synthetic circuit build time %u for timeout",
             gentime);
@@ -653,7 +743,7 @@ circuit_build_times_count_pretimeouts(circuit_build_times_t *cbt)
           ((double)cbt->pre_timeouts)/
                     (cbt->pre_timeouts+cbt->total_build_times);
     /* Make sure it doesn't exceed the synthetic max */
-    timeout_quantile *= MAX_SYNTHETIC_QUANTILE;
+    timeout_quantile *= CBT_MAX_SYNTHETIC_QUANTILE;
     cbt->Xm = circuit_build_times_mode(cbt);
     tor_assert(cbt->Xm > 0);
     /* Use current timeout to get an estimate on alpha */
@@ -673,7 +763,7 @@ int
 circuit_build_times_needs_circuits(circuit_build_times_t *cbt)
 {
   /* Return true if < MIN_CIRCUITS_TO_OBSERVE */
-  if (cbt->total_build_times < MIN_CIRCUITS_TO_OBSERVE)
+  if (cbt->total_build_times < circuit_build_times_min_circs_to_observe())
     return 1;
   return 0;
 }
@@ -686,7 +776,7 @@ int
 circuit_build_times_needs_circuits_now(circuit_build_times_t *cbt)
 {
   return circuit_build_times_needs_circuits(cbt) &&
-    approx_time()-cbt->last_circ_at > BUILD_TIMES_TEST_FREQUENCY;
+    approx_time()-cbt->last_circ_at > circuit_build_times_test_frequency();
 }
 
 /**
@@ -712,7 +802,7 @@ circuit_build_times_network_circ_success(circuit_build_times_t *cbt)
 {
   cbt->liveness.timeouts_after_firsthop[cbt->liveness.after_firsthop_idx] = 0;
   cbt->liveness.after_firsthop_idx++;
-  cbt->liveness.after_firsthop_idx %= RECENT_CIRCUITS;
+  cbt->liveness.after_firsthop_idx %= cbt->liveness.num_recent_circs;
 }
 
 /**
@@ -743,7 +833,7 @@ circuit_build_times_network_timeout(circuit_build_times_t *cbt,
     /* Count a one-hop timeout */
     cbt->liveness.timeouts_after_firsthop[cbt->liveness.after_firsthop_idx]=1;
     cbt->liveness.after_firsthop_idx++;
-    cbt->liveness.after_firsthop_idx %= RECENT_CIRCUITS;
+    cbt->liveness.after_firsthop_idx %= cbt->liveness.num_recent_circs;
   }
 }
 
@@ -758,7 +848,7 @@ int
 circuit_build_times_network_check_live(circuit_build_times_t *cbt)
 {
   time_t now = approx_time();
-  if (cbt->liveness.nonlive_timeouts >= NETWORK_NONLIVE_DISCARD_COUNT) {
+  if (cbt->liveness.nonlive_timeouts >= CBT_NETWORK_NONLIVE_DISCARD_COUNT) {
     if (!cbt->liveness.nonlive_discarded) {
       cbt->liveness.nonlive_discarded = 1;
       log_notice(LD_CIRC, "Network is no longer live (too many recent "
@@ -766,11 +856,13 @@ circuit_build_times_network_check_live(circuit_build_times_t *cbt)
                 (long int)(now - cbt->liveness.network_last_live));
       /* Only discard NETWORK_NONLIVE_TIMEOUT_COUNT-1 because we stopped
        * counting after that */
-      circuit_build_times_rewind_history(cbt, NETWORK_NONLIVE_TIMEOUT_COUNT-1);
+      circuit_build_times_rewind_history(cbt,
+                     CBT_NETWORK_NONLIVE_TIMEOUT_COUNT-1);
       control_event_buildtimeout_set(cbt, BUILDTIMEOUT_SET_EVENT_DISCARD);
     }
     return 0;
-  } else if (cbt->liveness.nonlive_timeouts >= NETWORK_NONLIVE_TIMEOUT_COUNT) {
+  } else if (cbt->liveness.nonlive_timeouts >=
+                CBT_NETWORK_NONLIVE_TIMEOUT_COUNT) {
     if (cbt->timeout_ms < circuit_build_times_get_initial_timeout()) {
       log_notice(LD_CIRC,
                 "Network is flaky. No activity for %ld seconds. "
@@ -812,19 +904,20 @@ circuit_build_times_network_check_changed(circuit_build_times_t *cbt)
 
   /* how many of our recent circuits made it to the first hop but then
    * timed out? */
-  for (i = 0; i < RECENT_CIRCUITS; i++) {
+  for (i = 0; i < cbt->liveness.num_recent_circs; i++) {
     timeout_count += cbt->liveness.timeouts_after_firsthop[i];
   }
 
   /* If 80% of our recent circuits are timing out after the first hop,
    * we need to re-estimate a new initial alpha and timeout. */
-  if (timeout_count < MAX_RECENT_TIMEOUT_COUNT) {
+  if (timeout_count < circuit_build_times_max_timeouts()) {
     return 0;
   }
 
   circuit_build_times_reset(cbt);
   memset(cbt->liveness.timeouts_after_firsthop, 0,
-          sizeof(cbt->liveness.timeouts_after_firsthop));
+          sizeof(*cbt->liveness.timeouts_after_firsthop)*
+          cbt->liveness.num_recent_circs);
   cbt->liveness.after_firsthop_idx = 0;
 
   /* Check to see if this has happened before. If so, double the timeout
@@ -875,13 +968,14 @@ circuit_build_times_add_timeout(circuit_build_times_t *cbt,
     cbt->pre_timeouts++;
     log_info(LD_CIRC,
              "Not enough circuits yet to calculate a new build timeout."
-             " Need %d more.",
-             MIN_CIRCUITS_TO_OBSERVE-cbt->total_build_times);
+             " Need %d more.", circuit_build_times_min_circs_to_observe()
+                               - cbt->total_build_times);
     return 0;
   }
 
   circuit_build_times_count_pretimeouts(cbt);
-  circuit_build_times_add_timeout_worker(cbt, BUILDTIMEOUT_QUANTILE_CUTOFF);
+  circuit_build_times_add_timeout_worker(cbt,
+           circuit_build_times_quantile_cutoff());
 
   return 1;
 }
@@ -893,7 +987,7 @@ circuit_build_times_add_timeout(circuit_build_times_t *cbt,
 void
 circuit_build_times_set_timeout(circuit_build_times_t *cbt)
 {
-  if (cbt->total_build_times < MIN_CIRCUITS_TO_OBSERVE) {
+  if (cbt->total_build_times < circuit_build_times_min_circs_to_observe()) {
     return;
   }
 
@@ -901,14 +995,14 @@ circuit_build_times_set_timeout(circuit_build_times_t *cbt)
   circuit_build_times_update_alpha(cbt);
 
   cbt->timeout_ms = circuit_build_times_calculate_timeout(cbt,
-                                BUILDTIMEOUT_QUANTILE_CUTOFF);
+                                circuit_build_times_quantile_cutoff());
 
   cbt->have_computed_timeout = 1;
 
-  if (cbt->timeout_ms < BUILD_TIMEOUT_MIN_VALUE) {
+  if (cbt->timeout_ms < circuit_build_times_min_timeout()) {
     log_warn(LD_CIRC, "Set buildtimeout to low value %lfms. Setting to %dms",
-             cbt->timeout_ms, BUILD_TIMEOUT_MIN_VALUE);
-    cbt->timeout_ms = BUILD_TIMEOUT_MIN_VALUE;
+             cbt->timeout_ms, circuit_build_times_min_timeout());
+    cbt->timeout_ms = circuit_build_times_min_timeout();
   }
 
   control_event_buildtimeout_set(cbt, BUILDTIMEOUT_SET_EVENT_COMPUTED);
diff --git a/src/or/control.c b/src/or/control.c
index a7e60d5..835c3be 100644
--- a/src/or/control.c
+++ b/src/or/control.c
@@ -3480,13 +3480,13 @@ control_event_buildtimeout_set(const circuit_build_times_t *cbt,
                         buildtimeout_set_event_t type)
 {
   const char *type_string = NULL;
-  double qnt = BUILDTIMEOUT_QUANTILE_CUTOFF;
+  double qnt = circuit_build_times_quantile_cutoff();
 
   if (!control_event_is_interesting(EVENT_BUILDTIMEOUT_SET))
     return 0;
 
   switch (type) {
-    case BUILDTIMEOUT_SET_EVENT_COMPUTED: 
+    case BUILDTIMEOUT_SET_EVENT_COMPUTED:
       type_string = "COMPUTED";
       break;
     case BUILDTIMEOUT_SET_EVENT_RESET:
@@ -3513,7 +3513,7 @@ control_event_buildtimeout_set(const circuit_build_times_t *cbt,
                      "650 BUILDTIMEOUT_SET %s TOTAL_TIMES=%lu "
                      "TIMEOUT_MS=%lu XM=%lu ALPHA=%lf CUTOFF_QUANTILE=%lf\r\n",
                      type_string, (unsigned long)cbt->total_build_times,
-                     (unsigned long)cbt->timeout_ms, 
+                     (unsigned long)cbt->timeout_ms,
                      (unsigned long)cbt->Xm, cbt->alpha, qnt);
 
   return 0;
diff --git a/src/or/networkstatus.c b/src/or/networkstatus.c
index 507875a..a507f1b 100644
--- a/src/or/networkstatus.c
+++ b/src/or/networkstatus.c
@@ -1680,6 +1680,7 @@ networkstatus_set_current_consensus(const char *consensus,
     dirvote_recalculate_timing(get_options(), now);
     routerstatus_list_update_named_server_map();
     cell_ewma_set_scale_factor(get_options(), current_consensus);
+    circuit_build_times_new_consensus_params(&circ_times, current_consensus);
   }
 
   if (!from_cache) {
diff --git a/src/or/or.h b/src/or/or.h
index 24cabb4..434de78 100644
--- a/src/or/or.h
+++ b/src/or/or.h
@@ -3002,50 +3002,28 @@ void entry_guards_free_all(void);
 
 /* Circuit Build Timeout "public" functions and structures. */
 
+/** Total size of the circuit timeout history to accumulate.
+ * 1000 is approx 2.5 days worth of continual-use circuits. */
+#define CBT_NCIRCUITS_TO_OBSERVE 1000
+
 /** Maximum quantile to use to generate synthetic timeouts.
  *  We want to stay a bit short of 1.0, because longtail is
  *  loooooooooooooooooooooooooooooooooooooooooooooooooooong. */
-#define MAX_SYNTHETIC_QUANTILE 0.985
-
-/** Minimum circuits before estimating a timeout */
-#define MIN_CIRCUITS_TO_OBSERVE 20
-
-/** Total size of the circuit timeout history to accumulate.
- * 5000 is approx 1.5 weeks worth of continual-use circuits. */
-#define NCIRCUITS_TO_OBSERVE 5000
+#define CBT_MAX_SYNTHETIC_QUANTILE 0.985
 
 /** Width of the histogram bins in milliseconds */
-#define BUILDTIME_BIN_WIDTH ((build_time_t)50)
-
-/** Cutoff point on the CDF for our timeout estimation.
- * TODO: This should be moved to the consensus */
-#define BUILDTIMEOUT_QUANTILE_CUTOFF 0.8
+#define CBT_BIN_WIDTH ((build_time_t)50)
 
 /** A build_time_t is milliseconds */
 typedef uint32_t build_time_t;
-#define BUILD_TIME_MAX ((build_time_t)(INT32_MAX))
-
-/** Lowest allowable value for CircuitBuildTimeout in milliseconds */
-#define BUILD_TIMEOUT_MIN_VALUE (3*1000)
-
-/** Initial circuit build timeout in milliseconds */
-#define BUILD_TIMEOUT_INITIAL_VALUE (60*1000)
-
-/** How often in seconds should we build a test circuit */
-#define BUILD_TIMES_TEST_FREQUENCY 60
+#define CBT_BUILD_TIME_MAX ((build_time_t)(INT32_MAX))
 
 /** Save state every 10 circuits */
-#define BUILD_TIMES_SAVE_STATE_EVERY 1
+#define CBT_SAVE_STATE_EVERY 10
 
 /* Circuit Build Timeout network liveness constants */
 
 /**
- * How many circuits count as recent when considering if the
- * connection has gone gimpy or changed.
- */
-#define RECENT_CIRCUITS 20
-
-/**
  * Have we received a cell in the last N circ attempts?
  *
  * This tells us when to temporarily switch back to
@@ -3053,7 +3031,7 @@ typedef uint32_t build_time_t;
  * at which point we switch back to computing the timeout from
  * our saved history.
  */
-#define NETWORK_NONLIVE_TIMEOUT_COUNT (RECENT_CIRCUITS*3/20)
+#define CBT_NETWORK_NONLIVE_TIMEOUT_COUNT (3)
 
 /**
  * This tells us when to toss out the last streak of N timeouts.
@@ -3061,7 +3039,15 @@ typedef uint32_t build_time_t;
  * If instead we start getting cells, we switch back to computing the timeout
  * from our saved history.
  */
-#define NETWORK_NONLIVE_DISCARD_COUNT (NETWORK_NONLIVE_TIMEOUT_COUNT*2)
+#define CBT_NETWORK_NONLIVE_DISCARD_COUNT (CBT_NETWORK_NONLIVE_TIMEOUT_COUNT*2)
+
+/* Circuit build times consensus parameters */
+
+/**
+ * How many circuits count as recent when considering if the
+ * connection has gone gimpy or changed.
+ */
+#define CBT_DEFAULT_RECENT_CIRCUITS 20
 
 /**
  * Maximum count of timeouts that finish the first hop in the past
@@ -3070,10 +3056,28 @@ typedef uint32_t build_time_t;
  * This tells us to abandon timeout history and set
  * the timeout back to BUILD_TIMEOUT_INITIAL_VALUE.
  */
-#define MAX_RECENT_TIMEOUT_COUNT (RECENT_CIRCUITS*4/5)
+#define CBT_DEFAULT_MAX_RECENT_TIMEOUT_COUNT (CBT_DEFAULT_RECENT_CIRCUITS*9/10)
+
+/** Minimum circuits before estimating a timeout */
+#define CBT_DEFAULT_MIN_CIRCUITS_TO_OBSERVE 100
+
+/** Cutoff percentile on the CDF for our timeout estimation. */
+#define CBT_DEFAULT_QUANTILE_CUTOFF 80
+double circuit_build_times_quantile_cutoff(void);
+
+/** How often in seconds should we build a test circuit */
+#define CBT_DEFAULT_TEST_FREQUENCY 60
+
+/** Lowest allowable value for CircuitBuildTimeout in milliseconds */
+#define CBT_DEFAULT_TIMEOUT_MIN_VALUE (2*1000)
+
+/** Initial circuit build timeout in milliseconds */
+#define CBT_DEFAULT_TIMEOUT_INITIAL_VALUE (60*1000)
+int32_t circuit_build_times_initial_timeout(void);
 
-#if MAX_RECENT_TIMEOUT_COUNT < 1 || NETWORK_NONLIVE_DISCARD_COUNT < 1 || \
-  NETWORK_NONLIVE_TIMEOUT_COUNT < 1
+#if CBT_DEFAULT_MAX_RECENT_TIMEOUT_COUNT < 1 || \
+    CBT_NETWORK_NONLIVE_DISCARD_COUNT < 1 || \
+    CBT_NETWORK_NONLIVE_TIMEOUT_COUNT < 1
 #error "RECENT_CIRCUITS is set too low."
 #endif
 
@@ -3087,7 +3091,9 @@ typedef struct {
   int nonlive_discarded;
   /** Circular array of circuits that have made it to the first hop. Slot is
    * 1 if circuit timed out, 0 if circuit succeeded */
-  int8_t timeouts_after_firsthop[RECENT_CIRCUITS];
+  int8_t *timeouts_after_firsthop;
+  /** Number of elements allocated for the above array */
+  int num_recent_circs;
   /** Index into circular array. */
   int after_firsthop_idx;
   /** The network is not live. Timeout gathering is suspended */
@@ -3097,10 +3103,10 @@ typedef struct {
 /** Structure for circuit build times history */
 typedef struct {
   /** The circular array of recorded build times in milliseconds */
-  build_time_t circuit_build_times[NCIRCUITS_TO_OBSERVE];
+  build_time_t circuit_build_times[CBT_NCIRCUITS_TO_OBSERVE];
   /** Current index in the circuit_build_times circular array */
   int build_times_idx;
-  /** Total number of build times accumulated. Maxes at NCIRCUITS_TO_OBSERVE */
+  /** Total number of build times accumulated. Max CBT_NCIRCUITS_TO_OBSERVE */
   int total_build_times;
   /** Information about the state of our local network connection */
   network_liveness_t liveness;
@@ -3132,6 +3138,8 @@ int circuit_build_times_add_time(circuit_build_times_t *cbt,
 int circuit_build_times_needs_circuits(circuit_build_times_t *cbt);
 int circuit_build_times_needs_circuits_now(circuit_build_times_t *cbt);
 void circuit_build_times_init(circuit_build_times_t *cbt);
+void circuit_build_times_new_consensus_params(circuit_build_times_t *cbt,
+                                              networkstatus_t *ns);
 
 #ifdef CIRCUIT_PRIVATE
 double circuit_build_times_calculate_timeout(circuit_build_times_t *cbt,
diff --git a/src/test/test.c b/src/test/test.c
index 8b84290..760558b 100644
--- a/src/test/test.c
+++ b/src/test/test.c
@@ -479,11 +479,12 @@ test_circuit_timeout(void)
   circuitbuild_running_unit_tests();
 #define timeout0 (build_time_t)(30*1000.0)
   initial.Xm = 750;
-  circuit_build_times_initial_alpha(&initial, BUILDTIMEOUT_QUANTILE_CUTOFF,
+  circuit_build_times_initial_alpha(&initial,
+                                    CBT_DEFAULT_QUANTILE_CUTOFF/100.0,
                                     timeout0);
   do {
     int n = 0;
-    for (i=0; i < MIN_CIRCUITS_TO_OBSERVE; i++) {
+    for (i=0; i < CBT_DEFAULT_MIN_CIRCUITS_TO_OBSERVE; i++) {
       if (circuit_build_times_add_time(&estimate,
               circuit_build_times_generate_sample(&initial, 0, 1)) == 0) {
         n++;
@@ -491,23 +492,23 @@ test_circuit_timeout(void)
     }
     circuit_build_times_update_alpha(&estimate);
     timeout1 = circuit_build_times_calculate_timeout(&estimate,
-                                  BUILDTIMEOUT_QUANTILE_CUTOFF);
+                                  CBT_DEFAULT_QUANTILE_CUTOFF/100.0);
     circuit_build_times_set_timeout(&estimate);
     log_warn(LD_CIRC, "Timeout is %lf, Xm is %d", timeout1, estimate.Xm);
     /* XXX: 5% distribution error may not be the right metric */
   } while (fabs(circuit_build_times_cdf(&initial, timeout0) -
                 circuit_build_times_cdf(&initial, timeout1)) > 0.05
                 /* 5% error */
-           && estimate.total_build_times < NCIRCUITS_TO_OBSERVE);
+           && estimate.total_build_times < CBT_NCIRCUITS_TO_OBSERVE);
 
-  test_assert(estimate.total_build_times < NCIRCUITS_TO_OBSERVE);
+  test_assert(estimate.total_build_times < CBT_NCIRCUITS_TO_OBSERVE);
 
   circuit_build_times_update_state(&estimate, &state);
   test_assert(circuit_build_times_parse_state(&final, &state, &msg) == 0);
 
   circuit_build_times_update_alpha(&final);
   timeout2 = circuit_build_times_calculate_timeout(&final,
-                                 BUILDTIMEOUT_QUANTILE_CUTOFF);
+                                 CBT_DEFAULT_QUANTILE_CUTOFF/100.0);
 
   circuit_build_times_set_timeout(&final);
   log_warn(LD_CIRC, "Timeout is %lf, Xm is %d", timeout2, final.Xm);
@@ -519,19 +520,19 @@ test_circuit_timeout(void)
     int build_times_idx = 0;
     int total_build_times = 0;
 
-    final.timeout_ms = BUILD_TIMEOUT_INITIAL_VALUE;
-    estimate.timeout_ms = BUILD_TIMEOUT_INITIAL_VALUE;
+    final.timeout_ms = CBT_DEFAULT_TIMEOUT_INITIAL_VALUE;
+    estimate.timeout_ms = CBT_DEFAULT_TIMEOUT_INITIAL_VALUE;
 
-    for (i = 0; i < RECENT_CIRCUITS*2; i++) {
+    for (i = 0; i < CBT_DEFAULT_RECENT_CIRCUITS*2; i++) {
       circuit_build_times_network_circ_success(&estimate);
       circuit_build_times_add_time(&estimate,
             circuit_build_times_generate_sample(&estimate, 0,
-                BUILDTIMEOUT_QUANTILE_CUTOFF));
+                CBT_DEFAULT_QUANTILE_CUTOFF/100.0));
       estimate.have_computed_timeout = 1;
       circuit_build_times_network_circ_success(&estimate);
       circuit_build_times_add_time(&final,
             circuit_build_times_generate_sample(&final, 0,
-                BUILDTIMEOUT_QUANTILE_CUTOFF));
+                CBT_DEFAULT_QUANTILE_CUTOFF/100.0));
       final.have_computed_timeout = 1;
     }
 
@@ -544,7 +545,7 @@ test_circuit_timeout(void)
 
     build_times_idx = estimate.build_times_idx;
     total_build_times = estimate.total_build_times;
-    for (i = 0; i < NETWORK_NONLIVE_TIMEOUT_COUNT; i++) {
+    for (i = 0; i < CBT_NETWORK_NONLIVE_TIMEOUT_COUNT; i++) {
       test_assert(circuit_build_times_network_check_live(&estimate));
       test_assert(circuit_build_times_network_check_live(&final));
 
@@ -559,12 +560,12 @@ test_circuit_timeout(void)
     test_assert(!circuit_build_times_network_check_live(&estimate));
     test_assert(!circuit_build_times_network_check_live(&final));
 
-    for ( ; i < NETWORK_NONLIVE_DISCARD_COUNT; i++) {
+    for ( ; i < CBT_NETWORK_NONLIVE_DISCARD_COUNT; i++) {
       if (circuit_build_times_add_timeout(&estimate, 0,
                 (time_t)(approx_time()-estimate.timeout_ms/1000.0-1)))
         estimate.have_computed_timeout = 1;
 
-      if (i < NETWORK_NONLIVE_DISCARD_COUNT-1) {
+      if (i < CBT_NETWORK_NONLIVE_DISCARD_COUNT-1) {
         if (circuit_build_times_add_timeout(&final, 0,
                 (time_t)(approx_time()-final.timeout_ms/1000.0-1)))
           final.have_computed_timeout = 1;
@@ -587,11 +588,11 @@ test_circuit_timeout(void)
     circuit_build_times_network_is_live(&estimate);
     circuit_build_times_network_is_live(&final);
 
-    for (i = 0; i < MAX_RECENT_TIMEOUT_COUNT; i++) {
+    for (i = 0; i < CBT_DEFAULT_MAX_RECENT_TIMEOUT_COUNT; i++) {
       if (circuit_build_times_add_timeout(&estimate, 1, approx_time()-1))
         estimate.have_computed_timeout = 1;
 
-      if (i < MAX_RECENT_TIMEOUT_COUNT-1) {
+      if (i < CBT_DEFAULT_MAX_RECENT_TIMEOUT_COUNT-1) {
         if (circuit_build_times_add_timeout(&final, 1, approx_time()-1))
           final.have_computed_timeout = 1;
       }
@@ -599,7 +600,7 @@ test_circuit_timeout(void)
 
     test_assert(estimate.liveness.after_firsthop_idx == 0);
     test_assert(final.liveness.after_firsthop_idx ==
-                MAX_RECENT_TIMEOUT_COUNT-1);
+                CBT_DEFAULT_MAX_RECENT_TIMEOUT_COUNT-1);
 
     test_assert(circuit_build_times_network_check_live(&estimate));
     test_assert(circuit_build_times_network_check_live(&final));
-- 
1.6.5