diff options
author | Andrei Pavel <andrei@isc.org> | 2023-04-26 14:45:29 +0200 |
---|---|---|
committer | Andrei Pavel <andrei@isc.org> | 2023-05-17 18:09:38 +0200 |
commit | 4a06d2baf0dff1d21948bd9a39f100c94a159fe0 (patch) | |
tree | 83c4bce0b946e63e204521806ad0341f747e5f46 /src/lib/asiolink | |
parent | [#2658] add BigIntElement (diff) | |
download | kea-4a06d2baf0dff1d21948bd9a39f100c94a159fe0.tar.xz kea-4a06d2baf0dff1d21948bd9a39f100c94a159fe0.zip |
[#2658] add big integer support to statistics
Pool capacities have been promoted in code from uint64_t to uint128_t.
Bigint is modelled as an int128_t in statistics, following the precedent of
signed integer of int64_t from statistics.
- "total-nas" is extended to 128 bits as requested in the issue.
- "total-pds" has the same risk of overflowing so it has been extended
as well.
- "total-addresses" always fits in 64 bits, but certain code forces a
128 bit value on it. See Pool::getCapacity(), Subnet::getPoolCapacity(),
Subnet::sumPoolCapacity(). It could have been truncated to a 64 bit value,
but that seems like an unnecessary complication.
Because of the disparity in signedness there is some truncation that can
happen when pool capacity values are passed on to statistics. That only happens
for the last half of the value range, so for prefix ranges larger than /1.
Diffstat (limited to 'src/lib/asiolink')
-rw-r--r-- | src/lib/asiolink/addr_utilities.cc | 28 | ||||
-rw-r--r-- | src/lib/asiolink/addr_utilities.h | 9 | ||||
-rw-r--r-- | src/lib/asiolink/tests/addr_utilities_unittest.cc | 10 |
3 files changed, 21 insertions, 26 deletions
diff --git a/src/lib/asiolink/addr_utilities.cc b/src/lib/asiolink/addr_utilities.cc index 04b44dc517..d99c66b49a 100644 --- a/src/lib/asiolink/addr_utilities.cc +++ b/src/lib/asiolink/addr_utilities.cc @@ -15,6 +15,7 @@ using namespace isc; using namespace isc::asiolink; +using namespace isc::util; namespace { @@ -199,7 +200,7 @@ IOAddress getNetmask4(uint8_t len) { return (IOAddress(x)); } -uint64_t +uint128_t addrsInRange(const IOAddress& min, const IOAddress& max) { if (min.getFamily() != max.getFamily()) { isc_throw(BadValue, "Both addresses have to be the same family"); @@ -349,28 +350,19 @@ prefixLengthFromRange(const IOAddress& min, const IOAddress& max) { } } -uint64_t prefixesInRange(const uint8_t pool_len, const uint8_t delegated_len) { +uint128_t prefixesInRange(const uint8_t pool_len, const uint8_t delegated_len) { if (delegated_len < pool_len) { return (0); } - uint64_t count = delegated_len - pool_len; - - if (count == 0) { - // If we want to delegate /64 out of /64 pool, we have only - // one prefix. - return (1); - } else if (count >= 64) { - // If the difference is greater than or equal 64, e.g. we want to - // delegate /96 out of /16 pool, the number is bigger than we can - // express, so we'll stick with maximum value of uint64_t. - return (std::numeric_limits<uint64_t>::max()); - } else { - // Now count specifies the exponent (e.g. if the difference between the - // delegated and pool length is 4, we have 16 prefixes), so we need - // to calculate 2^(count - 1) - return ((static_cast<uint64_t>(2)) << (count - 1)); + uint8_t const count(delegated_len - pool_len); + + if (count == 128) { + // One off is the best we can do, unless we promote to uint256_t. + return uint128_t(-1); } + + return (uint128_t(1) << count); } IOAddress offsetAddress(const IOAddress& addr, uint64_t offset) { diff --git a/src/lib/asiolink/addr_utilities.h b/src/lib/asiolink/addr_utilities.h index bd78deec4c..9aa9af2d10 100644 --- a/src/lib/asiolink/addr_utilities.h +++ b/src/lib/asiolink/addr_utilities.h @@ -8,6 +8,7 @@ #define ADDR_UTILITIES_H #include <asiolink/io_address.h> +#include <util/bigints.h> namespace isc { namespace asiolink { @@ -54,7 +55,7 @@ IOAddress getNetmask4(uint8_t len); /// @param min the first address in range /// @param max the last address in range /// @return number of addresses in range -uint64_t addrsInRange(const IOAddress& min, const IOAddress& max); +isc::util::uint128_t addrsInRange(const IOAddress& min, const IOAddress& max); /// @brief Returns prefix length from the specified range (min - max). /// @@ -78,7 +79,7 @@ int prefixLengthFromRange(const IOAddress& min, const IOAddress& max); /// @param pool_len length of the pool in bits /// @param delegated_len length of the prefixes to be delegated from the pool /// @return number of prefixes in range -uint64_t prefixesInRange(const uint8_t pool_len, const uint8_t delegated_len); +isc::util::uint128_t prefixesInRange(const uint8_t pool_len, const uint8_t delegated_len); /// @brief Finds the address increased by offset. /// @@ -92,7 +93,7 @@ uint64_t prefixesInRange(const uint8_t pool_len, const uint8_t delegated_len); /// @return address being offset greater than the input address IOAddress offsetAddress(const IOAddress& addr, uint64_t offset); -}; -}; +} // namespace asiolink +} // namespace isc #endif // ADDR_UTILITIES_H diff --git a/src/lib/asiolink/tests/addr_utilities_unittest.cc b/src/lib/asiolink/tests/addr_utilities_unittest.cc index a8564379a6..df7a6aca18 100644 --- a/src/lib/asiolink/tests/addr_utilities_unittest.cc +++ b/src/lib/asiolink/tests/addr_utilities_unittest.cc @@ -8,6 +8,7 @@ #include <asiolink/addr_utilities.h> #include <exceptions/exceptions.h> +#include <util/bigints.h> #include <gtest/gtest.h> @@ -18,6 +19,7 @@ using namespace std; using namespace isc::asiolink; +using namespace isc::util; namespace { @@ -358,13 +360,13 @@ TEST(AddrUtilitiesTest, prefixesInRange) { EXPECT_EQ(uint64_t(9223372036854775808ull), prefixesInRange(64, 127)); // How many /128 prefixes are in /64 pool? - EXPECT_EQ(std::numeric_limits<uint64_t>::max(), - prefixesInRange(64, 128)); + EXPECT_EQ(uint128_t(1) << 64, prefixesInRange(64, 128)); // Let's go overboard again. How many IPv6 addresses are there? - EXPECT_EQ(std::numeric_limits<uint64_t>::max(), - prefixesInRange(0, 128)); + EXPECT_EQ(uint128_t(1) << 127, prefixesInRange(1, 128)); + // Let's go overboard again. How many IPv6 addresses are there? + EXPECT_EQ(uint128_t(-1), prefixesInRange(0, 128)); } // Checks the function which finds an IPv4 address from input address and offset. |