From: Slawek Figiel Date: Thu, 6 Apr 2023 12:00:08 +0000 (+0200) Subject: [#2815] Implement del4 function X-Git-Tag: Kea-2.3.8~79 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=9fe50d3ea906d7e78abde56adf297cd27f671fad;p=thirdparty%2Fkea.git [#2815] Implement del4 function --- diff --git a/src/lib/dhcpsrv/cfg_hosts.cc b/src/lib/dhcpsrv/cfg_hosts.cc index 97fb3cb084..e1da797ff9 100644 --- a/src/lib/dhcpsrv/cfg_hosts.cc +++ b/src/lib/dhcpsrv/cfg_hosts.cc @@ -1131,13 +1131,33 @@ CfgHosts::delAll4(const SubnetID& subnet_id) { } bool -CfgHosts::del4(const SubnetID& /*subnet_id*/, - const Host::IdentifierType& /*identifier_type*/, - const uint8_t* /*identifier_begin*/, - const size_t /*identifier_len*/) { - /// @todo: Implement host removal - isc_throw(NotImplemented, "sorry, not implemented"); - return (false); +CfgHosts::del4(const SubnetID& subnet_id, + const Host::IdentifierType& identifier_type, + const uint8_t* identifier_begin, + const size_t identifier_len) { + HostContainerIndex0& idx = hosts_.get<0>(); + const auto t = boost::make_tuple(std::vector(identifier_begin, + identifier_begin + identifier_len), + identifier_type); + const auto& range = idx.equal_range(t); + size_t erased = 0; + for (auto key = range.first; key != range.second;) { + if ((*key)->getIPv4SubnetID() != subnet_id) { + ++key; + // Skip hosts from other subnets. + continue; + } + + key = idx.erase(key); + erased++; + } + + LOG_DEBUG(hosts_logger, HOSTS_DBG_TRACE, HOSTS_CFG_DEL4) + .arg(erased) + .arg(subnet_id) + .arg(Host::getIdentifierAsText(identifier_type, identifier_begin, identifier_len)); + + return (erased != 0); } size_t diff --git a/src/lib/dhcpsrv/hosts_messages.cc b/src/lib/dhcpsrv/hosts_messages.cc index 0eaec09048..c9d0b3f28c 100644 --- a/src/lib/dhcpsrv/hosts_messages.cc +++ b/src/lib/dhcpsrv/hosts_messages.cc @@ -14,6 +14,7 @@ extern const isc::log::MessageID HOSTS_CFG_ADD_HOST = "HOSTS_CFG_ADD_HOST"; extern const isc::log::MessageID HOSTS_CFG_CACHE_HOST_DATA_SOURCE = "HOSTS_CFG_CACHE_HOST_DATA_SOURCE"; extern const isc::log::MessageID HOSTS_CFG_CLOSE_HOST_DATA_SOURCE = "HOSTS_CFG_CLOSE_HOST_DATA_SOURCE"; extern const isc::log::MessageID HOSTS_CFG_DEL = "HOSTS_CFG_DEL"; +extern const isc::log::MessageID HOSTS_CFG_DEL4 = "HOSTS_CFG_DEL4"; extern const isc::log::MessageID HOSTS_CFG_DEL_ALL_SUBNET4 = "HOSTS_CFG_DEL_ALL_SUBNET4"; extern const isc::log::MessageID HOSTS_CFG_DEL_ALL_SUBNET6 = "HOSTS_CFG_DEL_ALL_SUBNET6"; extern const isc::log::MessageID HOSTS_CFG_GET_ALL = "HOSTS_CFG_GET_ALL"; @@ -87,6 +88,7 @@ const char* values[] = { "HOSTS_CFG_CACHE_HOST_DATA_SOURCE", "get host cache data source: %1", "HOSTS_CFG_CLOSE_HOST_DATA_SOURCE", "Closing host data source: %1", "HOSTS_CFG_DEL", "deleted %1 host(s) having %2 IPv6 reservation(s) for subnet id %3 and address %4", + "HOSTS_CFG_DEL4", "deleted %1 host(s) for subnet id %2 and identifier %3", "HOSTS_CFG_DEL_ALL_SUBNET4", "deleted all %1 host(s) for subnet id %2", "HOSTS_CFG_DEL_ALL_SUBNET6", "deleted all %1 host(s) having %2 IPv6 reservation(s) for subnet id %3", "HOSTS_CFG_GET_ALL", "get all hosts with reservations", diff --git a/src/lib/dhcpsrv/hosts_messages.h b/src/lib/dhcpsrv/hosts_messages.h index 937572c83a..d6ed062d92 100644 --- a/src/lib/dhcpsrv/hosts_messages.h +++ b/src/lib/dhcpsrv/hosts_messages.h @@ -15,6 +15,7 @@ extern const isc::log::MessageID HOSTS_CFG_ADD_HOST; extern const isc::log::MessageID HOSTS_CFG_CACHE_HOST_DATA_SOURCE; extern const isc::log::MessageID HOSTS_CFG_CLOSE_HOST_DATA_SOURCE; extern const isc::log::MessageID HOSTS_CFG_DEL; +extern const isc::log::MessageID HOSTS_CFG_DEL4; extern const isc::log::MessageID HOSTS_CFG_DEL_ALL_SUBNET4; extern const isc::log::MessageID HOSTS_CFG_DEL_ALL_SUBNET6; extern const isc::log::MessageID HOSTS_CFG_GET_ALL; diff --git a/src/lib/dhcpsrv/hosts_messages.mes b/src/lib/dhcpsrv/hosts_messages.mes index 232845deea..1bf3ddba7a 100644 --- a/src/lib/dhcpsrv/hosts_messages.mes +++ b/src/lib/dhcpsrv/hosts_messages.mes @@ -38,6 +38,12 @@ deleted. The second argument specifies how many reservations have been deleted. The third argument is the subnet identifier. The fourth argument is the IP address. +% HOSTS_CFG_DEL4 deleted %1 host(s) for subnet id %2 and identifier %3 +This debug message is issued when reservations are deleted for the specified +subnet and identifier. The first argument specifies how many hosts have been +deleted. The second argument is the subnet identifier. The third argument is +the identifier. + % HOSTS_CFG_DEL_ALL_SUBNET4 deleted all %1 host(s) for subnet id %2 This debug message is issued when all IPv4 reservations are deleted for the specified subnet. The first argument specifies how many reservations diff --git a/src/lib/dhcpsrv/tests/cfg_hosts_unittest.cc b/src/lib/dhcpsrv/tests/cfg_hosts_unittest.cc index efb170c490..65a2b5a65e 100644 --- a/src/lib/dhcpsrv/tests/cfg_hosts_unittest.cc +++ b/src/lib/dhcpsrv/tests/cfg_hosts_unittest.cc @@ -474,20 +474,20 @@ TEST_F(CfgHostsTest, deleteForIPv4) { } // Get all inserted hosts. - HostCollection hostsBySubnet = cfg.getAll4(subnet_id); - HostCollection hostsByAddress = cfg.getAll4(address); + HostCollection hosts_by_subnet = cfg.getAll4(subnet_id); + HostCollection hosts_by_address = cfg.getAll4(address); // Make sure the hosts and IP reservations were added. - ASSERT_EQ(host_count, hostsBySubnet.size()); - ASSERT_EQ(1, hostsByAddress.size()); + ASSERT_EQ(host_count, hosts_by_subnet.size()); + ASSERT_EQ(1, hosts_by_address.size()); // Delete one host. EXPECT_TRUE(cfg.del(subnet_id, address)); // Check if the host is actually deleted. - hostsBySubnet = cfg.getAll4(subnet_id); - hostsByAddress = cfg.getAll4(address); - EXPECT_EQ(host_count-1, hostsBySubnet.size()); - EXPECT_EQ(0, hostsByAddress.size()); + hosts_by_subnet = cfg.getAll4(subnet_id); + hosts_by_address = cfg.getAll4(address); + EXPECT_EQ(host_count-1, hosts_by_subnet.size()); + EXPECT_EQ(0, hosts_by_address.size()); } // This test checks that the IPv6 reservation for the specified subnet ID and @@ -511,20 +511,20 @@ TEST_F(CfgHostsTest, deleteForIPv6) { // Get all inserted hosts. - auto hostsBySubnetAndAddress = cfg.getAll6(subnet_id, address); - auto hostsBySubnet = cfg.getAll6(subnet_id); + auto hosts_by_subnet_and_address = cfg.getAll6(subnet_id, address); + auto hosts_by_subnet = cfg.getAll6(subnet_id); // Make sure the hosts and IP reservations were added. - ASSERT_EQ(1, hostsBySubnetAndAddress.size()); - ASSERT_EQ(host_count, hostsBySubnet.size()); + ASSERT_EQ(1, hosts_by_subnet_and_address.size()); + ASSERT_EQ(host_count, hosts_by_subnet.size()); // Delete one host. EXPECT_TRUE(cfg.del(subnet_id, address)); // Check if the host is actually deleted. - hostsBySubnetAndAddress = cfg.getAll6(subnet_id, address); - hostsBySubnet = cfg.getAll6(subnet_id); - EXPECT_EQ(0, hostsBySubnetAndAddress.size()); - EXPECT_EQ(host_count-1, hostsBySubnet.size()); + hosts_by_subnet_and_address = cfg.getAll6(subnet_id, address); + hosts_by_subnet = cfg.getAll6(subnet_id); + EXPECT_EQ(0, hosts_by_subnet_and_address.size()); + EXPECT_EQ(host_count-1, hosts_by_subnet.size()); } // This test checks that false is returned for deleting the IPv4 reservation @@ -545,6 +545,61 @@ TEST_F(CfgHostsTest, deleteForMissingIPv6) { EXPECT_FALSE(cfg.del(SubnetID(42), IOAddress(("2001:db8:1::1")))); } +// This test checks that the reservation for the specified IPv4 subnet and +// identifier can be deleted. +TEST_F(CfgHostsTest, del4) { + CfgHosts cfg; + + // Add hosts. + size_t host_count = 20; + size_t host_id = 5; + SubnetID subnet_id(42); + IOAddress address("10.0.0.1"); + + // Add half of the hosts with the same subnet ID but differ with DUID and + // address. + for (size_t i = 0; i < host_count / 2; i++) { + HostPtr host = HostPtr(new Host(duids_[i]->toText(), "duid", + subnet_id, SUBNET_ID_UNUSED, + increase(address, i))); + cfg.add(host); + } + // Add half of the hosts with the same subnet DUID and address but + // differ with address. + for (size_t i = 0; i < host_count / 2; i++) { + HostPtr host = HostPtr(new Host(duids_[host_id]->toText(), "duid", + SubnetID(subnet_id + i + 1), SUBNET_ID_UNUSED, + increase(address, host_id))); + cfg.add(host); + } + + + // Get all inserted hosts. + HostCollection hosts_by_subnet = cfg.getAll4(subnet_id); + HostCollection hosts_by_address = cfg.getAll4(increase(address, host_id)); + HostPtr host = cfg.get4(subnet_id, Host::IdentifierType::IDENT_DUID, + &duids_[host_id]->getDuid()[0], + duids_[host_id]->getDuid().size()); + // Make sure the hosts and IP reservations were added. + ASSERT_EQ(host_count / 2, hosts_by_subnet.size()); + ASSERT_EQ(host_count / 2 + 1, hosts_by_address.size()); + ASSERT_TRUE(host); + + // Delete one host. + EXPECT_TRUE(cfg.del4(subnet_id, Host::IdentifierType::IDENT_DUID, + &duids_[host_id]->getDuid()[0], duids_[host_id]->getDuid().size())); + + // Check if the host is actually deleted. + hosts_by_subnet = cfg.getAll4(subnet_id); + hosts_by_address = cfg.getAll4(increase(address, host_id)); + host = cfg.get4(subnet_id, Host::IdentifierType::IDENT_DUID, + &duids_[host_id]->getDuid()[0], + duids_[host_id]->getDuid().size()); + EXPECT_EQ((host_count / 2)-1, hosts_by_subnet.size()); + EXPECT_EQ(host_count / 2, hosts_by_address.size()); + EXPECT_FALSE(host); +} + // This test checks that all reservations for the specified IPv4 subnet can // be deleted. TEST_F(CfgHostsTest, deleteAll4) {