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

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

Issue 2193073003: Move shared files in net/quic/ into net/quic/core/ (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: io_thread_unittest.cc Created 4 years, 4 months 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
(Empty)
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
3 // found in the LICENSE file.
4
5 #include "net/quic/congestion_control/tcp_cubic_sender_packets.h"
6
7 #include <algorithm>
8
9 #include "base/metrics/histogram_macros.h"
10 #include "net/quic/congestion_control/prr_sender.h"
11 #include "net/quic/congestion_control/rtt_stats.h"
12 #include "net/quic/crypto/crypto_protocol.h"
13 #include "net/quic/proto/cached_network_parameters.pb.h"
14 #include "net/quic/quic_bug_tracker.h"
15 #include "net/quic/quic_flags.h"
16
17 using std::max;
18 using std::min;
19
20 namespace net {
21
22 namespace {
23 // Constants based on TCP defaults.
24 // The minimum cwnd based on RFC 3782 (TCP NewReno) for cwnd reductions on a
25 // fast retransmission. The cwnd after a timeout is still 1.
26 const QuicByteCount kMaxBurstBytes = 3 * kDefaultTCPMSS;
27 const float kRenoBeta = 0.7f; // Reno backoff factor.
28 const uint32_t kDefaultNumConnections = 2; // N-connection emulation.
29 const float kRateBasedExtraCwnd = 1.5f; // CWND for rate based sending.
30 } // namespace
31
32 TcpCubicSenderBase::TcpCubicSenderBase(const QuicClock* clock,
33 const RttStats* rtt_stats,
34 bool reno,
35 QuicConnectionStats* stats)
36 : rtt_stats_(rtt_stats),
37 stats_(stats),
38 reno_(reno),
39 num_connections_(kDefaultNumConnections),
40 largest_sent_packet_number_(0),
41 largest_acked_packet_number_(0),
42 largest_sent_at_last_cutback_(0),
43 min4_mode_(false),
44 last_cutback_exited_slowstart_(false),
45 slow_start_large_reduction_(false),
46 rate_based_sending_(false),
47 no_prr_(false) {}
48
49 TcpCubicSenderBase::~TcpCubicSenderBase() {}
50
51 void TcpCubicSenderBase::SetFromConfig(const QuicConfig& config,
52 Perspective perspective) {
53 if (perspective == Perspective::IS_SERVER) {
54 if (config.HasReceivedConnectionOptions() &&
55 ContainsQuicTag(config.ReceivedConnectionOptions(), kIW03)) {
56 // Initial window experiment.
57 SetCongestionWindowInPackets(3);
58 }
59 if (config.HasReceivedConnectionOptions() &&
60 ContainsQuicTag(config.ReceivedConnectionOptions(), kIW10)) {
61 // Initial window experiment.
62 SetCongestionWindowInPackets(10);
63 }
64 if (config.HasReceivedConnectionOptions() &&
65 ContainsQuicTag(config.ReceivedConnectionOptions(), kIW20)) {
66 // Initial window experiment.
67 SetCongestionWindowInPackets(20);
68 }
69 if (config.HasReceivedConnectionOptions() &&
70 ContainsQuicTag(config.ReceivedConnectionOptions(), kIW50)) {
71 // Initial window experiment.
72 SetCongestionWindowInPackets(50);
73 }
74 if (config.HasReceivedConnectionOptions() &&
75 ContainsQuicTag(config.ReceivedConnectionOptions(), kMIN1)) {
76 // Min CWND experiment.
77 SetMinCongestionWindowInPackets(1);
78 }
79 if (config.HasReceivedConnectionOptions() &&
80 ContainsQuicTag(config.ReceivedConnectionOptions(), kMIN4)) {
81 // Min CWND of 4 experiment.
82 min4_mode_ = true;
83 SetMinCongestionWindowInPackets(1);
84 }
85 if (config.HasReceivedConnectionOptions() &&
86 ContainsQuicTag(config.ReceivedConnectionOptions(), kSSLR)) {
87 // Slow Start Fast Exit experiment.
88 slow_start_large_reduction_ = true;
89 }
90 if (config.HasReceivedConnectionOptions() &&
91 ContainsQuicTag(config.ReceivedConnectionOptions(), kNPRR)) {
92 // Use unity pacing instead of PRR.
93 no_prr_ = true;
94 }
95 if (FLAGS_quic_rate_based_sending &&
96 config.HasReceivedConnectionOptions() &&
97 ContainsQuicTag(config.ReceivedConnectionOptions(), kRATE)) {
98 // Rate based sending experiment
99 rate_based_sending_ = true;
100 }
101 }
102 }
103
104 void TcpCubicSenderBase::ResumeConnectionState(
105 const CachedNetworkParameters& cached_network_params,
106 bool max_bandwidth_resumption) {
107 QuicBandwidth bandwidth = QuicBandwidth::FromBytesPerSecond(
108 max_bandwidth_resumption
109 ? cached_network_params.max_bandwidth_estimate_bytes_per_second()
110 : cached_network_params.bandwidth_estimate_bytes_per_second());
111 QuicTime::Delta rtt =
112 QuicTime::Delta::FromMilliseconds(cached_network_params.min_rtt_ms());
113
114 SetCongestionWindowFromBandwidthAndRtt(bandwidth, rtt);
115 }
116
117 void TcpCubicSenderBase::SetNumEmulatedConnections(int num_connections) {
118 num_connections_ = max(1, num_connections);
119 }
120
121 float TcpCubicSenderBase::RenoBeta() const {
122 // kNConnectionBeta is the backoff factor after loss for our N-connection
123 // emulation, which emulates the effective backoff of an ensemble of N
124 // TCP-Reno connections on a single loss event. The effective multiplier is
125 // computed as:
126 return (num_connections_ - 1 + kRenoBeta) / num_connections_;
127 }
128
129 void TcpCubicSenderBase::OnCongestionEvent(
130 bool rtt_updated,
131 QuicByteCount bytes_in_flight,
132 const CongestionVector& acked_packets,
133 const CongestionVector& lost_packets) {
134 if (rtt_updated && InSlowStart() &&
135 hybrid_slow_start_.ShouldExitSlowStart(
136 rtt_stats_->latest_rtt(), rtt_stats_->min_rtt(),
137 GetCongestionWindow() / kDefaultTCPMSS)) {
138 ExitSlowstart();
139 }
140 for (CongestionVector::const_iterator it = lost_packets.begin();
141 it != lost_packets.end(); ++it) {
142 OnPacketLost(it->first, it->second, bytes_in_flight);
143 }
144 for (CongestionVector::const_iterator it = acked_packets.begin();
145 it != acked_packets.end(); ++it) {
146 OnPacketAcked(it->first, it->second, bytes_in_flight);
147 }
148 }
149
150 void TcpCubicSenderBase::OnPacketAcked(QuicPacketNumber acked_packet_number,
151 QuicByteCount acked_bytes,
152 QuicByteCount bytes_in_flight) {
153 largest_acked_packet_number_ =
154 max(acked_packet_number, largest_acked_packet_number_);
155 if (InRecovery()) {
156 if (!no_prr_) {
157 // PRR is used when in recovery.
158 prr_.OnPacketAcked(acked_bytes);
159 }
160 return;
161 }
162 MaybeIncreaseCwnd(acked_packet_number, acked_bytes, bytes_in_flight);
163 if (InSlowStart()) {
164 hybrid_slow_start_.OnPacketAcked(acked_packet_number);
165 }
166 }
167
168 bool TcpCubicSenderBase::OnPacketSent(
169 QuicTime /*sent_time*/,
170 QuicByteCount /*bytes_in_flight*/,
171 QuicPacketNumber packet_number,
172 QuicByteCount bytes,
173 HasRetransmittableData is_retransmittable) {
174 if (InSlowStart()) {
175 ++(stats_->slowstart_packets_sent);
176 }
177
178 // Only update bytes_in_flight_ for data packets.
179 if (is_retransmittable != HAS_RETRANSMITTABLE_DATA) {
180 return false;
181 }
182 if (InRecovery()) {
183 // PRR is used when in recovery.
184 prr_.OnPacketSent(bytes);
185 }
186 DCHECK_LT(largest_sent_packet_number_, packet_number);
187 largest_sent_packet_number_ = packet_number;
188 hybrid_slow_start_.OnPacketSent(packet_number);
189 return true;
190 }
191
192 QuicTime::Delta TcpCubicSenderBase::TimeUntilSend(
193 QuicTime /* now */,
194 QuicByteCount bytes_in_flight) const {
195 if (!no_prr_ && InRecovery()) {
196 // PRR is used when in recovery.
197 return prr_.TimeUntilSend(GetCongestionWindow(), bytes_in_flight,
198 GetSlowStartThreshold());
199 }
200 if (GetCongestionWindow() > bytes_in_flight) {
201 return QuicTime::Delta::Zero();
202 }
203 if (min4_mode_ && bytes_in_flight < 4 * kDefaultTCPMSS) {
204 return QuicTime::Delta::Zero();
205 }
206 if (rate_based_sending_ &&
207 GetCongestionWindow() * kRateBasedExtraCwnd > bytes_in_flight) {
208 return QuicTime::Delta::Zero();
209 }
210 return QuicTime::Delta::Infinite();
211 }
212
213 QuicBandwidth TcpCubicSenderBase::PacingRate(
214 QuicByteCount bytes_in_flight) const {
215 // We pace at twice the rate of the underlying sender's bandwidth estimate
216 // during slow start and 1.25x during congestion avoidance to ensure pacing
217 // doesn't prevent us from filling the window.
218 QuicTime::Delta srtt = rtt_stats_->smoothed_rtt();
219 if (srtt.IsZero()) {
220 srtt = QuicTime::Delta::FromMicroseconds(rtt_stats_->initial_rtt_us());
221 }
222 const QuicBandwidth bandwidth =
223 QuicBandwidth::FromBytesAndTimeDelta(GetCongestionWindow(), srtt);
224 if (rate_based_sending_ && bytes_in_flight > GetCongestionWindow()) {
225 // Rate based sending allows sending more than CWND, but reduces the pacing
226 // rate when the bytes in flight is more than the CWND to 75% of bandwidth.
227 return 0.75 * bandwidth;
228 }
229 return bandwidth * (InSlowStart() ? 2 : (no_prr_ && InRecovery() ? 1 : 1.25));
230 }
231
232 QuicBandwidth TcpCubicSenderBase::BandwidthEstimate() const {
233 QuicTime::Delta srtt = rtt_stats_->smoothed_rtt();
234 if (srtt.IsZero()) {
235 // If we haven't measured an rtt, the bandwidth estimate is unknown.
236 return QuicBandwidth::Zero();
237 }
238 return QuicBandwidth::FromBytesAndTimeDelta(GetCongestionWindow(), srtt);
239 }
240
241 QuicTime::Delta TcpCubicSenderBase::RetransmissionDelay() const {
242 if (rtt_stats_->smoothed_rtt().IsZero()) {
243 return QuicTime::Delta::Zero();
244 }
245 return rtt_stats_->smoothed_rtt() + 4 * rtt_stats_->mean_deviation();
246 }
247
248 bool TcpCubicSenderBase::InSlowStart() const {
249 return GetCongestionWindow() < GetSlowStartThreshold();
250 }
251
252 bool TcpCubicSenderBase::IsCwndLimited(QuicByteCount bytes_in_flight) const {
253 const QuicByteCount congestion_window = GetCongestionWindow();
254 if (bytes_in_flight >= congestion_window) {
255 return true;
256 }
257 const QuicByteCount available_bytes = congestion_window - bytes_in_flight;
258 const bool slow_start_limited =
259 InSlowStart() && bytes_in_flight > congestion_window / 2;
260 return slow_start_limited || available_bytes <= kMaxBurstBytes;
261 }
262
263 bool TcpCubicSenderBase::InRecovery() const {
264 return largest_acked_packet_number_ <= largest_sent_at_last_cutback_ &&
265 largest_acked_packet_number_ != 0;
266 }
267
268 void TcpCubicSenderBase::OnRetransmissionTimeout(bool packets_retransmitted) {
269 largest_sent_at_last_cutback_ = 0;
270 if (!packets_retransmitted) {
271 return;
272 }
273 hybrid_slow_start_.Restart();
274 HandleRetransmissionTimeout();
275 }
276
277 void TcpCubicSenderBase::OnConnectionMigration() {
278 hybrid_slow_start_.Restart();
279 prr_ = PrrSender();
280 largest_sent_packet_number_ = 0;
281 largest_acked_packet_number_ = 0;
282 largest_sent_at_last_cutback_ = 0;
283 last_cutback_exited_slowstart_ = false;
284 }
285
286 } // namespace net
OLDNEW
« no previous file with comments | « net/quic/congestion_control/tcp_cubic_sender_base.h ('k') | net/quic/congestion_control/tcp_cubic_sender_bytes.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698