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, kMaxCongestionWindow
)),
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_EQ(QuicBandwidth::Zero(), sender_
->BandwidthEstimate());
192 // Make sure we can send.
193 EXPECT_TRUE(sender_
->TimeUntilSend(clock_
.Now(),
195 HAS_RETRANSMITTABLE_DATA
).IsZero());
197 for (int i
= 0; i
< kNumberOfAcks
; ++i
) {
198 // Send our full send window.
199 SendAvailableSendWindow();
202 const QuicByteCount cwnd
= sender_
->GetCongestionWindow();
203 EXPECT_EQ(kDefaultWindowTCP
+ kDefaultTCPMSS
* 2 * kNumberOfAcks
, cwnd
);
204 EXPECT_EQ(QuicBandwidth::FromBytesAndTimeDelta(
205 cwnd
, sender_
->rtt_stats_
.smoothed_rtt()),
206 sender_
->BandwidthEstimate());
209 TEST_F(TcpCubicSenderTest
, SlowStartPacketLoss
) {
210 sender_
->SetNumEmulatedConnections(1);
211 const int kNumberOfAcks
= 10;
212 for (int i
= 0; i
< kNumberOfAcks
; ++i
) {
213 // Send our full send window.
214 SendAvailableSendWindow();
217 SendAvailableSendWindow();
218 QuicByteCount expected_send_window
= kDefaultWindowTCP
+
219 (kDefaultTCPMSS
* 2 * kNumberOfAcks
);
220 EXPECT_EQ(expected_send_window
, sender_
->GetCongestionWindow());
222 // Lose a packet to exit slow start.
224 size_t packets_in_recovery_window
= expected_send_window
/ kDefaultTCPMSS
;
226 // We should now have fallen out of slow start with a reduced window.
227 expected_send_window
*= kRenoBeta
;
228 EXPECT_EQ(expected_send_window
, sender_
->GetCongestionWindow());
230 // Recovery phase. We need to ack every packet in the recovery window before
232 size_t number_of_packets_in_window
= expected_send_window
/ kDefaultTCPMSS
;
233 DVLOG(1) << "number_packets: " << number_of_packets_in_window
;
234 AckNPackets(packets_in_recovery_window
);
235 SendAvailableSendWindow();
236 EXPECT_EQ(expected_send_window
, sender_
->GetCongestionWindow());
238 // We need to ack an entire window before we increase CWND by 1.
239 AckNPackets(number_of_packets_in_window
- 2);
240 SendAvailableSendWindow();
241 EXPECT_EQ(expected_send_window
, sender_
->GetCongestionWindow());
243 // Next ack should increase cwnd by 1.
245 expected_send_window
+= kDefaultTCPMSS
;
246 EXPECT_EQ(expected_send_window
, sender_
->GetCongestionWindow());
248 // Now RTO and ensure slow start gets reset.
249 EXPECT_TRUE(sender_
->hybrid_slow_start().started());
250 sender_
->OnRetransmissionTimeout(true);
251 EXPECT_FALSE(sender_
->hybrid_slow_start().started());
254 TEST_F(TcpCubicSenderTest
, NoPRRWhenLessThanOnePacketInFlight
) {
255 SendAvailableSendWindow();
256 LoseNPackets(kInitialCongestionWindowPackets
- 1);
258 // PRR will allow 2 packets for every ack during recovery.
259 EXPECT_EQ(2, SendAvailableSendWindow());
260 // Simulate abandoning all packets by supplying a bytes_in_flight of 0.
261 // PRR should now allow a packet to be sent, even though prr's state
262 // variables believe it has sent enough packets.
263 EXPECT_EQ(QuicTime::Delta::Zero(),
264 sender_
->TimeUntilSend(clock_
.Now(), 0, HAS_RETRANSMITTABLE_DATA
));
267 TEST_F(TcpCubicSenderTest
, SlowStartPacketLossPRR
) {
268 sender_
->SetNumEmulatedConnections(1);
269 // Test based on the first example in RFC6937.
270 // Ack 10 packets in 5 acks to raise the CWND to 20, as in the example.
271 const int kNumberOfAcks
= 5;
272 for (int i
= 0; i
< kNumberOfAcks
; ++i
) {
273 // Send our full send window.
274 SendAvailableSendWindow();
277 SendAvailableSendWindow();
278 QuicByteCount expected_send_window
= kDefaultWindowTCP
+
279 (kDefaultTCPMSS
* 2 * kNumberOfAcks
);
280 EXPECT_EQ(expected_send_window
, sender_
->GetCongestionWindow());
284 // We should now have fallen out of slow start with a reduced window.
285 size_t send_window_before_loss
= expected_send_window
;
286 expected_send_window
*= kRenoBeta
;
287 EXPECT_EQ(expected_send_window
, sender_
->GetCongestionWindow());
289 // Testing TCP proportional rate reduction.
290 // We should send packets paced over the received acks for the remaining
291 // outstanding packets. The number of packets before we exit recovery is the
292 // original CWND minus the packet that has been lost and the one which
293 // triggered the loss.
294 size_t remaining_packets_in_recovery
=
295 send_window_before_loss
/ kDefaultTCPMSS
- 2;
297 for (size_t i
= 0; i
< remaining_packets_in_recovery
; ++i
) {
299 SendAvailableSendWindow();
300 EXPECT_EQ(expected_send_window
, sender_
->GetCongestionWindow());
303 // We need to ack another window before we increase CWND by 1.
304 size_t number_of_packets_in_window
= expected_send_window
/ kDefaultTCPMSS
;
305 for (size_t i
= 0; i
< number_of_packets_in_window
; ++i
) {
307 EXPECT_EQ(1, SendAvailableSendWindow());
308 EXPECT_EQ(expected_send_window
, sender_
->GetCongestionWindow());
312 expected_send_window
+= kDefaultTCPMSS
;
313 EXPECT_EQ(expected_send_window
, sender_
->GetCongestionWindow());
316 TEST_F(TcpCubicSenderTest
, SlowStartBurstPacketLossPRR
) {
317 sender_
->SetNumEmulatedConnections(1);
318 // Test based on the second example in RFC6937, though we also implement
319 // forward acknowledgements, so the first two incoming acks will trigger
321 // Ack 20 packets in 10 acks to raise the CWND to 30.
322 const int kNumberOfAcks
= 10;
323 for (int i
= 0; i
< kNumberOfAcks
; ++i
) {
324 // Send our full send window.
325 SendAvailableSendWindow();
328 SendAvailableSendWindow();
329 QuicByteCount expected_send_window
= kDefaultWindowTCP
+
330 (kDefaultTCPMSS
* 2 * kNumberOfAcks
);
331 EXPECT_EQ(expected_send_window
, sender_
->GetCongestionWindow());
333 // Lose one more than the congestion window reduction, so that after loss,
334 // bytes_in_flight is lesser than the congestion window.
335 size_t send_window_after_loss
= kRenoBeta
* expected_send_window
;
336 size_t num_packets_to_lose
=
337 (expected_send_window
- send_window_after_loss
) / kDefaultTCPMSS
+ 1;
338 LoseNPackets(num_packets_to_lose
);
339 // Immediately after the loss, ensure at least one packet can be sent.
340 // Losses without subsequent acks can occur with timer based loss detection.
341 EXPECT_TRUE(sender_
->TimeUntilSend(
342 clock_
.Now(), bytes_in_flight_
, HAS_RETRANSMITTABLE_DATA
).IsZero());
345 // We should now have fallen out of slow start with a reduced window.
346 expected_send_window
*= kRenoBeta
;
347 EXPECT_EQ(expected_send_window
, sender_
->GetCongestionWindow());
349 // Only 2 packets should be allowed to be sent, per PRR-SSRB
350 EXPECT_EQ(2, SendAvailableSendWindow());
352 // Ack the next packet, which triggers another loss.
356 // Send 2 packets to simulate PRR-SSRB.
357 EXPECT_EQ(2, SendAvailableSendWindow());
359 // Ack the next packet, which triggers another loss.
363 // Send 2 packets to simulate PRR-SSRB.
364 EXPECT_EQ(2, SendAvailableSendWindow());
366 // Exit recovery and return to sending at the new rate.
367 for (int i
= 0; i
< kNumberOfAcks
; ++i
) {
369 EXPECT_EQ(1, SendAvailableSendWindow());
373 TEST_F(TcpCubicSenderTest
, RTOCongestionWindow
) {
374 EXPECT_EQ(kDefaultWindowTCP
, sender_
->GetCongestionWindow());
375 EXPECT_EQ(kMaxCongestionWindow
, sender_
->slowstart_threshold());
377 // Expect the window to decrease to the minimum once the RTO fires
378 // and slow start threshold to be set to 1/2 of the CWND.
379 sender_
->OnRetransmissionTimeout(true);
380 EXPECT_EQ(2 * kDefaultTCPMSS
, sender_
->GetCongestionWindow());
381 EXPECT_EQ(5u, sender_
->slowstart_threshold());
384 TEST_F(TcpCubicSenderTest
, RTOCongestionWindowNoRetransmission
) {
385 EXPECT_EQ(kDefaultWindowTCP
, sender_
->GetCongestionWindow());
387 // Expect the window to remain unchanged if the RTO fires but no
388 // packets are retransmitted.
389 sender_
->OnRetransmissionTimeout(false);
390 EXPECT_EQ(kDefaultWindowTCP
, sender_
->GetCongestionWindow());
393 TEST_F(TcpCubicSenderTest
, RetransmissionDelay
) {
394 const int64 kRttMs
= 10;
395 const int64 kDeviationMs
= 3;
396 EXPECT_EQ(QuicTime::Delta::Zero(), sender_
->RetransmissionDelay());
398 sender_
->rtt_stats_
.UpdateRtt(QuicTime::Delta::FromMilliseconds(kRttMs
),
399 QuicTime::Delta::Zero(), clock_
.Now());
401 // Initial value is to set the median deviation to half of the initial
402 // rtt, the median in then multiplied by a factor of 4 and finally the
403 // smoothed rtt is added which is the initial rtt.
404 QuicTime::Delta expected_delay
=
405 QuicTime::Delta::FromMilliseconds(kRttMs
+ kRttMs
/ 2 * 4);
406 EXPECT_EQ(expected_delay
, sender_
->RetransmissionDelay());
408 for (int i
= 0; i
< 100; ++i
) {
409 // Run to make sure that we converge.
410 sender_
->rtt_stats_
.UpdateRtt(
411 QuicTime::Delta::FromMilliseconds(kRttMs
+ kDeviationMs
),
412 QuicTime::Delta::Zero(), clock_
.Now());
413 sender_
->rtt_stats_
.UpdateRtt(
414 QuicTime::Delta::FromMilliseconds(kRttMs
- kDeviationMs
),
415 QuicTime::Delta::Zero(), clock_
.Now());
417 expected_delay
= QuicTime::Delta::FromMilliseconds(kRttMs
+ kDeviationMs
* 4);
419 EXPECT_NEAR(kRttMs
, sender_
->rtt_stats_
.smoothed_rtt().ToMilliseconds(), 1);
420 EXPECT_NEAR(expected_delay
.ToMilliseconds(),
421 sender_
->RetransmissionDelay().ToMilliseconds(),
423 EXPECT_EQ(static_cast<int64
>(
424 sender_
->GetCongestionWindow() * kNumMicrosPerSecond
/
425 sender_
->rtt_stats_
.smoothed_rtt().ToMicroseconds()),
426 sender_
->BandwidthEstimate().ToBytesPerSecond());
429 TEST_F(TcpCubicSenderTest
, SlowStartMaxSendWindow
) {
430 const QuicPacketCount kMaxCongestionWindowTCP
= 50;
431 const int kNumberOfAcks
= 100;
433 new TcpCubicSenderPeer(&clock_
, false, kMaxCongestionWindowTCP
));
435 for (int i
= 0; i
< kNumberOfAcks
; ++i
) {
436 // Send our full send window.
437 SendAvailableSendWindow();
440 QuicByteCount expected_send_window
= kMaxCongestionWindowTCP
* kDefaultTCPMSS
;
441 EXPECT_EQ(expected_send_window
, sender_
->GetCongestionWindow());
444 TEST_F(TcpCubicSenderTest
, TcpRenoMaxCongestionWindow
) {
445 const QuicPacketCount kMaxCongestionWindowTCP
= 50;
446 const int kNumberOfAcks
= 1000;
447 sender_
.reset(new TcpCubicSenderPeer(&clock_
, true, kMaxCongestionWindowTCP
));
449 SendAvailableSendWindow();
451 // Make sure we fall out of slow start.
454 for (int i
= 0; i
< kNumberOfAcks
; ++i
) {
455 // Send our full send window.
456 SendAvailableSendWindow();
460 QuicByteCount expected_send_window
= kMaxCongestionWindowTCP
* kDefaultTCPMSS
;
461 EXPECT_EQ(expected_send_window
, sender_
->GetCongestionWindow());
464 TEST_F(TcpCubicSenderTest
, TcpCubicMaxCongestionWindow
) {
465 const QuicPacketCount kMaxCongestionWindowTCP
= 50;
466 // Set to 10000 to compensate for small cubic alpha.
467 const int kNumberOfAcks
= 10000;
470 new TcpCubicSenderPeer(&clock_
, false, kMaxCongestionWindowTCP
));
472 SendAvailableSendWindow();
474 // Make sure we fall out of slow start.
477 for (int i
= 0; i
< kNumberOfAcks
; ++i
) {
478 // Send our full send window.
479 SendAvailableSendWindow();
483 QuicByteCount expected_send_window
= kMaxCongestionWindowTCP
* kDefaultTCPMSS
;
484 EXPECT_EQ(expected_send_window
, sender_
->GetCongestionWindow());
487 TEST_F(TcpCubicSenderTest
, MultipleLossesInOneWindow
) {
488 SendAvailableSendWindow();
489 const QuicByteCount initial_window
= sender_
->GetCongestionWindow();
490 LosePacket(acked_sequence_number_
+ 1);
491 const QuicByteCount post_loss_window
= sender_
->GetCongestionWindow();
492 EXPECT_GT(initial_window
, post_loss_window
);
493 LosePacket(acked_sequence_number_
+ 3);
494 EXPECT_EQ(post_loss_window
, sender_
->GetCongestionWindow());
495 LosePacket(sequence_number_
- 1);
496 EXPECT_EQ(post_loss_window
, sender_
->GetCongestionWindow());
498 // Lose a later packet and ensure the window decreases.
499 LosePacket(sequence_number_
);
500 EXPECT_GT(post_loss_window
, sender_
->GetCongestionWindow());
503 TEST_F(TcpCubicSenderTest
, DontTrackAckPackets
) {
504 // Send a packet with no retransmittable data, and ensure it's not tracked.
505 EXPECT_FALSE(sender_
->OnPacketSent(clock_
.Now(), bytes_in_flight_
,
506 sequence_number_
++, kDefaultTCPMSS
,
507 NO_RETRANSMITTABLE_DATA
));
509 // Send a data packet with retransmittable data, and ensure it is tracked.
510 EXPECT_TRUE(sender_
->OnPacketSent(clock_
.Now(), bytes_in_flight_
,
511 sequence_number_
++, kDefaultTCPMSS
,
512 HAS_RETRANSMITTABLE_DATA
));
515 TEST_F(TcpCubicSenderTest
, ConfigureInitialWindow
) {
518 QuicTagVector options
;
519 options
.push_back(kIW03
);
520 QuicConfigPeer::SetReceivedConnectionOptions(&config
, options
);
521 sender_
->SetFromConfig(config
, Perspective::IS_SERVER
);
522 EXPECT_EQ(3u, sender_
->congestion_window());
525 options
.push_back(kIW10
);
526 QuicConfigPeer::SetReceivedConnectionOptions(&config
, options
);
527 sender_
->SetFromConfig(config
, Perspective::IS_SERVER
);
528 EXPECT_EQ(10u, sender_
->congestion_window());
531 options
.push_back(kIW20
);
532 QuicConfigPeer::SetReceivedConnectionOptions(&config
, options
);
533 sender_
->SetFromConfig(config
, Perspective::IS_SERVER
);
534 EXPECT_EQ(20u, sender_
->congestion_window());
537 options
.push_back(kIW50
);
538 QuicConfigPeer::SetReceivedConnectionOptions(&config
, options
);
539 sender_
->SetFromConfig(config
, Perspective::IS_SERVER
);
540 EXPECT_EQ(50u, sender_
->congestion_window());
543 TEST_F(TcpCubicSenderTest
, ConfigureMinimumWindow
) {
546 // Verify that kCOPT: kMIN1 forces the min CWND to 1 packet.
547 QuicTagVector options
;
548 options
.push_back(kMIN1
);
549 QuicConfigPeer::SetReceivedConnectionOptions(&config
, options
);
550 sender_
->SetFromConfig(config
, Perspective::IS_SERVER
);
551 sender_
->OnRetransmissionTimeout(true);
552 EXPECT_EQ(1u, sender_
->congestion_window());
555 TEST_F(TcpCubicSenderTest
, 2ConnectionCongestionAvoidanceAtEndOfRecovery
) {
556 sender_
->SetNumEmulatedConnections(2);
557 // Ack 10 packets in 5 acks to raise the CWND to 20.
558 const int kNumberOfAcks
= 5;
559 for (int i
= 0; i
< kNumberOfAcks
; ++i
) {
560 // Send our full send window.
561 SendAvailableSendWindow();
564 SendAvailableSendWindow();
565 QuicByteCount expected_send_window
= kDefaultWindowTCP
+
566 (kDefaultTCPMSS
* 2 * kNumberOfAcks
);
567 EXPECT_EQ(expected_send_window
, sender_
->GetCongestionWindow());
571 // We should now have fallen out of slow start with a reduced window.
572 expected_send_window
= expected_send_window
* sender_
->GetRenoBeta();
573 EXPECT_EQ(expected_send_window
, sender_
->GetCongestionWindow());
575 // No congestion window growth should occur in recovery phase, i.e., until the
576 // currently outstanding 20 packets are acked.
577 for (int i
= 0; i
< 10; ++i
) {
578 // Send our full send window.
579 SendAvailableSendWindow();
580 EXPECT_TRUE(sender_
->InRecovery());
582 EXPECT_EQ(expected_send_window
, sender_
->GetCongestionWindow());
584 EXPECT_FALSE(sender_
->InRecovery());
586 // Out of recovery now. Congestion window should not grow for half an RTT.
587 size_t packets_in_send_window
= expected_send_window
/ kDefaultTCPMSS
;
588 SendAvailableSendWindow();
589 AckNPackets(packets_in_send_window
/ 2 - 2);
590 EXPECT_EQ(expected_send_window
, sender_
->GetCongestionWindow());
592 // Next ack should increase congestion window by 1MSS.
593 SendAvailableSendWindow();
595 expected_send_window
+= kDefaultTCPMSS
;
596 packets_in_send_window
+= 1;
597 EXPECT_EQ(expected_send_window
, sender_
->GetCongestionWindow());
599 // Congestion window should remain steady again for half an RTT.
600 SendAvailableSendWindow();
601 AckNPackets(packets_in_send_window
/ 2 - 1);
602 EXPECT_EQ(expected_send_window
, sender_
->GetCongestionWindow());
604 // Next ack should cause congestion window to grow by 1MSS.
605 SendAvailableSendWindow();
607 expected_send_window
+= kDefaultTCPMSS
;
608 EXPECT_EQ(expected_send_window
, sender_
->GetCongestionWindow());
611 TEST_F(TcpCubicSenderTest
, 1ConnectionCongestionAvoidanceAtEndOfRecovery
) {
612 sender_
->SetNumEmulatedConnections(1);
613 // Ack 10 packets in 5 acks to raise the CWND to 20.
614 const int kNumberOfAcks
= 5;
615 for (int i
= 0; i
< kNumberOfAcks
; ++i
) {
616 // Send our full send window.
617 SendAvailableSendWindow();
620 SendAvailableSendWindow();
621 QuicByteCount expected_send_window
= kDefaultWindowTCP
+
622 (kDefaultTCPMSS
* 2 * kNumberOfAcks
);
623 EXPECT_EQ(expected_send_window
, sender_
->GetCongestionWindow());
627 // We should now have fallen out of slow start with a reduced window.
628 expected_send_window
*= kRenoBeta
;
629 EXPECT_EQ(expected_send_window
, sender_
->GetCongestionWindow());
631 // No congestion window growth should occur in recovery phase, i.e., until the
632 // currently outstanding 20 packets are acked.
633 for (int i
= 0; i
< 10; ++i
) {
634 // Send our full send window.
635 SendAvailableSendWindow();
636 EXPECT_TRUE(sender_
->InRecovery());
638 EXPECT_EQ(expected_send_window
, sender_
->GetCongestionWindow());
640 EXPECT_FALSE(sender_
->InRecovery());
642 // Out of recovery now. Congestion window should not grow during RTT.
643 for (uint64 i
= 0; i
< expected_send_window
/ kDefaultTCPMSS
- 2; i
+= 2) {
644 // Send our full send window.
645 SendAvailableSendWindow();
647 EXPECT_EQ(expected_send_window
, sender_
->GetCongestionWindow());
650 // Next ack should cause congestion window to grow by 1MSS.
651 SendAvailableSendWindow();
653 expected_send_window
+= kDefaultTCPMSS
;
654 EXPECT_EQ(expected_send_window
, sender_
->GetCongestionWindow());
657 TEST_F(TcpCubicSenderTest
, BandwidthResumption
) {
658 // Test that when provided with CachedNetworkParameters and opted in to the
659 // bandwidth resumption experiment, that the TcpCubicSender sets initial CWND
662 // Set some common values.
663 CachedNetworkParameters cached_network_params
;
664 const QuicPacketCount kNumberOfPackets
= 123;
665 const int kBandwidthEstimateBytesPerSecond
=
666 kNumberOfPackets
* kMaxPacketSize
;
667 cached_network_params
.set_bandwidth_estimate_bytes_per_second(
668 kBandwidthEstimateBytesPerSecond
);
669 cached_network_params
.set_min_rtt_ms(1000);
671 // Make sure that a bandwidth estimate results in a changed CWND.
672 cached_network_params
.set_timestamp(clock_
.WallNow().ToUNIXSeconds() -
673 (kNumSecondsPerHour
- 1));
674 sender_
->ResumeConnectionState(cached_network_params
, false);
675 EXPECT_EQ(kNumberOfPackets
, sender_
->congestion_window());
677 // Resumed CWND is limited to be in a sensible range.
678 cached_network_params
.set_bandwidth_estimate_bytes_per_second(
679 (kMaxCongestionWindow
+ 1) * kMaxPacketSize
);
680 sender_
->ResumeConnectionState(cached_network_params
, false);
681 EXPECT_EQ(kMaxCongestionWindow
, sender_
->congestion_window());
683 cached_network_params
.set_bandwidth_estimate_bytes_per_second(
684 (kMinCongestionWindowForBandwidthResumption
- 1) * kMaxPacketSize
);
685 sender_
->ResumeConnectionState(cached_network_params
, false);
686 EXPECT_EQ(kMinCongestionWindowForBandwidthResumption
,
687 sender_
->congestion_window());
689 // Resume to the max value.
690 cached_network_params
.set_max_bandwidth_estimate_bytes_per_second(
691 (kMinCongestionWindowForBandwidthResumption
+ 10) * kDefaultTCPMSS
);
692 sender_
->ResumeConnectionState(cached_network_params
, true);
693 EXPECT_EQ((kMinCongestionWindowForBandwidthResumption
+ 10) * kDefaultTCPMSS
,
694 sender_
->GetCongestionWindow());
697 TEST_F(TcpCubicSenderTest
, PaceBelowCWND
) {
700 // Verify that kCOPT: kMIN4 forces the min CWND to 1 packet, but allows up
702 QuicTagVector options
;
703 options
.push_back(kMIN4
);
704 QuicConfigPeer::SetReceivedConnectionOptions(&config
, options
);
705 sender_
->SetFromConfig(config
, Perspective::IS_SERVER
);
706 sender_
->OnRetransmissionTimeout(true);
707 EXPECT_EQ(1u, sender_
->congestion_window());
708 EXPECT_TRUE(sender_
->TimeUntilSend(QuicTime::Zero(), kDefaultTCPMSS
,
709 HAS_RETRANSMITTABLE_DATA
).IsZero());
710 EXPECT_TRUE(sender_
->TimeUntilSend(QuicTime::Zero(), 2 * kDefaultTCPMSS
,
711 HAS_RETRANSMITTABLE_DATA
).IsZero());
712 EXPECT_TRUE(sender_
->TimeUntilSend(QuicTime::Zero(), 3 * kDefaultTCPMSS
,
713 HAS_RETRANSMITTABLE_DATA
).IsZero());
714 EXPECT_FALSE(sender_
->TimeUntilSend(QuicTime::Zero(), 4 * kDefaultTCPMSS
,
715 HAS_RETRANSMITTABLE_DATA
).IsZero());