rns_net/common/
interface_stats.rs1pub const ANNOUNCE_SAMPLE_MAX: usize = 12;
3
4pub const INCOMING_ANNOUNCE_MIN_SAMPLE: usize = 8;
6
7#[derive(Debug, Clone, Default)]
9pub struct InterfaceStats {
10 pub rxb: u64,
11 pub txb: u64,
12 pub rx_packets: u64,
13 pub tx_packets: u64,
14 pub started: f64,
15 pub ia_timestamps: Vec<f64>,
17 pub oa_timestamps: Vec<f64>,
19}
20
21impl InterfaceStats {
22 pub fn record_incoming_announce(&mut self, now: f64) {
24 self.ia_timestamps.push(now);
25 if self.ia_timestamps.len() > ANNOUNCE_SAMPLE_MAX {
26 self.ia_timestamps.remove(0);
27 }
28 }
29
30 pub fn record_outgoing_announce(&mut self, now: f64) {
32 self.oa_timestamps.push(now);
33 if self.oa_timestamps.len() > ANNOUNCE_SAMPLE_MAX {
34 self.oa_timestamps.remove(0);
35 }
36 }
37
38 fn compute_frequency(timestamps: &[f64], min_sample: usize) -> f64 {
40 let sample_count = timestamps.len();
41 if sample_count <= min_sample {
42 return 0.0;
43 }
44 let span = timestamps[sample_count - 1] - timestamps[0];
45 if span <= 0.0 {
46 return 0.0;
47 }
48 sample_count as f64 / span
49 }
50
51 pub fn incoming_announce_freq(&self) -> f64 {
53 Self::compute_frequency(&self.ia_timestamps, INCOMING_ANNOUNCE_MIN_SAMPLE)
54 }
55
56 pub fn outgoing_announce_freq(&self) -> f64 {
58 Self::compute_frequency(&self.oa_timestamps, 1)
59 }
60}
61
62#[cfg(test)]
63mod tests {
64 use super::*;
65
66 #[test]
67 fn incoming_frequency_waits_for_minimum_sample_count() {
68 let mut stats = InterfaceStats::default();
69
70 for i in 0..8 {
71 stats.record_incoming_announce(i as f64);
72 }
73
74 assert_eq!(
75 stats.incoming_announce_freq(),
76 0.0,
77 "incoming announce frequency must stay zero until more than 8 samples exist"
78 );
79 }
80
81 #[test]
82 fn announce_frequency_keeps_twelve_samples() {
83 let mut stats = InterfaceStats::default();
84
85 for i in 0..12 {
86 stats.record_incoming_announce(i as f64);
87 stats.record_outgoing_announce(i as f64);
88 }
89
90 assert_eq!(stats.ia_timestamps.len(), 12);
91 assert_eq!(stats.oa_timestamps.len(), 12);
92
93 stats.record_incoming_announce(12.0);
94 stats.record_outgoing_announce(12.0);
95
96 assert_eq!(stats.ia_timestamps.len(), 12);
97 assert_eq!(stats.oa_timestamps.len(), 12);
98 assert_eq!(stats.ia_timestamps[0], 1.0);
99 assert_eq!(stats.oa_timestamps[0], 1.0);
100 }
101
102 #[test]
103 fn incoming_frequency_uses_sample_count_over_oldest_span() {
104 let mut stats = InterfaceStats::default();
105
106 for i in 0..12 {
107 stats.record_incoming_announce(i as f64);
108 }
109
110 let expected = 12.0 / 11.0;
111 assert!(
112 (stats.incoming_announce_freq() - expected).abs() < f64::EPSILON,
113 "incoming frequency should be samples / span, got {} expected {}",
114 stats.incoming_announce_freq(),
115 expected
116 );
117 }
118}