Kea 3.1.8
lease_mgr.cc
Go to the documentation of this file.
1// Copyright (C) 2012-2026 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
10#include <dhcp/libdhcp++.h>
11#include <dhcp/option_custom.h>
12#include <dhcpsrv/cfgmgr.h>
13#include <dhcpsrv/dhcpsrv_log.h>
14#include <dhcpsrv/lease_mgr.h>
16#include <dhcpsrv/subnet_id.h>
18#include <stats/stats_mgr.h>
19#include <util/encode/encode.h>
20#include <util/str.h>
22
23#include <boost/algorithm/string.hpp>
24
25#include <algorithm>
26#include <iostream>
27#include <iterator>
28#include <limits>
29#include <map>
30#include <sstream>
31#include <string>
32
33#include <time.h>
34
35using namespace isc::asiolink;
36using namespace isc::config;
37using namespace isc::data;
38using namespace isc::db;
39using namespace isc::dhcp;
40using namespace isc::stats;
41using namespace isc::util;
42using namespace std;
43
44namespace isc {
45namespace dhcp {
46
47LeasePageSize::LeasePageSize(const size_t page_size)
48 : page_size_(page_size) {
49
50 if (page_size_ == 0) {
51 isc_throw(OutOfRange, "page size of retrieved leases must not be 0");
52 }
53
54 if (page_size_ > std::numeric_limits<uint32_t>::max()) {
55 isc_throw(OutOfRange, "page size of retrieved leases must not be greater than "
56 << std::numeric_limits<uint32_t>::max());
57 }
58}
59
62 uint32_t iaid, SubnetID subnet_id) const {
63 Lease6Collection col = getLeases6(type, duid, iaid, subnet_id);
64
65 if (col.size() > 1) {
66 isc_throw(MultipleRecords, "More than one lease found for type "
67 << static_cast<int>(type) << ", duid "
68 << duid.toText() << ", iaid " << iaid
69 << " and subnet-id " << subnet_id);
70 }
71 if (col.empty()) {
72 return (Lease6Ptr());
73 }
74 return (*col.begin());
75}
76
77void
79 using namespace stats;
80
81 StatsMgr& stats_mgr = StatsMgr::instance();
82
84 if (!query) {
86 return;
87 }
88
89 // Zero out the global stats.
90 // Cumulative counters ("reclaimed-declined-addresses", "reclaimed-leases",
91 // "cumulative-assigned-addresses") never get zeroed.
92 int64_t zero = 0;
93
94 stats_mgr.setValue("assigned-addresses", zero);
95
96 stats_mgr.setValue("declined-addresses", zero);
97
98 // Create if it does not exit reclaimed declined leases global stats.
99 if (!stats_mgr.getObservation("reclaimed-declined-addresses")) {
100 stats_mgr.setValue("reclaimed-declined-addresses", zero);
101 }
102
103 // Create if it does not exit reclaimed leases global stats.
104 if (!stats_mgr.getObservation("reclaimed-leases")) {
105 stats_mgr.setValue("reclaimed-leases", zero);
106 }
107
108 // Create if it does not exit cumulative global stats.
109 if (!stats_mgr.getObservation("cumulative-assigned-addresses")) {
110 stats_mgr.setValue("cumulative-assigned-addresses", zero);
111 }
112
113 // Clear subnet level stats. This ensures we don't end up with corner
114 // cases that leave stale values in place.
115 const Subnet4Collection* subnets =
116 CfgMgr::instance().getCurrentCfg()->getCfgSubnets4()->getAll();
117
118 for (auto const& subnet : *subnets) {
119 SubnetID subnet_id = subnet->getID();
120 stats_mgr.setValue(StatsMgr::generateName("subnet", subnet_id,
121 "assigned-addresses"),
122 zero);
123
124 stats_mgr.setValue(StatsMgr::generateName("subnet", subnet_id,
125 "declined-addresses"),
126 zero);
127
128 const std::string name_rec_dec(StatsMgr::generateName("subnet", subnet_id,
129 "reclaimed-declined-addresses"));
130 if (!stats_mgr.getObservation(name_rec_dec)) {
131 stats_mgr.setValue(name_rec_dec, zero);
132 }
133
134 const std::string name_rec(StatsMgr::generateName("subnet", subnet_id,
135 "reclaimed-leases"));
136 if (!stats_mgr.getObservation(name_rec)) {
137 stats_mgr.setValue(name_rec, zero);
138 }
139
140 for (auto const& pool : subnet->getPools(Lease::TYPE_V4)) {
141 const std::string name_aa(StatsMgr::generateName("subnet", subnet_id,
142 StatsMgr::generateName("pool", pool->getID(),
143 "assigned-addresses")));
144 if (!stats_mgr.getObservation(name_aa)) {
145 stats_mgr.setValue(name_aa, zero);
146 }
147
148 const std::string& name_da(StatsMgr::generateName("subnet", subnet_id,
149 StatsMgr::generateName("pool", pool->getID(),
150 "declined-addresses")));
151 if (!stats_mgr.getObservation(name_da)) {
152 stats_mgr.setValue(name_da, zero);
153 }
154
155 const std::string& pname_rec_dec(StatsMgr::generateName("subnet", subnet_id,
156 StatsMgr::generateName("pool", pool->getID(),
157 "reclaimed-declined-addresses")));
158 if (!stats_mgr.getObservation(pname_rec_dec)) {
159 stats_mgr.setValue(pname_rec_dec, zero);
160 }
161
162 const std::string& pname_rec(StatsMgr::generateName("subnet", subnet_id,
163 StatsMgr::generateName("pool", pool->getID(),
164 "reclaimed-leases")));
165 if (!stats_mgr.getObservation(pname_rec)) {
166 stats_mgr.setValue(pname_rec, zero);
167 }
168 }
169 }
170
171 // Get counts per state per subnet. Iterate over the result set
172 // updating the subnet and global values.
173 LeaseStatsRow row;
174 while (query->getNextRow(row)) {
176 // Add to the global value.
177 stats_mgr.addValue("assigned-addresses", row.state_count_);
178
179 // Add to subnet level value.
180 stats_mgr.addValue(StatsMgr::generateName("subnet", row.subnet_id_,
181 "assigned-addresses"),
182 row.state_count_);
183 } else if (row.lease_state_ == Lease::STATE_DECLINED) {
184 // Set subnet level value.
185 stats_mgr.setValue(StatsMgr::generateName("subnet", row.subnet_id_,
186 "declined-addresses"),
187 row.state_count_);
188
189 // Add to the global value.
190 stats_mgr.addValue("assigned-addresses", row.state_count_);
191
192 // Add to the global value.
193 stats_mgr.addValue("declined-addresses", row.state_count_);
194
195 // Add to subnet level value.
196 // Declined leases also count as assigned.
197 stats_mgr.addValue(StatsMgr::generateName("subnet", row.subnet_id_,
198 "assigned-addresses"),
199 row.state_count_);
200 }
201 }
202
204 if (!query) {
206 return;
207 }
208
209 // Get counts per state per subnet and pool. Iterate over the result set
210 // updating the subnet and pool and global values.
211 while (query->getNextRow(row)) {
213 // Add to subnet and pool level value.
214 stats_mgr.addValue(StatsMgr::generateName("subnet", row.subnet_id_,
216 "assigned-addresses")),
217 row.state_count_);
218 } else if (row.lease_state_ == Lease::STATE_DECLINED) {
219 // Set subnet and pool level value.
220 stats_mgr.setValue(StatsMgr::generateName("subnet", row.subnet_id_,
222 "declined-addresses")),
223 row.state_count_);
224
225 // Add to subnet and pool level value.
226 // Declined leases also count as assigned.
227 stats_mgr.addValue(StatsMgr::generateName("subnet", row.subnet_id_,
229 "assigned-addresses")),
230 row.state_count_);
231 }
232 }
233}
234
236 : first_subnet_id_(0), last_subnet_id_(0), select_mode_(select_mode) {
237 if (select_mode != ALL_SUBNETS && select_mode != ALL_SUBNET_POOLS) {
238 isc_throw(BadValue, "LeaseStatsQuery: mode must be either ALL_SUBNETS or ALL_SUBNET_POOLS");
239 }
240}
241
243 : first_subnet_id_(subnet_id), last_subnet_id_(0),
244 select_mode_(SINGLE_SUBNET) {
245
246 if (first_subnet_id_ == 0) {
247 isc_throw(BadValue, "LeaseStatsQuery: subnet_id_ must be > 0");
248 }
249}
250
252 const SubnetID& last_subnet_id)
253 : first_subnet_id_(first_subnet_id), last_subnet_id_(last_subnet_id),
254 select_mode_(SUBNET_RANGE) {
255
256 if (first_subnet_id_ == 0) {
257 isc_throw(BadValue, "LeaseStatsQuery: first_subnet_id_ must be > 0");
258 }
259
260 if (last_subnet_id_ == 0) {
261 isc_throw(BadValue, "LeaseStatsQuery: last_subnet_id_ must be > 0");
262 }
263
266 "LeaseStatsQuery: last_subnet_id_must be > first_subnet_id_");
267 }
268}
269
274
279
282 return(LeaseStatsQueryPtr());
283}
284
287 const SubnetID& /* last_subnet_id */) {
288 return(LeaseStatsQueryPtr());
289}
290
291bool
293 return (false);
294}
295
296void
298 using namespace stats;
299
300 StatsMgr& stats_mgr = StatsMgr::instance();
301
303 if (!query) {
305 return;
306 }
307
308 // Zero out the global stats.
309 // Cumulative counters ("reclaimed-declined-addresses", "reclaimed-leases",
310 // "cumulative-assigned-nas", "cumulative-assigned-pds",
311 // "cumulative-registered-nas")) never get zeroed.
312 int64_t zero = 0;
313
314 stats_mgr.setValue("assigned-nas", zero);
315
316 stats_mgr.setValue("assigned-pds", zero);
317
318 stats_mgr.setValue("declined-addresses", zero);
319
320 if (!stats_mgr.getObservation("reclaimed-declined-addresses")) {
321 stats_mgr.setValue("reclaimed-declined-addresses", zero);
322 }
323
324 if (!stats_mgr.getObservation("reclaimed-leases")) {
325 stats_mgr.setValue("reclaimed-leases", zero);
326 }
327
328 // Create if it does not exit cumulative nas global stats.
329 if (!stats_mgr.getObservation("cumulative-assigned-nas")) {
330 stats_mgr.setValue("cumulative-assigned-nas", zero);
331 }
332
333 // Create if it does not exit cumulative pds global stats.
334 if (!stats_mgr.getObservation("cumulative-assigned-pds")) {
335 stats_mgr.setValue("cumulative-assigned-pds", zero);
336 }
337
338 // Create if it does not exit cumulative registered nas global stats.
339 if (!stats_mgr.getObservation("cumulative-registered-nas")) {
340 stats_mgr.setValue("cumulative-registered-nas", zero);
341 }
342
343 // Clear subnet level stats. This ensures we don't end up with corner
344 // cases that leave stale values in place.
345 const Subnet6Collection* subnets =
346 CfgMgr::instance().getCurrentCfg()->getCfgSubnets6()->getAll();
347
348 for (auto const& subnet : *subnets) {
349 SubnetID subnet_id = subnet->getID();
350 stats_mgr.setValue(StatsMgr::generateName("subnet", subnet_id,
351 "assigned-nas"),
352 zero);
353
354 stats_mgr.setValue(StatsMgr::generateName("subnet", subnet_id,
355 "assigned-pds"),
356 zero);
357
358 stats_mgr.setValue(StatsMgr::generateName("subnet", subnet_id,
359 "declined-addresses"),
360 zero);
361
362 if (!stats_mgr.getObservation(
363 StatsMgr::generateName("subnet", subnet_id,
364 "reclaimed-declined-addresses"))) {
365 stats_mgr.setValue(
366 StatsMgr::generateName("subnet", subnet_id,
367 "reclaimed-declined-addresses"),
368 zero);
369 }
370
371 if (!stats_mgr.getObservation(
372 StatsMgr::generateName("subnet", subnet_id,
373 "reclaimed-leases"))) {
374 stats_mgr.setValue(
375 StatsMgr::generateName("subnet", subnet_id,
376 "reclaimed-leases"),
377 zero);
378 }
379
380 if (!stats_mgr.getObservation(
381 StatsMgr::generateName("subnet", subnet_id,
382 "registered-nas"))) {
383 stats_mgr.setValue(
384 StatsMgr::generateName("subnet", subnet_id,
385 "registered-nas"),
386 zero);
387 }
388
389 for (auto const& pool : subnet->getPools(Lease::TYPE_NA)) {
390 const std::string& name_anas(StatsMgr::generateName("subnet", subnet_id,
391 StatsMgr::generateName("pool", pool->getID(),
392 "assigned-nas")));
393 if (!stats_mgr.getObservation(name_anas)) {
394 stats_mgr.setValue(name_anas, zero);
395 }
396
397 const std::string& name_da(StatsMgr::generateName("subnet", subnet_id,
398 StatsMgr::generateName("pool", pool->getID(),
399 "declined-addresses")));
400 if (!stats_mgr.getObservation(name_da)) {
401 stats_mgr.setValue(name_da, zero);
402 }
403
404 const std::string name_rec_dec(StatsMgr::generateName("subnet", subnet_id,
405 StatsMgr::generateName("pool", pool->getID(),
406 "reclaimed-declined-addresses")));
407 if (!stats_mgr.getObservation(name_rec_dec)) {
408 stats_mgr.setValue(name_rec_dec, zero);
409 }
410
411 const std::string& name_rec(StatsMgr::generateName("subnet", subnet_id,
412 StatsMgr::generateName("pool", pool->getID(),
413 "reclaimed-leases")));
414 if (!stats_mgr.getObservation(name_rec)) {
415 stats_mgr.setValue(name_rec, zero);
416 }
417 }
418
419 for (auto const& pool : subnet->getPools(Lease::TYPE_PD)) {
420 const std::string& name_apds(StatsMgr::generateName("subnet", subnet_id,
421 StatsMgr::generateName("pd-pool", pool->getID(),
422 "assigned-pds")));
423 if (!stats_mgr.getObservation(name_apds)) {
424 stats_mgr.setValue(name_apds, zero);
425 }
426
427 const std::string& name_rec(StatsMgr::generateName("subnet", subnet_id,
428 StatsMgr::generateName("pd-pool", pool->getID(),
429 "reclaimed-leases")));
430 if (!stats_mgr.getObservation(name_rec)) {
431 stats_mgr.setValue(name_rec, zero);
432 }
433 }
434 }
435
436 // Get counts per state per subnet. Iterate over the result set
437 // updating the subnet and global values.
438 LeaseStatsRow row;
439 while (query->getNextRow(row)) {
440 switch(row.lease_type_) {
441 case Lease::TYPE_NA:
443 // Add to the global value.
444 stats_mgr.addValue("assigned-nas", row.state_count_);
445
446 // Add to subnet level value.
447 stats_mgr.addValue(StatsMgr::generateName("subnet", row.subnet_id_,
448 "assigned-nas"),
449 row.state_count_);
450 } else if (row.lease_state_ == Lease::STATE_DECLINED) {
451 // Set subnet level value.
452 stats_mgr.setValue(StatsMgr::generateName("subnet", row.subnet_id_,
453 "declined-addresses"),
454 row.state_count_);
455
456 // Add to the global value.
457 stats_mgr.addValue("assigned-nas", row.state_count_);
458
459 // Add to the global value.
460 stats_mgr.addValue("declined-addresses", row.state_count_);
461
462 // Add to subnet level value.
463 // Declined leases also count as assigned.
464 stats_mgr.addValue(StatsMgr::generateName("subnet", row.subnet_id_,
465 "assigned-nas"),
466 row.state_count_);
467 } else if (row.lease_state_ == Lease::STATE_REGISTERED) {
468 // Add to subnet level value
469 stats_mgr.addValue(StatsMgr::generateName("subnet", row.subnet_id_,
470 "registered-nas"),
471 row.state_count_);
472 }
473 break;
474
475 case Lease::TYPE_PD:
477 // Add to the global value.
478 stats_mgr.addValue("assigned-pds", row.state_count_);
479
480 // Set subnet level value.
481 stats_mgr.setValue(StatsMgr::generateName("subnet", row.subnet_id_,
482 "assigned-pds"),
483 row.state_count_);
484 }
485 break;
486
487 default:
488 // We don't support TYPE_TAs yet
489 break;
490 }
491 }
492
494 if (!query) {
496 return;
497 }
498
499 // Get counts per state per subnet and pool. Iterate over the result set
500 // updating the subnet and pool and global values.
501 while (query->getNextRow(row)) {
502 switch(row.lease_type_) {
503 case Lease::TYPE_NA:
505 // Add to subnet and pool level value.
506 stats_mgr.addValue(StatsMgr::generateName("subnet", row.subnet_id_,
508 "assigned-nas")),
509 row.state_count_);
510 } else if (row.lease_state_ == Lease::STATE_DECLINED) {
511 // Set subnet and pool level value.
512 stats_mgr.setValue(StatsMgr::generateName("subnet", row.subnet_id_,
514 "declined-addresses")),
515 row.state_count_);
516
517 // Add to subnet and pool level value.
518 // Declined leases also count as assigned.
519 stats_mgr.addValue(StatsMgr::generateName("subnet", row.subnet_id_,
521 "assigned-nas")),
522 row.state_count_);
523 }
524 break;
525
526 case Lease::TYPE_PD:
528 // Set subnet and pool level value.
529 stats_mgr.setValue(StatsMgr::generateName("subnet", row.subnet_id_,
530 StatsMgr::generateName("pd-pool", row.pool_id_,
531 "assigned-pds")),
532 row.state_count_);
533 }
534 break;
535
536 default:
537 // We don't support TYPE_TAs yet
538 break;
539 }
540 }
541}
542
547
552
555 return(LeaseStatsQueryPtr());
556}
557
560 const SubnetID& /* last_subnet_id */) {
561 return(LeaseStatsQueryPtr());
562}
563
564std::string
566 isc_throw(NotImplemented, "LeaseMgr::getDBVersion() called");
567}
568
569void
571 std::string extended_info_tables;
572 try {
573 extended_info_tables = parameters.at("extended-info-tables");
574 } catch (const exception&) {
575 extended_info_tables = "false";
576 }
577 // If extended_info_tables is 'true' we will enable them.
578 if (extended_info_tables == "true") {
580 }
581}
582
583bool
587
588 bool changed = false;
589 if (!lease) {
590 return (changed);
591 }
592
594 return (changed);
595 }
596
597 ConstElementPtr user_context = lease->getContext();
598 if (!user_context) {
599 return (changed);
600 }
601
603 ConstElementPtr extended_info;
604 ElementPtr mutable_user_context;
605 ElementPtr mutable_isc;
606 string verifying = "";
607 bool removed_extended_info = false;
608
609 try {
610 verifying = "user context";
611 if (user_context->getType() != Element::map) {
612 isc_throw(BadValue, "user context is not a map");
613 }
614 if (user_context->empty()) {
615 changed = true;
616 lease->setContext(ConstElementPtr());
617 return (changed);
618 }
619
620 verifying = "isc";
621 isc = user_context->get("ISC");
622 if (!isc) {
623 return (changed);
624 }
625 mutable_user_context =
626 boost::const_pointer_cast<Element>(user_context);
627 if (!mutable_user_context) {
628 // Should not happen...
629 mutable_user_context = copy(user_context, 0);
630 lease->setContext(mutable_user_context);
631 }
632
633 if (isc->getType() != Element::map) {
634 isc_throw(BadValue, "ISC entry is not a map");
635 }
636 if (isc->empty()) {
637 changed = true;
638 mutable_user_context->remove("ISC");
639 if (mutable_user_context->empty()) {
640 lease->setContext(ConstElementPtr());
641 }
642 return (changed);
643 }
644
645 verifying = "relay-agent-info";
646 extended_info = isc->get("relay-agent-info");
647 if (!extended_info) {
648 return (changed);
649 }
650 mutable_isc = boost::const_pointer_cast<Element>(isc);
651 if (!mutable_isc) {
652 // Should not happen...
653 mutable_isc = copy(isc, 0);
654 mutable_user_context->set("ISC", mutable_isc);
655 }
656
657 if (extended_info->getType() == Element::string) {
658 // Upgrade
659 changed = true;
660 ElementPtr upgraded = Element::createMap();
661 upgraded->set("sub-options", extended_info);
662 mutable_isc->set("relay-agent-info", upgraded);
663
664 // Try to decode sub-options.
665 verifying = "rai";
666 string rai_hex = extended_info->stringValue();
667 vector<uint8_t> rai_data;
668 str::decodeFormattedHexString(rai_hex, rai_data);
669 OptionCustomPtr rai(new OptionCustom(rai_def, Option::V4, rai_data));
670 if (!rai) {
671 isc_throw(BadValue, "can't create RAI option");
672 }
673
674 OptionPtr remote_id = rai->getOption(RAI_OPTION_REMOTE_ID);
675 if (remote_id) {
676 vector<uint8_t> bytes = remote_id->toBinary();
677 if (bytes.size() > 0) {
678 upgraded->set("remote-id",
680 }
681 }
682
683 OptionPtr relay_id = rai->getOption(RAI_OPTION_RELAY_ID);
684 if (relay_id) {
685 vector<uint8_t> bytes = relay_id->toBinary(false);
686 if (bytes.size() > 0) {
687 upgraded->set("relay-id",
689 }
690 }
691
694 .arg(lease->addr_.toText());
695 return (changed);
696 } else if (extended_info->getType() != Element::map) {
697 mutable_isc->remove("relay-agent-info");
698 removed_extended_info = true;
699 isc_throw(BadValue, "relay-agent-info is not a map or a string");
700 }
701
703 return (changed);
704 }
705
706 // Try to decode sub-options.
707 ConstElementPtr sub_options = extended_info->get("sub-options");
708 if (sub_options) {
709 verifying = "sub-options";
710 if (sub_options->getType() != Element::string) {
711 mutable_isc->remove("relay-agent-info");
712 removed_extended_info = true;
713 isc_throw(BadValue, "sub-options is not a string");
714 }
715 string rai_hex = sub_options->stringValue();
716 vector<uint8_t> rai_data;
717 str::decodeFormattedHexString(rai_hex, rai_data);
718 }
719
720 ConstElementPtr remote_id = extended_info->get("remote-id");
721 if (remote_id) {
722 verifying = "remote-id";
723 if (remote_id->getType() != Element::string) {
724 mutable_isc->remove("relay-agent-info");
725 removed_extended_info = true;
726 isc_throw(BadValue, "remote-id is not a string");
727 }
728 string remote_id_hex = remote_id->stringValue();
729 vector<uint8_t> remote_id_data;
730 encode::decodeHex(remote_id_hex, remote_id_data);
731 if (remote_id_data.empty()) {
732 mutable_isc->remove("relay-agent-info");
733 removed_extended_info = true;
734 isc_throw(BadValue, "remote-id is empty");
735 }
736 }
737
738 ConstElementPtr relay_id = extended_info->get("relay-id");
739 if (relay_id) {
740 verifying = "relay-id";
741 if (relay_id->getType() != Element::string) {
742 mutable_isc->remove("relay-agent-info");
743 removed_extended_info = true;
744 isc_throw(BadValue, "relay-id is not a string");
745 }
746 string relay_id_hex = relay_id->stringValue();
747 vector<uint8_t> relay_id_data;
748 encode::decodeHex(relay_id_hex, relay_id_data);
749 if (relay_id_data.empty()) {
750 mutable_isc->remove("relay-agent-info");
751 removed_extended_info = true;
752 isc_throw(BadValue, "relay-id is empty");
753 }
754 }
755
757 return (changed);
758 }
759
760 verifying = "relay-agent-info";
761 for (auto const& elem : extended_info->mapValue()) {
762 if ((elem.first != "sub-options") &&
763 (elem.first != "remote-id") &&
764 (elem.first != "relay-id") &&
765 (elem.first != "comment")) {
766 mutable_isc->remove("relay-agent-info");
767 removed_extended_info = true;
768 isc_throw(BadValue, "spurious '" << elem.first <<
769 "' entry in relay-agent-info");
770 }
771 }
772
773 return (changed);
774 } catch (const exception& ex) {
775 ostringstream err;
776 err << "in " << verifying << " a problem was found: " << ex.what();
778 .arg(lease->addr_.toText())
779 .arg(err.str());
780
781 changed = true;
782 if (verifying == "user context") {
783 lease->setContext(ConstElementPtr());
784 } else if (verifying == "isc") {
785 mutable_user_context->remove("ISC");
786 if (mutable_user_context->empty()) {
787 lease->setContext(ConstElementPtr());
788 }
789 } else {
790 if (!removed_extended_info) {
791 mutable_isc->remove("relay-agent-info");
792 }
793 if (mutable_isc->empty()) {
794 mutable_user_context->remove("ISC");
795 if (mutable_user_context->empty()) {
796 lease->setContext(ConstElementPtr());
797 }
798 }
799 }
800 return (changed);
801 }
802}
803
804bool
807 bool changed = false;
808 if (!lease) {
809 return (changed);
810 }
811
813 return (changed);
814 }
815
816 ConstElementPtr user_context = lease->getContext();
817 if (!user_context) {
818 return (changed);
819 }
820
822 ConstElementPtr relay_info;
823 ElementPtr mutable_user_context;
824 ElementPtr mutable_isc;
825 string verifying = "";
826 bool removed_relay_info = false;
827 bool upgraded = false;
828 bool have_both = false;
829 int i = -1;
830
831 try {
832 verifying = "user context";
833 if (user_context->getType() != Element::map) {
834 isc_throw(BadValue, "user context is not a map");
835 }
836 if (user_context->empty()) {
837 changed = true;
838 lease->setContext(ConstElementPtr());
839 return (changed);
840 }
841
842 verifying = "isc";
843 isc = user_context->get("ISC");
844 if (!isc) {
845 return (changed);
846 }
847 mutable_user_context =
848 boost::const_pointer_cast<Element>(user_context);
849 if (!mutable_user_context) {
850 // Should not happen...
851 mutable_user_context = copy(user_context, 0);
852 lease->setContext(mutable_user_context);
853 }
854
855 if (isc->getType() != Element::map) {
856 isc_throw(BadValue, "ISC entry is not a map");
857 }
858 if (isc->empty()) {
859 changed = true;
860 mutable_user_context->remove("ISC");
861 if (mutable_user_context->empty()) {
862 lease->setContext(ConstElementPtr());
863 }
864 return (changed);
865 }
866 mutable_isc = boost::const_pointer_cast<Element>(isc);
867 if (!mutable_isc) {
868 // Should not happen...
869 mutable_isc = copy(isc, 0);
870 mutable_user_context->set("ISC", mutable_isc);
871 }
872
873 relay_info = mutable_isc->get("relays");
874 if (relay_info && isc->contains("relay-info")) {
875 changed = true;
876 mutable_isc->remove("relays");
877 have_both = true;
878 relay_info.reset();
879 }
880 if (relay_info) {
881 // Upgrade
882 changed = true;
883 upgraded = true;
884 verifying = "relays";
885 mutable_isc->set("relay-info", relay_info);
886 mutable_isc->remove("relays");
887
888 if (relay_info->getType() != Element::list) {
889 mutable_isc->remove("relay-info");
890 removed_relay_info = true;
891 isc_throw(BadValue, "relays is not a list");
892 }
893 if (relay_info->empty()) {
894 mutable_isc->remove("relay-info");
895 removed_relay_info = true;
896 isc_throw(BadValue, "relays is empty");
897 }
898
899 verifying = "relay";
900 for (i = 0; static_cast<size_t>(i) < relay_info->size(); ++i) {
901 ElementPtr relay = relay_info->getNonConst(i);
902 if (!relay) {
903 mutable_isc->remove("relay-info");
904 removed_relay_info = true;
905 isc_throw(BadValue, "null relay#" << i);
906 }
907 if (relay->getType() != Element::map) {
908 mutable_isc->remove("relay-info");
909 removed_relay_info = true;
910 isc_throw(BadValue, "relay#" << i << " is not a map");
911 }
912
913 // Try to decode options.
914 ConstElementPtr options = relay->get("options");
915 if (!options) {
916 continue;
917 }
918
919 verifying = "options";
920 if (options->getType() != Element::string) {
921 mutable_isc->remove("relay-info");
922 removed_relay_info = true;
923 isc_throw(BadValue, "options is not a string");
924 }
925 string options_hex = options->stringValue();
926 vector<uint8_t> options_data;
927 str::decodeFormattedHexString(options_hex, options_data);
928 OptionCollection opts;
929 LibDHCP::unpackOptions6(options_data, DHCP6_OPTION_SPACE, opts);
930
931 auto remote_id_it = opts.find(D6O_REMOTE_ID);
932 if (remote_id_it != opts.end()) {
933 OptionPtr remote_id = remote_id_it->second;
934 if (remote_id) {
935 vector<uint8_t> bytes = remote_id->toBinary();
936 if (bytes.size() > 0) {
937 relay->set("remote-id",
939 }
940 }
941 }
942
943 auto relay_id_it = opts.find(D6O_RELAY_ID);
944 if (relay_id_it != opts.end()) {
945 OptionPtr relay_id = relay_id_it->second;
946 if (relay_id) {
947 vector<uint8_t> bytes = relay_id->toBinary(false);
948 if (bytes.size() > 0) {
949 relay->set("relay-id",
951 }
952 }
953 }
954 }
955 }
956
957 verifying = (upgraded ? "relays" : "relay-info");
958 i = -1;
959 relay_info = mutable_isc->get("relay-info");
960 if (!relay_info) {
961 return (changed);
962 }
963 if (!upgraded && (relay_info->getType() != Element::list)) {
964 mutable_isc->remove("relay-info");
965 removed_relay_info = true;
966 isc_throw(BadValue, "relay-info is not a list");
967 }
968 if (!upgraded && relay_info->empty()) {
969 mutable_isc->remove("relay-info");
970 removed_relay_info = true;
971 isc_throw(BadValue, "relay-info is empty");
972 }
973
974 verifying = "relay";
975 for (i = 0; static_cast<size_t>(i) < relay_info->size(); ++i) {
976 ElementPtr relay = relay_info->getNonConst(i);
977 if (!upgraded && !relay) {
978 mutable_isc->remove("relay-info");
979 removed_relay_info = true;
980 isc_throw(BadValue, "null relay#" << i);
981 }
982 if (!upgraded && (relay->getType() != Element::map)) {
983 mutable_isc->remove("relay-info");
984 removed_relay_info = true;
985 isc_throw(BadValue, "relay#" << i << " is not a map");
986 }
987
988 ConstElementPtr options = relay->get("options");
989 if (!upgraded && options) {
990 // Try to decode options.
991 verifying = "options";
992 if (options->getType() != Element::string) {
993 mutable_isc->remove("relay-info");
994 removed_relay_info = true;
995 isc_throw(BadValue, "options is not a string");
996 }
997 string options_hex = options->stringValue();
998 vector<uint8_t> options_data;
999 str::decodeFormattedHexString(options_hex, options_data);
1000 OptionCollection opts;
1001 LibDHCP::unpackOptions6(options_data, DHCP6_OPTION_SPACE, opts);
1002 }
1004 continue;
1005 }
1006
1007 verifying = "link";
1008 ConstElementPtr link_addr = relay->get("link");
1009 if (!link_addr) {
1010 mutable_isc->remove("relay-info");
1011 removed_relay_info = true;
1012 isc_throw(BadValue, "no link");
1013 }
1014 if (link_addr->getType() != Element::string) {
1015 mutable_isc->remove("relay-info");
1016 removed_relay_info = true;
1017 isc_throw(BadValue, "link is not a string");
1018 }
1019 IOAddress laddr(link_addr->stringValue());
1020 if (!laddr.isV6()) {
1021 mutable_isc->remove("relay-info");
1022 removed_relay_info = true;
1023 isc_throw(BadValue, "link is not an IPv6 address");
1024 }
1025
1026 ConstElementPtr remote_id = relay->get("remote-id");
1027 if (!upgraded && remote_id) {
1028 verifying = "remote-id";
1029 if (remote_id->getType() != Element::string) {
1030 mutable_isc->remove("relay-info");
1031 removed_relay_info = true;
1032 isc_throw(BadValue, "remote-id is not a string");
1033 }
1034 string remote_id_hex = remote_id->stringValue();
1035 vector<uint8_t> remote_id_data;
1036 encode::decodeHex(remote_id_hex, remote_id_data);
1037 if (remote_id_data.empty()) {
1038 mutable_isc->remove("relay-info");
1039 removed_relay_info = true;
1040 isc_throw(BadValue, "remote-id is empty");
1041 }
1042 }
1043
1044 ConstElementPtr relay_id = relay->get("relay-id");
1045 if (!upgraded && relay_id) {
1046 verifying = "relay-id";
1047 if (relay_id->getType() != Element::string) {
1048 mutable_isc->remove("relay-info");
1049 removed_relay_info = true;
1050 isc_throw(BadValue, "relay-id is not a string");
1051 }
1052 string relay_id_hex = relay_id->stringValue();
1053 vector<uint8_t> relay_id_data;
1054 encode::decodeHex(relay_id_hex, relay_id_data);
1055 if (relay_id_data.empty()) {
1056 mutable_isc->remove("relay-info");
1057 removed_relay_info = true;
1058 isc_throw(BadValue, "relay-id is empty");
1059 }
1060 }
1061
1063 continue;
1064 }
1065
1066 verifying = "peer";
1067 ConstElementPtr peer_addr = relay->get("peer");
1068 if (!peer_addr) {
1069 mutable_isc->remove("relay-info");
1070 removed_relay_info = true;
1071 isc_throw(BadValue, "no peer");
1072 }
1073 if (peer_addr->getType() != Element::string) {
1074 mutable_isc->remove("relay-info");
1075 removed_relay_info = true;
1076 isc_throw(BadValue, "peer is not a string");
1077 }
1078 IOAddress paddr(peer_addr->stringValue());
1079 if (!paddr.isV6()) {
1080 mutable_isc->remove("relay-info");
1081 removed_relay_info = true;
1082 isc_throw(BadValue, "peer is not an IPv6 address");
1083 }
1084
1085 verifying = "hop";
1086 ConstElementPtr hop = relay->get("hop");
1087 if (!hop) {
1088 mutable_isc->remove("relay-info");
1089 removed_relay_info = true;
1090 isc_throw(BadValue, "no hop");
1091 }
1092 if (hop->getType() != Element::integer) {
1093 mutable_isc->remove("relay-info");
1094 removed_relay_info = true;
1095 isc_throw(BadValue, "hop is not an integer");
1096 }
1097
1098 verifying = (upgraded ? "relays" : "relay-info");
1099 for (auto const& elem : relay->mapValue()) {
1100 if ((elem.first != "hop") &&
1101 (elem.first != "link") &&
1102 (elem.first != "peer") &&
1103 (elem.first != "options") &&
1104 (elem.first != "remote-id") &&
1105 (elem.first != "relay-id") &&
1106 (elem.first != "comment")) {
1107 mutable_isc->remove("relay-info");
1108 removed_relay_info = true;
1109 isc_throw(BadValue, "spurious '" << elem.first << "' entry");
1110 }
1111 }
1112 }
1113
1114 if (upgraded) {
1117 .arg(lease->addr_.toText());
1118 }
1119
1120 return (changed);
1121 } catch (const exception& ex) {
1122 ostringstream err;
1123 err << "in " << verifying;
1124 if (i >= 0) {
1125 err << " [relay#" << i << "]";
1126 }
1127 err << " a problem was found: " << ex.what();
1129 .arg(lease->addr_.toText())
1130 .arg(err.str());
1131
1132 changed = true;
1133 have_both = !have_both;
1134 if (verifying == "user context") {
1135 lease->setContext(ConstElementPtr());
1136 } else if (verifying == "isc") {
1137 mutable_user_context->remove("ISC");
1138 if (mutable_user_context->empty()) {
1139 lease->setContext(ConstElementPtr());
1140 }
1141 } else {
1142 if (!removed_relay_info) {
1143 mutable_isc->remove("relay-info");
1144 }
1145 if (mutable_isc->empty()) {
1146 mutable_user_context->remove("ISC");
1147 if (mutable_user_context->empty()) {
1148 lease->setContext(ConstElementPtr());
1149 }
1150 }
1151 }
1152 return (changed);
1153 }
1154}
1155
1156void
1158 bool ignore_errors) {
1159 if (!lease) {
1160 return;
1161 }
1162
1163 ConstElementPtr user_context = lease->getContext();
1164 if (!user_context) {
1165 return;
1166 }
1167 if (user_context->getType() != Element::map) {
1168 if (ignore_errors) {
1169 return;
1170 }
1171 isc_throw(BadValue, "user context is not a map");
1172 }
1173 if (user_context->empty()) {
1174 return;
1175 }
1176
1177 ConstElementPtr isc = user_context->get("ISC");
1178 if (!isc) {
1179 return;
1180 }
1181 if (isc->getType() != Element::map) {
1182 if (ignore_errors) {
1183 return;
1184 }
1185 isc_throw(BadValue, "ISC entry is not a map");
1186 }
1187 if (isc->empty()) {
1188 return;
1189 }
1190
1191 ConstElementPtr extended_info = isc->get("relay-agent-info");
1192 if (!extended_info) {
1193 return;
1194 }
1195 if (extended_info->getType() != Element::map) {
1196 if (ignore_errors) {
1197 return;
1198 }
1199 isc_throw(BadValue, "relay-agent-info is not a map");
1200 }
1201 if (extended_info->empty()) {
1202 return;
1203 }
1204
1205 ConstElementPtr relay_id = extended_info->get("relay-id");
1206 if (relay_id) {
1207 if (relay_id->getType() == Element::string) {
1208 vector<uint8_t> bytes;
1209 try {
1210 encode::decodeHex(relay_id->stringValue(), bytes);
1211 } catch (...) {
1212 // Decode failed
1213 if (!ignore_errors) {
1214 throw;
1215 }
1216 }
1217 lease->relay_id_ = bytes;
1218 } else if (!ignore_errors) {
1219 isc_throw(BadValue, "relay-id entry is not a string");
1220 }
1221 }
1222
1223 ConstElementPtr remote_id = extended_info->get("remote-id");
1224 if (remote_id) {
1225 if (remote_id->getType() == Element::string) {
1226 vector<uint8_t> bytes;
1227 try {
1228 encode::decodeHex(remote_id->stringValue(), bytes);
1229 } catch (...) {
1230 // Decode failed
1231 if (!ignore_errors) {
1232 throw;
1233 }
1234 }
1235 lease->remote_id_ = bytes;
1236 } else if (!ignore_errors) {
1237 isc_throw(BadValue, "remote-id entry is not a string");
1238 }
1239 }
1240}
1241
1242bool
1244
1245 bool added = false;
1246 if (!lease) {
1247 return (added);
1248 }
1249
1250 ConstElementPtr user_context = lease->getContext();
1251 if (!user_context || (user_context->getType() != Element::map) ||
1252 user_context->empty()) {
1253 return (added);
1254 }
1255
1256 ConstElementPtr isc = user_context->get("ISC");
1257 if (!isc || (isc->getType() != Element::map) || isc->empty()) {
1258 return (added);
1259 }
1260
1261 ConstElementPtr relay_info = isc->get("relay-info");
1262 if (!relay_info || (relay_info->getType() != Element::list) ||
1263 relay_info->empty()) {
1264 return (added);
1265 }
1266
1267 for (unsigned i = 0; i < relay_info->size(); ++i) {
1268 ConstElementPtr relay = relay_info->get(i);
1269 if (!relay || (relay->getType() != Element::map) || relay->empty()) {
1270 continue;
1271 }
1272 try {
1273 ConstElementPtr relay_id = relay->get("relay-id");
1274 if (relay_id) {
1275 string relay_id_hex = relay_id->stringValue();
1276 vector<uint8_t> relay_id_data;
1277 encode::decodeHex(relay_id_hex, relay_id_data);
1278 if (relay_id_data.empty()) {
1279 continue;
1280 }
1281 addRelayId6(lease->addr_, relay_id_data);
1282 added = true;
1283 }
1284
1285 ConstElementPtr remote_id = relay->get("remote-id");
1286 if (remote_id) {
1287 string remote_id_hex = remote_id->stringValue();
1288 vector<uint8_t> remote_id_data;
1289 encode::decodeHex(remote_id_hex, remote_id_data);
1290 if (remote_id_data.empty()) {
1291 continue;
1292 }
1293 addRemoteId6(lease->addr_, remote_id_data);
1294 added = true;
1295 }
1296 } catch (const exception&) {
1297 continue;
1298 }
1299 }
1300 return (added);
1301}
1302
1303size_t
1305 return (0);
1306}
1307
1308size_t
1310 return (0);
1311}
1312
1315 return (ElementPtr());
1316}
1317
1320 ostringstream msg;
1321 msg << "lease backend '" << getName() << "' is not 'memfile'";
1323}
1324
1325void
1327 if (!lease->stateExpiredReclaimed()) {
1328 StatsMgr::instance().addValue("assigned-addresses", static_cast<int64_t>(1));
1329
1331 StatsMgr::generateName("subnet", lease->subnet_id_,
1332 "assigned-addresses"),
1333 static_cast<int64_t>(1));
1334
1335 PoolPtr pool;
1336 auto const& subnet = CfgMgr::instance().getCurrentCfg()->getCfgSubnets4()->getBySubnetId(lease->subnet_id_);
1337 if (subnet) {
1338 pool = subnet->getPool(Lease::TYPE_V4, lease->addr_, false);
1339 if (pool) {
1341 StatsMgr::generateName("subnet", subnet->getID(),
1342 StatsMgr::generateName("pool", pool->getID(),
1343 "assigned-addresses")),
1344 static_cast<int64_t>(1));
1345 }
1346 }
1347
1348 if (lease->stateDeclined()) {
1349 StatsMgr::instance().addValue("declined-addresses", static_cast<int64_t>(1));
1350
1352 StatsMgr::generateName("subnet", lease->subnet_id_,
1353 "declined-addresses"),
1354 static_cast<int64_t>(1));
1355
1356 if (pool) {
1358 StatsMgr::generateName("subnet", subnet->getID(),
1359 StatsMgr::generateName("pool", pool->getID(),
1360 "declined-addresses")),
1361 static_cast<int64_t>(1));
1362 }
1363 }
1364 }
1365}
1366
1367void
1369 if (lease->stateRegistered()) {
1371 StatsMgr::generateName("subnet", lease->subnet_id_, "registered-nas"),
1372 static_cast<int64_t>(1));
1373 } else if (!lease->stateExpiredReclaimed()) {
1374 StatsMgr::instance().addValue(lease->type_ == Lease::TYPE_NA ?
1375 "assigned-nas" : "assigned-pds",
1376 static_cast<int64_t>(1));
1377
1379 StatsMgr::generateName("subnet", lease->subnet_id_,
1380 lease->type_ == Lease::TYPE_NA ?
1381 "assigned-nas" : "assigned-pds"),
1382 static_cast<int64_t>(1));
1383
1384 PoolPtr pool;
1385 auto const& subnet = CfgMgr::instance().getCurrentCfg()->getCfgSubnets6()->getBySubnetId(lease->subnet_id_);
1386 if (subnet) {
1387 pool = subnet->getPool(lease->type_, lease->addr_, false);
1388 if (pool) {
1390 StatsMgr::generateName("subnet", subnet->getID(),
1391 StatsMgr::generateName(lease->type_ == Lease::TYPE_NA ?
1392 "pool" : "pd-pool", pool->getID(),
1393 lease->type_ == Lease::TYPE_NA ?
1394 "assigned-nas" : "assigned-pds")),
1395 static_cast<int64_t>(1));
1396 }
1397 }
1398
1399 if (lease->stateDeclined()) {
1400 StatsMgr::instance().addValue("declined-addresses", static_cast<int64_t>(1));
1401
1403 StatsMgr::generateName("subnet", lease->subnet_id_,
1404 "declined-addresses"),
1405 static_cast<int64_t>(1));
1406
1407 if (pool) {
1409 StatsMgr::generateName("subnet", subnet->getID(),
1410 StatsMgr::generateName("pool", pool->getID(),
1411 "declined-addresses")),
1412 static_cast<int64_t>(1));
1413 }
1414 }
1415 }
1416}
1417
1418void
1419LeaseMgr::bumpStat(const std::string& stat, SubnetID& subnet_id, PoolPtr pool, int value) {
1420 StatsMgr::instance().addValue(stat, static_cast<int64_t>(value));
1421 StatsMgr::instance().addValue(StatsMgr::generateName("subnet", subnet_id, stat),
1422 static_cast<int64_t>(value));
1423 if (pool) {
1425 StatsMgr::generateName("pool", pool->getID(), stat)),
1426 static_cast<int64_t>(value));
1427 }
1428}
1429
1430void
1431LeaseMgr::bumpStatPrefix(const std::string& stat, SubnetID& subnet_id, PoolPtr pool, int value) {
1432 StatsMgr::instance().addValue(stat, static_cast<int64_t>(value));
1433 StatsMgr::instance().addValue(StatsMgr::generateName("subnet", subnet_id, stat),
1434 static_cast<int64_t>(value));
1435 if (pool) {
1437 StatsMgr::generateName("pd-pool", pool->getID(), stat)),
1438 static_cast<int64_t>(value));
1439 }
1440}
1441
1443#define STATE_MASK(new_state, old_state) ((new_state << 4) | old_state)
1444
1446// New state ASSIGNED
1457// New state DECLINED
1468// New state EXPIRED_RECLAIMED
1473#if 0 // Currently unused.
1474constexpr uint16_t RECLAIMED_RECLAIMED = STATE_MASK(Lease::STATE_EXPIRED_RECLAIMED,
1476constexpr uint16_t RECLAIMED_RELEASED = STATE_MASK(Lease::STATE_EXPIRED_RECLAIMED,
1478#endif
1481// New state RELEASED
1486#if 0 // Currently unused.
1487constexpr uint16_t RELEASED_RECLAIMED = STATE_MASK(Lease::STATE_RELEASED,
1489constexpr uint16_t RELEASED_RELEASED = STATE_MASK(Lease::STATE_RELEASED,
1491#endif
1494// New state REGISTERED
1504
1505void
1507 const Lease4Ptr& lease) {
1508 if (existing->state_ == Lease::STATE_REGISTERED ||
1509 lease->state_ == Lease::STATE_REGISTERED) {
1510 // Registered is not valid for v4.
1511 return;
1512 }
1513
1514 if (existing->subnet_id_ == lease->subnet_id_) {
1515 if (existing->state_ == lease->state_) {
1516 // Same subnet, same state, nothing to do.
1517 return;
1518 }
1519
1520 // State is different so we know we're updating at least one stat.
1521 PoolPtr pool;
1522 auto const& subnet = CfgMgr::instance().getCurrentCfg()->
1523 getCfgSubnets4()->getBySubnetId(existing->subnet_id_);
1524 if (subnet) {
1525 pool = subnet->getPool(Lease::TYPE_V4, existing->addr_, false);
1526 }
1527
1528 // Switch on new-state:old-state mask.
1529 switch (STATE_MASK(lease->state_ , existing->state_)) {
1530 case ASSIGNED_DECLINED:
1531 bumpStat("declined-addresses", existing->subnet_id_, pool, -1);
1532 break;
1533
1534 case ASSIGNED_RECLAIMED:
1535 case ASSIGNED_RELEASED:
1536 bumpStat("assigned-addresses", existing->subnet_id_, pool, 1);
1537 break;
1538
1539 case DECLINED_ASSIGNED:
1540 bumpStat("declined-addresses", existing->subnet_id_, pool, 1);
1541 break;
1542
1543 case DECLINED_RECLAIMED:
1544 case DECLINED_RELEASED:
1545 bumpStat("assigned-addresses", existing->subnet_id_, pool, 1);
1546 bumpStat("declined-addresses", existing->subnet_id_, pool, 1);
1547 break;
1548
1549 case RECLAIMED_ASSIGNED:
1550 case RELEASED_ASSIGNED:
1551 bumpStat("assigned-addresses", existing->subnet_id_, pool, -1);
1552 break;
1553
1554 case RECLAIMED_DECLINED:
1555 case RELEASED_DECLINED:
1556 bumpStat("assigned-addresses", existing->subnet_id_, pool, -1);
1557 bumpStat("declined-addresses", existing->subnet_id_, pool, -1);
1558 break;
1559 default:
1560 // nothing to do.
1561 break;
1562 };
1563
1564 return;
1565 }
1566
1567 // Lease moved to a different subnet.
1568 // Fetch the new subnet and pool.
1569 auto const& new_subnet = CfgMgr::instance().getCurrentCfg()->
1570 getCfgSubnets4()->getBySubnetId(lease->subnet_id_);
1571 PoolPtr new_pool;
1572 if (new_subnet) {
1573 new_pool = new_subnet->getPool(Lease::TYPE_V4, lease->addr_, false);
1574 }
1575
1576 // Fetch the existing subnet and pool.
1577 auto const& existing_subnet = CfgMgr::instance().getCurrentCfg()->
1578 getCfgSubnets4()->getBySubnetId(existing->subnet_id_);
1579 PoolPtr existing_pool;
1580 if (existing_subnet) {
1581 existing_pool = existing_subnet->getPool(Lease::TYPE_V4, existing->addr_, false);
1582 }
1583
1584 // Switch on new-state:old-state mask.
1585 switch (STATE_MASK(lease->state_ , existing->state_)) {
1586 case ASSIGNED_ASSIGNED:
1587 bumpStat("assigned-addresses", existing->subnet_id_, existing_pool, -1);
1588 bumpStat("assigned-addresses", lease->subnet_id_, new_pool, 1);
1589 break;
1590
1591 case ASSIGNED_DECLINED:
1592 bumpStat("assigned-addresses", existing->subnet_id_, existing_pool, -1);
1593 bumpStat("declined-addresses", existing->subnet_id_, existing_pool, -1);
1594 bumpStat("assigned-addresses", lease->subnet_id_, new_pool, 1);
1595 break;
1596
1597 case ASSIGNED_RECLAIMED:
1598 case ASSIGNED_RELEASED:
1599 bumpStat("assigned-addresses", lease->subnet_id_, new_pool, 1);
1600 break;
1601
1602 case DECLINED_ASSIGNED:
1603 bumpStat("assigned-addresses", existing->subnet_id_, existing_pool, -1);
1604 bumpStat("assigned-addresses", lease->subnet_id_, new_pool, 1);
1605 bumpStat("declined-addresses", lease->subnet_id_, new_pool, 1);
1606 break;
1607
1608 case DECLINED_DECLINED:
1609 bumpStat("assigned-addresses", existing->subnet_id_, existing_pool, -1);
1610 bumpStat("declined-addresses", existing->subnet_id_, existing_pool, -1);
1611 bumpStat("assigned-addresses", lease->subnet_id_, new_pool, 1);
1612 bumpStat("declined-addresses", lease->subnet_id_, new_pool, 1);
1613 break;
1614
1615 case DECLINED_RECLAIMED:
1616 case DECLINED_RELEASED:
1617 bumpStat("assigned-addresses", lease->subnet_id_, new_pool, 1);
1618 bumpStat("declined-addresses", lease->subnet_id_, new_pool, 1);
1619 break;
1620
1621 case RECLAIMED_ASSIGNED:
1622 case RELEASED_ASSIGNED:
1623 bumpStat("assigned-addresses", existing->subnet_id_, existing_pool, -1);
1624 break;
1625
1626 case RECLAIMED_DECLINED:
1627 case RELEASED_DECLINED:
1628 bumpStat("assigned-addresses", existing->subnet_id_, existing_pool, -1);
1629 bumpStat("declined-addresses", existing->subnet_id_, existing_pool, -1);
1630 break;
1631
1632 default:
1633 // nothing to do.
1634 break;
1635 };
1636
1637 return;
1638}
1639
1640void
1642 const Lease6Ptr& lease) {
1643 if (existing->type_ != lease->type_) {
1644 // Something is fishy, mismatched types.
1645 return;
1646 }
1647
1648 if (existing->type_ == Lease::TYPE_PD &&
1649 (existing->state_ == Lease::STATE_DECLINED ||
1650 lease->state_ == Lease::STATE_DECLINED ||
1651 existing->state_ == Lease::STATE_REGISTERED ||
1652 lease->state_ == Lease::STATE_REGISTERED)) {
1653 // Something is fishy. Invalid states for PDs.
1654 return;
1655 }
1656
1657 if (existing->subnet_id_ == lease->subnet_id_) {
1658 if (existing->state_ == lease->state_) {
1659 // Same subnet, same state, nothing to do.
1660 return;
1661 }
1662
1663 // State is different so we know we're updating at least one stat.
1664 PoolPtr pool;
1665 auto const& subnet = CfgMgr::instance().getCurrentCfg()->
1666 getCfgSubnets6()->getBySubnetId(existing->subnet_id_);
1667 if (subnet) {
1668 pool = subnet->getPool(existing->type_, existing->addr_, false);
1669 }
1670
1671 // Switch on new-state:old-state mask.
1672 switch (STATE_MASK(lease->state_, existing->state_)) {
1673 case ASSIGNED_DECLINED:
1674 bumpStat("declined-addresses", existing->subnet_id_, pool, -1);
1675 break;
1676
1677 case ASSIGNED_RECLAIMED:
1678 case ASSIGNED_RELEASED:
1679 if (existing->type_ == Lease::TYPE_NA) {
1680 bumpStat("assigned-nas", existing->subnet_id_, pool, 1);
1681 } else {
1682 bumpStatPrefix("assigned-pds", existing->subnet_id_, pool, 1);
1683 }
1684 break;
1685
1687 bumpStat("assigned-nas", existing->subnet_id_, pool, 1);
1688 bumpStat("registered-nas", existing->subnet_id_, PoolPtr(), -1);
1689 break;
1690
1691 case DECLINED_ASSIGNED:
1692 bumpStat("declined-addresses", existing->subnet_id_, pool, 1);
1693 break;
1694
1695 case DECLINED_RECLAIMED:
1696 case DECLINED_RELEASED:
1697 bumpStat("assigned-nas", existing->subnet_id_, pool, 1);
1698 bumpStat("declined-addresses", existing->subnet_id_, pool, 1);
1699 break;
1700
1702 bumpStat("declined-addresses", existing->subnet_id_, pool, 1);
1703 bumpStat("registered-nas", existing->subnet_id_, PoolPtr(), -1);
1704 break;
1705
1706 case RECLAIMED_ASSIGNED:
1707 case RELEASED_ASSIGNED:
1708 if (existing->type_ == Lease::TYPE_NA) {
1709 bumpStat("assigned-nas", existing->subnet_id_, pool, -1);
1710 } else {
1711 bumpStatPrefix("assigned-pds", existing->subnet_id_, pool, -1);
1712 }
1713 break;
1714
1717 bumpStat("registered-nas", existing->subnet_id_, PoolPtr(), -1);
1718 break;
1719
1720 case RECLAIMED_DECLINED:
1721 case RELEASED_DECLINED:
1722 bumpStat("assigned-nas", existing->subnet_id_, pool, -1);
1723 bumpStat("declined-addresses", existing->subnet_id_, pool, -1);
1724 break;
1725
1727 bumpStat("assigned-nas", existing->subnet_id_, pool, -1);
1728 bumpStat("registered-nas", existing->subnet_id_, PoolPtr(), 1);
1729 break;
1730
1732 bumpStat("assigned-nas", existing->subnet_id_, pool, -1);
1733 bumpStat("declined-addresses", existing->subnet_id_, pool, -1);
1734 bumpStat("registered-nas", existing->subnet_id_, PoolPtr(), 1);
1735 break;
1736
1739 bumpStat("registered-nas", existing->subnet_id_, PoolPtr(), 1);
1740 break;
1741
1742 default:
1743 // nothing to do.
1744 break;
1745 };
1746
1747 return;
1748 }
1749
1750 // Lease moved to a different subnet.
1751 // Fetch the new subnet and pool.
1752 auto const& new_subnet = CfgMgr::instance().getCurrentCfg()->
1753 getCfgSubnets6()->getBySubnetId(lease->subnet_id_);
1754 PoolPtr new_pool;
1755 if (new_subnet) {
1756 new_pool = new_subnet->getPool(lease->type_, lease->addr_, false);
1757 }
1758
1759 // Fetch the existing subnet and pool.
1760 auto const& existing_subnet = CfgMgr::instance().getCurrentCfg()->
1761 getCfgSubnets6()->getBySubnetId(existing->subnet_id_);
1762 PoolPtr existing_pool;
1763 if (existing_subnet) {
1764 existing_pool = existing_subnet->getPool(existing->type_, existing->addr_, false);
1765 }
1766
1767 // Switch on new-state:old-state mask.
1768 switch (STATE_MASK(lease->state_, existing->state_)) {
1769 case ASSIGNED_ASSIGNED:
1770 if (lease->type_ == Lease::TYPE_NA) {
1771 bumpStat("assigned-nas", existing->subnet_id_, existing_pool, -1);
1772 bumpStat("assigned-nas", lease->subnet_id_, new_pool, 1);
1773 } else {
1774 bumpStatPrefix("assigned-pds", existing->subnet_id_, existing_pool, -1);
1775 bumpStatPrefix("assigned-pds", lease->subnet_id_, new_pool, 1);
1776 }
1777 break;
1778
1779 case ASSIGNED_DECLINED:
1780 bumpStat("assigned-nas", existing->subnet_id_, existing_pool, -1);
1781 bumpStat("declined-addresses", existing->subnet_id_, existing_pool, -1);
1782 bumpStat("assigned-nas", lease->subnet_id_, new_pool, 1);
1783 break;
1784
1785 case ASSIGNED_RECLAIMED:
1786 case ASSIGNED_RELEASED:
1787 if (lease->type_ == Lease::TYPE_NA) {
1788 bumpStat("assigned-nas", lease->subnet_id_, new_pool, 1);
1789 } else {
1790 bumpStatPrefix("assigned-pds", lease->subnet_id_, new_pool, 1);
1791 }
1792 break;
1793
1795 bumpStat("registered-nas", existing->subnet_id_, PoolPtr(), -1);
1796 bumpStat("assigned-nas", lease->subnet_id_, new_pool, 1);
1797 break;
1798
1799 case DECLINED_ASSIGNED:
1800 bumpStat("assigned-nas", existing->subnet_id_, existing_pool, -1);
1801 bumpStat("assigned-nas", lease->subnet_id_, new_pool, 1);
1802 bumpStat("declined-addresses", lease->subnet_id_, new_pool, 1);
1803 break;
1804
1805 case DECLINED_DECLINED:
1806 bumpStat("assigned-nas", existing->subnet_id_, existing_pool, -1);
1807 bumpStat("declined-addresses", existing->subnet_id_, existing_pool, -1);
1808 bumpStat("assigned-nas", lease->subnet_id_, new_pool, 1);
1809 bumpStat("declined-addresses", lease->subnet_id_, new_pool, 1);
1810 break;
1811
1812 case DECLINED_RECLAIMED:
1813 case DECLINED_RELEASED:
1814 bumpStat("assigned-nas", lease->subnet_id_, new_pool, 1);
1815 bumpStat("declined-addresses", lease->subnet_id_, new_pool, 1);
1816 break;
1817
1819 bumpStat("registered-nas", existing->subnet_id_, PoolPtr(), -1);
1820 bumpStat("assigned-nas", lease->subnet_id_, new_pool, 1);
1821 bumpStat("declined-addresses", lease->subnet_id_, new_pool, 1);
1822 break;
1823
1824 case RECLAIMED_ASSIGNED:
1825 case RELEASED_ASSIGNED:
1826 if (lease->type_ == Lease::TYPE_NA) {
1827 bumpStat("assigned-nas", existing->subnet_id_, existing_pool, -1);
1828 } else {
1829 bumpStatPrefix("assigned-pds", existing->subnet_id_, existing_pool, -1);
1830 }
1831 break;
1832
1833 case RECLAIMED_DECLINED:
1834 case RELEASED_DECLINED:
1835 bumpStat("assigned-nas", existing->subnet_id_, existing_pool, -1);
1836 bumpStat("declined-addresses", existing->subnet_id_, existing_pool, -1);
1837 break;
1838
1841 bumpStat("registered-nas", existing->subnet_id_, PoolPtr(), -1);
1842 break;
1843
1845 bumpStat("assigned-nas", existing->subnet_id_, existing_pool, -1);
1846 bumpStat("registered-nas", lease->subnet_id_, PoolPtr(), 1);
1847 break;
1848
1850 bumpStat("assigned-nas", existing->subnet_id_, existing_pool, -1);
1851 bumpStat("declined-addresses", existing->subnet_id_, existing_pool, -1);
1852 bumpStat("registered-nas", lease->subnet_id_, PoolPtr(), 1);
1853 break;
1854
1857 bumpStat("registered-nas", lease->subnet_id_, PoolPtr(), 1);
1858 break;
1859
1861 bumpStat("registered-nas", existing->subnet_id_, PoolPtr(), -1);
1862 bumpStat("registered-nas", lease->subnet_id_, PoolPtr(), 1);
1863 break;
1864
1865 default:
1866 // nothing to do.
1867 break;
1868 };
1869
1870 return;
1871}
1872
1873void
1875 if (!lease->stateExpiredReclaimed()) {
1876 StatsMgr::instance().addValue("assigned-addresses", static_cast<int64_t>(-1));
1877
1879 StatsMgr::generateName("subnet", lease->subnet_id_,
1880 "assigned-addresses"),
1881 static_cast<int64_t>(-1));
1882
1883 PoolPtr pool;
1884 auto const& subnet = CfgMgr::instance().getCurrentCfg()->getCfgSubnets4()->getBySubnetId(lease->subnet_id_);
1885 if (subnet) {
1886 pool = subnet->getPool(Lease::TYPE_V4, lease->addr_, false);
1887 if (pool) {
1889 StatsMgr::generateName("subnet", subnet->getID(),
1890 StatsMgr::generateName("pool", pool->getID(),
1891 "assigned-addresses")),
1892 static_cast<int64_t>(-1));
1893 }
1894 }
1895
1896 if (lease->stateDeclined()) {
1897 StatsMgr::instance().addValue("declined-addresses", static_cast<int64_t>(-1));
1898
1900 StatsMgr::generateName("subnet", lease->subnet_id_,
1901 "declined-addresses"),
1902 static_cast<int64_t>(-1));
1903
1904 if (pool) {
1906 StatsMgr::generateName("subnet", subnet->getID(),
1907 StatsMgr::generateName("pool", pool->getID(),
1908 "declined-addresses")),
1909 static_cast<int64_t>(-1));
1910 }
1911 }
1912 }
1913}
1914
1915void
1917 if (lease->stateRegistered()) {
1919 StatsMgr::generateName("subnet", lease->subnet_id_,
1920 "registered-nas"),
1921 static_cast<int64_t>(-1));
1922 } else if (!lease->stateExpiredReclaimed()) {
1923 StatsMgr::instance().addValue(lease->type_ == Lease::TYPE_NA ?
1924 "assigned-nas" : "assigned-pds",
1925 static_cast<int64_t>(-1));
1926
1928 StatsMgr::generateName("subnet", lease->subnet_id_,
1929 lease->type_ == Lease::TYPE_NA ?
1930 "assigned-nas" : "assigned-pds"),
1931 static_cast<int64_t>(-1));
1932
1933 PoolPtr pool;
1934 auto const& subnet = CfgMgr::instance().getCurrentCfg()->getCfgSubnets6()->getBySubnetId(lease->subnet_id_);
1935 if (subnet) {
1936 pool = subnet->getPool(lease->type_, lease->addr_, false);
1937 if (pool) {
1939 StatsMgr::generateName("subnet", subnet->getID(),
1940 StatsMgr::generateName(lease->type_ == Lease::TYPE_NA ?
1941 "pool" : "pd-pool", pool->getID(),
1942 lease->type_ == Lease::TYPE_NA ?
1943 "assigned-nas" : "assigned-pds")),
1944 static_cast<int64_t>(-1));
1945 }
1946 }
1947
1948 if (lease->stateDeclined()) {
1949 StatsMgr::instance().addValue("declined-addresses", static_cast<int64_t>(-1));
1950
1952 StatsMgr::generateName("subnet", lease->subnet_id_,
1953 "declined-addresses"),
1954 static_cast<int64_t>(-1));
1955
1956 if (pool) {
1958 StatsMgr::generateName("subnet", subnet->getID(),
1959 StatsMgr::generateName("pool", pool->getID(),
1960 "declined-addresses")),
1961 static_cast<int64_t>(-1));
1962 }
1963 }
1964 }
1965}
1966
1968 lease_type_(Lease::TYPE_V4),
1969 start_address_(IOAddress::IPV4_ZERO_ADDRESS()),
1970 end_address_(IOAddress::IPV4_ZERO_ADDRESS()),
1971 delegated_len_(128),
1972 subnet_id_(SUBNET_ID_UNUSED),
1973 free_leases_(0),
1974 created_ts_(),
1975 modified_ts_() {
1976}
1977
1978
1982 info->set("lease-type", Element::create(Lease::typeToText(lease_type_)));
1983 info->set("start-address", Element::create(start_address_.toText()));
1984 info->set("end-address", Element::create(end_address_.toText()));
1985 info->set("delegated-len", Element::create(delegated_len_));
1986 info->set("subnet-id", Element::create(subnet_id_));
1987 info->set("free-leases", ElementPtr(new IntElement(free_leases_)));
1990 return(info);
1991}
1992
1993bool
1995 isc_throw(NotImplemented, "LeaseMgr::sflqCreateFlqPool4() called");
1996}
1997
2000 isc_throw(NotImplemented, "LeaseMgr::sflqPickFreeLease4() called");
2001}
2002
2003bool
2005 isc_throw(NotImplemented, "LeaseMgr::sflqCreateFlqPool6() called");
2006}
2007
2010 isc_throw(NotImplemented, "LeaseMgr::sflqPickFreeLease6() called");
2011}
2012
2015 isc_throw(NotImplemented, "LeaseMgr::sflqPool4GetAll() called");
2016}
2017
2020 isc_throw(NotImplemented, "LeaseMgr::sflqPool4Get(SubnetID) called");
2021}
2022
2025 isc_throw(NotImplemented, "LeaseMgr::sflqPool4Get(IOAddress,IOAddress) called");
2026}
2027
2028bool
2030 isc_throw(NotImplemented, "LeaseMgr::sflqPool4Del() called");
2031}
2032
2035 isc_throw(NotImplemented, "LeaseMgr::sflqPool6GetAll() called");
2036}
2037
2040 isc_throw(NotImplemented, "LeaseMgr::sflqPool6Get(SubnetID) called");
2041}
2042
2045 isc_throw(NotImplemented, "LeaseMgr::sflqPool6Get(IOAddress,IOAddress) called");
2046}
2047
2048bool
2050 isc_throw(NotImplemented, "LeaseMgr::sflqPool6Del() called");
2051}
2052
2053bool
2055 // Only check the subnet if SFLQ is in-use in this config.
2057 auto const& subnet = CfgMgr::instance().getCurrentCfg()->
2058 getCfgSubnets4()->getBySubnetId(lease->subnet_id_);
2059
2060 // We should? always have a subnet.
2061 if (subnet) {
2062 return (subnet->getAllocator(Lease::TYPE_V4)->getType() == "shared-flq");
2063 }
2064 }
2065
2066 return false;
2067}
2068
2069bool
2071 // Only check the subnet if SFLQ is in-use in this config.
2073 auto const& subnet = CfgMgr::instance().getCurrentCfg()->
2074 getCfgSubnets6()->getBySubnetId(lease->subnet_id_);
2075
2076 // We should? always have a subnet.
2077 if (subnet) {
2078 return (subnet->getAllocator(lease->getType())->getType() == "shared-flq");
2079 }
2080 }
2081
2082 return false;
2083}
2084
2085} // namespace isc::dhcp
2086} // namespace isc
A generic exception that is thrown if a parameter given to a method is considered invalid in that con...
A generic exception that is thrown when a function is not implemented.
A generic exception that is thrown if a parameter given to a method would refer to or modify out-of-r...
static ElementPtr create(const Position &pos=ZERO_POSITION())
Create a NullElement.
Definition data.cc:299
static ElementPtr createMap(const Position &pos=ZERO_POSITION())
Creates an empty MapElement type ElementPtr.
Definition data.cc:354
Notes: IntElement type is changed to int64_t.
Definition data.h:776
std::map< std::string, std::string > ParameterMap
Database configuration parameter map.
Multiple lease records found where one expected.
ExtendedInfoSanity
Values for extended info sanity checks done for leases.
static CfgMgr & instance()
returns a single instance of Configuration Manager
Definition cfgmgr.cc:29
SrvConfigPtr getCurrentCfg()
Returns a pointer to the current configuration.
Definition cfgmgr.cc:116
Holds DUID (DHCPv6 Unique Identifier)
Definition duid.h:142
std::string toText() const
Returns textual representation of the identifier (e.g.
Definition duid.h:88
virtual bool sflqPool4Del(asiolink::IOAddress start_address, asiolink::IOAddress end_address, bool force=false)
Delete the SFLQ V4 pool that matches a start and end address.
virtual LeaseStatsQueryPtr startSubnetLeaseStatsQuery6(const SubnetID &subnet_id)
Creates and runs the IPv6 lease stats query for a single subnet.
Definition lease_mgr.cc:554
virtual LeaseStatsQueryPtr startPoolLeaseStatsQuery6()
Creates and runs the IPv6 lease stats query for all subnets and pools.
Definition lease_mgr.cc:549
virtual Lease6Collection getLeases6() const =0
Returns all IPv6 leases.
void recountLeaseStats6()
Recalculates per-subnet and global stats for IPv6 leases.
Definition lease_mgr.cc:297
virtual data::ElementPtr getStatus() const
Return status information.
void setExtendedInfoTablesEnabled(const bool enabled)
Modifies the setting whether the lease6 extended info tables are enabled.
Definition lease_mgr.h:1072
virtual bool sflqPool6Del(asiolink::IOAddress start_address, asiolink::IOAddress end_address, bool force=false)
Delete the SFLQ V6 pool that matches a start and end address.
virtual size_t byRelayId6size() const
Return the by-relay-id table size.
static bool upgradeLease6ExtendedInfo(const Lease6Ptr &lease, CfgConsistency::ExtendedInfoSanity check=CfgConsistency::EXTENDED_INFO_CHECK_FIX)
Upgrade a V6 lease user context to the new extended info entry.
Definition lease_mgr.cc:805
virtual SflqPoolInfoCollectionPtr sflqPool4Get(SubnetID subnet_id)
Fetch all SFLQ V4 pools belonging to a subnet.
virtual SflqPoolInfoCollectionPtr sflqPool4GetAll()
Fetch all SFLQ V4 pools.
static void updateStatsOnAdd(const Lease4Ptr &lease)
Update in-memory stats when adding a v4 lease.
virtual size_t byRemoteId6size() const
Return the by-remote-id table size.
virtual asiolink::IOAddress sflqPickFreeLease4(asiolink::IOAddress start_address, asiolink::IOAddress end_address)
Finds a free V4 address within the given pool range.
static void updateStatsOnUpdate(const Lease4Ptr &existing, const Lease4Ptr &lease)
Update in-memory stats when updating a v4 lease.
static bool useSharedFlqStatement(Lease4Ptr lease)
Determine if SFLQ alternate SQL statements should be used for a given v4 lease.
virtual void addRelayId6(const isc::asiolink::IOAddress &lease_addr, const std::vector< uint8_t > &relay_id)=0
Add lease6 extended info into by-relay-id table.
static void bumpStatPrefix(const std::string &stat, SubnetID &subnet_id, PoolPtr pool, int value)
Helper function that adds a value to a prefix stat's global, subnet, and pool level values.
virtual LeaseStatsQueryPtr startSubnetRangeLeaseStatsQuery4(const SubnetID &first_subnet_id, const SubnetID &last_subnet_id)
Creates and runs the IPv4 lease stats query for a single subnet.
Definition lease_mgr.cc:286
virtual std::string getName() const =0
Returns backend name.
void recountLeaseStats4()
Recalculates per-subnet and global stats for IPv4 leases.
Definition lease_mgr.cc:78
static std::string getDBVersion()
Class method to return extended version info This class method must be redeclared and redefined in de...
Definition lease_mgr.cc:565
virtual LeaseStatsQueryPtr startSubnetRangeLeaseStatsQuery6(const SubnetID &first_subnet_id, const SubnetID &last_subnet_id)
Creates and runs the IPv6 lease stats query for a single subnet.
Definition lease_mgr.cc:559
static void updateStatsOnDelete(const Lease4Ptr &lease)
Update in-memory stats when deleting a v4 lease.
virtual LeaseStatsQueryPtr startSubnetLeaseStatsQuery4(const SubnetID &subnet_id)
Creates and runs the IPv4 lease stats query for a single subnet.
Definition lease_mgr.cc:281
virtual Lease6Ptr getLease6(Lease::Type type, const isc::asiolink::IOAddress &addr) const =0
Returns existing IPv6 lease for a given IPv6 address.
virtual isc::data::ConstElementPtr lfcStartHandler()
Handler for kea-lfc-start command.
virtual LeaseStatsQueryPtr startLeaseStatsQuery4()
Creates and runs the IPv4 lease stats query for all subnets.
Definition lease_mgr.cc:271
static void extractLease4ExtendedInfo(const Lease4Ptr &lease, bool ignore_errors=true)
Extract relay and remote identifiers from the extended info.
virtual bool sflqCreateFlqPool4(asiolink::IOAddress start_address, asiolink::IOAddress end_address, SubnetID subnet_id, bool recreate=false)
Creates a v4 SFLQ Pool.
static bool upgradeLease4ExtendedInfo(const Lease4Ptr &lease, CfgConsistency::ExtendedInfoSanity check=CfgConsistency::EXTENDED_INFO_CHECK_FIX)
The following queries are used to fulfill Bulk Lease Query queries.
Definition lease_mgr.cc:584
virtual SflqPoolInfoCollectionPtr sflqPool6GetAll()
Fetch all SFLQ V6 pools.
virtual void addRemoteId6(const isc::asiolink::IOAddress &lease_addr, const std::vector< uint8_t > &remote_id)=0
Add lease6 extended info into by-remote-id table.
virtual LeaseStatsQueryPtr startPoolLeaseStatsQuery4()
Creates and runs the IPv4 lease stats query for all subnets and pools.
Definition lease_mgr.cc:276
static void bumpStat(const std::string &stat, SubnetID &subnet_id, PoolPtr pool, int value)
Helper function that adds a value to an address stat's global, subnet, and pool level values.
virtual bool addExtendedInfo6(const Lease6Ptr &lease)
Extract extended info from a lease6 and add it into tables.
virtual asiolink::IOAddress sflqPickFreeLease6(asiolink::IOAddress start_address, asiolink::IOAddress end_address)
Finds a free V6 address/prefix within the given pool range.
virtual SflqPoolInfoCollectionPtr sflqPool6Get(SubnetID subnet_id)
Fetch all SFLQ V6 pools belonging to a subnet.
virtual bool sflqCreateFlqPool6(asiolink::IOAddress start_address, asiolink::IOAddress end_address, Lease::Type lease_type, uint8_t delegated_len, SubnetID subnet_id, bool recreate=false)
Calls stored procedure to create an SFLQ pool for v6.
virtual LeaseStatsQueryPtr startLeaseStatsQuery6()
Creates and runs the IPv6 lease stats query for all subnets.
Definition lease_mgr.cc:544
const size_t page_size_
Holds page size.
Definition lease_mgr.h:56
LeasePageSize(const size_t page_size)
Constructor.
Definition lease_mgr.cc:47
LeaseStatsQuery(const SelectMode &select_mode=ALL_SUBNETS)
Constructor to query statistics for all subnets.
Definition lease_mgr.cc:235
SubnetID first_subnet_id_
First (or only) subnet_id in the selection criteria.
Definition lease_mgr.h:222
SubnetID last_subnet_id_
Last subnet_id in the selection criteria when a range is given.
Definition lease_mgr.h:225
virtual bool getNextRow(LeaseStatsRow &row)
Fetches the next row of data.
Definition lease_mgr.cc:292
SelectMode
Defines the types of selection criteria supported.
Definition lease_mgr.h:152
static const OptionDefinition & DHO_DHCP_AGENT_OPTIONS_DEF()
Get definition of DHO_DHCP_AGENT_OPTIONS option.
static size_t unpackOptions6(const OptionBuffer &buf, const std::string &option_space, isc::dhcp::OptionCollection &options, size_t *relay_msg_offset=0, size_t *relay_msg_len=0)
Parses provided buffer as DHCPv6 options and creates Option objects.
Definition libdhcp++.cc:317
Option with defined data fields represented as buffers that can be accessed using data field index.
Base class representing a DHCP option definition.
Lease::Type lease_type_
Definition lease_mgr.h:245
data::ConstElementPtr toElement() const
boost::posix_time::ptime modified_ts_
Definition lease_mgr.h:252
boost::posix_time::ptime created_ts_
Definition lease_mgr.h:251
asiolink::IOAddress start_address_
Definition lease_mgr.h:246
asiolink::IOAddress end_address_
Definition lease_mgr.h:247
static bool inUse()
Returns the global in-use flag.
Statistics Manager class.
ObservationPtr getObservation(const std::string &name) const
Returns an observation.
static StatsMgr & instance()
Statistics Manager accessor method.
static std::string generateName(const std::string &context, Type index, const std::string &stat_name)
Generates statistic name in a given context.
This file contains several functions and constants that are used for handling commands and responses ...
@ D6O_REMOTE_ID
Definition dhcp6.h:57
@ D6O_RELAY_ID
Definition dhcp6.h:73
#define isc_throw(type, stream)
A shortcut macro to insert known values into exception arguments.
void setValue(const std::string &name, const int64_t value)
Records absolute integer observation.
void addValue(const std::string &name, const int64_t value)
Records incremental integer observation.
#define STATE_MASK(new_state, old_state)
Creates a mask out of two states: new state and old state.
An abstract API for lease database.
#define LOG_ERROR(LOGGER, MESSAGE)
Macro to conveniently test error output and log it.
Definition macros.h:32
#define LOG_DEBUG(LOGGER, LEVEL, MESSAGE)
Macro to conveniently test debug output and log it.
Definition macros.h:14
ConstElementPtr createAnswer()
Creates a standard config/command level success answer message (i.e.
const int CONTROL_RESULT_COMMAND_UNSUPPORTED
Status code indicating that the specified command is not supported.
ElementPtr copy(ConstElementPtr from, unsigned level)
Copy the data up to a nesting level.
Definition data.cc:1527
boost::shared_ptr< const Element > ConstElementPtr
Definition data.h:30
boost::shared_ptr< Element > ElementPtr
Definition data.h:29
@ info
Definition db_log.h:120
isc::log::Logger dhcpsrv_logger("dhcpsrv")
DHCP server library Logger.
Definition dhcpsrv_log.h:56
constexpr uint16_t DECLINED_RECLAIMED
constexpr uint16_t RECLAIMED_ASSIGNED
constexpr uint16_t REGISTERED_RELEASED
boost::shared_ptr< SflqPoolInfoCollection > SflqPoolInfoCollectionPtr
Definition lease_mgr.h:262
const isc::log::MessageID DHCPSRV_LEASE6_EXTENDED_INFO_UPGRADED
boost::shared_ptr< OptionCustom > OptionCustomPtr
A pointer to the OptionCustom object.
boost::shared_ptr< Lease6 > Lease6Ptr
Pointer to a Lease6 structure.
Definition lease.h:528
std::vector< Lease6Ptr > Lease6Collection
A collection of IPv6 leases.
Definition lease.h:693
boost::shared_ptr< LeaseStatsQuery > LeaseStatsQueryPtr
Defines a pointer to a LeaseStatsQuery.
Definition lease_mgr.h:233
boost::multi_index_container< Subnet6Ptr, boost::multi_index::indexed_by< boost::multi_index::ordered_unique< boost::multi_index::tag< SubnetSubnetIdIndexTag >, boost::multi_index::const_mem_fun< Subnet, SubnetID, &Subnet::getID > >, boost::multi_index::ordered_unique< boost::multi_index::tag< SubnetPrefixIndexTag >, boost::multi_index::const_mem_fun< Subnet, std::string, &Subnet::toText > >, boost::multi_index::ordered_non_unique< boost::multi_index::tag< SubnetModificationTimeIndexTag >, boost::multi_index::const_mem_fun< data::BaseStampedElement, boost::posix_time::ptime, &data::BaseStampedElement::getModificationTime > > > > Subnet6Collection
A collection of Subnet6 objects.
Definition subnet.h:937
std::multimap< unsigned int, OptionPtr > OptionCollection
A collection of DHCP (v4 or v6) options.
Definition option.h:40
constexpr uint16_t REGISTERED_ASSIGNED
constexpr uint16_t RELEASED_DECLINED
constexpr uint16_t ASSIGNED_ASSIGNED
Constant expression state masks for use in switch statements.
constexpr uint16_t ASSIGNED_DECLINED
constexpr uint16_t RECLAIMED_REGISTERED
constexpr uint16_t RELEASED_ASSIGNED
constexpr uint16_t RECLAIMED_DECLINED
boost::shared_ptr< Pool > PoolPtr
a pointer to either IPv4 or IPv6 Pool
Definition pool.h:726
boost::multi_index_container< Subnet4Ptr, boost::multi_index::indexed_by< boost::multi_index::ordered_unique< boost::multi_index::tag< SubnetSubnetIdIndexTag >, boost::multi_index::const_mem_fun< Subnet, SubnetID, &Subnet::getID > >, boost::multi_index::ordered_unique< boost::multi_index::tag< SubnetPrefixIndexTag >, boost::multi_index::const_mem_fun< Subnet, std::string, &Subnet::toText > >, boost::multi_index::ordered_non_unique< boost::multi_index::tag< SubnetServerIdIndexTag >, boost::multi_index::const_mem_fun< Network4, asiolink::IOAddress, &Network4::getServerId > >, boost::multi_index::ordered_non_unique< boost::multi_index::tag< SubnetModificationTimeIndexTag >, boost::multi_index::const_mem_fun< data::BaseStampedElement, boost::posix_time::ptime, &data::BaseStampedElement::getModificationTime > > > > Subnet4Collection
A collection of Subnet4 objects.
Definition subnet.h:866
constexpr uint16_t REGISTERED_REGISTERED
uint32_t SubnetID
Defines unique IPv4 or IPv6 subnet identifier.
Definition subnet_id.h:25
constexpr uint16_t DECLINED_ASSIGNED
constexpr uint16_t RELEASED_REGISTERED
constexpr uint16_t ASSIGNED_RECLAIMED
constexpr uint16_t DECLINED_REGISTERED
constexpr uint16_t DECLINED_RELEASED
constexpr uint16_t ASSIGNED_RELEASED
constexpr uint16_t DECLINED_DECLINED
@ RAI_OPTION_RELAY_ID
Definition dhcp4.h:276
@ RAI_OPTION_REMOTE_ID
Definition dhcp4.h:266
const isc::log::MessageID DHCPSRV_LEASE4_EXTENDED_INFO_SANITY_FAIL
const isc::log::MessageID DHCPSRV_LEASE4_EXTENDED_INFO_UPGRADED
boost::shared_ptr< Lease4 > Lease4Ptr
Pointer to a Lease4 structure.
Definition lease.h:315
const int DHCPSRV_DBG_TRACE
DHCP server library logging levels.
Definition dhcpsrv_log.h:26
boost::shared_ptr< Option > OptionPtr
Definition option.h:37
const isc::log::MessageID DHCPSRV_LEASE6_EXTENDED_INFO_SANITY_FAIL
constexpr uint16_t REGISTERED_DECLINED
constexpr uint16_t ASSIGNED_REGISTERED
constexpr uint16_t REGISTERED_RECLAIMED
void decodeHex(const string &encoded_str, vector< uint8_t > &output)
Decode a base16 encoded string into binary data.
Definition encode.cc:367
string encodeHex(const vector< uint8_t > &binary)
Encode binary data in the base16 format.
Definition encode.cc:361
void decodeFormattedHexString(const string &hex_string, vector< uint8_t > &binary)
Converts a formatted string of hexadecimal digits into a vector.
Definition str.cc:212
std::string ptimeToText(boost::posix_time::ptime t, size_t fsecs_precision=MAX_FSECS_PRECISION)
Converts ptime structure to text.
Defines the logger used by the top-level component of kea-lfc.
#define DHCP6_OPTION_SPACE
Contains a single row of lease statistical data.
Definition lease_mgr.h:64
uint32_t pool_id_
The pool ID to which this data applies.
Definition lease_mgr.h:132
int64_t state_count_
state_count The count of leases in the lease state
Definition lease_mgr.h:141
uint32_t lease_state_
The lease_state to which the count applies.
Definition lease_mgr.h:138
SubnetID subnet_id_
The subnet ID to which this data applies.
Definition lease_mgr.h:129
Lease::Type lease_type_
The lease_type to which the count applies.
Definition lease_mgr.h:135
a common structure for IPv4 and IPv6 leases
Definition lease.h:31
static constexpr uint32_t STATE_DEFAULT
A lease in the default state.
Definition lease.h:69
static constexpr uint32_t STATE_EXPIRED_RECLAIMED
Expired and reclaimed lease.
Definition lease.h:75
static constexpr uint32_t STATE_DECLINED
Declined lease.
Definition lease.h:72
static constexpr uint32_t STATE_REGISTERED
Registered self-generated lease.
Definition lease.h:81
static constexpr uint32_t STATE_RELEASED
Released lease held in the database for lease affinity.
Definition lease.h:78
Type
Type of lease or pool.
Definition lease.h:46
@ TYPE_PD
the lease contains IPv6 prefix (for prefix delegation)
Definition lease.h:49
@ TYPE_V4
IPv4 lease.
Definition lease.h:50
@ TYPE_NA
the lease contains non-temporary IPv6 address
Definition lease.h:47
static std::string typeToText(Type type)
returns text representation of a lease type
Definition lease.cc:56