blob: 2ff90ec284bc0406917a7222126a68871073ae2f [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;
Sebastian Jansson89eb0bb2020-03-13 17:47:38 +010065 void UpdateConfig(std::function<void(BuiltInNetworkBehaviorConfig*)>
66 config_modifier) override;
Sebastian Janssoncec24332019-12-04 14:26:50 +010067 void PauseTransmissionUntil(int64_t until_us) override;
Sebastian Janssonf96b1ca2018-08-07 18:58:05 +020068
Artem Titov8ea1e9d2018-10-04 14:46:31 +020069 // NetworkBehaviorInterface
Sebastian Janssonf96b1ca2018-08-07 18:58:05 +020070 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 };
Sebastian Janssoneceea312019-01-31 11:50:04 +010081 // 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 };
Christoffer Rodbro813c79b2019-01-31 09:25:12 +010093
94 // Moves packets from capacity- to delay link.
Sebastian Janssoneceea312019-01-31 11:50:04 +010095 void UpdateCapacityQueue(ConfigState state, int64_t time_now_us)
96 RTC_RUN_ON(&process_checker_);
97 ConfigState GetConfigState() const;
Christoffer Rodbro813c79b2019-01-31 09:25:12 +010098
Sebastian Janssonf96b1ca2018-08-07 18:58:05 +020099 rtc::CriticalSection config_lock_;
100
Sebastian Janssoneceea312019-01-31 11:50:04 +0100101 // |process_checker_| guards the data structures involved in delay and loss
Sebastian Janssonf96b1ca2018-08-07 18:58:05 +0200102 // processes, such as the packet queues.
Sebastian Janssoneceea312019-01-31 11:50:04 +0100103 rtc::RaceChecker process_checker_;
Sebastian Jansson2b08e312019-02-25 10:24:46 +0100104 CoDelSimulation codel_controller_ RTC_GUARDED_BY(process_checker_);
Sebastian Janssoneceea312019-01-31 11:50:04 +0100105 std::queue<PacketInfo> capacity_link_ RTC_GUARDED_BY(process_checker_);
Sebastian Janssonf96b1ca2018-08-07 18:58:05 +0200106 Random random_;
107
Sebastian Janssoneceea312019-01-31 11:50:04 +0100108 std::deque<PacketInfo> delay_link_ RTC_GUARDED_BY(process_checker_);
Sebastian Janssonf96b1ca2018-08-07 18:58:05 +0200109
Sebastian Janssoneceea312019-01-31 11:50:04 +0100110 ConfigState config_state_ RTC_GUARDED_BY(config_lock_);
Sebastian Janssonf96b1ca2018-08-07 18:58:05 +0200111
112 // Are we currently dropping a burst of packets?
113 bool bursting_;
114
Sebastian Janssoneceea312019-01-31 11:50:04 +0100115 int64_t queue_size_bytes_ RTC_GUARDED_BY(process_checker_) = 0;
116 int64_t pending_drain_bits_ RTC_GUARDED_BY(process_checker_) = 0;
Christoffer Rodbro813c79b2019-01-31 09:25:12 +0100117 absl::optional<int64_t> last_capacity_link_visit_us_
Sebastian Janssoneceea312019-01-31 11:50:04 +0100118 RTC_GUARDED_BY(process_checker_);
Sebastian Jansson836fee12019-02-08 16:08:10 +0100119 absl::optional<int64_t> next_process_time_us_
120 RTC_GUARDED_BY(process_checker_);
Sebastian Janssonf96b1ca2018-08-07 18:58:05 +0200121};
122
123} // namespace webrtc
124
125#endif // CALL_SIMULATED_NETWORK_H_