mirror of
https://github.com/jmcorgan/fips.git
synced 2026-08-11 17:17:54 +00:00
Promote 27 hardcoded constants to configurable parameters
Add 9 config subsection structs (LimitsConfig, RateLimitConfig, RetryConfig, CacheConfig, DiscoveryConfig, TreeConfig, BloomConfig, SessionConfig, BuffersConfig) under node.* with serde defaults. Wire all configurable values through to consuming code: - Resource limits (max_connections, max_peers, max_links, max_pending_inbound) - Rate limiting (handshake_burst, handshake_rate, handshake_timeout_secs) - Retry/backoff (consolidate max_retries, base_interval_secs under node.retry.*, add max_backoff_secs) - Cache sizes/TTL (coord_size, coord_ttl_secs, route_size) - Discovery (ttl, timeout_secs, recent_expiry_secs) - Spanning tree (root_refresh_secs, announce_min_interval_ms, parent_switch_threshold) - Bloom filter (update_debounce_ms) - Session/data plane (default_hop_limit, pending_packets_per_dest, pending_max_destinations) - Internal buffers (packet_channel, tun_channel, dns_channel) - Network internals (base_rtt_ms, tick_interval_secs) - DNS responder TTL (dns.ttl) REPLAY_WINDOW_SIZE kept as compile-time constant (array sizing). Disable flaky test_discovery_100_nodes (run with --ignored).
This commit is contained in:
@@ -4,7 +4,7 @@
|
||||
//! visited filter for loop prevention, and reverse-path forwarding for
|
||||
//! responses.
|
||||
|
||||
use crate::node::{Node, RecentRequest, DISCOVERY_TTL, LOOKUP_TIMEOUT_MS};
|
||||
use crate::node::{Node, RecentRequest};
|
||||
use crate::protocol::{LookupRequest, LookupResponse};
|
||||
use crate::NodeAddr;
|
||||
use tracing::{debug, trace};
|
||||
@@ -299,13 +299,15 @@ impl Node {
|
||||
/// lookup was recently initiated and hasn't timed out, this is a no-op.
|
||||
pub(in crate::node) async fn maybe_initiate_lookup(&mut self, dest: &NodeAddr) {
|
||||
let now_ms = Self::now_ms();
|
||||
let lookup_timeout_ms = self.config.node.discovery.timeout_secs * 1000;
|
||||
if let Some(&initiated_at) = self.pending_lookups.get(dest) {
|
||||
if now_ms.saturating_sub(initiated_at) < LOOKUP_TIMEOUT_MS {
|
||||
if now_ms.saturating_sub(initiated_at) < lookup_timeout_ms {
|
||||
return;
|
||||
}
|
||||
}
|
||||
self.pending_lookups.insert(*dest, now_ms);
|
||||
self.initiate_lookup(dest, DISCOVERY_TTL).await;
|
||||
let ttl = self.config.node.discovery.ttl;
|
||||
self.initiate_lookup(dest, ttl).await;
|
||||
}
|
||||
|
||||
/// Remove timed-out pending lookups and drain their queued packets.
|
||||
@@ -317,7 +319,7 @@ impl Node {
|
||||
let timed_out: Vec<NodeAddr> = self
|
||||
.pending_lookups
|
||||
.iter()
|
||||
.filter(|&(_, &ts)| now_ms.saturating_sub(ts) >= LOOKUP_TIMEOUT_MS)
|
||||
.filter(|&(_, &ts)| now_ms.saturating_sub(ts) >= self.config.node.discovery.timeout_secs * 1000)
|
||||
.map(|(addr, _)| *addr)
|
||||
.collect();
|
||||
|
||||
@@ -333,8 +335,9 @@ impl Node {
|
||||
|
||||
/// Remove expired entries from the recent_requests cache.
|
||||
fn purge_expired_requests(&mut self, current_time_ms: u64) {
|
||||
let expiry_ms = self.config.node.discovery.recent_expiry_secs * 1000;
|
||||
self.recent_requests
|
||||
.retain(|_, entry| !entry.is_expired(current_time_ms));
|
||||
.retain(|_, entry| !entry.is_expired(current_time_ms, expiry_ms));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -198,7 +198,8 @@ impl Node {
|
||||
CoordsRequired::new(original.dest_addr, my_addr).encode()
|
||||
};
|
||||
|
||||
let error_dg = SessionDatagram::new(my_addr, original.src_addr, error_payload);
|
||||
let error_dg = SessionDatagram::new(my_addr, original.src_addr, error_payload)
|
||||
.with_hop_limit(self.config.node.session.default_hop_limit);
|
||||
|
||||
let next_hop_addr = match self.find_next_hop(&original.src_addr) {
|
||||
Some(peer) => *peer.node_addr(),
|
||||
|
||||
@@ -119,7 +119,7 @@ impl Node {
|
||||
packet.transport_id,
|
||||
packet.remote_addr.clone(),
|
||||
LinkDirection::Inbound,
|
||||
Duration::from_millis(100),
|
||||
Duration::from_millis(self.config.node.base_rtt_ms),
|
||||
);
|
||||
|
||||
self.links.insert(link_id, link);
|
||||
@@ -539,7 +539,7 @@ impl Node {
|
||||
let _ = self.index_allocator.free(old_idx);
|
||||
}
|
||||
|
||||
let new_peer = ActivePeer::with_session(
|
||||
let mut new_peer = ActivePeer::with_session(
|
||||
verified_identity,
|
||||
link_id,
|
||||
current_time_ms,
|
||||
@@ -550,6 +550,7 @@ impl Node {
|
||||
current_addr,
|
||||
link_stats,
|
||||
);
|
||||
new_peer.set_tree_announce_min_interval_ms(self.config.node.tree.announce_min_interval_ms);
|
||||
|
||||
self.peers.insert(peer_node_addr, new_peer);
|
||||
self.peers_by_index
|
||||
@@ -618,7 +619,7 @@ impl Node {
|
||||
return Err(NodeError::MaxPeersExceeded { max: self.max_peers });
|
||||
}
|
||||
|
||||
let new_peer = ActivePeer::with_session(
|
||||
let mut new_peer = ActivePeer::with_session(
|
||||
verified_identity,
|
||||
link_id,
|
||||
current_time_ms,
|
||||
@@ -629,6 +630,7 @@ impl Node {
|
||||
current_addr,
|
||||
link_stats,
|
||||
);
|
||||
new_peer.set_tree_announce_min_interval_ms(self.config.node.tree.announce_min_interval_ms);
|
||||
|
||||
self.peers.insert(peer_node_addr, new_peer);
|
||||
self.peers_by_index
|
||||
|
||||
@@ -51,7 +51,7 @@ impl Node {
|
||||
}
|
||||
};
|
||||
|
||||
let mut tick = tokio::time::interval(Duration::from_secs(1));
|
||||
let mut tick = tokio::time::interval(Duration::from_secs(self.config.node.tick_interval_secs));
|
||||
|
||||
info!("RX event loop started");
|
||||
|
||||
|
||||
@@ -143,7 +143,8 @@ impl Node {
|
||||
let our_coords = self.tree_state.my_coords().clone();
|
||||
let ack = SessionAck::new(our_coords).with_handshake(msg2);
|
||||
let my_addr = *self.node_addr();
|
||||
let datagram = SessionDatagram::new(my_addr, *src_addr, ack.encode());
|
||||
let datagram = SessionDatagram::new(my_addr, *src_addr, ack.encode())
|
||||
.with_hop_limit(self.config.node.session.default_hop_limit);
|
||||
|
||||
// Route the ack back to the initiator
|
||||
if let Err(e) = self.send_session_datagram(&datagram).await {
|
||||
@@ -400,7 +401,8 @@ impl Node {
|
||||
|
||||
// Wrap in SessionDatagram
|
||||
let my_addr = *self.node_addr();
|
||||
let datagram = SessionDatagram::new(my_addr, dest_addr, setup.encode());
|
||||
let datagram = SessionDatagram::new(my_addr, dest_addr, setup.encode())
|
||||
.with_hop_limit(self.config.node.session.default_hop_limit);
|
||||
|
||||
// Route toward destination
|
||||
self.send_session_datagram(&datagram).await?;
|
||||
@@ -450,7 +452,8 @@ impl Node {
|
||||
// Build DataPacket and wrap in SessionDatagram
|
||||
let data_packet = DataPacket::new(ciphertext);
|
||||
let my_addr = *self.node_addr();
|
||||
let datagram = SessionDatagram::new(my_addr, *dest_addr, data_packet.encode());
|
||||
let datagram = SessionDatagram::new(my_addr, *dest_addr, data_packet.encode())
|
||||
.with_hop_limit(self.config.node.session.default_hop_limit);
|
||||
|
||||
self.send_session_datagram(&datagram).await?;
|
||||
|
||||
@@ -514,11 +517,6 @@ impl Node {
|
||||
|
||||
// === TUN Outbound (Data Plane) ===
|
||||
|
||||
/// Maximum pending packets per destination during session establishment.
|
||||
const MAX_PENDING_PER_DEST: usize = 16;
|
||||
/// Maximum destinations with pending packets.
|
||||
const MAX_PENDING_DESTINATIONS: usize = 256;
|
||||
|
||||
/// Handle an outbound IPv6 packet from the TUN reader.
|
||||
///
|
||||
/// Extracts the destination FipsAddress, looks up the NodeAddr and PublicKey
|
||||
@@ -591,8 +589,9 @@ impl Node {
|
||||
/// Queue a packet while waiting for session establishment.
|
||||
fn queue_pending_packet(&mut self, dest_addr: NodeAddr, packet: Vec<u8>) {
|
||||
// Reject if we already have too many pending destinations
|
||||
let max_dests = self.config.node.session.pending_max_destinations;
|
||||
if !self.pending_tun_packets.contains_key(&dest_addr)
|
||||
&& self.pending_tun_packets.len() >= Self::MAX_PENDING_DESTINATIONS
|
||||
&& self.pending_tun_packets.len() >= max_dests
|
||||
{
|
||||
return;
|
||||
}
|
||||
@@ -601,7 +600,7 @@ impl Node {
|
||||
.pending_tun_packets
|
||||
.entry(dest_addr)
|
||||
.or_default();
|
||||
if queue.len() >= Self::MAX_PENDING_PER_DEST {
|
||||
if queue.len() >= self.config.node.session.pending_packets_per_dest {
|
||||
queue.pop_front(); // Drop oldest
|
||||
}
|
||||
queue.push_back(packet);
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
//! Timeout management for stale handshake connections.
|
||||
|
||||
use crate::node::Node;
|
||||
use crate::rate_limit::HANDSHAKE_TIMEOUT_SECS;
|
||||
use crate::transport::LinkId;
|
||||
use tracing::info;
|
||||
|
||||
@@ -9,7 +8,7 @@ impl Node {
|
||||
/// Check for timed-out handshake connections and clean them up.
|
||||
///
|
||||
/// Called periodically by the RX event loop. Removes connections that have
|
||||
/// been idle longer than HANDSHAKE_TIMEOUT_SECS or are in Failed state.
|
||||
/// been idle longer than the configured handshake timeout or are in Failed state.
|
||||
pub(in crate::node) fn check_timeouts(&mut self) {
|
||||
if self.connections.is_empty() {
|
||||
return;
|
||||
@@ -19,7 +18,7 @@ impl Node {
|
||||
.duration_since(std::time::UNIX_EPOCH)
|
||||
.map(|d| d.as_millis() as u64)
|
||||
.unwrap_or(0);
|
||||
let timeout_ms = HANDSHAKE_TIMEOUT_SECS * 1000;
|
||||
let timeout_ms = self.config.node.rate_limit.handshake_timeout_secs * 1000;
|
||||
|
||||
let stale: Vec<LinkId> = self.connections.iter()
|
||||
.filter(|(_, conn)| conn.is_timed_out(now_ms, timeout_ms) || conn.is_failed())
|
||||
|
||||
Reference in New Issue
Block a user