blob: 1b82b5309016e18431b123f9e59c79d20e33d55e [file] [log] [blame]
Sebastian Jansson98b07e912018-09-27 11:47:011/*
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 13:39:2415#include "rtc_base/numerics/safe_minmax.h"
16
Sebastian Jansson98b07e912018-09-27 11:47:0117namespace 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
30bool NullReceiver::TryDeliverPacket(rtc::CopyOnWriteBuffer packet,
31 uint64_t receiver,
32 Timestamp at_time) {
33 return true;
34}
35
36ActionReceiver::ActionReceiver(std::function<void()> action)
37 : action_(action) {}
38
39bool ActionReceiver::TryDeliverPacket(rtc::CopyOnWriteBuffer packet,
40 uint64_t receiver,
41 Timestamp at_time) {
42 action_();
43 return true;
44}
45
46NetworkNode::~NetworkNode() = default;
47
48NetworkNode::NetworkNode(NetworkNodeConfig config,
Artem Titov8ea1e9d2018-10-04 12:46:3149 std::unique_ptr<NetworkBehaviorInterface> behavior)
Sebastian Jansson98b07e912018-09-27 11:47:0150 : packet_overhead_(config.packet_overhead.bytes()),
Artem Titov8ea1e9d2018-10-04 12:46:3151 behavior_(std::move(behavior)) {}
Sebastian Jansson98b07e912018-09-27 11:47:0152
53void NetworkNode::SetRoute(uint64_t receiver, NetworkReceiverInterface* node) {
54 rtc::CritScope crit(&crit_sect_);
55 routing_[receiver] = node;
56}
57
58void NetworkNode::ClearRoute(uint64_t receiver_id) {
59 rtc::CritScope crit(&crit_sect_);
60 auto it = routing_.find(receiver_id);
61 routing_.erase(it);
62}
63
64bool NetworkNode::TryDeliverPacket(rtc::CopyOnWriteBuffer packet,
65 uint64_t receiver,
66 Timestamp at_time) {
67 rtc::CritScope crit(&crit_sect_);
68 if (routing_.find(receiver) == routing_.end())
69 return false;
70 uint64_t packet_id = next_packet_id_++;
Artem Titov8ea1e9d2018-10-04 12:46:3171 bool sent = behavior_->EnqueuePacket(PacketInFlightInfo(
Sebastian Jansson98b07e912018-09-27 11:47:0172 packet.size() + packet_overhead_, at_time.us(), packet_id));
73 if (sent) {
74 packets_.emplace_back(StoredPacket{packet, receiver, packet_id, false});
75 }
76 return sent;
77}
78
79void NetworkNode::Process(Timestamp at_time) {
80 std::vector<PacketDeliveryInfo> delivery_infos;
81 {
82 rtc::CritScope crit(&crit_sect_);
Artem Titov8ea1e9d2018-10-04 12:46:3183 absl::optional<int64_t> delivery_us = behavior_->NextDeliveryTimeUs();
Sebastian Jansson98b07e912018-09-27 11:47:0184 if (delivery_us && *delivery_us > at_time.us())
85 return;
86
Artem Titov8ea1e9d2018-10-04 12:46:3187 delivery_infos = behavior_->DequeueDeliverablePackets(at_time.us());
Sebastian Jansson98b07e912018-09-27 11:47:0188 }
89 for (PacketDeliveryInfo& delivery_info : delivery_infos) {
90 StoredPacket* packet = nullptr;
91 NetworkReceiverInterface* receiver = nullptr;
92 {
93 rtc::CritScope crit(&crit_sect_);
94 for (StoredPacket& stored_packet : packets_) {
95 if (stored_packet.id == delivery_info.packet_id) {
96 packet = &stored_packet;
97 break;
98 }
99 }
100 RTC_CHECK(packet);
101 RTC_DCHECK(!packet->removed);
102 receiver = routing_[packet->receiver_id];
103 packet->removed = true;
104 }
105 // We don't want to keep the lock here. Otherwise we would get a deadlock if
106 // the receiver tries to push a new packet.
107 receiver->TryDeliverPacket(packet->packet_data, packet->receiver_id,
Sebastian Janssonf3ef6cd2018-12-10 15:07:30108 Timestamp::us(delivery_info.receive_time_us));
Sebastian Jansson98b07e912018-09-27 11:47:01109 {
110 rtc::CritScope crit(&crit_sect_);
111 while (!packets_.empty() && packets_.front().removed) {
112 packets_.pop_front();
113 }
114 }
115 }
116}
117
118void NetworkNode::Route(int64_t receiver_id,
119 std::vector<NetworkNode*> nodes,
120 NetworkReceiverInterface* receiver) {
121 RTC_CHECK(!nodes.empty());
122 for (size_t i = 0; i + 1 < nodes.size(); ++i)
123 nodes[i]->SetRoute(receiver_id, nodes[i + 1]);
124 nodes.back()->SetRoute(receiver_id, receiver);
125}
126
127void NetworkNode::ClearRoute(int64_t receiver_id,
128 std::vector<NetworkNode*> nodes) {
129 for (NetworkNode* node : nodes)
130 node->ClearRoute(receiver_id);
131}
132
133std::unique_ptr<SimulationNode> SimulationNode::Create(
134 NetworkNodeConfig config) {
135 RTC_DCHECK(config.mode == NetworkNodeConfig::TrafficMode::kSimulation);
136 SimulatedNetwork::Config sim_config = CreateSimulationConfig(config);
137 auto network = absl::make_unique<SimulatedNetwork>(sim_config);
138 SimulatedNetwork* simulation_ptr = network.get();
139 return std::unique_ptr<SimulationNode>(
140 new SimulationNode(config, std::move(network), simulation_ptr));
141}
142
143void SimulationNode::UpdateConfig(
144 std::function<void(NetworkNodeConfig*)> modifier) {
145 modifier(&config_);
146 SimulatedNetwork::Config sim_config = CreateSimulationConfig(config_);
147 simulated_network_->SetConfig(sim_config);
148}
149
150void SimulationNode::PauseTransmissionUntil(Timestamp until) {
151 simulated_network_->PauseTransmissionUntil(until.us());
152}
153
154ColumnPrinter SimulationNode::ConfigPrinter() const {
155 return ColumnPrinter::Lambda("propagation_delay capacity loss_rate",
156 [this](rtc::SimpleStringBuilder& sb) {
157 sb.AppendFormat(
158 "%.3lf %.0lf %.2lf",
159 config_.simulation.delay.seconds<double>(),
160 config_.simulation.bandwidth.bps() / 8.0,
161 config_.simulation.loss_rate);
162 });
163}
164
165SimulationNode::SimulationNode(
166 NetworkNodeConfig config,
Artem Titov8ea1e9d2018-10-04 12:46:31167 std::unique_ptr<NetworkBehaviorInterface> behavior,
Sebastian Jansson98b07e912018-09-27 11:47:01168 SimulatedNetwork* simulation)
169 : NetworkNode(config, std::move(behavior)),
170 simulated_network_(simulation),
171 config_(config) {}
172
Sebastian Jansson800e1212018-10-22 09:49:03173NetworkNodeTransport::NetworkNodeTransport(const Clock* sender_clock,
174 Call* sender_call)
175 : sender_clock_(sender_clock), sender_call_(sender_call) {}
Sebastian Jansson98b07e912018-09-27 11:47:01176
177NetworkNodeTransport::~NetworkNodeTransport() = default;
178
179bool NetworkNodeTransport::SendRtp(const uint8_t* packet,
180 size_t length,
181 const PacketOptions& options) {
Sebastian Jansson800e1212018-10-22 09:49:03182 int64_t send_time_ms = sender_clock_->TimeInMilliseconds();
Sebastian Jansson156d11d2018-09-28 15:21:34183 rtc::SentPacket sent_packet;
184 sent_packet.packet_id = options.packet_id;
Sebastian Jansson03789972018-10-09 16:27:57185 sent_packet.info.included_in_feedback = options.included_in_feedback;
186 sent_packet.info.included_in_allocation = options.included_in_allocation;
Sebastian Jansson156d11d2018-09-28 15:21:34187 sent_packet.send_time_ms = send_time_ms;
188 sent_packet.info.packet_size_bytes = length;
189 sent_packet.info.packet_type = rtc::PacketType::kData;
Sebastian Jansson800e1212018-10-22 09:49:03190 sender_call_->OnSentPacket(sent_packet);
Sebastian Jansson156d11d2018-09-28 15:21:34191
192 Timestamp send_time = Timestamp::ms(send_time_ms);
Sebastian Jansson800e1212018-10-22 09:49:03193 rtc::CritScope crit(&crit_sect_);
194 if (!send_net_)
195 return false;
Sebastian Jansson98b07e912018-09-27 11:47:01196 rtc::CopyOnWriteBuffer buffer(packet, length,
197 length + packet_overhead_.bytes());
198 buffer.SetSize(length + packet_overhead_.bytes());
199 return send_net_->TryDeliverPacket(buffer, receiver_id_, send_time);
200}
201
202bool NetworkNodeTransport::SendRtcp(const uint8_t* packet, size_t length) {
203 rtc::CopyOnWriteBuffer buffer(packet, length);
Sebastian Jansson800e1212018-10-22 09:49:03204 Timestamp send_time = Timestamp::ms(sender_clock_->TimeInMilliseconds());
205 rtc::CritScope crit(&crit_sect_);
Sebastian Jansson98b07e912018-09-27 11:47:01206 buffer.SetSize(length + packet_overhead_.bytes());
Sebastian Jansson800e1212018-10-22 09:49:03207 if (!send_net_)
208 return false;
Sebastian Jansson98b07e912018-09-27 11:47:01209 return send_net_->TryDeliverPacket(buffer, receiver_id_, send_time);
210}
211
Sebastian Jansson800e1212018-10-22 09:49:03212void NetworkNodeTransport::Connect(NetworkNode* send_node,
213 uint64_t receiver_id,
214 DataSize packet_overhead) {
215 rtc::CritScope crit(&crit_sect_);
216 send_net_ = send_node;
217 receiver_id_ = receiver_id;
218 packet_overhead_ = packet_overhead;
219
220 rtc::NetworkRoute route;
221 route.connected = true;
222 route.local_network_id = receiver_id;
223 route.remote_network_id = receiver_id;
224 std::string transport_name = "dummy";
225 sender_call_->GetTransportControllerSend()->OnNetworkRouteChanged(
226 transport_name, route);
Sebastian Jansson98b07e912018-09-27 11:47:01227}
228
229CrossTrafficSource::CrossTrafficSource(NetworkReceiverInterface* target,
230 uint64_t receiver_id,
231 CrossTrafficConfig config)
232 : target_(target),
233 receiver_id_(receiver_id),
234 config_(config),
235 random_(config.random_seed) {}
236
237CrossTrafficSource::~CrossTrafficSource() = default;
238
239DataRate CrossTrafficSource::TrafficRate() const {
240 return config_.peak_rate * intensity_;
241}
242
243void CrossTrafficSource::Process(Timestamp at_time, TimeDelta delta) {
244 time_since_update_ += delta;
245 if (config_.mode == CrossTrafficConfig::Mode::kRandomWalk) {
246 if (time_since_update_ >= config_.random_walk.update_interval) {
247 intensity_ += random_.Gaussian(config_.random_walk.bias,
248 config_.random_walk.variance) *
249 time_since_update_.seconds<double>();
250 intensity_ = rtc::SafeClamp(intensity_, 0.0, 1.0);
251 time_since_update_ = TimeDelta::Zero();
252 }
253 } else if (config_.mode == CrossTrafficConfig::Mode::kPulsedPeaks) {
254 if (intensity_ == 0 && time_since_update_ >= config_.pulsed.hold_duration) {
255 intensity_ = 1;
256 time_since_update_ = TimeDelta::Zero();
257 } else if (intensity_ == 1 &&
258 time_since_update_ >= config_.pulsed.send_duration) {
259 intensity_ = 0;
260 time_since_update_ = TimeDelta::Zero();
261 }
262 }
263 pending_size_ += TrafficRate() * delta;
264 if (pending_size_ > config_.min_packet_size) {
265 target_->TryDeliverPacket(rtc::CopyOnWriteBuffer(pending_size_.bytes()),
266 receiver_id_, at_time);
267 pending_size_ = DataSize::Zero();
268 }
269}
270
271ColumnPrinter CrossTrafficSource::StatsPrinter() {
272 return ColumnPrinter::Lambda("cross_traffic_rate",
273 [this](rtc::SimpleStringBuilder& sb) {
274 sb.AppendFormat("%.0lf",
275 TrafficRate().bps() / 8.0);
276 },
277 32);
278}
279
280} // namespace test
281} // namespace webrtc