From: Tomek Mrugalski Date: Fri, 14 Dec 2012 18:28:09 +0000 (+0100) Subject: [2327] Reuse of expired leases implemented. X-Git-Tag: bind10-1.0.0-beta-release~6^2^2~3 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=95cc8210a2f620d6a2a886cf7577ed2d257d2bad;p=thirdparty%2Fkea.git [2327] Reuse of expired leases implemented. --- diff --git a/src/lib/dhcpsrv/alloc_engine.cc b/src/lib/dhcpsrv/alloc_engine.cc index 77a2df41ef..fc4b5810fa 100644 --- a/src/lib/dhcpsrv/alloc_engine.cc +++ b/src/lib/dhcpsrv/alloc_engine.cc @@ -44,8 +44,10 @@ AllocEngine::IterativeAllocator::increaseAddress(const isc::asiolink::IOAddress& len = 16; } + // Start increasing the least significant byte for (int i = len - 1; i >= 0; --i) { ++packed[i]; + // if we haven't overflowed (0xff -> 0x0), than we are done if (packed[i] != 0) { break; } @@ -197,6 +199,12 @@ AllocEngine::allocateAddress6(const Subnet6Ptr& subnet, if (lease) { return (lease); } + } else { + if (existing->expired()) { + return (reuseExpiredLease(existing, subnet, duid, iaid, + fake_allocation)); + } + } } @@ -220,6 +228,11 @@ AllocEngine::allocateAddress6(const Subnet6Ptr& subnet, // 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, duid, iaid, + fake_allocation)); + } } // continue trying allocation until we run out of attempts @@ -231,6 +244,46 @@ AllocEngine::allocateAddress6(const Subnet6Ptr& subnet, << " tries"); } +Lease6Ptr AllocEngine::reuseExpiredLease(Lease6Ptr& expired, + const Subnet6Ptr& subnet, + const DuidPtr& duid, + uint32_t iaid, + 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->iaid_ = iaid; + expired->duid_ = duid; + expired->preferred_lft_ = subnet->getPreferred(); + 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().updateLease6(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::createLease(const Subnet6Ptr& subnet, const DuidPtr& duid, uint32_t iaid, diff --git a/src/lib/dhcpsrv/alloc_engine.h b/src/lib/dhcpsrv/alloc_engine.h index 940b1f4d77..eab6e123e9 100644 --- a/src/lib/dhcpsrv/alloc_engine.h +++ b/src/lib/dhcpsrv/alloc_engine.h @@ -216,6 +216,24 @@ private: uint32_t iaid, const isc::asiolink::IOAddress& addr, bool fake_allocation = false); + /// @brief reuses expired lease + /// + /// Updates existing expired lease with new information. Lease database + /// is updated if this is real (i.e. REQUEST, fake_allocation = false), not + /// dummy allocation request (i.e. SOLICIT, fake_allocation = true). + /// + /// @param expired old, expired lease + /// @param subnet subnet the lease is allocated from + /// @param duid client's DUID + /// @param iaid IAID from the IA_NA container the client sent to us + /// @param fake_allocation is this real i.e. REQUEST (false) or just picking + /// an address for SOLICIT that is not really allocated (true) + /// @return refreshed lease + /// @throw BadValue if trying to recycle lease that is still valid + Lease6Ptr reuseExpiredLease(Lease6Ptr& expired, const Subnet6Ptr& subnet, + const DuidPtr& duid, uint32_t iaid, + bool fake_allocation = false); + /// @brief a pointer to currently used allocator boost::shared_ptr allocator_; diff --git a/src/lib/dhcpsrv/lease_mgr.cc b/src/lib/dhcpsrv/lease_mgr.cc index f7b63732ff..b3a605d329 100644 --- a/src/lib/dhcpsrv/lease_mgr.cc +++ b/src/lib/dhcpsrv/lease_mgr.cc @@ -46,6 +46,14 @@ Lease6::Lease6(LeaseType type, const isc::asiolink::IOAddress& addr, cltt_ = time(NULL); } +bool Lease6::expired() const { + + // Let's use int64 to avoid problems with negative/large uint32 values + int64_t expire_time = cltt_ + valid_lft_; + return (expire_time < time(NULL)); +} + + std::string LeaseMgr::getParameter(const std::string& name) const { ParameterMap::const_iterator param = parameters_.find(name); if (param == parameters_.end()) { diff --git a/src/lib/dhcpsrv/lease_mgr.h b/src/lib/dhcpsrv/lease_mgr.h index 7865e1120e..3fe11e68d3 100644 --- a/src/lib/dhcpsrv/lease_mgr.h +++ b/src/lib/dhcpsrv/lease_mgr.h @@ -379,6 +379,10 @@ struct Lease6 { /// @return String form of the lease std::string toText(); + /// @brief returns true if the lease is expired + /// @return true if the lease is expired + bool expired() const; + /// @brief Compare two leases for equality /// /// @param other lease6 object with which to compare