Browse Source

[3171] First test implementing PD lease allocation passed!

Tomek Mrugalski 11 years ago
parent
commit
3e08c03f16

+ 1 - 1
src/lib/dhcpsrv/alloc_engine.cc

@@ -517,7 +517,7 @@ AllocEngine::allocateAddress4(const SubnetPtr& subnet,
         }
 
         // check if the hint is in pool and is available
-        if (subnet->inPool(hint)) {
+        if (subnet->inPool(Lease::TYPE_V4, hint)) {
             existing = LeaseMgrFactory::instance().getLease4(hint);
             if (!existing) {
                 /// @todo: Check if the hint is reserved once we have host support

+ 40 - 49
src/lib/dhcpsrv/subnet.cc

@@ -168,32 +168,48 @@ const PoolCollection& Subnet::getPools(Lease::Type type) const {
     }
 }
 
-PoolPtr Subnet::getPool(Lease::Type type, isc::asiolink::IOAddress hint,
-                        bool anypool /* true */) {
-    // check if the type is valid (and throw if it isn't)
-    checkType(type);
-
-    PoolCollection* pools = NULL;
+PoolCollection& Subnet::getPools(Lease::Type type) {
+    switch (type) {
+    case Lease::TYPE_V4:
+    case Lease::TYPE_NA:
+        return (pools_);
+    case Lease::TYPE_TA:
+        return (pools_);
+    case Lease::TYPE_PD:
+        return (pools_pd_);
+    default:
+        isc_throw(BadValue, "Invalid pool type specified: "
+                  << static_cast<int>(type));
+    }
+}
 
+#if 0
+const PoolCollection& Subnet::getConstPools(Lease::Type type) const {
     switch (type) {
     case Lease::TYPE_V4:
     case Lease::TYPE_NA:
-        pools = &pools_;
-        break;
+        return (pools_);
     case Lease::TYPE_TA:
-        pools = &pools_ta_;
-        break;
+        return (pools_);
     case Lease::TYPE_PD:
-        pools = &pools_pd_;
-        break;
+        return (pools_pd_);
     default:
-        isc_throw(BadValue, "Failed to select pools. Unknown pool type: "
-                  << type);
+        isc_throw(BadValue, "Invalid pool type specified: "
+                  << static_cast<int>(type));
     }
+}
+#endif
+
+PoolPtr Subnet::getPool(Lease::Type type, isc::asiolink::IOAddress hint,
+                        bool anypool /* true */) {
+    // check if the type is valid (and throw if it isn't)
+    checkType(type);
+
+    const PoolCollection& pools = getPools(type);
 
     PoolPtr candidate;
-    for (PoolCollection::const_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 (anypool && !candidate) {
@@ -226,40 +242,13 @@ Subnet::addPool(const PoolPtr& pool) {
     // check if the type is valid (and throw if it isn't)
     checkType(pool->getType());
 
-    switch (pool->getType()) {
-    case Lease::TYPE_V4:
-    case Lease::TYPE_NA:
-        pools_.push_back(pool);
-        return;
-    case Lease::TYPE_TA:
-        pools_ta_.push_back(pool);
-        return;
-    case Lease::TYPE_PD:
-        pools_pd_.push_back(pool);
-        return;
-    default:
-        isc_throw(BadValue, "Invalid pool type specified: "
-                  << static_cast<int>(pool->getType()));
-    }
+    // Add the pool to the appropriate pools collection
+    getPools(pool->getType()).push_back(pool);
 }
 
 void
 Subnet::delPools(Lease::Type type) {
-    switch (type) {
-    case Lease::TYPE_V4:
-    case Lease::TYPE_NA:
-        pools_.clear();
-        return;
-    case Lease::TYPE_TA:
-        pools_ta_.clear();
-        return;
-    case Lease::TYPE_PD:
-        pools_pd_.clear();
-        return;
-    default:
-        isc_throw(BadValue, "Invalid pool type specified: "
-                  << static_cast<int>(type));
-    }
+    getPools(type).clear();
 }
 
 void
@@ -284,15 +273,17 @@ Subnet4::validateOption(const OptionPtr& option) const {
 }
 
 bool
-Subnet::inPool(const isc::asiolink::IOAddress& addr) const {
+Subnet::inPool(Lease::Type type, const isc::asiolink::IOAddress& addr) const {
 
     // Let's start with checking if it even belongs to that subnet.
     if (!inRange(addr)) {
         return (false);
     }
 
-    for (PoolCollection::const_iterator pool = pools_.begin();
-         pool != pools_.end(); ++pool) {
+    const PoolCollection& pools = getPools(type);
+
+    for (PoolCollection::const_iterator pool = pools.begin();
+         pool != pools.end(); ++pool) {
         if ((*pool)->inRange(addr)) {
             return (true);
         }

+ 11 - 2
src/lib/dhcpsrv/subnet.h

@@ -192,10 +192,11 @@ public:
     /// is not always true. For the given example, 2001::1234:abcd would return
     /// true for inSubnet(), but false for inPool() check.
     ///
+    /// @param type pool types to iterate over
     /// @param addr this address will be checked if it belongs to any pools in
     ///        that subnet
     /// @return true if the address is in any of the pools
-    bool inPool(const isc::asiolink::IOAddress& addr) const;
+    bool inPool(Lease::Type type, const isc::asiolink::IOAddress& addr) const;
 
     /// @brief return valid-lifetime for addresses in that prefix
     Triplet<uint32_t> getValid() const {
@@ -310,7 +311,7 @@ public:
     /// and 0.0.0.0 for Subnet4)
     virtual isc::asiolink::IOAddress default_pool() const = 0;
 
-    /// @brief returns all pools
+    /// @brief returns all pools (const variant)
     ///
     /// The reference is only valid as long as the object that returned it.
     ///
@@ -318,6 +319,14 @@ public:
     /// @return a collection of all pools
     const PoolCollection& getPools(Lease::Type type) const;
 
+    /// @brief returns all pools (variable variant)
+    ///
+    /// 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
+    PoolCollection& getPools(Lease::Type type);
+
     /// @brief sets name of the network interface for directly attached networks
     ///
     /// @param iface_name name of the interface

+ 63 - 6
src/lib/dhcpsrv/tests/alloc_engine_unittest.cc

@@ -127,7 +127,7 @@ public:
         // that is belongs to the right subnet
         EXPECT_EQ(lease->subnet_id_, subnet_->getID());
         EXPECT_TRUE(subnet_->inRange(lease->addr_));
-        EXPECT_TRUE(subnet_->inPool(lease->addr_));
+        EXPECT_TRUE(subnet_->inPool(Lease::TYPE_NA, lease->addr_));
 
         // that it have proper parameters
         EXPECT_EQ(iaid_, lease->iaid_);
@@ -142,6 +142,29 @@ public:
         // @todo: check cltt
     }
 
+    /// @brief checks if Lease6 PD matches expected configuration
+    ///
+    /// @param lease lease to be checked
+    void checkPDLease6(const Lease6Ptr& lease, uint8_t expected_pd_len) {
+        // that is belongs to the right subnet
+        EXPECT_EQ(lease->subnet_id_, subnet_->getID());
+        EXPECT_TRUE(subnet_->inRange(lease->addr_));
+        EXPECT_TRUE(subnet_->inPool(Lease::TYPE_PD, lease->addr_));
+
+        // that it have proper parameters
+        EXPECT_EQ(iaid_, lease->iaid_);
+        EXPECT_EQ(subnet_->getValid(), lease->valid_lft_);
+        EXPECT_EQ(subnet_->getPreferred(), lease->preferred_lft_);
+        EXPECT_EQ(subnet_->getT1(), lease->t1_);
+        EXPECT_EQ(subnet_->getT2(), lease->t2_);
+
+        EXPECT_EQ(expected_pd_len, lease->prefixlen_); // IA_PD
+        EXPECT_TRUE(false == lease->fqdn_fwd_);
+        EXPECT_TRUE(false == lease->fqdn_rev_);
+        EXPECT_TRUE(*lease->duid_ == *duid_);
+        // @todo: check cltt
+    }
+
     /// @brief checks if specified address is increased properly
     /// @param alloc IterativeAllocator that is tested
     /// @param input address to be increased
@@ -207,7 +230,7 @@ public:
         // Check that is belongs to the right subnet
         EXPECT_EQ(lease->subnet_id_, subnet_->getID());
         EXPECT_TRUE(subnet_->inRange(lease->addr_));
-        EXPECT_TRUE(subnet_->inPool(lease->addr_));
+        EXPECT_TRUE(subnet_->inPool(Lease::TYPE_V4, lease->addr_));
 
         // Check that it has proper parameters
         EXPECT_EQ(subnet_->getValid(), lease->valid_lft_);
@@ -288,6 +311,40 @@ TEST_F(AllocEngine6Test, simpleAlloc6) {
     detailCompareLease(lease, from_mgr);
 }
 
+
+// This test checks if the simple PD allocation can succeed
+TEST_F(AllocEngine6Test, pdSimpleAlloc6) {
+    boost::scoped_ptr<AllocEngine> engine;
+    ASSERT_NO_THROW(engine.reset(new AllocEngine(AllocEngine::ALLOC_ITERATIVE, 100)));
+    ASSERT_TRUE(engine);
+
+    subnet_->delPools(Lease::TYPE_NA);
+
+    Pool6Ptr pd_pool(new Pool6(Lease::TYPE_PD, IOAddress("2001:db8:1::"), 56, 64));
+    subnet_->addPool(pd_pool);
+
+    Lease6Ptr lease;
+    EXPECT_NO_THROW(lease = expectOneLease(engine->allocateAddress6(subnet_,
+                    duid_, iaid_, IOAddress("::"), Lease::TYPE_PD, false, false,
+                    "", false, CalloutHandlePtr())));
+
+    // Check that we got a lease
+    ASSERT_TRUE(lease);
+
+    EXPECT_EQ(Lease::TYPE_PD, lease->type_);
+
+    // Do all checks on the PD lease
+    checkPDLease6(lease, pd_pool->getLength());
+
+    // Check that the lease is indeed in LeaseMgr
+    Lease6Ptr from_mgr = LeaseMgrFactory::instance().getLease6(lease->type_,
+                                                               lease->addr_);
+    ASSERT_TRUE(from_mgr);
+
+    // Now check that the lease in LeaseMgr has the same parameters
+    detailCompareLease(lease, from_mgr);
+}
+
 // This test checks if the fake allocation (for SOLICIT) can succeed
 TEST_F(AllocEngine6Test, fakeAlloc6) {
     boost::scoped_ptr<AllocEngine> engine;
@@ -447,7 +504,7 @@ TEST_F(AllocEngine6Test, IterativeAllocator) {
 
     for (int i = 0; i < 1000; ++i) {
         IOAddress candidate = alloc->pickAddress(subnet_, duid_, IOAddress("::"));
-        EXPECT_TRUE(subnet_->inPool(candidate));
+        EXPECT_TRUE(subnet_->inPool(Lease::TYPE_NA, candidate));
     }
 }
 
@@ -636,7 +693,7 @@ TEST_F(AllocEngine6Test, IterativeAllocator_manyPools6) {
     int cnt = 0;
     while (++cnt) {
         IOAddress candidate = alloc.pickAddress(subnet_, duid_, IOAddress("::"));
-        EXPECT_TRUE(subnet_->inPool(candidate));
+        EXPECT_TRUE(subnet_->inPool(Lease::TYPE_NA, candidate));
 
         // One way to easily verify that the iterative allocator really works is
         // to uncomment the following line and observe its output that it
@@ -1093,7 +1150,7 @@ TEST_F(AllocEngine4Test, IterativeAllocator) {
     for (int i = 0; i < 1000; ++i) {
         IOAddress candidate = alloc->pickAddress(subnet_, clientid_,
                                                  IOAddress("0.0.0.0"));
-        EXPECT_TRUE(subnet_->inPool(candidate));
+        EXPECT_TRUE(subnet_->inPool(Lease::TYPE_V4, candidate));
     }
 }
 
@@ -1125,7 +1182,7 @@ TEST_F(AllocEngine4Test, IterativeAllocator_manyPools4) {
     int cnt = 0;
     while (++cnt) {
         IOAddress candidate = alloc.pickAddress(subnet_, clientid_, IOAddress("0.0.0.0"));
-        EXPECT_TRUE(subnet_->inPool(candidate));
+        EXPECT_TRUE(subnet_->inPool(Lease::TYPE_V4, candidate));
 
         // One way to easily verify that the iterative allocator really works is
         // to uncomment the following line and observe its output that it

+ 12 - 12
src/lib/dhcpsrv/tests/subnet_unittest.cc

@@ -140,27 +140,27 @@ TEST(Subnet4Test, inRangeinPool) {
     EXPECT_TRUE(subnet->inRange(IOAddress("192.1.1.1")));
 
     // ... but it does not belong to any pool within
-    EXPECT_FALSE(subnet->inPool(IOAddress("192.1.1.1")));
+    EXPECT_FALSE(subnet->inPool(Lease::TYPE_V4, IOAddress("192.1.1.1")));
 
     // the last address that is in range, but out of pool
     EXPECT_TRUE(subnet->inRange(IOAddress("192.1.255.255")));
-    EXPECT_FALSE(subnet->inPool(IOAddress("192.1.255.255")));
+    EXPECT_FALSE(subnet->inPool(Lease::TYPE_V4, IOAddress("192.1.255.255")));
 
     // the first address that is in range, in pool
     EXPECT_TRUE(subnet->inRange(IOAddress("192.2.0.0")));
-    EXPECT_TRUE (subnet->inPool(IOAddress("192.2.0.0")));
+    EXPECT_TRUE (subnet->inPool(Lease::TYPE_V4, IOAddress("192.2.0.0")));
 
     // let's try something in the middle as well
     EXPECT_TRUE(subnet->inRange(IOAddress("192.2.3.4")));
-    EXPECT_TRUE (subnet->inPool(IOAddress("192.2.3.4")));
+    EXPECT_TRUE (subnet->inPool(Lease::TYPE_V4, IOAddress("192.2.3.4")));
 
     // the last address that is in range, in pool
     EXPECT_TRUE(subnet->inRange(IOAddress("192.2.255.255")));
-    EXPECT_TRUE (subnet->inPool(IOAddress("192.2.255.255")));
+    EXPECT_TRUE (subnet->inPool(Lease::TYPE_V4, IOAddress("192.2.255.255")));
 
     // the first address that is in range, but out of pool
     EXPECT_TRUE(subnet->inRange(IOAddress("192.3.0.0")));
-    EXPECT_FALSE(subnet->inPool(IOAddress("192.3.0.0")));
+    EXPECT_FALSE(subnet->inPool(Lease::TYPE_V4, IOAddress("192.3.0.0")));
 }
 
 // This test checks if the toText() method returns text representation
@@ -609,27 +609,27 @@ TEST(Subnet6Test, inRangeinPool) {
     // 192.1.1.1 belongs to the subnet...
     EXPECT_TRUE(subnet->inRange(IOAddress("2001:db8::1")));
     // ... but it does not belong to any pool within
-    EXPECT_FALSE(subnet->inPool(IOAddress("2001:db8::1")));
+    EXPECT_FALSE(subnet->inPool(Lease::TYPE_V4, IOAddress("2001:db8::1")));
 
     // the last address that is in range, but out of pool
     EXPECT_TRUE(subnet->inRange(IOAddress("2001:db8::f")));
-    EXPECT_FALSE(subnet->inPool(IOAddress("2001:db8::f")));
+    EXPECT_FALSE(subnet->inPool(Lease::TYPE_V4, IOAddress("2001:db8::f")));
 
     // the first address that is in range, in pool
     EXPECT_TRUE(subnet->inRange(IOAddress("2001:db8::10")));
-    EXPECT_TRUE (subnet->inPool(IOAddress("2001:db8::10")));
+    EXPECT_TRUE (subnet->inPool(Lease::TYPE_V4, IOAddress("2001:db8::10")));
 
     // let's try something in the middle as well
     EXPECT_TRUE(subnet->inRange(IOAddress("2001:db8::18")));
-    EXPECT_TRUE (subnet->inPool(IOAddress("2001:db8::18")));
+    EXPECT_TRUE (subnet->inPool(Lease::TYPE_V4, IOAddress("2001:db8::18")));
 
     // the last address that is in range, in pool
     EXPECT_TRUE(subnet->inRange(IOAddress("2001:db8::20")));
-    EXPECT_TRUE (subnet->inPool(IOAddress("2001:db8::20")));
+    EXPECT_TRUE (subnet->inPool(Lease::TYPE_V4, IOAddress("2001:db8::20")));
 
     // the first address that is in range, but out of pool
     EXPECT_TRUE(subnet->inRange(IOAddress("2001:db8::21")));
-    EXPECT_FALSE(subnet->inPool(IOAddress("2001:db8::21")));
+    EXPECT_FALSE(subnet->inPool(Lease::TYPE_V4, IOAddress("2001:db8::21")));
 }
 
 // This test checks if the toText() method returns text representation