1
//! Implementation of the Fixed Window congestion control algorithm.
2
//!
3
//! This is used by the circuit reactor in order to decide when to send data and SENDMEs.
4
//!
5
//! The vanilla flow control system of fixed window SENDMEs in the spec.
6

            
7
use crate::Result;
8

            
9
use super::{
10
    params::{Algorithm, FixedWindowParams},
11
    rtt::RoundtripTimeEstimator,
12
    sendme::{self, WindowParams},
13
    CongestionControlAlgorithm, CongestionSignals, CongestionWindow, State,
14
};
15

            
16
/// Fixed window algorithm which is essentially the SENDME v0 with fixed receive and send window
17
/// size.
18
#[derive(Clone, Debug)]
19
pub(crate) struct FixedWindow {
20
    /// Window used to say how many cells we can receive.
21
    recvwindow: sendme::CircRecvWindow,
22
    /// Window used to say how many cells we can send.
23
    sendwindow: sendme::CircSendWindow,
24
    /// The params from the consensus.
25
    params: FixedWindowParams,
26
}
27

            
28
impl FixedWindow {
29
    /// Create a new `FixedWindow` form a given initial sendwindow size.
30
    ///
31
    /// Note: the initial recvwindow size is given by [`sendme::CircParams::start`].
32
472
    pub(crate) fn new(params: FixedWindowParams) -> Self {
33
472
        let initial_window = params.circ_window_start();
34
472
        Self {
35
472
            recvwindow: sendme::CircRecvWindow::new(sendme::CircParams::start()),
36
472
            sendwindow: sendme::CircSendWindow::new(initial_window),
37
472
            params,
38
472
        }
39
472
    }
40
}
41

            
42
impl CongestionControlAlgorithm for FixedWindow {
43
80
    fn uses_stream_sendme(&self) -> bool {
44
80
        true
45
80
    }
46

            
47
2728
    fn is_next_cell_sendme(&self) -> bool {
48
2728
        self.sendwindow.should_record_tag()
49
2728
    }
50

            
51
10120
    fn can_send(&self) -> bool {
52
10120
        self.sendwindow.window() > 0
53
10120
    }
54

            
55
28
    fn cwnd(&self) -> Option<&CongestionWindow> {
56
28
        None
57
28
    }
58

            
59
4
    fn sendme_received(
60
4
        &mut self,
61
4
        _state: &mut State,
62
4
        _rtt: &mut RoundtripTimeEstimator,
63
4
        _signals: CongestionSignals,
64
4
    ) -> Result<()> {
65
4
        self.sendwindow.put()
66
4
    }
67

            
68
    fn sendme_sent(&mut self) -> Result<()> {
69
        self.recvwindow.put();
70
        Ok(())
71
    }
72

            
73
24
    fn data_received(&mut self) -> Result<bool> {
74
24
        self.recvwindow.take()
75
24
    }
76

            
77
2728
    fn data_sent(&mut self) -> Result<()> {
78
2728
        self.sendwindow.take()
79
2728
    }
80

            
81
    #[cfg(feature = "conflux")]
82
    fn inflight(&self) -> Option<u32> {
83
        None
84
    }
85

            
86
    #[cfg(test)]
87
8
    fn send_window(&self) -> u32 {
88
8
        u32::from(self.sendwindow.window())
89
8
    }
90

            
91
4
    fn algorithm(&self) -> Algorithm {
92
4
        Algorithm::FixedWindow(self.params)
93
4
    }
94
}