Error recovery fixes and routing error rate limiting

- PathBroken handler: convert to async, trigger re-discovery via
  maybe_initiate_lookup(), reset COORDS_PRESENT warmup counter
  (was a stub that only invalidated coord_cache)

- CoordsRequired recovery timing: reset warmup counter in
  handle_lookup_response() when discovery completes for an
  established session, so COORDS_PRESENT packets fire after
  fresh coords are available (not just on CoordsRequired receipt)

- Routing error rate limiting: add RoutingErrorRateLimiter
  (100ms per-destination, matching ICMP PTB pattern) to gate
  send_routing_error() at transit nodes

- Remove root refresh dead code: the 1800s periodic root
  re-announcement in check_tree_state() only propagated to
  depth 1 (sequence-only changes don't cascade). Root loss
  detection relies on link failure propagation which works
  correctly.
This commit is contained in:
Johnathan Corgan
2026-02-17 00:00:04 +00:00
parent 8ca9db7480
commit 3ca2f9500a
8 changed files with 190 additions and 50 deletions
+19 -3
View File
@@ -48,7 +48,7 @@ impl Node {
self.handle_coords_required(inner).await;
}
Some(SessionMessageType::PathBroken) => {
self.handle_path_broken(inner);
self.handle_path_broken(inner).await;
}
None => {
debug!(msg_type, "Unknown session message type");
@@ -360,8 +360,9 @@ impl Node {
/// Handle a PathBroken error signal from a transit router.
///
/// The router has coordinates but still can't route to the destination.
/// Invalidate cached coordinates and consider re-discovery.
fn handle_path_broken(&mut self, inner: &[u8]) {
/// Invalidate cached coordinates, trigger re-discovery, and reset the
/// COORDS_PRESENT warmup counter so the new path gets warmed.
async fn handle_path_broken(&mut self, inner: &[u8]) {
let msg = match PathBroken::decode(inner) {
Ok(m) => m,
Err(e) => {
@@ -378,6 +379,21 @@ impl Node {
// Invalidate stale cached coordinates
self.coord_cache.remove(&msg.dest_addr);
// Trigger re-discovery to get fresh coordinates
self.maybe_initiate_lookup(&msg.dest_addr).await;
// Reset coords warmup counter so the next N packets include
// COORDS_PRESENT, re-warming transit caches along the new path.
if let Some(entry) = self.sessions.get_mut(&msg.dest_addr) {
let n = self.config.node.session.coords_warmup_packets;
entry.set_coords_warmup_remaining(n);
debug!(
dest = %msg.dest_addr,
warmup_packets = n,
"Reset coords warmup counter after PathBroken"
);
}
}
// === Session Initiation (Send Path) ===