]> git.ipfire.org Git - thirdparty/kea.git/commitdiff
[#3755] backport #3578 to 2.6.2
authorRazvan Becheriu <razvan@isc.org>
Tue, 4 Mar 2025 21:10:56 +0000 (23:10 +0200)
committerRazvan Becheriu <razvan@isc.org>
Wed, 5 Mar 2025 07:38:05 +0000 (09:38 +0200)
15 files changed:
src/bin/agent/parser_context.cc
src/bin/d2/parser_context.cc
src/bin/dhcp4/parser_context.cc
src/bin/dhcp4/tests/config_parser_unittest.cc
src/bin/dhcp4/tests/get_config_unittest.cc
src/bin/dhcp4/tests/get_config_unittest.cc.skel
src/bin/dhcp4/tests/kea_controller_unittest.cc
src/bin/dhcp6/parser_context.cc
src/bin/dhcp6/tests/config_parser_unittest.cc
src/bin/dhcp6/tests/get_config_unittest.cc
src/bin/dhcp6/tests/get_config_unittest.cc.skel
src/bin/dhcp6/tests/kea_controller_unittest.cc
src/bin/netconf/parser_context.cc
src/lib/database/database_connection.cc
src/lib/database/tests/database_connection_unittest.cc

index 7c18e034e3cba783577ec0c88ca5230a3ab27609..675fda3db67e3b89d6517eced3f8ed66be400883 100644 (file)
@@ -57,15 +57,14 @@ ParserContext::parseCommon() {
             isc_throw(ParseError, "Parser abort");
         }
         scanEnd();
-    }
-    catch (...) {
+    } catch (...) {
         scanEnd();
         throw;
     }
     if (stack_.size() == 1) {
         return (stack_[0]);
     } else {
-        isc_throw(ParseError, "Expected exactly one terminal Element expected, found "
+        isc_throw(ParseError, "Expected exactly one terminal Element, found "
                   << stack_.size());
     }
 }
index 26ee144e238db23babb429a220ce216be2abfd6f..83724e820cb2724523cc5cd58e7407b8bea962ef 100644 (file)
@@ -57,15 +57,14 @@ D2ParserContext::parseCommon() {
             isc_throw(D2ParseError, "Parser abort");
         }
         scanEnd();
-    }
-    catch (...) {
+    } catch (...) {
         scanEnd();
         throw;
     }
     if (stack_.size() == 1) {
         return (stack_[0]);
     } else {
-        isc_throw(D2ParseError, "Expected exactly one terminal Element expected, found "
+        isc_throw(D2ParseError, "Expected exactly one terminal Element, found "
                   << stack_.size());
     }
 }
index c13d2641339738320ee0acfbb7712d4effd80bcd..126f2eee2e3885afd1fbff224b32e153868ad97e 100644 (file)
@@ -55,15 +55,14 @@ Parser4Context::parseCommon() {
             isc_throw(Dhcp4ParseError, "Parser abort");
         }
         scanEnd();
-    }
-    catch (...) {
+    } catch (...) {
         scanEnd();
         throw;
     }
     if (stack_.size() == 1) {
         return (stack_[0]);
     } else {
-        isc_throw(Dhcp4ParseError, "Expected exactly one terminal Element expected, found "
+        isc_throw(Dhcp4ParseError, "Expected exactly one terminal Element, found "
                   << stack_.size());
     }
 }
index 16db37949d1041ffa770350045dbc4dbfcc7500f..8f0d8467ab26bf867fb1d54c8697083d0ff18871 100644 (file)
@@ -6,48 +6,52 @@
 
 #include <config.h>
 
-#include <arpa/inet.h>
-#include <gtest/gtest.h>
-
+#include <asiolink/addr_utilities.h>
 #include <cc/command_interpreter.h>
-#include <dhcp4/dhcp4_srv.h>
-#include <dhcp4/ctrl_dhcp4_srv.h>
-#include <dhcp4/json_config_parser.h>
+#include <dhcp/classify.h>
+#include <dhcp/docsis3_option_defs.h>
+#include <dhcp/iface_mgr.h>
+#include <dhcp/libdhcp++.h>
 #include <dhcp/option4_addrlst.h>
 #include <dhcp/option_custom.h>
 #include <dhcp/option_int.h>
-#include <dhcp/docsis3_option_defs.h>
-#include <dhcp/classify.h>
 #include <dhcp/testutils/iface_mgr_test_config.h>
-#include <dhcpsrv/subnet.h>
-#include <dhcpsrv/cfgmgr.h>
+#include <dhcp4/ctrl_dhcp4_srv.h>
+#include <dhcp4/dhcp4_srv.h>
+#include <dhcp4/json_config_parser.h>
 #include <dhcpsrv/cfg_expiration.h>
 #include <dhcpsrv/cfg_hosts.h>
 #include <dhcpsrv/cfg_subnets4.h>
+#include <dhcpsrv/cfgmgr.h>
 #include <dhcpsrv/parsers/simple_parser4.h>
+#include <dhcpsrv/subnet.h>
+#include <dhcpsrv/subnet_selector.h>
 #include <dhcpsrv/testutils/config_result_check.h>
 #include <dhcpsrv/testutils/test_config_backend_dhcp4.h>
-#include <process/config_ctl_info.h>
 #include <hooks/hooks_manager.h>
+#include <process/config_ctl_info.h>
 #include <stats/stats_mgr.h>
-#include <testutils/log_utils.h>
 #include <testutils/gtest_utils.h>
+#include <testutils/log_utils.h>
 #include <testutils/test_to_element.h>
 #include <util/chrono_time_utils.h>
 #include <util/doubles.h>
 
-#include "marker_file.h"
-#include "test_libraries.h"
-#include "test_data_files_config.h"
-#include "dhcp4_test_utils.h"
-#include "get_config_unittest.h"
-
 #include <boost/scoped_ptr.hpp>
 
 #include <iostream>
-#include <fstream>
 #include <sstream>
-#include <limits.h>
+#include <string>
+#include <vector>
+
+#include <arpa/inet.h>
+#include <gtest/gtest.h>
+#include <unistd.h>
+
+#include "dhcp4_test_utils.h"
+#include "get_config_unittest.h"
+#include "marker_file.h"
+#include "test_libraries.h"
 
 using namespace isc;
 using namespace isc::asiolink;
@@ -62,7 +66,7 @@ using namespace std;
 namespace {
 
 const char* PARSER_CONFIGS[] = {
-    // CONFIGURATION 0: one subnet with one pool, no user contexts
+    // Configuration 0: one subnet with one pool, no user contexts
     "{"
     "    \"interfaces-config\": {"
     "        \"interfaces\": [\"*\" ]"
@@ -162,12 +166,39 @@ const char* PARSER_CONFIGS[] = {
     "        \"type\": \"mysql\","
     "        \"name\": \"keatest2\","
     "        \"user\": \"keatest\","
+    "        \"retry-on-startup\": true,"
     "        \"password\": \"keatest\""
     "      }"
     "    ]"
     "}",
 
-    // Configuration 5 for comments
+    // Configuration 5: config databases
+    "{ \n"
+    "    \"interfaces-config\": { \n"
+    "        \"interfaces\": [\"*\" ] \n"
+    "    }, \n"
+    "    \"valid-lifetime\": 4000, \n"
+    "    \"rebind-timer\": 2000, \n"
+    "    \"renew-timer\": 1000, \n"
+    "    \"config-control\": { \n"
+    "       \"config-fetch-wait-time\": 10, \n"
+    "       \"config-databases\": [ { \n"
+    "               \"type\": \"mysql\", \n"
+    "               \"name\": \"keatest1\", \n"
+    "               \"user\": \"keatest\", \n"
+    "               \"password\": \"keatest\" \n"
+    "           },{ \n"
+    "               \"type\": \"mysql\", \n"
+    "               \"name\": \"keatest2\", \n"
+    "               \"user\": \"keatest\", \n"
+    "               \"retry-on-startup\": true, \n"
+    "               \"password\": \"keatest\" \n"
+    "           } \n"
+    "       ] \n"
+    "   } \n"
+    "} \n",
+
+    // Configuration 6 for comments
     "{"
     "    \"comment\": \"A DHCPv4 server\","
     "    \"interfaces-config\": {"
@@ -241,32 +272,7 @@ const char* PARSER_CONFIGS[] = {
     "        \"comment\": \"No dynamic DNS\","
     "        \"enable-updates\": false"
     "    }"
-    "}",
-
-    // Configuration 6: config databases
-    "{ \n"
-    "    \"interfaces-config\": { \n"
-    "        \"interfaces\": [\"*\" ] \n"
-    "    }, \n"
-    "    \"valid-lifetime\": 4000, \n"
-    "    \"rebind-timer\": 2000, \n"
-    "    \"renew-timer\": 1000, \n"
-    "    \"config-control\": { \n"
-    "       \"config-fetch-wait-time\": 10, \n"
-    "       \"config-databases\": [ { \n"
-    "               \"type\": \"mysql\", \n"
-    "               \"name\": \"keatest1\", \n"
-    "               \"user\": \"keatest\", \n"
-    "               \"password\": \"keatest\" \n"
-    "           },{ \n"
-    "               \"type\": \"mysql\", \n"
-    "               \"name\": \"keatest2\", \n"
-    "               \"user\": \"keatest\", \n"
-    "               \"password\": \"keatest\" \n"
-    "           } \n"
-    "       ] \n"
-    "   } \n"
-    "} \n"
+    "}"
 };
 
 class Dhcp4ParserTest : public LogContentTest {
@@ -281,17 +287,40 @@ protected:
     }
 
 public:
-    Dhcp4ParserTest()
-    : rcode_(-1) {
-        // Open port 0 means to not do anything at all. We don't want to
+    Dhcp4ParserTest() : rcode_(-1) {
+        // Open port 0 means to not open any sockets. We don't want to
         // deal with sockets here, just check if configuration handling
         // is sane.
         srv_.reset(new ControlledDhcpv4Srv(0));
-        // Create fresh context.
+
+        const IfaceCollection& ifaces = IfaceMgr::instance().getIfaces();
+
+        // There must be some interface detected
+        if (ifaces.empty()) {
+            // We can't use ASSERT in constructor
+            ADD_FAILURE() << "No interfaces detected.";
+        }
+
+        valid_iface_ = (*ifaces.begin())->getName();
+        bogus_iface_ = "nonexisting0";
+
+        if (IfaceMgr::instance().getIface(bogus_iface_)) {
+            ADD_FAILURE() << "The '" << bogus_iface_ << "' exists on this system"
+                          << " while the test assumes that it doesn't, to execute"
+                          << " some negative scenarios. Can't continue this test.";
+        }
+        // Reset configuration for each test.
         resetConfiguration();
     }
 
-public:
+    ~Dhcp4ParserTest() {
+        // Reset configuration database after each test.
+        resetConfiguration();
+
+        // ... and delete the hooks library marker files if present
+        static_cast<void>(remove(LOAD_MARKER_FILE));
+        static_cast<void>(remove(UNLOAD_MARKER_FILE));
+    };
 
     // Checks if the result of DHCP server configuration has
     // expected code (0 for success, other for failures).
@@ -308,7 +337,7 @@ public:
     void checkResult(ConstElementPtr status, int expected_code,
                      string expected_txt) {
         ASSERT_TRUE(status);
-        comment_ = parseAnswer(rcode_, status);
+        comment_ = parseAnswerText(rcode_, status);
         EXPECT_EQ(expected_code, rcode_) << "error text:" << comment_->stringValue();
         ASSERT_TRUE(comment_);
         ASSERT_EQ(Element::string, comment_->getType());
@@ -325,11 +354,7 @@ public:
     void configure(std::string config, int expected_code,
                    std::string exp_error = "") {
         ConstElementPtr json;
-        try {
-            json = parseDHCP4(config, true);
-        } catch(const std::exception& ex) {
-            ADD_FAILURE() << "parseDHCP4 failed: " << ex.what();
-        }
+        ASSERT_NO_THROW_LOG(json = parseDHCP4(config, true));
 
         ConstElementPtr status;
         EXPECT_NO_THROW(status = Dhcpv4SrvTest::configure(*srv_, json));
@@ -354,14 +379,6 @@ public:
         }
     }
 
-    ~Dhcp4ParserTest() {
-        resetConfiguration();
-
-        // ... and delete the hooks library marker files if present
-        static_cast<void>(remove(LOAD_MARKER_FILE));
-        static_cast<void>(remove(UNLOAD_MARKER_FILE));
-    };
-
     /// @brief Returns an interface configuration used by the most of the
     /// unit tests.
     std::string genIfaceConfig() const {
@@ -427,7 +444,8 @@ public:
     /// @params params map holding parameters and their values.
     /// @return configuration string containing custom values of parameters
     /// describing an option.
-    std::string createConfigWithOption(const std::map<std::string, std::string>& params) {
+    std::string createConfigWithOption(const std::map<std::string,
+                                       std::string>& params) {
         std::ostringstream stream;
         stream << "{ " << genIfaceConfig() << "," <<
             "\"rebind-timer\": 2000, "
@@ -450,7 +468,7 @@ public:
             } else if (param.first == "space") {
                 stream << "\"space\": \"" << param.second << "\"";
             } else if (param.first == "code") {
-                stream << "\"code\": " << param.second << "";
+                stream << "\"code\": " << param.second;
             } else if (param.first == "data") {
                 stream << "\"data\": \"" << param.second << "\"";
             } else if (param.first == "csv-format") {
@@ -486,10 +504,10 @@ public:
         Subnet4Ptr subnet = CfgMgr::instance().getStagingCfg()->
             getCfgSubnets4()->selectSubnet(subnet_address);
         if (!subnet) {
-            /// @todo replace toText() with the use of operator <<.
             ADD_FAILURE() << "A subnet for the specified address "
-                          << subnet_address.toText()
-                          << "does not exist in Config Manager";
+                          << subnet_address
+                          << " does not exist in Config Manager";
+            return (OptionDescriptor(false, false));
         }
         OptionContainerPtr options =
             subnet->getCfgOption()->getAll(DHCP4_OPTION_SPACE);
@@ -539,6 +557,7 @@ public:
         EXPECT_NO_THROW(x = Dhcpv4SrvTest::configure(*srv_, json));
         checkResult(x, 1);
         EXPECT_TRUE(errorContainsPosition(x, "<string>"));
+        CfgMgr::instance().clear();
     }
 
     /// @brief Test invalid option parameter value.
@@ -556,6 +575,7 @@ public:
         EXPECT_NO_THROW(x = Dhcpv4SrvTest::configure(*srv_, json));
         checkResult(x, 1);
         EXPECT_TRUE(errorContainsPosition(x, "<string>"));
+        CfgMgr::instance().clear();
     }
 
     /// @brief Test option against given code and data.
@@ -595,7 +615,8 @@ public:
         }
         // Verify that the data is correct. Do not verify suboptions and a header.
         const uint8_t* data = buf.getData();
-        EXPECT_EQ(0, memcmp(expected_data, data + option_desc.option_->getHeaderLen(),
+        EXPECT_EQ(0, memcmp(expected_data,
+                            data + option_desc.option_->getHeaderLen(),
                             expected_data_len));
     }
 
@@ -623,13 +644,17 @@ public:
                            const uint16_t option_code,
                            const uint8_t* expected_data,
                            const size_t expected_data_len) {
+        CfgMgr::instance().clear();
+
         std::string config = createConfigWithOption(params);
         ASSERT_TRUE(executeConfiguration(config, "parse option configuration"));
+
         // The subnet should now hold one option with the specified option code.
         OptionDescriptor desc =
             getOptionFromSubnet(IOAddress("192.0.2.24"), option_code);
         ASSERT_TRUE(desc.option_);
         testOption(desc, option_code, expected_data, expected_data_len);
+        CfgMgr::instance().clear();
     }
 
     /// @brief Parse and Execute configuration
@@ -687,19 +712,22 @@ public:
 
     /// @brief Reset configuration database.
     ///
-    /// This function resets configuration data base by
-    /// removing all subnets and option-data. Reset must
-    /// be performed after each test to make sure that
-    /// contents of the database do not affect result of
-    /// subsequent tests.
+    /// This function resets configuration data base by removing all subnets
+    /// option-data, and hooks libraries. The reset must be performed after each
+    /// test to make sure that contents of the database do not affect the
+    /// results of subsequent tests.
     void resetConfiguration() {
         // The default setting is to listen on all interfaces. In order to
         // properly test interface configuration we disable listening on
         // all interfaces before each test and later check that this setting
         // has been overridden by the configuration used in the test.
         CfgMgr::instance().clear();
-        string config = "{ " + genIfaceConfig() + "," +
-            "\"hooks-libraries\": [ ], "
+        string config = "{ \"interfaces-config\": {"
+            "    \"interfaces\": [ ]"
+            "},"
+            "\"hooks-libraries\": [ ],"
+            "\"rebind-timer\": 2000, "
+            "\"renew-timer\": 1000, "
             "\"valid-lifetime\": 4000, "
             "\"subnet4\": [ ], "
             "\"dhcp-ddns\": { \"enable-updates\" : false }, "
@@ -836,9 +864,11 @@ public:
                                                << isc::data::prettyPrint(exp_value);
     }
 
-    boost::scoped_ptr<Dhcpv4Srv> srv_;  ///< DHCP4 server under test
     int rcode_;                         ///< Return code from element parsing
-    ConstElementPtr comment_;           ///< Reason for parse fail
+    boost::scoped_ptr<Dhcpv4Srv> srv_;  ///< Instance of the Dhcpv4Srv used during tests
+    ConstElementPtr comment_; ///< Comment (see @ref isc::config::parseAnswer)
+    string valid_iface_; ///< Valid network interface name (present in system)
+    string bogus_iface_; ///< invalid network interface name (not in system)
     isc::dhcp::ClientClasses classify_; ///< used in client classification
 };
 
@@ -862,7 +892,8 @@ TEST_F(Dhcp4ParserTest, bogusCommand) {
 TEST_F(Dhcp4ParserTest, emptyInterfaceConfig) {
 
     ConstElementPtr json;
-    EXPECT_NO_THROW(json = parseDHCP4("{ \"rebind-timer\": 2000, "
+    EXPECT_NO_THROW(json = parseDHCP4("{ "
+                                      "\"rebind-timer\": 2000, "
                                       "\"renew-timer\": 1000, "
                                       "\"valid-lifetime\": 4000 }"));
 
@@ -873,34 +904,12 @@ TEST_F(Dhcp4ParserTest, emptyInterfaceConfig) {
     checkResult(status, 0);
 }
 
-/// The goal of this test is to verify if wrongly defined subnet will
-/// be rejected. Properly defined subnet must include at least one
-/// pool definition.
-TEST_F(Dhcp4ParserTest, emptySubnet) {
-
-    std::string config = "{ " + genIfaceConfig() + "," +
-        "\"rebind-timer\": 2000, "
-        "\"renew-timer\": 1000, "
-        "\"subnet4\": [  ], "
-        "\"valid-lifetime\": 4000 }";
-
-    ConstElementPtr json;
-    EXPECT_NO_THROW(json = parseDHCP4(config));
-    extractConfig(config);
-
-    ConstElementPtr status;
-    EXPECT_NO_THROW(status = Dhcpv4SrvTest::configure(*srv_, json));
-
-    // returned value should be 0 (success)
-    checkResult(status, 0);
-}
-
 /// Check that valid-lifetime must be between min-valid-lifetime and
 /// max-valid-lifetime when a bound is specified, *AND* a subnet is
 /// specified (boundary check is done when lifetimes are applied).
 TEST_F(Dhcp4ParserTest, outBoundValidLifetime) {
 
-    string too_small =  "{ " + genIfaceConfig() + "," +
+    string too_small =  "{ " + genIfaceConfig() + ","
         "\"subnet4\": [ { "
         "    \"id\": 1,"
         "    \"pools\": [ { \"pool\": \"192.0.2.1 - 192.0.2.100\" } ],"
@@ -918,7 +927,7 @@ TEST_F(Dhcp4ParserTest, outBoundValidLifetime) {
     checkResult(status, 1, expected);
     resetConfiguration();
 
-    string too_large =  "{ " + genIfaceConfig() + "," +
+    string too_large =  "{ " + genIfaceConfig() + ","
         "\"subnet4\": [ { "
         "    \"id\": 1,"
         "    \"pools\": [ { \"pool\": \"192.0.2.1 - 192.0.2.100\" } ],"
@@ -933,7 +942,7 @@ TEST_F(Dhcp4ParserTest, outBoundValidLifetime) {
     checkResult(status, 1, expected);
     resetConfiguration();
 
-    string before =  "{ " + genIfaceConfig() + "," +
+    string before =  "{ " + genIfaceConfig() + ","
         "\"subnet4\": [ { "
         "    \"id\": 1,"
         "    \"pools\": [ { \"pool\": \"192.0.2.1 - 192.0.2.100\" } ],"
@@ -949,7 +958,7 @@ TEST_F(Dhcp4ParserTest, outBoundValidLifetime) {
     checkResult(status, 1, expected);
     resetConfiguration();
 
-    string after =  "{ " + genIfaceConfig() + "," +
+    string after =  "{ " + genIfaceConfig() + ","
         "\"subnet4\": [ { "
         "    \"id\": 1,"
         "    \"pools\": [ { \"pool\": \"192.0.2.1 - 192.0.2.100\" } ],"
@@ -965,7 +974,7 @@ TEST_F(Dhcp4ParserTest, outBoundValidLifetime) {
     checkResult(status, 1, expected);
     resetConfiguration();
 
-    string crossed =  "{ " + genIfaceConfig() + "," +
+    string crossed =  "{ " + genIfaceConfig() + ","
         "\"subnet4\": [ { "
         "    \"id\": 1,"
         "    \"pools\": [ { \"pool\": \"192.0.2.1 - 192.0.2.100\" } ],"
@@ -986,7 +995,7 @@ TEST_F(Dhcp4ParserTest, outBoundValidLifetime) {
 /// parameters only.
 TEST_F(Dhcp4ParserTest, outBoundGlobalValidLifetime) {
 
-    string too_small =  "{ " + genIfaceConfig() + "," +
+    string too_small =  "{ " + genIfaceConfig() + ","
         "\"valid-lifetime\": 1000, \"min-valid-lifetime\": 2000 }";
 
     ConstElementPtr json;
@@ -1000,7 +1009,7 @@ TEST_F(Dhcp4ParserTest, outBoundGlobalValidLifetime) {
     checkResult(status, 1, expected);
     resetConfiguration();
 
-    string too_large =  "{ " + genIfaceConfig() + "," +
+    string too_large =  "{ " + genIfaceConfig() + ","
         "\"valid-lifetime\": 2000, \"max-valid-lifetime\": 1000 }";
 
     ASSERT_NO_THROW(json = parseDHCP4(too_large));
@@ -1011,7 +1020,7 @@ TEST_F(Dhcp4ParserTest, outBoundGlobalValidLifetime) {
     checkResult(status, 1, expected);
     resetConfiguration();
 
-    string before =  "{ " + genIfaceConfig() + "," +
+    string before =  "{ " + genIfaceConfig() + ","
         "\"valid-lifetime\": 1000, \"min-valid-lifetime\": 2000, "
         "\"max-valid-lifetime\": 4000 }";
 
@@ -1023,7 +1032,7 @@ TEST_F(Dhcp4ParserTest, outBoundGlobalValidLifetime) {
     checkResult(status, 1, expected);
     resetConfiguration();
 
-    string after =  "{ " + genIfaceConfig() + "," +
+    string after =  "{ " + genIfaceConfig() + ","
         "\"valid-lifetime\": 5000, \"min-valid-lifetime\": 1000, "
         "\"max-valid-lifetime\": 4000 }";
 
@@ -1035,7 +1044,7 @@ TEST_F(Dhcp4ParserTest, outBoundGlobalValidLifetime) {
     checkResult(status, 1, expected);
     resetConfiguration();
 
-    string crossed =  "{ " + genIfaceConfig() + "," +
+    string crossed =  "{ " + genIfaceConfig() + ","
         "\"valid-lifetime\": 1500, \"min-valid-lifetime\": 2000, "
         "\"max-valid-lifetime\": 1000 }";
 
@@ -1051,7 +1060,7 @@ TEST_F(Dhcp4ParserTest, outBoundGlobalValidLifetime) {
 /// it is marked unspecified in the Subnet.
 TEST_F(Dhcp4ParserTest, unspecifiedRenewTimer) {
 
-    string config = "{ " + genIfaceConfig() + "," +
+    string config = "{ " + genIfaceConfig() + ","
         "\"rebind-timer\": 2000, "
         "\"subnet4\": [ { "
         "    \"id\": 1,"
@@ -1086,7 +1095,7 @@ TEST_F(Dhcp4ParserTest, unspecifiedRenewTimer) {
 /// it is marked unspecified in the Subnet.
 TEST_F(Dhcp4ParserTest, unspecifiedRebindTimer) {
 
-    string config = "{ " + genIfaceConfig() + "," +
+    string config = "{ " + genIfaceConfig() + ","
         "\"renew-timer\": 1000, "
         "\"subnet4\": [ { "
         "    \"id\": 1,"
@@ -1116,11 +1125,32 @@ TEST_F(Dhcp4ParserTest, unspecifiedRebindTimer) {
     EXPECT_EQ(1, subnet->getID());
 }
 
+/// The goal of this test is to verify if configuration without any
+/// subnets defined can be accepted.
+TEST_F(Dhcp4ParserTest, emptySubnet) {
+
+    string config = "{ " + genIfaceConfig() + ","
+        "\"rebind-timer\": 2000, "
+        "\"renew-timer\": 1000, "
+        "\"subnet4\": [  ], "
+        "\"valid-lifetime\": 4000 }";
+
+    ConstElementPtr json;
+    ASSERT_NO_THROW(json = parseDHCP4(config));
+    extractConfig(config);
+
+    ConstElementPtr status;
+    EXPECT_NO_THROW(status = Dhcpv4SrvTest::configure(*srv_, json));
+
+    // returned value should be 0 (success)
+    checkResult(status, 0);
+}
+
 /// The goal of this test is to verify if defined subnet uses global
 /// parameter timer definitions.
 TEST_F(Dhcp4ParserTest, subnetGlobalDefaults) {
 
-    string config = "{ " + genIfaceConfig() + "," +
+    string config = "{ " + genIfaceConfig() + ","
         "\"rebind-timer\": 2000, "
         "\"renew-timer\": 1000, "
         "\"subnet4\": [ { "
@@ -1160,36 +1190,37 @@ TEST_F(Dhcp4ParserTest, subnetGlobalDefaults) {
 TEST_F(Dhcp4ParserTest, multipleSubnetsExplicitIDs) {
     ConstElementPtr x;
     // Four subnets with arbitrary subnet ids.
-    string config = "{ " + genIfaceConfig() + "," +
+    string config = "{ " + genIfaceConfig() + ","
         "\"rebind-timer\": 2000, "
         "\"renew-timer\": 1000, "
         "\"subnet4\": [ { "
         "    \"pools\": [ { \"pool\": \"192.0.2.1 - 192.0.2.100\" } ],"
         "    \"subnet\": \"192.0.2.0/24\", "
-        "    \"id\": 1024 "
+        "    \"id\": 1024"
         " },"
         " {"
         "    \"pools\": [ { \"pool\": \"192.0.3.101 - 192.0.3.150\" } ],"
         "    \"subnet\": \"192.0.3.0/24\", "
-        "    \"id\": 100 "
+        "    \"id\": 100"
         " },"
         " {"
         "    \"pools\": [ { \"pool\": \"192.0.4.101 - 192.0.4.150\" } ],"
         "    \"subnet\": \"192.0.4.0/24\", "
-        "    \"id\": 1 "
+        "    \"id\": 1"
         " },"
         " {"
         "    \"pools\": [ { \"pool\": \"192.0.5.101 - 192.0.5.150\" } ],"
         "    \"subnet\": \"192.0.5.0/24\", "
-        "    \"id\": 34 "
+        "    \"id\": 34"
         " } ],"
         "\"valid-lifetime\": 4000 }";
 
+    int cnt = 0; // Number of reconfigurations
+
     ConstElementPtr json;
     ASSERT_NO_THROW(json = parseDHCP4(config));
     extractConfig(config);
 
-    int cnt = 0; // Number of reconfigurations
     do {
         EXPECT_NO_THROW(x = Dhcpv4SrvTest::configure(*srv_, json));
         checkResult(x, 0);
@@ -1214,32 +1245,32 @@ TEST_F(Dhcp4ParserTest, multipleSubnetsExplicitIDs) {
     } while (++cnt < 3);
 }
 
-// Check that the configuration with two subnets having the same id is rejected.
+// Check that the configuration with two subnets having the same ID is rejected.
 TEST_F(Dhcp4ParserTest, multipleSubnetsOverlappingIDs) {
     ConstElementPtr x;
-    // Four subnets, two of them having the same id.
-    string config = "{ " + genIfaceConfig() + "," +
+    // Four subnets, two of them have the same id.
+    string config = "{ " + genIfaceConfig() + ","
         "\"rebind-timer\": 2000, "
         "\"renew-timer\": 1000, "
         "\"subnet4\": [ { "
         "    \"pools\": [ { \"pool\": \"192.0.2.1 - 192.0.2.100\" } ],"
         "    \"subnet\": \"192.0.2.0/24\", "
-        "    \"id\": 1024 "
+        "    \"id\": 1024"
         " },"
         " {"
         "    \"pools\": [ { \"pool\": \"192.0.3.101 - 192.0.3.150\" } ],"
         "    \"subnet\": \"192.0.3.0/24\", "
-        "    \"id\": 100 "
+        "    \"id\": 100"
         " },"
         " {"
         "    \"pools\": [ { \"pool\": \"192.0.4.101 - 192.0.4.150\" } ],"
         "    \"subnet\": \"192.0.4.0/24\", "
-        "    \"id\": 1024 "
+        "    \"id\": 1024"
         " },"
         " {"
         "    \"pools\": [ { \"pool\": \"192.0.5.101 - 192.0.5.150\" } ],"
         "    \"subnet\": \"192.0.5.0/24\", "
-        "    \"id\": 34 "
+        "    \"id\": 34"
         " } ],"
         "\"valid-lifetime\": 4000 }";
 
@@ -1257,70 +1288,70 @@ TEST_F(Dhcp4ParserTest, reconfigureRemoveSubnet) {
     ConstElementPtr x;
 
     // All four subnets
-    string config4 = "{ " + genIfaceConfig() + "," +
+    string config4 = "{ " + genIfaceConfig() + ","
         "\"rebind-timer\": 2000, "
         "\"renew-timer\": 1000, "
         "\"subnet4\": [ { "
         "    \"pools\": [ { \"pool\": \"192.0.2.1 - 192.0.2.100\" } ],"
         "    \"subnet\": \"192.0.2.0/24\", "
-        "    \"id\": 1 "
+        "    \"id\": 1"
         " },"
         " {"
         "    \"pools\": [ { \"pool\": \"192.0.3.101 - 192.0.3.150\" } ],"
         "    \"subnet\": \"192.0.3.0/24\", "
-        "    \"id\": 2 "
+        "    \"id\": 2"
         " },"
         " {"
         "    \"pools\": [ { \"pool\": \"192.0.4.101 - 192.0.4.150\" } ],"
         "    \"subnet\": \"192.0.4.0/24\", "
-        "    \"id\": 3 "
+        "    \"id\": 3"
         " },"
         " {"
         "    \"pools\": [ { \"pool\": \"192.0.5.101 - 192.0.5.150\" } ],"
         "    \"subnet\": \"192.0.5.0/24\", "
-        "    \"id\": 4 "
+        "    \"id\": 4"
         " } ],"
         "\"valid-lifetime\": 4000 }";
 
     // Three subnets (the last one removed)
-    string config_first3 = "{ " + genIfaceConfig() + "," +
+    string config_first3 = "{ " + genIfaceConfig() + ","
         "\"rebind-timer\": 2000, "
         "\"renew-timer\": 1000, "
         "\"subnet4\": [ { "
         "    \"pools\": [ { \"pool\": \"192.0.2.1 - 192.0.2.100\" } ],"
         "    \"subnet\": \"192.0.2.0/24\", "
-        "    \"id\": 1 "
+        "    \"id\": 1"
         " },"
         " {"
         "    \"pools\": [ { \"pool\":  \"192.0.3.101 - 192.0.3.150\" } ],"
         "    \"subnet\": \"192.0.3.0/24\", "
-        "    \"id\": 2 "
+        "    \"id\": 2"
         " },"
         " {"
         "    \"pools\": [ { \"pool\": \"192.0.4.101 - 192.0.4.150\" } ],"
         "    \"subnet\": \"192.0.4.0/24\", "
-        "    \"id\": 3 "
+        "    \"id\": 3"
         " } ],"
         "\"valid-lifetime\": 4000 }";
 
     // Second subnet removed
-    string config_second_removed = "{ " + genIfaceConfig() + "," +
+    string config_second_removed = "{ " + genIfaceConfig() + ","
         "\"rebind-timer\": 2000, "
         "\"renew-timer\": 1000, "
         "\"subnet4\": [ { "
         "    \"pools\": [ { \"pool\": \"192.0.2.1 - 192.0.2.100\" } ],"
         "    \"subnet\": \"192.0.2.0/24\", "
-        "    \"id\": 1 "
+        "    \"id\": 1"
         " },"
         " {"
         "    \"pools\": [ { \"pool\": \"192.0.4.101 - 192.0.4.150\" } ],"
         "    \"subnet\": \"192.0.4.0/24\", "
-        "    \"id\": 3 "
+        "    \"id\": 3"
         " },"
         " {"
         "    \"pools\": [ { \"pool\": \"192.0.5.101 - 192.0.5.150\" } ],"
         "    \"subnet\": \"192.0.5.0/24\", "
-        "    \"id\": 4 "
+        "    \"id\": 4"
         " } ],"
         "\"valid-lifetime\": 4000 }";
 
@@ -1329,11 +1360,14 @@ TEST_F(Dhcp4ParserTest, reconfigureRemoveSubnet) {
 
     ConstElementPtr json;
     ASSERT_NO_THROW(json = parseDHCP4(config4));
+    extractConfig(config4);
     EXPECT_NO_THROW(x = Dhcpv4SrvTest::configure(*srv_, json));
     checkResult(x, 0);
 
+    CfgMgr::instance().commit();
+
     const Subnet4Collection* subnets =
-        CfgMgr::instance().getStagingCfg()->getCfgSubnets4()->getAll();
+        CfgMgr::instance().getCurrentCfg()->getCfgSubnets4()->getAll();
     ASSERT_TRUE(subnets);
     ASSERT_EQ(4, subnets->size()); // We expect 4 subnets
 
@@ -1344,7 +1378,9 @@ TEST_F(Dhcp4ParserTest, reconfigureRemoveSubnet) {
     EXPECT_NO_THROW(x = Dhcpv4SrvTest::configure(*srv_, json));
     checkResult(x, 0);
 
-    subnets = CfgMgr::instance().getStagingCfg()->getCfgSubnets4()->getAll();
+    CfgMgr::instance().commit();
+
+    subnets = CfgMgr::instance().getCurrentCfg()->getCfgSubnets4()->getAll();
     ASSERT_TRUE(subnets);
     ASSERT_EQ(3, subnets->size()); // We expect 3 subnets now (4th is removed)
 
@@ -1362,22 +1398,24 @@ TEST_F(Dhcp4ParserTest, reconfigureRemoveSubnet) {
     EXPECT_NO_THROW(x = Dhcpv4SrvTest::configure(*srv_, json));
     checkResult(x, 0);
 
-    CfgMgr::instance().clear();
+    CfgMgr::instance().commit();
 
     // Do reconfiguration
     ASSERT_NO_THROW(json = parseDHCP4(config_second_removed));
     EXPECT_NO_THROW(x = Dhcpv4SrvTest::configure(*srv_, json));
     checkResult(x, 0);
 
-    subnets = CfgMgr::instance().getStagingCfg()->getCfgSubnets4()->getAll();
+    CfgMgr::instance().commit();
+
+    subnets = CfgMgr::instance().getCurrentCfg()->getCfgSubnets4()->getAll();
     ASSERT_TRUE(subnets);
     ASSERT_EQ(3, subnets->size()); // We expect 4 subnets
 
-    auto subnet_it = subnets->begin();
-    EXPECT_EQ(1, (*subnet_it)->getID());
+    subnet = subnets->begin();
+    EXPECT_EQ(1, (*subnet)->getID());
     // The second subnet (with subnet-id = 2) is no longer there
-    EXPECT_EQ(3, (*++subnet_it)->getID());
-    EXPECT_EQ(4, (*++subnet_it)->getID());
+    EXPECT_EQ(3, (*++subnet)->getID());
+    EXPECT_EQ(4, (*++subnet)->getID());
 }
 
 /// @todo: implement subnet removal test as part of #3281.
@@ -1386,7 +1424,7 @@ TEST_F(Dhcp4ParserTest, reconfigureRemoveSubnet) {
 // global parameter are taken into consideration.
 TEST_F(Dhcp4ParserTest, nextServerGlobal) {
 
-    string config = "{ " + genIfaceConfig() + "," +
+    string config = "{ " + genIfaceConfig() + ","
         "\"rebind-timer\": 2000, "
         "\"renew-timer\": 1000, "
         "\"next-server\": \"1.2.3.4\", "
@@ -1426,7 +1464,7 @@ TEST_F(Dhcp4ParserTest, nextServerGlobal) {
 // subnet parameter are taken into consideration.
 TEST_F(Dhcp4ParserTest, nextServerSubnet) {
 
-    string config = "{ " + genIfaceConfig() + "," +
+    string config = "{ " + genIfaceConfig() + ","
         "\"rebind-timer\": 2000, "
         "\"renew-timer\": 1000, "
         "\"subnet4\": [ { "
@@ -1464,7 +1502,7 @@ TEST_F(Dhcp4ParserTest, nextServerNegative) {
     IfaceMgrTestConfig test_config(true);
 
     // Config with junk instead of next-server address
-    string config_bogus1 = "{ " + genIfaceConfig() + "," +
+    string config_bogus1 = "{ " + genIfaceConfig() + ","
         "\"rebind-timer\": 2000, "
         "\"renew-timer\": 1000, "
         "\"subnet4\": [ { "
@@ -1477,7 +1515,7 @@ TEST_F(Dhcp4ParserTest, nextServerNegative) {
         "\"valid-lifetime\": 4000 }";
 
     // Config with IPv6 next server address
-    string config_bogus2 = "{ " + genIfaceConfig() + "," +
+    string config_bogus2 = "{ " + genIfaceConfig() + ","
         "\"rebind-timer\": 2000, "
         "\"renew-timer\": 1000, "
         "\"subnet4\": [ { "
@@ -1490,7 +1528,7 @@ TEST_F(Dhcp4ParserTest, nextServerNegative) {
         "\"valid-lifetime\": 4000 }";
 
     // Config with empty next server address
-    string config_bogus3 = "{ " + genIfaceConfig() + "," +
+    string config_bogus3 = "{ " + genIfaceConfig() + ","
         "\"rebind-timer\": 2000, "
         "\"renew-timer\": 1000, "
         "\"subnet4\": [ { "
@@ -1504,7 +1542,7 @@ TEST_F(Dhcp4ParserTest, nextServerNegative) {
 
     // Config with too large server-hostname
     string bigsname(Pkt4::MAX_SNAME_LEN + 1, ' ');
-    string config_bogus4 = "{ " + genIfaceConfig() + "," +
+    string config_bogus4 = "{ " + genIfaceConfig() + ","
         "\"rebind-timer\": 2000, "
         "\"renew-timer\": 1000, "
         "\"subnet4\": [ { "
@@ -1518,7 +1556,7 @@ TEST_F(Dhcp4ParserTest, nextServerNegative) {
 
     // Config with too large boot-file-hostname
     string bigfilename(Pkt4::MAX_FILE_LEN + 1, ' ');
-    string config_bogus5 = "{ " + genIfaceConfig() + "," +
+    string config_bogus5 = "{ " + genIfaceConfig() + ","
         "\"rebind-timer\": 2000, "
         "\"renew-timer\": 1000, "
         "\"subnet4\": [ { "
@@ -1576,7 +1614,7 @@ TEST_F(Dhcp4ParserTest, nextServerNegative) {
 // specific value.
 TEST_F(Dhcp4ParserTest, nextServerOverride) {
 
-    string config = "{ " + genIfaceConfig() + "," +
+    string config = "{ " + genIfaceConfig() + ","
         "\"rebind-timer\": 2000, "
         "\"renew-timer\": 1000, "
         "\"next-server\": \"192.0.0.1\", "
@@ -1614,7 +1652,7 @@ TEST_F(Dhcp4ParserTest, nextServerOverride) {
 // Check whether it is possible to configure echo-client-id
 TEST_F(Dhcp4ParserTest, echoClientId) {
 
-    string config_false = "{ " + genIfaceConfig() + "," +
+    string config_false = "{ " + genIfaceConfig() + ","
         "\"rebind-timer\": 2000, "
         "\"renew-timer\": 1000, "
         "\"echo-client-id\": false,"
@@ -1624,7 +1662,7 @@ TEST_F(Dhcp4ParserTest, echoClientId) {
         "    \"subnet\": \"192.0.2.0/24\" } ],"
         "\"valid-lifetime\": 4000 }";
 
-    string config_true = "{ " + genIfaceConfig() + "," +
+    string config_true = "{ " + genIfaceConfig() + ","
         "\"rebind-timer\": 2000, "
         "\"renew-timer\": 1000, "
         "\"echo-client-id\": true,"
@@ -1663,7 +1701,7 @@ TEST_F(Dhcp4ParserTest, echoClientId) {
 
 // Check whether it is possible to configure compatibility flags.
 TEST_F(Dhcp4ParserTest, compatibility) {
-    string config = "{ " + genIfaceConfig() + "," +
+    string config = "{ " + genIfaceConfig() + ","
         "\"rebind-timer\": 2000, "
         "\"renew-timer\": 1000, "
         "\"compatibility\": { "
@@ -1701,7 +1739,7 @@ TEST_F(Dhcp4ParserTest, compatibility) {
 
 // Check that unknown compatibility flag raises error.
 TEST_F(Dhcp4ParserTest, compatibilityUnknown) {
-    string config = "{ " + genIfaceConfig() + "," +
+    string config = "{ " + genIfaceConfig() + ","
         "\"rebind-timer\": 2000, "
         "\"renew-timer\": 1000, "
         "\"compatibility\": { "
@@ -1728,7 +1766,7 @@ TEST_F(Dhcp4ParserTest, compatibilityUnknown) {
 
 // Check that not boolean compatibility flag value raises error.
 TEST_F(Dhcp4ParserTest, compatibilityNotBool) {
-    string config = "{ " + genIfaceConfig() + "," +
+    string config = "{ " + genIfaceConfig() + ","
         "\"rebind-timer\": 2000, "
         "\"renew-timer\": 1000, "
         "\"compatibility\": { "
@@ -1756,7 +1794,7 @@ TEST_F(Dhcp4ParserTest, compatibilityNotBool) {
 // This test checks that the global match-client-id parameter is optional
 // and that values under the subnet are used.
 TEST_F(Dhcp4ParserTest, matchClientIdNoGlobal) {
-    std::string config = "{ " + genIfaceConfig() + "," +
+    std::string config = "{ " + genIfaceConfig() + ","
         "\"rebind-timer\": 2000, "
         "\"renew-timer\": 1000, "
         "\"subnet4\": [ "
@@ -1804,7 +1842,7 @@ TEST_F(Dhcp4ParserTest, matchClientIdNoGlobal) {
 // when there is no such parameter under subnet and that the parameter
 // specified for a subnet overrides the global setting.
 TEST_F(Dhcp4ParserTest, matchClientIdGlobal) {
-    std::string config = "{ " + genIfaceConfig() + "," +
+    std::string config = "{ " + genIfaceConfig() + ","
         "\"rebind-timer\": 2000, "
         "\"renew-timer\": 1000, "
         "\"match-client-id\": true,"
@@ -1851,7 +1889,7 @@ TEST_F(Dhcp4ParserTest, matchClientIdGlobal) {
 // This test checks that the global authoritative parameter is optional
 // and that values under the subnet are used.
 TEST_F(Dhcp4ParserTest, authoritativeNoGlobal) {
-    std::string config = "{ " + genIfaceConfig() + "," +
+    std::string config = "{ " + genIfaceConfig() + ","
         "\"rebind-timer\": 2000, "
         "\"renew-timer\": 1000, "
         "\"subnet4\": [ "
@@ -1899,7 +1937,7 @@ TEST_F(Dhcp4ParserTest, authoritativeNoGlobal) {
 // when there is no such parameter under subnet and that the parameter
 // specified for a subnet overrides the global setting.
 TEST_F(Dhcp4ParserTest, authoritativeGlobal) {
-    std::string config = "{ " + genIfaceConfig() + "," +
+    std::string config = "{ " + genIfaceConfig() + ","
         "\"rebind-timer\": 2000, "
         "\"renew-timer\": 1000, "
         "\"authoritative\": true,"
@@ -1947,7 +1985,7 @@ TEST_F(Dhcp4ParserTest, authoritativeGlobal) {
 // on a per subnet basis.
 TEST_F(Dhcp4ParserTest, subnetLocal) {
 
-    string config = "{ " + genIfaceConfig() + "," +
+    string config = "{ " + genIfaceConfig() + ","
         "\"rebind-timer\": 2000, "
         "\"renew-timer\": 1000, "
         "\"subnet4\": [ { "
@@ -1983,81 +2021,57 @@ TEST_F(Dhcp4ParserTest, subnetLocal) {
     EXPECT_EQ(5, subnet->getValid().getMax());
 }
 
-// This test checks that multiple pools can be defined and handled properly.
-// The test defines 2 subnets, each with 2 pools.
-TEST_F(Dhcp4ParserTest, multiplePools) {
+// This test checks if it is possible to define a subnet with an
+// interface defined.
+TEST_F(Dhcp4ParserTest, subnetInterface) {
+
+    // There should be at least one interface
+    // As far as I can tell, this is the first lambda in Kea code. Cool.
+    auto config = [this](string iface) {
+        return ("{ " + genIfaceConfig() + ","
+                "\"rebind-timer\": 2000, "
+                "\"renew-timer\": 1000, "
+                "\"subnet4\": [ { "
+                "    \"id\": 1,"
+                "    \"pools\": [ { "
+                "        \"pool\": \"192.0.2.1 - 192.0.2.100\" } ],"
+                "    \"interface\": \"" + iface + "\","
+                "    \"subnet\": \"192.0.2.0/24\" } ],"
+                "\"valid-lifetime\": 4000 }"); };
+    cout << config(valid_iface_) << endl;
 
-    // Collection with two subnets, each with 2 pools.
-    string config = "{ " + genIfaceConfig() + "," +
-        "\"rebind-timer\": 2000, "
-        "\"renew-timer\": 1000, "
-        "\"subnet4\": [ { "
-        "    \"id\": 1,"
-        "    \"pools\": [ "
-        "        { \"pool\": \"192.0.2.0/28\" },"
-        "        { \"pool\": \"192.0.2.200-192.0.2.255\" }"
-        "    ],"
-        "    \"subnet\": \"192.0.2.0/24\" "
-        " },"
-        " {"
-        "    \"id\": 2,"
-        "    \"pools\": [ "
-        "    { \"pool\": \"192.0.3.0/25\" },"
-        "    { \"pool\": \"192.0.3.128/25\" }"
-        "    ],"
-        "    \"subnet\": \"192.0.3.0/24\""
-        " } ],"
-        "\"valid-lifetime\": 4000 }";
     ConstElementPtr json;
-    ASSERT_NO_THROW(json = parseDHCP4(config));
-    extractConfig(config);
+    ASSERT_NO_THROW(json = parseDHCP4(config(valid_iface_)));
+    extractConfig(config("eth0"));
 
     ConstElementPtr status;
-    ASSERT_NO_THROW(status = Dhcpv4SrvTest::configure(*srv_, json));
-    checkResult(status, 0);
-
-    const Subnet4Collection* subnets =
-        CfgMgr::instance().getStagingCfg()->getCfgSubnets4()->getAll();
-    ASSERT_TRUE(subnets);
-    ASSERT_EQ(2, subnets->size()); // We expect 2 subnets
+    EXPECT_NO_THROW(status = Dhcpv4SrvTest::configure(*srv_, json));
 
-    // Check the first subnet
-    auto subnet = subnets->begin();
-    const PoolCollection& pools1 = (*subnet)->getPools(Lease::TYPE_V4);
-    ASSERT_EQ(2, pools1.size());
-    EXPECT_EQ("type=V4, 192.0.2.0-192.0.2.15",
-              pools1[0]->toText());
-    EXPECT_EQ("type=V4, 192.0.2.200-192.0.2.255",
-              pools1[1]->toText());
-    // There shouldn't be any TA or PD pools
-    EXPECT_THROW((*subnet)->getPools(Lease::TYPE_TA), BadValue);
-    EXPECT_THROW((*subnet)->getPools(Lease::TYPE_PD), BadValue);
+    // returned value should be 0 (configuration success)
+    checkResult(status, 0);
 
-    // Check the second subnet
-    ++subnet;
-    const PoolCollection& pools2 = (*subnet)->getPools(Lease::TYPE_V4);
-    ASSERT_EQ(2, pools2.size());
-    EXPECT_EQ("type=V4, 192.0.3.0-192.0.3.127",
-              pools2[0]->toText());
-    EXPECT_EQ("type=V4, 192.0.3.128-192.0.3.255",
-              pools2[1]->toText());
-    // There shouldn't be any TA or PD pools
-    EXPECT_THROW((*subnet)->getPools(Lease::TYPE_TA), BadValue);
-    EXPECT_THROW((*subnet)->getPools(Lease::TYPE_PD), BadValue);
+    Subnet4Ptr subnet = CfgMgr::instance().getStagingCfg()->getCfgSubnets4()->
+        selectSubnet(IOAddress("192.0.2.200"), classify_);
+    ASSERT_TRUE(subnet);
+    EXPECT_EQ(valid_iface_, subnet->getIface().get());
 }
 
-// Test verifies that a subnet with pool values that do not belong to that
-// pool are rejected.
-TEST_F(Dhcp4ParserTest, poolOutOfSubnet) {
+// This test checks if invalid interface name will be rejected in
+// Subnet4 definition.
+TEST_F(Dhcp4ParserTest, subnetInterfaceBogus) {
 
-    string config = "{ " + genIfaceConfig() + "," +
+    // There should be at least one interface
+
+    string config = "{ " + genIfaceConfig() + ","
         "\"rebind-timer\": 2000, "
         "\"renew-timer\": 1000, "
         "\"subnet4\": [ { "
         "    \"id\": 1,"
-        "    \"pools\": [ { \"pool\": \"192.0.4.0/28\" } ],"
+        "    \"pools\": [ { \"pool\": \"192.0.2.1 - 192.0.2.100\" } ],"
+        "    \"interface\": \"" + bogus_iface_ + "\","
         "    \"subnet\": \"192.0.2.0/24\" } ],"
         "\"valid-lifetime\": 4000 }";
+    cout << config << endl;
 
     ConstElementPtr json;
     ASSERT_NO_THROW(json = parseDHCP4(config));
@@ -2065,27 +2079,212 @@ TEST_F(Dhcp4ParserTest, poolOutOfSubnet) {
     ConstElementPtr status;
     EXPECT_NO_THROW(status = Dhcpv4SrvTest::configure(*srv_, json));
 
-    // returned value must be 1 (values error)
-    // as the pool does not belong to that subnet
+    // returned value should be 1 (configuration error)
     checkResult(status, 1);
     EXPECT_TRUE(errorContainsPosition(status, "<string>"));
+
+    Subnet4Ptr subnet = CfgMgr::instance().getStagingCfg()->getCfgSubnets4()->
+        selectSubnet(IOAddress("192.0.2.200"), classify_);
+    EXPECT_FALSE(subnet);
 }
 
-// Goal of this test is to verify if pools can be defined
-// using prefix/length notation. There is no separate test for min-max
-// notation as it was tested in several previous tests.
-TEST_F(Dhcp4ParserTest, poolPrefixLen) {
+// This test checks if it is not allowed to define global interface
+// parameter.
+TEST_F(Dhcp4ParserTest, interfaceGlobal) {
 
-    string config = "{ " + genIfaceConfig() + "," +
+    string config = "{ " + genIfaceConfig() + ","
         "\"rebind-timer\": 2000, "
         "\"renew-timer\": 1000, "
+        "\"interface\": \"" + valid_iface_ + "\"," // Not valid. Can be defined in subnet only
         "\"subnet4\": [ { "
         "    \"id\": 1,"
-        "    \"pools\": [ { \"pool\": \"192.0.2.128/28\" } ],"
+        "    \"pools\": [ { \"pool\": \"192.0.2.1 - 192.0.2.100\" } ],"
         "    \"subnet\": \"192.0.2.0/24\" } ],"
         "\"valid-lifetime\": 4000 }";
+    cout << config << endl;
 
-    ConstElementPtr json;
+    ConstElementPtr json = parseJSON(config);
+
+    ConstElementPtr status;
+    EXPECT_NO_THROW(status = Dhcpv4SrvTest::configure(*srv_, json));
+
+    // returned value should be 1 (parse error)
+    checkResult(status, 1);
+    EXPECT_TRUE(errorContainsPosition(status, "<string>"));
+
+    EXPECT_THROW(parseDHCP4(config), Dhcp4ParseError);
+}
+
+// Goal of this test is to verify that invalid subnet fails to be parsed.
+TEST_F(Dhcp4ParserTest, badSubnetValues) {
+
+    // Contains parts needed for a single test scenario.
+    struct Scenario {
+        std::string description_;
+        std::string config_json_;
+        std::string exp_error_msg_;
+    };
+
+    // Vector of scenarios.
+    std::vector<Scenario> scenarios = {
+        {
+        "IP is not an address",
+        "{ \"subnet4\": [ { "
+        "    \"subnet\": \"not an address/24\" } ],"
+        "\"valid-lifetime\": 4000 }",
+        "subnet configuration failed: "
+        "Failed to convert string to address 'notanaddress': Invalid argument"
+        },
+        {
+        "IP is Invalid",
+        "{ \"subnet4\": [ { "
+        "    \"subnet\": \"256.16.1.0/24\" } ],"
+        "\"valid-lifetime\": 4000 }",
+        "subnet configuration failed: "
+        "Failed to convert string to address '256.16.1.0': Invalid argument"
+        },
+        {
+        "Missing prefix",
+        "{ \"subnet4\": [ { "
+        "    \"subnet\": \"192.0.2.0\" } ],"
+        "\"valid-lifetime\": 4000 }",
+        "subnet configuration failed: "
+        "Invalid subnet syntax (prefix/len expected):192.0.2.0 (<string>:1:32)"
+        },
+        {
+        "Prefix not an integer (2 slashes)",
+        "{ \"subnet4\": [ { "
+        "    \"subnet\": \"192.0.2.0//24\" } ],"
+        "\"valid-lifetime\": 4000 }",
+        "subnet configuration failed: "
+        "prefix length: '/24' is not an integer (<string>:1:32)"
+        },
+        {
+        "Prefix value is insane",
+        "{ \"subnet4\": [ { "
+        "    \"subnet\": \"192.0.2.0/45938\" } ],"
+        "\"valid-lifetime\": 4000 }",
+        "subnet configuration failed: "
+        "Invalid prefix length specified for subnet: 45938 (<string>:1:32)"
+        }
+    };
+
+    // Iterate over the list of scenarios.  Each should fail to parse with
+    // a specific error message.
+    for (auto const& scenario : scenarios) {
+        SCOPED_TRACE(scenario.description_);
+        ConstElementPtr config;
+        ASSERT_NO_THROW(config = parseDHCP4(scenario.config_json_))
+                        << "invalid json, broken test";
+        ConstElementPtr status;
+        EXPECT_NO_THROW(status = Dhcpv4SrvTest::configure(*srv_, config));
+        checkResult(status, 1);
+        ASSERT_TRUE(comment_);
+        EXPECT_EQ(comment_->stringValue(), scenario.exp_error_msg_);
+    }
+}
+
+// This test checks that multiple pools can be defined and handled properly.
+// The test defines 2 subnets, each with 2 pools.
+TEST_F(Dhcp4ParserTest, multiplePools) {
+    // Collection with two subnets, each with 2 pools.
+    string config = "{ " + genIfaceConfig() + ","
+        "\"rebind-timer\": 2000, "
+        "\"renew-timer\": 1000, "
+        "\"subnet4\": [ { "
+        "    \"id\": 1,"
+        "    \"pools\": [ "
+        "        { \"pool\": \"192.0.2.0/28\" },"
+        "        { \"pool\": \"192.0.2.200-192.0.2.255\" }"
+        "    ],"
+        "    \"subnet\": \"192.0.2.0/24\" "
+        " },"
+        " {"
+        "    \"id\": 2,"
+        "    \"pools\": [ "
+        "    { \"pool\": \"192.0.3.0/25\" },"
+        "    { \"pool\": \"192.0.3.128/25\" }"
+        "    ],"
+        "    \"subnet\": \"192.0.3.0/24\""
+        " } ],"
+        "\"valid-lifetime\": 4000 }";
+    ConstElementPtr json;
+    ASSERT_NO_THROW(json = parseDHCP4(config));
+    extractConfig(config);
+
+    ConstElementPtr status;
+    ASSERT_NO_THROW(status = Dhcpv4SrvTest::configure(*srv_, json));
+    checkResult(status, 0);
+
+    const Subnet4Collection* subnets =
+        CfgMgr::instance().getStagingCfg()->getCfgSubnets4()->getAll();
+    ASSERT_TRUE(subnets);
+    ASSERT_EQ(2, subnets->size()); // We expect 2 subnets
+
+    // Check the first subnet
+    auto subnet = subnets->begin();
+    const PoolCollection& pools1 = (*subnet)->getPools(Lease::TYPE_V4);
+    ASSERT_EQ(2, pools1.size());
+    EXPECT_EQ("type=V4, 192.0.2.0-192.0.2.15",
+              pools1[0]->toText());
+    EXPECT_EQ("type=V4, 192.0.2.200-192.0.2.255",
+              pools1[1]->toText());
+    // There shouldn't be any TA or PD pools
+    EXPECT_THROW((*subnet)->getPools(Lease::TYPE_TA), BadValue);
+    EXPECT_THROW((*subnet)->getPools(Lease::TYPE_PD), BadValue);
+
+    // Check the second subnet
+    ++subnet;
+    const PoolCollection& pools2 = (*subnet)->getPools(Lease::TYPE_V4);
+    ASSERT_EQ(2, pools2.size());
+    EXPECT_EQ("type=V4, 192.0.3.0-192.0.3.127",
+              pools2[0]->toText());
+    EXPECT_EQ("type=V4, 192.0.3.128-192.0.3.255",
+              pools2[1]->toText());
+    // There shouldn't be any TA or PD pools
+    EXPECT_THROW((*subnet)->getPools(Lease::TYPE_TA), BadValue);
+    EXPECT_THROW((*subnet)->getPools(Lease::TYPE_PD), BadValue);
+}
+
+// Test verifies that a subnet with pool values that do not belong to that
+// pool are rejected.
+TEST_F(Dhcp4ParserTest, poolOutOfSubnet) {
+
+    string config = "{ " + genIfaceConfig() + ","
+        "\"rebind-timer\": 2000, "
+        "\"renew-timer\": 1000, "
+        "\"subnet4\": [ { "
+        "    \"id\": 1,"
+        "    \"pools\": [ { \"pool\": \"192.0.4.0/28\" } ],"
+        "    \"subnet\": \"192.0.2.0/24\" } ],"
+        "\"valid-lifetime\": 4000 }";
+
+    ConstElementPtr json;
+    ASSERT_NO_THROW(json = parseDHCP4(config));
+
+    ConstElementPtr status;
+    EXPECT_NO_THROW(status = Dhcpv4SrvTest::configure(*srv_, json));
+
+    // returned value must be 1 (values error)
+    // as the pool does not belong to that subnet
+    checkResult(status, 1);
+    EXPECT_TRUE(errorContainsPosition(status, "<string>"));
+}
+
+// Goal of this test is to verify if pools can be defined
+// using prefix/length notation. There is no separate test for min-max
+// notation as it was tested in several previous tests.
+TEST_F(Dhcp4ParserTest, poolPrefixLen) {
+    string config = "{ " + genIfaceConfig() + ","
+        "\"rebind-timer\": 2000, "
+        "\"renew-timer\": 1000, "
+        "\"subnet4\": [ { "
+        "    \"id\": 1,"
+        "    \"pools\": [ { \"pool\": \"192.0.2.128/28\" } ],"
+        "    \"subnet\": \"192.0.2.0/24\" } ],"
+        "\"valid-lifetime\": 4000 }";
+
+    ConstElementPtr json;
     ASSERT_NO_THROW(json = parseDHCP4(config));
     extractConfig(config);
 
@@ -2108,7 +2307,7 @@ TEST_F(Dhcp4ParserTest, poolPrefixLen) {
 TEST_F(Dhcp4ParserTest, badPools) {
 
     // not a prefix
-    string config_bogus1 = "{ " + genIfaceConfig() + "," +
+    string config_bogus1 = "{ " + genIfaceConfig() + ","
         "\"rebind-timer\": 2000, "
         "\"renew-timer\": 1000, "
         "\"subnet4\": [ { "
@@ -2118,7 +2317,7 @@ TEST_F(Dhcp4ParserTest, badPools) {
         "\"valid-lifetime\": 4000 }";
 
     // not a length
-    string config_bogus2 = "{ " + genIfaceConfig() + "," +
+    string config_bogus2 = "{ " + genIfaceConfig() + ","
         "\"rebind-timer\": 2000, "
         "\"renew-timer\": 1000, "
         "\"subnet4\": [ { "
@@ -2128,7 +2327,7 @@ TEST_F(Dhcp4ParserTest, badPools) {
         "\"valid-lifetime\": 4000 }";
 
     // invalid prefix length
-    string config_bogus3 = "{ " + genIfaceConfig() + "," +
+    string config_bogus3 = "{ " + genIfaceConfig() + ","
         "\"rebind-timer\": 2000, "
         "\"renew-timer\": 1000, "
         "\"subnet4\": [ { "
@@ -2138,7 +2337,7 @@ TEST_F(Dhcp4ParserTest, badPools) {
         "\"valid-lifetime\": 4000 }";
 
     // not a prefix nor a min-max
-    string config_bogus4 = "{ " + genIfaceConfig() + "," +
+    string config_bogus4 = "{ " + genIfaceConfig() + ","
         "\"rebind-timer\": 2000, "
         "\"renew-timer\": 1000, "
         "\"subnet4\": [ { "
@@ -2148,7 +2347,7 @@ TEST_F(Dhcp4ParserTest, badPools) {
         "\"valid-lifetime\": 4000 }";
 
     // not an address
-    string config_bogus5 = "{ " + genIfaceConfig() + "," +
+    string config_bogus5 = "{ " + genIfaceConfig() + ","
         "\"rebind-timer\": 2000, "
         "\"renew-timer\": 1000, "
         "\"subnet4\": [ { "
@@ -2158,7 +2357,7 @@ TEST_F(Dhcp4ParserTest, badPools) {
         "\"valid-lifetime\": 4000 }";
 
     // min > max
-    string config_bogus6 = "{ " + genIfaceConfig() + "," +
+    string config_bogus6 = "{ " + genIfaceConfig() + ","
         "\"rebind-timer\": 2000, "
         "\"renew-timer\": 1000, "
         "\"subnet4\": [ { "
@@ -2168,7 +2367,7 @@ TEST_F(Dhcp4ParserTest, badPools) {
         "\"valid-lifetime\": 4000 }";
 
     // out of range prefix length (new check)
-    string config_bogus7 = "{ " + genIfaceConfig() + "," +
+    string config_bogus7 = "{ " + genIfaceConfig() + ","
         "\"rebind-timer\": 2000, "
         "\"renew-timer\": 1000, "
         "\"subnet4\": [ { "
@@ -2241,7 +2440,7 @@ TEST_F(Dhcp4ParserTest, badPools) {
 TEST_F(Dhcp4ParserTest, noPools) {
 
     // Configuration string.
-    string config = "{ " + genIfaceConfig() + "," +
+    string config = "{ " + genIfaceConfig() + ","
         "\"rebind-timer\": 2000, "
         "\"renew-timer\": 1000, "
         "\"subnet4\": [ { "
@@ -2253,81 +2452,13 @@ TEST_F(Dhcp4ParserTest, noPools) {
     EXPECT_THROW(parseDHCP4(config, true), Dhcp4ParseError);
 }
 
-// Goal of this test is to verify that invalid subnet fails to be parsed.
-TEST_F(Dhcp4ParserTest, badSubnetValues) {
-
-    // Contains parts needed for a single test scenario.
-    struct Scenario {
-        std::string description_;
-        std::string config_json_;
-        std::string exp_error_msg_;
-    };
-
-    // Vector of scenarios.
-    std::vector<Scenario> scenarios = {
-        {
-        "IP is not an address",
-        "{ \"subnet4\": [ { "
-        "    \"subnet\": \"not an address/24\" } ],"
-        "\"valid-lifetime\": 4000 }",
-        "subnet configuration failed: "
-        "Failed to convert string to address 'notanaddress': Invalid argument"
-        },
-        {
-        "IP is Invalid",
-        "{ \"subnet4\": [ { "
-        "    \"subnet\": \"256.16.1.0/24\" } ],"
-        "\"valid-lifetime\": 4000 }",
-        "subnet configuration failed: "
-        "Failed to convert string to address '256.16.1.0': Invalid argument"
-        },
-        {
-        "Missing prefix",
-        "{ \"subnet4\": [ { "
-        "    \"subnet\": \"192.0.2.0\" } ],"
-        "\"valid-lifetime\": 4000 }",
-        "subnet configuration failed: "
-        "Invalid subnet syntax (prefix/len expected):192.0.2.0 (<string>:1:32)"
-        },
-        {
-        "Prefix not an integer (2 slashes)",
-        "{ \"subnet4\": [ { "
-        "    \"subnet\": \"192.0.2.0//24\" } ],"
-        "\"valid-lifetime\": 4000 }",
-        "subnet configuration failed: "
-        "prefix length: '/24' is not an integer (<string>:1:32)"
-        },
-        {
-        "Prefix value is insane",
-        "{ \"subnet4\": [ { "
-        "    \"subnet\": \"192.0.2.0/45938\" } ],"
-        "\"valid-lifetime\": 4000 }",
-        "subnet configuration failed: "
-        "Invalid prefix length specified for subnet: 45938 (<string>:1:32)"
-        }
-    };
-
-    // Iterate over the list of scenarios.  Each should fail to parse with
-    // a specific error message.
-    for (auto const& scenario : scenarios) {
-        SCOPED_TRACE(scenario.description_);
-        ConstElementPtr config;
-        ASSERT_NO_THROW(config = parseDHCP4(scenario.config_json_))
-                        << "invalid json, broken test";
-        ConstElementPtr status;
-        EXPECT_NO_THROW(status = Dhcpv4SrvTest::configure(*srv_, config));
-        checkResult(status, 1);
-        ASSERT_TRUE(comment_);
-        EXPECT_EQ(comment_->stringValue(), scenario.exp_error_msg_);
-    }
-}
 
 // Goal of this test is to verify that unknown interface fails
 // to be parsed.
 TEST_F(Dhcp4ParserTest, unknownInterface) {
 
     // Configuration string.
-    string config = "{ " + genIfaceConfig() + "," +
+    string config = "{ " + genIfaceConfig() + ","
         "\"rebind-timer\": 2000, "
         "\"renew-timer\": 1000, "
         "\"subnet4\": [ { "
@@ -2854,8 +2985,9 @@ TEST_F(Dhcp4ParserTest, optionDefEncapsulateOwnSpace) {
 /// used by any of the standard options.
 TEST_F(Dhcp4ParserTest, optionStandardDefOverride) {
 
-    // Configuration string. The option code 109 is unassigned so it
-    // can be used for a custom option definition in dhcp4 option space.
+    // Configuration string. The option code 109 is unassigned
+    // so it can be used for a custom option definition in
+    // dhcp4 option space.
     std::string config =
         "{ \"option-def\": [ {"
         "      \"name\": \"foo\","
@@ -2889,9 +3021,9 @@ TEST_F(Dhcp4ParserTest, optionStandardDefOverride) {
     EXPECT_EQ(OPT_STRING_TYPE, def->getType());
     EXPECT_FALSE(def->getArrayType());
 
-    // The combination of option space and code is invalid. The 'dhcp4' option
-    // space groups standard options and the code 3 is reserved for one of
-    // them.
+    // The combination of option space and code is invalid. The 'dhcp4'
+    // option space groups standard options and the code 3 is reserved
+    // for one of them.
     config =
         "{ \"option-def\": [ {"
         "      \"name\": \"routers\","
@@ -2941,7 +3073,7 @@ TEST_F(Dhcp4ParserTest, optionStandardDefOverride) {
 // Goal of this test is to verify that global option data is configured
 TEST_F(Dhcp4ParserTest, optionDataDefaultsGlobal) {
     ConstElementPtr x;
-    string config = "{ " + genIfaceConfig() + "," +
+    string config = "{ " + genIfaceConfig() + ","
         "\"rebind-timer\": 2000,"
         "\"renew-timer\": 1000,"
         "\"option-data\": [ {"
@@ -3013,7 +3145,7 @@ TEST_F(Dhcp4ParserTest, optionDataDefaultsGlobal) {
 // Goal of this test is to verify that subnet option data is configured
 TEST_F(Dhcp4ParserTest, optionDataDefaultsSubnet) {
     ConstElementPtr x;
-    string config = "{ " + genIfaceConfig() + "," +
+    string config = "{ " + genIfaceConfig() + ","
         "\"rebind-timer\": 2000,"
         "\"renew-timer\": 1000,"
         "\"subnet4\": [ { "
@@ -3089,7 +3221,7 @@ TEST_F(Dhcp4ParserTest, optionDataTwoSpaces) {
     // The definition is not required for the option that
     // belongs to the 'dhcp4' option space as it is the
     // standard option.
-    string config = "{ " + genIfaceConfig() + "," +
+    string config = "{ " + genIfaceConfig() + ","
         "\"valid-lifetime\": 4000,"
         "\"rebind-timer\": 2000,"
         "\"renew-timer\": 1000,"
@@ -3138,8 +3270,8 @@ TEST_F(Dhcp4ParserTest, optionDataTwoSpaces) {
     EXPECT_EQ(56, desc1.option_->getType());
     // Try to get the non-existing option from the non-existing
     // option space and  expect that option is not returned.
-    OptionDescriptor desc3 =
-        CfgMgr::instance().getStagingCfg()->getCfgOption()->get("non-existing", 56);
+    OptionDescriptor desc3 = CfgMgr::instance().getStagingCfg()->
+        getCfgOption()->get("non-existing", 56);
     ASSERT_FALSE(desc3.option_);
 }
 
@@ -3152,8 +3284,8 @@ TEST_F(Dhcp4ParserTest, optionDataTwoSpaces) {
 TEST_F(Dhcp4ParserTest, optionDataEncapsulate) {
 
     // @todo DHCP configurations has many dependencies between
-    // parameters. First of all, configuration for subnet was
-    // inherited from the global values. Thus subnet had to be
+    // parameters. First of all, configuration for subnet is
+    // inherited from the global values. Thus subnet has to be
     // configured when all global values have been configured.
     // Also, an option can encapsulate another option only
     // if the latter has been configured. For this reason in this
@@ -3164,7 +3296,7 @@ TEST_F(Dhcp4ParserTest, optionDataEncapsulate) {
     // at the very end (when all other parameters are configured).
 
     // Starting stage 1. Configure sub-options and their definitions.
-    string config = "{ " + genIfaceConfig() + "," +
+    string config = "{ " + genIfaceConfig() + ","
         "\"valid-lifetime\": 4000,"
         "\"rebind-timer\": 2000,"
         "\"renew-timer\": 1000,"
@@ -3207,7 +3339,7 @@ TEST_F(Dhcp4ParserTest, optionDataEncapsulate) {
     // the configuration from the stage 2 is repeated because Kea
     // configuration manager sends whole configuration for the lists
     // where at least one element is being modified or added.
-    config = "{ " + genIfaceConfig() + "," +
+    config = "{ " + genIfaceConfig() + ","
         "\"valid-lifetime\": 3000,"
         "\"rebind-timer\": 2000,"
         "\"renew-timer\": 1000,"
@@ -3288,7 +3420,7 @@ TEST_F(Dhcp4ParserTest, optionDataEncapsulate) {
 // option setting.
 TEST_F(Dhcp4ParserTest, optionDataInSingleSubnet) {
     ConstElementPtr x;
-    string config = "{ " + genIfaceConfig() + "," +
+    string config = "{ " + genIfaceConfig() + ","
         "\"rebind-timer\": 2000, "
         "\"renew-timer\": 1000, "
         "\"option-data\": [ {"
@@ -3369,8 +3501,7 @@ TEST_F(Dhcp4ParserTest, optionDataBoolean) {
                                      " boolean value"));
 
     // The subnet should now hold one option with the code 19.
-    OptionDescriptor desc = getOptionFromSubnet(IOAddress("192.0.2.24"),
-                                                        19);
+    OptionDescriptor desc = getOptionFromSubnet(IOAddress("192.0.2.24"), 19);
     ASSERT_TRUE(desc.option_);
 
     // This option should be set to "true", represented as 0x1 in the option
@@ -3432,14 +3563,13 @@ TEST_F(Dhcp4ParserTest, optionDataBoolean) {
     params["data"] = "01";
     testConfiguration(params, 19, expected_option_data,
                       sizeof(expected_option_data));
-
 }
 
 // Goal of this test is to verify options configuration
 // for multiple subnets.
 TEST_F(Dhcp4ParserTest, optionDataInMultipleSubnets) {
     ConstElementPtr x;
-    string config = "{ " + genIfaceConfig() + "," +
+    string config = "{ " + genIfaceConfig() + ","
         "\"rebind-timer\": 2000, "
         "\"renew-timer\": 1000, "
         "\"subnet4\": [ { "
@@ -3578,6 +3708,7 @@ TEST_F(Dhcp4ParserTest, optionDataSinglePool) {
     range = idx.equal_range(23);
     ASSERT_EQ(1, std::distance(range.first, range.second));
     // Do another round of testing with second option.
+
     const uint8_t foo2_expected[] = {
         0x01
     };
@@ -3692,12 +3823,19 @@ TEST_F(Dhcp4ParserTest, optionCodeNegative) {
 
 // Verify that out of bounds option code is rejected in the configuration.
 TEST_F(Dhcp4ParserTest, optionCodeNonUint8) {
-    // The valid option codes are uint16_t values so passing
-    // uint16_t maximum value incremented by 1 should result
+    // The valid option codes are uint8_t values so passing
+    // uint8_t maximum value incremented by 1 should result
     // in failure.
     testInvalidOptionParam("257", "code");
 }
 
+// Verify that out of bounds option code is rejected in the configuration.
+TEST_F(Dhcp4ParserTest, optionCodeHighNonUint8) {
+    // Another check for uint8_t overflow but this time
+    // let's pass even greater option code value.
+    testInvalidOptionParam("500", "code");
+}
+
 // Verify that zero option code is rejected in the configuration.
 TEST_F(Dhcp4ParserTest, optionCodeZero) {
     // Option code 0 is reserved and should not be accepted
@@ -3748,7 +3886,9 @@ TEST_F(Dhcp4ParserTest, optionDataValidHexLiterals) {
         // returned but in theory we may have multiple options with the same
         // code so we get the range.
         std::pair<OptionContainerTypeIndex::const_iterator,
-                OptionContainerTypeIndex::const_iterator> range = idx.equal_range(56);
+                OptionContainerTypeIndex::const_iterator> range =
+                    idx.equal_range(56);
+
         // Expect single option with the code equal to 100.
         ASSERT_EQ(1, std::distance(range.first, range.second));
         const uint8_t foo_expected[] = { 0x0A, 0x0B, 0x0C, 0x0D };
@@ -3784,8 +3924,7 @@ TEST_F(Dhcp4ParserTest, stdOptionData) {
     Subnet4Ptr subnet = CfgMgr::instance().getStagingCfg()->
         getCfgSubnets4()->selectSubnet(IOAddress("192.0.2.5"));
     ASSERT_TRUE(subnet);
-    OptionContainerPtr options =
-        subnet->getCfgOption()->getAll(DHCP4_OPTION_SPACE);
+    OptionContainerPtr options = subnet->getCfgOption()->getAll(DHCP4_OPTION_SPACE);
     ASSERT_TRUE(options);
     ASSERT_EQ(1, options->size());
 
@@ -3886,7 +4025,7 @@ TEST_F(Dhcp4ParserTest, domainSearchOption) {
 // slp-service-scope without option scope list
 TEST_F(Dhcp4ParserTest, slpOptions) {
     ConstElementPtr x;
-    string config = "{ " + genIfaceConfig() + "," +
+    string config = "{ " + genIfaceConfig() + ","
         "\"rebind-timer\": 2000,"
         "\"renew-timer\": 1000,"
         "\"option-data\": [ {"
@@ -3950,7 +4089,7 @@ TEST_F(Dhcp4ParserTest, stdOptionDataEncapsulate) {
     // In the first stage we create definitions of suboptions
     // that we will add to the base option.
     // Let's create some dummy options: foo and foo2.
-    string config = "{ " + genIfaceConfig() + "," +
+    string config = "{ " + genIfaceConfig() + ","
         "\"valid-lifetime\": 4000,"
         "\"rebind-timer\": 2000,"
         "\"renew-timer\": 1000,"
@@ -3997,7 +4136,7 @@ TEST_F(Dhcp4ParserTest, stdOptionDataEncapsulate) {
     // We add our dummy options to this option space and thus
     // they should be included as sub-options in the
     // 'vendor-encapsulated-options' option.
-    config = "{ " + genIfaceConfig() + "," +
+    config = "{ " + genIfaceConfig() + ","
         "\"valid-lifetime\": 3000,"
         "\"rebind-timer\": 2000,"
         "\"renew-timer\": 1000,"
@@ -4085,13 +4224,13 @@ TEST_F(Dhcp4ParserTest, stdOptionDataEncapsulate) {
 }
 
 // This test checks if vendor options can be specified in the config file
-// (in hex format), and later retrieved
+// (in hex format), and later retrieved from configured subnet
 TEST_F(Dhcp4ParserTest, vendorOptionsHex) {
 
     // This configuration string is to configure two options
     // sharing the code 1 and belonging to the different vendor spaces.
     // (different vendor-id values).
-    string config = "{ " + genIfaceConfig() + "," +
+    string config = "{ " + genIfaceConfig() + ","
         "\"valid-lifetime\": 4000,"
         "\"rebind-timer\": 2000,"
         "\"renew-timer\": 1000,"
@@ -4125,6 +4264,7 @@ TEST_F(Dhcp4ParserTest, vendorOptionsHex) {
     ASSERT_TRUE(status);
     checkResult(status, 0);
 
+    // Options should be now available
     // Try to get the option from the vendor space 4491
     OptionDescriptor desc1 = CfgMgr::instance().getStagingCfg()->
         getCfgOption()->get(VENDOR_ID_CABLE_LABS, 100);
@@ -4144,13 +4284,13 @@ TEST_F(Dhcp4ParserTest, vendorOptionsHex) {
 }
 
 // This test checks if vendor options can be specified in the config file,
-// (in csv format), and later retrieved
+// (in csv format), and later retrieved from configured subnet
 TEST_F(Dhcp4ParserTest, vendorOptionsCsv) {
 
     // This configuration string is to configure two options
     // sharing the code 1 and belonging to the different vendor spaces.
     // (different vendor-id values).
-    string config = "{ " + genIfaceConfig() + "," +
+    string config = "{ " + genIfaceConfig() + ","
         "\"valid-lifetime\": 4000,"
         "\"rebind-timer\": 2000,"
         "\"renew-timer\": 1000,"
@@ -4173,15 +4313,17 @@ TEST_F(Dhcp4ParserTest, vendorOptionsCsv) {
         " } ]"
         "}";
 
+    ConstElementPtr status;
+
     ConstElementPtr json;
     ASSERT_NO_THROW(json = parseDHCP4(config));
     extractConfig(config);
 
-    ConstElementPtr status;
     EXPECT_NO_THROW(status = Dhcpv4SrvTest::configure(*srv_, json));
     ASSERT_TRUE(status);
     checkResult(status, 0);
 
+    // Options should be now available.
     // Try to get the option from the vendor space 4491
     OptionDescriptor desc1 = CfgMgr::instance().getStagingCfg()->
         getCfgOption()->get(VENDOR_ID_CABLE_LABS, 100);
@@ -4204,20 +4346,22 @@ TEST_F(Dhcp4ParserTest, vendorOptionsCsv) {
 std::string
 buildHooksLibrariesConfig(const std::vector<std::string>& libraries = {},
                           bool multi_threading = true) {
+    const string lbrace("{");
+    const string rbrace("}");
+    const string liblabel("\"library\": ");
+    const string quote("\"");
 
     // Create the first part of the configuration string.
     string config =
-        "{  \"interfaces-config\": {"
-            "    \"interfaces\": [ \"*\" ]"
-            "},"
-            "\"hooks-libraries\": [";
+        "{ \"interfaces-config\": { \"interfaces\": [] },"
+           "\"hooks-libraries\": [";
 
     // Append the libraries (separated by commas if needed)
     for (unsigned int i = 0; i < libraries.size(); ++i) {
         if (i > 0) {
             config += string(", ");
         }
-        config += (string("{ \"library\": \"") + libraries[i] + string("\" }"));
+        config += (lbrace + liblabel + quote + libraries[i] + quote + rbrace);
     }
 
     // Append the remainder of the configuration.
@@ -4282,6 +4426,7 @@ TEST_F(Dhcp4ParserTest, InvalidLibrary) {
 
     ConstElementPtr json;
     ASSERT_NO_THROW(json = parseDHCP4(config));
+
     ConstElementPtr status;
     ASSERT_NO_THROW(status = Dhcpv4SrvTest::configure(*srv_, json));
 
@@ -4402,7 +4547,11 @@ TEST_F(Dhcp4ParserTest, IncompatibleLibrary3Specified) {
 TEST_F(Dhcp4ParserTest, selectedInterfaces) {
     IfaceMgrTestConfig test_config(true);
 
-    ConstElementPtr x;
+    // Make sure the config manager is clean and there is no hanging
+    // interface configuration.
+    ASSERT_FALSE(test_config.socketOpen("eth0", AF_INET));
+    ASSERT_FALSE(test_config.socketOpen("eth1", AF_INET));
+
     string config = "{ \"interfaces-config\": {"
         "  \"interfaces\": [ \"eth0\", \"eth1\" ]"
         "},"
@@ -4415,15 +4564,10 @@ TEST_F(Dhcp4ParserTest, selectedInterfaces) {
     extractConfig(config);
 
     ConstElementPtr status;
-
-    // Make sure the config manager is clean and there is no hanging
-    // interface configuration.
-    EXPECT_FALSE(test_config.socketOpen("eth0", AF_INET));
-    EXPECT_FALSE(test_config.socketOpen("eth1", AF_INET));
-
     // Apply configuration.
     EXPECT_NO_THROW(status = Dhcpv4SrvTest::configure(*srv_, json));
     ASSERT_TRUE(status);
+    // returned value must be 0 (configuration accepted)
     checkResult(status, 0);
 
     CfgMgr::instance().getStagingCfg()->getCfgIface()->openSockets(AF_INET, 10000);
@@ -4438,7 +4582,10 @@ TEST_F(Dhcp4ParserTest, selectedInterfaces) {
 TEST_F(Dhcp4ParserTest, allInterfaces) {
     IfaceMgrTestConfig test_config(true);
 
-    ConstElementPtr x;
+    // Make sure there is no old configuration.
+    ASSERT_FALSE(test_config.socketOpen("eth0", AF_INET));
+    ASSERT_FALSE(test_config.socketOpen("eth1", AF_INET));
+
     // This configuration specifies two interfaces on which server should listen
     // but it also includes asterisk. The asterisk switches server into the
     // mode when it listens on all interfaces regardless of what interface names
@@ -4456,10 +4603,6 @@ TEST_F(Dhcp4ParserTest, allInterfaces) {
 
     ConstElementPtr status;
 
-    // Make sure there is no old configuration.
-    ASSERT_FALSE(test_config.socketOpen("eth0", AF_INET));
-    ASSERT_FALSE(test_config.socketOpen("eth1", AF_INET));
-
     // Apply configuration.
     EXPECT_NO_THROW(status = Dhcpv4SrvTest::configure(*srv_, json));
     ASSERT_TRUE(status);
@@ -4512,129 +4655,11 @@ TEST_F(Dhcp4ParserTest, selectedInterfacesAndAddresses) {
     EXPECT_FALSE(test_config.socketOpen("eth1", "192.0.2.5"));
 }
 
-// This test verifies that valid d2CliengConfig works correctly.
-TEST_F(Dhcp4ParserTest, d2ClientConfigValid) {
-    ConstElementPtr status;
-
-    // Verify that the D2 configuration can be fetched and is set to disabled.
-    D2ClientConfigPtr d2_client_config = CfgMgr::instance().getD2ClientConfig();
-    EXPECT_FALSE(d2_client_config->getEnableUpdates());
-
-    // Verify that the convenience method agrees.
-    ASSERT_FALSE(CfgMgr::instance().ddnsEnabled());
-
-    string config_str = "{ " + genIfaceConfig() + "," +
-        "\"rebind-timer\": 2000, "
-        "\"renew-timer\": 1000, "
-        "\"subnet4\": [ { "
-        "    \"id\": 1,"
-        "    \"pools\": [ { \"pool\": \"192.0.2.1 - 192.0.2.100\" } ],"
-        "    \"subnet\": \"192.0.2.0/24\" } ],"
-        " \"dhcp-ddns\" : {"
-        "     \"enable-updates\" : true, "
-        "     \"server-ip\" : \"192.168.2.1\", "
-        "     \"server-port\" : 777, "
-        "     \"sender-ip\" : \"192.168.2.2\", "
-        "     \"sender-port\" : 778, "
-        "     \"max-queue-size\" : 2048, "
-        "     \"ncr-protocol\" : \"UDP\", "
-        "     \"ncr-format\" : \"JSON\"}, "
-        "\"valid-lifetime\": 4000 }";
-
-    // Convert the JSON string to configuration elements.
-    ConstElementPtr config;
-    ASSERT_NO_THROW(config = parseDHCP4(config_str, true));
-    extractConfig(config_str);
-
-    // Pass the configuration in for parsing.
-    EXPECT_NO_THROW(status = Dhcpv4SrvTest::configure(*srv_, config));
-
-    // check if returned status is OK
-    checkResult(status, 0);
-
-    // Verify that DHCP-DDNS updating is enabled.
-    EXPECT_TRUE(CfgMgr::instance().ddnsEnabled());
-
-    // Verify that the D2 configuration can be retrieved.
-    d2_client_config = CfgMgr::instance().getD2ClientConfig();
-    ASSERT_TRUE(d2_client_config);
-
-    // Verify that the configuration values are correct.
-    EXPECT_TRUE(d2_client_config->getEnableUpdates());
-    EXPECT_EQ("192.168.2.1", d2_client_config->getServerIp().toText());
-    EXPECT_EQ(777, d2_client_config->getServerPort());
-    EXPECT_EQ("192.168.2.2", d2_client_config->getSenderIp().toText());
-    EXPECT_EQ(778, d2_client_config->getSenderPort());
-    EXPECT_EQ(2048, d2_client_config->getMaxQueueSize());
-    EXPECT_EQ(dhcp_ddns::NCR_UDP, d2_client_config->getNcrProtocol());
-    EXPECT_EQ(dhcp_ddns::FMT_JSON, d2_client_config->getNcrFormat());
-
-    // ddns-send-updates should be global default
-    checkGlobal("ddns-send-updates", true);
-    checkGlobal("ddns-conflict-resolution-mode", "check-with-dhcid");
-
-    // The following, deprecated dhcp-ddns parameters,
-    // should all have global default values.
-    checkGlobal("ddns-override-no-update", false);
-    checkGlobal("ddns-override-client-update", false);
-    checkGlobal("ddns-replace-client-name", "never");
-    checkGlobal("ddns-generated-prefix", "myhost");
-    checkGlobal("ddns-qualifying-suffix", "");
-}
-
-// This test checks the ability of the server to handle a configuration
-// containing an invalid dhcp-ddns (D2ClientConfig) entry.
-TEST_F(Dhcp4ParserTest, invalidD2ClientConfig) {
-    ConstElementPtr status;
-
-    // Configuration string with an invalid D2 client config,
-    // "server-ip" is invalid.
-    string config_str = "{ " + genIfaceConfig() + "," +
-        "\"rebind-timer\": 2000, "
-        "\"renew-timer\": 1000, "
-        "\"ddns-override-no-update\" : true, "
-        "\"ddns-override-client-update\" : true, "
-        "\"ddns-replace-client-name\" : \"when-present\", "
-        "\"ddns-generated-prefix\" : \"test.prefix\", "
-        "\"ddns-qualifying-suffix\" : \"test.suffix.\", "
-        "\"subnet4\": [ { "
-        "    \"id\": 1,"
-        "    \"pools\": [ { \"pool\": \"192.0.2.1 - 192.0.2.100\" } ],"
-        "    \"subnet\": \"192.0.2.0/24\" } ],"
-        " \"dhcp-ddns\" : {"
-        "     \"enable-updates\" : true, "
-        "     \"server-ip\" : \"bogus-value\", "
-        "     \"server-port\" : 5301, "
-        "     \"ncr-protocol\" : \"UDP\", "
-        "     \"ncr-format\" : \"JSON\"},"
-        "\"valid-lifetime\": 4000 }";
-
-    // Convert the JSON string to configuration elements.
-    ConstElementPtr config;
-    ASSERT_NO_THROW(config = parseDHCP4(config_str));
-
-    // Configuration should not throw, but should fail.
-    EXPECT_NO_THROW(status = Dhcpv4SrvTest::configure(*srv_, config));
-
-    // check if returned status is failed.
-    checkResult(status, 1);
-    EXPECT_TRUE(errorContainsPosition(status, "<string>"));
-
-    // Verify that the D2 configuration can be fetched and is set to disabled.
-    D2ClientConfigPtr d2_client_config = CfgMgr::instance().getD2ClientConfig();
-    EXPECT_FALSE(d2_client_config->getEnableUpdates());
-
-    // Verify that the convenience method agrees.
-    ASSERT_FALSE(CfgMgr::instance().ddnsEnabled());
-}
-
 // This test checks if it is possible to specify relay information
 TEST_F(Dhcp4ParserTest, subnetRelayInfo) {
 
-    ConstElementPtr status;
-
     // A config with relay information.
-    string config = "{ " + genIfaceConfig() + "," +
+    string config = "{ " + genIfaceConfig() + ","
         "\"rebind-timer\": 2000, "
         "\"renew-timer\": 1000, "
         "\"subnet4\": [ { "
@@ -4653,6 +4678,7 @@ TEST_F(Dhcp4ParserTest, subnetRelayInfo) {
     ASSERT_NO_THROW(json = parseDHCP4(config));
     extractConfig(config);
 
+    ConstElementPtr status;
     EXPECT_NO_THROW(status = Dhcpv4SrvTest::configure(*srv_, json));
 
     // returned value should be 0 (configuration success)
@@ -4668,11 +4694,8 @@ TEST_F(Dhcp4ParserTest, subnetRelayInfo) {
 
 // This test checks if it is possible to specify a list of relays
 TEST_F(Dhcp4ParserTest, subnetRelayInfoList) {
-
-    ConstElementPtr status;
-
     // A config with relay information.
-    string config = "{ " + genIfaceConfig() + "," +
+    string config = "{ " + genIfaceConfig() + ","
         "\"rebind-timer\": 2000, "
         "\"renew-timer\": 1000, "
         "\"subnet4\": [ { "
@@ -4691,6 +4714,7 @@ TEST_F(Dhcp4ParserTest, subnetRelayInfoList) {
     ASSERT_NO_THROW(json = parseDHCP4(config));
     extractConfig(config);
 
+    ConstElementPtr status;
     EXPECT_NO_THROW(status = Dhcpv4SrvTest::configure(*srv_, json));
 
     // returned value should be 0 (configuration success)
@@ -4712,7 +4736,7 @@ TEST_F(Dhcp4ParserTest, subnetRelayInfoList) {
 // with defined client classes.
 TEST_F(Dhcp4ParserTest, classifySubnets) {
     ConstElementPtr x;
-    string config = "{ " + genIfaceConfig() + "," +
+    string config = "{ " + genIfaceConfig() + ","
         "\"rebind-timer\": 2000, "
         "\"renew-timer\": 1000, "
         "\"subnet4\": [ { "
@@ -4808,7 +4832,7 @@ TEST_F(Dhcp4ParserTest, classifySubnets) {
 // with defined client classes.
 TEST_F(Dhcp4ParserTest, classifyPools) {
     ConstElementPtr x;
-    string config = "{ " + genIfaceConfig() + "," +
+    string config = "{ " + genIfaceConfig() + ","
         "\"rebind-timer\": 2000, "
         "\"renew-timer\": 1000, "
         "\"subnet4\": [ { "
@@ -4846,59 +4870,172 @@ TEST_F(Dhcp4ParserTest, classifyPools) {
     const PoolCollection& pools = (*subnets->begin())->getPools(Lease::TYPE_V4);
     ASSERT_EQ(4, pools.size()); // We expect 4 pools
 
-    // Let's check if client belonging to alpha class is supported in pool[0]
-    // and not supported in any other pool (except pool[3], which allows
-    // everyone).
-    ClientClasses classes;
-    classes.insert("alpha");
-    EXPECT_TRUE(pools.at(0)->clientSupported(classes));
-    EXPECT_FALSE(pools.at(1)->clientSupported(classes));
-    EXPECT_FALSE(pools.at(2)->clientSupported(classes));
-    EXPECT_TRUE(pools.at(3)->clientSupported(classes));
+    // Let's check if client belonging to alpha class is supported in pool[0]
+    // and not supported in any other pool (except pool[3], which allows
+    // everyone).
+    ClientClasses classes;
+    classes.insert("alpha");
+    EXPECT_TRUE(pools.at(0)->clientSupported(classes));
+    EXPECT_FALSE(pools.at(1)->clientSupported(classes));
+    EXPECT_FALSE(pools.at(2)->clientSupported(classes));
+    EXPECT_TRUE(pools.at(3)->clientSupported(classes));
+
+    // Let's check if client belonging to beta class is supported in pool[1]
+    // and not supported in any other pool  (except pool[3], which allows
+    // everyone).
+    classes.clear();
+    classes.insert("beta");
+    EXPECT_FALSE(pools.at(0)->clientSupported(classes));
+    EXPECT_TRUE(pools.at(1)->clientSupported(classes));
+    EXPECT_FALSE(pools.at(2)->clientSupported(classes));
+    EXPECT_TRUE(pools.at(3)->clientSupported(classes));
+
+    // Let's check if client belonging to gamma class is supported in pool[2]
+    // and not supported in any other pool  (except pool[3], which allows
+    // everyone).
+    classes.clear();
+    classes.insert("gamma");
+    EXPECT_FALSE(pools.at(0)->clientSupported(classes));
+    EXPECT_FALSE(pools.at(1)->clientSupported(classes));
+    EXPECT_TRUE(pools.at(2)->clientSupported(classes));
+    EXPECT_TRUE(pools.at(3)->clientSupported(classes));
+
+    // Let's check if client belonging to some other class (not mentioned in
+    // the config) is supported only in pool[3], which allows everyone.
+    classes.clear();
+    classes.insert("delta");
+    EXPECT_FALSE(pools.at(0)->clientSupported(classes));
+    EXPECT_FALSE(pools.at(1)->clientSupported(classes));
+    EXPECT_FALSE(pools.at(2)->clientSupported(classes));
+    EXPECT_TRUE(pools.at(3)->clientSupported(classes));
+
+    // Finally, let's check class-less client. He should be allowed only in
+    // the last pool, which does not have any class restrictions.
+    classes.clear();
+    EXPECT_FALSE(pools.at(0)->clientSupported(classes));
+    EXPECT_FALSE(pools.at(1)->clientSupported(classes));
+    EXPECT_FALSE(pools.at(2)->clientSupported(classes));
+    EXPECT_TRUE(pools.at(3)->clientSupported(classes));
+}
+
+// This test verifies that valid d2CliengConfig works correctly.
+TEST_F(Dhcp4ParserTest, d2ClientConfigValid) {
+    // Verify that the D2 configuration can be fetched and is set to disabled.
+    D2ClientConfigPtr d2_client_config = CfgMgr::instance().getD2ClientConfig();
+    EXPECT_FALSE(d2_client_config->getEnableUpdates());
+
+    // Verify that the convenience method agrees.
+    ASSERT_FALSE(CfgMgr::instance().ddnsEnabled());
+
+    string config_str = "{ " + genIfaceConfig() + ","
+        "\"rebind-timer\": 2000, "
+        "\"renew-timer\": 1000, "
+        "\"subnet4\": [ { "
+        "    \"id\": 1,"
+        "    \"pools\": [ { \"pool\": \"192.0.2.1 - 192.0.2.100\" } ],"
+        "    \"subnet\": \"192.0.2.0/24\" } ],"
+        " \"dhcp-ddns\" : {"
+        "     \"enable-updates\" : true, "
+        "     \"server-ip\" : \"192.168.2.1\", "
+        "     \"server-port\" : 777, "
+        "     \"sender-ip\" : \"192.168.2.2\", "
+        "     \"sender-port\" : 778, "
+        "     \"max-queue-size\" : 2048, "
+        "     \"ncr-protocol\" : \"UDP\", "
+        "     \"ncr-format\" : \"JSON\"}, "
+        "\"valid-lifetime\": 4000 }";
+
+    // Convert the JSON string to configuration elements.
+    ConstElementPtr config;
+    ASSERT_NO_THROW(config = parseDHCP4(config_str, true));
+    extractConfig(config_str);
+
+    // Pass the configuration in for parsing.
+    ConstElementPtr status;
+    EXPECT_NO_THROW(status = Dhcpv4SrvTest::configure(*srv_, config));
+
+    // check if returned status is OK
+    checkResult(status, 0);
+
+    // Verify that DHCP-DDNS updating is enabled.
+    EXPECT_TRUE(CfgMgr::instance().ddnsEnabled());
+
+    // Verify that the D2 configuration can be retrieved.
+    d2_client_config = CfgMgr::instance().getD2ClientConfig();
+    ASSERT_TRUE(d2_client_config);
+
+    // Verify that the configuration values are correct.
+    EXPECT_TRUE(d2_client_config->getEnableUpdates());
+    EXPECT_EQ("192.168.2.1", d2_client_config->getServerIp().toText());
+    EXPECT_EQ(777, d2_client_config->getServerPort());
+    EXPECT_EQ("192.168.2.2", d2_client_config->getSenderIp().toText());
+    EXPECT_EQ(778, d2_client_config->getSenderPort());
+    EXPECT_EQ(2048, d2_client_config->getMaxQueueSize());
+    EXPECT_EQ(dhcp_ddns::NCR_UDP, d2_client_config->getNcrProtocol());
+    EXPECT_EQ(dhcp_ddns::FMT_JSON, d2_client_config->getNcrFormat());
+
+    // ddns-send-updates should be global default
+    checkGlobal("ddns-send-updates", true);
+    checkGlobal("ddns-conflict-resolution-mode", "check-with-dhcid");
+
+    // The following, deprecated dhcp-ddns parameters,
+    // should all have global default values.
+    checkGlobal("ddns-override-no-update", false);
+    checkGlobal("ddns-override-client-update", false);
+    checkGlobal("ddns-replace-client-name", "never");
+    checkGlobal("ddns-generated-prefix", "myhost");
+    checkGlobal("ddns-qualifying-suffix", "");
+}
+
+// This test checks the ability of the server to handle a configuration
+// containing an invalid dhcp-ddns (D2ClientConfig) entry.
+TEST_F(Dhcp4ParserTest, invalidD2ClientConfig) {
+    // Configuration string with an invalid D2 client config,
+    // "server-ip" is invalid.
+    string config_str = "{ " + genIfaceConfig() + ","
+        "\"rebind-timer\": 2000, "
+        "\"renew-timer\": 1000, "
+        "\"ddns-override-no-update\" : true, "
+        "\"ddns-override-client-update\" : true, "
+        "\"ddns-replace-client-name\" : \"when-present\", "
+        "\"ddns-generated-prefix\" : \"test.prefix\", "
+        "\"ddns-qualifying-suffix\" : \"test.suffix.\", "
+        "\"subnet4\": [ { "
+        "    \"id\": 1,"
+        "    \"pools\": [ { \"pool\": \"192.0.2.1 - 192.0.2.100\" } ],"
+        "    \"subnet\": \"192.0.2.0/24\" } ],"
+        " \"dhcp-ddns\" : {"
+        "     \"enable-updates\" : true, "
+        "     \"server-ip\" : \"bogus-value\", "
+        "     \"server-port\" : 5301, "
+        "     \"ncr-protocol\" : \"UDP\", "
+        "     \"ncr-format\" : \"JSON\"},"
+        "\"valid-lifetime\": 4000 }";
+
+    // Convert the JSON string to configuration elements.
+    ConstElementPtr config;
+    ASSERT_NO_THROW(config = parseDHCP4(config_str));
 
-    // Let's check if client belonging to beta class is supported in pool[1]
-    // and not supported in any other pool  (except pools[3], which allows
-    // everyone).
-    classes.clear();
-    classes.insert("beta");
-    EXPECT_FALSE(pools.at(0)->clientSupported(classes));
-    EXPECT_TRUE(pools.at(1)->clientSupported(classes));
-    EXPECT_FALSE(pools.at(2)->clientSupported(classes));
-    EXPECT_TRUE(pools.at(3)->clientSupported(classes));
+    // Configuration should not throw, but should fail.
+    ConstElementPtr status;
+    EXPECT_NO_THROW(status = Dhcpv4SrvTest::configure(*srv_, config));
 
-    // Let's check if client belonging to gamma class is supported in pool[2]
-    // and not supported in any other pool  (except pool[3], which allows
-    // everyone).
-    classes.clear();
-    classes.insert("gamma");
-    EXPECT_FALSE(pools.at(0)->clientSupported(classes));
-    EXPECT_FALSE(pools.at(1)->clientSupported(classes));
-    EXPECT_TRUE(pools.at(2)->clientSupported(classes));
-    EXPECT_TRUE(pools.at(3)->clientSupported(classes));
+    // check if returned status is failed.
+    checkResult(status, 1);
+    EXPECT_TRUE(errorContainsPosition(status, "<string>"));
 
-    // Let's check if client belonging to some other class (not mentioned in
-    // the config) is supported only in pool[3], which allows everyone.
-    classes.clear();
-    classes.insert("delta");
-    EXPECT_FALSE(pools.at(0)->clientSupported(classes));
-    EXPECT_FALSE(pools.at(1)->clientSupported(classes));
-    EXPECT_FALSE(pools.at(2)->clientSupported(classes));
-    EXPECT_TRUE(pools.at(3)->clientSupported(classes));
+    // Verify that the D2 configuration can be fetched and is set to disabled.
+    D2ClientConfigPtr d2_client_config = CfgMgr::instance().getD2ClientConfig();
+    EXPECT_FALSE(d2_client_config->getEnableUpdates());
 
-    // Finally, let's check class-less client. He should be allowed only in
-    // the last pool, which does not have any class restrictions.
-    classes.clear();
-    EXPECT_FALSE(pools.at(0)->clientSupported(classes));
-    EXPECT_FALSE(pools.at(1)->clientSupported(classes));
-    EXPECT_FALSE(pools.at(2)->clientSupported(classes));
-    EXPECT_TRUE(pools.at(3)->clientSupported(classes));
+    // Verify that the convenience method agrees.
+    ASSERT_FALSE(CfgMgr::instance().ddnsEnabled());
 }
-
 // This test verifies that the host reservations can be specified for
 // respective IPv4 subnets.
 TEST_F(Dhcp4ParserTest, reservations) {
     ConstElementPtr x;
-    string config = "{ " + genIfaceConfig() + "," +
+    string config = "{ " + genIfaceConfig() + ","
         "\"rebind-timer\": 2000, "
         "\"renew-timer\": 1000, "
         "\"subnet4\": [ "
@@ -4977,7 +5114,8 @@ TEST_F(Dhcp4ParserTest, reservations) {
         "        \"hostname\": \"\""
         "      }"
         "    ]"
-        " } ],"
+        " } "
+        "], "
         "\"valid-lifetime\": 4000 }";
 
     ConstElementPtr json;
@@ -5057,6 +5195,7 @@ TEST_F(Dhcp4ParserTest, reservations) {
                            circuit_id.size());
     EXPECT_TRUE(host);
     EXPECT_EQ("192.0.4.102", host->getIPv4Reservation().toText());
+
     // This reservation must not belong to other subnets.
     EXPECT_FALSE(hosts_cfg->get4(123, Host::IDENT_CIRCUIT_ID,
                                  &circuit_id[0], circuit_id.size()));
@@ -5068,6 +5207,7 @@ TEST_F(Dhcp4ParserTest, reservations) {
     host = hosts_cfg->get4(542, Host::IDENT_DUID, &duid_r[0], duid_r.size());
     ASSERT_TRUE(host);
     EXPECT_EQ("192.0.4.101", host->getIPv4Reservation().toText());
+
     EXPECT_FALSE(hosts_cfg->get4(123, Host::IDENT_DUID,
                                  &duid_r[0], duid_r.size()));
     EXPECT_FALSE(hosts_cfg->get4(234, Host::IDENT_DUID,
@@ -5102,7 +5242,7 @@ TEST_F(Dhcp4ParserTest, reservationWithOptionDefinition) {
     // The following configuration contains host declaration in which
     // a non-standard option is used. This option has option definition
     // specified in the configuration.
-    string config = "{ " + genIfaceConfig() + "," +
+    string config = "{ " + genIfaceConfig() + ","
         "\"rebind-timer\": 2000, "
         "\"renew-timer\": 1000, "
         "\"option-def\": [ {"
@@ -5129,9 +5269,9 @@ TEST_F(Dhcp4ParserTest, reservationWithOptionDefinition) {
         "    \"pools\": [ { \"pool\": \"192.0.3.101 - 192.0.3.150\" } ],"
         "    \"subnet\": \"192.0.3.0/24\", "
         "    \"id\": 234"
-        " } ],"
-        "\"valid-lifetime\": 4000"
-        "}";
+        " }"
+        "],"
+        "\"valid-lifetime\": 4000 }";
 
     ConstElementPtr json;
     ASSERT_NO_THROW(json = parseDHCP4(config, true));
@@ -5151,8 +5291,8 @@ TEST_F(Dhcp4ParserTest, reservationWithOptionDefinition) {
         duid.push_back(static_cast<uint8_t>(i));
     }
     // Retrieve the reservation and sanity check the address reserved.
-    ConstHostPtr host =
-        hosts_cfg->get4(234, Host::IDENT_DUID, &duid[0], duid.size());
+    ConstHostPtr host = hosts_cfg->get4(234, Host::IDENT_DUID,
+                                        &duid[0], duid.size());
     ASSERT_TRUE(host);
     EXPECT_EQ("192.0.3.112", host->getIPv4Reservation().toText());
 
@@ -5169,7 +5309,7 @@ TEST_F(Dhcp4ParserTest, reservationWithOptionDefinition) {
 TEST_F(Dhcp4ParserTest, reservationBogus) {
     // Case 1: misspelled hw-address parameter.
     ConstElementPtr x;
-    string config = "{ " + genIfaceConfig() + "," +
+    string config = "{ " + genIfaceConfig() + ","
         "\"rebind-timer\": 2000, "
         "\"renew-timer\": 1000, "
         "\"subnet4\": [ "
@@ -5184,7 +5324,8 @@ TEST_F(Dhcp4ParserTest, reservationBogus) {
         "        \"hostname\": \"\""
         "      }"
         "    ]"
-        " } ],"
+        " } "
+        "], "
         "\"valid-lifetime\": 4000 }";
 
     ConstElementPtr json;
@@ -5198,7 +5339,7 @@ TEST_F(Dhcp4ParserTest, reservationBogus) {
     EXPECT_THROW(parseDHCP4(config), Dhcp4ParseError);
 
     // Case 2: DUID and HW Address both specified.
-    config = "{ " + genIfaceConfig() + "," +
+    config = "{ " + genIfaceConfig() + ","
         "\"rebind-timer\": 2000, "
         "\"renew-timer\": 1000, "
         "\"subnet4\": [ "
@@ -5226,7 +5367,7 @@ TEST_F(Dhcp4ParserTest, reservationBogus) {
     checkResult(x, 1);
 
     // Case 3: Broken specification of option data.
-    config = "{ " + genIfaceConfig() + "," +
+    config = "{ " + genIfaceConfig() + ","
         "\"rebind-timer\": 2000, "
         "\"renew-timer\": 1000, "
         "\"subnet4\": [ "
@@ -5245,7 +5386,8 @@ TEST_F(Dhcp4ParserTest, reservationBogus) {
         "        ]"
         "      }"
         "    ]"
-        " } ],"
+        " } "
+        "], "
         "\"valid-lifetime\": 4000 }";
 
     ASSERT_NO_THROW(json = parseDHCP4(config));
@@ -5272,7 +5414,7 @@ TEST_F(Dhcp4ParserTest, hostReservationPerSubnet) {
     ///       - 192.0.6.0/24 (global + all enabled)
     ///       - 192.0.7.0/24 (global + out-of-pool enabled)
     const char* hr_config =
-        "{ "
+        "{"
         "\"rebind-timer\": 2000, "
         "\"renew-timer\": 1000, "
         "\"subnet4\": [ { "
@@ -5331,14 +5473,16 @@ TEST_F(Dhcp4ParserTest, hostReservationPerSubnet) {
     ConstElementPtr json;
     ASSERT_NO_THROW(json = parseDHCP4(hr_config));
     extractConfig(hr_config);
-    ConstElementPtr result;
-    EXPECT_NO_THROW(result = Dhcpv4SrvTest::configure(*srv_, json));
+
+    ConstElementPtr status;
+    EXPECT_NO_THROW(status = Dhcpv4SrvTest::configure(*srv_, json));
 
     // returned value should be 0 (success)
-    checkResult(result, 0);
+    checkResult(status, 0);
+    CfgMgr::instance().commit();
 
     // Let's get all subnets and check that there are 7 of them.
-    ConstCfgSubnets4Ptr subnets = CfgMgr::instance().getStagingCfg()->getCfgSubnets4();
+    ConstCfgSubnets4Ptr subnets = CfgMgr::instance().getCurrentCfg()->getCfgSubnets4();
     ASSERT_TRUE(subnets);
     const Subnet4Collection* subnet_col = subnets->getAll();
     ASSERT_EQ(7, subnet_col->size()); // We expect 7 subnets
@@ -5406,7 +5550,7 @@ TEST_F(Dhcp4ParserTest, hostReservationGlobal) {
     ///       - 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, "
         "\"reservations-global\": false,"
@@ -5430,14 +5574,16 @@ TEST_F(Dhcp4ParserTest, hostReservationGlobal) {
     ConstElementPtr json;
     ASSERT_NO_THROW(json = parseDHCP4(hr_config));
     extractConfig(hr_config);
-    ConstElementPtr result;
-    EXPECT_NO_THROW(result = Dhcpv4SrvTest::configure(*srv_, json));
+
+    ConstElementPtr status;
+    EXPECT_NO_THROW(status = Dhcpv4SrvTest::configure(*srv_, json));
 
     // returned value should be 0 (success)
-    checkResult(result, 0);
+    checkResult(status, 0);
+    CfgMgr::instance().commit();
 
     // Let's get all subnets and check that there are 4 of them.
-    ConstCfgSubnets4Ptr subnets = CfgMgr::instance().getStagingCfg()->getCfgSubnets4();
+    ConstCfgSubnets4Ptr subnets = CfgMgr::instance().getCurrentCfg()->getCfgSubnets4();
     ASSERT_TRUE(subnets);
     const Subnet4Collection* subnet_col = subnets->getAll();
     ASSERT_EQ(2, subnet_col->size()); // We expect 2 subnets
@@ -5450,7 +5596,7 @@ TEST_F(Dhcp4ParserTest, hostReservationGlobal) {
     ASSERT_TRUE(subnet);
     // Reset the fetch global function to staging (vs current) config.
     subnet->setFetchGlobalsFn([]() -> ConstCfgGlobalsPtr {
-        return (CfgMgr::instance().getStagingCfg()->getConfiguredGlobals());
+        return (CfgMgr::instance().getCurrentCfg()->getConfiguredGlobals());
     });
     EXPECT_FALSE(subnet->getReservationsGlobal());
     EXPECT_TRUE(subnet->getReservationsInSubnet());
@@ -5461,7 +5607,7 @@ TEST_F(Dhcp4ParserTest, hostReservationGlobal) {
     ASSERT_TRUE(subnet);
     // Reset the fetch global function to staging (vs current) config.
     subnet->setFetchGlobalsFn([]() -> ConstCfgGlobalsPtr {
-        return (CfgMgr::instance().getStagingCfg()->getConfiguredGlobals());
+        return (CfgMgr::instance().getCurrentCfg()->getConfiguredGlobals());
     });
     EXPECT_FALSE(subnet->getReservationsGlobal());
     EXPECT_TRUE(subnet->getReservationsInSubnet());
@@ -5471,16 +5617,16 @@ TEST_F(Dhcp4ParserTest, hostReservationGlobal) {
 /// Check that the decline-probation-period has a default value when not
 /// specified.
 TEST_F(Dhcp4ParserTest, declineTimerDefault) {
-    ConstElementPtr status;
 
-    string config = "{ " + genIfaceConfig() + "," +
-        "\"subnet4\": [ ]"
+    string config = "{ " + genIfaceConfig() + ","
+        "\"subnet4\": [  ] "
         "}";
 
     ConstElementPtr json;
     ASSERT_NO_THROW(json = parseDHCP4(config));
     extractConfig(config);
 
+    ConstElementPtr status;
     EXPECT_NO_THROW(status = Dhcpv4SrvTest::configure(*srv_, json));
 
     // returned value should be 0 (success)
@@ -5517,9 +5663,7 @@ TEST_F(Dhcp4ParserTest, dhcp4o6portDefault) {
 
 /// Check that the decline-probation-period value can be set properly.
 TEST_F(Dhcp4ParserTest, declineTimer) {
-    ConstElementPtr status;
-
-    string config = "{ " + genIfaceConfig() + "," +
+    string config = "{ " + genIfaceConfig() + ","
         "\"decline-probation-period\": 12345,"
         "\"subnet4\": [ ]"
         "}";
@@ -5528,6 +5672,7 @@ TEST_F(Dhcp4ParserTest, declineTimer) {
     ASSERT_NO_THROW(json = parseDHCP4(config));
     extractConfig(config);
 
+    ConstElementPtr status;
     EXPECT_NO_THROW(status = Dhcpv4SrvTest::configure(*srv_, json));
 
     // returned value should be 0 (success)
@@ -5541,9 +5686,7 @@ TEST_F(Dhcp4ParserTest, declineTimer) {
 
 /// Check that an incorrect decline-probation-period value will be caught.
 TEST_F(Dhcp4ParserTest, declineTimerError) {
-    ConstElementPtr status;
-
-    string config = "{ " + genIfaceConfig() + "," +
+    string config = "{ " + genIfaceConfig() + ","
         "\"decline-probation-period\": \"soon\","
         "\"subnet4\": [ ]"
         "}";
@@ -5551,6 +5694,7 @@ TEST_F(Dhcp4ParserTest, declineTimerError) {
     ConstElementPtr json;
     ASSERT_NO_THROW(json = parseJSON(config));
 
+    ConstElementPtr status;
     EXPECT_NO_THROW(status = Dhcpv4SrvTest::configure(*srv_, json));
 
     // returned value should be 1 (error)
@@ -5567,7 +5711,7 @@ TEST_F(Dhcp4ParserTest, declineTimerError) {
 // specified.
 TEST_F(Dhcp4ParserTest, expiredLeasesProcessing) {
     // Create basic configuration with the expiration specific parameters.
-    string config = "{ " + genIfaceConfig() + "," +
+    string config = "{ " + genIfaceConfig() + ","
         "\"expired-leases-processing\": "
         "{"
         "    \"reclaim-timer-wait-time\": 20,"
@@ -5609,7 +5753,7 @@ TEST_F(Dhcp4ParserTest, expiredLeasesProcessing) {
 TEST_F(Dhcp4ParserTest, expiredLeasesProcessingError) {
     // Create basic configuration with the expiration specific parameters.
     // One of the parameters holds invalid value.
-    string config = "{ " + genIfaceConfig() + "," +
+    string config = "{ " + genIfaceConfig() + ","
         "\"expired-leases-processing\": "
         "{"
         "    \"reclaim-timer-wait-time\": -5,"
@@ -5642,7 +5786,7 @@ TEST_F(Dhcp4ParserTest, 4o6default) {
     ConstElementPtr status;
 
     // Just a plain v4 config (no 4o6 parameters)
-    string config = "{ " + genIfaceConfig() + "," +
+    string config = "{ " + genIfaceConfig() + ","
         "\"rebind-timer\": 2000, "
         "\"renew-timer\": 1000, "
         "\"subnet4\": [ { "
@@ -5677,7 +5821,7 @@ TEST_F(Dhcp4ParserTest, 4o6subnet) {
     ConstElementPtr status;
 
     // Just a plain v4 config (no 4o6 parameters)
-    string config = "{ " + genIfaceConfig() + "," +
+    string config = "{ " + genIfaceConfig() + ","
         "\"rebind-timer\": 2000, "
         "\"renew-timer\": 1000, "
         "\"subnet4\": [ { "
@@ -5717,7 +5861,7 @@ TEST_F(Dhcp4ParserTest, 4o6subnetBogus) {
     // Just a plain v4 config (no 4o6 parameters)
     string config[] = {
         // Bogus configuration 1: missing / in subnet
-        "{ " + genIfaceConfig() + "," +
+        "{ " + genIfaceConfig() + ","
         "\"rebind-timer\": 2000, "
         "\"renew-timer\": 1000, "
         "\"subnet4\": [ { "
@@ -5728,7 +5872,7 @@ TEST_F(Dhcp4ParserTest, 4o6subnetBogus) {
         "\"valid-lifetime\": 4000 }",
 
         // Bogus configuration 2: incorrect address
-                "{ " + genIfaceConfig() + "," +
+                "{ " + genIfaceConfig() + ","
         "\"rebind-timer\": 2000, "
         "\"renew-timer\": 1000, "
         "\"subnet4\": [ { "
@@ -5739,7 +5883,7 @@ TEST_F(Dhcp4ParserTest, 4o6subnetBogus) {
         "\"valid-lifetime\": 4000 }",
 
         // Bogus configuration 3: incorrect prefix length
-        "{ " + genIfaceConfig() + "," +
+        "{ " + genIfaceConfig() + ","
         "\"rebind-timer\": 2000, "
         "\"renew-timer\": 1000, "
         "\"subnet4\": [ { "
@@ -5777,7 +5921,7 @@ TEST_F(Dhcp4ParserTest, 4o6iface) {
     ConstElementPtr status;
 
     // Just a plain v4 config (no 4o6 parameters)
-    string config = "{ " + genIfaceConfig() + "," +
+    string config = "{ " + genIfaceConfig() + ","
         "\"rebind-timer\": 2000, "
         "\"renew-timer\": 1000, "
         "\"subnet4\": [ { "
@@ -5814,7 +5958,7 @@ TEST_F(Dhcp4ParserTest, 4o6subnetIface) {
     ConstElementPtr status;
 
     // Just a plain v4 config (no 4o6 parameters)
-    string config = "{ " + genIfaceConfig() + "," +
+    string config = "{ " + genIfaceConfig() + ","
         "\"rebind-timer\": 2000, "
         "\"renew-timer\": 1000, "
         "\"subnet4\": [ { "
@@ -5855,7 +5999,7 @@ TEST_F(Dhcp4ParserTest, 4o6subnetInterfaceId) {
     ConstElementPtr status;
 
     // Just a plain v4 config (no 4o6 parameters)
-    string config = "{ " + genIfaceConfig() + "," +
+    string config = "{ " + genIfaceConfig() + ","
         "\"rebind-timer\": 2000, "
         "\"renew-timer\": 1000, "
         "\"subnet4\": [ { "
@@ -5894,7 +6038,7 @@ TEST_F(Dhcp4ParserTest, 4o6subnetInterfaceId) {
 // Verifies that simple list of valid classes parses and
 // is staged for commit.
 TEST_F(Dhcp4ParserTest, validClientClassDictionary) {
-    string config = "{ " + genIfaceConfig() + "," +
+    string config = "{ " + genIfaceConfig() + ","
         "\"valid-lifetime\": 4000, \n"
         "\"rebind-timer\": 2000, \n"
         "\"renew-timer\": 1000, \n"
@@ -5943,7 +6087,7 @@ TEST_F(Dhcp4ParserTest, validClientClassDictionary) {
 // Verifies that a class list containing an invalid
 // class definition causes a configuration error.
 TEST_F(Dhcp4ParserTest, invalidClientClassDictionary) {
-    string config = "{ " + genIfaceConfig() + "," +
+    string config = "{ " + genIfaceConfig() + ","
         "\"valid-lifetime\": 4000, \n"
         "\"rebind-timer\": 2000, \n"
         "\"renew-timer\": 1000, \n"
@@ -5966,7 +6110,7 @@ TEST_F(Dhcp4ParserTest, invalidClientClassDictionary) {
 // Verifies that simple list of valid classes parses and
 // is staged for commit.
 TEST_F(Dhcp4ParserTest, clientClassValidLifetime) {
-    string config = "{ " + genIfaceConfig() + "," +
+    string config = "{ " + genIfaceConfig() + ","
         "\"client-classes\" : [ \n"
         "   { \n"
         "       \"name\": \"one\", \n"
@@ -6022,7 +6166,7 @@ TEST_F(Dhcp4ParserTest, clientClassValidLifetime) {
 // Verifies that simple list of valid template classes parses and
 // is staged for commit.
 TEST_F(Dhcp4ParserTest, templateClientClassValidLifetime) {
-    string config = "{ " + genIfaceConfig() + "," +
+    string config = "{ " + genIfaceConfig() + ","
         "\"client-classes\" : [ \n"
         "   { \n"
         "       \"name\": \"one\", \n"
@@ -6140,7 +6284,7 @@ TEST_F(Dhcp4ParserTest, poolUserContextData) {
 
 // Test verifies that it's possible to specify parameters in the user context
 // in the min-max address pool.
-TEST_F(Dhcp4ParserTest, pooMinMaxlUserContext) {
+TEST_F(Dhcp4ParserTest, poolMinMaxUserContext) {
     extractConfig(PARSER_CONFIGS[3]);
     PoolPtr pool;
     getPool(string(PARSER_CONFIGS[3]), 0, 0, pool);
@@ -6299,12 +6443,10 @@ TEST_F(Dhcp4ParserTest, sharedNetworksName) {
 }
 
 // Test verifies that a degenerated shared-network (just one subnet) is
-// accepted.
+// accepted. Also tests that, unless explicitly specified, the subnet
+// gets default values.
 TEST_F(Dhcp4ParserTest, sharedNetworks1subnet) {
     string config = "{\n"
-        "\"valid-lifetime\": 4000, \n"
-        "\"rebind-timer\": 2000, \n"
-        "\"renew-timer\": 1000, \n"
         "\"shared-networks\": [ {\n"
         "    \"name\": \"foo\"\n,"
         "    \"subnet4\": [ { \n"
@@ -6331,11 +6473,11 @@ TEST_F(Dhcp4ParserTest, sharedNetworks1subnet) {
     ASSERT_TRUE(net);
     EXPECT_EQ("foo", net->getName());
 
-    // It should have one subnet.
+    // It should have one subnet. The subnet should have default values.
     const Subnet4SimpleCollection* subs = net->getAllSubnets();
     ASSERT_TRUE(subs);
     EXPECT_EQ(1, subs->size());
-    checkSubnet(*subs, "192.0.2.0/24", 1000, 2000, 4000);
+    checkSubnet(*subs, "192.0.2.0/24", 0, 0, 7200);
 
     // Now make sure the subnet was added to global list of subnets.
     CfgSubnets4Ptr subnets4 = CfgMgr::instance().getStagingCfg()->getCfgSubnets4();
@@ -6343,7 +6485,7 @@ TEST_F(Dhcp4ParserTest, sharedNetworks1subnet) {
 
     const Subnet4Collection* gsubs = subnets4->getAll();
     ASSERT_TRUE(gsubs);
-    checkSubnet(*gsubs, "192.0.2.0/24", 1000, 2000, 4000);
+    checkSubnet(*gsubs, "192.0.2.0/24", 0, 0, 7200);
 }
 
 // Test verifies that a proper shared-network (three subnets) is
@@ -6359,8 +6501,8 @@ TEST_F(Dhcp4ParserTest, sharedNetworks3subnets) {
         "\"valid-lifetime\": 4000, \n"
         "\"min-valid-lifetime\": 3000, \n"
         "\"max-valid-lifetime\": 5000, \n"
-        "\"rebind-timer\": 2000, \n"
         "\"renew-timer\": 1000, \n"
+        "\"rebind-timer\": 2000, \n"
         "\"shared-networks\": [ {\n"
         "    \"name\": \"foo\"\n,"
         "    \"subnet4\": [\n"
@@ -6517,6 +6659,7 @@ TEST_F(Dhcp4ParserTest, sharedNetworksDerive) {
     ASSERT_TRUE(nets);
     ASSERT_EQ(2, nets->size());
 
+    // Let's check the first one.
     SharedNetwork4Ptr net = nets->at(0);
     ASSERT_TRUE(net);
 
@@ -6588,6 +6731,130 @@ TEST_F(Dhcp4ParserTest, sharedNetworksDerive) {
     EXPECT_FALSE(s->getReservationsOutOfPool());
 }
 
+// Since it is not allowed to define both interface-id and interface
+// for the same subnet, we need dedicated test that will check
+// interface separately.
+TEST_F(Dhcp4ParserTest, sharedNetworksDeriveInterfaces) {
+
+    // We need to fake the interfaces present, because we want to test
+    // interface names inheritance. However, there are sanity checks
+    // on subnet level that would refuse the value if the interface
+    // is not present.
+    IfaceMgrTestConfig iface_config(true);
+
+    string config = "{\n"
+        "\"shared-networks\": [ {\n"
+        "    \"name\": \"foo\"\n,"
+        "    \"interface\": \"eth0\",\n"
+        "    \"rebind-timer\": 10, \n"
+        "    \"subnet4\": [\n"
+        "    { \n"
+        "        \"id\": 1, \n"
+        "        \"subnet\": \"192.0.1.0/24\",\n"
+        "        \"pools\": [ { \"pool\": \"192.0.1.1-192.0.1.10\" } ]\n"
+        "    },\n"
+        "    { \n"
+        "        \"id\": 2, \n"
+        "        \"subnet\": \"192.0.2.0/24\",\n"
+        "        \"rebind-timer\": 100, \n"
+        "        \"pools\": [ { \"pool\": \"192.0.2.1-192.0.2.10\" } ],\n"
+        "        \"interface\": \"eth0\"\n"
+        "    }\n"
+        "    ]\n"
+        " },\n"
+        "{ // second shared-network starts here\n"
+        "    \"name\": \"bar\",\n"
+        "    \"subnet4\": [\n"
+        "    {\n"
+        "        \"id\": 3, \n"
+        "        \"subnet\": \"192.0.3.0/24\",\n"
+        "        \"pools\": [ { \"pool\": \"192.0.3.1-192.0.3.10\" } ]\n"
+        "    }\n"
+        "    ]\n"
+        "} ]\n"
+        "} \n";
+
+    configure(config, CONTROL_RESULT_SUCCESS, "");
+
+    // Now verify that the shared network was indeed configured.
+    CfgSharedNetworks4Ptr cfg_net = CfgMgr::instance().getStagingCfg()
+        ->getCfgSharedNetworks4();
+
+    // Two shared networks are expected.
+    ASSERT_TRUE(cfg_net);
+    const SharedNetwork4Collection* nets = cfg_net->getAll();
+    ASSERT_TRUE(nets);
+    ASSERT_EQ(2, nets->size());
+
+    // Let's check the first one.
+    SharedNetwork4Ptr net = nets->at(0);
+    ASSERT_TRUE(net);
+
+    const Subnet4SimpleCollection* subs = net->getAllSubnets();
+    ASSERT_TRUE(subs);
+    EXPECT_EQ(2, subs->size());
+
+    // For the first subnet, the rebind-timer should be 10, because it was
+    // derived from shared-network level. Other parameters a derived
+    // from global scope to shared-network level and later again to
+    // subnet4 level.
+    Subnet4Ptr s = checkSubnet(*subs, "192.0.1.0/24", 0, 10, 7200);
+    ASSERT_TRUE(s);
+    EXPECT_EQ("eth0", s->getIface().get());
+
+    // For the second subnet, the rebind-timer should be 100, because it
+    // was specified explicitly. Other parameters a derived
+    // from global scope to shared-network level and later again to
+    // subnet4 level.
+    checkSubnet(*subs, "192.0.2.0/24", 0, 100, 7200);
+    EXPECT_EQ("eth0", s->getIface().get());
+
+    // Ok, now check the second shared subnet.
+    net = nets->at(1);
+    ASSERT_TRUE(net);
+
+    subs = net->getAllSubnets();
+    ASSERT_TRUE(subs);
+    EXPECT_EQ(1, subs->size());
+
+    // This subnet should derive its rebind-timer from global scope.
+    s = checkSubnet(*subs, "192.0.3.0/24", 0, 0, 7200);
+    EXPECT_EQ("", s->getIface().get());
+}
+
+// It is not allowed to have different values for interfaces names is subnets
+// in the same shared network.
+TEST_F(Dhcp4ParserTest, sharedNetworksInterfacesMixed) {
+
+    // We need to fake the interfaces present, because we want to test
+    // interface names inheritance. However, there are sanity checks
+    // on subnet level that would refuse the value if the interface
+    // is not present.
+    IfaceMgrTestConfig iface_config(true);
+
+    string config = "{\n"
+        "\"shared-networks\": [ {\n"
+        "    \"name\": \"foo\"\n,"
+        "    \"subnet4\": [\n"
+        "    { \n"
+        "        \"id\": 1, \n"
+        "        \"subnet\": \"192.0.1.0/24\",\n"
+        "        \"interface\": \"eth0\"\n"
+        "    },\n"
+        "    { \n"
+        "        \"id\": 2, \n"
+        "        \"subnet\": \"192.0.2.0/24\",\n"
+        "        \"interface\": \"eth1\"\n"
+        "    }\n"
+        "    ]\n"
+        " } ]\n"
+        "} \n";
+
+    configure(config, CONTROL_RESULT_ERROR, "Subnet 192.0.2.0/24 has specified "
+              "interface eth1, but earlier subnet in the same shared-network "
+              "or the shared-network itself used eth0");
+}
+
 // This test checks if client-class is derived properly.
 TEST_F(Dhcp4ParserTest, sharedNetworksDeriveClientClass) {
 
@@ -6624,7 +6891,6 @@ TEST_F(Dhcp4ParserTest, sharedNetworksDeriveClientClass) {
         "        \"pools\": [ { \"pool\": \"192.0.3.1-192.0.3.10\" } ]\n"
         "    }\n"
         "    ]\n"
-
         " } ]\n"
         "} \n";
 
@@ -6640,6 +6906,7 @@ TEST_F(Dhcp4ParserTest, sharedNetworksDeriveClientClass) {
     ASSERT_TRUE(nets);
     ASSERT_EQ(2, nets->size());
 
+    // Let's check the first one.
     SharedNetwork4Ptr net = nets->at(0);
     ASSERT_TRUE(net);
 
@@ -6659,11 +6926,12 @@ TEST_F(Dhcp4ParserTest, sharedNetworksDeriveClientClass) {
     // For the second subnet, the values are overridden on subnet level.
     // The value should not be inherited.
     s = checkSubnet(*subs, "192.0.2.0/24", 1, 2, 4);
+    ASSERT_TRUE(s);
     EXPECT_EQ("beta", s->getClientClass().get()); // beta defined on subnet level
 
-    // Ok, now check the second shared network. It doesn't have anything defined
-    // on shared-network or subnet level, so everything should have default
-    // values.
+    // Ok, now check the second shared network. It doesn't have
+    // anything defined on shared-network or subnet level, so
+    // everything should have default values.
     net = nets->at(1);
     ASSERT_TRUE(net);
 
@@ -6671,6 +6939,7 @@ TEST_F(Dhcp4ParserTest, sharedNetworksDeriveClientClass) {
     ASSERT_TRUE(subs);
     EXPECT_EQ(1, subs->size());
 
+    // This subnet should derive its renew-timer from global scope.
     s = checkSubnet(*subs, "192.0.3.0/24", 1, 2, 4);
     EXPECT_TRUE(s->getClientClass().empty());
 }
@@ -6690,13 +6959,13 @@ TEST_F(Dhcp4ParserTest, hostsDatabases) {
     ASSERT_EQ(2, hal.size());
     // Keywords are in alphabetical order
     EXPECT_EQ("name=keatest1 password=keatest type=mysql user=keatest", hal.front());
-    EXPECT_EQ("name=keatest2 password=keatest type=mysql user=keatest", hal.back());
+    EXPECT_EQ("name=keatest2 password=keatest retry-on-startup=true type=mysql user=keatest", hal.back());
 }
 
 // This test checks comments. Please keep it last.
 TEST_F(Dhcp4ParserTest, comments) {
 
-    string config = PARSER_CONFIGS[5];
+    string config = PARSER_CONFIGS[6];
     extractConfig(config);
     configure(config, CONTROL_RESULT_SUCCESS, "");
 
@@ -6896,22 +7165,12 @@ TEST_F(Dhcp4ParserTest, comments) {
     ASSERT_EQ(1, ctx_d2->size());
     ASSERT_TRUE(ctx_d2->get("comment"));
     EXPECT_EQ("\"No dynamic DNS\"", ctx_d2->get("comment")->str());
-
-#if 0
-    // Loggers section supports comments too.
-
-    string logging = "{\n"
-        "\"loggers\": [ {\n"
-        "    \"comment\": \"A logger\",\n"
-        "    \"name\": \"kea-dhcp4\"\n"
-        "} ]\n";
-#endif
 }
 
-// This test verifies that the global host reservations can be specified
+// This test verifies that the global host reservations can be specified.
 TEST_F(Dhcp4ParserTest, globalReservations) {
     ConstElementPtr x;
-    string config = "{ " + genIfaceConfig() + "," +
+    string config = "{ " + genIfaceConfig() + ","
         "\"rebind-timer\": 2000, \n"
         "\"renew-timer\": 1000,\n"
         "\"reservations\": [\n"
@@ -6956,9 +7215,9 @@ TEST_F(Dhcp4ParserTest, globalReservations) {
         "    \"pools\": [ { \"pool\": \"192.0.4.101 - 192.0.4.150\" } ],\n"
         "    \"subnet\": \"192.0.4.0/24\",\n"
         "    \"id\": 542\n"
-        " } ],\n"
-        "\"valid-lifetime\": 4000"
-        "}\n";
+        " }\n"
+        "],\n"
+        "\"valid-lifetime\": 4000 }\n";
 
     ConstElementPtr json;
     ASSERT_NO_THROW(json = parseDHCP4(config));
@@ -6991,7 +7250,14 @@ TEST_F(Dhcp4ParserTest, globalReservations) {
     ASSERT_TRUE(host);
     EXPECT_EQ("global2", host->getHostname());
 
-    // Check that options are stored correctly.
+    // This reservation should be solely assigned to the subnet 234,
+    // and not to other two.
+    EXPECT_FALSE(hosts_cfg->get4(123, Host::IDENT_HWADDR,
+                                 &hwaddr[0], hwaddr.size()));
+
+    EXPECT_FALSE(hosts_cfg->get4(542, Host::IDENT_HWADDR,
+                                 &hwaddr[0], hwaddr.size()));
+    // Check that options are assigned correctly.
     Option4AddrLstPtr opt_dns =
         retrieveOption<Option4AddrLstPtr>(*host, DHO_NAME_SERVERS);
     ASSERT_TRUE(opt_dns);
@@ -7003,14 +7269,6 @@ TEST_F(Dhcp4ParserTest, globalReservations) {
     ASSERT_TRUE(opt_ttl);
     EXPECT_EQ(11, static_cast<int>(opt_ttl->getValue()));
 
-    // This reservation should be global solely and not assigned to
-    // either subnet
-    EXPECT_FALSE(hosts_cfg->get4(123, Host::IDENT_HWADDR,
-                                 &hwaddr[0], hwaddr.size()));
-
-    EXPECT_FALSE(hosts_cfg->get4(542, Host::IDENT_HWADDR,
-                                 &hwaddr[0], hwaddr.size()));
-
     // Do the same test for the DUID based reservation.
     std::vector<uint8_t> duid;
     for (unsigned int i = 1; i < 0xb; ++i) {
@@ -7042,7 +7300,7 @@ TEST_F(Dhcp4ParserTest, globalReservations) {
 // reporting as disabled and thereby drawing attention to them.
 // This test verifies that configuration control with unsupported type fails
 TEST_F(Dhcp4ParserTest, configControlInfoNoFactory) {
-    string config = PARSER_CONFIGS[6];
+    string config = PARSER_CONFIGS[5];
 
     // Unregister "mysql" and ignore the return value.
     static_cast<void>(TestConfigBackendDHCPv4::
@@ -7058,7 +7316,7 @@ TEST_F(Dhcp4ParserTest, configControlInfoNoFactory) {
 
 // This test verifies that configuration control info gets populated.
 TEST_F(Dhcp4ParserTest, configControlInfo) {
-    string config = PARSER_CONFIGS[6];
+    string config = PARSER_CONFIGS[5];
 
     // Should be able to register a backend factory for "mysql".
     ASSERT_TRUE(TestConfigBackendDHCPv4::
@@ -7082,7 +7340,7 @@ TEST_F(Dhcp4ParserTest, configControlInfo) {
     //  alphabetical order).
     EXPECT_EQ("name=keatest1 password=keatest type=mysql user=keatest",
               dblist.front().getAccessString());
-    EXPECT_EQ("name=keatest2 password=keatest type=mysql user=keatest",
+    EXPECT_EQ("name=keatest2 password=keatest retry-on-startup=true type=mysql user=keatest",
               dblist.back().getAccessString());
 
     // Verify that the config-fetch-wait-time is correct.
@@ -7093,18 +7351,18 @@ TEST_F(Dhcp4ParserTest, configControlInfo) {
 // Check whether it is possible to configure server-tag
 TEST_F(Dhcp4ParserTest, serverTag) {
     // Config without server-tag
-    string config_no_tag = "{ " + genIfaceConfig() + "," +
+    string config_no_tag = "{ " + genIfaceConfig() + ","
         "\"subnet4\": [  ] "
         "}";
 
     // Config with server-tag
-    string config_tag = "{ " + genIfaceConfig() + "," +
+    string config_tag = "{ " + genIfaceConfig() + ","
         "\"server-tag\": \"boo\", "
         "\"subnet4\": [  ] "
         "}";
 
     // Config with an invalid server-tag
-    string bad_tag = "{ " + genIfaceConfig() + "," +
+    string bad_tag = "{ " + genIfaceConfig() + ","
         "\"server-tag\": 777, "
         "\"subnet4\": [  ] "
         "}";
@@ -7346,7 +7604,7 @@ TEST_F(Dhcp4ParserTest, calculateTeeTimesInheritence) {
         "        {  \n"
         "            \"id\": 200, \n"
         "            \"subnet\": \"192.0.2.0/24\", \n"
-        "            \"pools\": [ { \"pool\": \"192.0.2.1-192.0.2.10\"} ] \n"
+        "            \"pools\": [ { \"pool\": \"192.0.2.1-192.0.2.10\" } ] \n"
         "        } \n"
         "        ] \n"
         "     } ], \n"
@@ -7372,7 +7630,7 @@ TEST_F(Dhcp4ParserTest, calculateTeeTimesInheritence) {
     // Subnet 200 should use the shared-network values.
     subnet4 = subnets4->getBySubnetId(200);
     ASSERT_TRUE(subnet4);
-    EXPECT_EQ(true, subnet4->getCalculateTeeTimes());
+    EXPECT_TRUE(subnet4->getCalculateTeeTimes());
     EXPECT_TRUE(util::areDoublesEquivalent(0.4, subnet4->getT1Percent()));
     EXPECT_TRUE(util::areDoublesEquivalent(0.75, subnet4->getT2Percent()));
 
@@ -7387,7 +7645,7 @@ TEST_F(Dhcp4ParserTest, calculateTeeTimesInheritence) {
 // This test checks that the global store-extended-info parameter is optional
 // and that values under the subnet are used.
 TEST_F(Dhcp4ParserTest, storeExtendedInfoNoGlobal) {
-    std::string config = "{ " + genIfaceConfig() + "," +
+    const string config = "{ " + genIfaceConfig() + ","
         "\"rebind-timer\": 2000, "
         "\"renew-timer\": 1000, "
         "\"subnet4\": [ "
@@ -7413,29 +7671,31 @@ TEST_F(Dhcp4ParserTest, storeExtendedInfoNoGlobal) {
     ASSERT_NO_THROW(status = Dhcpv4SrvTest::configure(*srv_, json));
     checkResult(status, 0);
 
+    // First subnet should use global default.
     CfgSubnets4Ptr cfg = CfgMgr::instance().getStagingCfg()->getCfgSubnets4();
-    Subnet4Ptr subnet1 = cfg->selectSubnet(IOAddress("192.0.2.1"));
-    ASSERT_TRUE(subnet1);
+    Subnet4Ptr subnet = cfg->selectSubnet(IOAddress("192.0.2.1"));
+    ASSERT_TRUE(subnet);
     // Reset the fetch global function to staging (vs current) config.
-    subnet1->setFetchGlobalsFn([]() -> ConstCfgGlobalsPtr {
+    subnet->setFetchGlobalsFn([]() -> ConstCfgGlobalsPtr {
         return (CfgMgr::instance().getStagingCfg()->getConfiguredGlobals());
     });
-    EXPECT_TRUE(subnet1->getStoreExtendedInfo());
+    EXPECT_TRUE(subnet->getStoreExtendedInfo());
 
-    Subnet4Ptr subnet2 = cfg->selectSubnet(IOAddress("192.0.3.1"));
-    ASSERT_TRUE(subnet2);
+    // Second subnet should use its own value.
+    subnet = cfg->selectSubnet(IOAddress("192.0.3.1"));
+    ASSERT_TRUE(subnet);
     // Reset the fetch global function to staging (vs current) config.
-    subnet2->setFetchGlobalsFn([]() -> ConstCfgGlobalsPtr {
+    subnet->setFetchGlobalsFn([]() -> ConstCfgGlobalsPtr {
         return (CfgMgr::instance().getStagingCfg()->getConfiguredGlobals());
     });
-    EXPECT_FALSE(subnet2->getStoreExtendedInfo());
+    EXPECT_FALSE(subnet->getStoreExtendedInfo());
 }
 
 // This test checks that the global store-extended-info parameter is used
 // when there is no such parameter under subnet and that the parameter
 // specified for a subnet overrides the global setting.
 TEST_F(Dhcp4ParserTest, storeExtendedInfoGlobal) {
-    std::string config = "{ " + genIfaceConfig() + "," +
+    const string config = "{ " + genIfaceConfig() + ","
         "\"rebind-timer\": 2000, "
         "\"renew-timer\": 1000, "
         "\"store-extended-info\": true,"
@@ -7461,6 +7721,7 @@ TEST_F(Dhcp4ParserTest, storeExtendedInfoGlobal) {
     ASSERT_NO_THROW(status = Dhcpv4SrvTest::configure(*srv_, json));
     checkResult(status, 0);
 
+    // First subnet should override the global value.
     CfgSubnets4Ptr cfg = CfgMgr::instance().getStagingCfg()->getCfgSubnets4();
     Subnet4Ptr subnet1 = cfg->selectSubnet(IOAddress("192.0.2.1"));
     ASSERT_TRUE(subnet1);
@@ -7470,6 +7731,7 @@ TEST_F(Dhcp4ParserTest, storeExtendedInfoGlobal) {
     });
     EXPECT_FALSE(subnet1->getStoreExtendedInfo());
 
+    // Second subnet should use the global value.
     Subnet4Ptr subnet2 = cfg->selectSubnet(IOAddress("192.0.3.1"));
     ASSERT_TRUE(subnet2);
     // Reset the fetch global function to staging (vs current) config.
@@ -7482,7 +7744,7 @@ TEST_F(Dhcp4ParserTest, storeExtendedInfoGlobal) {
 /// This test checks that the statistic-default-sample-count and age
 /// global parameters are committed to the stats manager as expected.
 TEST_F(Dhcp4ParserTest, statsDefaultLimits) {
-    std::string config = "{ " + genIfaceConfig() + "," +
+    std::string config = "{ " + genIfaceConfig() + ","
         "\"rebind-timer\": 2000, "
         "\"renew-timer\": 1000, "
         "\"statistic-default-sample-count\": 10, "
@@ -7507,7 +7769,7 @@ TEST_F(Dhcp4ParserTest, statsDefaultLimits) {
 
 // This test checks that using default multi threading settings works.
 TEST_F(Dhcp4ParserTest, multiThreadingDefaultSettings) {
-    std::string config = "{ " + genIfaceConfig() + "," +
+    std::string config = "{ " + genIfaceConfig() + ","
         "\"subnet4\": [  ]"
         "}";
 
@@ -7544,7 +7806,7 @@ TEST_F(Dhcp4ParserTest, multiThreadingSettings) {
         "    \"thread-pool-size\": 48,\n"
         "    \"packet-queue-size\": 1024\n"
         "}";
-    std::string config = "{ " + genIfaceConfig() + "," +
+    std::string config = "{ " + genIfaceConfig() + ","
         "\"subnet4\": [  ], "
         "\"multi-threading\": " + content_json + "}";
 
@@ -7571,18 +7833,18 @@ TEST_F(Dhcp4ParserTest, multiThreadingSettings) {
 // is correct.
 TEST_F(Dhcp4ParserTest, parkedPacketLimit) {
     // Config without parked-packet-limit
-    string config_no_limit = "{ " + genIfaceConfig() + "," +
+    string config_no_limit = "{ " + genIfaceConfig() + ","
         "\"subnet4\": [  ] "
         "}";
 
     // Config with parked-packet-limit
-    string config_limit = "{ " + genIfaceConfig() + "," +
+    string config_limit = "{ " + genIfaceConfig() + ","
         "\"parked-packet-limit\": 777, "
         "\"subnet4\": [  ] "
         "}";
 
     // Config with an invalid parked-packet-limit
-    string bad_limit = "{ " + genIfaceConfig() + "," +
+    string bad_limit = "{ " + genIfaceConfig() + ","
         "\"parked-packet-limit\": \"boo\", "
         "\"subnet4\": [  ] "
         "}";
@@ -7612,7 +7874,7 @@ TEST_F(Dhcp4ParserTest, parkedPacketLimit) {
 // This test checks that ddns-conflict-resolution-mode value can be specified at
 // global and subnet levels.
 TEST_F(Dhcp4ParserTest, storeDdnsConflictResolutionMode) {
-    std::string config = "{ " + genIfaceConfig() + "," +
+    std::string config = "{ " + genIfaceConfig() + ","
         "\"rebind-timer\": 2000, "
         "\"renew-timer\": 1000, "
         "\"subnet4\": [ "
index 5e3149b9c58be2516b3c206ab65ac589ebb8707e..36ff160cb82eaf0b63c37cdd9aa7a003a187698a 100644 (file)
@@ -9,25 +9,24 @@
 #include <cc/command_interpreter.h>
 #include <cc/data.h>
 #include <cc/simple_parser.h>
-#include <cc/cfg_to_element.h>
-#include <testutils/user_context_utils.h>
 #include <dhcp/testutils/iface_mgr_test_config.h>
-#include <dhcpsrv/cfgmgr.h>
-#include <dhcpsrv/parsers/simple_parser4.h>
-#include <dhcp4/dhcp4_srv.h>
 #include <dhcp4/ctrl_dhcp4_srv.h>
+#include <dhcp4/dhcp4_srv.h>
 #include <dhcp4/json_config_parser.h>
 #include <dhcp4/tests/dhcp4_test_utils.h>
 #include <dhcp4/tests/get_config_unittest.h>
+#include <dhcpsrv/cfgmgr.h>
 #include <testutils/gtest_utils.h>
-
-#include <boost/algorithm/string.hpp>
-#include <gtest/gtest.h>
+#include <testutils/user_context_utils.h>
 
 #include <iostream>
-#include <string>
-#include <sstream>
 #include <list>
+#include <sstream>
+#include <string>
+
+#include <boost/algorithm/string.hpp>
+
+#include <gtest/gtest.h>
 
 using namespace isc::config;
 using namespace isc::data;
@@ -76,17 +75,6 @@ const char* EXTRACTED_CONFIGS[] = {
 "            \"re-detect\": false\n"
 "        },\n"
 "        \"rebind-timer\": 2000,\n"
-"        \"renew-timer\": 1000,\n"
-"        \"subnet4\": [ ],\n"
-"        \"valid-lifetime\": 4000\n"
-"    }\n",
-    // CONFIGURATION 1
-"{\n"
-"        \"interfaces-config\": {\n"
-"            \"interfaces\": [ \"*\" ],\n"
-"            \"re-detect\": false\n"
-"        },\n"
-"        \"rebind-timer\": 2000,\n"
 "        \"subnet4\": [\n"
 "            {\n"
 "                \"id\": 1,\n"
@@ -100,7 +88,7 @@ const char* EXTRACTED_CONFIGS[] = {
 "        ],\n"
 "        \"valid-lifetime\": 4000\n"
 "    }\n",
-    // CONFIGURATION 2
+    // CONFIGURATION 1
 "{\n"
 "        \"interfaces-config\": {\n"
 "            \"interfaces\": [ \"*\" ],\n"
@@ -119,6 +107,17 @@ const char* EXTRACTED_CONFIGS[] = {
 "            }\n"
 "        ],\n"
 "        \"valid-lifetime\": 4000\n"
+"    }\n",
+    // CONFIGURATION 2
+"{\n"
+"        \"interfaces-config\": {\n"
+"            \"interfaces\": [ \"*\" ],\n"
+"            \"re-detect\": false\n"
+"        },\n"
+"        \"rebind-timer\": 2000,\n"
+"        \"renew-timer\": 1000,\n"
+"        \"subnet4\": [ ],\n"
+"        \"valid-lifetime\": 4000\n"
 "    }\n",
     // CONFIGURATION 3
 "{\n"
@@ -193,6 +192,54 @@ const char* EXTRACTED_CONFIGS[] = {
 "    }\n",
     // CONFIGURATION 5
 "{\n"
+"        \"interfaces-config\": {\n"
+"            \"interfaces\": [ \"*\" ],\n"
+"            \"re-detect\": false\n"
+"        },\n"
+"        \"rebind-timer\": 2000,\n"
+"        \"renew-timer\": 1000,\n"
+"        \"subnet4\": [\n"
+"            {\n"
+"                \"id\": 1,\n"
+"                \"pools\": [\n"
+"                    {\n"
+"                        \"pool\": \"192.0.2.1 - 192.0.2.100\"\n"
+"                    }\n"
+"                ],\n"
+"                \"subnet\": \"192.0.2.0/24\"\n"
+"            },\n"
+"            {\n"
+"                \"id\": 2,\n"
+"                \"pools\": [\n"
+"                    {\n"
+"                        \"pool\": \"192.0.3.101 - 192.0.3.150\"\n"
+"                    }\n"
+"                ],\n"
+"                \"subnet\": \"192.0.3.0/24\"\n"
+"            },\n"
+"            {\n"
+"                \"id\": 3,\n"
+"                \"pools\": [\n"
+"                    {\n"
+"                        \"pool\": \"192.0.4.101 - 192.0.4.150\"\n"
+"                    }\n"
+"                ],\n"
+"                \"subnet\": \"192.0.4.0/24\"\n"
+"            },\n"
+"            {\n"
+"                \"id\": 4,\n"
+"                \"pools\": [\n"
+"                    {\n"
+"                        \"pool\": \"192.0.5.101 - 192.0.5.150\"\n"
+"                    }\n"
+"                ],\n"
+"                \"subnet\": \"192.0.5.0/24\"\n"
+"            }\n"
+"        ],\n"
+"        \"valid-lifetime\": 4000\n"
+"    }\n",
+    // CONFIGURATION 6
+"{\n"
 "        \"boot-file-name\": \"bar\",\n"
 "        \"interfaces-config\": {\n"
 "            \"interfaces\": [ \"*\" ],\n"
@@ -215,7 +262,7 @@ const char* EXTRACTED_CONFIGS[] = {
 "        ],\n"
 "        \"valid-lifetime\": 4000\n"
 "    }\n",
-    // CONFIGURATION 6
+    // CONFIGURATION 7
 "{\n"
 "        \"interfaces-config\": {\n"
 "            \"interfaces\": [ \"*\" ],\n"
@@ -239,7 +286,7 @@ const char* EXTRACTED_CONFIGS[] = {
 "        ],\n"
 "        \"valid-lifetime\": 4000\n"
 "    }\n",
-    // CONFIGURATION 7
+    // CONFIGURATION 8
 "{\n"
 "        \"boot-file-name\": \"nofile\",\n"
 "        \"interfaces-config\": {\n"
@@ -266,7 +313,7 @@ const char* EXTRACTED_CONFIGS[] = {
 "        ],\n"
 "        \"valid-lifetime\": 4000\n"
 "    }\n",
-    // CONFIGURATION 8
+    // CONFIGURATION 9
 "{\n"
 "        \"echo-client-id\": false,\n"
 "        \"interfaces-config\": {\n"
@@ -288,7 +335,7 @@ const char* EXTRACTED_CONFIGS[] = {
 "        ],\n"
 "        \"valid-lifetime\": 4000\n"
 "    }\n",
-    // CONFIGURATION 9
+    // CONFIGURATION 10
 "{\n"
 "        \"echo-client-id\": true,\n"
 "        \"interfaces-config\": {\n"
@@ -310,7 +357,7 @@ const char* EXTRACTED_CONFIGS[] = {
 "        ],\n"
 "        \"valid-lifetime\": 4000\n"
 "    }\n",
-    // CONFIGURATION 10
+    // CONFIGURATION 11
 "{\n"
 "        \"compatibility\": {\n"
 "            \"exclude-first-last-24\": true,\n"
@@ -337,7 +384,7 @@ const char* EXTRACTED_CONFIGS[] = {
 "        ],\n"
 "        \"valid-lifetime\": 4000\n"
 "    }\n",
-    // CONFIGURATION 11
+    // CONFIGURATION 12
 "{\n"
 "        \"interfaces-config\": {\n"
 "            \"interfaces\": [ \"*\" ],\n"
@@ -369,7 +416,7 @@ const char* EXTRACTED_CONFIGS[] = {
 "        ],\n"
 "        \"valid-lifetime\": 4000\n"
 "    }\n",
-    // CONFIGURATION 12
+    // CONFIGURATION 13
 "{\n"
 "        \"interfaces-config\": {\n"
 "            \"interfaces\": [ \"*\" ],\n"
@@ -401,7 +448,7 @@ const char* EXTRACTED_CONFIGS[] = {
 "        ],\n"
 "        \"valid-lifetime\": 4000\n"
 "    }\n",
-    // CONFIGURATION 13
+    // CONFIGURATION 14
 "{\n"
 "        \"interfaces-config\": {\n"
 "            \"interfaces\": [ \"*\" ],\n"
@@ -433,7 +480,7 @@ const char* EXTRACTED_CONFIGS[] = {
 "        ],\n"
 "        \"valid-lifetime\": 4000\n"
 "    }\n",
-    // CONFIGURATION 14
+    // CONFIGURATION 15
 "{\n"
 "        \"authoritative\": true,\n"
 "        \"interfaces-config\": {\n"
@@ -465,7 +512,7 @@ const char* EXTRACTED_CONFIGS[] = {
 "        ],\n"
 "        \"valid-lifetime\": 4000\n"
 "    }\n",
-    // CONFIGURATION 15
+    // CONFIGURATION 16
 "{\n"
 "        \"interfaces-config\": {\n"
 "            \"interfaces\": [ \"*\" ],\n"
@@ -493,7 +540,29 @@ const char* EXTRACTED_CONFIGS[] = {
 "        ],\n"
 "        \"valid-lifetime\": 4000\n"
 "    }\n",
-    // CONFIGURATION 16
+    // CONFIGURATION 17
+"{\n"
+"        \"interfaces-config\": {\n"
+"            \"interfaces\": [ \"*\" ],\n"
+"            \"re-detect\": false\n"
+"        },\n"
+"        \"rebind-timer\": 2000,\n"
+"        \"renew-timer\": 1000,\n"
+"        \"subnet4\": [\n"
+"            {\n"
+"                \"id\": 1,\n"
+"                \"interface\": \"eth0\",\n"
+"                \"pools\": [\n"
+"                    {\n"
+"                        \"pool\": \"192.0.2.1 - 192.0.2.100\"\n"
+"                    }\n"
+"                ],\n"
+"                \"subnet\": \"192.0.2.0/24\"\n"
+"            }\n"
+"        ],\n"
+"        \"valid-lifetime\": 4000\n"
+"    }\n",
+    // CONFIGURATION 18
 "{\n"
 "        \"interfaces-config\": {\n"
 "            \"interfaces\": [ \"*\" ],\n"
@@ -529,7 +598,7 @@ const char* EXTRACTED_CONFIGS[] = {
 "        ],\n"
 "        \"valid-lifetime\": 4000\n"
 "    }\n",
-    // CONFIGURATION 17
+    // CONFIGURATION 19
 "{\n"
 "        \"interfaces-config\": {\n"
 "            \"interfaces\": [ \"*\" ],\n"
@@ -550,7 +619,7 @@ const char* EXTRACTED_CONFIGS[] = {
 "        ],\n"
 "        \"valid-lifetime\": 4000\n"
 "    }\n",
-    // CONFIGURATION 18
+    // CONFIGURATION 20
 "{\n"
 "        \"option-def\": [\n"
 "            {\n"
@@ -561,7 +630,7 @@ const char* EXTRACTED_CONFIGS[] = {
 "            }\n"
 "        ]\n"
 "    }\n",
-    // CONFIGURATION 19
+    // CONFIGURATION 21
 "{\n"
 "        \"option-def\": [\n"
 "            {\n"
@@ -573,7 +642,7 @@ const char* EXTRACTED_CONFIGS[] = {
 "            }\n"
 "        ]\n"
 "    }\n",
-    // CONFIGURATION 20
+    // CONFIGURATION 22
 "{\n"
 "        \"option-def\": [\n"
 "            {\n"
@@ -590,7 +659,7 @@ const char* EXTRACTED_CONFIGS[] = {
 "            }\n"
 "        ]\n"
 "    }\n",
-    // CONFIGURATION 21
+    // CONFIGURATION 23
 "{\n"
 "        \"option-def\": [\n"
 "            {\n"
@@ -602,7 +671,7 @@ const char* EXTRACTED_CONFIGS[] = {
 "            }\n"
 "        ]\n"
 "    }\n",
-    // CONFIGURATION 22
+    // CONFIGURATION 24
 "{\n"
 "        \"option-def\": [\n"
 "            {\n"
@@ -614,7 +683,7 @@ const char* EXTRACTED_CONFIGS[] = {
 "            }\n"
 "        ]\n"
 "    }\n",
-    // CONFIGURATION 23
+    // CONFIGURATION 25
 "{\n"
 "        \"option-def\": [\n"
 "            {\n"
@@ -625,7 +694,7 @@ const char* EXTRACTED_CONFIGS[] = {
 "            }\n"
 "        ]\n"
 "    }\n",
-    // CONFIGURATION 24
+    // CONFIGURATION 26
 "{\n"
 "        \"option-def\": [\n"
 "            {\n"
@@ -636,7 +705,7 @@ const char* EXTRACTED_CONFIGS[] = {
 "            }\n"
 "        ]\n"
 "    }\n",
-    // CONFIGURATION 25
+    // CONFIGURATION 27
 "{\n"
 "        \"interfaces-config\": {\n"
 "            \"interfaces\": [ \"*\" ],\n"
@@ -669,7 +738,7 @@ const char* EXTRACTED_CONFIGS[] = {
 "        ],\n"
 "        \"valid-lifetime\": 4000\n"
 "    }\n",
-    // CONFIGURATION 26
+    // CONFIGURATION 28
 "{\n"
 "        \"interfaces-config\": {\n"
 "            \"interfaces\": [ \"*\" ],\n"
@@ -702,7 +771,7 @@ const char* EXTRACTED_CONFIGS[] = {
 "        ],\n"
 "        \"valid-lifetime\": 4000\n"
 "    }\n",
-    // CONFIGURATION 27
+    // CONFIGURATION 29
 "{\n"
 "        \"interfaces-config\": {\n"
 "            \"interfaces\": [ \"*\" ],\n"
@@ -743,7 +812,7 @@ const char* EXTRACTED_CONFIGS[] = {
 "        ],\n"
 "        \"valid-lifetime\": 4000\n"
 "    }\n",
-    // CONFIGURATION 28
+    // CONFIGURATION 30
 "{\n"
 "        \"interfaces-config\": {\n"
 "            \"interfaces\": [ \"*\" ],\n"
@@ -779,7 +848,7 @@ const char* EXTRACTED_CONFIGS[] = {
 "        \"renew-timer\": 1000,\n"
 "        \"valid-lifetime\": 4000\n"
 "    }\n",
-    // CONFIGURATION 29
+    // CONFIGURATION 31
 "{\n"
 "        \"interfaces-config\": {\n"
 "            \"interfaces\": [ \"*\" ],\n"
@@ -837,7 +906,7 @@ const char* EXTRACTED_CONFIGS[] = {
 "        ],\n"
 "        \"valid-lifetime\": 3000\n"
 "    }\n",
-    // CONFIGURATION 30
+    // CONFIGURATION 32
 "{\n"
 "        \"interfaces-config\": {\n"
 "            \"interfaces\": [ \"*\" ],\n"
@@ -877,7 +946,7 @@ const char* EXTRACTED_CONFIGS[] = {
 "        ],\n"
 "        \"valid-lifetime\": 4000\n"
 "    }\n",
-    // CONFIGURATION 31
+    // CONFIGURATION 33
 "{\n"
 "        \"interfaces-config\": {\n"
 "            \"interfaces\": [ \"*\" ],\n"
@@ -921,7 +990,7 @@ const char* EXTRACTED_CONFIGS[] = {
 "        ],\n"
 "        \"valid-lifetime\": 4000\n"
 "    }\n",
-    // CONFIGURATION 32
+    // CONFIGURATION 34
 "{\n"
 "        \"interfaces-config\": {\n"
 "            \"interfaces\": [ \"*\" ],\n"
@@ -954,7 +1023,7 @@ const char* EXTRACTED_CONFIGS[] = {
 "        ],\n"
 "        \"valid-lifetime\": 4000\n"
 "    }\n",
-    // CONFIGURATION 33
+    // CONFIGURATION 35
 "{\n"
 "        \"interfaces-config\": {\n"
 "            \"interfaces\": [ \"*\" ],\n"
@@ -992,7 +1061,7 @@ const char* EXTRACTED_CONFIGS[] = {
 "        ],\n"
 "        \"valid-lifetime\": 4000\n"
 "    }\n",
-    // CONFIGURATION 34
+    // CONFIGURATION 36
 "{\n"
 "        \"interfaces-config\": {\n"
 "            \"interfaces\": [ \"*\" ],\n"
@@ -1023,7 +1092,7 @@ const char* EXTRACTED_CONFIGS[] = {
 "        ],\n"
 "        \"valid-lifetime\": 4000\n"
 "    }\n",
-    // CONFIGURATION 35
+    // CONFIGURATION 37
 "{\n"
 "        \"interfaces-config\": {\n"
 "            \"interfaces\": [ \"*\" ],\n"
@@ -1059,7 +1128,7 @@ const char* EXTRACTED_CONFIGS[] = {
 "        \"renew-timer\": 1000,\n"
 "        \"valid-lifetime\": 4000\n"
 "    }\n",
-    // CONFIGURATION 36
+    // CONFIGURATION 38
 "{\n"
 "        \"interfaces-config\": {\n"
 "            \"interfaces\": [ \"*\" ],\n"
@@ -1112,7 +1181,7 @@ const char* EXTRACTED_CONFIGS[] = {
 "        ],\n"
 "        \"valid-lifetime\": 3000\n"
 "    }\n",
-    // CONFIGURATION 37
+    // CONFIGURATION 39
 "{\n"
 "        \"interfaces-config\": {\n"
 "            \"interfaces\": [ \"*\" ],\n"
@@ -1149,7 +1218,7 @@ const char* EXTRACTED_CONFIGS[] = {
 "        ],\n"
 "        \"valid-lifetime\": 4000\n"
 "    }\n",
-    // CONFIGURATION 38
+    // CONFIGURATION 40
 "{\n"
 "        \"interfaces-config\": {\n"
 "            \"interfaces\": [ \"*\" ],\n"
@@ -1186,7 +1255,7 @@ const char* EXTRACTED_CONFIGS[] = {
 "        ],\n"
 "        \"valid-lifetime\": 4000\n"
 "    }\n",
-    // CONFIGURATION 39
+    // CONFIGURATION 41
 "{\n"
 "        \"interfaces-config\": {\n"
 "            \"interfaces\": [ \"eth0\", \"eth1\" ],\n"
@@ -1196,7 +1265,7 @@ const char* EXTRACTED_CONFIGS[] = {
 "        \"renew-timer\": 1000,\n"
 "        \"valid-lifetime\": 4000\n"
 "    }\n",
-    // CONFIGURATION 40
+    // CONFIGURATION 42
 "{\n"
 "        \"interfaces-config\": {\n"
 "            \"interfaces\": [ \"eth0\", \"*\", \"eth1\" ],\n"
@@ -1206,38 +1275,7 @@ const char* EXTRACTED_CONFIGS[] = {
 "        \"renew-timer\": 1000,\n"
 "        \"valid-lifetime\": 4000\n"
 "    }\n",
-    // CONFIGURATION 41
-"{\n"
-"        \"dhcp-ddns\": {\n"
-"            \"enable-updates\": true,\n"
-"            \"max-queue-size\": 2048,\n"
-"            \"ncr-format\": \"JSON\",\n"
-"            \"ncr-protocol\": \"UDP\",\n"
-"            \"sender-ip\": \"192.168.2.2\",\n"
-"            \"sender-port\": 778,\n"
-"            \"server-ip\": \"192.168.2.1\",\n"
-"            \"server-port\": 777\n"
-"        },\n"
-"        \"interfaces-config\": {\n"
-"            \"interfaces\": [ \"*\" ],\n"
-"            \"re-detect\": false\n"
-"        },\n"
-"        \"rebind-timer\": 2000,\n"
-"        \"renew-timer\": 1000,\n"
-"        \"subnet4\": [\n"
-"            {\n"
-"                \"id\": 1,\n"
-"                \"pools\": [\n"
-"                    {\n"
-"                        \"pool\": \"192.0.2.1 - 192.0.2.100\"\n"
-"                    }\n"
-"                ],\n"
-"                \"subnet\": \"192.0.2.0/24\"\n"
-"            }\n"
-"        ],\n"
-"        \"valid-lifetime\": 4000\n"
-"    }\n",
-    // CONFIGURATION 42
+    // CONFIGURATION 43
 "{\n"
 "        \"interfaces-config\": {\n"
 "            \"interfaces\": [ \"*\" ],\n"
@@ -1264,7 +1302,7 @@ const char* EXTRACTED_CONFIGS[] = {
 "        ],\n"
 "        \"valid-lifetime\": 4000\n"
 "    }\n",
-    // CONFIGURATION 43
+    // CONFIGURATION 44
 "{\n"
 "        \"interfaces-config\": {\n"
 "            \"interfaces\": [ \"*\" ],\n"
@@ -1291,7 +1329,7 @@ const char* EXTRACTED_CONFIGS[] = {
 "        ],\n"
 "        \"valid-lifetime\": 4000\n"
 "    }\n",
-    // CONFIGURATION 44
+    // CONFIGURATION 45
 "{\n"
 "        \"interfaces-config\": {\n"
 "            \"interfaces\": [ \"*\" ],\n"
@@ -1342,7 +1380,7 @@ const char* EXTRACTED_CONFIGS[] = {
 "        ],\n"
 "        \"valid-lifetime\": 4000\n"
 "    }\n",
-    // CONFIGURATION 45
+    // CONFIGURATION 46
 "{\n"
 "        \"interfaces-config\": {\n"
 "            \"interfaces\": [ \"*\" ],\n"
@@ -1375,7 +1413,38 @@ const char* EXTRACTED_CONFIGS[] = {
 "        ],\n"
 "        \"valid-lifetime\": 4000\n"
 "    }\n",
-    // CONFIGURATION 46
+    // CONFIGURATION 47
+"{\n"
+"        \"dhcp-ddns\": {\n"
+"            \"enable-updates\": true,\n"
+"            \"max-queue-size\": 2048,\n"
+"            \"ncr-format\": \"JSON\",\n"
+"            \"ncr-protocol\": \"UDP\",\n"
+"            \"sender-ip\": \"192.168.2.2\",\n"
+"            \"sender-port\": 778,\n"
+"            \"server-ip\": \"192.168.2.1\",\n"
+"            \"server-port\": 777\n"
+"        },\n"
+"        \"interfaces-config\": {\n"
+"            \"interfaces\": [ \"*\" ],\n"
+"            \"re-detect\": false\n"
+"        },\n"
+"        \"rebind-timer\": 2000,\n"
+"        \"renew-timer\": 1000,\n"
+"        \"subnet4\": [\n"
+"            {\n"
+"                \"id\": 1,\n"
+"                \"pools\": [\n"
+"                    {\n"
+"                        \"pool\": \"192.0.2.1 - 192.0.2.100\"\n"
+"                    }\n"
+"                ],\n"
+"                \"subnet\": \"192.0.2.0/24\"\n"
+"            }\n"
+"        ],\n"
+"        \"valid-lifetime\": 4000\n"
+"    }\n",
+    // CONFIGURATION 48
 "{\n"
 "        \"interfaces-config\": {\n"
 "            \"interfaces\": [ \"*\" ],\n"
@@ -1474,7 +1543,7 @@ const char* EXTRACTED_CONFIGS[] = {
 "        ],\n"
 "        \"valid-lifetime\": 4000\n"
 "    }\n",
-    // CONFIGURATION 47
+    // CONFIGURATION 49
 "{\n"
 "        \"interfaces-config\": {\n"
 "            \"interfaces\": [ \"*\" ],\n"
@@ -1516,7 +1585,7 @@ const char* EXTRACTED_CONFIGS[] = {
 "        ],\n"
 "        \"valid-lifetime\": 4000\n"
 "    }\n",
-    // CONFIGURATION 48
+    // CONFIGURATION 50
 "{\n"
 "        \"rebind-timer\": 2000,\n"
 "        \"renew-timer\": 1000,\n"
@@ -1603,7 +1672,7 @@ const char* EXTRACTED_CONFIGS[] = {
 "        ],\n"
 "        \"valid-lifetime\": 4000\n"
 "    }\n",
-    // CONFIGURATION 49
+    // CONFIGURATION 51
 "{\n"
 "        \"rebind-timer\": 2000,\n"
 "        \"renew-timer\": 1000,\n"
@@ -1635,7 +1704,7 @@ const char* EXTRACTED_CONFIGS[] = {
 "        ],\n"
 "        \"valid-lifetime\": 4000\n"
 "    }\n",
-    // CONFIGURATION 50
+    // CONFIGURATION 52
 "{\n"
 "        \"interfaces-config\": {\n"
 "            \"interfaces\": [ \"*\" ],\n"
@@ -1643,7 +1712,7 @@ const char* EXTRACTED_CONFIGS[] = {
 "        },\n"
 "        \"subnet4\": [ ]\n"
 "    }\n",
-    // CONFIGURATION 51
+    // CONFIGURATION 53
 "{\n"
 "        \"interfaces-config\": {\n"
 "            \"interfaces\": [ \"*\" ],\n"
@@ -1651,7 +1720,7 @@ const char* EXTRACTED_CONFIGS[] = {
 "        },\n"
 "        \"subnet4\": [ ]\n"
 "    }\n",
-    // CONFIGURATION 52
+    // CONFIGURATION 54
 "{\n"
 "        \"decline-probation-period\": 12345,\n"
 "        \"interfaces-config\": {\n"
@@ -1660,7 +1729,7 @@ const char* EXTRACTED_CONFIGS[] = {
 "        },\n"
 "        \"subnet4\": [ ]\n"
 "    }\n",
-    // CONFIGURATION 53
+    // CONFIGURATION 55
 "{\n"
 "        \"expired-leases-processing\": {\n"
 "            \"flush-reclaimed-timer-wait-time\": 35,\n"
@@ -1676,7 +1745,7 @@ const char* EXTRACTED_CONFIGS[] = {
 "        },\n"
 "        \"subnet4\": [ ]\n"
 "    }\n",
-    // CONFIGURATION 54
+    // CONFIGURATION 56
 "{\n"
 "        \"interfaces-config\": {\n"
 "            \"interfaces\": [ \"*\" ],\n"
@@ -1697,7 +1766,7 @@ const char* EXTRACTED_CONFIGS[] = {
 "        ],\n"
 "        \"valid-lifetime\": 4000\n"
 "    }\n",
-    // CONFIGURATION 55
+    // CONFIGURATION 57
 "{\n"
 "        \"interfaces-config\": {\n"
 "            \"interfaces\": [ \"*\" ],\n"
@@ -1719,7 +1788,7 @@ const char* EXTRACTED_CONFIGS[] = {
 "        ],\n"
 "        \"valid-lifetime\": 4000\n"
 "    }\n",
-    // CONFIGURATION 56
+    // CONFIGURATION 58
 "{\n"
 "        \"interfaces-config\": {\n"
 "            \"interfaces\": [ \"*\" ],\n"
@@ -1741,7 +1810,7 @@ const char* EXTRACTED_CONFIGS[] = {
 "        ],\n"
 "        \"valid-lifetime\": 4000\n"
 "    }\n",
-    // CONFIGURATION 57
+    // CONFIGURATION 59
 "{\n"
 "        \"interfaces-config\": {\n"
 "            \"interfaces\": [ \"*\" ],\n"
@@ -1764,7 +1833,7 @@ const char* EXTRACTED_CONFIGS[] = {
 "        ],\n"
 "        \"valid-lifetime\": 4000\n"
 "    }\n",
-    // CONFIGURATION 58
+    // CONFIGURATION 60
 "{\n"
 "        \"interfaces-config\": {\n"
 "            \"interfaces\": [ \"*\" ],\n"
@@ -1786,7 +1855,7 @@ const char* EXTRACTED_CONFIGS[] = {
 "        ],\n"
 "        \"valid-lifetime\": 4000\n"
 "    }\n",
-    // CONFIGURATION 59
+    // CONFIGURATION 61
 "{\n"
 "        \"client-classes\": [\n"
 "            {\n"
@@ -1818,7 +1887,7 @@ const char* EXTRACTED_CONFIGS[] = {
 "        ],\n"
 "        \"valid-lifetime\": 4000\n"
 "    }\n",
-    // CONFIGURATION 60
+    // CONFIGURATION 62
 "{\n"
 "        \"client-classes\": [\n"
 "            {\n"
@@ -1847,7 +1916,7 @@ const char* EXTRACTED_CONFIGS[] = {
 "            }\n"
 "        ]\n"
 "    }\n",
-    // CONFIGURATION 61
+    // CONFIGURATION 63
 "{\n"
 "        \"client-classes\": [\n"
 "            {\n"
@@ -1878,7 +1947,7 @@ const char* EXTRACTED_CONFIGS[] = {
 "            }\n"
 "        ]\n"
 "    }\n",
-    // CONFIGURATION 62
+    // CONFIGURATION 64
 "{\n"
 "        \"interfaces-config\": {\n"
 "            \"interfaces\": [ \"*\" ],\n"
@@ -1899,7 +1968,7 @@ const char* EXTRACTED_CONFIGS[] = {
 "        ],\n"
 "        \"valid-lifetime\": 4000\n"
 "    }\n",
-    // CONFIGURATION 63
+    // CONFIGURATION 65
 "{\n"
 "        \"interfaces-config\": {\n"
 "            \"interfaces\": [ \"*\" ],\n"
@@ -1921,7 +1990,7 @@ const char* EXTRACTED_CONFIGS[] = {
 "        ],\n"
 "        \"valid-lifetime\": 4000\n"
 "    }\n",
-    // CONFIGURATION 64
+    // CONFIGURATION 66
 "{\n"
 "        \"interfaces-config\": {\n"
 "            \"interfaces\": [ \"*\" ],\n"
@@ -1947,7 +2016,7 @@ const char* EXTRACTED_CONFIGS[] = {
 "        ],\n"
 "        \"valid-lifetime\": 4000\n"
 "    }\n",
-    // CONFIGURATION 65
+    // CONFIGURATION 67
 "{\n"
 "        \"interfaces-config\": {\n"
 "            \"interfaces\": [ \"*\" ],\n"
@@ -1973,7 +2042,7 @@ const char* EXTRACTED_CONFIGS[] = {
 "        ],\n"
 "        \"valid-lifetime\": 4000\n"
 "    }\n",
-    // CONFIGURATION 66
+    // CONFIGURATION 68
 "{\n"
 "        \"hosts-databases\": [\n"
 "            {\n"
@@ -1985,6 +2054,7 @@ const char* EXTRACTED_CONFIGS[] = {
 "            {\n"
 "                \"name\": \"keatest2\",\n"
 "                \"password\": \"keatest\",\n"
+"                \"retry-on-startup\": true,\n"
 "                \"type\": \"mysql\",\n"
 "                \"user\": \"keatest\"\n"
 "            }\n"
@@ -1997,7 +2067,7 @@ const char* EXTRACTED_CONFIGS[] = {
 "        \"renew-timer\": 1000,\n"
 "        \"valid-lifetime\": 4000\n"
 "    }\n",
-    // CONFIGURATION 67
+    // CONFIGURATION 69
 "{\n"
 "        \"client-classes\": [\n"
 "            {\n"
@@ -2106,7 +2176,7 @@ const char* EXTRACTED_CONFIGS[] = {
 "            \"comment\": \"A DHCPv4 server\"\n"
 "        }\n"
 "    }\n",
-    // CONFIGURATION 68
+    // CONFIGURATION 70
 "{\n"
 "        \"interfaces-config\": {\n"
 "            \"interfaces\": [ \"*\" ],\n"
@@ -2168,7 +2238,7 @@ const char* EXTRACTED_CONFIGS[] = {
 "        ],\n"
 "        \"valid-lifetime\": 4000\n"
 "    }\n",
-    // CONFIGURATION 69
+    // CONFIGURATION 71
 "{\n"
 "        \"interfaces-config\": {\n"
 "            \"interfaces\": [ \"*\" ],\n"
@@ -2218,7 +2288,7 @@ const char* EXTRACTED_CONFIGS[] = {
 "        ],\n"
 "        \"valid-lifetime\": 4000\n"
 "    }\n",
-    // CONFIGURATION 70
+    // CONFIGURATION 72
 "{\n"
 "        \"interfaces-config\": {\n"
 "            \"interfaces\": [ \"*\" ],\n"
@@ -2250,7 +2320,7 @@ const char* EXTRACTED_CONFIGS[] = {
 "        ],\n"
 "        \"valid-lifetime\": 4000\n"
 "    }\n",
-    // CONFIGURATION 71
+    // CONFIGURATION 73
 "{\n"
 "        \"interfaces-config\": {\n"
 "            \"interfaces\": [ \"*\" ],\n"
@@ -2282,7 +2352,7 @@ const char* EXTRACTED_CONFIGS[] = {
 "        ],\n"
 "        \"valid-lifetime\": 4000\n"
 "    }\n",
-    // CONFIGURATION 72
+    // CONFIGURATION 74
 "{\n"
 "        \"interfaces-config\": {\n"
 "            \"interfaces\": [ \"*\" ],\n"
@@ -2294,7 +2364,7 @@ const char* EXTRACTED_CONFIGS[] = {
 "        \"statistic-default-sample-count\": 10,\n"
 "        \"valid-lifetime\": 4000\n"
 "    }\n",
-    // CONFIGURATION 73
+    // CONFIGURATION 75
 "{\n"
 "        \"interfaces-config\": {\n"
 "            \"interfaces\": [ \"*\" ],\n"
@@ -2302,7 +2372,7 @@ const char* EXTRACTED_CONFIGS[] = {
 "        },\n"
 "        \"subnet4\": [ ]\n"
 "    }\n",
-    // CONFIGURATION 74
+    // CONFIGURATION 76
 "{\n"
 "        \"interfaces-config\": {\n"
 "            \"interfaces\": [ \"*\" ],\n"
@@ -2315,7 +2385,7 @@ const char* EXTRACTED_CONFIGS[] = {
 "        },\n"
 "        \"subnet4\": [ ]\n"
 "    }\n",
-    // CONFIGURATION 75
+    // CONFIGURATION 77
 "{\n"
 "        \"ddns-conflict-resolution-mode\": \"no-check-with-dhcid\",\n"
 "        \"interfaces-config\": {\n"
@@ -2445,7 +2515,6 @@ const char* UNPARSED_CONFIGS[] = {
 "        \"option-def\": [ ],\n"
 "        \"parked-packet-limit\": 256,\n"
 "        \"rebind-timer\": 2000,\n"
-"        \"renew-timer\": 1000,\n"
 "        \"reservations-global\": false,\n"
 "        \"reservations-in-subnet\": true,\n"
 "        \"reservations-lookup-first\": false,\n"
@@ -2461,7 +2530,35 @@ const char* UNPARSED_CONFIGS[] = {
 "        \"statistic-default-sample-age\": 0,\n"
 "        \"statistic-default-sample-count\": 20,\n"
 "        \"store-extended-info\": false,\n"
-"        \"subnet4\": [ ],\n"
+"        \"subnet4\": [\n"
+"            {\n"
+"                \"4o6-interface\": \"\",\n"
+"                \"4o6-interface-id\": \"\",\n"
+"                \"4o6-subnet\": \"\",\n"
+"                \"allocator\": \"iterative\",\n"
+"                \"calculate-tee-times\": false,\n"
+"                \"id\": 1,\n"
+"                \"max-valid-lifetime\": 4000,\n"
+"                \"min-valid-lifetime\": 4000,\n"
+"                \"option-data\": [ ],\n"
+"                \"pools\": [\n"
+"                    {\n"
+"                        \"option-data\": [ ],\n"
+"                        \"pool\": \"192.0.2.1-192.0.2.100\"\n"
+"                    }\n"
+"                ],\n"
+"                \"rebind-timer\": 2000,\n"
+"                \"relay\": {\n"
+"                    \"ip-addresses\": [ ]\n"
+"                },\n"
+"                \"reservations\": [ ],\n"
+"                \"store-extended-info\": false,\n"
+"                \"subnet\": \"192.0.2.0/24\",\n"
+"                \"t1-percent\": 0.5,\n"
+"                \"t2-percent\": 0.875,\n"
+"                \"valid-lifetime\": 4000\n"
+"            }\n"
+"        ],\n"
 "        \"t1-percent\": 0.5,\n"
 "        \"t2-percent\": 0.875,\n"
 "        \"valid-lifetime\": 4000\n"
@@ -2529,7 +2626,7 @@ const char* UNPARSED_CONFIGS[] = {
 "        \"option-data\": [ ],\n"
 "        \"option-def\": [ ],\n"
 "        \"parked-packet-limit\": 256,\n"
-"        \"rebind-timer\": 2000,\n"
+"        \"renew-timer\": 1000,\n"
 "        \"reservations-global\": false,\n"
 "        \"reservations-in-subnet\": true,\n"
 "        \"reservations-lookup-first\": false,\n"
@@ -2562,10 +2659,10 @@ const char* UNPARSED_CONFIGS[] = {
 "                        \"pool\": \"192.0.2.1-192.0.2.100\"\n"
 "                    }\n"
 "                ],\n"
-"                \"rebind-timer\": 2000,\n"
 "                \"relay\": {\n"
 "                    \"ip-addresses\": [ ]\n"
 "                },\n"
+"                \"renew-timer\": 1000,\n"
 "                \"reservations\": [ ],\n"
 "                \"store-extended-info\": false,\n"
 "                \"subnet\": \"192.0.2.0/24\",\n"
@@ -2641,6 +2738,94 @@ const char* UNPARSED_CONFIGS[] = {
 "        \"option-data\": [ ],\n"
 "        \"option-def\": [ ],\n"
 "        \"parked-packet-limit\": 256,\n"
+"        \"rebind-timer\": 2000,\n"
+"        \"renew-timer\": 1000,\n"
+"        \"reservations-global\": false,\n"
+"        \"reservations-in-subnet\": true,\n"
+"        \"reservations-lookup-first\": false,\n"
+"        \"reservations-out-of-pool\": false,\n"
+"        \"sanity-checks\": {\n"
+"            \"extended-info-checks\": \"fix\",\n"
+"            \"lease-checks\": \"warn\"\n"
+"        },\n"
+"        \"server-hostname\": \"\",\n"
+"        \"server-tag\": \"\",\n"
+"        \"shared-networks\": [ ],\n"
+"        \"stash-agent-options\": false,\n"
+"        \"statistic-default-sample-age\": 0,\n"
+"        \"statistic-default-sample-count\": 20,\n"
+"        \"store-extended-info\": false,\n"
+"        \"subnet4\": [ ],\n"
+"        \"t1-percent\": 0.5,\n"
+"        \"t2-percent\": 0.875,\n"
+"        \"valid-lifetime\": 4000\n"
+"    }\n",
+    // CONFIGURATION 3
+"{\n"
+"        \"allocator\": \"iterative\",\n"
+"        \"authoritative\": false,\n"
+"        \"boot-file-name\": \"\",\n"
+"        \"calculate-tee-times\": false,\n"
+"        \"ddns-conflict-resolution-mode\": \"check-with-dhcid\",\n"
+"        \"ddns-generated-prefix\": \"myhost\",\n"
+"        \"ddns-override-client-update\": false,\n"
+"        \"ddns-override-no-update\": false,\n"
+"        \"ddns-qualifying-suffix\": \"\",\n"
+"        \"ddns-replace-client-name\": \"never\",\n"
+"        \"ddns-send-updates\": true,\n"
+"        \"ddns-update-on-renew\": false,\n"
+"        \"decline-probation-period\": 86400,\n"
+"        \"dhcp-ddns\": {\n"
+"            \"enable-updates\": false,\n"
+"            \"max-queue-size\": 1024,\n"
+"            \"ncr-format\": \"JSON\",\n"
+"            \"ncr-protocol\": \"UDP\",\n"
+"            \"sender-ip\": \"0.0.0.0\",\n"
+"            \"sender-port\": 0,\n"
+"            \"server-ip\": \"127.0.0.1\",\n"
+"            \"server-port\": 53001\n"
+"        },\n"
+"        \"dhcp-queue-control\": {\n"
+"            \"capacity\": 64,\n"
+"            \"enable-queue\": false,\n"
+"            \"queue-type\": \"kea-ring4\"\n"
+"        },\n"
+"        \"dhcp4o6-port\": 0,\n"
+"        \"early-global-reservations-lookup\": false,\n"
+"        \"echo-client-id\": true,\n"
+"        \"expired-leases-processing\": {\n"
+"            \"flush-reclaimed-timer-wait-time\": 25,\n"
+"            \"hold-reclaimed-time\": 3600,\n"
+"            \"max-reclaim-leases\": 100,\n"
+"            \"max-reclaim-time\": 250,\n"
+"            \"reclaim-timer-wait-time\": 10,\n"
+"            \"unwarned-reclaim-cycles\": 5\n"
+"        },\n"
+"        \"hooks-libraries\": [ ],\n"
+"        \"host-reservation-identifiers\": [ \"hw-address\", \"duid\", \"circuit-id\", \"client-id\" ],\n"
+"        \"hostname-char-replacement\": \"\",\n"
+"        \"hostname-char-set\": \"[^A-Za-z0-9.-]\",\n"
+"        \"interfaces-config\": {\n"
+"            \"interfaces\": [ \"*\" ],\n"
+"            \"re-detect\": false\n"
+"        },\n"
+"        \"ip-reservations-unique\": true,\n"
+"        \"lease-database\": {\n"
+"            \"type\": \"memfile\"\n"
+"        },\n"
+"        \"match-client-id\": true,\n"
+"        \"max-valid-lifetime\": 5000,\n"
+"        \"min-valid-lifetime\": 3000,\n"
+"        \"multi-threading\": {\n"
+"            \"enable-multi-threading\": true,\n"
+"            \"packet-queue-size\": 64,\n"
+"            \"thread-pool-size\": 0\n"
+"        },\n"
+"        \"next-server\": \"0.0.0.0\",\n"
+"        \"option-data\": [ ],\n"
+"        \"option-def\": [ ],\n"
+"        \"parked-packet-limit\": 256,\n"
+"        \"rebind-timer\": 2000,\n"
 "        \"renew-timer\": 1000,\n"
 "        \"reservations-global\": false,\n"
 "        \"reservations-in-subnet\": true,\n"
@@ -2665,8 +2850,8 @@ const char* UNPARSED_CONFIGS[] = {
 "                \"allocator\": \"iterative\",\n"
 "                \"calculate-tee-times\": false,\n"
 "                \"id\": 1,\n"
-"                \"max-valid-lifetime\": 4000,\n"
-"                \"min-valid-lifetime\": 4000,\n"
+"                \"max-valid-lifetime\": 5000,\n"
+"                \"min-valid-lifetime\": 3000,\n"
 "                \"option-data\": [ ],\n"
 "                \"pools\": [\n"
 "                    {\n"
@@ -2674,6 +2859,7 @@ const char* UNPARSED_CONFIGS[] = {
 "                        \"pool\": \"192.0.2.1-192.0.2.100\"\n"
 "                    }\n"
 "                ],\n"
+"                \"rebind-timer\": 2000,\n"
 "                \"relay\": {\n"
 "                    \"ip-addresses\": [ ]\n"
 "                },\n"
@@ -2690,7 +2876,7 @@ const char* UNPARSED_CONFIGS[] = {
 "        \"t2-percent\": 0.875,\n"
 "        \"valid-lifetime\": 4000\n"
 "    }\n",
-    // CONFIGURATION 3
+    // CONFIGURATION 4
 "{\n"
 "        \"allocator\": \"iterative\",\n"
 "        \"authoritative\": false,\n"
@@ -2744,8 +2930,6 @@ const char* UNPARSED_CONFIGS[] = {
 "            \"type\": \"memfile\"\n"
 "        },\n"
 "        \"match-client-id\": true,\n"
-"        \"max-valid-lifetime\": 5000,\n"
-"        \"min-valid-lifetime\": 3000,\n"
 "        \"multi-threading\": {\n"
 "            \"enable-multi-threading\": true,\n"
 "            \"packet-queue-size\": 64,\n"
@@ -2780,8 +2964,92 @@ const char* UNPARSED_CONFIGS[] = {
 "                \"allocator\": \"iterative\",\n"
 "                \"calculate-tee-times\": false,\n"
 "                \"id\": 1,\n"
-"                \"max-valid-lifetime\": 5000,\n"
-"                \"min-valid-lifetime\": 3000,\n"
+"                \"max-valid-lifetime\": 4000,\n"
+"                \"min-valid-lifetime\": 4000,\n"
+"                \"option-data\": [ ],\n"
+"                \"pools\": [\n"
+"                    {\n"
+"                        \"option-data\": [ ],\n"
+"                        \"pool\": \"192.0.4.101-192.0.4.150\"\n"
+"                    }\n"
+"                ],\n"
+"                \"rebind-timer\": 2000,\n"
+"                \"relay\": {\n"
+"                    \"ip-addresses\": [ ]\n"
+"                },\n"
+"                \"renew-timer\": 1000,\n"
+"                \"reservations\": [ ],\n"
+"                \"store-extended-info\": false,\n"
+"                \"subnet\": \"192.0.4.0/24\",\n"
+"                \"t1-percent\": 0.5,\n"
+"                \"t2-percent\": 0.875,\n"
+"                \"valid-lifetime\": 4000\n"
+"            },\n"
+"            {\n"
+"                \"4o6-interface\": \"\",\n"
+"                \"4o6-interface-id\": \"\",\n"
+"                \"4o6-subnet\": \"\",\n"
+"                \"allocator\": \"iterative\",\n"
+"                \"calculate-tee-times\": false,\n"
+"                \"id\": 34,\n"
+"                \"max-valid-lifetime\": 4000,\n"
+"                \"min-valid-lifetime\": 4000,\n"
+"                \"option-data\": [ ],\n"
+"                \"pools\": [\n"
+"                    {\n"
+"                        \"option-data\": [ ],\n"
+"                        \"pool\": \"192.0.5.101-192.0.5.150\"\n"
+"                    }\n"
+"                ],\n"
+"                \"rebind-timer\": 2000,\n"
+"                \"relay\": {\n"
+"                    \"ip-addresses\": [ ]\n"
+"                },\n"
+"                \"renew-timer\": 1000,\n"
+"                \"reservations\": [ ],\n"
+"                \"store-extended-info\": false,\n"
+"                \"subnet\": \"192.0.5.0/24\",\n"
+"                \"t1-percent\": 0.5,\n"
+"                \"t2-percent\": 0.875,\n"
+"                \"valid-lifetime\": 4000\n"
+"            },\n"
+"            {\n"
+"                \"4o6-interface\": \"\",\n"
+"                \"4o6-interface-id\": \"\",\n"
+"                \"4o6-subnet\": \"\",\n"
+"                \"allocator\": \"iterative\",\n"
+"                \"calculate-tee-times\": false,\n"
+"                \"id\": 100,\n"
+"                \"max-valid-lifetime\": 4000,\n"
+"                \"min-valid-lifetime\": 4000,\n"
+"                \"option-data\": [ ],\n"
+"                \"pools\": [\n"
+"                    {\n"
+"                        \"option-data\": [ ],\n"
+"                        \"pool\": \"192.0.3.101-192.0.3.150\"\n"
+"                    }\n"
+"                ],\n"
+"                \"rebind-timer\": 2000,\n"
+"                \"relay\": {\n"
+"                    \"ip-addresses\": [ ]\n"
+"                },\n"
+"                \"renew-timer\": 1000,\n"
+"                \"reservations\": [ ],\n"
+"                \"store-extended-info\": false,\n"
+"                \"subnet\": \"192.0.3.0/24\",\n"
+"                \"t1-percent\": 0.5,\n"
+"                \"t2-percent\": 0.875,\n"
+"                \"valid-lifetime\": 4000\n"
+"            },\n"
+"            {\n"
+"                \"4o6-interface\": \"\",\n"
+"                \"4o6-interface-id\": \"\",\n"
+"                \"4o6-subnet\": \"\",\n"
+"                \"allocator\": \"iterative\",\n"
+"                \"calculate-tee-times\": false,\n"
+"                \"id\": 1024,\n"
+"                \"max-valid-lifetime\": 4000,\n"
+"                \"min-valid-lifetime\": 4000,\n"
 "                \"option-data\": [ ],\n"
 "                \"pools\": [\n"
 "                    {\n"
@@ -2806,7 +3074,7 @@ const char* UNPARSED_CONFIGS[] = {
 "        \"t2-percent\": 0.875,\n"
 "        \"valid-lifetime\": 4000\n"
 "    }\n",
-    // CONFIGURATION 4
+    // CONFIGURATION 5
 "{\n"
 "        \"allocator\": \"iterative\",\n"
 "        \"authoritative\": false,\n"
@@ -2900,7 +3168,7 @@ const char* UNPARSED_CONFIGS[] = {
 "                \"pools\": [\n"
 "                    {\n"
 "                        \"option-data\": [ ],\n"
-"                        \"pool\": \"192.0.4.101-192.0.4.150\"\n"
+"                        \"pool\": \"192.0.2.1-192.0.2.100\"\n"
 "                    }\n"
 "                ],\n"
 "                \"rebind-timer\": 2000,\n"
@@ -2910,7 +3178,7 @@ const char* UNPARSED_CONFIGS[] = {
 "                \"renew-timer\": 1000,\n"
 "                \"reservations\": [ ],\n"
 "                \"store-extended-info\": false,\n"
-"                \"subnet\": \"192.0.4.0/24\",\n"
+"                \"subnet\": \"192.0.2.0/24\",\n"
 "                \"t1-percent\": 0.5,\n"
 "                \"t2-percent\": 0.875,\n"
 "                \"valid-lifetime\": 4000\n"
@@ -2921,14 +3189,14 @@ const char* UNPARSED_CONFIGS[] = {
 "                \"4o6-subnet\": \"\",\n"
 "                \"allocator\": \"iterative\",\n"
 "                \"calculate-tee-times\": false,\n"
-"                \"id\": 34,\n"
+"                \"id\": 2,\n"
 "                \"max-valid-lifetime\": 4000,\n"
 "                \"min-valid-lifetime\": 4000,\n"
 "                \"option-data\": [ ],\n"
 "                \"pools\": [\n"
 "                    {\n"
 "                        \"option-data\": [ ],\n"
-"                        \"pool\": \"192.0.5.101-192.0.5.150\"\n"
+"                        \"pool\": \"192.0.3.101-192.0.3.150\"\n"
 "                    }\n"
 "                ],\n"
 "                \"rebind-timer\": 2000,\n"
@@ -2938,7 +3206,7 @@ const char* UNPARSED_CONFIGS[] = {
 "                \"renew-timer\": 1000,\n"
 "                \"reservations\": [ ],\n"
 "                \"store-extended-info\": false,\n"
-"                \"subnet\": \"192.0.5.0/24\",\n"
+"                \"subnet\": \"192.0.3.0/24\",\n"
 "                \"t1-percent\": 0.5,\n"
 "                \"t2-percent\": 0.875,\n"
 "                \"valid-lifetime\": 4000\n"
@@ -2949,14 +3217,14 @@ const char* UNPARSED_CONFIGS[] = {
 "                \"4o6-subnet\": \"\",\n"
 "                \"allocator\": \"iterative\",\n"
 "                \"calculate-tee-times\": false,\n"
-"                \"id\": 100,\n"
+"                \"id\": 3,\n"
 "                \"max-valid-lifetime\": 4000,\n"
 "                \"min-valid-lifetime\": 4000,\n"
 "                \"option-data\": [ ],\n"
 "                \"pools\": [\n"
 "                    {\n"
 "                        \"option-data\": [ ],\n"
-"                        \"pool\": \"192.0.3.101-192.0.3.150\"\n"
+"                        \"pool\": \"192.0.4.101-192.0.4.150\"\n"
 "                    }\n"
 "                ],\n"
 "                \"rebind-timer\": 2000,\n"
@@ -2966,7 +3234,7 @@ const char* UNPARSED_CONFIGS[] = {
 "                \"renew-timer\": 1000,\n"
 "                \"reservations\": [ ],\n"
 "                \"store-extended-info\": false,\n"
-"                \"subnet\": \"192.0.3.0/24\",\n"
+"                \"subnet\": \"192.0.4.0/24\",\n"
 "                \"t1-percent\": 0.5,\n"
 "                \"t2-percent\": 0.875,\n"
 "                \"valid-lifetime\": 4000\n"
@@ -2977,14 +3245,14 @@ const char* UNPARSED_CONFIGS[] = {
 "                \"4o6-subnet\": \"\",\n"
 "                \"allocator\": \"iterative\",\n"
 "                \"calculate-tee-times\": false,\n"
-"                \"id\": 1024,\n"
+"                \"id\": 4,\n"
 "                \"max-valid-lifetime\": 4000,\n"
 "                \"min-valid-lifetime\": 4000,\n"
 "                \"option-data\": [ ],\n"
 "                \"pools\": [\n"
 "                    {\n"
 "                        \"option-data\": [ ],\n"
-"                        \"pool\": \"192.0.2.1-192.0.2.100\"\n"
+"                        \"pool\": \"192.0.5.101-192.0.5.150\"\n"
 "                    }\n"
 "                ],\n"
 "                \"rebind-timer\": 2000,\n"
@@ -2994,7 +3262,7 @@ const char* UNPARSED_CONFIGS[] = {
 "                \"renew-timer\": 1000,\n"
 "                \"reservations\": [ ],\n"
 "                \"store-extended-info\": false,\n"
-"                \"subnet\": \"192.0.2.0/24\",\n"
+"                \"subnet\": \"192.0.5.0/24\",\n"
 "                \"t1-percent\": 0.5,\n"
 "                \"t2-percent\": 0.875,\n"
 "                \"valid-lifetime\": 4000\n"
@@ -3004,7 +3272,7 @@ const char* UNPARSED_CONFIGS[] = {
 "        \"t2-percent\": 0.875,\n"
 "        \"valid-lifetime\": 4000\n"
 "    }\n",
-    // CONFIGURATION 5
+    // CONFIGURATION 6
 "{\n"
 "        \"allocator\": \"iterative\",\n"
 "        \"authoritative\": false,\n"
@@ -3118,7 +3386,7 @@ const char* UNPARSED_CONFIGS[] = {
 "        \"t2-percent\": 0.875,\n"
 "        \"valid-lifetime\": 4000\n"
 "    }\n",
-    // CONFIGURATION 6
+    // CONFIGURATION 7
 "{\n"
 "        \"allocator\": \"iterative\",\n"
 "        \"authoritative\": false,\n"
@@ -3235,7 +3503,7 @@ const char* UNPARSED_CONFIGS[] = {
 "        \"t2-percent\": 0.875,\n"
 "        \"valid-lifetime\": 4000\n"
 "    }\n",
-    // CONFIGURATION 7
+    // CONFIGURATION 8
 "{\n"
 "        \"allocator\": \"iterative\",\n"
 "        \"authoritative\": false,\n"
@@ -3352,7 +3620,7 @@ const char* UNPARSED_CONFIGS[] = {
 "        \"t2-percent\": 0.875,\n"
 "        \"valid-lifetime\": 4000\n"
 "    }\n",
-    // CONFIGURATION 8
+    // CONFIGURATION 9
 "{\n"
 "        \"allocator\": \"iterative\",\n"
 "        \"authoritative\": false,\n"
@@ -3466,7 +3734,7 @@ const char* UNPARSED_CONFIGS[] = {
 "        \"t2-percent\": 0.875,\n"
 "        \"valid-lifetime\": 4000\n"
 "    }\n",
-    // CONFIGURATION 9
+    // CONFIGURATION 10
 "{\n"
 "        \"allocator\": \"iterative\",\n"
 "        \"authoritative\": false,\n"
@@ -3580,7 +3848,7 @@ const char* UNPARSED_CONFIGS[] = {
 "        \"t2-percent\": 0.875,\n"
 "        \"valid-lifetime\": 4000\n"
 "    }\n",
-    // CONFIGURATION 10
+    // CONFIGURATION 11
 "{\n"
 "        \"allocator\": \"iterative\",\n"
 "        \"authoritative\": false,\n"
@@ -3673,14 +3941,158 @@ const char* UNPARSED_CONFIGS[] = {
 "                \"4o6-subnet\": \"\",\n"
 "                \"allocator\": \"iterative\",\n"
 "                \"calculate-tee-times\": false,\n"
-"                \"id\": 1,\n"
+"                \"id\": 1,\n"
+"                \"max-valid-lifetime\": 4000,\n"
+"                \"min-valid-lifetime\": 4000,\n"
+"                \"option-data\": [ ],\n"
+"                \"pools\": [\n"
+"                    {\n"
+"                        \"option-data\": [ ],\n"
+"                        \"pool\": \"192.0.2.1-192.0.2.100\"\n"
+"                    }\n"
+"                ],\n"
+"                \"rebind-timer\": 2000,\n"
+"                \"relay\": {\n"
+"                    \"ip-addresses\": [ ]\n"
+"                },\n"
+"                \"renew-timer\": 1000,\n"
+"                \"reservations\": [ ],\n"
+"                \"store-extended-info\": false,\n"
+"                \"subnet\": \"192.0.2.0/24\",\n"
+"                \"t1-percent\": 0.5,\n"
+"                \"t2-percent\": 0.875,\n"
+"                \"valid-lifetime\": 4000\n"
+"            }\n"
+"        ],\n"
+"        \"t1-percent\": 0.5,\n"
+"        \"t2-percent\": 0.875,\n"
+"        \"valid-lifetime\": 4000\n"
+"    }\n",
+    // CONFIGURATION 12
+"{\n"
+"        \"allocator\": \"iterative\",\n"
+"        \"authoritative\": false,\n"
+"        \"boot-file-name\": \"\",\n"
+"        \"calculate-tee-times\": false,\n"
+"        \"ddns-conflict-resolution-mode\": \"check-with-dhcid\",\n"
+"        \"ddns-generated-prefix\": \"myhost\",\n"
+"        \"ddns-override-client-update\": false,\n"
+"        \"ddns-override-no-update\": false,\n"
+"        \"ddns-qualifying-suffix\": \"\",\n"
+"        \"ddns-replace-client-name\": \"never\",\n"
+"        \"ddns-send-updates\": true,\n"
+"        \"ddns-update-on-renew\": false,\n"
+"        \"decline-probation-period\": 86400,\n"
+"        \"dhcp-ddns\": {\n"
+"            \"enable-updates\": false,\n"
+"            \"max-queue-size\": 1024,\n"
+"            \"ncr-format\": \"JSON\",\n"
+"            \"ncr-protocol\": \"UDP\",\n"
+"            \"sender-ip\": \"0.0.0.0\",\n"
+"            \"sender-port\": 0,\n"
+"            \"server-ip\": \"127.0.0.1\",\n"
+"            \"server-port\": 53001\n"
+"        },\n"
+"        \"dhcp-queue-control\": {\n"
+"            \"capacity\": 64,\n"
+"            \"enable-queue\": false,\n"
+"            \"queue-type\": \"kea-ring4\"\n"
+"        },\n"
+"        \"dhcp4o6-port\": 0,\n"
+"        \"early-global-reservations-lookup\": false,\n"
+"        \"echo-client-id\": true,\n"
+"        \"expired-leases-processing\": {\n"
+"            \"flush-reclaimed-timer-wait-time\": 25,\n"
+"            \"hold-reclaimed-time\": 3600,\n"
+"            \"max-reclaim-leases\": 100,\n"
+"            \"max-reclaim-time\": 250,\n"
+"            \"reclaim-timer-wait-time\": 10,\n"
+"            \"unwarned-reclaim-cycles\": 5\n"
+"        },\n"
+"        \"hooks-libraries\": [ ],\n"
+"        \"host-reservation-identifiers\": [ \"hw-address\", \"duid\", \"circuit-id\", \"client-id\" ],\n"
+"        \"hostname-char-replacement\": \"\",\n"
+"        \"hostname-char-set\": \"[^A-Za-z0-9.-]\",\n"
+"        \"interfaces-config\": {\n"
+"            \"interfaces\": [ \"*\" ],\n"
+"            \"re-detect\": false\n"
+"        },\n"
+"        \"ip-reservations-unique\": true,\n"
+"        \"lease-database\": {\n"
+"            \"type\": \"memfile\"\n"
+"        },\n"
+"        \"match-client-id\": true,\n"
+"        \"multi-threading\": {\n"
+"            \"enable-multi-threading\": true,\n"
+"            \"packet-queue-size\": 64,\n"
+"            \"thread-pool-size\": 0\n"
+"        },\n"
+"        \"next-server\": \"0.0.0.0\",\n"
+"        \"option-data\": [ ],\n"
+"        \"option-def\": [ ],\n"
+"        \"parked-packet-limit\": 256,\n"
+"        \"rebind-timer\": 2000,\n"
+"        \"renew-timer\": 1000,\n"
+"        \"reservations-global\": false,\n"
+"        \"reservations-in-subnet\": true,\n"
+"        \"reservations-lookup-first\": false,\n"
+"        \"reservations-out-of-pool\": false,\n"
+"        \"sanity-checks\": {\n"
+"            \"extended-info-checks\": \"fix\",\n"
+"            \"lease-checks\": \"warn\"\n"
+"        },\n"
+"        \"server-hostname\": \"\",\n"
+"        \"server-tag\": \"\",\n"
+"        \"shared-networks\": [ ],\n"
+"        \"stash-agent-options\": false,\n"
+"        \"statistic-default-sample-age\": 0,\n"
+"        \"statistic-default-sample-count\": 20,\n"
+"        \"store-extended-info\": false,\n"
+"        \"subnet4\": [\n"
+"            {\n"
+"                \"4o6-interface\": \"\",\n"
+"                \"4o6-interface-id\": \"\",\n"
+"                \"4o6-subnet\": \"\",\n"
+"                \"allocator\": \"iterative\",\n"
+"                \"calculate-tee-times\": false,\n"
+"                \"id\": 1,\n"
+"                \"match-client-id\": true,\n"
+"                \"max-valid-lifetime\": 4000,\n"
+"                \"min-valid-lifetime\": 4000,\n"
+"                \"option-data\": [ ],\n"
+"                \"pools\": [\n"
+"                    {\n"
+"                        \"option-data\": [ ],\n"
+"                        \"pool\": \"192.0.2.1-192.0.2.100\"\n"
+"                    }\n"
+"                ],\n"
+"                \"rebind-timer\": 2000,\n"
+"                \"relay\": {\n"
+"                    \"ip-addresses\": [ ]\n"
+"                },\n"
+"                \"renew-timer\": 1000,\n"
+"                \"reservations\": [ ],\n"
+"                \"store-extended-info\": false,\n"
+"                \"subnet\": \"192.0.2.0/24\",\n"
+"                \"t1-percent\": 0.5,\n"
+"                \"t2-percent\": 0.875,\n"
+"                \"valid-lifetime\": 4000\n"
+"            },\n"
+"            {\n"
+"                \"4o6-interface\": \"\",\n"
+"                \"4o6-interface-id\": \"\",\n"
+"                \"4o6-subnet\": \"\",\n"
+"                \"allocator\": \"iterative\",\n"
+"                \"calculate-tee-times\": false,\n"
+"                \"id\": 2,\n"
+"                \"match-client-id\": false,\n"
 "                \"max-valid-lifetime\": 4000,\n"
 "                \"min-valid-lifetime\": 4000,\n"
 "                \"option-data\": [ ],\n"
 "                \"pools\": [\n"
 "                    {\n"
 "                        \"option-data\": [ ],\n"
-"                        \"pool\": \"192.0.2.1-192.0.2.100\"\n"
+"                        \"pool\": \"192.0.3.1-192.0.3.100\"\n"
 "                    }\n"
 "                ],\n"
 "                \"rebind-timer\": 2000,\n"
@@ -3690,7 +4102,7 @@ const char* UNPARSED_CONFIGS[] = {
 "                \"renew-timer\": 1000,\n"
 "                \"reservations\": [ ],\n"
 "                \"store-extended-info\": false,\n"
-"                \"subnet\": \"192.0.2.0/24\",\n"
+"                \"subnet\": \"192.0.3.0/24\",\n"
 "                \"t1-percent\": 0.5,\n"
 "                \"t2-percent\": 0.875,\n"
 "                \"valid-lifetime\": 4000\n"
@@ -3700,7 +4112,7 @@ const char* UNPARSED_CONFIGS[] = {
 "        \"t2-percent\": 0.875,\n"
 "        \"valid-lifetime\": 4000\n"
 "    }\n",
-    // CONFIGURATION 11
+    // CONFIGURATION 13
 "{\n"
 "        \"allocator\": \"iterative\",\n"
 "        \"authoritative\": false,\n"
@@ -3788,7 +4200,7 @@ const char* UNPARSED_CONFIGS[] = {
 "                \"allocator\": \"iterative\",\n"
 "                \"calculate-tee-times\": false,\n"
 "                \"id\": 1,\n"
-"                \"match-client-id\": true,\n"
+"                \"match-client-id\": false,\n"
 "                \"max-valid-lifetime\": 4000,\n"
 "                \"min-valid-lifetime\": 4000,\n"
 "                \"option-data\": [ ],\n"
@@ -3817,7 +4229,6 @@ const char* UNPARSED_CONFIGS[] = {
 "                \"allocator\": \"iterative\",\n"
 "                \"calculate-tee-times\": false,\n"
 "                \"id\": 2,\n"
-"                \"match-client-id\": false,\n"
 "                \"max-valid-lifetime\": 4000,\n"
 "                \"min-valid-lifetime\": 4000,\n"
 "                \"option-data\": [ ],\n"
@@ -3844,7 +4255,7 @@ const char* UNPARSED_CONFIGS[] = {
 "        \"t2-percent\": 0.875,\n"
 "        \"valid-lifetime\": 4000\n"
 "    }\n",
-    // CONFIGURATION 12
+    // CONFIGURATION 14
 "{\n"
 "        \"allocator\": \"iterative\",\n"
 "        \"authoritative\": false,\n"
@@ -3930,9 +4341,9 @@ const char* UNPARSED_CONFIGS[] = {
 "                \"4o6-interface-id\": \"\",\n"
 "                \"4o6-subnet\": \"\",\n"
 "                \"allocator\": \"iterative\",\n"
+"                \"authoritative\": true,\n"
 "                \"calculate-tee-times\": false,\n"
 "                \"id\": 1,\n"
-"                \"match-client-id\": false,\n"
 "                \"max-valid-lifetime\": 4000,\n"
 "                \"min-valid-lifetime\": 4000,\n"
 "                \"option-data\": [ ],\n"
@@ -3959,6 +4370,7 @@ const char* UNPARSED_CONFIGS[] = {
 "                \"4o6-interface-id\": \"\",\n"
 "                \"4o6-subnet\": \"\",\n"
 "                \"allocator\": \"iterative\",\n"
+"                \"authoritative\": false,\n"
 "                \"calculate-tee-times\": false,\n"
 "                \"id\": 2,\n"
 "                \"max-valid-lifetime\": 4000,\n"
@@ -3987,10 +4399,10 @@ const char* UNPARSED_CONFIGS[] = {
 "        \"t2-percent\": 0.875,\n"
 "        \"valid-lifetime\": 4000\n"
 "    }\n",
-    // CONFIGURATION 13
+    // CONFIGURATION 15
 "{\n"
 "        \"allocator\": \"iterative\",\n"
-"        \"authoritative\": false,\n"
+"        \"authoritative\": true,\n"
 "        \"boot-file-name\": \"\",\n"
 "        \"calculate-tee-times\": false,\n"
 "        \"ddns-conflict-resolution-mode\": \"check-with-dhcid\",\n"
@@ -4073,7 +4485,7 @@ const char* UNPARSED_CONFIGS[] = {
 "                \"4o6-interface-id\": \"\",\n"
 "                \"4o6-subnet\": \"\",\n"
 "                \"allocator\": \"iterative\",\n"
-"                \"authoritative\": true,\n"
+"                \"authoritative\": false,\n"
 "                \"calculate-tee-times\": false,\n"
 "                \"id\": 1,\n"
 "                \"max-valid-lifetime\": 4000,\n"
@@ -4102,7 +4514,6 @@ const char* UNPARSED_CONFIGS[] = {
 "                \"4o6-interface-id\": \"\",\n"
 "                \"4o6-subnet\": \"\",\n"
 "                \"allocator\": \"iterative\",\n"
-"                \"authoritative\": false,\n"
 "                \"calculate-tee-times\": false,\n"
 "                \"id\": 2,\n"
 "                \"max-valid-lifetime\": 4000,\n"
@@ -4131,10 +4542,10 @@ const char* UNPARSED_CONFIGS[] = {
 "        \"t2-percent\": 0.875,\n"
 "        \"valid-lifetime\": 4000\n"
 "    }\n",
-    // CONFIGURATION 14
+    // CONFIGURATION 16
 "{\n"
 "        \"allocator\": \"iterative\",\n"
-"        \"authoritative\": true,\n"
+"        \"authoritative\": false,\n"
 "        \"boot-file-name\": \"\",\n"
 "        \"calculate-tee-times\": false,\n"
 "        \"ddns-conflict-resolution-mode\": \"check-with-dhcid\",\n"
@@ -4185,6 +4596,8 @@ const char* UNPARSED_CONFIGS[] = {
 "            \"type\": \"memfile\"\n"
 "        },\n"
 "        \"match-client-id\": true,\n"
+"        \"max-valid-lifetime\": 5000,\n"
+"        \"min-valid-lifetime\": 3000,\n"
 "        \"multi-threading\": {\n"
 "            \"enable-multi-threading\": true,\n"
 "            \"packet-queue-size\": 64,\n"
@@ -4217,11 +4630,10 @@ const char* UNPARSED_CONFIGS[] = {
 "                \"4o6-interface-id\": \"\",\n"
 "                \"4o6-subnet\": \"\",\n"
 "                \"allocator\": \"iterative\",\n"
-"                \"authoritative\": false,\n"
 "                \"calculate-tee-times\": false,\n"
 "                \"id\": 1,\n"
-"                \"max-valid-lifetime\": 4000,\n"
-"                \"min-valid-lifetime\": 4000,\n"
+"                \"max-valid-lifetime\": 5,\n"
+"                \"min-valid-lifetime\": 3,\n"
 "                \"option-data\": [ ],\n"
 "                \"pools\": [\n"
 "                    {\n"
@@ -4229,52 +4641,24 @@ const char* UNPARSED_CONFIGS[] = {
 "                        \"pool\": \"192.0.2.1-192.0.2.100\"\n"
 "                    }\n"
 "                ],\n"
-"                \"rebind-timer\": 2000,\n"
+"                \"rebind-timer\": 2,\n"
 "                \"relay\": {\n"
 "                    \"ip-addresses\": [ ]\n"
 "                },\n"
-"                \"renew-timer\": 1000,\n"
+"                \"renew-timer\": 1,\n"
 "                \"reservations\": [ ],\n"
 "                \"store-extended-info\": false,\n"
 "                \"subnet\": \"192.0.2.0/24\",\n"
 "                \"t1-percent\": 0.5,\n"
 "                \"t2-percent\": 0.875,\n"
-"                \"valid-lifetime\": 4000\n"
-"            },\n"
-"            {\n"
-"                \"4o6-interface\": \"\",\n"
-"                \"4o6-interface-id\": \"\",\n"
-"                \"4o6-subnet\": \"\",\n"
-"                \"allocator\": \"iterative\",\n"
-"                \"calculate-tee-times\": false,\n"
-"                \"id\": 2,\n"
-"                \"max-valid-lifetime\": 4000,\n"
-"                \"min-valid-lifetime\": 4000,\n"
-"                \"option-data\": [ ],\n"
-"                \"pools\": [\n"
-"                    {\n"
-"                        \"option-data\": [ ],\n"
-"                        \"pool\": \"192.0.3.1-192.0.3.100\"\n"
-"                    }\n"
-"                ],\n"
-"                \"rebind-timer\": 2000,\n"
-"                \"relay\": {\n"
-"                    \"ip-addresses\": [ ]\n"
-"                },\n"
-"                \"renew-timer\": 1000,\n"
-"                \"reservations\": [ ],\n"
-"                \"store-extended-info\": false,\n"
-"                \"subnet\": \"192.0.3.0/24\",\n"
-"                \"t1-percent\": 0.5,\n"
-"                \"t2-percent\": 0.875,\n"
-"                \"valid-lifetime\": 4000\n"
+"                \"valid-lifetime\": 4\n"
 "            }\n"
 "        ],\n"
 "        \"t1-percent\": 0.5,\n"
 "        \"t2-percent\": 0.875,\n"
 "        \"valid-lifetime\": 4000\n"
 "    }\n",
-    // CONFIGURATION 15
+    // CONFIGURATION 17
 "{\n"
 "        \"allocator\": \"iterative\",\n"
 "        \"authoritative\": false,\n"
@@ -4328,8 +4712,6 @@ const char* UNPARSED_CONFIGS[] = {
 "            \"type\": \"memfile\"\n"
 "        },\n"
 "        \"match-client-id\": true,\n"
-"        \"max-valid-lifetime\": 5000,\n"
-"        \"min-valid-lifetime\": 3000,\n"
 "        \"multi-threading\": {\n"
 "            \"enable-multi-threading\": true,\n"
 "            \"packet-queue-size\": 64,\n"
@@ -4364,8 +4746,9 @@ const char* UNPARSED_CONFIGS[] = {
 "                \"allocator\": \"iterative\",\n"
 "                \"calculate-tee-times\": false,\n"
 "                \"id\": 1,\n"
-"                \"max-valid-lifetime\": 5,\n"
-"                \"min-valid-lifetime\": 3,\n"
+"                \"interface\": \"eth0\",\n"
+"                \"max-valid-lifetime\": 4000,\n"
+"                \"min-valid-lifetime\": 4000,\n"
 "                \"option-data\": [ ],\n"
 "                \"pools\": [\n"
 "                    {\n"
@@ -4373,24 +4756,24 @@ const char* UNPARSED_CONFIGS[] = {
 "                        \"pool\": \"192.0.2.1-192.0.2.100\"\n"
 "                    }\n"
 "                ],\n"
-"                \"rebind-timer\": 2,\n"
+"                \"rebind-timer\": 2000,\n"
 "                \"relay\": {\n"
 "                    \"ip-addresses\": [ ]\n"
 "                },\n"
-"                \"renew-timer\": 1,\n"
+"                \"renew-timer\": 1000,\n"
 "                \"reservations\": [ ],\n"
 "                \"store-extended-info\": false,\n"
 "                \"subnet\": \"192.0.2.0/24\",\n"
 "                \"t1-percent\": 0.5,\n"
 "                \"t2-percent\": 0.875,\n"
-"                \"valid-lifetime\": 4\n"
+"                \"valid-lifetime\": 4000\n"
 "            }\n"
 "        ],\n"
 "        \"t1-percent\": 0.5,\n"
 "        \"t2-percent\": 0.875,\n"
 "        \"valid-lifetime\": 4000\n"
 "    }\n",
-    // CONFIGURATION 16
+    // CONFIGURATION 18
 "{\n"
 "        \"allocator\": \"iterative\",\n"
 "        \"authoritative\": false,\n"
@@ -4540,7 +4923,7 @@ const char* UNPARSED_CONFIGS[] = {
 "        \"t2-percent\": 0.875,\n"
 "        \"valid-lifetime\": 4000\n"
 "    }\n",
-    // CONFIGURATION 17
+    // CONFIGURATION 19
 "{\n"
 "        \"allocator\": \"iterative\",\n"
 "        \"authoritative\": false,\n"
@@ -4654,7 +5037,7 @@ const char* UNPARSED_CONFIGS[] = {
 "        \"t2-percent\": 0.875,\n"
 "        \"valid-lifetime\": 4000\n"
 "    }\n",
-    // CONFIGURATION 18
+    // CONFIGURATION 20
 "{\n"
 "        \"allocator\": \"iterative\",\n"
 "        \"authoritative\": false,\n"
@@ -4747,7 +5130,7 @@ const char* UNPARSED_CONFIGS[] = {
 "        \"t2-percent\": 0.875,\n"
 "        \"valid-lifetime\": 7200\n"
 "    }\n",
-    // CONFIGURATION 19
+    // CONFIGURATION 21
 "{\n"
 "        \"allocator\": \"iterative\",\n"
 "        \"authoritative\": false,\n"
@@ -4840,7 +5223,7 @@ const char* UNPARSED_CONFIGS[] = {
 "        \"t2-percent\": 0.875,\n"
 "        \"valid-lifetime\": 7200\n"
 "    }\n",
-    // CONFIGURATION 20
+    // CONFIGURATION 22
 "{\n"
 "        \"allocator\": \"iterative\",\n"
 "        \"authoritative\": false,\n"
@@ -4942,7 +5325,7 @@ const char* UNPARSED_CONFIGS[] = {
 "        \"t2-percent\": 0.875,\n"
 "        \"valid-lifetime\": 7200\n"
 "    }\n",
-    // CONFIGURATION 21
+    // CONFIGURATION 23
 "{\n"
 "        \"allocator\": \"iterative\",\n"
 "        \"authoritative\": false,\n"
@@ -5035,7 +5418,7 @@ const char* UNPARSED_CONFIGS[] = {
 "        \"t2-percent\": 0.875,\n"
 "        \"valid-lifetime\": 7200\n"
 "    }\n",
-    // CONFIGURATION 22
+    // CONFIGURATION 24
 "{\n"
 "        \"allocator\": \"iterative\",\n"
 "        \"authoritative\": false,\n"
@@ -5128,7 +5511,7 @@ const char* UNPARSED_CONFIGS[] = {
 "        \"t2-percent\": 0.875,\n"
 "        \"valid-lifetime\": 7200\n"
 "    }\n",
-    // CONFIGURATION 23
+    // CONFIGURATION 25
 "{\n"
 "        \"allocator\": \"iterative\",\n"
 "        \"authoritative\": false,\n"
@@ -5221,7 +5604,7 @@ const char* UNPARSED_CONFIGS[] = {
 "        \"t2-percent\": 0.875,\n"
 "        \"valid-lifetime\": 7200\n"
 "    }\n",
-    // CONFIGURATION 24
+    // CONFIGURATION 26
 "{\n"
 "        \"allocator\": \"iterative\",\n"
 "        \"authoritative\": false,\n"
@@ -5314,7 +5697,7 @@ const char* UNPARSED_CONFIGS[] = {
 "        \"t2-percent\": 0.875,\n"
 "        \"valid-lifetime\": 7200\n"
 "    }\n",
-    // CONFIGURATION 25
+    // CONFIGURATION 27
 "{\n"
 "        \"allocator\": \"iterative\",\n"
 "        \"authoritative\": false,\n"
@@ -5447,7 +5830,7 @@ const char* UNPARSED_CONFIGS[] = {
 "        \"t2-percent\": 0.875,\n"
 "        \"valid-lifetime\": 4000\n"
 "    }\n",
-    // CONFIGURATION 26
+    // CONFIGURATION 28
 "{\n"
 "        \"allocator\": \"iterative\",\n"
 "        \"authoritative\": false,\n"
@@ -5580,7 +5963,7 @@ const char* UNPARSED_CONFIGS[] = {
 "        \"t2-percent\": 0.875,\n"
 "        \"valid-lifetime\": 4000\n"
 "    }\n",
-    // CONFIGURATION 27
+    // CONFIGURATION 29
 "{\n"
 "        \"allocator\": \"iterative\",\n"
 "        \"authoritative\": false,\n"
@@ -5723,7 +6106,7 @@ const char* UNPARSED_CONFIGS[] = {
 "        \"t2-percent\": 0.875,\n"
 "        \"valid-lifetime\": 4000\n"
 "    }\n",
-    // CONFIGURATION 28
+    // CONFIGURATION 30
 "{\n"
 "        \"allocator\": \"iterative\",\n"
 "        \"authoritative\": false,\n"
@@ -5846,7 +6229,7 @@ const char* UNPARSED_CONFIGS[] = {
 "        \"t2-percent\": 0.875,\n"
 "        \"valid-lifetime\": 4000\n"
 "    }\n",
-    // CONFIGURATION 29
+    // CONFIGURATION 31
 "{\n"
 "        \"allocator\": \"iterative\",\n"
 "        \"authoritative\": false,\n"
@@ -6016,7 +6399,7 @@ const char* UNPARSED_CONFIGS[] = {
 "        \"t2-percent\": 0.875,\n"
 "        \"valid-lifetime\": 3000\n"
 "    }\n",
-    // CONFIGURATION 30
+    // CONFIGURATION 32
 "{\n"
 "        \"allocator\": \"iterative\",\n"
 "        \"authoritative\": false,\n"
@@ -6159,7 +6542,7 @@ const char* UNPARSED_CONFIGS[] = {
 "        \"t2-percent\": 0.875,\n"
 "        \"valid-lifetime\": 4000\n"
 "    }\n",
-    // CONFIGURATION 31
+    // CONFIGURATION 33
 "{\n"
 "        \"allocator\": \"iterative\",\n"
 "        \"authoritative\": false,\n"
@@ -6321,7 +6704,7 @@ const char* UNPARSED_CONFIGS[] = {
 "        \"t2-percent\": 0.875,\n"
 "        \"valid-lifetime\": 4000\n"
 "    }\n",
-    // CONFIGURATION 32
+    // CONFIGURATION 34
 "{\n"
 "        \"allocator\": \"iterative\",\n"
 "        \"authoritative\": false,\n"
@@ -6454,7 +6837,7 @@ const char* UNPARSED_CONFIGS[] = {
 "        \"t2-percent\": 0.875,\n"
 "        \"valid-lifetime\": 4000\n"
 "    }\n",
-    // CONFIGURATION 33
+    // CONFIGURATION 35
 "{\n"
 "        \"allocator\": \"iterative\",\n"
 "        \"authoritative\": false,\n"
@@ -6592,7 +6975,7 @@ const char* UNPARSED_CONFIGS[] = {
 "        \"t2-percent\": 0.875,\n"
 "        \"valid-lifetime\": 4000\n"
 "    }\n",
-    // CONFIGURATION 34
+    // CONFIGURATION 36
 "{\n"
 "        \"allocator\": \"iterative\",\n"
 "        \"authoritative\": false,\n"
@@ -6725,7 +7108,7 @@ const char* UNPARSED_CONFIGS[] = {
 "        \"t2-percent\": 0.875,\n"
 "        \"valid-lifetime\": 4000\n"
 "    }\n",
-    // CONFIGURATION 35
+    // CONFIGURATION 37
 "{\n"
 "        \"allocator\": \"iterative\",\n"
 "        \"authoritative\": false,\n"
@@ -6848,7 +7231,7 @@ const char* UNPARSED_CONFIGS[] = {
 "        \"t2-percent\": 0.875,\n"
 "        \"valid-lifetime\": 4000\n"
 "    }\n",
-    // CONFIGURATION 36
+    // CONFIGURATION 38
 "{\n"
 "        \"allocator\": \"iterative\",\n"
 "        \"authoritative\": false,\n"
@@ -7009,7 +7392,7 @@ const char* UNPARSED_CONFIGS[] = {
 "        \"t2-percent\": 0.875,\n"
 "        \"valid-lifetime\": 3000\n"
 "    }\n",
-    // CONFIGURATION 37
+    // CONFIGURATION 39
 "{\n"
 "        \"allocator\": \"iterative\",\n"
 "        \"authoritative\": false,\n"
@@ -7140,7 +7523,7 @@ const char* UNPARSED_CONFIGS[] = {
 "        \"t2-percent\": 0.875,\n"
 "        \"valid-lifetime\": 4000\n"
 "    }\n",
-    // CONFIGURATION 38
+    // CONFIGURATION 40
 "{\n"
 "        \"allocator\": \"iterative\",\n"
 "        \"authoritative\": false,\n"
@@ -7245,121 +7628,36 @@ const char* UNPARSED_CONFIGS[] = {
 "                \"4o6-interface\": \"\",\n"
 "                \"4o6-interface-id\": \"\",\n"
 "                \"4o6-subnet\": \"\",\n"
-"                \"allocator\": \"iterative\",\n"
-"                \"calculate-tee-times\": false,\n"
-"                \"id\": 1,\n"
-"                \"max-valid-lifetime\": 4000,\n"
-"                \"min-valid-lifetime\": 4000,\n"
-"                \"option-data\": [ ],\n"
-"                \"pools\": [\n"
-"                    {\n"
-"                        \"option-data\": [ ],\n"
-"                        \"pool\": \"192.0.2.1-192.0.2.100\"\n"
-"                    }\n"
-"                ],\n"
-"                \"rebind-timer\": 2000,\n"
-"                \"relay\": {\n"
-"                    \"ip-addresses\": [ ]\n"
-"                },\n"
-"                \"renew-timer\": 1000,\n"
-"                \"reservations\": [ ],\n"
-"                \"store-extended-info\": false,\n"
-"                \"subnet\": \"192.0.2.0/24\",\n"
-"                \"t1-percent\": 0.5,\n"
-"                \"t2-percent\": 0.875,\n"
-"                \"valid-lifetime\": 4000\n"
-"            }\n"
-"        ],\n"
-"        \"t1-percent\": 0.5,\n"
-"        \"t2-percent\": 0.875,\n"
-"        \"valid-lifetime\": 4000\n"
-"    }\n",
-    // CONFIGURATION 39
-"{\n"
-"        \"allocator\": \"iterative\",\n"
-"        \"authoritative\": false,\n"
-"        \"boot-file-name\": \"\",\n"
-"        \"calculate-tee-times\": false,\n"
-"        \"ddns-conflict-resolution-mode\": \"check-with-dhcid\",\n"
-"        \"ddns-generated-prefix\": \"myhost\",\n"
-"        \"ddns-override-client-update\": false,\n"
-"        \"ddns-override-no-update\": false,\n"
-"        \"ddns-qualifying-suffix\": \"\",\n"
-"        \"ddns-replace-client-name\": \"never\",\n"
-"        \"ddns-send-updates\": true,\n"
-"        \"ddns-update-on-renew\": false,\n"
-"        \"decline-probation-period\": 86400,\n"
-"        \"dhcp-ddns\": {\n"
-"            \"enable-updates\": false,\n"
-"            \"max-queue-size\": 1024,\n"
-"            \"ncr-format\": \"JSON\",\n"
-"            \"ncr-protocol\": \"UDP\",\n"
-"            \"sender-ip\": \"0.0.0.0\",\n"
-"            \"sender-port\": 0,\n"
-"            \"server-ip\": \"127.0.0.1\",\n"
-"            \"server-port\": 53001\n"
-"        },\n"
-"        \"dhcp-queue-control\": {\n"
-"            \"capacity\": 64,\n"
-"            \"enable-queue\": false,\n"
-"            \"queue-type\": \"kea-ring4\"\n"
-"        },\n"
-"        \"dhcp4o6-port\": 0,\n"
-"        \"early-global-reservations-lookup\": false,\n"
-"        \"echo-client-id\": true,\n"
-"        \"expired-leases-processing\": {\n"
-"            \"flush-reclaimed-timer-wait-time\": 25,\n"
-"            \"hold-reclaimed-time\": 3600,\n"
-"            \"max-reclaim-leases\": 100,\n"
-"            \"max-reclaim-time\": 250,\n"
-"            \"reclaim-timer-wait-time\": 10,\n"
-"            \"unwarned-reclaim-cycles\": 5\n"
-"        },\n"
-"        \"hooks-libraries\": [ ],\n"
-"        \"host-reservation-identifiers\": [ \"hw-address\", \"duid\", \"circuit-id\", \"client-id\" ],\n"
-"        \"hostname-char-replacement\": \"\",\n"
-"        \"hostname-char-set\": \"[^A-Za-z0-9.-]\",\n"
-"        \"interfaces-config\": {\n"
-"            \"interfaces\": [ \"eth0\", \"eth1\" ],\n"
-"            \"re-detect\": false\n"
-"        },\n"
-"        \"ip-reservations-unique\": true,\n"
-"        \"lease-database\": {\n"
-"            \"type\": \"memfile\"\n"
-"        },\n"
-"        \"match-client-id\": true,\n"
-"        \"multi-threading\": {\n"
-"            \"enable-multi-threading\": true,\n"
-"            \"packet-queue-size\": 64,\n"
-"            \"thread-pool-size\": 0\n"
-"        },\n"
-"        \"next-server\": \"0.0.0.0\",\n"
-"        \"option-data\": [ ],\n"
-"        \"option-def\": [ ],\n"
-"        \"parked-packet-limit\": 256,\n"
-"        \"rebind-timer\": 2000,\n"
-"        \"renew-timer\": 1000,\n"
-"        \"reservations-global\": false,\n"
-"        \"reservations-in-subnet\": true,\n"
-"        \"reservations-lookup-first\": false,\n"
-"        \"reservations-out-of-pool\": false,\n"
-"        \"sanity-checks\": {\n"
-"            \"extended-info-checks\": \"fix\",\n"
-"            \"lease-checks\": \"warn\"\n"
-"        },\n"
-"        \"server-hostname\": \"\",\n"
-"        \"server-tag\": \"\",\n"
-"        \"shared-networks\": [ ],\n"
-"        \"stash-agent-options\": false,\n"
-"        \"statistic-default-sample-age\": 0,\n"
-"        \"statistic-default-sample-count\": 20,\n"
-"        \"store-extended-info\": false,\n"
-"        \"subnet4\": [ ],\n"
+"                \"allocator\": \"iterative\",\n"
+"                \"calculate-tee-times\": false,\n"
+"                \"id\": 1,\n"
+"                \"max-valid-lifetime\": 4000,\n"
+"                \"min-valid-lifetime\": 4000,\n"
+"                \"option-data\": [ ],\n"
+"                \"pools\": [\n"
+"                    {\n"
+"                        \"option-data\": [ ],\n"
+"                        \"pool\": \"192.0.2.1-192.0.2.100\"\n"
+"                    }\n"
+"                ],\n"
+"                \"rebind-timer\": 2000,\n"
+"                \"relay\": {\n"
+"                    \"ip-addresses\": [ ]\n"
+"                },\n"
+"                \"renew-timer\": 1000,\n"
+"                \"reservations\": [ ],\n"
+"                \"store-extended-info\": false,\n"
+"                \"subnet\": \"192.0.2.0/24\",\n"
+"                \"t1-percent\": 0.5,\n"
+"                \"t2-percent\": 0.875,\n"
+"                \"valid-lifetime\": 4000\n"
+"            }\n"
+"        ],\n"
 "        \"t1-percent\": 0.5,\n"
 "        \"t2-percent\": 0.875,\n"
 "        \"valid-lifetime\": 4000\n"
 "    }\n",
-    // CONFIGURATION 40
+    // CONFIGURATION 41
 "{\n"
 "        \"allocator\": \"iterative\",\n"
 "        \"authoritative\": false,\n"
@@ -7405,7 +7703,7 @@ const char* UNPARSED_CONFIGS[] = {
 "        \"hostname-char-replacement\": \"\",\n"
 "        \"hostname-char-set\": \"[^A-Za-z0-9.-]\",\n"
 "        \"interfaces-config\": {\n"
-"            \"interfaces\": [ \"*\", \"eth0\", \"eth1\" ],\n"
+"            \"interfaces\": [ \"eth0\", \"eth1\" ],\n"
 "            \"re-detect\": false\n"
 "        },\n"
 "        \"ip-reservations-unique\": true,\n"
@@ -7444,7 +7742,7 @@ const char* UNPARSED_CONFIGS[] = {
 "        \"t2-percent\": 0.875,\n"
 "        \"valid-lifetime\": 4000\n"
 "    }\n",
-    // CONFIGURATION 41
+    // CONFIGURATION 42
 "{\n"
 "        \"allocator\": \"iterative\",\n"
 "        \"authoritative\": false,\n"
@@ -7460,14 +7758,14 @@ const char* UNPARSED_CONFIGS[] = {
 "        \"ddns-update-on-renew\": false,\n"
 "        \"decline-probation-period\": 86400,\n"
 "        \"dhcp-ddns\": {\n"
-"            \"enable-updates\": true,\n"
-"            \"max-queue-size\": 2048,\n"
+"            \"enable-updates\": false,\n"
+"            \"max-queue-size\": 1024,\n"
 "            \"ncr-format\": \"JSON\",\n"
 "            \"ncr-protocol\": \"UDP\",\n"
-"            \"sender-ip\": \"192.168.2.2\",\n"
-"            \"sender-port\": 778,\n"
-"            \"server-ip\": \"192.168.2.1\",\n"
-"            \"server-port\": 777\n"
+"            \"sender-ip\": \"0.0.0.0\",\n"
+"            \"sender-port\": 0,\n"
+"            \"server-ip\": \"127.0.0.1\",\n"
+"            \"server-port\": 53001\n"
 "        },\n"
 "        \"dhcp-queue-control\": {\n"
 "            \"capacity\": 64,\n"
@@ -7490,7 +7788,7 @@ const char* UNPARSED_CONFIGS[] = {
 "        \"hostname-char-replacement\": \"\",\n"
 "        \"hostname-char-set\": \"[^A-Za-z0-9.-]\",\n"
 "        \"interfaces-config\": {\n"
-"            \"interfaces\": [ \"*\" ],\n"
+"            \"interfaces\": [ \"*\", \"eth0\", \"eth1\" ],\n"
 "            \"re-detect\": false\n"
 "        },\n"
 "        \"ip-reservations-unique\": true,\n"
@@ -7524,41 +7822,12 @@ const char* UNPARSED_CONFIGS[] = {
 "        \"statistic-default-sample-age\": 0,\n"
 "        \"statistic-default-sample-count\": 20,\n"
 "        \"store-extended-info\": false,\n"
-"        \"subnet4\": [\n"
-"            {\n"
-"                \"4o6-interface\": \"\",\n"
-"                \"4o6-interface-id\": \"\",\n"
-"                \"4o6-subnet\": \"\",\n"
-"                \"allocator\": \"iterative\",\n"
-"                \"calculate-tee-times\": false,\n"
-"                \"id\": 1,\n"
-"                \"max-valid-lifetime\": 4000,\n"
-"                \"min-valid-lifetime\": 4000,\n"
-"                \"option-data\": [ ],\n"
-"                \"pools\": [\n"
-"                    {\n"
-"                        \"option-data\": [ ],\n"
-"                        \"pool\": \"192.0.2.1-192.0.2.100\"\n"
-"                    }\n"
-"                ],\n"
-"                \"rebind-timer\": 2000,\n"
-"                \"relay\": {\n"
-"                    \"ip-addresses\": [ ]\n"
-"                },\n"
-"                \"renew-timer\": 1000,\n"
-"                \"reservations\": [ ],\n"
-"                \"store-extended-info\": false,\n"
-"                \"subnet\": \"192.0.2.0/24\",\n"
-"                \"t1-percent\": 0.5,\n"
-"                \"t2-percent\": 0.875,\n"
-"                \"valid-lifetime\": 4000\n"
-"            }\n"
-"        ],\n"
+"        \"subnet4\": [ ],\n"
 "        \"t1-percent\": 0.5,\n"
 "        \"t2-percent\": 0.875,\n"
 "        \"valid-lifetime\": 4000\n"
 "    }\n",
-    // CONFIGURATION 42
+    // CONFIGURATION 43
 "{\n"
 "        \"allocator\": \"iterative\",\n"
 "        \"authoritative\": false,\n"
@@ -7672,7 +7941,7 @@ const char* UNPARSED_CONFIGS[] = {
 "        \"t2-percent\": 0.875,\n"
 "        \"valid-lifetime\": 4000\n"
 "    }\n",
-    // CONFIGURATION 43
+    // CONFIGURATION 44
 "{\n"
 "        \"allocator\": \"iterative\",\n"
 "        \"authoritative\": false,\n"
@@ -7786,7 +8055,7 @@ const char* UNPARSED_CONFIGS[] = {
 "        \"t2-percent\": 0.875,\n"
 "        \"valid-lifetime\": 4000\n"
 "    }\n",
-    // CONFIGURATION 44
+    // CONFIGURATION 45
 "{\n"
 "        \"allocator\": \"iterative\",\n"
 "        \"authoritative\": false,\n"
@@ -7987,7 +8256,7 @@ const char* UNPARSED_CONFIGS[] = {
 "        \"t2-percent\": 0.875,\n"
 "        \"valid-lifetime\": 4000\n"
 "    }\n",
-    // CONFIGURATION 45
+    // CONFIGURATION 46
 "{\n"
 "        \"allocator\": \"iterative\",\n"
 "        \"authoritative\": false,\n"
@@ -8116,7 +8385,121 @@ const char* UNPARSED_CONFIGS[] = {
 "        \"t2-percent\": 0.875,\n"
 "        \"valid-lifetime\": 4000\n"
 "    }\n",
-    // CONFIGURATION 46
+    // CONFIGURATION 47
+"{\n"
+"        \"allocator\": \"iterative\",\n"
+"        \"authoritative\": false,\n"
+"        \"boot-file-name\": \"\",\n"
+"        \"calculate-tee-times\": false,\n"
+"        \"ddns-conflict-resolution-mode\": \"check-with-dhcid\",\n"
+"        \"ddns-generated-prefix\": \"myhost\",\n"
+"        \"ddns-override-client-update\": false,\n"
+"        \"ddns-override-no-update\": false,\n"
+"        \"ddns-qualifying-suffix\": \"\",\n"
+"        \"ddns-replace-client-name\": \"never\",\n"
+"        \"ddns-send-updates\": true,\n"
+"        \"ddns-update-on-renew\": false,\n"
+"        \"decline-probation-period\": 86400,\n"
+"        \"dhcp-ddns\": {\n"
+"            \"enable-updates\": true,\n"
+"            \"max-queue-size\": 2048,\n"
+"            \"ncr-format\": \"JSON\",\n"
+"            \"ncr-protocol\": \"UDP\",\n"
+"            \"sender-ip\": \"192.168.2.2\",\n"
+"            \"sender-port\": 778,\n"
+"            \"server-ip\": \"192.168.2.1\",\n"
+"            \"server-port\": 777\n"
+"        },\n"
+"        \"dhcp-queue-control\": {\n"
+"            \"capacity\": 64,\n"
+"            \"enable-queue\": false,\n"
+"            \"queue-type\": \"kea-ring4\"\n"
+"        },\n"
+"        \"dhcp4o6-port\": 0,\n"
+"        \"early-global-reservations-lookup\": false,\n"
+"        \"echo-client-id\": true,\n"
+"        \"expired-leases-processing\": {\n"
+"            \"flush-reclaimed-timer-wait-time\": 25,\n"
+"            \"hold-reclaimed-time\": 3600,\n"
+"            \"max-reclaim-leases\": 100,\n"
+"            \"max-reclaim-time\": 250,\n"
+"            \"reclaim-timer-wait-time\": 10,\n"
+"            \"unwarned-reclaim-cycles\": 5\n"
+"        },\n"
+"        \"hooks-libraries\": [ ],\n"
+"        \"host-reservation-identifiers\": [ \"hw-address\", \"duid\", \"circuit-id\", \"client-id\" ],\n"
+"        \"hostname-char-replacement\": \"\",\n"
+"        \"hostname-char-set\": \"[^A-Za-z0-9.-]\",\n"
+"        \"interfaces-config\": {\n"
+"            \"interfaces\": [ \"*\" ],\n"
+"            \"re-detect\": false\n"
+"        },\n"
+"        \"ip-reservations-unique\": true,\n"
+"        \"lease-database\": {\n"
+"            \"type\": \"memfile\"\n"
+"        },\n"
+"        \"match-client-id\": true,\n"
+"        \"multi-threading\": {\n"
+"            \"enable-multi-threading\": true,\n"
+"            \"packet-queue-size\": 64,\n"
+"            \"thread-pool-size\": 0\n"
+"        },\n"
+"        \"next-server\": \"0.0.0.0\",\n"
+"        \"option-data\": [ ],\n"
+"        \"option-def\": [ ],\n"
+"        \"parked-packet-limit\": 256,\n"
+"        \"rebind-timer\": 2000,\n"
+"        \"renew-timer\": 1000,\n"
+"        \"reservations-global\": false,\n"
+"        \"reservations-in-subnet\": true,\n"
+"        \"reservations-lookup-first\": false,\n"
+"        \"reservations-out-of-pool\": false,\n"
+"        \"sanity-checks\": {\n"
+"            \"extended-info-checks\": \"fix\",\n"
+"            \"lease-checks\": \"warn\"\n"
+"        },\n"
+"        \"server-hostname\": \"\",\n"
+"        \"server-tag\": \"\",\n"
+"        \"shared-networks\": [ ],\n"
+"        \"stash-agent-options\": false,\n"
+"        \"statistic-default-sample-age\": 0,\n"
+"        \"statistic-default-sample-count\": 20,\n"
+"        \"store-extended-info\": false,\n"
+"        \"subnet4\": [\n"
+"            {\n"
+"                \"4o6-interface\": \"\",\n"
+"                \"4o6-interface-id\": \"\",\n"
+"                \"4o6-subnet\": \"\",\n"
+"                \"allocator\": \"iterative\",\n"
+"                \"calculate-tee-times\": false,\n"
+"                \"id\": 1,\n"
+"                \"max-valid-lifetime\": 4000,\n"
+"                \"min-valid-lifetime\": 4000,\n"
+"                \"option-data\": [ ],\n"
+"                \"pools\": [\n"
+"                    {\n"
+"                        \"option-data\": [ ],\n"
+"                        \"pool\": \"192.0.2.1-192.0.2.100\"\n"
+"                    }\n"
+"                ],\n"
+"                \"rebind-timer\": 2000,\n"
+"                \"relay\": {\n"
+"                    \"ip-addresses\": [ ]\n"
+"                },\n"
+"                \"renew-timer\": 1000,\n"
+"                \"reservations\": [ ],\n"
+"                \"store-extended-info\": false,\n"
+"                \"subnet\": \"192.0.2.0/24\",\n"
+"                \"t1-percent\": 0.5,\n"
+"                \"t2-percent\": 0.875,\n"
+"                \"valid-lifetime\": 4000\n"
+"            }\n"
+"        ],\n"
+"        \"t1-percent\": 0.5,\n"
+"        \"t2-percent\": 0.875,\n"
+"        \"valid-lifetime\": 4000\n"
+"    }\n",
+    // CONFIGURATION 48
 "{\n"
 "        \"allocator\": \"iterative\",\n"
 "        \"authoritative\": false,\n"
@@ -8395,7 +8778,7 @@ const char* UNPARSED_CONFIGS[] = {
 "        \"t2-percent\": 0.875,\n"
 "        \"valid-lifetime\": 4000\n"
 "    }\n",
-    // CONFIGURATION 47
+    // CONFIGURATION 49
 "{\n"
 "        \"allocator\": \"iterative\",\n"
 "        \"authoritative\": false,\n"
@@ -8540,7 +8923,7 @@ const char* UNPARSED_CONFIGS[] = {
 "        \"t2-percent\": 0.875,\n"
 "        \"valid-lifetime\": 4000\n"
 "    }\n",
-    // CONFIGURATION 48
+    // CONFIGURATION 50
 "{\n"
 "        \"allocator\": \"iterative\",\n"
 "        \"authoritative\": false,\n"
@@ -8838,7 +9221,7 @@ const char* UNPARSED_CONFIGS[] = {
 "        \"t2-percent\": 0.875,\n"
 "        \"valid-lifetime\": 4000\n"
 "    }\n",
-    // CONFIGURATION 49
+    // CONFIGURATION 51
 "{\n"
 "        \"allocator\": \"iterative\",\n"
 "        \"authoritative\": false,\n"
@@ -8983,7 +9366,7 @@ const char* UNPARSED_CONFIGS[] = {
 "        \"t2-percent\": 0.875,\n"
 "        \"valid-lifetime\": 4000\n"
 "    }\n",
-    // CONFIGURATION 50
+    // CONFIGURATION 52
 "{\n"
 "        \"allocator\": \"iterative\",\n"
 "        \"authoritative\": false,\n"
@@ -9066,7 +9449,7 @@ const char* UNPARSED_CONFIGS[] = {
 "        \"t2-percent\": 0.875,\n"
 "        \"valid-lifetime\": 7200\n"
 "    }\n",
-    // CONFIGURATION 51
+    // CONFIGURATION 53
 "{\n"
 "        \"allocator\": \"iterative\",\n"
 "        \"authoritative\": false,\n"
@@ -9149,7 +9532,7 @@ const char* UNPARSED_CONFIGS[] = {
 "        \"t2-percent\": 0.875,\n"
 "        \"valid-lifetime\": 7200\n"
 "    }\n",
-    // CONFIGURATION 52
+    // CONFIGURATION 54
 "{\n"
 "        \"allocator\": \"iterative\",\n"
 "        \"authoritative\": false,\n"
@@ -9232,7 +9615,7 @@ const char* UNPARSED_CONFIGS[] = {
 "        \"t2-percent\": 0.875,\n"
 "        \"valid-lifetime\": 7200\n"
 "    }\n",
-    // CONFIGURATION 53
+    // CONFIGURATION 55
 "{\n"
 "        \"allocator\": \"iterative\",\n"
 "        \"authoritative\": false,\n"
@@ -9315,7 +9698,7 @@ const char* UNPARSED_CONFIGS[] = {
 "        \"t2-percent\": 0.875,\n"
 "        \"valid-lifetime\": 7200\n"
 "    }\n",
-    // CONFIGURATION 54
+    // CONFIGURATION 56
 "{\n"
 "        \"allocator\": \"iterative\",\n"
 "        \"authoritative\": false,\n"
@@ -9429,7 +9812,7 @@ const char* UNPARSED_CONFIGS[] = {
 "        \"t2-percent\": 0.875,\n"
 "        \"valid-lifetime\": 4000\n"
 "    }\n",
-    // CONFIGURATION 55
+    // CONFIGURATION 57
 "{\n"
 "        \"allocator\": \"iterative\",\n"
 "        \"authoritative\": false,\n"
@@ -9543,7 +9926,7 @@ const char* UNPARSED_CONFIGS[] = {
 "        \"t2-percent\": 0.875,\n"
 "        \"valid-lifetime\": 4000\n"
 "    }\n",
-    // CONFIGURATION 56
+    // CONFIGURATION 58
 "{\n"
 "        \"allocator\": \"iterative\",\n"
 "        \"authoritative\": false,\n"
@@ -9657,7 +10040,7 @@ const char* UNPARSED_CONFIGS[] = {
 "        \"t2-percent\": 0.875,\n"
 "        \"valid-lifetime\": 4000\n"
 "    }\n",
-    // CONFIGURATION 57
+    // CONFIGURATION 59
 "{\n"
 "        \"allocator\": \"iterative\",\n"
 "        \"authoritative\": false,\n"
@@ -9771,7 +10154,7 @@ const char* UNPARSED_CONFIGS[] = {
 "        \"t2-percent\": 0.875,\n"
 "        \"valid-lifetime\": 4000\n"
 "    }\n",
-    // CONFIGURATION 58
+    // CONFIGURATION 60
 "{\n"
 "        \"allocator\": \"iterative\",\n"
 "        \"authoritative\": false,\n"
@@ -9885,7 +10268,7 @@ const char* UNPARSED_CONFIGS[] = {
 "        \"t2-percent\": 0.875,\n"
 "        \"valid-lifetime\": 4000\n"
 "    }\n",
-    // CONFIGURATION 59
+    // CONFIGURATION 61
 "{\n"
 "        \"allocator\": \"iterative\",\n"
 "        \"authoritative\": false,\n"
@@ -10025,7 +10408,7 @@ const char* UNPARSED_CONFIGS[] = {
 "        \"t2-percent\": 0.875,\n"
 "        \"valid-lifetime\": 4000\n"
 "    }\n",
-    // CONFIGURATION 60
+    // CONFIGURATION 62
 "{\n"
 "        \"allocator\": \"iterative\",\n"
 "        \"authoritative\": false,\n"
@@ -10156,7 +10539,7 @@ const char* UNPARSED_CONFIGS[] = {
 "        \"t2-percent\": 0.875,\n"
 "        \"valid-lifetime\": 7200\n"
 "    }\n",
-    // CONFIGURATION 61
+    // CONFIGURATION 63
 "{\n"
 "        \"allocator\": \"iterative\",\n"
 "        \"authoritative\": false,\n"
@@ -10289,7 +10672,7 @@ const char* UNPARSED_CONFIGS[] = {
 "        \"t2-percent\": 0.875,\n"
 "        \"valid-lifetime\": 7200\n"
 "    }\n",
-    // CONFIGURATION 62
+    // CONFIGURATION 64
 "{\n"
 "        \"allocator\": \"iterative\",\n"
 "        \"authoritative\": false,\n"
@@ -10403,7 +10786,7 @@ const char* UNPARSED_CONFIGS[] = {
 "        \"t2-percent\": 0.875,\n"
 "        \"valid-lifetime\": 4000\n"
 "    }\n",
-    // CONFIGURATION 63
+    // CONFIGURATION 65
 "{\n"
 "        \"allocator\": \"iterative\",\n"
 "        \"authoritative\": false,\n"
@@ -10518,7 +10901,7 @@ const char* UNPARSED_CONFIGS[] = {
 "        \"t2-percent\": 0.875,\n"
 "        \"valid-lifetime\": 4000\n"
 "    }\n",
-    // CONFIGURATION 64
+    // CONFIGURATION 66
 "{\n"
 "        \"allocator\": \"iterative\",\n"
 "        \"authoritative\": false,\n"
@@ -10637,7 +11020,7 @@ const char* UNPARSED_CONFIGS[] = {
 "        \"t2-percent\": 0.875,\n"
 "        \"valid-lifetime\": 4000\n"
 "    }\n",
-    // CONFIGURATION 65
+    // CONFIGURATION 67
 "{\n"
 "        \"allocator\": \"iterative\",\n"
 "        \"authoritative\": false,\n"
@@ -10756,7 +11139,7 @@ const char* UNPARSED_CONFIGS[] = {
 "        \"t2-percent\": 0.875,\n"
 "        \"valid-lifetime\": 4000\n"
 "    }\n",
-    // CONFIGURATION 66
+    // CONFIGURATION 68
 "{\n"
 "        \"allocator\": \"iterative\",\n"
 "        \"authoritative\": false,\n"
@@ -10811,6 +11194,7 @@ const char* UNPARSED_CONFIGS[] = {
 "            {\n"
 "                \"name\": \"keatest2\",\n"
 "                \"password\": \"keatest\",\n"
+"                \"retry-on-startup\": true,\n"
 "                \"type\": \"mysql\",\n"
 "                \"user\": \"keatest\"\n"
 "            }\n"
@@ -10855,7 +11239,7 @@ const char* UNPARSED_CONFIGS[] = {
 "        \"t2-percent\": 0.875,\n"
 "        \"valid-lifetime\": 4000\n"
 "    }\n",
-    // CONFIGURATION 67
+    // CONFIGURATION 69
 "{\n"
 "        \"allocator\": \"iterative\",\n"
 "        \"authoritative\": false,\n"
@@ -11093,7 +11477,7 @@ const char* UNPARSED_CONFIGS[] = {
 "        },\n"
 "        \"valid-lifetime\": 7200\n"
 "    }\n",
-    // CONFIGURATION 68
+    // CONFIGURATION 70
 "{\n"
 "        \"allocator\": \"iterative\",\n"
 "        \"authoritative\": false,\n"
@@ -11294,7 +11678,7 @@ const char* UNPARSED_CONFIGS[] = {
 "        \"t2-percent\": 0.875,\n"
 "        \"valid-lifetime\": 4000\n"
 "    }\n",
-    // CONFIGURATION 69
+    // CONFIGURATION 71
 "{\n"
 "        \"allocator\": \"iterative\",\n"
 "        \"authoritative\": false,\n"
@@ -11474,7 +11858,7 @@ const char* UNPARSED_CONFIGS[] = {
 "        \"t2-percent\": 0.875,\n"
 "        \"valid-lifetime\": 4000\n"
 "    }\n",
-    // CONFIGURATION 70
+    // CONFIGURATION 72
 "{\n"
 "        \"allocator\": \"iterative\",\n"
 "        \"authoritative\": false,\n"
@@ -11616,7 +12000,7 @@ const char* UNPARSED_CONFIGS[] = {
 "        \"t2-percent\": 0.875,\n"
 "        \"valid-lifetime\": 4000\n"
 "    }\n",
-    // CONFIGURATION 71
+    // CONFIGURATION 73
 "{\n"
 "        \"allocator\": \"iterative\",\n"
 "        \"authoritative\": false,\n"
@@ -11758,7 +12142,7 @@ const char* UNPARSED_CONFIGS[] = {
 "        \"t2-percent\": 0.875,\n"
 "        \"valid-lifetime\": 4000\n"
 "    }\n",
-    // CONFIGURATION 72
+    // CONFIGURATION 74
 "{\n"
 "        \"allocator\": \"iterative\",\n"
 "        \"authoritative\": false,\n"
@@ -11843,7 +12227,7 @@ const char* UNPARSED_CONFIGS[] = {
 "        \"t2-percent\": 0.875,\n"
 "        \"valid-lifetime\": 4000\n"
 "    }\n",
-    // CONFIGURATION 73
+    // CONFIGURATION 75
 "{\n"
 "        \"allocator\": \"iterative\",\n"
 "        \"authoritative\": false,\n"
@@ -11926,7 +12310,7 @@ const char* UNPARSED_CONFIGS[] = {
 "        \"t2-percent\": 0.875,\n"
 "        \"valid-lifetime\": 7200\n"
 "    }\n",
-    // CONFIGURATION 74
+    // CONFIGURATION 76
 "{\n"
 "        \"allocator\": \"iterative\",\n"
 "        \"authoritative\": false,\n"
@@ -12009,7 +12393,7 @@ const char* UNPARSED_CONFIGS[] = {
 "        \"t2-percent\": 0.875,\n"
 "        \"valid-lifetime\": 7200\n"
 "    }\n",
-    // CONFIGURATION 75
+    // CONFIGURATION 77
 "{\n"
 "        \"allocator\": \"iterative\",\n"
 "        \"authoritative\": false,\n"
index 8be9f77c0e6cc384d2776e18709cfd1f2e79935a..6ef5349dcd953fc4b687ae98fbf0d1e545d565f8 100644 (file)
@@ -9,25 +9,24 @@
 #include <cc/command_interpreter.h>
 #include <cc/data.h>
 #include <cc/simple_parser.h>
-#include <cc/cfg_to_element.h>
-#include <testutils/user_context_utils.h>
 #include <dhcp/testutils/iface_mgr_test_config.h>
-#include <dhcpsrv/cfgmgr.h>
-#include <dhcpsrv/parsers/simple_parser4.h>
-#include <dhcp4/dhcp4_srv.h>
 #include <dhcp4/ctrl_dhcp4_srv.h>
+#include <dhcp4/dhcp4_srv.h>
 #include <dhcp4/json_config_parser.h>
 #include <dhcp4/tests/dhcp4_test_utils.h>
 #include <dhcp4/tests/get_config_unittest.h>
+#include <dhcpsrv/cfgmgr.h>
 #include <testutils/gtest_utils.h>
-
-#include <boost/algorithm/string.hpp>
-#include <gtest/gtest.h>
+#include <testutils/user_context_utils.h>
 
 #include <iostream>
-#include <string>
-#include <sstream>
 #include <list>
+#include <sstream>
+#include <string>
+
+#include <boost/algorithm/string.hpp>
+
+#include <gtest/gtest.h>
 
 using namespace isc::config;
 using namespace isc::data;
index c636be1238919529b3aff71cd76ce6ded87c1981..e47c3ae14be8f02047a61f91aaa1392713912319 100644 (file)
@@ -176,7 +176,7 @@ typedef boost::shared_ptr<TestCBControlDHCPv4> TestCBControlDHCPv4Ptr;
 ///
 /// Exposes internal fields and installs stub implementation of the
 /// @c CBControlDHCPv4 object.
-class NakedControlledDhcpv4Srv: public ControlledDhcpv4Srv {
+class NakedControlledDhcpv4Srv : public ControlledDhcpv4Srv {
 public:
 
     /// @brief Constructor.
@@ -188,7 +188,7 @@ public:
     }
 };
 
-/// @brief test class for Kea configuration backend
+/// @brief test class for Kea configuration backend.
 ///
 /// This class is used for testing Kea configuration backend.
 /// It is very simple and currently focuses on reading
@@ -301,7 +301,6 @@ public:
         EXPECT_EQ(0, cb_control->getDatabaseCurrentConfigFetchCalls());
         EXPECT_EQ(1, cb_control->getDatabaseStagingConfigFetchCalls());
 
-
         if (call_command) {
             // The case where there is no backend is tested in the
             // controlled server tests so we have only to verify
@@ -1079,7 +1078,6 @@ testBackendReconfiguration(const std::string& backend_first,
               LeaseMgrFactory::instance().getType());
 }
 
-
 // This test verifies that backend specification can be added on
 // server reconfiguration.
 TEST_F(JSONFileBackendMySQLTest, reconfigureBackendUndefinedToMySQL) {
index ebf7bef835f84d81ce21f247a3c350a0227d5e08..312c29991a82089163ff06331185e285ede47df8 100644 (file)
@@ -55,15 +55,14 @@ Parser6Context::parseCommon() {
             isc_throw(Dhcp6ParseError, "Parser abort");
         }
         scanEnd();
-    }
-    catch (...) {
+    } catch (...) {
         scanEnd();
         throw;
     }
     if (stack_.size() == 1) {
         return (stack_[0]);
     } else {
-        isc_throw(Dhcp6ParseError, "Expected exactly one terminal Element expected, found "
+        isc_throw(Dhcp6ParseError, "Expected exactly one terminal Element, found "
                   << stack_.size());
     }
 }
index eeda548db4f9cbc3d22f94b2fc7cbea58297f448..cff24255d2fca3cc7b7d8ca73b9b194ce749f822 100644 (file)
@@ -6,22 +6,24 @@
 
 #include <config.h>
 
+#include <asiolink/addr_utilities.h>
 #include <cc/command_interpreter.h>
+#include <dhcp/classify.h>
 #include <dhcp/docsis3_option_defs.h>
+#include <dhcp/iface_mgr.h>
 #include <dhcp/libdhcp++.h>
+#include <dhcp/option6_addrlst.h>
 #include <dhcp/option6_ia.h>
-#include <dhcp/iface_mgr.h>
 #include <dhcp/option_custom.h>
 #include <dhcp/option_int.h>
-#include <dhcp/option6_addrlst.h>
 #include <dhcp/testutils/iface_mgr_test_config.h>
-#include <dhcp6/json_config_parser.h>
-#include <dhcp6/dhcp6_srv.h>
 #include <dhcp6/ctrl_dhcp6_srv.h>
-#include <asiolink/addr_utilities.h>
-#include <dhcpsrv/cfgmgr.h>
+#include <dhcp6/dhcp6_srv.h>
+#include <dhcp6/json_config_parser.h>
 #include <dhcpsrv/cfg_expiration.h>
 #include <dhcpsrv/cfg_hosts.h>
+#include <dhcpsrv/cfg_subnets6.h>
+#include <dhcpsrv/cfgmgr.h>
 #include <dhcpsrv/parsers/simple_parser6.h>
 #include <dhcpsrv/subnet.h>
 #include <dhcpsrv/subnet_selector.h>
 #include <testutils/log_utils.h>
 #include <testutils/test_to_element.h>
 #include <util/chrono_time_utils.h>
-
-#include "test_data_files_config.h"
-#include "test_libraries.h"
-#include "marker_file.h"
-#include "dhcp6_test_utils.h"
-#include "get_config_unittest.h"
-
-#include <gtest/gtest.h>
+#include <util/doubles.h>
 
 #include <boost/foreach.hpp>
-#include <fstream>
+
 #include <iostream>
 #include <sstream>
 #include <string>
 #include <vector>
 
 #include <arpa/inet.h>
+#include <gtest/gtest.h>
 #include <unistd.h>
 
+#include "dhcp6_test_utils.h"
+#include "get_config_unittest.h"
+#include "marker_file.h"
+#include "test_libraries.h"
+
 using namespace isc;
 using namespace isc::asiolink;
 using namespace isc::config;
@@ -66,7 +67,7 @@ using namespace std;
 namespace {
 
 const char* PARSER_CONFIGS[] = {
-    // CONFIGURATION 0: one subnet with one pool, no user contexts
+    // Configuration 0: one subnet with one pool, no user contexts
     "{"
     "    \"interfaces-config\": {"
     "        \"interfaces\": [\"*\" ]"
@@ -242,12 +243,13 @@ const char* PARSER_CONFIGS[] = {
     "        \"type\": \"mysql\","
     "        \"name\": \"keatest2\","
     "        \"user\": \"keatest\","
+    "        \"retry-on-startup\": true,"
     "        \"password\": \"keatest\""
     "      }"
     "    ]"
     "}",
 
-    // Configuration 8: config control
+    // Configuration 8: config database
     "{ \n"
     "    \"interfaces-config\": { \n"
     "        \"interfaces\": [\"*\" ] \n"
@@ -266,6 +268,7 @@ const char* PARSER_CONFIGS[] = {
     "               \"type\": \"mysql\", \n"
     "               \"name\": \"keatest2\", \n"
     "               \"user\": \"keatest\", \n"
+    "               \"retry-on-startup\": true, \n"
     "               \"password\": \"keatest\" \n"
     "           } \n"
     "       ] \n"
@@ -293,7 +296,7 @@ const char* PARSER_CONFIGS[] = {
     "        \"comment\": \"Set option value\","
     "        \"name\": \"subscriber-id\","
     "        \"data\": \"ABCDEF0105\","
-    "            \"csv-format\": false"
+    "        \"csv-format\": false"
     "     } ],"
     "    \"client-classes\": ["
     "        {"
@@ -373,8 +376,8 @@ protected:
     }
 
 public:
-    Dhcp6ParserTest() :rcode_(-1), srv_(0) {
-        // srv_(0) means to not open any sockets. We don't want to
+    Dhcp6ParserTest() : rcode_(-1), srv_(0) {
+        // Open port 0 means to not open any sockets. We don't want to
         // deal with sockets here, just check if configuration handling
         // is sane.
 
@@ -394,7 +397,6 @@ public:
                           << " while the test assumes that it doesn't, to execute"
                           << " some negative scenarios. Can't continue this test.";
         }
-
         // Reset configuration for each test.
         resetConfiguration();
     }
@@ -408,16 +410,13 @@ public:
         static_cast<void>(remove(UNLOAD_MARKER_FILE));
     };
 
-    // Checks if config_result (result of DHCP server configuration) has
+    // Checks if the result of DHCP server configuration has
     // expected code (0 for success, other for failures).
     // Also stores result in rcode_ and comment_.
     void checkResult(ConstElementPtr status, int expected_code) {
         ASSERT_TRUE(status);
         comment_ = parseAnswerText(rcode_, status);
-        EXPECT_EQ(expected_code, rcode_);
-        if (expected_code != rcode_) {
-            cout << "The comment returned was: [" << comment_->stringValue() << "]" << endl;
-        }
+        EXPECT_EQ(expected_code, rcode_) << "error text:" << comment_->stringValue();
     }
 
     // Checks if the result of DHCP server configuration has
@@ -443,7 +442,7 @@ public:
     void configure(std::string config, int expected_code,
                    std::string exp_error = "") {
         ConstElementPtr json;
-        ASSERT_NO_THROW(json = parseDHCP6(config, true));
+        ASSERT_NO_THROW_LOG(json = parseDHCP6(config, true));
 
         ConstElementPtr status;
         EXPECT_NO_THROW(status = Dhcpv6SrvTest::configure(srv_, json));
@@ -468,51 +467,6 @@ public:
         }
     }
 
-    /// @brief Checks if specified subnet is part of the collection
-    ///
-    /// @tparam CollectionType type of subnet6 collections i.e.
-    /// either Subnet6SimpleCollection or Subnet6Collection
-    /// @param col collection of subnets to be inspected
-    /// @param subnet text notation (e.g. 192.0.2.0/24)
-    /// @param t1 expected renew-timer value
-    /// @param t2 expected rebind-timer value
-    /// @param preferred expected preferred-lifetime value
-    /// @param valid expected valid-lifetime value
-    /// @param min_preferred expected min-preferred-lifetime value
-    ///        (0 (default) means same as preferred)
-    /// @param max_preferred expected max-preferred-lifetime value
-    ///        (0 (default) means same as preferred)
-    /// @param min_valid expected min-valid-lifetime value
-    ///        (0 (default) means same as valid)
-    /// @param max_valid expected max-valid-lifetime value
-    ///        (0 (default) means same as valid)
-    /// @return the subnet that was examined
-    template <typename CollectionType>
-    Subnet6Ptr
-    checkSubnet(const CollectionType& col, std::string subnet,
-                uint32_t t1, uint32_t t2, uint32_t pref, uint32_t valid,
-                uint32_t min_pref = 0, uint32_t max_pref = 0,
-                uint32_t min_valid = 0, uint32_t max_valid = 0) {
-        auto const& index = col.template get<SubnetPrefixIndexTag>();
-        auto subnet_it = index.find(subnet);
-        if (subnet_it == index.cend()) {
-            ADD_FAILURE() << "Unable to find expected subnet " << subnet;
-            return (Subnet6Ptr());
-        }
-        Subnet6Ptr s = *subnet_it;
-
-        EXPECT_EQ(t1, s->getT1().get());
-        EXPECT_EQ(t2, s->getT2().get());
-        EXPECT_EQ(pref, s->getPreferred().get());
-        EXPECT_EQ(valid, s->getValid().get());
-        EXPECT_EQ(min_pref ? min_pref : pref, s->getPreferred().getMin());
-        EXPECT_EQ(max_pref ? max_pref : pref, s->getPreferred().getMax());
-        EXPECT_EQ(min_valid ? min_valid : valid, s->getValid().getMin());
-        EXPECT_EQ(max_valid ? max_valid : valid, s->getValid().getMax());
-
-        return (s);
-    }
-
     /// @brief Returns an interface configuration used by the most of the
     /// unit tests.
     std::string genIfaceConfig() const {
@@ -531,6 +485,8 @@ public:
     /// injected into the configuration string.
     /// @param parameter name of the parameter to be configured with
     /// param value.
+    /// @return configuration string containing custom values of parameters
+    /// describing an option.
     std::string createConfigWithOption(const std::string& param_value,
                                        const std::string& parameter) {
         std::map<std::string, std::string> params;
@@ -577,10 +533,9 @@ public:
     /// @return configuration string containing custom values of parameters
     /// describing an option.
     std::string createConfigWithOption(const std::map<std::string,
-                                       std::string>& params)
-    {
+                                       std::string>& params) {
         std::ostringstream stream;
-        stream << "{ " << genIfaceConfig() << ","
+        stream << "{ " << genIfaceConfig() << "," <<
             "\"preferred-lifetime\": 3000,"
             "\"rebind-timer\": 2000, "
             "\"renew-timer\": 1000, "
@@ -591,7 +546,7 @@ public:
             "  \"space\": \"dhcp6\""
             "} ],"
             "\"subnet6\": [ { "
-            "    \"id\": 1, "
+            "    \"id\": 1,"
             "    \"pools\": [ { \"pool\": \"2001:db8:1::/80\" } ],"
             "    \"subnet\": \"2001:db8:1::/64\", "
             "    \"option-data\": [ {";
@@ -608,7 +563,7 @@ public:
             } else if (param.first == "space") {
                 stream << "\"space\": \"" << param.second << "\"";
             } else if (param.first == "code") {
-                stream << "\"code\": " << param.second;;
+                stream << "\"code\": " << param.second;
             } else if (param.first == "data") {
                 stream << "\"data\": \"" << param.second << "\"";
             } else if (param.first == "csv-format") {
@@ -641,8 +596,8 @@ public:
     getOptionFromSubnet(const IOAddress& subnet_address,
                         const uint16_t option_code,
                         const uint16_t expected_options_count = 1) {
-        Subnet6Ptr subnet = CfgMgr::instance().getStagingCfg()->getCfgSubnets6()->
-            selectSubnet(subnet_address, classify_);
+        Subnet6Ptr subnet = CfgMgr::instance().getStagingCfg()->
+            getCfgSubnets6()->selectSubnet(subnet_address, classify_);
         if (!subnet) {
             ADD_FAILURE() << "A subnet for the specified address "
                           << subnet_address
@@ -679,126 +634,6 @@ public:
         return (*range.first);
     }
 
-    /// @brief Parse and Execute configuration
-    ///
-    /// Parses a configuration and executes a configuration of the server.
-    /// If the operation fails, the current test will register a failure.
-    ///
-    /// @param config Configuration to parse
-    /// @param operation Operation being performed.  In the case of an error,
-    ///        the error text will include the string "unable to <operation>.".
-    ///
-    /// @return true if the configuration succeeded, false if not.  In the
-    ///         latter case, a failure will have been added to the current test.
-    bool
-    executeConfiguration(const std::string& config, const char* operation) {
-        ConstElementPtr json;
-        ConstElementPtr status;
-        try {
-            json = parseJSON(config);
-            status = Dhcpv6SrvTest::configure(srv_, json);
-
-        } catch (const std::exception& ex) {
-            ADD_FAILURE() << "Unable to " << operation << ". "
-                   << "The following configuration was used: " << std::endl
-                   << config << std::endl
-                   << " and the following error message was returned:"
-                   << ex.what() << std::endl;
-            return (false);
-        }
-
-        // The status object must not be NULL
-        if (!status) {
-            ADD_FAILURE() << "Unable to " << operation << ". "
-                   << "The configuration function returned a null pointer.";
-            return (false);
-        }
-
-        // Store the answer if we need it.
-
-        // Returned value should be 0 (configuration success)
-        comment_ = parseAnswerText(rcode_, status);
-        if (rcode_ != 0) {
-            string reason = "";
-            if (comment_) {
-                reason = string(" (") + comment_->stringValue() + string(")");
-            }
-            ADD_FAILURE() << "Unable to " << operation << ". "
-                   << "The configuration function returned error code "
-                   << rcode_ << reason;
-            return (false);
-        }
-
-        return (true);
-    }
-
-    /// @brief Reset configuration database.
-    ///
-    /// This function resets configuration data base by removing all subnets
-    /// option-data, and hooks libraries. The reset must be performed after each
-    /// test to make sure that contents of the database do not affect the
-    /// results of subsequent tests.
-    void resetConfiguration() {
-        // The default setting is to listen on all interfaces. In order to
-        // properly test interface configuration we disable listening on
-        // all interfaces before each test and later check that this setting
-        // has been overridden by the configuration used in the test.
-        CfgMgr::instance().clear();
-        string config = "{ \"interfaces-config\": {"
-            "    \"interfaces\": [ ]"
-            "},"
-            "\"hooks-libraries\": [ ],"
-            "\"preferred-lifetime\": 3000,"
-            "\"rebind-timer\": 2000, "
-            "\"renew-timer\": 1000, "
-            "\"valid-lifetime\": 4000, "
-            "\"subnet6\": [ ], "
-            "\"dhcp-ddns\": { \"enable-updates\" : false }, "
-            "\"option-def\": [ ], "
-            "\"option-data\": [ ] }";
-        static_cast<void>(executeConfiguration(config,
-                                               "reset configuration database"));
-        CfgMgr::instance().clearStagingConfiguration();
-    }
-
-    /// @brief Retrieve an option associated with a host.
-    ///
-    /// The option is retrieved from the "dhcp6" option space.
-    ///
-    /// @param host Reference to a host for which an option should be retrieved.
-    /// @param option_code Option code.
-    /// @tparam ReturnType Type of the pointer object returned.
-    ///
-    /// @return Pointer to an option or NULL pointer if not found.
-    template<typename ReturnType>
-    ReturnType
-    retrieveOption(const Host& host, const uint16_t option_code) const {
-        return (retrieveOption<ReturnType>(host, DHCP6_OPTION_SPACE, option_code));
-    }
-
-    /// @brief Retrieve an option associated with a host.
-    ///
-    /// @param host Reference to a host for which an option should be retrieved.
-    /// @param space Option space from which option should be retrieved.
-    /// @param option_code Option code.
-    /// @tparam ReturnType Type of the pointer object returned.
-    ///
-    /// @return Pointer to an option or NULL pointer if not found.
-    template<typename ReturnType>
-    ReturnType
-    retrieveOption(const Host& host, const std::string& space,
-                   const uint16_t option_code) const {
-        ConstCfgOptionPtr cfg_option = host.getCfgOption6();
-        if (cfg_option) {
-            OptionDescriptor opt_desc = cfg_option->get(space, option_code);
-            if (opt_desc.option_) {
-                return (boost::dynamic_pointer_cast<
-                        typename ReturnType::element_type>(opt_desc.option_));
-            }
-        }
-        return (ReturnType());
-    }
-
     /// @brief Test invalid option parameter value.
     ///
     /// This test function constructs the simple configuration
@@ -909,7 +744,7 @@ public:
         std::string config = createConfigWithOption(params);
         ASSERT_TRUE(executeConfiguration(config, "parse option configuration"));
 
-        // The subnet should now hold one option with the specified code.
+        // The subnet should now hold one option with the specified option code.
         OptionDescriptor desc =
             getOptionFromSubnet(IOAddress("2001:db8:1::5"), option_code);
         ASSERT_TRUE(desc.option_);
@@ -951,36 +786,200 @@ public:
         // Clear any existing configuration.
         CfgMgr::instance().clear();
     }
-
-    /// @brief This utility method attempts to configure using specified
-    ///        config and then returns requested pool from requested subnet
+    /// @brief Parse and Execute configuration
     ///
-    /// @param config configuration to be applied
-    /// @param subnet_index index of the subnet to be returned (0 - the first subnet)
-    /// @param pool_index index of the pool within a subnet (0 - the first pool)
-    /// @param type Pool type (TYPE_NA or TYPE_PD)
-    /// @param pool [out] Pool pointer will be stored here (if found)
-    void getPool(const std::string& config, size_t subnet_index,
-                 size_t pool_index, Lease::Type type, PoolPtr& pool) {
-        ConstElementPtr status;
+    /// Parses a configuration and executes a configuration of the server.
+    /// If the operation fails, the current test will register a failure.
+    ///
+    /// @param config Configuration to parse
+    /// @param operation Operation being performed.  In the case of an error,
+    ///        the error text will include the string "unable to <operation>.".
+    ///
+    /// @return true if the configuration succeeded, false if not.  In the
+    ///         latter case, a failure will have been added to the current test.
+    bool
+    executeConfiguration(const std::string& config, const char* operation) {
+        CfgMgr::instance().clear();
         ConstElementPtr json;
+        ConstElementPtr status;
+        try {
+            json = parseJSON(config);
+            status = Dhcpv6SrvTest::configure(srv_, json);
+        } catch (const std::exception& ex) {
+            ADD_FAILURE() << "Unable to " << operation << ". "
+                   << "The following configuration was used: " << std::endl
+                   << config << std::endl
+                   << " and the following error message was returned:"
+                   << ex.what() << std::endl;
+            return (false);
+        }
 
-        EXPECT_NO_THROW(json = parseDHCP6(config, true));
-        EXPECT_NO_THROW(status = Dhcpv6SrvTest::configure(srv_, json));
-        ASSERT_TRUE(status);
-        checkResult(status, 0);
-
-        ConstCfgSubnets6Ptr subnets6 = CfgMgr::instance().getStagingCfg()->getCfgSubnets6();
-        ASSERT_TRUE(subnets6);
+        // The status object must not be NULL
+        if (!status) {
+            ADD_FAILURE() << "Unable to " << operation << ". "
+                   << "The configuration function returned a null pointer.";
+            return (false);
+        }
 
-        const Subnet6Collection* subnets = subnets6->getAll();
-        ASSERT_TRUE(subnets);
-        ASSERT_GE(subnets->size(), subnet_index + 1);
+        // Store the answer if we need it.
 
-        auto subnet = subnets->begin();
-        // std::advance is not available for subnets iterators.
-        for (size_t i = 0; i < subnet_index; ++i) {
-            subnet = std::next(subnet);
+        // Returned value should be 0 (configuration success)
+        comment_ = parseAnswerText(rcode_, status);
+        if (rcode_ != 0) {
+            string reason = "";
+            if (comment_) {
+                reason = string(" (") + comment_->stringValue() + string(")");
+            }
+            ADD_FAILURE() << "Unable to " << operation << ". "
+                   << "The configuration function returned error code "
+                   << rcode_ << reason;
+            return (false);
+        }
+
+        return (true);
+    }
+
+    /// @brief Reset configuration database.
+    ///
+    /// This function resets configuration data base by removing all subnets
+    /// option-data, and hooks libraries. The reset must be performed after each
+    /// test to make sure that contents of the database do not affect the
+    /// results of subsequent tests.
+    void resetConfiguration() {
+        // The default setting is to listen on all interfaces. In order to
+        // properly test interface configuration we disable listening on
+        // all interfaces before each test and later check that this setting
+        // has been overridden by the configuration used in the test.
+        CfgMgr::instance().clear();
+        string config = "{ \"interfaces-config\": {"
+            "    \"interfaces\": [ ]"
+            "},"
+            "\"hooks-libraries\": [ ],"
+            "\"preferred-lifetime\": 3000,"
+            "\"rebind-timer\": 2000, "
+            "\"renew-timer\": 1000, "
+            "\"valid-lifetime\": 4000, "
+            "\"subnet6\": [ ], "
+            "\"dhcp-ddns\": { \"enable-updates\" : false }, "
+            "\"option-def\": [ ], "
+            "\"option-data\": [ ] }";
+        static_cast<void>(executeConfiguration(config,
+                                               "reset configuration database"));
+        CfgMgr::instance().clearStagingConfiguration();
+    }
+
+    /// @brief Retrieve an option associated with a host.
+    ///
+    /// The option is retrieved from the "dhcp6" option space.
+    ///
+    /// @param host Reference to a host for which an option should be retrieved.
+    /// @param option_code Option code.
+    /// @tparam ReturnType Type of the pointer object returned.
+    ///
+    /// @return Pointer to an option or NULL pointer if not found.
+    template<typename ReturnType>
+    ReturnType
+    retrieveOption(const Host& host, const uint16_t option_code) const {
+        return (retrieveOption<ReturnType>(host, DHCP6_OPTION_SPACE, option_code));
+    }
+
+    /// @brief Retrieve an option associated with a host.
+    ///
+    /// @param host Reference to a host for which an option should be retrieved.
+    /// @param space Option space from which option should be retrieved.
+    /// @param option_code Option code.
+    /// @tparam ReturnType Type of the pointer object returned.
+    ///
+    /// @return Pointer to an option or NULL pointer if not found.
+    template<typename ReturnType>
+    ReturnType
+    retrieveOption(const Host& host, const std::string& space,
+                   const uint16_t option_code) const {
+        ConstCfgOptionPtr cfg_option = host.getCfgOption6();
+        if (cfg_option) {
+            OptionDescriptor opt_desc = cfg_option->get(space, option_code);
+            if (opt_desc.option_) {
+                return (boost::dynamic_pointer_cast<
+                        typename ReturnType::element_type>(opt_desc.option_));
+            }
+        }
+        return (ReturnType());
+    }
+
+    /// @brief Checks if specified subnet is part of the collection
+    ///
+    /// @tparam CollectionType type of subnet6 collections i.e.
+    /// either Subnet6SimpleCollection or Subnet6Collection
+    /// @param col collection of subnets to be inspected
+    /// @param subnet text notation (e.g. 192.0.2.0/24)
+    /// @param t1 expected renew-timer value
+    /// @param t2 expected rebind-timer value
+    /// @param preferred expected preferred-lifetime value
+    /// @param valid expected valid-lifetime value
+    /// @param min_preferred expected min-preferred-lifetime value
+    ///        (0 (default) means same as preferred)
+    /// @param max_preferred expected max-preferred-lifetime value
+    ///        (0 (default) means same as preferred)
+    /// @param min_valid expected min-valid-lifetime value
+    ///        (0 (default) means same as valid)
+    /// @param max_valid expected max-valid-lifetime value
+    ///        (0 (default) means same as valid)
+    /// @return the subnet that was examined
+    template <typename CollectionType>
+    Subnet6Ptr
+    checkSubnet(const CollectionType& col, std::string subnet,
+                uint32_t t1, uint32_t t2, uint32_t pref, uint32_t valid,
+                uint32_t min_pref = 0, uint32_t max_pref = 0,
+                uint32_t min_valid = 0, uint32_t max_valid = 0) {
+        auto const& index = col.template get<SubnetPrefixIndexTag>();
+        auto subnet_it = index.find(subnet);
+        if (subnet_it == index.cend()) {
+            ADD_FAILURE() << "Unable to find expected subnet " << subnet;
+            return (Subnet6Ptr());
+        }
+        Subnet6Ptr s = *subnet_it;
+
+        EXPECT_EQ(t1, s->getT1().get());
+        EXPECT_EQ(t2, s->getT2().get());
+        EXPECT_EQ(pref, s->getPreferred().get());
+        EXPECT_EQ(valid, s->getValid().get());
+        EXPECT_EQ(min_pref ? min_pref : pref, s->getPreferred().getMin());
+        EXPECT_EQ(max_pref ? max_pref : pref, s->getPreferred().getMax());
+        EXPECT_EQ(min_valid ? min_valid : valid, s->getValid().getMin());
+        EXPECT_EQ(max_valid ? max_valid : valid, s->getValid().getMax());
+
+        return (s);
+    }
+
+    /// @brief This utility method attempts to configure using specified
+    ///        config and then returns requested pool from requested subnet
+    ///
+    /// @param config configuration to be applied
+    /// @param subnet_index index of the subnet to be returned (0 - the first subnet)
+    /// @param pool_index index of the pool within a subnet (0 - the first pool)
+    /// @param type Pool type (TYPE_NA or TYPE_PD)
+    /// @param pool [out] Pool pointer will be stored here (if found)
+    void getPool(const std::string& config, size_t subnet_index,
+                 size_t pool_index, Lease::Type type, PoolPtr& pool) {
+        ConstElementPtr status;
+        ConstElementPtr json;
+
+        EXPECT_NO_THROW(json = parseDHCP6(config, true));
+        EXPECT_NO_THROW(status = Dhcpv6SrvTest::configure(srv_, json));
+        ASSERT_TRUE(status);
+        checkResult(status, 0);
+
+        ConstCfgSubnets6Ptr subnets6 = CfgMgr::instance().getStagingCfg()->getCfgSubnets6();
+        ASSERT_TRUE(subnets6);
+
+        const Subnet6Collection* subnets = subnets6->getAll();
+        ASSERT_TRUE(subnets);
+        ASSERT_GE(subnets->size(), subnet_index + 1);
+
+        auto subnet = subnets->begin();
+        // std::advance is not available for subnets iterators.
+        for (size_t i = 0; i < subnet_index; ++i) {
+            subnet = std::next(subnet);
         }
         const PoolCollection pools = (*subnet)->getPools(type);
         ASSERT_GE(pools.size(), pool_index + 1);
@@ -1005,7 +1004,7 @@ public:
                                                << isc::data::prettyPrint(exp_value);
     }
 
-    int rcode_; ///< Return code (see @ref isc::config::parseAnswer)
+    int rcode_;                         ///< Return code from element parsing
     ControlledDhcpv6Srv srv_; ///< Instance of the ControlledDhcp6Srv used during tests
     ConstElementPtr comment_; ///< Comment (see @ref isc::config::parseAnswer)
     string valid_iface_; ///< Valid network interface name (present in system)
@@ -1033,7 +1032,8 @@ TEST_F(Dhcp6ParserTest, bogusCommand) {
 TEST_F(Dhcp6ParserTest, emptyInterfaceConfig) {
 
     ConstElementPtr json;
-    EXPECT_NO_THROW(json = parseDHCP6("{ \"preferred-lifetime\": 3000,"
+    EXPECT_NO_THROW(json = parseDHCP6("{ "
+                                      "\"preferred-lifetime\": 3000,"
                                       "\"rebind-timer\": 2000, "
                                       "\"renew-timer\": 1000, "
                                       "\"valid-lifetime\": 4000 }"));
@@ -1050,7 +1050,7 @@ TEST_F(Dhcp6ParserTest, emptyInterfaceConfig) {
 /// specified (boundary check is done when lifetimes are applied).
 TEST_F(Dhcp6ParserTest, outBoundValidLifetime) {
 
-    string too_small =  "{ " + genIfaceConfig() + "," +
+    string too_small =  "{ " + genIfaceConfig() + ","
         "\"subnet6\": [ { "
         "    \"id\": 1,"
         "    \"pools\": [ { \"pool\": \"2001:db8::/64\" } ],"
@@ -1068,7 +1068,7 @@ TEST_F(Dhcp6ParserTest, outBoundValidLifetime) {
     checkResult(status, 1, expected);
     resetConfiguration();
 
-    string too_large =  "{ " + genIfaceConfig() + "," +
+    string too_large =  "{ " + genIfaceConfig() + ","
         "\"subnet6\": [ { "
         "    \"id\": 1,"
         "    \"pools\": [ { \"pool\": \"2001:db8::/64\" } ],"
@@ -1083,7 +1083,7 @@ TEST_F(Dhcp6ParserTest, outBoundValidLifetime) {
     checkResult(status, 1, expected);
     resetConfiguration();
 
-    string before =  "{ " + genIfaceConfig() + "," +
+    string before =  "{ " + genIfaceConfig() + ","
         "\"subnet6\": [ { "
         "    \"id\": 1,"
         "    \"pools\": [ { \"pool\": \"2001:db8::/64\" } ],"
@@ -1099,7 +1099,7 @@ TEST_F(Dhcp6ParserTest, outBoundValidLifetime) {
     checkResult(status, 1, expected);
     resetConfiguration();
 
-    string after =  "{ " + genIfaceConfig() + "," +
+    string after =  "{ " + genIfaceConfig() + ","
         "\"subnet6\": [ { "
         "    \"id\": 1,"
         "    \"pools\": [ { \"pool\": \"2001:db8::/64\" } ],"
@@ -1115,7 +1115,7 @@ TEST_F(Dhcp6ParserTest, outBoundValidLifetime) {
     checkResult(status, 1, expected);
     resetConfiguration();
 
-    string crossed =  "{ " + genIfaceConfig() + "," +
+    string crossed =  "{ " + genIfaceConfig() + ","
         "\"subnet6\": [ { "
         "    \"id\": 1,"
         "    \"pools\": [ { \"pool\": \"2001:db8::/64\" } ],"
@@ -1136,7 +1136,7 @@ TEST_F(Dhcp6ParserTest, outBoundValidLifetime) {
 /// parameters only.
 TEST_F(Dhcp6ParserTest, outBoundGlobalValidLifetime) {
 
-    string too_small =  "{ " + genIfaceConfig() + "," +
+    string too_small =  "{ " + genIfaceConfig() + ","
         "\"valid-lifetime\": 1000, \"min-valid-lifetime\": 2000 }";
 
     ConstElementPtr json;
@@ -1150,7 +1150,7 @@ TEST_F(Dhcp6ParserTest, outBoundGlobalValidLifetime) {
     checkResult(status, 1, expected);
     resetConfiguration();
 
-    string too_large =  "{ " + genIfaceConfig() + "," +
+    string too_large =  "{ " + genIfaceConfig() + ","
         "\"valid-lifetime\": 2000, \"max-valid-lifetime\": 1000 }";
 
     ASSERT_NO_THROW(json = parseDHCP6(too_large));
@@ -1161,7 +1161,7 @@ TEST_F(Dhcp6ParserTest, outBoundGlobalValidLifetime) {
     checkResult(status, 1, expected);
     resetConfiguration();
 
-    string before =  "{ " + genIfaceConfig() + "," +
+    string before =  "{ " + genIfaceConfig() + ","
         "\"valid-lifetime\": 1000, \"min-valid-lifetime\": 2000, "
         "\"max-valid-lifetime\": 4000 }";
 
@@ -1173,7 +1173,7 @@ TEST_F(Dhcp6ParserTest, outBoundGlobalValidLifetime) {
     checkResult(status, 1, expected);
     resetConfiguration();
 
-    string after =  "{ " + genIfaceConfig() + "," +
+    string after =  "{ " + genIfaceConfig() + ","
         "\"valid-lifetime\": 5000, \"min-valid-lifetime\": 1000, "
         "\"max-valid-lifetime\": 4000 }";
 
@@ -1185,7 +1185,7 @@ TEST_F(Dhcp6ParserTest, outBoundGlobalValidLifetime) {
     checkResult(status, 1, expected);
     resetConfiguration();
 
-    string crossed =  "{ " + genIfaceConfig() + "," +
+    string crossed =  "{ " + genIfaceConfig() + ","
         "\"valid-lifetime\": 1500, \"min-valid-lifetime\": 2000, "
         "\"max-valid-lifetime\": 1000 }";
 
@@ -1197,12 +1197,81 @@ TEST_F(Dhcp6ParserTest, outBoundGlobalValidLifetime) {
     checkResult(status, 1, expected);
 }
 
+/// Check that the renew-timer doesn't have to be specified, in which case
+/// it is marked unspecified in the Subnet.
+TEST_F(Dhcp6ParserTest, unspecifiedRenewTimer) {
+
+    string config = "{ " + genIfaceConfig() + ","
+        "\"rebind-timer\": 2000, "
+        "\"subnet6\": [ { "
+        "    \"id\": 1,"
+        "    \"pools\": [ { \"pool\": \"2001:db8::/64\" } ],"
+        "    \"subnet\": \"2001:db8::/32\" } ],"
+        "\"valid-lifetime\": 4000 }";
+
+    ConstElementPtr json;
+    ASSERT_NO_THROW(json = parseDHCP6(config));
+    extractConfig(config);
+
+    ConstElementPtr status;
+    EXPECT_NO_THROW(status = Dhcpv6SrvTest::configure(srv_, json));
+
+    // returned value should be 0 (success)
+    checkResult(status, 0);
+
+    Subnet6Ptr subnet = CfgMgr::instance().getStagingCfg()->
+        getCfgSubnets6()->selectSubnet(IOAddress("2001:db8::1"));
+    ASSERT_TRUE(subnet);
+
+    EXPECT_TRUE(subnet->getT1().unspecified());
+    EXPECT_FALSE(subnet->getT2().unspecified());
+    EXPECT_EQ(2000, subnet->getT2().get());
+    EXPECT_EQ(4000, subnet->getValid().get());
+
+    // Check that subnet-id is 1
+    EXPECT_EQ(1, subnet->getID());
+}
+
+/// Check that the rebind-timer doesn't have to be specified, in which case
+/// it is marked unspecified in the Subnet.
+TEST_F(Dhcp6ParserTest, unspecifiedRebindTimer) {
+
+    string config = "{ " + genIfaceConfig() + ","
+        "\"renew-timer\": 1000, "
+        "\"subnet6\": [ { "
+        "    \"id\": 1,"
+        "    \"pools\": [ { \"pool\": \"2001:db8::/64\" } ],"
+        "    \"subnet\": \"2001:db8::/32\" } ],"
+        "\"valid-lifetime\": 4000 }";
+
+    ConstElementPtr json;
+    ASSERT_NO_THROW(json = parseDHCP6(config));
+    extractConfig(config);
+
+    ConstElementPtr status;
+    EXPECT_NO_THROW(status = Dhcpv6SrvTest::configure(srv_, json));
+
+    // returned value should be 0 (success)
+    checkResult(status, 0);
+
+    Subnet6Ptr subnet = CfgMgr::instance().getStagingCfg()->
+        getCfgSubnets6()->selectSubnet(IOAddress("2001:db8::1"));
+    ASSERT_TRUE(subnet);
+    EXPECT_FALSE(subnet->getT1().unspecified());
+    EXPECT_EQ(1000, subnet->getT1().get());
+    EXPECT_TRUE(subnet->getT2().unspecified());
+    EXPECT_EQ(4000, subnet->getValid().get());
+
+    // Check that subnet-id is 1
+    EXPECT_EQ(1, subnet->getID());
+}
+
 /// Check that preferred-lifetime must be between min-preferred-lifetime and
 /// max-preferred-lifetime when a bound is specified, *AND* a subnet is
 /// specified (boundary check is done when lifetimes are applied).
 TEST_F(Dhcp6ParserTest, outBoundPreferredLifetime) {
 
-    string too_small =  "{ " + genIfaceConfig() + "," +
+    string too_small =  "{ " + genIfaceConfig() + ","
         "\"subnet6\": [ { "
         "    \"id\": 1,"
         "    \"pools\": [ { \"pool\": \"2001:db8::/64\" } ],"
@@ -1220,7 +1289,7 @@ TEST_F(Dhcp6ParserTest, outBoundPreferredLifetime) {
     checkResult(status, 1, expected);
     resetConfiguration();
 
-    string too_large =  "{ " + genIfaceConfig() + "," +
+    string too_large =  "{ " + genIfaceConfig() + ","
         "\"subnet6\": [ { "
         "    \"id\": 1,"
         "    \"pools\": [ { \"pool\": \"2001:db8::/64\" } ],"
@@ -1235,7 +1304,7 @@ TEST_F(Dhcp6ParserTest, outBoundPreferredLifetime) {
     checkResult(status, 1, expected);
     resetConfiguration();
 
-    string before =  "{ " + genIfaceConfig() + "," +
+    string before =  "{ " + genIfaceConfig() + ","
         "\"subnet6\": [ { "
         "    \"id\": 1,"
         "    \"pools\": [ { \"pool\": \"2001:db8::/64\" } ],"
@@ -1251,7 +1320,7 @@ TEST_F(Dhcp6ParserTest, outBoundPreferredLifetime) {
     checkResult(status, 1, expected);
     resetConfiguration();
 
-    string after =  "{ " + genIfaceConfig() + "," +
+    string after =  "{ " + genIfaceConfig() + ","
         "\"subnet6\": [ { "
         "    \"id\": 1,"
         "    \"pools\": [ { \"pool\": \"2001:db8::/64\" } ],"
@@ -1267,7 +1336,7 @@ TEST_F(Dhcp6ParserTest, outBoundPreferredLifetime) {
     checkResult(status, 1, expected);
     resetConfiguration();
 
-    string crossed =  "{ " + genIfaceConfig() + "," +
+    string crossed =  "{ " + genIfaceConfig() + ","
         "\"subnet6\": [ { "
         "    \"id\": 1,"
         "    \"pools\": [ { \"pool\": \"2001:db8::/64\" } ],"
@@ -1288,7 +1357,7 @@ TEST_F(Dhcp6ParserTest, outBoundPreferredLifetime) {
 /// parameters only.
 TEST_F(Dhcp6ParserTest, outBoundGlobalPreferredLifetime) {
 
-    string too_small =  "{ " + genIfaceConfig() + "," +
+    string too_small =  "{ " + genIfaceConfig() + ","
         "\"preferred-lifetime\": 1000, \"min-preferred-lifetime\": 2000 }";
 
     ConstElementPtr json;
@@ -1302,7 +1371,7 @@ TEST_F(Dhcp6ParserTest, outBoundGlobalPreferredLifetime) {
     checkResult(status, 1, expected);
     resetConfiguration();
 
-    string too_large =  "{ " + genIfaceConfig() + "," +
+    string too_large =  "{ " + genIfaceConfig() + ","
         "\"preferred-lifetime\": 2000, \"max-preferred-lifetime\": 1000 }";
 
     ASSERT_NO_THROW(json = parseDHCP6(too_large));
@@ -1313,7 +1382,7 @@ TEST_F(Dhcp6ParserTest, outBoundGlobalPreferredLifetime) {
     checkResult(status, 1, expected);
     resetConfiguration();
 
-    string before =  "{ " + genIfaceConfig() + "," +
+    string before =  "{ " + genIfaceConfig() + ","
         "\"preferred-lifetime\": 1000, \"min-preferred-lifetime\": 2000, "
         "\"max-preferred-lifetime\": 4000 }";
 
@@ -1325,7 +1394,7 @@ TEST_F(Dhcp6ParserTest, outBoundGlobalPreferredLifetime) {
     checkResult(status, 1, expected);
     resetConfiguration();
 
-    string after =  "{ " + genIfaceConfig() + "," +
+    string after =  "{ " + genIfaceConfig() + ","
         "\"preferred-lifetime\": 5000, \"min-preferred-lifetime\": 1000, "
         "\"max-preferred-lifetime\": 4000 }";
 
@@ -1337,7 +1406,7 @@ TEST_F(Dhcp6ParserTest, outBoundGlobalPreferredLifetime) {
     checkResult(status, 1, expected);
     resetConfiguration();
 
-    string crossed =  "{ " + genIfaceConfig() + "," +
+    string crossed =  "{ " + genIfaceConfig() + ","
         "\"preferred-lifetime\": 1500, \"min-preferred-lifetime\": 2000, "
         "\"max-preferred-lifetime\": 1000 }";
 
@@ -1401,8 +1470,8 @@ TEST_F(Dhcp6ParserTest, subnetGlobalDefaults) {
 
     // Now check if the configuration was indeed handled and we have
     // expected pool configured.
-    Subnet6Ptr subnet = CfgMgr::instance().getStagingCfg()->getCfgSubnets6()->
-        selectSubnet(IOAddress("2001:db8:1::5"), classify_);
+    Subnet6Ptr subnet = CfgMgr::instance().getStagingCfg()->
+        getCfgSubnets6()->selectSubnet(IOAddress("2001:db8:1::5"), classify_);
     ASSERT_TRUE(subnet);
     EXPECT_EQ(1000, subnet->getT1().get());
     EXPECT_EQ(2000, subnet->getT2().get());
@@ -1464,7 +1533,7 @@ TEST_F(Dhcp6ParserTest, multipleSubnetsExplicitIDs) {
         ASSERT_TRUE(subnets);
         ASSERT_EQ(4, subnets->size()); // We expect 4 subnets
 
-        // Check that subnet ids are as expected.
+        // Verify that subnet ids are as expected.
         // Now the subnet order is the subnet id one.
         auto subnet = subnets->begin();
         EXPECT_EQ(1, (*subnet)->getID());
@@ -1521,7 +1590,7 @@ TEST_F(Dhcp6ParserTest, reconfigureRemoveSubnet) {
     ConstElementPtr x;
 
     // All four subnets
-    string config4 = "{ " + genIfaceConfig() + ","
+    string config6 = "{ " + genIfaceConfig() + ","
         "\"preferred-lifetime\": 3000,"
         "\"rebind-timer\": 2000, "
         "\"renew-timer\": 1000, "
@@ -1595,8 +1664,8 @@ TEST_F(Dhcp6ParserTest, reconfigureRemoveSubnet) {
     // last one.
 
     ConstElementPtr json;
-    ASSERT_NO_THROW(json = parseDHCP6(config4));
-    extractConfig(config4);
+    ASSERT_NO_THROW(json = parseDHCP6(config6));
+    extractConfig(config6);
     EXPECT_NO_THROW(x = Dhcpv6SrvTest::configure(srv_, json));
     checkResult(x, 0);
 
@@ -1607,6 +1676,8 @@ TEST_F(Dhcp6ParserTest, reconfigureRemoveSubnet) {
     ASSERT_TRUE(subnets);
     ASSERT_EQ(4, subnets->size()); // We expect 4 subnets
 
+    CfgMgr::instance().clear();
+
     // Do the reconfiguration (the last subnet is removed)
     ASSERT_NO_THROW(json = parseDHCP6(config_first3));
     EXPECT_NO_THROW(x = Dhcpv6SrvTest::configure(srv_, json));
@@ -1618,15 +1689,17 @@ TEST_F(Dhcp6ParserTest, reconfigureRemoveSubnet) {
     ASSERT_TRUE(subnets);
     ASSERT_EQ(3, subnets->size()); // We expect 3 subnets now (4th is removed)
 
+    // Check subnet-ids of each subnet (it should be monotonously increasing)
     auto subnet = subnets->begin();
     EXPECT_EQ(1, (*subnet)->getID());
     EXPECT_EQ(2, (*++subnet)->getID());
     EXPECT_EQ(3, (*++subnet)->getID());
 
+    CfgMgr::instance().clear();
+
     /// CASE 2: Configure 4 subnets, then reconfigure and remove one
     /// from in between (not first, not last)
-
-    ASSERT_NO_THROW(json = parseDHCP6(config4));
+    ASSERT_NO_THROW(json = parseDHCP6(config6));
     EXPECT_NO_THROW(x = Dhcpv6SrvTest::configure(srv_, json));
     checkResult(x, 0);
 
@@ -1652,7 +1725,7 @@ TEST_F(Dhcp6ParserTest, reconfigureRemoveSubnet) {
 
 // Check whether it is possible to configure compatibility flags.
 TEST_F(Dhcp6ParserTest, compatibility) {
-    string config = "{ " + genIfaceConfig() + "," +
+    string config = "{ " + genIfaceConfig() + ","
         "\"preferred-lifetime\": 3000,"
         "\"rebind-timer\": 2000, "
         "\"renew-timer\": 1000, "
@@ -1682,7 +1755,7 @@ TEST_F(Dhcp6ParserTest, compatibility) {
 
 // Check that unknown compatibility flag raises error.
 TEST_F(Dhcp6ParserTest, compatibilityUnknown) {
-    string config = "{ " + genIfaceConfig() + "," +
+    string config = "{ " + genIfaceConfig() + ","
         "\"preferred-lifetime\": 3000,"
         "\"rebind-timer\": 2000, "
         "\"renew-timer\": 1000, "
@@ -1710,7 +1783,7 @@ TEST_F(Dhcp6ParserTest, compatibilityUnknown) {
 
 // Check that not boolean compatibility flag value raises error.
 TEST_F(Dhcp6ParserTest, compatibilityNotBool) {
-    string config = "{ " + genIfaceConfig() + "," +
+    string config = "{ " + genIfaceConfig() + ","
         "\"preferred-lifetime\": 3000,"
         "\"rebind-timer\": 2000, "
         "\"renew-timer\": 1000, "
@@ -1772,8 +1845,8 @@ TEST_F(Dhcp6ParserTest, subnetLocal) {
     // returned value should be 0 (configuration success)
     checkResult(status, 0);
 
-    Subnet6Ptr subnet = CfgMgr::instance().getStagingCfg()->getCfgSubnets6()->
-        selectSubnet(IOAddress("2001:db8:1::5"), classify_);
+    Subnet6Ptr subnet = CfgMgr::instance().getStagingCfg()->
+        getCfgSubnets6()->selectSubnet(IOAddress("2001:db8:1::5"), classify_);
     ASSERT_TRUE(subnet);
     EXPECT_EQ(1, subnet->getT1().get());
     EXPECT_EQ(2, subnet->getT2().get());
@@ -1961,7 +2034,8 @@ TEST_F(Dhcp6ParserTest, interfaceIdGlobal) {
 // interface (i.e. local subnet) and interface-id (remote subnet) defined.
 TEST_F(Dhcp6ParserTest, subnetInterfaceAndInterfaceId) {
 
-    const string config = "{ \"preferred-lifetime\": 3000,"
+    const string config = "{"
+        "\"preferred-lifetime\": 3000,"
         "\"rebind-timer\": 2000, "
         "\"renew-timer\": 1000, "
         "\"subnet6\": [ { "
@@ -1998,35 +2072,40 @@ TEST_F(Dhcp6ParserTest, badSubnetValues) {
         {
         "IP is not an address",
         "{ \"subnet6\": [ { "
-        "  \"subnet\": \"not an address/64\" } ]}",
+        "  \"subnet\": \"not an address/64\" } ],"
+        "\"valid-lifetime\": 4000 }",
         "subnet configuration failed: "
         "Failed to convert string to address 'notanaddress': Invalid argument"
         },
         {
         "IP is Invalid",
         "{ \"subnet6\": [ { "
-        "  \"subnet\": \"200175:db8::/64\" } ]}",
+        "  \"subnet\": \"200175:db8::/64\" } ],"
+        "\"valid-lifetime\": 4000 }",
         "subnet configuration failed: "
         "Failed to convert string to address '200175:db8::': Invalid argument"
         },
         {
         "Missing prefix",
         "{ \"subnet6\": [ { "
-        "  \"subnet\": \"2001:db8::\" } ]}",
+        "  \"subnet\": \"2001:db8::\" } ],"
+        "\"valid-lifetime\": 4000 }",
         "subnet configuration failed: "
         "Invalid subnet syntax (prefix/len expected):2001:db8:: (<string>:1:30)"
         },
         {
         "Prefix not an integer (2 slashes)",
         "{ \"subnet6\": [ { "
-        "  \"subnet\": \"2001:db8:://64\" } ]}",
+        "  \"subnet\": \"2001:db8:://64\" } ],"
+        "\"valid-lifetime\": 4000 }",
         "subnet configuration failed: "
         "prefix length: '/64' is not an integer (<string>:1:30)"
         },
         {
         "Prefix value is insane",
         "{ \"subnet6\": [ { "
-        "  \"subnet\": \"2001:db8::/43225\" } ]}",
+        "  \"subnet\": \"2001:db8::/43225\" } ],"
+        "\"valid-lifetime\": 4000 }",
         "subnet configuration failed: "
         "Invalid prefix length specified for subnet: 43225 (<string>:1:30)"
         }
@@ -2042,6 +2121,7 @@ TEST_F(Dhcp6ParserTest, badSubnetValues) {
         ConstElementPtr status;
         EXPECT_NO_THROW(status = Dhcpv6SrvTest::configure(srv_, config));
         checkResult(status, 1);
+        ASSERT_TRUE(comment_);
         EXPECT_EQ(comment_->stringValue(), scenario.exp_error_msg_);
     }
 }
@@ -2192,9 +2272,6 @@ TEST_F(Dhcp6ParserTest, poolOutOfSubnet) {
 // Note this test also verifies that subnets can be configured without
 // prefix delegation pools.
 TEST_F(Dhcp6ParserTest, poolPrefixLen) {
-
-    ConstElementPtr x;
-
     string config = "{ " + genIfaceConfig() + ","
         "\"preferred-lifetime\": 3000,"
         "\"rebind-timer\": 2000, "
@@ -2209,13 +2286,14 @@ TEST_F(Dhcp6ParserTest, poolPrefixLen) {
     ASSERT_NO_THROW(json = parseDHCP6(config));
     extractConfig(config);
 
-    EXPECT_NO_THROW(x = Dhcpv6SrvTest::configure(srv_, json));
+    ConstElementPtr status;
+    EXPECT_NO_THROW(status = Dhcpv6SrvTest::configure(srv_, json));
 
-    // returned value must be 1 (configuration parse error)
-    checkResult(x, 0);
+    // returned value must be 0 (configuration accepted)
+    checkResult(status, 0);
 
-    Subnet6Ptr subnet = CfgMgr::instance().getStagingCfg()->getCfgSubnets6()->
-        selectSubnet(IOAddress("2001:db8:1::5"), classify_);
+    Subnet6Ptr subnet = CfgMgr::instance().getStagingCfg()->
+        getCfgSubnets6()->selectSubnet(IOAddress("2001:db8:1::5"), classify_);
     ASSERT_TRUE(subnet);
     EXPECT_EQ(1000, subnet->getT1().get());
     EXPECT_EQ(2000, subnet->getT2().get());
@@ -2363,6 +2441,24 @@ TEST_F(Dhcp6ParserTest, badPools) {
     EXPECT_TRUE(errorContainsPosition(status, "<string>"));
 }
 
+// Goal of this test is to verify no pool definitions is invalid
+// and returns a location in the error message.
+TEST_F(Dhcp6ParserTest, noPools) {
+
+    // Configuration string.
+    string config = "{ " + genIfaceConfig() + ","
+        "\"preferred-lifetime\": 3000,"
+        "\"rebind-timer\": 2000, "
+        "\"renew-timer\": 1000, "
+        "\"subnet6\": [ { "
+        "    \"id\": 1,"
+        "    \"pools\": [ { \"user-context\": { } } ],"
+        "    \"subnet\": \"2001:db8:1::/64\" } ],"
+        "\"valid-lifetime\": 4000 }";
+
+    EXPECT_THROW(parseDHCP6(config, true), Dhcp6ParseError);
+}
+
 // Goal of this test is to verify the basic parsing of a prefix delegation
 // pool. It uses a single, valid pd pool.
 TEST_F(Dhcp6ParserTest, pdPoolBasics) {
@@ -2712,12 +2808,36 @@ TEST_F(Dhcp6ParserTest, invalidPdPools) {
     }
 }
 
-// The goal of this test is to check whether an option definition
-// that defines an option carrying an IPv6 address can be created.
-TEST_F(Dhcp6ParserTest, optionDefIpv6Address) {
+// Goal of this test is to verify that unknown interface fails
+// to be parsed.
+TEST_F(Dhcp6ParserTest, unknownInterface) {
 
     // Configuration string.
-    std::string config =
+    string config = "{ " + genIfaceConfig() + ","
+        "\"preferred-lifetime\": 3000,"
+        "\"rebind-timer\": 2000, "
+        "\"renew-timer\": 1000, "
+        "\"subnet6\": [ { "
+        "    \"id\": 1,"
+        "    \"pools\": [ ],"
+        "    \"subnet\": \"2001:db8:1::/64\","
+        "    \"interface\": \"ethX\" } ],"
+        "\"valid-lifetime\": 4000 }";
+
+    ConstElementPtr json;
+    ASSERT_NO_THROW(json = parseDHCP6(config, true));
+    ConstElementPtr status;
+    EXPECT_NO_THROW(status = Dhcpv6SrvTest::configure(srv_, json));
+    checkResult(status, 1);
+    EXPECT_TRUE(errorContainsPosition(status, "<string>"));
+}
+
+// The goal of this test is to check whether an option definition
+// that defines an option carrying an IPv6 address can be created.
+TEST_F(Dhcp6ParserTest, optionDefIpv6Address) {
+
+    // Configuration string.
+    std::string config =
         "{ \"option-def\": [ {"
         "      \"name\": \"foo\","
         "      \"code\": 100,"
@@ -2754,6 +2874,7 @@ TEST_F(Dhcp6ParserTest, optionDefIpv6Address) {
     EXPECT_EQ(100, def->getCode());
     EXPECT_FALSE(def->getArrayType());
     EXPECT_EQ(OPT_IPV6_ADDRESS_TYPE, def->getType());
+    EXPECT_TRUE(def->getEncapsulatedSpace().empty());
 
     // The copy of the option definition should be available in the libdhcp++.
     OptionDefinitionPtr def_libdhcp = LibDHCP::getRuntimeOptionDef("isc", 100);
@@ -2813,6 +2934,7 @@ TEST_F(Dhcp6ParserTest, optionDefRecord) {
     EXPECT_EQ(100, def->getCode());
     EXPECT_EQ(OPT_RECORD_TYPE, def->getType());
     EXPECT_FALSE(def->getArrayType());
+    EXPECT_TRUE(def->getEncapsulatedSpace().empty());
 
     // The option comprises the record of data fields. Verify that all
     // fields are present and they are of the expected types.
@@ -2869,6 +2991,7 @@ TEST_F(Dhcp6ParserTest, optionDefMultiple) {
     EXPECT_EQ(100, def1->getCode());
     EXPECT_EQ(OPT_UINT32_TYPE, def1->getType());
     EXPECT_FALSE(def1->getArrayType());
+    EXPECT_TRUE(def1->getEncapsulatedSpace().empty());
 
     // Check the second option definition we have created.
     OptionDefinitionPtr def2 = CfgMgr::instance().getStagingCfg()->
@@ -2880,6 +3003,7 @@ TEST_F(Dhcp6ParserTest, optionDefMultiple) {
     EXPECT_EQ(101, def2->getCode());
     EXPECT_EQ(OPT_IPV4_ADDRESS_TYPE, def2->getType());
     EXPECT_FALSE(def2->getArrayType());
+    EXPECT_TRUE(def2->getEncapsulatedSpace().empty());
 }
 
 // The goal of this test is to verify that the duplicated option
@@ -2973,7 +3097,8 @@ TEST_F(Dhcp6ParserTest, optionDefArray) {
     checkResult(status, 0);
 
     // The option definition should now be available in the CfgMgr.
-    def = CfgMgr::instance().getStagingCfg()->getCfgOptionDef()->get("isc", 100);
+    def = CfgMgr::instance().getStagingCfg()->
+        getCfgOptionDef()->get("isc", 100);
     ASSERT_TRUE(def);
 
     // Check the option data.
@@ -2981,6 +3106,7 @@ TEST_F(Dhcp6ParserTest, optionDefArray) {
     EXPECT_EQ(100, def->getCode());
     EXPECT_EQ(OPT_UINT32_TYPE, def->getType());
     EXPECT_TRUE(def->getArrayType());
+    EXPECT_TRUE(def->getEncapsulatedSpace().empty());
 }
 
 // The purpose of this test to verify that encapsulated option
@@ -3014,7 +3140,8 @@ TEST_F(Dhcp6ParserTest, optionDefEncapsulate) {
     checkResult(status, 0);
 
     // The option definition should now be available in the CfgMgr.
-    def = CfgMgr::instance().getStagingCfg()->getCfgOptionDef()->get("isc", 100);
+    def = CfgMgr::instance().getStagingCfg()->
+        getCfgOptionDef()->get("isc", 100);
     ASSERT_TRUE(def);
 
     // Check the option data.
@@ -3227,6 +3354,7 @@ TEST_F(Dhcp6ParserTest, optionStandardDefOverride) {
         "}";
     ConstElementPtr json;
     ASSERT_NO_THROW(json = parseOPTION_DEFS(config));
+    extractConfig(config);
 
     OptionDefinitionPtr def = CfgMgr::instance().getStagingCfg()->
         getCfgOptionDef()->get(DHCP6_OPTION_SPACE, 100);
@@ -3260,7 +3388,7 @@ TEST_F(Dhcp6ParserTest, optionStandardDefOverride) {
         "      \"space\": \"dhcp6\""
         "  } ]"
         "}";
-    json = parseOPTION_DEFS(config);
+    ASSERT_NO_THROW(json = parseOPTION_DEFS(config));
 
     // Use the configuration string to create new option definition.
     EXPECT_NO_THROW(status = Dhcpv6SrvTest::configure(srv_, json));
@@ -3282,7 +3410,8 @@ TEST_F(Dhcp6ParserTest, optionStandardDefOverride) {
         "      \"space\": \"dhcp6\""
         "  } ]"
         "}";
-    json = parseOPTION_DEFS(config);
+    ASSERT_NO_THROW(json = parseOPTION_DEFS(config));
+    extractConfig(config);
 
     // Use the configuration string to create new option definition.
     EXPECT_NO_THROW(status = Dhcpv6SrvTest::configure(srv_, json));
@@ -3332,8 +3461,8 @@ TEST_F(Dhcp6ParserTest, optionDataDefaultsGlobal) {
     checkResult(x, 0);
 
     // These options are global
-    Subnet6Ptr subnet = CfgMgr::instance().getStagingCfg()->getCfgSubnets6()->
-        selectSubnet(IOAddress("2001:db8:1::5"), classify_);
+    Subnet6Ptr subnet = CfgMgr::instance().getStagingCfg()->
+        getCfgSubnets6()->selectSubnet(IOAddress("2001:db8:1::5"), classify_);
     ASSERT_TRUE(subnet);
     OptionContainerPtr options = subnet->getCfgOption()->getAll(DHCP6_OPTION_SPACE);
     ASSERT_EQ(0, options->size());
@@ -3410,8 +3539,8 @@ TEST_F(Dhcp6ParserTest, optionDataDefaultsSubnet) {
         CfgMgr::instance().getStagingCfg()->getCfgOption()->getAll(DHCP6_OPTION_SPACE);
     ASSERT_EQ(0, options->size());
 
-    Subnet6Ptr subnet = CfgMgr::instance().getStagingCfg()->getCfgSubnets6()->
-        selectSubnet(IOAddress("2001:db8:1::5"), classify_);
+    Subnet6Ptr subnet = CfgMgr::instance().getStagingCfg()->
+        getCfgSubnets6()->selectSubnet(IOAddress("2001:db8:1::5"), classify_);
     ASSERT_TRUE(subnet);
     options = subnet->getCfgOption()->getAll(DHCP6_OPTION_SPACE);
     ASSERT_EQ(2, options->size());
@@ -3579,7 +3708,7 @@ TEST_F(Dhcp6ParserTest, optionDataEncapsulate) {
     CfgMgr::instance().clear();
 
     // Stage 2. Configure base option and a subnet. Please note that
-    // the configuration from the stage 2 is repeated because BIND
+    // the configuration from the stage 2 is repeated because Kea
     // configuration manager sends whole configuration for the lists
     // where at least one element is being modified or added.
     config = "{ " + genIfaceConfig() + ","
@@ -3647,7 +3776,7 @@ TEST_F(Dhcp6ParserTest, optionDataEncapsulate) {
     EXPECT_EQ(100, desc.option_->getType());
 
     // This option should comprise two sub-options.
-    // Onf of them is 'foo' with code 110.
+    // One of them is 'foo' with code 110.
     OptionPtr option_foo = desc.option_->getOption(110);
     ASSERT_TRUE(option_foo);
     EXPECT_EQ(110, option_foo->getType());
@@ -3658,6 +3787,159 @@ TEST_F(Dhcp6ParserTest, optionDataEncapsulate) {
     EXPECT_EQ(111, option_foo2->getType());
 }
 
+// Goal of this test is to verify options configuration
+// for a single subnet. In particular this test checks
+// that local options configuration overrides global
+// option setting.
+TEST_F(Dhcp6ParserTest, optionDataInSingleSubnet) {
+    ConstElementPtr x;
+    string config = "{ " + genIfaceConfig() + ","
+        "\"preferred-lifetime\": 3000,"
+        "\"rebind-timer\": 2000, "
+        "\"renew-timer\": 1000, "
+        "\"option-data\": [ {"
+        "      \"name\": \"subscriber-id\","
+        "      \"data\": \"AB\","
+        "      \"csv-format\": false"
+        " } ],"
+        "\"subnet6\": [ { "
+        "    \"id\": 1,"
+        "    \"pools\": [ { \"pool\": \"2001:db8:1::/80\" } ],"
+        "    \"subnet\": \"2001:db8:1::/64\", "
+        "    \"option-data\": [ {"
+        "          \"name\": \"subscriber-id\","
+        "          \"data\": \"ABCDEF0105\","
+        "          \"csv-format\": false"
+        "        },"
+        "        {"
+        "          \"name\": \"user-class\","
+        "          \"data\": \"FFFEFDFCFB\","
+        "          \"csv-format\": false"
+        "        } ]"
+        " } ],"
+        "\"valid-lifetime\": 4000 }";
+
+    ConstElementPtr json;
+    ASSERT_NO_THROW(json = parseDHCP6(config));
+    extractConfig(config);
+
+    EXPECT_NO_THROW(x = Dhcpv6SrvTest::configure(srv_, json));
+    checkResult(x, 0);
+
+    Subnet6Ptr subnet = CfgMgr::instance().getStagingCfg()->
+        getCfgSubnets6()->selectSubnet(IOAddress("2001:db8:1::5"), classify_);
+    ASSERT_TRUE(subnet);
+    OptionContainerPtr options = subnet->getCfgOption()->getAll(DHCP6_OPTION_SPACE);
+    ASSERT_EQ(2, options->size());
+
+    // Get the search index. Index #1 is to search using option code.
+    const OptionContainerTypeIndex& idx = options->get<1>();
+
+    // Get the options for specified index. Expecting one option to be
+    // returned but in theory we may have multiple options with the same
+    // code so we get the range.
+    std::pair<OptionContainerTypeIndex::const_iterator,
+              OptionContainerTypeIndex::const_iterator> range =
+        idx.equal_range(D6O_SUBSCRIBER_ID);
+    // Expect single option with the code equal to 100.
+    ASSERT_EQ(1, std::distance(range.first, range.second));
+    const uint8_t subid_expected[] = {
+        0xAB, 0xCD, 0xEF, 0x01, 0x05
+    };
+    // Check if option is valid in terms of code and carried data.
+    testOption(*range.first, D6O_SUBSCRIBER_ID, subid_expected, sizeof(subid_expected));
+
+    range = idx.equal_range(D6O_USER_CLASS);
+    ASSERT_EQ(1, std::distance(range.first, range.second));
+    // Do another round of testing with second option.
+    const uint8_t user_class_expected[] = {
+        0xFF, 0xFE, 0xFD, 0xFC, 0xFB
+    };
+    testOption(*range.first, D6O_USER_CLASS, user_class_expected,
+               sizeof(user_class_expected));
+}
+
+// The goal of this test is to check that the option carrying a boolean
+// value can be configured using one of the values: "true", "false", "0"
+// or "1".
+TEST_F(Dhcp6ParserTest, optionDataBoolean) {
+    // Create configuration. Use standard option 1000.
+    std::map<std::string, std::string> params;
+    params["name"] = "bool-option";
+    params["space"] = DHCP6_OPTION_SPACE;
+    params["code"] = "1000";
+    params["data"] = "true";
+    params["csv-format"] = "true";
+
+    std::string config = createConfigWithOption(params);
+    ASSERT_TRUE(executeConfiguration(config, "parse configuration with a"
+                                     " boolean value"));
+
+    // The subnet should now hold one option with the code 1000.
+    OptionDescriptor desc = getOptionFromSubnet(IOAddress("2001:db8:1::5"), 1000);
+    ASSERT_TRUE(desc.option_);
+
+    // This option should be set to "true", represented as 0x1 in the option
+    // buffer.
+    uint8_t expected_option_data[] = {
+        0x1
+    };
+    testConfiguration(params, 1000, expected_option_data,
+                      sizeof(expected_option_data));
+
+    // Configure the option with the "1" value. This should have the same
+    // effect as if "true" was specified.
+    params["data"] = "1";
+    testConfiguration(params, 1000, expected_option_data,
+                      sizeof(expected_option_data));
+
+    // The value of "1" with a few leading zeros should work too.
+    params["data"] = "00001";
+    testConfiguration(params, 1000, expected_option_data,
+                      sizeof(expected_option_data));
+
+    // Configure the option with the "false" value.
+    params["data"] = "false";
+    // The option buffer should now hold the value of 0.
+    expected_option_data[0] = 0;
+    testConfiguration(params, 1000, expected_option_data,
+                      sizeof(expected_option_data));
+
+    // Specifying "0" should have the same effect as "false".
+    params["data"] = "0";
+    testConfiguration(params, 1000, expected_option_data,
+                      sizeof(expected_option_data));
+
+    // The same effect should be for multiple 0 chars.
+    params["data"] = "00000";
+    testConfiguration(params, 1000, expected_option_data,
+                      sizeof(expected_option_data));
+
+    // Bogus values should not be accepted.
+    params["data"] = "bogus";
+    testInvalidOptionParam(params);
+
+    params["data"] = "2";
+    testInvalidOptionParam(params);
+
+    // Now let's test that it is possible to use binary format.
+    params["data"] = "0";
+    params["csv-format"] = "false";
+    testConfiguration(params, 1000, expected_option_data,
+                      sizeof(expected_option_data));
+
+    // The binary 1 should work as well.
+    params["data"] = "1";
+    expected_option_data[0] = 1;
+    testConfiguration(params, 1000, expected_option_data,
+                      sizeof(expected_option_data));
+
+    // As well as an even number of digits.
+    params["data"] = "01";
+    testConfiguration(params, 1000, expected_option_data,
+                      sizeof(expected_option_data));
+}
+
 // Goal of this test is to verify options configuration
 // for multiple subnets.
 TEST_F(Dhcp6ParserTest, optionDataInMultipleSubnets) {
@@ -3695,8 +3977,8 @@ TEST_F(Dhcp6ParserTest, optionDataInMultipleSubnets) {
     EXPECT_NO_THROW(x = Dhcpv6SrvTest::configure(srv_, json));
     checkResult(x, 0);
 
-    Subnet6Ptr subnet1 = CfgMgr::instance().getStagingCfg()->getCfgSubnets6()->
-        selectSubnet(IOAddress("2001:db8:1::5"), classify_);
+    Subnet6Ptr subnet1 = CfgMgr::instance().getStagingCfg()->
+        getCfgSubnets6()->selectSubnet(IOAddress("2001:db8:1::5"), classify_);
     ASSERT_TRUE(subnet1);
     OptionContainerPtr options1 = subnet1->getCfgOption()->getAll(DHCP6_OPTION_SPACE);
     ASSERT_EQ(1, options1->size());
@@ -3721,8 +4003,8 @@ TEST_F(Dhcp6ParserTest, optionDataInMultipleSubnets) {
                sizeof(subid_expected));
 
     // Test another subnet in the same way.
-    Subnet6Ptr subnet2 = CfgMgr::instance().getStagingCfg()->getCfgSubnets6()->
-        selectSubnet(IOAddress("2001:db8:2::4"), classify_);
+    Subnet6Ptr subnet2 = CfgMgr::instance().getStagingCfg()->
+        getCfgSubnets6()->selectSubnet(IOAddress("2001:db8:2::4"), classify_);
     ASSERT_TRUE(subnet2);
     OptionContainerPtr options2 = subnet2->getCfgOption()->getAll(DHCP6_OPTION_SPACE);
     ASSERT_EQ(1, options2->size());
@@ -3742,6 +4024,82 @@ TEST_F(Dhcp6ParserTest, optionDataInMultipleSubnets) {
 
 // This test verifies that it is possible to specify options on
 // pool levels.
+TEST_F(Dhcp6ParserTest, optionDataSinglePool) {
+    ConstElementPtr x;
+    string config = "{ " + genIfaceConfig() + ","
+        "\"preferred-lifetime\": 3000,"
+        "\"rebind-timer\": 2000, "
+        "\"renew-timer\": 1000, "
+        "\"subnet6\": [ { "
+        "    \"id\": 1,"
+        "    \"pools\": [ { "
+        "        \"pool\": \"2001:db8:1::10 - 2001:db8:1::100\","
+        "        \"option-data\": [ {"
+        "            \"name\": \"subscriber-id\","
+        "            \"data\": \"0102030405060708090A\","
+        "            \"csv-format\": false"
+        "        },"
+        "        {"
+        "          \"name\": \"user-class\","
+        "          \"data\": \"FFFEFDFCFB\","
+        "          \"csv-format\": false"
+        "        } ]"
+        "    } ],"
+        "    \"subnet\": \"2001:db8:1::/64\""
+        " } ],"
+        "\"valid-lifetime\": 4000 }";
+
+    ConstElementPtr json;
+    ASSERT_NO_THROW(json = parseDHCP6(config));
+    extractConfig(config);
+
+    EXPECT_NO_THROW(x = Dhcpv6SrvTest::configure(srv_, json));
+    checkResult(x, 0);
+
+    Subnet6Ptr subnet = CfgMgr::instance().getStagingCfg()->getCfgSubnets6()->
+        selectSubnet(IOAddress("2001:db8:1::5"), classify_);
+    ASSERT_TRUE(subnet);
+
+    PoolPtr pool = subnet->getPool(Lease::TYPE_NA, IOAddress("2001:db8:1::10"), false);
+    ASSERT_TRUE(pool);
+    Pool6Ptr pool6 = boost::dynamic_pointer_cast<Pool6>(pool);
+    ASSERT_TRUE(pool6);
+
+    OptionContainerPtr options =
+        pool6->getCfgOption()->getAll(DHCP6_OPTION_SPACE);
+    ASSERT_EQ(2, options->size());
+
+    // Get the search index. Index #1 is to search using option code.
+    const OptionContainerTypeIndex& idx = options->get<1>();
+
+    // Get the options for specified index. Expecting one option to be
+    // returned but in theory we may have multiple options with the same
+    // code so we get the range.
+    std::pair<OptionContainerTypeIndex::const_iterator,
+              OptionContainerTypeIndex::const_iterator> range =
+        idx.equal_range(D6O_SUBSCRIBER_ID);
+    // Expect a single Subscriber ID option instance.
+    ASSERT_EQ(1, std::distance(range.first, range.second));
+    const uint8_t subscriber_id_expected[] = {
+        0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A
+    };
+    // Check if option is valid in terms of code and carried data.
+    testOption(*range.first, D6O_SUBSCRIBER_ID, subscriber_id_expected,
+               sizeof(subscriber_id_expected));
+
+    range = idx.equal_range(D6O_USER_CLASS);
+    ASSERT_EQ(1, std::distance(range.first, range.second));
+    // Do another round of testing with second option.
+
+    const uint8_t user_class_expected[] = {
+        0xFF, 0xFE, 0xFD, 0xFC, 0xFB
+    };
+    testOption(*range.first, D6O_USER_CLASS, user_class_expected,
+               sizeof(user_class_expected));
+}
+
+// This test verifies that it's possible to define different options in
+// different pools and those options are not confused.
 TEST_F(Dhcp6ParserTest, optionDataMultiplePools) {
     ConstElementPtr x;
     string config = "{ " + genIfaceConfig() + ","
@@ -3894,89 +4252,6 @@ TEST_F(Dhcp6ParserTest, optionDataMultiplePools) {
                sizeof(user_class_expected2));
 }
 
-// The goal of this test is to check that the option carrying a boolean
-// value can be configured using one of the values: "true", "false", "0"
-// or "1".
-TEST_F(Dhcp6ParserTest, optionDataBoolean) {
-    // Create configuration. Use standard option 1000.
-    std::map<std::string, std::string> params;
-    params["name"] = "bool-option";
-    params["space"] = DHCP6_OPTION_SPACE;
-    params["code"] = "1000";
-    params["data"] = "true";
-    params["csv-format"] = "true";
-
-    std::string config = createConfigWithOption(params);
-    ASSERT_TRUE(executeConfiguration(config, "parse configuration with a"
-                                     " boolean value"));
-
-    // The subnet should now hold one option with the code 1000.
-    OptionDescriptor desc =
-        getOptionFromSubnet(IOAddress("2001:db8:1::5"), 1000);
-    ASSERT_TRUE(desc.option_);
-
-    // This option should be set to "true", represented as 0x1 in the option
-    // buffer.
-    uint8_t expected_option_data[] = {
-        0x1
-    };
-    testConfiguration(params, 1000, expected_option_data,
-                      sizeof(expected_option_data));
-
-    // Configure the option with the "1" value. This should have the same
-    // effect as if "true" was specified.
-    params["data"] = "1";
-    testConfiguration(params, 1000, expected_option_data,
-                      sizeof(expected_option_data));
-
-    // The value of "1" with a few leading zeros should work too.
-    params["data"] = "00001";
-    testConfiguration(params, 1000, expected_option_data,
-                      sizeof(expected_option_data));
-
-    // Configure the option with the "false" value.
-    params["data"] = "false";
-    // The option buffer should now hold the value of 0.
-    expected_option_data[0] = 0;
-    testConfiguration(params, 1000, expected_option_data,
-                      sizeof(expected_option_data));
-
-    // Specifying "0" should have the same effect as "false".
-    params["data"] = "0";
-    testConfiguration(params, 1000, expected_option_data,
-                      sizeof(expected_option_data));
-
-    // The same effect should be for multiple 0 chars.
-    params["data"] = "00000";
-    testConfiguration(params, 1000, expected_option_data,
-                      sizeof(expected_option_data));
-
-    // Bogus values should not be accepted.
-    params["data"] = "bogus";
-    testInvalidOptionParam(params);
-
-    params["data"] = "2";
-    testInvalidOptionParam(params);
-
-    // Now let's test that it is possible to use binary format.
-    params["data"] = "0";
-    params["csv-format"] = "false";
-    testConfiguration(params, 1000, expected_option_data,
-                      sizeof(expected_option_data));
-
-    // The binary 1 should work as well.
-    params["data"] = "1";
-    expected_option_data[0] = 1;
-    testConfiguration(params, 1000, expected_option_data,
-                      sizeof(expected_option_data));
-
-    // As well as an even number of digits.
-    params["data"] = "01";
-    testConfiguration(params, 1000, expected_option_data,
-                      sizeof(expected_option_data));
-
-}
-
 // Verify that empty option name is rejected in the configuration.
 TEST_F(Dhcp6ParserTest, optionNameEmpty) {
     // Empty option names not allowed.
@@ -4048,8 +4323,8 @@ TEST_F(Dhcp6ParserTest, optionDataValidHexLiterals) {
         EXPECT_NO_THROW(x = Dhcpv6SrvTest::configure(srv_, json));
         checkResult(x, 0);
 
-        Subnet6Ptr subnet = CfgMgr::instance().getStagingCfg()->getCfgSubnets6()->
-                            selectSubnet(IOAddress("2001:db8:1::5"), classify_);
+        Subnet6Ptr subnet = CfgMgr::instance().getStagingCfg()->
+            getCfgSubnets6()->selectSubnet(IOAddress("2001:db8:1::5"), classify_);
         ASSERT_TRUE(subnet);
         OptionContainerPtr options = subnet->getCfgOption()->getAll(DHCP6_OPTION_SPACE);
         ASSERT_EQ(1, options->size());
@@ -4061,8 +4336,8 @@ TEST_F(Dhcp6ParserTest, optionDataValidHexLiterals) {
         // returned but in theory we may have multiple options with the same
         // code so we get the range.
         std::pair<OptionContainerTypeIndex::const_iterator,
-                   OptionContainerTypeIndex::const_iterator> range =
-                 idx.equal_range(D6O_SUBSCRIBER_ID);
+                OptionContainerTypeIndex::const_iterator> range =
+                    idx.equal_range(D6O_SUBSCRIBER_ID);
 
         // Expect single option with the code equal to 38.
         ASSERT_EQ(1, std::distance(range.first, range.second));
@@ -4085,19 +4360,22 @@ TEST_F(Dhcp6ParserTest, stdOptionData) {
     params["space"] = DHCP6_OPTION_SPACE;
     // Option code 3 means OPTION_IA_NA.
     params["code"] = "3";
+    // Specify option values in a CSV (user friendly) format.
     params["data"] = "12345, 6789, 1516";
     params["csv-format"] = "true";
 
     std::string config = createConfigWithOption(params);
-    ConstElementPtr json = parseDHCP6(config);
+    ConstElementPtr json;
+    ASSERT_NO_THROW(json = parseDHCP6(config));
 
     EXPECT_NO_THROW(x = Dhcpv6SrvTest::configure(srv_, json));
     checkResult(x, 0);
 
-    Subnet6Ptr subnet = CfgMgr::instance().getStagingCfg()->getCfgSubnets6()->
-        selectSubnet(IOAddress("2001:db8:1::5"), classify_);
+    Subnet6Ptr subnet = CfgMgr::instance().getStagingCfg()->
+        getCfgSubnets6()->selectSubnet(IOAddress("2001:db8:1::5"), classify_);
     ASSERT_TRUE(subnet);
     OptionContainerPtr options = subnet->getCfgOption()->getAll(DHCP6_OPTION_SPACE);
+    ASSERT_TRUE(options);
     ASSERT_EQ(1, options->size());
 
     // Get the search index. Index #1 is to search using option code.
@@ -4189,122 +4467,6 @@ TEST_F(Dhcp6ParserTest, rdnssOption) {
     EXPECT_EQ("example.com.", optionCustom->readFqdn(4));
 }
 
-// This test checks if vendor options can be specified in the config file
-// (in hex format), and later retrieved from configured subnet
-TEST_F(Dhcp6ParserTest, vendorOptionsHex) {
-
-    // This configuration string is to configure two options
-    // sharing the code 1 and belonging to the different vendor spaces.
-    // (different vendor-id values).
-    string config = "{ " + genIfaceConfig() + ","
-        "\"preferred-lifetime\": 3000,"
-        "\"valid-lifetime\": 4000,"
-        "\"rebind-timer\": 2000,"
-        "\"renew-timer\": 1000,"
-        "\"option-data\": [ {"
-        "    \"name\": \"option-one\","
-        "    \"space\": \"vendor-4491\","
-        "    \"code\": 100,"
-        "    \"data\": \"ABCDEF0105\","
-        "    \"csv-format\": false"
-        " },"
-        " {"
-        "    \"name\": \"option-two\","
-        "    \"space\": \"vendor-1234\","
-        "    \"code\": 100,"
-        "    \"data\": \"1234\","
-        "    \"csv-format\": false"
-        " } ],"
-        "\"subnet6\": [ { "
-        "    \"id\": 1,"
-        "    \"pools\": [ { \"pool\": \"2001:db8:1::/80\" } ],"
-        "    \"subnet\": \"2001:db8:1::/64\""
-        " } ]"
-        "}";
-
-    ConstElementPtr json;
-    ASSERT_NO_THROW(json = parseDHCP6(config));
-    extractConfig(config);
-
-    ConstElementPtr status;
-    EXPECT_NO_THROW(status = Dhcpv6SrvTest::configure(srv_, json));
-    ASSERT_TRUE(status);
-    checkResult(status, 0);
-
-    // Options should be now available
-    // Try to get the option from the vendor space 4491
-    OptionDescriptor desc1 =
-        CfgMgr::instance().getStagingCfg()->getCfgOption()->get(VENDOR_ID_CABLE_LABS, 100);
-    ASSERT_TRUE(desc1.option_);
-    EXPECT_EQ(100, desc1.option_->getType());
-    // Try to get the option from the vendor space 1234
-    OptionDescriptor desc2 =
-        CfgMgr::instance().getStagingCfg()->getCfgOption()->get(1234, 100);
-    ASSERT_TRUE(desc2.option_);
-    EXPECT_EQ(100, desc1.option_->getType());
-
-    // Try to get the non-existing option from the non-existing
-    // option space and  expect that option is not returned.
-    OptionDescriptor desc3 =
-        CfgMgr::instance().getStagingCfg()->getCfgOption()->get(5678, 38);
-    ASSERT_FALSE(desc3.option_);
-}
-
-// This test checks if vendor options can be specified in the config file,
-// (in csv format), and later retrieved from configured subnet
-TEST_F(Dhcp6ParserTest, vendorOptionsCsv) {
-
-    // This configuration string is to configure two options
-    // sharing the code 1 and belonging to the different vendor spaces.
-    // (different vendor-id values).
-    string config = "{ " + genIfaceConfig() + ","
-        "\"preferred-lifetime\": 3000,"
-        "\"valid-lifetime\": 4000,"
-        "\"rebind-timer\": 2000,"
-        "\"renew-timer\": 1000,"
-        "\"option-data\": [ {"
-        "    \"name\": \"foo\","
-        "    \"space\": \"vendor-4491\","
-        "    \"code\": 100,"
-        "    \"data\": \"this is a string vendor-opt\""
-        " } ],"
-        "\"option-def\": [ {"
-        "    \"name\": \"foo\","
-        "    \"code\": 100,"
-        "    \"type\": \"string\","
-        "    \"space\": \"vendor-4491\""
-        " } ],"
-        "\"subnet6\": [ { "
-        "    \"id\": 1,"
-        "    \"pools\": [ { \"pool\": \"2001:db8:1::/80\" } ],"
-        "    \"subnet\": \"2001:db8:1::/64\""
-        " } ]"
-        "}";
-
-    ConstElementPtr status;
-
-    ConstElementPtr json;
-    ASSERT_NO_THROW(json = parseDHCP6(config));
-    extractConfig(config);
-
-    EXPECT_NO_THROW(status = Dhcpv6SrvTest::configure(srv_, json));
-    ASSERT_TRUE(status);
-    checkResult(status, 0);
-
-    // Options should be now available.
-    // Try to get the option from the vendor space 4491
-    OptionDescriptor desc1 =
-        CfgMgr::instance().getStagingCfg()->getCfgOption()->get(VENDOR_ID_CABLE_LABS, 100);
-    ASSERT_TRUE(desc1.option_);
-    EXPECT_EQ(100, desc1.option_->getType());
-
-    // Try to get the non-existing option from the non-existing
-    // option space and  expect that option is not returned.
-    OptionDescriptor desc2 =
-        CfgMgr::instance().getStagingCfg()->getCfgOption()->get(5678, 100);
-    ASSERT_FALSE(desc2.option_);
-}
-
 /// @todo add tests similar to vendorOptionsCsv and vendorOptionsHex, but for
 ///       vendor options defined in a subnet.
 
@@ -4369,6 +4531,7 @@ TEST_F(Dhcp6ParserTest, DISABLED_stdOptionDataEncapsulate) {
     // they should be included as sub-options in the 'vendor-opts'
     // option.
     config = "{ " + genIfaceConfig() + ","
+        "\"valid-lifetime\": 3000,"
         "\"rebind-timer\": 2000,"
         "\"renew-timer\": 1000,"
         "\"option-data\": [ {"
@@ -4406,6 +4569,7 @@ TEST_F(Dhcp6ParserTest, DISABLED_stdOptionDataEncapsulate) {
 
     ASSERT_NO_THROW(json = parseDHCP6(config));
     extractConfig(config);
+
     EXPECT_NO_THROW(status = Dhcpv6SrvTest::configure(srv_, json));
     ASSERT_TRUE(status);
     checkResult(status, 0);
@@ -4438,20 +4602,136 @@ TEST_F(Dhcp6ParserTest, DISABLED_stdOptionDataEncapsulate) {
     // Validate the value according to the configuration.
     EXPECT_EQ(1234, option_foo_uint32->getValue());
 
-    // Option with the code 111 should be added as a sub-option.
-    OptionPtr option_foo2 = desc.option_->getOption(111);
-    ASSERT_TRUE(option_foo2);
-    EXPECT_EQ(111, option_foo2->getType());
-    // This option comprises the IPV4 address. Such option is
-    // represented by OptionCustom object.
-    OptionCustomPtr option_foo2_v4 =
-        boost::dynamic_pointer_cast<OptionCustom>(option_foo2);
-    ASSERT_TRUE(option_foo2_v4);
-    // Get the IP address carried by this option and validate it.
-    EXPECT_EQ("192.168.2.1", option_foo2_v4->readAddress().toText());
+    // Option with the code 111 should be added as a sub-option.
+    OptionPtr option_foo2 = desc.option_->getOption(111);
+    ASSERT_TRUE(option_foo2);
+    EXPECT_EQ(111, option_foo2->getType());
+    // This option comprises the IPV4 address. Such option is
+    // represented by OptionCustom object.
+    OptionCustomPtr option_foo2_v4 =
+        boost::dynamic_pointer_cast<OptionCustom>(option_foo2);
+    ASSERT_TRUE(option_foo2_v4);
+    // Get the IP address carried by this option and validate it.
+    EXPECT_EQ("192.168.2.1", option_foo2_v4->readAddress().toText());
+
+    // Option with the code 112 should not be added.
+    EXPECT_FALSE(desc.option_->getOption(112));
+}
+
+// This test checks if vendor options can be specified in the config file
+// (in hex format), and later retrieved from configured subnet
+TEST_F(Dhcp6ParserTest, vendorOptionsHex) {
+
+    // This configuration string is to configure two options
+    // sharing the code 1 and belonging to the different vendor spaces.
+    // (different vendor-id values).
+    string config = "{ " + genIfaceConfig() + ","
+        "\"preferred-lifetime\": 3000,"
+        "\"valid-lifetime\": 4000,"
+        "\"rebind-timer\": 2000,"
+        "\"renew-timer\": 1000,"
+        "\"option-data\": [ {"
+        "    \"name\": \"option-one\","
+        "    \"space\": \"vendor-4491\"," // VENDOR_ID_CABLE_LABS = 4491
+        "    \"code\": 100," // just a random code
+        "    \"data\": \"ABCDEF0105\","
+        "    \"csv-format\": false"
+        " },"
+        " {"
+        "    \"name\": \"option-two\","
+        "    \"space\": \"vendor-1234\","
+        "    \"code\": 100,"
+        "    \"data\": \"1234\","
+        "    \"csv-format\": false"
+        " } ],"
+        "\"subnet6\": [ { "
+        "    \"id\": 1,"
+        "    \"pools\": [ { \"pool\": \"2001:db8:1::/80\" } ],"
+        "    \"subnet\": \"2001:db8:1::/64\""
+        " } ]"
+        "}";
+
+    ConstElementPtr json;
+    ASSERT_NO_THROW(json = parseDHCP6(config));
+    extractConfig(config);
+
+    ConstElementPtr status;
+    EXPECT_NO_THROW(status = Dhcpv6SrvTest::configure(srv_, json));
+    ASSERT_TRUE(status);
+    checkResult(status, 0);
+
+    // Options should be now available
+    // Try to get the option from the vendor space 4491
+    OptionDescriptor desc1 = CfgMgr::instance().getStagingCfg()->
+        getCfgOption()->get(VENDOR_ID_CABLE_LABS, 100);
+    ASSERT_TRUE(desc1.option_);
+    EXPECT_EQ(100, desc1.option_->getType());
+    // Try to get the option from the vendor space 1234
+    OptionDescriptor desc2 =
+        CfgMgr::instance().getStagingCfg()->getCfgOption()->get(1234, 100);
+    ASSERT_TRUE(desc2.option_);
+    EXPECT_EQ(100, desc1.option_->getType());
+
+    // Try to get the non-existing option from the non-existing
+    // option space and  expect that option is not returned.
+    OptionDescriptor desc3 =
+        CfgMgr::instance().getStagingCfg()->getCfgOption()->get(5678, 38);
+    ASSERT_FALSE(desc3.option_);
+}
+
+// This test checks if vendor options can be specified in the config file,
+// (in csv format), and later retrieved from configured subnet
+TEST_F(Dhcp6ParserTest, vendorOptionsCsv) {
+
+    // This configuration string is to configure two options
+    // sharing the code 1 and belonging to the different vendor spaces.
+    // (different vendor-id values).
+    string config = "{ " + genIfaceConfig() + ","
+        "\"preferred-lifetime\": 3000,"
+        "\"valid-lifetime\": 4000,"
+        "\"rebind-timer\": 2000,"
+        "\"renew-timer\": 1000,"
+        "\"option-data\": [ {"
+        "    \"name\": \"foo\","
+        "    \"space\": \"vendor-4491\","
+        "    \"code\": 100,"
+        "    \"data\": \"this is a string vendor-opt\""
+        " } ],"
+        "\"option-def\": [ {"
+        "    \"name\": \"foo\","
+        "    \"code\": 100,"
+        "    \"type\": \"string\","
+        "    \"space\": \"vendor-4491\""
+        " } ],"
+        "\"subnet6\": [ { "
+        "    \"id\": 1,"
+        "    \"pools\": [ { \"pool\": \"2001:db8:1::/80\" } ],"
+        "    \"subnet\": \"2001:db8:1::/64\""
+        " } ]"
+        "}";
+
+    ConstElementPtr status;
+
+    ConstElementPtr json;
+    ASSERT_NO_THROW(json = parseDHCP6(config));
+    extractConfig(config);
 
-    // Option with the code 112 should not be added.
-    EXPECT_FALSE(desc.option_->getOption(112));
+    EXPECT_NO_THROW(status = Dhcpv6SrvTest::configure(srv_, json));
+    ASSERT_TRUE(status);
+    checkResult(status, 0);
+
+    // Options should be now available.
+    // Try to get the option from the vendor space 4491
+    OptionDescriptor desc1 = CfgMgr::instance().getStagingCfg()->
+        getCfgOption()->get(VENDOR_ID_CABLE_LABS, 100);
+    ASSERT_TRUE(desc1.option_);
+    EXPECT_EQ(100, desc1.option_->getType());
+
+    // Try to get the non-existing option from the non-existing
+    // option space and  expect that option is not returned.
+    OptionDescriptor desc2 =
+        CfgMgr::instance().getStagingCfg()->getCfgOption()->get(5678, 100);
+    ASSERT_FALSE(desc2.option_);
 }
 
 // Tests of the hooks libraries configuration.  All tests have the pre-
@@ -4484,6 +4764,7 @@ buildHooksLibrariesConfig(const std::vector<std::string>& libraries = {},
     // Append the remainder of the configuration.
     config += string(
         "],"
+        "\"valid-lifetime\": 4000,"
         "\"rebind-timer\": 2000,"
         "\"renew-timer\": 1000,"
         "\"option-data\": [ {"
@@ -4562,6 +4843,7 @@ TEST_F(Dhcp6ParserTest, LibrariesSpecified) {
     EXPECT_FALSE(checkMarkerFileExists(UNLOAD_MARKER_FILE));
 
     // Set up the configuration with two libraries and load them.
+    // Disable multi-threading since one of the libraries is single-threaded.
     string config = buildHooksLibrariesConfig({CALLOUT_LIBRARY_1, CALLOUT_LIBRARY_2},
                                               /* multi_threading = */ false);
     ASSERT_TRUE(executeConfiguration(config,
@@ -4574,6 +4856,8 @@ TEST_F(Dhcp6ParserTest, LibrariesSpecified) {
     EXPECT_TRUE(checkMarkerFile(LOAD_MARKER_FILE, "12"));
     EXPECT_FALSE(checkMarkerFileExists(UNLOAD_MARKER_FILE));
 
+    // Commit the changes so as we get the fresh configuration for the
+    // second part of this test.
     CfgMgr::instance().commit();
 
     // Unload the libraries.  The load file should not have changed, but
@@ -4655,12 +4939,14 @@ TEST_F(Dhcp6ParserTest, IncompatibleLibrary3Specified) {
     libraries = HooksManager::getLibraryNames();
     EXPECT_TRUE(libraries.empty());
 }
-// This test verifies that it is possible to select subset of interfaces on
-// which server should listen.
+
+// This test verifies that it is possible to select subset of interfaces
+// on which server should listen.
 TEST_F(Dhcp6ParserTest, selectedInterfaces) {
     IfaceMgrTestConfig test_config(true);
 
-    // Make sure there is no garbage interface configuration in the CfgMgr.
+    // Make sure the config manager is clean and there is no hanging
+    // interface configuration.
     ASSERT_FALSE(test_config.socketOpen("eth0", AF_INET6));
     ASSERT_FALSE(test_config.socketOpen("eth1", AF_INET6));
 
@@ -4677,10 +4963,10 @@ TEST_F(Dhcp6ParserTest, selectedInterfaces) {
     extractConfig(config);
 
     ConstElementPtr status;
+    // Apply configuration.
     EXPECT_NO_THROW(status = Dhcpv6SrvTest::configure(srv_, json));
-
-    // returned value must be 1 (values error)
-    // as the pool does not belong to that subnet
+    ASSERT_TRUE(status);
+    // returned value must be 0 (configuration accepted)
     checkResult(status, 0);
 
     CfgMgr::instance().getStagingCfg()->getCfgIface()->openSockets(AF_INET6, 10000);
@@ -4690,16 +4976,17 @@ TEST_F(Dhcp6ParserTest, selectedInterfaces) {
     EXPECT_FALSE(test_config.socketOpen("eth1", AF_INET6));
 }
 
-// This test verifies that it is possible to configure the server to listen on
-// all interfaces.
+// This test verifies that it is possible to configure the server in such a way
+// that it listens on all interfaces.
 TEST_F(Dhcp6ParserTest, allInterfaces) {
     IfaceMgrTestConfig test_config(true);
 
+    // Make sure there is no old configuration.
     ASSERT_FALSE(test_config.socketOpen("eth0", AF_INET6));
     ASSERT_FALSE(test_config.socketOpen("eth1", AF_INET6));
 
     // This configuration specifies two interfaces on which server should listen
-    // but also includes '*'. This keyword switches server into the
+    // but it also includes asterisk. The asterisk switches server into the
     // mode when it listens on all interfaces regardless of what interface names
     // were specified in the "interfaces" parameter.
     string config = "{ \"interfaces-config\": {"
@@ -4715,13 +5002,53 @@ TEST_F(Dhcp6ParserTest, allInterfaces) {
     extractConfig(config);
 
     ConstElementPtr status;
+
+    // Apply configuration.
     EXPECT_NO_THROW(status = Dhcpv6SrvTest::configure(srv_, json));
+    ASSERT_TRUE(status);
     checkResult(status, 0);
 
     CfgMgr::instance().getStagingCfg()->getCfgIface()->openSockets(AF_INET6, 10000);
 
     // All interfaces should be now active.
+    ASSERT_TRUE(test_config.socketOpen("eth0", AF_INET6));
+    ASSERT_TRUE(test_config.socketOpen("eth1", AF_INET6));
+}
+
+// This test verifies that it is possible to select subset of interfaces
+// and addresses.
+TEST_F(Dhcp6ParserTest, selectedInterfacesAndAddresses) {
+    IfaceMgrTestConfig test_config(true);
+
+    ConstElementPtr x;
+    string config = "{ \"interfaces-config\": {"
+        "    \"interfaces\": [ \"eth0/2001:db8:1::1\", \"eth1/fe80::3a60:77ff:fed5:abcd\" ]"
+        "},"
+        "\"preferred-lifetime\": 3000,"
+        "\"rebind-timer\": 2000, "
+        "\"renew-timer\": 1000, "
+        "\"valid-lifetime\": 4000 }";
+
+    ConstElementPtr json;
+    ASSERT_NO_THROW(json = parseDHCP6(config));
+
+    ConstElementPtr status;
+
+    // Make sure the config manager is clean and there is no hanging
+    // interface configuration.
+    ASSERT_FALSE(test_config.socketOpen("eth0", AF_INET6));
+    ASSERT_FALSE(test_config.socketOpen("eth1", AF_INET6));
+
+    // Apply configuration.
+    EXPECT_NO_THROW(status = Dhcpv6SrvTest::configure(srv_, json));
+    ASSERT_TRUE(status);
+    checkResult(status, 0);
+
+    CfgMgr::instance().getStagingCfg()->getCfgIface()->openSockets(AF_INET6, 10000);
+
+    // An address on eth0 was selected
     EXPECT_TRUE(test_config.socketOpen("eth0", AF_INET6));
+    // The 2001:db8:1::1 address on eth1 was selected.
     EXPECT_TRUE(test_config.socketOpen("eth1", AF_INET6));
 }
 
@@ -4735,6 +5062,9 @@ TEST_F(Dhcp6ParserTest, subnetRelayInfo) {
         "\"subnet6\": [ { "
         "    \"id\": 1,"
         "    \"pools\": [ { \"pool\": \"2001:db8:1::1 - 2001:db8:1::ffff\" } ],"
+        "    \"renew-timer\": 1, "
+        "    \"rebind-timer\": 2, "
+        "    \"valid-lifetime\": 4,"
         "    \"relay\": { "
         "        \"ip-addresses\": [ \"2001:db8:1::abcd\" ]"
         "    },"
@@ -4752,8 +5082,8 @@ TEST_F(Dhcp6ParserTest, subnetRelayInfo) {
     // returned value should be 0 (configuration success)
     checkResult(status, 0);
 
-    Subnet6Ptr subnet = CfgMgr::instance().getStagingCfg()->getCfgSubnets6()->
-        selectSubnet(IOAddress("2001:db8:1::1"), classify_);
+    Subnet6Ptr subnet = CfgMgr::instance().getStagingCfg()->
+        getCfgSubnets6()->selectSubnet(IOAddress("2001:db8:1::1"), classify_);
     ASSERT_TRUE(subnet);
 
     EXPECT_TRUE(subnet->hasRelays());
@@ -4769,6 +5099,9 @@ TEST_F(Dhcp6ParserTest, subnetRelayInfoList) {
         "\"subnet6\": [ { "
         "    \"id\": 1,"
         "    \"pools\": [ { \"pool\": \"2001:db8:1::1 - 2001:db8:1::ffff\" } ],"
+        "    \"renew-timer\": 1, "
+        "    \"rebind-timer\": 2, "
+        "    \"valid-lifetime\": 4,"
         "    \"relay\": { "
         "        \"ip-addresses\": [ \"2001:db9::abcd\", \"2001:db9::abce\" ]"
         "    },"
@@ -4786,8 +5119,8 @@ TEST_F(Dhcp6ParserTest, subnetRelayInfoList) {
     // returned value should be 0 (configuration success)
     checkResult(status, 0);
 
-    Subnet6Ptr subnet = CfgMgr::instance().getStagingCfg()->getCfgSubnets6()->
-        selectSubnet(IOAddress("2001:db9::abcd"), classify_, true);
+    Subnet6Ptr subnet = CfgMgr::instance().getStagingCfg()->
+        getCfgSubnets6()->selectSubnet(IOAddress("2001:db9::abcd"), classify_, true);
     ASSERT_TRUE(subnet);
 
     EXPECT_TRUE(subnet->hasRelays());
@@ -4940,10 +5273,10 @@ TEST_F(Dhcp6ParserTest, classifyPools) {
     // everyone).
     ClientClasses classes;
     classes.insert("alpha");
-    EXPECT_TRUE (pools.at(0)->clientSupported(classes));
+    EXPECT_TRUE(pools.at(0)->clientSupported(classes));
     EXPECT_FALSE(pools.at(1)->clientSupported(classes));
     EXPECT_FALSE(pools.at(2)->clientSupported(classes));
-    EXPECT_TRUE (pools.at(3)->clientSupported(classes));
+    EXPECT_TRUE(pools.at(3)->clientSupported(classes));
 
     // Let's check if client belonging to beta class is supported in pool[1]
     // and not supported in any other pool  (except pool[3], which allows
@@ -4951,9 +5284,9 @@ TEST_F(Dhcp6ParserTest, classifyPools) {
     classes.clear();
     classes.insert("beta");
     EXPECT_FALSE(pools.at(0)->clientSupported(classes));
-    EXPECT_TRUE (pools.at(1)->clientSupported(classes));
+    EXPECT_TRUE(pools.at(1)->clientSupported(classes));
     EXPECT_FALSE(pools.at(2)->clientSupported(classes));
-    EXPECT_TRUE (pools.at(3)->clientSupported(classes));
+    EXPECT_TRUE(pools.at(3)->clientSupported(classes));
 
     // Let's check if client belonging to gamma class is supported in pool[2]
     // and not supported in any other pool  (except pool[3], which allows
@@ -4962,8 +5295,8 @@ TEST_F(Dhcp6ParserTest, classifyPools) {
     classes.insert("gamma");
     EXPECT_FALSE(pools.at(0)->clientSupported(classes));
     EXPECT_FALSE(pools.at(1)->clientSupported(classes));
-    EXPECT_TRUE (pools.at(2)->clientSupported(classes));
-    EXPECT_TRUE (pools.at(3)->clientSupported(classes));
+    EXPECT_TRUE(pools.at(2)->clientSupported(classes));
+    EXPECT_TRUE(pools.at(3)->clientSupported(classes));
 
     // Let's check if client belonging to some other class (not mentioned in
     // the config) is supported only in pool[3], which allows everyone.
@@ -4972,7 +5305,7 @@ TEST_F(Dhcp6ParserTest, classifyPools) {
     EXPECT_FALSE(pools.at(0)->clientSupported(classes));
     EXPECT_FALSE(pools.at(1)->clientSupported(classes));
     EXPECT_FALSE(pools.at(2)->clientSupported(classes));
-    EXPECT_TRUE (pools.at(3)->clientSupported(classes));
+    EXPECT_TRUE(pools.at(3)->clientSupported(classes));
 
     // Finally, let's check class-less client. He should be allowed only in
     // the last pool, which does not have any class restrictions.
@@ -4980,7 +5313,7 @@ TEST_F(Dhcp6ParserTest, classifyPools) {
     EXPECT_FALSE(pools.at(0)->clientSupported(classes));
     EXPECT_FALSE(pools.at(1)->clientSupported(classes));
     EXPECT_FALSE(pools.at(2)->clientSupported(classes));
-    EXPECT_TRUE (pools.at(3)->clientSupported(classes));
+    EXPECT_TRUE(pools.at(3)->clientSupported(classes));
 }
 
 // Goal of this test is to verify that multiple pdpools can be configured
@@ -5039,10 +5372,10 @@ TEST_F(Dhcp6ParserTest, classifyPdPools) {
     // everyone).
     ClientClasses classes;
     classes.insert("alpha");
-    EXPECT_TRUE (pools.at(0)->clientSupported(classes));
+    EXPECT_TRUE(pools.at(0)->clientSupported(classes));
     EXPECT_FALSE(pools.at(1)->clientSupported(classes));
     EXPECT_FALSE(pools.at(2)->clientSupported(classes));
-    EXPECT_TRUE (pools.at(3)->clientSupported(classes));
+    EXPECT_TRUE(pools.at(3)->clientSupported(classes));
 
     // Let's check if client belonging to beta class is supported in pool[1]
     // and not supported in any other pool  (except pool[3], which allows
@@ -5050,9 +5383,9 @@ TEST_F(Dhcp6ParserTest, classifyPdPools) {
     classes.clear();
     classes.insert("beta");
     EXPECT_FALSE(pools.at(0)->clientSupported(classes));
-    EXPECT_TRUE (pools.at(1)->clientSupported(classes));
+    EXPECT_TRUE(pools.at(1)->clientSupported(classes));
     EXPECT_FALSE(pools.at(2)->clientSupported(classes));
-    EXPECT_TRUE (pools.at(3)->clientSupported(classes));
+    EXPECT_TRUE(pools.at(3)->clientSupported(classes));
 
     // Let's check if client belonging to gamma class is supported in pool[2]
     // and not supported in any other pool  (except pool[3], which allows
@@ -5061,8 +5394,8 @@ TEST_F(Dhcp6ParserTest, classifyPdPools) {
     classes.insert("gamma");
     EXPECT_FALSE(pools.at(0)->clientSupported(classes));
     EXPECT_FALSE(pools.at(1)->clientSupported(classes));
-    EXPECT_TRUE (pools.at(2)->clientSupported(classes));
-    EXPECT_TRUE (pools.at(3)->clientSupported(classes));
+    EXPECT_TRUE(pools.at(2)->clientSupported(classes));
+    EXPECT_TRUE(pools.at(3)->clientSupported(classes));
 
     // Let's check if client belonging to some other class (not mentioned in
     // the config) is supported only in pool[3], which allows everyone.
@@ -5071,7 +5404,7 @@ TEST_F(Dhcp6ParserTest, classifyPdPools) {
     EXPECT_FALSE(pools.at(0)->clientSupported(classes));
     EXPECT_FALSE(pools.at(1)->clientSupported(classes));
     EXPECT_FALSE(pools.at(2)->clientSupported(classes));
-    EXPECT_TRUE (pools.at(3)->clientSupported(classes));
+    EXPECT_TRUE(pools.at(3)->clientSupported(classes));
 
     // Finally, let's check class-less client. He should be allowed only in
     // the last pool, which does not have any class restrictions.
@@ -5079,7 +5412,7 @@ TEST_F(Dhcp6ParserTest, classifyPdPools) {
     EXPECT_FALSE(pools.at(0)->clientSupported(classes));
     EXPECT_FALSE(pools.at(1)->clientSupported(classes));
     EXPECT_FALSE(pools.at(2)->clientSupported(classes));
-    EXPECT_TRUE (pools.at(3)->clientSupported(classes));
+    EXPECT_TRUE(pools.at(3)->clientSupported(classes));
 }
 
 // This test verifies that valid d2CliengConfig works correctly.
@@ -5476,6 +5809,11 @@ TEST_F(Dhcp6ParserTest, reservationWithOptionDefinition) {
     ConstHostPtr host = hosts_cfg->get6(234, Host::IDENT_DUID,
                                         &duid[0], duid.size());
     ASSERT_TRUE(host);
+    IPv6ResrvRange resrv = host->getIPv6Reservations(IPv6Resrv::TYPE_NA);
+    ASSERT_EQ(1, std::distance(resrv.first, resrv.second));
+    EXPECT_TRUE(reservationExists(IPv6Resrv(IPv6Resrv::TYPE_NA,
+                                            IOAddress("2001:db8:2::1234")),
+                                  resrv));
 
     // Check if the option has been parsed.
     OptionUint32Ptr opt_foo = retrieveOption<OptionUint32Ptr>(*host, "isc",
@@ -5510,7 +5848,10 @@ TEST_F(Dhcp6ParserTest, reservationBogus) {
         "\"preferred-lifetime\": 3000,"
         "\"valid-lifetime\": 4000 }";
 
-    ConstElementPtr json = parseJSON(config);
+    ConstElementPtr json;
+    ASSERT_NO_THROW(json = parseJSON(config));
+
+    CfgMgr::instance().clear();
 
     EXPECT_NO_THROW(x = Dhcpv6SrvTest::configure(srv_, json));
     checkResult(x, 1);
@@ -5572,7 +5913,7 @@ TEST_F(Dhcp6ParserTest, reservationBogus) {
         "\"preferred-lifetime\": 3000,"
         "\"valid-lifetime\": 4000 }";
 
-    json = parseDHCP6(config);
+    ASSERT_NO_THROW(json = parseDHCP6(config));
 
     // Remove existing configuration, if any.
     CfgMgr::instance().clear();
@@ -5820,7 +6161,6 @@ TEST_F(Dhcp6ParserTest, hostReservationPerSubnet) {
     EXPECT_TRUE(subnet->getReservationsGlobal());
     EXPECT_TRUE(subnet->getReservationsInSubnet());
     EXPECT_TRUE(subnet->getReservationsOutOfPool());
-
 }
 
 /// The goal of this test is to verify that Host Reservation flags can be
@@ -5878,6 +6218,10 @@ TEST_F(Dhcp6ParserTest, hostReservationGlobal) {
     Subnet6Ptr subnet;
     subnet = subnets->selectSubnet(IOAddress("2001:db8:1::1"));
     ASSERT_TRUE(subnet);
+    // Reset the fetch global function to staging (vs current) config.
+    subnet->setFetchGlobalsFn([]() -> ConstCfgGlobalsPtr {
+        return (CfgMgr::instance().getCurrentCfg()->getConfiguredGlobals());
+    });
     EXPECT_FALSE(subnet->getReservationsGlobal());
     EXPECT_TRUE(subnet->getReservationsInSubnet());
     EXPECT_FALSE(subnet->getReservationsOutOfPool());
@@ -5885,11 +6229,39 @@ TEST_F(Dhcp6ParserTest, hostReservationGlobal) {
     // Subnet 2
     subnet = subnets->selectSubnet(IOAddress("2001:db8:2::1"));
     ASSERT_TRUE(subnet);
+    // Reset the fetch global function to staging (vs current) config.
+    subnet->setFetchGlobalsFn([]() -> ConstCfgGlobalsPtr {
+        return (CfgMgr::instance().getCurrentCfg()->getConfiguredGlobals());
+    });
     EXPECT_FALSE(subnet->getReservationsGlobal());
     EXPECT_TRUE(subnet->getReservationsInSubnet());
     EXPECT_TRUE(subnet->getReservationsOutOfPool());
 }
 
+/// Check that the decline-probation-period has a default value when not
+/// specified.
+TEST_F(Dhcp6ParserTest, declineTimerDefault) {
+
+    string config = "{ " + genIfaceConfig() + ","
+        "\"subnet6\": [  ] "
+        "}";
+
+    ConstElementPtr json;
+    ASSERT_NO_THROW(json = parseDHCP6(config));
+    extractConfig(config);
+
+    ConstElementPtr status;
+    EXPECT_NO_THROW(status = Dhcpv6SrvTest::configure(srv_, json));
+
+    // returned value should be 0 (success)
+    checkResult(status, 0);
+
+    // The value of decline-probation-period must be equal to the
+    // default value (86400). The default value is defined in GLOBAL6_DEFAULTS in
+    // simple_parser6.cc.
+    EXPECT_EQ(86400, CfgMgr::instance().getStagingCfg()->getDeclinePeriod());
+}
+
 /// The goal of this test is to verify that configuration can include
 /// Relay Supplied options (specified as numbers).
 TEST_F(Dhcp6ParserTest, rsooNumbers) {
@@ -6084,29 +6456,6 @@ TEST_F(Dhcp6ParserTest, testDataDir) {
     EXPECT_NE(original_datadir, string(CfgMgr::instance().getDataDir()));
 }
 
-/// Check that the decline-probation-period value has a default value if not
-/// specified explicitly.
-TEST_F(Dhcp6ParserTest, declineTimerDefault) {
-
-    string config_txt = "{ " + genIfaceConfig() + ","
-        "\"subnet6\": [  ] "
-        "}";
-    ConstElementPtr config;
-    ASSERT_NO_THROW(config = parseDHCP6(config_txt));
-    extractConfig(config_txt);
-
-    ConstElementPtr status;
-    EXPECT_NO_THROW(status = Dhcpv6SrvTest::configure(srv_, config));
-
-    // returned value should be 0 (success)
-    checkResult(status, 0);
-
-    // The value of decline-probation-period must be equal to the
-    // default value (86400). The default value is defined in GLOBAL6_DEFAULTS in
-    // simple_parser6.cc.
-    EXPECT_EQ(86400, CfgMgr::instance().getStagingCfg()->getDeclinePeriod());
-}
-
 /// Check that the dhcp4o6-port default value has a default value if not
 /// specified explicitly.
 TEST_F(Dhcp6ParserTest, dhcp4o6portDefault) {
@@ -6132,7 +6481,7 @@ TEST_F(Dhcp6ParserTest, dhcp4o6portDefault) {
 
 /// Check that the decline-probation-period value can be set properly.
 TEST_F(Dhcp6ParserTest, declineTimer) {
-    string config = "{ " + genIfaceConfig() + "," +
+    string config = "{ " + genIfaceConfig() + ","
         "\"decline-probation-period\": 12345,"
         "\"subnet6\": [ ]"
         "}";
@@ -6155,12 +6504,13 @@ TEST_F(Dhcp6ParserTest, declineTimer) {
 
 /// Check that an incorrect decline-probation-period value will be caught.
 TEST_F(Dhcp6ParserTest, declineTimerError) {
-    string config = "{ " + genIfaceConfig() + "," +
+    string config = "{ " + genIfaceConfig() + ","
         "\"decline-probation-period\": \"soon\","
         "\"subnet6\": [ ]"
         "}";
 
-    ConstElementPtr json = parseJSON(config);
+    ConstElementPtr json;
+    ASSERT_NO_THROW(json = parseJSON(config));
 
     ConstElementPtr status;
     EXPECT_NO_THROW(status = Dhcpv6SrvTest::configure(srv_, json));
@@ -6179,7 +6529,7 @@ TEST_F(Dhcp6ParserTest, declineTimerError) {
 // specified.
 TEST_F(Dhcp6ParserTest, expiredLeasesProcessing) {
     // Create basic configuration with the expiration specific parameters.
-    string config = "{ " + genIfaceConfig() + "," +
+    string config = "{ " + genIfaceConfig() + ","
         "\"expired-leases-processing\": "
         "{"
         "    \"reclaim-timer-wait-time\": 20,"
@@ -6221,7 +6571,7 @@ TEST_F(Dhcp6ParserTest, expiredLeasesProcessing) {
 TEST_F(Dhcp6ParserTest, expiredLeasesProcessingError) {
     // Create basic configuration with the expiration specific parameters.
     // One of the parameters holds invalid value.
-    string config = "{ " + genIfaceConfig() + "," +
+    string config = "{ " + genIfaceConfig() + ","
         "\"expired-leases-processing\": "
         "{"
         "    \"reclaim-timer-wait-time\": -5,"
@@ -6252,31 +6602,160 @@ TEST_F(Dhcp6ParserTest, expiredLeasesProcessingError) {
 TEST_F(Dhcp6ParserTest, validClientClassDictionary) {
     string config = "{ " + genIfaceConfig() + ","
         "\"preferred-lifetime\": 3000, \n"
+        "\"valid-lifetime\": 4000, \n"
         "\"rebind-timer\": 2000,  \n"
         "\"renew-timer\": 1000,  \n"
         "\"client-classes\" : [ \n"
         "   { \n"
-        "       \"name\": \"one\" \n"
-        "   }, \n"
-        "   { \n"
-        "       \"name\": \"two\" \n"
+        "       \"name\": \"one\" \n"
+        "   }, \n"
+        "   { \n"
+        "       \"name\": \"two\" \n"
+        "   }, \n"
+        "   { \n"
+        "       \"name\": \"three\" \n"
+        "   } \n"
+        "], \n"
+        "\"subnet6\": [ {  \n"
+        "    \"id\": 1, \n"
+        "    \"pools\": [ { \"pool\": \"2001:db8:1::1 - 2001:db8:1::ffff\" } ], \n"
+        "    \"subnet\": \"2001:db8:1::/64\"  \n"
+        " } ] \n"
+        "} \n";
+
+    ConstElementPtr json;
+    ASSERT_NO_THROW(json = parseDHCP6(config));
+    extractConfig(config);
+
+    ConstElementPtr status;
+    EXPECT_NO_THROW(status = Dhcpv6SrvTest::configure(srv_, json));
+    ASSERT_TRUE(status);
+    checkResult(status, 0);
+
+    // We check staging config because CfgMgr::commit hasn't been executed.
+    ClientClassDictionaryPtr dictionary;
+    dictionary = CfgMgr::instance().getStagingCfg()->getClientClassDictionary();
+    ASSERT_TRUE(dictionary);
+    EXPECT_EQ(3, dictionary->getClasses()->size());
+
+    // Execute the commit
+    ASSERT_NO_THROW(CfgMgr::instance().commit());
+
+    // Verify that after commit, the current config has the correct dictionary
+    dictionary = CfgMgr::instance().getCurrentCfg()->getClientClassDictionary();
+    ASSERT_TRUE(dictionary);
+    EXPECT_EQ(3, dictionary->getClasses()->size());
+}
+
+// Verifies that a class list containing an invalid
+// class definition causes a configuration error.
+TEST_F(Dhcp6ParserTest, invalidClientClassDictionary) {
+    string config = "{ " + genIfaceConfig() + ","
+        "\"valid-lifetime\": 4000, \n"
+        "\"rebind-timer\": 2000, \n"
+        "\"renew-timer\": 1000, \n"
+        "\"client-classes\" : [ \n"
+        "   { \n"
+        "       \"name\": \"one\", \n"
+        "       \"bogus\": \"bad\" \n"
+        "   } \n"
+        "], \n"
+        "\"subnet6\": [ {  \n"
+        "    \"id\": 1, \n"
+        "    \"pools\": [ { \"pool\":  \"2001:db8::1 - 2001:db8::ffff\" } ], \n"
+        "    \"subnet\": \"2001:db8::/64\"  \n"
+        " } ] \n"
+        "} \n";
+
+    EXPECT_THROW(parseDHCP6(config), Dhcp6ParseError);
+}
+
+// Verifies that simple list of valid classes parses and
+// is staged for commit.
+TEST_F(Dhcp6ParserTest, clientClassValidLifetime) {
+    string config = "{ " + genIfaceConfig() + ","
+        "\"client-classes\" : [ \n"
+        "   { \n"
+        "       \"name\": \"one\", \n"
+        "       \"min-valid-lifetime\": 1000, \n"
+        "       \"valid-lifetime\": 2000, \n"
+        "       \"max-valid-lifetime\": 3000 \n"
+        "   }, \n"
+        "   { \n"
+        "       \"name\": \"two\" \n"
+        "   } \n"
+        "], \n"
+        "\"subnet6\": [ {  \n"
+        "    \"id\": 1, \n"
+        "    \"pools\": [ { \"pool\":  \"2001:db8::1 - 2001:db8::ffff\" } ], \n"
+        "    \"subnet\": \"2001:db8::/64\"  \n"
+        " } ] \n"
+        "} \n";
+
+    ConstElementPtr json;
+    ASSERT_NO_THROW_LOG(json = parseDHCP6(config));
+    extractConfig(config);
+
+    ConstElementPtr status;
+    ASSERT_NO_THROW_LOG(status = Dhcpv6SrvTest::configure(srv_, json));
+    ASSERT_TRUE(status);
+    checkResult(status, 0);
+
+    // We check staging config because CfgMgr::commit hasn't been executed.
+    ClientClassDictionaryPtr dictionary;
+    dictionary = CfgMgr::instance().getStagingCfg()->getClientClassDictionary();
+    ASSERT_TRUE(dictionary);
+    EXPECT_EQ(2, dictionary->getClasses()->size());
+
+    // Execute the commit
+    ASSERT_NO_THROW(CfgMgr::instance().commit());
+
+    // Verify that after commit, the current config has the correct dictionary
+    dictionary = CfgMgr::instance().getCurrentCfg()->getClientClassDictionary();
+    ASSERT_TRUE(dictionary);
+    EXPECT_EQ(2, dictionary->getClasses()->size());
+
+    ClientClassDefPtr class_def = dictionary->findClass("one");
+    ASSERT_TRUE(class_def);
+    EXPECT_EQ(class_def->getValid().getMin(), 1000);
+    EXPECT_EQ(class_def->getValid().get(), 2000);
+    EXPECT_EQ(class_def->getValid().getMax(), 3000);
+
+    class_def = dictionary->findClass("two");
+    ASSERT_TRUE(class_def);
+    EXPECT_TRUE(class_def->getValid().unspecified());
+}
+
+// Verifies that simple list of valid template classes parses and
+// is staged for commit.
+TEST_F(Dhcp6ParserTest, templateClientClassValidLifetime) {
+    string config = "{ " + genIfaceConfig() + ","
+        "\"client-classes\" : [ \n"
+        "   { \n"
+        "       \"name\": \"one\", \n"
+        "       \"min-valid-lifetime\": 1000, \n"
+        "       \"valid-lifetime\": 2000, \n"
+        "       \"max-valid-lifetime\": 3000, \n"
+        "       \"template-test\": \"''\" \n"
         "   }, \n"
         "   { \n"
-        "       \"name\": \"three\" \n"
+        "       \"name\": \"two\", \n"
+        "       \"template-test\": \"''\" \n"
         "   } \n"
         "], \n"
         "\"subnet6\": [ {  \n"
         "    \"id\": 1, \n"
-        "    \"pools\": [ { \"pool\": \"2001:db8:1::1 - 2001:db8:1::ffff\" } ], \n"
-        "    \"subnet\": \"2001:db8:1::/64\" } ], \n"
-        "\"valid-lifetime\": 4000 } \n";
+        "    \"pools\": [ { \"pool\":  \"2001:db8::1 - 2001:db8::ffff\" } ], \n"
+        "    \"subnet\": \"2001:db8::/64\"  \n"
+        " } ] \n"
+        "} \n";
 
     ConstElementPtr json;
-    ASSERT_NO_THROW(json = parseDHCP6(config));
+    ASSERT_NO_THROW_LOG(json = parseDHCP6(config));
     extractConfig(config);
 
     ConstElementPtr status;
-    EXPECT_NO_THROW(status = Dhcpv6SrvTest::configure(srv_, json));
+    ASSERT_NO_THROW_LOG(status = Dhcpv6SrvTest::configure(srv_, json));
     ASSERT_TRUE(status);
     checkResult(status, 0);
 
@@ -6284,7 +6763,7 @@ TEST_F(Dhcp6ParserTest, validClientClassDictionary) {
     ClientClassDictionaryPtr dictionary;
     dictionary = CfgMgr::instance().getStagingCfg()->getClientClassDictionary();
     ASSERT_TRUE(dictionary);
-    EXPECT_EQ(3, dictionary->getClasses()->size());
+    EXPECT_EQ(2, dictionary->getClasses()->size());
 
     // Execute the commit
     ASSERT_NO_THROW(CfgMgr::instance().commit());
@@ -6292,30 +6771,19 @@ TEST_F(Dhcp6ParserTest, validClientClassDictionary) {
     // Verify that after commit, the current config has the correct dictionary
     dictionary = CfgMgr::instance().getCurrentCfg()->getClientClassDictionary();
     ASSERT_TRUE(dictionary);
-    EXPECT_EQ(3, dictionary->getClasses()->size());
-}
+    EXPECT_EQ(2, dictionary->getClasses()->size());
 
-// Verifies that a class list containing an invalid
-// class definition causes a configuration error.
-TEST_F(Dhcp6ParserTest, invalidClientClassDictionary) {
-    string config = "{ " + genIfaceConfig() + "," +
-        "\"valid-lifetime\": 4000, \n"
-        "\"rebind-timer\": 2000, \n"
-        "\"renew-timer\": 1000, \n"
-        "\"client-classes\" : [ \n"
-        "   { \n"
-        "       \"name\": \"one\", \n"
-        "       \"bogus\": \"bad\" \n"
-        "   } \n"
-        "], \n"
-        "\"subnet6\": [ {  \n"
-        "    \"id\": 1, \n"
-        "    \"pools\": [ { \"pool\":  \"2001:db8::1 - 2001:db8::ffff\" } ], \n"
-        "    \"subnet\": \"2001:db8::/64\"  \n"
-        " } ] \n"
-        "} \n";
+    ClientClassDefPtr class_def = dictionary->findClass("one");
+    ASSERT_TRUE(class_def);
+    ASSERT_TRUE(dynamic_cast<TemplateClientClassDef*>(class_def.get()));
+    EXPECT_EQ(class_def->getValid().getMin(), 1000);
+    EXPECT_EQ(class_def->getValid().get(), 2000);
+    EXPECT_EQ(class_def->getValid().getMax(), 3000);
 
-    EXPECT_THROW(parseDHCP6(config), Dhcp6ParseError);
+    class_def = dictionary->findClass("two");
+    ASSERT_TRUE(class_def);
+    ASSERT_TRUE(dynamic_cast<TemplateClientClassDef*>(class_def.get()));
+    EXPECT_TRUE(class_def->getValid().unspecified());
 }
 
 // Test verifies that regular configuration does not provide any user context
@@ -6383,6 +6851,46 @@ TEST_F(Dhcp6ParserTest, poolUserContextlw4over6) {
     EXPECT_EQ(56L, int_value);
 }
 
+// Test verifies that it's possible to specify parameters in the user context
+// in the address pool.
+TEST_F(Dhcp6ParserTest, poolUserContextData) {
+    extractConfig(PARSER_CONFIGS[2]);
+    PoolPtr pool;
+    getPool(string(PARSER_CONFIGS[2]), 0, 0, Lease::TYPE_NA, pool);
+    ASSERT_TRUE(pool);
+    ConstElementPtr ctx = pool->getContext();
+    ASSERT_TRUE(ctx);
+
+    // The context should be of type map and contain 4 parameters.
+    EXPECT_EQ(Element::map, ctx->getType());
+    EXPECT_EQ(4, ctx->size());
+    ConstElementPtr ratio   = ctx->get("lw4over6-sharing-ratio");
+    ConstElementPtr v4pool  = ctx->get("lw4over6-v4-pool");
+    ConstElementPtr exclude = ctx->get("lw4over6-sysports-exclude");
+    ConstElementPtr v6len   = ctx->get("lw4over6-bind-prefix-len");
+
+    ASSERT_TRUE(ratio);
+    ASSERT_EQ(Element::integer, ratio->getType());
+    int64_t int_value;
+    EXPECT_NO_THROW(ratio->getValue(int_value));
+    EXPECT_EQ(64L, int_value);
+
+    ASSERT_TRUE(v4pool);
+    ASSERT_EQ(Element::string, v4pool->getType());
+    EXPECT_EQ("192.0.2.0/24", v4pool->stringValue());
+
+    ASSERT_TRUE(exclude);
+    bool bool_value;
+    ASSERT_EQ(Element::boolean, exclude->getType());
+    EXPECT_NO_THROW(exclude->getValue(bool_value));
+    EXPECT_EQ(true, bool_value);
+
+    ASSERT_TRUE(v6len);
+    ASSERT_EQ(Element::integer, v6len->getType());
+    EXPECT_NO_THROW(v6len->getValue(int_value));
+    EXPECT_EQ(56L, int_value);
+}
+
 // Test verifies that it's possible to specify parameters in the user context
 // in the min-max address pool.
 TEST_F(Dhcp6ParserTest, poolMinMaxUserContext) {
@@ -6503,21 +7011,10 @@ TEST_F(Dhcp6ParserTest, invalidPoolRange) {
         " } ] \n"
         "} \n";
 
-    ConstElementPtr json;
-    ASSERT_NO_THROW(json = parseDHCP6(config, true));
-
-    ConstElementPtr status;
-    EXPECT_NO_THROW(status = Dhcpv6SrvTest::configure(srv_, json));
-    ASSERT_TRUE(status);
-    int rcode;
-    ConstElementPtr comment = parseAnswerText(rcode, status);
-    string text;
-    ASSERT_NO_THROW(text = comment->stringValue());
-
-    EXPECT_EQ(1, rcode);
     string expected = "Failed to create pool defined by: "
         "2001:db8::-200:1db8::ffff (<string>:8:26)";
-    EXPECT_EQ(expected, text);
+
+    configure(config, CONTROL_RESULT_ERROR, expected);
 }
 
 // Test verifies the error message for an outside subnet pool range
@@ -6535,23 +7032,12 @@ TEST_F(Dhcp6ParserTest, outsideSubnetPool) {
         " } ] \n"
         "} \n";
 
-    ConstElementPtr json;
-    ASSERT_NO_THROW(json = parseDHCP6(config, true));
-
-    ConstElementPtr status;
-    EXPECT_NO_THROW(status = Dhcpv6SrvTest::configure(srv_, json));
-    ASSERT_TRUE(status);
-    int rcode;
-    ConstElementPtr comment = parseAnswerText(rcode, status);
-    string text;
-    ASSERT_NO_THROW(text = comment->stringValue());
-
-    EXPECT_EQ(1, rcode);
     string expected = "subnet configuration failed: "
         "a pool of type IA_NA, with the following address range: "
         "2001:db8::-2001:db8::ffff does not match the prefix of a subnet: "
         "2001:dc8::/32 to which it is being added (<string>:6:14)";
-    EXPECT_EQ(expected, text);
+
+    configure(config, CONTROL_RESULT_ERROR, expected);
 }
 
 // Test verifies that empty shared networks are accepted.
@@ -6562,6 +7048,7 @@ TEST_F(Dhcp6ParserTest, sharedNetworksEmpty) {
         "\"renew-timer\": 1000, \n"
         "\"subnet6\": [ {  \n"
         "    \"id\": 1, \n"
+        "    \"pools\": [ { \"pool\": \"2001:db8:: - 2001:db8::ffff\" } ], \n"
         "    \"subnet\": \"2001:db8::/48\"  \n"
         " } ],\n"
         "\"shared-networks\": [ ]\n"
@@ -6579,6 +7066,7 @@ TEST_F(Dhcp6ParserTest, sharedNetworksNoName) {
         "\"renew-timer\": 1000, \n"
         "\"subnet6\": [ {  \n"
         "    \"id\": 1, \n"
+        "    \"pools\": [ { \"pool\": \"2001:db8:: - 2001:db8::ffff\" } ], \n"
         "    \"subnet\": \"2001:db8::/48\"  \n"
         " } ],\n"
         "\"shared-networks\": [ { } ]\n"
@@ -6595,6 +7083,7 @@ TEST_F(Dhcp6ParserTest, sharedNetworksEmptyName) {
         "\"renew-timer\": 1000, \n"
         "\"subnet6\": [ {  \n"
         "    \"id\": 1, \n"
+        "    \"pools\": [ { \"pool\": \"2001:db8:: - 2001:db8::ffff\" } ], \n"
         "    \"subnet\": \"2001:db8::/48\"  \n"
         " } ],\n"
         "\"shared-networks\": [ { \"name\": \"\" } ]\n"
@@ -6610,8 +7099,8 @@ TEST_F(Dhcp6ParserTest, sharedNetworksName) {
     string config = "{\n"
         "\"subnet6\": [ {  \n"
         "    \"id\": 1, \n"
-        "    \"subnet\": \"2001:db8::/48\",\n"
-        "    \"pools\": [ { \"pool\": \"2001:db8::1 - 2001:db8::ffff\" } ]\n"
+        "    \"pools\": [ { \"pool\": \"2001:db8:: - 2001:db8::ffff\" } ], \n"
+        "    \"subnet\": \"2001:db8::/48\"\n"
         " } ],\n"
         "\"shared-networks\": [ { \"name\": \"foo\" } ]\n"
         "} \n";
@@ -6643,7 +7132,7 @@ TEST_F(Dhcp6ParserTest, sharedNetworks1subnet) {
         "\"shared-networks\": [ {\n"
         "    \"name\": \"foo\"\n,"
         "    \"subnet6\": [ { \n"
-        "        \"id\": 1, \n"
+        "        \"id\": 1,\n"
         "        \"subnet\": \"2001:db8::/48\",\n"
         "        \"pools\": [ { \"pool\": \"2001:db8::1 - 2001:db8::ffff\" } ]\n"
         "    } ]\n"
@@ -6691,24 +7180,24 @@ TEST_F(Dhcp6ParserTest, sharedNetworks1subnet) {
 // - that overridden parameters only affect one subnet and not others
 TEST_F(Dhcp6ParserTest, sharedNetworks3subnets) {
     string config = "{\n"
+        "\"valid-lifetime\": 4000, \n"
+        "\"min-valid-lifetime\": 3000, \n"
+        "\"max-valid-lifetime\": 5000, \n"
         "\"renew-timer\": 1000, \n"
         "\"rebind-timer\": 2000, \n"
         "\"preferred-lifetime\": 3000, \n"
         "\"min-preferred-lifetime\": 2000, \n"
         "\"max-preferred-lifetime\": 4000, \n"
-        "\"valid-lifetime\": 4000, \n"
-        "\"min-valid-lifetime\": 3000, \n"
-        "\"max-valid-lifetime\": 5000, \n"
         "\"shared-networks\": [ {\n"
         "    \"name\": \"foo\"\n,"
         "    \"subnet6\": [\n"
         "    { \n"
-        "        \"id\": 1, \n"
+        "        \"id\": 1,\n"
         "        \"subnet\": \"2001:db1::/48\",\n"
         "        \"pools\": [ { \"pool\": \"2001:db1::/64\" } ]\n"
         "    },\n"
         "    { \n"
-        "        \"id\": 2, \n"
+        "        \"id\": 2,\n"
         "        \"subnet\": \"2001:db2::/48\",\n"
         "        \"pools\": [ { \"pool\": \"2001:db2::/64\" } ],\n"
         "        \"renew-timer\": 2,\n"
@@ -6721,7 +7210,7 @@ TEST_F(Dhcp6ParserTest, sharedNetworks3subnets) {
         "        \"max-valid-lifetime\": 3333\n"
         "    },\n"
         "    { \n"
-        "        \"id\": 3, \n"
+        "        \"id\": 3,\n"
         "        \"subnet\": \"2001:db3::/48\",\n"
         "        \"pools\": [ { \"pool\": \"2001:db3::/64\" } ]\n"
         "    }\n"
@@ -6797,7 +7286,7 @@ TEST_F(Dhcp6ParserTest, sharedNetworksDerive) {
     Option iface_id2(Option::V6, D6O_INTERFACE_ID, buffer2);
 
     string config = "{\n"
-        "\"renew-timer\": 1, \n"
+        "\"renew-timer\": 1, \n" // global values here
         "\"rebind-timer\": 2, \n"
         "\"preferred-lifetime\": 3,\n"
         "\"min-preferred-lifetime\": 2,\n"
@@ -6806,7 +7295,7 @@ TEST_F(Dhcp6ParserTest, sharedNetworksDerive) {
         "\"min-valid-lifetime\": 3, \n"
         "\"max-valid-lifetime\": 5, \n"
         "\"shared-networks\": [ {\n"
-        "    \"name\": \"foo\"\n,"
+        "    \"name\": \"foo\"\n," // shared network values here
         "    \"renew-timer\": 10,\n"
         "    \"rebind-timer\": 20, \n"
         "    \"preferred-lifetime\": 30,\n"
@@ -6825,12 +7314,12 @@ TEST_F(Dhcp6ParserTest, sharedNetworksDerive) {
         "    \"reservations-in-subnet\": false,\n"
         "    \"subnet6\": [\n"
         "    { \n"
-        "        \"id\": 1, \n"
+        "        \"id\": 1,\n"
         "        \"subnet\": \"2001:db1::/48\",\n"
         "        \"pools\": [ { \"pool\": \"2001:db1::/64\" } ]\n"
         "    },\n"
         "    { \n"
-        "        \"id\": 2, \n"
+        "        \"id\": 2,\n"
         "        \"subnet\": \"2001:db2::/48\",\n"
         "        \"pools\": [ { \"pool\": \"2001:db2::/64\" } ],\n"
         "        \"renew-timer\": 100\n,"
@@ -6856,12 +7345,12 @@ TEST_F(Dhcp6ParserTest, sharedNetworksDerive) {
         "    \"name\": \"bar\",\n"
         "    \"subnet6\": [\n"
         "    {\n"
-        "        \"id\": 3, \n"
+        "        \"id\": 3,\n"
         "        \"subnet\": \"2001:db3::/48\",\n"
         "        \"pools\": [ { \"pool\": \"2001:db3::/64\" } ]\n"
         "    }\n"
         "    ]\n"
-        "} ]\n"
+        " } ]\n"
         "} \n";
 
     configure(config, CONTROL_RESULT_SUCCESS, "");
@@ -6880,6 +7369,7 @@ TEST_F(Dhcp6ParserTest, sharedNetworksDerive) {
     SharedNetwork6Ptr net = nets->at(0);
     ASSERT_TRUE(net);
 
+    // The first shared network has two subnets.
     const Subnet6SimpleCollection* subs = net->getAllSubnets();
     ASSERT_TRUE(subs);
     EXPECT_EQ(2, subs->size());
@@ -6924,6 +7414,7 @@ TEST_F(Dhcp6ParserTest, sharedNetworksDerive) {
     EXPECT_EQ(1, subs->size());
 
     // This subnet should derive its renew-timer from global scope.
+    // All other parameters should have default values.
     s = checkSubnet(*subs, "2001:db3::/48", 1, 2, 3, 4, 2, 4, 3, 5);
     EXPECT_FALSE(s->getInterfaceId());
     EXPECT_FALSE(s->hasRelays());
@@ -7061,18 +7552,25 @@ TEST_F(Dhcp6ParserTest, sharedNetworksInterfacesMixed) {
 // This test checks if client-class is derived properly.
 TEST_F(Dhcp6ParserTest, sharedNetworksDeriveClientClass) {
 
+    // This config is structured in a way that the first shared network has
+    // client-class defined. This should in general be inherited by subnets, but
+    // it's also possible to override the values on subnet level.
     string config = "{\n"
+        "\"renew-timer\": 1, \n" // global values here
+        "\"rebind-timer\": 2, \n"
+        "\"preferred-lifetime\": 3,\n"
+        "\"valid-lifetime\": 4, \n"
         "\"shared-networks\": [ {\n"
-        "    \"name\": \"foo\"\n,"
+        "    \"name\": \"foo\"\n," // shared network values here
         "    \"client-class\": \"alpha\",\n"
         "    \"subnet6\": [\n"
         "    { \n"
-        "        \"id\": 1, \n"
+        "        \"id\": 1,\n"
         "        \"subnet\": \"2001:db1::/48\",\n"
         "        \"pools\": [ { \"pool\": \"2001:db1::/64\" } ]\n"
         "    },\n"
         "    { \n"
-        "        \"id\": 2, \n"
+        "        \"id\": 2,\n"
         "        \"subnet\": \"2001:db2::/48\",\n"
         "        \"pools\": [ { \"pool\": \"2001:db2::/64\" } ],\n"
         "        \"client-class\": \"beta\"\n"
@@ -7083,12 +7581,12 @@ TEST_F(Dhcp6ParserTest, sharedNetworksDeriveClientClass) {
         "    \"name\": \"bar\",\n"
         "    \"subnet6\": [\n"
         "    {\n"
-        "        \"id\": 3, \n"
+        "        \"id\": 3,\n"
         "        \"subnet\": \"2001:db3::/48\",\n"
         "        \"pools\": [ { \"pool\": \"2001:db3::/64\" } ]\n"
         "    }\n"
         "    ]\n"
-        "} ]\n"
+        " } ]\n"
         "} \n";
 
     configure(config, CONTROL_RESULT_SUCCESS, "");
@@ -7106,21 +7604,23 @@ TEST_F(Dhcp6ParserTest, sharedNetworksDeriveClientClass) {
     // Let's check the first one.
     SharedNetwork6Ptr net = nets->at(0);
     ASSERT_TRUE(net);
+
     EXPECT_EQ("alpha", net->getClientClass().get());
 
+    // The first shared network has two subnets.
     const Subnet6SimpleCollection* subs = net->getAllSubnets();
     ASSERT_TRUE(subs);
     EXPECT_EQ(2, subs->size());
 
     // For the first subnet, the client-class should be inherited from
     // shared-network level.
-    Subnet6Ptr s = checkSubnet(*subs, "2001:db1::/48", 0, 0, 0, 7200);
+    Subnet6Ptr s = checkSubnet(*subs, "2001:db1::/48", 1, 2, 3, 4);
     ASSERT_TRUE(s);
     EXPECT_EQ("alpha", s->getClientClass().get());
 
     // For the second subnet, the values are overridden on subnet level.
     // The value should not be inherited.
-    s = checkSubnet(*subs, "2001:db2::/48", 0, 0, 0, 7200);
+    s = checkSubnet(*subs, "2001:db2::/48", 1, 2, 3, 4);
     ASSERT_TRUE(s);
     EXPECT_EQ("beta", s->getClientClass().get()); // beta defined on subnet level
 
@@ -7135,7 +7635,7 @@ TEST_F(Dhcp6ParserTest, sharedNetworksDeriveClientClass) {
     EXPECT_EQ(1, subs->size());
 
     // This subnet should derive its renew-timer from global scope.
-    s = checkSubnet(*subs, "2001:db3::/48", 0, 0, 0, 7200);
+    s = checkSubnet(*subs, "2001:db3::/48", 1, 2, 3, 4);
     EXPECT_TRUE(s->getClientClass().empty());
 }
 
@@ -7257,7 +7757,7 @@ TEST_F(Dhcp6ParserTest, hostsDatabases) {
     ASSERT_EQ(2, hal.size());
     // Keywords are in alphabetical order
     EXPECT_EQ("name=keatest1 password=keatest type=mysql user=keatest", hal.front());
-    EXPECT_EQ("name=keatest2 password=keatest type=mysql user=keatest", hal.back());
+    EXPECT_EQ("name=keatest2 password=keatest retry-on-startup=true type=mysql user=keatest", hal.back());
 }
 
 // This test checks comments. Please keep it last.
@@ -7403,6 +7903,8 @@ TEST_F(Dhcp6ParserTest, comments) {
     ASSERT_EQ(1, subs->size());
     Subnet6Ptr sub = *subs->begin();
     ASSERT_TRUE(sub);
+    EXPECT_EQ(100, sub->getID());
+    EXPECT_EQ("2001:db1::/48", sub->toText());
 
     // Check subnet user context.
     ConstElementPtr ctx_sub = sub->getContext();
@@ -7410,8 +7912,6 @@ TEST_F(Dhcp6ParserTest, comments) {
     ASSERT_EQ(1, ctx_sub->size());
     ASSERT_TRUE(ctx_sub->get("comment"));
     EXPECT_EQ("\"A subnet\"", ctx_sub->get("comment")->str());
-    EXPECT_EQ(100, sub->getID());
-    EXPECT_EQ("2001:db1::/48", sub->toText());
 
     // The subnet has a pool.
     const PoolCollection& pools = sub->getPools(Lease::TYPE_NA);
@@ -7551,7 +8051,6 @@ TEST_F(Dhcp6ParserTest, globalReservations) {
         "\"valid-lifetime\": 4000 }\n";
 
     ConstElementPtr json;
-    (json = parseDHCP6(config));
     ASSERT_NO_THROW(json = parseDHCP6(config));
     extractConfig(config);
 
@@ -7577,6 +8076,7 @@ TEST_F(Dhcp6ParserTest, globalReservations) {
     for (unsigned int i = 1; i < 7; ++i) {
         hwaddr.push_back(static_cast<uint8_t>(i));
     }
+
     // Retrieve the reservation and sanity check the address reserved.
     ConstHostPtr host = hosts_cfg->get6(SUBNET_ID_GLOBAL, Host::IDENT_HWADDR,
                                         &hwaddr[0], hwaddr.size());
@@ -7586,10 +8086,12 @@ TEST_F(Dhcp6ParserTest, globalReservations) {
     EXPECT_TRUE(reservationExists(IPv6Resrv(IPv6Resrv::TYPE_NA,
                                             IOAddress("2001:db8:2::abcd")),
                                   resrv));
+
     // This reservation should be solely assigned to the subnet 234,
     // and not to other two.
     EXPECT_FALSE(hosts_cfg->get6(123, Host::IDENT_HWADDR,
                                  &hwaddr[0], hwaddr.size()));
+
     EXPECT_FALSE(hosts_cfg->get6(542, Host::IDENT_HWADDR,
                                  &hwaddr[0], hwaddr.size()));
     // Check that options are assigned correctly.
@@ -7609,6 +8111,8 @@ TEST_F(Dhcp6ParserTest, globalReservations) {
     for (unsigned int i = 1; i < 0xb; ++i) {
         duid.push_back(static_cast<uint8_t>(i));
     }
+
+    // Retrieve the global reservation and sanity check the  hostname reserved.
     host = hosts_cfg->get6(SUBNET_ID_GLOBAL, Host::IDENT_DUID, &duid[0], duid.size());
     ASSERT_TRUE(host);
     resrv = host->getIPv6Reservations(IPv6Resrv::TYPE_NA);
@@ -7616,8 +8120,7 @@ TEST_F(Dhcp6ParserTest, globalReservations) {
     EXPECT_TRUE(reservationExists(IPv6Resrv(IPv6Resrv::TYPE_NA,
                                             IOAddress("2001:db8:2::1234")),
                                   resrv));
-    EXPECT_FALSE(hosts_cfg->get6(123, Host::IDENT_DUID, &duid[0], duid.size()));
-    EXPECT_FALSE(hosts_cfg->get6(542, Host::IDENT_DUID, &duid[0], duid.size()));
+
     // Check that options are assigned correctly.
     opt_dns = retrieveOption<Option6AddrLstPtr>(*host, D6O_NAME_SERVERS);
     ASSERT_TRUE(opt_dns);
@@ -7627,6 +8130,29 @@ TEST_F(Dhcp6ParserTest, globalReservations) {
     opt_prf = retrieveOption<OptionUint8Ptr>(*host, D6O_PREFERENCE);
     ASSERT_TRUE(opt_prf);
     EXPECT_EQ(11, static_cast<int>(opt_prf->getValue()));
+
+    // This reservation should be global solely and not assigned to
+    // either subnet
+    EXPECT_FALSE(hosts_cfg->get6(123, Host::IDENT_DUID, &duid[0], duid.size()));
+    EXPECT_FALSE(hosts_cfg->get6(542, Host::IDENT_DUID, &duid[0], duid.size()));
+}
+
+// Rather than disable these tests they are compiled out.  This avoids them
+// reporting as disabled and thereby drawing attention to them.
+// This test verifies that configuration control with unsupported type fails
+TEST_F(Dhcp6ParserTest, configControlInfoNoFactory) {
+    string config = PARSER_CONFIGS[8];
+
+    // Unregister "mysql" and ignore the return value.
+    static_cast<void>(TestConfigBackendDHCPv6::
+                      unregisterBackendType(ConfigBackendDHCPv6Mgr::instance(),
+                                            "mysql"));
+
+    // Should fail because "type=mysql" has no factories.
+    configure(config, CONTROL_RESULT_ERROR,
+              "during update from config backend database: "
+              "The type of the configuration backend: "
+              "'mysql' is not supported");
 }
 
 // This test verifies that configuration control info gets populated.
@@ -7655,7 +8181,7 @@ TEST_F(Dhcp6ParserTest, configControlInfo) {
     //  alphabetical order).
     EXPECT_EQ("name=keatest1 password=keatest type=mysql user=keatest",
               dblist.front().getAccessString());
-    EXPECT_EQ("name=keatest2 password=keatest type=mysql user=keatest",
+    EXPECT_EQ("name=keatest2 password=keatest retry-on-startup=true type=mysql user=keatest",
               dblist.back().getAccessString());
 
     // Verify that the config-fetch-wait-time is correct.
@@ -7666,18 +8192,18 @@ TEST_F(Dhcp6ParserTest, configControlInfo) {
 // Check whether it is possible to configure server-tag
 TEST_F(Dhcp6ParserTest, serverTag) {
     // Config without server-tag
-    string config_no_tag = "{ " + genIfaceConfig() + "," +
+    string config_no_tag = "{ " + genIfaceConfig() + ","
         "\"subnet6\": [  ] "
         "}";
 
     // Config with server-tag
-    string config_tag = "{ " + genIfaceConfig() + "," +
+    string config_tag = "{ " + genIfaceConfig() + ","
         "\"server-tag\": \"boo\", "
         "\"subnet6\": [  ] "
         "}";
 
     // Config with an invalid server-tag
-    string bad_tag = "{ " + genIfaceConfig() + "," +
+    string bad_tag = "{ " + genIfaceConfig() + ","
         "\"server-tag\": 777, "
         "\"subnet6\": [  ] "
         "}";
@@ -7707,6 +8233,7 @@ TEST_F(Dhcp6ParserTest, dhcpQueueControl) {
         std::string json_;
         std::string mt_json_;
     };
+
     std::vector<Scenario> scenarios = {
         {
         "no entry",
@@ -7892,87 +8419,175 @@ TEST_F(Dhcp6ParserTest, dhcpQueueControlInvalid) {
     }
 }
 
-// Verifies the value of store-extended-info for subnets when there
-// is a global value defined.
-TEST_F(Dhcp6ParserTest, storeExtendedInfoGlobal) {
+// Checks inheritence of calculate-tee-times, t1-percent, t2-percent
+TEST_F(Dhcp6ParserTest, calculateTeeTimesInheritence) {
+    // Configure the server. This should succeed.
+    string config =
+        "{ \n"
+        "    \"interfaces-config\": { \n"
+        "        \"interfaces\": [\"*\" ] \n"
+        "    }, \n"
+        "    \"valid-lifetime\": 4000, \n"
+        "    \"preferred-lifetime\": 3000,"
+        "    \"shared-networks\": [ { \n"
+        "        \"name\": \"foo\", \n"
+        "       \"calculate-tee-times\": true, \n"
+        "       \"t1-percent\": .4, \n"
+        "       \"t2-percent\": .75,\n"
+        "        \"subnet6\": ["
+        "        { "
+        "            \"id\": 100,"
+        "            \"subnet\": \"2001:db8:1::/64\", \n"
+        "            \"pools\": [ { \"pool\": \"2001:db8:1::/80\" } ], \n"
+        "            \"calculate-tee-times\": false,\n"
+        "            \"t1-percent\": .45, \n"
+        "            \"t2-percent\": .65 \n"
+        "        }, \n"
+        "        {  \n"
+        "            \"id\": 200, \n"
+        "            \"subnet\": \"2001:db8:2::/64\", \n"
+        "            \"pools\": [ { \"pool\": \"2001:db8:2::/80\" } ] \n"
+        "        } \n"
+        "        ] \n"
+        "     } ], \n"
+        "    \"subnet6\": [ { \n"
+        "        \"id\": 300, \n"
+        "        \"subnet\":\"2001:db8:3::/64\", \n"
+        "        \"pools\": [ { \"pool\": \"2001:db8:3::/80\" } ]\n"
+        "     } ] \n"
+        "} \n";
+
+    extractConfig(config);
+    configure(config, CONTROL_RESULT_SUCCESS, "");
+
+    CfgSubnets6Ptr subnets6 = CfgMgr::instance().getStagingCfg()->getCfgSubnets6();
+
+    // Subnet 100 should use its own explicit values.
+    ConstSubnet6Ptr subnet6 = subnets6->getBySubnetId(100);
+    ASSERT_TRUE(subnet6);
+    EXPECT_FALSE(subnet6->getCalculateTeeTimes());
+    EXPECT_TRUE(util::areDoublesEquivalent(0.45, subnet6->getT1Percent()));
+    EXPECT_TRUE(util::areDoublesEquivalent(0.65, subnet6->getT2Percent()));
+
+    // Subnet 200 should use the shared-network values.
+    subnet6 = subnets6->getBySubnetId(200);
+    ASSERT_TRUE(subnet6);
+    EXPECT_TRUE(subnet6->getCalculateTeeTimes());
+    EXPECT_TRUE(util::areDoublesEquivalent(0.4, subnet6->getT1Percent()));
+    EXPECT_TRUE(util::areDoublesEquivalent(0.75, subnet6->getT2Percent()));
+
+    // Subnet 300 should use the global values.
+    subnet6 = subnets6->getBySubnetId(300);
+    ASSERT_TRUE(subnet6);
+    EXPECT_TRUE(subnet6->getCalculateTeeTimes());
+    EXPECT_TRUE(util::areDoublesEquivalent(0.5, subnet6->getT1Percent()));
+    EXPECT_TRUE(util::areDoublesEquivalent(0.8, subnet6->getT2Percent()));
+}
+
+// This test checks that the global store-extended-info parameter is optional
+// and that values under the subnet are used.
+TEST_F(Dhcp6ParserTest, storeExtendedInfoNoGlobal) {
     const string config = "{ " + genIfaceConfig() + ","
         "\"preferred-lifetime\": 3000,"
         "\"rebind-timer\": 2000, "
         "\"renew-timer\": 1000, "
-        "\"store-extended-info\": true,"
         "\"subnet6\": [ "
-        "{ "
-        "    \"id\": 1, "
+        "{"
+        "    \"id\": 1,"
         "    \"pools\": [ { \"pool\": \"2001:db8:1::1 - 2001:db8:1::ffff\" } ],"
-        "    \"subnet\": \"2001:db8:1::/64\","
-        "    \"store-extended-info\": false"
+        "    \"subnet\": \"2001:db8:1::/64\""
         "},"
         "{"
         "    \"id\": 2, "
+        "    \"store-extended-info\": true,"
         "    \"pools\": [ { \"pool\": \"2001:db8:2::1 - 2001:db8:2::ffff\" } ],"
-        "    \"subnet\": \"2001:db8:2::/64\" "
+        "    \"subnet\": \"2001:db8:2::/64\""
         "} ],"
         "\"valid-lifetime\": 4000 }";
 
-    ConstElementPtr json = parseJSON(config);
+    ConstElementPtr json;
+    ASSERT_NO_THROW(json = parseDHCP6(config));
+    extractConfig(config);
+
     ConstElementPtr status;
-    EXPECT_NO_THROW(status = Dhcpv6SrvTest::configure(srv_, json));
+    ASSERT_NO_THROW(status = Dhcpv6SrvTest::configure(srv_, json));
     checkResult(status, 0);
 
-    // First subnet should override the global value.
+    // First subnet should use global default.
     CfgSubnets6Ptr cfg = CfgMgr::instance().getStagingCfg()->getCfgSubnets6();
     Subnet6Ptr subnet = cfg->selectSubnet(IOAddress("2001:db8:1::"));
     ASSERT_TRUE(subnet);
+    // Reset the fetch global function to staging (vs current) config.
+    subnet->setFetchGlobalsFn([]() -> ConstCfgGlobalsPtr {
+        return (CfgMgr::instance().getStagingCfg()->getConfiguredGlobals());
+    });
     EXPECT_FALSE(subnet->getStoreExtendedInfo());
 
-    // Second subnet should use the global value.
+    // Second subnet should use its own value.
     subnet = cfg->selectSubnet(IOAddress("2001:db8:2::"));
     ASSERT_TRUE(subnet);
+    // Reset the fetch global function to staging (vs current) config.
+    subnet->setFetchGlobalsFn([]() -> ConstCfgGlobalsPtr {
+        return (CfgMgr::instance().getStagingCfg()->getConfiguredGlobals());
+    });
     EXPECT_TRUE(subnet->getStoreExtendedInfo());
 }
 
-// Verifies the value of store-extended-info for subnets when there
-// is no global value defined.
-TEST_F(Dhcp6ParserTest, storeExtendedInfoNoGlobal) {
+// This test checks that the global store-extended-info parameter is used
+// when there is no such parameter under subnet and that the parameter
+// specified for a subnet overrides the global setting.
+TEST_F(Dhcp6ParserTest, storeExtendedInfoGlobal) {
     const string config = "{ " + genIfaceConfig() + ","
         "\"preferred-lifetime\": 3000,"
         "\"rebind-timer\": 2000, "
         "\"renew-timer\": 1000, "
+        "\"store-extended-info\": true,"
         "\"subnet6\": [ "
         "{ "
-        "    \"id\": 1, "
+        "    \"id\": 1,"
+        "    \"store-extended-info\": false,"
         "    \"pools\": [ { \"pool\": \"2001:db8:1::1 - 2001:db8:1::ffff\" } ],"
         "    \"subnet\": \"2001:db8:1::/64\""
         "},"
         "{"
-        "    \"id\": 2, "
+        "    \"id\": 2,"
         "    \"pools\": [ { \"pool\": \"2001:db8:2::1 - 2001:db8:2::ffff\" } ],"
-        "    \"subnet\": \"2001:db8:2::/64\","
-        "    \"store-extended-info\": true"
+        "    \"subnet\": \"2001:db8:2::/64\" "
         "} ],"
         "\"valid-lifetime\": 4000 }";
 
-    ConstElementPtr json = parseJSON(config);
+    ConstElementPtr json;
+    ASSERT_NO_THROW(json = parseDHCP6(config));
+    extractConfig(config);
+
     ConstElementPtr status;
-    EXPECT_NO_THROW(status = Dhcpv6SrvTest::configure(srv_, json));
+    ASSERT_NO_THROW(status = Dhcpv6SrvTest::configure(srv_, json));
     checkResult(status, 0);
 
-    // First subnet should use global default.
+    // First subnet should override the global value.
     CfgSubnets6Ptr cfg = CfgMgr::instance().getStagingCfg()->getCfgSubnets6();
-    Subnet6Ptr subnet = cfg->selectSubnet(IOAddress("2001:db8:1::"));
-    ASSERT_TRUE(subnet);
-    EXPECT_FALSE(subnet->getStoreExtendedInfo());
+    Subnet6Ptr subnet1 = cfg->selectSubnet(IOAddress("2001:db8:1::"));
+    ASSERT_TRUE(subnet1);
+    // Reset the fetch global function to staging (vs current) config.
+    subnet1->setFetchGlobalsFn([]() -> ConstCfgGlobalsPtr {
+        return (CfgMgr::instance().getStagingCfg()->getConfiguredGlobals());
+    });
+    EXPECT_FALSE(subnet1->getStoreExtendedInfo());
 
-    // Second subnet should use its own value.
-    subnet = cfg->selectSubnet(IOAddress("2001:db8:2::"));
-    ASSERT_TRUE(subnet);
-    EXPECT_TRUE(subnet->getStoreExtendedInfo());
+    // Second subnet should use the global value.
+    Subnet6Ptr subnet2 = cfg->selectSubnet(IOAddress("2001:db8:2::"));
+    ASSERT_TRUE(subnet2);
+    // Reset the fetch global function to staging (vs current) config.
+    subnet2->setFetchGlobalsFn([]() -> ConstCfgGlobalsPtr {
+        return (CfgMgr::instance().getStagingCfg()->getConfiguredGlobals());
+    });
+    EXPECT_TRUE(subnet2->getStoreExtendedInfo());
 }
 
 /// This test checks that the statistic-default-sample-count and age
 /// global parameters are committed to the stats manager as expected.
 TEST_F(Dhcp6ParserTest, statsDefaultLimits) {
-    std::string config = "{ " + genIfaceConfig() + "," +
+    std::string config = "{ " + genIfaceConfig() + ","
         "\"preferred-lifetime\": 3000,"
         "\"rebind-timer\": 2000, "
         "\"renew-timer\": 1000, "
@@ -7998,7 +8613,7 @@ TEST_F(Dhcp6ParserTest, statsDefaultLimits) {
 
 // This test checks that using default multi threading settings works.
 TEST_F(Dhcp6ParserTest, multiThreadingDefaultSettings) {
-    std::string config = "{ " + genIfaceConfig() + "," +
+    std::string config = "{ " + genIfaceConfig() + ","
         "\"subnet6\": [  ]"
         "}";
 
@@ -8035,7 +8650,7 @@ TEST_F(Dhcp6ParserTest, multiThreadingSettings) {
         "    \"thread-pool-size\": 48,\n"
         "    \"packet-queue-size\": 1024\n"
         "}";
-    std::string config = "{ " + genIfaceConfig() + "," +
+    std::string config = "{ " + genIfaceConfig() + ","
         "\"subnet6\": [  ], "
         "\"multi-threading\": " + content_json + "}";
 
@@ -8058,10 +8673,52 @@ TEST_F(Dhcp6ParserTest, multiThreadingSettings) {
                 << "  actual: " << *(cfg) << std::endl;
 }
 
+// Verify that parsing for the global parameter, parked-packet-limit,
+// is correct.
+TEST_F(Dhcp6ParserTest, parkedPacketLimit) {
+    // Config without parked-packet-limit
+    string config_no_limit = "{ " + genIfaceConfig() + ","
+        "\"subnet6\": [  ] "
+        "}";
+
+    // Config with parked-packet-limit
+    string config_limit = "{ " + genIfaceConfig() + ","
+        "\"parked-packet-limit\": 777, "
+        "\"subnet6\": [  ] "
+        "}";
+
+    // Config with an invalid parked-packet-limit
+    string bad_limit = "{ " + genIfaceConfig() + ","
+        "\"parked-packet-limit\": \"boo\", "
+        "\"subnet6\": [  ] "
+        "}";
+
+    // Should not exist after construction.
+    ASSERT_FALSE(CfgMgr::instance().getStagingCfg()->getConfiguredGlobal("parked-packet-limit"));
+
+    // Configuration with no limit should default to 256.
+    configure(config_no_limit, CONTROL_RESULT_SUCCESS, "");
+    ConstElementPtr ppl;
+    ASSERT_TRUE(ppl = CfgMgr::instance().getStagingCfg()->getConfiguredGlobal("parked-packet-limit"));
+    EXPECT_EQ(256, ppl->intValue());
+
+    // Clear the config
+    CfgMgr::instance().clear();
+
+    // Configuration with the limit should have the limit value.
+    configure(config_limit, CONTROL_RESULT_SUCCESS, "");
+
+    ASSERT_TRUE(ppl = CfgMgr::instance().getStagingCfg()->getConfiguredGlobal("parked-packet-limit"));
+    EXPECT_EQ(777, ppl->intValue());
+
+    // Make sure an invalid limit fails to parse.
+    ASSERT_THROW(parseDHCP6(bad_limit), std::exception);
+}
+
 // Verifies that client class definitions may specify
 // valid and preferred lifetime triplets.
 TEST_F(Dhcp6ParserTest, clientClassValidPreferredLifetime) {
-    string config = "{ " + genIfaceConfig() + "," +
+    string config = "{ " + genIfaceConfig() + ","
         "\"client-classes\" : [ \n"
         "   { \n"
         "       \"name\": \"one\", \n"
@@ -8124,7 +8781,7 @@ TEST_F(Dhcp6ParserTest, clientClassValidPreferredLifetime) {
 // Verifies that template client class definitions may specify
 // valid and preferred lifetime triplets.
 TEST_F(Dhcp6ParserTest, templateClientClassValidPreferredLifetime) {
-    string config = "{ " + genIfaceConfig() + "," +
+    string config = "{ " + genIfaceConfig() + ","
         "\"client-classes\" : [ \n"
         "   { \n"
         "       \"name\": \"one\", \n"
@@ -8191,17 +8848,17 @@ TEST_F(Dhcp6ParserTest, templateClientClassValidPreferredLifetime) {
 // This test checks that ddns-conflict-resolution-mode value can be specified at
 // global and subnet levels.
 TEST_F(Dhcp6ParserTest, storeDdnsConflictResolutionMode) {
-    std::string config = "{ " + genIfaceConfig() + "," +
+    std::string config = "{ " + genIfaceConfig() + ","
         "\"rebind-timer\": 2000, "
         "\"renew-timer\": 1000, "
         "\"subnet6\": [ "
-        "{ "
+        "{"
         "    \"id\": 1,"
         "    \"pools\": [ { \"pool\": \"2001:db8:1::1 - 2001:db8:1::ffff\" } ],"
         "    \"ddns-conflict-resolution-mode\": \"check-with-dhcid\","
         "    \"subnet\": \"2001:db8:1::/64\""
         "},"
-        "{ "
+        "{"
         "    \"id\": 2,"
         "    \"pools\": [ { \"pool\": \"2001:db8:2::1 - 2001:db8:2::ffff\" } ],"
         "    \"ddns-conflict-resolution-mode\": \"check-exists-with-dhcid\","
index 83c306f56c97cc841e1a4cbd3550ca70921ff487..2111763ae256a954f804006f8d3a3932724a6e5e 100644 (file)
@@ -9,25 +9,24 @@
 #include <cc/command_interpreter.h>
 #include <cc/data.h>
 #include <cc/simple_parser.h>
-#include <cc/cfg_to_element.h>
-#include <testutils/user_context_utils.h>
 #include <dhcp/testutils/iface_mgr_test_config.h>
-#include <dhcpsrv/cfgmgr.h>
-#include <dhcpsrv/parsers/simple_parser6.h>
-#include <dhcp6/dhcp6_srv.h>
 #include <dhcp6/ctrl_dhcp6_srv.h>
+#include <dhcp6/dhcp6_srv.h>
 #include <dhcp6/json_config_parser.h>
 #include <dhcp6/tests/dhcp6_test_utils.h>
 #include <dhcp6/tests/get_config_unittest.h>
+#include <dhcpsrv/cfgmgr.h>
 #include <testutils/gtest_utils.h>
-
-#include <boost/algorithm/string.hpp>
-#include <gtest/gtest.h>
+#include <testutils/user_context_utils.h>
 
 #include <iostream>
-#include <string>
-#include <sstream>
 #include <list>
+#include <sstream>
+#include <string>
+
+#include <boost/algorithm/string.hpp>
+
+#include <gtest/gtest.h>
 
 using namespace isc::config;
 using namespace isc::data;
@@ -75,13 +74,53 @@ const char* EXTRACTED_CONFIGS[] = {
 "            \"interfaces\": [ \"*\" ],\n"
 "            \"re-detect\": false\n"
 "        },\n"
+"        \"rebind-timer\": 2000,\n"
+"        \"subnet6\": [\n"
+"            {\n"
+"                \"id\": 1,\n"
+"                \"pools\": [\n"
+"                    {\n"
+"                        \"pool\": \"2001:db8::/64\"\n"
+"                    }\n"
+"                ],\n"
+"                \"subnet\": \"2001:db8::/32\"\n"
+"            }\n"
+"        ],\n"
+"        \"valid-lifetime\": 4000\n"
+"    }\n",
+    // CONFIGURATION 1
+"{\n"
+"        \"interfaces-config\": {\n"
+"            \"interfaces\": [ \"*\" ],\n"
+"            \"re-detect\": false\n"
+"        },\n"
+"        \"renew-timer\": 1000,\n"
+"        \"subnet6\": [\n"
+"            {\n"
+"                \"id\": 1,\n"
+"                \"pools\": [\n"
+"                    {\n"
+"                        \"pool\": \"2001:db8::/64\"\n"
+"                    }\n"
+"                ],\n"
+"                \"subnet\": \"2001:db8::/32\"\n"
+"            }\n"
+"        ],\n"
+"        \"valid-lifetime\": 4000\n"
+"    }\n",
+    // CONFIGURATION 2
+"{\n"
+"        \"interfaces-config\": {\n"
+"            \"interfaces\": [ \"*\" ],\n"
+"            \"re-detect\": false\n"
+"        },\n"
 "        \"preferred-lifetime\": 3000,\n"
 "        \"rebind-timer\": 2000,\n"
 "        \"renew-timer\": 1000,\n"
 "        \"subnet6\": [ ],\n"
 "        \"valid-lifetime\": 4000\n"
 "    }\n",
-    // CONFIGURATION 1
+    // CONFIGURATION 3
 "{\n"
 "        \"interfaces-config\": {\n"
 "            \"interfaces\": [ \"*\" ],\n"
@@ -107,7 +146,7 @@ const char* EXTRACTED_CONFIGS[] = {
 "        ],\n"
 "        \"valid-lifetime\": 4000\n"
 "    }\n",
-    // CONFIGURATION 2
+    // CONFIGURATION 4
 "{\n"
 "        \"interfaces-config\": {\n"
 "            \"interfaces\": [ \"*\" ],\n"
@@ -156,7 +195,7 @@ const char* EXTRACTED_CONFIGS[] = {
 "        ],\n"
 "        \"valid-lifetime\": 4000\n"
 "    }\n",
-    // CONFIGURATION 3
+    // CONFIGURATION 5
 "{\n"
 "        \"interfaces-config\": {\n"
 "            \"interfaces\": [ \"*\" ],\n"
@@ -205,7 +244,7 @@ const char* EXTRACTED_CONFIGS[] = {
 "        ],\n"
 "        \"valid-lifetime\": 4000\n"
 "    }\n",
-    // CONFIGURATION 4
+    // CONFIGURATION 6
 "{\n"
 "        \"compatibility\": {\n"
 "            \"lenient-option-parsing\": true\n"
@@ -230,7 +269,7 @@ const char* EXTRACTED_CONFIGS[] = {
 "        ],\n"
 "        \"valid-lifetime\": 4000\n"
 "    }\n",
-    // CONFIGURATION 5
+    // CONFIGURATION 7
 "{\n"
 "        \"interfaces-config\": {\n"
 "            \"interfaces\": [ \"*\" ],\n"
@@ -264,7 +303,7 @@ const char* EXTRACTED_CONFIGS[] = {
 "        ],\n"
 "        \"valid-lifetime\": 4000\n"
 "    }\n",
-    // CONFIGURATION 6
+    // CONFIGURATION 8
 "{\n"
 "        \"interfaces-config\": {\n"
 "            \"interfaces\": [ \"*\" ],\n"
@@ -287,7 +326,7 @@ const char* EXTRACTED_CONFIGS[] = {
 "        ],\n"
 "        \"valid-lifetime\": 4000\n"
 "    }\n",
-    // CONFIGURATION 7
+    // CONFIGURATION 9
 "{\n"
 "        \"preferred-lifetime\": 3000,\n"
 "        \"rebind-timer\": 2000,\n"
@@ -306,7 +345,7 @@ const char* EXTRACTED_CONFIGS[] = {
 "        ],\n"
 "        \"valid-lifetime\": 4000\n"
 "    }\n",
-    // CONFIGURATION 8
+    // CONFIGURATION 10
 "{\n"
 "        \"interfaces-config\": {\n"
 "            \"interfaces\": [ \"*\" ],\n"
@@ -343,7 +382,7 @@ const char* EXTRACTED_CONFIGS[] = {
 "        ],\n"
 "        \"valid-lifetime\": 4000\n"
 "    }\n",
-    // CONFIGURATION 9
+    // CONFIGURATION 11
 "{\n"
 "        \"interfaces-config\": {\n"
 "            \"interfaces\": [ \"*\" ],\n"
@@ -365,7 +404,7 @@ const char* EXTRACTED_CONFIGS[] = {
 "        ],\n"
 "        \"valid-lifetime\": 4000\n"
 "    }\n",
-    // CONFIGURATION 10
+    // CONFIGURATION 12
 "{\n"
 "        \"interfaces-config\": {\n"
 "            \"interfaces\": [ \"*\" ],\n"
@@ -389,7 +428,7 @@ const char* EXTRACTED_CONFIGS[] = {
 "            }\n"
 "        ]\n"
 "    }\n",
-    // CONFIGURATION 11
+    // CONFIGURATION 13
 "{\n"
 "        \"interfaces-config\": {\n"
 "            \"interfaces\": [ \"*\" ],\n"
@@ -415,7 +454,7 @@ const char* EXTRACTED_CONFIGS[] = {
 "            }\n"
 "        ]\n"
 "    }\n",
-    // CONFIGURATION 12
+    // CONFIGURATION 14
 "{\n"
 "        \"interfaces-config\": {\n"
 "            \"interfaces\": [ \"*\" ],\n"
@@ -454,7 +493,7 @@ const char* EXTRACTED_CONFIGS[] = {
 "            }\n"
 "        ]\n"
 "    }\n",
-    // CONFIGURATION 13
+    // CONFIGURATION 15
 "{\n"
 "        \"interfaces-config\": {\n"
 "            \"interfaces\": [ \"*\" ],\n"
@@ -478,7 +517,7 @@ const char* EXTRACTED_CONFIGS[] = {
 "            }\n"
 "        ]\n"
 "    }\n",
-    // CONFIGURATION 14
+    // CONFIGURATION 16
 "{\n"
 "        \"option-def\": [\n"
 "            {\n"
@@ -489,7 +528,7 @@ const char* EXTRACTED_CONFIGS[] = {
 "            }\n"
 "        ]\n"
 "    }\n",
-    // CONFIGURATION 15
+    // CONFIGURATION 17
 "{\n"
 "        \"option-def\": [\n"
 "            {\n"
@@ -501,7 +540,7 @@ const char* EXTRACTED_CONFIGS[] = {
 "            }\n"
 "        ]\n"
 "    }\n",
-    // CONFIGURATION 16
+    // CONFIGURATION 18
 "{\n"
 "        \"option-def\": [\n"
 "            {\n"
@@ -518,7 +557,7 @@ const char* EXTRACTED_CONFIGS[] = {
 "            }\n"
 "        ]\n"
 "    }\n",
-    // CONFIGURATION 17
+    // CONFIGURATION 19
 "{\n"
 "        \"option-def\": [\n"
 "            {\n"
@@ -530,7 +569,7 @@ const char* EXTRACTED_CONFIGS[] = {
 "            }\n"
 "        ]\n"
 "    }\n",
-    // CONFIGURATION 18
+    // CONFIGURATION 20
 "{\n"
 "        \"option-def\": [\n"
 "            {\n"
@@ -542,7 +581,29 @@ const char* EXTRACTED_CONFIGS[] = {
 "            }\n"
 "        ]\n"
 "    }\n",
-    // CONFIGURATION 19
+    // CONFIGURATION 21
+"{\n"
+"        \"option-def\": [\n"
+"            {\n"
+"                \"code\": 100,\n"
+"                \"name\": \"foo\",\n"
+"                \"space\": \"dhcp6\",\n"
+"                \"type\": \"string\"\n"
+"            }\n"
+"        ]\n"
+"    }\n",
+    // CONFIGURATION 22
+"{\n"
+"        \"option-def\": [\n"
+"            {\n"
+"                \"code\": 63,\n"
+"                \"name\": \"geolocation\",\n"
+"                \"space\": \"dhcp6\",\n"
+"                \"type\": \"string\"\n"
+"            }\n"
+"        ]\n"
+"    }\n",
+    // CONFIGURATION 23
 "{\n"
 "        \"interfaces-config\": {\n"
 "            \"interfaces\": [ \"*\" ],\n"
@@ -575,7 +636,7 @@ const char* EXTRACTED_CONFIGS[] = {
 "        ],\n"
 "        \"valid-lifetime\": 4000\n"
 "    }\n",
-    // CONFIGURATION 20
+    // CONFIGURATION 24
 "{\n"
 "        \"interfaces-config\": {\n"
 "            \"interfaces\": [ \"*\" ],\n"
@@ -608,7 +669,7 @@ const char* EXTRACTED_CONFIGS[] = {
 "        ],\n"
 "        \"valid-lifetime\": 4000\n"
 "    }\n",
-    // CONFIGURATION 21
+    // CONFIGURATION 25
 "{\n"
 "        \"interfaces-config\": {\n"
 "            \"interfaces\": [ \"*\" ],\n"
@@ -650,7 +711,7 @@ const char* EXTRACTED_CONFIGS[] = {
 "        ],\n"
 "        \"valid-lifetime\": 4000\n"
 "    }\n",
-    // CONFIGURATION 22
+    // CONFIGURATION 26
 "{\n"
 "        \"interfaces-config\": {\n"
 "            \"interfaces\": [ \"*\" ],\n"
@@ -687,7 +748,7 @@ const char* EXTRACTED_CONFIGS[] = {
 "        \"renew-timer\": 1000,\n"
 "        \"valid-lifetime\": 4000\n"
 "    }\n",
-    // CONFIGURATION 23
+    // CONFIGURATION 27
 "{\n"
 "        \"interfaces-config\": {\n"
 "            \"interfaces\": [ \"*\" ],\n"
@@ -746,7 +807,48 @@ const char* EXTRACTED_CONFIGS[] = {
 "        ],\n"
 "        \"valid-lifetime\": 4000\n"
 "    }\n",
-    // CONFIGURATION 24
+    // CONFIGURATION 28
+"{\n"
+"        \"interfaces-config\": {\n"
+"            \"interfaces\": [ \"*\" ],\n"
+"            \"re-detect\": false\n"
+"        },\n"
+"        \"option-data\": [\n"
+"            {\n"
+"                \"csv-format\": false,\n"
+"                \"data\": \"AB\",\n"
+"                \"name\": \"subscriber-id\"\n"
+"            }\n"
+"        ],\n"
+"        \"preferred-lifetime\": 3000,\n"
+"        \"rebind-timer\": 2000,\n"
+"        \"renew-timer\": 1000,\n"
+"        \"subnet6\": [\n"
+"            {\n"
+"                \"id\": 1,\n"
+"                \"option-data\": [\n"
+"                    {\n"
+"                        \"csv-format\": false,\n"
+"                        \"data\": \"ABCDEF0105\",\n"
+"                        \"name\": \"subscriber-id\"\n"
+"                    },\n"
+"                    {\n"
+"                        \"csv-format\": false,\n"
+"                        \"data\": \"FFFEFDFCFB\",\n"
+"                        \"name\": \"user-class\"\n"
+"                    }\n"
+"                ],\n"
+"                \"pools\": [\n"
+"                    {\n"
+"                        \"pool\": \"2001:db8:1::/80\"\n"
+"                    }\n"
+"                ],\n"
+"                \"subnet\": \"2001:db8:1::/64\"\n"
+"            }\n"
+"        ],\n"
+"        \"valid-lifetime\": 4000\n"
+"    }\n",
+    // CONFIGURATION 29
 "{\n"
 "        \"interfaces-config\": {\n"
 "            \"interfaces\": [ \"*\" ],\n"
@@ -791,7 +893,41 @@ const char* EXTRACTED_CONFIGS[] = {
 "        ],\n"
 "        \"valid-lifetime\": 4000\n"
 "    }\n",
-    // CONFIGURATION 25
+    // CONFIGURATION 30
+"{\n"
+"        \"interfaces-config\": {\n"
+"            \"interfaces\": [ \"*\" ],\n"
+"            \"re-detect\": false\n"
+"        },\n"
+"        \"preferred-lifetime\": 3000,\n"
+"        \"rebind-timer\": 2000,\n"
+"        \"renew-timer\": 1000,\n"
+"        \"subnet6\": [\n"
+"            {\n"
+"                \"id\": 1,\n"
+"                \"pools\": [\n"
+"                    {\n"
+"                        \"option-data\": [\n"
+"                            {\n"
+"                                \"csv-format\": false,\n"
+"                                \"data\": \"0102030405060708090A\",\n"
+"                                \"name\": \"subscriber-id\"\n"
+"                            },\n"
+"                            {\n"
+"                                \"csv-format\": false,\n"
+"                                \"data\": \"FFFEFDFCFB\",\n"
+"                                \"name\": \"user-class\"\n"
+"                            }\n"
+"                        ],\n"
+"                        \"pool\": \"2001:db8:1::10 - 2001:db8:1::100\"\n"
+"                    }\n"
+"                ],\n"
+"                \"subnet\": \"2001:db8:1::/64\"\n"
+"            }\n"
+"        ],\n"
+"        \"valid-lifetime\": 4000\n"
+"    }\n",
+    // CONFIGURATION 31
 "{\n"
 "        \"interfaces-config\": {\n"
 "            \"interfaces\": [ \"*\" ],\n"
@@ -856,7 +992,7 @@ const char* EXTRACTED_CONFIGS[] = {
 "        ],\n"
 "        \"valid-lifetime\": 4000\n"
 "    }\n",
-    // CONFIGURATION 26
+    // CONFIGURATION 32
 "{\n"
 "        \"interfaces-config\": {\n"
 "            \"interfaces\": [ \"*\" ],\n"
@@ -894,7 +1030,7 @@ const char* EXTRACTED_CONFIGS[] = {
 "        ],\n"
 "        \"valid-lifetime\": 4000\n"
 "    }\n",
-    // CONFIGURATION 27
+    // CONFIGURATION 33
 "{\n"
 "        \"interfaces-config\": {\n"
 "            \"interfaces\": [ \"*\" ],\n"
@@ -932,7 +1068,7 @@ const char* EXTRACTED_CONFIGS[] = {
 "        ],\n"
 "        \"valid-lifetime\": 4000\n"
 "    }\n",
-    // CONFIGURATION 28
+    // CONFIGURATION 34
 "{\n"
 "        \"interfaces-config\": {\n"
 "            \"interfaces\": [ \"eth0\" ],\n"
@@ -943,7 +1079,7 @@ const char* EXTRACTED_CONFIGS[] = {
 "        \"renew-timer\": 1000,\n"
 "        \"valid-lifetime\": 4000\n"
 "    }\n",
-    // CONFIGURATION 29
+    // CONFIGURATION 35
 "{\n"
 "        \"interfaces-config\": {\n"
 "            \"interfaces\": [ \"eth0\", \"eth1\", \"*\" ],\n"
@@ -954,7 +1090,7 @@ const char* EXTRACTED_CONFIGS[] = {
 "        \"renew-timer\": 1000,\n"
 "        \"valid-lifetime\": 4000\n"
 "    }\n",
-    // CONFIGURATION 30
+    // CONFIGURATION 36
 "{\n"
 "        \"interfaces-config\": {\n"
 "            \"interfaces\": [ \"*\" ],\n"
@@ -971,15 +1107,18 @@ const char* EXTRACTED_CONFIGS[] = {
 "                        \"pool\": \"2001:db8:1::1 - 2001:db8:1::ffff\"\n"
 "                    }\n"
 "                ],\n"
+"                \"rebind-timer\": 2,\n"
 "                \"relay\": {\n"
 "                    \"ip-addresses\": [ \"2001:db8:1::abcd\" ]\n"
 "                },\n"
-"                \"subnet\": \"2001:db8:1::/64\"\n"
+"                \"renew-timer\": 1,\n"
+"                \"subnet\": \"2001:db8:1::/64\",\n"
+"                \"valid-lifetime\": 4\n"
 "            }\n"
 "        ],\n"
 "        \"valid-lifetime\": 4000\n"
 "    }\n",
-    // CONFIGURATION 31
+    // CONFIGURATION 37
 "{\n"
 "        \"interfaces-config\": {\n"
 "            \"interfaces\": [ \"*\" ],\n"
@@ -996,15 +1135,18 @@ const char* EXTRACTED_CONFIGS[] = {
 "                        \"pool\": \"2001:db8:1::1 - 2001:db8:1::ffff\"\n"
 "                    }\n"
 "                ],\n"
+"                \"rebind-timer\": 2,\n"
 "                \"relay\": {\n"
 "                    \"ip-addresses\": [ \"2001:db9::abcd\", \"2001:db9::abce\" ]\n"
 "                },\n"
-"                \"subnet\": \"2001:db8:1::/64\"\n"
+"                \"renew-timer\": 1,\n"
+"                \"subnet\": \"2001:db8:1::/64\",\n"
+"                \"valid-lifetime\": 4\n"
 "            }\n"
 "        ],\n"
 "        \"valid-lifetime\": 4000\n"
 "    }\n",
-    // CONFIGURATION 32
+    // CONFIGURATION 38
 "{\n"
 "        \"interfaces-config\": {\n"
 "            \"interfaces\": [ \"*\" ],\n"
@@ -1056,7 +1198,7 @@ const char* EXTRACTED_CONFIGS[] = {
 "        ],\n"
 "        \"valid-lifetime\": 4000\n"
 "    }\n",
-    // CONFIGURATION 33
+    // CONFIGURATION 39
 "{\n"
 "        \"interfaces-config\": {\n"
 "            \"interfaces\": [ \"*\" ],\n"
@@ -1090,7 +1232,7 @@ const char* EXTRACTED_CONFIGS[] = {
 "        ],\n"
 "        \"valid-lifetime\": 4000\n"
 "    }\n",
-    // CONFIGURATION 34
+    // CONFIGURATION 40
 "{\n"
 "        \"interfaces-config\": {\n"
 "            \"interfaces\": [ \"*\" ],\n"
@@ -1132,7 +1274,7 @@ const char* EXTRACTED_CONFIGS[] = {
 "        ],\n"
 "        \"valid-lifetime\": 4000\n"
 "    }\n",
-    // CONFIGURATION 35
+    // CONFIGURATION 41
 "{\n"
 "        \"dhcp-ddns\": {\n"
 "            \"enable-updates\": true,\n"
@@ -1164,7 +1306,7 @@ const char* EXTRACTED_CONFIGS[] = {
 "        ],\n"
 "        \"valid-lifetime\": 4000\n"
 "    }\n",
-    // CONFIGURATION 36
+    // CONFIGURATION 42
 "{\n"
 "        \"interfaces-config\": {\n"
 "            \"interfaces\": [ \"*\" ],\n"
@@ -1251,7 +1393,7 @@ const char* EXTRACTED_CONFIGS[] = {
 "        ],\n"
 "        \"valid-lifetime\": 4000\n"
 "    }\n",
-    // CONFIGURATION 37
+    // CONFIGURATION 43
 "{\n"
 "        \"interfaces-config\": {\n"
 "            \"interfaces\": [ \"*\" ],\n"
@@ -1291,7 +1433,7 @@ const char* EXTRACTED_CONFIGS[] = {
 "        ],\n"
 "        \"valid-lifetime\": 4000\n"
 "    }\n",
-    // CONFIGURATION 38
+    // CONFIGURATION 44
 "{\n"
 "        \"interfaces-config\": {\n"
 "            \"interfaces\": [ \"*\" ],\n"
@@ -1304,7 +1446,7 @@ const char* EXTRACTED_CONFIGS[] = {
 "        \"subnet6\": [ ],\n"
 "        \"valid-lifetime\": 4000\n"
 "    }\n",
-    // CONFIGURATION 39
+    // CONFIGURATION 45
 "{\n"
 "        \"interfaces-config\": {\n"
 "            \"interfaces\": [ \"*\" ],\n"
@@ -1317,7 +1459,7 @@ const char* EXTRACTED_CONFIGS[] = {
 "        \"subnet6\": [ ],\n"
 "        \"valid-lifetime\": 4000\n"
 "    }\n",
-    // CONFIGURATION 40
+    // CONFIGURATION 46
 "{\n"
 "        \"preferred-lifetime\": 3000,\n"
 "        \"rebind-timer\": 2000,\n"
@@ -1405,7 +1547,7 @@ const char* EXTRACTED_CONFIGS[] = {
 "        ],\n"
 "        \"valid-lifetime\": 4000\n"
 "    }\n",
-    // CONFIGURATION 41
+    // CONFIGURATION 47
 "{\n"
 "        \"preferred-lifetime\": 3000,\n"
 "        \"rebind-timer\": 2000,\n"
@@ -1438,7 +1580,15 @@ const char* EXTRACTED_CONFIGS[] = {
 "        ],\n"
 "        \"valid-lifetime\": 4000\n"
 "    }\n",
-    // CONFIGURATION 42
+    // CONFIGURATION 48
+"{\n"
+"        \"interfaces-config\": {\n"
+"            \"interfaces\": [ \"*\" ],\n"
+"            \"re-detect\": false\n"
+"        },\n"
+"        \"subnet6\": [ ]\n"
+"    }\n",
+    // CONFIGURATION 49
 "{\n"
 "        \"interfaces-config\": {\n"
 "            \"interfaces\": [ \"*\" ],\n"
@@ -1451,7 +1601,7 @@ const char* EXTRACTED_CONFIGS[] = {
 "        \"subnet6\": [ ],\n"
 "        \"valid-lifetime\": 4000\n"
 "    }\n",
-    // CONFIGURATION 43
+    // CONFIGURATION 50
 "{\n"
 "        \"interfaces-config\": {\n"
 "            \"interfaces\": [ \"*\" ],\n"
@@ -1459,15 +1609,7 @@ const char* EXTRACTED_CONFIGS[] = {
 "        },\n"
 "        \"subnet6\": [ ]\n"
 "    }\n",
-    // CONFIGURATION 44
-"{\n"
-"        \"interfaces-config\": {\n"
-"            \"interfaces\": [ \"*\" ],\n"
-"            \"re-detect\": false\n"
-"        },\n"
-"        \"subnet6\": [ ]\n"
-"    }\n",
-    // CONFIGURATION 45
+    // CONFIGURATION 51
 "{\n"
 "        \"decline-probation-period\": 12345,\n"
 "        \"interfaces-config\": {\n"
@@ -1476,7 +1618,7 @@ const char* EXTRACTED_CONFIGS[] = {
 "        },\n"
 "        \"subnet6\": [ ]\n"
 "    }\n",
-    // CONFIGURATION 46
+    // CONFIGURATION 52
 "{\n"
 "        \"expired-leases-processing\": {\n"
 "            \"flush-reclaimed-timer-wait-time\": 35,\n"
@@ -1492,7 +1634,7 @@ const char* EXTRACTED_CONFIGS[] = {
 "        },\n"
 "        \"subnet6\": [ ]\n"
 "    }\n",
-    // CONFIGURATION 47
+    // CONFIGURATION 53
 "{\n"
 "        \"client-classes\": [\n"
 "            {\n"
@@ -1525,7 +1667,67 @@ const char* EXTRACTED_CONFIGS[] = {
 "        ],\n"
 "        \"valid-lifetime\": 4000\n"
 "    }\n",
-    // CONFIGURATION 48
+    // CONFIGURATION 54
+"{\n"
+"        \"client-classes\": [\n"
+"            {\n"
+"                \"max-valid-lifetime\": 3000,\n"
+"                \"min-valid-lifetime\": 1000,\n"
+"                \"name\": \"one\",\n"
+"                \"valid-lifetime\": 2000\n"
+"            },\n"
+"            {\n"
+"                \"name\": \"two\"\n"
+"            }\n"
+"        ],\n"
+"        \"interfaces-config\": {\n"
+"            \"interfaces\": [ \"*\" ],\n"
+"            \"re-detect\": false\n"
+"        },\n"
+"        \"subnet6\": [\n"
+"            {\n"
+"                \"id\": 1,\n"
+"                \"pools\": [\n"
+"                    {\n"
+"                        \"pool\": \"2001:db8::1 - 2001:db8::ffff\"\n"
+"                    }\n"
+"                ],\n"
+"                \"subnet\": \"2001:db8::/64\"\n"
+"            }\n"
+"        ]\n"
+"    }\n",
+    // CONFIGURATION 55
+"{\n"
+"        \"client-classes\": [\n"
+"            {\n"
+"                \"max-valid-lifetime\": 3000,\n"
+"                \"min-valid-lifetime\": 1000,\n"
+"                \"name\": \"one\",\n"
+"                \"template-test\": \"''\",\n"
+"                \"valid-lifetime\": 2000\n"
+"            },\n"
+"            {\n"
+"                \"name\": \"two\",\n"
+"                \"template-test\": \"''\"\n"
+"            }\n"
+"        ],\n"
+"        \"interfaces-config\": {\n"
+"            \"interfaces\": [ \"*\" ],\n"
+"            \"re-detect\": false\n"
+"        },\n"
+"        \"subnet6\": [\n"
+"            {\n"
+"                \"id\": 1,\n"
+"                \"pools\": [\n"
+"                    {\n"
+"                        \"pool\": \"2001:db8::1 - 2001:db8::ffff\"\n"
+"                    }\n"
+"                ],\n"
+"                \"subnet\": \"2001:db8::/64\"\n"
+"            }\n"
+"        ]\n"
+"    }\n",
+    // CONFIGURATION 56
 "{\n"
 "        \"interfaces-config\": {\n"
 "            \"interfaces\": [ \"*\" ],\n"
@@ -1547,7 +1749,7 @@ const char* EXTRACTED_CONFIGS[] = {
 "        ],\n"
 "        \"valid-lifetime\": 4000\n"
 "    }\n",
-    // CONFIGURATION 49
+    // CONFIGURATION 57
 "{\n"
 "        \"interfaces-config\": {\n"
 "            \"interfaces\": [ \"*\" ],\n"
@@ -1570,7 +1772,7 @@ const char* EXTRACTED_CONFIGS[] = {
 "        ],\n"
 "        \"valid-lifetime\": 4000\n"
 "    }\n",
-    // CONFIGURATION 50
+    // CONFIGURATION 58
 "{\n"
 "        \"interfaces-config\": {\n"
 "            \"interfaces\": [ \"*\" ],\n"
@@ -1598,7 +1800,35 @@ const char* EXTRACTED_CONFIGS[] = {
 "        ],\n"
 "        \"valid-lifetime\": 4000\n"
 "    }\n",
-    // CONFIGURATION 51
+    // CONFIGURATION 59
+"{\n"
+"        \"interfaces-config\": {\n"
+"            \"interfaces\": [ \"*\" ],\n"
+"            \"re-detect\": false\n"
+"        },\n"
+"        \"preferred-lifetime\": 3000,\n"
+"        \"rebind-timer\": 2000,\n"
+"        \"renew-timer\": 1000,\n"
+"        \"subnet6\": [\n"
+"            {\n"
+"                \"id\": 1,\n"
+"                \"pools\": [\n"
+"                    {\n"
+"                        \"pool\": \"2001:db8::/64\",\n"
+"                        \"user-context\": {\n"
+"                            \"lw4over6-bind-prefix-len\": 56,\n"
+"                            \"lw4over6-sharing-ratio\": 64,\n"
+"                            \"lw4over6-sysports-exclude\": true,\n"
+"                            \"lw4over6-v4-pool\": \"192.0.2.0/24\"\n"
+"                        }\n"
+"                    }\n"
+"                ],\n"
+"                \"subnet\": \"2001:db8::/32\"\n"
+"            }\n"
+"        ],\n"
+"        \"valid-lifetime\": 4000\n"
+"    }\n",
+    // CONFIGURATION 60
 "{\n"
 "        \"interfaces-config\": {\n"
 "            \"interfaces\": [ \"*\" ],\n"
@@ -1626,7 +1856,7 @@ const char* EXTRACTED_CONFIGS[] = {
 "        ],\n"
 "        \"valid-lifetime\": 4000\n"
 "    }\n",
-    // CONFIGURATION 52
+    // CONFIGURATION 61
 "{\n"
 "        \"interfaces-config\": {\n"
 "            \"interfaces\": [ \"*\" ],\n"
@@ -1650,7 +1880,7 @@ const char* EXTRACTED_CONFIGS[] = {
 "        ],\n"
 "        \"valid-lifetime\": 4000\n"
 "    }\n",
-    // CONFIGURATION 53
+    // CONFIGURATION 62
 "{\n"
 "        \"interfaces-config\": {\n"
 "            \"interfaces\": [ \"*\" ],\n"
@@ -1675,7 +1905,7 @@ const char* EXTRACTED_CONFIGS[] = {
 "        ],\n"
 "        \"valid-lifetime\": 4000\n"
 "    }\n",
-    // CONFIGURATION 54
+    // CONFIGURATION 63
 "{\n"
 "        \"interfaces-config\": {\n"
 "            \"interfaces\": [ \"*\" ],\n"
@@ -1705,7 +1935,7 @@ const char* EXTRACTED_CONFIGS[] = {
 "        ],\n"
 "        \"valid-lifetime\": 4000\n"
 "    }\n",
-    // CONFIGURATION 55
+    // CONFIGURATION 64
 "{\n"
 "        \"hosts-databases\": [\n"
 "            {\n"
@@ -1717,6 +1947,7 @@ const char* EXTRACTED_CONFIGS[] = {
 "            {\n"
 "                \"name\": \"keatest2\",\n"
 "                \"password\": \"keatest\",\n"
+"                \"retry-on-startup\": true,\n"
 "                \"type\": \"mysql\",\n"
 "                \"user\": \"keatest\"\n"
 "            }\n"
@@ -1730,7 +1961,7 @@ const char* EXTRACTED_CONFIGS[] = {
 "        \"renew-timer\": 1000,\n"
 "        \"valid-lifetime\": 4000\n"
 "    }\n",
-    // CONFIGURATION 56
+    // CONFIGURATION 65
 "{\n"
 "        \"client-classes\": [\n"
 "            {\n"
@@ -1855,7 +2086,7 @@ const char* EXTRACTED_CONFIGS[] = {
 "            \"comment\": \"A DHCPv6 server\"\n"
 "        }\n"
 "    }\n",
-    // CONFIGURATION 57
+    // CONFIGURATION 66
 "{\n"
 "        \"interfaces-config\": {\n"
 "            \"interfaces\": [ \"*\" ],\n"
@@ -1920,7 +2151,123 @@ const char* EXTRACTED_CONFIGS[] = {
 "        ],\n"
 "        \"valid-lifetime\": 4000\n"
 "    }\n",
-    // CONFIGURATION 58
+    // CONFIGURATION 67
+"{\n"
+"        \"interfaces-config\": {\n"
+"            \"interfaces\": [ \"*\" ],\n"
+"            \"re-detect\": false\n"
+"        },\n"
+"        \"preferred-lifetime\": 3000,\n"
+"        \"shared-networks\": [\n"
+"            {\n"
+"                \"calculate-tee-times\": true,\n"
+"                \"name\": \"foo\",\n"
+"                \"subnet6\": [\n"
+"                    {\n"
+"                        \"calculate-tee-times\": false,\n"
+"                        \"id\": 100,\n"
+"                        \"pools\": [\n"
+"                            {\n"
+"                                \"pool\": \"2001:db8:1::/80\"\n"
+"                            }\n"
+"                        ],\n"
+"                        \"subnet\": \"2001:db8:1::/64\",\n"
+"                        \"t1-percent\": 0.45,\n"
+"                        \"t2-percent\": 0.65\n"
+"                    },\n"
+"                    {\n"
+"                        \"id\": 200,\n"
+"                        \"pools\": [\n"
+"                            {\n"
+"                                \"pool\": \"2001:db8:2::/80\"\n"
+"                            }\n"
+"                        ],\n"
+"                        \"subnet\": \"2001:db8:2::/64\"\n"
+"                    }\n"
+"                ],\n"
+"                \"t1-percent\": 0.4,\n"
+"                \"t2-percent\": 0.75\n"
+"            }\n"
+"        ],\n"
+"        \"subnet6\": [\n"
+"            {\n"
+"                \"id\": 300,\n"
+"                \"pools\": [\n"
+"                    {\n"
+"                        \"pool\": \"2001:db8:3::/80\"\n"
+"                    }\n"
+"                ],\n"
+"                \"subnet\": \"2001:db8:3::/64\"\n"
+"            }\n"
+"        ],\n"
+"        \"valid-lifetime\": 4000\n"
+"    }\n",
+    // CONFIGURATION 68
+"{\n"
+"        \"interfaces-config\": {\n"
+"            \"interfaces\": [ \"*\" ],\n"
+"            \"re-detect\": false\n"
+"        },\n"
+"        \"preferred-lifetime\": 3000,\n"
+"        \"rebind-timer\": 2000,\n"
+"        \"renew-timer\": 1000,\n"
+"        \"subnet6\": [\n"
+"            {\n"
+"                \"id\": 1,\n"
+"                \"pools\": [\n"
+"                    {\n"
+"                        \"pool\": \"2001:db8:1::1 - 2001:db8:1::ffff\"\n"
+"                    }\n"
+"                ],\n"
+"                \"subnet\": \"2001:db8:1::/64\"\n"
+"            },\n"
+"            {\n"
+"                \"id\": 2,\n"
+"                \"pools\": [\n"
+"                    {\n"
+"                        \"pool\": \"2001:db8:2::1 - 2001:db8:2::ffff\"\n"
+"                    }\n"
+"                ],\n"
+"                \"store-extended-info\": true,\n"
+"                \"subnet\": \"2001:db8:2::/64\"\n"
+"            }\n"
+"        ],\n"
+"        \"valid-lifetime\": 4000\n"
+"    }\n",
+    // CONFIGURATION 69
+"{\n"
+"        \"interfaces-config\": {\n"
+"            \"interfaces\": [ \"*\" ],\n"
+"            \"re-detect\": false\n"
+"        },\n"
+"        \"preferred-lifetime\": 3000,\n"
+"        \"rebind-timer\": 2000,\n"
+"        \"renew-timer\": 1000,\n"
+"        \"store-extended-info\": true,\n"
+"        \"subnet6\": [\n"
+"            {\n"
+"                \"id\": 1,\n"
+"                \"pools\": [\n"
+"                    {\n"
+"                        \"pool\": \"2001:db8:1::1 - 2001:db8:1::ffff\"\n"
+"                    }\n"
+"                ],\n"
+"                \"store-extended-info\": false,\n"
+"                \"subnet\": \"2001:db8:1::/64\"\n"
+"            },\n"
+"            {\n"
+"                \"id\": 2,\n"
+"                \"pools\": [\n"
+"                    {\n"
+"                        \"pool\": \"2001:db8:2::1 - 2001:db8:2::ffff\"\n"
+"                    }\n"
+"                ],\n"
+"                \"subnet\": \"2001:db8:2::/64\"\n"
+"            }\n"
+"        ],\n"
+"        \"valid-lifetime\": 4000\n"
+"    }\n",
+    // CONFIGURATION 70
 "{\n"
 "        \"interfaces-config\": {\n"
 "            \"interfaces\": [ \"*\" ],\n"
@@ -1933,7 +2280,7 @@ const char* EXTRACTED_CONFIGS[] = {
 "        \"statistic-default-sample-count\": 10,\n"
 "        \"valid-lifetime\": 4000\n"
 "    }\n",
-    // CONFIGURATION 59
+    // CONFIGURATION 71
 "{\n"
 "        \"interfaces-config\": {\n"
 "            \"interfaces\": [ \"*\" ],\n"
@@ -1941,7 +2288,7 @@ const char* EXTRACTED_CONFIGS[] = {
 "        },\n"
 "        \"subnet6\": [ ]\n"
 "    }\n",
-    // CONFIGURATION 60
+    // CONFIGURATION 72
 "{\n"
 "        \"interfaces-config\": {\n"
 "            \"interfaces\": [ \"*\" ],\n"
@@ -1954,7 +2301,7 @@ const char* EXTRACTED_CONFIGS[] = {
 "        },\n"
 "        \"subnet6\": [ ]\n"
 "    }\n",
-    // CONFIGURATION 61
+    // CONFIGURATION 73
 "{\n"
 "        \"client-classes\": [\n"
 "            {\n"
@@ -1986,7 +2333,7 @@ const char* EXTRACTED_CONFIGS[] = {
 "            }\n"
 "        ]\n"
 "    }\n",
-    // CONFIGURATION 62
+    // CONFIGURATION 74
 "{\n"
 "        \"client-classes\": [\n"
 "            {\n"
@@ -2020,7 +2367,7 @@ const char* EXTRACTED_CONFIGS[] = {
 "            }\n"
 "        ]\n"
 "    }\n",
-    // CONFIGURATION 63
+    // CONFIGURATION 75
 "{\n"
 "        \"ddns-conflict-resolution-mode\": \"no-check-with-dhcid\",\n"
 "        \"interfaces-config\": {\n"
@@ -2146,10 +2493,8 @@ const char* UNPARSED_CONFIGS[] = {
 "        \"option-def\": [ ],\n"
 "        \"parked-packet-limit\": 256,\n"
 "        \"pd-allocator\": \"iterative\",\n"
-"        \"preferred-lifetime\": 3000,\n"
 "        \"rebind-timer\": 2000,\n"
 "        \"relay-supplied-options\": [ \"65\" ],\n"
-"        \"renew-timer\": 1000,\n"
 "        \"reservations-global\": false,\n"
 "        \"reservations-in-subnet\": true,\n"
 "        \"reservations-lookup-first\": false,\n"
@@ -2171,7 +2516,35 @@ const char* UNPARSED_CONFIGS[] = {
 "        \"statistic-default-sample-age\": 0,\n"
 "        \"statistic-default-sample-count\": 20,\n"
 "        \"store-extended-info\": false,\n"
-"        \"subnet6\": [ ],\n"
+"        \"subnet6\": [\n"
+"            {\n"
+"                \"allocator\": \"iterative\",\n"
+"                \"calculate-tee-times\": true,\n"
+"                \"id\": 1,\n"
+"                \"max-valid-lifetime\": 4000,\n"
+"                \"min-valid-lifetime\": 4000,\n"
+"                \"option-data\": [ ],\n"
+"                \"pd-allocator\": \"iterative\",\n"
+"                \"pd-pools\": [ ],\n"
+"                \"pools\": [\n"
+"                    {\n"
+"                        \"option-data\": [ ],\n"
+"                        \"pool\": \"2001:db8::/64\"\n"
+"                    }\n"
+"                ],\n"
+"                \"rapid-commit\": false,\n"
+"                \"rebind-timer\": 2000,\n"
+"                \"relay\": {\n"
+"                    \"ip-addresses\": [ ]\n"
+"                },\n"
+"                \"reservations\": [ ],\n"
+"                \"store-extended-info\": false,\n"
+"                \"subnet\": \"2001:db8::/32\",\n"
+"                \"t1-percent\": 0.5,\n"
+"                \"t2-percent\": 0.8,\n"
+"                \"valid-lifetime\": 4000\n"
+"            }\n"
+"        ],\n"
 "        \"t1-percent\": 0.5,\n"
 "        \"t2-percent\": 0.8,\n"
 "        \"valid-lifetime\": 4000\n"
@@ -2227,8 +2600,214 @@ const char* UNPARSED_CONFIGS[] = {
 "            \"type\": \"memfile\"\n"
 "        },\n"
 "        \"mac-sources\": [ \"any\" ],\n"
-"        \"max-preferred-lifetime\": 4000,\n"
-"        \"max-valid-lifetime\": 5000,\n"
+"        \"multi-threading\": {\n"
+"            \"enable-multi-threading\": true,\n"
+"            \"packet-queue-size\": 64,\n"
+"            \"thread-pool-size\": 0\n"
+"        },\n"
+"        \"option-data\": [ ],\n"
+"        \"option-def\": [ ],\n"
+"        \"parked-packet-limit\": 256,\n"
+"        \"pd-allocator\": \"iterative\",\n"
+"        \"relay-supplied-options\": [ \"65\" ],\n"
+"        \"renew-timer\": 1000,\n"
+"        \"reservations-global\": false,\n"
+"        \"reservations-in-subnet\": true,\n"
+"        \"reservations-lookup-first\": false,\n"
+"        \"reservations-out-of-pool\": false,\n"
+"        \"sanity-checks\": {\n"
+"            \"extended-info-checks\": \"fix\",\n"
+"            \"lease-checks\": \"warn\"\n"
+"        },\n"
+"        \"server-id\": {\n"
+"            \"enterprise-id\": 0,\n"
+"            \"htype\": 0,\n"
+"            \"identifier\": \"\",\n"
+"            \"persist\": true,\n"
+"            \"time\": 0,\n"
+"            \"type\": \"LLT\"\n"
+"        },\n"
+"        \"server-tag\": \"\",\n"
+"        \"shared-networks\": [ ],\n"
+"        \"statistic-default-sample-age\": 0,\n"
+"        \"statistic-default-sample-count\": 20,\n"
+"        \"store-extended-info\": false,\n"
+"        \"subnet6\": [\n"
+"            {\n"
+"                \"allocator\": \"iterative\",\n"
+"                \"calculate-tee-times\": true,\n"
+"                \"id\": 1,\n"
+"                \"max-valid-lifetime\": 4000,\n"
+"                \"min-valid-lifetime\": 4000,\n"
+"                \"option-data\": [ ],\n"
+"                \"pd-allocator\": \"iterative\",\n"
+"                \"pd-pools\": [ ],\n"
+"                \"pools\": [\n"
+"                    {\n"
+"                        \"option-data\": [ ],\n"
+"                        \"pool\": \"2001:db8::/64\"\n"
+"                    }\n"
+"                ],\n"
+"                \"rapid-commit\": false,\n"
+"                \"relay\": {\n"
+"                    \"ip-addresses\": [ ]\n"
+"                },\n"
+"                \"renew-timer\": 1000,\n"
+"                \"reservations\": [ ],\n"
+"                \"store-extended-info\": false,\n"
+"                \"subnet\": \"2001:db8::/32\",\n"
+"                \"t1-percent\": 0.5,\n"
+"                \"t2-percent\": 0.8,\n"
+"                \"valid-lifetime\": 4000\n"
+"            }\n"
+"        ],\n"
+"        \"t1-percent\": 0.5,\n"
+"        \"t2-percent\": 0.8,\n"
+"        \"valid-lifetime\": 4000\n"
+"    }\n",
+    // CONFIGURATION 2
+"{\n"
+"        \"allocator\": \"iterative\",\n"
+"        \"calculate-tee-times\": true,\n"
+"        \"ddns-conflict-resolution-mode\": \"check-with-dhcid\",\n"
+"        \"ddns-generated-prefix\": \"myhost\",\n"
+"        \"ddns-override-client-update\": false,\n"
+"        \"ddns-override-no-update\": false,\n"
+"        \"ddns-qualifying-suffix\": \"\",\n"
+"        \"ddns-replace-client-name\": \"never\",\n"
+"        \"ddns-send-updates\": true,\n"
+"        \"ddns-update-on-renew\": false,\n"
+"        \"decline-probation-period\": 86400,\n"
+"        \"dhcp-ddns\": {\n"
+"            \"enable-updates\": false,\n"
+"            \"max-queue-size\": 1024,\n"
+"            \"ncr-format\": \"JSON\",\n"
+"            \"ncr-protocol\": \"UDP\",\n"
+"            \"sender-ip\": \"0.0.0.0\",\n"
+"            \"sender-port\": 0,\n"
+"            \"server-ip\": \"127.0.0.1\",\n"
+"            \"server-port\": 53001\n"
+"        },\n"
+"        \"dhcp-queue-control\": {\n"
+"            \"capacity\": 64,\n"
+"            \"enable-queue\": false,\n"
+"            \"queue-type\": \"kea-ring6\"\n"
+"        },\n"
+"        \"dhcp4o6-port\": 0,\n"
+"        \"early-global-reservations-lookup\": false,\n"
+"        \"expired-leases-processing\": {\n"
+"            \"flush-reclaimed-timer-wait-time\": 25,\n"
+"            \"hold-reclaimed-time\": 3600,\n"
+"            \"max-reclaim-leases\": 100,\n"
+"            \"max-reclaim-time\": 250,\n"
+"            \"reclaim-timer-wait-time\": 10,\n"
+"            \"unwarned-reclaim-cycles\": 5\n"
+"        },\n"
+"        \"hooks-libraries\": [ ],\n"
+"        \"host-reservation-identifiers\": [ \"hw-address\", \"duid\" ],\n"
+"        \"hostname-char-replacement\": \"\",\n"
+"        \"hostname-char-set\": \"[^A-Za-z0-9.-]\",\n"
+"        \"interfaces-config\": {\n"
+"            \"interfaces\": [ \"*\" ],\n"
+"            \"re-detect\": false\n"
+"        },\n"
+"        \"ip-reservations-unique\": true,\n"
+"        \"lease-database\": {\n"
+"            \"type\": \"memfile\"\n"
+"        },\n"
+"        \"mac-sources\": [ \"any\" ],\n"
+"        \"multi-threading\": {\n"
+"            \"enable-multi-threading\": true,\n"
+"            \"packet-queue-size\": 64,\n"
+"            \"thread-pool-size\": 0\n"
+"        },\n"
+"        \"option-data\": [ ],\n"
+"        \"option-def\": [ ],\n"
+"        \"parked-packet-limit\": 256,\n"
+"        \"pd-allocator\": \"iterative\",\n"
+"        \"preferred-lifetime\": 3000,\n"
+"        \"rebind-timer\": 2000,\n"
+"        \"relay-supplied-options\": [ \"65\" ],\n"
+"        \"renew-timer\": 1000,\n"
+"        \"reservations-global\": false,\n"
+"        \"reservations-in-subnet\": true,\n"
+"        \"reservations-lookup-first\": false,\n"
+"        \"reservations-out-of-pool\": false,\n"
+"        \"sanity-checks\": {\n"
+"            \"extended-info-checks\": \"fix\",\n"
+"            \"lease-checks\": \"warn\"\n"
+"        },\n"
+"        \"server-id\": {\n"
+"            \"enterprise-id\": 0,\n"
+"            \"htype\": 0,\n"
+"            \"identifier\": \"\",\n"
+"            \"persist\": true,\n"
+"            \"time\": 0,\n"
+"            \"type\": \"LLT\"\n"
+"        },\n"
+"        \"server-tag\": \"\",\n"
+"        \"shared-networks\": [ ],\n"
+"        \"statistic-default-sample-age\": 0,\n"
+"        \"statistic-default-sample-count\": 20,\n"
+"        \"store-extended-info\": false,\n"
+"        \"subnet6\": [ ],\n"
+"        \"t1-percent\": 0.5,\n"
+"        \"t2-percent\": 0.8,\n"
+"        \"valid-lifetime\": 4000\n"
+"    }\n",
+    // CONFIGURATION 3
+"{\n"
+"        \"allocator\": \"iterative\",\n"
+"        \"calculate-tee-times\": true,\n"
+"        \"ddns-conflict-resolution-mode\": \"check-with-dhcid\",\n"
+"        \"ddns-generated-prefix\": \"myhost\",\n"
+"        \"ddns-override-client-update\": false,\n"
+"        \"ddns-override-no-update\": false,\n"
+"        \"ddns-qualifying-suffix\": \"\",\n"
+"        \"ddns-replace-client-name\": \"never\",\n"
+"        \"ddns-send-updates\": true,\n"
+"        \"ddns-update-on-renew\": false,\n"
+"        \"decline-probation-period\": 86400,\n"
+"        \"dhcp-ddns\": {\n"
+"            \"enable-updates\": false,\n"
+"            \"max-queue-size\": 1024,\n"
+"            \"ncr-format\": \"JSON\",\n"
+"            \"ncr-protocol\": \"UDP\",\n"
+"            \"sender-ip\": \"0.0.0.0\",\n"
+"            \"sender-port\": 0,\n"
+"            \"server-ip\": \"127.0.0.1\",\n"
+"            \"server-port\": 53001\n"
+"        },\n"
+"        \"dhcp-queue-control\": {\n"
+"            \"capacity\": 64,\n"
+"            \"enable-queue\": false,\n"
+"            \"queue-type\": \"kea-ring6\"\n"
+"        },\n"
+"        \"dhcp4o6-port\": 0,\n"
+"        \"early-global-reservations-lookup\": false,\n"
+"        \"expired-leases-processing\": {\n"
+"            \"flush-reclaimed-timer-wait-time\": 25,\n"
+"            \"hold-reclaimed-time\": 3600,\n"
+"            \"max-reclaim-leases\": 100,\n"
+"            \"max-reclaim-time\": 250,\n"
+"            \"reclaim-timer-wait-time\": 10,\n"
+"            \"unwarned-reclaim-cycles\": 5\n"
+"        },\n"
+"        \"hooks-libraries\": [ ],\n"
+"        \"host-reservation-identifiers\": [ \"hw-address\", \"duid\" ],\n"
+"        \"hostname-char-replacement\": \"\",\n"
+"        \"hostname-char-set\": \"[^A-Za-z0-9.-]\",\n"
+"        \"interfaces-config\": {\n"
+"            \"interfaces\": [ \"*\" ],\n"
+"            \"re-detect\": false\n"
+"        },\n"
+"        \"ip-reservations-unique\": true,\n"
+"        \"lease-database\": {\n"
+"            \"type\": \"memfile\"\n"
+"        },\n"
+"        \"mac-sources\": [ \"any\" ],\n"
+"        \"max-preferred-lifetime\": 4000,\n"
+"        \"max-valid-lifetime\": 5000,\n"
 "        \"min-preferred-lifetime\": 2000,\n"
 "        \"min-valid-lifetime\": 3000,\n"
 "        \"multi-threading\": {\n"
@@ -2302,7 +2881,7 @@ const char* UNPARSED_CONFIGS[] = {
 "        \"t2-percent\": 0.8,\n"
 "        \"valid-lifetime\": 4000\n"
 "    }\n",
-    // CONFIGURATION 2
+    // CONFIGURATION 4
 "{\n"
 "        \"allocator\": \"iterative\",\n"
 "        \"calculate-tee-times\": true,\n"
@@ -2517,7 +3096,7 @@ const char* UNPARSED_CONFIGS[] = {
 "        \"t2-percent\": 0.8,\n"
 "        \"valid-lifetime\": 4000\n"
 "    }\n",
-    // CONFIGURATION 3
+    // CONFIGURATION 5
 "{\n"
 "        \"allocator\": \"iterative\",\n"
 "        \"calculate-tee-times\": true,\n"
@@ -2732,7 +3311,7 @@ const char* UNPARSED_CONFIGS[] = {
 "        \"t2-percent\": 0.8,\n"
 "        \"valid-lifetime\": 4000\n"
 "    }\n",
-    // CONFIGURATION 4
+    // CONFIGURATION 6
 "{\n"
 "        \"allocator\": \"iterative\",\n"
 "        \"calculate-tee-times\": true,\n"
@@ -2857,7 +3436,7 @@ const char* UNPARSED_CONFIGS[] = {
 "        \"t2-percent\": 0.8,\n"
 "        \"valid-lifetime\": 4000\n"
 "    }\n",
-    // CONFIGURATION 5
+    // CONFIGURATION 7
 "{\n"
 "        \"allocator\": \"iterative\",\n"
 "        \"calculate-tee-times\": true,\n"
@@ -2983,7 +3562,7 @@ const char* UNPARSED_CONFIGS[] = {
 "        \"t2-percent\": 0.8,\n"
 "        \"valid-lifetime\": 4000\n"
 "    }\n",
-    // CONFIGURATION 6
+    // CONFIGURATION 8
 "{\n"
 "        \"allocator\": \"iterative\",\n"
 "        \"calculate-tee-times\": true,\n"
@@ -3106,7 +3685,7 @@ const char* UNPARSED_CONFIGS[] = {
 "        \"t2-percent\": 0.8,\n"
 "        \"valid-lifetime\": 4000\n"
 "    }\n",
-    // CONFIGURATION 7
+    // CONFIGURATION 9
 "{\n"
 "        \"allocator\": \"iterative\",\n"
 "        \"calculate-tee-times\": true,\n"
@@ -3229,7 +3808,7 @@ const char* UNPARSED_CONFIGS[] = {
 "        \"t2-percent\": 0.8,\n"
 "        \"valid-lifetime\": 4000\n"
 "    }\n",
-    // CONFIGURATION 8
+    // CONFIGURATION 10
 "{\n"
 "        \"allocator\": \"iterative\",\n"
 "        \"calculate-tee-times\": true,\n"
@@ -3390,7 +3969,7 @@ const char* UNPARSED_CONFIGS[] = {
 "        \"t2-percent\": 0.8,\n"
 "        \"valid-lifetime\": 4000\n"
 "    }\n",
-    // CONFIGURATION 9
+    // CONFIGURATION 11
 "{\n"
 "        \"allocator\": \"iterative\",\n"
 "        \"calculate-tee-times\": true,\n"
@@ -3512,7 +4091,7 @@ const char* UNPARSED_CONFIGS[] = {
 "        \"t2-percent\": 0.8,\n"
 "        \"valid-lifetime\": 4000\n"
 "    }\n",
-    // CONFIGURATION 10
+    // CONFIGURATION 12
 "{\n"
 "        \"allocator\": \"iterative\",\n"
 "        \"calculate-tee-times\": true,\n"
@@ -3636,7 +4215,7 @@ const char* UNPARSED_CONFIGS[] = {
 "        \"t2-percent\": 0.8,\n"
 "        \"valid-lifetime\": 7200\n"
 "    }\n",
-    // CONFIGURATION 11
+    // CONFIGURATION 13
 "{\n"
 "        \"allocator\": \"iterative\",\n"
 "        \"calculate-tee-times\": true,\n"
@@ -3762,7 +4341,7 @@ const char* UNPARSED_CONFIGS[] = {
 "        \"t2-percent\": 0.8,\n"
 "        \"valid-lifetime\": 7200\n"
 "    }\n",
-    // CONFIGURATION 12
+    // CONFIGURATION 14
 "{\n"
 "        \"allocator\": \"iterative\",\n"
 "        \"calculate-tee-times\": true,\n"
@@ -3903,7 +4482,7 @@ const char* UNPARSED_CONFIGS[] = {
 "        \"t2-percent\": 0.8,\n"
 "        \"valid-lifetime\": 7200\n"
 "    }\n",
-    // CONFIGURATION 13
+    // CONFIGURATION 15
 "{\n"
 "        \"allocator\": \"iterative\",\n"
 "        \"calculate-tee-times\": true,\n"
@@ -4027,7 +4606,7 @@ const char* UNPARSED_CONFIGS[] = {
 "        \"t2-percent\": 0.8,\n"
 "        \"valid-lifetime\": 7200\n"
 "    }\n",
-    // CONFIGURATION 14
+    // CONFIGURATION 16
 "{\n"
 "        \"allocator\": \"iterative\",\n"
 "        \"calculate-tee-times\": true,\n"
@@ -4124,7 +4703,7 @@ const char* UNPARSED_CONFIGS[] = {
 "        \"t2-percent\": 0.8,\n"
 "        \"valid-lifetime\": 7200\n"
 "    }\n",
-    // CONFIGURATION 15
+    // CONFIGURATION 17
 "{\n"
 "        \"allocator\": \"iterative\",\n"
 "        \"calculate-tee-times\": true,\n"
@@ -4221,7 +4800,7 @@ const char* UNPARSED_CONFIGS[] = {
 "        \"t2-percent\": 0.8,\n"
 "        \"valid-lifetime\": 7200\n"
 "    }\n",
-    // CONFIGURATION 16
+    // CONFIGURATION 18
 "{\n"
 "        \"allocator\": \"iterative\",\n"
 "        \"calculate-tee-times\": true,\n"
@@ -4327,7 +4906,7 @@ const char* UNPARSED_CONFIGS[] = {
 "        \"t2-percent\": 0.8,\n"
 "        \"valid-lifetime\": 7200\n"
 "    }\n",
-    // CONFIGURATION 17
+    // CONFIGURATION 19
 "{\n"
 "        \"allocator\": \"iterative\",\n"
 "        \"calculate-tee-times\": true,\n"
@@ -4424,7 +5003,7 @@ const char* UNPARSED_CONFIGS[] = {
 "        \"t2-percent\": 0.8,\n"
 "        \"valid-lifetime\": 7200\n"
 "    }\n",
-    // CONFIGURATION 18
+    // CONFIGURATION 20
 "{\n"
 "        \"allocator\": \"iterative\",\n"
 "        \"calculate-tee-times\": true,\n"
@@ -4521,7 +5100,7 @@ const char* UNPARSED_CONFIGS[] = {
 "        \"t2-percent\": 0.8,\n"
 "        \"valid-lifetime\": 7200\n"
 "    }\n",
-    // CONFIGURATION 19
+    // CONFIGURATION 21
 "{\n"
 "        \"allocator\": \"iterative\",\n"
 "        \"calculate-tee-times\": true,\n"
@@ -4564,7 +5143,7 @@ const char* UNPARSED_CONFIGS[] = {
 "        \"hostname-char-replacement\": \"\",\n"
 "        \"hostname-char-set\": \"[^A-Za-z0-9.-]\",\n"
 "        \"interfaces-config\": {\n"
-"            \"interfaces\": [ \"*\" ],\n"
+"            \"interfaces\": [ ],\n"
 "            \"re-detect\": false\n"
 "        },\n"
 "        \"ip-reservations-unique\": true,\n"
@@ -4577,15 +5156,209 @@ const char* UNPARSED_CONFIGS[] = {
 "            \"packet-queue-size\": 64,\n"
 "            \"thread-pool-size\": 0\n"
 "        },\n"
-"        \"option-data\": [\n"
+"        \"option-data\": [ ],\n"
+"        \"option-def\": [\n"
 "            {\n"
-"                \"always-send\": false,\n"
-"                \"code\": 38,\n"
-"                \"csv-format\": false,\n"
-"                \"data\": \"ABCDEF0105\",\n"
-"                \"name\": \"subscriber-id\",\n"
-"                \"never-send\": false,\n"
-"                \"space\": \"dhcp6\"\n"
+"                \"array\": false,\n"
+"                \"code\": 100,\n"
+"                \"encapsulate\": \"\",\n"
+"                \"name\": \"foo\",\n"
+"                \"record-types\": \"\",\n"
+"                \"space\": \"dhcp6\",\n"
+"                \"type\": \"string\"\n"
+"            }\n"
+"        ],\n"
+"        \"parked-packet-limit\": 256,\n"
+"        \"pd-allocator\": \"iterative\",\n"
+"        \"relay-supplied-options\": [ \"65\" ],\n"
+"        \"reservations-global\": false,\n"
+"        \"reservations-in-subnet\": true,\n"
+"        \"reservations-lookup-first\": false,\n"
+"        \"reservations-out-of-pool\": false,\n"
+"        \"sanity-checks\": {\n"
+"            \"extended-info-checks\": \"fix\",\n"
+"            \"lease-checks\": \"warn\"\n"
+"        },\n"
+"        \"server-id\": {\n"
+"            \"enterprise-id\": 0,\n"
+"            \"htype\": 0,\n"
+"            \"identifier\": \"\",\n"
+"            \"persist\": true,\n"
+"            \"time\": 0,\n"
+"            \"type\": \"LLT\"\n"
+"        },\n"
+"        \"server-tag\": \"\",\n"
+"        \"shared-networks\": [ ],\n"
+"        \"statistic-default-sample-age\": 0,\n"
+"        \"statistic-default-sample-count\": 20,\n"
+"        \"store-extended-info\": false,\n"
+"        \"subnet6\": [ ],\n"
+"        \"t1-percent\": 0.5,\n"
+"        \"t2-percent\": 0.8,\n"
+"        \"valid-lifetime\": 7200\n"
+"    }\n",
+    // CONFIGURATION 22
+"{\n"
+"        \"allocator\": \"iterative\",\n"
+"        \"calculate-tee-times\": true,\n"
+"        \"ddns-conflict-resolution-mode\": \"check-with-dhcid\",\n"
+"        \"ddns-generated-prefix\": \"myhost\",\n"
+"        \"ddns-override-client-update\": false,\n"
+"        \"ddns-override-no-update\": false,\n"
+"        \"ddns-qualifying-suffix\": \"\",\n"
+"        \"ddns-replace-client-name\": \"never\",\n"
+"        \"ddns-send-updates\": true,\n"
+"        \"ddns-update-on-renew\": false,\n"
+"        \"decline-probation-period\": 86400,\n"
+"        \"dhcp-ddns\": {\n"
+"            \"enable-updates\": false,\n"
+"            \"max-queue-size\": 1024,\n"
+"            \"ncr-format\": \"JSON\",\n"
+"            \"ncr-protocol\": \"UDP\",\n"
+"            \"sender-ip\": \"0.0.0.0\",\n"
+"            \"sender-port\": 0,\n"
+"            \"server-ip\": \"127.0.0.1\",\n"
+"            \"server-port\": 53001\n"
+"        },\n"
+"        \"dhcp-queue-control\": {\n"
+"            \"capacity\": 64,\n"
+"            \"enable-queue\": false,\n"
+"            \"queue-type\": \"kea-ring6\"\n"
+"        },\n"
+"        \"dhcp4o6-port\": 0,\n"
+"        \"early-global-reservations-lookup\": false,\n"
+"        \"expired-leases-processing\": {\n"
+"            \"flush-reclaimed-timer-wait-time\": 25,\n"
+"            \"hold-reclaimed-time\": 3600,\n"
+"            \"max-reclaim-leases\": 100,\n"
+"            \"max-reclaim-time\": 250,\n"
+"            \"reclaim-timer-wait-time\": 10,\n"
+"            \"unwarned-reclaim-cycles\": 5\n"
+"        },\n"
+"        \"hooks-libraries\": [ ],\n"
+"        \"host-reservation-identifiers\": [ \"hw-address\", \"duid\" ],\n"
+"        \"hostname-char-replacement\": \"\",\n"
+"        \"hostname-char-set\": \"[^A-Za-z0-9.-]\",\n"
+"        \"interfaces-config\": {\n"
+"            \"interfaces\": [ ],\n"
+"            \"re-detect\": false\n"
+"        },\n"
+"        \"ip-reservations-unique\": true,\n"
+"        \"lease-database\": {\n"
+"            \"type\": \"memfile\"\n"
+"        },\n"
+"        \"mac-sources\": [ \"any\" ],\n"
+"        \"multi-threading\": {\n"
+"            \"enable-multi-threading\": true,\n"
+"            \"packet-queue-size\": 64,\n"
+"            \"thread-pool-size\": 0\n"
+"        },\n"
+"        \"option-data\": [ ],\n"
+"        \"option-def\": [\n"
+"            {\n"
+"                \"array\": false,\n"
+"                \"code\": 63,\n"
+"                \"encapsulate\": \"\",\n"
+"                \"name\": \"geolocation\",\n"
+"                \"record-types\": \"\",\n"
+"                \"space\": \"dhcp6\",\n"
+"                \"type\": \"string\"\n"
+"            }\n"
+"        ],\n"
+"        \"parked-packet-limit\": 256,\n"
+"        \"pd-allocator\": \"iterative\",\n"
+"        \"relay-supplied-options\": [ \"65\" ],\n"
+"        \"reservations-global\": false,\n"
+"        \"reservations-in-subnet\": true,\n"
+"        \"reservations-lookup-first\": false,\n"
+"        \"reservations-out-of-pool\": false,\n"
+"        \"sanity-checks\": {\n"
+"            \"extended-info-checks\": \"fix\",\n"
+"            \"lease-checks\": \"warn\"\n"
+"        },\n"
+"        \"server-id\": {\n"
+"            \"enterprise-id\": 0,\n"
+"            \"htype\": 0,\n"
+"            \"identifier\": \"\",\n"
+"            \"persist\": true,\n"
+"            \"time\": 0,\n"
+"            \"type\": \"LLT\"\n"
+"        },\n"
+"        \"server-tag\": \"\",\n"
+"        \"shared-networks\": [ ],\n"
+"        \"statistic-default-sample-age\": 0,\n"
+"        \"statistic-default-sample-count\": 20,\n"
+"        \"store-extended-info\": false,\n"
+"        \"subnet6\": [ ],\n"
+"        \"t1-percent\": 0.5,\n"
+"        \"t2-percent\": 0.8,\n"
+"        \"valid-lifetime\": 7200\n"
+"    }\n",
+    // CONFIGURATION 23
+"{\n"
+"        \"allocator\": \"iterative\",\n"
+"        \"calculate-tee-times\": true,\n"
+"        \"ddns-conflict-resolution-mode\": \"check-with-dhcid\",\n"
+"        \"ddns-generated-prefix\": \"myhost\",\n"
+"        \"ddns-override-client-update\": false,\n"
+"        \"ddns-override-no-update\": false,\n"
+"        \"ddns-qualifying-suffix\": \"\",\n"
+"        \"ddns-replace-client-name\": \"never\",\n"
+"        \"ddns-send-updates\": true,\n"
+"        \"ddns-update-on-renew\": false,\n"
+"        \"decline-probation-period\": 86400,\n"
+"        \"dhcp-ddns\": {\n"
+"            \"enable-updates\": false,\n"
+"            \"max-queue-size\": 1024,\n"
+"            \"ncr-format\": \"JSON\",\n"
+"            \"ncr-protocol\": \"UDP\",\n"
+"            \"sender-ip\": \"0.0.0.0\",\n"
+"            \"sender-port\": 0,\n"
+"            \"server-ip\": \"127.0.0.1\",\n"
+"            \"server-port\": 53001\n"
+"        },\n"
+"        \"dhcp-queue-control\": {\n"
+"            \"capacity\": 64,\n"
+"            \"enable-queue\": false,\n"
+"            \"queue-type\": \"kea-ring6\"\n"
+"        },\n"
+"        \"dhcp4o6-port\": 0,\n"
+"        \"early-global-reservations-lookup\": false,\n"
+"        \"expired-leases-processing\": {\n"
+"            \"flush-reclaimed-timer-wait-time\": 25,\n"
+"            \"hold-reclaimed-time\": 3600,\n"
+"            \"max-reclaim-leases\": 100,\n"
+"            \"max-reclaim-time\": 250,\n"
+"            \"reclaim-timer-wait-time\": 10,\n"
+"            \"unwarned-reclaim-cycles\": 5\n"
+"        },\n"
+"        \"hooks-libraries\": [ ],\n"
+"        \"host-reservation-identifiers\": [ \"hw-address\", \"duid\" ],\n"
+"        \"hostname-char-replacement\": \"\",\n"
+"        \"hostname-char-set\": \"[^A-Za-z0-9.-]\",\n"
+"        \"interfaces-config\": {\n"
+"            \"interfaces\": [ \"*\" ],\n"
+"            \"re-detect\": false\n"
+"        },\n"
+"        \"ip-reservations-unique\": true,\n"
+"        \"lease-database\": {\n"
+"            \"type\": \"memfile\"\n"
+"        },\n"
+"        \"mac-sources\": [ \"any\" ],\n"
+"        \"multi-threading\": {\n"
+"            \"enable-multi-threading\": true,\n"
+"            \"packet-queue-size\": 64,\n"
+"            \"thread-pool-size\": 0\n"
+"        },\n"
+"        \"option-data\": [\n"
+"            {\n"
+"                \"always-send\": false,\n"
+"                \"code\": 38,\n"
+"                \"csv-format\": false,\n"
+"                \"data\": \"ABCDEF0105\",\n"
+"                \"name\": \"subscriber-id\",\n"
+"                \"never-send\": false,\n"
+"                \"space\": \"dhcp6\"\n"
 "            },\n"
 "            {\n"
 "                \"always-send\": false,\n"
@@ -4662,7 +5435,7 @@ const char* UNPARSED_CONFIGS[] = {
 "        \"t2-percent\": 0.8,\n"
 "        \"valid-lifetime\": 4000\n"
 "    }\n",
-    // CONFIGURATION 20
+    // CONFIGURATION 24
 "{\n"
 "        \"allocator\": \"iterative\",\n"
 "        \"calculate-tee-times\": true,\n"
@@ -4803,7 +5576,7 @@ const char* UNPARSED_CONFIGS[] = {
 "        \"t2-percent\": 0.8,\n"
 "        \"valid-lifetime\": 4000\n"
 "    }\n",
-    // CONFIGURATION 21
+    // CONFIGURATION 25
 "{\n"
 "        \"allocator\": \"iterative\",\n"
 "        \"calculate-tee-times\": true,\n"
@@ -4954,7 +5727,7 @@ const char* UNPARSED_CONFIGS[] = {
 "        \"t2-percent\": 0.8,\n"
 "        \"valid-lifetime\": 4000\n"
 "    }\n",
-    // CONFIGURATION 22
+    // CONFIGURATION 26
 "{\n"
 "        \"allocator\": \"iterative\",\n"
 "        \"calculate-tee-times\": true,\n"
@@ -5082,7 +5855,7 @@ const char* UNPARSED_CONFIGS[] = {
 "        \"t2-percent\": 0.8,\n"
 "        \"valid-lifetime\": 4000\n"
 "    }\n",
-    // CONFIGURATION 23
+    // CONFIGURATION 27
 "{\n"
 "        \"allocator\": \"iterative\",\n"
 "        \"calculate-tee-times\": true,\n"
@@ -5260,7 +6033,7 @@ const char* UNPARSED_CONFIGS[] = {
 "        \"t2-percent\": 0.8,\n"
 "        \"valid-lifetime\": 4000\n"
 "    }\n",
-    // CONFIGURATION 24
+    // CONFIGURATION 28
 "{\n"
 "        \"allocator\": \"iterative\",\n"
 "        \"calculate-tee-times\": true,\n"
@@ -5316,7 +6089,17 @@ const char* UNPARSED_CONFIGS[] = {
 "            \"packet-queue-size\": 64,\n"
 "            \"thread-pool-size\": 0\n"
 "        },\n"
-"        \"option-data\": [ ],\n"
+"        \"option-data\": [\n"
+"            {\n"
+"                \"always-send\": false,\n"
+"                \"code\": 38,\n"
+"                \"csv-format\": false,\n"
+"                \"data\": \"AB\",\n"
+"                \"name\": \"subscriber-id\",\n"
+"                \"never-send\": false,\n"
+"                \"space\": \"dhcp6\"\n"
+"            }\n"
+"        ],\n"
 "        \"option-def\": [ ],\n"
 "        \"parked-packet-limit\": 256,\n"
 "        \"pd-allocator\": \"iterative\",\n"
@@ -5359,10 +6142,19 @@ const char* UNPARSED_CONFIGS[] = {
 "                        \"always-send\": false,\n"
 "                        \"code\": 38,\n"
 "                        \"csv-format\": false,\n"
-"                        \"data\": \"0102030405060708090A\",\n"
+"                        \"data\": \"ABCDEF0105\",\n"
 "                        \"name\": \"subscriber-id\",\n"
 "                        \"never-send\": false,\n"
 "                        \"space\": \"dhcp6\"\n"
+"                    },\n"
+"                    {\n"
+"                        \"always-send\": false,\n"
+"                        \"code\": 15,\n"
+"                        \"csv-format\": false,\n"
+"                        \"data\": \"FFFEFDFCFB\",\n"
+"                        \"name\": \"user-class\",\n"
+"                        \"never-send\": false,\n"
+"                        \"space\": \"dhcp6\"\n"
 "                    }\n"
 "                ],\n"
 "                \"pd-allocator\": \"iterative\",\n"
@@ -5386,54 +6178,13 @@ const char* UNPARSED_CONFIGS[] = {
 "                \"t1-percent\": 0.5,\n"
 "                \"t2-percent\": 0.8,\n"
 "                \"valid-lifetime\": 4000\n"
-"            },\n"
-"            {\n"
-"                \"allocator\": \"iterative\",\n"
-"                \"calculate-tee-times\": true,\n"
-"                \"id\": 2,\n"
-"                \"max-preferred-lifetime\": 3000,\n"
-"                \"max-valid-lifetime\": 4000,\n"
-"                \"min-preferred-lifetime\": 3000,\n"
-"                \"min-valid-lifetime\": 4000,\n"
-"                \"option-data\": [\n"
-"                    {\n"
-"                        \"always-send\": false,\n"
-"                        \"code\": 15,\n"
-"                        \"csv-format\": false,\n"
-"                        \"data\": \"FFFEFDFCFB\",\n"
-"                        \"name\": \"user-class\",\n"
-"                        \"never-send\": false,\n"
-"                        \"space\": \"dhcp6\"\n"
-"                    }\n"
-"                ],\n"
-"                \"pd-allocator\": \"iterative\",\n"
-"                \"pd-pools\": [ ],\n"
-"                \"pools\": [\n"
-"                    {\n"
-"                        \"option-data\": [ ],\n"
-"                        \"pool\": \"2001:db8:2::/80\"\n"
-"                    }\n"
-"                ],\n"
-"                \"preferred-lifetime\": 3000,\n"
-"                \"rapid-commit\": false,\n"
-"                \"rebind-timer\": 2000,\n"
-"                \"relay\": {\n"
-"                    \"ip-addresses\": [ ]\n"
-"                },\n"
-"                \"renew-timer\": 1000,\n"
-"                \"reservations\": [ ],\n"
-"                \"store-extended-info\": false,\n"
-"                \"subnet\": \"2001:db8:2::/64\",\n"
-"                \"t1-percent\": 0.5,\n"
-"                \"t2-percent\": 0.8,\n"
-"                \"valid-lifetime\": 4000\n"
 "            }\n"
 "        ],\n"
 "        \"t1-percent\": 0.5,\n"
 "        \"t2-percent\": 0.8,\n"
 "        \"valid-lifetime\": 4000\n"
 "    }\n",
-    // CONFIGURATION 25
+    // CONFIGURATION 29
 "{\n"
 "        \"allocator\": \"iterative\",\n"
 "        \"calculate-tee-times\": true,\n"
@@ -5527,70 +6278,64 @@ const char* UNPARSED_CONFIGS[] = {
 "                \"max-valid-lifetime\": 4000,\n"
 "                \"min-preferred-lifetime\": 3000,\n"
 "                \"min-valid-lifetime\": 4000,\n"
-"                \"option-data\": [ ],\n"
+"                \"option-data\": [\n"
+"                    {\n"
+"                        \"always-send\": false,\n"
+"                        \"code\": 38,\n"
+"                        \"csv-format\": false,\n"
+"                        \"data\": \"0102030405060708090A\",\n"
+"                        \"name\": \"subscriber-id\",\n"
+"                        \"never-send\": false,\n"
+"                        \"space\": \"dhcp6\"\n"
+"                    }\n"
+"                ],\n"
 "                \"pd-allocator\": \"iterative\",\n"
-"                \"pd-pools\": [\n"
+"                \"pd-pools\": [ ],\n"
+"                \"pools\": [\n"
 "                    {\n"
-"                        \"delegated-len\": 64,\n"
-"                        \"option-data\": [\n"
-"                            {\n"
-"                                \"always-send\": false,\n"
-"                                \"code\": 38,\n"
-"                                \"csv-format\": false,\n"
-"                                \"data\": \"112233445566\",\n"
-"                                \"name\": \"subscriber-id\",\n"
-"                                \"never-send\": false,\n"
-"                                \"space\": \"dhcp6\"\n"
-"                            }\n"
-"                        ],\n"
-"                        \"prefix\": \"3000::\",\n"
-"                        \"prefix-len\": 48\n"
-"                    },\n"
+"                        \"option-data\": [ ],\n"
+"                        \"pool\": \"2001:db8:1::/80\"\n"
+"                    }\n"
+"                ],\n"
+"                \"preferred-lifetime\": 3000,\n"
+"                \"rapid-commit\": false,\n"
+"                \"rebind-timer\": 2000,\n"
+"                \"relay\": {\n"
+"                    \"ip-addresses\": [ ]\n"
+"                },\n"
+"                \"renew-timer\": 1000,\n"
+"                \"reservations\": [ ],\n"
+"                \"store-extended-info\": false,\n"
+"                \"subnet\": \"2001:db8:1::/64\",\n"
+"                \"t1-percent\": 0.5,\n"
+"                \"t2-percent\": 0.8,\n"
+"                \"valid-lifetime\": 4000\n"
+"            },\n"
+"            {\n"
+"                \"allocator\": \"iterative\",\n"
+"                \"calculate-tee-times\": true,\n"
+"                \"id\": 2,\n"
+"                \"max-preferred-lifetime\": 3000,\n"
+"                \"max-valid-lifetime\": 4000,\n"
+"                \"min-preferred-lifetime\": 3000,\n"
+"                \"min-valid-lifetime\": 4000,\n"
+"                \"option-data\": [\n"
 "                    {\n"
-"                        \"delegated-len\": 64,\n"
-"                        \"option-data\": [\n"
-"                            {\n"
-"                                \"always-send\": false,\n"
-"                                \"code\": 15,\n"
-"                                \"csv-format\": false,\n"
-"                                \"data\": \"AABBCCDDEE\",\n"
-"                                \"name\": \"user-class\",\n"
-"                                \"never-send\": false,\n"
-"                                \"space\": \"dhcp6\"\n"
-"                            }\n"
-"                        ],\n"
-"                        \"prefix\": \"3001::\",\n"
-"                        \"prefix-len\": 48\n"
+"                        \"always-send\": false,\n"
+"                        \"code\": 15,\n"
+"                        \"csv-format\": false,\n"
+"                        \"data\": \"FFFEFDFCFB\",\n"
+"                        \"name\": \"user-class\",\n"
+"                        \"never-send\": false,\n"
+"                        \"space\": \"dhcp6\"\n"
 "                    }\n"
 "                ],\n"
+"                \"pd-allocator\": \"iterative\",\n"
+"                \"pd-pools\": [ ],\n"
 "                \"pools\": [\n"
 "                    {\n"
-"                        \"option-data\": [\n"
-"                            {\n"
-"                                \"always-send\": false,\n"
-"                                \"code\": 38,\n"
-"                                \"csv-format\": false,\n"
-"                                \"data\": \"0102030405060708090A\",\n"
-"                                \"name\": \"subscriber-id\",\n"
-"                                \"never-send\": false,\n"
-"                                \"space\": \"dhcp6\"\n"
-"                            }\n"
-"                        ],\n"
-"                        \"pool\": \"2001:db8:1::10-2001:db8:1::100\"\n"
-"                    },\n"
-"                    {\n"
-"                        \"option-data\": [\n"
-"                            {\n"
-"                                \"always-send\": false,\n"
-"                                \"code\": 15,\n"
-"                                \"csv-format\": false,\n"
-"                                \"data\": \"FFFEFDFCFB\",\n"
-"                                \"name\": \"user-class\",\n"
-"                                \"never-send\": false,\n"
-"                                \"space\": \"dhcp6\"\n"
-"                            }\n"
-"                        ],\n"
-"                        \"pool\": \"2001:db8:1::300-2001:db8:1::400\"\n"
+"                        \"option-data\": [ ],\n"
+"                        \"pool\": \"2001:db8:2::/80\"\n"
 "                    }\n"
 "                ],\n"
 "                \"preferred-lifetime\": 3000,\n"
@@ -5602,7 +6347,7 @@ const char* UNPARSED_CONFIGS[] = {
 "                \"renew-timer\": 1000,\n"
 "                \"reservations\": [ ],\n"
 "                \"store-extended-info\": false,\n"
-"                \"subnet\": \"2001:db8:1::/64\",\n"
+"                \"subnet\": \"2001:db8:2::/64\",\n"
 "                \"t1-percent\": 0.5,\n"
 "                \"t2-percent\": 0.8,\n"
 "                \"valid-lifetime\": 4000\n"
@@ -5612,7 +6357,7 @@ const char* UNPARSED_CONFIGS[] = {
 "        \"t2-percent\": 0.8,\n"
 "        \"valid-lifetime\": 4000\n"
 "    }\n",
-    // CONFIGURATION 26
+    // CONFIGURATION 30
 "{\n"
 "        \"allocator\": \"iterative\",\n"
 "        \"calculate-tee-times\": true,\n"
@@ -5668,24 +6413,7 @@ const char* UNPARSED_CONFIGS[] = {
 "            \"packet-queue-size\": 64,\n"
 "            \"thread-pool-size\": 0\n"
 "        },\n"
-"        \"option-data\": [\n"
-"            {\n"
-"                \"always-send\": false,\n"
-"                \"code\": 100,\n"
-"                \"csv-format\": false,\n"
-"                \"data\": \"1234\",\n"
-"                \"never-send\": false,\n"
-"                \"space\": \"vendor-1234\"\n"
-"            },\n"
-"            {\n"
-"                \"always-send\": false,\n"
-"                \"code\": 100,\n"
-"                \"csv-format\": false,\n"
-"                \"data\": \"ABCDEF0105\",\n"
-"                \"never-send\": false,\n"
-"                \"space\": \"vendor-4491\"\n"
-"            }\n"
-"        ],\n"
+"        \"option-data\": [ ],\n"
 "        \"option-def\": [ ],\n"
 "        \"parked-packet-limit\": 256,\n"
 "        \"pd-allocator\": \"iterative\",\n"
@@ -5728,8 +6456,27 @@ const char* UNPARSED_CONFIGS[] = {
 "                \"pd-pools\": [ ],\n"
 "                \"pools\": [\n"
 "                    {\n"
-"                        \"option-data\": [ ],\n"
-"                        \"pool\": \"2001:db8:1::/80\"\n"
+"                        \"option-data\": [\n"
+"                            {\n"
+"                                \"always-send\": false,\n"
+"                                \"code\": 38,\n"
+"                                \"csv-format\": false,\n"
+"                                \"data\": \"0102030405060708090A\",\n"
+"                                \"name\": \"subscriber-id\",\n"
+"                                \"never-send\": false,\n"
+"                                \"space\": \"dhcp6\"\n"
+"                            },\n"
+"                            {\n"
+"                                \"always-send\": false,\n"
+"                                \"code\": 15,\n"
+"                                \"csv-format\": false,\n"
+"                                \"data\": \"FFFEFDFCFB\",\n"
+"                                \"name\": \"user-class\",\n"
+"                                \"never-send\": false,\n"
+"                                \"space\": \"dhcp6\"\n"
+"                            }\n"
+"                        ],\n"
+"                        \"pool\": \"2001:db8:1::10-2001:db8:1::100\"\n"
 "                    }\n"
 "                ],\n"
 "                \"preferred-lifetime\": 3000,\n"
@@ -5751,7 +6498,7 @@ const char* UNPARSED_CONFIGS[] = {
 "        \"t2-percent\": 0.8,\n"
 "        \"valid-lifetime\": 4000\n"
 "    }\n",
-    // CONFIGURATION 27
+    // CONFIGURATION 31
 "{\n"
 "        \"allocator\": \"iterative\",\n"
 "        \"calculate-tee-times\": true,\n"
@@ -5807,28 +6554,8 @@ const char* UNPARSED_CONFIGS[] = {
 "            \"packet-queue-size\": 64,\n"
 "            \"thread-pool-size\": 0\n"
 "        },\n"
-"        \"option-data\": [\n"
-"            {\n"
-"                \"always-send\": false,\n"
-"                \"code\": 100,\n"
-"                \"csv-format\": true,\n"
-"                \"data\": \"this is a string vendor-opt\",\n"
-"                \"name\": \"foo\",\n"
-"                \"never-send\": false,\n"
-"                \"space\": \"vendor-4491\"\n"
-"            }\n"
-"        ],\n"
-"        \"option-def\": [\n"
-"            {\n"
-"                \"array\": false,\n"
-"                \"code\": 100,\n"
-"                \"encapsulate\": \"\",\n"
-"                \"name\": \"foo\",\n"
-"                \"record-types\": \"\",\n"
-"                \"space\": \"vendor-4491\",\n"
-"                \"type\": \"string\"\n"
-"            }\n"
-"        ],\n"
+"        \"option-data\": [ ],\n"
+"        \"option-def\": [ ],\n"
 "        \"parked-packet-limit\": 256,\n"
 "        \"pd-allocator\": \"iterative\",\n"
 "        \"preferred-lifetime\": 3000,\n"
@@ -5867,37 +6594,94 @@ const char* UNPARSED_CONFIGS[] = {
 "                \"min-valid-lifetime\": 4000,\n"
 "                \"option-data\": [ ],\n"
 "                \"pd-allocator\": \"iterative\",\n"
-"                \"pd-pools\": [ ],\n"
-"                \"pools\": [\n"
+"                \"pd-pools\": [\n"
 "                    {\n"
-"                        \"option-data\": [ ],\n"
-"                        \"pool\": \"2001:db8:1::/80\"\n"
+"                        \"delegated-len\": 64,\n"
+"                        \"option-data\": [\n"
+"                            {\n"
+"                                \"always-send\": false,\n"
+"                                \"code\": 38,\n"
+"                                \"csv-format\": false,\n"
+"                                \"data\": \"112233445566\",\n"
+"                                \"name\": \"subscriber-id\",\n"
+"                                \"never-send\": false,\n"
+"                                \"space\": \"dhcp6\"\n"
+"                            }\n"
+"                        ],\n"
+"                        \"prefix\": \"3000::\",\n"
+"                        \"prefix-len\": 48\n"
+"                    },\n"
+"                    {\n"
+"                        \"delegated-len\": 64,\n"
+"                        \"option-data\": [\n"
+"                            {\n"
+"                                \"always-send\": false,\n"
+"                                \"code\": 15,\n"
+"                                \"csv-format\": false,\n"
+"                                \"data\": \"AABBCCDDEE\",\n"
+"                                \"name\": \"user-class\",\n"
+"                                \"never-send\": false,\n"
+"                                \"space\": \"dhcp6\"\n"
+"                            }\n"
+"                        ],\n"
+"                        \"prefix\": \"3001::\",\n"
+"                        \"prefix-len\": 48\n"
 "                    }\n"
 "                ],\n"
-"                \"preferred-lifetime\": 3000,\n"
-"                \"rapid-commit\": false,\n"
-"                \"rebind-timer\": 2000,\n"
-"                \"relay\": {\n"
-"                    \"ip-addresses\": [ ]\n"
-"                },\n"
-"                \"renew-timer\": 1000,\n"
-"                \"reservations\": [ ],\n"
-"                \"store-extended-info\": false,\n"
-"                \"subnet\": \"2001:db8:1::/64\",\n"
-"                \"t1-percent\": 0.5,\n"
-"                \"t2-percent\": 0.8,\n"
-"                \"valid-lifetime\": 4000\n"
-"            }\n"
-"        ],\n"
-"        \"t1-percent\": 0.5,\n"
-"        \"t2-percent\": 0.8,\n"
-"        \"valid-lifetime\": 4000\n"
-"    }\n",
-    // CONFIGURATION 28
-"{\n"
-"        \"allocator\": \"iterative\",\n"
-"        \"calculate-tee-times\": true,\n"
-"        \"ddns-conflict-resolution-mode\": \"check-with-dhcid\",\n"
+"                \"pools\": [\n"
+"                    {\n"
+"                        \"option-data\": [\n"
+"                            {\n"
+"                                \"always-send\": false,\n"
+"                                \"code\": 38,\n"
+"                                \"csv-format\": false,\n"
+"                                \"data\": \"0102030405060708090A\",\n"
+"                                \"name\": \"subscriber-id\",\n"
+"                                \"never-send\": false,\n"
+"                                \"space\": \"dhcp6\"\n"
+"                            }\n"
+"                        ],\n"
+"                        \"pool\": \"2001:db8:1::10-2001:db8:1::100\"\n"
+"                    },\n"
+"                    {\n"
+"                        \"option-data\": [\n"
+"                            {\n"
+"                                \"always-send\": false,\n"
+"                                \"code\": 15,\n"
+"                                \"csv-format\": false,\n"
+"                                \"data\": \"FFFEFDFCFB\",\n"
+"                                \"name\": \"user-class\",\n"
+"                                \"never-send\": false,\n"
+"                                \"space\": \"dhcp6\"\n"
+"                            }\n"
+"                        ],\n"
+"                        \"pool\": \"2001:db8:1::300-2001:db8:1::400\"\n"
+"                    }\n"
+"                ],\n"
+"                \"preferred-lifetime\": 3000,\n"
+"                \"rapid-commit\": false,\n"
+"                \"rebind-timer\": 2000,\n"
+"                \"relay\": {\n"
+"                    \"ip-addresses\": [ ]\n"
+"                },\n"
+"                \"renew-timer\": 1000,\n"
+"                \"reservations\": [ ],\n"
+"                \"store-extended-info\": false,\n"
+"                \"subnet\": \"2001:db8:1::/64\",\n"
+"                \"t1-percent\": 0.5,\n"
+"                \"t2-percent\": 0.8,\n"
+"                \"valid-lifetime\": 4000\n"
+"            }\n"
+"        ],\n"
+"        \"t1-percent\": 0.5,\n"
+"        \"t2-percent\": 0.8,\n"
+"        \"valid-lifetime\": 4000\n"
+"    }\n",
+    // CONFIGURATION 32
+"{\n"
+"        \"allocator\": \"iterative\",\n"
+"        \"calculate-tee-times\": true,\n"
+"        \"ddns-conflict-resolution-mode\": \"check-with-dhcid\",\n"
 "        \"ddns-generated-prefix\": \"myhost\",\n"
 "        \"ddns-override-client-update\": false,\n"
 "        \"ddns-override-no-update\": false,\n"
@@ -5936,7 +6720,7 @@ const char* UNPARSED_CONFIGS[] = {
 "        \"hostname-char-replacement\": \"\",\n"
 "        \"hostname-char-set\": \"[^A-Za-z0-9.-]\",\n"
 "        \"interfaces-config\": {\n"
-"            \"interfaces\": [ \"eth0\" ],\n"
+"            \"interfaces\": [ \"*\" ],\n"
 "            \"re-detect\": false\n"
 "        },\n"
 "        \"ip-reservations-unique\": true,\n"
@@ -5949,7 +6733,24 @@ const char* UNPARSED_CONFIGS[] = {
 "            \"packet-queue-size\": 64,\n"
 "            \"thread-pool-size\": 0\n"
 "        },\n"
-"        \"option-data\": [ ],\n"
+"        \"option-data\": [\n"
+"            {\n"
+"                \"always-send\": false,\n"
+"                \"code\": 100,\n"
+"                \"csv-format\": false,\n"
+"                \"data\": \"1234\",\n"
+"                \"never-send\": false,\n"
+"                \"space\": \"vendor-1234\"\n"
+"            },\n"
+"            {\n"
+"                \"always-send\": false,\n"
+"                \"code\": 100,\n"
+"                \"csv-format\": false,\n"
+"                \"data\": \"ABCDEF0105\",\n"
+"                \"never-send\": false,\n"
+"                \"space\": \"vendor-4491\"\n"
+"            }\n"
+"        ],\n"
 "        \"option-def\": [ ],\n"
 "        \"parked-packet-limit\": 256,\n"
 "        \"pd-allocator\": \"iterative\",\n"
@@ -5978,12 +6779,44 @@ const char* UNPARSED_CONFIGS[] = {
 "        \"statistic-default-sample-age\": 0,\n"
 "        \"statistic-default-sample-count\": 20,\n"
 "        \"store-extended-info\": false,\n"
-"        \"subnet6\": [ ],\n"
+"        \"subnet6\": [\n"
+"            {\n"
+"                \"allocator\": \"iterative\",\n"
+"                \"calculate-tee-times\": true,\n"
+"                \"id\": 1,\n"
+"                \"max-preferred-lifetime\": 3000,\n"
+"                \"max-valid-lifetime\": 4000,\n"
+"                \"min-preferred-lifetime\": 3000,\n"
+"                \"min-valid-lifetime\": 4000,\n"
+"                \"option-data\": [ ],\n"
+"                \"pd-allocator\": \"iterative\",\n"
+"                \"pd-pools\": [ ],\n"
+"                \"pools\": [\n"
+"                    {\n"
+"                        \"option-data\": [ ],\n"
+"                        \"pool\": \"2001:db8:1::/80\"\n"
+"                    }\n"
+"                ],\n"
+"                \"preferred-lifetime\": 3000,\n"
+"                \"rapid-commit\": false,\n"
+"                \"rebind-timer\": 2000,\n"
+"                \"relay\": {\n"
+"                    \"ip-addresses\": [ ]\n"
+"                },\n"
+"                \"renew-timer\": 1000,\n"
+"                \"reservations\": [ ],\n"
+"                \"store-extended-info\": false,\n"
+"                \"subnet\": \"2001:db8:1::/64\",\n"
+"                \"t1-percent\": 0.5,\n"
+"                \"t2-percent\": 0.8,\n"
+"                \"valid-lifetime\": 4000\n"
+"            }\n"
+"        ],\n"
 "        \"t1-percent\": 0.5,\n"
 "        \"t2-percent\": 0.8,\n"
 "        \"valid-lifetime\": 4000\n"
 "    }\n",
-    // CONFIGURATION 29
+    // CONFIGURATION 33
 "{\n"
 "        \"allocator\": \"iterative\",\n"
 "        \"calculate-tee-times\": true,\n"
@@ -6026,7 +6859,7 @@ const char* UNPARSED_CONFIGS[] = {
 "        \"hostname-char-replacement\": \"\",\n"
 "        \"hostname-char-set\": \"[^A-Za-z0-9.-]\",\n"
 "        \"interfaces-config\": {\n"
-"            \"interfaces\": [ \"*\", \"eth0\", \"eth1\" ],\n"
+"            \"interfaces\": [ \"*\" ],\n"
 "            \"re-detect\": false\n"
 "        },\n"
 "        \"ip-reservations-unique\": true,\n"
@@ -6039,8 +6872,28 @@ const char* UNPARSED_CONFIGS[] = {
 "            \"packet-queue-size\": 64,\n"
 "            \"thread-pool-size\": 0\n"
 "        },\n"
-"        \"option-data\": [ ],\n"
-"        \"option-def\": [ ],\n"
+"        \"option-data\": [\n"
+"            {\n"
+"                \"always-send\": false,\n"
+"                \"code\": 100,\n"
+"                \"csv-format\": true,\n"
+"                \"data\": \"this is a string vendor-opt\",\n"
+"                \"name\": \"foo\",\n"
+"                \"never-send\": false,\n"
+"                \"space\": \"vendor-4491\"\n"
+"            }\n"
+"        ],\n"
+"        \"option-def\": [\n"
+"            {\n"
+"                \"array\": false,\n"
+"                \"code\": 100,\n"
+"                \"encapsulate\": \"\",\n"
+"                \"name\": \"foo\",\n"
+"                \"record-types\": \"\",\n"
+"                \"space\": \"vendor-4491\",\n"
+"                \"type\": \"string\"\n"
+"            }\n"
+"        ],\n"
 "        \"parked-packet-limit\": 256,\n"
 "        \"pd-allocator\": \"iterative\",\n"
 "        \"preferred-lifetime\": 3000,\n"
@@ -6068,12 +6921,44 @@ const char* UNPARSED_CONFIGS[] = {
 "        \"statistic-default-sample-age\": 0,\n"
 "        \"statistic-default-sample-count\": 20,\n"
 "        \"store-extended-info\": false,\n"
-"        \"subnet6\": [ ],\n"
+"        \"subnet6\": [\n"
+"            {\n"
+"                \"allocator\": \"iterative\",\n"
+"                \"calculate-tee-times\": true,\n"
+"                \"id\": 1,\n"
+"                \"max-preferred-lifetime\": 3000,\n"
+"                \"max-valid-lifetime\": 4000,\n"
+"                \"min-preferred-lifetime\": 3000,\n"
+"                \"min-valid-lifetime\": 4000,\n"
+"                \"option-data\": [ ],\n"
+"                \"pd-allocator\": \"iterative\",\n"
+"                \"pd-pools\": [ ],\n"
+"                \"pools\": [\n"
+"                    {\n"
+"                        \"option-data\": [ ],\n"
+"                        \"pool\": \"2001:db8:1::/80\"\n"
+"                    }\n"
+"                ],\n"
+"                \"preferred-lifetime\": 3000,\n"
+"                \"rapid-commit\": false,\n"
+"                \"rebind-timer\": 2000,\n"
+"                \"relay\": {\n"
+"                    \"ip-addresses\": [ ]\n"
+"                },\n"
+"                \"renew-timer\": 1000,\n"
+"                \"reservations\": [ ],\n"
+"                \"store-extended-info\": false,\n"
+"                \"subnet\": \"2001:db8:1::/64\",\n"
+"                \"t1-percent\": 0.5,\n"
+"                \"t2-percent\": 0.8,\n"
+"                \"valid-lifetime\": 4000\n"
+"            }\n"
+"        ],\n"
 "        \"t1-percent\": 0.5,\n"
 "        \"t2-percent\": 0.8,\n"
 "        \"valid-lifetime\": 4000\n"
 "    }\n",
-    // CONFIGURATION 30
+    // CONFIGURATION 34
 "{\n"
 "        \"allocator\": \"iterative\",\n"
 "        \"calculate-tee-times\": true,\n"
@@ -6116,7 +7001,7 @@ const char* UNPARSED_CONFIGS[] = {
 "        \"hostname-char-replacement\": \"\",\n"
 "        \"hostname-char-set\": \"[^A-Za-z0-9.-]\",\n"
 "        \"interfaces-config\": {\n"
-"            \"interfaces\": [ \"*\" ],\n"
+"            \"interfaces\": [ \"eth0\" ],\n"
 "            \"re-detect\": false\n"
 "        },\n"
 "        \"ip-reservations-unique\": true,\n"
@@ -6158,44 +7043,12 @@ const char* UNPARSED_CONFIGS[] = {
 "        \"statistic-default-sample-age\": 0,\n"
 "        \"statistic-default-sample-count\": 20,\n"
 "        \"store-extended-info\": false,\n"
-"        \"subnet6\": [\n"
-"            {\n"
-"                \"allocator\": \"iterative\",\n"
-"                \"calculate-tee-times\": true,\n"
-"                \"id\": 1,\n"
-"                \"max-preferred-lifetime\": 3000,\n"
-"                \"max-valid-lifetime\": 4000,\n"
-"                \"min-preferred-lifetime\": 3000,\n"
-"                \"min-valid-lifetime\": 4000,\n"
-"                \"option-data\": [ ],\n"
-"                \"pd-allocator\": \"iterative\",\n"
-"                \"pd-pools\": [ ],\n"
-"                \"pools\": [\n"
-"                    {\n"
-"                        \"option-data\": [ ],\n"
-"                        \"pool\": \"2001:db8:1::1-2001:db8:1::ffff\"\n"
-"                    }\n"
-"                ],\n"
-"                \"preferred-lifetime\": 3000,\n"
-"                \"rapid-commit\": false,\n"
-"                \"rebind-timer\": 2000,\n"
-"                \"relay\": {\n"
-"                    \"ip-addresses\": [ \"2001:db8:1::abcd\" ]\n"
-"                },\n"
-"                \"renew-timer\": 1000,\n"
-"                \"reservations\": [ ],\n"
-"                \"store-extended-info\": false,\n"
-"                \"subnet\": \"2001:db8:1::/64\",\n"
-"                \"t1-percent\": 0.5,\n"
-"                \"t2-percent\": 0.8,\n"
-"                \"valid-lifetime\": 4000\n"
-"            }\n"
-"        ],\n"
+"        \"subnet6\": [ ],\n"
 "        \"t1-percent\": 0.5,\n"
 "        \"t2-percent\": 0.8,\n"
 "        \"valid-lifetime\": 4000\n"
 "    }\n",
-    // CONFIGURATION 31
+    // CONFIGURATION 35
 "{\n"
 "        \"allocator\": \"iterative\",\n"
 "        \"calculate-tee-times\": true,\n"
@@ -6238,7 +7091,7 @@ const char* UNPARSED_CONFIGS[] = {
 "        \"hostname-char-replacement\": \"\",\n"
 "        \"hostname-char-set\": \"[^A-Za-z0-9.-]\",\n"
 "        \"interfaces-config\": {\n"
-"            \"interfaces\": [ \"*\" ],\n"
+"            \"interfaces\": [ \"*\", \"eth0\", \"eth1\" ],\n"
 "            \"re-detect\": false\n"
 "        },\n"
 "        \"ip-reservations-unique\": true,\n"
@@ -6280,44 +7133,12 @@ const char* UNPARSED_CONFIGS[] = {
 "        \"statistic-default-sample-age\": 0,\n"
 "        \"statistic-default-sample-count\": 20,\n"
 "        \"store-extended-info\": false,\n"
-"        \"subnet6\": [\n"
-"            {\n"
-"                \"allocator\": \"iterative\",\n"
-"                \"calculate-tee-times\": true,\n"
-"                \"id\": 1,\n"
-"                \"max-preferred-lifetime\": 3000,\n"
-"                \"max-valid-lifetime\": 4000,\n"
-"                \"min-preferred-lifetime\": 3000,\n"
-"                \"min-valid-lifetime\": 4000,\n"
-"                \"option-data\": [ ],\n"
-"                \"pd-allocator\": \"iterative\",\n"
-"                \"pd-pools\": [ ],\n"
-"                \"pools\": [\n"
-"                    {\n"
-"                        \"option-data\": [ ],\n"
-"                        \"pool\": \"2001:db8:1::1-2001:db8:1::ffff\"\n"
-"                    }\n"
-"                ],\n"
-"                \"preferred-lifetime\": 3000,\n"
-"                \"rapid-commit\": false,\n"
-"                \"rebind-timer\": 2000,\n"
-"                \"relay\": {\n"
-"                    \"ip-addresses\": [ \"2001:db9::abcd\", \"2001:db9::abce\" ]\n"
-"                },\n"
-"                \"renew-timer\": 1000,\n"
-"                \"reservations\": [ ],\n"
-"                \"store-extended-info\": false,\n"
-"                \"subnet\": \"2001:db8:1::/64\",\n"
-"                \"t1-percent\": 0.5,\n"
-"                \"t2-percent\": 0.8,\n"
-"                \"valid-lifetime\": 4000\n"
-"            }\n"
-"        ],\n"
+"        \"subnet6\": [ ],\n"
 "        \"t1-percent\": 0.5,\n"
 "        \"t2-percent\": 0.8,\n"
 "        \"valid-lifetime\": 4000\n"
 "    }\n",
-    // CONFIGURATION 32
+    // CONFIGURATION 36
 "{\n"
 "        \"allocator\": \"iterative\",\n"
 "        \"calculate-tee-times\": true,\n"
@@ -6406,24 +7227,268 @@ const char* UNPARSED_CONFIGS[] = {
 "            {\n"
 "                \"allocator\": \"iterative\",\n"
 "                \"calculate-tee-times\": true,\n"
-"                \"client-class\": \"alpha\",\n"
 "                \"id\": 1,\n"
 "                \"max-preferred-lifetime\": 3000,\n"
-"                \"max-valid-lifetime\": 4000,\n"
+"                \"max-valid-lifetime\": 4,\n"
 "                \"min-preferred-lifetime\": 3000,\n"
-"                \"min-valid-lifetime\": 4000,\n"
+"                \"min-valid-lifetime\": 4,\n"
 "                \"option-data\": [ ],\n"
 "                \"pd-allocator\": \"iterative\",\n"
 "                \"pd-pools\": [ ],\n"
 "                \"pools\": [\n"
 "                    {\n"
 "                        \"option-data\": [ ],\n"
-"                        \"pool\": \"2001:db8:1::/80\"\n"
+"                        \"pool\": \"2001:db8:1::1-2001:db8:1::ffff\"\n"
 "                    }\n"
 "                ],\n"
 "                \"preferred-lifetime\": 3000,\n"
 "                \"rapid-commit\": false,\n"
-"                \"rebind-timer\": 2000,\n"
+"                \"rebind-timer\": 2,\n"
+"                \"relay\": {\n"
+"                    \"ip-addresses\": [ \"2001:db8:1::abcd\" ]\n"
+"                },\n"
+"                \"renew-timer\": 1,\n"
+"                \"reservations\": [ ],\n"
+"                \"store-extended-info\": false,\n"
+"                \"subnet\": \"2001:db8:1::/64\",\n"
+"                \"t1-percent\": 0.5,\n"
+"                \"t2-percent\": 0.8,\n"
+"                \"valid-lifetime\": 4\n"
+"            }\n"
+"        ],\n"
+"        \"t1-percent\": 0.5,\n"
+"        \"t2-percent\": 0.8,\n"
+"        \"valid-lifetime\": 4000\n"
+"    }\n",
+    // CONFIGURATION 37
+"{\n"
+"        \"allocator\": \"iterative\",\n"
+"        \"calculate-tee-times\": true,\n"
+"        \"ddns-conflict-resolution-mode\": \"check-with-dhcid\",\n"
+"        \"ddns-generated-prefix\": \"myhost\",\n"
+"        \"ddns-override-client-update\": false,\n"
+"        \"ddns-override-no-update\": false,\n"
+"        \"ddns-qualifying-suffix\": \"\",\n"
+"        \"ddns-replace-client-name\": \"never\",\n"
+"        \"ddns-send-updates\": true,\n"
+"        \"ddns-update-on-renew\": false,\n"
+"        \"decline-probation-period\": 86400,\n"
+"        \"dhcp-ddns\": {\n"
+"            \"enable-updates\": false,\n"
+"            \"max-queue-size\": 1024,\n"
+"            \"ncr-format\": \"JSON\",\n"
+"            \"ncr-protocol\": \"UDP\",\n"
+"            \"sender-ip\": \"0.0.0.0\",\n"
+"            \"sender-port\": 0,\n"
+"            \"server-ip\": \"127.0.0.1\",\n"
+"            \"server-port\": 53001\n"
+"        },\n"
+"        \"dhcp-queue-control\": {\n"
+"            \"capacity\": 64,\n"
+"            \"enable-queue\": false,\n"
+"            \"queue-type\": \"kea-ring6\"\n"
+"        },\n"
+"        \"dhcp4o6-port\": 0,\n"
+"        \"early-global-reservations-lookup\": false,\n"
+"        \"expired-leases-processing\": {\n"
+"            \"flush-reclaimed-timer-wait-time\": 25,\n"
+"            \"hold-reclaimed-time\": 3600,\n"
+"            \"max-reclaim-leases\": 100,\n"
+"            \"max-reclaim-time\": 250,\n"
+"            \"reclaim-timer-wait-time\": 10,\n"
+"            \"unwarned-reclaim-cycles\": 5\n"
+"        },\n"
+"        \"hooks-libraries\": [ ],\n"
+"        \"host-reservation-identifiers\": [ \"hw-address\", \"duid\" ],\n"
+"        \"hostname-char-replacement\": \"\",\n"
+"        \"hostname-char-set\": \"[^A-Za-z0-9.-]\",\n"
+"        \"interfaces-config\": {\n"
+"            \"interfaces\": [ \"*\" ],\n"
+"            \"re-detect\": false\n"
+"        },\n"
+"        \"ip-reservations-unique\": true,\n"
+"        \"lease-database\": {\n"
+"            \"type\": \"memfile\"\n"
+"        },\n"
+"        \"mac-sources\": [ \"any\" ],\n"
+"        \"multi-threading\": {\n"
+"            \"enable-multi-threading\": true,\n"
+"            \"packet-queue-size\": 64,\n"
+"            \"thread-pool-size\": 0\n"
+"        },\n"
+"        \"option-data\": [ ],\n"
+"        \"option-def\": [ ],\n"
+"        \"parked-packet-limit\": 256,\n"
+"        \"pd-allocator\": \"iterative\",\n"
+"        \"preferred-lifetime\": 3000,\n"
+"        \"rebind-timer\": 2000,\n"
+"        \"relay-supplied-options\": [ \"65\" ],\n"
+"        \"renew-timer\": 1000,\n"
+"        \"reservations-global\": false,\n"
+"        \"reservations-in-subnet\": true,\n"
+"        \"reservations-lookup-first\": false,\n"
+"        \"reservations-out-of-pool\": false,\n"
+"        \"sanity-checks\": {\n"
+"            \"extended-info-checks\": \"fix\",\n"
+"            \"lease-checks\": \"warn\"\n"
+"        },\n"
+"        \"server-id\": {\n"
+"            \"enterprise-id\": 0,\n"
+"            \"htype\": 0,\n"
+"            \"identifier\": \"\",\n"
+"            \"persist\": true,\n"
+"            \"time\": 0,\n"
+"            \"type\": \"LLT\"\n"
+"        },\n"
+"        \"server-tag\": \"\",\n"
+"        \"shared-networks\": [ ],\n"
+"        \"statistic-default-sample-age\": 0,\n"
+"        \"statistic-default-sample-count\": 20,\n"
+"        \"store-extended-info\": false,\n"
+"        \"subnet6\": [\n"
+"            {\n"
+"                \"allocator\": \"iterative\",\n"
+"                \"calculate-tee-times\": true,\n"
+"                \"id\": 1,\n"
+"                \"max-preferred-lifetime\": 3000,\n"
+"                \"max-valid-lifetime\": 4,\n"
+"                \"min-preferred-lifetime\": 3000,\n"
+"                \"min-valid-lifetime\": 4,\n"
+"                \"option-data\": [ ],\n"
+"                \"pd-allocator\": \"iterative\",\n"
+"                \"pd-pools\": [ ],\n"
+"                \"pools\": [\n"
+"                    {\n"
+"                        \"option-data\": [ ],\n"
+"                        \"pool\": \"2001:db8:1::1-2001:db8:1::ffff\"\n"
+"                    }\n"
+"                ],\n"
+"                \"preferred-lifetime\": 3000,\n"
+"                \"rapid-commit\": false,\n"
+"                \"rebind-timer\": 2,\n"
+"                \"relay\": {\n"
+"                    \"ip-addresses\": [ \"2001:db9::abcd\", \"2001:db9::abce\" ]\n"
+"                },\n"
+"                \"renew-timer\": 1,\n"
+"                \"reservations\": [ ],\n"
+"                \"store-extended-info\": false,\n"
+"                \"subnet\": \"2001:db8:1::/64\",\n"
+"                \"t1-percent\": 0.5,\n"
+"                \"t2-percent\": 0.8,\n"
+"                \"valid-lifetime\": 4\n"
+"            }\n"
+"        ],\n"
+"        \"t1-percent\": 0.5,\n"
+"        \"t2-percent\": 0.8,\n"
+"        \"valid-lifetime\": 4000\n"
+"    }\n",
+    // CONFIGURATION 38
+"{\n"
+"        \"allocator\": \"iterative\",\n"
+"        \"calculate-tee-times\": true,\n"
+"        \"ddns-conflict-resolution-mode\": \"check-with-dhcid\",\n"
+"        \"ddns-generated-prefix\": \"myhost\",\n"
+"        \"ddns-override-client-update\": false,\n"
+"        \"ddns-override-no-update\": false,\n"
+"        \"ddns-qualifying-suffix\": \"\",\n"
+"        \"ddns-replace-client-name\": \"never\",\n"
+"        \"ddns-send-updates\": true,\n"
+"        \"ddns-update-on-renew\": false,\n"
+"        \"decline-probation-period\": 86400,\n"
+"        \"dhcp-ddns\": {\n"
+"            \"enable-updates\": false,\n"
+"            \"max-queue-size\": 1024,\n"
+"            \"ncr-format\": \"JSON\",\n"
+"            \"ncr-protocol\": \"UDP\",\n"
+"            \"sender-ip\": \"0.0.0.0\",\n"
+"            \"sender-port\": 0,\n"
+"            \"server-ip\": \"127.0.0.1\",\n"
+"            \"server-port\": 53001\n"
+"        },\n"
+"        \"dhcp-queue-control\": {\n"
+"            \"capacity\": 64,\n"
+"            \"enable-queue\": false,\n"
+"            \"queue-type\": \"kea-ring6\"\n"
+"        },\n"
+"        \"dhcp4o6-port\": 0,\n"
+"        \"early-global-reservations-lookup\": false,\n"
+"        \"expired-leases-processing\": {\n"
+"            \"flush-reclaimed-timer-wait-time\": 25,\n"
+"            \"hold-reclaimed-time\": 3600,\n"
+"            \"max-reclaim-leases\": 100,\n"
+"            \"max-reclaim-time\": 250,\n"
+"            \"reclaim-timer-wait-time\": 10,\n"
+"            \"unwarned-reclaim-cycles\": 5\n"
+"        },\n"
+"        \"hooks-libraries\": [ ],\n"
+"        \"host-reservation-identifiers\": [ \"hw-address\", \"duid\" ],\n"
+"        \"hostname-char-replacement\": \"\",\n"
+"        \"hostname-char-set\": \"[^A-Za-z0-9.-]\",\n"
+"        \"interfaces-config\": {\n"
+"            \"interfaces\": [ \"*\" ],\n"
+"            \"re-detect\": false\n"
+"        },\n"
+"        \"ip-reservations-unique\": true,\n"
+"        \"lease-database\": {\n"
+"            \"type\": \"memfile\"\n"
+"        },\n"
+"        \"mac-sources\": [ \"any\" ],\n"
+"        \"multi-threading\": {\n"
+"            \"enable-multi-threading\": true,\n"
+"            \"packet-queue-size\": 64,\n"
+"            \"thread-pool-size\": 0\n"
+"        },\n"
+"        \"option-data\": [ ],\n"
+"        \"option-def\": [ ],\n"
+"        \"parked-packet-limit\": 256,\n"
+"        \"pd-allocator\": \"iterative\",\n"
+"        \"preferred-lifetime\": 3000,\n"
+"        \"rebind-timer\": 2000,\n"
+"        \"relay-supplied-options\": [ \"65\" ],\n"
+"        \"renew-timer\": 1000,\n"
+"        \"reservations-global\": false,\n"
+"        \"reservations-in-subnet\": true,\n"
+"        \"reservations-lookup-first\": false,\n"
+"        \"reservations-out-of-pool\": false,\n"
+"        \"sanity-checks\": {\n"
+"            \"extended-info-checks\": \"fix\",\n"
+"            \"lease-checks\": \"warn\"\n"
+"        },\n"
+"        \"server-id\": {\n"
+"            \"enterprise-id\": 0,\n"
+"            \"htype\": 0,\n"
+"            \"identifier\": \"\",\n"
+"            \"persist\": true,\n"
+"            \"time\": 0,\n"
+"            \"type\": \"LLT\"\n"
+"        },\n"
+"        \"server-tag\": \"\",\n"
+"        \"shared-networks\": [ ],\n"
+"        \"statistic-default-sample-age\": 0,\n"
+"        \"statistic-default-sample-count\": 20,\n"
+"        \"store-extended-info\": false,\n"
+"        \"subnet6\": [\n"
+"            {\n"
+"                \"allocator\": \"iterative\",\n"
+"                \"calculate-tee-times\": true,\n"
+"                \"client-class\": \"alpha\",\n"
+"                \"id\": 1,\n"
+"                \"max-preferred-lifetime\": 3000,\n"
+"                \"max-valid-lifetime\": 4000,\n"
+"                \"min-preferred-lifetime\": 3000,\n"
+"                \"min-valid-lifetime\": 4000,\n"
+"                \"option-data\": [ ],\n"
+"                \"pd-allocator\": \"iterative\",\n"
+"                \"pd-pools\": [ ],\n"
+"                \"pools\": [\n"
+"                    {\n"
+"                        \"option-data\": [ ],\n"
+"                        \"pool\": \"2001:db8:1::/80\"\n"
+"                    }\n"
+"                ],\n"
+"                \"preferred-lifetime\": 3000,\n"
+"                \"rapid-commit\": false,\n"
+"                \"rebind-timer\": 2000,\n"
 "                \"relay\": {\n"
 "                    \"ip-addresses\": [ ]\n"
 "                },\n"
@@ -6535,7 +7600,7 @@ const char* UNPARSED_CONFIGS[] = {
 "        \"t2-percent\": 0.8,\n"
 "        \"valid-lifetime\": 4000\n"
 "    }\n",
-    // CONFIGURATION 33
+    // CONFIGURATION 39
 "{\n"
 "        \"allocator\": \"iterative\",\n"
 "        \"calculate-tee-times\": true,\n"
@@ -6672,7 +7737,7 @@ const char* UNPARSED_CONFIGS[] = {
 "        \"t2-percent\": 0.8,\n"
 "        \"valid-lifetime\": 4000\n"
 "    }\n",
-    // CONFIGURATION 34
+    // CONFIGURATION 40
 "{\n"
 "        \"allocator\": \"iterative\",\n"
 "        \"calculate-tee-times\": true,\n"
@@ -6817,7 +7882,7 @@ const char* UNPARSED_CONFIGS[] = {
 "        \"t2-percent\": 0.8,\n"
 "        \"valid-lifetime\": 4000\n"
 "    }\n",
-    // CONFIGURATION 35
+    // CONFIGURATION 41
 "{\n"
 "        \"allocator\": \"iterative\",\n"
 "        \"calculate-tee-times\": true,\n"
@@ -6939,7 +8004,7 @@ const char* UNPARSED_CONFIGS[] = {
 "        \"t2-percent\": 0.8,\n"
 "        \"valid-lifetime\": 4000\n"
 "    }\n",
-    // CONFIGURATION 36
+    // CONFIGURATION 42
 "{\n"
 "        \"allocator\": \"iterative\",\n"
 "        \"calculate-tee-times\": true,\n"
@@ -7204,7 +8269,7 @@ const char* UNPARSED_CONFIGS[] = {
 "        \"t2-percent\": 0.8,\n"
 "        \"valid-lifetime\": 4000\n"
 "    }\n",
-    // CONFIGURATION 37
+    // CONFIGURATION 43
 "{\n"
 "        \"allocator\": \"iterative\",\n"
 "        \"calculate-tee-times\": true,\n"
@@ -7350,7 +8415,7 @@ const char* UNPARSED_CONFIGS[] = {
 "        \"t2-percent\": 0.8,\n"
 "        \"valid-lifetime\": 4000\n"
 "    }\n",
-    // CONFIGURATION 38
+    // CONFIGURATION 44
 "{\n"
 "        \"allocator\": \"iterative\",\n"
 "        \"calculate-tee-times\": true,\n"
@@ -7440,7 +8505,7 @@ const char* UNPARSED_CONFIGS[] = {
 "        \"t2-percent\": 0.8,\n"
 "        \"valid-lifetime\": 4000\n"
 "    }\n",
-    // CONFIGURATION 39
+    // CONFIGURATION 45
 "{\n"
 "        \"allocator\": \"iterative\",\n"
 "        \"calculate-tee-times\": true,\n"
@@ -7530,7 +8595,7 @@ const char* UNPARSED_CONFIGS[] = {
 "        \"t2-percent\": 0.8,\n"
 "        \"valid-lifetime\": 4000\n"
 "    }\n",
-    // CONFIGURATION 40
+    // CONFIGURATION 46
 "{\n"
 "        \"allocator\": \"iterative\",\n"
 "        \"calculate-tee-times\": true,\n"
@@ -7854,7 +8919,7 @@ const char* UNPARSED_CONFIGS[] = {
 "        \"t2-percent\": 0.8,\n"
 "        \"valid-lifetime\": 4000\n"
 "    }\n",
-    // CONFIGURATION 41
+    // CONFIGURATION 47
 "{\n"
 "        \"allocator\": \"iterative\",\n"
 "        \"calculate-tee-times\": true,\n"
@@ -8010,7 +9075,7 @@ const char* UNPARSED_CONFIGS[] = {
 "        \"t2-percent\": 0.8,\n"
 "        \"valid-lifetime\": 4000\n"
 "    }\n",
-    // CONFIGURATION 42
+    // CONFIGURATION 48
 "{\n"
 "        \"allocator\": \"iterative\",\n"
 "        \"calculate-tee-times\": true,\n"
@@ -8070,10 +9135,7 @@ const char* UNPARSED_CONFIGS[] = {
 "        \"option-def\": [ ],\n"
 "        \"parked-packet-limit\": 256,\n"
 "        \"pd-allocator\": \"iterative\",\n"
-"        \"preferred-lifetime\": 3000,\n"
-"        \"rebind-timer\": 2000,\n"
-"        \"relay-supplied-options\": [ \"23\", \"37\", \"65\" ],\n"
-"        \"renew-timer\": 1000,\n"
+"        \"relay-supplied-options\": [ \"65\" ],\n"
 "        \"reservations-global\": false,\n"
 "        \"reservations-in-subnet\": true,\n"
 "        \"reservations-lookup-first\": false,\n"
@@ -8098,9 +9160,9 @@ const char* UNPARSED_CONFIGS[] = {
 "        \"subnet6\": [ ],\n"
 "        \"t1-percent\": 0.5,\n"
 "        \"t2-percent\": 0.8,\n"
-"        \"valid-lifetime\": 4000\n"
+"        \"valid-lifetime\": 7200\n"
 "    }\n",
-    // CONFIGURATION 43
+    // CONFIGURATION 49
 "{\n"
 "        \"allocator\": \"iterative\",\n"
 "        \"calculate-tee-times\": true,\n"
@@ -8160,7 +9222,10 @@ const char* UNPARSED_CONFIGS[] = {
 "        \"option-def\": [ ],\n"
 "        \"parked-packet-limit\": 256,\n"
 "        \"pd-allocator\": \"iterative\",\n"
-"        \"relay-supplied-options\": [ \"65\" ],\n"
+"        \"preferred-lifetime\": 3000,\n"
+"        \"rebind-timer\": 2000,\n"
+"        \"relay-supplied-options\": [ \"23\", \"37\", \"65\" ],\n"
+"        \"renew-timer\": 1000,\n"
 "        \"reservations-global\": false,\n"
 "        \"reservations-in-subnet\": true,\n"
 "        \"reservations-lookup-first\": false,\n"
@@ -8185,9 +9250,9 @@ const char* UNPARSED_CONFIGS[] = {
 "        \"subnet6\": [ ],\n"
 "        \"t1-percent\": 0.5,\n"
 "        \"t2-percent\": 0.8,\n"
-"        \"valid-lifetime\": 7200\n"
+"        \"valid-lifetime\": 4000\n"
 "    }\n",
-    // CONFIGURATION 44
+    // CONFIGURATION 50
 "{\n"
 "        \"allocator\": \"iterative\",\n"
 "        \"calculate-tee-times\": true,\n"
@@ -8274,7 +9339,7 @@ const char* UNPARSED_CONFIGS[] = {
 "        \"t2-percent\": 0.8,\n"
 "        \"valid-lifetime\": 7200\n"
 "    }\n",
-    // CONFIGURATION 45
+    // CONFIGURATION 51
 "{\n"
 "        \"allocator\": \"iterative\",\n"
 "        \"calculate-tee-times\": true,\n"
@@ -8361,7 +9426,7 @@ const char* UNPARSED_CONFIGS[] = {
 "        \"t2-percent\": 0.8,\n"
 "        \"valid-lifetime\": 7200\n"
 "    }\n",
-    // CONFIGURATION 46
+    // CONFIGURATION 52
 "{\n"
 "        \"allocator\": \"iterative\",\n"
 "        \"calculate-tee-times\": true,\n"
@@ -8448,7 +9513,7 @@ const char* UNPARSED_CONFIGS[] = {
 "        \"t2-percent\": 0.8,\n"
 "        \"valid-lifetime\": 7200\n"
 "    }\n",
-    // CONFIGURATION 47
+    // CONFIGURATION 53
 "{\n"
 "        \"allocator\": \"iterative\",\n"
 "        \"calculate-tee-times\": true,\n"
@@ -8584,10 +9649,23 @@ const char* UNPARSED_CONFIGS[] = {
 "        \"t2-percent\": 0.8,\n"
 "        \"valid-lifetime\": 4000\n"
 "    }\n",
-    // CONFIGURATION 48
+    // CONFIGURATION 54
 "{\n"
 "        \"allocator\": \"iterative\",\n"
 "        \"calculate-tee-times\": true,\n"
+"        \"client-classes\": [\n"
+"            {\n"
+"                \"max-valid-lifetime\": 3000,\n"
+"                \"min-valid-lifetime\": 1000,\n"
+"                \"name\": \"one\",\n"
+"                \"option-data\": [ ],\n"
+"                \"valid-lifetime\": 2000\n"
+"            },\n"
+"            {\n"
+"                \"name\": \"two\",\n"
+"                \"option-data\": [ ]\n"
+"            }\n"
+"        ],\n"
 "        \"ddns-conflict-resolution-mode\": \"check-with-dhcid\",\n"
 "        \"ddns-generated-prefix\": \"myhost\",\n"
 "        \"ddns-override-client-update\": false,\n"
@@ -8644,10 +9722,7 @@ const char* UNPARSED_CONFIGS[] = {
 "        \"option-def\": [ ],\n"
 "        \"parked-packet-limit\": 256,\n"
 "        \"pd-allocator\": \"iterative\",\n"
-"        \"preferred-lifetime\": 3000,\n"
-"        \"rebind-timer\": 2000,\n"
 "        \"relay-supplied-options\": [ \"65\" ],\n"
-"        \"renew-timer\": 1000,\n"
 "        \"reservations-global\": false,\n"
 "        \"reservations-in-subnet\": true,\n"
 "        \"reservations-lookup-first\": false,\n"
@@ -8674,42 +9749,52 @@ const char* UNPARSED_CONFIGS[] = {
 "                \"allocator\": \"iterative\",\n"
 "                \"calculate-tee-times\": true,\n"
 "                \"id\": 1,\n"
-"                \"max-preferred-lifetime\": 3000,\n"
-"                \"max-valid-lifetime\": 4000,\n"
-"                \"min-preferred-lifetime\": 3000,\n"
-"                \"min-valid-lifetime\": 4000,\n"
+"                \"max-valid-lifetime\": 7200,\n"
+"                \"min-valid-lifetime\": 7200,\n"
 "                \"option-data\": [ ],\n"
 "                \"pd-allocator\": \"iterative\",\n"
 "                \"pd-pools\": [ ],\n"
 "                \"pools\": [\n"
 "                    {\n"
 "                        \"option-data\": [ ],\n"
-"                        \"pool\": \"2001:db8::/64\"\n"
+"                        \"pool\": \"2001:db8::1-2001:db8::ffff\"\n"
 "                    }\n"
 "                ],\n"
-"                \"preferred-lifetime\": 3000,\n"
 "                \"rapid-commit\": false,\n"
-"                \"rebind-timer\": 2000,\n"
 "                \"relay\": {\n"
 "                    \"ip-addresses\": [ ]\n"
 "                },\n"
-"                \"renew-timer\": 1000,\n"
 "                \"reservations\": [ ],\n"
 "                \"store-extended-info\": false,\n"
-"                \"subnet\": \"2001:db8::/32\",\n"
+"                \"subnet\": \"2001:db8::/64\",\n"
 "                \"t1-percent\": 0.5,\n"
 "                \"t2-percent\": 0.8,\n"
-"                \"valid-lifetime\": 4000\n"
+"                \"valid-lifetime\": 7200\n"
 "            }\n"
 "        ],\n"
 "        \"t1-percent\": 0.5,\n"
 "        \"t2-percent\": 0.8,\n"
-"        \"valid-lifetime\": 4000\n"
+"        \"valid-lifetime\": 7200\n"
 "    }\n",
-    // CONFIGURATION 49
+    // CONFIGURATION 55
 "{\n"
 "        \"allocator\": \"iterative\",\n"
 "        \"calculate-tee-times\": true,\n"
+"        \"client-classes\": [\n"
+"            {\n"
+"                \"max-valid-lifetime\": 3000,\n"
+"                \"min-valid-lifetime\": 1000,\n"
+"                \"name\": \"one\",\n"
+"                \"option-data\": [ ],\n"
+"                \"template-test\": \"''\",\n"
+"                \"valid-lifetime\": 2000\n"
+"            },\n"
+"            {\n"
+"                \"name\": \"two\",\n"
+"                \"option-data\": [ ],\n"
+"                \"template-test\": \"''\"\n"
+"            }\n"
+"        ],\n"
 "        \"ddns-conflict-resolution-mode\": \"check-with-dhcid\",\n"
 "        \"ddns-generated-prefix\": \"myhost\",\n"
 "        \"ddns-override-client-update\": false,\n"
@@ -8766,10 +9851,7 @@ const char* UNPARSED_CONFIGS[] = {
 "        \"option-def\": [ ],\n"
 "        \"parked-packet-limit\": 256,\n"
 "        \"pd-allocator\": \"iterative\",\n"
-"        \"preferred-lifetime\": 3000,\n"
-"        \"rebind-timer\": 2000,\n"
 "        \"relay-supplied-options\": [ \"65\" ],\n"
-"        \"renew-timer\": 1000,\n"
 "        \"reservations-global\": false,\n"
 "        \"reservations-in-subnet\": true,\n"
 "        \"reservations-lookup-first\": false,\n"
@@ -8796,40 +9878,34 @@ const char* UNPARSED_CONFIGS[] = {
 "                \"allocator\": \"iterative\",\n"
 "                \"calculate-tee-times\": true,\n"
 "                \"id\": 1,\n"
-"                \"max-preferred-lifetime\": 3000,\n"
-"                \"max-valid-lifetime\": 4000,\n"
-"                \"min-preferred-lifetime\": 3000,\n"
-"                \"min-valid-lifetime\": 4000,\n"
+"                \"max-valid-lifetime\": 7200,\n"
+"                \"min-valid-lifetime\": 7200,\n"
 "                \"option-data\": [ ],\n"
 "                \"pd-allocator\": \"iterative\",\n"
 "                \"pd-pools\": [ ],\n"
 "                \"pools\": [\n"
 "                    {\n"
 "                        \"option-data\": [ ],\n"
-"                        \"pool\": \"2001:db8::/64\",\n"
-"                        \"user-context\": { }\n"
+"                        \"pool\": \"2001:db8::1-2001:db8::ffff\"\n"
 "                    }\n"
 "                ],\n"
-"                \"preferred-lifetime\": 3000,\n"
 "                \"rapid-commit\": false,\n"
-"                \"rebind-timer\": 2000,\n"
 "                \"relay\": {\n"
 "                    \"ip-addresses\": [ ]\n"
 "                },\n"
-"                \"renew-timer\": 1000,\n"
 "                \"reservations\": [ ],\n"
 "                \"store-extended-info\": false,\n"
-"                \"subnet\": \"2001:db8::/32\",\n"
+"                \"subnet\": \"2001:db8::/64\",\n"
 "                \"t1-percent\": 0.5,\n"
 "                \"t2-percent\": 0.8,\n"
-"                \"valid-lifetime\": 4000\n"
+"                \"valid-lifetime\": 7200\n"
 "            }\n"
 "        ],\n"
 "        \"t1-percent\": 0.5,\n"
 "        \"t2-percent\": 0.8,\n"
-"        \"valid-lifetime\": 4000\n"
+"        \"valid-lifetime\": 7200\n"
 "    }\n",
-    // CONFIGURATION 50
+    // CONFIGURATION 56
 "{\n"
 "        \"allocator\": \"iterative\",\n"
 "        \"calculate-tee-times\": true,\n"
@@ -8929,13 +10005,7 @@ const char* UNPARSED_CONFIGS[] = {
 "                \"pools\": [\n"
 "                    {\n"
 "                        \"option-data\": [ ],\n"
-"                        \"pool\": \"2001:db8::/64\",\n"
-"                        \"user-context\": {\n"
-"                            \"lw4over6-bind-prefix-len\": 56,\n"
-"                            \"lw4over6-sharing-ratio\": 64,\n"
-"                            \"lw4over6-sysports-exclude\": true,\n"
-"                            \"lw4over6-v4-pool\": \"192.0.2.0/24\"\n"
-"                        }\n"
+"                        \"pool\": \"2001:db8::/64\"\n"
 "                    }\n"
 "                ],\n"
 "                \"preferred-lifetime\": 3000,\n"
@@ -8957,7 +10027,7 @@ const char* UNPARSED_CONFIGS[] = {
 "        \"t2-percent\": 0.8,\n"
 "        \"valid-lifetime\": 4000\n"
 "    }\n",
-    // CONFIGURATION 51
+    // CONFIGURATION 57
 "{\n"
 "        \"allocator\": \"iterative\",\n"
 "        \"calculate-tee-times\": true,\n"
@@ -9058,12 +10128,7 @@ const char* UNPARSED_CONFIGS[] = {
 "                    {\n"
 "                        \"option-data\": [ ],\n"
 "                        \"pool\": \"2001:db8::/64\",\n"
-"                        \"user-context\": {\n"
-"                            \"lw4over6-bind-prefix-len\": 56,\n"
-"                            \"lw4over6-sharing-ratio\": 64,\n"
-"                            \"lw4over6-sysports-exclude\": true,\n"
-"                            \"lw4over6-v4-pool\": \"192.0.2.0/24\"\n"
-"                        }\n"
+"                        \"user-context\": { }\n"
 "                    }\n"
 "                ],\n"
 "                \"preferred-lifetime\": 3000,\n"
@@ -9085,7 +10150,7 @@ const char* UNPARSED_CONFIGS[] = {
 "        \"t2-percent\": 0.8,\n"
 "        \"valid-lifetime\": 4000\n"
 "    }\n",
-    // CONFIGURATION 52
+    // CONFIGURATION 58
 "{\n"
 "        \"allocator\": \"iterative\",\n"
 "        \"calculate-tee-times\": true,\n"
@@ -9181,15 +10246,19 @@ const char* UNPARSED_CONFIGS[] = {
 "                \"min-valid-lifetime\": 4000,\n"
 "                \"option-data\": [ ],\n"
 "                \"pd-allocator\": \"iterative\",\n"
-"                \"pd-pools\": [\n"
+"                \"pd-pools\": [ ],\n"
+"                \"pools\": [\n"
 "                    {\n"
-"                        \"delegated-len\": 64,\n"
 "                        \"option-data\": [ ],\n"
-"                        \"prefix\": \"2001:db8::\",\n"
-"                        \"prefix-len\": 56\n"
+"                        \"pool\": \"2001:db8::/64\",\n"
+"                        \"user-context\": {\n"
+"                            \"lw4over6-bind-prefix-len\": 56,\n"
+"                            \"lw4over6-sharing-ratio\": 64,\n"
+"                            \"lw4over6-sysports-exclude\": true,\n"
+"                            \"lw4over6-v4-pool\": \"192.0.2.0/24\"\n"
+"                        }\n"
 "                    }\n"
 "                ],\n"
-"                \"pools\": [ ],\n"
 "                \"preferred-lifetime\": 3000,\n"
 "                \"rapid-commit\": false,\n"
 "                \"rebind-timer\": 2000,\n"
@@ -9209,7 +10278,7 @@ const char* UNPARSED_CONFIGS[] = {
 "        \"t2-percent\": 0.8,\n"
 "        \"valid-lifetime\": 4000\n"
 "    }\n",
-    // CONFIGURATION 53
+    // CONFIGURATION 59
 "{\n"
 "        \"allocator\": \"iterative\",\n"
 "        \"calculate-tee-times\": true,\n"
@@ -9305,16 +10374,19 @@ const char* UNPARSED_CONFIGS[] = {
 "                \"min-valid-lifetime\": 4000,\n"
 "                \"option-data\": [ ],\n"
 "                \"pd-allocator\": \"iterative\",\n"
-"                \"pd-pools\": [\n"
+"                \"pd-pools\": [ ],\n"
+"                \"pools\": [\n"
 "                    {\n"
-"                        \"delegated-len\": 64,\n"
 "                        \"option-data\": [ ],\n"
-"                        \"prefix\": \"2001:db8::\",\n"
-"                        \"prefix-len\": 56,\n"
-"                        \"user-context\": { }\n"
+"                        \"pool\": \"2001:db8::/64\",\n"
+"                        \"user-context\": {\n"
+"                            \"lw4over6-bind-prefix-len\": 56,\n"
+"                            \"lw4over6-sharing-ratio\": 64,\n"
+"                            \"lw4over6-sysports-exclude\": true,\n"
+"                            \"lw4over6-v4-pool\": \"192.0.2.0/24\"\n"
+"                        }\n"
 "                    }\n"
 "                ],\n"
-"                \"pools\": [ ],\n"
 "                \"preferred-lifetime\": 3000,\n"
 "                \"rapid-commit\": false,\n"
 "                \"rebind-timer\": 2000,\n"
@@ -9334,7 +10406,7 @@ const char* UNPARSED_CONFIGS[] = {
 "        \"t2-percent\": 0.8,\n"
 "        \"valid-lifetime\": 4000\n"
 "    }\n",
-    // CONFIGURATION 54
+    // CONFIGURATION 60
 "{\n"
 "        \"allocator\": \"iterative\",\n"
 "        \"calculate-tee-times\": true,\n"
@@ -9430,12 +10502,11 @@ const char* UNPARSED_CONFIGS[] = {
 "                \"min-valid-lifetime\": 4000,\n"
 "                \"option-data\": [ ],\n"
 "                \"pd-allocator\": \"iterative\",\n"
-"                \"pd-pools\": [\n"
+"                \"pd-pools\": [ ],\n"
+"                \"pools\": [\n"
 "                    {\n"
-"                        \"delegated-len\": 64,\n"
 "                        \"option-data\": [ ],\n"
-"                        \"prefix\": \"2001:db8::\",\n"
-"                        \"prefix-len\": 56,\n"
+"                        \"pool\": \"2001:db8::/64\",\n"
 "                        \"user-context\": {\n"
 "                            \"lw4over6-bind-prefix-len\": 56,\n"
 "                            \"lw4over6-sharing-ratio\": 64,\n"
@@ -9444,7 +10515,6 @@ const char* UNPARSED_CONFIGS[] = {
 "                        }\n"
 "                    }\n"
 "                ],\n"
-"                \"pools\": [ ],\n"
 "                \"preferred-lifetime\": 3000,\n"
 "                \"rapid-commit\": false,\n"
 "                \"rebind-timer\": 2000,\n"
@@ -9464,7 +10534,7 @@ const char* UNPARSED_CONFIGS[] = {
 "        \"t2-percent\": 0.8,\n"
 "        \"valid-lifetime\": 4000\n"
 "    }\n",
-    // CONFIGURATION 55
+    // CONFIGURATION 61
 "{\n"
 "        \"allocator\": \"iterative\",\n"
 "        \"calculate-tee-times\": true,\n"
@@ -9506,20 +10576,6 @@ const char* UNPARSED_CONFIGS[] = {
 "        \"host-reservation-identifiers\": [ \"hw-address\", \"duid\" ],\n"
 "        \"hostname-char-replacement\": \"\",\n"
 "        \"hostname-char-set\": \"[^A-Za-z0-9.-]\",\n"
-"        \"hosts-databases\": [\n"
-"            {\n"
-"                \"name\": \"keatest1\",\n"
-"                \"password\": \"keatest\",\n"
-"                \"type\": \"mysql\",\n"
-"                \"user\": \"keatest\"\n"
-"            },\n"
-"            {\n"
-"                \"name\": \"keatest2\",\n"
-"                \"password\": \"keatest\",\n"
-"                \"type\": \"mysql\",\n"
-"                \"user\": \"keatest\"\n"
-"            }\n"
-"        ],\n"
 "        \"interfaces-config\": {\n"
 "            \"interfaces\": [ \"*\" ],\n"
 "            \"re-detect\": false\n"
@@ -9563,44 +10619,49 @@ const char* UNPARSED_CONFIGS[] = {
 "        \"statistic-default-sample-age\": 0,\n"
 "        \"statistic-default-sample-count\": 20,\n"
 "        \"store-extended-info\": false,\n"
-"        \"subnet6\": [ ],\n"
+"        \"subnet6\": [\n"
+"            {\n"
+"                \"allocator\": \"iterative\",\n"
+"                \"calculate-tee-times\": true,\n"
+"                \"id\": 1,\n"
+"                \"max-preferred-lifetime\": 3000,\n"
+"                \"max-valid-lifetime\": 4000,\n"
+"                \"min-preferred-lifetime\": 3000,\n"
+"                \"min-valid-lifetime\": 4000,\n"
+"                \"option-data\": [ ],\n"
+"                \"pd-allocator\": \"iterative\",\n"
+"                \"pd-pools\": [\n"
+"                    {\n"
+"                        \"delegated-len\": 64,\n"
+"                        \"option-data\": [ ],\n"
+"                        \"prefix\": \"2001:db8::\",\n"
+"                        \"prefix-len\": 56\n"
+"                    }\n"
+"                ],\n"
+"                \"pools\": [ ],\n"
+"                \"preferred-lifetime\": 3000,\n"
+"                \"rapid-commit\": false,\n"
+"                \"rebind-timer\": 2000,\n"
+"                \"relay\": {\n"
+"                    \"ip-addresses\": [ ]\n"
+"                },\n"
+"                \"renew-timer\": 1000,\n"
+"                \"reservations\": [ ],\n"
+"                \"store-extended-info\": false,\n"
+"                \"subnet\": \"2001:db8::/32\",\n"
+"                \"t1-percent\": 0.5,\n"
+"                \"t2-percent\": 0.8,\n"
+"                \"valid-lifetime\": 4000\n"
+"            }\n"
+"        ],\n"
 "        \"t1-percent\": 0.5,\n"
 "        \"t2-percent\": 0.8,\n"
 "        \"valid-lifetime\": 4000\n"
 "    }\n",
-    // CONFIGURATION 56
+    // CONFIGURATION 62
 "{\n"
 "        \"allocator\": \"iterative\",\n"
 "        \"calculate-tee-times\": true,\n"
-"        \"client-classes\": [\n"
-"            {\n"
-"                \"name\": \"all\",\n"
-"                \"option-data\": [ ],\n"
-"                \"test\": \"'' == ''\",\n"
-"                \"user-context\": {\n"
-"                    \"comment\": \"match all\"\n"
-"                }\n"
-"            },\n"
-"            {\n"
-"                \"name\": \"none\",\n"
-"                \"option-data\": [ ]\n"
-"            },\n"
-"            {\n"
-"                \"name\": \"both\",\n"
-"                \"option-data\": [ ],\n"
-"                \"user-context\": {\n"
-"                    \"comment\": \"a comment\",\n"
-"                    \"version\": 1\n"
-"                }\n"
-"            }\n"
-"        ],\n"
-"        \"control-socket\": {\n"
-"            \"socket-name\": \"/tmp/kea6-ctrl-socket\",\n"
-"            \"socket-type\": \"unix\",\n"
-"            \"user-context\": {\n"
-"                \"comment\": \"Indirect comment\"\n"
-"            }\n"
-"        },\n"
 "        \"ddns-conflict-resolution-mode\": \"check-with-dhcid\",\n"
 "        \"ddns-generated-prefix\": \"myhost\",\n"
 "        \"ddns-override-client-update\": false,\n"
@@ -9618,10 +10679,7 @@ const char* UNPARSED_CONFIGS[] = {
 "            \"sender-ip\": \"0.0.0.0\",\n"
 "            \"sender-port\": 0,\n"
 "            \"server-ip\": \"127.0.0.1\",\n"
-"            \"server-port\": 53001,\n"
-"            \"user-context\": {\n"
-"                \"comment\": \"No dynamic DNS\"\n"
-"            }\n"
+"            \"server-port\": 53001\n"
 "        },\n"
 "        \"dhcp-queue-control\": {\n"
 "            \"capacity\": 64,\n"
@@ -9644,10 +10702,840 @@ const char* UNPARSED_CONFIGS[] = {
 "        \"hostname-char-set\": \"[^A-Za-z0-9.-]\",\n"
 "        \"interfaces-config\": {\n"
 "            \"interfaces\": [ \"*\" ],\n"
-"            \"re-detect\": false,\n"
-"            \"user-context\": {\n"
-"                \"comment\": \"Use wildcard\"\n"
-"            }\n"
+"            \"re-detect\": false\n"
+"        },\n"
+"        \"ip-reservations-unique\": true,\n"
+"        \"lease-database\": {\n"
+"            \"type\": \"memfile\"\n"
+"        },\n"
+"        \"mac-sources\": [ \"any\" ],\n"
+"        \"multi-threading\": {\n"
+"            \"enable-multi-threading\": true,\n"
+"            \"packet-queue-size\": 64,\n"
+"            \"thread-pool-size\": 0\n"
+"        },\n"
+"        \"option-data\": [ ],\n"
+"        \"option-def\": [ ],\n"
+"        \"parked-packet-limit\": 256,\n"
+"        \"pd-allocator\": \"iterative\",\n"
+"        \"preferred-lifetime\": 3000,\n"
+"        \"rebind-timer\": 2000,\n"
+"        \"relay-supplied-options\": [ \"65\" ],\n"
+"        \"renew-timer\": 1000,\n"
+"        \"reservations-global\": false,\n"
+"        \"reservations-in-subnet\": true,\n"
+"        \"reservations-lookup-first\": false,\n"
+"        \"reservations-out-of-pool\": false,\n"
+"        \"sanity-checks\": {\n"
+"            \"extended-info-checks\": \"fix\",\n"
+"            \"lease-checks\": \"warn\"\n"
+"        },\n"
+"        \"server-id\": {\n"
+"            \"enterprise-id\": 0,\n"
+"            \"htype\": 0,\n"
+"            \"identifier\": \"\",\n"
+"            \"persist\": true,\n"
+"            \"time\": 0,\n"
+"            \"type\": \"LLT\"\n"
+"        },\n"
+"        \"server-tag\": \"\",\n"
+"        \"shared-networks\": [ ],\n"
+"        \"statistic-default-sample-age\": 0,\n"
+"        \"statistic-default-sample-count\": 20,\n"
+"        \"store-extended-info\": false,\n"
+"        \"subnet6\": [\n"
+"            {\n"
+"                \"allocator\": \"iterative\",\n"
+"                \"calculate-tee-times\": true,\n"
+"                \"id\": 1,\n"
+"                \"max-preferred-lifetime\": 3000,\n"
+"                \"max-valid-lifetime\": 4000,\n"
+"                \"min-preferred-lifetime\": 3000,\n"
+"                \"min-valid-lifetime\": 4000,\n"
+"                \"option-data\": [ ],\n"
+"                \"pd-allocator\": \"iterative\",\n"
+"                \"pd-pools\": [\n"
+"                    {\n"
+"                        \"delegated-len\": 64,\n"
+"                        \"option-data\": [ ],\n"
+"                        \"prefix\": \"2001:db8::\",\n"
+"                        \"prefix-len\": 56,\n"
+"                        \"user-context\": { }\n"
+"                    }\n"
+"                ],\n"
+"                \"pools\": [ ],\n"
+"                \"preferred-lifetime\": 3000,\n"
+"                \"rapid-commit\": false,\n"
+"                \"rebind-timer\": 2000,\n"
+"                \"relay\": {\n"
+"                    \"ip-addresses\": [ ]\n"
+"                },\n"
+"                \"renew-timer\": 1000,\n"
+"                \"reservations\": [ ],\n"
+"                \"store-extended-info\": false,\n"
+"                \"subnet\": \"2001:db8::/32\",\n"
+"                \"t1-percent\": 0.5,\n"
+"                \"t2-percent\": 0.8,\n"
+"                \"valid-lifetime\": 4000\n"
+"            }\n"
+"        ],\n"
+"        \"t1-percent\": 0.5,\n"
+"        \"t2-percent\": 0.8,\n"
+"        \"valid-lifetime\": 4000\n"
+"    }\n",
+    // CONFIGURATION 63
+"{\n"
+"        \"allocator\": \"iterative\",\n"
+"        \"calculate-tee-times\": true,\n"
+"        \"ddns-conflict-resolution-mode\": \"check-with-dhcid\",\n"
+"        \"ddns-generated-prefix\": \"myhost\",\n"
+"        \"ddns-override-client-update\": false,\n"
+"        \"ddns-override-no-update\": false,\n"
+"        \"ddns-qualifying-suffix\": \"\",\n"
+"        \"ddns-replace-client-name\": \"never\",\n"
+"        \"ddns-send-updates\": true,\n"
+"        \"ddns-update-on-renew\": false,\n"
+"        \"decline-probation-period\": 86400,\n"
+"        \"dhcp-ddns\": {\n"
+"            \"enable-updates\": false,\n"
+"            \"max-queue-size\": 1024,\n"
+"            \"ncr-format\": \"JSON\",\n"
+"            \"ncr-protocol\": \"UDP\",\n"
+"            \"sender-ip\": \"0.0.0.0\",\n"
+"            \"sender-port\": 0,\n"
+"            \"server-ip\": \"127.0.0.1\",\n"
+"            \"server-port\": 53001\n"
+"        },\n"
+"        \"dhcp-queue-control\": {\n"
+"            \"capacity\": 64,\n"
+"            \"enable-queue\": false,\n"
+"            \"queue-type\": \"kea-ring6\"\n"
+"        },\n"
+"        \"dhcp4o6-port\": 0,\n"
+"        \"early-global-reservations-lookup\": false,\n"
+"        \"expired-leases-processing\": {\n"
+"            \"flush-reclaimed-timer-wait-time\": 25,\n"
+"            \"hold-reclaimed-time\": 3600,\n"
+"            \"max-reclaim-leases\": 100,\n"
+"            \"max-reclaim-time\": 250,\n"
+"            \"reclaim-timer-wait-time\": 10,\n"
+"            \"unwarned-reclaim-cycles\": 5\n"
+"        },\n"
+"        \"hooks-libraries\": [ ],\n"
+"        \"host-reservation-identifiers\": [ \"hw-address\", \"duid\" ],\n"
+"        \"hostname-char-replacement\": \"\",\n"
+"        \"hostname-char-set\": \"[^A-Za-z0-9.-]\",\n"
+"        \"interfaces-config\": {\n"
+"            \"interfaces\": [ \"*\" ],\n"
+"            \"re-detect\": false\n"
+"        },\n"
+"        \"ip-reservations-unique\": true,\n"
+"        \"lease-database\": {\n"
+"            \"type\": \"memfile\"\n"
+"        },\n"
+"        \"mac-sources\": [ \"any\" ],\n"
+"        \"multi-threading\": {\n"
+"            \"enable-multi-threading\": true,\n"
+"            \"packet-queue-size\": 64,\n"
+"            \"thread-pool-size\": 0\n"
+"        },\n"
+"        \"option-data\": [ ],\n"
+"        \"option-def\": [ ],\n"
+"        \"parked-packet-limit\": 256,\n"
+"        \"pd-allocator\": \"iterative\",\n"
+"        \"preferred-lifetime\": 3000,\n"
+"        \"rebind-timer\": 2000,\n"
+"        \"relay-supplied-options\": [ \"65\" ],\n"
+"        \"renew-timer\": 1000,\n"
+"        \"reservations-global\": false,\n"
+"        \"reservations-in-subnet\": true,\n"
+"        \"reservations-lookup-first\": false,\n"
+"        \"reservations-out-of-pool\": false,\n"
+"        \"sanity-checks\": {\n"
+"            \"extended-info-checks\": \"fix\",\n"
+"            \"lease-checks\": \"warn\"\n"
+"        },\n"
+"        \"server-id\": {\n"
+"            \"enterprise-id\": 0,\n"
+"            \"htype\": 0,\n"
+"            \"identifier\": \"\",\n"
+"            \"persist\": true,\n"
+"            \"time\": 0,\n"
+"            \"type\": \"LLT\"\n"
+"        },\n"
+"        \"server-tag\": \"\",\n"
+"        \"shared-networks\": [ ],\n"
+"        \"statistic-default-sample-age\": 0,\n"
+"        \"statistic-default-sample-count\": 20,\n"
+"        \"store-extended-info\": false,\n"
+"        \"subnet6\": [\n"
+"            {\n"
+"                \"allocator\": \"iterative\",\n"
+"                \"calculate-tee-times\": true,\n"
+"                \"id\": 1,\n"
+"                \"max-preferred-lifetime\": 3000,\n"
+"                \"max-valid-lifetime\": 4000,\n"
+"                \"min-preferred-lifetime\": 3000,\n"
+"                \"min-valid-lifetime\": 4000,\n"
+"                \"option-data\": [ ],\n"
+"                \"pd-allocator\": \"iterative\",\n"
+"                \"pd-pools\": [\n"
+"                    {\n"
+"                        \"delegated-len\": 64,\n"
+"                        \"option-data\": [ ],\n"
+"                        \"prefix\": \"2001:db8::\",\n"
+"                        \"prefix-len\": 56,\n"
+"                        \"user-context\": {\n"
+"                            \"lw4over6-bind-prefix-len\": 56,\n"
+"                            \"lw4over6-sharing-ratio\": 64,\n"
+"                            \"lw4over6-sysports-exclude\": true,\n"
+"                            \"lw4over6-v4-pool\": \"192.0.2.0/24\"\n"
+"                        }\n"
+"                    }\n"
+"                ],\n"
+"                \"pools\": [ ],\n"
+"                \"preferred-lifetime\": 3000,\n"
+"                \"rapid-commit\": false,\n"
+"                \"rebind-timer\": 2000,\n"
+"                \"relay\": {\n"
+"                    \"ip-addresses\": [ ]\n"
+"                },\n"
+"                \"renew-timer\": 1000,\n"
+"                \"reservations\": [ ],\n"
+"                \"store-extended-info\": false,\n"
+"                \"subnet\": \"2001:db8::/32\",\n"
+"                \"t1-percent\": 0.5,\n"
+"                \"t2-percent\": 0.8,\n"
+"                \"valid-lifetime\": 4000\n"
+"            }\n"
+"        ],\n"
+"        \"t1-percent\": 0.5,\n"
+"        \"t2-percent\": 0.8,\n"
+"        \"valid-lifetime\": 4000\n"
+"    }\n",
+    // CONFIGURATION 64
+"{\n"
+"        \"allocator\": \"iterative\",\n"
+"        \"calculate-tee-times\": true,\n"
+"        \"ddns-conflict-resolution-mode\": \"check-with-dhcid\",\n"
+"        \"ddns-generated-prefix\": \"myhost\",\n"
+"        \"ddns-override-client-update\": false,\n"
+"        \"ddns-override-no-update\": false,\n"
+"        \"ddns-qualifying-suffix\": \"\",\n"
+"        \"ddns-replace-client-name\": \"never\",\n"
+"        \"ddns-send-updates\": true,\n"
+"        \"ddns-update-on-renew\": false,\n"
+"        \"decline-probation-period\": 86400,\n"
+"        \"dhcp-ddns\": {\n"
+"            \"enable-updates\": false,\n"
+"            \"max-queue-size\": 1024,\n"
+"            \"ncr-format\": \"JSON\",\n"
+"            \"ncr-protocol\": \"UDP\",\n"
+"            \"sender-ip\": \"0.0.0.0\",\n"
+"            \"sender-port\": 0,\n"
+"            \"server-ip\": \"127.0.0.1\",\n"
+"            \"server-port\": 53001\n"
+"        },\n"
+"        \"dhcp-queue-control\": {\n"
+"            \"capacity\": 64,\n"
+"            \"enable-queue\": false,\n"
+"            \"queue-type\": \"kea-ring6\"\n"
+"        },\n"
+"        \"dhcp4o6-port\": 0,\n"
+"        \"early-global-reservations-lookup\": false,\n"
+"        \"expired-leases-processing\": {\n"
+"            \"flush-reclaimed-timer-wait-time\": 25,\n"
+"            \"hold-reclaimed-time\": 3600,\n"
+"            \"max-reclaim-leases\": 100,\n"
+"            \"max-reclaim-time\": 250,\n"
+"            \"reclaim-timer-wait-time\": 10,\n"
+"            \"unwarned-reclaim-cycles\": 5\n"
+"        },\n"
+"        \"hooks-libraries\": [ ],\n"
+"        \"host-reservation-identifiers\": [ \"hw-address\", \"duid\" ],\n"
+"        \"hostname-char-replacement\": \"\",\n"
+"        \"hostname-char-set\": \"[^A-Za-z0-9.-]\",\n"
+"        \"hosts-databases\": [\n"
+"            {\n"
+"                \"name\": \"keatest1\",\n"
+"                \"password\": \"keatest\",\n"
+"                \"type\": \"mysql\",\n"
+"                \"user\": \"keatest\"\n"
+"            },\n"
+"            {\n"
+"                \"name\": \"keatest2\",\n"
+"                \"password\": \"keatest\",\n"
+"                \"retry-on-startup\": true,\n"
+"                \"type\": \"mysql\",\n"
+"                \"user\": \"keatest\"\n"
+"            }\n"
+"        ],\n"
+"        \"interfaces-config\": {\n"
+"            \"interfaces\": [ \"*\" ],\n"
+"            \"re-detect\": false\n"
+"        },\n"
+"        \"ip-reservations-unique\": true,\n"
+"        \"lease-database\": {\n"
+"            \"type\": \"memfile\"\n"
+"        },\n"
+"        \"mac-sources\": [ \"any\" ],\n"
+"        \"multi-threading\": {\n"
+"            \"enable-multi-threading\": true,\n"
+"            \"packet-queue-size\": 64,\n"
+"            \"thread-pool-size\": 0\n"
+"        },\n"
+"        \"option-data\": [ ],\n"
+"        \"option-def\": [ ],\n"
+"        \"parked-packet-limit\": 256,\n"
+"        \"pd-allocator\": \"iterative\",\n"
+"        \"preferred-lifetime\": 3000,\n"
+"        \"rebind-timer\": 2000,\n"
+"        \"relay-supplied-options\": [ \"65\" ],\n"
+"        \"renew-timer\": 1000,\n"
+"        \"reservations-global\": false,\n"
+"        \"reservations-in-subnet\": true,\n"
+"        \"reservations-lookup-first\": false,\n"
+"        \"reservations-out-of-pool\": false,\n"
+"        \"sanity-checks\": {\n"
+"            \"extended-info-checks\": \"fix\",\n"
+"            \"lease-checks\": \"warn\"\n"
+"        },\n"
+"        \"server-id\": {\n"
+"            \"enterprise-id\": 0,\n"
+"            \"htype\": 0,\n"
+"            \"identifier\": \"\",\n"
+"            \"persist\": true,\n"
+"            \"time\": 0,\n"
+"            \"type\": \"LLT\"\n"
+"        },\n"
+"        \"server-tag\": \"\",\n"
+"        \"shared-networks\": [ ],\n"
+"        \"statistic-default-sample-age\": 0,\n"
+"        \"statistic-default-sample-count\": 20,\n"
+"        \"store-extended-info\": false,\n"
+"        \"subnet6\": [ ],\n"
+"        \"t1-percent\": 0.5,\n"
+"        \"t2-percent\": 0.8,\n"
+"        \"valid-lifetime\": 4000\n"
+"    }\n",
+    // CONFIGURATION 65
+"{\n"
+"        \"allocator\": \"iterative\",\n"
+"        \"calculate-tee-times\": true,\n"
+"        \"client-classes\": [\n"
+"            {\n"
+"                \"name\": \"all\",\n"
+"                \"option-data\": [ ],\n"
+"                \"test\": \"'' == ''\",\n"
+"                \"user-context\": {\n"
+"                    \"comment\": \"match all\"\n"
+"                }\n"
+"            },\n"
+"            {\n"
+"                \"name\": \"none\",\n"
+"                \"option-data\": [ ]\n"
+"            },\n"
+"            {\n"
+"                \"name\": \"both\",\n"
+"                \"option-data\": [ ],\n"
+"                \"user-context\": {\n"
+"                    \"comment\": \"a comment\",\n"
+"                    \"version\": 1\n"
+"                }\n"
+"            }\n"
+"        ],\n"
+"        \"control-socket\": {\n"
+"            \"socket-name\": \"/tmp/kea6-ctrl-socket\",\n"
+"            \"socket-type\": \"unix\",\n"
+"            \"user-context\": {\n"
+"                \"comment\": \"Indirect comment\"\n"
+"            }\n"
+"        },\n"
+"        \"ddns-conflict-resolution-mode\": \"check-with-dhcid\",\n"
+"        \"ddns-generated-prefix\": \"myhost\",\n"
+"        \"ddns-override-client-update\": false,\n"
+"        \"ddns-override-no-update\": false,\n"
+"        \"ddns-qualifying-suffix\": \"\",\n"
+"        \"ddns-replace-client-name\": \"never\",\n"
+"        \"ddns-send-updates\": true,\n"
+"        \"ddns-update-on-renew\": false,\n"
+"        \"decline-probation-period\": 86400,\n"
+"        \"dhcp-ddns\": {\n"
+"            \"enable-updates\": false,\n"
+"            \"max-queue-size\": 1024,\n"
+"            \"ncr-format\": \"JSON\",\n"
+"            \"ncr-protocol\": \"UDP\",\n"
+"            \"sender-ip\": \"0.0.0.0\",\n"
+"            \"sender-port\": 0,\n"
+"            \"server-ip\": \"127.0.0.1\",\n"
+"            \"server-port\": 53001,\n"
+"            \"user-context\": {\n"
+"                \"comment\": \"No dynamic DNS\"\n"
+"            }\n"
+"        },\n"
+"        \"dhcp-queue-control\": {\n"
+"            \"capacity\": 64,\n"
+"            \"enable-queue\": false,\n"
+"            \"queue-type\": \"kea-ring6\"\n"
+"        },\n"
+"        \"dhcp4o6-port\": 0,\n"
+"        \"early-global-reservations-lookup\": false,\n"
+"        \"expired-leases-processing\": {\n"
+"            \"flush-reclaimed-timer-wait-time\": 25,\n"
+"            \"hold-reclaimed-time\": 3600,\n"
+"            \"max-reclaim-leases\": 100,\n"
+"            \"max-reclaim-time\": 250,\n"
+"            \"reclaim-timer-wait-time\": 10,\n"
+"            \"unwarned-reclaim-cycles\": 5\n"
+"        },\n"
+"        \"hooks-libraries\": [ ],\n"
+"        \"host-reservation-identifiers\": [ \"hw-address\", \"duid\" ],\n"
+"        \"hostname-char-replacement\": \"\",\n"
+"        \"hostname-char-set\": \"[^A-Za-z0-9.-]\",\n"
+"        \"interfaces-config\": {\n"
+"            \"interfaces\": [ \"*\" ],\n"
+"            \"re-detect\": false,\n"
+"            \"user-context\": {\n"
+"                \"comment\": \"Use wildcard\"\n"
+"            }\n"
+"        },\n"
+"        \"ip-reservations-unique\": true,\n"
+"        \"lease-database\": {\n"
+"            \"type\": \"memfile\"\n"
+"        },\n"
+"        \"mac-sources\": [ \"any\" ],\n"
+"        \"multi-threading\": {\n"
+"            \"enable-multi-threading\": true,\n"
+"            \"packet-queue-size\": 64,\n"
+"            \"thread-pool-size\": 0\n"
+"        },\n"
+"        \"option-data\": [\n"
+"            {\n"
+"                \"always-send\": false,\n"
+"                \"code\": 38,\n"
+"                \"csv-format\": false,\n"
+"                \"data\": \"ABCDEF0105\",\n"
+"                \"name\": \"subscriber-id\",\n"
+"                \"never-send\": false,\n"
+"                \"space\": \"dhcp6\",\n"
+"                \"user-context\": {\n"
+"                    \"comment\": \"Set option value\"\n"
+"                }\n"
+"            }\n"
+"        ],\n"
+"        \"option-def\": [\n"
+"            {\n"
+"                \"array\": false,\n"
+"                \"code\": 100,\n"
+"                \"encapsulate\": \"\",\n"
+"                \"name\": \"foo\",\n"
+"                \"record-types\": \"\",\n"
+"                \"space\": \"isc\",\n"
+"                \"type\": \"ipv6-address\",\n"
+"                \"user-context\": {\n"
+"                    \"comment\": \"An option definition\"\n"
+"                }\n"
+"            }\n"
+"        ],\n"
+"        \"parked-packet-limit\": 256,\n"
+"        \"pd-allocator\": \"iterative\",\n"
+"        \"relay-supplied-options\": [ \"65\" ],\n"
+"        \"reservations-global\": false,\n"
+"        \"reservations-in-subnet\": true,\n"
+"        \"reservations-lookup-first\": false,\n"
+"        \"reservations-out-of-pool\": false,\n"
+"        \"sanity-checks\": {\n"
+"            \"extended-info-checks\": \"fix\",\n"
+"            \"lease-checks\": \"warn\"\n"
+"        },\n"
+"        \"server-id\": {\n"
+"            \"enterprise-id\": 0,\n"
+"            \"htype\": 0,\n"
+"            \"identifier\": \"\",\n"
+"            \"persist\": true,\n"
+"            \"time\": 0,\n"
+"            \"type\": \"LL\",\n"
+"            \"user-context\": {\n"
+"                \"comment\": \"DHCPv6 specific\"\n"
+"            }\n"
+"        },\n"
+"        \"server-tag\": \"\",\n"
+"        \"shared-networks\": [\n"
+"            {\n"
+"                \"allocator\": \"iterative\",\n"
+"                \"calculate-tee-times\": true,\n"
+"                \"max-valid-lifetime\": 7200,\n"
+"                \"min-valid-lifetime\": 7200,\n"
+"                \"name\": \"foo\",\n"
+"                \"option-data\": [ ],\n"
+"                \"pd-allocator\": \"iterative\",\n"
+"                \"rapid-commit\": false,\n"
+"                \"relay\": {\n"
+"                    \"ip-addresses\": [ ]\n"
+"                },\n"
+"                \"store-extended-info\": false,\n"
+"                \"subnet6\": [\n"
+"                    {\n"
+"                        \"allocator\": \"iterative\",\n"
+"                        \"calculate-tee-times\": true,\n"
+"                        \"id\": 100,\n"
+"                        \"max-valid-lifetime\": 7200,\n"
+"                        \"min-valid-lifetime\": 7200,\n"
+"                        \"option-data\": [ ],\n"
+"                        \"pd-allocator\": \"iterative\",\n"
+"                        \"pd-pools\": [\n"
+"                            {\n"
+"                                \"delegated-len\": 64,\n"
+"                                \"option-data\": [ ],\n"
+"                                \"prefix\": \"2001:db2::\",\n"
+"                                \"prefix-len\": 48,\n"
+"                                \"user-context\": {\n"
+"                                    \"comment\": \"A prefix pool\"\n"
+"                                }\n"
+"                            }\n"
+"                        ],\n"
+"                        \"pools\": [\n"
+"                            {\n"
+"                                \"option-data\": [ ],\n"
+"                                \"pool\": \"2001:db1::/64\",\n"
+"                                \"user-context\": {\n"
+"                                    \"comment\": \"A pool\"\n"
+"                                }\n"
+"                            }\n"
+"                        ],\n"
+"                        \"relay\": {\n"
+"                            \"ip-addresses\": [ ]\n"
+"                        },\n"
+"                        \"reservations\": [\n"
+"                            {\n"
+"                                \"client-classes\": [ ],\n"
+"                                \"hostname\": \"foo.example.com\",\n"
+"                                \"hw-address\": \"aa:bb:cc:dd:ee:ff\",\n"
+"                                \"ip-addresses\": [ ],\n"
+"                                \"option-data\": [\n"
+"                                    {\n"
+"                                        \"always-send\": false,\n"
+"                                        \"code\": 24,\n"
+"                                        \"csv-format\": true,\n"
+"                                        \"data\": \"example.com\",\n"
+"                                        \"name\": \"domain-search\",\n"
+"                                        \"never-send\": false,\n"
+"                                        \"space\": \"dhcp6\",\n"
+"                                        \"user-context\": {\n"
+"                                            \"comment\": \"An option in a reservation\"\n"
+"                                        }\n"
+"                                    }\n"
+"                                ],\n"
+"                                \"prefixes\": [ ],\n"
+"                                \"user-context\": {\n"
+"                                    \"comment\": \"A host reservation\"\n"
+"                                }\n"
+"                            }\n"
+"                        ],\n"
+"                        \"store-extended-info\": false,\n"
+"                        \"subnet\": \"2001:db1::/48\",\n"
+"                        \"t1-percent\": 0.5,\n"
+"                        \"t2-percent\": 0.8,\n"
+"                        \"user-context\": {\n"
+"                            \"comment\": \"A subnet\"\n"
+"                        },\n"
+"                        \"valid-lifetime\": 7200\n"
+"                    }\n"
+"                ],\n"
+"                \"t1-percent\": 0.5,\n"
+"                \"t2-percent\": 0.8,\n"
+"                \"user-context\": {\n"
+"                    \"comment\": \"A shared network\"\n"
+"                },\n"
+"                \"valid-lifetime\": 7200\n"
+"            }\n"
+"        ],\n"
+"        \"statistic-default-sample-age\": 0,\n"
+"        \"statistic-default-sample-count\": 20,\n"
+"        \"store-extended-info\": false,\n"
+"        \"subnet6\": [ ],\n"
+"        \"t1-percent\": 0.5,\n"
+"        \"t2-percent\": 0.8,\n"
+"        \"user-context\": {\n"
+"            \"comment\": \"A DHCPv6 server\"\n"
+"        },\n"
+"        \"valid-lifetime\": 7200\n"
+"    }\n",
+    // CONFIGURATION 66
+"{\n"
+"        \"allocator\": \"iterative\",\n"
+"        \"calculate-tee-times\": true,\n"
+"        \"ddns-conflict-resolution-mode\": \"check-with-dhcid\",\n"
+"        \"ddns-generated-prefix\": \"myhost\",\n"
+"        \"ddns-override-client-update\": false,\n"
+"        \"ddns-override-no-update\": false,\n"
+"        \"ddns-qualifying-suffix\": \"\",\n"
+"        \"ddns-replace-client-name\": \"never\",\n"
+"        \"ddns-send-updates\": true,\n"
+"        \"ddns-update-on-renew\": false,\n"
+"        \"decline-probation-period\": 86400,\n"
+"        \"dhcp-ddns\": {\n"
+"            \"enable-updates\": false,\n"
+"            \"max-queue-size\": 1024,\n"
+"            \"ncr-format\": \"JSON\",\n"
+"            \"ncr-protocol\": \"UDP\",\n"
+"            \"sender-ip\": \"0.0.0.0\",\n"
+"            \"sender-port\": 0,\n"
+"            \"server-ip\": \"127.0.0.1\",\n"
+"            \"server-port\": 53001\n"
+"        },\n"
+"        \"dhcp-queue-control\": {\n"
+"            \"capacity\": 64,\n"
+"            \"enable-queue\": false,\n"
+"            \"queue-type\": \"kea-ring6\"\n"
+"        },\n"
+"        \"dhcp4o6-port\": 0,\n"
+"        \"early-global-reservations-lookup\": false,\n"
+"        \"expired-leases-processing\": {\n"
+"            \"flush-reclaimed-timer-wait-time\": 25,\n"
+"            \"hold-reclaimed-time\": 3600,\n"
+"            \"max-reclaim-leases\": 100,\n"
+"            \"max-reclaim-time\": 250,\n"
+"            \"reclaim-timer-wait-time\": 10,\n"
+"            \"unwarned-reclaim-cycles\": 5\n"
+"        },\n"
+"        \"hooks-libraries\": [ ],\n"
+"        \"host-reservation-identifiers\": [ \"hw-address\", \"duid\" ],\n"
+"        \"hostname-char-replacement\": \"\",\n"
+"        \"hostname-char-set\": \"[^A-Za-z0-9.-]\",\n"
+"        \"interfaces-config\": {\n"
+"            \"interfaces\": [ \"*\" ],\n"
+"            \"re-detect\": false\n"
+"        },\n"
+"        \"ip-reservations-unique\": true,\n"
+"        \"lease-database\": {\n"
+"            \"type\": \"memfile\"\n"
+"        },\n"
+"        \"mac-sources\": [ \"any\" ],\n"
+"        \"multi-threading\": {\n"
+"            \"enable-multi-threading\": true,\n"
+"            \"packet-queue-size\": 64,\n"
+"            \"thread-pool-size\": 0\n"
+"        },\n"
+"        \"option-data\": [ ],\n"
+"        \"option-def\": [ ],\n"
+"        \"parked-packet-limit\": 256,\n"
+"        \"pd-allocator\": \"iterative\",\n"
+"        \"preferred-lifetime\": 3000,\n"
+"        \"rebind-timer\": 2000,\n"
+"        \"relay-supplied-options\": [ \"65\" ],\n"
+"        \"renew-timer\": 1000,\n"
+"        \"reservations\": [\n"
+"            {\n"
+"                \"client-classes\": [ ],\n"
+"                \"hostname\": \"\",\n"
+"                \"hw-address\": \"01:02:03:04:05:06\",\n"
+"                \"ip-addresses\": [ \"2001:db8:2::abcd\" ],\n"
+"                \"option-data\": [\n"
+"                    {\n"
+"                        \"always-send\": false,\n"
+"                        \"code\": 23,\n"
+"                        \"csv-format\": true,\n"
+"                        \"data\": \"2001:db8:2::abbc\",\n"
+"                        \"name\": \"dns-servers\",\n"
+"                        \"never-send\": false,\n"
+"                        \"space\": \"dhcp6\"\n"
+"                    },\n"
+"                    {\n"
+"                        \"always-send\": false,\n"
+"                        \"code\": 7,\n"
+"                        \"csv-format\": true,\n"
+"                        \"data\": \"25\",\n"
+"                        \"name\": \"preference\",\n"
+"                        \"never-send\": false,\n"
+"                        \"space\": \"dhcp6\"\n"
+"                    }\n"
+"                ],\n"
+"                \"prefixes\": [ ]\n"
+"            },\n"
+"            {\n"
+"                \"client-classes\": [ ],\n"
+"                \"duid\": \"01:02:03:04:05:06:07:08:09:0a\",\n"
+"                \"hostname\": \"\",\n"
+"                \"ip-addresses\": [ \"2001:db8:2::1234\" ],\n"
+"                \"option-data\": [\n"
+"                    {\n"
+"                        \"always-send\": false,\n"
+"                        \"code\": 23,\n"
+"                        \"csv-format\": true,\n"
+"                        \"data\": \"2001:db8:2::1111\",\n"
+"                        \"name\": \"dns-servers\",\n"
+"                        \"never-send\": false,\n"
+"                        \"space\": \"dhcp6\"\n"
+"                    },\n"
+"                    {\n"
+"                        \"always-send\": false,\n"
+"                        \"code\": 7,\n"
+"                        \"csv-format\": true,\n"
+"                        \"data\": \"11\",\n"
+"                        \"name\": \"preference\",\n"
+"                        \"never-send\": false,\n"
+"                        \"space\": \"dhcp6\"\n"
+"                    }\n"
+"                ],\n"
+"                \"prefixes\": [ ]\n"
+"            }\n"
+"        ],\n"
+"        \"reservations-global\": false,\n"
+"        \"reservations-in-subnet\": true,\n"
+"        \"reservations-lookup-first\": false,\n"
+"        \"reservations-out-of-pool\": false,\n"
+"        \"sanity-checks\": {\n"
+"            \"extended-info-checks\": \"fix\",\n"
+"            \"lease-checks\": \"warn\"\n"
+"        },\n"
+"        \"server-id\": {\n"
+"            \"enterprise-id\": 0,\n"
+"            \"htype\": 0,\n"
+"            \"identifier\": \"\",\n"
+"            \"persist\": true,\n"
+"            \"time\": 0,\n"
+"            \"type\": \"LLT\"\n"
+"        },\n"
+"        \"server-tag\": \"\",\n"
+"        \"shared-networks\": [ ],\n"
+"        \"statistic-default-sample-age\": 0,\n"
+"        \"statistic-default-sample-count\": 20,\n"
+"        \"store-extended-info\": false,\n"
+"        \"subnet6\": [\n"
+"            {\n"
+"                \"allocator\": \"iterative\",\n"
+"                \"calculate-tee-times\": true,\n"
+"                \"id\": 123,\n"
+"                \"max-preferred-lifetime\": 3000,\n"
+"                \"max-valid-lifetime\": 4000,\n"
+"                \"min-preferred-lifetime\": 3000,\n"
+"                \"min-valid-lifetime\": 4000,\n"
+"                \"option-data\": [ ],\n"
+"                \"pd-allocator\": \"iterative\",\n"
+"                \"pd-pools\": [ ],\n"
+"                \"pools\": [\n"
+"                    {\n"
+"                        \"option-data\": [ ],\n"
+"                        \"pool\": \"2001:db8:1::/80\"\n"
+"                    }\n"
+"                ],\n"
+"                \"preferred-lifetime\": 3000,\n"
+"                \"rapid-commit\": false,\n"
+"                \"rebind-timer\": 2000,\n"
+"                \"relay\": {\n"
+"                    \"ip-addresses\": [ ]\n"
+"                },\n"
+"                \"renew-timer\": 1000,\n"
+"                \"reservations\": [ ],\n"
+"                \"store-extended-info\": false,\n"
+"                \"subnet\": \"2001:db8:1::/64\",\n"
+"                \"t1-percent\": 0.5,\n"
+"                \"t2-percent\": 0.8,\n"
+"                \"valid-lifetime\": 4000\n"
+"            },\n"
+"            {\n"
+"                \"allocator\": \"iterative\",\n"
+"                \"calculate-tee-times\": true,\n"
+"                \"id\": 234,\n"
+"                \"max-preferred-lifetime\": 3000,\n"
+"                \"max-valid-lifetime\": 4000,\n"
+"                \"min-preferred-lifetime\": 3000,\n"
+"                \"min-valid-lifetime\": 4000,\n"
+"                \"option-data\": [ ],\n"
+"                \"pd-allocator\": \"iterative\",\n"
+"                \"pd-pools\": [ ],\n"
+"                \"pools\": [ ],\n"
+"                \"preferred-lifetime\": 3000,\n"
+"                \"rapid-commit\": false,\n"
+"                \"rebind-timer\": 2000,\n"
+"                \"relay\": {\n"
+"                    \"ip-addresses\": [ ]\n"
+"                },\n"
+"                \"renew-timer\": 1000,\n"
+"                \"reservations\": [ ],\n"
+"                \"store-extended-info\": false,\n"
+"                \"subnet\": \"2001:db8:2::/64\",\n"
+"                \"t1-percent\": 0.5,\n"
+"                \"t2-percent\": 0.8,\n"
+"                \"valid-lifetime\": 4000\n"
+"            },\n"
+"            {\n"
+"                \"allocator\": \"iterative\",\n"
+"                \"calculate-tee-times\": true,\n"
+"                \"id\": 542,\n"
+"                \"max-preferred-lifetime\": 3000,\n"
+"                \"max-valid-lifetime\": 4000,\n"
+"                \"min-preferred-lifetime\": 3000,\n"
+"                \"min-valid-lifetime\": 4000,\n"
+"                \"option-data\": [ ],\n"
+"                \"pd-allocator\": \"iterative\",\n"
+"                \"pd-pools\": [ ],\n"
+"                \"pools\": [ ],\n"
+"                \"preferred-lifetime\": 3000,\n"
+"                \"rapid-commit\": false,\n"
+"                \"rebind-timer\": 2000,\n"
+"                \"relay\": {\n"
+"                    \"ip-addresses\": [ ]\n"
+"                },\n"
+"                \"renew-timer\": 1000,\n"
+"                \"reservations\": [ ],\n"
+"                \"store-extended-info\": false,\n"
+"                \"subnet\": \"2001:db8:3::/64\",\n"
+"                \"t1-percent\": 0.5,\n"
+"                \"t2-percent\": 0.8,\n"
+"                \"valid-lifetime\": 4000\n"
+"            }\n"
+"        ],\n"
+"        \"t1-percent\": 0.5,\n"
+"        \"t2-percent\": 0.8,\n"
+"        \"valid-lifetime\": 4000\n"
+"    }\n",
+    // CONFIGURATION 67
+"{\n"
+"        \"allocator\": \"iterative\",\n"
+"        \"calculate-tee-times\": true,\n"
+"        \"ddns-conflict-resolution-mode\": \"check-with-dhcid\",\n"
+"        \"ddns-generated-prefix\": \"myhost\",\n"
+"        \"ddns-override-client-update\": false,\n"
+"        \"ddns-override-no-update\": false,\n"
+"        \"ddns-qualifying-suffix\": \"\",\n"
+"        \"ddns-replace-client-name\": \"never\",\n"
+"        \"ddns-send-updates\": true,\n"
+"        \"ddns-update-on-renew\": false,\n"
+"        \"decline-probation-period\": 86400,\n"
+"        \"dhcp-ddns\": {\n"
+"            \"enable-updates\": false,\n"
+"            \"max-queue-size\": 1024,\n"
+"            \"ncr-format\": \"JSON\",\n"
+"            \"ncr-protocol\": \"UDP\",\n"
+"            \"sender-ip\": \"0.0.0.0\",\n"
+"            \"sender-port\": 0,\n"
+"            \"server-ip\": \"127.0.0.1\",\n"
+"            \"server-port\": 53001\n"
+"        },\n"
+"        \"dhcp-queue-control\": {\n"
+"            \"capacity\": 64,\n"
+"            \"enable-queue\": false,\n"
+"            \"queue-type\": \"kea-ring6\"\n"
+"        },\n"
+"        \"dhcp4o6-port\": 0,\n"
+"        \"early-global-reservations-lookup\": false,\n"
+"        \"expired-leases-processing\": {\n"
+"            \"flush-reclaimed-timer-wait-time\": 25,\n"
+"            \"hold-reclaimed-time\": 3600,\n"
+"            \"max-reclaim-leases\": 100,\n"
+"            \"max-reclaim-time\": 250,\n"
+"            \"reclaim-timer-wait-time\": 10,\n"
+"            \"unwarned-reclaim-cycles\": 5\n"
+"        },\n"
+"        \"hooks-libraries\": [ ],\n"
+"        \"host-reservation-identifiers\": [ \"hw-address\", \"duid\" ],\n"
+"        \"hostname-char-replacement\": \"\",\n"
+"        \"hostname-char-set\": \"[^A-Za-z0-9.-]\",\n"
+"        \"interfaces-config\": {\n"
+"            \"interfaces\": [ \"*\" ],\n"
+"            \"re-detect\": false\n"
 "        },\n"
 "        \"ip-reservations-unique\": true,\n"
 "        \"lease-database\": {\n"
@@ -9659,37 +11547,211 @@ const char* UNPARSED_CONFIGS[] = {
 "            \"packet-queue-size\": 64,\n"
 "            \"thread-pool-size\": 0\n"
 "        },\n"
-"        \"option-data\": [\n"
+"        \"option-data\": [ ],\n"
+"        \"option-def\": [ ],\n"
+"        \"parked-packet-limit\": 256,\n"
+"        \"pd-allocator\": \"iterative\",\n"
+"        \"preferred-lifetime\": 3000,\n"
+"        \"relay-supplied-options\": [ \"65\" ],\n"
+"        \"reservations-global\": false,\n"
+"        \"reservations-in-subnet\": true,\n"
+"        \"reservations-lookup-first\": false,\n"
+"        \"reservations-out-of-pool\": false,\n"
+"        \"sanity-checks\": {\n"
+"            \"extended-info-checks\": \"fix\",\n"
+"            \"lease-checks\": \"warn\"\n"
+"        },\n"
+"        \"server-id\": {\n"
+"            \"enterprise-id\": 0,\n"
+"            \"htype\": 0,\n"
+"            \"identifier\": \"\",\n"
+"            \"persist\": true,\n"
+"            \"time\": 0,\n"
+"            \"type\": \"LLT\"\n"
+"        },\n"
+"        \"server-tag\": \"\",\n"
+"        \"shared-networks\": [\n"
 "            {\n"
-"                \"always-send\": false,\n"
-"                \"code\": 38,\n"
-"                \"csv-format\": false,\n"
-"                \"data\": \"ABCDEF0105\",\n"
-"                \"name\": \"subscriber-id\",\n"
-"                \"never-send\": false,\n"
-"                \"space\": \"dhcp6\",\n"
-"                \"user-context\": {\n"
-"                    \"comment\": \"Set option value\"\n"
-"                }\n"
+"                \"allocator\": \"iterative\",\n"
+"                \"calculate-tee-times\": true,\n"
+"                \"max-preferred-lifetime\": 3000,\n"
+"                \"max-valid-lifetime\": 4000,\n"
+"                \"min-preferred-lifetime\": 3000,\n"
+"                \"min-valid-lifetime\": 4000,\n"
+"                \"name\": \"foo\",\n"
+"                \"option-data\": [ ],\n"
+"                \"pd-allocator\": \"iterative\",\n"
+"                \"preferred-lifetime\": 3000,\n"
+"                \"rapid-commit\": false,\n"
+"                \"relay\": {\n"
+"                    \"ip-addresses\": [ ]\n"
+"                },\n"
+"                \"store-extended-info\": false,\n"
+"                \"subnet6\": [\n"
+"                    {\n"
+"                        \"allocator\": \"iterative\",\n"
+"                        \"calculate-tee-times\": false,\n"
+"                        \"id\": 100,\n"
+"                        \"max-preferred-lifetime\": 3000,\n"
+"                        \"max-valid-lifetime\": 4000,\n"
+"                        \"min-preferred-lifetime\": 3000,\n"
+"                        \"min-valid-lifetime\": 4000,\n"
+"                        \"option-data\": [ ],\n"
+"                        \"pd-allocator\": \"iterative\",\n"
+"                        \"pd-pools\": [ ],\n"
+"                        \"pools\": [\n"
+"                            {\n"
+"                                \"option-data\": [ ],\n"
+"                                \"pool\": \"2001:db8:1::/80\"\n"
+"                            }\n"
+"                        ],\n"
+"                        \"preferred-lifetime\": 3000,\n"
+"                        \"relay\": {\n"
+"                            \"ip-addresses\": [ ]\n"
+"                        },\n"
+"                        \"reservations\": [ ],\n"
+"                        \"store-extended-info\": false,\n"
+"                        \"subnet\": \"2001:db8:1::/64\",\n"
+"                        \"t1-percent\": 0.45,\n"
+"                        \"t2-percent\": 0.65,\n"
+"                        \"valid-lifetime\": 4000\n"
+"                    },\n"
+"                    {\n"
+"                        \"allocator\": \"iterative\",\n"
+"                        \"calculate-tee-times\": true,\n"
+"                        \"id\": 200,\n"
+"                        \"max-preferred-lifetime\": 3000,\n"
+"                        \"max-valid-lifetime\": 4000,\n"
+"                        \"min-preferred-lifetime\": 3000,\n"
+"                        \"min-valid-lifetime\": 4000,\n"
+"                        \"option-data\": [ ],\n"
+"                        \"pd-allocator\": \"iterative\",\n"
+"                        \"pd-pools\": [ ],\n"
+"                        \"pools\": [\n"
+"                            {\n"
+"                                \"option-data\": [ ],\n"
+"                                \"pool\": \"2001:db8:2::/80\"\n"
+"                            }\n"
+"                        ],\n"
+"                        \"preferred-lifetime\": 3000,\n"
+"                        \"relay\": {\n"
+"                            \"ip-addresses\": [ ]\n"
+"                        },\n"
+"                        \"reservations\": [ ],\n"
+"                        \"store-extended-info\": false,\n"
+"                        \"subnet\": \"2001:db8:2::/64\",\n"
+"                        \"t1-percent\": 0.4,\n"
+"                        \"t2-percent\": 0.75,\n"
+"                        \"valid-lifetime\": 4000\n"
+"                    }\n"
+"                ],\n"
+"                \"t1-percent\": 0.4,\n"
+"                \"t2-percent\": 0.75,\n"
+"                \"valid-lifetime\": 4000\n"
 "            }\n"
 "        ],\n"
-"        \"option-def\": [\n"
+"        \"statistic-default-sample-age\": 0,\n"
+"        \"statistic-default-sample-count\": 20,\n"
+"        \"store-extended-info\": false,\n"
+"        \"subnet6\": [\n"
 "            {\n"
-"                \"array\": false,\n"
-"                \"code\": 100,\n"
-"                \"encapsulate\": \"\",\n"
-"                \"name\": \"foo\",\n"
-"                \"record-types\": \"\",\n"
-"                \"space\": \"isc\",\n"
-"                \"type\": \"ipv6-address\",\n"
-"                \"user-context\": {\n"
-"                    \"comment\": \"An option definition\"\n"
-"                }\n"
+"                \"allocator\": \"iterative\",\n"
+"                \"calculate-tee-times\": true,\n"
+"                \"id\": 300,\n"
+"                \"max-preferred-lifetime\": 3000,\n"
+"                \"max-valid-lifetime\": 4000,\n"
+"                \"min-preferred-lifetime\": 3000,\n"
+"                \"min-valid-lifetime\": 4000,\n"
+"                \"option-data\": [ ],\n"
+"                \"pd-allocator\": \"iterative\",\n"
+"                \"pd-pools\": [ ],\n"
+"                \"pools\": [\n"
+"                    {\n"
+"                        \"option-data\": [ ],\n"
+"                        \"pool\": \"2001:db8:3::/80\"\n"
+"                    }\n"
+"                ],\n"
+"                \"preferred-lifetime\": 3000,\n"
+"                \"rapid-commit\": false,\n"
+"                \"relay\": {\n"
+"                    \"ip-addresses\": [ ]\n"
+"                },\n"
+"                \"reservations\": [ ],\n"
+"                \"store-extended-info\": false,\n"
+"                \"subnet\": \"2001:db8:3::/64\",\n"
+"                \"t1-percent\": 0.5,\n"
+"                \"t2-percent\": 0.8,\n"
+"                \"valid-lifetime\": 4000\n"
 "            }\n"
 "        ],\n"
+"        \"t1-percent\": 0.5,\n"
+"        \"t2-percent\": 0.8,\n"
+"        \"valid-lifetime\": 4000\n"
+"    }\n",
+    // CONFIGURATION 68
+"{\n"
+"        \"allocator\": \"iterative\",\n"
+"        \"calculate-tee-times\": true,\n"
+"        \"ddns-conflict-resolution-mode\": \"check-with-dhcid\",\n"
+"        \"ddns-generated-prefix\": \"myhost\",\n"
+"        \"ddns-override-client-update\": false,\n"
+"        \"ddns-override-no-update\": false,\n"
+"        \"ddns-qualifying-suffix\": \"\",\n"
+"        \"ddns-replace-client-name\": \"never\",\n"
+"        \"ddns-send-updates\": true,\n"
+"        \"ddns-update-on-renew\": false,\n"
+"        \"decline-probation-period\": 86400,\n"
+"        \"dhcp-ddns\": {\n"
+"            \"enable-updates\": false,\n"
+"            \"max-queue-size\": 1024,\n"
+"            \"ncr-format\": \"JSON\",\n"
+"            \"ncr-protocol\": \"UDP\",\n"
+"            \"sender-ip\": \"0.0.0.0\",\n"
+"            \"sender-port\": 0,\n"
+"            \"server-ip\": \"127.0.0.1\",\n"
+"            \"server-port\": 53001\n"
+"        },\n"
+"        \"dhcp-queue-control\": {\n"
+"            \"capacity\": 64,\n"
+"            \"enable-queue\": false,\n"
+"            \"queue-type\": \"kea-ring6\"\n"
+"        },\n"
+"        \"dhcp4o6-port\": 0,\n"
+"        \"early-global-reservations-lookup\": false,\n"
+"        \"expired-leases-processing\": {\n"
+"            \"flush-reclaimed-timer-wait-time\": 25,\n"
+"            \"hold-reclaimed-time\": 3600,\n"
+"            \"max-reclaim-leases\": 100,\n"
+"            \"max-reclaim-time\": 250,\n"
+"            \"reclaim-timer-wait-time\": 10,\n"
+"            \"unwarned-reclaim-cycles\": 5\n"
+"        },\n"
+"        \"hooks-libraries\": [ ],\n"
+"        \"host-reservation-identifiers\": [ \"hw-address\", \"duid\" ],\n"
+"        \"hostname-char-replacement\": \"\",\n"
+"        \"hostname-char-set\": \"[^A-Za-z0-9.-]\",\n"
+"        \"interfaces-config\": {\n"
+"            \"interfaces\": [ \"*\" ],\n"
+"            \"re-detect\": false\n"
+"        },\n"
+"        \"ip-reservations-unique\": true,\n"
+"        \"lease-database\": {\n"
+"            \"type\": \"memfile\"\n"
+"        },\n"
+"        \"mac-sources\": [ \"any\" ],\n"
+"        \"multi-threading\": {\n"
+"            \"enable-multi-threading\": true,\n"
+"            \"packet-queue-size\": 64,\n"
+"            \"thread-pool-size\": 0\n"
+"        },\n"
+"        \"option-data\": [ ],\n"
+"        \"option-def\": [ ],\n"
 "        \"parked-packet-limit\": 256,\n"
 "        \"pd-allocator\": \"iterative\",\n"
+"        \"preferred-lifetime\": 3000,\n"
+"        \"rebind-timer\": 2000,\n"
 "        \"relay-supplied-options\": [ \"65\" ],\n"
+"        \"renew-timer\": 1000,\n"
 "        \"reservations-global\": false,\n"
 "        \"reservations-in-subnet\": true,\n"
 "        \"reservations-lookup-first\": false,\n"
@@ -9704,114 +11766,82 @@ const char* UNPARSED_CONFIGS[] = {
 "            \"identifier\": \"\",\n"
 "            \"persist\": true,\n"
 "            \"time\": 0,\n"
-"            \"type\": \"LL\",\n"
-"            \"user-context\": {\n"
-"                \"comment\": \"DHCPv6 specific\"\n"
-"            }\n"
+"            \"type\": \"LLT\"\n"
 "        },\n"
 "        \"server-tag\": \"\",\n"
-"        \"shared-networks\": [\n"
+"        \"shared-networks\": [ ],\n"
+"        \"statistic-default-sample-age\": 0,\n"
+"        \"statistic-default-sample-count\": 20,\n"
+"        \"store-extended-info\": false,\n"
+"        \"subnet6\": [\n"
 "            {\n"
 "                \"allocator\": \"iterative\",\n"
 "                \"calculate-tee-times\": true,\n"
-"                \"max-valid-lifetime\": 7200,\n"
-"                \"min-valid-lifetime\": 7200,\n"
-"                \"name\": \"foo\",\n"
+"                \"id\": 1,\n"
+"                \"max-preferred-lifetime\": 3000,\n"
+"                \"max-valid-lifetime\": 4000,\n"
+"                \"min-preferred-lifetime\": 3000,\n"
+"                \"min-valid-lifetime\": 4000,\n"
 "                \"option-data\": [ ],\n"
 "                \"pd-allocator\": \"iterative\",\n"
+"                \"pd-pools\": [ ],\n"
+"                \"pools\": [\n"
+"                    {\n"
+"                        \"option-data\": [ ],\n"
+"                        \"pool\": \"2001:db8:1::1-2001:db8:1::ffff\"\n"
+"                    }\n"
+"                ],\n"
+"                \"preferred-lifetime\": 3000,\n"
 "                \"rapid-commit\": false,\n"
+"                \"rebind-timer\": 2000,\n"
 "                \"relay\": {\n"
 "                    \"ip-addresses\": [ ]\n"
 "                },\n"
+"                \"renew-timer\": 1000,\n"
+"                \"reservations\": [ ],\n"
 "                \"store-extended-info\": false,\n"
-"                \"subnet6\": [\n"
+"                \"subnet\": \"2001:db8:1::/64\",\n"
+"                \"t1-percent\": 0.5,\n"
+"                \"t2-percent\": 0.8,\n"
+"                \"valid-lifetime\": 4000\n"
+"            },\n"
+"            {\n"
+"                \"allocator\": \"iterative\",\n"
+"                \"calculate-tee-times\": true,\n"
+"                \"id\": 2,\n"
+"                \"max-preferred-lifetime\": 3000,\n"
+"                \"max-valid-lifetime\": 4000,\n"
+"                \"min-preferred-lifetime\": 3000,\n"
+"                \"min-valid-lifetime\": 4000,\n"
+"                \"option-data\": [ ],\n"
+"                \"pd-allocator\": \"iterative\",\n"
+"                \"pd-pools\": [ ],\n"
+"                \"pools\": [\n"
 "                    {\n"
-"                        \"allocator\": \"iterative\",\n"
-"                        \"calculate-tee-times\": true,\n"
-"                        \"id\": 100,\n"
-"                        \"max-valid-lifetime\": 7200,\n"
-"                        \"min-valid-lifetime\": 7200,\n"
 "                        \"option-data\": [ ],\n"
-"                        \"pd-allocator\": \"iterative\",\n"
-"                        \"pd-pools\": [\n"
-"                            {\n"
-"                                \"delegated-len\": 64,\n"
-"                                \"option-data\": [ ],\n"
-"                                \"prefix\": \"2001:db2::\",\n"
-"                                \"prefix-len\": 48,\n"
-"                                \"user-context\": {\n"
-"                                    \"comment\": \"A prefix pool\"\n"
-"                                }\n"
-"                            }\n"
-"                        ],\n"
-"                        \"pools\": [\n"
-"                            {\n"
-"                                \"option-data\": [ ],\n"
-"                                \"pool\": \"2001:db1::/64\",\n"
-"                                \"user-context\": {\n"
-"                                    \"comment\": \"A pool\"\n"
-"                                }\n"
-"                            }\n"
-"                        ],\n"
-"                        \"relay\": {\n"
-"                            \"ip-addresses\": [ ]\n"
-"                        },\n"
-"                        \"reservations\": [\n"
-"                            {\n"
-"                                \"client-classes\": [ ],\n"
-"                                \"hostname\": \"foo.example.com\",\n"
-"                                \"hw-address\": \"aa:bb:cc:dd:ee:ff\",\n"
-"                                \"ip-addresses\": [ ],\n"
-"                                \"option-data\": [\n"
-"                                    {\n"
-"                                        \"always-send\": false,\n"
-"                                        \"code\": 24,\n"
-"                                        \"csv-format\": true,\n"
-"                                        \"data\": \"example.com\",\n"
-"                                        \"name\": \"domain-search\",\n"
-"                                        \"never-send\": false,\n"
-"                                        \"space\": \"dhcp6\",\n"
-"                                        \"user-context\": {\n"
-"                                            \"comment\": \"An option in a reservation\"\n"
-"                                        }\n"
-"                                    }\n"
-"                                ],\n"
-"                                \"prefixes\": [ ],\n"
-"                                \"user-context\": {\n"
-"                                    \"comment\": \"A host reservation\"\n"
-"                                }\n"
-"                            }\n"
-"                        ],\n"
-"                        \"store-extended-info\": false,\n"
-"                        \"subnet\": \"2001:db1::/48\",\n"
-"                        \"t1-percent\": 0.5,\n"
-"                        \"t2-percent\": 0.8,\n"
-"                        \"user-context\": {\n"
-"                            \"comment\": \"A subnet\"\n"
-"                        },\n"
-"                        \"valid-lifetime\": 7200\n"
+"                        \"pool\": \"2001:db8:2::1-2001:db8:2::ffff\"\n"
 "                    }\n"
 "                ],\n"
+"                \"preferred-lifetime\": 3000,\n"
+"                \"rapid-commit\": false,\n"
+"                \"rebind-timer\": 2000,\n"
+"                \"relay\": {\n"
+"                    \"ip-addresses\": [ ]\n"
+"                },\n"
+"                \"renew-timer\": 1000,\n"
+"                \"reservations\": [ ],\n"
+"                \"store-extended-info\": true,\n"
+"                \"subnet\": \"2001:db8:2::/64\",\n"
 "                \"t1-percent\": 0.5,\n"
 "                \"t2-percent\": 0.8,\n"
-"                \"user-context\": {\n"
-"                    \"comment\": \"A shared network\"\n"
-"                },\n"
-"                \"valid-lifetime\": 7200\n"
+"                \"valid-lifetime\": 4000\n"
 "            }\n"
 "        ],\n"
-"        \"statistic-default-sample-age\": 0,\n"
-"        \"statistic-default-sample-count\": 20,\n"
-"        \"store-extended-info\": false,\n"
-"        \"subnet6\": [ ],\n"
 "        \"t1-percent\": 0.5,\n"
 "        \"t2-percent\": 0.8,\n"
-"        \"user-context\": {\n"
-"            \"comment\": \"A DHCPv6 server\"\n"
-"        },\n"
-"        \"valid-lifetime\": 7200\n"
+"        \"valid-lifetime\": 4000\n"
 "    }\n",
-    // CONFIGURATION 57
+    // CONFIGURATION 69
 "{\n"
 "        \"allocator\": \"iterative\",\n"
 "        \"calculate-tee-times\": true,\n"
@@ -9875,62 +11905,6 @@ const char* UNPARSED_CONFIGS[] = {
 "        \"rebind-timer\": 2000,\n"
 "        \"relay-supplied-options\": [ \"65\" ],\n"
 "        \"renew-timer\": 1000,\n"
-"        \"reservations\": [\n"
-"            {\n"
-"                \"client-classes\": [ ],\n"
-"                \"hostname\": \"\",\n"
-"                \"hw-address\": \"01:02:03:04:05:06\",\n"
-"                \"ip-addresses\": [ \"2001:db8:2::abcd\" ],\n"
-"                \"option-data\": [\n"
-"                    {\n"
-"                        \"always-send\": false,\n"
-"                        \"code\": 23,\n"
-"                        \"csv-format\": true,\n"
-"                        \"data\": \"2001:db8:2::abbc\",\n"
-"                        \"name\": \"dns-servers\",\n"
-"                        \"never-send\": false,\n"
-"                        \"space\": \"dhcp6\"\n"
-"                    },\n"
-"                    {\n"
-"                        \"always-send\": false,\n"
-"                        \"code\": 7,\n"
-"                        \"csv-format\": true,\n"
-"                        \"data\": \"25\",\n"
-"                        \"name\": \"preference\",\n"
-"                        \"never-send\": false,\n"
-"                        \"space\": \"dhcp6\"\n"
-"                    }\n"
-"                ],\n"
-"                \"prefixes\": [ ]\n"
-"            },\n"
-"            {\n"
-"                \"client-classes\": [ ],\n"
-"                \"duid\": \"01:02:03:04:05:06:07:08:09:0a\",\n"
-"                \"hostname\": \"\",\n"
-"                \"ip-addresses\": [ \"2001:db8:2::1234\" ],\n"
-"                \"option-data\": [\n"
-"                    {\n"
-"                        \"always-send\": false,\n"
-"                        \"code\": 23,\n"
-"                        \"csv-format\": true,\n"
-"                        \"data\": \"2001:db8:2::1111\",\n"
-"                        \"name\": \"dns-servers\",\n"
-"                        \"never-send\": false,\n"
-"                        \"space\": \"dhcp6\"\n"
-"                    },\n"
-"                    {\n"
-"                        \"always-send\": false,\n"
-"                        \"code\": 7,\n"
-"                        \"csv-format\": true,\n"
-"                        \"data\": \"11\",\n"
-"                        \"name\": \"preference\",\n"
-"                        \"never-send\": false,\n"
-"                        \"space\": \"dhcp6\"\n"
-"                    }\n"
-"                ],\n"
-"                \"prefixes\": [ ]\n"
-"            }\n"
-"        ],\n"
 "        \"reservations-global\": false,\n"
 "        \"reservations-in-subnet\": true,\n"
 "        \"reservations-lookup-first\": false,\n"
@@ -9951,12 +11925,12 @@ const char* UNPARSED_CONFIGS[] = {
 "        \"shared-networks\": [ ],\n"
 "        \"statistic-default-sample-age\": 0,\n"
 "        \"statistic-default-sample-count\": 20,\n"
-"        \"store-extended-info\": false,\n"
+"        \"store-extended-info\": true,\n"
 "        \"subnet6\": [\n"
 "            {\n"
 "                \"allocator\": \"iterative\",\n"
 "                \"calculate-tee-times\": true,\n"
-"                \"id\": 123,\n"
+"                \"id\": 1,\n"
 "                \"max-preferred-lifetime\": 3000,\n"
 "                \"max-valid-lifetime\": 4000,\n"
 "                \"min-preferred-lifetime\": 3000,\n"
@@ -9967,7 +11941,7 @@ const char* UNPARSED_CONFIGS[] = {
 "                \"pools\": [\n"
 "                    {\n"
 "                        \"option-data\": [ ],\n"
-"                        \"pool\": \"2001:db8:1::/80\"\n"
+"                        \"pool\": \"2001:db8:1::1-2001:db8:1::ffff\"\n"
 "                    }\n"
 "                ],\n"
 "                \"preferred-lifetime\": 3000,\n"
@@ -9987,7 +11961,7 @@ const char* UNPARSED_CONFIGS[] = {
 "            {\n"
 "                \"allocator\": \"iterative\",\n"
 "                \"calculate-tee-times\": true,\n"
-"                \"id\": 234,\n"
+"                \"id\": 2,\n"
 "                \"max-preferred-lifetime\": 3000,\n"
 "                \"max-valid-lifetime\": 4000,\n"
 "                \"min-preferred-lifetime\": 3000,\n"
@@ -9995,7 +11969,12 @@ const char* UNPARSED_CONFIGS[] = {
 "                \"option-data\": [ ],\n"
 "                \"pd-allocator\": \"iterative\",\n"
 "                \"pd-pools\": [ ],\n"
-"                \"pools\": [ ],\n"
+"                \"pools\": [\n"
+"                    {\n"
+"                        \"option-data\": [ ],\n"
+"                        \"pool\": \"2001:db8:2::1-2001:db8:2::ffff\"\n"
+"                    }\n"
+"                ],\n"
 "                \"preferred-lifetime\": 3000,\n"
 "                \"rapid-commit\": false,\n"
 "                \"rebind-timer\": 2000,\n"
@@ -10004,44 +11983,18 @@ const char* UNPARSED_CONFIGS[] = {
 "                },\n"
 "                \"renew-timer\": 1000,\n"
 "                \"reservations\": [ ],\n"
-"                \"store-extended-info\": false,\n"
+"                \"store-extended-info\": true,\n"
 "                \"subnet\": \"2001:db8:2::/64\",\n"
 "                \"t1-percent\": 0.5,\n"
 "                \"t2-percent\": 0.8,\n"
 "                \"valid-lifetime\": 4000\n"
-"            },\n"
-"            {\n"
-"                \"allocator\": \"iterative\",\n"
-"                \"calculate-tee-times\": true,\n"
-"                \"id\": 542,\n"
-"                \"max-preferred-lifetime\": 3000,\n"
-"                \"max-valid-lifetime\": 4000,\n"
-"                \"min-preferred-lifetime\": 3000,\n"
-"                \"min-valid-lifetime\": 4000,\n"
-"                \"option-data\": [ ],\n"
-"                \"pd-allocator\": \"iterative\",\n"
-"                \"pd-pools\": [ ],\n"
-"                \"pools\": [ ],\n"
-"                \"preferred-lifetime\": 3000,\n"
-"                \"rapid-commit\": false,\n"
-"                \"rebind-timer\": 2000,\n"
-"                \"relay\": {\n"
-"                    \"ip-addresses\": [ ]\n"
-"                },\n"
-"                \"renew-timer\": 1000,\n"
-"                \"reservations\": [ ],\n"
-"                \"store-extended-info\": false,\n"
-"                \"subnet\": \"2001:db8:3::/64\",\n"
-"                \"t1-percent\": 0.5,\n"
-"                \"t2-percent\": 0.8,\n"
-"                \"valid-lifetime\": 4000\n"
 "            }\n"
 "        ],\n"
 "        \"t1-percent\": 0.5,\n"
 "        \"t2-percent\": 0.8,\n"
 "        \"valid-lifetime\": 4000\n"
 "    }\n",
-    // CONFIGURATION 58
+    // CONFIGURATION 70
 "{\n"
 "        \"allocator\": \"iterative\",\n"
 "        \"calculate-tee-times\": true,\n"
@@ -10131,7 +12084,7 @@ const char* UNPARSED_CONFIGS[] = {
 "        \"t2-percent\": 0.8,\n"
 "        \"valid-lifetime\": 4000\n"
 "    }\n",
-    // CONFIGURATION 59
+    // CONFIGURATION 71
 "{\n"
 "        \"allocator\": \"iterative\",\n"
 "        \"calculate-tee-times\": true,\n"
@@ -10218,7 +12171,7 @@ const char* UNPARSED_CONFIGS[] = {
 "        \"t2-percent\": 0.8,\n"
 "        \"valid-lifetime\": 7200\n"
 "    }\n",
-    // CONFIGURATION 60
+    // CONFIGURATION 72
 "{\n"
 "        \"allocator\": \"iterative\",\n"
 "        \"calculate-tee-times\": true,\n"
@@ -10305,7 +12258,7 @@ const char* UNPARSED_CONFIGS[] = {
 "        \"t2-percent\": 0.8,\n"
 "        \"valid-lifetime\": 7200\n"
 "    }\n",
-    // CONFIGURATION 61
+    // CONFIGURATION 73
 "{\n"
 "        \"allocator\": \"iterative\",\n"
 "        \"calculate-tee-times\": true,\n"
@@ -10435,7 +12388,7 @@ const char* UNPARSED_CONFIGS[] = {
 "        \"t2-percent\": 0.8,\n"
 "        \"valid-lifetime\": 7200\n"
 "    }\n",
-    // CONFIGURATION 62
+    // CONFIGURATION 74
 "{\n"
 "        \"allocator\": \"iterative\",\n"
 "        \"calculate-tee-times\": true,\n"
@@ -10567,7 +12520,7 @@ const char* UNPARSED_CONFIGS[] = {
 "        \"t2-percent\": 0.8,\n"
 "        \"valid-lifetime\": 7200\n"
 "    }\n",
-    // CONFIGURATION 63
+    // CONFIGURATION 75
 "{\n"
 "        \"allocator\": \"iterative\",\n"
 "        \"calculate-tee-times\": true,\n"
index b07abaa16d0435eb4169a7b4a9905ab8b86dc4ae..1a619eaa9168a0a8035a836b6f4f047e20fb3a81 100644 (file)
@@ -9,25 +9,24 @@
 #include <cc/command_interpreter.h>
 #include <cc/data.h>
 #include <cc/simple_parser.h>
-#include <cc/cfg_to_element.h>
-#include <testutils/user_context_utils.h>
 #include <dhcp/testutils/iface_mgr_test_config.h>
-#include <dhcpsrv/cfgmgr.h>
-#include <dhcpsrv/parsers/simple_parser6.h>
-#include <dhcp6/dhcp6_srv.h>
 #include <dhcp6/ctrl_dhcp6_srv.h>
+#include <dhcp6/dhcp6_srv.h>
 #include <dhcp6/json_config_parser.h>
 #include <dhcp6/tests/dhcp6_test_utils.h>
 #include <dhcp6/tests/get_config_unittest.h>
+#include <dhcpsrv/cfgmgr.h>
 #include <testutils/gtest_utils.h>
-
-#include <boost/algorithm/string.hpp>
-#include <gtest/gtest.h>
+#include <testutils/user_context_utils.h>
 
 #include <iostream>
-#include <string>
-#include <sstream>
 #include <list>
+#include <sstream>
+#include <string>
+
+#include <boost/algorithm/string.hpp>
+
+#include <gtest/gtest.h>
 
 using namespace isc::config;
 using namespace isc::data;
index 9ec596040e18fe7c214c4b59e98511480a600b25..0c1482e82c841ca04dc9fc5dd710d726cb4d3259 100644 (file)
@@ -173,7 +173,7 @@ typedef boost::shared_ptr<TestCBControlDHCPv6> TestCBControlDHCPv6Ptr;
 ///
 /// Exposes internal fields and installs stub implementation of the
 /// @c CBControlDHCPv6 object.
-class NakedControlledDhcpv6Srv: public ControlledDhcpv6Srv {
+class NakedControlledDhcpv6Srv : public ControlledDhcpv6Srv {
 public:
 
     /// @brief Constructor.
@@ -185,7 +185,12 @@ public:
     }
 };
 
-
+/// @brief test class for Kea configuration backend.
+///
+/// This class is used for testing Kea configuration backend.
+/// It is very simple and currently focuses on reading
+/// config file from disk. It is expected to be expanded in the
+/// near future.
 class JSONFileBackendTest : public dhcp::test::BaseServerTest {
 public:
     JSONFileBackendTest() {
@@ -286,7 +291,6 @@ public:
         EXPECT_EQ(0, cb_control->getDatabaseCurrentConfigFetchCalls());
         EXPECT_EQ(1, cb_control->getDatabaseStagingConfigFetchCalls());
 
-
         if (call_command) {
             // The case where there is no backend is tested in the
             // controlled server tests so we have only to verify
@@ -796,7 +800,6 @@ TEST_F(JSONFileBackendTest, timers) {
                                        duid_expired, 1, 50, 60, SubnetID(1)));
     lease_expired->cltt_ = time(NULL) - 100;
 
-
     // Create expired-reclaimed lease. The lease has expired 1000 - 60 seconds
     // ago. It should be removed from the lease database when the "flush" timer
     // goes off.
@@ -1062,7 +1065,6 @@ testBackendReconfiguration(const std::string& backend_first,
               LeaseMgrFactory::instance().getType());
 }
 
-
 // This test verifies that backend specification can be added on
 // server reconfiguration.
 TEST_F(JSONFileBackendMySQLTest, reconfigureBackendUndefinedToMySQL) {
index d0e20fc11176a48ebab9dc90cdbf02e9714db236..3e57c51e9fa661a66c9bb982777b65dfccd62195 100644 (file)
@@ -57,15 +57,14 @@ ParserContext::parseCommon() {
             isc_throw(ParseError, "Parser abort");
         }
         scanEnd();
-    }
-    catch (...) {
+    } catch (...) {
         scanEnd();
         throw;
     }
     if (stack_.size() == 1) {
         return (stack_[0]);
     } else {
-        isc_throw(ParseError, "Expected exactly one terminal Element expected, found "
+        isc_throw(ParseError, "Expected exactly one terminal Element, found "
                   << stack_.size());
     }
 }
index 6a79340f4aa10f36d32ff6ae902421bc1db28de4..7c7a3552699d0c249925572746ad568e837c4153 100644 (file)
@@ -241,7 +241,8 @@ DatabaseConnection::toElement(const ParameterMap& params) {
                     .arg(keyword).arg(value);
             }
         } else if ((keyword == "persist") ||
-                   (keyword == "readonly")) {
+                   (keyword == "readonly") ||
+                   (keyword == "retry-on-startup")) {
             if (value == "true") {
                 result->set(keyword, isc::data::Element::create(true));
             } else if (value == "false") {
@@ -256,7 +257,6 @@ DatabaseConnection::toElement(const ParameterMap& params) {
                    (keyword == "host") ||
                    (keyword == "name") ||
                    (keyword == "on-fail") ||
-                   (keyword == "retry-on-startup") ||
                    (keyword == "trust-anchor") ||
                    (keyword == "cert-file") ||
                    (keyword == "key-file") ||
index d8fec9e6593a5892eef9608e6465a24bc42e32b3..070a5c65598d6b9500342acc7c1b23ba7e89edcb 100644 (file)
@@ -536,6 +536,7 @@ TEST(DatabaseConnection, toElementDbAccessStringValid) {
         "\"port\" : 300, \n"
         "\"readonly\" : false, \n"
         "\"reconnect-wait-time\": 99, \n"
+        "\"retry-on-startup\" : true, \n"
         "\"type\": \"memfile\", \n"
         "\"user\": \"user_str\", \n"
         "\"max-row-errors\": 50, \n"