blob: a715093f64f42e2a2a06a3d8290dd07f28ad0f03 [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
Sebastian Janssonf65309c2018-12-20 09:26:0030void NullReceiver::DeliverPacket(rtc::CopyOnWriteBuffer packet,
31 uint64_t receiver,
32 Timestamp at_time) {}
Sebastian Jansson98b07e912018-09-27 11:47:0133
34ActionReceiver::ActionReceiver(std::function<void()> action)
35 : action_(action) {}
36
Sebastian Janssonf65309c2018-12-20 09:26:0037void ActionReceiver::DeliverPacket(rtc::CopyOnWriteBuffer packet,
38 uint64_t receiver,
39 Timestamp at_time) {
Sebastian Jansson98b07e912018-09-27 11:47:0140 action_();
Sebastian Jansson98b07e912018-09-27 11:47:0141}
42
43NetworkNode::~NetworkNode() = default;
44
45NetworkNode::NetworkNode(NetworkNodeConfig config,
Artem Titov8ea1e9d2018-10-04 12:46:3146 std::unique_ptr<NetworkBehaviorInterface> behavior)
Sebastian Jansson98b07e912018-09-27 11:47:0147 : packet_overhead_(config.packet_overhead.bytes()),
Artem Titov8ea1e9d2018-10-04 12:46:3148 behavior_(std::move(behavior)) {}
Sebastian Jansson98b07e912018-09-27 11:47:0149
50void NetworkNode::SetRoute(uint64_t receiver, NetworkReceiverInterface* node) {
51 rtc::CritScope crit(&crit_sect_);
52 routing_[receiver] = node;
53}
54
55void NetworkNode::ClearRoute(uint64_t receiver_id) {
56 rtc::CritScope crit(&crit_sect_);
57 auto it = routing_.find(receiver_id);
58 routing_.erase(it);
59}
60
Sebastian Janssonf65309c2018-12-20 09:26:0061void NetworkNode::DeliverPacket(rtc::CopyOnWriteBuffer packet,
62 uint64_t receiver,
63 Timestamp at_time) {
Sebastian Jansson98b07e912018-09-27 11:47:0164 rtc::CritScope crit(&crit_sect_);
65 if (routing_.find(receiver) == routing_.end())
Sebastian Janssonf65309c2018-12-20 09:26:0066 return;
Sebastian Jansson98b07e912018-09-27 11:47:0167 uint64_t packet_id = next_packet_id_++;
Sebastian Janssonf65309c2018-12-20 09:26:0068 if (behavior_->EnqueuePacket(PacketInFlightInfo(
69 packet.size() + packet_overhead_, at_time.us(), packet_id))) {
Sebastian Jansson98b07e912018-09-27 11:47:0170 packets_.emplace_back(StoredPacket{packet, receiver, packet_id, false});
71 }
Sebastian Jansson98b07e912018-09-27 11:47:0172}
73
74void NetworkNode::Process(Timestamp at_time) {
75 std::vector<PacketDeliveryInfo> delivery_infos;
76 {
77 rtc::CritScope crit(&crit_sect_);
Artem Titov8ea1e9d2018-10-04 12:46:3178 absl::optional<int64_t> delivery_us = behavior_->NextDeliveryTimeUs();
Sebastian Jansson98b07e912018-09-27 11:47:0179 if (delivery_us && *delivery_us > at_time.us())
80 return;
81
Artem Titov8ea1e9d2018-10-04 12:46:3182 delivery_infos = behavior_->DequeueDeliverablePackets(at_time.us());
Sebastian Jansson98b07e912018-09-27 11:47:0183 }
84 for (PacketDeliveryInfo& delivery_info : delivery_infos) {
85 StoredPacket* packet = nullptr;
86 NetworkReceiverInterface* receiver = nullptr;
87 {
88 rtc::CritScope crit(&crit_sect_);
89 for (StoredPacket& stored_packet : packets_) {
90 if (stored_packet.id == delivery_info.packet_id) {
91 packet = &stored_packet;
92 break;
93 }
94 }
95 RTC_CHECK(packet);
96 RTC_DCHECK(!packet->removed);
97 receiver = routing_[packet->receiver_id];
98 packet->removed = true;
99 }
100 // We don't want to keep the lock here. Otherwise we would get a deadlock if
101 // the receiver tries to push a new packet.
Sebastian Janssonf65309c2018-12-20 09:26:00102 receiver->DeliverPacket(packet->packet_data, packet->receiver_id,
103 Timestamp::us(delivery_info.receive_time_us));
Sebastian Jansson98b07e912018-09-27 11:47:01104 {
105 rtc::CritScope crit(&crit_sect_);
106 while (!packets_.empty() && packets_.front().removed) {
107 packets_.pop_front();
108 }
109 }
110 }
111}
112
113void NetworkNode::Route(int64_t receiver_id,
114 std::vector<NetworkNode*> nodes,
115 NetworkReceiverInterface* receiver) {
116 RTC_CHECK(!nodes.empty());
117 for (size_t i = 0; i + 1 < nodes.size(); ++i)
118 nodes[i]->SetRoute(receiver_id, nodes[i + 1]);
119 nodes.back()->SetRoute(receiver_id, receiver);
120}
121
122void NetworkNode::ClearRoute(int64_t receiver_id,
123 std::vector<NetworkNode*> nodes) {
124 for (NetworkNode* node : nodes)
125 node->ClearRoute(receiver_id);
126}
127
128std::unique_ptr<SimulationNode> SimulationNode::Create(
129 NetworkNodeConfig config) {
130 RTC_DCHECK(config.mode == NetworkNodeConfig::TrafficMode::kSimulation);
131 SimulatedNetwork::Config sim_config = CreateSimulationConfig(config);
132 auto network = absl::make_unique<SimulatedNetwork>(sim_config);
133 SimulatedNetwork* simulation_ptr = network.get();
134 return std::unique_ptr<SimulationNode>(
135 new SimulationNode(config, std::move(network), simulation_ptr));
136}
137
138void SimulationNode::UpdateConfig(
139 std::function<void(NetworkNodeConfig*)> modifier) {
140 modifier(&config_);
141 SimulatedNetwork::Config sim_config = CreateSimulationConfig(config_);
142 simulated_network_->SetConfig(sim_config);
143}
144
145void SimulationNode::PauseTransmissionUntil(Timestamp until) {
146 simulated_network_->PauseTransmissionUntil(until.us());
147}
148
149ColumnPrinter SimulationNode::ConfigPrinter() const {
150 return ColumnPrinter::Lambda("propagation_delay capacity loss_rate",
151 [this](rtc::SimpleStringBuilder& sb) {
152 sb.AppendFormat(
153 "%.3lf %.0lf %.2lf",
154 config_.simulation.delay.seconds<double>(),
155 config_.simulation.bandwidth.bps() / 8.0,
156 config_.simulation.loss_rate);
157 });
158}
159
160SimulationNode::SimulationNode(
161 NetworkNodeConfig config,
Artem Titov8ea1e9d2018-10-04 12:46:31162 std::unique_ptr<NetworkBehaviorInterface> behavior,
Sebastian Jansson98b07e912018-09-27 11:47:01163 SimulatedNetwork* simulation)
164 : NetworkNode(config, std::move(behavior)),
165 simulated_network_(simulation),
166 config_(config) {}
167
Sebastian Jansson800e1212018-10-22 09:49:03168NetworkNodeTransport::NetworkNodeTransport(const Clock* sender_clock,
169 Call* sender_call)
170 : sender_clock_(sender_clock), sender_call_(sender_call) {}
Sebastian Jansson98b07e912018-09-27 11:47:01171
172NetworkNodeTransport::~NetworkNodeTransport() = default;
173
174bool NetworkNodeTransport::SendRtp(const uint8_t* packet,
175 size_t length,
176 const PacketOptions& options) {
Sebastian Jansson800e1212018-10-22 09:49:03177 int64_t send_time_ms = sender_clock_->TimeInMilliseconds();
Sebastian Jansson156d11d2018-09-28 15:21:34178 rtc::SentPacket sent_packet;
179 sent_packet.packet_id = options.packet_id;
Sebastian Jansson03789972018-10-09 16:27:57180 sent_packet.info.included_in_feedback = options.included_in_feedback;
181 sent_packet.info.included_in_allocation = options.included_in_allocation;
Sebastian Jansson156d11d2018-09-28 15:21:34182 sent_packet.send_time_ms = send_time_ms;
183 sent_packet.info.packet_size_bytes = length;
184 sent_packet.info.packet_type = rtc::PacketType::kData;
Sebastian Jansson800e1212018-10-22 09:49:03185 sender_call_->OnSentPacket(sent_packet);
Sebastian Jansson156d11d2018-09-28 15:21:34186
187 Timestamp send_time = Timestamp::ms(send_time_ms);
Sebastian Jansson800e1212018-10-22 09:49:03188 rtc::CritScope crit(&crit_sect_);
189 if (!send_net_)
190 return false;
Sebastian Jansson98b07e912018-09-27 11:47:01191 rtc::CopyOnWriteBuffer buffer(packet, length,
192 length + packet_overhead_.bytes());
193 buffer.SetSize(length + packet_overhead_.bytes());
Sebastian Janssonf65309c2018-12-20 09:26:00194 send_net_->DeliverPacket(buffer, receiver_id_, send_time);
195 return true;
Sebastian Jansson98b07e912018-09-27 11:47:01196}
197
198bool NetworkNodeTransport::SendRtcp(const uint8_t* packet, size_t length) {
199 rtc::CopyOnWriteBuffer buffer(packet, length);
Sebastian Jansson800e1212018-10-22 09:49:03200 Timestamp send_time = Timestamp::ms(sender_clock_->TimeInMilliseconds());
201 rtc::CritScope crit(&crit_sect_);
Sebastian Jansson98b07e912018-09-27 11:47:01202 buffer.SetSize(length + packet_overhead_.bytes());
Sebastian Jansson800e1212018-10-22 09:49:03203 if (!send_net_)
204 return false;
Sebastian Janssonf65309c2018-12-20 09:26:00205 send_net_->DeliverPacket(buffer, receiver_id_, send_time);
206 return true;
Sebastian Jansson98b07e912018-09-27 11:47:01207}
208
Sebastian Jansson800e1212018-10-22 09:49:03209void NetworkNodeTransport::Connect(NetworkNode* send_node,
210 uint64_t receiver_id,
211 DataSize packet_overhead) {
212 rtc::CritScope crit(&crit_sect_);
213 send_net_ = send_node;
214 receiver_id_ = receiver_id;
215 packet_overhead_ = packet_overhead;
216
217 rtc::NetworkRoute route;
218 route.connected = true;
219 route.local_network_id = receiver_id;
220 route.remote_network_id = receiver_id;
221 std::string transport_name = "dummy";
222 sender_call_->GetTransportControllerSend()->OnNetworkRouteChanged(
223 transport_name, route);
Sebastian Jansson98b07e912018-09-27 11:47:01224}
225
226CrossTrafficSource::CrossTrafficSource(NetworkReceiverInterface* target,
227 uint64_t receiver_id,
228 CrossTrafficConfig config)
229 : target_(target),
230 receiver_id_(receiver_id),
231 config_(config),
232 random_(config.random_seed) {}
233
234CrossTrafficSource::~CrossTrafficSource() = default;
235
236DataRate CrossTrafficSource::TrafficRate() const {
237 return config_.peak_rate * intensity_;
238}
239
240void CrossTrafficSource::Process(Timestamp at_time, TimeDelta delta) {
241 time_since_update_ += delta;
242 if (config_.mode == CrossTrafficConfig::Mode::kRandomWalk) {
243 if (time_since_update_ >= config_.random_walk.update_interval) {
244 intensity_ += random_.Gaussian(config_.random_walk.bias,
245 config_.random_walk.variance) *
246 time_since_update_.seconds<double>();
247 intensity_ = rtc::SafeClamp(intensity_, 0.0, 1.0);
248 time_since_update_ = TimeDelta::Zero();
249 }
250 } else if (config_.mode == CrossTrafficConfig::Mode::kPulsedPeaks) {
251 if (intensity_ == 0 && time_since_update_ >= config_.pulsed.hold_duration) {
252 intensity_ = 1;
253 time_since_update_ = TimeDelta::Zero();
254 } else if (intensity_ == 1 &&
255 time_since_update_ >= config_.pulsed.send_duration) {
256 intensity_ = 0;
257 time_since_update_ = TimeDelta::Zero();
258 }
259 }
260 pending_size_ += TrafficRate() * delta;
261 if (pending_size_ > config_.min_packet_size) {
Sebastian Janssonf65309c2018-12-20 09:26:00262 target_->DeliverPacket(rtc::CopyOnWriteBuffer(pending_size_.bytes()),
263 receiver_id_, at_time);
Sebastian Jansson98b07e912018-09-27 11:47:01264 pending_size_ = DataSize::Zero();
265 }
266}
267
268ColumnPrinter CrossTrafficSource::StatsPrinter() {
269 return ColumnPrinter::Lambda("cross_traffic_rate",
270 [this](rtc::SimpleStringBuilder& sb) {
271 sb.AppendFormat("%.0lf",
272 TrafficRate().bps() / 8.0);
273 },
274 32);
275}
276
277} // namespace test
278} // namespace webrtc