diff options
author | Marcin Siodelski <marcin@isc.org> | 2015-06-26 12:29:25 +0200 |
---|---|---|
committer | Marcin Siodelski <marcin@isc.org> | 2015-06-26 12:29:25 +0200 |
commit | 6c489c3e41b80055f2ac76b11ea14addc4a5f4c2 (patch) | |
tree | 64804bff864ac7385e28af85c8c6258ae73e7ec9 | |
parent | [master] ChangeLog updated after 3918 merge. (diff) | |
download | kea-6c489c3e41b80055f2ac76b11ea14addc4a5f4c2.tar.xz kea-6c489c3e41b80055f2ac76b11ea14addc4a5f4c2.zip |
[3913] Allocation engine extends the lifetime of the lease for Request.
-rw-r--r-- | src/lib/dhcpsrv/alloc_engine.cc | 55 | ||||
-rw-r--r-- | src/lib/dhcpsrv/alloc_engine.h | 17 | ||||
-rw-r--r-- | src/lib/dhcpsrv/tests/alloc_engine6_unittest.cc | 112 | ||||
-rw-r--r-- | src/lib/dhcpsrv/tests/alloc_engine_utils.cc | 2 |
4 files changed, 175 insertions, 11 deletions
diff --git a/src/lib/dhcpsrv/alloc_engine.cc b/src/lib/dhcpsrv/alloc_engine.cc index f5659bde95..34633aa622 100644 --- a/src/lib/dhcpsrv/alloc_engine.cc +++ b/src/lib/dhcpsrv/alloc_engine.cc @@ -289,10 +289,45 @@ AllocEngine::AllocatorPtr AllocEngine::getAllocator(Lease::Type type) { return (alloc->second); } +} // end of isc::dhcp namespace +} // end of isc namespace + +namespace { + +/// @brief Extends the lease lifetime. +/// +/// This function is called to conditionally extend the lifetime of +/// the DHCPv4 or DHCPv6 lease. It is envisaged that this function will +/// make a decision if the lease lifetime should be extended, using +/// a preconfigured threshold, which would indicate how many percent +/// of the valid lifetime should have passed for the lease lifetime +/// to be extended. The lease lifetime would not be extended if +/// the threshold hasn't been reached. +/// +/// @todo Currently this function always extends the lease lifetime. +/// In the future, it will take the threshold value into account, +/// once the threshold is configurable. +/// +/// @param [out] lease A lease for which the lifetime should be +/// extended. +/// +/// @return true if the lease lifetime has been extended, false +/// otherwise. +bool +conditionalExtendLifetime(Lease& lease) { + lease.cltt_ = time(NULL); + return (true); +} + +} // end of anonymous namespace + // ########################################################################## // # DHCPv6 lease allocation code starts here. // ########################################################################## +namespace isc { +namespace dhcp { + AllocEngine::ClientContext6::ClientContext6() : subnet_(), duid_(), iaid_(0), type_(Lease::TYPE_NA), hwaddr_(), hints_(), fwd_dns_update_(false), rev_dns_update_(false), hostname_(""), @@ -422,7 +457,7 @@ AllocEngine::allocateLeases6(ClientContext6& ctx) { if (!leases.empty()) { // Return old leases so the server can see what has changed. - return (updateFqdnData(ctx, leases)); + return (updateLeaseData(ctx, leases)); } // If leases are empty at this stage, it means that we used to have @@ -719,7 +754,7 @@ AllocEngine::allocateReservedLeases6(ClientContext6& ctx, Lease6Collection& exis uint8_t prefix_len = resv->second.getPrefixLen(); // Check if already have this lease on the existing_leases list. - for (Lease6Collection::const_iterator l = existing_leases.begin(); + for (Lease6Collection::iterator l = existing_leases.begin(); l != existing_leases.end(); ++l) { // Ok, we already have a lease for this reservation and it's usable @@ -729,6 +764,13 @@ AllocEngine::allocateReservedLeases6(ClientContext6& ctx, Lease6Collection& exis .arg(ctx.query_->getLabel()) .arg((*l)->typeToText((*l)->type_)) .arg((*l)->addr_.toText()); + + // If this is a real allocation, we may need to extend the lease + // lifetime. + if (!ctx.fake_allocation_ && conditionalExtendLifetime(**l)) { + LeaseMgrFactory::instance().updateLease6(*l); + } + return; } } @@ -1186,12 +1228,14 @@ AllocEngine::extendLease6(ClientContext6& ctx, Lease6Ptr lease) { lease->valid_lft_ = ctx.subnet_->getValid(); lease->t1_ = ctx.subnet_->getT1(); lease->t2_ = ctx.subnet_->getT2(); - lease->cltt_ = time(NULL); lease->hostname_ = ctx.hostname_; lease->fqdn_fwd_ = ctx.fwd_dns_update_; lease->fqdn_rev_ = ctx.rev_dns_update_; lease->hwaddr_ = ctx.hwaddr_; + // Extend lease lifetime if it is time to extend it. + conditionalExtendLifetime(*lease); + LOG_DEBUG(alloc_engine_logger, ALLOC_ENGINE_DBG_TRACE_DETAIL_DATA, ALLOC_ENGINE_V6_EXTEND_NEW_LEASE_DATA) .arg(ctx.query_->getLabel()) @@ -1246,7 +1290,7 @@ AllocEngine::extendLease6(ClientContext6& ctx, Lease6Ptr lease) { } Lease6Collection -AllocEngine::updateFqdnData(ClientContext6& ctx, const Lease6Collection& leases) { +AllocEngine::updateLeaseData(ClientContext6& ctx, const Lease6Collection& leases) { Lease6Collection updated_leases; for (Lease6Collection::const_iterator lease_it = leases.begin(); lease_it != leases.end(); ++lease_it) { @@ -1255,7 +1299,8 @@ AllocEngine::updateFqdnData(ClientContext6& ctx, const Lease6Collection& leases) lease->fqdn_rev_ = ctx.rev_dns_update_; lease->hostname_ = ctx.hostname_; if (!ctx.fake_allocation_ && - ((lease->fqdn_fwd_ != (*lease_it)->fqdn_fwd_) || + (conditionalExtendLifetime(*lease) || + (lease->fqdn_fwd_ != (*lease_it)->fqdn_fwd_) || (lease->fqdn_rev_ != (*lease_it)->fqdn_rev_) || (lease->hostname_ != (*lease_it)->hostname_))) { ctx.changed_leases_.push_back(*lease_it); diff --git a/src/lib/dhcpsrv/alloc_engine.h b/src/lib/dhcpsrv/alloc_engine.h index f867f8c8fb..2c2335dbe3 100644 --- a/src/lib/dhcpsrv/alloc_engine.h +++ b/src/lib/dhcpsrv/alloc_engine.h @@ -634,19 +634,26 @@ private: ClientContext6& ctx, uint8_t prefix_len); - /// @brief Updates FQDN data for a collection of leases. + /// @brief Updates FQDN and Client's Last Tranmission Time for a collection + /// of leases. + /// + /// This method is executed when the server finds existing leases for a + /// client and updates some date for these leases if needed: + /// - client's last transmission time (cltt), if the lease to be returned + /// to the client should have its lifetime extended, + /// - FQDN data, when the client has negotiated new FQDN with the server. /// /// @param ctx IPv6 client context (old versions of the leases that had /// FQDN data changed will be stored in ctx.changed_leases_, /// ctx.fwd_dns_update, ctx.rev_dns_update, ctx.hostname_ /// and ctx.fake_allocation_ will be used. - /// @param leases Collection of leases for which FQDN data should be + /// @param leases Collection of leases for which lease data should be /// updated. /// - /// @return Collection of leases with updated FQDN data. Note that returned + /// @return Collection of leases with updated data. Note that returned /// collection holds updated FQDN data even for fake allocation. - Lease6Collection updateFqdnData(ClientContext6& ctx, - const Lease6Collection& leases); + Lease6Collection updateLeaseData(ClientContext6& ctx, + const Lease6Collection& leases); /// @brief Utility function that removes all leases with a specified address /// @param container A collection of Lease6 pointers diff --git a/src/lib/dhcpsrv/tests/alloc_engine6_unittest.cc b/src/lib/dhcpsrv/tests/alloc_engine6_unittest.cc index e15ecf0afd..b4251a8deb 100644 --- a/src/lib/dhcpsrv/tests/alloc_engine6_unittest.cc +++ b/src/lib/dhcpsrv/tests/alloc_engine6_unittest.cc @@ -601,6 +601,118 @@ TEST_F(AllocEngine6Test, requestReuseExpiredLease6) { EXPECT_EQ(100, stat->getInteger().first); } +// Checks if the lease lifetime is extended when the client sends the +// Request. +TEST_F(AllocEngine6Test, requestExtendLeaseLifetime) { + // Create a lease for the client. + Lease6Ptr lease(new Lease6(Lease::TYPE_NA, IOAddress("2001:db8:1::15"), + duid_, iaid_, 300, 400, 100, 200, + subnet_->getID(), HWAddrPtr(), 128)); + + // Allocated 200 seconds ago - half of the lifetime. + time_t lease_cltt = time(NULL) - 200; + lease->cltt_ = lease_cltt; + + ASSERT_TRUE(LeaseMgrFactory::instance().addLease(lease)); + + // Client should receive a lease. + Lease6Ptr new_lease = simpleAlloc6Test(pool_, IOAddress("::"), false); + ASSERT_TRUE(new_lease); + + // And the lease lifetime should be extended. + EXPECT_GT(new_lease->cltt_, lease_cltt) + << "Lease lifetime was not extended, but it should"; +} + +// Checks if the lease lifetime is extended when the client sends the +// Request and the client has a reservation for the lease. +TEST_F(AllocEngine6Test, requestExtendLeaseLifetimeForReservation) { + // Create reservation for the client. This is in-pool reservation, + // as the pool is 2001:db8:1::10 - 2001:db8:1::20. + createHost6(true, IPv6Resrv::TYPE_NA, IOAddress("2001:db8:1::1c"), 128); + + // Create a lease for the client. + Lease6Ptr lease(new Lease6(Lease::TYPE_NA, IOAddress("2001:db8:1::1c"), + duid_, iaid_, 300, 400, 100, 200, + subnet_->getID(), HWAddrPtr(), 128)); + + // Allocated 200 seconds ago - half of the lifetime. + time_t lease_cltt = time(NULL) - 200; + lease->cltt_ = lease_cltt; + + ASSERT_TRUE(LeaseMgrFactory::instance().addLease(lease)); + + // Client should receive a lease. + Lease6Ptr new_lease = simpleAlloc6Test(pool_, IOAddress("::"), false); + ASSERT_TRUE(new_lease); + + // And the lease lifetime should be extended. + EXPECT_GT(new_lease->cltt_, lease_cltt) + << "Lease lifetime was not extended, but it should"; +} + +// Checks if the lease lifetime is extended when the client sends the +// Renew. +TEST_F(AllocEngine6Test, renewExtendLeaseLifetime) { + // Create a lease for the client. + Lease6Ptr lease(new Lease6(Lease::TYPE_NA, IOAddress("2001:db8:1::15"), + duid_, iaid_, 300, 400, 100, 200, + subnet_->getID(), HWAddrPtr(), 128)); + + // Allocated 200 seconds ago - half of the lifetime. + time_t lease_cltt = time(NULL) - 200; + lease->cltt_ = lease_cltt; + + ASSERT_TRUE(LeaseMgrFactory::instance().addLease(lease)); + + AllocEngine engine(AllocEngine::ALLOC_ITERATIVE, 100); + + // This is what the client will send in his renew message. + AllocEngine::HintContainer hints; + hints.push_back(make_pair(IOAddress("2001:db8:1::15"), 128)); + + // Client should receive a lease. + Lease6Collection renewed = renewTest(engine, pool_, hints, true); + ASSERT_EQ(1, renewed.size()); + + // And the lease lifetime should be extended. + EXPECT_GT(renewed[0]->cltt_, lease_cltt) + << "Lease lifetime was not extended, but it should"; +} + +// Checks if the lease lifetime is extended when the client sends the +// Renew and the client has a reservation for the lease. +TEST_F(AllocEngine6Test, renewExtendLeaseLifetimeForReservation) { + // Create reservation for the client. This is in-pool reservation, + // as the pool is 2001:db8:1::10 - 2001:db8:1::20. + createHost6(true, IPv6Resrv::TYPE_NA, IOAddress("2001:db8:1::15"), 128); + + // Create a lease for the client. + Lease6Ptr lease(new Lease6(Lease::TYPE_NA, IOAddress("2001:db8:1::15"), + duid_, iaid_, 300, 400, 100, 200, + subnet_->getID(), HWAddrPtr(), 128)); + + // Allocated 200 seconds ago - half of the lifetime. + time_t lease_cltt = time(NULL) - 200; + lease->cltt_ = lease_cltt; + + ASSERT_TRUE(LeaseMgrFactory::instance().addLease(lease)); + + AllocEngine engine(AllocEngine::ALLOC_ITERATIVE, 100); + + // This is what the client will send in his renew message. + AllocEngine::HintContainer hints; + hints.push_back(make_pair(IOAddress("2001:db8:1::15"), 128)); + + // Client should receive a lease. + Lease6Collection renewed = renewTest(engine, pool_, hints, true); + ASSERT_EQ(1, renewed.size()); + + // And the lease lifetime should be extended. + EXPECT_GT(renewed[0]->cltt_, lease_cltt) + << "Lease lifetime was not extended, but it should"; +} + // --- v6 host reservation --- // Checks that a client gets the address reserved (in-pool case) diff --git a/src/lib/dhcpsrv/tests/alloc_engine_utils.cc b/src/lib/dhcpsrv/tests/alloc_engine_utils.cc index 7b65171b0e..d5894d92cc 100644 --- a/src/lib/dhcpsrv/tests/alloc_engine_utils.cc +++ b/src/lib/dhcpsrv/tests/alloc_engine_utils.cc @@ -74,7 +74,7 @@ AllocEngine6Test::initSubnet(const asiolink::IOAddress& subnet, const asiolink::IOAddress& pool_end) { CfgMgr& cfg_mgr = CfgMgr::instance(); - subnet_ = Subnet6Ptr(new Subnet6(subnet, 56, 1, 2, 3, 4)); + subnet_ = Subnet6Ptr(new Subnet6(subnet, 56, 100, 200, 300, 400)); pool_ = Pool6Ptr(new Pool6(Lease::TYPE_NA, pool_start, pool_end)); subnet_->addPool(pool_); |