use crate::{
random,
recovery::{
bbr::{startup, BbrCongestionController, State},
congestion_controller::Publisher,
},
time::Timestamp,
};
use num_rational::Ratio;
use num_traits::One;
pub(crate) const PACING_GAIN: Ratio<u64> = Ratio::new_raw(1, 2);
pub(crate) const CWND_GAIN: Ratio<u64> = startup::CWND_GAIN;
impl BbrCongestionController {
#[inline]
pub(super) fn enter_drain<Pub: Publisher>(&mut self, publisher: &mut Pub) {
self.try_fast_path = false;
self.state.transition_to(State::Drain, publisher);
}
#[inline]
pub(super) fn check_drain_done<Pub: Publisher>(
&mut self,
random_generator: &mut dyn random::Generator,
now: Timestamp,
publisher: &mut Pub,
) {
if self.state.is_drain()
&& self.bytes_in_flight <= self.inflight(self.data_rate_model.bw(), Ratio::one())
{
self.enter_probe_bw(false, random_generator, now, publisher);
}
}
}
#[cfg(test)]
mod tests {
use crate::{
counter::Counter,
event, path,
path::MINIMUM_MAX_DATAGRAM_SIZE,
random,
recovery::{
bandwidth::RateSample, bbr::BbrCongestionController,
congestion_controller::PathPublisher,
},
time::{Clock, NoopClock},
};
use core::time::Duration;
#[test]
fn enter_drain() {
let mut bbr = BbrCongestionController::new(MINIMUM_MAX_DATAGRAM_SIZE, Default::default());
let mut publisher = event::testing::Publisher::snapshot();
let mut publisher = PathPublisher::new(&mut publisher, path::Id::test_id());
bbr.enter_drain(&mut publisher);
assert!(bbr.state.is_drain());
assert!(!bbr.try_fast_path);
}
#[test]
fn check_drain_done() {
let mut bbr = BbrCongestionController::new(MINIMUM_MAX_DATAGRAM_SIZE, Default::default());
let now = NoopClock.get_time();
let mut rng = random::testing::Generator::default();
let mut publisher = event::testing::Publisher::snapshot();
let mut publisher = PathPublisher::new(&mut publisher, path::Id::test_id());
bbr.check_drain_done(&mut rng, now, &mut publisher);
assert!(bbr.state.is_startup());
bbr.enter_drain(&mut publisher);
bbr.bytes_in_flight = Counter::new(100);
bbr.check_drain_done(&mut rng, now, &mut publisher);
assert!(!bbr.state.is_drain());
let rate_sample = RateSample {
delivered_bytes: 100_000,
interval: Duration::from_millis(1),
..Default::default()
};
bbr.data_rate_model.update_max_bw(rate_sample);
bbr.data_rate_model.bound_bw_for_model();
bbr.check_drain_done(&mut rng, now, &mut publisher);
assert!(bbr.state.is_probing_bw());
}
}