iroh_quinn_proto/connection/
stats.rs1use crate::FrameType;
4use crate::{Dir, Duration, frame::Frame};
5
6#[derive(Default, Debug, Copy, Clone)]
10#[non_exhaustive]
11pub struct UdpStats {
12 pub datagrams: u64,
14 pub bytes: u64,
16 pub ios: u64,
20}
21
22impl UdpStats {
23 pub(crate) fn on_sent(&mut self, datagrams: u64, bytes: usize) {
24 self.datagrams += datagrams;
25 self.bytes += bytes as u64;
26 self.ios += 1;
27 }
28}
29
30#[derive(Default, Copy, Clone)]
32#[non_exhaustive]
33#[allow(missing_docs)]
34pub struct FrameStats {
35 pub acks: u64,
36 pub path_acks: u64,
37 pub ack_frequency: u64,
38 pub crypto: u64,
39 pub connection_close: u64,
40 pub data_blocked: u64,
41 pub datagram: u64,
42 pub handshake_done: u8,
43 pub immediate_ack: u64,
44 pub max_data: u64,
45 pub max_stream_data: u64,
46 pub max_streams_bidi: u64,
47 pub max_streams_uni: u64,
48 pub new_connection_id: u64,
49 pub path_new_connection_id: u64,
50 pub new_token: u64,
51 pub path_challenge: u64,
52 pub path_response: u64,
53 pub ping: u64,
54 pub reset_stream: u64,
55 pub retire_connection_id: u64,
56 pub path_retire_connection_id: u64,
57 pub stream_data_blocked: u64,
58 pub streams_blocked_bidi: u64,
59 pub streams_blocked_uni: u64,
60 pub stop_sending: u64,
61 pub stream: u64,
62 pub observed_addr: u64,
63 pub path_abandon: u64,
64 pub path_status_available: u64,
65 pub path_status_backup: u64,
66 pub max_path_id: u64,
67 pub paths_blocked: u64,
68 pub path_cids_blocked: u64,
69 pub add_address: u64,
70 pub reach_out: u64,
71 pub remove_address: u64,
72}
73
74impl FrameStats {
75 pub(crate) fn record(&mut self, frame: &Frame) {
76 match frame {
77 Frame::Padding => {}
78 Frame::Ping => self.ping += 1,
79 Frame::Ack(_) => self.acks += 1,
80 Frame::PathAck(_) => self.path_acks += 1,
81 Frame::ResetStream(_) => self.reset_stream += 1,
82 Frame::StopSending(_) => self.stop_sending += 1,
83 Frame::Crypto(_) => self.crypto += 1,
84 Frame::Datagram(_) => self.datagram += 1,
85 Frame::NewToken(_) => self.new_token += 1,
86 Frame::MaxData(_) => self.max_data += 1,
87 Frame::MaxStreamData { .. } => self.max_stream_data += 1,
88 Frame::MaxStreams { dir, .. } => {
89 if *dir == Dir::Bi {
90 self.max_streams_bidi += 1;
91 } else {
92 self.max_streams_uni += 1;
93 }
94 }
95 Frame::DataBlocked { .. } => self.data_blocked += 1,
96 Frame::Stream(_) => self.stream += 1,
97 Frame::StreamDataBlocked { .. } => self.stream_data_blocked += 1,
98 Frame::StreamsBlocked { dir, .. } => {
99 if *dir == Dir::Bi {
100 self.streams_blocked_bidi += 1;
101 } else {
102 self.streams_blocked_uni += 1;
103 }
104 }
105 Frame::NewConnectionId(frame) => match frame.path_id {
106 Some(_) => self.path_new_connection_id += 1,
107 None => self.new_connection_id += 1,
108 },
109 Frame::RetireConnectionId(frame) => match frame.get_type() {
110 FrameType::RETIRE_CONNECTION_ID => self.retire_connection_id += 1,
111 FrameType::PATH_RETIRE_CONNECTION_ID => self.path_retire_connection_id += 1,
112 _ => unreachable!(),
113 },
114 Frame::PathChallenge(_) => self.path_challenge += 1,
115 Frame::PathResponse(_) => self.path_response += 1,
116 Frame::Close(_) => self.connection_close += 1,
117 Frame::AckFrequency(_) => self.ack_frequency += 1,
118 Frame::ImmediateAck => self.immediate_ack += 1,
119 Frame::HandshakeDone => self.handshake_done = self.handshake_done.saturating_add(1),
120 Frame::ObservedAddr(_) => self.observed_addr += 1,
121 Frame::PathAbandon(_) => self.path_abandon = self.path_abandon.saturating_add(1),
122 Frame::PathStatusAvailable(_) => {
123 self.path_status_available = self.path_status_available.saturating_add(1)
124 }
125 Frame::PathStatusBackup(_) => {
126 self.path_status_backup = self.path_status_backup.saturating_add(1)
127 }
128 Frame::MaxPathId(_) => self.max_path_id = self.max_path_id.saturating_add(1),
129 Frame::PathsBlocked(_) => self.paths_blocked = self.paths_blocked.saturating_add(1),
130 Frame::PathCidsBlocked(_) => {
131 self.path_cids_blocked = self.path_cids_blocked.saturating_add(1)
132 }
133 Frame::AddAddress(_) => self.add_address = self.add_address.saturating_add(1),
134 Frame::ReachOut(_) => self.reach_out = self.reach_out.saturating_add(1),
135 Frame::RemoveAddress(_) => self.remove_address = self.remove_address.saturating_add(1),
136 }
137 }
138}
139
140impl std::fmt::Debug for FrameStats {
141 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
142 f.debug_struct("FrameStats")
143 .field("ACK", &self.acks)
144 .field("ACK_FREQUENCY", &self.ack_frequency)
145 .field("CONNECTION_CLOSE", &self.connection_close)
146 .field("CRYPTO", &self.crypto)
147 .field("DATA_BLOCKED", &self.data_blocked)
148 .field("DATAGRAM", &self.datagram)
149 .field("HANDSHAKE_DONE", &self.handshake_done)
150 .field("IMMEDIATE_ACK", &self.immediate_ack)
151 .field("MAX_DATA", &self.max_data)
152 .field("MAX_PATH_ID", &self.max_path_id)
153 .field("MAX_STREAM_DATA", &self.max_stream_data)
154 .field("MAX_STREAMS_BIDI", &self.max_streams_bidi)
155 .field("MAX_STREAMS_UNI", &self.max_streams_uni)
156 .field("NEW_CONNECTION_ID", &self.new_connection_id)
157 .field("NEW_TOKEN", &self.new_token)
158 .field("PATHS_BLOCKED", &self.paths_blocked)
159 .field("PATH_ABANDON", &self.path_abandon)
160 .field("PATH_ACK", &self.path_acks)
161 .field("PATH_STATUS_AVAILABLE", &self.path_status_available)
162 .field("PATH_STATUS_BACKUP", &self.path_status_backup)
163 .field("PATH_CHALLENGE", &self.path_challenge)
164 .field("PATH_CIDS_BLOCKED", &self.path_cids_blocked)
165 .field("PATH_NEW_CONNECTION_ID", &self.path_new_connection_id)
166 .field("PATH_RESPONSE", &self.path_response)
167 .field("PATH_RETIRE_CONNECTION_ID", &self.path_retire_connection_id)
168 .field("PING", &self.ping)
169 .field("RESET_STREAM", &self.reset_stream)
170 .field("RETIRE_CONNECTION_ID", &self.retire_connection_id)
171 .field("STREAM_DATA_BLOCKED", &self.stream_data_blocked)
172 .field("STREAMS_BLOCKED_BIDI", &self.streams_blocked_bidi)
173 .field("STREAMS_BLOCKED_UNI", &self.streams_blocked_uni)
174 .field("STOP_SENDING", &self.stop_sending)
175 .field("STREAM", &self.stream)
176 .finish()
177 }
178}
179
180#[derive(Debug, Default, Copy, Clone, PartialEq, Eq)]
182#[non_exhaustive]
183pub struct PathStats {
184 pub rtt: Duration,
186 pub cwnd: u64,
188 pub congestion_events: u64,
190 pub lost_packets: u64,
192 pub lost_bytes: u64,
194 pub sent_packets: u64,
196 pub sent_plpmtud_probes: u64,
198 pub lost_plpmtud_probes: u64,
201 pub black_holes_detected: u64,
203 pub current_mtu: u16,
205}
206
207#[derive(Debug, Default, Clone)]
209#[non_exhaustive]
210pub struct ConnectionStats {
211 pub udp_tx: UdpStats,
213 pub udp_rx: UdpStats,
215 pub frame_tx: FrameStats,
217 pub frame_rx: FrameStats,
219}