noq_proto/congestion.rs
1//! Logic for controlling the rate at which data is sent
2
3use crate::connection::RttEstimator;
4use crate::{Duration, Instant};
5use std::any::Any;
6use std::sync::Arc;
7
8mod bbr3;
9mod cubic;
10mod new_reno;
11
12pub use bbr3::{Bbr3, Bbr3Config};
13pub use cubic::{Cubic, CubicConfig};
14pub use new_reno::{NewReno, NewRenoConfig};
15
16/// Common interface for different congestion controllers
17pub trait Controller: Send + Sync + std::fmt::Debug {
18 /// One or more packets were just sent
19 #[allow(unused_variables)]
20 fn on_sent(&mut self, now: Instant, bytes: u64, largest_pn: u64) {}
21
22 /// One packet was just sent
23 #[allow(unused_variables)]
24 fn on_packet_sent(&mut self, now: Instant, bytes: u16, pn: u64) {}
25
26 /// The connection had data to send but was blocked by the congestion window
27 ///
28 /// Reports the spec's `C.is_cwnd_limited` signal to the controller: the sender fully utilized
29 /// the congestion window at this point in the current round trip.
30 fn on_cwnd_limited(&mut self) {}
31
32 /// Packet deliveries were confirmed
33 ///
34 /// `app_limited` indicates whether the connection was blocked on outgoing
35 /// application data prior to receiving these acknowledgements.
36 #[allow(unused_variables)]
37 fn on_ack(
38 &mut self,
39 now: Instant,
40 sent: Instant,
41 bytes: u64,
42 pn: u64,
43 app_limited: bool,
44 rtt: &RttEstimator,
45 ) {
46 }
47
48 /// Packets are acked in batches, all with the same `now` argument. This indicates one of those
49 /// batches has completed.
50 #[allow(unused_variables)]
51 fn on_end_acks(
52 &mut self,
53 now: Instant,
54 in_flight: u64,
55 app_limited: bool,
56 largest_packet_num_acked: Option<u64>,
57 ) {
58 }
59
60 /// Packets were deemed lost or marked congested
61 ///
62 /// `in_persistent_congestion` indicates whether all packets sent within the persistent
63 /// congestion threshold period ending when the most recent packet in this batch was sent were
64 /// lost.
65 /// `lost_bytes` indicates how many bytes were lost. This value will be 0 for ECN triggers.
66 /// `largest_lost_pn` indicates the packet number of the packet with the highest packet number
67 /// in the congestion event.
68 fn on_congestion_event(
69 &mut self,
70 now: Instant,
71 sent: Instant,
72 is_persistent_congestion: bool,
73 is_ecn: bool,
74 lost_bytes: u64,
75 largest_lost_pn: u64,
76 );
77
78 /// One packet was just lost
79 #[allow(unused_variables)]
80 fn on_packet_lost(&mut self, lost_bytes: u16, pn: u64, now: Instant) {}
81
82 /// Packets were incorrectly deemed lost
83 ///
84 /// This function is called when all packets that were deemed lost (for instance because
85 /// of packet reordering) are acknowledged after the congestion event was raised.
86 fn on_spurious_congestion_event(&mut self) {}
87
88 /// The known MTU for the current network path has been updated
89 fn on_mtu_update(&mut self, new_mtu: u16);
90
91 /// The peer's ACK-frequency parameters have changed
92 ///
93 /// `ack_eliciting_threshold` is the number of ack-eliciting packets the peer may receive
94 /// before being required to send an immediate ACK (per the QUIC ACK frequency extension).
95 /// `requested_max_ack_delay` is the maximum delay we asked the peer to wait before sending
96 /// an ACK when the threshold hasn't been reached.
97 ///
98 /// Controllers can use this to refine estimates that depend on peer ACK behavior (e.g.
99 /// BBR's offload budget).
100 #[allow(unused_variables)]
101 fn on_ack_frequency_update(
102 &mut self,
103 ack_eliciting_threshold: u64,
104 requested_max_ack_delay: Duration,
105 ) {
106 }
107
108 /// Number of ack-eliciting bytes that may be in flight
109 fn window(&self) -> u64;
110
111 /// Retrieve implementation-specific metrics used to populate `qlog` traces when they are
112 /// enabled This is also used to alter the pacing of the connection with
113 /// `pacing_rate` and `send_quantum`
114 fn metrics(&self) -> ControllerMetrics {
115 ControllerMetrics {
116 congestion_window: self.window(),
117 ssthresh: None,
118 pacing_rate: None,
119 send_quantum: None,
120 }
121 }
122
123 /// Duplicate the controller's state
124 fn clone_box(&self) -> Box<dyn Controller>;
125
126 /// Initial congestion window
127 fn initial_window(&self) -> u64;
128
129 /// Returns Self for use in down-casting to extract implementation details
130 fn into_any(self: Box<Self>) -> Box<dyn Any>;
131}
132
133/// Common congestion controller metrics used both for logging purposes
134/// but also to alter the pacing of the connection with
135/// `pacing_rate` and `send_quantum`
136#[derive(Default)]
137#[non_exhaustive]
138pub struct ControllerMetrics {
139 /// Congestion window (bytes)
140 pub congestion_window: u64,
141 /// Slow start threshold (bytes)
142 pub ssthresh: Option<u64>,
143 /// Pacing rate (bytes/s)
144 pub pacing_rate: Option<u64>,
145 /// Send Quantum (bytes) used to control the size of packet bursts
146 pub send_quantum: Option<u64>,
147}
148
149/// Constructs controllers on demand
150pub trait ControllerFactory {
151 /// Construct a fresh `Controller`
152 fn build(self: Arc<Self>, now: Instant, current_mtu: u16) -> Box<dyn Controller>;
153}
154
155const BASE_DATAGRAM_SIZE: u64 = 1200;