Browse Source

[2327] Reuse of expired leases implemented.

Tomek Mrugalski 12 years ago
parent
commit
95cc8210a2

+ 53 - 0
src/lib/dhcpsrv/alloc_engine.cc

@@ -44,8 +44,10 @@ AllocEngine::IterativeAllocator::increaseAddress(const isc::asiolink::IOAddress&
         len = 16;
         len = 16;
     }
     }
 
 
+    // Start increasing the least significant byte
     for (int i = len - 1; i >= 0; --i) {
     for (int i = len - 1; i >= 0; --i) {
         ++packed[i];
         ++packed[i];
+        // if we haven't overflowed (0xff -> 0x0), than we are done
         if (packed[i] != 0) {
         if (packed[i] != 0) {
             break;
             break;
         }
         }
@@ -197,6 +199,12 @@ AllocEngine::allocateAddress6(const Subnet6Ptr& subnet,
             if (lease) {
             if (lease) {
                 return (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
             // Although the address was free just microseconds ago, it may have
             // been taken just now. If the lease insertion fails, we continue
             // been taken just now. If the lease insertion fails, we continue
             // allocation attempts.
             // allocation attempts.
+        } else {
+            if (existing->expired()) {
+                return (reuseExpiredLease(existing, subnet, duid, iaid,
+                                          fake_allocation));
+            }
         }
         }
 
 
         // continue trying allocation until we run out of attempts
         // continue trying allocation until we run out of attempts
@@ -231,6 +244,46 @@ AllocEngine::allocateAddress6(const Subnet6Ptr& subnet,
               << " tries");
               << " 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,
 Lease6Ptr AllocEngine::createLease(const Subnet6Ptr& subnet,
                                    const DuidPtr& duid,
                                    const DuidPtr& duid,
                                    uint32_t iaid,
                                    uint32_t iaid,

+ 18 - 0
src/lib/dhcpsrv/alloc_engine.h

@@ -216,6 +216,24 @@ private:
                           uint32_t iaid, const isc::asiolink::IOAddress& addr,
                           uint32_t iaid, const isc::asiolink::IOAddress& addr,
                           bool fake_allocation = false);
                           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
     /// @brief a pointer to currently used allocator
     boost::shared_ptr<Allocator> allocator_;
     boost::shared_ptr<Allocator> allocator_;
 
 

+ 8 - 0
src/lib/dhcpsrv/lease_mgr.cc

@@ -46,6 +46,14 @@ Lease6::Lease6(LeaseType type, const isc::asiolink::IOAddress& addr,
     cltt_ = time(NULL);
     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 {
 std::string LeaseMgr::getParameter(const std::string& name) const {
     ParameterMap::const_iterator param = parameters_.find(name);
     ParameterMap::const_iterator param = parameters_.find(name);
     if (param == parameters_.end()) {
     if (param == parameters_.end()) {

+ 4 - 0
src/lib/dhcpsrv/lease_mgr.h

@@ -379,6 +379,10 @@ struct Lease6 {
     /// @return String form of the lease
     /// @return String form of the lease
     std::string toText();
     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
     /// @brief Compare two leases for equality
     ///
     ///
     /// @param other lease6 object with which to compare
     /// @param other lease6 object with which to compare