2
0
mirror of https://gitlab.isc.org/isc-projects/kea synced 2025-08-31 14:05:33 +00:00

[master] Merge branch 'trac3973'

This commit is contained in:
Marcin Siodelski
2015-09-21 10:06:18 +02:00
5 changed files with 1674 additions and 0 deletions

View File

@@ -14,17 +14,24 @@
#include <config.h>
#include <dhcp/option_data_types.h>
#include <dhcp_ddns/ncr_msg.h>
#include <dhcpsrv/alloc_engine.h>
#include <dhcpsrv/alloc_engine_log.h>
#include <dhcpsrv/cfgmgr.h>
#include <dhcpsrv/d2_client_mgr.h>
#include <dhcpsrv/dhcpsrv_log.h>
#include <dhcpsrv/host_mgr.h>
#include <dhcpsrv/host.h>
#include <dhcpsrv/lease_mgr_factory.h>
#include <dhcp/dhcp6.h>
#include <stats/stats_mgr.h>
#include <util/stopwatch.h>
#include <hooks/server_hooks.h>
#include <hooks/hooks_manager.h>
#include <boost/foreach.hpp>
#include <cstring>
#include <sstream>
#include <limits>
@@ -34,6 +41,7 @@
using namespace isc::asiolink;
using namespace isc::dhcp;
using namespace isc::dhcp_ddns;
using namespace isc::hooks;
using namespace isc::stats;
@@ -1272,6 +1280,230 @@ AllocEngine::updateLeaseData(ClientContext6& ctx, const Lease6Collection& leases
return (updated_leases);
}
void
AllocEngine::reclaimExpiredLeases6(const size_t max_leases, const uint16_t timeout,
const bool remove_lease) {
LOG_DEBUG(alloc_engine_logger, ALLOC_ENGINE_DBG_TRACE,
ALLOC_ENGINE_V6_LEASES_RECLAMATION_START)
.arg(max_leases)
.arg(timeout);
// Create stopwatch and automatically start it to measure the time
// taken by the routine.
/// @todo Monitor time elapsed and return from the lease reclamation routine
/// if it hits the timeout value.
util::Stopwatch stopwatch;
LeaseMgr& lease_mgr = LeaseMgrFactory::instance();
Lease6Collection leases;
lease_mgr.getExpiredLeases6(leases, max_leases);
BOOST_FOREACH(Lease6Ptr lease, leases) {
try {
/// @todo execute a lease6_expire hook here.
// Generate removal name change request for D2, if required.
// This will return immediatelly if the DNS wasn't updated
// when the lease was created.
if (lease->duid_) {
queueRemovalNameChangeRequest(lease, *(lease->duid_));
}
// Reclaim the lease - depending on the configuration, set the
// expired-reclaimed state or simply remove it.
reclaimLeaseInDatabase<Lease6Ptr>(lease, remove_lease,
boost::bind(&LeaseMgr::updateLease6,
&lease_mgr, _1));
// Update statistics.
// Decrease number of assigned leases.
if (lease->type_ == Lease::TYPE_NA) {
// IA_NA
StatsMgr::instance().addValue(StatsMgr::generateName("subnet",
lease->subnet_id_,
"assigned-nas"),
int64_t(-1));
} else if (lease->type_ == Lease::TYPE_PD) {
// IA_PD
StatsMgr::instance().addValue(StatsMgr::generateName("subnet",
lease->subnet_id_,
"assigned-pds"),
int64_t(-1));
}
// Increase total number of reclaimed leases.
StatsMgr::instance().addValue("reclaimed-leases", int64_t(1));
// Increase number of reclaimed leases for a subnet.
StatsMgr::instance().addValue(StatsMgr::generateName("subnet",
lease->subnet_id_,
"reclaimed-leases"),
int64_t(1));
} catch (const std::exception& ex) {
LOG_ERROR(alloc_engine_logger, ALLOC_ENGINE_V6_LEASE_RECLAMATION_FAILED)
.arg(lease->addr_.toText())
.arg(ex.what());
}
}
// Stop measuring the time.
stopwatch.stop();
// Mark completion of the lease reclamation routine and present some stats.
LOG_DEBUG(alloc_engine_logger, ALLOC_ENGINE_DBG_TRACE,
ALLOC_ENGINE_V6_LEASES_RECLAMATION_COMPLETE)
.arg(leases.size())
.arg(stopwatch.logFormatTotalDuration());
}
void
AllocEngine::reclaimExpiredLeases4(const size_t max_leases, const uint16_t timeout,
const bool remove_lease) {
LOG_DEBUG(alloc_engine_logger, ALLOC_ENGINE_DBG_TRACE,
ALLOC_ENGINE_V4_LEASES_RECLAMATION_START)
.arg(max_leases)
.arg(timeout);
// Create stopwatch and automatically start it to measure the time
// taken by the routine.
/// @todo Monitor time elapsed and return from the lease reclamation routine
/// if it hits the timeout value.
util::Stopwatch stopwatch;
LeaseMgr& lease_mgr = LeaseMgrFactory::instance();
Lease4Collection leases;
lease_mgr.getExpiredLeases4(leases, max_leases);
BOOST_FOREACH(Lease4Ptr lease, leases) {
try {
/// @todo execute a lease4_expire hook here.
// Generate removal name change request for D2, if required.
// This will return immediatelly if the DNS wasn't updated
// when the lease was created.
if (lease->client_id_) {
// Client id takes precedence over HW address.
queueRemovalNameChangeRequest(lease, lease->client_id_->getClientId());
} else {
// Client id is not specified for the lease. Use HW address
// instead.
queueRemovalNameChangeRequest(lease, lease->hwaddr_);
}
// Reclaim the lease - depending on the configuration, set the
// expired-reclaimed state or simply remove it.
reclaimLeaseInDatabase<Lease4Ptr>(lease, remove_lease,
boost::bind(&LeaseMgr::updateLease4,
&lease_mgr, _1));
// Update statistics.
// Decrease number of assigned addresses.
StatsMgr::instance().addValue(StatsMgr::generateName("subnet",
lease->subnet_id_,
"assigned-addresses"),
int64_t(-1));
// Increase total number of reclaimed leases.
StatsMgr::instance().addValue("reclaimed-leases", int64_t(1));
// Increase number of reclaimed leases for a subnet.
StatsMgr::instance().addValue(StatsMgr::generateName("subnet",
lease->subnet_id_,
"reclaimed-leases"),
int64_t(1));
} catch (const std::exception& ex) {
LOG_ERROR(alloc_engine_logger, ALLOC_ENGINE_V4_LEASE_RECLAMATION_FAILED)
.arg(lease->addr_.toText())
.arg(ex.what());
}
}
// Stop measuring the time.
stopwatch.stop();
// Mark completion of the lease reclamation routine and present some stats.
LOG_DEBUG(alloc_engine_logger, ALLOC_ENGINE_DBG_TRACE,
ALLOC_ENGINE_V4_LEASES_RECLAMATION_COMPLETE)
.arg(leases.size())
.arg(stopwatch.logFormatTotalDuration());
}
template<typename LeasePtrType, typename IdentifierType>
void
AllocEngine::queueRemovalNameChangeRequest(const LeasePtrType& lease,
const IdentifierType& identifier) const {
// Check if there is a need for update.
if (!lease || lease->hostname_.empty() || (!lease->fqdn_fwd_ && !lease->fqdn_rev_)
|| !CfgMgr::instance().getD2ClientMgr().ddnsEnabled()) {
return;
}
try {
// Create DHCID
std::vector<uint8_t> hostname_wire;
OptionDataTypeUtil::writeFqdn(lease->hostname_, hostname_wire, true);
dhcp_ddns::D2Dhcid dhcid = D2Dhcid(identifier, hostname_wire);
// Create name change request.
NameChangeRequestPtr ncr(new NameChangeRequest(isc::dhcp_ddns::CHG_REMOVE,
lease->fqdn_fwd_, lease->fqdn_rev_,
lease->hostname_,
lease->addr_.toText(),
dhcid, 0, lease->valid_lft_));
// Send name change request.
CfgMgr::instance().getD2ClientMgr().sendRequest(ncr);
} catch (const std::exception& ex) {
LOG_ERROR(alloc_engine_logger, ALLOC_ENGINE_REMOVAL_NCR_FAILED)
.arg(lease->addr_.toText())
.arg(ex.what());
}
}
template<typename LeasePtrType>
void AllocEngine::reclaimLeaseInDatabase(const LeasePtrType& lease,
const bool remove_lease,
const boost::function<void (const LeasePtrType&)>&
lease_update_fun) const {
LeaseMgr& lease_mgr = LeaseMgrFactory::instance();
// Reclaim the lease - depending on the configuration, set the
// expired-reclaimed state or simply remove it.
if (remove_lease) {
lease_mgr.deleteLease(lease->addr_);
} else {
// Clear FQDN information as we have already sent the
// name change request to remove the DNS record.
lease->hostname_.clear();
lease->fqdn_fwd_ = false;
lease->fqdn_rev_ = false;
lease->state_ = Lease::STATE_EXPIRED_RECLAIMED;
lease_update_fun(lease);
}
// Lease has been reclaimed.
LOG_DEBUG(alloc_engine_logger, ALLOC_ENGINE_DBG_TRACE,
ALLOC_ENGINE_LEASE_RECLAIMED)
.arg(lease->addr_.toText());
}
} // end of isc::dhcp namespace
} // end of isc namespace

