blob: 750b14e69229f371a061a757a190d53e0ac3bc63 [file] [log] [blame]
QUICHE teama6ef0a62019-03-07 20:34:33 -05001// Copyright 2016 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/third_party/quiche/src/quic/core/congestion_control/bandwidth_sampler.h"
6
wub254545c2019-04-04 13:56:52 -07007#include "net/third_party/quiche/src/quic/core/quic_types.h"
QUICHE teama6ef0a62019-03-07 20:34:33 -05008#include "net/third_party/quiche/src/quic/platform/api/quic_flags.h"
9#include "net/third_party/quiche/src/quic/platform/api/quic_test.h"
10#include "net/third_party/quiche/src/quic/test_tools/mock_clock.h"
11
12namespace quic {
13namespace test {
14
15class BandwidthSamplerPeer {
16 public:
17 static size_t GetNumberOfTrackedPackets(const BandwidthSampler& sampler) {
18 return sampler.connection_state_map_.number_of_present_entries();
19 }
20
21 static QuicByteCount GetPacketSize(const BandwidthSampler& sampler,
22 QuicPacketNumber packet_number) {
23 return sampler.connection_state_map_.GetEntry(packet_number)->size;
24 }
25};
26
27const QuicByteCount kRegularPacketSize = 1280;
28// Enforce divisibility for some of the tests.
29static_assert((kRegularPacketSize & 31) == 0,
30 "kRegularPacketSize has to be five times divisible by 2");
31
32// A test fixture with utility methods for BandwidthSampler tests.
33class BandwidthSamplerTest : public QuicTest {
34 protected:
35 BandwidthSamplerTest() : bytes_in_flight_(0) {
36 // Ensure that the clock does not start at zero.
37 clock_.AdvanceTime(QuicTime::Delta::FromSeconds(1));
38 }
39
40 MockClock clock_;
41 BandwidthSampler sampler_;
42 QuicByteCount bytes_in_flight_;
43
wub254545c2019-04-04 13:56:52 -070044 QuicByteCount PacketsToBytes(QuicPacketCount packet_count) {
45 return packet_count * kRegularPacketSize;
46 }
47
QUICHE teama6ef0a62019-03-07 20:34:33 -050048 void SendPacketInner(uint64_t packet_number,
49 QuicByteCount bytes,
50 HasRetransmittableData has_retransmittable_data) {
51 sampler_.OnPacketSent(clock_.Now(), QuicPacketNumber(packet_number), bytes,
52 bytes_in_flight_, has_retransmittable_data);
53 if (has_retransmittable_data == HAS_RETRANSMITTABLE_DATA) {
54 bytes_in_flight_ += bytes;
55 }
56 }
57
58 void SendPacket(uint64_t packet_number) {
59 SendPacketInner(packet_number, kRegularPacketSize,
60 HAS_RETRANSMITTABLE_DATA);
61 }
62
63 BandwidthSample AckPacketInner(uint64_t packet_number) {
64 QuicByteCount size = BandwidthSamplerPeer::GetPacketSize(
65 sampler_, QuicPacketNumber(packet_number));
66 bytes_in_flight_ -= size;
67 return sampler_.OnPacketAcknowledged(clock_.Now(),
68 QuicPacketNumber(packet_number));
69 }
70
71 // Acknowledge receipt of a packet and expect it to be not app-limited.
72 QuicBandwidth AckPacket(uint64_t packet_number) {
73 BandwidthSample sample = AckPacketInner(packet_number);
wub254545c2019-04-04 13:56:52 -070074 EXPECT_TRUE(sample.state_at_send.is_valid);
75 EXPECT_FALSE(sample.state_at_send.is_app_limited);
QUICHE teama6ef0a62019-03-07 20:34:33 -050076 return sample.bandwidth;
77 }
78
wub254545c2019-04-04 13:56:52 -070079 SendTimeState LosePacket(uint64_t packet_number) {
QUICHE teama6ef0a62019-03-07 20:34:33 -050080 QuicByteCount size = BandwidthSamplerPeer::GetPacketSize(
81 sampler_, QuicPacketNumber(packet_number));
82 bytes_in_flight_ -= size;
wub254545c2019-04-04 13:56:52 -070083 SendTimeState send_time_state =
84 sampler_.OnPacketLost(QuicPacketNumber(packet_number));
85 EXPECT_TRUE(send_time_state.is_valid);
86 return send_time_state;
QUICHE teama6ef0a62019-03-07 20:34:33 -050087 }
88
89 // Sends one packet and acks it. Then, send 20 packets. Finally, send
90 // another 20 packets while acknowledging previous 20.
91 void Send40PacketsAndAckFirst20(QuicTime::Delta time_between_packets) {
92 // Send 20 packets at a constant inter-packet time.
93 for (int i = 1; i <= 20; i++) {
94 SendPacket(i);
95 clock_.AdvanceTime(time_between_packets);
96 }
97
98 // Ack packets 1 to 20, while sending new packets at the same rate as
99 // before.
100 for (int i = 1; i <= 20; i++) {
101 AckPacket(i);
102 SendPacket(i + 20);
103 clock_.AdvanceTime(time_between_packets);
104 }
105 }
106};
107
108// Test the sampler in a simple stop-and-wait sender setting.
109TEST_F(BandwidthSamplerTest, SendAndWait) {
110 QuicTime::Delta time_between_packets = QuicTime::Delta::FromMilliseconds(10);
111 QuicBandwidth expected_bandwidth =
112 QuicBandwidth::FromBytesPerSecond(kRegularPacketSize * 100);
113
114 // Send packets at the constant bandwidth.
115 for (int i = 1; i < 20; i++) {
116 SendPacket(i);
117 clock_.AdvanceTime(time_between_packets);
118 QuicBandwidth current_sample = AckPacket(i);
119 EXPECT_EQ(expected_bandwidth, current_sample);
120 }
121
122 // Send packets at the exponentially decreasing bandwidth.
123 for (int i = 20; i < 25; i++) {
124 time_between_packets = time_between_packets * 2;
125 expected_bandwidth = expected_bandwidth * 0.5;
126
127 SendPacket(i);
128 clock_.AdvanceTime(time_between_packets);
129 QuicBandwidth current_sample = AckPacket(i);
130 EXPECT_EQ(expected_bandwidth, current_sample);
131 }
132 EXPECT_EQ(0u, BandwidthSamplerPeer::GetNumberOfTrackedPackets(sampler_));
133 EXPECT_EQ(0u, bytes_in_flight_);
134}
135
wub254545c2019-04-04 13:56:52 -0700136TEST_F(BandwidthSamplerTest, SendTimeState) {
137 QuicTime::Delta time_between_packets = QuicTime::Delta::FromMilliseconds(10);
138
139 // Send packets 1-5.
140 for (int i = 1; i <= 5; i++) {
141 SendPacket(i);
142 EXPECT_EQ(PacketsToBytes(i), sampler_.total_bytes_sent());
143 clock_.AdvanceTime(time_between_packets);
144 }
145
146 // Ack packet 1.
147 SendTimeState send_time_state = AckPacketInner(1).state_at_send;
148 EXPECT_EQ(PacketsToBytes(1), send_time_state.total_bytes_sent);
wub07cc9382019-04-05 13:30:25 -0700149 EXPECT_EQ(0u, send_time_state.total_bytes_acked);
150 EXPECT_EQ(0u, send_time_state.total_bytes_lost);
wub254545c2019-04-04 13:56:52 -0700151 EXPECT_EQ(PacketsToBytes(1), sampler_.total_bytes_acked());
152
153 // Lose packet 2.
154 send_time_state = LosePacket(2);
155 EXPECT_EQ(PacketsToBytes(2), send_time_state.total_bytes_sent);
wub07cc9382019-04-05 13:30:25 -0700156 EXPECT_EQ(0u, send_time_state.total_bytes_acked);
157 EXPECT_EQ(0u, send_time_state.total_bytes_lost);
wub254545c2019-04-04 13:56:52 -0700158 EXPECT_EQ(PacketsToBytes(1), sampler_.total_bytes_lost());
159
160 // Lose packet 3.
161 send_time_state = LosePacket(3);
162 EXPECT_EQ(PacketsToBytes(3), send_time_state.total_bytes_sent);
wub07cc9382019-04-05 13:30:25 -0700163 EXPECT_EQ(0u, send_time_state.total_bytes_acked);
164 EXPECT_EQ(0u, send_time_state.total_bytes_lost);
wub254545c2019-04-04 13:56:52 -0700165 EXPECT_EQ(PacketsToBytes(2), sampler_.total_bytes_lost());
166
167 // Send packets 6-10.
168 for (int i = 6; i <= 10; i++) {
169 SendPacket(i);
170 EXPECT_EQ(PacketsToBytes(i), sampler_.total_bytes_sent());
171 clock_.AdvanceTime(time_between_packets);
172 }
173
174 // Ack all inflight packets.
175 QuicPacketCount acked_packet_count = 1;
176 EXPECT_EQ(PacketsToBytes(acked_packet_count), sampler_.total_bytes_acked());
177 for (int i = 4; i <= 10; i++) {
178 send_time_state = AckPacketInner(i).state_at_send;
179 ++acked_packet_count;
180 EXPECT_EQ(PacketsToBytes(acked_packet_count), sampler_.total_bytes_acked());
181 EXPECT_EQ(PacketsToBytes(i), send_time_state.total_bytes_sent);
182 if (i <= 5) {
wub07cc9382019-04-05 13:30:25 -0700183 EXPECT_EQ(0u, send_time_state.total_bytes_acked);
184 EXPECT_EQ(0u, send_time_state.total_bytes_lost);
wub254545c2019-04-04 13:56:52 -0700185 } else {
186 EXPECT_EQ(PacketsToBytes(1), send_time_state.total_bytes_acked);
187 EXPECT_EQ(PacketsToBytes(2), send_time_state.total_bytes_lost);
188 }
189 clock_.AdvanceTime(time_between_packets);
190 }
191}
192
QUICHE teama6ef0a62019-03-07 20:34:33 -0500193// Test the sampler during regular windowed sender scenario with fixed
194// CWND of 20.
195TEST_F(BandwidthSamplerTest, SendPaced) {
196 const QuicTime::Delta time_between_packets =
197 QuicTime::Delta::FromMilliseconds(1);
198 QuicBandwidth expected_bandwidth =
199 QuicBandwidth::FromKBytesPerSecond(kRegularPacketSize);
200
201 Send40PacketsAndAckFirst20(time_between_packets);
202
203 // Ack the packets 21 to 40, arriving at the correct bandwidth.
204 QuicBandwidth last_bandwidth = QuicBandwidth::Zero();
205 for (int i = 21; i <= 40; i++) {
206 last_bandwidth = AckPacket(i);
207 EXPECT_EQ(expected_bandwidth, last_bandwidth);
208 clock_.AdvanceTime(time_between_packets);
209 }
210 EXPECT_EQ(0u, BandwidthSamplerPeer::GetNumberOfTrackedPackets(sampler_));
211 EXPECT_EQ(0u, bytes_in_flight_);
212}
213
214// Test the sampler in a scenario where 50% of packets is consistently lost.
215TEST_F(BandwidthSamplerTest, SendWithLosses) {
216 const QuicTime::Delta time_between_packets =
217 QuicTime::Delta::FromMilliseconds(1);
218 QuicBandwidth expected_bandwidth =
219 QuicBandwidth::FromKBytesPerSecond(kRegularPacketSize) * 0.5;
220
221 // Send 20 packets, each 1 ms apart.
222 for (int i = 1; i <= 20; i++) {
223 SendPacket(i);
224 clock_.AdvanceTime(time_between_packets);
225 }
226
227 // Ack packets 1 to 20, losing every even-numbered packet, while sending new
228 // packets at the same rate as before.
229 for (int i = 1; i <= 20; i++) {
230 if (i % 2 == 0) {
231 AckPacket(i);
232 } else {
233 LosePacket(i);
234 }
235 SendPacket(i + 20);
236 clock_.AdvanceTime(time_between_packets);
237 }
238
239 // Ack the packets 21 to 40 with the same loss pattern.
240 QuicBandwidth last_bandwidth = QuicBandwidth::Zero();
241 for (int i = 21; i <= 40; i++) {
242 if (i % 2 == 0) {
243 last_bandwidth = AckPacket(i);
244 EXPECT_EQ(expected_bandwidth, last_bandwidth);
245 } else {
246 LosePacket(i);
247 }
248 clock_.AdvanceTime(time_between_packets);
249 }
250 EXPECT_EQ(0u, BandwidthSamplerPeer::GetNumberOfTrackedPackets(sampler_));
251 EXPECT_EQ(0u, bytes_in_flight_);
252}
253
254// Test the sampler in a scenario where the 50% of packets are not
255// congestion controlled (specifically, non-retransmittable data is not
256// congestion controlled). Should be functionally consistent in behavior with
257// the SendWithLosses test.
258TEST_F(BandwidthSamplerTest, NotCongestionControlled) {
259 const QuicTime::Delta time_between_packets =
260 QuicTime::Delta::FromMilliseconds(1);
261 QuicBandwidth expected_bandwidth =
262 QuicBandwidth::FromKBytesPerSecond(kRegularPacketSize) * 0.5;
263
264 // Send 20 packets, each 1 ms apart. Every even packet is not congestion
265 // controlled.
266 for (int i = 1; i <= 20; i++) {
267 SendPacketInner(
268 i, kRegularPacketSize,
269 i % 2 == 0 ? HAS_RETRANSMITTABLE_DATA : NO_RETRANSMITTABLE_DATA);
270 clock_.AdvanceTime(time_between_packets);
271 }
272
273 // Ensure only congestion controlled packets are tracked.
274 EXPECT_EQ(10u, BandwidthSamplerPeer::GetNumberOfTrackedPackets(sampler_));
275
276 // Ack packets 2 to 21, ignoring every even-numbered packet, while sending new
277 // packets at the same rate as before.
278 for (int i = 1; i <= 20; i++) {
279 if (i % 2 == 0) {
280 AckPacket(i);
281 }
282 SendPacketInner(
283 i + 20, kRegularPacketSize,
284 i % 2 == 0 ? HAS_RETRANSMITTABLE_DATA : NO_RETRANSMITTABLE_DATA);
285 clock_.AdvanceTime(time_between_packets);
286 }
287
288 // Ack the packets 22 to 41 with the same congestion controlled pattern.
289 QuicBandwidth last_bandwidth = QuicBandwidth::Zero();
290 for (int i = 21; i <= 40; i++) {
291 if (i % 2 == 0) {
292 last_bandwidth = AckPacket(i);
293 EXPECT_EQ(expected_bandwidth, last_bandwidth);
294 }
295 clock_.AdvanceTime(time_between_packets);
296 }
297
298 // Since only congestion controlled packets are entered into the map, it has
299 // to be empty at this point.
300 EXPECT_EQ(0u, BandwidthSamplerPeer::GetNumberOfTrackedPackets(sampler_));
301 EXPECT_EQ(0u, bytes_in_flight_);
302}
303
304// Simulate a situation where ACKs arrive in burst and earlier than usual, thus
305// producing an ACK rate which is higher than the original send rate.
306TEST_F(BandwidthSamplerTest, CompressedAck) {
307 const QuicTime::Delta time_between_packets =
308 QuicTime::Delta::FromMilliseconds(1);
309 QuicBandwidth expected_bandwidth =
310 QuicBandwidth::FromKBytesPerSecond(kRegularPacketSize);
311
312 Send40PacketsAndAckFirst20(time_between_packets);
313
314 // Simulate an RTT somewhat lower than the one for 1-to-21 transmission.
315 clock_.AdvanceTime(time_between_packets * 15);
316
317 // Ack the packets 21 to 40 almost immediately at once.
318 QuicBandwidth last_bandwidth = QuicBandwidth::Zero();
319 QuicTime::Delta ridiculously_small_time_delta =
320 QuicTime::Delta::FromMicroseconds(20);
321 for (int i = 21; i <= 40; i++) {
322 last_bandwidth = AckPacket(i);
323 clock_.AdvanceTime(ridiculously_small_time_delta);
324 }
325 EXPECT_EQ(expected_bandwidth, last_bandwidth);
326 EXPECT_EQ(0u, BandwidthSamplerPeer::GetNumberOfTrackedPackets(sampler_));
327 EXPECT_EQ(0u, bytes_in_flight_);
328}
329
330// Tests receiving ACK packets in the reverse order.
331TEST_F(BandwidthSamplerTest, ReorderedAck) {
332 const QuicTime::Delta time_between_packets =
333 QuicTime::Delta::FromMilliseconds(1);
334 QuicBandwidth expected_bandwidth =
335 QuicBandwidth::FromKBytesPerSecond(kRegularPacketSize);
336
337 Send40PacketsAndAckFirst20(time_between_packets);
338
339 // Ack the packets 21 to 40 in the reverse order, while sending packets 41 to
340 // 60.
341 QuicBandwidth last_bandwidth = QuicBandwidth::Zero();
342 for (int i = 0; i < 20; i++) {
343 last_bandwidth = AckPacket(40 - i);
344 EXPECT_EQ(expected_bandwidth, last_bandwidth);
345 SendPacket(41 + i);
346 clock_.AdvanceTime(time_between_packets);
347 }
348
349 // Ack the packets 41 to 60, now in the regular order.
350 for (int i = 41; i <= 60; i++) {
351 last_bandwidth = AckPacket(i);
352 EXPECT_EQ(expected_bandwidth, last_bandwidth);
353 clock_.AdvanceTime(time_between_packets);
354 }
355 EXPECT_EQ(0u, BandwidthSamplerPeer::GetNumberOfTrackedPackets(sampler_));
356 EXPECT_EQ(0u, bytes_in_flight_);
357}
358
359// Test the app-limited logic.
360TEST_F(BandwidthSamplerTest, AppLimited) {
361 const QuicTime::Delta time_between_packets =
362 QuicTime::Delta::FromMilliseconds(1);
363 QuicBandwidth expected_bandwidth =
364 QuicBandwidth::FromKBytesPerSecond(kRegularPacketSize);
365
366 Send40PacketsAndAckFirst20(time_between_packets);
367
368 // We are now app-limited. Ack 21 to 40 as usual, but do not send anything for
369 // now.
370 sampler_.OnAppLimited();
371 for (int i = 21; i <= 40; i++) {
372 QuicBandwidth current_sample = AckPacket(i);
373 EXPECT_EQ(expected_bandwidth, current_sample);
374 clock_.AdvanceTime(time_between_packets);
375 }
376
377 // Enter quiescence.
378 clock_.AdvanceTime(QuicTime::Delta::FromSeconds(1));
379
380 // Send packets 41 to 60, all of which would be marked as app-limited.
381 for (int i = 41; i <= 60; i++) {
382 SendPacket(i);
383 clock_.AdvanceTime(time_between_packets);
384 }
385
386 // Ack packets 41 to 60, while sending packets 61 to 80. 41 to 60 should be
387 // app-limited and underestimate the bandwidth due to that.
388 for (int i = 41; i <= 60; i++) {
389 BandwidthSample sample = AckPacketInner(i);
wub254545c2019-04-04 13:56:52 -0700390 EXPECT_TRUE(sample.state_at_send.is_app_limited);
QUICHE teama6ef0a62019-03-07 20:34:33 -0500391 EXPECT_LT(sample.bandwidth, 0.7f * expected_bandwidth);
392
393 SendPacket(i + 20);
394 clock_.AdvanceTime(time_between_packets);
395 }
396
397 // Run out of packets, and then ack packet 61 to 80, all of which should have
398 // correct non-app-limited samples.
399 for (int i = 61; i <= 80; i++) {
400 QuicBandwidth last_bandwidth = AckPacket(i);
401 EXPECT_EQ(expected_bandwidth, last_bandwidth);
402 clock_.AdvanceTime(time_between_packets);
403 }
404
405 EXPECT_EQ(0u, BandwidthSamplerPeer::GetNumberOfTrackedPackets(sampler_));
406 EXPECT_EQ(0u, bytes_in_flight_);
407}
408
409// Test the samples taken at the first flight of packets sent.
410TEST_F(BandwidthSamplerTest, FirstRoundTrip) {
411 const QuicTime::Delta time_between_packets =
412 QuicTime::Delta::FromMilliseconds(1);
413 const QuicTime::Delta rtt = QuicTime::Delta::FromMilliseconds(800);
414 const int num_packets = 10;
415 const QuicByteCount num_bytes = kRegularPacketSize * num_packets;
416 const QuicBandwidth real_bandwidth =
417 QuicBandwidth::FromBytesAndTimeDelta(num_bytes, rtt);
418
419 for (int i = 1; i <= 10; i++) {
420 SendPacket(i);
421 clock_.AdvanceTime(time_between_packets);
422 }
423
424 clock_.AdvanceTime(rtt - num_packets * time_between_packets);
425
426 QuicBandwidth last_sample = QuicBandwidth::Zero();
427 for (int i = 1; i <= 10; i++) {
428 QuicBandwidth sample = AckPacket(i);
429 EXPECT_GT(sample, last_sample);
430 last_sample = sample;
431 clock_.AdvanceTime(time_between_packets);
432 }
433
434 // The final measured sample for the first flight of sample is expected to be
435 // smaller than the real bandwidth, yet it should not lose more than 10%. The
436 // specific value of the error depends on the difference between the RTT and
437 // the time it takes to exhaust the congestion window (i.e. in the limit when
438 // all packets are sent simultaneously, last sample would indicate the real
439 // bandwidth).
440 EXPECT_LT(last_sample, real_bandwidth);
441 EXPECT_GT(last_sample, 0.9f * real_bandwidth);
442}
443
444// Test sampler's ability to remove obsolete packets.
445TEST_F(BandwidthSamplerTest, RemoveObsoletePackets) {
446 SendPacket(1);
447 SendPacket(2);
448 SendPacket(3);
449 SendPacket(4);
450 SendPacket(5);
451
452 clock_.AdvanceTime(QuicTime::Delta::FromMilliseconds(100));
453
454 EXPECT_EQ(5u, BandwidthSamplerPeer::GetNumberOfTrackedPackets(sampler_));
455 sampler_.RemoveObsoletePackets(QuicPacketNumber(4));
456 EXPECT_EQ(2u, BandwidthSamplerPeer::GetNumberOfTrackedPackets(sampler_));
457 sampler_.OnPacketLost(QuicPacketNumber(4));
458 EXPECT_EQ(1u, BandwidthSamplerPeer::GetNumberOfTrackedPackets(sampler_));
459 AckPacket(5);
460 EXPECT_EQ(0u, BandwidthSamplerPeer::GetNumberOfTrackedPackets(sampler_));
461}
462
463} // namespace test
464} // namespace quic