From 0bf4c298529bc4afcd5f9821747aa8c708b3b576 Mon Sep 17 00:00:00 2001 From: Artem Titov Date: Tue, 26 Feb 2019 10:00:07 +0100 Subject: [PATCH] Add support of auto IP generation in network emulation manager. Bug: webrtc:10138 Change-Id: If50195ae44fb4d01fae1dd17a8d78a2a23b63b01 Reviewed-on: https://webrtc-review.googlesource.com/c/123191 Commit-Queue: Artem Titov Reviewed-by: Sebastian Jansson Cr-Commit-Position: refs/heads/master@{#26851} --- test/pc/e2e/peer_connection_e2e_smoke_test.cc | 4 +- .../network/network_emulation_manager.cc | 51 +++++++++++++++++-- .../network/network_emulation_manager.h | 24 +++++++-- .../network/network_emulation_pc_unittest.cc | 13 ++--- .../network/network_emulation_unittest.cc | 31 +++++++++-- 5 files changed, 106 insertions(+), 17 deletions(-) diff --git a/test/pc/e2e/peer_connection_e2e_smoke_test.cc b/test/pc/e2e/peer_connection_e2e_smoke_test.cc index e20ba52e05..54889a8a28 100644 --- a/test/pc/e2e/peer_connection_e2e_smoke_test.cc +++ b/test/pc/e2e/peer_connection_e2e_smoke_test.cc @@ -73,9 +73,9 @@ TEST(PeerConnectionE2EQualityTestSmokeTest, RunWithEmulatedNetwork) { EmulatedNetworkNode* bob_node = network_emulation_manager.CreateEmulatedNode( absl::make_unique(BuiltInNetworkBehaviorConfig())); EndpointNode* alice_endpoint = - network_emulation_manager.CreateEndpoint(rtc::IPAddress(1)); + network_emulation_manager.CreateEndpoint(EndpointConfig()); EndpointNode* bob_endpoint = - network_emulation_manager.CreateEndpoint(rtc::IPAddress(2)); + network_emulation_manager.CreateEndpoint(EndpointConfig()); network_emulation_manager.CreateRoute(alice_endpoint, {alice_node}, bob_endpoint); network_emulation_manager.CreateRoute(bob_endpoint, {bob_node}, diff --git a/test/scenario/network/network_emulation_manager.cc b/test/scenario/network/network_emulation_manager.cc index 2d83936481..1c9f249875 100644 --- a/test/scenario/network/network_emulation_manager.cc +++ b/test/scenario/network/network_emulation_manager.cc @@ -22,12 +22,24 @@ namespace test { namespace { constexpr int64_t kPacketProcessingIntervalMs = 1; +// uint32_t representation of 192.168.0.0 address +constexpr uint32_t kMinIPv4Address = 0xC0A80000; +// uint32_t representation of 192.168.255.255 address +constexpr uint32_t kMaxIPv4Address = 0xC0A8FFFF; } // namespace +EndpointConfig::EndpointConfig() = default; +EndpointConfig::~EndpointConfig() = default; +EndpointConfig::EndpointConfig(EndpointConfig&) = default; +EndpointConfig& EndpointConfig::operator=(EndpointConfig&) = default; +EndpointConfig::EndpointConfig(EndpointConfig&&) = default; +EndpointConfig& EndpointConfig::operator=(EndpointConfig&&) = default; + NetworkEmulationManager::NetworkEmulationManager() : clock_(Clock::GetRealTimeClock()), next_node_id_(1), + next_ip4_address_(kMinIPv4Address), task_queue_("network_emulation_manager") { process_task_handle_ = RepeatingTaskHandle::Start(&task_queue_, [this] { ProcessNetworkPackets(); @@ -55,8 +67,25 @@ EmulatedNetworkNode* NetworkEmulationManager::CreateEmulatedNode( return out; } -EndpointNode* NetworkEmulationManager::CreateEndpoint(rtc::IPAddress ip) { - auto node = absl::make_unique(next_node_id_++, ip, clock_); +EndpointNode* NetworkEmulationManager::CreateEndpoint(EndpointConfig config) { + absl::optional ip = config.ip; + if (!ip) { + switch (config.generated_ip_family) { + case EndpointConfig::IpAddressFamily::kIpv4: + ip = GetNextIPv4Address(); + RTC_CHECK(ip) << "All auto generated IPv4 addresses exhausted"; + break; + case EndpointConfig::IpAddressFamily::kIpv6: + ip = GetNextIPv4Address(); + RTC_CHECK(ip) << "All auto generated IPv6 addresses exhausted"; + ip = ip->AsIPv6Address(); + break; + } + } + + bool res = used_ip_addresses_.insert(*ip).second; + RTC_CHECK(res) << "IP=" << ip->ToString() << " already in use"; + auto node = absl::make_unique(next_node_id_++, *ip, clock_); EndpointNode* out = node.get(); endpoints_.push_back(std::move(node)); return out; @@ -98,7 +127,7 @@ void NetworkEmulationManager::ClearRoute( TrafficRoute* NetworkEmulationManager::CreateTrafficRoute( std::vector via_nodes) { RTC_CHECK(!via_nodes.empty()); - EndpointNode* endpoint = CreateEndpoint(rtc::IPAddress(next_node_id_++)); + EndpointNode* endpoint = CreateEndpoint(EndpointConfig()); // Setup a route via specified nodes. EmulatedNetworkNode* cur_node = via_nodes[0]; @@ -171,6 +200,22 @@ FakeNetworkSocketServer* NetworkEmulationManager::CreateSocketServer( return out; } +absl::optional NetworkEmulationManager::GetNextIPv4Address() { + uint32_t addresses_count = kMaxIPv4Address - kMinIPv4Address; + for (uint32_t i = 0; i < addresses_count; i++) { + rtc::IPAddress ip(next_ip4_address_); + if (next_ip4_address_ == kMaxIPv4Address) { + next_ip4_address_ = kMinIPv4Address; + } else { + next_ip4_address_++; + } + if (used_ip_addresses_.find(ip) == used_ip_addresses_.end()) { + return ip; + } + } + return absl::nullopt; +} + void NetworkEmulationManager::ProcessNetworkPackets() { Timestamp current_time = Now(); for (auto& traffic : random_cross_traffics_) { diff --git a/test/scenario/network/network_emulation_manager.h b/test/scenario/network/network_emulation_manager.h index 47189676c6..3f204434f3 100644 --- a/test/scenario/network/network_emulation_manager.h +++ b/test/scenario/network/network_emulation_manager.h @@ -31,6 +31,22 @@ namespace webrtc { namespace test { +struct EndpointConfig { + enum IpAddressFamily { kIpv4, kIpv6 }; + + EndpointConfig(); + ~EndpointConfig(); + EndpointConfig(EndpointConfig&); + EndpointConfig& operator=(EndpointConfig&); + EndpointConfig(EndpointConfig&&); + EndpointConfig& operator=(EndpointConfig&&); + + IpAddressFamily generated_ip_family = IpAddressFamily::kIpv4; + // If specified will be used as IP address for endpoint node. Should be unique + // among all created nodes. + absl::optional ip; +}; + class NetworkEmulationManager { public: NetworkEmulationManager(); @@ -39,9 +55,7 @@ class NetworkEmulationManager { EmulatedNetworkNode* CreateEmulatedNode( std::unique_ptr network_behavior); - // TODO(titovartem) add method without IP address, where manager - // will provided some unique generated address. - EndpointNode* CreateEndpoint(rtc::IPAddress ip); + EndpointNode* CreateEndpoint(EndpointConfig config); void CreateRoute(EndpointNode* from, std::vector via_nodes, @@ -63,6 +77,7 @@ class NetworkEmulationManager { private: FakeNetworkSocketServer* CreateSocketServer( std::vector endpoints); + absl::optional GetNextIPv4Address(); void ProcessNetworkPackets(); Timestamp Now() const; @@ -71,6 +86,9 @@ class NetworkEmulationManager { RepeatingTaskHandle process_task_handle_; + uint32_t next_ip4_address_; + std::set used_ip_addresses_; + // All objects can be added to the manager only when it is idle. std::vector> endpoints_; std::vector> network_nodes_; diff --git a/test/scenario/network/network_emulation_pc_unittest.cc b/test/scenario/network/network_emulation_pc_unittest.cc index d8a2b8a937..0f61e2ca5e 100644 --- a/test/scenario/network/network_emulation_pc_unittest.cc +++ b/test/scenario/network/network_emulation_pc_unittest.cc @@ -108,10 +108,9 @@ TEST(NetworkEmulationManagerPCTest, Run) { absl::make_unique(BuiltInNetworkBehaviorConfig())); EmulatedNetworkNode* bob_node = network_manager.CreateEmulatedNode( absl::make_unique(BuiltInNetworkBehaviorConfig())); - rtc::IPAddress alice_ip(1); - EndpointNode* alice_endpoint = network_manager.CreateEndpoint(alice_ip); - rtc::IPAddress bob_ip(2); - EndpointNode* bob_endpoint = network_manager.CreateEndpoint(bob_ip); + EndpointNode* alice_endpoint = + network_manager.CreateEndpoint(EndpointConfig()); + EndpointNode* bob_endpoint = network_manager.CreateEndpoint(EndpointConfig()); network_manager.CreateRoute(alice_endpoint, {alice_node}, bob_endpoint); network_manager.CreateRoute(bob_endpoint, {bob_node}, alice_endpoint); @@ -127,7 +126,8 @@ TEST(NetworkEmulationManagerPCTest, Run) { absl::make_unique(); std::unique_ptr alice_network_manager = absl::make_unique(); - alice_network_manager->AddInterface(rtc::SocketAddress(alice_ip, 0)); + alice_network_manager->AddInterface( + rtc::SocketAddress(alice_endpoint->GetPeerLocalAddress(), 0)); rtc::scoped_refptr bob_pcf; rtc::scoped_refptr bob_pc; @@ -135,7 +135,8 @@ TEST(NetworkEmulationManagerPCTest, Run) { absl::make_unique(); std::unique_ptr bob_network_manager = absl::make_unique(); - bob_network_manager->AddInterface(rtc::SocketAddress(bob_ip, 0)); + bob_network_manager->AddInterface( + rtc::SocketAddress(bob_endpoint->GetPeerLocalAddress(), 0)); signaling_thread->Invoke(RTC_FROM_HERE, [&]() { alice_pcf = CreatePeerConnectionFactory(signaling_thread.get(), diff --git a/test/scenario/network/network_emulation_unittest.cc b/test/scenario/network/network_emulation_unittest.cc index c55b412f00..09932f0456 100644 --- a/test/scenario/network/network_emulation_unittest.cc +++ b/test/scenario/network/network_emulation_unittest.cc @@ -57,6 +57,32 @@ class SocketReader : public sigslot::has_slots<> { int received_count_ RTC_GUARDED_BY(lock_) = 0; }; +TEST(NetworkEmulationManagerTest, GeneratedIpv4AddressDoesNotCollide) { + NetworkEmulationManager network_manager; + std::set ips; + EndpointConfig config; + config.generated_ip_family = EndpointConfig::IpAddressFamily::kIpv4; + for (int i = 0; i < 1000; i++) { + EndpointNode* endpoint = network_manager.CreateEndpoint(config); + ASSERT_EQ(endpoint->GetPeerLocalAddress().family(), AF_INET); + bool result = ips.insert(endpoint->GetPeerLocalAddress()).second; + ASSERT_TRUE(result); + } +} + +TEST(NetworkEmulationManagerTest, GeneratedIpv6AddressDoesNotCollide) { + NetworkEmulationManager network_manager; + std::set ips; + EndpointConfig config; + config.generated_ip_family = EndpointConfig::IpAddressFamily::kIpv6; + for (int i = 0; i < 1000; i++) { + EndpointNode* endpoint = network_manager.CreateEndpoint(config); + ASSERT_EQ(endpoint->GetPeerLocalAddress().family(), AF_INET6); + bool result = ips.insert(endpoint->GetPeerLocalAddress()).second; + ASSERT_TRUE(result); + } +} + TEST(NetworkEmulationManagerTest, Run) { NetworkEmulationManager network_manager; @@ -65,9 +91,8 @@ TEST(NetworkEmulationManagerTest, Run) { EmulatedNetworkNode* bob_node = network_manager.CreateEmulatedNode( absl::make_unique(BuiltInNetworkBehaviorConfig())); EndpointNode* alice_endpoint = - network_manager.CreateEndpoint(rtc::IPAddress(1)); - EndpointNode* bob_endpoint = - network_manager.CreateEndpoint(rtc::IPAddress(2)); + network_manager.CreateEndpoint(EndpointConfig()); + EndpointNode* bob_endpoint = network_manager.CreateEndpoint(EndpointConfig()); network_manager.CreateRoute(alice_endpoint, {alice_node}, bob_endpoint); network_manager.CreateRoute(bob_endpoint, {bob_node}, alice_endpoint);