Kea  2.3.5-git
communication_state.h
Go to the documentation of this file.
1 // Copyright (C) 2018-2022 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 
109 private:
115  void setPartnerStateInternal(const std::string& state);
116 
117 public:
121  std::set<std::string> getPartnerScopes() const;
122 
126  void setPartnerScopes(data::ConstElementPtr new_scopes);
127 
128 private:
132  void setPartnerScopesInternal(data::ConstElementPtr new_scopes);
133 
134 public:
140  void startHeartbeat(const long interval,
141  const std::function<void()>& heartbeat_impl);
142 
144  void stopHeartbeat();
145 
146 private:
152  void startHeartbeatInternal(const long interval = 0,
153  const std::function<void()>& heartbeat_impl = 0);
154 
156  void stopHeartbeatInternal();
157 
158 public:
162  bool isHeartbeatRunning() const;
163 
169  void poke();
170 
171 private:
177  void pokeInternal();
178 
179 public:
183  int64_t getDurationInMillisecs() const;
184 
193  bool isCommunicationInterrupted() const;
194 
195 protected:
196 
204  static std::vector<uint8_t> getClientId(const dhcp::PktPtr& message,
205  const uint16_t option_type);
206 public:
207 
239  virtual void analyzeMessage(const boost::shared_ptr<dhcp::Pkt>& message) = 0;
240 
246  size_t getAnalyzedMessagesCount() const;
247 
262  virtual bool failureDetected() const = 0;
263 
272  virtual size_t getConnectingClientsCount() const = 0;
273 
282  virtual size_t getUnackedClientsCount() const = 0;
283 
284 protected:
285 
298  virtual void clearConnectingClients() = 0;
299 
300 public:
301 
310 
311 protected:
312 
320  virtual size_t getRejectedLeaseUpdatesCountInternal() = 0;
321 
329  template<typename RejectedClientsType>
330  static size_t getRejectedLeaseUpdatesCountFromContainer(RejectedClientsType& rejected_clients) {
331  if (rejected_clients.empty()) {
332  return (0);
333  }
334  auto& idx = rejected_clients.template get<1>();
335  auto upper_limit = idx.upper_bound(time(NULL));
336  if (upper_limit != idx.end()) {
337  auto lower_limit = idx.cbegin();
338  idx.erase(lower_limit, upper_limit);
339  }
340  return (rejected_clients.size());
341  }
342 
343 public:
344 
357  bool reportRejectedLeaseUpdate(const dhcp::PktPtr& message,
358  const uint32_t lifetime = 86400);
359 
360 protected:
361 
374  virtual bool reportRejectedLeaseUpdateInternal(const dhcp::PktPtr& message,
375  const uint32_t lifetime) = 0;
376 public:
377 
387  bool reportSuccessfulLeaseUpdate(const dhcp::PktPtr& message);
388 
389 protected:
390 
400  virtual bool reportSuccessfulLeaseUpdateInternal(const dhcp::PktPtr& message) = 0;
401 
402 public:
403 
406 
407 protected:
408 
410  virtual void clearRejectedLeaseUpdatesInternal() = 0;
411 
412 public:
413 
436  bool clockSkewShouldWarn();
437 
438 private:
461  bool clockSkewShouldWarnInternal();
462 
463 public:
481 
482 private:
499  bool clockSkewShouldTerminateInternal();
500 
507  bool isClockSkewGreater(const long seconds) const;
508 
509 public:
510 
519 
520 private:
521 
529  bool rejectedLeaseUpdatesShouldTerminateInternal();
530 
531 public:
532 
544  void setPartnerTime(const std::string& time_text);
545 
546 private:
558  void setPartnerTimeInternal(const std::string& time_text);
559 
560 public:
562  std::string logFormatClockSkew() const;
563 
564 private:
566  std::string logFormatClockSkewInternal() const;
567 
568 public:
576  data::ElementPtr getReport() const;
577 
585  void modifyPokeTime(const long secs);
586 
587 private:
588 
594  int64_t getDurationInMillisecsInternal() const;
595 
596 protected:
600  boost::posix_time::time_duration updatePokeTime();
601 
602 private:
608  boost::posix_time::time_duration updatePokeTimeInternal();
609 
610 public:
611 
613  uint64_t getUnsentUpdateCount() const;
614 
627 
628 private:
629 
631  void increaseUnsentUpdateCountInternal();
632 
633 public:
634 
644  bool hasPartnerNewUnsentUpdates() const;
645 
646 private:
647 
652  bool hasPartnerNewUnsentUpdatesInternal() const;
653 
654 public:
655 
660  void setPartnerUnsentUpdateCount(uint64_t unsent_update_count);
661 
662 private:
663 
668  void setPartnerUnsentUpdateCountInternal(uint64_t unsent_update_count);
669 
670 protected:
673 
676 
679 
681  long interval_;
682 
684  boost::posix_time::ptime poke_time_;
685 
687  std::function<void()> heartbeat_impl_;
688 
693 
695  std::set<std::string> partner_scopes_;
696 
698  boost::posix_time::time_duration clock_skew_;
699 
702  boost::posix_time::ptime last_clock_skew_warn_;
703 
705  boost::posix_time::ptime my_time_at_skew_;
706 
708  boost::posix_time::ptime partner_time_at_skew_;
709 
712 
722 
729  std::pair<uint64_t, uint64_t> partner_unsent_update_count_;
730 
732  const boost::scoped_ptr<std::mutex> mutex_;
733 };
734 
736 typedef boost::shared_ptr<CommunicationState> CommunicationStatePtr;
737 
738 
745 public:
746 
752  const HAConfigPtr& config);
753 
768  virtual void analyzeMessage(const boost::shared_ptr<dhcp::Pkt>& message);
769 
775  virtual bool failureDetected() const;
776 
785  virtual size_t getConnectingClientsCount() const;
786 
795  virtual size_t getUnackedClientsCount() const;
796 
797 protected:
798 
806  virtual size_t getRejectedLeaseUpdatesCountInternal();
807 
820  virtual bool reportRejectedLeaseUpdateInternal(const dhcp::PktPtr& message,
821  const uint32_t lifetime);
822 
832  virtual bool reportSuccessfulLeaseUpdateInternal(const dhcp::PktPtr& message);
833 
835  virtual void clearRejectedLeaseUpdatesInternal();
836 
853  virtual void analyzeMessageInternal(const boost::shared_ptr<dhcp::Pkt>& message);
854 
862  virtual bool failureDetectedInternal() const;
863 
869  virtual void clearConnectingClients();
870 
875  template<typename ClientData>
876  using ClientIdent4 = boost::multi_index::hashed_unique<
877  boost::multi_index::composite_key<
878  ClientData,
879  boost::multi_index::member<ClientData, std::vector<uint8_t>,
880  &ClientData::hwaddr_>,
881  boost::multi_index::member<ClientData, std::vector<uint8_t>,
882  &ClientData::clientid_>
883  >
884  >;
885 
889  std::vector<uint8_t> hwaddr_;
890  std::vector<uint8_t> clientid_;
891  bool unacked_;
892  };
893 
896  typedef boost::multi_index_container<
898  boost::multi_index::indexed_by<
899  // First index is a composite index which allows to find a client
900  // by the HW address/client identifier tuple.
902  // Second index allows for counting all clients which are
903  // considered unacked.
904  boost::multi_index::ordered_non_unique<
905  boost::multi_index::member<ConnectingClient4, bool, &ConnectingClient4::unacked_>
906  >
907  >
909 
914 
918  std::vector<uint8_t> hwaddr_;
919  std::vector<uint8_t> clientid_;
920  int64_t expire_;
921  };
922 
925  typedef boost::multi_index_container<
927  boost::multi_index::indexed_by<
929  boost::multi_index::ordered_non_unique<
930  boost::multi_index::member<RejectedClient4, int64_t,
931  &RejectedClient4::expire_>
932  >
933  >
935 
939 };
940 
942 typedef boost::shared_ptr<CommunicationState4> CommunicationState4Ptr;
943 
950 public:
951 
957  const HAConfigPtr& config);
958 
967  virtual void analyzeMessage(const boost::shared_ptr<dhcp::Pkt>& message);
968 
974  virtual bool failureDetected() const;
975 
984  virtual size_t getConnectingClientsCount() const;
985 
994  virtual size_t getUnackedClientsCount() const;
995 
996 protected:
997 
1005  virtual size_t getRejectedLeaseUpdatesCountInternal();
1006 
1019  virtual bool reportRejectedLeaseUpdateInternal(const dhcp::PktPtr& message,
1020  const uint32_t lifetime = 86400);
1021 
1031  virtual bool reportSuccessfulLeaseUpdateInternal(const dhcp::PktPtr& message);
1032 
1034  virtual void clearRejectedLeaseUpdatesInternal();
1035 
1036 protected:
1037 
1048  virtual void analyzeMessageInternal(const boost::shared_ptr<dhcp::Pkt>& message);
1049 
1057  virtual bool failureDetectedInternal() const;
1058 
1064  virtual void clearConnectingClients();
1065 
1070  template<typename ClientData>
1071  using ClientIdent6 = boost::multi_index::hashed_unique<
1072  boost::multi_index::member<ClientData, std::vector<uint8_t>,
1073  &ClientData::duid_>
1074  >;
1075 
1079  std::vector<uint8_t> duid_;
1080  bool unacked_;
1081  };
1082 
1085  typedef boost::multi_index_container<
1087  boost::multi_index::indexed_by<
1088  // First index is for accessing connecting clients by DUID.
1090  // Second index allows for counting all clients which are
1091  // considered unacked.
1092  boost::multi_index::ordered_non_unique<
1093  boost::multi_index::member<ConnectingClient6, bool, &ConnectingClient6::unacked_>
1094  >
1095  >
1097 
1102 
1106  std::vector<uint8_t> duid_;
1107  int64_t expire_;
1108  };
1109 
1112  typedef boost::multi_index_container<
1114  boost::multi_index::indexed_by<
1116  boost::multi_index::ordered_non_unique<
1117  boost::multi_index::member<RejectedClient6, int64_t,
1118  &RejectedClient6::expire_>
1119  >
1120  >
1122 
1126 };
1127 
1129 typedef boost::shared_ptr<CommunicationState6> CommunicationState6Ptr;
1130 
1131 } // end of namespace isc::ha
1132 } // end of namespace isc
1133 
1134 #endif
std::set< std::string > getPartnerScopes() const
Returns scopes served by the partner server.
data::ElementPtr getReport() const
Returns the report about current communication state.
boost::shared_ptr< CommunicationState6 > CommunicationState6Ptr
Pointer to the CommunicationState6 object.
virtual size_t getConnectingClientsCount() const =0
Returns the current number of clients which attempted to get a lease from the partner server...
virtual void clearConnectingClients()=0
Removes information about the clients the partner server should respond to while communication with t...
virtual void clearRejectedLeaseUpdatesInternal()=0
Clears rejected client leases.
int64_t getDurationInMillisecs() const
Returns duration between the poke time and current time.
void setPartnerTime(const std::string &time_text)
Provide partner&#39;s notion of time so the new clock skew can be calculated.
Holds communication state between the two HA peers.
uint64_t getUnsentUpdateCount() const
Returns a total number of unsent lease updates.
boost::shared_ptr< CommunicationState4 > CommunicationState4Ptr
Pointer to the CommunicationState4 object.
void clearRejectedLeaseUpdates()
Clears rejected client leases (MT safe).
RejectedClients6 rejected_clients_
Holds information about the clients for whom lease updates have been rejected by the partner...
ConnectingClients4 connecting_clients_
Holds information about the clients attempting to contact the partner server while the servers are in...
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...
static size_t getRejectedLeaseUpdatesCountFromContainer(RejectedClientsType &rejected_clients)
Extracts the number of lease updates rejected by the partner from the specified container.
size_t getRejectedLeaseUpdatesCount()
Returns the number of lease updates rejected by the partner (MT safe).
boost::shared_ptr< Element > ElementPtr
Definition: data.h:24
bool isCommunicationInterrupted() const
Checks if communication with the partner is interrupted.
std::function< void()> heartbeat_impl_
Pointer to the function providing heartbeat implementation.
asiolink::IOServicePtr io_service_
Pointer to the common IO service instance.
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)...
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.
uint64_t unsent_update_count_
Total number of unsent lease updates.
int getPartnerState() const
Returns last known state of the partner.
bool hasPartnerNewUnsentUpdates() const
Checks if the partner allocated new leases for which it hasn&#39;t sent any lease updates.
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.
Structure holding information about the client who has a rejected lease update.
Structure holding information about a client which sent a packet being analyzed.
boost::posix_time::time_duration updatePokeTime()
Update the poke time and compute the duration.
boost::posix_time::ptime partner_time_at_skew_
Partner reported time when skew was calculated.
Structure holding information about the client who has a rejected lease update.
long interval_
Interval specified for the heartbeat.
std::pair< uint64_t, uint64_t > partner_unsent_update_count_
Previous and current total number of unsent lease updates from the partner.
boost::posix_time::ptime poke_time_
Last poke time.
Holds communication state between DHCPv4 servers.
RejectedClients4 rejected_clients_
Holds information about the clients for whom lease updates have been 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.
int partner_state_
Last known state of the partner server.
const boost::scoped_ptr< std::mutex > mutex_
The mutex used to protect internal state.
bool clockSkewShouldTerminate()
Indicates whether the HA service should enter "terminated" state as a result of the clock skew exceed...
boost::shared_ptr< const Element > ConstElementPtr
Definition: data.h:27
bool isHeartbeatRunning() const
Checks if recurring heartbeat is running.
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_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...
boost::shared_ptr< isc::dhcp::Pkt > PktPtr
A pointer to either Pkt4 or Pkt6 packet.
Definition: pkt.h:853
void stopHeartbeat()
Stops recurring heartbeat.
virtual bool failureDetected() const =0
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...
Defines the logger used by the top-level component of kea-lfc.
void poke()
Pokes the communication state.
bool reportSuccessfulLeaseUpdate(const dhcp::PktPtr &message)
Marks the lease update successful (MT safe).
boost::posix_time::time_duration clock_skew_
Clock skew between the active servers.
void increaseUnsentUpdateCount()
Increases a total number of unsent lease updates by 1.
ConnectingClients6 connecting_clients_
Holds information about the clients attempting to contact the partner server while the servers are in...
boost::posix_time::ptime my_time_at_skew_
My time when skew was calculated.
void setPartnerState(const std::string &state)
Sets partner state.
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.
void startHeartbeat(const long interval, const std::function< void()> &heartbeat_impl)
Starts recurring heartbeat (public interface).
size_t getAnalyzedMessagesCount() const
Returns the number of analyzed messages while being in the communications interrupted state...
std::string logFormatClockSkew() const
Returns current clock skew value in the logger friendly format.
virtual size_t getRejectedLeaseUpdatesCountInternal()=0
Returns the number of lease updates rejected by the partner.
std::set< std::string > partner_scopes_
Last known set of scopes served by the partner server.
virtual ~CommunicationState()
Destructor.
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.
Structure holding information about the client which has sent the packet being analyzed.
bool rejectedLeaseUpdatesShouldTerminate()
Indicates whether the HA service should enter "terminated" state due to excessive number of rejected ...
bool clockSkewShouldWarn()
Issues a warning about high clock skew between the active servers if one is warranted.
boost::posix_time::ptime last_clock_skew_warn_
Holds a time when last warning about too high clock skew was issued.
asiolink::IntervalTimerPtr timer_
Interval timer triggering heartbeat commands.
void setPartnerScopes(data::ConstElementPtr new_scopes)
Sets partner scopes.
virtual size_t getUnackedClientsCount() const =0
Returns the current number of clients which haven&#39;t got the lease from the partner server...
HAConfigPtr config_
High availability configuration.
boost::shared_ptr< CommunicationState > CommunicationStatePtr
Type of the pointer to the CommunicationState object.
virtual bool reportSuccessfulLeaseUpdateInternal(const dhcp::PktPtr &message)=0
Marks the lease update successful.
boost::shared_ptr< HAConfig > HAConfigPtr
Pointer to the High Availability configuration structure.
Definition: ha_config.h:820
void setPartnerUnsentUpdateCount(uint64_t unsent_update_count)
Saves new total number of unsent lease updates from the partner.
size_t analyzed_messages_count_
Total number of analyzed messages to be responded by partner.
Holds communication state between DHCPv6 servers.
CommunicationState(const asiolink::IOServicePtr &io_service, const HAConfigPtr &config)
Constructor.