blob: 2c961912009796302eaa3781ff0c4c98bdecb8c4 [file] [log] [blame]
Artem Titov0774bd92019-01-30 15:26:05 +01001/*
2 * Copyright (c) 2019 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_manager.h"
Artem Titov0774bd92019-01-30 15:26:05 +010012
13#include <algorithm>
14#include <memory>
15
Artem Titov0774bd92019-01-30 15:26:05 +010016#include "api/units/time_delta.h"
17#include "api/units/timestamp.h"
Artem Titov48b1b182019-07-05 13:09:48 +020018#include "call/simulated_network.h"
Artem Titov20863472019-03-13 10:30:51 +010019#include "rtc_base/fake_network.h"
Jonas Oreland97050112020-11-17 21:30:33 +010020#include "test/network/emulated_turn_server.h"
Andrey Logvinf9ee0e02021-01-14 09:50:32 +000021#include "test/network/traffic_route.h"
Artem Titov386802e2019-07-05 10:48:17 +020022#include "test/time_controller/real_time_controller.h"
Sebastian Jansson6ce033a2020-01-22 10:12:56 +010023#include "test/time_controller/simulated_time_controller.h"
Artem Titov0774bd92019-01-30 15:26:05 +010024
25namespace webrtc {
26namespace test {
27namespace {
28
Artem Titov0bf4c292019-02-26 10:00:07 +010029// uint32_t representation of 192.168.0.0 address
30constexpr uint32_t kMinIPv4Address = 0xC0A80000;
31// uint32_t representation of 192.168.255.255 address
32constexpr uint32_t kMaxIPv4Address = 0xC0A8FFFF;
Sebastian Jansson6ce033a2020-01-22 10:12:56 +010033
34std::unique_ptr<TimeController> CreateTimeController(TimeMode mode) {
35 switch (mode) {
36 case TimeMode::kRealTime:
37 return std::make_unique<RealTimeController>();
38 case TimeMode::kSimulated:
39 // Using an offset of 100000 to get nice fixed width and readable
40 // timestamps in typical test scenarios.
Danil Chapovalov0c626af2020-02-10 11:16:00 +010041 const Timestamp kSimulatedStartTime = Timestamp::Seconds(100000);
Sebastian Jansson6ce033a2020-01-22 10:12:56 +010042 return std::make_unique<GlobalSimulatedTimeController>(
43 kSimulatedStartTime);
44 }
45}
Artem Titov0774bd92019-01-30 15:26:05 +010046} // namespace
47
Sebastian Jansson6ce033a2020-01-22 10:12:56 +010048NetworkEmulationManagerImpl::NetworkEmulationManagerImpl(TimeMode mode)
Artem Titovcc8a1f82021-01-26 13:58:23 +010049 : time_mode_(mode),
50 time_controller_(CreateTimeController(mode)),
Sebastian Jansson6ce033a2020-01-22 10:12:56 +010051 clock_(time_controller_->GetClock()),
Artem Titov0774bd92019-01-30 15:26:05 +010052 next_node_id_(1),
Artem Titov0bf4c292019-02-26 10:00:07 +010053 next_ip4_address_(kMinIPv4Address),
Sebastian Jansson6ce033a2020-01-22 10:12:56 +010054 task_queue_(time_controller_->GetTaskQueueFactory()->CreateTaskQueue(
Sebastian Jansson5d97f552019-04-15 14:43:03 +020055 "NetworkEmulation",
Artem Titov386802e2019-07-05 10:48:17 +020056 TaskQueueFactory::Priority::NORMAL)) {}
Artem Titov0774bd92019-01-30 15:26:05 +010057
Sebastian Janssonb00eb192019-02-11 09:13:01 +010058// TODO(srte): Ensure that any pending task that must be run for consistency
59// (such as stats collection tasks) are not cancelled when the task queue is
60// destroyed.
Jonas Oreland97050112020-11-17 21:30:33 +010061NetworkEmulationManagerImpl::~NetworkEmulationManagerImpl() {
62 for (auto& turn_server : turn_servers_) {
63 turn_server->Stop();
64 }
65}
Sebastian Janssonb00eb192019-02-11 09:13:01 +010066
Artem Titov7bf8c7f2019-03-15 15:00:37 +010067EmulatedNetworkNode* NetworkEmulationManagerImpl::CreateEmulatedNode(
Artem Titovec9b2812021-01-07 15:49:31 +010068 BuiltInNetworkBehaviorConfig config,
69 uint64_t random_seed) {
70 return CreateEmulatedNode(
71 std::make_unique<SimulatedNetwork>(config, random_seed));
Artem Titov48b1b182019-07-05 13:09:48 +020072}
73
74EmulatedNetworkNode* NetworkEmulationManagerImpl::CreateEmulatedNode(
Artem Titov0774bd92019-01-30 15:26:05 +010075 std::unique_ptr<NetworkBehaviorInterface> network_behavior) {
Mirko Bonadei317a1f02019-09-17 17:06:18 +020076 auto node = std::make_unique<EmulatedNetworkNode>(
Sebastian Jansson4124dab2019-04-01 14:33:53 +020077 clock_, &task_queue_, std::move(network_behavior));
Artem Titov0774bd92019-01-30 15:26:05 +010078 EmulatedNetworkNode* out = node.get();
Sebastian Jansson86314cf2019-09-17 20:29:59 +020079 task_queue_.PostTask([this, node = std::move(node)]() mutable {
80 network_nodes_.push_back(std::move(node));
81 });
Artem Titov0774bd92019-01-30 15:26:05 +010082 return out;
83}
84
Sebastian Janssoncec24332019-12-04 14:26:50 +010085NetworkEmulationManager::SimulatedNetworkNode::Builder
86NetworkEmulationManagerImpl::NodeBuilder() {
Sebastian Jansson8d3e4bd2019-07-31 18:33:17 +020087 return SimulatedNetworkNode::Builder(this);
88}
89
Niels Möller376cf382021-02-26 09:24:51 +010090EmulatedEndpointImpl* NetworkEmulationManagerImpl::CreateEndpoint(
Artem Titova268b692019-03-12 13:37:28 +010091 EmulatedEndpointConfig config) {
Artem Titov0bf4c292019-02-26 10:00:07 +010092 absl::optional<rtc::IPAddress> ip = config.ip;
93 if (!ip) {
94 switch (config.generated_ip_family) {
Artem Titova268b692019-03-12 13:37:28 +010095 case EmulatedEndpointConfig::IpAddressFamily::kIpv4:
Artem Titov0bf4c292019-02-26 10:00:07 +010096 ip = GetNextIPv4Address();
97 RTC_CHECK(ip) << "All auto generated IPv4 addresses exhausted";
98 break;
Artem Titova268b692019-03-12 13:37:28 +010099 case EmulatedEndpointConfig::IpAddressFamily::kIpv6:
Artem Titov0bf4c292019-02-26 10:00:07 +0100100 ip = GetNextIPv4Address();
101 RTC_CHECK(ip) << "All auto generated IPv6 addresses exhausted";
102 ip = ip->AsIPv6Address();
103 break;
104 }
105 }
106
107 bool res = used_ip_addresses_.insert(*ip).second;
108 RTC_CHECK(res) << "IP=" << ip->ToString() << " already in use";
Sebastian Janssoncec24332019-12-04 14:26:50 +0100109 auto node = std::make_unique<EmulatedEndpointImpl>(
Artem Titov3d37e062021-02-19 20:26:32 +0100110 EmulatedEndpointImpl::Options(next_node_id_++, *ip, config),
111 config.start_as_enabled, &task_queue_, clock_);
Niels Möller376cf382021-02-26 09:24:51 +0100112 EmulatedEndpointImpl* out = node.get();
Artem Titov0774bd92019-01-30 15:26:05 +0100113 endpoints_.push_back(std::move(node));
114 return out;
115}
116
Artem Titove5cc85b2019-03-28 12:11:09 +0100117void NetworkEmulationManagerImpl::EnableEndpoint(EmulatedEndpoint* endpoint) {
118 EmulatedNetworkManager* network_manager =
119 endpoint_to_network_manager_[endpoint];
120 RTC_CHECK(network_manager);
Sebastian Janssoncec24332019-12-04 14:26:50 +0100121 network_manager->EnableEndpoint(static_cast<EmulatedEndpointImpl*>(endpoint));
Artem Titove5cc85b2019-03-28 12:11:09 +0100122}
123
124void NetworkEmulationManagerImpl::DisableEndpoint(EmulatedEndpoint* endpoint) {
125 EmulatedNetworkManager* network_manager =
126 endpoint_to_network_manager_[endpoint];
127 RTC_CHECK(network_manager);
Sebastian Janssoncec24332019-12-04 14:26:50 +0100128 network_manager->DisableEndpoint(
129 static_cast<EmulatedEndpointImpl*>(endpoint));
Artem Titove5cc85b2019-03-28 12:11:09 +0100130}
131
Artem Titov7bf8c7f2019-03-15 15:00:37 +0100132EmulatedRoute* NetworkEmulationManagerImpl::CreateRoute(
Artem Titovaba8dc22019-03-11 10:08:40 +0100133 EmulatedEndpoint* from,
Artem Titov7bf8c7f2019-03-15 15:00:37 +0100134 const std::vector<EmulatedNetworkNode*>& via_nodes,
Artem Titovaba8dc22019-03-11 10:08:40 +0100135 EmulatedEndpoint* to) {
Artem Titov0774bd92019-01-30 15:26:05 +0100136 // Because endpoint has no send node by default at least one should be
137 // provided here.
138 RTC_CHECK(!via_nodes.empty());
139
Sebastian Janssoncec24332019-12-04 14:26:50 +0100140 static_cast<EmulatedEndpointImpl*>(from)->router()->SetReceiver(
141 to->GetPeerLocalAddress(), via_nodes[0]);
Artem Titov0774bd92019-01-30 15:26:05 +0100142 EmulatedNetworkNode* cur_node = via_nodes[0];
143 for (size_t i = 1; i < via_nodes.size(); ++i) {
Sebastian Jansson62bb47f2019-04-01 18:23:58 +0200144 cur_node->router()->SetReceiver(to->GetPeerLocalAddress(), via_nodes[i]);
Artem Titov0774bd92019-01-30 15:26:05 +0100145 cur_node = via_nodes[i];
146 }
Sebastian Jansson62bb47f2019-04-01 18:23:58 +0200147 cur_node->router()->SetReceiver(to->GetPeerLocalAddress(), to);
Artem Titovfc6ab002019-03-12 13:48:32 +0100148
Sebastian Janssoncec24332019-12-04 14:26:50 +0100149 std::unique_ptr<EmulatedRoute> route = std::make_unique<EmulatedRoute>(
150 static_cast<EmulatedEndpointImpl*>(from), std::move(via_nodes),
Artem Titov3d37e062021-02-19 20:26:32 +0100151 static_cast<EmulatedEndpointImpl*>(to), /*is_default=*/false);
Artem Titovfc6ab002019-03-12 13:48:32 +0100152 EmulatedRoute* out = route.get();
153 routes_.push_back(std::move(route));
154 return out;
Artem Titov0774bd92019-01-30 15:26:05 +0100155}
156
Sebastian Janssonb13ccc52019-06-07 13:06:00 +0200157EmulatedRoute* NetworkEmulationManagerImpl::CreateRoute(
158 const std::vector<EmulatedNetworkNode*>& via_nodes) {
159 EmulatedEndpoint* from = CreateEndpoint(EmulatedEndpointConfig());
160 EmulatedEndpoint* to = CreateEndpoint(EmulatedEndpointConfig());
161 return CreateRoute(from, via_nodes, to);
162}
163
Artem Titov3d37e062021-02-19 20:26:32 +0100164EmulatedRoute* NetworkEmulationManagerImpl::CreateDefaultRoute(
165 EmulatedEndpoint* from,
166 const std::vector<EmulatedNetworkNode*>& via_nodes,
167 EmulatedEndpoint* to) {
168 // Because endpoint has no send node by default at least one should be
169 // provided here.
170 RTC_CHECK(!via_nodes.empty());
171
172 static_cast<EmulatedEndpointImpl*>(from)->router()->SetDefaultReceiver(
173 via_nodes[0]);
174 EmulatedNetworkNode* cur_node = via_nodes[0];
175 for (size_t i = 1; i < via_nodes.size(); ++i) {
176 cur_node->router()->SetDefaultReceiver(via_nodes[i]);
177 cur_node = via_nodes[i];
178 }
179 cur_node->router()->SetDefaultReceiver(to);
180
181 std::unique_ptr<EmulatedRoute> route = std::make_unique<EmulatedRoute>(
182 static_cast<EmulatedEndpointImpl*>(from), std::move(via_nodes),
183 static_cast<EmulatedEndpointImpl*>(to), /*is_default=*/true);
184 EmulatedRoute* out = route.get();
185 routes_.push_back(std::move(route));
186 return out;
187}
188
Artem Titov7bf8c7f2019-03-15 15:00:37 +0100189void NetworkEmulationManagerImpl::ClearRoute(EmulatedRoute* route) {
Artem Titovfc6ab002019-03-12 13:48:32 +0100190 RTC_CHECK(route->active) << "Route already cleared";
Danil Chapovaloveb90e6f2019-10-15 10:04:57 +0200191 task_queue_.SendTask(
192 [route]() {
193 // Remove receiver from intermediate nodes.
194 for (auto* node : route->via_nodes) {
Artem Titov3d37e062021-02-19 20:26:32 +0100195 if (route->is_default) {
196 node->router()->RemoveDefaultReceiver();
197 } else {
198 node->router()->RemoveReceiver(route->to->GetPeerLocalAddress());
199 }
Danil Chapovaloveb90e6f2019-10-15 10:04:57 +0200200 }
201 // Remove destination endpoint from source endpoint's router.
Artem Titov3d37e062021-02-19 20:26:32 +0100202 if (route->is_default) {
203 route->from->router()->RemoveDefaultReceiver();
204 } else {
205 route->from->router()->RemoveReceiver(
206 route->to->GetPeerLocalAddress());
207 }
Artem Titovfc6ab002019-03-12 13:48:32 +0100208
Danil Chapovaloveb90e6f2019-10-15 10:04:57 +0200209 route->active = false;
210 },
211 RTC_FROM_HERE);
Artem Titov0774bd92019-01-30 15:26:05 +0100212}
213
Andrey Logvinf9ee0e02021-01-14 09:50:32 +0000214TcpMessageRoute* NetworkEmulationManagerImpl::CreateTcpRoute(
215 EmulatedRoute* send_route,
216 EmulatedRoute* ret_route) {
217 auto tcp_route = std::make_unique<TcpMessageRouteImpl>(
218 clock_, task_queue_.Get(), send_route, ret_route);
219 auto* route_ptr = tcp_route.get();
220 task_queue_.PostTask([this, tcp_route = std::move(tcp_route)]() mutable {
221 tcp_message_routes_.push_back(std::move(tcp_route));
222 });
223 return route_ptr;
224}
225
226CrossTrafficRoute* NetworkEmulationManagerImpl::CreateCrossTrafficRoute(
Artem Titov7bf8c7f2019-03-15 15:00:37 +0100227 const std::vector<EmulatedNetworkNode*>& via_nodes) {
Artem Titovd3666b22019-02-11 14:40:17 +0100228 RTC_CHECK(!via_nodes.empty());
Niels Möller376cf382021-02-26 09:24:51 +0100229 EmulatedEndpointImpl* endpoint = CreateEndpoint(EmulatedEndpointConfig());
Artem Titovd3666b22019-02-11 14:40:17 +0100230
231 // Setup a route via specified nodes.
232 EmulatedNetworkNode* cur_node = via_nodes[0];
233 for (size_t i = 1; i < via_nodes.size(); ++i) {
Sebastian Jansson62bb47f2019-04-01 18:23:58 +0200234 cur_node->router()->SetReceiver(endpoint->GetPeerLocalAddress(),
235 via_nodes[i]);
Artem Titovd3666b22019-02-11 14:40:17 +0100236 cur_node = via_nodes[i];
237 }
Sebastian Jansson62bb47f2019-04-01 18:23:58 +0200238 cur_node->router()->SetReceiver(endpoint->GetPeerLocalAddress(), endpoint);
Artem Titovd3666b22019-02-11 14:40:17 +0100239
Andrey Logvinf9ee0e02021-01-14 09:50:32 +0000240 std::unique_ptr<CrossTrafficRoute> traffic_route =
241 std::make_unique<CrossTrafficRouteImpl>(clock_, via_nodes[0], endpoint);
242 CrossTrafficRoute* out = traffic_route.get();
Artem Titovd3666b22019-02-11 14:40:17 +0100243 traffic_routes_.push_back(std::move(traffic_route));
244 return out;
245}
246
Andrey Logvinf9ee0e02021-01-14 09:50:32 +0000247CrossTrafficGenerator* NetworkEmulationManagerImpl::StartCrossTraffic(
248 std::unique_ptr<CrossTrafficGenerator> generator) {
249 CrossTrafficGenerator* out = generator.get();
250 task_queue_.PostTask([this, generator = std::move(generator)]() mutable {
251 auto* generator_ptr = generator.get();
Sebastian Janssonf6e64352019-04-17 18:02:34 +0200252
Andrey Logvinf9ee0e02021-01-14 09:50:32 +0000253 auto repeating_task_handle =
254 RepeatingTaskHandle::Start(task_queue_.Get(), [this, generator_ptr] {
255 generator_ptr->Process(Now());
256 return generator_ptr->GetProcessInterval();
257 });
Artem Titovd3666b22019-02-11 14:40:17 +0100258
Andrey Logvinf9ee0e02021-01-14 09:50:32 +0000259 cross_traffics_.push_back(CrossTrafficSource(
260 std::move(generator), std::move(repeating_task_handle)));
Sebastian Janssond8aff212019-10-11 17:00:39 +0200261 });
Andrey Logvinf9ee0e02021-01-14 09:50:32 +0000262 return out;
Sebastian Janssondcc910a2019-11-12 16:36:34 +0100263}
264
Sebastian Janssond8aff212019-10-11 17:00:39 +0200265void NetworkEmulationManagerImpl::StopCrossTraffic(
Andrey Logvinf9ee0e02021-01-14 09:50:32 +0000266 CrossTrafficGenerator* generator) {
Sebastian Janssond8aff212019-10-11 17:00:39 +0200267 task_queue_.PostTask([=]() {
Andrey Logvinf9ee0e02021-01-14 09:50:32 +0000268 auto it = std::find_if(cross_traffics_.begin(), cross_traffics_.end(),
269 [=](const CrossTrafficSource& el) {
270 return el.first.get() == generator;
271 });
272 it->second.Stop();
273 cross_traffics_.erase(it);
Sebastian Janssonb13ccc52019-06-07 13:06:00 +0200274 });
275}
276
Artem Titove5cc85b2019-03-28 12:11:09 +0100277EmulatedNetworkManagerInterface*
278NetworkEmulationManagerImpl::CreateEmulatedNetworkManagerInterface(
Artem Titov7bf8c7f2019-03-15 15:00:37 +0100279 const std::vector<EmulatedEndpoint*>& endpoints) {
Sebastian Janssoncec24332019-12-04 14:26:50 +0100280 std::vector<EmulatedEndpointImpl*> endpoint_impls;
Mirko Bonadei14cad9f2021-02-03 09:48:01 +0100281 endpoint_impls.reserve(endpoints.size());
Sebastian Janssoncec24332019-12-04 14:26:50 +0100282 for (EmulatedEndpoint* endpoint : endpoints) {
283 endpoint_impls.push_back(static_cast<EmulatedEndpointImpl*>(endpoint));
284 }
285 auto endpoints_container =
286 std::make_unique<EndpointsContainer>(endpoint_impls);
Mirko Bonadei317a1f02019-09-17 17:06:18 +0200287 auto network_manager = std::make_unique<EmulatedNetworkManager>(
Sebastian Jansson6ce033a2020-01-22 10:12:56 +0100288 time_controller_.get(), &task_queue_, endpoints_container.get());
Artem Titov20863472019-03-13 10:30:51 +0100289 for (auto* endpoint : endpoints) {
Artem Titove5cc85b2019-03-28 12:11:09 +0100290 // Associate endpoint with network manager.
291 bool insertion_result =
292 endpoint_to_network_manager_.insert({endpoint, network_manager.get()})
293 .second;
294 RTC_CHECK(insertion_result)
295 << "Endpoint ip=" << endpoint->GetPeerLocalAddress().ToString()
296 << " is already used for another network";
Artem Titov20863472019-03-13 10:30:51 +0100297 }
Artem Titov20863472019-03-13 10:30:51 +0100298
Artem Titove5cc85b2019-03-28 12:11:09 +0100299 EmulatedNetworkManagerInterface* out = network_manager.get();
300
Artem Titov0d32a732019-04-05 14:49:59 +0200301 endpoints_containers_.push_back(std::move(endpoints_container));
Artem Titove5cc85b2019-03-28 12:11:09 +0100302 network_managers_.push_back(std::move(network_manager));
Artem Titov0774bd92019-01-30 15:26:05 +0100303 return out;
304}
305
Artem Titovcf781282020-07-28 13:45:16 +0200306void NetworkEmulationManagerImpl::GetStats(
Per Kjellander410c9982021-02-15 11:24:37 +0100307 rtc::ArrayView<EmulatedEndpoint* const> endpoints,
Artem Titovcf781282020-07-28 13:45:16 +0200308 std::function<void(std::unique_ptr<EmulatedNetworkStats>)> stats_callback) {
309 task_queue_.PostTask([endpoints, stats_callback]() {
310 EmulatedNetworkStatsBuilder stats_builder;
311 for (auto* endpoint : endpoints) {
Artem Titov9dcab802020-08-04 11:19:28 +0200312 // It's safe to cast here because EmulatedEndpointImpl can be the only
313 // implementation of EmulatedEndpoint, because only it has access to
314 // EmulatedEndpoint constructor.
315 auto endpoint_impl = static_cast<EmulatedEndpointImpl*>(endpoint);
316 stats_builder.AddEmulatedNetworkStats(*endpoint_impl->stats());
Artem Titovcf781282020-07-28 13:45:16 +0200317 }
318 stats_callback(stats_builder.Build());
319 });
320}
321
Artem Titov7bf8c7f2019-03-15 15:00:37 +0100322absl::optional<rtc::IPAddress>
323NetworkEmulationManagerImpl::GetNextIPv4Address() {
Artem Titov0bf4c292019-02-26 10:00:07 +0100324 uint32_t addresses_count = kMaxIPv4Address - kMinIPv4Address;
325 for (uint32_t i = 0; i < addresses_count; i++) {
326 rtc::IPAddress ip(next_ip4_address_);
327 if (next_ip4_address_ == kMaxIPv4Address) {
328 next_ip4_address_ = kMinIPv4Address;
329 } else {
330 next_ip4_address_++;
331 }
332 if (used_ip_addresses_.find(ip) == used_ip_addresses_.end()) {
333 return ip;
334 }
335 }
336 return absl::nullopt;
337}
338
Artem Titov7bf8c7f2019-03-15 15:00:37 +0100339Timestamp NetworkEmulationManagerImpl::Now() const {
Sebastian Janssonb64ad0e2019-06-19 09:39:34 +0200340 return clock_->CurrentTime();
Artem Titov0774bd92019-01-30 15:26:05 +0100341}
342
Jonas Oreland97050112020-11-17 21:30:33 +0100343EmulatedTURNServerInterface* NetworkEmulationManagerImpl::CreateTURNServer(
344 EmulatedTURNServerConfig config) {
345 auto* client = CreateEndpoint(config.client_config);
346 auto* peer = CreateEndpoint(config.client_config);
347 char buf[128];
348 rtc::SimpleStringBuilder str(buf);
349 str.AppendFormat("turn_server_%u",
350 static_cast<unsigned>(turn_servers_.size()));
351 auto turn = std::make_unique<EmulatedTURNServer>(
352 time_controller_->CreateThread(str.str()), client, peer);
353 auto out = turn.get();
354 turn_servers_.push_back(std::move(turn));
355 return out;
356}
357
Artem Titov0774bd92019-01-30 15:26:05 +0100358} // namespace test
359} // namespace webrtc