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 #ifndef QUICHE_QUIC_TEST_TOOLS_SIMULATOR_LINK_H_ 6 #define QUICHE_QUIC_TEST_TOOLS_SIMULATOR_LINK_H_ 7 8 #include <utility> 9 10 #include "quiche/quic/core/crypto/quic_random.h" 11 #include "quiche/quic/core/quic_bandwidth.h" 12 #include "quiche/quic/test_tools/simulator/actor.h" 13 #include "quiche/quic/test_tools/simulator/port.h" 14 #include "quiche/common/quiche_circular_deque.h" 15 16 namespace quic { 17 namespace simulator { 18 19 // A reliable simplex link between two endpoints with constrained bandwidth. A 20 // few microseconds of random delay are added for every packet to avoid 21 // synchronization issues. 22 class OneWayLink : public Actor, public ConstrainedPortInterface { 23 public: 24 OneWayLink(Simulator* simulator, std::string name, 25 UnconstrainedPortInterface* sink, QuicBandwidth bandwidth, 26 QuicTime::Delta propagation_delay); 27 OneWayLink(const OneWayLink&) = delete; 28 OneWayLink& operator=(const OneWayLink&) = delete; 29 ~OneWayLink() override; 30 31 void AcceptPacket(std::unique_ptr<Packet> packet) override; 32 QuicTime::Delta TimeUntilAvailable() override; 33 void Act() override; 34 bandwidth()35 QuicBandwidth bandwidth() const { return bandwidth_; } set_bandwidth(QuicBandwidth new_bandwidth)36 void set_bandwidth(QuicBandwidth new_bandwidth) { 37 bandwidth_ = new_bandwidth; 38 } 39 40 protected: 41 // Get the value of a random delay imposed on each packet. By default, this 42 // is a short random delay in order to avoid artifical synchronization 43 // artifacts during the simulation. Subclasses may override this behavior 44 // (for example, to provide a random component of delay). 45 virtual QuicTime::Delta GetRandomDelay(QuicTime::Delta transfer_time); 46 47 private: 48 struct QueuedPacket { 49 std::unique_ptr<Packet> packet; 50 QuicTime dequeue_time; 51 52 QueuedPacket(std::unique_ptr<Packet> packet, QuicTime dequeue_time); 53 QueuedPacket(QueuedPacket&& other); 54 ~QueuedPacket(); 55 }; 56 57 // Schedule the next packet to be egressed out of the link if there are 58 // packets on the link. 59 void ScheduleNextPacketDeparture(); 60 61 UnconstrainedPortInterface* sink_; 62 quiche::QuicheCircularDeque<QueuedPacket> packets_in_transit_; 63 64 QuicBandwidth bandwidth_; 65 const QuicTime::Delta propagation_delay_; 66 67 QuicTime next_write_at_; 68 }; 69 70 // A full-duplex link between two endpoints, functionally equivalent to two 71 // OneWayLink objects tied together. 72 class SymmetricLink { 73 public: 74 SymmetricLink(Simulator* simulator, std::string name, 75 UnconstrainedPortInterface* sink_a, 76 UnconstrainedPortInterface* sink_b, QuicBandwidth bandwidth, 77 QuicTime::Delta propagation_delay); 78 SymmetricLink(Endpoint* endpoint_a, Endpoint* endpoint_b, 79 QuicBandwidth bandwidth, QuicTime::Delta propagation_delay); 80 SymmetricLink(const SymmetricLink&) = delete; 81 SymmetricLink& operator=(const SymmetricLink&) = delete; 82 bandwidth()83 QuicBandwidth bandwidth() { return a_to_b_link_.bandwidth(); } set_bandwidth(QuicBandwidth new_bandwidth)84 void set_bandwidth(QuicBandwidth new_bandwidth) { 85 a_to_b_link_.set_bandwidth(new_bandwidth); 86 b_to_a_link_.set_bandwidth(new_bandwidth); 87 } 88 89 private: 90 OneWayLink a_to_b_link_; 91 OneWayLink b_to_a_link_; 92 }; 93 94 } // namespace simulator 95 } // namespace quic 96 97 #endif // QUICHE_QUIC_TEST_TOOLS_SIMULATOR_LINK_H_ 98