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" |
(...skipping 12 matching lines...) Expand all Loading... |
23 // TODO(ianswett): A number of theses tests were written with the assumption of | 23 // TODO(ianswett): A number of theses tests were written with the assumption of |
24 // an initial CWND of 10. They have carefully calculated values which should be | 24 // an initial CWND of 10. They have carefully calculated values which should be |
25 // updated to be based on kInitialCongestionWindowInsecure. | 25 // updated to be based on kInitialCongestionWindowInsecure. |
26 const uint32 kInitialCongestionWindowPackets = 10; | 26 const uint32 kInitialCongestionWindowPackets = 10; |
27 const uint32 kDefaultWindowTCP = | 27 const uint32 kDefaultWindowTCP = |
28 kInitialCongestionWindowPackets * kDefaultTCPMSS; | 28 kInitialCongestionWindowPackets * kDefaultTCPMSS; |
29 const float kRenoBeta = 0.7f; // Reno backoff factor. | 29 const float kRenoBeta = 0.7f; // Reno backoff factor. |
30 | 30 |
31 class TcpCubicSenderPeer : public TcpCubicSender { | 31 class TcpCubicSenderPeer : public TcpCubicSender { |
32 public: | 32 public: |
33 TcpCubicSenderPeer(const QuicClock* clock, bool reno) | 33 TcpCubicSenderPeer(const QuicClock* clock, |
| 34 bool reno, |
| 35 QuicPacketCount max_tcp_congestion_window) |
34 : TcpCubicSender(clock, | 36 : TcpCubicSender(clock, |
35 &rtt_stats_, | 37 &rtt_stats_, |
36 reno, | 38 reno, |
37 kInitialCongestionWindowPackets, | 39 kInitialCongestionWindowPackets, |
| 40 max_tcp_congestion_window, |
38 &stats_) {} | 41 &stats_) {} |
39 | 42 |
40 QuicPacketCount congestion_window() { | 43 QuicPacketCount congestion_window() { |
41 return congestion_window_; | 44 return congestion_window_; |
42 } | 45 } |
43 | 46 |
44 QuicPacketCount slowstart_threshold() { | 47 QuicPacketCount slowstart_threshold() { |
45 return slowstart_threshold_; | 48 return slowstart_threshold_; |
46 } | 49 } |
47 | 50 |
48 const HybridSlowStart& hybrid_slow_start() const { | 51 const HybridSlowStart& hybrid_slow_start() const { |
49 return hybrid_slow_start_; | 52 return hybrid_slow_start_; |
50 } | 53 } |
51 | 54 |
52 float GetRenoBeta() const { | 55 float GetRenoBeta() const { |
53 return RenoBeta(); | 56 return RenoBeta(); |
54 } | 57 } |
55 | 58 |
56 RttStats rtt_stats_; | 59 RttStats rtt_stats_; |
57 QuicConnectionStats stats_; | 60 QuicConnectionStats stats_; |
58 }; | 61 }; |
59 | 62 |
60 class TcpCubicSenderTest : public ::testing::Test { | 63 class TcpCubicSenderTest : public ::testing::Test { |
61 protected: | 64 protected: |
62 TcpCubicSenderTest() | 65 TcpCubicSenderTest() |
63 : one_ms_(QuicTime::Delta::FromMilliseconds(1)), | 66 : one_ms_(QuicTime::Delta::FromMilliseconds(1)), |
64 sender_(new TcpCubicSenderPeer(&clock_, true)), | 67 sender_(new TcpCubicSenderPeer(&clock_, true, kMaxTcpCongestionWindow)), |
65 sequence_number_(1), | 68 sequence_number_(1), |
66 acked_sequence_number_(0), | 69 acked_sequence_number_(0), |
67 bytes_in_flight_(0) { | 70 bytes_in_flight_(0) { |
68 standard_packet_.bytes_sent = kDefaultTCPMSS; | 71 standard_packet_.bytes_sent = kDefaultTCPMSS; |
69 } | 72 } |
70 | 73 |
71 int SendAvailableSendWindow() { | 74 int SendAvailableSendWindow() { |
72 // Send as long as TimeUntilSend returns Zero. | 75 // Send as long as TimeUntilSend returns Zero. |
73 int packets_sent = 0; | 76 int packets_sent = 0; |
74 bool can_send = sender_->TimeUntilSend( | 77 bool can_send = sender_->TimeUntilSend( |
(...skipping 124 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
199 const QuicByteCount cwnd = sender_->GetCongestionWindow(); | 202 const QuicByteCount cwnd = sender_->GetCongestionWindow(); |
200 EXPECT_EQ(kDefaultWindowTCP + kDefaultTCPMSS * 2 * kNumberOfAcks, cwnd); | 203 EXPECT_EQ(kDefaultWindowTCP + kDefaultTCPMSS * 2 * kNumberOfAcks, cwnd); |
201 EXPECT_FALSE(sender_->HasReliableBandwidthEstimate()); | 204 EXPECT_FALSE(sender_->HasReliableBandwidthEstimate()); |
202 EXPECT_EQ(QuicBandwidth::FromBytesAndTimeDelta( | 205 EXPECT_EQ(QuicBandwidth::FromBytesAndTimeDelta( |
203 cwnd, sender_->rtt_stats_.smoothed_rtt()), | 206 cwnd, sender_->rtt_stats_.smoothed_rtt()), |
204 sender_->BandwidthEstimate()); | 207 sender_->BandwidthEstimate()); |
205 } | 208 } |
206 | 209 |
207 TEST_F(TcpCubicSenderTest, SlowStartAckTrain) { | 210 TEST_F(TcpCubicSenderTest, SlowStartAckTrain) { |
208 sender_->SetNumEmulatedConnections(1); | 211 sender_->SetNumEmulatedConnections(1); |
| 212 EXPECT_EQ(kMaxTcpCongestionWindow * kDefaultTCPMSS, |
| 213 sender_->GetSlowStartThreshold()); |
209 | 214 |
210 // Make sure that we fall out of slow start when we send ACK train longer | 215 // Make sure that we fall out of slow start when we send ACK train longer |
211 // than half the RTT, in this test case 30ms, which is more than 30 calls to | 216 // than half the RTT, in this test case 30ms, which is more than 30 calls to |
212 // Ack2Packets in one round. | 217 // Ack2Packets in one round. |
213 // Since we start at 10 packet first round will be 5 second round 10 etc | 218 // Since we start at 10 packet first round will be 5 second round 10 etc |
214 // Hence we should pass 30 at 65 = 5 + 10 + 20 + 30 | 219 // Hence we should pass 30 at 65 = 5 + 10 + 20 + 30 |
215 const int kNumberOfAcks = 65; | 220 const int kNumberOfAcks = 65; |
216 for (int i = 0; i < kNumberOfAcks; ++i) { | 221 for (int i = 0; i < kNumberOfAcks; ++i) { |
217 // Send our full send window. | 222 // Send our full send window. |
218 SendAvailableSendWindow(); | 223 SendAvailableSendWindow(); |
(...skipping 188 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
407 | 412 |
408 // Exit recovery and return to sending at the new rate. | 413 // Exit recovery and return to sending at the new rate. |
409 for (int i = 0; i < kNumberOfAcks; ++i) { | 414 for (int i = 0; i < kNumberOfAcks; ++i) { |
410 AckNPackets(1); | 415 AckNPackets(1); |
411 EXPECT_EQ(1, SendAvailableSendWindow()); | 416 EXPECT_EQ(1, SendAvailableSendWindow()); |
412 } | 417 } |
413 } | 418 } |
414 | 419 |
415 TEST_F(TcpCubicSenderTest, RTOCongestionWindow) { | 420 TEST_F(TcpCubicSenderTest, RTOCongestionWindow) { |
416 EXPECT_EQ(kDefaultWindowTCP, sender_->GetCongestionWindow()); | 421 EXPECT_EQ(kDefaultWindowTCP, sender_->GetCongestionWindow()); |
| 422 EXPECT_EQ(kMaxTcpCongestionWindow, sender_->slowstart_threshold()); |
| 423 |
417 // Expect the window to decrease to the minimum once the RTO fires | 424 // Expect the window to decrease to the minimum once the RTO fires |
418 // and slow start threshold to be set to 1/2 of the CWND. | 425 // and slow start threshold to be set to 1/2 of the CWND. |
419 sender_->OnRetransmissionTimeout(true); | 426 sender_->OnRetransmissionTimeout(true); |
420 EXPECT_EQ(2 * kDefaultTCPMSS, sender_->GetCongestionWindow()); | 427 EXPECT_EQ(2 * kDefaultTCPMSS, sender_->GetCongestionWindow()); |
421 EXPECT_EQ(5u, sender_->slowstart_threshold()); | 428 EXPECT_EQ(5u, sender_->slowstart_threshold()); |
422 } | 429 } |
423 | 430 |
424 TEST_F(TcpCubicSenderTest, RTOCongestionWindowNoRetransmission) { | 431 TEST_F(TcpCubicSenderTest, RTOCongestionWindowNoRetransmission) { |
425 EXPECT_EQ(kDefaultWindowTCP, sender_->GetCongestionWindow()); | 432 EXPECT_EQ(kDefaultWindowTCP, sender_->GetCongestionWindow()); |
426 | 433 |
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
459 EXPECT_NEAR(kRttMs, sender_->rtt_stats_.smoothed_rtt().ToMilliseconds(), 1); | 466 EXPECT_NEAR(kRttMs, sender_->rtt_stats_.smoothed_rtt().ToMilliseconds(), 1); |
460 EXPECT_NEAR(expected_delay.ToMilliseconds(), | 467 EXPECT_NEAR(expected_delay.ToMilliseconds(), |
461 sender_->RetransmissionDelay().ToMilliseconds(), | 468 sender_->RetransmissionDelay().ToMilliseconds(), |
462 1); | 469 1); |
463 EXPECT_EQ(static_cast<int64>( | 470 EXPECT_EQ(static_cast<int64>( |
464 sender_->GetCongestionWindow() * kNumMicrosPerSecond / | 471 sender_->GetCongestionWindow() * kNumMicrosPerSecond / |
465 sender_->rtt_stats_.smoothed_rtt().ToMicroseconds()), | 472 sender_->rtt_stats_.smoothed_rtt().ToMicroseconds()), |
466 sender_->BandwidthEstimate().ToBytesPerSecond()); | 473 sender_->BandwidthEstimate().ToBytesPerSecond()); |
467 } | 474 } |
468 | 475 |
| 476 TEST_F(TcpCubicSenderTest, SlowStartMaxSendWindow) { |
| 477 const QuicPacketCount kMaxCongestionWindowTCP = 50; |
| 478 const int kNumberOfAcks = 100; |
| 479 sender_.reset( |
| 480 new TcpCubicSenderPeer(&clock_, false, kMaxCongestionWindowTCP)); |
| 481 |
| 482 for (int i = 0; i < kNumberOfAcks; ++i) { |
| 483 // Send our full send window. |
| 484 SendAvailableSendWindow(); |
| 485 AckNPackets(2); |
| 486 } |
| 487 QuicByteCount expected_send_window = kMaxCongestionWindowTCP * kDefaultTCPMSS; |
| 488 EXPECT_EQ(expected_send_window, sender_->GetCongestionWindow()); |
| 489 } |
| 490 |
| 491 TEST_F(TcpCubicSenderTest, TcpRenoMaxCongestionWindow) { |
| 492 const QuicPacketCount kMaxCongestionWindowTCP = 50; |
| 493 const int kNumberOfAcks = 1000; |
| 494 sender_.reset(new TcpCubicSenderPeer(&clock_, true, kMaxCongestionWindowTCP)); |
| 495 |
| 496 SendAvailableSendWindow(); |
| 497 AckNPackets(2); |
| 498 // Make sure we fall out of slow start. |
| 499 LoseNPackets(1); |
| 500 |
| 501 for (int i = 0; i < kNumberOfAcks; ++i) { |
| 502 // Send our full send window. |
| 503 SendAvailableSendWindow(); |
| 504 AckNPackets(2); |
| 505 } |
| 506 |
| 507 QuicByteCount expected_send_window = kMaxCongestionWindowTCP * kDefaultTCPMSS; |
| 508 EXPECT_EQ(expected_send_window, sender_->GetCongestionWindow()); |
| 509 } |
| 510 |
| 511 TEST_F(TcpCubicSenderTest, TcpCubicMaxCongestionWindow) { |
| 512 const QuicPacketCount kMaxCongestionWindowTCP = 50; |
| 513 // Set to 10000 to compensate for small cubic alpha. |
| 514 const int kNumberOfAcks = 10000; |
| 515 |
| 516 sender_.reset( |
| 517 new TcpCubicSenderPeer(&clock_, false, kMaxCongestionWindowTCP)); |
| 518 |
| 519 SendAvailableSendWindow(); |
| 520 AckNPackets(2); |
| 521 // Make sure we fall out of slow start. |
| 522 LoseNPackets(1); |
| 523 |
| 524 for (int i = 0; i < kNumberOfAcks; ++i) { |
| 525 // Send our full send window. |
| 526 SendAvailableSendWindow(); |
| 527 AckNPackets(2); |
| 528 } |
| 529 |
| 530 QuicByteCount expected_send_window = kMaxCongestionWindowTCP * kDefaultTCPMSS; |
| 531 EXPECT_EQ(expected_send_window, sender_->GetCongestionWindow()); |
| 532 } |
| 533 |
469 TEST_F(TcpCubicSenderTest, MultipleLossesInOneWindow) { | 534 TEST_F(TcpCubicSenderTest, MultipleLossesInOneWindow) { |
470 SendAvailableSendWindow(); | 535 SendAvailableSendWindow(); |
471 const QuicByteCount initial_window = sender_->GetCongestionWindow(); | 536 const QuicByteCount initial_window = sender_->GetCongestionWindow(); |
472 LosePacket(acked_sequence_number_ + 1); | 537 LosePacket(acked_sequence_number_ + 1); |
473 const QuicByteCount post_loss_window = sender_->GetCongestionWindow(); | 538 const QuicByteCount post_loss_window = sender_->GetCongestionWindow(); |
474 EXPECT_GT(initial_window, post_loss_window); | 539 EXPECT_GT(initial_window, post_loss_window); |
475 LosePacket(acked_sequence_number_ + 3); | 540 LosePacket(acked_sequence_number_ + 3); |
476 EXPECT_EQ(post_loss_window, sender_->GetCongestionWindow()); | 541 EXPECT_EQ(post_loss_window, sender_->GetCongestionWindow()); |
477 LosePacket(sequence_number_ - 1); | 542 LosePacket(sequence_number_ - 1); |
478 EXPECT_EQ(post_loss_window, sender_->GetCongestionWindow()); | 543 EXPECT_EQ(post_loss_window, sender_->GetCongestionWindow()); |
(...skipping 172 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
651 EXPECT_EQ(10u, sender_->congestion_window()); | 716 EXPECT_EQ(10u, sender_->congestion_window()); |
652 | 717 |
653 // If the estimate is new enough, make sure it is used. | 718 // If the estimate is new enough, make sure it is used. |
654 cached_network_params.set_timestamp(clock_.WallNow().ToUNIXSeconds() - | 719 cached_network_params.set_timestamp(clock_.WallNow().ToUNIXSeconds() - |
655 (kNumSecondsPerHour - 1)); | 720 (kNumSecondsPerHour - 1)); |
656 EXPECT_TRUE(sender_->ResumeConnectionState(cached_network_params)); | 721 EXPECT_TRUE(sender_->ResumeConnectionState(cached_network_params)); |
657 EXPECT_EQ(kNumberOfPackets, sender_->congestion_window()); | 722 EXPECT_EQ(kNumberOfPackets, sender_->congestion_window()); |
658 | 723 |
659 // Resumed CWND is limited to be in a sensible range. | 724 // Resumed CWND is limited to be in a sensible range. |
660 cached_network_params.set_bandwidth_estimate_bytes_per_second( | 725 cached_network_params.set_bandwidth_estimate_bytes_per_second( |
661 (kMaxCongestionWindowForBandwidthResumption + 1) * kMaxPacketSize); | 726 (kMaxTcpCongestionWindow + 1) * kMaxPacketSize); |
662 EXPECT_TRUE(sender_->ResumeConnectionState(cached_network_params)); | 727 EXPECT_TRUE(sender_->ResumeConnectionState(cached_network_params)); |
663 EXPECT_EQ(kMaxCongestionWindowForBandwidthResumption, | 728 EXPECT_EQ(kMaxTcpCongestionWindow, sender_->congestion_window()); |
664 sender_->congestion_window()); | |
665 | 729 |
666 cached_network_params.set_bandwidth_estimate_bytes_per_second( | 730 cached_network_params.set_bandwidth_estimate_bytes_per_second( |
667 (kMinCongestionWindowForBandwidthResumption - 1) * kMaxPacketSize); | 731 (kMinCongestionWindowForBandwidthResumption - 1) * kMaxPacketSize); |
668 EXPECT_TRUE(sender_->ResumeConnectionState(cached_network_params)); | 732 EXPECT_TRUE(sender_->ResumeConnectionState(cached_network_params)); |
669 EXPECT_EQ(kMinCongestionWindowForBandwidthResumption, | 733 EXPECT_EQ(kMinCongestionWindowForBandwidthResumption, |
670 sender_->congestion_window()); | 734 sender_->congestion_window()); |
671 } | 735 } |
672 | 736 |
673 } // namespace test | 737 } // namespace test |
674 } // namespace net | 738 } // namespace net |
OLD | NEW |