summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMarcin Siodelski <marcin@isc.org>2015-06-26 12:29:25 +0200
committerMarcin Siodelski <marcin@isc.org>2015-06-26 12:29:25 +0200
commit6c489c3e41b80055f2ac76b11ea14addc4a5f4c2 (patch)
tree64804bff864ac7385e28af85c8c6258ae73e7ec9
parent[master] ChangeLog updated after 3918 merge. (diff)
downloadkea-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.cc55
-rw-r--r--src/lib/dhcpsrv/alloc_engine.h17
-rw-r--r--src/lib/dhcpsrv/tests/alloc_engine6_unittest.cc112
-rw-r--r--src/lib/dhcpsrv/tests/alloc_engine_utils.cc2
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_);