Browse Source

[3677] Partial support for multiple addresses per host added.

Tomek Mrugalski 10 years ago
parent
commit
1ea60ccfc7

+ 10 - 0
src/lib/dhcpsrv/alloc_engine.cc

@@ -670,6 +670,16 @@ AllocEngine::allocateReservedLeases6(ClientContext6& ctx, Lease6Collection& exis
         IOAddress addr = resv->second.getPrefix();
         IOAddress addr = resv->second.getPrefix();
         uint8_t prefix_len = resv->second.getPrefixLen();
         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.
         // 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.
         // It doesn't matter whether it is for this client or for someone else.
         if (!LeaseMgrFactory::instance().getLease6(ctx.type_, addr)) {
         if (!LeaseMgrFactory::instance().getLease6(ctx.type_, addr)) {

+ 7 - 0
src/lib/dhcpsrv/lease.h

@@ -415,6 +415,13 @@ typedef boost::shared_ptr<const Lease6> ConstLease6Ptr;
 /// @brief A collection of IPv6 leases.
 /// @brief A collection of IPv6 leases.
 typedef std::vector<Lease6Ptr> Lease6Collection;
 typedef std::vector<Lease6Ptr> Lease6Collection;
 
 
+/// @brief A non-const iterator for IPv6 leases collection
+typedef std::vector<Lease6Ptr>::iterator Lease6CollectionIter;
+
+/// @brief A const iterator for IPv6 leases collection
+typedef std::vector<Lease6Ptr>::const_iterator Lease6CollectionConstIter;
+
+
 /// @brief Stream output operator.
 /// @brief Stream output operator.
 ///
 ///
 /// Dumps the output of Lease::toText to the given stream.
 /// Dumps the output of Lease::toText to the given stream.

+ 41 - 0
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());
     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
 // Checks whether address can change during renew (if there is a new
 // reservation for this client)
 // reservation for this client)
 TEST_F(AllocEngine6Test, reservedAddressRenewChange) {
 TEST_F(AllocEngine6Test, reservedAddressRenewChange) {