View File

@@ -26,6 +26,7 @@
#include <dhcpsrv/lease_mgr.h>
#include <hooks/callout_handle.h>
#include <boost/function.hpp>
#include <boost/shared_ptr.hpp>
#include <boost/noncopyable.hpp>
@@ -490,6 +491,52 @@ public:
/// @return Returns renewed lease.
Lease6Collection renewLeases6(ClientContext6& ctx);
/// @brief Reclaims expired IPv6 leases.
///
/// This method retrieves a collection of expired leases and reclaims them.
/// See http://kea.isc.org/wiki/LeaseExpirationDesign#LeasesReclamationRoutine
/// for the details.
///
/// This method is executed periodically to act upon expired leases. This
/// includes for each lease:
/// - executing "lease_expire6" hook,
/// - removing DNS record for a lease,
/// - reclaiming a lease in the database, i.e. setting its state to
/// "expired-reclaimed" or removing it from the lease databse,
/// - updating statistics of assigned and reclaimed leases
///
/// @param max_leases Maximum number of leases to be reclaimed.
/// @param timeout Maximum amount of time that the reclaimation routine
/// may be processing expired leases, expressed in seconds.
/// @param remove_lease A boolean value indicating if the lease should
/// be removed when it is reclaimed (if true) or it should be left in the
/// database in the "expired-reclaimed" state (if false).
void reclaimExpiredLeases6(const size_t max_leases, const uint16_t timeout,
const bool remove_lease);
/// @brief Reclaims expired IPv4 leases.
///
/// This method retrieves a collection of expired leases and reclaims them.
/// See http://kea.isc.org/wiki/LeaseExpirationDesign#LeasesReclamationRoutine
/// for the details.
///
/// This method is executed periodically to act upon expired leases. This
/// includes for each lease:
/// - executing "lease_expire6" hook,
/// - removing DNS record for a lease,
/// - reclaiming a lease in the database, i.e. setting its state to
/// "expired-reclaimed" or removing it from the lease databse,
/// - updating statistics of assigned and reclaimed leases
///
/// @param max_leases Maximum number of leases to be reclaimed.
/// @param timeout Maximum amount of time that the reclaimation routine
/// may be processing expired leases, expressed in seconds.
/// @param remove_lease A boolean value indicating if the lease should
/// be removed when it is reclaimed (if true) or it should be left in the
/// database in the "expired-reclaimed" state (if false).
void reclaimExpiredLeases4(const size_t max_leases, const uint16_t timeout,
const bool remove_lease);
/// @brief Attempts to find appropriate host reservation.
///
/// Attempts to find appropriate host reservation in HostMgr. If found, it
@@ -663,6 +710,45 @@ private:
/// @param lease IPv6 lease to be extended.
void extendLease6(ClientContext6& ctx, Lease6Ptr lease);
/// @brief Sends removal name change reuqest to D2.
///
/// This method is exception safe.
///
/// @param lease Pointer to a lease for which NCR should be sent.
/// @param identifier Identifier to be used to generate DHCID for
/// the DNS update. For DHCPv4 it will be hardware address or client
/// identifier. For DHCPv6 it will be a DUID.
///
/// @tparam LeasePtrType Pointer to a lease.
/// @tparam IdentifierType HW Address, Client Identifier or DUID.
template<typename LeasePtrType, typename IdentifierType>
void queueRemovalNameChangeRequest(const LeasePtrType& lease,
const IdentifierType& identifier) const;
/// @brief Marks lease as reclaimed in the database.
///
/// This method is called internally by the leases reclaimation routines.
/// Depending on the value of the @c remove_lease parameter this method
/// will delete the reclaimed lease from the database or set its sate
/// to "expired-reclaimed". In the latter case it will also clear the
/// FQDN information.
///
/// This method may throw exceptions if the operation on the lease database
/// fails for any reason.
///
/// @param lease Pointer to the lease.
/// @param remove_lease Boolean flag indicating if the lease should be
/// removed from the database (if true).
/// @param lease_update_fun Pointer to the function in the @c LeaseMgr to
/// be used to update the lease if the @c remove_lease is set to false.
///
/// @tparam LeasePtrType One of the @c Lease6Ptr or @c Lease4Ptr.
template<typename LeasePtrType>
void reclaimLeaseInDatabase(const LeasePtrType& lease,
const bool remove_lease,
const boost::function<void (const LeasePtrType&)>&
lease_update_fun) const;
public:
/// @brief Context information for the DHCPv4 lease allocation.

