Commit 154fbc8f authored by Tomek Mrugalski's avatar Tomek Mrugalski 🛰
Browse files

[3150] First part of prefix pool support

parent 48b5e32e
......@@ -141,13 +141,13 @@ protected:
///
/// @param addr is the IPv6 prefix of the pool.
/// @param len is the prefix length.
/// @param ptype is the type of IPv6 pool (Pool6::Pool6Type). Note this is
/// passed in as an int32_t and cast to Pool6Type to accommodate a
/// @param ptype is the type of IPv6 pool (Pool::PoolType). Note this is
/// passed in as an int32_t and cast to PoolType to accommodate a
/// polymorphic interface.
/// @return returns a PoolPtr to the new Pool4 object.
PoolPtr poolMaker (IOAddress &addr, uint32_t len, int32_t ptype)
{
return (PoolPtr(new Pool6(static_cast<isc::dhcp::Pool6::Pool6Type>
return (PoolPtr(new Pool6(static_cast<isc::dhcp::Pool::PoolType>
(ptype), addr, len)));
}
......@@ -155,13 +155,13 @@ protected:
///
/// @param min is the first IPv6 address in the pool.
/// @param max is the last IPv6 address in the pool.
/// @param ptype is the type of IPv6 pool (Pool6::Pool6Type). Note this is
/// passed in as an int32_t and cast to Pool6Type to accommodate a
/// @param ptype is the type of IPv6 pool (Pool::PoolType). Note this is
/// passed in as an int32_t and cast to PoolType to accommodate a
/// polymorphic interface.
/// @return returns a PoolPtr to the new Pool4 object.
PoolPtr poolMaker (IOAddress &min, IOAddress &max, int32_t ptype)
{
return (PoolPtr(new Pool6(static_cast<isc::dhcp::Pool6::Pool6Type>
return (PoolPtr(new Pool6(static_cast<isc::dhcp::Pool::PoolType>
(ptype), min, max)));
}
};
......
......@@ -53,8 +53,8 @@ AllocEngineHooks Hooks;
namespace isc {
namespace dhcp {
AllocEngine::IterativeAllocator::IterativeAllocator()
:Allocator() {
AllocEngine::IterativeAllocator::IterativeAllocator(Pool::PoolType lease_type)
:Allocator(lease_type) {
}
isc::asiolink::IOAddress
......@@ -94,7 +94,7 @@ AllocEngine::IterativeAllocator::pickAddress(const SubnetPtr& subnet,
// Let's get the last allocated address. It is usually set correctly,
// but there are times when it won't be (like after removing a pool or
// perhaps restarting the server).
IOAddress last = subnet->getLastAllocated();
IOAddress last = subnet->getLastAllocated(lease_type_);
const PoolCollection& pools = subnet->getPools();
......@@ -117,7 +117,7 @@ AllocEngine::IterativeAllocator::pickAddress(const SubnetPtr& subnet,
if (it == pools.end()) {
// ok to access first element directly. We checked that pools is non-empty
IOAddress next = pools[0]->getFirstAddress();
subnet->setLastAllocated(next);
subnet->setLastAllocated(next, lease_type_);
return (next);
}
......@@ -126,7 +126,7 @@ AllocEngine::IterativeAllocator::pickAddress(const SubnetPtr& subnet,
IOAddress next = increaseAddress(last); // basically addr++
if ((*it)->inRange(next)) {
// the next one is in the pool as well, so we haven't hit pool boundary yet
subnet->setLastAllocated(next);
subnet->setLastAllocated(next, lease_type_);
return (next);
}
......@@ -136,18 +136,18 @@ AllocEngine::IterativeAllocator::pickAddress(const SubnetPtr& subnet,
// Really out of luck today. That was the last pool. Let's rewind
// to the beginning.
next = pools[0]->getFirstAddress();
subnet->setLastAllocated(next);
subnet->setLastAllocated(next, lease_type_);
return (next);
}
// there is a next pool, let's try first address from it
next = (*it)->getFirstAddress();
subnet->setLastAllocated(next);
subnet->setLastAllocated(next, lease_type_);
return (next);
}
AllocEngine::HashedAllocator::HashedAllocator()
:Allocator() {
AllocEngine::HashedAllocator::HashedAllocator(Pool::PoolType lease_type)
:Allocator(lease_type) {
isc_throw(NotImplemented, "Hashed allocator is not implemented");
}
......@@ -159,8 +159,8 @@ AllocEngine::HashedAllocator::pickAddress(const SubnetPtr&,
isc_throw(NotImplemented, "Hashed allocator is not implemented");
}
AllocEngine::RandomAllocator::RandomAllocator()
:Allocator() {
AllocEngine::RandomAllocator::RandomAllocator(Pool::PoolType lease_type)
:Allocator(lease_type) {
isc_throw(NotImplemented, "Random allocator is not implemented");
}
......@@ -177,13 +177,13 @@ AllocEngine::AllocEngine(AllocType engine_type, unsigned int attempts)
:attempts_(attempts) {
switch (engine_type) {
case ALLOC_ITERATIVE:
allocator_ = boost::shared_ptr<Allocator>(new IterativeAllocator());
allocator_.reset(new IterativeAllocator(Pool6::TYPE_IA));
break;
case ALLOC_HASHED:
allocator_ = boost::shared_ptr<Allocator>(new HashedAllocator());
allocator_.reset(new HashedAllocator(Pool6::TYPE_IA));
break;
case ALLOC_RANDOM:
allocator_ = boost::shared_ptr<Allocator>(new RandomAllocator());
allocator_.reset(new RandomAllocator(Pool6::TYPE_IA));
break;
default:
......
......@@ -77,10 +77,20 @@ protected:
pickAddress(const SubnetPtr& subnet, const DuidPtr& duid,
const isc::asiolink::IOAddress& hint) = 0;
/// @brief Default constructor.
///
/// Specifies which type of leases this allocator will assign
Allocator(Pool::PoolType lease_type)
:lease_type_(lease_type) {
}
/// @brief virtual destructor
virtual ~Allocator() {
}
protected:
/// @brief defines lease type allocation
Pool::PoolType lease_type_;
};
/// @brief Address/prefix allocator that iterates over all addresses
......@@ -95,7 +105,8 @@ protected:
/// @brief default constructor
///
/// Does not do anything
IterativeAllocator();
/// @param type - specifies allocation type
IterativeAllocator(Pool::PoolType type);
/// @brief returns the next address from pools in a subnet
///
......@@ -123,7 +134,8 @@ protected:
public:
/// @brief default constructor (does nothing)
HashedAllocator();
/// @param type - specifies allocation type
HashedAllocator(Pool::PoolType type);
/// @brief returns an address based on hash calculated from client's DUID.
///
......@@ -145,7 +157,8 @@ protected:
public:
/// @brief default constructor (does nothing)
RandomAllocator();
/// @param type - specifies allocation type
RandomAllocator(Pool::PoolType type);
/// @brief returns an random address from pool of specified subnet
///
......
......@@ -62,7 +62,7 @@ Pool4::Pool4(const isc::asiolink::IOAddress& prefix,
}
Pool6::Pool6(Pool6Type type, const isc::asiolink::IOAddress& first,
Pool6::Pool6(PoolType type, const isc::asiolink::IOAddress& first,
const isc::asiolink::IOAddress& last)
:Pool(first, last), type_(type) {
......@@ -93,7 +93,7 @@ Pool6::Pool6(Pool6Type type, const isc::asiolink::IOAddress& first,
}
}
Pool6::Pool6(Pool6Type type, const isc::asiolink::IOAddress& prefix,
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) {
......
......@@ -32,6 +32,25 @@ class Pool {
public:
/// @brief specifies Pool type
///
/// Currently there are 3 pool types defined in DHCPv6:
/// - Non-temporary addresses (conveyed in IA_NA)
/// - Temporary addresses (conveyed in IA_TA)
/// - Delegated Prefixes (conveyed in IA_PD)
///
/// The fourth one (TYPE_V4) is used in DHCPv4 use cases when getPool()
/// code is shared between v4 and v6 code.
///
/// There is a new one being worked on (IA_PA, see draft-ietf-dhc-host-gen-id), but
/// support for it is not planned for now.
typedef enum {
TYPE_IA = 0,
TYPE_TA = 1,
TYPE_PD = 2,
TYPE_V4 = 3
} PoolType;
/// @brief returns Pool-id
///
/// @return pool-id value
......@@ -127,20 +146,6 @@ typedef std::vector<Pool4Ptr> Pool4Collection;
class Pool6 : public Pool {
public:
/// @brief specifies Pool type
///
/// Currently there are 3 pool types defined in DHCPv6:
/// - Non-temporary addresses (conveyed in IA_NA)
/// - Temporary addresses (conveyed in IA_TA)
/// - Delegated Prefixes (conveyed in IA_PD)
/// There is a new one being worked on (IA_PA, see draft-ietf-dhc-host-gen-id), but
/// support for it is not planned for now.
typedef enum {
TYPE_IA,
TYPE_TA,
TYPE_PD
} Pool6Type;
/// @brief the constructor for Pool6 "min-max" style definition
///
/// @throw BadValue if PD is define (PD can be only prefix/len)
......@@ -148,7 +153,7 @@ public:
/// @param type type of the pool (IA or TA)
/// @param first the first address in a pool
/// @param last the last address in a pool
Pool6(Pool6Type type, const isc::asiolink::IOAddress& first,
Pool6(PoolType type, const isc::asiolink::IOAddress& first,
const isc::asiolink::IOAddress& last);
/// @brief the constructor for Pool6 "prefix/len" style definition
......@@ -172,13 +177,13 @@ public:
/// @param prefix specifies prefix of the pool
/// @param prefix_len specifies prefix length of the pool
/// @param delegated_len specifies lenght of the delegated prefixes
Pool6(Pool6Type type, const isc::asiolink::IOAddress& prefix,
Pool6(PoolType type, const isc::asiolink::IOAddress& prefix,
uint8_t prefix_len, uint8_t delegated_len = 128);
/// @brief returns pool type
///
/// @return pool type
Pool6Type getType() const {
PoolType getType() const {
return (type_);
}
......@@ -193,7 +198,7 @@ public:
private:
/// @brief defines a pool type
Pool6Type type_;
PoolType type_;
/// @brief Defines prefix length (for TYPE_PD only)
uint8_t prefix_len_;
......
......@@ -30,7 +30,9 @@ Subnet::Subnet(const isc::asiolink::IOAddress& prefix, uint8_t len,
const Triplet<uint32_t>& valid_lifetime)
:id_(getNextID()), prefix_(prefix), prefix_len_(len), t1_(t1),
t2_(t2), valid_(valid_lifetime),
last_allocated_(lastAddrInPrefix(prefix, len)) {
last_allocated_ia_(lastAddrInPrefix(prefix, len)),
last_allocated_ta_(lastAddrInPrefix(prefix, len)),
last_allocated_pd_(lastAddrInPrefix(prefix, len)) {
if ((prefix.isV6() && len > 128) ||
(prefix.isV4() && len > 32)) {
isc_throw(BadValue,
......@@ -86,6 +88,38 @@ Subnet::getOptionDescriptor(const std::string& option_space,
return (*range.first);
}
isc::asiolink::IOAddress Subnet::getLastAllocated(Pool::PoolType type) const {
switch (type) {
case Pool::TYPE_V4:
case Pool::TYPE_IA:
return last_allocated_ia_;
case Pool::TYPE_TA:
return last_allocated_ta_;
case Pool::TYPE_PD:
return last_allocated_pd_;
default:
isc_throw(BadValue, "Pool type " << type << " not supported");
}
}
void Subnet::setLastAllocated(const isc::asiolink::IOAddress& addr,
Pool::PoolType type) {
switch (type) {
case Pool::TYPE_V4:
case Pool::TYPE_IA:
last_allocated_ia_ = addr;
return;
case Pool::TYPE_TA:
last_allocated_ta_ = addr;
return;
case Pool::TYPE_PD:
last_allocated_pd_ = addr;
return;
default:
isc_throw(BadValue, "Pool type " << type << " not supported");
}
}
std::string
Subnet::toText() const {
std::stringstream tmp;
......@@ -104,6 +138,10 @@ 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();
......
......@@ -240,10 +240,9 @@ public:
/// @todo: Define map<SubnetID, IOAddress> somewhere in the
/// AllocEngine::IterativeAllocator and keep the data there
///
/// @return address that was last tried from this pool
isc::asiolink::IOAddress getLastAllocated() const {
return (last_allocated_);
}
/// @param type lease type to be returned
/// @return address/prefix that was last tried from this pool
isc::asiolink::IOAddress getLastAllocated(Pool::PoolType type) const;
/// @brief sets the last address that was tried from this pool
///
......@@ -253,9 +252,10 @@ public:
///
/// @todo: Define map<SubnetID, IOAddress> somewhere in the
/// AllocEngine::IterativeAllocator and keep the data there
void setLastAllocated(const isc::asiolink::IOAddress& addr) {
last_allocated_ = addr;
}
/// @param addr address/prefix to that was tried last
/// @param type lease type to be set
void setLastAllocated(const isc::asiolink::IOAddress& addr,
Pool::PoolType type);
/// @brief returns unique ID for that subnet
/// @return unique ID for that subnet
......@@ -280,7 +280,7 @@ public:
/// @brief Returns a pool without any address specified
/// @return returns one of the pools defined
PoolPtr getPool() {
PoolPtr getAnyPool() {
return (getPool(default_pool()));
}
......@@ -295,9 +295,7 @@ public:
/// The reference is only valid as long as the object that returned it.
///
/// @return a collection of all pools
const PoolCollection& getPools() const {
return pools_;
}
const PoolCollection& getPools() const;
/// @brief sets name of the network interface for directly attached networks
///
......@@ -377,7 +375,17 @@ protected:
/// removing a pool, restarting or changing allocation algorithms. For
/// that purpose it should be only considered a help that should not be
/// fully trusted.
isc::asiolink::IOAddress last_allocated_;
isc::asiolink::IOAddress last_allocated_ia_;
/// @brief last allocated temporary address
///
/// See @ref last_allocated_ia_ for details.
isc::asiolink::IOAddress last_allocated_ta_;
/// @brief last allocated IPv6 prefix
///
/// See @ref last_allocated_ia_ for details.
isc::asiolink::IOAddress last_allocated_pd_;
/// @brief Name of the network interface (if connected directly)
std::string iface_;
......@@ -493,7 +501,7 @@ protected:
/// @brief specifies optional interface-id
OptionPtr interface_id_;
/// @brief collection of pools in that list
/// @brief collection of pools for non-temporary addresses
Pool6Collection pools_;
/// @brief a triplet with preferred lifetime (in seconds)
......
......@@ -375,7 +375,7 @@ TEST_F(AllocEngine6Test, allocateAddress6Nulls) {
// pool
TEST_F(AllocEngine6Test, IterativeAllocator) {
boost::scoped_ptr<NakedAllocEngine::Allocator>
alloc(new NakedAllocEngine::IterativeAllocator());
alloc(new NakedAllocEngine::IterativeAllocator(Pool6::TYPE_IA));
for (int i = 0; i < 1000; ++i) {
IOAddress candidate = alloc->pickAddress(subnet_, duid_, IOAddress("::"));
......@@ -388,7 +388,7 @@ TEST_F(AllocEngine6Test, IterativeAllocator) {
// in all pools in specified subnet. It also must not pick the same address twice
// unless it runs out of pool space and must start over.
TEST_F(AllocEngine6Test, IterativeAllocator_manyPools6) {
NakedAllocEngine::IterativeAllocator alloc;
NakedAllocEngine::IterativeAllocator alloc(Pool6::TYPE_IA);
// let's start from 2, as there is 2001:db8:1::10 - 2001:db8:1::20 pool already.
for (int i = 2; i < 10; ++i) {
......@@ -829,7 +829,7 @@ TEST_F(AllocEngine4Test, allocateAddress4Nulls) {
// pool
TEST_F(AllocEngine4Test, IterativeAllocator) {
boost::scoped_ptr<NakedAllocEngine::Allocator>
alloc(new NakedAllocEngine::IterativeAllocator());
alloc(new NakedAllocEngine::IterativeAllocator(Pool6::TYPE_V4));
for (int i = 0; i < 1000; ++i) {
IOAddress candidate = alloc->pickAddress(subnet_, clientid_,
......@@ -843,7 +843,7 @@ TEST_F(AllocEngine4Test, IterativeAllocator) {
// in all pools in specified subnet. It also must not pick the same address twice
// unless it runs out of pool space and must start over.
TEST_F(AllocEngine4Test, IterativeAllocator_manyPools4) {
NakedAllocEngine::IterativeAllocator alloc;
NakedAllocEngine::IterativeAllocator alloc(Pool6::TYPE_V4);
// Let's start from 2, as there is 2001:db8:1::10 - 2001:db8:1::20 pool already.
for (int i = 2; i < 10; ++i) {
......
......@@ -69,7 +69,7 @@ TEST(Subnet4Test, Pool4InSubnet4) {
subnet->addPool(pool1);
// If there's only one pool, get that pool
PoolPtr mypool = subnet->getPool();
PoolPtr mypool = subnet->getAnyPool();
EXPECT_EQ(mypool, pool1);
......@@ -78,7 +78,7 @@ TEST(Subnet4Test, Pool4InSubnet4) {
// If there are more than one pool and we didn't provide hint, we
// should get the first pool
mypool = subnet->getPool();
mypool = subnet->getAnyPool();
EXPECT_EQ(mypool, pool1);
......@@ -215,7 +215,7 @@ TEST(Subnet6Test, Pool6InSubnet6) {
subnet->addPool(pool1);
// If there's only one pool, get that pool
PoolPtr mypool = subnet->getPool();
PoolPtr mypool = subnet->getAnyPool();
EXPECT_EQ(mypool, pool1);
......@@ -224,7 +224,7 @@ TEST(Subnet6Test, Pool6InSubnet6) {
// If there are more than one pool and we didn't provide hint, we
// should get the first pool
mypool = subnet->getPool();
mypool = subnet->getAnyPool();
EXPECT_EQ(mypool, pool1);
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment