mirror of
https://github.com/jmcorgan/fips.git
synced 2026-08-09 16:24:45 +00:00
Merge branch 'master' into next
This commit is contained in:
@@ -618,7 +618,7 @@ impl Node {
|
||||
}
|
||||
|
||||
/// Tracks a pending discovery lookup with retry state.
|
||||
pub(crate) struct PendingLookup {
|
||||
pub struct PendingLookup {
|
||||
/// When the lookup was first initiated.
|
||||
pub initiated_ms: u64,
|
||||
/// When the last attempt was sent.
|
||||
|
||||
@@ -102,7 +102,7 @@ impl Node {
|
||||
}
|
||||
Some((request, response_tx)) = control_rx.recv() => {
|
||||
let response = if request.command.starts_with("show_") {
|
||||
queries::dispatch(self, &request.command)
|
||||
queries::dispatch(self, &request.command, request.params.as_ref())
|
||||
} else {
|
||||
commands::dispatch(
|
||||
self,
|
||||
@@ -127,6 +127,7 @@ impl Node {
|
||||
self.check_tree_state().await;
|
||||
self.check_bloom_state().await;
|
||||
self.compute_mesh_size();
|
||||
self.record_stats_history();
|
||||
self.check_mmp_reports().await;
|
||||
self.check_session_mmp_reports().await;
|
||||
self.check_link_heartbeats().await;
|
||||
|
||||
+109
@@ -14,6 +14,7 @@ mod routing_error_rate_limit;
|
||||
pub(crate) mod session;
|
||||
pub(crate) mod session_wire;
|
||||
pub(crate) mod stats;
|
||||
pub(crate) mod stats_history;
|
||||
#[cfg(test)]
|
||||
mod tests;
|
||||
mod tree;
|
||||
@@ -363,6 +364,9 @@ pub struct Node {
|
||||
/// Routing, forwarding, discovery, and error signal counters.
|
||||
stats: stats::NodeStats,
|
||||
|
||||
/// Time-series history of node-level metrics (1s/1m rings).
|
||||
stats_history: stats_history::StatsHistory,
|
||||
|
||||
// === TUN Interface ===
|
||||
/// TUN device state.
|
||||
tun_state: TunState,
|
||||
@@ -546,6 +550,7 @@ impl Node {
|
||||
next_link_id: 1,
|
||||
next_transport_id: 1,
|
||||
stats: stats::NodeStats::new(),
|
||||
stats_history: stats_history::StatsHistory::new(),
|
||||
tun_state,
|
||||
tun_name: None,
|
||||
tun_tx: None,
|
||||
@@ -657,6 +662,7 @@ impl Node {
|
||||
next_link_id: 1,
|
||||
next_transport_id: 1,
|
||||
stats: stats::NodeStats::new(),
|
||||
stats_history: stats_history::StatsHistory::new(),
|
||||
tun_state,
|
||||
tun_name: None,
|
||||
tun_tx: None,
|
||||
@@ -1143,6 +1149,70 @@ impl Node {
|
||||
&mut self.stats
|
||||
}
|
||||
|
||||
/// Get the stats history collector.
|
||||
pub fn stats_history(&self) -> &stats_history::StatsHistory {
|
||||
&self.stats_history
|
||||
}
|
||||
|
||||
/// Sample the current node state into the stats history ring.
|
||||
/// Called once per tick from the RX loop.
|
||||
pub(crate) fn record_stats_history(&mut self) {
|
||||
let fwd = &self.stats.forwarding;
|
||||
let peers_with_mmp: Vec<f64> = self
|
||||
.peers
|
||||
.values()
|
||||
.filter_map(|p| p.mmp().map(|m| m.metrics.loss_rate()))
|
||||
.collect();
|
||||
let loss_rate = if peers_with_mmp.is_empty() {
|
||||
0.0
|
||||
} else {
|
||||
peers_with_mmp.iter().sum::<f64>() / peers_with_mmp.len() as f64
|
||||
};
|
||||
|
||||
let snap = stats_history::Snapshot {
|
||||
mesh_size: self.estimated_mesh_size,
|
||||
tree_depth: self.tree_state.my_coords().depth() as u32,
|
||||
peer_count: self.peers.len() as u64,
|
||||
parent_switches_total: self.stats.tree.parent_switches,
|
||||
bytes_in_total: fwd.received_bytes,
|
||||
bytes_out_total: fwd.forwarded_bytes + fwd.originated_bytes,
|
||||
packets_in_total: fwd.received_packets,
|
||||
packets_out_total: fwd.forwarded_packets + fwd.originated_packets,
|
||||
loss_rate,
|
||||
active_sessions: self.sessions.len() as u64,
|
||||
};
|
||||
|
||||
let now = std::time::Instant::now();
|
||||
let peer_snaps: Vec<stats_history::PeerSnapshot> = self
|
||||
.peers
|
||||
.values()
|
||||
.map(|p| {
|
||||
let stats = p.link_stats();
|
||||
let (srtt_ms, loss_rate, ecn_ce) = match p.mmp() {
|
||||
Some(m) => (
|
||||
m.metrics.srtt_ms(),
|
||||
Some(m.metrics.loss_rate()),
|
||||
m.receiver.ecn_ce_count() as u64,
|
||||
),
|
||||
None => (None, None, 0),
|
||||
};
|
||||
stats_history::PeerSnapshot {
|
||||
node_addr: *p.node_addr(),
|
||||
last_seen: now,
|
||||
srtt_ms,
|
||||
loss_rate,
|
||||
bytes_in_total: stats.bytes_recv,
|
||||
bytes_out_total: stats.bytes_sent,
|
||||
packets_in_total: stats.packets_recv,
|
||||
packets_out_total: stats.packets_sent,
|
||||
ecn_ce_total: ecn_ce,
|
||||
}
|
||||
})
|
||||
.collect();
|
||||
|
||||
self.stats_history.tick(now, &snap, &peer_snaps);
|
||||
}
|
||||
|
||||
// === TUN Interface ===
|
||||
|
||||
/// Get the TUN state.
|
||||
@@ -1453,16 +1523,55 @@ impl Node {
|
||||
self.identity_cache.len()
|
||||
}
|
||||
|
||||
/// Iterate over identity cache entries.
|
||||
///
|
||||
/// Returns `(NodeAddr, PublicKey, last_seen_ms)` for each cached identity.
|
||||
/// Used by the `show_identity_cache` control query.
|
||||
pub fn identity_cache_iter(
|
||||
&self,
|
||||
) -> impl Iterator<Item = (&NodeAddr, &secp256k1::PublicKey, u64)> {
|
||||
self.identity_cache
|
||||
.values()
|
||||
.map(|(addr, pk, ts)| (addr, pk, *ts))
|
||||
}
|
||||
|
||||
/// Configured maximum identity cache size.
|
||||
pub fn identity_cache_max(&self) -> usize {
|
||||
self.config.node.cache.identity_size
|
||||
}
|
||||
|
||||
/// Number of pending discovery lookups.
|
||||
pub fn pending_lookup_count(&self) -> usize {
|
||||
self.pending_lookups.len()
|
||||
}
|
||||
|
||||
/// Iterate over pending discovery lookups for diagnostics.
|
||||
pub fn pending_lookups_iter(
|
||||
&self,
|
||||
) -> impl Iterator<Item = (&NodeAddr, &handlers::discovery::PendingLookup)> {
|
||||
self.pending_lookups.iter()
|
||||
}
|
||||
|
||||
/// Number of recent discovery requests tracked.
|
||||
pub fn recent_request_count(&self) -> usize {
|
||||
self.recent_requests.len()
|
||||
}
|
||||
|
||||
/// Count of destinations with queued TUN packets awaiting session setup.
|
||||
pub fn pending_tun_destinations(&self) -> usize {
|
||||
self.pending_tun_packets.len()
|
||||
}
|
||||
|
||||
/// Total TUN packets queued across all destinations.
|
||||
pub fn pending_tun_total_packets(&self) -> usize {
|
||||
self.pending_tun_packets.values().map(|q| q.len()).sum()
|
||||
}
|
||||
|
||||
/// Iterate over retry state for diagnostics.
|
||||
pub fn retry_state_iter(&self) -> impl Iterator<Item = (&NodeAddr, &retry::RetryState)> {
|
||||
self.retry_pending.iter()
|
||||
}
|
||||
|
||||
// === Routing ===
|
||||
|
||||
/// Check if a peer is a tree neighbor (parent or child in the spanning tree).
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user