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

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

Issue 2193073003: Move shared files in net/quic/ into net/quic/core/ (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: io_thread_unittest.cc Created 4 years, 4 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 2015 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/general_loss_algorithm.h"
6
7 #include <algorithm>
8
9 #include "base/logging.h"
10 #include "net/quic/congestion_control/rtt_stats.h"
11 #include "net/quic/quic_flags.h"
12 #include "net/quic/quic_unacked_packet_map.h"
13 #include "net/quic/test_tools/mock_clock.h"
14 #include "testing/gtest/include/gtest/gtest.h"
15
16 using std::vector;
17
18 namespace net {
19 namespace test {
20 namespace {
21
22 // Default packet length.
23 const uint32_t kDefaultLength = 1000;
24
25 class GeneralLossAlgorithmTest : public ::testing::Test {
26 protected:
27 GeneralLossAlgorithmTest() {
28 rtt_stats_.UpdateRtt(QuicTime::Delta::FromMilliseconds(100),
29 QuicTime::Delta::Zero(), clock_.Now());
30 EXPECT_LT(0, rtt_stats_.smoothed_rtt().ToMicroseconds());
31 }
32
33 ~GeneralLossAlgorithmTest() override {}
34
35 void SendDataPacket(QuicPacketNumber packet_number) {
36 QuicStreamFrame* frame = new QuicStreamFrame();
37 frame->stream_id = kHeadersStreamId;
38 SerializedPacket packet(kDefaultPathId, packet_number,
39 PACKET_1BYTE_PACKET_NUMBER, nullptr, kDefaultLength,
40 0, false, false);
41 packet.retransmittable_frames.push_back(QuicFrame(frame));
42 unacked_packets_.AddSentPacket(&packet, 0, NOT_RETRANSMISSION, clock_.Now(),
43 true);
44 }
45
46 void VerifyLosses(QuicPacketNumber largest_newly_acked,
47 QuicPacketNumber* losses_expected,
48 size_t num_losses) {
49 if (largest_newly_acked > unacked_packets_.largest_observed()) {
50 unacked_packets_.IncreaseLargestObserved(largest_newly_acked);
51 }
52 SendAlgorithmInterface::CongestionVector lost_packets;
53 loss_algorithm_.DetectLosses(unacked_packets_, clock_.Now(), rtt_stats_,
54 largest_newly_acked, &lost_packets);
55 EXPECT_EQ(num_losses, lost_packets.size());
56 for (size_t i = 0; i < num_losses; ++i) {
57 EXPECT_EQ(lost_packets[i].first, losses_expected[i]);
58 }
59 }
60
61 QuicUnackedPacketMap unacked_packets_;
62 GeneralLossAlgorithm loss_algorithm_;
63 RttStats rtt_stats_;
64 MockClock clock_;
65 };
66
67 TEST_F(GeneralLossAlgorithmTest, NackRetransmit1Packet) {
68 const size_t kNumSentPackets = 5;
69 // Transmit 5 packets.
70 for (size_t i = 1; i <= kNumSentPackets; ++i) {
71 SendDataPacket(i);
72 }
73 // No loss on one ack.
74 unacked_packets_.RemoveFromInFlight(2);
75 VerifyLosses(2, nullptr, 0);
76 // No loss on two acks.
77 unacked_packets_.RemoveFromInFlight(3);
78 VerifyLosses(3, nullptr, 0);
79 // Loss on three acks.
80 unacked_packets_.RemoveFromInFlight(4);
81 QuicPacketNumber lost[] = {1};
82 VerifyLosses(4, lost, arraysize(lost));
83 EXPECT_EQ(QuicTime::Zero(), loss_algorithm_.GetLossTimeout());
84 }
85
86 // A stretch ack is an ack that covers more than 1 packet of previously
87 // unacknowledged data.
88 TEST_F(GeneralLossAlgorithmTest, NackRetransmit1PacketWith1StretchAck) {
89 const size_t kNumSentPackets = 10;
90 // Transmit 10 packets.
91 for (size_t i = 1; i <= kNumSentPackets; ++i) {
92 SendDataPacket(i);
93 }
94
95 // Nack the first packet 3 times in a single StretchAck.
96 unacked_packets_.RemoveFromInFlight(2);
97 unacked_packets_.RemoveFromInFlight(3);
98 unacked_packets_.RemoveFromInFlight(4);
99 QuicPacketNumber lost[] = {1};
100 VerifyLosses(4, lost, arraysize(lost));
101 EXPECT_EQ(QuicTime::Zero(), loss_algorithm_.GetLossTimeout());
102 }
103
104 // Ack a packet 3 packets ahead, causing a retransmit.
105 TEST_F(GeneralLossAlgorithmTest, NackRetransmit1PacketSingleAck) {
106 const size_t kNumSentPackets = 10;
107 // Transmit 10 packets.
108 for (size_t i = 1; i <= kNumSentPackets; ++i) {
109 SendDataPacket(i);
110 }
111
112 // Nack the first packet 3 times in an AckFrame with three missing packets.
113 unacked_packets_.RemoveFromInFlight(4);
114 QuicPacketNumber lost[] = {1};
115 VerifyLosses(4, lost, arraysize(lost));
116 EXPECT_EQ(QuicTime::Zero(), loss_algorithm_.GetLossTimeout());
117 }
118
119 TEST_F(GeneralLossAlgorithmTest, EarlyRetransmit1Packet) {
120 const size_t kNumSentPackets = 2;
121 // Transmit 2 packets.
122 for (size_t i = 1; i <= kNumSentPackets; ++i) {
123 SendDataPacket(i);
124 }
125 // Early retransmit when the final packet gets acked and the first is nacked.
126 unacked_packets_.RemoveFromInFlight(2);
127 VerifyLosses(2, nullptr, 0);
128 EXPECT_EQ(clock_.Now() + 1.25 * rtt_stats_.smoothed_rtt(),
129 loss_algorithm_.GetLossTimeout());
130
131 clock_.AdvanceTime(1.25 * rtt_stats_.latest_rtt());
132 QuicPacketNumber lost[] = {1};
133 VerifyLosses(2, lost, arraysize(lost));
134 EXPECT_EQ(QuicTime::Zero(), loss_algorithm_.GetLossTimeout());
135 }
136
137 TEST_F(GeneralLossAlgorithmTest, EarlyRetransmitAllPackets) {
138 const size_t kNumSentPackets = 5;
139 for (size_t i = 1; i <= kNumSentPackets; ++i) {
140 SendDataPacket(i);
141 // Advance the time 1/4 RTT between 3 and 4.
142 if (i == 3) {
143 clock_.AdvanceTime(0.25 * rtt_stats_.smoothed_rtt());
144 }
145 }
146
147 // Early retransmit when the final packet gets acked and 1.25 RTTs have
148 // elapsed since the packets were sent.
149 unacked_packets_.RemoveFromInFlight(kNumSentPackets);
150 // This simulates a single ack following multiple missing packets with FACK.
151 QuicPacketNumber lost[] = {1, 2};
152 VerifyLosses(kNumSentPackets, lost, arraysize(lost));
153 // The time has already advanced 1/4 an RTT, so ensure the timeout is set
154 // 1.25 RTTs after the earliest pending packet(3), not the last(4).
155 EXPECT_EQ(clock_.Now() + rtt_stats_.smoothed_rtt(),
156 loss_algorithm_.GetLossTimeout());
157
158 clock_.AdvanceTime(rtt_stats_.smoothed_rtt());
159 QuicPacketNumber lost2[] = {1, 2, 3};
160 VerifyLosses(kNumSentPackets, lost2, arraysize(lost2));
161 EXPECT_EQ(clock_.Now() + 0.25 * rtt_stats_.smoothed_rtt(),
162 loss_algorithm_.GetLossTimeout());
163 clock_.AdvanceTime(0.25 * rtt_stats_.smoothed_rtt());
164 QuicPacketNumber lost3[] = {1, 2, 3, 4};
165 VerifyLosses(kNumSentPackets, lost3, arraysize(lost3));
166 EXPECT_EQ(QuicTime::Zero(), loss_algorithm_.GetLossTimeout());
167 }
168
169 TEST_F(GeneralLossAlgorithmTest, DontEarlyRetransmitNeuteredPacket) {
170 const size_t kNumSentPackets = 2;
171 // Transmit 2 packets.
172 for (size_t i = 1; i <= kNumSentPackets; ++i) {
173 SendDataPacket(i);
174 }
175 // Neuter packet 1.
176 unacked_packets_.RemoveRetransmittability(1);
177
178 // Early retransmit when the final packet gets acked and the first is nacked.
179 unacked_packets_.IncreaseLargestObserved(2);
180 unacked_packets_.RemoveFromInFlight(2);
181 VerifyLosses(2, nullptr, 0);
182 EXPECT_EQ(QuicTime::Zero(), loss_algorithm_.GetLossTimeout());
183 }
184
185 TEST_F(GeneralLossAlgorithmTest, AlwaysLosePacketSent1RTTEarlier) {
186 // Transmit 1 packet and then wait an rtt plus 1ms.
187 SendDataPacket(1);
188 clock_.AdvanceTime(rtt_stats_.smoothed_rtt() +
189 QuicTime::Delta::FromMilliseconds(1));
190
191 // Transmit 2 packets.
192 SendDataPacket(2);
193 SendDataPacket(3);
194
195 // Wait another RTT and ack 2.
196 clock_.AdvanceTime(rtt_stats_.smoothed_rtt());
197 unacked_packets_.IncreaseLargestObserved(2);
198 unacked_packets_.RemoveFromInFlight(2);
199 QuicPacketNumber lost[] = {1};
200 VerifyLosses(2, lost, arraysize(lost));
201 }
202
203 // Time-based loss detection tests.
204 TEST_F(GeneralLossAlgorithmTest, NoLossFor500Nacks) {
205 loss_algorithm_.SetLossDetectionType(kTime);
206 const size_t kNumSentPackets = 5;
207 // Transmit 5 packets.
208 for (size_t i = 1; i <= kNumSentPackets; ++i) {
209 SendDataPacket(i);
210 }
211 unacked_packets_.RemoveFromInFlight(2);
212 for (size_t i = 1; i < 500; ++i) {
213 VerifyLosses(2, nullptr, 0);
214 }
215 EXPECT_EQ(1.25 * rtt_stats_.smoothed_rtt(),
216 loss_algorithm_.GetLossTimeout() - clock_.Now());
217 }
218
219 TEST_F(GeneralLossAlgorithmTest, NoLossUntilTimeout) {
220 loss_algorithm_.SetLossDetectionType(kTime);
221 const size_t kNumSentPackets = 10;
222 // Transmit 10 packets at 1/10th an RTT interval.
223 for (size_t i = 1; i <= kNumSentPackets; ++i) {
224 SendDataPacket(i);
225 clock_.AdvanceTime(0.1 * rtt_stats_.smoothed_rtt());
226 }
227 // Expect the timer to not be set.
228 EXPECT_EQ(QuicTime::Zero(), loss_algorithm_.GetLossTimeout());
229 // The packet should not be lost until 1.25 RTTs pass.
230 unacked_packets_.RemoveFromInFlight(2);
231 VerifyLosses(2, nullptr, 0);
232 // Expect the timer to be set to 0.25 RTT's in the future.
233 EXPECT_EQ(0.25 * rtt_stats_.smoothed_rtt(),
234 loss_algorithm_.GetLossTimeout() - clock_.Now());
235 VerifyLosses(2, nullptr, 0);
236 clock_.AdvanceTime(0.25 * rtt_stats_.smoothed_rtt());
237 QuicPacketNumber lost[] = {1};
238 VerifyLosses(2, lost, arraysize(lost));
239 EXPECT_EQ(QuicTime::Zero(), loss_algorithm_.GetLossTimeout());
240 }
241
242 TEST_F(GeneralLossAlgorithmTest, NoLossWithoutNack) {
243 loss_algorithm_.SetLossDetectionType(kTime);
244 const size_t kNumSentPackets = 10;
245 // Transmit 10 packets at 1/10th an RTT interval.
246 for (size_t i = 1; i <= kNumSentPackets; ++i) {
247 SendDataPacket(i);
248 clock_.AdvanceTime(0.1 * rtt_stats_.smoothed_rtt());
249 }
250 // Expect the timer to not be set.
251 EXPECT_EQ(QuicTime::Zero(), loss_algorithm_.GetLossTimeout());
252 // The packet should not be lost without a nack.
253 unacked_packets_.RemoveFromInFlight(1);
254 VerifyLosses(1, nullptr, 0);
255 // The timer should still not be set.
256 EXPECT_EQ(QuicTime::Zero(), loss_algorithm_.GetLossTimeout());
257 clock_.AdvanceTime(0.25 * rtt_stats_.smoothed_rtt());
258 VerifyLosses(1, nullptr, 0);
259 clock_.AdvanceTime(rtt_stats_.smoothed_rtt());
260 VerifyLosses(1, nullptr, 0);
261
262 EXPECT_EQ(QuicTime::Zero(), loss_algorithm_.GetLossTimeout());
263 }
264
265 TEST_F(GeneralLossAlgorithmTest, MultipleLossesAtOnce) {
266 loss_algorithm_.SetLossDetectionType(kTime);
267 const size_t kNumSentPackets = 10;
268 // Transmit 10 packets at once and then go forward an RTT.
269 for (size_t i = 1; i <= kNumSentPackets; ++i) {
270 SendDataPacket(i);
271 }
272 clock_.AdvanceTime(rtt_stats_.smoothed_rtt());
273 // Expect the timer to not be set.
274 EXPECT_EQ(QuicTime::Zero(), loss_algorithm_.GetLossTimeout());
275 // The packet should not be lost until 1.25 RTTs pass.
276 unacked_packets_.RemoveFromInFlight(10);
277 VerifyLosses(10, nullptr, 0);
278 // Expect the timer to be set to 0.25 RTT's in the future.
279 EXPECT_EQ(0.25 * rtt_stats_.smoothed_rtt(),
280 loss_algorithm_.GetLossTimeout() - clock_.Now());
281 clock_.AdvanceTime(0.25 * rtt_stats_.smoothed_rtt());
282 QuicPacketNumber lost[] = {1, 2, 3, 4, 5, 6, 7, 8, 9};
283 VerifyLosses(10, lost, arraysize(lost));
284 EXPECT_EQ(QuicTime::Zero(), loss_algorithm_.GetLossTimeout());
285 }
286
287 TEST_F(GeneralLossAlgorithmTest, NoSpuriousLossesFromLargeReordering) {
288 FLAGS_quic_loss_recovery_use_largest_acked = true;
289 loss_algorithm_.SetLossDetectionType(kTime);
290 const size_t kNumSentPackets = 10;
291 // Transmit 10 packets at once and then go forward an RTT.
292 for (size_t i = 1; i <= kNumSentPackets; ++i) {
293 SendDataPacket(i);
294 }
295 clock_.AdvanceTime(rtt_stats_.smoothed_rtt());
296 // Expect the timer to not be set.
297 EXPECT_EQ(QuicTime::Zero(), loss_algorithm_.GetLossTimeout());
298 // The packet should not be lost until 1.25 RTTs pass.
299
300 unacked_packets_.RemoveFromInFlight(10);
301 VerifyLosses(10, nullptr, 0);
302 // Expect the timer to be set to 0.25 RTT's in the future.
303 EXPECT_EQ(0.25 * rtt_stats_.smoothed_rtt(),
304 loss_algorithm_.GetLossTimeout() - clock_.Now());
305 clock_.AdvanceTime(0.25 * rtt_stats_.smoothed_rtt());
306 // Now ack packets 1 to 9 and ensure the timer is no longer set and no packets
307 // are lost.
308 for (QuicPacketNumber i = 1; i <= 9; ++i) {
309 unacked_packets_.RemoveFromInFlight(i);
310 VerifyLosses(i, nullptr, 0);
311 EXPECT_EQ(QuicTime::Zero(), loss_algorithm_.GetLossTimeout());
312 }
313 }
314
315 TEST_F(GeneralLossAlgorithmTest, IncreaseThresholdUponSpuriousLoss) {
316 loss_algorithm_.SetLossDetectionType(kAdaptiveTime);
317 EXPECT_EQ(4, loss_algorithm_.reordering_shift());
318 const size_t kNumSentPackets = 10;
319 // Transmit 2 packets at 1/10th an RTT interval.
320 for (size_t i = 1; i <= kNumSentPackets; ++i) {
321 SendDataPacket(i);
322 clock_.AdvanceTime(0.1 * rtt_stats_.smoothed_rtt());
323 }
324 EXPECT_EQ(QuicTime::Zero() + rtt_stats_.smoothed_rtt(), clock_.Now());
325
326 // Expect the timer to not be set.
327 EXPECT_EQ(QuicTime::Zero(), loss_algorithm_.GetLossTimeout());
328 // Packet 1 should not be lost until 1/16 RTTs pass.
329 unacked_packets_.RemoveFromInFlight(2);
330 VerifyLosses(2, nullptr, 0);
331 // Expect the timer to be set to 1/16 RTT's in the future.
332 EXPECT_EQ(rtt_stats_.smoothed_rtt() * (1.0f / 16),
333 loss_algorithm_.GetLossTimeout() - clock_.Now());
334 VerifyLosses(2, nullptr, 0);
335 clock_.AdvanceTime(rtt_stats_.smoothed_rtt() * (1.0f / 16));
336 QuicPacketNumber lost[] = {1};
337 VerifyLosses(2, lost, arraysize(lost));
338 EXPECT_EQ(QuicTime::Zero(), loss_algorithm_.GetLossTimeout());
339 // Retransmit packet 1 as 11 and 2 as 12.
340 SendDataPacket(11);
341 SendDataPacket(12);
342
343 // Advance the time 1/4 RTT and indicate the loss was spurious.
344 // The new threshold should be 1/2 RTT.
345 clock_.AdvanceTime(rtt_stats_.smoothed_rtt() * (1.0f / 4));
346 loss_algorithm_.SpuriousRetransmitDetected(unacked_packets_, clock_.Now(),
347 rtt_stats_, 11);
348 EXPECT_EQ(1, loss_algorithm_.reordering_shift());
349
350 // Detect another spurious retransmit and ensure the threshold doesn't
351 // increase again.
352 loss_algorithm_.SpuriousRetransmitDetected(unacked_packets_, clock_.Now(),
353 rtt_stats_, 12);
354 EXPECT_EQ(1, loss_algorithm_.reordering_shift());
355 }
356
357 } // namespace
358 } // namespace test
359 } // namespace net
OLDNEW
« no previous file with comments | « net/quic/congestion_control/general_loss_algorithm.cc ('k') | net/quic/congestion_control/hybrid_slow_start.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698