/// - Configuration:
/// - only addresses (no prefixes)
- /// - 4 subnets with:
- /// - 192.0.2.0/24 (all reservations enabled)
- /// - 192.0.3.0/24 (out-of-pool reservations)
- /// - 192.0.4.0/24 (reservations disabled)
+ /// - 5 subnets with:
+ /// - 192.0.1.0/24 (all reservations enabled)
+ /// - 192.0.2.0/24 (out-of-pool reservations)
+ /// - 192.0.3.0/24 (reservations disabled)
+ /// - 192.0.4.0/24 (global reservations)
/// - 192.0.5.0/24 (reservations not specified)
const char* hr_config =
"{ "
"\"rebind-timer\": 2000, "
"\"renew-timer\": 1000, "
"\"subnet4\": [ { "
+ " \"pools\": [ { \"pool\": \"192.0.1.0/24\" } ],"
+ " \"subnet\": \"192.0.1.0/24\", "
+ " \"reservation-mode\": \"all\""
+ " },"
+ " {"
" \"pools\": [ { \"pool\": \"192.0.2.0/24\" } ],"
" \"subnet\": \"192.0.2.0/24\", "
- " \"reservation-mode\": \"all\""
+ " \"reservation-mode\": \"out-of-pool\""
" },"
" {"
" \"pools\": [ { \"pool\": \"192.0.3.0/24\" } ],"
- " \"subnet\": \"192.0.3.0/24\", "
- " \"reservation-mode\": \"out-of-pool\""
+ " \"subnet\": \"192.0.4.0/24\", "
+ " \"reservation-mode\": \"disabled\""
" },"
" {"
" \"pools\": [ { \"pool\": \"192.0.4.0/24\" } ],"
" \"subnet\": \"192.0.4.0/24\", "
- " \"reservation-mode\": \"disabled\""
+ " \"reservation-mode\": \"global\""
" },"
" {"
" \"pools\": [ { \"pool\": \"192.0.5.0/24\" } ],"
// returned value should be 0 (success)
checkResult(result, 0);
- // Let's get all subnets and check that there are 4 of them.
+ // Let's get all subnets and check that there are 5 of them.
ConstCfgSubnets4Ptr subnets = CfgMgr::instance().getStagingCfg()->getCfgSubnets4();
ASSERT_TRUE(subnets);
const Subnet4Collection* subnet_col = subnets->getAll();
- ASSERT_EQ(4, subnet_col->size()); // We expect 4 subnets
+ ASSERT_EQ(5, subnet_col->size()); // We expect 5 subnets
// Let's check if the parsed subnets have correct HR modes.
// Subnet 1
Subnet4Ptr subnet;
- subnet = subnets->selectSubnet(IOAddress("192.0.2.1"));
+ subnet = subnets->selectSubnet(IOAddress("192.0.1.1"));
ASSERT_TRUE(subnet);
EXPECT_EQ(Network::HR_ALL, subnet->getHostReservationMode());
// Subnet 2
- subnet = subnets->selectSubnet(IOAddress("192.0.3.1"));
+ subnet = subnets->selectSubnet(IOAddress("192.0.2.1"));
ASSERT_TRUE(subnet);
EXPECT_EQ(Network::HR_OUT_OF_POOL, subnet->getHostReservationMode());
// Subnet 3
+ subnet = subnets->selectSubnet(IOAddress("192.0.3.1"));
+ ASSERT_TRUE(subnet);
+ EXPECT_EQ(Network::HR_DISABLED, subnet->getHostReservationMode());
+
+ // Subnet 4
subnet = subnets->selectSubnet(IOAddress("192.0.4.1"));
ASSERT_TRUE(subnet);
+ EXPECT_EQ(Network::HR_GLOBAL, subnet->getHostReservationMode());
+
+ // Subnet 5
+ subnet = subnets->selectSubnet(IOAddress("192.0.5.1"));
+ ASSERT_TRUE(subnet);
+ EXPECT_EQ(Network::HR_ALL, subnet->getHostReservationMode());
+}
+
+/// The goal of this test is to verify that Host Reservation modes can be
+/// specified on a per-subnet basis.
+TEST_F(Dhcp4ParserTest, hostReservationModesPerSubnet) {
+
+ /// - Configuration:
+ /// - only addresses (no prefixes)
+ /// - 6 subnets with:
+ /// - 192.0.1.0/24 (all reservations enabled)
+ /// - 192.0.2.0/24 (out-of-pool reservations)
+ /// - 192.0.3.0/24 (reservations disabled)
+ /// - 192.0.4.0/24 (global reservations)
+ /// - 192.0.5.0/24 (reservations not specified)
+ /// - 192.0.6.0/24 (global + all enabled)
+ const char* hr_config =
+ "{ "
+ "\"rebind-timer\": 2000, "
+ "\"renew-timer\": 1000, "
+ "\"subnet4\": [ { "
+ " \"pools\": [ { \"pool\": \"192.0.1.0/24\" } ],"
+ " \"subnet\": \"192.0.1.0/24\", "
+ " \"reservation-modes\": {"
+ " \"in-subnet\": True,"
+ " \"out-of-pool\": True"
+ " }"
+ " },"
+ " {"
+ " \"pools\": [ { \"pool\": \"192.0.2.0/24\" } ],"
+ " \"subnet\": \"192.0.2.0/24\", "
+ " \"reservation-modes\": {"
+ " \"out-of-pool\": True"
+ " }"
+ " },"
+ " {"
+ " \"pools\": [ { \"pool\": \"192.0.3.0/24\" } ],"
+ " \"subnet\": \"192.0.4.0/24\", "
+ " \"reservation-modes\": {"
+ " \"in-subnet\": False,"
+ " \"out-of-pool\": False,"
+ " \"global\": False"
+ " }"
+ " },"
+ " {"
+ " \"pools\": [ { \"pool\": \"192.0.4.0/24\" } ],"
+ " \"subnet\": \"192.0.4.0/24\", "
+ " \"reservation-modes\": {"
+ " \"global\": True"
+ " }"
+ " },"
+ " {"
+ " \"pools\": [ { \"pool\": \"192.0.5.0/24\" } ],"
+ " \"subnet\": \"192.0.5.0/24\""
+ " },"
+ " {"
+ " \"pools\": [ { \"pool\": \"192.0.6.0/24\" } ],"
+ " \"subnet\": \"192.0.6.0/24\", "
+ " \"reservation-modes\": {"
+ " \"in-subnet\": True,"
+ " \"out-of-pool\": True,"
+ " \"global\": True"
+ " }"
+ " } ],"
+ "\"valid-lifetime\": 4000 }";
+
+ ConstElementPtr json;
+ ASSERT_NO_THROW(json = parseDHCP4(hr_config));
+ extractConfig(hr_config);
+ ConstElementPtr result;
+ EXPECT_NO_THROW(result = configureDhcp4Server(*srv_, json));
+
+ // returned value should be 0 (success)
+ checkResult(result, 0);
+
+ // Let's get all subnets and check that there are 6 of them.
+ ConstCfgSubnets4Ptr subnets = CfgMgr::instance().getStagingCfg()->getCfgSubnets4();
+ ASSERT_TRUE(subnets);
+ const Subnet4Collection* subnet_col = subnets->getAll();
+ ASSERT_EQ(6, subnet_col->size()); // We expect 6 subnets
+
+ // Let's check if the parsed subnets have correct HR modes.
+
+ // Subnet 1
+ Subnet4Ptr subnet;
+ subnet = subnets->selectSubnet(IOAddress("192.0.1.1"));
+ ASSERT_TRUE(subnet);
+ EXPECT_EQ(Network::HR_ALL, subnet->getHostReservationMode());
+
+ // Subnet 2
+ subnet = subnets->selectSubnet(IOAddress("192.0.2.1"));
+ ASSERT_TRUE(subnet);
+ EXPECT_EQ(Network::HR_OUT_OF_POOL, subnet->getHostReservationMode());
+
+ // Subnet 3
+ subnet = subnets->selectSubnet(IOAddress("192.0.3.1"));
+ ASSERT_TRUE(subnet);
EXPECT_EQ(Network::HR_DISABLED, subnet->getHostReservationMode());
// Subnet 4
+ subnet = subnets->selectSubnet(IOAddress("192.0.4.1"));
+ ASSERT_TRUE(subnet);
+ EXPECT_EQ(Network::HR_GLOBAL, subnet->getHostReservationMode());
+
+ // Subnet 5
subnet = subnets->selectSubnet(IOAddress("192.0.5.1"));
ASSERT_TRUE(subnet);
EXPECT_EQ(Network::HR_ALL, subnet->getHostReservationMode());
+
+ // Subnet 6
+ subnet = subnets->selectSubnet(IOAddress("192.0.6.1"));
+ ASSERT_TRUE(subnet);
+ EXPECT_EQ(Network::HR_ALL|Network::HR_GLOBAL, subnet->getHostReservationMode());
}
/// The goal of this test is to verify that Host Reservation modes can be
EXPECT_EQ(Network::HR_OUT_OF_POOL, subnet->getHostReservationMode());
}
+/// The goal of this test is to verify that Host Reservation modes can be
+/// specified globally.
+TEST_F(Dhcp4ParserTest, hostReservationModesGlobal) {
+
+ /// - Configuration:
+ /// - only addresses (no prefixes)
+ /// - 2 subnets with :
+ /// - 192.0.2.0/24 (all reservations enabled)
+ /// - 192.0.3.0/24 (reservations not specified)
+ const char* hr_config =
+ "{ "
+ "\"rebind-timer\": 2000, "
+ "\"renew-timer\": 1000, "
+ "\"reservation-modes\": {"
+ " \"out-of-pool\": True"
+ " },"
+ "\"subnet4\": [ { "
+ " \"pools\": [ { \"pool\": \"192.0.2.0/24\" } ],"
+ " \"subnet\": \"192.0.2.0/24\", "
+ " \"reservation-modes\": {"
+ " \"in-subnet\": True,"
+ " \"out-of-pool\": True"
+ " }"
+ " },"
+ " {"
+ " \"pools\": [ { \"pool\": \"192.0.3.0/24\" } ],"
+ " \"subnet\": \"192.0.3.0/24\""
+ " } ],"
+ "\"valid-lifetime\": 4000 }";
+
+ ConstElementPtr json;
+ ASSERT_NO_THROW(json = parseDHCP4(hr_config));
+ extractConfig(hr_config);
+ ConstElementPtr result;
+ EXPECT_NO_THROW(result = configureDhcp4Server(*srv_, json));
+
+ // returned value should be 0 (success)
+ checkResult(result, 0);
+
+ // Let's get all subnets and check that there are 4 of them.
+ ConstCfgSubnets4Ptr subnets = CfgMgr::instance().getStagingCfg()->getCfgSubnets4();
+ ASSERT_TRUE(subnets);
+ const Subnet4Collection* subnet_col = subnets->getAll();
+ ASSERT_EQ(2, subnet_col->size()); // We expect 2 subnets
+
+ // Let's check if the parsed subnets have correct HR modes.
+
+ // Subnet 1
+ Subnet4Ptr subnet;
+ subnet = subnets->selectSubnet(IOAddress("192.0.2.1"));
+ ASSERT_TRUE(subnet);
+ // Reset the fetch global function to staging (vs current) config.
+ subnet->setFetchGlobalsFn([]() -> ConstElementPtr {
+ return (CfgMgr::instance().getStagingCfg()->getConfiguredGlobals());
+ });
+ EXPECT_EQ(Network::HR_ALL, subnet->getHostReservationMode());
+
+ // Subnet 2
+ subnet = subnets->selectSubnet(IOAddress("192.0.3.1"));
+ ASSERT_TRUE(subnet);
+ // Reset the fetch global function to staging (vs current) config.
+ subnet->setFetchGlobalsFn([]() -> ConstElementPtr {
+ return (CfgMgr::instance().getStagingCfg()->getConfiguredGlobals());
+ });
+ EXPECT_EQ(Network::HR_OUT_OF_POOL, subnet->getHostReservationMode());
+}
+
/// Check that the decline-probation-period has a default value when not
/// specified.
TEST_F(Dhcp4ParserTest, declineTimerDefault) {
" \"relay\": {\n"
" \"ip-address\": \"5.6.7.8\"\n"
" },\n"
- " \"reservation-mode\": \"out-of-pool\",\n"
+ " \"reservation-modes\": {"
+ " \"out-of-pool\": True"
+ " },"
" \"renew-timer\": 10,\n"
" \"rebind-timer\": 20,\n"
" \"valid-lifetime\": 40,\n"
" \"relay\": {\n"
" \"ip-address\": \"55.66.77.88\"\n"
" },\n"
- " \"reservation-mode\": \"disabled\"\n"
+ " \"reservation-modes\": {"
+ " \"global\": False"
+ " }"
" }\n"
" ]\n"
" },\n"
EXPECT_EQ(Network::HR_ALL, subnet->getHostReservationMode());
}
+/// The goal of this test is to verify that Host Reservation modes can be
+/// specified on a per-subnet basis.
+TEST_F(Dhcp6ParserTest, hostReservationModesPerSubnet) {
+
+ /// - Configuration:
+ /// - only addresses (no prefixes)
+ /// - 6 subnets with:
+ /// - 2001:db8:1::/64 (all reservations enabled)
+ /// - 2001:db8:2::/64 (out-of-pool reservations)
+ /// - 2001:db8:3::/64 (reservations disabled)
+ /// - 2001:db8:4::/64 (global reservations)
+ /// - 2001:db8:5::/64 (reservations not specified)
+ /// - 2001:db8:5::/64 (global + all enabled)
+ const char* HR_CONFIG =
+ "{"
+ "\"preferred-lifetime\": 3000,"
+ "\"rebind-timer\": 2000, "
+ "\"renew-timer\": 1000, "
+ "\"subnet6\": [ { "
+ " \"pools\": [ { \"pool\": \"2001:db8:1::/64\" } ],"
+ " \"subnet\": \"2001:db8:1::/48\", "
+ " \"reservation-modes\": {"
+ " \"in-subnet\": True,"
+ " \"out-of-pool\": True"
+ " }"
+ " },"
+ " {"
+ " \"pools\": [ { \"pool\": \"2001:db8:2::/64\" } ],"
+ " \"subnet\": \"2001:db8:2::/48\", "
+ " \"reservation-modes\": {"
+ " \"out-of-pool\": True"
+ " }"
+ " },"
+ " {"
+ " \"pools\": [ { \"pool\": \"2001:db8:3::/64\" } ],"
+ " \"subnet\": \"2001:db8:3::/48\", "
+ " \"reservation-modes\": {"
+ " \"in-subnet\": False,"
+ " \"out-of-pool\": False,"
+ " \"global\": False"
+ " }"
+ " },"
+ " {"
+ " \"pools\": [ { \"pool\": \"2001:db8:4::/64\" } ],"
+ " \"subnet\": \"2001:db8:4::/48\", "
+ " \"reservation-modes\": {"
+ " \"global\": True"
+ " }"
+ " },"
+ " {"
+ " \"pools\": [ { \"pool\": \"2001:db8:5::/64\" } ],"
+ " \"subnet\": \"2001:db8:5::/48\" "
+ " },"
+ " {"
+ " \"pools\": [ { \"pool\": \"2001:db8:6::/64\" } ],"
+ " \"subnet\": \"2001:db8:6::/48\", "
+ " \"reservation-modes\": {"
+ " \"in-subnet\": True,"
+ " \"out-of-pool\": True,"
+ " \"global\": True"
+ " }"
+ " } ],"
+ "\"valid-lifetime\": 4000 }";
+
+ ConstElementPtr json;
+ ASSERT_NO_THROW(json = parseDHCP6(HR_CONFIG));
+ extractConfig(HR_CONFIG);
+
+ ConstElementPtr status;
+ EXPECT_NO_THROW(status = configureDhcp6Server(srv_, json));
+
+ // returned value should be 0 (success)
+ checkResult(status, 0);
+ CfgMgr::instance().commit();
+
+ // Let's get all subnets and check that there are 6 of them.
+ ConstCfgSubnets6Ptr subnets = CfgMgr::instance().getCurrentCfg()->getCfgSubnets6();
+ ASSERT_TRUE(subnets);
+ const Subnet6Collection* subnet_col = subnets->getAll();
+ ASSERT_EQ(6, subnet_col->size()); // We expect 6 subnets
+
+ // Let's check if the parsed subnets have correct HR modes.
+
+ // Subnet 1
+ Subnet6Ptr subnet;
+ subnet = subnets->selectSubnet(IOAddress("2001:db8:1::1"));
+ ASSERT_TRUE(subnet);
+ EXPECT_EQ(Network::HR_ALL, subnet->getHostReservationMode());
+
+ // Subnet 2
+ subnet = subnets->selectSubnet(IOAddress("2001:db8:2::1"));
+ ASSERT_TRUE(subnet);
+ EXPECT_EQ(Network::HR_OUT_OF_POOL, subnet->getHostReservationMode());
+
+ // Subnet 3
+ subnet = subnets->selectSubnet(IOAddress("2001:db8:3::1"));
+ ASSERT_TRUE(subnet);
+ EXPECT_EQ(Network::HR_DISABLED, subnet->getHostReservationMode());
+
+ // Subnet 4
+ subnet = subnets->selectSubnet(IOAddress("2001:db8:4::1"));
+ ASSERT_TRUE(subnet);
+ EXPECT_EQ(Network::HR_GLOBAL, subnet->getHostReservationMode());
+
+ // Subnet 5
+ subnet = subnets->selectSubnet(IOAddress("2001:db8:5::1"));
+ ASSERT_TRUE(subnet);
+ EXPECT_EQ(Network::HR_ALL, subnet->getHostReservationMode());
+
+ // Subnet 6
+ subnet = subnets->selectSubnet(IOAddress("2001:db8:6::1"));
+ ASSERT_TRUE(subnet);
+ EXPECT_EQ(Network::HR_ALL|Network::HR_GLOBAL, subnet->getHostReservationMode());
+}
+
/// The goal of this test is to verify that Host Reservation modes can be
/// specified globally.
TEST_F(Dhcp6ParserTest, hostReservationGlobal) {
EXPECT_EQ(Network::HR_OUT_OF_POOL, subnet->getHostReservationMode());
}
+/// The goal of this test is to verify that Host Reservation modes can be
+/// specified globally.
+TEST_F(Dhcp6ParserTest, hostReservationModesGlobal) {
+
+ /// - Configuration:
+ /// - only addresses (no prefixes)
+ /// - 2 subnets with:
+ /// - 2001:db8:1::/64 (all reservations enabled)
+ /// - 2001:db8:2::/64 (reservations not specified)
+ const char* HR_CONFIG =
+ "{"
+ "\"preferred-lifetime\": 3000,"
+ "\"rebind-timer\": 2000, "
+ "\"renew-timer\": 1000, "
+ "\"reservation-modes\": {"
+ " \"out-of-pool\": True"
+ " },"
+ "\"subnet6\": [ { "
+ " \"pools\": [ { \"pool\": \"2001:db8:1::/64\" } ],"
+ " \"subnet\": \"2001:db8:1::/48\", "
+ " \"reservation-modes\": {"
+ " \"in-subnet\": True,"
+ " \"out-of-pool\": True"
+ " }"
+ " },"
+ " {"
+ " \"pools\": [ { \"pool\": \"2001:db8:2::/64\" } ],"
+ " \"subnet\": \"2001:db8:2::/48\" "
+ " } ],"
+ "\"valid-lifetime\": 4000 }";
+
+ ConstElementPtr json;
+ ASSERT_NO_THROW(json = parseDHCP6(HR_CONFIG));
+ extractConfig(HR_CONFIG);
+
+ ConstElementPtr status;
+ EXPECT_NO_THROW(status = configureDhcp6Server(srv_, json));
+
+ // returned value should be 0 (success)
+ checkResult(status, 0);
+ CfgMgr::instance().commit();
+
+ // Let's get all subnets and check that there are 2 of them.
+ ConstCfgSubnets6Ptr subnets = CfgMgr::instance().getCurrentCfg()->getCfgSubnets6();
+ ASSERT_TRUE(subnets);
+ const Subnet6Collection* subnet_col = subnets->getAll();
+ ASSERT_EQ(2, subnet_col->size()); // We expect 2 subnets
+
+ // Let's check if the parsed subnets have correct HR modes.
+
+ // Subnet 1
+ Subnet6Ptr subnet;
+ subnet = subnets->selectSubnet(IOAddress("2001:db8:1::1"));
+ ASSERT_TRUE(subnet);
+ EXPECT_EQ(Network::HR_ALL, subnet->getHostReservationMode());
+
+ // Subnet 2
+ subnet = subnets->selectSubnet(IOAddress("2001:db8:2::1"));
+ ASSERT_TRUE(subnet);
+ EXPECT_EQ(Network::HR_OUT_OF_POOL, subnet->getHostReservationMode());
+}
+
/// The goal of this test is to verify that configuration can include
/// Relay Supplied options (specified as numbers).
TEST_F(Dhcp6ParserTest, rsooNumbers) {
" \"ip-address\": \"1111::1\"\n"
" },\n"
" \"rapid-commit\": true,\n"
- " \"reservation-mode\": \"disabled\",\n"
+ " \"reservation-modes\": {"
+ " \"global\": False"
+ " }"
" \"subnet6\": [\n"
" { \n"
" \"subnet\": \"2001:db1::/48\",\n"
" \"max-valid-lifetime\": 500, \n"
" \"interface-id\": \"twotwo\",\n"
" \"rapid-commit\": true,\n"
- " \"reservation-mode\": \"out-of-pool\"\n"
+ " \"reservation-modes\": {"
+ " \"out-of-pool\": True"
+ " }"
" }\n"
" ]\n"
" },\n"
AllocEngine::ClientContext6::currentHost() const {
Subnet6Ptr subnet = host_subnet_ ? host_subnet_ : subnet_;
if (subnet) {
- SubnetID id = (subnet_->getHostReservationMode() == Network::HR_GLOBAL ?
+ SubnetID id = (subnet_->getHostReservationMode() & Network::HR_GLOBAL ?
SUBNET_ID_GLOBAL : subnet->getID());
auto host = hosts_.find(id);
ConstHostPtr
AllocEngine::ClientContext6::globalHost() const {
Subnet6Ptr subnet = host_subnet_ ? host_subnet_ : subnet_;
- if (subnet && subnet_->getHostReservationMode() == Network::HR_GLOBAL) {
+ if (subnet && (subnet_->getHostReservationMode() & Network::HR_GLOBAL)) {
auto host = hosts_.find(SUBNET_ID_GLOBAL);
if (host != hosts_.cend()) {
return (host->second);
SharedNetwork6Ptr network;
subnet->getSharedNetwork(network);
- if (subnet->getHostReservationMode() == Network::HR_GLOBAL) {
+ if (subnet->getHostReservationMode() & Network::HR_GLOBAL) {
ConstHostPtr ghost = findGlobalReservation(ctx);
if (ghost) {
ctx.hosts_[SUBNET_ID_GLOBAL] = ghost;
// @todo In theory, to support global as part of HR_ALL,
// we would just keep going, instead of returning.
- return;
+ if (subnet->getHostReservationMode() == Network::HR_GLOBAL) {
+ return;
+ }
}
}
}
// First check for reservation when it is the choice.
- if (check_reservation_first && (hr_mode == Network::HR_ALL)) {
+ if (check_reservation_first && (hr_mode & Network::HR_IN_SUBNET)) {
auto hosts = getIPv6Resrv(subnet->getID(), candidate);
if (!hosts.empty()) {
// Don't allocate.
/// In-pool reservations: Check if this address is reserved for someone
/// else. There is no need to check for whom it is reserved, because if
/// it has been reserved for us we would have already allocated a lease.
- if (!check_reservation_first && (hr_mode == Network::HR_ALL)) {
+ if (!check_reservation_first && (hr_mode & Network::HR_IN_SUBNET)) {
auto hosts = getIPv6Resrv(subnet->getID(), candidate);
if (!hosts.empty()) {
// Don't allocate.
// allocation attempts.
} else if (existing->expired()) {
// Make sure it's not reserved.
- if (!check_reservation_first && (hr_mode == Network::HR_ALL)) {
+ if (!check_reservation_first && (hr_mode & Network::HR_IN_SUBNET)) {
auto hosts = getIPv6Resrv(subnet->getID(), candidate);
if (!hosts.empty()) {
// Don't allocate.
ConstHostPtr
AllocEngine::ClientContext4::currentHost() const {
if (subnet_) {
- SubnetID id = (subnet_->getHostReservationMode() == Network::HR_GLOBAL ?
+ SubnetID id = (subnet_->getHostReservationMode() & Network::HR_GLOBAL ?
SUBNET_ID_GLOBAL : subnet_->getID());
auto host = hosts_.find(id);
ConstHostPtr
AllocEngine::ClientContext4::globalHost() const {
- if (subnet_ && subnet_->getHostReservationMode() == Network::HR_GLOBAL) {
+ if (subnet_ && (subnet_->getHostReservationMode() & Network::HR_GLOBAL)) {
auto host = hosts_.find(SUBNET_ID_GLOBAL);
if (host != hosts_.cend()) {
return (host->second);
SharedNetwork4Ptr network;
subnet->getSharedNetwork(network);
- if (subnet->getHostReservationMode() == Network::HR_GLOBAL) {
+ if (subnet->getHostReservationMode() & Network::HR_GLOBAL) {
ConstHostPtr ghost = findGlobalReservation(ctx);
if (ghost) {
ctx.hosts_[SUBNET_ID_GLOBAL] = ghost;
util::Optional<bool> hr_mode_global;
getGlobalProperty(hr_mode_global, "reservation-modes.global");
if (!hr_mode_global.unspecified()) {
- flags |= Network::HR_GLOBAL;
+ if (hr_mode_global.get()) {
+ flags |= Network::HR_GLOBAL;
+ }
found = true;
}
util::Optional<bool> hr_mode_in_subnet;
getGlobalProperty(hr_mode_in_subnet, "reservation-modes.in-subnet");
if (!hr_mode_in_subnet.unspecified()) {
- flags |= Network::HR_IN_SUBNET;
+ if (hr_mode_in_subnet.get()) {
+ flags |= Network::HR_IN_SUBNET;
+ }
found = true;
}
util::Optional<bool> hr_mode_out_of_pool;
getGlobalProperty(hr_mode_out_of_pool, "reservation-modes.out-of-pool");
if (!hr_mode_out_of_pool.unspecified()) {
- flags |= Network::HR_OUT_OF_POOL;
+ if (hr_mode_out_of_pool.get()) {
+ flags |= Network::HR_OUT_OF_POOL;
+ }
found = true;
}
if (found) {
return (false);
}
-Subnet4Ptr
-SharedNetwork4::subnetsAllHRGlobal() const {
- for (auto subnet : *getAllSubnets()) {
- if (subnet->getHostReservationMode() != Network::HR_GLOBAL) {
- return (subnet);
- }
- }
- return (Subnet4Ptr());
-}
-
ElementPtr
SharedNetwork4::toElement() const {
ElementPtr map = Network4::toElement();
return (Impl::getPreferredSubnet(subnets_, selected_subnet, lease_type));
}
-Subnet6Ptr
-SharedNetwork6::subnetsAllHRGlobal() const {
- for (auto subnet : *getAllSubnets()) {
- if (subnet->getHostReservationMode() != Network::HR_GLOBAL) {
- return (subnet);
- }
- }
- return (Subnet6Ptr());
-}
-
ElementPtr
SharedNetwork6::toElement() const {
ElementPtr map = Network6::toElement();
bool subnetsIncludeMatchClientId(const Subnet4Ptr& first_subnet,
const ClientClasses& client_classes);
- /// @brief Check if the shared network includes a subnet with
- /// not global host reservation mode.
- ///
- /// @return First subnet which has not a global host reservation mode.
- Subnet4Ptr subnetsAllHRGlobal() const;
-
/// @brief Unparses shared network object.
///
/// @return A pointer to unparsed shared network configuration.
Subnet6Ptr getPreferredSubnet(const Subnet6Ptr& selected_subnet,
const Lease::Type& lease_type) const;
- /// @brief Check if the shared network includes a subnet with
- /// not global host reservation mode.
- ///
- /// @return First subnet which has not a global host reservation mode.
- Subnet6Ptr subnetsAllHRGlobal() const;
-
/// @brief Unparses shared network object.
///
/// @return A pointer to unparsed shared network configuration.
globals_->set("cache-max-age", Element::create(20));
globals_->set("ddns-update-on-renew", Element::create(true));
globals_->set("ddns-use-conflict-resolution", Element::create(true));
+ auto reservation_modes = Element::createMap();
+ reservation_modes->set("global", Element::create(false));
+ reservation_modes->set("in-subnet", Element::create(false));
+ reservation_modes->set("out-of-pool", Element::create(false));
+ globals_->set("reservation-modes", reservation_modes);
// For each parameter for which inheritance is supported run
// the test that checks if the values are inherited properly.
Network::HR_OUT_OF_POOL,
Network::HR_DISABLED);
}
+ {
+ SCOPED_TRACE("reservation-modes");
+ testNetworkInheritance<TestNetwork>(&Network::getHostReservationMode,
+ &Network::setHostReservationMode,
+ Network::HR_OUT_OF_POOL,
+ Network::HR_DISABLED);
+ }
{
SCOPED_TRACE("calculate-tee-times");
testNetworkInheritance<TestNetwork>(&Network::getCalculateTeeTimes,
" \"rebind-timer\": 199,"
" \"relay\": { \"ip-addresses\": [ \"10.1.1.1\" ] },"
" \"renew-timer\": 99,"
- " \"reservation-mode\": \"out-of-pool\","
+ " \"reservation-modes\": {\"out-of-pool\": True},"
" \"server-hostname\": \"example.org\","
" \"require-client-classes\": [ \"runner\" ],"
" \"user-context\": { \"comment\": \"example\" },"
" \"relay\": { \"ip-addresses\": [ \"2001:db8:1::1\" ] },"
" \"renew-timer\": 99,"
" \"require-client-classes\": [ \"runner\" ],"
- " \"reservation-mode\": \"out-of-pool\","
+ " \"reservation-modes\": {\"out-of-pool\": True},"
" \"user-context\": { },"
" \"valid-lifetime\": 399,"
" \"min-valid-lifetime\": 299,"
EXPECT_TRUE(SharedNetwork4::subnetsIncludeMatchClientId(subnet1, classes));
}
-// This test verifies that subnetsAllHRGlobal() works as expected.
-TEST(SharedNetwork4Test, subnetsAllHRGlobal) {
- SharedNetwork4Ptr network(new SharedNetwork4("frog"));
- Subnet4Ptr bad;
-
- // Empty shared network is right.
- ASSERT_NO_THROW(bad = network->subnetsAllHRGlobal());
- EXPECT_FALSE(bad);
-
- // Create a subnet and add it to the shared network.
- Subnet4Ptr subnet(new Subnet4(IOAddress("10.0.0.0"), 8, 10, 20, 30,
- SubnetID(1)));
- ASSERT_NO_THROW(network->add(subnet));
-
- // Default host reservation mode is ALL.
- bad.reset();
- ASSERT_NO_THROW(bad = network->subnetsAllHRGlobal());
- ASSERT_TRUE(bad);
- EXPECT_EQ(1, bad->getID());
- EXPECT_EQ("10.0.0.0/8", bad->toText());
-
- // Set the HR mode to global.
- subnet->setHostReservationMode(Network::HR_GLOBAL);
-
- // Now the shared network is all global.
- bad.reset();
- ASSERT_NO_THROW(bad = network->subnetsAllHRGlobal());
- EXPECT_FALSE(bad);
-}
-
// This test verifies operations on the network's relay list
TEST(SharedNetwork4Test, relayInfoList) {
SharedNetwork4Ptr network(new SharedNetwork4("frog"));
EXPECT_EQ(subnet3->getID(), preferred->getID());
}
-// This test verifies that subnetsAllHRGlobal() works as expected.
-TEST(SharedNetwork6Test, subnetsAllHRGlobal) {
- SharedNetwork6Ptr network(new SharedNetwork6("frog"));
- Subnet6Ptr bad;
-
- // Empty shared network is right.
- ASSERT_NO_THROW(bad = network->subnetsAllHRGlobal());
- EXPECT_FALSE(bad);
-
- // Create a subnet and add it to the shared network.
- Subnet6Ptr subnet(new Subnet6(IOAddress("2001:db8:1::"), 64, 10, 20, 30,
- 40, SubnetID(1)));
- ASSERT_NO_THROW(network->add(subnet));
-
- // Default host reservation mode is ALL.
- bad.reset();
- ASSERT_NO_THROW(bad = network->subnetsAllHRGlobal());
- ASSERT_TRUE(bad);
- EXPECT_EQ(1, bad->getID());
- EXPECT_EQ("2001:db8:1::/64", bad->toText());
-
- // Set the HR mode to global.
- subnet->setHostReservationMode(Network::HR_GLOBAL);
-
- // Now the shared network is all global.
- bad.reset();
- ASSERT_NO_THROW(bad = network->subnetsAllHRGlobal());
- EXPECT_FALSE(bad);
-}
-
// This test verifies operations on the network's relay list
TEST(SharedNetwork6Test, relayInfoList) {
SharedNetwork6Ptr network(new SharedNetwork6("frog"));