smoltcp/socket/tcp/
congestion.rs

1use crate::time::Instant;
2
3use super::RttEstimator;
4
5pub(super) mod no_control;
6
7#[cfg(feature = "socket-tcp-cubic")]
8pub(super) mod cubic;
9
10#[cfg(feature = "socket-tcp-reno")]
11pub(super) mod reno;
12
13#[allow(unused_variables)]
14pub(super) trait Controller {
15    /// Returns the number of bytes that can be sent.
16    fn window(&self) -> usize;
17
18    /// Set the remote window size.
19    fn set_remote_window(&mut self, remote_window: usize) {}
20
21    fn on_ack(&mut self, now: Instant, len: usize, rtt: &RttEstimator) {}
22
23    fn on_retransmit(&mut self, now: Instant) {}
24
25    fn on_duplicate_ack(&mut self, now: Instant) {}
26
27    fn pre_transmit(&mut self, now: Instant) {}
28
29    fn post_transmit(&mut self, now: Instant, len: usize) {}
30
31    /// Set the maximum segment size.
32    fn set_mss(&mut self, mss: usize) {}
33}
34
35#[derive(Debug)]
36#[cfg_attr(feature = "defmt", derive(defmt::Format))]
37pub(super) enum AnyController {
38    None(no_control::NoControl),
39
40    #[cfg(feature = "socket-tcp-reno")]
41    Reno(reno::Reno),
42
43    #[cfg(feature = "socket-tcp-cubic")]
44    Cubic(cubic::Cubic),
45}
46
47impl AnyController {
48    /// Create a new congestion controller.
49    /// `AnyController::new()` selects the best congestion controller based on the features.
50    ///
51    /// - If `socket-tcp-cubic` feature is enabled, it will use `Cubic`.
52    /// - If `socket-tcp-reno` feature is enabled, it will use `Reno`.
53    /// - If both `socket-tcp-cubic` and `socket-tcp-reno` features are enabled, it will use `Cubic`.
54    ///    - `Cubic` is more efficient regarding throughput.
55    ///    - `Reno` is more conservative and is suitable for low-power devices.
56    /// - If no congestion controller is available, it will use `NoControl`.
57    ///
58    /// Users can also select a congestion controller manually by [`super::Socket::set_congestion_control()`]
59    /// method at run-time.
60    #[allow(unreachable_code)]
61    #[inline]
62    pub fn new() -> Self {
63        #[cfg(feature = "socket-tcp-cubic")]
64        {
65            return AnyController::Cubic(cubic::Cubic::new());
66        }
67
68        #[cfg(feature = "socket-tcp-reno")]
69        {
70            return AnyController::Reno(reno::Reno::new());
71        }
72
73        AnyController::None(no_control::NoControl)
74    }
75
76    #[inline]
77    pub fn inner_mut(&mut self) -> &mut dyn Controller {
78        match self {
79            AnyController::None(n) => n,
80
81            #[cfg(feature = "socket-tcp-reno")]
82            AnyController::Reno(r) => r,
83
84            #[cfg(feature = "socket-tcp-cubic")]
85            AnyController::Cubic(c) => c,
86        }
87    }
88
89    #[inline]
90    pub fn inner(&self) -> &dyn Controller {
91        match self {
92            AnyController::None(n) => n,
93
94            #[cfg(feature = "socket-tcp-reno")]
95            AnyController::Reno(r) => r,
96
97            #[cfg(feature = "socket-tcp-cubic")]
98            AnyController::Cubic(c) => c,
99        }
100    }
101}