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

[or-cvs] [tor/master 09/28] Bug 1296: Add option+logic to disable CBT learning.



Author: Mike Perry <mikeperry-git@xxxxxxxxxx>
Date: Sat, 8 May 2010 11:54:29 -0700
Subject: Bug 1296: Add option+logic to disable CBT learning.
Commit: 29e0d7081454c49cb6cab14685447aa811379a22

There are now four ways that CBT can be disabled:

1. Network-wide, with the cbtdisabled consensus param.
2. Via config, with "LearnCircuitBuildTimeout 0"
3. Via config, with "AuthoritativeDirectory 1"
4. Via a state file write failure.
---
 doc/spec/path-spec.txt |    6 ++++++
 doc/tor.1.txt          |    9 ++++++++-
 src/or/circuitbuild.c  |   38 +++++++++++++++++++++++++++++++++++---
 src/or/config.c        |    5 ++++-
 src/or/or.h            |    9 ++++++---
 5 files changed, 59 insertions(+), 8 deletions(-)

diff --git a/doc/spec/path-spec.txt b/doc/spec/path-spec.txt
index ae5ab3e..2beeede 100644
--- a/doc/spec/path-spec.txt
+++ b/doc/spec/path-spec.txt
@@ -382,6 +382,12 @@ of their choices.
    construction. If these parameters are not present in the consensus,
    the listed default values should be used instead.
 
+      cbtdisabled
+        Default: 0
+        Effect: If non-zero, all CircuitBuildTime learning code should be
+                disabled and history should be discarded. For use in
+                emergency situations only.
+
       cbtrecentcount
         Default: 20
         Effect: This is the number of circuit build times to keep track of
diff --git a/doc/tor.1.txt b/doc/tor.1.txt
index 2ae5005..e6bce02 100644
--- a/doc/tor.1.txt
+++ b/doc/tor.1.txt
@@ -419,9 +419,16 @@ The following options are useful only for clients (that is, if
     fingerprint to look up the bridge descriptor at the bridge authority, if
     it's provided and if UpdateBridgesFromAuthority is set too.
 
+**LearnCircuitBuildTimeout** **0**|**1**::
+    If 0, CircuitBuildTimeout adaptive learning is disabled. (Default: 1)
+
 **CircuitBuildTimeout** __NUM__::
+
     Try for at most NUM seconds when building circuits. If the circuit isn't
-    open in that time, give up on it. (Default: 1 minute.)
+    open in that time, give up on it. If LearnCircuitBuildTimeout is 1, this
+    value serves as the initial value to use before a timeout is learned. If
+    LearnCircuitBuildTimeout is 0, this value is the only value used.
+    (Default: 60 seconds.)
 
 **CircuitIdleTimeout** __NUM__::
     If we have kept a clean (never used) circuit around for NUM seconds, then
diff --git a/src/or/circuitbuild.c b/src/or/circuitbuild.c
index 3600ce7..4f79d32 100644
--- a/src/or/circuitbuild.c
+++ b/src/or/circuitbuild.c
@@ -81,6 +81,28 @@ static int onion_append_hop(crypt_path_t **head_ptr, extend_info_t *choice);
 
 static void entry_guards_changed(void);
 
+static int
+circuit_build_times_disabled(void)
+{
+  int consensus_disabled = networkstatus_get_param(NULL, "cbtdisabled",
+                                                   0);
+  int config_disabled = !get_options()->LearnCircuitBuildTimeout;
+  int dirauth_disabled = get_options()->AuthoritativeDir;
+  int state_disabled = (get_or_state()->LastWritten == -1);
+
+  if (consensus_disabled || config_disabled || dirauth_disabled ||
+         state_disabled) {
+    log_info(LD_CIRC,
+             "CircuitBuildTime learning is disabled. "
+             "Consensus=%d, Config=%d, AuthDir=%d, StateFile=%d",
+             consensus_disabled, config_disabled, dirauth_disabled,
+             state_disabled);
+    return 1;
+  } else {
+    return 0;
+  }
+}
+
 static int32_t
 circuit_build_times_max_timeouts(void)
 {
@@ -531,11 +553,16 @@ circuit_build_times_parse_state(circuit_build_times_t *cbt,
   uint32_t loaded_cnt = 0, N = 0;
   config_line_t *line;
   int i;
-  build_time_t *loaded_times = tor_malloc(sizeof(build_time_t)
-                                          * state->TotalBuildTimes);
+  build_time_t *loaded_times;
   circuit_build_times_init(cbt);
   *msg = NULL;
 
+  if (circuit_build_times_disabled()) {
+    return 0;
+  }
+
+  loaded_times = tor_malloc(sizeof(build_time_t)*state->TotalBuildTimes);
+
   for (line = state->BuildtimeHistogram; line; line = line->next) {
     smartlist_t *args = smartlist_create();
     smartlist_split_string(args, line->value, " ",
@@ -1020,6 +1047,11 @@ circuit_build_times_add_timeout(circuit_build_times_t *cbt,
                                 int did_onehop,
                                 time_t start_time)
 {
+  if (circuit_build_times_disabled()) {
+    cbt->timeout_ms = circuit_build_times_get_initial_timeout();
+    return 0;
+  }
+
   circuit_build_times_network_timeout(cbt, did_onehop, start_time);
 
   /* Only count timeouts if network is live.. */
@@ -1769,7 +1801,7 @@ circuit_send_next_onion_skin(origin_circuit_t *circ)
         if (timediff < 0 || timediff > 2*circ_times.timeout_ms+1000) {
           log_notice(LD_CIRC, "Strange value for circuit build time: %ld. "
                               "Assuming clock jump.", timediff);
-        } else {
+        } else if (!circuit_build_times_disabled()) {
           circuit_build_times_add_time(&circ_times, (build_time_t)timediff);
           circuit_build_times_network_circ_success(&circ_times);
           circuit_build_times_set_timeout(&circ_times);
diff --git a/src/or/config.c b/src/or/config.c
index 5d07cd7..77ef45e 100644
--- a/src/or/config.c
+++ b/src/or/config.c
@@ -167,6 +167,7 @@ static config_var_t _option_vars[] = {
   V(BridgeRecordUsageByCountry,  BOOL,     "1"),
   V(BridgeRelay,                 BOOL,     "0"),
   V(CellStatistics,              BOOL,     "0"),
+  V(LearnCircuitBuildTimeout,    BOOL,     "1"),
   V(CircuitBuildTimeout,         INTERVAL, "0"),
   V(CircuitIdleTimeout,          INTERVAL, "1 hour"),
   V(CircuitStreamTimeout,        INTERVAL, "0"),
@@ -4982,7 +4983,6 @@ or_state_save(time_t now)
   if (accounting_is_enabled(get_options()))
     accounting_run_housekeeping(now);
 
-  global_state->LastWritten = time(NULL);
   tor_free(global_state->TorVersion);
   tor_asprintf(&global_state->TorVersion, "Tor %s", get_version());
 
@@ -4997,10 +4997,13 @@ or_state_save(time_t now)
   fname = get_datadir_fname("state");
   if (write_str_to_file(fname, contents, 0)<0) {
     log_warn(LD_FS, "Unable to write state to file \"%s\"", fname);
+    global_state->LastWritten = -1;
     tor_free(fname);
     tor_free(contents);
     return -1;
   }
+
+  global_state->LastWritten = time(NULL);
   log_info(LD_GENERAL, "Saved state to \"%s\"", fname);
   tor_free(fname);
   tor_free(contents);
diff --git a/src/or/or.h b/src/or/or.h
index f318474..36c45e2 100644
--- a/src/or/or.h
+++ b/src/or/or.h
@@ -2496,9 +2496,12 @@ typedef struct {
                         * connections alive? */
   int SocksTimeout; /**< How long do we let a socks connection wait
                      * unattached before we fail it? */
-  int CircuitBuildTimeout; /**< If non-zero, cull non-open circuits that
-                            * were born at least this many seconds ago. If
-                            * zero, use the internal adaptive algorithm. */
+  int LearnCircuitBuildTimeout; /**< If non-zero, we attempt to learn a value
+                                 * for CircuitBuildTimeout based on timeout
+                                 * history */
+  int CircuitBuildTimeout; /**< Cull non-open circuits that were born at
+                            * least this many seconds ago. Used until
+                            * adaptive algorithm learns a new value. */
   int CircuitIdleTimeout; /**< Cull open clean circuits that were born
                            * at least this many seconds ago. */
   int CircuitStreamTimeout; /**< If non-zero, detach streams from circuits
-- 
1.7.1