]> git.ipfire.org Git - thirdparty/kea.git/commitdiff
[#226] Finished v6 code
authorFrancis Dupont <fdupont@isc.org>
Wed, 13 Aug 2025 17:00:33 +0000 (19:00 +0200)
committerFrancis Dupont <fdupont@isc.org>
Wed, 20 Aug 2025 15:39:16 +0000 (17:39 +0200)
src/bin/dhcp6/tests/flq_unittest.cc
src/lib/dhcpsrv/alloc_engine.cc
src/lib/dhcpsrv/alloc_engine.h

index 798634f23543ec5e8df021780ab015b1b5b475fc..41ad2a7cb77e13e6185ea7275a49803e3ae88c5c 100644 (file)
@@ -27,8 +27,8 @@ std::string FLQ_CONFIG =
     "\"preferred-lifetime\": 200,"
     "\"max-preferred-lifetime\": 300,"
     "\"min-valid-lifetime\": 400,"
-    "\"valid-lifetime\": 500,"
-    "\"max-valid-lifetime\": 600,"
+    "\"valid-lifetime\": 600,"
+    "\"max-valid-lifetime\": 700,"
     "\"rebind-timer\": 250,"
     "\"renew-timer\": 250,"
     "\"adaptive-lease-time-threshold\": .5,"
@@ -99,8 +99,8 @@ TEST_F(FLQTest, empty) {
     // Preferred lifetime should be the config preferred-lifetime (200).
     EXPECT_EQ(200, lease->preferred_lft_);
 
-    // Valid lifetime should be the config valid-lifetime (500).
-    EXPECT_EQ(500, lease->valid_lft_);
+    // Valid lifetime should be the config valid-lifetime (600).
+    EXPECT_EQ(600, lease->valid_lft_);
 }
 
 // Test allocation with almost full pool.
@@ -247,190 +247,273 @@ TEST_F(FLQTest, reclaimed) {
     // Valid lifetime should be the config min-valid-lifetime (400).
     EXPECT_EQ(400, lease->valid_lft_);
 }
-#if 0
+
 // Test renewal with almost empty pool.
 TEST_F(FLQTest, renew) {
-    Dhcp6Client client(srv_, Dhcp6Client::SELECTING);
+    Dhcp6Client client(srv_);
 
     // Configure DHCP server.
     configure(FLQ_CONFIG, *client.getServer());
 
-    // Obtain a lease from the server using the 4-way exchange.
-    boost::shared_ptr<IOAddress> hint(new IOAddress("10.0.0.14"));
-    ASSERT_NO_THROW(client.doDORA(hint));
+    // Perform 4-way exchange with the server requesting the last prefix.
+    client.requestPrefix(1, 51, IOAddress("2001:db8:1:e000::"));
+    ASSERT_NO_THROW(client.doSARR());
 
-    // Make sure that the server responded.
-    Pkt6Ptr resp = client.getContext().response_;
-    ASSERT_TRUE(resp);
+    // Server should have assigned a prefix.
+    ASSERT_EQ(1, client.getLeaseNum());
+    Lease6Ptr lease = checkLease(client.getLease(0));
+    ASSERT_TRUE(lease);
 
-    // Make sure that the server has responded with DHCPACK.
-    ASSERT_EQ(DHCPACK, static_cast<int>(resp->getType()));
+    // Make sure that the client has got the requested prefix.
+    EXPECT_EQ("2001:db8:1:e000::", lease->addr_.toText());
+    EXPECT_EQ(51, lease->prefixlen_);
 
-    // Make sure that the client has got the requested address.
-    EXPECT_EQ(*hint, resp->getYiaddr());
+    // Preferred lifetime should be the config preferred-lifetime (200).
+    EXPECT_EQ(200, lease->preferred_lft_);
 
-    // Valid lifetime should be the valid-lifetime parameter value (200).
-    OptionUint32Ptr opt = boost::dynamic_pointer_cast<
-        OptionUint32>(resp->getOption(DHO_DHCP_LEASE_TIME));
-    ASSERT_TRUE(opt);
-    EXPECT_EQ(200, opt->getValue());
+    // Valid lifetime should be the config valid-lifetime (600).
+    EXPECT_EQ(600, lease->valid_lft_);
 
     // Age the lease.
+    lease->cltt_ -= 1000;
+    lease->current_cltt_ -= 1000;
     auto& lease_mgr = LeaseMgrFactory::instance();
-    Lease6Ptr lease = lease_mgr.getLease6(*hint);
-    ASSERT_TRUE(lease);
-    lease->cltt_ -= 150;
-    lease->current_cltt_ -= 150;
     EXPECT_NO_THROW(lease_mgr.updateLease6(lease));
 
-    // Let's transition the client to Renewing state.
-    client.setState(Dhcp6Client::RENEWING);
+    // Send the renew message to the server.
+    ASSERT_NO_THROW(client.doRenew());
+
+    // Server should have renewed the prefix.
+    ASSERT_EQ(1, client.getLeaseNum());
+    Lease6Ptr renewed = checkLease(client.getLease(0));
+    ASSERT_TRUE(renewed);
 
-    // Set the unicast destination address to indicate that it is a renewal.
-    client.setDestAddress(IOAddress("10.0.0.1"));
-    ASSERT_NO_THROW(client.doRequest());
+    // Make sure that the client has got the same prefix.
+    EXPECT_EQ(lease->addr_, renewed->addr_);
+    EXPECT_EQ(lease->prefixlen_, renewed->prefixlen_);
 
-    // Make sure that renewal was ACKed.
-    resp = client.getContext().response_;
-    ASSERT_TRUE(resp);
-    ASSERT_EQ(DHCPACK, static_cast<int>(resp->getType()));
+    // Check the lease was updated.
+    EXPECT_NEAR(lease->cltt_ + 1000, renewed->cltt_, 2);
 
-    // Make sure that the client renewed the requested address.
-    EXPECT_EQ(*hint, resp->getYiaddr());
+    // Preferred lifetime should be the config preferred-lifetime (200).
+    EXPECT_EQ(200, renewed->preferred_lft_);
 
-    // Valid lifetime should be the valid-lifetime parameter value (200).
-    opt = boost::dynamic_pointer_cast<OptionUint32>(resp->getOption(DHO_DHCP_LEASE_TIME));
-    ASSERT_TRUE(opt);
-    EXPECT_EQ(200, opt->getValue());
+    // Valid lifetime should be the config valid-lifetime (600).
+    EXPECT_EQ(600, renewed->valid_lft_);
 }
 
 // Test renewal with full pool.
 TEST_F(FLQTest, renewFull) {
-    Dhcp6Client client(srv_, Dhcp6Client::SELECTING);
+    Dhcp6Client client(srv_);
 
     // Configure DHCP server.
     configure(FLQ_CONFIG, *client.getServer());
 
-    // Obtain a lease from the server using the 4-way exchange.
-    boost::shared_ptr<IOAddress> hint(new IOAddress("10.0.0.14"));
-    ASSERT_NO_THROW(client.doDORA(hint));
+    // Perform 4-way exchange with the server requesting the last prefix.
+    client.requestPrefix(1, 51, IOAddress("2001:db8:1:e000::"));
+    ASSERT_NO_THROW(client.doSARR());
 
-    // Make sure that the server responded.
-    Pkt6Ptr resp = client.getContext().response_;
-    ASSERT_TRUE(resp);
+    // Server should have assigned a prefix.
+    ASSERT_EQ(1, client.getLeaseNum());
+    Lease6Ptr lease = checkLease(client.getLease(0));
+    ASSERT_TRUE(lease);
 
-    // Make sure that the server has responded with DHCPACK.
-    ASSERT_EQ(DHCPACK, static_cast<int>(resp->getType()));
+    // Make sure that the client has got the requested prefix.
+    EXPECT_EQ("2001:db8:1:e000::", lease->addr_.toText());
+    EXPECT_EQ(51, lease->prefixlen_);
 
-    // Make sure that the client has got the requested address.
-    EXPECT_EQ(*hint, resp->getYiaddr());
+    // Preferred lifetime should be the config preferred-lifetime (200).
+    EXPECT_EQ(200, lease->preferred_lft_);
 
-    // Valid lifetime should be the valid-lifetime parameter value (200).
-    OptionUint32Ptr opt = boost::dynamic_pointer_cast<
-        OptionUint32>(resp->getOption(DHO_DHCP_LEASE_TIME));
-    ASSERT_TRUE(opt);
-    EXPECT_EQ(200, opt->getValue());
+    // Valid lifetime should be the config valid-lifetime (600).
+    EXPECT_EQ(600, lease->valid_lft_);
 
-    // Age the lease.
+    // Create leases for the first prefixes.
     auto& lease_mgr = LeaseMgrFactory::instance();
-    Lease6Ptr lease = lease_mgr.getLease6(*hint);
-    ASSERT_TRUE(lease);
-    lease->cltt_ -= 150;
-    lease->current_cltt_ -= 150;
-    EXPECT_NO_THROW(lease_mgr.updateLease6(lease));
-
-    // Create leases for the first addresses.
-    auto lease1 = createLease6(IOAddress("10.0.0.11"), 1);
+    auto lease0 = createLease6(IOAddress("2001:db8:1::"), 1);
+    EXPECT_TRUE(lease_mgr.addLease(lease0));
+    auto lease1 = createLease6(IOAddress("2001:db8:1:2000::"), 2);
     EXPECT_TRUE(lease_mgr.addLease(lease1));
-    auto lease2 = createLease6(IOAddress("10.0.0.12"), 2);
+    auto lease2 = createLease6(IOAddress("2001:db8:1:4000::"), 3);
     EXPECT_TRUE(lease_mgr.addLease(lease2));
-    auto lease3 = createLease6(IOAddress("10.0.0.13"), 3);
+    auto lease3 = createLease6(IOAddress("2001:db8:1:6000::"), 4);
     EXPECT_TRUE(lease_mgr.addLease(lease3));
+    auto lease4 = createLease6(IOAddress("2001:db8:1:8000::"), 5);
+    EXPECT_TRUE(lease_mgr.addLease(lease4));
+    auto lease5 = createLease6(IOAddress("2001:db8:1:a000::"), 6);
+    EXPECT_TRUE(lease_mgr.addLease(lease5));
+    auto lease6 = createLease6(IOAddress("2001:db8:1:c000::"), 7);
+    EXPECT_TRUE(lease_mgr.addLease(lease6));
+    auto lease7 = createLease6(IOAddress("2001:db8:1:e000::"), 8);
+
+    // Age the lease.
+    lease->cltt_ -= 1000;
+    lease->current_cltt_ -= 1000;
+    EXPECT_NO_THROW(lease_mgr.updateLease6(lease));
 
-    // Let's transition the client to Renewing state.
-    client.setState(Dhcp6Client::RENEWING);
+    // Send the renew message to the server.
+    ASSERT_NO_THROW(client.doRenew());
 
-    // Set the unicast destination address to indicate that it is a renewal.
-    client.setDestAddress(IOAddress("10.0.0.1"));
-    ASSERT_NO_THROW(client.doRequest());
+    // Server should have renewed the prefix.
+    ASSERT_EQ(1, client.getLeaseNum());
+    Lease6Ptr renewed = checkLease(client.getLease(0));
+    ASSERT_TRUE(renewed);
 
-    // Make sure that renewal was ACKed.
-    resp = client.getContext().response_;
-    ASSERT_TRUE(resp);
-    ASSERT_EQ(DHCPACK, static_cast<int>(resp->getType()));
+    // Make sure that the client has got the same prefix.
+    EXPECT_EQ(lease->addr_, renewed->addr_);
+    EXPECT_EQ(lease->prefixlen_, renewed->prefixlen_);
 
-    // Make sure that the client renewed the requested address.
-    EXPECT_EQ(*hint, resp->getYiaddr());
+    // Check the lease was updated.
+    EXPECT_NEAR(lease->cltt_ + 1000, renewed->cltt_, 2);
 
-    // Valid lifetime should be the min-valid-lifetime parameter value (100).
-    opt = boost::dynamic_pointer_cast<OptionUint32>(resp->getOption(DHO_DHCP_LEASE_TIME));
-    ASSERT_TRUE(opt);
-    EXPECT_EQ(100, opt->getValue());
+    // Preferred lifetime should be the config min-preferred-lifetime (100).
+    EXPECT_EQ(100, renewed->preferred_lft_);
+
+    // Valid lifetime should be the config min-valid-lifetime (400).
+    EXPECT_EQ(400, renewed->valid_lft_);
 }
 
-// Test renewal with full pool but remaining lifetime greater than minimal.
+// Test renewal with full pool but remaining lifetimes greater than minimal.
 TEST_F(FLQTest, renewRemaining) {
-    Dhcp6Client client(srv_, Dhcp6Client::SELECTING);
+    Dhcp6Client client(srv_);
 
     // Configure DHCP server.
     configure(FLQ_CONFIG, *client.getServer());
 
-    // Obtain a lease from the server using the 4-way exchange.
-    boost::shared_ptr<IOAddress> hint(new IOAddress("10.0.0.14"));
-    ASSERT_NO_THROW(client.doDORA(hint));
+    // Perform 4-way exchange with the server requesting the last prefix.
+    client.requestPrefix(1, 51, IOAddress("2001:db8:1:e000::"));
+    ASSERT_NO_THROW(client.doSARR());
 
-    // Make sure that the server responded.
-    Pkt6Ptr resp = client.getContext().response_;
-    ASSERT_TRUE(resp);
+    // Server should have assigned a prefix.
+    ASSERT_EQ(1, client.getLeaseNum());
+    Lease6Ptr lease = checkLease(client.getLease(0));
+    ASSERT_TRUE(lease);
 
-    // Make sure that the server has responded with DHCPACK.
-    ASSERT_EQ(DHCPACK, static_cast<int>(resp->getType()));
+    // Make sure that the client has got the requested prefix.
+    EXPECT_EQ("2001:db8:1:e000::", lease->addr_.toText());
+    EXPECT_EQ(51, lease->prefixlen_);
 
-    // Make sure that the client has got the requested address.
-    EXPECT_EQ(*hint, resp->getYiaddr());
+    // Preferred lifetime should be the config preferred-lifetime (200).
+    EXPECT_EQ(200, lease->preferred_lft_);
 
-    // Valid lifetime should be the valid-lifetime parameter value (200).
-    OptionUint32Ptr opt = boost::dynamic_pointer_cast<
-        OptionUint32>(resp->getOption(DHO_DHCP_LEASE_TIME));
-    ASSERT_TRUE(opt);
-    EXPECT_EQ(200, opt->getValue());
+    // Valid lifetime should be the config valid-lifetime (600).
+    EXPECT_EQ(600, lease->valid_lft_);
 
-    // Age the lease but only by 50 seconds.
+    // Create leases for the first prefixes.
     auto& lease_mgr = LeaseMgrFactory::instance();
-    Lease6Ptr lease = lease_mgr.getLease6(*hint);
-    ASSERT_TRUE(lease);
+    auto lease0 = createLease6(IOAddress("2001:db8:1::"), 1);
+    EXPECT_TRUE(lease_mgr.addLease(lease0));
+    auto lease1 = createLease6(IOAddress("2001:db8:1:2000::"), 2);
+    EXPECT_TRUE(lease_mgr.addLease(lease1));
+    auto lease2 = createLease6(IOAddress("2001:db8:1:4000::"), 3);
+    EXPECT_TRUE(lease_mgr.addLease(lease2));
+    auto lease3 = createLease6(IOAddress("2001:db8:1:6000::"), 4);
+    EXPECT_TRUE(lease_mgr.addLease(lease3));
+    auto lease4 = createLease6(IOAddress("2001:db8:1:8000::"), 5);
+    EXPECT_TRUE(lease_mgr.addLease(lease4));
+    auto lease5 = createLease6(IOAddress("2001:db8:1:a000::"), 6);
+    EXPECT_TRUE(lease_mgr.addLease(lease5));
+    auto lease6 = createLease6(IOAddress("2001:db8:1:c000::"), 7);
+    EXPECT_TRUE(lease_mgr.addLease(lease6));
+    auto lease7 = createLease6(IOAddress("2001:db8:1:e000::"), 8);
+
+    // Age the lease but only by 50 seconds.
     lease->cltt_ -= 50;
     lease->current_cltt_ -= 50;
     EXPECT_NO_THROW(lease_mgr.updateLease6(lease));
 
-    // Create leases for the first addresses.
-    auto lease1 = createLease6(IOAddress("10.0.0.11"), 1);
+    // Send the renew message to the server.
+    ASSERT_NO_THROW(client.doRenew());
+
+    // Server should have renewed the prefix.
+    ASSERT_EQ(1, client.getLeaseNum());
+    Lease6Ptr renewed = checkLease(client.getLease(0));
+    ASSERT_TRUE(renewed);
+
+    // Make sure that the client has got the same prefix.
+    EXPECT_EQ(lease->addr_, renewed->addr_);
+    EXPECT_EQ(lease->prefixlen_, renewed->prefixlen_);
+
+    // Check the lease was updated.
+    EXPECT_NEAR(lease->cltt_ + 50, renewed->cltt_, 2);
+
+    // Preferred lifetime should be the remaining lifetime so ~150.
+    EXPECT_NEAR(150, renewed->preferred_lft_, 2);
+
+    // Valid lifetime should be the remaining lifetime so ~550
+    EXPECT_NEAR(550, renewed->valid_lft_, 2);
+}
+
+// Test renewal with full pool but remaining valid lifetime only greater
+// than minimal.
+TEST_F(FLQTest, renewRemainingValid) {
+    Dhcp6Client client(srv_);
+
+    // Configure DHCP server.
+    configure(FLQ_CONFIG, *client.getServer());
+
+    // Perform 4-way exchange with the server requesting the last prefix.
+    client.requestPrefix(1, 51, IOAddress("2001:db8:1:e000::"));
+    ASSERT_NO_THROW(client.doSARR());
+
+    // Server should have assigned a prefix.
+    ASSERT_EQ(1, client.getLeaseNum());
+    Lease6Ptr lease = checkLease(client.getLease(0));
+    ASSERT_TRUE(lease);
+
+    // Make sure that the client has got the requested prefix.
+    EXPECT_EQ("2001:db8:1:e000::", lease->addr_.toText());
+    EXPECT_EQ(51, lease->prefixlen_);
+
+    // Preferred lifetime should be the config preferred-lifetime (200).
+    EXPECT_EQ(200, lease->preferred_lft_);
+
+    // Valid lifetime should be the config valid-lifetime (600).
+    EXPECT_EQ(600, lease->valid_lft_);
+
+    // Create leases for the first prefixes.
+    auto& lease_mgr = LeaseMgrFactory::instance();
+    auto lease0 = createLease6(IOAddress("2001:db8:1::"), 1);
+    EXPECT_TRUE(lease_mgr.addLease(lease0));
+    auto lease1 = createLease6(IOAddress("2001:db8:1:2000::"), 2);
     EXPECT_TRUE(lease_mgr.addLease(lease1));
-    auto lease2 = createLease6(IOAddress("10.0.0.12"), 2);
+    auto lease2 = createLease6(IOAddress("2001:db8:1:4000::"), 3);
     EXPECT_TRUE(lease_mgr.addLease(lease2));
-    auto lease3 = createLease6(IOAddress("10.0.0.13"), 3);
+    auto lease3 = createLease6(IOAddress("2001:db8:1:6000::"), 4);
     EXPECT_TRUE(lease_mgr.addLease(lease3));
+    auto lease4 = createLease6(IOAddress("2001:db8:1:8000::"), 5);
+    EXPECT_TRUE(lease_mgr.addLease(lease4));
+    auto lease5 = createLease6(IOAddress("2001:db8:1:a000::"), 6);
+    EXPECT_TRUE(lease_mgr.addLease(lease5));
+    auto lease6 = createLease6(IOAddress("2001:db8:1:c000::"), 7);
+    EXPECT_TRUE(lease_mgr.addLease(lease6));
+    auto lease7 = createLease6(IOAddress("2001:db8:1:e000::"), 8);
+
+    // Age the lease but only by 150 seconds.
+    lease->cltt_ -= 150;
+    lease->current_cltt_ -= 150;
+    EXPECT_NO_THROW(lease_mgr.updateLease6(lease));
+
+    // Send the renew message to the server.
+    ASSERT_NO_THROW(client.doRenew());
 
-    // Let's transition the client to Renewing state.
-    client.setState(Dhcp6Client::RENEWING);
+    // Server should have renewed the prefix.
+    ASSERT_EQ(1, client.getLeaseNum());
+    Lease6Ptr renewed = checkLease(client.getLease(0));
+    ASSERT_TRUE(renewed);
 
-    // Set the unicast destination address to indicate that it is a renewal.
-    client.setDestAddress(IOAddress("10.0.0.1"));
-    ASSERT_NO_THROW(client.doRequest());
+    // Make sure that the client has got the same prefix.
+    EXPECT_EQ(lease->addr_, renewed->addr_);
+    EXPECT_EQ(lease->prefixlen_, renewed->prefixlen_);
 
-    // Make sure that renewal was ACKed.
-    resp = client.getContext().response_;
-    ASSERT_TRUE(resp);
-    ASSERT_EQ(DHCPACK, static_cast<int>(resp->getType()));
+    // Check the lease was updated.
+    EXPECT_NEAR(lease->cltt_ + 150, renewed->cltt_, 2);
 
-    // Make sure that the client renewed the requested address.
-    EXPECT_EQ(*hint, resp->getYiaddr());
+    // Preferred lifetime should be the config min-preferred-lifetime (100).
+    EXPECT_EQ(100, renewed->preferred_lft_);
 
-    // Valid lifetime should be the remaining lifetime so ~150 seconds.
-    opt = boost::dynamic_pointer_cast<OptionUint32>(resp->getOption(DHO_DHCP_LEASE_TIME));
-    ASSERT_TRUE(opt);
-    EXPECT_NEAR(150, opt->getValue(), 2);
+    // Valid lifetime should be the remaining lifetime so ~450
+    EXPECT_NEAR(450, renewed->valid_lft_, 2);
 }
-#endif
 
 }
