From 6b939f2c73e8909e0a2270e99d934be90181dfd1 Mon Sep 17 00:00:00 2001 From: tv Date: Sat, 31 Oct 2026 12:17:13 +0100 Subject: contradicting clock samples replace stored ones --- src/transport/paths.rs | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-) (limited to 'src/transport/paths.rs') diff --git a/src/transport/paths.rs b/src/transport/paths.rs index 6512759..2ef3a12 100644 --- a/src/transport/paths.rs +++ b/src/transport/paths.rs @@ -107,7 +107,7 @@ const SWITCH_MIN: Duration = Duration::from_millis(5); /// Paths kept at most: they are of peers this node chose among, but bounded anyway. const MAX_PATHS: usize = 4096; /// A path's clock sample with the narrowest bound is kept this long at most; then the -/// next one takes its place, so a clock that was set anew shows within this time. +/// next one takes its place. (A clock set anew shows at once: `Table::clock`.) const CLOCK_KEPT: Duration = Duration::from_secs(300); /// How far a peer's clock is ahead of ours (behind if negative), from a PING and its @@ -395,14 +395,18 @@ impl Table { } /// A clock sample from a PONG over `address`: kept if its bound is as narrow as the - /// one kept, or that one is older than `CLOCK_KEPT`. The narrowest bound is the + /// one kept, or that one is older than `CLOCK_KEPT`, or the two can't both be right + /// (their bounds don't overlap: a clock was set anew). The narrowest bound is the /// round trip least delayed by queues and relays. fn clock(&mut self, address: &str, offset: ClockOffset, now: Instant) { let Some(path) = self.paths.get_mut(address) else { return; }; let replaces = path.clock.is_none_or(|(kept, at)| { - offset.within_ms <= kept.within_ms || now.saturating_duration_since(at) >= CLOCK_KEPT + offset.within_ms <= kept.within_ms + || now.saturating_duration_since(at) >= CLOCK_KEPT + || offset.offset_ms.abs_diff(kept.offset_ms) + > offset.within_ms.saturating_add(kept.within_ms) }); if replaces { path.clock = Some((offset, now)); @@ -1224,6 +1228,14 @@ mod tests { table.paths["libp2p:z"].clock.map(|(kept, _)| kept), Some(wider) ); + // A clock set anew: a sample the kept one contradicts takes its place at once, + // its bound wider or not. + let set_anew = ClockOffset::of(UnixMillis(25_000), heard, rtt * 8); + table.clock("libp2p:z", set_anew, now + CLOCK_KEPT); + assert_eq!( + table.paths["libp2p:z"].clock.map(|(kept, _)| kept), + Some(set_anew) + ); } /// A peer's only path is measured too once messages go over it, unless its -- cgit v1.3.1