iroh_quinn_proto/connection/
stats.rs1use crate::Duration;
4use crate::FrameType;
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_type: FrameType) {
76 use FrameType::*;
77 macro_rules! inc {
79 ($field_name: ident) => {{ self.$field_name = self.$field_name.saturating_add(1) }};
80 }
81 match frame_type {
82 Padding => {}
83 Ping => inc!(ping),
84 Ack | AckEcn => inc!(acks),
85 PathAck | PathAckEcn => inc!(path_acks),
86 ResetStream => inc!(reset_stream),
87 StopSending => inc!(stop_sending),
88 Crypto => inc!(crypto),
89 Datagram(_) => inc!(datagram),
90 NewToken => inc!(new_token),
91 MaxData => inc!(max_data),
92 MaxStreamData => inc!(max_stream_data),
93 MaxStreamsBidi => inc!(max_streams_bidi),
94 MaxStreamsUni => inc!(max_streams_uni),
95 DataBlocked => inc!(data_blocked),
96 Stream(_) => inc!(stream),
97 StreamDataBlocked => inc!(stream_data_blocked),
98 StreamsBlockedUni => inc!(streams_blocked_uni),
99 StreamsBlockedBidi => inc!(streams_blocked_bidi),
100 NewConnectionId => inc!(new_connection_id),
101 PathNewConnectionId => inc!(path_new_connection_id),
102 RetireConnectionId => inc!(retire_connection_id),
103 PathRetireConnectionId => inc!(path_retire_connection_id),
104 PathChallenge => inc!(path_challenge),
105 PathResponse => inc!(path_response),
106 ConnectionClose | ApplicationClose => inc!(connection_close),
107 AckFrequency => inc!(ack_frequency),
108 ImmediateAck => inc!(immediate_ack),
109 HandshakeDone => inc!(handshake_done),
110 ObservedIpv4Addr | ObservedIpv6Addr => inc!(observed_addr),
111 PathAbandon => inc!(path_abandon),
112 PathStatusAvailable => inc!(path_status_available),
113 PathStatusBackup => inc!(path_status_backup),
114 MaxPathId => inc!(max_path_id),
115 PathsBlocked => inc!(paths_blocked),
116 PathCidsBlocked => inc!(path_cids_blocked),
117 AddIpv4Address | AddIpv6Address => inc!(add_address),
118 ReachOutAtIpv4 | ReachOutAtIpv6 => inc!(reach_out),
119 RemoveAddress => inc!(remove_address),
120 };
121 }
122}
123
124impl std::fmt::Debug for FrameStats {
125 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
126 f.debug_struct("FrameStats")
127 .field("ACK", &self.acks)
128 .field("ACK_FREQUENCY", &self.ack_frequency)
129 .field("CONNECTION_CLOSE", &self.connection_close)
130 .field("CRYPTO", &self.crypto)
131 .field("DATA_BLOCKED", &self.data_blocked)
132 .field("DATAGRAM", &self.datagram)
133 .field("HANDSHAKE_DONE", &self.handshake_done)
134 .field("IMMEDIATE_ACK", &self.immediate_ack)
135 .field("MAX_DATA", &self.max_data)
136 .field("MAX_PATH_ID", &self.max_path_id)
137 .field("MAX_STREAM_DATA", &self.max_stream_data)
138 .field("MAX_STREAMS_BIDI", &self.max_streams_bidi)
139 .field("MAX_STREAMS_UNI", &self.max_streams_uni)
140 .field("NEW_CONNECTION_ID", &self.new_connection_id)
141 .field("NEW_TOKEN", &self.new_token)
142 .field("PATHS_BLOCKED", &self.paths_blocked)
143 .field("PATH_ABANDON", &self.path_abandon)
144 .field("PATH_ACK", &self.path_acks)
145 .field("PATH_STATUS_AVAILABLE", &self.path_status_available)
146 .field("PATH_STATUS_BACKUP", &self.path_status_backup)
147 .field("PATH_CHALLENGE", &self.path_challenge)
148 .field("PATH_CIDS_BLOCKED", &self.path_cids_blocked)
149 .field("PATH_NEW_CONNECTION_ID", &self.path_new_connection_id)
150 .field("PATH_RESPONSE", &self.path_response)
151 .field("PATH_RETIRE_CONNECTION_ID", &self.path_retire_connection_id)
152 .field("PING", &self.ping)
153 .field("RESET_STREAM", &self.reset_stream)
154 .field("RETIRE_CONNECTION_ID", &self.retire_connection_id)
155 .field("STREAM_DATA_BLOCKED", &self.stream_data_blocked)
156 .field("STREAMS_BLOCKED_BIDI", &self.streams_blocked_bidi)
157 .field("STREAMS_BLOCKED_UNI", &self.streams_blocked_uni)
158 .field("STOP_SENDING", &self.stop_sending)
159 .field("STREAM", &self.stream)
160 .finish()
161 }
162}
163
164#[derive(Debug, Default, Copy, Clone, PartialEq, Eq)]
166#[non_exhaustive]
167pub struct PathStats {
168 pub rtt: Duration,
170 pub cwnd: u64,
172 pub congestion_events: u64,
174 pub lost_packets: u64,
176 pub lost_bytes: u64,
178 pub sent_packets: u64,
180 pub sent_plpmtud_probes: u64,
182 pub lost_plpmtud_probes: u64,
185 pub black_holes_detected: u64,
187 pub current_mtu: u16,
189}
190
191#[derive(Debug, Default, Clone)]
193#[non_exhaustive]
194pub struct ConnectionStats {
195 pub udp_tx: UdpStats,
197 pub udp_rx: UdpStats,
199 pub frame_tx: FrameStats,
201 pub frame_rx: FrameStats,
203}