blob: adc7b42e0fc46aab04b11dba08130626f813f47f [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 Titov0774bd92019-01-30 15:26:05 +010023#include "rtc_base/logging.h"
Artem Titovff393122019-04-05 11:19:52 +020024#include "system_wrappers/include/sleep.h"
Artem Titov0774bd92019-01-30 15:26:05 +010025#include "test/gmock.h"
26#include "test/gtest.h"
Artem Titov386802e2019-07-05 10:48:17 +020027#include "test/network/network_emulation_manager.h"
Artem Titov0774bd92019-01-30 15:26:05 +010028
29namespace webrtc {
30namespace test {
Artem Titovff393122019-04-05 11:19:52 +020031namespace {
32
33constexpr int kNetworkPacketWaitTimeoutMs = 100;
Artem Titov806299e2019-04-12 12:17:19 +020034constexpr int kStatsWaitTimeoutMs = 1000;
Artem Titov0774bd92019-01-30 15:26:05 +010035
36class SocketReader : public sigslot::has_slots<> {
37 public:
Artem Titov519d74a2019-05-17 12:01:00 +020038 explicit SocketReader(rtc::AsyncSocket* socket, rtc::Thread* network_thread)
39 : socket_(socket), network_thread_(network_thread) {
Artem Titov0774bd92019-01-30 15:26:05 +010040 socket_->SignalReadEvent.connect(this, &SocketReader::OnReadEvent);
41 size_ = 128 * 1024;
42 buf_ = new char[size_];
43 }
44 ~SocketReader() override { delete[] buf_; }
45
46 void OnReadEvent(rtc::AsyncSocket* socket) {
47 RTC_DCHECK(socket_ == socket);
Artem Titov519d74a2019-05-17 12:01:00 +020048 network_thread_->PostTask(RTC_FROM_HERE, [this]() {
49 int64_t timestamp;
50 len_ = socket_->Recv(buf_, size_, &timestamp);
51
Artem Titov0774bd92019-01-30 15:26:05 +010052 rtc::CritScope crit(&lock_);
53 received_count_++;
Artem Titov519d74a2019-05-17 12:01:00 +020054 });
Artem Titov0774bd92019-01-30 15:26:05 +010055 }
56
57 int ReceivedCount() {
58 rtc::CritScope crit(&lock_);
59 return received_count_;
60 }
61
62 private:
Artem Titov519d74a2019-05-17 12:01:00 +020063 rtc::AsyncSocket* const socket_;
64 rtc::Thread* const network_thread_;
Artem Titov0774bd92019-01-30 15:26:05 +010065 char* buf_;
66 size_t size_;
67 int len_;
68
69 rtc::CriticalSection lock_;
70 int received_count_ RTC_GUARDED_BY(lock_) = 0;
71};
72
Artem Titovff393122019-04-05 11:19:52 +020073class MockReceiver : public EmulatedNetworkReceiverInterface {
74 public:
75 MOCK_METHOD1(OnPacketReceived, void(EmulatedIpPacket packet));
76};
77
78class NetworkEmulationManagerThreeNodesRoutingTest : public ::testing::Test {
79 public:
80 NetworkEmulationManagerThreeNodesRoutingTest() {
81 e1_ = emulation_.CreateEndpoint(EmulatedEndpointConfig());
82 e2_ = emulation_.CreateEndpoint(EmulatedEndpointConfig());
83 e3_ = emulation_.CreateEndpoint(EmulatedEndpointConfig());
84 }
85
86 void SetupRouting(
87 std::function<void(EmulatedEndpoint*,
88 EmulatedEndpoint*,
89 EmulatedEndpoint*,
90 NetworkEmulationManager*)> create_routing_func) {
91 create_routing_func(e1_, e2_, e3_, &emulation_);
92 }
93
94 void SendPacketsAndValidateDelivery() {
Mirko Bonadei6a489f22019-04-09 15:11:12 +020095 EXPECT_CALL(r_e1_e2_, OnPacketReceived(::testing::_)).Times(1);
96 EXPECT_CALL(r_e2_e1_, OnPacketReceived(::testing::_)).Times(1);
97 EXPECT_CALL(r_e1_e3_, OnPacketReceived(::testing::_)).Times(1);
98 EXPECT_CALL(r_e3_e1_, OnPacketReceived(::testing::_)).Times(1);
Artem Titovff393122019-04-05 11:19:52 +020099
100 uint16_t common_send_port = 80;
101 uint16_t r_e1_e2_port = e2_->BindReceiver(0, &r_e1_e2_).value();
102 uint16_t r_e2_e1_port = e1_->BindReceiver(0, &r_e2_e1_).value();
103 uint16_t r_e1_e3_port = e3_->BindReceiver(0, &r_e1_e3_).value();
104 uint16_t r_e3_e1_port = e1_->BindReceiver(0, &r_e3_e1_).value();
105
106 // Next code is using API of EmulatedEndpoint, that is visible only for
107 // internals of network emulation layer. Don't use this API in other tests.
108 // Send packet from e1 to e2.
109 e1_->SendPacket(
110 rtc::SocketAddress(e1_->GetPeerLocalAddress(), common_send_port),
111 rtc::SocketAddress(e2_->GetPeerLocalAddress(), r_e1_e2_port),
112 rtc::CopyOnWriteBuffer(10));
113
114 // Send packet from e2 to e1.
115 e2_->SendPacket(
116 rtc::SocketAddress(e2_->GetPeerLocalAddress(), common_send_port),
117 rtc::SocketAddress(e1_->GetPeerLocalAddress(), r_e2_e1_port),
118 rtc::CopyOnWriteBuffer(10));
119
120 // Send packet from e1 to e3.
121 e1_->SendPacket(
122 rtc::SocketAddress(e1_->GetPeerLocalAddress(), common_send_port),
123 rtc::SocketAddress(e3_->GetPeerLocalAddress(), r_e1_e3_port),
124 rtc::CopyOnWriteBuffer(10));
125
126 // Send packet from e3 to e1.
127 e3_->SendPacket(
128 rtc::SocketAddress(e3_->GetPeerLocalAddress(), common_send_port),
129 rtc::SocketAddress(e1_->GetPeerLocalAddress(), r_e3_e1_port),
130 rtc::CopyOnWriteBuffer(10));
131
132 // Sleep at the end to wait for async packets delivery.
133 SleepMs(kNetworkPacketWaitTimeoutMs);
134 }
135
136 private:
137 // Receivers: r_<source endpoint>_<destination endpoint>
138 // They must be destroyed after emulation, so they should be declared before.
139 MockReceiver r_e1_e2_;
140 MockReceiver r_e2_e1_;
141 MockReceiver r_e1_e3_;
142 MockReceiver r_e3_e1_;
143
144 NetworkEmulationManagerImpl emulation_;
145 EmulatedEndpoint* e1_;
146 EmulatedEndpoint* e2_;
147 EmulatedEndpoint* e3_;
148};
149
150EmulatedNetworkNode* CreateEmulatedNodeWithDefaultBuiltInConfig(
151 NetworkEmulationManager* emulation) {
152 return emulation->CreateEmulatedNode(
153 absl::make_unique<SimulatedNetwork>(BuiltInNetworkBehaviorConfig()));
154}
155
156} // namespace
157
Mirko Bonadei6a489f22019-04-09 15:11:12 +0200158using ::testing::_;
Artem Titovff393122019-04-05 11:19:52 +0200159
Artem Titov0bf4c292019-02-26 10:00:07 +0100160TEST(NetworkEmulationManagerTest, GeneratedIpv4AddressDoesNotCollide) {
Artem Titov7bf8c7f2019-03-15 15:00:37 +0100161 NetworkEmulationManagerImpl network_manager;
Artem Titov0bf4c292019-02-26 10:00:07 +0100162 std::set<rtc::IPAddress> ips;
Artem Titova268b692019-03-12 13:37:28 +0100163 EmulatedEndpointConfig config;
164 config.generated_ip_family = EmulatedEndpointConfig::IpAddressFamily::kIpv4;
Artem Titov0bf4c292019-02-26 10:00:07 +0100165 for (int i = 0; i < 1000; i++) {
Artem Titovaba8dc22019-03-11 10:08:40 +0100166 EmulatedEndpoint* endpoint = network_manager.CreateEndpoint(config);
Artem Titov0bf4c292019-02-26 10:00:07 +0100167 ASSERT_EQ(endpoint->GetPeerLocalAddress().family(), AF_INET);
168 bool result = ips.insert(endpoint->GetPeerLocalAddress()).second;
169 ASSERT_TRUE(result);
170 }
171}
172
173TEST(NetworkEmulationManagerTest, GeneratedIpv6AddressDoesNotCollide) {
Artem Titov7bf8c7f2019-03-15 15:00:37 +0100174 NetworkEmulationManagerImpl network_manager;
Artem Titov0bf4c292019-02-26 10:00:07 +0100175 std::set<rtc::IPAddress> ips;
Artem Titova268b692019-03-12 13:37:28 +0100176 EmulatedEndpointConfig config;
177 config.generated_ip_family = EmulatedEndpointConfig::IpAddressFamily::kIpv6;
Artem Titov0bf4c292019-02-26 10:00:07 +0100178 for (int i = 0; i < 1000; i++) {
Artem Titovaba8dc22019-03-11 10:08:40 +0100179 EmulatedEndpoint* endpoint = network_manager.CreateEndpoint(config);
Artem Titov0bf4c292019-02-26 10:00:07 +0100180 ASSERT_EQ(endpoint->GetPeerLocalAddress().family(), AF_INET6);
181 bool result = ips.insert(endpoint->GetPeerLocalAddress()).second;
182 ASSERT_TRUE(result);
183 }
184}
185
Artem Titov0774bd92019-01-30 15:26:05 +0100186TEST(NetworkEmulationManagerTest, Run) {
Artem Titov7bf8c7f2019-03-15 15:00:37 +0100187 NetworkEmulationManagerImpl network_manager;
Artem Titov0774bd92019-01-30 15:26:05 +0100188
189 EmulatedNetworkNode* alice_node = network_manager.CreateEmulatedNode(
190 absl::make_unique<SimulatedNetwork>(BuiltInNetworkBehaviorConfig()));
191 EmulatedNetworkNode* bob_node = network_manager.CreateEmulatedNode(
192 absl::make_unique<SimulatedNetwork>(BuiltInNetworkBehaviorConfig()));
Artem Titovaba8dc22019-03-11 10:08:40 +0100193 EmulatedEndpoint* alice_endpoint =
Artem Titova268b692019-03-12 13:37:28 +0100194 network_manager.CreateEndpoint(EmulatedEndpointConfig());
Artem Titovaba8dc22019-03-11 10:08:40 +0100195 EmulatedEndpoint* bob_endpoint =
Artem Titova268b692019-03-12 13:37:28 +0100196 network_manager.CreateEndpoint(EmulatedEndpointConfig());
Artem Titov0774bd92019-01-30 15:26:05 +0100197 network_manager.CreateRoute(alice_endpoint, {alice_node}, bob_endpoint);
198 network_manager.CreateRoute(bob_endpoint, {bob_node}, alice_endpoint);
199
Artem Titove5cc85b2019-03-28 12:11:09 +0100200 EmulatedNetworkManagerInterface* nt1 =
201 network_manager.CreateEmulatedNetworkManagerInterface({alice_endpoint});
202 EmulatedNetworkManagerInterface* nt2 =
203 network_manager.CreateEmulatedNetworkManagerInterface({bob_endpoint});
Artem Titov0774bd92019-01-30 15:26:05 +0100204
Artem Titov806299e2019-04-12 12:17:19 +0200205 rtc::CopyOnWriteBuffer data("Hello");
Artem Titov0774bd92019-01-30 15:26:05 +0100206 for (uint64_t j = 0; j < 2; j++) {
Artem Titove5cc85b2019-03-28 12:11:09 +0100207 auto* s1 = nt1->network_thread()->socketserver()->CreateAsyncSocket(
208 AF_INET, SOCK_DGRAM);
209 auto* s2 = nt2->network_thread()->socketserver()->CreateAsyncSocket(
210 AF_INET, SOCK_DGRAM);
Artem Titov0774bd92019-01-30 15:26:05 +0100211
Artem Titov519d74a2019-05-17 12:01:00 +0200212 SocketReader r1(s1, nt1->network_thread());
213 SocketReader r2(s2, nt2->network_thread());
Artem Titov0774bd92019-01-30 15:26:05 +0100214
215 rtc::SocketAddress a1(alice_endpoint->GetPeerLocalAddress(), 0);
216 rtc::SocketAddress a2(bob_endpoint->GetPeerLocalAddress(), 0);
217
218 s1->Bind(a1);
219 s2->Bind(a2);
220
Artem Titove5cc85b2019-03-28 12:11:09 +0100221 s1->Connect(s2->GetLocalAddress());
222 s2->Connect(s1->GetLocalAddress());
Artem Titov0774bd92019-01-30 15:26:05 +0100223
Artem Titov0774bd92019-01-30 15:26:05 +0100224 for (uint64_t i = 0; i < 1000; i++) {
Artem Titov519d74a2019-05-17 12:01:00 +0200225 nt1->network_thread()->PostTask(
226 RTC_FROM_HERE, [&]() { s1->Send(data.data(), data.size()); });
227 nt2->network_thread()->PostTask(
228 RTC_FROM_HERE, [&]() { s2->Send(data.data(), data.size()); });
Artem Titov0774bd92019-01-30 15:26:05 +0100229 }
230
231 rtc::Event wait;
232 wait.Wait(1000);
Artem Titov806299e2019-04-12 12:17:19 +0200233 EXPECT_EQ(r1.ReceivedCount(), 1000);
234 EXPECT_EQ(r2.ReceivedCount(), 1000);
Artem Titov0774bd92019-01-30 15:26:05 +0100235
236 delete s1;
237 delete s2;
238 }
Artem Titov806299e2019-04-12 12:17:19 +0200239
240 int64_t single_packet_size = data.size();
241 std::atomic<int> received_stats_count{0};
242 nt1->GetStats([&](EmulatedNetworkStats st) {
243 EXPECT_EQ(st.packets_sent, 2000l);
244 EXPECT_EQ(st.bytes_sent.bytes(), single_packet_size * 2000l);
245 EXPECT_EQ(st.packets_received, 2000l);
246 EXPECT_EQ(st.bytes_received.bytes(), single_packet_size * 2000l);
247 EXPECT_EQ(st.packets_dropped, 0l);
248 EXPECT_EQ(st.bytes_dropped.bytes(), 0l);
249 received_stats_count++;
250 });
251 nt2->GetStats([&](EmulatedNetworkStats st) {
252 EXPECT_EQ(st.packets_sent, 2000l);
253 EXPECT_EQ(st.bytes_sent.bytes(), single_packet_size * 2000l);
254 EXPECT_EQ(st.packets_received, 2000l);
255 EXPECT_EQ(st.bytes_received.bytes(), single_packet_size * 2000l);
256 EXPECT_EQ(st.packets_dropped, 0l);
257 EXPECT_EQ(st.bytes_dropped.bytes(), 0l);
258 received_stats_count++;
259 });
260 ASSERT_EQ_WAIT(received_stats_count.load(), 2, kStatsWaitTimeoutMs);
261}
262
Artem Titova7683452019-05-15 12:26:38 +0200263TEST(NetworkEmulationManagerTest, ThroughputStats) {
Artem Titov806299e2019-04-12 12:17:19 +0200264 NetworkEmulationManagerImpl network_manager;
265
266 EmulatedNetworkNode* alice_node = network_manager.CreateEmulatedNode(
267 absl::make_unique<SimulatedNetwork>(BuiltInNetworkBehaviorConfig()));
268 EmulatedNetworkNode* bob_node = network_manager.CreateEmulatedNode(
269 absl::make_unique<SimulatedNetwork>(BuiltInNetworkBehaviorConfig()));
270 EmulatedEndpoint* alice_endpoint =
271 network_manager.CreateEndpoint(EmulatedEndpointConfig());
272 EmulatedEndpoint* bob_endpoint =
273 network_manager.CreateEndpoint(EmulatedEndpointConfig());
274 network_manager.CreateRoute(alice_endpoint, {alice_node}, bob_endpoint);
275 network_manager.CreateRoute(bob_endpoint, {bob_node}, alice_endpoint);
276
277 EmulatedNetworkManagerInterface* nt1 =
278 network_manager.CreateEmulatedNetworkManagerInterface({alice_endpoint});
279 EmulatedNetworkManagerInterface* nt2 =
280 network_manager.CreateEmulatedNetworkManagerInterface({bob_endpoint});
281
282 int64_t single_packet_size = 100;
283 rtc::CopyOnWriteBuffer data(single_packet_size);
284 auto* s1 = nt1->network_thread()->socketserver()->CreateAsyncSocket(
285 AF_INET, SOCK_DGRAM);
286 auto* s2 = nt2->network_thread()->socketserver()->CreateAsyncSocket(
287 AF_INET, SOCK_DGRAM);
288
Artem Titov519d74a2019-05-17 12:01:00 +0200289 SocketReader r1(s1, nt1->network_thread());
290 SocketReader r2(s2, nt2->network_thread());
Artem Titov806299e2019-04-12 12:17:19 +0200291
292 rtc::SocketAddress a1(alice_endpoint->GetPeerLocalAddress(), 0);
293 rtc::SocketAddress a2(bob_endpoint->GetPeerLocalAddress(), 0);
294
295 s1->Bind(a1);
296 s2->Bind(a2);
297
298 s1->Connect(s2->GetLocalAddress());
299 s2->Connect(s1->GetLocalAddress());
300
301 // Send 10 packets for 1
302 rtc::Event wait;
303 for (uint64_t i = 0; i < 11; i++) {
Artem Titov519d74a2019-05-17 12:01:00 +0200304 nt1->network_thread()->PostTask(
305 RTC_FROM_HERE, [&]() { s1->Send(data.data(), data.size()); });
306 nt2->network_thread()->PostTask(
307 RTC_FROM_HERE, [&]() { s2->Send(data.data(), data.size()); });
Artem Titov806299e2019-04-12 12:17:19 +0200308 wait.Wait(100);
309 }
Artem Titov806299e2019-04-12 12:17:19 +0200310
Artem Titov806299e2019-04-12 12:17:19 +0200311 std::atomic<int> received_stats_count{0};
312 nt1->GetStats([&](EmulatedNetworkStats st) {
313 EXPECT_EQ(st.packets_sent, 11l);
314 EXPECT_EQ(st.bytes_sent.bytes(), single_packet_size * 11l);
Artem Titova7683452019-05-15 12:26:38 +0200315 EXPECT_GE(st.last_packet_sent_time - st.first_packet_sent_time,
316 TimeDelta::seconds(1));
317 EXPECT_GT(st.AverageSendRate().bps(), 0);
Artem Titov806299e2019-04-12 12:17:19 +0200318 received_stats_count++;
319 });
320 ASSERT_EQ_WAIT(received_stats_count.load(), 1, kStatsWaitTimeoutMs);
Artem Titova7683452019-05-15 12:26:38 +0200321 EXPECT_EQ(r1.ReceivedCount(), 11);
322 EXPECT_EQ(r2.ReceivedCount(), 11);
Artem Titov519d74a2019-05-17 12:01:00 +0200323
324 delete s1;
325 delete s2;
Artem Titov0774bd92019-01-30 15:26:05 +0100326}
327
Artem Titovff393122019-04-05 11:19:52 +0200328// Testing that packets are delivered via all routes using a routing scheme as
329// follows:
330// * e1 -> n1 -> e2
331// * e2 -> n2 -> e1
332// * e1 -> n3 -> e3
333// * e3 -> n4 -> e1
334TEST_F(NetworkEmulationManagerThreeNodesRoutingTest,
335 PacketsAreDeliveredInBothWaysWhenConnectedToTwoPeers) {
336 SetupRouting([](EmulatedEndpoint* e1, EmulatedEndpoint* e2,
337 EmulatedEndpoint* e3, NetworkEmulationManager* emulation) {
338 auto* node1 = CreateEmulatedNodeWithDefaultBuiltInConfig(emulation);
339 auto* node2 = CreateEmulatedNodeWithDefaultBuiltInConfig(emulation);
340 auto* node3 = CreateEmulatedNodeWithDefaultBuiltInConfig(emulation);
341 auto* node4 = CreateEmulatedNodeWithDefaultBuiltInConfig(emulation);
342
343 emulation->CreateRoute(e1, {node1}, e2);
344 emulation->CreateRoute(e2, {node2}, e1);
345
346 emulation->CreateRoute(e1, {node3}, e3);
347 emulation->CreateRoute(e3, {node4}, e1);
348 });
349 SendPacketsAndValidateDelivery();
350}
351
352// Testing that packets are delivered via all routes using a routing scheme as
353// follows:
354// * e1 -> n1 -> e2
355// * e2 -> n2 -> e1
356// * e1 -> n1 -> e3
357// * e3 -> n4 -> e1
358TEST_F(NetworkEmulationManagerThreeNodesRoutingTest,
359 PacketsAreDeliveredInBothWaysWhenConnectedToTwoPeersOverSameSendLink) {
360 SetupRouting([](EmulatedEndpoint* e1, EmulatedEndpoint* e2,
361 EmulatedEndpoint* e3, NetworkEmulationManager* emulation) {
362 auto* node1 = CreateEmulatedNodeWithDefaultBuiltInConfig(emulation);
363 auto* node2 = CreateEmulatedNodeWithDefaultBuiltInConfig(emulation);
364 auto* node3 = CreateEmulatedNodeWithDefaultBuiltInConfig(emulation);
365
366 emulation->CreateRoute(e1, {node1}, e2);
367 emulation->CreateRoute(e2, {node2}, e1);
368
369 emulation->CreateRoute(e1, {node1}, e3);
370 emulation->CreateRoute(e3, {node3}, e1);
371 });
372 SendPacketsAndValidateDelivery();
373}
374
Artem Titov0774bd92019-01-30 15:26:05 +0100375} // namespace test
376} // namespace webrtc