Kea 2.5.8
communication_state.h
Go to the documentation of this file.
1// Copyright (C) 2018-2023 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 <map>
29#include <mutex>
30#include <set>
31#include <string>
32#include <utility>
33
34namespace isc {
35namespace ha {
36
83public:
84
90 const HAConfigPtr& config);
91
95 virtual ~CommunicationState();
96
100 int getPartnerState() const;
101
107 void setPartnerState(const std::string& state);
108
116
117private:
123 void setPartnerStateInternal(const std::string& state);
124
125public:
126
131 boost::posix_time::time_duration getDurationSincePartnerStateTime() const;
132
133private:
134
138 void setCurrentPartnerStateTimeInternal();
139
140public:
141
145 std::set<std::string> getPartnerScopes() const;
146
151
152private:
156 void setPartnerScopesInternal(data::ConstElementPtr new_scopes);
157
158public:
164 void startHeartbeat(const long interval,
165 const std::function<void()>& heartbeat_impl);
166
168 void stopHeartbeat();
169
170private:
176 void startHeartbeatInternal(const long interval = 0,
177 const std::function<void()>& heartbeat_impl = 0);
178
180 void stopHeartbeatInternal();
181
182public:
186 bool isHeartbeatRunning() const;
187
193 void poke();
194
195private:
201 void pokeInternal();
202
203public:
207 int64_t getDurationInMillisecs() const;
208
217 bool isCommunicationInterrupted() const;
218
219protected:
220
228 static std::vector<uint8_t> getClientId(const dhcp::PktPtr& message,
229 const uint16_t option_type);
230public:
231
263 virtual void analyzeMessage(const boost::shared_ptr<dhcp::Pkt>& message) = 0;
264
270 size_t getAnalyzedMessagesCount() const;
271
286 virtual bool failureDetected() const = 0;
287
296 virtual size_t getConnectingClientsCount() const = 0;
297
306 virtual size_t getUnackedClientsCount() const = 0;
307
308protected:
309
322 virtual void clearConnectingClients() = 0;
323
324public:
325
334
335protected:
336
345
353 template<typename RejectedClientsType>
354 static size_t getRejectedLeaseUpdatesCountFromContainer(RejectedClientsType& rejected_clients) {
355 if (rejected_clients.empty()) {
356 return (0);
357 }
358 auto& idx = rejected_clients.template get<1>();
359 auto upper_limit = idx.upper_bound(time(NULL));
360 if (upper_limit != idx.end()) {
361 auto lower_limit = idx.cbegin();
362 idx.erase(lower_limit, upper_limit);
363 }
364 return (rejected_clients.size());
365 }
366
367public:
368
381 bool reportRejectedLeaseUpdate(const dhcp::PktPtr& message,
382 const uint32_t lifetime = 86400);
383
384protected:
385
399 const uint32_t lifetime) = 0;
400public:
401
411 bool reportSuccessfulLeaseUpdate(const dhcp::PktPtr& message);
412
413protected:
414
424 virtual bool reportSuccessfulLeaseUpdateInternal(const dhcp::PktPtr& message) = 0;
425
426public:
427
430
431protected:
432
435
436public:
437
460 bool clockSkewShouldWarn();
461
462private:
485 bool clockSkewShouldWarnInternal();
486
487public:
505
506private:
523 bool clockSkewShouldTerminateInternal();
524
531 bool isClockSkewGreater(const long seconds) const;
532
533public:
534
543
544private:
545
553 bool rejectedLeaseUpdatesShouldTerminateInternal();
554
555public:
556
568 void setPartnerTime(const std::string& time_text);
569
570private:
571
583 void setPartnerTimeInternal(const std::string& time_text);
584
589 void resetPartnerTimeInternal();
590
591public:
593 std::string logFormatClockSkew() const;
594
595private:
597 std::string logFormatClockSkewInternal() const;
598
599public:
608
616 void modifyPokeTime(const long secs);
617
618private:
619
625 int64_t getDurationInMillisecsInternal() const;
626
627protected:
631 boost::posix_time::time_duration updatePokeTime();
632
633private:
639 boost::posix_time::time_duration updatePokeTimeInternal();
640
641public:
642
644 uint64_t getUnsentUpdateCount() const;
645
658
659private:
660
662 void increaseUnsentUpdateCountInternal();
663
664public:
665
675 bool hasPartnerNewUnsentUpdates() const;
676
677private:
678
683 bool hasPartnerNewUnsentUpdatesInternal() const;
684
685public:
686
691 void setPartnerUnsentUpdateCount(uint64_t unsent_update_count);
692
693private:
694
699 void setPartnerUnsentUpdateCountInternal(uint64_t unsent_update_count);
700
701protected:
704
707
710
713
715 boost::posix_time::ptime poke_time_;
716
718 std::function<void()> heartbeat_impl_;
719
724
726 boost::posix_time::ptime partner_state_time_;
727
729 std::set<std::string> partner_scopes_;
730
732 boost::posix_time::time_duration clock_skew_;
733
736 boost::posix_time::ptime last_clock_skew_warn_;
737
739 boost::posix_time::ptime my_time_at_skew_;
740
742 boost::posix_time::ptime partner_time_at_skew_;
743
746
756
763 std::pair<uint64_t, uint64_t> partner_unsent_update_count_;
764
766 const boost::scoped_ptr<std::mutex> mutex_;
767};
768
770typedef boost::shared_ptr<CommunicationState> CommunicationStatePtr;
771
772
779public:
780
786 const HAConfigPtr& config);
787
802 virtual void analyzeMessage(const boost::shared_ptr<dhcp::Pkt>& message);
803
809 virtual bool failureDetected() const;
810
819 virtual size_t getConnectingClientsCount() const;
820
829 virtual size_t getUnackedClientsCount() const;
830
831protected:
832
841
854 virtual bool reportRejectedLeaseUpdateInternal(const dhcp::PktPtr& message,
855 const uint32_t lifetime);
856
866 virtual bool reportSuccessfulLeaseUpdateInternal(const dhcp::PktPtr& message);
867
870
887 virtual void analyzeMessageInternal(const boost::shared_ptr<dhcp::Pkt>& message);
888
896 virtual bool failureDetectedInternal() const;
897
903 virtual void clearConnectingClients();
904
909 template<typename ClientData>
910 using ClientIdent4 = boost::multi_index::hashed_unique<
911 boost::multi_index::composite_key<
912 ClientData,
913 boost::multi_index::member<ClientData, std::vector<uint8_t>,
914 &ClientData::hwaddr_>,
915 boost::multi_index::member<ClientData, std::vector<uint8_t>,
916 &ClientData::clientid_>
917 >
918 >;
919
923 std::vector<uint8_t> hwaddr_;
924 std::vector<uint8_t> clientid_;
926 };
927
930 typedef boost::multi_index_container<
932 boost::multi_index::indexed_by<
933 // First index is a composite index which allows to find a client
934 // by the HW address/client identifier tuple.
936 // Second index allows for counting all clients which are
937 // considered unacked.
938 boost::multi_index::ordered_non_unique<
939 boost::multi_index::member<ConnectingClient4, bool, &ConnectingClient4::unacked_>
940 >
941 >
943
948
952 std::vector<uint8_t> hwaddr_;
953 std::vector<uint8_t> clientid_;
954 int64_t expire_;
955 };
956
959 typedef boost::multi_index_container<
961 boost::multi_index::indexed_by<
963 boost::multi_index::ordered_non_unique<
964 boost::multi_index::member<RejectedClient4, int64_t,
966 >
967 >
969
973};
974
976typedef boost::shared_ptr<CommunicationState4> CommunicationState4Ptr;
977
984public:
985
991 const HAConfigPtr& config);
992
1001 virtual void analyzeMessage(const boost::shared_ptr<dhcp::Pkt>& message);
1002
1008 virtual bool failureDetected() const;
1009
1018 virtual size_t getConnectingClientsCount() const;
1019
1028 virtual size_t getUnackedClientsCount() const;
1029
1030protected:
1031
1039 virtual size_t getRejectedLeaseUpdatesCountInternal();
1040
1053 virtual bool reportRejectedLeaseUpdateInternal(const dhcp::PktPtr& message,
1054 const uint32_t lifetime = 86400);
1055
1065 virtual bool reportSuccessfulLeaseUpdateInternal(const dhcp::PktPtr& message);
1066
1068 virtual void clearRejectedLeaseUpdatesInternal();
1069
1070protected:
1071
1082 virtual void analyzeMessageInternal(const boost::shared_ptr<dhcp::Pkt>& message);
1083
1091 virtual bool failureDetectedInternal() const;
1092
1098 virtual void clearConnectingClients();
1099
1104 template<typename ClientData>
1105 using ClientIdent6 = boost::multi_index::hashed_unique<
1106 boost::multi_index::member<ClientData, std::vector<uint8_t>,
1107 &ClientData::duid_>
1108 >;
1109
1113 std::vector<uint8_t> duid_;
1115 };
1116
1119 typedef boost::multi_index_container<
1121 boost::multi_index::indexed_by<
1122 // First index is for accessing connecting clients by DUID.
1124 // Second index allows for counting all clients which are
1125 // considered unacked.
1126 boost::multi_index::ordered_non_unique<
1127 boost::multi_index::member<ConnectingClient6, bool, &ConnectingClient6::unacked_>
1128 >
1129 >
1131
1136
1140 std::vector<uint8_t> duid_;
1141 int64_t expire_;
1142 };
1143
1146 typedef boost::multi_index_container<
1148 boost::multi_index::indexed_by<
1150 boost::multi_index::ordered_non_unique<
1151 boost::multi_index::member<RejectedClient6, int64_t,
1153 >
1154 >
1156
1160};
1161
1163typedef boost::shared_ptr<CommunicationState6> CommunicationState6Ptr;
1164
1165} // end of namespace isc::ha
1166} // end of namespace isc
1167
1168#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.
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.
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...
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...
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...
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.
virtual void clearRejectedLeaseUpdatesInternal()
Clears rejected client 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.
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::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.
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 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:982
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.