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 "net/quic/congestion_control/tcp_cubic_sender_packets.h" | |
6 | |
7 #include <algorithm> | |
8 #include <memory> | |
9 | |
10 #include "base/logging.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" | |
21 | |
22 using std::min; | |
23 | |
24 namespace net { | |
25 namespace test { | |
26 | |
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 kInitialCongestionWindow. | |
30 const uint32_t kInitialCongestionWindowPackets = 10; | |
31 const uint32_t kMaxCongestionWindowPackets = 200; | |
32 const uint32_t kDefaultWindowTCP = | |
33 kInitialCongestionWindowPackets * kDefaultTCPMSS; | |
34 const float kRenoBeta = 0.7f; // Reno backoff factor. | |
35 | |
36 class TcpCubicSenderPacketsPeer : public TcpCubicSenderPackets { | |
37 public: | |
38 TcpCubicSenderPacketsPeer(const QuicClock* clock, | |
39 bool reno, | |
40 QuicPacketCount max_tcp_congestion_window) | |
41 : TcpCubicSenderPackets(clock, | |
42 &rtt_stats_, | |
43 reno, | |
44 kInitialCongestionWindowPackets, | |
45 max_tcp_congestion_window, | |
46 &stats_) {} | |
47 | |
48 QuicPacketCount congestion_window() { return congestion_window_; } | |
49 | |
50 QuicPacketCount max_congestion_window() { return max_tcp_congestion_window_; } | |
51 | |
52 QuicPacketCount slowstart_threshold() { return slowstart_threshold_; } | |
53 | |
54 const HybridSlowStart& hybrid_slow_start() const { | |
55 return hybrid_slow_start_; | |
56 } | |
57 | |
58 float GetRenoBeta() const { return RenoBeta(); } | |
59 | |
60 RttStats rtt_stats_; | |
61 QuicConnectionStats stats_; | |
62 }; | |
63 | |
64 class TcpCubicSenderPacketsTest : public ::testing::Test { | |
65 protected: | |
66 TcpCubicSenderPacketsTest() | |
67 : one_ms_(QuicTime::Delta::FromMilliseconds(1)), | |
68 sender_(new TcpCubicSenderPacketsPeer(&clock_, | |
69 true, | |
70 kMaxCongestionWindowPackets)), | |
71 packet_number_(1), | |
72 acked_packet_number_(0), | |
73 bytes_in_flight_(0) {} | |
74 | |
75 int SendAvailableSendWindow() { | |
76 return SendAvailableSendWindow(kDefaultTCPMSS); | |
77 } | |
78 | |
79 int SendAvailableSendWindow(QuicPacketLength packet_length) { | |
80 // Send as long as TimeUntilSend returns Zero. | |
81 int packets_sent = 0; | |
82 bool can_send = | |
83 sender_->TimeUntilSend(clock_.Now(), bytes_in_flight_).IsZero(); | |
84 while (can_send) { | |
85 sender_->OnPacketSent(clock_.Now(), bytes_in_flight_, packet_number_++, | |
86 kDefaultTCPMSS, HAS_RETRANSMITTABLE_DATA); | |
87 ++packets_sent; | |
88 bytes_in_flight_ += kDefaultTCPMSS; | |
89 can_send = | |
90 sender_->TimeUntilSend(clock_.Now(), bytes_in_flight_).IsZero(); | |
91 } | |
92 return packets_sent; | |
93 } | |
94 | |
95 // Normal is that TCP acks every other segment. | |
96 void AckNPackets(int n) { | |
97 sender_->rtt_stats_.UpdateRtt(QuicTime::Delta::FromMilliseconds(60), | |
98 QuicTime::Delta::Zero(), clock_.Now()); | |
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_, kDefaultTCPMSS)); | |
105 } | |
106 sender_->OnCongestionEvent(true, bytes_in_flight_, acked_packets, | |
107 lost_packets); | |
108 bytes_in_flight_ -= n * kDefaultTCPMSS; | |
109 clock_.AdvanceTime(one_ms_); | |
110 } | |
111 | |
112 void LoseNPackets(int n) { LoseNPackets(n, kDefaultTCPMSS); } | |
113 | |
114 void LoseNPackets(int n, QuicPacketLength packet_length) { | |
115 SendAlgorithmInterface::CongestionVector acked_packets; | |
116 SendAlgorithmInterface::CongestionVector lost_packets; | |
117 for (int i = 0; i < n; ++i) { | |
118 ++acked_packet_number_; | |
119 lost_packets.push_back( | |
120 std::make_pair(acked_packet_number_, packet_length)); | |
121 } | |
122 sender_->OnCongestionEvent(false, bytes_in_flight_, acked_packets, | |
123 lost_packets); | |
124 bytes_in_flight_ -= n * packet_length; | |
125 } | |
126 | |
127 // Does not increment acked_packet_number_. | |
128 void LosePacket(QuicPacketNumber packet_number) { | |
129 SendAlgorithmInterface::CongestionVector acked_packets; | |
130 SendAlgorithmInterface::CongestionVector lost_packets; | |
131 lost_packets.push_back(std::make_pair(packet_number, kDefaultTCPMSS)); | |
132 sender_->OnCongestionEvent(false, bytes_in_flight_, acked_packets, | |
133 lost_packets); | |
134 bytes_in_flight_ -= kDefaultTCPMSS; | |
135 } | |
136 | |
137 const QuicTime::Delta one_ms_; | |
138 MockClock clock_; | |
139 std::unique_ptr<TcpCubicSenderPacketsPeer> sender_; | |
140 QuicPacketNumber packet_number_; | |
141 QuicPacketNumber acked_packet_number_; | |
142 QuicByteCount bytes_in_flight_; | |
143 }; | |
144 | |
145 TEST_F(TcpCubicSenderPacketsTest, SimpleSender) { | |
146 // At startup make sure we are at the default. | |
147 EXPECT_EQ(kDefaultWindowTCP, sender_->GetCongestionWindow()); | |
148 // At startup make sure we can send. | |
149 EXPECT_TRUE(sender_->TimeUntilSend(clock_.Now(), 0).IsZero()); | |
150 // Make sure we can send. | |
151 EXPECT_TRUE(sender_->TimeUntilSend(clock_.Now(), 0).IsZero()); | |
152 // And that window is un-affected. | |
153 EXPECT_EQ(kDefaultWindowTCP, sender_->GetCongestionWindow()); | |
154 | |
155 // Fill the send window with data, then verify that we can't send. | |
156 SendAvailableSendWindow(); | |
157 EXPECT_FALSE( | |
158 sender_->TimeUntilSend(clock_.Now(), sender_->GetCongestionWindow()) | |
159 .IsZero()); | |
160 } | |
161 | |
162 TEST_F(TcpCubicSenderPacketsTest, 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(), 0).IsZero()); | |
167 // Make sure we can send. | |
168 EXPECT_TRUE(sender_->TimeUntilSend(clock_.Now(), 0).IsZero()); | |
169 | |
170 SendAvailableSendWindow(); | |
171 for (int i = 0; i < kNumberOfAcks; ++i) { | |
172 AckNPackets(2); | |
173 } | |
174 QuicByteCount bytes_to_send = sender_->GetCongestionWindow(); | |
175 // It's expected 2 acks will arrive when the bytes_in_flight are greater than | |
176 // half the CWND. | |
177 EXPECT_EQ(kDefaultWindowTCP + kDefaultTCPMSS * 2 * 2, bytes_to_send); | |
178 } | |
179 | |
180 TEST_F(TcpCubicSenderPacketsTest, ExponentialSlowStart) { | |
181 const int kNumberOfAcks = 20; | |
182 // At startup make sure we can send. | |
183 EXPECT_TRUE(sender_->TimeUntilSend(clock_.Now(), 0).IsZero()); | |
184 EXPECT_EQ(QuicBandwidth::Zero(), sender_->BandwidthEstimate()); | |
185 // Make sure we can send. | |
186 EXPECT_TRUE(sender_->TimeUntilSend(clock_.Now(), 0).IsZero()); | |
187 | |
188 for (int i = 0; i < kNumberOfAcks; ++i) { | |
189 // Send our full send window. | |
190 SendAvailableSendWindow(); | |
191 AckNPackets(2); | |
192 } | |
193 const QuicByteCount cwnd = sender_->GetCongestionWindow(); | |
194 EXPECT_EQ(kDefaultWindowTCP + kDefaultTCPMSS * 2 * kNumberOfAcks, cwnd); | |
195 EXPECT_EQ(QuicBandwidth::FromBytesAndTimeDelta( | |
196 cwnd, sender_->rtt_stats_.smoothed_rtt()), | |
197 sender_->BandwidthEstimate()); | |
198 } | |
199 | |
200 TEST_F(TcpCubicSenderPacketsTest, SlowStartPacketLoss) { | |
201 sender_->SetNumEmulatedConnections(1); | |
202 const int kNumberOfAcks = 10; | |
203 for (int i = 0; i < kNumberOfAcks; ++i) { | |
204 // Send our full send window. | |
205 SendAvailableSendWindow(); | |
206 AckNPackets(2); | |
207 } | |
208 SendAvailableSendWindow(); | |
209 QuicByteCount expected_send_window = | |
210 kDefaultWindowTCP + (kDefaultTCPMSS * 2 * kNumberOfAcks); | |
211 EXPECT_EQ(expected_send_window, sender_->GetCongestionWindow()); | |
212 | |
213 // Lose a packet to exit slow start. | |
214 LoseNPackets(1); | |
215 size_t packets_in_recovery_window = expected_send_window / kDefaultTCPMSS; | |
216 | |
217 // We should now have fallen out of slow start with a reduced window. | |
218 expected_send_window *= kRenoBeta; | |
219 EXPECT_EQ(expected_send_window, sender_->GetCongestionWindow()); | |
220 | |
221 // Recovery phase. We need to ack every packet in the recovery window before | |
222 // we exit recovery. | |
223 size_t number_of_packets_in_window = expected_send_window / kDefaultTCPMSS; | |
224 DVLOG(1) << "number_packets: " << number_of_packets_in_window; | |
225 AckNPackets(packets_in_recovery_window); | |
226 SendAvailableSendWindow(); | |
227 EXPECT_EQ(expected_send_window, sender_->GetCongestionWindow()); | |
228 | |
229 // We need to ack an entire window before we increase CWND by 1. | |
230 AckNPackets(number_of_packets_in_window - 2); | |
231 SendAvailableSendWindow(); | |
232 EXPECT_EQ(expected_send_window, sender_->GetCongestionWindow()); | |
233 | |
234 // Next ack should increase cwnd by 1. | |
235 AckNPackets(1); | |
236 expected_send_window += kDefaultTCPMSS; | |
237 EXPECT_EQ(expected_send_window, sender_->GetCongestionWindow()); | |
238 | |
239 // Now RTO and ensure slow start gets reset. | |
240 EXPECT_TRUE(sender_->hybrid_slow_start().started()); | |
241 sender_->OnRetransmissionTimeout(true); | |
242 EXPECT_FALSE(sender_->hybrid_slow_start().started()); | |
243 } | |
244 | |
245 TEST_F(TcpCubicSenderPacketsTest, SlowStartPacketLossWithLargeReduction) { | |
246 QuicConfig config; | |
247 QuicTagVector options; | |
248 options.push_back(kSSLR); | |
249 QuicConfigPeer::SetReceivedConnectionOptions(&config, options); | |
250 sender_->SetFromConfig(config, Perspective::IS_SERVER); | |
251 | |
252 sender_->SetNumEmulatedConnections(1); | |
253 const int kNumberOfAcks = (kDefaultWindowTCP / (2 * kDefaultTCPMSS)) - 1; | |
254 for (int i = 0; i < kNumberOfAcks; ++i) { | |
255 // Send our full send window. | |
256 SendAvailableSendWindow(); | |
257 AckNPackets(2); | |
258 } | |
259 SendAvailableSendWindow(); | |
260 QuicByteCount expected_send_window = | |
261 kDefaultWindowTCP + (kDefaultTCPMSS * 2 * kNumberOfAcks); | |
262 EXPECT_EQ(expected_send_window, sender_->GetCongestionWindow()); | |
263 | |
264 // Lose a packet to exit slow start. We should now have fallen out of | |
265 // slow start with a window reduced by 1. | |
266 LoseNPackets(1); | |
267 expected_send_window -= kDefaultTCPMSS; | |
268 EXPECT_EQ(expected_send_window, sender_->GetCongestionWindow()); | |
269 | |
270 // Lose 5 packets in recovery and verify that congestion window is reduced | |
271 // further. | |
272 LoseNPackets(5); | |
273 expected_send_window -= 5 * kDefaultTCPMSS; | |
274 EXPECT_EQ(expected_send_window, sender_->GetCongestionWindow()); | |
275 // Lose another 10 packets and ensure it reduces below half the peak CWND, | |
276 // because we never acked the full IW. | |
277 LoseNPackets(10); | |
278 expected_send_window -= 10 * kDefaultTCPMSS; | |
279 EXPECT_EQ(expected_send_window, sender_->GetCongestionWindow()); | |
280 | |
281 size_t packets_in_recovery_window = expected_send_window / kDefaultTCPMSS; | |
282 | |
283 // Recovery phase. We need to ack every packet in the recovery window before | |
284 // we exit recovery. | |
285 size_t number_of_packets_in_window = expected_send_window / kDefaultTCPMSS; | |
286 DVLOG(1) << "number_packets: " << number_of_packets_in_window; | |
287 AckNPackets(packets_in_recovery_window); | |
288 SendAvailableSendWindow(); | |
289 EXPECT_EQ(expected_send_window, sender_->GetCongestionWindow()); | |
290 | |
291 // We need to ack the rest of the window before cwnd increases by 1. | |
292 AckNPackets(number_of_packets_in_window - 1); | |
293 SendAvailableSendWindow(); | |
294 EXPECT_EQ(expected_send_window, sender_->GetCongestionWindow()); | |
295 | |
296 // Next ack should increase cwnd by 1. | |
297 AckNPackets(1); | |
298 expected_send_window += kDefaultTCPMSS; | |
299 EXPECT_EQ(expected_send_window, sender_->GetCongestionWindow()); | |
300 | |
301 // Now RTO and ensure slow start gets reset. | |
302 EXPECT_TRUE(sender_->hybrid_slow_start().started()); | |
303 sender_->OnRetransmissionTimeout(true); | |
304 EXPECT_FALSE(sender_->hybrid_slow_start().started()); | |
305 } | |
306 | |
307 TEST_F(TcpCubicSenderPacketsTest, SlowStartHalfPacketLossWithLargeReduction) { | |
308 QuicConfig config; | |
309 QuicTagVector options; | |
310 options.push_back(kSSLR); | |
311 QuicConfigPeer::SetReceivedConnectionOptions(&config, options); | |
312 sender_->SetFromConfig(config, Perspective::IS_SERVER); | |
313 | |
314 sender_->SetNumEmulatedConnections(1); | |
315 const int kNumberOfAcks = 10; | |
316 for (int i = 0; i < kNumberOfAcks; ++i) { | |
317 // Send our full send window in half sized packets. | |
318 SendAvailableSendWindow(kDefaultTCPMSS / 2); | |
319 AckNPackets(2); | |
320 } | |
321 SendAvailableSendWindow(kDefaultTCPMSS / 2); | |
322 QuicByteCount expected_send_window = | |
323 kDefaultWindowTCP + (kDefaultTCPMSS * 2 * kNumberOfAcks); | |
324 EXPECT_EQ(expected_send_window, sender_->GetCongestionWindow()); | |
325 | |
326 // Lose a packet to exit slow start. We should now have fallen out of | |
327 // slow start with a window reduced by 1. | |
328 LoseNPackets(1); | |
329 expected_send_window -= kDefaultTCPMSS; | |
330 EXPECT_EQ(expected_send_window, sender_->GetCongestionWindow()); | |
331 | |
332 // Lose 10 packets in recovery and verify that congestion window is reduced | |
333 // by 5 packets. | |
334 LoseNPackets(10, kDefaultTCPMSS / 2); | |
335 expected_send_window -= 5 * kDefaultTCPMSS; | |
336 EXPECT_EQ(expected_send_window, sender_->GetCongestionWindow()); | |
337 } | |
338 | |
339 TEST_F(TcpCubicSenderPacketsTest, SlowStartPacketLossWithMaxHalfReduction) { | |
340 QuicConfig config; | |
341 QuicTagVector options; | |
342 options.push_back(kSSLR); | |
343 QuicConfigPeer::SetReceivedConnectionOptions(&config, options); | |
344 sender_->SetFromConfig(config, Perspective::IS_SERVER); | |
345 | |
346 sender_->SetNumEmulatedConnections(1); | |
347 const int kNumberOfAcks = kInitialCongestionWindowPackets / 2; | |
348 for (int i = 0; i < kNumberOfAcks; ++i) { | |
349 // Send our full send window. | |
350 SendAvailableSendWindow(); | |
351 AckNPackets(2); | |
352 } | |
353 SendAvailableSendWindow(); | |
354 QuicByteCount expected_send_window = | |
355 kDefaultWindowTCP + (kDefaultTCPMSS * 2 * kNumberOfAcks); | |
356 EXPECT_EQ(expected_send_window, sender_->GetCongestionWindow()); | |
357 | |
358 // Lose a packet to exit slow start. We should now have fallen out of | |
359 // slow start with a window reduced by 1. | |
360 LoseNPackets(1); | |
361 expected_send_window -= kDefaultTCPMSS; | |
362 EXPECT_EQ(expected_send_window, sender_->GetCongestionWindow()); | |
363 | |
364 // Lose half the outstanding packets in recovery and verify the congestion | |
365 // window is only reduced by a max of half. | |
366 LoseNPackets(kNumberOfAcks * 2); | |
367 expected_send_window -= (kNumberOfAcks * 2 - 1) * kDefaultTCPMSS; | |
368 EXPECT_EQ(expected_send_window, sender_->GetCongestionWindow()); | |
369 LoseNPackets(5); | |
370 EXPECT_EQ(expected_send_window, sender_->GetCongestionWindow()); | |
371 } | |
372 | |
373 TEST_F(TcpCubicSenderPacketsTest, NoPRRWhenLessThanOnePacketInFlight) { | |
374 SendAvailableSendWindow(); | |
375 LoseNPackets(kInitialCongestionWindowPackets - 1); | |
376 AckNPackets(1); | |
377 // PRR will allow 2 packets for every ack during recovery. | |
378 EXPECT_EQ(2, SendAvailableSendWindow()); | |
379 // Simulate abandoning all packets by supplying a bytes_in_flight of 0. | |
380 // PRR should now allow a packet to be sent, even though prr's state | |
381 // variables believe it has sent enough packets. | |
382 EXPECT_EQ(QuicTime::Delta::Zero(), sender_->TimeUntilSend(clock_.Now(), 0)); | |
383 } | |
384 | |
385 TEST_F(TcpCubicSenderPacketsTest, SlowStartPacketLossPRR) { | |
386 sender_->SetNumEmulatedConnections(1); | |
387 // Test based on the first example in RFC6937. | |
388 // Ack 10 packets in 5 acks to raise the CWND to 20, as in the example. | |
389 const int kNumberOfAcks = 5; | |
390 for (int i = 0; i < kNumberOfAcks; ++i) { | |
391 // Send our full send window. | |
392 SendAvailableSendWindow(); | |
393 AckNPackets(2); | |
394 } | |
395 SendAvailableSendWindow(); | |
396 QuicByteCount expected_send_window = | |
397 kDefaultWindowTCP + (kDefaultTCPMSS * 2 * kNumberOfAcks); | |
398 EXPECT_EQ(expected_send_window, sender_->GetCongestionWindow()); | |
399 | |
400 LoseNPackets(1); | |
401 | |
402 // We should now have fallen out of slow start with a reduced window. | |
403 size_t send_window_before_loss = expected_send_window; | |
404 expected_send_window *= kRenoBeta; | |
405 EXPECT_EQ(expected_send_window, sender_->GetCongestionWindow()); | |
406 | |
407 // Testing TCP proportional rate reduction. | |
408 // We should send packets paced over the received acks for the remaining | |
409 // outstanding packets. The number of packets before we exit recovery is the | |
410 // original CWND minus the packet that has been lost and the one which | |
411 // triggered the loss. | |
412 size_t remaining_packets_in_recovery = | |
413 send_window_before_loss / kDefaultTCPMSS - 2; | |
414 | |
415 for (size_t i = 0; i < remaining_packets_in_recovery; ++i) { | |
416 AckNPackets(1); | |
417 SendAvailableSendWindow(); | |
418 EXPECT_EQ(expected_send_window, sender_->GetCongestionWindow()); | |
419 } | |
420 | |
421 // We need to ack another window before we increase CWND by 1. | |
422 size_t number_of_packets_in_window = expected_send_window / kDefaultTCPMSS; | |
423 for (size_t i = 0; i < number_of_packets_in_window; ++i) { | |
424 AckNPackets(1); | |
425 EXPECT_EQ(1, SendAvailableSendWindow()); | |
426 EXPECT_EQ(expected_send_window, sender_->GetCongestionWindow()); | |
427 } | |
428 | |
429 AckNPackets(1); | |
430 expected_send_window += kDefaultTCPMSS; | |
431 EXPECT_EQ(expected_send_window, sender_->GetCongestionWindow()); | |
432 } | |
433 | |
434 TEST_F(TcpCubicSenderPacketsTest, SlowStartBurstPacketLossPRR) { | |
435 sender_->SetNumEmulatedConnections(1); | |
436 // Test based on the second example in RFC6937, though we also implement | |
437 // forward acknowledgements, so the first two incoming acks will trigger | |
438 // PRR immediately. | |
439 // Ack 20 packets in 10 acks to raise the CWND to 30. | |
440 const int kNumberOfAcks = 10; | |
441 for (int i = 0; i < kNumberOfAcks; ++i) { | |
442 // Send our full send window. | |
443 SendAvailableSendWindow(); | |
444 AckNPackets(2); | |
445 } | |
446 SendAvailableSendWindow(); | |
447 QuicByteCount expected_send_window = | |
448 kDefaultWindowTCP + (kDefaultTCPMSS * 2 * kNumberOfAcks); | |
449 EXPECT_EQ(expected_send_window, sender_->GetCongestionWindow()); | |
450 | |
451 // Lose one more than the congestion window reduction, so that after loss, | |
452 // bytes_in_flight is lesser than the congestion window. | |
453 size_t send_window_after_loss = kRenoBeta * expected_send_window; | |
454 size_t num_packets_to_lose = | |
455 (expected_send_window - send_window_after_loss) / kDefaultTCPMSS + 1; | |
456 LoseNPackets(num_packets_to_lose); | |
457 // Immediately after the loss, ensure at least one packet can be sent. | |
458 // Losses without subsequent acks can occur with timer based loss detection. | |
459 EXPECT_TRUE(sender_->TimeUntilSend(clock_.Now(), bytes_in_flight_).IsZero()); | |
460 AckNPackets(1); | |
461 | |
462 // We should now have fallen out of slow start with a reduced window. | |
463 expected_send_window *= kRenoBeta; | |
464 EXPECT_EQ(expected_send_window, sender_->GetCongestionWindow()); | |
465 | |
466 // Only 2 packets should be allowed to be sent, per PRR-SSRB | |
467 EXPECT_EQ(2, SendAvailableSendWindow()); | |
468 | |
469 // Ack the next packet, which triggers another loss. | |
470 LoseNPackets(1); | |
471 AckNPackets(1); | |
472 | |
473 // Send 2 packets to simulate PRR-SSRB. | |
474 EXPECT_EQ(2, SendAvailableSendWindow()); | |
475 | |
476 // Ack the next packet, which triggers another loss. | |
477 LoseNPackets(1); | |
478 AckNPackets(1); | |
479 | |
480 // Send 2 packets to simulate PRR-SSRB. | |
481 EXPECT_EQ(2, SendAvailableSendWindow()); | |
482 | |
483 // Exit recovery and return to sending at the new rate. | |
484 for (int i = 0; i < kNumberOfAcks; ++i) { | |
485 AckNPackets(1); | |
486 EXPECT_EQ(1, SendAvailableSendWindow()); | |
487 } | |
488 } | |
489 | |
490 TEST_F(TcpCubicSenderPacketsTest, RTOCongestionWindow) { | |
491 EXPECT_EQ(kDefaultWindowTCP, sender_->GetCongestionWindow()); | |
492 EXPECT_EQ(kMaxCongestionWindowPackets, sender_->slowstart_threshold()); | |
493 | |
494 // Expect the window to decrease to the minimum once the RTO fires | |
495 // and slow start threshold to be set to 1/2 of the CWND. | |
496 sender_->OnRetransmissionTimeout(true); | |
497 EXPECT_EQ(2 * kDefaultTCPMSS, sender_->GetCongestionWindow()); | |
498 EXPECT_EQ(5u, sender_->slowstart_threshold()); | |
499 } | |
500 | |
501 TEST_F(TcpCubicSenderPacketsTest, RTOCongestionWindowNoRetransmission) { | |
502 EXPECT_EQ(kDefaultWindowTCP, sender_->GetCongestionWindow()); | |
503 | |
504 // Expect the window to remain unchanged if the RTO fires but no | |
505 // packets are retransmitted. | |
506 sender_->OnRetransmissionTimeout(false); | |
507 EXPECT_EQ(kDefaultWindowTCP, sender_->GetCongestionWindow()); | |
508 } | |
509 | |
510 TEST_F(TcpCubicSenderPacketsTest, RetransmissionDelay) { | |
511 const int64_t kRttMs = 10; | |
512 const int64_t kDeviationMs = 3; | |
513 EXPECT_EQ(QuicTime::Delta::Zero(), sender_->RetransmissionDelay()); | |
514 | |
515 sender_->rtt_stats_.UpdateRtt(QuicTime::Delta::FromMilliseconds(kRttMs), | |
516 QuicTime::Delta::Zero(), clock_.Now()); | |
517 | |
518 // Initial value is to set the median deviation to half of the initial | |
519 // rtt, the median in then multiplied by a factor of 4 and finally the | |
520 // smoothed rtt is added which is the initial rtt. | |
521 QuicTime::Delta expected_delay = | |
522 QuicTime::Delta::FromMilliseconds(kRttMs + kRttMs / 2 * 4); | |
523 EXPECT_EQ(expected_delay, sender_->RetransmissionDelay()); | |
524 | |
525 for (int i = 0; i < 100; ++i) { | |
526 // Run to make sure that we converge. | |
527 sender_->rtt_stats_.UpdateRtt( | |
528 QuicTime::Delta::FromMilliseconds(kRttMs + kDeviationMs), | |
529 QuicTime::Delta::Zero(), clock_.Now()); | |
530 sender_->rtt_stats_.UpdateRtt( | |
531 QuicTime::Delta::FromMilliseconds(kRttMs - kDeviationMs), | |
532 QuicTime::Delta::Zero(), clock_.Now()); | |
533 } | |
534 expected_delay = QuicTime::Delta::FromMilliseconds(kRttMs + kDeviationMs * 4); | |
535 | |
536 EXPECT_NEAR(kRttMs, sender_->rtt_stats_.smoothed_rtt().ToMilliseconds(), 1); | |
537 EXPECT_NEAR(expected_delay.ToMilliseconds(), | |
538 sender_->RetransmissionDelay().ToMilliseconds(), 1); | |
539 EXPECT_EQ(static_cast<int64_t>( | |
540 sender_->GetCongestionWindow() * kNumMicrosPerSecond / | |
541 sender_->rtt_stats_.smoothed_rtt().ToMicroseconds()), | |
542 sender_->BandwidthEstimate().ToBytesPerSecond()); | |
543 } | |
544 | |
545 TEST_F(TcpCubicSenderPacketsTest, SlowStartMaxSendWindow) { | |
546 const QuicPacketCount kMaxCongestionWindowTCP = 50; | |
547 const int kNumberOfAcks = 100; | |
548 sender_.reset( | |
549 new TcpCubicSenderPacketsPeer(&clock_, false, kMaxCongestionWindowTCP)); | |
550 | |
551 for (int i = 0; i < kNumberOfAcks; ++i) { | |
552 // Send our full send window. | |
553 SendAvailableSendWindow(); | |
554 AckNPackets(2); | |
555 } | |
556 QuicByteCount expected_send_window = kMaxCongestionWindowTCP * kDefaultTCPMSS; | |
557 EXPECT_EQ(expected_send_window, sender_->GetCongestionWindow()); | |
558 } | |
559 | |
560 TEST_F(TcpCubicSenderPacketsTest, TcpRenoMaxCongestionWindow) { | |
561 const QuicPacketCount kMaxCongestionWindowTCP = 50; | |
562 const int kNumberOfAcks = 1000; | |
563 sender_.reset( | |
564 new TcpCubicSenderPacketsPeer(&clock_, true, kMaxCongestionWindowTCP)); | |
565 | |
566 SendAvailableSendWindow(); | |
567 AckNPackets(2); | |
568 // Make sure we fall out of slow start. | |
569 LoseNPackets(1); | |
570 | |
571 for (int i = 0; i < kNumberOfAcks; ++i) { | |
572 // Send our full send window. | |
573 SendAvailableSendWindow(); | |
574 AckNPackets(2); | |
575 } | |
576 | |
577 QuicByteCount expected_send_window = kMaxCongestionWindowTCP * kDefaultTCPMSS; | |
578 EXPECT_EQ(expected_send_window, sender_->GetCongestionWindow()); | |
579 } | |
580 | |
581 TEST_F(TcpCubicSenderPacketsTest, TcpCubicMaxCongestionWindow) { | |
582 const QuicPacketCount kMaxCongestionWindowTCP = 50; | |
583 // Set to 10000 to compensate for small cubic alpha. | |
584 const int kNumberOfAcks = 10000; | |
585 | |
586 sender_.reset( | |
587 new TcpCubicSenderPacketsPeer(&clock_, false, kMaxCongestionWindowTCP)); | |
588 | |
589 SendAvailableSendWindow(); | |
590 AckNPackets(2); | |
591 // Make sure we fall out of slow start. | |
592 LoseNPackets(1); | |
593 | |
594 for (int i = 0; i < kNumberOfAcks; ++i) { | |
595 // Send our full send window. | |
596 SendAvailableSendWindow(); | |
597 AckNPackets(2); | |
598 } | |
599 | |
600 QuicByteCount expected_send_window = kMaxCongestionWindowTCP * kDefaultTCPMSS; | |
601 EXPECT_EQ(expected_send_window, sender_->GetCongestionWindow()); | |
602 } | |
603 | |
604 TEST_F(TcpCubicSenderPacketsTest, TcpCubicResetEpochOnQuiescence) { | |
605 const int kMaxCongestionWindow = 50; | |
606 const QuicByteCount kMaxCongestionWindowBytes = | |
607 kMaxCongestionWindow * kDefaultTCPMSS; | |
608 sender_.reset( | |
609 new TcpCubicSenderPacketsPeer(&clock_, false, kMaxCongestionWindow)); | |
610 | |
611 int num_sent = SendAvailableSendWindow(); | |
612 | |
613 // Make sure we fall out of slow start. | |
614 QuicByteCount saved_cwnd = sender_->GetCongestionWindow(); | |
615 LoseNPackets(1); | |
616 EXPECT_GT(saved_cwnd, sender_->GetCongestionWindow()); | |
617 | |
618 // Ack the rest of the outstanding packets to get out of recovery. | |
619 for (int i = 1; i < num_sent; ++i) { | |
620 AckNPackets(1); | |
621 } | |
622 EXPECT_EQ(0u, bytes_in_flight_); | |
623 | |
624 // Send a new window of data and ack all; cubic growth should occur. | |
625 saved_cwnd = sender_->GetCongestionWindow(); | |
626 num_sent = SendAvailableSendWindow(); | |
627 for (int i = 0; i < num_sent; ++i) { | |
628 AckNPackets(1); | |
629 } | |
630 EXPECT_LT(saved_cwnd, sender_->GetCongestionWindow()); | |
631 EXPECT_GT(kMaxCongestionWindowBytes, sender_->GetCongestionWindow()); | |
632 EXPECT_EQ(0u, bytes_in_flight_); | |
633 | |
634 // Quiescent time of 100 seconds | |
635 clock_.AdvanceTime(QuicTime::Delta::FromMilliseconds(100000)); | |
636 | |
637 // Send new window of data and ack one packet. Cubic epoch should have | |
638 // been reset; ensure cwnd increase is not dramatic. | |
639 saved_cwnd = sender_->GetCongestionWindow(); | |
640 SendAvailableSendWindow(); | |
641 AckNPackets(1); | |
642 EXPECT_NEAR(saved_cwnd, sender_->GetCongestionWindow(), kDefaultTCPMSS); | |
643 EXPECT_GT(kMaxCongestionWindowBytes, sender_->GetCongestionWindow()); | |
644 } | |
645 | |
646 TEST_F(TcpCubicSenderPacketsTest, TcpCubicShiftedEpochOnQuiescence) { | |
647 ValueRestore<bool> old_flag(&FLAGS_shift_quic_cubic_epoch_when_app_limited, | |
648 true); | |
649 const int kMaxCongestionWindow = 50; | |
650 const QuicByteCount kMaxCongestionWindowBytes = | |
651 kMaxCongestionWindow * kDefaultTCPMSS; | |
652 sender_.reset( | |
653 new TcpCubicSenderPacketsPeer(&clock_, false, kMaxCongestionWindow)); | |
654 | |
655 int num_sent = SendAvailableSendWindow(); | |
656 | |
657 // Make sure we fall out of slow start. | |
658 QuicByteCount saved_cwnd = sender_->GetCongestionWindow(); | |
659 LoseNPackets(1); | |
660 EXPECT_GT(saved_cwnd, sender_->GetCongestionWindow()); | |
661 | |
662 // Ack the rest of the outstanding packets to get out of recovery. | |
663 for (int i = 1; i < num_sent; ++i) { | |
664 AckNPackets(1); | |
665 } | |
666 EXPECT_EQ(0u, bytes_in_flight_); | |
667 | |
668 // Send a new window of data and ack all; cubic growth should occur. | |
669 saved_cwnd = sender_->GetCongestionWindow(); | |
670 num_sent = SendAvailableSendWindow(); | |
671 for (int i = 0; i < num_sent; ++i) { | |
672 AckNPackets(1); | |
673 } | |
674 EXPECT_LT(saved_cwnd, sender_->GetCongestionWindow()); | |
675 EXPECT_GT(kMaxCongestionWindowBytes, sender_->GetCongestionWindow()); | |
676 EXPECT_EQ(0u, bytes_in_flight_); | |
677 | |
678 // Quiescent time of 100 seconds | |
679 clock_.AdvanceTime(QuicTime::Delta::FromSeconds(100)); | |
680 | |
681 // Send new window of data and ack one packet. Cubic epoch should have | |
682 // been reset; ensure cwnd increase is not dramatic. | |
683 saved_cwnd = sender_->GetCongestionWindow(); | |
684 SendAvailableSendWindow(); | |
685 AckNPackets(1); | |
686 EXPECT_NEAR(saved_cwnd, sender_->GetCongestionWindow(), kDefaultTCPMSS); | |
687 EXPECT_GT(kMaxCongestionWindowBytes, sender_->GetCongestionWindow()); | |
688 } | |
689 | |
690 TEST_F(TcpCubicSenderPacketsTest, MultipleLossesInOneWindow) { | |
691 SendAvailableSendWindow(); | |
692 const QuicByteCount initial_window = sender_->GetCongestionWindow(); | |
693 LosePacket(acked_packet_number_ + 1); | |
694 const QuicByteCount post_loss_window = sender_->GetCongestionWindow(); | |
695 EXPECT_GT(initial_window, post_loss_window); | |
696 LosePacket(acked_packet_number_ + 3); | |
697 EXPECT_EQ(post_loss_window, sender_->GetCongestionWindow()); | |
698 LosePacket(packet_number_ - 1); | |
699 EXPECT_EQ(post_loss_window, sender_->GetCongestionWindow()); | |
700 | |
701 // Lose a later packet and ensure the window decreases. | |
702 LosePacket(packet_number_); | |
703 EXPECT_GT(post_loss_window, sender_->GetCongestionWindow()); | |
704 } | |
705 | |
706 TEST_F(TcpCubicSenderPacketsTest, DontTrackAckPackets) { | |
707 // Send a packet with no retransmittable data, and ensure it's not tracked. | |
708 EXPECT_FALSE(sender_->OnPacketSent(clock_.Now(), bytes_in_flight_, | |
709 packet_number_++, kDefaultTCPMSS, | |
710 NO_RETRANSMITTABLE_DATA)); | |
711 | |
712 // Send a data packet with retransmittable data, and ensure it is tracked. | |
713 EXPECT_TRUE(sender_->OnPacketSent(clock_.Now(), bytes_in_flight_, | |
714 packet_number_++, kDefaultTCPMSS, | |
715 HAS_RETRANSMITTABLE_DATA)); | |
716 } | |
717 | |
718 TEST_F(TcpCubicSenderPacketsTest, ConfigureInitialWindow) { | |
719 QuicConfig config; | |
720 | |
721 QuicTagVector options; | |
722 options.push_back(kIW03); | |
723 QuicConfigPeer::SetReceivedConnectionOptions(&config, options); | |
724 sender_->SetFromConfig(config, Perspective::IS_SERVER); | |
725 EXPECT_EQ(3u, sender_->congestion_window()); | |
726 | |
727 options.clear(); | |
728 options.push_back(kIW10); | |
729 QuicConfigPeer::SetReceivedConnectionOptions(&config, options); | |
730 sender_->SetFromConfig(config, Perspective::IS_SERVER); | |
731 EXPECT_EQ(10u, sender_->congestion_window()); | |
732 | |
733 options.clear(); | |
734 options.push_back(kIW20); | |
735 QuicConfigPeer::SetReceivedConnectionOptions(&config, options); | |
736 sender_->SetFromConfig(config, Perspective::IS_SERVER); | |
737 EXPECT_EQ(20u, sender_->congestion_window()); | |
738 | |
739 options.clear(); | |
740 options.push_back(kIW50); | |
741 QuicConfigPeer::SetReceivedConnectionOptions(&config, options); | |
742 sender_->SetFromConfig(config, Perspective::IS_SERVER); | |
743 EXPECT_EQ(50u, sender_->congestion_window()); | |
744 } | |
745 | |
746 TEST_F(TcpCubicSenderPacketsTest, ConfigureMinimumWindow) { | |
747 QuicConfig config; | |
748 | |
749 // Verify that kCOPT: kMIN1 forces the min CWND to 1 packet. | |
750 QuicTagVector options; | |
751 options.push_back(kMIN1); | |
752 QuicConfigPeer::SetReceivedConnectionOptions(&config, options); | |
753 sender_->SetFromConfig(config, Perspective::IS_SERVER); | |
754 sender_->OnRetransmissionTimeout(true); | |
755 EXPECT_EQ(1u, sender_->congestion_window()); | |
756 } | |
757 | |
758 TEST_F(TcpCubicSenderPacketsTest, | |
759 2ConnectionCongestionAvoidanceAtEndOfRecovery) { | |
760 sender_->SetNumEmulatedConnections(2); | |
761 // Ack 10 packets in 5 acks to raise the CWND to 20. | |
762 const int kNumberOfAcks = 5; | |
763 for (int i = 0; i < kNumberOfAcks; ++i) { | |
764 // Send our full send window. | |
765 SendAvailableSendWindow(); | |
766 AckNPackets(2); | |
767 } | |
768 SendAvailableSendWindow(); | |
769 QuicByteCount expected_send_window = | |
770 kDefaultWindowTCP + (kDefaultTCPMSS * 2 * kNumberOfAcks); | |
771 EXPECT_EQ(expected_send_window, sender_->GetCongestionWindow()); | |
772 | |
773 LoseNPackets(1); | |
774 | |
775 // We should now have fallen out of slow start with a reduced window. | |
776 expected_send_window = expected_send_window * sender_->GetRenoBeta(); | |
777 EXPECT_EQ(expected_send_window, sender_->GetCongestionWindow()); | |
778 | |
779 // No congestion window growth should occur in recovery phase, i.e., until the | |
780 // currently outstanding 20 packets are acked. | |
781 for (int i = 0; i < 10; ++i) { | |
782 // Send our full send window. | |
783 SendAvailableSendWindow(); | |
784 EXPECT_TRUE(sender_->InRecovery()); | |
785 AckNPackets(2); | |
786 EXPECT_EQ(expected_send_window, sender_->GetCongestionWindow()); | |
787 } | |
788 EXPECT_FALSE(sender_->InRecovery()); | |
789 | |
790 // Out of recovery now. Congestion window should not grow for half an RTT. | |
791 size_t packets_in_send_window = expected_send_window / kDefaultTCPMSS; | |
792 SendAvailableSendWindow(); | |
793 AckNPackets(packets_in_send_window / 2 - 2); | |
794 EXPECT_EQ(expected_send_window, sender_->GetCongestionWindow()); | |
795 | |
796 // Next ack should increase congestion window by 1MSS. | |
797 SendAvailableSendWindow(); | |
798 AckNPackets(2); | |
799 expected_send_window += kDefaultTCPMSS; | |
800 packets_in_send_window += 1; | |
801 EXPECT_EQ(expected_send_window, sender_->GetCongestionWindow()); | |
802 | |
803 // Congestion window should remain steady again for half an RTT. | |
804 SendAvailableSendWindow(); | |
805 AckNPackets(packets_in_send_window / 2 - 1); | |
806 EXPECT_EQ(expected_send_window, sender_->GetCongestionWindow()); | |
807 | |
808 // Next ack should cause congestion window to grow by 1MSS. | |
809 SendAvailableSendWindow(); | |
810 AckNPackets(2); | |
811 expected_send_window += kDefaultTCPMSS; | |
812 EXPECT_EQ(expected_send_window, sender_->GetCongestionWindow()); | |
813 } | |
814 | |
815 TEST_F(TcpCubicSenderPacketsTest, | |
816 1ConnectionCongestionAvoidanceAtEndOfRecovery) { | |
817 sender_->SetNumEmulatedConnections(1); | |
818 // Ack 10 packets in 5 acks to raise the CWND to 20. | |
819 const int kNumberOfAcks = 5; | |
820 for (int i = 0; i < kNumberOfAcks; ++i) { | |
821 // Send our full send window. | |
822 SendAvailableSendWindow(); | |
823 AckNPackets(2); | |
824 } | |
825 SendAvailableSendWindow(); | |
826 QuicByteCount expected_send_window = | |
827 kDefaultWindowTCP + (kDefaultTCPMSS * 2 * kNumberOfAcks); | |
828 EXPECT_EQ(expected_send_window, sender_->GetCongestionWindow()); | |
829 | |
830 LoseNPackets(1); | |
831 | |
832 // We should now have fallen out of slow start with a reduced window. | |
833 expected_send_window *= kRenoBeta; | |
834 EXPECT_EQ(expected_send_window, sender_->GetCongestionWindow()); | |
835 | |
836 // No congestion window growth should occur in recovery phase, i.e., until the | |
837 // currently outstanding 20 packets are acked. | |
838 for (int i = 0; i < 10; ++i) { | |
839 // Send our full send window. | |
840 SendAvailableSendWindow(); | |
841 EXPECT_TRUE(sender_->InRecovery()); | |
842 AckNPackets(2); | |
843 EXPECT_EQ(expected_send_window, sender_->GetCongestionWindow()); | |
844 } | |
845 EXPECT_FALSE(sender_->InRecovery()); | |
846 | |
847 // Out of recovery now. Congestion window should not grow during RTT. | |
848 for (uint64_t i = 0; i < expected_send_window / kDefaultTCPMSS - 2; i += 2) { | |
849 // Send our full send window. | |
850 SendAvailableSendWindow(); | |
851 AckNPackets(2); | |
852 EXPECT_EQ(expected_send_window, sender_->GetCongestionWindow()); | |
853 } | |
854 | |
855 // Next ack should cause congestion window to grow by 1MSS. | |
856 SendAvailableSendWindow(); | |
857 AckNPackets(2); | |
858 expected_send_window += kDefaultTCPMSS; | |
859 EXPECT_EQ(expected_send_window, sender_->GetCongestionWindow()); | |
860 } | |
861 | |
862 TEST_F(TcpCubicSenderPacketsTest, BandwidthResumption) { | |
863 // Test that when provided with CachedNetworkParameters and opted in to the | |
864 // bandwidth resumption experiment, that the TcpCubicSenderPackets sets | |
865 // initial CWND appropriately. | |
866 | |
867 // Set some common values. | |
868 CachedNetworkParameters cached_network_params; | |
869 const QuicPacketCount kNumberOfPackets = 123; | |
870 const int kBandwidthEstimateBytesPerSecond = | |
871 kNumberOfPackets * kDefaultTCPMSS; | |
872 cached_network_params.set_bandwidth_estimate_bytes_per_second( | |
873 kBandwidthEstimateBytesPerSecond); | |
874 cached_network_params.set_min_rtt_ms(1000); | |
875 | |
876 // Make sure that a bandwidth estimate results in a changed CWND. | |
877 cached_network_params.set_timestamp(clock_.WallNow().ToUNIXSeconds() - | |
878 (kNumSecondsPerHour - 1)); | |
879 sender_->ResumeConnectionState(cached_network_params, false); | |
880 EXPECT_EQ(kNumberOfPackets, sender_->congestion_window()); | |
881 | |
882 // Resumed CWND is limited to be in a sensible range. | |
883 cached_network_params.set_bandwidth_estimate_bytes_per_second( | |
884 (kMaxCongestionWindowPackets + 1) * kDefaultTCPMSS); | |
885 sender_->ResumeConnectionState(cached_network_params, false); | |
886 EXPECT_EQ(kMaxCongestionWindowPackets, sender_->congestion_window()); | |
887 | |
888 if (FLAGS_quic_no_lower_bw_resumption_limit) { | |
889 // Resume with an illegal value of 0 and verify the server uses 1 instead. | |
890 cached_network_params.set_bandwidth_estimate_bytes_per_second(0); | |
891 sender_->ResumeConnectionState(cached_network_params, false); | |
892 EXPECT_EQ(sender_->min_congestion_window(), sender_->congestion_window()); | |
893 } else { | |
894 cached_network_params.set_bandwidth_estimate_bytes_per_second( | |
895 (kMinCongestionWindowForBandwidthResumption - 1) * kDefaultTCPMSS); | |
896 sender_->ResumeConnectionState(cached_network_params, false); | |
897 EXPECT_EQ(kMinCongestionWindowForBandwidthResumption, | |
898 sender_->congestion_window()); | |
899 } | |
900 | |
901 // Resume to the max value. | |
902 cached_network_params.set_max_bandwidth_estimate_bytes_per_second( | |
903 kMaxCongestionWindowPackets * kDefaultTCPMSS); | |
904 sender_->ResumeConnectionState(cached_network_params, true); | |
905 EXPECT_EQ(kMaxCongestionWindowPackets * kDefaultTCPMSS, | |
906 sender_->GetCongestionWindow()); | |
907 } | |
908 | |
909 TEST_F(TcpCubicSenderPacketsTest, PaceBelowCWND) { | |
910 QuicConfig config; | |
911 | |
912 // Verify that kCOPT: kMIN4 forces the min CWND to 1 packet, but allows up | |
913 // to 4 to be sent. | |
914 QuicTagVector options; | |
915 options.push_back(kMIN4); | |
916 QuicConfigPeer::SetReceivedConnectionOptions(&config, options); | |
917 sender_->SetFromConfig(config, Perspective::IS_SERVER); | |
918 sender_->OnRetransmissionTimeout(true); | |
919 EXPECT_EQ(1u, sender_->congestion_window()); | |
920 EXPECT_TRUE( | |
921 sender_->TimeUntilSend(QuicTime::Zero(), kDefaultTCPMSS).IsZero()); | |
922 EXPECT_TRUE( | |
923 sender_->TimeUntilSend(QuicTime::Zero(), 2 * kDefaultTCPMSS).IsZero()); | |
924 EXPECT_TRUE( | |
925 sender_->TimeUntilSend(QuicTime::Zero(), 3 * kDefaultTCPMSS).IsZero()); | |
926 EXPECT_FALSE( | |
927 sender_->TimeUntilSend(QuicTime::Zero(), 4 * kDefaultTCPMSS).IsZero()); | |
928 } | |
929 | |
930 TEST_F(TcpCubicSenderPacketsTest, NoPRR) { | |
931 QuicTime::Delta rtt = QuicTime::Delta::FromMilliseconds(100); | |
932 sender_->rtt_stats_.UpdateRtt(rtt, QuicTime::Delta::Zero(), QuicTime::Zero()); | |
933 | |
934 sender_->SetNumEmulatedConnections(1); | |
935 // Verify that kCOPT: kNPRR allows all packets to be sent, even if only one | |
936 // ack has been received. | |
937 QuicTagVector options; | |
938 options.push_back(kNPRR); | |
939 QuicConfig config; | |
940 QuicConfigPeer::SetReceivedConnectionOptions(&config, options); | |
941 sender_->SetFromConfig(config, Perspective::IS_SERVER); | |
942 SendAvailableSendWindow(); | |
943 LoseNPackets(9); | |
944 AckNPackets(1); | |
945 | |
946 // We should now have fallen out of slow start with a reduced window. | |
947 EXPECT_EQ(kRenoBeta * kDefaultWindowTCP, sender_->GetCongestionWindow()); | |
948 const QuicPacketCount window_in_packets = | |
949 kRenoBeta * kDefaultWindowTCP / kDefaultTCPMSS; | |
950 const QuicBandwidth expected_pacing_rate = | |
951 QuicBandwidth::FromBytesAndTimeDelta(kRenoBeta * kDefaultWindowTCP, | |
952 sender_->rtt_stats_.smoothed_rtt()); | |
953 EXPECT_EQ(expected_pacing_rate, sender_->PacingRate(0)); | |
954 EXPECT_EQ(window_in_packets, | |
955 static_cast<uint64_t>(SendAvailableSendWindow())); | |
956 EXPECT_EQ(expected_pacing_rate, | |
957 sender_->PacingRate(kRenoBeta * kDefaultWindowTCP)); | |
958 } | |
959 | |
960 TEST_F(TcpCubicSenderPacketsTest, PaceSlowerAboveCwnd) { | |
961 ValueRestore<bool> old_flag(&FLAGS_quic_rate_based_sending, true); | |
962 QuicTime::Delta rtt(QuicTime::Delta::FromMilliseconds(60)); | |
963 sender_->rtt_stats_.UpdateRtt(rtt, QuicTime::Delta::Zero(), clock_.Now()); | |
964 | |
965 QuicConfig config; | |
966 QuicTagVector options; | |
967 options.push_back(kRATE); | |
968 QuicConfigPeer::SetReceivedConnectionOptions(&config, options); | |
969 sender_->SetFromConfig(config, Perspective::IS_SERVER); | |
970 EXPECT_EQ(10u, sender_->congestion_window()); | |
971 sender_->SetNumEmulatedConnections(1); | |
972 // Lose a packet to exit slow start. | |
973 LoseNPackets(1); | |
974 const QuicPacketCount cwnd = 7; | |
975 EXPECT_EQ(cwnd * kDefaultTCPMSS, sender_->GetCongestionWindow()); | |
976 | |
977 EXPECT_TRUE( | |
978 sender_->TimeUntilSend(QuicTime::Zero(), kDefaultTCPMSS).IsZero()); | |
979 EXPECT_EQ( | |
980 sender_->PacingRate(kDefaultTCPMSS), | |
981 QuicBandwidth::FromBytesAndTimeDelta(7 * kDefaultTCPMSS, rtt) * 1.25); | |
982 for (QuicPacketCount i = cwnd + 1; i < 1.5 * cwnd; ++i) { | |
983 EXPECT_TRUE( | |
984 sender_->TimeUntilSend(QuicTime::Zero(), i * kDefaultTCPMSS).IsZero()); | |
985 EXPECT_EQ(sender_->PacingRate(i * kDefaultTCPMSS), | |
986 QuicBandwidth::FromBytesAndTimeDelta(cwnd * kDefaultTCPMSS, rtt) * | |
987 0.75); | |
988 } | |
989 EXPECT_FALSE( | |
990 sender_->TimeUntilSend(QuicTime::Zero(), 11 * kDefaultTCPMSS).IsZero()); | |
991 } | |
992 | |
993 TEST_F(TcpCubicSenderPacketsTest, ResetAfterConnectionMigration) { | |
994 EXPECT_EQ(kDefaultWindowTCP, sender_->GetCongestionWindow()); | |
995 EXPECT_EQ(kMaxCongestionWindowPackets, sender_->slowstart_threshold()); | |
996 | |
997 // Starts with slow start. | |
998 sender_->SetNumEmulatedConnections(1); | |
999 const int kNumberOfAcks = 10; | |
1000 for (int i = 0; i < kNumberOfAcks; ++i) { | |
1001 // Send our full send window. | |
1002 SendAvailableSendWindow(); | |
1003 AckNPackets(2); | |
1004 } | |
1005 SendAvailableSendWindow(); | |
1006 QuicByteCount expected_send_window = | |
1007 kDefaultWindowTCP + (kDefaultTCPMSS * 2 * kNumberOfAcks); | |
1008 EXPECT_EQ(expected_send_window, sender_->GetCongestionWindow()); | |
1009 | |
1010 // Loses a packet to exit slow start. | |
1011 LoseNPackets(1); | |
1012 | |
1013 // We should now have fallen out of slow start with a reduced window. Slow | |
1014 // start threshold is also updated. | |
1015 expected_send_window *= kRenoBeta; | |
1016 EXPECT_EQ(expected_send_window, sender_->GetCongestionWindow()); | |
1017 EXPECT_EQ(expected_send_window / kDefaultTCPMSS, | |
1018 sender_->slowstart_threshold()); | |
1019 | |
1020 // Resets cwnd and slow start threshold on connection migrations. | |
1021 sender_->OnConnectionMigration(); | |
1022 EXPECT_EQ(kDefaultWindowTCP, sender_->GetCongestionWindow()); | |
1023 EXPECT_EQ(kMaxCongestionWindowPackets, sender_->slowstart_threshold()); | |
1024 EXPECT_FALSE(sender_->hybrid_slow_start().started()); | |
1025 } | |
1026 | |
1027 TEST_F(TcpCubicSenderPacketsTest, DefaultMaxCwnd) { | |
1028 RttStats rtt_stats; | |
1029 QuicConnectionStats stats; | |
1030 std::unique_ptr<SendAlgorithmInterface> sender(SendAlgorithmInterface::Create( | |
1031 &clock_, &rtt_stats, kCubic, &stats, kInitialCongestionWindow)); | |
1032 | |
1033 SendAlgorithmInterface::CongestionVector acked_packets; | |
1034 SendAlgorithmInterface::CongestionVector missing_packets; | |
1035 for (uint64_t i = 1; i < kDefaultMaxCongestionWindowPackets; ++i) { | |
1036 acked_packets.clear(); | |
1037 acked_packets.push_back(std::make_pair(i, 1350)); | |
1038 sender->OnCongestionEvent(true, sender->GetCongestionWindow(), | |
1039 acked_packets, missing_packets); | |
1040 } | |
1041 EXPECT_EQ(kDefaultMaxCongestionWindowPackets, | |
1042 sender->GetCongestionWindow() / kDefaultTCPMSS); | |
1043 } | |
1044 | |
1045 } // namespace test | |
1046 } // namespace net | |
OLD | NEW |