1 /*
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
11 #include "test/network/network_emulation_manager.h"
12
13 #include <algorithm>
14 #include <memory>
15
16 #include "api/units/time_delta.h"
17 #include "api/units/timestamp.h"
18 #include "call/simulated_network.h"
19 #include "test/network/emulated_turn_server.h"
20 #include "test/network/traffic_route.h"
21 #include "test/time_controller/real_time_controller.h"
22 #include "test/time_controller/simulated_time_controller.h"
23
24 namespace webrtc {
25 namespace test {
26 namespace {
27
28 // uint32_t representation of 192.168.0.0 address
29 constexpr uint32_t kMinIPv4Address = 0xC0A80000;
30 // uint32_t representation of 192.168.255.255 address
31 constexpr uint32_t kMaxIPv4Address = 0xC0A8FFFF;
32
CreateTimeController(TimeMode mode)33 std::unique_ptr<TimeController> CreateTimeController(TimeMode mode) {
34 switch (mode) {
35 case TimeMode::kRealTime:
36 return std::make_unique<RealTimeController>();
37 case TimeMode::kSimulated:
38 // Using an offset of 100000 to get nice fixed width and readable
39 // timestamps in typical test scenarios.
40 const Timestamp kSimulatedStartTime = Timestamp::Seconds(100000);
41 return std::make_unique<GlobalSimulatedTimeController>(
42 kSimulatedStartTime);
43 }
44 }
45 } // namespace
46
NetworkEmulationManagerImpl(TimeMode mode,EmulatedNetworkStatsGatheringMode stats_gathering_mode)47 NetworkEmulationManagerImpl::NetworkEmulationManagerImpl(
48 TimeMode mode,
49 EmulatedNetworkStatsGatheringMode stats_gathering_mode)
50 : time_mode_(mode),
51 stats_gathering_mode_(stats_gathering_mode),
52 time_controller_(CreateTimeController(mode)),
53 clock_(time_controller_->GetClock()),
54 next_node_id_(1),
55 next_ip4_address_(kMinIPv4Address),
56 task_queue_(time_controller_->GetTaskQueueFactory()->CreateTaskQueue(
57 "NetworkEmulation",
58 TaskQueueFactory::Priority::NORMAL)) {}
59
60 // TODO(srte): Ensure that any pending task that must be run for consistency
61 // (such as stats collection tasks) are not cancelled when the task queue is
62 // destroyed.
~NetworkEmulationManagerImpl()63 NetworkEmulationManagerImpl::~NetworkEmulationManagerImpl() {
64 for (auto& turn_server : turn_servers_) {
65 turn_server->Stop();
66 }
67 }
68
CreateEmulatedNode(BuiltInNetworkBehaviorConfig config,uint64_t random_seed)69 EmulatedNetworkNode* NetworkEmulationManagerImpl::CreateEmulatedNode(
70 BuiltInNetworkBehaviorConfig config,
71 uint64_t random_seed) {
72 return CreateEmulatedNode(
73 std::make_unique<SimulatedNetwork>(config, random_seed));
74 }
75
CreateEmulatedNode(std::unique_ptr<NetworkBehaviorInterface> network_behavior)76 EmulatedNetworkNode* NetworkEmulationManagerImpl::CreateEmulatedNode(
77 std::unique_ptr<NetworkBehaviorInterface> network_behavior) {
78 auto node = std::make_unique<EmulatedNetworkNode>(
79 clock_, &task_queue_, std::move(network_behavior), stats_gathering_mode_);
80 EmulatedNetworkNode* out = node.get();
81 task_queue_.PostTask([this, node = std::move(node)]() mutable {
82 network_nodes_.push_back(std::move(node));
83 });
84 return out;
85 }
86
87 NetworkEmulationManager::SimulatedNetworkNode::Builder
NodeBuilder()88 NetworkEmulationManagerImpl::NodeBuilder() {
89 return SimulatedNetworkNode::Builder(this);
90 }
91
CreateEndpoint(EmulatedEndpointConfig config)92 EmulatedEndpointImpl* NetworkEmulationManagerImpl::CreateEndpoint(
93 EmulatedEndpointConfig config) {
94 absl::optional<rtc::IPAddress> ip = config.ip;
95 if (!ip) {
96 switch (config.generated_ip_family) {
97 case EmulatedEndpointConfig::IpAddressFamily::kIpv4:
98 ip = GetNextIPv4Address();
99 RTC_CHECK(ip) << "All auto generated IPv4 addresses exhausted";
100 break;
101 case EmulatedEndpointConfig::IpAddressFamily::kIpv6:
102 ip = GetNextIPv4Address();
103 RTC_CHECK(ip) << "All auto generated IPv6 addresses exhausted";
104 ip = ip->AsIPv6Address();
105 break;
106 }
107 }
108
109 bool res = used_ip_addresses_.insert(*ip).second;
110 RTC_CHECK(res) << "IP=" << ip->ToString() << " already in use";
111 auto node = std::make_unique<EmulatedEndpointImpl>(
112 EmulatedEndpointImpl::Options(next_node_id_++, *ip, config,
113 stats_gathering_mode_),
114 config.start_as_enabled, &task_queue_, clock_);
115 EmulatedEndpointImpl* out = node.get();
116 endpoints_.push_back(std::move(node));
117 return out;
118 }
119
EnableEndpoint(EmulatedEndpoint * endpoint)120 void NetworkEmulationManagerImpl::EnableEndpoint(EmulatedEndpoint* endpoint) {
121 EmulatedNetworkManager* network_manager =
122 endpoint_to_network_manager_[endpoint];
123 RTC_CHECK(network_manager);
124 network_manager->EnableEndpoint(static_cast<EmulatedEndpointImpl*>(endpoint));
125 }
126
DisableEndpoint(EmulatedEndpoint * endpoint)127 void NetworkEmulationManagerImpl::DisableEndpoint(EmulatedEndpoint* endpoint) {
128 EmulatedNetworkManager* network_manager =
129 endpoint_to_network_manager_[endpoint];
130 RTC_CHECK(network_manager);
131 network_manager->DisableEndpoint(
132 static_cast<EmulatedEndpointImpl*>(endpoint));
133 }
134
CreateRoute(EmulatedEndpoint * from,const std::vector<EmulatedNetworkNode * > & via_nodes,EmulatedEndpoint * to)135 EmulatedRoute* NetworkEmulationManagerImpl::CreateRoute(
136 EmulatedEndpoint* from,
137 const std::vector<EmulatedNetworkNode*>& via_nodes,
138 EmulatedEndpoint* to) {
139 // Because endpoint has no send node by default at least one should be
140 // provided here.
141 RTC_CHECK(!via_nodes.empty());
142
143 static_cast<EmulatedEndpointImpl*>(from)->router()->SetReceiver(
144 to->GetPeerLocalAddress(), via_nodes[0]);
145 EmulatedNetworkNode* cur_node = via_nodes[0];
146 for (size_t i = 1; i < via_nodes.size(); ++i) {
147 cur_node->router()->SetReceiver(to->GetPeerLocalAddress(), via_nodes[i]);
148 cur_node = via_nodes[i];
149 }
150 cur_node->router()->SetReceiver(to->GetPeerLocalAddress(), to);
151
152 std::unique_ptr<EmulatedRoute> route = std::make_unique<EmulatedRoute>(
153 static_cast<EmulatedEndpointImpl*>(from), std::move(via_nodes),
154 static_cast<EmulatedEndpointImpl*>(to), /*is_default=*/false);
155 EmulatedRoute* out = route.get();
156 routes_.push_back(std::move(route));
157 return out;
158 }
159
CreateRoute(const std::vector<EmulatedNetworkNode * > & via_nodes)160 EmulatedRoute* NetworkEmulationManagerImpl::CreateRoute(
161 const std::vector<EmulatedNetworkNode*>& via_nodes) {
162 EmulatedEndpoint* from = CreateEndpoint(EmulatedEndpointConfig());
163 EmulatedEndpoint* to = CreateEndpoint(EmulatedEndpointConfig());
164 return CreateRoute(from, via_nodes, to);
165 }
166
CreateDefaultRoute(EmulatedEndpoint * from,const std::vector<EmulatedNetworkNode * > & via_nodes,EmulatedEndpoint * to)167 EmulatedRoute* NetworkEmulationManagerImpl::CreateDefaultRoute(
168 EmulatedEndpoint* from,
169 const std::vector<EmulatedNetworkNode*>& via_nodes,
170 EmulatedEndpoint* to) {
171 // Because endpoint has no send node by default at least one should be
172 // provided here.
173 RTC_CHECK(!via_nodes.empty());
174
175 static_cast<EmulatedEndpointImpl*>(from)->router()->SetDefaultReceiver(
176 via_nodes[0]);
177 EmulatedNetworkNode* cur_node = via_nodes[0];
178 for (size_t i = 1; i < via_nodes.size(); ++i) {
179 cur_node->router()->SetDefaultReceiver(via_nodes[i]);
180 cur_node = via_nodes[i];
181 }
182 cur_node->router()->SetDefaultReceiver(to);
183
184 std::unique_ptr<EmulatedRoute> route = std::make_unique<EmulatedRoute>(
185 static_cast<EmulatedEndpointImpl*>(from), std::move(via_nodes),
186 static_cast<EmulatedEndpointImpl*>(to), /*is_default=*/true);
187 EmulatedRoute* out = route.get();
188 routes_.push_back(std::move(route));
189 return out;
190 }
191
ClearRoute(EmulatedRoute * route)192 void NetworkEmulationManagerImpl::ClearRoute(EmulatedRoute* route) {
193 RTC_CHECK(route->active) << "Route already cleared";
194 task_queue_.SendTask([route]() {
195 // Remove receiver from intermediate nodes.
196 for (auto* node : route->via_nodes) {
197 if (route->is_default) {
198 node->router()->RemoveDefaultReceiver();
199 } else {
200 node->router()->RemoveReceiver(route->to->GetPeerLocalAddress());
201 }
202 }
203 // Remove destination endpoint from source endpoint's router.
204 if (route->is_default) {
205 route->from->router()->RemoveDefaultReceiver();
206 } else {
207 route->from->router()->RemoveReceiver(route->to->GetPeerLocalAddress());
208 }
209
210 route->active = false;
211 });
212 }
213
CreateTcpRoute(EmulatedRoute * send_route,EmulatedRoute * ret_route)214 TcpMessageRoute* 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
CreateCrossTrafficRoute(const std::vector<EmulatedNetworkNode * > & via_nodes)226 CrossTrafficRoute* NetworkEmulationManagerImpl::CreateCrossTrafficRoute(
227 const std::vector<EmulatedNetworkNode*>& via_nodes) {
228 RTC_CHECK(!via_nodes.empty());
229 EmulatedEndpointImpl* endpoint = CreateEndpoint(EmulatedEndpointConfig());
230
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) {
234 cur_node->router()->SetReceiver(endpoint->GetPeerLocalAddress(),
235 via_nodes[i]);
236 cur_node = via_nodes[i];
237 }
238 cur_node->router()->SetReceiver(endpoint->GetPeerLocalAddress(), endpoint);
239
240 std::unique_ptr<CrossTrafficRoute> traffic_route =
241 std::make_unique<CrossTrafficRouteImpl>(clock_, via_nodes[0], endpoint);
242 CrossTrafficRoute* out = traffic_route.get();
243 traffic_routes_.push_back(std::move(traffic_route));
244 return out;
245 }
246
StartCrossTraffic(std::unique_ptr<CrossTrafficGenerator> generator)247 CrossTrafficGenerator* 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();
252
253 auto repeating_task_handle =
254 RepeatingTaskHandle::Start(task_queue_.Get(), [this, generator_ptr] {
255 generator_ptr->Process(Now());
256 return generator_ptr->GetProcessInterval();
257 });
258
259 cross_traffics_.push_back(CrossTrafficSource(
260 std::move(generator), std::move(repeating_task_handle)));
261 });
262 return out;
263 }
264
StopCrossTraffic(CrossTrafficGenerator * generator)265 void NetworkEmulationManagerImpl::StopCrossTraffic(
266 CrossTrafficGenerator* generator) {
267 task_queue_.PostTask([=]() {
268 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);
274 });
275 }
276
277 EmulatedNetworkManagerInterface*
CreateEmulatedNetworkManagerInterface(const std::vector<EmulatedEndpoint * > & endpoints)278 NetworkEmulationManagerImpl::CreateEmulatedNetworkManagerInterface(
279 const std::vector<EmulatedEndpoint*>& endpoints) {
280 std::vector<EmulatedEndpointImpl*> endpoint_impls;
281 endpoint_impls.reserve(endpoints.size());
282 for (EmulatedEndpoint* endpoint : endpoints) {
283 endpoint_impls.push_back(static_cast<EmulatedEndpointImpl*>(endpoint));
284 }
285 auto endpoints_container = std::make_unique<EndpointsContainer>(
286 endpoint_impls, stats_gathering_mode_);
287 auto network_manager = std::make_unique<EmulatedNetworkManager>(
288 time_controller_.get(), &task_queue_, endpoints_container.get());
289 for (auto* endpoint : endpoints) {
290 // 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";
297 }
298
299 EmulatedNetworkManagerInterface* out = network_manager.get();
300
301 endpoints_containers_.push_back(std::move(endpoints_container));
302 network_managers_.push_back(std::move(network_manager));
303 return out;
304 }
305
GetStats(rtc::ArrayView<EmulatedEndpoint * const> endpoints,std::function<void (EmulatedNetworkStats)> stats_callback)306 void NetworkEmulationManagerImpl::GetStats(
307 rtc::ArrayView<EmulatedEndpoint* const> endpoints,
308 std::function<void(EmulatedNetworkStats)> stats_callback) {
309 task_queue_.PostTask([endpoints, stats_callback,
310 stats_gathering_mode = stats_gathering_mode_]() {
311 EmulatedNetworkStatsBuilder stats_builder(stats_gathering_mode);
312 for (auto* endpoint : endpoints) {
313 // It's safe to cast here because EmulatedEndpointImpl can be the only
314 // implementation of EmulatedEndpoint, because only it has access to
315 // EmulatedEndpoint constructor.
316 auto endpoint_impl = static_cast<EmulatedEndpointImpl*>(endpoint);
317 stats_builder.AddEmulatedNetworkStats(endpoint_impl->stats());
318 }
319 stats_callback(stats_builder.Build());
320 });
321 }
322
GetStats(rtc::ArrayView<EmulatedNetworkNode * const> nodes,std::function<void (EmulatedNetworkNodeStats)> stats_callback)323 void NetworkEmulationManagerImpl::GetStats(
324 rtc::ArrayView<EmulatedNetworkNode* const> nodes,
325 std::function<void(EmulatedNetworkNodeStats)> stats_callback) {
326 task_queue_.PostTask(
327 [nodes, stats_callback, stats_gathering_mode = stats_gathering_mode_]() {
328 EmulatedNetworkNodeStatsBuilder stats_builder(stats_gathering_mode);
329 for (auto* node : nodes) {
330 stats_builder.AddEmulatedNetworkNodeStats(node->stats());
331 }
332 stats_callback(stats_builder.Build());
333 });
334 }
335
336 absl::optional<rtc::IPAddress>
GetNextIPv4Address()337 NetworkEmulationManagerImpl::GetNextIPv4Address() {
338 uint32_t addresses_count = kMaxIPv4Address - kMinIPv4Address;
339 for (uint32_t i = 0; i < addresses_count; i++) {
340 rtc::IPAddress ip(next_ip4_address_);
341 if (next_ip4_address_ == kMaxIPv4Address) {
342 next_ip4_address_ = kMinIPv4Address;
343 } else {
344 next_ip4_address_++;
345 }
346 if (used_ip_addresses_.find(ip) == used_ip_addresses_.end()) {
347 return ip;
348 }
349 }
350 return absl::nullopt;
351 }
352
Now() const353 Timestamp NetworkEmulationManagerImpl::Now() const {
354 return clock_->CurrentTime();
355 }
356
CreateTURNServer(EmulatedTURNServerConfig config)357 EmulatedTURNServerInterface* NetworkEmulationManagerImpl::CreateTURNServer(
358 EmulatedTURNServerConfig config) {
359 auto* client = CreateEndpoint(config.client_config);
360 auto* peer = CreateEndpoint(config.client_config);
361 char buf[128];
362 rtc::SimpleStringBuilder str(buf);
363 str.AppendFormat("turn_server_%u",
364 static_cast<unsigned>(turn_servers_.size()));
365 auto turn = std::make_unique<EmulatedTURNServer>(
366 time_controller_->CreateThread(str.str()), client, peer);
367 auto out = turn.get();
368 turn_servers_.push_back(std::move(turn));
369 return out;
370 }
371
372 } // namespace test
373 } // namespace webrtc
374