Commit c9bae474 authored by Tomek Mrugalski's avatar Tomek Mrugalski 🛰
Browse files

[2238] lifetimes are now property of Subnet6, not Pool6

parent daf7bbcc
......@@ -23,12 +23,8 @@ namespace isc {
namespace dhcp {
Pool::Pool(const isc::asiolink::IOAddress& first,
const isc::asiolink::IOAddress& last,
const Triplet<uint32_t>& t1,
const Triplet<uint32_t>& t2,
const Triplet<uint32_t>& valid_lifetime)
:id_(getNextID()), first_(first), last_(last), t1_(t1), t2_(t2),
valid_(valid_lifetime) {
const isc::asiolink::IOAddress& last)
:id_(getNextID()), first_(first), last_(last) {
}
bool Pool::inRange(const isc::asiolink::IOAddress& addr) {
......@@ -36,13 +32,8 @@ bool Pool::inRange(const isc::asiolink::IOAddress& addr) {
}
Pool6::Pool6(Pool6Type type, const isc::asiolink::IOAddress& first,
const isc::asiolink::IOAddress& last,
const Triplet<uint32_t>& t1,
const Triplet<uint32_t>& t2,
const Triplet<uint32_t>& preferred_lifetime,
const Triplet<uint32_t>& valid_lifetime)
:Pool(first, last, t1, t2, valid_lifetime),
type_(type), prefix_len_(0), preferred_(preferred_lifetime) {
const isc::asiolink::IOAddress& last)
:Pool(first, last), type_(type), prefix_len_(0) {
// check if specified address boundaries are sane
if (first.getFamily() != AF_INET6 || last.getFamily() != AF_INET6) {
......@@ -70,13 +61,9 @@ Pool6::Pool6(Pool6Type type, const isc::asiolink::IOAddress& first,
}
Pool6::Pool6(Pool6Type type, const isc::asiolink::IOAddress& prefix,
uint8_t prefix_len,
const Triplet<uint32_t>& t1,
const Triplet<uint32_t>& t2,
const Triplet<uint32_t>& preferred_lifetime,
const Triplet<uint32_t>& valid_lifetime)
:Pool(prefix, IOAddress("::"), t1, t2, valid_lifetime),
type_(type), prefix_len_(prefix_len), preferred_(preferred_lifetime) {
uint8_t prefix_len)
:Pool(prefix, IOAddress("::")),
type_(type), prefix_len_(prefix_len) {
// check if the prefix is sane
if (prefix.getFamily() != AF_INET6) {
......@@ -92,8 +79,12 @@ Pool6::Pool6(Pool6Type type, const isc::asiolink::IOAddress& prefix,
last_ = lastAddrInPrefix(prefix, prefix_len);
}
Subnet::Subnet(const isc::asiolink::IOAddress& prefix, uint8_t len)
:id_(getNextID()), prefix_(prefix), prefix_len_(len) {
Subnet::Subnet(const isc::asiolink::IOAddress& prefix, uint8_t len,
const Triplet<uint32_t>& t1,
const Triplet<uint32_t>& t2,
const Triplet<uint32_t>& valid_lifetime)
:id_(getNextID()), prefix_(prefix), prefix_len_(len), t1_(t1),
t2_(t2), valid_(valid_lifetime) {
if ( (prefix.getFamily() == AF_INET6 && len > 128) ||
(prefix.getFamily() == AF_INET && len > 32) ) {
isc_throw(BadValue, "Invalid prefix length specified for subnet: " << len);
......@@ -107,10 +98,16 @@ bool Subnet::inRange(const isc::asiolink::IOAddress& addr) {
return ( (first <= addr) && (addr <= last) );
}
Subnet6::Subnet6(const isc::asiolink::IOAddress& prefix, uint8_t length)
:Subnet(prefix, length) {
Subnet6::Subnet6(const isc::asiolink::IOAddress& prefix, uint8_t length,
const Triplet<uint32_t>& t1,
const Triplet<uint32_t>& t2,
const Triplet<uint32_t>& preferred_lifetime,
const Triplet<uint32_t>& valid_lifetime)
:Subnet(prefix, length, t1, t2, valid_lifetime),
preferred_(preferred_lifetime){
if (prefix.getFamily() != AF_INET6) {
isc_throw(BadValue, "Invalid prefix " << prefix.toText() << " specified in subnet6");
isc_throw(BadValue, "Invalid prefix " << prefix.toText()
<< " specified in subnet6");
}
}
......@@ -127,7 +124,6 @@ void Subnet6::addPool6(const Pool6Ptr& pool) {
pools_.push_back(pool);
}
Pool6Ptr Subnet6::getPool6(const isc::asiolink::IOAddress& hint /* = IOAddress("::")*/ ) {
Pool6Ptr candidate;
for (Pool6Collection::iterator pool = pools_.begin(); pool != pools_.end(); ++pool) {
......
......@@ -28,14 +28,18 @@ namespace isc {
namespace dhcp {
class Pool6;
class Subnet6;
/// @brief this class specifes parameter value
/// @brief this template specifes a parameter value
///
/// This class is used to store configuration parameters, like lifetime or T1.
/// It defines 3 parameters: min/default/max values. There are 2 constructors:
/// This template class is used to store configuration parameters, like lifetime or T1.
/// It defines 3 parameters: min, default, and max value. There are 2 constructors:
/// - simple (just one value that sets all parameters)
/// - extended (that sets default value and two thresholds)
/// It will be used with integer types. It provides necessary operators, so
/// it can be assigned to a plain integer or integer assigned to a Triplet.
/// See TripletTest.operator test for details on an easy Triplet usage.
template <class T>
class Triplet {
public:
......@@ -57,6 +61,9 @@ public:
}
/// @brief sets a fixed value
///
/// This constructor assigns a fixed (i.e. no range, just a single value)
/// value.
Triplet(T value)
:min_(value), default_(value), max_(value) {
}
......@@ -109,6 +116,11 @@ protected:
T max_;
};
/// @brief base class for Pool4 and Pool6
///
/// Stores information about pool of IPv4 or IPv6 addresses.
/// That is a basic component of a configuration.
class Pool {
public:
......@@ -116,10 +128,6 @@ public:
return (id_);
}
Triplet<uint32_t> getValid() const {
return (valid_);
}
const isc::asiolink::IOAddress& getFirstAddress() const {
return (first_);
}
......@@ -128,14 +136,6 @@ public:
return (last_);
}
Triplet<uint32_t> getT1() const {
return (t1_);
}
Triplet<uint32_t> getT2() const {
return (t2_);
}
/// @brief checks if specified address is in range
bool inRange(const isc::asiolink::IOAddress& addr);
......@@ -143,10 +143,7 @@ protected:
/// @brief protected constructor
Pool(const isc::asiolink::IOAddress& first,
const isc::asiolink::IOAddress& last,
const Triplet<uint32_t>& t1,
const Triplet<uint32_t>& t2,
const Triplet<uint32_t>& valid_lifetime);
const isc::asiolink::IOAddress& last);
static uint32_t getNextID() {
static uint32_t id = 0;
......@@ -162,12 +159,6 @@ protected:
isc::asiolink::IOAddress last_;
Triplet<uint32_t> t1_;
Triplet<uint32_t> t2_;
Triplet<uint32_t> valid_;
std::string comments_;
///uint128_t available_leases_;
......@@ -184,27 +175,15 @@ public:
} Pool6Type;
Pool6(Pool6Type type, const isc::asiolink::IOAddress& first,
const isc::asiolink::IOAddress& last,
const Triplet<uint32_t>& t1,
const Triplet<uint32_t>& t2,
const Triplet<uint32_t>& preferred_lifetime,
const Triplet<uint32_t>& valid_lifetime);
const isc::asiolink::IOAddress& last);
Pool6(Pool6Type type, const isc::asiolink::IOAddress& addr,
uint8_t prefix_len,
const Triplet<uint32_t>& t1,
const Triplet<uint32_t>& t2,
const Triplet<uint32_t>& preferred_lifetime,
const Triplet<uint32_t>& valid_lifetime);
uint8_t prefix_len);
Pool6Type getType() const {
return (type_);
}
Triplet<uint32_t> getPreferred() const {
return (preferred_);
}
protected:
Pool6Type type_;
......@@ -212,8 +191,6 @@ protected:
/// @brief prefix length
/// used by TYPE_PD only (zeroed for other types)
uint8_t prefix_len_;
Triplet<uint32_t> preferred_;
};
typedef boost::shared_ptr<Pool> PoolPtr;
......@@ -226,12 +203,27 @@ public:
/// @brief checks if specified address is in range
bool inRange(const isc::asiolink::IOAddress& addr);
Triplet<uint32_t> getValid() const {
return (valid_);
}
Triplet<uint32_t> getT1() const {
return (t1_);
}
Triplet<uint32_t> getT2() const {
return (t2_);
}
protected:
/// @brief protected constructor
//
/// By making the constructor protected, we make sure that noone will
/// ever instantiate that class. Pool4 and Pool6 should be used instead.
Subnet(const isc::asiolink::IOAddress& prefix, uint8_t len);
Subnet(const isc::asiolink::IOAddress& prefix, uint8_t len,
const Triplet<uint32_t>& t1,
const Triplet<uint32_t>& t2,
const Triplet<uint32_t>& valid_lifetime);
static uint32_t getNextID() {
static uint32_t id = 0;
......@@ -246,13 +238,28 @@ protected:
uint8_t prefix_len_;
Pool6Collection pool_;
Triplet<uint32_t> t1_;
Triplet<uint32_t> t2_;
Triplet<uint32_t> valid_;
};
class Subnet6 : public Subnet {
public:
Subnet6(const isc::asiolink::IOAddress& prefix, uint8_t length);
Subnet6(const isc::asiolink::IOAddress& prefix, uint8_t length,
const Triplet<uint32_t>& t1,
const Triplet<uint32_t>& t2,
const Triplet<uint32_t>& preferred_lifetime,
const Triplet<uint32_t>& valid_lifetime);
Triplet<uint32_t> getPreferred() const {
return (preferred_);
}
Pool6Ptr getPool6(const isc::asiolink::IOAddress& hint = isc::asiolink::IOAddress("::"));
Pool6Ptr getPool6(const isc::asiolink::IOAddress& hint =
isc::asiolink::IOAddress("::"));
void addPool6(const Pool6Ptr& pool);
......@@ -264,11 +271,39 @@ protected:
/// collection of pools in that list
Pool6Collection pools_;
Triplet<uint32_t> preferred_;
};
typedef boost::shared_ptr<Subnet6> Subnet6Ptr;
typedef std::vector<Subnet6Ptr> Subnet6Collection;
/// @brief Configuration Manager
///
/// This singleton class holds the whole configuration for DHCPv4 and DHCPv6
/// servers. It currently holds information about zero or more subnets6.
/// Each subnet may contain zero or more pools. Pool4 and Pool6 is the most
/// basic "chunk" of configuration. It contains a range of assigneable
/// addresses.
///
/// The sketch of configuration inheritance (it is not implemented yet).
/// Let's investigate the following configuration:
///
/// valid-lifetime 1000;
/// subnet6 2001:db8:1::/48 {
/// pool6 2001::db8:1::1 - 2001::db8:1::ff;
/// };
/// subnet6 2001:db8:2::/48 {
/// valid-lifetime 2000;
/// pool6 2001::db8:2::1 - 2001::db8:2::ff;
/// };
/// Parameters defined in a global scope are considered valid until
/// they are overwritten in a smaller scope, in this case subnet6.
/// In the example above, the first subnet6
///
/// @todo: Implement Subnet4 support (ticket #2237)
/// @todo: Implement option definition support
/// @todo: Implement inheritance.
class CfgMgr : public boost::noncopyable {
public:
static CfgMgr& instance();
......
......@@ -103,58 +103,42 @@ TEST(Pool6Test, constructor_first_last) {
// let's construct 2001:db8:1:: - 2001:db8:1::ffff:ffff:ffff:ffff pool
Pool6 pool1(Pool6::TYPE_IA, IOAddress("2001:db8:1::"),
IOAddress("2001:db8:1::ffff:ffff:ffff:ffff"),
1000, 2000, 3000, 4000);
IOAddress("2001:db8:1::ffff:ffff:ffff:ffff"));
EXPECT_EQ(Pool6::TYPE_IA, pool1.getType());
EXPECT_EQ(IOAddress("2001:db8:1::"), pool1.getFirstAddress());
EXPECT_EQ(IOAddress("2001:db8:1::ffff:ffff:ffff:ffff"),
pool1.getLastAddress());
EXPECT_EQ(1000, pool1.getT1());
EXPECT_EQ(2000, pool1.getT2());
EXPECT_EQ(3000, pool1.getPreferred());
EXPECT_EQ(4000, pool1.getValid());
// This is Pool6, IPv4 addresses do not belong here
EXPECT_THROW(Pool6(Pool6::TYPE_IA, IOAddress("2001:db8::1"),
IOAddress("192.168.0.5"),
1000, 2000, 3000, 4000), BadValue);
IOAddress("192.168.0.5")), BadValue);
EXPECT_THROW(Pool6(Pool6::TYPE_IA, IOAddress("192.168.0.2"),
IOAddress("2001:db8::1"),
1000, 2000, 3000, 4000), BadValue);
IOAddress("2001:db8::1")), BadValue);
// Should throw. Range should be 2001:db8::1 - 2001:db8::2, not
// the other way around.
EXPECT_THROW(Pool6(Pool6::TYPE_IA, IOAddress("2001:db8::2"),
IOAddress("2001:db8::1"),
1000, 2000, 3000, 4000), BadValue);
IOAddress("2001:db8::1")), BadValue);
}
TEST(Pool6Test, constructor_prefix_len) {
// let's construct 2001:db8:1::/96 pool
Pool6 pool1(Pool6::TYPE_IA, IOAddress("2001:db8:1::"),
96, 1000, 2000, 3000, 4000);
Pool6 pool1(Pool6::TYPE_IA, IOAddress("2001:db8:1::"), 96);
EXPECT_EQ(Pool6::TYPE_IA, pool1.getType());
EXPECT_EQ("2001:db8:1::", pool1.getFirstAddress().toText());
EXPECT_EQ("2001:db8:1::ffff:ffff", pool1.getLastAddress().toText());
EXPECT_EQ(1000, pool1.getT1());
EXPECT_EQ(2000, pool1.getT2());
EXPECT_EQ(3000, pool1.getPreferred());
EXPECT_EQ(4000, pool1.getValid());
// This is Pool6, IPv4 addresses do not belong here
EXPECT_THROW(Pool6(Pool6::TYPE_IA, IOAddress("192.168.0.2"),
96, 1000, 2000, 3000, 4000),
EXPECT_THROW(Pool6(Pool6::TYPE_IA, IOAddress("192.168.0.2"), 96),
BadValue);
}
TEST(Pool6Test, in_range) {
Pool6 pool1(Pool6::TYPE_IA, IOAddress("2001:db8:1::1"),
IOAddress("2001:db8:1::f"),
1000, 2000, 3000, 4000);
IOAddress("2001:db8:1::f"));
EXPECT_FALSE(pool1.inRange(IOAddress("2001:db8:1::")));
EXPECT_TRUE(pool1.inRange(IOAddress("2001:db8:1::1")));
......@@ -172,8 +156,7 @@ TEST(Pool6Test, unique_id) {
for (int i = 0; i < num_pools; ++i) {
pools.push_back(Pool6Ptr(new Pool6(Pool6::TYPE_IA, IOAddress("2001:db8:1::"),
IOAddress("2001:db8:1::ffff:ffff:ffff:ffff"),
1000, 2000, 3000, 4000)));
IOAddress("2001:db8:1::ffff:ffff:ffff:ffff"))));
}
for (int i = 0; i < num_pools; ++i) {
......@@ -189,16 +172,23 @@ TEST(Pool6Test, unique_id) {
TEST(Subnet6Test, constructor) {
EXPECT_NO_THROW(Subnet6 subnet1(IOAddress("2001:db8:1::"), 64));
EXPECT_NO_THROW(Subnet6 subnet1(IOAddress("2001:db8:1::"), 64,
1, 2, 3, 4));
EXPECT_THROW(Subnet6 subnet2(IOAddress("2001:db8:1::"), 129),
EXPECT_THROW(Subnet6 subnet2(IOAddress("2001:db8:1::"), 129, 1, 2, 3, 4),
BadValue); // invalid prefix length
EXPECT_THROW(Subnet6 subnet3(IOAddress("192.168.0.0"), 32),
EXPECT_THROW(Subnet6 subnet3(IOAddress("192.168.0.0"), 32, 1, 2, 3, 4),
BadValue); // IPv4 addresses are not allowed in Subnet6
}
TEST(Subnet6Test, in_range) {
Subnet6 subnet(IOAddress("2001:db8:1::"), 64);
Subnet6 subnet(IOAddress("2001:db8:1::"), 64, 1000, 2000, 3000, 4000);
EXPECT_EQ(1000, subnet.getT1());
EXPECT_EQ(2000, subnet.getT2());
EXPECT_EQ(3000, subnet.getPreferred());
EXPECT_EQ(4000, subnet.getValid());
EXPECT_FALSE(subnet.inRange(IOAddress("2001:db8:0:ffff:ffff:ffff:ffff:ffff")));
EXPECT_TRUE(subnet.inRange(IOAddress("2001:db8:1::0")));
......@@ -210,15 +200,11 @@ TEST(Subnet6Test, in_range) {
TEST(Subnet6Test, Pool6InSubnet6) {
Subnet6Ptr subnet(new Subnet6(IOAddress("2001:db8:1::"), 56));
Pool6Ptr pool1(new Pool6(Pool6::TYPE_IA, IOAddress("2001:db8:1:1::"),
64, 101, 102, 103, 104));
Pool6Ptr pool2(new Pool6(Pool6::TYPE_IA, IOAddress("2001:db8:1:2::"),
64, 201, 202, 203, 204));
Pool6Ptr pool3(new Pool6(Pool6::TYPE_IA, IOAddress("2001:db8:1:3::"),
64, 301, 302, 303, 304));
Subnet6Ptr subnet(new Subnet6(IOAddress("2001:db8:1::"), 56, 1, 2, 3, 4));
Pool6Ptr pool1(new Pool6(Pool6::TYPE_IA, IOAddress("2001:db8:1:1::"), 64));
Pool6Ptr pool2(new Pool6(Pool6::TYPE_IA, IOAddress("2001:db8:1:2::"), 64));
Pool6Ptr pool3(new Pool6(Pool6::TYPE_IA, IOAddress("2001:db8:1:3::"), 64));
subnet->addPool6(pool1);
......@@ -245,21 +231,20 @@ TEST(Subnet6Test, Pool6InSubnet6) {
TEST(Subnet6Test, Subnet6_Pool6_checks) {
Subnet6Ptr subnet(new Subnet6(IOAddress("2001:db8:1::"), 56));
Subnet6Ptr subnet(new Subnet6(IOAddress("2001:db8:1::"), 56, 1, 2, 3, 4));
// this one is in subnet
Pool6Ptr pool1(new Pool6(Pool6::TYPE_IA, IOAddress("2001:db8:1:1::"),
64, 101, 102, 103, 104));
Pool6Ptr pool1(new Pool6(Pool6::TYPE_IA, IOAddress("2001:db8:1:1::"), 64));
subnet->addPool6(pool1);
Pool6Ptr pool2(new Pool6(Pool6::TYPE_IA, IOAddress("2001:db8::"),
48, 201, 202, 203, 204)); // this one is larger than the subnet!
// this one is larger than the subnet!
Pool6Ptr pool2(new Pool6(Pool6::TYPE_IA, IOAddress("2001:db8::"), 48));
EXPECT_THROW(subnet->addPool6(pool2), BadValue);
// this one is totally out of blue
Pool6Ptr pool3(new Pool6(Pool6::TYPE_IA, IOAddress("3000::"),
16, 301, 302, 303, 304));
Pool6Ptr pool3(new Pool6(Pool6::TYPE_IA, IOAddress("3000::"), 16));
EXPECT_THROW(subnet->addPool6(pool3), BadValue);
}
......@@ -271,9 +256,9 @@ TEST(CfgMgrTest, subnet6) {
ASSERT_TRUE(&cfg_mgr != 0);
Subnet6Ptr subnet1(new Subnet6(IOAddress("2000::"), 48));
Subnet6Ptr subnet2(new Subnet6(IOAddress("3000::"), 48));
Subnet6Ptr subnet3(new Subnet6(IOAddress("4000::"), 48));
Subnet6Ptr subnet1(new Subnet6(IOAddress("2000::"), 48, 1, 2, 3, 4));
Subnet6Ptr subnet2(new Subnet6(IOAddress("3000::"), 48, 1, 2, 3, 4));
Subnet6Ptr subnet3(new Subnet6(IOAddress("4000::"), 48, 1, 2, 3, 4));
// there shouldn't be any subnet configured at this stage
EXPECT_EQ( Subnet6Ptr(), cfg_mgr.getSubnet6(IOAddress("2000::1")));
......
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