blob: fa72762b448d26f7c8bf2a26b797016b1064caa9 [file] [log] [blame]
Sebastian Janssonf96b1ca2018-08-07 18:58:05 +02001/*
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
Yves Gerey3e707812018-11-28 16:47:49 +010013#include <stdint.h>
Jonas Olssona4d87372019-07-05 19:08:33 +020014
Sebastian Janssonf96b1ca2018-08-07 18:58:05 +020015#include <deque>
16#include <queue>
17#include <vector>
18
Sebastian Janssonf96b1ca2018-08-07 18:58:05 +020019#include "absl/types/optional.h"
20#include "api/test/simulated_network.h"
Sebastian Jansson2b08e312019-02-25 10:24:46 +010021#include "api/units/data_size.h"
22#include "api/units/timestamp.h"
Steve Anton10542f22019-01-11 09:11:00 -080023#include "rtc_base/critical_section.h"
Sebastian Janssoneceea312019-01-31 11:50:04 +010024#include "rtc_base/race_checker.h"
Sebastian Janssonf96b1ca2018-08-07 18:58:05 +020025#include "rtc_base/random.h"
26#include "rtc_base/thread_annotations.h"
Sebastian Janssoneceea312019-01-31 11:50:04 +010027#include "rtc_base/thread_checker.h"
Sebastian Janssonf96b1ca2018-08-07 18:58:05 +020028
29namespace webrtc {
Sebastian Jansson2b08e312019-02-25 10:24:46 +010030// 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.
34class 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};
Sebastian Janssonf96b1ca2018-08-07 18:58:05 +020053
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.
Sebastian Janssoncec24332019-12-04 14:26:50 +010057class SimulatedNetwork : public SimulatedNetworkInterface {
Sebastian Janssonf96b1ca2018-08-07 18:58:05 +020058 public:
Artem Titov75e36472018-10-08 12:28:56 +020059 using Config = BuiltInNetworkBehaviorConfig;
Sebastian Janssonf96b1ca2018-08-07 18:58:05 +020060 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.
Sebastian Janssoncec24332019-12-04 14:26:50 +010064 void SetConfig(const Config& config) override;
65 void PauseTransmissionUntil(int64_t until_us) override;
Sebastian Janssonf96b1ca2018-08-07 18:58:05 +020066
Artem Titov8ea1e9d2018-10-04 14:46:31 +020067 // NetworkBehaviorInterface
Sebastian Janssonf96b1ca2018-08-07 18:58:05 +020068 bool EnqueuePacket(PacketInFlightInfo packet) override;
69 std::vector<PacketDeliveryInfo> DequeueDeliverablePackets(
70 int64_t receive_time_us) override;
71
72 absl::optional<int64_t> NextDeliveryTimeUs() const override;
73
74 private:
75 struct PacketInfo {
76 PacketInFlightInfo packet;
77 int64_t arrival_time_us;
78 };
Sebastian Janssoneceea312019-01-31 11:50:04 +010079 // Contains current configuration state.
80 struct ConfigState {
81 // Static link configuration.
82 Config config;
83 // The probability to drop the packet if we are currently dropping a
84 // burst of packet
85 double prob_loss_bursting;
86 // The probability to drop a burst of packets.
87 double prob_start_bursting;
88 // Used for temporary delay spikes.
89 int64_t pause_transmission_until_us = 0;
90 };
Christoffer Rodbro813c79b2019-01-31 09:25:12 +010091
92 // Moves packets from capacity- to delay link.
Sebastian Janssoneceea312019-01-31 11:50:04 +010093 void UpdateCapacityQueue(ConfigState state, int64_t time_now_us)
94 RTC_RUN_ON(&process_checker_);
95 ConfigState GetConfigState() const;
Christoffer Rodbro813c79b2019-01-31 09:25:12 +010096
Sebastian Janssonf96b1ca2018-08-07 18:58:05 +020097 rtc::CriticalSection config_lock_;
98
Sebastian Janssoneceea312019-01-31 11:50:04 +010099 // |process_checker_| guards the data structures involved in delay and loss
Sebastian Janssonf96b1ca2018-08-07 18:58:05 +0200100 // processes, such as the packet queues.
Sebastian Janssoneceea312019-01-31 11:50:04 +0100101 rtc::RaceChecker process_checker_;
Sebastian Jansson2b08e312019-02-25 10:24:46 +0100102 CoDelSimulation codel_controller_ RTC_GUARDED_BY(process_checker_);
Sebastian Janssoneceea312019-01-31 11:50:04 +0100103 std::queue<PacketInfo> capacity_link_ RTC_GUARDED_BY(process_checker_);
Sebastian Janssonf96b1ca2018-08-07 18:58:05 +0200104 Random random_;
105
Sebastian Janssoneceea312019-01-31 11:50:04 +0100106 std::deque<PacketInfo> delay_link_ RTC_GUARDED_BY(process_checker_);
Sebastian Janssonf96b1ca2018-08-07 18:58:05 +0200107
Sebastian Janssoneceea312019-01-31 11:50:04 +0100108 ConfigState config_state_ RTC_GUARDED_BY(config_lock_);
Sebastian Janssonf96b1ca2018-08-07 18:58:05 +0200109
110 // Are we currently dropping a burst of packets?
111 bool bursting_;
112
Sebastian Janssoneceea312019-01-31 11:50:04 +0100113 int64_t queue_size_bytes_ RTC_GUARDED_BY(process_checker_) = 0;
114 int64_t pending_drain_bits_ RTC_GUARDED_BY(process_checker_) = 0;
Christoffer Rodbro813c79b2019-01-31 09:25:12 +0100115 absl::optional<int64_t> last_capacity_link_visit_us_
Sebastian Janssoneceea312019-01-31 11:50:04 +0100116 RTC_GUARDED_BY(process_checker_);
Sebastian Jansson836fee12019-02-08 16:08:10 +0100117 absl::optional<int64_t> next_process_time_us_
118 RTC_GUARDED_BY(process_checker_);
Sebastian Janssonf96b1ca2018-08-07 18:58:05 +0200119};
120
121} // namespace webrtc
122
123#endif // CALL_SIMULATED_NETWORK_H_