Skip to content

Commit 899efd2

Browse files
authored
fix(netcheck): Stable derp-region sorting (#1250)
Make sure derp-regions are always sorted in the same way by using the region id if we don't have any relevant latencies.
1 parent 33464a7 commit 899efd2

1 file changed

Lines changed: 98 additions & 8 deletions

File tree

iroh-net/src/hp/netcheck/reportgen/probes.rs

Lines changed: 98 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -466,22 +466,25 @@ impl DerpNodeCache {
466466
///
467467
/// This uses the latencies from the last report to determine the order. Regions with no
468468
/// data are at the end.
469-
fn sort_regions<'a>(dm: &'a DerpMap, last: &Report) -> Vec<&'a DerpRegion> {
470-
let mut prev: Vec<_> = dm.regions.values().filter(|r| !r.avoid).collect();
469+
fn sort_regions<'a>(derp_map: &'a DerpMap, last_report: &Report) -> Vec<&'a DerpRegion> {
470+
let mut prev: Vec<_> = derp_map.regions.values().filter(|r| !r.avoid).collect();
471471
prev.sort_by(|a, b| {
472-
let da = last.region_latency.get(a.region_id);
473-
let db = last.region_latency.get(b.region_id);
474-
match (da, db) {
472+
let latencies_a = last_report.region_latency.get(a.region_id);
473+
let latencies_b = last_report.region_latency.get(b.region_id);
474+
match (latencies_a, latencies_b) {
475475
(Some(_), None) => {
476476
// Non-zero sorts before zero.
477-
std::cmp::Ordering::Greater
477+
std::cmp::Ordering::Less
478478
}
479479
(None, Some(_)) => {
480480
// Zero can't sort before anything else.
481+
std::cmp::Ordering::Greater
482+
}
483+
(None, None) => {
484+
// For both empty latencies sort by region_id.
481485
a.region_id.cmp(&b.region_id)
482486
}
483-
(None, None) => std::cmp::Ordering::Equal,
484-
(Some(_), Some(_)) => match da.cmp(&db) {
487+
(Some(_), Some(_)) => match latencies_a.cmp(&latencies_b) {
485488
std::cmp::Ordering::Equal => a.region_id.cmp(&b.region_id),
486489
x => x,
487490
},
@@ -883,4 +886,91 @@ mod tests {
883886
assert_eq!(plan.to_string(), expected_plan.to_string(), "{}", i);
884887
}
885888
}
889+
890+
fn create_last_report(latency_1: Option<Duration>, latency_2: Option<Duration>) -> Report {
891+
let mut latencies = RegionLatencies::new();
892+
if let Some(latency_1) = latency_1 {
893+
latencies.update_region(1, latency_1);
894+
}
895+
if let Some(latency_2) = latency_2 {
896+
latencies.update_region(2, latency_2);
897+
}
898+
Report {
899+
udp: true,
900+
ipv6: true,
901+
ipv4: true,
902+
ipv6_can_send: true,
903+
ipv4_can_send: true,
904+
os_has_ipv6: true,
905+
icmpv4: true,
906+
mapping_varies_by_dest_ip: Some(false),
907+
hair_pinning: Some(true),
908+
portmap_probe: None,
909+
preferred_derp: 1,
910+
region_latency: latencies.clone(),
911+
region_v4_latency: latencies.clone(),
912+
region_v6_latency: latencies.clone(),
913+
global_v4: None,
914+
global_v6: None,
915+
captive_portal: None,
916+
}
917+
}
918+
919+
#[test]
920+
fn test_derp_region_sort_two_latencies() {
921+
let derp_map = default_derp_map();
922+
let last_report = create_last_report(
923+
Some(Duration::from_millis(1)),
924+
Some(Duration::from_millis(2)),
925+
);
926+
let sorted: Vec<_> = sort_regions(&derp_map, &last_report)
927+
.iter()
928+
.map(|reg| reg.region_id)
929+
.collect();
930+
assert_eq!(sorted, vec![1, 2]);
931+
}
932+
933+
#[test]
934+
fn test_derp_region_sort_equal_latencies() {
935+
let derp_map = default_derp_map();
936+
let last_report = create_last_report(
937+
Some(Duration::from_millis(2)),
938+
Some(Duration::from_millis(2)),
939+
);
940+
let sorted: Vec<_> = sort_regions(&derp_map, &last_report)
941+
.iter()
942+
.map(|reg| reg.region_id)
943+
.collect();
944+
assert_eq!(sorted, vec![1, 2]);
945+
}
946+
947+
#[test]
948+
fn test_derp_region_sort_missing_latency() {
949+
let derp_map = default_derp_map();
950+
let last_report = create_last_report(None, Some(Duration::from_millis(2)));
951+
let sorted: Vec<_> = sort_regions(&derp_map, &last_report)
952+
.iter()
953+
.map(|reg| reg.region_id)
954+
.collect();
955+
assert_eq!(sorted, vec![2, 1]);
956+
957+
let last_report = create_last_report(Some(Duration::from_millis(2)), None);
958+
let sorted: Vec<_> = sort_regions(&derp_map, &last_report)
959+
.iter()
960+
.map(|reg| reg.region_id)
961+
.collect();
962+
assert_eq!(sorted, vec![1, 2]);
963+
}
964+
965+
#[test]
966+
fn test_derp_region_sort_no_latency() {
967+
let derp_map = default_derp_map();
968+
let last_report = create_last_report(None, None);
969+
let sorted: Vec<_> = sort_regions(&derp_map, &last_report)
970+
.iter()
971+
.map(|reg| reg.region_id)
972+
.collect();
973+
// sorted by region id only
974+
assert_eq!(sorted, vec![1, 2]);
975+
}
886976
}

0 commit comments

Comments
 (0)