[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