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 <titovartem@webrtc.org>
Reviewed-by: Sebastian Jansson <srte@webrtc.org>
Cr-Commit-Position: refs/heads/master@{#26851}
diff --git a/test/pc/e2e/peer_connection_e2e_smoke_test.cc b/test/pc/e2e/peer_connection_e2e_smoke_test.cc
index e20ba52..54889a8 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 @@
EmulatedNetworkNode* bob_node = network_emulation_manager.CreateEmulatedNode(
absl::make_unique<SimulatedNetwork>(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 2d83936..1c9f249 100644
--- a/test/scenario/network/network_emulation_manager.cc
+++ b/test/scenario/network/network_emulation_manager.cc
@@ -22,12 +22,24 @@
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 @@
return out;
}
-EndpointNode* NetworkEmulationManager::CreateEndpoint(rtc::IPAddress ip) {
- auto node = absl::make_unique<EndpointNode>(next_node_id_++, ip, clock_);
+EndpointNode* NetworkEmulationManager::CreateEndpoint(EndpointConfig config) {
+ absl::optional<rtc::IPAddress> 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<EndpointNode>(next_node_id_++, *ip, clock_);
EndpointNode* out = node.get();
endpoints_.push_back(std::move(node));
return out;
@@ -98,7 +127,7 @@
TrafficRoute* NetworkEmulationManager::CreateTrafficRoute(
std::vector<EmulatedNetworkNode*> 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 @@
return out;
}
+absl::optional<rtc::IPAddress> 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 4718967..3f20443 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<rtc::IPAddress> ip;
+};
+
class NetworkEmulationManager {
public:
NetworkEmulationManager();
@@ -39,9 +55,7 @@
EmulatedNetworkNode* CreateEmulatedNode(
std::unique_ptr<NetworkBehaviorInterface> 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<EmulatedNetworkNode*> via_nodes,
@@ -63,6 +77,7 @@
private:
FakeNetworkSocketServer* CreateSocketServer(
std::vector<EndpointNode*> endpoints);
+ absl::optional<rtc::IPAddress> GetNextIPv4Address();
void ProcessNetworkPackets();
Timestamp Now() const;
@@ -71,6 +86,9 @@
RepeatingTaskHandle process_task_handle_;
+ uint32_t next_ip4_address_;
+ std::set<rtc::IPAddress> used_ip_addresses_;
+
// All objects can be added to the manager only when it is idle.
std::vector<std::unique_ptr<EndpointNode>> endpoints_;
std::vector<std::unique_ptr<EmulatedNetworkNode>> network_nodes_;
diff --git a/test/scenario/network/network_emulation_pc_unittest.cc b/test/scenario/network/network_emulation_pc_unittest.cc
index d8a2b8a..0f61e2c 100644
--- a/test/scenario/network/network_emulation_pc_unittest.cc
+++ b/test/scenario/network/network_emulation_pc_unittest.cc
@@ -108,10 +108,9 @@
absl::make_unique<SimulatedNetwork>(BuiltInNetworkBehaviorConfig()));
EmulatedNetworkNode* bob_node = network_manager.CreateEmulatedNode(
absl::make_unique<SimulatedNetwork>(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 @@
absl::make_unique<MockPeerConnectionObserver>();
std::unique_ptr<rtc::FakeNetworkManager> alice_network_manager =
absl::make_unique<rtc::FakeNetworkManager>();
- alice_network_manager->AddInterface(rtc::SocketAddress(alice_ip, 0));
+ alice_network_manager->AddInterface(
+ rtc::SocketAddress(alice_endpoint->GetPeerLocalAddress(), 0));
rtc::scoped_refptr<PeerConnectionFactoryInterface> bob_pcf;
rtc::scoped_refptr<PeerConnectionInterface> bob_pc;
@@ -135,7 +135,8 @@
absl::make_unique<MockPeerConnectionObserver>();
std::unique_ptr<rtc::FakeNetworkManager> bob_network_manager =
absl::make_unique<rtc::FakeNetworkManager>();
- bob_network_manager->AddInterface(rtc::SocketAddress(bob_ip, 0));
+ bob_network_manager->AddInterface(
+ rtc::SocketAddress(bob_endpoint->GetPeerLocalAddress(), 0));
signaling_thread->Invoke<void>(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 c55b412..09932f0 100644
--- a/test/scenario/network/network_emulation_unittest.cc
+++ b/test/scenario/network/network_emulation_unittest.cc
@@ -57,6 +57,32 @@
int received_count_ RTC_GUARDED_BY(lock_) = 0;
};
+TEST(NetworkEmulationManagerTest, GeneratedIpv4AddressDoesNotCollide) {
+ NetworkEmulationManager network_manager;
+ std::set<rtc::IPAddress> 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<rtc::IPAddress> 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 @@
EmulatedNetworkNode* bob_node = network_manager.CreateEmulatedNode(
absl::make_unique<SimulatedNetwork>(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);