Kea 2.2.0
ip_range_permutation.cc
Go to the documentation of this file.
1// Copyright (C) 2020 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>
10
11#include <iostream>
12
13using namespace isc::asiolink;
14
15namespace isc {
16namespace dhcp {
17
19 : range_start_(range.start_), step_(1), cursor_(addrsInRange(range_start_, range.end_) - 1),
20 state_(), done_(false), generator_() {
21 std::random_device rd;
22 generator_.seed(rd());
23}
24
26 : range_start_(range.start_), step_(static_cast<uint64_t>(1) << (128 - range.delegated_length_)),
27 cursor_(prefixesInRange(range.prefix_length_, range.delegated_length_) - 1),
28 state_(), done_(false), generator_() {
29}
30
33 // If we're done iterating over the pool let's return zero address and
34 // set the user supplied done flag to true.
35 if (done_) {
36 done = true;
38 }
39
40 // If there is one address left, return this address.
41 if (cursor_ == 0) {
42 done = done_ = true;
43 return (state_.at(0));
44 }
45
46 // We're not done.
47 done = false;
48
49 // The cursor indicates where we're in the range starting from its end. The
50 // addresses between the cursor and the end of the range have been already
51 // returned by this function. Therefore we focus on the remaining cursor-1
52 // addresses. Let's get random address from this sub-range.
53 std::uniform_int_distribution<int> dist(0, cursor_ - 1);
54 auto next_loc = dist(generator_);
55
56 IOAddress next_loc_address = IOAddress::IPV4_ZERO_ADDRESS();
57
58 // Check whether this address exists in our map or not. If it exists
59 // it means it was swapped with some other address in previous calls to
60 // this function.
61 auto next_loc_existing = state_.find(next_loc);
62 if (next_loc_existing != state_.end()) {
63 // Address exists, so let's record it.
64 next_loc_address = next_loc_existing->second;
65 } else {
66 // Address does not exist on this position. We infer this address from
67 // its position by advancing the range start by position. For example,
68 // if the range is 192.0.2.1-192.0.2.10 and the picked random position is
69 // 5, the address we get is 192.0.2.6. This random address will be later
70 // returned to the caller.
71 next_loc_address = offsetAddress(range_start_, next_loc * step_);
72 }
73
74 // Let's get the address at cursor position in the same way.
75 IOAddress cursor_address = IOAddress::IPV4_ZERO_ADDRESS();
76 auto cursor_existing = state_.find(cursor_);
77 if (cursor_existing != state_.end()) {
78 cursor_address = cursor_existing->second;
79 } else {
80 cursor_address = offsetAddress(range_start_, cursor_ * step_);
81 }
82
83 // Now we swap them.... in fact we don't swap because as an optimization
84 // we don't record the addresses we returned by this function. We merely
85 // replace the address at random position with the address from cursor
86 // position. This address will be returned in the future if we get back
87 // to this position as a result of randomization.
88 if (next_loc_existing == state_.end()) {
89 state_.insert(std::make_pair(next_loc, cursor_address));
90 } else {
91 state_.at(next_loc) = cursor_address;
92 }
93 // Move the cursor one position backwards.
94 --cursor_;
95
96 // Return the address from the random position.
97 return (next_loc_address);
98}
99
100} // end of namespace isc::dhcp
101} // end of namespace isc
asiolink::IOAddress next(bool &done)
Returns next random address or prefix from the permutation.
IPRangePermutation(const AddressRange &range)
Constructor for address ranges.
Defines the logger used by the top-level component of kea-lfc.
Structure representing IP address range.
Definition: ip_range.h:16
Structure representing delegated prefix range.
Definition: ip_range.h:32