expiration_cfg->setHoldReclaimedTime(0);
}
+ try {
+ CfgMgr::instance().getStagingCfg()->getCfgSubnets4()->initAllocatorsAfterConfigure();
+ } catch (const std::exception& ex) {
+ ADD_FAILURE() << "Error initializing the allocators after configure: "
+ << ex.what();
+ }
+
try {
CfgMultiThreading::apply(CfgMgr::instance().getStagingCfg()->getDHCPMultiThreading());
} catch (const std::exception& ex) {
" ]"
" }"
" ]"
+ "}",
+
+// Configuration #21
+// - a shared network with two subnets
+// - first subnet uses the FLQ allocator
+// - second subnet uses the random allocator
+ "{"
+ " \"interfaces-config\": {"
+ " \"interfaces\": [ \"*\" ]"
+ " },"
+ " \"valid-lifetime\": 600,"
+ " \"shared-networks\": ["
+ " {"
+ " \"name\": \"frog\","
+ " \"relay\": {"
+ " \"ip-address\": \"192.3.5.6\""
+ " },"
+ " \"subnet4\": ["
+ " {"
+ " \"subnet\": \"192.0.2.0/24\","
+ " \"allocator\": \"flq\","
+ " \"pools\": ["
+ " {"
+ " \"pool\": \"192.0.2.1 - 192.0.2.10\""
+ " }"
+ " ]"
+ " },"
+ " {"
+ " \"subnet\": \"192.0.3.0/24\","
+ " \"allocator\": \"random\","
+ " \"pools\": ["
+ " {"
+ " \"pool\": \"192.0.3.1 - 192.0.3.10\""
+ " }"
+ " ]"
+ " }"
+ " ]"
+ " }"
+ " ]"
"}"
};
}
}
+// Test that different allocator types can be used within a shared network.
+// All available addresses should be assigned from the subnets belonging to
+// the shared network.
+TEST_F(Dhcpv4SharedNetworkTest, randomAndFlqAllocation) {
+ // Create the base client and server configuration.
+ Dhcp4Client client(Dhcp4Client::SELECTING);
+ configure(NETWORKS_CONFIG[21], *client.getServer());
+
+ // Record what addresses have been allocated.
+ std::set<std::string> allocated_set;
+
+ // Simulate allocations from different clients.
+ for (auto i = 0; i < 20; ++i) {
+ // Create a client from the base client.
+ Dhcp4Client next_client(client.getServer(), Dhcp4Client::SELECTING);
+ next_client.useRelay(true, IOAddress("192.3.5.6"), IOAddress("10.0.0.2"));
+ // Run 4-way exchange.
+ ASSERT_NO_THROW(next_client.doDORA());
+ // Make sure that the server responded.
+ ASSERT_TRUE(next_client.getContext().response_);
+ // Make sure that the server has responded with DHCPACK.
+ ASSERT_EQ(DHCPACK, static_cast<int>(next_client.getContext().response_->getType()));
+ // Make sure that the address is not zero.
+ ASSERT_FALSE(next_client.config_.lease_.addr_.isV4Zero());
+ // Remember allocated address uniqueness.
+ allocated_set.insert(next_client.config_.lease_.addr_.toText());
+ }
+ // Make sure that we have 20 distinct allocations.
+ ASSERT_EQ(20, allocated_set.size());
+}
+
} // end of anonymous namespace
expiration_cfg->setHoldReclaimedTime(0);
}
+ try {
+ CfgMgr::instance().getStagingCfg()->getCfgSubnets6()->initAllocatorsAfterConfigure();
+ } catch (const std::exception& ex) {
+ ADD_FAILURE() << "Error initializing the allocators after configure: "
+ << ex.what();
+ }
+
try {
CfgMultiThreading::apply(CfgMgr::instance().getStagingCfg()->getDHCPMultiThreading());
} catch (const std::exception& ex) {
" ]"
" }"
" ]"
- "}"
+ "}",
+// Configuration #23.
+// - a shared network with two subnets
+// - first subnet uses the FLQ allocator
+// - second subnet uses the random allocator
+ "{"
+ " \"shared-networks\": ["
+ " {"
+ " \"name\": \"frog\","
+ " \"interface\": \"eth1\","
+ " \"subnet6\": ["
+ " {"
+ " \"subnet\": \"2001:db8:1::/64\","
+ " \"pd-allocator\": \"flq\","
+ " \"pd-pools\": ["
+ " {"
+ " \"prefix\": \"2001:db8:1::\","
+ " \"prefix-len\": 64,"
+ " \"delegated-len\": 68"
+ " }"
+ " ]"
+ " },"
+ " {"
+ " \"subnet\": \"2001:db8:2::/64\","
+ " \"pd-allocator\": \"random\","
+ " \"pd-pools\": ["
+ " {"
+ " \"prefix\": \"2001:db8:2::\","
+ " \"prefix-len\": 64,"
+ " \"delegated-len\": 68"
+ " }"
+ " ]"
+ " }"
+ " ]"
+ " }"
+ " ]"
+ "}"
};
/// @Brief Test fixture class for DHCPv6 server using shared networks.
EXPECT_EQ(1, client2.getLeasesWithNonZeroLifetime().size());
}
+// Test that different allocator types can be used within a shared network.
+// All available prefixes should be delegated from the subnets belonging to
+// the shared network.
+TEST_F(Dhcpv6SharedNetworkTest, randomAndFlqAllocation) {
+ // Create the base client and server configuration.
+ Dhcp6Client client;
+ ASSERT_NO_FATAL_FAILURE(configure(NETWORKS_CONFIG[23], *client.getServer()));
+
+ // Record what prefixes have been allocated.
+ std::set<std::string> allocated_set;
+
+ // Simulate allocations from different clients.
+ for (auto i = 0; i < 32; ++i) {
+ // Create a client from the base client.
+ Dhcp6Client next_client(client.getServer());
+ next_client.setInterface("eth1");
+ next_client.requestPrefix();
+ // Run 4-way exchange.
+ ASSERT_NO_THROW(next_client.doSARR());
+ // Make sure that the server responded.
+ ASSERT_TRUE(next_client.getContext().response_);
+ auto leases = next_client.getLeasesByType(Lease::TYPE_PD);
+ ASSERT_EQ(1, leases.size());
+ // Make sure that the prefix is not zero.
+ ASSERT_FALSE(leases[0].addr_.isV6Zero());
+ // Remember the allocated prefix uniqueness.
+ allocated_set.insert(leases[0].addr_.toText());
+ }
+ // Make sure that we have 32 distinct allocations.
+ ASSERT_EQ(32, allocated_set.size());
+}
+
+
// Verify option processing precedence
// Order is global < class < shared-network < subnet < pools < host reservation
TEST_F(Dhcpv6SharedNetworkTest, precedenceGlobal) {
candidate = allocator->pickAddress(classes, ctx.duid_, hint);
}
+ // An allocator may return zero address when it has pools exhausted.
+ if (candidate.isV6Zero()) {
+ break;
+ }
+
// First check for reservation when it is the choice.
if (check_reservation_first && in_subnet && !out_of_pool) {
auto hosts = getIPv6Resrv(subnet->getID(), candidate);
client_id,
ctx.requested_address_);
+ // An allocator may return zero address when it has pools exhausted.
+ if (candidate.isV4Zero()) {
+ break;
+ }
+
if (exclude_first_last_24) {
// Exclude .0 and .255 addresses.
auto const& bytes = candidate.toBytes();