From: Tomek Mrugalski Date: Mon, 9 Feb 2015 16:11:37 +0000 (+0100) Subject: [3677] Partial support for multiple addresses per host added. X-Git-Tag: trac3712_base~7^2~5 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=1ea60ccfc761fef4650fbf746d52d7264c64e8d6;p=thirdparty%2Fkea.git [3677] Partial support for multiple addresses per host added. --- diff --git a/src/lib/dhcpsrv/alloc_engine.cc b/src/lib/dhcpsrv/alloc_engine.cc index 6ade1237ec..4b54d19a60 100644 --- a/src/lib/dhcpsrv/alloc_engine.cc +++ b/src/lib/dhcpsrv/alloc_engine.cc @@ -670,6 +670,16 @@ AllocEngine::allocateReservedLeases6(ClientContext6& ctx, Lease6Collection& exis IOAddress addr = resv->second.getPrefix(); uint8_t prefix_len = resv->second.getPrefixLen(); + // Check if already have this lease on the existing_leases list. + for (Lease6CollectionConstIter l = existing_leases.begin(); + l != existing_leases.end(); ++l) { + + // Ok, we already have a lease for this reservation and it's usable + if (((*l)->addr_ == addr) && (*l)->valid_lft_ != 0) { + return; + } + } + // If there's a lease for this address, let's not create it. // It doesn't matter whether it is for this client or for someone else. if (!LeaseMgrFactory::instance().getLease6(ctx.type_, addr)) { diff --git a/src/lib/dhcpsrv/lease.h b/src/lib/dhcpsrv/lease.h index bea3715277..0c536fb5a2 100644 --- a/src/lib/dhcpsrv/lease.h +++ b/src/lib/dhcpsrv/lease.h @@ -415,6 +415,13 @@ typedef boost::shared_ptr ConstLease6Ptr; /// @brief A collection of IPv6 leases. typedef std::vector Lease6Collection; +/// @brief A non-const iterator for IPv6 leases collection +typedef std::vector::iterator Lease6CollectionIter; + +/// @brief A const iterator for IPv6 leases collection +typedef std::vector::const_iterator Lease6CollectionConstIter; + + /// @brief Stream output operator. /// /// Dumps the output of Lease::toText to the given stream. diff --git a/src/lib/dhcpsrv/tests/alloc_engine_unittest.cc b/src/lib/dhcpsrv/tests/alloc_engine_unittest.cc index b4bdd0616a..18258e1ab2 100644 --- a/src/lib/dhcpsrv/tests/alloc_engine_unittest.cc +++ b/src/lib/dhcpsrv/tests/alloc_engine_unittest.cc @@ -1684,6 +1684,47 @@ TEST_F(AllocEngine6Test, reservedAddressRenewal) { ASSERT_EQ("2001:db8:1::1c", leases[0]->addr_.toText()); } +// Checks whether a single host can have more than one reservation. +TEST_F(AllocEngine6Test, reserved2Addresses) { + // Create reservation for the client. This is in-pool reservation, + // as the pool is 2001:db8:1::10 - 2001:db8:1::20. + // Two addresses are reserved: 2001:db8:1::babe and 2001:db8:1::cafe + HostPtr host = createHost6(true, IPv6Resrv::TYPE_NA, + IOAddress("2001:db8:1::babe"), 128); + + IPv6Resrv resv2(IPv6Resrv::TYPE_NA, IOAddress("2001:db8:1::cafe"), 128); + host->addReservation(resv2); + CfgMgr::instance().getStagingCfg()->getCfgHosts()->add(host); + CfgMgr::instance().commit(); + + AllocEngine engine(AllocEngine::ALLOC_ITERATIVE, 100); + + AllocEngine::ClientContext6 ctx1(subnet_, duid_, iaid_, IOAddress("::"), + pool_->getType(), false, false, "", false); + Lease6Collection leases1; + EXPECT_NO_THROW(leases1 = engine.allocateLeases6(ctx1)); + ASSERT_EQ(1, leases1.size()); + EXPECT_EQ("2001:db8:1::babe", leases1[0]->addr_.toText()); + + // Double check that repeating the same duid/type/iaid will end up with + // the same address. + AllocEngine::ClientContext6 ctx2(subnet_, duid_, iaid_, IOAddress("::"), + pool_->getType(), false, false, "", false); + Lease6Collection leases2; + EXPECT_NO_THROW(leases2 = engine.allocateLeases6(ctx2)); + EXPECT_EQ(1, leases2.size()); + EXPECT_EQ("2001:db8:1::babe", leases2[0]->addr_.toText()); + + // Ok, now the tricky part. Request allocation for the same duid and type, but + // different iaid. The second address should be assigned. + AllocEngine::ClientContext6 ctx3(subnet_, duid_, iaid_ + 1, IOAddress("::"), + pool_->getType(), false, false, "", false); + Lease6Collection leases3; + EXPECT_NO_THROW(leases3 = engine.allocateLeases6(ctx3)); + ASSERT_EQ(1, leases3.size()); + EXPECT_EQ("2001:db8:1::cafe", leases3[0]->addr_.toText()); +} + // Checks whether address can change during renew (if there is a new // reservation for this client) TEST_F(AllocEngine6Test, reservedAddressRenewChange) {