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 <algorithm> | 5 #include <algorithm> |
6 | 6 |
7 #include "base/logging.h" | 7 #include "base/logging.h" |
8 #include "base/memory/scoped_ptr.h" | 8 #include "base/memory/scoped_ptr.h" |
9 #include "net/quic/congestion_control/rtt_stats.h" | 9 #include "net/quic/congestion_control/rtt_stats.h" |
10 #include "net/quic/congestion_control/tcp_cubic_sender.h" | 10 #include "net/quic/congestion_control/tcp_cubic_sender.h" |
11 #include "net/quic/congestion_control/tcp_receiver.h" | 11 #include "net/quic/congestion_control/tcp_receiver.h" |
12 #include "net/quic/crypto/crypto_protocol.h" | 12 #include "net/quic/crypto/crypto_protocol.h" |
13 #include "net/quic/quic_utils.h" | 13 #include "net/quic/quic_utils.h" |
14 #include "net/quic/test_tools/mock_clock.h" | 14 #include "net/quic/test_tools/mock_clock.h" |
15 #include "net/quic/test_tools/quic_config_peer.h" | 15 #include "net/quic/test_tools/quic_config_peer.h" |
16 #include "testing/gtest/include/gtest/gtest.h" | 16 #include "testing/gtest/include/gtest/gtest.h" |
17 | 17 |
18 using std::make_pair; | 18 using std::make_pair; |
19 using std::min; | 19 using std::min; |
20 | 20 |
21 namespace net { | 21 namespace net { |
22 namespace test { | 22 namespace test { |
23 | 23 |
24 const int64 kInitialCongestionWindow = 10; | 24 const int64 kInitialCongestionWindow = 10; |
25 const uint32 kDefaultWindowTCP = kInitialCongestionWindow * kDefaultTCPMSS; | 25 const uint32 kDefaultWindowTCP = kInitialCongestionWindow * kDefaultTCPMSS; |
| 26 const float kRenoBeta = 0.7f; // Reno backoff factor. |
26 | 27 |
27 // TODO(ianswett): Remove 10000 once b/10075719 is fixed. | 28 // TODO(ianswett): Remove 10000 once b/10075719 is fixed. |
28 const QuicPacketCount kDefaultMaxCongestionWindowTCP = 10000; | 29 const QuicPacketCount kDefaultMaxCongestionWindowTCP = 10000; |
29 | 30 |
30 class TcpCubicSenderPeer : public TcpCubicSender { | 31 class TcpCubicSenderPeer : public TcpCubicSender { |
31 public: | 32 public: |
32 TcpCubicSenderPeer(const QuicClock* clock, | 33 TcpCubicSenderPeer(const QuicClock* clock, |
33 bool reno, | 34 bool reno, |
34 QuicPacketCount max_tcp_congestion_window) | 35 QuicPacketCount max_tcp_congestion_window) |
35 : TcpCubicSender( | 36 : TcpCubicSender( |
36 clock, &rtt_stats_, reno, max_tcp_congestion_window, &stats_) { | 37 clock, &rtt_stats_, reno, max_tcp_congestion_window, &stats_) { |
37 } | 38 } |
38 | 39 |
39 QuicPacketCount congestion_window() { | 40 QuicPacketCount congestion_window() { |
40 return congestion_window_; | 41 return congestion_window_; |
41 } | 42 } |
42 | 43 |
43 QuicPacketCount slowstart_threshold() { | 44 QuicPacketCount slowstart_threshold() { |
44 return slowstart_threshold_; | 45 return slowstart_threshold_; |
45 } | 46 } |
46 | 47 |
47 const HybridSlowStart& hybrid_slow_start() const { | 48 const HybridSlowStart& hybrid_slow_start() const { |
48 return hybrid_slow_start_; | 49 return hybrid_slow_start_; |
49 } | 50 } |
50 | 51 |
| 52 float GetRenoBeta() const { |
| 53 return RenoBeta(); |
| 54 } |
| 55 |
51 RttStats rtt_stats_; | 56 RttStats rtt_stats_; |
52 QuicConnectionStats stats_; | 57 QuicConnectionStats stats_; |
53 }; | 58 }; |
54 | 59 |
55 class TcpCubicSenderTest : public ::testing::Test { | 60 class TcpCubicSenderTest : public ::testing::Test { |
56 protected: | 61 protected: |
57 TcpCubicSenderTest() | 62 TcpCubicSenderTest() |
58 : one_ms_(QuicTime::Delta::FromMilliseconds(1)), | 63 : one_ms_(QuicTime::Delta::FromMilliseconds(1)), |
59 sender_(new TcpCubicSenderPeer(&clock_, true, | 64 sender_(new TcpCubicSenderPeer(&clock_, true, |
60 kDefaultMaxCongestionWindowTCP)), | 65 kDefaultMaxCongestionWindowTCP)), |
(...skipping 196 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
257 SendAvailableSendWindow(); | 262 SendAvailableSendWindow(); |
258 AckNPackets(2); | 263 AckNPackets(2); |
259 } | 264 } |
260 SendAvailableSendWindow(); | 265 SendAvailableSendWindow(); |
261 QuicByteCount expected_send_window = kDefaultWindowTCP + | 266 QuicByteCount expected_send_window = kDefaultWindowTCP + |
262 (kDefaultTCPMSS * 2 * kNumberOfAcks); | 267 (kDefaultTCPMSS * 2 * kNumberOfAcks); |
263 EXPECT_EQ(expected_send_window, sender_->GetCongestionWindow()); | 268 EXPECT_EQ(expected_send_window, sender_->GetCongestionWindow()); |
264 | 269 |
265 // Lose a packet to exit slow start. | 270 // Lose a packet to exit slow start. |
266 LoseNPackets(1); | 271 LoseNPackets(1); |
| 272 size_t packets_in_recovery_window = expected_send_window / kDefaultTCPMSS; |
267 | 273 |
268 // We should now have fallen out of slow start. | 274 // We should now have fallen out of slow start with a reduced window. |
269 // We expect window to be cut in half by Reno. | 275 expected_send_window *= kRenoBeta; |
270 expected_send_window /= 2; | |
271 EXPECT_EQ(expected_send_window, sender_->GetCongestionWindow()); | 276 EXPECT_EQ(expected_send_window, sender_->GetCongestionWindow()); |
272 | 277 |
273 // Testing Reno phase. | 278 // Recovery phase. We need to ack every packet in the recovery window before |
274 // We need to ack half of the pending packet before we can send again. | 279 // we exit recovery. |
275 size_t number_of_packets_in_window = expected_send_window / kDefaultTCPMSS; | 280 size_t number_of_packets_in_window = expected_send_window / kDefaultTCPMSS; |
276 AckNPackets(number_of_packets_in_window); | 281 DVLOG(1) << "number_packets: " << number_of_packets_in_window; |
| 282 AckNPackets(packets_in_recovery_window); |
| 283 SendAvailableSendWindow(); |
277 EXPECT_EQ(expected_send_window, sender_->GetCongestionWindow()); | 284 EXPECT_EQ(expected_send_window, sender_->GetCongestionWindow()); |
278 | 285 |
279 // We need to ack every packet in the window before we exit recovery. | 286 // We need to ack an entire window before we increase CWND by 1. |
280 for (size_t i = 0; i < number_of_packets_in_window; ++i) { | 287 AckNPackets(number_of_packets_in_window - 2); |
281 AckNPackets(1); | 288 SendAvailableSendWindow(); |
282 SendAvailableSendWindow(); | 289 EXPECT_EQ(expected_send_window, sender_->GetCongestionWindow()); |
283 EXPECT_EQ(expected_send_window, sender_->GetCongestionWindow()); | |
284 } | |
285 | 290 |
286 // We need to ack another window before we increase CWND by 1. | 291 // Next ack should increase cwnd by 1. |
287 for (size_t i = 0; i < number_of_packets_in_window - 2; ++i) { | |
288 AckNPackets(1); | |
289 SendAvailableSendWindow(); | |
290 EXPECT_EQ(expected_send_window, sender_->GetCongestionWindow()); | |
291 } | |
292 | |
293 AckNPackets(1); | 292 AckNPackets(1); |
294 expected_send_window += kDefaultTCPMSS; | 293 expected_send_window += kDefaultTCPMSS; |
295 EXPECT_EQ(expected_send_window, sender_->GetCongestionWindow()); | 294 EXPECT_EQ(expected_send_window, sender_->GetCongestionWindow()); |
296 | 295 |
297 // Now RTO and ensure slow start gets reset. | 296 // Now RTO and ensure slow start gets reset. |
298 EXPECT_TRUE(sender_->hybrid_slow_start().started()); | 297 EXPECT_TRUE(sender_->hybrid_slow_start().started()); |
299 sender_->OnRetransmissionTimeout(true); | 298 sender_->OnRetransmissionTimeout(true); |
300 EXPECT_FALSE(sender_->hybrid_slow_start().started()); | 299 EXPECT_FALSE(sender_->hybrid_slow_start().started()); |
301 } | 300 } |
302 | 301 |
(...skipping 20 matching lines...) Expand all Loading... |
323 SendAvailableSendWindow(); | 322 SendAvailableSendWindow(); |
324 AckNPackets(2); | 323 AckNPackets(2); |
325 } | 324 } |
326 SendAvailableSendWindow(); | 325 SendAvailableSendWindow(); |
327 QuicByteCount expected_send_window = kDefaultWindowTCP + | 326 QuicByteCount expected_send_window = kDefaultWindowTCP + |
328 (kDefaultTCPMSS * 2 * kNumberOfAcks); | 327 (kDefaultTCPMSS * 2 * kNumberOfAcks); |
329 EXPECT_EQ(expected_send_window, sender_->GetCongestionWindow()); | 328 EXPECT_EQ(expected_send_window, sender_->GetCongestionWindow()); |
330 | 329 |
331 LoseNPackets(1); | 330 LoseNPackets(1); |
332 | 331 |
333 // We should now have fallen out of slow start. | 332 // We should now have fallen out of slow start with a reduced window. |
334 // We expect window to be cut in half by Reno. | 333 size_t send_window_before_loss = expected_send_window; |
335 expected_send_window /= 2; | 334 expected_send_window *= kRenoBeta; |
336 EXPECT_EQ(expected_send_window, sender_->GetCongestionWindow()); | 335 EXPECT_EQ(expected_send_window, sender_->GetCongestionWindow()); |
337 | 336 |
338 // Testing TCP proportional rate reduction. | 337 // Testing TCP proportional rate reduction. |
339 // We should send one packet for every two received acks over the remaining | 338 // We should send packets paced over the received acks for the remaining |
340 // 18 outstanding packets. | 339 // outstanding packets. The number of packets before we exit recovery is the |
341 size_t number_of_packets_in_window = expected_send_window / kDefaultTCPMSS; | 340 // original CWND minus the packet that has been lost and the one which |
342 // The number of packets before we exit recovery is the original CWND minus | 341 // triggered the loss. |
343 // the packet that has been lost and the one which triggered the loss. | 342 size_t remaining_packets_in_recovery = |
344 size_t remaining_packets_in_recovery = number_of_packets_in_window * 2 - 1; | 343 send_window_before_loss / kDefaultTCPMSS - 2; |
345 for (size_t i = 0; i < remaining_packets_in_recovery - 1; i += 2) { | 344 |
346 AckNPackets(2); | 345 for (size_t i = 0; i < remaining_packets_in_recovery; ++i) { |
347 EXPECT_TRUE(sender_->TimeUntilSend( | 346 AckNPackets(1); |
348 clock_.Now(), bytes_in_flight_, HAS_RETRANSMITTABLE_DATA).IsZero()); | 347 SendAvailableSendWindow(); |
349 EXPECT_EQ(1, SendAvailableSendWindow()); | |
350 EXPECT_EQ(expected_send_window, sender_->GetCongestionWindow()); | 348 EXPECT_EQ(expected_send_window, sender_->GetCongestionWindow()); |
351 } | 349 } |
352 | 350 |
353 // We need to ack another window before we increase CWND by 1. | 351 // We need to ack another window before we increase CWND by 1. |
| 352 size_t number_of_packets_in_window = expected_send_window / kDefaultTCPMSS; |
354 for (size_t i = 0; i < number_of_packets_in_window; ++i) { | 353 for (size_t i = 0; i < number_of_packets_in_window; ++i) { |
355 AckNPackets(1); | 354 AckNPackets(1); |
356 EXPECT_EQ(1, SendAvailableSendWindow()); | 355 EXPECT_EQ(1, SendAvailableSendWindow()); |
357 EXPECT_EQ(expected_send_window, sender_->GetCongestionWindow()); | 356 EXPECT_EQ(expected_send_window, sender_->GetCongestionWindow()); |
358 } | 357 } |
359 | 358 |
360 AckNPackets(1); | 359 AckNPackets(1); |
361 expected_send_window += kDefaultTCPMSS; | 360 expected_send_window += kDefaultTCPMSS; |
362 EXPECT_EQ(expected_send_window, sender_->GetCongestionWindow()); | 361 EXPECT_EQ(expected_send_window, sender_->GetCongestionWindow()); |
363 } | 362 } |
364 | 363 |
365 TEST_F(TcpCubicSenderTest, SlowStartBurstPacketLossPRR) { | 364 TEST_F(TcpCubicSenderTest, SlowStartBurstPacketLossPRR) { |
366 sender_->SetNumEmulatedConnections(1); | 365 sender_->SetNumEmulatedConnections(1); |
367 // Test based on the second example in RFC6937, though we also implement | 366 // Test based on the second example in RFC6937, though we also implement |
368 // forward acknowledgements, so the first two incoming acks will trigger | 367 // forward acknowledgements, so the first two incoming acks will trigger |
369 // PRR immediately. | 368 // PRR immediately. |
370 // Ack 10 packets in 5 acks to raise the CWND to 20, as in the example. | 369 // Ack 20 packets in 10 acks to raise the CWND to 30. |
371 const int kNumberOfAcks = 5; | 370 const int kNumberOfAcks = 10; |
372 for (int i = 0; i < kNumberOfAcks; ++i) { | 371 for (int i = 0; i < kNumberOfAcks; ++i) { |
373 // Send our full send window. | 372 // Send our full send window. |
374 SendAvailableSendWindow(); | 373 SendAvailableSendWindow(); |
375 AckNPackets(2); | 374 AckNPackets(2); |
376 } | 375 } |
377 SendAvailableSendWindow(); | 376 SendAvailableSendWindow(); |
378 QuicByteCount expected_send_window = kDefaultWindowTCP + | 377 QuicByteCount expected_send_window = kDefaultWindowTCP + |
379 (kDefaultTCPMSS * 2 * kNumberOfAcks); | 378 (kDefaultTCPMSS * 2 * kNumberOfAcks); |
380 EXPECT_EQ(expected_send_window, sender_->GetCongestionWindow()); | 379 EXPECT_EQ(expected_send_window, sender_->GetCongestionWindow()); |
381 | 380 |
382 // Ack a packet with a 15 packet gap, losing 13 of them due to FACK. | 381 // Lose one more than the congestion window reduction, so that after loss, |
383 LoseNPackets(13); | 382 // bytes_in_flight is lesser than the congestion window. |
| 383 size_t send_window_after_loss = kRenoBeta * expected_send_window; |
| 384 size_t num_packets_to_lose = |
| 385 (expected_send_window - send_window_after_loss) / kDefaultTCPMSS + 1; |
| 386 LoseNPackets(num_packets_to_lose); |
384 // Immediately after the loss, ensure at least one packet can be sent. | 387 // Immediately after the loss, ensure at least one packet can be sent. |
385 // Losses without subsequent acks can occur with timer based loss detection. | 388 // Losses without subsequent acks can occur with timer based loss detection. |
386 EXPECT_TRUE(sender_->TimeUntilSend( | 389 EXPECT_TRUE(sender_->TimeUntilSend( |
387 clock_.Now(), bytes_in_flight_, HAS_RETRANSMITTABLE_DATA).IsZero()); | 390 clock_.Now(), bytes_in_flight_, HAS_RETRANSMITTABLE_DATA).IsZero()); |
388 AckNPackets(1); | 391 AckNPackets(1); |
389 | 392 |
390 // We should now have fallen out of slow start. | 393 // We should now have fallen out of slow start with a reduced window. |
391 // We expect window to be cut in half by Reno. | 394 expected_send_window *= kRenoBeta; |
392 expected_send_window /= 2; | |
393 EXPECT_EQ(expected_send_window, sender_->GetCongestionWindow()); | 395 EXPECT_EQ(expected_send_window, sender_->GetCongestionWindow()); |
394 | 396 |
395 // Only 2 packets should be allowed to be sent, per PRR-SSRB | 397 // Only 2 packets should be allowed to be sent, per PRR-SSRB |
396 EXPECT_EQ(2, SendAvailableSendWindow()); | 398 EXPECT_EQ(2, SendAvailableSendWindow()); |
397 | 399 |
398 // Ack the next packet, which triggers another loss. | 400 // Ack the next packet, which triggers another loss. |
399 LoseNPackets(1); | 401 LoseNPackets(1); |
400 AckNPackets(1); | 402 AckNPackets(1); |
401 | 403 |
402 // Send 2 packets to simulate PRR-SSRB. | 404 // Send 2 packets to simulate PRR-SSRB. |
403 EXPECT_EQ(2, SendAvailableSendWindow()); | 405 EXPECT_EQ(2, SendAvailableSendWindow()); |
404 | 406 |
405 // Ack the next packet, which triggers another loss. | 407 // Ack the next packet, which triggers another loss. |
406 LoseNPackets(1); | 408 LoseNPackets(1); |
407 AckNPackets(1); | 409 AckNPackets(1); |
408 | 410 |
409 // Send 2 packets to simulate PRR-SSRB. | 411 // Send 2 packets to simulate PRR-SSRB. |
410 EXPECT_EQ(2, SendAvailableSendWindow()); | 412 EXPECT_EQ(2, SendAvailableSendWindow()); |
411 | 413 |
412 AckNPackets(1); | |
413 EXPECT_EQ(2, SendAvailableSendWindow()); | |
414 | |
415 AckNPackets(1); | |
416 EXPECT_EQ(2, SendAvailableSendWindow()); | |
417 | |
418 // The window should not have changed. | |
419 EXPECT_EQ(expected_send_window, sender_->GetCongestionWindow()); | |
420 | |
421 // Exit recovery and return to sending at the new rate. | 414 // Exit recovery and return to sending at the new rate. |
422 for (int i = 0; i < kNumberOfAcks; ++i) { | 415 for (int i = 0; i < kNumberOfAcks; ++i) { |
423 AckNPackets(1); | 416 AckNPackets(1); |
424 EXPECT_EQ(1, SendAvailableSendWindow()); | 417 EXPECT_EQ(1, SendAvailableSendWindow()); |
425 } | 418 } |
426 } | 419 } |
427 | 420 |
428 TEST_F(TcpCubicSenderTest, RTOCongestionWindowAndRevert) { | 421 TEST_F(TcpCubicSenderTest, RTOCongestionWindowAndRevert) { |
429 EXPECT_EQ(kDefaultWindowTCP, sender_->GetCongestionWindow()); | 422 EXPECT_EQ(kDefaultWindowTCP, sender_->GetCongestionWindow()); |
430 EXPECT_EQ(10000u, sender_->slowstart_threshold()); | 423 EXPECT_EQ(10000u, sender_->slowstart_threshold()); |
(...skipping 171 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
602 SendAvailableSendWindow(); | 595 SendAvailableSendWindow(); |
603 AckNPackets(2); | 596 AckNPackets(2); |
604 } | 597 } |
605 SendAvailableSendWindow(); | 598 SendAvailableSendWindow(); |
606 QuicByteCount expected_send_window = kDefaultWindowTCP + | 599 QuicByteCount expected_send_window = kDefaultWindowTCP + |
607 (kDefaultTCPMSS * 2 * kNumberOfAcks); | 600 (kDefaultTCPMSS * 2 * kNumberOfAcks); |
608 EXPECT_EQ(expected_send_window, sender_->GetCongestionWindow()); | 601 EXPECT_EQ(expected_send_window, sender_->GetCongestionWindow()); |
609 | 602 |
610 LoseNPackets(1); | 603 LoseNPackets(1); |
611 | 604 |
612 // We should now have fallen out of slow start, and window should be cut in | 605 // We should now have fallen out of slow start with a reduced window. |
613 // half by Reno. New cwnd should be 10. | 606 expected_send_window = expected_send_window * sender_->GetRenoBeta(); |
614 expected_send_window /= 2; | |
615 EXPECT_EQ(expected_send_window, sender_->GetCongestionWindow()); | 607 EXPECT_EQ(expected_send_window, sender_->GetCongestionWindow()); |
616 | 608 |
617 // No congestion window growth should occur in recovery phase, i.e., until the | 609 // No congestion window growth should occur in recovery phase, i.e., until the |
618 // currently outstanding 20 packets are acked. | 610 // currently outstanding 20 packets are acked. |
619 for (int i = 0; i < 10; ++i) { | 611 for (int i = 0; i < 10; ++i) { |
620 // Send our full send window. | 612 // Send our full send window. |
621 SendAvailableSendWindow(); | 613 SendAvailableSendWindow(); |
622 EXPECT_TRUE(sender_->InRecovery()); | 614 EXPECT_TRUE(sender_->InRecovery()); |
623 AckNPackets(2); | 615 AckNPackets(2); |
624 EXPECT_EQ(expected_send_window, sender_->GetCongestionWindow()); | 616 EXPECT_EQ(expected_send_window, sender_->GetCongestionWindow()); |
625 } | 617 } |
626 EXPECT_FALSE(sender_->InRecovery()); | 618 EXPECT_FALSE(sender_->InRecovery()); |
627 | 619 |
628 // Out of recovery now. Congestion window should not grow for half an RTT. | 620 // Out of recovery now. Congestion window should not grow for half an RTT. |
| 621 size_t packets_in_send_window = expected_send_window / kDefaultTCPMSS; |
| 622 SendAvailableSendWindow(); |
| 623 AckNPackets(packets_in_send_window / 2 - 2); |
| 624 EXPECT_EQ(expected_send_window, sender_->GetCongestionWindow()); |
| 625 |
| 626 // Next ack should increase congestion window by 1MSS. |
629 SendAvailableSendWindow(); | 627 SendAvailableSendWindow(); |
630 AckNPackets(2); | 628 AckNPackets(2); |
| 629 expected_send_window += kDefaultTCPMSS; |
| 630 packets_in_send_window += 1; |
631 EXPECT_EQ(expected_send_window, sender_->GetCongestionWindow()); | 631 EXPECT_EQ(expected_send_window, sender_->GetCongestionWindow()); |
632 | 632 |
633 // Next ack will be the 5th and should increase congestion window by 1MSS. | 633 // Congestion window should remain steady again for half an RTT. |
| 634 SendAvailableSendWindow(); |
| 635 AckNPackets(packets_in_send_window / 2 - 1); |
| 636 EXPECT_EQ(expected_send_window, sender_->GetCongestionWindow()); |
| 637 |
| 638 // Next ack should cause congestion window to grow by 1MSS. |
| 639 SendAvailableSendWindow(); |
634 AckNPackets(2); | 640 AckNPackets(2); |
635 expected_send_window += kDefaultTCPMSS; | 641 expected_send_window += kDefaultTCPMSS; |
636 EXPECT_EQ(expected_send_window, sender_->GetCongestionWindow()); | 642 EXPECT_EQ(expected_send_window, sender_->GetCongestionWindow()); |
637 | |
638 for (int i = 0; i < 2; ++i) { | |
639 SendAvailableSendWindow(); | |
640 AckNPackets(2); | |
641 EXPECT_EQ(expected_send_window, sender_->GetCongestionWindow()); | |
642 } | |
643 | |
644 // Next ack should cause congestion window to grow by 1MSS. | |
645 AckNPackets(2); | |
646 expected_send_window += kDefaultTCPMSS; | |
647 EXPECT_EQ(expected_send_window, sender_->GetCongestionWindow()); | |
648 } | 643 } |
649 | 644 |
650 TEST_F(TcpCubicSenderTest, 1ConnectionCongestionAvoidanceAtEndOfRecovery) { | 645 TEST_F(TcpCubicSenderTest, 1ConnectionCongestionAvoidanceAtEndOfRecovery) { |
651 sender_->SetNumEmulatedConnections(1); | 646 sender_->SetNumEmulatedConnections(1); |
652 // Ack 10 packets in 5 acks to raise the CWND to 20. | 647 // Ack 10 packets in 5 acks to raise the CWND to 20. |
653 const int kNumberOfAcks = 5; | 648 const int kNumberOfAcks = 5; |
654 for (int i = 0; i < kNumberOfAcks; ++i) { | 649 for (int i = 0; i < kNumberOfAcks; ++i) { |
655 // Send our full send window. | 650 // Send our full send window. |
656 SendAvailableSendWindow(); | 651 SendAvailableSendWindow(); |
657 AckNPackets(2); | 652 AckNPackets(2); |
658 } | 653 } |
659 SendAvailableSendWindow(); | 654 SendAvailableSendWindow(); |
660 QuicByteCount expected_send_window = kDefaultWindowTCP + | 655 QuicByteCount expected_send_window = kDefaultWindowTCP + |
661 (kDefaultTCPMSS * 2 * kNumberOfAcks); | 656 (kDefaultTCPMSS * 2 * kNumberOfAcks); |
662 EXPECT_EQ(expected_send_window, sender_->GetCongestionWindow()); | 657 EXPECT_EQ(expected_send_window, sender_->GetCongestionWindow()); |
663 | 658 |
664 LoseNPackets(1); | 659 LoseNPackets(1); |
665 | 660 |
666 // We should now have fallen out of slow start, and window should be cut in | 661 // We should now have fallen out of slow start with a reduced window. |
667 // half by Reno. New cwnd should be 10. | 662 expected_send_window *= kRenoBeta; |
668 expected_send_window /= 2; | |
669 EXPECT_EQ(expected_send_window, sender_->GetCongestionWindow()); | 663 EXPECT_EQ(expected_send_window, sender_->GetCongestionWindow()); |
670 | 664 |
671 // No congestion window growth should occur in recovery phase, i.e., until the | 665 // No congestion window growth should occur in recovery phase, i.e., until the |
672 // currently outstanding 20 packets are acked. | 666 // currently outstanding 20 packets are acked. |
673 for (int i = 0; i < 10; ++i) { | 667 for (int i = 0; i < 10; ++i) { |
674 // Send our full send window. | 668 // Send our full send window. |
675 SendAvailableSendWindow(); | 669 SendAvailableSendWindow(); |
676 EXPECT_TRUE(sender_->InRecovery()); | 670 EXPECT_TRUE(sender_->InRecovery()); |
677 AckNPackets(2); | 671 AckNPackets(2); |
678 EXPECT_EQ(expected_send_window, sender_->GetCongestionWindow()); | 672 EXPECT_EQ(expected_send_window, sender_->GetCongestionWindow()); |
679 } | 673 } |
680 EXPECT_FALSE(sender_->InRecovery()); | 674 EXPECT_FALSE(sender_->InRecovery()); |
681 | 675 |
682 // Out of recovery now. Congestion window should not grow during RTT. | 676 // Out of recovery now. Congestion window should not grow during RTT. |
683 for (int i = 0; i < 4; ++i) { | 677 for (uint64 i = 0; i < expected_send_window / kDefaultTCPMSS - 2; i += 2) { |
684 // Send our full send window. | 678 // Send our full send window. |
685 SendAvailableSendWindow(); | 679 SendAvailableSendWindow(); |
686 AckNPackets(2); | 680 AckNPackets(2); |
687 EXPECT_EQ(expected_send_window, sender_->GetCongestionWindow()); | 681 EXPECT_EQ(expected_send_window, sender_->GetCongestionWindow()); |
688 } | 682 } |
689 | 683 |
690 // Next ack should cause congestion window to grow by 1MSS. | 684 // Next ack should cause congestion window to grow by 1MSS. |
| 685 SendAvailableSendWindow(); |
691 AckNPackets(2); | 686 AckNPackets(2); |
692 expected_send_window += kDefaultTCPMSS; | 687 expected_send_window += kDefaultTCPMSS; |
693 EXPECT_EQ(expected_send_window, sender_->GetCongestionWindow()); | 688 EXPECT_EQ(expected_send_window, sender_->GetCongestionWindow()); |
694 } | 689 } |
695 | 690 |
696 } // namespace test | 691 } // namespace test |
697 } // namespace net | 692 } // namespace net |
OLD | NEW |