| 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 uint32 kDefaultWindowTCP = kDefaultInitialWindow * kDefaultTCPMSS; | 24 // TODO(ianswett): A number of theses tests were written with the assumption of |
| 25 // an initial CWND of 10. They have carefully calculated values which should be |
| 26 // updated to be based on kInitialCongestionWindowInsecure. |
| 27 const uint32 kInitialCongestionWindowPackets = 10; |
| 28 const uint32 kDefaultWindowTCP = |
| 29 kInitialCongestionWindowPackets * kDefaultTCPMSS; |
| 25 const float kRenoBeta = 0.7f; // Reno backoff factor. | 30 const float kRenoBeta = 0.7f; // Reno backoff factor. |
| 26 | 31 |
| 27 // TODO(ianswett): Remove 10000 once b/10075719 is fixed. | |
| 28 const QuicPacketCount kDefaultMaxCongestionWindowTCP = 10000; | |
| 29 | |
| 30 class TcpCubicSenderPeer : public TcpCubicSender { | 32 class TcpCubicSenderPeer : public TcpCubicSender { |
| 31 public: | 33 public: |
| 32 TcpCubicSenderPeer(const QuicClock* clock, | 34 TcpCubicSenderPeer(const QuicClock* clock, |
| 33 bool reno, | 35 bool reno, |
| 34 QuicPacketCount max_tcp_congestion_window) | 36 QuicPacketCount max_tcp_congestion_window) |
| 35 : TcpCubicSender( | 37 : TcpCubicSender( |
| 36 clock, &rtt_stats_, reno, max_tcp_congestion_window, &stats_) { | 38 clock, &rtt_stats_, reno, kInitialCongestionWindowPackets, |
| 39 max_tcp_congestion_window, &stats_) { |
| 37 } | 40 } |
| 38 | 41 |
| 39 QuicPacketCount congestion_window() { | 42 QuicPacketCount congestion_window() { |
| 40 return congestion_window_; | 43 return congestion_window_; |
| 41 } | 44 } |
| 42 | 45 |
| 43 QuicPacketCount slowstart_threshold() { | 46 QuicPacketCount slowstart_threshold() { |
| 44 return slowstart_threshold_; | 47 return slowstart_threshold_; |
| 45 } | 48 } |
| 46 | 49 |
| 47 const HybridSlowStart& hybrid_slow_start() const { | 50 const HybridSlowStart& hybrid_slow_start() const { |
| 48 return hybrid_slow_start_; | 51 return hybrid_slow_start_; |
| 49 } | 52 } |
| 50 | 53 |
| 51 float GetRenoBeta() const { | 54 float GetRenoBeta() const { |
| 52 return RenoBeta(); | 55 return RenoBeta(); |
| 53 } | 56 } |
| 54 | 57 |
| 55 RttStats rtt_stats_; | 58 RttStats rtt_stats_; |
| 56 QuicConnectionStats stats_; | 59 QuicConnectionStats stats_; |
| 57 }; | 60 }; |
| 58 | 61 |
| 59 class TcpCubicSenderTest : public ::testing::Test { | 62 class TcpCubicSenderTest : public ::testing::Test { |
| 60 protected: | 63 protected: |
| 61 TcpCubicSenderTest() | 64 TcpCubicSenderTest() |
| 62 : one_ms_(QuicTime::Delta::FromMilliseconds(1)), | 65 : one_ms_(QuicTime::Delta::FromMilliseconds(1)), |
| 63 sender_(new TcpCubicSenderPeer(&clock_, true, | 66 sender_(new TcpCubicSenderPeer(&clock_, true, |
| 64 kDefaultMaxCongestionWindowTCP)), | 67 kMaxTcpCongestionWindow)), |
| 65 receiver_(new TcpReceiver()), | 68 receiver_(new TcpReceiver()), |
| 66 sequence_number_(1), | 69 sequence_number_(1), |
| 67 acked_sequence_number_(0), | 70 acked_sequence_number_(0), |
| 68 bytes_in_flight_(0) { | 71 bytes_in_flight_(0) { |
| 69 standard_packet_.bytes_sent = kDefaultTCPMSS; | 72 standard_packet_.bytes_sent = kDefaultTCPMSS; |
| 70 } | 73 } |
| 71 | 74 |
| 72 int SendAvailableSendWindow() { | 75 int SendAvailableSendWindow() { |
| 73 // Send as long as TimeUntilSend returns Zero. | 76 // Send as long as TimeUntilSend returns Zero. |
| 74 int packets_sent = 0; | 77 int packets_sent = 0; |
| (...skipping 127 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 202 const QuicByteCount cwnd = sender_->GetCongestionWindow(); | 205 const QuicByteCount cwnd = sender_->GetCongestionWindow(); |
| 203 EXPECT_EQ(kDefaultWindowTCP + kDefaultTCPMSS * 2 * kNumberOfAcks, cwnd); | 206 EXPECT_EQ(kDefaultWindowTCP + kDefaultTCPMSS * 2 * kNumberOfAcks, cwnd); |
| 204 EXPECT_FALSE(sender_->HasReliableBandwidthEstimate()); | 207 EXPECT_FALSE(sender_->HasReliableBandwidthEstimate()); |
| 205 EXPECT_EQ(QuicBandwidth::FromBytesAndTimeDelta( | 208 EXPECT_EQ(QuicBandwidth::FromBytesAndTimeDelta( |
| 206 cwnd, sender_->rtt_stats_.smoothed_rtt()), | 209 cwnd, sender_->rtt_stats_.smoothed_rtt()), |
| 207 sender_->BandwidthEstimate()); | 210 sender_->BandwidthEstimate()); |
| 208 } | 211 } |
| 209 | 212 |
| 210 TEST_F(TcpCubicSenderTest, SlowStartAckTrain) { | 213 TEST_F(TcpCubicSenderTest, SlowStartAckTrain) { |
| 211 sender_->SetNumEmulatedConnections(1); | 214 sender_->SetNumEmulatedConnections(1); |
| 212 EXPECT_EQ(kDefaultMaxCongestionWindowTCP * kDefaultTCPMSS, | 215 EXPECT_EQ(kMaxTcpCongestionWindow * kDefaultTCPMSS, |
| 213 sender_->GetSlowStartThreshold()); | 216 sender_->GetSlowStartThreshold()); |
| 214 | 217 |
| 215 // Make sure that we fall out of slow start when we send ACK train longer | 218 // Make sure that we fall out of slow start when we send ACK train longer |
| 216 // than half the RTT, in this test case 30ms, which is more than 30 calls to | 219 // than half the RTT, in this test case 30ms, which is more than 30 calls to |
| 217 // Ack2Packets in one round. | 220 // Ack2Packets in one round. |
| 218 // Since we start at 10 packet first round will be 5 second round 10 etc | 221 // Since we start at 10 packet first round will be 5 second round 10 etc |
| 219 // Hence we should pass 30 at 65 = 5 + 10 + 20 + 30 | 222 // Hence we should pass 30 at 65 = 5 + 10 + 20 + 30 |
| 220 const int kNumberOfAcks = 65; | 223 const int kNumberOfAcks = 65; |
| 221 for (int i = 0; i < kNumberOfAcks; ++i) { | 224 for (int i = 0; i < kNumberOfAcks; ++i) { |
| 222 // Send our full send window. | 225 // Send our full send window. |
| (...skipping 75 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 298 EXPECT_EQ(expected_send_window, sender_->GetCongestionWindow()); | 301 EXPECT_EQ(expected_send_window, sender_->GetCongestionWindow()); |
| 299 | 302 |
| 300 // Now RTO and ensure slow start gets reset. | 303 // Now RTO and ensure slow start gets reset. |
| 301 EXPECT_TRUE(sender_->hybrid_slow_start().started()); | 304 EXPECT_TRUE(sender_->hybrid_slow_start().started()); |
| 302 sender_->OnRetransmissionTimeout(true); | 305 sender_->OnRetransmissionTimeout(true); |
| 303 EXPECT_FALSE(sender_->hybrid_slow_start().started()); | 306 EXPECT_FALSE(sender_->hybrid_slow_start().started()); |
| 304 } | 307 } |
| 305 | 308 |
| 306 TEST_F(TcpCubicSenderTest, NoPRRWhenLessThanOnePacketInFlight) { | 309 TEST_F(TcpCubicSenderTest, NoPRRWhenLessThanOnePacketInFlight) { |
| 307 SendAvailableSendWindow(); | 310 SendAvailableSendWindow(); |
| 308 LoseNPackets(kDefaultInitialWindow - 1); | 311 LoseNPackets(kInitialCongestionWindowPackets - 1); |
| 309 AckNPackets(1); | 312 AckNPackets(1); |
| 310 // PRR will allow 2 packets for every ack during recovery. | 313 // PRR will allow 2 packets for every ack during recovery. |
| 311 EXPECT_EQ(2, SendAvailableSendWindow()); | 314 EXPECT_EQ(2, SendAvailableSendWindow()); |
| 312 // Simulate abandoning all packets by supplying a bytes_in_flight of 0. | 315 // Simulate abandoning all packets by supplying a bytes_in_flight of 0. |
| 313 // PRR should now allow a packet to be sent, even though prr's state | 316 // PRR should now allow a packet to be sent, even though prr's state |
| 314 // variables believe it has sent enough packets. | 317 // variables believe it has sent enough packets. |
| 315 EXPECT_EQ(QuicTime::Delta::Zero(), | 318 EXPECT_EQ(QuicTime::Delta::Zero(), |
| 316 sender_->TimeUntilSend(clock_.Now(), 0, HAS_RETRANSMITTABLE_DATA)); | 319 sender_->TimeUntilSend(clock_.Now(), 0, HAS_RETRANSMITTABLE_DATA)); |
| 317 } | 320 } |
| 318 | 321 |
| (...skipping 98 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 417 | 420 |
| 418 // Exit recovery and return to sending at the new rate. | 421 // Exit recovery and return to sending at the new rate. |
| 419 for (int i = 0; i < kNumberOfAcks; ++i) { | 422 for (int i = 0; i < kNumberOfAcks; ++i) { |
| 420 AckNPackets(1); | 423 AckNPackets(1); |
| 421 EXPECT_EQ(1, SendAvailableSendWindow()); | 424 EXPECT_EQ(1, SendAvailableSendWindow()); |
| 422 } | 425 } |
| 423 } | 426 } |
| 424 | 427 |
| 425 TEST_F(TcpCubicSenderTest, RTOCongestionWindowAndRevert) { | 428 TEST_F(TcpCubicSenderTest, RTOCongestionWindowAndRevert) { |
| 426 EXPECT_EQ(kDefaultWindowTCP, sender_->GetCongestionWindow()); | 429 EXPECT_EQ(kDefaultWindowTCP, sender_->GetCongestionWindow()); |
| 427 EXPECT_EQ(10000u, sender_->slowstart_threshold()); | 430 EXPECT_EQ(kMaxTcpCongestionWindow, sender_->slowstart_threshold()); |
| 428 | 431 |
| 429 // 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 |
| 430 // 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. |
| 431 sender_->OnRetransmissionTimeout(true); | 434 sender_->OnRetransmissionTimeout(true); |
| 432 EXPECT_EQ(2 * kDefaultTCPMSS, sender_->GetCongestionWindow()); | 435 EXPECT_EQ(2 * kDefaultTCPMSS, sender_->GetCongestionWindow()); |
| 433 EXPECT_EQ(5u, sender_->slowstart_threshold()); | 436 EXPECT_EQ(5u, sender_->slowstart_threshold()); |
| 434 | 437 |
| 435 // Now repair the RTO and ensure the slowstart threshold reverts. | 438 // Now repair the RTO and ensure the slowstart threshold reverts. |
| 436 sender_->RevertRetransmissionTimeout(); | 439 sender_->RevertRetransmissionTimeout(); |
| 437 EXPECT_EQ(kDefaultWindowTCP, sender_->GetCongestionWindow()); | 440 EXPECT_EQ(kDefaultWindowTCP, sender_->GetCongestionWindow()); |
| 438 EXPECT_EQ(10000u, sender_->slowstart_threshold()); | 441 EXPECT_EQ(kMaxTcpCongestionWindow, sender_->slowstart_threshold()); |
| 439 } | 442 } |
| 440 | 443 |
| 441 TEST_F(TcpCubicSenderTest, RTOCongestionWindowNoRetransmission) { | 444 TEST_F(TcpCubicSenderTest, RTOCongestionWindowNoRetransmission) { |
| 442 EXPECT_EQ(kDefaultWindowTCP, sender_->GetCongestionWindow()); | 445 EXPECT_EQ(kDefaultWindowTCP, sender_->GetCongestionWindow()); |
| 443 | 446 |
| 444 // 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 |
| 445 // packets are retransmitted. | 448 // packets are retransmitted. |
| 446 sender_->OnRetransmissionTimeout(false); | 449 sender_->OnRetransmissionTimeout(false); |
| 447 EXPECT_EQ(kDefaultWindowTCP, sender_->GetCongestionWindow()); | 450 EXPECT_EQ(kDefaultWindowTCP, sender_->GetCongestionWindow()); |
| 448 } | 451 } |
| (...skipping 118 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 567 sequence_number_++, kDefaultTCPMSS, | 570 sequence_number_++, kDefaultTCPMSS, |
| 568 NO_RETRANSMITTABLE_DATA)); | 571 NO_RETRANSMITTABLE_DATA)); |
| 569 | 572 |
| 570 // 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. |
| 571 EXPECT_TRUE(sender_->OnPacketSent(clock_.Now(), bytes_in_flight_, | 574 EXPECT_TRUE(sender_->OnPacketSent(clock_.Now(), bytes_in_flight_, |
| 572 sequence_number_++, kDefaultTCPMSS, | 575 sequence_number_++, kDefaultTCPMSS, |
| 573 HAS_RETRANSMITTABLE_DATA)); | 576 HAS_RETRANSMITTABLE_DATA)); |
| 574 } | 577 } |
| 575 | 578 |
| 576 TEST_F(TcpCubicSenderTest, ConfigureMaxInitialWindow) { | 579 TEST_F(TcpCubicSenderTest, ConfigureMaxInitialWindow) { |
| 577 QuicPacketCount congestion_window = sender_->congestion_window(); | |
| 578 QuicConfig config; | 580 QuicConfig config; |
| 579 QuicConfigPeer::SetReceivedInitialWindow(&config, 2 * congestion_window); | |
| 580 | 581 |
| 581 sender_->SetFromConfig(config, true); | 582 // Verify that kCOPT: kIW10 forces the congestion window to the default of 10. |
| 582 EXPECT_EQ(2 * congestion_window, sender_->congestion_window()); | |
| 583 | |
| 584 // Verify that kCOPT: kIW10 forces the congestion window to the | |
| 585 // default of 10 regardless of ReceivedInitialWindow. | |
| 586 QuicTagVector options; | 583 QuicTagVector options; |
| 587 options.push_back(kIW10); | 584 options.push_back(kIW10); |
| 588 QuicConfigPeer::SetReceivedConnectionOptions(&config, options); | 585 QuicConfigPeer::SetReceivedConnectionOptions(&config, options); |
| 589 sender_->SetFromConfig(config, true); | 586 sender_->SetFromConfig(config, |
| 590 EXPECT_EQ(congestion_window, sender_->congestion_window()); | 587 /* is_server= */ true, |
| 588 /* using_pacing= */ false); |
| 589 EXPECT_EQ(10u, sender_->congestion_window()); |
| 590 } |
| 591 |
| 592 TEST_F(TcpCubicSenderTest, DisableAckTrainDetectionWithPacing) { |
| 593 EXPECT_TRUE(sender_->hybrid_slow_start().ack_train_detection()); |
| 594 |
| 595 QuicConfig config; |
| 596 sender_->SetFromConfig(config, |
| 597 /* is_server= */ true, |
| 598 /* using_pacing= */ true); |
| 599 EXPECT_FALSE(sender_->hybrid_slow_start().ack_train_detection()); |
| 591 } | 600 } |
| 592 | 601 |
| 593 TEST_F(TcpCubicSenderTest, 2ConnectionCongestionAvoidanceAtEndOfRecovery) { | 602 TEST_F(TcpCubicSenderTest, 2ConnectionCongestionAvoidanceAtEndOfRecovery) { |
| 594 sender_->SetNumEmulatedConnections(2); | 603 sender_->SetNumEmulatedConnections(2); |
| 595 // Ack 10 packets in 5 acks to raise the CWND to 20. | 604 // Ack 10 packets in 5 acks to raise the CWND to 20. |
| 596 const int kNumberOfAcks = 5; | 605 const int kNumberOfAcks = 5; |
| 597 for (int i = 0; i < kNumberOfAcks; ++i) { | 606 for (int i = 0; i < kNumberOfAcks; ++i) { |
| 598 // Send our full send window. | 607 // Send our full send window. |
| 599 SendAvailableSendWindow(); | 608 SendAvailableSendWindow(); |
| 600 AckNPackets(2); | 609 AckNPackets(2); |
| (...skipping 86 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 687 | 696 |
| 688 // Next ack should cause congestion window to grow by 1MSS. | 697 // Next ack should cause congestion window to grow by 1MSS. |
| 689 SendAvailableSendWindow(); | 698 SendAvailableSendWindow(); |
| 690 AckNPackets(2); | 699 AckNPackets(2); |
| 691 expected_send_window += kDefaultTCPMSS; | 700 expected_send_window += kDefaultTCPMSS; |
| 692 EXPECT_EQ(expected_send_window, sender_->GetCongestionWindow()); | 701 EXPECT_EQ(expected_send_window, sender_->GetCongestionWindow()); |
| 693 } | 702 } |
| 694 | 703 |
| 695 } // namespace test | 704 } // namespace test |
| 696 } // namespace net | 705 } // namespace net |
| OLD | NEW |