Browse Source

[3689] findReservation() implemented

Tomek Mrugalski 10 years ago
parent
commit
15925ccf96
3 changed files with 78 additions and 33 deletions
  1. 8 4
      src/bin/dhcp6/dhcp6_srv.cc
  2. 45 24
      src/lib/dhcpsrv/alloc_engine.cc
  3. 25 5
      src/lib/dhcpsrv/alloc_engine.h

+ 8 - 4
src/bin/dhcp6/dhcp6_srv.cc

@@ -1301,7 +1301,8 @@ Dhcpv6Srv::assignIA_NA(const Subnet6Ptr& subnet, const DuidPtr& duid,
     // It's ok if there response is NULL. Hardware address is optional in Lease6.
     ctx.hwaddr_ = getMAC(query);
 
-    Lease6Collection leases = alloc_engine_->allocateLeases6(ctx);
+    alloc_engine_->findReservation(ctx);
+    Lease6Collection leases = alloc_engine_->allocateLeases6(ctx, false);
 
     /// @todo: Handle more than one lease
     Lease6Ptr lease;
@@ -1444,7 +1445,8 @@ Dhcpv6Srv::assignIA_PD(const Subnet6Ptr& subnet, const DuidPtr& duid,
     // It's ok if there response is NULL. Hardware address is optional in Lease6
     ctx.hwaddr_ = getMAC(query);
 
-    Lease6Collection leases = alloc_engine_->allocateLeases6(ctx);
+    alloc_engine_->findReservation(ctx);
+    Lease6Collection leases = alloc_engine_->allocateLeases6(ctx, false);
 
     if (!leases.empty()) {
 
@@ -1589,7 +1591,8 @@ Dhcpv6Srv::extendIA_NA(const Subnet6Ptr& subnet, const DuidPtr& duid,
         ctx.allow_new_leases_in_renewals_ = true;
     }
 
-    Lease6Collection leases = alloc_engine_->renewLeases6(ctx);
+    alloc_engine_->findReservation(ctx);
+    Lease6Collection leases = alloc_engine_->renewLeases6(ctx, false);
 
     // Ok, now we have the leases extended. We have:
     // - what the client tried to renew in ctx.hints_
@@ -1770,7 +1773,8 @@ Dhcpv6Srv::extendIA_PD(const Subnet6Ptr& subnet, const DuidPtr& duid,
     // - old_leases - leases that used to be, but are no longer valid
     // - changed_leases - leases that have FQDN changed (not really important
     //                    in PD context)
-    Lease6Collection leases = alloc_engine_->renewLeases6(ctx);
+    alloc_engine_->findReservation(ctx);
+    Lease6Collection leases = alloc_engine_->renewLeases6(ctx, false);
 
     // For all the leases we have now, add the IAPPREFIX with non-zero lifetimes
     for (Lease6Collection::const_iterator l = leases.begin(); l != leases.end(); ++l) {

+ 45 - 24
src/lib/dhcpsrv/alloc_engine.cc

@@ -318,9 +318,30 @@ AllocEngine::ClientContext6::ClientContext6(const Subnet6Ptr& subnet, const Duid
 }
 
 
+void AllocEngine::findReservation(ClientContext6& ctx) const {
+    if (!ctx.subnet_) {
+        isc_throw(InvalidOperation, "Subnet is required for IPv6 lease allocation");
+    } else if (!ctx.duid_) {
+        isc_throw(InvalidOperation, "DUID is mandatory for IPv6 lease allocation");
+    }
+
+    // Check which host reservation mode is supported in this subnet.
+    Subnet::HRMode hr_mode = ctx.subnet_->getHostReservationMode();
+
+    // Check if there's a host reservation for this client. Attempt to get
+    // host info only if reservations are not disabled.
+    if (hr_mode != Subnet::HR_DISABLED) {
+
+        ctx.host_ = HostMgr::instance().get6(ctx.subnet_->getID(), ctx.duid_,
+                                             ctx.hwaddr_);
+        } else {
+        // Let's explicitly set it to NULL if reservations are disabled.
+        ctx.host_.reset();
+    }
+}
 
 Lease6Collection
-AllocEngine::allocateLeases6(ClientContext6& ctx) {
+AllocEngine::allocateLeases6(ClientContext6& ctx, bool find_reservation) {
 
     try {
         if (!ctx.subnet_) {
@@ -330,18 +351,17 @@ AllocEngine::allocateLeases6(ClientContext6& ctx) {
             isc_throw(InvalidOperation, "DUID is mandatory for IPv6 lease allocation");
         }
 
-        // Check which host reservation mode is supported in this subnet.
-        Subnet::HRMode hr_mode = ctx.subnet_->getHostReservationMode();
-
-        // Check if there's a host reservation for this client. Attempt to get
-        // host info only if reservations are not disabled.
-        if (hr_mode != Subnet::HR_DISABLED) {
+        if (find_reservation) {
+            findReservation(ctx);
+        }
 
-            ctx.host_ = HostMgr::instance().get6(ctx.subnet_->getID(), ctx.duid_,
-                                                 ctx.hwaddr_);
-        } else {
-            // Let's explicitly set it to NULL if reservations are disabled.
-            ctx.host_.reset();
+        // Let's check whether there's a hostname specified in the reservation
+        if (ctx.host_) {
+            std::string hostname = ctx.host_->getHostname();
+            // If there is, let's use it
+            if (!hostname.empty()) {
+                ctx.hostname_ = hostname;
+            }
         }
 
         // Check if there are existing leases for that subnet/duid/iaid
@@ -1001,7 +1021,7 @@ Lease6Ptr AllocEngine::createLease6(ClientContext6& ctx,
 }
 
 Lease6Collection
-AllocEngine::renewLeases6(ClientContext6& ctx) {
+AllocEngine::renewLeases6(ClientContext6& ctx, bool find_host) {
     try {
         if (!ctx.subnet_) {
             isc_throw(InvalidOperation, "Subnet is required for allocation");
@@ -1011,20 +1031,21 @@ AllocEngine::renewLeases6(ClientContext6& ctx) {
             isc_throw(InvalidOperation, "DUID is mandatory for allocation");
         }
 
-        // Check which host reservation mode is supported in this subnet.
-        Subnet::HRMode hr_mode = ctx.subnet_->getHostReservationMode();
-
-        // Check if there's a host reservation for this client. Attempt to get
-        // host info only if reservations are not disabled.
-        if (hr_mode != Subnet::HR_DISABLED) {
+        // We can attempt to find appropriate reservation
+        if (find_host) {
+            findReservation(ctx);
+        }
 
-            ctx.host_ = HostMgr::instance().get6(ctx.subnet_->getID(), ctx.duid_,
-                                                 ctx.hwaddr_);
-        } else {
-            // Host reservations disabled? Then explicitly set host to NULL
-            ctx.host_.reset();
+        // Let's check whether there's a hostname specified in the reservation
+        if (ctx.host_) {
+            std::string hostname = ctx.host_->getHostname();
+            // If there is, let's use it
+            if (!hostname.empty()) {
+                ctx.hostname_ = hostname;
+            }
         }
 
+
         // Check if there are any leases for this client.
         Lease6Collection leases = LeaseMgrFactory::instance()
             .getLeases6(ctx.type_, *ctx.duid_, ctx.iaid_, ctx.subnet_->getID());

+ 25 - 5
src/lib/dhcpsrv/alloc_engine.h

@@ -406,7 +406,8 @@ public:
     /// it into LeaseMgr (if this allocation is not fake, i.e. this is not a
     /// response to SOLICIT).
     ///
-    /// This method uses host reservation if appropriate. The host reservation
+    /// This method uses host reservation if ctx.host_ is set. The easy way to
+    /// set it is to call @ref AllocEngine::findReservation(ctx). The host reservation
     /// is convenient, but incurs performance penalty, so it can be tweaked on
     /// a per subnet basis. There are three possible modes:
     /// 1. disabled (no host reservation at all). This is the most performant one
@@ -444,6 +445,12 @@ public:
     ///
     /// @param ctx client context that passes all necessary information. See
     ///        @ref ClientContext6 for details.
+    /// @param find_resrv specifies whether the code should search for host
+    ///   reservation. true means that the code will consult HostMgr, false means
+    ///   to skip this check. That is easier to use, but is redundant if the
+    ///   ctx.host_ field is already set. We can't use ctx.host_ == NULL as
+    ///   check, because for cases whithout reservations, the reservation
+    ///   search would be repeated.
     ///
     /// The following fields of ClientContext6 are used:
     ///
@@ -477,8 +484,7 @@ public:
     ///
     /// @return Allocated IPv6 leases (may be empty if allocation failed)
     Lease6Collection
-    allocateLeases6(ClientContext6& ctx);
-
+    allocateLeases6(ClientContext6& ctx, bool find_resrv = true);
 
     /// @brief Renews existing DHCPv6 leases for a given IA.
     ///
@@ -498,9 +504,23 @@ public:
     /// prefixes the client had sent. @ref ClientContext6::old_leases_ will
     /// contain removed leases in this case.
     ///
+    /// @param find_resrv specifies whether the code should search for host
+    ///   reservation. true means that the code will consult HostMgr, false means
+    ///   to skip this check. That is easier to use, but is redundant if the
+    ///   ctx.host_ field is already set. We can't use ctx.host_ == NULL as
+    ///   check, because for cases whithout reservations, the reservation
+    ///   search would be repeated.
+    ///
+    ///
     /// @return Returns renewed lease.
-    Lease6Collection
-    renewLeases6(ClientContext6& ctx);
+    Lease6Collection renewLeases6(ClientContext6& ctx, bool find_resrv = true);
+
+    /// @brief Attempts to find appropriate host reservation.
+    ///
+    /// Attempts to find appropriate host reservation in HostMgr. If found, it
+    /// will be set in ctx.host_.
+    /// @param ctx Client context that contains all necessary information.
+    void findReservation(ClientContext6& ctx) const;
 
 private: