[or-cvs] [tor/master] Clean up Fallon's partially complete GSoC project.

arma at seul.org arma at seul.org
Thu Sep 17 01:46:21 UTC 2009


Author: Mike Perry <mikeperry-git at fscked.org>
Date: Tue, 25 Aug 2009 17:13:12 -0700
Subject: Clean up Fallon's partially complete GSoC project.
Commit: 7750bee21dda817611afd936558834bb21411301

The code actually isn't that bad. It's a shame she didn't finish.
Using it as the base for this feature.
---
 src/or/circuitbuild.c |  160 +++++++++++++++++++++++++++++++++++++++++++++++++
 src/or/circuitlist.c  |    1 +
 src/or/config.c       |   17 +++++
 src/or/or.h           |   18 ++++++
 4 files changed, 196 insertions(+), 0 deletions(-)

diff --git a/src/or/circuitbuild.c b/src/or/circuitbuild.c
index ef9d24c..7334308 100644
--- a/src/or/circuitbuild.c
+++ b/src/or/circuitbuild.c
@@ -12,6 +12,11 @@
 #include "or.h"
 
 /********* START VARIABLES **********/
+/** Global list of circuit build times */
+// XXX: Make this a smartlist..
+uint16_t circuit_build_times[NCIRCUITS_TO_OBSERVE];
+int build_times_idx = 0;
+int total_build_times = 0;
 
 /** A global list of all circuits at this hop. */
 extern circuit_t *global_circuitlist;
@@ -60,6 +65,156 @@ static int onion_append_hop(crypt_path_t **head_ptr, extend_info_t *choice);
 static void entry_guards_changed(void);
 static time_t start_of_month(time_t when);
 
