1use 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 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 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 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 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 end_of_app_limited_phase: Option<u64>,
125 overestimate_avoidance: bool,
126 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#[derive(Debug, Default, Clone, Copy)]
138pub struct SendTimeState {
139 pub is_valid: bool,
141 pub is_app_limited: bool,
146 pub total_bytes_sent: usize,
149 pub total_bytes_acked: usize,
151 #[allow(dead_code)]
153 pub total_bytes_lost: usize,
154 pub bytes_in_flight: usize,
159}
160
161#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Clone, Copy, Default)]
162struct ExtraAckedEvent {
163 extra_acked: usize,
165 bytes_acked: usize,
167 time_delta: Duration,
168 round: usize,
170}
171
172struct BandwidthSample {
175 bandwidth: Bandwidth,
177 rtt: Duration,
180 send_rate: Option<Bandwidth>,
184 ack_rate: Bandwidth,
188 state_at_send: SendTimeState,
190}
191
192#[derive(Debug, Clone, Copy)]
194struct AckPoint {
195 ack_time: Instant,
196 total_bytes_acked: usize,
197}
198
199#[derive(Debug, Default)]
202struct RecentAckPoints {
203 ack_points: [Option<AckPoint>; 2],
204}
205
206#[derive(Debug)]
211struct ConnectionStateOnSentPacket {
212 sent_time: Instant,
214 size: usize,
216 total_bytes_sent_at_last_acked_packet: usize,
219 last_acked_packet_sent_time: Instant,
222 last_acked_packet_ack_time: Instant,
225 send_time_state: SendTimeState,
228}
229
230#[derive(Debug)]
234struct MaxAckHeightTracker {
235 max_ack_height_filter: WindowedFilter<ExtraAckedEvent, usize, usize>,
238 aggregation_epoch_start_time: Option<Instant>,
241 aggregation_epoch_bytes: usize,
242 last_sent_packet_number_before_epoch: u64,
245 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#[derive(Default)]
256pub(crate) struct CongestionEventSample {
257 pub sample_max_bandwidth: Option<Bandwidth>,
259 pub sample_is_app_limited: bool,
261 pub sample_rtt: Option<Duration>,
263 pub sample_max_inflight: usize,
267 pub last_packet_send_state: SendTimeState,
271 pub extra_acked: usize,
275
276 pub sample_max_send_rate: Option<Bandwidth>,
279 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 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 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 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 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 if self.aggregation_epoch_bytes <=
394 (self.ack_aggregation_bandwidth_threshold *
395 expected_bytes_acked as f64) as usize
396 {
397 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 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 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 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 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 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 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 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 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 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 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 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 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 fn send_40_and_ack_first_20(&mut self, time_between_packets: Duration) {
1053 for i in 1..=20 {
1055 self.send_packet(i, REGULAR_PACKET_SIZE, true);
1056 self.advance_time(time_between_packets);
1057 }
1058
1059 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 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 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 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 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 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 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 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 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 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 #[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 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 #[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 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 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 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 #[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 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 assert_eq!(10, test_sender.number_of_tracked_packets());
1302
1303 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 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 assert_eq!(0, test_sender.number_of_tracked_packets());
1331 assert_eq!(0, test_sender.bytes_in_flight);
1332 }
1333
1334 #[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 test_sender.advance_time(time_between_packets * 15);
1351
1352 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 assert_eq!(0, test_sender.number_of_tracked_packets());
1365 assert_eq!(0, test_sender.bytes_in_flight);
1366 }
1367
1368 #[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 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 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 #[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 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 test_sender.advance_time(Duration::from_secs(1));
1443
1444 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 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 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 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 #[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 assert!(last_sample < real_bandwidth);
1520 assert!(last_sample > real_bandwidth * 0.9);
1521 }
1522
1523 #[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 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 #[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 #[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 let sample = test_sender.on_congestion_event(&[i], &[i - 1]);
1661 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 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 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 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 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 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 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 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}