Allow consensus interval of 10 seconds when testing

Decrease minimum consensus interval to 10 seconds
when TestingTorNetwork is set. (Or 5 seconds for
the first consensus.)

Fix code that assumes larger interval values.

This assists in quickly bootstrapping a testing
Tor network.

Fixes bugs 13718 & 13823.
This commit is contained in:
teor 2014-12-20 21:53:00 +11:00
parent 083c58f126
commit 1ee41b3eef
8 changed files with 160 additions and 21 deletions

View File

@ -0,0 +1,8 @@
o Minor bugfixes:
- Decrease minimum consensus interval to 10 seconds
when TestingTorNetwork is set. (Or 5 seconds for
the first consensus.)
Fix code that assumes larger interval values.
This assists in quickly bootstrapping a testing
Tor network.
Fixes bugs 13718 & 13823.

View File

@ -468,7 +468,7 @@ static const config_var_t testing_tor_network_defaults[] = {
V(V3AuthVotingInterval, INTERVAL, "5 minutes"), V(V3AuthVotingInterval, INTERVAL, "5 minutes"),
V(V3AuthVoteDelay, INTERVAL, "20 seconds"), V(V3AuthVoteDelay, INTERVAL, "20 seconds"),
V(V3AuthDistDelay, INTERVAL, "20 seconds"), V(V3AuthDistDelay, INTERVAL, "20 seconds"),
V(TestingV3AuthInitialVotingInterval, INTERVAL, "5 minutes"), V(TestingV3AuthInitialVotingInterval, INTERVAL, "150 seconds"),
V(TestingV3AuthInitialVoteDelay, INTERVAL, "20 seconds"), V(TestingV3AuthInitialVoteDelay, INTERVAL, "20 seconds"),
V(TestingV3AuthInitialDistDelay, INTERVAL, "20 seconds"), V(TestingV3AuthInitialDistDelay, INTERVAL, "20 seconds"),
V(TestingV3AuthVotingStartOffset, INTERVAL, "0"), V(TestingV3AuthVotingStartOffset, INTERVAL, "0"),
@ -3397,19 +3397,68 @@ options_validate(or_options_t *old_options, or_options_t *options,
if (options->V3AuthVoteDelay + options->V3AuthDistDelay >= if (options->V3AuthVoteDelay + options->V3AuthDistDelay >=
options->V3AuthVotingInterval/2) { options->V3AuthVotingInterval/2) {
REJECT("V3AuthVoteDelay plus V3AuthDistDelay must be less than half " /*
"V3AuthVotingInterval"); This doesn't work, but it seems like it should:
what code is preventing the interval being less than twice the lead-up?
if (options->TestingTorNetwork) {
if (options->V3AuthVoteDelay + options->V3AuthDistDelay >=
options->V3AuthVotingInterval) {
REJECT("V3AuthVoteDelay plus V3AuthDistDelay must be less than "
"V3AuthVotingInterval");
} else {
COMPLAIN("V3AuthVoteDelay plus V3AuthDistDelay is more than half "
"V3AuthVotingInterval. This may lead to "
"consensus instability, particularly if clocks drift.");
}
} else {
*/
REJECT("V3AuthVoteDelay plus V3AuthDistDelay must be less than half "
"V3AuthVotingInterval");
/*
}
*/
}
if (options->V3AuthVoteDelay < MIN_VOTE_SECONDS) {
if (options->TestingTorNetwork) {
if (options->V3AuthVoteDelay < MIN_VOTE_SECONDS_TESTING) {
REJECT("V3AuthVoteDelay is way too low.");
} else {
COMPLAIN("V3AuthVoteDelay is very low. "
"This may lead to failure to vote for a consensus.");
}
} else {
REJECT("V3AuthVoteDelay is way too low.");
}
}
if (options->V3AuthDistDelay < MIN_DIST_SECONDS) {
if (options->TestingTorNetwork) {
if (options->V3AuthDistDelay < MIN_DIST_SECONDS_TESTING) {
REJECT("V3AuthDistDelay is way too low.");
} else {
COMPLAIN("V3AuthDistDelay is very low. "
"This may lead to missing votes in a consensus.");
}
} else {
REJECT("V3AuthDistDelay is way too low.");
}
} }
if (options->V3AuthVoteDelay < MIN_VOTE_SECONDS)
REJECT("V3AuthVoteDelay is way too low.");
if (options->V3AuthDistDelay < MIN_DIST_SECONDS)
REJECT("V3AuthDistDelay is way too low.");
if (options->V3AuthNIntervalsValid < 2) if (options->V3AuthNIntervalsValid < 2)
REJECT("V3AuthNIntervalsValid must be at least 2."); REJECT("V3AuthNIntervalsValid must be at least 2.");
if (options->V3AuthVotingInterval < MIN_VOTE_INTERVAL) { if (options->V3AuthVotingInterval < MIN_VOTE_INTERVAL) {
REJECT("V3AuthVotingInterval is insanely low."); if (options->TestingTorNetwork) {
if (options->V3AuthVotingInterval < MIN_VOTE_INTERVAL_TESTING) {
REJECT("V3AuthVotingInterval is insanely low.");
} else {
COMPLAIN("V3AuthVotingInterval is very low. "
"This may lead to failure to synchronise for a consensus.");
}
} else {
REJECT("V3AuthVotingInterval is insanely low.");
}
} else if (options->V3AuthVotingInterval > 24*60*60) { } else if (options->V3AuthVotingInterval > 24*60*60) {
REJECT("V3AuthVotingInterval is insanely high."); REJECT("V3AuthVotingInterval is insanely high.");
} else if (((24*60*60) % options->V3AuthVotingInterval) != 0) { } else if (((24*60*60) % options->V3AuthVotingInterval) != 0) {
@ -3484,26 +3533,27 @@ options_validate(or_options_t *old_options, or_options_t *options,
CHECK_DEFAULT(TestingCertMaxDownloadTries); CHECK_DEFAULT(TestingCertMaxDownloadTries);
#undef CHECK_DEFAULT #undef CHECK_DEFAULT
if (options->TestingV3AuthInitialVotingInterval < MIN_VOTE_INTERVAL) { if (options->TestingV3AuthInitialVotingInterval
< MIN_VOTE_INTERVAL_TESTING_INITIAL) {
REJECT("TestingV3AuthInitialVotingInterval is insanely low."); REJECT("TestingV3AuthInitialVotingInterval is insanely low.");
} else if (((30*60) % options->TestingV3AuthInitialVotingInterval) != 0) { } else if (((30*60) % options->TestingV3AuthInitialVotingInterval) != 0) {
REJECT("TestingV3AuthInitialVotingInterval does not divide evenly into " REJECT("TestingV3AuthInitialVotingInterval does not divide evenly into "
"30 minutes."); "30 minutes.");
} }
if (options->TestingV3AuthInitialVoteDelay < MIN_VOTE_SECONDS) { if (options->TestingV3AuthInitialVoteDelay < MIN_VOTE_SECONDS_TESTING) {
REJECT("TestingV3AuthInitialVoteDelay is way too low."); REJECT("TestingV3AuthInitialVoteDelay is way too low.");
} }
if (options->TestingV3AuthInitialDistDelay < MIN_DIST_SECONDS) { if (options->TestingV3AuthInitialDistDelay < MIN_DIST_SECONDS_TESTING) {
REJECT("TestingV3AuthInitialDistDelay is way too low."); REJECT("TestingV3AuthInitialDistDelay is way too low.");
} }
if (options->TestingV3AuthInitialVoteDelay + if (options->TestingV3AuthInitialVoteDelay +
options->TestingV3AuthInitialDistDelay >= options->TestingV3AuthInitialDistDelay >=
options->TestingV3AuthInitialVotingInterval/2) { options->TestingV3AuthInitialVotingInterval) {
REJECT("TestingV3AuthInitialVoteDelay plus TestingV3AuthInitialDistDelay " REJECT("TestingV3AuthInitialVoteDelay plus TestingV3AuthInitialDistDelay "
"must be less than half TestingV3AuthInitialVotingInterval"); "must be less than TestingV3AuthInitialVotingInterval");
} }
if (options->TestingV3AuthVotingStartOffset > if (options->TestingV3AuthVotingStartOffset >
@ -3511,6 +3561,8 @@ options_validate(or_options_t *old_options, or_options_t *options,
options->V3AuthVotingInterval)) { options->V3AuthVotingInterval)) {
REJECT("TestingV3AuthVotingStartOffset is higher than the voting " REJECT("TestingV3AuthVotingStartOffset is higher than the voting "
"interval."); "interval.");
} else if (options->TestingV3AuthVotingStartOffset < 0) {
REJECT("TestingV3AuthVotingStartOffset must be non-negative.");
} }
if (options->TestingAuthDirTimeToLearnReachability < 0) { if (options->TestingAuthDirTimeToLearnReachability < 0) {

View File

@ -1107,8 +1107,12 @@ networkstatus_compute_consensus(smartlist_t *votes,
vote_seconds = median_int(votesec_list, n_votes); vote_seconds = median_int(votesec_list, n_votes);
dist_seconds = median_int(distsec_list, n_votes); dist_seconds = median_int(distsec_list, n_votes);
tor_assert(valid_after+MIN_VOTE_INTERVAL <= fresh_until); tor_assert(valid_after +
tor_assert(fresh_until+MIN_VOTE_INTERVAL <= valid_until); (get_options()->TestingTorNetwork ?
MIN_VOTE_INTERVAL_TESTING : MIN_VOTE_INTERVAL) <= fresh_until);
tor_assert(fresh_until +
(get_options()->TestingTorNetwork ?
MIN_VOTE_INTERVAL_TESTING : MIN_VOTE_INTERVAL) <= valid_until);
tor_assert(vote_seconds >= MIN_VOTE_SECONDS); tor_assert(vote_seconds >= MIN_VOTE_SECONDS);
tor_assert(dist_seconds >= MIN_DIST_SECONDS); tor_assert(dist_seconds >= MIN_DIST_SECONDS);

View File

@ -14,12 +14,42 @@
#include "testsupport.h" #include "testsupport.h"
/*
* Ideally, assuming synced clocks, we should only need 1 second for each of:
* - Vote
* - Distribute
* - Consensus Publication
* As we can gather descriptors continuously.
* (Could we even go as far as publishing the previous consensus,
* in the same second that we vote for the next one?)
* But we're not there yet: these are the lowest working values at this time.
*/
/** Lowest allowable value for VoteSeconds. */ /** Lowest allowable value for VoteSeconds. */
#define MIN_VOTE_SECONDS 2 #define MIN_VOTE_SECONDS 2
/** Lowest allowable value for VoteSeconds when TestingTorNetwork is 1 */
#define MIN_VOTE_SECONDS_TESTING 2
/** Lowest allowable value for DistSeconds. */ /** Lowest allowable value for DistSeconds. */
#define MIN_DIST_SECONDS 2 #define MIN_DIST_SECONDS 2
/** Smallest allowable voting interval. */ /** Lowest allowable value for DistSeconds when TestingTorNetwork is 1 */
#define MIN_DIST_SECONDS_TESTING 2
/** Lowest allowable voting interval. */
#define MIN_VOTE_INTERVAL 300 #define MIN_VOTE_INTERVAL 300
/** Lowest allowable voting interval when TestingTorNetwork is 1:
* Voting Interval can be:
* 10, 12, 15, 18, 20, 24, 25, 30, 36, 40, 45, 50, 60, ...
* Testing Initial Voting Interval can be:
* 5, 6, 8, 9, or any of the possible values for Voting Interval,
* as they both need to evenly divide 30 minutes.
* If clock desynchronisation is an issue, use an interval of at least:
* 18 * drift in seconds, to allow for a clock slop factor */
#define MIN_VOTE_INTERVAL_TESTING \
(((MIN_VOTE_SECONDS_TESTING)+(MIN_DIST_SECONDS_TESTING)+1)*2)
#define MIN_VOTE_INTERVAL_TESTING_INITIAL \
((MIN_VOTE_SECONDS_TESTING)+(MIN_DIST_SECONDS_TESTING)+1)
/** The lowest consensus method that we currently support. */ /** The lowest consensus method that we currently support. */
#define MIN_SUPPORTED_CONSENSUS_METHOD 13 #define MIN_SUPPORTED_CONSENSUS_METHOD 13

View File

@ -832,6 +832,10 @@ update_consensus_networkstatus_fetch_time_impl(time_t now, int flav)
a crazy-fast voting interval, though, 2 minutes may be too a crazy-fast voting interval, though, 2 minutes may be too
much. */ much. */
min_sec_before_caching = interval/16; min_sec_before_caching = interval/16;
/* make sure we always delay by at least a second before caching */
if (min_sec_before_caching == 0) {
min_sec_before_caching = 1;
}
} }
if (directory_fetches_dir_info_early(options)) { if (directory_fetches_dir_info_early(options)) {
@ -863,8 +867,16 @@ update_consensus_networkstatus_fetch_time_impl(time_t now, int flav)
dl_interval = (c->valid_until - start) - min_sec_before_caching; dl_interval = (c->valid_until - start) - min_sec_before_caching;
} }
} }
/* catch low dl_interval in crazy-fast networks */
if (dl_interval < 1) if (dl_interval < 1)
dl_interval = 1; dl_interval = 1;
/* catch late start in crazy-fast networks */
if (start+dl_interval >= c->valid_until)
start = c->valid_until - dl_interval - 1;
log_debug(LD_DIR,
"fresh_until: %ld start: %ld "
"dl_interval: %ld valid_until: %ld ",
c->fresh_until, start, dl_interval, c->valid_until);
/* We must not try to replace c while it's still fresh: */ /* We must not try to replace c while it's still fresh: */
tor_assert(c->fresh_until < start); tor_assert(c->fresh_until < start);
/* We must download the next one before c is invalid: */ /* We must download the next one before c is invalid: */

View File

@ -1223,6 +1223,11 @@ router_orport_found_reachable(void)
" Publishing server descriptor." : ""); " Publishing server descriptor." : "");
can_reach_or_port = 1; can_reach_or_port = 1;
mark_my_descriptor_dirty("ORPort found reachable"); mark_my_descriptor_dirty("ORPort found reachable");
/* This is a significant enough change to upload immediately,
* at least in a test network */
if (get_options()->TestingTorNetwork == 1) {
reschedule_descriptor_update_check();
}
control_event_server_status(LOG_NOTICE, control_event_server_status(LOG_NOTICE,
"REACHABILITY_SUCCEEDED ORADDRESS=%s:%d", "REACHABILITY_SUCCEEDED ORADDRESS=%s:%d",
address, me->or_port); address, me->or_port);
@ -1240,8 +1245,14 @@ router_dirport_found_reachable(void)
log_notice(LD_DIRSERV,"Self-testing indicates your DirPort is reachable " log_notice(LD_DIRSERV,"Self-testing indicates your DirPort is reachable "
"from the outside. Excellent."); "from the outside. Excellent.");
can_reach_dir_port = 1; can_reach_dir_port = 1;
if (decide_to_advertise_dirport(get_options(), me->dir_port)) if (decide_to_advertise_dirport(get_options(), me->dir_port)) {
mark_my_descriptor_dirty("DirPort found reachable"); mark_my_descriptor_dirty("DirPort found reachable");
/* This is a significant enough change to upload immediately,
* at least in a test network */
if (get_options()->TestingTorNetwork == 1) {
reschedule_descriptor_update_check();
}
}
control_event_server_status(LOG_NOTICE, control_event_server_status(LOG_NOTICE,
"REACHABILITY_SUCCEEDED DIRADDRESS=%s:%d", "REACHABILITY_SUCCEEDED DIRADDRESS=%s:%d",
address, me->dir_port); address, me->dir_port);

View File

@ -2210,11 +2210,29 @@ router_choose_random_node(smartlist_t *excludedsmartlist,
router_add_running_nodes_to_smartlist(sl, allow_invalid, router_add_running_nodes_to_smartlist(sl, allow_invalid,
need_uptime, need_capacity, need_uptime, need_capacity,
need_guard, need_desc); need_guard, need_desc);
log_debug(LD_CIRC,
"We found %d running nodes.",
smartlist_len(sl));
smartlist_subtract(sl,excludednodes); smartlist_subtract(sl,excludednodes);
if (excludedsmartlist) log_debug(LD_CIRC,
"We removed %d excludednodes, leaving %d nodes.",
smartlist_len(excludednodes),
smartlist_len(sl));
if (excludedsmartlist) {
smartlist_subtract(sl,excludedsmartlist); smartlist_subtract(sl,excludedsmartlist);
if (excludedset) log_debug(LD_CIRC,
"We removed %d excludedsmartlist, leaving %d nodes.",
smartlist_len(excludedsmartlist),
smartlist_len(sl));
}
if (excludedset) {
routerset_subtract_nodes(sl,excludedset); routerset_subtract_nodes(sl,excludedset);
log_debug(LD_CIRC,
"We removed excludedset, leaving %d nodes.",
smartlist_len(sl));
}
// Always weight by bandwidth // Always weight by bandwidth
choice = node_sl_choose_by_bandwidth(sl, rule); choice = node_sl_choose_by_bandwidth(sl, rule);

View File

@ -2598,11 +2598,15 @@ networkstatus_parse_vote_from_string(const char *s, const char **eos_out,
(int) tor_parse_long(tok->args[1], 10, 0, INT_MAX, &ok, NULL); (int) tor_parse_long(tok->args[1], 10, 0, INT_MAX, &ok, NULL);
if (!ok) if (!ok)
goto err; goto err;
if (ns->valid_after + MIN_VOTE_INTERVAL > ns->fresh_until) { if (ns->valid_after +
(get_options()->TestingTorNetwork ?
MIN_VOTE_INTERVAL_TESTING : MIN_VOTE_INTERVAL) > ns->fresh_until) {
log_warn(LD_DIR, "Vote/consensus freshness interval is too short"); log_warn(LD_DIR, "Vote/consensus freshness interval is too short");
goto err; goto err;
} }
if (ns->valid_after + MIN_VOTE_INTERVAL*2 > ns->valid_until) { if (ns->valid_after +
(get_options()->TestingTorNetwork ?
MIN_VOTE_INTERVAL_TESTING : MIN_VOTE_INTERVAL)*2 > ns->valid_until) {
log_warn(LD_DIR, "Vote/consensus liveness interval is too short"); log_warn(LD_DIR, "Vote/consensus liveness interval is too short");
goto err; goto err;
} }