From: Tomek Mrugalski Date: Thu, 19 Sep 2013 17:38:05 +0000 (+0200) Subject: [3171] First test implementing PD lease allocation passed! X-Git-Tag: bind10-1.2.0beta1-release~190^2~10 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=3e08c03f168623554f4dac564cbfd4bc5160bf76;p=thirdparty%2Fkea.git [3171] First test implementing PD lease allocation passed! --- diff --git a/src/lib/dhcpsrv/alloc_engine.cc b/src/lib/dhcpsrv/alloc_engine.cc index 0d0189b351..1a1f7aa080 100644 --- a/src/lib/dhcpsrv/alloc_engine.cc +++ b/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 diff --git a/src/lib/dhcpsrv/subnet.cc b/src/lib/dhcpsrv/subnet.cc index 0cd19163ac..44aafe7beb 100644 --- a/src/lib/dhcpsrv/subnet.cc +++ b/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(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(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(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(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); } diff --git a/src/lib/dhcpsrv/subnet.h b/src/lib/dhcpsrv/subnet.h index 130c24e429..ce9ba1fa5e 100644 --- a/src/lib/dhcpsrv/subnet.h +++ b/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 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 diff --git a/src/lib/dhcpsrv/tests/alloc_engine_unittest.cc b/src/lib/dhcpsrv/tests/alloc_engine_unittest.cc index 1d6775bc07..54f417b226 100644 --- a/src/lib/dhcpsrv/tests/alloc_engine_unittest.cc +++ b/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 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 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 diff --git a/src/lib/dhcpsrv/tests/subnet_unittest.cc b/src/lib/dhcpsrv/tests/subnet_unittest.cc index a3dcbdcd84..d8497d6218 100644 --- a/src/lib/dhcpsrv/tests/subnet_unittest.cc +++ b/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