blob: 4cd2fda1d077471f4d349de339a7ada599dc0e14 [file] [log] [blame]
Artem Titov40f51152019-01-04 15:45:01 +01001/*
2 * Copyright (c) 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
Artem Titov386802e2019-07-05 10:48:17 +020011#include "test/network/network_emulation.h"
Artem Titov40f51152019-01-04 15:45:01 +010012
Artem Titov386802e2019-07-05 10:48:17 +020013#include <algorithm>
Artem Titov0774bd92019-01-30 15:26:05 +010014#include <limits>
Artem Titov40f51152019-01-04 15:45:01 +010015#include <memory>
Artem Titov3d37e062021-02-19 20:26:32 +010016#include <utility>
Artem Titov40f51152019-01-04 15:45:01 +010017
Artem Titovd2dd7322021-01-21 17:28:17 +010018#include "absl/types/optional.h"
Artem Titovcbe6e8a2020-09-22 15:45:00 +020019#include "api/numerics/samples_stats_counter.h"
Artem Titov3d37e062021-02-19 20:26:32 +010020#include "api/test/network_emulation/network_emulation_interfaces.h"
Artem Titov806299e2019-04-12 12:17:19 +020021#include "api/units/data_size.h"
Artem Titov37d18482019-01-08 15:41:45 +010022#include "rtc_base/logging.h"
23
Artem Titov40f51152019-01-04 15:45:01 +010024namespace webrtc {
25
Artem Titov14b46a72020-07-31 12:57:24 +020026DataRate EmulatedNetworkOutgoingStatsImpl::AverageSendRate() const {
27 RTC_DCHECK_GE(packets_sent_, 2);
28 RTC_DCHECK(first_packet_sent_time_.IsFinite());
29 RTC_DCHECK(last_packet_sent_time_.IsFinite());
30 return (bytes_sent_ - first_sent_packet_size_) /
31 (last_packet_sent_time_ - first_packet_sent_time_);
32}
33
34DataRate EmulatedNetworkIncomingStatsImpl::AverageReceiveRate() const {
35 RTC_DCHECK_GE(packets_received_, 2);
36 RTC_DCHECK(first_packet_received_time_.IsFinite());
37 RTC_DCHECK(last_packet_received_time_.IsFinite());
38 return (bytes_received_ - first_received_packet_size_) /
39 (last_packet_received_time_ - first_packet_received_time_);
40}
41
42std::map<rtc::IPAddress, std::unique_ptr<EmulatedNetworkOutgoingStats>>
43EmulatedNetworkStatsImpl::OutgoingStatsPerDestination() const {
44 std::map<rtc::IPAddress, std::unique_ptr<EmulatedNetworkOutgoingStats>> out;
45 for (const auto& entry : outgoing_stats_per_destination_) {
46 out.emplace(entry.first, std::make_unique<EmulatedNetworkOutgoingStatsImpl>(
47 *entry.second));
Artem Titov3e0b65d2020-07-23 02:19:02 +020048 }
Artem Titov14b46a72020-07-31 12:57:24 +020049 return out;
Artem Titov3e0b65d2020-07-23 02:19:02 +020050}
51
Artem Titov14b46a72020-07-31 12:57:24 +020052std::map<rtc::IPAddress, std::unique_ptr<EmulatedNetworkIncomingStats>>
53EmulatedNetworkStatsImpl::IncomingStatsPerSource() const {
54 std::map<rtc::IPAddress, std::unique_ptr<EmulatedNetworkIncomingStats>> out;
55 for (const auto& entry : incoming_stats_per_source_) {
56 out.emplace(entry.first, std::make_unique<EmulatedNetworkIncomingStatsImpl>(
57 *entry.second));
58 }
59 return out;
Artem Titov3e0b65d2020-07-23 02:19:02 +020060}
Artem Titov14b46a72020-07-31 12:57:24 +020061
62std::unique_ptr<EmulatedNetworkOutgoingStats>
63EmulatedNetworkStatsImpl::GetOverallOutgoingStats() const {
64 EmulatedNetworkOutgoingStatsBuilder builder;
65 for (const auto& entry : outgoing_stats_per_destination_) {
66 builder.AddOutgoingStats(*entry.second);
67 }
68 return builder.Build();
69}
70
71std::unique_ptr<EmulatedNetworkIncomingStats>
72EmulatedNetworkStatsImpl::GetOverallIncomingStats() const {
73 EmulatedNetworkIncomingStatsBuilder builder;
74 for (const auto& entry : incoming_stats_per_source_) {
75 builder.AddIncomingStats(*entry.second);
76 }
77 return builder.Build();
78}
79
80EmulatedNetworkOutgoingStatsBuilder::EmulatedNetworkOutgoingStatsBuilder() {
Artem Titov3e0b65d2020-07-23 02:19:02 +020081 sequence_checker_.Detach();
82}
83
Artem Titovcbe6e8a2020-09-22 15:45:00 +020084void EmulatedNetworkOutgoingStatsBuilder::OnPacketSent(
85 Timestamp sent_time,
86 DataSize packet_size,
87 EmulatedEndpointConfig::StatsGatheringMode mode) {
Artem Titov3e0b65d2020-07-23 02:19:02 +020088 RTC_DCHECK_RUN_ON(&sequence_checker_);
89 RTC_CHECK_GE(packet_size, DataSize::Zero());
90 if (first_packet_sent_time_.IsInfinite()) {
91 first_packet_sent_time_ = sent_time;
92 first_sent_packet_size_ = packet_size;
93 }
94 last_packet_sent_time_ = sent_time;
95 packets_sent_++;
96 bytes_sent_ += packet_size;
Artem Titovcbe6e8a2020-09-22 15:45:00 +020097 if (mode == EmulatedEndpointConfig::StatsGatheringMode::kDebug) {
98 sent_packets_size_counter_.AddSample(packet_size.bytes());
99 }
Artem Titov3e0b65d2020-07-23 02:19:02 +0200100}
101
Artem Titov14b46a72020-07-31 12:57:24 +0200102void EmulatedNetworkOutgoingStatsBuilder::AddOutgoingStats(
103 const EmulatedNetworkOutgoingStats& stats) {
104 RTC_DCHECK_RUN_ON(&sequence_checker_);
105 packets_sent_ += stats.PacketsSent();
106 bytes_sent_ += stats.BytesSent();
Artem Titovcbe6e8a2020-09-22 15:45:00 +0200107 sent_packets_size_counter_.AddSamples(stats.SentPacketsSizeCounter());
Artem Titov14b46a72020-07-31 12:57:24 +0200108 if (first_packet_sent_time_ > stats.FirstPacketSentTime()) {
109 first_packet_sent_time_ = stats.FirstPacketSentTime();
110 first_sent_packet_size_ = stats.FirstSentPacketSize();
111 }
112 if (last_packet_sent_time_ < stats.LastPacketSentTime()) {
113 last_packet_sent_time_ = stats.LastPacketSentTime();
114 }
115}
116
117std::unique_ptr<EmulatedNetworkOutgoingStats>
118EmulatedNetworkOutgoingStatsBuilder::Build() const {
119 RTC_DCHECK_RUN_ON(&sequence_checker_);
120 return std::make_unique<EmulatedNetworkOutgoingStatsImpl>(
Artem Titovcbe6e8a2020-09-22 15:45:00 +0200121 packets_sent_, bytes_sent_, sent_packets_size_counter_,
122 first_sent_packet_size_, first_packet_sent_time_, last_packet_sent_time_);
Artem Titov14b46a72020-07-31 12:57:24 +0200123}
124
125EmulatedNetworkIncomingStatsBuilder::EmulatedNetworkIncomingStatsBuilder() {
126 sequence_checker_.Detach();
127}
128
129void EmulatedNetworkIncomingStatsBuilder::OnPacketDropped(
Artem Titovcbe6e8a2020-09-22 15:45:00 +0200130 DataSize packet_size,
131 EmulatedEndpointConfig::StatsGatheringMode mode) {
Artem Titov14b46a72020-07-31 12:57:24 +0200132 RTC_DCHECK_RUN_ON(&sequence_checker_);
133 packets_dropped_++;
134 bytes_dropped_ += packet_size;
Artem Titovcbe6e8a2020-09-22 15:45:00 +0200135 if (mode == EmulatedEndpointConfig::StatsGatheringMode::kDebug) {
136 dropped_packets_size_counter_.AddSample(packet_size.bytes());
137 }
Artem Titov14b46a72020-07-31 12:57:24 +0200138}
139
140void EmulatedNetworkIncomingStatsBuilder::OnPacketReceived(
141 Timestamp received_time,
Artem Titovcbe6e8a2020-09-22 15:45:00 +0200142 DataSize packet_size,
143 EmulatedEndpointConfig::StatsGatheringMode mode) {
Artem Titov14b46a72020-07-31 12:57:24 +0200144 RTC_DCHECK_RUN_ON(&sequence_checker_);
145 RTC_CHECK_GE(packet_size, DataSize::Zero());
146 if (first_packet_received_time_.IsInfinite()) {
147 first_packet_received_time_ = received_time;
148 first_received_packet_size_ = packet_size;
149 }
150 last_packet_received_time_ = received_time;
151 packets_received_++;
152 bytes_received_ += packet_size;
Artem Titovcbe6e8a2020-09-22 15:45:00 +0200153 if (mode == EmulatedEndpointConfig::StatsGatheringMode::kDebug) {
154 received_packets_size_counter_.AddSample(packet_size.bytes());
155 }
Artem Titov14b46a72020-07-31 12:57:24 +0200156}
157
158void EmulatedNetworkIncomingStatsBuilder::AddIncomingStats(
159 const EmulatedNetworkIncomingStats& stats) {
160 RTC_DCHECK_RUN_ON(&sequence_checker_);
161 packets_received_ += stats.PacketsReceived();
162 bytes_received_ += stats.BytesReceived();
Artem Titovcbe6e8a2020-09-22 15:45:00 +0200163 received_packets_size_counter_.AddSamples(stats.ReceivedPacketsSizeCounter());
Artem Titov14b46a72020-07-31 12:57:24 +0200164 packets_dropped_ += stats.PacketsDropped();
165 bytes_dropped_ += stats.BytesDropped();
Artem Titovcbe6e8a2020-09-22 15:45:00 +0200166 dropped_packets_size_counter_.AddSamples(stats.DroppedPacketsSizeCounter());
Artem Titov14b46a72020-07-31 12:57:24 +0200167 if (first_packet_received_time_ > stats.FirstPacketReceivedTime()) {
168 first_packet_received_time_ = stats.FirstPacketReceivedTime();
169 first_received_packet_size_ = stats.FirstReceivedPacketSize();
170 }
171 if (last_packet_received_time_ < stats.LastPacketReceivedTime()) {
172 last_packet_received_time_ = stats.LastPacketReceivedTime();
173 }
174}
175
176std::unique_ptr<EmulatedNetworkIncomingStats>
177EmulatedNetworkIncomingStatsBuilder::Build() const {
178 RTC_DCHECK_RUN_ON(&sequence_checker_);
179 return std::make_unique<EmulatedNetworkIncomingStatsImpl>(
Artem Titovcbe6e8a2020-09-22 15:45:00 +0200180 packets_received_, bytes_received_, received_packets_size_counter_,
181 packets_dropped_, bytes_dropped_, dropped_packets_size_counter_,
Artem Titov14b46a72020-07-31 12:57:24 +0200182 first_received_packet_size_, first_packet_received_time_,
183 last_packet_received_time_);
184}
185
186EmulatedNetworkStatsBuilder::EmulatedNetworkStatsBuilder() {
187 sequence_checker_.Detach();
188}
189
190EmulatedNetworkStatsBuilder::EmulatedNetworkStatsBuilder(
191 rtc::IPAddress local_ip) {
192 local_addresses_.push_back(local_ip);
193 sequence_checker_.Detach();
194}
195
Artem Titovcbe6e8a2020-09-22 15:45:00 +0200196void EmulatedNetworkStatsBuilder::OnPacketSent(
197 Timestamp queued_time,
198 Timestamp sent_time,
199 rtc::IPAddress destination_ip,
200 DataSize packet_size,
201 EmulatedEndpointConfig::StatsGatheringMode mode) {
Artem Titov14b46a72020-07-31 12:57:24 +0200202 RTC_DCHECK_RUN_ON(&sequence_checker_);
Artem Titovcbe6e8a2020-09-22 15:45:00 +0200203 if (mode == EmulatedEndpointConfig::StatsGatheringMode::kDebug) {
204 sent_packets_queue_wait_time_us_.AddSample((sent_time - queued_time).us());
205 }
206 outgoing_stats_per_destination_[destination_ip].OnPacketSent(
207 sent_time, packet_size, mode);
Artem Titov14b46a72020-07-31 12:57:24 +0200208}
209
Artem Titovcbe6e8a2020-09-22 15:45:00 +0200210void EmulatedNetworkStatsBuilder::OnPacketDropped(
211 rtc::IPAddress source_ip,
212 DataSize packet_size,
213 EmulatedEndpointConfig::StatsGatheringMode mode) {
Artem Titov3e0b65d2020-07-23 02:19:02 +0200214 RTC_DCHECK_RUN_ON(&sequence_checker_);
Artem Titovcbe6e8a2020-09-22 15:45:00 +0200215 incoming_stats_per_source_[source_ip].OnPacketDropped(packet_size, mode);
Artem Titov3e0b65d2020-07-23 02:19:02 +0200216}
217
Artem Titovcbe6e8a2020-09-22 15:45:00 +0200218void EmulatedNetworkStatsBuilder::OnPacketReceived(
219 Timestamp received_time,
220 rtc::IPAddress source_ip,
221 DataSize packet_size,
222 EmulatedEndpointConfig::StatsGatheringMode mode) {
Artem Titov3e0b65d2020-07-23 02:19:02 +0200223 RTC_DCHECK_RUN_ON(&sequence_checker_);
Artem Titov14b46a72020-07-31 12:57:24 +0200224 incoming_stats_per_source_[source_ip].OnPacketReceived(received_time,
Artem Titovcbe6e8a2020-09-22 15:45:00 +0200225 packet_size, mode);
Artem Titov3e0b65d2020-07-23 02:19:02 +0200226}
227
Artem Titov14b46a72020-07-31 12:57:24 +0200228void EmulatedNetworkStatsBuilder::AddEmulatedNetworkStats(
229 const EmulatedNetworkStats& stats) {
Artem Titov3e0b65d2020-07-23 02:19:02 +0200230 RTC_DCHECK_RUN_ON(&sequence_checker_);
Artem Titov14b46a72020-07-31 12:57:24 +0200231
232 // Append IPs from other endpoints stats to the builder.
233 for (const rtc::IPAddress& addr : stats.LocalAddresses()) {
Artem Titov3e0b65d2020-07-23 02:19:02 +0200234 local_addresses_.push_back(addr);
235 }
236
Artem Titovcbe6e8a2020-09-22 15:45:00 +0200237 sent_packets_queue_wait_time_us_.AddSamples(
238 stats.SentPacketsQueueWaitTimeUs());
239
Artem Titov14b46a72020-07-31 12:57:24 +0200240 // Add outgoing stats from other endpoints to the builder.
241 const std::map<rtc::IPAddress, std::unique_ptr<EmulatedNetworkOutgoingStats>>
242 outgoing_stats_per_destination = stats.OutgoingStatsPerDestination();
243 for (const auto& entry : outgoing_stats_per_destination) {
244 outgoing_stats_per_destination_[entry.first].AddOutgoingStats(
245 *entry.second);
246 }
247
248 // Add incoming stats from other endpoints to the builder.
249 const std::map<rtc::IPAddress, std::unique_ptr<EmulatedNetworkIncomingStats>>
250 incoming_stats_per_source = stats.IncomingStatsPerSource();
Artem Titov3e0b65d2020-07-23 02:19:02 +0200251 for (const auto& entry : incoming_stats_per_source) {
Artem Titov14b46a72020-07-31 12:57:24 +0200252 incoming_stats_per_source_[entry.first].AddIncomingStats(*entry.second);
Artem Titov3e0b65d2020-07-23 02:19:02 +0200253 }
254}
255
256std::unique_ptr<EmulatedNetworkStats> EmulatedNetworkStatsBuilder::Build()
257 const {
258 RTC_DCHECK_RUN_ON(&sequence_checker_);
Artem Titov14b46a72020-07-31 12:57:24 +0200259 std::map<rtc::IPAddress, std::unique_ptr<EmulatedNetworkOutgoingStats>>
260 outgoing_stats;
261 for (const auto& entry : outgoing_stats_per_destination_) {
262 outgoing_stats.emplace(entry.first, entry.second.Build());
263 }
264 std::map<rtc::IPAddress, std::unique_ptr<EmulatedNetworkIncomingStats>>
265 incoming_stats;
266 for (const auto& entry : incoming_stats_per_source_) {
267 incoming_stats.emplace(entry.first, entry.second.Build());
268 }
Artem Titov3e0b65d2020-07-23 02:19:02 +0200269 return std::make_unique<EmulatedNetworkStatsImpl>(
Artem Titovcbe6e8a2020-09-22 15:45:00 +0200270 local_addresses_, sent_packets_queue_wait_time_us_,
271 std::move(outgoing_stats), std::move(incoming_stats));
Artem Titov3e0b65d2020-07-23 02:19:02 +0200272}
273
Sebastian Jansson62bb47f2019-04-01 18:23:58 +0200274void LinkEmulation::OnPacketReceived(EmulatedIpPacket packet) {
Sebastian Janssonee5ec9a2019-09-17 20:34:03 +0200275 task_queue_->PostTask([this, packet = std::move(packet)]() mutable {
276 RTC_DCHECK_RUN_ON(task_queue_);
Sebastian Jansson4124dab2019-04-01 14:33:53 +0200277
Sebastian Janssonee5ec9a2019-09-17 20:34:03 +0200278 uint64_t packet_id = next_packet_id_++;
Niels Möller7536bc52019-10-04 13:54:39 +0200279 bool sent = network_behavior_->EnqueuePacket(PacketInFlightInfo(
280 packet.ip_packet_size(), packet.arrival_time.us(), packet_id));
Sebastian Janssonee5ec9a2019-09-17 20:34:03 +0200281 if (sent) {
282 packets_.emplace_back(StoredPacket{packet_id, std::move(packet), false});
283 }
284 if (process_task_.Running())
285 return;
286 absl::optional<int64_t> next_time_us =
287 network_behavior_->NextDeliveryTimeUs();
288 if (!next_time_us)
289 return;
290 Timestamp current_time = clock_->CurrentTime();
291 process_task_ = RepeatingTaskHandle::DelayedStart(
292 task_queue_->Get(),
293 std::max(TimeDelta::Zero(),
Danil Chapovalov0c626af2020-02-10 11:16:00 +0100294 Timestamp::Micros(*next_time_us) - current_time),
Sebastian Janssonee5ec9a2019-09-17 20:34:03 +0200295 [this]() {
296 RTC_DCHECK_RUN_ON(task_queue_);
297 Timestamp current_time = clock_->CurrentTime();
298 Process(current_time);
299 absl::optional<int64_t> next_time_us =
300 network_behavior_->NextDeliveryTimeUs();
301 if (!next_time_us) {
302 process_task_.Stop();
303 return TimeDelta::Zero(); // This is ignored.
304 }
305 RTC_DCHECK_GE(*next_time_us, current_time.us());
Danil Chapovalov0c626af2020-02-10 11:16:00 +0100306 return Timestamp::Micros(*next_time_us) - current_time;
Sebastian Janssonee5ec9a2019-09-17 20:34:03 +0200307 });
308 });
Artem Titov37d18482019-01-08 15:41:45 +0100309}
310
Sebastian Jansson62bb47f2019-04-01 18:23:58 +0200311void LinkEmulation::Process(Timestamp at_time) {
Sebastian Jansson4124dab2019-04-01 14:33:53 +0200312 std::vector<PacketDeliveryInfo> delivery_infos =
313 network_behavior_->DequeueDeliverablePackets(at_time.us());
Artem Titov37d18482019-01-08 15:41:45 +0100314 for (PacketDeliveryInfo& delivery_info : delivery_infos) {
315 StoredPacket* packet = nullptr;
Sebastian Jansson4124dab2019-04-01 14:33:53 +0200316 for (auto& stored_packet : packets_) {
317 if (stored_packet.id == delivery_info.packet_id) {
318 packet = &stored_packet;
319 break;
Artem Titov37d18482019-01-08 15:41:45 +0100320 }
Artem Titov37d18482019-01-08 15:41:45 +0100321 }
Sebastian Jansson4124dab2019-04-01 14:33:53 +0200322 RTC_CHECK(packet);
323 RTC_DCHECK(!packet->removed);
Sebastian Jansson4124dab2019-04-01 14:33:53 +0200324 packet->removed = true;
325
Johannes Krona8f9e252019-01-24 15:38:23 +0100326 if (delivery_info.receive_time_us != PacketDeliveryInfo::kNotReceived) {
327 packet->packet.arrival_time =
Danil Chapovalov0c626af2020-02-10 11:16:00 +0100328 Timestamp::Micros(delivery_info.receive_time_us);
Sebastian Jansson62bb47f2019-04-01 18:23:58 +0200329 receiver_->OnPacketReceived(std::move(packet->packet));
Johannes Krona8f9e252019-01-24 15:38:23 +0100330 }
Sebastian Jansson4124dab2019-04-01 14:33:53 +0200331 while (!packets_.empty() && packets_.front().removed) {
332 packets_.pop_front();
Artem Titov37d18482019-01-08 15:41:45 +0100333 }
334 }
335}
336
Sebastian Jansson62bb47f2019-04-01 18:23:58 +0200337NetworkRouterNode::NetworkRouterNode(rtc::TaskQueue* task_queue)
338 : task_queue_(task_queue) {}
339
340void NetworkRouterNode::OnPacketReceived(EmulatedIpPacket packet) {
341 RTC_DCHECK_RUN_ON(task_queue_);
Sebastian Jansson71c6b562019-08-14 11:31:02 +0200342 if (watcher_) {
343 watcher_(packet);
344 }
Sebastian Jansson3d4d94a2020-01-14 14:25:41 +0100345 if (filter_) {
346 if (!filter_(packet))
347 return;
348 }
Sebastian Jansson62bb47f2019-04-01 18:23:58 +0200349 auto receiver_it = routing_.find(packet.to.ipaddr());
350 if (receiver_it == routing_.end()) {
Artem Titov3d37e062021-02-19 20:26:32 +0100351 if (default_receiver_.has_value()) {
352 (*default_receiver_)->OnPacketReceived(std::move(packet));
353 }
Sebastian Jansson62bb47f2019-04-01 18:23:58 +0200354 return;
355 }
356 RTC_CHECK(receiver_it != routing_.end());
357
358 receiver_it->second->OnPacketReceived(std::move(packet));
359}
360
361void NetworkRouterNode::SetReceiver(
Yves Gerey2257c082020-01-03 12:37:56 +0100362 const rtc::IPAddress& dest_ip,
Artem Titov37d18482019-01-08 15:41:45 +0100363 EmulatedNetworkReceiverInterface* receiver) {
Sebastian Jansson4124dab2019-04-01 14:33:53 +0200364 task_queue_->PostTask([=] {
365 RTC_DCHECK_RUN_ON(task_queue_);
366 EmulatedNetworkReceiverInterface* cur_receiver = routing_[dest_ip];
367 RTC_CHECK(cur_receiver == nullptr || cur_receiver == receiver)
368 << "Routing for dest_ip=" << dest_ip.ToString() << " already exists";
369 routing_[dest_ip] = receiver;
370 });
Artem Titov37d18482019-01-08 15:41:45 +0100371}
372
Yves Gerey2257c082020-01-03 12:37:56 +0100373void NetworkRouterNode::RemoveReceiver(const rtc::IPAddress& dest_ip) {
Sebastian Jansson4124dab2019-04-01 14:33:53 +0200374 RTC_DCHECK_RUN_ON(task_queue_);
Artem Titov4cd433e2019-04-01 11:01:16 +0200375 routing_.erase(dest_ip);
Artem Titov37d18482019-01-08 15:41:45 +0100376}
377
Artem Titov3d37e062021-02-19 20:26:32 +0100378void NetworkRouterNode::SetDefaultReceiver(
379 EmulatedNetworkReceiverInterface* receiver) {
380 task_queue_->PostTask([=] {
381 RTC_DCHECK_RUN_ON(task_queue_);
382 if (default_receiver_.has_value()) {
383 RTC_CHECK_EQ(*default_receiver_, receiver)
384 << "Router already default receiver";
385 }
386 default_receiver_ = receiver;
387 });
388}
389
390void NetworkRouterNode::RemoveDefaultReceiver() {
391 RTC_DCHECK_RUN_ON(task_queue_);
392 default_receiver_ = absl::nullopt;
393}
394
Sebastian Jansson71c6b562019-08-14 11:31:02 +0200395void NetworkRouterNode::SetWatcher(
396 std::function<void(const EmulatedIpPacket&)> watcher) {
397 task_queue_->PostTask([=] {
398 RTC_DCHECK_RUN_ON(task_queue_);
399 watcher_ = watcher;
400 });
401}
402
Sebastian Jansson3d4d94a2020-01-14 14:25:41 +0100403void NetworkRouterNode::SetFilter(
404 std::function<bool(const EmulatedIpPacket&)> filter) {
405 task_queue_->PostTask([=] {
406 RTC_DCHECK_RUN_ON(task_queue_);
407 filter_ = filter;
408 });
409}
410
Sebastian Jansson62bb47f2019-04-01 18:23:58 +0200411EmulatedNetworkNode::EmulatedNetworkNode(
412 Clock* clock,
413 rtc::TaskQueue* task_queue,
414 std::unique_ptr<NetworkBehaviorInterface> network_behavior)
415 : router_(task_queue),
416 link_(clock, task_queue, std::move(network_behavior), &router_) {}
417
418void EmulatedNetworkNode::OnPacketReceived(EmulatedIpPacket packet) {
419 link_.OnPacketReceived(std::move(packet));
420}
421
422void EmulatedNetworkNode::CreateRoute(
Yves Gerey2257c082020-01-03 12:37:56 +0100423 const rtc::IPAddress& receiver_ip,
Sebastian Jansson62bb47f2019-04-01 18:23:58 +0200424 std::vector<EmulatedNetworkNode*> nodes,
425 EmulatedNetworkReceiverInterface* receiver) {
426 RTC_CHECK(!nodes.empty());
427 for (size_t i = 0; i + 1 < nodes.size(); ++i)
428 nodes[i]->router()->SetReceiver(receiver_ip, nodes[i + 1]);
429 nodes.back()->router()->SetReceiver(receiver_ip, receiver);
430}
431
Yves Gerey2257c082020-01-03 12:37:56 +0100432void EmulatedNetworkNode::ClearRoute(const rtc::IPAddress& receiver_ip,
Sebastian Jansson62bb47f2019-04-01 18:23:58 +0200433 std::vector<EmulatedNetworkNode*> nodes) {
434 for (EmulatedNetworkNode* node : nodes)
435 node->router()->RemoveReceiver(receiver_ip);
436}
437
438EmulatedNetworkNode::~EmulatedNetworkNode() = default;
439
Artem Titov3d37e062021-02-19 20:26:32 +0100440EmulatedEndpointImpl::Options::Options(uint64_t id,
441 const rtc::IPAddress& ip,
442 const EmulatedEndpointConfig& config)
443 : id(id),
444 ip(ip),
445 stats_gathering_mode(config.stats_gathering_mode),
446 type(config.type),
447 allow_send_packet_with_different_source_ip(
448 config.allow_send_packet_with_different_source_ip),
449 allow_receive_packets_with_different_dest_ip(
Artem Titov28547e92021-02-22 15:01:38 +0100450 config.allow_receive_packets_with_different_dest_ip),
Artem Titov3d37e062021-02-19 20:26:32 +0100451 log_name(ip.ToString() + " (" + config.name.value_or("") + ")") {}
452
453EmulatedEndpointImpl::EmulatedEndpointImpl(const Options& options,
454 bool is_enabled,
455 rtc::TaskQueue* task_queue,
456 Clock* clock)
457 : options_(options),
Artem Titove5cc85b2019-03-28 12:11:09 +0100458 is_enabled_(is_enabled),
Artem Titov0774bd92019-01-30 15:26:05 +0100459 clock_(clock),
Artem Titovff393122019-04-05 11:19:52 +0200460 task_queue_(task_queue),
461 router_(task_queue_),
Artem Titov3e0b65d2020-07-23 02:19:02 +0200462 next_port_(kFirstEphemeralPort),
Artem Titov3d37e062021-02-19 20:26:32 +0100463 stats_builder_(options_.ip) {
Artem Titove5cc85b2019-03-28 12:11:09 +0100464 constexpr int kIPv4NetworkPrefixLength = 24;
465 constexpr int kIPv6NetworkPrefixLength = 64;
466
467 int prefix_length = 0;
Artem Titov3d37e062021-02-19 20:26:32 +0100468 if (options_.ip.family() == AF_INET) {
Artem Titove5cc85b2019-03-28 12:11:09 +0100469 prefix_length = kIPv4NetworkPrefixLength;
Artem Titov3d37e062021-02-19 20:26:32 +0100470 } else if (options_.ip.family() == AF_INET6) {
Artem Titove5cc85b2019-03-28 12:11:09 +0100471 prefix_length = kIPv6NetworkPrefixLength;
472 }
Artem Titov3d37e062021-02-19 20:26:32 +0100473 rtc::IPAddress prefix = TruncateIP(options_.ip, prefix_length);
Mirko Bonadei317a1f02019-09-17 17:06:18 +0200474 network_ = std::make_unique<rtc::Network>(
Artem Titov3d37e062021-02-19 20:26:32 +0100475 options_.ip.ToString(), "Endpoint id=" + std::to_string(options_.id),
476 prefix, prefix_length, options_.type);
477 network_->AddIP(options_.ip);
Artem Titove5cc85b2019-03-28 12:11:09 +0100478
Sebastian Janssonc01367d2019-04-08 15:20:44 +0200479 enabled_state_checker_.Detach();
Harald Alvestrand97597c02021-11-04 12:01:23 +0000480 RTC_LOG(LS_INFO) << "Created emulated endpoint " << options_.log_name
481 << "; id=" << options_.id;
Artem Titove5cc85b2019-03-28 12:11:09 +0100482}
Sebastian Janssoncec24332019-12-04 14:26:50 +0100483EmulatedEndpointImpl::~EmulatedEndpointImpl() = default;
Artem Titov0774bd92019-01-30 15:26:05 +0100484
Sebastian Janssoncec24332019-12-04 14:26:50 +0100485uint64_t EmulatedEndpointImpl::GetId() const {
Artem Titov3d37e062021-02-19 20:26:32 +0100486 return options_.id;
Artem Titov0774bd92019-01-30 15:26:05 +0100487}
488
Sebastian Janssoncec24332019-12-04 14:26:50 +0100489void EmulatedEndpointImpl::SendPacket(const rtc::SocketAddress& from,
490 const rtc::SocketAddress& to,
Sebastian Jansson77bd3852020-01-17 13:05:54 +0100491 rtc::CopyOnWriteBuffer packet_data,
492 uint16_t application_overhead) {
Artem Titov3d37e062021-02-19 20:26:32 +0100493 if (!options_.allow_send_packet_with_different_source_ip) {
494 RTC_CHECK(from.ipaddr() == options_.ip);
495 }
Sebastian Janssonee5ec9a2019-09-17 20:34:03 +0200496 EmulatedIpPacket packet(from, to, std::move(packet_data),
Sebastian Jansson77bd3852020-01-17 13:05:54 +0100497 clock_->CurrentTime(), application_overhead);
Sebastian Janssonee5ec9a2019-09-17 20:34:03 +0200498 task_queue_->PostTask([this, packet = std::move(packet)]() mutable {
499 RTC_DCHECK_RUN_ON(task_queue_);
Artem Titov3d37e062021-02-19 20:26:32 +0100500 stats_builder_.OnPacketSent(packet.arrival_time, clock_->CurrentTime(),
501 packet.to.ipaddr(),
502 DataSize::Bytes(packet.ip_packet_size()),
503 options_.stats_gathering_mode);
Sebastian Janssonee5ec9a2019-09-17 20:34:03 +0200504
Artem Titov3d37e062021-02-19 20:26:32 +0100505 if (packet.to.ipaddr() == options_.ip) {
Artem Titov5d555972020-11-12 16:15:44 +0100506 OnPacketReceived(std::move(packet));
507 } else {
508 router_.OnPacketReceived(std::move(packet));
509 }
Sebastian Janssonee5ec9a2019-09-17 20:34:03 +0200510 });
Artem Titov0774bd92019-01-30 15:26:05 +0100511}
512
Sebastian Janssoncec24332019-12-04 14:26:50 +0100513absl::optional<uint16_t> EmulatedEndpointImpl::BindReceiver(
Artem Titov0774bd92019-01-30 15:26:05 +0100514 uint16_t desired_port,
515 EmulatedNetworkReceiverInterface* receiver) {
Niels Möller376cf382021-02-26 09:24:51 +0100516 return BindReceiverInternal(desired_port, receiver, /*is_one_shot=*/false);
517}
518
519absl::optional<uint16_t> EmulatedEndpointImpl::BindOneShotReceiver(
520 uint16_t desired_port,
521 EmulatedNetworkReceiverInterface* receiver) {
522 return BindReceiverInternal(desired_port, receiver, /*is_one_shot=*/true);
523}
524
525absl::optional<uint16_t> EmulatedEndpointImpl::BindReceiverInternal(
526 uint16_t desired_port,
527 EmulatedNetworkReceiverInterface* receiver,
528 bool is_one_shot) {
529 MutexLock lock(&receiver_lock_);
Artem Titov0774bd92019-01-30 15:26:05 +0100530 uint16_t port = desired_port;
531 if (port == 0) {
532 // Because client can specify its own port, next_port_ can be already in
533 // use, so we need to find next available port.
534 int ports_pool_size =
535 std::numeric_limits<uint16_t>::max() - kFirstEphemeralPort + 1;
536 for (int i = 0; i < ports_pool_size; ++i) {
537 uint16_t next_port = NextPort();
538 if (port_to_receiver_.find(next_port) == port_to_receiver_.end()) {
539 port = next_port;
540 break;
541 }
542 }
543 }
544 RTC_CHECK(port != 0) << "Can't find free port for receiver in endpoint "
Artem Titov3d37e062021-02-19 20:26:32 +0100545 << options_.log_name << "; id=" << options_.id;
Niels Möller376cf382021-02-26 09:24:51 +0100546 bool result =
547 port_to_receiver_.insert({port, {receiver, is_one_shot}}).second;
Artem Titov0774bd92019-01-30 15:26:05 +0100548 if (!result) {
Harald Alvestrand97597c02021-11-04 12:01:23 +0000549 RTC_LOG(LS_INFO) << "Can't bind receiver to used port " << desired_port
550 << " in endpoint " << options_.log_name
551 << "; id=" << options_.id;
Artem Titov0774bd92019-01-30 15:26:05 +0100552 return absl::nullopt;
553 }
Harald Alvestrand97597c02021-11-04 12:01:23 +0000554 RTC_LOG(LS_INFO) << "New receiver is binded to endpoint " << options_.log_name
555 << "; id=" << options_.id << " on port " << port;
Artem Titov0774bd92019-01-30 15:26:05 +0100556 return port;
557}
558
Sebastian Janssoncec24332019-12-04 14:26:50 +0100559uint16_t EmulatedEndpointImpl::NextPort() {
Artem Titov0774bd92019-01-30 15:26:05 +0100560 uint16_t out = next_port_;
561 if (next_port_ == std::numeric_limits<uint16_t>::max()) {
562 next_port_ = kFirstEphemeralPort;
563 } else {
564 next_port_++;
565 }
566 return out;
567}
568
Sebastian Janssoncec24332019-12-04 14:26:50 +0100569void EmulatedEndpointImpl::UnbindReceiver(uint16_t port) {
Niels Möller376cf382021-02-26 09:24:51 +0100570 MutexLock lock(&receiver_lock_);
Harald Alvestrand97597c02021-11-04 12:01:23 +0000571 RTC_LOG(LS_INFO) << "Receiver is removed on port " << port
572 << " from endpoint " << options_.log_name
573 << "; id=" << options_.id;
Artem Titov0774bd92019-01-30 15:26:05 +0100574 port_to_receiver_.erase(port);
575}
576
Artem Titov3d37e062021-02-19 20:26:32 +0100577void EmulatedEndpointImpl::BindDefaultReceiver(
578 EmulatedNetworkReceiverInterface* receiver) {
Niels Möller376cf382021-02-26 09:24:51 +0100579 MutexLock lock(&receiver_lock_);
Artem Titov3d37e062021-02-19 20:26:32 +0100580 RTC_CHECK(!default_receiver_.has_value())
581 << "Endpoint " << options_.log_name << "; id=" << options_.id
582 << " already has default receiver";
Harald Alvestrand97597c02021-11-04 12:01:23 +0000583 RTC_LOG(LS_INFO) << "Default receiver is binded to endpoint "
584 << options_.log_name << "; id=" << options_.id;
Artem Titov3d37e062021-02-19 20:26:32 +0100585 default_receiver_ = receiver;
586}
587
588void EmulatedEndpointImpl::UnbindDefaultReceiver() {
Niels Möller376cf382021-02-26 09:24:51 +0100589 MutexLock lock(&receiver_lock_);
Harald Alvestrand97597c02021-11-04 12:01:23 +0000590 RTC_LOG(LS_INFO) << "Default receiver is removed from endpoint "
591 << options_.log_name << "; id=" << options_.id;
Artem Titov3d37e062021-02-19 20:26:32 +0100592 default_receiver_ = absl::nullopt;
593}
594
Sebastian Janssoncec24332019-12-04 14:26:50 +0100595rtc::IPAddress EmulatedEndpointImpl::GetPeerLocalAddress() const {
Artem Titov3d37e062021-02-19 20:26:32 +0100596 return options_.ip;
Artem Titov0774bd92019-01-30 15:26:05 +0100597}
598
Sebastian Janssoncec24332019-12-04 14:26:50 +0100599void EmulatedEndpointImpl::OnPacketReceived(EmulatedIpPacket packet) {
Artem Titov806299e2019-04-12 12:17:19 +0200600 RTC_DCHECK_RUN_ON(task_queue_);
Artem Titov28547e92021-02-22 15:01:38 +0100601 if (!options_.allow_receive_packets_with_different_dest_ip) {
Artem Titov3d37e062021-02-19 20:26:32 +0100602 RTC_CHECK(packet.to.ipaddr() == options_.ip)
603 << "Routing error: wrong destination endpoint. Packet.to.ipaddr()=: "
604 << packet.to.ipaddr().ToString()
605 << "; Receiver options_.ip=" << options_.ip.ToString();
606 }
Niels Möller376cf382021-02-26 09:24:51 +0100607 MutexLock lock(&receiver_lock_);
Artem Titov3e0b65d2020-07-23 02:19:02 +0200608 stats_builder_.OnPacketReceived(clock_->CurrentTime(), packet.from.ipaddr(),
Artem Titovcbe6e8a2020-09-22 15:45:00 +0200609 DataSize::Bytes(packet.ip_packet_size()),
Artem Titov3d37e062021-02-19 20:26:32 +0100610 options_.stats_gathering_mode);
Artem Titov0774bd92019-01-30 15:26:05 +0100611 auto it = port_to_receiver_.find(packet.to.port());
612 if (it == port_to_receiver_.end()) {
Artem Titov3d37e062021-02-19 20:26:32 +0100613 if (default_receiver_.has_value()) {
614 (*default_receiver_)->OnPacketReceived(std::move(packet));
615 return;
616 }
Artem Titov0774bd92019-01-30 15:26:05 +0100617 // It can happen, that remote peer closed connection, but there still some
618 // packets, that are going to it. It can happen during peer connection close
619 // process: one peer closed connection, second still sending data.
Harald Alvestrand97597c02021-11-04 12:01:23 +0000620 RTC_LOG(LS_INFO) << "Drop packet: no receiver registered in "
621 << options_.log_name << "; id=" << options_.id
622 << " on port " << packet.to.port();
Artem Titov3e0b65d2020-07-23 02:19:02 +0200623 stats_builder_.OnPacketDropped(packet.from.ipaddr(),
Artem Titovcbe6e8a2020-09-22 15:45:00 +0200624 DataSize::Bytes(packet.ip_packet_size()),
Artem Titov3d37e062021-02-19 20:26:32 +0100625 options_.stats_gathering_mode);
Artem Titov0774bd92019-01-30 15:26:05 +0100626 return;
627 }
Niels Möller376cf382021-02-26 09:24:51 +0100628 // Endpoint holds lock during packet processing to ensure that a call to
629 // UnbindReceiver followed by a delete of the receiver cannot race with this
630 // call to OnPacketReceived.
631 it->second.receiver->OnPacketReceived(std::move(packet));
632
633 if (it->second.is_one_shot) {
634 port_to_receiver_.erase(it);
635 }
Artem Titov0774bd92019-01-30 15:26:05 +0100636}
637
Sebastian Janssoncec24332019-12-04 14:26:50 +0100638void EmulatedEndpointImpl::Enable() {
Artem Titove5cc85b2019-03-28 12:11:09 +0100639 RTC_DCHECK_RUN_ON(&enabled_state_checker_);
640 RTC_CHECK(!is_enabled_);
641 is_enabled_ = true;
642}
643
Sebastian Janssoncec24332019-12-04 14:26:50 +0100644void EmulatedEndpointImpl::Disable() {
Artem Titove5cc85b2019-03-28 12:11:09 +0100645 RTC_DCHECK_RUN_ON(&enabled_state_checker_);
646 RTC_CHECK(is_enabled_);
647 is_enabled_ = false;
648}
649
Sebastian Janssoncec24332019-12-04 14:26:50 +0100650bool EmulatedEndpointImpl::Enabled() const {
Artem Titove5cc85b2019-03-28 12:11:09 +0100651 RTC_DCHECK_RUN_ON(&enabled_state_checker_);
652 return is_enabled_;
653}
654
Artem Titov3e0b65d2020-07-23 02:19:02 +0200655std::unique_ptr<EmulatedNetworkStats> EmulatedEndpointImpl::stats() const {
Artem Titov806299e2019-04-12 12:17:19 +0200656 RTC_DCHECK_RUN_ON(task_queue_);
Artem Titov3e0b65d2020-07-23 02:19:02 +0200657 return stats_builder_.Build();
Artem Titov806299e2019-04-12 12:17:19 +0200658}
659
Artem Titove5cc85b2019-03-28 12:11:09 +0100660EndpointsContainer::EndpointsContainer(
Sebastian Janssoncec24332019-12-04 14:26:50 +0100661 const std::vector<EmulatedEndpointImpl*>& endpoints)
Artem Titove5cc85b2019-03-28 12:11:09 +0100662 : endpoints_(endpoints) {}
663
Sebastian Janssoncec24332019-12-04 14:26:50 +0100664EmulatedEndpointImpl* EndpointsContainer::LookupByLocalAddress(
Artem Titove5cc85b2019-03-28 12:11:09 +0100665 const rtc::IPAddress& local_ip) const {
666 for (auto* endpoint : endpoints_) {
Artem Titov4cd433e2019-04-01 11:01:16 +0200667 rtc::IPAddress peer_local_address = endpoint->GetPeerLocalAddress();
668 if (peer_local_address == local_ip) {
Artem Titove5cc85b2019-03-28 12:11:09 +0100669 return endpoint;
670 }
671 }
672 RTC_CHECK(false) << "No network found for address" << local_ip.ToString();
673}
674
Sebastian Janssoncec24332019-12-04 14:26:50 +0100675bool EndpointsContainer::HasEndpoint(EmulatedEndpointImpl* endpoint) const {
Artem Titove5cc85b2019-03-28 12:11:09 +0100676 for (auto* e : endpoints_) {
677 if (e->GetId() == endpoint->GetId()) {
678 return true;
679 }
680 }
681 return false;
682}
683
684std::vector<std::unique_ptr<rtc::Network>>
685EndpointsContainer::GetEnabledNetworks() const {
686 std::vector<std::unique_ptr<rtc::Network>> networks;
687 for (auto* endpoint : endpoints_) {
688 if (endpoint->Enabled()) {
689 networks.emplace_back(
Mirko Bonadei317a1f02019-09-17 17:06:18 +0200690 std::make_unique<rtc::Network>(endpoint->network()));
Artem Titove5cc85b2019-03-28 12:11:09 +0100691 }
692 }
693 return networks;
694}
695
Artem Titov5501cef2020-08-04 11:49:19 +0200696std::vector<EmulatedEndpoint*> EndpointsContainer::GetEndpoints() const {
Artem Titovcf781282020-07-28 13:45:16 +0200697 return std::vector<EmulatedEndpoint*>(endpoints_.begin(), endpoints_.end());
698}
699
Artem Titov3e0b65d2020-07-23 02:19:02 +0200700std::unique_ptr<EmulatedNetworkStats> EndpointsContainer::GetStats() const {
701 EmulatedNetworkStatsBuilder stats_builder;
Artem Titov806299e2019-04-12 12:17:19 +0200702 for (auto* endpoint : endpoints_) {
Artem Titov14b46a72020-07-31 12:57:24 +0200703 stats_builder.AddEmulatedNetworkStats(*endpoint->stats());
Artem Titov806299e2019-04-12 12:17:19 +0200704 }
Artem Titov3e0b65d2020-07-23 02:19:02 +0200705 return stats_builder.Build();
Artem Titov806299e2019-04-12 12:17:19 +0200706}
707
Artem Titov40f51152019-01-04 15:45:01 +0100708} // namespace webrtc