blob: 1e7a8ce53a09af6d06d6b9a775a1d18254963116 [file] [log] [blame]
QUICHE teama6ef0a62019-03-07 20:34:33 -05001// 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/third_party/quiche/src/quic/test_tools/simulator/simulator.h"
6
7#include "net/third_party/quiche/src/quic/platform/api/quic_containers.h"
8#include "net/third_party/quiche/src/quic/platform/api/quic_logging.h"
9#include "net/third_party/quiche/src/quic/platform/api/quic_ptr_util.h"
10#include "net/third_party/quiche/src/quic/platform/api/quic_test.h"
11#include "net/third_party/quiche/src/quic/test_tools/quic_test_utils.h"
12#include "net/third_party/quiche/src/quic/test_tools/simulator/alarm_factory.h"
13#include "net/third_party/quiche/src/quic/test_tools/simulator/link.h"
14#include "net/third_party/quiche/src/quic/test_tools/simulator/packet_filter.h"
15#include "net/third_party/quiche/src/quic/test_tools/simulator/queue.h"
16#include "net/third_party/quiche/src/quic/test_tools/simulator/switch.h"
17#include "net/third_party/quiche/src/quic/test_tools/simulator/traffic_policer.h"
18
19using testing::_;
20using testing::Return;
21using testing::StrictMock;
22
23namespace quic {
24namespace simulator {
25
26// A simple counter that increments its value by 1 every specified period.
27class Counter : public Actor {
28 public:
vasilvvc48c8712019-03-11 13:38:16 -070029 Counter(Simulator* simulator, std::string name, QuicTime::Delta period)
QUICHE teama6ef0a62019-03-07 20:34:33 -050030 : Actor(simulator, name), value_(-1), period_(period) {
31 Schedule(clock_->Now());
32 }
33 ~Counter() override {}
34
35 inline int get_value() const { return value_; }
36
37 void Act() override {
38 ++value_;
39 QUIC_DVLOG(1) << name_ << " has value " << value_ << " at time "
40 << clock_->Now().ToDebuggingValue();
41 Schedule(clock_->Now() + period_);
42 }
43
44 private:
45 int value_;
46 QuicTime::Delta period_;
47};
48
49class SimulatorTest : public QuicTest {};
50
51// Test that the basic event handling works, and that Actors can be created and
52// destroyed mid-simulation.
53TEST_F(SimulatorTest, Counters) {
54 Simulator simulator;
55 for (int i = 0; i < 2; ++i) {
56 Counter fast_counter(&simulator, "fast_counter",
57 QuicTime::Delta::FromSeconds(3));
58 Counter slow_counter(&simulator, "slow_counter",
59 QuicTime::Delta::FromSeconds(10));
60
61 simulator.RunUntil(
62 [&slow_counter]() { return slow_counter.get_value() >= 10; });
63
64 EXPECT_EQ(10, slow_counter.get_value());
65 EXPECT_EQ(10 * 10 / 3, fast_counter.get_value());
66 }
67}
68
69// A port which counts the number of packets received on it, both total and
70// per-destination.
71class CounterPort : public UnconstrainedPortInterface {
72 public:
73 CounterPort() { Reset(); }
74 ~CounterPort() override {}
75
76 inline QuicByteCount bytes() const { return bytes_; }
77 inline QuicPacketCount packets() const { return packets_; }
78
79 void AcceptPacket(std::unique_ptr<Packet> packet) override {
80 bytes_ += packet->size;
81 packets_ += 1;
82
83 per_destination_packet_counter_[packet->destination] += 1;
84 }
85
86 void Reset() {
87 bytes_ = 0;
88 packets_ = 0;
89 per_destination_packet_counter_.clear();
90 }
91
vasilvvc48c8712019-03-11 13:38:16 -070092 QuicPacketCount CountPacketsForDestination(std::string destination) const {
QUICHE teama6ef0a62019-03-07 20:34:33 -050093 auto result_it = per_destination_packet_counter_.find(destination);
94 if (result_it == per_destination_packet_counter_.cend()) {
95 return 0;
96 }
97 return result_it->second;
98 }
99
100 private:
101 QuicByteCount bytes_;
102 QuicPacketCount packets_;
103
vasilvvc48c8712019-03-11 13:38:16 -0700104 QuicUnorderedMap<std::string, QuicPacketCount>
105 per_destination_packet_counter_;
QUICHE teama6ef0a62019-03-07 20:34:33 -0500106};
107
108// Sends the packet to the specified destination at the uplink rate. Provides a
109// CounterPort as an Rx interface.
110class LinkSaturator : public Endpoint {
111 public:
112 LinkSaturator(Simulator* simulator,
vasilvvc48c8712019-03-11 13:38:16 -0700113 std::string name,
QUICHE teama6ef0a62019-03-07 20:34:33 -0500114 QuicByteCount packet_size,
vasilvvc48c8712019-03-11 13:38:16 -0700115 std::string destination)
QUICHE teama6ef0a62019-03-07 20:34:33 -0500116 : Endpoint(simulator, name),
117 packet_size_(packet_size),
118 destination_(std::move(destination)),
119 bytes_transmitted_(0),
120 packets_transmitted_(0) {
121 Schedule(clock_->Now());
122 }
123
124 void Act() override {
125 if (tx_port_->TimeUntilAvailable().IsZero()) {
126 auto packet = QuicMakeUnique<Packet>();
127 packet->source = name_;
128 packet->destination = destination_;
129 packet->tx_timestamp = clock_->Now();
130 packet->size = packet_size_;
131
132 tx_port_->AcceptPacket(std::move(packet));
133
134 bytes_transmitted_ += packet_size_;
135 packets_transmitted_ += 1;
136 }
137
138 Schedule(clock_->Now() + tx_port_->TimeUntilAvailable());
139 }
140
141 UnconstrainedPortInterface* GetRxPort() override {
142 return static_cast<UnconstrainedPortInterface*>(&rx_port_);
143 }
144
145 void SetTxPort(ConstrainedPortInterface* port) override { tx_port_ = port; }
146
147 CounterPort* counter() { return &rx_port_; }
148
149 inline QuicByteCount bytes_transmitted() const { return bytes_transmitted_; }
150 inline QuicPacketCount packets_transmitted() const {
151 return packets_transmitted_;
152 }
153
154 void Pause() { Unschedule(); }
155 void Resume() { Schedule(clock_->Now()); }
156
157 private:
158 QuicByteCount packet_size_;
vasilvvc48c8712019-03-11 13:38:16 -0700159 std::string destination_;
QUICHE teama6ef0a62019-03-07 20:34:33 -0500160
161 ConstrainedPortInterface* tx_port_;
162 CounterPort rx_port_;
163
164 QuicByteCount bytes_transmitted_;
165 QuicPacketCount packets_transmitted_;
166};
167
168// Saturate a symmetric link and verify that the number of packets sent and
169// received is correct.
170TEST_F(SimulatorTest, DirectLinkSaturation) {
171 Simulator simulator;
172 LinkSaturator saturator_a(&simulator, "Saturator A", 1000, "Saturator B");
173 LinkSaturator saturator_b(&simulator, "Saturator B", 100, "Saturator A");
174 SymmetricLink link(&saturator_a, &saturator_b,
175 QuicBandwidth::FromKBytesPerSecond(1000),
176 QuicTime::Delta::FromMilliseconds(100) +
177 QuicTime::Delta::FromMicroseconds(1));
178
179 const QuicTime start_time = simulator.GetClock()->Now();
180 const QuicTime after_first_50_ms =
181 start_time + QuicTime::Delta::FromMilliseconds(50);
182 simulator.RunUntil([&simulator, after_first_50_ms]() {
183 return simulator.GetClock()->Now() >= after_first_50_ms;
184 });
185 EXPECT_LE(1000u * 50u, saturator_a.bytes_transmitted());
186 EXPECT_GE(1000u * 51u, saturator_a.bytes_transmitted());
187 EXPECT_LE(1000u * 50u, saturator_b.bytes_transmitted());
188 EXPECT_GE(1000u * 51u, saturator_b.bytes_transmitted());
189 EXPECT_LE(50u, saturator_a.packets_transmitted());
190 EXPECT_GE(51u, saturator_a.packets_transmitted());
191 EXPECT_LE(500u, saturator_b.packets_transmitted());
192 EXPECT_GE(501u, saturator_b.packets_transmitted());
193 EXPECT_EQ(0u, saturator_a.counter()->bytes());
194 EXPECT_EQ(0u, saturator_b.counter()->bytes());
195
196 simulator.RunUntil([&saturator_a, &saturator_b]() {
197 if (saturator_a.counter()->packets() > 1000 ||
198 saturator_b.counter()->packets() > 100) {
199 ADD_FAILURE() << "The simulation did not arrive at the expected "
200 "termination contidition. Saturator A counter: "
201 << saturator_a.counter()->packets()
202 << ", saturator B counter: "
203 << saturator_b.counter()->packets();
204 return true;
205 }
206
207 return saturator_a.counter()->packets() == 1000 &&
208 saturator_b.counter()->packets() == 100;
209 });
210 EXPECT_EQ(201u, saturator_a.packets_transmitted());
211 EXPECT_EQ(2001u, saturator_b.packets_transmitted());
212 EXPECT_EQ(201u * 1000, saturator_a.bytes_transmitted());
213 EXPECT_EQ(2001u * 100, saturator_b.bytes_transmitted());
214
215 EXPECT_EQ(1000u,
216 saturator_a.counter()->CountPacketsForDestination("Saturator A"));
217 EXPECT_EQ(100u,
218 saturator_b.counter()->CountPacketsForDestination("Saturator B"));
219 EXPECT_EQ(0u,
220 saturator_a.counter()->CountPacketsForDestination("Saturator B"));
221 EXPECT_EQ(0u,
222 saturator_b.counter()->CountPacketsForDestination("Saturator A"));
223
224 const QuicTime end_time = simulator.GetClock()->Now();
225 const QuicBandwidth observed_bandwidth = QuicBandwidth::FromBytesAndTimeDelta(
226 saturator_a.bytes_transmitted(), end_time - start_time);
wub9343d702019-05-02 17:12:56 -0700227 EXPECT_APPROX_EQ(link.bandwidth(), observed_bandwidth, 0.01f);
QUICHE teama6ef0a62019-03-07 20:34:33 -0500228}
229
230// Accepts packets and stores them internally.
231class PacketAcceptor : public ConstrainedPortInterface {
232 public:
233 void AcceptPacket(std::unique_ptr<Packet> packet) override {
234 packets_.emplace_back(std::move(packet));
235 }
236
237 QuicTime::Delta TimeUntilAvailable() override {
238 return QuicTime::Delta::Zero();
239 }
240
241 std::vector<std::unique_ptr<Packet>>* packets() { return &packets_; }
242
243 private:
244 std::vector<std::unique_ptr<Packet>> packets_;
245};
246
247// Ensure the queue behaves correctly with accepting packets.
248TEST_F(SimulatorTest, Queue) {
249 Simulator simulator;
250 Queue queue(&simulator, "Queue", 1000);
251 PacketAcceptor acceptor;
252 queue.set_tx_port(&acceptor);
253
254 EXPECT_EQ(0u, queue.bytes_queued());
255 EXPECT_EQ(0u, queue.packets_queued());
256 EXPECT_EQ(0u, acceptor.packets()->size());
257
258 auto first_packet = QuicMakeUnique<Packet>();
259 first_packet->size = 600;
260 queue.AcceptPacket(std::move(first_packet));
261 EXPECT_EQ(600u, queue.bytes_queued());
262 EXPECT_EQ(1u, queue.packets_queued());
263 EXPECT_EQ(0u, acceptor.packets()->size());
264
265 // The second packet does not fit and is dropped.
266 auto second_packet = QuicMakeUnique<Packet>();
267 second_packet->size = 500;
268 queue.AcceptPacket(std::move(second_packet));
269 EXPECT_EQ(600u, queue.bytes_queued());
270 EXPECT_EQ(1u, queue.packets_queued());
271 EXPECT_EQ(0u, acceptor.packets()->size());
272
273 auto third_packet = QuicMakeUnique<Packet>();
274 third_packet->size = 400;
275 queue.AcceptPacket(std::move(third_packet));
276 EXPECT_EQ(1000u, queue.bytes_queued());
277 EXPECT_EQ(2u, queue.packets_queued());
278 EXPECT_EQ(0u, acceptor.packets()->size());
279
280 // Run until there is nothing scheduled, so that the queue can deplete.
281 simulator.RunUntil([]() { return false; });
282 EXPECT_EQ(0u, queue.bytes_queued());
283 EXPECT_EQ(0u, queue.packets_queued());
284 ASSERT_EQ(2u, acceptor.packets()->size());
285 EXPECT_EQ(600u, acceptor.packets()->at(0)->size);
286 EXPECT_EQ(400u, acceptor.packets()->at(1)->size);
287}
288
289// Simulate a situation where the bottleneck link is 10 times slower than the
290// uplink, and they are separated by a queue.
291TEST_F(SimulatorTest, QueueBottleneck) {
292 const QuicBandwidth local_bandwidth =
293 QuicBandwidth::FromKBytesPerSecond(1000);
294 const QuicBandwidth bottleneck_bandwidth = 0.1f * local_bandwidth;
295 const QuicTime::Delta local_propagation_delay =
296 QuicTime::Delta::FromMilliseconds(1);
297 const QuicTime::Delta bottleneck_propagation_delay =
298 QuicTime::Delta::FromMilliseconds(20);
299 const QuicByteCount bdp =
300 bottleneck_bandwidth *
301 (local_propagation_delay + bottleneck_propagation_delay);
302
303 Simulator simulator;
304 LinkSaturator saturator(&simulator, "Saturator", 1000, "Counter");
305 ASSERT_GE(bdp, 1000u);
306 Queue queue(&simulator, "Queue", bdp);
307 CounterPort counter;
308
309 OneWayLink local_link(&simulator, "Local link", &queue, local_bandwidth,
310 local_propagation_delay);
311 OneWayLink bottleneck_link(&simulator, "Bottleneck link", &counter,
312 bottleneck_bandwidth,
313 bottleneck_propagation_delay);
314 saturator.SetTxPort(&local_link);
315 queue.set_tx_port(&bottleneck_link);
316
317 static const QuicPacketCount packets_received = 1000;
318 simulator.RunUntil(
319 [&counter]() { return counter.packets() == packets_received; });
320 const double loss_ratio = 1 - static_cast<double>(packets_received) /
321 saturator.packets_transmitted();
322 EXPECT_NEAR(loss_ratio, 0.9, 0.001);
323}
324
325// Verify that the queue of exactly one packet allows the transmission to
326// actually go through.
327TEST_F(SimulatorTest, OnePacketQueue) {
328 const QuicBandwidth local_bandwidth =
329 QuicBandwidth::FromKBytesPerSecond(1000);
330 const QuicBandwidth bottleneck_bandwidth = 0.1f * local_bandwidth;
331 const QuicTime::Delta local_propagation_delay =
332 QuicTime::Delta::FromMilliseconds(1);
333 const QuicTime::Delta bottleneck_propagation_delay =
334 QuicTime::Delta::FromMilliseconds(20);
335
336 Simulator simulator;
337 LinkSaturator saturator(&simulator, "Saturator", 1000, "Counter");
338 Queue queue(&simulator, "Queue", 1000);
339 CounterPort counter;
340
341 OneWayLink local_link(&simulator, "Local link", &queue, local_bandwidth,
342 local_propagation_delay);
343 OneWayLink bottleneck_link(&simulator, "Bottleneck link", &counter,
344 bottleneck_bandwidth,
345 bottleneck_propagation_delay);
346 saturator.SetTxPort(&local_link);
347 queue.set_tx_port(&bottleneck_link);
348
349 static const QuicPacketCount packets_received = 10;
350 // The deadline here is to prevent this tests from looping infinitely in case
351 // the packets never reach the receiver.
352 const QuicTime deadline =
353 simulator.GetClock()->Now() + QuicTime::Delta::FromSeconds(10);
354 simulator.RunUntil([&simulator, &counter, deadline]() {
355 return counter.packets() == packets_received ||
356 simulator.GetClock()->Now() > deadline;
357 });
358 ASSERT_EQ(packets_received, counter.packets());
359}
360
361// Simulate a network where three endpoints are connected to a switch and they
362// are sending traffic in circle (1 -> 2, 2 -> 3, 3 -> 1).
363TEST_F(SimulatorTest, SwitchedNetwork) {
364 const QuicBandwidth bandwidth = QuicBandwidth::FromBytesPerSecond(10000);
365 const QuicTime::Delta base_propagation_delay =
366 QuicTime::Delta::FromMilliseconds(50);
367
368 Simulator simulator;
369 LinkSaturator saturator1(&simulator, "Saturator 1", 1000, "Saturator 2");
370 LinkSaturator saturator2(&simulator, "Saturator 2", 1000, "Saturator 3");
371 LinkSaturator saturator3(&simulator, "Saturator 3", 1000, "Saturator 1");
372 Switch network_switch(&simulator, "Switch", 8,
373 bandwidth * base_propagation_delay * 10);
374
375 // For determinicity, make it so that the first packet will arrive from
376 // Saturator 1, then from Saturator 2, and then from Saturator 3.
377 SymmetricLink link1(&saturator1, network_switch.port(1), bandwidth,
378 base_propagation_delay);
379 SymmetricLink link2(&saturator2, network_switch.port(2), bandwidth,
380 base_propagation_delay * 2);
381 SymmetricLink link3(&saturator3, network_switch.port(3), bandwidth,
382 base_propagation_delay * 3);
383
384 const QuicTime start_time = simulator.GetClock()->Now();
385 static const QuicPacketCount bytes_received = 64 * 1000;
386 simulator.RunUntil([&saturator1]() {
387 return saturator1.counter()->bytes() >= bytes_received;
388 });
389 const QuicTime end_time = simulator.GetClock()->Now();
390
391 const QuicBandwidth observed_bandwidth = QuicBandwidth::FromBytesAndTimeDelta(
392 bytes_received, end_time - start_time);
393 const double bandwidth_ratio =
394 static_cast<double>(observed_bandwidth.ToBitsPerSecond()) /
395 bandwidth.ToBitsPerSecond();
396 EXPECT_NEAR(1, bandwidth_ratio, 0.1);
397
398 const double normalized_received_packets_for_saturator_2 =
399 static_cast<double>(saturator2.counter()->packets()) /
400 saturator1.counter()->packets();
401 const double normalized_received_packets_for_saturator_3 =
402 static_cast<double>(saturator3.counter()->packets()) /
403 saturator1.counter()->packets();
404 EXPECT_NEAR(1, normalized_received_packets_for_saturator_2, 0.1);
405 EXPECT_NEAR(1, normalized_received_packets_for_saturator_3, 0.1);
406
407 // Since Saturator 1 has its packet arrive first into the switch, switch will
408 // always know how to route traffic to it.
409 EXPECT_EQ(0u,
410 saturator2.counter()->CountPacketsForDestination("Saturator 1"));
411 EXPECT_EQ(0u,
412 saturator3.counter()->CountPacketsForDestination("Saturator 1"));
413
414 // Packets from the other saturators will be broadcast at least once.
415 EXPECT_EQ(1u,
416 saturator1.counter()->CountPacketsForDestination("Saturator 2"));
417 EXPECT_EQ(1u,
418 saturator3.counter()->CountPacketsForDestination("Saturator 2"));
419 EXPECT_EQ(1u,
420 saturator1.counter()->CountPacketsForDestination("Saturator 3"));
421 EXPECT_EQ(1u,
422 saturator2.counter()->CountPacketsForDestination("Saturator 3"));
423}
424
425// Toggle an alarm on and off at the specified interval. Assumes that alarm is
426// initially set and unsets it almost immediately after the object is
427// instantiated.
428class AlarmToggler : public Actor {
429 public:
430 AlarmToggler(Simulator* simulator,
vasilvvc48c8712019-03-11 13:38:16 -0700431 std::string name,
QUICHE teama6ef0a62019-03-07 20:34:33 -0500432 QuicAlarm* alarm,
433 QuicTime::Delta interval)
434 : Actor(simulator, name),
435 alarm_(alarm),
436 interval_(interval),
437 deadline_(alarm->deadline()),
438 times_set_(0),
439 times_cancelled_(0) {
440 EXPECT_TRUE(alarm->IsSet());
441 EXPECT_GE(alarm->deadline(), clock_->Now());
442 Schedule(clock_->Now());
443 }
444
445 void Act() override {
446 if (deadline_ <= clock_->Now()) {
447 return;
448 }
449
450 if (alarm_->IsSet()) {
451 alarm_->Cancel();
452 times_cancelled_++;
453 } else {
454 alarm_->Set(deadline_);
455 times_set_++;
456 }
457
458 Schedule(clock_->Now() + interval_);
459 }
460
461 inline int times_set() { return times_set_; }
462 inline int times_cancelled() { return times_cancelled_; }
463
464 private:
465 QuicAlarm* alarm_;
466 QuicTime::Delta interval_;
467 QuicTime deadline_;
468
469 // Counts the number of times the alarm was set.
470 int times_set_;
471 // Counts the number of times the alarm was cancelled.
472 int times_cancelled_;
473};
474
475// Counts the number of times an alarm has fired.
476class CounterDelegate : public QuicAlarm::Delegate {
477 public:
478 explicit CounterDelegate(size_t* counter) : counter_(counter) {}
479
480 void OnAlarm() override { *counter_ += 1; }
481
482 private:
483 size_t* counter_;
484};
485
486// Verifies that the alarms work correctly, even when they are repeatedly
487// toggled.
488TEST_F(SimulatorTest, Alarms) {
489 Simulator simulator;
490 QuicAlarmFactory* alarm_factory = simulator.GetAlarmFactory();
491
492 size_t fast_alarm_counter = 0;
493 size_t slow_alarm_counter = 0;
494 std::unique_ptr<QuicAlarm> alarm_fast(
495 alarm_factory->CreateAlarm(new CounterDelegate(&fast_alarm_counter)));
496 std::unique_ptr<QuicAlarm> alarm_slow(
497 alarm_factory->CreateAlarm(new CounterDelegate(&slow_alarm_counter)));
498
499 const QuicTime start_time = simulator.GetClock()->Now();
500 alarm_fast->Set(start_time + QuicTime::Delta::FromMilliseconds(100));
501 alarm_slow->Set(start_time + QuicTime::Delta::FromMilliseconds(750));
502 AlarmToggler toggler(&simulator, "Toggler", alarm_slow.get(),
503 QuicTime::Delta::FromMilliseconds(100));
504
505 const QuicTime end_time =
506 start_time + QuicTime::Delta::FromMilliseconds(1000);
507 EXPECT_FALSE(simulator.RunUntil([&simulator, end_time]() {
508 return simulator.GetClock()->Now() >= end_time;
509 }));
510 EXPECT_EQ(1u, slow_alarm_counter);
511 EXPECT_EQ(1u, fast_alarm_counter);
512
513 EXPECT_EQ(4, toggler.times_set());
514 EXPECT_EQ(4, toggler.times_cancelled());
515}
516
517// Verifies that a cancelled alarm is never fired.
518TEST_F(SimulatorTest, AlarmCancelling) {
519 Simulator simulator;
520 QuicAlarmFactory* alarm_factory = simulator.GetAlarmFactory();
521
522 size_t alarm_counter = 0;
523 std::unique_ptr<QuicAlarm> alarm(
524 alarm_factory->CreateAlarm(new CounterDelegate(&alarm_counter)));
525
526 const QuicTime start_time = simulator.GetClock()->Now();
527 const QuicTime alarm_at = start_time + QuicTime::Delta::FromMilliseconds(300);
528 const QuicTime end_time = start_time + QuicTime::Delta::FromMilliseconds(400);
529
530 alarm->Set(alarm_at);
531 alarm->Cancel();
532 EXPECT_FALSE(alarm->IsSet());
533
534 EXPECT_FALSE(simulator.RunUntil([&simulator, end_time]() {
535 return simulator.GetClock()->Now() >= end_time;
536 }));
537
538 EXPECT_FALSE(alarm->IsSet());
539 EXPECT_EQ(0u, alarm_counter);
540}
541
542// Verifies that alarms can be scheduled into the past.
543TEST_F(SimulatorTest, AlarmInPast) {
544 Simulator simulator;
545 QuicAlarmFactory* alarm_factory = simulator.GetAlarmFactory();
546
547 size_t alarm_counter = 0;
548 std::unique_ptr<QuicAlarm> alarm(
549 alarm_factory->CreateAlarm(new CounterDelegate(&alarm_counter)));
550
551 const QuicTime start_time = simulator.GetClock()->Now();
552 simulator.RunFor(QuicTime::Delta::FromMilliseconds(400));
553
554 alarm->Set(start_time);
555 simulator.RunFor(QuicTime::Delta::FromMilliseconds(1));
556 EXPECT_FALSE(alarm->IsSet());
557 EXPECT_EQ(1u, alarm_counter);
558}
559
560// Tests Simulator::RunUntilOrTimeout() interface.
561TEST_F(SimulatorTest, RunUntilOrTimeout) {
562 Simulator simulator;
563 bool simulation_result;
564
565 // Count the number of seconds since the beginning of the simulation.
566 Counter counter(&simulator, "counter", QuicTime::Delta::FromSeconds(1));
567
568 // Ensure that the counter reaches the value of 10 given a 20 second deadline.
569 simulation_result = simulator.RunUntilOrTimeout(
570 [&counter]() { return counter.get_value() == 10; },
571 QuicTime::Delta::FromSeconds(20));
572 ASSERT_TRUE(simulation_result);
573
574 // Ensure that the counter will not reach the value of 100 given that the
575 // starting value is 10 and the deadline is 20 seconds.
576 simulation_result = simulator.RunUntilOrTimeout(
577 [&counter]() { return counter.get_value() == 100; },
578 QuicTime::Delta::FromSeconds(20));
579 ASSERT_FALSE(simulation_result);
580}
581
582// Tests Simulator::RunFor() interface.
583TEST_F(SimulatorTest, RunFor) {
584 Simulator simulator;
585
586 Counter counter(&simulator, "counter", QuicTime::Delta::FromSeconds(3));
587
588 simulator.RunFor(QuicTime::Delta::FromSeconds(100));
589
590 EXPECT_EQ(33, counter.get_value());
591}
592
593class MockPacketFilter : public PacketFilter {
594 public:
vasilvvc48c8712019-03-11 13:38:16 -0700595 MockPacketFilter(Simulator* simulator, std::string name, Endpoint* endpoint)
QUICHE teama6ef0a62019-03-07 20:34:33 -0500596 : PacketFilter(simulator, name, endpoint) {}
597 MOCK_METHOD1(FilterPacket, bool(const Packet&));
598};
599
600// Set up two trivial packet filters, one allowing any packets, and one dropping
601// all of them.
602TEST_F(SimulatorTest, PacketFilter) {
603 const QuicBandwidth bandwidth =
604 QuicBandwidth::FromBytesPerSecond(1024 * 1024);
605 const QuicTime::Delta base_propagation_delay =
606 QuicTime::Delta::FromMilliseconds(5);
607
608 Simulator simulator;
609 LinkSaturator saturator_a(&simulator, "Saturator A", 1000, "Saturator B");
610 LinkSaturator saturator_b(&simulator, "Saturator B", 1000, "Saturator A");
611
612 // Attach packets to the switch to create a delay between the point at which
613 // the packet is generated and the point at which it is filtered. Note that
614 // if the saturators were connected directly, the link would be always
615 // available for the endpoint which has all of its packets dropped, resulting
616 // in saturator looping infinitely.
617 Switch network_switch(&simulator, "Switch", 8,
618 bandwidth * base_propagation_delay * 10);
619 StrictMock<MockPacketFilter> a_to_b_filter(&simulator, "A -> B filter",
620 network_switch.port(1));
621 StrictMock<MockPacketFilter> b_to_a_filter(&simulator, "B -> A filter",
622 network_switch.port(2));
623 SymmetricLink link_a(&a_to_b_filter, &saturator_b, bandwidth,
624 base_propagation_delay);
625 SymmetricLink link_b(&b_to_a_filter, &saturator_a, bandwidth,
626 base_propagation_delay);
627
628 // Allow packets from A to B, but not from B to A.
629 EXPECT_CALL(a_to_b_filter, FilterPacket(_)).WillRepeatedly(Return(true));
630 EXPECT_CALL(b_to_a_filter, FilterPacket(_)).WillRepeatedly(Return(false));
631
632 // Run the simulation for a while, and expect that only B will receive any
633 // packets.
634 simulator.RunFor(QuicTime::Delta::FromSeconds(10));
635 EXPECT_GE(saturator_b.counter()->packets(), 1u);
636 EXPECT_EQ(saturator_a.counter()->packets(), 0u);
637}
638
639// Set up a traffic policer in one direction that throttles at 25% of link
640// bandwidth, and put two link saturators at each endpoint.
641TEST_F(SimulatorTest, TrafficPolicer) {
642 const QuicBandwidth bandwidth =
643 QuicBandwidth::FromBytesPerSecond(1024 * 1024);
644 const QuicTime::Delta base_propagation_delay =
645 QuicTime::Delta::FromMilliseconds(5);
646 const QuicTime::Delta timeout = QuicTime::Delta::FromSeconds(10);
647
648 Simulator simulator;
649 LinkSaturator saturator1(&simulator, "Saturator 1", 1000, "Saturator 2");
650 LinkSaturator saturator2(&simulator, "Saturator 2", 1000, "Saturator 1");
651 Switch network_switch(&simulator, "Switch", 8,
652 bandwidth * base_propagation_delay * 10);
653
654 static const QuicByteCount initial_burst = 1000 * 10;
655 static const QuicByteCount max_bucket_size = 1000 * 100;
656 static const QuicBandwidth target_bandwidth = bandwidth * 0.25;
657 TrafficPolicer policer(&simulator, "Policer", initial_burst, max_bucket_size,
658 target_bandwidth, network_switch.port(2));
659
660 SymmetricLink link1(&saturator1, network_switch.port(1), bandwidth,
661 base_propagation_delay);
662 SymmetricLink link2(&saturator2, &policer, bandwidth, base_propagation_delay);
663
664 // Ensure the initial burst passes without being dropped at all.
665 bool simulator_result = simulator.RunUntilOrTimeout(
666 [&saturator1]() {
667 return saturator1.bytes_transmitted() == initial_burst;
668 },
669 timeout);
670 ASSERT_TRUE(simulator_result);
671 saturator1.Pause();
672 simulator_result = simulator.RunUntilOrTimeout(
673 [&saturator2]() {
674 return saturator2.counter()->bytes() == initial_burst;
675 },
676 timeout);
677 ASSERT_TRUE(simulator_result);
678 saturator1.Resume();
679
680 // Run for some time so that the initial burst is not visible.
681 const QuicTime::Delta simulation_time = QuicTime::Delta::FromSeconds(10);
682 simulator.RunFor(simulation_time);
683
684 // Ensure we've transmitted the amount of data we expected.
685 for (auto* saturator : {&saturator1, &saturator2}) {
wub9343d702019-05-02 17:12:56 -0700686 EXPECT_APPROX_EQ(bandwidth * simulation_time,
687 saturator->bytes_transmitted(), 0.01f);
QUICHE teama6ef0a62019-03-07 20:34:33 -0500688 }
689
690 // Check that only one direction is throttled.
wub9343d702019-05-02 17:12:56 -0700691 EXPECT_APPROX_EQ(saturator1.bytes_transmitted() / 4,
692 saturator2.counter()->bytes(), 0.1f);
693 EXPECT_APPROX_EQ(saturator2.bytes_transmitted(),
694 saturator1.counter()->bytes(), 0.1f);
QUICHE teama6ef0a62019-03-07 20:34:33 -0500695}
696
697// Ensure that a larger burst is allowed when the policed saturator exits
698// quiescence.
699TEST_F(SimulatorTest, TrafficPolicerBurst) {
700 const QuicBandwidth bandwidth =
701 QuicBandwidth::FromBytesPerSecond(1024 * 1024);
702 const QuicTime::Delta base_propagation_delay =
703 QuicTime::Delta::FromMilliseconds(5);
704 const QuicTime::Delta timeout = QuicTime::Delta::FromSeconds(10);
705
706 Simulator simulator;
707 LinkSaturator saturator1(&simulator, "Saturator 1", 1000, "Saturator 2");
708 LinkSaturator saturator2(&simulator, "Saturator 2", 1000, "Saturator 1");
709 Switch network_switch(&simulator, "Switch", 8,
710 bandwidth * base_propagation_delay * 10);
711
712 const QuicByteCount initial_burst = 1000 * 10;
713 const QuicByteCount max_bucket_size = 1000 * 100;
714 const QuicBandwidth target_bandwidth = bandwidth * 0.25;
715 TrafficPolicer policer(&simulator, "Policer", initial_burst, max_bucket_size,
716 target_bandwidth, network_switch.port(2));
717
718 SymmetricLink link1(&saturator1, network_switch.port(1), bandwidth,
719 base_propagation_delay);
720 SymmetricLink link2(&saturator2, &policer, bandwidth, base_propagation_delay);
721
722 // Ensure at least one packet is sent on each side.
723 bool simulator_result = simulator.RunUntilOrTimeout(
724 [&saturator1, &saturator2]() {
725 return saturator1.packets_transmitted() > 0 &&
726 saturator2.packets_transmitted() > 0;
727 },
728 timeout);
729 ASSERT_TRUE(simulator_result);
730
731 // Wait until the bucket fills up.
732 saturator1.Pause();
733 saturator2.Pause();
734 simulator.RunFor(1.5f * target_bandwidth.TransferTime(max_bucket_size));
735
736 // Send a burst.
737 saturator1.Resume();
738 simulator.RunFor(bandwidth.TransferTime(max_bucket_size));
739 saturator1.Pause();
740 simulator.RunFor(2 * base_propagation_delay);
741
742 // Expect the burst to pass without losses.
wub9343d702019-05-02 17:12:56 -0700743 EXPECT_APPROX_EQ(saturator1.bytes_transmitted(),
744 saturator2.counter()->bytes(), 0.1f);
QUICHE teama6ef0a62019-03-07 20:34:33 -0500745
746 // Expect subsequent traffic to be policed.
747 saturator1.Resume();
748 simulator.RunFor(QuicTime::Delta::FromSeconds(10));
wub9343d702019-05-02 17:12:56 -0700749 EXPECT_APPROX_EQ(saturator1.bytes_transmitted() / 4,
750 saturator2.counter()->bytes(), 0.1f);
QUICHE teama6ef0a62019-03-07 20:34:33 -0500751}
752
753// Test that the packet aggregation support in queues work.
754TEST_F(SimulatorTest, PacketAggregation) {
755 // Model network where the delays are dominated by transfer delay.
756 const QuicBandwidth bandwidth = QuicBandwidth::FromBytesPerSecond(1000);
757 const QuicTime::Delta base_propagation_delay =
758 QuicTime::Delta::FromMicroseconds(1);
759 const QuicByteCount aggregation_threshold = 1000;
760 const QuicTime::Delta aggregation_timeout = QuicTime::Delta::FromSeconds(30);
761
762 Simulator simulator;
763 LinkSaturator saturator1(&simulator, "Saturator 1", 10, "Saturator 2");
764 LinkSaturator saturator2(&simulator, "Saturator 2", 10, "Saturator 1");
765 Switch network_switch(&simulator, "Switch", 8, 10 * aggregation_threshold);
766
767 // Make links with asymmetric propagation delay so that Saturator 2 only
768 // receives packets addressed to it.
769 SymmetricLink link1(&saturator1, network_switch.port(1), bandwidth,
770 base_propagation_delay);
771 SymmetricLink link2(&saturator2, network_switch.port(2), bandwidth,
772 2 * base_propagation_delay);
773
774 // Enable aggregation in 1 -> 2 direction.
775 Queue* queue = network_switch.port_queue(2);
776 queue->EnableAggregation(aggregation_threshold, aggregation_timeout);
777
778 // Enable aggregation in 2 -> 1 direction in a way that all packets are larger
779 // than the threshold, so that aggregation is effectively a no-op.
780 network_switch.port_queue(1)->EnableAggregation(5, aggregation_timeout);
781
782 // Fill up the aggregation buffer up to 90% (900 bytes).
783 simulator.RunFor(0.9 * bandwidth.TransferTime(aggregation_threshold));
784 EXPECT_EQ(0u, saturator2.counter()->bytes());
785
786 // Stop sending, ensure that given a timespan much shorter than timeout, the
787 // packets remain in the queue.
788 saturator1.Pause();
789 saturator2.Pause();
790 simulator.RunFor(QuicTime::Delta::FromSeconds(10));
791 EXPECT_EQ(0u, saturator2.counter()->bytes());
792 EXPECT_EQ(900u, queue->bytes_queued());
793
794 // Ensure that all packets have reached the saturator not affected by
795 // aggregation. Here, 10 extra bytes account for a misrouted packet in the
796 // beginning.
797 EXPECT_EQ(910u, saturator1.counter()->bytes());
798
799 // Send 500 more bytes. Since the aggregation threshold is 1000 bytes, and
800 // queue already has 900 bytes, 1000 bytes will be send and 400 will be in the
801 // queue.
802 saturator1.Resume();
803 simulator.RunFor(0.5 * bandwidth.TransferTime(aggregation_threshold));
804 saturator1.Pause();
805 simulator.RunFor(QuicTime::Delta::FromSeconds(10));
806 EXPECT_EQ(1000u, saturator2.counter()->bytes());
807 EXPECT_EQ(400u, queue->bytes_queued());
808
809 // Actually time out, and cause all of the data to be received.
810 simulator.RunFor(aggregation_timeout);
811 EXPECT_EQ(1400u, saturator2.counter()->bytes());
812 EXPECT_EQ(0u, queue->bytes_queued());
813
814 // Run saturator for a longer time, to ensure that the logic to cancel and
815 // reset alarms works correctly.
816 saturator1.Resume();
817 simulator.RunFor(5.5 * bandwidth.TransferTime(aggregation_threshold));
818 saturator1.Pause();
819 simulator.RunFor(QuicTime::Delta::FromSeconds(10));
820 EXPECT_EQ(6400u, saturator2.counter()->bytes());
821 EXPECT_EQ(500u, queue->bytes_queued());
822
823 // Time out again.
824 simulator.RunFor(aggregation_timeout);
825 EXPECT_EQ(6900u, saturator2.counter()->bytes());
826 EXPECT_EQ(0u, queue->bytes_queued());
827}
828
829} // namespace simulator
830} // namespace quic