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));
253FreeLeaseQueueAllocator::initAfterConfigureInternal() {
255 auto const& pools = subnet->getPools(
pool_type_);
265 populateFreeAddressLeases(leases4, pools);
270 populateFreeAddressLeases(leases6, pools);
274 populateFreePrefixDelegationLeases(leases6, pools);
283 std::bind(&FreeLeaseQueueAllocator::addLeaseCallback,
this,
284 std::placeholders::_1));
286 std::bind(&FreeLeaseQueueAllocator::updateLeaseCallback,
this,
287 std::placeholders::_1));
289 std::bind(&FreeLeaseQueueAllocator::deleteLeaseCallback,
this,
290 std::placeholders::_1));
293template<
typename LeaseCollectionType>
295FreeLeaseQueueAllocator::populateFreeAddressLeases(
const LeaseCollectionType& leases,
299 .arg(subnet->toText());
306 unordered_set<IOAddress, IOAddress::Hash> leased_addresses;
307 for (
auto const& lease : leases) {
308 if ((lease->getType() ==
pool_type_) && (!lease->expired()) && (!lease->stateExpiredReclaimed())) {
309 leased_addresses.insert(lease->addr_);
313 size_t free_lease_count = 0;
314 for (
auto const& pool : pools) {
317 IPRangePermutation perm(AddressRange(pool->getFirstAddress(), pool->getLastAddress()));
318 auto pool_state = getPoolState(pool);
321 auto address = perm.next(done);
322 if (address.isV4Zero() || address.isV6Zero()) {
325 if (leased_addresses.count(address) == 0) {
327 pool_state->addFreeLease(address);
330 free_lease_count += pool_state->getFreeLeaseCount();
336 .arg(free_lease_count)
337 .arg(subnet->toText())
342FreeLeaseQueueAllocator::populateFreePrefixDelegationLeases(
const Lease6Collection& leases,
346 .arg(subnet->toText());
353 unordered_set<IOAddress, IOAddress::Hash> leased_prefixes;
354 for (
auto const& lease : leases) {
355 if ((lease->getType() ==
Lease::TYPE_PD) && (!lease->expired()) && (!lease->stateExpiredReclaimed())) {
356 leased_prefixes.insert(lease->addr_);
360 size_t free_lease_count = 0;
361 for (
auto const& pool : pools) {
362 auto pool6 = boost::dynamic_pointer_cast<Pool6>(pool);
368 IPRangePermutation perm(PrefixRange(pool->getFirstAddress(),
369 pool->getLastAddress(),
370 pool6->getLength()));
371 auto pool_state = getPoolState(pool);
374 auto prefix = perm.next(done);
375 if (prefix.isV4Zero() || prefix.isV6Zero()) {
378 if (leased_prefixes.count(prefix) == 0) {
380 pool_state->addFreeLease(prefix);
383 free_lease_count += pool_state->getFreeLeaseCount();
389 .arg(free_lease_count)
390 .arg(subnet->toText())
395FreeLeaseQueueAllocator::getPoolState(
const PoolPtr& pool)
const {
396 if (!pool->getAllocationState()) {
399 return (boost::dynamic_pointer_cast<PoolFreeLeaseQueueAllocationState>(pool->getAllocationState()));
403FreeLeaseQueueAllocator::getLeasePool(
const LeasePtr& lease)
const {
408 auto pool = subnet->getPool(
pool_type_, lease->addr_,
false);
413FreeLeaseQueueAllocator::addLeaseCallback(
LeasePtr lease) {
414 MultiThreadingLock lock(
mutex_);
415 addLeaseCallbackInternal(lease);
419FreeLeaseQueueAllocator::addLeaseCallbackInternal(
LeasePtr lease) {
420 if (lease->expired()) {
423 auto pool = getLeasePool(lease);
427 getPoolState(pool)->deleteFreeLease(lease->addr_);
431FreeLeaseQueueAllocator::updateLeaseCallback(
LeasePtr lease) {
432 MultiThreadingLock lock(
mutex_);
433 updateLeaseCallbackInternal(lease);
437FreeLeaseQueueAllocator::updateLeaseCallbackInternal(
LeasePtr lease) {
438 auto pool = getLeasePool(lease);
442 auto pool_state = getPoolState(pool);
443 if (lease->stateExpiredReclaimed() || (lease->expired())) {
444 pool_state->addFreeLease(lease->addr_);
446 pool_state->deleteFreeLease(lease->addr_);
451FreeLeaseQueueAllocator::deleteLeaseCallback(
LeasePtr lease) {
452 MultiThreadingLock lock(
mutex_);
453 deleteLeaseCallbackInternal(lease);
457FreeLeaseQueueAllocator::deleteLeaseCallbackInternal(
LeasePtr lease) {
458 auto pool = getLeasePool(lease);
462 getPoolState(pool)->addFreeLease(lease->addr_);
466FreeLeaseQueueAllocator::getRandomNumber(uint64_t limit) {
471 std::uniform_int_distribution<uint64_t> dist(0, limit);
472 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.
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_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
RAII lock object to protect the code in the same scope with a mutex.