From: Tomek Mrugalski Date: Mon, 17 Sep 2012 17:26:03 +0000 (+0200) Subject: [2238] lifetimes are now property of Subnet6, not Pool6 X-Git-Tag: trac2402_base~5^2~17^2~6 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=c9bae4745f58fc361ebeb0f91bb15b288e96e5cf;p=thirdparty%2Fkea.git [2238] lifetimes are now property of Subnet6, not Pool6 --- diff --git a/src/lib/dhcp/cfgmgr.cc b/src/lib/dhcp/cfgmgr.cc index c3098b6de4..0da47ad418 100644 --- a/src/lib/dhcp/cfgmgr.cc +++ b/src/lib/dhcp/cfgmgr.cc @@ -23,12 +23,8 @@ namespace isc { namespace dhcp { Pool::Pool(const isc::asiolink::IOAddress& first, - const isc::asiolink::IOAddress& last, - const Triplet& t1, - const Triplet& t2, - const Triplet& 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& t1, - const Triplet& t2, - const Triplet& preferred_lifetime, - const Triplet& 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& t1, - const Triplet& t2, - const Triplet& preferred_lifetime, - const Triplet& 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& t1, + const Triplet& t2, + const Triplet& 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& t1, + const Triplet& t2, + const Triplet& preferred_lifetime, + const Triplet& 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) { diff --git a/src/lib/dhcp/cfgmgr.h b/src/lib/dhcp/cfgmgr.h index ff58a54ef9..4023e0c5b5 100644 --- a/src/lib/dhcp/cfgmgr.h +++ b/src/lib/dhcp/cfgmgr.h @@ -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 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 getValid() const { - return (valid_); - } - const isc::asiolink::IOAddress& getFirstAddress() const { return (first_); } @@ -128,14 +136,6 @@ public: return (last_); } - Triplet getT1() const { - return (t1_); - } - - Triplet 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& t1, - const Triplet& t2, - const Triplet& 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 t1_; - - Triplet t2_; - - Triplet 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& t1, - const Triplet& t2, - const Triplet& preferred_lifetime, - const Triplet& valid_lifetime); + const isc::asiolink::IOAddress& last); Pool6(Pool6Type type, const isc::asiolink::IOAddress& addr, - uint8_t prefix_len, - const Triplet& t1, - const Triplet& t2, - const Triplet& preferred_lifetime, - const Triplet& valid_lifetime); + uint8_t prefix_len); Pool6Type getType() const { return (type_); } - Triplet 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 preferred_; }; typedef boost::shared_ptr PoolPtr; @@ -226,12 +203,27 @@ public: /// @brief checks if specified address is in range bool inRange(const isc::asiolink::IOAddress& addr); + Triplet getValid() const { + return (valid_); + } + + Triplet getT1() const { + return (t1_); + } + + Triplet 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& t1, + const Triplet& t2, + const Triplet& valid_lifetime); static uint32_t getNextID() { static uint32_t id = 0; @@ -246,13 +238,28 @@ protected: uint8_t prefix_len_; Pool6Collection pool_; + + Triplet t1_; + + Triplet t2_; + + Triplet 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& t1, + const Triplet& t2, + const Triplet& preferred_lifetime, + const Triplet& valid_lifetime); + + Triplet 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 preferred_; }; typedef boost::shared_ptr Subnet6Ptr; typedef std::vector 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(); diff --git a/src/lib/dhcp/tests/cfgmgr_unittest.cc b/src/lib/dhcp/tests/cfgmgr_unittest.cc index d810cd227b..6592803c3b 100644 --- a/src/lib/dhcp/tests/cfgmgr_unittest.cc +++ b/src/lib/dhcp/tests/cfgmgr_unittest.cc @@ -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")));