| # QUIC network simulator | 
 |  | 
 | This directory contains a discrete event network simulator which QUIC code uses | 
 | for testing congestion control and other transmission control code that requires | 
 | a network simulation for tests on QuicConnection level of abstraction. | 
 |  | 
 | ## Actors | 
 |  | 
 | The core of the simulator is the Simulator class, which maintains a virtual | 
 | clock and an event queue. Any object in a simulation that needs to schedule | 
 | events has to subclass Actor. Subclassing Actor involves: | 
 |  | 
 | 1.  Calling the `Actor::Actor(Simulator*, std::string)` constructor to establish | 
 |     the name of the object and the simulator it is associated with. | 
 | 2.  Calling `Schedule(QuicTime)` to schedule the time at which `Act()` method is | 
 |     called. `Schedule` will only cause the object to be rescheduled if the time | 
 |     for which it is currently scheduled is later than the new time. | 
 | 3.  Implementing `Act()` method with the relevant logic. The actor will be | 
 |     removed from the event queue right before `Act()` is called. | 
 |  | 
 | Here is a simple example of an object that outputs simulation time into the log | 
 | every 100 ms. | 
 |  | 
 | ```c++ | 
 | class LogClock : public Actor { | 
 |  public: | 
 |   LogClock(Simulator* simulator, std::string name) : Actor(simulator, name) { | 
 |     Schedule(clock_->Now()); | 
 |   } | 
 |   ~LogClock() override {} | 
 |  | 
 |   void Act() override { | 
 |     QUIC_LOG(INFO) << "The current time is " | 
 |                    << clock_->Now().ToDebuggingValue(); | 
 |     Schedule(clock_->Now() + QuicTime::Delta::FromMilliseconds(100)); | 
 |   } | 
 | }; | 
 | ``` | 
 |  | 
 | A QuicAlarm object can be used to schedule events in the simulation using | 
 | `Simulator::GetAlarmFactory()`. | 
 |  | 
 | ## Ports | 
 |  | 
 | The simulated network transfers packets, which are modelled as an instance of | 
 | struct `Packet`. A packet consists of source and destination address (which are | 
 | just plain strings), a transmission timestamp and the UDP-layer payload. | 
 |  | 
 | The simulation uses the push model: any object that wishes to transfer a packet | 
 | to another component in the simulation has to explicitly do it itself. Any | 
 | object that can accept a packet is called a *port*. There are two types of | 
 | ports: unconstrained ports, which can always accept packets, and constrained | 
 | ports, which signal when they can accept a new packet. | 
 |  | 
 | An endpoint is an object that is connected to the network and can both receive | 
 | and send packets. In our model, the endpoint always receives packets as an | 
 | unconstrained port (*RX port*), and always writes packets to a constrained port | 
 | (*TX port*). | 
 |  | 
 | ## Links | 
 |  | 
 | The `SymmetricLink` class models a symmetric duplex links with finite bandwidth | 
 | and propagation delay. It consists of a pair of identical `OneWayLink`s, which | 
 | accept packets as a constrained port (where constrain comes from the finiteness | 
 | of bandwidth) and outputs them into an unconstrained port. Two endpoints | 
 | connected via a `SymmetricLink` look like this: | 
 |  | 
 | ```none | 
 |  Endpoint A                                                 Endpoint B | 
 | +-----------+                 SymmetricLink                +-----------+ | 
 | |           |       +------------------------------+       |           | | 
 | |      +---------+  |  +------------------------+  |  +---------+      | | 
 | |      | RX port <-----|       OneWayLink      *<-----| TX port |      | | 
 | |      +---------+  |  +------------------------+  |  +---------+      | | 
 | |           |       |                              |       |           | | 
 | |      +---------+  |  +------------------------+  |  +---------+      | | 
 | |      | TX port |----->*      OneWayLink       |-----> RX port |      | | 
 | |      +---------+  |  +------------------------+  |  +---------+      | | 
 | |           |       +------------------------------+       |           | | 
 | +-----------+                                              +-----------+ | 
 |  | 
 |                     ( -->* denotes constrained port) | 
 | ``` | 
 |  | 
 | In most common scenario, one of the endpoints is going to be a QUIC endpoint, | 
 | and another is going to be a switch port. | 
 |  | 
 | ## Other objects | 
 |  | 
 | Besides `SymmetricLink`, the simulator provides the following objects: | 
 |  | 
 | *   `Queue` allows to convert a constrained port into an unconstrained one by | 
 |     buffering packets upon arrival. The queue has a finite size, and once the | 
 |     queue is full, the packets are silently dropped. | 
 | *   `Switch` simulates a multi-port learning switch with a fixed queue for each | 
 |     output port. | 
 | *   `QuicEndpoint` allows QuicConnection to be run over the simulated network. | 
 | *   `QuicEndpointMultiplexer` allows multiple connections to share the same | 
 |     network endpoint. |