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 "net/quic/congestion_control/tcp_cubic_sender.h"
9 #include "base/logging.h"
10 #include "base/memory/scoped_ptr.h"
11 #include "net/quic/congestion_control/rtt_stats.h"
12 #include "net/quic/crypto/crypto_protocol.h"
13 #include "net/quic/proto/cached_network_parameters.pb.h"
14 #include "net/quic/quic_flags.h"
15 #include "net/quic/quic_protocol.h"
16 #include "net/quic/quic_utils.h"
17 #include "net/quic/test_tools/mock_clock.h"
18 #include "net/quic/test_tools/quic_config_peer.h"
19 #include "net/quic/test_tools/quic_test_utils.h"
20 #include "testing/gtest/include/gtest/gtest.h"
27 // TODO(ianswett): A number of theses tests were written with the assumption of
28 // an initial CWND of 10. They have carefully calculated values which should be
29 // updated to be based on kInitialCongestionWindowInsecure.
30 const uint32 kInitialCongestionWindowPackets
= 10;
31 const uint32 kDefaultWindowTCP
=
32 kInitialCongestionWindowPackets
* kDefaultTCPMSS
;
33 const float kRenoBeta
= 0.7f
; // Reno backoff factor.
35 class TcpCubicSenderPeer
: public TcpCubicSender
{
37 TcpCubicSenderPeer(const QuicClock
* clock
,
39 QuicPacketCount max_tcp_congestion_window
)
40 : TcpCubicSender(clock
,
43 kInitialCongestionWindowPackets
,
44 max_tcp_congestion_window
,
47 QuicPacketCount
congestion_window() {
48 return congestion_window_
;
51 QuicPacketCount
slowstart_threshold() {
52 return slowstart_threshold_
;
55 const HybridSlowStart
& hybrid_slow_start() const {
56 return hybrid_slow_start_
;
59 float GetRenoBeta() const {
64 QuicConnectionStats stats_
;
67 class TcpCubicSenderTest
: public ::testing::Test
{
70 : one_ms_(QuicTime::Delta::FromMilliseconds(1)),
71 sender_(new TcpCubicSenderPeer(&clock_
, true, kMaxCongestionWindow
)),
73 acked_packet_number_(0),
75 standard_packet_
.bytes_sent
= kDefaultTCPMSS
;
78 int SendAvailableSendWindow() {
79 // Send as long as TimeUntilSend returns Zero.
81 bool can_send
= sender_
->TimeUntilSend(
82 clock_
.Now(), bytes_in_flight_
, HAS_RETRANSMITTABLE_DATA
).IsZero();
84 sender_
->OnPacketSent(clock_
.Now(), bytes_in_flight_
, packet_number_
++,
85 kDefaultTCPMSS
, HAS_RETRANSMITTABLE_DATA
);
87 bytes_in_flight_
+= kDefaultTCPMSS
;
88 can_send
= sender_
->TimeUntilSend(
89 clock_
.Now(), bytes_in_flight_
, HAS_RETRANSMITTABLE_DATA
).IsZero();
94 // Normal is that TCP acks every other segment.
95 void AckNPackets(int n
) {
96 sender_
->rtt_stats_
.UpdateRtt(QuicTime::Delta::FromMilliseconds(60),
97 QuicTime::Delta::Zero(),
99 SendAlgorithmInterface::CongestionVector acked_packets
;
100 SendAlgorithmInterface::CongestionVector lost_packets
;
101 for (int i
= 0; i
< n
; ++i
) {
102 ++acked_packet_number_
;
103 acked_packets
.push_back(
104 std::make_pair(acked_packet_number_
, standard_packet_
));
106 sender_
->OnCongestionEvent(
107 true, bytes_in_flight_
, acked_packets
, lost_packets
);
108 bytes_in_flight_
-= n
* kDefaultTCPMSS
;
109 clock_
.AdvanceTime(one_ms_
);
112 void LoseNPackets(int n
) {
113 SendAlgorithmInterface::CongestionVector acked_packets
;
114 SendAlgorithmInterface::CongestionVector lost_packets
;
115 for (int i
= 0; i
< n
; ++i
) {
116 ++acked_packet_number_
;
117 lost_packets
.push_back(
118 std::make_pair(acked_packet_number_
, standard_packet_
));
120 sender_
->OnCongestionEvent(
121 false, bytes_in_flight_
, acked_packets
, lost_packets
);
122 bytes_in_flight_
-= n
* kDefaultTCPMSS
;
125 // Does not increment acked_packet_number_.
126 void LosePacket(QuicPacketNumber packet_number
) {
127 SendAlgorithmInterface::CongestionVector acked_packets
;
128 SendAlgorithmInterface::CongestionVector lost_packets
;
129 lost_packets
.push_back(std::make_pair(packet_number
, standard_packet_
));
130 sender_
->OnCongestionEvent(
131 false, bytes_in_flight_
, acked_packets
, lost_packets
);
132 bytes_in_flight_
-= kDefaultTCPMSS
;
135 const QuicTime::Delta one_ms_
;
137 scoped_ptr
<TcpCubicSenderPeer
> sender_
;
138 QuicPacketNumber packet_number_
;
139 QuicPacketNumber acked_packet_number_
;
140 QuicByteCount bytes_in_flight_
;
141 TransmissionInfo standard_packet_
;
144 TEST_F(TcpCubicSenderTest
, SimpleSender
) {
145 // At startup make sure we are at the default.
146 EXPECT_EQ(kDefaultWindowTCP
, sender_
->GetCongestionWindow());
147 // At startup make sure we can send.
148 EXPECT_TRUE(sender_
->TimeUntilSend(clock_
.Now(),
150 HAS_RETRANSMITTABLE_DATA
).IsZero());
151 // Make sure we can send.
152 EXPECT_TRUE(sender_
->TimeUntilSend(clock_
.Now(),
154 HAS_RETRANSMITTABLE_DATA
).IsZero());
155 // And that window is un-affected.
156 EXPECT_EQ(kDefaultWindowTCP
, sender_
->GetCongestionWindow());
158 // Fill the send window with data, then verify that we can't send.
159 SendAvailableSendWindow();
160 EXPECT_FALSE(sender_
->TimeUntilSend(clock_
.Now(),
161 sender_
->GetCongestionWindow(),
162 HAS_RETRANSMITTABLE_DATA
).IsZero());
165 TEST_F(TcpCubicSenderTest
, ApplicationLimitedSlowStart
) {
166 // Send exactly 10 packets and ensure the CWND ends at 14 packets.
167 const int kNumberOfAcks
= 5;
168 // At startup make sure we can send.
169 EXPECT_TRUE(sender_
->TimeUntilSend(clock_
.Now(),
171 HAS_RETRANSMITTABLE_DATA
).IsZero());
172 // Make sure we can send.
173 EXPECT_TRUE(sender_
->TimeUntilSend(clock_
.Now(),
175 HAS_RETRANSMITTABLE_DATA
).IsZero());
177 SendAvailableSendWindow();
178 for (int i
= 0; i
< kNumberOfAcks
; ++i
) {
181 QuicByteCount bytes_to_send
= sender_
->GetCongestionWindow();
182 // It's expected 2 acks will arrive when the bytes_in_flight are greater than
184 EXPECT_EQ(kDefaultWindowTCP
+ kDefaultTCPMSS
* 2 * 2,
188 TEST_F(TcpCubicSenderTest
, ExponentialSlowStart
) {
189 const int kNumberOfAcks
= 20;
190 // At startup make sure we can send.
191 EXPECT_TRUE(sender_
->TimeUntilSend(clock_
.Now(),
193 HAS_RETRANSMITTABLE_DATA
).IsZero());
194 EXPECT_EQ(QuicBandwidth::Zero(), sender_
->BandwidthEstimate());
195 // Make sure we can send.
196 EXPECT_TRUE(sender_
->TimeUntilSend(clock_
.Now(),
198 HAS_RETRANSMITTABLE_DATA
).IsZero());
200 for (int i
= 0; i
< kNumberOfAcks
; ++i
) {
201 // Send our full send window.
202 SendAvailableSendWindow();
205 const QuicByteCount cwnd
= sender_
->GetCongestionWindow();
206 EXPECT_EQ(kDefaultWindowTCP
+ kDefaultTCPMSS
* 2 * kNumberOfAcks
, cwnd
);
207 EXPECT_EQ(QuicBandwidth::FromBytesAndTimeDelta(
208 cwnd
, sender_
->rtt_stats_
.smoothed_rtt()),
209 sender_
->BandwidthEstimate());
212 TEST_F(TcpCubicSenderTest
, SlowStartPacketLoss
) {
213 sender_
->SetNumEmulatedConnections(1);
214 const int kNumberOfAcks
= 10;
215 for (int i
= 0; i
< kNumberOfAcks
; ++i
) {
216 // Send our full send window.
217 SendAvailableSendWindow();
220 SendAvailableSendWindow();
221 QuicByteCount expected_send_window
= kDefaultWindowTCP
+
222 (kDefaultTCPMSS
* 2 * kNumberOfAcks
);
223 EXPECT_EQ(expected_send_window
, sender_
->GetCongestionWindow());
225 // Lose a packet to exit slow start.
227 size_t packets_in_recovery_window
= expected_send_window
/ kDefaultTCPMSS
;
229 // We should now have fallen out of slow start with a reduced window.
230 expected_send_window
*= kRenoBeta
;
231 EXPECT_EQ(expected_send_window
, sender_
->GetCongestionWindow());
233 // Recovery phase. We need to ack every packet in the recovery window before
235 size_t number_of_packets_in_window
= expected_send_window
/ kDefaultTCPMSS
;
236 DVLOG(1) << "number_packets: " << number_of_packets_in_window
;
237 AckNPackets(packets_in_recovery_window
);
238 SendAvailableSendWindow();
239 EXPECT_EQ(expected_send_window
, sender_
->GetCongestionWindow());
241 // We need to ack an entire window before we increase CWND by 1.
242 AckNPackets(number_of_packets_in_window
- 2);
243 SendAvailableSendWindow();
244 EXPECT_EQ(expected_send_window
, sender_
->GetCongestionWindow());
246 // Next ack should increase cwnd by 1.
248 expected_send_window
+= kDefaultTCPMSS
;
249 EXPECT_EQ(expected_send_window
, sender_
->GetCongestionWindow());
251 // Now RTO and ensure slow start gets reset.
252 EXPECT_TRUE(sender_
->hybrid_slow_start().started());
253 sender_
->OnRetransmissionTimeout(true);
254 EXPECT_FALSE(sender_
->hybrid_slow_start().started());
257 TEST_F(TcpCubicSenderTest
, NoPRRWhenLessThanOnePacketInFlight
) {
258 SendAvailableSendWindow();
259 LoseNPackets(kInitialCongestionWindowPackets
- 1);
261 // PRR will allow 2 packets for every ack during recovery.
262 EXPECT_EQ(2, SendAvailableSendWindow());
263 // Simulate abandoning all packets by supplying a bytes_in_flight of 0.
264 // PRR should now allow a packet to be sent, even though prr's state
265 // variables believe it has sent enough packets.
266 EXPECT_EQ(QuicTime::Delta::Zero(),
267 sender_
->TimeUntilSend(clock_
.Now(), 0, HAS_RETRANSMITTABLE_DATA
));
270 TEST_F(TcpCubicSenderTest
, SlowStartPacketLossPRR
) {
271 sender_
->SetNumEmulatedConnections(1);
272 // Test based on the first example in RFC6937.
273 // Ack 10 packets in 5 acks to raise the CWND to 20, as in the example.
274 const int kNumberOfAcks
= 5;
275 for (int i
= 0; i
< kNumberOfAcks
; ++i
) {
276 // Send our full send window.
277 SendAvailableSendWindow();
280 SendAvailableSendWindow();
281 QuicByteCount expected_send_window
= kDefaultWindowTCP
+
282 (kDefaultTCPMSS
* 2 * kNumberOfAcks
);
283 EXPECT_EQ(expected_send_window
, sender_
->GetCongestionWindow());
287 // We should now have fallen out of slow start with a reduced window.
288 size_t send_window_before_loss
= expected_send_window
;
289 expected_send_window
*= kRenoBeta
;
290 EXPECT_EQ(expected_send_window
, sender_
->GetCongestionWindow());
292 // Testing TCP proportional rate reduction.
293 // We should send packets paced over the received acks for the remaining
294 // outstanding packets. The number of packets before we exit recovery is the
295 // original CWND minus the packet that has been lost and the one which
296 // triggered the loss.
297 size_t remaining_packets_in_recovery
=
298 send_window_before_loss
/ kDefaultTCPMSS
- 2;
300 for (size_t i
= 0; i
< remaining_packets_in_recovery
; ++i
) {
302 SendAvailableSendWindow();
303 EXPECT_EQ(expected_send_window
, sender_
->GetCongestionWindow());
306 // We need to ack another window before we increase CWND by 1.
307 size_t number_of_packets_in_window
= expected_send_window
/ kDefaultTCPMSS
;
308 for (size_t i
= 0; i
< number_of_packets_in_window
; ++i
) {
310 EXPECT_EQ(1, SendAvailableSendWindow());
311 EXPECT_EQ(expected_send_window
, sender_
->GetCongestionWindow());
315 expected_send_window
+= kDefaultTCPMSS
;
316 EXPECT_EQ(expected_send_window
, sender_
->GetCongestionWindow());
319 TEST_F(TcpCubicSenderTest
, SlowStartBurstPacketLossPRR
) {
320 sender_
->SetNumEmulatedConnections(1);
321 // Test based on the second example in RFC6937, though we also implement
322 // forward acknowledgements, so the first two incoming acks will trigger
324 // Ack 20 packets in 10 acks to raise the CWND to 30.
325 const int kNumberOfAcks
= 10;
326 for (int i
= 0; i
< kNumberOfAcks
; ++i
) {
327 // Send our full send window.
328 SendAvailableSendWindow();
331 SendAvailableSendWindow();
332 QuicByteCount expected_send_window
= kDefaultWindowTCP
+
333 (kDefaultTCPMSS
* 2 * kNumberOfAcks
);
334 EXPECT_EQ(expected_send_window
, sender_
->GetCongestionWindow());
336 // Lose one more than the congestion window reduction, so that after loss,
337 // bytes_in_flight is lesser than the congestion window.
338 size_t send_window_after_loss
= kRenoBeta
* expected_send_window
;
339 size_t num_packets_to_lose
=
340 (expected_send_window
- send_window_after_loss
) / kDefaultTCPMSS
+ 1;
341 LoseNPackets(num_packets_to_lose
);
342 // Immediately after the loss, ensure at least one packet can be sent.
343 // Losses without subsequent acks can occur with timer based loss detection.
344 EXPECT_TRUE(sender_
->TimeUntilSend(
345 clock_
.Now(), bytes_in_flight_
, HAS_RETRANSMITTABLE_DATA
).IsZero());
348 // We should now have fallen out of slow start with a reduced window.
349 expected_send_window
*= kRenoBeta
;
350 EXPECT_EQ(expected_send_window
, sender_
->GetCongestionWindow());
352 // Only 2 packets should be allowed to be sent, per PRR-SSRB
353 EXPECT_EQ(2, SendAvailableSendWindow());
355 // Ack the next packet, which triggers another loss.
359 // Send 2 packets to simulate PRR-SSRB.
360 EXPECT_EQ(2, SendAvailableSendWindow());
362 // Ack the next packet, which triggers another loss.
366 // Send 2 packets to simulate PRR-SSRB.
367 EXPECT_EQ(2, SendAvailableSendWindow());
369 // Exit recovery and return to sending at the new rate.
370 for (int i
= 0; i
< kNumberOfAcks
; ++i
) {
372 EXPECT_EQ(1, SendAvailableSendWindow());
376 TEST_F(TcpCubicSenderTest
, RTOCongestionWindow
) {
377 EXPECT_EQ(kDefaultWindowTCP
, sender_
->GetCongestionWindow());
378 EXPECT_EQ(kMaxCongestionWindow
, sender_
->slowstart_threshold());
380 // Expect the window to decrease to the minimum once the RTO fires
381 // and slow start threshold to be set to 1/2 of the CWND.
382 sender_
->OnRetransmissionTimeout(true);
383 EXPECT_EQ(2 * kDefaultTCPMSS
, sender_
->GetCongestionWindow());
384 EXPECT_EQ(5u, sender_
->slowstart_threshold());
387 TEST_F(TcpCubicSenderTest
, RTOCongestionWindowNoRetransmission
) {
388 EXPECT_EQ(kDefaultWindowTCP
, sender_
->GetCongestionWindow());
390 // Expect the window to remain unchanged if the RTO fires but no
391 // packets are retransmitted.
392 sender_
->OnRetransmissionTimeout(false);
393 EXPECT_EQ(kDefaultWindowTCP
, sender_
->GetCongestionWindow());
396 TEST_F(TcpCubicSenderTest
, RetransmissionDelay
) {
397 const int64 kRttMs
= 10;
398 const int64 kDeviationMs
= 3;
399 EXPECT_EQ(QuicTime::Delta::Zero(), sender_
->RetransmissionDelay());
401 sender_
->rtt_stats_
.UpdateRtt(QuicTime::Delta::FromMilliseconds(kRttMs
),
402 QuicTime::Delta::Zero(), clock_
.Now());
404 // Initial value is to set the median deviation to half of the initial
405 // rtt, the median in then multiplied by a factor of 4 and finally the
406 // smoothed rtt is added which is the initial rtt.
407 QuicTime::Delta expected_delay
=
408 QuicTime::Delta::FromMilliseconds(kRttMs
+ kRttMs
/ 2 * 4);
409 EXPECT_EQ(expected_delay
, sender_
->RetransmissionDelay());
411 for (int i
= 0; i
< 100; ++i
) {
412 // Run to make sure that we converge.
413 sender_
->rtt_stats_
.UpdateRtt(
414 QuicTime::Delta::FromMilliseconds(kRttMs
+ kDeviationMs
),
415 QuicTime::Delta::Zero(), clock_
.Now());
416 sender_
->rtt_stats_
.UpdateRtt(
417 QuicTime::Delta::FromMilliseconds(kRttMs
- kDeviationMs
),
418 QuicTime::Delta::Zero(), clock_
.Now());
420 expected_delay
= QuicTime::Delta::FromMilliseconds(kRttMs
+ kDeviationMs
* 4);
422 EXPECT_NEAR(kRttMs
, sender_
->rtt_stats_
.smoothed_rtt().ToMilliseconds(), 1);
423 EXPECT_NEAR(expected_delay
.ToMilliseconds(),
424 sender_
->RetransmissionDelay().ToMilliseconds(),
426 EXPECT_EQ(static_cast<int64
>(
427 sender_
->GetCongestionWindow() * kNumMicrosPerSecond
/
428 sender_
->rtt_stats_
.smoothed_rtt().ToMicroseconds()),
429 sender_
->BandwidthEstimate().ToBytesPerSecond());
432 TEST_F(TcpCubicSenderTest
, SlowStartMaxSendWindow
) {
433 const QuicPacketCount kMaxCongestionWindowTCP
= 50;
434 const int kNumberOfAcks
= 100;
436 new TcpCubicSenderPeer(&clock_
, false, kMaxCongestionWindowTCP
));
438 for (int i
= 0; i
< kNumberOfAcks
; ++i
) {
439 // Send our full send window.
440 SendAvailableSendWindow();
443 QuicByteCount expected_send_window
= kMaxCongestionWindowTCP
* kDefaultTCPMSS
;
444 EXPECT_EQ(expected_send_window
, sender_
->GetCongestionWindow());
447 TEST_F(TcpCubicSenderTest
, TcpRenoMaxCongestionWindow
) {
448 const QuicPacketCount kMaxCongestionWindowTCP
= 50;
449 const int kNumberOfAcks
= 1000;
450 sender_
.reset(new TcpCubicSenderPeer(&clock_
, true, kMaxCongestionWindowTCP
));
452 SendAvailableSendWindow();
454 // Make sure we fall out of slow start.
457 for (int i
= 0; i
< kNumberOfAcks
; ++i
) {
458 // Send our full send window.
459 SendAvailableSendWindow();
463 QuicByteCount expected_send_window
= kMaxCongestionWindowTCP
* kDefaultTCPMSS
;
464 EXPECT_EQ(expected_send_window
, sender_
->GetCongestionWindow());
467 TEST_F(TcpCubicSenderTest
, TcpCubicMaxCongestionWindow
) {
468 const QuicPacketCount kMaxCongestionWindowTCP
= 50;
469 // Set to 10000 to compensate for small cubic alpha.
470 const int kNumberOfAcks
= 10000;
473 new TcpCubicSenderPeer(&clock_
, false, kMaxCongestionWindowTCP
));
475 SendAvailableSendWindow();
477 // Make sure we fall out of slow start.
480 for (int i
= 0; i
< kNumberOfAcks
; ++i
) {
481 // Send our full send window.
482 SendAvailableSendWindow();
486 QuicByteCount expected_send_window
= kMaxCongestionWindowTCP
* kDefaultTCPMSS
;
487 EXPECT_EQ(expected_send_window
, sender_
->GetCongestionWindow());
490 TEST_F(TcpCubicSenderTest
, TcpCubicResetEpochOnQuiescence
) {
491 ValueRestore
<bool> old_flag(&FLAGS_reset_cubic_epoch_when_app_limited
, true);
492 const int kMaxCongestionWindow
= 50;
493 const QuicByteCount kMaxCongestionWindowBytes
=
494 kMaxCongestionWindow
* kDefaultTCPMSS
;
495 sender_
.reset(new TcpCubicSenderPeer(&clock_
, false, kMaxCongestionWindow
));
497 int num_sent
= SendAvailableSendWindow();
499 // Make sure we fall out of slow start.
500 QuicByteCount saved_cwnd
= sender_
->GetCongestionWindow();
502 EXPECT_GT(saved_cwnd
, sender_
->GetCongestionWindow());
504 // Ack the rest of the outstanding packets to get out of recovery.
505 for (int i
= 1; i
< num_sent
; ++i
) {
508 EXPECT_EQ(0u, bytes_in_flight_
);
510 // Send a new window of data and ack all; cubic growth should occur.
511 saved_cwnd
= sender_
->GetCongestionWindow();
512 num_sent
= SendAvailableSendWindow();
513 for (int i
= 0; i
< num_sent
; ++i
) {
516 EXPECT_LT(saved_cwnd
, sender_
->GetCongestionWindow());
517 EXPECT_GT(kMaxCongestionWindowBytes
, sender_
->GetCongestionWindow());
518 EXPECT_EQ(0u, bytes_in_flight_
);
520 // Quiescent time of 100 seconds
521 clock_
.AdvanceTime(QuicTime::Delta::FromMilliseconds(100000));
523 // Send new window of data and ack one packet. Cubic epoch should have
524 // been reset; ensure cwnd increase is not dramatic.
525 saved_cwnd
= sender_
->GetCongestionWindow();
526 SendAvailableSendWindow();
528 EXPECT_NEAR(saved_cwnd
, sender_
->GetCongestionWindow(), kDefaultTCPMSS
);
529 EXPECT_GT(kMaxCongestionWindowBytes
, sender_
->GetCongestionWindow());
532 TEST_F(TcpCubicSenderTest
, MultipleLossesInOneWindow
) {
533 SendAvailableSendWindow();
534 const QuicByteCount initial_window
= sender_
->GetCongestionWindow();
535 LosePacket(acked_packet_number_
+ 1);
536 const QuicByteCount post_loss_window
= sender_
->GetCongestionWindow();
537 EXPECT_GT(initial_window
, post_loss_window
);
538 LosePacket(acked_packet_number_
+ 3);
539 EXPECT_EQ(post_loss_window
, sender_
->GetCongestionWindow());
540 LosePacket(packet_number_
- 1);
541 EXPECT_EQ(post_loss_window
, sender_
->GetCongestionWindow());
543 // Lose a later packet and ensure the window decreases.
544 LosePacket(packet_number_
);
545 EXPECT_GT(post_loss_window
, sender_
->GetCongestionWindow());
548 TEST_F(TcpCubicSenderTest
, DontTrackAckPackets
) {
549 // Send a packet with no retransmittable data, and ensure it's not tracked.
550 EXPECT_FALSE(sender_
->OnPacketSent(clock_
.Now(), bytes_in_flight_
,
551 packet_number_
++, kDefaultTCPMSS
,
552 NO_RETRANSMITTABLE_DATA
));
554 // Send a data packet with retransmittable data, and ensure it is tracked.
555 EXPECT_TRUE(sender_
->OnPacketSent(clock_
.Now(), bytes_in_flight_
,
556 packet_number_
++, kDefaultTCPMSS
,
557 HAS_RETRANSMITTABLE_DATA
));
560 TEST_F(TcpCubicSenderTest
, ConfigureInitialWindow
) {
563 QuicTagVector options
;
564 options
.push_back(kIW03
);
565 QuicConfigPeer::SetReceivedConnectionOptions(&config
, options
);
566 sender_
->SetFromConfig(config
, Perspective::IS_SERVER
);
567 EXPECT_EQ(3u, sender_
->congestion_window());
570 options
.push_back(kIW10
);
571 QuicConfigPeer::SetReceivedConnectionOptions(&config
, options
);
572 sender_
->SetFromConfig(config
, Perspective::IS_SERVER
);
573 EXPECT_EQ(10u, sender_
->congestion_window());
576 options
.push_back(kIW20
);
577 QuicConfigPeer::SetReceivedConnectionOptions(&config
, options
);
578 sender_
->SetFromConfig(config
, Perspective::IS_SERVER
);
579 EXPECT_EQ(20u, sender_
->congestion_window());
582 options
.push_back(kIW50
);
583 QuicConfigPeer::SetReceivedConnectionOptions(&config
, options
);
584 sender_
->SetFromConfig(config
, Perspective::IS_SERVER
);
585 EXPECT_EQ(50u, sender_
->congestion_window());
588 TEST_F(TcpCubicSenderTest
, ConfigureMinimumWindow
) {
591 // Verify that kCOPT: kMIN1 forces the min CWND to 1 packet.
592 QuicTagVector options
;
593 options
.push_back(kMIN1
);
594 QuicConfigPeer::SetReceivedConnectionOptions(&config
, options
);
595 sender_
->SetFromConfig(config
, Perspective::IS_SERVER
);
596 sender_
->OnRetransmissionTimeout(true);
597 EXPECT_EQ(1u, sender_
->congestion_window());
600 TEST_F(TcpCubicSenderTest
, 2ConnectionCongestionAvoidanceAtEndOfRecovery
) {
601 sender_
->SetNumEmulatedConnections(2);
602 // Ack 10 packets in 5 acks to raise the CWND to 20.
603 const int kNumberOfAcks
= 5;
604 for (int i
= 0; i
< kNumberOfAcks
; ++i
) {
605 // Send our full send window.
606 SendAvailableSendWindow();
609 SendAvailableSendWindow();
610 QuicByteCount expected_send_window
= kDefaultWindowTCP
+
611 (kDefaultTCPMSS
* 2 * kNumberOfAcks
);
612 EXPECT_EQ(expected_send_window
, sender_
->GetCongestionWindow());
616 // We should now have fallen out of slow start with a reduced window.
617 expected_send_window
= expected_send_window
* sender_
->GetRenoBeta();
618 EXPECT_EQ(expected_send_window
, sender_
->GetCongestionWindow());
620 // No congestion window growth should occur in recovery phase, i.e., until the
621 // currently outstanding 20 packets are acked.
622 for (int i
= 0; i
< 10; ++i
) {
623 // Send our full send window.
624 SendAvailableSendWindow();
625 EXPECT_TRUE(sender_
->InRecovery());
627 EXPECT_EQ(expected_send_window
, sender_
->GetCongestionWindow());
629 EXPECT_FALSE(sender_
->InRecovery());
631 // Out of recovery now. Congestion window should not grow for half an RTT.
632 size_t packets_in_send_window
= expected_send_window
/ kDefaultTCPMSS
;
633 SendAvailableSendWindow();
634 AckNPackets(packets_in_send_window
/ 2 - 2);
635 EXPECT_EQ(expected_send_window
, sender_
->GetCongestionWindow());
637 // Next ack should increase congestion window by 1MSS.
638 SendAvailableSendWindow();
640 expected_send_window
+= kDefaultTCPMSS
;
641 packets_in_send_window
+= 1;
642 EXPECT_EQ(expected_send_window
, sender_
->GetCongestionWindow());
644 // Congestion window should remain steady again for half an RTT.
645 SendAvailableSendWindow();
646 AckNPackets(packets_in_send_window
/ 2 - 1);
647 EXPECT_EQ(expected_send_window
, sender_
->GetCongestionWindow());
649 // Next ack should cause congestion window to grow by 1MSS.
650 SendAvailableSendWindow();
652 expected_send_window
+= kDefaultTCPMSS
;
653 EXPECT_EQ(expected_send_window
, sender_
->GetCongestionWindow());
656 TEST_F(TcpCubicSenderTest
, 1ConnectionCongestionAvoidanceAtEndOfRecovery
) {
657 sender_
->SetNumEmulatedConnections(1);
658 // Ack 10 packets in 5 acks to raise the CWND to 20.
659 const int kNumberOfAcks
= 5;
660 for (int i
= 0; i
< kNumberOfAcks
; ++i
) {
661 // Send our full send window.
662 SendAvailableSendWindow();
665 SendAvailableSendWindow();
666 QuicByteCount expected_send_window
= kDefaultWindowTCP
+
667 (kDefaultTCPMSS
* 2 * kNumberOfAcks
);
668 EXPECT_EQ(expected_send_window
, sender_
->GetCongestionWindow());
672 // We should now have fallen out of slow start with a reduced window.
673 expected_send_window
*= kRenoBeta
;
674 EXPECT_EQ(expected_send_window
, sender_
->GetCongestionWindow());
676 // No congestion window growth should occur in recovery phase, i.e., until the
677 // currently outstanding 20 packets are acked.
678 for (int i
= 0; i
< 10; ++i
) {
679 // Send our full send window.
680 SendAvailableSendWindow();
681 EXPECT_TRUE(sender_
->InRecovery());
683 EXPECT_EQ(expected_send_window
, sender_
->GetCongestionWindow());
685 EXPECT_FALSE(sender_
->InRecovery());
687 // Out of recovery now. Congestion window should not grow during RTT.
688 for (uint64 i
= 0; i
< expected_send_window
/ kDefaultTCPMSS
- 2; i
+= 2) {
689 // Send our full send window.
690 SendAvailableSendWindow();
692 EXPECT_EQ(expected_send_window
, sender_
->GetCongestionWindow());
695 // Next ack should cause congestion window to grow by 1MSS.
696 SendAvailableSendWindow();
698 expected_send_window
+= kDefaultTCPMSS
;
699 EXPECT_EQ(expected_send_window
, sender_
->GetCongestionWindow());
702 TEST_F(TcpCubicSenderTest
, BandwidthResumption
) {
703 // Test that when provided with CachedNetworkParameters and opted in to the
704 // bandwidth resumption experiment, that the TcpCubicSender sets initial CWND
707 // Set some common values.
708 CachedNetworkParameters cached_network_params
;
709 const QuicPacketCount kNumberOfPackets
= 123;
710 const int kBandwidthEstimateBytesPerSecond
=
711 kNumberOfPackets
* kMaxPacketSize
;
712 cached_network_params
.set_bandwidth_estimate_bytes_per_second(
713 kBandwidthEstimateBytesPerSecond
);
714 cached_network_params
.set_min_rtt_ms(1000);
716 // Make sure that a bandwidth estimate results in a changed CWND.
717 cached_network_params
.set_timestamp(clock_
.WallNow().ToUNIXSeconds() -
718 (kNumSecondsPerHour
- 1));
719 sender_
->ResumeConnectionState(cached_network_params
, false);
720 EXPECT_EQ(kNumberOfPackets
, sender_
->congestion_window());
722 // Resumed CWND is limited to be in a sensible range.
723 cached_network_params
.set_bandwidth_estimate_bytes_per_second(
724 (kMaxCongestionWindow
+ 1) * kMaxPacketSize
);
725 sender_
->ResumeConnectionState(cached_network_params
, false);
726 EXPECT_EQ(kMaxCongestionWindow
, sender_
->congestion_window());
728 cached_network_params
.set_bandwidth_estimate_bytes_per_second(
729 (kMinCongestionWindowForBandwidthResumption
- 1) * kMaxPacketSize
);
730 sender_
->ResumeConnectionState(cached_network_params
, false);
731 EXPECT_EQ(kMinCongestionWindowForBandwidthResumption
,
732 sender_
->congestion_window());
734 // Resume to the max value.
735 cached_network_params
.set_max_bandwidth_estimate_bytes_per_second(
736 (kMinCongestionWindowForBandwidthResumption
+ 10) * kDefaultTCPMSS
);
737 sender_
->ResumeConnectionState(cached_network_params
, true);
738 EXPECT_EQ((kMinCongestionWindowForBandwidthResumption
+ 10) * kDefaultTCPMSS
,
739 sender_
->GetCongestionWindow());
742 TEST_F(TcpCubicSenderTest
, PaceBelowCWND
) {
745 // Verify that kCOPT: kMIN4 forces the min CWND to 1 packet, but allows up
747 QuicTagVector options
;
748 options
.push_back(kMIN4
);
749 QuicConfigPeer::SetReceivedConnectionOptions(&config
, options
);
750 sender_
->SetFromConfig(config
, Perspective::IS_SERVER
);
751 sender_
->OnRetransmissionTimeout(true);
752 EXPECT_EQ(1u, sender_
->congestion_window());
753 EXPECT_TRUE(sender_
->TimeUntilSend(QuicTime::Zero(), kDefaultTCPMSS
,
754 HAS_RETRANSMITTABLE_DATA
).IsZero());
755 EXPECT_TRUE(sender_
->TimeUntilSend(QuicTime::Zero(), 2 * kDefaultTCPMSS
,
756 HAS_RETRANSMITTABLE_DATA
).IsZero());
757 EXPECT_TRUE(sender_
->TimeUntilSend(QuicTime::Zero(), 3 * kDefaultTCPMSS
,
758 HAS_RETRANSMITTABLE_DATA
).IsZero());
759 EXPECT_FALSE(sender_
->TimeUntilSend(QuicTime::Zero(), 4 * kDefaultTCPMSS
,
760 HAS_RETRANSMITTABLE_DATA
).IsZero());