Commit 5b10e071 authored by Tomek Mrugalski's avatar Tomek Mrugalski 🛰
Browse files

[2994] lease4_select hook implemented.

parent 1626b91e
......@@ -29,11 +29,13 @@ using namespace isc::hooks;
namespace {
/// Structure that holds registered hook indexes
struct Dhcp6Hooks {
struct AllocEngineHooks {
int hook_index_lease4_select_; ///< index for "lease4_receive" hook point
int hook_index_lease6_select_; ///< index for "lease6_receive" hook point
/// Constructor that registers hook points for AllocationEngine
Dhcp6Hooks() {
AllocEngineHooks() {
hook_index_lease6_select_ = HooksManager::registerHook("lease4_select");
hook_index_lease6_select_ = HooksManager::registerHook("lease6_select");
}
};
......@@ -42,7 +44,7 @@ struct Dhcp6Hooks {
// will be instantiated (and the constructor run) when the module is loaded.
// As a result, the hook indexes will be defined before any method in this
// module is called.
Dhcp6Hooks Hooks;
AllocEngineHooks Hooks;
}; // anonymous namespace
......@@ -187,6 +189,7 @@ AllocEngine::AllocEngine(AllocType engine_type, unsigned int attempts)
}
// Register hook points
hook_index_lease4_select_ = Hooks.hook_index_lease4_select_;
hook_index_lease6_select_ = Hooks.hook_index_lease6_select_;
}
......@@ -312,7 +315,8 @@ AllocEngine::allocateAddress4(const SubnetPtr& subnet,
const ClientIdPtr& clientid,
const HWAddrPtr& hwaddr,
const IOAddress& hint,
bool fake_allocation /* = false */ ) {
bool fake_allocation,
const isc::hooks::CalloutHandlePtr& callout_handle) {
try {
// Allocator is always created in AllocEngine constructor and there is
......@@ -365,7 +369,8 @@ AllocEngine::allocateAddress4(const SubnetPtr& subnet,
/// implemented
// The hint is valid and not currently used, let's create a lease for it
Lease4Ptr lease = createLease4(subnet, clientid, hwaddr, hint, fake_allocation);
Lease4Ptr lease = createLease4(subnet, clientid, hwaddr, hint,
callout_handle, fake_allocation);
// It can happen that the lease allocation failed (we could have lost
// the race condition. That means that the hint is lo longer usable and
......@@ -376,7 +381,7 @@ AllocEngine::allocateAddress4(const SubnetPtr& subnet,
} else {
if (existing->expired()) {
return (reuseExpiredLease(existing, subnet, clientid, hwaddr,
fake_allocation));
callout_handle, fake_allocation));
}
}
......@@ -410,7 +415,7 @@ AllocEngine::allocateAddress4(const SubnetPtr& subnet,
// there's no existing lease for selected candidate, so it is
// free. Let's allocate it.
Lease4Ptr lease = createLease4(subnet, clientid, hwaddr, candidate,
fake_allocation);
callout_handle, fake_allocation);
if (lease) {
return (lease);
}
......@@ -421,7 +426,7 @@ AllocEngine::allocateAddress4(const SubnetPtr& subnet,
} else {
if (existing->expired()) {
return (reuseExpiredLease(existing, subnet, clientid, hwaddr,
fake_allocation));
callout_handle, fake_allocation));
}
}
......@@ -515,7 +520,7 @@ Lease6Ptr AllocEngine::reuseExpiredLease(Lease6Ptr& expired,
// assigned, so the client will get NoAddrAvail as a result. The lease
// won't be inserted into the
if (callout_handle->getSkip()) {
LOG_DEBUG(dhcpsrv_logger, DHCPSRV_DBG_HOOKS, DHCPSRV_HOOK_LEASE6_IA_ADD_SKIP);
LOG_DEBUG(dhcpsrv_logger, DHCPSRV_DBG_HOOKS, DHCPSRV_HOOK_LEASE6_SELECT_SKIP);
return (Lease6Ptr());
}
......@@ -541,6 +546,7 @@ Lease4Ptr AllocEngine::reuseExpiredLease(Lease4Ptr& expired,
const SubnetPtr& subnet,
const ClientIdPtr& clientid,
const HWAddrPtr& hwaddr,
const isc::hooks::CalloutHandlePtr& callout_handle,
bool fake_allocation /*= false */ ) {
if (!expired->expired()) {
......@@ -563,6 +569,39 @@ Lease4Ptr AllocEngine::reuseExpiredLease(Lease4Ptr& expired,
/// @todo: log here that the lease was reused (there's ticket #2524 for
/// logging in libdhcpsrv)
// Let's execute all callouts registered for lease4_select
if (callout_handle &&
HooksManager::getHooksManager().calloutsPresent(hook_index_lease4_select_)) {
// Delete all previous arguments
callout_handle->deleteAllArguments();
// Pass necessary arguments
// Subnet from which we do the allocation
callout_handle->setArgument("subnet4", subnet);
// Is this solicit (fake = true) or request (fake = false)
callout_handle->setArgument("fake_allocation", fake_allocation);
// The lease that will be assigned to a client
callout_handle->setArgument("lease4", expired);
// Call the callouts
HooksManager::callCallouts(hook_index_lease6_select_, *callout_handle);
// Callouts decided to skip the action. This means that the lease is not
// assigned, so the client will get NoAddrAvail as a result. The lease
// won't be inserted into the
if (callout_handle->getSkip()) {
LOG_DEBUG(dhcpsrv_logger, DHCPSRV_DBG_HOOKS, DHCPSRV_HOOK_LEASE4_SELECT_SKIP);
return (Lease4Ptr());
}
// Let's use whatever callout returned. Hopefully it is the same lease
// we handled to it.
callout_handle->getArgument("lease4", expired);
}
if (!fake_allocation) {
// for REQUEST we do update the lease
LeaseMgrFactory::instance().updateLease4(expired);
......@@ -587,7 +626,7 @@ Lease6Ptr AllocEngine::createLease6(const Subnet6Ptr& subnet,
subnet->getPreferred(), subnet->getValid(),
subnet->getT1(), subnet->getT2(), subnet->getID()));
// Let's execute all callouts registered for lease6_ia_added
// Let's execute all callouts registered for lease6_select
if (callout_handle &&
HooksManager::getHooksManager().calloutsPresent(hook_index_lease6_select_)) {
......@@ -613,7 +652,7 @@ Lease6Ptr AllocEngine::createLease6(const Subnet6Ptr& subnet,
// assigned, so the client will get NoAddrAvail as a result. The lease
// won't be inserted into the
if (callout_handle->getSkip()) {
LOG_DEBUG(dhcpsrv_logger, DHCPSRV_DBG_HOOKS, DHCPSRV_HOOK_LEASE6_IA_ADD_SKIP);
LOG_DEBUG(dhcpsrv_logger, DHCPSRV_DBG_HOOKS, DHCPSRV_HOOK_LEASE6_SELECT_SKIP);
return (Lease6Ptr());
}
......@@ -654,6 +693,7 @@ Lease4Ptr AllocEngine::createLease4(const SubnetPtr& subnet,
const DuidPtr& clientid,
const HWAddrPtr& hwaddr,
const IOAddress& addr,
const isc::hooks::CalloutHandlePtr& callout_handle,
bool fake_allocation /*= false */ ) {
if (!hwaddr) {
isc_throw(BadValue, "Can't create a lease with NULL HW address");
......@@ -671,6 +711,43 @@ Lease4Ptr AllocEngine::createLease4(const SubnetPtr& subnet,
subnet->getT1(), subnet->getT2(), now,
subnet->getID()));
// Let's execute all callouts registered for lease4_select
if (callout_handle &&
HooksManager::getHooksManager().calloutsPresent(hook_index_lease4_select_)) {
// Delete all previous arguments
callout_handle->deleteAllArguments();
// Clear skip flag if it was set in previous callouts
callout_handle->setSkip(false);
// Pass necessary arguments
// Subnet from which we do the allocation
callout_handle->setArgument("subnet4", subnet);
// Is this solicit (fake = true) or request (fake = false)
callout_handle->setArgument("fake_allocation", fake_allocation);
callout_handle->setArgument("lease4", lease);
// This is the first callout, so no need to clear any arguments
HooksManager::callCallouts(hook_index_lease4_select_, *callout_handle);
// Callouts decided to skip the action. This means that the lease is not
// assigned, so the client will get NoAddrAvail as a result. The lease
// won't be inserted into the
if (callout_handle->getSkip()) {
LOG_DEBUG(dhcpsrv_logger, DHCPSRV_DBG_HOOKS, DHCPSRV_HOOK_LEASE4_SELECT_SKIP);
return (Lease4Ptr());
}
// Let's use whatever callout returned. Hopefully it is the same lease
// we handled to it.
callout_handle->getArgument("lease6", lease);
}
if (!fake_allocation) {
// That is a real (REQUEST) allocation
bool status = LeaseMgrFactory::instance().addLease(lease);
......
......@@ -194,13 +194,16 @@ protected:
/// @param hint a hint that the client provided
/// @param fake_allocation is this real i.e. REQUEST (false) or just picking
/// an address for DISCOVER that is not really allocated (true)
/// @param callout_handle a callout handle (used in hooks). A lease callouts
/// will be executed if this parameter is passed.
/// @return Allocated IPv4 lease (or NULL if allocation failed)
Lease4Ptr
allocateAddress4(const SubnetPtr& subnet,
const ClientIdPtr& clientid,
const HWAddrPtr& hwaddr,
const isc::asiolink::IOAddress& hint,
bool fake_allocation);
bool fake_allocation,
const isc::hooks::CalloutHandlePtr& callout_handle);
/// @brief Renews a IPv4 lease
///
......@@ -262,6 +265,8 @@ private:
/// @param clientid client identifier
/// @param hwaddr client's hardware address
/// @param addr an address that was selected and is confirmed to be available
/// @param callout_handle a callout handle (used in hooks). A lease callouts
/// will be executed if this parameter is passed.
/// @param fake_allocation is this real i.e. REQUEST (false) or just picking
/// an address for DISCOVER that is not really allocated (true)
/// @return allocated lease (or NULL in the unlikely case of the lease just
......@@ -269,6 +274,7 @@ private:
Lease4Ptr createLease4(const SubnetPtr& subnet, const DuidPtr& clientid,
const HWAddrPtr& hwaddr,
const isc::asiolink::IOAddress& addr,
const isc::hooks::CalloutHandlePtr& callout_handle,
bool fake_allocation = false);
/// @brief creates a lease and inserts it in LeaseMgr if necessary
......@@ -302,6 +308,8 @@ private:
/// @param subnet subnet the lease is allocated from
/// @param clientid client identifier
/// @param hwaddr client's hardware address
/// @param callout_handle a callout handle (used in hooks). A lease callouts
/// will be executed if this parameter is passed.
/// @param fake_allocation is this real i.e. REQUEST (false) or just picking
/// an address for DISCOVER that is not really allocated (true)
/// @return refreshed lease
......@@ -309,6 +317,7 @@ private:
Lease4Ptr reuseExpiredLease(Lease4Ptr& expired, const SubnetPtr& subnet,
const ClientIdPtr& clientid,
const HWAddrPtr& hwaddr,
const isc::hooks::CalloutHandlePtr& callout_handle,
bool fake_allocation = false);
/// @brief Reuses expired IPv6 lease
......@@ -338,8 +347,9 @@ private:
/// @brief number of attempts before we give up lease allocation (0=unlimited)
unsigned int attempts_;
/// @brief hook name index (used in hooks callouts)
int hook_index_lease6_select_;
// hook name indexes (used in hooks callouts)
int hook_index_lease4_select_; ///< index for lease4_select hook
int hook_index_lease6_select_; ///< index for lease6_select hook
};
}; // namespace isc::dhcp
......
......@@ -121,8 +121,14 @@ the database access parameters are changed: in the latter case, the
server closes the currently open database, and opens a database using
the new parameters.
% DHCPSRV_HOOK_LEASE6_IA_ADD_SKIP Lease6 (non-temporary) creation was skipped, because of callout skip flag.
This debug message is printed when a callout installed on lease6_assign
% DHCPSRV_HOOK_LEASE4_SELECT_SKIP Lease4 creation was skipped, because of callout skip flag.
This debug message is printed when a callout installed on lease4_select
hook point sets a skip flag. It means that the server was told that no lease4
should be assigned. The server will not put that lease in its database and the client
will get a NAK packet.
% DHCPSRV_HOOK_LEASE6_SELECT_SKIP Lease6 (non-temporary) creation was skipped, because of callout skip flag.
This debug message is printed when a callout installed on lease6_select
hook point sets a skip flag. It means that the server was told that no lease6
should be assigned. The server will not put that lease in its database and the client
will get a NoAddrsAvail for that IA_NA option.
......
......@@ -592,7 +592,8 @@ TEST_F(AllocEngine4Test, simpleAlloc4) {
ASSERT_TRUE(engine);
Lease4Ptr lease = engine->allocateAddress4(subnet_, clientid_, hwaddr_,
IOAddress("0.0.0.0"), false);
IOAddress("0.0.0.0"), false,
CalloutHandlePtr());
// Check that we got a lease
ASSERT_TRUE(lease);
......@@ -615,7 +616,8 @@ TEST_F(AllocEngine4Test, fakeAlloc4) {
ASSERT_TRUE(engine);
Lease4Ptr lease = engine->allocateAddress4(subnet_, clientid_, hwaddr_,
IOAddress("0.0.0.0"), true);
IOAddress("0.0.0.0"), true,
CalloutHandlePtr());
// Check that we got a lease
ASSERT_TRUE(lease);
......@@ -638,7 +640,7 @@ TEST_F(AllocEngine4Test, allocWithValidHint4) {
Lease4Ptr lease = engine->allocateAddress4(subnet_, clientid_, hwaddr_,
IOAddress("192.0.2.105"),
false);
false, CalloutHandlePtr());
// Check that we got a lease
ASSERT_TRUE(lease);
......@@ -678,7 +680,7 @@ TEST_F(AllocEngine4Test, allocWithUsedHint4) {
// twice.
Lease4Ptr lease = engine->allocateAddress4(subnet_, clientid_, hwaddr_,
IOAddress("192.0.2.106"),
false);
false, CalloutHandlePtr());
// Check that we got a lease
ASSERT_TRUE(lease);
......@@ -712,7 +714,7 @@ TEST_F(AllocEngine4Test, allocBogusHint4) {
// with the normal allocation
Lease4Ptr lease = engine->allocateAddress4(subnet_, clientid_, hwaddr_,
IOAddress("10.1.1.1"),
false);
false, CalloutHandlePtr());
// Check that we got a lease
ASSERT_TRUE(lease);
......@@ -739,18 +741,19 @@ TEST_F(AllocEngine4Test, allocateAddress4Nulls) {
// Allocations without subnet are not allowed
Lease4Ptr lease = engine->allocateAddress4(SubnetPtr(), clientid_, hwaddr_,
IOAddress("0.0.0.0"), false);
IOAddress("0.0.0.0"), false,
CalloutHandlePtr());
EXPECT_FALSE(lease);
// Allocations without HW address are not allowed
lease = engine->allocateAddress4(subnet_, clientid_, HWAddrPtr(),
IOAddress("0.0.0.0"), false);
IOAddress("0.0.0.0"), false, CalloutHandlePtr());
EXPECT_FALSE(lease);
// Allocations without client-id are allowed
clientid_ = ClientIdPtr();
lease = engine->allocateAddress4(subnet_, ClientIdPtr(), hwaddr_,
IOAddress("0.0.0.0"), false);
IOAddress("0.0.0.0"), false, CalloutHandlePtr());
// Check that we got a lease
ASSERT_TRUE(lease);
......@@ -854,7 +857,7 @@ TEST_F(AllocEngine4Test, smallPool4) {
cfg_mgr.addSubnet4(subnet_);
Lease4Ptr lease = engine->allocateAddress4(subnet_, clientid_, hwaddr_, IOAddress("0.0.0.0"),
false);
false, CalloutHandlePtr());
// Check that we got that single lease
ASSERT_TRUE(lease);
......@@ -902,7 +905,8 @@ TEST_F(AllocEngine4Test, outOfAddresses4) {
// else, so the allocation should fail
Lease4Ptr lease2 = engine->allocateAddress4(subnet_, clientid_, hwaddr_,
IOAddress("0.0.0.0"), false);
IOAddress("0.0.0.0"), false,
CalloutHandlePtr());
EXPECT_FALSE(lease2);
}
......@@ -935,7 +939,7 @@ TEST_F(AllocEngine4Test, discoverReuseExpiredLease4) {
// CASE 1: Asking for any address
lease = engine->allocateAddress4(subnet_, clientid_, hwaddr_, IOAddress("0.0.0.0"),
true);
true, CalloutHandlePtr());
// Check that we got that single lease
ASSERT_TRUE(lease);
EXPECT_EQ(addr.toText(), lease->addr_.toText());
......@@ -945,7 +949,7 @@ TEST_F(AllocEngine4Test, discoverReuseExpiredLease4) {
// CASE 2: Asking specifically for this address
lease = engine->allocateAddress4(subnet_, clientid_, hwaddr_, IOAddress(addr.toText()),
true);
true, CalloutHandlePtr());
// Check that we got that single lease
ASSERT_TRUE(lease);
EXPECT_EQ(addr.toText(), lease->addr_.toText());
......@@ -972,7 +976,8 @@ TEST_F(AllocEngine4Test, requestReuseExpiredLease4) {
// A client comes along, asking specifically for this address
lease = engine->allocateAddress4(subnet_, clientid_, hwaddr_,
IOAddress(addr.toText()), false);
IOAddress(addr.toText()), false,
CalloutHandlePtr());
// Check that he got that single lease
ASSERT_TRUE(lease);
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment