cyfs_bdt/cc/
cc.rs

1use std::{
2    time::Duration
3};
4use crate::types::*;
5use super::{
6    cc_impl::CcImpl, 
7    ledbat::{self, Ledbat},
8    bbr::{self, Bbr},
9};
10
11
12#[derive(Debug)]
13struct EstimateRtt {
14    srtt: i64, // smoothed round trip time << 3
15    mdev: i64, //medium deviation
16    mdev_max: i64, //maximal m_dev for the last rtt period
17    rttvar: i64, //smoothed m_dev_max
18    // rtt_seq: i64, //sequence number to update rtt_var
19    min_rtt: i64,
20}
21
22impl EstimateRtt {
23    fn new() -> Self {
24        Self {
25            srtt: 0,
26            mdev: Duration::from_secs(1).as_micros() as i64,
27            mdev_max: 0,
28            rttvar: 0,
29            // rtt_seq: 0,
30            min_rtt: 0,
31        }
32    }
33
34    fn update(&mut self, config: &Config, rtt: Duration) -> (Duration/*srtt*/, Duration/*rto*/) {
35        let mut rtt = rtt.as_micros() as i64;
36        if rtt == 0 {
37            rtt = 1;
38        }
39
40        if self.min_rtt == 0 ||
41            self.min_rtt > rtt {
42            self.min_rtt = rtt;
43        }
44
45        if self.srtt != 0 {
46            rtt -= self.srtt / 8;
47            self.srtt += rtt;
48            if rtt < 0 {
49                rtt = 0 - rtt;
50                rtt -= self.mdev / 4;
51                if rtt > 0 {
52                    rtt >>= 3;
53                }
54            } else {
55                rtt -= self.mdev / 4;
56            }
57
58            self.mdev = self.mdev + rtt;
59
60            if self.mdev > self.mdev_max {
61                self.mdev_max = self.mdev;
62                if self.mdev_max > self.rttvar {
63                    self.rttvar = self.mdev_max;
64                }
65            }
66            if self.mdev < self.mdev_max {
67                self.rttvar -= (self.rttvar - self.mdev_max) / 4;
68            }
69            self.mdev_max = config.min_rto.as_micros() as i64;
70        } else {
71            self.srtt = rtt * 8;
72            self.mdev = rtt * 2;
73            self.rttvar = std::cmp::max(self.mdev, config.min_rto.as_micros() as i64);
74            self.mdev_max = self.rttvar;
75        }
76        let srtt = (self.srtt / 8) as u64;
77        let rto = (self.srtt / 8 + self.rttvar) as u64;
78        (Duration::from_micros(srtt), Duration::from_micros(rto))
79    }
80}
81
82#[derive(Clone)]
83pub enum ImplConfig {
84    Ledbat(ledbat::Config),
85    BBR(bbr::Config),
86}
87
88#[derive(Clone)]
89pub struct Config {
90    pub init_rto: Duration, 
91    pub min_rto: Duration, 
92    pub cc_impl: ImplConfig
93}
94
95pub struct CongestionControl {
96    rtt: Duration, 
97    rto: Duration, 
98    config: Config, 
99    est_rtt: EstimateRtt, 
100    cc: Box<dyn CcImpl>, 
101}
102
103impl CongestionControl {
104    pub fn new(mss: usize, config: &Config) -> Self {
105        Self {
106            rtt: Duration::from_secs(0), 
107            rto: config.init_rto, 
108            est_rtt: EstimateRtt::new(), 
109            cc: match &config.cc_impl { 
110                ImplConfig::Ledbat(config) => {
111                    Box::new(Ledbat::new(mss, config))
112                },
113                ImplConfig::BBR(config) => {
114                    Box::new(Bbr::new(mss, config))
115                }
116            },
117            config: config.clone()
118        }
119    }
120    
121    pub fn on_sent(&mut self, now: Timestamp, bytes: u64, last_packet_number: u64) {
122        self.cc.on_sent(now, bytes, last_packet_number);
123    }
124
125    pub fn cwnd(&self) -> u64 {
126        self.cc.cwnd()
127    }
128
129    pub fn rto(&self) -> Duration {
130        self.rto
131    }
132
133    pub fn rtt(&self) -> Duration {
134        self.rtt
135    }
136
137    pub fn on_estimate(&mut self, est_rtt: Duration, est_delay: Duration, app_limited: bool) {
138        let (rtt, rto) = self.est_rtt.update(&self.config, est_rtt);
139        self.rto = rto;
140        self.rtt = rtt;
141        self.cc.on_estimate(Duration::from_micros(self.est_rtt.min_rtt as u64), rto, est_delay, app_limited);
142    }
143
144    pub fn on_ack(&mut self,
145        flight: u64, 
146        ack: u64,
147        largest_packet_num_acked: Option<u64>, 
148        sent_time: Timestamp,
149        app_limited: bool) {
150        self.cc.on_ack(flight, ack, largest_packet_num_acked, sent_time, app_limited)
151    }
152
153    pub fn on_loss(&mut self, lost: u64) {
154        self.cc.on_loss(lost)
155    }
156
157    pub fn on_no_resp(&mut self, lost: u64) {
158        let rto = self.cc.on_no_resp(self.rto, lost);
159        self.rto = rto;
160    }
161
162    pub fn on_time_escape(&mut self, now: Timestamp) {
163        self.cc.on_time_escape(now)
164    }
165
166    pub fn rate(&self) -> u64 {
167        self.cc.rate()
168    }
169}