simulated_network.h (7244B)
1 /* 2 * Copyright (c) 2018 The WebRTC project authors. All Rights Reserved. 3 * 4 * Use of this source code is governed by a BSD-style license 5 * that can be found in the LICENSE file in the root of the source 6 * tree. An additional intellectual property rights grant can be found 7 * in the file PATENTS. All contributing project authors may 8 * be found in the AUTHORS file in the root of the source tree. 9 */ 10 11 #ifndef API_TEST_SIMULATED_NETWORK_H_ 12 #define API_TEST_SIMULATED_NETWORK_H_ 13 14 #include <stddef.h> 15 #include <stdint.h> 16 17 #include <functional> 18 #include <optional> 19 #include <vector> 20 21 #include "absl/functional/any_invocable.h" 22 #include "api/transport/ecn_marking.h" 23 #include "api/units/data_rate.h" 24 #include "api/units/data_size.h" 25 #include "api/units/timestamp.h" 26 27 namespace webrtc { 28 29 struct PacketInFlightInfo { 30 PacketInFlightInfo(size_t size, 31 int64_t send_time_us, 32 uint64_t packet_id, 33 EcnMarking ecn) 34 : size(size), 35 send_time_us(send_time_us), 36 packet_id(packet_id), 37 ecn(ecn) {} 38 PacketInFlightInfo(DataSize size, 39 Timestamp send_time, 40 uint64_t packet_id, 41 EcnMarking ecn) 42 : PacketInFlightInfo(size.bytes(), send_time.us(), packet_id, ecn) {} 43 PacketInFlightInfo(DataSize size, Timestamp send_time, uint64_t packet_id) 44 : PacketInFlightInfo(size.bytes(), 45 send_time.us(), 46 packet_id, 47 EcnMarking::kNotEct) {} 48 49 PacketInFlightInfo(size_t size, int64_t send_time_us, uint64_t packet_id) 50 : PacketInFlightInfo(size, send_time_us, packet_id, EcnMarking::kNotEct) { 51 } 52 53 DataSize packet_size() const { return DataSize::Bytes(size); } 54 Timestamp send_time() const { return Timestamp::Micros(send_time_us); } 55 56 size_t size; 57 int64_t send_time_us; 58 // Unique identifier for the packet in relation to other packets in flight. 59 uint64_t packet_id; 60 EcnMarking ecn; 61 }; 62 63 struct PacketDeliveryInfo { 64 static constexpr int kNotReceived = -1; 65 PacketDeliveryInfo(PacketInFlightInfo source, int64_t receive_time_us) 66 : receive_time_us(receive_time_us), 67 packet_id(source.packet_id), 68 ecn(source.ecn) {} 69 70 bool operator==(const PacketDeliveryInfo& other) const { 71 return receive_time_us == other.receive_time_us && 72 packet_id == other.packet_id; 73 } 74 75 int64_t receive_time_us; 76 uint64_t packet_id; 77 EcnMarking ecn; 78 }; 79 80 // BuiltInNetworkBehaviorConfig is a built-in network behavior configuration 81 // for built-in network behavior that will be used by WebRTC if no custom 82 // NetworkBehaviorInterface is provided. 83 struct BuiltInNetworkBehaviorConfig { 84 // Queue length in number of packets. 85 size_t queue_length_packets = 0; 86 // Delay in addition to capacity induced delay. 87 int queue_delay_ms = 0; 88 // Standard deviation of the extra delay. 89 int delay_standard_deviation_ms = 0; 90 // Link capacity. 91 DataRate link_capacity = DataRate::Infinity(); 92 // Random packet loss, range 0 to 100. 93 double loss_percent = 0.; 94 // If packets are allowed to be reordered. 95 bool allow_reordering = false; 96 // The average length of a burst of lost packets. 97 int avg_burst_loss_length = -1; 98 // Additional bytes to add to packet size. 99 int packet_overhead = 0; 100 }; 101 102 // Interface that represents a Network behaviour. 103 // 104 // It is clients of this interface responsibility to enqueue and dequeue 105 // packets (based on the estimated delivery time expressed by 106 // NextDeliveryTimeUs). 107 // 108 // To enqueue packets, call EnqueuePacket: 109 // EXPECT_TRUE(network.EnqueuePacket( 110 // PacketInFlightInfo(/*size=*/1, /*send_time_us=*/0, /*packet_id=*/1))); 111 // 112 // To know when to call DequeueDeliverablePackets to pull packets out of the 113 // network, call NextDeliveryTimeUs and schedule a task to invoke 114 // DequeueDeliverablePackets (if not already scheduled). 115 // 116 // DequeueDeliverablePackets will return a vector of delivered packets, but this 117 // vector can be empty in case of extra delay. In such case, make sure to invoke 118 // NextDeliveryTimeUs and schedule a task to call DequeueDeliverablePackets for 119 // the next estimated delivery of packets. 120 // 121 // std::vector<PacketDeliveryInfo> delivered_packets = 122 // network.DequeueDeliverablePackets(/*receive_time_us=*/1000000); 123 class NetworkBehaviorInterface { 124 public: 125 // Enqueues a packet in the network and returns true if the action was 126 // successful, false otherwise (for example, because the network capacity has 127 // been saturated). If the return value is false, the packet should be 128 // considered as dropped and it will not be returned by future calls 129 // to DequeueDeliverablePackets. 130 // Packets enqueued will exit the network when DequeueDeliverablePackets is 131 // called and enough time has passed (see NextDeliveryTimeUs). 132 virtual bool EnqueuePacket(PacketInFlightInfo packet_info) = 0; 133 // Retrieves all packets that should be delivered by the given receive time. 134 // Not all the packets in the returned std::vector are actually delivered. 135 // In order to know the state of each packet it is necessary to check the 136 // `receive_time_us` field of each packet. If that is set to 137 // PacketDeliveryInfo::kNotReceived then the packet is considered lost in the 138 // network. 139 virtual std::vector<PacketDeliveryInfo> DequeueDeliverablePackets( 140 int64_t receive_time_us) = 0; 141 // Returns time in microseconds when caller should call 142 // DequeueDeliverablePackets to get the next set of delivered packets. It is 143 // possible that no packet will be delivered by that time (e.g. in case of 144 // random extra delay), in such case this method should be called again to get 145 // the updated estimated delivery time. 146 virtual std::optional<int64_t> NextDeliveryTimeUs() const = 0; 147 // Registers a callback that should be triggered by an implementation if the 148 // next NextDeliveryTimeUs() has changed between a call to NextDeliveryTimeUs 149 // and DequeueDeliverablePackets. 150 // The intended usage is to invoke NextDeliveryTimeUs and reschedule the 151 // DequeueDeliverablePackets call when network parameters (such as link 152 // capacity) changes. 153 virtual void RegisterDeliveryTimeChangedCallback( 154 absl::AnyInvocable<void()> /* callback */) {} 155 virtual ~NetworkBehaviorInterface() = default; 156 }; 157 158 // Class simulating a network link. This is a simple and naive solution just 159 // faking capacity and adding an extra transport delay in addition to the 160 // capacity introduced delay. 161 class SimulatedNetworkInterface : public NetworkBehaviorInterface { 162 public: 163 // Sets a new configuration. 164 virtual void SetConfig(const BuiltInNetworkBehaviorConfig& config) = 0; 165 virtual void UpdateConfig( 166 std::function<void(BuiltInNetworkBehaviorConfig*)> config_modifier) = 0; 167 // Pauses the network until `until_us`. This affects both delivery (calling 168 // DequeueDeliverablePackets before `until_us` results in an empty std::vector 169 // of packets) and capacity (the network is paused, so packets are not 170 // flowing and they will restart flowing at `until_us`). 171 virtual void PauseTransmissionUntil(int64_t until_us) = 0; 172 }; 173 174 } // namespace webrtc 175 176 #endif // API_TEST_SIMULATED_NETWORK_H_