|
@@ -12,6 +12,11 @@
|
|
|
#include "or.h"
|
|
|
|
|
|
|
|
|
+
|
|
|
+
|
|
|
+uint16_t circuit_build_times[NCIRCUITS_TO_OBSERVE];
|
|
|
+int build_times_idx = 0;
|
|
|
+int total_build_times = 0;
|
|
|
|
|
|
|
|
|
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);
|
|
|
+
|
|
|
+ * 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;
|
|
|
+
|
|
|
+ for(i = 0; i < NCIRCUITS_TO_OBSERVE; i++) {
|
|
|
+ if(circuit_build_times[i] == 0) continue;
|
|
|
+
|
|
|
+ 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] &&
|
|
|
+ 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);
|
|
|
+
|
|
|
+ config_free_lines(state->BuildtimeHistogram);
|
|
|
+ next = &state->BuildtimeHistogram;
|
|
|
+ *next = NULL;
|
|
|
+
|
|
|
+ state->TotalBuildTimes = total_build_times;
|
|
|
+
|
|
|
+
|
|
|
+ for(i = 0; i < nbins; i++) {
|
|
|
+ if(histogram[i] == 0) continue;
|
|
|
+ *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)
|
|
|
+{
|
|
|
+ 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;
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
+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;
|
|
|
+
|
|
|
+ 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);
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
|
|
|
* 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);
|
|
|
|
|
|
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)
|