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" |
11 #include "net/quic/core/crypto/crypto_protocol.h" | 11 #include "net/quic/core/crypto/crypto_protocol.h" |
12 #include "net/quic/core/proto/cached_network_parameters.pb.h" | 12 #include "net/quic/core/proto/cached_network_parameters.pb.h" |
13 #include "net/quic/core/quic_flags.h" | |
14 #include "net/quic/platform/api/quic_bug_tracker.h" | 13 #include "net/quic/platform/api/quic_bug_tracker.h" |
15 #include "net/quic/platform/api/quic_flag_utils.h" | 14 #include "net/quic/platform/api/quic_flag_utils.h" |
| 15 #include "net/quic/platform/api/quic_flags.h" |
16 #include "net/quic/platform/api/quic_logging.h" | 16 #include "net/quic/platform/api/quic_logging.h" |
17 | 17 |
18 namespace net { | 18 namespace net { |
19 | 19 |
20 namespace { | 20 namespace { |
21 // Constants based on TCP defaults. | 21 // Constants based on TCP defaults. |
22 const QuicByteCount kMaxSegmentSize = kDefaultTCPMSS; | 22 const QuicByteCount kMaxSegmentSize = kDefaultTCPMSS; |
23 // The minimum CWND to ensure delayed acks don't reduce bandwidth measurements. | 23 // The minimum CWND to ensure delayed acks don't reduce bandwidth measurements. |
24 // Does not inflate the pacing rate. | 24 // Does not inflate the pacing rate. |
25 const QuicByteCount kMinimumCongestionWindow = 4 * kMaxSegmentSize; | 25 const QuicByteCount kMinimumCongestionWindow = 4 * kMaxSegmentSize; |
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
73 QuicRandom* random) | 73 QuicRandom* random) |
74 : rtt_stats_(rtt_stats), | 74 : rtt_stats_(rtt_stats), |
75 unacked_packets_(unacked_packets), | 75 unacked_packets_(unacked_packets), |
76 random_(random), | 76 random_(random), |
77 mode_(STARTUP), | 77 mode_(STARTUP), |
78 sampler_(), | 78 sampler_(), |
79 round_trip_count_(0), | 79 round_trip_count_(0), |
80 last_sent_packet_(0), | 80 last_sent_packet_(0), |
81 current_round_trip_end_(0), | 81 current_round_trip_end_(0), |
82 max_bandwidth_(kBandwidthWindowSize, QuicBandwidth::Zero(), 0), | 82 max_bandwidth_(kBandwidthWindowSize, QuicBandwidth::Zero(), 0), |
83 max_ack_spacing_(kBandwidthWindowSize, QuicTime::Delta::Zero(), 0), | |
84 largest_acked_time_(QuicTime::Zero()), | |
85 largest_acked_sent_time_(QuicTime::Zero()), | |
86 max_ack_height_(kBandwidthWindowSize, 0, 0), | 83 max_ack_height_(kBandwidthWindowSize, 0, 0), |
87 aggregation_epoch_start_time_(QuicTime::Zero()), | 84 aggregation_epoch_start_time_(QuicTime::Zero()), |
88 aggregation_epoch_bytes_(0), | 85 aggregation_epoch_bytes_(0), |
89 min_rtt_(QuicTime::Delta::Zero()), | 86 min_rtt_(QuicTime::Delta::Zero()), |
90 min_rtt_timestamp_(QuicTime::Zero()), | 87 min_rtt_timestamp_(QuicTime::Zero()), |
91 congestion_window_(initial_tcp_congestion_window * kDefaultTCPMSS), | 88 congestion_window_(initial_tcp_congestion_window * kDefaultTCPMSS), |
92 initial_congestion_window_(initial_tcp_congestion_window * | 89 initial_congestion_window_(initial_tcp_congestion_window * |
93 kDefaultTCPMSS), | 90 kDefaultTCPMSS), |
94 max_congestion_window_(max_tcp_congestion_window * kDefaultTCPMSS), | 91 max_congestion_window_(max_tcp_congestion_window * kDefaultTCPMSS), |
95 pacing_rate_(QuicBandwidth::Zero()), | 92 pacing_rate_(QuicBandwidth::Zero()), |
96 pacing_gain_(1), | 93 pacing_gain_(1), |
97 congestion_window_gain_(1), | 94 congestion_window_gain_(1), |
98 congestion_window_gain_constant_( | 95 congestion_window_gain_constant_( |
99 static_cast<float>(base::GetFlag(FLAGS_quic_bbr_cwnd_gain))), | 96 static_cast<float>(GetQuicFlag(FLAGS_quic_bbr_cwnd_gain))), |
100 rtt_variance_weight_(static_cast<float>( | 97 rtt_variance_weight_( |
101 base::GetFlag(FLAGS_quic_bbr_rtt_variation_weight))), | 98 static_cast<float>(GetQuicFlag(FLAGS_quic_bbr_rtt_variation_weight))), |
102 num_startup_rtts_(kRoundTripsWithoutGrowthBeforeExitingStartup), | 99 num_startup_rtts_(kRoundTripsWithoutGrowthBeforeExitingStartup), |
103 cycle_current_offset_(0), | 100 cycle_current_offset_(0), |
104 last_cycle_start_(QuicTime::Zero()), | 101 last_cycle_start_(QuicTime::Zero()), |
105 is_at_full_bandwidth_(false), | 102 is_at_full_bandwidth_(false), |
106 rounds_without_bandwidth_gain_(0), | 103 rounds_without_bandwidth_gain_(0), |
107 bandwidth_at_last_round_(QuicBandwidth::Zero()), | 104 bandwidth_at_last_round_(QuicBandwidth::Zero()), |
108 exiting_quiescence_(false), | 105 exiting_quiescence_(false), |
109 exit_probe_rtt_at_(QuicTime::Zero()), | 106 exit_probe_rtt_at_(QuicTime::Zero()), |
110 probe_rtt_round_passed_(false), | 107 probe_rtt_round_passed_(false), |
111 last_sample_is_app_limited_(false), | 108 last_sample_is_app_limited_(false), |
(...skipping 26 matching lines...) Expand all Loading... |
138 } | 135 } |
139 | 136 |
140 QuicTime::Delta BbrSender::TimeUntilSend(QuicTime /* now */, | 137 QuicTime::Delta BbrSender::TimeUntilSend(QuicTime /* now */, |
141 QuicByteCount bytes_in_flight) const { | 138 QuicByteCount bytes_in_flight) const { |
142 if (bytes_in_flight < GetCongestionWindow()) { | 139 if (bytes_in_flight < GetCongestionWindow()) { |
143 return QuicTime::Delta::Zero(); | 140 return QuicTime::Delta::Zero(); |
144 } | 141 } |
145 return QuicTime::Delta::Infinite(); | 142 return QuicTime::Delta::Infinite(); |
146 } | 143 } |
147 | 144 |
148 QuicBandwidth BbrSender::PacingRate(QuicByteCount /*bytes_in_flight*/) const { | 145 QuicBandwidth BbrSender::PacingRate(QuicByteCount bytes_in_flight) const { |
149 if (pacing_rate_.IsZero()) { | 146 if (pacing_rate_.IsZero()) { |
150 return kHighGain * QuicBandwidth::FromBytesAndTimeDelta( | 147 return kHighGain * QuicBandwidth::FromBytesAndTimeDelta( |
151 initial_congestion_window_, GetMinRtt()); | 148 initial_congestion_window_, GetMinRtt()); |
152 } | 149 } |
| 150 if (FLAGS_quic_reloadable_flag_quic_bbr_keep_sending_at_recent_rate && |
| 151 mode_ == PROBE_BW && bytes_in_flight > congestion_window_) { |
| 152 QUIC_FLAG_COUNT_N(quic_reloadable_flag_quic_bbr_keep_sending_at_recent_rate, |
| 153 1, 2); |
| 154 if (pacing_gain_ > 1) { |
| 155 return max_bandwidth_.GetBest(); |
| 156 } else { |
| 157 return max_bandwidth_.GetThirdBest(); |
| 158 } |
| 159 } |
153 return pacing_rate_; | 160 return pacing_rate_; |
154 } | 161 } |
155 | 162 |
156 QuicBandwidth BbrSender::BandwidthEstimate() const { | 163 QuicBandwidth BbrSender::BandwidthEstimate() const { |
157 return max_bandwidth_.GetBest(); | 164 return max_bandwidth_.GetBest(); |
158 } | 165 } |
159 | 166 |
160 QuicByteCount BbrSender::GetCongestionWindow() const { | 167 QuicByteCount BbrSender::GetCongestionWindow() const { |
161 if (mode_ == PROBE_RTT) { | 168 if (mode_ == PROBE_RTT) { |
162 return kMinimumCongestionWindow; | 169 return kMinimumCongestionWindow; |
163 } | 170 } |
164 | 171 |
165 if (InRecovery()) { | 172 if (InRecovery()) { |
166 return std::min(congestion_window_, recovery_window_); | 173 return std::min(congestion_window_, recovery_window_); |
167 } | 174 } |
168 | 175 |
| 176 if (FLAGS_quic_reloadable_flag_quic_bbr_keep_sending_at_recent_rate && |
| 177 mode_ == PROBE_BW && pacing_gain_ >= 1) { |
| 178 QUIC_FLAG_COUNT_N(quic_reloadable_flag_quic_bbr_keep_sending_at_recent_rate, |
| 179 2, 2); |
| 180 // Send for another SRTT at a more recently measured bandwidth. |
| 181 return congestion_window_ + |
| 182 max_bandwidth_.GetThirdBest() * rtt_stats_->smoothed_rtt(); |
| 183 } |
| 184 |
169 return congestion_window_; | 185 return congestion_window_; |
170 } | 186 } |
171 | 187 |
172 QuicByteCount BbrSender::GetSlowStartThreshold() const { | 188 QuicByteCount BbrSender::GetSlowStartThreshold() const { |
173 return 0; | 189 return 0; |
174 } | 190 } |
175 | 191 |
176 bool BbrSender::InRecovery() const { | 192 bool BbrSender::InRecovery() const { |
177 return recovery_state_ != NOT_IN_RECOVERY; | 193 return recovery_state_ != NOT_IN_RECOVERY; |
178 } | 194 } |
(...skipping 11 matching lines...) Expand all Loading... |
190 } | 206 } |
191 } | 207 } |
192 | 208 |
193 void BbrSender::ResumeConnectionState( | 209 void BbrSender::ResumeConnectionState( |
194 const CachedNetworkParameters& cached_network_params, | 210 const CachedNetworkParameters& cached_network_params, |
195 bool max_bandwidth_resumption) { | 211 bool max_bandwidth_resumption) { |
196 if (!FLAGS_quic_reloadable_flag_quic_bbr_bandwidth_resumption) { | 212 if (!FLAGS_quic_reloadable_flag_quic_bbr_bandwidth_resumption) { |
197 return; | 213 return; |
198 } | 214 } |
199 | 215 |
| 216 QUIC_FLAG_COUNT(quic_reloadable_flag_quic_bbr_bandwidth_resumption); |
| 217 |
200 QuicBandwidth bandwidth = QuicBandwidth::FromBytesPerSecond( | 218 QuicBandwidth bandwidth = QuicBandwidth::FromBytesPerSecond( |
201 max_bandwidth_resumption | 219 max_bandwidth_resumption |
202 ? cached_network_params.max_bandwidth_estimate_bytes_per_second() | 220 ? cached_network_params.max_bandwidth_estimate_bytes_per_second() |
203 : cached_network_params.bandwidth_estimate_bytes_per_second()); | 221 : cached_network_params.bandwidth_estimate_bytes_per_second()); |
204 QuicTime::Delta rtt = | 222 QuicTime::Delta rtt = |
205 QuicTime::Delta::FromMilliseconds(cached_network_params.min_rtt_ms()); | 223 QuicTime::Delta::FromMilliseconds(cached_network_params.min_rtt_ms()); |
206 | 224 |
207 max_bandwidth_.Update(bandwidth, round_trip_count_); | 225 max_bandwidth_.Update(bandwidth, round_trip_count_); |
208 if (!rtt.IsZero() && (min_rtt_ > rtt || min_rtt_.IsZero())) { | 226 if (!rtt.IsZero() && (min_rtt_ > rtt || min_rtt_.IsZero())) { |
209 min_rtt_ = rtt; | 227 min_rtt_ = rtt; |
(...skipping 12 matching lines...) Expand all Loading... |
222 | 240 |
223 DiscardLostPackets(lost_packets); | 241 DiscardLostPackets(lost_packets); |
224 | 242 |
225 // Input the new data into the BBR model of the connection. | 243 // Input the new data into the BBR model of the connection. |
226 if (!acked_packets.empty()) { | 244 if (!acked_packets.empty()) { |
227 QuicPacketNumber last_acked_packet = acked_packets.rbegin()->first; | 245 QuicPacketNumber last_acked_packet = acked_packets.rbegin()->first; |
228 is_round_start = UpdateRoundTripCounter(last_acked_packet); | 246 is_round_start = UpdateRoundTripCounter(last_acked_packet); |
229 min_rtt_expired = UpdateBandwidthAndMinRtt(event_time, acked_packets); | 247 min_rtt_expired = UpdateBandwidthAndMinRtt(event_time, acked_packets); |
230 UpdateRecoveryState(last_acked_packet, !lost_packets.empty(), | 248 UpdateRecoveryState(last_acked_packet, !lost_packets.empty(), |
231 is_round_start); | 249 is_round_start); |
232 if (FLAGS_quic_reloadable_flag_quic_bbr_ack_spacing2) { | |
233 QUIC_FLAG_COUNT_N(quic_reloadable_flag_quic_bbr_ack_spacing2, 1, 2); | |
234 UpdateAckSpacing(event_time, last_acked_packet, acked_packets); | |
235 } | |
236 if (FLAGS_quic_reloadable_flag_quic_bbr_ack_aggregation_bytes) { | 250 if (FLAGS_quic_reloadable_flag_quic_bbr_ack_aggregation_bytes) { |
237 QUIC_FLAG_COUNT_N(quic_reloadable_flag_quic_bbr_ack_aggregation_bytes, 1, | 251 QUIC_FLAG_COUNT_N(quic_reloadable_flag_quic_bbr_ack_aggregation_bytes, 1, |
238 2); | 252 2); |
239 UpdateAckAggregationBytes( | 253 UpdateAckAggregationBytes( |
240 event_time, sampler_.total_bytes_acked() - total_bytes_acked_before); | 254 event_time, sampler_.total_bytes_acked() - total_bytes_acked_before); |
241 } | 255 } |
242 } | 256 } |
243 | 257 |
244 // Handle logic specific to PROBE_BW mode. | 258 // Handle logic specific to PROBE_BW mode. |
245 if (mode_ == PROBE_BW) { | 259 if (mode_ == PROBE_BW) { |
(...skipping 26 matching lines...) Expand all Loading... |
272 } | 286 } |
273 | 287 |
274 QuicTime::Delta BbrSender::GetMinRtt() const { | 288 QuicTime::Delta BbrSender::GetMinRtt() const { |
275 return !min_rtt_.IsZero() | 289 return !min_rtt_.IsZero() |
276 ? min_rtt_ | 290 ? min_rtt_ |
277 : QuicTime::Delta::FromMicroseconds(rtt_stats_->initial_rtt_us()); | 291 : QuicTime::Delta::FromMicroseconds(rtt_stats_->initial_rtt_us()); |
278 } | 292 } |
279 | 293 |
280 QuicByteCount BbrSender::GetTargetCongestionWindow(float gain) const { | 294 QuicByteCount BbrSender::GetTargetCongestionWindow(float gain) const { |
281 QuicByteCount bdp = GetMinRtt() * BandwidthEstimate(); | 295 QuicByteCount bdp = GetMinRtt() * BandwidthEstimate(); |
| 296 if (FLAGS_quic_reloadable_flag_quic_bbr_base_cwnd_on_srtt && |
| 297 mode_ == PROBE_BW && gain >= 1 && !rtt_stats_->smoothed_rtt().IsZero()) { |
| 298 bdp = rtt_stats_->smoothed_rtt() * BandwidthEstimate(); |
| 299 } |
282 QuicByteCount congestion_window = gain * bdp; | 300 QuicByteCount congestion_window = gain * bdp; |
283 | 301 |
284 // BDP estimate will be zero if no bandwidth samples are available yet. | 302 // BDP estimate will be zero if no bandwidth samples are available yet. |
285 if (congestion_window == 0) { | 303 if (congestion_window == 0) { |
286 congestion_window = gain * initial_congestion_window_; | 304 congestion_window = gain * initial_congestion_window_; |
287 } | 305 } |
288 | 306 |
289 return std::max(congestion_window, kMinimumCongestionWindow); | 307 return std::max(congestion_window, kMinimumCongestionWindow); |
290 } | 308 } |
291 | 309 |
(...skipping 203 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
495 | 513 |
496 case GROWTH: | 514 case GROWTH: |
497 // Exit recovery if appropriate. | 515 // Exit recovery if appropriate. |
498 if (!has_losses && last_acked_packet > end_recovery_at_) { | 516 if (!has_losses && last_acked_packet > end_recovery_at_) { |
499 recovery_state_ = NOT_IN_RECOVERY; | 517 recovery_state_ = NOT_IN_RECOVERY; |
500 } | 518 } |
501 break; | 519 break; |
502 } | 520 } |
503 } | 521 } |
504 | 522 |
505 // TODO(ianswett): Move this logic into BandwidthSampler. | |
506 void BbrSender::UpdateAckSpacing(QuicTime ack_time, | |
507 QuicPacketNumber largest_newly_acked, | |
508 const CongestionVector& acked_packets) { | |
509 // Ignore acks of reordered packets. | |
510 if (largest_newly_acked < unacked_packets_->largest_observed()) { | |
511 return; | |
512 } | |
513 // Ignore acks of only one packet to filter out delayed acks. | |
514 if (acked_packets.size() == 1) { | |
515 return; | |
516 } | |
517 QuicTime largest_newly_acked_sent_time = | |
518 unacked_packets_->GetTransmissionInfo(largest_newly_acked).sent_time; | |
519 // Initialize on the first ack. | |
520 if (!largest_acked_time_.IsInitialized()) { | |
521 largest_acked_time_ = ack_time; | |
522 largest_acked_sent_time_ = largest_newly_acked_sent_time; | |
523 return; | |
524 } | |
525 QuicTime::Delta ack_delta = ack_time - largest_acked_time_; | |
526 QuicTime::Delta send_delta = | |
527 largest_newly_acked_sent_time - largest_acked_sent_time_; | |
528 largest_acked_time_ = ack_time; | |
529 largest_acked_sent_time_ = largest_newly_acked_sent_time; | |
530 if (ack_delta <= send_delta) { | |
531 return; | |
532 } | |
533 | |
534 // Limit the ack spacing to SRTT to filter outliers. | |
535 QuicTime::Delta ack_spacing = | |
536 std::min(ack_delta - send_delta, rtt_stats_->smoothed_rtt()); | |
537 max_ack_spacing_.Update(ack_spacing, round_trip_count_); | |
538 } | |
539 | |
540 // TODO(ianswett): Move this logic into BandwidthSampler. | |
541 void BbrSender::UpdateAckAggregationBytes(QuicTime ack_time, | 523 void BbrSender::UpdateAckAggregationBytes(QuicTime ack_time, |
542 QuicByteCount newly_acked_bytes) { | 524 QuicByteCount newly_acked_bytes) { |
543 // Compute how many bytes are expected to be delivered, assuming max bandwidth | 525 // Compute how many bytes are expected to be delivered, assuming max bandwidth |
544 // is correct. | 526 // is correct. |
545 QuicByteCount expected_bytes_acked = | 527 QuicByteCount expected_bytes_acked = |
546 max_bandwidth_.GetBest() * (ack_time - aggregation_epoch_start_time_); | 528 max_bandwidth_.GetBest() * (ack_time - aggregation_epoch_start_time_); |
547 // Reset the current aggregation epoch as soon as the ack arrival rate is less | 529 // Reset the current aggregation epoch as soon as the ack arrival rate is less |
548 // than or equal to the max bandwidth. | 530 // than or equal to the max bandwidth. |
549 if (aggregation_epoch_bytes_ <= expected_bytes_acked) { | 531 if (aggregation_epoch_bytes_ <= expected_bytes_acked) { |
550 // Reset to start measuring a new aggregation epoch. | 532 // Reset to start measuring a new aggregation epoch. |
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
587 if (mode_ == PROBE_RTT) { | 569 if (mode_ == PROBE_RTT) { |
588 return; | 570 return; |
589 } | 571 } |
590 | 572 |
591 QuicByteCount target_window = | 573 QuicByteCount target_window = |
592 GetTargetCongestionWindow(congestion_window_gain_); | 574 GetTargetCongestionWindow(congestion_window_gain_); |
593 | 575 |
594 if (rtt_variance_weight_ > 0.f && !BandwidthEstimate().IsZero()) { | 576 if (rtt_variance_weight_ > 0.f && !BandwidthEstimate().IsZero()) { |
595 target_window += rtt_variance_weight_ * rtt_stats_->mean_deviation() * | 577 target_window += rtt_variance_weight_ * rtt_stats_->mean_deviation() * |
596 BandwidthEstimate(); | 578 BandwidthEstimate(); |
597 } else if (FLAGS_quic_reloadable_flag_quic_bbr_ack_spacing2 && | |
598 is_at_full_bandwidth_) { | |
599 QUIC_FLAG_COUNT_N(quic_reloadable_flag_quic_bbr_ack_spacing2, 2, 2); | |
600 // Add CWND for inter-ack spacing once STARTUP has been exited. | |
601 target_window += max_ack_spacing_.GetBest() * BandwidthEstimate(); | |
602 } else if (FLAGS_quic_reloadable_flag_quic_bbr_ack_aggregation_bytes && | 579 } else if (FLAGS_quic_reloadable_flag_quic_bbr_ack_aggregation_bytes && |
603 is_at_full_bandwidth_) { | 580 is_at_full_bandwidth_) { |
604 QUIC_FLAG_COUNT_N(quic_reloadable_flag_quic_bbr_ack_aggregation_bytes, 2, | 581 QUIC_FLAG_COUNT_N(quic_reloadable_flag_quic_bbr_ack_aggregation_bytes, 2, |
605 2); | 582 2); |
606 target_window += max_ack_height_.GetBest(); | 583 target_window += max_ack_height_.GetBest(); |
607 } | 584 } |
608 if (FLAGS_quic_reloadable_flag_quic_bbr_add_tso_cwnd) { | 585 if (FLAGS_quic_reloadable_flag_quic_bbr_add_tso_cwnd) { |
609 // QUIC doesn't have TSO, but it does have similarly quantized pacing, so | 586 // QUIC doesn't have TSO, but it does have similarly quantized pacing, so |
610 // allow extra CWND to make QUIC's BBR CWND identical to TCP's. | 587 // allow extra CWND to make QUIC's BBR CWND identical to TCP's. |
611 QuicByteCount tso_segs_goal = 0; | 588 QuicByteCount tso_segs_goal = 0; |
(...skipping 100 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
712 os << "Minimum RTT timestamp: " << state.min_rtt_timestamp.ToDebuggingValue() | 689 os << "Minimum RTT timestamp: " << state.min_rtt_timestamp.ToDebuggingValue() |
713 << std::endl; | 690 << std::endl; |
714 | 691 |
715 os << "Last sample is app-limited: " | 692 os << "Last sample is app-limited: " |
716 << (state.last_sample_is_app_limited ? "yes" : "no"); | 693 << (state.last_sample_is_app_limited ? "yes" : "no"); |
717 | 694 |
718 return os; | 695 return os; |
719 } | 696 } |
720 | 697 |
721 } // namespace net | 698 } // namespace net |
OLD | NEW |