1use crate::{Dir, Duration, frame::Frame};
4
5#[derive(Default, Debug, Copy, Clone)]
9#[non_exhaustive]
10pub struct UdpStats {
11 pub datagrams: u64,
13 pub bytes: u64,
15 pub ios: u64,
19}
20
21impl UdpStats {
22 pub(crate) fn on_sent(&mut self, datagrams: u64, bytes: usize) {
23 self.datagrams += datagrams;
24 self.bytes += bytes as u64;
25 self.ios += 1;
26 }
27}
28
29#[derive(Default, Copy, Clone)]
31#[non_exhaustive]
32#[allow(missing_docs)]
33pub struct FrameStats {
34 pub acks: u64,
35 pub ack_frequency: u64,
36 pub crypto: u64,
37 pub connection_close: u64,
38 pub data_blocked: u64,
39 pub datagram: u64,
40 pub handshake_done: u8,
41 pub immediate_ack: u64,
42 pub max_data: u64,
43 pub max_stream_data: u64,
44 pub max_streams_bidi: u64,
45 pub max_streams_uni: u64,
46 pub new_connection_id: u64,
47 pub new_token: u64,
48 pub path_challenge: u64,
49 pub path_response: u64,
50 pub ping: u64,
51 pub reset_stream: u64,
52 pub retire_connection_id: u64,
53 pub stream_data_blocked: u64,
54 pub streams_blocked_bidi: u64,
55 pub streams_blocked_uni: u64,
56 pub stop_sending: u64,
57 pub stream: u64,
58}
59
60impl FrameStats {
61 pub(crate) fn record(&mut self, frame: &Frame) {
62 match frame {
63 Frame::Padding => {}
64 Frame::Ping => self.ping += 1,
65 Frame::Ack(_) => self.acks += 1,
66 Frame::ResetStream(_) => self.reset_stream += 1,
67 Frame::StopSending(_) => self.stop_sending += 1,
68 Frame::Crypto(_) => self.crypto += 1,
69 Frame::Datagram(_) => self.datagram += 1,
70 Frame::NewToken(_) => self.new_token += 1,
71 Frame::MaxData(_) => self.max_data += 1,
72 Frame::MaxStreamData { .. } => self.max_stream_data += 1,
73 Frame::MaxStreams { dir, .. } => {
74 if *dir == Dir::Bi {
75 self.max_streams_bidi += 1;
76 } else {
77 self.max_streams_uni += 1;
78 }
79 }
80 Frame::DataBlocked { .. } => self.data_blocked += 1,
81 Frame::Stream(_) => self.stream += 1,
82 Frame::StreamDataBlocked { .. } => self.stream_data_blocked += 1,
83 Frame::StreamsBlocked { dir, .. } => {
84 if *dir == Dir::Bi {
85 self.streams_blocked_bidi += 1;
86 } else {
87 self.streams_blocked_uni += 1;
88 }
89 }
90 Frame::NewConnectionId(_) => self.new_connection_id += 1,
91 Frame::RetireConnectionId { .. } => self.retire_connection_id += 1,
92 Frame::PathChallenge(_) => self.path_challenge += 1,
93 Frame::PathResponse(_) => self.path_response += 1,
94 Frame::Close(_) => self.connection_close += 1,
95 Frame::AckFrequency(_) => self.ack_frequency += 1,
96 Frame::ImmediateAck => self.immediate_ack += 1,
97 Frame::HandshakeDone => self.handshake_done = self.handshake_done.saturating_add(1),
98 }
99 }
100}
101
102impl std::fmt::Debug for FrameStats {
103 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
104 f.debug_struct("FrameStats")
105 .field("ACK", &self.acks)
106 .field("ACK_FREQUENCY", &self.ack_frequency)
107 .field("CONNECTION_CLOSE", &self.connection_close)
108 .field("CRYPTO", &self.crypto)
109 .field("DATA_BLOCKED", &self.data_blocked)
110 .field("DATAGRAM", &self.datagram)
111 .field("HANDSHAKE_DONE", &self.handshake_done)
112 .field("IMMEDIATE_ACK", &self.immediate_ack)
113 .field("MAX_DATA", &self.max_data)
114 .field("MAX_STREAM_DATA", &self.max_stream_data)
115 .field("MAX_STREAMS_BIDI", &self.max_streams_bidi)
116 .field("MAX_STREAMS_UNI", &self.max_streams_uni)
117 .field("NEW_CONNECTION_ID", &self.new_connection_id)
118 .field("NEW_TOKEN", &self.new_token)
119 .field("PATH_CHALLENGE", &self.path_challenge)
120 .field("PATH_RESPONSE", &self.path_response)
121 .field("PING", &self.ping)
122 .field("RESET_STREAM", &self.reset_stream)
123 .field("RETIRE_CONNECTION_ID", &self.retire_connection_id)
124 .field("STREAM_DATA_BLOCKED", &self.stream_data_blocked)
125 .field("STREAMS_BLOCKED_BIDI", &self.streams_blocked_bidi)
126 .field("STREAMS_BLOCKED_UNI", &self.streams_blocked_uni)
127 .field("STOP_SENDING", &self.stop_sending)
128 .field("STREAM", &self.stream)
129 .finish()
130 }
131}
132
133#[derive(Debug, Default, Copy, Clone)]
135#[non_exhaustive]
136pub struct PathStats {
137 pub rtt: Duration,
139 pub cwnd: u64,
141 pub congestion_events: u64,
143 pub lost_packets: u64,
145 pub lost_bytes: u64,
147 pub sent_packets: u64,
149 pub sent_plpmtud_probes: u64,
151 pub lost_plpmtud_probes: u64,
154 pub black_holes_detected: u64,
156 pub current_mtu: u16,
158}
159
160#[derive(Debug, Default, Copy, Clone)]
162#[non_exhaustive]
163pub struct ConnectionStats {
164 pub udp_tx: UdpStats,
166 pub udp_rx: UdpStats,
168 pub frame_tx: FrameStats,
170 pub frame_rx: FrameStats,
172 pub path: PathStats,
174}