quiche/recovery/gcongestion/mod.rs
1// Copyright (C) 2024, Cloudflare, Inc.
2// All rights reserved.
3//
4// Redistribution and use in source and binary forms, with or without
5// modification, are permitted provided that the following conditions are
6// met:
7//
8// * Redistributions of source code must retain the above copyright notice,
9// this list of conditions and the following disclaimer.
10//
11// * Redistributions in binary form must reproduce the above copyright
12// notice, this list of conditions and the following disclaimer in the
13// documentation and/or other materials provided with the distribution.
14//
15// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
16// IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
17// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
18// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
19// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
20// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
21// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
22// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
23// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
24// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26
27mod bbr;
28mod bbr2;
29pub mod pacer;
30mod recovery;
31
32use std::fmt::Debug;
33use std::str::FromStr;
34use std::time::Instant;
35
36pub use self::recovery::GRecovery;
37use crate::recovery::bandwidth::Bandwidth;
38
39use crate::recovery::rtt::RttStats;
40use crate::recovery::RecoveryStats;
41
42#[derive(Debug)]
43pub struct Lost {
44 pub(super) packet_number: u64,
45 pub(super) bytes_lost: usize,
46}
47
48#[derive(Debug)]
49pub struct Acked {
50 pub(super) pkt_num: u64,
51 pub(super) time_sent: Instant,
52}
53
54pub(super) trait CongestionControl: Debug {
55 /// Returns the name of the current state of the congestion control state
56 /// machine. Used to annotate qlogs after state transitions.
57 #[cfg(feature = "qlog")]
58 fn state_str(&self) -> &'static str;
59
60 /// Returns the size of the current congestion window in bytes. Note, this
61 /// is not the *available* window. Some send algorithms may not use a
62 /// congestion window and will return 0.
63 fn get_congestion_window(&self) -> usize;
64
65 /// Returns the size of the current congestion window in packets. Note, this
66 /// is not the *available* window. Some send algorithms may not use a
67 /// congestion window and will return 0.
68 fn get_congestion_window_in_packets(&self) -> usize;
69
70 /// Make decision on whether the sender can send right now. Note that even
71 /// when this method returns true, the sending can be delayed due to pacing.
72 fn can_send(&self, bytes_in_flight: usize) -> bool;
73
74 /// Inform that we sent `bytes` to the wire, and if the packet is
75 /// retransmittable. `bytes_in_flight` is the number of bytes in flight
76 /// before the packet was sent. Note: this function must be called for
77 /// every packet sent to the wire.
78 fn on_packet_sent(
79 &mut self, sent_time: Instant, bytes_in_flight: usize,
80 packet_number: u64, bytes: usize, is_retransmissible: bool,
81 );
82
83 /// Inform that `packet_number` has been neutered.
84 fn on_packet_neutered(&mut self, _packet_number: u64) {}
85
86 /// Indicates an update to the congestion state, caused either by an
87 /// incoming ack or loss event timeout. `rtt_updated` indicates whether a
88 /// new `latest_rtt` sample has been taken, `prior_in_flight` the bytes in
89 /// flight prior to the congestion event. `acked_packets` and `lost_packets`
90 /// are any packets considered acked or lost as a result of the
91 /// congestion event.
92 #[allow(clippy::too_many_arguments)]
93 fn on_congestion_event(
94 &mut self, rtt_updated: bool, prior_in_flight: usize,
95 bytes_in_flight: usize, event_time: Instant, acked_packets: &[Acked],
96 lost_packets: &[Lost], least_unacked: u64, rtt_stats: &RttStats,
97 recovery_stats: &mut RecoveryStats,
98 );
99
100 /// Called when an RTO fires. Resets the retransmission alarm if there are
101 /// remaining unacked packets.
102 fn on_retransmission_timeout(&mut self, packets_retransmitted: bool);
103
104 /// Called when connection migrates and cwnd needs to be reset.
105 #[allow(dead_code)]
106 fn on_connection_migration(&mut self);
107
108 /// Adjust the current cwnd to a new maximal size
109 fn limit_cwnd(&mut self, _max_cwnd: usize) {}
110
111 fn is_in_recovery(&self) -> bool;
112
113 #[allow(dead_code)]
114 fn is_cwnd_limited(&self, bytes_in_flight: usize) -> bool;
115
116 fn pacing_rate(
117 &self, bytes_in_flight: usize, rtt_stats: &RttStats,
118 ) -> Bandwidth;
119
120 fn bandwidth_estimate(&self, rtt_stats: &RttStats) -> Bandwidth;
121
122 fn max_bandwidth(&self) -> Bandwidth;
123
124 fn update_mss(&mut self, new_mss: usize);
125
126 fn on_app_limited(&mut self, _bytes_in_flight: usize) {}
127
128 #[cfg(feature = "qlog")]
129 fn ssthresh(&self) -> Option<u64> {
130 None
131 }
132}
133
134/// BBR settings used to customize the algorithm's behavior.
135///
136/// This functionality is experimental and will be removed in the future.
137///
138/// A congestion control algorithm has dual-responsibility of effective network
139/// utilization and avoiding congestion. Custom values should be choosen
140/// carefully since incorrect values can lead to network degradation for all
141/// connections on the shared network.
142#[derive(Debug, Default, Copy, Clone, PartialEq)]
143#[repr(C)]
144#[doc(hidden)]
145pub struct BbrParams {
146 /// Controls the BBR startup gain.
147 pub startup_cwnd_gain: Option<f32>,
148
149 /// Controls the BBR startup pacing gain.
150 pub startup_pacing_gain: Option<f32>,
151
152 /// Controls the BBR full bandwidth threshold.
153 pub full_bw_threshold: Option<f32>,
154
155 /// Controls the number of rounds to stay in STARTUP before
156 /// exiting due to bandwidth plateau.
157 pub startup_full_bw_rounds: Option<usize>,
158
159 /// Controls the BBR startup loss count necessary to exit startup.
160 pub startup_full_loss_count: Option<usize>,
161
162 /// Controls the BBR drain cwnd gain.
163 pub drain_cwnd_gain: Option<f32>,
164
165 /// Controls the BBR drain pacing gain.
166 pub drain_pacing_gain: Option<f32>,
167
168 /// Controls if BBR should respect Reno coexistence.
169 pub enable_reno_coexistence: Option<bool>,
170
171 /// Controls if BBR should enable code in Bandwidth Sampler that
172 /// attempts to avoid overestimating bandwidth on ack compression.
173 pub enable_overestimate_avoidance: Option<bool>,
174
175 /// Controls if BBR should enable a possible fix in Bandwidth
176 /// Sampler that attempts to bandwidth over estimation avoidance.
177 pub choose_a0_point_fix: Option<bool>,
178
179 /// Controls the BBR bandwidth probe up pacing gain.
180 pub probe_bw_probe_up_pacing_gain: Option<f32>,
181
182 /// Controls the BBR bandwidth probe down pacing gain.
183 pub probe_bw_probe_down_pacing_gain: Option<f32>,
184
185 /// Controls the BBR probe bandwidth DOWN/CRUISE/REFILL cwnd gain.
186 pub probe_bw_cwnd_gain: Option<f32>,
187
188 /// Controls the BBR probe bandwidth UP cwnd gain.
189 pub probe_bw_up_cwnd_gain: Option<f32>,
190
191 /// Controls the BBR probe RTT pacing gain.
192 pub probe_rtt_pacing_gain: Option<f32>,
193
194 /// Controls the BBR probe RTT cwnd gain.
195 pub probe_rtt_cwnd_gain: Option<f32>,
196
197 /// Controls the number of rounds BBR should stay in probe up if
198 /// bytes_in_flight doesn't drop below target.
199 pub max_probe_up_queue_rounds: Option<usize>,
200
201 /// Controls the BBR loss threshold.
202 pub loss_threshold: Option<f32>,
203
204 /// Controls if BBR should use bytes delievered as an estimate for
205 /// inflight_hi.
206 pub use_bytes_delivered_for_inflight_hi: Option<bool>,
207
208 /// Controls if BBR should adjust startup pacing at round end.
209 pub decrease_startup_pacing_at_end_of_round: Option<bool>,
210
211 /// Controls the BBR bandwidth lo reduction strategy.
212 pub bw_lo_reduction_strategy: Option<BbrBwLoReductionStrategy>,
213
214 /// Determines whether app limited rounds with no bandwidth growth count
215 /// towards the rounds threshold to exit startup.
216 pub ignore_app_limited_for_no_bandwidth_growth: Option<bool>,
217
218 /// Initial pacing rate for a new connection before an RTT
219 /// estimate is available. This rate serves as an upper bound on
220 /// the initial pacing rate, which is calculated by dividing the
221 /// initial cwnd by the first RTT estimate.
222 pub initial_pacing_rate_bytes_per_second: Option<u64>,
223
224 /// If true, scale the pacing rate when updating mss when doing pmtud.
225 pub scale_pacing_rate_by_mss: Option<bool>,
226
227 /// Disable `has_stayed_long_enough_in_probe_down` which can cause ProbeDown
228 /// to exit early.
229 pub disable_probe_down_early_exit: Option<bool>,
230
231 /// Set the expected send time for packets when using BBR to `now`
232 /// instead of `get_next_release_time()`. Setting the time based
233 /// on `get_next_release_time()` can result in artificially low
234 /// minRTT measurements which will make BBR misbehave.
235 pub time_sent_set_to_now: Option<bool>,
236}
237
238/// Controls BBR's bandwidth reduction strategy on congestion event.
239///
240/// This functionality is experimental and will be removed in the future.
241#[derive(Debug, Copy, Clone, PartialEq, Eq)]
242#[repr(C)]
243#[doc(hidden)]
244pub enum BbrBwLoReductionStrategy {
245 /// Uses the default strategy based on `BBRBeta`.
246 Default = 0,
247
248 /// Considers min-rtt to estimate bandwidth reduction.
249 MinRttReduction = 1,
250
251 /// Considers inflight data to estimate bandwidth reduction.
252 InflightReduction = 2,
253
254 /// Considers cwnd to estimate bandwidth reduction.
255 CwndReduction = 3,
256}
257
258#[doc(hidden)]
259impl FromStr for BbrBwLoReductionStrategy {
260 type Err = crate::Error;
261
262 /// Converts a string to `BbrBwLoReductionStrategy`.
263 ///
264 /// If `name` is not valid, `Error::CongestionControl` is returned.
265 fn from_str(name: &str) -> Result<Self, Self::Err> {
266 match name {
267 "default" => Ok(BbrBwLoReductionStrategy::Default),
268 "minrtt" => Ok(BbrBwLoReductionStrategy::MinRttReduction),
269 "inflight" => Ok(BbrBwLoReductionStrategy::InflightReduction),
270 "cwnd" => Ok(BbrBwLoReductionStrategy::CwndReduction),
271
272 _ => Err(crate::Error::CongestionControl),
273 }
274 }
275}