OLD | NEW |
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_macros.h" | 9 #include "base/metrics/histogram_macros.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 #include "net/quic/proto/cached_network_parameters.pb.h" | 13 #include "net/quic/proto/cached_network_parameters.pb.h" |
14 #include "net/quic/quic_flags.h" | 14 #include "net/quic/quic_flags.h" |
15 | 15 |
16 using std::max; | 16 using std::max; |
17 using std::min; | 17 using std::min; |
18 | 18 |
19 namespace net { | 19 namespace net { |
20 | 20 |
21 namespace { | 21 namespace { |
22 // Constants based on TCP defaults. | 22 // Constants based on TCP defaults. |
23 // The minimum cwnd based on RFC 3782 (TCP NewReno) for cwnd reductions on a | 23 // The minimum cwnd based on RFC 3782 (TCP NewReno) for cwnd reductions on a |
24 // fast retransmission. The cwnd after a timeout is still 1. | 24 // fast retransmission. The cwnd after a timeout is still 1. |
25 const QuicPacketCount kDefaultMinimumCongestionWindow = 2; | 25 const QuicPacketCount kDefaultMinimumCongestionWindow = 2; |
26 const QuicByteCount kMaxSegmentSize = kDefaultTCPMSS; | 26 const QuicByteCount kMaxBurstBytes = 3 * kDefaultTCPMSS; |
27 const QuicByteCount kMaxBurstBytes = 3 * kMaxSegmentSize; | |
28 const float kRenoBeta = 0.7f; // Reno backoff factor. | 27 const float kRenoBeta = 0.7f; // Reno backoff factor. |
29 const uint32 kDefaultNumConnections = 2; // N-connection emulation. | 28 const uint32 kDefaultNumConnections = 2; // N-connection emulation. |
30 } // namespace | 29 } // namespace |
31 | 30 |
32 TcpCubicSender::TcpCubicSender(const QuicClock* clock, | 31 TcpCubicSender::TcpCubicSender(const QuicClock* clock, |
33 const RttStats* rtt_stats, | 32 const RttStats* rtt_stats, |
34 bool reno, | 33 bool reno, |
35 QuicPacketCount initial_tcp_congestion_window, | 34 QuicPacketCount initial_tcp_congestion_window, |
36 QuicPacketCount max_tcp_congestion_window, | 35 QuicPacketCount max_tcp_congestion_window, |
37 QuicConnectionStats* stats) | 36 QuicConnectionStats* stats) |
(...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
98 bool max_bandwidth_resumption) { | 97 bool max_bandwidth_resumption) { |
99 QuicBandwidth bandwidth = QuicBandwidth::FromBytesPerSecond( | 98 QuicBandwidth bandwidth = QuicBandwidth::FromBytesPerSecond( |
100 max_bandwidth_resumption | 99 max_bandwidth_resumption |
101 ? cached_network_params.max_bandwidth_estimate_bytes_per_second() | 100 ? cached_network_params.max_bandwidth_estimate_bytes_per_second() |
102 : cached_network_params.bandwidth_estimate_bytes_per_second()); | 101 : cached_network_params.bandwidth_estimate_bytes_per_second()); |
103 QuicTime::Delta rtt_ms = | 102 QuicTime::Delta rtt_ms = |
104 QuicTime::Delta::FromMilliseconds(cached_network_params.min_rtt_ms()); | 103 QuicTime::Delta::FromMilliseconds(cached_network_params.min_rtt_ms()); |
105 | 104 |
106 // Make sure CWND is in appropriate range (in case of bad data). | 105 // Make sure CWND is in appropriate range (in case of bad data). |
107 QuicPacketCount new_congestion_window = | 106 QuicPacketCount new_congestion_window = |
108 bandwidth.ToBytesPerPeriod(rtt_ms) / kMaxPacketSize; | 107 bandwidth.ToBytesPerPeriod(rtt_ms) / kDefaultTCPMSS; |
109 congestion_window_ = max(min(new_congestion_window, kMaxCongestionWindow), | 108 congestion_window_ = max(min(new_congestion_window, kMaxCongestionWindow), |
110 kMinCongestionWindowForBandwidthResumption); | 109 kMinCongestionWindowForBandwidthResumption); |
111 } | 110 } |
112 | 111 |
113 void TcpCubicSender::SetNumEmulatedConnections(int num_connections) { | 112 void TcpCubicSender::SetNumEmulatedConnections(int num_connections) { |
114 num_connections_ = max(1, num_connections); | 113 num_connections_ = max(1, num_connections); |
115 cubic_.SetNumConnections(num_connections_); | 114 cubic_.SetNumConnections(num_connections_); |
116 } | 115 } |
117 | 116 |
118 void TcpCubicSender::SetMaxCongestionWindow( | 117 void TcpCubicSender::SetMaxCongestionWindow( |
119 QuicByteCount max_congestion_window) { | 118 QuicByteCount max_congestion_window) { |
120 max_tcp_congestion_window_ = max_congestion_window / kMaxPacketSize; | 119 max_tcp_congestion_window_ = max_congestion_window / kDefaultTCPMSS; |
121 } | 120 } |
122 | 121 |
123 float TcpCubicSender::RenoBeta() const { | 122 float TcpCubicSender::RenoBeta() const { |
124 // kNConnectionBeta is the backoff factor after loss for our N-connection | 123 // kNConnectionBeta is the backoff factor after loss for our N-connection |
125 // emulation, which emulates the effective backoff of an ensemble of N | 124 // emulation, which emulates the effective backoff of an ensemble of N |
126 // TCP-Reno connections on a single loss event. The effective multiplier is | 125 // TCP-Reno connections on a single loss event. The effective multiplier is |
127 // computed as: | 126 // computed as: |
128 return (num_connections_ - 1 + kRenoBeta) / num_connections_; | 127 return (num_connections_ - 1 + kRenoBeta) / num_connections_; |
129 } | 128 } |
130 | 129 |
(...skipping 99 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
230 QuicTime /* now */, | 229 QuicTime /* now */, |
231 QuicByteCount bytes_in_flight, | 230 QuicByteCount bytes_in_flight, |
232 HasRetransmittableData has_retransmittable_data) const { | 231 HasRetransmittableData has_retransmittable_data) const { |
233 if (has_retransmittable_data == NO_RETRANSMITTABLE_DATA) { | 232 if (has_retransmittable_data == NO_RETRANSMITTABLE_DATA) { |
234 // For TCP we can always send an ACK immediately. | 233 // For TCP we can always send an ACK immediately. |
235 return QuicTime::Delta::Zero(); | 234 return QuicTime::Delta::Zero(); |
236 } | 235 } |
237 if (InRecovery()) { | 236 if (InRecovery()) { |
238 // PRR is used when in recovery. | 237 // PRR is used when in recovery. |
239 return prr_.TimeUntilSend(GetCongestionWindow(), bytes_in_flight, | 238 return prr_.TimeUntilSend(GetCongestionWindow(), bytes_in_flight, |
240 slowstart_threshold_ * kMaxSegmentSize); | 239 slowstart_threshold_ * kDefaultTCPMSS); |
241 } | 240 } |
242 if (GetCongestionWindow() > bytes_in_flight) { | 241 if (GetCongestionWindow() > bytes_in_flight) { |
243 return QuicTime::Delta::Zero(); | 242 return QuicTime::Delta::Zero(); |
244 } | 243 } |
245 if (min4_mode_ && bytes_in_flight < 4 * kMaxSegmentSize) { | 244 if (min4_mode_ && bytes_in_flight < 4 * kDefaultTCPMSS) { |
246 return QuicTime::Delta::Zero(); | 245 return QuicTime::Delta::Zero(); |
247 } | 246 } |
248 return QuicTime::Delta::Infinite(); | 247 return QuicTime::Delta::Infinite(); |
249 } | 248 } |
250 | 249 |
251 QuicBandwidth TcpCubicSender::PacingRate() const { | 250 QuicBandwidth TcpCubicSender::PacingRate() const { |
252 // We pace at twice the rate of the underlying sender's bandwidth estimate | 251 // We pace at twice the rate of the underlying sender's bandwidth estimate |
253 // during slow start and 1.25x during congestion avoidance to ensure pacing | 252 // during slow start and 1.25x during congestion avoidance to ensure pacing |
254 // doesn't prevent us from filling the window. | 253 // doesn't prevent us from filling the window. |
255 QuicTime::Delta srtt = rtt_stats_->smoothed_rtt(); | 254 QuicTime::Delta srtt = rtt_stats_->smoothed_rtt(); |
(...skipping 16 matching lines...) Expand all Loading... |
272 | 271 |
273 QuicTime::Delta TcpCubicSender::RetransmissionDelay() const { | 272 QuicTime::Delta TcpCubicSender::RetransmissionDelay() const { |
274 if (rtt_stats_->smoothed_rtt().IsZero()) { | 273 if (rtt_stats_->smoothed_rtt().IsZero()) { |
275 return QuicTime::Delta::Zero(); | 274 return QuicTime::Delta::Zero(); |
276 } | 275 } |
277 return rtt_stats_->smoothed_rtt().Add( | 276 return rtt_stats_->smoothed_rtt().Add( |
278 rtt_stats_->mean_deviation().Multiply(4)); | 277 rtt_stats_->mean_deviation().Multiply(4)); |
279 } | 278 } |
280 | 279 |
281 QuicByteCount TcpCubicSender::GetCongestionWindow() const { | 280 QuicByteCount TcpCubicSender::GetCongestionWindow() const { |
282 return congestion_window_ * kMaxSegmentSize; | 281 return congestion_window_ * kDefaultTCPMSS; |
283 } | 282 } |
284 | 283 |
285 bool TcpCubicSender::InSlowStart() const { | 284 bool TcpCubicSender::InSlowStart() const { |
286 return congestion_window_ < slowstart_threshold_; | 285 return congestion_window_ < slowstart_threshold_; |
287 } | 286 } |
288 | 287 |
289 QuicByteCount TcpCubicSender::GetSlowStartThreshold() const { | 288 QuicByteCount TcpCubicSender::GetSlowStartThreshold() const { |
290 return slowstart_threshold_ * kMaxSegmentSize; | 289 return slowstart_threshold_ * kDefaultTCPMSS; |
291 } | 290 } |
292 | 291 |
293 bool TcpCubicSender::IsCwndLimited(QuicByteCount bytes_in_flight) const { | 292 bool TcpCubicSender::IsCwndLimited(QuicByteCount bytes_in_flight) const { |
294 const QuicByteCount congestion_window_bytes = GetCongestionWindow(); | 293 const QuicByteCount congestion_window_bytes = GetCongestionWindow(); |
295 if (bytes_in_flight >= congestion_window_bytes) { | 294 if (bytes_in_flight >= congestion_window_bytes) { |
296 return true; | 295 return true; |
297 } | 296 } |
298 const QuicByteCount available_bytes = | 297 const QuicByteCount available_bytes = |
299 congestion_window_bytes - bytes_in_flight; | 298 congestion_window_bytes - bytes_in_flight; |
300 const bool slow_start_limited = InSlowStart() && | 299 const bool slow_start_limited = InSlowStart() && |
(...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
363 hybrid_slow_start_.Restart(); | 362 hybrid_slow_start_.Restart(); |
364 slowstart_threshold_ = congestion_window_ / 2; | 363 slowstart_threshold_ = congestion_window_ / 2; |
365 congestion_window_ = min_congestion_window_; | 364 congestion_window_ = min_congestion_window_; |
366 } | 365 } |
367 | 366 |
368 CongestionControlType TcpCubicSender::GetCongestionControlType() const { | 367 CongestionControlType TcpCubicSender::GetCongestionControlType() const { |
369 return reno_ ? kReno : kCubic; | 368 return reno_ ? kReno : kCubic; |
370 } | 369 } |
371 | 370 |
372 } // namespace net | 371 } // namespace net |
OLD | NEW |