Skip to content
GitLab
Menu
Projects
Groups
Snippets
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
Menu
Open sidebar
ISC Open Source Projects
Kea
Commits
5c5c3c52
Commit
5c5c3c52
authored
Jan 19, 2018
by
Francis Dupont
Browse files
[5425a] Rebased and known client removal: first phase done
parent
ac01be53
Changes
15
Expand all
Hide whitespace changes
Inline
Side-by-side
src/lib/dhcpsrv/alloc_engine.cc
View file @
5c5c3c52
...
...
@@ -144,19 +144,33 @@ AllocEngine::IterativeAllocator::increasePrefix(const isc::asiolink::IOAddress&
return
(
IOAddress
::
fromBytes
(
AF_INET6
,
packed
));
}
isc
::
asiolink
::
IOAddress
AllocEngine
::
IterativeAllocator
::
increaseAddress
(
const
isc
::
asiolink
::
IOAddress
&
address
,
bool
prefix
,
const
uint8_t
prefix_len
)
{
if
(
!
prefix
)
{
return
(
IOAddress
::
increase
(
address
));
}
else
{
return
(
increasePrefix
(
address
,
prefix_len
));
}
}
isc
::
asiolink
::
IOAddress
AllocEngine
::
IterativeAllocator
::
pickAddress
(
const
SubnetPtr
&
subnet
,
const
ClientClasses
&
client_classes
,
const
DuidPtr
&
,
const
IOAddress
&
)
{
// Is this prefix allocation?
bool
prefix
=
pool_type_
==
Lease
::
TYPE_PD
;
uint8_t
prefix_len
=
0
;
// 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
=
subnet
->
getLastAllocated
(
pool_type_
);
bool
valid
=
true
;
bool
retrying
=
false
;
const
PoolCollection
&
pools
=
subnet
->
getPools
(
pool_type_
);
...
...
@@ -166,58 +180,108 @@ AllocEngine::IterativeAllocator::pickAddress(const SubnetPtr& subnet,
// first we need to find a pool the last address belongs to.
PoolCollection
::
const_iterator
it
;
PoolCollection
::
const_iterator
first
=
pools
.
end
();
PoolPtr
first_pool
;
for
(
it
=
pools
.
begin
();
it
!=
pools
.
end
();
++
it
)
{
if
(
!
(
*
it
)
->
clientSupported
(
client_classes
))
{
continue
;
}
if
(
first
==
pools
.
end
())
{
first
=
it
;
}
if
((
*
it
)
->
inRange
(
last
))
{
break
;
}
}
// Caller checked this cannot happen
if
(
first
==
pools
.
end
())
{
isc_throw
(
AllocFailed
,
"No allowed pools defined in selected subnet"
);
}
// last one was bogus for one of several reasons:
// - we just booted up and that's the first address we're allocating
// - a subnet was removed or other reconfiguration just completed
// - perhaps allocation algorithm was changed
// - last pool does not allow this client
if
(
it
==
pools
.
end
())
{
// ok to access first element directly. We checked that pools is non-empty
IOAddress
next
=
pools
[
0
]
->
getFirstAddress
();
subnet
->
setLastAllocated
(
pool_type_
,
next
);
return
(
next
);
it
=
first
;
}
// Ok, we have a pool that the last address belonged to, let's use it.
for
(;;)
{
// Trying next pool
if
(
retrying
)
{
for
(;
it
!=
pools
.
end
();
++
it
)
{
if
((
*
it
)
->
clientSupported
(
client_classes
))
{
break
;
}
}
if
(
it
==
pools
.
end
())
{
// Really out of luck today. That was the last pool.
break
;
}
}
IOAddress
next
(
"::"
);
if
(
!
prefix
)
{
next
=
IOAddress
::
increase
(
last
);
// basically addr++
}
else
{
Pool6Ptr
pool6
=
boost
::
dynamic_pointer_cast
<
Pool6
>
(
*
it
);
if
(
!
pool6
)
{
// Something is gravely wrong here
isc_throw
(
Unexpected
,
"Wrong type of pool: "
<<
(
*
it
)
->
toText
()
<<
" is not Pool6"
);
last
=
(
*
it
)
->
getLastAllocated
();
valid
=
(
*
it
)
->
isLastAllocatedValid
();
if
(
!
valid
&&
(
last
==
(
*
it
)
->
getFirstAddress
()))
{
// Pool was (re)initialized
(
*
it
)
->
setLastAllocated
(
last
);
subnet
->
setLastAllocated
(
pool_type_
,
last
);
return
(
last
);
}
// Get the next prefix
next
=
increasePrefix
(
last
,
pool6
->
getLength
());
}
if
((
*
it
)
->
inRange
(
next
))
{
// the next one is in the pool as well, so we haven't hit pool boundary yet
subnet
->
setLastAllocated
(
pool_type_
,
next
);
return
(
next
);
// still can be bogus
if
(
valid
&&
!
(
*
it
)
->
inRange
(
last
))
{
valid
=
false
;
(
*
it
)
->
resetLastAllocated
();
(
*
it
)
->
setLastAllocated
((
*
it
)
->
getFirstAddress
());
}
if
(
valid
)
{
// Ok, we have a pool that the last address belonged to, let's use it.
if
(
prefix
)
{
Pool6Ptr
pool6
=
boost
::
dynamic_pointer_cast
<
Pool6
>
(
*
it
);
if
(
!
pool6
)
{
// Something is gravely wrong here
isc_throw
(
Unexpected
,
"Wrong type of pool: "
<<
(
*
it
)
->
toText
()
<<
" is not Pool6"
);
}
// Get the prefix length
prefix_len
=
pool6
->
getLength
();
}
IOAddress
next
=
increaseAddress
(
last
,
prefix
,
prefix_len
);
if
((
*
it
)
->
inRange
(
next
))
{
// the next one is in the pool as well, so we haven't hit
// pool boundary yet
(
*
it
)
->
setLastAllocated
(
next
);
subnet
->
setLastAllocated
(
pool_type_
,
next
);
return
(
next
);
}
valid
=
false
;
(
*
it
)
->
resetLastAllocated
();
}
// We hit pool boundary, let's try to jump to the next pool and try again
++
it
;
retrying
=
true
;
}
// We hit pool boundary, let's try to jump to the next pool and try again
++
it
;
if
(
it
==
pools
.
end
())
{
// Really out of luck today. That was the last pool. Let's rewind
// to the beginning.
next
=
pools
[
0
]
->
getFirstAddress
();
subnet
->
setLastAllocated
(
pool_type_
,
next
);
return
(
next
);
// Let's rewind to the beginning.
for
(
it
=
first
;
it
!=
pools
.
end
();
++
it
)
{
if
((
*
it
)
->
clientSupported
(
client_classes
))
{
(
*
it
)
->
setLastAllocated
((
*
it
)
->
getFirstAddress
());
(
*
it
)
->
resetLastAllocated
();
}
}
// there is a next pool, let's try first address from it
next
=
(
*
it
)
->
getFirstAddress
();
subnet
->
setLastAllocated
(
pool_type_
,
next
);
return
(
next
);
// ok to access first element directly. We checked that pools is non-empty
last
=
(
*
first
)
->
getLastAllocated
();
(
*
first
)
->
setLastAllocated
(
last
);
subnet
->
setLastAllocated
(
pool_type_
,
last
);
return
(
last
);
}
AllocEngine
::
HashedAllocator
::
HashedAllocator
(
Lease
::
Type
lease_type
)
...
...
@@ -228,6 +292,7 @@ AllocEngine::HashedAllocator::HashedAllocator(Lease::Type lease_type)
isc
::
asiolink
::
IOAddress
AllocEngine
::
HashedAllocator
::
pickAddress
(
const
SubnetPtr
&
,
const
ClientClasses
&
,
const
DuidPtr
&
,
const
IOAddress
&
)
{
isc_throw
(
NotImplemented
,
"Hashed allocator is not implemented"
);
...
...
@@ -241,6 +306,7 @@ AllocEngine::RandomAllocator::RandomAllocator(Lease::Type lease_type)
isc
::
asiolink
::
IOAddress
AllocEngine
::
RandomAllocator
::
pickAddress
(
const
SubnetPtr
&
,
const
ClientClasses
&
,
const
DuidPtr
&
,
const
IOAddress
&
)
{
isc_throw
(
NotImplemented
,
"Random allocator is not implemented"
);
...
...
@@ -361,20 +427,29 @@ namespace {
/// function when it belongs to a shared network.
/// @param lease_type Type of the lease.
/// @param address IPv6 address or prefix to be checked.
/// @param check_subnet if true only subnets are checked else both subnets
/// and pools are checked
///
/// @return true if address belongs to a pool in a selected subnet or in
/// a pool within any of the subnets belonging to the current shared network.
bool
inAllowedPool
(
AllocEngine
::
ClientContext6
&
ctx
,
const
Lease
::
Type
&
lease_type
,
const
IOAddress
&
address
)
{
const
IOAddress
&
address
,
bool
check_subnet
)
{
// If the subnet belongs to a shared network we will be iterating
// over the subnets that belong to this shared network.
Subnet6Ptr
current_subnet
=
ctx
.
subnet_
;
while
(
current_subnet
)
{
if
(
current_subnet
->
clientSupported
(
ctx
.
query_
->
getClasses
()))
{
if
(
current_subnet
->
inPool
(
lease_type
,
address
))
{
return
(
true
);
if
(
check_subnet
)
{
if
(
current_subnet
->
inPool
(
lease_type
,
address
))
{
return
(
true
);
}
}
else
{
if
(
current_subnet
->
inPool
(
lease_type
,
address
,
ctx
.
query_
->
getClasses
()))
{
return
(
true
);
}
}
}
...
...
@@ -677,7 +752,12 @@ AllocEngine::allocateUnreservedLeases6(ClientContext6& ctx) {
// check if the hint is in pool and is available
// This is equivalent of subnet->inPool(hint), but returns the pool
pool
=
boost
::
dynamic_pointer_cast
<
Pool6
>
(
subnet
->
getPool
(
ctx
.
currentIA
().
type_
,
hint
,
false
));
(
subnet
->
getPool
(
ctx
.
currentIA
().
type_
,
ctx
.
query_
->
getClasses
(),
hint
));
// check if the pool is allowed
if
(
pool
&&
!
pool
->
clientSupported
(
ctx
.
query_
->
getClasses
()))
{
pool
.
reset
();
}
if
(
pool
)
{
...
...
@@ -775,14 +855,23 @@ AllocEngine::allocateUnreservedLeases6(ClientContext6& ctx) {
// - we find a free address
// - we find an address for which the lease has expired
// - we exhaust number of tries
uint64_t
max_attempts
=
(
attempts_
>
0
?
attempts_
:
subnet
->
getPoolCapacity
(
ctx
.
currentIA
().
type_
));
uint64_t
possible_attempts
=
subnet
->
getPoolCapacity
(
ctx
.
currentIA
().
type_
,
ctx
.
query_
->
getClasses
());
// Try next subnet if there is no chance to get something
if
(
possible_attempts
==
0
)
{
subnet
=
subnet
->
getNextSubnet
(
original_subnet
);
continue
;
}
uint64_t
max_attempts
=
(
attempts_
>
0
?
attempts_
:
possible_attempts
);
for
(
uint64_t
i
=
0
;
i
<
max_attempts
;
++
i
)
{
++
total_attempts
;
IOAddress
candidate
=
allocator
->
pickAddress
(
subnet
,
ctx
.
duid_
,
IOAddress
candidate
=
allocator
->
pickAddress
(
subnet
,
ctx
.
query_
->
getClasses
(),
ctx
.
duid_
,
hint
);
/// In-pool reservations: Check if this address is reserved for someone
...
...
@@ -800,7 +889,7 @@ AllocEngine::allocateUnreservedLeases6(ClientContext6& ctx) {
uint8_t
prefix_len
=
128
;
if
(
ctx
.
currentIA
().
type_
==
Lease
::
TYPE_PD
)
{
pool
=
boost
::
dynamic_pointer_cast
<
Pool6
>
(
subnet
->
getPool
(
ctx
.
currentIA
().
type_
,
candidat
e
,
fals
e
));
subnet
->
getPool
(
ctx
.
currentIA
().
type_
,
c
tx
.
query_
->
getClasses
(),
c
andidate
));
if
(
pool
)
{
prefix_len
=
pool
->
getLength
();
}
...
...
@@ -1034,11 +1123,14 @@ AllocEngine::allocateReservedLeases6(ClientContext6& ctx,
void
AllocEngine
::
removeNonmatchingReservedLeases6
(
ClientContext6
&
ctx
,
Lease6Collection
&
existing_leases
)
{
// If there are no leases (so nothing to remove) or
// host reservation is disabled (so there are no reserved leases),
// just return.
if
(
existing_leases
.
empty
()
||
!
ctx
.
subnet_
||
(
ctx
.
subnet_
->
getHostReservationMode
()
==
Network
::
HR_DISABLED
)
)
{
// If there are no leases (so nothing to remove) just return.
if
(
existing_leases
.
empty
()
||
!
ctx
.
subnet_
)
{
return
;
}
// If host reservation is disabled (so there are no reserved leases)
// use the simplified version.
if
(
ctx
.
subnet_
->
getHostReservationMode
()
==
Network
::
HR_DISABLED
)
{
removeNonmatchingReservedNoHostLeases6
(
ctx
,
existing_leases
);
return
;
}
...
...
@@ -1075,7 +1167,8 @@ AllocEngine::removeNonmatchingReservedLeases6(ClientContext6& ctx,
// be allocated to us from a dynamic pool, but we must check if
// this lease belongs to any pool. If it does, we can proceed to
// checking the next lease.
if
(
!
host
&&
inAllowedPool
(
ctx
,
candidate
->
type_
,
candidate
->
addr_
))
{
if
(
!
host
&&
inAllowedPool
(
ctx
,
candidate
->
type_
,
candidate
->
addr_
,
false
))
{
continue
;
}
...
...
@@ -1122,6 +1215,44 @@ AllocEngine::removeNonmatchingReservedLeases6(ClientContext6& ctx,
}
}
void
AllocEngine
::
removeNonmatchingReservedNoHostLeases6
(
ClientContext6
&
ctx
,
Lease6Collection
&
existing_leases
)
{
// We need a copy, so we won't be iterating over a container and
// removing from it at the same time. It's only a copy of pointers,
// so the operation shouldn't be that expensive.
Lease6Collection
copy
=
existing_leases
;
BOOST_FOREACH
(
const
Lease6Ptr
&
candidate
,
copy
)
{
// Lease can be allocated to us from a dynamic pool, but we must
// check if this lease belongs to any allowed pool. If it does,
// we can proceed to checking the next lease.
if
(
inAllowedPool
(
ctx
,
candidate
->
type_
,
candidate
->
addr_
,
false
))
{
continue
;
}
// Remove this lease from LeaseMgr as it doesn't belong to a pool.
LeaseMgrFactory
::
instance
().
deleteLease
(
candidate
->
addr_
);
// Update DNS if needed.
queueNCR
(
CHG_REMOVE
,
candidate
);
// Need to decrease statistic for assigned addresses.
StatsMgr
::
instance
().
addValue
(
StatsMgr
::
generateName
(
"subnet"
,
candidate
->
subnet_id_
,
ctx
.
currentIA
().
type_
==
Lease
::
TYPE_NA
?
"assigned-nas"
:
"assigned-pds"
),
static_cast
<
int64_t
>
(
-
1
));
// Add this to the list of removed leases.
ctx
.
currentIA
().
old_leases_
.
push_back
(
candidate
);
// Let's remove this candidate from existing leases
removeLeases
(
existing_leases
,
candidate
->
addr_
);
}
}
bool
AllocEngine
::
removeLeases
(
Lease6Collection
&
container
,
const
asiolink
::
IOAddress
&
addr
)
{
...
...
@@ -1675,7 +1806,8 @@ AllocEngine::updateLeaseData(ClientContext6& ctx, const Lease6Collection& leases
// If the lease is in the current subnet we need to account
// for the re-assignment of The lease.
if
(
inAllowedPool
(
ctx
,
ctx
.
currentIA
().
type_
,
lease
->
addr_
))
{
if
(
inAllowedPool
(
ctx
,
ctx
.
currentIA
().
type_
,
lease
->
addr_
,
true
))
{
StatsMgr
::
instance
().
addValue
(
StatsMgr
::
generateName
(
"subnet"
,
lease
->
subnet_id_
,
ctx
.
currentIA
().
type_
==
Lease
::
TYPE_NA
?
...
...
@@ -2478,6 +2610,7 @@ void findClientLease(AllocEngine::ClientContext4& ctx, Lease4Ptr& client_lease)
/// within a shared network.
///
/// @todo Update this function to take client classification into account.
/// @note client classification in pools (vs subnets) is checked
///
/// @param ctx Client context. Current subnet may be modified by this
/// function when it belongs to a shared network.
...
...
@@ -2492,7 +2625,8 @@ inAllowedPool(AllocEngine::ClientContext4& ctx, const IOAddress& address) {
Subnet4Ptr
current_subnet
=
ctx
.
subnet_
;
while
(
current_subnet
)
{
if
(
current_subnet
->
inPool
(
Lease
::
TYPE_V4
,
address
))
{
if
(
current_subnet
->
inPool
(
Lease
::
TYPE_V4
,
address
,
ctx
.
query_
->
getClasses
()))
{
// We found a subnet that this address belongs to, so it
// seems that this subnet is the good candidate for allocation.
// Let's update the selected subnet.
...
...
@@ -2816,9 +2950,13 @@ AllocEngine::requestLease4(AllocEngine::ClientContext4& ctx) {
// If the client is requesting an address which is assigned to the client
// let's just renew this address. Also, renew this address if the client
// doesn't request any specific address.
// Added extra checks: the address is reserved or belongs to the dynamic
// pool for the case the pool class has changed before the request.
if
(
client_lease
)
{
if
((
client_lease
->
addr_
==
ctx
.
requested_address_
)
||
ctx
.
requested_address_
.
isV4Zero
())
{
if
(((
client_lease
->
addr_
==
ctx
.
requested_address_
)
||
ctx
.
requested_address_
.
isV4Zero
())
&&
(
hasAddressReservation
(
ctx
)
||
inAllowedPool
(
ctx
,
client_lease
->
addr_
)))
{
LOG_DEBUG
(
alloc_engine_logger
,
ALLOC_ENGINE_DBG_TRACE
,
ALLOC_ENGINE_V4_REQUEST_EXTEND_LEASE
)
...
...
@@ -3214,10 +3352,19 @@ AllocEngine::allocateUnreservedLease4(ClientContext4& ctx) {
client_id
=
ctx
.
clientid_
;
}
const
uint64_t
max_attempts
=
(
attempts_
>
0
?
attempts_
:
subnet
->
getPoolCapacity
(
Lease
::
TYPE_V4
));
uint64_t
possible_attempts
=
subnet
->
getPoolCapacity
(
Lease
::
TYPE_V4
,
ctx
.
query_
->
getClasses
());
uint64_t
max_attempts
=
(
attempts_
>
0
?
attempts_
:
possible_attempts
);
// Skip trying if there is no chance to get something
if
(
possible_attempts
==
0
)
{
max_attempts
=
0
;
}
for
(
uint64_t
i
=
0
;
i
<
max_attempts
;
++
i
)
{
IOAddress
candidate
=
allocator
->
pickAddress
(
subnet
,
client_id
,
IOAddress
candidate
=
allocator
->
pickAddress
(
subnet
,
ctx
.
query_
->
getClasses
(),
client_id
,
ctx
.
requested_address_
);
// If address is not reserved for another client, try to allocate it.
if
(
!
addressReserved
(
candidate
,
ctx
))
{
...
...
src/lib/dhcpsrv/alloc_engine.h
View file @
5c5c3c52
...
...
@@ -8,6 +8,7 @@
#define ALLOC_ENGINE_H
#include <asiolink/io_address.h>
#include <dhcp/classify.h>
#include <dhcp/duid.h>
#include <dhcp/hwaddr.h>
#include <dhcp/pkt4.h>
...
...
@@ -78,13 +79,19 @@ protected:
/// than pickResource(), because nobody would immediately know what the
/// resource means in this context.
///
/// 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
DuidPtr
&
duid
,
pickAddress
(
const
SubnetPtr
&
subnet
,
const
ClientClasses
&
client_classes
,
const
DuidPtr
&
duid
,
const
isc
::
asiolink
::
IOAddress
&
hint
)
=
0
;
/// @brief Default constructor.
...
...
@@ -125,11 +132,13 @@ protected:
/// @brief returns the next address from pools in a subnet
///
/// @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 (ignored)
/// @param hint client's hint (ignored)
/// @return the next address
virtual
isc
::
asiolink
::
IOAddress
pickAddress
(
const
SubnetPtr
&
subnet
,
const
ClientClasses
&
client_classes
,
const
DuidPtr
&
duid
,
const
isc
::
asiolink
::
IOAddress
&
hint
);
protected:
...
...
@@ -147,6 +156,20 @@ protected:
static
isc
::
asiolink
::
IOAddress
increasePrefix
(
const
isc
::
asiolink
::
IOAddress
&
prefix
,
const
uint8_t
prefix_len
);
/// @brief Returns the next address or prefix
///
/// This method works for IPv4 addresses, IPv6 addresses and
/// IPv6 prefixes.
///
/// @param address address or prefix to be increased
/// @param prefix true when the previous argument is a prefix
/// @param prefix_len length of the prefix
/// @return result address or prefix
static
isc
::
asiolink
::
IOAddress
increaseAddress
(
const
isc
::
asiolink
::
IOAddress
&
address
,
bool
prefix
,
const
uint8_t
prefix_len
);
};
/// @brief Address/prefix allocator that gets an address based on a hash
...
...
@@ -164,12 +187,15 @@ protected:
/// @todo: Implement this method
///
/// @param subnet an address will be picked from pool of that subnet
/// @param client_classes list of classes client belongs to
/// @param duid Client's DUID
/// @param hint a hint (last address that was picked)
/// @return selected address
virtual
isc
::
asiolink
::
IOAddress
pickAddress
(
const
SubnetPtr
&
subnet
,
const
DuidPtr
&
duid
,
const
isc
::
asiolink
::
IOAddress
&
hint
);
virtual
isc
::
asiolink
::
IOAddress
pickAddress
(
const
SubnetPtr
&
subnet
,
const
ClientClasses
&
client_classes
,
const
DuidPtr
&
duid
,
const
isc
::
asiolink
::
IOAddress
&
hint
);
};
/// @brief Random allocator that picks address randomly
...
...
@@ -191,7 +217,9 @@ protected:
/// @param hint the last address that was picked (ignored)
/// @return a random address from the pool
virtual
isc
::
asiolink
::
IOAddress
pickAddress
(
const
SubnetPtr
&
subnet
,
const
DuidPtr
&
duid
,
pickAddress
(
const
SubnetPtr
&
subnet
,
const
ClientClasses
&
client_classes
,
const
DuidPtr
&
duid
,
const
isc
::
asiolink
::
IOAddress
&
hint
);
};
...
...
@@ -803,8 +831,8 @@ private:
/// @brief Removes leases that are reserved for someone else.
///
/// Goes through the list specified in existing_leases and removes those that
/// are reserved by someone else
. The removed leases are added to the
/// ctx.removed_leases_ collection.
/// are reserved by someone else
or do not belong to an allowed pool.
///
The removed leases are added to the
ctx.removed_leases_ collection.
///
/// @param ctx client context that contains all details (subnet, client-id, etc.)
/// @param existing_leases [in/out] leases that should be checked
...
...
@@ -812,6 +840,17 @@ private:
removeNonmatchingReservedLeases6
(
ClientContext6
&
ctx
,
Lease6Collection
&
existing_leases
);
/// @brief Removes leases that are reserved for someone else.
///
/// Simplified version of removeNonmatchingReservedLeases6 to be
/// used when host reservations are disabled.
///
/// @param ctx client context that contains all details (subnet, client-id, etc.)
/// @param existing_leases [in/out] leases that should be checked
void
removeNonmatchingReservedNoHostLeases6
(
ClientContext6
&
ctx
,
Lease6Collection
&
existing_leases
);
/// @brief Removed leases that are not reserved for this client
///
/// This method iterates over existing_leases and will remove leases that are
...
...
src/lib/dhcpsrv/parsers/dhcp_parsers.cc
View file @
5c5c3c52
...
...
@@ -377,6 +377,15 @@ PoolParser::parse(PoolStoragePtr pools,
<<
" ("
<<
option_data
->
getPosition
()
<<
")"
);
}
}
// Client-class.
ConstElementPtr
client_class
=
pool_structure
->
get
(
"client-class"
);
if
(
client_class
)
{
string
cclass
=
client_class
->
stringValue
();
if
(
!
cclass
.
empty
())
{
pool
->
allowClientClass
(
cclass
);
}
}
}
//****************************** Pool4Parser *************************
...
...
@@ -846,6 +855,11 @@ PdPoolParser::parse(PoolStoragePtr pools, ConstElementPtr pd_pool_) {
user_context_
=
user_context
;
}
ConstElementPtr
client_class
=
pd_pool_
->
get
(
"client-class"
);
if
(
client_class
)
{
client_class_
=
client_class
;
}
// Check the pool parameters. It will throw an exception if any
// of the required parameters are invalid.
try
{
...
...
@@ -869,6 +883,14 @@ PdPoolParser::parse(PoolStoragePtr pools, ConstElementPtr pd_pool_) {
pool_
->
setContext
(
user_context_
);
}
if
(
client_class_
)
{
string
cclass
=
client_class_
->
stringValue
();
if
(
!
cclass
.
empty
())
{
pool_
->
allowClientClass
(
cclass
);
}
}
// Add the local pool to the external storage ptr.
pools
->
push_back
(
pool_
);
}
...
...
src/lib/dhcpsrv/parsers/dhcp_parsers.h
View file @
5c5c3c52
...
...
@@ -652,6 +652,9 @@ private:
CfgOptionPtr
options_
;
isc
::
data
::
ConstElementPtr
user_context_
;
isc
::
data
::
ConstElementPtr
client_class_
;
};
/// @brief Parser for a list of prefix delegation pools.
...
...
src/lib/dhcpsrv/pool.cc
View file @
5c5c3c52
...
...
@@ -18,13 +18,35 @@ namespace dhcp {
Pool
::
Pool
(
Lease
::
Type
type
,
const
isc
::
asiolink
::
IOAddress
&
first
,
const
isc
::
asiolink
::
IOAddress
&
last
)
:
id_
(
getNextID
()),
first_
(
first
),
last_
(
last
),
type_
(
type
),
capacity_
(
0
),
cfg_option_
(
new
CfgOption
())
{
capacity_
(
0
),
cfg_option_
(
new
CfgOption
()),
white_list_
(),
last_allocated_
(
first
),
last_allocated_valid_
(
false
)
{
}
bool
Pool
::
inRange
(
const
isc
::
asiolink
::
IOAddress
&
addr
)
const
{
return
(
first_
.
smallerEqual
(
addr
)
&&
addr
.
smallerEqual
(
last_
));
}
bool
Pool
::
clientSupported
(
const
ClientClasses
&
classes
)
const
{
if
(
white_list_
.
empty
())
{
// There is no class defined for this pool, so we do
// support everyone.
return
(
true
);
}
for
(
ClientClasses
::
const_iterator
it
=
white_list_
.
begin
();
it
!=
white_list_
.
end
();
++
it
)
{
if
(
classes
.
contains
(
*
it
))
{
return
(
true
);
}
}
return
(
false
);
}