mirror of
https://gitlab.torproject.org/tpo/core/tor.git
synced 2024-11-10 13:13:44 +01:00
Clean up Fallon's partially complete GSoC project.
The code actually isn't that bad. It's a shame she didn't finish. Using it as the base for this feature.
This commit is contained in:
parent
2dbf5b7741
commit
7750bee21d
@ -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)
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
|
||||
|
18
src/or/or.h
18
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);
|
||||
|
Loading…
Reference in New Issue
Block a user