quiche/recovery/gcongestion/bbr2/
probe_rtt.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 ProbeRTT {
47 pub(super) model: BBRv2NetworkModel,
48 pub(super) cycle: Cycle,
49 exit_time: Option<Instant>,
50}
51
52impl ProbeRTT {
53 pub(super) fn new(model: BBRv2NetworkModel, cycle: Cycle) -> Self {
54 ProbeRTT {
55 model,
56 cycle,
57 exit_time: None,
58 }
59 }
60
61 fn into_probe_bw(
62 mut self, now: Instant, congestion_event: Option<&BBRv2CongestionEvent>,
63 params: &Params,
64 ) -> Mode {
65 self.leave(now, congestion_event);
66 let mut next_mode = Mode::probe_bw(self.model, self.cycle);
67 next_mode.enter(now, congestion_event, params);
68 next_mode
69 }
70
71 fn inflight_target(&self, params: &Params) -> usize {
72 self.model.bdp(
73 self.model.max_bandwidth(),
74 params.probe_rtt_inflight_target_bdp_fraction,
75 )
76 }
77}
78
79impl ModeImpl for ProbeRTT {
80 #[cfg(feature = "qlog")]
81 fn state_str(&self) -> &'static str {
82 "bbr_probe_rtt"
83 }
84
85 fn is_probing_for_bandwidth(&self) -> bool {
86 false
87 }
88
89 fn on_congestion_event(
90 mut self, _prior_in_flight: usize, event_time: Instant,
91 _acked_packets: &[Acked], _lost_packets: &[Lost],
92 congestion_event: &mut BBRv2CongestionEvent,
93 _target_bytes_inflight: usize, params: &Params,
94 _recovery_stats: &mut RecoveryStats, _cwnd: usize,
95 ) -> Mode {
96 match self.exit_time {
97 None => {
98 if congestion_event.bytes_in_flight <=
99 self.inflight_target(params)
100 {
101 self.exit_time = Some(
102 congestion_event.event_time + params.probe_rtt_duration,
103 )
104 }
105 Mode::ProbeRTT(self)
106 },
107 Some(exit_time) =>
108 if congestion_event.event_time > exit_time {
109 self.into_probe_bw(event_time, Some(congestion_event), params)
110 } else {
111 Mode::ProbeRTT(self)
112 },
113 }
114 }
115
116 fn get_cwnd_limits(&self, params: &Params) -> Limits<usize> {
117 let inflight_upper_bound = self
118 .model
119 .inflight_lo()
120 .min(self.model.inflight_hi_with_headroom(params));
121 Limits::no_greater_than(
122 inflight_upper_bound.min(self.inflight_target(params)),
123 )
124 }
125
126 fn on_exit_quiescence(
127 self, now: Instant, _quiescence_start_time: Instant, params: &Params,
128 ) -> Mode {
129 match self.exit_time {
130 None => self.into_probe_bw(now, None, params),
131 Some(exit_time) if now > exit_time =>
132 self.into_probe_bw(now, None, params),
133 Some(_) => Mode::ProbeRTT(self),
134 }
135 }
136
137 fn enter(
138 &mut self, _now: Instant,
139 _congestion_event: Option<&BBRv2CongestionEvent>, _params: &Params,
140 ) {
141 self.model.set_pacing_gain(1.0);
142 self.model.set_cwnd_gain(1.0);
143 self.exit_time = None;
144 }
145
146 fn leave(
147 &mut self, _now: Instant,
148 _congestion_event: Option<&BBRv2CongestionEvent>,
149 ) {
150 }
151}