2
0
mirror of https://gitlab.isc.org/isc-projects/kea synced 2025-08-30 05:27:55 +00:00

[#2631] Global reserved addresses must be feasible

kea-dhcp<4/6> both now enforce globally reserved addresses
to be within the selected subnet/shared-network

Added a ChangeLog entry

doc/sphinx/arm/dhcp4-srv.rst
doc/sphinx/arm/dhcp6-srv.rst
    Updated global reservation commmentary

src/lib/dhcpsrv/alloc_engine.cc
    AllocEngine::allocateGlobalReservedLeases6() - modified to enforce
    address feasibility/subnet reselect

    AllocEngine::labelNetworkOrSubnet() - new convenience method for logging

    hasAddressReservation() - modified to enforce
    address feasibility/subnet reselect

src/lib/dhcpsrv/alloc_engine_messages.mes
    New log messages:
    ALLOC_ENGINE_IGNORING_UNSUITABLE_GLOBAL_ADDRESS
    ALLOC_ENGINE_IGNORING_UNSUITABLE_GLOBAL_ADDRESS6

src/lib/dhcpsrv/tests/alloc_engine4_unittest.cc
src/lib/dhcpsrv/tests/alloc_engine6_unittest.cc
src/lib/dhcpsrv/tests/alloc_engine_utils.*
src/bin/dhcp4/tests/host_unittest.cc
src/bin/dhcp6/tests/host_unittest.cc
    New and updated tests
This commit is contained in:
Thomas Markwalder 2023-01-25 10:00:12 -05:00
parent b73b3a331c
commit 2ec065a08a
14 changed files with 469 additions and 97 deletions

View File

@ -1,3 +1,14 @@
2099. [func]* tmark
An address reserved in a global reservation must now lie
within the range of the subnet or shared-network selected
by Kea. In the event that it does not, the server will
attempt to allocate an address dynamically. This change
applies to both kea-dhcp4 and kea-dhcp6. Prior to this
the servers would grant a lease for any globallyo reserved
address without regard for its feasibility within the
selected subnet.
(Gitlab #2631)
2098. [doc] razvan
Updated classify ARM examples with a case when both operands of
the evaluated expression are computed at runtime.

View File

@ -5225,16 +5225,21 @@ every subnet that has global reservations enabled.
This feature can be used to assign certain parameters, such as hostname
or other dedicated, host-specific options. It can also be used to assign
addresses. However, global reservations that assign addresses bypass the
whole topology determination provided by the DHCP logic implemented in Kea.
It is very easy to misuse this feature and get a configuration that is
inconsistent. To give a specific example, imagine a global reservation
for the address 192.0.2.100 and two subnets 192.0.2.0/24 and 192.0.5.0/24.
If global reservations are used in both subnets and a device matching
global host reservations visits part of the network that is serviced by
192.0.5.0/24, it will get an IP address 192.0.2.100, a subnet 192.0.5.0,
and a default router 192.0.5.1. Obviously, such a configuration is
unusable, as the client will not be able to reach its default gateway.
addresses.
An address assigned via global host reservation must be feasible for the
subnet the server selects for the client. In other words, the address must
lie within the subnet otherwise it will be ignored and the server will
attempt to dynamically allocate an address. In the event the selected subnet
belongs to a shared-network the server will check for feasibility against
the subnet's siblings, selecting the first in-range subnet. If no such
subnet exists, the server will fallback to dynamically allocating the address.
.. note::
Prior to release 2.3.5, the server did not perform feasibility checks on
globally reserved addresses. This allowed the server to be configured to
hand out nonsensical leases for arbitrary address values.
To use global host reservations, a configuration similar to the
following can be used:

View File

@ -4566,18 +4566,22 @@ every subnet that has global reservations enabled.
This feature can be used to assign certain parameters, such as hostname
or other dedicated, host-specific options. It can also be used to assign
addresses or prefixes. However, global reservations that assign either
of these bypass the whole topology determination provided by the DHCP logic
implemented in Kea. It is very easy to misuse this feature and get a
configuration that is inconsistent. To give a specific example, imagine
a global reservation for the address 2001:db8:1111::1 and two subnets
2001:db8:1111::/48 and 2001:db8:ffff::/48. If global reservations are
used in both subnets and a device matching global host reservations
visits part of the network that is covered by 2001:db8:ffff::/48, it
will get the IP address 2001:db8:ffff::1, which is outside of the
prefix announced by its local router using router advertisements. Such a
configuration is unusable or, at the very least, riddled with
issues, such as downlink traffic not reaching the device.
addresses or prefixes.
An address assigned via global host reservation must be feasible for the
subnet the server selects for the client. In other words, the address must
lie within the subnet otherwise it will be ignored and the server will
attempt to dynamically allocate an address. In the event the selected subnet
belongs to a shared-network the server will check for feasibility against
the subnet's siblings, selecting the first in-range subnet. If no such
subnet exists, the server will fallback to dynamically allocating the address.
This does not apply to globally reserved prefixes.
.. note::
Prior to release 2.3.5, the server did not perform feasibility checks on
globally reserved addresses. This allowed the server to be configured to
hand out nonsensical leases for arbitrary address values.
To use global host reservations, a configuration similar to the
following can be used:

View File

@ -50,10 +50,15 @@ const char* CONFIGS[] = {
"},\n"
"{\n"
" \"hw-address\": \"01:02:03:04:05:06\",\n"
" \"hostname\": \"hw-host-fixed\",\n"
" \"hostname\": \"hw-host-fixed-out-of-range\",\n"
" \"ip-address\": \"192.0.1.77\"\n"
"},\n"
"{\n"
" \"hw-address\": \"02:02:03:04:05:06\",\n"
" \"hostname\": \"hw-host-fixed-in-range\",\n"
" \"ip-address\": \"10.0.0.77\"\n"
"},\n"
"{\n"
" \"duid\": \"01:02:03:04:05\",\n"
" \"hostname\": \"duid-host\"\n"
"},\n"
@ -587,15 +592,24 @@ TEST_F(HostTest, globalHardwareDynamicAddress) {
runDoraTest(CONFIGS[0], client, "hw-host-dynamic", "10.0.0.10");
}
// Verifies that a client matched to a global address reservation
// gets both the hostname and the reserved address
// when the subnet reservations flags are global only.
TEST_F(HostTest, globalHardwareFixedAddress) {
// Verifies that a client matched to a global in-subnet address reservation
// gets both the hostname and the reserved address when the subnet reservations
// flags are global only.
TEST_F(HostTest, globalHardwareFixedAddressInRange) {
Dhcp4Client client(Dhcp4Client::SELECTING);
client.setHWAddress("02:02:03:04:05:06");
runDoraTest(CONFIGS[0], client, "hw-host-fixed-in-range", "10.0.0.77");
}
// Verifies that a client matched to a global out-of-range address reservation
// gets the hostname and a dynmaic address when the subnet reservations
// flags are global only.
TEST_F(HostTest, globalHardwareFixedAddressOutOfRange) {
Dhcp4Client client(Dhcp4Client::SELECTING);
//client.includeClientId(clientid_a);
client.setHWAddress("01:02:03:04:05:06");
runDoraTest(CONFIGS[0], client, "hw-host-fixed", "192.0.1.77");
runDoraTest(CONFIGS[0], client, "hw-host-fixed-out-of-range", "10.0.0.10");
}
// Verifies that a client can be matched to a global reservation by DUID

View File

@ -332,8 +332,13 @@ const char* CONFIGS[] = {
"\"reservations\": [ \n"
"{ \n"
" \"duid\": \"01:02:03:04\", \n"
" \"hostname\": \"duid-host-fixed\", \n"
" \"ip-addresses\": [ \"3001::1\" ] \n"
" \"hostname\": \"duid-host-fixed-out-of-range\", \n"
" \"ip-addresses\": [ \"2001:db8:1::1\" ] \n"
"}, \n"
"{ \n"
" \"duid\": \"02:02:03:04\", \n"
" \"hostname\": \"duid-host-fixed-in-range\", \n"
" \"ip-addresses\": [ \"2001:db8:1::77\" ] \n"
"}, \n"
"{ \n"
" \"duid\": \"01:02:03:05\", \n"
@ -2365,11 +2370,19 @@ TEST_F(HostTest, globalReservationsNA) {
ASSERT_EQ(2, subnets->size());
{
SCOPED_TRACE("Global HR by DUID with reserved address");
SCOPED_TRACE("Global HR by DUID with in-range reserved address");
client.setDUID("02:02:03:04");
client.requestAddress(1234, IOAddress("::"));
// Should get global reserved address and reserved host name
ASSERT_NO_FATAL_FAILURE(sarrTest(client, "2001:db8:1::77", "duid-host-fixed-in-range"));
}
{
SCOPED_TRACE("Global HR by DUID with an out-of-range reserved address");
client.setDUID("01:02:03:04");
client.requestAddress(1234, IOAddress("::"));
// Should get global reserved address and reserved host name
ASSERT_NO_FATAL_FAILURE(sarrTest(client, "3001::1", "duid-host-fixed"));
ASSERT_NO_FATAL_FAILURE(sarrTest(client, "2001:db8:1::1", "duid-host-fixed-out-of-range"));
}
{
@ -2388,7 +2401,7 @@ TEST_F(HostTest, globalReservationsNA) {
client.setLinkLocal(IOAddress("fe80::3a60:77ff:fed5:ffee"));
client.requestAddress(1234, IOAddress("::"));
// Should get dynamic address and hardware host name
ASSERT_NO_FATAL_FAILURE(sarrTest(client, "2001:db8:1::1", "hw-host"));
ASSERT_NO_FATAL_FAILURE(sarrTest(client, "2001:db8:1::2", "hw-host"));
}
{

View File

@ -1346,6 +1346,32 @@ AllocEngine::allocateGlobalReservedLeases6(ClientContext6& ctx,
// It doesn't matter whether it is for this client or for someone else.
if (!LeaseMgrFactory::instance().getLease6(ctx.currentIA().type_, addr)) {
// Check the feasibility of this address within this shared-network.
// Assign the context's subnet accordingly.
// Only necessary for IA_NA
if (type == IPv6Resrv::TYPE_NA) {
bool valid_subnet = false;
auto subnet = ctx.subnet_;
while (subnet) {
if (subnet->inRange(addr)) {
valid_subnet = true;
break;
}
subnet = subnet->getNextSubnet(ctx.subnet_);
}
if (!valid_subnet) {
LOG_DEBUG(alloc_engine_logger, ALLOC_ENGINE_DBG_TRACE,
ALLOC_ENGINE_IGNORING_UNSUITABLE_GLOBAL_ADDRESS6)
.arg(addr.toText())
.arg(labelNetworkOrSubnet(ctx.subnet_));
continue;
}
ctx.subnet_ = subnet;
}
if (!ghost->getHostname().empty()) {
// If there is a hostname reservation here we should stick
// to this reservation. By updating the hostname in the
@ -3023,6 +3049,25 @@ void AllocEngine::reclaimLeaseInDatabase(const LeasePtrType& lease,
.arg(lease->addr_.toText());
}
std::string
AllocEngine::labelNetworkOrSubnet(SubnetPtr subnet) {
if (!subnet) {
return("<empty subnet>");
}
SharedNetwork4Ptr network;
subnet->getSharedNetwork(network);
std::ostringstream ss;
if (network) {
ss << "shared-network: " << network->getName();
} else {
ss << "subnet id: " << subnet->getID();
}
return(ss.str());
}
} // namespace dhcp
} // namespace isc
@ -3117,23 +3162,24 @@ hasAddressReservation(AllocEngine::ClientContext4& ctx) {
return (false);
}
// Flag used to perform search for global reservations only once.
bool search_global_done = false;
// Fetch the globally reserved address if there is one.
auto host = ctx.hosts_.find(SUBNET_ID_GLOBAL);
auto global_host_address = ((host != ctx.hosts_.end() && host->second) ?
host->second->getIPv4Reservation() :
IOAddress::IPV4_ZERO_ADDRESS());
// Start with currently selected subnet.
Subnet4Ptr subnet = ctx.subnet_;
while (subnet) {
// Skip search if the global reservations have already been examined.
if (!search_global_done && subnet->getReservationsGlobal()) {
auto host = ctx.hosts_.find(SUBNET_ID_GLOBAL);
// if we want global + other modes we would need to
// return only if true, else continue
if (host != ctx.hosts_.end() && host->second &&
!host->second->getIPv4Reservation().isV4Zero()) {
return (true);
}
// No need to perform this search again as there are no global
// reservations.
search_global_done = true;
// If there's a globally reserved address and global reservations are
// enabled for this network and we're either not enforcing address
// feasiblity or we are and it's feasible, update the selected
// network to that of the address and return true.
if (subnet->getReservationsGlobal() &&
(global_host_address != IOAddress::IPV4_ZERO_ADDRESS()) &&
(subnet->inRange(global_host_address))) {
ctx.subnet_ = subnet;
return (true);
}
if (subnet->getReservationsInSubnet()) {
@ -3158,6 +3204,13 @@ hasAddressReservation(AllocEngine::ClientContext4& ctx) {
subnet = subnet->getNextSubnet(ctx.subnet_, ctx.query_->getClasses());
}
if (global_host_address != IOAddress::IPV4_ZERO_ADDRESS()) {
LOG_DEBUG(alloc_engine_logger, ALLOC_ENGINE_DBG_TRACE,
ALLOC_ENGINE_IGNORING_UNSUITABLE_GLOBAL_ADDRESS)
.arg(ctx.currentHost()->getIPv4Reservation().toText())
.arg(AllocEngine::labelNetworkOrSubnet(ctx.subnet_));
}
return (false);
}

View File

@ -1836,6 +1836,16 @@ public:
/// @brief The read-write mutex.
isc::util::ReadWriteMutex rw_mutex_;
/// @brief Generates a label for subnet or shared-network from subnet
///
/// Creates a string for the subnet and it's ID for stand alone subnets
/// or the shared-network and its name if the given subnet belongs to a
/// shared-network.
///
/// @param subnet pointer to the source subnet
/// @return string contaning the generated label
static std::string labelNetworkOrSubnet(SubnetPtr subnet);
};
/// @brief A pointer to the @c AllocEngine object.

View File

@ -7,6 +7,8 @@
namespace isc {
namespace dhcp {
extern const isc::log::MessageID ALLOC_ENGINE_IGNORING_UNSUITABLE_GLOBAL_ADDRESS = "ALLOC_ENGINE_IGNORING_UNSUITABLE_GLOBAL_ADDRESS";
extern const isc::log::MessageID ALLOC_ENGINE_IGNORING_UNSUITABLE_GLOBAL_ADDRESS6 = "ALLOC_ENGINE_IGNORING_UNSUITABLE_GLOBAL_ADDRESS6";
extern const isc::log::MessageID ALLOC_ENGINE_LEASE_RECLAIMED = "ALLOC_ENGINE_LEASE_RECLAIMED";
extern const isc::log::MessageID ALLOC_ENGINE_REMOVAL_NCR_FAILED = "ALLOC_ENGINE_REMOVAL_NCR_FAILED";
extern const isc::log::MessageID ALLOC_ENGINE_V4_ALLOC_ERROR = "ALLOC_ENGINE_V4_ALLOC_ERROR";
@ -90,6 +92,8 @@ extern const isc::log::MessageID ALLOC_ENGINE_V6_REVOKED_SHARED_PREFIX_LEASE = "
namespace {
const char* values[] = {
"ALLOC_ENGINE_IGNORING_UNSUITABLE_GLOBAL_ADDRESS", "ignoring globally reserved address %1, it falls outside %2",
"ALLOC_ENGINE_IGNORING_UNSUITABLE_GLOBAL_ADDRESS6", "ignoring globally reserved address %1, it falls outside %2",
"ALLOC_ENGINE_LEASE_RECLAIMED", "successfully reclaimed lease %1",
"ALLOC_ENGINE_REMOVAL_NCR_FAILED", "sending removal name change request failed for lease %1: %2",
"ALLOC_ENGINE_V4_ALLOC_ERROR", "%1: error during attempt to allocate an IPv4 address: %2",

View File

@ -8,6 +8,8 @@
namespace isc {
namespace dhcp {
extern const isc::log::MessageID ALLOC_ENGINE_IGNORING_UNSUITABLE_GLOBAL_ADDRESS;
extern const isc::log::MessageID ALLOC_ENGINE_IGNORING_UNSUITABLE_GLOBAL_ADDRESS6;
extern const isc::log::MessageID ALLOC_ENGINE_LEASE_RECLAIMED;
extern const isc::log::MessageID ALLOC_ENGINE_REMOVAL_NCR_FAILED;
extern const isc::log::MessageID ALLOC_ENGINE_V4_ALLOC_ERROR;

View File

@ -606,3 +606,15 @@ normal occurrence during conflict resolution, which can occur in cases
such as the system administrator adding reservations for an address
that is currently in use by another client. The server will fully
recover from this situation, but clients will change their prefixes.
% ALLOC_ENGINE_IGNORING_UNSUITABLE_GLOBAL_ADDRESS ignoring globally reserved address %1, it falls outside %2
This debug message is issued when the allocation engine determines that
the globally reserved address falls outside the selected subnet or
shared-network. The server should ignore the reserved address and
attempt a dynamic allocation.
% ALLOC_ENGINE_IGNORING_UNSUITABLE_GLOBAL_ADDRESS6 ignoring globally reserved address %1, it falls outside %2
This debug message is issued when the allocation engine determines that
the globally reserved address falls outside the selected subnet or
shared-network. The server should ignore the reserved address and
attempt a dynamic allocation.

View File

@ -1174,6 +1174,54 @@ TEST_F(SharedNetworkAlloc4Test, discoverSharedNetworkPoolClassification) {
EXPECT_EQ("192.0.2.17", lease->addr_.toText());
}
// Test that global reservations within shared network take precedence over the
// existing leases regardless in which subnet belonging to a shared network
// reservations belong.
TEST_F(SharedNetworkAlloc4Test, discoverSharedNetworkReservationsGlobal) {
EXPECT_FALSE(HostMgr::instance().getDisableSingleQuery());
// Create reservation for the client.
HostPtr host(new Host(&hwaddr_->hwaddr_[0], hwaddr_->hwaddr_.size(),
Host::IDENT_HWADDR, SUBNET_ID_GLOBAL,
SUBNET_ID_UNUSED, IOAddress("10.1.2.105")));
CfgMgr::instance().getStagingCfg()->getCfgHosts()->add(host);
CfgMgr::instance().commit();
subnet1_->setReservationsGlobal(true);
subnet1_->setReservationsInSubnet(true);
subnet2_->setReservationsGlobal(true);
subnet2_->setReservationsInSubnet(true);
// Start allocation from subnet1. The engine should determine that the
// client has global reservations within subnet2 and should rather
// assign reserved addresses.
AllocEngine::ClientContext4
ctx(subnet1_, ClientIdPtr(), hwaddr_, IOAddress::IPV4_ZERO_ADDRESS(),
false, false, "host.example.com.", true);
ctx.query_.reset(new Pkt4(DHCPDISCOVER, 1234));
AllocEngine::findReservation(ctx);
Lease4Ptr lease = engine_.allocateLease4(ctx);
ASSERT_TRUE(lease);
EXPECT_EQ("10.1.2.105", lease->addr_.toText());
EXPECT_EQ(lease->subnet_id_, subnet2_->getID());
// Let's create a lease for the client to make sure the lease is not
// renewed but a reserved lease is offered.
Lease4Ptr lease2(new Lease4(IOAddress("192.0.2.17"), hwaddr_, ClientIdPtr(),
501, time(NULL), subnet1_->getID()));
lease->cltt_ = time(NULL) - 10; // Allocated 10 seconds ago
ASSERT_TRUE(LeaseMgrFactory::instance().addLease(lease2));
ctx.subnet_ = subnet1_;
ctx.hosts_.clear();
AllocEngine::findReservation(ctx);
lease = engine_.allocateLease4(ctx);
ASSERT_TRUE(lease);
EXPECT_EQ("10.1.2.105", lease->addr_.toText());
EXPECT_EQ(lease->subnet_id_, subnet2_->getID());
}
// Test that reservations within shared network take precedence over the
// existing leases regardless in which subnet belonging to a shared network
// reservations belong.
@ -1184,7 +1232,7 @@ TEST_F(SharedNetworkAlloc4Test, discoverSharedNetworkReservations) {
// Create reservation for the client.
HostPtr host(new Host(&hwaddr_->hwaddr_[0], hwaddr_->hwaddr_.size(),
Host::IDENT_HWADDR, subnet2_->getID(),
SUBNET_ID_UNUSED, IOAddress("10.2.3.23")));
SUBNET_ID_UNUSED, IOAddress("10.1.2.105")));
CfgMgr::instance().getStagingCfg()->getCfgHosts()->add(host);
CfgMgr::instance().commit();
@ -1198,22 +1246,39 @@ TEST_F(SharedNetworkAlloc4Test, discoverSharedNetworkReservations) {
AllocEngine::findReservation(ctx);
Lease4Ptr lease = engine_.allocateLease4(ctx);
ASSERT_TRUE(lease);
EXPECT_EQ("10.2.3.23", lease->addr_.toText());
EXPECT_EQ("10.1.2.105", lease->addr_.toText());
EXPECT_EQ(lease->subnet_id_, subnet2_->getID());
// Let's create a lease for the client to make sure the lease is not
// renewed but a reserved lease is offered.
// Let's create a lease for the client in subnet1 to make sure the lease
// is not renewed but a reserved lease is offered.
Lease4Ptr lease2(new Lease4(IOAddress("192.0.2.17"), hwaddr_, ClientIdPtr(),
501, time(NULL), subnet1_->getID()));
lease->cltt_ = time(NULL) - 10; // Allocated 10 seconds ago
lease2->cltt_ = time(NULL) - 10; // Allocated 10 seconds ago
ASSERT_TRUE(LeaseMgrFactory::instance().addLease(lease2));
ctx.subnet_ = subnet1_;
ctx.hosts_.clear();
AllocEngine::findReservation(ctx);
lease = engine_.allocateLease4(ctx);
ASSERT_TRUE(lease);
EXPECT_EQ("10.2.3.23", lease->addr_.toText());
EXPECT_EQ("10.1.2.105", lease->addr_.toText());
EXPECT_EQ(lease->subnet_id_, subnet2_->getID());
// Let's create a lease for the client in subnet2 to make sure the lease
// is not renewed but a reserved lease is offered.
Lease4Ptr lease3(new Lease4(IOAddress("10.1.2.55"), hwaddr_, ClientIdPtr(),
501, time(NULL), subnet2_->getID()));
lease3->cltt_ = time(NULL) - 10; // Allocated 10 seconds ago
ASSERT_TRUE(LeaseMgrFactory::instance().addLease(lease3));
ctx.subnet_ = subnet1_;
ctx.hosts_.clear();
AllocEngine::findReservation(ctx);
lease = engine_.allocateLease4(ctx);
ASSERT_TRUE(lease);
EXPECT_EQ("10.1.2.105", lease->addr_.toText());
EXPECT_EQ(lease->subnet_id_, subnet2_->getID());
}
// Test that reservations within shared network take precedence over the
// existing leases regardless in which subnet belonging to a shared network
// reservations belong. Host lookups returning a collection are disabled.
@ -1228,10 +1293,15 @@ TEST_F(SharedNetworkAlloc4Test, discoverSharedNetworkReservationsNoColl) {
// Create reservation for the client.
HostPtr host(new Host(&hwaddr_->hwaddr_[0], hwaddr_->hwaddr_.size(),
Host::IDENT_HWADDR, subnet2_->getID(),
SUBNET_ID_UNUSED, IOAddress("10.2.3.23")));
SUBNET_ID_UNUSED, IOAddress("10.1.2.105")));
CfgMgr::instance().getStagingCfg()->getCfgHosts()->add(host);
CfgMgr::instance().commit();
subnet1_->setReservationsGlobal(true);
subnet1_->setReservationsInSubnet(true);
subnet2_->setReservationsGlobal(true);
subnet2_->setReservationsInSubnet(true);
// Start allocation from subnet1. The engine should determine that the
// client has reservations in subnet2 and should rather assign reserved
// addresses.
@ -1242,7 +1312,8 @@ TEST_F(SharedNetworkAlloc4Test, discoverSharedNetworkReservationsNoColl) {
AllocEngine::findReservation(ctx);
Lease4Ptr lease = engine_.allocateLease4(ctx);
ASSERT_TRUE(lease);
EXPECT_EQ("10.2.3.23", lease->addr_.toText());
EXPECT_EQ("10.1.2.105", lease->addr_.toText());
EXPECT_EQ(lease->subnet_id_, subnet2_->getID());
// Let's create a lease for the client to make sure the lease is not
// renewed but a reserved lease is offered.
@ -1255,7 +1326,8 @@ TEST_F(SharedNetworkAlloc4Test, discoverSharedNetworkReservationsNoColl) {
AllocEngine::findReservation(ctx);
lease = engine_.allocateLease4(ctx);
ASSERT_TRUE(lease);
EXPECT_EQ("10.2.3.23", lease->addr_.toText());
EXPECT_EQ("10.1.2.105", lease->addr_.toText());
EXPECT_EQ(lease->subnet_id_, subnet2_->getID());
}
// This test verifies that the server can offer an address from a shared
@ -1499,7 +1571,7 @@ TEST_F(SharedNetworkAlloc4Test, requestSharedNetworkReservations) {
// Create reservation for the client.
HostPtr host(new Host(&hwaddr_->hwaddr_[0], hwaddr_->hwaddr_.size(),
Host::IDENT_HWADDR, subnet2_->getID(),
SUBNET_ID_UNUSED, IOAddress("10.2.3.23")));
SUBNET_ID_UNUSED, IOAddress("10.1.2.105")));
CfgMgr::instance().getStagingCfg()->getCfgHosts()->add(host);
CfgMgr::instance().commit();
@ -1513,7 +1585,8 @@ TEST_F(SharedNetworkAlloc4Test, requestSharedNetworkReservations) {
AllocEngine::findReservation(ctx);
Lease4Ptr lease = engine_.allocateLease4(ctx);
ASSERT_TRUE(lease);
EXPECT_EQ("10.2.3.23", lease->addr_.toText());
EXPECT_EQ("10.1.2.105", lease->addr_.toText());
EXPECT_EQ(lease->subnet_id_, subnet2_->getID());
// Remove the lease for another test below.
ASSERT_TRUE(LeaseMgrFactory::instance().deleteLease(lease));
@ -1529,7 +1602,8 @@ TEST_F(SharedNetworkAlloc4Test, requestSharedNetworkReservations) {
AllocEngine::findReservation(ctx);
lease = engine_.allocateLease4(ctx);
ASSERT_TRUE(lease);
EXPECT_EQ("10.2.3.23", lease->addr_.toText());
EXPECT_EQ("10.1.2.105", lease->addr_.toText());
EXPECT_EQ(lease->subnet_id_, subnet2_->getID());
}
// Test that reservations within shared network take precedence over the
@ -1546,7 +1620,7 @@ TEST_F(SharedNetworkAlloc4Test, requestSharedNetworkReservationsNoColl) {
// Create reservation for the client.
HostPtr host(new Host(&hwaddr_->hwaddr_[0], hwaddr_->hwaddr_.size(),
Host::IDENT_HWADDR, subnet2_->getID(),
SUBNET_ID_UNUSED, IOAddress("10.2.3.23")));
SUBNET_ID_UNUSED, IOAddress("10.1.2.105")));
CfgMgr::instance().getStagingCfg()->getCfgHosts()->add(host);
CfgMgr::instance().commit();
@ -1560,7 +1634,8 @@ TEST_F(SharedNetworkAlloc4Test, requestSharedNetworkReservationsNoColl) {
AllocEngine::findReservation(ctx);
Lease4Ptr lease = engine_.allocateLease4(ctx);
ASSERT_TRUE(lease);
EXPECT_EQ("10.2.3.23", lease->addr_.toText());
EXPECT_EQ("10.1.2.105", lease->addr_.toText());
EXPECT_EQ(lease->subnet_id_, subnet2_->getID());
// Remove the lease for another test below.
ASSERT_TRUE(LeaseMgrFactory::instance().deleteLease(lease));
@ -1576,7 +1651,8 @@ TEST_F(SharedNetworkAlloc4Test, requestSharedNetworkReservationsNoColl) {
AllocEngine::findReservation(ctx);
lease = engine_.allocateLease4(ctx);
ASSERT_TRUE(lease);
EXPECT_EQ("10.2.3.23", lease->addr_.toText());
EXPECT_EQ("10.1.2.105", lease->addr_.toText());
EXPECT_EQ(lease->subnet_id_, subnet2_->getID());
}
// This test checks if an expired lease can be reused in DHCPDISCOVER (fake
@ -3128,11 +3204,11 @@ TEST_F(AllocEngine4Test, reservedAddressExistingLeaseStat) {
// This test checks the behavior of the allocation engine in the following
// scenario:
// - Client has no lease in the database.
// - Client has a global reservation.
// - Client has a global reservation outside of the subnet.
// - Client sends DISCOVER
// - Client is allocated the reserved address.
// - Client is allocated an address within the subnet.
// - Lease is not added to the lease database
TEST_F(AllocEngine4Test, globalReservationReservedAddressDiscover) {
TEST_F(AllocEngine4Test, globalReservationReservedNonMatchingAddressDiscover) {
// Create reservation for the client.
HostPtr host(new Host(&hwaddr_->hwaddr_[0], hwaddr_->hwaddr_.size(),
Host::IDENT_HWADDR, SUBNET_ID_GLOBAL,
@ -3159,10 +3235,10 @@ TEST_F(AllocEngine4Test, globalReservationReservedAddressDiscover) {
EXPECT_EQ(ctx.currentHost()->getHostname(), host->getHostname());
EXPECT_EQ(ctx.currentHost()->getIPv4Reservation(), host->getIPv4Reservation());
// We should allocate the reserved address.
// We should allocate an address in the subnet
Lease4Ptr lease = engine.allocateLease4(ctx);
ASSERT_TRUE(lease);
EXPECT_EQ("192.0.77.123", lease->addr_.toText());
EXPECT_TRUE(subnet_->inRange(lease->addr_));
// This is a "fake" allocation so the returned lease should not be committed
// to the lease database.
@ -3176,11 +3252,59 @@ TEST_F(AllocEngine4Test, globalReservationReservedAddressDiscover) {
// This test checks the behavior of the allocation engine in the following
// scenario:
// - Client has no lease in the database.
// - Client has a global reservation.
// - Client has a global reservation matching the current subnet.
// - Client sends DISCOVER
// - Client is allocated the reserved address.
// - Lease is not added to the lease database
TEST_F(AllocEngine4Test, globalReservationReservedMatchingAddressDiscover) {
// Create reservation for the client.
HostPtr host(new Host(&hwaddr_->hwaddr_[0], hwaddr_->hwaddr_.size(),
Host::IDENT_HWADDR, SUBNET_ID_GLOBAL,
SUBNET_ID_UNUSED, IOAddress("192.0.2.10")));
CfgMgr::instance().getStagingCfg()->getCfgHosts()->add(host);
CfgMgr::instance().commit();
AllocEngine engine(0);
subnet_->setReservationsGlobal(true);
// Query allocation engine for the lease to be assigned to this
// client without specifying the address to be assigned.
AllocEngine::ClientContext4 ctx(subnet_, clientid_, hwaddr_,
IOAddress("0.0.0.0"), false, false,
"", true);
ctx.query_.reset(new Pkt4(DHCPDISCOVER, 1234));
// Look up the host.
AllocEngine::findReservation(ctx);
// We should have the correct current host
EXPECT_TRUE(ctx.currentHost());
EXPECT_EQ(ctx.currentHost()->getHostname(), host->getHostname());
EXPECT_EQ(ctx.currentHost()->getIPv4Reservation(), host->getIPv4Reservation());
// We should allocate the reserved address.
Lease4Ptr lease = engine.allocateLease4(ctx);
ASSERT_TRUE(lease);
EXPECT_EQ("192.0.2.10", lease->addr_.toText());
// This is a "fake" allocation so the returned lease should not be committed
// to the lease database.
EXPECT_FALSE(LeaseMgrFactory::instance().getLease4(lease->addr_));
// Client had no lease in the database, so the old lease returned should
// be NULL.
ASSERT_FALSE(ctx.old_lease_);
}
// This test checks the behavior of the allocation engine in the following
// scenario:
// - Client has no lease in the database.
// - Client has a global reservation outside the current subnet.
// - Client sends REQUEST
// - Client is allocated the reserved address.
// - Lease is added to the lease database
TEST_F(AllocEngine4Test, globalReservationReservedAddressRequest) {
TEST_F(AllocEngine4Test, globalReservationReservedNonMatchingAddressRequest) {
// Create reservation for the client.
HostPtr host(new Host(&hwaddr_->hwaddr_[0], hwaddr_->hwaddr_.size(),
Host::IDENT_HWADDR, SUBNET_ID_GLOBAL,
@ -3210,7 +3334,58 @@ TEST_F(AllocEngine4Test, globalReservationReservedAddressRequest) {
// We should allocate the reserved address.
Lease4Ptr lease = engine.allocateLease4(ctx);
ASSERT_TRUE(lease);
EXPECT_EQ("192.0.77.123", lease->addr_.toText());
EXPECT_TRUE(subnet_->inRange(lease->addr_));
// Check that the lease is indeed in LeaseMgr
Lease4Ptr from_mgr = LeaseMgrFactory::instance().getLease4(lease->addr_);
ASSERT_TRUE(from_mgr);
// Now check that the lease in LeaseMgr has the same parameters
detailCompareLease(lease, from_mgr);
// Client had no lease in the database, so the old lease returned should
// be NULL.
ASSERT_FALSE(ctx.old_lease_);
}
// This test checks the behavior of the allocation engine in the following
// scenario:
// - Client has no lease in the database.
// - Client has a global reservation matching the current subnet.
// - Client sends REQUEST
// - Client is allocated the reserved address.
// - Lease is added to the lease database
TEST_F(AllocEngine4Test, globalReservationReservedMatchingAddressRequest) {
// Create reservation for the client.
HostPtr host(new Host(&hwaddr_->hwaddr_[0], hwaddr_->hwaddr_.size(),
Host::IDENT_HWADDR, SUBNET_ID_GLOBAL,
SUBNET_ID_UNUSED, IOAddress("192.0.2.10")));
CfgMgr::instance().getStagingCfg()->getCfgHosts()->add(host);
CfgMgr::instance().commit();
AllocEngine engine(0);
subnet_->setReservationsGlobal(true);
// Query allocation engine for the lease to be assigned to this
// client without specifying the address to be assigned.
AllocEngine::ClientContext4 ctx(subnet_, clientid_, hwaddr_,
IOAddress("0.0.0.0"), false, false,
"", false);
ctx.query_.reset(new Pkt4(DHCPREQUEST, 1234));
// Look up the host.
AllocEngine::findReservation(ctx);
// We should have the correct current host
EXPECT_TRUE(ctx.currentHost());
EXPECT_EQ(ctx.currentHost()->getHostname(), host->getHostname());
EXPECT_EQ(ctx.currentHost()->getIPv4Reservation(), host->getIPv4Reservation());
// We should allocate the reserved address.
Lease4Ptr lease = engine.allocateLease4(ctx);
ASSERT_TRUE(lease);
EXPECT_EQ("192.0.2.10", lease->addr_.toText());
// Check that the lease is indeed in LeaseMgr
Lease4Ptr from_mgr = LeaseMgrFactory::instance().getLease4(lease->addr_);

View File

@ -28,6 +28,10 @@ namespace isc {
namespace dhcp {
namespace test {
// Convenience values to improve readibility.
const bool IN_SUBNET = true;
const bool IN_POOL = true;
// Test convenience method adding hints to IA context.
TEST(ClientContext6Test, addHint) {
AllocEngine::ClientContext6 ctx;
@ -792,7 +796,7 @@ TEST_F(AllocEngine6Test, renewExtendLeaseLifetime) {
hints.push_back(AllocEngine::Resource(IOAddress("2001:db8:1::15"), 128));
// Client should receive a lease.
Lease6Collection renewed = renewTest(engine, pool_, hints, true);
Lease6Collection renewed = renewTest(engine, pool_, hints, IN_SUBNET, IN_POOL);
ASSERT_EQ(1, renewed.size());
// And the lease lifetime should be extended.
@ -823,7 +827,7 @@ TEST_F(AllocEngine6Test, defaultRenewLeaseLifetime) {
128, 0, 0));
// Client should receive a lease.
Lease6Collection renewed = renewTest(engine, pool_, hints, true);
Lease6Collection renewed = renewTest(engine, pool_, hints, IN_SUBNET, IN_POOL);
ASSERT_EQ(1, renewed.size());
// And the lease lifetime should be extended.
@ -858,7 +862,7 @@ TEST_F(AllocEngine6Test, hintRenewLeaseLifetime) {
128, 301, 399));
// Client should receive a lease.
Lease6Collection renewed = renewTest(engine, pool_, hints, true);
Lease6Collection renewed = renewTest(engine, pool_, hints, IN_SUBNET, IN_POOL);
ASSERT_EQ(1, renewed.size());
// And the lease lifetime should be extended.
@ -893,7 +897,7 @@ TEST_F(AllocEngine6Test, minRenewLeaseLifetime) {
128, 100, 200));
// Client should receive a lease.
Lease6Collection renewed = renewTest(engine, pool_, hints, true);
Lease6Collection renewed = renewTest(engine, pool_, hints, IN_SUBNET, IN_POOL);
ASSERT_EQ(1, renewed.size());
// And the lease lifetime should be extended.
@ -928,7 +932,7 @@ TEST_F(AllocEngine6Test, maxRenewLeaseLifetime) {
128, 500, 600));
// Client should receive a lease.
Lease6Collection renewed = renewTest(engine, pool_, hints, true);
Lease6Collection renewed = renewTest(engine, pool_, hints, IN_SUBNET, IN_POOL);
ASSERT_EQ(1, renewed.size());
// And the lease lifetime should be extended.
@ -965,7 +969,7 @@ TEST_F(AllocEngine6Test, renewExtendLeaseLifetimeForReservation) {
hints.push_back(AllocEngine::Resource(IOAddress("2001:db8:1::15"), 128));
// Client should receive a lease.
Lease6Collection renewed = renewTest(engine, pool_, hints, true);
Lease6Collection renewed = renewTest(engine, pool_, hints, IN_SUBNET, IN_POOL);
ASSERT_EQ(1, renewed.size());
// And the lease lifetime should be extended.
@ -1741,7 +1745,7 @@ TEST_F(AllocEngine6Test, addressRenewal) {
AllocEngine::HintContainer hints;
hints.push_back(AllocEngine::Resource(leases[0]->addr_, 128));
Lease6Collection renewed = renewTest(engine, pool_, hints, true);
Lease6Collection renewed = renewTest(engine, pool_, hints, IN_SUBNET, IN_POOL);
ASSERT_EQ(1, renewed.size());
// Check that the lease was indeed renewed and hasn't changed
@ -1794,7 +1798,7 @@ TEST_F(AllocEngine6Test, reservedAddressRenewal) {
AllocEngine::HintContainer hints;
hints.push_back(AllocEngine::Resource(leases[0]->addr_, 128));
Lease6Collection renewed = renewTest(engine, pool_, hints, true);
Lease6Collection renewed = renewTest(engine, pool_, hints, IN_SUBNET, IN_POOL);
ASSERT_EQ(1, renewed.size());
ASSERT_EQ("2001:db8:1::1c", leases[0]->addr_.toText());
@ -1940,7 +1944,7 @@ TEST_F(AllocEngine6Test, reservedAddressRenewChange) {
// as the pool is 2001:db8:1::10 - 2001:db8:1::20.
createHost6(true, IPv6Resrv::TYPE_NA, IOAddress("2001:db8:1::1c"), 128);
Lease6Collection renewed = renewTest(engine, pool_, hints, true);
Lease6Collection renewed = renewTest(engine, pool_, hints, IN_SUBNET, IN_POOL);
ASSERT_EQ(1, renewed.size());
ASSERT_EQ("2001:db8:1::1c", renewed[0]->addr_.toText());
}
@ -1971,7 +1975,7 @@ TEST_F(AllocEngine6Test, reservedAddressRenewReserved) {
CfgMgr::instance().getStagingCfg()->getCfgHosts()->add(host);
CfgMgr::instance().commit();
Lease6Collection renewed = renewTest(engine, pool_, hints, true);
Lease6Collection renewed = renewTest(engine, pool_, hints, IN_SUBNET, IN_POOL);
ASSERT_EQ(1, renewed.size());
// Check that we no longer have the reserved address.
@ -3139,7 +3143,7 @@ TEST_F(AllocEngine6Test, hostDynamicAddress) {
hostname_ = "host1";
// Client should receive a lease.
Lease6Collection renewed = renewTest(*engine, pool_, hints, true);
Lease6Collection renewed = renewTest(*engine, pool_, hints, IN_SUBNET, IN_POOL);
ASSERT_EQ(1, renewed.size());
Lease6Ptr renewed_lease = renewed[0];
@ -3229,7 +3233,7 @@ TEST_F(AllocEngine6Test, globalHostDynamicAddress) {
hostname_ = "ghost1";
// Client should receive a lease.
Lease6Collection renewed = renewTest(*engine, pool_, hints, true);
Lease6Collection renewed = renewTest(*engine, pool_, hints, IN_SUBNET, IN_POOL);
ASSERT_EQ(1, renewed.size());
// And the lease lifetime should be extended.
@ -3302,7 +3306,70 @@ TEST_F(AllocEngine6Test, globalHostReservedAddress) {
Lease6Ptr lease;
ASSERT_NO_THROW(lease = expectOneLease(engine->allocateLeases6(ctx)));
ASSERT_TRUE(lease);
EXPECT_EQ("3001::1", lease->addr_.toText());
// EXPECT_EQ("3001::1", lease->addr_.toText());
EXPECT_TRUE(subnet_->inRange(lease->addr_))
<< " address not in range: " << lease->addr_.toText();
ASSERT_NO_FATAL_FAILURE(rollbackPersistedCltt(lease));
EXPECT_NO_THROW(LeaseMgrFactory::instance().updateLease6(lease));
// This is what the client will send in his renew message.
AllocEngine::HintContainer hints;
hints.push_back(AllocEngine::Resource(IOAddress(lease->addr_.toText()), 128));
// Set test fixture hostname_ to the expected value. This gets checked in
// renewTest.
hostname_ = "ghost1";
// Client should receive a lease.
Lease6Collection renewed = renewTest(*engine, pool_, hints, IN_SUBNET, IN_POOL);
ASSERT_EQ(1, renewed.size());
// And the lease lifetime should be extended.
EXPECT_GT(renewed[0]->cltt_, lease->cltt_)
<< "Lease lifetime was not extended, but it should";
}
// Verifies that client with a global address reservation can get and
// renew a lease for an arbitrary address.
TEST_F(AllocEngine6Test, globalHostReservedMatchingAddress) {
boost::scoped_ptr<AllocEngine> engine;
ASSERT_NO_THROW(engine.reset(new AllocEngine(100)));
ASSERT_TRUE(engine);
HostPtr host(new Host(&duid_->getDuid()[0], duid_->getDuid().size(),
Host::IDENT_DUID, SUBNET_ID_UNUSED, SUBNET_ID_GLOBAL,
asiolink::IOAddress("0.0.0.0")));
host->setHostname("ghost1");
IPv6Resrv resv(IPv6Resrv::TYPE_NA, asiolink::IOAddress("2001:db8:1::a"), 128);
host->addReservation(resv);
CfgMgr::instance().getStagingCfg()->getCfgHosts()->add(host);
CfgMgr::instance().commit();
subnet_->setReservationsGlobal(true);
// Create context which will be used to try to allocate leases
Pkt6Ptr query(new Pkt6(DHCPV6_REQUEST, 1234));
AllocEngine::ClientContext6 ctx(subnet_, duid_, false, false, "", false, query);
ctx.currentIA().iaid_ = iaid_;
// Look up the reservation.
findReservation(*engine, ctx);
// Make sure we found our host.
ConstHostPtr current = ctx.currentHost();
ASSERT_TRUE(current);
ASSERT_EQ("ghost1", current->getHostname());
// Check that we have been allocated the fixed address.
Lease6Ptr lease;
ASSERT_NO_THROW(lease = expectOneLease(engine->allocateLeases6(ctx)));
ASSERT_TRUE(lease);
EXPECT_EQ("2001:db8:1::a", lease->addr_.toText());
// We're going to rollback the clock a little so we can verify a renewal.
//--lease->cltt_;
ASSERT_NO_FATAL_FAILURE(rollbackPersistedCltt(lease));
// We're going to rollback the clock a little so we can verify a renewal.
--lease->cltt_;
@ -3310,14 +3377,14 @@ TEST_F(AllocEngine6Test, globalHostReservedAddress) {
// This is what the client will send in his renew message.
AllocEngine::HintContainer hints;
hints.push_back(AllocEngine::Resource(IOAddress("3001::1"), 128));
hints.push_back(AllocEngine::Resource(IOAddress("2008:db8:1::a"), 128));
// Set test fixture hostname_ to the expected value. This gets checked in
// renewTest.
hostname_ = "ghost1";
// Client should receive a lease.
Lease6Collection renewed = renewTest(*engine, pool_, hints, false);
Lease6Collection renewed = renewTest(*engine, pool_, hints, IN_SUBNET, !IN_POOL);
ASSERT_EQ(1, renewed.size());
// And the lease lifetime should be extended.
@ -3379,7 +3446,7 @@ TEST_F(AllocEngine6Test, globalHostReservedPrefix) {
Pool6Ptr dummy_pool(new Pool6(Lease::TYPE_PD, IOAddress("2001:db8::"), 64, 64));
// Client should receive a lease.
Lease6Collection renewed = renewTest(*engine, dummy_pool, hints, false);
Lease6Collection renewed = renewTest(*engine, dummy_pool, hints, !IN_SUBNET, !IN_POOL);
ASSERT_EQ(1, renewed.size());
// And the lease lifetime should be extended.
@ -3444,7 +3511,7 @@ TEST_F(AllocEngine6Test, globalHostReservedPrefixDifferentPrefixLen) {
Pool6Ptr dummy_pool(new Pool6(Lease::TYPE_PD, IOAddress("2001:db8::"), 64, 64));
// Client should receive a lease.
Lease6Collection renewed = renewTest(*engine, dummy_pool, hints, false);
Lease6Collection renewed = renewTest(*engine, dummy_pool, hints, !IN_SUBNET, !IN_POOL);
ASSERT_EQ(1, renewed.size());
// And the lease lifetime should be extended.
@ -3504,7 +3571,7 @@ TEST_F(AllocEngine6Test, mixedHostReservedAddress) {
hostname_ = "mhost1";
// Client should receive a lease.
Lease6Collection renewed = renewTest(*engine, pool_, hints, true);
Lease6Collection renewed = renewTest(*engine, pool_, hints, IN_SUBNET, IN_POOL);
ASSERT_EQ(1, renewed.size());
// And the lease lifetime should be extended.
@ -3570,7 +3637,7 @@ TEST_F(AllocEngine6Test, mixedHostReservedPrefix) {
Pool6Ptr dummy_pool(new Pool6(Lease::TYPE_PD, IOAddress("2001:db8::"), 64, 64));
// Client should receive a lease.
Lease6Collection renewed = renewTest(*engine, dummy_pool, hints, true);
Lease6Collection renewed = renewTest(*engine, dummy_pool, hints, IN_SUBNET, IN_POOL);
ASSERT_EQ(1, renewed.size());
// And the lease lifetime should be extended.
@ -3633,7 +3700,7 @@ TEST_F(AllocEngine6Test, mixedHostReservedPrefixDifferentPrefixLen) {
Pool6Ptr dummy_pool(new Pool6(Lease::TYPE_PD, IOAddress("2001:db8::"), 64, 64));
// Client should receive a lease.
Lease6Collection renewed = renewTest(*engine, dummy_pool, hints, true);
Lease6Collection renewed = renewTest(*engine, dummy_pool, hints, IN_SUBNET, IN_POOL);
ASSERT_EQ(1, renewed.size());
// And the lease lifetime should be extended.
@ -3702,7 +3769,7 @@ TEST_F(AllocEngine6Test, bothHostReservedAddress) {
hostname_ = "mhost1";
// Client should receive a lease.
Lease6Collection renewed = renewTest(*engine, pool_, hints, true);
Lease6Collection renewed = renewTest(*engine, pool_, hints, IN_SUBNET, IN_POOL);
ASSERT_EQ(1, renewed.size());
// And the lease lifetime should be extended.
@ -3774,7 +3841,7 @@ TEST_F(AllocEngine6Test, bothHostReservedPrefix) {
Pool6Ptr dummy_pool(new Pool6(Lease::TYPE_PD, IOAddress("2001:db8::"), 64, 64));
// Client should receive a lease.
Lease6Collection renewed = renewTest(*engine, dummy_pool, hints, true);
Lease6Collection renewed = renewTest(*engine, dummy_pool, hints, IN_SUBNET, IN_POOL);
ASSERT_EQ(1, renewed.size());
// And the lease lifetime should be extended.
@ -3849,7 +3916,7 @@ TEST_F(AllocEngine6Test, bothHostReservedPrefixDifferentPrefixLen) {
Pool6Ptr dummy_pool(new Pool6(Lease::TYPE_PD, IOAddress("2001:db8::"), 64, 64));
// Client should receive a lease.
Lease6Collection renewed = renewTest(*engine, dummy_pool, hints, true);
Lease6Collection renewed = renewTest(*engine, dummy_pool, hints, IN_SUBNET, IN_POOL);
ASSERT_EQ(1, renewed.size());
// And the lease lifetime should be extended.

View File

@ -403,7 +403,7 @@ AllocEngine6Test::simpleAlloc6Test(const Pool6Ptr& pool, const DuidPtr& duid,
Lease6Collection
AllocEngine6Test::renewTest(AllocEngine& engine, const Pool6Ptr& pool,
AllocEngine::HintContainer& hints,
bool in_pool) {
bool in_subnet, bool in_pool) {
Lease::Type type = pool->getType();
uint8_t expected_len = pool->getLength();
@ -421,7 +421,7 @@ AllocEngine6Test::renewTest(AllocEngine& engine, const Pool6Ptr& pool,
for (Lease6Collection::iterator it = leases.begin(); it != leases.end(); ++it) {
// Do all checks on the lease
checkLease6(duid_, *it, type, expected_len, in_pool, in_pool);
checkLease6(duid_, *it, type, expected_len, in_subnet, in_pool);
// Check that context has been updated with allocated addresses or
// prefixes.

View File

@ -358,12 +358,14 @@ public:
/// @param engine a reference to Allocation Engine
/// @param pool pool from which the lease will be allocated from
/// @param hints address to be used as a hint
/// @param in_subnet whether the lease is expected to be in subnet
/// @param in_pool specifies whether the lease is expected to be in pool
/// @return allocated lease(s) (may be empty)
Lease6Collection renewTest(AllocEngine& engine,
const Pool6Ptr& pool,
AllocEngine::HintContainer& hints,
bool in_pool = true);
bool in_subnet,
bool in_pool);
/// @brief Checks if the address allocation with a hint that is in range,
/// in pool, but is currently used, can succeed