blob: a2d8d90d675e87d3902fc78b56f039073b3d03d6 [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"
Artem Titov386802e2019-07-05 10:48:17 +020020#include "test/time_controller/real_time_controller.h"
Artem Titov0774bd92019-01-30 15:26:05 +010021
22namespace webrtc {
23namespace test {
24namespace {
25
Artem Titov0bf4c292019-02-26 10:00:07 +010026// uint32_t representation of 192.168.0.0 address
27constexpr uint32_t kMinIPv4Address = 0xC0A80000;
28// uint32_t representation of 192.168.255.255 address
29constexpr uint32_t kMaxIPv4Address = 0xC0A8FFFF;
Artem Titov0774bd92019-01-30 15:26:05 +010030} // namespace
31
Artem Titov7bf8c7f2019-03-15 15:00:37 +010032NetworkEmulationManagerImpl::NetworkEmulationManagerImpl()
Sebastian Jansson5d97f552019-04-15 14:43:03 +020033 : NetworkEmulationManagerImpl(GlobalRealTimeController()) {}
34
35NetworkEmulationManagerImpl::NetworkEmulationManagerImpl(
36 TimeController* time_controller)
37 : clock_(time_controller->GetClock()),
Artem Titov0774bd92019-01-30 15:26:05 +010038 next_node_id_(1),
Artem Titov0bf4c292019-02-26 10:00:07 +010039 next_ip4_address_(kMinIPv4Address),
Sebastian Jansson5d97f552019-04-15 14:43:03 +020040 task_queue_(time_controller->GetTaskQueueFactory()->CreateTaskQueue(
41 "NetworkEmulation",
Artem Titov386802e2019-07-05 10:48:17 +020042 TaskQueueFactory::Priority::NORMAL)) {}
Artem Titov0774bd92019-01-30 15:26:05 +010043
Sebastian Janssonb00eb192019-02-11 09:13:01 +010044// TODO(srte): Ensure that any pending task that must be run for consistency
45// (such as stats collection tasks) are not cancelled when the task queue is
46// destroyed.
Artem Titov7bf8c7f2019-03-15 15:00:37 +010047NetworkEmulationManagerImpl::~NetworkEmulationManagerImpl() = default;
Sebastian Janssonb00eb192019-02-11 09:13:01 +010048
Artem Titov7bf8c7f2019-03-15 15:00:37 +010049EmulatedNetworkNode* NetworkEmulationManagerImpl::CreateEmulatedNode(
Artem Titov48b1b182019-07-05 13:09:48 +020050 BuiltInNetworkBehaviorConfig config) {
Mirko Bonadei317a1f02019-09-17 17:06:18 +020051 return CreateEmulatedNode(std::make_unique<SimulatedNetwork>(config));
Artem Titov48b1b182019-07-05 13:09:48 +020052}
53
54EmulatedNetworkNode* NetworkEmulationManagerImpl::CreateEmulatedNode(
Artem Titov0774bd92019-01-30 15:26:05 +010055 std::unique_ptr<NetworkBehaviorInterface> network_behavior) {
Mirko Bonadei317a1f02019-09-17 17:06:18 +020056 auto node = std::make_unique<EmulatedNetworkNode>(
Sebastian Jansson4124dab2019-04-01 14:33:53 +020057 clock_, &task_queue_, std::move(network_behavior));
Artem Titov0774bd92019-01-30 15:26:05 +010058 EmulatedNetworkNode* out = node.get();
Sebastian Jansson86314cf2019-09-17 20:29:59 +020059 task_queue_.PostTask([this, node = std::move(node)]() mutable {
60 network_nodes_.push_back(std::move(node));
61 });
Artem Titov0774bd92019-01-30 15:26:05 +010062 return out;
63}
64
Sebastian Jansson8d3e4bd2019-07-31 18:33:17 +020065SimulatedNetworkNode::Builder NetworkEmulationManagerImpl::NodeBuilder() {
66 return SimulatedNetworkNode::Builder(this);
67}
68
Artem Titov7bf8c7f2019-03-15 15:00:37 +010069EmulatedEndpoint* NetworkEmulationManagerImpl::CreateEndpoint(
Artem Titova268b692019-03-12 13:37:28 +010070 EmulatedEndpointConfig config) {
Artem Titov0bf4c292019-02-26 10:00:07 +010071 absl::optional<rtc::IPAddress> ip = config.ip;
72 if (!ip) {
73 switch (config.generated_ip_family) {
Artem Titova268b692019-03-12 13:37:28 +010074 case EmulatedEndpointConfig::IpAddressFamily::kIpv4:
Artem Titov0bf4c292019-02-26 10:00:07 +010075 ip = GetNextIPv4Address();
76 RTC_CHECK(ip) << "All auto generated IPv4 addresses exhausted";
77 break;
Artem Titova268b692019-03-12 13:37:28 +010078 case EmulatedEndpointConfig::IpAddressFamily::kIpv6:
Artem Titov0bf4c292019-02-26 10:00:07 +010079 ip = GetNextIPv4Address();
80 RTC_CHECK(ip) << "All auto generated IPv6 addresses exhausted";
81 ip = ip->AsIPv6Address();
82 break;
83 }
84 }
85
86 bool res = used_ip_addresses_.insert(*ip).second;
87 RTC_CHECK(res) << "IP=" << ip->ToString() << " already in use";
Mirko Bonadei317a1f02019-09-17 17:06:18 +020088 auto node = std::make_unique<EmulatedEndpoint>(
Artem Titovff393122019-04-05 11:19:52 +020089 next_node_id_++, *ip, config.start_as_enabled, &task_queue_, clock_);
Artem Titovaba8dc22019-03-11 10:08:40 +010090 EmulatedEndpoint* out = node.get();
Artem Titov0774bd92019-01-30 15:26:05 +010091 endpoints_.push_back(std::move(node));
92 return out;
93}
94
Artem Titove5cc85b2019-03-28 12:11:09 +010095void NetworkEmulationManagerImpl::EnableEndpoint(EmulatedEndpoint* endpoint) {
96 EmulatedNetworkManager* network_manager =
97 endpoint_to_network_manager_[endpoint];
98 RTC_CHECK(network_manager);
99 network_manager->EnableEndpoint(endpoint);
100}
101
102void NetworkEmulationManagerImpl::DisableEndpoint(EmulatedEndpoint* endpoint) {
103 EmulatedNetworkManager* network_manager =
104 endpoint_to_network_manager_[endpoint];
105 RTC_CHECK(network_manager);
106 network_manager->DisableEndpoint(endpoint);
107}
108
Artem Titov7bf8c7f2019-03-15 15:00:37 +0100109EmulatedRoute* NetworkEmulationManagerImpl::CreateRoute(
Artem Titovaba8dc22019-03-11 10:08:40 +0100110 EmulatedEndpoint* from,
Artem Titov7bf8c7f2019-03-15 15:00:37 +0100111 const std::vector<EmulatedNetworkNode*>& via_nodes,
Artem Titovaba8dc22019-03-11 10:08:40 +0100112 EmulatedEndpoint* to) {
Artem Titov0774bd92019-01-30 15:26:05 +0100113 // Because endpoint has no send node by default at least one should be
114 // provided here.
115 RTC_CHECK(!via_nodes.empty());
116
Artem Titovff393122019-04-05 11:19:52 +0200117 from->router()->SetReceiver(to->GetPeerLocalAddress(), via_nodes[0]);
Artem Titov0774bd92019-01-30 15:26:05 +0100118 EmulatedNetworkNode* cur_node = via_nodes[0];
119 for (size_t i = 1; i < via_nodes.size(); ++i) {
Sebastian Jansson62bb47f2019-04-01 18:23:58 +0200120 cur_node->router()->SetReceiver(to->GetPeerLocalAddress(), via_nodes[i]);
Artem Titov0774bd92019-01-30 15:26:05 +0100121 cur_node = via_nodes[i];
122 }
Sebastian Jansson62bb47f2019-04-01 18:23:58 +0200123 cur_node->router()->SetReceiver(to->GetPeerLocalAddress(), to);
Artem Titovfc6ab002019-03-12 13:48:32 +0100124
125 std::unique_ptr<EmulatedRoute> route =
Mirko Bonadei317a1f02019-09-17 17:06:18 +0200126 std::make_unique<EmulatedRoute>(from, std::move(via_nodes), to);
Artem Titovfc6ab002019-03-12 13:48:32 +0100127 EmulatedRoute* out = route.get();
128 routes_.push_back(std::move(route));
129 return out;
Artem Titov0774bd92019-01-30 15:26:05 +0100130}
131
Sebastian Janssonb13ccc52019-06-07 13:06:00 +0200132EmulatedRoute* NetworkEmulationManagerImpl::CreateRoute(
133 const std::vector<EmulatedNetworkNode*>& via_nodes) {
134 EmulatedEndpoint* from = CreateEndpoint(EmulatedEndpointConfig());
135 EmulatedEndpoint* to = CreateEndpoint(EmulatedEndpointConfig());
136 return CreateRoute(from, via_nodes, to);
137}
138
Artem Titov7bf8c7f2019-03-15 15:00:37 +0100139void NetworkEmulationManagerImpl::ClearRoute(EmulatedRoute* route) {
Artem Titovfc6ab002019-03-12 13:48:32 +0100140 RTC_CHECK(route->active) << "Route already cleared";
Danil Chapovaloveb90e6f2019-10-15 10:04:57 +0200141 task_queue_.SendTask(
142 [route]() {
143 // Remove receiver from intermediate nodes.
144 for (auto* node : route->via_nodes) {
145 node->router()->RemoveReceiver(route->to->GetPeerLocalAddress());
146 }
147 // Remove destination endpoint from source endpoint's router.
148 route->from->router()->RemoveReceiver(route->to->GetPeerLocalAddress());
Artem Titovfc6ab002019-03-12 13:48:32 +0100149
Danil Chapovaloveb90e6f2019-10-15 10:04:57 +0200150 route->active = false;
151 },
152 RTC_FROM_HERE);
Artem Titov0774bd92019-01-30 15:26:05 +0100153}
154
Artem Titov7bf8c7f2019-03-15 15:00:37 +0100155TrafficRoute* NetworkEmulationManagerImpl::CreateTrafficRoute(
156 const std::vector<EmulatedNetworkNode*>& via_nodes) {
Artem Titovd3666b22019-02-11 14:40:17 +0100157 RTC_CHECK(!via_nodes.empty());
Artem Titova268b692019-03-12 13:37:28 +0100158 EmulatedEndpoint* endpoint = CreateEndpoint(EmulatedEndpointConfig());
Artem Titovd3666b22019-02-11 14:40:17 +0100159
160 // Setup a route via specified nodes.
161 EmulatedNetworkNode* cur_node = via_nodes[0];
162 for (size_t i = 1; i < via_nodes.size(); ++i) {
Sebastian Jansson62bb47f2019-04-01 18:23:58 +0200163 cur_node->router()->SetReceiver(endpoint->GetPeerLocalAddress(),
164 via_nodes[i]);
Artem Titovd3666b22019-02-11 14:40:17 +0100165 cur_node = via_nodes[i];
166 }
Sebastian Jansson62bb47f2019-04-01 18:23:58 +0200167 cur_node->router()->SetReceiver(endpoint->GetPeerLocalAddress(), endpoint);
Artem Titovd3666b22019-02-11 14:40:17 +0100168
169 std::unique_ptr<TrafficRoute> traffic_route =
Mirko Bonadei317a1f02019-09-17 17:06:18 +0200170 std::make_unique<TrafficRoute>(clock_, via_nodes[0], endpoint);
Artem Titovd3666b22019-02-11 14:40:17 +0100171 TrafficRoute* out = traffic_route.get();
172 traffic_routes_.push_back(std::move(traffic_route));
173 return out;
174}
175
Artem Titov7bf8c7f2019-03-15 15:00:37 +0100176RandomWalkCrossTraffic*
177NetworkEmulationManagerImpl::CreateRandomWalkCrossTraffic(
Artem Titovd3666b22019-02-11 14:40:17 +0100178 TrafficRoute* traffic_route,
179 RandomWalkConfig config) {
Sebastian Janssonf6e64352019-04-17 18:02:34 +0200180 auto traffic =
Mirko Bonadei317a1f02019-09-17 17:06:18 +0200181 std::make_unique<RandomWalkCrossTraffic>(config, traffic_route);
Artem Titovd3666b22019-02-11 14:40:17 +0100182 RandomWalkCrossTraffic* out = traffic.get();
Sebastian Janssonf6e64352019-04-17 18:02:34 +0200183
Sebastian Jansson86314cf2019-09-17 20:29:59 +0200184 task_queue_.PostTask(
185 [this, config, traffic = std::move(traffic)]() mutable {
Sebastian Jansson2d87a502019-04-23 09:55:38 +0200186 auto* traffic_ptr = traffic.get();
Sebastian Janssonf6e64352019-04-17 18:02:34 +0200187 random_cross_traffics_.push_back(std::move(traffic));
Sebastian Jansson2d87a502019-04-23 09:55:38 +0200188 RepeatingTaskHandle::Start(task_queue_.Get(),
189 [this, config, traffic_ptr] {
190 traffic_ptr->Process(Now());
191 return config.min_packet_interval;
192 });
Sebastian Jansson86314cf2019-09-17 20:29:59 +0200193 });
Artem Titovd3666b22019-02-11 14:40:17 +0100194 return out;
195}
196
Artem Titov7bf8c7f2019-03-15 15:00:37 +0100197PulsedPeaksCrossTraffic*
198NetworkEmulationManagerImpl::CreatePulsedPeaksCrossTraffic(
Artem Titovd3666b22019-02-11 14:40:17 +0100199 TrafficRoute* traffic_route,
200 PulsedPeaksConfig config) {
Sebastian Janssonf6e64352019-04-17 18:02:34 +0200201 auto traffic =
Mirko Bonadei317a1f02019-09-17 17:06:18 +0200202 std::make_unique<PulsedPeaksCrossTraffic>(config, traffic_route);
Artem Titovd3666b22019-02-11 14:40:17 +0100203 PulsedPeaksCrossTraffic* out = traffic.get();
Sebastian Jansson86314cf2019-09-17 20:29:59 +0200204 task_queue_.PostTask(
205 [this, config, traffic = std::move(traffic)]() mutable {
Sebastian Jansson2d87a502019-04-23 09:55:38 +0200206 auto* traffic_ptr = traffic.get();
Sebastian Janssonf6e64352019-04-17 18:02:34 +0200207 pulsed_cross_traffics_.push_back(std::move(traffic));
Sebastian Jansson2d87a502019-04-23 09:55:38 +0200208 RepeatingTaskHandle::Start(task_queue_.Get(),
209 [this, config, traffic_ptr] {
210 traffic_ptr->Process(Now());
211 return config.min_packet_interval;
212 });
Sebastian Jansson86314cf2019-09-17 20:29:59 +0200213 });
Artem Titovd3666b22019-02-11 14:40:17 +0100214 return out;
215}
216
Sebastian Janssond8aff212019-10-11 17:00:39 +0200217FakeTcpCrossTraffic* NetworkEmulationManagerImpl::StartFakeTcpCrossTraffic(
218 std::vector<EmulatedNetworkNode*> send_link,
219 std::vector<EmulatedNetworkNode*> ret_link,
Sebastian Janssonb13ccc52019-06-07 13:06:00 +0200220 FakeTcpConfig config) {
Sebastian Janssond8aff212019-10-11 17:00:39 +0200221 auto traffic = std::make_unique<FakeTcpCrossTraffic>(
222 clock_, config, CreateRoute(send_link), CreateRoute(ret_link));
223 auto* traffic_ptr = traffic.get();
224 task_queue_.PostTask([this, traffic = std::move(traffic)]() mutable {
225 traffic->Start(task_queue_.Get());
Sebastian Janssonb13ccc52019-06-07 13:06:00 +0200226 tcp_cross_traffics_.push_back(std::move(traffic));
Sebastian Janssond8aff212019-10-11 17:00:39 +0200227 });
228 return traffic_ptr;
229}
230
Sebastian Janssondcc910a2019-11-12 16:36:34 +0100231TcpMessageRoute* NetworkEmulationManagerImpl::CreateTcpRoute(
Sebastian Jansson50f86862019-11-13 14:10:07 +0100232 EmulatedRoute* send_route,
233 EmulatedRoute* ret_route) {
234 auto tcp_route = std::make_unique<TcpMessageRoute>(clock_, task_queue_.Get(),
235 send_route, ret_route);
Sebastian Janssondcc910a2019-11-12 16:36:34 +0100236 auto* route_ptr = tcp_route.get();
237 task_queue_.PostTask([this, tcp_route = std::move(tcp_route)]() mutable {
238 tcp_message_routes_.push_back(std::move(tcp_route));
239 });
240 return route_ptr;
241}
242
Sebastian Janssond8aff212019-10-11 17:00:39 +0200243void NetworkEmulationManagerImpl::StopCrossTraffic(
244 FakeTcpCrossTraffic* traffic) {
245 task_queue_.PostTask([=]() {
246 traffic->Stop();
247 tcp_cross_traffics_.remove_if(
248 [=](const std::unique_ptr<FakeTcpCrossTraffic>& ptr) {
249 return ptr.get() == traffic;
250 });
Sebastian Janssonb13ccc52019-06-07 13:06:00 +0200251 });
252}
253
Artem Titove5cc85b2019-03-28 12:11:09 +0100254EmulatedNetworkManagerInterface*
255NetworkEmulationManagerImpl::CreateEmulatedNetworkManagerInterface(
Artem Titov7bf8c7f2019-03-15 15:00:37 +0100256 const std::vector<EmulatedEndpoint*>& endpoints) {
Mirko Bonadei317a1f02019-09-17 17:06:18 +0200257 auto endpoints_container = std::make_unique<EndpointsContainer>(endpoints);
258 auto network_manager = std::make_unique<EmulatedNetworkManager>(
Artem Titov806299e2019-04-12 12:17:19 +0200259 clock_, &task_queue_, endpoints_container.get());
Artem Titov20863472019-03-13 10:30:51 +0100260 for (auto* endpoint : endpoints) {
Artem Titove5cc85b2019-03-28 12:11:09 +0100261 // Associate endpoint with network manager.
262 bool insertion_result =
263 endpoint_to_network_manager_.insert({endpoint, network_manager.get()})
264 .second;
265 RTC_CHECK(insertion_result)
266 << "Endpoint ip=" << endpoint->GetPeerLocalAddress().ToString()
267 << " is already used for another network";
Artem Titov20863472019-03-13 10:30:51 +0100268 }
Artem Titov20863472019-03-13 10:30:51 +0100269
Artem Titove5cc85b2019-03-28 12:11:09 +0100270 EmulatedNetworkManagerInterface* out = network_manager.get();
271
Artem Titov0d32a732019-04-05 14:49:59 +0200272 endpoints_containers_.push_back(std::move(endpoints_container));
Artem Titove5cc85b2019-03-28 12:11:09 +0100273 network_managers_.push_back(std::move(network_manager));
Artem Titov0774bd92019-01-30 15:26:05 +0100274 return out;
275}
276
Artem Titov7bf8c7f2019-03-15 15:00:37 +0100277absl::optional<rtc::IPAddress>
278NetworkEmulationManagerImpl::GetNextIPv4Address() {
Artem Titov0bf4c292019-02-26 10:00:07 +0100279 uint32_t addresses_count = kMaxIPv4Address - kMinIPv4Address;
280 for (uint32_t i = 0; i < addresses_count; i++) {
281 rtc::IPAddress ip(next_ip4_address_);
282 if (next_ip4_address_ == kMaxIPv4Address) {
283 next_ip4_address_ = kMinIPv4Address;
284 } else {
285 next_ip4_address_++;
286 }
287 if (used_ip_addresses_.find(ip) == used_ip_addresses_.end()) {
288 return ip;
289 }
290 }
291 return absl::nullopt;
292}
293
Artem Titov7bf8c7f2019-03-15 15:00:37 +0100294Timestamp NetworkEmulationManagerImpl::Now() const {
Sebastian Janssonb64ad0e2019-06-19 09:39:34 +0200295 return clock_->CurrentTime();
Artem Titov0774bd92019-01-30 15:26:05 +0100296}
297
298} // namespace test
299} // namespace webrtc