COORDS_PRESENT warmup-then-reactive for DataPackets

Include source and destination coordinates on the first N DataPackets
of each session (default 5, configurable via
node.session.coords_warmup_packets). This warms transit node
coord_caches so multi-hop forwarding and error signal routing work
after SessionSetup cache entries expire.

On CoordsRequired receipt, reset the counter to re-enable coordinate
inclusion for the next N packets, handling mid-session cache expiry
and path changes.

Changes:
- SessionConfig: add coords_warmup_packets field (default 5)
- SessionEntry: add coords_warmup_remaining counter, initialized on
  Established transition (both initiator and responder paths)
- send_session_data(): attach coords via DataPacket::with_coords()
  while counter > 0, decrement per send
- handle_coords_required(): reset counter for affected session
- 4 new unit tests for counter lifecycle and config default
This commit is contained in:
Johnathan Corgan
2026-02-16 23:28:24 +00:00
parent f374370e5c
commit 1f60fbd7a2
4 changed files with 135 additions and 2 deletions
+28 -2
View File
@@ -211,6 +211,7 @@ impl Node {
};
entry.set_state(EndToEndState::Established(session));
entry.set_coords_warmup_remaining(self.config.node.session.coords_warmup_packets);
entry.touch(Self::now_ms());
self.sessions.insert(*src_addr, entry);
@@ -278,6 +279,7 @@ impl Node {
}
};
entry.set_state(EndToEndState::Established(noise_session));
entry.set_coords_warmup_remaining(self.config.node.session.coords_warmup_packets);
debug!(src = %src_addr, "Session established (responder, on first data)");
}
@@ -341,6 +343,18 @@ impl Node {
);
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 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 CoordsRequired"
);
}
}
/// Handle a PathBroken error signal from a transit router.
@@ -449,8 +463,20 @@ impl Node {
reason: format!("session encrypt failed: {}", e),
})?;
// Build DataPacket and wrap in SessionDatagram
let data_packet = DataPacket::new(ciphertext);
// Check warmup counter and decrement (while entry is still borrowed)
let include_coords = entry.coords_warmup_remaining() > 0;
if include_coords {
entry.set_coords_warmup_remaining(entry.coords_warmup_remaining() - 1);
}
// Build DataPacket, conditionally with coordinates
let mut data_packet = DataPacket::new(ciphertext);
if include_coords {
let my_coords = self.tree_state.my_coords().clone();
let dest_coords = self.get_dest_coords(dest_addr);
data_packet = data_packet.with_coords(my_coords, dest_coords);
}
let my_addr = *self.node_addr();
let datagram = SessionDatagram::new(my_addr, *dest_addr, data_packet.encode())
.with_hop_limit(self.config.node.session.default_hop_limit);