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/quic_protocol.h"
13 #include "net/quic/quic_utils.h"
14 #include "net/quic/test_tools/mock_clock.h"
15 #include "net/quic/test_tools/quic_config_peer.h"
16 #include "testing/gtest/include/gtest/gtest.h"
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
25 // updated to be based on kInitialCongestionWindowInsecure.
26 const uint32 kInitialCongestionWindowPackets
= 10;
27 const uint32 kDefaultWindowTCP
=
28 kInitialCongestionWindowPackets
* kDefaultTCPMSS
;
29 const float kRenoBeta
= 0.7f
; // Reno backoff factor.
31 class TcpCubicSenderPeer
: public TcpCubicSender
{
33 TcpCubicSenderPeer(const QuicClock
* clock
, bool reno
)
34 : TcpCubicSender(clock
,
37 kInitialCongestionWindowPackets
,
40 QuicPacketCount
congestion_window() {
41 return congestion_window_
;
44 QuicPacketCount
slowstart_threshold() {
45 return slowstart_threshold_
;
48 const HybridSlowStart
& hybrid_slow_start() const {
49 return hybrid_slow_start_
;
52 float GetRenoBeta() const {
57 QuicConnectionStats stats_
;
60 class TcpCubicSenderTest
: public ::testing::Test
{
63 : one_ms_(QuicTime::Delta::FromMilliseconds(1)),
64 sender_(new TcpCubicSenderPeer(&clock_
, true)),
66 acked_sequence_number_(0),
68 standard_packet_
.bytes_sent
= kDefaultTCPMSS
;
71 int SendAvailableSendWindow() {
72 // Send as long as TimeUntilSend returns Zero.
74 bool can_send
= sender_
->TimeUntilSend(
75 clock_
.Now(), bytes_in_flight_
, HAS_RETRANSMITTABLE_DATA
).IsZero();
77 sender_
->OnPacketSent(clock_
.Now(), bytes_in_flight_
, sequence_number_
++,
78 kDefaultTCPMSS
, HAS_RETRANSMITTABLE_DATA
);
80 bytes_in_flight_
+= kDefaultTCPMSS
;
81 can_send
= sender_
->TimeUntilSend(
82 clock_
.Now(), bytes_in_flight_
, HAS_RETRANSMITTABLE_DATA
).IsZero();
87 // Normal is that TCP acks every other segment.
88 void AckNPackets(int n
) {
89 sender_
->rtt_stats_
.UpdateRtt(QuicTime::Delta::FromMilliseconds(60),
90 QuicTime::Delta::Zero(),
92 SendAlgorithmInterface::CongestionVector acked_packets
;
93 SendAlgorithmInterface::CongestionVector lost_packets
;
94 for (int i
= 0; i
< n
; ++i
) {
95 ++acked_sequence_number_
;
96 acked_packets
.push_back(
97 std::make_pair(acked_sequence_number_
, standard_packet_
));
99 sender_
->OnCongestionEvent(
100 true, bytes_in_flight_
, acked_packets
, lost_packets
);
101 bytes_in_flight_
-= n
* kDefaultTCPMSS
;
102 clock_
.AdvanceTime(one_ms_
);
105 void LoseNPackets(int n
) {
106 SendAlgorithmInterface::CongestionVector acked_packets
;
107 SendAlgorithmInterface::CongestionVector lost_packets
;
108 for (int i
= 0; i
< n
; ++i
) {
109 ++acked_sequence_number_
;
110 lost_packets
.push_back(
111 std::make_pair(acked_sequence_number_
, standard_packet_
));
113 sender_
->OnCongestionEvent(
114 false, bytes_in_flight_
, acked_packets
, lost_packets
);
115 bytes_in_flight_
-= n
* kDefaultTCPMSS
;
118 // Does not increment acked_sequence_number_.
119 void LosePacket(QuicPacketSequenceNumber sequence_number
) {
120 SendAlgorithmInterface::CongestionVector acked_packets
;
121 SendAlgorithmInterface::CongestionVector lost_packets
;
122 lost_packets
.push_back(std::make_pair(sequence_number
, standard_packet_
));
123 sender_
->OnCongestionEvent(
124 false, bytes_in_flight_
, acked_packets
, lost_packets
);
125 bytes_in_flight_
-= kDefaultTCPMSS
;
128 const QuicTime::Delta one_ms_
;
130 scoped_ptr
<TcpCubicSenderPeer
> sender_
;
131 QuicPacketSequenceNumber sequence_number_
;
132 QuicPacketSequenceNumber acked_sequence_number_
;
133 QuicByteCount bytes_in_flight_
;
134 TransmissionInfo standard_packet_
;
137 TEST_F(TcpCubicSenderTest
, SimpleSender
) {
138 // At startup make sure we are at the default.
139 EXPECT_EQ(kDefaultWindowTCP
, sender_
->GetCongestionWindow());
140 // At startup make sure we can send.
141 EXPECT_TRUE(sender_
->TimeUntilSend(clock_
.Now(),
143 HAS_RETRANSMITTABLE_DATA
).IsZero());
144 // Make sure we can send.
145 EXPECT_TRUE(sender_
->TimeUntilSend(clock_
.Now(),
147 HAS_RETRANSMITTABLE_DATA
).IsZero());
148 // And that window is un-affected.
149 EXPECT_EQ(kDefaultWindowTCP
, sender_
->GetCongestionWindow());
151 // Fill the send window with data, then verify that we can't send.
152 SendAvailableSendWindow();
153 EXPECT_FALSE(sender_
->TimeUntilSend(clock_
.Now(),
154 sender_
->GetCongestionWindow(),
155 HAS_RETRANSMITTABLE_DATA
).IsZero());
158 TEST_F(TcpCubicSenderTest
, ApplicationLimitedSlowStart
) {
159 // Send exactly 10 packets and ensure the CWND ends at 14 packets.
160 const int kNumberOfAcks
= 5;
161 // At startup make sure we can send.
162 EXPECT_TRUE(sender_
->TimeUntilSend(clock_
.Now(),
164 HAS_RETRANSMITTABLE_DATA
).IsZero());
165 // Make sure we can send.
166 EXPECT_TRUE(sender_
->TimeUntilSend(clock_
.Now(),
168 HAS_RETRANSMITTABLE_DATA
).IsZero());
170 SendAvailableSendWindow();
171 for (int i
= 0; i
< kNumberOfAcks
; ++i
) {
174 QuicByteCount bytes_to_send
= sender_
->GetCongestionWindow();
175 // It's expected 2 acks will arrive when the bytes_in_flight are greater than
177 EXPECT_EQ(kDefaultWindowTCP
+ kDefaultTCPMSS
* 2 * 2,
181 TEST_F(TcpCubicSenderTest
, ExponentialSlowStart
) {
182 const int kNumberOfAcks
= 20;
183 // At startup make sure we can send.
184 EXPECT_TRUE(sender_
->TimeUntilSend(clock_
.Now(),
186 HAS_RETRANSMITTABLE_DATA
).IsZero());
187 EXPECT_FALSE(sender_
->HasReliableBandwidthEstimate());
188 EXPECT_EQ(QuicBandwidth::Zero(), sender_
->BandwidthEstimate());
189 // Make sure we can send.
190 EXPECT_TRUE(sender_
->TimeUntilSend(clock_
.Now(),
192 HAS_RETRANSMITTABLE_DATA
).IsZero());
194 for (int i
= 0; i
< kNumberOfAcks
; ++i
) {
195 // Send our full send window.
196 SendAvailableSendWindow();
199 const QuicByteCount cwnd
= sender_
->GetCongestionWindow();
200 EXPECT_EQ(kDefaultWindowTCP
+ kDefaultTCPMSS
* 2 * kNumberOfAcks
, cwnd
);
201 EXPECT_FALSE(sender_
->HasReliableBandwidthEstimate());
202 EXPECT_EQ(QuicBandwidth::FromBytesAndTimeDelta(
203 cwnd
, sender_
->rtt_stats_
.smoothed_rtt()),
204 sender_
->BandwidthEstimate());
207 TEST_F(TcpCubicSenderTest
, SlowStartAckTrain
) {
208 sender_
->SetNumEmulatedConnections(1);
210 // 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
212 // Ack2Packets in one round.
213 // 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
215 const int kNumberOfAcks
= 65;
216 for (int i
= 0; i
< kNumberOfAcks
; ++i
) {
217 // Send our full send window.
218 SendAvailableSendWindow();
221 QuicByteCount expected_send_window
=
222 kDefaultWindowTCP
+ (kDefaultTCPMSS
* 2 * kNumberOfAcks
);
223 EXPECT_EQ(expected_send_window
, sender_
->GetCongestionWindow());
225 // We should now have fallen out of slow start.
226 // Testing Reno phase.
227 // We should need 140(65*2+10) ACK:ed packets before increasing window by
229 for (int i
= 0; i
< 69; ++i
) {
230 SendAvailableSendWindow();
232 EXPECT_EQ(expected_send_window
, sender_
->GetCongestionWindow());
234 SendAvailableSendWindow();
236 QuicByteCount expected_ss_tresh
= expected_send_window
;
237 expected_send_window
+= kDefaultTCPMSS
;
238 EXPECT_EQ(expected_send_window
, sender_
->GetCongestionWindow());
239 EXPECT_EQ(expected_ss_tresh
, sender_
->GetSlowStartThreshold());
240 EXPECT_EQ(140u, sender_
->slowstart_threshold());
242 // Now RTO and ensure slow start gets reset.
243 EXPECT_TRUE(sender_
->hybrid_slow_start().started());
244 sender_
->OnRetransmissionTimeout(true);
245 EXPECT_FALSE(sender_
->hybrid_slow_start().started());
246 EXPECT_EQ(2 * kDefaultTCPMSS
, sender_
->GetCongestionWindow());
247 EXPECT_EQ(expected_send_window
/ 2 / kDefaultTCPMSS
,
248 sender_
->slowstart_threshold());
251 TEST_F(TcpCubicSenderTest
, SlowStartPacketLoss
) {
252 sender_
->SetNumEmulatedConnections(1);
253 const int kNumberOfAcks
= 10;
254 for (int i
= 0; i
< kNumberOfAcks
; ++i
) {
255 // Send our full send window.
256 SendAvailableSendWindow();
259 SendAvailableSendWindow();
260 QuicByteCount expected_send_window
= kDefaultWindowTCP
+
261 (kDefaultTCPMSS
* 2 * kNumberOfAcks
);
262 EXPECT_EQ(expected_send_window
, sender_
->GetCongestionWindow());
264 // Lose a packet to exit slow start.
266 size_t packets_in_recovery_window
= expected_send_window
/ kDefaultTCPMSS
;
268 // We should now have fallen out of slow start with a reduced window.
269 expected_send_window
*= kRenoBeta
;
270 EXPECT_EQ(expected_send_window
, sender_
->GetCongestionWindow());
272 // Recovery phase. We need to ack every packet in the recovery window before
274 size_t number_of_packets_in_window
= expected_send_window
/ kDefaultTCPMSS
;
275 DVLOG(1) << "number_packets: " << number_of_packets_in_window
;
276 AckNPackets(packets_in_recovery_window
);
277 SendAvailableSendWindow();
278 EXPECT_EQ(expected_send_window
, sender_
->GetCongestionWindow());
280 // We need to ack an entire window before we increase CWND by 1.
281 AckNPackets(number_of_packets_in_window
- 2);
282 SendAvailableSendWindow();
283 EXPECT_EQ(expected_send_window
, sender_
->GetCongestionWindow());
285 // Next ack should increase cwnd by 1.
287 expected_send_window
+= kDefaultTCPMSS
;
288 EXPECT_EQ(expected_send_window
, sender_
->GetCongestionWindow());
290 // Now RTO and ensure slow start gets reset.
291 EXPECT_TRUE(sender_
->hybrid_slow_start().started());
292 sender_
->OnRetransmissionTimeout(true);
293 EXPECT_FALSE(sender_
->hybrid_slow_start().started());
296 TEST_F(TcpCubicSenderTest
, NoPRRWhenLessThanOnePacketInFlight
) {
297 SendAvailableSendWindow();
298 LoseNPackets(kInitialCongestionWindowPackets
- 1);
300 // PRR will allow 2 packets for every ack during recovery.
301 EXPECT_EQ(2, SendAvailableSendWindow());
302 // Simulate abandoning all packets by supplying a bytes_in_flight of 0.
303 // PRR should now allow a packet to be sent, even though prr's state
304 // variables believe it has sent enough packets.
305 EXPECT_EQ(QuicTime::Delta::Zero(),
306 sender_
->TimeUntilSend(clock_
.Now(), 0, HAS_RETRANSMITTABLE_DATA
));
309 TEST_F(TcpCubicSenderTest
, SlowStartPacketLossPRR
) {
310 sender_
->SetNumEmulatedConnections(1);
311 // Test based on the first example in RFC6937.
312 // Ack 10 packets in 5 acks to raise the CWND to 20, as in the example.
313 const int kNumberOfAcks
= 5;
314 for (int i
= 0; i
< kNumberOfAcks
; ++i
) {
315 // Send our full send window.
316 SendAvailableSendWindow();
319 SendAvailableSendWindow();
320 QuicByteCount expected_send_window
= kDefaultWindowTCP
+
321 (kDefaultTCPMSS
* 2 * kNumberOfAcks
);
322 EXPECT_EQ(expected_send_window
, sender_
->GetCongestionWindow());
326 // We should now have fallen out of slow start with a reduced window.
327 size_t send_window_before_loss
= expected_send_window
;
328 expected_send_window
*= kRenoBeta
;
329 EXPECT_EQ(expected_send_window
, sender_
->GetCongestionWindow());
331 // Testing TCP proportional rate reduction.
332 // We should send packets paced over the received acks for the remaining
333 // outstanding packets. The number of packets before we exit recovery is the
334 // original CWND minus the packet that has been lost and the one which
335 // triggered the loss.
336 size_t remaining_packets_in_recovery
=
337 send_window_before_loss
/ kDefaultTCPMSS
- 2;
339 for (size_t i
= 0; i
< remaining_packets_in_recovery
; ++i
) {
341 SendAvailableSendWindow();
342 EXPECT_EQ(expected_send_window
, sender_
->GetCongestionWindow());
345 // We need to ack another window before we increase CWND by 1.
346 size_t number_of_packets_in_window
= expected_send_window
/ kDefaultTCPMSS
;
347 for (size_t i
= 0; i
< number_of_packets_in_window
; ++i
) {
349 EXPECT_EQ(1, SendAvailableSendWindow());
350 EXPECT_EQ(expected_send_window
, sender_
->GetCongestionWindow());
354 expected_send_window
+= kDefaultTCPMSS
;
355 EXPECT_EQ(expected_send_window
, sender_
->GetCongestionWindow());
358 TEST_F(TcpCubicSenderTest
, SlowStartBurstPacketLossPRR
) {
359 sender_
->SetNumEmulatedConnections(1);
360 // Test based on the second example in RFC6937, though we also implement
361 // forward acknowledgements, so the first two incoming acks will trigger
363 // Ack 20 packets in 10 acks to raise the CWND to 30.
364 const int kNumberOfAcks
= 10;
365 for (int i
= 0; i
< kNumberOfAcks
; ++i
) {
366 // Send our full send window.
367 SendAvailableSendWindow();
370 SendAvailableSendWindow();
371 QuicByteCount expected_send_window
= kDefaultWindowTCP
+
372 (kDefaultTCPMSS
* 2 * kNumberOfAcks
);
373 EXPECT_EQ(expected_send_window
, sender_
->GetCongestionWindow());
375 // Lose one more than the congestion window reduction, so that after loss,
376 // bytes_in_flight is lesser than the congestion window.
377 size_t send_window_after_loss
= kRenoBeta
* expected_send_window
;
378 size_t num_packets_to_lose
=
379 (expected_send_window
- send_window_after_loss
) / kDefaultTCPMSS
+ 1;
380 LoseNPackets(num_packets_to_lose
);
381 // Immediately after the loss, ensure at least one packet can be sent.
382 // Losses without subsequent acks can occur with timer based loss detection.
383 EXPECT_TRUE(sender_
->TimeUntilSend(
384 clock_
.Now(), bytes_in_flight_
, HAS_RETRANSMITTABLE_DATA
).IsZero());
387 // We should now have fallen out of slow start with a reduced window.
388 expected_send_window
*= kRenoBeta
;
389 EXPECT_EQ(expected_send_window
, sender_
->GetCongestionWindow());
391 // Only 2 packets should be allowed to be sent, per PRR-SSRB
392 EXPECT_EQ(2, SendAvailableSendWindow());
394 // Ack the next packet, which triggers another loss.
398 // Send 2 packets to simulate PRR-SSRB.
399 EXPECT_EQ(2, SendAvailableSendWindow());
401 // Ack the next packet, which triggers another loss.
405 // Send 2 packets to simulate PRR-SSRB.
406 EXPECT_EQ(2, SendAvailableSendWindow());
408 // Exit recovery and return to sending at the new rate.
409 for (int i
= 0; i
< kNumberOfAcks
; ++i
) {
411 EXPECT_EQ(1, SendAvailableSendWindow());
415 TEST_F(TcpCubicSenderTest
, RTOCongestionWindow
) {
416 EXPECT_EQ(kDefaultWindowTCP
, sender_
->GetCongestionWindow());
417 // 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.
419 sender_
->OnRetransmissionTimeout(true);
420 EXPECT_EQ(2 * kDefaultTCPMSS
, sender_
->GetCongestionWindow());
421 EXPECT_EQ(5u, sender_
->slowstart_threshold());
424 TEST_F(TcpCubicSenderTest
, RTOCongestionWindowNoRetransmission
) {
425 EXPECT_EQ(kDefaultWindowTCP
, sender_
->GetCongestionWindow());
427 // Expect the window to remain unchanged if the RTO fires but no
428 // packets are retransmitted.
429 sender_
->OnRetransmissionTimeout(false);
430 EXPECT_EQ(kDefaultWindowTCP
, sender_
->GetCongestionWindow());
433 TEST_F(TcpCubicSenderTest
, RetransmissionDelay
) {
434 const int64 kRttMs
= 10;
435 const int64 kDeviationMs
= 3;
436 EXPECT_EQ(QuicTime::Delta::Zero(), sender_
->RetransmissionDelay());
438 sender_
->rtt_stats_
.UpdateRtt(QuicTime::Delta::FromMilliseconds(kRttMs
),
439 QuicTime::Delta::Zero(), clock_
.Now());
441 // Initial value is to set the median deviation to half of the initial
442 // rtt, the median in then multiplied by a factor of 4 and finally the
443 // smoothed rtt is added which is the initial rtt.
444 QuicTime::Delta expected_delay
=
445 QuicTime::Delta::FromMilliseconds(kRttMs
+ kRttMs
/ 2 * 4);
446 EXPECT_EQ(expected_delay
, sender_
->RetransmissionDelay());
448 for (int i
= 0; i
< 100; ++i
) {
449 // Run to make sure that we converge.
450 sender_
->rtt_stats_
.UpdateRtt(
451 QuicTime::Delta::FromMilliseconds(kRttMs
+ kDeviationMs
),
452 QuicTime::Delta::Zero(), clock_
.Now());
453 sender_
->rtt_stats_
.UpdateRtt(
454 QuicTime::Delta::FromMilliseconds(kRttMs
- kDeviationMs
),
455 QuicTime::Delta::Zero(), clock_
.Now());
457 expected_delay
= QuicTime::Delta::FromMilliseconds(kRttMs
+ kDeviationMs
* 4);
459 EXPECT_NEAR(kRttMs
, sender_
->rtt_stats_
.smoothed_rtt().ToMilliseconds(), 1);
460 EXPECT_NEAR(expected_delay
.ToMilliseconds(),
461 sender_
->RetransmissionDelay().ToMilliseconds(),
463 EXPECT_EQ(static_cast<int64
>(
464 sender_
->GetCongestionWindow() * kNumMicrosPerSecond
/
465 sender_
->rtt_stats_
.smoothed_rtt().ToMicroseconds()),
466 sender_
->BandwidthEstimate().ToBytesPerSecond());
469 TEST_F(TcpCubicSenderTest
, MultipleLossesInOneWindow
) {
470 SendAvailableSendWindow();
471 const QuicByteCount initial_window
= sender_
->GetCongestionWindow();
472 LosePacket(acked_sequence_number_
+ 1);
473 const QuicByteCount post_loss_window
= sender_
->GetCongestionWindow();
474 EXPECT_GT(initial_window
, post_loss_window
);
475 LosePacket(acked_sequence_number_
+ 3);
476 EXPECT_EQ(post_loss_window
, sender_
->GetCongestionWindow());
477 LosePacket(sequence_number_
- 1);
478 EXPECT_EQ(post_loss_window
, sender_
->GetCongestionWindow());
480 // Lose a later packet and ensure the window decreases.
481 LosePacket(sequence_number_
);
482 EXPECT_GT(post_loss_window
, sender_
->GetCongestionWindow());
485 TEST_F(TcpCubicSenderTest
, DontTrackAckPackets
) {
486 // Send a packet with no retransmittable data, and ensure it's not tracked.
487 EXPECT_FALSE(sender_
->OnPacketSent(clock_
.Now(), bytes_in_flight_
,
488 sequence_number_
++, kDefaultTCPMSS
,
489 NO_RETRANSMITTABLE_DATA
));
491 // Send a data packet with retransmittable data, and ensure it is tracked.
492 EXPECT_TRUE(sender_
->OnPacketSent(clock_
.Now(), bytes_in_flight_
,
493 sequence_number_
++, kDefaultTCPMSS
,
494 HAS_RETRANSMITTABLE_DATA
));
497 TEST_F(TcpCubicSenderTest
, ConfigureMaxInitialWindow
) {
500 // Verify that kCOPT: kIW10 forces the congestion window to the default of 10.
501 QuicTagVector options
;
502 options
.push_back(kIW10
);
503 QuicConfigPeer::SetReceivedConnectionOptions(&config
, options
);
504 sender_
->SetFromConfig(config
,
505 /* is_server= */ true,
506 /* using_pacing= */ false);
507 EXPECT_EQ(10u, sender_
->congestion_window());
510 TEST_F(TcpCubicSenderTest
, DisableAckTrainDetectionWithPacing
) {
511 EXPECT_TRUE(sender_
->hybrid_slow_start().ack_train_detection());
514 sender_
->SetFromConfig(config
,
515 /* is_server= */ true,
516 /* using_pacing= */ true);
517 EXPECT_FALSE(sender_
->hybrid_slow_start().ack_train_detection());
520 TEST_F(TcpCubicSenderTest
, 2ConnectionCongestionAvoidanceAtEndOfRecovery
) {
521 sender_
->SetNumEmulatedConnections(2);
522 // Ack 10 packets in 5 acks to raise the CWND to 20.
523 const int kNumberOfAcks
= 5;
524 for (int i
= 0; i
< kNumberOfAcks
; ++i
) {
525 // Send our full send window.
526 SendAvailableSendWindow();
529 SendAvailableSendWindow();
530 QuicByteCount expected_send_window
= kDefaultWindowTCP
+
531 (kDefaultTCPMSS
* 2 * kNumberOfAcks
);
532 EXPECT_EQ(expected_send_window
, sender_
->GetCongestionWindow());
536 // We should now have fallen out of slow start with a reduced window.
537 expected_send_window
= expected_send_window
* sender_
->GetRenoBeta();
538 EXPECT_EQ(expected_send_window
, sender_
->GetCongestionWindow());
540 // No congestion window growth should occur in recovery phase, i.e., until the
541 // currently outstanding 20 packets are acked.
542 for (int i
= 0; i
< 10; ++i
) {
543 // Send our full send window.
544 SendAvailableSendWindow();
545 EXPECT_TRUE(sender_
->InRecovery());
547 EXPECT_EQ(expected_send_window
, sender_
->GetCongestionWindow());
549 EXPECT_FALSE(sender_
->InRecovery());
551 // Out of recovery now. Congestion window should not grow for half an RTT.
552 size_t packets_in_send_window
= expected_send_window
/ kDefaultTCPMSS
;
553 SendAvailableSendWindow();
554 AckNPackets(packets_in_send_window
/ 2 - 2);
555 EXPECT_EQ(expected_send_window
, sender_
->GetCongestionWindow());
557 // Next ack should increase congestion window by 1MSS.
558 SendAvailableSendWindow();
560 expected_send_window
+= kDefaultTCPMSS
;
561 packets_in_send_window
+= 1;
562 EXPECT_EQ(expected_send_window
, sender_
->GetCongestionWindow());
564 // Congestion window should remain steady again for half an RTT.
565 SendAvailableSendWindow();
566 AckNPackets(packets_in_send_window
/ 2 - 1);
567 EXPECT_EQ(expected_send_window
, sender_
->GetCongestionWindow());
569 // Next ack should cause congestion window to grow by 1MSS.
570 SendAvailableSendWindow();
572 expected_send_window
+= kDefaultTCPMSS
;
573 EXPECT_EQ(expected_send_window
, sender_
->GetCongestionWindow());
576 TEST_F(TcpCubicSenderTest
, 1ConnectionCongestionAvoidanceAtEndOfRecovery
) {
577 sender_
->SetNumEmulatedConnections(1);
578 // Ack 10 packets in 5 acks to raise the CWND to 20.
579 const int kNumberOfAcks
= 5;
580 for (int i
= 0; i
< kNumberOfAcks
; ++i
) {
581 // Send our full send window.
582 SendAvailableSendWindow();
585 SendAvailableSendWindow();
586 QuicByteCount expected_send_window
= kDefaultWindowTCP
+
587 (kDefaultTCPMSS
* 2 * kNumberOfAcks
);
588 EXPECT_EQ(expected_send_window
, sender_
->GetCongestionWindow());
592 // We should now have fallen out of slow start with a reduced window.
593 expected_send_window
*= kRenoBeta
;
594 EXPECT_EQ(expected_send_window
, sender_
->GetCongestionWindow());
596 // No congestion window growth should occur in recovery phase, i.e., until the
597 // currently outstanding 20 packets are acked.
598 for (int i
= 0; i
< 10; ++i
) {
599 // Send our full send window.
600 SendAvailableSendWindow();
601 EXPECT_TRUE(sender_
->InRecovery());
603 EXPECT_EQ(expected_send_window
, sender_
->GetCongestionWindow());
605 EXPECT_FALSE(sender_
->InRecovery());
607 // Out of recovery now. Congestion window should not grow during RTT.
608 for (uint64 i
= 0; i
< expected_send_window
/ kDefaultTCPMSS
- 2; i
+= 2) {
609 // Send our full send window.
610 SendAvailableSendWindow();
612 EXPECT_EQ(expected_send_window
, sender_
->GetCongestionWindow());
615 // Next ack should cause congestion window to grow by 1MSS.
616 SendAvailableSendWindow();
618 expected_send_window
+= kDefaultTCPMSS
;
619 EXPECT_EQ(expected_send_window
, sender_
->GetCongestionWindow());
622 TEST_F(TcpCubicSenderTest
, BandwidthResumption
) {
623 // Test that when provided with CachedNetworkParameters and opted in to the
624 // bandwidth resumption experiment, that the TcpCubicSender sets initial CWND
627 // Set some common values.
628 CachedNetworkParameters cached_network_params
;
629 const QuicPacketCount kNumberOfPackets
= 123;
630 const int kBandwidthEstimateBytesPerSecond
=
631 kNumberOfPackets
* kMaxPacketSize
;
632 cached_network_params
.set_bandwidth_estimate_bytes_per_second(
633 kBandwidthEstimateBytesPerSecond
);
634 cached_network_params
.set_min_rtt_ms(1000);
636 // Ensure that an old estimate is not used for bandwidth resumption.
637 cached_network_params
.set_timestamp(clock_
.WallNow().ToUNIXSeconds() -
638 (kNumSecondsPerHour
+ 1));
639 EXPECT_FALSE(sender_
->ResumeConnectionState(cached_network_params
));
640 EXPECT_EQ(10u, sender_
->congestion_window());
642 // If the estimate is new enough, make sure it is used.
643 cached_network_params
.set_timestamp(clock_
.WallNow().ToUNIXSeconds() -
644 (kNumSecondsPerHour
- 1));
645 EXPECT_TRUE(sender_
->ResumeConnectionState(cached_network_params
));
646 EXPECT_EQ(kNumberOfPackets
, sender_
->congestion_window());
648 // Resumed CWND is limited to be in a sensible range.
649 cached_network_params
.set_bandwidth_estimate_bytes_per_second(
650 (kMaxCongestionWindowForBandwidthResumption
+ 1) * kMaxPacketSize
);
651 EXPECT_TRUE(sender_
->ResumeConnectionState(cached_network_params
));
652 EXPECT_EQ(kMaxCongestionWindowForBandwidthResumption
,
653 sender_
->congestion_window());
655 cached_network_params
.set_bandwidth_estimate_bytes_per_second(
656 (kMinCongestionWindowForBandwidthResumption
- 1) * kMaxPacketSize
);
657 EXPECT_TRUE(sender_
->ResumeConnectionState(cached_network_params
));
658 EXPECT_EQ(kMinCongestionWindowForBandwidthResumption
,
659 sender_
->congestion_window());