| 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 |