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

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

Issue 1785663003: Deprecate FLAG_quic_use_new_tcp_sender (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@115885351
Patch Set: Created 4 years, 9 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
« no previous file with comments | « net/quic/congestion_control/tcp_cubic_sender.cc ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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.h"
6
7 #include <algorithm>
8
9 #include "base/logging.h"
10 #include "base/memory/scoped_ptr.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_flags.h"
15 #include "net/quic/quic_protocol.h"
16 #include "net/quic/quic_utils.h"
17 #include "net/quic/test_tools/mock_clock.h"
18 #include "net/quic/test_tools/quic_config_peer.h"
19 #include "net/quic/test_tools/quic_test_utils.h"
20 #include "testing/gtest/include/gtest/gtest.h"
21
22 using std::min;
23
24 namespace net {
25 namespace test {
26
27 // TODO(ianswett): A number of theses tests were written with the assumption of
28 // an initial CWND of 10. They have carefully calculated values which should be
29 // updated to be based on kInitialCongestionWindow.
30 const uint32_t kInitialCongestionWindowPackets = 10;
31 const uint32_t kDefaultWindowTCP =
32 kInitialCongestionWindowPackets * kDefaultTCPMSS;
33 const float kRenoBeta = 0.7f; // Reno backoff factor.
34
35 class TcpCubicSenderPeer : public TcpCubicSender {
36 public:
37 TcpCubicSenderPeer(const QuicClock* clock,
38 bool reno,
39 QuicPacketCount max_tcp_congestion_window)
40 : TcpCubicSender(clock,
41 &rtt_stats_,
42 reno,
43 kInitialCongestionWindowPackets,
44 max_tcp_congestion_window,
45 &stats_) {}
46
47 QuicPacketCount congestion_window() { return congestion_window_; }
48
49 QuicPacketCount slowstart_threshold() { return slowstart_threshold_; }
50
51 const HybridSlowStart& hybrid_slow_start() const {
52 return hybrid_slow_start_;
53 }
54
55 float GetRenoBeta() const { return RenoBeta(); }
56
57 RttStats rtt_stats_;
58 QuicConnectionStats stats_;
59 };
60
61 class TcpCubicSenderTest : public ::testing::Test {
62 protected:
63 TcpCubicSenderTest()
64 : one_ms_(QuicTime::Delta::FromMilliseconds(1)),
65 sender_(new TcpCubicSenderPeer(&clock_, true, kMaxCongestionWindow)),
66 packet_number_(1),
67 acked_packet_number_(0),
68 bytes_in_flight_(0) {}
69
70 int SendAvailableSendWindow() {
71 // Send as long as TimeUntilSend returns Zero.
72 int packets_sent = 0;
73 bool can_send = sender_->TimeUntilSend(clock_.Now(), bytes_in_flight_,
74 HAS_RETRANSMITTABLE_DATA)
75 .IsZero();
76 while (can_send) {
77 sender_->OnPacketSent(clock_.Now(), bytes_in_flight_, packet_number_++,
78 kDefaultTCPMSS, HAS_RETRANSMITTABLE_DATA);
79 ++packets_sent;
80 bytes_in_flight_ += kDefaultTCPMSS;
81 can_send = sender_->TimeUntilSend(clock_.Now(), bytes_in_flight_,
82 HAS_RETRANSMITTABLE_DATA)
83 .IsZero();
84 }
85 return packets_sent;
86 }
87
88 // Normal is that TCP acks every other segment.
89 void AckNPackets(int n) {
90 sender_->rtt_stats_.UpdateRtt(QuicTime::Delta::FromMilliseconds(60),
91 QuicTime::Delta::Zero(), clock_.Now());
92 SendAlgorithmInterface::CongestionVector acked_packets;
93 SendAlgorithmInterface::CongestionVector lost_packets;
94 for (int i = 0; i < n; ++i) {
95 ++acked_packet_number_;
96 acked_packets.push_back(
97 std::make_pair(acked_packet_number_, kDefaultTCPMSS));
98 }
99 sender_->OnCongestionEvent(true, bytes_in_flight_, acked_packets,
100 lost_packets);
101 bytes_in_flight_ -= n * kDefaultTCPMSS;
102 clock_.AdvanceTime(one_ms_);
103 }
104
105 void LoseNPackets(int n) {
106 SendAlgorithmInterface::CongestionVector acked_packets;
107 SendAlgorithmInterface::CongestionVector lost_packets;
108 for (int i = 0; i < n; ++i) {
109 ++acked_packet_number_;
110 lost_packets.push_back(
111 std::make_pair(acked_packet_number_, kDefaultTCPMSS));
112 }
113 sender_->OnCongestionEvent(false, bytes_in_flight_, acked_packets,
114 lost_packets);
115 bytes_in_flight_ -= n * kDefaultTCPMSS;
116 }
117
118 // Does not increment acked_packet_number_.
119 void LosePacket(QuicPacketNumber packet_number) {
120 SendAlgorithmInterface::CongestionVector acked_packets;
121 SendAlgorithmInterface::CongestionVector lost_packets;
122 lost_packets.push_back(std::make_pair(packet_number, kDefaultTCPMSS));
123 sender_->OnCongestionEvent(false, bytes_in_flight_, acked_packets,
124 lost_packets);
125 bytes_in_flight_ -= kDefaultTCPMSS;
126 }
127
128 const QuicTime::Delta one_ms_;
129 MockClock clock_;
130 scoped_ptr<TcpCubicSenderPeer> sender_;
131 QuicPacketNumber packet_number_;
132 QuicPacketNumber acked_packet_number_;
133 QuicByteCount bytes_in_flight_;
134 };
135
136 TEST_F(TcpCubicSenderTest, SimpleSender) {
137 // At startup make sure we are at the default.
138 EXPECT_EQ(kDefaultWindowTCP, sender_->GetCongestionWindow());
139 // At startup make sure we can send.
140 EXPECT_TRUE(sender_->TimeUntilSend(clock_.Now(), 0, HAS_RETRANSMITTABLE_DATA)
141 .IsZero());
142 // Make sure we can send.
143 EXPECT_TRUE(sender_->TimeUntilSend(clock_.Now(), 0, HAS_RETRANSMITTABLE_DATA)
144 .IsZero());
145 // And that window is un-affected.
146 EXPECT_EQ(kDefaultWindowTCP, sender_->GetCongestionWindow());
147
148 // Fill the send window with data, then verify that we can't send.
149 SendAvailableSendWindow();
150 EXPECT_FALSE(sender_->TimeUntilSend(clock_.Now(),
151 sender_->GetCongestionWindow(),
152 HAS_RETRANSMITTABLE_DATA)
153 .IsZero());
154 }
155
156 TEST_F(TcpCubicSenderTest, ApplicationLimitedSlowStart) {
157 // Send exactly 10 packets and ensure the CWND ends at 14 packets.
158 const int kNumberOfAcks = 5;
159 // At startup make sure we can send.
160 EXPECT_TRUE(sender_->TimeUntilSend(clock_.Now(), 0, HAS_RETRANSMITTABLE_DATA)
161 .IsZero());
162 // Make sure we can send.
163 EXPECT_TRUE(sender_->TimeUntilSend(clock_.Now(), 0, HAS_RETRANSMITTABLE_DATA)
164 .IsZero());
165
166 SendAvailableSendWindow();
167 for (int i = 0; i < kNumberOfAcks; ++i) {
168 AckNPackets(2);
169 }
170 QuicByteCount bytes_to_send = sender_->GetCongestionWindow();
171 // It's expected 2 acks will arrive when the bytes_in_flight are greater than
172 // half the CWND.
173 EXPECT_EQ(kDefaultWindowTCP + kDefaultTCPMSS * 2 * 2, bytes_to_send);
174 }
175
176 TEST_F(TcpCubicSenderTest, ExponentialSlowStart) {
177 const int kNumberOfAcks = 20;
178 // At startup make sure we can send.
179 EXPECT_TRUE(sender_->TimeUntilSend(clock_.Now(), 0, HAS_RETRANSMITTABLE_DATA)
180 .IsZero());
181 EXPECT_EQ(QuicBandwidth::Zero(), sender_->BandwidthEstimate());
182 // Make sure we can send.
183 EXPECT_TRUE(sender_->TimeUntilSend(clock_.Now(), 0, HAS_RETRANSMITTABLE_DATA)
184 .IsZero());
185
186 for (int i = 0; i < kNumberOfAcks; ++i) {
187 // Send our full send window.
188 SendAvailableSendWindow();
189 AckNPackets(2);
190 }
191 const QuicByteCount cwnd = sender_->GetCongestionWindow();
192 EXPECT_EQ(kDefaultWindowTCP + kDefaultTCPMSS * 2 * kNumberOfAcks, cwnd);
193 EXPECT_EQ(QuicBandwidth::FromBytesAndTimeDelta(
194 cwnd, sender_->rtt_stats_.smoothed_rtt()),
195 sender_->BandwidthEstimate());
196 }
197
198 TEST_F(TcpCubicSenderTest, SlowStartPacketLoss) {
199 sender_->SetNumEmulatedConnections(1);
200 const int kNumberOfAcks = 10;
201 for (int i = 0; i < kNumberOfAcks; ++i) {
202 // Send our full send window.
203 SendAvailableSendWindow();
204 AckNPackets(2);
205 }
206 SendAvailableSendWindow();
207 QuicByteCount expected_send_window =
208 kDefaultWindowTCP + (kDefaultTCPMSS * 2 * kNumberOfAcks);
209 EXPECT_EQ(expected_send_window, sender_->GetCongestionWindow());
210
211 // Lose a packet to exit slow start.
212 LoseNPackets(1);
213 size_t packets_in_recovery_window = expected_send_window / kDefaultTCPMSS;
214
215 // We should now have fallen out of slow start with a reduced window.
216 expected_send_window *= kRenoBeta;
217 EXPECT_EQ(expected_send_window, sender_->GetCongestionWindow());
218
219 // Recovery phase. We need to ack every packet in the recovery window before
220 // we exit recovery.
221 size_t number_of_packets_in_window = expected_send_window / kDefaultTCPMSS;
222 DVLOG(1) << "number_packets: " << number_of_packets_in_window;
223 AckNPackets(packets_in_recovery_window);
224 SendAvailableSendWindow();
225 EXPECT_EQ(expected_send_window, sender_->GetCongestionWindow());
226
227 // We need to ack an entire window before we increase CWND by 1.
228 AckNPackets(number_of_packets_in_window - 2);
229 SendAvailableSendWindow();
230 EXPECT_EQ(expected_send_window, sender_->GetCongestionWindow());
231
232 // Next ack should increase cwnd by 1.
233 AckNPackets(1);
234 expected_send_window += kDefaultTCPMSS;
235 EXPECT_EQ(expected_send_window, sender_->GetCongestionWindow());
236
237 // Now RTO and ensure slow start gets reset.
238 EXPECT_TRUE(sender_->hybrid_slow_start().started());
239 sender_->OnRetransmissionTimeout(true);
240 EXPECT_FALSE(sender_->hybrid_slow_start().started());
241 }
242
243 TEST_F(TcpCubicSenderTest, SlowStartPacketLossWithLargeReduction) {
244 QuicConfig config;
245 QuicTagVector options;
246 options.push_back(kSSLR);
247 QuicConfigPeer::SetReceivedConnectionOptions(&config, options);
248 sender_->SetFromConfig(config, Perspective::IS_SERVER);
249
250 sender_->SetNumEmulatedConnections(1);
251 const int kNumberOfAcks = 10;
252 for (int i = 0; i < kNumberOfAcks; ++i) {
253 // Send our full send window.
254 SendAvailableSendWindow();
255 AckNPackets(2);
256 }
257 SendAvailableSendWindow();
258 QuicByteCount expected_send_window =
259 kDefaultWindowTCP + (kDefaultTCPMSS * 2 * kNumberOfAcks);
260 EXPECT_EQ(expected_send_window, sender_->GetCongestionWindow());
261
262 // Lose a packet to exit slow start. We should now have fallen out of
263 // slow start with a window reduced by 1.
264 LoseNPackets(1);
265 expected_send_window -= kDefaultTCPMSS;
266 EXPECT_EQ(expected_send_window, sender_->GetCongestionWindow());
267
268 // Lose 5 packets in recovery and verify that congestion window is reduced
269 // further.
270 LoseNPackets(5);
271 expected_send_window -= 5 * kDefaultTCPMSS;
272 EXPECT_EQ(expected_send_window, sender_->GetCongestionWindow());
273
274 size_t packets_in_recovery_window = expected_send_window / kDefaultTCPMSS;
275
276 // Recovery phase. We need to ack every packet in the recovery window before
277 // we exit recovery.
278 size_t number_of_packets_in_window = expected_send_window / kDefaultTCPMSS;
279 DVLOG(1) << "number_packets: " << number_of_packets_in_window;
280 AckNPackets(packets_in_recovery_window);
281 SendAvailableSendWindow();
282 EXPECT_EQ(expected_send_window, sender_->GetCongestionWindow());
283
284 // We need to ack the rest of the window before cwnd increases by 1.
285 AckNPackets(number_of_packets_in_window - 1);
286 SendAvailableSendWindow();
287 EXPECT_EQ(expected_send_window, sender_->GetCongestionWindow());
288
289 // Next ack should increase cwnd by 1.
290 AckNPackets(1);
291 expected_send_window += kDefaultTCPMSS;
292 EXPECT_EQ(expected_send_window, sender_->GetCongestionWindow());
293
294 // Now RTO and ensure slow start gets reset.
295 EXPECT_TRUE(sender_->hybrid_slow_start().started());
296 sender_->OnRetransmissionTimeout(true);
297 EXPECT_FALSE(sender_->hybrid_slow_start().started());
298 }
299
300 TEST_F(TcpCubicSenderTest, NoPRRWhenLessThanOnePacketInFlight) {
301 SendAvailableSendWindow();
302 LoseNPackets(kInitialCongestionWindowPackets - 1);
303 AckNPackets(1);
304 // PRR will allow 2 packets for every ack during recovery.
305 EXPECT_EQ(2, SendAvailableSendWindow());
306 // Simulate abandoning all packets by supplying a bytes_in_flight of 0.
307 // PRR should now allow a packet to be sent, even though prr's state
308 // variables believe it has sent enough packets.
309 EXPECT_EQ(QuicTime::Delta::Zero(),
310 sender_->TimeUntilSend(clock_.Now(), 0, HAS_RETRANSMITTABLE_DATA));
311 }
312
313 TEST_F(TcpCubicSenderTest, SlowStartPacketLossPRR) {
314 sender_->SetNumEmulatedConnections(1);
315 // Test based on the first example in RFC6937.
316 // Ack 10 packets in 5 acks to raise the CWND to 20, as in the example.
317 const int kNumberOfAcks = 5;
318 for (int i = 0; i < kNumberOfAcks; ++i) {
319 // Send our full send window.
320 SendAvailableSendWindow();
321 AckNPackets(2);
322 }
323 SendAvailableSendWindow();
324 QuicByteCount expected_send_window =
325 kDefaultWindowTCP + (kDefaultTCPMSS * 2 * kNumberOfAcks);
326 EXPECT_EQ(expected_send_window, sender_->GetCongestionWindow());
327
328 LoseNPackets(1);
329
330 // We should now have fallen out of slow start with a reduced window.
331 size_t send_window_before_loss = expected_send_window;
332 expected_send_window *= kRenoBeta;
333 EXPECT_EQ(expected_send_window, sender_->GetCongestionWindow());
334
335 // Testing TCP proportional rate reduction.
336 // We should send packets paced over the received acks for the remaining
337 // outstanding packets. The number of packets before we exit recovery is the
338 // original CWND minus the packet that has been lost and the one which
339 // triggered the loss.
340 size_t remaining_packets_in_recovery =
341 send_window_before_loss / kDefaultTCPMSS - 2;
342
343 for (size_t i = 0; i < remaining_packets_in_recovery; ++i) {
344 AckNPackets(1);
345 SendAvailableSendWindow();
346 EXPECT_EQ(expected_send_window, sender_->GetCongestionWindow());
347 }
348
349 // We need to ack another window before we increase CWND by 1.
350 size_t number_of_packets_in_window = expected_send_window / kDefaultTCPMSS;
351 for (size_t i = 0; i < number_of_packets_in_window; ++i) {
352 AckNPackets(1);
353 EXPECT_EQ(1, SendAvailableSendWindow());
354 EXPECT_EQ(expected_send_window, sender_->GetCongestionWindow());
355 }
356
357 AckNPackets(1);
358 expected_send_window += kDefaultTCPMSS;
359 EXPECT_EQ(expected_send_window, sender_->GetCongestionWindow());
360 }
361
362 TEST_F(TcpCubicSenderTest, SlowStartBurstPacketLossPRR) {
363 sender_->SetNumEmulatedConnections(1);
364 // Test based on the second example in RFC6937, though we also implement
365 // forward acknowledgements, so the first two incoming acks will trigger
366 // PRR immediately.
367 // Ack 20 packets in 10 acks to raise the CWND to 30.
368 const int kNumberOfAcks = 10;
369 for (int i = 0; i < kNumberOfAcks; ++i) {
370 // Send our full send window.
371 SendAvailableSendWindow();
372 AckNPackets(2);
373 }
374 SendAvailableSendWindow();
375 QuicByteCount expected_send_window =
376 kDefaultWindowTCP + (kDefaultTCPMSS * 2 * kNumberOfAcks);
377 EXPECT_EQ(expected_send_window, sender_->GetCongestionWindow());
378
379 // Lose one more than the congestion window reduction, so that after loss,
380 // bytes_in_flight is lesser than the congestion window.
381 size_t send_window_after_loss = kRenoBeta * expected_send_window;
382 size_t num_packets_to_lose =
383 (expected_send_window - send_window_after_loss) / kDefaultTCPMSS + 1;
384 LoseNPackets(num_packets_to_lose);
385 // Immediately after the loss, ensure at least one packet can be sent.
386 // Losses without subsequent acks can occur with timer based loss detection.
387 EXPECT_TRUE(sender_->TimeUntilSend(clock_.Now(), bytes_in_flight_,
388 HAS_RETRANSMITTABLE_DATA)
389 .IsZero());
390 AckNPackets(1);
391
392 // We should now have fallen out of slow start with a reduced window.
393 expected_send_window *= kRenoBeta;
394 EXPECT_EQ(expected_send_window, sender_->GetCongestionWindow());
395
396 // Only 2 packets should be allowed to be sent, per PRR-SSRB
397 EXPECT_EQ(2, SendAvailableSendWindow());
398
399 // Ack the next packet, which triggers another loss.
400 LoseNPackets(1);
401 AckNPackets(1);
402
403 // Send 2 packets to simulate PRR-SSRB.
404 EXPECT_EQ(2, SendAvailableSendWindow());
405
406 // Ack the next packet, which triggers another loss.
407 LoseNPackets(1);
408 AckNPackets(1);
409
410 // Send 2 packets to simulate PRR-SSRB.
411 EXPECT_EQ(2, SendAvailableSendWindow());
412
413 // Exit recovery and return to sending at the new rate.
414 for (int i = 0; i < kNumberOfAcks; ++i) {
415 AckNPackets(1);
416 EXPECT_EQ(1, SendAvailableSendWindow());
417 }
418 }
419
420 TEST_F(TcpCubicSenderTest, RTOCongestionWindow) {
421 EXPECT_EQ(kDefaultWindowTCP, sender_->GetCongestionWindow());
422 EXPECT_EQ(kMaxCongestionWindow, sender_->slowstart_threshold());
423
424 // Expect the window to decrease to the minimum once the RTO fires
425 // and slow start threshold to be set to 1/2 of the CWND.
426 sender_->OnRetransmissionTimeout(true);
427 EXPECT_EQ(2 * kDefaultTCPMSS, sender_->GetCongestionWindow());
428 EXPECT_EQ(5u, sender_->slowstart_threshold());
429 }
430
431 TEST_F(TcpCubicSenderTest, RTOCongestionWindowNoRetransmission) {
432 EXPECT_EQ(kDefaultWindowTCP, sender_->GetCongestionWindow());
433
434 // Expect the window to remain unchanged if the RTO fires but no
435 // packets are retransmitted.
436 sender_->OnRetransmissionTimeout(false);
437 EXPECT_EQ(kDefaultWindowTCP, sender_->GetCongestionWindow());
438 }
439
440 TEST_F(TcpCubicSenderTest, RetransmissionDelay) {
441 const int64_t kRttMs = 10;
442 const int64_t kDeviationMs = 3;
443 EXPECT_EQ(QuicTime::Delta::Zero(), sender_->RetransmissionDelay());
444
445 sender_->rtt_stats_.UpdateRtt(QuicTime::Delta::FromMilliseconds(kRttMs),
446 QuicTime::Delta::Zero(), clock_.Now());
447
448 // Initial value is to set the median deviation to half of the initial
449 // rtt, the median in then multiplied by a factor of 4 and finally the
450 // smoothed rtt is added which is the initial rtt.
451 QuicTime::Delta expected_delay =
452 QuicTime::Delta::FromMilliseconds(kRttMs + kRttMs / 2 * 4);
453 EXPECT_EQ(expected_delay, sender_->RetransmissionDelay());
454
455 for (int i = 0; i < 100; ++i) {
456 // Run to make sure that we converge.
457 sender_->rtt_stats_.UpdateRtt(
458 QuicTime::Delta::FromMilliseconds(kRttMs + kDeviationMs),
459 QuicTime::Delta::Zero(), clock_.Now());
460 sender_->rtt_stats_.UpdateRtt(
461 QuicTime::Delta::FromMilliseconds(kRttMs - kDeviationMs),
462 QuicTime::Delta::Zero(), clock_.Now());
463 }
464 expected_delay = QuicTime::Delta::FromMilliseconds(kRttMs + kDeviationMs * 4);
465
466 EXPECT_NEAR(kRttMs, sender_->rtt_stats_.smoothed_rtt().ToMilliseconds(), 1);
467 EXPECT_NEAR(expected_delay.ToMilliseconds(),
468 sender_->RetransmissionDelay().ToMilliseconds(), 1);
469 EXPECT_EQ(static_cast<int64_t>(
470 sender_->GetCongestionWindow() * kNumMicrosPerSecond /
471 sender_->rtt_stats_.smoothed_rtt().ToMicroseconds()),
472 sender_->BandwidthEstimate().ToBytesPerSecond());
473 }
474
475 TEST_F(TcpCubicSenderTest, SlowStartMaxSendWindow) {
476 const QuicPacketCount kMaxCongestionWindowTCP = 50;
477 const int kNumberOfAcks = 100;
478 sender_.reset(
479 new TcpCubicSenderPeer(&clock_, false, kMaxCongestionWindowTCP));
480
481 for (int i = 0; i < kNumberOfAcks; ++i) {
482 // Send our full send window.
483 SendAvailableSendWindow();
484 AckNPackets(2);
485 }
486 QuicByteCount expected_send_window = kMaxCongestionWindowTCP * kDefaultTCPMSS;
487 EXPECT_EQ(expected_send_window, sender_->GetCongestionWindow());
488 }
489
490 TEST_F(TcpCubicSenderTest, TcpRenoMaxCongestionWindow) {
491 const QuicPacketCount kMaxCongestionWindowTCP = 50;
492 const int kNumberOfAcks = 1000;
493 sender_.reset(new TcpCubicSenderPeer(&clock_, true, kMaxCongestionWindowTCP));
494
495 SendAvailableSendWindow();
496 AckNPackets(2);
497 // Make sure we fall out of slow start.
498 LoseNPackets(1);
499
500 for (int i = 0; i < kNumberOfAcks; ++i) {
501 // Send our full send window.
502 SendAvailableSendWindow();
503 AckNPackets(2);
504 }
505
506 QuicByteCount expected_send_window = kMaxCongestionWindowTCP * kDefaultTCPMSS;
507 EXPECT_EQ(expected_send_window, sender_->GetCongestionWindow());
508 }
509
510 TEST_F(TcpCubicSenderTest, TcpCubicMaxCongestionWindow) {
511 const QuicPacketCount kMaxCongestionWindowTCP = 50;
512 // Set to 10000 to compensate for small cubic alpha.
513 const int kNumberOfAcks = 10000;
514
515 sender_.reset(
516 new TcpCubicSenderPeer(&clock_, false, kMaxCongestionWindowTCP));
517
518 SendAvailableSendWindow();
519 AckNPackets(2);
520 // Make sure we fall out of slow start.
521 LoseNPackets(1);
522
523 for (int i = 0; i < kNumberOfAcks; ++i) {
524 // Send our full send window.
525 SendAvailableSendWindow();
526 AckNPackets(2);
527 }
528
529 QuicByteCount expected_send_window = kMaxCongestionWindowTCP * kDefaultTCPMSS;
530 EXPECT_EQ(expected_send_window, sender_->GetCongestionWindow());
531 }
532
533 TEST_F(TcpCubicSenderTest, TcpCubicResetEpochOnQuiescence) {
534 const int kMaxCongestionWindow = 50;
535 const QuicByteCount kMaxCongestionWindowBytes =
536 kMaxCongestionWindow * kDefaultTCPMSS;
537 sender_.reset(new TcpCubicSenderPeer(&clock_, false, kMaxCongestionWindow));
538
539 int num_sent = SendAvailableSendWindow();
540
541 // Make sure we fall out of slow start.
542 QuicByteCount saved_cwnd = sender_->GetCongestionWindow();
543 LoseNPackets(1);
544 EXPECT_GT(saved_cwnd, sender_->GetCongestionWindow());
545
546 // Ack the rest of the outstanding packets to get out of recovery.
547 for (int i = 1; i < num_sent; ++i) {
548 AckNPackets(1);
549 }
550 EXPECT_EQ(0u, bytes_in_flight_);
551
552 // Send a new window of data and ack all; cubic growth should occur.
553 saved_cwnd = sender_->GetCongestionWindow();
554 num_sent = SendAvailableSendWindow();
555 for (int i = 0; i < num_sent; ++i) {
556 AckNPackets(1);
557 }
558 EXPECT_LT(saved_cwnd, sender_->GetCongestionWindow());
559 EXPECT_GT(kMaxCongestionWindowBytes, sender_->GetCongestionWindow());
560 EXPECT_EQ(0u, bytes_in_flight_);
561
562 // Quiescent time of 100 seconds
563 clock_.AdvanceTime(QuicTime::Delta::FromMilliseconds(100000));
564
565 // Send new window of data and ack one packet. Cubic epoch should have
566 // been reset; ensure cwnd increase is not dramatic.
567 saved_cwnd = sender_->GetCongestionWindow();
568 SendAvailableSendWindow();
569 AckNPackets(1);
570 EXPECT_NEAR(saved_cwnd, sender_->GetCongestionWindow(), kDefaultTCPMSS);
571 EXPECT_GT(kMaxCongestionWindowBytes, sender_->GetCongestionWindow());
572 }
573
574 TEST_F(TcpCubicSenderTest, TcpCubicShiftedEpochOnQuiescence) {
575 ValueRestore<bool> old_flag(&FLAGS_shift_quic_cubic_epoch_when_app_limited,
576 true);
577 const int kMaxCongestionWindow = 50;
578 const QuicByteCount kMaxCongestionWindowBytes =
579 kMaxCongestionWindow * kDefaultTCPMSS;
580 sender_.reset(new TcpCubicSenderPeer(&clock_, false, kMaxCongestionWindow));
581
582 int num_sent = SendAvailableSendWindow();
583
584 // Make sure we fall out of slow start.
585 QuicByteCount saved_cwnd = sender_->GetCongestionWindow();
586 LoseNPackets(1);
587 EXPECT_GT(saved_cwnd, sender_->GetCongestionWindow());
588
589 // Ack the rest of the outstanding packets to get out of recovery.
590 for (int i = 1; i < num_sent; ++i) {
591 AckNPackets(1);
592 }
593 EXPECT_EQ(0u, bytes_in_flight_);
594
595 // Send a new window of data and ack all; cubic growth should occur.
596 saved_cwnd = sender_->GetCongestionWindow();
597 num_sent = SendAvailableSendWindow();
598 for (int i = 0; i < num_sent; ++i) {
599 AckNPackets(1);
600 }
601 EXPECT_LT(saved_cwnd, sender_->GetCongestionWindow());
602 EXPECT_GT(kMaxCongestionWindowBytes, sender_->GetCongestionWindow());
603 EXPECT_EQ(0u, bytes_in_flight_);
604
605 // Quiescent time of 100 seconds
606 clock_.AdvanceTime(QuicTime::Delta::FromSeconds(100));
607
608 // Send new window of data and ack one packet. Cubic epoch should have
609 // been reset; ensure cwnd increase is not dramatic.
610 saved_cwnd = sender_->GetCongestionWindow();
611 SendAvailableSendWindow();
612 AckNPackets(1);
613 EXPECT_NEAR(saved_cwnd, sender_->GetCongestionWindow(), kDefaultTCPMSS);
614 EXPECT_GT(kMaxCongestionWindowBytes, sender_->GetCongestionWindow());
615 }
616
617 TEST_F(TcpCubicSenderTest, MultipleLossesInOneWindow) {
618 SendAvailableSendWindow();
619 const QuicByteCount initial_window = sender_->GetCongestionWindow();
620 LosePacket(acked_packet_number_ + 1);
621 const QuicByteCount post_loss_window = sender_->GetCongestionWindow();
622 EXPECT_GT(initial_window, post_loss_window);
623 LosePacket(acked_packet_number_ + 3);
624 EXPECT_EQ(post_loss_window, sender_->GetCongestionWindow());
625 LosePacket(packet_number_ - 1);
626 EXPECT_EQ(post_loss_window, sender_->GetCongestionWindow());
627
628 // Lose a later packet and ensure the window decreases.
629 LosePacket(packet_number_);
630 EXPECT_GT(post_loss_window, sender_->GetCongestionWindow());
631 }
632
633 TEST_F(TcpCubicSenderTest, DontTrackAckPackets) {
634 // Send a packet with no retransmittable data, and ensure it's not tracked.
635 EXPECT_FALSE(sender_->OnPacketSent(clock_.Now(), bytes_in_flight_,
636 packet_number_++, kDefaultTCPMSS,
637 NO_RETRANSMITTABLE_DATA));
638
639 // Send a data packet with retransmittable data, and ensure it is tracked.
640 EXPECT_TRUE(sender_->OnPacketSent(clock_.Now(), bytes_in_flight_,
641 packet_number_++, kDefaultTCPMSS,
642 HAS_RETRANSMITTABLE_DATA));
643 }
644
645 TEST_F(TcpCubicSenderTest, ConfigureInitialWindow) {
646 QuicConfig config;
647
648 QuicTagVector options;
649 options.push_back(kIW03);
650 QuicConfigPeer::SetReceivedConnectionOptions(&config, options);
651 sender_->SetFromConfig(config, Perspective::IS_SERVER);
652 EXPECT_EQ(3u, sender_->congestion_window());
653
654 options.clear();
655 options.push_back(kIW10);
656 QuicConfigPeer::SetReceivedConnectionOptions(&config, options);
657 sender_->SetFromConfig(config, Perspective::IS_SERVER);
658 EXPECT_EQ(10u, sender_->congestion_window());
659
660 options.clear();
661 options.push_back(kIW20);
662 QuicConfigPeer::SetReceivedConnectionOptions(&config, options);
663 sender_->SetFromConfig(config, Perspective::IS_SERVER);
664 EXPECT_EQ(20u, sender_->congestion_window());
665
666 options.clear();
667 options.push_back(kIW50);
668 QuicConfigPeer::SetReceivedConnectionOptions(&config, options);
669 sender_->SetFromConfig(config, Perspective::IS_SERVER);
670 EXPECT_EQ(50u, sender_->congestion_window());
671 }
672
673 TEST_F(TcpCubicSenderTest, ConfigureMinimumWindow) {
674 QuicConfig config;
675
676 // Verify that kCOPT: kMIN1 forces the min CWND to 1 packet.
677 QuicTagVector options;
678 options.push_back(kMIN1);
679 QuicConfigPeer::SetReceivedConnectionOptions(&config, options);
680 sender_->SetFromConfig(config, Perspective::IS_SERVER);
681 sender_->OnRetransmissionTimeout(true);
682 EXPECT_EQ(1u, sender_->congestion_window());
683 }
684
685 TEST_F(TcpCubicSenderTest, 2ConnectionCongestionAvoidanceAtEndOfRecovery) {
686 sender_->SetNumEmulatedConnections(2);
687 // Ack 10 packets in 5 acks to raise the CWND to 20.
688 const int kNumberOfAcks = 5;
689 for (int i = 0; i < kNumberOfAcks; ++i) {
690 // Send our full send window.
691 SendAvailableSendWindow();
692 AckNPackets(2);
693 }
694 SendAvailableSendWindow();
695 QuicByteCount expected_send_window =
696 kDefaultWindowTCP + (kDefaultTCPMSS * 2 * kNumberOfAcks);
697 EXPECT_EQ(expected_send_window, sender_->GetCongestionWindow());
698
699 LoseNPackets(1);
700
701 // We should now have fallen out of slow start with a reduced window.
702 expected_send_window = expected_send_window * sender_->GetRenoBeta();
703 EXPECT_EQ(expected_send_window, sender_->GetCongestionWindow());
704
705 // No congestion window growth should occur in recovery phase, i.e., until the
706 // currently outstanding 20 packets are acked.
707 for (int i = 0; i < 10; ++i) {
708 // Send our full send window.
709 SendAvailableSendWindow();
710 EXPECT_TRUE(sender_->InRecovery());
711 AckNPackets(2);
712 EXPECT_EQ(expected_send_window, sender_->GetCongestionWindow());
713 }
714 EXPECT_FALSE(sender_->InRecovery());
715
716 // Out of recovery now. Congestion window should not grow for half an RTT.
717 size_t packets_in_send_window = expected_send_window / kDefaultTCPMSS;
718 SendAvailableSendWindow();
719 AckNPackets(packets_in_send_window / 2 - 2);
720 EXPECT_EQ(expected_send_window, sender_->GetCongestionWindow());
721
722 // Next ack should increase congestion window by 1MSS.
723 SendAvailableSendWindow();
724 AckNPackets(2);
725 expected_send_window += kDefaultTCPMSS;
726 packets_in_send_window += 1;
727 EXPECT_EQ(expected_send_window, sender_->GetCongestionWindow());
728
729 // Congestion window should remain steady again for half an RTT.
730 SendAvailableSendWindow();
731 AckNPackets(packets_in_send_window / 2 - 1);
732 EXPECT_EQ(expected_send_window, sender_->GetCongestionWindow());
733
734 // Next ack should cause congestion window to grow by 1MSS.
735 SendAvailableSendWindow();
736 AckNPackets(2);
737 expected_send_window += kDefaultTCPMSS;
738 EXPECT_EQ(expected_send_window, sender_->GetCongestionWindow());
739 }
740
741 TEST_F(TcpCubicSenderTest, 1ConnectionCongestionAvoidanceAtEndOfRecovery) {
742 sender_->SetNumEmulatedConnections(1);
743 // Ack 10 packets in 5 acks to raise the CWND to 20.
744 const int kNumberOfAcks = 5;
745 for (int i = 0; i < kNumberOfAcks; ++i) {
746 // Send our full send window.
747 SendAvailableSendWindow();
748 AckNPackets(2);
749 }
750 SendAvailableSendWindow();
751 QuicByteCount expected_send_window =
752 kDefaultWindowTCP + (kDefaultTCPMSS * 2 * kNumberOfAcks);
753 EXPECT_EQ(expected_send_window, sender_->GetCongestionWindow());
754
755 LoseNPackets(1);
756
757 // We should now have fallen out of slow start with a reduced window.
758 expected_send_window *= kRenoBeta;
759 EXPECT_EQ(expected_send_window, sender_->GetCongestionWindow());
760
761 // No congestion window growth should occur in recovery phase, i.e., until the
762 // currently outstanding 20 packets are acked.
763 for (int i = 0; i < 10; ++i) {
764 // Send our full send window.
765 SendAvailableSendWindow();
766 EXPECT_TRUE(sender_->InRecovery());
767 AckNPackets(2);
768 EXPECT_EQ(expected_send_window, sender_->GetCongestionWindow());
769 }
770 EXPECT_FALSE(sender_->InRecovery());
771
772 // Out of recovery now. Congestion window should not grow during RTT.
773 for (uint64_t i = 0; i < expected_send_window / kDefaultTCPMSS - 2; i += 2) {
774 // Send our full send window.
775 SendAvailableSendWindow();
776 AckNPackets(2);
777 EXPECT_EQ(expected_send_window, sender_->GetCongestionWindow());
778 }
779
780 // Next ack should cause congestion window to grow by 1MSS.
781 SendAvailableSendWindow();
782 AckNPackets(2);
783 expected_send_window += kDefaultTCPMSS;
784 EXPECT_EQ(expected_send_window, sender_->GetCongestionWindow());
785 }
786
787 TEST_F(TcpCubicSenderTest, BandwidthResumption) {
788 // Test that when provided with CachedNetworkParameters and opted in to the
789 // bandwidth resumption experiment, that the TcpCubicSender sets initial CWND
790 // appropriately.
791
792 // Set some common values.
793 CachedNetworkParameters cached_network_params;
794 const QuicPacketCount kNumberOfPackets = 123;
795 const int kBandwidthEstimateBytesPerSecond =
796 kNumberOfPackets * kDefaultTCPMSS;
797 cached_network_params.set_bandwidth_estimate_bytes_per_second(
798 kBandwidthEstimateBytesPerSecond);
799 cached_network_params.set_min_rtt_ms(1000);
800
801 // Make sure that a bandwidth estimate results in a changed CWND.
802 cached_network_params.set_timestamp(clock_.WallNow().ToUNIXSeconds() -
803 (kNumSecondsPerHour - 1));
804 sender_->ResumeConnectionState(cached_network_params, false);
805 EXPECT_EQ(kNumberOfPackets, sender_->congestion_window());
806
807 // Resumed CWND is limited to be in a sensible range.
808 cached_network_params.set_bandwidth_estimate_bytes_per_second(
809 (kMaxCongestionWindow + 1) * kDefaultTCPMSS);
810 sender_->ResumeConnectionState(cached_network_params, false);
811 EXPECT_EQ(kMaxCongestionWindow, sender_->congestion_window());
812
813 cached_network_params.set_bandwidth_estimate_bytes_per_second(
814 (kMinCongestionWindowForBandwidthResumption - 1) * kDefaultTCPMSS);
815 sender_->ResumeConnectionState(cached_network_params, false);
816 EXPECT_EQ(kMinCongestionWindowForBandwidthResumption,
817 sender_->congestion_window());
818
819 // Resume to the max value.
820 cached_network_params.set_max_bandwidth_estimate_bytes_per_second(
821 (kMinCongestionWindowForBandwidthResumption + 10) * kDefaultTCPMSS);
822 sender_->ResumeConnectionState(cached_network_params, true);
823 EXPECT_EQ((kMinCongestionWindowForBandwidthResumption + 10) * kDefaultTCPMSS,
824 sender_->GetCongestionWindow());
825 }
826
827 TEST_F(TcpCubicSenderTest, PaceBelowCWND) {
828 QuicConfig config;
829
830 // Verify that kCOPT: kMIN4 forces the min CWND to 1 packet, but allows up
831 // to 4 to be sent.
832 QuicTagVector options;
833 options.push_back(kMIN4);
834 QuicConfigPeer::SetReceivedConnectionOptions(&config, options);
835 sender_->SetFromConfig(config, Perspective::IS_SERVER);
836 sender_->OnRetransmissionTimeout(true);
837 EXPECT_EQ(1u, sender_->congestion_window());
838 EXPECT_TRUE(sender_->TimeUntilSend(QuicTime::Zero(), kDefaultTCPMSS,
839 HAS_RETRANSMITTABLE_DATA)
840 .IsZero());
841 EXPECT_TRUE(sender_->TimeUntilSend(QuicTime::Zero(), 2 * kDefaultTCPMSS,
842 HAS_RETRANSMITTABLE_DATA)
843 .IsZero());
844 EXPECT_TRUE(sender_->TimeUntilSend(QuicTime::Zero(), 3 * kDefaultTCPMSS,
845 HAS_RETRANSMITTABLE_DATA)
846 .IsZero());
847 EXPECT_FALSE(sender_->TimeUntilSend(QuicTime::Zero(), 4 * kDefaultTCPMSS,
848 HAS_RETRANSMITTABLE_DATA)
849 .IsZero());
850 }
851
852 TEST_F(TcpCubicSenderTest, ResetAfterConnectionMigration) {
853 EXPECT_EQ(kDefaultWindowTCP, sender_->GetCongestionWindow());
854 EXPECT_EQ(kMaxCongestionWindow, sender_->slowstart_threshold());
855
856 // Starts with slow start.
857 sender_->SetNumEmulatedConnections(1);
858 const int kNumberOfAcks = 10;
859 for (int i = 0; i < kNumberOfAcks; ++i) {
860 // Send our full send window.
861 SendAvailableSendWindow();
862 AckNPackets(2);
863 }
864 SendAvailableSendWindow();
865 QuicByteCount expected_send_window =
866 kDefaultWindowTCP + (kDefaultTCPMSS * 2 * kNumberOfAcks);
867 EXPECT_EQ(expected_send_window, sender_->GetCongestionWindow());
868
869 // Loses a packet to exit slow start.
870 LoseNPackets(1);
871
872 // We should now have fallen out of slow start with a reduced window. Slow
873 // start threshold is also updated.
874 expected_send_window *= kRenoBeta;
875 EXPECT_EQ(expected_send_window, sender_->GetCongestionWindow());
876 EXPECT_EQ(expected_send_window / kDefaultTCPMSS,
877 sender_->slowstart_threshold());
878
879 // Resets cwnd and slow start threshold on connection migrations.
880 sender_->OnConnectionMigration();
881 EXPECT_EQ(kDefaultWindowTCP, sender_->GetCongestionWindow());
882 EXPECT_EQ(kMaxCongestionWindow, sender_->slowstart_threshold());
883 EXPECT_FALSE(sender_->hybrid_slow_start().started());
884 }
885
886 } // namespace test
887 } // namespace net
OLDNEW
« no previous file with comments | « net/quic/congestion_control/tcp_cubic_sender.cc ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698