diff --git a/rtc_base/network.cc b/rtc_base/network.cc index 07b121bb3a..cebd31593b 100644 --- a/rtc_base/network.cc +++ b/rtc_base/network.cc @@ -329,8 +329,14 @@ void NetworkManagerBase::MergeNetworkList(const NetworkList& new_networks, Network* net = kv.second.net; auto existing = networks_map_.find(key); if (existing == networks_map_.end()) { - // This network is new. Place it in the network map. + if (interface_ids_by_name_.find(net->name()) == + interface_ids_by_name_.end()) { + interface_ids_by_name_.emplace(net->name(), + next_available_interface_id_++); + } + net->set_interface_id(interface_ids_by_name_[net->name()]); merged_list.push_back(net); + // This network is new. Place it in the network map. networks_map_[key] = net; net->set_id(next_available_network_id_++); // Also, we might have accumulated IPAddresses from the first diff --git a/rtc_base/network.h b/rtc_base/network.h index fb40166bf9..4d0a52f178 100644 --- a/rtc_base/network.h +++ b/rtc_base/network.h @@ -207,6 +207,11 @@ class RTC_EXPORT NetworkManagerBase : public NetworkManager { IPAddress default_local_ipv4_address_; IPAddress default_local_ipv6_address_; + + std::map interface_ids_by_name_; + // Use 16 bits to save the bandwidth consumption when sending the interface + // id. + uint16_t next_available_interface_id_ = 1; // We use 16 bits to save the bandwidth consumption when sending the network // id over the Internet. It is OK that the 16-bit integer overflows to get a // network id 0 because we only compare the network ids in the old and the new @@ -415,6 +420,16 @@ class RTC_EXPORT Network { uint16_t id() const { return id_; } void set_id(uint16_t id) { id_ = id; } + // A unique id assigned by the network manager to each network interface name. + // Networks on the same network interface (as identified by the interface + // name) have the same interface id. + uint16_t interface_id() const { return interface_id_; } + void set_interface_id(uint16_t interface_id) { + RTC_DCHECK(interface_id_ == 0); + RTC_DCHECK(interface_id != 0); + interface_id_ = interface_id; + } + int preference() const { return preference_; } void set_preference(int preference) { preference_ = preference; } @@ -447,6 +462,7 @@ class RTC_EXPORT Network { int preference_; bool active_ = true; uint16_t id_ = 0; + uint16_t interface_id_ = 0; friend class NetworkManager; }; diff --git a/rtc_base/network_unittest.cc b/rtc_base/network_unittest.cc index 41358646fe..539e390761 100644 --- a/rtc_base/network_unittest.cc +++ b/rtc_base/network_unittest.cc @@ -380,7 +380,9 @@ TEST_F(NetworkTest, TestBasicMergeNetworkList) { EXPECT_TRUE(SameNameAndPrefix(ipv4_network1, *list[0])); Network* net1 = list[0]; uint16_t net_id1 = net1->id(); + uint16_t net_if_id1 = net1->interface_id(); EXPECT_EQ(1, net_id1); + EXPECT_EQ(1, net_if_id1); list.clear(); // Replace ipv4_network1 with ipv4_network2. @@ -396,8 +398,10 @@ TEST_F(NetworkTest, TestBasicMergeNetworkList) { EXPECT_TRUE(SameNameAndPrefix(ipv4_network2, *list[0])); Network* net2 = list[0]; uint16_t net_id2 = net2->id(); + uint16_t net_if_id2 = net2->interface_id(); // Network id will increase. EXPECT_LT(net_id1, net_id2); + EXPECT_LT(net_if_id1, net_if_id2); list.clear(); // Add Network2 back. @@ -416,6 +420,8 @@ TEST_F(NetworkTest, TestBasicMergeNetworkList) { (net1 == list[1] && net2 == list[0])); EXPECT_TRUE((net_id1 == list[0]->id() && net_id2 == list[1]->id()) || (net_id1 == list[1]->id() && net_id2 == list[0]->id())); + EXPECT_TRUE((net_if_id1 == list[0]->id() && net_if_id2 == list[1]->id()) || + (net_if_id1 == list[1]->id() && net_if_id2 == list[0]->id())); list.clear(); // Call MergeNetworkList() again and verify that we don't get update @@ -433,11 +439,60 @@ TEST_F(NetworkTest, TestBasicMergeNetworkList) { EXPECT_EQ(2U, list.size()); EXPECT_TRUE((net1 == list[0] && net2 == list[1]) || (net1 == list[1] && net2 == list[0])); - EXPECT_TRUE((net_id1 == list[0]->id() && net_id2 == list[1]->id()) || - (net_id1 == list[1]->id() && net_id2 == list[0]->id())); + EXPECT_TRUE((net_if_id1 == list[0]->interface_id() && + net_if_id2 == list[1]->interface_id()) || + (net_if_id1 == list[1]->interface_id() && + net_if_id2 == list[0]->interface_id())); list.clear(); } +// Verify that one interface id is generated per network name. +TEST_F(NetworkTest, TestInterfaceId) { + Network ipv4_network1("test_eth0", "Test Network Adapter 1", + IPAddress(0x12345600U), 24); + Network ipv4_network2("test_eth0", "Test Network Adapter 2", + IPAddress(0xaabbcc00U), 24); + Network ipv4_network3("test_eth1", "Test Network Adapter 2", + IPAddress(0x00010000U), 16); + ipv4_network1.AddIP(IPAddress(0x12345678)); + ipv4_network2.AddIP(IPAddress(0xaabbcc01)); + ipv4_network3.AddIP(IPAddress(0x00010004)); + BasicNetworkManager manager; + + // Add list of networks. + { + NetworkManager::NetworkList list; + list.push_back(new Network(ipv4_network1)); + list.push_back(new Network(ipv4_network2)); + list.push_back(new Network(ipv4_network3)); + bool changed; + NetworkManager::Stats stats = MergeNetworkList(manager, list, &changed); + EXPECT_TRUE(changed); + EXPECT_EQ(stats.ipv6_network_count, 0); + EXPECT_EQ(stats.ipv4_network_count, 3); + } + + { + NetworkManager::NetworkList list; + manager.GetNetworks(&list); + EXPECT_EQ(list.size(), 3U); + + // There should be 2 interfaces + std::map networks_per_interface; + for (const auto& network : list) { + networks_per_interface[network->interface_id()]++; + } + EXPECT_EQ(networks_per_interface.size(), 2U); + for (const auto& network : list) { + if (network->name() == "test_eth0") { + EXPECT_EQ(networks_per_interface[network->interface_id()], 2); + } else { + EXPECT_EQ(networks_per_interface[network->interface_id()], 1); + } + } + } +} + // Sets up some test IPv6 networks and appends them to list. // Four networks are added - public and link local, for two interfaces. void SetupNetworks(NetworkManager::NetworkList* list) {