Skip to main content

quiche/recovery/gcongestion/bbr/
bandwidth_sampler.rs

1// Copyright (c) 2016 The Chromium Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5// Copyright (C) 2023, Cloudflare, Inc.
6// All rights reserved.
7//
8// Redistribution and use in source and binary forms, with or without
9// modification, are permitted provided that the following conditions are
10// met:
11//
12//     * Redistributions of source code must retain the above copyright notice,
13//       this list of conditions and the following disclaimer.
14//
15//     * Redistributions in binary form must reproduce the above copyright
16//       notice, this list of conditions and the following disclaimer in the
17//       documentation and/or other materials provided with the distribution.
18//
19// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
20// IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
21// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
23// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
24// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
25// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
26// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
27// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
28// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
29// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30
31use std::collections::VecDeque;
32use std::time::Duration;
33use std::time::Instant;
34
35use super::Acked;
36use crate::recovery::gcongestion::Bandwidth;
37use crate::recovery::gcongestion::Lost;
38
39use super::windowed_filter::WindowedFilter;
40
41#[derive(Debug)]
42struct ConnectionStateMap<T> {
43    packet_map: VecDeque<(u64, Option<T>)>,
44}
45
46impl<T> Default for ConnectionStateMap<T> {
47    fn default() -> Self {
48        ConnectionStateMap {
49            packet_map: VecDeque::new(),
50        }
51    }
52}
53
54impl<T> ConnectionStateMap<T> {
55    fn insert(&mut self, pkt_num: u64, val: T) {
56        if let Some((last_pkt, _)) = self.packet_map.back() {
57            assert!(pkt_num > *last_pkt, "{} > {}", pkt_num, *last_pkt);
58        }
59
60        self.packet_map.push_back((pkt_num, Some(val)));
61    }
62
63    fn take(&mut self, pkt_num: u64) -> Option<T> {
64        // First we check if the next packet is the one we are looking for
65        let first = self.packet_map.front()?;
66        if first.0 == pkt_num {
67            return self.packet_map.pop_front().and_then(|(_, v)| v);
68        }
69        // Use binary search
70        let ret =
71            match self.packet_map.binary_search_by_key(&pkt_num, |&(n, _)| n) {
72                Ok(found) =>
73                    self.packet_map.get_mut(found).and_then(|(_, v)| v.take()),
74                Err(_) => None,
75            };
76
77        while let Some((_, None)) = self.packet_map.front() {
78            self.packet_map.pop_front();
79        }
80
81        ret
82    }
83
84    #[cfg(test)]
85    fn peek(&self, pkt_num: u64) -> Option<&T> {
86        // Use binary search
87        match self.packet_map.binary_search_by_key(&pkt_num, |&(n, _)| n) {
88            Ok(found) => self.packet_map.get(found).and_then(|(_, v)| v.as_ref()),
89            Err(_) => None,
90        }
91    }
92
93    fn remove_obsolete(&mut self, least_acked: u64) {
94        while match self.packet_map.front() {
95            Some(&(p, _)) if p < least_acked => {
96                self.packet_map.pop_front();
97                true
98            },
99            _ => false,
100        } {}
101    }
102}
103
104#[derive(Debug)]
105pub struct BandwidthSampler {
106    /// The total number of congestion controlled bytes sent during the
107    /// connection.
108    total_bytes_sent: usize,
109    total_bytes_acked: usize,
110    total_bytes_lost: usize,
111    total_bytes_neutered: usize,
112    last_sent_packet: u64,
113    last_acked_packet: u64,
114    is_app_limited: bool,
115    last_acked_packet_ack_time: Instant,
116    total_bytes_sent_at_last_acked_packet: usize,
117    last_acked_packet_sent_time: Instant,
118    recent_ack_points: RecentAckPoints,
119    a0_candidates: VecDeque<AckPoint>,
120    connection_state_map: ConnectionStateMap<ConnectionStateOnSentPacket>,
121    max_ack_height_tracker: MaxAckHeightTracker,
122    /// The packet that will be acknowledged after this one will cause the
123    /// sampler to exit the app-limited phase.
124    end_of_app_limited_phase: Option<u64>,
125    overestimate_avoidance: bool,
126    // If true, apply the fix to A0 point selection logic so the
127    // implementation is consistent with the behavior of the
128    // google/quiche implementation.
129    choose_a0_point_fix: bool,
130    limit_max_ack_height_tracker_by_send_rate: bool,
131
132    total_bytes_acked_after_last_ack_event: usize,
133}
134
135/// A subset of [`ConnectionStateOnSentPacket`] which is returned
136/// to the caller when the packet is acked or lost.
137#[derive(Debug, Default, Clone, Copy)]
138pub struct SendTimeState {
139    /// Whether other states in this object is valid.
140    pub is_valid: bool,
141    /// Whether the sender is app limited at the time the packet was sent.
142    /// App limited bandwidth sample might be artificially low because the
143    /// sender did not have enough data to send in order to saturate the
144    /// link.
145    pub is_app_limited: bool,
146    /// Total number of sent bytes at the time the packet was sent.
147    /// Includes the packet itself.
148    pub total_bytes_sent: usize,
149    /// Total number of acked bytes at the time the packet was sent.
150    pub total_bytes_acked: usize,
151    /// Total number of lost bytes at the time the packet was sent.
152    #[allow(dead_code)]
153    pub total_bytes_lost: usize,
154    /// Total number of inflight bytes at the time the packet was sent.
155    /// Includes the packet itself.
156    /// It should be equal to `total_bytes_sent` minus the sum of
157    /// `total_bytes_acked`, `total_bytes_lost` and total neutered bytes.
158    pub bytes_in_flight: usize,
159}
160
161#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Clone, Copy, Default)]
162struct ExtraAckedEvent {
163    /// The excess bytes acknowlwedged in the time delta for this event.
164    extra_acked: usize,
165    /// The bytes acknowledged and time delta from the event.
166    bytes_acked: usize,
167    time_delta: Duration,
168    /// The round trip of the event.
169    round: usize,
170}
171
172// BandwidthSample holds per-packet rate measurements
173// This is the internal struct used by BandwidthSampler to track rates
174struct BandwidthSample {
175    /// The bandwidth at that particular sample.
176    bandwidth: Bandwidth,
177    /// The RTT measurement at this particular sample.  Does not correct for
178    /// delayed ack time.
179    rtt: Duration,
180    /// `send_rate` is computed from the current packet being acked('P') and
181    /// an earlier packet that is acked before P was sent.
182    /// <https://www.ietf.org/archive/id/draft-ietf-ccwg-bbr-04.html#name-send-rate>
183    send_rate: Option<Bandwidth>,
184    // ack_rate tracks the acknowledgment rate for this sample
185    /// `ack_rate` is computed as bytes_acked_delta / time_delta between ack
186    /// points. <https://www.ietf.org/archive/id/draft-ietf-ccwg-bbr-04.html#name-ack-rate>
187    ack_rate: Bandwidth,
188    /// States captured when the packet was sent.
189    state_at_send: SendTimeState,
190}
191
192/// [`AckPoint`] represents a point on the ack line.
193#[derive(Debug, Clone, Copy)]
194struct AckPoint {
195    ack_time: Instant,
196    total_bytes_acked: usize,
197}
198
199/// [`RecentAckPoints`] maintains the most recent 2 ack points at distinct
200/// times.
201#[derive(Debug, Default)]
202struct RecentAckPoints {
203    ack_points: [Option<AckPoint>; 2],
204}
205
206// [`ConnectionStateOnSentPacket`] represents the information about a sent
207// packet and the state of the connection at the moment the packet was sent,
208// specifically the information about the most recently acknowledged packet at
209// that moment.
210#[derive(Debug)]
211struct ConnectionStateOnSentPacket {
212    /// Time at which the packet is sent.
213    sent_time: Instant,
214    /// Size of the packet.
215    size: usize,
216    /// The value of [`BandwidthSampler::total_bytes_sent_at_last_acked_packet`]
217    /// at the time the packet was sent.
218    total_bytes_sent_at_last_acked_packet: usize,
219    /// The value of [`BandwidthSampler::last_acked_packet_sent_time`] at the
220    /// time the packet was sent.
221    last_acked_packet_sent_time: Instant,
222    /// The value of [`BandwidthSampler::last_acked_packet_ack_time`] at the
223    /// time the packet was sent.
224    last_acked_packet_ack_time: Instant,
225    /// Send time states that are returned to the congestion controller when the
226    /// packet is acked or lost.
227    send_time_state: SendTimeState,
228}
229
230/// [`MaxAckHeightTracker`] is part of the [`BandwidthSampler`]. It is called
231/// after every ack event to keep track the degree of ack
232/// aggregation(a.k.a "ack height").
233#[derive(Debug)]
234struct MaxAckHeightTracker {
235    /// Tracks the maximum number of bytes acked faster than the estimated
236    /// bandwidth.
237    max_ack_height_filter: WindowedFilter<ExtraAckedEvent, usize, usize>,
238    /// The time this aggregation started and the number of bytes acked during
239    /// it.
240    aggregation_epoch_start_time: Option<Instant>,
241    aggregation_epoch_bytes: usize,
242    /// The last sent packet number before the current aggregation epoch
243    /// started.
244    last_sent_packet_number_before_epoch: u64,
245    /// The number of ack aggregation epochs ever started, including the ongoing
246    /// one. Stats only.
247    num_ack_aggregation_epochs: u64,
248    ack_aggregation_bandwidth_threshold: f64,
249    start_new_aggregation_epoch_after_full_round: bool,
250    reduce_extra_acked_on_bandwidth_increase: bool,
251}
252
253/// Measurements collected from a congestion event, used for bandwidth
254/// estimation and congestion control in BBR.
255#[derive(Default)]
256pub(crate) struct CongestionEventSample {
257    /// The maximum bandwidth sample from all acked packets.
258    pub sample_max_bandwidth: Option<Bandwidth>,
259    /// Whether [`Self::sample_max_bandwidth`] is from a app-limited sample.
260    pub sample_is_app_limited: bool,
261    /// The minimum rtt sample from all acked packets.
262    pub sample_rtt: Option<Duration>,
263    /// For each packet p in acked packets, this is the max value of
264    /// INFLIGHT(p), where INFLIGHT(p) is the number of bytes acked while p
265    /// is inflight.
266    pub sample_max_inflight: usize,
267    /// The send state of the largest packet in acked_packets, unless it is
268    /// empty. If acked_packets is empty, it's the send state of the largest
269    /// packet in lost_packets.
270    pub last_packet_send_state: SendTimeState,
271    /// The number of extra bytes acked from this ack event, compared to what is
272    /// expected from the flow's bandwidth. Larger value means more ack
273    /// aggregation.
274    pub extra_acked: usize,
275
276    /// The maximum send rate observed across all acked packets in this event.
277    /// Computed as bytes_sent_delta / time_delta between packet send times.
278    pub sample_max_send_rate: Option<Bandwidth>,
279    /// The maximum ack rate observed across all acked packets in this event.
280    /// Computed as bytes_acked_delta / time_delta between ack times.
281    pub sample_max_ack_rate: Option<Bandwidth>,
282}
283
284impl MaxAckHeightTracker {
285    pub(crate) fn new(window: usize, overestimate_avoidance: bool) -> Self {
286        MaxAckHeightTracker {
287            max_ack_height_filter: WindowedFilter::new(window),
288            aggregation_epoch_start_time: None,
289            aggregation_epoch_bytes: 0,
290            last_sent_packet_number_before_epoch: 0,
291            num_ack_aggregation_epochs: 0,
292            ack_aggregation_bandwidth_threshold: if overestimate_avoidance {
293                2.0
294            } else {
295                1.0
296            },
297            start_new_aggregation_epoch_after_full_round: true,
298            reduce_extra_acked_on_bandwidth_increase: true,
299        }
300    }
301
302    #[allow(dead_code)]
303    fn reset(&mut self, new_height: usize, new_time: usize) {
304        self.max_ack_height_filter.reset(
305            ExtraAckedEvent {
306                extra_acked: new_height,
307                bytes_acked: 0,
308                time_delta: Duration::ZERO,
309                round: new_time,
310            },
311            new_time,
312        );
313    }
314
315    #[allow(clippy::too_many_arguments)]
316    fn update(
317        &mut self, bandwidth_estimate: Bandwidth, is_new_max_bandwidth: bool,
318        round_trip_count: usize, last_sent_packet_number: u64,
319        last_acked_packet_number: u64, ack_time: Instant, bytes_acked: usize,
320    ) -> usize {
321        let mut force_new_epoch = false;
322
323        if self.reduce_extra_acked_on_bandwidth_increase && is_new_max_bandwidth {
324            // Save and clear existing entries.
325            let mut best =
326                self.max_ack_height_filter.get_best().unwrap_or_default();
327            let mut second_best = self
328                .max_ack_height_filter
329                .get_second_best()
330                .unwrap_or_default();
331            let mut third_best = self
332                .max_ack_height_filter
333                .get_third_best()
334                .unwrap_or_default();
335            self.max_ack_height_filter.clear();
336
337            // Reinsert the heights into the filter after recalculating.
338            let expected_bytes_acked =
339                bandwidth_estimate.to_bytes_per_period(best.time_delta) as usize;
340            if expected_bytes_acked < best.bytes_acked {
341                best.extra_acked = best.bytes_acked - expected_bytes_acked;
342                self.max_ack_height_filter.update(best, best.round);
343            }
344
345            let expected_bytes_acked = bandwidth_estimate
346                .to_bytes_per_period(second_best.time_delta)
347                as usize;
348            if expected_bytes_acked < second_best.bytes_acked {
349                second_best.extra_acked =
350                    second_best.bytes_acked - expected_bytes_acked;
351                self.max_ack_height_filter
352                    .update(second_best, second_best.round);
353            }
354
355            let expected_bytes_acked = bandwidth_estimate
356                .to_bytes_per_period(third_best.time_delta)
357                as usize;
358            if expected_bytes_acked < third_best.bytes_acked {
359                third_best.extra_acked =
360                    third_best.bytes_acked - expected_bytes_acked;
361                self.max_ack_height_filter
362                    .update(third_best, third_best.round);
363            }
364        }
365
366        // Start a new epoch if this epoch includes any acknowledged packet.
367        if self.start_new_aggregation_epoch_after_full_round &&
368            last_acked_packet_number >
369                self.last_sent_packet_number_before_epoch
370        {
371            force_new_epoch = true;
372        }
373
374        let epoch_start_time = match self.aggregation_epoch_start_time {
375            Some(time) if !force_new_epoch => time,
376            _ => {
377                self.aggregation_epoch_bytes = bytes_acked;
378                self.aggregation_epoch_start_time = Some(ack_time);
379                self.last_sent_packet_number_before_epoch =
380                    last_sent_packet_number;
381                self.num_ack_aggregation_epochs += 1;
382                return 0;
383            },
384        };
385
386        // Compute how many bytes are expected to be delivered, assuming max
387        // bandwidth is correct.
388        let aggregation_delta = ack_time.duration_since(epoch_start_time);
389        let expected_bytes_acked =
390            bandwidth_estimate.to_bytes_per_period(aggregation_delta) as usize;
391        // Reset the current aggregation epoch as soon as the ack arrival rate
392        // is less than or equal to the max bandwidth.
393        if self.aggregation_epoch_bytes <=
394            (self.ack_aggregation_bandwidth_threshold *
395                expected_bytes_acked as f64) as usize
396        {
397            // Reset to start measuring a new aggregation epoch.
398            self.aggregation_epoch_bytes = bytes_acked;
399            self.aggregation_epoch_start_time = Some(ack_time);
400            self.last_sent_packet_number_before_epoch = last_sent_packet_number;
401            self.num_ack_aggregation_epochs += 1;
402            return 0;
403        }
404
405        self.aggregation_epoch_bytes += bytes_acked;
406
407        // Compute how many extra bytes were delivered vs max bandwidth.
408        let extra_bytes_acked =
409            self.aggregation_epoch_bytes - expected_bytes_acked;
410
411        let new_event = ExtraAckedEvent {
412            extra_acked: extra_bytes_acked,
413            bytes_acked: self.aggregation_epoch_bytes,
414            time_delta: aggregation_delta,
415            round: 0,
416        };
417
418        self.max_ack_height_filter
419            .update(new_event, round_trip_count);
420        extra_bytes_acked
421    }
422}
423
424impl From<(Instant, usize, usize, &BandwidthSampler)>
425    for ConnectionStateOnSentPacket
426{
427    fn from(
428        (sent_time, size, bytes_in_flight, sampler): (
429            Instant,
430            usize,
431            usize,
432            &BandwidthSampler,
433        ),
434    ) -> Self {
435        ConnectionStateOnSentPacket {
436            sent_time,
437            size,
438            total_bytes_sent_at_last_acked_packet: sampler
439                .total_bytes_sent_at_last_acked_packet,
440            last_acked_packet_sent_time: sampler.last_acked_packet_sent_time,
441            last_acked_packet_ack_time: sampler.last_acked_packet_ack_time,
442            send_time_state: SendTimeState {
443                is_valid: true,
444                is_app_limited: sampler.is_app_limited,
445                total_bytes_sent: sampler.total_bytes_sent,
446                total_bytes_acked: sampler.total_bytes_acked,
447                total_bytes_lost: sampler.total_bytes_lost,
448                bytes_in_flight,
449            },
450        }
451    }
452}
453
454impl RecentAckPoints {
455    fn update(&mut self, ack_time: Instant, total_bytes_acked: usize) {
456        assert!(
457            total_bytes_acked >=
458                self.ack_points[1].map(|p| p.total_bytes_acked).unwrap_or(0)
459        );
460
461        self.ack_points[0] = self.ack_points[1];
462        self.ack_points[1] = Some(AckPoint {
463            ack_time,
464            total_bytes_acked,
465        });
466    }
467
468    fn clear(&mut self) {
469        self.ack_points = Default::default();
470    }
471
472    fn most_recent(&self) -> Option<AckPoint> {
473        self.ack_points[1]
474    }
475
476    fn less_recent_point(&self, choose_a0_point_fix: bool) -> Option<AckPoint> {
477        if choose_a0_point_fix {
478            self.ack_points[0]
479                .filter(|ack_point| ack_point.total_bytes_acked > 0)
480                .or(self.ack_points[1])
481        } else {
482            self.ack_points[0].or(self.ack_points[1])
483        }
484    }
485}
486
487impl BandwidthSampler {
488    pub(crate) fn new(
489        max_height_tracker_window_length: usize, overestimate_avoidance: bool,
490        choose_a0_point_fix: bool,
491    ) -> Self {
492        BandwidthSampler {
493            total_bytes_sent: 0,
494            total_bytes_acked: 0,
495            total_bytes_lost: 0,
496            total_bytes_neutered: 0,
497            total_bytes_sent_at_last_acked_packet: 0,
498            last_acked_packet_sent_time: Instant::now(),
499            last_acked_packet_ack_time: Instant::now(),
500            is_app_limited: true,
501            connection_state_map: ConnectionStateMap::default(),
502            max_ack_height_tracker: MaxAckHeightTracker::new(
503                max_height_tracker_window_length,
504                overestimate_avoidance,
505            ),
506            total_bytes_acked_after_last_ack_event: 0,
507            overestimate_avoidance,
508            choose_a0_point_fix,
509            limit_max_ack_height_tracker_by_send_rate: false,
510
511            last_sent_packet: 0,
512            last_acked_packet: 0,
513            recent_ack_points: RecentAckPoints::default(),
514            a0_candidates: VecDeque::new(),
515            end_of_app_limited_phase: None,
516        }
517    }
518
519    #[allow(dead_code)]
520    pub(crate) fn is_app_limited(&self) -> bool {
521        self.is_app_limited
522    }
523
524    pub(crate) fn on_packet_sent(
525        &mut self, sent_time: Instant, packet_number: u64, bytes: usize,
526        bytes_in_flight: usize, has_retransmittable_data: bool,
527    ) {
528        self.last_sent_packet = packet_number;
529
530        if !has_retransmittable_data {
531            return;
532        }
533
534        self.total_bytes_sent += bytes;
535
536        // If there are no packets in flight, the time at which the new
537        // transmission opens can be treated as the A_0 point for the
538        // purpose of bandwidth sampling. This underestimates bandwidth to
539        // some extent, and produces some artificially low samples for
540        // most packets in flight, but it provides with samples at
541        // important points where we would not have them otherwise, most
542        // importantly at the beginning of the connection.
543        if bytes_in_flight == 0 {
544            self.last_acked_packet_ack_time = sent_time;
545            if self.overestimate_avoidance {
546                self.recent_ack_points.clear();
547                self.recent_ack_points
548                    .update(sent_time, self.total_bytes_acked);
549                self.a0_candidates.clear();
550                self.a0_candidates
551                    .push_back(self.recent_ack_points.most_recent().unwrap());
552            }
553
554            self.total_bytes_sent_at_last_acked_packet = self.total_bytes_sent;
555
556            // In this situation ack compression is not a concern, set send rate
557            // to effectively infinite.
558            self.last_acked_packet_sent_time = sent_time;
559        }
560
561        self.connection_state_map.insert(
562            packet_number,
563            (sent_time, bytes, bytes_in_flight + bytes, &*self).into(),
564        );
565    }
566
567    pub(crate) fn on_packet_neutered(&mut self, packet_number: u64) {
568        if let Some(pkt) = self.connection_state_map.take(packet_number) {
569            self.total_bytes_neutered += pkt.size;
570        }
571    }
572
573    pub(crate) fn on_congestion_event(
574        &mut self, ack_time: Instant, acked_packets: &[Acked],
575        lost_packets: &[Lost], mut max_bandwidth: Option<Bandwidth>,
576        est_bandwidth_upper_bound: Bandwidth, round_trip_count: usize,
577    ) -> CongestionEventSample {
578        let mut last_lost_packet_send_state = SendTimeState::default();
579        let mut last_acked_packet_send_state = SendTimeState::default();
580        let mut last_lost_packet_num = 0u64;
581        let mut last_acked_packet_num = 0u64;
582
583        for packet in lost_packets {
584            let send_state =
585                self.on_packet_lost(packet.packet_number, packet.bytes_lost);
586            if send_state.is_valid {
587                last_lost_packet_send_state = send_state;
588                last_lost_packet_num = packet.packet_number;
589            }
590        }
591
592        if acked_packets.is_empty() {
593            // Only populate send state for a loss-only event.
594            return CongestionEventSample {
595                last_packet_send_state: last_lost_packet_send_state,
596                ..Default::default()
597            };
598        }
599
600        let mut event_sample = CongestionEventSample::default();
601
602        let mut max_send_rate = None;
603        let mut max_ack_rate = None;
604        for packet in acked_packets {
605            let sample =
606                match self.on_packet_acknowledged(ack_time, packet.pkt_num) {
607                    Some(sample) if sample.state_at_send.is_valid => sample,
608                    _ => continue,
609                };
610
611            last_acked_packet_send_state = sample.state_at_send;
612            last_acked_packet_num = packet.pkt_num;
613
614            event_sample.sample_rtt = Some(
615                sample
616                    .rtt
617                    .min(*event_sample.sample_rtt.get_or_insert(sample.rtt)),
618            );
619
620            if Some(sample.bandwidth) > event_sample.sample_max_bandwidth {
621                event_sample.sample_max_bandwidth = Some(sample.bandwidth);
622                event_sample.sample_is_app_limited =
623                    sample.state_at_send.is_app_limited;
624            }
625            max_send_rate = max_send_rate.max(sample.send_rate);
626            max_ack_rate = max_ack_rate.max(Some(sample.ack_rate));
627
628            let inflight_sample = self.total_bytes_acked -
629                last_acked_packet_send_state.total_bytes_acked;
630            if inflight_sample > event_sample.sample_max_inflight {
631                event_sample.sample_max_inflight = inflight_sample;
632            }
633        }
634
635        if !last_lost_packet_send_state.is_valid {
636            event_sample.last_packet_send_state = last_acked_packet_send_state;
637        } else if !last_acked_packet_send_state.is_valid {
638            event_sample.last_packet_send_state = last_lost_packet_send_state;
639        } else {
640            // If a loss alarm for two in-flight packets fires late, the first
641            // packet may already be acknowledged. Reevaluating loss detection
642            // could then declare the second packet lost.
643            event_sample.last_packet_send_state =
644                if last_acked_packet_num > last_lost_packet_num {
645                    last_acked_packet_send_state
646                } else {
647                    last_lost_packet_send_state
648                };
649        }
650
651        let is_new_max_bandwidth =
652            event_sample.sample_max_bandwidth > max_bandwidth;
653        max_bandwidth = event_sample.sample_max_bandwidth.max(max_bandwidth);
654
655        if self.limit_max_ack_height_tracker_by_send_rate {
656            max_bandwidth = max_bandwidth.max(max_send_rate);
657        }
658
659        let bandwidth_estimate = if let Some(max_bandwidth) = max_bandwidth {
660            max_bandwidth.min(est_bandwidth_upper_bound)
661        } else {
662            est_bandwidth_upper_bound
663        };
664
665        event_sample.extra_acked = self.on_ack_event_end(
666            bandwidth_estimate,
667            is_new_max_bandwidth,
668            round_trip_count,
669        );
670
671        event_sample.sample_max_send_rate = max_send_rate;
672        event_sample.sample_max_ack_rate = max_ack_rate;
673
674        event_sample
675    }
676
677    fn on_packet_lost(
678        &mut self, packet_number: u64, bytes_lost: usize,
679    ) -> SendTimeState {
680        let mut send_time_state = SendTimeState::default();
681
682        self.total_bytes_lost += bytes_lost;
683        if let Some(state) = self.connection_state_map.take(packet_number) {
684            send_time_state = state.send_time_state;
685            send_time_state.is_valid = true;
686        }
687
688        send_time_state
689    }
690
691    fn on_ack_event_end(
692        &mut self, bandwidth_estimate: Bandwidth, is_new_max_bandwidth: bool,
693        round_trip_count: usize,
694    ) -> usize {
695        let newly_acked_bytes =
696            self.total_bytes_acked - self.total_bytes_acked_after_last_ack_event;
697
698        if newly_acked_bytes == 0 {
699            return 0;
700        }
701
702        self.total_bytes_acked_after_last_ack_event = self.total_bytes_acked;
703        let extra_acked = self.max_ack_height_tracker.update(
704            bandwidth_estimate,
705            is_new_max_bandwidth,
706            round_trip_count,
707            self.last_sent_packet,
708            self.last_acked_packet,
709            self.last_acked_packet_ack_time,
710            newly_acked_bytes,
711        );
712        // If `extra_acked` is zero, this ACK starts a new aggregation epoch.
713        // Save the previous epoch's last ACK point as an A0 candidate.
714        if self.overestimate_avoidance && extra_acked == 0 {
715            self.a0_candidates.push_back(
716                self.recent_ack_points
717                    .less_recent_point(self.choose_a0_point_fix)
718                    .unwrap(),
719            );
720        }
721
722        extra_acked
723    }
724
725    fn on_packet_acknowledged(
726        &mut self, ack_time: Instant, packet_number: u64,
727    ) -> Option<BandwidthSample> {
728        self.last_acked_packet = packet_number;
729        let sent_packet = self.connection_state_map.take(packet_number)?;
730
731        self.total_bytes_acked += sent_packet.size;
732        self.total_bytes_sent_at_last_acked_packet =
733            sent_packet.send_time_state.total_bytes_sent;
734        self.last_acked_packet_sent_time = sent_packet.sent_time;
735        self.last_acked_packet_ack_time = ack_time;
736        if self.overestimate_avoidance {
737            self.recent_ack_points
738                .update(ack_time, self.total_bytes_acked);
739        }
740
741        if self.is_app_limited {
742            // Exit the app-limited phase if no end packet was recorded, or if
743            // this acknowledged packet was sent after the recorded end packet.
744            if self.end_of_app_limited_phase.is_none() ||
745                Some(packet_number) > self.end_of_app_limited_phase
746            {
747                self.is_app_limited = false;
748            }
749        }
750
751        // No send rate indicates that the sampler is supposed to discard the
752        // current send rate sample and use only the ack rate.
753        let send_rate = if sent_packet.sent_time >
754            sent_packet.last_acked_packet_sent_time
755        {
756            Some(Bandwidth::from_bytes_and_time_delta(
757                sent_packet.send_time_state.total_bytes_sent -
758                    sent_packet.total_bytes_sent_at_last_acked_packet,
759                sent_packet.sent_time - sent_packet.last_acked_packet_sent_time,
760            ))
761        } else {
762            None
763        };
764
765        let a0 = if self.overestimate_avoidance {
766            Self::choose_a0_point(
767                &mut self.a0_candidates,
768                sent_packet.send_time_state.total_bytes_acked,
769                self.choose_a0_point_fix,
770            )
771        } else {
772            None
773        };
774
775        let a0 = a0.unwrap_or(AckPoint {
776            ack_time: sent_packet.last_acked_packet_ack_time,
777            total_bytes_acked: sent_packet.send_time_state.total_bytes_acked,
778        });
779
780        // During the slope calculation, ensure that ack time of the current
781        // packet is always larger than the time of the previous packet,
782        // otherwise division by zero or integer underflow can occur.
783        if ack_time <= a0.ack_time {
784            return None;
785        }
786
787        let ack_rate = Bandwidth::from_bytes_and_time_delta(
788            self.total_bytes_acked - a0.total_bytes_acked,
789            ack_time.duration_since(a0.ack_time),
790        );
791
792        let bandwidth = if let Some(send_rate) = send_rate {
793            send_rate.min(ack_rate)
794        } else {
795            ack_rate
796        };
797
798        // Note: this sample does not account for delayed acknowledgement time.
799        // This means that the RTT measurements here can be artificially
800        // high, especially on low bandwidth connections.
801        let rtt = ack_time.duration_since(sent_packet.sent_time);
802
803        Some(BandwidthSample {
804            bandwidth,
805            rtt,
806            send_rate,
807            ack_rate,
808            state_at_send: SendTimeState {
809                is_valid: true,
810                ..sent_packet.send_time_state
811            },
812        })
813    }
814
815    fn choose_a0_point(
816        a0_candidates: &mut VecDeque<AckPoint>, total_bytes_acked: usize,
817        choose_a0_point_fix: bool,
818    ) -> Option<AckPoint> {
819        if a0_candidates.is_empty() {
820            return None;
821        }
822
823        while let Some(candidate) = a0_candidates.get(1) {
824            if candidate.total_bytes_acked > total_bytes_acked {
825                if choose_a0_point_fix {
826                    break;
827                } else {
828                    return Some(*candidate);
829                }
830            }
831            a0_candidates.pop_front();
832        }
833
834        Some(a0_candidates[0])
835    }
836
837    pub(crate) fn total_bytes_acked(&self) -> usize {
838        self.total_bytes_acked
839    }
840
841    pub(crate) fn total_bytes_lost(&self) -> usize {
842        self.total_bytes_lost
843    }
844
845    #[allow(dead_code)]
846    pub(crate) fn reset_max_ack_height_tracker(
847        &mut self, new_height: usize, new_time: usize,
848    ) {
849        self.max_ack_height_tracker.reset(new_height, new_time);
850    }
851
852    pub(crate) fn max_ack_height(&self) -> Option<usize> {
853        self.max_ack_height_tracker
854            .max_ack_height_filter
855            .get_best()
856            .map(|b| b.extra_acked)
857    }
858
859    pub(crate) fn on_app_limited(&mut self) {
860        self.is_app_limited = true;
861        self.end_of_app_limited_phase = Some(self.last_sent_packet);
862    }
863
864    pub(crate) fn remove_obsolete_packets(&mut self, least_acked: u64) {
865        // A packet can become obsolete when it is removed from
866        // QuicUnackedPacketMap's view of inflight before it is acked or
867        // marked as lost. For example, when
868        // QuicSentPacketManager::RetransmitCryptoPackets retransmits a crypto
869        // packet, the packet is removed from QuicUnackedPacketMap's
870        // inflight, but is not marked as acked or lost in the
871        // BandwidthSampler.
872        self.connection_state_map.remove_obsolete(least_acked);
873    }
874}
875
876#[cfg(test)]
877mod bandwidth_sampler_tests {
878    use rstest::rstest;
879
880    use super::*;
881
882    const REGULAR_PACKET_SIZE: usize = 1280;
883
884    struct TestSender {
885        sampler: BandwidthSampler,
886        sampler_app_limited_at_start: bool,
887        bytes_in_flight: usize,
888        clock: Instant,
889        max_bandwidth: Bandwidth,
890        est_bandwidth_upper_bound: Bandwidth,
891        round_trip_count: usize,
892    }
893
894    impl TestSender {
895        fn new(overestimate_avoidance: bool, choose_a0_point_fix: bool) -> Self {
896            let sampler = BandwidthSampler::new(
897                0,
898                overestimate_avoidance,
899                choose_a0_point_fix,
900            );
901            TestSender {
902                sampler_app_limited_at_start: sampler.is_app_limited(),
903                sampler,
904                bytes_in_flight: 0,
905                clock: Instant::now(),
906                max_bandwidth: Bandwidth::zero(),
907                est_bandwidth_upper_bound: Bandwidth::infinite(),
908                round_trip_count: 0,
909            }
910        }
911
912        fn get_packet_size(&self, pkt_num: u64) -> usize {
913            self.sampler
914                .connection_state_map
915                .peek(pkt_num)
916                .unwrap()
917                .size
918        }
919
920        fn get_packet_time(&self, pkt_num: u64) -> Instant {
921            self.sampler
922                .connection_state_map
923                .peek(pkt_num)
924                .unwrap()
925                .sent_time
926        }
927
928        fn number_of_tracked_packets(&self) -> usize {
929            self.sampler.connection_state_map.packet_map.len()
930        }
931
932        fn make_acked_packet(&self, pkt_num: u64) -> Acked {
933            let time_sent = self.get_packet_time(pkt_num);
934
935            Acked { pkt_num, time_sent }
936        }
937
938        fn make_lost_packet(&self, pkt_num: u64) -> Lost {
939            let size = self.get_packet_size(pkt_num);
940            Lost {
941                packet_number: pkt_num,
942                bytes_lost: size,
943            }
944        }
945
946        fn ack_packet(&mut self, pkt_num: u64) -> BandwidthSample {
947            let size = self.get_packet_size(pkt_num);
948            self.bytes_in_flight -= size;
949
950            let sample = self.sampler.on_congestion_event(
951                self.clock,
952                &[self.make_acked_packet(pkt_num)],
953                &[],
954                Some(self.max_bandwidth),
955                self.est_bandwidth_upper_bound,
956                self.round_trip_count,
957            );
958
959            let sample_max_bandwidth = sample.sample_max_bandwidth.unwrap();
960            self.max_bandwidth = self.max_bandwidth.max(sample_max_bandwidth);
961
962            let bandwidth_sample = BandwidthSample {
963                bandwidth: sample_max_bandwidth,
964                rtt: sample.sample_rtt.unwrap(),
965                send_rate: None,
966                // Use zero for ack_rate in test helper
967                ack_rate: Bandwidth::zero(),
968                state_at_send: sample.last_packet_send_state,
969            };
970            assert!(bandwidth_sample.state_at_send.is_valid);
971            bandwidth_sample
972        }
973
974        fn lose_packet(&mut self, pkt_num: u64) -> SendTimeState {
975            let size = self.get_packet_size(pkt_num);
976            self.bytes_in_flight -= size;
977
978            let sample = self.sampler.on_congestion_event(
979                self.clock,
980                &[],
981                &[self.make_lost_packet(pkt_num)],
982                Some(self.max_bandwidth),
983                self.est_bandwidth_upper_bound,
984                self.round_trip_count,
985            );
986
987            assert!(sample.last_packet_send_state.is_valid);
988            assert_eq!(sample.sample_max_bandwidth, None);
989            assert_eq!(sample.sample_rtt, None);
990            sample.last_packet_send_state
991        }
992
993        fn on_congestion_event(
994            &mut self, acked: &[u64], lost: &[u64],
995        ) -> CongestionEventSample {
996            let acked = acked
997                .iter()
998                .map(|pkt| {
999                    let acked_size = self.get_packet_size(*pkt);
1000                    self.bytes_in_flight -= acked_size;
1001
1002                    self.make_acked_packet(*pkt)
1003                })
1004                .collect::<Vec<_>>();
1005
1006            let lost = lost
1007                .iter()
1008                .map(|pkt| {
1009                    let lost = self.make_lost_packet(*pkt);
1010                    self.bytes_in_flight -= lost.bytes_lost;
1011                    lost
1012                })
1013                .collect::<Vec<_>>();
1014
1015            let sample = self.sampler.on_congestion_event(
1016                self.clock,
1017                &acked,
1018                &lost,
1019                Some(self.max_bandwidth),
1020                self.est_bandwidth_upper_bound,
1021                self.round_trip_count,
1022            );
1023
1024            self.max_bandwidth =
1025                self.max_bandwidth.max(sample.sample_max_bandwidth.unwrap());
1026
1027            sample
1028        }
1029
1030        fn send_packet(
1031            &mut self, pkt_num: u64, pkt_sz: usize,
1032            has_retransmittable_data: bool,
1033        ) {
1034            self.sampler.on_packet_sent(
1035                self.clock,
1036                pkt_num,
1037                pkt_sz,
1038                self.bytes_in_flight,
1039                has_retransmittable_data,
1040            );
1041            if has_retransmittable_data {
1042                self.bytes_in_flight += pkt_sz;
1043            }
1044        }
1045
1046        fn advance_time(&mut self, delta: Duration) {
1047            self.clock += delta;
1048        }
1049
1050        // Sends one packet and acks it.  Then, send 20 packets.  Finally, send
1051        // another 20 packets while acknowledging previous 20.
1052        fn send_40_and_ack_first_20(&mut self, time_between_packets: Duration) {
1053            // Send 20 packets at a constant inter-packet time.
1054            for i in 1..=20 {
1055                self.send_packet(i, REGULAR_PACKET_SIZE, true);
1056                self.advance_time(time_between_packets);
1057            }
1058
1059            // Acknowledge packets 1 to 20 while sending new packets at the same
1060            // rate as before.
1061            for i in 1..=20 {
1062                self.ack_packet(i);
1063                self.send_packet(i + 20, REGULAR_PACKET_SIZE, true);
1064                self.advance_time(time_between_packets);
1065            }
1066        }
1067    }
1068
1069    #[rstest]
1070    fn send_and_wait(
1071        #[values(false, true)] overestimate_avoidance: bool,
1072        #[values(false, true)] choose_a0_point_fix: bool,
1073    ) {
1074        let mut test_sender =
1075            TestSender::new(overestimate_avoidance, choose_a0_point_fix);
1076        let mut time_between_packets = Duration::from_millis(10);
1077        let mut expected_bandwidth =
1078            Bandwidth::from_bytes_per_second(REGULAR_PACKET_SIZE as u64 * 100);
1079
1080        // Send packets at the constant bandwidth.
1081        for i in 1..20 {
1082            test_sender.send_packet(i, REGULAR_PACKET_SIZE, true);
1083            test_sender.advance_time(time_between_packets);
1084            let current_sample = test_sender.ack_packet(i);
1085            assert_eq!(expected_bandwidth, current_sample.bandwidth);
1086        }
1087
1088        // Send packets at the exponentially decreasing bandwidth.
1089        for i in 20..25 {
1090            time_between_packets *= 2;
1091            expected_bandwidth = expected_bandwidth * 0.5;
1092
1093            test_sender.send_packet(i, REGULAR_PACKET_SIZE, true);
1094            test_sender.advance_time(time_between_packets);
1095            let current_sample = test_sender.ack_packet(i);
1096            assert_eq!(expected_bandwidth, current_sample.bandwidth);
1097        }
1098
1099        test_sender.sampler.remove_obsolete_packets(25);
1100        assert_eq!(0, test_sender.number_of_tracked_packets());
1101        assert_eq!(0, test_sender.bytes_in_flight);
1102    }
1103
1104    #[rstest]
1105    fn send_time_state(
1106        #[values(false, true)] overestimate_avoidance: bool,
1107        #[values(false, true)] choose_a0_point_fix: bool,
1108    ) {
1109        let mut test_sender =
1110            TestSender::new(overestimate_avoidance, choose_a0_point_fix);
1111        let time_between_packets = Duration::from_millis(10);
1112
1113        // Send packets 1-5.
1114        for i in 1..=5 {
1115            test_sender.send_packet(i, REGULAR_PACKET_SIZE, true);
1116            assert_eq!(
1117                test_sender.sampler.total_bytes_sent,
1118                REGULAR_PACKET_SIZE * i as usize
1119            );
1120            test_sender.advance_time(time_between_packets);
1121        }
1122
1123        // Ack packet 1.
1124        let send_time_state = test_sender.ack_packet(1).state_at_send;
1125        assert_eq!(REGULAR_PACKET_SIZE, send_time_state.total_bytes_sent);
1126        assert_eq!(0, send_time_state.total_bytes_acked);
1127        assert_eq!(0, send_time_state.total_bytes_lost);
1128        assert_eq!(REGULAR_PACKET_SIZE, test_sender.sampler.total_bytes_acked);
1129
1130        // Lose packet 2.
1131        let send_time_state = test_sender.lose_packet(2);
1132        assert_eq!(REGULAR_PACKET_SIZE * 2, send_time_state.total_bytes_sent);
1133        assert_eq!(0, send_time_state.total_bytes_acked);
1134        assert_eq!(0, send_time_state.total_bytes_lost);
1135        assert_eq!(REGULAR_PACKET_SIZE, test_sender.sampler.total_bytes_lost);
1136
1137        // Lose packet 3.
1138        let send_time_state = test_sender.lose_packet(3);
1139        assert_eq!(REGULAR_PACKET_SIZE * 3, send_time_state.total_bytes_sent);
1140        assert_eq!(0, send_time_state.total_bytes_acked);
1141        assert_eq!(0, send_time_state.total_bytes_lost);
1142        assert_eq!(
1143            REGULAR_PACKET_SIZE * 2,
1144            test_sender.sampler.total_bytes_lost
1145        );
1146
1147        // Send packets 6-10.
1148        for i in 6..=10 {
1149            test_sender.send_packet(i, REGULAR_PACKET_SIZE, true);
1150            assert_eq!(
1151                test_sender.sampler.total_bytes_sent,
1152                REGULAR_PACKET_SIZE * i as usize
1153            );
1154            test_sender.advance_time(time_between_packets);
1155        }
1156
1157        // Ack all inflight packets.
1158        let mut acked_packet_count = 1;
1159        assert_eq!(
1160            REGULAR_PACKET_SIZE * acked_packet_count,
1161            test_sender.sampler.total_bytes_acked
1162        );
1163        for i in 4..=10 {
1164            let send_time_state = test_sender.ack_packet(i).state_at_send;
1165            acked_packet_count += 1;
1166            assert_eq!(
1167                REGULAR_PACKET_SIZE * acked_packet_count,
1168                test_sender.sampler.total_bytes_acked
1169            );
1170            assert_eq!(
1171                REGULAR_PACKET_SIZE * i as usize,
1172                send_time_state.total_bytes_sent
1173            );
1174
1175            if i <= 5 {
1176                assert_eq!(0, send_time_state.total_bytes_acked);
1177                assert_eq!(0, send_time_state.total_bytes_lost);
1178            } else {
1179                assert_eq!(
1180                    REGULAR_PACKET_SIZE,
1181                    send_time_state.total_bytes_acked
1182                );
1183                assert_eq!(
1184                    REGULAR_PACKET_SIZE * 2,
1185                    send_time_state.total_bytes_lost
1186                );
1187            }
1188
1189            // This equation works because there is no neutered bytes.
1190            assert_eq!(
1191                send_time_state.total_bytes_sent -
1192                    send_time_state.total_bytes_acked -
1193                    send_time_state.total_bytes_lost,
1194                send_time_state.bytes_in_flight
1195            );
1196
1197            test_sender.advance_time(time_between_packets);
1198        }
1199    }
1200
1201    /// Test the sampler during regular windowed sender scenario with fixed CWND
1202    /// of 20.
1203    #[rstest]
1204    fn send_paced(
1205        #[values(false, true)] overestimate_avoidance: bool,
1206        #[values(false, true)] choose_a0_point_fix: bool,
1207    ) {
1208        let mut test_sender =
1209            TestSender::new(overestimate_avoidance, choose_a0_point_fix);
1210        let time_between_packets = Duration::from_millis(1);
1211        let expected_bandwidth =
1212            Bandwidth::from_kbits_per_second(REGULAR_PACKET_SIZE as u64 * 8);
1213
1214        test_sender.send_40_and_ack_first_20(time_between_packets);
1215
1216        // Ack the packets 21 to 40, arriving at the correct bandwidth.
1217        for i in 21..=40 {
1218            let last_bandwidth = test_sender.ack_packet(i).bandwidth;
1219            assert_eq!(expected_bandwidth, last_bandwidth);
1220            test_sender.advance_time(time_between_packets);
1221        }
1222        test_sender.sampler.remove_obsolete_packets(41);
1223        assert_eq!(0, test_sender.number_of_tracked_packets());
1224        assert_eq!(0, test_sender.bytes_in_flight);
1225    }
1226
1227    /// Test the sampler in a scenario where 50% of packets is consistently
1228    /// lost.
1229    #[rstest]
1230    fn send_with_losses(
1231        #[values(false, true)] overestimate_avoidance: bool,
1232        #[values(false, true)] choose_a0_point_fix: bool,
1233    ) {
1234        let mut test_sender =
1235            TestSender::new(overestimate_avoidance, choose_a0_point_fix);
1236        let time_between_packets = Duration::from_millis(1);
1237        let expected_bandwidth =
1238            Bandwidth::from_kbits_per_second(REGULAR_PACKET_SIZE as u64 / 2 * 8);
1239
1240        // Send 20 packets, each 1 ms apart.
1241        for i in 1..=20 {
1242            test_sender.send_packet(i, REGULAR_PACKET_SIZE, true);
1243            test_sender.advance_time(time_between_packets);
1244        }
1245
1246        // Ack packets 1 to 20, losing every even-numbered packet, while sending
1247        // new packets at the same rate as before.
1248        for i in 1..=20 {
1249            if i % 2 == 0 {
1250                test_sender.ack_packet(i);
1251            } else {
1252                test_sender.lose_packet(i);
1253            }
1254            test_sender.send_packet(i + 20, REGULAR_PACKET_SIZE, true);
1255            test_sender.advance_time(time_between_packets);
1256        }
1257
1258        // Ack the packets 21 to 40 with the same loss pattern.
1259        for i in 21..=40 {
1260            if i % 2 == 0 {
1261                let last_bandwidth = test_sender.ack_packet(i).bandwidth;
1262                assert_eq!(expected_bandwidth, last_bandwidth);
1263            } else {
1264                test_sender.lose_packet(i);
1265            }
1266            test_sender.advance_time(time_between_packets);
1267        }
1268        test_sender.sampler.remove_obsolete_packets(41);
1269        assert_eq!(0, test_sender.number_of_tracked_packets());
1270        assert_eq!(0, test_sender.bytes_in_flight);
1271    }
1272
1273    /// Test the sampler in a scenario where the 50% of packets are not
1274    /// congestion controlled (specifically, non-retransmittable data is not
1275    /// congestion controlled).  Should be functionally consistent in behavior
1276    /// with the [`send_with_losses`] test.
1277    #[rstest]
1278    fn not_congestion_controlled(
1279        #[values(false, true)] overestimate_avoidance: bool,
1280        #[values(false, true)] choose_a0_point_fix: bool,
1281    ) {
1282        let mut test_sender =
1283            TestSender::new(overestimate_avoidance, choose_a0_point_fix);
1284        let time_between_packets = Duration::from_millis(1);
1285        let expected_bandwidth =
1286            Bandwidth::from_kbits_per_second(REGULAR_PACKET_SIZE as u64 / 2 * 8);
1287
1288        // Send 20 packets, each 1 ms apart. Every even packet is not congestion
1289        // controlled.
1290        for i in 1..=20 {
1291            let has_retransmittable_data = i % 2 == 0;
1292            test_sender.send_packet(
1293                i,
1294                REGULAR_PACKET_SIZE,
1295                has_retransmittable_data,
1296            );
1297            test_sender.advance_time(time_between_packets);
1298        }
1299
1300        // Ensure only congestion controlled packets are tracked.
1301        assert_eq!(10, test_sender.number_of_tracked_packets());
1302
1303        // Acknowledge packets 2 to 21, ignoring every even-numbered packet,
1304        // while sending new packets at the same rate as before.
1305        for i in 1..=20 {
1306            if i % 2 == 0 {
1307                test_sender.ack_packet(i);
1308            }
1309            let has_retransmittable_data = i % 2 == 0;
1310            test_sender.send_packet(
1311                i + 20,
1312                REGULAR_PACKET_SIZE,
1313                has_retransmittable_data,
1314            );
1315            test_sender.advance_time(time_between_packets);
1316        }
1317
1318        // Ack the packets 22 to 41 with the same congestion controlled pattern.
1319        for i in 21..=40 {
1320            if i % 2 == 0 {
1321                let last_bandwidth = test_sender.ack_packet(i).bandwidth;
1322                assert_eq!(expected_bandwidth, last_bandwidth);
1323            }
1324            test_sender.advance_time(time_between_packets);
1325        }
1326
1327        test_sender.sampler.remove_obsolete_packets(41);
1328        // Since only congestion controlled packets are entered into the map, it
1329        // has to be empty at this point.
1330        assert_eq!(0, test_sender.number_of_tracked_packets());
1331        assert_eq!(0, test_sender.bytes_in_flight);
1332    }
1333
1334    /// Simulate a situation where ACKs arrive in burst and earlier than usual,
1335    /// thus producing an ACK rate which is higher than the original send rate.
1336    #[rstest]
1337    fn compressed_ack(
1338        #[values(false, true)] overestimate_avoidance: bool,
1339        #[values(false, true)] choose_a0_point_fix: bool,
1340    ) {
1341        let mut test_sender =
1342            TestSender::new(overestimate_avoidance, choose_a0_point_fix);
1343        let time_between_packets = Duration::from_millis(1);
1344        let expected_bandwidth =
1345            Bandwidth::from_kbits_per_second(REGULAR_PACKET_SIZE as u64 * 8);
1346
1347        test_sender.send_40_and_ack_first_20(time_between_packets);
1348
1349        // Simulate an RTT somewhat lower than the one for 1-to-21 transmission.
1350        test_sender.advance_time(time_between_packets * 15);
1351
1352        // Ack the packets 21 to 40 almost immediately at once.
1353        let ridiculously_small_time_delta = Duration::from_micros(20);
1354        let mut last_bandwidth = Bandwidth::zero();
1355        for i in 21..=40 {
1356            last_bandwidth = test_sender.ack_packet(i).bandwidth;
1357            test_sender.advance_time(ridiculously_small_time_delta);
1358        }
1359        assert_eq!(expected_bandwidth, last_bandwidth);
1360
1361        test_sender.sampler.remove_obsolete_packets(41);
1362        // Since only congestion controlled packets are entered into the map, it
1363        // has to be empty at this point.
1364        assert_eq!(0, test_sender.number_of_tracked_packets());
1365        assert_eq!(0, test_sender.bytes_in_flight);
1366    }
1367
1368    /// Tests receiving ACK packets in the reverse order.
1369    #[rstest]
1370    fn reordered_ack(
1371        #[values(false, true)] overestimate_avoidance: bool,
1372        #[values(false, true)] choose_a0_point_fix: bool,
1373    ) {
1374        let mut test_sender =
1375            TestSender::new(overestimate_avoidance, choose_a0_point_fix);
1376        let time_between_packets = Duration::from_millis(1);
1377        let expected_bandwidth =
1378            Bandwidth::from_kbits_per_second(REGULAR_PACKET_SIZE as u64 * 8);
1379
1380        test_sender.send_40_and_ack_first_20(time_between_packets);
1381
1382        // Acknowledge packets 21 to 40 in reverse order while sending packets
1383        // 41 to 60.
1384        for i in 0..20 {
1385            let last_bandwidth = test_sender.ack_packet(40 - i).bandwidth;
1386            assert_eq!(expected_bandwidth, last_bandwidth);
1387            test_sender.send_packet(41 + i, REGULAR_PACKET_SIZE, true);
1388            test_sender.advance_time(time_between_packets);
1389        }
1390
1391        // Ack the packets 41 to 60, now in the regular order.
1392        for i in 41..=60 {
1393            let last_bandwidth = test_sender.ack_packet(i).bandwidth;
1394            assert_eq!(expected_bandwidth, last_bandwidth);
1395            test_sender.advance_time(time_between_packets);
1396        }
1397
1398        test_sender.sampler.remove_obsolete_packets(61);
1399        assert_eq!(0, test_sender.number_of_tracked_packets());
1400        assert_eq!(0, test_sender.bytes_in_flight);
1401    }
1402
1403    /// Test the app-limited logic.
1404    #[rstest]
1405    fn app_limited(
1406        #[values(false, true)] overestimate_avoidance: bool,
1407        #[values(false, true)] choose_a0_point_fix: bool,
1408    ) {
1409        let mut test_sender =
1410            TestSender::new(overestimate_avoidance, choose_a0_point_fix);
1411        let time_between_packets = Duration::from_millis(1);
1412        let expected_bandwidth =
1413            Bandwidth::from_kbits_per_second(REGULAR_PACKET_SIZE as u64 * 8);
1414
1415        for i in 1..=20 {
1416            test_sender.send_packet(i, REGULAR_PACKET_SIZE, true);
1417            test_sender.advance_time(time_between_packets);
1418        }
1419
1420        for i in 1..=20 {
1421            let sample = test_sender.ack_packet(i);
1422            assert_eq!(
1423                sample.state_at_send.is_app_limited,
1424                test_sender.sampler_app_limited_at_start,
1425                "{i}"
1426            );
1427            test_sender.send_packet(i + 20, REGULAR_PACKET_SIZE, true);
1428            test_sender.advance_time(time_between_packets);
1429        }
1430
1431        // We are now app-limited. Acknowledge 21 to 40 as usual, but do not
1432        // send anything for now.
1433        test_sender.sampler.on_app_limited();
1434        for i in 21..=40 {
1435            let sample = test_sender.ack_packet(i);
1436            assert!(!sample.state_at_send.is_app_limited, "{i}");
1437            assert_eq!(expected_bandwidth, sample.bandwidth, "{i}");
1438            test_sender.advance_time(time_between_packets);
1439        }
1440
1441        // Enter quiescence.
1442        test_sender.advance_time(Duration::from_secs(1));
1443
1444        // Send packets 41 to 60, all of which would be marked as app-limited.
1445        for i in 41..=60 {
1446            test_sender.send_packet(i, REGULAR_PACKET_SIZE, true);
1447            test_sender.advance_time(time_between_packets);
1448        }
1449
1450        // Acknowledge packets 41 to 60 while sending packets 61 to 80. These
1451        // app-limited ACKs should underestimate bandwidth.
1452        for i in 41..=60 {
1453            let sample = test_sender.ack_packet(i);
1454            assert!(sample.state_at_send.is_app_limited, "{i}");
1455            if !overestimate_avoidance || choose_a0_point_fix || i < 43 {
1456                assert!(
1457                    sample.bandwidth < expected_bandwidth * 0.7,
1458                    "{} {:?} vs {:?}",
1459                    i,
1460                    sample.bandwidth,
1461                    expected_bandwidth * 0.7
1462                );
1463            } else {
1464                // Needs further investigation. With `overestimate_avoidance`,
1465                // `sample.bandwidth` rises 17 packets too soon.
1466                assert_eq!(sample.bandwidth, expected_bandwidth, "{i}");
1467            }
1468            test_sender.send_packet(i + 20, REGULAR_PACKET_SIZE, true);
1469            test_sender.advance_time(time_between_packets);
1470        }
1471
1472        // Run out of packets, and then ack packet 61 to 80, all of which should
1473        // have correct non-app-limited samples.
1474        for i in 61..=80 {
1475            let sample = test_sender.ack_packet(i);
1476            assert!(!sample.state_at_send.is_app_limited, "{i}");
1477            assert_eq!(sample.bandwidth, expected_bandwidth, "{i}");
1478            test_sender.advance_time(time_between_packets);
1479        }
1480
1481        test_sender.sampler.remove_obsolete_packets(81);
1482        assert_eq!(0, test_sender.number_of_tracked_packets());
1483        assert_eq!(0, test_sender.bytes_in_flight);
1484    }
1485
1486    /// Test the samples taken at the first flight of packets sent.
1487    #[rstest]
1488    fn first_round_trip(
1489        #[values(false, true)] overestimate_avoidance: bool,
1490        #[values(false, true)] choose_a0_point_fix: bool,
1491    ) {
1492        let mut test_sender =
1493            TestSender::new(overestimate_avoidance, choose_a0_point_fix);
1494        let time_between_packets = Duration::from_millis(1);
1495        let rtt = Duration::from_millis(800);
1496        let num_packets = 10;
1497        let num_bytes = REGULAR_PACKET_SIZE * num_packets;
1498        let real_bandwidth = Bandwidth::from_bytes_and_time_delta(num_bytes, rtt);
1499
1500        for i in 1..=10 {
1501            test_sender.send_packet(i, REGULAR_PACKET_SIZE, true);
1502            test_sender.advance_time(time_between_packets);
1503        }
1504        test_sender.advance_time(rtt - time_between_packets * num_packets as _);
1505
1506        let mut last_sample = Bandwidth::zero();
1507        for i in 1..=10 {
1508            let sample = test_sender.ack_packet(i).bandwidth;
1509            assert!(sample > last_sample);
1510            last_sample = sample;
1511            test_sender.advance_time(time_between_packets);
1512        }
1513
1514        // The final sample for the first flight should underestimate the real
1515        // bandwidth by no more than 10%. The exact error depends on the
1516        // difference between the RTT and the time it takes to exhaust the
1517        // congestion window (i.e. in the limit when all packets are sent
1518        // simultaneously, last sample would indicate the real bandwidth).
1519        assert!(last_sample < real_bandwidth);
1520        assert!(last_sample > real_bandwidth * 0.9);
1521    }
1522
1523    /// Test sampler's ability to remove obsolete packets.
1524    #[rstest]
1525    fn remove_obsolete_packets(
1526        #[values(false, true)] overestimate_avoidance: bool,
1527        #[values(false, true)] choose_a0_point_fix: bool,
1528    ) {
1529        let mut test_sender =
1530            TestSender::new(overestimate_avoidance, choose_a0_point_fix);
1531
1532        for i in 1..=5 {
1533            test_sender.send_packet(i, REGULAR_PACKET_SIZE, true);
1534        }
1535        test_sender.advance_time(Duration::from_millis(100));
1536        assert_eq!(5, test_sender.number_of_tracked_packets());
1537        test_sender.sampler.remove_obsolete_packets(4);
1538        assert_eq!(2, test_sender.number_of_tracked_packets());
1539        test_sender.lose_packet(4);
1540        test_sender.sampler.remove_obsolete_packets(5);
1541        assert_eq!(1, test_sender.number_of_tracked_packets());
1542        test_sender.ack_packet(5);
1543        test_sender.sampler.remove_obsolete_packets(6);
1544        assert_eq!(0, test_sender.number_of_tracked_packets());
1545    }
1546
1547    #[rstest]
1548    fn neuter_packet(
1549        #[values(false, true)] overestimate_avoidance: bool,
1550        #[values(false, true)] choose_a0_point_fix: bool,
1551    ) {
1552        let mut test_sender =
1553            TestSender::new(overestimate_avoidance, choose_a0_point_fix);
1554        test_sender.send_packet(1, REGULAR_PACKET_SIZE, true);
1555        assert_eq!(test_sender.sampler.total_bytes_neutered, 0);
1556        test_sender.advance_time(Duration::from_millis(10));
1557        test_sender.sampler.on_packet_neutered(1);
1558        assert!(0 < test_sender.sampler.total_bytes_neutered);
1559        assert_eq!(0, test_sender.sampler.total_bytes_acked);
1560
1561        // If packet 1 is acked it should not produce a bandwidth sample.
1562        let acked = Acked {
1563            pkt_num: 1,
1564            time_sent: test_sender.clock,
1565        };
1566        test_sender.advance_time(Duration::from_millis(10));
1567        let sample = test_sender.sampler.on_congestion_event(
1568            test_sender.clock,
1569            &[acked],
1570            &[],
1571            Some(test_sender.max_bandwidth),
1572            test_sender.est_bandwidth_upper_bound,
1573            test_sender.round_trip_count,
1574        );
1575
1576        assert_eq!(0, test_sender.sampler.total_bytes_acked);
1577        assert!(sample.sample_max_bandwidth.is_none());
1578        assert!(!sample.sample_is_app_limited);
1579        assert!(sample.sample_rtt.is_none());
1580        assert_eq!(sample.sample_max_inflight, 0);
1581        assert_eq!(sample.extra_acked, 0);
1582    }
1583
1584    /// Make sure a default constructed [`CongestionEventSample`] has the
1585    /// correct initial values for
1586    /// [`BandwidthSampler::on_congestion_event()`] to work.
1587    #[rstest]
1588    fn congestion_event_sample_default_values() {
1589        let sample = CongestionEventSample::default();
1590        assert!(sample.sample_max_bandwidth.is_none());
1591        assert!(!sample.sample_is_app_limited);
1592        assert!(sample.sample_rtt.is_none());
1593        assert_eq!(sample.sample_max_inflight, 0);
1594        assert_eq!(sample.extra_acked, 0);
1595    }
1596
1597    /// 1) Send 2 packets, 2) Ack both in 1 event, 3) Repeat.
1598    #[rstest]
1599    fn two_acked_packets_per_event(
1600        #[values(false, true)] overestimate_avoidance: bool,
1601        #[values(false, true)] choose_a0_point_fix: bool,
1602    ) {
1603        let mut test_sender =
1604            TestSender::new(overestimate_avoidance, choose_a0_point_fix);
1605        let time_between_packets = Duration::from_millis(10);
1606        let sending_rate = Bandwidth::from_bytes_and_time_delta(
1607            REGULAR_PACKET_SIZE,
1608            time_between_packets,
1609        );
1610
1611        for i in 1..21 {
1612            test_sender.send_packet(i, REGULAR_PACKET_SIZE, true);
1613            test_sender.advance_time(time_between_packets);
1614            if i % 2 != 0 {
1615                continue;
1616            }
1617
1618            let sample = test_sender.on_congestion_event(&[i - 1, i], &[]);
1619            assert_eq!(sending_rate, sample.sample_max_bandwidth.unwrap());
1620            assert_eq!(time_between_packets, sample.sample_rtt.unwrap());
1621            assert_eq!(2 * REGULAR_PACKET_SIZE, sample.sample_max_inflight);
1622            assert!(sample.last_packet_send_state.is_valid);
1623            assert_eq!(
1624                2 * REGULAR_PACKET_SIZE,
1625                sample.last_packet_send_state.bytes_in_flight
1626            );
1627            assert_eq!(
1628                i as usize * REGULAR_PACKET_SIZE,
1629                sample.last_packet_send_state.total_bytes_sent
1630            );
1631            assert_eq!(
1632                (i - 2) as usize * REGULAR_PACKET_SIZE,
1633                sample.last_packet_send_state.total_bytes_acked
1634            );
1635            assert_eq!(0, sample.last_packet_send_state.total_bytes_lost);
1636            test_sender.sampler.remove_obsolete_packets(i - 2);
1637        }
1638    }
1639
1640    #[rstest]
1641    fn lose_every_other_packet(
1642        #[values(false, true)] overestimate_avoidance: bool,
1643        #[values(false, true)] choose_a0_point_fix: bool,
1644    ) {
1645        let mut test_sender =
1646            TestSender::new(overestimate_avoidance, choose_a0_point_fix);
1647        let time_between_packets = Duration::from_millis(10);
1648        let sending_rate = Bandwidth::from_bytes_and_time_delta(
1649            REGULAR_PACKET_SIZE,
1650            time_between_packets,
1651        );
1652
1653        for i in 1..21 {
1654            test_sender.send_packet(i, REGULAR_PACKET_SIZE, true);
1655            test_sender.advance_time(time_between_packets);
1656            if i % 2 != 0 {
1657                continue;
1658            }
1659            // Ack packet i and lose i-1.
1660            let sample = test_sender.on_congestion_event(&[i], &[i - 1]);
1661            // Losing 50% packets means sending rate is twice the bandwidth.
1662
1663            assert_eq!(sending_rate, sample.sample_max_bandwidth.unwrap() * 2.);
1664            assert_eq!(time_between_packets, sample.sample_rtt.unwrap());
1665            assert_eq!(REGULAR_PACKET_SIZE, sample.sample_max_inflight);
1666            assert!(sample.last_packet_send_state.is_valid);
1667            assert_eq!(
1668                2 * REGULAR_PACKET_SIZE,
1669                sample.last_packet_send_state.bytes_in_flight
1670            );
1671            assert_eq!(
1672                i as usize * REGULAR_PACKET_SIZE,
1673                sample.last_packet_send_state.total_bytes_sent
1674            );
1675            assert_eq!(
1676                (i - 2) as usize * REGULAR_PACKET_SIZE / 2,
1677                sample.last_packet_send_state.total_bytes_acked
1678            );
1679            assert_eq!(
1680                (i - 2) as usize * REGULAR_PACKET_SIZE / 2,
1681                sample.last_packet_send_state.total_bytes_lost
1682            );
1683            test_sender.sampler.remove_obsolete_packets(i - 2);
1684        }
1685    }
1686
1687    #[rstest]
1688    fn ack_height_respect_bandwidth_estimate_upper_bound(
1689        #[values(false, true)] overestimate_avoidance: bool,
1690        #[values(false, true)] choose_a0_point_fix: bool,
1691    ) {
1692        let mut test_sender =
1693            TestSender::new(overestimate_avoidance, choose_a0_point_fix);
1694        let time_between_packets = Duration::from_millis(10);
1695        let first_packet_sending_rate = Bandwidth::from_bytes_and_time_delta(
1696            REGULAR_PACKET_SIZE,
1697            time_between_packets,
1698        );
1699
1700        // Send packets 1 to 4 and ack packet 1.
1701        test_sender.send_packet(1, REGULAR_PACKET_SIZE, true);
1702        test_sender.advance_time(time_between_packets);
1703        test_sender.send_packet(2, REGULAR_PACKET_SIZE, true);
1704        test_sender.send_packet(3, REGULAR_PACKET_SIZE, true);
1705        test_sender.send_packet(4, REGULAR_PACKET_SIZE, true);
1706        let sample = test_sender.on_congestion_event(&[1], &[]);
1707        assert_eq!(
1708            first_packet_sending_rate,
1709            sample.sample_max_bandwidth.unwrap()
1710        );
1711        assert_eq!(first_packet_sending_rate, test_sender.max_bandwidth);
1712
1713        // Ack packet 2, 3 and 4, all of which uses S(1) to calculate ack rate
1714        // since there were no acks at the time they were sent.
1715        test_sender.round_trip_count += 1;
1716        test_sender.est_bandwidth_upper_bound = first_packet_sending_rate * 0.3;
1717        test_sender.advance_time(time_between_packets);
1718
1719        let sample = test_sender.on_congestion_event(&[2, 3, 4], &[]);
1720
1721        assert_eq!(
1722            first_packet_sending_rate * 2.,
1723            sample.sample_max_bandwidth.unwrap()
1724        );
1725        assert_eq!(
1726            test_sender.max_bandwidth,
1727            sample.sample_max_bandwidth.unwrap()
1728        );
1729        assert!(2 * REGULAR_PACKET_SIZE < sample.extra_acked);
1730    }
1731}
1732
1733#[cfg(test)]
1734mod max_ack_height_tracker_tests {
1735    use rstest::rstest;
1736
1737    use super::*;
1738
1739    struct TestTracker {
1740        tracker: MaxAckHeightTracker,
1741        bandwidth: Bandwidth,
1742        start: Instant,
1743        now: Instant,
1744        last_sent_packet_number: u64,
1745        last_acked_packet_number: u64,
1746        rtt: Duration,
1747    }
1748
1749    impl TestTracker {
1750        fn new(overestimate_avoidance: bool) -> Self {
1751            let mut tracker =
1752                MaxAckHeightTracker::new(10, overestimate_avoidance);
1753            tracker.ack_aggregation_bandwidth_threshold = 1.8;
1754            tracker.start_new_aggregation_epoch_after_full_round = true;
1755            let start = Instant::now();
1756            TestTracker {
1757                tracker,
1758                start,
1759                now: start + Duration::from_millis(1),
1760                bandwidth: Bandwidth::from_bytes_per_second(10 * 1000),
1761                last_sent_packet_number: 0,
1762                last_acked_packet_number: 0,
1763                rtt: Duration::from_millis(60),
1764            }
1765        }
1766
1767        // Run a full aggregation episode, which is one or more aggregated acks,
1768        // followed by a quiet period in which no ack happens.
1769        // After this function returns, the time is set to the earliest point at
1770        // which any ack event will cause tracker_.Update() to start a new
1771        // aggregation.
1772        fn aggregation_episode(
1773            &mut self, aggregation_bandwidth: Bandwidth,
1774            aggregation_duration: Duration, bytes_per_ack: usize,
1775            expect_new_aggregation_epoch: bool,
1776        ) {
1777            assert!(aggregation_bandwidth >= self.bandwidth);
1778            let start_time = self.now;
1779
1780            let aggregation_bytes =
1781                (aggregation_bandwidth * aggregation_duration) as usize;
1782
1783            let num_acks = aggregation_bytes / bytes_per_ack;
1784            assert_eq!(aggregation_bytes, num_acks * bytes_per_ack);
1785
1786            let time_between_acks = Duration::from_micros(
1787                aggregation_duration.as_micros() as u64 / num_acks as u64,
1788            );
1789            assert_eq!(aggregation_duration, time_between_acks * num_acks as u32);
1790
1791            // The total duration of aggregation time and quiet period.
1792            let total_duration = Duration::from_micros(
1793                (aggregation_bytes as u64 * 8 * 1000000) /
1794                    self.bandwidth.to_bits_per_second(),
1795            );
1796
1797            assert_eq!(aggregation_bytes as u64, self.bandwidth * total_duration);
1798
1799            let mut last_extra_acked = 0;
1800
1801            for bytes in (0..aggregation_bytes).step_by(bytes_per_ack) {
1802                let extra_acked = self.tracker.update(
1803                    self.bandwidth,
1804                    true,
1805                    self.round_trip_count(),
1806                    self.last_sent_packet_number,
1807                    self.last_acked_packet_number,
1808                    self.now,
1809                    bytes_per_ack,
1810                );
1811                // `extra_acked` should be 0 if either
1812                // [1] We are at the beginning of a aggregation epoch(bytes==0)
1813                // and the     the current tracker implementation
1814                // can identify it, or [2] We are not really
1815                // aggregating acks.
1816                if (bytes == 0 && expect_new_aggregation_epoch) ||
1817                    (aggregation_bandwidth == self.bandwidth)
1818                {
1819                    assert_eq!(0, extra_acked);
1820                } else {
1821                    assert!(last_extra_acked < extra_acked);
1822                }
1823                self.now += time_between_acks;
1824                last_extra_acked = extra_acked;
1825            }
1826
1827            // Advance past the quiet period.
1828            self.now = start_time + total_duration;
1829        }
1830
1831        fn round_trip_count(&self) -> usize {
1832            ((self.now - self.start).as_micros() / self.rtt.as_micros()) as usize
1833        }
1834    }
1835
1836    fn test_inner(
1837        overestimate_avoidance: bool, bandwidth_gain: f64,
1838        agg_duration: Duration, byte_per_ack: usize,
1839    ) {
1840        let mut test_tracker = TestTracker::new(overestimate_avoidance);
1841
1842        let rnd = |tracker: &mut TestTracker, expect: bool| {
1843            tracker.aggregation_episode(
1844                tracker.bandwidth * bandwidth_gain,
1845                agg_duration,
1846                byte_per_ack,
1847                expect,
1848            );
1849        };
1850
1851        rnd(&mut test_tracker, true);
1852        rnd(&mut test_tracker, true);
1853
1854        test_tracker.now = test_tracker
1855            .now
1856            .checked_sub(Duration::from_millis(1))
1857            .unwrap();
1858
1859        if test_tracker.tracker.ack_aggregation_bandwidth_threshold > 1.1 {
1860            rnd(&mut test_tracker, true);
1861            assert_eq!(3, test_tracker.tracker.num_ack_aggregation_epochs);
1862        } else {
1863            rnd(&mut test_tracker, false);
1864            assert_eq!(2, test_tracker.tracker.num_ack_aggregation_epochs);
1865        }
1866    }
1867
1868    #[rstest]
1869    fn very_aggregated_large_acks(
1870        #[values(false, true)] overestimate_avoidance: bool,
1871    ) {
1872        test_inner(overestimate_avoidance, 20.0, Duration::from_millis(6), 1200)
1873    }
1874
1875    #[rstest]
1876    fn very_aggregated_small_acks(
1877        #[values(false, true)] overestimate_avoidance: bool,
1878    ) {
1879        test_inner(overestimate_avoidance, 20., Duration::from_millis(6), 300)
1880    }
1881
1882    #[rstest]
1883    fn somewhat_aggregated_large_acks(
1884        #[values(false, true)] overestimate_avoidance: bool,
1885    ) {
1886        test_inner(overestimate_avoidance, 2.0, Duration::from_millis(50), 1000)
1887    }
1888
1889    #[rstest]
1890    fn somewhat_aggregated_small_acks(
1891        #[values(false, true)] overestimate_avoidance: bool,
1892    ) {
1893        test_inner(overestimate_avoidance, 2.0, Duration::from_millis(50), 100)
1894    }
1895
1896    #[rstest]
1897    fn not_aggregated(#[values(false, true)] overestimate_avoidance: bool) {
1898        let mut test_tracker = TestTracker::new(overestimate_avoidance);
1899        test_tracker.aggregation_episode(
1900            test_tracker.bandwidth,
1901            Duration::from_millis(100),
1902            100,
1903            true,
1904        );
1905        assert!(2 < test_tracker.tracker.num_ack_aggregation_epochs);
1906    }
1907
1908    #[rstest]
1909    fn start_new_epoch_after_a_full_round(
1910        #[values(false, true)] overestimate_avoidance: bool,
1911    ) {
1912        let mut test_tracker = TestTracker::new(overestimate_avoidance);
1913
1914        test_tracker.last_sent_packet_number = 10;
1915
1916        test_tracker.aggregation_episode(
1917            test_tracker.bandwidth * 2.0,
1918            Duration::from_millis(50),
1919            100,
1920            true,
1921        );
1922
1923        test_tracker.last_acked_packet_number = 11;
1924
1925        // Update with a tiny bandwidth causes a very low expected bytes acked,
1926        // which in turn causes the current epoch to continue if the
1927        // `tracker` doesn't check the packet numbers.
1928        test_tracker.tracker.update(
1929            test_tracker.bandwidth * 0.1,
1930            true,
1931            test_tracker.round_trip_count(),
1932            test_tracker.last_sent_packet_number,
1933            test_tracker.last_acked_packet_number,
1934            test_tracker.now,
1935            100,
1936        );
1937
1938        assert_eq!(2, test_tracker.tracker.num_ack_aggregation_epochs)
1939    }
1940}