23using namespace std::chrono;
25namespace ph = std::placeholders;
41 uint32_t reply_timeout)
49 config->setMinPingRequests(min_echos);
50 config->setReplyTimeout(reply_timeout);
51 config->setPingChannelThreads(num_threads);
80 local_cache->setGlobalConfig(
config_cache_->getGlobalConfig());
81 auto const& subnets = server_config->getCfgSubnets4()->getAll();
82 for (
auto const& subnet : (*subnets)) {
83 auto user_context = subnet->getContext();
84 local_cache->parseAndCacheConfig(subnet->getID(), user_context);
103 auto subnet_id = lease->subnet_id_;
108 auto const& subnet = server_config->getCfgSubnets4()->getBySubnetId(subnet_id);
112 "no subnet for id: " << subnet_id
113 <<
", for lease address: " << lease->addr_);
117 if (subnet->getModificationTime() >
config_cache_->getLastFlushTime()) {
126 auto user_context = subnet->getContext();
129 }
catch (
const std::exception& ex) {
162 .arg(query->getLabel());
165 store_->addContext(lease, query,
config->getMinPingRequests(),
166 config->getReplyTimeout(), parking_lot);
184 return (
store_->getNextToSend());
196 store_->updateContext(context);
212 << echo->getType() <<
" is not an ECHO_REQUEST");
219 " no context found for: " << echo->getDestination());
228 context->beginWaitingForReply();
229 store_->updateContext(context);
234 }
catch (
const std::exception& ex) {
251 switch (reply->getType()) {
265 }
catch (
const std::exception& ex) {
278 .arg(echo_reply->getSource())
279 .arg(echo_reply->getId())
280 .arg(echo_reply->getSequence());
286 .arg(echo_reply->getSource())
287 .arg(echo_reply->getId())
288 .arg(echo_reply->getSequence());
291 store_->updateContext(context);
297 auto parking_lot = context->getParkingLot();
299 auto query = context->getQuery();
300 auto callout_handle = query->getCalloutHandle();
301 callout_handle->setArgument(
"offer_address_in_use",
true);
302 parking_lot->unpark(query);
306 store_->deleteContext(context);
313 auto payload = unreachable->getPayload();
321 .arg(embedded_echo->getDestination())
322 .arg(embedded_echo->getId())
323 .arg(embedded_echo->getSequence());
329 .arg(embedded_echo->getDestination())
330 .arg(embedded_echo->getId())
331 .arg(embedded_echo->getSequence());
340 store_->updateContext(context);
344 .arg(context->getTarget())
345 .arg(context->getQuery()->getLabel());
351 auto parking_lot = context->getParkingLot();
353 auto query = context->getQuery();
354 auto callout_handle = query->getCalloutHandle();
355 callout_handle->setArgument(
"offer_address_in_use",
false);
356 parking_lot->unpark(context->getQuery());
360 store_->deleteContext(context);
376 auto expired_pings =
store_->getExpiredSince(since);
377 size_t more_pings = 0;
378 for (
auto const& context : *(expired_pings)) {
381 .arg(context->getTarget())
382 .arg(context->getEchosSent())
383 .arg(context->getMinEchos())
384 .arg(context->getReplyTimeout());
386 if (context->getEchosSent() < context->getMinEchos()) {
402 .arg(context->getTarget())
403 .arg(context->getEchosSent() + 1)
404 .arg(context->getMinEchos());
406 context->beginWaitingToSend();
407 store_->updateContext(context);
436 auto timeout = duration_cast<milliseconds>(context->getNextExpiry() - now);
438 timeout = (timeout > milliseconds(2) ? timeout : milliseconds(2));
499 if (
store_->getContextByAddress(lease->addr_)) {
503 .arg(query->getLabel());
508 if (host && (host->getIPv4Reservation() == lease->addr_)) {
516 if (old_lease && (old_lease->addr_ == lease->addr_)) {
517 if (old_lease->belongsToClient(lease->hwaddr_, lease->client_id_)) {
518 if (!old_lease->expired() ||
519 ((time(0) - old_lease->cltt_) <
config->getPingClttSecs())) {
598 auto use_threads = (
config->getPingChannelThreads() ?
config->getPingChannelThreads()
608 }
catch (
const std::exception& ex) {
623 }
catch (
const std::exception& ex) {
637 this, ph::_1, ph::_2),
658 }
catch (
const std::exception& ex) {
680 }
catch (
const std::exception& ex) {
701 }
catch (
const std::exception& ex) {
788 auto contexts =
store_->getAll();
789 for (
auto const& context : *contexts) {
793 auto parking_lot = context->getParkingLot();
795 parking_lot->drop(context->getQuery());
CalloutNextStep
Specifies allowed next steps.
A generic exception that is thrown if a parameter given to a method is considered invalid in that con...
virtual const char * what() const
Returns a C-style character string of the cause of the exception.
A generic exception that is thrown if a function is called in a prohibited way.
Exception thrown when a worker thread is trying to stop or pause the respective thread pool (which wo...
A generic exception that is thrown when an unexpected error condition occurs.
The IOService class is a wrapper for the ASIO io_context class.
The IntervalTimer class is a wrapper for the ASIO boost::asio::deadline_timer class.
Implements a pausable pool of IOService driven threads.
static CfgMgr & instance()
returns a single instance of Configuration Manager
SrvConfigPtr getCurrentCfg()
Returns a pointer to the current configuration.
To be removed. Please use ConfigError instead.
@ NEXT_STEP_PARK
park the packet
@ NEXT_STEP_CONTINUE
continue normally
@ NEXT_STEP_DROP
drop the packet
ConfigCache stores ping check config per subnet.
static ICMPMsgPtr unpack(const uint8_t *wire_data, size_t length)
Unpacks an ICMP message from the given wire_data.
Provides thread-safe ICMP ECHO REQUEST/ECHO REPLY service.
Houses the Ping check configuration parameters for a single scope (e.g.
virtual void channelShutdown()
Callback passed to PingChannel to invoke when it shuts down.
virtual void expirationTimedOut()
Callback passed to expiration timer to invoke on timeout.
virtual void updateContextToSend(PingContextPtr context)
Callback passed to PingChannel to update a context to SENDING state just before sending.
asiolink::IntervalTimerPtr expiration_timer_
Timer which tracks the next expiration event.
bool isRunning()
Indicates if the thread pool is running.
void checkPermissions()
Check if the current thread can perform thread pool state transition.
void configure(data::ConstElementPtr params)
Configure the PingCheckMgr.
asiolink::IoServiceThreadPoolPtr thread_pool_
Thread pool used when running multi-threaded.
void cancelExpirationTimerInternal()
Cancels the expiration timer.
TimeStamp next_expiry_
TimeStamp of the next expiration event.
virtual void setNextExpirationInternal()
Updates the expiration timer.
void stopService(bool finish_free=false)
Shuts down the manager's channel, flushes the store.
void resume()
Resume PingChannel operations.
void startService(dhcp::NetworkStatePtr network_state)
Performs a deferred start by posting an invocation of start() to the given IOService.
const PingCheckConfigPtr getScopedConfig(dhcp::Lease4Ptr &lease)
Fetches the current, scoped configuration parameters.
bool isStopped()
Indicates if the thread pool is stopped.
virtual PingChannelPtr createChannel(asiolink::IOServicePtr io_service)
Creates a ping channel instance.
const PingCheckConfigPtr getGlobalConfig() const
Fetches the current, global configuration parameters.
TimeStamp getNextExpiry()
Fetches the time at which expiration timer will next expire.
void handleTargetUnreachable(const ICMPMsgPtr &unreachable)
Process an UNREACHABLE message.
void startPing(dhcp::Lease4Ptr &lease, dhcp::Pkt4Ptr &query, hooks::ParkingLotHandlePtr &parking_lot, const PingCheckConfigPtr &config)
Initiates a ping check for a given lease and its associated DHCPDISCOVER packet.
void finishFree(const PingContextPtr &context)
Processes a context whose address has been deemed free to use.
const boost::scoped_ptr< std::mutex > mutex_
The mutex used to protect internal state.
virtual size_t processExpiredSince(const TimeStamp &since=PingContext::now())
Performs expiration processing for contexts whose WAITING_FOR_REPLY states expired prior to a given p...
bool checkSuspendedInternal()
Checks if operations are currently suspended due to NetworkState.
void pause()
Pause PingChannel operations.
virtual ~PingCheckMgr()
Destructor.
bool checkSuspended()
Checks if operations are currently suspended due to NetworkState.
PingCheckMgr()
Constructor.
void flush(bool finish_free=false)
Flushes the ping context store.
PingChannelPtr channel_
Channel that conducts ICMP messaging.
bool suspended_
Indicates whether or not operations have been suspended.
void cancelExpirationTimer()
Cancels the expiration timer (thread safe).
void start()
Start PingChannel operations.
void updateSubnetConfig(dhcp::SrvConfigPtr server_config)
Update the cache of subnet ping check configurations.
virtual void replyReceived(const ICMPMsgPtr &reply)
Callback passed to PingChannel to invoke when an ICMP reply has been received.
PingContextStorePtr store_
In-memory store of PingContexts.
virtual hooks::CalloutHandle::CalloutNextStep shouldPing(dhcp::Lease4Ptr &lease, dhcp::Pkt4Ptr &query, dhcp::Lease4Ptr &old_lease, dhcp::ConstHostPtr host, const PingCheckConfigPtr &config)
Determines whether or not a lease should be ping checked.
virtual PingContextPtr nextToSend()
Callback passed to PingChannel to use to retrieve the next context with address to check.
void startSingleThreaded()
Start single-threaded PingChannel operations.
void stop()
Stop PingChannel operations.
ConfigCachePtr config_cache_
Warehouses parsed global and subnet configuration.
isc::asiolink::IOServicePtr io_service_
The hook I/O service.
dhcp::NetworkStatePtr network_state_
Tracks whether or not the server is processing DHCP packets.
void handleEchoReply(const ICMPMsgPtr &echo_reply)
Process an ECHO REPLY message.
virtual void setNextExpiration()
Updates the expiration timer (thread safe).
void doNextEcho(const PingContextPtr &context)
Position a context to do another ping test.
virtual void sendCompleted(const ICMPMsgPtr &echo, bool send_failed)
Callback passed to PingChannel to invoke when an ECHO REQUEST send has completed.
bool isPaused()
Indicates if the thread pool is paused.
Maintains an in-memory store of PingContexts.
static const TimeStamp & EMPTY_TIME()
Fetches an empty timestamp.
static TimeStamp now()
Fetches the current timestamp (UTC/milliseconds precision)
static MultiThreadingMgr & instance()
Returns a single instance of Multi Threading Manager.
void removeCriticalSectionCallbacks(const std::string &name)
Removes the set of callbacks associated with a given name from the list of CriticalSection callbacks.
void addCriticalSectionCallbacks(const std::string &name, const CSCallbackSet::Callback &check_cb, const CSCallbackSet::Callback &entry_cb, const CSCallbackSet::Callback &exit_cb)
Adds a set of callbacks to the list of CriticalSection callbacks.
#define isc_throw(type, stream)
A shortcut macro to insert known values into exception arguments.
#define LOG_ERROR(LOGGER, MESSAGE)
Macro to conveniently test error output and log it.
#define LOG_INFO(LOGGER, MESSAGE)
Macro to conveniently test info output and log it.
#define LOG_DEBUG(LOGGER, LEVEL, MESSAGE)
Macro to conveniently test debug output and log it.
boost::shared_ptr< IOService > IOServicePtr
Defines a smart pointer to an IOService instance.
boost::shared_ptr< const Element > ConstElementPtr
boost::shared_ptr< Pkt4 > Pkt4Ptr
A pointer to Pkt4 object.
boost::shared_ptr< SrvConfig > SrvConfigPtr
Non-const pointer to the SrvConfig.
boost::shared_ptr< NetworkState > NetworkStatePtr
Pointer to the NetworkState object.
boost::shared_ptr< const Host > ConstHostPtr
Const pointer to the Host object.
boost::shared_ptr< Lease4 > Lease4Ptr
Pointer to a Lease4 structure.
boost::shared_ptr< ParkingLotHandle > ParkingLotHandlePtr
Pointer to the parking lot handle.
const int DBGLVL_TRACE_BASIC
Trace basic operations.
const int DBGLVL_TRACE_DETAIL
Trace detailed operations.
boost::shared_ptr< PingCheckConfig > PingCheckConfigPtr
Defines a shared pointer to a PingCheckConfig.
boost::shared_ptr< ICMPMsg > ICMPMsgPtr
Shared pointer type for ICMPMsg.
isc::log::Logger ping_check_logger("ping-check-hooks")
std::chrono::time_point< std::chrono::system_clock > TimeStamp
Specifies the type for time stamps.
boost::shared_ptr< ConfigCache > ConfigCachePtr
Defines a shared pointer to a ConfigCache.
boost::shared_ptr< PingContext > PingContextPtr
Defines a shared pointer to a PingContext.
boost::shared_ptr< PingChannel > PingChannelPtr
Defines a smart pointer to PingChannel.
Defines the logger used by the top-level component of kea-lfc.
const isc::log::MessageID PING_CHECK_MGR_STARTED
const isc::log::MessageID PING_CHECK_MGR_NEXT_ECHO_SCHEDULED
const isc::log::MessageID PING_CHECK_MGR_STARTED_SINGLE_THREADED
const isc::log::MessageID PING_CHECK_DUPLICATE_CHECK
const isc::log::MessageID PING_CHECK_MGR_CHANNEL_DOWN
const isc::log::MessageID PING_CHECK_MGR_RECEIVED_UNREACHABLE_MSG
const isc::log::MessageID PING_CHECK_MGR_RECEIVED_ECHO_REPLY
const isc::log::MessageID PING_CHECK_MGR_RECEIVED_UNEXPECTED_ECHO_REPLY
const isc::log::MessageID PING_CHECK_RESUME_FAILED
const isc::log::MessageID PING_CHECK_MGR_STOPPING
const isc::log::MessageID PING_CHECK_MGR_REPLY_RECEIVED_ERROR
const isc::log::MessageID PING_CHECK_MGR_SEND_COMPLETED_ERROR
const isc::log::MessageID PING_CHECK_MGR_SUBNET_CONFIG_FAILED
const isc::log::MessageID PING_CHECK_MGR_LEASE_FREE_TO_USE
const isc::log::MessageID PING_CHECK_MGR_STOPPED
const isc::log::MessageID PING_CHECK_MGR_REPLY_TIMEOUT_EXPIRED
const isc::log::MessageID PING_CHECK_PAUSE_FAILED
const isc::log::MessageID PING_CHECK_MGR_START_PING_CHECK
const isc::log::MessageID PING_CHECK_MGR_RECEIVED_UNEXPECTED_UNREACHABLE_MSG
const isc::log::MessageID PING_CHECK_PAUSE_PERMISSIONS_FAILED
const isc::log::MessageID PING_CHECK_PAUSE_ILLEGAL
RAII lock object to protect the code in the same scope with a mutex.