17#include <unordered_set>
26const string FLQ_OWNER =
"flq";
35 generator_.seed(rd());
39FreeLeaseQueueAllocator::pickAddressInternal(
const ClientClasses& client_classes,
43 auto const& pools = subnet->getPools(
pool_type_);
50 std::vector<uint64_t> available;
51 for (
unsigned i = 0; i < pools.size(); ++i) {
53 if (pools[i]->clientSupported(client_classes)) {
55 auto pool_state = getPoolState(pools[i]);
56 if (!pool_state->exhausted()) {
58 available.push_back(i);
62 if (available.empty()) {
67 auto const& pool = pools[available[getRandomNumber(available.size() - 1)]];
70 auto pool_state = getPoolState(pool);
73 auto free_lease = pool_state->offerFreeLease();
75 if (!free_lease.isV4Zero() && !free_lease.isV6Zero()) {
83FreeLeaseQueueAllocator::pickPrefixInternal(
const ClientClasses& client_classes,
86 PrefixLenMatchType prefix_length_match,
88 uint8_t hint_prefix_length) {
90 auto const& pools = subnet->getPools(
pool_type_);
97 std::vector<uint64_t> available;
98 for (
unsigned i = 0; i < pools.size(); ++i) {
100 if (pools[i]->clientSupported(client_classes)) {
102 hint_prefix_length)) {
106 auto pool_state = getPoolState(pools[i]);
107 if (!pool_state->exhausted()) {
109 available.push_back(i);
113 if (available.empty()) {
118 auto const& pool = pools[available[getRandomNumber(available.size() - 1)]];
119 pool6 = boost::dynamic_pointer_cast<Pool6>(pool);
122 isc_throw(Unexpected,
"Wrong type of pool: "
127 auto pool_state = getPoolState(pool);
129 auto free_lease = pool_state->offerFreeLease();
131 if (!free_lease.isV6Zero()) {
151 if (!pool->clientSupported(client_classes)) {
154 uint128_t capacity = pool->getCapacity();
156 if (total >= std::numeric_limits<uint64_t>::max()) {
159 auto pool_state = boost::dynamic_pointer_cast<PoolFreeLeaseQueueAllocationState>(pool->getAllocationState());
163 uint128_t free_cnt = pool_state->getFreeLeaseCount();
164 if (!found && pool->inRange(addr)) {
166 if ((free_cnt > 0) && pool_state->isFreeLease(addr)) {
170 if (free_cnt > capacity) {
173 busy += capacity - free_cnt;
182 return (
static_cast<double>(busy) /
static_cast<double>(total));
199 if (!pool->clientSupported(client_classes)) {
202 auto const& pool6 = boost::dynamic_pointer_cast<Pool6>(pool);
203 if (!pool6 || (pool6->getLength() > plen)) {
206 uint128_t capacity = pool->getCapacity();
208 if (total >= std::numeric_limits<uint64_t>::max()) {
211 auto pool_state = boost::dynamic_pointer_cast<PoolFreeLeaseQueueAllocationState>(pool->getAllocationState());
215 uint128_t free_cnt = pool_state->getFreeLeaseCount();
216 if (!found && pool->inRange(pref)) {
218 if ((free_cnt > 0) && pool_state->isFreeLease(pref)) {
222 if (free_cnt > capacity) {
225 busy += capacity - free_cnt;
234 return (
static_cast<double>(busy) /
static_cast<double>(total));
238FreeLeaseQueueAllocator::initAfterConfigureInternal() {
240 auto const& pools = subnet->getPools(
pool_type_);
250 populateFreeAddressLeases(leases4, pools);
255 populateFreeAddressLeases(leases6, pools);
259 populateFreePrefixDelegationLeases(leases6, pools);
268 std::bind(&FreeLeaseQueueAllocator::addLeaseCallback,
this,
269 std::placeholders::_1));
271 std::bind(&FreeLeaseQueueAllocator::updateLeaseCallback,
this,
272 std::placeholders::_1));
274 std::bind(&FreeLeaseQueueAllocator::deleteLeaseCallback,
this,
275 std::placeholders::_1));
278template<
typename LeaseCollectionType>
280FreeLeaseQueueAllocator::populateFreeAddressLeases(
const LeaseCollectionType& leases,
284 .arg(subnet->toText());
291 unordered_set<IOAddress, IOAddress::Hash> leased_addresses;
292 for (
auto const& lease : leases) {
293 if ((lease->getType() ==
pool_type_) && (!lease->expired()) && (!lease->stateExpiredReclaimed())) {
294 leased_addresses.insert(lease->addr_);
298 size_t free_lease_count = 0;
299 for (
auto const& pool : pools) {
302 IPRangePermutation perm(AddressRange(pool->getFirstAddress(), pool->getLastAddress()));
303 auto pool_state = getPoolState(pool);
306 auto address = perm.next(done);
307 if (address.isV4Zero() || address.isV6Zero()) {
310 if (leased_addresses.count(address) == 0) {
312 pool_state->addFreeLease(address);
315 free_lease_count += pool_state->getFreeLeaseCount();
321 .arg(free_lease_count)
322 .arg(subnet->toText())
327FreeLeaseQueueAllocator::populateFreePrefixDelegationLeases(
const Lease6Collection& leases,
331 .arg(subnet->toText());
338 unordered_set<IOAddress, IOAddress::Hash> leased_prefixes;
339 for (
auto const& lease : leases) {
340 if ((lease->getType() ==
Lease::TYPE_PD) && (!lease->expired()) && (!lease->stateExpiredReclaimed())) {
341 leased_prefixes.insert(lease->addr_);
345 size_t free_lease_count = 0;
346 for (
auto const& pool : pools) {
347 auto pool6 = boost::dynamic_pointer_cast<Pool6>(pool);
353 IPRangePermutation perm(PrefixRange(pool->getFirstAddress(),
354 pool->getLastAddress(),
355 pool6->getLength()));
356 auto pool_state = getPoolState(pool);
359 auto prefix = perm.next(done);
360 if (prefix.isV4Zero() || prefix.isV6Zero()) {
363 if (leased_prefixes.count(prefix) == 0) {
365 pool_state->addFreeLease(prefix);
368 free_lease_count += pool_state->getFreeLeaseCount();
374 .arg(free_lease_count)
375 .arg(subnet->toText())
380FreeLeaseQueueAllocator::getPoolState(
const PoolPtr& pool)
const {
381 if (!pool->getAllocationState()) {
384 return (boost::dynamic_pointer_cast<PoolFreeLeaseQueueAllocationState>(pool->getAllocationState()));
388FreeLeaseQueueAllocator::getLeasePool(
const LeasePtr& lease)
const {
393 auto pool = subnet->getPool(
pool_type_, lease->addr_,
false);
398FreeLeaseQueueAllocator::addLeaseCallback(
LeasePtr lease) {
399 MultiThreadingLock lock(
mutex_);
400 addLeaseCallbackInternal(lease);
404FreeLeaseQueueAllocator::addLeaseCallbackInternal(
LeasePtr lease) {
405 if (lease->expired()) {
408 auto pool = getLeasePool(lease);
412 getPoolState(pool)->deleteFreeLease(lease->addr_);
416FreeLeaseQueueAllocator::updateLeaseCallback(
LeasePtr lease) {
417 MultiThreadingLock lock(
mutex_);
418 updateLeaseCallbackInternal(lease);
422FreeLeaseQueueAllocator::updateLeaseCallbackInternal(
LeasePtr lease) {
423 auto pool = getLeasePool(lease);
427 auto pool_state = getPoolState(pool);
428 if (lease->stateExpiredReclaimed() || (lease->expired())) {
429 pool_state->addFreeLease(lease->addr_);
431 pool_state->deleteFreeLease(lease->addr_);
436FreeLeaseQueueAllocator::deleteLeaseCallback(
LeasePtr lease) {
437 MultiThreadingLock lock(
mutex_);
438 deleteLeaseCallbackInternal(lease);
442FreeLeaseQueueAllocator::deleteLeaseCallbackInternal(
LeasePtr lease) {
443 auto pool = getLeasePool(lease);
447 getPoolState(pool)->addFreeLease(lease->addr_);
451FreeLeaseQueueAllocator::getRandomNumber(uint64_t limit) {
456 std::uniform_int_distribution<uint64_t> dist(0, limit);
457 return (dist(generator_));
The IOAddress class represents an IP addresses (version agnostic)
static const IOAddress & IPV4_ZERO_ADDRESS()
Returns an address set to all zeros.
bool isV6() const
Convenience function to check for an IPv6 address.
bool isV4() const
Convenience function to check for an IPv4 address.
static const IOAddress & IPV6_ZERO_ADDRESS()
Returns an IPv6 zero address.
Lease::Type pool_type_
Defines pool type allocation.
std::mutex mutex_
The mutex to protect the allocated lease.
Allocator(Lease::Type type, const WeakSubnetPtr &subnet)
Constructor.
WeakSubnetPtr subnet_
Weak pointer to the subnet owning the allocator.
static bool isValidPrefixPool(Allocator::PrefixLenMatchType prefix_length_match, PoolPtr pool, uint8_t hint_prefix_length)
Check if the pool matches the selection criteria relative to the provided hint prefix length.
Container for storing client class names.
FreeLeaseQueueAllocator(Lease::Type type, const WeakSubnetPtr &subnet)
Constructor.
virtual double getOccupancyRate(const asiolink::IOAddress &addr, const ClientClasses &client_classes) const
Returns the occupancy rate (v4 addresses).
static TrackingLeaseMgr & instance()
Return current lease manager.
virtual Lease6Collection getLeases6(Lease::Type type, const DUID &duid, uint32_t iaid) const =0
Returns existing IPv6 leases for a given DUID+IA combination.
virtual Lease4Collection getLeases4(SubnetID subnet_id) const =0
Returns all IPv4 leases for the particular subnet identifier.
static PoolFreeLeaseQueueAllocationStatePtr create(const PoolPtr &pool)
Factory function creating the state instance from a pool.
void stop()
Stops the stopwatch.
std::string logFormatLastDuration() const
Returns the last measured duration in the format directly usable in log messages.
#define isc_throw(type, stream)
A shortcut macro to insert known values into exception arguments.
#define LOG_INFO(LOGGER, MESSAGE)
Macro to conveniently test info output and log it.
isc::log::Logger dhcpsrv_logger("dhcpsrv")
DHCP server library Logger.
boost::shared_ptr< PoolFreeLeaseQueueAllocationState > PoolFreeLeaseQueueAllocationStatePtr
Type of the pointer to the PoolFreeLeaseQueueAllocationState.
const isc::log::MessageID DHCPSRV_CFGMGR_FLQ_POPULATE_FREE_PREFIX_LEASES
boost::weak_ptr< Subnet > WeakSubnetPtr
Weak pointer to the Subnet.
const isc::log::MessageID DHCPSRV_CFGMGR_FLQ_POPULATE_FREE_ADDRESS_LEASES_DONE
std::vector< Lease6Ptr > Lease6Collection
A collection of IPv6 leases.
const isc::log::MessageID DHCPSRV_CFGMGR_FLQ_POPULATE_FREE_PREFIX_LEASES_DONE
std::vector< PoolPtr > PoolCollection
a container for either IPv4 or IPv6 Pools
boost::shared_ptr< IdentifierBaseType > IdentifierBaseTypePtr
Shared pointer to a IdentifierType.
boost::shared_ptr< Pool > PoolPtr
a pointer to either IPv4 or IPv6 Pool
boost::shared_ptr< Lease > LeasePtr
Pointer to the lease object.
std::vector< Lease4Ptr > Lease4Collection
A collection of IPv4 leases.
const isc::log::MessageID DHCPSRV_CFGMGR_FLQ_POPULATE_FREE_ADDRESS_LEASES
boost::shared_ptr< Pool6 > Pool6Ptr
a pointer an IPv6 Pool
boost::multiprecision::checked_uint128_t uint128_t
Defines the logger used by the top-level component of kea-lfc.
Type
Type of lease or pool.
@ TYPE_TA
the lease contains temporary IPv6 address
@ TYPE_PD
the lease contains IPv6 prefix (for prefix delegation)
@ TYPE_NA
the lease contains non-temporary IPv6 address