Kea 2.7.5
communication_state.h
Go to the documentation of this file.
1// Copyright (C) 2018-2024 Internet Systems Consortium, Inc. ("ISC")
2//
3// This Source Code Form is subject to the terms of the Mozilla Public
4// License, v. 2.0. If a copy of the MPL was not distributed with this
5// file, You can obtain one at http://mozilla.org/MPL/2.0/.
6
7#ifndef HA_COMMUNICATION_STATE_H
8#define HA_COMMUNICATION_STATE_H
9
10#include <ha_config.h>
11#include <ha_service_states.h>
13#include <asiolink/io_service.h>
14#include <cc/data.h>
15#include <dhcp/pkt.h>
16
17#include <boost/date_time/posix_time/posix_time.hpp>
18#include <boost/multi_index_container.hpp>
19#include <boost/multi_index/composite_key.hpp>
20#include <boost/multi_index/hashed_index.hpp>
21#include <boost/multi_index/indexed_by.hpp>
22#include <boost/multi_index/member.hpp>
23#include <boost/multi_index/ordered_index.hpp>
24#include <boost/scoped_ptr.hpp>
25#include <boost/shared_ptr.hpp>
26
27#include <functional>
28#include <mutex>
29#include <set>
30#include <string>
31#include <utility>
32
33namespace isc {
34namespace ha {
35
82public:
83
89 const HAConfigPtr& config);
90
94 virtual ~CommunicationState();
95
99 int getPartnerState() const;
100
106 void setPartnerState(const std::string& state);
107
115
116private:
122 void setPartnerStateInternal(const std::string& state);
123
124public:
125
130 boost::posix_time::time_duration getDurationSincePartnerStateTime() const;
131
132private:
133
137 void setCurrentPartnerStateTimeInternal();
138
139public:
140
144 std::set<std::string> getPartnerScopes() const;
145
150
151private:
155 void setPartnerScopesInternal(data::ConstElementPtr new_scopes);
156
157public:
163 void startHeartbeat(const long interval,
164 const std::function<void()>& heartbeat_impl);
165
167 void stopHeartbeat();
168
169private:
175 void startHeartbeatInternal(const long interval = 0,
176 const std::function<void()>& heartbeat_impl = 0);
177
179 void stopHeartbeatInternal();
180
181public:
185 bool isHeartbeatRunning() const;
186
192 void poke();
193
194private:
200 void pokeInternal();
201
202public:
206 int64_t getDurationInMillisecs() const;
207
216 bool isCommunicationInterrupted() const;
217
218protected:
219
227 static std::vector<uint8_t> getClientId(const dhcp::PktPtr& message,
228 const uint16_t option_type);
229public:
230
262 virtual void analyzeMessage(const boost::shared_ptr<dhcp::Pkt>& message) = 0;
263
269 size_t getAnalyzedMessagesCount() const;
270
285 virtual bool failureDetected() const = 0;
286
295 virtual size_t getConnectingClientsCount() const = 0;
296
305 virtual size_t getUnackedClientsCount() const = 0;
306
307protected:
308
321 virtual void clearConnectingClients() = 0;
322
323public:
324
333
334protected:
335
344
352 template<typename RejectedClientsType>
353 static size_t getRejectedLeaseUpdatesCountFromContainer(RejectedClientsType& rejected_clients) {
354 if (rejected_clients.empty()) {
355 return (0);
356 }
357 auto& idx = rejected_clients.template get<1>();
358 auto upper_limit = idx.upper_bound(time(NULL));
359 if (upper_limit != idx.end()) {
360 auto lower_limit = idx.cbegin();
361 idx.erase(lower_limit, upper_limit);
362 }
363 return (rejected_clients.size());
364 }
365
366public:
367
380 bool reportRejectedLeaseUpdate(const dhcp::PktPtr& message,
381 const uint32_t lifetime = 86400);
382
383protected:
384
398 const uint32_t lifetime) = 0;
399public:
400
410 bool reportSuccessfulLeaseUpdate(const dhcp::PktPtr& message);
411
412protected:
413
423 virtual bool reportSuccessfulLeaseUpdateInternal(const dhcp::PktPtr& message) = 0;
424
425public:
426
429
430protected:
431
434
435public:
436
459 bool clockSkewShouldWarn();
460
461private:
484 bool clockSkewShouldWarnInternal();
485
486public:
504
505private:
522 bool clockSkewShouldTerminateInternal();
523
530 bool isClockSkewGreater(const long seconds) const;
531
532public:
533
542
543private:
544
552 bool rejectedLeaseUpdatesShouldTerminateInternal();
553
554public:
555
567 void setPartnerTime(const std::string& time_text);
568
569private:
570
582 void setPartnerTimeInternal(const std::string& time_text);
583
588 void resetPartnerTimeInternal();
589
590public:
592 std::string logFormatClockSkew() const;
593
594private:
596 std::string logFormatClockSkewInternal() const;
597
598public:
607
615 void modifyPokeTime(const long secs);
616
617private:
618
624 int64_t getDurationInMillisecsInternal() const;
625
626protected:
630 boost::posix_time::time_duration updatePokeTime();
631
632private:
638 boost::posix_time::time_duration updatePokeTimeInternal();
639
640public:
641
643 uint64_t getUnsentUpdateCount() const;
644
657
658private:
659
661 void increaseUnsentUpdateCountInternal();
662
663public:
664
674 bool hasPartnerNewUnsentUpdates() const;
675
676private:
677
682 bool hasPartnerNewUnsentUpdatesInternal() const;
683
684public:
685
690 void setPartnerUnsentUpdateCount(uint64_t unsent_update_count);
691
692private:
693
698 void setPartnerUnsentUpdateCountInternal(uint64_t unsent_update_count);
699
700public:
704 boost::posix_time::ptime getMyTimeAtSkew() const;
705
709 boost::posix_time::ptime getPartnerTimeAtSkew() const;
710
711protected:
714
717
720
723
725 boost::posix_time::ptime poke_time_;
726
728 std::function<void()> heartbeat_impl_;
729
734
736 boost::posix_time::ptime partner_state_time_;
737
739 std::set<std::string> partner_scopes_;
740
742 boost::posix_time::time_duration clock_skew_;
743
746 boost::posix_time::ptime last_clock_skew_warn_;
747
749 boost::posix_time::ptime my_time_at_skew_;
750
752 boost::posix_time::ptime partner_time_at_skew_;
753
756
766
773 std::pair<uint64_t, uint64_t> partner_unsent_update_count_;
774
776 const boost::scoped_ptr<std::mutex> mutex_;
777};
778
780typedef boost::shared_ptr<CommunicationState> CommunicationStatePtr;
781
782
789public:
790
796 const HAConfigPtr& config);
797
812 virtual void analyzeMessage(const boost::shared_ptr<dhcp::Pkt>& message);
813
819 virtual bool failureDetected() const;
820
829 virtual size_t getConnectingClientsCount() const;
830
839 virtual size_t getUnackedClientsCount() const;
840
841protected:
842
851
864 virtual bool reportRejectedLeaseUpdateInternal(const dhcp::PktPtr& message,
865 const uint32_t lifetime);
866
876 virtual bool reportSuccessfulLeaseUpdateInternal(const dhcp::PktPtr& message);
877
880
897 virtual void analyzeMessageInternal(const boost::shared_ptr<dhcp::Pkt>& message);
898
906 virtual bool failureDetectedInternal() const;
907
913 virtual void clearConnectingClients();
914
919 template<typename ClientData>
920 using ClientIdent4 = boost::multi_index::hashed_unique<
921 boost::multi_index::composite_key<
922 ClientData,
923 boost::multi_index::member<ClientData, std::vector<uint8_t>,
924 &ClientData::hwaddr_>,
925 boost::multi_index::member<ClientData, std::vector<uint8_t>,
926 &ClientData::clientid_>
927 >
928 >;
929
933 std::vector<uint8_t> hwaddr_;
934 std::vector<uint8_t> clientid_;
936 };
937
940 typedef boost::multi_index_container<
942 boost::multi_index::indexed_by<
943 // First index is a composite index which allows to find a client
944 // by the HW address/client identifier tuple.
945 ClientIdent4<ConnectingClient4>,
946 // Second index allows for counting all clients which are
947 // considered unacked.
948 boost::multi_index::ordered_non_unique<
949 boost::multi_index::member<ConnectingClient4, bool, &ConnectingClient4::unacked_>
950 >
951 >
953
958
962 std::vector<uint8_t> hwaddr_;
963 std::vector<uint8_t> clientid_;
964 int64_t expire_;
965 };
966
969 typedef boost::multi_index_container<
971 boost::multi_index::indexed_by<
972 ClientIdent4<RejectedClient4>,
973 boost::multi_index::ordered_non_unique<
974 boost::multi_index::member<RejectedClient4, int64_t,
976 >
977 >
979
983};
984
986typedef boost::shared_ptr<CommunicationState4> CommunicationState4Ptr;
987
994public:
995
1001 const HAConfigPtr& config);
1002
1011 virtual void analyzeMessage(const boost::shared_ptr<dhcp::Pkt>& message);
1012
1018 virtual bool failureDetected() const;
1019
1028 virtual size_t getConnectingClientsCount() const;
1029
1038 virtual size_t getUnackedClientsCount() const;
1039
1040protected:
1041
1049 virtual size_t getRejectedLeaseUpdatesCountInternal();
1050
1063 virtual bool reportRejectedLeaseUpdateInternal(const dhcp::PktPtr& message,
1064 const uint32_t lifetime = 86400);
1065
1075 virtual bool reportSuccessfulLeaseUpdateInternal(const dhcp::PktPtr& message);
1076
1078 virtual void clearRejectedLeaseUpdatesInternal();
1079
1080protected:
1081
1092 virtual void analyzeMessageInternal(const boost::shared_ptr<dhcp::Pkt>& message);
1093
1101 virtual bool failureDetectedInternal() const;
1102
1108 virtual void clearConnectingClients();
1109
1114 template<typename ClientData>
1115 using ClientIdent6 = boost::multi_index::hashed_unique<
1116 boost::multi_index::member<ClientData, std::vector<uint8_t>,
1117 &ClientData::duid_>
1118 >;
1119
1123 std::vector<uint8_t> duid_;
1125 };
1126
1129 typedef boost::multi_index_container<
1131 boost::multi_index::indexed_by<
1132 // First index is for accessing connecting clients by DUID.
1133 ClientIdent6<ConnectingClient6>,
1134 // Second index allows for counting all clients which are
1135 // considered unacked.
1136 boost::multi_index::ordered_non_unique<
1137 boost::multi_index::member<ConnectingClient6, bool, &ConnectingClient6::unacked_>
1138 >
1139 >
1141
1146
1150 std::vector<uint8_t> duid_;
1151 int64_t expire_;
1152 };
1153
1156 typedef boost::multi_index_container<
1158 boost::multi_index::indexed_by<
1159 ClientIdent6<RejectedClient6>,
1160 boost::multi_index::ordered_non_unique<
1161 boost::multi_index::member<RejectedClient6, int64_t,
1163 >
1164 >
1166
1170};
1171
1173typedef boost::shared_ptr<CommunicationState6> CommunicationState6Ptr;
1174
1175} // end of namespace isc::ha
1176} // end of namespace isc
1177
1178#endif
Holds communication state between DHCPv4 servers.
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.
boost::multi_index_container< RejectedClient4, boost::multi_index::indexed_by< ClientIdent4< RejectedClient4 >, boost::multi_index::ordered_non_unique< boost::multi_index::member< RejectedClient4, int64_t, &RejectedClient4::expire_ > > > > RejectedClients4
Multi index container holding information about the clients who have rejected leases.
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.
boost::multi_index::hashed_unique< boost::multi_index::composite_key< ClientData, boost::multi_index::member< ClientData, std::vector< uint8_t >, &ClientData::hwaddr_ >, boost::multi_index::member< ClientData, std::vector< uint8_t >, &ClientData::clientid_ > > > ClientIdent4
Hashed index used in the multi index containers to find clients by HW address and client identifier.
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...
boost::multi_index_container< ConnectingClient4, boost::multi_index::indexed_by< ClientIdent4< ConnectingClient4 >, boost::multi_index::ordered_non_unique< boost::multi_index::member< ConnectingClient4, bool, &ConnectingClient4::unacked_ > > > > ConnectingClients4
Multi index container holding information about the clients attempting to get leases from the partner...
CommunicationState4(const asiolink::IOServicePtr &io_service, const HAConfigPtr &config)
Constructor.
Holds communication state between DHCPv6 servers.
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...
boost::multi_index_container< ConnectingClient6, boost::multi_index::indexed_by< ClientIdent6< ConnectingClient6 >, boost::multi_index::ordered_non_unique< boost::multi_index::member< ConnectingClient6, bool, &ConnectingClient6::unacked_ > > > > ConnectingClients6
Multi index container holding information about the clients attempting to get leases from the partner...
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.
boost::multi_index_container< RejectedClient6, boost::multi_index::indexed_by< ClientIdent6< RejectedClient6 >, boost::multi_index::ordered_non_unique< boost::multi_index::member< RejectedClient6, int64_t, &RejectedClient6::expire_ > > > > RejectedClients6
Multi index container holding information about the clients who have rejected leases.
boost::multi_index::hashed_unique< boost::multi_index::member< ClientData, std::vector< uint8_t >, &ClientData::duid_ > > ClientIdent6
Hashed index used in the multi index containers to find clients by DUID.
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.
boost::posix_time::ptime partner_state_time_
Holds a time when partner was first seen in the current state.
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.
virtual void analyzeMessage(const boost::shared_ptr< dhcp::Pkt > &message)=0
Checks if the DHCP message appears to be unanswered.
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::ptime getPartnerTimeAtSkew() const
Retrieves the time of the partner node when skew was last calculated.
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.
boost::posix_time::time_duration getDurationSincePartnerStateTime() const
Returns the duration since the partner was first seen in the current state.
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 getMyTimeAtSkew() const
Retrieves the time of the local node when skew was last calculated.
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).
virtual bool failureDetected() const =0
Checks if the partner failure has been detected based on the DHCP traffic analysis.
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.
boost::shared_ptr< const Element > ConstElementPtr
Definition data.h:29
boost::shared_ptr< Element > ElementPtr
Definition data.h:28
boost::shared_ptr< isc::dhcp::Pkt > PktPtr
A pointer to either Pkt4 or Pkt6 packet.
Definition pkt.h:998
boost::shared_ptr< CommunicationState > CommunicationStatePtr
Type of the pointer to the CommunicationState object.
boost::shared_ptr< CommunicationState4 > CommunicationState4Ptr
Pointer to the CommunicationState4 object.
boost::shared_ptr< HAConfig > HAConfigPtr
Pointer to the High Availability configuration structure.
Definition ha_config.h:37
boost::shared_ptr< CommunicationState6 > CommunicationState6Ptr
Pointer to the CommunicationState6 object.
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.
Structure holding information about the client who has a rejected lease update.
Structure holding information about a client which sent a packet being analyzed.
Structure holding information about the client who has a rejected lease update.