Use a better calculation for deciding if we have enough paths.

This commit is contained in:
Nick Mathewson 2020-12-02 14:09:33 -05:00
parent 412f1763de
commit 6f25dd05af
2 changed files with 62 additions and 12 deletions

View File

@ -176,22 +176,41 @@ impl NetDir {
pub fn relays(&self) -> impl Iterator<Item = Relay<'_>> {
self.all_relays().filter_map(UncheckedRelay::into_relay)
}
/// Return true if there is enough information in this NetDir to build
/// multihop circuits.
fn have_enough_paths(&self) -> bool {
// TODO: Implement the real path-based algorithm.
let mut total_bw = 0_u64;
let mut have_bw = 0_u64;
/// Return the fraction of total bandwidth weight for a given role
/// that we have available information for in this NetDir.
fn frac_for_role(&self, role: WeightRole) -> f64 {
let mut total_weight = 0_u64;
let mut have_weight = 0_u64;
for r in self.all_relays() {
let w = self.weights.weight_rs_for_role(&r.rs, WeightRole::Middle);
total_bw += w;
let w = self.weights.weight_rs_for_role(&r.rs, role);
total_weight += w;
if r.is_usable() {
have_bw += w;
have_weight += w
}
}
// TODO: Do a real calculation here.
have_bw > (total_bw / 2)
(have_weight as f64) / (total_weight as f64)
}
/// Return true if there is enough information in this NetDir to build
/// multihop circuits.
fn have_enough_paths(&self) -> bool {
// If we can build a randomly chosen path with at least this
// probability, we know enough information to participate
// on the network.
let min_pct = self
.consensus
.params()
.get_clamped("min_paths_for_circs_pct", 25, 95)
.unwrap_or(60);
let min_frac_paths = (min_pct as f64) / 100.0;
// What fraction of paths can we build?
let available = self.frac_for_role(WeightRole::Guard)
* self.frac_for_role(WeightRole::Middle)
* self.frac_for_role(WeightRole::Exit);
available >= min_frac_paths
}
/// Chose a relay at random.
///

View File

@ -136,7 +136,33 @@ impl<T> NetParams<T> {
self.params.get(v.as_ref())
}
}
impl<T> NetParams<T>
where
T: Copy + Clone,
{
/// Return a given network parameter by value, if it is present.
pub fn get_val<A: AsRef<str>>(&self, v: A) -> Option<T> {
self.get(v).map(T::clone)
}
}
impl<T> NetParams<T>
where
T: Copy + Clone + PartialOrd,
{
/// Return a given network parameter by value, if it is
/// present. Clamp it so that it lies within the range `low..=high`.
pub fn get_clamped<A: AsRef<str>>(&self, v: A, low: T, high: T) -> Option<T> {
self.get_val(v).map(|x| {
if x < low {
low
} else if x > high {
high
} else {
x
}
})
}
}
/// A list of subprotocol versions that implementors should/must provide.
#[allow(dead_code)]
#[derive(Debug, Clone)]
@ -477,6 +503,11 @@ impl MDConsensus {
pub fn bandwidth_weights(&self) -> &NetParams<i32> {
&self.footer.weights
}
/// Return the map of network parameters that this consensus advertises.
pub fn params(&self) -> &NetParams<u32> {
&self.header.hdr.params
}
}
decl_keyword! {