Browse Source

[2592] getLease4(clientid,hwaddr,subnetid) implemented in memfile LeaseMgr

- Patch by David Carlier
Tomek Mrugalski 11 years ago
parent
commit
4c18226299

+ 5 - 0
src/lib/dhcpsrv/dhcpsrv_messages.mes

@@ -204,6 +204,11 @@ A debug message issued when the server is attempting to obtain an IPv6
 lease from the memory file database for a client with the specified IAID
 (Identity Association ID), Subnet ID and DUID (DHCP Unique Identifier).
 
+% DHCPSRV_MEMFILE_GET_CLIENTID_HWADDR_SUBID obtaining IPv4 lease for client ID %1, hardware address %2 and subnet ID %3
+A debug message issued when the server is attempting to obtain an IPv4
+lease from the memory file database for a client with the specified
+client ID, hardware address and subnet ID.
+
 % DHCPSRV_MEMFILE_GET_SUBID_CLIENTID obtaining IPv4 lease for subnet ID %1 and client ID %2
 A debug message issued when the server is attempting to obtain an IPv4
 lease from the memory file database for a client with the specified

+ 31 - 6
src/lib/dhcpsrv/memfile_lease_mgr.cc

@@ -124,11 +124,7 @@ Memfile_LeaseMgr::getLease4(const ClientId& clientid) const {
 
         // client-id is not mandatory in DHCPv4. There can be a lease that does
         // not have a client-id. Dereferencing null pointer would be a bad thing
-        if (!(*lease)->client_id_) {
-            continue;
-        }
-
-        if(*(*lease)->client_id_ == clientid) {
+        if((*lease)->client_id_ && *(*lease)->client_id_ == clientid) {
             collection.push_back((* lease));
         }
     }
@@ -138,7 +134,36 @@ Memfile_LeaseMgr::getLease4(const ClientId& clientid) const {
 
 Lease4Ptr
 Memfile_LeaseMgr::getLease4(const ClientId& client_id,
-                                      SubnetID subnet_id) const {
+                            const HWAddr& hwaddr,
+                            SubnetID subnet_id) const {
+    LOG_DEBUG(dhcpsrv_logger, DHCPSRV_DBG_TRACE_DETAIL,
+              DHCPSRV_MEMFILE_GET_CLIENTID_HWADDR_SUBID).arg(client_id.toText())
+                                                        .arg(hwaddr.toText())
+                                                        .arg(subnet_id);
+
+    // We are going to use index #3 of the multi index container.
+    // We define SearchIndex locally in this function because
+    // currently only this function uses this index.
+    typedef Lease4Storage::nth_index<3>::type SearchIndex;
+    // Get the index.
+    const SearchIndex& idx = storage4_.get<3>();
+    // Try to get the lease using client id, hardware address and subnet id.
+    SearchIndex::const_iterator lease =
+        idx.find(boost::make_tuple(client_id.getClientId(), hwaddr.hwaddr_,
+                                   subnet_id));
+
+    if (lease == idx.end()) {
+        // Lease was not found. Return empty pointer to the caller.
+        return (Lease4Ptr());
+    }
+
+    // Lease was found. Return it to the caller.
+    return (*lease);
+}
+
+Lease4Ptr
+Memfile_LeaseMgr::getLease4(const ClientId& client_id,
+                            SubnetID subnet_id) const {
     LOG_DEBUG(dhcpsrv_logger, DHCPSRV_DBG_TRACE_DETAIL,
               DHCPSRV_MEMFILE_GET_SUBID_CLIENTID).arg(subnet_id)
               .arg(client_id.toText());

+ 44 - 0
src/lib/dhcpsrv/memfile_lease_mgr.h

@@ -107,6 +107,21 @@ public:
     /// @param clientid client identifier
     virtual Lease4Collection getLease4(const ClientId& clientid) const;
 
+    /// @brief Returns IPv4 lease for specified client-id/hwaddr/subnet-id tuple
+    ///
+    /// There can be at most one lease for a given client-id/hwaddr tuple
+    /// in a single pool, so this method with either return a single lease
+    /// or NULL.
+    ///
+    /// @param clientid client identifier
+    /// @param hwaddr hardware address of the client
+    /// @param subnet_id identifier of the subnet that lease must belong to
+    ///
+    /// @return a pointer to the lease (or NULL if a lease is not found)
+    virtual Lease4Ptr getLease4(const ClientId& clientid,
+                                const HWAddr& hwaddr,
+                                SubnetID subnet_id) const;
+
     /// @brief Returns existing IPv4 lease for specified client-id
     ///
     /// There can be at most one lease for a given HW address in a single
@@ -321,6 +336,35 @@ protected:
                     // The subnet id is accessed through the subnet_id_ member.
                     boost::multi_index::member<Lease, uint32_t, &Lease::subnet_id_>
                 >
+            >,
+
+            // Specification of the fourth index starts here.
+            boost::multi_index::ordered_unique<
+                // This is a composite index that uses two values to search for a
+                // lease: client id and subnet id.
+                boost::multi_index::composite_key<
+                    Lease4,
+                    // The client id value is not directly accessible through the
+                    // Lease4 object as it is wrapped with the ClientIdPtr object.
+                    // Therefore we use the KeyFromKeyExtractor class to access
+                    // client id through this cascaded structure. The client id
+                    // is used as an index value.
+                    KeyFromKeyExtractor<
+                        // Specify that the vector holding client id value can be obtained
+                        // from the ClientId object.
+                        boost::multi_index::const_mem_fun<ClientId, std::vector<uint8_t>,
+                                                          &ClientId::getClientId>,
+                        // Specify that the ClientId object (actually pointer to it) can
+                        // be accessed by the client_id_ member of Lease4 class.
+                        boost::multi_index::member<Lease4, ClientIdPtr, &Lease4::client_id_>
+                    >,
+                    // The hardware address is held in the hwaddr_ member of the
+                    // Lease4 object.
+                    boost::multi_index::member<Lease4, std::vector<uint8_t>,
+                                               &Lease4::hwaddr_>,
+                    // The subnet id is accessed through the subnet_id_ member.
+                    boost::multi_index::member<Lease, SubnetID, &Lease::subnet_id_>
+                >
             >
         >
     > Lease4Storage; // Specify the type name for this container.

+ 27 - 2
src/lib/dhcpsrv/tests/memfile_lease_mgr_unittest.cc

@@ -145,6 +145,10 @@ TEST_F(MemfileLeaseMgrTest, getLease4ClientId) {
     ASSERT_EQ(1, returned.size());
     // We should retrieve our lease...
     detailCompareLease(lease, *returned.begin());
+    lease = initializeLease4(straddress4_[2]);
+    returned = lease_mgr->getLease4(*lease->client_id_);
+
+    ASSERT_EQ(0, returned.size());
 }
 
 // Checks that lease4 retrieval client id is null is working
@@ -170,9 +174,8 @@ TEST_F(MemfileLeaseMgrTest, getLease4HWAddr) {
     boost::scoped_ptr<Memfile_LeaseMgr> lease_mgr(new Memfile_LeaseMgr(pmap));
     // Let's initialize two different leases 4 and just add the first ...
     Lease4Ptr leaseA = initializeLease4(straddress4_[5]);
-    Lease4Ptr leaseB = initializeLease4(straddress4_[6]);
     HWAddr hwaddrA(leaseA->hwaddr_, HTYPE_ETHER);
-    HWAddr hwaddrB(leaseB->hwaddr_, HTYPE_ETHER);
+    HWAddr hwaddrB(vector<uint8_t>(6, 0x80), HTYPE_ETHER);
 
     EXPECT_TRUE(lease_mgr->addLease(leaseA));
 
@@ -185,4 +188,26 @@ TEST_F(MemfileLeaseMgrTest, getLease4HWAddr) {
     ASSERT_EQ(1, returned.size());
 }
 
+// Checks lease4 retrieval with clientId, HWAddr and subnet_id
+TEST_F(MemfileLeaseMgrTest, getLease4ClientIdHWAddrSubnetId) {
+    const LeaseMgr::ParameterMap pmap;
+    boost::scoped_ptr<Memfile_LeaseMgr> lease_mgr(new Memfile_LeaseMgr(pmap));
+
+    Lease4Ptr leaseA = initializeLease4(straddress4_[4]);
+    Lease4Ptr leaseB = initializeLease4(straddress4_[5]);
+    HWAddr hwaddrA(leaseA->hwaddr_, HTYPE_ETHER);
+    HWAddr hwaddrB(leaseB->hwaddr_, HTYPE_ETHER);
+    EXPECT_TRUE(lease_mgr->addLease(leaseA));
+    // First case we should retrieve our lease
+    Lease4Ptr lease = lease_mgr->getLease4(*leaseA->client_id_, hwaddrA, leaseA->subnet_id_);
+    detailCompareLease(lease, leaseA);
+    lease = lease_mgr->getLease4(*leaseB->client_id_, hwaddrA, leaseA->subnet_id_);
+    detailCompareLease(lease, leaseA);
+    // But not the folowing, with different  hwaddr and subnet
+    lease = lease_mgr->getLease4(*leaseA->client_id_, hwaddrB, leaseA->subnet_id_);
+    EXPECT_TRUE(lease == Lease4Ptr());
+    lease = lease_mgr->getLease4(*leaseA->client_id_, hwaddrA, leaseB->subnet_id_);
+    EXPECT_TRUE(lease == Lease4Ptr());
+}
+
 }; // end of anonymous namespace