23#include <boost/pointer_cast.hpp>
38using namespace boost::posix_time;
44constexpr long WARN_CLOCK_SKEW = 30;
47constexpr long TERM_CLOCK_SKEW = 60;
50constexpr long MIN_TIME_SINCE_CLOCK_SKEW_WARN = 60;
59 : io_service_(io_service), config_(config), timer_(), interval_(0),
60 poke_time_(
boost::posix_time::microsec_clock::universal_time()),
61 heartbeat_impl_(0), partner_state_(-1), partner_scopes_(),
62 clock_skew_(0, 0, 0, 0), last_clock_skew_warn_(),
63 my_time_at_skew_(), partner_time_at_skew_(),
64 analyzed_messages_count_(0), unsent_update_count_(0),
65 partner_unsent_update_count_{0, 0}, mutex_(new mutex()) {
74 if (MultiThreadingMgr::instance().getMode()) {
75 std::lock_guard<std::mutex> lk(*
mutex_);
76 poke_time_ += boost::posix_time::seconds(secs);
78 poke_time_ += boost::posix_time::seconds(secs);
84 if (MultiThreadingMgr::instance().getMode()) {
85 std::lock_guard<std::mutex> lk(*
mutex_);
94 if (MultiThreadingMgr::instance().getMode()) {
95 std::lock_guard<std::mutex> lk(*
mutex_);
96 setPartnerStateInternal(state);
98 setPartnerStateInternal(state);
104 if (MultiThreadingMgr::instance().getMode()) {
105 std::lock_guard<std::mutex> lk(*
mutex_);
106 setPartnerStateInternal(
"unavailable");
107 resetPartnerTimeInternal();
109 setPartnerStateInternal(
"unavailable");
110 resetPartnerTimeInternal();
115CommunicationState::setPartnerStateInternal(
const std::string& state) {
126 if (MultiThreadingMgr::instance().getMode()) {
127 std::lock_guard<std::mutex> lk(*
mutex_);
136 if (MultiThreadingMgr::instance().getMode()) {
137 std::lock_guard<std::mutex> lk(*
mutex_);
138 setPartnerScopesInternal(new_scopes);
140 setPartnerScopesInternal(new_scopes);
145CommunicationState::setPartnerScopesInternal(
ConstElementPtr new_scopes) {
146 if (!new_scopes || (new_scopes->getType() != Element::list)) {
148 " the received value is not a valid JSON list");
151 std::set<std::string> partner_scopes;
152 for (
auto i = 0; i < new_scopes->size(); ++i) {
153 auto scope = new_scopes->get(i);
154 if (scope->getType() != Element::string) {
156 " the received scope value is not a valid JSON string");
158 auto scope_str = scope->stringValue();
159 if (!scope_str.empty()) {
160 partner_scopes.insert(scope_str);
168 const std::function<
void()>& heartbeat_impl) {
169 if (MultiThreadingMgr::instance().getMode()) {
170 std::lock_guard<std::mutex> lk(*
mutex_);
171 startHeartbeatInternal(interval, heartbeat_impl);
173 startHeartbeatInternal(interval, heartbeat_impl);
178CommunicationState::startHeartbeatInternal(
const long interval,
179 const std::function<
void()>& heartbeat_impl) {
180 bool settings_modified =
false;
184 if (heartbeat_impl) {
185 settings_modified =
true;
192 " to the heartbeat implementation is not specified");
198 settings_modified |= (
interval_ != interval);
206 " for the heartbeat timer is not specified");
213 if (settings_modified) {
220 if (MultiThreadingMgr::instance().getMode()) {
221 std::lock_guard<std::mutex> lk(*
mutex_);
222 stopHeartbeatInternal();
224 stopHeartbeatInternal();
229CommunicationState::stopHeartbeatInternal() {
240 if (MultiThreadingMgr::instance().getMode()) {
241 std::lock_guard<std::mutex> lk(*
mutex_);
242 return (
static_cast<bool>(
timer_));
244 return (
static_cast<bool>(
timer_));
248boost::posix_time::time_duration
250 if (MultiThreadingMgr::instance().getMode()) {
251 std::lock_guard<std::mutex> lk(*
mutex_);
252 return (updatePokeTimeInternal());
254 return (updatePokeTimeInternal());
258boost::posix_time::time_duration
259CommunicationState::updatePokeTimeInternal() {
261 boost::posix_time::ptime prev_poke_time =
poke_time_;
263 poke_time_ = boost::posix_time::microsec_clock::universal_time();
269 if (MultiThreadingMgr::instance().getMode()) {
270 std::lock_guard<std::mutex> lk(*
mutex_);
278CommunicationState::pokeInternal() {
280 boost::posix_time::time_duration duration_since_poke = updatePokeTimeInternal();
293 if (duration_since_poke.total_seconds() > 0) {
297 startHeartbeatInternal();
304 if (MultiThreadingMgr::instance().getMode()) {
305 std::lock_guard<std::mutex> lk(*
mutex_);
306 return (getDurationInMillisecsInternal());
308 return (getDurationInMillisecsInternal());
313CommunicationState::getDurationInMillisecsInternal()
const {
314 ptime now = boost::posix_time::microsec_clock::universal_time();
316 return (duration.total_milliseconds());
326 const uint16_t option_type) {
327 std::vector<uint8_t> client_id;
328 OptionPtr opt_client_id = message->getOption(option_type);
330 client_id = opt_client_id->getData();
342 if (MultiThreadingMgr::instance().getMode()) {
343 std::lock_guard<std::mutex> lk(*
mutex_);
352 const uint32_t lifetime) {
353 if (MultiThreadingMgr::instance().getMode()) {
354 std::lock_guard<std::mutex> lk(*
mutex_);
363 if (MultiThreadingMgr::instance().getMode()) {
364 std::lock_guard<std::mutex> lk(*
mutex_);
373 if (MultiThreadingMgr::instance().getMode()) {
374 std::lock_guard<std::mutex> lk(*
mutex_);
383 if (MultiThreadingMgr::instance().getMode()) {
384 std::lock_guard<std::mutex> lk(*
mutex_);
385 return (clockSkewShouldWarnInternal());
387 return (clockSkewShouldWarnInternal());
392CommunicationState::clockSkewShouldWarnInternal() {
394 if (isClockSkewGreater(WARN_CLOCK_SKEW)) {
401 ptime now = boost::posix_time::microsec_clock::universal_time();
408 (since_warn_duration.total_seconds() > MIN_TIME_SINCE_CLOCK_SKEW_WARN)) {
411 .arg(
config_->getThisServerName())
412 .arg(logFormatClockSkewInternal());
423 if (MultiThreadingMgr::instance().getMode()) {
424 std::lock_guard<std::mutex> lk(*
mutex_);
426 return (clockSkewShouldTerminateInternal());
428 return (clockSkewShouldTerminateInternal());
433CommunicationState::clockSkewShouldTerminateInternal() {
434 if (isClockSkewGreater(TERM_CLOCK_SKEW)) {
436 .arg(
config_->getThisServerName())
437 .arg(logFormatClockSkewInternal());
445 if (MultiThreadingMgr::instance().getMode()) {
446 std::lock_guard<std::mutex> lk(*
mutex_);
447 return (rejectedLeaseUpdatesShouldTerminateInternal());
449 return (rejectedLeaseUpdatesShouldTerminateInternal());
454CommunicationState::rejectedLeaseUpdatesShouldTerminateInternal() {
455 if (
config_->getMaxRejectedLeaseUpdates() &&
458 .arg(
config_->getThisServerName());
465CommunicationState::isClockSkewGreater(
const long seconds)
const {
472 if (MultiThreadingMgr::instance().getMode()) {
473 std::lock_guard<std::mutex> lk(*
mutex_);
474 setPartnerTimeInternal(time_text);
476 setPartnerTimeInternal(time_text);
481CommunicationState::setPartnerTimeInternal(
const std::string& time_text) {
488CommunicationState::resetPartnerTimeInternal() {
489 clock_skew_ = boost::posix_time::time_duration(0, 0, 0, 0);
497 if (MultiThreadingMgr::instance().getMode()) {
498 std::lock_guard<std::mutex> lk(*
mutex_);
499 return (logFormatClockSkewInternal());
501 return (logFormatClockSkewInternal());
506CommunicationState::logFormatClockSkewInternal()
const {
507 std::ostringstream os;
513 return (
"skew not initialized");
520 <<
", partner's clock is ";
524 os <<
clock_skew_.invert_sign().total_seconds() <<
"s behind";
535 auto report = Element::createMap();
538 report->set(
"in-touch", Element::create(in_touch));
541 report->set(
"age", Element::create(age));
547 report->set(
"last-state", Element::create(std::string()));
550 auto list = Element::createList();
552 list->add(Element::create(scope));
554 report->set(
"last-scopes", list);
555 report->set(
"communication-interrupted",
560 long long unacked_clients_left = 0;
562 unacked_clients_left =
static_cast<long long>(
config_->getMaxUnackedClients() -
565 report->set(
"unacked-clients-left", Element::create(unacked_clients_left));
573 if (MultiThreadingMgr::instance().getMode()) {
574 std::lock_guard<std::mutex> lk(*
mutex_);
583 if (MultiThreadingMgr::instance().getMode()) {
584 std::lock_guard<std::mutex> lk(*
mutex_);
585 increaseUnsentUpdateCountInternal();
587 increaseUnsentUpdateCountInternal();
592CommunicationState::increaseUnsentUpdateCountInternal() {
604 if (MultiThreadingMgr::instance().getMode()) {
605 std::lock_guard<std::mutex> lk(*
mutex_);
606 return (hasPartnerNewUnsentUpdatesInternal());
608 return (hasPartnerNewUnsentUpdatesInternal());
613CommunicationState::hasPartnerNewUnsentUpdatesInternal()
const {
620 if (MultiThreadingMgr::instance().getMode()) {
621 std::lock_guard<std::mutex> lk(*
mutex_);
622 setPartnerUnsentUpdateCountInternal(unsent_update_count);
624 setPartnerUnsentUpdateCountInternal(unsent_update_count);
629CommunicationState::setPartnerUnsentUpdateCountInternal(uint64_t unsent_update_count) {
637 rejected_clients_() {
642 if (MultiThreadingMgr::instance().getMode()) {
643 std::lock_guard<std::mutex> lk(*
mutex_);
653 Pkt4Ptr msg = boost::dynamic_pointer_cast<Pkt4>(message);
662 uint16_t secs = msg->getSecs();
667 if ((secs > 255) && ((secs & 0xFF) == 0)) {
668 secs = ((secs >> 8) | (secs << 8));
675 auto unacked = (secs * 1000 >
config_->getMaxAckDelay());
680 bool log_unacked =
false;
684 auto existing_request = idx.find(boost::make_tuple(msg->getHWAddr()->hwaddr_, client_id));
685 if (existing_request != idx.end()) {
690 if (!existing_request->unacked_ && unacked) {
692 idx.replace(existing_request, connecting_client);
700 idx.insert(connecting_client);
701 log_unacked = unacked;
708 .arg(
config_->getThisServerName())
709 .arg(message->getLabel());
715 unsigned unacked_left = 0;
717 if (
config_->getMaxUnackedClients() >= unacked_total) {
718 unacked_left =
config_->getMaxUnackedClients() - unacked_total + 1;
721 .arg(
config_->getThisServerName())
722 .arg(message->getLabel())
730 if (MultiThreadingMgr::instance().getMode()) {
731 std::lock_guard<std::mutex> lk(*
mutex_);
740 return ((
config_->getMaxUnackedClients() == 0) ||
742 config_->getMaxUnackedClients()));
747 if (MultiThreadingMgr::instance().getMode()) {
748 std::lock_guard<std::mutex> lk(*
mutex_);
757 if (MultiThreadingMgr::instance().getMode()) {
758 std::lock_guard<std::mutex> lk(*
mutex_);
777 Pkt4Ptr msg = boost::dynamic_pointer_cast<Pkt4>(message);
779 isc_throw(
BadValue,
"DHCP message for which the lease update was rejected is not a DHCPv4 message");
783 auto existing_client =
rejected_clients_.find(boost::make_tuple(msg->getHWAddr()->hwaddr_, client_id));
798 Pkt4Ptr msg = boost::dynamic_pointer_cast<Pkt4>(message);
800 isc_throw(
BadValue,
"DHCP message for which the lease update was successful is not a DHCPv4 message");
803 auto existing_client =
rejected_clients_.find(boost::make_tuple(msg->getHWAddr()->hwaddr_, client_id));
819 rejected_clients_() {
824 if (MultiThreadingMgr::instance().getMode()) {
825 std::lock_guard<std::mutex> lk(*
mutex_);
835 Pkt6Ptr msg = boost::dynamic_pointer_cast<Pkt6>(message);
847 auto unacked = (elapsed_time && elapsed_time->getValue() * 10 >
config_->getMaxAckDelay());
855 bool log_unacked =
false;
859 auto existing_request = idx.find(duid);
860 if (existing_request != idx.end()) {
865 if (!existing_request->unacked_ && unacked) {
867 idx.replace(existing_request, connecting_client);
875 idx.insert(connecting_client);
876 log_unacked = unacked;
883 .arg(
config_->getThisServerName())
884 .arg(message->getLabel());
890 unsigned unacked_left = 0;
892 if (
config_->getMaxUnackedClients() >= unacked_total) {
893 unacked_left =
config_->getMaxUnackedClients() - unacked_total + 1;
896 .arg(
config_->getThisServerName())
897 .arg(message->getLabel())
905 if (MultiThreadingMgr::instance().getMode()) {
906 std::lock_guard<std::mutex> lk(*
mutex_);
915 return ((
config_->getMaxUnackedClients() == 0) ||
917 config_->getMaxUnackedClients()));
922 if (MultiThreadingMgr::instance().getMode()) {
923 std::lock_guard<std::mutex> lk(*
mutex_);
932 if (MultiThreadingMgr::instance().getMode()) {
933 std::lock_guard<std::mutex> lk(*
mutex_);
952 Pkt6Ptr msg = boost::dynamic_pointer_cast<Pkt6>(message);
954 isc_throw(
BadValue,
"DHCP message for which the lease update was rejected is not a DHCPv6 message");
976 Pkt6Ptr msg = boost::dynamic_pointer_cast<Pkt6>(message);
978 isc_throw(
BadValue,
"DHCP message for which the lease update was successful is not a DHCPv6 message");
A generic exception that is thrown if a parameter given to a method is considered invalid in that con...
The IntervalTimer class is a wrapper for the ASIO boost::asio::deadline_timer class.
Forward declaration to OptionInt.
virtual bool reportRejectedLeaseUpdateInternal(const dhcp::PktPtr &message, const uint32_t lifetime)
Marks that the lease update failed due to a conflict for the specified DHCP message.
virtual size_t getRejectedLeaseUpdatesCountInternal()
Returns the number of lease updates rejected by the partner.
virtual bool reportSuccessfulLeaseUpdateInternal(const dhcp::PktPtr &message)
Marks the lease update successful.
virtual size_t getUnackedClientsCount() const
Returns the current number of clients which haven't gotten a lease from the partner server.
virtual void clearRejectedLeaseUpdatesInternal()
Clears rejected client leases.
virtual void analyzeMessageInternal(const boost::shared_ptr< dhcp::Pkt > &message)
Checks if the DHCPv4 message appears to be unanswered.
virtual size_t getConnectingClientsCount() const
Returns the current number of clients which attempted to get a lease from the partner server.
virtual void analyzeMessage(const boost::shared_ptr< dhcp::Pkt > &message)
Checks if the DHCPv4 message appears to be unanswered.
RejectedClients4 rejected_clients_
Holds information about the clients for whom lease updates have been rejected by the partner.
virtual bool failureDetectedInternal() const
Checks if the partner failure has been detected based on the DHCP traffic analysis.
ConnectingClients4 connecting_clients_
Holds information about the clients attempting to contact the partner server while the servers are in...
virtual bool failureDetected() const
Checks if the partner failure has been detected based on the DHCP traffic analysis.
virtual void clearConnectingClients()
Removes information about the clients the partner server should respond to while communication with t...
CommunicationState4(const asiolink::IOServicePtr &io_service, const HAConfigPtr &config)
Constructor.
virtual void analyzeMessage(const boost::shared_ptr< dhcp::Pkt > &message)
Checks if the DHCPv6 message appears to be unanswered.
RejectedClients6 rejected_clients_
Holds information about the clients for whom lease updates have been rejected by the partner.
virtual size_t getRejectedLeaseUpdatesCountInternal()
Returns the number of lease updates rejected by the partner.
ConnectingClients6 connecting_clients_
Holds information about the clients attempting to contact the partner server while the servers are in...
CommunicationState6(const asiolink::IOServicePtr &io_service, const HAConfigPtr &config)
Constructor.
virtual bool reportSuccessfulLeaseUpdateInternal(const dhcp::PktPtr &message)
Marks the lease update successful.
virtual void clearConnectingClients()
Removes information about the clients the partner server should respond to while communication with t...
virtual bool failureDetected() const
Checks if the partner failure has been detected based on the DHCP traffic analysis.
virtual size_t getUnackedClientsCount() const
Returns the current number of clients which haven't gotten a lease from the partner server.
virtual bool failureDetectedInternal() const
Checks if the partner failure has been detected based on the DHCP traffic analysis.
virtual void analyzeMessageInternal(const boost::shared_ptr< dhcp::Pkt > &message)
Checks if the DHCPv6 message appears to be unanswered.
virtual bool reportRejectedLeaseUpdateInternal(const dhcp::PktPtr &message, const uint32_t lifetime=86400)
Marks that the lease update failed due to a conflict for the specified DHCP message.
virtual size_t getConnectingClientsCount() const
Returns the current number of clients which attempted to get a lease from the partner server.
virtual void clearRejectedLeaseUpdatesInternal()
Clears rejected client leases.
Holds communication state between the two HA peers.
virtual size_t getConnectingClientsCount() const =0
Returns the current number of clients which attempted to get a lease from the partner server.
virtual bool reportRejectedLeaseUpdateInternal(const dhcp::PktPtr &message, const uint32_t lifetime)=0
Marks that the lease update failed due to a conflict for the specified DHCP message.
virtual void clearRejectedLeaseUpdatesInternal()=0
Clears rejected client leases.
virtual size_t getUnackedClientsCount() const =0
Returns the current number of clients which haven't got the lease from the partner server.
virtual void clearConnectingClients()=0
Removes information about the clients the partner server should respond to while communication with t...
void clearRejectedLeaseUpdates()
Clears rejected client leases (MT safe).
void startHeartbeat(const long interval, const std::function< void()> &heartbeat_impl)
Starts recurring heartbeat (public interface).
uint64_t unsent_update_count_
Total number of unsent lease updates.
bool isCommunicationInterrupted() const
Checks if communication with the partner is interrupted.
void setPartnerScopes(data::ConstElementPtr new_scopes)
Sets partner scopes.
int getPartnerState() const
Returns last known state of the partner.
bool clockSkewShouldWarn()
Issues a warning about high clock skew between the active servers if one is warranted.
std::string logFormatClockSkew() const
Returns current clock skew value in the logger friendly format.
void setPartnerUnsentUpdateCount(uint64_t unsent_update_count)
Saves new total number of unsent lease updates from the partner.
void setPartnerState(const std::string &state)
Sets partner state.
bool clockSkewShouldTerminate()
Indicates whether the HA service should enter "terminated" state as a result of the clock skew exceed...
std::pair< uint64_t, uint64_t > partner_unsent_update_count_
Previous and current total number of unsent lease updates from the partner.
std::set< std::string > getPartnerScopes() const
Returns scopes served by the partner server.
virtual ~CommunicationState()
Destructor.
HAConfigPtr config_
High availability configuration.
bool isHeartbeatRunning() const
Checks if recurring heartbeat is running.
static size_t getRejectedLeaseUpdatesCountFromContainer(RejectedClientsType &rejected_clients)
Extracts the number of lease updates rejected by the partner from the specified container.
long interval_
Interval specified for the heartbeat.
void setPartnerUnavailable()
Sets partner state unavailable.
void stopHeartbeat()
Stops recurring heartbeat.
void increaseUnsentUpdateCount()
Increases a total number of unsent lease updates by 1.
void setPartnerTime(const std::string &time_text)
Provide partner's notion of time so the new clock skew can be calculated.
bool hasPartnerNewUnsentUpdates() const
Checks if the partner allocated new leases for which it hasn't sent any lease updates.
virtual bool reportSuccessfulLeaseUpdateInternal(const dhcp::PktPtr &message)=0
Marks the lease update successful.
asiolink::IOServicePtr io_service_
Pointer to the common IO service instance.
virtual size_t getRejectedLeaseUpdatesCountInternal()=0
Returns the number of lease updates rejected by the partner.
void modifyPokeTime(const long secs)
Modifies poke time by adding seconds to it.
const boost::scoped_ptr< std::mutex > mutex_
The mutex used to protect internal state.
data::ElementPtr getReport() const
Returns the report about current communication state.
boost::posix_time::time_duration clock_skew_
Clock skew between the active servers.
size_t getAnalyzedMessagesCount() const
Returns the number of analyzed messages while being in the communications interrupted state.
size_t analyzed_messages_count_
Total number of analyzed messages to be responded by partner.
std::function< void()> heartbeat_impl_
Pointer to the function providing heartbeat implementation.
boost::posix_time::ptime poke_time_
Last poke time.
boost::posix_time::time_duration updatePokeTime()
Update the poke time and compute the duration.
bool reportSuccessfulLeaseUpdate(const dhcp::PktPtr &message)
Marks the lease update successful (MT safe).
boost::posix_time::ptime partner_time_at_skew_
Partner reported time when skew was calculated.
CommunicationState(const asiolink::IOServicePtr &io_service, const HAConfigPtr &config)
Constructor.
int partner_state_
Last known state of the partner server.
boost::posix_time::ptime last_clock_skew_warn_
Holds a time when last warning about too high clock skew was issued.
std::set< std::string > partner_scopes_
Last known set of scopes served by the partner server.
static std::vector< uint8_t > getClientId(const dhcp::PktPtr &message, const uint16_t option_type)
Convenience function attempting to retrieve client identifier from the DHCP message.
uint64_t getUnsentUpdateCount() const
Returns a total number of unsent lease updates.
bool rejectedLeaseUpdatesShouldTerminate()
Indicates whether the HA service should enter "terminated" state due to excessive number of rejected ...
boost::posix_time::ptime my_time_at_skew_
My time when skew was calculated.
int64_t getDurationInMillisecs() const
Returns duration between the poke time and current time.
bool reportRejectedLeaseUpdate(const dhcp::PktPtr &message, const uint32_t lifetime=86400)
Marks that the lease update failed due to a conflict for the specified DHCP message (MT safe).
size_t getRejectedLeaseUpdatesCount()
Returns the number of lease updates rejected by the partner (MT safe).
asiolink::IntervalTimerPtr timer_
Interval timer triggering heartbeat commands.
void poke()
Pokes the communication state.
This class parses and generates time values used in HTTP.
boost::posix_time::ptime getPtime() const
Returns time encapsulated by this class.
static HttpDateTime fromRfc1123(const std::string &time_string)
Creates an instance from a string containing time value formatted as specified in RFC 1123.
#define isc_throw(type, stream)
A shortcut macro to insert known values into exception arguments.
boost::shared_ptr< OptionUint16 > OptionUint16Ptr
#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_WARN(LOGGER, MESSAGE)
Macro to conveniently test warn 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< Element > ElementPtr
boost::shared_ptr< isc::dhcp::Pkt > PktPtr
A pointer to either Pkt4 or Pkt6 packet.
@ DHO_DHCP_CLIENT_IDENTIFIER
boost::shared_ptr< Pkt4 > Pkt4Ptr
A pointer to Pkt4 object.
boost::shared_ptr< Pkt6 > Pkt6Ptr
A pointer to Pkt6 packet.
boost::shared_ptr< Option > OptionPtr
const isc::log::MessageID HA_COMMUNICATION_INTERRUPTED_CLIENT4_UNACKED
const isc::log::MessageID HA_COMMUNICATION_INTERRUPTED_CLIENT6
isc::log::Logger ha_logger("ha-hooks")
const isc::log::MessageID HA_HIGH_CLOCK_SKEW_CAUSED_TERMINATION
const isc::log::MessageID HA_LEASE_UPDATE_REJECTS_CAUSED_TERMINATION
boost::shared_ptr< HAConfig > HAConfigPtr
Pointer to the High Availability configuration structure.
const isc::log::MessageID HA_COMMUNICATION_INTERRUPTED_CLIENT6_UNACKED
std::string stateToString(int state)
Returns state name.
const isc::log::MessageID HA_COMMUNICATION_INTERRUPTED_CLIENT4
int stringToState(const std::string &state_name)
Returns state for a given name.
const isc::log::MessageID HA_HIGH_CLOCK_SKEW
std::string ptimeToText(boost::posix_time::ptime t, size_t fsecs_precision=MAX_FSECS_PRECISION)
Converts ptime structure to text.
Defines the logger used by the top-level component of kea-lfc.
Structure holding information about the client which has sent the packet being analyzed.
std::vector< uint8_t > hwaddr_
Structure holding information about the client who has a rejected lease update.
std::vector< uint8_t > hwaddr_
Structure holding information about a client which sent a packet being analyzed.
Structure holding information about the client who has a rejected lease update.