]> git.ipfire.org Git - thirdparty/kea.git/commitdiff
[#2780] Configure FLQ allocator
authorMarcin Siodelski <msiodelski@gmail.com>
Thu, 16 Mar 2023 18:09:05 +0000 (19:09 +0100)
committerMarcin Siodelski <msiodelski@gmail.com>
Wed, 29 Mar 2023 12:44:01 +0000 (14:44 +0200)
src/bin/dhcp4/ctrl_dhcp4_srv.cc
src/bin/dhcp6/ctrl_dhcp6_srv.cc
src/lib/dhcpsrv/dhcpsrv_messages.mes
src/lib/dhcpsrv/flq_allocator.cc
src/lib/dhcpsrv/parsers/base_network_parser.cc
src/lib/dhcpsrv/parsers/dhcp_parsers.cc
src/lib/dhcpsrv/tests/dhcp_parsers_unittest.cc

index d739707c746b0890dee204a9011da8095d3fe046..b6981bf1b313e12172b80a6af48edb8ddef87f34 100644 (file)
@@ -930,7 +930,7 @@ ControlledDhcpv4Srv::processConfig(isc::data::ConstElementPtr config) {
         cfg_db->createManagers();
         // Reset counters related to connections as all managers have been recreated.
         srv->getNetworkState()->reset(NetworkState::Origin::DB_CONNECTION);
-        CfgMgr::instance().getStagingCfg()->getCfgSubnets4()->initAllocatorsAfterConfigure();
+
     } catch (const std::exception& ex) {
         err << "Unable to open database: " << ex.what();
         return (isc::config::createAnswer(CONTROL_RESULT_ERROR, err.str()));
@@ -1083,6 +1083,17 @@ ControlledDhcpv4Srv::finishConfigHookLibraries(isc::data::ConstElementPtr config
     }
 
     return (ConstElementPtr());
+    }
+
+    // Initialize the allocators. If the user selected a Free Lease Queue Allocator
+    // for any of the subnets, the server will now populate free leases to the queue.
+    // It may take a while!
+    try {
+        CfgMgr::instance().getStagingCfg()->getCfgSubnets4()->initAllocatorsAfterConfigure();
+
+    } catch (const std::exception& ex) {
+        err << "Error initializing the lease allocators: "
+            << ex.what();
 }
 
 isc::data::ConstElementPtr
index 710bd18ad2cde8991dc701897f667530ca3fb01c..f5702ed23aba1ab442a2e0d026ac89add161b92b 100644 (file)
@@ -1102,6 +1102,16 @@ ControlledDhcpv6Srv::finishConfigHookLibraries(isc::data::ConstElementPtr config
     }
 
     return (ConstElementPtr());
+    // Initialize the allocators. If the user selected a Free Lease Queue Allocator
+    // for any of the subnets, the server will now populate free leases to the queue.
+    // It may take a while!
+    try {
+        CfgMgr::instance().getStagingCfg()->getCfgSubnets6()->initAllocatorsAfterConfigure();
+
+    } catch (const std::exception& ex) {
+        err << "Error initializing the lease allocators: " << ex.what();
+    }
+
 }
 
 isc::data::ConstElementPtr
index 70612e983dd62f61e4137524fe3aca8bac855824..3dd04687f57bf8e6f256e45cf4b28121c16ff832 100644 (file)
@@ -81,6 +81,24 @@ server configuration. The argument identifies the removed subnet.
 This debug message is issued when a subnet is successfully removed from the
 server configuration. The argument identifies the removed subnet.
 
+% DHCPSRV_CFGMGR_FLQ_POPULATE_FREE_ADDRESS_LEASES populating free address leases for the FLQ allocator in subnet %1; it can take a while!
+This informational message is issued when the server begins building a queue
+of free address leases for the given subnet. It can take a considerable amount
+of time, depending on the size of the address pools.
+
+% DHCPSRV_CFGMGR_FLQ_POPULATE_FREE_ADDRESS_LEASES_DONE populating free address leases for the FLQ allocator in subnet %1 completed
+This informational message is issued when the server ends building a queue
+of free address leases for a given subnet.
+
+% DHCPSRV_CFGMGR_FLQ_POPULATE_FREE_PREFIX_LEASES populating free prefix leases for the FLQ allocator in subnet %1; it can take a while!
+This informational message is issued when the server begins building a queue
+of free leases for the given subnet. It can take a considerable amount of
+time, depending on the size of the delegated prefix pools.
+
+% DHCPSRV_CFGMGR_FLQ_POPULATE_FREE_PREFIX_LEASES_DONE populating free prefix leases for the FLQ allocator in subnet %1 completed
+This informational message is issued when the server ends building a queue
+of free prefix leases for a given subnet.
+
 % DHCPSRV_CFGMGR_IPV4_RESERVATIONS_NON_UNIQUE_IGNORED ignoring "ip-reservations-unique" setting because at least one of the host database backends does not support non-unique IP reservations in a subnet
 This warning message is issued when the server failed to use the new setting
 of the ip-reservations-unique global parameter configured via the configuration
