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.
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"
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
{
34 TcpCubicSenderPeer(const QuicClock
* clock
,
36 QuicPacketCount max_tcp_congestion_window
)
37 : TcpCubicSender(clock
,
40 kInitialCongestionWindowPackets
,
41 max_tcp_congestion_window
,
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 {
61 QuicConnectionStats stats_
;
64 class TcpCubicSenderTest
: public ::testing::Test
{
67 : one_ms_(QuicTime::Delta::FromMilliseconds(1)),
68 sender_(new TcpCubicSenderPeer(&clock_
, true, kMaxTcpCongestionWindow
)),
70 acked_sequence_number_(0),
72 standard_packet_
.bytes_sent
= kDefaultTCPMSS
;
75 int SendAvailableSendWindow() {
76 // Send as long as TimeUntilSend returns Zero.
78 bool can_send
= sender_
->TimeUntilSend(
79 clock_
.Now(), bytes_in_flight_
, HAS_RETRANSMITTABLE_DATA
).IsZero();
81 sender_
->OnPacketSent(clock_
.Now(), bytes_in_flight_
, sequence_number_
++,
82 kDefaultTCPMSS
, HAS_RETRANSMITTABLE_DATA
);
84 bytes_in_flight_
+= kDefaultTCPMSS
;
85 can_send
= sender_
->TimeUntilSend(
86 clock_
.Now(), bytes_in_flight_
, HAS_RETRANSMITTABLE_DATA
).IsZero();
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(),
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_
;
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
) {
178 QuicByteCount bytes_to_send
= sender_
->GetCongestionWindow();
179 // It's expected 2 acks will arrive when the bytes_in_flight are greater than
181 EXPECT_EQ(kDefaultWindowTCP
+ kDefaultTCPMSS
* 2 * 2,
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();
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();
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.
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
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.
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);
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();
279 SendAvailableSendWindow();
280 QuicByteCount expected_send_window
= kDefaultWindowTCP
+
281 (kDefaultTCPMSS
* 2 * kNumberOfAcks
);
282 EXPECT_EQ(expected_send_window
, sender_
->GetCongestionWindow());
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
) {
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
) {
309 EXPECT_EQ(1, SendAvailableSendWindow());
310 EXPECT_EQ(expected_send_window
, sender_
->GetCongestionWindow());
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
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();
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());
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.
358 // Send 2 packets to simulate PRR-SSRB.
359 EXPECT_EQ(2, SendAvailableSendWindow());
361 // Ack the next packet, which triggers another loss.
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
) {
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;
435 new TcpCubicSenderPeer(&clock_
, false, kMaxCongestionWindowTCP
));
437 for (int i
= 0; i
< kNumberOfAcks
; ++i
) {
438 // Send our full send window.
439 SendAvailableSendWindow();
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();
453 // Make sure we fall out of slow start.
456 for (int i
= 0; i
< kNumberOfAcks
; ++i
) {
457 // Send our full send window.
458 SendAvailableSendWindow();
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;
472 new TcpCubicSenderPeer(&clock_
, false, kMaxCongestionWindowTCP
));
474 SendAvailableSendWindow();
476 // Make sure we fall out of slow start.
479 for (int i
= 0; i
< kNumberOfAcks
; ++i
) {
480 // Send our full send window.
481 SendAvailableSendWindow();
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
) {
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
) {
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();
549 SendAvailableSendWindow();
550 QuicByteCount expected_send_window
= kDefaultWindowTCP
+
551 (kDefaultTCPMSS
* 2 * kNumberOfAcks
);
552 EXPECT_EQ(expected_send_window
, sender_
->GetCongestionWindow());
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());
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();
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();
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();
605 SendAvailableSendWindow();
606 QuicByteCount expected_send_window
= kDefaultWindowTCP
+
607 (kDefaultTCPMSS
* 2 * kNumberOfAcks
);
608 EXPECT_EQ(expected_send_window
, sender_
->GetCongestionWindow());
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());
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();
632 EXPECT_EQ(expected_send_window
, sender_
->GetCongestionWindow());
635 // Next ack should cause congestion window to grow by 1MSS.
636 SendAvailableSendWindow();
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
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());