| 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 | 26 |
| 27 // TODO(ianswett): Remove 10000 once b/10075719 is fixed. | 27 // TODO(ianswett): Remove 10000 once b/10075719 is fixed. |
| 28 const QuicTcpCongestionWindow kDefaultMaxCongestionWindowTCP = 10000; | 28 const QuicPacketCount kDefaultMaxCongestionWindowTCP = 10000; |
| 29 | 29 |
| 30 class TcpCubicSenderPeer : public TcpCubicSender { | 30 class TcpCubicSenderPeer : public TcpCubicSender { |
| 31 public: | 31 public: |
| 32 TcpCubicSenderPeer(const QuicClock* clock, | 32 TcpCubicSenderPeer(const QuicClock* clock, |
| 33 bool reno, | 33 bool reno, |
| 34 QuicTcpCongestionWindow max_tcp_congestion_window) | 34 QuicPacketCount max_tcp_congestion_window) |
| 35 : TcpCubicSender( | 35 : TcpCubicSender( |
| 36 clock, &rtt_stats_, reno, max_tcp_congestion_window, &stats_) { | 36 clock, &rtt_stats_, reno, max_tcp_congestion_window, &stats_) { |
| 37 } | 37 } |
| 38 | 38 |
| 39 QuicTcpCongestionWindow congestion_window() { | 39 QuicPacketCount congestion_window() { |
| 40 return congestion_window_; | 40 return congestion_window_; |
| 41 } | 41 } |
| 42 | 42 |
| 43 QuicTcpCongestionWindow slowstart_threshold() { | 43 QuicPacketCount slowstart_threshold() { |
| 44 return slowstart_threshold_; | 44 return slowstart_threshold_; |
| 45 } | 45 } |
| 46 | 46 |
| 47 const HybridSlowStart& hybrid_slow_start() const { | 47 const HybridSlowStart& hybrid_slow_start() const { |
| 48 return hybrid_slow_start_; | 48 return hybrid_slow_start_; |
| 49 } | 49 } |
| 50 | 50 |
| 51 RttStats rtt_stats_; | 51 RttStats rtt_stats_; |
| 52 QuicConnectionStats stats_; | 52 QuicConnectionStats stats_; |
| 53 | |
| 54 using TcpCubicSender::SendWindow; | |
| 55 }; | 53 }; |
| 56 | 54 |
| 57 class TcpCubicSenderTest : public ::testing::Test { | 55 class TcpCubicSenderTest : public ::testing::Test { |
| 58 protected: | 56 protected: |
| 59 TcpCubicSenderTest() | 57 TcpCubicSenderTest() |
| 60 : one_ms_(QuicTime::Delta::FromMilliseconds(1)), | 58 : one_ms_(QuicTime::Delta::FromMilliseconds(1)), |
| 61 sender_(new TcpCubicSenderPeer(&clock_, true, | 59 sender_(new TcpCubicSenderPeer(&clock_, true, |
| 62 kDefaultMaxCongestionWindowTCP)), | 60 kDefaultMaxCongestionWindowTCP)), |
| 63 receiver_(new TcpReceiver()), | 61 receiver_(new TcpReceiver()), |
| 64 sequence_number_(1), | 62 sequence_number_(1), |
| (...skipping 100 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 165 HAS_RETRANSMITTABLE_DATA).IsZero()); | 163 HAS_RETRANSMITTABLE_DATA).IsZero()); |
| 166 // Make sure we can send. | 164 // Make sure we can send. |
| 167 EXPECT_TRUE(sender_->TimeUntilSend(clock_.Now(), | 165 EXPECT_TRUE(sender_->TimeUntilSend(clock_.Now(), |
| 168 0, | 166 0, |
| 169 HAS_RETRANSMITTABLE_DATA).IsZero()); | 167 HAS_RETRANSMITTABLE_DATA).IsZero()); |
| 170 | 168 |
| 171 SendAvailableSendWindow(); | 169 SendAvailableSendWindow(); |
| 172 for (int i = 0; i < kNumberOfAcks; ++i) { | 170 for (int i = 0; i < kNumberOfAcks; ++i) { |
| 173 AckNPackets(2); | 171 AckNPackets(2); |
| 174 } | 172 } |
| 175 QuicByteCount bytes_to_send = sender_->SendWindow(); | 173 QuicByteCount bytes_to_send = sender_->GetCongestionWindow(); |
| 176 // It's expected 2 acks will arrive when the bytes_in_flight are greater than | 174 // It's expected 2 acks will arrive when the bytes_in_flight are greater than |
| 177 // half the CWND. | 175 // half the CWND. |
| 178 EXPECT_EQ(kDefaultWindowTCP + kDefaultTCPMSS * 2 * 2, | 176 EXPECT_EQ(kDefaultWindowTCP + kDefaultTCPMSS * 2 * 2, |
| 179 bytes_to_send); | 177 bytes_to_send); |
| 180 } | 178 } |
| 181 | 179 |
| 182 TEST_F(TcpCubicSenderTest, ExponentialSlowStart) { | 180 TEST_F(TcpCubicSenderTest, ExponentialSlowStart) { |
| 183 const int kNumberOfAcks = 20; | 181 const int kNumberOfAcks = 20; |
| 184 // At startup make sure we can send. | 182 // At startup make sure we can send. |
| 185 EXPECT_TRUE(sender_->TimeUntilSend(clock_.Now(), | 183 EXPECT_TRUE(sender_->TimeUntilSend(clock_.Now(), |
| 186 0, | 184 0, |
| 187 HAS_RETRANSMITTABLE_DATA).IsZero()); | 185 HAS_RETRANSMITTABLE_DATA).IsZero()); |
| 188 // Make sure we can send. | 186 // Make sure we can send. |
| 189 EXPECT_TRUE(sender_->TimeUntilSend(clock_.Now(), | 187 EXPECT_TRUE(sender_->TimeUntilSend(clock_.Now(), |
| 190 0, | 188 0, |
| 191 HAS_RETRANSMITTABLE_DATA).IsZero()); | 189 HAS_RETRANSMITTABLE_DATA).IsZero()); |
| 192 | 190 |
| 193 for (int i = 0; i < kNumberOfAcks; ++i) { | 191 for (int i = 0; i < kNumberOfAcks; ++i) { |
| 194 // Send our full send window. | 192 // Send our full send window. |
| 195 SendAvailableSendWindow(); | 193 SendAvailableSendWindow(); |
| 196 AckNPackets(2); | 194 AckNPackets(2); |
| 197 } | 195 } |
| 198 QuicByteCount bytes_to_send = sender_->SendWindow(); | 196 QuicByteCount bytes_to_send = sender_->GetCongestionWindow(); |
| 199 EXPECT_EQ(kDefaultWindowTCP + kDefaultTCPMSS * 2 * kNumberOfAcks, | 197 EXPECT_EQ(kDefaultWindowTCP + kDefaultTCPMSS * 2 * kNumberOfAcks, |
| 200 bytes_to_send); | 198 bytes_to_send); |
| 201 } | 199 } |
| 202 | 200 |
| 203 TEST_F(TcpCubicSenderTest, SlowStartAckTrain) { | 201 TEST_F(TcpCubicSenderTest, SlowStartAckTrain) { |
| 204 sender_->SetNumEmulatedConnections(1); | 202 sender_->SetNumEmulatedConnections(1); |
| 205 EXPECT_EQ(kDefaultMaxCongestionWindowTCP * kDefaultTCPMSS, | 203 EXPECT_EQ(kDefaultMaxCongestionWindowTCP * kDefaultTCPMSS, |
| 206 sender_->GetSlowStartThreshold()); | 204 sender_->GetSlowStartThreshold()); |
| 207 | 205 |
| 208 // Make sure that we fall out of slow start when we send ACK train longer | 206 // Make sure that we fall out of slow start when we send ACK train longer |
| (...skipping 212 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 421 EXPECT_EQ(expected_send_window, sender_->GetCongestionWindow()); | 419 EXPECT_EQ(expected_send_window, sender_->GetCongestionWindow()); |
| 422 | 420 |
| 423 // Exit recovery and return to sending at the new rate. | 421 // Exit recovery and return to sending at the new rate. |
| 424 for (int i = 0; i < kNumberOfAcks; ++i) { | 422 for (int i = 0; i < kNumberOfAcks; ++i) { |
| 425 AckNPackets(1); | 423 AckNPackets(1); |
| 426 EXPECT_EQ(1, SendAvailableSendWindow()); | 424 EXPECT_EQ(1, SendAvailableSendWindow()); |
| 427 } | 425 } |
| 428 } | 426 } |
| 429 | 427 |
| 430 TEST_F(TcpCubicSenderTest, RTOCongestionWindowAndRevert) { | 428 TEST_F(TcpCubicSenderTest, RTOCongestionWindowAndRevert) { |
| 431 EXPECT_EQ(kDefaultWindowTCP, sender_->SendWindow()); | 429 EXPECT_EQ(kDefaultWindowTCP, sender_->GetCongestionWindow()); |
| 432 EXPECT_EQ(10000u, sender_->slowstart_threshold()); | 430 EXPECT_EQ(10000u, sender_->slowstart_threshold()); |
| 433 | 431 |
| 434 // Expect the window to decrease to the minimum once the RTO fires | 432 // Expect the window to decrease to the minimum once the RTO fires |
| 435 // and slow start threshold to be set to 1/2 of the CWND. | 433 // and slow start threshold to be set to 1/2 of the CWND. |
| 436 sender_->OnRetransmissionTimeout(true); | 434 sender_->OnRetransmissionTimeout(true); |
| 437 EXPECT_EQ(2 * kDefaultTCPMSS, sender_->SendWindow()); | 435 EXPECT_EQ(2 * kDefaultTCPMSS, sender_->GetCongestionWindow()); |
| 438 EXPECT_EQ(5u, sender_->slowstart_threshold()); | 436 EXPECT_EQ(5u, sender_->slowstart_threshold()); |
| 439 | 437 |
| 440 // Now repair the RTO and ensure the slowstart threshold reverts. | 438 // Now repair the RTO and ensure the slowstart threshold reverts. |
| 441 sender_->RevertRetransmissionTimeout(); | 439 sender_->RevertRetransmissionTimeout(); |
| 442 EXPECT_EQ(kDefaultWindowTCP, sender_->SendWindow()); | 440 EXPECT_EQ(kDefaultWindowTCP, sender_->GetCongestionWindow()); |
| 443 EXPECT_EQ(10000u, sender_->slowstart_threshold()); | 441 EXPECT_EQ(10000u, sender_->slowstart_threshold()); |
| 444 } | 442 } |
| 445 | 443 |
| 446 TEST_F(TcpCubicSenderTest, RTOCongestionWindowNoRetransmission) { | 444 TEST_F(TcpCubicSenderTest, RTOCongestionWindowNoRetransmission) { |
| 447 EXPECT_EQ(kDefaultWindowTCP, sender_->SendWindow()); | 445 EXPECT_EQ(kDefaultWindowTCP, sender_->GetCongestionWindow()); |
| 448 | 446 |
| 449 // Expect the window to remain unchanged if the RTO fires but no | 447 // Expect the window to remain unchanged if the RTO fires but no |
| 450 // packets are retransmitted. | 448 // packets are retransmitted. |
| 451 sender_->OnRetransmissionTimeout(false); | 449 sender_->OnRetransmissionTimeout(false); |
| 452 EXPECT_EQ(kDefaultWindowTCP, sender_->SendWindow()); | 450 EXPECT_EQ(kDefaultWindowTCP, sender_->GetCongestionWindow()); |
| 453 } | 451 } |
| 454 | 452 |
| 455 TEST_F(TcpCubicSenderTest, RetransmissionDelay) { | 453 TEST_F(TcpCubicSenderTest, RetransmissionDelay) { |
| 456 const int64 kRttMs = 10; | 454 const int64 kRttMs = 10; |
| 457 const int64 kDeviationMs = 3; | 455 const int64 kDeviationMs = 3; |
| 458 EXPECT_EQ(QuicTime::Delta::Zero(), sender_->RetransmissionDelay()); | 456 EXPECT_EQ(QuicTime::Delta::Zero(), sender_->RetransmissionDelay()); |
| 459 | 457 |
| 460 sender_->rtt_stats_.UpdateRtt(QuicTime::Delta::FromMilliseconds(kRttMs), | 458 sender_->rtt_stats_.UpdateRtt(QuicTime::Delta::FromMilliseconds(kRttMs), |
| 461 QuicTime::Delta::Zero(), clock_.Now()); | 459 QuicTime::Delta::Zero(), clock_.Now()); |
| 462 | 460 |
| (...skipping 19 matching lines...) Expand all Loading... |
| 482 EXPECT_NEAR(expected_delay.ToMilliseconds(), | 480 EXPECT_NEAR(expected_delay.ToMilliseconds(), |
| 483 sender_->RetransmissionDelay().ToMilliseconds(), | 481 sender_->RetransmissionDelay().ToMilliseconds(), |
| 484 1); | 482 1); |
| 485 EXPECT_EQ(static_cast<int64>( | 483 EXPECT_EQ(static_cast<int64>( |
| 486 sender_->GetCongestionWindow() * kNumMicrosPerSecond / | 484 sender_->GetCongestionWindow() * kNumMicrosPerSecond / |
| 487 sender_->rtt_stats_.SmoothedRtt().ToMicroseconds()), | 485 sender_->rtt_stats_.SmoothedRtt().ToMicroseconds()), |
| 488 sender_->BandwidthEstimate().ToBytesPerSecond()); | 486 sender_->BandwidthEstimate().ToBytesPerSecond()); |
| 489 } | 487 } |
| 490 | 488 |
| 491 TEST_F(TcpCubicSenderTest, SlowStartMaxSendWindow) { | 489 TEST_F(TcpCubicSenderTest, SlowStartMaxSendWindow) { |
| 492 const QuicTcpCongestionWindow kMaxCongestionWindowTCP = 50; | 490 const QuicPacketCount kMaxCongestionWindowTCP = 50; |
| 493 const int kNumberOfAcks = 100; | 491 const int kNumberOfAcks = 100; |
| 494 sender_.reset( | 492 sender_.reset( |
| 495 new TcpCubicSenderPeer(&clock_, false, kMaxCongestionWindowTCP)); | 493 new TcpCubicSenderPeer(&clock_, false, kMaxCongestionWindowTCP)); |
| 496 | 494 |
| 497 for (int i = 0; i < kNumberOfAcks; ++i) { | 495 for (int i = 0; i < kNumberOfAcks; ++i) { |
| 498 // Send our full send window. | 496 // Send our full send window. |
| 499 SendAvailableSendWindow(); | 497 SendAvailableSendWindow(); |
| 500 AckNPackets(2); | 498 AckNPackets(2); |
| 501 } | 499 } |
| 502 QuicByteCount expected_send_window = | 500 QuicByteCount expected_send_window = |
| 503 kMaxCongestionWindowTCP * kDefaultTCPMSS; | 501 kMaxCongestionWindowTCP * kDefaultTCPMSS; |
| 504 EXPECT_EQ(expected_send_window, sender_->GetCongestionWindow()); | 502 EXPECT_EQ(expected_send_window, sender_->GetCongestionWindow()); |
| 505 } | 503 } |
| 506 | 504 |
| 507 TEST_F(TcpCubicSenderTest, TcpRenoMaxCongestionWindow) { | 505 TEST_F(TcpCubicSenderTest, TcpRenoMaxCongestionWindow) { |
| 508 const QuicTcpCongestionWindow kMaxCongestionWindowTCP = 50; | 506 const QuicPacketCount kMaxCongestionWindowTCP = 50; |
| 509 const int kNumberOfAcks = 1000; | 507 const int kNumberOfAcks = 1000; |
| 510 sender_.reset( | 508 sender_.reset( |
| 511 new TcpCubicSenderPeer(&clock_, true, kMaxCongestionWindowTCP)); | 509 new TcpCubicSenderPeer(&clock_, true, kMaxCongestionWindowTCP)); |
| 512 | 510 |
| 513 SendAvailableSendWindow(); | 511 SendAvailableSendWindow(); |
| 514 AckNPackets(2); | 512 AckNPackets(2); |
| 515 // Make sure we fall out of slow start. | 513 // Make sure we fall out of slow start. |
| 516 LoseNPackets(1); | 514 LoseNPackets(1); |
| 517 | 515 |
| 518 for (int i = 0; i < kNumberOfAcks; ++i) { | 516 for (int i = 0; i < kNumberOfAcks; ++i) { |
| 519 // Send our full send window. | 517 // Send our full send window. |
| 520 SendAvailableSendWindow(); | 518 SendAvailableSendWindow(); |
| 521 AckNPackets(2); | 519 AckNPackets(2); |
| 522 } | 520 } |
| 523 | 521 |
| 524 QuicByteCount expected_send_window = | 522 QuicByteCount expected_send_window = |
| 525 kMaxCongestionWindowTCP * kDefaultTCPMSS; | 523 kMaxCongestionWindowTCP * kDefaultTCPMSS; |
| 526 EXPECT_EQ(expected_send_window, sender_->GetCongestionWindow()); | 524 EXPECT_EQ(expected_send_window, sender_->GetCongestionWindow()); |
| 527 } | 525 } |
| 528 | 526 |
| 529 TEST_F(TcpCubicSenderTest, TcpCubicMaxCongestionWindow) { | 527 TEST_F(TcpCubicSenderTest, TcpCubicMaxCongestionWindow) { |
| 530 const QuicTcpCongestionWindow kMaxCongestionWindowTCP = 50; | 528 const QuicPacketCount kMaxCongestionWindowTCP = 50; |
| 531 // Set to 10000 to compensate for small cubic alpha. | 529 // Set to 10000 to compensate for small cubic alpha. |
| 532 const int kNumberOfAcks = 10000; | 530 const int kNumberOfAcks = 10000; |
| 533 | 531 |
| 534 sender_.reset( | 532 sender_.reset( |
| 535 new TcpCubicSenderPeer(&clock_, false, kMaxCongestionWindowTCP)); | 533 new TcpCubicSenderPeer(&clock_, false, kMaxCongestionWindowTCP)); |
| 536 | 534 |
| 537 SendAvailableSendWindow(); | 535 SendAvailableSendWindow(); |
| 538 AckNPackets(2); | 536 AckNPackets(2); |
| 539 // Make sure we fall out of slow start. | 537 // Make sure we fall out of slow start. |
| 540 LoseNPackets(1); | 538 LoseNPackets(1); |
| (...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 572 sequence_number_++, kDefaultTCPMSS, | 570 sequence_number_++, kDefaultTCPMSS, |
| 573 NO_RETRANSMITTABLE_DATA)); | 571 NO_RETRANSMITTABLE_DATA)); |
| 574 | 572 |
| 575 // Send a data packet with retransmittable data, and ensure it is tracked. | 573 // Send a data packet with retransmittable data, and ensure it is tracked. |
| 576 EXPECT_TRUE(sender_->OnPacketSent(clock_.Now(), bytes_in_flight_, | 574 EXPECT_TRUE(sender_->OnPacketSent(clock_.Now(), bytes_in_flight_, |
| 577 sequence_number_++, kDefaultTCPMSS, | 575 sequence_number_++, kDefaultTCPMSS, |
| 578 HAS_RETRANSMITTABLE_DATA)); | 576 HAS_RETRANSMITTABLE_DATA)); |
| 579 } | 577 } |
| 580 | 578 |
| 581 TEST_F(TcpCubicSenderTest, ConfigureMaxInitialWindow) { | 579 TEST_F(TcpCubicSenderTest, ConfigureMaxInitialWindow) { |
| 582 QuicTcpCongestionWindow congestion_window = sender_->congestion_window(); | 580 QuicPacketCount congestion_window = sender_->congestion_window(); |
| 583 QuicConfig config; | 581 QuicConfig config; |
| 584 QuicConfigPeer::SetReceivedInitialWindow(&config, 2 * congestion_window); | 582 QuicConfigPeer::SetReceivedInitialWindow(&config, 2 * congestion_window); |
| 585 | 583 |
| 586 sender_->SetFromConfig(config, true); | 584 sender_->SetFromConfig(config, true); |
| 587 EXPECT_EQ(2 * congestion_window, sender_->congestion_window()); | 585 EXPECT_EQ(2 * congestion_window, sender_->congestion_window()); |
| 588 | 586 |
| 589 // Verify that kCOPT: kIW10 forces the congestion window to the | 587 // Verify that kCOPT: kIW10 forces the congestion window to the |
| 590 // default of 10 regardless of ReceivedInitialWindow. | 588 // default of 10 regardless of ReceivedInitialWindow. |
| 591 QuicTagVector options; | 589 QuicTagVector options; |
| 592 options.push_back(kIW10); | 590 options.push_back(kIW10); |
| (...skipping 97 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 690 } | 688 } |
| 691 | 689 |
| 692 // Next ack should cause congestion window to grow by 1MSS. | 690 // Next ack should cause congestion window to grow by 1MSS. |
| 693 AckNPackets(2); | 691 AckNPackets(2); |
| 694 expected_send_window += kDefaultTCPMSS; | 692 expected_send_window += kDefaultTCPMSS; |
| 695 EXPECT_EQ(expected_send_window, sender_->GetCongestionWindow()); | 693 EXPECT_EQ(expected_send_window, sender_->GetCongestionWindow()); |
| 696 } | 694 } |
| 697 | 695 |
| 698 } // namespace test | 696 } // namespace test |
| 699 } // namespace net | 697 } // namespace net |
| OLD | NEW |