View File

@@ -14,6 +14,18 @@
$NAMESPACE isc::dhcp
% ALLOC_ENGINE_LEASE_RECLAIMED successfully reclaimed lease %1
This debug message is logged when the allocation engine successfully
reclaims a lease. The lease is now available for assignment.
% ALLOC_ENGINE_REMOVAL_NCR_FAILED sending removal name change request failed for lease %1: %2
This error message is logged when sending a removal name change request
to DHCP DDNS failed. This name change request is usually generated when
the lease reclamation routine acts upon expired leases. If a lease being
reclaimed has a corresponding DNS entry it needs to be removed.
This message indicates that removal of the DNS entry has failed.
Nevertheless the lease will be reclaimed.
% ALLOC_ENGINE_V4_ALLOC_ERROR %1: error during attempt to allocate an IPv4 address: %2
An error occurred during an attempt to allocate an IPv4 address, the
reason for the failure being contained in the message. The server will
@@ -49,6 +61,27 @@ client sending the DHCPDISCOVER has a reservation for the specified
address. The allocation engine will try to offer this address to
the client.
% ALLOC_ENGINE_V4_LEASE_RECLAMATION_FAILED failed to reclaim the lease %1: %2
This error message is logged when the allocation engine fails to
reclaim an expired lease. The reason for the failure is included in the
message. The error may be triggered in the lease expiration hook or
while performing the operation on the lease database.
% ALLOC_ENGINE_V4_LEASES_RECLAMATION_COMPLETE reclaimed %1 leases in %2
This debug message is logged when the allocation engine completes
reclamation of a set of expired leases. The maximum number of leases
to be reclaimed in a single pass of the lease reclamation routine
is configurable using 'max-reclaim-leases' parameter. However,
the number of reclaimed leases may also be limited by the timeout
value, configured with 'max-reclaim-time'. The message includes the
number of reclaimed leases and the total time.
% ALLOC_ENGINE_V4_LEASES_RECLAMATION_START starting reclamation of expired leases (limit = %1 leases or %2 seconds)
This debug message is issued when the allocation engine starts the
reclamation of the expired leases. The maximum number of leases to
be reclaimed and the timeout is included in the message. If any of
these values is 0, it means "unlimited".
% ALLOC_ENGINE_V4_OFFER_EXISTING_LEASE allocation engine will try to offer existing lease to the client %1
This message is issued when the allocation engine determines that
the client has a lease in the lease database, it doesn't have
@@ -246,6 +279,27 @@ reserved for it.
This informational message signals that the specified client was assigned the prefix
reserved for it.
% ALLOC_ENGINE_V6_LEASE_RECLAMATION_FAILED failed to reclaim the lease %1: %2
This error message is logged when the allocation engine fails to
reclaim an expired lease. The reason for the failure is included in the
message. The error may be triggered in the lease expiration hook or
while performing the operation on the lease database.
% ALLOC_ENGINE_V6_LEASES_RECLAMATION_COMPLETE reclaimed %1 leases in %2
This debug message is logged when the allocation engine completes
reclamation of a set of expired leases. The maximum number of leases
to be reclaimed in a single pass of the lease reclamation routine
is configurable using 'max-reclaim-leases' parameter. However,
the number of reclaimed leases may also be limited by the timeout
value, configured with 'max-reclaim-time'. The message includes the
number of reclaimed leases and the total time.
% ALLOC_ENGINE_V6_LEASES_RECLAMATION_START starting reclamation of expired leases (limit = %1 leases or %2 seconds)
This debug message is issued when the allocation engine starts the
reclamation of the expired leases. The maximum number of leases to
be reclaimed and the timeout is included in the message. If any of
these values is 0, it means "unlimited".
% ALLOC_ENGINE_V6_RENEW_HR allocating leases reserved for the client %1 as a result of Renew
This debug message is issued when the allocation engine tries to
allocate reserved leases for the client sending a Renew message.

View File

@@ -60,6 +60,7 @@ TESTS += libdhcpsrv_unittests
libdhcpsrv_unittests_SOURCES = run_unittests.cc
libdhcpsrv_unittests_SOURCES += addr_utilities_unittest.cc
libdhcpsrv_unittests_SOURCES += alloc_engine_utils.cc alloc_engine_utils.h
libdhcpsrv_unittests_SOURCES += alloc_engine_expiration_unittest.cc
libdhcpsrv_unittests_SOURCES += alloc_engine_hooks_unittest.cc
libdhcpsrv_unittests_SOURCES += alloc_engine4_unittest.cc
libdhcpsrv_unittests_SOURCES += alloc_engine6_unittest.cc

File diff suppressed because it is too large Load Diff