index 1b322d0e9fc86d27ee98407429b6f9c68a1d4bc0..a86e338f58bbe8f0bb53c840726be55f58030844 100644 (file)
@@ -1737,6 +1737,22 @@ AllocEngine::removeNonreservedLeases6(ClientContext6& ctx,
         existing_leases.end(), Lease6Ptr()), existing_leases.end());
 }
 
+namespace {
+bool
+useMinLifetimes6(AllocEngine::ClientContext6& ctx, const IOAddress& addr,
+                 uint8_t prefix_len) {
+    auto const& threshold = ctx.subnet_->getAdaptiveLeaseTimeThreshold();
+    if (!threshold.unspecified() && (threshold < 1.0)) {
+        auto const& occupancy = ctx.subnet_->getAllocator(Lease::TYPE_PD)->
+            getOccupancyRate(addr, prefix_len, ctx.query_->getClasses());
+        if (occupancy >= threshold) {
+            return (true);
+        }
+    }
+    return (false);
+}
+} // end of anonymous namespace.
+
 Lease6Ptr
 AllocEngine::reuseExpiredLease(Lease6Ptr& expired, ClientContext6& ctx,
                                uint8_t prefix_len,
@@ -1750,19 +1766,8 @@ AllocEngine::reuseExpiredLease(Lease6Ptr& expired, ClientContext6& ctx,
         isc_throw(BadValue, "Attempt to recycle registered address");
     }
 
-    bool use_min = false;
     if (expired->type_ != Lease::TYPE_PD) {
         prefix_len = 128; // non-PD lease types must be always /128
-    } else {
-       auto const& threshold = ctx.subnet_->getAdaptiveLeaseTimeThreshold();
-        if (!threshold.unspecified() && (threshold < 1.0)) {
-            auto const& occupancy = ctx.subnet_->getAllocator(Lease::TYPE_PD)->
-                getOccupancyRate(expired->addr_, prefix_len,
-                                 ctx.query_->getClasses());
-            if (occupancy >= threshold) {
-                use_min = true;
-            }
-        }
     }
 
     if (!ctx.fake_allocation_) {
@@ -1780,10 +1785,11 @@ AllocEngine::reuseExpiredLease(Lease6Ptr& expired, ClientContext6& ctx,
     // Calculate life times.
     expired->preferred_lft_ = 0;
     expired->valid_lft_ = 0;
-    if (use_min) {
-       getMinLifetimes6(ctx, expired->preferred_lft_, expired->valid_lft_);
+    if ((expired->type_ == Lease::TYPE_PD) &&
+        useMinLifetimes6(ctx, expired->addr_, prefix_len)) {
+        getMinLifetimes6(ctx, expired->preferred_lft_, expired->valid_lft_);
     } else {
-       getLifetimes6(ctx, expired->preferred_lft_, expired->valid_lft_);
+        getLifetimes6(ctx, expired->preferred_lft_, expired->valid_lft_);
     }
     expired->reuseable_valid_lft_ = 0;
 
@@ -2053,23 +2059,14 @@ Lease6Ptr AllocEngine::createLease6(ClientContext6& ctx,
                                     uint8_t prefix_len,
                                     CalloutHandle::CalloutNextStep& callout_status) {
 
-    uint32_t preferred = 0;
-    uint32_t valid = 0;
-    bool use_min = false;
     if (ctx.currentIA().type_ != Lease::TYPE_PD) {
         prefix_len = 128; // non-PD lease types must be always /128
-    } else {
-        auto const& threshold = ctx.subnet_->getAdaptiveLeaseTimeThreshold();
-        if (!threshold.unspecified() && (threshold < 1.0)) {
-            auto const& occupancy = ctx.subnet_->getAllocator(Lease::TYPE_PD)->
-                getOccupancyRate(addr, prefix_len,
-                                 ctx.query_->getClasses());
-            if (occupancy >= threshold) {
-                use_min = true;
-            }
-        }
     }
-    if (use_min) {
+
+    uint32_t preferred = 0;
+    uint32_t valid = 0;
+    if ((ctx.currentIA().type_ == Lease::TYPE_PD) &&
+        useMinLifetimes6(ctx, addr, prefix_len)) {
         getMinLifetimes6(ctx, preferred, valid);
     } else {
         getLifetimes6(ctx, preferred, valid);
@@ -2201,8 +2198,8 @@ Lease6Ptr AllocEngine::createLease6(ClientContext6& ctx,
 }
 
 void
-AllocEngine::getRemaining(const Lease6Ptr& lease, uint32_t& valid,
-                          uint32_t& preferred) {
+AllocEngine::getRemaining(const Lease6Ptr& lease, uint32_t& preferred,
+                          uint32_t& valid) {
     valid = 0;
     preferred = 0;
     if (!lease || (lease->state_ != Lease::STATE_DEFAULT)) {
@@ -2409,7 +2406,17 @@ AllocEngine::extendLease6(ClientContext6& ctx, Lease6Ptr lease) {
 
     // Calculate life times.
     uint32_t current_preferred_lft = lease->preferred_lft_;
-    getLifetimes6(ctx, lease->preferred_lft_, lease->valid_lft_);
+    if ((lease->type_ == Lease::TYPE_PD) &&
+        useMinLifetimes6(ctx, lease->addr_, lease->prefixlen_)) {
+        uint32_t remain_preferred_lft(0);
+        uint32_t remain_valid_lft(0);
+        getRemaining(lease, remain_preferred_lft, remain_valid_lft);
+        lease->preferred_lft_ = remain_preferred_lft;
+        lease->valid_lft_ = remain_valid_lft;
+        getMinLifetimes6(ctx, lease->preferred_lft_, lease->valid_lft_);
+    } else {
+        getLifetimes6(ctx, lease->preferred_lft_, lease->valid_lft_);
+    }
 
     // If either has changed set the changed flag.
     if ((lease->preferred_lft_ != current_preferred_lft) ||
@@ -2595,7 +2602,13 @@ AllocEngine::updateLeaseData(ClientContext6& ctx, const Lease6Collection& leases
         uint32_t current_preferred_lft = lease->preferred_lft_;
         if (lease->valid_lft_ == 0) {
             // The lease was expired by a release: reset zero lifetimes.
-            getLifetimes6(ctx, lease->preferred_lft_, lease->valid_lft_);
+            lease->preferred_lft_ = 0;
+            if ((lease->type_ == Lease::TYPE_PD) &&
+                useMinLifetimes6(ctx, lease->addr_, lease->prefixlen_)) {
+                getMinLifetimes6(ctx, lease->preferred_lft_, lease->valid_lft_);
+            } else {
+                getLifetimes6(ctx, lease->preferred_lft_, lease->valid_lft_);
+            }
         }
         if (!ctx.fake_allocation_) {
             bool update_stats = false;
@@ -4484,6 +4497,21 @@ AllocEngine::getMinValidLft(const ClientContext4& ctx, uint32_t& valid) {
     }
 }
 
+namespace {
+bool
+useMinValidLft(const AllocEngine::ClientContext4& ctx, const IOAddress&addr) {
+    auto const& threshold = ctx.subnet_->getAdaptiveLeaseTimeThreshold();
+    if (!threshold.unspecified() && (threshold < 1.0)) {
+        auto const& occupancy = ctx.subnet_->getAllocator(Lease::TYPE_V4)->
+            getOccupancyRate(addr, ctx.query_->getClasses());
+        if (occupancy >= threshold) {
+            return (true);
+        }
+    }
+    return (false);
+}
+} // end of anonymous namespace.
+
 Lease4Ptr
 AllocEngine::createLease4(const ClientContext4& ctx, const IOAddress& addr,
                           CalloutHandle::CalloutNextStep& callout_status) {
@@ -4497,16 +4525,7 @@ AllocEngine::createLease4(const ClientContext4& ctx, const IOAddress& addr,
     // Get the context appropriate lifetime.
     uint32_t valid_lft = ctx.offer_lft_;
     if (!valid_lft) {
-        bool use_min(false);
-        auto const& threshold = ctx.subnet_->getAdaptiveLeaseTimeThreshold();
-        if (!threshold.unspecified() && (threshold < 1.0)) {
-            auto const& occupancy = ctx.subnet_->getAllocator(Lease::TYPE_V4)->
-                getOccupancyRate(addr, ctx.query_->getClasses());
-            if (occupancy >= threshold) {
-                use_min = true;
-            }
-        }
-        if (use_min) {
+        if (useMinValidLft(ctx, addr)) {
             getMinValidLft(ctx, valid_lft);
         } else {
             valid_lft = getValidLft(ctx);
@@ -5216,16 +5235,7 @@ AllocEngine::updateLease4Information(const Lease4Ptr& lease,
     // Get the context appropriate valid lifetime.
     lease->valid_lft_ = ctx.offer_lft_;
     if (!lease->valid_lft_) {
-        bool use_min(false);
-        auto const& threshold = ctx.subnet_->getAdaptiveLeaseTimeThreshold();
-        if (!threshold.unspecified() && (threshold < 1.0)) {
-            auto const& occupancy = ctx.subnet_->getAllocator(Lease::TYPE_V4)->
-                getOccupancyRate(lease->addr_, ctx.query_->getClasses());
-            if (occupancy >= threshold) {
-                use_min = true;
-            }
-        }
-        if (use_min) {
+        if (useMinValidLft(ctx, lease->addr_)) {
             lease->valid_lft_ = remain_lft;
             getMinValidLft(ctx, lease->valid_lft_);
         } else {
index 90fb16ee20961ec45be42475d7ab31386e5570bf..1dfe8ed04698be3fcc9f0aedbcd4b7ebfb05f341 100644 (file)
@@ -1596,10 +1596,10 @@ public:
     /// @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);
+    /// @param [out] valid The remaining valid life time or 0.
+    static void getRemaining(const Lease6Ptr& lease, uint32_t& preferred,
+                             uint32_t& valid);
 
 private: