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

Side by Side Diff: net/quic/congestion_control/tcp_cubic_sender.cc

Issue 706203003: Update from https://crrev.com/303153 (Closed) Base URL: git@github.com:domokit/mojo.git@master
Patch Set: Created 6 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 (c) 2012 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2012 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/congestion_control/tcp_cubic_sender.h" 5 #include "net/quic/congestion_control/tcp_cubic_sender.h"
6 6
7 #include <algorithm> 7 #include <algorithm>
8 8
9 #include "base/metrics/histogram.h" 9 #include "base/metrics/histogram.h"
10 #include "net/quic/congestion_control/prr_sender.h" 10 #include "net/quic/congestion_control/prr_sender.h"
11 #include "net/quic/congestion_control/rtt_stats.h" 11 #include "net/quic/congestion_control/rtt_stats.h"
12 #include "net/quic/crypto/crypto_protocol.h" 12 #include "net/quic/crypto/crypto_protocol.h"
13 13
14 using std::max; 14 using std::max;
15 using std::min; 15 using std::min;
16 16
17 namespace net { 17 namespace net {
18 18
19 namespace { 19 namespace {
20 // Constants based on TCP defaults. 20 // Constants based on TCP defaults.
21 // The minimum cwnd based on RFC 3782 (TCP NewReno) for cwnd reductions on a 21 // The minimum cwnd based on RFC 3782 (TCP NewReno) for cwnd reductions on a
22 // fast retransmission. The cwnd after a timeout is still 1. 22 // fast retransmission. The cwnd after a timeout is still 1.
23 const QuicPacketCount kMinimumCongestionWindow = 2; 23 const QuicPacketCount kMinimumCongestionWindow = 2;
24 const QuicByteCount kMaxSegmentSize = kDefaultTCPMSS; 24 const QuicByteCount kMaxSegmentSize = kDefaultTCPMSS;
25 const int64 kInitialCongestionWindow = 10;
26 const int kMaxBurstLength = 3; 25 const int kMaxBurstLength = 3;
27 const float kRenoBeta = 0.7f; // Reno backoff factor. 26 const float kRenoBeta = 0.7f; // Reno backoff factor.
28 const uint32 kDefaultNumConnections = 2; // N-connection emulation. 27 const uint32 kDefaultNumConnections = 2; // N-connection emulation.
29 } // namespace 28 } // namespace
30 29
31 TcpCubicSender::TcpCubicSender( 30 TcpCubicSender::TcpCubicSender(
32 const QuicClock* clock, 31 const QuicClock* clock,
33 const RttStats* rtt_stats, 32 const RttStats* rtt_stats,
34 bool reno, 33 bool reno,
35 QuicPacketCount max_tcp_congestion_window, 34 QuicPacketCount max_tcp_congestion_window,
36 QuicConnectionStats* stats) 35 QuicConnectionStats* stats)
37 : hybrid_slow_start_(clock), 36 : hybrid_slow_start_(clock),
38 cubic_(clock, stats), 37 cubic_(clock, stats),
39 rtt_stats_(rtt_stats), 38 rtt_stats_(rtt_stats),
40 stats_(stats), 39 stats_(stats),
41 reno_(reno), 40 reno_(reno),
42 num_connections_(kDefaultNumConnections), 41 num_connections_(kDefaultNumConnections),
43 congestion_window_count_(0), 42 congestion_window_count_(0),
44 largest_sent_sequence_number_(0), 43 largest_sent_sequence_number_(0),
45 largest_acked_sequence_number_(0), 44 largest_acked_sequence_number_(0),
46 largest_sent_at_last_cutback_(0), 45 largest_sent_at_last_cutback_(0),
47 congestion_window_(kInitialCongestionWindow), 46 congestion_window_(kDefaultInitialWindow),
48 previous_congestion_window_(0), 47 previous_congestion_window_(0),
49 slowstart_threshold_(max_tcp_congestion_window), 48 slowstart_threshold_(max_tcp_congestion_window),
50 previous_slowstart_threshold_(0), 49 previous_slowstart_threshold_(0),
51 last_cutback_exited_slowstart_(false), 50 last_cutback_exited_slowstart_(false),
52 max_tcp_congestion_window_(max_tcp_congestion_window) { 51 max_tcp_congestion_window_(max_tcp_congestion_window) {
53 } 52 }
54 53
55 TcpCubicSender::~TcpCubicSender() { 54 TcpCubicSender::~TcpCubicSender() {
56 UMA_HISTOGRAM_COUNTS("Net.QuicSession.FinalTcpCwnd", congestion_window_); 55 UMA_HISTOGRAM_COUNTS("Net.QuicSession.FinalTcpCwnd", congestion_window_);
57 } 56 }
58 57
59 void TcpCubicSender::SetFromConfig(const QuicConfig& config, bool is_server) { 58 void TcpCubicSender::SetFromConfig(const QuicConfig& config, bool is_server) {
60 if (is_server) { 59 if (is_server) {
61 if (config.HasReceivedConnectionOptions() && 60 if (config.HasReceivedConnectionOptions() &&
62 ContainsQuicTag(config.ReceivedConnectionOptions(), kIW10)) { 61 ContainsQuicTag(config.ReceivedConnectionOptions(), kIW10)) {
63 // Initial window experiment. Ignore the initial congestion 62 // Initial window experiment. Ignore the initial congestion
64 // window suggested by the client and use the default ICWND of 63 // window suggested by the client and use the default ICWND of
65 // 10 instead. 64 // 10 instead.
66 congestion_window_ = kInitialCongestionWindow; 65 congestion_window_ = kDefaultInitialWindow;
67 } else if (config.HasReceivedInitialCongestionWindow()) { 66 } else if (config.HasReceivedInitialCongestionWindow()) {
68 // Set the initial window size. 67 // Set the initial window size.
69 congestion_window_ = min(kMaxInitialWindow, 68 congestion_window_ = max(kMinimumCongestionWindow,
70 config.ReceivedInitialCongestionWindow()); 69 min(kMaxInitialWindow,
70 static_cast<QuicPacketCount>(
71 config.ReceivedInitialCongestionWindow())));
71 } 72 }
72 } 73 }
73 } 74 }
74 75
75 void TcpCubicSender::SetNumEmulatedConnections(int num_connections) { 76 void TcpCubicSender::SetNumEmulatedConnections(int num_connections) {
76 num_connections_ = max(1, num_connections); 77 num_connections_ = max(1, num_connections);
77 cubic_.SetNumConnections(num_connections_); 78 cubic_.SetNumConnections(num_connections_);
78 } 79 }
79 80
80 float TcpCubicSender::RenoBeta() const { 81 float TcpCubicSender::RenoBeta() const {
81 // kNConnectionBeta is the backoff factor after loss for our N-connection 82 // kNConnectionBeta is the backoff factor after loss for our N-connection
82 // emulation, which emulates the effective backoff of an ensemble of N 83 // emulation, which emulates the effective backoff of an ensemble of N
83 // TCP-Reno connections on a single loss event. The effective multiplier is 84 // TCP-Reno connections on a single loss event. The effective multiplier is
84 // computed as: 85 // computed as:
85 return (num_connections_ - 1 + kRenoBeta) / num_connections_; 86 return (num_connections_ - 1 + kRenoBeta) / num_connections_;
86 } 87 }
87 88
88 void TcpCubicSender::OnCongestionEvent( 89 void TcpCubicSender::OnCongestionEvent(
89 bool rtt_updated, 90 bool rtt_updated,
90 QuicByteCount bytes_in_flight, 91 QuicByteCount bytes_in_flight,
91 const CongestionVector& acked_packets, 92 const CongestionVector& acked_packets,
92 const CongestionVector& lost_packets) { 93 const CongestionVector& lost_packets) {
93 if (rtt_updated && InSlowStart() && 94 if (rtt_updated && InSlowStart() &&
94 hybrid_slow_start_.ShouldExitSlowStart(rtt_stats_->latest_rtt(), 95 hybrid_slow_start_.ShouldExitSlowStart(rtt_stats_->latest_rtt(),
95 rtt_stats_->MinRtt(), 96 rtt_stats_->min_rtt(),
96 congestion_window_)) { 97 congestion_window_)) {
97 slowstart_threshold_ = congestion_window_; 98 slowstart_threshold_ = congestion_window_;
98 } 99 }
99 for (CongestionVector::const_iterator it = lost_packets.begin(); 100 for (CongestionVector::const_iterator it = lost_packets.begin();
100 it != lost_packets.end(); ++it) { 101 it != lost_packets.end(); ++it) {
101 OnPacketLost(it->first, bytes_in_flight); 102 OnPacketLost(it->first, bytes_in_flight);
102 } 103 }
103 for (CongestionVector::const_iterator it = acked_packets.begin(); 104 for (CongestionVector::const_iterator it = acked_packets.begin();
104 it != acked_packets.end(); ++it) { 105 it != acked_packets.end(); ++it) {
105 OnPacketAcked(it->first, it->second.bytes_sent, bytes_in_flight); 106 OnPacketAcked(it->first, it->second.bytes_sent, bytes_in_flight);
(...skipping 90 matching lines...) Expand 10 before | Expand all | Expand 10 after
196 if (GetCongestionWindow() > bytes_in_flight) { 197 if (GetCongestionWindow() > bytes_in_flight) {
197 return QuicTime::Delta::Zero(); 198 return QuicTime::Delta::Zero();
198 } 199 }
199 return QuicTime::Delta::Infinite(); 200 return QuicTime::Delta::Infinite();
200 } 201 }
201 202
202 QuicBandwidth TcpCubicSender::PacingRate() const { 203 QuicBandwidth TcpCubicSender::PacingRate() const {
203 // We pace at twice the rate of the underlying sender's bandwidth estimate 204 // We pace at twice the rate of the underlying sender's bandwidth estimate
204 // during slow start and 1.25x during congestion avoidance to ensure pacing 205 // during slow start and 1.25x during congestion avoidance to ensure pacing
205 // doesn't prevent us from filling the window. 206 // doesn't prevent us from filling the window.
206 return BandwidthEstimate().Scale(InSlowStart() ? 2 : 1.25); 207 QuicTime::Delta srtt = rtt_stats_->smoothed_rtt();
208 if (srtt.IsZero()) {
209 srtt = QuicTime::Delta::FromMicroseconds(rtt_stats_->initial_rtt_us());
210 }
211 const QuicBandwidth bandwidth =
212 QuicBandwidth::FromBytesAndTimeDelta(GetCongestionWindow(), srtt);
213 return bandwidth.Scale(InSlowStart() ? 2 : 1.25);
207 } 214 }
208 215
209 QuicBandwidth TcpCubicSender::BandwidthEstimate() const { 216 QuicBandwidth TcpCubicSender::BandwidthEstimate() const {
210 if (rtt_stats_->SmoothedRtt().IsZero()) { 217 QuicTime::Delta srtt = rtt_stats_->smoothed_rtt();
211 LOG(DFATAL) << "In BandwidthEstimate(), smoothed RTT is zero!"; 218 if (srtt.IsZero()) {
219 // If we haven't measured an rtt, the bandwidth estimate is unknown.
212 return QuicBandwidth::Zero(); 220 return QuicBandwidth::Zero();
213 } 221 }
214 return QuicBandwidth::FromBytesAndTimeDelta(GetCongestionWindow(), 222 return QuicBandwidth::FromBytesAndTimeDelta(GetCongestionWindow(), srtt);
215 rtt_stats_->SmoothedRtt());
216 } 223 }
217 224
218 bool TcpCubicSender::HasReliableBandwidthEstimate() const { 225 bool TcpCubicSender::HasReliableBandwidthEstimate() const {
219 return !InSlowStart() && !InRecovery(); 226 return !InSlowStart() && !InRecovery() &&
227 !rtt_stats_->smoothed_rtt().IsZero();;
220 } 228 }
221 229
222 QuicTime::Delta TcpCubicSender::RetransmissionDelay() const { 230 QuicTime::Delta TcpCubicSender::RetransmissionDelay() const {
223 if (!rtt_stats_->HasUpdates()) { 231 if (rtt_stats_->smoothed_rtt().IsZero()) {
224 return QuicTime::Delta::Zero(); 232 return QuicTime::Delta::Zero();
225 } 233 }
226 return rtt_stats_->SmoothedRtt().Add( 234 return rtt_stats_->smoothed_rtt().Add(
227 rtt_stats_->mean_deviation().Multiply(4)); 235 rtt_stats_->mean_deviation().Multiply(4));
228 } 236 }
229 237
230 QuicByteCount TcpCubicSender::GetCongestionWindow() const { 238 QuicByteCount TcpCubicSender::GetCongestionWindow() const {
231 return congestion_window_ * kMaxSegmentSize; 239 return congestion_window_ * kMaxSegmentSize;
232 } 240 }
233 241
234 bool TcpCubicSender::InSlowStart() const { 242 bool TcpCubicSender::InSlowStart() const {
235 return congestion_window_ < slowstart_threshold_; 243 return congestion_window_ < slowstart_threshold_;
236 } 244 }
(...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after
292 ++congestion_window_; 300 ++congestion_window_;
293 congestion_window_count_ = 0; 301 congestion_window_count_ = 0;
294 } 302 }
295 303
296 DVLOG(1) << "Reno; congestion window: " << congestion_window_ 304 DVLOG(1) << "Reno; congestion window: " << congestion_window_
297 << " slowstart threshold: " << slowstart_threshold_ 305 << " slowstart threshold: " << slowstart_threshold_
298 << " congestion window count: " << congestion_window_count_; 306 << " congestion window count: " << congestion_window_count_;
299 } else { 307 } else {
300 congestion_window_ = min(max_tcp_congestion_window_, 308 congestion_window_ = min(max_tcp_congestion_window_,
301 cubic_.CongestionWindowAfterAck( 309 cubic_.CongestionWindowAfterAck(
302 congestion_window_, rtt_stats_->MinRtt())); 310 congestion_window_, rtt_stats_->min_rtt()));
303 DVLOG(1) << "Cubic; congestion window: " << congestion_window_ 311 DVLOG(1) << "Cubic; congestion window: " << congestion_window_
304 << " slowstart threshold: " << slowstart_threshold_; 312 << " slowstart threshold: " << slowstart_threshold_;
305 } 313 }
306 } 314 }
307 315
308 void TcpCubicSender::OnRetransmissionTimeout(bool packets_retransmitted) { 316 void TcpCubicSender::OnRetransmissionTimeout(bool packets_retransmitted) {
309 largest_sent_at_last_cutback_ = 0; 317 largest_sent_at_last_cutback_ = 0;
310 if (!packets_retransmitted) { 318 if (!packets_retransmitted) {
311 return; 319 return;
312 } 320 }
(...skipping 13 matching lines...) Expand all
326 congestion_window_ = previous_congestion_window_; 334 congestion_window_ = previous_congestion_window_;
327 slowstart_threshold_ = previous_slowstart_threshold_; 335 slowstart_threshold_ = previous_slowstart_threshold_;
328 previous_congestion_window_ = 0; 336 previous_congestion_window_ = 0;
329 } 337 }
330 338
331 CongestionControlType TcpCubicSender::GetCongestionControlType() const { 339 CongestionControlType TcpCubicSender::GetCongestionControlType() const {
332 return reno_ ? kReno : kCubic; 340 return reno_ ? kReno : kCubic;
333 } 341 }
334 342
335 } // namespace net 343 } // namespace net
OLDNEW
« no previous file with comments | « net/quic/congestion_control/rtt_stats_test.cc ('k') | net/quic/congestion_control/tcp_cubic_sender_test.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698