]> git.ipfire.org Git - thirdparty/kea.git/commitdiff
[3688] Implemented AllocEngine::findReservation for DHCPv4.
authorMarcin Siodelski <marcin@isc.org>
Mon, 9 Mar 2015 11:28:28 +0000 (12:28 +0100)
committerMarcin Siodelski <marcin@isc.org>
Mon, 9 Mar 2015 11:28:28 +0000 (12:28 +0100)
src/lib/dhcpsrv/alloc_engine.cc
src/lib/dhcpsrv/alloc_engine.h
src/lib/dhcpsrv/tests/alloc_engine4_unittest.cc

index 1b96d90a99960f44b30f32968e94e21a8750a466..9a2516d3635d49f81252ea6278e29ee5e4535247 100644 (file)
@@ -1300,6 +1300,26 @@ AllocEngine::allocateLease4(ClientContext4& ctx) {
     return (new_lease);
 }
 
+void
+AllocEngine::findReservation(ClientContext4& ctx) const {
+    ctx.host_.reset();
+
+    // We can only search for the reservation if a subnet has been selected.
+    if (ctx.subnet_) {
+        // Check which host reservation mode is supported in this subnet.
+        Subnet::HRMode hr_mode = ctx.subnet_->getHostReservationMode();
+
+        // Check if there is a host reseravtion for this client. Attempt to
+        // get host information
+        if (hr_mode != Subnet::HR_DISABLED) {
+            // This method should handle the case when there is neither hwaddr
+            // nor clientid_ available and simply return NULL.
+            ctx.host_ = HostMgr::instance().get4(ctx.subnet_->getID(), ctx.hwaddr_,
+                                                 ctx.clientid_);
+        }
+    }
+}
+
 Lease4Ptr
 AllocEngine::discoverLease4(AllocEngine::ClientContext4& ctx) {
     // Obtain the sole instance of the LeaseMgr.
index a92a837aae491e5e21cc5756d6037592956cce48..1b4e6f31a4ae2b9faa6ace646d85cbdc6e14dc17 100644 (file)
@@ -874,6 +874,16 @@ public:
     /// @return Allocated IPv4 lease (or NULL if allocation failed).
     Lease4Ptr allocateLease4(ClientContext4& ctx);
 
+    /// @brief Attempts to find the host reservation for the client.
+    ///
+    /// This method attempts to find the host reservation for the client. If
+    /// found, it is set in the @c ctx.host_. If the host reservations are
+    /// disabled for the particular subnet or the reservation is not found
+    /// for the client, the @ctx.host_ is set to NULL.
+    ///
+    /// @param ctx Client context holding various information about the client.
+    void findReservation(ClientContext4& ctx) const;
+
 private:
 
     /// @brief Offers the lease.
index 3d5706ce3e21f9f4c1ed8a69dafb75b7f4b2d8d8..3ea9042bfadd8755c7144e55d3dbf5a7b9bba520 100644 (file)
@@ -1292,6 +1292,80 @@ TEST_F(AllocEngine4Test, reservedAddressShortPool) {
     EXPECT_EQ("192.0.2.100", allocated_lease->addr_.toText());
 }
 
+// This test checks that the AllocEngine::findReservation method finds
+// and returns host reservation for the DHCPv4 client using the data from
+// the client context. If the host reservation can't be found, it sets
+// the value of NULL in the host_ field of the client context.
+TEST_F(AllocEngine4Test, findReservation) {
+    // Create the instance of the allocation engine.
+    AllocEngine engine(AllocEngine::ALLOC_ITERATIVE, 100, false);
+
+    // Context is required to call the AllocEngine::findReservation.
+    AllocEngine::ClientContext4 ctx(subnet_, clientid_, hwaddr_,
+                                    IOAddress("0.0.0.0"), false, false,
+                                    "", false);
+
+    // There is no reservation in the database so no host should be
+    // retruned.
+    ASSERT_NO_THROW(engine.findReservation(ctx));
+    EXPECT_FALSE(ctx.host_);
+
+    // Create a reservation for the client.
+    HostPtr host(new Host(&hwaddr_->hwaddr_[0], hwaddr_->hwaddr_.size(),
+                          Host::IDENT_HWADDR, subnet_->getID(),
+                          SubnetID(0), IOAddress("192.0.2.100")));
+    CfgMgr::instance().getStagingCfg()->getCfgHosts()->add(host);
+    CfgMgr::instance().commit();
+
+    // This time the reservation should be returned.
+    ASSERT_NO_THROW(engine.findReservation(ctx));
+    EXPECT_TRUE(ctx.host_);
+    EXPECT_EQ(ctx.host_->getIPv4Reservation(), host->getIPv4Reservation());
+
+    // If the host reservation mode for the subnet is disabled, the
+    // host should not be returned, even though it exists in the
+    // host database.
+    subnet_->setHostReservationMode(Subnet::HR_DISABLED);
+    ASSERT_NO_THROW(engine.findReservation(ctx));
+    EXPECT_FALSE(ctx.host_);
+
+    // Check the third possible reservation mode.
+    subnet_->setHostReservationMode(Subnet::HR_OUT_OF_POOL);
+    ASSERT_NO_THROW(engine.findReservation(ctx));
+    EXPECT_TRUE(ctx.host_);
+    EXPECT_EQ(ctx.host_->getIPv4Reservation(), host->getIPv4Reservation());
+
+    // This time use the client identifier to search for the host.
+    host.reset(new Host(&clientid_->getClientId()[0],
+                        clientid_->getClientId().size(),
+                        Host::IDENT_DUID, subnet_->getID(),
+                        SubnetID(0), IOAddress("192.0.2.101")));
+    CfgMgr::instance().getStagingCfg()->getCfgHosts()->add(host);
+    CfgMgr::instance().commit();
+
+    ASSERT_NO_THROW(engine.findReservation(ctx));
+    EXPECT_TRUE(ctx.host_);
+    EXPECT_EQ(ctx.host_->getIPv4Reservation(), host->getIPv4Reservation());
+
+    // Remove the subnet. Subnet id is required to find host reservations, so
+    // if it is set to NULL, no reservation should be returned
+    ctx.subnet_.reset();
+    ASSERT_NO_THROW(engine.findReservation(ctx));
+    EXPECT_FALSE(ctx.host_);
+
+    // The same if there is a mismatch of the subnet id between the reservation
+    // and the context.
+    ctx.subnet_ = subnet_;
+    host.reset(new Host(&hwaddr_->hwaddr_[0], hwaddr_->hwaddr_.size(),
+                        Host::IDENT_HWADDR, subnet_->getID() + 1,
+                        SubnetID(0), IOAddress("192.0.2.100")));
+    CfgMgr::instance().getStagingCfg()->getCfgHosts()->add(host);
+    CfgMgr::instance().commit();
+
+    ASSERT_NO_THROW(engine.findReservation(ctx));
+    EXPECT_FALSE(ctx.host_);
+}
+
 }; // namespace test
 }; // namespace dhcp
 }; // namespace isc