OLD | NEW |
1 // Copyright 2016 The Chromium Authors. All rights reserved. | 1 // Copyright 2016 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "net/quic/core/congestion_control/bbr_sender.h" | 5 #include "net/quic/core/congestion_control/bbr_sender.h" |
6 | 6 |
7 #include <algorithm> | 7 #include <algorithm> |
8 #include <sstream> | 8 #include <sstream> |
9 | 9 |
10 #include "net/quic/core/congestion_control/rtt_stats.h" | 10 #include "net/quic/core/congestion_control/rtt_stats.h" |
(...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
82 random_(random), | 82 random_(random), |
83 mode_(STARTUP), | 83 mode_(STARTUP), |
84 sampler_(), | 84 sampler_(), |
85 round_trip_count_(0), | 85 round_trip_count_(0), |
86 last_sent_packet_(0), | 86 last_sent_packet_(0), |
87 current_round_trip_end_(0), | 87 current_round_trip_end_(0), |
88 max_bandwidth_(kBandwidthWindowSize, QuicBandwidth::Zero(), 0), | 88 max_bandwidth_(kBandwidthWindowSize, QuicBandwidth::Zero(), 0), |
89 max_ack_height_(kBandwidthWindowSize, 0, 0), | 89 max_ack_height_(kBandwidthWindowSize, 0, 0), |
90 aggregation_epoch_start_time_(QuicTime::Zero()), | 90 aggregation_epoch_start_time_(QuicTime::Zero()), |
91 aggregation_epoch_bytes_(0), | 91 aggregation_epoch_bytes_(0), |
| 92 bytes_acked_since_queue_drained_(0), |
92 min_rtt_(QuicTime::Delta::Zero()), | 93 min_rtt_(QuicTime::Delta::Zero()), |
93 min_rtt_timestamp_(QuicTime::Zero()), | 94 min_rtt_timestamp_(QuicTime::Zero()), |
94 congestion_window_(initial_tcp_congestion_window * kDefaultTCPMSS), | 95 congestion_window_(initial_tcp_congestion_window * kDefaultTCPMSS), |
95 initial_congestion_window_(initial_tcp_congestion_window * | 96 initial_congestion_window_(initial_tcp_congestion_window * |
96 kDefaultTCPMSS), | 97 kDefaultTCPMSS), |
97 max_congestion_window_(max_tcp_congestion_window * kDefaultTCPMSS), | 98 max_congestion_window_(max_tcp_congestion_window * kDefaultTCPMSS), |
98 pacing_rate_(QuicBandwidth::Zero()), | 99 pacing_rate_(QuicBandwidth::Zero()), |
99 pacing_gain_(1), | 100 pacing_gain_(1), |
100 congestion_window_gain_(1), | 101 congestion_window_gain_(1), |
101 congestion_window_gain_constant_( | 102 congestion_window_gain_constant_( |
(...skipping 10 matching lines...) Expand all Loading... |
112 is_at_full_bandwidth_(false), | 113 is_at_full_bandwidth_(false), |
113 rounds_without_bandwidth_gain_(0), | 114 rounds_without_bandwidth_gain_(0), |
114 bandwidth_at_last_round_(QuicBandwidth::Zero()), | 115 bandwidth_at_last_round_(QuicBandwidth::Zero()), |
115 exiting_quiescence_(false), | 116 exiting_quiescence_(false), |
116 exit_probe_rtt_at_(QuicTime::Zero()), | 117 exit_probe_rtt_at_(QuicTime::Zero()), |
117 probe_rtt_round_passed_(false), | 118 probe_rtt_round_passed_(false), |
118 last_sample_is_app_limited_(false), | 119 last_sample_is_app_limited_(false), |
119 recovery_state_(NOT_IN_RECOVERY), | 120 recovery_state_(NOT_IN_RECOVERY), |
120 end_recovery_at_(0), | 121 end_recovery_at_(0), |
121 recovery_window_(max_congestion_window_), | 122 recovery_window_(max_congestion_window_), |
122 bytes_recently_acked_(0) { | 123 bytes_recently_acked_(0), |
| 124 rate_based_recovery_(false) { |
123 EnterStartupMode(); | 125 EnterStartupMode(); |
124 } | 126 } |
125 | 127 |
126 BbrSender::~BbrSender() {} | 128 BbrSender::~BbrSender() {} |
127 | 129 |
128 bool BbrSender::InSlowStart() const { | 130 bool BbrSender::InSlowStart() const { |
129 return mode_ == STARTUP; | 131 return mode_ == STARTUP; |
130 } | 132 } |
131 | 133 |
132 bool BbrSender::OnPacketSent(QuicTime sent_time, | 134 bool BbrSender::OnPacketSent(QuicTime sent_time, |
(...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
197 | 199 |
198 QuicBandwidth BbrSender::BandwidthEstimate() const { | 200 QuicBandwidth BbrSender::BandwidthEstimate() const { |
199 return max_bandwidth_.GetBest(); | 201 return max_bandwidth_.GetBest(); |
200 } | 202 } |
201 | 203 |
202 QuicByteCount BbrSender::GetCongestionWindow() const { | 204 QuicByteCount BbrSender::GetCongestionWindow() const { |
203 if (mode_ == PROBE_RTT) { | 205 if (mode_ == PROBE_RTT) { |
204 return kMinimumCongestionWindow; | 206 return kMinimumCongestionWindow; |
205 } | 207 } |
206 | 208 |
207 if (InRecovery()) { | 209 if (InRecovery() && !rate_based_recovery_) { |
208 return std::min(congestion_window_, recovery_window_); | 210 return std::min(congestion_window_, recovery_window_); |
209 } | 211 } |
210 | 212 |
211 return congestion_window_; | 213 return congestion_window_; |
212 } | 214 } |
213 | 215 |
214 QuicByteCount BbrSender::GetSlowStartThreshold() const { | 216 QuicByteCount BbrSender::GetSlowStartThreshold() const { |
215 return 0; | 217 return 0; |
216 } | 218 } |
217 | 219 |
218 bool BbrSender::InRecovery() const { | 220 bool BbrSender::InRecovery() const { |
219 return recovery_state_ != NOT_IN_RECOVERY; | 221 return recovery_state_ != NOT_IN_RECOVERY; |
220 } | 222 } |
221 | 223 |
222 void BbrSender::SetFromConfig(const QuicConfig& config, | 224 void BbrSender::SetFromConfig(const QuicConfig& config, |
223 Perspective perspective) { | 225 Perspective perspective) { |
224 if (config.HasClientRequestedIndependentOption(k1RTT, perspective)) { | 226 if (config.HasClientRequestedIndependentOption(k1RTT, perspective)) { |
225 num_startup_rtts_ = 1; | 227 num_startup_rtts_ = 1; |
226 } | 228 } |
227 if (config.HasClientRequestedIndependentOption(k2RTT, perspective)) { | 229 if (config.HasClientRequestedIndependentOption(k2RTT, perspective)) { |
228 num_startup_rtts_ = 2; | 230 num_startup_rtts_ = 2; |
229 } | 231 } |
| 232 if (FLAGS_quic_reloadable_flag_quic_bbr_rate_recovery && |
| 233 config.HasClientRequestedIndependentOption(kBBRR, perspective)) { |
| 234 rate_based_recovery_ = true; |
| 235 } |
230 } | 236 } |
231 | 237 |
232 void BbrSender::ResumeConnectionState( | 238 void BbrSender::ResumeConnectionState( |
233 const CachedNetworkParameters& cached_network_params, | 239 const CachedNetworkParameters& cached_network_params, |
234 bool max_bandwidth_resumption) { | 240 bool max_bandwidth_resumption) { |
235 if (!FLAGS_quic_reloadable_flag_quic_bbr_bandwidth_resumption) { | 241 if (!FLAGS_quic_reloadable_flag_quic_bbr_bandwidth_resumption) { |
236 return; | 242 return; |
237 } | 243 } |
238 | 244 |
239 QUIC_FLAG_COUNT(quic_reloadable_flag_quic_bbr_bandwidth_resumption); | 245 QUIC_FLAG_COUNT(quic_reloadable_flag_quic_bbr_bandwidth_resumption); |
(...skipping 24 matching lines...) Expand all Loading... |
264 DiscardLostPackets(lost_packets); | 270 DiscardLostPackets(lost_packets); |
265 | 271 |
266 // Input the new data into the BBR model of the connection. | 272 // Input the new data into the BBR model of the connection. |
267 if (!acked_packets.empty()) { | 273 if (!acked_packets.empty()) { |
268 QuicPacketNumber last_acked_packet = acked_packets.rbegin()->first; | 274 QuicPacketNumber last_acked_packet = acked_packets.rbegin()->first; |
269 is_round_start = UpdateRoundTripCounter(last_acked_packet); | 275 is_round_start = UpdateRoundTripCounter(last_acked_packet); |
270 min_rtt_expired = UpdateBandwidthAndMinRtt(event_time, acked_packets); | 276 min_rtt_expired = UpdateBandwidthAndMinRtt(event_time, acked_packets); |
271 UpdateRecoveryState(last_acked_packet, !lost_packets.empty(), | 277 UpdateRecoveryState(last_acked_packet, !lost_packets.empty(), |
272 is_round_start); | 278 is_round_start); |
273 | 279 |
| 280 const QuicByteCount bytes_acked = |
| 281 sampler_.total_bytes_acked() - total_bytes_acked_before; |
274 if (FLAGS_quic_reloadable_flag_quic_bbr_slow_recent_delivery) { | 282 if (FLAGS_quic_reloadable_flag_quic_bbr_slow_recent_delivery) { |
275 QUIC_FLAG_COUNT_N(quic_reloadable_flag_quic_bbr_slow_recent_delivery, 1, | 283 QUIC_FLAG_COUNT_N(quic_reloadable_flag_quic_bbr_slow_recent_delivery, 1, |
276 2); | 284 2); |
277 UpdateRecentlyAcked( | 285 UpdateRecentlyAcked(event_time, bytes_acked); |
278 event_time, sampler_.total_bytes_acked() - total_bytes_acked_before); | |
279 } | 286 } |
280 | 287 |
281 if (FLAGS_quic_reloadable_flag_quic_bbr_ack_aggregation_bytes) { | 288 if (FLAGS_quic_reloadable_flag_quic_bbr_ack_aggregation_bytes) { |
282 QUIC_FLAG_COUNT_N(quic_reloadable_flag_quic_bbr_ack_aggregation_bytes, 1, | 289 QUIC_FLAG_COUNT_N(quic_reloadable_flag_quic_bbr_ack_aggregation_bytes, 1, |
283 2); | 290 2); |
284 UpdateAckAggregationBytes( | 291 UpdateAckAggregationBytes(event_time, bytes_acked); |
285 event_time, sampler_.total_bytes_acked() - total_bytes_acked_before); | 292 } |
| 293 if (FLAGS_quic_reloadable_flag_quic_bbr_ack_aggregation_bytes2) { |
| 294 QUIC_FLAG_COUNT_N(quic_reloadable_flag_quic_bbr_ack_aggregation_bytes2, 1, |
| 295 2); |
| 296 UpdateAckAggregationBytes(event_time, bytes_acked); |
| 297 if (unacked_packets_->bytes_in_flight() <= |
| 298 1.25 * GetTargetCongestionWindow(pacing_gain_)) { |
| 299 bytes_acked_since_queue_drained_ = 0; |
| 300 } else { |
| 301 bytes_acked_since_queue_drained_ += bytes_acked; |
| 302 } |
286 } | 303 } |
287 } | 304 } |
288 | 305 |
289 // Handle logic specific to PROBE_BW mode. | 306 // Handle logic specific to PROBE_BW mode. |
290 if (mode_ == PROBE_BW) { | 307 if (mode_ == PROBE_BW) { |
291 UpdateGainCyclePhase(event_time, prior_in_flight, !lost_packets.empty()); | 308 UpdateGainCyclePhase(event_time, prior_in_flight, !lost_packets.empty()); |
292 } | 309 } |
293 | 310 |
294 // Handle logic specific to STARTUP and DRAIN modes. | 311 // Handle logic specific to STARTUP and DRAIN modes. |
295 if (is_round_start && !is_at_full_bandwidth_) { | 312 if (is_round_start && !is_at_full_bandwidth_) { |
(...skipping 307 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
603 max_ack_height_.Update(aggregation_epoch_bytes_ - expected_bytes_acked, | 620 max_ack_height_.Update(aggregation_epoch_bytes_ - expected_bytes_acked, |
604 round_trip_count_); | 621 round_trip_count_); |
605 } | 622 } |
606 | 623 |
607 void BbrSender::CalculatePacingRate() { | 624 void BbrSender::CalculatePacingRate() { |
608 if (BandwidthEstimate().IsZero()) { | 625 if (BandwidthEstimate().IsZero()) { |
609 return; | 626 return; |
610 } | 627 } |
611 | 628 |
612 QuicBandwidth target_rate = pacing_gain_ * BandwidthEstimate(); | 629 QuicBandwidth target_rate = pacing_gain_ * BandwidthEstimate(); |
| 630 if (rate_based_recovery_ && InRecovery()) { |
| 631 QUIC_FLAG_COUNT(quic_reloadable_flag_quic_bbr_rate_recovery); |
| 632 pacing_rate_ = pacing_gain_ * max_bandwidth_.GetThirdBest(); |
| 633 } |
613 if (is_at_full_bandwidth_) { | 634 if (is_at_full_bandwidth_) { |
614 pacing_rate_ = target_rate; | 635 pacing_rate_ = target_rate; |
615 return; | 636 return; |
616 } | 637 } |
617 | 638 |
618 // Pace at the rate of initial_window / RTT as soon as RTT measurements are | 639 // Pace at the rate of initial_window / RTT as soon as RTT measurements are |
619 // available. | 640 // available. |
620 if (pacing_rate_.IsZero() && !rtt_stats_->min_rtt().IsZero()) { | 641 if (pacing_rate_.IsZero() && !rtt_stats_->min_rtt().IsZero()) { |
621 pacing_rate_ = QuicBandwidth::FromBytesAndTimeDelta( | 642 pacing_rate_ = QuicBandwidth::FromBytesAndTimeDelta( |
622 initial_congestion_window_, rtt_stats_->min_rtt()); | 643 initial_congestion_window_, rtt_stats_->min_rtt()); |
(...skipping 13 matching lines...) Expand all Loading... |
636 GetTargetCongestionWindow(congestion_window_gain_); | 657 GetTargetCongestionWindow(congestion_window_gain_); |
637 | 658 |
638 if (rtt_variance_weight_ > 0.f && !BandwidthEstimate().IsZero()) { | 659 if (rtt_variance_weight_ > 0.f && !BandwidthEstimate().IsZero()) { |
639 target_window += rtt_variance_weight_ * rtt_stats_->mean_deviation() * | 660 target_window += rtt_variance_weight_ * rtt_stats_->mean_deviation() * |
640 BandwidthEstimate(); | 661 BandwidthEstimate(); |
641 } else if (FLAGS_quic_reloadable_flag_quic_bbr_ack_aggregation_bytes && | 662 } else if (FLAGS_quic_reloadable_flag_quic_bbr_ack_aggregation_bytes && |
642 is_at_full_bandwidth_) { | 663 is_at_full_bandwidth_) { |
643 QUIC_FLAG_COUNT_N(quic_reloadable_flag_quic_bbr_ack_aggregation_bytes, 2, | 664 QUIC_FLAG_COUNT_N(quic_reloadable_flag_quic_bbr_ack_aggregation_bytes, 2, |
644 2); | 665 2); |
645 target_window += max_ack_height_.GetBest(); | 666 target_window += max_ack_height_.GetBest(); |
| 667 } else if (FLAGS_quic_reloadable_flag_quic_bbr_ack_aggregation_bytes2 && |
| 668 is_at_full_bandwidth_) { |
| 669 QUIC_FLAG_COUNT_N(quic_reloadable_flag_quic_bbr_ack_aggregation_bytes2, 2, |
| 670 2); |
| 671 if (2 * max_ack_height_.GetBest() > bytes_acked_since_queue_drained_) { |
| 672 target_window += |
| 673 2 * max_ack_height_.GetBest() - bytes_acked_since_queue_drained_; |
| 674 } |
646 } | 675 } |
647 if (FLAGS_quic_reloadable_flag_quic_bbr_add_tso_cwnd) { | 676 if (FLAGS_quic_reloadable_flag_quic_bbr_add_tso_cwnd) { |
648 // QUIC doesn't have TSO, but it does have similarly quantized pacing, so | 677 // QUIC doesn't have TSO, but it does have similarly quantized pacing, so |
649 // allow extra CWND to make QUIC's BBR CWND identical to TCP's. | 678 // allow extra CWND to make QUIC's BBR CWND identical to TCP's. |
650 QuicByteCount tso_segs_goal = 0; | 679 QuicByteCount tso_segs_goal = 0; |
651 if (pacing_rate_ < QuicBandwidth::FromKBitsPerSecond(1200)) { | 680 if (pacing_rate_ < QuicBandwidth::FromKBitsPerSecond(1200)) { |
652 tso_segs_goal = kDefaultTCPMSS; | 681 tso_segs_goal = kDefaultTCPMSS; |
653 } else if (pacing_rate_ < QuicBandwidth::FromKBitsPerSecond(24000)) { | 682 } else if (pacing_rate_ < QuicBandwidth::FromKBitsPerSecond(24000)) { |
654 tso_segs_goal = 2 * kDefaultTCPMSS; | 683 tso_segs_goal = 2 * kDefaultTCPMSS; |
655 } else { | 684 } else { |
(...skipping 17 matching lines...) Expand all Loading... |
673 congestion_window_ = congestion_window_ + bytes_acked; | 702 congestion_window_ = congestion_window_ + bytes_acked; |
674 } | 703 } |
675 | 704 |
676 // Enforce the limits on the congestion window. | 705 // Enforce the limits on the congestion window. |
677 congestion_window_ = std::max(congestion_window_, kMinimumCongestionWindow); | 706 congestion_window_ = std::max(congestion_window_, kMinimumCongestionWindow); |
678 congestion_window_ = std::min(congestion_window_, max_congestion_window_); | 707 congestion_window_ = std::min(congestion_window_, max_congestion_window_); |
679 } | 708 } |
680 | 709 |
681 void BbrSender::CalculateRecoveryWindow(QuicByteCount bytes_acked, | 710 void BbrSender::CalculateRecoveryWindow(QuicByteCount bytes_acked, |
682 QuicByteCount bytes_lost) { | 711 QuicByteCount bytes_lost) { |
| 712 if (rate_based_recovery_) { |
| 713 return; |
| 714 } |
683 if (FLAGS_quic_reloadable_flag_quic_bbr_fix_conservation2) { | 715 if (FLAGS_quic_reloadable_flag_quic_bbr_fix_conservation2) { |
684 if (recovery_state_ == NOT_IN_RECOVERY) { | 716 if (recovery_state_ == NOT_IN_RECOVERY) { |
685 return; | 717 return; |
686 } | 718 } |
687 | 719 |
688 // Set up the initial recovery window. | 720 // Set up the initial recovery window. |
689 if (recovery_window_ == 0) { | 721 if (recovery_window_ == 0) { |
690 QUIC_FLAG_COUNT_N(quic_reloadable_flag_quic_bbr_fix_conservation2, 2, 3); | 722 QUIC_FLAG_COUNT_N(quic_reloadable_flag_quic_bbr_fix_conservation2, 2, 3); |
691 recovery_window_ = unacked_packets_->bytes_in_flight() + bytes_acked; | 723 recovery_window_ = unacked_packets_->bytes_in_flight() + bytes_acked; |
692 recovery_window_ = std::max(kMinimumCongestionWindow, recovery_window_); | 724 recovery_window_ = std::max(kMinimumCongestionWindow, recovery_window_); |
(...skipping 94 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
787 os << "Minimum RTT timestamp: " << state.min_rtt_timestamp.ToDebuggingValue() | 819 os << "Minimum RTT timestamp: " << state.min_rtt_timestamp.ToDebuggingValue() |
788 << std::endl; | 820 << std::endl; |
789 | 821 |
790 os << "Last sample is app-limited: " | 822 os << "Last sample is app-limited: " |
791 << (state.last_sample_is_app_limited ? "yes" : "no"); | 823 << (state.last_sample_is_app_limited ? "yes" : "no"); |
792 | 824 |
793 return os; | 825 return os; |
794 } | 826 } |
795 | 827 |
796 } // namespace net | 828 } // namespace net |
OLD | NEW |