diff --git a/src/bin/dhcp6/tests/flq_unittest.cc b/src/bin/dhcp6/tests/flq_unittest.cc index 798634f235..41ad2a7cb7 100644 --- a/src/bin/dhcp6/tests/flq_unittest.cc +++ b/src/bin/dhcp6/tests/flq_unittest.cc @@ -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 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(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()); - // 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(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 valid-lifetime parameter value (200). - opt = boost::dynamic_pointer_cast(resp->getOption(DHO_DHCP_LEASE_TIME)); - ASSERT_TRUE(opt); - EXPECT_EQ(200, opt->getValue()); + // Preferred lifetime should be the config preferred-lifetime (200). + EXPECT_EQ(200, renewed->preferred_lft_); + + // 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 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(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_); + + // 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("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. - auto& lease_mgr = LeaseMgrFactory::instance(); - Lease6Ptr lease = lease_mgr.getLease6(*hint); - ASSERT_TRUE(lease); - lease->cltt_ -= 150; - lease->current_cltt_ -= 150; + lease->cltt_ -= 1000; + lease->current_cltt_ -= 1000; EXPECT_NO_THROW(lease_mgr.updateLease6(lease)); - // Create leases for the first addresses. - auto lease1 = createLease6(IOAddress("10.0.0.11"), 1); - EXPECT_TRUE(lease_mgr.addLease(lease1)); - auto lease2 = createLease6(IOAddress("10.0.0.12"), 2); - EXPECT_TRUE(lease_mgr.addLease(lease2)); - auto lease3 = createLease6(IOAddress("10.0.0.13"), 3); - EXPECT_TRUE(lease_mgr.addLease(lease3)); + // 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(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 min-preferred-lifetime (100). + EXPECT_EQ(100, renewed->preferred_lft_); - // Valid lifetime should be the min-valid-lifetime parameter value (100). - opt = boost::dynamic_pointer_cast(resp->getOption(DHO_DHCP_LEASE_TIME)); - ASSERT_TRUE(opt); - EXPECT_EQ(100, opt->getValue()); + // 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 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(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_); + + // 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("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. - auto& lease_mgr = LeaseMgrFactory::instance(); - Lease6Ptr lease = lease_mgr.getLease6(*hint); - ASSERT_TRUE(lease); 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); - // Let's transition the client to Renewing state. - client.setState(Dhcp6Client::RENEWING); + // Age the lease but only by 150 seconds. + lease->cltt_ -= 150; + lease->current_cltt_ -= 150; + EXPECT_NO_THROW(lease_mgr.updateLease6(lease)); - // Set the unicast destination address to indicate that it is a renewal. - client.setDestAddress(IOAddress("10.0.0.1")); - ASSERT_NO_THROW(client.doRequest()); + // Send the renew message to the server. + ASSERT_NO_THROW(client.doRenew()); - // Make sure that renewal was ACKed. - resp = client.getContext().response_; - ASSERT_TRUE(resp); - ASSERT_EQ(DHCPACK, static_cast(resp->getType())); + // 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 renewed the requested address. - EXPECT_EQ(*hint, resp->getYiaddr()); + // Make sure that the client has got the same prefix. + EXPECT_EQ(lease->addr_, renewed->addr_); + EXPECT_EQ(lease->prefixlen_, renewed->prefixlen_); - // Valid lifetime should be the remaining lifetime so ~150 seconds. - opt = boost::dynamic_pointer_cast(resp->getOption(DHO_DHCP_LEASE_TIME)); - ASSERT_TRUE(opt); - EXPECT_NEAR(150, opt->getValue(), 2); + // Check the lease was updated. + EXPECT_NEAR(lease->cltt_ + 150, renewed->cltt_, 2); + + // Preferred lifetime should be the config min-preferred-lifetime (100). + EXPECT_EQ(100, renewed->preferred_lft_); + + // Valid lifetime should be the remaining lifetime so ~450 + EXPECT_NEAR(450, renewed->valid_lft_, 2); } -#endif } diff --git a/src/lib/dhcpsrv/alloc_engine.cc b/src/lib/dhcpsrv/alloc_engine.cc index 1b322d0e9f..a86e338f58 100644 --- a/src/lib/dhcpsrv/alloc_engine.cc +++ b/src/lib/dhcpsrv/alloc_engine.cc @@ -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 { diff --git a/src/lib/dhcpsrv/alloc_engine.h b/src/lib/dhcpsrv/alloc_engine.h index 90fb16ee20..1dfe8ed046 100644 --- a/src/lib/dhcpsrv/alloc_engine.h +++ b/src/lib/dhcpsrv/alloc_engine.h @@ -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: