Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(211)

Side by Side Diff: net/quic/congestion_control/tcp_cubic_sender_test.cc

Issue 992733002: Remove //net (except for Android test stuff) and sdch (Closed) Base URL: git@github.com:domokit/mojo.git@master
Patch Set: Created 5 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
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.
4
5 #include <algorithm>
6
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"
17
18 using std::min;
19
20 namespace net {
21 namespace test {
22
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.
30
31 class TcpCubicSenderPeer : public TcpCubicSender {
32 public:
33 TcpCubicSenderPeer(const QuicClock* clock,
34 bool reno,
35 QuicPacketCount max_tcp_congestion_window)
36 : TcpCubicSender(
37 clock, &rtt_stats_, reno, kInitialCongestionWindowPackets,
38 max_tcp_congestion_window, &stats_) {
39 }
40
41 QuicPacketCount congestion_window() {
42 return congestion_window_;
43 }
44
45 QuicPacketCount slowstart_threshold() {
46 return slowstart_threshold_;
47 }
48
49 const HybridSlowStart& hybrid_slow_start() const {
50 return hybrid_slow_start_;
51 }
52
53 float GetRenoBeta() const {
54 return RenoBeta();
55 }
56
57 RttStats rtt_stats_;
58 QuicConnectionStats stats_;
59 };
60
61 class TcpCubicSenderTest : public ::testing::Test {
62 protected:
63 TcpCubicSenderTest()
64 : one_ms_(QuicTime::Delta::FromMilliseconds(1)),
65 sender_(new TcpCubicSenderPeer(&clock_, true,
66 kMaxTcpCongestionWindow)),
67 sequence_number_(1),
68 acked_sequence_number_(0),
69 bytes_in_flight_(0) {
70 standard_packet_.bytes_sent = kDefaultTCPMSS;
71 }
72
73 int SendAvailableSendWindow() {
74 // Send as long as TimeUntilSend returns Zero.
75 int packets_sent = 0;
76 bool can_send = sender_->TimeUntilSend(
77 clock_.Now(), bytes_in_flight_, HAS_RETRANSMITTABLE_DATA).IsZero();
78 while (can_send) {
79 sender_->OnPacketSent(clock_.Now(), bytes_in_flight_, sequence_number_++,
80 kDefaultTCPMSS, HAS_RETRANSMITTABLE_DATA);
81 ++packets_sent;
82 bytes_in_flight_ += kDefaultTCPMSS;
83 can_send = sender_->TimeUntilSend(
84 clock_.Now(), bytes_in_flight_, HAS_RETRANSMITTABLE_DATA).IsZero();
85 }
86 return packets_sent;
87 }
88
89 // Normal is that TCP acks every other segment.
90 void AckNPackets(int n) {
91 sender_->rtt_stats_.UpdateRtt(QuicTime::Delta::FromMilliseconds(60),
92 QuicTime::Delta::Zero(),
93 clock_.Now());
94 SendAlgorithmInterface::CongestionVector acked_packets;
95 SendAlgorithmInterface::CongestionVector lost_packets;
96 for (int i = 0; i < n; ++i) {
97 ++acked_sequence_number_;
98 acked_packets.push_back(
99 std::make_pair(acked_sequence_number_, standard_packet_));
100 }
101 sender_->OnCongestionEvent(
102 true, bytes_in_flight_, acked_packets, lost_packets);
103 bytes_in_flight_ -= n * kDefaultTCPMSS;
104 clock_.AdvanceTime(one_ms_);
105 }
106
107 void LoseNPackets(int n) {
108 SendAlgorithmInterface::CongestionVector acked_packets;
109 SendAlgorithmInterface::CongestionVector lost_packets;
110 for (int i = 0; i < n; ++i) {
111 ++acked_sequence_number_;
112 lost_packets.push_back(
113 std::make_pair(acked_sequence_number_, standard_packet_));
114 }
115 sender_->OnCongestionEvent(
116 false, bytes_in_flight_, acked_packets, lost_packets);
117 bytes_in_flight_ -= n * kDefaultTCPMSS;
118 }
119
120 // Does not increment acked_sequence_number_.
121 void LosePacket(QuicPacketSequenceNumber sequence_number) {
122 SendAlgorithmInterface::CongestionVector acked_packets;
123 SendAlgorithmInterface::CongestionVector lost_packets;
124 lost_packets.push_back(std::make_pair(sequence_number, standard_packet_));
125 sender_->OnCongestionEvent(
126 false, bytes_in_flight_, acked_packets, lost_packets);
127 bytes_in_flight_ -= kDefaultTCPMSS;
128 }
129
130 const QuicTime::Delta one_ms_;
131 MockClock clock_;
132 scoped_ptr<TcpCubicSenderPeer> sender_;
133 QuicPacketSequenceNumber sequence_number_;
134 QuicPacketSequenceNumber acked_sequence_number_;
135 QuicByteCount bytes_in_flight_;
136 TransmissionInfo standard_packet_;
137 };
138
139 TEST_F(TcpCubicSenderTest, SimpleSender) {
140 // At startup make sure we are at the default.
141 EXPECT_EQ(kDefaultWindowTCP, sender_->GetCongestionWindow());
142 // At startup make sure we can send.
143 EXPECT_TRUE(sender_->TimeUntilSend(clock_.Now(),
144 0,
145 HAS_RETRANSMITTABLE_DATA).IsZero());
146 // Make sure we can send.
147 EXPECT_TRUE(sender_->TimeUntilSend(clock_.Now(),
148 0,
149 HAS_RETRANSMITTABLE_DATA).IsZero());
150 // And that window is un-affected.
151 EXPECT_EQ(kDefaultWindowTCP, sender_->GetCongestionWindow());
152
153 // Fill the send window with data, then verify that we can't send.
154 SendAvailableSendWindow();
155 EXPECT_FALSE(sender_->TimeUntilSend(clock_.Now(),
156 sender_->GetCongestionWindow(),
157 HAS_RETRANSMITTABLE_DATA).IsZero());
158 }
159
160 TEST_F(TcpCubicSenderTest, ApplicationLimitedSlowStart) {
161 // Send exactly 10 packets and ensure the CWND ends at 14 packets.
162 const int kNumberOfAcks = 5;
163 // At startup make sure we can send.
164 EXPECT_TRUE(sender_->TimeUntilSend(clock_.Now(),
165 0,
166 HAS_RETRANSMITTABLE_DATA).IsZero());
167 // Make sure we can send.
168 EXPECT_TRUE(sender_->TimeUntilSend(clock_.Now(),
169 0,
170 HAS_RETRANSMITTABLE_DATA).IsZero());
171
172 SendAvailableSendWindow();
173 for (int i = 0; i < kNumberOfAcks; ++i) {
174 AckNPackets(2);
175 }
176 QuicByteCount bytes_to_send = sender_->GetCongestionWindow();
177 // It's expected 2 acks will arrive when the bytes_in_flight are greater than
178 // half the CWND.
179 EXPECT_EQ(kDefaultWindowTCP + kDefaultTCPMSS * 2 * 2,
180 bytes_to_send);
181 }
182
183 TEST_F(TcpCubicSenderTest, ExponentialSlowStart) {
184 const int kNumberOfAcks = 20;
185 // At startup make sure we can send.
186 EXPECT_TRUE(sender_->TimeUntilSend(clock_.Now(),
187 0,
188 HAS_RETRANSMITTABLE_DATA).IsZero());
189 EXPECT_FALSE(sender_->HasReliableBandwidthEstimate());
190 EXPECT_EQ(QuicBandwidth::Zero(), sender_->BandwidthEstimate());
191 // Make sure we can send.
192 EXPECT_TRUE(sender_->TimeUntilSend(clock_.Now(),
193 0,
194 HAS_RETRANSMITTABLE_DATA).IsZero());
195
196 for (int i = 0; i < kNumberOfAcks; ++i) {
197 // Send our full send window.
198 SendAvailableSendWindow();
199 AckNPackets(2);
200 }
201 const QuicByteCount cwnd = sender_->GetCongestionWindow();
202 EXPECT_EQ(kDefaultWindowTCP + kDefaultTCPMSS * 2 * kNumberOfAcks, cwnd);
203 EXPECT_FALSE(sender_->HasReliableBandwidthEstimate());
204 EXPECT_EQ(QuicBandwidth::FromBytesAndTimeDelta(
205 cwnd, sender_->rtt_stats_.smoothed_rtt()),
206 sender_->BandwidthEstimate());
207 }
208
209 TEST_F(TcpCubicSenderTest, SlowStartAckTrain) {
210 sender_->SetNumEmulatedConnections(1);
211 EXPECT_EQ(kMaxTcpCongestionWindow * kDefaultTCPMSS,
212 sender_->GetSlowStartThreshold());
213
214 // Make sure that we fall out of slow start when we send ACK train longer
215 // than half the RTT, in this test case 30ms, which is more than 30 calls to
216 // Ack2Packets in one round.
217 // Since we start at 10 packet first round will be 5 second round 10 etc
218 // Hence we should pass 30 at 65 = 5 + 10 + 20 + 30
219 const int kNumberOfAcks = 65;
220 for (int i = 0; i < kNumberOfAcks; ++i) {
221 // Send our full send window.
222 SendAvailableSendWindow();
223 AckNPackets(2);
224 }
225 QuicByteCount expected_send_window =
226 kDefaultWindowTCP + (kDefaultTCPMSS * 2 * kNumberOfAcks);
227 EXPECT_EQ(expected_send_window, sender_->GetCongestionWindow());
228
229 // We should now have fallen out of slow start.
230 // Testing Reno phase.
231 // We should need 140(65*2+10) ACK:ed packets before increasing window by
232 // one.
233 for (int i = 0; i < 69; ++i) {
234 SendAvailableSendWindow();
235 AckNPackets(2);
236 EXPECT_EQ(expected_send_window, sender_->GetCongestionWindow());
237 }
238 SendAvailableSendWindow();
239 AckNPackets(2);
240 QuicByteCount expected_ss_tresh = expected_send_window;
241 expected_send_window += kDefaultTCPMSS;
242 EXPECT_EQ(expected_send_window, sender_->GetCongestionWindow());
243 EXPECT_EQ(expected_ss_tresh, sender_->GetSlowStartThreshold());
244 EXPECT_EQ(140u, sender_->slowstart_threshold());
245
246 // Now RTO and ensure slow start gets reset.
247 EXPECT_TRUE(sender_->hybrid_slow_start().started());
248 sender_->OnRetransmissionTimeout(true);
249 EXPECT_FALSE(sender_->hybrid_slow_start().started());
250 EXPECT_EQ(2 * kDefaultTCPMSS, sender_->GetCongestionWindow());
251 EXPECT_EQ(expected_send_window / 2 / kDefaultTCPMSS,
252 sender_->slowstart_threshold());
253
254 // Now revert the RTO and ensure the CWND and slowstart threshold revert.
255 sender_->RevertRetransmissionTimeout();
256 EXPECT_EQ(expected_send_window, sender_->GetCongestionWindow());
257 EXPECT_EQ(140u, sender_->slowstart_threshold());
258 }
259
260 TEST_F(TcpCubicSenderTest, SlowStartPacketLoss) {
261 sender_->SetNumEmulatedConnections(1);
262 const int kNumberOfAcks = 10;
263 for (int i = 0; i < kNumberOfAcks; ++i) {
264 // Send our full send window.
265 SendAvailableSendWindow();
266 AckNPackets(2);
267 }
268 SendAvailableSendWindow();
269 QuicByteCount expected_send_window = kDefaultWindowTCP +
270 (kDefaultTCPMSS * 2 * kNumberOfAcks);
271 EXPECT_EQ(expected_send_window, sender_->GetCongestionWindow());
272
273 // Lose a packet to exit slow start.
274 LoseNPackets(1);
275 size_t packets_in_recovery_window = expected_send_window / kDefaultTCPMSS;
276
277 // We should now have fallen out of slow start with a reduced window.
278 expected_send_window *= kRenoBeta;
279 EXPECT_EQ(expected_send_window, sender_->GetCongestionWindow());
280
281 // Recovery phase. We need to ack every packet in the recovery window before
282 // we exit recovery.
283 size_t number_of_packets_in_window = expected_send_window / kDefaultTCPMSS;
284 DVLOG(1) << "number_packets: " << number_of_packets_in_window;
285 AckNPackets(packets_in_recovery_window);
286 SendAvailableSendWindow();
287 EXPECT_EQ(expected_send_window, sender_->GetCongestionWindow());
288
289 // We need to ack an entire window before we increase CWND by 1.
290 AckNPackets(number_of_packets_in_window - 2);
291 SendAvailableSendWindow();
292 EXPECT_EQ(expected_send_window, sender_->GetCongestionWindow());
293
294 // Next ack should increase cwnd by 1.
295 AckNPackets(1);
296 expected_send_window += kDefaultTCPMSS;
297 EXPECT_EQ(expected_send_window, sender_->GetCongestionWindow());
298
299 // Now RTO and ensure slow start gets reset.
300 EXPECT_TRUE(sender_->hybrid_slow_start().started());
301 sender_->OnRetransmissionTimeout(true);
302 EXPECT_FALSE(sender_->hybrid_slow_start().started());
303 }
304
305 TEST_F(TcpCubicSenderTest, NoPRRWhenLessThanOnePacketInFlight) {
306 SendAvailableSendWindow();
307 LoseNPackets(kInitialCongestionWindowPackets - 1);
308 AckNPackets(1);
309 // PRR will allow 2 packets for every ack during recovery.
310 EXPECT_EQ(2, SendAvailableSendWindow());
311 // Simulate abandoning all packets by supplying a bytes_in_flight of 0.
312 // PRR should now allow a packet to be sent, even though prr's state
313 // variables believe it has sent enough packets.
314 EXPECT_EQ(QuicTime::Delta::Zero(),
315 sender_->TimeUntilSend(clock_.Now(), 0, HAS_RETRANSMITTABLE_DATA));
316 }
317
318 TEST_F(TcpCubicSenderTest, SlowStartPacketLossPRR) {
319 sender_->SetNumEmulatedConnections(1);
320 // Test based on the first example in RFC6937.
321 // Ack 10 packets in 5 acks to raise the CWND to 20, as in the example.
322 const int kNumberOfAcks = 5;
323 for (int i = 0; i < kNumberOfAcks; ++i) {
324 // Send our full send window.
325 SendAvailableSendWindow();
326 AckNPackets(2);
327 }
328 SendAvailableSendWindow();
329 QuicByteCount expected_send_window = kDefaultWindowTCP +
330 (kDefaultTCPMSS * 2 * kNumberOfAcks);
331 EXPECT_EQ(expected_send_window, sender_->GetCongestionWindow());
332
333 LoseNPackets(1);
334
335 // We should now have fallen out of slow start with a reduced window.
336 size_t send_window_before_loss = expected_send_window;
337 expected_send_window *= kRenoBeta;
338 EXPECT_EQ(expected_send_window, sender_->GetCongestionWindow());
339
340 // Testing TCP proportional rate reduction.
341 // We should send packets paced over the received acks for the remaining
342 // outstanding packets. The number of packets before we exit recovery is the
343 // original CWND minus the packet that has been lost and the one which
344 // triggered the loss.
345 size_t remaining_packets_in_recovery =
346 send_window_before_loss / kDefaultTCPMSS - 2;
347
348 for (size_t i = 0; i < remaining_packets_in_recovery; ++i) {
349 AckNPackets(1);
350 SendAvailableSendWindow();
351 EXPECT_EQ(expected_send_window, sender_->GetCongestionWindow());
352 }
353
354 // We need to ack another window before we increase CWND by 1.
355 size_t number_of_packets_in_window = expected_send_window / kDefaultTCPMSS;
356 for (size_t i = 0; i < number_of_packets_in_window; ++i) {
357 AckNPackets(1);
358 EXPECT_EQ(1, SendAvailableSendWindow());
359 EXPECT_EQ(expected_send_window, sender_->GetCongestionWindow());
360 }
361
362 AckNPackets(1);
363 expected_send_window += kDefaultTCPMSS;
364 EXPECT_EQ(expected_send_window, sender_->GetCongestionWindow());
365 }
366
367 TEST_F(TcpCubicSenderTest, SlowStartBurstPacketLossPRR) {
368 sender_->SetNumEmulatedConnections(1);
369 // Test based on the second example in RFC6937, though we also implement
370 // forward acknowledgements, so the first two incoming acks will trigger
371 // PRR immediately.
372 // Ack 20 packets in 10 acks to raise the CWND to 30.
373 const int kNumberOfAcks = 10;
374 for (int i = 0; i < kNumberOfAcks; ++i) {
375 // Send our full send window.
376 SendAvailableSendWindow();
377 AckNPackets(2);
378 }
379 SendAvailableSendWindow();
380 QuicByteCount expected_send_window = kDefaultWindowTCP +
381 (kDefaultTCPMSS * 2 * kNumberOfAcks);
382 EXPECT_EQ(expected_send_window, sender_->GetCongestionWindow());
383
384 // Lose one more than the congestion window reduction, so that after loss,
385 // bytes_in_flight is lesser than the congestion window.
386 size_t send_window_after_loss = kRenoBeta * expected_send_window;
387 size_t num_packets_to_lose =
388 (expected_send_window - send_window_after_loss) / kDefaultTCPMSS + 1;
389 LoseNPackets(num_packets_to_lose);
390 // Immediately after the loss, ensure at least one packet can be sent.
391 // Losses without subsequent acks can occur with timer based loss detection.
392 EXPECT_TRUE(sender_->TimeUntilSend(
393 clock_.Now(), bytes_in_flight_, HAS_RETRANSMITTABLE_DATA).IsZero());
394 AckNPackets(1);
395
396 // We should now have fallen out of slow start with a reduced window.
397 expected_send_window *= kRenoBeta;
398 EXPECT_EQ(expected_send_window, sender_->GetCongestionWindow());
399
400 // Only 2 packets should be allowed to be sent, per PRR-SSRB
401 EXPECT_EQ(2, SendAvailableSendWindow());
402
403 // Ack the next packet, which triggers another loss.
404 LoseNPackets(1);
405 AckNPackets(1);
406
407 // Send 2 packets to simulate PRR-SSRB.
408 EXPECT_EQ(2, SendAvailableSendWindow());
409
410 // Ack the next packet, which triggers another loss.
411 LoseNPackets(1);
412 AckNPackets(1);
413
414 // Send 2 packets to simulate PRR-SSRB.
415 EXPECT_EQ(2, SendAvailableSendWindow());
416
417 // Exit recovery and return to sending at the new rate.
418 for (int i = 0; i < kNumberOfAcks; ++i) {
419 AckNPackets(1);
420 EXPECT_EQ(1, SendAvailableSendWindow());
421 }
422 }
423
424 TEST_F(TcpCubicSenderTest, RTOCongestionWindowAndRevert) {
425 EXPECT_EQ(kDefaultWindowTCP, sender_->GetCongestionWindow());
426 EXPECT_EQ(kMaxTcpCongestionWindow, sender_->slowstart_threshold());
427
428 // Expect the window to decrease to the minimum once the RTO fires
429 // and slow start threshold to be set to 1/2 of the CWND.
430 sender_->OnRetransmissionTimeout(true);
431 EXPECT_EQ(2 * kDefaultTCPMSS, sender_->GetCongestionWindow());
432 EXPECT_EQ(5u, sender_->slowstart_threshold());
433
434 // Now repair the RTO and ensure the slowstart threshold reverts.
435 sender_->RevertRetransmissionTimeout();
436 EXPECT_EQ(kDefaultWindowTCP, sender_->GetCongestionWindow());
437 EXPECT_EQ(kMaxTcpCongestionWindow, sender_->slowstart_threshold());
438 }
439
440 TEST_F(TcpCubicSenderTest, RTOCongestionWindowNoRetransmission) {
441 EXPECT_EQ(kDefaultWindowTCP, sender_->GetCongestionWindow());
442
443 // Expect the window to remain unchanged if the RTO fires but no
444 // packets are retransmitted.
445 sender_->OnRetransmissionTimeout(false);
446 EXPECT_EQ(kDefaultWindowTCP, sender_->GetCongestionWindow());
447 }
448
449 TEST_F(TcpCubicSenderTest, RTOTwiceOnlyHalvesSsthresh) {
450 EXPECT_EQ(kDefaultWindowTCP, sender_->GetCongestionWindow());
451
452 sender_->OnRetransmissionTimeout(true);
453 EXPECT_EQ(2 * kDefaultTCPMSS, sender_->GetCongestionWindow());
454 EXPECT_EQ(5u, sender_->slowstart_threshold());
455
456 sender_->OnRetransmissionTimeout(true);
457 EXPECT_EQ(2 * kDefaultTCPMSS, sender_->GetCongestionWindow());
458 EXPECT_EQ(5u, sender_->slowstart_threshold());
459
460 AckNPackets(2);
461
462 EXPECT_EQ(4 * kDefaultTCPMSS, sender_->GetCongestionWindow());
463 EXPECT_EQ(5u, sender_->slowstart_threshold());
464
465 sender_->OnRetransmissionTimeout(true);
466 EXPECT_EQ(2 * kDefaultTCPMSS, sender_->GetCongestionWindow());
467 EXPECT_EQ(2u, sender_->slowstart_threshold());
468 }
469
470 TEST_F(TcpCubicSenderTest, RetransmissionDelay) {
471 const int64 kRttMs = 10;
472 const int64 kDeviationMs = 3;
473 EXPECT_EQ(QuicTime::Delta::Zero(), sender_->RetransmissionDelay());
474
475 sender_->rtt_stats_.UpdateRtt(QuicTime::Delta::FromMilliseconds(kRttMs),
476 QuicTime::Delta::Zero(), clock_.Now());
477
478 // Initial value is to set the median deviation to half of the initial
479 // rtt, the median in then multiplied by a factor of 4 and finally the
480 // smoothed rtt is added which is the initial rtt.
481 QuicTime::Delta expected_delay =
482 QuicTime::Delta::FromMilliseconds(kRttMs + kRttMs / 2 * 4);
483 EXPECT_EQ(expected_delay, sender_->RetransmissionDelay());
484
485 for (int i = 0; i < 100; ++i) {
486 // Run to make sure that we converge.
487 sender_->rtt_stats_.UpdateRtt(
488 QuicTime::Delta::FromMilliseconds(kRttMs + kDeviationMs),
489 QuicTime::Delta::Zero(), clock_.Now());
490 sender_->rtt_stats_.UpdateRtt(
491 QuicTime::Delta::FromMilliseconds(kRttMs - kDeviationMs),
492 QuicTime::Delta::Zero(), clock_.Now());
493 }
494 expected_delay = QuicTime::Delta::FromMilliseconds(kRttMs + kDeviationMs * 4);
495
496 EXPECT_NEAR(kRttMs, sender_->rtt_stats_.smoothed_rtt().ToMilliseconds(), 1);
497 EXPECT_NEAR(expected_delay.ToMilliseconds(),
498 sender_->RetransmissionDelay().ToMilliseconds(),
499 1);
500 EXPECT_EQ(static_cast<int64>(
501 sender_->GetCongestionWindow() * kNumMicrosPerSecond /
502 sender_->rtt_stats_.smoothed_rtt().ToMicroseconds()),
503 sender_->BandwidthEstimate().ToBytesPerSecond());
504 }
505
506 TEST_F(TcpCubicSenderTest, SlowStartMaxSendWindow) {
507 const QuicPacketCount kMaxCongestionWindowTCP = 50;
508 const int kNumberOfAcks = 100;
509 sender_.reset(
510 new TcpCubicSenderPeer(&clock_, false, kMaxCongestionWindowTCP));
511
512 for (int i = 0; i < kNumberOfAcks; ++i) {
513 // Send our full send window.
514 SendAvailableSendWindow();
515 AckNPackets(2);
516 }
517 QuicByteCount expected_send_window =
518 kMaxCongestionWindowTCP * kDefaultTCPMSS;
519 EXPECT_EQ(expected_send_window, sender_->GetCongestionWindow());
520 }
521
522 TEST_F(TcpCubicSenderTest, TcpRenoMaxCongestionWindow) {
523 const QuicPacketCount kMaxCongestionWindowTCP = 50;
524 const int kNumberOfAcks = 1000;
525 sender_.reset(
526 new TcpCubicSenderPeer(&clock_, true, kMaxCongestionWindowTCP));
527
528 SendAvailableSendWindow();
529 AckNPackets(2);
530 // Make sure we fall out of slow start.
531 LoseNPackets(1);
532
533 for (int i = 0; i < kNumberOfAcks; ++i) {
534 // Send our full send window.
535 SendAvailableSendWindow();
536 AckNPackets(2);
537 }
538
539 QuicByteCount expected_send_window =
540 kMaxCongestionWindowTCP * kDefaultTCPMSS;
541 EXPECT_EQ(expected_send_window, sender_->GetCongestionWindow());
542 }
543
544 TEST_F(TcpCubicSenderTest, TcpCubicMaxCongestionWindow) {
545 const QuicPacketCount kMaxCongestionWindowTCP = 50;
546 // Set to 10000 to compensate for small cubic alpha.
547 const int kNumberOfAcks = 10000;
548
549 sender_.reset(
550 new TcpCubicSenderPeer(&clock_, false, kMaxCongestionWindowTCP));
551
552 SendAvailableSendWindow();
553 AckNPackets(2);
554 // Make sure we fall out of slow start.
555 LoseNPackets(1);
556
557 for (int i = 0; i < kNumberOfAcks; ++i) {
558 // Send our full send window.
559 SendAvailableSendWindow();
560 AckNPackets(2);
561 }
562
563 QuicByteCount expected_send_window =
564 kMaxCongestionWindowTCP * kDefaultTCPMSS;
565 EXPECT_EQ(expected_send_window, sender_->GetCongestionWindow());
566 }
567
568 TEST_F(TcpCubicSenderTest, MultipleLossesInOneWindow) {
569 SendAvailableSendWindow();
570 const QuicByteCount initial_window = sender_->GetCongestionWindow();
571 LosePacket(acked_sequence_number_ + 1);
572 const QuicByteCount post_loss_window = sender_->GetCongestionWindow();
573 EXPECT_GT(initial_window, post_loss_window);
574 LosePacket(acked_sequence_number_ + 3);
575 EXPECT_EQ(post_loss_window, sender_->GetCongestionWindow());
576 LosePacket(sequence_number_ - 1);
577 EXPECT_EQ(post_loss_window, sender_->GetCongestionWindow());
578
579 // Lose a later packet and ensure the window decreases.
580 LosePacket(sequence_number_);
581 EXPECT_GT(post_loss_window, sender_->GetCongestionWindow());
582 }
583
584 TEST_F(TcpCubicSenderTest, DontTrackAckPackets) {
585 // Send a packet with no retransmittable data, and ensure it's not tracked.
586 EXPECT_FALSE(sender_->OnPacketSent(clock_.Now(), bytes_in_flight_,
587 sequence_number_++, kDefaultTCPMSS,
588 NO_RETRANSMITTABLE_DATA));
589
590 // Send a data packet with retransmittable data, and ensure it is tracked.
591 EXPECT_TRUE(sender_->OnPacketSent(clock_.Now(), bytes_in_flight_,
592 sequence_number_++, kDefaultTCPMSS,
593 HAS_RETRANSMITTABLE_DATA));
594 }
595
596 TEST_F(TcpCubicSenderTest, ConfigureMaxInitialWindow) {
597 QuicConfig config;
598
599 // Verify that kCOPT: kIW10 forces the congestion window to the default of 10.
600 QuicTagVector options;
601 options.push_back(kIW10);
602 QuicConfigPeer::SetReceivedConnectionOptions(&config, options);
603 sender_->SetFromConfig(config,
604 /* is_server= */ true,
605 /* using_pacing= */ false);
606 EXPECT_EQ(10u, sender_->congestion_window());
607 }
608
609 TEST_F(TcpCubicSenderTest, DisableAckTrainDetectionWithPacing) {
610 EXPECT_TRUE(sender_->hybrid_slow_start().ack_train_detection());
611
612 QuicConfig config;
613 sender_->SetFromConfig(config,
614 /* is_server= */ true,
615 /* using_pacing= */ true);
616 EXPECT_FALSE(sender_->hybrid_slow_start().ack_train_detection());
617 }
618
619 TEST_F(TcpCubicSenderTest, 2ConnectionCongestionAvoidanceAtEndOfRecovery) {
620 sender_->SetNumEmulatedConnections(2);
621 // Ack 10 packets in 5 acks to raise the CWND to 20.
622 const int kNumberOfAcks = 5;
623 for (int i = 0; i < kNumberOfAcks; ++i) {
624 // Send our full send window.
625 SendAvailableSendWindow();
626 AckNPackets(2);
627 }
628 SendAvailableSendWindow();
629 QuicByteCount expected_send_window = kDefaultWindowTCP +
630 (kDefaultTCPMSS * 2 * kNumberOfAcks);
631 EXPECT_EQ(expected_send_window, sender_->GetCongestionWindow());
632
633 LoseNPackets(1);
634
635 // We should now have fallen out of slow start with a reduced window.
636 expected_send_window = expected_send_window * sender_->GetRenoBeta();
637 EXPECT_EQ(expected_send_window, sender_->GetCongestionWindow());
638
639 // No congestion window growth should occur in recovery phase, i.e., until the
640 // currently outstanding 20 packets are acked.
641 for (int i = 0; i < 10; ++i) {
642 // Send our full send window.
643 SendAvailableSendWindow();
644 EXPECT_TRUE(sender_->InRecovery());
645 AckNPackets(2);
646 EXPECT_EQ(expected_send_window, sender_->GetCongestionWindow());
647 }
648 EXPECT_FALSE(sender_->InRecovery());
649
650 // Out of recovery now. Congestion window should not grow for half an RTT.
651 size_t packets_in_send_window = expected_send_window / kDefaultTCPMSS;
652 SendAvailableSendWindow();
653 AckNPackets(packets_in_send_window / 2 - 2);
654 EXPECT_EQ(expected_send_window, sender_->GetCongestionWindow());
655
656 // Next ack should increase congestion window by 1MSS.
657 SendAvailableSendWindow();
658 AckNPackets(2);
659 expected_send_window += kDefaultTCPMSS;
660 packets_in_send_window += 1;
661 EXPECT_EQ(expected_send_window, sender_->GetCongestionWindow());
662
663 // Congestion window should remain steady again for half an RTT.
664 SendAvailableSendWindow();
665 AckNPackets(packets_in_send_window / 2 - 1);
666 EXPECT_EQ(expected_send_window, sender_->GetCongestionWindow());
667
668 // Next ack should cause congestion window to grow by 1MSS.
669 SendAvailableSendWindow();
670 AckNPackets(2);
671 expected_send_window += kDefaultTCPMSS;
672 EXPECT_EQ(expected_send_window, sender_->GetCongestionWindow());
673 }
674
675 TEST_F(TcpCubicSenderTest, 1ConnectionCongestionAvoidanceAtEndOfRecovery) {
676 sender_->SetNumEmulatedConnections(1);
677 // Ack 10 packets in 5 acks to raise the CWND to 20.
678 const int kNumberOfAcks = 5;
679 for (int i = 0; i < kNumberOfAcks; ++i) {
680 // Send our full send window.
681 SendAvailableSendWindow();
682 AckNPackets(2);
683 }
684 SendAvailableSendWindow();
685 QuicByteCount expected_send_window = kDefaultWindowTCP +
686 (kDefaultTCPMSS * 2 * kNumberOfAcks);
687 EXPECT_EQ(expected_send_window, sender_->GetCongestionWindow());
688
689 LoseNPackets(1);
690
691 // We should now have fallen out of slow start with a reduced window.
692 expected_send_window *= kRenoBeta;
693 EXPECT_EQ(expected_send_window, sender_->GetCongestionWindow());
694
695 // No congestion window growth should occur in recovery phase, i.e., until the
696 // currently outstanding 20 packets are acked.
697 for (int i = 0; i < 10; ++i) {
698 // Send our full send window.
699 SendAvailableSendWindow();
700 EXPECT_TRUE(sender_->InRecovery());
701 AckNPackets(2);
702 EXPECT_EQ(expected_send_window, sender_->GetCongestionWindow());
703 }
704 EXPECT_FALSE(sender_->InRecovery());
705
706 // Out of recovery now. Congestion window should not grow during RTT.
707 for (uint64 i = 0; i < expected_send_window / kDefaultTCPMSS - 2; i += 2) {
708 // Send our full send window.
709 SendAvailableSendWindow();
710 AckNPackets(2);
711 EXPECT_EQ(expected_send_window, sender_->GetCongestionWindow());
712 }
713
714 // Next ack should cause congestion window to grow by 1MSS.
715 SendAvailableSendWindow();
716 AckNPackets(2);
717 expected_send_window += kDefaultTCPMSS;
718 EXPECT_EQ(expected_send_window, sender_->GetCongestionWindow());
719 }
720
721 TEST_F(TcpCubicSenderTest, BandwidthResumption) {
722 // Test that when provided with CachedNetworkParameters and opted in to the
723 // bandwidth resumption experiment, that the TcpCubicSender sets initial CWND
724 // appropriately.
725
726 // Set some common values.
727 CachedNetworkParameters cached_network_params;
728 const QuicPacketCount kNumberOfPackets = 123;
729 const int kBandwidthEstimateBytesPerSecond =
730 kNumberOfPackets * kMaxPacketSize;
731 cached_network_params.set_bandwidth_estimate_bytes_per_second(
732 kBandwidthEstimateBytesPerSecond);
733 cached_network_params.set_min_rtt_ms(1000);
734
735 // Ensure that an old estimate is not used for bandwidth resumption.
736 cached_network_params.set_timestamp(clock_.WallNow().ToUNIXSeconds() -
737 (kNumSecondsPerHour + 1));
738 EXPECT_FALSE(sender_->ResumeConnectionState(cached_network_params));
739 EXPECT_EQ(10u, sender_->congestion_window());
740
741 // If the estimate is new enough, make sure it is used.
742 cached_network_params.set_timestamp(clock_.WallNow().ToUNIXSeconds() -
743 (kNumSecondsPerHour - 1));
744 EXPECT_TRUE(sender_->ResumeConnectionState(cached_network_params));
745 EXPECT_EQ(kNumberOfPackets, sender_->congestion_window());
746
747 // Resumed CWND is limited to be in a sensible range.
748 cached_network_params.set_bandwidth_estimate_bytes_per_second(
749 (kMaxTcpCongestionWindow + 1) * kMaxPacketSize);
750 EXPECT_TRUE(sender_->ResumeConnectionState(cached_network_params));
751 EXPECT_EQ(kMaxTcpCongestionWindow, sender_->congestion_window());
752
753 cached_network_params.set_bandwidth_estimate_bytes_per_second(
754 (kMinCongestionWindowForBandwidthResumption - 1) * kMaxPacketSize);
755 EXPECT_TRUE(sender_->ResumeConnectionState(cached_network_params));
756 EXPECT_EQ(kMinCongestionWindowForBandwidthResumption,
757 sender_->congestion_window());
758 }
759
760 } // namespace test
761 } // namespace net
OLDNEW
« no previous file with comments | « net/quic/congestion_control/tcp_cubic_sender.cc ('k') | net/quic/congestion_control/tcp_loss_algorithm.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698