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