index 633ac31aee4390ef86b64a2aeffcf5df9ebc13c4..8a5535124c973cbf90118983b6ba4a1e563b73b1 100644 (file)
@@ -7,6 +7,7 @@
 #include <config.h>
 
 #include <asiolink/addr_utilities.h>
+#include <dhcpsrv/dhcpsrv_log.h>
 #include <dhcpsrv/flq_allocator.h>
 #include <dhcpsrv/ip_range_permutation.h>
 #include <dhcpsrv/lease_mgr_factory.h>
@@ -179,6 +180,10 @@ FreeLeaseQueueAllocator::initAfterConfigure() {
 template<typename LeaseCollectionType>
 void
 FreeLeaseQueueAllocator::populateFreeAddressLeases(const LeaseCollectionType& leases, const PoolCollection& pools) {
+    auto subnet = subnet_.lock();
+    LOG_INFO(dhcpsrv_logger, DHCPSRV_CFGMGR_FLQ_POPULATE_FREE_ADDRESS_LEASES)
+        .arg(subnet->toText());
+
     // Let's iterate over the lease queue and index them with the
     // unordered_set. Also, elminate the expired leases and those
     // in the expired-reclaimed state.
@@ -206,10 +211,16 @@ FreeLeaseQueueAllocator::populateFreeAddressLeases(const LeaseCollectionType& le
             }
         }
     }
+    LOG_INFO(dhcpsrv_logger, DHCPSRV_CFGMGR_FLQ_POPULATE_FREE_ADDRESS_LEASES_DONE)
+        .arg(subnet->toText());
 }
 
 void
 FreeLeaseQueueAllocator::populateFreePrefixDelegationLeases(const Lease6Collection& leases, const PoolCollection& pools) {
+    auto subnet = subnet_.lock();
+    LOG_INFO(dhcpsrv_logger, DHCPSRV_CFGMGR_FLQ_POPULATE_FREE_PREFIX_LEASES)
+        .arg(subnet->toText());
+
     // Let's iterate over the lease queue and index them with the
     // unordered_set. Also, elminate the expired leases and those
     // in the expired-reclaimed state.
@@ -241,6 +252,8 @@ FreeLeaseQueueAllocator::populateFreePrefixDelegationLeases(const Lease6Collecti
             }
         }
     }
+    LOG_INFO(dhcpsrv_logger, DHCPSRV_CFGMGR_FLQ_POPULATE_FREE_PREFIX_LEASES_DONE)
+        .arg(subnet->toText());
 }
 
 SubnetFreeLeaseQueueAllocationStatePtr
