mirror of
https://gitlab.isc.org/isc-projects/kea
synced 2025-08-30 13:37:55 +00:00
[#3110] HA decline updates working
Updates are working, need clean up and UTs in HA. src/bin/dhcp4/dhcp4_hooks.dox Updated hooks dev guide src/bin/dhcp4/dhcp4_srv.cc Added callout lease4_server_decline Dhcpv4Srv::serverDecline() - added lease4_server_decline hook point src/bin/dhcp4/tests/hooks_unittest.cc TEST_F(HooksDhcpv4SrvTest, lease4OfferDiscoverDecline) - new test src/hooks/dhcp/high_availability/ha_callouts.cc lease4_server_decline() - new callout function src/hooks/dhcp/high_availability/ha_impl.* HAImpl::lease4ServerDecline() - new callout handler src/hooks/dhcp/high_availability/ha_messages.mes HA_LEASE4_SERVER_DECLINE_FAILED - new log src/hooks/dhcp/high_availability/ha_service.* HAService::asyncSendLeaseUpdate() - new function for a single lease update HAService::asyncSendLeaseUpdates() - check parking lot null
This commit is contained in:
@@ -340,8 +340,32 @@ called before "subnet4_select".
|
|||||||
- <b>Next step status</b>: If any callout installed on the "lease4_offer" hook point
|
- <b>Next step status</b>: If any callout installed on the "lease4_offer" hook point
|
||||||
sets the next step action to DROP, the server will drop the processed query
|
sets the next step action to DROP, the server will drop the processed query
|
||||||
and discard the prepared DHCPOFFER rather than sending it to the client.
|
and discard the prepared DHCPOFFER rather than sending it to the client.
|
||||||
Any further action, such as marking the discarded DHCPOFFER's lease as declined,
|
If it sets the next step action to PARK, the server will park the processed
|
||||||
is the responsibility of the callout.
|
packet (hold packet processing) until the hook libraries explicitly unpark
|
||||||
|
the packet after they are done performing asynchronous operations.
|
||||||
|
|
||||||
|
Prior to unparking the packet, callouts are expected to set the argument,
|
||||||
|
"offer_address_in_use" to false if the address is available and the offer should
|
||||||
|
be sent to the client. If the address should be declined, callouts should set
|
||||||
|
the argument to true. This will cause the server to discard the DHCPOFFER, mark
|
||||||
|
the lease DECLINED in the lease store, update the relevant statitics, and then
|
||||||
|
invoke callouts installed for lease4_server_decline.
|
||||||
|
|
||||||
|
@subsection dhcpv4Lease4ServerDecline lease4_server_decline
|
||||||
|
|
||||||
|
- @b Arguments:
|
||||||
|
- name: @b query4, type: isc::dhcp::Pkt4Ptr, direction: <b>in</b>
|
||||||
|
- name: @b lease4, type: isc::dhcp::Lease4Ptr, direction: <b>in</b>
|
||||||
|
|
||||||
|
- @b Description: this callout is executed after a lease4_offer callout has
|
||||||
|
determined that the lease to be offered is already in use by an unknown
|
||||||
|
client. At this point in processing, the offer has been discarded, the lease
|
||||||
|
has been marked DECLINED in the lease store, and the relevant statistics have
|
||||||
|
been updated. The argument "query4" contains a pointer to an isc::dhcp::Pkt4
|
||||||
|
object that contains all information regarding incoming DHCPDISCOVER packet.
|
||||||
|
The "leases4" object will hold the pointer to the declined lease.
|
||||||
|
|
||||||
|
- <b>Next step status</b>: Not applicable, its value will be ignored.
|
||||||
|
|
||||||
@subsection dhcpv4HooksPkt4Send pkt4_send
|
@subsection dhcpv4HooksPkt4Send pkt4_send
|
||||||
|
|
||||||
|
@@ -100,6 +100,7 @@ struct Dhcp4Hooks {
|
|||||||
int hook_index_host4_identifier_; ///< index for "host4_identifier" hook point
|
int hook_index_host4_identifier_; ///< index for "host4_identifier" hook point
|
||||||
int hook_index_ddns4_update_; ///< index for "ddns4_update" hook point
|
int hook_index_ddns4_update_; ///< index for "ddns4_update" hook point
|
||||||
int hook_index_lease4_offer_; ///< index for "lease4_offer" hook point
|
int hook_index_lease4_offer_; ///< index for "lease4_offer" hook point
|
||||||
|
int hook_index_lease4_server_decline_; ///< index for "lease4_server_decline" hook point
|
||||||
|
|
||||||
/// Constructor that registers hook points for DHCPv4 engine
|
/// Constructor that registers hook points for DHCPv4 engine
|
||||||
Dhcp4Hooks() {
|
Dhcp4Hooks() {
|
||||||
@@ -114,6 +115,7 @@ struct Dhcp4Hooks {
|
|||||||
hook_index_host4_identifier_ = HooksManager::registerHook("host4_identifier");
|
hook_index_host4_identifier_ = HooksManager::registerHook("host4_identifier");
|
||||||
hook_index_ddns4_update_ = HooksManager::registerHook("ddns4_update");
|
hook_index_ddns4_update_ = HooksManager::registerHook("ddns4_update");
|
||||||
hook_index_lease4_offer_ = HooksManager::registerHook("lease4_offer");
|
hook_index_lease4_offer_ = HooksManager::registerHook("lease4_offer");
|
||||||
|
hook_index_lease4_server_decline_ = HooksManager::registerHook("lease4_server_decline");
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -3949,8 +3951,11 @@ Dhcpv4Srv::declineLease(const Lease4Ptr& lease, const Pkt4Ptr& decline,
|
|||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
Dhcpv4Srv::serverDecline(hooks::CalloutHandlePtr& /* callout_handle */, Pkt4Ptr& query,
|
Dhcpv4Srv::serverDecline(hooks::CalloutHandlePtr& callout_handle, Pkt4Ptr& query,
|
||||||
Lease4Ptr lease, bool lease_exists) {
|
Lease4Ptr lease, bool lease_exists) {
|
||||||
|
LOG_INFO(lease4_logger, DHCP4_SERVER_INITIATED_DECLINE)
|
||||||
|
.arg(lease->addr_.toText())
|
||||||
|
.arg(lease->valid_lft_);
|
||||||
|
|
||||||
{
|
{
|
||||||
// Check if the resource is busy i.e. can be modified by another thread
|
// Check if the resource is busy i.e. can be modified by another thread
|
||||||
@@ -4039,47 +4044,25 @@ Dhcpv4Srv::serverDecline(hooks::CalloutHandlePtr& /* callout_handle */, Pkt4Ptr&
|
|||||||
StatsMgr::instance().addValue("assigned-addresses", static_cast<int64_t>(1));
|
StatsMgr::instance().addValue("assigned-addresses", static_cast<int64_t>(1));
|
||||||
}
|
}
|
||||||
|
|
||||||
/* (comment it out so picky tools don't flag this as dead code
|
|
||||||
//
|
|
||||||
/// @todo #3110, HA will implement a handler for this hook point to
|
|
||||||
/// propagate an update of the lease to peers.
|
|
||||||
//
|
|
||||||
// Let's check if there are hooks installed for server decline hook point.
|
// Let's check if there are hooks installed for server decline hook point.
|
||||||
// If they are, let's pass the lease and client's packet. Note this code
|
// If there are, let's pass the DHCPDISCOVER and the declined lease .
|
||||||
// has never been compiled, it is just an initial draft.
|
|
||||||
if (HooksManager::calloutsPresent(Hooks.hook_index_lease4_server_decline_)) {
|
if (HooksManager::calloutsPresent(Hooks.hook_index_lease4_server_decline_)) {
|
||||||
CalloutHandlePtr callout_handle = getCalloutHandle(decline);
|
|
||||||
|
|
||||||
// Use the RAII wrapper to make sure that the callout handle state is
|
// Use the RAII wrapper to make sure that the callout handle state is
|
||||||
// reset when this object goes out of scope. All hook points must do
|
// reset when this object goes out of scope. All hook points must do
|
||||||
// it to prevent possible circular dependency between the callout
|
// it to prevent possible circular dependency between the callout
|
||||||
// handle and its arguments.
|
// handle and its arguments.
|
||||||
ScopedCalloutHandleState callout_handle_state(callout_handle);
|
ScopedCalloutHandleState callout_handle_state(callout_handle);
|
||||||
|
|
||||||
// Pass the original packet
|
// Pass in the original DHCPDISCOVER
|
||||||
callout_handle->setArgument("query4", query);
|
callout_handle->setArgument("query4", query);
|
||||||
|
|
||||||
// Pass the lease to be updated
|
// Pass in the declined lease.
|
||||||
callout_handle->setArgument("lease4", lease);
|
callout_handle->setArgument("lease4", lease);
|
||||||
|
|
||||||
// Call callouts
|
// Call callouts
|
||||||
HooksManager::callCallouts(Hooks.hook_index_lease4_server_decline_,
|
HooksManager::callCallouts(Hooks.hook_index_lease4_server_decline_,
|
||||||
*callout_handle);
|
*callout_handle);
|
||||||
|
|
||||||
// Check if callouts decided to skip the next processing step.
|
|
||||||
// If any of them did, we will drop the packet.
|
|
||||||
if ((callout_handle->getStatus() == CalloutHandle::NEXT_STEP_SKIP) ||
|
|
||||||
(callout_handle->getStatus() == CalloutHandle::NEXT_STEP_DROP)) {
|
|
||||||
LOG_DEBUG(hooks_logger, DBGLVL_PKT_HANDLING, DHCP4_HOOK_SERVER_DECLINE_SKIP)
|
|
||||||
.arg(query->getLabel()).arg(lease->addr_.toText());
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
*/
|
|
||||||
|
|
||||||
LOG_INFO(lease4_logger, DHCP4_SERVER_INITIATED_DECLINE)
|
|
||||||
.arg(lease->addr_.toText())
|
|
||||||
.arg(lease->valid_lft_);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
@@ -4092,7 +4075,6 @@ Dhcpv4Srv::serverDeclineNoThrow(hooks::CalloutHandlePtr& callout_handle, Pkt4Ptr
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
Pkt4Ptr
|
Pkt4Ptr
|
||||||
Dhcpv4Srv::processInform(Pkt4Ptr& inform, AllocEngine::ClientContext4Ptr& context) {
|
Dhcpv4Srv::processInform(Pkt4Ptr& inform, AllocEngine::ClientContext4Ptr& context) {
|
||||||
// server-id is supposed to be forbidden (as is requested address)
|
// server-id is supposed to be forbidden (as is requested address)
|
||||||
|
@@ -58,6 +58,7 @@ TEST_F(Dhcpv4SrvTest, Hooks) {
|
|||||||
int hook_index_leases4_committed = -1;
|
int hook_index_leases4_committed = -1;
|
||||||
int hook_index_host4_identifier = -1;
|
int hook_index_host4_identifier = -1;
|
||||||
int hook_index_lease4_offer = -1;
|
int hook_index_lease4_offer = -1;
|
||||||
|
int hook_index_lease4_server_decline = -1;
|
||||||
|
|
||||||
// check if appropriate indexes are set
|
// check if appropriate indexes are set
|
||||||
EXPECT_NO_THROW(hook_index_dhcp4_srv_configured = ServerHooks::getServerHooks()
|
EXPECT_NO_THROW(hook_index_dhcp4_srv_configured = ServerHooks::getServerHooks()
|
||||||
@@ -84,6 +85,8 @@ TEST_F(Dhcpv4SrvTest, Hooks) {
|
|||||||
.getIndex("host4_identifier"));
|
.getIndex("host4_identifier"));
|
||||||
EXPECT_NO_THROW(hook_index_lease4_offer = ServerHooks::getServerHooks()
|
EXPECT_NO_THROW(hook_index_lease4_offer = ServerHooks::getServerHooks()
|
||||||
.getIndex("lease4_offer"));
|
.getIndex("lease4_offer"));
|
||||||
|
EXPECT_NO_THROW(hook_index_lease4_server_decline = ServerHooks::getServerHooks()
|
||||||
|
.getIndex("lease4_server_decline"));
|
||||||
|
|
||||||
EXPECT_TRUE(hook_index_dhcp4_srv_configured > 0);
|
EXPECT_TRUE(hook_index_dhcp4_srv_configured > 0);
|
||||||
EXPECT_TRUE(hook_index_buffer4_receive > 0);
|
EXPECT_TRUE(hook_index_buffer4_receive > 0);
|
||||||
@@ -97,6 +100,7 @@ TEST_F(Dhcpv4SrvTest, Hooks) {
|
|||||||
EXPECT_TRUE(hook_index_leases4_committed > 0);
|
EXPECT_TRUE(hook_index_leases4_committed > 0);
|
||||||
EXPECT_TRUE(hook_index_host4_identifier > 0);
|
EXPECT_TRUE(hook_index_host4_identifier > 0);
|
||||||
EXPECT_TRUE(hook_index_lease4_offer > 0);
|
EXPECT_TRUE(hook_index_lease4_offer > 0);
|
||||||
|
EXPECT_TRUE(hook_index_lease4_server_decline > 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
// A dummy MAC address, padded with 0s
|
// A dummy MAC address, padded with 0s
|
||||||
@@ -164,6 +168,7 @@ public:
|
|||||||
HooksManager::preCalloutsLibraryHandle().deregisterAllCallouts("lease4_decline");
|
HooksManager::preCalloutsLibraryHandle().deregisterAllCallouts("lease4_decline");
|
||||||
HooksManager::preCalloutsLibraryHandle().deregisterAllCallouts("host4_identifier");
|
HooksManager::preCalloutsLibraryHandle().deregisterAllCallouts("host4_identifier");
|
||||||
HooksManager::preCalloutsLibraryHandle().deregisterAllCallouts("lease4_offer");
|
HooksManager::preCalloutsLibraryHandle().deregisterAllCallouts("lease4_offer");
|
||||||
|
HooksManager::preCalloutsLibraryHandle().deregisterAllCallouts("lease4_server_decline");
|
||||||
|
|
||||||
HooksManager::setTestMode(false);
|
HooksManager::setTestMode(false);
|
||||||
bool status = HooksManager::unloadLibraries();
|
bool status = HooksManager::unloadLibraries();
|
||||||
@@ -836,6 +841,39 @@ public:
|
|||||||
return (0);
|
return (0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
lease4_offer_park_in_use_callout(CalloutHandle& callout_handle) {
|
||||||
|
callback_name_ = string("lease4_offer");
|
||||||
|
|
||||||
|
callout_handle.getArgument("query4", callback_qry_pkt4_);
|
||||||
|
|
||||||
|
callout_handle.setArgument("offer_address_in_use", true);
|
||||||
|
io_service_->post(std::bind(&HooksDhcpv4SrvTest::pkt4_unpark_callout,
|
||||||
|
callout_handle.getParkingLotHandlePtr(),
|
||||||
|
callback_qry_pkt4_));
|
||||||
|
|
||||||
|
callout_handle.getParkingLotHandlePtr()->reference(callback_qry_pkt4_);
|
||||||
|
callout_handle.setStatus(CalloutHandle::NEXT_STEP_PARK);
|
||||||
|
|
||||||
|
Lease4CollectionPtr leases4;
|
||||||
|
callout_handle.getArgument("leases4", leases4);
|
||||||
|
if (leases4->size() > 0) {
|
||||||
|
callback_lease4_ = leases4->at(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
callout_handle.getArgument("offer_lifetime", callback_offer_lft_);
|
||||||
|
callout_handle.getArgument("old_lease", callback_old_lease_);
|
||||||
|
callback_argument_names_ = callout_handle.getArgumentNames();
|
||||||
|
sort(callback_argument_names_.begin(), callback_argument_names_.end());
|
||||||
|
|
||||||
|
if (callback_qry_pkt4_) {
|
||||||
|
callback_qry_options_copy_ = callback_qry_pkt4_->isCopyRetrievedOptions();
|
||||||
|
}
|
||||||
|
|
||||||
|
return (0);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/// @brief Test callback that stores callout name and passed parameters.
|
/// @brief Test callback that stores callout name and passed parameters.
|
||||||
///
|
///
|
||||||
/// @param callout_handle handle passed by the hooks framework
|
/// @param callout_handle handle passed by the hooks framework
|
||||||
@@ -868,6 +906,29 @@ public:
|
|||||||
return (0);
|
return (0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// @brief Test callback that stores callout name and passed parameters.
|
||||||
|
///
|
||||||
|
/// @param callout_handle handle passed by the hooks framework
|
||||||
|
/// @return always 0
|
||||||
|
static int
|
||||||
|
lease4_server_decline_callout(CalloutHandle& callout_handle) {
|
||||||
|
callback_name_ = string("lease4_server_decline");
|
||||||
|
callout_handle.getArgument("query4", callback_qry_pkt4_);
|
||||||
|
|
||||||
|
Lease4Ptr lease4;
|
||||||
|
callout_handle.getArgument("lease4", lease4);
|
||||||
|
callback_lease4_ = lease4;
|
||||||
|
|
||||||
|
callback_argument_names_ = callout_handle.getArgumentNames();
|
||||||
|
sort(callback_argument_names_.begin(), callback_argument_names_.end());
|
||||||
|
|
||||||
|
if (callback_qry_pkt4_) {
|
||||||
|
callback_qry_options_copy_ = callback_qry_pkt4_->isCopyRetrievedOptions();
|
||||||
|
}
|
||||||
|
|
||||||
|
return (0);
|
||||||
|
}
|
||||||
|
|
||||||
/// @brief Test callback which asks the server to unpark the packet.
|
/// @brief Test callback which asks the server to unpark the packet.
|
||||||
///
|
///
|
||||||
/// This can be used with hook points: leases4_committed, lease4_offer.
|
/// This can be used with hook points: leases4_committed, lease4_offer.
|
||||||
@@ -3881,4 +3942,82 @@ TEST_F(HooksDhcpv4SrvTest, lease4OfferParkedPacketLimit) {
|
|||||||
EXPECT_EQ(1, getStatistic("pkt4-receive-drop"));
|
EXPECT_EQ(1, getStatistic("pkt4-receive-drop"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// This test verifies that a lease4_offer callout that marks a
|
||||||
|
// lease as in-use and unparks the query, causes the offer to be
|
||||||
|
// discarded, and Dhcpv4Srv::serverDecline() to be invoked. This should,
|
||||||
|
// in turn, cause the lease to be declined in the lease store and the
|
||||||
|
// callout for lease4_server_decline to be called.
|
||||||
|
TEST_F(HooksDhcpv4SrvTest, lease4OfferDiscoverDecline) {
|
||||||
|
IfaceMgrTestConfig test_config(true);
|
||||||
|
IfaceMgr::instance().openSockets4();
|
||||||
|
|
||||||
|
// Install lease4_offer callout that will mark lease as in-use and unpark
|
||||||
|
ASSERT_NO_THROW(HooksManager::preCalloutsLibraryHandle().registerCallout(
|
||||||
|
"lease4_offer", lease4_offer_park_in_use_callout));
|
||||||
|
|
||||||
|
// Install lease4_server_decline callout
|
||||||
|
ASSERT_NO_THROW(HooksManager::preCalloutsLibraryHandle().registerCallout(
|
||||||
|
"lease4_server_decline", lease4_server_decline_callout));
|
||||||
|
|
||||||
|
// Make sure there's no existing lease.
|
||||||
|
IOAddress expected_address("192.0.2.100");
|
||||||
|
ASSERT_FALSE(LeaseMgrFactory::instance().getLease4(expected_address));
|
||||||
|
|
||||||
|
// Generate a DISCOVER.
|
||||||
|
Dhcp4Client client(Dhcp4Client::SELECTING);
|
||||||
|
client.setIfaceName("eth1");
|
||||||
|
client.setIfaceIndex(ETH1_INDEX);
|
||||||
|
ASSERT_NO_THROW(client.doDiscover());
|
||||||
|
|
||||||
|
// Check that the callback called is indeed the one we installed
|
||||||
|
EXPECT_EQ("lease4_offer", callback_name_);
|
||||||
|
|
||||||
|
// Check if all expected parameters were really received
|
||||||
|
vector<string> expected_argument_names;
|
||||||
|
expected_argument_names.push_back("query4");
|
||||||
|
expected_argument_names.push_back("leases4");
|
||||||
|
expected_argument_names.push_back("offer_lifetime");
|
||||||
|
expected_argument_names.push_back("old_lease");
|
||||||
|
expected_argument_names.push_back("offer_address_in_use");
|
||||||
|
|
||||||
|
sort(expected_argument_names.begin(), expected_argument_names.end());
|
||||||
|
EXPECT_TRUE(callback_argument_names_ == expected_argument_names);
|
||||||
|
|
||||||
|
// Declined lease should be returned.
|
||||||
|
ASSERT_TRUE(callback_lease4_);
|
||||||
|
EXPECT_EQ(expected_address, callback_lease4_->addr_);
|
||||||
|
|
||||||
|
// Since the callout set offer_address_in_use flag to true the offer should
|
||||||
|
// have been discarded. Make sure that we did not receive a repsonse.
|
||||||
|
ASSERT_FALSE(client.getContext().response_);
|
||||||
|
|
||||||
|
// Clear static buffers
|
||||||
|
resetCalloutBuffers();
|
||||||
|
|
||||||
|
// Polling the IOService should unpark the packet invoking the unpark lambda
|
||||||
|
// which should invoke Dhcp4Srv::serverDecline(). This should decline the
|
||||||
|
// lease in the db and then invoke lease4_server_decline callback.
|
||||||
|
ASSERT_NO_THROW(io_service_->poll());
|
||||||
|
|
||||||
|
// The lease should be in the lease store and in the DECLINED state.
|
||||||
|
Lease4Ptr declined_lease = LeaseMgrFactory::instance().getLease4(callback_lease4_->addr_);
|
||||||
|
ASSERT_TRUE(declined_lease);
|
||||||
|
EXPECT_EQ(declined_lease->state_, Lease::STATE_DECLINED);
|
||||||
|
|
||||||
|
// Check that we called lease4_server_decline callback.
|
||||||
|
EXPECT_EQ("lease4_server_decline", callback_name_);
|
||||||
|
|
||||||
|
// Check if all expected parameters were really received
|
||||||
|
expected_argument_names.clear();
|
||||||
|
expected_argument_names.push_back("query4");
|
||||||
|
expected_argument_names.push_back("lease4");
|
||||||
|
|
||||||
|
sort(expected_argument_names.begin(), expected_argument_names.end());
|
||||||
|
EXPECT_TRUE(callback_argument_names_ == expected_argument_names);
|
||||||
|
|
||||||
|
// Declined lease should be returned.
|
||||||
|
ASSERT_TRUE(callback_lease4_);
|
||||||
|
EXPECT_EQ(expected_address, callback_lease4_->addr_);
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
|
@@ -115,6 +115,28 @@ int leases4_committed(CalloutHandle& handle) {
|
|||||||
return (0);
|
return (0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// @brief lease4_server_decline callout implementation.
|
||||||
|
///
|
||||||
|
/// @param handle callout handle.
|
||||||
|
int lease4_server_decline(CalloutHandle& handle) {
|
||||||
|
CalloutHandle::CalloutNextStep status = handle.getStatus();
|
||||||
|
if (status == CalloutHandle::NEXT_STEP_DROP ||
|
||||||
|
status == CalloutHandle::NEXT_STEP_SKIP) {
|
||||||
|
return (0);
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
impl->lease4ServerDecline(handle);
|
||||||
|
} catch (const std::exception& ex) {
|
||||||
|
LOG_ERROR(ha_logger, HA_LEASE4_SERVER_DECLINE_FAILED)
|
||||||
|
.arg(ex.what());
|
||||||
|
return (1);
|
||||||
|
}
|
||||||
|
|
||||||
|
return (0);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/// @brief dhcp6_srv_configured callout implementation.
|
/// @brief dhcp6_srv_configured callout implementation.
|
||||||
///
|
///
|
||||||
/// @param handle callout handle.
|
/// @param handle callout handle.
|
||||||
|
@@ -185,6 +185,41 @@ HAImpl::leases4Committed(CalloutHandle& callout_handle) {
|
|||||||
callout_handle.setStatus(CalloutHandle::NEXT_STEP_PARK);
|
callout_handle.setStatus(CalloutHandle::NEXT_STEP_PARK);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
HAImpl::lease4ServerDecline(CalloutHandle& callout_handle) {
|
||||||
|
// If the hook library is configured to not send lease updates to the
|
||||||
|
// partner, there is nothing to do because this whole callout is
|
||||||
|
// currently about sending lease updates.
|
||||||
|
if (!config_->amSendingLeaseUpdates()) {
|
||||||
|
// No need to log it, because it was already logged when configuration
|
||||||
|
// was applied.
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Pkt4Ptr query4;
|
||||||
|
Lease4Ptr lease4;
|
||||||
|
|
||||||
|
// Get all arguments available for the lease4_server_decline hook point.
|
||||||
|
// If any of these arguments is not available this is a programmatic
|
||||||
|
// error. An exception will be thrown which will be caught by the
|
||||||
|
// caller and logged.
|
||||||
|
callout_handle.getArgument("query4", query4);
|
||||||
|
callout_handle.getArgument("lease4", lease4);
|
||||||
|
|
||||||
|
// Get the parking lot for this hook point. We're going to remember this
|
||||||
|
// pointer until we unpark the packet.
|
||||||
|
ParkingLotHandlePtr parking_lot = callout_handle.getParkingLotHandlePtr();
|
||||||
|
|
||||||
|
// Asynchronously send lease updates. In some cases no updates will be sent,
|
||||||
|
// e.g. when this server is in the partner-down state and there are no backup
|
||||||
|
// servers. In those cases we simply return without parking the DHCP query.
|
||||||
|
// The response will be sent to the client immediately.
|
||||||
|
service_->asyncSendLeaseUpdate(query4, lease4, parking_lot);
|
||||||
|
|
||||||
|
callout_handle.setStatus(CalloutHandle::NEXT_STEP_CONTINUE);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
HAImpl::buffer6Receive(hooks::CalloutHandle& callout_handle) {
|
HAImpl::buffer6Receive(hooks::CalloutHandle& callout_handle) {
|
||||||
Pkt6Ptr query6;
|
Pkt6Ptr query6;
|
||||||
|
@@ -106,6 +106,11 @@ public:
|
|||||||
/// @param callout_handle Callout handle provided to the callout.
|
/// @param callout_handle Callout handle provided to the callout.
|
||||||
void leases4Committed(hooks::CalloutHandle& callout_handle);
|
void leases4Committed(hooks::CalloutHandle& callout_handle);
|
||||||
|
|
||||||
|
/// @brief Implementation of the "lease4_server_decline" callout.
|
||||||
|
///
|
||||||
|
/// @param callout_handle Callout handle provided to the callout.
|
||||||
|
void lease4ServerDecline(hooks::CalloutHandle& callout_handle);
|
||||||
|
|
||||||
/// @brief Implementation of the "buffer6_receive" callout.
|
/// @brief Implementation of the "buffer6_receive" callout.
|
||||||
///
|
///
|
||||||
/// This callout uses HA service to check if the query should be processed
|
/// This callout uses HA service to check if the query should be processed
|
||||||
|
@@ -49,6 +49,7 @@ extern const isc::log::MessageID HA_INIT_OK = "HA_INIT_OK";
|
|||||||
extern const isc::log::MessageID HA_INVALID_PARTNER_STATE_COMMUNICATION_RECOVERY = "HA_INVALID_PARTNER_STATE_COMMUNICATION_RECOVERY";
|
extern const isc::log::MessageID HA_INVALID_PARTNER_STATE_COMMUNICATION_RECOVERY = "HA_INVALID_PARTNER_STATE_COMMUNICATION_RECOVERY";
|
||||||
extern const isc::log::MessageID HA_INVALID_PARTNER_STATE_HOT_STANDBY = "HA_INVALID_PARTNER_STATE_HOT_STANDBY";
|
extern const isc::log::MessageID HA_INVALID_PARTNER_STATE_HOT_STANDBY = "HA_INVALID_PARTNER_STATE_HOT_STANDBY";
|
||||||
extern const isc::log::MessageID HA_INVALID_PARTNER_STATE_LOAD_BALANCING = "HA_INVALID_PARTNER_STATE_LOAD_BALANCING";
|
extern const isc::log::MessageID HA_INVALID_PARTNER_STATE_LOAD_BALANCING = "HA_INVALID_PARTNER_STATE_LOAD_BALANCING";
|
||||||
|
extern const isc::log::MessageID HA_LEASE4_SERVER_DECLINE_FAILED = "HA_LEASE4_SERVER_DECLINE_FAILED";
|
||||||
extern const isc::log::MessageID HA_LEASES4_COMMITTED_FAILED = "HA_LEASES4_COMMITTED_FAILED";
|
extern const isc::log::MessageID HA_LEASES4_COMMITTED_FAILED = "HA_LEASES4_COMMITTED_FAILED";
|
||||||
extern const isc::log::MessageID HA_LEASES4_COMMITTED_NOTHING_TO_UPDATE = "HA_LEASES4_COMMITTED_NOTHING_TO_UPDATE";
|
extern const isc::log::MessageID HA_LEASES4_COMMITTED_NOTHING_TO_UPDATE = "HA_LEASES4_COMMITTED_NOTHING_TO_UPDATE";
|
||||||
extern const isc::log::MessageID HA_LEASES6_COMMITTED_FAILED = "HA_LEASES6_COMMITTED_FAILED";
|
extern const isc::log::MessageID HA_LEASES6_COMMITTED_FAILED = "HA_LEASES6_COMMITTED_FAILED";
|
||||||
@@ -157,6 +158,7 @@ const char* values[] = {
|
|||||||
"HA_INVALID_PARTNER_STATE_COMMUNICATION_RECOVERY", "%1: partner is in the communication-recovery state unexpectedly",
|
"HA_INVALID_PARTNER_STATE_COMMUNICATION_RECOVERY", "%1: partner is in the communication-recovery state unexpectedly",
|
||||||
"HA_INVALID_PARTNER_STATE_HOT_STANDBY", "%1: partner is in the hot-standby state unexpectedly",
|
"HA_INVALID_PARTNER_STATE_HOT_STANDBY", "%1: partner is in the hot-standby state unexpectedly",
|
||||||
"HA_INVALID_PARTNER_STATE_LOAD_BALANCING", "%1: partner is in the load-balancing state unexpectedly",
|
"HA_INVALID_PARTNER_STATE_LOAD_BALANCING", "%1: partner is in the load-balancing state unexpectedly",
|
||||||
|
"HA_LEASE4_SERVER_DECLINE_FAILED", "lease4_server_decline callout failed: %1",
|
||||||
"HA_LEASES4_COMMITTED_FAILED", "leases4_committed callout failed: %1",
|
"HA_LEASES4_COMMITTED_FAILED", "leases4_committed callout failed: %1",
|
||||||
"HA_LEASES4_COMMITTED_NOTHING_TO_UPDATE", "%1: leases4_committed callout was invoked without any leases",
|
"HA_LEASES4_COMMITTED_NOTHING_TO_UPDATE", "%1: leases4_committed callout was invoked without any leases",
|
||||||
"HA_LEASES6_COMMITTED_FAILED", "leases6_committed callout failed: %1",
|
"HA_LEASES6_COMMITTED_FAILED", "leases6_committed callout failed: %1",
|
||||||
|
@@ -50,6 +50,7 @@ extern const isc::log::MessageID HA_INIT_OK;
|
|||||||
extern const isc::log::MessageID HA_INVALID_PARTNER_STATE_COMMUNICATION_RECOVERY;
|
extern const isc::log::MessageID HA_INVALID_PARTNER_STATE_COMMUNICATION_RECOVERY;
|
||||||
extern const isc::log::MessageID HA_INVALID_PARTNER_STATE_HOT_STANDBY;
|
extern const isc::log::MessageID HA_INVALID_PARTNER_STATE_HOT_STANDBY;
|
||||||
extern const isc::log::MessageID HA_INVALID_PARTNER_STATE_LOAD_BALANCING;
|
extern const isc::log::MessageID HA_INVALID_PARTNER_STATE_LOAD_BALANCING;
|
||||||
|
extern const isc::log::MessageID HA_LEASE4_SERVER_DECLINE_FAILED;
|
||||||
extern const isc::log::MessageID HA_LEASES4_COMMITTED_FAILED;
|
extern const isc::log::MessageID HA_LEASES4_COMMITTED_FAILED;
|
||||||
extern const isc::log::MessageID HA_LEASES4_COMMITTED_NOTHING_TO_UPDATE;
|
extern const isc::log::MessageID HA_LEASES4_COMMITTED_NOTHING_TO_UPDATE;
|
||||||
extern const isc::log::MessageID HA_LEASES6_COMMITTED_FAILED;
|
extern const isc::log::MessageID HA_LEASES6_COMMITTED_FAILED;
|
||||||
|
@@ -631,3 +631,10 @@ This informational message is issued when the server has been restarted after
|
|||||||
correcting the clock skew. The partner server is still in the terminated
|
correcting the clock skew. The partner server is still in the terminated
|
||||||
state. The partner must be restarted before the server can synchronize the
|
state. The partner must be restarted before the server can synchronize the
|
||||||
database and start normal operation.
|
database and start normal operation.
|
||||||
|
|
||||||
|
% HA_LEASE4_SERVER_DECLINE_FAILED lease4_server_decline callout failed: %1
|
||||||
|
This error message is issued when the callout for the lease4_server_declinehook
|
||||||
|
point failed. This includes unexpected errors like wrong arguments provided to
|
||||||
|
the callout by the DHCP server (unlikely internal server error).
|
||||||
|
The argument contains a reason for the error.
|
||||||
|
|
||||||
|
@@ -1243,6 +1243,55 @@ HAService::asyncSendLeaseUpdates(const dhcp::Pkt4Ptr& query,
|
|||||||
return (sent_num);
|
return (sent_num);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
size_t
|
||||||
|
HAService::asyncSendLeaseUpdate(const dhcp::Pkt4Ptr& query,
|
||||||
|
const dhcp::Lease4Ptr& lease,
|
||||||
|
const hooks::ParkingLotHandlePtr& parking_lot) {
|
||||||
|
|
||||||
|
// Get configurations of the peers. Exclude this instance.
|
||||||
|
HAConfig::PeerConfigMap peers_configs = config_->getOtherServersConfig();
|
||||||
|
|
||||||
|
size_t sent_num = 0;
|
||||||
|
|
||||||
|
// Schedule sending lease updates to each peer.
|
||||||
|
for (auto p = peers_configs.begin(); p != peers_configs.end(); ++p) {
|
||||||
|
HAConfig::PeerConfigPtr conf = p->second;
|
||||||
|
|
||||||
|
// Check if the lease updates should be queued. This is the case when the
|
||||||
|
// server is in the communication-recovery state. Queued lease updates may
|
||||||
|
// be sent when the communication is re-established.
|
||||||
|
if (shouldQueueLeaseUpdates(conf)) {
|
||||||
|
lease_update_backlog_.push(LeaseUpdateBacklog::ADD, lease);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check if the lease update should be sent to the server. If we're in
|
||||||
|
// the partner-down state we don't send lease updates to the partner.
|
||||||
|
if (!shouldSendLeaseUpdates(conf)) {
|
||||||
|
// If we decide to not send the lease updates to an active partner, we
|
||||||
|
// should make a record of it in the communication state. The partner
|
||||||
|
// can check if there were any unsent lease updates when he determines
|
||||||
|
// whether it should synchronize its database or not when it recovers
|
||||||
|
// from the partner-down state.
|
||||||
|
if (conf->getRole() != HAConfig::PeerConfig::BACKUP) {
|
||||||
|
communication_state_->increaseUnsentUpdateCount();
|
||||||
|
}
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
asyncSendLeaseUpdate(query, conf, CommandCreator::createLease4Update(*lease), parking_lot);
|
||||||
|
|
||||||
|
// If we're contacting a backup server from which we don't expect a
|
||||||
|
// response prior to responding to the DHCP client we don't count
|
||||||
|
// it.
|
||||||
|
if ((config_->amWaitingBackupAck() || (conf->getRole() != HAConfig::PeerConfig::BACKUP))) {
|
||||||
|
++sent_num;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return (sent_num);
|
||||||
|
}
|
||||||
|
|
||||||
size_t
|
size_t
|
||||||
HAService::asyncSendLeaseUpdates(const dhcp::Pkt6Ptr& query,
|
HAService::asyncSendLeaseUpdates(const dhcp::Pkt6Ptr& query,
|
||||||
const dhcp::Lease6CollectionPtr& leases,
|
const dhcp::Lease6CollectionPtr& leases,
|
||||||
@@ -1324,7 +1373,9 @@ HAService::leaseUpdateCompleteInternal(QueryPtrType& query,
|
|||||||
// If there are no more pending requests for this query, let's unpark
|
// If there are no more pending requests for this query, let's unpark
|
||||||
// the DHCP packet.
|
// the DHCP packet.
|
||||||
if (it == pending_requests_.end() || (--pending_requests_[query] <= 0)) {
|
if (it == pending_requests_.end() || (--pending_requests_[query] <= 0)) {
|
||||||
|
if (parking_lot) {
|
||||||
parking_lot->unpark(query);
|
parking_lot->unpark(query);
|
||||||
|
}
|
||||||
|
|
||||||
// If we have unparked the packet we can clear pending requests for
|
// If we have unparked the packet we can clear pending requests for
|
||||||
// this query.
|
// this query.
|
||||||
@@ -1481,8 +1532,10 @@ HAService::asyncSendLeaseUpdate(const QueryPtrType& query,
|
|||||||
// a backup server and the lease update was unsuccessful. In such
|
// a backup server and the lease update was unsuccessful. In such
|
||||||
// case the DHCP exchange fails.
|
// case the DHCP exchange fails.
|
||||||
if (!lease_update_success) {
|
if (!lease_update_success) {
|
||||||
|
if (parking_lot) {
|
||||||
parking_lot->drop(query);
|
parking_lot->drop(query);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
// This was a response from the backup server and we're configured to
|
// This was a response from the backup server and we're configured to
|
||||||
// not wait for their acknowledgments, so there is nothing more to do.
|
// not wait for their acknowledgments, so there is nothing more to do.
|
||||||
|
@@ -580,6 +580,10 @@ public:
|
|||||||
const dhcp::Lease4CollectionPtr& deleted_leases,
|
const dhcp::Lease4CollectionPtr& deleted_leases,
|
||||||
const hooks::ParkingLotHandlePtr& parking_lot);
|
const hooks::ParkingLotHandlePtr& parking_lot);
|
||||||
|
|
||||||
|
size_t asyncSendLeaseUpdate(const dhcp::Pkt4Ptr& query,
|
||||||
|
const dhcp::Lease4Ptr& lease,
|
||||||
|
const hooks::ParkingLotHandlePtr& parking_lot);
|
||||||
|
|
||||||
/// @brief Schedules asynchronous IPv6 lease updates.
|
/// @brief Schedules asynchronous IPv6 lease updates.
|
||||||
///
|
///
|
||||||
/// This method schedules asynchronous IPv6 lease updates as a result of the
|
/// This method schedules asynchronous IPv6 lease updates as a result of the
|
||||||
|
Reference in New Issue
Block a user