| 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 |