#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>
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);
}
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);
}
#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>
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
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
#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>
/// @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();
/// 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.
/// @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.
/// 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.
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.
#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>
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) {
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;