]> git.ipfire.org Git - thirdparty/kea.git/commitdiff
[#1405] updated unittests
authorRazvan Becheriu <razvan@isc.org>
Fri, 9 Oct 2020 15:39:58 +0000 (18:39 +0300)
committerRazvan Becheriu <razvan@isc.org>
Wed, 18 Nov 2020 13:55:22 +0000 (15:55 +0200)
src/bin/dhcp4/tests/config_parser_unittest.cc
src/bin/dhcp6/tests/config_parser_unittest.cc
src/lib/dhcpsrv/alloc_engine.cc
src/lib/dhcpsrv/network.h
src/lib/dhcpsrv/shared_network.cc
src/lib/dhcpsrv/shared_network.h
src/lib/dhcpsrv/tests/network_unittest.cc
src/lib/dhcpsrv/tests/shared_network_parser_unittest.cc
src/lib/dhcpsrv/tests/shared_network_unittest.cc

index e9c2f6c232456d0952c49c705226a4dc5a81efbd..6900615e0360f0bc27f80dff36d888fcbdcd7d35 100644 (file)
@@ -5286,29 +5286,35 @@ TEST_F(Dhcp4ParserTest, hostReservationPerSubnet) {
 
     /// - 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\" } ],"
@@ -5325,34 +5331,151 @@ TEST_F(Dhcp4ParserTest, hostReservationPerSubnet) {
     // 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
@@ -5417,6 +5540,73 @@ TEST_F(Dhcp4ParserTest, 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(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) {
@@ -6271,7 +6461,9 @@ TEST_F(Dhcp4ParserTest, sharedNetworksDerive) {
         "    \"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"
@@ -6297,7 +6489,9 @@ TEST_F(Dhcp4ParserTest, sharedNetworksDerive) {
         "        \"relay\": {\n"
         "            \"ip-address\": \"55.66.77.88\"\n"
         "        },\n"
-        "        \"reservation-mode\": \"disabled\"\n"
+        "        \"reservation-modes\": {"
+        "            \"global\": False"
+        "         }"
         "    }\n"
         "    ]\n"
         " },\n"
index f68c2e3251029279c3b8c9ea2b0ddd2f156fcdda..61755958ec530f55300585006fbcec9a56afeb9b 100644 (file)
@@ -5738,6 +5738,121 @@ TEST_F(Dhcp6ParserTest, hostReservationPerSubnet) {
     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) {
@@ -5795,6 +5910,68 @@ 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) {
@@ -6714,7 +6891,9 @@ TEST_F(Dhcp6ParserTest, sharedNetworksDerive) {
         "        \"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"
@@ -6736,7 +6915,9 @@ TEST_F(Dhcp6ParserTest, sharedNetworksDerive) {
         "        \"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"
index 6ea19bb024aa5ed7b2f413fe4e36554a67c8277b..17411ff4f9361a06ff3cdafbf79db69d68cbaa1e 100644 (file)
@@ -536,7 +536,7 @@ ConstHostPtr
 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);
@@ -551,7 +551,7 @@ AllocEngine::ClientContext6::currentHost() const {
 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);
@@ -599,14 +599,16 @@ void AllocEngine::findReservation(ClientContext6& ctx) {
     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;
+            }
         }
     }
 
@@ -1072,7 +1074,7 @@ AllocEngine::allocateUnreservedLeases6(ClientContext6& ctx) {
             }
 
             // 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.
@@ -1097,7 +1099,7 @@ AllocEngine::allocateUnreservedLeases6(ClientContext6& ctx) {
                 /// 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.
@@ -1129,7 +1131,7 @@ AllocEngine::allocateUnreservedLeases6(ClientContext6& ctx) {
                 // 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.
@@ -3211,7 +3213,7 @@ AllocEngine::ClientContext4::ClientContext4(const Subnet4Ptr& subnet,
 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);
@@ -3224,7 +3226,7 @@ AllocEngine::ClientContext4::currentHost() const {
 
 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);
@@ -3311,7 +3313,7 @@ AllocEngine::findReservation(ClientContext4& ctx) {
     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;
index 95cb0465a1b6bde16ecb8f6a30dc0ef9a07f9c7a..75046175c4de15d1b4e9f2b46ae69a0a2d83c4b4 100644 (file)
@@ -451,19 +451,25 @@ public:
                 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) {
index cc495b4154f9cd14988757f4fdca9633b35349c9..3d80c3c656146e34cc9a97d3894ca7853896e6c2 100644 (file)
@@ -399,16 +399,6 @@ SharedNetwork4::subnetsIncludeMatchClientId(const Subnet4Ptr& first_subnet,
     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();
@@ -498,16 +488,6 @@ SharedNetwork6::getPreferredSubnet(const Subnet6Ptr& selected_subnet,
     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();
index e463033ed4dd8ba9ec6d7bebe59d083ed4843ace..9dd939cbd87750698460f390f79a252268180d8e 100644 (file)
@@ -195,12 +195,6 @@ public:
     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.
@@ -399,12 +393,6 @@ public:
     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.
index a04ac3048516072e29c5fd202d80970c73a03bf9..c94f30f3d7b58d8402a6b0926434686da819fd6a 100644 (file)
@@ -185,6 +185,11 @@ TEST_F(NetworkTest, inheritanceSupport4) {
     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.
@@ -217,6 +222,13 @@ TEST_F(NetworkTest, inheritanceSupport4) {
                                             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,
index dc17c8a626083e17d3e0eaa0326e298cd6531a1c..f3d0b8f13d27c3543ba08e99f16df585742c2718 100644 (file)
@@ -128,7 +128,7 @@ public:
                 "    \"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\" },"
@@ -549,7 +549,7 @@ public:
                 "    \"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,"
index 03864b8c735d6531df4303a3ac4f0e8b4acd6a67..a1f6c30e4cafd29a6d076eb2a20004b2aec27bd5 100644 (file)
@@ -576,36 +576,6 @@ TEST(SharedNetwork4Test, subnetsIncludeMatchClientId) {
     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"));
@@ -1298,36 +1268,6 @@ TEST(SharedNetwork6Test, getPreferredSubnetMultiThreading) {
     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"));