We started redesigning GpuMemoryBuffer interface to handle multiple buffers [0].
[chromium-blink-merge.git] / net / quic / congestion_control / tcp_cubic_sender_test.cc
blob5813faa0d3e29ce4964c18036e296fe66e5f5578
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.
5 #include <algorithm>
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/crypto/crypto_protocol.h"
12 #include "net/quic/proto/cached_network_parameters.pb.h"
13 #include "net/quic/quic_protocol.h"
14 #include "net/quic/quic_utils.h"
15 #include "net/quic/test_tools/mock_clock.h"
16 #include "net/quic/test_tools/quic_config_peer.h"
17 #include "testing/gtest/include/gtest/gtest.h"
19 using std::min;
21 namespace net {
22 namespace test {
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;
30 const float kRenoBeta = 0.7f; // Reno backoff factor.
32 class TcpCubicSenderPeer : public TcpCubicSender {
33 public:
34 TcpCubicSenderPeer(const QuicClock* clock,
35 bool reno,
36 QuicPacketCount max_tcp_congestion_window)
37 : TcpCubicSender(clock,
38 &rtt_stats_,
39 reno,
40 kInitialCongestionWindowPackets,
41 max_tcp_congestion_window,
42 &stats_) {}
44 QuicPacketCount congestion_window() {
45 return congestion_window_;
48 QuicPacketCount slowstart_threshold() {
49 return slowstart_threshold_;
52 const HybridSlowStart& hybrid_slow_start() const {
53 return hybrid_slow_start_;
56 float GetRenoBeta() const {
57 return RenoBeta();
60 RttStats rtt_stats_;
61 QuicConnectionStats stats_;
64 class TcpCubicSenderTest : public ::testing::Test {
65 protected:
66 TcpCubicSenderTest()
67 : one_ms_(QuicTime::Delta::FromMilliseconds(1)),
68 sender_(new TcpCubicSenderPeer(&clock_, true, kMaxTcpCongestionWindow)),
69 sequence_number_(1),
70 acked_sequence_number_(0),
71 bytes_in_flight_(0) {
72 standard_packet_.bytes_sent = kDefaultTCPMSS;
75 int SendAvailableSendWindow() {
76 // Send as long as TimeUntilSend returns Zero.
77 int packets_sent = 0;
78 bool can_send = sender_->TimeUntilSend(
79 clock_.Now(), bytes_in_flight_, HAS_RETRANSMITTABLE_DATA).IsZero();
80 while (can_send) {
81 sender_->OnPacketSent(clock_.Now(), bytes_in_flight_, sequence_number_++,
82 kDefaultTCPMSS, HAS_RETRANSMITTABLE_DATA);
83 ++packets_sent;
84 bytes_in_flight_ += kDefaultTCPMSS;
85 can_send = sender_->TimeUntilSend(
86 clock_.Now(), bytes_in_flight_, HAS_RETRANSMITTABLE_DATA).IsZero();
88 return packets_sent;
91 // Normal is that TCP acks every other segment.
92 void AckNPackets(int n) {
93 sender_->rtt_stats_.UpdateRtt(QuicTime::Delta::FromMilliseconds(60),
94 QuicTime::Delta::Zero(),
95 clock_.Now());
96 SendAlgorithmInterface::CongestionVector acked_packets;
97 SendAlgorithmInterface::CongestionVector lost_packets;
98 for (int i = 0; i < n; ++i) {
99 ++acked_sequence_number_;
100 acked_packets.push_back(
101 std::make_pair(acked_sequence_number_, standard_packet_));
103 sender_->OnCongestionEvent(
104 true, bytes_in_flight_, acked_packets, lost_packets);
105 bytes_in_flight_ -= n * kDefaultTCPMSS;
106 clock_.AdvanceTime(one_ms_);
109 void LoseNPackets(int n) {
110 SendAlgorithmInterface::CongestionVector acked_packets;
111 SendAlgorithmInterface::CongestionVector lost_packets;
112 for (int i = 0; i < n; ++i) {
113 ++acked_sequence_number_;
114 lost_packets.push_back(
115 std::make_pair(acked_sequence_number_, standard_packet_));
117 sender_->OnCongestionEvent(
118 false, bytes_in_flight_, acked_packets, lost_packets);
119 bytes_in_flight_ -= n * kDefaultTCPMSS;
122 // Does not increment acked_sequence_number_.
123 void LosePacket(QuicPacketSequenceNumber sequence_number) {
124 SendAlgorithmInterface::CongestionVector acked_packets;
125 SendAlgorithmInterface::CongestionVector lost_packets;
126 lost_packets.push_back(std::make_pair(sequence_number, standard_packet_));
127 sender_->OnCongestionEvent(
128 false, bytes_in_flight_, acked_packets, lost_packets);
129 bytes_in_flight_ -= kDefaultTCPMSS;
132 const QuicTime::Delta one_ms_;
133 MockClock clock_;
134 scoped_ptr<TcpCubicSenderPeer> sender_;
135 QuicPacketSequenceNumber sequence_number_;
136 QuicPacketSequenceNumber acked_sequence_number_;
137 QuicByteCount bytes_in_flight_;
138 TransmissionInfo standard_packet_;
141 TEST_F(TcpCubicSenderTest, SimpleSender) {
142 // At startup make sure we are at the default.
143 EXPECT_EQ(kDefaultWindowTCP, sender_->GetCongestionWindow());
144 // At startup make sure we can send.
145 EXPECT_TRUE(sender_->TimeUntilSend(clock_.Now(),
147 HAS_RETRANSMITTABLE_DATA).IsZero());
148 // Make sure we can send.
149 EXPECT_TRUE(sender_->TimeUntilSend(clock_.Now(),
151 HAS_RETRANSMITTABLE_DATA).IsZero());
152 // And that window is un-affected.
153 EXPECT_EQ(kDefaultWindowTCP, sender_->GetCongestionWindow());
155 // Fill the send window with data, then verify that we can't send.
156 SendAvailableSendWindow();
157 EXPECT_FALSE(sender_->TimeUntilSend(clock_.Now(),
158 sender_->GetCongestionWindow(),
159 HAS_RETRANSMITTABLE_DATA).IsZero());
162 TEST_F(TcpCubicSenderTest, ApplicationLimitedSlowStart) {
163 // Send exactly 10 packets and ensure the CWND ends at 14 packets.
164 const int kNumberOfAcks = 5;
165 // At startup make sure we can send.
166 EXPECT_TRUE(sender_->TimeUntilSend(clock_.Now(),
168 HAS_RETRANSMITTABLE_DATA).IsZero());
169 // Make sure we can send.
170 EXPECT_TRUE(sender_->TimeUntilSend(clock_.Now(),
172 HAS_RETRANSMITTABLE_DATA).IsZero());
174 SendAvailableSendWindow();
175 for (int i = 0; i < kNumberOfAcks; ++i) {
176 AckNPackets(2);
178 QuicByteCount bytes_to_send = sender_->GetCongestionWindow();
179 // It's expected 2 acks will arrive when the bytes_in_flight are greater than
180 // half the CWND.
181 EXPECT_EQ(kDefaultWindowTCP + kDefaultTCPMSS * 2 * 2,
182 bytes_to_send);
185 TEST_F(TcpCubicSenderTest, ExponentialSlowStart) {
186 const int kNumberOfAcks = 20;
187 // At startup make sure we can send.
188 EXPECT_TRUE(sender_->TimeUntilSend(clock_.Now(),
190 HAS_RETRANSMITTABLE_DATA).IsZero());
191 EXPECT_FALSE(sender_->HasReliableBandwidthEstimate());
192 EXPECT_EQ(QuicBandwidth::Zero(), sender_->BandwidthEstimate());
193 // Make sure we can send.
194 EXPECT_TRUE(sender_->TimeUntilSend(clock_.Now(),
196 HAS_RETRANSMITTABLE_DATA).IsZero());
198 for (int i = 0; i < kNumberOfAcks; ++i) {
199 // Send our full send window.
200 SendAvailableSendWindow();
201 AckNPackets(2);
203 const QuicByteCount cwnd = sender_->GetCongestionWindow();
204 EXPECT_EQ(kDefaultWindowTCP + kDefaultTCPMSS * 2 * kNumberOfAcks, cwnd);
205 EXPECT_FALSE(sender_->HasReliableBandwidthEstimate());
206 EXPECT_EQ(QuicBandwidth::FromBytesAndTimeDelta(
207 cwnd, sender_->rtt_stats_.smoothed_rtt()),
208 sender_->BandwidthEstimate());
211 TEST_F(TcpCubicSenderTest, SlowStartPacketLoss) {
212 sender_->SetNumEmulatedConnections(1);
213 const int kNumberOfAcks = 10;
214 for (int i = 0; i < kNumberOfAcks; ++i) {
215 // Send our full send window.
216 SendAvailableSendWindow();
217 AckNPackets(2);
219 SendAvailableSendWindow();
220 QuicByteCount expected_send_window = kDefaultWindowTCP +
221 (kDefaultTCPMSS * 2 * kNumberOfAcks);
222 EXPECT_EQ(expected_send_window, sender_->GetCongestionWindow());
224 // Lose a packet to exit slow start.
225 LoseNPackets(1);
226 size_t packets_in_recovery_window = expected_send_window / kDefaultTCPMSS;
228 // We should now have fallen out of slow start with a reduced window.
229 expected_send_window *= kRenoBeta;
230 EXPECT_EQ(expected_send_window, sender_->GetCongestionWindow());
232 // Recovery phase. We need to ack every packet in the recovery window before
233 // we exit recovery.
234 size_t number_of_packets_in_window = expected_send_window / kDefaultTCPMSS;
235 DVLOG(1) << "number_packets: " << number_of_packets_in_window;
236 AckNPackets(packets_in_recovery_window);
237 SendAvailableSendWindow();
238 EXPECT_EQ(expected_send_window, sender_->GetCongestionWindow());
240 // We need to ack an entire window before we increase CWND by 1.
241 AckNPackets(number_of_packets_in_window - 2);
242 SendAvailableSendWindow();
243 EXPECT_EQ(expected_send_window, sender_->GetCongestionWindow());
245 // Next ack should increase cwnd by 1.
246 AckNPackets(1);
247 expected_send_window += kDefaultTCPMSS;
248 EXPECT_EQ(expected_send_window, sender_->GetCongestionWindow());
250 // Now RTO and ensure slow start gets reset.
251 EXPECT_TRUE(sender_->hybrid_slow_start().started());
252 sender_->OnRetransmissionTimeout(true);
253 EXPECT_FALSE(sender_->hybrid_slow_start().started());
256 TEST_F(TcpCubicSenderTest, NoPRRWhenLessThanOnePacketInFlight) {
257 SendAvailableSendWindow();
258 LoseNPackets(kInitialCongestionWindowPackets - 1);
259 AckNPackets(1);
260 // PRR will allow 2 packets for every ack during recovery.
261 EXPECT_EQ(2, SendAvailableSendWindow());
262 // Simulate abandoning all packets by supplying a bytes_in_flight of 0.
263 // PRR should now allow a packet to be sent, even though prr's state
264 // variables believe it has sent enough packets.
265 EXPECT_EQ(QuicTime::Delta::Zero(),
266 sender_->TimeUntilSend(clock_.Now(), 0, HAS_RETRANSMITTABLE_DATA));
269 TEST_F(TcpCubicSenderTest, SlowStartPacketLossPRR) {
270 sender_->SetNumEmulatedConnections(1);
271 // Test based on the first example in RFC6937.
272 // Ack 10 packets in 5 acks to raise the CWND to 20, as in the example.
273 const int kNumberOfAcks = 5;
274 for (int i = 0; i < kNumberOfAcks; ++i) {
275 // Send our full send window.
276 SendAvailableSendWindow();
277 AckNPackets(2);
279 SendAvailableSendWindow();
280 QuicByteCount expected_send_window = kDefaultWindowTCP +
281 (kDefaultTCPMSS * 2 * kNumberOfAcks);
282 EXPECT_EQ(expected_send_window, sender_->GetCongestionWindow());
284 LoseNPackets(1);
286 // We should now have fallen out of slow start with a reduced window.
287 size_t send_window_before_loss = expected_send_window;
288 expected_send_window *= kRenoBeta;
289 EXPECT_EQ(expected_send_window, sender_->GetCongestionWindow());
291 // Testing TCP proportional rate reduction.
292 // We should send packets paced over the received acks for the remaining
293 // outstanding packets. The number of packets before we exit recovery is the
294 // original CWND minus the packet that has been lost and the one which
295 // triggered the loss.
296 size_t remaining_packets_in_recovery =
297 send_window_before_loss / kDefaultTCPMSS - 2;
299 for (size_t i = 0; i < remaining_packets_in_recovery; ++i) {
300 AckNPackets(1);
301 SendAvailableSendWindow();
302 EXPECT_EQ(expected_send_window, sender_->GetCongestionWindow());
305 // We need to ack another window before we increase CWND by 1.
306 size_t number_of_packets_in_window = expected_send_window / kDefaultTCPMSS;
307 for (size_t i = 0; i < number_of_packets_in_window; ++i) {
308 AckNPackets(1);
309 EXPECT_EQ(1, SendAvailableSendWindow());
310 EXPECT_EQ(expected_send_window, sender_->GetCongestionWindow());
313 AckNPackets(1);
314 expected_send_window += kDefaultTCPMSS;
315 EXPECT_EQ(expected_send_window, sender_->GetCongestionWindow());
318 TEST_F(TcpCubicSenderTest, SlowStartBurstPacketLossPRR) {
319 sender_->SetNumEmulatedConnections(1);
320 // Test based on the second example in RFC6937, though we also implement
321 // forward acknowledgements, so the first two incoming acks will trigger
322 // PRR immediately.
323 // Ack 20 packets in 10 acks to raise the CWND to 30.
324 const int kNumberOfAcks = 10;
325 for (int i = 0; i < kNumberOfAcks; ++i) {
326 // Send our full send window.
327 SendAvailableSendWindow();
328 AckNPackets(2);
330 SendAvailableSendWindow();
331 QuicByteCount expected_send_window = kDefaultWindowTCP +
332 (kDefaultTCPMSS * 2 * kNumberOfAcks);
333 EXPECT_EQ(expected_send_window, sender_->GetCongestionWindow());
335 // Lose one more than the congestion window reduction, so that after loss,
336 // bytes_in_flight is lesser than the congestion window.
337 size_t send_window_after_loss = kRenoBeta * expected_send_window;
338 size_t num_packets_to_lose =
339 (expected_send_window - send_window_after_loss) / kDefaultTCPMSS + 1;
340 LoseNPackets(num_packets_to_lose);
341 // Immediately after the loss, ensure at least one packet can be sent.
342 // Losses without subsequent acks can occur with timer based loss detection.
343 EXPECT_TRUE(sender_->TimeUntilSend(
344 clock_.Now(), bytes_in_flight_, HAS_RETRANSMITTABLE_DATA).IsZero());
345 AckNPackets(1);
347 // We should now have fallen out of slow start with a reduced window.
348 expected_send_window *= kRenoBeta;
349 EXPECT_EQ(expected_send_window, sender_->GetCongestionWindow());
351 // Only 2 packets should be allowed to be sent, per PRR-SSRB
352 EXPECT_EQ(2, SendAvailableSendWindow());
354 // Ack the next packet, which triggers another loss.
355 LoseNPackets(1);
356 AckNPackets(1);
358 // Send 2 packets to simulate PRR-SSRB.
359 EXPECT_EQ(2, SendAvailableSendWindow());
361 // Ack the next packet, which triggers another loss.
362 LoseNPackets(1);
363 AckNPackets(1);
365 // Send 2 packets to simulate PRR-SSRB.
366 EXPECT_EQ(2, SendAvailableSendWindow());
368 // Exit recovery and return to sending at the new rate.
369 for (int i = 0; i < kNumberOfAcks; ++i) {
370 AckNPackets(1);
371 EXPECT_EQ(1, SendAvailableSendWindow());
375 TEST_F(TcpCubicSenderTest, RTOCongestionWindow) {
376 EXPECT_EQ(kDefaultWindowTCP, sender_->GetCongestionWindow());
377 EXPECT_EQ(kMaxTcpCongestionWindow, sender_->slowstart_threshold());
379 // Expect the window to decrease to the minimum once the RTO fires
380 // and slow start threshold to be set to 1/2 of the CWND.
381 sender_->OnRetransmissionTimeout(true);
382 EXPECT_EQ(2 * kDefaultTCPMSS, sender_->GetCongestionWindow());
383 EXPECT_EQ(5u, sender_->slowstart_threshold());
386 TEST_F(TcpCubicSenderTest, RTOCongestionWindowNoRetransmission) {
387 EXPECT_EQ(kDefaultWindowTCP, sender_->GetCongestionWindow());
389 // Expect the window to remain unchanged if the RTO fires but no
390 // packets are retransmitted.
391 sender_->OnRetransmissionTimeout(false);
392 EXPECT_EQ(kDefaultWindowTCP, sender_->GetCongestionWindow());
395 TEST_F(TcpCubicSenderTest, RetransmissionDelay) {
396 const int64 kRttMs = 10;
397 const int64 kDeviationMs = 3;
398 EXPECT_EQ(QuicTime::Delta::Zero(), sender_->RetransmissionDelay());
400 sender_->rtt_stats_.UpdateRtt(QuicTime::Delta::FromMilliseconds(kRttMs),
401 QuicTime::Delta::Zero(), clock_.Now());
403 // Initial value is to set the median deviation to half of the initial
404 // rtt, the median in then multiplied by a factor of 4 and finally the
405 // smoothed rtt is added which is the initial rtt.
406 QuicTime::Delta expected_delay =
407 QuicTime::Delta::FromMilliseconds(kRttMs + kRttMs / 2 * 4);
408 EXPECT_EQ(expected_delay, sender_->RetransmissionDelay());
410 for (int i = 0; i < 100; ++i) {
411 // Run to make sure that we converge.
412 sender_->rtt_stats_.UpdateRtt(
413 QuicTime::Delta::FromMilliseconds(kRttMs + kDeviationMs),
414 QuicTime::Delta::Zero(), clock_.Now());
415 sender_->rtt_stats_.UpdateRtt(
416 QuicTime::Delta::FromMilliseconds(kRttMs - kDeviationMs),
417 QuicTime::Delta::Zero(), clock_.Now());
419 expected_delay = QuicTime::Delta::FromMilliseconds(kRttMs + kDeviationMs * 4);
421 EXPECT_NEAR(kRttMs, sender_->rtt_stats_.smoothed_rtt().ToMilliseconds(), 1);
422 EXPECT_NEAR(expected_delay.ToMilliseconds(),
423 sender_->RetransmissionDelay().ToMilliseconds(),
425 EXPECT_EQ(static_cast<int64>(
426 sender_->GetCongestionWindow() * kNumMicrosPerSecond /
427 sender_->rtt_stats_.smoothed_rtt().ToMicroseconds()),
428 sender_->BandwidthEstimate().ToBytesPerSecond());
431 TEST_F(TcpCubicSenderTest, SlowStartMaxSendWindow) {
432 const QuicPacketCount kMaxCongestionWindowTCP = 50;
433 const int kNumberOfAcks = 100;
434 sender_.reset(
435 new TcpCubicSenderPeer(&clock_, false, kMaxCongestionWindowTCP));
437 for (int i = 0; i < kNumberOfAcks; ++i) {
438 // Send our full send window.
439 SendAvailableSendWindow();
440 AckNPackets(2);
442 QuicByteCount expected_send_window = kMaxCongestionWindowTCP * kDefaultTCPMSS;
443 EXPECT_EQ(expected_send_window, sender_->GetCongestionWindow());
446 TEST_F(TcpCubicSenderTest, TcpRenoMaxCongestionWindow) {
447 const QuicPacketCount kMaxCongestionWindowTCP = 50;
448 const int kNumberOfAcks = 1000;
449 sender_.reset(new TcpCubicSenderPeer(&clock_, true, kMaxCongestionWindowTCP));
451 SendAvailableSendWindow();
452 AckNPackets(2);
453 // Make sure we fall out of slow start.
454 LoseNPackets(1);
456 for (int i = 0; i < kNumberOfAcks; ++i) {
457 // Send our full send window.
458 SendAvailableSendWindow();
459 AckNPackets(2);
462 QuicByteCount expected_send_window = kMaxCongestionWindowTCP * kDefaultTCPMSS;
463 EXPECT_EQ(expected_send_window, sender_->GetCongestionWindow());
466 TEST_F(TcpCubicSenderTest, TcpCubicMaxCongestionWindow) {
467 const QuicPacketCount kMaxCongestionWindowTCP = 50;
468 // Set to 10000 to compensate for small cubic alpha.
469 const int kNumberOfAcks = 10000;
471 sender_.reset(
472 new TcpCubicSenderPeer(&clock_, false, kMaxCongestionWindowTCP));
474 SendAvailableSendWindow();
475 AckNPackets(2);
476 // Make sure we fall out of slow start.
477 LoseNPackets(1);
479 for (int i = 0; i < kNumberOfAcks; ++i) {
480 // Send our full send window.
481 SendAvailableSendWindow();
482 AckNPackets(2);
485 QuicByteCount expected_send_window = kMaxCongestionWindowTCP * kDefaultTCPMSS;
486 EXPECT_EQ(expected_send_window, sender_->GetCongestionWindow());
489 TEST_F(TcpCubicSenderTest, MultipleLossesInOneWindow) {
490 SendAvailableSendWindow();
491 const QuicByteCount initial_window = sender_->GetCongestionWindow();
492 LosePacket(acked_sequence_number_ + 1);
493 const QuicByteCount post_loss_window = sender_->GetCongestionWindow();
494 EXPECT_GT(initial_window, post_loss_window);
495 LosePacket(acked_sequence_number_ + 3);
496 EXPECT_EQ(post_loss_window, sender_->GetCongestionWindow());
497 LosePacket(sequence_number_ - 1);
498 EXPECT_EQ(post_loss_window, sender_->GetCongestionWindow());
500 // Lose a later packet and ensure the window decreases.
501 LosePacket(sequence_number_);
502 EXPECT_GT(post_loss_window, sender_->GetCongestionWindow());
505 TEST_F(TcpCubicSenderTest, DontTrackAckPackets) {
506 // Send a packet with no retransmittable data, and ensure it's not tracked.
507 EXPECT_FALSE(sender_->OnPacketSent(clock_.Now(), bytes_in_flight_,
508 sequence_number_++, kDefaultTCPMSS,
509 NO_RETRANSMITTABLE_DATA));
511 // Send a data packet with retransmittable data, and ensure it is tracked.
512 EXPECT_TRUE(sender_->OnPacketSent(clock_.Now(), bytes_in_flight_,
513 sequence_number_++, kDefaultTCPMSS,
514 HAS_RETRANSMITTABLE_DATA));
517 TEST_F(TcpCubicSenderTest, ConfigureInitialWindow) {
518 QuicConfig config;
520 // Verify that kCOPT: kIW10 forces the congestion window to the default of 10.
521 QuicTagVector options;
522 options.push_back(kIW10);
523 QuicConfigPeer::SetReceivedConnectionOptions(&config, options);
524 sender_->SetFromConfig(config, Perspective::IS_SERVER);
525 EXPECT_EQ(10u, sender_->congestion_window());
528 TEST_F(TcpCubicSenderTest, ConfigureMinimumWindow) {
529 QuicConfig config;
531 // Verify that kCOPT: kMIN1 forces the min CWND to 1 packet.
532 QuicTagVector options;
533 options.push_back(kMIN1);
534 QuicConfigPeer::SetReceivedConnectionOptions(&config, options);
535 sender_->SetFromConfig(config, Perspective::IS_SERVER);
536 sender_->OnRetransmissionTimeout(true);
537 EXPECT_EQ(1u, sender_->congestion_window());
540 TEST_F(TcpCubicSenderTest, 2ConnectionCongestionAvoidanceAtEndOfRecovery) {
541 sender_->SetNumEmulatedConnections(2);
542 // Ack 10 packets in 5 acks to raise the CWND to 20.
543 const int kNumberOfAcks = 5;
544 for (int i = 0; i < kNumberOfAcks; ++i) {
545 // Send our full send window.
546 SendAvailableSendWindow();
547 AckNPackets(2);
549 SendAvailableSendWindow();
550 QuicByteCount expected_send_window = kDefaultWindowTCP +
551 (kDefaultTCPMSS * 2 * kNumberOfAcks);
552 EXPECT_EQ(expected_send_window, sender_->GetCongestionWindow());
554 LoseNPackets(1);
556 // We should now have fallen out of slow start with a reduced window.
557 expected_send_window = expected_send_window * sender_->GetRenoBeta();
558 EXPECT_EQ(expected_send_window, sender_->GetCongestionWindow());
560 // No congestion window growth should occur in recovery phase, i.e., until the
561 // currently outstanding 20 packets are acked.
562 for (int i = 0; i < 10; ++i) {
563 // Send our full send window.
564 SendAvailableSendWindow();
565 EXPECT_TRUE(sender_->InRecovery());
566 AckNPackets(2);
567 EXPECT_EQ(expected_send_window, sender_->GetCongestionWindow());
569 EXPECT_FALSE(sender_->InRecovery());
571 // Out of recovery now. Congestion window should not grow for half an RTT.
572 size_t packets_in_send_window = expected_send_window / kDefaultTCPMSS;
573 SendAvailableSendWindow();
574 AckNPackets(packets_in_send_window / 2 - 2);
575 EXPECT_EQ(expected_send_window, sender_->GetCongestionWindow());
577 // Next ack should increase congestion window by 1MSS.
578 SendAvailableSendWindow();
579 AckNPackets(2);
580 expected_send_window += kDefaultTCPMSS;
581 packets_in_send_window += 1;
582 EXPECT_EQ(expected_send_window, sender_->GetCongestionWindow());
584 // Congestion window should remain steady again for half an RTT.
585 SendAvailableSendWindow();
586 AckNPackets(packets_in_send_window / 2 - 1);
587 EXPECT_EQ(expected_send_window, sender_->GetCongestionWindow());
589 // Next ack should cause congestion window to grow by 1MSS.
590 SendAvailableSendWindow();
591 AckNPackets(2);
592 expected_send_window += kDefaultTCPMSS;
593 EXPECT_EQ(expected_send_window, sender_->GetCongestionWindow());
596 TEST_F(TcpCubicSenderTest, 1ConnectionCongestionAvoidanceAtEndOfRecovery) {
597 sender_->SetNumEmulatedConnections(1);
598 // Ack 10 packets in 5 acks to raise the CWND to 20.
599 const int kNumberOfAcks = 5;
600 for (int i = 0; i < kNumberOfAcks; ++i) {
601 // Send our full send window.
602 SendAvailableSendWindow();
603 AckNPackets(2);
605 SendAvailableSendWindow();
606 QuicByteCount expected_send_window = kDefaultWindowTCP +
607 (kDefaultTCPMSS * 2 * kNumberOfAcks);
608 EXPECT_EQ(expected_send_window, sender_->GetCongestionWindow());
610 LoseNPackets(1);
612 // We should now have fallen out of slow start with a reduced window.
613 expected_send_window *= kRenoBeta;
614 EXPECT_EQ(expected_send_window, sender_->GetCongestionWindow());
616 // No congestion window growth should occur in recovery phase, i.e., until the
617 // currently outstanding 20 packets are acked.
618 for (int i = 0; i < 10; ++i) {
619 // Send our full send window.
620 SendAvailableSendWindow();
621 EXPECT_TRUE(sender_->InRecovery());
622 AckNPackets(2);
623 EXPECT_EQ(expected_send_window, sender_->GetCongestionWindow());
625 EXPECT_FALSE(sender_->InRecovery());
627 // Out of recovery now. Congestion window should not grow during RTT.
628 for (uint64 i = 0; i < expected_send_window / kDefaultTCPMSS - 2; i += 2) {
629 // Send our full send window.
630 SendAvailableSendWindow();
631 AckNPackets(2);
632 EXPECT_EQ(expected_send_window, sender_->GetCongestionWindow());
635 // Next ack should cause congestion window to grow by 1MSS.
636 SendAvailableSendWindow();
637 AckNPackets(2);
638 expected_send_window += kDefaultTCPMSS;
639 EXPECT_EQ(expected_send_window, sender_->GetCongestionWindow());
642 TEST_F(TcpCubicSenderTest, BandwidthResumption) {
643 // Test that when provided with CachedNetworkParameters and opted in to the
644 // bandwidth resumption experiment, that the TcpCubicSender sets initial CWND
645 // appropriately.
647 // Set some common values.
648 CachedNetworkParameters cached_network_params;
649 const QuicPacketCount kNumberOfPackets = 123;
650 const int kBandwidthEstimateBytesPerSecond =
651 kNumberOfPackets * kMaxPacketSize;
652 cached_network_params.set_bandwidth_estimate_bytes_per_second(
653 kBandwidthEstimateBytesPerSecond);
654 cached_network_params.set_min_rtt_ms(1000);
656 // Ensure that an old estimate is not used for bandwidth resumption.
657 cached_network_params.set_timestamp(clock_.WallNow().ToUNIXSeconds() -
658 (kNumSecondsPerHour + 1));
659 EXPECT_FALSE(sender_->ResumeConnectionState(cached_network_params, false));
660 EXPECT_EQ(10u, sender_->congestion_window());
662 // If the estimate is new enough, make sure it is used.
663 cached_network_params.set_timestamp(clock_.WallNow().ToUNIXSeconds() -
664 (kNumSecondsPerHour - 1));
665 EXPECT_TRUE(sender_->ResumeConnectionState(cached_network_params, false));
666 EXPECT_EQ(kNumberOfPackets, sender_->congestion_window());
668 // Resumed CWND is limited to be in a sensible range.
669 cached_network_params.set_bandwidth_estimate_bytes_per_second(
670 (kMaxTcpCongestionWindow + 1) * kMaxPacketSize);
671 EXPECT_TRUE(sender_->ResumeConnectionState(cached_network_params, false));
672 EXPECT_EQ(kMaxTcpCongestionWindow, sender_->congestion_window());
674 cached_network_params.set_bandwidth_estimate_bytes_per_second(
675 (kMinCongestionWindowForBandwidthResumption - 1) * kMaxPacketSize);
676 EXPECT_TRUE(sender_->ResumeConnectionState(cached_network_params, false));
677 EXPECT_EQ(kMinCongestionWindowForBandwidthResumption,
678 sender_->congestion_window());
680 // Resume to the max value.
681 cached_network_params.set_max_bandwidth_estimate_bytes_per_second(
682 (kMinCongestionWindowForBandwidthResumption + 10) * kDefaultTCPMSS);
683 EXPECT_TRUE(sender_->ResumeConnectionState(cached_network_params, true));
684 EXPECT_EQ((kMinCongestionWindowForBandwidthResumption + 10) * kDefaultTCPMSS,
685 sender_->GetCongestionWindow());
688 } // namespace test
689 } // namespace net