iroh_quinn_proto/connection/
stats.rs

1//! Connection statistics
2
3use crate::Duration;
4use crate::FrameType;
5
6/// Statistics about UDP datagrams transmitted or received on a connection
7///
8/// All QUIC packets are carried by UDP datagrams. Hence, these statistics cover all traffic on a connection.
9#[derive(Default, Debug, Copy, Clone)]
10#[non_exhaustive]
11pub struct UdpStats {
12    /// The amount of UDP datagrams observed
13    pub datagrams: u64,
14    /// The total amount of bytes which have been transferred inside UDP datagrams
15    pub bytes: u64,
16    /// The amount of I/O operations executed
17    ///
18    /// Can be less than `datagrams` when GSO, GRO, and/or batched system calls are in use.
19    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/// Number of frames transmitted or received of each frame type
31#[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        // Increments the field. Added for readability
78        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/// Statistics related to a transmission path
165#[derive(Debug, Default, Copy, Clone, PartialEq, Eq)]
166#[non_exhaustive]
167pub struct PathStats {
168    /// Current best estimate of this connection's latency (round-trip-time)
169    pub rtt: Duration,
170    /// Current congestion window of the connection
171    pub cwnd: u64,
172    /// Congestion events on the connection
173    pub congestion_events: u64,
174    /// The amount of packets lost on this path
175    pub lost_packets: u64,
176    /// The amount of bytes lost on this path
177    pub lost_bytes: u64,
178    /// The amount of packets sent on this path
179    pub sent_packets: u64,
180    /// The amount of PLPMTUD probe packets sent on this path (also counted by `sent_packets`)
181    pub sent_plpmtud_probes: u64,
182    /// The amount of PLPMTUD probe packets lost on this path (ignored by `lost_packets` and
183    /// `lost_bytes`)
184    pub lost_plpmtud_probes: u64,
185    /// The number of times a black hole was detected in the path
186    pub black_holes_detected: u64,
187    /// Largest UDP payload size the path currently supports
188    pub current_mtu: u16,
189}
190
191/// Connection statistics
192#[derive(Debug, Default, Clone)]
193#[non_exhaustive]
194pub struct ConnectionStats {
195    /// Statistics about UDP datagrams transmitted on a connection
196    pub udp_tx: UdpStats,
197    /// Statistics about UDP datagrams received on a connection
198    pub udp_rx: UdpStats,
199    /// Statistics about frames transmitted on a connection
200    pub frame_tx: FrameStats,
201    /// Statistics about frames received on a connection
202    pub frame_rx: FrameStats,
203}