Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(142)

Side by Side Diff: net/quic/core/congestion_control/bbr_sender.cc

Issue 2487613002: Landing Recent QUIC changes until 12:43 PM, Nov 5, 2016 UTC+8 (Closed)
Patch Set: Created 4 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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 39 matching lines...) Expand 10 before | Expand all | Expand 10 after
50 : mode(sender.mode_), 50 : mode(sender.mode_),
51 max_bandwidth(sender.max_bandwidth_.GetBest()), 51 max_bandwidth(sender.max_bandwidth_.GetBest()),
52 round_trip_count(sender.round_trip_count_), 52 round_trip_count(sender.round_trip_count_),
53 gain_cycle_index(sender.cycle_current_offset_), 53 gain_cycle_index(sender.cycle_current_offset_),
54 congestion_window(sender.congestion_window_), 54 congestion_window(sender.congestion_window_),
55 is_at_full_bandwidth(sender.is_at_full_bandwidth_), 55 is_at_full_bandwidth(sender.is_at_full_bandwidth_),
56 bandwidth_at_last_round(sender.bandwidth_at_last_round_), 56 bandwidth_at_last_round(sender.bandwidth_at_last_round_),
57 rounds_without_bandwidth_gain(sender.rounds_without_bandwidth_gain_), 57 rounds_without_bandwidth_gain(sender.rounds_without_bandwidth_gain_),
58 min_rtt(sender.min_rtt_), 58 min_rtt(sender.min_rtt_),
59 min_rtt_timestamp(sender.min_rtt_timestamp_), 59 min_rtt_timestamp(sender.min_rtt_timestamp_),
60 recovery_state(sender.recovery_state_),
61 recovery_window(sender.recovery_window_),
60 last_sample_is_app_limited(sender.last_sample_is_app_limited_) {} 62 last_sample_is_app_limited(sender.last_sample_is_app_limited_) {}
61 63
62 BbrSender::DebugState::DebugState(const DebugState& state) = default; 64 BbrSender::DebugState::DebugState(const DebugState& state) = default;
63 65
64 BbrSender::BbrSender(const QuicClock* clock, 66 BbrSender::BbrSender(const QuicClock* clock,
65 const RttStats* rtt_stats, 67 const RttStats* rtt_stats,
66 const QuicUnackedPacketMap* unacked_packets, 68 const QuicUnackedPacketMap* unacked_packets,
67 QuicPacketCount initial_tcp_congestion_window, 69 QuicPacketCount initial_tcp_congestion_window,
68 QuicPacketCount max_tcp_congestion_window, 70 QuicPacketCount max_tcp_congestion_window,
69 QuicRandom* random) 71 QuicRandom* random)
(...skipping 17 matching lines...) Expand all
87 pacing_gain_(1), 89 pacing_gain_(1),
88 congestion_window_gain_(1), 90 congestion_window_gain_(1),
89 cycle_current_offset_(0), 91 cycle_current_offset_(0),
90 last_cycle_start_(QuicTime::Zero()), 92 last_cycle_start_(QuicTime::Zero()),
91 is_at_full_bandwidth_(false), 93 is_at_full_bandwidth_(false),
92 rounds_without_bandwidth_gain_(0), 94 rounds_without_bandwidth_gain_(0),
93 bandwidth_at_last_round_(QuicBandwidth::Zero()), 95 bandwidth_at_last_round_(QuicBandwidth::Zero()),
94 exiting_quiescence_(false), 96 exiting_quiescence_(false),
95 exit_probe_rtt_at_(QuicTime::Zero()), 97 exit_probe_rtt_at_(QuicTime::Zero()),
96 probe_rtt_round_passed_(false), 98 probe_rtt_round_passed_(false),
97 last_sample_is_app_limited_(false) { 99 last_sample_is_app_limited_(false),
100 recovery_state_(NOT_IN_RECOVERY),
101 end_recovery_at_(0) {
98 EnterStartupMode(); 102 EnterStartupMode();
99 } 103 }
100 104
101 BbrSender::~BbrSender() {} 105 BbrSender::~BbrSender() {}
102 106
103 bool BbrSender::InSlowStart() const { 107 bool BbrSender::InSlowStart() const {
104 return mode_ == STARTUP; 108 return mode_ == STARTUP;
105 } 109 }
106 110
107 bool BbrSender::OnPacketSent(QuicTime sent_time, 111 bool BbrSender::OnPacketSent(QuicTime sent_time,
(...skipping 30 matching lines...) Expand all
138 142
139 QuicBandwidth BbrSender::BandwidthEstimate() const { 143 QuicBandwidth BbrSender::BandwidthEstimate() const {
140 return max_bandwidth_.GetBest(); 144 return max_bandwidth_.GetBest();
141 } 145 }
142 146
143 QuicByteCount BbrSender::GetCongestionWindow() const { 147 QuicByteCount BbrSender::GetCongestionWindow() const {
144 if (mode_ == PROBE_RTT) { 148 if (mode_ == PROBE_RTT) {
145 return kMinimumCongestionWindow; 149 return kMinimumCongestionWindow;
146 } 150 }
147 151
152 if (InRecovery()) {
153 return std::min(congestion_window_, recovery_window_);
154 }
155
148 return congestion_window_; 156 return congestion_window_;
149 } 157 }
150 158
151 QuicByteCount BbrSender::GetSlowStartThreshold() const { 159 QuicByteCount BbrSender::GetSlowStartThreshold() const {
152 return 0; 160 return 0;
153 } 161 }
154 162
155 bool BbrSender::InRecovery() const { 163 bool BbrSender::InRecovery() const {
156 return false; 164 return recovery_state_ != NOT_IN_RECOVERY;
157 } 165 }
158 166
159 void BbrSender::OnCongestionEvent(bool /*rtt_updated*/, 167 void BbrSender::OnCongestionEvent(bool /*rtt_updated*/,
160 QuicByteCount prior_in_flight, 168 QuicByteCount prior_in_flight,
161 QuicTime event_time, 169 QuicTime event_time,
162 const CongestionVector& acked_packets, 170 const CongestionVector& acked_packets,
163 const CongestionVector& lost_packets) { 171 const CongestionVector& lost_packets) {
164 const QuicByteCount total_bytes_acked_before = sampler_.total_bytes_acked(); 172 const QuicByteCount total_bytes_acked_before = sampler_.total_bytes_acked();
165 173
166 bool is_round_start = false; 174 bool is_round_start = false;
167 bool min_rtt_expired = false; 175 bool min_rtt_expired = false;
168 176
169 DiscardLostPackets(lost_packets); 177 DiscardLostPackets(lost_packets);
170 178
171 // Input the new data into the BBR model of the connection. 179 // Input the new data into the BBR model of the connection.
172 if (!acked_packets.empty()) { 180 if (!acked_packets.empty()) {
173 QuicPacketNumber last_acked_packet = acked_packets.rbegin()->first; 181 QuicPacketNumber last_acked_packet = acked_packets.rbegin()->first;
174 is_round_start = UpdateRoundTripCounter(last_acked_packet); 182 is_round_start = UpdateRoundTripCounter(last_acked_packet);
175 min_rtt_expired = UpdateBandwidthAndMinRtt(event_time, acked_packets); 183 min_rtt_expired = UpdateBandwidthAndMinRtt(event_time, acked_packets);
184 UpdateRecoveryState(last_acked_packet, !lost_packets.empty(),
185 is_round_start);
176 } 186 }
177 187
178 // Handle logic specific to PROBE_BW mode. 188 // Handle logic specific to PROBE_BW mode.
179 if (mode_ == PROBE_BW) { 189 if (mode_ == PROBE_BW) {
180 UpdateGainCyclePhase(event_time, prior_in_flight, !lost_packets.empty()); 190 UpdateGainCyclePhase(event_time, prior_in_flight, !lost_packets.empty());
181 } 191 }
182 192
183 // Handle logic specific to STARTUP and DRAIN modes. 193 // Handle logic specific to STARTUP and DRAIN modes.
184 if (is_round_start && !is_at_full_bandwidth_) { 194 if (is_round_start && !is_at_full_bandwidth_) {
185 CheckIfFullBandwidthReached(); 195 CheckIfFullBandwidthReached();
186 } 196 }
187 MaybeExitStartupOrDrain(event_time); 197 MaybeExitStartupOrDrain(event_time);
188 198
189 // Handle logic specific to PROBE_RTT. 199 // Handle logic specific to PROBE_RTT.
190 MaybeEnterOrExitProbeRtt(event_time, is_round_start, min_rtt_expired); 200 MaybeEnterOrExitProbeRtt(event_time, is_round_start, min_rtt_expired);
191 201
192 // After the model is updated, recalculate the pacing rate and congestion 202 // After the model is updated, recalculate the pacing rate and congestion
193 // window. 203 // window.
194 QuicByteCount bytes_acked = 204 QuicByteCount bytes_acked =
195 sampler_.total_bytes_acked() - total_bytes_acked_before; 205 sampler_.total_bytes_acked() - total_bytes_acked_before;
196 CalculatePacingRate(); 206 CalculatePacingRate();
197 CalculateCongestionWindow(bytes_acked); 207 CalculateCongestionWindow(bytes_acked);
208 CalculateRecoveryWindow(bytes_acked);
198 209
199 // Cleanup internal state. 210 // Cleanup internal state.
200 sampler_.RemoveObsoletePackets(unacked_packets_->GetLeastUnacked()); 211 sampler_.RemoveObsoletePackets(unacked_packets_->GetLeastUnacked());
201 } 212 }
202 213
203 CongestionControlType BbrSender::GetCongestionControlType() const { 214 CongestionControlType BbrSender::GetCongestionControlType() const {
204 return kBBR; 215 return kBBR;
205 } 216 }
206 217
207 QuicTime::Delta BbrSender::GetMinRtt() const { 218 QuicTime::Delta BbrSender::GetMinRtt() const {
(...skipping 189 matching lines...) Expand 10 before | Expand all | Expand 10 after
397 } else { 408 } else {
398 EnterProbeBandwidthMode(now); 409 EnterProbeBandwidthMode(now);
399 } 410 }
400 } 411 }
401 } 412 }
402 } 413 }
403 414
404 exiting_quiescence_ = false; 415 exiting_quiescence_ = false;
405 } 416 }
406 417
418 void BbrSender::UpdateRecoveryState(QuicPacketNumber last_acked_packet,
419 bool has_losses,
420 bool is_round_start) {
421 // Exit recovery when there are no losses for a round.
422 if (has_losses) {
423 end_recovery_at_ = last_sent_packet_;
424 }
425
426 switch (recovery_state_) {
427 case NOT_IN_RECOVERY:
428 // Enter conservation on the first loss.
429 if (has_losses) {
430 recovery_state_ = CONSERVATION;
431 // Since the conservation phase is meant to be lasting for a whole
432 // round, extend the current round as if it were started right now.
433 current_round_trip_end_ = last_sent_packet_;
434 }
435 break;
436
437 case CONSERVATION:
438 if (is_round_start) {
439 recovery_state_ = GROWTH;
440 }
441
442 case GROWTH:
443 // Exit recovery if appropriate.
444 if (!has_losses && last_acked_packet > end_recovery_at_) {
445 recovery_state_ = NOT_IN_RECOVERY;
446 }
447 break;
448 }
449 }
450
407 void BbrSender::CalculatePacingRate() { 451 void BbrSender::CalculatePacingRate() {
408 if (BandwidthEstimate().IsZero()) { 452 if (BandwidthEstimate().IsZero()) {
409 return; 453 return;
410 } 454 }
411 455
412 pacing_rate_ = pacing_gain_ * BandwidthEstimate(); 456 pacing_rate_ = pacing_gain_ * BandwidthEstimate();
413 } 457 }
414 458
415 void BbrSender::CalculateCongestionWindow(QuicByteCount bytes_acked) { 459 void BbrSender::CalculateCongestionWindow(QuicByteCount bytes_acked) {
416 if (mode_ == PROBE_RTT) { 460 if (mode_ == PROBE_RTT) {
(...skipping 14 matching lines...) Expand all
431 } else if (congestion_window_ < target_window || 475 } else if (congestion_window_ < target_window ||
432 sampler_.total_bytes_acked() < initial_congestion_window_) { 476 sampler_.total_bytes_acked() < initial_congestion_window_) {
433 congestion_window_ = congestion_window_ + bytes_acked; 477 congestion_window_ = congestion_window_ + bytes_acked;
434 } 478 }
435 479
436 // Enforce the limits on the congestion window. 480 // Enforce the limits on the congestion window.
437 congestion_window_ = std::max(congestion_window_, kMinimumCongestionWindow); 481 congestion_window_ = std::max(congestion_window_, kMinimumCongestionWindow);
438 congestion_window_ = std::min(congestion_window_, max_congestion_window_); 482 congestion_window_ = std::min(congestion_window_, max_congestion_window_);
439 } 483 }
440 484
485 void BbrSender::CalculateRecoveryWindow(QuicByteCount bytes_acked) {
486 switch (recovery_state_) {
487 case CONSERVATION:
488 recovery_window_ = unacked_packets_->bytes_in_flight() + bytes_acked;
489 break;
490 case GROWTH:
491 recovery_window_ = unacked_packets_->bytes_in_flight() + 2 * bytes_acked;
492 break;
493 default:
494 break;
495 }
496 recovery_window_ = std::max(kMinimumCongestionWindow, recovery_window_);
497 }
498
441 std::string BbrSender::GetDebugState() const { 499 std::string BbrSender::GetDebugState() const {
442 std::ostringstream stream; 500 std::ostringstream stream;
443 stream << ExportDebugState(); 501 stream << ExportDebugState();
444 return stream.str(); 502 return stream.str();
445 } 503 }
446 504
447 void BbrSender::OnApplicationLimited(QuicByteCount bytes_in_flight) { 505 void BbrSender::OnApplicationLimited(QuicByteCount bytes_in_flight) {
448 if (bytes_in_flight >= GetCongestionWindow()) { 506 if (bytes_in_flight >= GetCongestionWindow()) {
449 return; 507 return;
450 } 508 }
(...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after
497 os << "Minimum RTT timestamp: " << state.min_rtt_timestamp.ToDebuggingValue() 555 os << "Minimum RTT timestamp: " << state.min_rtt_timestamp.ToDebuggingValue()
498 << std::endl; 556 << std::endl;
499 557
500 os << "Last sample is app-limited: " 558 os << "Last sample is app-limited: "
501 << (state.last_sample_is_app_limited ? "yes" : "no"); 559 << (state.last_sample_is_app_limited ? "yes" : "no");
502 560
503 return os; 561 return os;
504 } 562 }
505 563
506 } // namespace net 564 } // namespace net
OLDNEW
« no previous file with comments | « net/quic/core/congestion_control/bbr_sender.h ('k') | net/quic/core/congestion_control/bbr_sender_test.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698