2
0
mirror of https://gitlab.isc.org/isc-projects/kea synced 2025-09-05 00:15:17 +00:00

[#2780] Removed unused code

This commit is contained in:
Marcin Siodelski
2023-03-20 21:49:12 +01:00
parent 147da862f2
commit 373ae7c427
5 changed files with 1 additions and 1277 deletions

View File

@@ -109,7 +109,6 @@ libkea_dhcpsrv_la_SOURCES += dhcpsrv_log.cc dhcpsrv_log.h
libkea_dhcpsrv_la_SOURCES += dhcpsrv_messages.h dhcpsrv_messages.cc
libkea_dhcpsrv_la_SOURCES += flq_allocation_state.cc flq_allocation_state.h
libkea_dhcpsrv_la_SOURCES += flq_allocator.cc flq_allocator.h
libkea_dhcpsrv_la_SOURCES += free_lease_queue.h free_lease_queue.cc
libkea_dhcpsrv_la_SOURCES += host.cc host.h
libkea_dhcpsrv_la_SOURCES += host_container.h
libkea_dhcpsrv_la_SOURCES += host_data_source_factory.cc host_data_source_factory.h
@@ -343,7 +342,7 @@ libkea_dhcpsrv_include_HEADERS = \
db_type.h \
dhcp4o6_ipc.h \
dhcpsrv_log.h \
free_lease_queue.h \
flq_allocator.h \
host.h \
host_container.h \
host_data_source_factory.h \

View File

@@ -1,249 +0,0 @@
// Copyright (C) 2020-2021 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
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
#include <config.h>
#include <asiolink/addr_utilities.h>
#include <dhcpsrv/free_lease_queue.h>
#include <boost/make_shared.hpp>
#include <iostream>
#include <tuple>
#include <utility>
using namespace isc::asiolink;
namespace isc {
namespace dhcp {
FreeLeaseQueue::FreeLeaseQueue()
: ranges_() {
}
void
FreeLeaseQueue::addRange(const AddressRange& range) {
// If the container with ranges is empty, there are is no need for
// doing any checks. Let's just add the new range.
if (!ranges_.empty()) {
checkRangeOverlaps(range.start_, range.end_);
}
ranges_.insert(RangeDescriptor{range.start_, range.end_, 128, boost::make_shared<Leases>()});
}
void
FreeLeaseQueue::addRange(const IOAddress& start, const IOAddress& end) {
addRange(AddressRange(start, end));
}
void
FreeLeaseQueue::addRange(const PrefixRange& range) {
if (!ranges_.empty()) {
auto last_addr = offsetAddress(range.end_, range.delegated_length_ - 1);
checkRangeOverlaps(range.start_, last_addr);
}
ranges_.insert(RangeDescriptor{range.start_, range.end_, range.delegated_length_,
boost::make_shared<Leases>()});
}
void
FreeLeaseQueue::addRange(const asiolink::IOAddress& prefix, const uint8_t prefix_length,
const uint8_t delegated_length) {
addRange(PrefixRange(prefix, prefix_length, delegated_length));
}
bool
FreeLeaseQueue::append(const IOAddress& address) {
// If there are no ranges defined, there is nothing to do.
if (ranges_.empty()) {
return (false);
}
// Find the beginning of the range which has the start address
// greater than the address we're appending.
auto lb = ranges_.upper_bound(address);
// If the range we found is the first one in the container
// there is no range matching our address because all existing
// ranges include higher addresses.
if (lb == ranges_.begin()) {
return (false);
}
--lb;
// Go one range back and see if our address is within its boundaries.
if ((lb->range_end_ < address) || (address < lb->range_start_)) {
return (false);
}
// Use the range we found and append the address to it.
AddressRange range(lb->range_start_, lb->range_end_);
append(range, address);
// Everything is fine.
return (true);
}
bool
FreeLeaseQueue::append(const IOAddress& prefix, const uint8_t delegated_length) {
// If there are no ranges defined, there is nothing to do.
if (ranges_.empty()) {
return (false);
}
// Find the beginning of the range which has the start address
// greater than the address we're appending.
auto lb = ranges_.upper_bound(prefix);
// If the range we found is the first one in the container
// there is no range matching our prefix because all existing
// ranges include higher addresses.
if (lb == ranges_.begin()) {
return (false);
}
--lb;
// Go one range back and see if our prefix is within its boundaries.
if ((lb->range_end_ < prefix) || (prefix < lb->range_start_) ||
(delegated_length != lb->delegated_length_)) {
return (false);
}
// Use the range we found and append the prefix to it.
PrefixRange range(lb->range_start_, lb->range_end_, lb->delegated_length_);
append(range, prefix);
// Everything is fine.
return (true);
}
void
FreeLeaseQueue::append(const AddressRange& range, const IOAddress& address) {
// Make sure the address is within the range boundaries.
checkRangeBoundaries(range, address);
auto cont = getLeases(range);
cont->insert(address);
}
void
FreeLeaseQueue::append(const uint64_t range_index, const IOAddress& ip) {
auto desc = getRangeDescriptor(range_index);
if ((ip < desc.range_start_) || (desc.range_end_ < ip)) {
isc_throw(BadValue, ip << " is not within the range of " << desc.range_start_
<< ":" << desc.range_end_);
}
desc.leases_->insert(ip);
}
void
FreeLeaseQueue::append(const PrefixRange& range, const asiolink::IOAddress& prefix) {
checkRangeBoundaries(range, prefix, true);
auto cont = getLeases(range);
cont->insert(prefix);
}
bool
FreeLeaseQueue::use(const AddressRange& range, const IOAddress& address) {
checkRangeBoundaries(range, address);
auto cont = getLeases(range);
auto found = cont->find(address);
if (found != cont->end()) {
static_cast<void>(cont->erase(found));
return (true);
}
return (false);
}
bool
FreeLeaseQueue::use(const PrefixRange& range, const IOAddress& prefix) {
checkRangeBoundaries(range, prefix, true);
auto cont = getLeases(range);
auto found = cont->find(prefix);
if (found != cont->end()) {
static_cast<void>(cont->erase(found));
return (true);
}
return (false);
}
template<typename RangeType>
void
FreeLeaseQueue::checkRangeBoundaries(const RangeType& range, const IOAddress& ip,
const bool prefix) const {
if ((ip < range.start_) || (range.end_ < ip)) {
isc_throw(BadValue, (prefix ? "prefix " : "address ") << ip << " is not within the range of "
<< range.start_ << ":" << range.end_);
}
}
void
FreeLeaseQueue::checkRangeOverlaps(const IOAddress& start, const IOAddress& end) const {
// Get the next range in the container relative to the start of the new
// range. The upper_bound returns the range which starts after the start
// of the new range.
auto next_range = ranges_.lower_bound(start);
// Get the range the range that is before that one. It is also possible that
// there is no previous range in which case we default to end().
auto previous_range = ranges_.end();
// If the next range is at the beginning of the container there is no
// previous range.
if (next_range != ranges_.begin()) {
// This should work fine even if the next range is set to end(). We
// will get the range that is one position before end() and that
// should be the range that goes before the new one.
auto it = next_range;
--it;
previous_range = it;
}
// Now that we have next and previous ranges set we should check that the
// new range we're adding does not overlap with them.
// If the previous range exists, let's check that the start of the new
// range is neither within that range nor lower. Assuming that the ranges
// are constructed such that the end must be greater or equal the start
// it is sufficient to check that the start of the new range is not lower
// or equal the end of the previous range.
if ((previous_range != ranges_.end()) &&
(start <= previous_range->range_end_)) {
isc_throw(BadValue, "new address range " << start << ":" << end
<< " overlaps with the existing range");
}
// If the next range exists, let's check that the end of the new range
// is neither within that range nor higher.
if ((next_range != ranges_.end()) &&
(next_range->range_start_ <= end)) {
isc_throw(BadValue, "new address range " << start << ":" << end
<< " overlaps with the existing range");
}
}
FreeLeaseQueue::LeasesPtr
FreeLeaseQueue::getLeases(const AddressRange& range) const {
auto cont = ranges_.find(range.start_);
if (cont == ranges_.end()) {
isc_throw(BadValue, "container for the specified address range " << range.start_
<< ":" << range.end_ << " does not exist");
}
return (cont->leases_);
}
FreeLeaseQueue::LeasesPtr
FreeLeaseQueue::getLeases(const PrefixRange& range) const {
auto cont = ranges_.find(range.start_);
if (cont == ranges_.end()) {
isc_throw(BadValue, "container for the specified prefix " << range.start_
<< " and delegated length of " << static_cast<int>(range.delegated_length_)
<< " does not exist");
}
return (cont->leases_);
}
FreeLeaseQueue::RangeDescriptor
FreeLeaseQueue::getRangeDescriptor(const uint64_t range_index) const {
if (ranges_.get<2>().size() <= range_index) {
isc_throw(BadValue, "container for the specified range index " << range_index
<< " does not exist");
}
auto cont = ranges_.get<2>().at(range_index);
return (cont);
}
} // end of namespace isc::dhcp
} // end of namespace isc

View File

@@ -1,412 +0,0 @@
// Copyright (C) 2020-2021 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
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
#ifndef FREE_LEASE_QUEUE_H
#define FREE_LEASE_QUEUE_H
#include <asiolink/io_address.h>
#include <dhcpsrv/ip_range.h>
#include <exceptions/exceptions.h>
#include <boost/multi_index_container.hpp>
#include <boost/multi_index/hashed_index.hpp>
#include <boost/multi_index/identity.hpp>
#include <boost/multi_index/indexed_by.hpp>
#include <boost/multi_index/member.hpp>
#include <boost/multi_index/ordered_index.hpp>
#include <boost/multi_index/random_access_index.hpp>
#include <boost/multi_index/sequenced_index.hpp>
#include <boost/shared_ptr.hpp>
#include <iterator>
#include <map>
namespace isc {
namespace dhcp {
/// @brief Queue holding free leases for various address and prefix ranges.
///
/// Free leases can be stored in this queue to provide the DHCP allocation
/// engine with the fast lookup mechanism for available leases. This avoids
/// costly lookup for available leases in the lease database backend when
/// the client's packet is being processed. Instead, when the server is being
/// configured, it iterates over the addresses and/or prefixes in respective
/// pools, verifies if leases exist for these addresses and/or prefixes and
/// for each of them for which it doesn't find the lease it creates an
/// appropriate entry in the queue.
///
/// This effectively moves the free lease lookup to the configuration phase.
/// When the server is going to allocate a new lease, it will make an
/// appropriate query to this queue to get the next available lease for the
/// given pool. If the server decides to use this lease, it is removed from
/// this queue. Conversely, when the lease expires (and is reclaimed) or is
/// released it is returned to this queue so it can be offered to a requesting
/// client at some later time.
///
/// The queue with free leases is optimized for two use cases. Firstly, it is
/// optimized to get the next available address or prefix efficiently. In order
/// to the get the next available lease the allocation engine can call the
/// @c FreeLeaseQueue::next function. The range from which the lease is to be
/// returned must be specified in the call. The range corresponds to the address
/// or prefix pool boundaries. The @c next function puts the returned lease
/// at the end of the queue. If the lease is rejected by the allocation engine
/// for any reason, e.g. conflict with existing host reservations, the allocation
/// engine simply calls @c next function again. It may need to perform multiple
/// calls to the @c next function until it gets the satifactionary lease.
/// However, it should be typically one call per allocation when no reservations
/// are present or there is a low number of in pool reservations. If the
/// allocation engine decides to allocate the returned lease, it must call
/// @c FreeLeaseQueue::use to remove this lease from the queue.
///
/// If the @c FreeLeaseQueue::pop method is used instead of @c next to get
/// the next available lease the returned lease is removed from the queue.
/// In that case, the allocation engine must not call @c FreeLeaseQueue::use
/// function when this lease is allocated. However, if the allocation engine
/// rejects this lease the @c FreeLeaseQueue::append must be called to return
/// the lease to the queue.
///
/// The second use case for which this queue is optimized is the lease
/// reclamation. This is the process by which expired leases are again made
/// available for allocation. The leases belonging to different pools expire at
/// various times. When the expired leases are reclaimed the server doesn't know
/// to which pools they belong. Since this queue associates free leases with
/// certain ranges it is important that this container can efficiently identify
/// the range. Once the range is identified, the reclaimed lease is appended to
/// the end of the queue for that range.
///
/// @todo Methods of this class should be called in thread safe context. Otherwise
/// they should be made thread safe.
class FreeLeaseQueue {
public:
/// @brief Constructor.
FreeLeaseQueue();
/// @brief Adds new address range to the queue.
///
/// The new range must not overlap with existing ranges.
///
/// @param range the new range to be added.
/// @throw BadValue if the new range overlaps with any of the existing ranges.
void addRange(const AddressRange& range);
/// @brief Adds new address range to the queue.
///
/// This variant of the method accepts the address range as a pair of
/// start/end arguments.
///
/// @param start beginning of the new address range.
/// @param end end of the new address range.
/// @throw BadValue if the new range overlaps with any of the existing ranges.
void addRange(const asiolink::IOAddress& start, const asiolink::IOAddress& end);
/// @brief Adds new delegated prefix range to the queue.
///
/// The new range must not overlap with existing ranges.
///
/// @param range the new range to be added.
/// @throw BadValue of the new range overlaps with any of the existing ranges.
void addRange(const PrefixRange& range);
/// @brief Adds new delegated prefix range to the queue.
///
/// This variant of the method accepts the prefix range specified with three
/// parameters: prefix, prefix length and delegated prefix length.
///
/// @param prefix range prefix.
/// @param prefix_length range prefix length.
/// @param delegated_length delegated prefix length.
/// @throw BadValue if the new range overlaps with any of the existing ranges.
void addRange(const asiolink::IOAddress& prefix, const uint8_t prefix_length,
const uint8_t delegated_length);
/// @brief Removes the range from the queue.
///
/// It removes all free leases associated with the removed address range.
///
/// @param range range to be removed.
/// @tparam RangeType type of the range, i.e. @c Range or @c PrefixRange.
/// @return true if the range existed and was removed.
template<typename RangeType>
bool removeRange(const RangeType& range) {
return (ranges_.get<1>().erase(range.start_) > 0);
}
/// @brief Appends an address to the end of the queue for a range.
///
/// This method is typically called when a lease expires and is reclaimed.
/// The range is not specified by the caller. The method identifies
/// appropriate address range for that address.
///
/// @param address address to be appended to the range queue.
/// @return true if the range was found and the address was appended,
/// false otherwise.
bool append(const asiolink::IOAddress& address);
/// @brief Appends a delegated prefix to the end of the queue for a range.
///
/// This method is typically called when a lease expires and is reclaimed.
/// The range is not specified by the caller. The method identifies
/// appropriate prefix range for that prefix.
///
/// @param prefix delegated prefix to be appended to the range queue.
/// @param delegated_length delegated prefix length.
/// @return true if the range was found and the prefix was appended,
/// false otherwise.
bool append(const asiolink::IOAddress& prefix, const uint8_t delegated_length);
/// @brief Appends an address to the end of the queue for a range.
///
/// This method is typically called upon server startup or reconfiguration.
/// For each address belonging to the pool for which there is no lease
/// this method appends free address at the end of the queue for the
/// specified range.
///
/// @param range specifies the address range to which the given address
/// belongs.
/// @param address address to be appended to the range queue.
/// @throw BadValue if the address does not belong to the specified
/// range or if the given range does not exist.
void append(const AddressRange& range, const asiolink::IOAddress& address);
/// @brief Appends a prefix to the end of the queue for a range.
///
/// This method is typically called upon server startup or reconfiguration.
/// For each delegated prefix belonging to the pool for which there is no
/// lease this method appends free delegated prefix at the end of the queue
/// for the specified range.
///
/// @param range specifies the prefix range to which the given prefix
/// belongs.
/// @param prefix delegated prefix to be appended to the range queue.
/// @throw BadValue if the prefix does not belong to the specified
/// range or if the given range does not exist.
void append(const PrefixRange& range, const asiolink::IOAddress& prefix);
/// @brief Appends an address or prefix to the end of the queue for a range.
///
/// This variant of the @c append method is called upon server startup or
/// reconfiguration. It is considered faster than the overload of this
/// method taking the @c Range structure as an argument. The range is
/// identified by the @c range_index which designates the range index
/// in the queue returned by the @c getRangeIndex method. Use
/// this method variant to add many addresses to the same range.
///
/// @param range_index address range index returned by @c getRangeIndex.
/// @param ip address or prefix to be appended to the range queue.
/// @throw BadValue if the address or prefix does not belong to the
/// specified range or if the given range does not exist.
void append(const uint64_t range_index, const asiolink::IOAddress& ip);
/// @brief Removes the specified address from the free addresses.
///
/// This method should be called upon successful lease allocation for
/// that address.
///
/// @param range range from which the free address should be removed.
/// @param address address to remove.
/// @return true if the address was found and successfully removed,
/// false otherwise.
/// @throw BadValue if the range does not exist.
bool use(const AddressRange& range, const asiolink::IOAddress& address);
/// @brief Removes the specified delegated prefix from the free prefixes.
///
/// This method should be called upon successful lease allocation for
/// that delegated prefix.
///
/// @param range range from which the free prefix should be removed.
/// @param prefix prefix to remove.
/// @return true if the prefix was found and successfully removed,
/// false otherwise.
/// @throw BadValue if the range does not exist.
bool use(const PrefixRange& range, const asiolink::IOAddress& prefix);
/// @brief Returns next free address or delegated prefix in the range.
///
/// This address or delegated prefix is moved to the end of the queue
/// for the range.
///
/// @param range range for which next address is to be returned.
/// @tparam RangeType type of the range, i.e. @c AddressRange or @c PrefixRange.
/// @return Next free address or delegated prefix in that range.
/// @throw BadValue if the range does not exist.
template<typename RangeType>
asiolink::IOAddress next(const RangeType& range) {
return (popNextInternal(range, true));
}
/// @brief Pops and returns next free address or delegated prefix in the range.
///
/// The address or delegated prefix is removed from the queue. If the caller,
/// i.e. allocation engine decides to not use this address or prefix it
/// should be appended to the queue using the @c append method.
///
/// @param range range for which next address or prefix is to be returned.
/// @tparam RangeType type of the range, i.e. @c AddressRange or @c PrefixRange.
/// @return Next free address or delegated prefix in that range.
/// @throw BadValue if the range does not exist.
template<typename RangeType>
asiolink::IOAddress pop(const RangeType& range) {
return (popNextInternal(range, false));
}
/// @brief Returns range index.
///
/// The range index designates the position of the range within the queue.
/// Searching for a range using the index is faster than searching by the
/// range itself because it uses random access index.
///
/// @param range range which index is to be returned.
/// @tparam RangeType type of the range, i.e. @c AddressRange or PrefixRange.
/// @return range index.
/// @throw BadValue if the range does not exist.
template<typename RangeType>
uint64_t getRangeIndex(const RangeType& range) const {
auto cont = ranges_.get<1>().find(range.start_);
if (cont == ranges_.get<1>().end()) {
isc_throw(BadValue, "container for the specified range " << range.start_
<< ":" << range.end_ << " does not exist");
}
return (std::distance(ranges_.get<2>().begin(), ranges_.project<2>(cont)));
}
private:
/// @brief Queue holding free leases for a range.
///
/// This container holds free leases for a given range. It contains two
/// indexes. The first index orders free leases by address values. The
/// second index is sequential and serves as a double-ended queue from
/// which leases are picked.
typedef boost::multi_index_container<
isc::asiolink::IOAddress,
boost::multi_index::indexed_by<
boost::multi_index::ordered_unique<
boost::multi_index::identity<asiolink::IOAddress>
>,
boost::multi_index::sequenced<>
>
> Leases;
/// Pointer to the queue of free leases for a range.
typedef boost::shared_ptr<Leases> LeasesPtr;
/// @brief Helper structure associating a range with the queue of
/// free leases.
struct RangeDescriptor {
/// Range start.
asiolink::IOAddress range_start_;
/// Range end.
asiolink::IOAddress range_end_;
/// Delegated length (used in prefix delegation).
uint8_t delegated_length_;
/// Queue holding free addresses for the range.
LeasesPtr leases_;
};
/// @brief Collection (container) of containers for various ranges.
///
/// This container provides two indexes for searching a given range along with
/// the appropriate container holding free leases. The first index is by the
/// range start value. The second index is the random access index allowing
/// faster access once the range index is known.
typedef boost::multi_index_container<
RangeDescriptor,
boost::multi_index::indexed_by<
boost::multi_index::ordered_unique<
boost::multi_index::member<RangeDescriptor, asiolink::IOAddress,
&RangeDescriptor::range_start_>
>,
boost::multi_index::hashed_unique<
boost::multi_index::member<RangeDescriptor, asiolink::IOAddress,
&RangeDescriptor::range_start_>
>,
boost::multi_index::random_access<>
>
> Ranges;
/// @brief Checks if the specified address or delegated prefix is within the
/// range.
///
/// @param range range for which the check should be performed.
/// @param ip address or delegated prefix for which the check should be performed.
/// @param prefix boolean value indicating if the specified IP is an address or
/// delegated prefix - used in error logging.
/// @tparam RangeType type of the range used, i.e. @c AddressRange or @c PrefixRange.
/// @throw BadValue of the address or delegated prefix does not belong to the range.
template<typename RangeType>
void checkRangeBoundaries(const RangeType& range, const asiolink::IOAddress& ip,
const bool prefix = false) const;
/// @brief Checks if the specified address or prefix range overlaps with an
/// existing range.
///
/// @param start beginning of the range.
/// @param end end of the range.
/// @throw BadValue if the specified range overlaps with an existing range.
void checkRangeOverlaps(const asiolink::IOAddress& start,
const asiolink::IOAddress& end) const;
/// @brief Returns queue for a given address range.
///
/// @param range range for which the container should be returned.
/// @return Pointer to the container (if found).
/// @throw BadValue if the specified range does not exist.
LeasesPtr getLeases(const AddressRange& range) const;
/// @brief Returns queue for a given prefix range.
///
/// @param range range for which the container should be returned.
/// @return Pointer to the container (if found).
/// @throw BadValue if the specified range does not exist.
LeasesPtr getLeases(const PrefixRange& range) const;
/// @brief Returns descriptor for a given range index.
///
/// The returned descriptor includes the range boundaries and also the
/// pointer to the queue with free leases for the range.
///
/// @param range_index index of the range which descriptor should be
/// returned.
/// @return Range descriptor if found.
/// @throw BadValue if the range with the given index does not exist.
RangeDescriptor getRangeDescriptor(const uint64_t range_index) const;
/// @brief This is internal implementation of the @c next and @c pop
/// methods.
///
/// @param range range for which next address is to be returned.
/// @param push boolean flag indicating if the value should be appended
/// to the end of the queue upon return (if true) or removed from the
/// queue (if false).
/// @return Next free address in that range.
/// @throw BadValue if the range does not exist.
template<typename RangeType>
asiolink::IOAddress popNextInternal(const RangeType& range, const bool push) {
auto cont = getLeases(range);
if (cont->empty()) {
return (range.start_.isV4() ? asiolink::IOAddress::IPV4_ZERO_ADDRESS() :
asiolink::IOAddress::IPV6_ZERO_ADDRESS());
}
auto& idx = cont->template get<1>();
auto next = idx.front();
idx.pop_front();
if (push) {
idx.push_back(next);
}
return (next);
}
/// @brief Holds a collection of containers with free leases for each
/// address range.
Ranges ranges_;
};
} // end of namespace isc::dhcp
} // end of namespace isc
#endif // FREE_LEASE_QUEUE_H

View File

@@ -92,7 +92,6 @@ libdhcpsrv_unittests_SOURCES += duid_config_parser_unittest.cc
libdhcpsrv_unittests_SOURCES += expiration_config_parser_unittest.cc
libdhcpsrv_unittests_SOURCES += flq_allocation_state_unittest.cc
libdhcpsrv_unittests_SOURCES += flq_allocator_unittest.cc
libdhcpsrv_unittests_SOURCES += free_lease_queue_unittest.cc
libdhcpsrv_unittests_SOURCES += host_cache_unittest.cc
libdhcpsrv_unittests_SOURCES += host_data_source_factory_unittest.cc
libdhcpsrv_unittests_SOURCES += host_mgr_unittest.cc

View File

@@ -1,613 +0,0 @@
// Copyright (C) 2020 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
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
#include <config.h>
#include <dhcpsrv/free_lease_queue.h>
#include <gtest/gtest.h>
using namespace isc;
using namespace isc::asiolink;
using namespace isc::dhcp;
namespace {
// This test verifies that it is not allowed to add a range that overlaps with
// any existing range.
TEST(FreeLeaseQueueTest, addRangeOverlapping) {
FreeLeaseQueue lq;
// Add the initial range. This should succeed.
ASSERT_NO_THROW(lq.addRange(IOAddress("192.0.2.10"), IOAddress("192.0.3.100")));
// Let's assume the following naming convention:
// - r1s - start of the first range added.
// - r1e - end of the first range added.
// - r2s - start of the second range (will be added later in this test).
// - r2e - end of the second range (will be added later in this test).
// - ns - start of the new range colliding with existing ones.
// - ne - end of the new range colliding with existing ones.
// - #### overlap
// - ns/ne/r1s - overlap on the edges of the ranges (single address shared).
// r1s ns####r2s ne
EXPECT_THROW(lq.addRange(IOAddress("192.0.2.50"), IOAddress("192.0.3.199")),
BadValue);
// ns r1s###ne r1s
EXPECT_THROW(lq.addRange(IOAddress("192.0.2.5"), IOAddress("192.0.2.100")),
BadValue);
// r1s ns####ne r2s
EXPECT_THROW(lq.addRange(IOAddress("192.0.2.50"), IOAddress("192.0.3.50")),
BadValue);
EXPECT_THROW(lq.addRange(IOAddress("192.0.2.5"), IOAddress("192.0.3.200")),
BadValue);
// ns ne/r1s r1e
EXPECT_THROW(lq.addRange(IOAddress("192.0.2.5"), IOAddress("192.0.2.10")),
BadValue);
// r1s r1e/ns ne
EXPECT_THROW(lq.addRange(IOAddress("192.0.3.100"), IOAddress("192.0.3.105")),
BadValue);
// ns/ne/r1s r1e
EXPECT_THROW(lq.addRange(IOAddress("192.0.2.10"), IOAddress("192.0.2.10")),
BadValue);
// r1s r1e/ns/ne
EXPECT_THROW(lq.addRange(IOAddress("192.0.3.100"), IOAddress("192.0.3.100")),
BadValue);
// Add another range, marked as r2s, r2e.
ASSERT_NO_THROW(lq.addRange(IOAddress("192.0.4.10"), IOAddress("192.0.5.100")));
// r1s ns####r1e ne r2s r2e
EXPECT_THROW(lq.addRange(IOAddress("192.0.2.50"), IOAddress("192.0.3.199")),
BadValue);
// r1s r1e r2s ns####r2e ne
EXPECT_THROW(lq.addRange(IOAddress("192.0.4.50"), IOAddress("192.0.5.199")),
BadValue);
// r1s ns####r2s####r2e ne
EXPECT_THROW(lq.addRange(IOAddress("192.0.2.50"), IOAddress("192.0.5.199")),
BadValue);
// ns r1s####ne r1e r2s r2e
EXPECT_THROW(lq.addRange(IOAddress("192.0.2.5"), IOAddress("192.0.2.100")),
BadValue);
// r1s r1e ns r2s####ne r2e
EXPECT_THROW(lq.addRange(IOAddress("192.0.4.5"), IOAddress("192.0.4.100")),
BadValue);
// ns r1s####r1e r2s####ne r2e
EXPECT_THROW(lq.addRange(IOAddress("192.0.2.5"), IOAddress("192.0.4.100")),
BadValue);
// r1s ns####ne r1e r2s r2e
EXPECT_THROW(lq.addRange(IOAddress("192.0.2.50"), IOAddress("192.0.3.50")),
BadValue);
// r1s r1e r2s ns####ne r2e
EXPECT_THROW(lq.addRange(IOAddress("192.0.4.50"), IOAddress("192.0.5.50")),
BadValue);
// r1s ns####r1e r2s####ne r2e
EXPECT_THROW(lq.addRange(IOAddress("192.0.2.50"), IOAddress("192.0.5.50")),
BadValue);
// ns r1s r1e ne r2s r2e
EXPECT_THROW(lq.addRange(IOAddress("192.0.2.5"), IOAddress("192.0.3.200")),
BadValue);
// r1s r1e ns r2s####r2e ne
EXPECT_THROW(lq.addRange(IOAddress("192.0.4.5"), IOAddress("192.0.5.200")),
BadValue);
// ns r1s####r1e r2s####r2e ne
EXPECT_THROW(lq.addRange(IOAddress("192.0.2.5"), IOAddress("192.0.5.200")),
BadValue);
// ns ne/r1s r1e r2s r2e
EXPECT_THROW(lq.addRange(IOAddress("192.0.2.5"), IOAddress("192.0.2.10")),
BadValue);
// r1s r1e/ns ne r2s r2e
EXPECT_THROW(lq.addRange(IOAddress("192.0.3.100"), IOAddress("192.0.3.105")),
BadValue);
// r1s r1e ns ne/r2s r2e
EXPECT_THROW(lq.addRange(IOAddress("192.0.4.5"), IOAddress("192.0.4.10")),
BadValue);
// r1s r1e r2s r2e/ns ne
EXPECT_THROW(lq.addRange(IOAddress("192.0.5.100"), IOAddress("192.0.5.105")),
BadValue);
}
// This test verifies that it is not allowed to add a prefix range that overlaps with
// any existing range.
TEST(FreeLeaseQueueTest, addPrefixRangeOverlapping) {
FreeLeaseQueue lq;
// Add the initial range. This should succeed.
ASSERT_NO_THROW(lq.addRange(IOAddress("2001:db8:1::"), 64, 96));
EXPECT_THROW(lq.addRange(IOAddress("2001:db8:1:0:0:5:ffff:0"), 96, 120),
BadValue);
EXPECT_THROW(lq.addRange(IOAddress("2001:db8:1::0"), 80, 88),
BadValue);
}
// This test verifies that a range can be removed from the container.
TEST(FreeLeaseQueueTest, removeRange) {
FreeLeaseQueue lq;
// Add two ranges.
AddressRange range1(IOAddress("192.0.2.99"), IOAddress("192.0.2.100"));
AddressRange range2(IOAddress("192.0.3.99"), IOAddress("192.0.3.100"));
ASSERT_NO_THROW(lq.addRange(range1));
ASSERT_NO_THROW(lq.addRange(range2));
bool removed = false;
// Expect true to be returned when the range is removed.
ASSERT_NO_THROW(removed = lq.removeRange(range1));
EXPECT_TRUE(removed);
// An attempt to append an address to the removed range should not succeed.
EXPECT_FALSE(lq.append(IOAddress("192.0.2.99")));
// Removing it the second time should return false to indicate that the range
// was no longer there.
ASSERT_NO_THROW(removed = lq.removeRange(range1));
EXPECT_FALSE(removed);
// Same for the second range.
ASSERT_NO_THROW(removed = lq.removeRange(range2));
EXPECT_TRUE(removed);
ASSERT_NO_THROW(removed = lq.removeRange(range2));
EXPECT_FALSE(removed);
}
// This test verifies that a prefix range can be removed from the container.
TEST(FreeLeaseQueueTest, removePrefixRange) {
FreeLeaseQueue lq;
// Add two ranges.
PrefixRange range1(IOAddress("3000::"), 64, 96);
PrefixRange range2(IOAddress("3001::"), 64, 96);
ASSERT_NO_THROW(lq.addRange(range1));
ASSERT_NO_THROW(lq.addRange(range2));
bool removed = false;
// Expect true to be returned when the range is removed.
ASSERT_NO_THROW(removed = lq.removeRange(range1));
EXPECT_TRUE(removed);
// An attempt to append a prefix to the removed range should not succeed.
EXPECT_FALSE(lq.append(IOAddress("3000::5:0:0"), 96));
// Removing it the second time should return false to indicate that the range
// was no longer there.
ASSERT_NO_THROW(removed = lq.removeRange(range1));
EXPECT_FALSE(removed);
// Same for the second range.
ASSERT_NO_THROW(removed = lq.removeRange(range2));
EXPECT_TRUE(removed);
ASSERT_NO_THROW(removed = lq.removeRange(range2));
EXPECT_FALSE(removed);
}
// This test verifies that an attempt to use an address from outside the
// given range throws and that an attempt to use non-existing in-range
// address returns false.
TEST(FreeLeaseQueueTest, useInvalidAddress) {
AddressRange range(IOAddress("192.0.2.99"), IOAddress("192.0.2.100"));
FreeLeaseQueue lq;
ASSERT_NO_THROW(lq.addRange(range));
// Using out of range address.
EXPECT_THROW(lq.use(range, IOAddress("192.0.2.1")), BadValue);
// Using in-range address but not existing in the container.
bool used = true;
ASSERT_NO_THROW(used = lq.use(range, IOAddress("192.0.2.99")));
EXPECT_FALSE(used);
}
// This test verifies that an attempt to use a prefix from outside the
// given range throws and that an attempt to use non-existing in-range
// address returns false.
TEST(FreeLeaseQueueTest, useInvalidPrefix) {
PrefixRange range(IOAddress("2001:db8:1::"), 64, 96);
FreeLeaseQueue lq;
ASSERT_NO_THROW(lq.addRange(range));
// Using out of range prefix.
EXPECT_THROW(lq.use(range, IOAddress("2001:db8:2::")), BadValue);
// Using in-range prefix but not existing in the container.
bool used = false;
ASSERT_NO_THROW(used = lq.use(range, IOAddress("2001:db8:1::5:0:0")));
EXPECT_FALSE(used);
}
// Check that duplicates are eliminated when appending free address to
// the range queue.
TEST(FreeLeaseQueueTest, appendDuplicates) {
FreeLeaseQueue lq;
AddressRange range(IOAddress("192.0.2.1"), IOAddress("192.0.2.255"));
ASSERT_NO_THROW(lq.addRange(range));
ASSERT_NO_THROW(lq.append(range, IOAddress("192.0.2.10")));
// Append the duplicate of the first address.
ASSERT_NO_THROW(lq.append(range, IOAddress("192.0.2.10")));
ASSERT_NO_THROW(lq.append(range, IOAddress("192.0.2.5")));
IOAddress next(0);
// The first address should be returned first.
ASSERT_NO_THROW(next = lq.next(range));
EXPECT_EQ("192.0.2.10", next.toText());
// The duplicate should not be returned. Instead, the second address should
// be returned.
ASSERT_NO_THROW(next = lq.next(range));
EXPECT_EQ("192.0.2.5", next.toText());
}
// This test verifies that it is possible to pick next address from the given
// range.
TEST(FreeLeaseQueueTest, next) {
FreeLeaseQueue lq;
// Let's create two distinct address ranges.
AddressRange range1(IOAddress("192.0.2.1"), IOAddress("192.0.2.255"));
AddressRange range2(IOAddress("192.0.3.1"), IOAddress("192.0.3.255"));
ASSERT_NO_THROW(lq.addRange(range1));
ASSERT_NO_THROW(lq.addRange(range2));
// Append some IP addresses to those address ranges.
ASSERT_NO_THROW(lq.append(AddressRange(range1), IOAddress("192.0.2.10")));
ASSERT_NO_THROW(lq.append(AddressRange(range1), IOAddress("192.0.2.5")));
ASSERT_NO_THROW(lq.append(AddressRange(range2), IOAddress("192.0.3.23")));
ASSERT_NO_THROW(lq.append(AddressRange(range2), IOAddress("192.0.3.46")));
// Get the first address from the first range.
IOAddress next(0);
ASSERT_NO_THROW(next = lq.next(range1));
EXPECT_EQ("192.0.2.10", next.toText());
// Get the next one.
ASSERT_NO_THROW(next = lq.next(range1));
EXPECT_EQ("192.0.2.5", next.toText());
// After iterating over all addresses we should get the first one again.
ASSERT_NO_THROW(next = lq.next(range1));
EXPECT_EQ("192.0.2.10", next.toText());
// Repeat that test for the second address range.
ASSERT_NO_THROW(next = lq.next(range2));
EXPECT_EQ("192.0.3.23", next.toText());
ASSERT_NO_THROW(next = lq.next(range2));
EXPECT_EQ("192.0.3.46", next.toText());
ASSERT_NO_THROW(next = lq.next(range2));
EXPECT_EQ("192.0.3.23", next.toText());
// Use (remove) the address from the first range.
bool used = false;
ASSERT_NO_THROW(used = lq.use(range1, IOAddress("192.0.2.5")));
EXPECT_TRUE(used);
// We should now be getting the sole address from that range.
ASSERT_NO_THROW(next = lq.next(range1));
EXPECT_EQ("192.0.2.10", next.toText());
ASSERT_NO_THROW(next = lq.next(range1));
EXPECT_EQ("192.0.2.10", next.toText());
// Check the same for the second range.
ASSERT_NO_THROW(lq.use(range2, IOAddress("192.0.3.46")));
ASSERT_NO_THROW(next = lq.next(range2));
EXPECT_EQ("192.0.3.23", next.toText());
}
// This test verifies that it is possible to pick next prefix from the given
// range.
TEST(FreeLeaseQueueTest, nextPrefix) {
FreeLeaseQueue lq;
PrefixRange range1(IOAddress("2001:db8:1::"), 64, 96);
ASSERT_NO_THROW(lq.addRange(range1));
ASSERT_NO_THROW(lq.append(range1, IOAddress("2001:db8:1::4:0")));
ASSERT_NO_THROW(lq.append(range1, IOAddress("2001:db8:1::7:0")));
ASSERT_NO_THROW(lq.append(range1, IOAddress("2001:db8:1::3:0")));
ASSERT_NO_THROW(lq.append(range1, IOAddress("2001:db8:1::")));
IOAddress next = IOAddress::IPV6_ZERO_ADDRESS();
ASSERT_NO_THROW(next = lq.next(range1));
EXPECT_EQ("2001:db8:1::4:0", next.toText());
ASSERT_NO_THROW(next = lq.next(range1));
EXPECT_EQ("2001:db8:1::7:0", next.toText());
ASSERT_NO_THROW(next = lq.next(range1));
EXPECT_EQ("2001:db8:1::3:0", next.toText());
ASSERT_NO_THROW(next = lq.next(range1));
EXPECT_EQ("2001:db8:1::", next.toText());
ASSERT_NO_THROW(next = lq.next(range1));
EXPECT_EQ("2001:db8:1::4:0", next.toText());
// Use (remove) the prefix from the range.
bool used = false;
ASSERT_NO_THROW(used = lq.use(range1, IOAddress("2001:db8:1::7:0")));
EXPECT_TRUE(used);
// After we have removed the second prefix, the third prefix should be
// returned.
ASSERT_NO_THROW(next = lq.next(range1));
EXPECT_EQ("2001:db8:1::3:0", next.toText());
}
// This test verifies that it is possible to pop next address from the given
// range.
TEST(FreeLeaseQueueTest, pop) {
FreeLeaseQueue lq;
// Let's create two distinct address ranges.
AddressRange range1(IOAddress("192.0.2.1"), IOAddress("192.0.2.255"));
AddressRange range2(IOAddress("192.0.3.1"), IOAddress("192.0.3.255"));
ASSERT_NO_THROW(lq.addRange(range1));
ASSERT_NO_THROW(lq.addRange(range2));
// Append some IP addresses to those address ranges.
ASSERT_NO_THROW(lq.append(AddressRange(range1), IOAddress("192.0.2.10")));
ASSERT_NO_THROW(lq.append(AddressRange(range1), IOAddress("192.0.2.5")));
ASSERT_NO_THROW(lq.append(AddressRange(range2), IOAddress("192.0.3.23")));
ASSERT_NO_THROW(lq.append(AddressRange(range2), IOAddress("192.0.3.46")));
// Pop first from first range.
IOAddress next(0);
ASSERT_NO_THROW(next = lq.pop(range1));
EXPECT_EQ("192.0.2.10", next.toText());
// Pop second from the first range.
ASSERT_NO_THROW(next = lq.pop(range1));
EXPECT_EQ("192.0.2.5", next.toText());
// After iterating over all addresses we should get empty queue.
ASSERT_NO_THROW(next = lq.pop(range1));
EXPECT_TRUE(next.isV4Zero());
// Repeat that test for the second address range.
ASSERT_NO_THROW(next = lq.pop(range2));
EXPECT_EQ("192.0.3.23", next.toText());
ASSERT_NO_THROW(next = lq.pop(range2));
EXPECT_EQ("192.0.3.46", next.toText());
ASSERT_NO_THROW(next = lq.pop(range2));
EXPECT_TRUE(next.isV4Zero());
}
// This test verifies that it is possible to pop next prefix from the given
// range.
TEST(FreeLeaseQueueTest, popPrefix) {
FreeLeaseQueue lq;
// Add the range.
PrefixRange range1(IOAddress("2001:db8:1::"), 64, 96);
ASSERT_NO_THROW(lq.addRange(range1));
// Append several prefixes to that range.
ASSERT_NO_THROW(lq.append(range1, IOAddress("2001:db8:1::4:0")));
ASSERT_NO_THROW(lq.append(range1, IOAddress("2001:db8:1::7:0")));
ASSERT_NO_THROW(lq.append(range1, IOAddress("2001:db8:1::3:0")));
ASSERT_NO_THROW(lq.append(range1, IOAddress("2001:db8:1::")));
// Make sure we get retrieve them in the order in which they have
// been added.
IOAddress next = IOAddress::IPV6_ZERO_ADDRESS();
ASSERT_NO_THROW(next = lq.pop(range1));
EXPECT_EQ("2001:db8:1::4:0", next.toText());
ASSERT_NO_THROW(next = lq.pop(range1));
EXPECT_EQ("2001:db8:1::7:0", next.toText());
ASSERT_NO_THROW(next = lq.pop(range1));
EXPECT_EQ("2001:db8:1::3:0", next.toText());
ASSERT_NO_THROW(next = lq.pop(range1));
EXPECT_EQ("2001:db8:1::", next.toText());
// After we went over all of them they should all be gone from the
// container and the IPv6 zero address should be returned.
ASSERT_NO_THROW(next = lq.pop(range1));
EXPECT_TRUE(next.isV6Zero());
}
// Check that out of bounds address can't be appended to the range.
TEST(FreeLeaseQueueTest, nextRangeMismatch) {
AddressRange range(IOAddress("192.0.2.1"), IOAddress("192.0.2.255"));
FreeLeaseQueue lq;
EXPECT_THROW(lq.append(AddressRange(range), IOAddress("192.0.3.1")),
isc::BadValue);
}
// Check that it is possible to return an address to the range and that the
// appropriate range is detected.
TEST(FreeLeaseQueueTest, detectRange) {
FreeLeaseQueue lq;
// Create three ranges.
AddressRange range1(IOAddress("192.0.2.1"), IOAddress("192.0.2.255"));
AddressRange range2(IOAddress("192.0.3.1"), IOAddress("192.0.3.255"));
AddressRange range3(IOAddress("10.0.0.1"), IOAddress("10.8.1.45"));
ASSERT_NO_THROW(lq.addRange(range1));
ASSERT_NO_THROW(lq.addRange(range2));
ASSERT_NO_THROW(lq.addRange(range3));
// Append some addresses matching the first range.
ASSERT_NO_THROW(lq.append(IOAddress("192.0.2.7")));
ASSERT_NO_THROW(lq.append(IOAddress("192.0.2.1")));
ASSERT_NO_THROW(lq.append(IOAddress("192.0.2.255")));
// Make sure that these addresses have been appended to that range.
IOAddress next(0);
ASSERT_NO_THROW(next = lq.next(range1));
EXPECT_EQ("192.0.2.7", next.toText());
ASSERT_NO_THROW(next = lq.next(range1));
EXPECT_EQ("192.0.2.1", next.toText());
ASSERT_NO_THROW(next = lq.next(range1));
EXPECT_EQ("192.0.2.255", next.toText());
// Append some addresses matching the remaining two ranges.
ASSERT_NO_THROW(lq.append(IOAddress("10.5.4.3")));
ASSERT_NO_THROW(lq.append(IOAddress("192.0.3.98")));
ASSERT_NO_THROW(next = lq.next(range3));
EXPECT_EQ("10.5.4.3", next.toText());
ASSERT_NO_THROW(next = lq.next(range2));
EXPECT_EQ("192.0.3.98", next.toText());
// Appending out of bounds address should not succeed.
EXPECT_FALSE(lq.append(IOAddress("10.0.0.0")));
}
// Check that it is possible to return a delegated prefix to the range and
// that the appropriate range is detected.
TEST(FreeLeaseQueueTest, detectPrefixRange) {
FreeLeaseQueue lq;
// Create three ranges.
PrefixRange range1(IOAddress("2001:db8:1::"), 64, 96);
PrefixRange range2(IOAddress("2001:db8:2::"), 112, 120);
PrefixRange range3(IOAddress("2001:db8:3::"), 96, 104);
ASSERT_NO_THROW(lq.addRange(range1));
ASSERT_NO_THROW(lq.addRange(range2));
ASSERT_NO_THROW(lq.addRange(range3));
// Append some prefixes matching the first range.
ASSERT_NO_THROW(lq.append(IOAddress("2001:db8:1::7:0"), 96));
ASSERT_NO_THROW(lq.append(IOAddress("2001:db8:1::100:0"), 96));
ASSERT_NO_THROW(lq.append(IOAddress("2001:db8:1::4:0"), 96));
// Make sure that these prefixes have been appended to that range.
IOAddress next(0);
ASSERT_NO_THROW(next = lq.next(range1));
EXPECT_EQ("2001:db8:1::7:0", next.toText());
ASSERT_NO_THROW(next = lq.next(range1));
EXPECT_EQ("2001:db8:1::100:0", next.toText());
ASSERT_NO_THROW(next = lq.next(range1));
EXPECT_EQ("2001:db8:1::4:0", next.toText());
// Append some prefixes matching the remaining two ranges.
ASSERT_NO_THROW(lq.append(IOAddress("2001:db8:2::10"), 120));
ASSERT_NO_THROW(lq.append(IOAddress("2001:db8:3::50"), 104));
ASSERT_NO_THROW(next = lq.next(range3));
EXPECT_EQ("2001:db8:3::50", next.toText());
ASSERT_NO_THROW(next = lq.next(range2));
EXPECT_EQ("2001:db8:2::10", next.toText());
// Appending out of bounds prefix should not succeed.
EXPECT_FALSE(lq.append(IOAddress("2001:db8:4::10"), 96));
EXPECT_FALSE(lq.append(IOAddress("2001:db8:2::30"), 97));
}
// This test verifies that false is returned if the specified address to be
// appended does not belong to any of the existing ranges.
TEST(FreeLeaseQueueTest, detectRangeFailed) {
AddressRange range(IOAddress("192.0.2.1"), IOAddress("192.0.2.255"));
FreeLeaseQueue lq;
ASSERT_NO_THROW(lq.addRange(range));
EXPECT_FALSE(lq.append(IOAddress("192.0.3.7")));
}
// This test verifies that it is possible to append IP addresses to the
// selected range via random access index.
TEST(FreeLeaseQueueTest, appendThroughRangeIndex) {
FreeLeaseQueue lq;
AddressRange range1(IOAddress("192.0.2.1"), IOAddress("192.0.2.255"));
AddressRange range2(IOAddress("192.0.3.1"), IOAddress("192.0.3.255"));
AddressRange range3(IOAddress("10.0.0.1"), IOAddress("10.8.1.45"));
ASSERT_NO_THROW(lq.addRange(range1));
ASSERT_NO_THROW(lq.addRange(range2));
ASSERT_NO_THROW(lq.addRange(range3));
uint64_t index1 = 0;
ASSERT_NO_THROW(index1 = lq.getRangeIndex(range1));
uint64_t index2 = 0;
ASSERT_NO_THROW(index2 = lq.getRangeIndex(range2));
uint64_t index3 = 0;
ASSERT_NO_THROW(index3 = lq.getRangeIndex(range3));
EXPECT_NE(index1, index2);
EXPECT_NE(index2, index3);
EXPECT_NE(index1, index3);
ASSERT_NO_THROW(lq.append(index1, IOAddress("192.0.2.50")));
ASSERT_NO_THROW(lq.append(index2, IOAddress("192.0.3.50")));
ASSERT_NO_THROW(lq.append(index3, IOAddress("10.1.1.50")));
ASSERT_THROW(lq.append(index2, IOAddress("10.1.1.51")), BadValue);
ASSERT_THROW(lq.append(index3, IOAddress("192.0.3.34")), BadValue);
}
// This test verifies that it is possible to append delegated prefixes to the
// selected range via random access index.
TEST(FreeLeaseQueueTest, appendPrefixThroughRangeIndex) {
FreeLeaseQueue lq;
PrefixRange range1(IOAddress("2001:db8:1::"), 64, 96);
PrefixRange range2(IOAddress("2001:db8:2::"), 64, 96);
PrefixRange range3(IOAddress("2001:db8:3::"), 64, 96);
ASSERT_NO_THROW(lq.addRange(range1));
ASSERT_NO_THROW(lq.addRange(range2));
ASSERT_NO_THROW(lq.addRange(range3));
uint64_t index1 = 0;
ASSERT_NO_THROW(index1 = lq.getRangeIndex(range1));
uint64_t index2 = 0;
ASSERT_NO_THROW(index2 = lq.getRangeIndex(range2));
uint64_t index3 = 0;
ASSERT_NO_THROW(index3 = lq.getRangeIndex(range3));
EXPECT_NE(index1, index2);
EXPECT_NE(index2, index3);
EXPECT_NE(index1, index3);
ASSERT_NO_THROW(lq.append(index1, IOAddress("2001:db8:1::5:0:0")));
ASSERT_NO_THROW(lq.append(index2, IOAddress("2001:db8:2::7:0:0")));
ASSERT_NO_THROW(lq.append(index3, IOAddress("2001:db8:3::2:0:0")));
ASSERT_THROW(lq.append(index2, IOAddress("2001:db8:3::3:0:0")), BadValue);
ASSERT_THROW(lq.append(index3, IOAddress("2001:db8:2::8:0:0")), BadValue);
}
} // end of anonymous namespace