]> git.ipfire.org Git - thirdparty/kea.git/commitdiff
[#2823] Common methods for instantiating allocators
authorMarcin Siodelski <marcin@isc.org>
Tue, 4 Apr 2023 20:45:18 +0000 (22:45 +0200)
committerMarcin Siodelski <marcin@isc.org>
Wed, 19 Apr 2023 16:26:04 +0000 (18:26 +0200)
The logic creating allocators and allocation states have been moved to the
Subnet. It can now be reused in the config backend fetch.

src/lib/dhcpsrv/parsers/dhcp_parsers.cc
src/lib/dhcpsrv/subnet.cc
src/lib/dhcpsrv/subnet.h
src/lib/dhcpsrv/tests/subnet_unittest.cc

index c5ffd3e1f7ad4121743ff62de072458d1d837f60..2aa74afc8be1f3d4c992ffd54256a734e10d3340 100644 (file)
 #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>
-#include <dhcpsrv/random_allocator.h>
 #include <dhcpsrv/parsers/dhcp_parsers.h>
 #include <dhcpsrv/parsers/host_reservation_parser.h>
 #include <dhcpsrv/parsers/host_reservations_list_parser.h>
@@ -726,29 +720,8 @@ Subnet4ConfigParser::parse(ConstElementPtr subnet) {
     auto network4 = boost::dynamic_pointer_cast<Network>(sn4ptr);
     parseAllocatorParams(subnet, network4);
 
-    if (sn4ptr->getAllocatorType() == "random") {
-        sn4ptr->setAllocator(Lease::TYPE_V4,
-                             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));
-        }
-    }
+    // Instantiate the allocator.
+    sn4ptr->createAllocators();
 
     return (sn4ptr);
 }
@@ -1270,64 +1243,8 @@ Subnet6ConfigParser::parse(ConstElementPtr subnet) {
     auto network6 = boost::dynamic_pointer_cast<Network6>(sn6ptr);
     parsePdAllocatorParams(subnet, network6);
 
-    // If we use the random allocator we need to create its instance and
-    // the state instance for it. There is no need to do it for the iterative
-    // allocator because it is configured by default.
-    if (sn6ptr->getAllocatorType() == "random") {
-        sn6ptr->setAllocator(Lease::TYPE_NA,
-                              boost::make_shared<RandomAllocator>
-                              (Lease::TYPE_NA, sn6ptr));
-        sn6ptr->setAllocator(Lease::TYPE_TA,
-                              boost::make_shared<RandomAllocator>
-                              (Lease::TYPE_TA, sn6ptr));
-        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));
-        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_NA:
-        case Lease::TYPE_TA:
-            if (sn6ptr->getAllocatorType() == "random") {
-                pool->setAllocationState(PoolRandomAllocationState::create(pool));
-
-            } else {
-                pool->setAllocationState(PoolIterativeAllocationState::create(pool));
-            }
-            break;
-        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;
-        }
-    }
+    // Instantiate the allocators.
+    sn6ptr->createAllocators();
 
     return (sn6ptr);
 }
index 762589c0d80ccaef176164d5eb2185cba258604f..dbd7108107af26aacebe89570581ee23309adfd0 100644 (file)
@@ -9,7 +9,12 @@
 #include <asiolink/io_address.h>
 #include <asiolink/addr_utilities.h>
 #include <dhcp/option_space.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>
+#include <dhcpsrv/random_allocator.h>
 #include <dhcpsrv/shared_network.h>
 #include <dhcpsrv/subnet.h>
 #include <util/multi_threading_mgr.h>
@@ -743,6 +748,33 @@ Subnet::toElement() const {
     return (map);
 }
 
