|
@@ -884,46 +884,70 @@ router_get_advertised_bandwidth(routerinfo_t *router)
|
|
|
* the advertised bandwidth of each router.
|
|
|
*/
|
|
|
routerinfo_t *
|
|
|
-routerlist_sl_choose_by_bandwidth(smartlist_t *sl)
|
|
|
+routerlist_sl_choose_by_bandwidth(smartlist_t *sl, int for_exit)
|
|
|
{
|
|
|
int i;
|
|
|
routerinfo_t *router;
|
|
|
- smartlist_t *bandwidths;
|
|
|
- uint32_t this_bw, tmp, total_bw=0, rand_bw;
|
|
|
- uint32_t *p;
|
|
|
+ uint32_t *bandwidths;
|
|
|
+ uint32_t this_bw;
|
|
|
+ uint64_t total_nonexit_bw = 0, total_exit_bw = 0, total_bw = 0;
|
|
|
+ uint64_t rand_bw, tmp;
|
|
|
+ double exit_weight;
|
|
|
|
|
|
|
|
|
* of each value. */
|
|
|
- bandwidths = smartlist_create();
|
|
|
+ bandwidths = tor_malloc(sizeof(uint32_t)*smartlist_len(sl));
|
|
|
for (i = 0; i < smartlist_len(sl); ++i) {
|
|
|
router = smartlist_get(sl, i);
|
|
|
this_bw = router_get_advertised_bandwidth(router);
|
|
|
|
|
|
if (this_bw > MAX_BELIEVABLE_BANDWIDTH)
|
|
|
this_bw = MAX_BELIEVABLE_BANDWIDTH;
|
|
|
- p = tor_malloc(sizeof(uint32_t));
|
|
|
- *p = this_bw;
|
|
|
- smartlist_add(bandwidths, p);
|
|
|
- total_bw += this_bw;
|
|
|
+ bandwidths[i] = this_bw;
|
|
|
+ if (router->is_exit)
|
|
|
+ total_exit_bw += this_bw;
|
|
|
+ else
|
|
|
+ total_nonexit_bw += this_bw;
|
|
|
}
|
|
|
- if (!total_bw) {
|
|
|
- SMARTLIST_FOREACH(bandwidths, uint32_t*, p, tor_free(p));
|
|
|
- smartlist_free(bandwidths);
|
|
|
+ if (!(total_exit_bw+total_nonexit_bw)) {
|
|
|
+ tor_free(bandwidths);
|
|
|
return smartlist_choose(sl);
|
|
|
}
|
|
|
+ if (for_exit) {
|
|
|
+ exit_weight = 1.0;
|
|
|
+ total_bw = total_exit_bw + total_nonexit_bw;
|
|
|
+ } else if (total_exit_bw < total_nonexit_bw / 2) {
|
|
|
+ exit_weight = 0.0;
|
|
|
+ total_bw = total_nonexit_bw;
|
|
|
+ } else {
|
|
|
+ uint64_t leftover = (total_exit_bw - total_nonexit_bw / 2);
|
|
|
+ exit_weight = U64_TO_DBL(leftover) /
|
|
|
+ U64_TO_DBL(leftover + total_nonexit_bw);
|
|
|
+ total_bw = total_nonexit_bw +
|
|
|
+ DBL_TO_U64(exit_weight * U64_TO_DBL(total_exit_bw));
|
|
|
+ }
|
|
|
+
|
|
|
+ log_debug(LD_CIRC, "Total bw = "U64_FORMAT", total exit bw = "U64_FORMAT
|
|
|
+ ", total nonexit bw = "U64_FORMAT", exit weight = %lf "
|
|
|
+ "(for exit == %d)",
|
|
|
+ U64_PRINTF_ARG(total_bw), U64_PRINTF_ARG(total_exit_bw),
|
|
|
+ U64_PRINTF_ARG(total_nonexit_bw), exit_weight, for_exit);
|
|
|
+ */
|
|
|
+
|
|
|
|
|
|
- rand_bw = crypto_rand_int(total_bw);
|
|
|
+ rand_bw = crypto_rand_uint64(total_bw);
|
|
|
|
|
|
tmp = 0;
|
|
|
- for (i=0; ; i++) {
|
|
|
- tor_assert(i < smartlist_len(sl));
|
|
|
- p = smartlist_get(bandwidths, i);
|
|
|
- tmp += *p;
|
|
|
+ for (i=0; i < smartlist_len(sl); i++) {
|
|
|
+ router = smartlist_get(sl, i);
|
|
|
+ if (router->is_exit)
|
|
|
+ tmp += ((uint64_t)(bandwidths[i] * exit_weight));
|
|
|
+ else
|
|
|
+ tmp += bandwidths[i];
|
|
|
if (tmp >= rand_bw)
|
|
|
break;
|
|
|
}
|
|
|
- SMARTLIST_FOREACH(bandwidths, uint32_t*, p, tor_free(p));
|
|
|
- smartlist_free(bandwidths);
|
|
|
+ tor_free(bandwidths);
|
|
|
return (routerinfo_t *)smartlist_get(sl, i);
|
|
|
}
|
|
|
|
|
@@ -944,7 +968,8 @@ router_choose_random_node(const char *preferred,
|
|
|
smartlist_t *excludedsmartlist,
|
|
|
int need_uptime, int need_capacity,
|
|
|
int need_guard,
|
|
|
- int allow_invalid, int strict)
|
|
|
+ int allow_invalid, int strict,
|
|
|
+ int weight_for_exit)
|
|
|
{
|
|
|
smartlist_t *sl, *excludednodes;
|
|
|
routerinfo_t *choice = NULL;
|
|
@@ -975,8 +1000,8 @@ router_choose_random_node(const char *preferred,
|
|
|
smartlist_subtract(sl,excludedsmartlist);
|
|
|
routerlist_sl_remove_unreliable_routers(sl, need_uptime,
|
|
|
need_capacity, need_guard);
|
|
|
- if (need_capacity)
|
|
|
- choice = routerlist_sl_choose_by_bandwidth(sl);
|
|
|
+ if (need_capacity)
|
|
|
+ choice = routerlist_sl_choose_by_bandwidth(sl, weight_for_exit);
|
|
|
else
|
|
|
choice = smartlist_choose(sl);
|
|
|
smartlist_free(sl);
|
|
@@ -989,7 +1014,8 @@ router_choose_random_node(const char *preferred,
|
|
|
need_uptime?", stable":"",
|
|
|
need_guard?", guard":"");
|
|
|
choice = router_choose_random_node(
|
|
|
- NULL, excluded, excludedsmartlist, 0, 0, 0, allow_invalid, 0);
|
|
|
+ NULL, excluded, excludedsmartlist,
|
|
|
+ 0, 0, 0, allow_invalid, 0, weight_for_exit);
|
|
|
}
|
|
|
}
|
|
|
smartlist_free(excludednodes);
|
|
@@ -3422,6 +3448,7 @@ routers_update_status_from_networkstatus(smartlist_t *routers,
|
|
|
router->is_fast = rs->status.is_fast;
|
|
|
router->is_stable = rs->status.is_stable;
|
|
|
router->is_possible_guard = rs->status.is_possible_guard;
|
|
|
+ router->is_exit = rs->status.is_exit;
|
|
|
}
|
|
|
if (router->is_running && ds) {
|
|
|
ds->n_networkstatus_failures = 0;
|