BIND 10 trac3150, updated. f6619e644f62317afb4259e2af7732caa9d10c25 [3150] Support for different pool types in subnet implemented
BIND 10 source code commits
bind10-changes at lists.isc.org
Mon Sep 16 10:46:32 UTC 2013
The branch, trac3150 has been updated
via f6619e644f62317afb4259e2af7732caa9d10c25 (commit)
from 154fbc8f1d2a8de45de50799228a52585726d823 (commit)
Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.
- Log -----------------------------------------------------------------
commit f6619e644f62317afb4259e2af7732caa9d10c25
Author: Tomek Mrugalski <tomasz at isc.org>
Date: Mon Sep 16 12:46:12 2013 +0200
[3150] Support for different pool types in subnet implemented
-----------------------------------------------------------------------
Summary of changes:
src/lib/dhcpsrv/alloc_engine.cc | 2 +-
src/lib/dhcpsrv/pool.cc | 22 +++--
src/lib/dhcpsrv/pool.h | 33 ++++---
src/lib/dhcpsrv/subnet.cc | 110 ++++++++++++++++--------
src/lib/dhcpsrv/subnet.h | 28 ++++--
src/lib/dhcpsrv/tests/alloc_engine_unittest.cc | 2 +-
src/lib/dhcpsrv/tests/subnet_unittest.cc | 12 +--
7 files changed, 138 insertions(+), 71 deletions(-)
-----------------------------------------------------------------------
diff --git a/src/lib/dhcpsrv/alloc_engine.cc b/src/lib/dhcpsrv/alloc_engine.cc
index 24dee0b..1f79897 100644
--- a/src/lib/dhcpsrv/alloc_engine.cc
+++ b/src/lib/dhcpsrv/alloc_engine.cc
@@ -96,7 +96,7 @@ AllocEngine::IterativeAllocator::pickAddress(const SubnetPtr& subnet,
// perhaps restarting the server).
IOAddress last = subnet->getLastAllocated(lease_type_);
- const PoolCollection& pools = subnet->getPools();
+ const PoolCollection& pools = subnet->getPools(lease_type_);
if (pools.empty()) {
isc_throw(AllocFailed, "No pools defined in selected subnet");
diff --git a/src/lib/dhcpsrv/pool.cc b/src/lib/dhcpsrv/pool.cc
index 53b62ed..e9d057f 100644
--- a/src/lib/dhcpsrv/pool.cc
+++ b/src/lib/dhcpsrv/pool.cc
@@ -21,9 +21,9 @@ using namespace isc::asiolink;
namespace isc {
namespace dhcp {
-Pool::Pool(const isc::asiolink::IOAddress& first,
+Pool::Pool(PoolType type, const isc::asiolink::IOAddress& first,
const isc::asiolink::IOAddress& last)
- :id_(getNextID()), first_(first), last_(last) {
+ :id_(getNextID()), first_(first), last_(last), type_(type) {
}
bool Pool::inRange(const isc::asiolink::IOAddress& addr) const {
@@ -32,7 +32,7 @@ bool Pool::inRange(const isc::asiolink::IOAddress& addr) const {
Pool4::Pool4(const isc::asiolink::IOAddress& first,
const isc::asiolink::IOAddress& last)
-:Pool(first, last) {
+:Pool(Pool::TYPE_V4, first, last) {
// check if specified address boundaries are sane
if (!first.isV4() || !last.isV4()) {
isc_throw(BadValue, "Invalid Pool4 address boundaries: not IPv4");
@@ -43,9 +43,8 @@ Pool4::Pool4(const isc::asiolink::IOAddress& first,
}
}
-Pool4::Pool4(const isc::asiolink::IOAddress& prefix,
- uint8_t prefix_len)
- :Pool(prefix, IOAddress("0.0.0.0")) {
+Pool4::Pool4( const isc::asiolink::IOAddress& prefix, uint8_t prefix_len)
+:Pool(Pool::TYPE_V4, prefix, IOAddress("0.0.0.0")) {
// check if the prefix is sane
if (!prefix.isV4()) {
@@ -64,13 +63,19 @@ Pool4::Pool4(const isc::asiolink::IOAddress& prefix,
Pool6::Pool6(PoolType type, const isc::asiolink::IOAddress& first,
const isc::asiolink::IOAddress& last)
- :Pool(first, last), type_(type) {
+ :Pool(type, first, last) {
// check if specified address boundaries are sane
if (!first.isV6() || !last.isV6()) {
isc_throw(BadValue, "Invalid Pool6 address boundaries: not IPv6");
}
+ if ( (type != Pool::TYPE_IA) && (type != Pool::TYPE_TA) &&
+ (type != Pool::TYPE_PD)) {
+ isc_throw(BadValue, "Invalid Pool6 type: " << static_cast<int>(type)
+ << ", must be TYPE_IA, TYPE_TA or TYPE_PD");
+ }
+
if (last < first) {
isc_throw(BadValue, "Upper boundary is smaller than lower boundary.");
// This check is a bit strict. If we decide that it is too strict,
@@ -95,8 +100,7 @@ Pool6::Pool6(PoolType type, const isc::asiolink::IOAddress& first,
Pool6::Pool6(PoolType type, const isc::asiolink::IOAddress& prefix,
uint8_t prefix_len, uint8_t delegated_len /* = 128 */)
- :Pool(prefix, IOAddress("::")),
- type_(type), prefix_len_(delegated_len) {
+ :Pool(type, prefix, IOAddress("::")), prefix_len_(delegated_len) {
// check if the prefix is sane
if (!prefix.isV6()) {
diff --git a/src/lib/dhcpsrv/pool.h b/src/lib/dhcpsrv/pool.h
index e63541d..cb5c924 100644
--- a/src/lib/dhcpsrv/pool.h
+++ b/src/lib/dhcpsrv/pool.h
@@ -77,6 +77,20 @@ public:
/// @return true, if the address is in pool
bool inRange(const isc::asiolink::IOAddress& addr) const;
+ /// @brief Returns pool type (v4, v6 non-temporary, v6 temp, v6 prefix)
+ /// @return returns pool type
+ PoolType getType() const {
+ return (type_);
+ }
+
+ /// @brief virtual destructor
+ ///
+ /// We need Pool to be a polymorphic class, so we could dynamic cast
+ /// from PoolPtr to Pool6Ptr if we need to. A class becomes polymorphic,
+ /// when there is at least one virtual method.
+ virtual ~Pool() {
+ }
+
protected:
/// @brief protected constructor
@@ -84,7 +98,12 @@ protected:
/// This constructor is protected to prevent anyone from instantiating
/// Pool class directly. Instances of Pool4 and Pool6 should be created
/// instead.
- Pool(const isc::asiolink::IOAddress& first,
+ ///
+ /// @param type type of the pool
+ /// @param first first address of a range
+ /// @param last last address of a range
+ Pool(PoolType type,
+ const isc::asiolink::IOAddress& first,
const isc::asiolink::IOAddress& last);
/// @brief returns the next unique Pool-ID
@@ -110,6 +129,9 @@ protected:
///
/// @todo: This field is currently not used.
std::string comments_;
+
+ /// @brief defines a pool type
+ PoolType type_;
};
/// @brief Pool information for IPv4 addresses
@@ -136,9 +158,6 @@ public:
/// @brief a pointer an IPv4 Pool
typedef boost::shared_ptr<Pool4> Pool4Ptr;
-/// @brief a container for IPv4 Pools
-typedef std::vector<Pool4Ptr> Pool4Collection;
-
/// @brief Pool information for IPv6 addresses and prefixes
///
/// It holds information about pool6, i.e. a range of IPv6 address space that
@@ -197,9 +216,6 @@ public:
}
private:
- /// @brief defines a pool type
- PoolType type_;
-
/// @brief Defines prefix length (for TYPE_PD only)
uint8_t prefix_len_;
};
@@ -207,9 +223,6 @@ private:
/// @brief a pointer an IPv6 Pool
typedef boost::shared_ptr<Pool6> Pool6Ptr;
-/// @brief a container for IPv6 Pools
-typedef std::vector<Pool6Ptr> Pool6Collection;
-
/// @brief a pointer to either IPv4 or IPv6 Pool
typedef boost::shared_ptr<Pool> PoolPtr;
diff --git a/src/lib/dhcpsrv/subnet.cc b/src/lib/dhcpsrv/subnet.cc
index 9802a1c..d7892ba 100644
--- a/src/lib/dhcpsrv/subnet.cc
+++ b/src/lib/dhcpsrv/subnet.cc
@@ -35,12 +35,12 @@ Subnet::Subnet(const isc::asiolink::IOAddress& prefix, uint8_t len,
last_allocated_pd_(lastAddrInPrefix(prefix, len)) {
if ((prefix.isV6() && len > 128) ||
(prefix.isV4() && len > 32)) {
- isc_throw(BadValue,
+ isc_throw(BadValue,
"Invalid prefix length specified for subnet: " << len);
}
}
-bool
+bool
Subnet::inRange(const isc::asiolink::IOAddress& addr) const {
IOAddress first = firstAddrInPrefix(prefix_, prefix_len_);
IOAddress last = lastAddrInPrefix(prefix_, prefix_len_);
@@ -120,7 +120,7 @@ void Subnet::setLastAllocated(const isc::asiolink::IOAddress& addr,
}
}
-std::string
+std::string
Subnet::toText() const {
std::stringstream tmp;
tmp << prefix_.toText() << "/" << static_cast<unsigned int>(prefix_len_);
@@ -138,39 +138,50 @@ Subnet4::Subnet4(const isc::asiolink::IOAddress& prefix, uint8_t length,
}
}
-const PoolCollection& Subnet::getPools() const {
- return pools_;
-}
-
-void
-Subnet::addPool(const PoolPtr& pool) {
- IOAddress first_addr = pool->getFirstAddress();
- IOAddress last_addr = pool->getLastAddress();
-
- if (!inRange(first_addr) || !inRange(last_addr)) {
- isc_throw(BadValue, "Pool (" << first_addr.toText() << "-"
- << last_addr.toText()
- << " does not belong in this (" << prefix_.toText() << "/"
- << static_cast<int>(prefix_len_) << ") subnet4");
+const PoolCollection& Subnet::getPools(Pool::PoolType type) const {
+ switch (type) {
+ case Pool::TYPE_V4:
+ case Pool::TYPE_IA:
+ return (pools_);
+ case Pool::TYPE_TA:
+ return (pools_ta_);
+ case Pool::TYPE_PD:
+ return (pools_pd_);
+ default:
+ isc_throw(BadValue, "Unsupported pool type: " << type);
}
+}
- /// @todo: Check that pools do not overlap
+PoolPtr Subnet::getPool(Pool::PoolType type, isc::asiolink::IOAddress hint) {
- pools_.push_back(pool);
-}
+ PoolCollection* pools = NULL;
-PoolPtr Subnet::getPool(isc::asiolink::IOAddress hint) {
+ switch (type) {
+ case Pool::TYPE_V4:
+ case Pool::TYPE_IA:
+ pools = &pools_;
+ break;
+ case Pool::TYPE_TA:
+ pools = &pools_ta_;
+ break;
+ case Pool::TYPE_PD:
+ pools = &pools_pd_;
+ break;
+ default:
+ isc_throw(BadValue, "Failed to select pools. Unknown pool type: "
+ << type);
+ }
PoolPtr candidate;
- for (PoolCollection::iterator pool = pools_.begin();
- pool != pools_.end(); ++pool) {
+ 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 we won't find anything better, then let's just use the first pool
if (!candidate) {
candidate = *pool;
}
- // If the client provided a pool and there's a pool that hint is valid
+ // 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);
@@ -179,30 +190,59 @@ PoolPtr Subnet::getPool(isc::asiolink::IOAddress hint) {
return (candidate);
}
-void
+void
+Subnet::addPool(const PoolPtr& pool) {
+ IOAddress first_addr = pool->getFirstAddress();
+ IOAddress last_addr = pool->getLastAddress();
+
+ if (!inRange(first_addr) || !inRange(last_addr)) {
+ isc_throw(BadValue, "Pool (" << first_addr.toText() << "-"
+ << last_addr.toText()
+ << " does not belong in this (" << prefix_.toText() << "/"
+ << static_cast<int>(prefix_len_) << ") subnet");
+ }
+
+ /// @todo: Check that pools do not overlap
+
+ switch (pool->getType()) {
+ case Pool::TYPE_V4:
+ case Pool::TYPE_IA:
+ pools_.push_back(pool);
+ return;
+ case Pool6::TYPE_TA:
+ pools_ta_.push_back(pool);
+ return;
+ case Pool6::TYPE_PD:
+ pools_pd_.push_back(pool);
+ return;
+ default:
+ isc_throw(BadValue, "Invalid pool type specified: "
+ << static_cast<int>(pool->getType()));
+ }
+}
+
+void
Subnet::setIface(const std::string& iface_name) {
iface_ = iface_name;
}
-std::string
+std::string
Subnet::getIface() const {
return (iface_);
}
-
-
void
Subnet4::validateOption(const OptionPtr& option) const {
if (!option) {
- isc_throw(isc::BadValue,
+ isc_throw(isc::BadValue,
"option configured for subnet must not be NULL");
} else if (option->getUniverse() != Option::V4) {
- isc_throw(isc::BadValue,
+ isc_throw(isc::BadValue,
"expected V4 option to be added to the subnet");
}
}
-bool
+bool
Subnet::inPool(const isc::asiolink::IOAddress& addr) const {
// Let's start with checking if it even belongs to that subnet.
@@ -210,7 +250,7 @@ Subnet::inPool(const isc::asiolink::IOAddress& addr) const {
return (false);
}
- for (PoolCollection::const_iterator pool = pools_.begin();
+ for (PoolCollection::const_iterator pool = pools_.begin();
pool != pools_.end(); ++pool) {
if ((*pool)->inRange(addr)) {
return (true);
@@ -236,10 +276,10 @@ Subnet6::Subnet6(const isc::asiolink::IOAddress& prefix, uint8_t length,
void
Subnet6::validateOption(const OptionPtr& option) const {
if (!option) {
- isc_throw(isc::BadValue,
+ isc_throw(isc::BadValue,
"option configured for subnet must not be NULL");
} else if (option->getUniverse() != Option::V6) {
- isc_throw(isc::BadValue,
+ isc_throw(isc::BadValue,
"expected V6 option to be added to the subnet");
}
}
diff --git a/src/lib/dhcpsrv/subnet.h b/src/lib/dhcpsrv/subnet.h
index 10d858e..6323944 100644
--- a/src/lib/dhcpsrv/subnet.h
+++ b/src/lib/dhcpsrv/subnet.h
@@ -274,14 +274,20 @@ public:
/// @brief Returns a pool that specified address belongs to
///
+ /// If there is no pool that the address belongs to (hint is invalid), other
+ /// pool of specified type will be returned.
+ ///
+ /// @param type pool type that the pool is looked for
/// @param addr address that the returned pool should cover (optional)
- /// @return Pointer to found Pool4 or Pool6 (or NULL)
- PoolPtr getPool(isc::asiolink::IOAddress addr);
+ /// @return found pool (or NULL)
+ PoolPtr getPool(Pool::PoolType type, isc::asiolink::IOAddress addr);
/// @brief Returns a pool without any address specified
+ ///
+ /// @param type pool type that the pool is looked for
/// @return returns one of the pools defined
- PoolPtr getAnyPool() {
- return (getPool(default_pool()));
+ PoolPtr getAnyPool(Pool::PoolType type) {
+ return (getPool(type, default_pool()));
}
/// @brief Returns the default address that will be used for pool selection
@@ -294,8 +300,9 @@ public:
///
/// The reference is only valid as long as the object that returned it.
///
+ /// @param type lease type to be set
/// @return a collection of all pools
- const PoolCollection& getPools() const;
+ const PoolCollection& getPools(Pool::PoolType type) const;
/// @brief sets name of the network interface for directly attached networks
///
@@ -348,9 +355,15 @@ protected:
/// a Subnet4 or Subnet6.
SubnetID id_;
- /// @brief collection of pools in that list
+ /// @brief collection of IPv4 or non-temporary IPv6 pools in that subnet
PoolCollection pools_;
+ /// @brief collection of IPv6 temporary address pools in that subnet
+ PoolCollection pools_ta_;
+
+ /// @brief collection of IPv6 prefix pools in that subnet
+ PoolCollection pools_pd_;
+
/// @brief a prefix of the subnet
isc::asiolink::IOAddress prefix_;
@@ -501,9 +514,6 @@ protected:
/// @brief specifies optional interface-id
OptionPtr interface_id_;
- /// @brief collection of pools for non-temporary addresses
- Pool6Collection pools_;
-
/// @brief a triplet with preferred lifetime (in seconds)
Triplet<uint32_t> preferred_;
};
diff --git a/src/lib/dhcpsrv/tests/alloc_engine_unittest.cc b/src/lib/dhcpsrv/tests/alloc_engine_unittest.cc
index 27e31d9..229692a 100644
--- a/src/lib/dhcpsrv/tests/alloc_engine_unittest.cc
+++ b/src/lib/dhcpsrv/tests/alloc_engine_unittest.cc
@@ -1119,7 +1119,7 @@ TEST_F(AllocEngine4Test, renewLease4) {
// renew it.
ASSERT_FALSE(lease->expired());
lease = engine->renewLease4(subnet_, clientid_, hwaddr_, true,
- true, "host.example.com.", lease,
+ true, "host.example.com.", lease,
callout_handle, false);
// Check that he got that single lease
ASSERT_TRUE(lease);
diff --git a/src/lib/dhcpsrv/tests/subnet_unittest.cc b/src/lib/dhcpsrv/tests/subnet_unittest.cc
index 14b01d4..cbb04bd 100644
--- a/src/lib/dhcpsrv/tests/subnet_unittest.cc
+++ b/src/lib/dhcpsrv/tests/subnet_unittest.cc
@@ -69,7 +69,7 @@ TEST(Subnet4Test, Pool4InSubnet4) {
subnet->addPool(pool1);
// If there's only one pool, get that pool
- PoolPtr mypool = subnet->getAnyPool();
+ PoolPtr mypool = subnet->getAnyPool(Pool::TYPE_V4);
EXPECT_EQ(mypool, pool1);
@@ -78,12 +78,12 @@ TEST(Subnet4Test, Pool4InSubnet4) {
// If there are more than one pool and we didn't provide hint, we
// should get the first pool
- mypool = subnet->getAnyPool();
+ mypool = subnet->getAnyPool(Pool::TYPE_V4);
EXPECT_EQ(mypool, pool1);
// If we provide a hint, we should get a pool that this hint belongs to
- mypool = subnet->getPool(IOAddress("192.1.2.195"));
+ mypool = subnet->getPool(Pool::TYPE_V4, IOAddress("192.1.2.195"));
EXPECT_EQ(mypool, pool3);
@@ -215,7 +215,7 @@ TEST(Subnet6Test, Pool6InSubnet6) {
subnet->addPool(pool1);
// If there's only one pool, get that pool
- PoolPtr mypool = subnet->getAnyPool();
+ PoolPtr mypool = subnet->getAnyPool(Pool::TYPE_IA);
EXPECT_EQ(mypool, pool1);
@@ -224,12 +224,12 @@ TEST(Subnet6Test, Pool6InSubnet6) {
// If there are more than one pool and we didn't provide hint, we
// should get the first pool
- mypool = subnet->getAnyPool();
+ mypool = subnet->getAnyPool(Pool::TYPE_IA);
EXPECT_EQ(mypool, pool1);
// If we provide a hint, we should get a pool that this hint belongs to
- mypool = subnet->getPool(IOAddress("2001:db8:1:3::dead:beef"));
+ mypool = subnet->getPool(Pool::TYPE_IA, IOAddress("2001:db8:1:3::dead:beef"));
EXPECT_EQ(mypool, pool3);
}
More information about the bind10-changes
mailing list