+void
+Subnet4::createAllocators() {
+    if (getAllocatorType() == "random") {
+        setAllocator(Lease::TYPE_V4,
+                     boost::make_shared<RandomAllocator>
+                     (Lease::TYPE_V4, shared_from_this()));
+        setAllocationState(Lease::TYPE_V4, SubnetAllocationStatePtr());
+
+        for (auto pool : pools_) {
+            pool->setAllocationState(PoolRandomAllocationState::create(pool));
+        }
+
+    } else if (getAllocatorType() == "flq") {
+        setAllocator(Lease::TYPE_V4,
+                     boost::make_shared<FreeLeaseQueueAllocator>
+                     (Lease::TYPE_V4, shared_from_this()));
+        for (auto pool : pools_) {
+            pool->setAllocationState(PoolFreeLeaseQueueAllocationState::create(pool));
+        }
+
+    } else {
+        for (auto pool : pools_) {
+            pool->setAllocationState(PoolIterativeAllocationState::create(pool));
+        }
+    }
+}
+
 data::ElementPtr
 Subnet4::toElement() const {
     // Prepare the map
@@ -777,6 +809,66 @@ Subnet4::parsePrefix(const std::string& prefix) {
     return (parsed);
 }
 
+void
+Subnet6::createAllocators() {
+    // If we use the random allocator we need to create its instance and
+    // the state instance for it. There is no need to do it for the iterative
+    // allocator because it is configured by default.
+    if (getAllocatorType() == "random") {
+        setAllocator(Lease::TYPE_NA,
+                     boost::make_shared<RandomAllocator>
+                     (Lease::TYPE_NA, shared_from_this()));
+        setAllocator(Lease::TYPE_TA,
+                     boost::make_shared<RandomAllocator>
+                     (Lease::TYPE_TA, shared_from_this()));
+        setAllocationState(Lease::TYPE_NA, SubnetAllocationStatePtr());
+        setAllocationState(Lease::TYPE_TA, SubnetAllocationStatePtr());
+
+    } else if (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 (getPdAllocatorType() == "random") {
+        setAllocator(Lease::TYPE_PD,
+                     boost::make_shared<RandomAllocator>
+                     (Lease::TYPE_PD, shared_from_this()));
+        setAllocationState(Lease::TYPE_PD, SubnetAllocationStatePtr());
+
+    } else  if (getPdAllocatorType() == "flq") {
+        setAllocator(Lease::TYPE_PD,
+                     boost::make_shared<FreeLeaseQueueAllocator>
+                     (Lease::TYPE_PD, shared_from_this()));
+        setAllocationState(Lease::TYPE_PD, SubnetAllocationStatePtr());
+    }
+    // Create allocation states for NA pools.
+    for (auto pool : pools_) {
+        if (getAllocatorType() == "random") {
+            pool->setAllocationState(PoolRandomAllocationState::create(pool));
+        } else {
+            pool->setAllocationState(PoolIterativeAllocationState::create(pool));
+        }
+    }
+    // Create allocation states for TA pools.
+    for (auto pool : pools_ta_) {
+        if (getAllocatorType() == "random") {
+            pool->setAllocationState(PoolRandomAllocationState::create(pool));
+        } else {
+            pool->setAllocationState(PoolIterativeAllocationState::create(pool));
+        }
+    }
+    // Create allocation states for PD pools.
+    for (auto pool : pools_pd_) {
+        if (getPdAllocatorType() == "random") {
+            pool->setAllocationState(PoolRandomAllocationState::create(pool));
+        } else if (getPdAllocatorType() == "flq") {
+            pool->setAllocationState(PoolFreeLeaseQueueAllocationState::create(pool));
+        } else {
+            pool->setAllocationState(PoolIterativeAllocationState::create(pool));
+        }
+    }
+}
+
 data::ElementPtr
 Subnet6::toElement() const {
     // Prepare the map
index a388d5f18a69f35a05c27d57d308308cffc9d0fb..891d20d42437cabd57f114c31f97c6c803c2859b 100644 (file)
@@ -20,6 +20,7 @@
 #include <util/dhcp_space.h>
 #include <util/triplet.h>
 
+#include <boost/enable_shared_from_this.hpp>
 #include <boost/multi_index/mem_fun.hpp>
 #include <boost/multi_index/indexed_by.hpp>
 #include <boost/multi_index/ordered_index.hpp>
@@ -316,6 +317,15 @@ public:
     /// @param allocation_state allocation state instance.
     void setAllocationState(Lease::Type type, const SubnetAllocationStatePtr& allocation_state);
 
+    /// @brief Instantiates the allocators and their states.
+    ///
+    /// It determines the types of the allocators to create using the list of
+    /// the allocator types specified with the @c Network::setAllocatorType method.
+    ///
+    /// This function is called from the subnet parsers and after fetching
+    /// the subnet configuration from a configuration backend.
+    virtual void createAllocators() = 0;
+
     /// @brief Calls @c initAfterConfigure for each allocator.
     void initAllocatorsAfterConfigure();
 
@@ -490,7 +500,7 @@ typedef boost::shared_ptr<Subnet4> Subnet4Ptr;
 /// This class represents an IPv4 subnet.
 /// @note Subnet and Network use virtual inheritance to avoid
 /// a diamond issue with UserContext
-class Subnet4 : public Subnet, public Network4 {
+class Subnet4 : public Subnet, public Network4, public boost::enable_shared_from_this<Subnet4> {
 public:
 
     /// @brief Constructor with all parameters.
@@ -601,6 +611,15 @@ public:
     /// @return A pointer to unparsed subnet configuration.
     virtual data::ElementPtr toElement() const;
 
+    /// @brief Instantiates the allocator and its state.
+    ///
+    /// It uses the type of the allocator specified with the
+    /// @c Network::setAllocatorType method.
+    ///
+    /// This function is called from the subnet parsers and after fetching
+    /// the subnet configuration from a configuration backend.
+    virtual void createAllocators();
+
     /// @brief Converts subnet prefix to a pair of prefix/length pair.
     ///
     /// @param prefix Prefix to be parsed.
@@ -648,7 +667,7 @@ typedef boost::shared_ptr<Subnet6> Subnet6Ptr;
 /// This class represents an IPv6 subnet.
 /// @note Subnet and Network use virtual inheritance to avoid
 /// a diamond issue with UserContext
-class Subnet6 : public Subnet, public Network6 {
+class Subnet6 : public Subnet, public Network6, public boost::enable_shared_from_this<Subnet6> {
 public:
 
     /// @brief Constructor with all parameters.
@@ -742,6 +761,15 @@ public:
     virtual bool
     clientSupported(const isc::dhcp::ClientClasses& client_classes) const;
 
+    /// @brief Instantiates the allocators and their states.
+    ///
+    /// It determines the types of the allocators to create using the list of
+    /// the allocator types specified with the @c Network::setAllocatorType method.
+    ///
+    /// This function is called from the subnet parsers and after fetching
+    /// the subnet configuration from a configuration backend.
+    virtual void createAllocators();
+
     /// @brief Unparse a subnet object.
     ///
     /// @return A pointer to unparsed subnet configuration.
index 85de81ee0b6d296068c0b2a32abb02c435c88f4c..304ca88ba9d561422237cc2038aa6b2be90d840f 100644 (file)
 #include <dhcp/option_custom.h>
 #include <dhcp/option_definition.h>
 #include <dhcp/option_space.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/random_allocator.h>
+#include <dhcpsrv/random_allocation_state.h>
 #include <dhcpsrv/shared_network.h>
 #include <dhcpsrv/subnet.h>
 #include <exceptions/exceptions.h>
@@ -763,6 +769,70 @@ TEST(Subnet4Test, getServerId) {
     EXPECT_EQ("1.2.3.4", subnet.getServerId().toText());
 }
 
+// This test verifies that an iterative allocator and the corresponding
+// states are instantiated for a subnet.
+TEST(Subnet4Test, createAllocatorsIterative) {
+    // Create a subnet.
+    auto subnet = Subnet4::create(IOAddress("192.2.0.0"), 16, 1, 2, 3);
+    ASSERT_TRUE(subnet);
+    // Create a pool.
+    auto pool = boost::make_shared<Pool4>(IOAddress("192.2.0.0"), 16);
+    subnet->addPool(pool);
+    // Instantiate the allocator.
+    ASSERT_NO_THROW(subnet->createAllocators());
+    // Expect iterative allocator.
+    EXPECT_TRUE(boost::dynamic_pointer_cast<IterativeAllocator>
+                (subnet->getAllocator(Lease::TYPE_V4)));
+    // Expect iterative allocation state for the subnet.
+    EXPECT_TRUE(boost::dynamic_pointer_cast<SubnetIterativeAllocationState>
+                (subnet->getAllocationState(Lease::TYPE_V4)));
+    // Expect iterative allocation state for the pool.
+    EXPECT_TRUE(boost::dynamic_pointer_cast<PoolIterativeAllocationState>
+                (pool->getAllocationState()));
+}
+
+// This test verifies that a random allocator and the corresponding
+// states are instantiated for a subnet.
+TEST(Subnet4Test, createAllocatorsRandom) {
+    // Create a subnet.
+    auto subnet = Subnet4::create(IOAddress("192.2.0.0"), 16, 1, 2, 3);
+    ASSERT_TRUE(subnet);
+    // Create a pool.
+    auto pool = boost::make_shared<Pool4>(IOAddress("192.2.0.0"), 16);
+    subnet->addPool(pool);
+    // Select the random allocator.
+    subnet->setAllocatorType("random");
+    // Instantiate the allocator.
+    ASSERT_NO_THROW(subnet->createAllocators());
+    // Expect random allocator.
+    EXPECT_TRUE(boost::dynamic_pointer_cast<RandomAllocator>
+                (subnet->getAllocator(Lease::TYPE_V4)));
+    // Expect random allocation state for the pool.
+    EXPECT_TRUE(boost::dynamic_pointer_cast<PoolRandomAllocationState>
+                (pool->getAllocationState()));
+}
+
+// This test verifies that an FLQ allocator and the corresponding
+// states are instantiated for a subnet.
+TEST(Subnet4Test, createAllocatorsFreeLeaseQueue) {
+    // Create a subnet.
+    auto subnet = Subnet4::create(IOAddress("192.2.0.0"), 16, 1, 2, 3);
+    ASSERT_TRUE(subnet);
+    // Create a pool.
+    auto pool = boost::make_shared<Pool4>(IOAddress("192.2.0.0"), 16);
+    subnet->addPool(pool);
+    // Select the FLQ allocator.
+    subnet->setAllocatorType("flq");
+    // Instantiate the allocator.
+    ASSERT_NO_THROW(subnet->createAllocators());
+    // Expect FLQ allocator.
+    EXPECT_TRUE(boost::dynamic_pointer_cast<FreeLeaseQueueAllocator>
+                (subnet->getAllocator(Lease::TYPE_V4)));
+    // Expect FLQ allocation state for the pool.
+    EXPECT_TRUE(boost::dynamic_pointer_cast<PoolFreeLeaseQueueAllocationState>
+                (pool->getAllocationState()));
+}
+
 // Tests for Subnet6
 
 TEST(Subnet6Test, constructor) {
@@ -1701,6 +1771,142 @@ TEST(Subnet6Test, rapidCommit) {
     EXPECT_FALSE(subnet.getRapidCommit());
 }
 
+// This test verifies that an iterative allocator and the corresponding
+// states are instantiated for a subnet.
+TEST(Subnet6Test, createAllocatorsIterative) {
+    // Create a subnet.
+    auto subnet = Subnet6::create(IOAddress("2001:db8:1::"), 56, 1, 2, 3, 4);
+    ASSERT_TRUE(subnet);
+    // NA pool.
+    auto pool = boost::make_shared<Pool6>(Lease::TYPE_NA, IOAddress("2001:db8:1:1::"), 112);
+    subnet->addPool(pool);
+    // TA pool.
+    auto ta_pool = boost::make_shared<Pool6>(Lease::TYPE_TA, IOAddress("2001:db8:1:2::"), 112);
+    subnet->addPool(ta_pool);
+    // PD pool.
+    auto pd_pool = boost::make_shared<Pool6>(Lease::TYPE_PD, IOAddress("3000::"), 112, 120);
+    subnet->addPool(pd_pool);
+    // Instantiate the allocators.
+    ASSERT_NO_THROW(subnet->createAllocators());
+    // Expect iterative allocator for NA.
+    EXPECT_TRUE(boost::dynamic_pointer_cast<IterativeAllocator>
+                (subnet->getAllocator(Lease::TYPE_NA)));
+    // Expect iterative allocator for TA.
+    EXPECT_TRUE(boost::dynamic_pointer_cast<IterativeAllocator>
+                (subnet->getAllocator(Lease::TYPE_TA)));
+    // Expect iterative allocator for PD.
+    EXPECT_TRUE(boost::dynamic_pointer_cast<IterativeAllocator>
+                (subnet->getAllocator(Lease::TYPE_PD)));
+    // Expect iterative allocation state for NA.
+    EXPECT_TRUE(boost::dynamic_pointer_cast<SubnetIterativeAllocationState>
+                (subnet->getAllocationState(Lease::TYPE_NA)));
+    // Expect iterative allocation state for TA.
+    EXPECT_TRUE(boost::dynamic_pointer_cast<SubnetIterativeAllocationState>
+                (subnet->getAllocationState(Lease::TYPE_TA)));
+    // Expect iterative allocation state for PD.
+    EXPECT_TRUE(boost::dynamic_pointer_cast<SubnetIterativeAllocationState>
+                (subnet->getAllocationState(Lease::TYPE_PD)));
+    // Expect iterative allocation state for the NA pool.
+    EXPECT_TRUE(boost::dynamic_pointer_cast<PoolIterativeAllocationState>
+                (pool->getAllocationState()));
+    // Expect iterative allocation state for the TA pool.
+    EXPECT_TRUE(boost::dynamic_pointer_cast<PoolIterativeAllocationState>
+                (pool->getAllocationState()));
+    // Expect iterative allocation state for the PD pool.
+    EXPECT_TRUE(boost::dynamic_pointer_cast<PoolIterativeAllocationState>
+                (pd_pool->getAllocationState()));
+}
+
+// This test verifies that a random allocator and the corresponding
+// states are instantiated for a subnet.
+TEST(Subnet6Test, createAllocatorsRandom) {
+    // Create a subnet.
+    auto subnet = Subnet6::create(IOAddress("2001:db8:1::"), 56, 1, 2, 3, 4);
+    ASSERT_TRUE(subnet);
+    // NA pool.
+    auto pool = boost::make_shared<Pool6>(Lease::TYPE_NA, IOAddress("2001:db8:1:1::"), 112);
+    subnet->addPool(pool);
+    // TA pool.
+    auto ta_pool = boost::make_shared<Pool6>(Lease::TYPE_TA, IOAddress("2001:db8:1:2::"), 112);
+    subnet->addPool(ta_pool);
+    // PD pool.
+    auto pd_pool = boost::make_shared<Pool6>(Lease::TYPE_PD, IOAddress("3000::"), 112, 120);
+    subnet->addPool(pd_pool);
+    // Select the random allocators.
+    subnet->setAllocatorType("random");
+    subnet->setPdAllocatorType("random");
+    // Instantiate the allocators.
+    ASSERT_NO_THROW(subnet->createAllocators());
+    // Expect random allocator for NA.
+    EXPECT_TRUE(boost::dynamic_pointer_cast<RandomAllocator>
+                (subnet->getAllocator(Lease::TYPE_NA)));
+    // Expect random allocator for TA.
+    EXPECT_TRUE(boost::dynamic_pointer_cast<RandomAllocator>
+                (subnet->getAllocator(Lease::TYPE_TA)));
+    // Expect random allocator for PD.
+    EXPECT_TRUE(boost::dynamic_pointer_cast<RandomAllocator>
+                (subnet->getAllocator(Lease::TYPE_PD)));
+    // Expect random allocation state for the NA pool.
+    EXPECT_TRUE(boost::dynamic_pointer_cast<PoolRandomAllocationState>
+                (pool->getAllocationState()));
+    // Expect random allocation state for the TA pool.
+    EXPECT_TRUE(boost::dynamic_pointer_cast<PoolRandomAllocationState>
+                (pool->getAllocationState()));
+    // Expect random allocation state for the PD pool.
+    EXPECT_TRUE(boost::dynamic_pointer_cast<PoolRandomAllocationState>
+                (pd_pool->getAllocationState()));
+}
+
+// This test verifies that a FLQ allocator and the corresponding
+// states are instantiated for a subnet.
+TEST(Subnet6Test, createAllocatorsFreeLeaseQueue) {
+    // Create a subnet.
+    auto subnet = Subnet6::create(IOAddress("2001:db8:1::"), 56, 1, 2, 3, 4);
+    ASSERT_TRUE(subnet);
+    // NA pool.
+    auto pool = boost::make_shared<Pool6>(Lease::TYPE_NA, IOAddress("2001:db8:1:1::"), 112);
+    subnet->addPool(pool);
+    // TA pool.
+    auto ta_pool = boost::make_shared<Pool6>(Lease::TYPE_TA, IOAddress("2001:db8:1:2::"), 112);
+    subnet->addPool(ta_pool);
+    // PD pool.
+    auto pd_pool = boost::make_shared<Pool6>(Lease::TYPE_PD, IOAddress("3000::"), 112, 120);
+    subnet->addPool(pd_pool);
+    // Select the random allocator for addresses.
+    subnet->setAllocatorType("random");
+    // Select the FLQ allocator for the prefix delegation.
+    subnet->setPdAllocatorType("flq");
+    // Instantiate the allocators.
+    ASSERT_NO_THROW(subnet->createAllocators());
+    // Expect random allocator for NA.
+    EXPECT_TRUE(boost::dynamic_pointer_cast<RandomAllocator>
+                (subnet->getAllocator(Lease::TYPE_NA)));
+    // Expect random allocator for TA.
+    EXPECT_TRUE(boost::dynamic_pointer_cast<RandomAllocator>
+                (subnet->getAllocator(Lease::TYPE_TA)));
+    // Expect FLQ allocator for PD.
+    EXPECT_TRUE(boost::dynamic_pointer_cast<FreeLeaseQueueAllocator>
+                (subnet->getAllocator(Lease::TYPE_PD)));
+    // Expect random allocation state for the NA pool.
+    EXPECT_TRUE(boost::dynamic_pointer_cast<PoolRandomAllocationState>
+                (pool->getAllocationState()));
+    // Expect random allocation state for the TA pool.
+    EXPECT_TRUE(boost::dynamic_pointer_cast<PoolRandomAllocationState>
+                (pool->getAllocationState()));
+    // Expect FLQ allocation state for the PD pool.
+    EXPECT_TRUE(boost::dynamic_pointer_cast<PoolFreeLeaseQueueAllocationState>
+                (pd_pool->getAllocationState()));
+}
+
+// Test that it is not allowed to use the FLQ allocator for the address pools.
+TEST(Subnet6Test, createAllocatorsFreeLeaseQueueNotAllowed) {
+    auto subnet = Subnet6::create(IOAddress("2001:db8:1::"), 56, 1, 2, 3, 4);
+    ASSERT_TRUE(subnet);
+
+    subnet->setAllocatorType("flq");
+    EXPECT_THROW(subnet->createAllocators(), BadValue);
+}
+
 // This test verifies that the IPv4 subnet can be fetched by id.
 TEST(SubnetFetcherTest, getSubnet4ById) {
     Subnet4Collection collection;