From: Marcin Siodelski Date: Mon, 9 Mar 2015 11:28:28 +0000 (+0100) Subject: [3688] Implemented AllocEngine::findReservation for DHCPv4. X-Git-Tag: trac3764_base~12^2~16 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=ac390543456cb370b683d788da13ed8dcb2c5dc6;p=thirdparty%2Fkea.git [3688] Implemented AllocEngine::findReservation for DHCPv4. --- diff --git a/src/lib/dhcpsrv/alloc_engine.cc b/src/lib/dhcpsrv/alloc_engine.cc index 1b96d90a99..9a2516d363 100644 --- a/src/lib/dhcpsrv/alloc_engine.cc +++ b/src/lib/dhcpsrv/alloc_engine.cc @@ -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. diff --git a/src/lib/dhcpsrv/alloc_engine.h b/src/lib/dhcpsrv/alloc_engine.h index a92a837aae..1b4e6f31a4 100644 --- a/src/lib/dhcpsrv/alloc_engine.h +++ b/src/lib/dhcpsrv/alloc_engine.h @@ -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. diff --git a/src/lib/dhcpsrv/tests/alloc_engine4_unittest.cc b/src/lib/dhcpsrv/tests/alloc_engine4_unittest.cc index 3d5706ce3e..3ea9042bfa 100644 --- a/src/lib/dhcpsrv/tests/alloc_engine4_unittest.cc +++ b/src/lib/dhcpsrv/tests/alloc_engine4_unittest.cc @@ -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