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
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 \
+++ /dev/null
-// 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
+++ /dev/null
-// 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
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
+++ /dev/null
-// 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