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()) {
142 return (getOccupancyRateInternal(addr, client_classes));
146FreeLeaseQueueAllocator::getOccupancyRateInternal(
const IOAddress& addr,
158 if (!pool->clientSupported(client_classes)) {
161 uint128_t capacity = pool->getCapacity();
163 if (total >= std::numeric_limits<uint64_t>::max()) {
166 auto pool_state = boost::dynamic_pointer_cast<PoolFreeLeaseQueueAllocationState>(pool->getAllocationState());
170 uint128_t free_cnt = pool_state->getFreeLeaseCount();
171 if (!found && pool->inRange(addr)) {
173 if ((free_cnt > 0) && pool_state->isFreeLease(addr)) {
177 if (free_cnt > capacity) {
180 busy += capacity - free_cnt;
189 return (
static_cast<double>(busy) /
static_cast<double>(total));
197 return (getOccupancyRateInternal(pref, plen, client_classes));
201FreeLeaseQueueAllocator::getOccupancyRateInternal(
const IOAddress& pref,
214 if (!pool->clientSupported(client_classes)) {
217 auto const& pool6 = boost::dynamic_pointer_cast<Pool6>(pool);
218 if (!pool6 || (pool6->getLength() > plen)) {
221 uint128_t capacity = pool->getCapacity();
223 if (total >= std::numeric_limits<uint64_t>::max()) {
226 auto pool_state = boost::dynamic_pointer_cast<PoolFreeLeaseQueueAllocationState>(pool->getAllocationState());
230 uint128_t free_cnt = pool_state->getFreeLeaseCount();
231 if (!found && pool->inRange(pref)) {
233 if ((free_cnt > 0) && pool_state->isFreeLease(pref)) {
237 if (free_cnt > capacity) {
240 busy += capacity - free_cnt;
249 return (
static_cast<double>(busy) /
static_cast<double>(total));
255 auto const& pools = subnet->getPools(
pool_type_);
265 populateFreeAddressLeases(leases4, pools);
269 populateFreeAddressLeases(leases6, pools);
273 populateFreePrefixDelegationLeases(leases6, pools);
282 std::bind(&FreeLeaseQueueAllocator::addLeaseCallback,
this,
283 std::placeholders::_1));
285 std::bind(&FreeLeaseQueueAllocator::updateLeaseCallback,
this,
286 std::placeholders::_1));
288 std::bind(&FreeLeaseQueueAllocator::deleteLeaseCallback,
this,
289 std::placeholders::_1));
292template<
typename LeaseCollectionType>
294FreeLeaseQueueAllocator::populateFreeAddressLeases(
const LeaseCollectionType& leases,
298 .arg(subnet->toText());
305 unordered_set<IOAddress, IOAddress::Hash> leased_addresses;
306 for (
auto const& lease : leases) {
307 if ((lease->getType() ==
pool_type_) && (!lease->expired()) && (!lease->stateExpiredReclaimed())) {
308 leased_addresses.insert(lease->addr_);
312 size_t free_lease_count = 0;
313 for (
auto const& pool : pools) {
316 IPRangePermutation perm(AddressRange(pool->getFirstAddress(), pool->getLastAddress()));
317 auto pool_state = getPoolState(pool);
320 auto address = perm.next(done);
321 if (address.isV4Zero() || address.isV6Zero()) {
324 if (leased_addresses.count(address) == 0) {
326 pool_state->addFreeLease(address);
329 free_lease_count += pool_state->getFreeLeaseCount();
335 .arg(free_lease_count)
336 .arg(subnet->toText())
341FreeLeaseQueueAllocator::populateFreePrefixDelegationLeases(
const Lease6Collection& leases,
345 .arg(subnet->toText());
352 unordered_set<IOAddress, IOAddress::Hash> leased_prefixes;
353 for (
auto const& lease : leases) {
354 if ((lease->getType() ==
Lease::TYPE_PD) && (!lease->expired()) && (!lease->stateExpiredReclaimed())) {
355 leased_prefixes.insert(lease->addr_);
359 size_t free_lease_count = 0;
360 for (
auto const& pool : pools) {
361 auto pool6 = boost::dynamic_pointer_cast<Pool6>(pool);
367 IPRangePermutation perm(PrefixRange(pool->getFirstAddress(),
368 pool->getLastAddress(),
369 pool6->getLength()));
370 auto pool_state = getPoolState(pool);
373 auto prefix = perm.next(done);
374 if (prefix.isV4Zero() || prefix.isV6Zero()) {
377 if (leased_prefixes.count(prefix) == 0) {
379 pool_state->addFreeLease(prefix);
382 free_lease_count += pool_state->getFreeLeaseCount();
388 .arg(free_lease_count)
389 .arg(subnet->toText())
394FreeLeaseQueueAllocator::getPoolState(
const PoolPtr& pool)
const {
395 if (!pool->getAllocationState()) {
398 return (boost::dynamic_pointer_cast<PoolFreeLeaseQueueAllocationState>(pool->getAllocationState()));
402FreeLeaseQueueAllocator::getLeasePool(
const LeasePtr& lease)
const {
407 auto pool = subnet->getPool(
pool_type_, lease->addr_,
false);
412FreeLeaseQueueAllocator::addLeaseCallback(
LeasePtr lease) {
413 MultiThreadingLock lock(
mutex_);
414 addLeaseCallbackInternal(lease);
418FreeLeaseQueueAllocator::addLeaseCallbackInternal(
LeasePtr lease) {
419 if (lease->expired()) {
422 auto pool = getLeasePool(lease);
426 getPoolState(pool)->deleteFreeLease(lease->addr_);
430FreeLeaseQueueAllocator::updateLeaseCallback(
LeasePtr lease) {
431 MultiThreadingLock lock(
mutex_);
432 updateLeaseCallbackInternal(lease);
436FreeLeaseQueueAllocator::updateLeaseCallbackInternal(
LeasePtr lease) {
437 auto pool = getLeasePool(lease);
441 auto pool_state = getPoolState(pool);
442 if (lease->stateExpiredReclaimed() || (lease->expired())) {
443 pool_state->addFreeLease(lease->addr_);
445 pool_state->deleteFreeLease(lease->addr_);
450FreeLeaseQueueAllocator::deleteLeaseCallback(
LeasePtr lease) {
451 MultiThreadingLock lock(
mutex_);
452 deleteLeaseCallbackInternal(lease);
456FreeLeaseQueueAllocator::deleteLeaseCallbackInternal(
LeasePtr lease) {
457 auto pool = getLeasePool(lease);
461 getPoolState(pool)->addFreeLease(lease->addr_);
465FreeLeaseQueueAllocator::getRandomNumber(uint64_t limit) {
470 std::uniform_int_distribution<uint64_t> dist(0, limit);
471 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.
virtual void initAfterConfigureInternal()
Allocator-specific initialization function.
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.
virtual double getOccupancyRate(const asiolink::IOAddress &addr, const ClientClasses &client_classes)
Returns the occupancy rate (v4 addresses).
FreeLeaseQueueAllocator(Lease::Type type, const WeakSubnetPtr &subnet)
Constructor.
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_PD
the lease contains IPv6 prefix (for prefix delegation)
@ TYPE_NA
the lease contains non-temporary IPv6 address
RAII lock object to protect the code in the same scope with a mutex.