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