]> git.ipfire.org Git - thirdparty/kea.git/commitdiff
[#969] Added ability to reset permutation
authorMarcin Siodelski <marcin@isc.org>
Mon, 24 Oct 2022 12:51:56 +0000 (14:51 +0200)
committerMarcin Siodelski <marcin@isc.org>
Sat, 7 Jan 2023 10:45:05 +0000 (11:45 +0100)
src/lib/dhcpsrv/ip_range_permutation.cc
src/lib/dhcpsrv/ip_range_permutation.h
src/lib/dhcpsrv/tests/ip_range_permutation_unittest.cc

index 8785e54174b4f3d0d9b9bf296f97da7558c70f0d..ad622d6abd03ea400b5b788543c791276e891f69 100644 (file)
@@ -1,4 +1,4 @@
-// Copyright (C) 2020 Internet Systems Consortium, Inc. ("ISC")
+// Copyright (C) 2020-2022 Internet Systems Consortium, Inc. ("ISC")
 //
 // This Source Code Form is subject to the terms of the Mozilla Public
 // License, v. 2.0. If a copy of the MPL was not distributed with this
@@ -17,7 +17,7 @@ namespace dhcp {
 
 IPRangePermutation::IPRangePermutation(const AddressRange& range)
     : range_start_(range.start_), step_(1), cursor_(addrsInRange(range_start_, range.end_) - 1),
-      state_(), done_(false), generator_() {
+      initial_cursor_(cursor_), state_(), done_(false), generator_() {
     std::random_device rd;
     generator_.seed(rd());
 }
@@ -25,7 +25,7 @@ IPRangePermutation::IPRangePermutation(const AddressRange& range)
 IPRangePermutation::IPRangePermutation(const PrefixRange& range)
     : range_start_(range.start_), step_(static_cast<uint64_t>(1) << (128 - range.delegated_length_)),
       cursor_(prefixesInRange(range.prefix_length_, range.delegated_length_) - 1),
-      state_(), done_(false), generator_() {
+      initial_cursor_(cursor_), state_(), done_(false), generator_() {
 }
 
 IOAddress
@@ -97,5 +97,12 @@ IPRangePermutation::next(bool& done) {
     return (next_loc_address);
 }
 
+void
+IPRangePermutation::reset() {
+    state_.clear();
+    cursor_ = initial_cursor_;
+    done_ = false;
+}
+
 } // end of namespace isc::dhcp
 } // end of namespace isc
index c03a471fbfa41f58ecd9574adb003271eb507021..76868947f81d795704b4d92fbaa34dd6034fe6db 100644 (file)
@@ -1,4 +1,4 @@
-// Copyright (C) 2020-2021 Internet Systems Consortium, Inc. ("ISC")
+// Copyright (C) 2020-2022 Internet Systems Consortium, Inc. ("ISC")
 //
 // This Source Code Form is subject to the terms of the Mozilla Public
 // License, v. 2.0. If a copy of the MPL was not distributed with this
@@ -99,6 +99,13 @@ public:
     /// prefixes in the range.
     asiolink::IOAddress next(bool& done);
 
+    /// @brief Resets the permutation state.
+    ///
+    /// It effectively causes the permutation to start over the process of
+    /// serving addresses. Any previously returned addresses can be returned
+    /// again after calling this function.
+    void reset();
+
 private:
 
     /// Beginning of the range.
@@ -115,6 +122,9 @@ private:
     /// is returned.
     uint64_t cursor_;
 
+    /// Keeps the initial cursor position for @c reset function.
+    uint64_t initial_cursor_;
+
     /// Keeps the current permutation state. The state associates the
     /// swapped IP addresses or delegated prefixes with their positions in
     /// the permutation.
index 25a45f4397501889044d4c3044abf64359196889..339f53e3a672c4b11da547b048c56fca5dbd3593 100644 (file)
@@ -137,4 +137,33 @@ TEST(IPRangePermutationTest, pd) {
     EXPECT_TRUE(addrs.begin()->isV6Zero());
 }
 
+// This test verifies that it is possible to reset the permutation state.
+TEST(IPRangePermutationTest, reset) {
+    // Create address range with 11 addresses.
+    AddressRange range(IOAddress("192.0.2.10"), IOAddress("192.0.2.20"));
+    IPRangePermutation perm(range);
+
+    // This set will record unique IP addresses generated.
+    std::set<IOAddress> addrs;
+    bool done = false;
+
+    // Call the next() function several times to consume several addresses.
+    for (auto i = 0; i < 5; ++i) {
+        auto next = perm.next(done);
+        EXPECT_FALSE(next.isV4Zero());
+        addrs.insert(next);
+    }
+    EXPECT_EQ(5, addrs.size());
+
+    // Reset the permutation. We should be able to get all addresses again.
+    perm.reset();
+
+    for (auto i = 0; i < 11; ++i) {
+        auto next = perm.next(done);
+        EXPECT_FALSE(next.isV4Zero());
+        addrs.insert(next);
+    }
+    EXPECT_EQ(11, addrs.size());
+}
+
 } // end of anonymous namespace