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 3 // found in the LICENSE file. 4 5 #include <algorithm> 6 7 #include "base/logging.h" 8 #include "base/memory/scoped_ptr.h" 9 #include "net/quic/congestion_control/rtt_stats.h" 10 #include "net/quic/congestion_control/tcp_cubic_sender.h" 11 #include "net/quic/congestion_control/tcp_receiver.h" 12 #include "net/quic/quic_utils.h" 13 #include "net/quic/test_tools/mock_clock.h" 14 #include "net/quic/test_tools/quic_config_peer.h" 15 #include "testing/gtest/include/gtest/gtest.h" 16 17 using std::min; 18 19 namespace net { 20 namespace test { 21 22 const uint32 kDefaultWindowTCP = 10 * kDefaultTCPMSS; 23 24 // TODO(ianswett): Remove 10000 once b/10075719 is fixed. 25 const QuicTcpCongestionWindow kDefaultMaxCongestionWindowTCP = 10000; 26 27 class TcpCubicSenderPeer : public TcpCubicSender { 28 public: 29 TcpCubicSenderPeer(const QuicClock* clock, 30 bool reno, 31 QuicTcpCongestionWindow max_tcp_congestion_window) 32 : TcpCubicSender( 33 clock, &rtt_stats_, reno, max_tcp_congestion_window, &stats_) { 34 } 35 36 QuicTcpCongestionWindow congestion_window() { 37 return congestion_window_; 38 } 39 40 const HybridSlowStart& hybrid_slow_start() const { 41 return hybrid_slow_start_; 42 } 43 44 RttStats rtt_stats_; 45 QuicConnectionStats stats_; 46 47 using TcpCubicSender::SendWindow; 48 }; 49 50 class TcpCubicSenderTest : public ::testing::Test { 51 protected: 52 TcpCubicSenderTest() 53 : one_ms_(QuicTime::Delta::FromMilliseconds(1)), 54 sender_(new TcpCubicSenderPeer(&clock_, true, 55 kDefaultMaxCongestionWindowTCP)), 56 receiver_(new TcpReceiver()), 57 sequence_number_(1), 58 acked_sequence_number_(0), 59 bytes_in_flight_(0) { 60 standard_packet_.bytes_sent = kDefaultTCPMSS; 61 } 62 63 int SendAvailableSendWindow() { 64 // Send as long as TimeUntilSend returns Zero. 65 int packets_sent = 0; 66 bool can_send = sender_->TimeUntilSend( 67 clock_.Now(), bytes_in_flight_, HAS_RETRANSMITTABLE_DATA).IsZero(); 68 while (can_send) { 69 sender_->OnPacketSent(clock_.Now(), bytes_in_flight_, sequence_number_++, 70 kDefaultTCPMSS, HAS_RETRANSMITTABLE_DATA); 71 ++packets_sent; 72 bytes_in_flight_ += kDefaultTCPMSS; 73 can_send = sender_->TimeUntilSend( 74 clock_.Now(), bytes_in_flight_, HAS_RETRANSMITTABLE_DATA).IsZero(); 75 } 76 return packets_sent; 77 } 78 79 // Normal is that TCP acks every other segment. 80 void AckNPackets(int n) { 81 sender_->rtt_stats_.UpdateRtt(QuicTime::Delta::FromMilliseconds(60), 82 QuicTime::Delta::Zero(), 83 clock_.Now()); 84 SendAlgorithmInterface::CongestionMap acked_packets; 85 SendAlgorithmInterface::CongestionMap lost_packets; 86 for (int i = 0; i < n; ++i) { 87 ++acked_sequence_number_; 88 acked_packets[acked_sequence_number_] = standard_packet_; 89 } 90 sender_->OnCongestionEvent( 91 true, bytes_in_flight_, acked_packets, lost_packets); 92 bytes_in_flight_ -= n * kDefaultTCPMSS; 93 clock_.AdvanceTime(one_ms_); 94 } 95 96 void LoseNPackets(int n) { 97 SendAlgorithmInterface::CongestionMap acked_packets; 98 SendAlgorithmInterface::CongestionMap lost_packets; 99 for (int i = 0; i < n; ++i) { 100 ++acked_sequence_number_; 101 lost_packets[acked_sequence_number_] = standard_packet_; 102 } 103 sender_->OnCongestionEvent( 104 false, bytes_in_flight_, acked_packets, lost_packets); 105 bytes_in_flight_ -= n * kDefaultTCPMSS; 106 } 107 108 // Does not increment acked_sequence_number_. 109 void LosePacket(QuicPacketSequenceNumber sequence_number) { 110 SendAlgorithmInterface::CongestionMap acked_packets; 111 SendAlgorithmInterface::CongestionMap lost_packets; 112 lost_packets[sequence_number] = standard_packet_; 113 sender_->OnCongestionEvent( 114 false, bytes_in_flight_, acked_packets, lost_packets); 115 bytes_in_flight_ -= kDefaultTCPMSS; 116 } 117 118 const QuicTime::Delta one_ms_; 119 MockClock clock_; 120 scoped_ptr<TcpCubicSenderPeer> sender_; 121 scoped_ptr<TcpReceiver> receiver_; 122 QuicPacketSequenceNumber sequence_number_; 123 QuicPacketSequenceNumber acked_sequence_number_; 124 QuicByteCount bytes_in_flight_; 125 TransmissionInfo standard_packet_; 126 }; 127 128 TEST_F(TcpCubicSenderTest, SimpleSender) { 129 QuicCongestionFeedbackFrame feedback; 130 // At startup make sure we are at the default. 131 EXPECT_EQ(kDefaultWindowTCP, sender_->GetCongestionWindow()); 132 // At startup make sure we can send. 133 EXPECT_TRUE(sender_->TimeUntilSend(clock_.Now(), 134 0, 135 HAS_RETRANSMITTABLE_DATA).IsZero()); 136 // Get default QuicCongestionFeedbackFrame from receiver. 137 ASSERT_TRUE(receiver_->GenerateCongestionFeedback(&feedback)); 138 sender_->OnIncomingQuicCongestionFeedbackFrame(feedback, clock_.Now()); 139 // Make sure we can send. 140 EXPECT_TRUE(sender_->TimeUntilSend(clock_.Now(), 141 0, 142 HAS_RETRANSMITTABLE_DATA).IsZero()); 143 // And that window is un-affected. 144 EXPECT_EQ(kDefaultWindowTCP, sender_->GetCongestionWindow()); 145 146 // Fill the send window with data, then verify that we can't send. 147 SendAvailableSendWindow(); 148 EXPECT_FALSE(sender_->TimeUntilSend(clock_.Now(), 149 sender_->GetCongestionWindow(), 150 HAS_RETRANSMITTABLE_DATA).IsZero()); 151 } 152 153 TEST_F(TcpCubicSenderTest, ApplicationLimitedSlowStart) { 154 // Send exactly 10 packets and ensure the CWND ends at 14 packets. 155 const int kNumberOfAcks = 5; 156 QuicCongestionFeedbackFrame feedback; 157 // At startup make sure we can send. 158 EXPECT_TRUE(sender_->TimeUntilSend(clock_.Now(), 159 0, 160 HAS_RETRANSMITTABLE_DATA).IsZero()); 161 // Get default QuicCongestionFeedbackFrame from receiver. 162 ASSERT_TRUE(receiver_->GenerateCongestionFeedback(&feedback)); 163 sender_->OnIncomingQuicCongestionFeedbackFrame(feedback, clock_.Now()); 164 // Make sure we can send. 165 EXPECT_TRUE(sender_->TimeUntilSend(clock_.Now(), 166 0, 167 HAS_RETRANSMITTABLE_DATA).IsZero()); 168 169 SendAvailableSendWindow(); 170 for (int i = 0; i < kNumberOfAcks; ++i) { 171 AckNPackets(2); 172 } 173 QuicByteCount bytes_to_send = sender_->SendWindow(); 174 // It's expected 2 acks will arrive when the bytes_in_flight are greater than 175 // half the CWND. 176 EXPECT_EQ(kDefaultWindowTCP + kDefaultTCPMSS * 2 * 2, 177 bytes_to_send); 178 } 179 180 TEST_F(TcpCubicSenderTest, ExponentialSlowStart) { 181 const int kNumberOfAcks = 20; 182 QuicCongestionFeedbackFrame feedback; 183 // At startup make sure we can send. 184 EXPECT_TRUE(sender_->TimeUntilSend(clock_.Now(), 185 0, 186 HAS_RETRANSMITTABLE_DATA).IsZero()); 187 // Get default QuicCongestionFeedbackFrame from receiver. 188 ASSERT_TRUE(receiver_->GenerateCongestionFeedback(&feedback)); 189 sender_->OnIncomingQuicCongestionFeedbackFrame(feedback, clock_.Now()); 190 // Make sure we can send. 191 EXPECT_TRUE(sender_->TimeUntilSend(clock_.Now(), 192 0, 193 HAS_RETRANSMITTABLE_DATA).IsZero()); 194 195 for (int i = 0; i < kNumberOfAcks; ++i) { 196 // Send our full send window. 197 SendAvailableSendWindow(); 198 AckNPackets(2); 199 } 200 QuicByteCount bytes_to_send = sender_->SendWindow(); 201 EXPECT_EQ(kDefaultWindowTCP + kDefaultTCPMSS * 2 * kNumberOfAcks, 202 bytes_to_send); 203 } 204 205 TEST_F(TcpCubicSenderTest, SlowStartAckTrain) { 206 // Make sure that we fall out of slow start when we send ACK train longer 207 // than half the RTT, in this test case 30ms, which is more than 30 calls to 208 // Ack2Packets in one round. 209 // Since we start at 10 packet first round will be 5 second round 10 etc 210 // Hence we should pass 30 at 65 = 5 + 10 + 20 + 30 211 const int kNumberOfAcks = 65; 212 QuicCongestionFeedbackFrame feedback; 213 // Get default QuicCongestionFeedbackFrame from receiver. 214 ASSERT_TRUE(receiver_->GenerateCongestionFeedback(&feedback)); 215 sender_->OnIncomingQuicCongestionFeedbackFrame(feedback, clock_.Now()); 216 217 for (int i = 0; i < kNumberOfAcks; ++i) { 218 // Send our full send window. 219 SendAvailableSendWindow(); 220 AckNPackets(2); 221 } 222 QuicByteCount expected_send_window = 223 kDefaultWindowTCP + (kDefaultTCPMSS * 2 * kNumberOfAcks); 224 EXPECT_EQ(expected_send_window, sender_->GetCongestionWindow()); 225 226 // We should now have fallen out of slow start. 227 // Testing Reno phase. 228 // We should need 140(65*2+10) ACK:ed packets before increasing window by 229 // one. 230 for (int i = 0; i < 69; ++i) { 231 SendAvailableSendWindow(); 232 AckNPackets(2); 233 EXPECT_EQ(expected_send_window, sender_->GetCongestionWindow()); 234 } 235 SendAvailableSendWindow(); 236 AckNPackets(2); 237 expected_send_window += kDefaultTCPMSS; 238 EXPECT_EQ(expected_send_window, sender_->GetCongestionWindow()); 239 240 // Now RTO and ensure slow start gets reset. 241 EXPECT_TRUE(sender_->hybrid_slow_start().started()); 242 sender_->OnRetransmissionTimeout(true); 243 EXPECT_FALSE(sender_->hybrid_slow_start().started()); 244 } 245 246 TEST_F(TcpCubicSenderTest, SlowStartPacketLoss) { 247 // Make sure that we fall out of slow start when we encounter a packet loss. 248 QuicCongestionFeedbackFrame feedback; 249 // Get default QuicCongestionFeedbackFrame from receiver. 250 ASSERT_TRUE(receiver_->GenerateCongestionFeedback(&feedback)); 251 sender_->OnIncomingQuicCongestionFeedbackFrame(feedback, clock_.Now()); 252 253 const int kNumberOfAcks = 10; 254 for (int i = 0; i < kNumberOfAcks; ++i) { 255 // Send our full send window. 256 SendAvailableSendWindow(); 257 AckNPackets(2); 258 } 259 SendAvailableSendWindow(); 260 QuicByteCount expected_send_window = kDefaultWindowTCP + 261 (kDefaultTCPMSS * 2 * kNumberOfAcks); 262 EXPECT_EQ(expected_send_window, sender_->GetCongestionWindow()); 263 264 // Lose a packet to exit slow start. 265 LoseNPackets(1); 266 267 // We should now have fallen out of slow start. 268 // We expect window to be cut in half by Reno. 269 expected_send_window /= 2; 270 EXPECT_EQ(expected_send_window, sender_->GetCongestionWindow()); 271 272 // Testing Reno phase. 273 // We need to ack half of the pending packet before we can send again. 274 size_t number_of_packets_in_window = expected_send_window / kDefaultTCPMSS; 275 AckNPackets(number_of_packets_in_window); 276 EXPECT_EQ(expected_send_window, sender_->GetCongestionWindow()); 277 278 // We need to ack every packet in the window before we exit recovery. 279 for (size_t i = 0; i < number_of_packets_in_window; ++i) { 280 AckNPackets(1); 281 SendAvailableSendWindow(); 282 EXPECT_EQ(expected_send_window, sender_->GetCongestionWindow()); 283 } 284 285 // We need to ack another window before we increase CWND by 1. 286 for (size_t i = 0; i < number_of_packets_in_window - 2; ++i) { 287 AckNPackets(1); 288 SendAvailableSendWindow(); 289 EXPECT_EQ(expected_send_window, sender_->GetCongestionWindow()); 290 } 291 292 AckNPackets(1); 293 expected_send_window += kDefaultTCPMSS; 294 EXPECT_EQ(expected_send_window, sender_->GetCongestionWindow()); 295 296 // Now RTO and ensure slow start gets reset. 297 EXPECT_TRUE(sender_->hybrid_slow_start().started()); 298 sender_->OnRetransmissionTimeout(true); 299 EXPECT_FALSE(sender_->hybrid_slow_start().started()); 300 } 301 302 TEST_F(TcpCubicSenderTest, SlowStartPacketLossPRR) { 303 // Test based on the first example in RFC6937. 304 // Make sure that we fall out of slow start when we encounter a packet loss. 305 QuicCongestionFeedbackFrame feedback; 306 // Get default QuicCongestionFeedbackFrame from receiver. 307 ASSERT_TRUE(receiver_->GenerateCongestionFeedback(&feedback)); 308 sender_->OnIncomingQuicCongestionFeedbackFrame(feedback, clock_.Now()); 309 310 // Ack 10 packets in 5 acks to raise the CWND to 20, as in the example. 311 const int kNumberOfAcks = 5; 312 for (int i = 0; i < kNumberOfAcks; ++i) { 313 // Send our full send window. 314 SendAvailableSendWindow(); 315 AckNPackets(2); 316 } 317 SendAvailableSendWindow(); 318 QuicByteCount expected_send_window = kDefaultWindowTCP + 319 (kDefaultTCPMSS * 2 * kNumberOfAcks); 320 EXPECT_EQ(expected_send_window, sender_->GetCongestionWindow()); 321 322 LoseNPackets(1); 323 324 // We should now have fallen out of slow start. 325 // We expect window to be cut in half by Reno. 326 expected_send_window /= 2; 327 EXPECT_EQ(expected_send_window, sender_->GetCongestionWindow()); 328 329 // Testing TCP proportional rate reduction. 330 // We should send one packet for every two received acks over the remaining 331 // 18 outstanding packets. 332 size_t number_of_packets_in_window = expected_send_window / kDefaultTCPMSS; 333 // The number of packets before we exit recovery is the original CWND minus 334 // the packet that has been lost and the one which triggered the loss. 335 size_t remaining_packets_in_recovery = number_of_packets_in_window * 2 - 1; 336 for (size_t i = 0; i < remaining_packets_in_recovery - 1; i += 2) { 337 AckNPackets(2); 338 EXPECT_TRUE(sender_->TimeUntilSend( 339 clock_.Now(), bytes_in_flight_, HAS_RETRANSMITTABLE_DATA).IsZero()); 340 EXPECT_EQ(1, SendAvailableSendWindow()); 341 EXPECT_EQ(expected_send_window, sender_->GetCongestionWindow()); 342 } 343 344 // We need to ack another window before we increase CWND by 1. 345 for (size_t i = 0; i < number_of_packets_in_window; ++i) { 346 AckNPackets(1); 347 EXPECT_EQ(1, SendAvailableSendWindow()); 348 EXPECT_EQ(expected_send_window, sender_->GetCongestionWindow()); 349 } 350 351 AckNPackets(1); 352 expected_send_window += kDefaultTCPMSS; 353 EXPECT_EQ(expected_send_window, sender_->GetCongestionWindow()); 354 } 355 356 TEST_F(TcpCubicSenderTest, SlowStartBurstPacketLossPRR) { 357 // Test based on the second example in RFC6937, though we also implement 358 // forward acknowledgements, so the first two incoming acks will trigger 359 // PRR immediately. 360 // Make sure that we fall out of slow start when we encounter a packet loss. 361 QuicCongestionFeedbackFrame feedback; 362 // Get default QuicCongestionFeedbackFrame from receiver. 363 ASSERT_TRUE(receiver_->GenerateCongestionFeedback(&feedback)); 364 sender_->OnIncomingQuicCongestionFeedbackFrame(feedback, clock_.Now()); 365 366 // Ack 10 packets in 5 acks to raise the CWND to 20, as in the example. 367 const int kNumberOfAcks = 5; 368 for (int i = 0; i < kNumberOfAcks; ++i) { 369 // Send our full send window. 370 SendAvailableSendWindow(); 371 AckNPackets(2); 372 } 373 SendAvailableSendWindow(); 374 QuicByteCount expected_send_window = kDefaultWindowTCP + 375 (kDefaultTCPMSS * 2 * kNumberOfAcks); 376 EXPECT_EQ(expected_send_window, sender_->GetCongestionWindow()); 377 378 // Ack a packet with a 15 packet gap, losing 13 of them due to FACK. 379 LoseNPackets(13); 380 // Immediately after the loss, ensure at least one packet can be sent. 381 // Losses without subsequent acks can occur with timer based loss detection. 382 EXPECT_TRUE(sender_->TimeUntilSend( 383 clock_.Now(), bytes_in_flight_, HAS_RETRANSMITTABLE_DATA).IsZero()); 384 AckNPackets(1); 385 386 // We should now have fallen out of slow start. 387 // We expect window to be cut in half by Reno. 388 expected_send_window /= 2; 389 EXPECT_EQ(expected_send_window, sender_->GetCongestionWindow()); 390 391 // Only 2 packets should be allowed to be sent, per PRR-SSRB 392 EXPECT_EQ(2, SendAvailableSendWindow()); 393 394 // Ack the next packet, which triggers another loss. 395 LoseNPackets(1); 396 AckNPackets(1); 397 398 // Send 2 packets to simulate PRR-SSRB. 399 EXPECT_EQ(2, SendAvailableSendWindow()); 400 401 // Ack the next packet, which triggers another loss. 402 LoseNPackets(1); 403 AckNPackets(1); 404 405 // Send 2 packets to simulate PRR-SSRB. 406 EXPECT_EQ(2, SendAvailableSendWindow()); 407 408 AckNPackets(1); 409 EXPECT_EQ(2, SendAvailableSendWindow()); 410 411 AckNPackets(1); 412 EXPECT_EQ(2, SendAvailableSendWindow()); 413 414 // The window should not have changed. 415 EXPECT_EQ(expected_send_window, sender_->GetCongestionWindow()); 416 417 // Exit recovery and return to sending at the new rate. 418 for (int i = 0; i < kNumberOfAcks; ++i) { 419 AckNPackets(1); 420 EXPECT_EQ(1, SendAvailableSendWindow()); 421 } 422 } 423 424 TEST_F(TcpCubicSenderTest, RTOCongestionWindow) { 425 EXPECT_EQ(kDefaultWindowTCP, sender_->SendWindow()); 426 427 // Expect the window to decrease to the minimum once the RTO fires. 428 sender_->OnRetransmissionTimeout(true); 429 EXPECT_EQ(2 * kDefaultTCPMSS, sender_->SendWindow()); 430 } 431 432 TEST_F(TcpCubicSenderTest, RTOCongestionWindowNoRetransmission) { 433 EXPECT_EQ(kDefaultWindowTCP, sender_->SendWindow()); 434 435 // Expect the window to remain unchanged if the RTO fires but no 436 // packets are retransmitted. 437 sender_->OnRetransmissionTimeout(false); 438 EXPECT_EQ(kDefaultWindowTCP, sender_->SendWindow()); 439 } 440 441 TEST_F(TcpCubicSenderTest, RetransmissionDelay) { 442 const int64 kRttMs = 10; 443 const int64 kDeviationMs = 3; 444 EXPECT_EQ(QuicTime::Delta::Zero(), sender_->RetransmissionDelay()); 445 446 sender_->rtt_stats_.UpdateRtt(QuicTime::Delta::FromMilliseconds(kRttMs), 447 QuicTime::Delta::Zero(), clock_.Now()); 448 449 // Initial value is to set the median deviation to half of the initial 450 // rtt, the median in then multiplied by a factor of 4 and finally the 451 // smoothed rtt is added which is the initial rtt. 452 QuicTime::Delta expected_delay = 453 QuicTime::Delta::FromMilliseconds(kRttMs + kRttMs / 2 * 4); 454 EXPECT_EQ(expected_delay, sender_->RetransmissionDelay()); 455 456 for (int i = 0; i < 100; ++i) { 457 // Run to make sure that we converge. 458 sender_->rtt_stats_.UpdateRtt( 459 QuicTime::Delta::FromMilliseconds(kRttMs + kDeviationMs), 460 QuicTime::Delta::Zero(), clock_.Now()); 461 sender_->rtt_stats_.UpdateRtt( 462 QuicTime::Delta::FromMilliseconds(kRttMs - kDeviationMs), 463 QuicTime::Delta::Zero(), clock_.Now()); 464 } 465 expected_delay = QuicTime::Delta::FromMilliseconds(kRttMs + kDeviationMs * 4); 466 467 EXPECT_NEAR(kRttMs, sender_->rtt_stats_.SmoothedRtt().ToMilliseconds(), 1); 468 EXPECT_NEAR(expected_delay.ToMilliseconds(), 469 sender_->RetransmissionDelay().ToMilliseconds(), 470 1); 471 EXPECT_EQ(static_cast<int64>( 472 sender_->GetCongestionWindow() * kNumMicrosPerSecond / 473 sender_->rtt_stats_.SmoothedRtt().ToMicroseconds()), 474 sender_->BandwidthEstimate().ToBytesPerSecond()); 475 } 476 477 TEST_F(TcpCubicSenderTest, SlowStartMaxSendWindow) { 478 const QuicTcpCongestionWindow kMaxCongestionWindowTCP = 50; 479 const int kNumberOfAcks = 100; 480 sender_.reset( 481 new TcpCubicSenderPeer(&clock_, false, kMaxCongestionWindowTCP)); 482 483 QuicCongestionFeedbackFrame feedback; 484 // Get default QuicCongestionFeedbackFrame from receiver. 485 ASSERT_TRUE(receiver_->GenerateCongestionFeedback(&feedback)); 486 sender_->OnIncomingQuicCongestionFeedbackFrame(feedback, clock_.Now()); 487 488 for (int i = 0; i < kNumberOfAcks; ++i) { 489 // Send our full send window. 490 SendAvailableSendWindow(); 491 AckNPackets(2); 492 } 493 QuicByteCount expected_send_window = 494 kMaxCongestionWindowTCP * kDefaultTCPMSS; 495 EXPECT_EQ(expected_send_window, sender_->GetCongestionWindow()); 496 } 497 498 TEST_F(TcpCubicSenderTest, TcpRenoMaxCongestionWindow) { 499 const QuicTcpCongestionWindow kMaxCongestionWindowTCP = 50; 500 const int kNumberOfAcks = 1000; 501 sender_.reset( 502 new TcpCubicSenderPeer(&clock_, true, kMaxCongestionWindowTCP)); 503 504 QuicCongestionFeedbackFrame feedback; 505 // Get default QuicCongestionFeedbackFrame from receiver. 506 ASSERT_TRUE(receiver_->GenerateCongestionFeedback(&feedback)); 507 sender_->OnIncomingQuicCongestionFeedbackFrame(feedback, clock_.Now()); 508 509 SendAvailableSendWindow(); 510 AckNPackets(2); 511 // Make sure we fall out of slow start. 512 LoseNPackets(1); 513 514 for (int i = 0; i < kNumberOfAcks; ++i) { 515 // Send our full send window. 516 SendAvailableSendWindow(); 517 AckNPackets(2); 518 } 519 520 QuicByteCount expected_send_window = 521 kMaxCongestionWindowTCP * kDefaultTCPMSS; 522 EXPECT_EQ(expected_send_window, sender_->GetCongestionWindow()); 523 } 524 525 TEST_F(TcpCubicSenderTest, TcpCubicMaxCongestionWindow) { 526 const QuicTcpCongestionWindow kMaxCongestionWindowTCP = 50; 527 // Set to 10000 to compensate for small cubic alpha. 528 const int kNumberOfAcks = 10000; 529 530 sender_.reset( 531 new TcpCubicSenderPeer(&clock_, false, kMaxCongestionWindowTCP)); 532 533 QuicCongestionFeedbackFrame feedback; 534 // Get default QuicCongestionFeedbackFrame from receiver. 535 ASSERT_TRUE(receiver_->GenerateCongestionFeedback(&feedback)); 536 sender_->OnIncomingQuicCongestionFeedbackFrame(feedback, clock_.Now()); 537 538 SendAvailableSendWindow(); 539 AckNPackets(2); 540 // Make sure we fall out of slow start. 541 LoseNPackets(1); 542 543 for (int i = 0; i < kNumberOfAcks; ++i) { 544 // Send our full send window. 545 SendAvailableSendWindow(); 546 AckNPackets(2); 547 } 548 549 QuicByteCount expected_send_window = 550 kMaxCongestionWindowTCP * kDefaultTCPMSS; 551 EXPECT_EQ(expected_send_window, sender_->GetCongestionWindow()); 552 } 553 554 TEST_F(TcpCubicSenderTest, MultipleLossesInOneWindow) { 555 SendAvailableSendWindow(); 556 const QuicByteCount initial_window = sender_->GetCongestionWindow(); 557 LosePacket(acked_sequence_number_ + 1); 558 const QuicByteCount post_loss_window = sender_->GetCongestionWindow(); 559 EXPECT_GT(initial_window, post_loss_window); 560 LosePacket(acked_sequence_number_ + 3); 561 EXPECT_EQ(post_loss_window, sender_->GetCongestionWindow()); 562 LosePacket(sequence_number_ - 1); 563 EXPECT_EQ(post_loss_window, sender_->GetCongestionWindow()); 564 565 // Lose a later packet and ensure the window decreases. 566 LosePacket(sequence_number_); 567 EXPECT_GT(post_loss_window, sender_->GetCongestionWindow()); 568 } 569 570 TEST_F(TcpCubicSenderTest, DontTrackAckPackets) { 571 // Send a packet with no retransmittable data, and ensure it's not tracked. 572 EXPECT_FALSE(sender_->OnPacketSent(clock_.Now(), bytes_in_flight_, 573 sequence_number_++, kDefaultTCPMSS, 574 NO_RETRANSMITTABLE_DATA)); 575 576 // Send a data packet with retransmittable data, and ensure it is tracked. 577 EXPECT_TRUE(sender_->OnPacketSent(clock_.Now(), bytes_in_flight_, 578 sequence_number_++, kDefaultTCPMSS, 579 HAS_RETRANSMITTABLE_DATA)); 580 } 581 582 TEST_F(TcpCubicSenderTest, ConfigureMaxInitialWindow) { 583 QuicTcpCongestionWindow congestion_window = sender_->congestion_window(); 584 QuicConfig config; 585 QuicConfigPeer::SetReceivedInitialWindow(&config, 2 * congestion_window); 586 587 sender_->SetFromConfig(config, true); 588 EXPECT_EQ(2 * congestion_window, sender_->congestion_window()); 589 } 590 591 TEST_F(TcpCubicSenderTest, CongestionAvoidanceAtEndOfRecovery) { 592 // Make sure that we fall out of slow start when we encounter a packet loss. 593 QuicCongestionFeedbackFrame feedback; 594 // Get default QuicCongestionFeedbackFrame from receiver. 595 ASSERT_TRUE(receiver_->GenerateCongestionFeedback(&feedback)); 596 sender_->OnIncomingQuicCongestionFeedbackFrame(feedback, clock_.Now()); 597 // Ack 10 packets in 5 acks to raise the CWND to 20. 598 const int kNumberOfAcks = 5; 599 for (int i = 0; i < kNumberOfAcks; ++i) { 600 // Send our full send window. 601 SendAvailableSendWindow(); 602 AckNPackets(2); 603 } 604 SendAvailableSendWindow(); 605 QuicByteCount expected_send_window = kDefaultWindowTCP + 606 (kDefaultTCPMSS * 2 * kNumberOfAcks); 607 EXPECT_EQ(expected_send_window, sender_->GetCongestionWindow()); 608 609 LoseNPackets(1); 610 611 // We should now have fallen out of slow start, and window should be cut in 612 // half by Reno. New cwnd should be 10. 613 expected_send_window /= 2; 614 EXPECT_EQ(expected_send_window, sender_->GetCongestionWindow()); 615 616 // No congestion window growth should occur in recovery phase, i.e., 617 // until the currently outstanding 20 packets are acked. 618 for (int i = 0; i < 10; ++i) { 619 // Send our full send window. 620 SendAvailableSendWindow(); 621 AckNPackets(2); 622 EXPECT_EQ(expected_send_window, sender_->GetCongestionWindow()); 623 } 624 625 // Out of recovery now. Congestion window should not grow during RTT. 626 for (int i = 0; i < 4; ++i) { 627 // Send our full send window. 628 SendAvailableSendWindow(); 629 AckNPackets(2); 630 EXPECT_EQ(expected_send_window, sender_->GetCongestionWindow()); 631 } 632 633 // Next ack should cause congestion window to grow by 1MSS. 634 AckNPackets(2); 635 expected_send_window += kDefaultTCPMSS; 636 EXPECT_EQ(expected_send_window, sender_->GetCongestionWindow()); 637 } 638 639 } // namespace test 640 } // namespace net 641