blob: e38867f4eeb1e57c4bdf85b7998b43417e39890b [file] [log] [blame]
Artem Titov0774bd92019-01-30 15:26:05 +01001/*
2 * Copyright 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
Jonas Olssona4d87372019-07-05 19:08:33 +020011#include "test/network/network_emulation.h"
12
Artem Titovff393122019-04-05 11:19:52 +020013#include <atomic>
Artem Titov0774bd92019-01-30 15:26:05 +010014#include <memory>
Artem Titov386802e2019-07-05 10:48:17 +020015#include <set>
Artem Titov0774bd92019-01-30 15:26:05 +010016
17#include "absl/memory/memory.h"
18#include "api/test/simulated_network.h"
Artem Titova7683452019-05-15 12:26:38 +020019#include "api/units/time_delta.h"
Artem Titov0774bd92019-01-30 15:26:05 +010020#include "call/simulated_network.h"
21#include "rtc_base/event.h"
Artem Titovff393122019-04-05 11:19:52 +020022#include "rtc_base/gunit.h"
Artem Titovff393122019-04-05 11:19:52 +020023#include "system_wrappers/include/sleep.h"
Artem Titov0774bd92019-01-30 15:26:05 +010024#include "test/gmock.h"
25#include "test/gtest.h"
Artem Titov386802e2019-07-05 10:48:17 +020026#include "test/network/network_emulation_manager.h"
Artem Titov0774bd92019-01-30 15:26:05 +010027
28namespace webrtc {
29namespace test {
Artem Titovff393122019-04-05 11:19:52 +020030namespace {
31
32constexpr int kNetworkPacketWaitTimeoutMs = 100;
Artem Titov806299e2019-04-12 12:17:19 +020033constexpr int kStatsWaitTimeoutMs = 1000;
Artem Titov0774bd92019-01-30 15:26:05 +010034
35class SocketReader : public sigslot::has_slots<> {
36 public:
Artem Titov519d74a2019-05-17 12:01:00 +020037 explicit SocketReader(rtc::AsyncSocket* socket, rtc::Thread* network_thread)
38 : socket_(socket), network_thread_(network_thread) {
Artem Titov0774bd92019-01-30 15:26:05 +010039 socket_->SignalReadEvent.connect(this, &SocketReader::OnReadEvent);
40 size_ = 128 * 1024;
41 buf_ = new char[size_];
42 }
43 ~SocketReader() override { delete[] buf_; }
44
45 void OnReadEvent(rtc::AsyncSocket* socket) {
46 RTC_DCHECK(socket_ == socket);
Artem Titov519d74a2019-05-17 12:01:00 +020047 network_thread_->PostTask(RTC_FROM_HERE, [this]() {
48 int64_t timestamp;
49 len_ = socket_->Recv(buf_, size_, &timestamp);
50
Artem Titov0774bd92019-01-30 15:26:05 +010051 rtc::CritScope crit(&lock_);
52 received_count_++;
Artem Titov519d74a2019-05-17 12:01:00 +020053 });
Artem Titov0774bd92019-01-30 15:26:05 +010054 }
55
56 int ReceivedCount() {
57 rtc::CritScope crit(&lock_);
58 return received_count_;
59 }
60
61 private:
Artem Titov519d74a2019-05-17 12:01:00 +020062 rtc::AsyncSocket* const socket_;
63 rtc::Thread* const network_thread_;
Artem Titov0774bd92019-01-30 15:26:05 +010064 char* buf_;
65 size_t size_;
66 int len_;
67
68 rtc::CriticalSection lock_;
69 int received_count_ RTC_GUARDED_BY(lock_) = 0;
70};
71
Artem Titovff393122019-04-05 11:19:52 +020072class MockReceiver : public EmulatedNetworkReceiverInterface {
73 public:
74 MOCK_METHOD1(OnPacketReceived, void(EmulatedIpPacket packet));
75};
76
77class NetworkEmulationManagerThreeNodesRoutingTest : public ::testing::Test {
78 public:
79 NetworkEmulationManagerThreeNodesRoutingTest() {
80 e1_ = emulation_.CreateEndpoint(EmulatedEndpointConfig());
81 e2_ = emulation_.CreateEndpoint(EmulatedEndpointConfig());
82 e3_ = emulation_.CreateEndpoint(EmulatedEndpointConfig());
83 }
84
85 void SetupRouting(
86 std::function<void(EmulatedEndpoint*,
87 EmulatedEndpoint*,
88 EmulatedEndpoint*,
89 NetworkEmulationManager*)> create_routing_func) {
90 create_routing_func(e1_, e2_, e3_, &emulation_);
91 }
92
93 void SendPacketsAndValidateDelivery() {
Mirko Bonadei6a489f22019-04-09 15:11:12 +020094 EXPECT_CALL(r_e1_e2_, OnPacketReceived(::testing::_)).Times(1);
95 EXPECT_CALL(r_e2_e1_, OnPacketReceived(::testing::_)).Times(1);
96 EXPECT_CALL(r_e1_e3_, OnPacketReceived(::testing::_)).Times(1);
97 EXPECT_CALL(r_e3_e1_, OnPacketReceived(::testing::_)).Times(1);
Artem Titovff393122019-04-05 11:19:52 +020098
99 uint16_t common_send_port = 80;
100 uint16_t r_e1_e2_port = e2_->BindReceiver(0, &r_e1_e2_).value();
101 uint16_t r_e2_e1_port = e1_->BindReceiver(0, &r_e2_e1_).value();
102 uint16_t r_e1_e3_port = e3_->BindReceiver(0, &r_e1_e3_).value();
103 uint16_t r_e3_e1_port = e1_->BindReceiver(0, &r_e3_e1_).value();
104
105 // Next code is using API of EmulatedEndpoint, that is visible only for
106 // internals of network emulation layer. Don't use this API in other tests.
107 // Send packet from e1 to e2.
108 e1_->SendPacket(
109 rtc::SocketAddress(e1_->GetPeerLocalAddress(), common_send_port),
110 rtc::SocketAddress(e2_->GetPeerLocalAddress(), r_e1_e2_port),
111 rtc::CopyOnWriteBuffer(10));
112
113 // Send packet from e2 to e1.
114 e2_->SendPacket(
115 rtc::SocketAddress(e2_->GetPeerLocalAddress(), common_send_port),
116 rtc::SocketAddress(e1_->GetPeerLocalAddress(), r_e2_e1_port),
117 rtc::CopyOnWriteBuffer(10));
118
119 // Send packet from e1 to e3.
120 e1_->SendPacket(
121 rtc::SocketAddress(e1_->GetPeerLocalAddress(), common_send_port),
122 rtc::SocketAddress(e3_->GetPeerLocalAddress(), r_e1_e3_port),
123 rtc::CopyOnWriteBuffer(10));
124
125 // Send packet from e3 to e1.
126 e3_->SendPacket(
127 rtc::SocketAddress(e3_->GetPeerLocalAddress(), common_send_port),
128 rtc::SocketAddress(e1_->GetPeerLocalAddress(), r_e3_e1_port),
129 rtc::CopyOnWriteBuffer(10));
130
131 // Sleep at the end to wait for async packets delivery.
132 SleepMs(kNetworkPacketWaitTimeoutMs);
133 }
134
135 private:
136 // Receivers: r_<source endpoint>_<destination endpoint>
137 // They must be destroyed after emulation, so they should be declared before.
138 MockReceiver r_e1_e2_;
139 MockReceiver r_e2_e1_;
140 MockReceiver r_e1_e3_;
141 MockReceiver r_e3_e1_;
142
143 NetworkEmulationManagerImpl emulation_;
144 EmulatedEndpoint* e1_;
145 EmulatedEndpoint* e2_;
146 EmulatedEndpoint* e3_;
147};
148
149EmulatedNetworkNode* CreateEmulatedNodeWithDefaultBuiltInConfig(
150 NetworkEmulationManager* emulation) {
151 return emulation->CreateEmulatedNode(
152 absl::make_unique<SimulatedNetwork>(BuiltInNetworkBehaviorConfig()));
153}
154
155} // namespace
156
Mirko Bonadei6a489f22019-04-09 15:11:12 +0200157using ::testing::_;
Artem Titovff393122019-04-05 11:19:52 +0200158
Artem Titov0bf4c292019-02-26 10:00:07 +0100159TEST(NetworkEmulationManagerTest, GeneratedIpv4AddressDoesNotCollide) {
Artem Titov7bf8c7f2019-03-15 15:00:37 +0100160 NetworkEmulationManagerImpl network_manager;
Artem Titov0bf4c292019-02-26 10:00:07 +0100161 std::set<rtc::IPAddress> ips;
Artem Titova268b692019-03-12 13:37:28 +0100162 EmulatedEndpointConfig config;
163 config.generated_ip_family = EmulatedEndpointConfig::IpAddressFamily::kIpv4;
Artem Titov0bf4c292019-02-26 10:00:07 +0100164 for (int i = 0; i < 1000; i++) {
Artem Titovaba8dc22019-03-11 10:08:40 +0100165 EmulatedEndpoint* endpoint = network_manager.CreateEndpoint(config);
Artem Titov0bf4c292019-02-26 10:00:07 +0100166 ASSERT_EQ(endpoint->GetPeerLocalAddress().family(), AF_INET);
167 bool result = ips.insert(endpoint->GetPeerLocalAddress()).second;
168 ASSERT_TRUE(result);
169 }
170}
171
172TEST(NetworkEmulationManagerTest, GeneratedIpv6AddressDoesNotCollide) {
Artem Titov7bf8c7f2019-03-15 15:00:37 +0100173 NetworkEmulationManagerImpl network_manager;
Artem Titov0bf4c292019-02-26 10:00:07 +0100174 std::set<rtc::IPAddress> ips;
Artem Titova268b692019-03-12 13:37:28 +0100175 EmulatedEndpointConfig config;
176 config.generated_ip_family = EmulatedEndpointConfig::IpAddressFamily::kIpv6;
Artem Titov0bf4c292019-02-26 10:00:07 +0100177 for (int i = 0; i < 1000; i++) {
Artem Titovaba8dc22019-03-11 10:08:40 +0100178 EmulatedEndpoint* endpoint = network_manager.CreateEndpoint(config);
Artem Titov0bf4c292019-02-26 10:00:07 +0100179 ASSERT_EQ(endpoint->GetPeerLocalAddress().family(), AF_INET6);
180 bool result = ips.insert(endpoint->GetPeerLocalAddress()).second;
181 ASSERT_TRUE(result);
182 }
183}
184
Artem Titov0774bd92019-01-30 15:26:05 +0100185TEST(NetworkEmulationManagerTest, Run) {
Artem Titov7bf8c7f2019-03-15 15:00:37 +0100186 NetworkEmulationManagerImpl network_manager;
Artem Titov0774bd92019-01-30 15:26:05 +0100187
188 EmulatedNetworkNode* alice_node = network_manager.CreateEmulatedNode(
189 absl::make_unique<SimulatedNetwork>(BuiltInNetworkBehaviorConfig()));
190 EmulatedNetworkNode* bob_node = network_manager.CreateEmulatedNode(
191 absl::make_unique<SimulatedNetwork>(BuiltInNetworkBehaviorConfig()));
Artem Titovaba8dc22019-03-11 10:08:40 +0100192 EmulatedEndpoint* alice_endpoint =
Artem Titova268b692019-03-12 13:37:28 +0100193 network_manager.CreateEndpoint(EmulatedEndpointConfig());
Artem Titovaba8dc22019-03-11 10:08:40 +0100194 EmulatedEndpoint* bob_endpoint =
Artem Titova268b692019-03-12 13:37:28 +0100195 network_manager.CreateEndpoint(EmulatedEndpointConfig());
Artem Titov0774bd92019-01-30 15:26:05 +0100196 network_manager.CreateRoute(alice_endpoint, {alice_node}, bob_endpoint);
197 network_manager.CreateRoute(bob_endpoint, {bob_node}, alice_endpoint);
198
Artem Titove5cc85b2019-03-28 12:11:09 +0100199 EmulatedNetworkManagerInterface* nt1 =
200 network_manager.CreateEmulatedNetworkManagerInterface({alice_endpoint});
201 EmulatedNetworkManagerInterface* nt2 =
202 network_manager.CreateEmulatedNetworkManagerInterface({bob_endpoint});
Artem Titov0774bd92019-01-30 15:26:05 +0100203
Artem Titov806299e2019-04-12 12:17:19 +0200204 rtc::CopyOnWriteBuffer data("Hello");
Artem Titov0774bd92019-01-30 15:26:05 +0100205 for (uint64_t j = 0; j < 2; j++) {
Artem Titove5cc85b2019-03-28 12:11:09 +0100206 auto* s1 = nt1->network_thread()->socketserver()->CreateAsyncSocket(
207 AF_INET, SOCK_DGRAM);
208 auto* s2 = nt2->network_thread()->socketserver()->CreateAsyncSocket(
209 AF_INET, SOCK_DGRAM);
Artem Titov0774bd92019-01-30 15:26:05 +0100210
Artem Titov519d74a2019-05-17 12:01:00 +0200211 SocketReader r1(s1, nt1->network_thread());
212 SocketReader r2(s2, nt2->network_thread());
Artem Titov0774bd92019-01-30 15:26:05 +0100213
214 rtc::SocketAddress a1(alice_endpoint->GetPeerLocalAddress(), 0);
215 rtc::SocketAddress a2(bob_endpoint->GetPeerLocalAddress(), 0);
216
217 s1->Bind(a1);
218 s2->Bind(a2);
219
Artem Titove5cc85b2019-03-28 12:11:09 +0100220 s1->Connect(s2->GetLocalAddress());
221 s2->Connect(s1->GetLocalAddress());
Artem Titov0774bd92019-01-30 15:26:05 +0100222
Artem Titov0774bd92019-01-30 15:26:05 +0100223 for (uint64_t i = 0; i < 1000; i++) {
Artem Titov519d74a2019-05-17 12:01:00 +0200224 nt1->network_thread()->PostTask(
225 RTC_FROM_HERE, [&]() { s1->Send(data.data(), data.size()); });
226 nt2->network_thread()->PostTask(
227 RTC_FROM_HERE, [&]() { s2->Send(data.data(), data.size()); });
Artem Titov0774bd92019-01-30 15:26:05 +0100228 }
229
230 rtc::Event wait;
231 wait.Wait(1000);
Artem Titov806299e2019-04-12 12:17:19 +0200232 EXPECT_EQ(r1.ReceivedCount(), 1000);
233 EXPECT_EQ(r2.ReceivedCount(), 1000);
Artem Titov0774bd92019-01-30 15:26:05 +0100234
235 delete s1;
236 delete s2;
237 }
Artem Titov806299e2019-04-12 12:17:19 +0200238
239 int64_t single_packet_size = data.size();
240 std::atomic<int> received_stats_count{0};
241 nt1->GetStats([&](EmulatedNetworkStats st) {
242 EXPECT_EQ(st.packets_sent, 2000l);
243 EXPECT_EQ(st.bytes_sent.bytes(), single_packet_size * 2000l);
244 EXPECT_EQ(st.packets_received, 2000l);
245 EXPECT_EQ(st.bytes_received.bytes(), single_packet_size * 2000l);
246 EXPECT_EQ(st.packets_dropped, 0l);
247 EXPECT_EQ(st.bytes_dropped.bytes(), 0l);
248 received_stats_count++;
249 });
250 nt2->GetStats([&](EmulatedNetworkStats st) {
251 EXPECT_EQ(st.packets_sent, 2000l);
252 EXPECT_EQ(st.bytes_sent.bytes(), single_packet_size * 2000l);
253 EXPECT_EQ(st.packets_received, 2000l);
254 EXPECT_EQ(st.bytes_received.bytes(), single_packet_size * 2000l);
255 EXPECT_EQ(st.packets_dropped, 0l);
256 EXPECT_EQ(st.bytes_dropped.bytes(), 0l);
257 received_stats_count++;
258 });
259 ASSERT_EQ_WAIT(received_stats_count.load(), 2, kStatsWaitTimeoutMs);
260}
261
Artem Titova7683452019-05-15 12:26:38 +0200262TEST(NetworkEmulationManagerTest, ThroughputStats) {
Artem Titov806299e2019-04-12 12:17:19 +0200263 NetworkEmulationManagerImpl network_manager;
264
265 EmulatedNetworkNode* alice_node = network_manager.CreateEmulatedNode(
266 absl::make_unique<SimulatedNetwork>(BuiltInNetworkBehaviorConfig()));
267 EmulatedNetworkNode* bob_node = network_manager.CreateEmulatedNode(
268 absl::make_unique<SimulatedNetwork>(BuiltInNetworkBehaviorConfig()));
269 EmulatedEndpoint* alice_endpoint =
270 network_manager.CreateEndpoint(EmulatedEndpointConfig());
271 EmulatedEndpoint* bob_endpoint =
272 network_manager.CreateEndpoint(EmulatedEndpointConfig());
273 network_manager.CreateRoute(alice_endpoint, {alice_node}, bob_endpoint);
274 network_manager.CreateRoute(bob_endpoint, {bob_node}, alice_endpoint);
275
276 EmulatedNetworkManagerInterface* nt1 =
277 network_manager.CreateEmulatedNetworkManagerInterface({alice_endpoint});
278 EmulatedNetworkManagerInterface* nt2 =
279 network_manager.CreateEmulatedNetworkManagerInterface({bob_endpoint});
280
281 int64_t single_packet_size = 100;
282 rtc::CopyOnWriteBuffer data(single_packet_size);
283 auto* s1 = nt1->network_thread()->socketserver()->CreateAsyncSocket(
284 AF_INET, SOCK_DGRAM);
285 auto* s2 = nt2->network_thread()->socketserver()->CreateAsyncSocket(
286 AF_INET, SOCK_DGRAM);
287
Artem Titov519d74a2019-05-17 12:01:00 +0200288 SocketReader r1(s1, nt1->network_thread());
289 SocketReader r2(s2, nt2->network_thread());
Artem Titov806299e2019-04-12 12:17:19 +0200290
291 rtc::SocketAddress a1(alice_endpoint->GetPeerLocalAddress(), 0);
292 rtc::SocketAddress a2(bob_endpoint->GetPeerLocalAddress(), 0);
293
294 s1->Bind(a1);
295 s2->Bind(a2);
296
297 s1->Connect(s2->GetLocalAddress());
298 s2->Connect(s1->GetLocalAddress());
299
Yves Gereyb64d65e2019-09-06 16:35:20 +0200300 // Send 11 packets, totalizing 1 second between the first and the last.
301 const int kNumPacketsSent = 11;
302 const int kDelayMs = 100;
Artem Titov806299e2019-04-12 12:17:19 +0200303 rtc::Event wait;
Yves Gereyb64d65e2019-09-06 16:35:20 +0200304 for (int i = 0; i < kNumPacketsSent; i++) {
Artem Titov519d74a2019-05-17 12:01:00 +0200305 nt1->network_thread()->PostTask(
306 RTC_FROM_HERE, [&]() { s1->Send(data.data(), data.size()); });
307 nt2->network_thread()->PostTask(
308 RTC_FROM_HERE, [&]() { s2->Send(data.data(), data.size()); });
Yves Gereyb64d65e2019-09-06 16:35:20 +0200309 wait.Wait(kDelayMs);
Artem Titov806299e2019-04-12 12:17:19 +0200310 }
Artem Titov806299e2019-04-12 12:17:19 +0200311
Artem Titov806299e2019-04-12 12:17:19 +0200312 std::atomic<int> received_stats_count{0};
313 nt1->GetStats([&](EmulatedNetworkStats st) {
Yves Gereyb64d65e2019-09-06 16:35:20 +0200314 EXPECT_EQ(st.packets_sent, kNumPacketsSent);
315 EXPECT_EQ(st.bytes_sent.bytes(), single_packet_size * kNumPacketsSent);
316
317 const double tolerance = 0.99; // Accept 1% tolerance for timing.
Artem Titova7683452019-05-15 12:26:38 +0200318 EXPECT_GE(st.last_packet_sent_time - st.first_packet_sent_time,
Yves Gereyb64d65e2019-09-06 16:35:20 +0200319 TimeDelta::ms((kNumPacketsSent - 1) * kDelayMs * tolerance));
Artem Titova7683452019-05-15 12:26:38 +0200320 EXPECT_GT(st.AverageSendRate().bps(), 0);
Artem Titov806299e2019-04-12 12:17:19 +0200321 received_stats_count++;
322 });
323 ASSERT_EQ_WAIT(received_stats_count.load(), 1, kStatsWaitTimeoutMs);
Artem Titova7683452019-05-15 12:26:38 +0200324 EXPECT_EQ(r1.ReceivedCount(), 11);
325 EXPECT_EQ(r2.ReceivedCount(), 11);
Artem Titov519d74a2019-05-17 12:01:00 +0200326
327 delete s1;
328 delete s2;
Artem Titov0774bd92019-01-30 15:26:05 +0100329}
330
Artem Titovff393122019-04-05 11:19:52 +0200331// Testing that packets are delivered via all routes using a routing scheme as
332// follows:
333// * e1 -> n1 -> e2
334// * e2 -> n2 -> e1
335// * e1 -> n3 -> e3
336// * e3 -> n4 -> e1
337TEST_F(NetworkEmulationManagerThreeNodesRoutingTest,
338 PacketsAreDeliveredInBothWaysWhenConnectedToTwoPeers) {
339 SetupRouting([](EmulatedEndpoint* e1, EmulatedEndpoint* e2,
340 EmulatedEndpoint* e3, NetworkEmulationManager* emulation) {
341 auto* node1 = CreateEmulatedNodeWithDefaultBuiltInConfig(emulation);
342 auto* node2 = CreateEmulatedNodeWithDefaultBuiltInConfig(emulation);
343 auto* node3 = CreateEmulatedNodeWithDefaultBuiltInConfig(emulation);
344 auto* node4 = CreateEmulatedNodeWithDefaultBuiltInConfig(emulation);
345
346 emulation->CreateRoute(e1, {node1}, e2);
347 emulation->CreateRoute(e2, {node2}, e1);
348
349 emulation->CreateRoute(e1, {node3}, e3);
350 emulation->CreateRoute(e3, {node4}, e1);
351 });
352 SendPacketsAndValidateDelivery();
353}
354
355// Testing that packets are delivered via all routes using a routing scheme as
356// follows:
357// * e1 -> n1 -> e2
358// * e2 -> n2 -> e1
359// * e1 -> n1 -> e3
360// * e3 -> n4 -> e1
361TEST_F(NetworkEmulationManagerThreeNodesRoutingTest,
362 PacketsAreDeliveredInBothWaysWhenConnectedToTwoPeersOverSameSendLink) {
363 SetupRouting([](EmulatedEndpoint* e1, EmulatedEndpoint* e2,
364 EmulatedEndpoint* e3, NetworkEmulationManager* emulation) {
365 auto* node1 = CreateEmulatedNodeWithDefaultBuiltInConfig(emulation);
366 auto* node2 = CreateEmulatedNodeWithDefaultBuiltInConfig(emulation);
367 auto* node3 = CreateEmulatedNodeWithDefaultBuiltInConfig(emulation);
368
369 emulation->CreateRoute(e1, {node1}, e2);
370 emulation->CreateRoute(e2, {node2}, e1);
371
372 emulation->CreateRoute(e1, {node1}, e3);
373 emulation->CreateRoute(e3, {node3}, e1);
374 });
375 SendPacketsAndValidateDelivery();
376}
377
Artem Titov0774bd92019-01-30 15:26:05 +0100378} // namespace test
379} // namespace webrtc