+static int circuit_build_times_add_time(time_t time);
+/** circuit_build_times is a circular array, so loop around when
+ *  array is full
+ *
+ * time units are milliseconds
+ */
+static
+int
+circuit_build_times_add_time(long time)
+{
+  if(time > UINT16_MAX) {
+    log_notice(LD_CIRC,
+       "Circuit build time of %dms exceeds max. Capping at 65536ms", time);
+    time = UINT16_MAX;
+  }
+  circuit_build_times[build_times_idx] = time;
+  build_times_idx = (build_times_idx + 1) % NCIRCUITS_TO_OBSERVE;
+  if(total_build_times + 1 < NCIRCUITS_TO_OBSERVE)
+    total_build_times++;
+
+  return 0;
+}
+
+/**
+ * Calculate histogram
+ */
+void
+circuit_build_times_create_histogram(uint16_t * histogram)
+{
+ int i, c;
+   // calculate histogram
+  for(i = 0; i < NCIRCUITS_TO_OBSERVE; i++) {
+    if(circuit_build_times[i] == 0) continue; /* 0 <-> uninitialized */
+
+    c = (circuit_build_times[i] / BUILDTIME_BIN_WIDTH);
+    histogram[c]++;
+  }
+}
+
+/**
+ * Find maximum circuit build time
+ */
+uint16_t
+circuit_build_times_max()
+{
+  int i = 0, max_build_time = 0;
+  for( i = 0; i < NCIRCUITS_TO_OBSERVE; i++) {
+    if(circuit_build_times[i] > max_build_time)
+      max_build_time = circuit_build_times[i];
+  }
+  return max_build_time;
+}
+
+uint16_t
+circuit_build_times_min()
+{
+  int i = 0;
+  uint16_t min_build_time = UINT16_MAX;
+  for( i = 0; i < NCIRCUITS_TO_OBSERVE; i++) {
+    if(circuit_build_times[i] && /* 0 <-> uninitialized */
+            circuit_build_times[i] < min_build_time)
+      min_build_time = circuit_build_times[i];
+  }
+  return min_build_time;
+}
+
+/**
+ * output a histogram of current circuit build times
+ */
+void
+circuit_build_times_update_state(or_state_t * state)
+{
+  uint16_t max_build_time = 0, *histogram;
+  int i = 0, nbins = 0;
+  config_line_t **next, *line;
+
+  max_build_time = circuit_build_times_max();
+  nbins = 1 + (max_build_time / BUILDTIME_BIN_WIDTH);
+  histogram = tor_malloc_zero(nbins * sizeof(uint16_t));
+
+  circuit_build_times_create_histogram(histogram);
+  // write to state
+  config_free_lines(state->BuildtimeHistogram);
+  next = &state->BuildtimeHistogram;
+  *next = NULL;
+
+  state->TotalBuildTimes = total_build_times;
+
+  // total build times?
+  for(i = 0; i < nbins; i++) {
+    if(histogram[i] == 0) continue; // compress the histogram by skipping the blanks
+    *next = line = tor_malloc_zero(sizeof(config_line_t));
+    line->key = tor_strdup("CircuitBuildTimeBin");
+    line->value = tor_malloc(20);
+    tor_snprintf(line->value, 20, "%d %d", i*BUILDTIME_BIN_WIDTH,
+                 histogram[i]);
+    next = &(line->next);
+  }
+  if(!get_options()->AvoidDiskWrites)
+    or_state_mark_dirty(get_or_state(), 0);
+
+  if(histogram) tor_free(histogram);
+}
+
+int
+find_next_available(int chosen)
+{// find index of next open slot in circuit_build_times
+  int idx = 0;
+  for(idx = (chosen + 1) % NCIRCUITS_TO_OBSERVE; idx < chosen;
+          idx = ((idx + 1 ) % NCIRCUITS_TO_OBSERVE)) {
+    if(circuit_build_times[idx] == 0) {
+      return idx;
+    }
+  }
+  return 0;
+}
+
+/** Load histogram from state */
+int
+circuit_build_times_parse_state(or_state_t *state, char **msg)
+{
+  config_line_t *line;
+  msg = NULL;
+  memset(circuit_build_times, 0, NCIRCUITS_TO_OBSERVE);
+  total_build_times = state->TotalBuildTimes;
+
+  for(line = state->BuildtimeHistogram; line; line = line->next) {
+    smartlist_t * args = smartlist_create();
+    smartlist_split_string(args, line->value, " ",
+                                  SPLIT_SKIP_SPACE|SPLIT_IGNORE_BLANK, 0);
+    if(smartlist_len(args) < 2) {
+      *msg = tor_strdup("Unable to parse circuit build times: "
+                          "Too few arguments to CircuitBuildTIme");
+      break;
+    } else {
+      uint16_t ms, count, i;
+      /* XXX: use tor_strtol */
+      ms = atol(smartlist_get(args,0));
+      count = atol(smartlist_get(args,1));
+      for(i = 0; i < count; i++) {
+        circuit_build_times_add_time(ms);
+      }
+    }
+  }
+  return (msg ? -1 : 0);
+}
+
+
+
+
 /** Iterate over values of circ_id, starting from conn-\>next_circ_id,
  * and with the high bit specified by conn-\>circ_id_type, until we get
  * a circ_id that is not in use by any other circuit on that conn.
@@ -641,8 +796,13 @@ circuit_send_next_onion_skin(origin_circuit_t *circ)
     log_debug(LD_CIRC,"starting to send subsequent skin.");
     hop = onion_next_hop_in_cpath(circ->cpath);
     if (!hop) {
+      struct timeval end;
+      tor_gettimeofday(&end);
       /* done building the circuit. whew. */
       circuit_set_state(TO_CIRCUIT(circ), CIRCUIT_STATE_OPEN);
+      circuit_build_times_add_time(tor_mdiff(&circ->_base.timestamp_created,
+                  &end));
+      circuit_build_times_recompute();
       log_info(LD_CIRC,"circuit built!");
       circuit_reset_failure_count(0);
       if (circ->build_state->onehop_tunnel)
