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}
This commit is contained in:
Artem Titov 2019-02-26 10:00:07 +01:00 committed by Commit Bot
parent 9595d1b221
commit 0bf4c29852
5 changed files with 106 additions and 17 deletions

View File

@ -73,9 +73,9 @@ TEST(PeerConnectionE2EQualityTestSmokeTest, RunWithEmulatedNetwork) {
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},

View File

@ -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<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 @@ void NetworkEmulationManager::ClearRoute(
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 @@ FakeNetworkSocketServer* NetworkEmulationManager::CreateSocketServer(
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_) {

View File

@ -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 @@ class NetworkEmulationManager {
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 @@ class NetworkEmulationManager {
private:
FakeNetworkSocketServer* CreateSocketServer(
std::vector<EndpointNode*> endpoints);
absl::optional<rtc::IPAddress> GetNextIPv4Address();
void ProcessNetworkPackets();
Timestamp Now() const;
@ -71,6 +86,9 @@ class NetworkEmulationManager {
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_;

View File

@ -108,10 +108,9 @@ TEST(NetworkEmulationManagerPCTest, Run) {
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 @@ TEST(NetworkEmulationManagerPCTest, Run) {
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 @@ TEST(NetworkEmulationManagerPCTest, Run) {
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(),

View File

@ -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<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 @@ TEST(NetworkEmulationManagerTest, Run) {
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);