backport the load balancing stuff. man, i hope i got all
of this right. other people should check too. svn:r11274
This commit is contained in:
parent
26bdb03d28
commit
7d9051940a
11
ChangeLog
11
ChangeLog
|
@ -4,6 +4,17 @@ Changes in version 0.1.2.17 - 2007-08-xx
|
|||
deprecated since Tor 0.1.1.1-alpha, and keeping it safe and secure
|
||||
has been more of a headache than it's worth.
|
||||
|
||||
o Major bugfixes (load balancing):
|
||||
- When choosing nodes for non-guard positions, weight guards
|
||||
proportionally less, since they already have enough load. Patch
|
||||
from Mike Perry.
|
||||
- Raise the "max believable bandwidth" from 1.5MB/s to 10MB/s. This
|
||||
will allow fast Tor servers to get more attention.
|
||||
- When we're upgrading from an old Tor version, forget our current
|
||||
guards and pick new ones according to the new weightings. These
|
||||
three load balancing patches could raise effective network capacity
|
||||
by a factor of four. Thanks to Mike Perry for measurements.
|
||||
|
||||
o Major bugfixes (stream expiration):
|
||||
- Expire not-yet-successful application streams in all cases if
|
||||
they've been around longer than SocksTimeout. Right now there are
|
||||
|
|
|
@ -1246,7 +1246,7 @@ choose_good_exit_server_general(routerlist_t *dir, int need_uptime,
|
|||
smartlist_subtract(sl,excludedexits);
|
||||
if (options->StrictExitNodes || smartlist_overlap(sl,preferredexits))
|
||||
smartlist_intersect(sl,preferredexits);
|
||||
router = routerlist_sl_choose_by_bandwidth(sl, 1);
|
||||
router = routerlist_sl_choose_by_bandwidth(sl, 1, 0);
|
||||
} else {
|
||||
/* Either there are no pending connections, or no routers even seem to
|
||||
* possibly support any of them. Choose a router at random that satisfies
|
||||
|
@ -1290,7 +1290,7 @@ choose_good_exit_server_general(routerlist_t *dir, int need_uptime,
|
|||
smartlist_intersect(sl,preferredexits);
|
||||
/* XXX sometimes the above results in null, when the requested
|
||||
* exit node is down. we should pick it anyway. */
|
||||
router = routerlist_sl_choose_by_bandwidth(sl, 1);
|
||||
router = routerlist_sl_choose_by_bandwidth(sl, 1, 0);
|
||||
if (router)
|
||||
break;
|
||||
}
|
||||
|
|
|
@ -3994,16 +3994,18 @@ or_state_validate(or_state_t *old_state, or_state_t *state,
|
|||
if (entry_guards_parse_state(state, 0, msg)<0) {
|
||||
return -1;
|
||||
}
|
||||
if (state->TorVersion) {
|
||||
if (state->EntryGuards && state->TorVersion) {
|
||||
tor_version_t v;
|
||||
if (tor_version_parse(state->TorVersion, &v)) {
|
||||
log_warn(LD_GENERAL, "Can't parse Tor version '%s' from your state "
|
||||
"file. Proceeding anyway.", state->TorVersion);
|
||||
} else { /* take action based on v */
|
||||
if (tor_version_as_new_as(state->TorVersion, "0.1.1.10-alpha") &&
|
||||
!tor_version_as_new_as(state->TorVersion, "0.1.1.16-rc-cvs")) {
|
||||
log_notice(LD_CONFIG, "Detected state file from buggy version '%s'. "
|
||||
"Enabling workaround to choose working entry guards.",
|
||||
if ((tor_version_as_new_as(state->TorVersion, "0.1.1.10-alpha") &&
|
||||
!tor_version_as_new_as(state->TorVersion, "0.1.2.17")) ||
|
||||
(tor_version_as_new_as(state->TorVersion, "0.2.0.0-alpha") &&
|
||||
!tor_version_as_new_as(state->TorVersion, "0.2.0.6-alpha"))) {
|
||||
log_notice(LD_CONFIG, "Detected state file from old version '%s'. "
|
||||
"Choosing new entry guards for you.",
|
||||
state->TorVersion);
|
||||
config_free_lines(state->EntryGuards);
|
||||
state->EntryGuards = NULL;
|
||||
|
|
|
@ -2903,7 +2903,8 @@ routerinfo_t *router_find_exact_exit_enclave(const char *address,
|
|||
int router_is_unreliable(routerinfo_t *router, int need_uptime,
|
||||
int need_capacity, int need_guard);
|
||||
uint32_t router_get_advertised_bandwidth(routerinfo_t *router);
|
||||
routerinfo_t *routerlist_sl_choose_by_bandwidth(smartlist_t *sl, int for_exit);
|
||||
routerinfo_t *routerlist_sl_choose_by_bandwidth(smartlist_t *sl, int for_exit,
|
||||
int for_guard);
|
||||
routerstatus_t *routerstatus_sl_choose_by_bandwidth(smartlist_t *sl);
|
||||
|
||||
routerinfo_t *router_choose_random_node(const char *preferred,
|
||||
|
|
|
@ -935,7 +935,7 @@ router_get_advertised_bandwidth(routerinfo_t *router)
|
|||
|
||||
/** Do not weight any declared bandwidth more than this much when picking
|
||||
* routers by bandwidth. */
|
||||
#define MAX_BELIEVABLE_BANDWIDTH 1500000 /* 1.5 MB/sec */
|
||||
#define MAX_BELIEVABLE_BANDWIDTH 10000000 /* 10 MB/sec */
|
||||
|
||||
/** Helper function:
|
||||
* choose a random element of smartlist <b>sl</b>, weighted by
|
||||
|
@ -945,28 +945,35 @@ router_get_advertised_bandwidth(routerinfo_t *router)
|
|||
* routerinfo_t's. Otherwise it's a list of routerstatus_t's.
|
||||
*
|
||||
* If <b>for_exit</b>, we're picking an exit node: consider all nodes'
|
||||
* bandwidth equally regardless of their Exit status. If not <b>for_exit</b>,
|
||||
* bandwidth equally regardless of their Exit status, since there may be
|
||||
* some in the list because they exit to obscure ports. If not <b>for_exit</b>,
|
||||
* we're picking a non-exit node: weight exit-node's bandwidth downwards
|
||||
* depending on the smallness of the fraction of Exit-to-total bandwidth.
|
||||
*
|
||||
* If <b>for_guard</b>, we're picking a guard node: consider all guard's
|
||||
* bandwidth equally. Otherwise, weight guards proportionally less.
|
||||
*/
|
||||
static void *
|
||||
smartlist_choose_by_bandwidth(smartlist_t *sl, int for_exit, int statuses)
|
||||
smartlist_choose_by_bandwidth(smartlist_t *sl, int for_exit, int for_guard,
|
||||
int statuses)
|
||||
{
|
||||
int i;
|
||||
routerinfo_t *router;
|
||||
routerstatus_t *status;
|
||||
routerstatus_t *status=NULL;
|
||||
int32_t *bandwidths;
|
||||
int is_exit;
|
||||
int is_guard;
|
||||
uint64_t total_nonexit_bw = 0, total_exit_bw = 0, total_bw = 0;
|
||||
uint64_t total_nonguard_bw = 0, total_guard_bw = 0;
|
||||
uint64_t rand_bw, tmp;
|
||||
double exit_weight;
|
||||
double guard_weight;
|
||||
int n_unknown = 0;
|
||||
int include_exits = 1;
|
||||
|
||||
/* First count the total bandwidth weight, and make a list
|
||||
* of each value. <0 means "unknown; no routerinfo." We use the
|
||||
* bits of negative values to remember whether the router was fast (-x)&1
|
||||
* and whether it was an exit (-x)&2. Yes, it's a hack. */
|
||||
* and whether it was an exit (-x)&2 or guard (-x)&4. Yes, it's a hack. */
|
||||
bandwidths = tor_malloc(sizeof(int32_t)*smartlist_len(sl));
|
||||
|
||||
/* Iterate over all the routerinfo_t or routerstatus_t, and */
|
||||
|
@ -980,16 +987,19 @@ smartlist_choose_by_bandwidth(smartlist_t *sl, int for_exit, int statuses)
|
|||
status = smartlist_get(sl, i);
|
||||
router = router_get_by_digest(status->identity_digest);
|
||||
is_exit = status->is_exit;
|
||||
is_guard = status->is_possible_guard;
|
||||
if (router) {
|
||||
this_bw = router_get_advertised_bandwidth(router);
|
||||
} else { /* guess */
|
||||
is_known = 0;
|
||||
flags = status->is_fast ? 1 : 0;
|
||||
flags |= is_exit ? 2 : 0;
|
||||
flags |= is_guard ? 4 : 0;
|
||||
}
|
||||
} else {
|
||||
router = smartlist_get(sl, i);
|
||||
is_exit = router->is_exit;
|
||||
is_guard = router->is_possible_guard;
|
||||
this_bw = router_get_advertised_bandwidth(router);
|
||||
}
|
||||
/* if they claim something huge, don't believe it */
|
||||
|
@ -997,6 +1007,10 @@ smartlist_choose_by_bandwidth(smartlist_t *sl, int for_exit, int statuses)
|
|||
this_bw = MAX_BELIEVABLE_BANDWIDTH;
|
||||
if (is_known) {
|
||||
bandwidths[i] = (int32_t) this_bw; // safe since MAX_BELIEVABLE<INT32_MAX
|
||||
if (is_guard)
|
||||
total_guard_bw += this_bw;
|
||||
else
|
||||
total_nonguard_bw += this_bw;
|
||||
if (is_exit)
|
||||
total_exit_bw += this_bw;
|
||||
else
|
||||
|
@ -1025,11 +1039,16 @@ smartlist_choose_by_bandwidth(smartlist_t *sl, int for_exit, int statuses)
|
|||
if (bw>=0)
|
||||
continue;
|
||||
is_exit = ((-bw)&2);
|
||||
is_guard = ((-bw)&4);
|
||||
bandwidths[i] = ((-bw)&1) ? avg_fast : avg_slow;
|
||||
if (is_exit)
|
||||
total_exit_bw += bandwidths[i];
|
||||
else
|
||||
total_nonexit_bw += bandwidths[i];
|
||||
if (is_guard)
|
||||
total_guard_bw += bandwidths[i];
|
||||
else
|
||||
total_nonguard_bw += bandwidths[i];
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1039,41 +1058,53 @@ smartlist_choose_by_bandwidth(smartlist_t *sl, int for_exit, int statuses)
|
|||
return smartlist_choose(sl);
|
||||
}
|
||||
|
||||
/* Figure out how to weight exits. */
|
||||
if (for_exit) {
|
||||
/* If we're choosing an exit node, exit bandwidth counts fully. */
|
||||
exit_weight = 1.0;
|
||||
total_bw = total_exit_bw + total_nonexit_bw;
|
||||
} else {
|
||||
/* Figure out how to weight exits and guards. */
|
||||
{
|
||||
double all_bw = U64_TO_DBL(total_exit_bw+total_nonexit_bw);
|
||||
double exit_bw = U64_TO_DBL(total_exit_bw);
|
||||
double guard_bw = U64_TO_DBL(total_guard_bw);
|
||||
/*
|
||||
* For detailed derivation of this formula, see
|
||||
* http://archives.seul.org/or/dev/Jul-2007/msg00056.html
|
||||
*/
|
||||
exit_weight = 1.0 - all_bw/(3.0*exit_bw);
|
||||
if (exit_weight <= 0.0) {
|
||||
include_exits = 0;
|
||||
if (for_exit)
|
||||
exit_weight = 1.0;
|
||||
else
|
||||
exit_weight = 1.0 - all_bw/(3.0*exit_bw);
|
||||
|
||||
if (for_guard)
|
||||
guard_weight = 1.0;
|
||||
else
|
||||
guard_weight = 1.0 - all_bw/(3.0*guard_bw);
|
||||
|
||||
if (exit_weight <= 0.0)
|
||||
exit_weight = 0.0;
|
||||
total_bw = total_nonexit_bw;
|
||||
} else {
|
||||
include_exits = 1;
|
||||
total_bw = 0;
|
||||
for (i=0; i < smartlist_len(sl); i++) {
|
||||
if (statuses) {
|
||||
status = smartlist_get(sl, i);
|
||||
is_exit = status->is_exit;
|
||||
} else {
|
||||
router = smartlist_get(sl, i);
|
||||
is_exit = router->is_exit;
|
||||
}
|
||||
if (is_exit)
|
||||
total_bw += ((uint64_t)(bandwidths[i] * exit_weight));
|
||||
else
|
||||
total_bw += bandwidths[i];
|
||||
|
||||
if (guard_weight <= 0.0)
|
||||
guard_weight = 0.0;
|
||||
|
||||
total_bw = 0;
|
||||
for (i=0; i < smartlist_len(sl); i++) {
|
||||
if (statuses) {
|
||||
status = smartlist_get(sl, i);
|
||||
is_exit = status->is_exit;
|
||||
is_guard = status->is_possible_guard;
|
||||
} else {
|
||||
router = smartlist_get(sl, i);
|
||||
is_exit = router->is_exit;
|
||||
is_guard = router->is_possible_guard;
|
||||
}
|
||||
if (is_exit && is_guard)
|
||||
total_bw += ((uint64_t)(bandwidths[i] * exit_weight * guard_weight));
|
||||
else if (is_guard)
|
||||
total_bw += ((uint64_t)(bandwidths[i] * guard_weight));
|
||||
else if (is_exit)
|
||||
total_bw += ((uint64_t)(bandwidths[i] * exit_weight));
|
||||
else
|
||||
total_bw += bandwidths[i];
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
log_debug(LD_CIRC, "Total bw = "U64_FORMAT", total exit bw = "U64_FORMAT
|
||||
", total nonexit bw = "U64_FORMAT", exit weight = %lf "
|
||||
|
@ -1091,14 +1122,23 @@ smartlist_choose_by_bandwidth(smartlist_t *sl, int for_exit, int statuses)
|
|||
if (statuses) {
|
||||
status = smartlist_get(sl, i);
|
||||
is_exit = status->is_exit;
|
||||
is_guard = status->is_possible_guard;
|
||||
} else {
|
||||
router = smartlist_get(sl, i);
|
||||
is_exit = router->is_exit;
|
||||
is_guard = router->is_possible_guard;
|
||||
}
|
||||
if (is_exit)
|
||||
|
||||
/* Weights can be 0 if not counting guards/exits */
|
||||
if (is_exit && is_guard)
|
||||
tmp += ((uint64_t)(bandwidths[i] * exit_weight * guard_weight));
|
||||
else if (is_guard)
|
||||
tmp += ((uint64_t)(bandwidths[i] * guard_weight));
|
||||
else if (is_exit)
|
||||
tmp += ((uint64_t)(bandwidths[i] * exit_weight));
|
||||
else
|
||||
tmp += bandwidths[i];
|
||||
|
||||
if (tmp >= rand_bw)
|
||||
break;
|
||||
}
|
||||
|
@ -1116,18 +1156,19 @@ smartlist_choose_by_bandwidth(smartlist_t *sl, int for_exit, int statuses)
|
|||
* the advertised bandwidth of each router.
|
||||
*/
|
||||
routerinfo_t *
|
||||
routerlist_sl_choose_by_bandwidth(smartlist_t *sl, int for_exit)
|
||||
routerlist_sl_choose_by_bandwidth(smartlist_t *sl, int for_exit, int for_guard)
|
||||
{
|
||||
return smartlist_choose_by_bandwidth(sl, for_exit, 0);
|
||||
return smartlist_choose_by_bandwidth(sl, for_exit, for_guard, 0);
|
||||
}
|
||||
|
||||
/** Choose a random element of status list <b>sl</b>, weighted by
|
||||
* the advertised bandwidth of each status.
|
||||
* the advertised bandwidth of each status. Avoid putting load on
|
||||
* exits and guards.
|
||||
*/
|
||||
routerstatus_t *
|
||||
routerstatus_sl_choose_by_bandwidth(smartlist_t *sl)
|
||||
{
|
||||
return smartlist_choose_by_bandwidth(sl, 1, 1);
|
||||
return smartlist_choose_by_bandwidth(sl, 0, 0, 1);
|
||||
}
|
||||
|
||||
/** Return a random running router from the routerlist. If any node
|
||||
|
@ -1184,7 +1225,8 @@ router_choose_random_node(const char *preferred,
|
|||
smartlist_subtract(sl,excludedsmartlist);
|
||||
|
||||
if (need_capacity || need_guard)
|
||||
choice = routerlist_sl_choose_by_bandwidth(sl, weight_for_exit);
|
||||
choice = routerlist_sl_choose_by_bandwidth(sl, weight_for_exit,
|
||||
need_guard);
|
||||
else
|
||||
choice = smartlist_choose(sl);
|
||||
|
||||
|
|
Loading…
Reference in New Issue