diff --git a/src/or/circuitlist.c b/src/or/circuitlist.c
index e1da117..54bda94 100644
--- a/src/or/circuitlist.c
+++ b/src/or/circuitlist.c
@@ -379,6 +379,7 @@ static void
 init_circuit_base(circuit_t *circ)
 {
   circ->timestamp_created = time(NULL);
+  tor_gettimeofday(&circ->highres_created);
 
   circ->package_window = circuit_initial_package_window();
   circ->deliver_window = CIRCWINDOW_START;
diff --git a/src/or/config.c b/src/or/config.c
index d830229..0345ca7 100644
--- a/src/or/config.c
+++ b/src/or/config.c
@@ -409,6 +409,11 @@ static config_var_t _state_vars[] = {
   V(LastRotatedOnionKey,              ISOTIME,  NULL),
   V(LastWritten,                      ISOTIME,  NULL),
 
+  VAR("TotalBuildTimes",         UINT,        TotalBuildTimes,     NULL),
+  VAR("CircuitBuildTimeBin",      LINELIST_S,  BuildtimeHistogram,     NULL),
+  VAR("BuildtimeHistogram",      LINELIST_V,  BuildtimeHistogram,     NULL),
+
+
   { NULL, CONFIG_TYPE_OBSOLETE, 0, NULL }
 };
 
@@ -597,6 +602,10 @@ static config_var_description_t options_description[] = {
   /* Hidden service options: HiddenService: dir,excludenodes, nodes,
    * options, port.  PublishHidServDescriptor */
 
+  /* Circuit build time histogram options */
+  { "CircuitBuildTimeBin", "Histogram of recent circuit build times"},
+  { "TotalBuildTimes", "Total number of buildtimes in histogram"},
+
   /* Nonpersistent options: __LeaveStreamsUnattached, __AllDirActionsPrivate */
   { NULL, NULL },
 };
@@ -5060,6 +5069,13 @@ or_state_set(or_state_t *new_state)
     log_warn(LD_GENERAL,"Unparseable bandwidth history state: %s",err);
     tor_free(err);
   }
+
+  if(circuit_build_times_parse_state(global_state, &err) < 0)   {
+    log_warn(LD_GENERAL,"%s",err);
+    tor_free(err);
+
+  }
+
 }
 
 /** Reload the persistent state from disk, generating a new state as needed.
@@ -5192,6 +5208,7 @@ or_state_save(time_t now)
    * to avoid redundant writes. */
   entry_guards_update_state(global_state);
   rep_hist_update_state(global_state);
+  circuit_build_times_update_state(global_state);
   if (accounting_is_enabled(get_options()))
     accounting_run_housekeeping(now);
 
diff --git a/src/or/or.h b/src/or/or.h
index 8587ea6..be54ab4 100644
--- a/src/or/or.h
+++ b/src/or/or.h
@@ -1884,6 +1884,13 @@ typedef struct crypt_path_t {
                                  DH_KEY_LEN)
 #define ONIONSKIN_REPLY_LEN (DH_KEY_LEN+DIGEST_LEN)
 
+// XXX: Do we want to artifically tweak CircuitIdleTimeout and
+// the number of circuits we build at a time if < MIN here?
+#define MIN_CIRCUITS_TO_OBSERVE 1000
+#define NCIRCUITS_TO_OBSERVE 10000 /* approx 3 weeks worth of circuits */
+#define BUILDTIME_BIN_WIDTH 50
+
+
 /** Information used to build a circuit. */
 typedef struct {
   /** Intended length of the final circuit. */
@@ -1977,6 +1984,7 @@ typedef struct circuit_t {
   time_t timestamp_created; /**< When was this circuit created? */
   time_t timestamp_dirty; /**< When the circuit was first used, or 0 if the
                            * circuit is clean. */
+  struct timeval highres_created; /**< When exactly was this circuit created? */
 
   uint16_t marked_for_close; /**< Should we close this circuit at the end of
                               * the main loop? (If true, holds the line number
@@ -2683,6 +2691,11 @@ typedef struct {
   int         BWHistoryWriteInterval;
   smartlist_t *BWHistoryWriteValues;
 
+  /** Build time histogram */
+  config_line_t * BuildtimeHistogram;
+  uint16_t TotalBuildTimes;
+
+
   /** What version of Tor wrote this state file? */
   char *TorVersion;
 
@@ -2852,6 +2865,11 @@ void bridges_retry_all(void);
 
 void entry_guards_free_all(void);
 
+void circuit_build_times_update_state(or_state_t *state);
+int  circuit_build_times_parse_state(or_state_t *state, char **msg);
+
+
+
 /********************************* circuitlist.c ***********************/
 
 circuit_t * _circuit_get_global_list(void);
-- 
1.5.6.5




More information about the tor-commits mailing list