Browse Source

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

Tomek Mrugalski 12 years ago
parent
commit
c9bae4745f
3 changed files with 133 additions and 117 deletions
  1. 22 26
      src/lib/dhcp/cfgmgr.cc
  2. 79 44
      src/lib/dhcp/cfgmgr.h
  3. 32 47
      src/lib/dhcp/tests/cfgmgr_unittest.cc

+ 22 - 26
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<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) {

+ 79 - 44
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 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();

+ 32 - 47
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")));