From: Tomek Mrugalski Date: Thu, 19 Sep 2013 16:35:32 +0000 (+0200) Subject: [3171] IterativeAllocator::pickAddress() now handles prefixes as well X-Git-Tag: bind10-1.2.0beta1-release~190^2~11 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=4b7664ccfdf1640cbdd914ddd032989149a3f0ef;p=thirdparty%2Fkea.git [3171] IterativeAllocator::pickAddress() now handles prefixes as well - pickAddress() handles prefixes as well - Subnet::delPools() implemented - tests for iterating over address and prefix pools implemented. --- diff --git a/src/lib/dhcpsrv/alloc_engine.cc b/src/lib/dhcpsrv/alloc_engine.cc index 5ad754f258..0d0189b351 100644 --- a/src/lib/dhcpsrv/alloc_engine.cc +++ b/src/lib/dhcpsrv/alloc_engine.cc @@ -137,6 +137,9 @@ AllocEngine::IterativeAllocator::pickAddress(const SubnetPtr& subnet, const DuidPtr&, const IOAddress&) { + // Is this prefix allocation? + bool prefix = pool_type_ == Lease::TYPE_PD; + // Let's get the last allocated address. It is usually set correctly, // but there are times when it won't be (like after removing a pool or // perhaps restarting the server). @@ -169,7 +172,18 @@ AllocEngine::IterativeAllocator::pickAddress(const SubnetPtr& subnet, // Ok, we have a pool that the last address belonged to, let's use it. - IOAddress next = increaseAddress(last); // basically addr++ + IOAddress next("::"); + if (!prefix) { + next = increaseAddress(last); // basically addr++ + } else { + Pool6Ptr pool6 = boost::dynamic_pointer_cast(*it); + if (!pool6) { + // Something is gravely wrong here + isc_throw(InvalidParameter, "Wrong type of pool"); + } + // Get the next prefix + next = increasePrefix(last, (pool6)->getLength()); + } if ((*it)->inRange(next)) { // the next one is in the pool as well, so we haven't hit pool boundary yet subnet->setLastAllocated(pool_type_, next); diff --git a/src/lib/dhcpsrv/subnet.cc b/src/lib/dhcpsrv/subnet.cc index 442f4180b8..0cd19163ac 100644 --- a/src/lib/dhcpsrv/subnet.cc +++ b/src/lib/dhcpsrv/subnet.cc @@ -243,6 +243,25 @@ Subnet::addPool(const PoolPtr& 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)); + } +} + void Subnet::setIface(const std::string& iface_name) { iface_ = iface_name; diff --git a/src/lib/dhcpsrv/subnet.h b/src/lib/dhcpsrv/subnet.h index b209c2d3ab..130c24e429 100644 --- a/src/lib/dhcpsrv/subnet.h +++ b/src/lib/dhcpsrv/subnet.h @@ -272,6 +272,13 @@ public: /// @param pool pool to be added void addPool(const PoolPtr& pool); + + /// @brief Deletes all pools of specified type + /// + /// This method is used for testing purposes only + /// @param type type of pools to be deleted + void delPools(Lease::Type type); + /// @brief Returns a pool that specified address belongs to /// /// If there is no pool that the address belongs to (hint is invalid), other diff --git a/src/lib/dhcpsrv/tests/alloc_engine_unittest.cc b/src/lib/dhcpsrv/tests/alloc_engine_unittest.cc index ecfe9d26ac..1d6775bc07 100644 --- a/src/lib/dhcpsrv/tests/alloc_engine_unittest.cc +++ b/src/lib/dhcpsrv/tests/alloc_engine_unittest.cc @@ -451,10 +451,100 @@ TEST_F(AllocEngine6Test, IterativeAllocator) { } } -// This test verifies that the allocator iterates over addresses properly TEST_F(AllocEngine6Test, IterativeAllocatorAddrStep) { NakedAllocEngine::NakedIterativeAllocator alloc(Lease::TYPE_NA); + subnet_->delPools(Lease::TYPE_NA); // Get rid of default pool + + Pool6Ptr pool1(new Pool6(Lease::TYPE_NA, IOAddress("2001:db8:1::1"), + IOAddress("2001:db8:1::5"))); + Pool6Ptr pool2(new Pool6(Lease::TYPE_NA, IOAddress("2001:db8:1::100"), + IOAddress("2001:db8:1::100"))); + Pool6Ptr pool3(new Pool6(Lease::TYPE_NA, IOAddress("2001:db8:1::105"), + IOAddress("2001:db8:1::106"))); + subnet_->addPool(pool1); + subnet_->addPool(pool2); + subnet_->addPool(pool3); + + // Let's check the first pool (5 addresses here) + EXPECT_EQ("2001:db8:1::1", alloc.pickAddress(subnet_, duid_, IOAddress("::")).toText()); + EXPECT_EQ("2001:db8:1::2", alloc.pickAddress(subnet_, duid_, IOAddress("::")).toText()); + EXPECT_EQ("2001:db8:1::3", alloc.pickAddress(subnet_, duid_, IOAddress("::")).toText()); + EXPECT_EQ("2001:db8:1::4", alloc.pickAddress(subnet_, duid_, IOAddress("::")).toText()); + EXPECT_EQ("2001:db8:1::5", alloc.pickAddress(subnet_, duid_, IOAddress("::")).toText()); + + // The second pool is easy - only one address here + EXPECT_EQ("2001:db8:1::100", alloc.pickAddress(subnet_, duid_, IOAddress("::")).toText()); + + // This is the third and last pool, with 2 addresses in it + EXPECT_EQ("2001:db8:1::105", alloc.pickAddress(subnet_, duid_, IOAddress("::")).toText()); + EXPECT_EQ("2001:db8:1::106", alloc.pickAddress(subnet_, duid_, IOAddress("::")).toText()); + + // We iterated over all addresses and reached to the end of the last pool. + // Let's wrap around and start from the beginning + EXPECT_EQ("2001:db8:1::1", alloc.pickAddress(subnet_, duid_, IOAddress("::")).toText()); + EXPECT_EQ("2001:db8:1::2", alloc.pickAddress(subnet_, duid_, IOAddress("::")).toText()); +} + +TEST_F(AllocEngine6Test, IterativeAllocatorPrefixStep) { + NakedAllocEngine::NakedIterativeAllocator alloc(Lease::TYPE_PD); + + subnet_.reset(new Subnet6(IOAddress("2001:db8::"), 32, 1, 2, 3, 4)); + + Pool6Ptr pool1(new Pool6(Lease::TYPE_PD, IOAddress("2001:db8::"), 56, 60)); + Pool6Ptr pool2(new Pool6(Lease::TYPE_PD, IOAddress("2001:db8:1::"), 48, 48)); + Pool6Ptr pool3(new Pool6(Lease::TYPE_PD, IOAddress("2001:db8:2::"), 56, 64)); + subnet_->addPool(pool1); + subnet_->addPool(pool2); + subnet_->addPool(pool3); + + // We have a 2001:db8::/48 subnet that has 3 pools defined in it: + // 2001:db8::/56 split into /60 prefixes (16 leases) (or 2001:db8:0:X0::) + // 2001:db8:1::/48 split into a single /48 prefix (just 1 lease) + // 2001:db8:2::/56 split into /64 prefixes (256 leases) (or 2001:db8:2:XX::) + + // First pool check (Let's check over all 16 leases) + EXPECT_EQ("2001:db8::", alloc.pickAddress(subnet_, duid_, IOAddress("::")).toText()); + EXPECT_EQ("2001:db8:0:10::", alloc.pickAddress(subnet_, duid_, IOAddress("::")).toText()); + EXPECT_EQ("2001:db8:0:20::", alloc.pickAddress(subnet_, duid_, IOAddress("::")).toText()); + EXPECT_EQ("2001:db8:0:30::", alloc.pickAddress(subnet_, duid_, IOAddress("::")).toText()); + EXPECT_EQ("2001:db8:0:40::", alloc.pickAddress(subnet_, duid_, IOAddress("::")).toText()); + EXPECT_EQ("2001:db8:0:50::", alloc.pickAddress(subnet_, duid_, IOAddress("::")).toText()); + EXPECT_EQ("2001:db8:0:60::", alloc.pickAddress(subnet_, duid_, IOAddress("::")).toText()); + EXPECT_EQ("2001:db8:0:70::", alloc.pickAddress(subnet_, duid_, IOAddress("::")).toText()); + EXPECT_EQ("2001:db8:0:80::", alloc.pickAddress(subnet_, duid_, IOAddress("::")).toText()); + EXPECT_EQ("2001:db8:0:90::", alloc.pickAddress(subnet_, duid_, IOAddress("::")).toText()); + EXPECT_EQ("2001:db8:0:a0::", alloc.pickAddress(subnet_, duid_, IOAddress("::")).toText()); + EXPECT_EQ("2001:db8:0:b0::", alloc.pickAddress(subnet_, duid_, IOAddress("::")).toText()); + EXPECT_EQ("2001:db8:0:c0::", alloc.pickAddress(subnet_, duid_, IOAddress("::")).toText()); + EXPECT_EQ("2001:db8:0:d0::", alloc.pickAddress(subnet_, duid_, IOAddress("::")).toText()); + EXPECT_EQ("2001:db8:0:e0::", alloc.pickAddress(subnet_, duid_, IOAddress("::")).toText()); + EXPECT_EQ("2001:db8:0:f0::", alloc.pickAddress(subnet_, duid_, IOAddress("::")).toText()); + + // Second pool (just one lease here) + EXPECT_EQ("2001:db8:1::", alloc.pickAddress(subnet_, duid_, IOAddress("::")).toText()); + + // Third pool (256 leases, let's check first and last explictly and the + // rest over in a pool + EXPECT_EQ("2001:db8:2::", alloc.pickAddress(subnet_, duid_, IOAddress("::")).toText()); + for (int i = 1; i < 255; i++) { + stringstream exp; + exp << "2001:db8:2:" << hex << i << dec << "::"; + EXPECT_EQ(exp.str(), alloc.pickAddress(subnet_, duid_, IOAddress("::")).toText()); + + } + EXPECT_EQ("2001:db8:2:ff::", alloc.pickAddress(subnet_, duid_, IOAddress("::")).toText()); + + // Ok, we've iterated over all prefixes in all pools. We now wrap around. + // We're looping over now (iterating over first pool again) + EXPECT_EQ("2001:db8::", alloc.pickAddress(subnet_, duid_, IOAddress("::")).toText()); + EXPECT_EQ("2001:db8:0:10::", alloc.pickAddress(subnet_, duid_, IOAddress("::")).toText()); +} + +// This test verifies that the iterative allocator can step over addresses +TEST_F(AllocEngine6Test, IterativeAllocatorAddressIncrease) { + NakedAllocEngine::NakedIterativeAllocator alloc(Lease::TYPE_NA); + // Let's pick the first address IOAddress addr1 = alloc.pickAddress(subnet_, duid_, IOAddress("2001:db8:1::10")); @@ -469,8 +559,11 @@ TEST_F(AllocEngine6Test, IterativeAllocatorAddrStep) { checkAddrIncrease(alloc, "2001:db8::ffff", "2001:db8::1:0"); checkAddrIncrease(alloc, "::", "::1"); checkAddrIncrease(alloc, "ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff", "::"); +} - // Check that prefixes can be increased properly +// This test verifies that the allocator can step over prefixes +TEST_F(AllocEngine6Test, IterativeAllocatorPrefixIncrease) { + NakedAllocEngine::NakedIterativeAllocator alloc(Lease::TYPE_PD); // For /128 prefix, increasePrefix should work the same as addressIncrease checkPrefixIncrease(alloc, "2001:db8::9", 128, "2001:db8::a");