]> git.ipfire.org Git - thirdparty/kea.git/commitdiff
[#4547] Checkpoint
authorFrancis Dupont <fdupont@isc.org>
Tue, 7 Jul 2026 18:32:54 +0000 (20:32 +0200)
committerFrancis Dupont <fdupont@isc.org>
Thu, 9 Jul 2026 16:53:05 +0000 (18:53 +0200)
src/bin/dhcp4/dhcp4_messages.cc
src/bin/dhcp4/dhcp4_messages.h
src/bin/dhcp4/dhcp4_messages.mes
src/bin/dhcp4/dhcp4_srv.cc
src/bin/dhcp4/tests/release_unittest.cc

index 54cf029d2e316798261a61977fb7e8166a29e789..cfffda725488d0654e20db328e6df191595e5b07 100644 (file)
@@ -151,6 +151,7 @@ extern const isc::log::MessageID DHCP4_RECLAIM_EXPIRED_LEASES_FAIL = "DHCP4_RECL
 extern const isc::log::MessageID DHCP4_RECLAIM_EXPIRED_LEASES_SKIPPED = "DHCP4_RECLAIM_EXPIRED_LEASES_SKIPPED";
 extern const isc::log::MessageID DHCP4_RECOVERED_STASHED_RELAY_AGENT_INFO = "DHCP4_RECOVERED_STASHED_RELAY_AGENT_INFO";
 extern const isc::log::MessageID DHCP4_RELEASE = "DHCP4_RELEASE";
+extern const isc::log::MessageID DHCP4_RELEASE_ALREADY_IN_RELEASED_STATE = "DHCP4_RELEASE_ALREADY_IN_RELEASED_STATE";
 extern const isc::log::MessageID DHCP4_RELEASE_DELETED = "DHCP4_RELEASE_DELETED";
 extern const isc::log::MessageID DHCP4_RELEASE_EXCEPTION = "DHCP4_RELEASE_EXCEPTION";
 extern const isc::log::MessageID DHCP4_RELEASE_EXPIRED = "DHCP4_RELEASE_EXPIRED";
@@ -339,6 +340,7 @@ const char* values[] = {
     "DHCP4_RECLAIM_EXPIRED_LEASES_SKIPPED", "dhcp6 service is currently disabled. Try again in %1 seconds.",
     "DHCP4_RECOVERED_STASHED_RELAY_AGENT_INFO", "recovered for query %1 relay agent option from lease %2: %3",
     "DHCP4_RELEASE", "%1: address %2 was released properly.",
+    "DHCP4_RELEASE_ALREADY_IN_RELEASED_STATE", "%1: client is trying to release the lease %2 which is already in the RELEASED state",
     "DHCP4_RELEASE_DELETED", "%1: address %2 was deleted on release.",
     "DHCP4_RELEASE_EXCEPTION", "%1: while trying to release address %2 an exception occurred: %3",
     "DHCP4_RELEASE_EXPIRED", "%1: address %2 expired on release.",
index d9142d7a9d8cffefe9d5b1bd741780c4f3f2bc1f..9e1d9c22931d81c1e0c5ca46313dd2b7b53f11d4 100644 (file)
@@ -152,6 +152,7 @@ extern const isc::log::MessageID DHCP4_RECLAIM_EXPIRED_LEASES_FAIL;
 extern const isc::log::MessageID DHCP4_RECLAIM_EXPIRED_LEASES_SKIPPED;
 extern const isc::log::MessageID DHCP4_RECOVERED_STASHED_RELAY_AGENT_INFO;
 extern const isc::log::MessageID DHCP4_RELEASE;
+extern const isc::log::MessageID DHCP4_RELEASE_ALREADY_IN_RELEASED_STATE;
 extern const isc::log::MessageID DHCP4_RELEASE_DELETED;
 extern const isc::log::MessageID DHCP4_RELEASE_EXCEPTION;
 extern const isc::log::MessageID DHCP4_RELEASE_EXPIRED;
index 11d5f91781fe98ae1fb81b44d997dae03c6f372c..7dd7f3c6e059be9bc6ebecf34a390a98d015473b 100644 (file)
@@ -980,6 +980,14 @@ is a normal operation during client shutdown. The first argument includes
 the client and transaction identification information. The second argument
 includes the released IPv4 address.
 
+% DHCP4_RELEASE_ALREADY_IN_RELEASED_STATE %1: client is trying to release the lease %2 which is already in the RELEASED state
+Logged at debug log level 50.
+This debug message is issued when a client is trying to release the
+lease which is already in the RELEASED state i.e. kept for the client
+by the lease affinity feature. The first argument includes the client
+and the transaction identification information. The second argument
+specifies the leased address.
+
 % DHCP4_RELEASE_DELETED %1: address %2 was deleted on release.
 This informational message indicates that an address was deleted on release. It
 is a normal operation during client shutdown. The first argument includes the
index 4c1dab0ce3cdedaab9871f40ddd17c1cc68012e5..e0849df7bbefda1b48bc4ef0c4fcf1a74e07c9bf 100644 (file)
@@ -4174,6 +4174,14 @@ Dhcpv4Srv::processRelease(Pkt4Ptr& release, AllocEngine::ClientContext4Ptr& cont
             return;
         }
 
+        if (lease->state_ == Lease4::STATE_RELEASED) {
+            LOG_DEBUG(lease4_logger, DBG_DHCP4_DETAIL,
+                      DHCP4_RELEASE_ALREADY_IN_RELEASED_STATE)
+                .arg(release->getLabel())
+                .arg(release->getCiaddr().toText());
+            return;
+        }
+
         bool skip = false;
 
         // Execute all callouts registered for lease4_release
index c56487876bba241c125a2d6cfc9214f22aa79138..251a977679879747d97100bdf416ff819b6498ed 100644 (file)
@@ -512,4 +512,51 @@ TEST_F(ReleaseTest, releaseAndReclaim) {
     ASSERT_EQ(count, after);
 }
 
+// This test checks that to release a second time just logs when lease
+// affinity is enabled. Specialized from acquireAndRelease code.
+TEST_F(ReleaseTest, releaseAlreadyReleased) {
+    CfgMgr::instance().clear();
+    Dhcp4Client client(srv_, Dhcp4Client::SELECTING);
+    configure(RELEASE_CONFIGS[0], *client.getServer(), true, true, true, false,
+              LEASE_AFFINITY_ENABLED);
+    // Explicitly set the client id.
+    client.includeClientId("12:14");
+    // Explicitly set the HW address.
+    client.setHWAddress("01:02:03:04:05:06");
+    // Perform 4-way exchange to obtain a new lease.
+    acquireLease(client);
+
+    std::stringstream name;
+
+    // Let's get the subnet-id and generate statistics name out of it
+    const Subnet4Collection* subnets =
+        CfgMgr::instance().getCurrentCfg()->getCfgSubnets4()->getAll();
+    ASSERT_EQ(1U, subnets->size());
+    name << "subnet[" << (*subnets->begin())->getID() << "].assigned-addresses";
+
+    ObservationPtr assigned_cnt = StatsMgr::instance().getObservation(name.str());
+    ASSERT_TRUE(assigned_cnt);
+    uint64_t before = assigned_cnt->getInteger().first;
+
+    // Remember the acquired address.
+    IOAddress leased_address = client.config_.lease_.addr_;
+
+    // Send the release.
+    ASSERT_NO_THROW(client.doRelease());
+
+    // Restore the lease and send the release a second time.
+    client.createLease(leased_address, 0);
+    ASSERT_NO_THROW(client.doRelease());
+
+    assigned_cnt = StatsMgr::instance().getObservation(name.str());
+    ASSERT_TRUE(assigned_cnt);
+    uint64_t after = assigned_cnt->getInteger().first;
+
+    // assigned stat is decremented once.
+    EXPECT_EQ(before, after + 1);
+
+    // The alredy in RELEASED state is logged.
+    EXPECT_EQ(1U, countFile("DHCP4_RELEASE_ALREADY_IN_RELEASED_STATE"));
+}
+
 } // end of anonymous namespace