index e75abeed2912c18b4d1e0f04b280fb6fda5304da..d5a21b26e88ed16cae87c10d358942b5511b85c3 100644 (file)
@@ -281,9 +281,10 @@ BaseNetworkParser::parseAllocatorParams(const data::ConstElementPtr& network_dat
                                         NetworkPtr& network) {
     if (network_data->contains("allocator")) {
         auto allocator_type = getString(network_data, "allocator");
-        if ((allocator_type != "iterative") && (allocator_type != "random")) {
+        if ((allocator_type != "iterative") && (allocator_type != "random") &&
+            (allocator_type != "flq")) {
             // Unsupported allocator type used.
-            isc_throw(DhcpConfigError, "supported allocators are: iterative and random");
+            isc_throw(DhcpConfigError, "supported allocators are: iterative, random and flq");
         }
         network->setAllocatorType(allocator_type);
     }
@@ -294,9 +295,10 @@ BaseNetworkParser::parsePdAllocatorParams(const data::ConstElementPtr& network_d
                                           Network6Ptr& network) {
     if (network_data->contains("pd-allocator")) {
         auto allocator_type = getString(network_data, "pd-allocator");
-        if ((allocator_type != "iterative") && (allocator_type != "random")) {
+        if ((allocator_type != "iterative") && (allocator_type != "random") &&
+            (allocator_type != "flq")) {
             // Unsupported allocator type used.
-            isc_throw(DhcpConfigError, "supported allocators are: iterative and random");
+            isc_throw(DhcpConfigError, "supported allocators are: iterative, random and flq");
         }
         network->setPdAllocatorType(allocator_type);
     }
index 6053d722c34f642ab40dce981dd9c12910fbae3b..c5ffd3e1f7ad4121743ff62de072458d1d837f60 100644 (file)
@@ -11,6 +11,8 @@
 #include <dhcpsrv/cfgmgr.h>
 #include <dhcpsrv/cfg_option.h>
 #include <dhcpsrv/dhcpsrv_log.h>
+#include <dhcpsrv/flq_allocation_state.h>
+#include <dhcpsrv/flq_allocator.h>
 #include <dhcpsrv/iterative_allocation_state.h>
 #include <dhcpsrv/iterative_allocator.h>
 #include <dhcpsrv/random_allocation_state.h>
@@ -726,14 +728,22 @@ Subnet4ConfigParser::parse(ConstElementPtr subnet) {
 
     if (sn4ptr->getAllocatorType() == "random") {
         sn4ptr->setAllocator(Lease::TYPE_V4,
-                              boost::make_shared<RandomAllocator>
-                              (Lease::TYPE_V4, sn4ptr));
+                             boost::make_shared<RandomAllocator>
+                             (Lease::TYPE_V4, sn4ptr));
         sn4ptr->setAllocationState(Lease::TYPE_V4, SubnetAllocationStatePtr());
 
         for (auto pool : *pools_) {
             pool->setAllocationState(PoolRandomAllocationState::create(pool));
         }
 
+    } else if (sn4ptr->getAllocatorType() == "flq") {
+        sn4ptr->setAllocator(Lease::TYPE_V4,
+                             boost::make_shared<FreeLeaseQueueAllocator>
+                             (Lease::TYPE_V4, sn4ptr));
+        for (auto pool : *pools_) {
+            pool->setAllocationState(PoolFreeLeaseQueueAllocationState::create(pool));
+        }
+
     } else {
         for (auto pool : *pools_) {
             pool->setAllocationState(PoolIterativeAllocationState::create(pool));
@@ -1273,25 +1283,32 @@ Subnet6ConfigParser::parse(ConstElementPtr subnet) {
         sn6ptr->setAllocationState(Lease::TYPE_NA, SubnetAllocationStatePtr());
         sn6ptr->setAllocationState(Lease::TYPE_TA, SubnetAllocationStatePtr());
 
+    } else if (sn6ptr->getAllocatorType() == "flq") {
+        isc_throw(BadValue, "Free Lease Queue allocator is not supported for IPv6 address pools");
     }
 
     // Repeat the same for the delegated prefix allocator.
     if (sn6ptr->getPdAllocatorType() == "random") {
         sn6ptr->setAllocator(Lease::TYPE_PD,
-                              boost::make_shared<RandomAllocator>
-                              (Lease::TYPE_PD, sn6ptr));
+                             boost::make_shared<RandomAllocator>
+                             (Lease::TYPE_PD, sn6ptr));
         sn6ptr->setAllocationState(Lease::TYPE_PD, SubnetAllocationStatePtr());
 
+    } else  if (sn6ptr->getPdAllocatorType() == "flq") {
+        sn6ptr->setAllocator(Lease::TYPE_PD,
+                             boost::make_shared<FreeLeaseQueueAllocator>
+                             (Lease::TYPE_PD, sn6ptr));
+        sn6ptr->setAllocationState(Lease::TYPE_PD, SubnetAllocationStatePtr());
     }
 
     // Create states for the pools.
     for (auto pool : *pools_) {
         switch (pool->getType()) {
-        case Lease::TYPE_V4:
         case Lease::TYPE_NA:
         case Lease::TYPE_TA:
             if (sn6ptr->getAllocatorType() == "random") {
                 pool->setAllocationState(PoolRandomAllocationState::create(pool));
+
             } else {
                 pool->setAllocationState(PoolIterativeAllocationState::create(pool));
             }
@@ -1299,10 +1316,16 @@ Subnet6ConfigParser::parse(ConstElementPtr subnet) {
         case Lease::TYPE_PD:
             if (sn6ptr->getPdAllocatorType() == "random") {
                 pool->setAllocationState(PoolRandomAllocationState::create(pool));
+
+            } else if (sn6ptr->getPdAllocatorType() == "flq") {
+                pool->setAllocationState(PoolFreeLeaseQueueAllocationState::create(pool));
+
             } else {
                 pool->setAllocationState(PoolIterativeAllocationState::create(pool));
             }
             break;
+        default:
+            continue;
         }
     }
 
index 50b05b3c5d881337566bbc792e29923eac075261..c9dfa44ea6eee863091afee713098aba196918b3 100644 (file)
@@ -18,6 +18,8 @@
 #include <dhcpsrv/cfgmgr.h>
 #include <dhcpsrv/subnet.h>
 #include <dhcpsrv/cfg_mac_source.h>
+#include <dhcpsrv/flq_allocator.h>
+#include <dhcpsrv/flq_allocation_state.h>
 #include <dhcpsrv/iterative_allocator.h>
 #include <dhcpsrv/iterative_allocation_state.h>
 #include <dhcpsrv/parsers/dhcp_parsers.h>
@@ -3238,6 +3240,34 @@ TEST_F(ParseConfigTest, randomSubnetAllocator4) {
     EXPECT_TRUE(boost::dynamic_pointer_cast<RandomAllocator>(allocator));
 }
 
+// This test verifies that Free Lease Queue allocator can be selected for
+// a subnet.
+TEST_F(ParseConfigTest, flqSubnetAllocator4) {
+    std::string config =
+        "{"
+        "    \"subnet4\": [ {"
+        "        \"subnet\": \"192.0.2.0/24\","
+        "        \"id\": 1,"
+        "        \"allocator\": \"flq\""
+        "    } ]"
+        "}";
+
+    ElementPtr json = Element::fromJSON(config);
+    EXPECT_TRUE(json);
+    ConstElementPtr status = parseElementSet(json, false);
+    int rcode = 0;
+    ConstElementPtr comment = parseAnswer(rcode, status);
+    ASSERT_EQ(0, rcode);
+
+    auto subnet = CfgMgr::instance().getStagingCfg()->getCfgSubnets4()->getBySubnetId(1);
+    ASSERT_TRUE(subnet);
+
+    EXPECT_EQ("flq", subnet->getAllocatorType().get());
+    auto allocator = subnet->getAllocator(Lease::TYPE_V4);
+    ASSERT_TRUE(allocator);
+    EXPECT_TRUE(boost::dynamic_pointer_cast<FreeLeaseQueueAllocator>(allocator));
+}
+
 // This test verifies that unknown allocator is rejected.
 TEST_F(ParseConfigTest, invalidSubnetAllocator4) {
     std::string config =
@@ -3258,7 +3288,7 @@ TEST_F(ParseConfigTest, invalidSubnetAllocator4) {
     ASSERT_EQ(comment->getType(), Element::string);
     EXPECT_EQ(1, rcode);
     std::string expected = "Configuration parsing failed: ";
-    expected += "supported allocators are: iterative and random";
+    expected += "supported allocators are: iterative, random and flq";
     EXPECT_EQ(expected, comment->stringValue());
 }
 
@@ -3297,6 +3327,31 @@ TEST_F(ParseConfigTest, randomSubnetAllocator6) {
     EXPECT_TRUE(boost::dynamic_pointer_cast<IterativeAllocator>(allocator));
 }
 
+// This test verifies that FLQ allocator is not supported for
+// IPv6 address pools.
+TEST_F(ParseConfigTest, flqSubnetAllocator6) {
+    std::string config =
+        "{"
+        "    \"subnet6\": [ {"
+        "        \"subnet\": \"2001:db8:1::/64\","
+        "        \"id\": 1,"
+        "        \"allocator\": \"flq\""
+        "    } ]"
+        "}";
+
+    ElementPtr json = Element::fromJSON(config);
+    EXPECT_TRUE(json);
+    ConstElementPtr status = parseElementSet(json, false);
+    int rcode = 0;
+    ConstElementPtr comment = parseAnswer(rcode, status);
+    ASSERT_TRUE(comment);
+    ASSERT_EQ(comment->getType(), Element::string);
+    EXPECT_EQ(1, rcode);
+    std::string expected = "Configuration parsing failed: ";
+    expected += "Free Lease Queue allocator is not supported for IPv6 address pools";
+    EXPECT_EQ(expected, comment->stringValue());
+}
+
 // This test verifies that unknown allocator is rejected.
 TEST_F(ParseConfigTest, invalidSubnetAllocator6) {
     std::string config =
@@ -3317,7 +3372,7 @@ TEST_F(ParseConfigTest, invalidSubnetAllocator6) {
     ASSERT_EQ(comment->getType(), Element::string);
     EXPECT_EQ(1, rcode);
     std::string expected = "Configuration parsing failed: ";
-    expected += "supported allocators are: iterative and random";
+    expected += "supported allocators are: iterative, random and flq";
     EXPECT_EQ(expected, comment->stringValue());
 }
 
@@ -3378,7 +3433,7 @@ TEST_F(ParseConfigTest, invalidSubnetPdAllocator6) {
     ASSERT_EQ(comment->getType(), Element::string);
     EXPECT_EQ(1, rcode);
     std::string expected = "Configuration parsing failed: ";
-    expected += "supported allocators are: iterative and random";
+    expected += "supported allocators are: iterative, random and flq";
     EXPECT_EQ(expected, comment->stringValue());
 }