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);
192 next = context->getTarget();
195 store_->updateContext(context);
213 << echo->getType() <<
" is not an ECHO_REQUEST");
220 " no context found for: " << echo->getDestination());
229 context->beginWaitingForReply();
230 store_->updateContext(context);
235 }
catch (
const std::exception& ex) {
252 switch (reply->getType()) {
266 }
catch (
const std::exception& ex) {
279 .arg(echo_reply->getSource())
280 .arg(echo_reply->getId())
281 .arg(echo_reply->getSequence());
287 .arg(echo_reply->getSource())
288 .arg(echo_reply->getId())
289 .arg(echo_reply->getSequence());
292 store_->updateContext(context);
298 auto parking_lot = context->getParkingLot();
300 auto query = context->getQuery();
301 auto callout_handle = query->getCalloutHandle();
302 callout_handle->setArgument(
"offer_address_in_use",
true);
303 parking_lot->unpark(query);
307 store_->deleteContext(context);
314 auto payload = unreachable->getPayload();
322 .arg(embedded_echo->getDestination())
323 .arg(embedded_echo->getId())
324 .arg(embedded_echo->getSequence());
330 .arg(embedded_echo->getDestination())
331 .arg(embedded_echo->getId())
332 .arg(embedded_echo->getSequence());
341 store_->updateContext(context);
345 .arg(context->getTarget())
346 .arg(context->getQuery()->getLabel());
352 auto parking_lot = context->getParkingLot();
354 auto query = context->getQuery();
355 auto callout_handle = query->getCalloutHandle();
356 callout_handle->setArgument(
"offer_address_in_use",
false);
357 parking_lot->unpark(context->getQuery());
361 store_->deleteContext(context);
377 auto expired_pings =
store_->getExpiredSince(since);
378 size_t more_pings = 0;
379 for (
auto const& context : *(expired_pings)) {
382 .arg(context->getTarget())
383 .arg(context->getEchosSent())
384 .arg(context->getMinEchos())
385 .arg(context->getReplyTimeout());
387 if (context->getEchosSent() < context->getMinEchos()) {
403 .arg(context->getTarget())
404 .arg(context->getEchosSent() + 1)
405 .arg(context->getMinEchos());
407 context->beginWaitingToSend();
408 store_->updateContext(context);
437 auto timeout = duration_cast<milliseconds>(context->getNextExpiry() - now);
439 timeout = (timeout > milliseconds(2) ? timeout : milliseconds(2));
500 if (
store_->getContextByAddress(lease->addr_)) {
504 .arg(query->getLabel());
509 if (host && (host->getIPv4Reservation() == lease->addr_)) {
517 if (old_lease && (old_lease->addr_ == lease->addr_)) {
518 if (old_lease->belongsToClient(lease->hwaddr_, lease->client_id_)) {
519 if (!old_lease->expired() ||
520 ((time(0) - old_lease->cltt_) <
config->getPingClttSecs())) {
599 auto use_threads = (
config->getPingChannelThreads() ?
config->getPingChannelThreads()
609 }
catch (
const std::exception& ex) {
624 }
catch (
const std::exception& ex) {
636 this, ph::_1, ph::_2),
657 }
catch (
const std::exception& ex) {
679 }
catch (
const std::exception& ex) {
700 }
catch (
const std::exception& ex) {
787 auto contexts =
store_->getAll();
788 for (
auto const& context : *contexts) {
792 auto parking_lot = context->getParkingLot();
794 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 IOAddress class represents an IP addresses (version agnostic)
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.
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 bool nextToSend(asiolink::IOAddress &next)
Callback passed to PingChannel to use to retrieve the next address to check.
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.
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.