Kea  2.5.2
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 
34 namespace isc {
35 namespace ha {
36 
83 public:
84 
90  const HAConfigPtr& config);
91 
95  virtual ~CommunicationState();
96 
100  int getPartnerState() const;
101 
107  void setPartnerState(const std::string& state);
108 
115  void setPartnerUnavailable();
116 
117 private:
123  void setPartnerStateInternal(const std::string& state);
124 
125 public:
129  std::set<std::string> getPartnerScopes() const;
130 
134  void setPartnerScopes(data::ConstElementPtr new_scopes);
135 
136 private:
140  void setPartnerScopesInternal(data::ConstElementPtr new_scopes);
141 
142 public:
148  void startHeartbeat(const long interval,
149  const std::function<void()>& heartbeat_impl);
150 
152  void stopHeartbeat();
153 
154 private:
160  void startHeartbeatInternal(const long interval = 0,
161  const std::function<void()>& heartbeat_impl = 0);
162 
164  void stopHeartbeatInternal();
165 
166 public:
170  bool isHeartbeatRunning() const;
171 
177  void poke();
178 
179 private:
185  void pokeInternal();
186 
187 public:
191  int64_t getDurationInMillisecs() const;
192 
201  bool isCommunicationInterrupted() const;
202 
203 protected:
204 
212  static std::vector<uint8_t> getClientId(const dhcp::PktPtr& message,
213  const uint16_t option_type);
214 public:
215 
247  virtual void analyzeMessage(const boost::shared_ptr<dhcp::Pkt>& message) = 0;
248 
254  size_t getAnalyzedMessagesCount() const;
255 
270  virtual bool failureDetected() const = 0;
271 
280  virtual size_t getConnectingClientsCount() const = 0;
281 
290  virtual size_t getUnackedClientsCount() const = 0;
291 
292 protected:
293 
306  virtual void clearConnectingClients() = 0;
307 
308 public:
309 
318 
319 protected:
320 
329 
337  template<typename RejectedClientsType>
338  static size_t getRejectedLeaseUpdatesCountFromContainer(RejectedClientsType& rejected_clients) {
339  if (rejected_clients.empty()) {
340  return (0);
341  }
342  auto& idx = rejected_clients.template get<1>();
343  auto upper_limit = idx.upper_bound(time(NULL));
344  if (upper_limit != idx.end()) {
345  auto lower_limit = idx.cbegin();
346  idx.erase(lower_limit, upper_limit);
347  }
348  return (rejected_clients.size());
349  }
350 
351 public:
352 
365  bool reportRejectedLeaseUpdate(const dhcp::PktPtr& message,
366  const uint32_t lifetime = 86400);
367 
368 protected:
369 
382  virtual bool reportRejectedLeaseUpdateInternal(const dhcp::PktPtr& message,
383  const uint32_t lifetime) = 0;
384 public:
385 
395  bool reportSuccessfulLeaseUpdate(const dhcp::PktPtr& message);
396 
397 protected:
398 
408  virtual bool reportSuccessfulLeaseUpdateInternal(const dhcp::PktPtr& message) = 0;
409 
410 public:
411 
414 
415 protected:
416 
419 
420 public:
421 
444  bool clockSkewShouldWarn();
445 
446 private:
469  bool clockSkewShouldWarnInternal();
470 
471 public:
489 
490 private:
507  bool clockSkewShouldTerminateInternal();
508 
515  bool isClockSkewGreater(const long seconds) const;
516 
517 public:
518 
527 
528 private:
529 
537  bool rejectedLeaseUpdatesShouldTerminateInternal();
538 
539 public:
540 
552  void setPartnerTime(const std::string& time_text);
553 
554 private:
555 
567  void setPartnerTimeInternal(const std::string& time_text);
568 
573  void resetPartnerTimeInternal();
574 
575 public:
577  std::string logFormatClockSkew() const;
578 
579 private:
581  std::string logFormatClockSkewInternal() const;
582 
583 public:
591  data::ElementPtr getReport() const;
592 
600  void modifyPokeTime(const long secs);
601 
602 private:
603 
609  int64_t getDurationInMillisecsInternal() const;
610 
611 protected:
615  boost::posix_time::time_duration updatePokeTime();
616 
617 private:
623  boost::posix_time::time_duration updatePokeTimeInternal();
624 
625 public:
626 
628  uint64_t getUnsentUpdateCount() const;
629 
642 
643 private:
644 
646  void increaseUnsentUpdateCountInternal();
647 
648 public:
649 
659  bool hasPartnerNewUnsentUpdates() const;
660 
661 private:
662 
667  bool hasPartnerNewUnsentUpdatesInternal() const;
668 
669 public:
670 
675  void setPartnerUnsentUpdateCount(uint64_t unsent_update_count);
676 
677 private:
678 
683  void setPartnerUnsentUpdateCountInternal(uint64_t unsent_update_count);
684 
685 protected:
688 
691 
694 
696  long interval_;
697 
699  boost::posix_time::ptime poke_time_;
700 
702  std::function<void()> heartbeat_impl_;
703 
708 
710  std::set<std::string> partner_scopes_;
711 
713  boost::posix_time::time_duration clock_skew_;
714 
717  boost::posix_time::ptime last_clock_skew_warn_;
718 
720  boost::posix_time::ptime my_time_at_skew_;
721 
723  boost::posix_time::ptime partner_time_at_skew_;
724 
727 
737 
744  std::pair<uint64_t, uint64_t> partner_unsent_update_count_;
745 
747  const boost::scoped_ptr<std::mutex> mutex_;
748 };
749 
751 typedef boost::shared_ptr<CommunicationState> CommunicationStatePtr;
752 
753 
760 public:
761 
767  const HAConfigPtr& config);
768 
783  virtual void analyzeMessage(const boost::shared_ptr<dhcp::Pkt>& message);
784 
790  virtual bool failureDetected() const;
791 
800  virtual size_t getConnectingClientsCount() const;
801 
810  virtual size_t getUnackedClientsCount() const;
811 
812 protected:
813 
821  virtual size_t getRejectedLeaseUpdatesCountInternal();
822 
835  virtual bool reportRejectedLeaseUpdateInternal(const dhcp::PktPtr& message,
836  const uint32_t lifetime);
837 
847  virtual bool reportSuccessfulLeaseUpdateInternal(const dhcp::PktPtr& message);
848 
850  virtual void clearRejectedLeaseUpdatesInternal();
851 
868  virtual void analyzeMessageInternal(const boost::shared_ptr<dhcp::Pkt>& message);
869 
877  virtual bool failureDetectedInternal() const;
878 
884  virtual void clearConnectingClients();
885 
890  template<typename ClientData>
891  using ClientIdent4 = boost::multi_index::hashed_unique<
892  boost::multi_index::composite_key<
893  ClientData,
894  boost::multi_index::member<ClientData, std::vector<uint8_t>,
895  &ClientData::hwaddr_>,
896  boost::multi_index::member<ClientData, std::vector<uint8_t>,
897  &ClientData::clientid_>
898  >
899  >;
900 
904  std::vector<uint8_t> hwaddr_;
905  std::vector<uint8_t> clientid_;
906  bool unacked_;
907  };
908 
911  typedef boost::multi_index_container<
913  boost::multi_index::indexed_by<
914  // First index is a composite index which allows to find a client
915  // by the HW address/client identifier tuple.
917  // Second index allows for counting all clients which are
918  // considered unacked.
919  boost::multi_index::ordered_non_unique<
920  boost::multi_index::member<ConnectingClient4, bool, &ConnectingClient4::unacked_>
921  >
922  >
924 
929 
933  std::vector<uint8_t> hwaddr_;
934  std::vector<uint8_t> clientid_;
935  int64_t expire_;
936  };
937 
940  typedef boost::multi_index_container<
942  boost::multi_index::indexed_by<
944  boost::multi_index::ordered_non_unique<
945  boost::multi_index::member<RejectedClient4, int64_t,
947  >
948  >
950 
954 };
955 
957 typedef boost::shared_ptr<CommunicationState4> CommunicationState4Ptr;
958 
965 public:
966 
972  const HAConfigPtr& config);
973 
982  virtual void analyzeMessage(const boost::shared_ptr<dhcp::Pkt>& message);
983 
989  virtual bool failureDetected() const;
990 
999  virtual size_t getConnectingClientsCount() const;
1000 
1009  virtual size_t getUnackedClientsCount() const;
1010 
1011 protected:
1012 
1020  virtual size_t getRejectedLeaseUpdatesCountInternal();
1021 
1034  virtual bool reportRejectedLeaseUpdateInternal(const dhcp::PktPtr& message,
1035  const uint32_t lifetime = 86400);
1036 
1046  virtual bool reportSuccessfulLeaseUpdateInternal(const dhcp::PktPtr& message);
1047 
1049  virtual void clearRejectedLeaseUpdatesInternal();
1050 
1051 protected:
1052 
1063  virtual void analyzeMessageInternal(const boost::shared_ptr<dhcp::Pkt>& message);
1064 
1072  virtual bool failureDetectedInternal() const;
1073 
1079  virtual void clearConnectingClients();
1080 
1085  template<typename ClientData>
1086  using ClientIdent6 = boost::multi_index::hashed_unique<
1087  boost::multi_index::member<ClientData, std::vector<uint8_t>,
1088  &ClientData::duid_>
1089  >;
1090 
1094  std::vector<uint8_t> duid_;
1095  bool unacked_;
1096  };
1097 
1100  typedef boost::multi_index_container<
1102  boost::multi_index::indexed_by<
1103  // First index is for accessing connecting clients by DUID.
1105  // Second index allows for counting all clients which are
1106  // considered unacked.
1107  boost::multi_index::ordered_non_unique<
1108  boost::multi_index::member<ConnectingClient6, bool, &ConnectingClient6::unacked_>
1109  >
1110  >
1112 
1117 
1121  std::vector<uint8_t> duid_;
1122  int64_t expire_;
1123  };
1124 
1127  typedef boost::multi_index_container<
1129  boost::multi_index::indexed_by<
1131  boost::multi_index::ordered_non_unique<
1132  boost::multi_index::member<RejectedClient6, int64_t,
1134  >
1135  >
1137 
1141 };
1142 
1144 typedef boost::shared_ptr<CommunicationState6> CommunicationState6Ptr;
1145 
1146 } // end of namespace isc::ha
1147 } // end of namespace isc
1148 
1149 #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...
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.
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.
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.
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).
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:26
boost::shared_ptr< isc::dhcp::Pkt > PktPtr
A pointer to either Pkt4 or Pkt6 packet.
Definition: pkt.h:864
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:820
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.