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