quiche/recovery/gcongestion/bbr2/
drain.rs1use std::time::Instant;
32
33use crate::recovery::gcongestion::bbr2::Params;
34use crate::recovery::gcongestion::Acked;
35use crate::recovery::gcongestion::Lost;
36use crate::recovery::RecoveryStats;
37
38use super::mode::Cycle;
39use super::mode::Mode;
40use super::mode::ModeImpl;
41use super::network_model::BBRv2NetworkModel;
42use super::BBRv2CongestionEvent;
43use super::Limits;
44
45#[derive(Debug)]
46pub(super) struct Drain {
47 pub(super) model: BBRv2NetworkModel,
48 pub(super) cycle: Cycle,
49}
50
51impl ModeImpl for Drain {
52 #[cfg(feature = "qlog")]
53 fn state_str(&self) -> &'static str {
54 "bbr_drain"
55 }
56
57 fn is_probing_for_bandwidth(&self) -> bool {
58 false
59 }
60
61 fn on_congestion_event(
62 mut self, _prior_in_flight: usize, event_time: Instant,
63 _acked_packets: &[Acked], _lost_packets: &[Lost],
64 congestion_event: &mut BBRv2CongestionEvent,
65 _target_bytes_inflight: usize, params: &Params,
66 _recovery_stats: &mut RecoveryStats, _cwnd: usize,
67 ) -> Mode {
68 self.model.set_pacing_gain(params.drain_pacing_gain);
69 self.model.set_cwnd_gain(params.drain_cwnd_gain);
72
73 let drain_target = self.drain_target();
74 if congestion_event.bytes_in_flight <= drain_target {
75 return self.into_probe_bw(
76 event_time,
77 Some(congestion_event),
78 params,
79 );
80 }
81
82 Mode::Drain(self)
83 }
84
85 fn get_cwnd_limits(&self, _params: &Params) -> Limits<usize> {
86 Limits {
87 lo: 0,
88 hi: self.model.inflight_lo(),
89 }
90 }
91
92 fn on_exit_quiescence(
93 self, _now: Instant, _quiescence_start_time: Instant, _params: &Params,
94 ) -> Mode {
95 Mode::Drain(self)
96 }
97
98 fn enter(
99 &mut self, _: Instant, _: Option<&BBRv2CongestionEvent>, _params: &Params,
100 ) {
101 }
102
103 fn leave(&mut self, _: Instant, _: Option<&BBRv2CongestionEvent>) {}
104}
105
106impl Drain {
107 fn into_probe_bw(
108 mut self, now: Instant, congestion_event: Option<&BBRv2CongestionEvent>,
109 params: &Params,
110 ) -> Mode {
111 self.leave(now, congestion_event);
112 let mut next_mode = Mode::probe_bw(self.model, self.cycle);
113 next_mode.enter(now, congestion_event, params);
114 next_mode
115 }
116
117 fn drain_target(&self) -> usize {
118 self.model.bdp0()
119 }
120}