mirror of
https://gitlab.isc.org/isc-projects/kea
synced 2025-08-31 05:55:28 +00:00
[#3375] Made cfg_host MT safe
This commit is contained in:
@@ -13,6 +13,7 @@
|
||||
#include <dhcpsrv/cfgmgr.h>
|
||||
#include <exceptions/exceptions.h>
|
||||
#include <util/encode/encode.h>
|
||||
#include <util/multi_threading_mgr.h>
|
||||
#include <boost/foreach.hpp>
|
||||
#include <ostream>
|
||||
#include <string>
|
||||
@@ -20,11 +21,15 @@
|
||||
|
||||
using namespace isc::asiolink;
|
||||
using namespace isc::data;
|
||||
using namespace isc::util;
|
||||
using namespace std;
|
||||
|
||||
namespace isc {
|
||||
namespace dhcp {
|
||||
|
||||
CfgHosts::CfgHosts() : mutex_(new mutex()) {
|
||||
}
|
||||
|
||||
ConstHostCollection
|
||||
CfgHosts::getAll(const Host::IdentifierType& identifier_type,
|
||||
const uint8_t* identifier_begin,
|
||||
@@ -32,6 +37,7 @@ CfgHosts::getAll(const Host::IdentifierType& identifier_type,
|
||||
// Do not issue logging message here because it will be logged by
|
||||
// the getAllInternal method.
|
||||
ConstHostCollection collection;
|
||||
MultiThreadingLock lock(*mutex_);
|
||||
getAllInternal<ConstHostCollection>(identifier_type, identifier_begin,
|
||||
identifier_len, collection);
|
||||
return (collection);
|
||||
@@ -43,6 +49,7 @@ CfgHosts::getAll(const Host::IdentifierType& identifier_type,
|
||||
// Do not issue logging message here because it will be logged by
|
||||
// the getAllInternal method.
|
||||
HostCollection collection;
|
||||
MultiThreadingLock lock(*mutex_);
|
||||
getAllInternal<HostCollection>(identifier_type, identifier_begin,
|
||||
identifier_len, collection);
|
||||
return (collection);
|
||||
@@ -53,6 +60,7 @@ CfgHosts::getAll4(const SubnetID& subnet_id) const {
|
||||
// Do not issue logging message here because it will be logged by
|
||||
// the getAllInternal4 method.
|
||||
ConstHostCollection collection;
|
||||
MultiThreadingLock lock(*mutex_);
|
||||
getAllInternal4<ConstHostCollection>(subnet_id, collection);
|
||||
return (collection);
|
||||
}
|
||||
@@ -62,6 +70,7 @@ CfgHosts::getAll4(const SubnetID& subnet_id) {
|
||||
// Do not issue logging message here because it will be logged by
|
||||
// the getAllInternal4 method.
|
||||
HostCollection collection;
|
||||
MultiThreadingLock lock(*mutex_);
|
||||
getAllInternal4<HostCollection>(subnet_id, collection);
|
||||
return (collection);
|
||||
}
|
||||
@@ -71,6 +80,7 @@ CfgHosts::getAll6(const SubnetID& subnet_id) const {
|
||||
// Do not issue logging message here because it will be logged by
|
||||
// the getAllInternal6 method.
|
||||
ConstHostCollection collection;
|
||||
MultiThreadingLock lock(*mutex_);
|
||||
getAllInternal6<ConstHostCollection>(subnet_id, collection);
|
||||
return (collection);
|
||||
}
|
||||
@@ -80,6 +90,7 @@ CfgHosts::getAll6(const SubnetID& subnet_id) {
|
||||
// Do not issue logging message here because it will be logged by
|
||||
// the getAllInternal6 method.
|
||||
HostCollection collection;
|
||||
MultiThreadingLock lock(*mutex_);
|
||||
getAllInternal6<HostCollection>(subnet_id, collection);
|
||||
return (collection);
|
||||
}
|
||||
@@ -89,6 +100,7 @@ CfgHosts::getAllbyHostname(const std::string& hostname) const {
|
||||
// Do not issue logging message here because it will be logged by
|
||||
// the getAllbyHostnameInternal method.
|
||||
ConstHostCollection collection;
|
||||
MultiThreadingLock lock(*mutex_);
|
||||
getAllbyHostnameInternal<ConstHostCollection>(hostname, collection);
|
||||
return (collection);
|
||||
}
|
||||
@@ -98,6 +110,7 @@ CfgHosts::getAllbyHostname(const std::string& hostname) {
|
||||
// Do not issue logging message here because it will be logged by
|
||||
// the getAllbyHostnameInternal method.
|
||||
HostCollection collection;
|
||||
MultiThreadingLock lock(*mutex_);
|
||||
getAllbyHostnameInternal<HostCollection>(hostname, collection);
|
||||
return (collection);
|
||||
}
|
||||
@@ -108,6 +121,7 @@ CfgHosts::getAllbyHostname4(const std::string& hostname,
|
||||
// Do not issue logging message here because it will be logged by
|
||||
// the getAllbyHostnameInternal4 method.
|
||||
ConstHostCollection collection;
|
||||
MultiThreadingLock lock(*mutex_);
|
||||
getAllbyHostnameInternal4<ConstHostCollection>(hostname, subnet_id, collection);
|
||||
return (collection);
|
||||
}
|
||||
@@ -118,6 +132,7 @@ CfgHosts::getAllbyHostname4(const std::string& hostname,
|
||||
// Do not issue logging message here because it will be logged by
|
||||
// the getAllbyHostnameInternal4 method.
|
||||
HostCollection collection;
|
||||
MultiThreadingLock lock(*mutex_);
|
||||
getAllbyHostnameInternal4<HostCollection>(hostname, subnet_id, collection);
|
||||
return (collection);
|
||||
}
|
||||
@@ -128,6 +143,7 @@ CfgHosts::getAllbyHostname6(const std::string& hostname,
|
||||
// Do not issue logging message here because it will be logged by
|
||||
// the getAllbyHostnameInternal6 method.
|
||||
ConstHostCollection collection;
|
||||
MultiThreadingLock lock(*mutex_);
|
||||
getAllbyHostnameInternal6<ConstHostCollection>(hostname, subnet_id, collection);
|
||||
return (collection);
|
||||
}
|
||||
@@ -138,6 +154,7 @@ CfgHosts::getAllbyHostname6(const std::string& hostname,
|
||||
// Do not issue logging message here because it will be logged by
|
||||
// the getAllbyHostnameInternal6 method.
|
||||
HostCollection collection;
|
||||
MultiThreadingLock lock(*mutex_);
|
||||
getAllbyHostnameInternal6<HostCollection>(hostname, subnet_id, collection);
|
||||
return (collection);
|
||||
}
|
||||
@@ -150,6 +167,7 @@ CfgHosts::getPage4(const SubnetID& subnet_id,
|
||||
// Do not issue logging message here because it will be logged by
|
||||
// the getPageInternal4 method.
|
||||
ConstHostCollection collection;
|
||||
MultiThreadingLock lock(*mutex_);
|
||||
getPageInternal4<ConstHostCollection>(subnet_id,
|
||||
lower_host_id,
|
||||
page_size,
|
||||
@@ -165,6 +183,7 @@ CfgHosts::getPage4(const SubnetID& subnet_id,
|
||||
// Do not issue logging message here because it will be logged by
|
||||
// the getPageInternal4 method.
|
||||
HostCollection collection;
|
||||
MultiThreadingLock lock(*mutex_);
|
||||
getPageInternal4<HostCollection>(subnet_id,
|
||||
lower_host_id,
|
||||
page_size,
|
||||
@@ -180,6 +199,7 @@ CfgHosts::getPage6(const SubnetID& subnet_id,
|
||||
// Do not issue logging message here because it will be logged by
|
||||
// the getPageInternal6 method.
|
||||
ConstHostCollection collection;
|
||||
MultiThreadingLock lock(*mutex_);
|
||||
getPageInternal6<ConstHostCollection>(subnet_id,
|
||||
lower_host_id,
|
||||
page_size,
|
||||
@@ -195,6 +215,7 @@ CfgHosts::getPage6(const SubnetID& subnet_id,
|
||||
// Do not issue logging message here because it will be logged by
|
||||
// the getPageInternal6 method.
|
||||
HostCollection collection;
|
||||
MultiThreadingLock lock(*mutex_);
|
||||
getPageInternal6<HostCollection>(subnet_id,
|
||||
lower_host_id,
|
||||
page_size,
|
||||
@@ -209,6 +230,7 @@ CfgHosts::getPage4(size_t& /*source_index*/,
|
||||
// Do not issue logging message here because it will be logged by
|
||||
// the getPageInternal method.
|
||||
ConstHostCollection collection;
|
||||
MultiThreadingLock lock(*mutex_);
|
||||
getPageInternal<ConstHostCollection>(lower_host_id,
|
||||
page_size,
|
||||
collection);
|
||||
@@ -222,6 +244,7 @@ CfgHosts::getPage4(size_t& /*source_index*/,
|
||||
// Do not issue logging message here because it will be logged by
|
||||
// the getPageInternal method.
|
||||
HostCollection collection;
|
||||
MultiThreadingLock lock(*mutex_);
|
||||
getPageInternal<HostCollection>(lower_host_id,
|
||||
page_size,
|
||||
collection);
|
||||
@@ -235,6 +258,7 @@ CfgHosts::getPage6(size_t& /*source_index*/,
|
||||
// Do not issue logging message here because it will be logged by
|
||||
// the getPageInternal method.
|
||||
ConstHostCollection collection;
|
||||
MultiThreadingLock lock(*mutex_);
|
||||
getPageInternal<ConstHostCollection>(lower_host_id,
|
||||
page_size,
|
||||
collection);
|
||||
@@ -248,6 +272,7 @@ CfgHosts::getPage6(size_t& /*source_index*/,
|
||||
// Do not issue logging message here because it will be logged by
|
||||
// the getPageInternal method.
|
||||
HostCollection collection;
|
||||
MultiThreadingLock lock(*mutex_);
|
||||
getPageInternal<HostCollection>(lower_host_id,
|
||||
page_size,
|
||||
collection);
|
||||
@@ -259,6 +284,7 @@ CfgHosts::getAll4(const IOAddress& address) const {
|
||||
// Do not issue logging message here because it will be logged by
|
||||
// the getAllInternal4 method.
|
||||
ConstHostCollection collection;
|
||||
MultiThreadingLock lock(*mutex_);
|
||||
getAllInternal4<ConstHostCollection>(address, collection);
|
||||
return (collection);
|
||||
}
|
||||
@@ -268,6 +294,7 @@ CfgHosts::getAll4(const IOAddress& address) {
|
||||
// Do not issue logging message here because it will be logged by
|
||||
// the getAllInternal4 method.
|
||||
HostCollection collection;
|
||||
MultiThreadingLock lock(*mutex_);
|
||||
getAllInternal4<HostCollection>(address, collection);
|
||||
return (collection);
|
||||
}
|
||||
@@ -277,6 +304,7 @@ CfgHosts::getAll6(const IOAddress& address) const {
|
||||
// Do not issue logging message here because it will be logged by
|
||||
// the getAllInternal6 method.
|
||||
ConstHostCollection collection;
|
||||
MultiThreadingLock lock(*mutex_);
|
||||
getAllInternal6<ConstHostCollection>(address, collection);
|
||||
return (collection);
|
||||
}
|
||||
@@ -286,6 +314,7 @@ CfgHosts::getAll6(const IOAddress& address) {
|
||||
// Do not issue logging message here because it will be logged by
|
||||
// the getAllInternal6 method.
|
||||
HostCollection collection;
|
||||
MultiThreadingLock lock(*mutex_);
|
||||
getAllInternal6<HostCollection>(address, collection);
|
||||
return (collection);
|
||||
}
|
||||
@@ -632,6 +661,42 @@ CfgHosts::getAllInternal4(const IOAddress& address, Storage& storage) const {
|
||||
.arg(storage.size());
|
||||
}
|
||||
|
||||
ConstHostCollection
|
||||
CfgHosts::getAllInternal4(const SubnetID& subnet_id,
|
||||
const IOAddress& address) const {
|
||||
LOG_DEBUG(hosts_logger, HOSTS_DBG_TRACE, HOSTS_CFG_GET_ALL_SUBNET_ID_ADDRESS4)
|
||||
.arg(subnet_id)
|
||||
.arg(address.toText());
|
||||
|
||||
// Must not specify address other than IPv4.
|
||||
if (!address.isV4()) {
|
||||
isc_throw(BadHostAddress, "must specify an IPv4 address when searching"
|
||||
" for a host, specified address was " << address);
|
||||
}
|
||||
// Search for the Host using the reserved IPv4 address as a key.
|
||||
ConstHostCollection hosts;
|
||||
const HostContainerIndex1& idx = hosts_.get<1>();
|
||||
HostContainerIndex1Range r = idx.equal_range(address);
|
||||
// Append each Host object to the storage.
|
||||
BOOST_FOREACH(auto const& host, r) {
|
||||
if (host->getIPv4SubnetID() == subnet_id) {
|
||||
LOG_DEBUG(hosts_logger, HOSTS_DBG_TRACE_DETAIL_DATA,
|
||||
HOSTS_CFG_GET_ALL_SUBNET_ID_ADDRESS4_HOST)
|
||||
.arg(subnet_id)
|
||||
.arg(address.toText())
|
||||
.arg(host->toText());
|
||||
hosts.push_back(host);
|
||||
}
|
||||
}
|
||||
|
||||
LOG_DEBUG(hosts_logger, HOSTS_DBG_RESULTS,
|
||||
HOSTS_CFG_GET_ALL_SUBNET_ID_ADDRESS4_COUNT)
|
||||
.arg(subnet_id)
|
||||
.arg(address.toText())
|
||||
.arg(hosts.size());
|
||||
return (hosts);
|
||||
}
|
||||
|
||||
template<typename Storage>
|
||||
void
|
||||
CfgHosts::getAllInternal6(const IOAddress& address, Storage& storage) const {
|
||||
@@ -665,6 +730,7 @@ CfgHosts::get4(const SubnetID& subnet_id,
|
||||
const Host::IdentifierType& identifier_type,
|
||||
const uint8_t* identifier_begin,
|
||||
const size_t identifier_len) const {
|
||||
MultiThreadingLock lock(*mutex_);
|
||||
return (getHostInternal(subnet_id, false, identifier_type, identifier_begin,
|
||||
identifier_len));
|
||||
}
|
||||
@@ -674,6 +740,7 @@ CfgHosts::get4(const SubnetID& subnet_id,
|
||||
const Host::IdentifierType& identifier_type,
|
||||
const uint8_t* identifier_begin,
|
||||
const size_t identifier_len) {
|
||||
MultiThreadingLock lock(*mutex_);
|
||||
return (getHostInternal(subnet_id, false, identifier_type, identifier_begin,
|
||||
identifier_len));
|
||||
}
|
||||
@@ -683,46 +750,29 @@ CfgHosts::get4(const SubnetID& subnet_id, const IOAddress& address) const {
|
||||
LOG_DEBUG(hosts_logger, HOSTS_DBG_TRACE, HOSTS_CFG_GET_ONE_SUBNET_ID_ADDRESS4)
|
||||
.arg(subnet_id).arg(address.toText());
|
||||
|
||||
ConstHostCollection hosts = getAll4(address);
|
||||
for (auto const& host : hosts) {
|
||||
if (host->getIPv4SubnetID() == subnet_id) {
|
||||
LOG_DEBUG(hosts_logger, HOSTS_DBG_RESULTS,
|
||||
HOSTS_CFG_GET_ONE_SUBNET_ID_ADDRESS4_HOST)
|
||||
.arg(subnet_id)
|
||||
.arg(address.toText())
|
||||
.arg(host->toText());
|
||||
return (host);
|
||||
}
|
||||
ConstHostCollection hosts = getAllInternal4(subnet_id, address);
|
||||
if (hosts.empty()) {
|
||||
LOG_DEBUG(hosts_logger, HOSTS_DBG_RESULTS,
|
||||
HOSTS_CFG_GET_ONE_SUBNET_ID_ADDRESS4_NULL)
|
||||
.arg(subnet_id)
|
||||
.arg(address.toText());
|
||||
return (ConstHostPtr());
|
||||
} else {
|
||||
ConstHostPtr host = *hosts.begin();
|
||||
LOG_DEBUG(hosts_logger, HOSTS_DBG_RESULTS,
|
||||
HOSTS_CFG_GET_ONE_SUBNET_ID_ADDRESS4_HOST)
|
||||
.arg(subnet_id)
|
||||
.arg(address.toText())
|
||||
.arg(host->toText());
|
||||
return (host);
|
||||
}
|
||||
|
||||
LOG_DEBUG(hosts_logger, HOSTS_DBG_RESULTS, HOSTS_CFG_GET_ONE_SUBNET_ID_ADDRESS4_NULL)
|
||||
.arg(subnet_id).arg(address.toText());
|
||||
return (ConstHostPtr());
|
||||
}
|
||||
|
||||
ConstHostCollection
|
||||
CfgHosts::getAll4(const SubnetID& subnet_id,
|
||||
const asiolink::IOAddress& address) const {
|
||||
LOG_DEBUG(hosts_logger, HOSTS_DBG_TRACE, HOSTS_CFG_GET_ALL_SUBNET_ID_ADDRESS4)
|
||||
.arg(subnet_id).arg(address.toText());
|
||||
|
||||
ConstHostCollection hosts;
|
||||
for (auto const& host : getAll4(address)) {
|
||||
if (host->getIPv4SubnetID() == subnet_id) {
|
||||
LOG_DEBUG(hosts_logger, HOSTS_DBG_TRACE_DETAIL_DATA,
|
||||
HOSTS_CFG_GET_ALL_SUBNET_ID_ADDRESS4_HOST)
|
||||
.arg(subnet_id)
|
||||
.arg(address.toText())
|
||||
.arg(host->toText());
|
||||
hosts.push_back(host);
|
||||
}
|
||||
}
|
||||
LOG_DEBUG(hosts_logger, HOSTS_DBG_RESULTS, HOSTS_CFG_GET_ALL_SUBNET_ID_ADDRESS4_COUNT)
|
||||
.arg(subnet_id)
|
||||
.arg(address.toText())
|
||||
.arg(hosts.size());
|
||||
|
||||
return (hosts);
|
||||
MultiThreadingLock lock(*mutex_);
|
||||
return (getAllInternal4(subnet_id, address));
|
||||
}
|
||||
|
||||
ConstHostPtr
|
||||
@@ -730,6 +780,7 @@ CfgHosts::get6(const SubnetID& subnet_id,
|
||||
const Host::IdentifierType& identifier_type,
|
||||
const uint8_t* identifier_begin,
|
||||
const size_t identifier_len) const {
|
||||
MultiThreadingLock lock(*mutex_);
|
||||
return (getHostInternal(subnet_id, true, identifier_type, identifier_begin,
|
||||
identifier_len));
|
||||
}
|
||||
@@ -739,17 +790,20 @@ CfgHosts::get6(const SubnetID& subnet_id,
|
||||
const Host::IdentifierType& identifier_type,
|
||||
const uint8_t* identifier_begin,
|
||||
const size_t identifier_len) {
|
||||
MultiThreadingLock lock(*mutex_);
|
||||
return (getHostInternal(subnet_id, true, identifier_type, identifier_begin,
|
||||
identifier_len));
|
||||
}
|
||||
|
||||
ConstHostPtr
|
||||
CfgHosts::get6(const IOAddress& prefix, const uint8_t prefix_len) const {
|
||||
MultiThreadingLock lock(*mutex_);
|
||||
return (getHostInternal6<ConstHostPtr>(prefix, prefix_len));
|
||||
}
|
||||
|
||||
HostPtr
|
||||
CfgHosts::get6(const IOAddress& prefix, const uint8_t prefix_len) {
|
||||
MultiThreadingLock lock(*mutex_);
|
||||
return (getHostInternal6<HostPtr>(prefix, prefix_len));
|
||||
}
|
||||
|
||||
@@ -757,6 +811,7 @@ ConstHostPtr
|
||||
CfgHosts::get6(const SubnetID& subnet_id,
|
||||
const asiolink::IOAddress& address) const {
|
||||
// Do not log here because getHostInternal6 logs.
|
||||
MultiThreadingLock lock(*mutex_);
|
||||
return (getHostInternal6<ConstHostPtr, ConstHostCollection>(subnet_id, address));
|
||||
}
|
||||
|
||||
@@ -764,6 +819,7 @@ HostPtr
|
||||
CfgHosts::get6(const SubnetID& subnet_id,
|
||||
const asiolink::IOAddress& address) {
|
||||
// Do not log here because getHostInternal6 logs.
|
||||
MultiThreadingLock lock(*mutex_);
|
||||
return (getHostInternal6<HostPtr, HostCollection>(subnet_id, address));
|
||||
}
|
||||
|
||||
@@ -771,6 +827,7 @@ ConstHostCollection
|
||||
CfgHosts::getAll6(const SubnetID& subnet_id,
|
||||
const asiolink::IOAddress& address) const {
|
||||
ConstHostCollection hosts;
|
||||
MultiThreadingLock lock(*mutex_);
|
||||
getAllInternal6(subnet_id, address, hosts);
|
||||
return (hosts);
|
||||
}
|
||||
@@ -963,6 +1020,8 @@ CfgHosts::add(const HostPtr& host) {
|
||||
" 0 when adding new host reservation");
|
||||
}
|
||||
|
||||
MultiThreadingLock lock(*mutex_);
|
||||
|
||||
add4(host);
|
||||
|
||||
add6(host);
|
||||
@@ -977,16 +1036,16 @@ CfgHosts::add4(const HostPtr& host) {
|
||||
// Check for duplicates for the specified IPv4 subnet.
|
||||
if (host->getIPv4SubnetID() != SUBNET_ID_UNUSED) {
|
||||
if (hwaddr && !hwaddr->hwaddr_.empty() &&
|
||||
get4(host->getIPv4SubnetID(), Host::IDENT_HWADDR,
|
||||
&hwaddr->hwaddr_[0], hwaddr->hwaddr_.size())) {
|
||||
getHostInternal(host->getIPv4SubnetID(), false, Host::IDENT_HWADDR,
|
||||
&hwaddr->hwaddr_[0], hwaddr->hwaddr_.size())) {
|
||||
isc_throw(DuplicateHost, "failed to add new host using the HW"
|
||||
<< " address '" << hwaddr->toText(false)
|
||||
<< "' to the IPv4 subnet id '" << host->getIPv4SubnetID()
|
||||
<< "' as this host has already been added");
|
||||
}
|
||||
if (duid && !duid->getDuid().empty() &&
|
||||
get4(host->getIPv4SubnetID(), Host::IDENT_DUID,
|
||||
&duid->getDuid()[0], duid->getDuid().size())) {
|
||||
getHostInternal(host->getIPv4SubnetID(), false, Host::IDENT_DUID,
|
||||
&duid->getDuid()[0], duid->getDuid().size())) {
|
||||
isc_throw(DuplicateHost, "failed to add new host using the "
|
||||
<< "DUID '" << duid->toText()
|
||||
<< "' to the IPv4 subnet id '" << host->getIPv4SubnetID()
|
||||
@@ -995,16 +1054,16 @@ CfgHosts::add4(const HostPtr& host) {
|
||||
// Check for duplicates for the specified IPv6 subnet.
|
||||
} else if (host->getIPv6SubnetID() != SUBNET_ID_UNUSED) {
|
||||
if (duid && !duid->getDuid().empty() &&
|
||||
get6(host->getIPv6SubnetID(), Host::IDENT_DUID,
|
||||
&duid->getDuid()[0], duid->getDuid().size())) {
|
||||
getHostInternal(host->getIPv6SubnetID(), true, Host::IDENT_DUID,
|
||||
&duid->getDuid()[0], duid->getDuid().size())) {
|
||||
isc_throw(DuplicateHost, "failed to add new host using the "
|
||||
<< "DUID '" << duid->toText()
|
||||
<< "' to the IPv6 subnet id '" << host->getIPv6SubnetID()
|
||||
<< "' as this host has already been added");
|
||||
}
|
||||
if (hwaddr && !hwaddr->hwaddr_.empty() &&
|
||||
get6(host->getIPv6SubnetID(), Host::IDENT_HWADDR,
|
||||
&hwaddr->hwaddr_[0], hwaddr->hwaddr_.size())) {
|
||||
getHostInternal(host->getIPv6SubnetID(), true, Host::IDENT_HWADDR,
|
||||
&hwaddr->hwaddr_[0], hwaddr->hwaddr_.size())) {
|
||||
isc_throw(DuplicateHost, "failed to add new host using the HW"
|
||||
<< " address '" << hwaddr->toText(false)
|
||||
<< "' to the IPv6 subnet id '" << host->getIPv6SubnetID()
|
||||
@@ -1015,7 +1074,8 @@ CfgHosts::add4(const HostPtr& host) {
|
||||
// Check if the address is already reserved for the specified IPv4 subnet.
|
||||
if (ip_reservations_unique_ && !host->getIPv4Reservation().isV4Zero() &&
|
||||
(host->getIPv4SubnetID() != SUBNET_ID_UNUSED) &&
|
||||
get4(host->getIPv4SubnetID(), host->getIPv4Reservation())) {
|
||||
!getAllInternal4(host->getIPv4SubnetID(),
|
||||
host->getIPv4Reservation()).empty()) {
|
||||
isc_throw(ReservedAddress, "failed to add new host using the HW"
|
||||
" address '" << (hwaddr ? hwaddr->toText(false) : "(null)")
|
||||
<< " and DUID '" << (duid ? duid->toText() : "(null)")
|
||||
@@ -1027,8 +1087,8 @@ CfgHosts::add4(const HostPtr& host) {
|
||||
// Check if the (identifier type, identifier) tuple is already used.
|
||||
const std::vector<uint8_t>& id = host->getIdentifier();
|
||||
if ((host->getIPv4SubnetID() != SUBNET_ID_UNUSED) && !id.empty()) {
|
||||
if (get4(host->getIPv4SubnetID(), host->getIdentifierType(), &id[0],
|
||||
id.size())) {
|
||||
if (getHostInternal(host->getIPv4SubnetID(), false,
|
||||
host->getIdentifierType(), &id[0], id.size())) {
|
||||
isc_throw(DuplicateHost, "failed to add duplicate IPv4 host using identifier: "
|
||||
<< Host::getIdentifierAsText(host->getIdentifierType(),
|
||||
&id[0], id.size()));
|
||||
@@ -1066,7 +1126,8 @@ CfgHosts::add6(const HostPtr& host) {
|
||||
|
||||
if (ip_reservations_unique_) {
|
||||
// If there's an entry for this (subnet-id, address), reject it.
|
||||
if (get6(host->getIPv6SubnetID(), it.second.getPrefix())) {
|
||||
if (getHostInternal6<ConstHostPtr, ConstHostCollection>
|
||||
(host->getIPv6SubnetID(), it.second.getPrefix())) {
|
||||
isc_throw(DuplicateHost, "failed to add address reservation for "
|
||||
<< "host using the HW address '"
|
||||
<< (hwaddr ? hwaddr->toText(false) : "(null)")
|
||||
@@ -1084,10 +1145,16 @@ bool
|
||||
CfgHosts::del(const SubnetID& subnet_id, const asiolink::IOAddress& addr) {
|
||||
size_t erased_hosts = 0;
|
||||
size_t erased_addresses = 0;
|
||||
MultiThreadingLock lock(*mutex_);
|
||||
if (addr.isV4()) {
|
||||
HostContainerIndex4& idx = hosts_.get<4>();
|
||||
ConstHostCollection hosts;
|
||||
getAllInternal4<ConstHostCollection>(addr, hosts);
|
||||
// Delete IPv4 reservation and host.
|
||||
for (auto const& host : getAll4(subnet_id, addr)) {
|
||||
for (auto const& host : hosts) {
|
||||
if (host->getIPv4SubnetID() != subnet_id) {
|
||||
continue;
|
||||
}
|
||||
erased_hosts += idx.erase(host->getHostId());
|
||||
}
|
||||
erased_addresses = erased_hosts;
|
||||
@@ -1116,6 +1183,7 @@ CfgHosts::del(const SubnetID& subnet_id, const asiolink::IOAddress& addr) {
|
||||
size_t
|
||||
CfgHosts::delAll4(const SubnetID& subnet_id) {
|
||||
HostContainerIndex2& idx = hosts_.get<2>();
|
||||
MultiThreadingLock lock(*mutex_);
|
||||
size_t erased = idx.erase(subnet_id);
|
||||
|
||||
LOG_DEBUG(hosts_logger, HOSTS_DBG_TRACE, HOSTS_CFG_DEL_ALL_SUBNET4)
|
||||
@@ -1131,6 +1199,7 @@ CfgHosts::del4(const SubnetID& subnet_id,
|
||||
const uint8_t* identifier_begin,
|
||||
const size_t identifier_len) {
|
||||
HostContainerIndex0& idx = hosts_.get<0>();
|
||||
MultiThreadingLock lock(*mutex_);
|
||||
auto const t = boost::make_tuple(std::vector<uint8_t>(identifier_begin,
|
||||
identifier_begin + identifier_len),
|
||||
identifier_type);
|
||||
@@ -1159,6 +1228,7 @@ size_t
|
||||
CfgHosts::delAll6(const SubnetID& subnet_id) {
|
||||
// Delete IPv6 reservations.
|
||||
HostContainer6Index2& idx6 = hosts6_.get<2>();
|
||||
MultiThreadingLock lock(*mutex_);
|
||||
size_t erased_addresses = idx6.erase(subnet_id);
|
||||
|
||||
// Delete hosts.
|
||||
@@ -1184,6 +1254,7 @@ CfgHosts::del6(const SubnetID& subnet_id,
|
||||
auto const t = boost::make_tuple(std::vector<uint8_t>(identifier_begin,
|
||||
identifier_begin + identifier_len),
|
||||
identifier_type);
|
||||
MultiThreadingLock lock(*mutex_);
|
||||
auto const& range = idx.equal_range(t);
|
||||
size_t erased_hosts = 0;
|
||||
size_t erased_reservations = 0;
|
||||
@@ -1213,6 +1284,7 @@ CfgHosts::del6(const SubnetID& subnet_id,
|
||||
|
||||
bool
|
||||
CfgHosts::setIPReservationsUnique(const bool unique) {
|
||||
MultiThreadingLock lock(*mutex_);
|
||||
ip_reservations_unique_ = unique;
|
||||
return (true);
|
||||
}
|
||||
@@ -1236,6 +1308,7 @@ CfgHosts::toElement4() const {
|
||||
CfgHostsList result;
|
||||
// Iterate using arbitrary the index 0
|
||||
const HostContainerIndex0& idx = hosts_.get<0>();
|
||||
MultiThreadingLock lock(*mutex_);
|
||||
for (auto const& host : idx) {
|
||||
|
||||
// Convert host to element representation
|
||||
@@ -1253,6 +1326,7 @@ CfgHosts::toElement6() const {
|
||||
CfgHostsList result;
|
||||
// Iterate using arbitrary the index 0
|
||||
const HostContainerIndex0& idx = hosts_.get<0>();
|
||||
MultiThreadingLock lock(*mutex_);
|
||||
for (auto const& host : idx) {
|
||||
|
||||
// Convert host to Element representation
|
||||
|
@@ -1,4 +1,4 @@
|
||||
// Copyright (C) 2014-2023 Internet Systems Consortium, Inc. ("ISC")
|
||||
// Copyright (C) 2014-2024 Internet Systems Consortium, Inc. ("ISC")
|
||||
//
|
||||
// This Source Code Form is subject to the terms of the Mozilla Public
|
||||
// License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
@@ -14,7 +14,10 @@
|
||||
#include <dhcpsrv/host_container.h>
|
||||
#include <dhcpsrv/subnet_id.h>
|
||||
#include <dhcpsrv/writable_host_data_source.h>
|
||||
#include <boost/scoped_ptr.hpp>
|
||||
#include <boost/shared_ptr.hpp>
|
||||
#include <set>
|
||||
#include <mutex>
|
||||
#include <vector>
|
||||
|
||||
namespace isc {
|
||||
@@ -38,6 +41,9 @@ class CfgHosts : public BaseHostDataSource, public WritableHostDataSource,
|
||||
public isc::data::CfgToElement {
|
||||
public:
|
||||
|
||||
/// @brief Constructor.
|
||||
CfgHosts();
|
||||
|
||||
/// @brief Destructor.
|
||||
virtual ~CfgHosts() { }
|
||||
|
||||
@@ -536,13 +542,13 @@ public:
|
||||
/// has already been added to the IPv4 or IPv6 subnet.
|
||||
virtual void add(const HostPtr& host);
|
||||
|
||||
/// @brief Attempts to delete a hosts by address.
|
||||
/// @brief Attempts to delete hosts by address.
|
||||
///
|
||||
/// This method supports both v4 and v6.
|
||||
/// @todo: Not implemented.
|
||||
///
|
||||
/// @param subnet_id subnet identifier.
|
||||
/// @param addr specified address.
|
||||
/// @return true if deletion was successful, false otherwise.
|
||||
virtual bool del(const SubnetID& subnet_id, const asiolink::IOAddress& addr);
|
||||
|
||||
/// @brief Attempts to delete all hosts for a given IPv4 subnet.
|
||||
@@ -555,7 +561,6 @@ public:
|
||||
/// @brief Attempts to delete a host by (subnet4-id, identifier, identifier-type)
|
||||
///
|
||||
/// This method supports v4 only.
|
||||
/// @todo: Not implemented.
|
||||
///
|
||||
/// @param subnet_id IPv4 Subnet identifier.
|
||||
/// @param identifier_type Identifier type.
|
||||
@@ -577,7 +582,6 @@ public:
|
||||
/// @brief Attempts to delete a host by (subnet6-id, identifier, identifier-type)
|
||||
///
|
||||
/// This method supports v6 only.
|
||||
/// @todo: Not implemented.
|
||||
///
|
||||
/// @param subnet_id IPv6 Subnet identifier.
|
||||
/// @param identifier_type Identifier type.
|
||||
@@ -635,6 +639,9 @@ public:
|
||||
|
||||
private:
|
||||
|
||||
/// @note: all private/internal methods suppose the caller takes
|
||||
/// the mutex at the exception of toElement[46].
|
||||
|
||||
/// @brief Returns @c Host objects for the specific identifier and type.
|
||||
///
|
||||
/// This private method is called by the @c CfgHosts::getAll
|
||||
@@ -812,6 +819,19 @@ private:
|
||||
void getAllInternal6(const asiolink::IOAddress& address,
|
||||
Storage& storage) const;
|
||||
|
||||
/// @brief Returns @c Host objects for the specified (Subnet-id,IPv6 address) tuple.
|
||||
///
|
||||
/// This private method is called by the @c CfgHosts::getAll4 methods
|
||||
/// to retrieve the @c Host for which the specified IPv4 address is
|
||||
/// reserved and is in specified subnet-id. The retrieved objects are
|
||||
/// appended to the returned container.
|
||||
///
|
||||
/// @param subnet_id Subnet identifier.
|
||||
/// @param address IPv4 address.
|
||||
/// @return Collection of const @c Host objects.
|
||||
ConstHostCollection
|
||||
getAllInternal4(const SubnetID& subnet_id,
|
||||
const asiolink::IOAddress& address) const;
|
||||
|
||||
/// @brief Returns @c Host objects for the specified (Subnet-id,IPv6 address) tuple.
|
||||
///
|
||||
@@ -924,6 +944,9 @@ private:
|
||||
/// may be non-unique.
|
||||
bool ip_reservations_unique_ = true;
|
||||
|
||||
/// @brief The mutex used to protect host containers.
|
||||
const boost::scoped_ptr<std::mutex> mutex_;
|
||||
|
||||
/// @brief Unparse a configuration object (DHCPv4 reservations)
|
||||
///
|
||||
/// @return a pointer to unparsed configuration
|
||||
|
@@ -14,6 +14,7 @@
|
||||
#include <dhcpsrv/host.h>
|
||||
#include <dhcpsrv/cfgmgr.h>
|
||||
#include <testutils/gtest_utils.h>
|
||||
#include <testutils/multi_threading_utils.h>
|
||||
|
||||
#include <gtest/gtest.h>
|
||||
|
||||
@@ -21,8 +22,10 @@
|
||||
#include <set>
|
||||
|
||||
using namespace isc;
|
||||
using namespace isc::dhcp;
|
||||
using namespace isc::asiolink;
|
||||
using namespace isc::dhcp;
|
||||
using namespace isc::test;
|
||||
using namespace isc::util;
|
||||
|
||||
namespace {
|
||||
|
||||
@@ -55,6 +58,40 @@ public:
|
||||
/// @param address Address to be increased.
|
||||
IOAddress increase(const IOAddress& address, const uint8_t num) const;
|
||||
|
||||
/// @brief test methods.
|
||||
void testGetAllNonRepeatingHosts();
|
||||
void testGetAllRepeatingHosts();
|
||||
void testGetAll4BySubnet();
|
||||
void testGetAll6BySubnet();
|
||||
void testGetAll6ByAddress();
|
||||
void testGetPage4();
|
||||
void testGetPage6();
|
||||
void testGetPage4All();
|
||||
void testGetPage6All();
|
||||
void testGetAll4ByAddress();
|
||||
void testDeleteForIPv4();
|
||||
void testDeleteForIPv6();
|
||||
void testDel4();
|
||||
void testDel6();
|
||||
void testDeleteAll4();
|
||||
void testGet4();
|
||||
void testUnparsed4();
|
||||
void testGet6();
|
||||
void testDeleteAll6();
|
||||
void testUnparse6();
|
||||
void testGet6ByAddr();
|
||||
void testGet6MultipleAddrs();
|
||||
void testAdd4AlreadyReserved();
|
||||
void testAllow4AlreadyReserved();
|
||||
void testAdd6Invalid2Hosts();
|
||||
void testAllowAddress6AlreadyReserved();
|
||||
void testAllowPrefix6AlreadyReserved();
|
||||
void testDuplicatesSubnet4HWAddr();
|
||||
void testDuplicatesSubnet4DUID();
|
||||
void testDuplicatesSubnet6HWAddr();
|
||||
void testDuplicatesSubnet6DUID();
|
||||
void testUpdate();
|
||||
|
||||
/// @brief Collection of HW address objects allocated for unit tests.
|
||||
std::vector<HWAddrPtr> hwaddrs_;
|
||||
/// @brief Collection of DUIDs allocated for unit tests.
|
||||
@@ -95,10 +132,12 @@ CfgHostsTest::CfgHostsTest() {
|
||||
IOAddress addrb(addrb_template + i);
|
||||
addressesb_.push_back(addrb);
|
||||
}
|
||||
MultiThreadingMgr::instance().setMode(false);
|
||||
}
|
||||
|
||||
CfgHostsTest::~CfgHostsTest() {
|
||||
CfgMgr::instance().setFamily(AF_INET);
|
||||
MultiThreadingMgr::instance().setMode(false);
|
||||
}
|
||||
|
||||
IOAddress
|
||||
@@ -113,7 +152,8 @@ CfgHostsTest::increase(const IOAddress& address, const uint8_t num) const {
|
||||
|
||||
// This test checks that hosts with unique HW addresses and DUIDs can be
|
||||
// retrieved from the host configuration.
|
||||
TEST_F(CfgHostsTest, getAllNonRepeatingHosts) {
|
||||
void
|
||||
CfgHostsTest::testGetAllNonRepeatingHosts() {
|
||||
CfgHosts cfg;
|
||||
// Add 25 hosts identified by HW address and 25 hosts identified by
|
||||
// DUID. They are added to different subnets.
|
||||
@@ -161,9 +201,19 @@ TEST_F(CfgHostsTest, getAllNonRepeatingHosts) {
|
||||
}
|
||||
}
|
||||
|
||||
TEST_F(CfgHostsTest, getAllNonRepeatingHosts) {
|
||||
testGetAllNonRepeatingHosts();
|
||||
}
|
||||
|
||||
TEST_F(CfgHostsTest, getAllNonRepeatingHostsMultiThreading) {
|
||||
MultiThreadingTest mt(true);
|
||||
testGetAllNonRepeatingHosts();
|
||||
}
|
||||
|
||||
// This test verifies that the host can be added to multiple subnets and
|
||||
// that the getAll message retrieves all instances of the host.
|
||||
TEST_F(CfgHostsTest, getAllRepeatingHosts) {
|
||||
void
|
||||
CfgHostsTest::testGetAllRepeatingHosts() {
|
||||
CfgHosts cfg;
|
||||
// Add hosts.
|
||||
for (unsigned i = 0; i < 25; ++i) {
|
||||
@@ -219,9 +269,19 @@ TEST_F(CfgHostsTest, getAllRepeatingHosts) {
|
||||
}
|
||||
}
|
||||
|
||||
TEST_F(CfgHostsTest, getAllRepeatingHosts) {
|
||||
testGetAllRepeatingHosts();
|
||||
}
|
||||
|
||||
TEST_F(CfgHostsTest, getAllRepeatingHostsMultiThreading) {
|
||||
MultiThreadingTest mt(true);
|
||||
testGetAllRepeatingHosts();
|
||||
}
|
||||
|
||||
// This test checks that hosts in the same subnet can be retrieved from
|
||||
// the host configuration.
|
||||
TEST_F(CfgHostsTest, getAll4BySubnet) {
|
||||
void
|
||||
CfgHostsTest::testGetAll4BySubnet() {
|
||||
CfgHosts cfg;
|
||||
// Add 25 hosts identified by HW address in the same subnet.
|
||||
for (unsigned i = 0; i < 25; ++i) {
|
||||
@@ -245,9 +305,19 @@ TEST_F(CfgHostsTest, getAll4BySubnet) {
|
||||
}
|
||||
}
|
||||
|
||||
TEST_F(CfgHostsTest, getAll4BySubnet) {
|
||||
testGetAll4BySubnet();
|
||||
}
|
||||
|
||||
TEST_F(CfgHostsTest, getAll4BySubnetMultiThreading) {
|
||||
MultiThreadingTest mt(true);
|
||||
testGetAll4BySubnet();
|
||||
}
|
||||
|
||||
// This test checks that hosts in the same subnet can be retrieved from
|
||||
// the host configuration.
|
||||
TEST_F(CfgHostsTest, getAll6BySubnet) {
|
||||
void
|
||||
CfgHostsTest::testGetAll6BySubnet() {
|
||||
CfgHosts cfg;
|
||||
// Add 25 hosts identified by DUID in the same subnet.
|
||||
for (unsigned i = 0; i < 25; ++i) {
|
||||
@@ -277,9 +347,19 @@ TEST_F(CfgHostsTest, getAll6BySubnet) {
|
||||
}
|
||||
}
|
||||
|
||||
TEST_F(CfgHostsTest, getAll6BySubnet) {
|
||||
testGetAll6BySubnet();
|
||||
}
|
||||
|
||||
TEST_F(CfgHostsTest, getAll6BySubnetMultiThreading) {
|
||||
MultiThreadingTest mt(true);
|
||||
testGetAll6BySubnet();
|
||||
}
|
||||
|
||||
// This test checks that hosts with the same reserved address can be retrieved
|
||||
// from the host configuration.
|
||||
TEST_F(CfgHostsTest, getAll6ByAddress) {
|
||||
void
|
||||
CfgHostsTest::testGetAll6ByAddress() {
|
||||
CfgHosts cfg;
|
||||
// Add 25 hosts identified by DUID in the same subnet.
|
||||
for (unsigned i = 0; i < 25; ++i) {
|
||||
@@ -305,9 +385,19 @@ TEST_F(CfgHostsTest, getAll6ByAddress) {
|
||||
}
|
||||
}
|
||||
|
||||
TEST_F(CfgHostsTest, getAll6ByAddress) {
|
||||
testGetAll6ByAddress();
|
||||
}
|
||||
|
||||
TEST_F(CfgHostsTest, getAll6ByAddressMultiThreading) {
|
||||
MultiThreadingTest mt(true);
|
||||
testGetAll6ByAddress();
|
||||
}
|
||||
|
||||
// This test checks that hosts in the same subnet can be retrieved from
|
||||
// the host configuration by pages.
|
||||
TEST_F(CfgHostsTest, getPage4) {
|
||||
void
|
||||
CfgHostsTest::testGetPage4() {
|
||||
CfgHosts cfg;
|
||||
// Add 25 hosts identified by DUID in the same subnet.
|
||||
for (unsigned i = 0; i < 25; ++i) {
|
||||
@@ -342,9 +432,19 @@ TEST_F(CfgHostsTest, getPage4) {
|
||||
EXPECT_EQ(0, page.size());
|
||||
}
|
||||
|
||||
TEST_F(CfgHostsTest, getPage4) {
|
||||
testGetPage4();
|
||||
}
|
||||
|
||||
TEST_F(CfgHostsTest, getPage4MultiThreading) {
|
||||
MultiThreadingTest mt(true);
|
||||
testGetPage4();
|
||||
}
|
||||
|
||||
// This test checks that hosts in the same subnet can be retrieved from
|
||||
// the host configuration by pages.
|
||||
TEST_F(CfgHostsTest, getPage6) {
|
||||
void
|
||||
CfgHostsTest::testGetPage6() {
|
||||
CfgHosts cfg;
|
||||
// Add 25 hosts identified by HW address in the same subnet.
|
||||
for (unsigned i = 0; i < 25; ++i) {
|
||||
@@ -384,9 +484,19 @@ TEST_F(CfgHostsTest, getPage6) {
|
||||
EXPECT_EQ(0, page.size());
|
||||
}
|
||||
|
||||
TEST_F(CfgHostsTest, getPage6) {
|
||||
testGetPage6();
|
||||
}
|
||||
|
||||
TEST_F(CfgHostsTest, getPage6MultiThreading) {
|
||||
MultiThreadingTest mt(true);
|
||||
testGetPage6();
|
||||
}
|
||||
|
||||
// This test checks that all hosts can be retrieved from the host
|
||||
// configuration by pages.
|
||||
TEST_F(CfgHostsTest, getPage4All) {
|
||||
void
|
||||
CfgHostsTest::testGetPage4All() {
|
||||
CfgHosts cfg;
|
||||
// Add 25 hosts identified by DUID.
|
||||
for (unsigned i = 0; i < 25; ++i) {
|
||||
@@ -417,9 +527,19 @@ TEST_F(CfgHostsTest, getPage4All) {
|
||||
EXPECT_EQ(0, page.size());
|
||||
}
|
||||
|
||||
TEST_F(CfgHostsTest, getPage4All) {
|
||||
testGetPage4All();
|
||||
}
|
||||
|
||||
TEST_F(CfgHostsTest, getPage4AllMultiThreading) {
|
||||
MultiThreadingTest mt(true);
|
||||
testGetPage4All();
|
||||
}
|
||||
|
||||
// This test checks that all hosts can be retrieved from the host
|
||||
// configuration by pages.
|
||||
TEST_F(CfgHostsTest, getPage6All) {
|
||||
void
|
||||
CfgHostsTest::testGetPage6All() {
|
||||
CfgHosts cfg;
|
||||
// Add 25 hosts identified by HW address.
|
||||
for (unsigned i = 0; i < 25; ++i) {
|
||||
@@ -455,9 +575,19 @@ TEST_F(CfgHostsTest, getPage6All) {
|
||||
EXPECT_EQ(0, page.size());
|
||||
}
|
||||
|
||||
TEST_F(CfgHostsTest, getPage6All) {
|
||||
testGetPage6All();
|
||||
}
|
||||
|
||||
TEST_F(CfgHostsTest, getPage6AllMultiThreading) {
|
||||
MultiThreadingTest mt(true);
|
||||
testGetPage6All();
|
||||
}
|
||||
|
||||
// This test checks that all reservations for the specified IPv4 address can
|
||||
// be retrieved.
|
||||
TEST_F(CfgHostsTest, getAll4ByAddress) {
|
||||
void
|
||||
CfgHostsTest::testGetAll4ByAddress() {
|
||||
CfgHosts cfg;
|
||||
// Add hosts.
|
||||
for (unsigned i = 0; i < 25; ++i) {
|
||||
@@ -483,9 +613,19 @@ TEST_F(CfgHostsTest, getAll4ByAddress) {
|
||||
EXPECT_EQ(25, *subnet_ids.rbegin());
|
||||
}
|
||||
|
||||
TEST_F(CfgHostsTest, getAll4ByAddress) {
|
||||
testGetAll4ByAddress();
|
||||
}
|
||||
|
||||
TEST_F(CfgHostsTest, getAll4ByAddressMultiThreading) {
|
||||
MultiThreadingTest mt(true);
|
||||
testGetAll4ByAddress();
|
||||
}
|
||||
|
||||
// This test checks that the IPv4 reservation for the specified IPv4 address can
|
||||
// be deleted.
|
||||
TEST_F(CfgHostsTest, deleteForIPv4) {
|
||||
void
|
||||
CfgHostsTest::testDeleteForIPv4() {
|
||||
CfgHosts cfg;
|
||||
// Add hosts.
|
||||
IOAddress address("10.0.0.42");
|
||||
@@ -517,9 +657,19 @@ TEST_F(CfgHostsTest, deleteForIPv4) {
|
||||
EXPECT_EQ(0, hosts_by_address.size());
|
||||
}
|
||||
|
||||
TEST_F(CfgHostsTest, deleteForIPv4) {
|
||||
testDeleteForIPv4();
|
||||
}
|
||||
|
||||
TEST_F(CfgHostsTest, deleteForIPv4MultiThreading) {
|
||||
MultiThreadingTest mt(true);
|
||||
testDeleteForIPv4();
|
||||
}
|
||||
|
||||
// This test checks that the IPv6 reservation for the specified subnet ID and
|
||||
// IPv6 address can be deleted.
|
||||
TEST_F(CfgHostsTest, deleteForIPv6) {
|
||||
void
|
||||
CfgHostsTest::testDeleteForIPv6() {
|
||||
CfgHosts cfg;
|
||||
// Add hosts.
|
||||
IOAddress address("2001:db8:1::1");
|
||||
@@ -554,6 +704,15 @@ TEST_F(CfgHostsTest, deleteForIPv6) {
|
||||
EXPECT_EQ(host_count-1, hosts_by_subnet.size());
|
||||
}
|
||||
|
||||
TEST_F(CfgHostsTest, deleteForIPv6) {
|
||||
testDeleteForIPv6();
|
||||
}
|
||||
|
||||
TEST_F(CfgHostsTest, deleteForIPv6MultiThreading) {
|
||||
MultiThreadingTest mt(true);
|
||||
testDeleteForIPv6();
|
||||
}
|
||||
|
||||
// This test checks that false is returned for deleting the IPv4 reservation
|
||||
// that doesn't exist.
|
||||
TEST_F(CfgHostsTest, deleteForMissingIPv4) {
|
||||
@@ -561,6 +720,9 @@ TEST_F(CfgHostsTest, deleteForMissingIPv4) {
|
||||
|
||||
// Delete non-existent host.
|
||||
EXPECT_FALSE(cfg.del(SubnetID(42), IOAddress(("10.0.0.42"))));
|
||||
|
||||
MultiThreadingTest mt(true);
|
||||
EXPECT_FALSE(cfg.del(SubnetID(42), IOAddress(("10.0.0.42"))));
|
||||
}
|
||||
|
||||
// This test checks that false is returned for deleting the IPv6 reservation
|
||||
@@ -570,11 +732,15 @@ TEST_F(CfgHostsTest, deleteForMissingIPv6) {
|
||||
|
||||
// Delete non-existent host.
|
||||
EXPECT_FALSE(cfg.del(SubnetID(42), IOAddress(("2001:db8:1::1"))));
|
||||
|
||||
MultiThreadingTest mt(true);
|
||||
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) {
|
||||
void
|
||||
CfgHostsTest::testDel4() {
|
||||
CfgHosts cfg;
|
||||
|
||||
// Add hosts.
|
||||
@@ -627,9 +793,19 @@ TEST_F(CfgHostsTest, del4) {
|
||||
EXPECT_FALSE(host);
|
||||
}
|
||||
|
||||
TEST_F(CfgHostsTest, del4) {
|
||||
testDel4();
|
||||
}
|
||||
|
||||
TEST_F(CfgHostsTest, del4MultiThreading) {
|
||||
MultiThreadingTest mt(true);
|
||||
testDel4();
|
||||
}
|
||||
|
||||
// This test checks that the host and its reservations for the specified IPv6
|
||||
// subnet and identifier can be deleted.
|
||||
TEST_F(CfgHostsTest, del6) {
|
||||
void
|
||||
CfgHostsTest::testDel6() {
|
||||
CfgHosts cfg;
|
||||
|
||||
// Add hosts.
|
||||
@@ -686,12 +862,24 @@ TEST_F(CfgHostsTest, del6) {
|
||||
EXPECT_FALSE(host);
|
||||
}
|
||||
|
||||
TEST_F(CfgHostsTest, del6) {
|
||||
testDel6();
|
||||
}
|
||||
|
||||
TEST_F(CfgHostsTest, del6MultiThreading) {
|
||||
MultiThreadingTest mt(true);
|
||||
testDel6();
|
||||
}
|
||||
|
||||
// This test checks that false is returned for deleting the IPv4 host that
|
||||
// doesn't exist.
|
||||
TEST_F(CfgHostsTest, del4MissingHost) {
|
||||
CfgHosts cfg;
|
||||
EXPECT_FALSE(cfg.del4(SubnetID(42), Host::IdentifierType::IDENT_DUID,
|
||||
&duids_[0]->getDuid()[0], duids_[0]->getDuid().size()));
|
||||
MultiThreadingTest mt(true);
|
||||
EXPECT_FALSE(cfg.del4(SubnetID(42), Host::IdentifierType::IDENT_DUID,
|
||||
&duids_[0]->getDuid()[0], duids_[0]->getDuid().size()));
|
||||
}
|
||||
|
||||
// This test checks that false is returned for deleting the IPv6 host that
|
||||
@@ -700,11 +888,15 @@ TEST_F(CfgHostsTest, del6MissingHost) {
|
||||
CfgHosts cfg;
|
||||
EXPECT_FALSE(cfg.del6(SubnetID(42), Host::IdentifierType::IDENT_DUID,
|
||||
&duids_[0]->getDuid()[0], duids_[0]->getDuid().size()));
|
||||
MultiThreadingTest mt(true);
|
||||
EXPECT_FALSE(cfg.del6(SubnetID(42), Host::IdentifierType::IDENT_DUID,
|
||||
&duids_[0]->getDuid()[0], duids_[0]->getDuid().size()));
|
||||
}
|
||||
|
||||
// This test checks that all reservations for the specified IPv4 subnet can
|
||||
// be deleted.
|
||||
TEST_F(CfgHostsTest, deleteAll4) {
|
||||
void
|
||||
CfgHostsTest::testDeleteAll4() {
|
||||
CfgHosts cfg;
|
||||
// Add hosts.
|
||||
for (unsigned i = 0; i < 25; ++i) {
|
||||
@@ -748,9 +940,19 @@ TEST_F(CfgHostsTest, deleteAll4) {
|
||||
EXPECT_EQ(1, *subnet_ids.begin());
|
||||
}
|
||||
|
||||
TEST_F(CfgHostsTest, deleteAll4) {
|
||||
testDeleteAll4();
|
||||
}
|
||||
|
||||
TEST_F(CfgHostsTest, deleteAll4MultiThreading) {
|
||||
MultiThreadingTest mt(true);
|
||||
testDeleteAll4();
|
||||
}
|
||||
|
||||
// This test checks that the reservations can be retrieved for the particular
|
||||
// host connected to the specific IPv4 subnet (by subnet id).
|
||||
TEST_F(CfgHostsTest, get4) {
|
||||
void
|
||||
CfgHostsTest::testGet4() {
|
||||
CfgHosts cfg;
|
||||
// Add hosts.
|
||||
for (unsigned i = 0; i < 25; ++i) {
|
||||
@@ -787,8 +989,18 @@ TEST_F(CfgHostsTest, get4) {
|
||||
}
|
||||
}
|
||||
|
||||
TEST_F(CfgHostsTest, get4) {
|
||||
testGet4();
|
||||
}
|
||||
|
||||
TEST_F(CfgHostsTest, get4MultiThreading) {
|
||||
MultiThreadingTest mt(true);
|
||||
testGet4();
|
||||
}
|
||||
|
||||
// This test checks that the DHCPv4 reservations can be unparsed
|
||||
TEST_F(CfgHostsTest, unparsed4) {
|
||||
void
|
||||
CfgHostsTest::testUnparsed4() {
|
||||
CfgMgr::instance().setFamily(AF_INET);
|
||||
CfgHosts cfg;
|
||||
CfgHostsList list;
|
||||
@@ -871,9 +1083,19 @@ TEST_F(CfgHostsTest, unparsed4) {
|
||||
}
|
||||
}
|
||||
|
||||
TEST_F(CfgHostsTest, unparsed4) {
|
||||
testUnparsed4();
|
||||
}
|
||||
|
||||
TEST_F(CfgHostsTest, unparsed4MultiThreading) {
|
||||
MultiThreadingTest mt(true);
|
||||
testUnparsed4();
|
||||
}
|
||||
|
||||
// This test checks that the reservations can be retrieved for the particular
|
||||
// host connected to the specific IPv6 subnet (by subnet id).
|
||||
TEST_F(CfgHostsTest, get6) {
|
||||
void
|
||||
CfgHostsTest::testGet6() {
|
||||
CfgHosts cfg;
|
||||
// Add hosts.
|
||||
for (unsigned i = 0; i < 25; ++i) {
|
||||
@@ -922,9 +1144,19 @@ TEST_F(CfgHostsTest, get6) {
|
||||
}
|
||||
}
|
||||
|
||||
TEST_F(CfgHostsTest, get6) {
|
||||
testGet6();
|
||||
}
|
||||
|
||||
TEST_F(CfgHostsTest, get6MultiThreading) {
|
||||
MultiThreadingTest mt(true);
|
||||
testGet6();
|
||||
}
|
||||
|
||||
// This test checks that all reservations for the specified IPv6 subnet can
|
||||
// be deleted.
|
||||
TEST_F(CfgHostsTest, deleteAll6) {
|
||||
void
|
||||
CfgHostsTest::testDeleteAll6() {
|
||||
CfgHosts cfg;
|
||||
// Add hosts.
|
||||
for (unsigned i = 0; i < 25; ++i) {
|
||||
@@ -969,8 +1201,18 @@ TEST_F(CfgHostsTest, deleteAll6) {
|
||||
}
|
||||
}
|
||||
|
||||
TEST_F(CfgHostsTest, deleteAll6) {
|
||||
testDeleteAll6();
|
||||
}
|
||||
|
||||
TEST_F(CfgHostsTest, deleteAll6MultiThreading) {
|
||||
MultiThreadingTest mt(true);
|
||||
testDeleteAll6();
|
||||
}
|
||||
|
||||
// This test checks that the DHCPv6 reservations can be unparsed
|
||||
TEST_F(CfgHostsTest, unparse6) {
|
||||
void
|
||||
CfgHostsTest::testUnparse6() {
|
||||
CfgMgr::instance().setFamily(AF_INET6);
|
||||
CfgHosts cfg;
|
||||
CfgHostsList list;
|
||||
@@ -1071,9 +1313,19 @@ TEST_F(CfgHostsTest, unparse6) {
|
||||
}
|
||||
}
|
||||
|
||||
TEST_F(CfgHostsTest, unparse6) {
|
||||
testUnparse6();
|
||||
}
|
||||
|
||||
TEST_F(CfgHostsTest, unparse6MultiThreading) {
|
||||
MultiThreadingTest mt(true);
|
||||
testUnparse6();
|
||||
}
|
||||
|
||||
// This test checks that the IPv6 reservations can be retrieved for a particular
|
||||
// (subnet-id, address) tuple.
|
||||
TEST_F(CfgHostsTest, get6ByAddr) {
|
||||
void
|
||||
CfgHostsTest::testGet6ByAddr() {
|
||||
CfgHosts cfg;
|
||||
// Add hosts.
|
||||
for (unsigned i = 0; i < 25; ++i) {
|
||||
@@ -1103,9 +1355,19 @@ TEST_F(CfgHostsTest, get6ByAddr) {
|
||||
}
|
||||
}
|
||||
|
||||
TEST_F(CfgHostsTest, get6ByAddr) {
|
||||
testGet6ByAddr();
|
||||
}
|
||||
|
||||
TEST_F(CfgHostsTest, get6ByAddrMultiThreading) {
|
||||
MultiThreadingTest mt(true);
|
||||
testGet6ByAddr();
|
||||
}
|
||||
|
||||
// This test checks that the IPv6 reservations can be retrieved for a particular
|
||||
// (subnet-id, address) tuple.
|
||||
TEST_F(CfgHostsTest, get6MultipleAddrs) {
|
||||
void
|
||||
CfgHostsTest::testGet6MultipleAddrs() {
|
||||
CfgHosts cfg;
|
||||
|
||||
// Add 25 hosts. Each host has reservations for 5 addresses.
|
||||
@@ -1154,10 +1416,19 @@ TEST_F(CfgHostsTest, get6MultipleAddrs) {
|
||||
}
|
||||
}
|
||||
|
||||
TEST_F(CfgHostsTest, get6MultipleAddrs) {
|
||||
testGet6MultipleAddrs();
|
||||
}
|
||||
|
||||
TEST_F(CfgHostsTest, get6MultipleAddrsMultiThreading) {
|
||||
MultiThreadingTest mt(true);
|
||||
testGet6MultipleAddrs();
|
||||
}
|
||||
|
||||
// Checks that it's not possible for a second host to reserve an address
|
||||
// which is already reserved.
|
||||
TEST_F(CfgHostsTest, add4AlreadyReserved) {
|
||||
void
|
||||
CfgHostsTest::testAdd4AlreadyReserved() {
|
||||
CfgHosts cfg;
|
||||
|
||||
// First host has a reservation for address 192.0.2.1
|
||||
@@ -1179,9 +1450,19 @@ TEST_F(CfgHostsTest, add4AlreadyReserved) {
|
||||
EXPECT_THROW(cfg.add(host2), isc::dhcp::ReservedAddress);
|
||||
}
|
||||
|
||||
TEST_F(CfgHostsTest, add4AlreadyReserved) {
|
||||
testAdd4AlreadyReserved();
|
||||
}
|
||||
|
||||
TEST_F(CfgHostsTest, add4AlreadyReservedMultiThreading) {
|
||||
MultiThreadingTest mt(true);
|
||||
testAdd4AlreadyReserved();
|
||||
}
|
||||
|
||||
// Test that it is possible to allow inserting multiple reservations for
|
||||
// the same IP address.
|
||||
TEST_F(CfgHostsTest, allow4AlreadyReserved) {
|
||||
void
|
||||
CfgHostsTest::testAllow4AlreadyReserved() {
|
||||
CfgHosts cfg;
|
||||
// Allow creating multiple reservations for the same IP address.
|
||||
ASSERT_TRUE(cfg.setIPReservationsUnique(false));
|
||||
@@ -1212,9 +1493,19 @@ TEST_F(CfgHostsTest, allow4AlreadyReserved) {
|
||||
returned[1]->getIPv4Reservation().toText());
|
||||
}
|
||||
|
||||
TEST_F(CfgHostsTest, allow4AlreadyReserved) {
|
||||
testAllow4AlreadyReserved();
|
||||
}
|
||||
|
||||
TEST_F(CfgHostsTest, allow4AlreadyReservedMultiThreading) {
|
||||
MultiThreadingTest mt(true);
|
||||
testAllow4AlreadyReserved();
|
||||
}
|
||||
|
||||
// Checks that it's not possible for two hosts to have the same address
|
||||
// reserved at the same time.
|
||||
TEST_F(CfgHostsTest, add6Invalid2Hosts) {
|
||||
void
|
||||
CfgHostsTest::testAdd6Invalid2Hosts() {
|
||||
CfgHosts cfg;
|
||||
|
||||
// First host has a reservation for address 2001:db8::1
|
||||
@@ -1238,9 +1529,19 @@ TEST_F(CfgHostsTest, add6Invalid2Hosts) {
|
||||
EXPECT_THROW(cfg.add(host2), isc::dhcp::DuplicateHost);
|
||||
}
|
||||
|
||||
TEST_F(CfgHostsTest, add6Invalid2Hosts) {
|
||||
testAdd6Invalid2Hosts();
|
||||
}
|
||||
|
||||
TEST_F(CfgHostsTest, add6Invalid2HostsMultiThreading) {
|
||||
MultiThreadingTest mt(true);
|
||||
testAdd6Invalid2Hosts();
|
||||
}
|
||||
|
||||
// Test that it is possible to allow inserting multiple reservations for
|
||||
// the same IPv6 address.
|
||||
TEST_F(CfgHostsTest, allowAddress6AlreadyReserved) {
|
||||
void
|
||||
CfgHostsTest::testAllowAddress6AlreadyReserved() {
|
||||
CfgHosts cfg;
|
||||
// Allow creating multiple reservations for the same IP address.
|
||||
ASSERT_TRUE(cfg.setIPReservationsUnique(false));
|
||||
@@ -1279,9 +1580,19 @@ TEST_F(CfgHostsTest, allowAddress6AlreadyReserved) {
|
||||
range1.first->second.getPrefix().toText());
|
||||
}
|
||||
|
||||
TEST_F(CfgHostsTest, allowAddress6AlreadyReserved) {
|
||||
testAllowAddress6AlreadyReserved();
|
||||
}
|
||||
|
||||
TEST_F(CfgHostsTest, allowAddress6AlreadyReservedMultiThreading) {
|
||||
MultiThreadingTest mt(true);
|
||||
testAllowAddress6AlreadyReserved();
|
||||
}
|
||||
|
||||
// Test that it is possible to allow inserting multiple reservations for
|
||||
// the same IPv6 delegated prefix.
|
||||
TEST_F(CfgHostsTest, allowPrefix6AlreadyReserved) {
|
||||
void
|
||||
CfgHostsTest::testAllowPrefix6AlreadyReserved() {
|
||||
CfgHosts cfg;
|
||||
// Allow creating multiple reservations for the same delegated prefix.
|
||||
ASSERT_TRUE(cfg.setIPReservationsUnique(false));
|
||||
@@ -1320,6 +1631,15 @@ TEST_F(CfgHostsTest, allowPrefix6AlreadyReserved) {
|
||||
range1.first->second.getPrefix().toText());
|
||||
}
|
||||
|
||||
TEST_F(CfgHostsTest, allowPrefix6AlreadyReserved) {
|
||||
testAllowPrefix6AlreadyReserved();
|
||||
}
|
||||
|
||||
TEST_F(CfgHostsTest, allowPrefix6AlreadyReservedMultiThreading) {
|
||||
MultiThreadingTest mt(true);
|
||||
testAllowPrefix6AlreadyReserved();
|
||||
}
|
||||
|
||||
// Check that no error is reported when adding a host with subnet
|
||||
// ids equal to global.
|
||||
TEST_F(CfgHostsTest, globalSubnetIDs) {
|
||||
@@ -1344,7 +1664,8 @@ TEST_F(CfgHostsTest, unusedSubnetIDs) {
|
||||
|
||||
// This test verifies that it is not possible to add the same Host to the
|
||||
// same IPv4 subnet twice.
|
||||
TEST_F(CfgHostsTest, duplicatesSubnet4HWAddr) {
|
||||
void
|
||||
CfgHostsTest::testDuplicatesSubnet4HWAddr() {
|
||||
CfgHosts cfg;
|
||||
// Add a host.
|
||||
ASSERT_NO_THROW(cfg.add(HostPtr(new Host(hwaddrs_[0]->toText(false),
|
||||
@@ -1367,9 +1688,19 @@ TEST_F(CfgHostsTest, duplicatesSubnet4HWAddr) {
|
||||
IOAddress("10.0.0.10")))));
|
||||
}
|
||||
|
||||
TEST_F(CfgHostsTest, duplicatesSubnet4HWAddr) {
|
||||
testDuplicatesSubnet4HWAddr();
|
||||
}
|
||||
|
||||
TEST_F(CfgHostsTest, duplicatesSubnet4HWAddrMultiThreading) {
|
||||
MultiThreadingTest mt(true);
|
||||
testDuplicatesSubnet4HWAddr();
|
||||
}
|
||||
|
||||
// This test verifies that it is not possible to add the same Host to the
|
||||
// same IPv4 subnet twice.
|
||||
TEST_F(CfgHostsTest, duplicatesSubnet4DUID) {
|
||||
void
|
||||
CfgHostsTest::testDuplicatesSubnet4DUID() {
|
||||
CfgHosts cfg;
|
||||
// Add a host.
|
||||
ASSERT_NO_THROW(cfg.add(HostPtr(new Host(duids_[0]->toText(),
|
||||
@@ -1392,9 +1723,19 @@ TEST_F(CfgHostsTest, duplicatesSubnet4DUID) {
|
||||
IOAddress("10.0.0.10")))));
|
||||
}
|
||||
|
||||
TEST_F(CfgHostsTest, duplicatesSubnet4DUID) {
|
||||
testDuplicatesSubnet4DUID();
|
||||
}
|
||||
|
||||
TEST_F(CfgHostsTest, duplicatesSubnet4DUIDMultiThreading) {
|
||||
MultiThreadingTest mt(true);
|
||||
testDuplicatesSubnet4DUID();
|
||||
}
|
||||
|
||||
// This test verifies that it is not possible to add the same Host to the
|
||||
// same IPv6 subnet twice.
|
||||
TEST_F(CfgHostsTest, duplicatesSubnet6HWAddr) {
|
||||
void
|
||||
CfgHostsTest::testDuplicatesSubnet6HWAddr() {
|
||||
CfgHosts cfg;
|
||||
// Add a host.
|
||||
ASSERT_NO_THROW(cfg.add(HostPtr(new Host(hwaddrs_[0]->toText(false),
|
||||
@@ -1420,9 +1761,19 @@ TEST_F(CfgHostsTest, duplicatesSubnet6HWAddr) {
|
||||
"foo.example.com"))));
|
||||
}
|
||||
|
||||
TEST_F(CfgHostsTest, duplicatesSubnet6HWAddr) {
|
||||
testDuplicatesSubnet6HWAddr();
|
||||
}
|
||||
|
||||
TEST_F(CfgHostsTest, duplicatesSubnet6HWAddrMultiThreading) {
|
||||
MultiThreadingTest mt(true);
|
||||
testDuplicatesSubnet6HWAddr();
|
||||
}
|
||||
|
||||
// This test verifies that it is not possible to add the same Host to the
|
||||
// same IPv6 subnet twice.
|
||||
TEST_F(CfgHostsTest, duplicatesSubnet6DUID) {
|
||||
void
|
||||
CfgHostsTest::testDuplicatesSubnet6DUID() {
|
||||
CfgHosts cfg;
|
||||
// Add a host.
|
||||
ASSERT_NO_THROW(cfg.add(HostPtr(new Host(duids_[0]->toText(),
|
||||
@@ -1448,8 +1799,18 @@ TEST_F(CfgHostsTest, duplicatesSubnet6DUID) {
|
||||
"foo.example.com"))));
|
||||
}
|
||||
|
||||
// Checks that updates work correctly.
|
||||
TEST_F(CfgHostsTest, update) {
|
||||
TEST_F(CfgHostsTest, duplicatesSubnet6DUID) {
|
||||
testDuplicatesSubnet6DUID();
|
||||
}
|
||||
|
||||
TEST_F(CfgHostsTest, duplicatesSubnet6DUIDMultiThreading) {
|
||||
MultiThreadingTest mt(true);
|
||||
testDuplicatesSubnet6DUID();
|
||||
}
|
||||
|
||||
// Checks that updates work correctly. Note it is not really MT safe.
|
||||
void
|
||||
CfgHostsTest::testUpdate() {
|
||||
CfgHosts cfg;
|
||||
|
||||
HostPtr const host(boost::make_shared<Host>(duids_[0]->toText(), "duid", SUBNET_ID_UNUSED,
|
||||
@@ -1506,4 +1867,13 @@ TEST_F(CfgHostsTest, update) {
|
||||
"key=(empty) ipv6_reservations=(none)", hosts[0]->toText());
|
||||
}
|
||||
|
||||
TEST_F(CfgHostsTest, update) {
|
||||
testUpdate();
|
||||
}
|
||||
|
||||
TEST_F(CfgHostsTest, updateMultiThreading) {
|
||||
MultiThreadingTest mt(true);
|
||||
testUpdate();
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
Reference in New Issue
Block a user