mirror of
https://gitlab.isc.org/isc-projects/kea
synced 2025-08-31 14:05:33 +00:00
[2320] Allocation Engine for IPv4 implemented
This commit is contained in:
@@ -260,6 +260,114 @@ AllocEngine::allocateAddress6(const Subnet6Ptr& subnet,
|
|||||||
<< " tries");
|
<< " tries");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Lease4Ptr
|
||||||
|
AllocEngine::allocateAddress4(const SubnetPtr& subnet,
|
||||||
|
const ClientIdPtr& clientid,
|
||||||
|
const HWAddrPtr& hwaddr,
|
||||||
|
const IOAddress& hint,
|
||||||
|
bool fake_allocation /* = false */ ) {
|
||||||
|
|
||||||
|
// That check is not necessary. We create allocator in AllocEngine
|
||||||
|
// constructor
|
||||||
|
if (!allocator_) {
|
||||||
|
isc_throw(InvalidOperation, "No allocator selected");
|
||||||
|
}
|
||||||
|
|
||||||
|
// check if there's existing lease for that subnet/clientid/hwaddr combination.
|
||||||
|
Lease4Ptr existing = LeaseMgrFactory::instance().getLease4(hwaddr->hwaddr_, subnet->getID());
|
||||||
|
if (existing) {
|
||||||
|
// we have a lease already. This is a returning client, probably after
|
||||||
|
// his reboot.
|
||||||
|
return (existing);
|
||||||
|
}
|
||||||
|
|
||||||
|
existing = LeaseMgrFactory::instance().getLease4(*clientid, subnet->getID());
|
||||||
|
if (existing) {
|
||||||
|
// we have a lease already. This is a returning client, probably after
|
||||||
|
// his reboot.
|
||||||
|
|
||||||
|
// @todo: produce a warning. We haven't found him using MAC address, but
|
||||||
|
// we found him using client-id
|
||||||
|
return (existing);
|
||||||
|
}
|
||||||
|
|
||||||
|
// check if the hint is in pool and is available
|
||||||
|
if (subnet->inPool(hint)) {
|
||||||
|
existing = LeaseMgrFactory::instance().getLease4(hint);
|
||||||
|
if (!existing) {
|
||||||
|
/// @todo: check if the hint is reserved once we have host support
|
||||||
|
/// implemented
|
||||||
|
|
||||||
|
// the hint is valid and not currently used, let's create a lease for it
|
||||||
|
Lease4Ptr lease = createLease4(subnet, clientid, hwaddr, hint, fake_allocation);
|
||||||
|
|
||||||
|
// It can happen that the lease allocation failed (we could have lost
|
||||||
|
// the race condition. That means that the hint is lo longer usable and
|
||||||
|
// we need to continue the regular allocation path.
|
||||||
|
if (lease) {
|
||||||
|
return (lease);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (existing->expired()) {
|
||||||
|
return (reuseExpiredLease(existing, subnet, clientid, hwaddr,
|
||||||
|
fake_allocation));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Hint is in the pool but is not available. Search the pool until first of
|
||||||
|
// the following occurs:
|
||||||
|
// - we find a free address
|
||||||
|
// - we find an address for which the lease has expired
|
||||||
|
// - we exhaust number of tries
|
||||||
|
//
|
||||||
|
// @todo: Current code does not handle pool exhaustion well. It will be
|
||||||
|
// improved. Current problems:
|
||||||
|
// 1. with attempts set to too large value (e.g. 1000) and a small pool (e.g.
|
||||||
|
// 10 addresses), we will iterate over it 100 times before giving up
|
||||||
|
// 2. attempts 0 mean unlimited (this is really UINT_MAX, not infinite)
|
||||||
|
// 3. the whole concept of infinite attempts is just asking for infinite loop
|
||||||
|
// We may consider some form or reference counting (this pool has X addresses
|
||||||
|
// left), but this has one major problem. We exactly control allocation
|
||||||
|
// moment, but we currently do not control expiration time at all
|
||||||
|
|
||||||
|
unsigned int i = attempts_;
|
||||||
|
do {
|
||||||
|
IOAddress candidate = allocator_->pickAddress(subnet, clientid, hint);
|
||||||
|
|
||||||
|
/// @todo: check if the address is reserved once we have host support
|
||||||
|
/// implemented
|
||||||
|
|
||||||
|
Lease4Ptr existing = LeaseMgrFactory::instance().getLease4(candidate);
|
||||||
|
if (!existing) {
|
||||||
|
// there's no existing lease for selected candidate, so it is
|
||||||
|
// free. Let's allocate it.
|
||||||
|
Lease4Ptr lease = createLease4(subnet, clientid, hwaddr, candidate,
|
||||||
|
fake_allocation);
|
||||||
|
if (lease) {
|
||||||
|
return (lease);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Although the address was free just microseconds ago, it may have
|
||||||
|
// been taken just now. If the lease insertion fails, we continue
|
||||||
|
// allocation attempts.
|
||||||
|
} else {
|
||||||
|
if (existing->expired()) {
|
||||||
|
return (reuseExpiredLease(existing, subnet, clientid, hwaddr,
|
||||||
|
fake_allocation));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// continue trying allocation until we run out of attempts
|
||||||
|
// (or attempts are set to 0, which means infinite)
|
||||||
|
--i;
|
||||||
|
} while ( i || !attempts_);
|
||||||
|
|
||||||
|
isc_throw(AllocFailed, "Failed to allocate address after " << attempts_
|
||||||
|
<< " tries");
|
||||||
|
}
|
||||||
|
|
||||||
Lease6Ptr AllocEngine::reuseExpiredLease(Lease6Ptr& expired,
|
Lease6Ptr AllocEngine::reuseExpiredLease(Lease6Ptr& expired,
|
||||||
const Subnet6Ptr& subnet,
|
const Subnet6Ptr& subnet,
|
||||||
const DuidPtr& duid,
|
const DuidPtr& duid,
|
||||||
@@ -300,6 +408,45 @@ Lease6Ptr AllocEngine::reuseExpiredLease(Lease6Ptr& expired,
|
|||||||
return (expired);
|
return (expired);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Lease4Ptr AllocEngine::reuseExpiredLease(Lease4Ptr& expired,
|
||||||
|
const SubnetPtr& subnet,
|
||||||
|
const ClientIdPtr& clientid,
|
||||||
|
const HWAddrPtr& hwaddr,
|
||||||
|
bool fake_allocation /*= false */ ) {
|
||||||
|
|
||||||
|
if (!expired->expired()) {
|
||||||
|
isc_throw(BadValue, "Attempt to recycle lease that is still valid");
|
||||||
|
}
|
||||||
|
|
||||||
|
// address, lease type and prefixlen (0) stay the same
|
||||||
|
expired->client_id_ = clientid;
|
||||||
|
expired->hwaddr_ = hwaddr->hwaddr_;
|
||||||
|
expired->valid_lft_ = subnet->getValid();
|
||||||
|
expired->t1_ = subnet->getT1();
|
||||||
|
expired->t2_ = subnet->getT2();
|
||||||
|
expired->cltt_ = time(NULL);
|
||||||
|
expired->subnet_id_ = subnet->getID();
|
||||||
|
expired->fixed_ = false;
|
||||||
|
expired->hostname_ = std::string("");
|
||||||
|
expired->fqdn_fwd_ = false;
|
||||||
|
expired->fqdn_rev_ = false;
|
||||||
|
|
||||||
|
/// @todo: log here that the lease was reused (there's ticket #2524 for
|
||||||
|
/// logging in libdhcpsrv)
|
||||||
|
|
||||||
|
if (!fake_allocation) {
|
||||||
|
// for REQUEST we do update the lease
|
||||||
|
LeaseMgrFactory::instance().updateLease4(expired);
|
||||||
|
}
|
||||||
|
|
||||||
|
// We do nothing for SOLICIT. We'll just update database when
|
||||||
|
// the client gets back to us with REQUEST message.
|
||||||
|
|
||||||
|
// it's not really expired at this stage anymore - let's return it as
|
||||||
|
// an updated lease
|
||||||
|
return (expired);
|
||||||
|
}
|
||||||
|
|
||||||
Lease6Ptr AllocEngine::createLease6(const Subnet6Ptr& subnet,
|
Lease6Ptr AllocEngine::createLease6(const Subnet6Ptr& subnet,
|
||||||
const DuidPtr& duid,
|
const DuidPtr& duid,
|
||||||
uint32_t iaid,
|
uint32_t iaid,
|
||||||
@@ -338,6 +485,48 @@ Lease6Ptr AllocEngine::createLease6(const Subnet6Ptr& subnet,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Lease4Ptr AllocEngine::createLease4(const SubnetPtr& subnet,
|
||||||
|
const DuidPtr& clientid,
|
||||||
|
const HWAddrPtr& hwaddr,
|
||||||
|
const IOAddress& addr,
|
||||||
|
bool fake_allocation /*= false */ ) {
|
||||||
|
if (!hwaddr) {
|
||||||
|
isc_throw(BadValue, "Can't create a lease with NULL HW address");
|
||||||
|
}
|
||||||
|
time_t now = time(NULL);
|
||||||
|
Lease4Ptr lease(new Lease4(addr, &hwaddr->hwaddr_[0], hwaddr->hwaddr_.size(),
|
||||||
|
&clientid->getDuid()[0], clientid->getDuid().size(),
|
||||||
|
subnet->getValid(), subnet->getT1(), subnet->getT2(),
|
||||||
|
now, subnet->getID()));
|
||||||
|
|
||||||
|
if (!fake_allocation) {
|
||||||
|
// That is a real (REQUEST) allocation
|
||||||
|
bool status = LeaseMgrFactory::instance().addLease(lease);
|
||||||
|
|
||||||
|
if (status) {
|
||||||
|
return (lease);
|
||||||
|
} else {
|
||||||
|
// One of many failures with LeaseMgr (e.g. lost connection to the
|
||||||
|
// database, database failed etc.). One notable case for that
|
||||||
|
// is that we are working in multi-process mode and we lost a race
|
||||||
|
// (some other process got that address first)
|
||||||
|
return (Lease4Ptr());
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// That is only fake (DISCOVER) allocation
|
||||||
|
|
||||||
|
// It is for OFFER only. We should not insert the lease into LeaseMgr,
|
||||||
|
// but rather check that we could have inserted it.
|
||||||
|
Lease4Ptr existing = LeaseMgrFactory::instance().getLease4(addr);
|
||||||
|
if (!existing) {
|
||||||
|
return (lease);
|
||||||
|
} else {
|
||||||
|
return (Lease4Ptr());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
AllocEngine::~AllocEngine() {
|
AllocEngine::~AllocEngine() {
|
||||||
// no need to delete allocator. smart_ptr will do the trick for us
|
// no need to delete allocator. smart_ptr will do the trick for us
|
||||||
}
|
}
|
||||||
|
@@ -17,6 +17,7 @@
|
|||||||
|
|
||||||
#include <asiolink/io_address.h>
|
#include <asiolink/io_address.h>
|
||||||
#include <dhcp/duid.h>
|
#include <dhcp/duid.h>
|
||||||
|
#include <dhcp/hwaddr.h>
|
||||||
#include <dhcpsrv/subnet.h>
|
#include <dhcpsrv/subnet.h>
|
||||||
#include <dhcpsrv/lease_mgr.h>
|
#include <dhcpsrv/lease_mgr.h>
|
||||||
|
|
||||||
@@ -182,13 +183,15 @@ protected:
|
|||||||
///
|
///
|
||||||
/// @param subnet subnet the allocation should come from
|
/// @param subnet subnet the allocation should come from
|
||||||
/// @param clientid Client identifier
|
/// @param clientid Client identifier
|
||||||
|
/// @param hwaddr client's hardware address info
|
||||||
/// @param hint a hint that the client provided
|
/// @param hint a hint that the client provided
|
||||||
/// @param fake_allocation is this real i.e. REQUEST (false) or just picking
|
/// @param fake_allocation is this real i.e. REQUEST (false) or just picking
|
||||||
/// an address for DISCOVER that is not really allocated (true)
|
/// an address for DISCOVER that is not really allocated (true)
|
||||||
/// @return Allocated IPv4 lease (or NULL if allocation failed)
|
/// @return Allocated IPv4 lease (or NULL if allocation failed)
|
||||||
Lease4Ptr
|
Lease4Ptr
|
||||||
allocateAddress4(const SubnetPtr& subnet,
|
allocateAddress4(const SubnetPtr& subnet,
|
||||||
const DuidPtr& clientid,
|
const ClientIdPtr& clientid,
|
||||||
|
const HWAddrPtr& hwaddr,
|
||||||
const isc::asiolink::IOAddress& hint,
|
const isc::asiolink::IOAddress& hint,
|
||||||
bool fake_allocation);
|
bool fake_allocation);
|
||||||
|
|
||||||
@@ -224,12 +227,14 @@ private:
|
|||||||
///
|
///
|
||||||
/// @param subnet subnet the lease is allocated from
|
/// @param subnet subnet the lease is allocated from
|
||||||
/// @param clientid client identifier
|
/// @param clientid client identifier
|
||||||
|
/// @param hwaddr client's hardware address
|
||||||
/// @param addr an address that was selected and is confirmed to be available
|
/// @param addr an address that was selected and is confirmed to be available
|
||||||
/// @param fake_allocation is this real i.e. REQUEST (false) or just picking
|
/// @param fake_allocation is this real i.e. REQUEST (false) or just picking
|
||||||
/// an address for DISCOVER that is not really allocated (true)
|
/// an address for DISCOVER that is not really allocated (true)
|
||||||
/// @return allocated lease (or NULL in the unlikely case of the lease just
|
/// @return allocated lease (or NULL in the unlikely case of the lease just
|
||||||
/// becomed unavailable)
|
/// becomed unavailable)
|
||||||
Lease4Ptr createLease4(const Subnet4Ptr& subnet, const DuidPtr& clientid,
|
Lease4Ptr createLease4(const SubnetPtr& subnet, const DuidPtr& clientid,
|
||||||
|
const HWAddrPtr& hwaddr,
|
||||||
const isc::asiolink::IOAddress& addr,
|
const isc::asiolink::IOAddress& addr,
|
||||||
bool fake_allocation = false);
|
bool fake_allocation = false);
|
||||||
|
|
||||||
@@ -260,12 +265,14 @@ private:
|
|||||||
/// @param expired old, expired lease
|
/// @param expired old, expired lease
|
||||||
/// @param subnet subnet the lease is allocated from
|
/// @param subnet subnet the lease is allocated from
|
||||||
/// @param clientid client identifier
|
/// @param clientid client identifier
|
||||||
|
/// @param hwaddr client's hardware address
|
||||||
/// @param fake_allocation is this real i.e. REQUEST (false) or just picking
|
/// @param fake_allocation is this real i.e. REQUEST (false) or just picking
|
||||||
/// an address for DISCOVER that is not really allocated (true)
|
/// an address for DISCOVER that is not really allocated (true)
|
||||||
/// @return refreshed lease
|
/// @return refreshed lease
|
||||||
/// @throw BadValue if trying to recycle lease that is still valid
|
/// @throw BadValue if trying to recycle lease that is still valid
|
||||||
Lease4Ptr reuseExpiredLease(Lease4Ptr& expired, const Subnet4Ptr& subnet,
|
Lease4Ptr reuseExpiredLease(Lease4Ptr& expired, const SubnetPtr& subnet,
|
||||||
const DuidPtr& clientid,
|
const ClientIdPtr& clientid,
|
||||||
|
const HWAddrPtr& hwaddr,
|
||||||
bool fake_allocation = false);
|
bool fake_allocation = false);
|
||||||
|
|
||||||
/// @brief reuses expired IPv6 lease
|
/// @brief reuses expired IPv6 lease
|
||||||
|
@@ -233,10 +233,10 @@ struct Lease4 : public Lease {
|
|||||||
/// @param valid_lft Lifetime of the lease
|
/// @param valid_lft Lifetime of the lease
|
||||||
/// @param cltt Client last transmission time
|
/// @param cltt Client last transmission time
|
||||||
/// @param subnet_id Subnet identification
|
/// @param subnet_id Subnet identification
|
||||||
Lease4(uint32_t addr, const uint8_t* hwaddr, size_t hwaddr_len,
|
Lease4(const isc::asiolink::IOAddress& addr, const uint8_t* hwaddr, size_t hwaddr_len,
|
||||||
const uint8_t* clientid, size_t clientid_len, uint32_t valid_lft,
|
const uint8_t* clientid, size_t clientid_len, uint32_t valid_lft,
|
||||||
time_t cltt, uint32_t subnet_id)
|
uint32_t t1, uint32_t t2, time_t cltt, uint32_t subnet_id)
|
||||||
: Lease(addr, 0, 0, valid_lft, subnet_id, cltt),
|
: Lease(addr, t1, t2, valid_lft, subnet_id, cltt),
|
||||||
ext_(0), hwaddr_(hwaddr, hwaddr + hwaddr_len),
|
ext_(0), hwaddr_(hwaddr, hwaddr + hwaddr_len),
|
||||||
client_id_(new ClientId(clientid, clientid_len)) {
|
client_id_(new ClientId(clientid, clientid_len)) {
|
||||||
}
|
}
|
||||||
@@ -370,6 +370,7 @@ typedef std::vector<Lease6Ptr> Lease6Collection;
|
|||||||
class LeaseMgr {
|
class LeaseMgr {
|
||||||
public:
|
public:
|
||||||
/// Client hardware address
|
/// Client hardware address
|
||||||
|
/// @todo: migrate to HWAddr structure
|
||||||
typedef std::vector<uint8_t> HWAddr;
|
typedef std::vector<uint8_t> HWAddr;
|
||||||
|
|
||||||
/// Database configuration parameter map
|
/// Database configuration parameter map
|
||||||
|
@@ -13,6 +13,7 @@
|
|||||||
// PERFORMANCE OF THIS SOFTWARE.
|
// PERFORMANCE OF THIS SOFTWARE.
|
||||||
|
|
||||||
#include <dhcpsrv/memfile_lease_mgr.h>
|
#include <dhcpsrv/memfile_lease_mgr.h>
|
||||||
|
#include <exceptions/exceptions.h>
|
||||||
|
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
|
|
||||||
@@ -27,8 +28,13 @@ Memfile_LeaseMgr::Memfile_LeaseMgr(const ParameterMap& parameters)
|
|||||||
Memfile_LeaseMgr::~Memfile_LeaseMgr() {
|
Memfile_LeaseMgr::~Memfile_LeaseMgr() {
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Memfile_LeaseMgr::addLease(const Lease4Ptr&) {
|
bool Memfile_LeaseMgr::addLease(const Lease4Ptr& lease) {
|
||||||
return (false);
|
if (getLease4(lease->addr_)) {
|
||||||
|
// there is a lease with specified address already
|
||||||
|
return (false);
|
||||||
|
}
|
||||||
|
storage4_.insert(lease);
|
||||||
|
return (true);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Memfile_LeaseMgr::addLease(const Lease6Ptr& lease) {
|
bool Memfile_LeaseMgr::addLease(const Lease6Ptr& lease) {
|
||||||
@@ -40,27 +46,51 @@ bool Memfile_LeaseMgr::addLease(const Lease6Ptr& lease) {
|
|||||||
return (true);
|
return (true);
|
||||||
}
|
}
|
||||||
|
|
||||||
Lease4Ptr Memfile_LeaseMgr::getLease4(const isc::asiolink::IOAddress&) const {
|
Lease4Ptr Memfile_LeaseMgr::getLease4(const isc::asiolink::IOAddress& addr) const {
|
||||||
return (Lease4Ptr());
|
Lease4Storage::iterator l = storage4_.find(addr);
|
||||||
|
if (l == storage4_.end()) {
|
||||||
|
return (Lease4Ptr());
|
||||||
|
} else {
|
||||||
|
return (*l);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Lease4Collection Memfile_LeaseMgr::getLease4(const HWAddr& ) const {
|
Lease4Collection Memfile_LeaseMgr::getLease4(const HWAddr& ) const {
|
||||||
|
isc_throw(NotImplemented, "getLease4(HWaddr x) method not implemented yet");
|
||||||
return (Lease4Collection());
|
return (Lease4Collection());
|
||||||
}
|
}
|
||||||
|
|
||||||
Lease4Ptr Memfile_LeaseMgr::getLease4(const HWAddr&,
|
Lease4Ptr Memfile_LeaseMgr::getLease4(const HWAddr& hwaddr,
|
||||||
SubnetID) const {
|
SubnetID id) const {
|
||||||
|
Lease4Storage::iterator l;
|
||||||
|
for (l = storage4_.begin(); l != storage4_.end(); ++l) {
|
||||||
|
if ( ((*l)->hwaddr_ == hwaddr) &&
|
||||||
|
((*l)->subnet_id_ == id)) {
|
||||||
|
return (*l);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// not found
|
||||||
return (Lease4Ptr());
|
return (Lease4Ptr());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
Lease4Ptr Memfile_LeaseMgr::getLease4(const ClientId&,
|
Lease4Ptr Memfile_LeaseMgr::getLease4(const ClientId& client_id,
|
||||||
SubnetID) const {
|
SubnetID subnet_id) const {
|
||||||
|
Lease4Storage::iterator l;
|
||||||
|
for (l = storage4_.begin(); l != storage4_.end(); ++l) {
|
||||||
|
if ( (*(*l)->client_id_ == client_id) &&
|
||||||
|
((*l)->subnet_id_ == subnet_id)) {
|
||||||
|
return (*l);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// not found
|
||||||
return (Lease4Ptr());
|
return (Lease4Ptr());
|
||||||
}
|
}
|
||||||
|
|
||||||
Lease4Collection Memfile_LeaseMgr::getLease4(const ClientId& ) const {
|
Lease4Collection Memfile_LeaseMgr::getLease4(const ClientId& ) const {
|
||||||
return (Lease4Collection());
|
isc_throw(NotImplemented, "getLease4(ClientId) not implemented");
|
||||||
}
|
}
|
||||||
|
|
||||||
Lease6Ptr Memfile_LeaseMgr::getLease6(const isc::asiolink::IOAddress& addr) const {
|
Lease6Ptr Memfile_LeaseMgr::getLease6(const isc::asiolink::IOAddress& addr) const {
|
||||||
@@ -98,11 +128,18 @@ void Memfile_LeaseMgr::updateLease6(const Lease6Ptr& ) {
|
|||||||
|
|
||||||
bool Memfile_LeaseMgr::deleteLease(const isc::asiolink::IOAddress& addr) {
|
bool Memfile_LeaseMgr::deleteLease(const isc::asiolink::IOAddress& addr) {
|
||||||
if (addr.isV4()) {
|
if (addr.isV4()) {
|
||||||
// V4 not implemented yet
|
// v4 lease
|
||||||
return (false);
|
Lease4Storage::iterator l = storage4_.find(addr);
|
||||||
|
if (l == storage4_.end()) {
|
||||||
|
// No such lease
|
||||||
|
return (false);
|
||||||
|
} else {
|
||||||
|
storage4_.erase(l);
|
||||||
|
return (true);
|
||||||
|
}
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
// V6 lease
|
// v6 lease
|
||||||
Lease6Storage::iterator l = storage6_.find(addr);
|
Lease6Storage::iterator l = storage6_.find(addr);
|
||||||
if (l == storage6_.end()) {
|
if (l == storage6_.end()) {
|
||||||
// No such lease
|
// No such lease
|
||||||
|
@@ -231,6 +231,22 @@ protected:
|
|||||||
>
|
>
|
||||||
> Lease6Storage; // Let the whole contraption be called Lease6Storage.
|
> Lease6Storage; // Let the whole contraption be called Lease6Storage.
|
||||||
|
|
||||||
|
typedef boost::multi_index_container< // this is a multi-index container...
|
||||||
|
Lease4Ptr, // it will hold shared_ptr to leases6
|
||||||
|
boost::multi_index::indexed_by< // and will be sorted by
|
||||||
|
// IPv6 address that are unique. That particular key is a member
|
||||||
|
// of the Lease6 structure, is of type IOAddress and can be accessed
|
||||||
|
// by doing &Lease6::addr_
|
||||||
|
boost::multi_index::ordered_unique<
|
||||||
|
boost::multi_index::member<Lease, isc::asiolink::IOAddress, &Lease::addr_>
|
||||||
|
>
|
||||||
|
>
|
||||||
|
> Lease4Storage; // Let the whole contraption be called Lease6Storage.
|
||||||
|
|
||||||
|
/// @brief stores IPv4 leases
|
||||||
|
Lease4Storage storage4_;
|
||||||
|
|
||||||
|
/// @brief stores IPv6 leases
|
||||||
Lease6Storage storage6_;
|
Lease6Storage storage6_;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@@ -448,9 +448,10 @@ public:
|
|||||||
time_t cltt = 0;
|
time_t cltt = 0;
|
||||||
MySqlLeaseMgr::convertFromDatabaseTime(expire_, valid_lifetime_, cltt);
|
MySqlLeaseMgr::convertFromDatabaseTime(expire_, valid_lifetime_, cltt);
|
||||||
|
|
||||||
|
// note that T1 and T2 are not stored
|
||||||
return (Lease4Ptr(new Lease4(addr4_, hwaddr_buffer_, hwaddr_length_,
|
return (Lease4Ptr(new Lease4(addr4_, hwaddr_buffer_, hwaddr_length_,
|
||||||
client_id_buffer_, client_id_length_,
|
client_id_buffer_, client_id_length_,
|
||||||
valid_lifetime_, cltt, subnet_id_)));
|
valid_lifetime_, 0, 0, cltt, subnet_id_)));
|
||||||
}
|
}
|
||||||
|
|
||||||
/// @brief Return columns in error
|
/// @brief Return columns in error
|
||||||
|
@@ -16,6 +16,7 @@
|
|||||||
|
|
||||||
#include <asiolink/io_address.h>
|
#include <asiolink/io_address.h>
|
||||||
#include <dhcp/duid.h>
|
#include <dhcp/duid.h>
|
||||||
|
#include <dhcp/dhcp4.h>
|
||||||
#include <dhcpsrv/alloc_engine.h>
|
#include <dhcpsrv/alloc_engine.h>
|
||||||
#include <dhcpsrv/cfgmgr.h>
|
#include <dhcpsrv/cfgmgr.h>
|
||||||
#include <dhcpsrv/lease_mgr.h>
|
#include <dhcpsrv/lease_mgr.h>
|
||||||
@@ -50,11 +51,10 @@ public:
|
|||||||
using AllocEngine::IterativeAllocator;
|
using AllocEngine::IterativeAllocator;
|
||||||
};
|
};
|
||||||
|
|
||||||
// empty class for now, but may be extended once Addr6 becomes bigger
|
class AllocEngine6Test : public ::testing::Test {
|
||||||
class AllocEngineTest : public ::testing::Test {
|
|
||||||
public:
|
public:
|
||||||
AllocEngineTest() {
|
AllocEngine6Test() {
|
||||||
duid_ = boost::shared_ptr<DUID>(new DUID(vector<uint8_t>(8, 0x42)));
|
duid_ = DuidPtr(new DUID(vector<uint8_t>(8, 0x42)));
|
||||||
iaid_ = 42;
|
iaid_ = 42;
|
||||||
|
|
||||||
// instantiate cfg_mgr
|
// instantiate cfg_mgr
|
||||||
@@ -88,7 +88,7 @@ public:
|
|||||||
// @todo: check cltt
|
// @todo: check cltt
|
||||||
}
|
}
|
||||||
|
|
||||||
~AllocEngineTest() {
|
~AllocEngine6Test() {
|
||||||
factory_.destroy();
|
factory_.destroy();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -99,9 +99,59 @@ public:
|
|||||||
LeaseMgrFactory factory_;
|
LeaseMgrFactory factory_;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class AllocEngine4Test : public ::testing::Test {
|
||||||
|
public:
|
||||||
|
AllocEngine4Test() {
|
||||||
|
clientid_ = ClientIdPtr(new ClientId(vector<uint8_t>(8, 0x44)));
|
||||||
|
static uint8_t mac[] = { 0, 1, 22, 33, 44, 55};
|
||||||
|
|
||||||
|
// Let's use odd hardware type to check if there is no Ethernet
|
||||||
|
// hardcoded anywhere.
|
||||||
|
hwaddr_ = HWAddrPtr(new HWAddr(mac, sizeof(mac), HTYPE_FDDI));
|
||||||
|
|
||||||
|
// instantiate cfg_mgr
|
||||||
|
CfgMgr& cfg_mgr = CfgMgr::instance();
|
||||||
|
|
||||||
|
subnet_ = Subnet4Ptr(new Subnet4(IOAddress("192.0.2.0"), 24, 1, 2, 3));
|
||||||
|
pool_ = Pool4Ptr(new Pool4(IOAddress("192.0.2.100"),
|
||||||
|
IOAddress("192.0.2.109")));
|
||||||
|
subnet_->addPool(pool_);
|
||||||
|
cfg_mgr.addSubnet4(subnet_);
|
||||||
|
|
||||||
|
factory_.create("type=memfile");
|
||||||
|
}
|
||||||
|
|
||||||
|
void checkLease4(const Lease4Ptr& lease) {
|
||||||
|
// that is belongs to the right subnet
|
||||||
|
EXPECT_EQ(lease->subnet_id_, subnet_->getID());
|
||||||
|
EXPECT_TRUE(subnet_->inRange(lease->addr_));
|
||||||
|
EXPECT_TRUE(subnet_->inPool(lease->addr_));
|
||||||
|
|
||||||
|
// that it have proper parameters
|
||||||
|
EXPECT_EQ(subnet_->getValid(), lease->valid_lft_);
|
||||||
|
EXPECT_EQ(subnet_->getT1(), lease->t1_);
|
||||||
|
EXPECT_EQ(subnet_->getT2(), lease->t2_);
|
||||||
|
EXPECT_TRUE(false == lease->fqdn_fwd_);
|
||||||
|
EXPECT_TRUE(false == lease->fqdn_rev_);
|
||||||
|
EXPECT_TRUE(*lease->client_id_ == *clientid_);
|
||||||
|
EXPECT_TRUE(lease->hwaddr_ == hwaddr_->hwaddr_);
|
||||||
|
// @todo: check cltt
|
||||||
|
}
|
||||||
|
|
||||||
|
~AllocEngine4Test() {
|
||||||
|
factory_.destroy();
|
||||||
|
}
|
||||||
|
|
||||||
|
ClientIdPtr clientid_;
|
||||||
|
HWAddrPtr hwaddr_;
|
||||||
|
Subnet4Ptr subnet_;
|
||||||
|
Pool4Ptr pool_;
|
||||||
|
LeaseMgrFactory factory_;
|
||||||
|
};
|
||||||
|
|
||||||
// This test checks if the Allocation Engine can be instantiated and that it
|
// This test checks if the Allocation Engine can be instantiated and that it
|
||||||
// parses parameters string properly.
|
// parses parameters string properly.
|
||||||
TEST_F(AllocEngineTest, constructor) {
|
TEST_F(AllocEngine6Test, constructor) {
|
||||||
boost::scoped_ptr<AllocEngine> x;
|
boost::scoped_ptr<AllocEngine> x;
|
||||||
|
|
||||||
// Hashed and random allocators are not supported yet
|
// Hashed and random allocators are not supported yet
|
||||||
@@ -112,7 +162,7 @@ TEST_F(AllocEngineTest, constructor) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// This test checks if the simple allocation can succeed
|
// This test checks if the simple allocation can succeed
|
||||||
TEST_F(AllocEngineTest, simpleAlloc) {
|
TEST_F(AllocEngine6Test, simpleAlloc6) {
|
||||||
boost::scoped_ptr<AllocEngine> engine;
|
boost::scoped_ptr<AllocEngine> engine;
|
||||||
ASSERT_NO_THROW(engine.reset(new AllocEngine(AllocEngine::ALLOC_ITERATIVE, 100)));
|
ASSERT_NO_THROW(engine.reset(new AllocEngine(AllocEngine::ALLOC_ITERATIVE, 100)));
|
||||||
ASSERT_TRUE(engine);
|
ASSERT_TRUE(engine);
|
||||||
@@ -135,7 +185,7 @@ TEST_F(AllocEngineTest, simpleAlloc) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// This test checks if the fake allocation (for SOLICIT) can succeed
|
// This test checks if the fake allocation (for SOLICIT) can succeed
|
||||||
TEST_F(AllocEngineTest, fakeAlloc) {
|
TEST_F(AllocEngine6Test, fakeAlloc6) {
|
||||||
boost::scoped_ptr<AllocEngine> engine;
|
boost::scoped_ptr<AllocEngine> engine;
|
||||||
ASSERT_NO_THROW(engine.reset(new AllocEngine(AllocEngine::ALLOC_ITERATIVE, 100)));
|
ASSERT_NO_THROW(engine.reset(new AllocEngine(AllocEngine::ALLOC_ITERATIVE, 100)));
|
||||||
ASSERT_TRUE(engine);
|
ASSERT_TRUE(engine);
|
||||||
@@ -156,7 +206,7 @@ TEST_F(AllocEngineTest, fakeAlloc) {
|
|||||||
|
|
||||||
// This test checks if the allocation with a hint that is valid (in range,
|
// This test checks if the allocation with a hint that is valid (in range,
|
||||||
// in pool and free) can succeed
|
// in pool and free) can succeed
|
||||||
TEST_F(AllocEngineTest, allocWithValidHint) {
|
TEST_F(AllocEngine6Test, allocWithValidHint6) {
|
||||||
boost::scoped_ptr<AllocEngine> engine;
|
boost::scoped_ptr<AllocEngine> engine;
|
||||||
ASSERT_NO_THROW(engine.reset(new AllocEngine(AllocEngine::ALLOC_ITERATIVE, 100)));
|
ASSERT_NO_THROW(engine.reset(new AllocEngine(AllocEngine::ALLOC_ITERATIVE, 100)));
|
||||||
ASSERT_TRUE(engine);
|
ASSERT_TRUE(engine);
|
||||||
@@ -184,15 +234,16 @@ TEST_F(AllocEngineTest, allocWithValidHint) {
|
|||||||
|
|
||||||
// This test checks if the allocation with a hint that is in range,
|
// This test checks if the allocation with a hint that is in range,
|
||||||
// in pool, but is currently used) can succeed
|
// in pool, but is currently used) can succeed
|
||||||
TEST_F(AllocEngineTest, allocWithUsedHint) {
|
TEST_F(AllocEngine6Test, allocWithUsedHint6) {
|
||||||
boost::scoped_ptr<AllocEngine> engine;
|
boost::scoped_ptr<AllocEngine> engine;
|
||||||
ASSERT_NO_THROW(engine.reset(new AllocEngine(AllocEngine::ALLOC_ITERATIVE, 100)));
|
ASSERT_NO_THROW(engine.reset(new AllocEngine(AllocEngine::ALLOC_ITERATIVE, 100)));
|
||||||
ASSERT_TRUE(engine);
|
ASSERT_TRUE(engine);
|
||||||
|
|
||||||
// let's create a lease and put it in the LeaseMgr
|
// let's create a lease and put it in the LeaseMgr
|
||||||
DuidPtr duid2 = boost::shared_ptr<DUID>(new DUID(vector<uint8_t>(8, 0xff)));
|
DuidPtr duid2 = boost::shared_ptr<DUID>(new DUID(vector<uint8_t>(8, 0xff)));
|
||||||
|
time_t now = time(NULL);
|
||||||
Lease6Ptr used(new Lease6(Lease6::LEASE_IA_NA, IOAddress("2001:db8:1::1f"),
|
Lease6Ptr used(new Lease6(Lease6::LEASE_IA_NA, IOAddress("2001:db8:1::1f"),
|
||||||
duid2, 1, 2, 3, 4, 5, subnet_->getID()));
|
duid2, 1, 2, 3, 4, now, subnet_->getID()));
|
||||||
ASSERT_TRUE(LeaseMgrFactory::instance().addLease(used));
|
ASSERT_TRUE(LeaseMgrFactory::instance().addLease(used));
|
||||||
|
|
||||||
// another client comes in and request an address that is in pool, but
|
// another client comes in and request an address that is in pool, but
|
||||||
@@ -223,7 +274,7 @@ TEST_F(AllocEngineTest, allocWithUsedHint) {
|
|||||||
|
|
||||||
// This test checks if the allocation with a hint that is out the blue
|
// This test checks if the allocation with a hint that is out the blue
|
||||||
// can succeed. The invalid hint should be ignored completely.
|
// can succeed. The invalid hint should be ignored completely.
|
||||||
TEST_F(AllocEngineTest, allocBogusHint) {
|
TEST_F(AllocEngine6Test, allocBogusHint6) {
|
||||||
boost::scoped_ptr<AllocEngine> engine;
|
boost::scoped_ptr<AllocEngine> engine;
|
||||||
ASSERT_NO_THROW(engine.reset(new AllocEngine(AllocEngine::ALLOC_ITERATIVE, 100)));
|
ASSERT_NO_THROW(engine.reset(new AllocEngine(AllocEngine::ALLOC_ITERATIVE, 100)));
|
||||||
ASSERT_TRUE(engine);
|
ASSERT_TRUE(engine);
|
||||||
@@ -253,7 +304,7 @@ TEST_F(AllocEngineTest, allocBogusHint) {
|
|||||||
|
|
||||||
// This test verifies that the allocator picks addresses that belong to the
|
// This test verifies that the allocator picks addresses that belong to the
|
||||||
// pool
|
// pool
|
||||||
TEST_F(AllocEngineTest, IterativeAllocator) {
|
TEST_F(AllocEngine6Test, IterativeAllocator) {
|
||||||
boost::scoped_ptr<NakedAllocEngine::Allocator>
|
boost::scoped_ptr<NakedAllocEngine::Allocator>
|
||||||
alloc(new NakedAllocEngine::IterativeAllocator());
|
alloc(new NakedAllocEngine::IterativeAllocator());
|
||||||
|
|
||||||
@@ -267,7 +318,7 @@ TEST_F(AllocEngineTest, IterativeAllocator) {
|
|||||||
// This test verifies that the iterative allocator really walks over all addresses
|
// This test verifies that the iterative allocator really walks over all addresses
|
||||||
// in all pools in specified subnet. It also must not pick the same address twice
|
// 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.
|
// unless it runs out of pool space and must start over.
|
||||||
TEST_F(AllocEngineTest, IterativeAllocator_manyPools) {
|
TEST_F(AllocEngine6Test, IterativeAllocator_manyPools6) {
|
||||||
NakedAllocEngine::IterativeAllocator* alloc = new NakedAllocEngine::IterativeAllocator();
|
NakedAllocEngine::IterativeAllocator* alloc = new NakedAllocEngine::IterativeAllocator();
|
||||||
|
|
||||||
// let's start from 2, as there is 2001:db8:1::10 - 2001:db8:1::20 pool already.
|
// let's start from 2, as there is 2001:db8:1::10 - 2001:db8:1::20 pool already.
|
||||||
@@ -322,7 +373,7 @@ TEST_F(AllocEngineTest, IterativeAllocator_manyPools) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// This test checks if really small pools are working
|
// This test checks if really small pools are working
|
||||||
TEST_F(AllocEngineTest, smallPool) {
|
TEST_F(AllocEngine6Test, smallPool6) {
|
||||||
boost::scoped_ptr<AllocEngine> engine;
|
boost::scoped_ptr<AllocEngine> engine;
|
||||||
ASSERT_NO_THROW(engine.reset(new AllocEngine(AllocEngine::ALLOC_ITERATIVE, 100)));
|
ASSERT_NO_THROW(engine.reset(new AllocEngine(AllocEngine::ALLOC_ITERATIVE, 100)));
|
||||||
ASSERT_TRUE(engine);
|
ASSERT_TRUE(engine);
|
||||||
@@ -358,7 +409,7 @@ TEST_F(AllocEngineTest, smallPool) {
|
|||||||
|
|
||||||
// This test checks if all addresses in a pool are currently used, the attempt
|
// This test checks if all addresses in a pool are currently used, the attempt
|
||||||
// to find out a new lease fails.
|
// to find out a new lease fails.
|
||||||
TEST_F(AllocEngineTest, outOfAddresses) {
|
TEST_F(AllocEngine6Test, outOfAddresses6) {
|
||||||
boost::scoped_ptr<AllocEngine> engine;
|
boost::scoped_ptr<AllocEngine> engine;
|
||||||
ASSERT_NO_THROW(engine.reset(new AllocEngine(AllocEngine::ALLOC_ITERATIVE, 100)));
|
ASSERT_NO_THROW(engine.reset(new AllocEngine(AllocEngine::ALLOC_ITERATIVE, 100)));
|
||||||
ASSERT_TRUE(engine);
|
ASSERT_TRUE(engine);
|
||||||
@@ -389,7 +440,7 @@ TEST_F(AllocEngineTest, outOfAddresses) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// This test checks if an expired lease can be reused in SOLICIT (fake allocation)
|
// This test checks if an expired lease can be reused in SOLICIT (fake allocation)
|
||||||
TEST_F(AllocEngineTest, solicitReuseExpiredLease) {
|
TEST_F(AllocEngine6Test, solicitReuseExpiredLease6) {
|
||||||
boost::scoped_ptr<AllocEngine> engine;
|
boost::scoped_ptr<AllocEngine> engine;
|
||||||
ASSERT_NO_THROW(engine.reset(new AllocEngine(AllocEngine::ALLOC_ITERATIVE, 100)));
|
ASSERT_NO_THROW(engine.reset(new AllocEngine(AllocEngine::ALLOC_ITERATIVE, 100)));
|
||||||
ASSERT_TRUE(engine);
|
ASSERT_TRUE(engine);
|
||||||
@@ -413,6 +464,9 @@ TEST_F(AllocEngineTest, solicitReuseExpiredLease) {
|
|||||||
lease->valid_lft_ = 495; // Lease was valid for 495 seconds
|
lease->valid_lft_ = 495; // Lease was valid for 495 seconds
|
||||||
ASSERT_TRUE(LeaseMgrFactory::instance().addLease(lease));
|
ASSERT_TRUE(LeaseMgrFactory::instance().addLease(lease));
|
||||||
|
|
||||||
|
// Make sure that we really created expired lease
|
||||||
|
ASSERT_TRUE(lease->expired());
|
||||||
|
|
||||||
// CASE 1: Asking for any address
|
// CASE 1: Asking for any address
|
||||||
lease = engine->allocateAddress6(subnet_, duid_, iaid_, IOAddress("::"),
|
lease = engine->allocateAddress6(subnet_, duid_, iaid_, IOAddress("::"),
|
||||||
true);
|
true);
|
||||||
@@ -432,7 +486,7 @@ TEST_F(AllocEngineTest, solicitReuseExpiredLease) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// This test checks if an expired lease can be reused in REQUEST (actual allocation)
|
// This test checks if an expired lease can be reused in REQUEST (actual allocation)
|
||||||
TEST_F(AllocEngineTest, requestReuseExpiredLease) {
|
TEST_F(AllocEngine6Test, requestReuseExpiredLease6) {
|
||||||
boost::scoped_ptr<AllocEngine> engine;
|
boost::scoped_ptr<AllocEngine> engine;
|
||||||
ASSERT_NO_THROW(engine.reset(new AllocEngine(AllocEngine::ALLOC_ITERATIVE, 100)));
|
ASSERT_NO_THROW(engine.reset(new AllocEngine(AllocEngine::ALLOC_ITERATIVE, 100)));
|
||||||
ASSERT_TRUE(engine);
|
ASSERT_TRUE(engine);
|
||||||
@@ -473,4 +527,372 @@ TEST_F(AllocEngineTest, requestReuseExpiredLease) {
|
|||||||
detailCompareLease(lease, from_mgr);
|
detailCompareLease(lease, from_mgr);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// --- IPv4 ---
|
||||||
|
|
||||||
|
// This test checks if the simple IPv4 allocation can succeed
|
||||||
|
TEST_F(AllocEngine4Test, simpleAlloc4) {
|
||||||
|
boost::scoped_ptr<AllocEngine> engine;
|
||||||
|
ASSERT_NO_THROW(engine.reset(new AllocEngine(AllocEngine::ALLOC_ITERATIVE, 100)));
|
||||||
|
ASSERT_TRUE(engine);
|
||||||
|
|
||||||
|
Lease4Ptr lease = engine->allocateAddress4(subnet_, clientid_, hwaddr_,
|
||||||
|
IOAddress("0.0.0.0"), false);
|
||||||
|
|
||||||
|
// check that we got a lease
|
||||||
|
ASSERT_TRUE(lease);
|
||||||
|
|
||||||
|
// do all checks on the lease
|
||||||
|
checkLease4(lease);
|
||||||
|
|
||||||
|
// Check that the lease is indeed in LeaseMgr
|
||||||
|
Lease4Ptr from_mgr = LeaseMgrFactory::instance().getLease4(lease->addr_);
|
||||||
|
ASSERT_TRUE(from_mgr);
|
||||||
|
|
||||||
|
// Now check that the lease in LeaseMgr has the same parameters
|
||||||
|
detailCompareLease(lease, from_mgr);
|
||||||
|
}
|
||||||
|
|
||||||
|
// This test checks if the fake allocation (for DISCOVER) can succeed
|
||||||
|
TEST_F(AllocEngine4Test, fakeAlloc4) {
|
||||||
|
boost::scoped_ptr<AllocEngine> engine;
|
||||||
|
ASSERT_NO_THROW(engine.reset(new AllocEngine(AllocEngine::ALLOC_ITERATIVE, 100)));
|
||||||
|
ASSERT_TRUE(engine);
|
||||||
|
|
||||||
|
Lease4Ptr lease = engine->allocateAddress4(subnet_, clientid_, hwaddr_,
|
||||||
|
IOAddress("0.0.0.0"), true);
|
||||||
|
|
||||||
|
// check that we got a lease
|
||||||
|
ASSERT_TRUE(lease);
|
||||||
|
|
||||||
|
// do all checks on the lease
|
||||||
|
checkLease4(lease);
|
||||||
|
|
||||||
|
// Check that the lease is NOT in LeaseMgr
|
||||||
|
Lease4Ptr from_mgr = LeaseMgrFactory::instance().getLease4(lease->addr_);
|
||||||
|
ASSERT_FALSE(from_mgr);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// This test checks if the allocation with a hint that is valid (in range,
|
||||||
|
// in pool and free) can succeed
|
||||||
|
TEST_F(AllocEngine4Test, allocWithValidHint4) {
|
||||||
|
boost::scoped_ptr<AllocEngine> engine;
|
||||||
|
ASSERT_NO_THROW(engine.reset(new AllocEngine(AllocEngine::ALLOC_ITERATIVE, 100)));
|
||||||
|
ASSERT_TRUE(engine);
|
||||||
|
|
||||||
|
Lease4Ptr lease = engine->allocateAddress4(subnet_, clientid_, hwaddr_,
|
||||||
|
IOAddress("192.0.2.105"),
|
||||||
|
false);
|
||||||
|
|
||||||
|
// check that we got a lease
|
||||||
|
ASSERT_TRUE(lease);
|
||||||
|
|
||||||
|
// we should get what we asked for
|
||||||
|
EXPECT_EQ(lease->addr_.toText(), "192.0.2.105");
|
||||||
|
|
||||||
|
// do all checks on the lease
|
||||||
|
checkLease4(lease);
|
||||||
|
|
||||||
|
// Check that the lease is indeed in LeaseMgr
|
||||||
|
Lease4Ptr from_mgr = LeaseMgrFactory::instance().getLease4(lease->addr_);
|
||||||
|
ASSERT_TRUE(from_mgr);
|
||||||
|
|
||||||
|
// Now check that the lease in LeaseMgr has the same parameters
|
||||||
|
detailCompareLease(lease, from_mgr);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// This test checks if the allocation with a hint that is in range,
|
||||||
|
// in pool, but is currently used) can succeed
|
||||||
|
TEST_F(AllocEngine4Test, allocWithUsedHint4) {
|
||||||
|
boost::scoped_ptr<AllocEngine> engine;
|
||||||
|
ASSERT_NO_THROW(engine.reset(new AllocEngine(AllocEngine::ALLOC_ITERATIVE, 100)));
|
||||||
|
ASSERT_TRUE(engine);
|
||||||
|
|
||||||
|
// let's create a lease and put it in the LeaseMgr
|
||||||
|
uint8_t hwaddr2[] = { 0, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe};
|
||||||
|
uint8_t clientid2[] = { 8, 7, 6, 5, 4, 3, 2, 1 };
|
||||||
|
time_t now = time(NULL);
|
||||||
|
Lease4Ptr used(new Lease4(IOAddress("192.0.2.106"), hwaddr2, sizeof(hwaddr2),
|
||||||
|
clientid2, sizeof(clientid2), 1, 2, 3, now, subnet_->getID()));
|
||||||
|
ASSERT_TRUE(LeaseMgrFactory::instance().addLease(used));
|
||||||
|
|
||||||
|
// another client comes in and request an address that is in pool, but
|
||||||
|
// unfortunately it is used already. The same address must not be allocated
|
||||||
|
// twice.
|
||||||
|
Lease4Ptr lease = engine->allocateAddress4(subnet_, clientid_, hwaddr_,
|
||||||
|
IOAddress("192.0.2.106"),
|
||||||
|
false);
|
||||||
|
// check that we got a lease
|
||||||
|
ASSERT_TRUE(lease);
|
||||||
|
|
||||||
|
// allocated address must be different
|
||||||
|
EXPECT_TRUE(used->addr_.toText() != lease->addr_.toText());
|
||||||
|
|
||||||
|
// we should NOT get what we asked for, because it is used already
|
||||||
|
EXPECT_TRUE(lease->addr_.toText() != "192.0.2.106");
|
||||||
|
|
||||||
|
// do all checks on the lease
|
||||||
|
checkLease4(lease);
|
||||||
|
|
||||||
|
// Check that the lease is indeed in LeaseMgr
|
||||||
|
Lease4Ptr from_mgr = LeaseMgrFactory::instance().getLease4(lease->addr_);
|
||||||
|
ASSERT_TRUE(from_mgr);
|
||||||
|
|
||||||
|
// Now check that the lease in LeaseMgr has the same parameters
|
||||||
|
detailCompareLease(lease, from_mgr);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// This test checks if the allocation with a hint that is out the blue
|
||||||
|
// can succeed. The invalid hint should be ignored completely.
|
||||||
|
TEST_F(AllocEngine4Test, allocBogusHint4) {
|
||||||
|
boost::scoped_ptr<AllocEngine> engine;
|
||||||
|
ASSERT_NO_THROW(engine.reset(new AllocEngine(AllocEngine::ALLOC_ITERATIVE, 100)));
|
||||||
|
ASSERT_TRUE(engine);
|
||||||
|
|
||||||
|
// Client would like to get a 3000::abc lease, which does not belong to any
|
||||||
|
// supported lease. Allocation engine should ignore it and carry on
|
||||||
|
// with the normal allocation
|
||||||
|
Lease4Ptr lease = engine->allocateAddress4(subnet_, clientid_, hwaddr_,
|
||||||
|
IOAddress("10.1.1.1"),
|
||||||
|
false);
|
||||||
|
// check that we got a lease
|
||||||
|
ASSERT_TRUE(lease);
|
||||||
|
|
||||||
|
// we should NOT get what we asked for, because it is used already
|
||||||
|
EXPECT_TRUE(lease->addr_.toText() != "10.1.1.1");
|
||||||
|
|
||||||
|
// do all checks on the lease
|
||||||
|
checkLease4(lease);
|
||||||
|
|
||||||
|
// Check that the lease is indeed in LeaseMgr
|
||||||
|
Lease4Ptr from_mgr = LeaseMgrFactory::instance().getLease4(lease->addr_);
|
||||||
|
ASSERT_TRUE(from_mgr);
|
||||||
|
|
||||||
|
// Now check that the lease in LeaseMgr has the same parameters
|
||||||
|
detailCompareLease(lease, from_mgr);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// This test verifies that the allocator picks addresses that belong to the
|
||||||
|
// pool
|
||||||
|
TEST_F(AllocEngine4Test, IterativeAllocator) {
|
||||||
|
boost::scoped_ptr<NakedAllocEngine::Allocator>
|
||||||
|
alloc(new NakedAllocEngine::IterativeAllocator());
|
||||||
|
|
||||||
|
for (int i = 0; i < 1000; ++i) {
|
||||||
|
IOAddress candidate = alloc->pickAddress(subnet_, clientid_,
|
||||||
|
IOAddress("0.0.0.0"));
|
||||||
|
EXPECT_TRUE(subnet_->inPool(candidate));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// This test verifies that the iterative allocator really walks over all addresses
|
||||||
|
// 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(AllocEngine4Test, IterativeAllocator_manyPools4) {
|
||||||
|
NakedAllocEngine::IterativeAllocator* alloc = new NakedAllocEngine::IterativeAllocator();
|
||||||
|
|
||||||
|
// 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) {
|
||||||
|
stringstream min, max;
|
||||||
|
|
||||||
|
min << "192.0.2." << i*10 + 1;
|
||||||
|
max << "192.0.2." << i*10 + 9;
|
||||||
|
|
||||||
|
Pool4Ptr pool(new Pool4(IOAddress(min.str()),
|
||||||
|
IOAddress(max.str())));
|
||||||
|
// cout << "Adding pool: " << min.str() << "-" << max.str() << endl;
|
||||||
|
subnet_->addPool(pool);
|
||||||
|
}
|
||||||
|
|
||||||
|
int total = 10 + 8*9; // first pool (.100 - .109) has 10 addresses in it,
|
||||||
|
// there are 8 extra pools with 9 addresses in each.
|
||||||
|
|
||||||
|
// Let's keep picked addresses here and check their uniqueness.
|
||||||
|
std::map<IOAddress, int> generated_addrs;
|
||||||
|
int cnt = 0;
|
||||||
|
while (++cnt) {
|
||||||
|
IOAddress candidate = alloc->pickAddress(subnet_, clientid_, IOAddress("0.0.0.0"));
|
||||||
|
EXPECT_TRUE(subnet_->inPool(candidate));
|
||||||
|
|
||||||
|
// One way to easily verify that the iterative allocator really works is
|
||||||
|
// to uncomment the following line and observe its output that it
|
||||||
|
// covers all defined subnets.
|
||||||
|
// cout << candidate.toText() << endl;
|
||||||
|
|
||||||
|
if (generated_addrs.find(candidate) == generated_addrs.end()) {
|
||||||
|
// we haven't had this
|
||||||
|
generated_addrs[candidate] = 0;
|
||||||
|
} else {
|
||||||
|
// we have seen this address before. That should mean that we
|
||||||
|
// iterated over all addresses.
|
||||||
|
if (generated_addrs.size() == total) {
|
||||||
|
// we have exactly the number of address in all pools
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
ADD_FAILURE() << "Too many or not enough unique addresses generated.";
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( cnt>total ) {
|
||||||
|
ADD_FAILURE() << "Too many unique addresses generated.";
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
delete alloc;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// This test checks if really small pools are working
|
||||||
|
TEST_F(AllocEngine4Test, smallPool4) {
|
||||||
|
boost::scoped_ptr<AllocEngine> engine;
|
||||||
|
ASSERT_NO_THROW(engine.reset(new AllocEngine(AllocEngine::ALLOC_ITERATIVE, 100)));
|
||||||
|
ASSERT_TRUE(engine);
|
||||||
|
|
||||||
|
IOAddress addr("192.0.2.17");
|
||||||
|
CfgMgr& cfg_mgr = CfgMgr::instance();
|
||||||
|
cfg_mgr.deleteSubnets4(); // Get rid of the default test configuration
|
||||||
|
|
||||||
|
// 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));
|
||||||
|
pool_ = Pool4Ptr(new Pool4(addr, addr)); // just a single address
|
||||||
|
subnet_->addPool(pool_);
|
||||||
|
cfg_mgr.addSubnet4(subnet_);
|
||||||
|
|
||||||
|
Lease4Ptr lease = engine->allocateAddress4(subnet_, clientid_, hwaddr_, IOAddress("0.0.0.0"),
|
||||||
|
false);
|
||||||
|
|
||||||
|
// Check that we got that single lease
|
||||||
|
ASSERT_TRUE(lease);
|
||||||
|
|
||||||
|
EXPECT_EQ("192.0.2.17", lease->addr_.toText());
|
||||||
|
|
||||||
|
// do all checks on the lease
|
||||||
|
checkLease4(lease);
|
||||||
|
|
||||||
|
// Check that the lease is indeed in LeaseMgr
|
||||||
|
Lease4Ptr from_mgr = LeaseMgrFactory::instance().getLease4(lease->addr_);
|
||||||
|
ASSERT_TRUE(from_mgr);
|
||||||
|
|
||||||
|
// Now check that the lease in LeaseMgr has the same parameters
|
||||||
|
detailCompareLease(lease, from_mgr);
|
||||||
|
}
|
||||||
|
|
||||||
|
// This test checks if all addresses in a pool are currently used, the attempt
|
||||||
|
// to find out a new lease fails.
|
||||||
|
TEST_F(AllocEngine4Test, outOfAddresses4) {
|
||||||
|
boost::scoped_ptr<AllocEngine> engine;
|
||||||
|
ASSERT_NO_THROW(engine.reset(new AllocEngine(AllocEngine::ALLOC_ITERATIVE, 100)));
|
||||||
|
ASSERT_TRUE(engine);
|
||||||
|
|
||||||
|
IOAddress addr("192.0.2.17");
|
||||||
|
CfgMgr& cfg_mgr = CfgMgr::instance();
|
||||||
|
cfg_mgr.deleteSubnets4(); // Get rid of the default test configuration
|
||||||
|
|
||||||
|
// 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));
|
||||||
|
pool_ = Pool4Ptr(new Pool4(addr, addr)); // just a single address
|
||||||
|
subnet_->addPool(pool_);
|
||||||
|
cfg_mgr.addSubnet4(subnet_);
|
||||||
|
|
||||||
|
// Just a different hw/client-id for the second client
|
||||||
|
uint8_t hwaddr2[] = { 0, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe};
|
||||||
|
uint8_t clientid2[] = { 8, 7, 6, 5, 4, 3, 2, 1 };
|
||||||
|
time_t now = time(NULL);
|
||||||
|
Lease4Ptr lease(new Lease4(addr, hwaddr2, sizeof(hwaddr2), clientid2, sizeof(clientid2),
|
||||||
|
501, 502, 503, now, subnet_->getID()));
|
||||||
|
lease->cltt_ = time(NULL) - 10; // Allocated 10 seconds ago
|
||||||
|
ASSERT_TRUE(LeaseMgrFactory::instance().addLease(lease));
|
||||||
|
|
||||||
|
// There is just a single address in the pool and allocated it to someone
|
||||||
|
// else, so the allocation should fail
|
||||||
|
|
||||||
|
EXPECT_THROW(engine->allocateAddress4(subnet_, clientid_, hwaddr_, IOAddress("0.0.0.0"),false),
|
||||||
|
AllocFailed);
|
||||||
|
}
|
||||||
|
|
||||||
|
// This test checks if an expired lease can be reused in DISCOVER (fake allocation)
|
||||||
|
TEST_F(AllocEngine4Test, discoverReuseExpiredLease4) {
|
||||||
|
boost::scoped_ptr<AllocEngine> engine;
|
||||||
|
ASSERT_NO_THROW(engine.reset(new AllocEngine(AllocEngine::ALLOC_ITERATIVE, 100)));
|
||||||
|
ASSERT_TRUE(engine);
|
||||||
|
|
||||||
|
IOAddress addr("192.0.2.15");
|
||||||
|
CfgMgr& cfg_mgr = CfgMgr::instance();
|
||||||
|
cfg_mgr.deleteSubnets4(); // Get rid of the default test configuration
|
||||||
|
|
||||||
|
// 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));
|
||||||
|
pool_ = Pool4Ptr(new Pool4(addr, addr)); // just a single address
|
||||||
|
subnet_->addPool(pool_);
|
||||||
|
cfg_mgr.addSubnet4(subnet_);
|
||||||
|
|
||||||
|
// Just a different hw/client-id for the second client
|
||||||
|
uint8_t hwaddr2[] = { 0, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe};
|
||||||
|
uint8_t clientid2[] = { 8, 7, 6, 5, 4, 3, 2, 1 };
|
||||||
|
time_t now = time(NULL) - 500; // Allocated 500 seconds ago
|
||||||
|
Lease4Ptr lease(new Lease4(addr, clientid2, sizeof(clientid2), hwaddr2, sizeof(hwaddr2),
|
||||||
|
495, 100, 200, now, subnet_->getID()));
|
||||||
|
// lease was assigned 500 seconds ago, but its valid lifetime is 495, so it
|
||||||
|
// is expired already
|
||||||
|
ASSERT_TRUE(lease->expired());
|
||||||
|
ASSERT_TRUE(LeaseMgrFactory::instance().addLease(lease));
|
||||||
|
|
||||||
|
// CASE 1: Asking for any address
|
||||||
|
lease = engine->allocateAddress4(subnet_, clientid_, hwaddr_, IOAddress("0.0.0.0"),
|
||||||
|
true);
|
||||||
|
// Check that we got that single lease
|
||||||
|
ASSERT_TRUE(lease);
|
||||||
|
EXPECT_EQ(addr.toText(), lease->addr_.toText());
|
||||||
|
|
||||||
|
// Do all checks on the lease (if subnet-id, preferred/valid times are ok etc.)
|
||||||
|
checkLease4(lease);
|
||||||
|
|
||||||
|
// CASE 2: Asking specifically for this address
|
||||||
|
lease = engine->allocateAddress4(subnet_, clientid_, hwaddr_, IOAddress(addr.toText()),
|
||||||
|
true);
|
||||||
|
// Check that we got that single lease
|
||||||
|
ASSERT_TRUE(lease);
|
||||||
|
EXPECT_EQ(addr.toText(), lease->addr_.toText());
|
||||||
|
}
|
||||||
|
|
||||||
|
// This test checks if an expired lease can be reused in REQUEST (actual allocation)
|
||||||
|
TEST_F(AllocEngine4Test, requestReuseExpiredLease4) {
|
||||||
|
boost::scoped_ptr<AllocEngine> engine;
|
||||||
|
ASSERT_NO_THROW(engine.reset(new AllocEngine(AllocEngine::ALLOC_ITERATIVE, 100)));
|
||||||
|
ASSERT_TRUE(engine);
|
||||||
|
|
||||||
|
IOAddress addr("192.0.2.105");
|
||||||
|
|
||||||
|
// Just a different hw/client-id for the second client
|
||||||
|
uint8_t hwaddr2[] = { 0, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe};
|
||||||
|
uint8_t clientid2[] = { 8, 7, 6, 5, 4, 3, 2, 1 };
|
||||||
|
time_t now = time(NULL) - 500; // Allocated 500 seconds ago
|
||||||
|
Lease4Ptr lease(new Lease4(addr, clientid2, sizeof(clientid2), hwaddr2, sizeof(hwaddr2),
|
||||||
|
495, 100, 200, now, subnet_->getID()));
|
||||||
|
// lease was assigned 500 seconds ago, but its valid lifetime is 495, so it
|
||||||
|
// is expired already
|
||||||
|
ASSERT_TRUE(lease->expired());
|
||||||
|
ASSERT_TRUE(LeaseMgrFactory::instance().addLease(lease));
|
||||||
|
|
||||||
|
// A client comes along, asking specifically for this address
|
||||||
|
lease = engine->allocateAddress4(subnet_, clientid_, hwaddr_,
|
||||||
|
IOAddress(addr.toText()), false);
|
||||||
|
|
||||||
|
// Check that he got that single lease
|
||||||
|
ASSERT_TRUE(lease);
|
||||||
|
EXPECT_EQ(addr.toText(), lease->addr_.toText());
|
||||||
|
|
||||||
|
// Check that the lease is indeed updated in LeaseMgr
|
||||||
|
Lease4Ptr from_mgr = LeaseMgrFactory::instance().getLease4(addr);
|
||||||
|
ASSERT_TRUE(from_mgr);
|
||||||
|
|
||||||
|
// Now check that the lease in LeaseMgr has the same parameters
|
||||||
|
detailCompareLease(lease, from_mgr);
|
||||||
|
}
|
||||||
|
|
||||||
}; // end of anonymous namespace
|
}; // end of anonymous namespace
|
||||||
|
@@ -39,9 +39,14 @@ namespace {
|
|||||||
class CfgMgrTest : public ::testing::Test {
|
class CfgMgrTest : public ::testing::Test {
|
||||||
public:
|
public:
|
||||||
CfgMgrTest() {
|
CfgMgrTest() {
|
||||||
|
// make sure we start with a clean configuration
|
||||||
|
CfgMgr::instance().deleteSubnets4();
|
||||||
|
CfgMgr::instance().deleteSubnets6();
|
||||||
}
|
}
|
||||||
|
|
||||||
~CfgMgrTest() {
|
~CfgMgrTest() {
|
||||||
|
// clean up after the test
|
||||||
|
CfgMgr::instance().deleteSubnets4();
|
||||||
CfgMgr::instance().deleteSubnets6();
|
CfgMgr::instance().deleteSubnets6();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@@ -272,7 +272,7 @@ TEST(Lease4, Lease4Constructor) {
|
|||||||
|
|
||||||
// Create the lease
|
// Create the lease
|
||||||
Lease4 lease(ADDRESS[i], HWADDR, sizeof(HWADDR),
|
Lease4 lease(ADDRESS[i], HWADDR, sizeof(HWADDR),
|
||||||
CLIENTID, sizeof(CLIENTID), VALID_LIFETIME, current_time,
|
CLIENTID, sizeof(CLIENTID), VALID_LIFETIME, 0, 0, current_time,
|
||||||
SUBNET_ID);
|
SUBNET_ID);
|
||||||
|
|
||||||
EXPECT_EQ(ADDRESS[i], static_cast<uint32_t>(lease.addr_));
|
EXPECT_EQ(ADDRESS[i], static_cast<uint32_t>(lease.addr_));
|
||||||
@@ -312,10 +312,10 @@ TEST(Lease4, OperatorEquals) {
|
|||||||
|
|
||||||
// Check when the leases are equal.
|
// Check when the leases are equal.
|
||||||
Lease4 lease1(ADDRESS, HWADDR, sizeof(HWADDR),
|
Lease4 lease1(ADDRESS, HWADDR, sizeof(HWADDR),
|
||||||
CLIENTID, sizeof(CLIENTID), VALID_LIFETIME, current_time,
|
CLIENTID, sizeof(CLIENTID), VALID_LIFETIME, current_time, 0, 0,
|
||||||
SUBNET_ID);
|
SUBNET_ID);
|
||||||
Lease4 lease2(ADDRESS, HWADDR, sizeof(HWADDR),
|
Lease4 lease2(ADDRESS, HWADDR, sizeof(HWADDR),
|
||||||
CLIENTID, sizeof(CLIENTID), VALID_LIFETIME, current_time,
|
CLIENTID, sizeof(CLIENTID), VALID_LIFETIME, current_time, 0, 0,
|
||||||
SUBNET_ID);
|
SUBNET_ID);
|
||||||
EXPECT_TRUE(lease1 == lease2);
|
EXPECT_TRUE(lease1 == lease2);
|
||||||
EXPECT_FALSE(lease1 != lease2);
|
EXPECT_FALSE(lease1 != lease2);
|
||||||
|
@@ -1414,9 +1414,7 @@ TestControl::sendRequest4(const TestControlSocket& socket,
|
|||||||
setDefaults4(socket, pkt4);
|
setDefaults4(socket, pkt4);
|
||||||
|
|
||||||
// Set hardware address
|
// Set hardware address
|
||||||
const uint8_t* chaddr = offer_pkt4->getChaddr();
|
pkt4->setHWAddr(offer_pkt4->getHWAddr());
|
||||||
std::vector<uint8_t> mac_address(chaddr, chaddr + HW_ETHER_LEN);
|
|
||||||
pkt4->setHWAddr(HTYPE_ETHER, mac_address.size(), mac_address);
|
|
||||||
// Set elapsed time.
|
// Set elapsed time.
|
||||||
uint32_t elapsed_time = getElapsedTime<Pkt4Ptr>(discover_pkt4, offer_pkt4);
|
uint32_t elapsed_time = getElapsedTime<Pkt4Ptr>(discover_pkt4, offer_pkt4);
|
||||||
pkt4->setSecs(static_cast<uint16_t>(elapsed_time / 1000));
|
pkt4->setSecs(static_cast<uint16_t>(elapsed_time / 1000));
|
||||||
@@ -1461,8 +1459,10 @@ TestControl::sendRequest4(const TestControlSocket& socket,
|
|||||||
transid));
|
transid));
|
||||||
|
|
||||||
// Set hardware address from OFFER packet received.
|
// Set hardware address from OFFER packet received.
|
||||||
const uint8_t* chaddr = offer_pkt4->getChaddr();
|
HWAddrPtr hwaddr = offer_pkt4->getHWAddr();
|
||||||
std::vector<uint8_t> mac_address(chaddr, chaddr + HW_ETHER_LEN);
|
std::vector<uint8_t> mac_address(HW_ETHER_LEN, 0);
|
||||||
|
uint8_t hw_len = hwaddr->hwaddr_.size();
|
||||||
|
memcpy(&mac_address[0], &hwaddr->hwaddr_[0], hw_len > 16 ? 16 : hw_len);
|
||||||
pkt4->writeAt(rand_offset, mac_address.begin(), mac_address.end());
|
pkt4->writeAt(rand_offset, mac_address.begin(), mac_address.end());
|
||||||
|
|
||||||
// Set elapsed time.
|
// Set elapsed time.
|
||||||
|
Reference in New Issue
Block a user