]> git.ipfire.org Git - thirdparty/kea.git/commitdiff
[268-reservation-mode-is-not-global] Updated code for global reservation mode
authorFrancis Dupont <fdupont@isc.org>
Fri, 16 Nov 2018 22:09:31 +0000 (23:09 +0100)
committerFrancis Dupont <fdupont@isc.org>
Tue, 20 Nov 2018 18:00:41 +0000 (19:00 +0100)
12 files changed:
src/bin/dhcp4/dhcp4_lexer.ll
src/bin/dhcp4/dhcp4_parser.yy
src/bin/dhcp4/json_config_parser.cc
src/bin/dhcp4/parser_context.h
src/bin/dhcp4/tests/config_parser_unittest.cc
src/bin/dhcp6/dhcp6_lexer.ll
src/bin/dhcp6/dhcp6_parser.yy
src/bin/dhcp6/json_config_parser.cc
src/bin/dhcp6/parser_context.h
src/bin/dhcp6/tests/config_parser_unittest.cc
src/lib/dhcpsrv/parsers/simple_parser4.cc
src/lib/dhcpsrv/parsers/simple_parser6.cc

index c4b5c26f834911632bad83e4b34cec7bfa8a4100..314ca284aece6f8837fa0a8b4a8204474d5bbd71 100644 (file)
@@ -766,6 +766,7 @@ ControlCharacterFill            [^"\\]|\\{JSONEscapeSequence}
 
 \"reservation-mode\" {
     switch(driver.ctx_) {
+    case isc::dhcp::Parser4Context::DHCP4:
     case isc::dhcp::Parser4Context::SUBNET4:
     case isc::dhcp::Parser4Context::SHARED_NETWORK:
         return isc::dhcp::Dhcp4Parser::make_RESERVATION_MODE(driver.loc_);
index a3add7ff8538ba5e027ac0012c54c6d5055d39ce..0a03e7eba76f8e7f46176ed9b5595f4179e8ef4c 100644 (file)
@@ -464,6 +464,7 @@ global_param: valid_lifetime
             | reservations
             | config_control
             | server_tag
+            | reservation_mode
             | unknown_map_entry
             ;
 
index 913ff50a23a413ccf6f35293da64a1d1e7741f11..fcaaa75b00e90ee594477c68347cd9f66b78c0f3 100644 (file)
@@ -545,7 +545,8 @@ configureDhcp4Server(Dhcpv4Srv& server, isc::data::ConstElementPtr config_set,
                  (config_pair.first == "next-server") ||
                  (config_pair.first == "server-hostname") ||
                  (config_pair.first == "boot-file-name") ||
-                 (config_pair.first == "server-tag")) {
+                 (config_pair.first == "server-tag") ||
+                 (config_pair.first == "reservation-mode")) {
                 continue;
             }
 
index 85f262e0126044c64210f9cc8470b8b0d3fa6f13..a9a35ea2c2ca8d8a9ca9beb8a611d1c4302ddbfc 100644 (file)
@@ -244,7 +244,7 @@ public:
         /// Used while parsing shared-networks structures.
         SHARED_NETWORK,
 
-        /// Used while parsing Dhcp4/Subnet4/reservation-mode.
+        /// Used while parsing Dhcp4/reservation-mode.
         RESERVATION_MODE,
 
         /// Used while parsing Dhcp4/option-def structures.
index 2b050c0bfd3d99aa5d88af6d45df2ac8c47de136..f3d5e0225806ebd8def51590033b0d9800eb12a4 100644 (file)
@@ -4929,6 +4929,60 @@ TEST_F(Dhcp4ParserTest, hostReservationPerSubnet) {
     EXPECT_EQ(Network::HR_ALL, subnet->getHostReservationMode());
 }
 
+/// The goal of this test is to verify that Host Reservation modes can be
+/// specified globally.
+TEST_F(Dhcp4ParserTest, hostReservationGlobal) {
+
+    /// - 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-mode\": \"out-of-pool\", "
+        "\"subnet4\": [ { "
+        "    \"pools\": [ { \"pool\": \"192.0.2.0/24\" } ],"
+        "    \"subnet\": \"192.0.2.0/24\", "
+        "    \"reservation-mode\": \"all\""
+        " },"
+        " {"
+        "    \"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);
+    EXPECT_EQ(Network::HR_ALL, subnet->getHostReservationMode());
+
+    // Subnet 2
+    subnet = subnets->selectSubnet(IOAddress("192.0.3.1"));
+    ASSERT_TRUE(subnet);
+    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) {
index dd9d7892083355fe6dfc09003334d8860f0de4de..0cb1a73fdba14f50c8167e1ee40200a9101d0ccb 100644 (file)
@@ -1039,6 +1039,7 @@ ControlCharacterFill            [^"\\]|\\{JSONEscapeSequence}
 
 \"reservation-mode\" {
     switch(driver.ctx_) {
+    case isc::dhcp::Parser6Context::DHCP6:
     case isc::dhcp::Parser6Context::SUBNET6:
     case isc::dhcp::Parser6Context::SHARED_NETWORK:
         return isc::dhcp::Dhcp6Parser::make_RESERVATION_MODE(driver.loc_);
index 1b88046c0a60578ea30d0ad9effbd67e91d3f6ba..be817255bfcef19a5c4598bebb88bd07a63608bc 100644 (file)
@@ -465,6 +465,7 @@ global_param: preferred_lifetime
             | reservations
             | config_control
             | server_tag
+            | reservation_mode
             | unknown_map_entry
             ;
 
index 3ff82c89bb82a3957f30a8fdb00936e8c46e951b..555b3500c99a165ef5e6c2e902772f00f67ae409 100644 (file)
@@ -637,7 +637,8 @@ configureDhcp6Server(Dhcpv6Srv& server, isc::data::ConstElementPtr config_set,
                  (config_pair.first == "decline-probation-period") ||
                  (config_pair.first == "dhcp4o6-port") ||
                  (config_pair.first == "user-context") ||
-                 (config_pair.first == "server-tag")) {
+                 (config_pair.first == "server-tag") ||
+                 (config_pair.first == "reservation-mode")) {
                 continue;
             }
 
index 27953b9f37241d2d65ce8a015c23dc1f5a30d289..9cec79b29ab0dd38f4c7ab2bf885b0046722c7f9 100644 (file)
@@ -245,7 +245,7 @@ public:
         /// Used while parsing shared-networks structures.
         SHARED_NETWORK,
 
-        /// Used while parsing Dhcp6/Subnet6/reservation-mode.
+        /// Used while parsing Dhcp6/reservation-mode.
         RESERVATION_MODE,
 
         /// Used while parsing Dhcp6/option-def structures.
index 4888c627d82c3f7b0f22b92aee327a0b565dac05..646f5c3975a2c4bc6b52973df4d0378cb93f533b 100644 (file)
@@ -5184,11 +5184,12 @@ TEST_F(Dhcp6ParserTest, hostReservationPerSubnet) {
 
     /// - Configuration:
     ///   - only addresses (no prefixes)
-    ///   - 4 subnets with:
+    ///   - 5 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:3::/64 (reservations not specified)
+    ///       - 2001:db8:4::/64 (global reservations)
+    ///       - 2001:db8:5::/64 (reservations not specified)
     const char* HR_CONFIG =
         "{"
         "\"preferred-lifetime\": 3000,"
@@ -5231,11 +5232,11 @@ TEST_F(Dhcp6ParserTest, hostReservationPerSubnet) {
     checkResult(status, 0);
     CfgMgr::instance().commit();
 
-    // 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.
     ConstCfgSubnets6Ptr subnets = CfgMgr::instance().getCurrentCfg()->getCfgSubnets6();
     ASSERT_TRUE(subnets);
     const Subnet6Collection* subnet_col = subnets->getAll();
-    ASSERT_EQ(5, 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.
 
@@ -5266,6 +5267,63 @@ 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 globally.
+TEST_F(Dhcp6ParserTest, hostReservationGlobal) {
+
+    /// - 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-mode\": \"out-of-pool\", "
+        "\"subnet6\": [ { "
+        "    \"pools\": [ { \"pool\": \"2001:db8:1::/64\" } ],"
+        "    \"subnet\": \"2001:db8:1::/48\", "
+        "    \"reservation-mode\": \"all\""
+        " },"
+        " {"
+        "    \"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) {
index b6a356397a755dd8e2b899d8bb2d54a9a616bbf4..eb83fc539d139231f6ff7570f437c6379298adca 100644 (file)
@@ -67,7 +67,8 @@ const SimpleDefaults SimpleParser4::GLOBAL4_DEFAULTS = {
     { "next-server",              Element::string,  "0.0.0.0" },
     { "server-hostname",          Element::string,  "" },
     { "boot-file-name",           Element::string,  "" },
-    { "server-tag",               Element::string,  "" }
+    { "server-tag",               Element::string,  "" },
+    { "reservation-mode",         Element::string,  "all" }
 };
 
 /// @brief This table defines default values for each IPv4 subnet.
@@ -81,7 +82,6 @@ const SimpleDefaults SimpleParser4::SUBNET4_DEFAULTS = {
     { "id",               Element::integer, "0" }, // 0 means autogenerate
     { "interface",        Element::string,  "" },
     { "client-class",     Element::string,  "" },
-    { "reservation-mode", Element::string,  "all" },
     { "4o6-interface",    Element::string,  "" },
     { "4o6-interface-id", Element::string,  "" },
     { "4o6-subnet",       Element::string,  "" },
@@ -103,8 +103,7 @@ const SimpleDefaults SimpleParser4::SHARED_SUBNET4_DEFAULTS = {
 /// @brief This table defines default values for each IPv4 shared network.
 const SimpleDefaults SimpleParser4::SHARED_NETWORK4_DEFAULTS = {
     { "client-class",     Element::string, "" },
-    { "interface",        Element::string, "" },
-    { "reservation-mode", Element::string, "all" }
+    { "interface",        Element::string, "" }
 };
 
 /// @brief This table defines default values for interfaces for DHCPv4.
index 8f4c45b1e2c876d0e31326ea5f762cf0cc4b2fc6..dbb2b463b1bb16b89421ad1474f19589dacb78f6 100644 (file)
@@ -63,7 +63,8 @@ const SimpleDefaults SimpleParser6::GLOBAL6_DEFAULTS = {
     { "valid-lifetime",           Element::integer, "7200" },
     { "decline-probation-period", Element::integer, "86400" }, // 24h
     { "dhcp4o6-port",             Element::integer, "0" },
-    { "server-tag",               Element::string, "" }
+    { "server-tag",               Element::string,  "" },
+    { "reservation-mode",         Element::string,  "all" }
 };
 
 /// @brief This table defines default values for each IPv6 subnet.
@@ -71,9 +72,8 @@ const SimpleDefaults SimpleParser6::SUBNET6_DEFAULTS = {
     { "id",               Element::integer, "0" }, // 0 means autogenerate
     { "interface",        Element::string,  "" },
     { "client-class",     Element::string,  "" },
-    { "reservation-mode", Element::string,  "all" },
     { "rapid-commit",     Element::boolean, "false" }, // rapid-commit disabled by default
-    { "interface-id",     Element::string,  "" },
+    { "interface-id",     Element::string,  "" }
 };
 
 /// @brief This table defines default values for each IPv6 subnet.
@@ -84,9 +84,8 @@ const SimpleDefaults SimpleParser6::SHARED_SUBNET6_DEFAULTS = {
 /// @brief This table defines default values for each IPv6 shared network.
 const SimpleDefaults SimpleParser6::SHARED_NETWORK6_DEFAULTS = {
     { "client-class",     Element::string,  "" },
-    { "interface",        Element::string, "" },
+    { "interface",        Element::string,  "" },
     { "interface-id",     Element::string,  "" },
-    { "reservation-mode", Element::string, "all" },
     { "rapid-commit",     Element::boolean, "false" } // rapid-commit disabled by default
 };