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;