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