1 /* 2 * Copyright 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 #ifndef CALL_SIMULATED_NETWORK_H_ 11 #define CALL_SIMULATED_NETWORK_H_ 12 13 #include <stdint.h> 14 15 #include <deque> 16 #include <queue> 17 #include <vector> 18 19 #include "absl/types/optional.h" 20 #include "api/test/simulated_network.h" 21 #include "api/units/data_size.h" 22 #include "api/units/timestamp.h" 23 #include "rtc_base/race_checker.h" 24 #include "rtc_base/random.h" 25 #include "rtc_base/synchronization/mutex.h" 26 #include "rtc_base/thread_annotations.h" 27 #include "rtc_base/thread_checker.h" 28 29 namespace webrtc { 30 // Implementation of the CoDel active queue management algorithm. Loosely based 31 // on CoDel pseudocode from ACMQueue. CoDel keeps queuing delays low by dropping 32 // packets when delay is high. For each packet ready for dequeue, call 33 // DropDequeuePacket with the packet parameters to update the CoDel state. 34 class CoDelSimulation { 35 public: 36 CoDelSimulation(); 37 ~CoDelSimulation(); 38 39 // Returns true if packet should be dropped. 40 bool DropDequeuedPacket(Timestamp now, 41 Timestamp enqueing_time, 42 DataSize packet_size, 43 DataSize queue_size); 44 45 private: 46 enum State { kNormal, kPending, kDropping }; 47 Timestamp enter_drop_state_at_ = Timestamp::PlusInfinity(); 48 Timestamp last_drop_at_ = Timestamp::MinusInfinity(); 49 int drop_count_ = 0; 50 int previous_drop_count_ = 0; 51 State state_ = State::kNormal; 52 }; 53 54 // Class simulating a network link. This is a simple and naive solution just 55 // faking capacity and adding an extra transport delay in addition to the 56 // capacity introduced delay. 57 class SimulatedNetwork : public SimulatedNetworkInterface { 58 public: 59 using Config = BuiltInNetworkBehaviorConfig; 60 explicit SimulatedNetwork(Config config, uint64_t random_seed = 1); 61 ~SimulatedNetwork() override; 62 63 // Sets a new configuration. This won't affect packets already in the pipe. 64 void SetConfig(const Config& config) override; 65 void UpdateConfig(std::function<void(BuiltInNetworkBehaviorConfig*)> 66 config_modifier) override; 67 void PauseTransmissionUntil(int64_t until_us) override; 68 69 // NetworkBehaviorInterface 70 bool EnqueuePacket(PacketInFlightInfo packet) override; 71 std::vector<PacketDeliveryInfo> DequeueDeliverablePackets( 72 int64_t receive_time_us) override; 73 74 absl::optional<int64_t> NextDeliveryTimeUs() const override; 75 76 private: 77 struct PacketInfo { 78 PacketInFlightInfo packet; 79 int64_t arrival_time_us; 80 }; 81 // Contains current configuration state. 82 struct ConfigState { 83 // Static link configuration. 84 Config config; 85 // The probability to drop the packet if we are currently dropping a 86 // burst of packet 87 double prob_loss_bursting; 88 // The probability to drop a burst of packets. 89 double prob_start_bursting; 90 // Used for temporary delay spikes. 91 int64_t pause_transmission_until_us = 0; 92 }; 93 94 // Moves packets from capacity- to delay link. 95 void UpdateCapacityQueue(ConfigState state, int64_t time_now_us) 96 RTC_RUN_ON(&process_checker_); 97 ConfigState GetConfigState() const; 98 99 mutable Mutex config_lock_; 100 101 // |process_checker_| guards the data structures involved in delay and loss 102 // processes, such as the packet queues. 103 rtc::RaceChecker process_checker_; 104 CoDelSimulation codel_controller_ RTC_GUARDED_BY(process_checker_); 105 std::queue<PacketInfo> capacity_link_ RTC_GUARDED_BY(process_checker_); 106 Random random_; 107 108 std::deque<PacketInfo> delay_link_ RTC_GUARDED_BY(process_checker_); 109 110 ConfigState config_state_ RTC_GUARDED_BY(config_lock_); 111 112 // Are we currently dropping a burst of packets? 113 bool bursting_; 114 115 int64_t queue_size_bytes_ RTC_GUARDED_BY(process_checker_) = 0; 116 int64_t pending_drain_bits_ RTC_GUARDED_BY(process_checker_) = 0; 117 absl::optional<int64_t> last_capacity_link_visit_us_ 118 RTC_GUARDED_BY(process_checker_); 119 absl::optional<int64_t> next_process_time_us_ 120 RTC_GUARDED_BY(process_checker_); 121 }; 122 123 } // namespace webrtc 124 125 #endif // CALL_SIMULATED_NETWORK_H_ 126