Kea 3.2.0-git
subnet.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
11#include <dhcp/option_space.h>
12#include <dhcpsrv/dhcpsrv_log.h>
22#include <dhcpsrv/subnet.h>
24
25#include <boost/lexical_cast.hpp>
26#include <boost/make_shared.hpp>
27
28#include <algorithm>
29#include <limits>
30#include <sstream>
31
32using namespace isc::asiolink;
33using namespace isc::data;
34using namespace isc::dhcp;
35using namespace isc::util;
36
37using namespace std;
38
39namespace {
40
45bool
46prefixLessThanFirstAddress(const IOAddress& prefix,
47 const PoolPtr& pool) {
48 return (prefix < pool->getFirstAddress());
49}
50
59bool
60comparePoolFirstAddress(const PoolPtr& pool1,
61 const PoolPtr& pool2) {
62 return (pool1->getFirstAddress() < pool2->getFirstAddress());
63}
64
65}
66
67namespace isc {
68namespace dhcp {
69
70Subnet::Subnet(const isc::asiolink::IOAddress& prefix, uint8_t len,
71 const SubnetID id)
72 : id_(id), prefix_(prefix), prefix_len_(len), shared_network_name_() {
73 if ((id == SUBNET_ID_GLOBAL) || (id == SUBNET_ID_UNUSED)) {
75 "Invalid id specified for subnet: " << id);
76 }
77 if ((prefix.isV6() && len > 128) || (prefix.isV4() && len > 32)) {
78 isc_throw(BadValue,
79 "Invalid prefix length specified for subnet: " << len);
80 }
81}
82
83bool
87
88 return ((first <= addr) && (addr <= last));
89}
90
91std::string
93 std::stringstream tmp;
94 tmp << prefix_ << "/" << static_cast<unsigned int>(prefix_len_);
95 return (tmp.str());
96}
97
100 switch (type) {
101 case Lease::TYPE_V4:
102 case Lease::TYPE_NA:
103 return sumPoolCapacity(pools_);
104 case Lease::TYPE_PD:
106 default:
107 isc_throw(BadValue, "Unsupported pool type: "
108 << static_cast<int>(type));
109 }
110}
111
114 const ClientClasses& client_classes) const {
115 switch (type) {
116 case Lease::TYPE_V4:
117 case Lease::TYPE_NA:
118 return sumPoolCapacity(pools_, client_classes);
119 case Lease::TYPE_PD:
120 return sumPoolCapacity(pools_pd_, client_classes);
121 default:
122 isc_throw(BadValue, "Unsupported pool type: "
123 << static_cast<int>(type));
124 }
125}
126
129 const ClientClasses& client_classes,
130 Allocator::PrefixLenMatchType prefix_length_match,
131 uint8_t hint_prefix_length) const {
132 switch (type) {
133 case Lease::TYPE_V4:
134 case Lease::TYPE_NA:
135 return sumPoolCapacity(pools_, client_classes);
136 case Lease::TYPE_PD:
137 return sumPoolCapacity(pools_pd_, client_classes, prefix_length_match,
138 hint_prefix_length);
139 default:
140 isc_throw(BadValue, "Unsupported pool type: "
141 << static_cast<int>(type));
142 }
143}
144
147 uint128_t sum(0);
148 for (auto const& p : pools) {
149 uint128_t const c(p->getCapacity());
150
151 // Check if we can add it. If sum + c > UINT128_MAX, then we would have
152 // overflown if we tried to add it.
153 if (c > numeric_limits<uint128_t>::max() - sum) {
154 return (numeric_limits<uint128_t>::max());
155 }
156
157 sum += c;
158 }
159
160 return (sum);
161}
162
165 const ClientClasses& client_classes) const {
166 uint128_t sum(0);
167 for (auto const& p : pools) {
168 if (!p->clientSupported(client_classes)) {
169 continue;
170 }
171
172 uint128_t const c(p->getCapacity());
173
174 // Check if we can add it. If sum + c > UINT128_MAX, then we would have
175 // overflown if we tried to add it.
176 if (c > numeric_limits<uint128_t>::max() - sum) {
177 return (numeric_limits<uint128_t>::max());
178 }
179
180 sum += c;
181 }
182
183 return (sum);
184}
185
188 const ClientClasses& client_classes,
189 Allocator::PrefixLenMatchType prefix_length_match,
190 uint8_t hint_prefix_length) const {
191 uint128_t sum(0);
192 for (auto const& p : pools) {
193 if (!p->clientSupported(client_classes)) {
194 continue;
195 }
196
197 if (!Allocator::isValidPrefixPool(prefix_length_match, p,
198 hint_prefix_length)) {
199 continue;
200 }
201
202 uint128_t const c(p->getCapacity());
203
204 // Check if we can add it. If sum + c > UINT128_MAX, then we would have
205 // overflown if we tried to add it.
206 if (c > numeric_limits<uint128_t>::max() - sum) {
207 return (numeric_limits<uint128_t>::max());
208 }
209
210 sum += c;
211 }
212
213 return (sum);
214}
215
216std::pair<IOAddress, uint8_t>
217Subnet::parsePrefixCommon(const std::string& prefix) {
218 auto pos = prefix.find('/');
219 if ((pos == std::string::npos) ||
220 (pos == prefix.size() - 1) ||
221 (pos == 0)) {
222 isc_throw(BadValue, "unable to parse invalid prefix " << prefix);
223 }
224
225 try {
226 IOAddress address(prefix.substr(0, pos));
227 int length = boost::lexical_cast<int>(prefix.substr(pos + 1));
228 return (std::make_pair(address, static_cast<int>(length)));
229
230 } catch (...) {
231 isc_throw(BadValue, "unable to parse invalid prefix " << prefix);
232 }
233}
234
235
236void Subnet4::checkType(Lease::Type type) const {
237 if (type != Lease::TYPE_V4) {
238 isc_throw(BadValue, "Only TYPE_V4 is allowed for Subnet4");
239 }
240}
241
242Subnet4::Subnet4(const IOAddress& prefix, uint8_t length,
243 const Triplet<uint32_t>& t1,
244 const Triplet<uint32_t>& t2,
245 const Triplet<uint32_t>& valid_lifetime,
246 const SubnetID id)
247 : Subnet(prefix, length, id), Network4() {
248 if (!prefix.isV4()) {
249 isc_throw(BadValue, "Non IPv4 prefix " << prefix.toText()
250 << " specified in subnet4");
251 }
252 // Timers.
253 setT1(t1);
254 setT2(t2);
255 setValid(valid_lifetime);
256}
257
259Subnet4::create(const IOAddress& prefix, uint8_t length,
260 const Triplet<uint32_t>& t1,
261 const Triplet<uint32_t>& t2,
262 const Triplet<uint32_t>& valid_lifetime,
263 const SubnetID id) {
264 Subnet4Ptr subnet = boost::make_shared<Subnet4>
265 (prefix, length, t1, t2, valid_lifetime, id);
266 subnet->setAllocator(Lease::TYPE_V4,
267 boost::make_shared<IterativeAllocator>
268 (Lease::TYPE_V4, subnet));
269 subnet->setAllocationState(Lease::TYPE_V4,
271
272 return (subnet);
273}
274
276Subnet4::getNextSubnet(const ConstSubnet4Ptr& first_subnet) const {
277 SharedNetwork4Ptr network;
278 getSharedNetwork(network);
279 if (network) {
280 return (network->getNextSubnet(first_subnet, getID()));
281 }
282
283 return (Subnet4Ptr());
284}
285
288 const ClientClasses& client_classes) const {
289 SharedNetwork4Ptr network;
290 getSharedNetwork(network);
291 // We can only get next subnet if shared network has been defined for
292 // the current subnet.
293 if (network) {
294 ConstSubnet4Ptr subnet;
295 do {
296 // Use subnet identifier of this subnet if this is the first
297 // time we're calling getNextSubnet. Otherwise, use the
298 // subnet id of the previously returned subnet.
299 SubnetID subnet_id = subnet ? subnet->getID() : getID();
300 subnet = network->getNextSubnet(first_subnet, subnet_id);
301 // If client classes match the subnet, return it. Otherwise,
302 // try another subnet.
303 if (subnet && subnet->clientSupported(client_classes)) {
304 return (subnet);
305 }
306 } while (subnet);
307 }
308
309 // No subnet found.
310 return (Subnet4Ptr());
311}
312
313
314bool
316 NetworkPtr network;
317 getSharedNetwork(network);
318 if (network && !network->clientSupported(client_classes)) {
319 return (false);
320 }
321
322 return (Network4::clientSupported(client_classes));
323}
324
326 // check if the type is valid (and throw if it isn't)
327 checkType(type);
328
329 switch (type) {
330 case Lease::TYPE_V4:
331 case Lease::TYPE_NA:
332 return (pools_);
333 case Lease::TYPE_PD:
334 return (pools_pd_);
335 default:
336 isc_throw(BadValue, "Unsupported pool type: "
337 << static_cast<int>(type));
338 }
339}
340
342 // check if the type is valid (and throw if it isn't)
343 checkType(type);
344
345 switch (type) {
346 case Lease::TYPE_V4:
347 case Lease::TYPE_NA:
348 return (pools_);
349 case Lease::TYPE_PD:
350 return (pools_pd_);
351 default:
352 isc_throw(BadValue, "Invalid pool type specified: "
353 << static_cast<int>(type));
354 }
355}
356
359 auto alloc = allocators_.find(type);
360
361 if (alloc == allocators_.end()) {
362 isc_throw(BadValue, "no allocator initialized for pool type "
363 << Lease::typeToText(type));
364 }
365 return (alloc->second);
366}
367
368void
370 allocators_[type] = allocator;
371}
372
375 auto state = allocation_states_.find(type);
376
377 if (state == allocation_states_.end()) {
378 isc_throw(BadValue, "no allocation state initialized for pool type "
379 << Lease::typeToText(type));
380 }
381 return (state->second);
382}
383
384void
386 allocation_states_[type] = allocation_state;
387}
388
390 bool anypool /* true */) const {
391 // check if the type is valid (and throw if it isn't)
392 checkType(type);
393
394 auto const& pools = getPools(type);
395
396 PoolPtr candidate;
397
398 if (!pools.empty()) {
399 // Pools are sorted by their first prefixes. For example: 2001::,
400 // 2001::db8::, 3000:: etc. If our hint is 2001:db8:5:: we want to
401 // find the pool with the longest matching prefix, so: 2001:db8::,
402 // rather than 2001::. upper_bound returns the first pool with a prefix
403 // that is greater than 2001:db8:5::, i.e. 3000::. To find the longest
404 // matching prefix we use decrement operator to go back by one item.
405 // If returned iterator points to begin it means that prefixes in all
406 // pools are greater than out prefix, and thus there is no match.
407 auto ub =
408 std::upper_bound(pools.begin(), pools.end(), hint,
409 prefixLessThanFirstAddress);
410
411 if (ub != pools.begin()) {
412 --ub;
413 if ((*ub)->inRange(hint)) {
414 candidate = *ub;
415 }
416 }
417
418 // If we don't find anything better, then let's just use the first pool
419 if (!candidate && anypool) {
420 candidate = *pools.begin();
421 }
422 }
423
424 // Return a pool or NULL if no match found.
425 return (candidate);
426}
427
428void
430 for (auto const& allocator : allocators_) {
431 allocator.second->initAfterConfigure();
432 }
433}
434
436 const ClientClasses& client_classes,
437 const isc::asiolink::IOAddress& hint) const {
438 // check if the type is valid (and throw if it isn't)
439 checkType(type);
440
441 auto const& pools = getPools(type);
442
443 PoolPtr candidate;
444
445 if (!pools.empty()) {
446 auto ub =
447 std::upper_bound(pools.begin(), pools.end(), hint,
448 prefixLessThanFirstAddress);
449
450 if (ub != pools.begin()) {
451 --ub;
452 if ((*ub)->inRange(hint) &&
453 (*ub)->clientSupported(client_classes)) {
454 candidate = *ub;
455 }
456 }
457 }
458
459 // Return a pool or NULL if no match found.
460 return (candidate);
461}
462
463void
465 // check if the type is valid (and throw if it isn't)
466 checkType(pool->getType());
467
468 // Check that the pool is in range with a subnet only if this is
469 // not a pool of IPv6 prefixes. The IPv6 prefixes delegated for
470 // the particular subnet don't need to match the prefix of the
471 // subnet.
472 if (pool->getType() != Lease::TYPE_PD) {
473 if (!inRange(pool->getFirstAddress()) || !inRange(pool->getLastAddress())) {
474 isc_throw(BadValue, "a pool of type "
475 << Lease::typeToText(pool->getType())
476 << ", with the following address range: "
477 << pool->getFirstAddress() << "-"
478 << pool->getLastAddress() << " does not match"
479 << " the prefix of a subnet: "
480 << prefix_ << "/" << static_cast<int>(prefix_len_)
481 << " to which it is being added");
482
483 }
484 }
485
486 bool overlaps = false;
487 if (pool->getType() == Lease::TYPE_V4) {
488 overlaps = poolOverlaps(Lease::TYPE_V4, pool);
489
490 } else {
491 overlaps =
494 }
495
496 if (overlaps) {
497 isc_throw(BadValue,"a pool of type "
498 << Lease::typeToText(pool->getType())
499 << ", with the following address range: "
500 << pool->getFirstAddress() << "-"
501 << pool->getLastAddress() << " overlaps with "
502 "an existing pool in the subnet: "
503 << prefix_ << "/" << static_cast<int>(prefix_len_)
504 << " to which it is being added");
505 }
506
507 PoolCollection& pools_writable = getPoolsWritable(pool->getType());
508
509 // Add the pool to the appropriate pools collection
510 pools_writable.push_back(pool);
511
512 // Sort pools by first address.
513 std::sort(pools_writable.begin(), pools_writable.end(),
514 comparePoolFirstAddress);
515}
516
517void
519 getPoolsWritable(type).clear();
520}
521
522bool
524
525 // Let's start with checking if it even belongs to that subnet.
526 if ((type != Lease::TYPE_PD) && !inRange(addr)) {
527 return (false);
528 }
529
530 auto const& pools = getPools(type);
531 for (auto const& pool : pools) {
532 if (pool->inRange(addr)) {
533 return (true);
534 }
535 }
536 // There's no pool that address belongs to
537 return (false);
538}
539
540bool
542 const isc::asiolink::IOAddress& addr,
543 const ClientClasses& client_classes) const {
544
545 // Let's start with checking if it even belongs to that subnet.
546 if ((type != Lease::TYPE_PD) && !inRange(addr)) {
547 return (false);
548 }
549
550 auto const& pools = getPools(type);
551 for (auto const& pool : pools) {
552 if (!pool->clientSupported(client_classes)) {
553 continue;
554 }
555 if (pool->inRange(addr)) {
556 return (true);
557 }
558 }
559 // There's no pool that address belongs to
560 return (false);
561}
562
563bool
564Subnet::poolOverlaps(const Lease::Type& pool_type, const PoolPtr& pool) const {
565 auto const& pools = getPools(pool_type);
566
567 // If no pools, we don't overlap. Nothing to do.
568 if (pools.empty()) {
569 return (false);
570 }
571
572 // We're going to insert a new pool, likely between two existing pools.
573 // So we're going to end up with the following case:
574 // |<---- pool1 ---->| |<-------- pool2 ------>| |<-- pool3 -->|
575 // F1 L1 F2 L2 F3 L3
576 // where pool1 and pool3 are existing pools, pool2 is a pool being
577 // inserted and "F"/"L" mark first and last address in the pools
578 // respectively. So the following conditions must be fulfilled:
579 // F2 > L1 and L2 < F3. Obviously, for any pool: F < L.
580
581 // Search for pool3. We use F2 and upper_bound to find the F3 (upper_bound
582 // returns first pool in the sorted container which first address is
583 // greater than F2). prefixLessThanPoolAddress with the first argument
584 // set to "true" is the custom comparison function for upper_bound, which
585 // compares F2 with the first addresses of the existing pools.
586 auto const pool3_it =
587 std::upper_bound(pools.begin(), pools.end(), pool->getFirstAddress(),
588 prefixLessThanFirstAddress);
589
590 // The upper_bound function returns a first pool which first address is
591 // greater than the address F2. However, it is also possible that there is a
592 // pool which first address is equal to F2. Such pool is also in conflict
593 // with a new pool. If the returned value is pools.begin() it means that all
594 // pools have greater first address than F2, thus none of the pools can have
595 // first address equal to F2. Otherwise, we'd need to check them for
596 // equality. However any pool has first address <= last address, so checking
597 // that the new pool first address is greater than the pool before pool3
598 // last address is enough. We now have to find the pool1. This pool should
599 // be right before the pool3 if there is any pool before pool3.
600 if (pool3_it != pools.begin()) {
601 PoolPtr pool1 = *(pool3_it - 1);
602 // F2 must be greater than L1, otherwise pools will overlap.
603 if (pool->getFirstAddress() <= pool1->getLastAddress()) {
604 return (true);
605 }
606 }
607
608 // If returned value is unequal pools.end() it means that there is a pool3,
609 // with F3 > F2.
610 if (pool3_it != pools.end()) {
611 // Let's store the pointer to this pool.
612 PoolPtr pool3 = *pool3_it;
613 // F3 must be greater than L2, otherwise pools will overlap.
614 if (pool3->getFirstAddress() <= pool->getLastAddress()) {
615 return (true);
616 }
617 }
618
619 return (false);
620}
621
622Subnet6::Subnet6(const IOAddress& prefix, uint8_t length,
623 const Triplet<uint32_t>& t1,
624 const Triplet<uint32_t>& t2,
625 const Triplet<uint32_t>& preferred_lifetime,
626 const Triplet<uint32_t>& valid_lifetime,
627 const SubnetID id)
628 : Subnet(prefix, length, id), Network6() {
629 if (!prefix.isV6()) {
630 isc_throw(BadValue, "Non IPv6 prefix " << prefix
631 << " specified in subnet6");
632 }
633
634 // Timers.
635 setT1(t1);
636 setT2(t2);
637 setPreferred(preferred_lifetime);
638 setValid(valid_lifetime);
639}
640
642Subnet6::create(const IOAddress& prefix, uint8_t length,
643 const Triplet<uint32_t>& t1,
644 const Triplet<uint32_t>& t2,
645 const Triplet<uint32_t>& preferred_lifetime,
646 const Triplet<uint32_t>& valid_lifetime,
647 const SubnetID id) {
648 Subnet6Ptr subnet = boost::make_shared<Subnet6>
649 (prefix, length, t1, t2, preferred_lifetime, valid_lifetime, id);
650 // IA_NA
651 subnet->setAllocator(Lease::TYPE_NA,
652 boost::make_shared<IterativeAllocator>
653 (Lease::TYPE_NA, subnet));
654 subnet->setAllocationState(Lease::TYPE_NA,
656 // IA_PD
657 subnet->setAllocator(Lease::TYPE_PD,
658 boost::make_shared<IterativeAllocator>
659 (Lease::TYPE_PD, subnet));
660 subnet->setAllocationState(Lease::TYPE_PD,
662 return (subnet);
663}
664
665void Subnet6::checkType(Lease::Type type) const {
666 if ((type != Lease::TYPE_NA) && (type != Lease::TYPE_PD)) {
667 isc_throw(BadValue, "Invalid Pool type: " << Lease::typeToText(type)
668 << "(" << static_cast<int>(type)
669 << "), must be TYPE_NA or TYPE_PD for Subnet6");
670 }
671}
672
674Subnet6::getNextSubnet(const ConstSubnet6Ptr& first_subnet) const {
675 SharedNetwork6Ptr network;
676 getSharedNetwork(network);
677 if (network) {
678 return (network->getNextSubnet(first_subnet, getID()));
679 }
680
681 return (Subnet6Ptr());
682}
683
686 const ClientClasses& client_classes) const {
687 SharedNetwork6Ptr network;
688 getSharedNetwork(network);
689 // We can only get next subnet if shared network has been defined for
690 // the current subnet.
691 if (network) {
692 ConstSubnet6Ptr subnet;
693 do {
694 // Use subnet identifier of this subnet if this is the first
695 // time we're calling getNextSubnet. Otherwise, use the
696 // subnet id of the previously returned subnet.
697 SubnetID subnet_id = subnet ? subnet->getID() : getID();
698 subnet = network->getNextSubnet(first_subnet, subnet_id);
699 // If client classes match the subnet, return it. Otherwise,
700 // try another subnet.
701 if (subnet && subnet->clientSupported(client_classes)) {
702 return (subnet);
703 }
704 } while (subnet);
705 }
706
707 // No subnet found.
708 return (Subnet6Ptr());
709}
710
711bool
713 NetworkPtr network;
714 getSharedNetwork(network);
715 if (network && !network->clientSupported(client_classes)) {
716 return (false);
717 }
718
719 return (Network6::clientSupported(client_classes));
720}
721
725
726 // Add user-context
727 contextToElement(map);
728
729 // Set subnet id
730 SubnetID id = getID();
731 map->set("id", Element::create(static_cast<long long>(id)));
732
733 // Set subnet
734 map->set("subnet", Element::create(toText()));
735
736 return (map);
737}
738
739void
741 auto allocator_type = getAllocatorType();
742 if (allocator_type.empty()) {
743 allocator_type = getDefaultAllocatorType();
744 }
745 if (allocator_type == "random") {
747 boost::make_shared<RandomAllocator>
748 (Lease::TYPE_V4, shared_from_this()));
750
751 for (auto const& pool : pools_) {
752 pool->setAllocationState(PoolRandomAllocationState::create(pool));
753 }
754
755 } else if (allocator_type == "flq") {
757 boost::make_shared<FreeLeaseQueueAllocator>
758 (Lease::TYPE_V4, shared_from_this()));
760
761 for (auto const& pool : pools_) {
762 pool->setAllocationState(PoolFreeLeaseQueueAllocationState::create(pool));
763 }
764 } else if (allocator_type == "shared-flq") {
766 boost::make_shared<SharedFlqAllocator>
767 (Lease::TYPE_V4, shared_from_this()));
769 boost::make_shared<SubnetSflqAllocationState>());
770 // Does not use pool level allocation states.
771 } else {
773 boost::make_shared<IterativeAllocator>
774 (Lease::TYPE_V4, shared_from_this()));
776 SubnetIterativeAllocationState::create(shared_from_this()));
777
778 for (auto const& pool : pools_) {
779 pool->setAllocationState(PoolIterativeAllocationState::create(pool));
780 }
781 }
782}
783
786 // Prepare the map
788 ElementPtr network_map = Network4::toElement();
789
790 merge(map, network_map);
791
792 // Set DHCP4o6
793 const Cfg4o6& d4o6 = get4o6();
794 isc::data::merge(map, d4o6.toElement());
795
796 // Set pools
797 auto const& pools = getPools(Lease::TYPE_V4);
798 ElementPtr pool_list = Element::createList();
799 for (auto const& pool : pools) {
800 // Add the formatted pool to the list
801 pool_list->add(pool->toElement());
802 }
803 map->set("pools", pool_list);
804
805 return (map);
806}
807
808std::pair<IOAddress, uint8_t>
809Subnet4::parsePrefix(const std::string& prefix) {
810 std::pair<IOAddress, uint8_t> parsed = Subnet::parsePrefixCommon(prefix);
811 if (!parsed.first.isV4() || parsed.first.isV4Zero() ||
812 (parsed.second > 32) || (parsed.second == 0)) {
813 isc_throw(BadValue, "unable to parse invalid IPv4 prefix " << prefix);
814 }
815 return (parsed);
816}
817
818void
820 auto allocator_type = getAllocatorType();
821 if (allocator_type.empty()) {
822 allocator_type = getDefaultAllocatorType();
823 }
824 if (allocator_type == "random") {
826 boost::make_shared<RandomAllocator>
827 (Lease::TYPE_NA, shared_from_this()));
829
830 } else if (allocator_type == "flq") {
831 isc_throw(BadValue, "Free Lease Queue allocator is not supported for IPv6 address pools");
832 } else if (allocator_type == "shared-flq") {
834 boost::make_shared<SharedFlqAllocator>
835 (Lease::TYPE_NA, shared_from_this()));
837 boost::make_shared<SubnetSflqAllocationState>());
838 } else {
840 boost::make_shared<IterativeAllocator>
841 (Lease::TYPE_NA, shared_from_this()));
843 }
844
845 auto pd_allocator_type = getPdAllocatorType();
846 if (pd_allocator_type.empty()) {
847 pd_allocator_type = getDefaultPdAllocatorType();
848 }
849 // Repeat the same for the delegated prefix allocator.
850 if (pd_allocator_type == "random") {
852 boost::make_shared<RandomAllocator>
853 (Lease::TYPE_PD, shared_from_this()));
855
856 } else if (pd_allocator_type == "flq") {
858 boost::make_shared<FreeLeaseQueueAllocator>
859 (Lease::TYPE_PD, shared_from_this()));
861 } else if (pd_allocator_type == "shared-flq") {
863 boost::make_shared<SharedFlqAllocator>
864 (Lease::TYPE_PD, shared_from_this()));
866 boost::make_shared<SubnetSflqAllocationState>());
867 // Does not use pool level allocation states.
868 } else {
870 boost::make_shared<IterativeAllocator>
871 (Lease::TYPE_PD, shared_from_this()));
873 }
874 // Create allocation states for NA pools.
875 for (auto const& pool : pools_) {
876 if (allocator_type == "random") {
877 pool->setAllocationState(PoolRandomAllocationState::create(pool));
878 } else {
879 pool->setAllocationState(PoolIterativeAllocationState::create(pool));
880 }
881 }
882 // Create allocation states for PD pools.
883 for (auto const& pool : pools_pd_) {
884 if (pd_allocator_type == "random") {
885 pool->setAllocationState(PoolRandomAllocationState::create(pool));
886 } else if (pd_allocator_type == "flq") {
887 pool->setAllocationState(PoolFreeLeaseQueueAllocationState::create(pool));
888 } else {
889 pool->setAllocationState(PoolIterativeAllocationState::create(pool));
890 }
891 }
892}
893
896 // Prepare the map
898 ElementPtr network_map = Network6::toElement();
899
900 merge(map, network_map);
901
902 // Set pools
903 auto const& pools = getPools(Lease::TYPE_NA);
904 ElementPtr pool_list = Element::createList();
905 for (auto const& pool : pools) {
906 // Add the formatted pool to the list
907 pool_list->add(pool->toElement());
908 }
909 map->set("pools", pool_list);
910
911 // Set pd-pools
912 auto const& pdpools = getPools(Lease::TYPE_PD);
913 ElementPtr pdpool_list = Element::createList();
914 for (auto const& pool : pdpools) {
915 // Add the formatted pool to the list
916 pdpool_list->add(pool->toElement());
917 }
918 map->set("pd-pools", pdpool_list);
919
920 return (map);
921}
922
923std::pair<IOAddress, uint8_t>
924Subnet6::parsePrefix(const std::string& prefix) {
925 std::pair<IOAddress, uint8_t> parsed = Subnet::parsePrefixCommon(prefix);
926 if (!parsed.first.isV6() || parsed.first.isV6Zero() ||
927 (parsed.second > 128) || (parsed.second == 0)) {
928 isc_throw(BadValue, "unable to parse invalid IPv6 prefix " << prefix);
929 }
930 return (parsed);
931}
932
933} // namespace dhcp
934} // namespace isc
A generic exception that is thrown if a parameter given to a method is considered invalid in that con...
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
static ElementPtr createList(const Position &pos=ZERO_POSITION())
Creates an empty ListElement type ElementPtr.
Definition data.cc:349
PrefixLenMatchType
Type of preferred PD-pool prefix length selection criteria.
Definition allocator.h:61
static bool isValidPrefixPool(Allocator::PrefixLenMatchType prefix_length_match, PoolPtr pool, uint8_t hint_prefix_length)
Check if the pool matches the selection criteria relative to the provided hint prefix length.
Definition allocator.cc:38
Container for storing client class names.
Definition classify.h:110
Network4()
Constructor.
Definition network.h:1354
virtual data::ElementPtr toElement() const
Unparses network object.
Definition network.cc:307
util::Optional< std::string > getDefaultPdAllocatorType(const Inheritance &inheritance=Inheritance::ALL) const
Returns a default allocator type for prefix delegation.
Definition network.h:1607
Network6()
Constructor.
Definition network.h:1515
void setPreferred(const isc::util::Triplet< uint32_t > &preferred)
Sets new preferred lifetime for a network.
Definition network.h:1536
virtual data::ElementPtr toElement() const
Unparses network object.
Definition network.cc:359
util::Optional< std::string > getPdAllocatorType(const Inheritance &inheritance=Inheritance::ALL) const
Returns allocator type for prefix delegation.
Definition network.h:1582
virtual bool clientSupported(const isc::dhcp::ClientClasses &client_classes) const
Checks whether this network supports a client that belongs to the specified classes.
Definition network.cc:69
void setT2(const isc::util::Triplet< uint32_t > &t2)
Sets new rebind timer for a network.
Definition network.h:419
util::Optional< std::string > getAllocatorType(const Inheritance &inheritance=Inheritance::ALL) const
Returns allocator type.
Definition network.h:860
util::Optional< std::string > getDefaultAllocatorType(const Inheritance &inheritance=Inheritance::ALL) const
Returns a default allocator type.
Definition network.h:885
void setT1(const isc::util::Triplet< uint32_t > &t1)
Sets new renew timer for a network.
Definition network.h:404
void setValid(const isc::util::Triplet< uint32_t > &valid)
Sets new valid lifetime for a network.
Definition network.h:389
static PoolFreeLeaseQueueAllocationStatePtr create(const PoolPtr &pool)
Factory function creating the state instance from a pool.
static PoolIterativeAllocationStatePtr create(const PoolPtr &pool)
Factory function creating the state instance from pool.
static PoolRandomAllocationStatePtr create(const PoolPtr &pool)
Factory function creating the state instance from pool.
virtual bool clientSupported(const isc::dhcp::ClientClasses &client_classes) const
Checks whether this subnet and parent shared network supports the client that belongs to specified cl...
Definition subnet.cc:315
Cfg4o6 & get4o6()
Returns DHCP4o6 configuration parameters.
Definition subnet.h:557
ConstSubnet4Ptr getNextSubnet(const ConstSubnet4Ptr &first_subnet) const
Returns next subnet within shared network.
Definition subnet.cc:276
virtual void createAllocators()
Instantiates the allocator and its state.
Definition subnet.cc:740
virtual data::ElementPtr toElement() const
Unparse a subnet object.
Definition subnet.cc:785
static Subnet4Ptr create(const isc::asiolink::IOAddress &prefix, uint8_t length, const util::Triplet< uint32_t > &t1, const util::Triplet< uint32_t > &t2, const util::Triplet< uint32_t > &valid_lifetime, const SubnetID id)
Factory function creating an instance of the Subnet4.
Definition subnet.cc:259
Subnet4(const isc::asiolink::IOAddress &prefix, uint8_t length, const util::Triplet< uint32_t > &t1, const util::Triplet< uint32_t > &t2, const util::Triplet< uint32_t > &valid_lifetime, const SubnetID id)
Constructor with all parameters.
Definition subnet.cc:242
static std::pair< asiolink::IOAddress, uint8_t > parsePrefix(const std::string &prefix)
Converts subnet prefix to a pair of prefix/length pair.
Definition subnet.cc:809
virtual bool clientSupported(const isc::dhcp::ClientClasses &client_classes) const
Checks whether this subnet and parent shared network supports the client that belongs to specified cl...
Definition subnet.cc:712
static Subnet6Ptr create(const isc::asiolink::IOAddress &prefix, uint8_t length, const util::Triplet< uint32_t > &t1, const util::Triplet< uint32_t > &t2, const util::Triplet< uint32_t > &preferred_lifetime, const util::Triplet< uint32_t > &valid_lifetime, const SubnetID id)
Factory function creating an instance of the Subnet4.
Definition subnet.cc:642
static std::pair< asiolink::IOAddress, uint8_t > parsePrefix(const std::string &prefix)
Converts subnet prefix to a pair of prefix/length pair.
Definition subnet.cc:924
virtual void createAllocators()
Instantiates the allocators and their states.
Definition subnet.cc:819
virtual data::ElementPtr toElement() const
Unparse a subnet object.
Definition subnet.cc:895
ConstSubnet6Ptr getNextSubnet(const ConstSubnet6Ptr &first_subnet) const
Returns next subnet within shared network.
Definition subnet.cc:674
Subnet6(const isc::asiolink::IOAddress &prefix, uint8_t length, const util::Triplet< uint32_t > &t1, const util::Triplet< uint32_t > &t2, const util::Triplet< uint32_t > &preferred_lifetime, const util::Triplet< uint32_t > &valid_lifetime, const SubnetID id)
Constructor with all parameters.
Definition subnet.cc:622
static SubnetIterativeAllocationStatePtr create(const SubnetPtr &subnet)
Factory function creating the state instance from subnet.
isc::util::uint128_t getPoolCapacity(Lease::Type type) const
Returns the number of possible leases for specified lease type.
Definition subnet.cc:99
isc::asiolink::IOAddress prefix_
a prefix of the subnet.
Definition subnet.h:430
SubnetID getID() const
Returns unique ID for that subnet.
Definition subnet.h:83
uint8_t prefix_len_
a prefix length of the subnet.
Definition subnet.h:433
isc::util::uint128_t sumPoolCapacity(const PoolCollection &pools) const
Returns a sum of possible leases in all pools.
Definition subnet.cc:146
virtual data::ElementPtr toElement() const
Unparse a subnet object.
Definition subnet.cc:723
AllocatorPtr getAllocator(Lease::Type type) const
Returns lease allocator instance.
Definition subnet.cc:358
void getSharedNetwork(SharedNetworkPtrType &shared_network) const
Retrieves pointer to a shared network associated with a subnet.
Definition subnet.h:231
void initAllocatorsAfterConfigure()
Calls initAfterConfigure for each allocator.
Definition subnet.cc:429
SubnetID id_
subnet-id
Definition subnet.h:421
SubnetAllocationStatePtr getAllocationState(Lease::Type type) const
Returns subnet-specific allocation state.
Definition subnet.cc:374
void addPool(const PoolPtr &pool)
Adds a new pool for the subnet.
Definition subnet.cc:464
bool inRange(const isc::asiolink::IOAddress &addr) const
checks if specified address is in range.
Definition subnet.cc:84
std::map< Lease::Type, AllocatorPtr > allocators_
Lease allocators used by the subnet.
Definition subnet.h:439
virtual std::string toText() const
Returns textual representation of the subnet (e.g.
Definition subnet.cc:92
void delPools(Lease::Type type)
Deletes all pools of specified type.
Definition subnet.cc:518
static std::pair< asiolink::IOAddress, uint8_t > parsePrefixCommon(const std::string &prefix)
Converts subnet prefix to a pair of prefix/length pair.
Definition subnet.cc:217
void setAllocator(Lease::Type type, const AllocatorPtr &allocator)
Sets new allocator instance.
Definition subnet.cc:369
PoolCollection pools_
collection of IPv4 or non-temporary IPv6 pools in that subnet.
Definition subnet.h:424
PoolCollection & getPoolsWritable(Lease::Type type)
Returns all pools (non-const variant).
Definition subnet.cc:341
const PoolPtr getPool(Lease::Type type, const isc::asiolink::IOAddress &addr, bool anypool=true) const
Returns a pool that specified address belongs to.
Definition subnet.cc:389
Subnet(const isc::asiolink::IOAddress &prefix, uint8_t len, const SubnetID id)
Protected constructor.
Definition subnet.cc:70
std::string shared_network_name_
Shared network name.
Definition subnet.h:436
bool poolOverlaps(const Lease::Type &pool_type, const PoolPtr &pool) const
Checks if the specified pool overlaps with an existing pool.
Definition subnet.cc:564
PoolCollection pools_pd_
collection of IPv6 prefix pools in that subnet.
Definition subnet.h:427
const PoolCollection & getPools(Lease::Type type) const
Returns all pools (const variant).
Definition subnet.cc:325
virtual void checkType(Lease::Type type) const =0
Checks if used pool type is valid.
std::map< Lease::Type, SubnetAllocationStatePtr > allocation_states_
Holds subnet-specific allocation state.
Definition subnet.h:442
bool inPool(Lease::Type type, const isc::asiolink::IOAddress &addr) const
checks if the specified address is in pools.
Definition subnet.cc:523
void setAllocationState(Lease::Type type, const SubnetAllocationStatePtr &allocation_state)
Sets subnet-specific allocation state.
Definition subnet.cc:385
This template specifies a parameter value.
Definition triplet.h:37
#define isc_throw(type, stream)
A shortcut macro to insert known values into exception arguments.
void merge(ElementPtr element, ConstElementPtr other)
Merges the data from other into element. (on the first level).
Definition data.cc:1281
boost::shared_ptr< Element > ElementPtr
Definition data.h:29
boost::shared_ptr< Subnet4 > Subnet4Ptr
A pointer to a Subnet4 object.
Definition subnet.h:458
boost::shared_ptr< const Subnet6 > ConstSubnet6Ptr
A const pointer to a Subnet6 object.
Definition subnet.h:620
boost::shared_ptr< const Subnet4 > ConstSubnet4Ptr
A const pointer to a Subnet4 object.
Definition subnet.h:455
boost::shared_ptr< Subnet6 > Subnet6Ptr
A pointer to a Subnet6 object.
Definition subnet.h:623
std::vector< PoolPtr > PoolCollection
a container for either IPv4 or IPv6 Pools
Definition pool.h:729
boost::shared_ptr< SharedNetwork6 > SharedNetwork6Ptr
Pointer to SharedNetwork6 object.
boost::shared_ptr< Pool > PoolPtr
a pointer to either IPv4 or IPv6 Pool
Definition pool.h:726
uint32_t SubnetID
Defines unique IPv4 or IPv6 subnet identifier.
Definition subnet_id.h:25
boost::shared_ptr< Network > NetworkPtr
Pointer to the Network object.
Definition network.h:73
boost::shared_ptr< Allocator > AllocatorPtr
Defines a pointer to an allocator.
Definition allocator.h:269
boost::shared_ptr< SubnetAllocationState > SubnetAllocationStatePtr
boost::shared_ptr< SharedNetwork4 > SharedNetwork4Ptr
Pointer to SharedNetwork4 object.
boost::multiprecision::checked_uint128_t uint128_t
Definition bigints.h:21
Defines the logger used by the top-level component of kea-lfc.
void contextToElement(data::ElementPtr map) const
Merge unparse a user_context object.
This structure contains information about DHCP4o6 (RFC7341).
Definition cfg_4o6.h:22
virtual isc::data::ElementPtr toElement() const
Unparse a configuration object.
Definition cfg_4o6.cc:22
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