blob: 6c089163070713034e5f622ce04af70cbecbbb89 [file] [log] [blame]
Sebastian Jansson98b07e92018-09-27 13:47:01 +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#include "test/scenario/network_node.h"
11
12#include <algorithm>
13#include <vector>
14
Yves Gerey2e00abc2018-10-05 15:39:24 +020015#include "rtc_base/numerics/safe_minmax.h"
16
Sebastian Jansson98b07e92018-09-27 13:47:01 +020017namespace webrtc {
18namespace test {
19namespace {
20SimulatedNetwork::Config CreateSimulationConfig(NetworkNodeConfig config) {
21 SimulatedNetwork::Config sim_config;
22 sim_config.link_capacity_kbps = config.simulation.bandwidth.kbps_or(0);
23 sim_config.loss_percent = config.simulation.loss_rate * 100;
24 sim_config.queue_delay_ms = config.simulation.delay.ms();
25 sim_config.delay_standard_deviation_ms = config.simulation.delay_std_dev.ms();
26 return sim_config;
27}
28} // namespace
29
Artem Titov40f51152019-01-04 15:45:01 +010030void NullReceiver::OnPacketReceived(EmulatedIpPacket packet) {}
Sebastian Jansson98b07e92018-09-27 13:47:01 +020031
32ActionReceiver::ActionReceiver(std::function<void()> action)
33 : action_(action) {}
34
Artem Titov40f51152019-01-04 15:45:01 +010035void ActionReceiver::OnPacketReceived(EmulatedIpPacket packet) {
Sebastian Jansson98b07e92018-09-27 13:47:01 +020036 action_();
Sebastian Jansson98b07e92018-09-27 13:47:01 +020037}
38
Sebastian Jansson98b07e92018-09-27 13:47:01 +020039std::unique_ptr<SimulationNode> SimulationNode::Create(
40 NetworkNodeConfig config) {
41 RTC_DCHECK(config.mode == NetworkNodeConfig::TrafficMode::kSimulation);
42 SimulatedNetwork::Config sim_config = CreateSimulationConfig(config);
43 auto network = absl::make_unique<SimulatedNetwork>(sim_config);
44 SimulatedNetwork* simulation_ptr = network.get();
45 return std::unique_ptr<SimulationNode>(
46 new SimulationNode(config, std::move(network), simulation_ptr));
47}
48
49void SimulationNode::UpdateConfig(
50 std::function<void(NetworkNodeConfig*)> modifier) {
51 modifier(&config_);
52 SimulatedNetwork::Config sim_config = CreateSimulationConfig(config_);
53 simulated_network_->SetConfig(sim_config);
54}
55
56void SimulationNode::PauseTransmissionUntil(Timestamp until) {
57 simulated_network_->PauseTransmissionUntil(until.us());
58}
59
60ColumnPrinter SimulationNode::ConfigPrinter() const {
61 return ColumnPrinter::Lambda("propagation_delay capacity loss_rate",
62 [this](rtc::SimpleStringBuilder& sb) {
63 sb.AppendFormat(
64 "%.3lf %.0lf %.2lf",
65 config_.simulation.delay.seconds<double>(),
66 config_.simulation.bandwidth.bps() / 8.0,
67 config_.simulation.loss_rate);
68 });
69}
70
71SimulationNode::SimulationNode(
72 NetworkNodeConfig config,
Artem Titov8ea1e9d2018-10-04 14:46:31 +020073 std::unique_ptr<NetworkBehaviorInterface> behavior,
Sebastian Jansson98b07e92018-09-27 13:47:01 +020074 SimulatedNetwork* simulation)
Artem Titov37d18482019-01-08 15:41:45 +010075 : EmulatedNetworkNode(std::move(behavior),
76 config.packet_overhead.bytes_or(0)),
Sebastian Jansson98b07e92018-09-27 13:47:01 +020077 simulated_network_(simulation),
78 config_(config) {}
79
Sebastian Jansson800e1212018-10-22 11:49:03 +020080NetworkNodeTransport::NetworkNodeTransport(const Clock* sender_clock,
81 Call* sender_call)
82 : sender_clock_(sender_clock), sender_call_(sender_call) {}
Sebastian Jansson98b07e92018-09-27 13:47:01 +020083
84NetworkNodeTransport::~NetworkNodeTransport() = default;
85
86bool NetworkNodeTransport::SendRtp(const uint8_t* packet,
87 size_t length,
88 const PacketOptions& options) {
Sebastian Jansson800e1212018-10-22 11:49:03 +020089 int64_t send_time_ms = sender_clock_->TimeInMilliseconds();
Sebastian Jansson156d11d2018-09-28 17:21:34 +020090 rtc::SentPacket sent_packet;
91 sent_packet.packet_id = options.packet_id;
Sebastian Jansson03789972018-10-09 18:27:57 +020092 sent_packet.info.included_in_feedback = options.included_in_feedback;
93 sent_packet.info.included_in_allocation = options.included_in_allocation;
Sebastian Jansson156d11d2018-09-28 17:21:34 +020094 sent_packet.send_time_ms = send_time_ms;
95 sent_packet.info.packet_size_bytes = length;
96 sent_packet.info.packet_type = rtc::PacketType::kData;
Sebastian Jansson800e1212018-10-22 11:49:03 +020097 sender_call_->OnSentPacket(sent_packet);
Sebastian Jansson156d11d2018-09-28 17:21:34 +020098
99 Timestamp send_time = Timestamp::ms(send_time_ms);
Sebastian Jansson800e1212018-10-22 11:49:03 +0200100 rtc::CritScope crit(&crit_sect_);
101 if (!send_net_)
102 return false;
Sebastian Jansson98b07e92018-09-27 13:47:01 +0200103 rtc::CopyOnWriteBuffer buffer(packet, length,
104 length + packet_overhead_.bytes());
105 buffer.SetSize(length + packet_overhead_.bytes());
Artem Titov40f51152019-01-04 15:45:01 +0100106 send_net_->OnPacketReceived(EmulatedIpPacket(
107 rtc::SocketAddress() /*from*/, rtc::SocketAddress() /*to*/, receiver_id_,
108 buffer, send_time));
Sebastian Janssonf65309c2018-12-20 10:26:00 +0100109 return true;
Sebastian Jansson98b07e92018-09-27 13:47:01 +0200110}
111
112bool NetworkNodeTransport::SendRtcp(const uint8_t* packet, size_t length) {
113 rtc::CopyOnWriteBuffer buffer(packet, length);
Sebastian Jansson800e1212018-10-22 11:49:03 +0200114 Timestamp send_time = Timestamp::ms(sender_clock_->TimeInMilliseconds());
115 rtc::CritScope crit(&crit_sect_);
Sebastian Jansson98b07e92018-09-27 13:47:01 +0200116 buffer.SetSize(length + packet_overhead_.bytes());
Sebastian Jansson800e1212018-10-22 11:49:03 +0200117 if (!send_net_)
118 return false;
Artem Titov40f51152019-01-04 15:45:01 +0100119 send_net_->OnPacketReceived(EmulatedIpPacket(
120 rtc::SocketAddress() /*from*/, rtc::SocketAddress() /*to*/, receiver_id_,
121 buffer, send_time));
Sebastian Janssonf65309c2018-12-20 10:26:00 +0100122 return true;
Sebastian Jansson98b07e92018-09-27 13:47:01 +0200123}
124
Artem Titov37d18482019-01-08 15:41:45 +0100125void NetworkNodeTransport::Connect(EmulatedNetworkNode* send_node,
Sebastian Jansson800e1212018-10-22 11:49:03 +0200126 uint64_t receiver_id,
127 DataSize packet_overhead) {
128 rtc::CritScope crit(&crit_sect_);
129 send_net_ = send_node;
130 receiver_id_ = receiver_id;
131 packet_overhead_ = packet_overhead;
132
133 rtc::NetworkRoute route;
134 route.connected = true;
135 route.local_network_id = receiver_id;
136 route.remote_network_id = receiver_id;
137 std::string transport_name = "dummy";
138 sender_call_->GetTransportControllerSend()->OnNetworkRouteChanged(
139 transport_name, route);
Sebastian Jansson98b07e92018-09-27 13:47:01 +0200140}
141
Artem Titov40f51152019-01-04 15:45:01 +0100142CrossTrafficSource::CrossTrafficSource(EmulatedNetworkReceiverInterface* target,
Sebastian Jansson98b07e92018-09-27 13:47:01 +0200143 uint64_t receiver_id,
144 CrossTrafficConfig config)
145 : target_(target),
146 receiver_id_(receiver_id),
147 config_(config),
148 random_(config.random_seed) {}
149
150CrossTrafficSource::~CrossTrafficSource() = default;
151
152DataRate CrossTrafficSource::TrafficRate() const {
153 return config_.peak_rate * intensity_;
154}
155
156void CrossTrafficSource::Process(Timestamp at_time, TimeDelta delta) {
157 time_since_update_ += delta;
158 if (config_.mode == CrossTrafficConfig::Mode::kRandomWalk) {
159 if (time_since_update_ >= config_.random_walk.update_interval) {
160 intensity_ += random_.Gaussian(config_.random_walk.bias,
161 config_.random_walk.variance) *
162 time_since_update_.seconds<double>();
163 intensity_ = rtc::SafeClamp(intensity_, 0.0, 1.0);
164 time_since_update_ = TimeDelta::Zero();
165 }
166 } else if (config_.mode == CrossTrafficConfig::Mode::kPulsedPeaks) {
167 if (intensity_ == 0 && time_since_update_ >= config_.pulsed.hold_duration) {
168 intensity_ = 1;
169 time_since_update_ = TimeDelta::Zero();
170 } else if (intensity_ == 1 &&
171 time_since_update_ >= config_.pulsed.send_duration) {
172 intensity_ = 0;
173 time_since_update_ = TimeDelta::Zero();
174 }
175 }
176 pending_size_ += TrafficRate() * delta;
177 if (pending_size_ > config_.min_packet_size) {
Artem Titov40f51152019-01-04 15:45:01 +0100178 target_->OnPacketReceived(EmulatedIpPacket(
179 rtc::SocketAddress() /*from*/, rtc::SocketAddress() /*to*/,
180 receiver_id_, rtc::CopyOnWriteBuffer(pending_size_.bytes()), at_time));
Sebastian Jansson98b07e92018-09-27 13:47:01 +0200181 pending_size_ = DataSize::Zero();
182 }
183}
184
185ColumnPrinter CrossTrafficSource::StatsPrinter() {
186 return ColumnPrinter::Lambda("cross_traffic_rate",
187 [this](rtc::SimpleStringBuilder& sb) {
188 sb.AppendFormat("%.0lf",
189 TrafficRate().bps() / 8.0);
190 },
191 32);
192}
193
194} // namespace test
195} // namespace webrtc