OLD | NEW |
| (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 | |
OLD | NEW |