|
@@ -2003,6 +2003,7 @@ compute_weighted_bandwidths(const smartlist_t *sl,
|
|
|
double Wg = -1, Wm = -1, We = -1, Wd = -1;
|
|
|
double Wgb = -1, Wmb = -1, Web = -1, Wdb = -1;
|
|
|
uint64_t weighted_bw = 0;
|
|
|
+ guardfraction_bandwidth_t guardfraction_bw;
|
|
|
u64_dbl_t *bandwidths;
|
|
|
|
|
|
/* Can't choose exit and guard at same time */
|
|
@@ -2092,6 +2093,8 @@ compute_weighted_bandwidths(const smartlist_t *sl,
|
|
|
SMARTLIST_FOREACH_BEGIN(sl, const node_t *, node) {
|
|
|
int is_exit = 0, is_guard = 0, is_dir = 0, this_bw = 0;
|
|
|
double weight = 1;
|
|
|
+ double weight_without_guard_flag = 0; /* Used for guardfraction */
|
|
|
+ double final_weight = 0;
|
|
|
is_exit = node->is_exit && ! node->is_bad_exit;
|
|
|
is_guard = node->is_possible_guard;
|
|
|
is_dir = node_is_dir(node);
|
|
@@ -2119,8 +2122,10 @@ compute_weighted_bandwidths(const smartlist_t *sl,
|
|
|
|
|
|
if (is_guard && is_exit) {
|
|
|
weight = (is_dir ? Wdb*Wd : Wd);
|
|
|
+ weight_without_guard_flag = (is_dir ? Web*We : We);
|
|
|
} else if (is_guard) {
|
|
|
weight = (is_dir ? Wgb*Wg : Wg);
|
|
|
+ weight_without_guard_flag = (is_dir ? Wmb*Wm : Wm);
|
|
|
} else if (is_exit) {
|
|
|
weight = (is_dir ? Web*We : We);
|
|
|
} else { // middle
|
|
@@ -2132,8 +2137,43 @@ compute_weighted_bandwidths(const smartlist_t *sl,
|
|
|
this_bw = 0;
|
|
|
if (weight < 0.0)
|
|
|
weight = 0.0;
|
|
|
+ if (weight_without_guard_flag < 0.0)
|
|
|
+ weight_without_guard_flag = 0.0;
|
|
|
|
|
|
- bandwidths[node_sl_idx].dbl = weight*this_bw + 0.5;
|
|
|
+ /* If guardfraction information is available in the consensus, we
|
|
|
+ * want to calculate this router's bandwidth according to its
|
|
|
+ * guardfraction. Quoting from proposal236:
|
|
|
+ *
|
|
|
+ * Let Wpf denote the weight from the 'bandwidth-weights' line a
|
|
|
+ * client would apply to N for position p if it had the guard
|
|
|
+ * flag, Wpn the weight if it did not have the guard flag, and B the
|
|
|
+ * measured bandwidth of N in the consensus. Then instead of choosing
|
|
|
+ * N for position p proportionally to Wpf*B or Wpn*B, clients should
|
|
|
+ * choose N proportionally to F*Wpf*B + (1-F)*Wpn*B.
|
|
|
+ */
|
|
|
+ if (node->rs && node->rs->has_guardfraction && rule != WEIGHT_FOR_GUARD) {
|
|
|
+ /* XXX The assert should actually check for is_guard. However,
|
|
|
+ * that crashes dirauths because of #13297. This should be
|
|
|
+ * equivalent: */
|
|
|
+ tor_assert(node->rs->is_possible_guard);
|
|
|
+
|
|
|
+ guard_get_guardfraction_bandwidth(&guardfraction_bw,
|
|
|
+ this_bw,
|
|
|
+ node->rs->guardfraction_percentage);
|
|
|
+
|
|
|
+ /* Calculate final_weight = F*Wpf*B + (1-F)*Wpn*B */
|
|
|
+ final_weight =
|
|
|
+ guardfraction_bw.guard_bw * weight +
|
|
|
+ guardfraction_bw.non_guard_bw * weight_without_guard_flag;
|
|
|
+
|
|
|
+ log_warn(LD_GENERAL, "%s: Guardfraction weight %f instead of %f (%s)",
|
|
|
+ node->rs->nickname, final_weight, weight*this_bw,
|
|
|
+ bandwidth_weight_rule_to_string(rule));
|
|
|
+ } else { /* no guardfraction information. calculate the weight normally. */
|
|
|
+ final_weight = weight*this_bw;
|
|
|
+ }
|
|
|
+
|
|
|
+ bandwidths[node_sl_idx].dbl = final_weight + 0.5;
|
|
|
} SMARTLIST_FOREACH_END(node);
|
|
|
|
|
|
log_debug(LD_CIRC, "Generated weighted bandwidths for rule %s based "
|