1use crate::connection::RttEstimator;
13use std::any::Any;
14use std::time::Instant;
15
16pub(crate) mod bbr;
18pub(crate) mod cubic;
19pub(crate) mod new_reno;
20
21pub(crate) use self::cubic::CubicConfig;
24#[derive(Debug, Default, Clone, Copy)]
28pub struct ControllerMetrics {
29 pub congestion_window: u64,
31 pub ssthresh: Option<u64>,
33 pub pacing_rate: Option<u64>,
35}
36
37pub trait Controller: Send + Sync {
39 fn on_sent(&mut self, now: Instant, bytes: u64, last_packet_number: u64) {
41 let _ = (now, bytes, last_packet_number);
42 }
43
44 fn on_ack(
46 &mut self,
47 now: Instant,
48 sent: Instant,
49 bytes: u64,
50 app_limited: bool,
51 rtt: &RttEstimator,
52 );
53
54 fn on_end_acks(
56 &mut self,
57 now: Instant,
58 in_flight: u64,
59 app_limited: bool,
60 largest_packet_num_acked: Option<u64>,
61 ) {
62 let _ = (now, in_flight, app_limited, largest_packet_num_acked);
63 }
64
65 fn on_congestion_event(
67 &mut self,
68 now: Instant,
69 sent: Instant,
70 is_persistent_congestion: bool,
71 lost_bytes: u64,
72 );
73
74 fn on_mtu_update(&mut self, new_mtu: u16);
76
77 fn window(&self) -> u64;
79
80 fn metrics(&self) -> ControllerMetrics {
82 ControllerMetrics {
83 congestion_window: self.window(),
84 ssthresh: None,
85 pacing_rate: None,
86 }
87 }
88
89 fn clone_box(&self) -> Box<dyn Controller>;
91
92 fn initial_window(&self) -> u64;
94
95 fn into_any(self: Box<Self>) -> Box<dyn Any>;
97}
98
99pub(crate) const BASE_DATAGRAM_SIZE: u64 = 1200;
101
102#[derive(Clone)]
106#[allow(dead_code)]
107pub(crate) struct NewReno {
108 window: u64,
110
111 ssthresh: u64,
113
114 min_window: u64,
116
117 max_window: u64,
119
120 initial_window: u64,
122
123 current_mtu: u64,
125
126 recovery_start_time: Instant,
128}
129
130impl NewReno {
131 #[allow(dead_code)]
133 pub(crate) fn new(min_window: u64, max_window: u64, now: Instant) -> Self {
134 let initial_window = min_window.max(10 * BASE_DATAGRAM_SIZE);
135 Self {
136 window: initial_window,
137 ssthresh: max_window,
138 min_window,
139 max_window,
140 initial_window,
141 current_mtu: BASE_DATAGRAM_SIZE,
142 recovery_start_time: now,
143 }
144 }
145}
146
147impl Controller for NewReno {
148 fn on_ack(
149 &mut self,
150 _now: Instant,
151 sent: Instant,
152 bytes: u64,
153 app_limited: bool,
154 _rtt: &RttEstimator,
155 ) {
156 if app_limited || sent <= self.recovery_start_time {
157 return;
158 }
159
160 if self.window < self.ssthresh {
161 self.window = (self.window + bytes).min(self.max_window);
163 } else {
164 let increase = (bytes * self.current_mtu) / self.window;
166 self.window = (self.window + increase).min(self.max_window);
167 }
168 }
169
170 fn on_congestion_event(
171 &mut self,
172 now: Instant,
173 sent: Instant,
174 is_persistent_congestion: bool,
175 _lost_bytes: u64,
176 ) {
177 if sent <= self.recovery_start_time {
178 return;
179 }
180
181 self.recovery_start_time = now;
182 self.window = (self.window / 2).max(self.min_window);
183 self.ssthresh = self.window;
184
185 if is_persistent_congestion {
186 self.window = self.min_window;
187 }
188 }
189
190 fn on_mtu_update(&mut self, new_mtu: u16) {
191 self.current_mtu = new_mtu as u64;
192 self.min_window = 2 * self.current_mtu;
193 self.window = self.window.max(self.min_window);
194 }
195
196 fn window(&self) -> u64 {
197 self.window
198 }
199
200 fn metrics(&self) -> ControllerMetrics {
201 ControllerMetrics {
202 congestion_window: self.window,
203 ssthresh: Some(self.ssthresh),
204 pacing_rate: None,
205 }
206 }
207
208 fn clone_box(&self) -> Box<dyn Controller> {
209 Box::new(self.clone())
210 }
211
212 fn initial_window(&self) -> u64 {
213 self.initial_window
214 }
215
216 fn into_any(self: Box<Self>) -> Box<dyn Any> {
217 self
218 }
219}
220
221pub trait ControllerFactory: Send + Sync {
223 fn new_controller(
225 &self,
226 min_window: u64,
227 max_window: u64,
228 now: Instant,
229 ) -> Box<dyn Controller + Send + Sync>;
230}