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:
parent
b73b3a331c
commit
2ec065a08a
11
ChangeLog
11
ChangeLog
@ -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.
|
||||
|
@ -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:
|
||||
|
@ -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:
|
||||
|
@ -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
|
||||
|
@ -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"));
|
||||
}
|
||||
|
||||
{
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
@ -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.
|
||||
|
@ -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",
|
||||
|
@ -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;
|
||||
|
@ -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.
|
||||
|
@ -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_);
|
||||
|
@ -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.
|
||||
|
@ -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.
|
||||
|
@ -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
|
||||
|
Loading…
x
Reference in New Issue
Block a user