]> git.ipfire.org Git - thirdparty/kea.git/commitdiff
[#226] Added getRemaining
authorFrancis Dupont <fdupont@isc.org>
Fri, 8 Aug 2025 13:55:35 +0000 (15:55 +0200)
committerFrancis Dupont <fdupont@isc.org>
Wed, 20 Aug 2025 15:39:15 +0000 (17:39 +0200)
src/lib/dhcpsrv/alloc_engine.cc
src/lib/dhcpsrv/alloc_engine.h
src/lib/dhcpsrv/tests/alloc_engine4_unittest.cc
src/lib/dhcpsrv/tests/alloc_engine6_unittest.cc

index 92d456d7943de9b286dbc9f02fa3e94b449ffbbd..8cb6e39b600d18a62e2cd22e45e5be023806c7ff 100644 (file)
@@ -2098,6 +2098,31 @@ Lease6Ptr AllocEngine::createLease6(ClientContext6& ctx,
     }
 }
 
+void
+AllocEngine::getRemaining(const Lease6Ptr& lease, uint32_t& valid,
+                          uint32_t& preferred) {
+    valid = 0;
+    preferred = 0;
+    if (!lease || (lease->state_ != Lease::STATE_DEFAULT)) {
+        return;
+    }
+    time_t now = time(0);
+    // Refuse time not going forward.
+    if (lease->cltt_ > now) {
+        return;
+    }
+    uint32_t age = now - lease->cltt_;
+    // Already expired.
+    if (age >= lease->valid_lft_) {
+        return;
+    }
+    valid = lease->valid_lft_ - age;
+    if (age >= lease->preferred_lft_) {
+        return;
+    }
+    preferred = lease->preferred_lft_ - age;
+}
+
 Lease6Collection
 AllocEngine::renewLeases6(ClientContext6& ctx) {
     try {
@@ -4457,6 +4482,30 @@ AllocEngine::createLease4(const ClientContext4& ctx, const IOAddress& addr,
     }
 }
 
+void
+AllocEngine::getRemaining(const Lease4Ptr& lease, uint32_t& valid) {
+    valid = 0;
+    if (!lease || (lease->state_ != Lease::STATE_DEFAULT)) {
+        return;
+    }
+    // Always remain infinite lifetime leases.
+    if (lease->valid_lft_ == Lease::INFINITY_LFT) {
+        valid = Lease::INFINITY_LFT;
+        return;
+    }
+    time_t now = time(0);
+    // Refuse time not going forward.
+    if (lease->cltt_ > now) {
+        return;
+    }
+    uint32_t age = now - lease->cltt_;
+    // Already expired.
+    if (age >= lease->valid_lft_) {
+        return;
+    }
+    valid = lease->valid_lft_ - age;
+}
+
 Lease4Ptr
 AllocEngine::renewLease4(const Lease4Ptr& lease,
                          AllocEngine::ClientContext4& ctx) {
index de0ce5d3453e08490d2374dace1fd49cb7752e79..1e32036a5a2239a43577aa3ccf4f9694e6082919 100644 (file)
@@ -1555,6 +1555,20 @@ public:
     /// @return unsigned integer value of the offer lifetime to use.
     static uint32_t getOfferLft(const ClientContext4& ctx,
                                 bool only_on_discover = true);
+    /// @brief Set remaining valid life time.
+    ///
+    /// @param lease A pointer to the lease.
+    /// @param [out] valid The remaining valid life time or 0.
+    static void getRemaining(const Lease4Ptr& lease, uint32_t& valid);
+
+    /// @brief Set remaining valid and preferred life times.
+    ///
+    /// @param lease A pointer to the lease.
+    /// @param [out] valid The remaining valid life time or 0.
+    /// @param [out] preferred The remaining preferred life time or 0.
+    static void getRemaining(const Lease6Ptr& lease, uint32_t& valid,
+                             uint32_t& preferred);
+
 private:
 
     /// @brief Offers the lease.
index a58c39ccd58f08974120bd71432590ac10668fb5..560d6cff3baa4667ad4885f596d1c23172bae087 100644 (file)
@@ -4850,6 +4850,52 @@ TEST_F(AllocEngine4Test, getValidLft4) {
     }
 }
 
+// Verifies that AllocEngine::getRemaining retuns the remaining lifetime value.
+TEST_F(AllocEngine4Test, getRemaining) {
+    // No Lease.
+    uint32_t valid(1);
+    Lease4Ptr lease;
+    AllocEngine::getRemaining(lease, valid);
+    EXPECT_EQ(0, valid);
+
+    // Unexpected state.
+    valid = 1;
+    uint8_t hwaddr_data[] = { 0, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe };
+    HWAddrPtr hwaddr(new HWAddr(hwaddr_data, sizeof(hwaddr_data), HTYPE_ETHER));
+    uint8_t clientid[] = { 8, 7, 6, 5, 4, 3, 2, 1 };
+    time_t now = time(0);
+    lease.reset(new Lease4(IOAddress("192.0.2.100"), hwaddr, clientid,
+                           sizeof(clientid), 100, now, 1));
+    lease->state_ = Lease::STATE_DECLINED;
+    AllocEngine::getRemaining(lease, valid);
+    EXPECT_EQ(0, valid);
+
+    // Infinite lifetime.
+    lease->state_ = Lease::STATE_DEFAULT;
+    uint32_t infinity_lft = Lease::INFINITY_LFT;
+    lease->valid_lft_ = lease->current_valid_lft_ = infinity_lft;
+    AllocEngine::getRemaining(lease, valid);
+    EXPECT_EQ(infinity_lft, valid);
+
+    // Time going backward.
+    lease->cltt_ = lease->current_cltt_ = now + 100;
+    lease->valid_lft_ = lease->current_valid_lft_ = 50;
+    AllocEngine::getRemaining(lease, valid);
+    EXPECT_EQ(0, valid);
+
+    // Already expired.
+    valid = 1;
+    lease->cltt_ = lease->current_cltt_ = now - 100;
+    AllocEngine::getRemaining(lease, valid);
+    EXPECT_EQ(0, valid);
+
+    // Valid case.
+    now = time(0);
+    lease->cltt_ = lease->current_cltt_ = now - 10;
+    AllocEngine::getRemaining(lease, valid);
+    EXPECT_NEAR(40, valid, 1);
+}
+
 // Verifies that AllocEngine::getValidLft(ctx4) returns the appropriate
 // lifetime value based on the context content.
 TEST_F(AllocEngine4Test, getTemplateClassValidLft4) {
index 24bd92174d41a729ed495e82b621ff58fb6f4271..1bc3739c2c800a7f1237d7c17c12317e5753663a 100644 (file)
@@ -6027,6 +6027,62 @@ TEST_F(AllocEngine6Test, getTemplateClassValidLifetime) {
     }
 }
 
+// Verifies that AllocEngine::getRemaining retuns the remaining lifetime values.
+TEST_F(AllocEngine6Test, getRemaining) {
+    // No Lease.
+    uint32_t valid(1);
+    uint32_t preferred(1);
+    Lease6Ptr lease;
+    AllocEngine::getRemaining(lease, valid, preferred);
+    EXPECT_EQ(0, valid);
+    EXPECT_EQ(0, preferred);
+
+    // Unexpected state.
+    valid = 1;
+    preferred = 1;
+    DuidPtr duid(new DUID(vector<uint8_t>(12, 0xff)));
+    const uint32_t  iaid = 3568;
+    time_t now = time(0);
+    lease.reset(new Lease6(Lease::TYPE_NA, IOAddress("2001:db8:1::1"), duid,
+                           iaid, 30, 50, 1));
+    lease->state_ = Lease::STATE_DECLINED;
+    AllocEngine::getRemaining(lease, valid, preferred);
+    EXPECT_EQ(0, valid);
+    EXPECT_EQ(0, preferred);
+
+    // Time going backward.
+    valid = 1;
+    preferred = 1;
+    lease->state_ = Lease::STATE_DEFAULT;
+    lease->cltt_ = lease->current_cltt_ = now + 100;
+    lease->valid_lft_ = lease->current_valid_lft_ = 50;
+    AllocEngine::getRemaining(lease, valid, preferred);
+    EXPECT_EQ(0, valid);
+    EXPECT_EQ(0, preferred);
+
+    // Already expired.
+    valid = 1;
+    preferred = 1;
+    lease->cltt_ = lease->current_cltt_ = now - 100;
+    AllocEngine::getRemaining(lease, valid, preferred);
+    EXPECT_EQ(0, valid);
+    EXPECT_EQ(0, preferred);
+
+    // Valid case.
+    now = time(0);
+    lease->cltt_ = lease->current_cltt_ = now - 10;
+    AllocEngine::getRemaining(lease, valid, preferred);
+    EXPECT_NEAR(40, valid, 1);
+    EXPECT_NEAR(20, preferred, 1);
+
+    // No longer preferred.
+    now = time(0);
+    lease->cltt_ = lease->current_cltt_ = now - 40;
+    AllocEngine::getRemaining(lease, valid, preferred);
+    EXPECT_NEAR(10, valid, 1);
+    EXPECT_EQ(0, preferred);
+}
+
 // Verifies that AllocEngine::getLifetimes6() returns the appropriate
 // preferred lifetime value based on the context content.
 TEST_F(AllocEngine6Test, getPreferredLifetime) {