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