mirror of
https://gitlab.isc.org/isc-projects/kea
synced 2025-08-30 13:37:55 +00:00
[master] Merge branch 'trac2280'
This commit is contained in:
@@ -1,4 +1,4 @@
|
||||
// Copyright (C) 2012-2015 Internet Systems Consortium, Inc. ("ISC")
|
||||
// Copyright (C) 2012-2016 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
|
||||
@@ -10,10 +10,37 @@
|
||||
#include <dhcp/option_space.h>
|
||||
#include <dhcpsrv/addr_utilities.h>
|
||||
#include <dhcpsrv/subnet.h>
|
||||
|
||||
#include <algorithm>
|
||||
#include <sstream>
|
||||
|
||||
using namespace isc::asiolink;
|
||||
using namespace isc::dhcp;
|
||||
|
||||
namespace {
|
||||
|
||||
/// @brief Function used in calls to std::upper_bound to check
|
||||
/// if the specified prefix is lower than the first address a pool.
|
||||
///
|
||||
/// @return true if prefix is lower than the first address in the pool.
|
||||
bool
|
||||
prefixLessThanFirstAddress(const IOAddress& prefix, const PoolPtr& pool) {
|
||||
return (prefix < pool->getFirstAddress());
|
||||
}
|
||||
|
||||
/// @brief Function used in calls to std::sort to compare first
|
||||
/// prefixes of the two pools.
|
||||
///
|
||||
/// @param pool1 First pool.
|
||||
/// @param pool2 Second pool.
|
||||
///
|
||||
/// @return true if first prefix of the first pool is smaller than
|
||||
/// the first address of the second pool.
|
||||
bool
|
||||
comparePoolFirstAddress(const PoolPtr& pool1, const PoolPtr& pool2) {
|
||||
return (pool1->getFirstAddress() < pool2->getFirstAddress());
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
namespace isc {
|
||||
namespace dhcp {
|
||||
@@ -228,27 +255,41 @@ PoolCollection& Subnet::getPoolsWritable(Lease::Type type) {
|
||||
}
|
||||
|
||||
const PoolPtr Subnet::getPool(Lease::Type type, const isc::asiolink::IOAddress& hint,
|
||||
bool anypool /* true */) const {
|
||||
bool anypool /* true */) const {
|
||||
// check if the type is valid (and throw if it isn't)
|
||||
checkType(type);
|
||||
|
||||
const PoolCollection& pools = getPools(type);
|
||||
|
||||
PoolPtr candidate;
|
||||
for (PoolCollection::const_iterator pool = pools.begin();
|
||||
pool != pools.end(); ++pool) {
|
||||
|
||||
// if we won't find anything better, then let's just use the first pool
|
||||
if (anypool && !candidate) {
|
||||
candidate = *pool;
|
||||
if (!pools.empty()) {
|
||||
// Pools are sorted by their first prefixes. For example: 2001::,
|
||||
// 2001::db8::, 3000:: etc. If our hint is 2001:db8:5:: we want to
|
||||
// find the pool with the longest matching prefix, so: 2001:db8::,
|
||||
// rather than 2001::. upper_bound returns the first pool with a prefix
|
||||
// that is greater than 2001:db8:5::, i.e. 3000::. To find the longest
|
||||
// matching prefix we use decrement operator to go back by one item.
|
||||
// If returned iterator points to begin it means that prefixes in all
|
||||
// pools are greater than out prefix, and thus there is no match.
|
||||
PoolCollection::const_iterator ub =
|
||||
std::upper_bound(pools.begin(), pools.end(), hint,
|
||||
prefixLessThanFirstAddress);
|
||||
|
||||
if (ub != pools.begin()) {
|
||||
--ub;
|
||||
if ((*ub)->inRange(hint)) {
|
||||
candidate = *ub;
|
||||
}
|
||||
}
|
||||
|
||||
// if the client provided a pool and there's a pool that hint is valid
|
||||
// in, then let's use that pool
|
||||
if ((*pool)->inRange(hint)) {
|
||||
return (*pool);
|
||||
// If we don't find anything better, then let's just use the first pool
|
||||
if (!candidate && anypool) {
|
||||
candidate = *pools.begin();
|
||||
}
|
||||
}
|
||||
|
||||
// Return a pool or NULL if no match found.
|
||||
return (candidate);
|
||||
}
|
||||
|
||||
@@ -271,13 +312,40 @@ Subnet::addPool(const PoolPtr& pool) {
|
||||
<< " the prefix of a subnet: "
|
||||
<< prefix_ << "/" << static_cast<int>(prefix_len_)
|
||||
<< " to which it is being added");
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
/// @todo: Check that pools do not overlap
|
||||
bool overlaps = false;
|
||||
if (pool->getType() == Lease::TYPE_V4) {
|
||||
overlaps = poolOverlaps(Lease::TYPE_V4, pool);
|
||||
|
||||
} else {
|
||||
overlaps =
|
||||
poolOverlaps(Lease::TYPE_NA, pool) ||
|
||||
poolOverlaps(Lease::TYPE_PD, pool) ||
|
||||
poolOverlaps(Lease::TYPE_TA, pool);
|
||||
}
|
||||
|
||||
if (overlaps) {
|
||||
isc_throw(BadValue,"a pool of type "
|
||||
<< Lease::typeToText(pool->getType())
|
||||
<< ", with the following address range: "
|
||||
<< pool->getFirstAddress() << "-"
|
||||
<< pool->getLastAddress() << " overlaps with "
|
||||
"an existing pool in the subnet: "
|
||||
<< prefix_ << "/" << static_cast<int>(prefix_len_)
|
||||
<< " to which it is being added");
|
||||
}
|
||||
|
||||
PoolCollection& pools_writable = getPoolsWritable(pool->getType());
|
||||
|
||||
// Add the pool to the appropriate pools collection
|
||||
getPoolsWritable(pool->getType()).push_back(pool);
|
||||
pools_writable.push_back(pool);
|
||||
|
||||
// Sort pools by first address.
|
||||
std::sort(pools_writable.begin(), pools_writable.end(),
|
||||
comparePoolFirstAddress);
|
||||
}
|
||||
|
||||
void
|
||||
@@ -315,6 +383,72 @@ Subnet::inPool(Lease::Type type, const isc::asiolink::IOAddress& addr) const {
|
||||
return (false);
|
||||
}
|
||||
|
||||
bool
|
||||
Subnet::poolOverlaps(const Lease::Type& pool_type, const PoolPtr& pool) const {
|
||||
const PoolCollection& pools = getPools(pool_type);
|
||||
|
||||
// If no pools, we don't overlap. Nothing to do.
|
||||
if (pools.empty()) {
|
||||
return (false);
|
||||
}
|
||||
|
||||
// We're going to insert a new pool, likely between two existing pools.
|
||||
// So we're going to end up with the following case:
|
||||
// |<---- pool1 ---->| |<-------- pool2 ------>| |<-- pool3 -->|
|
||||
// F1 L1 F2 L2 F3 L3
|
||||
// where pool1 and pool3 are existing pools, pool2 is a pool being
|
||||
// inserted and "F"/"L" mark first and last address in the pools
|
||||
// respectively. So the following conditions must be fulfilled:
|
||||
// F2 > L1 and L2 < F3. Obviously, for any pool: F < L.
|
||||
|
||||
// Search for pool3. We use F2 and upper_bound to find the F3 (upper_bound
|
||||
// returns first pool in the sorted container which first address is
|
||||
// greater than F2). prefixLessThanPoolAddress with the first argument
|
||||
// set to "true" is the custom comparison function for upper_bound, which
|
||||
// compares F2 with the first addresses of the existing pools.
|
||||
PoolCollection::const_iterator pool3_it =
|
||||
std::upper_bound(pools.begin(), pools.end(), pool->getFirstAddress(),
|
||||
prefixLessThanFirstAddress);
|
||||
|
||||
// upper_bound returns a first pool which first address is greater than the
|
||||
// address F2. However, it is also possible that there is a pool which first
|
||||
// address is equal to F2. Such pool is also in conflict with a new pool.
|
||||
// If the returned value is pools.begin() it means that all pools have greater
|
||||
// first address than F2, thus none of the pools can have first address equal
|
||||
// to F2. Otherwise, we'd need to check them for equality.
|
||||
if (pool3_it != pools.begin()) {
|
||||
// Go back one pool and check if addresses are equal.
|
||||
PoolPtr pool3 = *(pool3_it - 1);
|
||||
if (pool3->getFirstAddress() == pool->getFirstAddress()) {
|
||||
return (true);
|
||||
}
|
||||
}
|
||||
|
||||
// If returned value is unequal pools.end() it means that there is a pool3,
|
||||
// with F3 > F2.
|
||||
if (pool3_it != pools.end()) {
|
||||
// Let's store the pointer to this pool.
|
||||
PoolPtr pool3 = *pool3_it;
|
||||
// F3 must be greater than L2, otherwise pools will overlap.
|
||||
if (pool3->getFirstAddress() <= pool->getLastAddress()) {
|
||||
return (true);
|
||||
}
|
||||
}
|
||||
|
||||
// If L2 is ok, we now have to find the pool1. This pool should be
|
||||
// right before the pool3 if there is any pool before pool3.
|
||||
if (pool3_it != pools.begin()) {
|
||||
PoolPtr pool1 = *(pool3_it - 1);
|
||||
// F2 must be greater than L1.
|
||||
if (pool->getFirstAddress() <= pool1->getLastAddress()) {
|
||||
return (true);
|
||||
}
|
||||
}
|
||||
|
||||
return (false);
|
||||
}
|
||||
|
||||
|
||||
Subnet6::Subnet6(const isc::asiolink::IOAddress& prefix, uint8_t length,
|
||||
const Triplet<uint32_t>& t1,
|
||||
const Triplet<uint32_t>& t2,
|
||||
|
@@ -173,14 +173,21 @@ public:
|
||||
/// requesting router because the requesting router may use the
|
||||
/// delegated prefixes in different networks (using different subnets).
|
||||
///
|
||||
/// A DHCPv4 pool being added must not overlap with any existing DHCPv4
|
||||
/// pool. A DHCPv6 pool being added must not overlap with any existing
|
||||
/// DHCPv6 pool.
|
||||
///
|
||||
/// Pools held within a subnet are sorted by first pool address/prefix
|
||||
/// from the lowest to the highest.
|
||||
///
|
||||
/// @param pool pool to be added
|
||||
///
|
||||
/// @throw isc::BadValue if the pool type is invalid or the pool
|
||||
/// @throw isc::BadValue if the pool type is invalid, the pool
|
||||
/// is not an IA_PD pool and the address range of this pool does not
|
||||
/// match the subnet prefix.
|
||||
/// match the subnet prefix, or the pool overlaps with an existing pool
|
||||
/// within the subnet.
|
||||
void addPool(const PoolPtr& pool);
|
||||
|
||||
|
||||
/// @brief Deletes all pools of specified type
|
||||
///
|
||||
/// This method is used for testing purposes only
|
||||
@@ -189,6 +196,10 @@ public:
|
||||
|
||||
/// @brief Returns a pool that specified address belongs to
|
||||
///
|
||||
/// This method uses binary search to retrieve the pool. Thus, the number
|
||||
/// of comparisons performed by this method is logarithmic in the number
|
||||
/// of pools belonging to a subnet.
|
||||
///
|
||||
/// If there is no pool that the address belongs to (hint is invalid), other
|
||||
/// pool of specified type will be returned.
|
||||
///
|
||||
@@ -413,6 +424,16 @@ protected:
|
||||
/// @return sum of possible leases
|
||||
uint64_t sumPoolCapacity(const PoolCollection& pools) const;
|
||||
|
||||
/// @brief Checks if the specified pool overlaps with an existing pool.
|
||||
///
|
||||
/// @param pool_type Pool type.
|
||||
/// @param pool Pointer to a pool for which the method should check if
|
||||
/// it overlaps with any existing pool within this subnet.
|
||||
///
|
||||
/// @return true if pool overlaps with an existing pool of a specified
|
||||
/// type.
|
||||
bool poolOverlaps(const Lease::Type& pool_type, const PoolPtr& pool) const;
|
||||
|
||||
/// @brief subnet-id
|
||||
///
|
||||
/// Subnet-id is a unique value that can be used to find or identify
|
||||
|
@@ -143,9 +143,9 @@ TEST_F(AllocEngine6Test, allocWithUsedHint6) {
|
||||
// in pool, but is currently used, can succeed
|
||||
TEST_F(AllocEngine6Test, pdAllocWithUsedHint6) {
|
||||
allocWithUsedHintTest(Lease::TYPE_PD,
|
||||
IOAddress("2001:db8:1::"), // allocate this prefix as used
|
||||
IOAddress("2001:db8:1::"), // request this prefix
|
||||
64);
|
||||
IOAddress("2001:db8:1:2::"), // allocate this prefix as used
|
||||
IOAddress("2001:db8:1:2::"), // request this prefix
|
||||
80);
|
||||
}
|
||||
|
||||
// This test checks if the allocation with a hint that is out the blue
|
||||
@@ -159,7 +159,7 @@ TEST_F(AllocEngine6Test, allocBogusHint6) {
|
||||
// can succeed. The invalid hint should be ignored completely.
|
||||
TEST_F(AllocEngine6Test, pdAllocBogusHint6) {
|
||||
|
||||
allocBogusHint6(Lease::TYPE_PD, IOAddress("3000::abc"), 64);
|
||||
allocBogusHint6(Lease::TYPE_PD, IOAddress("3000::abc"), 80);
|
||||
}
|
||||
|
||||
// This test checks that NULL values are handled properly
|
||||
@@ -1612,7 +1612,7 @@ TEST_F(AllocEngine6Test, largePDPool) {
|
||||
|
||||
// Configure the PD pool with the prefix length of /64 and the delegated
|
||||
// length /96.
|
||||
Pool6Ptr pool(new Pool6(Lease::TYPE_PD, IOAddress("2001:db8:1::"), 64, 96));
|
||||
Pool6Ptr pool(new Pool6(Lease::TYPE_PD, IOAddress("2001:db8:1:2::"), 80, 96));
|
||||
subnet_->addPool(pool);
|
||||
|
||||
// We should have got exactly one lease.
|
||||
@@ -1649,6 +1649,7 @@ TEST_F(AllocEngine6Test, largePoolOver32bits) {
|
||||
TEST_F(AllocEngine6Test, largeAllocationAttemptsOverride) {
|
||||
// Remove the default NA pools.
|
||||
subnet_->delPools(Lease::TYPE_NA);
|
||||
subnet_->delPools(Lease::TYPE_PD);
|
||||
|
||||
// Add exactly one pool with many addresses.
|
||||
Pool6Ptr pool(new Pool6(Lease::TYPE_NA, IOAddress("2001:db8:1::"), 56));
|
||||
|
@@ -140,7 +140,9 @@ AllocEngine6Test::AllocEngine6Test() {
|
||||
// Initialize a subnet and short address pool.
|
||||
initSubnet(IOAddress("2001:db8:1::"),
|
||||
IOAddress("2001:db8:1::10"),
|
||||
IOAddress("2001:db8:1::20"));
|
||||
IOAddress("2001:db8:1::20"),
|
||||
IOAddress("2001:db8:1:2::"),
|
||||
64, 80);
|
||||
|
||||
initFqdn("", false, false);
|
||||
|
||||
@@ -148,8 +150,11 @@ AllocEngine6Test::AllocEngine6Test() {
|
||||
|
||||
void
|
||||
AllocEngine6Test::initSubnet(const asiolink::IOAddress& subnet,
|
||||
const asiolink::IOAddress& pool_start,
|
||||
const asiolink::IOAddress& pool_end) {
|
||||
const asiolink::IOAddress& pool_start,
|
||||
const asiolink::IOAddress& pool_end,
|
||||
const asiolink::IOAddress& pd_pool_prefix,
|
||||
const uint8_t pd_pool_length,
|
||||
const uint8_t pd_delegated_length) {
|
||||
CfgMgr& cfg_mgr = CfgMgr::instance();
|
||||
|
||||
subnet_ = Subnet6Ptr(new Subnet6(subnet, 56, 100, 200, 300, 400));
|
||||
@@ -157,7 +162,10 @@ AllocEngine6Test::initSubnet(const asiolink::IOAddress& subnet,
|
||||
|
||||
subnet_->addPool(pool_);
|
||||
|
||||
pd_pool_ = Pool6Ptr(new Pool6(Lease::TYPE_PD, subnet, 56, 64));
|
||||
if (!pd_pool_prefix.isV6Zero()) {
|
||||
pd_pool_ = Pool6Ptr(new Pool6(Lease::TYPE_PD, pd_pool_prefix,
|
||||
pd_pool_length, pd_delegated_length));
|
||||
}
|
||||
subnet_->addPool(pd_pool_);
|
||||
|
||||
cfg_mgr.getStagingCfg()->getCfgSubnets6()->add(subnet_);
|
||||
|
@@ -101,9 +101,18 @@ public:
|
||||
/// @param subnet Address of a subnet to be configured.
|
||||
/// @param pool_start First address in the address pool.
|
||||
/// @param pool_end Last address in the address pool.
|
||||
/// @param pd_pool_prefix Prefix for the prefix delegation pool. It
|
||||
/// defaults to 0 which means that PD pool is not specified.
|
||||
/// @param pd_pool_length Length of the PD pool prefix.
|
||||
/// @param pd_delegated_length Delegated prefix length.
|
||||
void initSubnet(const asiolink::IOAddress& subnet,
|
||||
const asiolink::IOAddress& pool_start,
|
||||
const asiolink::IOAddress& pool_end);
|
||||
const asiolink::IOAddress& pool_end,
|
||||
const asiolink::IOAddress& pd_pool_prefix =
|
||||
asiolink::IOAddress::IPV6_ZERO_ADDRESS(),
|
||||
const uint8_t pd_pool_length = 0,
|
||||
const uint8_t pd_delegated_length = 0);
|
||||
|
||||
|
||||
/// @brief Initializes FQDN data for a test.
|
||||
///
|
||||
|
@@ -124,7 +124,8 @@ TEST(Subnet4Test, matchClientId) {
|
||||
EXPECT_TRUE(subnet.getMatchClientId());
|
||||
}
|
||||
|
||||
TEST(Subnet4Test, Pool4InSubnet4) {
|
||||
// Checks that it is possible to add and retrieve multiple pools.
|
||||
TEST(Subnet4Test, pool4InSubnet4) {
|
||||
|
||||
Subnet4Ptr subnet(new Subnet4(IOAddress("192.1.2.0"), 24, 1, 2, 3));
|
||||
|
||||
@@ -132,15 +133,16 @@ TEST(Subnet4Test, Pool4InSubnet4) {
|
||||
PoolPtr pool2(new Pool4(IOAddress("192.1.2.128"), 26));
|
||||
PoolPtr pool3(new Pool4(IOAddress("192.1.2.192"), 30));
|
||||
|
||||
EXPECT_NO_THROW(subnet->addPool(pool1));
|
||||
// Add pools in reverse order to make sure that they get ordered by
|
||||
// first address.
|
||||
EXPECT_NO_THROW(subnet->addPool(pool3));
|
||||
|
||||
// If there's only one pool, get that pool
|
||||
PoolPtr mypool = subnet->getAnyPool(Lease::TYPE_V4);
|
||||
EXPECT_EQ(mypool, pool1);
|
||||
|
||||
EXPECT_EQ(mypool, pool3);
|
||||
|
||||
EXPECT_NO_THROW(subnet->addPool(pool2));
|
||||
EXPECT_NO_THROW(subnet->addPool(pool3));
|
||||
EXPECT_NO_THROW(subnet->addPool(pool1));
|
||||
|
||||
// If there are more than one pool and we didn't provide hint, we
|
||||
// should get the first pool
|
||||
@@ -149,11 +151,30 @@ TEST(Subnet4Test, Pool4InSubnet4) {
|
||||
EXPECT_EQ(mypool, pool1);
|
||||
|
||||
// If we provide a hint, we should get a pool that this hint belongs to
|
||||
EXPECT_NO_THROW(mypool = subnet->getPool(Lease::TYPE_V4,
|
||||
ASSERT_NO_THROW(mypool = subnet->getPool(Lease::TYPE_V4,
|
||||
IOAddress("192.1.2.195")));
|
||||
|
||||
EXPECT_EQ(mypool, pool3);
|
||||
|
||||
ASSERT_NO_THROW(mypool = subnet->getPool(Lease::TYPE_V4,
|
||||
IOAddress("192.1.2.129")));
|
||||
EXPECT_EQ(mypool, pool2);
|
||||
|
||||
ASSERT_NO_THROW(mypool = subnet->getPool(Lease::TYPE_V4,
|
||||
IOAddress("192.1.2.64")));
|
||||
EXPECT_EQ(mypool, pool1);
|
||||
|
||||
// Specify addresses which don't belong to any existing pools. The
|
||||
// third parameter prevents it from returning "any" available
|
||||
// pool if a good match is not found.
|
||||
ASSERT_NO_THROW(mypool = subnet->getPool(Lease::TYPE_V4,
|
||||
IOAddress("192.1.2.200"),
|
||||
false));
|
||||
EXPECT_FALSE(mypool);
|
||||
|
||||
ASSERT_NO_THROW(mypool = subnet->getPool(Lease::TYPE_V4,
|
||||
IOAddress("192.1.1.254"),
|
||||
false));
|
||||
EXPECT_FALSE(mypool);
|
||||
}
|
||||
|
||||
// Check if it's possible to get specified number of possible leases for
|
||||
@@ -182,22 +203,69 @@ TEST(Subnet4Test, getCapacity) {
|
||||
EXPECT_EQ(196, subnet->getPoolCapacity(Lease::TYPE_V4));
|
||||
}
|
||||
|
||||
TEST(Subnet4Test, Subnet4_Pool4_checks) {
|
||||
// Checks that it is not allowed to add invalid pools.
|
||||
TEST(Subnet4Test, pool4Checks) {
|
||||
|
||||
Subnet4Ptr subnet(new Subnet4(IOAddress("192.0.2.0"), 8, 1, 2, 3));
|
||||
|
||||
// this one is in subnet
|
||||
Pool4Ptr pool1(new Pool4(IOAddress("192.255.0.0"), 16));
|
||||
Pool4Ptr pool1(new Pool4(IOAddress("192.254.0.0"), 16));
|
||||
subnet->addPool(pool1);
|
||||
|
||||
// this one is larger than the subnet!
|
||||
Pool4Ptr pool2(new Pool4(IOAddress("193.0.0.0"), 24));
|
||||
|
||||
EXPECT_THROW(subnet->addPool(pool2), BadValue);
|
||||
ASSERT_THROW(subnet->addPool(pool2), BadValue);
|
||||
|
||||
// this one is totally out of blue
|
||||
Pool4Ptr pool3(new Pool4(IOAddress("1.2.3.4"), 16));
|
||||
EXPECT_THROW(subnet->addPool(pool3), BadValue);
|
||||
ASSERT_THROW(subnet->addPool(pool3), BadValue);
|
||||
|
||||
// This pool should be added just fine.
|
||||
Pool4Ptr pool4(new Pool4(IOAddress("192.0.2.10"),
|
||||
IOAddress("192.0.2.20")));
|
||||
ASSERT_NO_THROW(subnet->addPool(pool4));
|
||||
|
||||
// This one overlaps with the previous pool.
|
||||
Pool4Ptr pool5(new Pool4(IOAddress("192.0.2.1"),
|
||||
IOAddress("192.0.2.15")));
|
||||
ASSERT_THROW(subnet->addPool(pool5), BadValue);
|
||||
|
||||
// This one also overlaps.
|
||||
Pool4Ptr pool6(new Pool4(IOAddress("192.0.2.20"),
|
||||
IOAddress("192.0.2.30")));
|
||||
ASSERT_THROW(subnet->addPool(pool6), BadValue);
|
||||
|
||||
// This one "surrounds" the other pool.
|
||||
Pool4Ptr pool7(new Pool4(IOAddress("192.0.2.8"),
|
||||
IOAddress("192.0.2.23")));
|
||||
ASSERT_THROW(subnet->addPool(pool7), BadValue);
|
||||
|
||||
// This one does not overlap.
|
||||
Pool4Ptr pool8(new Pool4(IOAddress("192.0.2.30"),
|
||||
IOAddress("192.0.2.40")));
|
||||
ASSERT_NO_THROW(subnet->addPool(pool8));
|
||||
|
||||
// This one has a lower bound in the pool of 192.0.2.10-20.
|
||||
Pool4Ptr pool9(new Pool4(IOAddress("192.0.2.18"),
|
||||
IOAddress("192.0.2.30")));
|
||||
ASSERT_THROW(subnet->addPool(pool9), BadValue);
|
||||
|
||||
// This one has an upper bound in the pool of 192.0.2.30-40.
|
||||
Pool4Ptr pool10(new Pool4(IOAddress("192.0.2.25"),
|
||||
IOAddress("192.0.2.32")));
|
||||
ASSERT_THROW(subnet->addPool(pool10), BadValue);
|
||||
|
||||
// Add a pool with a single address.
|
||||
Pool4Ptr pool11(new Pool4(IOAddress("192.255.0.50"),
|
||||
IOAddress("192.255.0.50")));
|
||||
ASSERT_NO_THROW(subnet->addPool(pool11));
|
||||
|
||||
// Now we're going to add the same pool again. This is an interesting
|
||||
// case because we're checking if the code is properly using upper_bound
|
||||
// function, which returns a pool that has an address greater than the
|
||||
// specified one.
|
||||
ASSERT_THROW(subnet->addPool(pool11), BadValue);
|
||||
}
|
||||
|
||||
// Tests whether Subnet4 object is able to store and process properly
|
||||
@@ -721,27 +789,78 @@ TEST(Subnet6Test, clientClassesMultiple) {
|
||||
EXPECT_TRUE(subnet->clientSupported(bar_class));
|
||||
}
|
||||
|
||||
TEST(Subnet6Test, Subnet6_Pool6_checks) {
|
||||
// Checks that it is not allowed to add invalid pools.
|
||||
TEST(Subnet6Test, pool6Checks) {
|
||||
|
||||
Subnet6Ptr subnet(new Subnet6(IOAddress("2001:db8:1::"), 56, 1, 2, 3, 4));
|
||||
|
||||
// this one is in subnet
|
||||
Pool6Ptr pool1(new Pool6(Lease::TYPE_NA, IOAddress("2001:db8:1:1::"), 64));
|
||||
subnet->addPool(pool1);
|
||||
ASSERT_NO_THROW(subnet->addPool(pool1));
|
||||
|
||||
// this one is larger than the subnet!
|
||||
Pool6Ptr pool2(new Pool6(Lease::TYPE_NA, IOAddress("2001:db8::"), 48));
|
||||
|
||||
EXPECT_THROW(subnet->addPool(pool2), BadValue);
|
||||
|
||||
ASSERT_THROW(subnet->addPool(pool2), BadValue);
|
||||
|
||||
// this one is totally out of blue
|
||||
Pool6Ptr pool3(new Pool6(Lease::TYPE_NA, IOAddress("3000::"), 16));
|
||||
EXPECT_THROW(subnet->addPool(pool3), BadValue);
|
||||
|
||||
ASSERT_THROW(subnet->addPool(pool3), BadValue);
|
||||
|
||||
Pool6Ptr pool4(new Pool6(Lease::TYPE_NA, IOAddress("4001:db8:1::"), 80));
|
||||
EXPECT_THROW(subnet->addPool(pool4), BadValue);
|
||||
ASSERT_THROW(subnet->addPool(pool4), BadValue);
|
||||
|
||||
// This pool should be added just fine.
|
||||
Pool6Ptr pool5(new Pool6(Lease::TYPE_NA, IOAddress("2001:db8:1:2::100"),
|
||||
IOAddress("2001:db8:1:2::200")));
|
||||
ASSERT_NO_THROW(subnet->addPool(pool5));
|
||||
|
||||
// This pool overlaps with a previously added pool.
|
||||
Pool6Ptr pool6(new Pool6(Lease::TYPE_NA, IOAddress("2001:db8:1:2::1"),
|
||||
IOAddress("2001:db8:1:2::150")));
|
||||
ASSERT_THROW(subnet->addPool(pool6), BadValue);
|
||||
|
||||
// This pool also overlaps
|
||||
Pool6Ptr pool7(new Pool6(Lease::TYPE_NA, IOAddress("2001:db8:1:2::150"),
|
||||
IOAddress("2001:db8:1:2::300")));
|
||||
ASSERT_THROW(subnet->addPool(pool7), BadValue);
|
||||
|
||||
// This one "surrounds" the other pool.
|
||||
Pool6Ptr pool8(new Pool6(Lease::TYPE_NA, IOAddress("2001:db8:1:2::50"),
|
||||
IOAddress("2001:db8:1:2::250")));
|
||||
ASSERT_THROW(subnet->addPool(pool8), BadValue);
|
||||
|
||||
// This one does not overlap.
|
||||
Pool6Ptr pool9(new Pool6(Lease::TYPE_NA, IOAddress("2001:db8:1:2::300"),
|
||||
IOAddress("2001:db8:1:2::400")));
|
||||
ASSERT_NO_THROW(subnet->addPool(pool9));
|
||||
|
||||
// This one has a lower bound in the pool of 2001:db8:1::100-200.
|
||||
Pool6Ptr pool10(new Pool6(Lease::TYPE_NA, IOAddress("2001:db8:1:2::200"),
|
||||
IOAddress("2001:db8:1:2::225")));
|
||||
ASSERT_THROW(subnet->addPool(pool10), BadValue);
|
||||
|
||||
// This one has an upper bound in the pool of 2001:db8:1::300-400.
|
||||
Pool6Ptr pool11(new Pool6(Lease::TYPE_NA, IOAddress("2001:db8:1:2::250"),
|
||||
IOAddress("2001:db8:1:2::300")));
|
||||
ASSERT_THROW(subnet->addPool(pool11), BadValue);
|
||||
|
||||
// Add a pool with a single address.
|
||||
Pool6Ptr pool12(new Pool6(Lease::TYPE_NA, IOAddress("2001:db8:1:3::250"),
|
||||
IOAddress("2001:db8:1:3::250")));
|
||||
ASSERT_NO_THROW(subnet->addPool(pool12));
|
||||
|
||||
// Now we're going to add the same pool again. This is an interesting
|
||||
// case because we're checking if the code is properly using upper_bound
|
||||
// function, which returns a pool that has an address greater than the
|
||||
// specified one.
|
||||
ASSERT_THROW(subnet->addPool(pool12), BadValue);
|
||||
|
||||
// Prefix pool overlaps with the pool1. We can't hand out addresses and
|
||||
// prefixes from the same range.
|
||||
Pool6Ptr pool13(new Pool6(Lease::TYPE_PD, IOAddress("2001:db8:1:1:2::"),
|
||||
80, 96));
|
||||
ASSERT_THROW(subnet->addPool(pool13), BadValue);
|
||||
}
|
||||
|
||||
TEST(Subnet6Test, addOptions) {
|
||||
|
Reference in New Issue
Block a user