| Kea 3.0.2-git

communication_state.cc
Go to the documentation of this file.
1// Copyright (C) 2018-2025 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#include <config.h>
8
9#include <communication_state.h>
10#include <ha_log.h>
11#include <ha_service_states.h>
12#include <cc/data.h>
13#include <exceptions/exceptions.h>
14#include <dhcp/dhcp4.h>
15#include <dhcp/dhcp6.h>
16#include <dhcp/option_int.h>
17#include <dhcp/pkt4.h>
18#include <dhcp/pkt6.h>
19#include <http/date_time.h>
20#include <util/boost_time_utils.h>
21#include <util/multi_threading_mgr.h>
22
23#include <boost/pointer_cast.hpp>
24
25#include <ctime>
26#include <functional>
27#include <limits>
28#include <sstream>
29#include <utility>
30
31 using namespace isc::asiolink;
32 using namespace isc::data;
33 using namespace isc::dhcp;
34 using namespace isc::http;
35 using namespace isc::log;
36 using namespace isc::util;
37
38 using namespace boost::posix_time;
39 using namespace std;
40
41 namespace {
42
44 constexpr long WARN_CLOCK_SKEW = 30;
45
47 constexpr long TERM_CLOCK_SKEW = 60;
48
50 constexpr long MIN_TIME_SINCE_CLOCK_SKEW_WARN = 60;
51
52}
53
54 namespace isc {
55 namespace ha {
56
57 CommunicationState::CommunicationState(const IOServicePtr& io_service,
58 const HAConfigPtr& config)
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_state_time_(),
62 partner_scopes_(), 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()) {
66}
67
68 CommunicationState::~CommunicationState() {
69 stopHeartbeat();
70}
71
72 void
73 CommunicationState::modifyPokeTime(const long secs) {
74 if (MultiThreadingMgr::instance().getMode()) {
75 std::lock_guard<std::mutex> lk(*mutex_);
76 poke_time_ += boost::posix_time::seconds(secs);
77 } else {
78 poke_time_ += boost::posix_time::seconds(secs);
79 }
80}
81
82 int
83 CommunicationState::getPartnerState() const {
84 if (MultiThreadingMgr::instance().getMode()) {
85 std::lock_guard<std::mutex> lk(*mutex_);
86 return (partner_state_);
87 } else {
88 return (partner_state_);
89 }
90}
91
92 void
93 CommunicationState::setPartnerState(const std::string& state) {
94 if (MultiThreadingMgr::instance().getMode()) {
95 std::lock_guard<std::mutex> lk(*mutex_);
96 setPartnerStateInternal(state);
97 } else {
98 setPartnerStateInternal(state);
99 }
100}
101
102 void
103 CommunicationState::setPartnerUnavailable() {
104 if (MultiThreadingMgr::instance().getMode()) {
105 std::lock_guard<std::mutex> lk(*mutex_);
106 setPartnerStateInternal("unavailable");
107 resetPartnerTimeInternal();
108 } else {
109 setPartnerStateInternal("unavailable");
110 resetPartnerTimeInternal();
111 }
112}
113
114 void
115CommunicationState::setPartnerStateInternal(const std::string& state) {
116 try {
117 auto new_partner_state = stringToState(state);
118 if (new_partner_state != partner_state_) {
119 setCurrentPartnerStateTimeInternal();
120 }
121 partner_state_ = new_partner_state;
122 } catch (...) {
123 isc_throw(BadValue, "unsupported HA partner state returned "
124 << state);
125 }
126}
127
128time_duration
129 CommunicationState::getDurationSincePartnerStateTime() const {
130 ptime now = boost::posix_time::microsec_clock::universal_time();
131 if (MultiThreadingMgr::instance().getMode()) {
132 std::lock_guard<std::mutex> lk(*mutex_);
133 return (now - partner_state_time_);
134 } else {
135 return (now - partner_state_time_);
136 }
137}
138
139 void
140CommunicationState::setCurrentPartnerStateTimeInternal() {
141 partner_state_time_ = boost::posix_time::microsec_clock::universal_time();
142}
143
144std::set<std::string>
145 CommunicationState::getPartnerScopes() const {
146 if (MultiThreadingMgr::instance().getMode()) {
147 std::lock_guard<std::mutex> lk(*mutex_);
148 return (partner_scopes_);
149 } else {
150 return (partner_scopes_);
151 }
152}
153
154 void
155 CommunicationState::setPartnerScopes(ConstElementPtr new_scopes) {
156 if (MultiThreadingMgr::instance().getMode()) {
157 std::lock_guard<std::mutex> lk(*mutex_);
158 setPartnerScopesInternal(new_scopes);
159 } else {
160 setPartnerScopesInternal(new_scopes);
161 }
162}
163
164 void
165CommunicationState::setPartnerScopesInternal(ConstElementPtr new_scopes) {
166 if (!new_scopes || (new_scopes->getType() != Element::list)) {
167 isc_throw(BadValue, "unable to record partner's HA scopes because"
168 " the received value is not a valid JSON list");
169 }
170
171 std::set<std::string> partner_scopes;
172 for (unsigned i = 0; i < new_scopes->size(); ++i) {
173 auto scope = new_scopes->get(i);
174 if (scope->getType() != Element::string) {
175 isc_throw(BadValue, "unable to record partner's HA scopes because"
176 " the received scope value is not a valid JSON string");
177 }
178 auto scope_str = scope->stringValue();
179 if (!scope_str.empty()) {
180 partner_scopes.insert(scope_str);
181 }
182 }
183 partner_scopes_ = partner_scopes;
184}
185
186 void
187 CommunicationState::startHeartbeat(const long interval,
188 const std::function<void()>& heartbeat_impl) {
189 if (MultiThreadingMgr::instance().getMode()) {
190 std::lock_guard<std::mutex> lk(*mutex_);
191 startHeartbeatInternal(interval, heartbeat_impl);
192 } else {
193 startHeartbeatInternal(interval, heartbeat_impl);
194 }
195}
196
197 void
198CommunicationState::startHeartbeatInternal(const long interval,
199 const std::function<void()>& heartbeat_impl) {
200 bool settings_modified = false;
201
202 // If we're setting the heartbeat for the first time, it should
203 // be non-null.
204 if (heartbeat_impl) {
205 settings_modified = true;
206 heartbeat_impl_ = heartbeat_impl;
207
208 } else if (!heartbeat_impl_) {
209 // The heartbeat is re-scheduled but we have no historic implementation
210 // pointer we could re-use. This is a programmatic issue.
211 isc_throw(BadValue, "unable to start heartbeat when pointer"
212 " to the heartbeat implementation is not specified");
213 }
214
215 // If we're setting the heartbeat for the first time, the interval
216 // should be greater than 0.
217 if (interval != 0) {
218 settings_modified |= (interval_ != interval);
219 interval_ = interval;
220
221 } else if (interval_ <= 0) {
222 // The heartbeat is re-scheduled but we have no historic interval
223 // which we could re-use. This is a programmatic issue.
224 heartbeat_impl_ = 0;
225 isc_throw(BadValue, "unable to start heartbeat when interval"
226 " for the heartbeat timer is not specified");
227 }
228
229 if (!timer_) {
230 timer_.reset(new IntervalTimer(io_service_));
231 }
232
233 if (settings_modified) {
234 timer_->setup(heartbeat_impl_, interval_, IntervalTimer::ONE_SHOT);
235 }
236}
237
238 void
239 CommunicationState::stopHeartbeat() {
240 if (MultiThreadingMgr::instance().getMode()) {
241 std::lock_guard<std::mutex> lk(*mutex_);
242 stopHeartbeatInternal();
243 } else {
244 stopHeartbeatInternal();
245 }
246}
247
248 void
249CommunicationState::stopHeartbeatInternal() {
250 if (timer_) {
251 timer_->cancel();
252 timer_.reset();
253 interval_ = 0;
254 heartbeat_impl_ = 0;
255 }
256}
257
258 bool
259 CommunicationState::isHeartbeatRunning() const {
260 if (MultiThreadingMgr::instance().getMode()) {
261 std::lock_guard<std::mutex> lk(*mutex_);
262 return (static_cast<bool>(timer_));
263 } else {
264 return (static_cast<bool>(timer_));
265 }
266}
267
268boost::posix_time::time_duration
269 CommunicationState::updatePokeTime() {
270 if (MultiThreadingMgr::instance().getMode()) {
271 std::lock_guard<std::mutex> lk(*mutex_);
272 return (updatePokeTimeInternal());
273 } else {
274 return (updatePokeTimeInternal());
275 }
276}
277
278boost::posix_time::time_duration
279CommunicationState::updatePokeTimeInternal() {
280 // Remember previous poke time.
281 boost::posix_time::ptime prev_poke_time = poke_time_;
282 // Set poke time to the current time.
283 poke_time_ = boost::posix_time::microsec_clock::universal_time();
284 return (poke_time_ - prev_poke_time);
285}
286
287 void
288 CommunicationState::poke() {
289 if (MultiThreadingMgr::instance().getMode()) {
290 std::lock_guard<std::mutex> lk(*mutex_);
291 pokeInternal();
292 } else {
293 pokeInternal();
294 }
295}
296
297 void
298CommunicationState::pokeInternal() {
299 // Update poke time and compute duration.
300 boost::posix_time::time_duration duration_since_poke = updatePokeTimeInternal();
301
302 // If we have been tracking the DHCP messages directed to the partner,
303 // we need to clear any gathered information because the connection
304 // seems to be (re)established.
305 clearConnectingClients();
306 analyzed_messages_count_ = 0;
307
308 if (timer_) {
309 // Check the duration since last poke. If it is less than a second, we don't
310 // want to reschedule the timer. In order to avoid the overhead of
311 // re-scheduling the timer too frequently we reschedule it only if the
312 // duration is 1s or more. This matches the time resolution for heartbeats.
313 if (duration_since_poke.total_seconds() > 0) {
314 // A poke causes the timer to be re-scheduled to prevent it
315 // from triggering a heartbeat shortly after confirming the
316 // connection is ok.
317 startHeartbeatInternal();
318 }
319 }
320}
321
322int64_t
323 CommunicationState::getDurationInMillisecs() const {
324 if (MultiThreadingMgr::instance().getMode()) {
325 std::lock_guard<std::mutex> lk(*mutex_);
326 return (getDurationInMillisecsInternal());
327 } else {
328 return (getDurationInMillisecsInternal());
329 }
330}
331
332int64_t
333CommunicationState::getDurationInMillisecsInternal() const {
334 ptime now = boost::posix_time::microsec_clock::universal_time();
335 time_duration duration = now - poke_time_;
336 return (duration.total_milliseconds());
337}
338
339 bool
340 CommunicationState::isCommunicationInterrupted() const {
341 return (getDurationInMillisecs() > config_->getMaxResponseDelay());
342}
343
344std::vector<uint8_t>
345 CommunicationState::getClientId(const PktPtr& message,
346 const uint16_t option_type) {
347 std::vector<uint8_t> client_id;
348 OptionPtr opt_client_id = message->getOption(option_type);
349 if (opt_client_id) {
350 client_id = opt_client_id->getData();
351 }
352 return (client_id);
353}
354
355 size_t
356 CommunicationState::getAnalyzedMessagesCount() const {
357 return (analyzed_messages_count_);
358}
359
360 size_t
361 CommunicationState::getRejectedLeaseUpdatesCount() {
362 if (MultiThreadingMgr::instance().getMode()) {
363 std::lock_guard<std::mutex> lk(*mutex_);
364 return (getRejectedLeaseUpdatesCountInternal());
365 } else {
366 return (getRejectedLeaseUpdatesCountInternal());
367 }
368}
369
370 bool
371 CommunicationState::reportRejectedLeaseUpdate(const PktPtr& message,
372 const uint32_t lifetime) {
373 if (MultiThreadingMgr::instance().getMode()) {
374 std::lock_guard<std::mutex> lk(*mutex_);
375 return (reportRejectedLeaseUpdateInternal(message, lifetime));
376 } else {
377 return (reportRejectedLeaseUpdateInternal(message, lifetime));
378 }
379}
380
381 bool
382 CommunicationState::reportSuccessfulLeaseUpdate(const PktPtr& message) {
383 if (MultiThreadingMgr::instance().getMode()) {
384 std::lock_guard<std::mutex> lk(*mutex_);
385 return (reportSuccessfulLeaseUpdateInternal(message));
386 } else {
387 return (reportSuccessfulLeaseUpdateInternal(message));
388 }
389}
390
391 void
392 CommunicationState::clearRejectedLeaseUpdates() {
393 if (MultiThreadingMgr::instance().getMode()) {
394 std::lock_guard<std::mutex> lk(*mutex_);
395 return (clearRejectedLeaseUpdatesInternal());
396 } else {
397 return (clearRejectedLeaseUpdatesInternal());
398 }
399}
400
401 bool
402 CommunicationState::clockSkewShouldWarn() {
403 if (MultiThreadingMgr::instance().getMode()) {
404 std::lock_guard<std::mutex> lk(*mutex_);
405 return (clockSkewShouldWarnInternal());
406 } else {
407 return (clockSkewShouldWarnInternal());
408 }
409}
410
411 bool
412CommunicationState::clockSkewShouldWarnInternal() {
413 // First check if the clock skew is beyond the threshold.
414 if (isClockSkewGreater(WARN_CLOCK_SKEW)) {
415
416 // In order to prevent to frequent warnings we provide a gating mechanism
417 // which doesn't allow for issuing a warning earlier than 60 seconds after
418 // the previous one.
419
420 // Find the current time and the duration since last warning.
421 ptime now = boost::posix_time::microsec_clock::universal_time();
422 time_duration since_warn_duration = now - last_clock_skew_warn_;
423
424 // If the last warning was issued more than 60 seconds ago or it is a
425 // first warning, we need to update the last warning timestamp and return
426 // true to indicate that new warning should be issued.
427 if (last_clock_skew_warn_.is_not_a_date_time() ||
428 (since_warn_duration.total_seconds() > MIN_TIME_SINCE_CLOCK_SKEW_WARN)) {
429 last_clock_skew_warn_ = now;
430 LOG_WARN(ha_logger, HA_HIGH_CLOCK_SKEW)
431 .arg(config_->getThisServerName())
432 .arg(logFormatClockSkewInternal());
433 return (true);
434 }
435 }
436
437 // The warning should not be issued.
438 return (false);
439}
440
441 bool
442 CommunicationState::clockSkewShouldTerminate() {
443 if (MultiThreadingMgr::instance().getMode()) {
444 std::lock_guard<std::mutex> lk(*mutex_);
445 // Issue a warning if the clock skew is greater than 60s.
446 return (clockSkewShouldTerminateInternal());
447 } else {
448 return (clockSkewShouldTerminateInternal());
449 }
450}
451
452 bool
453CommunicationState::clockSkewShouldTerminateInternal() {
454 if (isClockSkewGreater(TERM_CLOCK_SKEW)) {
455 LOG_ERROR(ha_logger, HA_HIGH_CLOCK_SKEW_CAUSED_TERMINATION)
456 .arg(config_->getThisServerName())
457 .arg(logFormatClockSkewInternal());
458 return (true);
459 }
460 return (false);
461}
462
463 bool
464 CommunicationState::rejectedLeaseUpdatesShouldTerminate() {
465 if (MultiThreadingMgr::instance().getMode()) {
466 std::lock_guard<std::mutex> lk(*mutex_);
467 return (rejectedLeaseUpdatesShouldTerminateInternal());
468 } else {
469 return (rejectedLeaseUpdatesShouldTerminateInternal());
470 }
471}
472
473 bool
474CommunicationState::rejectedLeaseUpdatesShouldTerminateInternal() {
475 if (config_->getMaxRejectedLeaseUpdates() &&
476 (config_->getMaxRejectedLeaseUpdates() <= getRejectedLeaseUpdatesCountInternal())) {
477 LOG_ERROR(ha_logger, HA_LEASE_UPDATE_REJECTS_CAUSED_TERMINATION)
478 .arg(config_->getThisServerName());
479 return (true);
480 }
481 return (false);
482}
483
484 bool
485CommunicationState::isClockSkewGreater(const long seconds) const {
486 return ((clock_skew_.total_seconds() > seconds) ||
487 (clock_skew_.total_seconds() < -seconds));
488}
489
490 void
491 CommunicationState::setPartnerTime(const std::string& time_text) {
492 if (MultiThreadingMgr::instance().getMode()) {
493 std::lock_guard<std::mutex> lk(*mutex_);
494 setPartnerTimeInternal(time_text);
495 } else {
496 setPartnerTimeInternal(time_text);
497 }
498}
499
500 void
501CommunicationState::setPartnerTimeInternal(const std::string& time_text) {
502 partner_time_at_skew_ = HttpDateTime().fromRfc1123(time_text).getPtime();
503 my_time_at_skew_ = HttpDateTime().getPtime();
504 clock_skew_ = partner_time_at_skew_ - my_time_at_skew_;
505}
506
507 void
508CommunicationState::resetPartnerTimeInternal() {
509 clock_skew_ = boost::posix_time::time_duration(0, 0, 0, 0);
510 last_clock_skew_warn_ = boost::posix_time::ptime();
511 my_time_at_skew_ = boost::posix_time::ptime();
512 partner_time_at_skew_ = boost::posix_time::ptime();
513}
514
515std::string
516 CommunicationState::logFormatClockSkew() const {
517 if (MultiThreadingMgr::instance().getMode()) {
518 std::lock_guard<std::mutex> lk(*mutex_);
519 return (logFormatClockSkewInternal());
520 } else {
521 return (logFormatClockSkewInternal());
522 }
523}
524
525std::string
526CommunicationState::logFormatClockSkewInternal() const {
527 std::ostringstream os;
528
529 if ((my_time_at_skew_.is_not_a_date_time()) ||
530 (partner_time_at_skew_.is_not_a_date_time())) {
531 // Guard against being called before times have been set.
532 // Otherwise we'll get out-range exceptions.
533 return ("skew not initialized");
534 }
535
536 // Note HttpTime resolution is only to seconds, so we use fractional
537 // precision of zero when logging.
538 os << "my time: " << ptimeToText(my_time_at_skew_, 0)
539 << ", partner's time: " << ptimeToText(partner_time_at_skew_, 0)
540 << ", partner's clock is ";
541
542 if (clock_skew_.total_seconds() == 0) {
543 // Most common case.
544 os << "synchroninzed";
545 } else if (clock_skew_.is_negative()) {
546 // Partner's time is behind our time.
547 os << clock_skew_.invert_sign().total_seconds() << "s behind";
548 } else {
549 // Partner's time is ahead of ours.
550 os << clock_skew_.total_seconds() << "s ahead";
551 }
552
553 return (os.str());
554}
555
556 ElementPtr
557 CommunicationState::getReport() const {
558 auto report = Element::createMap();
559
560 auto in_touch = (getPartnerState() > 0);
561 report->set("in-touch", Element::create(in_touch));
562
563 auto age = in_touch ? static_cast<long long int>(getDurationInMillisecs() / 1000) : 0;
564 report->set("age", Element::create(age));
565
566 try {
567 report->set("last-state", Element::create(stateToString(getPartnerState())));
568
569 } catch (...) {
570 report->set("last-state", Element::create(std::string()));
571 }
572
573 auto list = Element::createList();
574 for (auto const& scope : getPartnerScopes()) {
575 list->add(Element::create(scope));
576 }
577 report->set("last-scopes", list);
578 report->set("communication-interrupted",
579 Element::create(isCommunicationInterrupted()));
580 report->set("connecting-clients", Element::create(static_cast<long long>(getConnectingClientsCount())));
581 report->set("unacked-clients", Element::create(static_cast<long long>(getUnackedClientsCount())));
582
583 long long unacked_clients_left = 0;
584 if (isCommunicationInterrupted() && (config_->getMaxUnackedClients() >= getUnackedClientsCount())) {
585 unacked_clients_left = static_cast<long long>(config_->getMaxUnackedClients() -
586 getUnackedClientsCount() + 1);
587 }
588 report->set("unacked-clients-left", Element::create(unacked_clients_left));
589 report->set("analyzed-packets", Element::create(static_cast<long long>(getAnalyzedMessagesCount())));
590 if (partner_time_at_skew_.is_not_a_date_time()) {
591 report->set("system-time", Element::create());
592 report->set("clock-skew", Element::create());
593 } else {
594 report->set("system-time", Element::create(ptimeToText(partner_time_at_skew_, 0)));
595 report->set("clock-skew", Element::create(clock_skew_.total_seconds()));
596 }
597
598 return (report);
599}
600
601uint64_t
602 CommunicationState::getUnsentUpdateCount() const {
603 if (MultiThreadingMgr::instance().getMode()) {
604 std::lock_guard<std::mutex> lk(*mutex_);
605 return (unsent_update_count_);
606 } else {
607 return (unsent_update_count_);
608 }
609}
610
611 void
612 CommunicationState::increaseUnsentUpdateCount() {
613 if (MultiThreadingMgr::instance().getMode()) {
614 std::lock_guard<std::mutex> lk(*mutex_);
615 increaseUnsentUpdateCountInternal();
616 } else {
617 increaseUnsentUpdateCountInternal();
618 }
619}
620
621 void
622CommunicationState::increaseUnsentUpdateCountInternal() {
623 // Protect against setting the incremented value to zero.
624 // The zero value is reserved for a server startup.
625 if (unsent_update_count_ < std::numeric_limits<uint64_t>::max()) {
626 ++unsent_update_count_;
627 } else {
628 unsent_update_count_ = 1;
629 }
630}
631
632 bool
633 CommunicationState::hasPartnerNewUnsentUpdates() const {
634 if (MultiThreadingMgr::instance().getMode()) {
635 std::lock_guard<std::mutex> lk(*mutex_);
636 return (hasPartnerNewUnsentUpdatesInternal());
637 } else {
638 return (hasPartnerNewUnsentUpdatesInternal());
639 }
640}
641
642 bool
643CommunicationState::hasPartnerNewUnsentUpdatesInternal() const {
644 return (partner_unsent_update_count_.second > 0 &&
645 (partner_unsent_update_count_.first != partner_unsent_update_count_.second));
646}
647
648 void
649 CommunicationState::setPartnerUnsentUpdateCount(uint64_t unsent_update_count) {
650 if (MultiThreadingMgr::instance().getMode()) {
651 std::lock_guard<std::mutex> lk(*mutex_);
652 setPartnerUnsentUpdateCountInternal(unsent_update_count);
653 } else {
654 setPartnerUnsentUpdateCountInternal(unsent_update_count);
655 }
656}
657
658 void
659CommunicationState::setPartnerUnsentUpdateCountInternal(uint64_t unsent_update_count) {
660 partner_unsent_update_count_.first = partner_unsent_update_count_.second;
661 partner_unsent_update_count_.second = unsent_update_count;
662}
663
664boost::posix_time::ptime
665 CommunicationState::getMyTimeAtSkew() const {
666 return my_time_at_skew_;
667}
668
669boost::posix_time::ptime
670 CommunicationState::getPartnerTimeAtSkew() const {
671 return partner_time_at_skew_;
672}
673
674 CommunicationState4::CommunicationState4(const IOServicePtr& io_service,
675 const HAConfigPtr& config)
676 : CommunicationState(io_service, config), connecting_clients_(),
677 rejected_clients_() {
678}
679
680 void
681 CommunicationState4::analyzeMessage(const boost::shared_ptr<dhcp::Pkt>& message) {
682 if (MultiThreadingMgr::instance().getMode()) {
683 std::lock_guard<std::mutex> lk(*mutex_);
684 analyzeMessageInternal(message);
685 } else {
686 analyzeMessageInternal(message);
687 }
688}
689
690 void
691 CommunicationState4::analyzeMessageInternal(const PktPtr& message) {
692 // The DHCP message must successfully cast to a Pkt4 object.
693 Pkt4Ptr msg = boost::dynamic_pointer_cast<Pkt4>(message);
694 if (!msg) {
695 isc_throw(BadValue, "DHCP message to be analyzed is not a DHCPv4 message");
696 }
697
698 ++analyzed_messages_count_;
699
700 // Check value of the "secs" field by comparing it with the configured
701 // threshold.
702 uint16_t secs = msg->getSecs();
703
704 // It was observed that some Windows clients may send swapped bytes in the
705 // "secs" field. When the second byte is 0 and the first byte is non-zero
706 // we consider bytes to be swapped and so we correct them.
707 if ((secs > 255) && ((secs & 0xFF) == 0)) {
708 secs = ((secs >> 8) | (secs << 8));
709 }
710
711 // Check the value of the "secs" field. The "secs" field holds a value in
712 // seconds, hence we have to multiple by 1000 to get a value in milliseconds.
713 // If the secs value is above the threshold, it means that the current
714 // client should be considered unacked.
715 auto unacked = (secs * 1000 > config_->getMaxAckDelay());
716
717 // Client identifier will be stored together with the hardware address. It
718 // may remain empty if the client hasn't specified it.
719 auto client_id = getClientId(message, DHO_DHCP_CLIENT_IDENTIFIER);
720 bool log_unacked = false;
721
722 // Check if the given client was already recorded.
723 auto& idx = connecting_clients_.get<0>();
724 auto existing_request = idx.find(boost::make_tuple(msg->getHWAddr()->hwaddr_, client_id));
725 if (existing_request != idx.end()) {
726 // If the client was recorded and was not considered unacked
727 // but it should be considered unacked as a result of processing
728 // this packet, let's update the recorded request to mark the
729 // client unacked.
730 if (!existing_request->unacked_ && unacked) {
731 ConnectingClient4 connecting_client{ msg->getHWAddr()->hwaddr_, client_id, unacked };
732 idx.replace(existing_request, connecting_client);
733 log_unacked = true;
734 }
735
736 } else {
737 // This is the first time we see the packet from this client. Let's
738 // record it.
739 ConnectingClient4 connecting_client{ msg->getHWAddr()->hwaddr_, client_id, unacked };
740 idx.insert(connecting_client);
741 log_unacked = unacked;
742
743 if (!unacked) {
744 // This is the first time we see this client after getting into the
745 // communication interrupted state. But, this client hasn't been
746 // yet trying log enough to be considered unacked.
747 LOG_INFO(ha_logger, HA_COMMUNICATION_INTERRUPTED_CLIENT4)
748 .arg(config_->getThisServerName())
749 .arg(message->getLabel());
750 }
751 }
752
753 // Only log the first time we detect a client is unacked.
754 if (log_unacked) {
755 unsigned unacked_left = 0;
756 unsigned unacked_total = connecting_clients_.get<1>().count(true);
757 if (config_->getMaxUnackedClients() >= unacked_total) {
758 unacked_left = config_->getMaxUnackedClients() - unacked_total + 1;
759 }
760 LOG_INFO(ha_logger, HA_COMMUNICATION_INTERRUPTED_CLIENT4_UNACKED)
761 .arg(config_->getThisServerName())
762 .arg(message->getLabel())
763 .arg(unacked_total)
764 .arg(unacked_left);
765 }
766}
767
768 bool
769 CommunicationState4::failureDetected() const {
770 if (MultiThreadingMgr::instance().getMode()) {
771 std::lock_guard<std::mutex> lk(*mutex_);
772 return (failureDetectedInternal());
773 } else {
774 return (failureDetectedInternal());
775 }
776}
777
778 bool
779 CommunicationState4::failureDetectedInternal() const {
780 return ((config_->getMaxUnackedClients() == 0) ||
781 (connecting_clients_.get<1>().count(true) >
782 config_->getMaxUnackedClients()));
783}
784
785 size_t
786 CommunicationState4::getConnectingClientsCount() const {
787 if (MultiThreadingMgr::instance().getMode()) {
788 std::lock_guard<std::mutex> lk(*mutex_);
789 return (connecting_clients_.size());
790 } else {
791 return (connecting_clients_.size());
792 }
793}
794
795 size_t
796 CommunicationState4::getUnackedClientsCount() const {
797 if (MultiThreadingMgr::instance().getMode()) {
798 std::lock_guard<std::mutex> lk(*mutex_);
799 return (connecting_clients_.get<1>().count(true));
800 } else {
801 return (connecting_clients_.get<1>().count(true));
802 }
803}
804
805 void
806 CommunicationState4::clearConnectingClients() {
807 connecting_clients_.clear();
808}
809
810 size_t
811 CommunicationState4::getRejectedLeaseUpdatesCountInternal() {
812 return (getRejectedLeaseUpdatesCountFromContainer(rejected_clients_));
813}
814
815 bool
816 CommunicationState4::reportRejectedLeaseUpdateInternal(const PktPtr& message, const uint32_t lifetime) {
817 Pkt4Ptr msg = boost::dynamic_pointer_cast<Pkt4>(message);
818 if (!msg) {
819 isc_throw(BadValue, "DHCP message for which the lease update was rejected is not a DHCPv4 message");
820 }
821 auto client_id = getClientId(message, DHO_DHCP_CLIENT_IDENTIFIER);
822 RejectedClient4 client{ msg->getHWAddr()->hwaddr_, client_id, time(NULL) + lifetime };
823 auto existing_client = rejected_clients_.find(boost::make_tuple(msg->getHWAddr()->hwaddr_, client_id));
824 if (existing_client == rejected_clients_.end()) {
825 rejected_clients_.insert(client);
826 return (true);
827 }
828 rejected_clients_.replace(existing_client, client);
829 return (false);
830}
831
832 bool
833 CommunicationState4::reportSuccessfulLeaseUpdateInternal(const PktPtr& message) {
834 // Early check if there is anything to do.
835 if (getRejectedLeaseUpdatesCountInternal() == 0) {
836 return (false);
837 }
838 Pkt4Ptr msg = boost::dynamic_pointer_cast<Pkt4>(message);
839 if (!msg) {
840 isc_throw(BadValue, "DHCP message for which the lease update was successful is not a DHCPv4 message");
841 }
842 auto client_id = getClientId(msg, DHO_DHCP_CLIENT_IDENTIFIER);
843 auto existing_client = rejected_clients_.find(boost::make_tuple(msg->getHWAddr()->hwaddr_, client_id));
844 if (existing_client != rejected_clients_.end()) {
845 rejected_clients_.erase(existing_client);
846 return (true);
847 }
848 return (false);
849}
850
851 void
852 CommunicationState4::clearRejectedLeaseUpdatesInternal() {
853 rejected_clients_.clear();
854}
855
856 CommunicationState6::CommunicationState6(const IOServicePtr& io_service,
857 const HAConfigPtr& config)
858 : CommunicationState(io_service, config), connecting_clients_(),
859 rejected_clients_() {
860}
861
862 void
863 CommunicationState6::analyzeMessage(const boost::shared_ptr<dhcp::Pkt>& message) {
864 if (MultiThreadingMgr::instance().getMode()) {
865 std::lock_guard<std::mutex> lk(*mutex_);
866 analyzeMessageInternal(message);
867 } else {
868 analyzeMessageInternal(message);
869 }
870}
871
872 void
873 CommunicationState6::analyzeMessageInternal(const boost::shared_ptr<dhcp::Pkt>& message) {
874 // The DHCP message must successfully cast to a Pkt6 object.
875 Pkt6Ptr msg = boost::dynamic_pointer_cast<Pkt6>(message);
876 if (!msg) {
877 isc_throw(BadValue, "DHCP message to be analyzed is not a DHCPv6 message");
878 }
879
880 ++analyzed_messages_count_;
881
882 // Check the value of the "elapsed time" option. If it is below the threshold
883 // there is nothing to do. The "elapsed time" option holds the time in
884 // 1/100 of second, hence we have to multiply by 10 to get a value in milliseconds.
885 OptionUint16Ptr elapsed_time = boost::dynamic_pointer_cast<
886 OptionUint16>(msg->getOption(D6O_ELAPSED_TIME));
887 auto unacked = (elapsed_time && elapsed_time->getValue() * 10 > config_->getMaxAckDelay());
888
889 // Get the DUID of the client to see if it hasn't been recorded already.
890 auto duid = getClientId(msg, D6O_CLIENTID);
891 if (duid.empty()) {
892 return;
893 }
894
895 bool log_unacked = false;
896
897 // Check if the given client was already recorded.
898 auto& idx = connecting_clients_.get<0>();
899 auto existing_request = idx.find(duid);
900 if (existing_request != idx.end()) {
901 // If the client was recorded and was not considered unacked
902 // but it should be considered unacked as a result of processing
903 // this packet, let's update the recorded request to mark the
904 // client unacked.
905 if (!existing_request->unacked_ && unacked) {
906 ConnectingClient6 connecting_client{ duid, unacked };
907 idx.replace(existing_request, connecting_client);
908 log_unacked = true;
909 }
910
911 } else {
912 // This is the first time we see the packet from this client. Let's
913 // record it.
914 ConnectingClient6 connecting_client{ duid, unacked };
915 idx.insert(connecting_client);
916 log_unacked = unacked;
917
918 if (!unacked) {
919 // This is the first time we see this client after getting into the
920 // communication interrupted state. But, this client hasn't been
921 // yet trying log enough to be considered unacked.
922 LOG_INFO(ha_logger, HA_COMMUNICATION_INTERRUPTED_CLIENT6)
923 .arg(config_->getThisServerName())
924 .arg(message->getLabel());
925 }
926 }
927
928 // Only log the first time we detect a client is unacked.
929 if (log_unacked) {
930 unsigned unacked_left = 0;
931 unsigned unacked_total = connecting_clients_.get<1>().count(true);
932 if (config_->getMaxUnackedClients() >= unacked_total) {
933 unacked_left = config_->getMaxUnackedClients() - unacked_total + 1;
934 }
935 LOG_INFO(ha_logger, HA_COMMUNICATION_INTERRUPTED_CLIENT6_UNACKED)
936 .arg(config_->getThisServerName())
937 .arg(message->getLabel())
938 .arg(unacked_total)
939 .arg(unacked_left);
940 }
941}
942
943 bool
944 CommunicationState6::failureDetected() const {
945 if (MultiThreadingMgr::instance().getMode()) {
946 std::lock_guard<std::mutex> lk(*mutex_);
947 return (failureDetectedInternal());
948 } else {
949 return (failureDetectedInternal());
950 }
951}
952
953 bool
954 CommunicationState6::failureDetectedInternal() const {
955 return ((config_->getMaxUnackedClients() == 0) ||
956 (connecting_clients_.get<1>().count(true) >
957 config_->getMaxUnackedClients()));
958}
959
960 size_t
961 CommunicationState6::getConnectingClientsCount() const {
962 if (MultiThreadingMgr::instance().getMode()) {
963 std::lock_guard<std::mutex> lk(*mutex_);
964 return (connecting_clients_.size());
965 } else {
966 return (connecting_clients_.size());
967 }
968}
969
970 size_t
971 CommunicationState6::getUnackedClientsCount() const {
972 if (MultiThreadingMgr::instance().getMode()) {
973 std::lock_guard<std::mutex> lk(*mutex_);
974 return (connecting_clients_.get<1>().count(true));
975 } else {
976 return (connecting_clients_.get<1>().count(true));
977 }
978}
979
980 void
981 CommunicationState6::clearConnectingClients() {
982 connecting_clients_.clear();
983}
984
985 size_t
986 CommunicationState6::getRejectedLeaseUpdatesCountInternal() {
987 return (getRejectedLeaseUpdatesCountFromContainer(rejected_clients_));
988}
989
990 bool
991 CommunicationState6::reportRejectedLeaseUpdateInternal(const PktPtr& message, const uint32_t lifetime) {
992 Pkt6Ptr msg = boost::dynamic_pointer_cast<Pkt6>(message);
993 if (!msg) {
994 isc_throw(BadValue, "DHCP message for which the lease update was rejected is not a DHCPv6 message");
995 }
996 auto duid = getClientId(msg, D6O_CLIENTID);
997 if (duid.empty()) {
998 return (false);
999 }
1000 RejectedClient6 client{ duid, time(NULL) + lifetime };
1001 auto existing_client = rejected_clients_.find(duid);
1002 if (existing_client == rejected_clients_.end()) {
1003 rejected_clients_.insert(client);
1004 return (true);
1005 }
1006 rejected_clients_.replace(existing_client, client);
1007 return (false);
1008}
1009
1010 bool
1011 CommunicationState6::reportSuccessfulLeaseUpdateInternal(const PktPtr& message) {
1012 // Early check if there is anything to do.
1013 if (getRejectedLeaseUpdatesCountInternal() == 0) {
1014 return (false);
1015 }
1016 Pkt6Ptr msg = boost::dynamic_pointer_cast<Pkt6>(message);
1017 if (!msg) {
1018 isc_throw(BadValue, "DHCP message for which the lease update was successful is not a DHCPv6 message");
1019 }
1020 auto duid = getClientId(msg, D6O_CLIENTID);
1021 if (duid.empty()) {
1022 return (false);
1023 }
1024 auto existing_client = rejected_clients_.find(duid);
1025 if (existing_client != rejected_clients_.end()) {
1026 rejected_clients_.erase(existing_client);
1027 return (true);
1028 }
1029 return (false);
1030}
1031
1032 void
1033 CommunicationState6::clearRejectedLeaseUpdatesInternal() {
1034 rejected_clients_.clear();
1035}
1036
1037} // end of namespace isc::ha
1038} // end of namespace isc
boost_time_utils.h
Element::create
static ElementPtr create(const Position &pos=ZERO_POSITION())
Definition data.cc:249
Element::list
@ list
Definition data.h:146
Element::string
@ string
Definition data.h:144
Element::createMap
static ElementPtr createMap(const Position &pos=ZERO_POSITION())
Creates an empty MapElement type ElementPtr.
Definition data.cc:304
Element::createList
static ElementPtr createList(const Position &pos=ZERO_POSITION())
Creates an empty ListElement type ElementPtr.
Definition data.cc:299
isc::BadValue
A generic exception that is thrown if a parameter given to a method is considered invalid in that con...
Definition exceptions/exceptions.h:132
isc::asiolink::IntervalTimer::ONE_SHOT
@ ONE_SHOT
Definition interval_timer.h:63
isc::ha::CommunicationState4::reportRejectedLeaseUpdateInternal
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.
Definition communication_state.cc:816
isc::ha::CommunicationState4::getRejectedLeaseUpdatesCountInternal
virtual size_t getRejectedLeaseUpdatesCountInternal()
Returns the number of lease updates rejected by the partner.
Definition communication_state.cc:811
isc::ha::CommunicationState4::reportSuccessfulLeaseUpdateInternal
virtual bool reportSuccessfulLeaseUpdateInternal(const dhcp::PktPtr &message)
Marks the lease update successful.
Definition communication_state.cc:833
isc::ha::CommunicationState4::getUnackedClientsCount
virtual size_t getUnackedClientsCount() const
Returns the current number of clients which haven't gotten a lease from the partner server.
Definition communication_state.cc:796
isc::ha::CommunicationState4::clearRejectedLeaseUpdatesInternal
virtual void clearRejectedLeaseUpdatesInternal()
Clears rejected client leases.
Definition communication_state.cc:852
isc::ha::CommunicationState4::analyzeMessageInternal
virtual void analyzeMessageInternal(const boost::shared_ptr< dhcp::Pkt > &message)
Checks if the DHCPv4 message appears to be unanswered.
Definition communication_state.cc:691
isc::ha::CommunicationState4::getConnectingClientsCount
virtual size_t getConnectingClientsCount() const
Returns the current number of clients which attempted to get a lease from the partner server.
Definition communication_state.cc:786
isc::ha::CommunicationState4::analyzeMessage
virtual void analyzeMessage(const boost::shared_ptr< dhcp::Pkt > &message)
Checks if the DHCPv4 message appears to be unanswered.
Definition communication_state.cc:681
isc::ha::CommunicationState4::rejected_clients_
RejectedClients4 rejected_clients_
Holds information about the clients for whom lease updates have been rejected by the partner.
Definition communication_state.h:982
isc::ha::CommunicationState4::failureDetectedInternal
virtual bool failureDetectedInternal() const
Checks if the partner failure has been detected based on the DHCP traffic analysis.
Definition communication_state.cc:779
isc::ha::CommunicationState4::connecting_clients_
ConnectingClients4 connecting_clients_
Holds information about the clients attempting to contact the partner server while the servers are in...
Definition communication_state.h:957
isc::ha::CommunicationState4::failureDetected
virtual bool failureDetected() const
Checks if the partner failure has been detected based on the DHCP traffic analysis.
Definition communication_state.cc:769
isc::ha::CommunicationState4::clearConnectingClients
virtual void clearConnectingClients()
Removes information about the clients the partner server should respond to while communication with t...
Definition communication_state.cc:806
isc::ha::CommunicationState4::CommunicationState4
CommunicationState4(const asiolink::IOServicePtr &io_service, const HAConfigPtr &config)
Constructor.
Definition communication_state.cc:674
isc::ha::CommunicationState6::analyzeMessage
virtual void analyzeMessage(const boost::shared_ptr< dhcp::Pkt > &message)
Checks if the DHCPv6 message appears to be unanswered.
Definition communication_state.cc:863
isc::ha::CommunicationState6::rejected_clients_
RejectedClients6 rejected_clients_
Holds information about the clients for whom lease updates have been rejected by the partner.
Definition communication_state.h:1169
isc::ha::CommunicationState6::getRejectedLeaseUpdatesCountInternal
virtual size_t getRejectedLeaseUpdatesCountInternal()
Returns the number of lease updates rejected by the partner.
Definition communication_state.cc:986
isc::ha::CommunicationState6::connecting_clients_
ConnectingClients6 connecting_clients_
Holds information about the clients attempting to contact the partner server while the servers are in...
Definition communication_state.h:1145
isc::ha::CommunicationState6::CommunicationState6
CommunicationState6(const asiolink::IOServicePtr &io_service, const HAConfigPtr &config)
Constructor.
Definition communication_state.cc:856
isc::ha::CommunicationState6::reportSuccessfulLeaseUpdateInternal
virtual bool reportSuccessfulLeaseUpdateInternal(const dhcp::PktPtr &message)
Marks the lease update successful.
Definition communication_state.cc:1011
isc::ha::CommunicationState6::clearConnectingClients
virtual void clearConnectingClients()
Removes information about the clients the partner server should respond to while communication with t...
Definition communication_state.cc:981
isc::ha::CommunicationState6::failureDetected
virtual bool failureDetected() const
Checks if the partner failure has been detected based on the DHCP traffic analysis.
Definition communication_state.cc:944
isc::ha::CommunicationState6::getUnackedClientsCount
virtual size_t getUnackedClientsCount() const
Returns the current number of clients which haven't gotten a lease from the partner server.
Definition communication_state.cc:971
isc::ha::CommunicationState6::failureDetectedInternal
virtual bool failureDetectedInternal() const
Checks if the partner failure has been detected based on the DHCP traffic analysis.
Definition communication_state.cc:954
isc::ha::CommunicationState6::analyzeMessageInternal
virtual void analyzeMessageInternal(const boost::shared_ptr< dhcp::Pkt > &message)
Checks if the DHCPv6 message appears to be unanswered.
Definition communication_state.cc:873
isc::ha::CommunicationState6::reportRejectedLeaseUpdateInternal
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.
Definition communication_state.cc:991
isc::ha::CommunicationState6::getConnectingClientsCount
virtual size_t getConnectingClientsCount() const
Returns the current number of clients which attempted to get a lease from the partner server.
Definition communication_state.cc:961
isc::ha::CommunicationState6::clearRejectedLeaseUpdatesInternal
virtual void clearRejectedLeaseUpdatesInternal()
Clears rejected client leases.
Definition communication_state.cc:1033
isc::ha::CommunicationState::getConnectingClientsCount
virtual size_t getConnectingClientsCount() const =0
Returns the current number of clients which attempted to get a lease from the partner server.
isc::ha::CommunicationState::reportRejectedLeaseUpdateInternal
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.
isc::ha::CommunicationState::partner_state_time_
boost::posix_time::ptime partner_state_time_
Holds a time when partner was first seen in the current state.
Definition communication_state.h:736
isc::ha::CommunicationState::clearRejectedLeaseUpdatesInternal
virtual void clearRejectedLeaseUpdatesInternal()=0
Clears rejected client leases.
isc::ha::CommunicationState::getUnackedClientsCount
virtual size_t getUnackedClientsCount() const =0
Returns the current number of clients which haven't got the lease from the partner server.
isc::ha::CommunicationState::clearConnectingClients
virtual void clearConnectingClients()=0
Removes information about the clients the partner server should respond to while communication with t...
isc::ha::CommunicationState::clearRejectedLeaseUpdates
void clearRejectedLeaseUpdates()
Clears rejected client leases (MT safe).
Definition communication_state.cc:392
isc::ha::CommunicationState::startHeartbeat
void startHeartbeat(const long interval, const std::function< void()> &heartbeat_impl)
Starts recurring heartbeat (public interface).
Definition communication_state.cc:187
isc::ha::CommunicationState::unsent_update_count_
uint64_t unsent_update_count_
Total number of unsent lease updates.
Definition communication_state.h:765
isc::ha::CommunicationState::isCommunicationInterrupted
bool isCommunicationInterrupted() const
Checks if communication with the partner is interrupted.
Definition communication_state.cc:340
isc::ha::CommunicationState::setPartnerScopes
void setPartnerScopes(data::ConstElementPtr new_scopes)
Sets partner scopes.
Definition communication_state.cc:155
isc::ha::CommunicationState::getPartnerState
int getPartnerState() const
Returns last known state of the partner.
Definition communication_state.cc:83
isc::ha::CommunicationState::clockSkewShouldWarn
bool clockSkewShouldWarn()
Issues a warning about high clock skew between the active servers if one is warranted.
Definition communication_state.cc:402
isc::ha::CommunicationState::logFormatClockSkew
std::string logFormatClockSkew() const
Returns current clock skew value in the logger friendly format.
Definition communication_state.cc:516
isc::ha::CommunicationState::setPartnerUnsentUpdateCount
void setPartnerUnsentUpdateCount(uint64_t unsent_update_count)
Saves new total number of unsent lease updates from the partner.
Definition communication_state.cc:649
isc::ha::CommunicationState::setPartnerState
void setPartnerState(const std::string &state)
Sets partner state.
Definition communication_state.cc:93
isc::ha::CommunicationState::clockSkewShouldTerminate
bool clockSkewShouldTerminate()
Indicates whether the HA service should enter "terminated" state as a result of the clock skew exceed...
Definition communication_state.cc:442
isc::ha::CommunicationState::partner_unsent_update_count_
std::pair< uint64_t, uint64_t > partner_unsent_update_count_
Previous and current total number of unsent lease updates from the partner.
Definition communication_state.h:773
isc::ha::CommunicationState::getPartnerScopes
std::set< std::string > getPartnerScopes() const
Returns scopes served by the partner server.
Definition communication_state.cc:145
isc::ha::CommunicationState::~CommunicationState
virtual ~CommunicationState()
Destructor.
Definition communication_state.cc:68
isc::ha::CommunicationState::config_
HAConfigPtr config_
High availability configuration.
Definition communication_state.h:716
isc::ha::CommunicationState::isHeartbeatRunning
bool isHeartbeatRunning() const
Checks if recurring heartbeat is running.
Definition communication_state.cc:259
isc::ha::CommunicationState::getRejectedLeaseUpdatesCountFromContainer
static size_t getRejectedLeaseUpdatesCountFromContainer(RejectedClientsType &rejected_clients)
Extracts the number of lease updates rejected by the partner from the specified container.
Definition communication_state.h:353
isc::ha::CommunicationState::interval_
long interval_
Interval specified for the heartbeat.
Definition communication_state.h:722
isc::ha::CommunicationState::setPartnerUnavailable
void setPartnerUnavailable()
Sets partner state unavailable.
Definition communication_state.cc:103
isc::ha::CommunicationState::stopHeartbeat
void stopHeartbeat()
Stops recurring heartbeat.
Definition communication_state.cc:239
isc::ha::CommunicationState::increaseUnsentUpdateCount
void increaseUnsentUpdateCount()
Increases a total number of unsent lease updates by 1.
Definition communication_state.cc:612
isc::ha::CommunicationState::setPartnerTime
void setPartnerTime(const std::string &time_text)
Provide partner's notion of time so the new clock skew can be calculated.
Definition communication_state.cc:491
isc::ha::CommunicationState::hasPartnerNewUnsentUpdates
bool hasPartnerNewUnsentUpdates() const
Checks if the partner allocated new leases for which it hasn't sent any lease updates.
Definition communication_state.cc:633
isc::ha::CommunicationState::reportSuccessfulLeaseUpdateInternal
virtual bool reportSuccessfulLeaseUpdateInternal(const dhcp::PktPtr &message)=0
Marks the lease update successful.
isc::ha::CommunicationState::io_service_
asiolink::IOServicePtr io_service_
Pointer to the common IO service instance.
Definition communication_state.h:713
isc::ha::CommunicationState::getRejectedLeaseUpdatesCountInternal
virtual size_t getRejectedLeaseUpdatesCountInternal()=0
Returns the number of lease updates rejected by the partner.
isc::ha::CommunicationState::modifyPokeTime
void modifyPokeTime(const long secs)
Modifies poke time by adding seconds to it.
Definition communication_state.cc:73
isc::ha::CommunicationState::mutex_
const boost::scoped_ptr< std::mutex > mutex_
The mutex used to protect internal state.
Definition communication_state.h:776
isc::ha::CommunicationState::getReport
data::ElementPtr getReport() const
Returns the report about current communication state.
Definition communication_state.cc:557
isc::ha::CommunicationState::getPartnerTimeAtSkew
boost::posix_time::ptime getPartnerTimeAtSkew() const
Retrieves the time of the partner node when skew was last calculated.
Definition communication_state.cc:670
isc::ha::CommunicationState::clock_skew_
boost::posix_time::time_duration clock_skew_
Clock skew between the active servers.
Definition communication_state.h:742
isc::ha::CommunicationState::getAnalyzedMessagesCount
size_t getAnalyzedMessagesCount() const
Returns the number of analyzed messages while being in the communications interrupted state.
Definition communication_state.cc:356
isc::ha::CommunicationState::analyzed_messages_count_
size_t analyzed_messages_count_
Total number of analyzed messages to be responded by partner.
Definition communication_state.h:755
isc::ha::CommunicationState::heartbeat_impl_
std::function< void()> heartbeat_impl_
Pointer to the function providing heartbeat implementation.
Definition communication_state.h:728
isc::ha::CommunicationState::poke_time_
boost::posix_time::ptime poke_time_
Last poke time.
Definition communication_state.h:725
isc::ha::CommunicationState::updatePokeTime
boost::posix_time::time_duration updatePokeTime()
Update the poke time and compute the duration.
Definition communication_state.cc:269
isc::ha::CommunicationState::reportSuccessfulLeaseUpdate
bool reportSuccessfulLeaseUpdate(const dhcp::PktPtr &message)
Marks the lease update successful (MT safe).
Definition communication_state.cc:382
isc::ha::CommunicationState::partner_time_at_skew_
boost::posix_time::ptime partner_time_at_skew_
Partner reported time when skew was calculated.
Definition communication_state.h:752
isc::ha::CommunicationState::CommunicationState
CommunicationState(const asiolink::IOServicePtr &io_service, const HAConfigPtr &config)
Constructor.
Definition communication_state.cc:57
isc::ha::CommunicationState::getDurationSincePartnerStateTime
boost::posix_time::time_duration getDurationSincePartnerStateTime() const
Returns the duration since the partner was first seen in the current state.
Definition communication_state.cc:129
isc::ha::CommunicationState::partner_state_
int partner_state_
Last known state of the partner server.
Definition communication_state.h:733
isc::ha::CommunicationState::last_clock_skew_warn_
boost::posix_time::ptime last_clock_skew_warn_
Holds a time when last warning about too high clock skew was issued.
Definition communication_state.h:746
isc::ha::CommunicationState::partner_scopes_
std::set< std::string > partner_scopes_
Last known set of scopes served by the partner server.
Definition communication_state.h:739
isc::ha::CommunicationState::getClientId
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.
Definition communication_state.cc:345
isc::ha::CommunicationState::getUnsentUpdateCount
uint64_t getUnsentUpdateCount() const
Returns a total number of unsent lease updates.
Definition communication_state.cc:602
isc::ha::CommunicationState::rejectedLeaseUpdatesShouldTerminate
bool rejectedLeaseUpdatesShouldTerminate()
Indicates whether the HA service should enter "terminated" state due to excessive number of rejected ...
Definition communication_state.cc:464
isc::ha::CommunicationState::getMyTimeAtSkew
boost::posix_time::ptime getMyTimeAtSkew() const
Retrieves the time of the local node when skew was last calculated.
Definition communication_state.cc:665
isc::ha::CommunicationState::my_time_at_skew_
boost::posix_time::ptime my_time_at_skew_
My time when skew was calculated.
Definition communication_state.h:749
isc::ha::CommunicationState::getDurationInMillisecs
int64_t getDurationInMillisecs() const
Returns duration between the poke time and current time.
Definition communication_state.cc:323
isc::ha::CommunicationState::reportRejectedLeaseUpdate
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).
Definition communication_state.cc:371
isc::ha::CommunicationState::getRejectedLeaseUpdatesCount
size_t getRejectedLeaseUpdatesCount()
Returns the number of lease updates rejected by the partner (MT safe).
Definition communication_state.cc:361
isc::ha::CommunicationState::timer_
asiolink::IntervalTimerPtr timer_
Interval timer triggering heartbeat commands.
Definition communication_state.h:719
isc::ha::CommunicationState::poke
void poke()
Pokes the communication state.
Definition communication_state.cc:288
isc::http::HttpDateTime
This class parses and generates time values used in HTTP.
Definition date_time.h:41
isc::http::HttpDateTime::getPtime
boost::posix_time::ptime getPtime() const
Returns time encapsulated by this class.
Definition date_time.h:59
isc::http::HttpDateTime::fromRfc1123
static HttpDateTime fromRfc1123(const std::string &time_string)
Creates an instance from a string containing time value formatted as specified in RFC 1123.
Definition date_time.cc:45
isc::util::MultiThreadingMgr::instance
static MultiThreadingMgr & instance()
Returns a single instance of Multi Threading Manager.
Definition multi_threading_mgr.cc:25
communication_state.h
data.h
date_time.h
dhcp4.h
dhcp6.h
D6O_CLIENTID
@ D6O_CLIENTID
Definition dhcp6.h:21
D6O_ELAPSED_TIME
@ D6O_ELAPSED_TIME
Definition dhcp6.h:28
exceptions.h
isc_throw
#define isc_throw(type, stream)
A shortcut macro to insert known values into exception arguments.
Definition exceptions/exceptions.h:210
isc::dhcp::OptionUint16
OptionInt< uint16_t > OptionUint16
Definition option_int.h:32
isc::dhcp::OptionUint16Ptr
boost::shared_ptr< OptionUint16 > OptionUint16Ptr
Definition option_int.h:33
ha_log.h
ha_service_states.h
LOG_ERROR
#define LOG_ERROR(LOGGER, MESSAGE)
Macro to conveniently test error output and log it.
Definition macros.h:32
LOG_INFO
#define LOG_INFO(LOGGER, MESSAGE)
Macro to conveniently test info output and log it.
Definition macros.h:20
LOG_WARN
#define LOG_WARN(LOGGER, MESSAGE)
Macro to conveniently test warn output and log it.
Definition macros.h:26
multi_threading_mgr.h
isc::asiolink
Definition addr_utilities.cc:170
isc::asiolink::IOServicePtr
boost::shared_ptr< IOService > IOServicePtr
Defines a smart pointer to an IOService instance.
Definition io_service.h:28
isc::config
Definition command_interpreter.cc:23
isc::data
Definition base_stamped_element.cc:12
isc::data::ConstElementPtr
boost::shared_ptr< const Element > ConstElementPtr
Definition data.h:29
isc::data::ElementPtr
boost::shared_ptr< Element > ElementPtr
Definition data.h:28
isc::dhcp
Definition dhcp4/client_handler.cc:20
isc::dhcp::PktPtr
boost::shared_ptr< isc::dhcp::Pkt > PktPtr
A pointer to either Pkt4 or Pkt6 packet.
Definition pkt.h:998
isc::dhcp::DHO_DHCP_CLIENT_IDENTIFIER
@ DHO_DHCP_CLIENT_IDENTIFIER
Definition dhcp4.h:130
isc::dhcp::Pkt4Ptr
boost::shared_ptr< Pkt4 > Pkt4Ptr
A pointer to Pkt4 object.
Definition pkt4.h:555
isc::dhcp::Pkt6Ptr
boost::shared_ptr< Pkt6 > Pkt6Ptr
A pointer to Pkt6 packet.
Definition pkt6.h:31
isc::dhcp::OptionPtr
boost::shared_ptr< Option > OptionPtr
Definition option.h:37
isc::ha
Definition command_creator.cc:20
isc::ha::HA_COMMUNICATION_INTERRUPTED_CLIENT4_UNACKED
const isc::log::MessageID HA_COMMUNICATION_INTERRUPTED_CLIENT4_UNACKED
Definition ha_messages.h:22
isc::ha::HA_COMMUNICATION_INTERRUPTED_CLIENT6
const isc::log::MessageID HA_COMMUNICATION_INTERRUPTED_CLIENT6
Definition ha_messages.h:23
isc::ha::ha_logger
isc::log::Logger ha_logger("ha-hooks")
Definition ha_log.h:17
isc::ha::HA_HIGH_CLOCK_SKEW_CAUSED_TERMINATION
const isc::log::MessageID HA_HIGH_CLOCK_SKEW_CAUSED_TERMINATION
Definition ha_messages.h:48
isc::ha::HA_LEASE_UPDATE_REJECTS_CAUSED_TERMINATION
const isc::log::MessageID HA_LEASE_UPDATE_REJECTS_CAUSED_TERMINATION
Definition ha_messages.h:85
isc::ha::HAConfigPtr
boost::shared_ptr< HAConfig > HAConfigPtr
Pointer to the High Availability configuration structure.
Definition ha_config.h:37
isc::ha::HA_COMMUNICATION_INTERRUPTED_CLIENT6_UNACKED
const isc::log::MessageID HA_COMMUNICATION_INTERRUPTED_CLIENT6_UNACKED
Definition ha_messages.h:24
isc::ha::stateToString
std::string stateToString(int state)
Returns state name.
Definition ha_service_states.cc:14
isc::ha::HA_COMMUNICATION_INTERRUPTED_CLIENT4
const isc::log::MessageID HA_COMMUNICATION_INTERRUPTED_CLIENT4
Definition ha_messages.h:21
isc::ha::stringToState
int stringToState(const std::string &state_name)
Returns state for a given name.
Definition ha_service_states.cc:49
isc::ha::HA_HIGH_CLOCK_SKEW
const isc::log::MessageID HA_HIGH_CLOCK_SKEW
Definition ha_messages.h:47
isc::http
Definition auth_config.h:19
isc::log
Definition buffer_appender_impl.cc:17
isc::util
Definition time_utils.cc:43
isc::util::ptimeToText
std::string ptimeToText(boost::posix_time::ptime t, size_t fsecs_precision=MAX_FSECS_PRECISION)
Converts ptime structure to text.
Definition boost_time_utils.cc:14
isc
Defines the logger used by the top-level component of kea-lfc.
Definition agent_parser.cc:148
option_int.h
pkt4.h
pkt6.h
isc::ha::CommunicationState4::ConnectingClient4
Structure holding information about the client which has sent the packet being analyzed.
Definition communication_state.h:932
isc::ha::CommunicationState4::RejectedClient4
Structure holding information about the client who has a rejected lease update.
Definition communication_state.h:961
isc::ha::CommunicationState6::ConnectingClient6
Structure holding information about a client which sent a packet being analyzed.
Definition communication_state.h:1122
isc::ha::CommunicationState6::RejectedClient6
Structure holding information about the client who has a rejected lease update.
Definition communication_state.h:1149