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

[#2348] Allocator is a subnet property

This commit is contained in:
Marcin Siodelski 2022-10-20 18:10:47 +02:00
parent 8cd0931513
commit 9fb382f676
21 changed files with 474 additions and 451 deletions

View File

@ -1231,10 +1231,10 @@ TEST_F(Dhcpv4SrvTest, DiscoverValidLifetime) {
// Recreate subnet
Triplet<uint32_t> unspecified;
Triplet<uint32_t> valid_lft(500, 1000, 1500);
subnet_.reset(new Subnet4(IOAddress("192.0.2.0"), 24,
subnet_ = Subnet4::create(IOAddress("192.0.2.0"), 24,
unspecified,
unspecified,
valid_lft));
valid_lft);
pool_ = Pool4Ptr(new Pool4(IOAddress("192.0.2.100"),
IOAddress("192.0.2.110")));
@ -1311,10 +1311,10 @@ TEST_F(Dhcpv4SrvTest, DiscoverTimers) {
// Recreate subnet
Triplet<uint32_t> unspecified;
Triplet<uint32_t> valid_lft(1000);
subnet_.reset(new Subnet4(IOAddress("192.0.2.0"), 24,
subnet_ = Subnet4::create(IOAddress("192.0.2.0"), 24,
unspecified,
unspecified,
valid_lft));
valid_lft);
pool_ = Pool4Ptr(new Pool4(IOAddress("192.0.2.100"),
IOAddress("192.0.2.110")));
@ -1462,10 +1462,10 @@ TEST_F(Dhcpv4SrvTest, calculateTeeTimers) {
// Recreate subnet
Triplet<uint32_t> unspecified;
Triplet<uint32_t> valid_lft(1000);
subnet_.reset(new Subnet4(IOAddress("192.0.2.0"), 24,
subnet_ = Subnet4::create(IOAddress("192.0.2.0"), 24,
unspecified,
unspecified,
valid_lft));
valid_lft);
pool_ = Pool4Ptr(new Pool4(IOAddress("192.0.2.100"),
IOAddress("192.0.2.110")));
@ -1843,10 +1843,10 @@ TEST_F(Dhcpv4SrvTest, RequestNoTimers) {
req->setIndex(ETH1_INDEX);
// Recreate a subnet but set T1 and T2 to "unspecified".
subnet_.reset(new Subnet4(IOAddress("192.0.2.0"), 24,
subnet_ = Subnet4::create(IOAddress("192.0.2.0"), 24,
Triplet<uint32_t>(),
Triplet<uint32_t>(),
3000));
3000);
pool_ = Pool4Ptr(new Pool4(IOAddress("192.0.2.100"),
IOAddress("192.0.2.110")));
subnet_->addPool(pool_);

View File

@ -62,8 +62,7 @@ Dhcpv4SrvTest::Dhcpv4SrvTest()
// Wipe any existing statistics
isc::stats::StatsMgr::instance().removeAll();
subnet_ = Subnet4Ptr(new Subnet4(IOAddress("192.0.2.0"), 24, 1000,
2000, 3000));
subnet_ = Subnet4::create(IOAddress("192.0.2.0"), 24, 1000, 2000, 3000);
pool_ = Pool4Ptr(new Pool4(IOAddress("192.0.2.100"), IOAddress("192.0.2.110")));
subnet_->addPool(pool_);

View File

@ -449,8 +449,8 @@ TEST_F(Dhcp6CBTest, mergeSubnets) {
extractConfig(base_config);
// Make a few subnets
Subnet6Ptr subnet1(new Subnet6(IOAddress("2001:1::"), 64, 1, 2, 100, 100, SubnetID(1)));
Subnet6Ptr subnet3(new Subnet6(IOAddress("2001:3::"), 64, 1, 2, 100, 100, SubnetID(3)));
auto subnet1 = Subnet6::create(IOAddress("2001:1::"), 64, 1, 2, 100, 100, SubnetID(1));
auto subnet3 = Subnet6::create(IOAddress("2001:3::"), 64, 1, 2, 100, 100, SubnetID(3));
// Add subnet1 to db1 and subnet3 to db2
db1_->createUpdateSubnet6(ServerSelector::ALL(), subnet1);

View File

@ -695,7 +695,7 @@ TEST_F(Dhcpv6SrvTest, SolicitBasic) {
// check that IA_NA was returned and that there's an address included
boost::shared_ptr<Option6IAAddr> addr = checkIA_NA(reply, 234, subnet_->getT1(),
subnet_->getT2());
subnet_->getT2());
ASSERT_TRUE(addr);
// Check that the assigned address is indeed from the configured pool
@ -2333,9 +2333,9 @@ TEST_F(Dhcpv6SrvTest, testUnicast) {
TEST_F(Dhcpv6SrvTest, selectSubnetAddr) {
NakedDhcpv6Srv srv(0);
Subnet6Ptr subnet1(new Subnet6(IOAddress("2001:db8:1::"), 48, 1, 2, 3, 4));
Subnet6Ptr subnet2(new Subnet6(IOAddress("2001:db8:2::"), 48, 1, 2, 3, 4));
Subnet6Ptr subnet3(new Subnet6(IOAddress("2001:db8:3::"), 48, 1, 2, 3, 4));
auto subnet1 = Subnet6::create(IOAddress("2001:db8:1::"), 48, 1, 2, 3, 4);
auto subnet2 = Subnet6::create(IOAddress("2001:db8:2::"), 48, 1, 2, 3, 4);
auto subnet3 = Subnet6::create(IOAddress("2001:db8:3::"), 48, 1, 2, 3, 4);
// CASE 1: We have only one subnet defined and we received local traffic.
// The only available subnet used to be picked, but not anymore
@ -2405,9 +2405,9 @@ TEST_F(Dhcpv6SrvTest, selectSubnetAddr) {
TEST_F(Dhcpv6SrvTest, selectSubnetIface) {
NakedDhcpv6Srv srv(0);
Subnet6Ptr subnet1(new Subnet6(IOAddress("2001:db8:1::"), 48, 1, 2, 3, 4));
Subnet6Ptr subnet2(new Subnet6(IOAddress("2001:db8:2::"), 48, 1, 2, 3, 4));
Subnet6Ptr subnet3(new Subnet6(IOAddress("2001:db8:3::"), 48, 1, 2, 3, 4));
auto subnet1 = Subnet6::create(IOAddress("2001:db8:1::"), 48, 1, 2, 3, 4);
auto subnet2 = Subnet6::create(IOAddress("2001:db8:2::"), 48, 1, 2, 3, 4);
auto subnet3 = Subnet6::create(IOAddress("2001:db8:3::"), 48, 1, 2, 3, 4);
subnet1->setIface("eth0");
subnet3->setIface("wifi1");
@ -2470,9 +2470,9 @@ TEST_F(Dhcpv6SrvTest, selectSubnetIface) {
TEST_F(Dhcpv6SrvTest, selectSubnetRelayLinkaddr) {
NakedDhcpv6Srv srv(0);
Subnet6Ptr subnet1(new Subnet6(IOAddress("2001:db8:1::"), 48, 1, 2, 3, 4));
Subnet6Ptr subnet2(new Subnet6(IOAddress("2001:db8:2::"), 48, 1, 2, 3, 4));
Subnet6Ptr subnet3(new Subnet6(IOAddress("2001:db8:3::"), 48, 1, 2, 3, 4));
auto subnet1 = Subnet6::create(IOAddress("2001:db8:1::"), 48, 1, 2, 3, 4);
auto subnet2 = Subnet6::create(IOAddress("2001:db8:2::"), 48, 1, 2, 3, 4);
auto subnet3 = Subnet6::create(IOAddress("2001:db8:3::"), 48, 1, 2, 3, 4);
Pkt6::RelayInfo relay;
relay.linkaddr_ = IOAddress("2001:db8:2::1234");
@ -2593,9 +2593,9 @@ TEST_F(Dhcpv6SrvTest, selectSubnetRelayLinkaddr) {
TEST_F(Dhcpv6SrvTest, selectSubnetRelayInterfaceId) {
NakedDhcpv6Srv srv(0);
Subnet6Ptr subnet1(new Subnet6(IOAddress("2001:db8:1::"), 48, 1, 2, 3, 4));
Subnet6Ptr subnet2(new Subnet6(IOAddress("2001:db8:2::"), 48, 1, 2, 3, 4));
Subnet6Ptr subnet3(new Subnet6(IOAddress("2001:db8:3::"), 48, 1, 2, 3, 4));
auto subnet1 = Subnet6::create(IOAddress("2001:db8:1::"), 48, 1, 2, 3, 4);
auto subnet2 = Subnet6::create(IOAddress("2001:db8:2::"), 48, 1, 2, 3, 4);
auto subnet3 = Subnet6::create(IOAddress("2001:db8:3::"), 48, 1, 2, 3, 4);
subnet1->setInterfaceId(generateInterfaceId("relay1"));
subnet2->setInterfaceId(generateInterfaceId("relay2"));

View File

@ -56,8 +56,8 @@ BaseServerTest::~BaseServerTest() {
Dhcpv6SrvTest::Dhcpv6SrvTest()
: NakedDhcpv6SrvTest(), srv_(0), multi_threading_(false) {
subnet_ = isc::dhcp::Subnet6Ptr(new isc::dhcp::Subnet6(isc::asiolink::IOAddress("2001:db8:1::"),
48, 1000, 2000, 3000, 4000));
subnet_ = Subnet6::create(isc::asiolink::IOAddress("2001:db8:1::"),
48, 1000, 2000, 3000, 4000);
subnet_->setIface("eth0");
pool_ = isc::dhcp::Pool6Ptr(new isc::dhcp::Pool6(isc::dhcp::Lease::TYPE_NA,
@ -272,8 +272,8 @@ Dhcpv6SrvTest::testRenewBasic(Lease::Type type,
// and then be reused.
if (expire_before_renew) {
CfgMgr::instance().clear();
subnet_.reset(new Subnet6(IOAddress("2001:db8:1:1::"),
48, 1000, 2000, 3000, 4000));
subnet_ = Subnet6::create(IOAddress("2001:db8:1:1::"),
48, 1000, 2000, 3000, 4000);
subnet_->setIface("eth0");
pool_.reset(new Pool6(Lease::TYPE_NA, existing, existing));
subnet_->addPool(pool_);

View File

@ -1376,8 +1376,7 @@ TEST_F(FqdnDhcpv6SrvTest, processRequestReuseExpiredLease) {
// exactly one address. This address will be handed out to the
// client, will get expired and then be reused.
CfgMgr::instance().clear();
subnet_ = Subnet6Ptr(new Subnet6(IOAddress("2001:db8:1:1::"), 56, 1, 2,
3, 4));
subnet_ = Subnet6::create(IOAddress("2001:db8:1:1::"), 56, 1, 2, 3, 4);
subnet_->setIface("eth0");
subnet_->setDdnsSendUpdates(true);

View File

@ -94,35 +94,11 @@ AllocEngine::AllocEngine(AllocType, uint64_t attempts, bool ipv6)
: attempts_(attempts), incomplete_v4_reclamations_(0),
incomplete_v6_reclamations_(0) {
// Choose the basic (normal address) lease type
Lease::Type basic_type = ipv6 ? Lease::TYPE_NA : Lease::TYPE_V4;
// Initialize normal address allocators
allocators_[basic_type] = AllocatorPtr(new IterativeAllocator(basic_type));
// If this is IPv6 allocation engine, initialize also temporary addrs
// and prefixes
if (ipv6) {
allocators_[Lease::TYPE_TA] = AllocatorPtr(new IterativeAllocator(Lease::TYPE_TA));
allocators_[Lease::TYPE_PD] = AllocatorPtr(new IterativeAllocator(Lease::TYPE_PD));
}
// Register hook points
hook_index_lease4_select_ = Hooks.hook_index_lease4_select_;
hook_index_lease6_select_ = Hooks.hook_index_lease6_select_;
}
AllocatorPtr
AllocEngine::getAllocator(Lease::Type type) {
std::map<Lease::Type, AllocatorPtr>::const_iterator alloc = allocators_.find(type);
if (alloc == allocators_.end()) {
isc_throw(BadValue, "No allocator initialized for pool type "
<< Lease::typeToText(type));
}
return (alloc->second);
}
} // end of namespace isc::dhcp
} // end of namespace isc
@ -649,13 +625,6 @@ AllocEngine::allocateLeases6(ClientContext6& ctx) {
Lease6Collection
AllocEngine::allocateUnreservedLeases6(ClientContext6& ctx) {
AllocatorPtr allocator = getAllocator(ctx.currentIA().type_);
if (!allocator) {
isc_throw(InvalidOperation, "No allocator specified for "
<< Lease6::typeToText(ctx.currentIA().type_));
}
Lease6Collection leases;
IOAddress hint = IOAddress::IPV6_ZERO_ADDRESS();
@ -864,8 +833,8 @@ AllocEngine::allocateUnreservedLeases6(ClientContext6& ctx) {
++total_attempts;
IOAddress candidate = allocator->pickAddress(subnet,
classes,
auto allocator = subnet->getAllocator(ctx.currentIA().type_);
IOAddress candidate = allocator->pickAddress(classes,
ctx.duid_,
hint);
// The first step is to find out prefix length. It is 128 for
@ -4128,7 +4097,6 @@ AllocEngine::allocateOrReuseLease4(const IOAddress& candidate, ClientContext4& c
Lease4Ptr
AllocEngine::allocateUnreservedLease4(ClientContext4& ctx) {
Lease4Ptr new_lease;
AllocatorPtr allocator = getAllocator(Lease::TYPE_V4);
Subnet4Ptr subnet = ctx.subnet_;
// Need to check if the subnet belongs to a shared network. If so,
@ -4201,8 +4169,8 @@ AllocEngine::allocateUnreservedLease4(ClientContext4& ctx) {
++total_attempts;
IOAddress candidate = allocator->pickAddress(subnet,
classes,
auto allocator = subnet->getAllocator(Lease::TYPE_V4);
IOAddress candidate = allocator->pickAddress(classes,
client_id,
ctx.requested_address_);
// First check for reservation when it is the choice.

View File

@ -73,23 +73,8 @@ public:
/// @brief Destructor.
virtual ~AllocEngine() { }
/// @brief Returns allocator for a given pool type
///
/// @param type type of pool (V4, IA, TA or PD)
///
/// @throw BadValue if allocator for a given type is missing
///
/// @return pointer to allocator handling a given resource types
AllocatorPtr getAllocator(Lease::Type type);
private:
/// @brief A pointer to currently used allocator
///
/// For IPv4, there will be only one allocator: TYPE_V4
/// For IPv6, there will be 3 allocators: TYPE_NA, TYPE_TA, TYPE_PD
std::map<Lease::Type, AllocatorPtr> allocators_;
/// @brief number of attempts before we give up lease allocation (0=unlimited)
uint64_t attempts_;

View File

@ -10,15 +10,25 @@
#include <asiolink/io_address.h>
#include <dhcp/classify.h>
#include <dhcp/duid.h>
#include <dhcpsrv/subnet.h>
#include <exceptions/exceptions.h>
#include <dhcpsrv/lease.h>
#include <util/multi_threading_mgr.h>
#include <boost/shared_ptr.hpp>
#include <boost/weak_ptr.hpp>
#include <mutex>
namespace isc {
namespace dhcp {
/// @brief Forward declaration of a @c Subnet.
///
/// We don't include the subnet header because it would cause a
/// circular dependency.
class Subnet;
/// @brief Weak pointer to the @c Subnet.
typedef boost::weak_ptr<Subnet> WeakSubnetPtr;
/// An exception that is thrown when allocation module fails (e.g. due to
/// lack of available addresses)
class AllocFailed : public Exception {
@ -37,10 +47,31 @@ public:
///
/// This is an abstract class that should not be used directly, but rather
/// specialized implementations should be used instead.
///
/// This class holds a weak pointer to the subnet owning it because
/// it must not exist without the subnet. Also, it can't hold a shared
/// pointer to the subnet because it would cause a circular dependency
/// between the two.
class Allocator {
public:
/// @brief Picks a address or a delegated prefix
/// @brief Constructor
///
/// Specifies which type of leases this allocator will assign.
///
/// @param type specifies pool type (addresses, temporary addresses
/// or prefixes).
/// @param subnet weak pointer to the subnet owning the allocator.
Allocator(Lease::Type type, const WeakSubnetPtr& subnet)
: pool_type_(type),
subnet_(subnet) {
}
/// @brief Virtual destructor
virtual ~Allocator() {
}
/// @brief Picks an address or a delegated prefix.
///
/// This method returns one address from the available pools in the
/// specified subnet. It should not check if the address is used or
@ -58,58 +89,59 @@ public:
///
/// Pools which are not allowed for client classes are skipped.
///
/// @param subnet next address will be returned from pool of that subnet
/// @param client_classes list of classes client belongs to
/// @param duid Client's DUID
/// @param hint Client's hint
///
/// @return the next address.
virtual isc::asiolink::IOAddress
pickAddress(const SubnetPtr& subnet,
const ClientClasses& client_classes,
pickAddress(const ClientClasses& client_classes,
const DuidPtr& duid,
const asiolink::IOAddress& hint) {
if (util::MultiThreadingMgr::instance().getMode()) {
std::lock_guard<std::mutex> lock(mutex_);
return pickAddressInternal(subnet, client_classes, duid, hint);
return pickAddressInternal(client_classes, duid, hint);
} else {
return pickAddressInternal(subnet, client_classes, duid, hint);
return pickAddressInternal(client_classes, duid, hint);
}
}
/// @brief Default constructor
///
/// Specifies which type of leases this allocator will assign
/// @param pool_type specifies pool type (addresses, temp. addr or prefixes)
Allocator(Lease::Type pool_type) : pool_type_(pool_type) {
}
private:
/// @brief Virtual destructor
virtual ~Allocator() {
}
/// @brief Picks an address or delegated prefix.
///
/// Internal thread-unsafe implementation of the @c pickAddress.
/// Derived classes must provide their specific implementations of
/// this function.
///
/// @param client_classes list of classes client belongs to
/// @param duid Client's DUID
/// @param hint Client's hint
///
/// @return the next address.
virtual isc::asiolink::IOAddress
pickAddressInternal(const ClientClasses& client_classes,
const DuidPtr& duid,
const isc::asiolink::IOAddress& hint) = 0;
private:
virtual isc::asiolink::IOAddress
pickAddressInternal(const SubnetPtr& subnet,
const ClientClasses& client_classes,
const DuidPtr& duid,
const isc::asiolink::IOAddress& hint) = 0;
protected:
protected:
/// @brief Defines pool type allocation
Lease::Type pool_type_;
/// @brief Defines pool type allocation
Lease::Type pool_type_;
/// @brief Weak pointer to the subnet owning the allocator.
WeakSubnetPtr subnet_;
private:
private:
/// @brief The mutex to protect the allocated lease
std::mutex mutex_;
/// @brief The mutex to protect the allocated lease.
std::mutex mutex_;
};
/// defines a pointer to allocator
/// Defines a pointer to an allocator.
typedef boost::shared_ptr<Allocator> AllocatorPtr;
} // end of namespace isc::dhcp
} // end of namespace isc
#endif // ALLOCATOR_H
#endif // ALLOCATOR_H

View File

@ -17,8 +17,9 @@ using namespace std;
namespace isc {
namespace dhcp {
IterativeAllocator::IterativeAllocator(const Lease::Type& lease_type)
: Allocator(lease_type) {
IterativeAllocator::IterativeAllocator(const Lease::Type& lease_type,
const WeakSubnetPtr& subnet)
: Allocator(lease_type, subnet) {
}
isc::asiolink::IOAddress
@ -86,8 +87,7 @@ IterativeAllocator::increaseAddress(const IOAddress& address,
}
IOAddress
IterativeAllocator::pickAddressInternal(const SubnetPtr& subnet,
const ClientClasses& client_classes,
IterativeAllocator::pickAddressInternal(const ClientClasses& client_classes,
const DuidPtr&,
const IOAddress&) {
// Is this prefix allocation?
@ -97,11 +97,11 @@ IterativeAllocator::pickAddressInternal(const SubnetPtr& subnet,
// Let's get the last allocated address. It is usually set correctly,
// but there are times when it won't be (like after removing a pool or
// perhaps restarting the server).
IOAddress last = getSubnetState(subnet)->getLastAllocated(pool_type_);
IOAddress last = getSubnetState()->getLastAllocated(pool_type_);
bool valid = true;
bool retrying = false;
const PoolCollection& pools = subnet->getPools(pool_type_);
const PoolCollection& pools = subnet_.lock()->getPools(pool_type_);
if (pools.empty()) {
isc_throw(AllocFailed, "No pools defined in selected subnet");
@ -156,7 +156,7 @@ IterativeAllocator::pickAddressInternal(const SubnetPtr& subnet,
if (!valid && (last == (*it)->getFirstAddress())) {
// Pool was (re)initialized
getPoolState(*it)->setLastAllocated(last);
getSubnetState(subnet)->setLastAllocated(pool_type_, last);
getSubnetState()->setLastAllocated(pool_type_, last);
return (last);
}
// still can be bogus
@ -186,7 +186,7 @@ IterativeAllocator::pickAddressInternal(const SubnetPtr& subnet,
// the next one is in the pool as well, so we haven't hit
// pool boundary yet
getPoolState(*it)->setLastAllocated(next);
getSubnetState(subnet)->setLastAllocated(pool_type_, next);
getSubnetState()->setLastAllocated(pool_type_, next);
return (next);
}
@ -209,12 +209,13 @@ IterativeAllocator::pickAddressInternal(const SubnetPtr& subnet,
// ok to access first element directly. We checked that pools is non-empty
last = getPoolState(*first)->getLastAllocated();
getPoolState(*first)->setLastAllocated(last);
getSubnetState(subnet)->setLastAllocated(pool_type_, last);
getSubnetState()->setLastAllocated(pool_type_, last);
return (last);
}
SubnetIterativeAllocationStatePtr
IterativeAllocator::getSubnetState(const SubnetPtr& subnet) const {
IterativeAllocator::getSubnetState() const {
auto subnet = subnet_.lock();
if (!subnet->getAllocationState()) {
subnet->setAllocationState(SubnetIterativeAllocationState::create(subnet));
}

View File

@ -27,23 +27,22 @@ public:
/// @brief Constructor.
///
/// Does not do anything.
///
/// @param lease_type specifies the type of allocated leases.
IterativeAllocator(const Lease::Type& lease_type);
/// @param subnet weak pointer to the subnet owning the allocator.
IterativeAllocator(const Lease::Type& lease_type, const WeakSubnetPtr& subnet);
private:
/// @brief Returns the next address from the pools in the subnet.
///
/// @param subnet next address will be returned from pool of that subnet.
/// Internal thread-unsafe implementation of the @c pickAddress.
///
/// @param client_classes list of classes client belongs to.
/// @param duid client DUID (ignored).
/// @param hint client hint (ignored).
///
/// @return next offered address.
virtual asiolink::IOAddress pickAddressInternal(const SubnetPtr& subnet,
const ClientClasses& client_classes,
virtual asiolink::IOAddress pickAddressInternal(const ClientClasses& client_classes,
const DuidPtr& duid,
const asiolink::IOAddress& hint);
@ -51,7 +50,7 @@ private:
///
/// @param subnet subnet instance.
/// @return allocation state instance for the subnet.
SubnetIterativeAllocationStatePtr getSubnetState(const SubnetPtr& subnet) const;
SubnetIterativeAllocationStatePtr getSubnetState() const;
/// @brief Convenience function returning pool allocation state instance.
///

View File

@ -739,9 +739,9 @@ Subnet4ConfigParser::initSubnet(data::ConstElementPtr params,
SubnetID subnet_id = static_cast<SubnetID>(getInteger(params, "id", 0,
subnet_id_max));
Subnet4Ptr subnet4(new Subnet4(addr, len, Triplet<uint32_t>(),
auto subnet4 = Subnet4::create(addr, len, Triplet<uint32_t>(),
Triplet<uint32_t>(), Triplet<uint32_t>(),
subnet_id));
subnet_id);
subnet_ = subnet4;
// Move from reservation mode to new reservations flags.
@ -1265,12 +1265,12 @@ Subnet6ConfigParser::initSubnet(data::ConstElementPtr params,
Triplet<uint32_t> pref = parseIntTriplet(params, "preferred-lifetime");
// Create a new subnet.
Subnet6* subnet6 = new Subnet6(addr, len, Triplet<uint32_t>(),
auto subnet6 = Subnet6::create(addr, len, Triplet<uint32_t>(),
Triplet<uint32_t>(),
pref,
Triplet<uint32_t>(),
subnet_id);
subnet_.reset(subnet6);
subnet_ = subnet6;
// Move from reservation mode to new reservations flags.
ElementPtr mutable_params;

View File

@ -1,4 +1,4 @@
// Copyright (C) 2012-2021 Internet Systems Consortium, Inc. ("ISC")
// Copyright (C) 2012-2022 Internet Systems Consortium, Inc. ("ISC")
//
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
@ -9,6 +9,7 @@
#include <asiolink/io_address.h>
#include <asiolink/addr_utilities.h>
#include <dhcp/option_space.h>
#include <dhcpsrv/iterative_allocator.h>
#include <dhcpsrv/shared_network.h>
#include <dhcpsrv/subnet.h>
#include <util/multi_threading_mgr.h>
@ -192,7 +193,6 @@ Subnet4::Subnet4(const IOAddress& prefix, uint8_t length,
isc_throw(BadValue, "Non IPv4 prefix " << prefix.toText()
<< " specified in subnet4");
}
// Timers.
setT1(t1);
setT2(t2);
@ -207,6 +207,10 @@ Subnet4::create(const IOAddress& prefix, uint8_t length,
const SubnetID id) {
Subnet4Ptr subnet = boost::make_shared<Subnet4>
(prefix, length, t1, t2, valid_lifetime, id);
subnet->setAllocator(Lease::TYPE_V4,
boost::make_shared<IterativeAllocator>
(Lease::TYPE_V4, subnet));
return (subnet);
}
@ -296,6 +300,22 @@ PoolCollection& Subnet::getPoolsWritable(Lease::Type type) {
}
}
AllocatorPtr
Subnet::getAllocator(Lease::Type type) const {
auto alloc = allocators_.find(type);
if (alloc == allocators_.end()) {
isc_throw(BadValue, "no allocator initialized for pool type "
<< Lease::typeToText(type));
}
return (alloc->second);
}
void
Subnet::setAllocator(Lease::Type type, const AllocatorPtr& allocator) {
allocators_[type] = allocator;
}
const PoolPtr Subnet::getPool(Lease::Type type, const isc::asiolink::IOAddress& hint,
bool anypool /* true */) const {
// check if the type is valid (and throw if it isn't)
@ -562,6 +582,16 @@ Subnet6::create(const IOAddress& prefix, uint8_t length,
const SubnetID id) {
Subnet6Ptr subnet = boost::make_shared<Subnet6>
(prefix, length, t1, t2, preferred_lifetime, valid_lifetime, id);
subnet->setAllocator(Lease::TYPE_NA,
boost::make_shared<IterativeAllocator>
(Lease::TYPE_NA, subnet));
subnet->setAllocator(Lease::TYPE_TA,
boost::make_shared<IterativeAllocator>
(Lease::TYPE_TA, subnet));
subnet->setAllocator(Lease::TYPE_PD,
boost::make_shared<IterativeAllocator>
(Lease::TYPE_PD, subnet));
return (subnet);
}

View File

@ -11,6 +11,7 @@
#include <cc/data.h>
#include <cc/user_context.h>
#include <dhcp/option_space_container.h>
#include <dhcpsrv/allocator.h>
#include <dhcpsrv/allocation_state.h>
#include <dhcpsrv/lease.h>
#include <dhcpsrv/network.h>
@ -264,6 +265,27 @@ public:
/// @return a collection of all pools
PoolCollection& getPoolsWritable(Lease::Type type);
/// @brief Returns lease allocator instance.
///
/// An allocator is responsible for selecting leases from the subnet's
/// pools. Each subnet has one allocator common for all pools belonging
/// to the subnet. The allocation engine uses this function to get the
/// current subnet allocator and uses it to select and offer an address.
///
/// @param type lease type for which the allocator instance should be
/// returned.
/// @return Allocator instance.
AllocatorPtr getAllocator(Lease::Type type) const;
/// @brief Sets new allocator instance.
///
/// If the server is configured to use a different allocator for the
/// subnet, it can set the current allocator with this function.
///
/// @param type lease type for which the allocator is set.
/// @param allocator new allocator instance.
void setAllocator(Lease::Type type, const AllocatorPtr& allocator);
/// @brief Returns subnet-specific allocation state.
///
/// The actual type of the state depends on the allocator type.
@ -406,6 +428,9 @@ protected:
/// @brief Shared network name.
std::string shared_network_name_;
/// @brief Lease allocators used by the subnet.
std::map<Lease::Type, AllocatorPtr> allocators_;
};
/// @brief A generic pointer to either Subnet4 or Subnet6 object
@ -452,6 +477,10 @@ public:
/// unloaded before the object is destroyed. This ensures that the
/// ownership of the object by the Kea process is retained.
///
/// It associates the subnet with the default, iterative, allocator.
/// Therefore, using this function should be preferred over the
/// constructor whenever the subnet needs a default allocator.
///
/// @param prefix Subnet4 prefix
/// @param length prefix length
/// @param t1 renewal timer (in seconds)
@ -602,6 +631,10 @@ public:
/// unloaded before the object is destroyed. This ensures that the
/// ownership of the object by the Kea process is retained.
///
/// It associates the subnet with the default, iterative, allocator.
/// Therefore, using this function should be preferred over the
/// constructor whenever the subnet needs a default allocator.
///
/// @param prefix Subnet6 prefix
/// @param length prefix length
/// @param t1 renewal timer (in seconds)

View File

@ -50,14 +50,6 @@ TEST_F(AllocEngine4Test, constructor) {
// 100 attempts to pick up a lease
ASSERT_NO_THROW(x.reset(new AllocEngine(AllocEngine::ALLOC_ITERATIVE, 100,
false)));
// There should be V4 allocator
ASSERT_TRUE(x->getAllocator(Lease::TYPE_V4));
// Check that allocators for V6 stuff are not created
EXPECT_THROW(x->getAllocator(Lease::TYPE_NA), BadValue);
EXPECT_THROW(x->getAllocator(Lease::TYPE_TA), BadValue);
EXPECT_THROW(x->getAllocator(Lease::TYPE_PD), BadValue);
}
// This test checks if two simple IPv4 allocations succeed and that the
@ -862,7 +854,7 @@ TEST_F(AllocEngine4Test, smallPool4) {
cfg_mgr.clear();
// Create configuration similar to other tests, but with a single address pool
subnet_ = Subnet4Ptr(new Subnet4(IOAddress("192.0.2.0"), 24, 1, 2, 3));
subnet_ = Subnet4::create(IOAddress("192.0.2.0"), 24, 1, 2, 3);
pool_ = Pool4Ptr(new Pool4(addr, addr)); // just a single address
subnet_->addPool(pool_);
cfg_mgr.getStagingCfg()->getCfgSubnets4()->add(subnet_);
@ -906,7 +898,7 @@ TEST_F(AllocEngine4Test, outOfAddresses4) {
cfg_mgr.clear();
// Create configuration similar to other tests, but with a single address pool
subnet_ = Subnet4Ptr(new Subnet4(IOAddress("192.0.2.0"), 24, 1, 2, 3));
subnet_ = Subnet4::create(IOAddress("192.0.2.0"), 24, 1, 2, 3);
pool_ = Pool4Ptr(new Pool4(addr, addr)); // just a single address
subnet_->addPool(pool_);
cfg_mgr.getStagingCfg()->getCfgSubnets4()->add(subnet_);
@ -961,8 +953,8 @@ public:
// Create two subnets, each with a single address pool. The first subnet
// has only one address in its address pool to make it easier to simulate
// address exhaustion.
subnet1_.reset(new Subnet4(IOAddress("192.0.2.0"), 24, 1, 2, 3, SubnetID(1)));
subnet2_.reset(new Subnet4(IOAddress("10.1.2.0"), 24, 1, 2, 3, SubnetID(2)));
subnet1_ = Subnet4::create(IOAddress("192.0.2.0"), 24, 1, 2, 3, SubnetID(1));
subnet2_ = Subnet4::create(IOAddress("10.1.2.0"), 24, 1, 2, 3, SubnetID(2));
pool1_.reset(new Pool4(IOAddress("192.0.2.17"), IOAddress("192.0.2.17")));
pool2_.reset(new Pool4(IOAddress("10.1.2.5"), IOAddress("10.1.2.100")));
@ -1621,7 +1613,7 @@ TEST_F(AllocEngine4Test, discoverReuseExpiredLease4) {
cfg_mgr.clear();
// Create configuration similar to other tests, but with a single address pool
subnet_ = Subnet4Ptr(new Subnet4(IOAddress("192.0.2.0"), 24, 1, 2, 3));
subnet_ = Subnet4::create(IOAddress("192.0.2.0"), 24, 1, 2, 3);
pool_ = Pool4Ptr(new Pool4(addr, addr)); // just a single address
subnet_->addPool(pool_);
cfg_mgr.getStagingCfg()->getCfgSubnets4()->add(subnet_);
@ -1758,7 +1750,7 @@ TEST_F(AllocEngine4Test, discoverReuseDeclinedLease4) {
IOAddress addr("192.0.2.15");
CfgMgr& cfg_mgr = CfgMgr::instance();
cfg_mgr.clear();
subnet_ = Subnet4Ptr(new Subnet4(IOAddress("192.0.2.0"), 24, 1, 2, 3));
subnet_ = Subnet4::create(IOAddress("192.0.2.0"), 24, 1, 2, 3);
pool_ = Pool4Ptr(new Pool4(addr, addr)); // just a single address
subnet_->addPool(pool_);
cfg_mgr.getStagingCfg()->getCfgSubnets4()->add(subnet_);
@ -1796,7 +1788,7 @@ TEST_F(AllocEngine4Test, discoverReuseDeclinedLease4Stats) {
IOAddress addr("192.0.2.15");
CfgMgr& cfg_mgr = CfgMgr::instance();
cfg_mgr.clear();
subnet_ = Subnet4Ptr(new Subnet4(IOAddress("192.0.2.0"), 24, 1, 2, 3));
subnet_ = Subnet4::create(IOAddress("192.0.2.0"), 24, 1, 2, 3);
pool_ = Pool4Ptr(new Pool4(addr, addr)); // just a single address
subnet_->addPool(pool_);
cfg_mgr.getStagingCfg()->getCfgSubnets4()->add(subnet_);
@ -1837,7 +1829,7 @@ TEST_F(AllocEngine4Test, requestReuseDeclinedLease4) {
IOAddress addr("192.0.2.15");
CfgMgr& cfg_mgr = CfgMgr::instance();
cfg_mgr.clear();
subnet_ = Subnet4Ptr(new Subnet4(IOAddress("192.0.2.0"), 24, 1, 2, 3));
subnet_ = Subnet4::create(IOAddress("192.0.2.0"), 24, 1, 2, 3);
pool_ = Pool4Ptr(new Pool4(addr, addr)); // just a single address
subnet_->addPool(pool_);
cfg_mgr.getStagingCfg()->getCfgSubnets4()->add(subnet_);
@ -1873,7 +1865,7 @@ TEST_F(AllocEngine4Test, requestReuseDeclinedLease4Stats) {
IOAddress addr("192.0.2.15");
CfgMgr& cfg_mgr = CfgMgr::instance();
cfg_mgr.clear();
subnet_ = Subnet4Ptr(new Subnet4(IOAddress("192.0.2.0"), 24, 1, 2, 3));
subnet_ = Subnet4::create(IOAddress("192.0.2.0"), 24, 1, 2, 3);
pool_ = Pool4Ptr(new Pool4(addr, addr)); // just a single address
subnet_->addPool(pool_);
cfg_mgr.getStagingCfg()->getCfgSubnets4()->add(subnet_);

View File

@ -61,18 +61,6 @@ TEST_F(AllocEngine6Test, constructor) {
boost::scoped_ptr<AllocEngine> x;
ASSERT_NO_THROW(x.reset(new AllocEngine(AllocEngine::ALLOC_ITERATIVE, 100, true)));
// Check that allocator for normal addresses is created
ASSERT_TRUE(x->getAllocator(Lease::TYPE_NA));
// Check that allocator for temporary address is created
ASSERT_TRUE(x->getAllocator(Lease::TYPE_TA));
// Check that allocator for prefixes is created
ASSERT_TRUE(x->getAllocator(Lease::TYPE_PD));
// There should be no V4 allocator
EXPECT_THROW(x->getAllocator(Lease::TYPE_V4), BadValue);
}
// This test checks if two simple IPv6 allocations succeed and that the
@ -300,11 +288,10 @@ TEST_F(AllocEngine6Test, allocateAddress6Nulls) {
// This test verifies that the allocator picks addresses that belong to the
// pool
TEST_F(AllocEngine6Test, IterativeAllocator) {
boost::scoped_ptr<Allocator> alloc(new NakedIterativeAllocator(Lease::TYPE_NA));
boost::scoped_ptr<Allocator> alloc(new NakedIterativeAllocator(Lease::TYPE_NA, subnet_));
for (int i = 0; i < 1000; ++i) {
IOAddress candidate = alloc->pickAddress(subnet_, cc_,
duid_, IOAddress("::"));
IOAddress candidate = alloc->pickAddress(cc_, duid_, IOAddress("::"));
EXPECT_TRUE(subnet_->inPool(Lease::TYPE_NA, candidate));
}
}
@ -312,7 +299,7 @@ TEST_F(AllocEngine6Test, IterativeAllocator) {
// This test verifies that the allocator picks addresses that belong to the
// pool using classification
TEST_F(AllocEngine6Test, IterativeAllocator_class) {
boost::scoped_ptr<Allocator> alloc(new NakedIterativeAllocator(Lease::TYPE_NA));
boost::scoped_ptr<Allocator> alloc(new NakedIterativeAllocator(Lease::TYPE_NA, subnet_));
// Restrict pool_ to the foo class. Add a second pool with bar class.
pool_->allowClientClass("foo");
@ -325,16 +312,13 @@ TEST_F(AllocEngine6Test, IterativeAllocator_class) {
cc_.insert("bar");
for (int i = 0; i < 1000; ++i) {
IOAddress candidate = alloc->pickAddress(subnet_, cc_,
duid_, IOAddress("::"));
IOAddress candidate = alloc->pickAddress(cc_, duid_, IOAddress("::"));
EXPECT_TRUE(subnet_->inPool(Lease::TYPE_NA, candidate));
EXPECT_TRUE(subnet_->inPool(Lease::TYPE_NA, candidate, cc_));
}
}
TEST_F(AllocEngine6Test, IterativeAllocatorAddrStep) {
NakedIterativeAllocator alloc(Lease::TYPE_NA);
subnet_->delPools(Lease::TYPE_NA); // Get rid of default pool
Pool6Ptr pool1(new Pool6(Lease::TYPE_NA, IOAddress("2001:db8:1::1"),
@ -347,39 +331,39 @@ TEST_F(AllocEngine6Test, IterativeAllocatorAddrStep) {
subnet_->addPool(pool2);
subnet_->addPool(pool3);
NakedIterativeAllocator alloc(Lease::TYPE_NA, subnet_);
// Let's check the first pool (5 addresses here)
EXPECT_EQ("2001:db8:1::1",
alloc.pickAddress(subnet_, cc_, duid_, IOAddress("::")).toText());
alloc.pickAddress(cc_, duid_, IOAddress("::")).toText());
EXPECT_EQ("2001:db8:1::2",
alloc.pickAddress(subnet_, cc_, duid_, IOAddress("::")).toText());
alloc.pickAddress(cc_, duid_, IOAddress("::")).toText());
EXPECT_EQ("2001:db8:1::3",
alloc.pickAddress(subnet_, cc_, duid_, IOAddress("::")).toText());
alloc.pickAddress(cc_, duid_, IOAddress("::")).toText());
EXPECT_EQ("2001:db8:1::4",
alloc.pickAddress(subnet_, cc_, duid_, IOAddress("::")).toText());
alloc.pickAddress(cc_, duid_, IOAddress("::")).toText());
EXPECT_EQ("2001:db8:1::5",
alloc.pickAddress(subnet_, cc_, duid_, IOAddress("::")).toText());
alloc.pickAddress(cc_, duid_, IOAddress("::")).toText());
// The second pool is easy - only one address here
EXPECT_EQ("2001:db8:1::100",
alloc.pickAddress(subnet_, cc_, duid_, IOAddress("::")).toText());
alloc.pickAddress(cc_, duid_, IOAddress("::")).toText());
// This is the third and last pool, with 2 addresses in it
EXPECT_EQ("2001:db8:1::105",
alloc.pickAddress(subnet_, cc_, duid_, IOAddress("::")).toText());
alloc.pickAddress(cc_, duid_, IOAddress("::")).toText());
EXPECT_EQ("2001:db8:1::106",
alloc.pickAddress(subnet_, cc_, duid_, IOAddress("::")).toText());
alloc.pickAddress(cc_, duid_, IOAddress("::")).toText());
// We iterated over all addresses and reached to the end of the last pool.
// Let's wrap around and start from the beginning
EXPECT_EQ("2001:db8:1::1",
alloc.pickAddress(subnet_, cc_, duid_, IOAddress("::")).toText());
alloc.pickAddress(cc_, duid_, IOAddress("::")).toText());
EXPECT_EQ("2001:db8:1::2",
alloc.pickAddress(subnet_, cc_, duid_, IOAddress("::")).toText());
alloc.pickAddress(cc_, duid_, IOAddress("::")).toText());
}
TEST_F(AllocEngine6Test, IterativeAllocatorAddrStepInClass) {
NakedIterativeAllocator alloc(Lease::TYPE_NA);
subnet_->delPools(Lease::TYPE_NA); // Get rid of default pool
Pool6Ptr pool1(new Pool6(Lease::TYPE_NA, IOAddress("2001:db8:1::1"),
@ -395,42 +379,42 @@ TEST_F(AllocEngine6Test, IterativeAllocatorAddrStepInClass) {
subnet_->addPool(pool2);
subnet_->addPool(pool3);
NakedIterativeAllocator alloc(Lease::TYPE_NA, subnet_);
// Clients are in foo
cc_.insert("foo");
// Let's check the first pool (5 addresses here)
EXPECT_EQ("2001:db8:1::1",
alloc.pickAddress(subnet_, cc_, duid_, IOAddress("::")).toText());
alloc.pickAddress(cc_, duid_, IOAddress("::")).toText());
EXPECT_EQ("2001:db8:1::2",
alloc.pickAddress(subnet_, cc_, duid_, IOAddress("::")).toText());
alloc.pickAddress(cc_, duid_, IOAddress("::")).toText());
EXPECT_EQ("2001:db8:1::3",
alloc.pickAddress(subnet_, cc_, duid_, IOAddress("::")).toText());
alloc.pickAddress(cc_, duid_, IOAddress("::")).toText());
EXPECT_EQ("2001:db8:1::4",
alloc.pickAddress(subnet_, cc_, duid_, IOAddress("::")).toText());
alloc.pickAddress(cc_, duid_, IOAddress("::")).toText());
EXPECT_EQ("2001:db8:1::5",
alloc.pickAddress(subnet_, cc_, duid_, IOAddress("::")).toText());
alloc.pickAddress(cc_, duid_, IOAddress("::")).toText());
// The second pool is easy - only one address here
EXPECT_EQ("2001:db8:1::100",
alloc.pickAddress(subnet_, cc_, duid_, IOAddress("::")).toText());
alloc.pickAddress(cc_, duid_, IOAddress("::")).toText());
// This is the third and last pool, with 2 addresses in it
EXPECT_EQ("2001:db8:1::105",
alloc.pickAddress(subnet_, cc_, duid_, IOAddress("::")).toText());
alloc.pickAddress(cc_, duid_, IOAddress("::")).toText());
EXPECT_EQ("2001:db8:1::106",
alloc.pickAddress(subnet_, cc_, duid_, IOAddress("::")).toText());
alloc.pickAddress(cc_, duid_, IOAddress("::")).toText());
// We iterated over all addresses and reached to the end of the last pool.
// Let's wrap around and start from the beginning
EXPECT_EQ("2001:db8:1::1",
alloc.pickAddress(subnet_, cc_, duid_, IOAddress("::")).toText());
alloc.pickAddress(cc_, duid_, IOAddress("::")).toText());
EXPECT_EQ("2001:db8:1::2",
alloc.pickAddress(subnet_, cc_, duid_, IOAddress("::")).toText());
alloc.pickAddress(cc_, duid_, IOAddress("::")).toText());
}
TEST_F(AllocEngine6Test, IterativeAllocatorAddrStepOutClass) {
NakedIterativeAllocator alloc(Lease::TYPE_NA);
subnet_->delPools(Lease::TYPE_NA); // Get rid of default pool
Pool6Ptr pool1(new Pool6(Lease::TYPE_NA, IOAddress("2001:db8:1::1"),
@ -445,38 +429,38 @@ TEST_F(AllocEngine6Test, IterativeAllocatorAddrStepOutClass) {
subnet_->addPool(pool2);
subnet_->addPool(pool3);
NakedIterativeAllocator alloc(Lease::TYPE_NA, subnet_);
// Let's check the first pool (5 addresses here)
EXPECT_EQ("2001:db8:1::1",
alloc.pickAddress(subnet_, cc_, duid_, IOAddress("::")).toText());
alloc.pickAddress(cc_, duid_, IOAddress("::")).toText());
EXPECT_EQ("2001:db8:1::2",
alloc.pickAddress(subnet_, cc_, duid_, IOAddress("::")).toText());
alloc.pickAddress(cc_, duid_, IOAddress("::")).toText());
EXPECT_EQ("2001:db8:1::3",
alloc.pickAddress(subnet_, cc_, duid_, IOAddress("::")).toText());
alloc.pickAddress(cc_, duid_, IOAddress("::")).toText());
EXPECT_EQ("2001:db8:1::4",
alloc.pickAddress(subnet_, cc_, duid_, IOAddress("::")).toText());
alloc.pickAddress(cc_, duid_, IOAddress("::")).toText());
EXPECT_EQ("2001:db8:1::5",
alloc.pickAddress(subnet_, cc_, duid_, IOAddress("::")).toText());
alloc.pickAddress(cc_, duid_, IOAddress("::")).toText());
// The second pool is skipped
// This is the third and last pool, with 2 addresses in it
EXPECT_EQ("2001:db8:1::105",
alloc.pickAddress(subnet_, cc_, duid_, IOAddress("::")).toText());
alloc.pickAddress(cc_, duid_, IOAddress("::")).toText());
EXPECT_EQ("2001:db8:1::106",
alloc.pickAddress(subnet_, cc_, duid_, IOAddress("::")).toText());
alloc.pickAddress(cc_, duid_, IOAddress("::")).toText());
// We iterated over all addresses and reached to the end of the last pool.
// Let's wrap around and start from the beginning
EXPECT_EQ("2001:db8:1::1",
alloc.pickAddress(subnet_, cc_, duid_, IOAddress("::")).toText());
alloc.pickAddress(cc_, duid_, IOAddress("::")).toText());
EXPECT_EQ("2001:db8:1::2",
alloc.pickAddress(subnet_, cc_, duid_, IOAddress("::")).toText());
alloc.pickAddress(cc_, duid_, IOAddress("::")).toText());
}
TEST_F(AllocEngine6Test, IterativeAllocatorPrefixStep) {
NakedIterativeAllocator alloc(Lease::TYPE_PD);
subnet_.reset(new Subnet6(IOAddress("2001:db8::"), 32, 1, 2, 3, 4));
subnet_ = Subnet6::create(IOAddress("2001:db8::"), 32, 1, 2, 3, 4);
Pool6Ptr pool1(new Pool6(Lease::TYPE_PD, IOAddress("2001:db8::"), 56, 60));
Pool6Ptr pool2(new Pool6(Lease::TYPE_PD, IOAddress("2001:db8:1::"), 48, 48));
@ -485,6 +469,8 @@ TEST_F(AllocEngine6Test, IterativeAllocatorPrefixStep) {
subnet_->addPool(pool2);
subnet_->addPool(pool3);
NakedIterativeAllocator alloc(Lease::TYPE_PD, subnet_);
// We have a 2001:db8::/48 subnet that has 3 pools defined in it:
// 2001:db8::/56 split into /60 prefixes (16 leases) (or 2001:db8:0:X0::)
// 2001:db8:1::/48 split into a single /48 prefix (just 1 lease)
@ -492,68 +478,66 @@ TEST_F(AllocEngine6Test, IterativeAllocatorPrefixStep) {
// First pool check (Let's check over all 16 leases)
EXPECT_EQ("2001:db8::",
alloc.pickAddress(subnet_, cc_, duid_, IOAddress("::")).toText());
alloc.pickAddress(cc_, duid_, IOAddress("::")).toText());
EXPECT_EQ("2001:db8:0:10::",
alloc.pickAddress(subnet_, cc_, duid_, IOAddress("::")).toText());
alloc.pickAddress(cc_, duid_, IOAddress("::")).toText());
EXPECT_EQ("2001:db8:0:20::",
alloc.pickAddress(subnet_, cc_, duid_, IOAddress("::")).toText());
alloc.pickAddress(cc_, duid_, IOAddress("::")).toText());
EXPECT_EQ("2001:db8:0:30::",
alloc.pickAddress(subnet_, cc_, duid_, IOAddress("::")).toText());
alloc.pickAddress(cc_, duid_, IOAddress("::")).toText());
EXPECT_EQ("2001:db8:0:40::",
alloc.pickAddress(subnet_, cc_, duid_, IOAddress("::")).toText());
alloc.pickAddress(cc_, duid_, IOAddress("::")).toText());
EXPECT_EQ("2001:db8:0:50::",
alloc.pickAddress(subnet_, cc_, duid_, IOAddress("::")).toText());
alloc.pickAddress(cc_, duid_, IOAddress("::")).toText());
EXPECT_EQ("2001:db8:0:60::",
alloc.pickAddress(subnet_, cc_, duid_, IOAddress("::")).toText());
alloc.pickAddress(cc_, duid_, IOAddress("::")).toText());
EXPECT_EQ("2001:db8:0:70::",
alloc.pickAddress(subnet_, cc_, duid_, IOAddress("::")).toText());
alloc.pickAddress(cc_, duid_, IOAddress("::")).toText());
EXPECT_EQ("2001:db8:0:80::",
alloc.pickAddress(subnet_, cc_, duid_, IOAddress("::")).toText());
alloc.pickAddress(cc_, duid_, IOAddress("::")).toText());
EXPECT_EQ("2001:db8:0:90::",
alloc.pickAddress(subnet_, cc_, duid_, IOAddress("::")).toText());
alloc.pickAddress(cc_, duid_, IOAddress("::")).toText());
EXPECT_EQ("2001:db8:0:a0::",
alloc.pickAddress(subnet_, cc_, duid_, IOAddress("::")).toText());
alloc.pickAddress(cc_, duid_, IOAddress("::")).toText());
EXPECT_EQ("2001:db8:0:b0::",
alloc.pickAddress(subnet_, cc_, duid_, IOAddress("::")).toText());
alloc.pickAddress(cc_, duid_, IOAddress("::")).toText());
EXPECT_EQ("2001:db8:0:c0::",
alloc.pickAddress(subnet_, cc_, duid_, IOAddress("::")).toText());
alloc.pickAddress(cc_, duid_, IOAddress("::")).toText());
EXPECT_EQ("2001:db8:0:d0::",
alloc.pickAddress(subnet_, cc_, duid_, IOAddress("::")).toText());
alloc.pickAddress(cc_, duid_, IOAddress("::")).toText());
EXPECT_EQ("2001:db8:0:e0::",
alloc.pickAddress(subnet_, cc_, duid_, IOAddress("::")).toText());
alloc.pickAddress(cc_, duid_, IOAddress("::")).toText());
EXPECT_EQ("2001:db8:0:f0::",
alloc.pickAddress(subnet_, cc_, duid_, IOAddress("::")).toText());
alloc.pickAddress(cc_, duid_, IOAddress("::")).toText());
// Second pool (just one lease here)
EXPECT_EQ("2001:db8:1::",
alloc.pickAddress(subnet_, cc_, duid_, IOAddress("::")).toText());
alloc.pickAddress(cc_, duid_, IOAddress("::")).toText());
// Third pool (256 leases, let's check first and last explicitly and the
// rest over in a pool
EXPECT_EQ("2001:db8:2::",
alloc.pickAddress(subnet_, cc_, duid_, IOAddress("::")).toText());
alloc.pickAddress(cc_, duid_, IOAddress("::")).toText());
for (int i = 1; i < 255; i++) {
stringstream exp;
exp << "2001:db8:2:" << hex << i << dec << "::";
EXPECT_EQ(exp.str(),
alloc.pickAddress(subnet_, cc_, duid_, IOAddress("::")).toText());
alloc.pickAddress(cc_, duid_, IOAddress("::")).toText());
}
EXPECT_EQ("2001:db8:2:ff::",
alloc.pickAddress(subnet_, cc_, duid_, IOAddress("::")).toText());
alloc.pickAddress(cc_, duid_, IOAddress("::")).toText());
// Ok, we've iterated over all prefixes in all pools. We now wrap around.
// We're looping over now (iterating over first pool again)
EXPECT_EQ("2001:db8::",
alloc.pickAddress(subnet_, cc_, duid_, IOAddress("::")).toText());
alloc.pickAddress(cc_, duid_, IOAddress("::")).toText());
EXPECT_EQ("2001:db8:0:10::",
alloc.pickAddress(subnet_, cc_, duid_, IOAddress("::")).toText());
alloc.pickAddress(cc_, duid_, IOAddress("::")).toText());
}
TEST_F(AllocEngine6Test, IterativeAllocatorPrefixStepInClass) {
NakedIterativeAllocator alloc(Lease::TYPE_PD);
subnet_.reset(new Subnet6(IOAddress("2001:db8::"), 32, 1, 2, 3, 4));
subnet_ = Subnet6::create(IOAddress("2001:db8::"), 32, 1, 2, 3, 4);
Pool6Ptr pool1(new Pool6(Lease::TYPE_PD, IOAddress("2001:db8::"), 56, 60));
Pool6Ptr pool2(new Pool6(Lease::TYPE_PD, IOAddress("2001:db8:1::"), 48, 48));
@ -565,6 +549,8 @@ TEST_F(AllocEngine6Test, IterativeAllocatorPrefixStepInClass) {
subnet_->addPool(pool2);
subnet_->addPool(pool3);
NakedIterativeAllocator alloc(Lease::TYPE_PD, subnet_);
// Clients are in foo
cc_.insert("foo");
@ -575,68 +561,66 @@ TEST_F(AllocEngine6Test, IterativeAllocatorPrefixStepInClass) {
// First pool check (Let's check over all 16 leases)
EXPECT_EQ("2001:db8::",
alloc.pickAddress(subnet_, cc_, duid_, IOAddress("::")).toText());
alloc.pickAddress(cc_, duid_, IOAddress("::")).toText());
EXPECT_EQ("2001:db8:0:10::",
alloc.pickAddress(subnet_, cc_, duid_, IOAddress("::")).toText());
alloc.pickAddress(cc_, duid_, IOAddress("::")).toText());
EXPECT_EQ("2001:db8:0:20::",
alloc.pickAddress(subnet_, cc_, duid_, IOAddress("::")).toText());
alloc.pickAddress(cc_, duid_, IOAddress("::")).toText());
EXPECT_EQ("2001:db8:0:30::",
alloc.pickAddress(subnet_, cc_, duid_, IOAddress("::")).toText());
alloc.pickAddress(cc_, duid_, IOAddress("::")).toText());
EXPECT_EQ("2001:db8:0:40::",
alloc.pickAddress(subnet_, cc_, duid_, IOAddress("::")).toText());
alloc.pickAddress(cc_, duid_, IOAddress("::")).toText());
EXPECT_EQ("2001:db8:0:50::",
alloc.pickAddress(subnet_, cc_, duid_, IOAddress("::")).toText());
alloc.pickAddress(cc_, duid_, IOAddress("::")).toText());
EXPECT_EQ("2001:db8:0:60::",
alloc.pickAddress(subnet_, cc_, duid_, IOAddress("::")).toText());
alloc.pickAddress(cc_, duid_, IOAddress("::")).toText());
EXPECT_EQ("2001:db8:0:70::",
alloc.pickAddress(subnet_, cc_, duid_, IOAddress("::")).toText());
alloc.pickAddress(cc_, duid_, IOAddress("::")).toText());
EXPECT_EQ("2001:db8:0:80::",
alloc.pickAddress(subnet_, cc_, duid_, IOAddress("::")).toText());
alloc.pickAddress(cc_, duid_, IOAddress("::")).toText());
EXPECT_EQ("2001:db8:0:90::",
alloc.pickAddress(subnet_, cc_, duid_, IOAddress("::")).toText());
alloc.pickAddress(cc_, duid_, IOAddress("::")).toText());
EXPECT_EQ("2001:db8:0:a0::",
alloc.pickAddress(subnet_, cc_, duid_, IOAddress("::")).toText());
alloc.pickAddress(cc_, duid_, IOAddress("::")).toText());
EXPECT_EQ("2001:db8:0:b0::",
alloc.pickAddress(subnet_, cc_, duid_, IOAddress("::")).toText());
alloc.pickAddress(cc_, duid_, IOAddress("::")).toText());
EXPECT_EQ("2001:db8:0:c0::",
alloc.pickAddress(subnet_, cc_, duid_, IOAddress("::")).toText());
alloc.pickAddress(cc_, duid_, IOAddress("::")).toText());
EXPECT_EQ("2001:db8:0:d0::",
alloc.pickAddress(subnet_, cc_, duid_, IOAddress("::")).toText());
alloc.pickAddress(cc_, duid_, IOAddress("::")).toText());
EXPECT_EQ("2001:db8:0:e0::",
alloc.pickAddress(subnet_, cc_, duid_, IOAddress("::")).toText());
alloc.pickAddress(cc_, duid_, IOAddress("::")).toText());
EXPECT_EQ("2001:db8:0:f0::",
alloc.pickAddress(subnet_, cc_, duid_, IOAddress("::")).toText());
alloc.pickAddress(cc_, duid_, IOAddress("::")).toText());
// Second pool (just one lease here)
EXPECT_EQ("2001:db8:1::",
alloc.pickAddress(subnet_, cc_, duid_, IOAddress("::")).toText());
alloc.pickAddress(cc_, duid_, IOAddress("::")).toText());
// Third pool (256 leases, let's check first and last explicitly and the
// rest over in a pool
EXPECT_EQ("2001:db8:2::",
alloc.pickAddress(subnet_, cc_, duid_, IOAddress("::")).toText());
alloc.pickAddress(cc_, duid_, IOAddress("::")).toText());
for (int i = 1; i < 255; i++) {
stringstream exp;
exp << "2001:db8:2:" << hex << i << dec << "::";
EXPECT_EQ(exp.str(),
alloc.pickAddress(subnet_, cc_, duid_, IOAddress("::")).toText());
alloc.pickAddress(cc_, duid_, IOAddress("::")).toText());
}
EXPECT_EQ("2001:db8:2:ff::",
alloc.pickAddress(subnet_, cc_, duid_, IOAddress("::")).toText());
alloc.pickAddress(cc_, duid_, IOAddress("::")).toText());
// Ok, we've iterated over all prefixes in all pools. We now wrap around.
// We're looping over now (iterating over first pool again)
EXPECT_EQ("2001:db8::",
alloc.pickAddress(subnet_, cc_, duid_, IOAddress("::")).toText());
alloc.pickAddress(cc_, duid_, IOAddress("::")).toText());
EXPECT_EQ("2001:db8:0:10::",
alloc.pickAddress(subnet_, cc_, duid_, IOAddress("::")).toText());
alloc.pickAddress(cc_, duid_, IOAddress("::")).toText());
}
TEST_F(AllocEngine6Test, IterativeAllocatorPrefixStepOutClass) {
NakedIterativeAllocator alloc(Lease::TYPE_PD);
subnet_.reset(new Subnet6(IOAddress("2001:db8::"), 32, 1, 2, 3, 4));
subnet_ = Subnet6::create(IOAddress("2001:db8::"), 32, 1, 2, 3, 4);
Pool6Ptr pool1(new Pool6(Lease::TYPE_PD, IOAddress("2001:db8::"), 56, 60));
Pool6Ptr pool2(new Pool6(Lease::TYPE_PD, IOAddress("2001:db8:1::"), 48, 48));
@ -647,6 +631,8 @@ TEST_F(AllocEngine6Test, IterativeAllocatorPrefixStepOutClass) {
subnet_->addPool(pool2);
subnet_->addPool(pool3);
NakedIterativeAllocator alloc(Lease::TYPE_PD, subnet_);
// We have a 2001:db8::/48 subnet that has 3 pools defined in it:
// 2001:db8::/56 split into /60 prefixes (16 leases) (or 2001:db8:0:X0::)
// 2001:db8:1::/48 split into a single /48 prefix (just 1 lease)
@ -654,68 +640,68 @@ TEST_F(AllocEngine6Test, IterativeAllocatorPrefixStepOutClass) {
// First pool check (Let's check over all 16 leases)
EXPECT_EQ("2001:db8::",
alloc.pickAddress(subnet_, cc_, duid_, IOAddress("::")).toText());
alloc.pickAddress(cc_, duid_, IOAddress("::")).toText());
EXPECT_EQ("2001:db8:0:10::",
alloc.pickAddress(subnet_, cc_, duid_, IOAddress("::")).toText());
alloc.pickAddress(cc_, duid_, IOAddress("::")).toText());
EXPECT_EQ("2001:db8:0:20::",
alloc.pickAddress(subnet_, cc_, duid_, IOAddress("::")).toText());
alloc.pickAddress(cc_, duid_, IOAddress("::")).toText());
EXPECT_EQ("2001:db8:0:30::",
alloc.pickAddress(subnet_, cc_, duid_, IOAddress("::")).toText());
alloc.pickAddress(cc_, duid_, IOAddress("::")).toText());
EXPECT_EQ("2001:db8:0:40::",
alloc.pickAddress(subnet_, cc_, duid_, IOAddress("::")).toText());
alloc.pickAddress(cc_, duid_, IOAddress("::")).toText());
EXPECT_EQ("2001:db8:0:50::",
alloc.pickAddress(subnet_, cc_, duid_, IOAddress("::")).toText());
alloc.pickAddress(cc_, duid_, IOAddress("::")).toText());
EXPECT_EQ("2001:db8:0:60::",
alloc.pickAddress(subnet_, cc_, duid_, IOAddress("::")).toText());
alloc.pickAddress(cc_, duid_, IOAddress("::")).toText());
EXPECT_EQ("2001:db8:0:70::",
alloc.pickAddress(subnet_, cc_, duid_, IOAddress("::")).toText());
alloc.pickAddress(cc_, duid_, IOAddress("::")).toText());
EXPECT_EQ("2001:db8:0:80::",
alloc.pickAddress(subnet_, cc_, duid_, IOAddress("::")).toText());
alloc.pickAddress(cc_, duid_, IOAddress("::")).toText());
EXPECT_EQ("2001:db8:0:90::",
alloc.pickAddress(subnet_, cc_, duid_, IOAddress("::")).toText());
alloc.pickAddress(cc_, duid_, IOAddress("::")).toText());
EXPECT_EQ("2001:db8:0:a0::",
alloc.pickAddress(subnet_, cc_, duid_, IOAddress("::")).toText());
alloc.pickAddress(cc_, duid_, IOAddress("::")).toText());
EXPECT_EQ("2001:db8:0:b0::",
alloc.pickAddress(subnet_, cc_, duid_, IOAddress("::")).toText());
alloc.pickAddress(cc_, duid_, IOAddress("::")).toText());
EXPECT_EQ("2001:db8:0:c0::",
alloc.pickAddress(subnet_, cc_, duid_, IOAddress("::")).toText());
alloc.pickAddress(cc_, duid_, IOAddress("::")).toText());
EXPECT_EQ("2001:db8:0:d0::",
alloc.pickAddress(subnet_, cc_, duid_, IOAddress("::")).toText());
alloc.pickAddress(cc_, duid_, IOAddress("::")).toText());
EXPECT_EQ("2001:db8:0:e0::",
alloc.pickAddress(subnet_, cc_, duid_, IOAddress("::")).toText());
alloc.pickAddress(cc_, duid_, IOAddress("::")).toText());
EXPECT_EQ("2001:db8:0:f0::",
alloc.pickAddress(subnet_, cc_, duid_, IOAddress("::")).toText());
alloc.pickAddress(cc_, duid_, IOAddress("::")).toText());
// The second pool is skipped
// Third pool (256 leases, let's check first and last explicitly and the
// rest over in a pool
EXPECT_EQ("2001:db8:2::",
alloc.pickAddress(subnet_, cc_, duid_, IOAddress("::")).toText());
alloc.pickAddress(cc_, duid_, IOAddress("::")).toText());
for (int i = 1; i < 255; i++) {
stringstream exp;
exp << "2001:db8:2:" << hex << i << dec << "::";
EXPECT_EQ(exp.str(),
alloc.pickAddress(subnet_, cc_, duid_, IOAddress("::")).toText());
alloc.pickAddress(cc_, duid_, IOAddress("::")).toText());
}
EXPECT_EQ("2001:db8:2:ff::",
alloc.pickAddress(subnet_, cc_, duid_, IOAddress("::")).toText());
alloc.pickAddress(cc_, duid_, IOAddress("::")).toText());
// Ok, we've iterated over all prefixes in all pools. We now wrap around.
// We're looping over now (iterating over first pool again)
EXPECT_EQ("2001:db8::",
alloc.pickAddress(subnet_, cc_, duid_, IOAddress("::")).toText());
alloc.pickAddress(cc_, duid_, IOAddress("::")).toText());
EXPECT_EQ("2001:db8:0:10::",
alloc.pickAddress(subnet_, cc_, duid_, IOAddress("::")).toText());
alloc.pickAddress(cc_, duid_, IOAddress("::")).toText());
}
// This test verifies that the iterative allocator can step over addresses
TEST_F(AllocEngine6Test, IterativeAllocatorAddressIncrease) {
NakedIterativeAllocator alloc(Lease::TYPE_NA);
NakedIterativeAllocator alloc(Lease::TYPE_NA, subnet_);
// Let's pick the first address
IOAddress addr1 = alloc.pickAddress(subnet_, cc_, duid_, IOAddress("2001:db8:1::10"));
IOAddress addr1 = alloc.pickAddress(cc_, duid_, IOAddress("2001:db8:1::10"));
// Check that we can indeed pick the first address from the pool
EXPECT_EQ("2001:db8:1::10", addr1.toText());
@ -732,7 +718,7 @@ TEST_F(AllocEngine6Test, IterativeAllocatorAddressIncrease) {
// This test verifies that the allocator can step over prefixes
TEST_F(AllocEngine6Test, IterativeAllocatorPrefixIncrease) {
NakedIterativeAllocator alloc(Lease::TYPE_PD);
NakedIterativeAllocator alloc(Lease::TYPE_PD, subnet_);
// For /128 prefix, increasePrefix should work the same as addressIncrease
checkPrefixIncrease(alloc, "2001:db8::9", 128, "2001:db8::a");
@ -784,7 +770,7 @@ TEST_F(AllocEngine6Test, IterativeAllocatorPrefixIncrease) {
// in all pools in specified subnet. It also must not pick the same address twice
// unless it runs out of pool space and must start over.
TEST_F(AllocEngine6Test, IterativeAllocator_manyPools6) {
NakedIterativeAllocator alloc(Lease::TYPE_NA);
NakedIterativeAllocator alloc(Lease::TYPE_NA, subnet_);
// let's start from 2, as there is 2001:db8:1::10 - 2001:db8:1::20 pool already.
for (int i = 2; i < 10; ++i) {
@ -805,8 +791,7 @@ TEST_F(AllocEngine6Test, IterativeAllocator_manyPools6) {
std::set<IOAddress> generated_addrs;
int cnt = 0;
while (++cnt) {
IOAddress candidate = alloc.pickAddress(subnet_, cc_,
duid_, IOAddress("::"));
IOAddress candidate = alloc.pickAddress(cc_, duid_, IOAddress("::"));
EXPECT_TRUE(subnet_->inPool(Lease::TYPE_NA, candidate));
// One way to easily verify that the iterative allocator really works is
@ -889,7 +874,7 @@ TEST_F(AllocEngine6Test, outOfAddresses6) {
cfg_mgr.clear(); // Get rid of the default test configuration
// Create configuration similar to other tests, but with a single address pool
subnet_ = Subnet6Ptr(new Subnet6(IOAddress("2001:db8:1::"), 56, 1, 2, 3, 4));
subnet_ = Subnet6::create(IOAddress("2001:db8:1::"), 56, 1, 2, 3, 4);
pool_ = Pool6Ptr(new Pool6(Lease::TYPE_NA, addr, addr)); // just a single address
subnet_->addPool(pool_);
cfg_mgr.getStagingCfg()->getCfgSubnets6()->add(subnet_);
@ -1194,7 +1179,7 @@ TEST_F(AllocEngine6Test, requestReuseExpiredLease6) {
cfg_mgr.clear(); // Get rid of the default test configuration
// Create configuration similar to other tests, but with a single address pool
subnet_ = Subnet6Ptr(new Subnet6(IOAddress("2001:db8:1::"), 56, 1, 2, 3, 4));
subnet_ = Subnet6::create(IOAddress("2001:db8:1::"), 56, 1, 2, 3, 4);
pool_ = Pool6Ptr(new Pool6(Lease::TYPE_NA, addr, addr)); // just a single address
subnet_->addPool(pool_);
cfg_mgr.getStagingCfg()->getCfgSubnets6()->add(subnet_);
@ -2672,7 +2657,7 @@ TEST_F(AllocEngine6Test, largePoolOver32bits) {
AllocEngine engine(AllocEngine::ALLOC_ITERATIVE, 0);
// Configure 2001:db8::/32 subnet
subnet_.reset(new Subnet6(IOAddress("2001:db8::"), 32, 1, 2, 3, 4));
subnet_ = Subnet6::create(IOAddress("2001:db8::"), 32, 1, 2, 3, 4);
// Configure the NA pool of /48. So there are 2^80 addresses there. Make
// sure that we still can handle cases where number of available addresses
@ -2924,7 +2909,7 @@ TEST_F(AllocEngine6Test, reuseReclaimedExpiredViaRequest) {
cfg_mgr.clear(); // Get rid of the default test configuration
// Create configuration similar to other tests, but with a single address pool
subnet_ = Subnet6Ptr(new Subnet6(IOAddress("2001:db8:1::"), 56, 1, 2, 3, 4));
subnet_ = Subnet6::create(IOAddress("2001:db8:1::"), 56, 1, 2, 3, 4);
pool_ = Pool6Ptr(new Pool6(Lease::TYPE_NA, addr, addr)); // just a single address
subnet_->addPool(pool_);
cfg_mgr.getStagingCfg()->getCfgSubnets6()->add(subnet_);
@ -2999,8 +2984,8 @@ public:
SharedNetworkAlloc6Test()
:engine_(AllocEngine::ALLOC_ITERATIVE, 0) {
subnet1_.reset(new Subnet6(IOAddress("2001:db8:1::"), 56, 1, 2, 3, 4));
subnet2_.reset(new Subnet6(IOAddress("2001:db8:2::"), 56, 1, 2, 3, 4));
subnet1_ = Subnet6::create(IOAddress("2001:db8:1::"), 56, 1, 2, 3, 4);
subnet2_ = Subnet6::create(IOAddress("2001:db8:2::"), 56, 1, 2, 3, 4);
pool1_.reset(new Pool6(Lease::TYPE_NA, IOAddress("2001:db8:1::1"),
IOAddress("2001:db8:1::1")));
pool2_.reset(new Pool6(Lease::TYPE_NA, IOAddress("2001:db8:2::"),

View File

@ -176,7 +176,7 @@ AllocEngine6Test::initSubnet(const asiolink::IOAddress& subnet,
const uint8_t pd_delegated_length) {
CfgMgr& cfg_mgr = CfgMgr::instance();
subnet_ = Subnet6Ptr(new Subnet6(subnet, 56, 100, 200, 300, 400));
subnet_ = Subnet6::create(subnet, 56, 100, 200, 300, 400);
pool_ = Pool6Ptr(new Pool6(Lease::TYPE_NA, pool_start, pool_end));
subnet_->addPool(pool_);
@ -601,7 +601,7 @@ AllocEngine4Test::initSubnet(const asiolink::IOAddress& pool_start,
const asiolink::IOAddress& pool_end) {
CfgMgr& cfg_mgr = CfgMgr::instance();
subnet_ = Subnet4Ptr(new Subnet4(IOAddress("192.0.2.0"), 24, 1, 2, 3));
subnet_ = Subnet4::create(IOAddress("192.0.2.0"), 24, 1, 2, 3);
pool_ = Pool4Ptr(new Pool4(pool_start, pool_end));
subnet_->addPool(pool_);

View File

@ -63,7 +63,8 @@ class NakedIterativeAllocator : public IterativeAllocator {
public:
/// @brief constructor
/// @param type pool types that will be iterated through
NakedIterativeAllocator(Lease::Type type) : IterativeAllocator(type) {
NakedIterativeAllocator(Lease::Type type, const WeakSubnetPtr& subnet)
: IterativeAllocator(type, subnet) {
}
using IterativeAllocator::increaseAddress;
@ -82,7 +83,6 @@ public:
}
// Expose internal classes for testing purposes
using AllocEngine::getAllocator;
using AllocEngine::updateLease4ExtendedInfo;
/// @brief Wrapper method for invoking AllocEngine4::updateLease4ExtendedInfo().

View File

@ -2804,6 +2804,7 @@ TEST_F(ParseConfigTest, defaultSubnet4) {
EXPECT_FALSE(subnet->getDdnsUseConflictResolution().get());
EXPECT_TRUE(subnet->getAllocationState());
EXPECT_TRUE(subnet->getAllocator(Lease::TYPE_V4));
}
// This test verifies that it is possible to parse an IPv6 subnet for which
@ -2896,6 +2897,11 @@ TEST_F(ParseConfigTest, defaultSubnet6) {
EXPECT_TRUE(subnet->getDdnsUseConflictResolution().unspecified());
EXPECT_FALSE(subnet->getDdnsUseConflictResolution().get());
EXPECT_TRUE(subnet->getAllocationState());
EXPECT_TRUE(subnet->getAllocator(Lease::TYPE_NA));
EXPECT_TRUE(subnet->getAllocator(Lease::TYPE_TA));
EXPECT_TRUE(subnet->getAllocator(Lease::TYPE_PD));
}
// This test verifies that it is possible to parse an IPv4 shared network

View File

@ -24,11 +24,10 @@ using IterativeAllocatorTest4 = AllocEngine4Test;
// This test verifies that the allocator picks addresses that belong to the
// pool
TEST_F(IterativeAllocatorTest4, basic) {
boost::scoped_ptr<Allocator> alloc(new IterativeAllocator(Lease::TYPE_V4));
boost::scoped_ptr<Allocator> alloc(new IterativeAllocator(Lease::TYPE_V4, subnet_));
for (int i = 0; i < 1000; ++i) {
IOAddress candidate = alloc->pickAddress(subnet_, cc_, clientid_,
IOAddress("0.0.0.0"));
IOAddress candidate = alloc->pickAddress(cc_, clientid_, IOAddress("0.0.0.0"));
EXPECT_TRUE(subnet_->inPool(Lease::TYPE_V4, candidate));
}
}
@ -36,7 +35,7 @@ TEST_F(IterativeAllocatorTest4, basic) {
// This test verifies that the allocator picks addresses that belong to the
// pool using classification
TEST_F(IterativeAllocatorTest4, clientClass) {
boost::scoped_ptr<Allocator> alloc(new IterativeAllocator(Lease::TYPE_V4));
boost::scoped_ptr<Allocator> alloc(new IterativeAllocator(Lease::TYPE_V4, subnet_));
// Restrict pool_ to the foo class. Add a second pool with bar class.
pool_->allowClientClass("foo");
@ -49,8 +48,7 @@ TEST_F(IterativeAllocatorTest4, clientClass) {
cc_.insert("bar");
for (int i = 0; i < 1000; ++i) {
IOAddress candidate = alloc->pickAddress(subnet_, cc_, clientid_,
IOAddress("0.0.0.0"));
IOAddress candidate = alloc->pickAddress(cc_, clientid_, IOAddress("0.0.0.0"));
EXPECT_TRUE(subnet_->inPool(Lease::TYPE_V4, candidate));
EXPECT_TRUE(subnet_->inPool(Lease::TYPE_V4, candidate, cc_));
}
@ -60,7 +58,7 @@ TEST_F(IterativeAllocatorTest4, clientClass) {
// in all pools in specified subnet. It also must not pick the same address twice
// unless it runs out of pool space and must start over.
TEST_F(IterativeAllocatorTest4, manyPools) {
IterativeAllocator alloc(Lease::TYPE_V4);
IterativeAllocator alloc(Lease::TYPE_V4, subnet_);
// Let's start from 2, as there is 2001:db8:1::10 - 2001:db8:1::20 pool already.
for (int i = 2; i < 10; ++i) {
@ -82,7 +80,7 @@ TEST_F(IterativeAllocatorTest4, manyPools) {
std::set<IOAddress> generated_addrs;
int cnt = 0;
while (++cnt) {
IOAddress candidate = alloc.pickAddress(subnet_, cc_, clientid_, IOAddress("0.0.0.0"));
IOAddress candidate = alloc.pickAddress(cc_, clientid_, IOAddress("0.0.0.0"));
EXPECT_TRUE(subnet_->inPool(Lease::TYPE_V4, candidate));
// One way to easily verify that the iterative allocator really works is
@ -116,11 +114,10 @@ using IterativeAllocatorTest6 = AllocEngine6Test;
// This test verifies that the allocator picks addresses that belong to the
// pool
TEST_F(IterativeAllocatorTest6, basic) {
boost::scoped_ptr<Allocator> alloc(new NakedIterativeAllocator(Lease::TYPE_NA));
boost::scoped_ptr<Allocator> alloc(new NakedIterativeAllocator(Lease::TYPE_NA, subnet_));
for (int i = 0; i < 1000; ++i) {
IOAddress candidate = alloc->pickAddress(subnet_, cc_,
duid_, IOAddress("::"));
IOAddress candidate = alloc->pickAddress(cc_, duid_, IOAddress("::"));
EXPECT_TRUE(subnet_->inPool(Lease::TYPE_NA, candidate));
}
}
@ -128,7 +125,7 @@ TEST_F(IterativeAllocatorTest6, basic) {
// This test verifies that the allocator picks addresses that belong to the
// pool using classification
TEST_F(IterativeAllocatorTest6, clientClass) {
boost::scoped_ptr<Allocator> alloc(new NakedIterativeAllocator(Lease::TYPE_NA));
boost::scoped_ptr<Allocator> alloc(new NakedIterativeAllocator(Lease::TYPE_NA, subnet_));
// Restrict pool_ to the foo class. Add a second pool with bar class.
pool_->allowClientClass("foo");
@ -141,8 +138,7 @@ TEST_F(IterativeAllocatorTest6, clientClass) {
cc_.insert("bar");
for (int i = 0; i < 1000; ++i) {
IOAddress candidate = alloc->pickAddress(subnet_, cc_,
duid_, IOAddress("::"));
IOAddress candidate = alloc->pickAddress(cc_, duid_, IOAddress("::"));
EXPECT_TRUE(subnet_->inPool(Lease::TYPE_NA, candidate));
EXPECT_TRUE(subnet_->inPool(Lease::TYPE_NA, candidate, cc_));
}
@ -151,8 +147,6 @@ TEST_F(IterativeAllocatorTest6, clientClass) {
// This test verifies that the allocator walks over the addresses in the
// non-contiguous pools.
TEST_F(IterativeAllocatorTest6, addrStep) {
NakedIterativeAllocator alloc(Lease::TYPE_NA);
subnet_->delPools(Lease::TYPE_NA); // Get rid of default pool
Pool6Ptr pool1(new Pool6(Lease::TYPE_NA, IOAddress("2001:db8:1::1"),
@ -165,41 +159,41 @@ TEST_F(IterativeAllocatorTest6, addrStep) {
subnet_->addPool(pool2);
subnet_->addPool(pool3);
NakedIterativeAllocator alloc(Lease::TYPE_NA, subnet_);
// Let's check the first pool (5 addresses here)
EXPECT_EQ("2001:db8:1::1",
alloc.pickAddress(subnet_, cc_, duid_, IOAddress("::")).toText());
alloc.pickAddress(cc_, duid_, IOAddress("::")).toText());
EXPECT_EQ("2001:db8:1::2",
alloc.pickAddress(subnet_, cc_, duid_, IOAddress("::")).toText());
alloc.pickAddress(cc_, duid_, IOAddress("::")).toText());
EXPECT_EQ("2001:db8:1::3",
alloc.pickAddress(subnet_, cc_, duid_, IOAddress("::")).toText());
alloc.pickAddress(cc_, duid_, IOAddress("::")).toText());
EXPECT_EQ("2001:db8:1::4",
alloc.pickAddress(subnet_, cc_, duid_, IOAddress("::")).toText());
alloc.pickAddress(cc_, duid_, IOAddress("::")).toText());
EXPECT_EQ("2001:db8:1::5",
alloc.pickAddress(subnet_, cc_, duid_, IOAddress("::")).toText());
alloc.pickAddress(cc_, duid_, IOAddress("::")).toText());
// The second pool is easy - only one address here
EXPECT_EQ("2001:db8:1::100",
alloc.pickAddress(subnet_, cc_, duid_, IOAddress("::")).toText());
alloc.pickAddress(cc_, duid_, IOAddress("::")).toText());
// This is the third and last pool, with 2 addresses in it
EXPECT_EQ("2001:db8:1::105",
alloc.pickAddress(subnet_, cc_, duid_, IOAddress("::")).toText());
alloc.pickAddress(cc_, duid_, IOAddress("::")).toText());
EXPECT_EQ("2001:db8:1::106",
alloc.pickAddress(subnet_, cc_, duid_, IOAddress("::")).toText());
alloc.pickAddress(cc_, duid_, IOAddress("::")).toText());
// We iterated over all addresses and reached to the end of the last pool.
// Let's wrap around and start from the beginning
EXPECT_EQ("2001:db8:1::1",
alloc.pickAddress(subnet_, cc_, duid_, IOAddress("::")).toText());
alloc.pickAddress(cc_, duid_, IOAddress("::")).toText());
EXPECT_EQ("2001:db8:1::2",
alloc.pickAddress(subnet_, cc_, duid_, IOAddress("::")).toText());
alloc.pickAddress(cc_, duid_, IOAddress("::")).toText());
}
// This test verifies that the allocator walks over the addresses in the
// non-contiguous pools when pools contain class guards.
TEST_F(IterativeAllocatorTest6, addrStepInClass) {
NakedIterativeAllocator alloc(Lease::TYPE_NA);
subnet_->delPools(Lease::TYPE_NA); // Get rid of default pool
Pool6Ptr pool1(new Pool6(Lease::TYPE_NA, IOAddress("2001:db8:1::1"),
@ -215,43 +209,43 @@ TEST_F(IterativeAllocatorTest6, addrStepInClass) {
subnet_->addPool(pool2);
subnet_->addPool(pool3);
NakedIterativeAllocator alloc(Lease::TYPE_NA, subnet_);
// Clients are in foo
cc_.insert("foo");
// Let's check the first pool (5 addresses here)
EXPECT_EQ("2001:db8:1::1",
alloc.pickAddress(subnet_, cc_, duid_, IOAddress("::")).toText());
alloc.pickAddress(cc_, duid_, IOAddress("::")).toText());
EXPECT_EQ("2001:db8:1::2",
alloc.pickAddress(subnet_, cc_, duid_, IOAddress("::")).toText());
alloc.pickAddress(cc_, duid_, IOAddress("::")).toText());
EXPECT_EQ("2001:db8:1::3",
alloc.pickAddress(subnet_, cc_, duid_, IOAddress("::")).toText());
alloc.pickAddress(cc_, duid_, IOAddress("::")).toText());
EXPECT_EQ("2001:db8:1::4",
alloc.pickAddress(subnet_, cc_, duid_, IOAddress("::")).toText());
alloc.pickAddress(cc_, duid_, IOAddress("::")).toText());
EXPECT_EQ("2001:db8:1::5",
alloc.pickAddress(subnet_, cc_, duid_, IOAddress("::")).toText());
alloc.pickAddress(cc_, duid_, IOAddress("::")).toText());
// The second pool is easy - only one address here
EXPECT_EQ("2001:db8:1::100",
alloc.pickAddress(subnet_, cc_, duid_, IOAddress("::")).toText());
alloc.pickAddress(cc_, duid_, IOAddress("::")).toText());
// This is the third and last pool, with 2 addresses in it
EXPECT_EQ("2001:db8:1::105",
alloc.pickAddress(subnet_, cc_, duid_, IOAddress("::")).toText());
alloc.pickAddress(cc_, duid_, IOAddress("::")).toText());
EXPECT_EQ("2001:db8:1::106",
alloc.pickAddress(subnet_, cc_, duid_, IOAddress("::")).toText());
alloc.pickAddress(cc_, duid_, IOAddress("::")).toText());
// We iterated over all addresses and reached to the end of the last pool.
// Let's wrap around and start from the beginning
EXPECT_EQ("2001:db8:1::1",
alloc.pickAddress(subnet_, cc_, duid_, IOAddress("::")).toText());
alloc.pickAddress(cc_, duid_, IOAddress("::")).toText());
EXPECT_EQ("2001:db8:1::2",
alloc.pickAddress(subnet_, cc_, duid_, IOAddress("::")).toText());
alloc.pickAddress(cc_, duid_, IOAddress("::")).toText());
}
// This test verifies that the allocator omits pools with non-matching class guards.
TEST_F(IterativeAllocatorTest6, addrStepOutClass) {
NakedIterativeAllocator alloc(Lease::TYPE_NA);
subnet_->delPools(Lease::TYPE_NA); // Get rid of default pool
Pool6Ptr pool1(new Pool6(Lease::TYPE_NA, IOAddress("2001:db8:1::1"),
@ -266,39 +260,39 @@ TEST_F(IterativeAllocatorTest6, addrStepOutClass) {
subnet_->addPool(pool2);
subnet_->addPool(pool3);
NakedIterativeAllocator alloc(Lease::TYPE_NA, subnet_);
// Let's check the first pool (5 addresses here)
EXPECT_EQ("2001:db8:1::1",
alloc.pickAddress(subnet_, cc_, duid_, IOAddress("::")).toText());
alloc.pickAddress(cc_, duid_, IOAddress("::")).toText());
EXPECT_EQ("2001:db8:1::2",
alloc.pickAddress(subnet_, cc_, duid_, IOAddress("::")).toText());
alloc.pickAddress(cc_, duid_, IOAddress("::")).toText());
EXPECT_EQ("2001:db8:1::3",
alloc.pickAddress(subnet_, cc_, duid_, IOAddress("::")).toText());
alloc.pickAddress(cc_, duid_, IOAddress("::")).toText());
EXPECT_EQ("2001:db8:1::4",
alloc.pickAddress(subnet_, cc_, duid_, IOAddress("::")).toText());
alloc.pickAddress(cc_, duid_, IOAddress("::")).toText());
EXPECT_EQ("2001:db8:1::5",
alloc.pickAddress(subnet_, cc_, duid_, IOAddress("::")).toText());
alloc.pickAddress(cc_, duid_, IOAddress("::")).toText());
// The second pool is skipped
// This is the third and last pool, with 2 addresses in it
EXPECT_EQ("2001:db8:1::105",
alloc.pickAddress(subnet_, cc_, duid_, IOAddress("::")).toText());
alloc.pickAddress(cc_, duid_, IOAddress("::")).toText());
EXPECT_EQ("2001:db8:1::106",
alloc.pickAddress(subnet_, cc_, duid_, IOAddress("::")).toText());
alloc.pickAddress(cc_, duid_, IOAddress("::")).toText());
// We iterated over all addresses and reached to the end of the last pool.
// Let's wrap around and start from the beginning
EXPECT_EQ("2001:db8:1::1",
alloc.pickAddress(subnet_, cc_, duid_, IOAddress("::")).toText());
alloc.pickAddress(cc_, duid_, IOAddress("::")).toText());
EXPECT_EQ("2001:db8:1::2",
alloc.pickAddress(subnet_, cc_, duid_, IOAddress("::")).toText());
alloc.pickAddress(cc_, duid_, IOAddress("::")).toText());
}
// This test verifies that the allocator picks delegated prefixes from several
// pools.
TEST_F(IterativeAllocatorTest6, prefixStep) {
NakedIterativeAllocator alloc(Lease::TYPE_PD);
subnet_.reset(new Subnet6(IOAddress("2001:db8::"), 32, 1, 2, 3, 4));
Pool6Ptr pool1(new Pool6(Lease::TYPE_PD, IOAddress("2001:db8::"), 56, 60));
@ -308,6 +302,8 @@ TEST_F(IterativeAllocatorTest6, prefixStep) {
subnet_->addPool(pool2);
subnet_->addPool(pool3);
NakedIterativeAllocator alloc(Lease::TYPE_PD, subnet_);
// We have a 2001:db8::/48 subnet that has 3 pools defined in it:
// 2001:db8::/56 split into /60 prefixes (16 leases) (or 2001:db8:0:X0::)
// 2001:db8:1::/48 split into a single /48 prefix (just 1 lease)
@ -315,69 +311,67 @@ TEST_F(IterativeAllocatorTest6, prefixStep) {
// First pool check (Let's check over all 16 leases)
EXPECT_EQ("2001:db8::",
alloc.pickAddress(subnet_, cc_, duid_, IOAddress("::")).toText());
alloc.pickAddress(cc_, duid_, IOAddress("::")).toText());
EXPECT_EQ("2001:db8:0:10::",
alloc.pickAddress(subnet_, cc_, duid_, IOAddress("::")).toText());
alloc.pickAddress(cc_, duid_, IOAddress("::")).toText());
EXPECT_EQ("2001:db8:0:20::",
alloc.pickAddress(subnet_, cc_, duid_, IOAddress("::")).toText());
alloc.pickAddress(cc_, duid_, IOAddress("::")).toText());
EXPECT_EQ("2001:db8:0:30::",
alloc.pickAddress(subnet_, cc_, duid_, IOAddress("::")).toText());
alloc.pickAddress(cc_, duid_, IOAddress("::")).toText());
EXPECT_EQ("2001:db8:0:40::",
alloc.pickAddress(subnet_, cc_, duid_, IOAddress("::")).toText());
alloc.pickAddress(cc_, duid_, IOAddress("::")).toText());
EXPECT_EQ("2001:db8:0:50::",
alloc.pickAddress(subnet_, cc_, duid_, IOAddress("::")).toText());
alloc.pickAddress(cc_, duid_, IOAddress("::")).toText());
EXPECT_EQ("2001:db8:0:60::",
alloc.pickAddress(subnet_, cc_, duid_, IOAddress("::")).toText());
alloc.pickAddress(cc_, duid_, IOAddress("::")).toText());
EXPECT_EQ("2001:db8:0:70::",
alloc.pickAddress(subnet_, cc_, duid_, IOAddress("::")).toText());
alloc.pickAddress(cc_, duid_, IOAddress("::")).toText());
EXPECT_EQ("2001:db8:0:80::",
alloc.pickAddress(subnet_, cc_, duid_, IOAddress("::")).toText());
alloc.pickAddress(cc_, duid_, IOAddress("::")).toText());
EXPECT_EQ("2001:db8:0:90::",
alloc.pickAddress(subnet_, cc_, duid_, IOAddress("::")).toText());
alloc.pickAddress(cc_, duid_, IOAddress("::")).toText());
EXPECT_EQ("2001:db8:0:a0::",
alloc.pickAddress(subnet_, cc_, duid_, IOAddress("::")).toText());
alloc.pickAddress(cc_, duid_, IOAddress("::")).toText());
EXPECT_EQ("2001:db8:0:b0::",
alloc.pickAddress(subnet_, cc_, duid_, IOAddress("::")).toText());
alloc.pickAddress(cc_, duid_, IOAddress("::")).toText());
EXPECT_EQ("2001:db8:0:c0::",
alloc.pickAddress(subnet_, cc_, duid_, IOAddress("::")).toText());
alloc.pickAddress(cc_, duid_, IOAddress("::")).toText());
EXPECT_EQ("2001:db8:0:d0::",
alloc.pickAddress(subnet_, cc_, duid_, IOAddress("::")).toText());
alloc.pickAddress(cc_, duid_, IOAddress("::")).toText());
EXPECT_EQ("2001:db8:0:e0::",
alloc.pickAddress(subnet_, cc_, duid_, IOAddress("::")).toText());
alloc.pickAddress(cc_, duid_, IOAddress("::")).toText());
EXPECT_EQ("2001:db8:0:f0::",
alloc.pickAddress(subnet_, cc_, duid_, IOAddress("::")).toText());
alloc.pickAddress(cc_, duid_, IOAddress("::")).toText());
// Second pool (just one lease here)
EXPECT_EQ("2001:db8:1::",
alloc.pickAddress(subnet_, cc_, duid_, IOAddress("::")).toText());
alloc.pickAddress(cc_, duid_, IOAddress("::")).toText());
// Third pool (256 leases, let's check first and last explicitly and the
// rest over in a pool
EXPECT_EQ("2001:db8:2::",
alloc.pickAddress(subnet_, cc_, duid_, IOAddress("::")).toText());
alloc.pickAddress(cc_, duid_, IOAddress("::")).toText());
for (int i = 1; i < 255; i++) {
stringstream exp;
exp << "2001:db8:2:" << hex << i << dec << "::";
EXPECT_EQ(exp.str(),
alloc.pickAddress(subnet_, cc_, duid_, IOAddress("::")).toText());
alloc.pickAddress(cc_, duid_, IOAddress("::")).toText());
}
EXPECT_EQ("2001:db8:2:ff::",
alloc.pickAddress(subnet_, cc_, duid_, IOAddress("::")).toText());
alloc.pickAddress(cc_, duid_, IOAddress("::")).toText());
// Ok, we've iterated over all prefixes in all pools. We now wrap around.
// We're looping over now (iterating over first pool again)
EXPECT_EQ("2001:db8::",
alloc.pickAddress(subnet_, cc_, duid_, IOAddress("::")).toText());
alloc.pickAddress(cc_, duid_, IOAddress("::")).toText());
EXPECT_EQ("2001:db8:0:10::",
alloc.pickAddress(subnet_, cc_, duid_, IOAddress("::")).toText());
alloc.pickAddress(cc_, duid_, IOAddress("::")).toText());
}
// This test verifies that the allocator picks delegated prefixes from the pools
// with class guards.
TEST_F(IterativeAllocatorTest6, prefixStepInClass) {
NakedIterativeAllocator alloc(Lease::TYPE_PD);
subnet_.reset(new Subnet6(IOAddress("2001:db8::"), 32, 1, 2, 3, 4));
Pool6Ptr pool1(new Pool6(Lease::TYPE_PD, IOAddress("2001:db8::"), 56, 60));
@ -390,6 +384,8 @@ TEST_F(IterativeAllocatorTest6, prefixStepInClass) {
subnet_->addPool(pool2);
subnet_->addPool(pool3);
NakedIterativeAllocator alloc(Lease::TYPE_PD, subnet_);
// Clients are in foo
cc_.insert("foo");
@ -400,68 +396,66 @@ TEST_F(IterativeAllocatorTest6, prefixStepInClass) {
// First pool check (Let's check over all 16 leases)
EXPECT_EQ("2001:db8::",
alloc.pickAddress(subnet_, cc_, duid_, IOAddress("::")).toText());
alloc.pickAddress(cc_, duid_, IOAddress("::")).toText());
EXPECT_EQ("2001:db8:0:10::",
alloc.pickAddress(subnet_, cc_, duid_, IOAddress("::")).toText());
alloc.pickAddress(cc_, duid_, IOAddress("::")).toText());
EXPECT_EQ("2001:db8:0:20::",
alloc.pickAddress(subnet_, cc_, duid_, IOAddress("::")).toText());
alloc.pickAddress(cc_, duid_, IOAddress("::")).toText());
EXPECT_EQ("2001:db8:0:30::",
alloc.pickAddress(subnet_, cc_, duid_, IOAddress("::")).toText());
alloc.pickAddress(cc_, duid_, IOAddress("::")).toText());
EXPECT_EQ("2001:db8:0:40::",
alloc.pickAddress(subnet_, cc_, duid_, IOAddress("::")).toText());
alloc.pickAddress(cc_, duid_, IOAddress("::")).toText());
EXPECT_EQ("2001:db8:0:50::",
alloc.pickAddress(subnet_, cc_, duid_, IOAddress("::")).toText());
alloc.pickAddress(cc_, duid_, IOAddress("::")).toText());
EXPECT_EQ("2001:db8:0:60::",
alloc.pickAddress(subnet_, cc_, duid_, IOAddress("::")).toText());
alloc.pickAddress(cc_, duid_, IOAddress("::")).toText());
EXPECT_EQ("2001:db8:0:70::",
alloc.pickAddress(subnet_, cc_, duid_, IOAddress("::")).toText());
alloc.pickAddress(cc_, duid_, IOAddress("::")).toText());
EXPECT_EQ("2001:db8:0:80::",
alloc.pickAddress(subnet_, cc_, duid_, IOAddress("::")).toText());
alloc.pickAddress(cc_, duid_, IOAddress("::")).toText());
EXPECT_EQ("2001:db8:0:90::",
alloc.pickAddress(subnet_, cc_, duid_, IOAddress("::")).toText());
alloc.pickAddress(cc_, duid_, IOAddress("::")).toText());
EXPECT_EQ("2001:db8:0:a0::",
alloc.pickAddress(subnet_, cc_, duid_, IOAddress("::")).toText());
alloc.pickAddress(cc_, duid_, IOAddress("::")).toText());
EXPECT_EQ("2001:db8:0:b0::",
alloc.pickAddress(subnet_, cc_, duid_, IOAddress("::")).toText());
alloc.pickAddress(cc_, duid_, IOAddress("::")).toText());
EXPECT_EQ("2001:db8:0:c0::",
alloc.pickAddress(subnet_, cc_, duid_, IOAddress("::")).toText());
alloc.pickAddress(cc_, duid_, IOAddress("::")).toText());
EXPECT_EQ("2001:db8:0:d0::",
alloc.pickAddress(subnet_, cc_, duid_, IOAddress("::")).toText());
alloc.pickAddress(cc_, duid_, IOAddress("::")).toText());
EXPECT_EQ("2001:db8:0:e0::",
alloc.pickAddress(subnet_, cc_, duid_, IOAddress("::")).toText());
alloc.pickAddress(cc_, duid_, IOAddress("::")).toText());
EXPECT_EQ("2001:db8:0:f0::",
alloc.pickAddress(subnet_, cc_, duid_, IOAddress("::")).toText());
alloc.pickAddress(cc_, duid_, IOAddress("::")).toText());
// Second pool (just one lease here)
EXPECT_EQ("2001:db8:1::",
alloc.pickAddress(subnet_, cc_, duid_, IOAddress("::")).toText());
alloc.pickAddress(cc_, duid_, IOAddress("::")).toText());
// Third pool (256 leases, let's check first and last explicitly and the
// rest over in a pool
EXPECT_EQ("2001:db8:2::",
alloc.pickAddress(subnet_, cc_, duid_, IOAddress("::")).toText());
alloc.pickAddress(cc_, duid_, IOAddress("::")).toText());
for (int i = 1; i < 255; i++) {
stringstream exp;
exp << "2001:db8:2:" << hex << i << dec << "::";
EXPECT_EQ(exp.str(),
alloc.pickAddress(subnet_, cc_, duid_, IOAddress("::")).toText());
alloc.pickAddress(cc_, duid_, IOAddress("::")).toText());
}
EXPECT_EQ("2001:db8:2:ff::",
alloc.pickAddress(subnet_, cc_, duid_, IOAddress("::")).toText());
alloc.pickAddress(cc_, duid_, IOAddress("::")).toText());
// Ok, we've iterated over all prefixes in all pools. We now wrap around.
// We're looping over now (iterating over first pool again)
EXPECT_EQ("2001:db8::",
alloc.pickAddress(subnet_, cc_, duid_, IOAddress("::")).toText());
alloc.pickAddress(cc_, duid_, IOAddress("::")).toText());
EXPECT_EQ("2001:db8:0:10::",
alloc.pickAddress(subnet_, cc_, duid_, IOAddress("::")).toText());
alloc.pickAddress(cc_, duid_, IOAddress("::")).toText());
}
// This test verifies that the allocator omits pools with non-matching client classes.
TEST_F(IterativeAllocatorTest6, prefixStepOutClass) {
NakedIterativeAllocator alloc(Lease::TYPE_PD);
subnet_.reset(new Subnet6(IOAddress("2001:db8::"), 32, 1, 2, 3, 4));
Pool6Ptr pool1(new Pool6(Lease::TYPE_PD, IOAddress("2001:db8::"), 56, 60));
@ -473,6 +467,8 @@ TEST_F(IterativeAllocatorTest6, prefixStepOutClass) {
subnet_->addPool(pool2);
subnet_->addPool(pool3);
NakedIterativeAllocator alloc(Lease::TYPE_PD, subnet_);
// We have a 2001:db8::/48 subnet that has 3 pools defined in it:
// 2001:db8::/56 split into /60 prefixes (16 leases) (or 2001:db8:0:X0::)
// 2001:db8:1::/48 split into a single /48 prefix (just 1 lease)
@ -480,68 +476,68 @@ TEST_F(IterativeAllocatorTest6, prefixStepOutClass) {
// First pool check (Let's check over all 16 leases)
EXPECT_EQ("2001:db8::",
alloc.pickAddress(subnet_, cc_, duid_, IOAddress("::")).toText());
alloc.pickAddress(cc_, duid_, IOAddress("::")).toText());
EXPECT_EQ("2001:db8:0:10::",
alloc.pickAddress(subnet_, cc_, duid_, IOAddress("::")).toText());
alloc.pickAddress(cc_, duid_, IOAddress("::")).toText());
EXPECT_EQ("2001:db8:0:20::",
alloc.pickAddress(subnet_, cc_, duid_, IOAddress("::")).toText());
alloc.pickAddress(cc_, duid_, IOAddress("::")).toText());
EXPECT_EQ("2001:db8:0:30::",
alloc.pickAddress(subnet_, cc_, duid_, IOAddress("::")).toText());
alloc.pickAddress(cc_, duid_, IOAddress("::")).toText());
EXPECT_EQ("2001:db8:0:40::",
alloc.pickAddress(subnet_, cc_, duid_, IOAddress("::")).toText());
alloc.pickAddress(cc_, duid_, IOAddress("::")).toText());
EXPECT_EQ("2001:db8:0:50::",
alloc.pickAddress(subnet_, cc_, duid_, IOAddress("::")).toText());
alloc.pickAddress(cc_, duid_, IOAddress("::")).toText());
EXPECT_EQ("2001:db8:0:60::",
alloc.pickAddress(subnet_, cc_, duid_, IOAddress("::")).toText());
alloc.pickAddress(cc_, duid_, IOAddress("::")).toText());
EXPECT_EQ("2001:db8:0:70::",
alloc.pickAddress(subnet_, cc_, duid_, IOAddress("::")).toText());
alloc.pickAddress(cc_, duid_, IOAddress("::")).toText());
EXPECT_EQ("2001:db8:0:80::",
alloc.pickAddress(subnet_, cc_, duid_, IOAddress("::")).toText());
alloc.pickAddress(cc_, duid_, IOAddress("::")).toText());
EXPECT_EQ("2001:db8:0:90::",
alloc.pickAddress(subnet_, cc_, duid_, IOAddress("::")).toText());
alloc.pickAddress(cc_, duid_, IOAddress("::")).toText());
EXPECT_EQ("2001:db8:0:a0::",
alloc.pickAddress(subnet_, cc_, duid_, IOAddress("::")).toText());
alloc.pickAddress(cc_, duid_, IOAddress("::")).toText());
EXPECT_EQ("2001:db8:0:b0::",
alloc.pickAddress(subnet_, cc_, duid_, IOAddress("::")).toText());
alloc.pickAddress(cc_, duid_, IOAddress("::")).toText());
EXPECT_EQ("2001:db8:0:c0::",
alloc.pickAddress(subnet_, cc_, duid_, IOAddress("::")).toText());
alloc.pickAddress(cc_, duid_, IOAddress("::")).toText());
EXPECT_EQ("2001:db8:0:d0::",
alloc.pickAddress(subnet_, cc_, duid_, IOAddress("::")).toText());
alloc.pickAddress(cc_, duid_, IOAddress("::")).toText());
EXPECT_EQ("2001:db8:0:e0::",
alloc.pickAddress(subnet_, cc_, duid_, IOAddress("::")).toText());
alloc.pickAddress(cc_, duid_, IOAddress("::")).toText());
EXPECT_EQ("2001:db8:0:f0::",
alloc.pickAddress(subnet_, cc_, duid_, IOAddress("::")).toText());
alloc.pickAddress(cc_, duid_, IOAddress("::")).toText());
// The second pool is skipped
// Third pool (256 leases, let's check first and last explicitly and the
// rest over in a pool
EXPECT_EQ("2001:db8:2::",
alloc.pickAddress(subnet_, cc_, duid_, IOAddress("::")).toText());
alloc.pickAddress(cc_, duid_, IOAddress("::")).toText());
for (int i = 1; i < 255; i++) {
stringstream exp;
exp << "2001:db8:2:" << hex << i << dec << "::";
EXPECT_EQ(exp.str(),
alloc.pickAddress(subnet_, cc_, duid_, IOAddress("::")).toText());
alloc.pickAddress(cc_, duid_, IOAddress("::")).toText());
}
EXPECT_EQ("2001:db8:2:ff::",
alloc.pickAddress(subnet_, cc_, duid_, IOAddress("::")).toText());
alloc.pickAddress(cc_, duid_, IOAddress("::")).toText());
// Ok, we've iterated over all prefixes in all pools. We now wrap around.
// We're looping over now (iterating over first pool again)
EXPECT_EQ("2001:db8::",
alloc.pickAddress(subnet_, cc_, duid_, IOAddress("::")).toText());
alloc.pickAddress(cc_, duid_, IOAddress("::")).toText());
EXPECT_EQ("2001:db8:0:10::",
alloc.pickAddress(subnet_, cc_, duid_, IOAddress("::")).toText());
alloc.pickAddress(cc_, duid_, IOAddress("::")).toText());
}
// This test verifies that the iterative allocator can step over addresses.
TEST_F(IterativeAllocatorTest6, addressIncrease) {
NakedIterativeAllocator alloc(Lease::TYPE_NA);
NakedIterativeAllocator alloc(Lease::TYPE_NA, subnet_);
// Let's pick the first address
IOAddress addr1 = alloc.pickAddress(subnet_, cc_, duid_, IOAddress("2001:db8:1::10"));
IOAddress addr1 = alloc.pickAddress(cc_, duid_, IOAddress("2001:db8:1::10"));
// Check that we can indeed pick the first address from the pool
EXPECT_EQ("2001:db8:1::10", addr1.toText());
@ -558,7 +554,7 @@ TEST_F(IterativeAllocatorTest6, addressIncrease) {
// This test verifies that the allocator can step over prefixes.
TEST_F(IterativeAllocatorTest6, prefixIncrease) {
NakedIterativeAllocator alloc(Lease::TYPE_PD);
NakedIterativeAllocator alloc(Lease::TYPE_PD, subnet_);
// For /128 prefix, increasePrefix should work the same as addressIncrease
checkPrefixIncrease(alloc, "2001:db8::9", 128, "2001:db8::a");
@ -610,7 +606,7 @@ TEST_F(IterativeAllocatorTest6, prefixIncrease) {
// in all pools in specified subnet. It also must not pick the same address twice
// unless it runs out of pool space and must start over.
TEST_F(IterativeAllocatorTest6, manyPools) {
NakedIterativeAllocator alloc(Lease::TYPE_NA);
NakedIterativeAllocator alloc(Lease::TYPE_NA, subnet_);
// let's start from 2, as there is 2001:db8:1::10 - 2001:db8:1::20 pool already.
for (int i = 2; i < 10; ++i) {
@ -631,8 +627,7 @@ TEST_F(IterativeAllocatorTest6, manyPools) {
std::set<IOAddress> generated_addrs;
int cnt = 0;
while (++cnt) {
IOAddress candidate = alloc.pickAddress(subnet_, cc_,
duid_, IOAddress("::"));
IOAddress candidate = alloc.pickAddress(cc_, duid_, IOAddress("::"));
EXPECT_TRUE(subnet_->inPool(Lease::TYPE_NA, candidate));
// One way to easily verify that the iterative allocator really works is
@ -663,4 +658,4 @@ TEST_F(IterativeAllocatorTest6, manyPools) {
} // end of namespace isc::dhcp::test
} // end of namespace isc::dhcp
} // end of namespace isc
} // end of namespace isc

View File

@ -155,8 +155,8 @@ TEST(Subnet4Test, defaults) {
// arbitrary value through the constructor.
TEST(Subnet4Test, subnetID) {
// Create subnet and don't specify id, so as it is autogenerated.
Subnet4Ptr subnet(new Subnet4(IOAddress("192.0.2.0"), 24, 1000, 2000,
3000));
auto subnet = Subnet4::create(IOAddress("192.0.2.0"), 24, 1000, 2000,
3000);
SubnetID id0 = subnet->getID();
// Create another subnet and let id be autogenerated.
@ -172,8 +172,7 @@ TEST(Subnet4Test, subnetID) {
// subnet id we provide via constructor is used and it is not
// autogenerated - if it was autogenerated we would get id other
// than id1 because id1 has already been used.
subnet.reset(new Subnet4(IOAddress("192.0.4.0"), 24, 1000, 2000,
3000, id1));
subnet = Subnet4::create(IOAddress("192.0.4.0"), 24, 1000, 2000, 3000, id1);
EXPECT_EQ(id1, subnet->getID());
}
@ -290,7 +289,7 @@ TEST(Subnet4Test, matchClientId) {
// Checks that it is possible to add and retrieve multiple pools.
TEST(Subnet4Test, pool4InSubnet4) {
Subnet4Ptr subnet(new Subnet4(IOAddress("192.1.2.0"), 24, 1, 2, 3));
auto subnet = Subnet4::create(IOAddress("192.1.2.0"), 24, 1, 2, 3);
PoolPtr pool1(new Pool4(IOAddress("192.1.2.0"), 25));
PoolPtr pool2(new Pool4(IOAddress("192.1.2.128"), 26));
@ -399,7 +398,7 @@ TEST(Subnet4Test, pool4InSubnet4) {
TEST(Subnet4Test, getCapacity) {
// There's one /24 pool.
Subnet4Ptr subnet(new Subnet4(IOAddress("192.1.2.0"), 24, 1, 2, 3));
auto subnet = Subnet4::create(IOAddress("192.1.2.0"), 24, 1, 2, 3);
// There are no pools defined, so the total number of available addrs is 0.
EXPECT_EQ(0, subnet->getPoolCapacity(Lease::TYPE_V4));
@ -455,7 +454,7 @@ TEST(Subnet4Test, getCapacity) {
// Checks that it is not allowed to add invalid pools.
TEST(Subnet4Test, pool4Checks) {
Subnet4Ptr subnet(new Subnet4(IOAddress("192.0.2.0"), 8, 1, 2, 3));
auto subnet = Subnet4::create(IOAddress("192.0.2.0"), 8, 1, 2, 3);
// this one is in subnet
Pool4Ptr pool1(new Pool4(IOAddress("192.254.0.0"), 16));
@ -521,7 +520,7 @@ TEST(Subnet4Test, pool4Checks) {
// information about allowed client class (a single class).
TEST(Subnet4Test, clientClass) {
// Create the V4 subnet.
Subnet4Ptr subnet(new Subnet4(IOAddress("192.0.2.0"), 8, 1, 2, 3));
auto subnet = Subnet4::create(IOAddress("192.0.2.0"), 8, 1, 2, 3);
// This client does not belong to any class.
isc::dhcp::ClientClasses no_class;
@ -580,7 +579,7 @@ TEST(Subnet4Test, clientClass) {
TEST(Subnet4Test, addInvalidOption) {
// Create the V4 subnet.
Subnet4Ptr subnet(new Subnet4(IOAddress("192.0.2.0"), 8, 1, 2, 3));
auto subnet = Subnet4::create(IOAddress("192.0.2.0"), 8, 1, 2, 3);
// Create NULL pointer option. Attempt to add NULL option
// should result in exception.
@ -592,7 +591,7 @@ TEST(Subnet4Test, addInvalidOption) {
// This test verifies that inRange() and inPool() methods work properly.
TEST(Subnet4Test, inRangeinPool) {
Subnet4Ptr subnet(new Subnet4(IOAddress("192.0.0.0"), 8, 1, 2, 3));
auto subnet = Subnet4::create(IOAddress("192.0.0.0"), 8, 1, 2, 3);
// this one is in subnet
Pool4Ptr pool1(new Pool4(IOAddress("192.2.0.0"), 16));
@ -652,7 +651,7 @@ TEST(Subnet4Test, inRangeinPool) {
// This test checks if the toText() method returns text representation
TEST(Subnet4Test, toText) {
Subnet4Ptr subnet(new Subnet4(IOAddress("192.0.2.0"), 24, 1, 2, 3));
auto subnet = Subnet4::create(IOAddress("192.0.2.0"), 24, 1, 2, 3);
EXPECT_EQ("192.0.2.0/24", subnet->toText());
}
@ -688,7 +687,7 @@ TEST(Subnet4Test, parsePrefix) {
// This test checks if the get() method returns proper parameters
TEST(Subnet4Test, get) {
Subnet4Ptr subnet(new Subnet4(IOAddress("192.0.2.0"), 28, 1, 2, 3));
auto subnet = Subnet4::create(IOAddress("192.0.2.0"), 28, 1, 2, 3);
EXPECT_EQ("192.0.2.0", subnet->get().first.toText());
EXPECT_EQ(28, subnet->get().second);
}
@ -697,7 +696,7 @@ TEST(Subnet4Test, get) {
// is working properly.
TEST(Subnet4Test, PoolType) {
Subnet4Ptr subnet(new Subnet4(IOAddress("192.2.0.0"), 16, 1, 2, 3));
auto subnet = Subnet4::create(IOAddress("192.2.0.0"), 16, 1, 2, 3);
PoolPtr pool1(new Pool4(IOAddress("192.2.1.0"), 24));
PoolPtr pool2(new Pool4(IOAddress("192.2.2.0"), 24));
@ -870,8 +869,8 @@ TEST(SharedNetwork6Test, defaults) {
// arbitrary value through the constructor.
TEST(Subnet6Test, subnetID) {
// Create subnet and don't specify id, so as it is autogenerated.
Subnet6Ptr subnet(new Subnet6(IOAddress("2001:db8:1::"), 64, 1000, 2000,
3000, 4000));
auto subnet = Subnet6::create(IOAddress("2001:db8:1::"), 64, 1000, 2000,
3000, 4000);
SubnetID id0 = subnet->getID();
// Create another subnet and let id be autogenerated.
@ -942,7 +941,7 @@ TEST(Subnet6Test, relay) {
// calculated properly.
TEST(Subnet6Test, Pool6getCapacity) {
Subnet6Ptr subnet(new Subnet6(IOAddress("2001:db8:1::"), 56, 1, 2, 3, 4));
auto subnet = Subnet6::create(IOAddress("2001:db8:1::"), 56, 1, 2, 3, 4);
// There's 2^16 = 65536 addresses in this one.
PoolPtr pool1(new Pool6(Lease::TYPE_NA, IOAddress("2001:db8:1:1::"), 112));
@ -1001,7 +1000,7 @@ TEST(Subnet6Test, Pool6getCapacity) {
// calculated properly.
TEST(Subnet6Test, Pool6PdgetPoolCapacity) {
Subnet6Ptr subnet(new Subnet6(IOAddress("2001:db8::"), 32, 1, 2, 3, 4));
auto subnet = Subnet6::create(IOAddress("2001:db8::"), 32, 1, 2, 3, 4);
// There's 2^16 = 65536 addresses in this one.
PoolPtr pool1(new Pool6(Lease::TYPE_PD, IOAddress("2001:db8:1::"), 48, 64));
@ -1038,7 +1037,7 @@ TEST(Subnet6Test, Pool6PdgetPoolCapacity) {
TEST(Subnet6Test, Pool6InSubnet6) {
Subnet6Ptr subnet(new Subnet6(IOAddress("2001:db8:1::"), 56, 1, 2, 3, 4));
auto subnet = Subnet6::create(IOAddress("2001:db8:1::"), 56, 1, 2, 3, 4);
PoolPtr pool1(new Pool6(Lease::TYPE_NA, IOAddress("2001:db8:1:1::"), 64));
PoolPtr pool2(new Pool6(Lease::TYPE_NA, IOAddress("2001:db8:1:2::"), 64));
@ -1103,7 +1102,7 @@ TEST(Subnet6Test, Pool6InSubnet6) {
// Check if Subnet6 supports different types of pools properly.
TEST(Subnet6Test, poolTypes) {
Subnet6Ptr subnet(new Subnet6(IOAddress("2001:db8:1::"), 56, 1, 2, 3, 4));
auto subnet = Subnet6::create(IOAddress("2001:db8:1::"), 56, 1, 2, 3, 4);
PoolPtr pool1(new Pool6(Lease::TYPE_NA, IOAddress("2001:db8:1:1::"), 64));
PoolPtr pool2(new Pool6(Lease::TYPE_TA, IOAddress("2001:db8:1:2::"), 64));
@ -1175,7 +1174,7 @@ TEST(Subnet6Test, poolTypes) {
// information about allowed client class (a single class).
TEST(Subnet6Test, clientClass) {
// Create the V6 subnet.
Subnet6Ptr subnet(new Subnet6(IOAddress("2001:db8:1::"), 56, 1, 2, 3, 4));
auto subnet = Subnet6::create(IOAddress("2001:db8:1::"), 56, 1, 2, 3, 4);
// This client does not belong to any class.
isc::dhcp::ClientClasses no_class;
@ -1235,7 +1234,7 @@ TEST(Subnet6Test, clientClass) {
// Checks that it is not allowed to add invalid pools.
TEST(Subnet6Test, pool6Checks) {
Subnet6Ptr subnet(new Subnet6(IOAddress("2001:db8:1::"), 56, 1, 2, 3, 4));
auto subnet = Subnet6::create(IOAddress("2001:db8:1::"), 56, 1, 2, 3, 4);
// this one is in subnet
Pool6Ptr pool1(new Pool6(Lease::TYPE_NA, IOAddress("2001:db8:1:1::"), 64));
@ -1308,7 +1307,7 @@ TEST(Subnet6Test, pool6Checks) {
TEST(Subnet6Test, addOptions) {
// Create as subnet to add options to it.
Subnet6Ptr subnet(new Subnet6(IOAddress("2001:db8:1::"), 56, 1, 2, 3, 4));
auto subnet = Subnet6::create(IOAddress("2001:db8:1::"), 56, 1, 2, 3, 4);
// Differentiate options by their codes (100-109)
for (uint16_t code = 100; code < 110; ++code) {
@ -1358,7 +1357,7 @@ TEST(Subnet6Test, addOptions) {
TEST(Subnet6Test, addNonUniqueOptions) {
// Create as subnet to add options to it.
Subnet6Ptr subnet(new Subnet6(IOAddress("2001:db8:1::"), 56, 1, 2, 3, 4));
auto subnet = Subnet6::create(IOAddress("2001:db8:1::"), 56, 1, 2, 3, 4);
// Create a set of options with non-unique codes.
for (int i = 0; i < 2; ++i) {
@ -1399,7 +1398,7 @@ TEST(Subnet6Test, addNonUniqueOptions) {
TEST(Subnet6Test, addPersistentOption) {
// Create as subnet to add options to it.
Subnet6Ptr subnet(new Subnet6(IOAddress("2001:db8:1::"), 56, 1, 2, 3, 4));
auto subnet = Subnet6::create(IOAddress("2001:db8:1::"), 56, 1, 2, 3, 4);
// Add 10 options to the subnet with option codes 100 - 109.
for (uint16_t code = 100; code < 110; ++code) {
@ -1435,7 +1434,7 @@ TEST(Subnet6Test, addPersistentOption) {
}
TEST(Subnet6Test, getOptions) {
Subnet6Ptr subnet(new Subnet6(IOAddress("2001:db8::"), 56, 1, 2, 3, 4));
auto subnet = Subnet6::create(IOAddress("2001:db8::"), 56, 1, 2, 3, 4);
// Add 10 options to a "dhcp6" option space in the subnet.
for (uint16_t code = 100; code < 110; ++code) {
@ -1462,7 +1461,7 @@ TEST(Subnet6Test, getOptions) {
TEST(Subnet6Test, addVendorOption) {
// Create as subnet to add options to it.
Subnet6Ptr subnet(new Subnet6(IOAddress("2001:db8:1::"), 56, 1, 2, 3, 4));
auto subnet = Subnet6::create(IOAddress("2001:db8:1::"), 56, 1, 2, 3, 4);
// Differentiate options by their codes (100-109)
for (uint16_t code = 100; code < 110; ++code) {
@ -1512,7 +1511,7 @@ TEST(Subnet6Test, addVendorOption) {
// This test verifies that inRange() and inPool() methods work properly.
TEST(Subnet6Test, inRangeinPool) {
Subnet6Ptr subnet(new Subnet6(IOAddress("2001:db8::"), 32, 1, 2, 3, 4));
auto subnet = Subnet6::create(IOAddress("2001:db8::"), 32, 1, 2, 3, 4);
// this one is in subnet
Pool6Ptr pool1(new Pool6(Lease::TYPE_NA, IOAddress("2001:db8::10"),
@ -1573,7 +1572,7 @@ TEST(Subnet6Test, inRangeinPool) {
// This test verifies that inRange() and inPool() methods work properly
// for prefixes too.
TEST(Subnet6Test, PdinRangeinPool) {
Subnet6Ptr subnet(new Subnet6(IOAddress("2001:db8::"), 64, 1, 2, 3, 4));
auto subnet = Subnet6::create(IOAddress("2001:db8::"), 64, 1, 2, 3, 4);
// this one is in subnet
Pool6Ptr pool1(new Pool6(Lease::TYPE_PD, IOAddress("2001:db8::"),
@ -1662,7 +1661,7 @@ TEST(Subnet6Test, iface) {
// later retrieved for a subnet6 object.
TEST(Subnet6Test, interfaceId) {
// Create as subnet to add options to it.
Subnet6Ptr subnet(new Subnet6(IOAddress("2001:db8:1::"), 56, 1, 2, 3, 4));
auto subnet = Subnet6::create(IOAddress("2001:db8:1::"), 56, 1, 2, 3, 4);
EXPECT_FALSE(subnet->getInterfaceId());