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());
}
}
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());
}
}
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());
}
}
#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;
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\": [\"*\" ]"
" \"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\": {"
" \"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 {
}
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).
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());
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));
}
}
- ~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 {
/// @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, "
} 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") {
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);
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.
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.
}
// 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));
}
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
/// @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 }, "
<< 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
};
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 }"));
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\" } ],"
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\" } ],"
checkResult(status, 1, expected);
resetConfiguration();
- string before = "{ " + genIfaceConfig() + "," +
+ string before = "{ " + genIfaceConfig() + ","
"\"subnet4\": [ { "
" \"id\": 1,"
" \"pools\": [ { \"pool\": \"192.0.2.1 - 192.0.2.100\" } ],"
checkResult(status, 1, expected);
resetConfiguration();
- string after = "{ " + genIfaceConfig() + "," +
+ string after = "{ " + genIfaceConfig() + ","
"\"subnet4\": [ { "
" \"id\": 1,"
" \"pools\": [ { \"pool\": \"192.0.2.1 - 192.0.2.100\" } ],"
checkResult(status, 1, expected);
resetConfiguration();
- string crossed = "{ " + genIfaceConfig() + "," +
+ string crossed = "{ " + genIfaceConfig() + ","
"\"subnet4\": [ { "
" \"id\": 1,"
" \"pools\": [ { \"pool\": \"192.0.2.1 - 192.0.2.100\" } ],"
/// parameters only.
TEST_F(Dhcp4ParserTest, outBoundGlobalValidLifetime) {
- string too_small = "{ " + genIfaceConfig() + "," +
+ string too_small = "{ " + genIfaceConfig() + ","
"\"valid-lifetime\": 1000, \"min-valid-lifetime\": 2000 }";
ConstElementPtr json;
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));
checkResult(status, 1, expected);
resetConfiguration();
- string before = "{ " + genIfaceConfig() + "," +
+ string before = "{ " + genIfaceConfig() + ","
"\"valid-lifetime\": 1000, \"min-valid-lifetime\": 2000, "
"\"max-valid-lifetime\": 4000 }";
checkResult(status, 1, expected);
resetConfiguration();
- string after = "{ " + genIfaceConfig() + "," +
+ string after = "{ " + genIfaceConfig() + ","
"\"valid-lifetime\": 5000, \"min-valid-lifetime\": 1000, "
"\"max-valid-lifetime\": 4000 }";
checkResult(status, 1, expected);
resetConfiguration();
- string crossed = "{ " + genIfaceConfig() + "," +
+ string crossed = "{ " + genIfaceConfig() + ","
"\"valid-lifetime\": 1500, \"min-valid-lifetime\": 2000, "
"\"max-valid-lifetime\": 1000 }";
/// it is marked unspecified in the Subnet.
TEST_F(Dhcp4ParserTest, unspecifiedRenewTimer) {
- string config = "{ " + genIfaceConfig() + "," +
+ string config = "{ " + genIfaceConfig() + ","
"\"rebind-timer\": 2000, "
"\"subnet4\": [ { "
" \"id\": 1,"
/// it is marked unspecified in the Subnet.
TEST_F(Dhcp4ParserTest, unspecifiedRebindTimer) {
- string config = "{ " + genIfaceConfig() + "," +
+ string config = "{ " + genIfaceConfig() + ","
"\"renew-timer\": 1000, "
"\"subnet4\": [ { "
" \"id\": 1,"
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\": [ { "
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);
} 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 }";
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 }";
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
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)
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.
// 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\", "
// subnet parameter are taken into consideration.
TEST_F(Dhcp4ParserTest, nextServerSubnet) {
- string config = "{ " + genIfaceConfig() + "," +
+ string config = "{ " + genIfaceConfig() + ","
"\"rebind-timer\": 2000, "
"\"renew-timer\": 1000, "
"\"subnet4\": [ { "
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\": [ { "
"\"valid-lifetime\": 4000 }";
// Config with IPv6 next server address
- string config_bogus2 = "{ " + genIfaceConfig() + "," +
+ string config_bogus2 = "{ " + genIfaceConfig() + ","
"\"rebind-timer\": 2000, "
"\"renew-timer\": 1000, "
"\"subnet4\": [ { "
"\"valid-lifetime\": 4000 }";
// Config with empty next server address
- string config_bogus3 = "{ " + genIfaceConfig() + "," +
+ string config_bogus3 = "{ " + genIfaceConfig() + ","
"\"rebind-timer\": 2000, "
"\"renew-timer\": 1000, "
"\"subnet4\": [ { "
// 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\": [ { "
// 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\": [ { "
// specific value.
TEST_F(Dhcp4ParserTest, nextServerOverride) {
- string config = "{ " + genIfaceConfig() + "," +
+ string config = "{ " + genIfaceConfig() + ","
"\"rebind-timer\": 2000, "
"\"renew-timer\": 1000, "
"\"next-server\": \"192.0.0.1\", "
// 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,"
" \"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,"
// 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\": { "
// Check that unknown compatibility flag raises error.
TEST_F(Dhcp4ParserTest, compatibilityUnknown) {
- string config = "{ " + genIfaceConfig() + "," +
+ string config = "{ " + genIfaceConfig() + ","
"\"rebind-timer\": 2000, "
"\"renew-timer\": 1000, "
"\"compatibility\": { "
// 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\": { "
// 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\": [ "
// 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,"
// 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\": [ "
// 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,"
// on a per subnet basis.
TEST_F(Dhcp4ParserTest, subnetLocal) {
- string config = "{ " + genIfaceConfig() + "," +
+ string config = "{ " + genIfaceConfig() + ","
"\"rebind-timer\": 2000, "
"\"renew-timer\": 1000, "
"\"subnet4\": [ { "
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));
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);
TEST_F(Dhcp4ParserTest, badPools) {
// not a prefix
- string config_bogus1 = "{ " + genIfaceConfig() + "," +
+ string config_bogus1 = "{ " + genIfaceConfig() + ","
"\"rebind-timer\": 2000, "
"\"renew-timer\": 1000, "
"\"subnet4\": [ { "
"\"valid-lifetime\": 4000 }";
// not a length
- string config_bogus2 = "{ " + genIfaceConfig() + "," +
+ string config_bogus2 = "{ " + genIfaceConfig() + ","
"\"rebind-timer\": 2000, "
"\"renew-timer\": 1000, "
"\"subnet4\": [ { "
"\"valid-lifetime\": 4000 }";
// invalid prefix length
- string config_bogus3 = "{ " + genIfaceConfig() + "," +
+ string config_bogus3 = "{ " + genIfaceConfig() + ","
"\"rebind-timer\": 2000, "
"\"renew-timer\": 1000, "
"\"subnet4\": [ { "
"\"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\": [ { "
"\"valid-lifetime\": 4000 }";
// not an address
- string config_bogus5 = "{ " + genIfaceConfig() + "," +
+ string config_bogus5 = "{ " + genIfaceConfig() + ","
"\"rebind-timer\": 2000, "
"\"renew-timer\": 1000, "
"\"subnet4\": [ { "
"\"valid-lifetime\": 4000 }";
// min > max
- string config_bogus6 = "{ " + genIfaceConfig() + "," +
+ string config_bogus6 = "{ " + genIfaceConfig() + ","
"\"rebind-timer\": 2000, "
"\"renew-timer\": 1000, "
"\"subnet4\": [ { "
"\"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\": [ { "
TEST_F(Dhcp4ParserTest, noPools) {
// Configuration string.
- string config = "{ " + genIfaceConfig() + "," +
+ string config = "{ " + genIfaceConfig() + ","
"\"rebind-timer\": 2000, "
"\"renew-timer\": 1000, "
"\"subnet4\": [ { "
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\": [ { "
/// 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\","
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\","
// 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\": [ {"
// 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\": [ { "
// 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,"
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_);
}
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
// 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,"
// 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,"
// option setting.
TEST_F(Dhcp4ParserTest, optionDataInSingleSubnet) {
ConstElementPtr x;
- string config = "{ " + genIfaceConfig() + "," +
+ string config = "{ " + genIfaceConfig() + ","
"\"rebind-timer\": 2000, "
"\"renew-timer\": 1000, "
"\"option-data\": [ {"
" 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
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\": [ { "
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
};
// 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
// 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 };
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());
// 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\": [ {"
// 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,"
// 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,"
}
// 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,"
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);
}
// 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,"
" } ]"
"}";
+ 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);
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.
ConstElementPtr json;
ASSERT_NO_THROW(json = parseDHCP4(config));
+
ConstElementPtr status;
ASSERT_NO_THROW(status = Dhcpv4SrvTest::configure(*srv_, json));
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\" ]"
"},"
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);
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
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);
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\": [ { "
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)
// 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\": [ { "
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)
// with defined client classes.
TEST_F(Dhcp4ParserTest, classifySubnets) {
ConstElementPtr x;
- string config = "{ " + genIfaceConfig() + "," +
+ string config = "{ " + genIfaceConfig() + ","
"\"rebind-timer\": 2000, "
"\"renew-timer\": 1000, "
"\"subnet4\": [ { "
// with defined client classes.
TEST_F(Dhcp4ParserTest, classifyPools) {
ConstElementPtr x;
- string config = "{ " + genIfaceConfig() + "," +
+ string config = "{ " + genIfaceConfig() + ","
"\"rebind-timer\": 2000, "
"\"renew-timer\": 1000, "
"\"subnet4\": [ { "
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\": [ "
" \"hostname\": \"\""
" }"
" ]"
- " } ],"
+ " } "
+ "], "
"\"valid-lifetime\": 4000 }";
ConstElementPtr json;
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()));
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,
// 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\": [ {"
" \"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));
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());
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\": [ "
" \"hostname\": \"\""
" }"
" ]"
- " } ],"
+ " } "
+ "], "
"\"valid-lifetime\": 4000 }";
ConstElementPtr json;
EXPECT_THROW(parseDHCP4(config), Dhcp4ParseError);
// Case 2: DUID and HW Address both specified.
- config = "{ " + genIfaceConfig() + "," +
+ config = "{ " + genIfaceConfig() + ","
"\"rebind-timer\": 2000, "
"\"renew-timer\": 1000, "
"\"subnet4\": [ "
checkResult(x, 1);
// Case 3: Broken specification of option data.
- config = "{ " + genIfaceConfig() + "," +
+ config = "{ " + genIfaceConfig() + ","
"\"rebind-timer\": 2000, "
"\"renew-timer\": 1000, "
"\"subnet4\": [ "
" ]"
" }"
" ]"
- " } ],"
+ " } "
+ "], "
"\"valid-lifetime\": 4000 }";
ASSERT_NO_THROW(json = parseDHCP4(config));
/// - 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\": [ { "
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
/// - 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,"
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
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());
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());
/// 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)
/// 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\": [ ]"
"}";
ASSERT_NO_THROW(json = parseDHCP4(config));
extractConfig(config);
+ ConstElementPtr status;
EXPECT_NO_THROW(status = Dhcpv4SrvTest::configure(*srv_, json));
// returned value should be 0 (success)
/// 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\": [ ]"
"}";
ConstElementPtr json;
ASSERT_NO_THROW(json = parseJSON(config));
+ ConstElementPtr status;
EXPECT_NO_THROW(status = Dhcpv4SrvTest::configure(*srv_, json));
// returned value should be 1 (error)
// 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,"
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,"
ConstElementPtr status;
// Just a plain v4 config (no 4o6 parameters)
- string config = "{ " + genIfaceConfig() + "," +
+ string config = "{ " + genIfaceConfig() + ","
"\"rebind-timer\": 2000, "
"\"renew-timer\": 1000, "
"\"subnet4\": [ { "
ConstElementPtr status;
// Just a plain v4 config (no 4o6 parameters)
- string config = "{ " + genIfaceConfig() + "," +
+ string config = "{ " + genIfaceConfig() + ","
"\"rebind-timer\": 2000, "
"\"renew-timer\": 1000, "
"\"subnet4\": [ { "
// 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\": [ { "
"\"valid-lifetime\": 4000 }",
// Bogus configuration 2: incorrect address
- "{ " + genIfaceConfig() + "," +
+ "{ " + genIfaceConfig() + ","
"\"rebind-timer\": 2000, "
"\"renew-timer\": 1000, "
"\"subnet4\": [ { "
"\"valid-lifetime\": 4000 }",
// Bogus configuration 3: incorrect prefix length
- "{ " + genIfaceConfig() + "," +
+ "{ " + genIfaceConfig() + ","
"\"rebind-timer\": 2000, "
"\"renew-timer\": 1000, "
"\"subnet4\": [ { "
ConstElementPtr status;
// Just a plain v4 config (no 4o6 parameters)
- string config = "{ " + genIfaceConfig() + "," +
+ string config = "{ " + genIfaceConfig() + ","
"\"rebind-timer\": 2000, "
"\"renew-timer\": 1000, "
"\"subnet4\": [ { "
ConstElementPtr status;
// Just a plain v4 config (no 4o6 parameters)
- string config = "{ " + genIfaceConfig() + "," +
+ string config = "{ " + genIfaceConfig() + ","
"\"rebind-timer\": 2000, "
"\"renew-timer\": 1000, "
"\"subnet4\": [ { "
ConstElementPtr status;
// Just a plain v4 config (no 4o6 parameters)
- string config = "{ " + genIfaceConfig() + "," +
+ string config = "{ " + genIfaceConfig() + ","
"\"rebind-timer\": 2000, "
"\"renew-timer\": 1000, "
"\"subnet4\": [ { "
// 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"
// 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"
// 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"
// 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"
// 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);
}
// 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"
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();
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
"\"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"
ASSERT_TRUE(nets);
ASSERT_EQ(2, nets->size());
+ // Let's check the first one.
SharedNetwork4Ptr net = nets->at(0);
ASSERT_TRUE(net);
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) {
" \"pools\": [ { \"pool\": \"192.0.3.1-192.0.3.10\" } ]\n"
" }\n"
" ]\n"
-
" } ]\n"
"} \n";
ASSERT_TRUE(nets);
ASSERT_EQ(2, nets->size());
+ // Let's check the first one.
SharedNetwork4Ptr net = nets->at(0);
ASSERT_TRUE(net);
// 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);
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());
}
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, "");
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"
" \"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));
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);
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) {
// 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::
// 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::
// 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.
// 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\": [ ] "
"}";
" { \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"
// 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()));
// 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\": [ "
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,"
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);
});
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.
/// 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, "
// This test checks that using default multi threading settings works.
TEST_F(Dhcp4ParserTest, multiThreadingDefaultSettings) {
- std::string config = "{ " + genIfaceConfig() + "," +
+ std::string config = "{ " + genIfaceConfig() + ","
"\"subnet4\": [ ]"
"}";
" \"thread-pool-size\": 48,\n"
" \"packet-queue-size\": 1024\n"
"}";
- std::string config = "{ " + genIfaceConfig() + "," +
+ std::string config = "{ " + genIfaceConfig() + ","
"\"subnet4\": [ ], "
"\"multi-threading\": " + content_json + "}";
// 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\": [ ] "
"}";
// 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\": [ "
#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;
" \"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"
" ],\n"
" \"valid-lifetime\": 4000\n"
" }\n",
- // CONFIGURATION 2
+ // CONFIGURATION 1
"{\n"
" \"interfaces-config\": {\n"
" \"interfaces\": [ \"*\" ],\n"
" }\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"
" }\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"
" ],\n"
" \"valid-lifetime\": 4000\n"
" }\n",
- // CONFIGURATION 6
+ // CONFIGURATION 7
"{\n"
" \"interfaces-config\": {\n"
" \"interfaces\": [ \"*\" ],\n"
" ],\n"
" \"valid-lifetime\": 4000\n"
" }\n",
- // CONFIGURATION 7
+ // CONFIGURATION 8
"{\n"
" \"boot-file-name\": \"nofile\",\n"
" \"interfaces-config\": {\n"
" ],\n"
" \"valid-lifetime\": 4000\n"
" }\n",
- // CONFIGURATION 8
+ // CONFIGURATION 9
"{\n"
" \"echo-client-id\": false,\n"
" \"interfaces-config\": {\n"
" ],\n"
" \"valid-lifetime\": 4000\n"
" }\n",
- // CONFIGURATION 9
+ // CONFIGURATION 10
"{\n"
" \"echo-client-id\": true,\n"
" \"interfaces-config\": {\n"
" ],\n"
" \"valid-lifetime\": 4000\n"
" }\n",
- // CONFIGURATION 10
+ // CONFIGURATION 11
"{\n"
" \"compatibility\": {\n"
" \"exclude-first-last-24\": true,\n"
" ],\n"
" \"valid-lifetime\": 4000\n"
" }\n",
- // CONFIGURATION 11
+ // CONFIGURATION 12
"{\n"
" \"interfaces-config\": {\n"
" \"interfaces\": [ \"*\" ],\n"
" ],\n"
" \"valid-lifetime\": 4000\n"
" }\n",
- // CONFIGURATION 12
+ // CONFIGURATION 13
"{\n"
" \"interfaces-config\": {\n"
" \"interfaces\": [ \"*\" ],\n"
" ],\n"
" \"valid-lifetime\": 4000\n"
" }\n",
- // CONFIGURATION 13
+ // CONFIGURATION 14
"{\n"
" \"interfaces-config\": {\n"
" \"interfaces\": [ \"*\" ],\n"
" ],\n"
" \"valid-lifetime\": 4000\n"
" }\n",
- // CONFIGURATION 14
+ // CONFIGURATION 15
"{\n"
" \"authoritative\": true,\n"
" \"interfaces-config\": {\n"
" ],\n"
" \"valid-lifetime\": 4000\n"
" }\n",
- // CONFIGURATION 15
+ // CONFIGURATION 16
"{\n"
" \"interfaces-config\": {\n"
" \"interfaces\": [ \"*\" ],\n"
" ],\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"
" ],\n"
" \"valid-lifetime\": 4000\n"
" }\n",
- // CONFIGURATION 17
+ // CONFIGURATION 19
"{\n"
" \"interfaces-config\": {\n"
" \"interfaces\": [ \"*\" ],\n"
" ],\n"
" \"valid-lifetime\": 4000\n"
" }\n",
- // CONFIGURATION 18
+ // CONFIGURATION 20
"{\n"
" \"option-def\": [\n"
" {\n"
" }\n"
" ]\n"
" }\n",
- // CONFIGURATION 19
+ // CONFIGURATION 21
"{\n"
" \"option-def\": [\n"
" {\n"
" }\n"
" ]\n"
" }\n",
- // CONFIGURATION 20
+ // CONFIGURATION 22
"{\n"
" \"option-def\": [\n"
" {\n"
" }\n"
" ]\n"
" }\n",
- // CONFIGURATION 21
+ // CONFIGURATION 23
"{\n"
" \"option-def\": [\n"
" {\n"
" }\n"
" ]\n"
" }\n",
- // CONFIGURATION 22
+ // CONFIGURATION 24
"{\n"
" \"option-def\": [\n"
" {\n"
" }\n"
" ]\n"
" }\n",
- // CONFIGURATION 23
+ // CONFIGURATION 25
"{\n"
" \"option-def\": [\n"
" {\n"
" }\n"
" ]\n"
" }\n",
- // CONFIGURATION 24
+ // CONFIGURATION 26
"{\n"
" \"option-def\": [\n"
" {\n"
" }\n"
" ]\n"
" }\n",
- // CONFIGURATION 25
+ // CONFIGURATION 27
"{\n"
" \"interfaces-config\": {\n"
" \"interfaces\": [ \"*\" ],\n"
" ],\n"
" \"valid-lifetime\": 4000\n"
" }\n",
- // CONFIGURATION 26
+ // CONFIGURATION 28
"{\n"
" \"interfaces-config\": {\n"
" \"interfaces\": [ \"*\" ],\n"
" ],\n"
" \"valid-lifetime\": 4000\n"
" }\n",
- // CONFIGURATION 27
+ // CONFIGURATION 29
"{\n"
" \"interfaces-config\": {\n"
" \"interfaces\": [ \"*\" ],\n"
" ],\n"
" \"valid-lifetime\": 4000\n"
" }\n",
- // CONFIGURATION 28
+ // CONFIGURATION 30
"{\n"
" \"interfaces-config\": {\n"
" \"interfaces\": [ \"*\" ],\n"
" \"renew-timer\": 1000,\n"
" \"valid-lifetime\": 4000\n"
" }\n",
- // CONFIGURATION 29
+ // CONFIGURATION 31
"{\n"
" \"interfaces-config\": {\n"
" \"interfaces\": [ \"*\" ],\n"
" ],\n"
" \"valid-lifetime\": 3000\n"
" }\n",
- // CONFIGURATION 30
+ // CONFIGURATION 32
"{\n"
" \"interfaces-config\": {\n"
" \"interfaces\": [ \"*\" ],\n"
" ],\n"
" \"valid-lifetime\": 4000\n"
" }\n",
- // CONFIGURATION 31
+ // CONFIGURATION 33
"{\n"
" \"interfaces-config\": {\n"
" \"interfaces\": [ \"*\" ],\n"
" ],\n"
" \"valid-lifetime\": 4000\n"
" }\n",
- // CONFIGURATION 32
+ // CONFIGURATION 34
"{\n"
" \"interfaces-config\": {\n"
" \"interfaces\": [ \"*\" ],\n"
" ],\n"
" \"valid-lifetime\": 4000\n"
" }\n",
- // CONFIGURATION 33
+ // CONFIGURATION 35
"{\n"
" \"interfaces-config\": {\n"
" \"interfaces\": [ \"*\" ],\n"
" ],\n"
" \"valid-lifetime\": 4000\n"
" }\n",
- // CONFIGURATION 34
+ // CONFIGURATION 36
"{\n"
" \"interfaces-config\": {\n"
" \"interfaces\": [ \"*\" ],\n"
" ],\n"
" \"valid-lifetime\": 4000\n"
" }\n",
- // CONFIGURATION 35
+ // CONFIGURATION 37
"{\n"
" \"interfaces-config\": {\n"
" \"interfaces\": [ \"*\" ],\n"
" \"renew-timer\": 1000,\n"
" \"valid-lifetime\": 4000\n"
" }\n",
- // CONFIGURATION 36
+ // CONFIGURATION 38
"{\n"
" \"interfaces-config\": {\n"
" \"interfaces\": [ \"*\" ],\n"
" ],\n"
" \"valid-lifetime\": 3000\n"
" }\n",
- // CONFIGURATION 37
+ // CONFIGURATION 39
"{\n"
" \"interfaces-config\": {\n"
" \"interfaces\": [ \"*\" ],\n"
" ],\n"
" \"valid-lifetime\": 4000\n"
" }\n",
- // CONFIGURATION 38
+ // CONFIGURATION 40
"{\n"
" \"interfaces-config\": {\n"
" \"interfaces\": [ \"*\" ],\n"
" ],\n"
" \"valid-lifetime\": 4000\n"
" }\n",
- // CONFIGURATION 39
+ // CONFIGURATION 41
"{\n"
" \"interfaces-config\": {\n"
" \"interfaces\": [ \"eth0\", \"eth1\" ],\n"
" \"renew-timer\": 1000,\n"
" \"valid-lifetime\": 4000\n"
" }\n",
- // CONFIGURATION 40
+ // CONFIGURATION 42
"{\n"
" \"interfaces-config\": {\n"
" \"interfaces\": [ \"eth0\", \"*\", \"eth1\" ],\n"
" \"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"
" ],\n"
" \"valid-lifetime\": 4000\n"
" }\n",
- // CONFIGURATION 43
+ // CONFIGURATION 44
"{\n"
" \"interfaces-config\": {\n"
" \"interfaces\": [ \"*\" ],\n"
" ],\n"
" \"valid-lifetime\": 4000\n"
" }\n",
- // CONFIGURATION 44
+ // CONFIGURATION 45
"{\n"
" \"interfaces-config\": {\n"
" \"interfaces\": [ \"*\" ],\n"
" ],\n"
" \"valid-lifetime\": 4000\n"
" }\n",
- // CONFIGURATION 45
+ // CONFIGURATION 46
"{\n"
" \"interfaces-config\": {\n"
" \"interfaces\": [ \"*\" ],\n"
" ],\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"
" ],\n"
" \"valid-lifetime\": 4000\n"
" }\n",
- // CONFIGURATION 47
+ // CONFIGURATION 49
"{\n"
" \"interfaces-config\": {\n"
" \"interfaces\": [ \"*\" ],\n"
" ],\n"
" \"valid-lifetime\": 4000\n"
" }\n",
- // CONFIGURATION 48
+ // CONFIGURATION 50
"{\n"
" \"rebind-timer\": 2000,\n"
" \"renew-timer\": 1000,\n"
" ],\n"
" \"valid-lifetime\": 4000\n"
" }\n",
- // CONFIGURATION 49
+ // CONFIGURATION 51
"{\n"
" \"rebind-timer\": 2000,\n"
" \"renew-timer\": 1000,\n"
" ],\n"
" \"valid-lifetime\": 4000\n"
" }\n",
- // CONFIGURATION 50
+ // CONFIGURATION 52
"{\n"
" \"interfaces-config\": {\n"
" \"interfaces\": [ \"*\" ],\n"
" },\n"
" \"subnet4\": [ ]\n"
" }\n",
- // CONFIGURATION 51
+ // CONFIGURATION 53
"{\n"
" \"interfaces-config\": {\n"
" \"interfaces\": [ \"*\" ],\n"
" },\n"
" \"subnet4\": [ ]\n"
" }\n",
- // CONFIGURATION 52
+ // CONFIGURATION 54
"{\n"
" \"decline-probation-period\": 12345,\n"
" \"interfaces-config\": {\n"
" },\n"
" \"subnet4\": [ ]\n"
" }\n",
- // CONFIGURATION 53
+ // CONFIGURATION 55
"{\n"
" \"expired-leases-processing\": {\n"
" \"flush-reclaimed-timer-wait-time\": 35,\n"
" },\n"
" \"subnet4\": [ ]\n"
" }\n",
- // CONFIGURATION 54
+ // CONFIGURATION 56
"{\n"
" \"interfaces-config\": {\n"
" \"interfaces\": [ \"*\" ],\n"
" ],\n"
" \"valid-lifetime\": 4000\n"
" }\n",
- // CONFIGURATION 55
+ // CONFIGURATION 57
"{\n"
" \"interfaces-config\": {\n"
" \"interfaces\": [ \"*\" ],\n"
" ],\n"
" \"valid-lifetime\": 4000\n"
" }\n",
- // CONFIGURATION 56
+ // CONFIGURATION 58
"{\n"
" \"interfaces-config\": {\n"
" \"interfaces\": [ \"*\" ],\n"
" ],\n"
" \"valid-lifetime\": 4000\n"
" }\n",
- // CONFIGURATION 57
+ // CONFIGURATION 59
"{\n"
" \"interfaces-config\": {\n"
" \"interfaces\": [ \"*\" ],\n"
" ],\n"
" \"valid-lifetime\": 4000\n"
" }\n",
- // CONFIGURATION 58
+ // CONFIGURATION 60
"{\n"
" \"interfaces-config\": {\n"
" \"interfaces\": [ \"*\" ],\n"
" ],\n"
" \"valid-lifetime\": 4000\n"
" }\n",
- // CONFIGURATION 59
+ // CONFIGURATION 61
"{\n"
" \"client-classes\": [\n"
" {\n"
" ],\n"
" \"valid-lifetime\": 4000\n"
" }\n",
- // CONFIGURATION 60
+ // CONFIGURATION 62
"{\n"
" \"client-classes\": [\n"
" {\n"
" }\n"
" ]\n"
" }\n",
- // CONFIGURATION 61
+ // CONFIGURATION 63
"{\n"
" \"client-classes\": [\n"
" {\n"
" }\n"
" ]\n"
" }\n",
- // CONFIGURATION 62
+ // CONFIGURATION 64
"{\n"
" \"interfaces-config\": {\n"
" \"interfaces\": [ \"*\" ],\n"
" ],\n"
" \"valid-lifetime\": 4000\n"
" }\n",
- // CONFIGURATION 63
+ // CONFIGURATION 65
"{\n"
" \"interfaces-config\": {\n"
" \"interfaces\": [ \"*\" ],\n"
" ],\n"
" \"valid-lifetime\": 4000\n"
" }\n",
- // CONFIGURATION 64
+ // CONFIGURATION 66
"{\n"
" \"interfaces-config\": {\n"
" \"interfaces\": [ \"*\" ],\n"
" ],\n"
" \"valid-lifetime\": 4000\n"
" }\n",
- // CONFIGURATION 65
+ // CONFIGURATION 67
"{\n"
" \"interfaces-config\": {\n"
" \"interfaces\": [ \"*\" ],\n"
" ],\n"
" \"valid-lifetime\": 4000\n"
" }\n",
- // CONFIGURATION 66
+ // CONFIGURATION 68
"{\n"
" \"hosts-databases\": [\n"
" {\n"
" {\n"
" \"name\": \"keatest2\",\n"
" \"password\": \"keatest\",\n"
+" \"retry-on-startup\": true,\n"
" \"type\": \"mysql\",\n"
" \"user\": \"keatest\"\n"
" }\n"
" \"renew-timer\": 1000,\n"
" \"valid-lifetime\": 4000\n"
" }\n",
- // CONFIGURATION 67
+ // CONFIGURATION 69
"{\n"
" \"client-classes\": [\n"
" {\n"
" \"comment\": \"A DHCPv4 server\"\n"
" }\n"
" }\n",
- // CONFIGURATION 68
+ // CONFIGURATION 70
"{\n"
" \"interfaces-config\": {\n"
" \"interfaces\": [ \"*\" ],\n"
" ],\n"
" \"valid-lifetime\": 4000\n"
" }\n",
- // CONFIGURATION 69
+ // CONFIGURATION 71
"{\n"
" \"interfaces-config\": {\n"
" \"interfaces\": [ \"*\" ],\n"
" ],\n"
" \"valid-lifetime\": 4000\n"
" }\n",
- // CONFIGURATION 70
+ // CONFIGURATION 72
"{\n"
" \"interfaces-config\": {\n"
" \"interfaces\": [ \"*\" ],\n"
" ],\n"
" \"valid-lifetime\": 4000\n"
" }\n",
- // CONFIGURATION 71
+ // CONFIGURATION 73
"{\n"
" \"interfaces-config\": {\n"
" \"interfaces\": [ \"*\" ],\n"
" ],\n"
" \"valid-lifetime\": 4000\n"
" }\n",
- // CONFIGURATION 72
+ // CONFIGURATION 74
"{\n"
" \"interfaces-config\": {\n"
" \"interfaces\": [ \"*\" ],\n"
" \"statistic-default-sample-count\": 10,\n"
" \"valid-lifetime\": 4000\n"
" }\n",
- // CONFIGURATION 73
+ // CONFIGURATION 75
"{\n"
" \"interfaces-config\": {\n"
" \"interfaces\": [ \"*\" ],\n"
" },\n"
" \"subnet4\": [ ]\n"
" }\n",
- // CONFIGURATION 74
+ // CONFIGURATION 76
"{\n"
" \"interfaces-config\": {\n"
" \"interfaces\": [ \"*\" ],\n"
" },\n"
" \"subnet4\": [ ]\n"
" }\n",
- // CONFIGURATION 75
+ // CONFIGURATION 77
"{\n"
" \"ddns-conflict-resolution-mode\": \"no-check-with-dhcid\",\n"
" \"interfaces-config\": {\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"
" \"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"
" \"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"
" \"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"
" \"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"
" \"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"
" \"pool\": \"192.0.2.1-192.0.2.100\"\n"
" }\n"
" ],\n"
+" \"rebind-timer\": 2000,\n"
" \"relay\": {\n"
" \"ip-addresses\": [ ]\n"
" },\n"
" \"t2-percent\": 0.875,\n"
" \"valid-lifetime\": 4000\n"
" }\n",
- // CONFIGURATION 3
+ // CONFIGURATION 4
"{\n"
" \"allocator\": \"iterative\",\n"
" \"authoritative\": false,\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"
" \"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"
" \"t2-percent\": 0.875,\n"
" \"valid-lifetime\": 4000\n"
" }\n",
- // CONFIGURATION 4
+ // CONFIGURATION 5
"{\n"
" \"allocator\": \"iterative\",\n"
" \"authoritative\": false,\n"
" \"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"
" \"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"
" \"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"
" \"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"
" \"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"
" \"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"
" \"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"
" \"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"
" \"t2-percent\": 0.875,\n"
" \"valid-lifetime\": 4000\n"
" }\n",
- // CONFIGURATION 5
+ // CONFIGURATION 6
"{\n"
" \"allocator\": \"iterative\",\n"
" \"authoritative\": false,\n"
" \"t2-percent\": 0.875,\n"
" \"valid-lifetime\": 4000\n"
" }\n",
- // CONFIGURATION 6
+ // CONFIGURATION 7
"{\n"
" \"allocator\": \"iterative\",\n"
" \"authoritative\": false,\n"
" \"t2-percent\": 0.875,\n"
" \"valid-lifetime\": 4000\n"
" }\n",
- // CONFIGURATION 7
+ // CONFIGURATION 8
"{\n"
" \"allocator\": \"iterative\",\n"
" \"authoritative\": false,\n"
" \"t2-percent\": 0.875,\n"
" \"valid-lifetime\": 4000\n"
" }\n",
- // CONFIGURATION 8
+ // CONFIGURATION 9
"{\n"
" \"allocator\": \"iterative\",\n"
" \"authoritative\": false,\n"
" \"t2-percent\": 0.875,\n"
" \"valid-lifetime\": 4000\n"
" }\n",
- // CONFIGURATION 9
+ // CONFIGURATION 10
"{\n"
" \"allocator\": \"iterative\",\n"
" \"authoritative\": false,\n"
" \"t2-percent\": 0.875,\n"
" \"valid-lifetime\": 4000\n"
" }\n",
- // CONFIGURATION 10
+ // CONFIGURATION 11
"{\n"
" \"allocator\": \"iterative\",\n"
" \"authoritative\": false,\n"
" \"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"
" \"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"
" \"t2-percent\": 0.875,\n"
" \"valid-lifetime\": 4000\n"
" }\n",
- // CONFIGURATION 11
+ // CONFIGURATION 13
"{\n"
" \"allocator\": \"iterative\",\n"
" \"authoritative\": false,\n"
" \"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"
" \"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"
" \"t2-percent\": 0.875,\n"
" \"valid-lifetime\": 4000\n"
" }\n",
- // CONFIGURATION 12
+ // CONFIGURATION 14
"{\n"
" \"allocator\": \"iterative\",\n"
" \"authoritative\": false,\n"
" \"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"
" \"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"
" \"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"
" \"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"
" \"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"
" \"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"
" \"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"
" \"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"
" \"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"
" \"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"
" \"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"
" \"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"
" \"t2-percent\": 0.875,\n"
" \"valid-lifetime\": 4000\n"
" }\n",
- // CONFIGURATION 17
+ // CONFIGURATION 19
"{\n"
" \"allocator\": \"iterative\",\n"
" \"authoritative\": false,\n"
" \"t2-percent\": 0.875,\n"
" \"valid-lifetime\": 4000\n"
" }\n",
- // CONFIGURATION 18
+ // CONFIGURATION 20
"{\n"
" \"allocator\": \"iterative\",\n"
" \"authoritative\": false,\n"
" \"t2-percent\": 0.875,\n"
" \"valid-lifetime\": 7200\n"
" }\n",
- // CONFIGURATION 19
+ // CONFIGURATION 21
"{\n"
" \"allocator\": \"iterative\",\n"
" \"authoritative\": false,\n"
" \"t2-percent\": 0.875,\n"
" \"valid-lifetime\": 7200\n"
" }\n",
- // CONFIGURATION 20
+ // CONFIGURATION 22
"{\n"
" \"allocator\": \"iterative\",\n"
" \"authoritative\": false,\n"
" \"t2-percent\": 0.875,\n"
" \"valid-lifetime\": 7200\n"
" }\n",
- // CONFIGURATION 21
+ // CONFIGURATION 23
"{\n"
" \"allocator\": \"iterative\",\n"
" \"authoritative\": false,\n"
" \"t2-percent\": 0.875,\n"
" \"valid-lifetime\": 7200\n"
" }\n",
- // CONFIGURATION 22
+ // CONFIGURATION 24
"{\n"
" \"allocator\": \"iterative\",\n"
" \"authoritative\": false,\n"
" \"t2-percent\": 0.875,\n"
" \"valid-lifetime\": 7200\n"
" }\n",
- // CONFIGURATION 23
+ // CONFIGURATION 25
"{\n"
" \"allocator\": \"iterative\",\n"
" \"authoritative\": false,\n"
" \"t2-percent\": 0.875,\n"
" \"valid-lifetime\": 7200\n"
" }\n",
- // CONFIGURATION 24
+ // CONFIGURATION 26
"{\n"
" \"allocator\": \"iterative\",\n"
" \"authoritative\": false,\n"
" \"t2-percent\": 0.875,\n"
" \"valid-lifetime\": 7200\n"
" }\n",
- // CONFIGURATION 25
+ // CONFIGURATION 27
"{\n"
" \"allocator\": \"iterative\",\n"
" \"authoritative\": false,\n"
" \"t2-percent\": 0.875,\n"
" \"valid-lifetime\": 4000\n"
" }\n",
- // CONFIGURATION 26
+ // CONFIGURATION 28
"{\n"
" \"allocator\": \"iterative\",\n"
" \"authoritative\": false,\n"
" \"t2-percent\": 0.875,\n"
" \"valid-lifetime\": 4000\n"
" }\n",
- // CONFIGURATION 27
+ // CONFIGURATION 29
"{\n"
" \"allocator\": \"iterative\",\n"
" \"authoritative\": false,\n"
" \"t2-percent\": 0.875,\n"
" \"valid-lifetime\": 4000\n"
" }\n",
- // CONFIGURATION 28
+ // CONFIGURATION 30
"{\n"
" \"allocator\": \"iterative\",\n"
" \"authoritative\": false,\n"
" \"t2-percent\": 0.875,\n"
" \"valid-lifetime\": 4000\n"
" }\n",
- // CONFIGURATION 29
+ // CONFIGURATION 31
"{\n"
" \"allocator\": \"iterative\",\n"
" \"authoritative\": false,\n"
" \"t2-percent\": 0.875,\n"
" \"valid-lifetime\": 3000\n"
" }\n",
- // CONFIGURATION 30
+ // CONFIGURATION 32
"{\n"
" \"allocator\": \"iterative\",\n"
" \"authoritative\": false,\n"
" \"t2-percent\": 0.875,\n"
" \"valid-lifetime\": 4000\n"
" }\n",
- // CONFIGURATION 31
+ // CONFIGURATION 33
"{\n"
" \"allocator\": \"iterative\",\n"
" \"authoritative\": false,\n"
" \"t2-percent\": 0.875,\n"
" \"valid-lifetime\": 4000\n"
" }\n",
- // CONFIGURATION 32
+ // CONFIGURATION 34
"{\n"
" \"allocator\": \"iterative\",\n"
" \"authoritative\": false,\n"
" \"t2-percent\": 0.875,\n"
" \"valid-lifetime\": 4000\n"
" }\n",
- // CONFIGURATION 33
+ // CONFIGURATION 35
"{\n"
" \"allocator\": \"iterative\",\n"
" \"authoritative\": false,\n"
" \"t2-percent\": 0.875,\n"
" \"valid-lifetime\": 4000\n"
" }\n",
- // CONFIGURATION 34
+ // CONFIGURATION 36
"{\n"
" \"allocator\": \"iterative\",\n"
" \"authoritative\": false,\n"
" \"t2-percent\": 0.875,\n"
" \"valid-lifetime\": 4000\n"
" }\n",
- // CONFIGURATION 35
+ // CONFIGURATION 37
"{\n"
" \"allocator\": \"iterative\",\n"
" \"authoritative\": false,\n"
" \"t2-percent\": 0.875,\n"
" \"valid-lifetime\": 4000\n"
" }\n",
- // CONFIGURATION 36
+ // CONFIGURATION 38
"{\n"
" \"allocator\": \"iterative\",\n"
" \"authoritative\": false,\n"
" \"t2-percent\": 0.875,\n"
" \"valid-lifetime\": 3000\n"
" }\n",
- // CONFIGURATION 37
+ // CONFIGURATION 39
"{\n"
" \"allocator\": \"iterative\",\n"
" \"authoritative\": false,\n"
" \"t2-percent\": 0.875,\n"
" \"valid-lifetime\": 4000\n"
" }\n",
- // CONFIGURATION 38
+ // CONFIGURATION 40
"{\n"
" \"allocator\": \"iterative\",\n"
" \"authoritative\": false,\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 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"
" \"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"
" \"t2-percent\": 0.875,\n"
" \"valid-lifetime\": 4000\n"
" }\n",
- // CONFIGURATION 41
+ // CONFIGURATION 42
"{\n"
" \"allocator\": \"iterative\",\n"
" \"authoritative\": false,\n"
" \"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"
" \"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"
" \"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"
" \"t2-percent\": 0.875,\n"
" \"valid-lifetime\": 4000\n"
" }\n",
- // CONFIGURATION 43
+ // CONFIGURATION 44
"{\n"
" \"allocator\": \"iterative\",\n"
" \"authoritative\": false,\n"
" \"t2-percent\": 0.875,\n"
" \"valid-lifetime\": 4000\n"
" }\n",
- // CONFIGURATION 44
+ // CONFIGURATION 45
"{\n"
" \"allocator\": \"iterative\",\n"
" \"authoritative\": false,\n"
" \"t2-percent\": 0.875,\n"
" \"valid-lifetime\": 4000\n"
" }\n",
- // CONFIGURATION 45
+ // CONFIGURATION 46
"{\n"
" \"allocator\": \"iterative\",\n"
" \"authoritative\": false,\n"
" \"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"
" \"t2-percent\": 0.875,\n"
" \"valid-lifetime\": 4000\n"
" }\n",
- // CONFIGURATION 47
+ // CONFIGURATION 49
"{\n"
" \"allocator\": \"iterative\",\n"
" \"authoritative\": false,\n"
" \"t2-percent\": 0.875,\n"
" \"valid-lifetime\": 4000\n"
" }\n",
- // CONFIGURATION 48
+ // CONFIGURATION 50
"{\n"
" \"allocator\": \"iterative\",\n"
" \"authoritative\": false,\n"
" \"t2-percent\": 0.875,\n"
" \"valid-lifetime\": 4000\n"
" }\n",
- // CONFIGURATION 49
+ // CONFIGURATION 51
"{\n"
" \"allocator\": \"iterative\",\n"
" \"authoritative\": false,\n"
" \"t2-percent\": 0.875,\n"
" \"valid-lifetime\": 4000\n"
" }\n",
- // CONFIGURATION 50
+ // CONFIGURATION 52
"{\n"
" \"allocator\": \"iterative\",\n"
" \"authoritative\": false,\n"
" \"t2-percent\": 0.875,\n"
" \"valid-lifetime\": 7200\n"
" }\n",
- // CONFIGURATION 51
+ // CONFIGURATION 53
"{\n"
" \"allocator\": \"iterative\",\n"
" \"authoritative\": false,\n"
" \"t2-percent\": 0.875,\n"
" \"valid-lifetime\": 7200\n"
" }\n",
- // CONFIGURATION 52
+ // CONFIGURATION 54
"{\n"
" \"allocator\": \"iterative\",\n"
" \"authoritative\": false,\n"
" \"t2-percent\": 0.875,\n"
" \"valid-lifetime\": 7200\n"
" }\n",
- // CONFIGURATION 53
+ // CONFIGURATION 55
"{\n"
" \"allocator\": \"iterative\",\n"
" \"authoritative\": false,\n"
" \"t2-percent\": 0.875,\n"
" \"valid-lifetime\": 7200\n"
" }\n",
- // CONFIGURATION 54
+ // CONFIGURATION 56
"{\n"
" \"allocator\": \"iterative\",\n"
" \"authoritative\": false,\n"
" \"t2-percent\": 0.875,\n"
" \"valid-lifetime\": 4000\n"
" }\n",
- // CONFIGURATION 55
+ // CONFIGURATION 57
"{\n"
" \"allocator\": \"iterative\",\n"
" \"authoritative\": false,\n"
" \"t2-percent\": 0.875,\n"
" \"valid-lifetime\": 4000\n"
" }\n",
- // CONFIGURATION 56
+ // CONFIGURATION 58
"{\n"
" \"allocator\": \"iterative\",\n"
" \"authoritative\": false,\n"
" \"t2-percent\": 0.875,\n"
" \"valid-lifetime\": 4000\n"
" }\n",
- // CONFIGURATION 57
+ // CONFIGURATION 59
"{\n"
" \"allocator\": \"iterative\",\n"
" \"authoritative\": false,\n"
" \"t2-percent\": 0.875,\n"
" \"valid-lifetime\": 4000\n"
" }\n",
- // CONFIGURATION 58
+ // CONFIGURATION 60
"{\n"
" \"allocator\": \"iterative\",\n"
" \"authoritative\": false,\n"
" \"t2-percent\": 0.875,\n"
" \"valid-lifetime\": 4000\n"
" }\n",
- // CONFIGURATION 59
+ // CONFIGURATION 61
"{\n"
" \"allocator\": \"iterative\",\n"
" \"authoritative\": false,\n"
" \"t2-percent\": 0.875,\n"
" \"valid-lifetime\": 4000\n"
" }\n",
- // CONFIGURATION 60
+ // CONFIGURATION 62
"{\n"
" \"allocator\": \"iterative\",\n"
" \"authoritative\": false,\n"
" \"t2-percent\": 0.875,\n"
" \"valid-lifetime\": 7200\n"
" }\n",
- // CONFIGURATION 61
+ // CONFIGURATION 63
"{\n"
" \"allocator\": \"iterative\",\n"
" \"authoritative\": false,\n"
" \"t2-percent\": 0.875,\n"
" \"valid-lifetime\": 7200\n"
" }\n",
- // CONFIGURATION 62
+ // CONFIGURATION 64
"{\n"
" \"allocator\": \"iterative\",\n"
" \"authoritative\": false,\n"
" \"t2-percent\": 0.875,\n"
" \"valid-lifetime\": 4000\n"
" }\n",
- // CONFIGURATION 63
+ // CONFIGURATION 65
"{\n"
" \"allocator\": \"iterative\",\n"
" \"authoritative\": false,\n"
" \"t2-percent\": 0.875,\n"
" \"valid-lifetime\": 4000\n"
" }\n",
- // CONFIGURATION 64
+ // CONFIGURATION 66
"{\n"
" \"allocator\": \"iterative\",\n"
" \"authoritative\": false,\n"
" \"t2-percent\": 0.875,\n"
" \"valid-lifetime\": 4000\n"
" }\n",
- // CONFIGURATION 65
+ // CONFIGURATION 67
"{\n"
" \"allocator\": \"iterative\",\n"
" \"authoritative\": false,\n"
" \"t2-percent\": 0.875,\n"
" \"valid-lifetime\": 4000\n"
" }\n",
- // CONFIGURATION 66
+ // CONFIGURATION 68
"{\n"
" \"allocator\": \"iterative\",\n"
" \"authoritative\": false,\n"
" {\n"
" \"name\": \"keatest2\",\n"
" \"password\": \"keatest\",\n"
+" \"retry-on-startup\": true,\n"
" \"type\": \"mysql\",\n"
" \"user\": \"keatest\"\n"
" }\n"
" \"t2-percent\": 0.875,\n"
" \"valid-lifetime\": 4000\n"
" }\n",
- // CONFIGURATION 67
+ // CONFIGURATION 69
"{\n"
" \"allocator\": \"iterative\",\n"
" \"authoritative\": false,\n"
" },\n"
" \"valid-lifetime\": 7200\n"
" }\n",
- // CONFIGURATION 68
+ // CONFIGURATION 70
"{\n"
" \"allocator\": \"iterative\",\n"
" \"authoritative\": false,\n"
" \"t2-percent\": 0.875,\n"
" \"valid-lifetime\": 4000\n"
" }\n",
- // CONFIGURATION 69
+ // CONFIGURATION 71
"{\n"
" \"allocator\": \"iterative\",\n"
" \"authoritative\": false,\n"
" \"t2-percent\": 0.875,\n"
" \"valid-lifetime\": 4000\n"
" }\n",
- // CONFIGURATION 70
+ // CONFIGURATION 72
"{\n"
" \"allocator\": \"iterative\",\n"
" \"authoritative\": false,\n"
" \"t2-percent\": 0.875,\n"
" \"valid-lifetime\": 4000\n"
" }\n",
- // CONFIGURATION 71
+ // CONFIGURATION 73
"{\n"
" \"allocator\": \"iterative\",\n"
" \"authoritative\": false,\n"
" \"t2-percent\": 0.875,\n"
" \"valid-lifetime\": 4000\n"
" }\n",
- // CONFIGURATION 72
+ // CONFIGURATION 74
"{\n"
" \"allocator\": \"iterative\",\n"
" \"authoritative\": false,\n"
" \"t2-percent\": 0.875,\n"
" \"valid-lifetime\": 4000\n"
" }\n",
- // CONFIGURATION 73
+ // CONFIGURATION 75
"{\n"
" \"allocator\": \"iterative\",\n"
" \"authoritative\": false,\n"
" \"t2-percent\": 0.875,\n"
" \"valid-lifetime\": 7200\n"
" }\n",
- // CONFIGURATION 74
+ // CONFIGURATION 76
"{\n"
" \"allocator\": \"iterative\",\n"
" \"authoritative\": false,\n"
" \"t2-percent\": 0.875,\n"
" \"valid-lifetime\": 7200\n"
" }\n",
- // CONFIGURATION 75
+ // CONFIGURATION 77
"{\n"
" \"allocator\": \"iterative\",\n"
" \"authoritative\": false,\n"
#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;
///
/// Exposes internal fields and installs stub implementation of the
/// @c CBControlDHCPv4 object.
-class NakedControlledDhcpv4Srv: public ControlledDhcpv4Srv {
+class NakedControlledDhcpv4Srv : public ControlledDhcpv4Srv {
public:
/// @brief Constructor.
}
};
-/// @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
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
LeaseMgrFactory::instance().getType());
}
-
// This test verifies that backend specification can be added on
// server reconfiguration.
TEST_F(JSONFileBackendMySQLTest, reconfigureBackendUndefinedToMySQL) {
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());
}
}
#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;
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\": [\"*\" ]"
" \"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"
" \"type\": \"mysql\", \n"
" \"name\": \"keatest2\", \n"
" \"user\": \"keatest\", \n"
+ " \"retry-on-startup\": true, \n"
" \"password\": \"keatest\" \n"
" } \n"
" ] \n"
" \"comment\": \"Set option value\","
" \"name\": \"subscriber-id\","
" \"data\": \"ABCDEF0105\","
- " \"csv-format\": false"
+ " \"csv-format\": false"
" } ],"
" \"client-classes\": ["
" {"
}
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.
<< " while the test assumes that it doesn't, to execute"
<< " some negative scenarios. Can't continue this test.";
}
-
// Reset configuration for each test.
resetConfiguration();
}
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
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));
}
}
- /// @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 {
/// 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;
/// @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, "
" \"space\": \"dhcp6\""
"} ],"
"\"subnet6\": [ { "
- " \"id\": 1, "
+ " \"id\": 1,"
" \"pools\": [ { \"pool\": \"2001:db8:1::/80\" } ],"
" \"subnet\": \"2001:db8:1::/64\", "
" \"option-data\": [ {";
} 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") {
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
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
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_);
// 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);
<< 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)
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 }"));
/// 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\" } ],"
checkResult(status, 1, expected);
resetConfiguration();
- string too_large = "{ " + genIfaceConfig() + "," +
+ string too_large = "{ " + genIfaceConfig() + ","
"\"subnet6\": [ { "
" \"id\": 1,"
" \"pools\": [ { \"pool\": \"2001:db8::/64\" } ],"
checkResult(status, 1, expected);
resetConfiguration();
- string before = "{ " + genIfaceConfig() + "," +
+ string before = "{ " + genIfaceConfig() + ","
"\"subnet6\": [ { "
" \"id\": 1,"
" \"pools\": [ { \"pool\": \"2001:db8::/64\" } ],"
checkResult(status, 1, expected);
resetConfiguration();
- string after = "{ " + genIfaceConfig() + "," +
+ string after = "{ " + genIfaceConfig() + ","
"\"subnet6\": [ { "
" \"id\": 1,"
" \"pools\": [ { \"pool\": \"2001:db8::/64\" } ],"
checkResult(status, 1, expected);
resetConfiguration();
- string crossed = "{ " + genIfaceConfig() + "," +
+ string crossed = "{ " + genIfaceConfig() + ","
"\"subnet6\": [ { "
" \"id\": 1,"
" \"pools\": [ { \"pool\": \"2001:db8::/64\" } ],"
/// parameters only.
TEST_F(Dhcp6ParserTest, outBoundGlobalValidLifetime) {
- string too_small = "{ " + genIfaceConfig() + "," +
+ string too_small = "{ " + genIfaceConfig() + ","
"\"valid-lifetime\": 1000, \"min-valid-lifetime\": 2000 }";
ConstElementPtr json;
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));
checkResult(status, 1, expected);
resetConfiguration();
- string before = "{ " + genIfaceConfig() + "," +
+ string before = "{ " + genIfaceConfig() + ","
"\"valid-lifetime\": 1000, \"min-valid-lifetime\": 2000, "
"\"max-valid-lifetime\": 4000 }";
checkResult(status, 1, expected);
resetConfiguration();
- string after = "{ " + genIfaceConfig() + "," +
+ string after = "{ " + genIfaceConfig() + ","
"\"valid-lifetime\": 5000, \"min-valid-lifetime\": 1000, "
"\"max-valid-lifetime\": 4000 }";
checkResult(status, 1, expected);
resetConfiguration();
- string crossed = "{ " + genIfaceConfig() + "," +
+ string crossed = "{ " + genIfaceConfig() + ","
"\"valid-lifetime\": 1500, \"min-valid-lifetime\": 2000, "
"\"max-valid-lifetime\": 1000 }";
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\" } ],"
checkResult(status, 1, expected);
resetConfiguration();
- string too_large = "{ " + genIfaceConfig() + "," +
+ string too_large = "{ " + genIfaceConfig() + ","
"\"subnet6\": [ { "
" \"id\": 1,"
" \"pools\": [ { \"pool\": \"2001:db8::/64\" } ],"
checkResult(status, 1, expected);
resetConfiguration();
- string before = "{ " + genIfaceConfig() + "," +
+ string before = "{ " + genIfaceConfig() + ","
"\"subnet6\": [ { "
" \"id\": 1,"
" \"pools\": [ { \"pool\": \"2001:db8::/64\" } ],"
checkResult(status, 1, expected);
resetConfiguration();
- string after = "{ " + genIfaceConfig() + "," +
+ string after = "{ " + genIfaceConfig() + ","
"\"subnet6\": [ { "
" \"id\": 1,"
" \"pools\": [ { \"pool\": \"2001:db8::/64\" } ],"
checkResult(status, 1, expected);
resetConfiguration();
- string crossed = "{ " + genIfaceConfig() + "," +
+ string crossed = "{ " + genIfaceConfig() + ","
"\"subnet6\": [ { "
" \"id\": 1,"
" \"pools\": [ { \"pool\": \"2001:db8::/64\" } ],"
/// parameters only.
TEST_F(Dhcp6ParserTest, outBoundGlobalPreferredLifetime) {
- string too_small = "{ " + genIfaceConfig() + "," +
+ string too_small = "{ " + genIfaceConfig() + ","
"\"preferred-lifetime\": 1000, \"min-preferred-lifetime\": 2000 }";
ConstElementPtr json;
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));
checkResult(status, 1, expected);
resetConfiguration();
- string before = "{ " + genIfaceConfig() + "," +
+ string before = "{ " + genIfaceConfig() + ","
"\"preferred-lifetime\": 1000, \"min-preferred-lifetime\": 2000, "
"\"max-preferred-lifetime\": 4000 }";
checkResult(status, 1, expected);
resetConfiguration();
- string after = "{ " + genIfaceConfig() + "," +
+ string after = "{ " + genIfaceConfig() + ","
"\"preferred-lifetime\": 5000, \"min-preferred-lifetime\": 1000, "
"\"max-preferred-lifetime\": 4000 }";
checkResult(status, 1, expected);
resetConfiguration();
- string crossed = "{ " + genIfaceConfig() + "," +
+ string crossed = "{ " + genIfaceConfig() + ","
"\"preferred-lifetime\": 1500, \"min-preferred-lifetime\": 2000, "
"\"max-preferred-lifetime\": 1000 }";
// 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());
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());
ConstElementPtr x;
// All four subnets
- string config4 = "{ " + genIfaceConfig() + ","
+ string config6 = "{ " + genIfaceConfig() + ","
"\"preferred-lifetime\": 3000,"
"\"rebind-timer\": 2000, "
"\"renew-timer\": 1000, "
// 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);
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));
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);
// 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, "
// 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, "
// 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, "
// 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());
// 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\": [ { "
{
"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)"
}
ConstElementPtr status;
EXPECT_NO_THROW(status = Dhcpv6SrvTest::configure(srv_, config));
checkResult(status, 1);
+ ASSERT_TRUE(comment_);
EXPECT_EQ(comment_->stringValue(), scenario.exp_error_msg_);
}
}
// 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, "
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());
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) {
}
}
-// 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,"
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);
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.
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()->
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
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.
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
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.
"}";
ConstElementPtr json;
ASSERT_NO_THROW(json = parseOPTION_DEFS(config));
+ extractConfig(config);
OptionDefinitionPtr def = CfgMgr::instance().getStagingCfg()->
getCfgOptionDef()->get(DHCP6_OPTION_SPACE, 100);
" \"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));
" \"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));
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());
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());
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() + ","
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());
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) {
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());
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());
// 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() + ","
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.
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());
// 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));
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.
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.
// 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\": [ {"
ASSERT_NO_THROW(json = parseDHCP6(config));
extractConfig(config);
+
EXPECT_NO_THROW(status = Dhcpv6SrvTest::configure(srv_, json));
ASSERT_TRUE(status);
checkResult(status, 0);
// 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-
// Append the remainder of the configuration.
config += string(
"],"
+ "\"valid-lifetime\": 4000,"
"\"rebind-timer\": 2000,"
"\"renew-timer\": 1000,"
"\"option-data\": [ {"
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,
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
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));
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);
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\": {"
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));
}
"\"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\" ]"
" },"
// 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());
"\"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\" ]"
" },"
// 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());
// 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
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
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.
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.
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
// 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
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
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.
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.
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.
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",
"\"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);
"\"preferred-lifetime\": 3000,"
"\"valid-lifetime\": 4000 }";
- json = parseDHCP6(config);
+ ASSERT_NO_THROW(json = parseDHCP6(config));
// Remove existing configuration, if any.
CfgMgr::instance().clear();
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
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());
// 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) {
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) {
/// 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\": [ ]"
"}";
/// 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));
// 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,"
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,"
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);
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());
// 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
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) {
" } ] \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
" } ] \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.
"\"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"
"\"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"
"\"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"
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";
"\"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"
// - 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"
" \"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"
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"
"\"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"
" \"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,"
" \"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, "");
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());
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());
// 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"
" \"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, "");
// 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
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());
}
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.
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();
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);
"\"valid-lifetime\": 4000 }\n";
ConstElementPtr json;
- (json = parseDHCP6(config));
ASSERT_NO_THROW(json = parseDHCP6(config));
extractConfig(config);
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());
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.
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);
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);
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.
// 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.
// 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\": [ ] "
"}";
std::string json_;
std::string mt_json_;
};
+
std::vector<Scenario> scenarios = {
{
"no entry",
}
}
-// 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, "
// This test checks that using default multi threading settings works.
TEST_F(Dhcp6ParserTest, multiThreadingDefaultSettings) {
- std::string config = "{ " + genIfaceConfig() + "," +
+ std::string config = "{ " + genIfaceConfig() + ","
"\"subnet6\": [ ]"
"}";
" \"thread-pool-size\": 48,\n"
" \"packet-queue-size\": 1024\n"
"}";
- std::string config = "{ " + genIfaceConfig() + "," +
+ std::string config = "{ " + genIfaceConfig() + ","
"\"subnet6\": [ ], "
"\"multi-threading\": " + content_json + "}";
<< " 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"
// 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"
// 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\","
#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;
" \"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"
" ],\n"
" \"valid-lifetime\": 4000\n"
" }\n",
- // CONFIGURATION 2
+ // CONFIGURATION 4
"{\n"
" \"interfaces-config\": {\n"
" \"interfaces\": [ \"*\" ],\n"
" ],\n"
" \"valid-lifetime\": 4000\n"
" }\n",
- // CONFIGURATION 3
+ // CONFIGURATION 5
"{\n"
" \"interfaces-config\": {\n"
" \"interfaces\": [ \"*\" ],\n"
" ],\n"
" \"valid-lifetime\": 4000\n"
" }\n",
- // CONFIGURATION 4
+ // CONFIGURATION 6
"{\n"
" \"compatibility\": {\n"
" \"lenient-option-parsing\": true\n"
" ],\n"
" \"valid-lifetime\": 4000\n"
" }\n",
- // CONFIGURATION 5
+ // CONFIGURATION 7
"{\n"
" \"interfaces-config\": {\n"
" \"interfaces\": [ \"*\" ],\n"
" ],\n"
" \"valid-lifetime\": 4000\n"
" }\n",
- // CONFIGURATION 6
+ // CONFIGURATION 8
"{\n"
" \"interfaces-config\": {\n"
" \"interfaces\": [ \"*\" ],\n"
" ],\n"
" \"valid-lifetime\": 4000\n"
" }\n",
- // CONFIGURATION 7
+ // CONFIGURATION 9
"{\n"
" \"preferred-lifetime\": 3000,\n"
" \"rebind-timer\": 2000,\n"
" ],\n"
" \"valid-lifetime\": 4000\n"
" }\n",
- // CONFIGURATION 8
+ // CONFIGURATION 10
"{\n"
" \"interfaces-config\": {\n"
" \"interfaces\": [ \"*\" ],\n"
" ],\n"
" \"valid-lifetime\": 4000\n"
" }\n",
- // CONFIGURATION 9
+ // CONFIGURATION 11
"{\n"
" \"interfaces-config\": {\n"
" \"interfaces\": [ \"*\" ],\n"
" ],\n"
" \"valid-lifetime\": 4000\n"
" }\n",
- // CONFIGURATION 10
+ // CONFIGURATION 12
"{\n"
" \"interfaces-config\": {\n"
" \"interfaces\": [ \"*\" ],\n"
" }\n"
" ]\n"
" }\n",
- // CONFIGURATION 11
+ // CONFIGURATION 13
"{\n"
" \"interfaces-config\": {\n"
" \"interfaces\": [ \"*\" ],\n"
" }\n"
" ]\n"
" }\n",
- // CONFIGURATION 12
+ // CONFIGURATION 14
"{\n"
" \"interfaces-config\": {\n"
" \"interfaces\": [ \"*\" ],\n"
" }\n"
" ]\n"
" }\n",
- // CONFIGURATION 13
+ // CONFIGURATION 15
"{\n"
" \"interfaces-config\": {\n"
" \"interfaces\": [ \"*\" ],\n"
" }\n"
" ]\n"
" }\n",
- // CONFIGURATION 14
+ // CONFIGURATION 16
"{\n"
" \"option-def\": [\n"
" {\n"
" }\n"
" ]\n"
" }\n",
- // CONFIGURATION 15
+ // CONFIGURATION 17
"{\n"
" \"option-def\": [\n"
" {\n"
" }\n"
" ]\n"
" }\n",
- // CONFIGURATION 16
+ // CONFIGURATION 18
"{\n"
" \"option-def\": [\n"
" {\n"
" }\n"
" ]\n"
" }\n",
- // CONFIGURATION 17
+ // CONFIGURATION 19
"{\n"
" \"option-def\": [\n"
" {\n"
" }\n"
" ]\n"
" }\n",
- // CONFIGURATION 18
+ // CONFIGURATION 20
"{\n"
" \"option-def\": [\n"
" {\n"
" }\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"
" ],\n"
" \"valid-lifetime\": 4000\n"
" }\n",
- // CONFIGURATION 20
+ // CONFIGURATION 24
"{\n"
" \"interfaces-config\": {\n"
" \"interfaces\": [ \"*\" ],\n"
" ],\n"
" \"valid-lifetime\": 4000\n"
" }\n",
- // CONFIGURATION 21
+ // CONFIGURATION 25
"{\n"
" \"interfaces-config\": {\n"
" \"interfaces\": [ \"*\" ],\n"
" ],\n"
" \"valid-lifetime\": 4000\n"
" }\n",
- // CONFIGURATION 22
+ // CONFIGURATION 26
"{\n"
" \"interfaces-config\": {\n"
" \"interfaces\": [ \"*\" ],\n"
" \"renew-timer\": 1000,\n"
" \"valid-lifetime\": 4000\n"
" }\n",
- // CONFIGURATION 23
+ // CONFIGURATION 27
"{\n"
" \"interfaces-config\": {\n"
" \"interfaces\": [ \"*\" ],\n"
" ],\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"
" ],\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"
" ],\n"
" \"valid-lifetime\": 4000\n"
" }\n",
- // CONFIGURATION 26
+ // CONFIGURATION 32
"{\n"
" \"interfaces-config\": {\n"
" \"interfaces\": [ \"*\" ],\n"
" ],\n"
" \"valid-lifetime\": 4000\n"
" }\n",
- // CONFIGURATION 27
+ // CONFIGURATION 33
"{\n"
" \"interfaces-config\": {\n"
" \"interfaces\": [ \"*\" ],\n"
" ],\n"
" \"valid-lifetime\": 4000\n"
" }\n",
- // CONFIGURATION 28
+ // CONFIGURATION 34
"{\n"
" \"interfaces-config\": {\n"
" \"interfaces\": [ \"eth0\" ],\n"
" \"renew-timer\": 1000,\n"
" \"valid-lifetime\": 4000\n"
" }\n",
- // CONFIGURATION 29
+ // CONFIGURATION 35
"{\n"
" \"interfaces-config\": {\n"
" \"interfaces\": [ \"eth0\", \"eth1\", \"*\" ],\n"
" \"renew-timer\": 1000,\n"
" \"valid-lifetime\": 4000\n"
" }\n",
- // CONFIGURATION 30
+ // CONFIGURATION 36
"{\n"
" \"interfaces-config\": {\n"
" \"interfaces\": [ \"*\" ],\n"
" \"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"
" \"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"
" ],\n"
" \"valid-lifetime\": 4000\n"
" }\n",
- // CONFIGURATION 33
+ // CONFIGURATION 39
"{\n"
" \"interfaces-config\": {\n"
" \"interfaces\": [ \"*\" ],\n"
" ],\n"
" \"valid-lifetime\": 4000\n"
" }\n",
- // CONFIGURATION 34
+ // CONFIGURATION 40
"{\n"
" \"interfaces-config\": {\n"
" \"interfaces\": [ \"*\" ],\n"
" ],\n"
" \"valid-lifetime\": 4000\n"
" }\n",
- // CONFIGURATION 35
+ // CONFIGURATION 41
"{\n"
" \"dhcp-ddns\": {\n"
" \"enable-updates\": true,\n"
" ],\n"
" \"valid-lifetime\": 4000\n"
" }\n",
- // CONFIGURATION 36
+ // CONFIGURATION 42
"{\n"
" \"interfaces-config\": {\n"
" \"interfaces\": [ \"*\" ],\n"
" ],\n"
" \"valid-lifetime\": 4000\n"
" }\n",
- // CONFIGURATION 37
+ // CONFIGURATION 43
"{\n"
" \"interfaces-config\": {\n"
" \"interfaces\": [ \"*\" ],\n"
" ],\n"
" \"valid-lifetime\": 4000\n"
" }\n",
- // CONFIGURATION 38
+ // CONFIGURATION 44
"{\n"
" \"interfaces-config\": {\n"
" \"interfaces\": [ \"*\" ],\n"
" \"subnet6\": [ ],\n"
" \"valid-lifetime\": 4000\n"
" }\n",
- // CONFIGURATION 39
+ // CONFIGURATION 45
"{\n"
" \"interfaces-config\": {\n"
" \"interfaces\": [ \"*\" ],\n"
" \"subnet6\": [ ],\n"
" \"valid-lifetime\": 4000\n"
" }\n",
- // CONFIGURATION 40
+ // CONFIGURATION 46
"{\n"
" \"preferred-lifetime\": 3000,\n"
" \"rebind-timer\": 2000,\n"
" ],\n"
" \"valid-lifetime\": 4000\n"
" }\n",
- // CONFIGURATION 41
+ // CONFIGURATION 47
"{\n"
" \"preferred-lifetime\": 3000,\n"
" \"rebind-timer\": 2000,\n"
" ],\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"
" \"subnet6\": [ ],\n"
" \"valid-lifetime\": 4000\n"
" }\n",
- // CONFIGURATION 43
+ // CONFIGURATION 50
"{\n"
" \"interfaces-config\": {\n"
" \"interfaces\": [ \"*\" ],\n"
" },\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"
" },\n"
" \"subnet6\": [ ]\n"
" }\n",
- // CONFIGURATION 46
+ // CONFIGURATION 52
"{\n"
" \"expired-leases-processing\": {\n"
" \"flush-reclaimed-timer-wait-time\": 35,\n"
" },\n"
" \"subnet6\": [ ]\n"
" }\n",
- // CONFIGURATION 47
+ // CONFIGURATION 53
"{\n"
" \"client-classes\": [\n"
" {\n"
" ],\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"
" ],\n"
" \"valid-lifetime\": 4000\n"
" }\n",
- // CONFIGURATION 49
+ // CONFIGURATION 57
"{\n"
" \"interfaces-config\": {\n"
" \"interfaces\": [ \"*\" ],\n"
" ],\n"
" \"valid-lifetime\": 4000\n"
" }\n",
- // CONFIGURATION 50
+ // CONFIGURATION 58
"{\n"
" \"interfaces-config\": {\n"
" \"interfaces\": [ \"*\" ],\n"
" ],\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"
" ],\n"
" \"valid-lifetime\": 4000\n"
" }\n",
- // CONFIGURATION 52
+ // CONFIGURATION 61
"{\n"
" \"interfaces-config\": {\n"
" \"interfaces\": [ \"*\" ],\n"
" ],\n"
" \"valid-lifetime\": 4000\n"
" }\n",
- // CONFIGURATION 53
+ // CONFIGURATION 62
"{\n"
" \"interfaces-config\": {\n"
" \"interfaces\": [ \"*\" ],\n"
" ],\n"
" \"valid-lifetime\": 4000\n"
" }\n",
- // CONFIGURATION 54
+ // CONFIGURATION 63
"{\n"
" \"interfaces-config\": {\n"
" \"interfaces\": [ \"*\" ],\n"
" ],\n"
" \"valid-lifetime\": 4000\n"
" }\n",
- // CONFIGURATION 55
+ // CONFIGURATION 64
"{\n"
" \"hosts-databases\": [\n"
" {\n"
" {\n"
" \"name\": \"keatest2\",\n"
" \"password\": \"keatest\",\n"
+" \"retry-on-startup\": true,\n"
" \"type\": \"mysql\",\n"
" \"user\": \"keatest\"\n"
" }\n"
" \"renew-timer\": 1000,\n"
" \"valid-lifetime\": 4000\n"
" }\n",
- // CONFIGURATION 56
+ // CONFIGURATION 65
"{\n"
" \"client-classes\": [\n"
" {\n"
" \"comment\": \"A DHCPv6 server\"\n"
" }\n"
" }\n",
- // CONFIGURATION 57
+ // CONFIGURATION 66
"{\n"
" \"interfaces-config\": {\n"
" \"interfaces\": [ \"*\" ],\n"
" ],\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"
" \"statistic-default-sample-count\": 10,\n"
" \"valid-lifetime\": 4000\n"
" }\n",
- // CONFIGURATION 59
+ // CONFIGURATION 71
"{\n"
" \"interfaces-config\": {\n"
" \"interfaces\": [ \"*\" ],\n"
" },\n"
" \"subnet6\": [ ]\n"
" }\n",
- // CONFIGURATION 60
+ // CONFIGURATION 72
"{\n"
" \"interfaces-config\": {\n"
" \"interfaces\": [ \"*\" ],\n"
" },\n"
" \"subnet6\": [ ]\n"
" }\n",
- // CONFIGURATION 61
+ // CONFIGURATION 73
"{\n"
" \"client-classes\": [\n"
" {\n"
" }\n"
" ]\n"
" }\n",
- // CONFIGURATION 62
+ // CONFIGURATION 74
"{\n"
" \"client-classes\": [\n"
" {\n"
" }\n"
" ]\n"
" }\n",
- // CONFIGURATION 63
+ // CONFIGURATION 75
"{\n"
" \"ddns-conflict-resolution-mode\": \"no-check-with-dhcid\",\n"
" \"interfaces-config\": {\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"
" \"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"
" \"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"
" \"t2-percent\": 0.8,\n"
" \"valid-lifetime\": 4000\n"
" }\n",
- // CONFIGURATION 2
+ // CONFIGURATION 4
"{\n"
" \"allocator\": \"iterative\",\n"
" \"calculate-tee-times\": true,\n"
" \"t2-percent\": 0.8,\n"
" \"valid-lifetime\": 4000\n"
" }\n",
- // CONFIGURATION 3
+ // CONFIGURATION 5
"{\n"
" \"allocator\": \"iterative\",\n"
" \"calculate-tee-times\": true,\n"
" \"t2-percent\": 0.8,\n"
" \"valid-lifetime\": 4000\n"
" }\n",
- // CONFIGURATION 4
+ // CONFIGURATION 6
"{\n"
" \"allocator\": \"iterative\",\n"
" \"calculate-tee-times\": true,\n"
" \"t2-percent\": 0.8,\n"
" \"valid-lifetime\": 4000\n"
" }\n",
- // CONFIGURATION 5
+ // CONFIGURATION 7
"{\n"
" \"allocator\": \"iterative\",\n"
" \"calculate-tee-times\": true,\n"
" \"t2-percent\": 0.8,\n"
" \"valid-lifetime\": 4000\n"
" }\n",
- // CONFIGURATION 6
+ // CONFIGURATION 8
"{\n"
" \"allocator\": \"iterative\",\n"
" \"calculate-tee-times\": true,\n"
" \"t2-percent\": 0.8,\n"
" \"valid-lifetime\": 4000\n"
" }\n",
- // CONFIGURATION 7
+ // CONFIGURATION 9
"{\n"
" \"allocator\": \"iterative\",\n"
" \"calculate-tee-times\": true,\n"
" \"t2-percent\": 0.8,\n"
" \"valid-lifetime\": 4000\n"
" }\n",
- // CONFIGURATION 8
+ // CONFIGURATION 10
"{\n"
" \"allocator\": \"iterative\",\n"
" \"calculate-tee-times\": true,\n"
" \"t2-percent\": 0.8,\n"
" \"valid-lifetime\": 4000\n"
" }\n",
- // CONFIGURATION 9
+ // CONFIGURATION 11
"{\n"
" \"allocator\": \"iterative\",\n"
" \"calculate-tee-times\": true,\n"
" \"t2-percent\": 0.8,\n"
" \"valid-lifetime\": 4000\n"
" }\n",
- // CONFIGURATION 10
+ // CONFIGURATION 12
"{\n"
" \"allocator\": \"iterative\",\n"
" \"calculate-tee-times\": true,\n"
" \"t2-percent\": 0.8,\n"
" \"valid-lifetime\": 7200\n"
" }\n",
- // CONFIGURATION 11
+ // CONFIGURATION 13
"{\n"
" \"allocator\": \"iterative\",\n"
" \"calculate-tee-times\": true,\n"
" \"t2-percent\": 0.8,\n"
" \"valid-lifetime\": 7200\n"
" }\n",
- // CONFIGURATION 12
+ // CONFIGURATION 14
"{\n"
" \"allocator\": \"iterative\",\n"
" \"calculate-tee-times\": true,\n"
" \"t2-percent\": 0.8,\n"
" \"valid-lifetime\": 7200\n"
" }\n",
- // CONFIGURATION 13
+ // CONFIGURATION 15
"{\n"
" \"allocator\": \"iterative\",\n"
" \"calculate-tee-times\": true,\n"
" \"t2-percent\": 0.8,\n"
" \"valid-lifetime\": 7200\n"
" }\n",
- // CONFIGURATION 14
+ // CONFIGURATION 16
"{\n"
" \"allocator\": \"iterative\",\n"
" \"calculate-tee-times\": true,\n"
" \"t2-percent\": 0.8,\n"
" \"valid-lifetime\": 7200\n"
" }\n",
- // CONFIGURATION 15
+ // CONFIGURATION 17
"{\n"
" \"allocator\": \"iterative\",\n"
" \"calculate-tee-times\": true,\n"
" \"t2-percent\": 0.8,\n"
" \"valid-lifetime\": 7200\n"
" }\n",
- // CONFIGURATION 16
+ // CONFIGURATION 18
"{\n"
" \"allocator\": \"iterative\",\n"
" \"calculate-tee-times\": true,\n"
" \"t2-percent\": 0.8,\n"
" \"valid-lifetime\": 7200\n"
" }\n",
- // CONFIGURATION 17
+ // CONFIGURATION 19
"{\n"
" \"allocator\": \"iterative\",\n"
" \"calculate-tee-times\": true,\n"
" \"t2-percent\": 0.8,\n"
" \"valid-lifetime\": 7200\n"
" }\n",
- // CONFIGURATION 18
+ // CONFIGURATION 20
"{\n"
" \"allocator\": \"iterative\",\n"
" \"calculate-tee-times\": true,\n"
" \"t2-percent\": 0.8,\n"
" \"valid-lifetime\": 7200\n"
" }\n",
- // CONFIGURATION 19
+ // CONFIGURATION 21
"{\n"
" \"allocator\": \"iterative\",\n"
" \"calculate-tee-times\": true,\n"
" \"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"
" \"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"
" \"t2-percent\": 0.8,\n"
" \"valid-lifetime\": 4000\n"
" }\n",
- // CONFIGURATION 20
+ // CONFIGURATION 24
"{\n"
" \"allocator\": \"iterative\",\n"
" \"calculate-tee-times\": true,\n"
" \"t2-percent\": 0.8,\n"
" \"valid-lifetime\": 4000\n"
" }\n",
- // CONFIGURATION 21
+ // CONFIGURATION 25
"{\n"
" \"allocator\": \"iterative\",\n"
" \"calculate-tee-times\": true,\n"
" \"t2-percent\": 0.8,\n"
" \"valid-lifetime\": 4000\n"
" }\n",
- // CONFIGURATION 22
+ // CONFIGURATION 26
"{\n"
" \"allocator\": \"iterative\",\n"
" \"calculate-tee-times\": true,\n"
" \"t2-percent\": 0.8,\n"
" \"valid-lifetime\": 4000\n"
" }\n",
- // CONFIGURATION 23
+ // CONFIGURATION 27
"{\n"
" \"allocator\": \"iterative\",\n"
" \"calculate-tee-times\": true,\n"
" \"t2-percent\": 0.8,\n"
" \"valid-lifetime\": 4000\n"
" }\n",
- // CONFIGURATION 24
+ // CONFIGURATION 28
"{\n"
" \"allocator\": \"iterative\",\n"
" \"calculate-tee-times\": true,\n"
" \"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"
" \"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"
" \"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"
" \"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"
" \"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"
" \"t2-percent\": 0.8,\n"
" \"valid-lifetime\": 4000\n"
" }\n",
- // CONFIGURATION 26
+ // CONFIGURATION 30
"{\n"
" \"allocator\": \"iterative\",\n"
" \"calculate-tee-times\": true,\n"
" \"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"
" \"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"
" \"t2-percent\": 0.8,\n"
" \"valid-lifetime\": 4000\n"
" }\n",
- // CONFIGURATION 27
+ // CONFIGURATION 31
"{\n"
" \"allocator\": \"iterative\",\n"
" \"calculate-tee-times\": true,\n"
" \"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"
" \"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"
" \"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"
" \"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"
" \"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"
" \"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"
" \"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"
" \"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"
" \"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"
" \"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"
" \"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"
" \"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"
" {\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"
" \"t2-percent\": 0.8,\n"
" \"valid-lifetime\": 4000\n"
" }\n",
- // CONFIGURATION 33
+ // CONFIGURATION 39
"{\n"
" \"allocator\": \"iterative\",\n"
" \"calculate-tee-times\": true,\n"
" \"t2-percent\": 0.8,\n"
" \"valid-lifetime\": 4000\n"
" }\n",
- // CONFIGURATION 34
+ // CONFIGURATION 40
"{\n"
" \"allocator\": \"iterative\",\n"
" \"calculate-tee-times\": true,\n"
" \"t2-percent\": 0.8,\n"
" \"valid-lifetime\": 4000\n"
" }\n",
- // CONFIGURATION 35
+ // CONFIGURATION 41
"{\n"
" \"allocator\": \"iterative\",\n"
" \"calculate-tee-times\": true,\n"
" \"t2-percent\": 0.8,\n"
" \"valid-lifetime\": 4000\n"
" }\n",
- // CONFIGURATION 36
+ // CONFIGURATION 42
"{\n"
" \"allocator\": \"iterative\",\n"
" \"calculate-tee-times\": true,\n"
" \"t2-percent\": 0.8,\n"
" \"valid-lifetime\": 4000\n"
" }\n",
- // CONFIGURATION 37
+ // CONFIGURATION 43
"{\n"
" \"allocator\": \"iterative\",\n"
" \"calculate-tee-times\": true,\n"
" \"t2-percent\": 0.8,\n"
" \"valid-lifetime\": 4000\n"
" }\n",
- // CONFIGURATION 38
+ // CONFIGURATION 44
"{\n"
" \"allocator\": \"iterative\",\n"
" \"calculate-tee-times\": true,\n"
" \"t2-percent\": 0.8,\n"
" \"valid-lifetime\": 4000\n"
" }\n",
- // CONFIGURATION 39
+ // CONFIGURATION 45
"{\n"
" \"allocator\": \"iterative\",\n"
" \"calculate-tee-times\": true,\n"
" \"t2-percent\": 0.8,\n"
" \"valid-lifetime\": 4000\n"
" }\n",
- // CONFIGURATION 40
+ // CONFIGURATION 46
"{\n"
" \"allocator\": \"iterative\",\n"
" \"calculate-tee-times\": true,\n"
" \"t2-percent\": 0.8,\n"
" \"valid-lifetime\": 4000\n"
" }\n",
- // CONFIGURATION 41
+ // CONFIGURATION 47
"{\n"
" \"allocator\": \"iterative\",\n"
" \"calculate-tee-times\": true,\n"
" \"t2-percent\": 0.8,\n"
" \"valid-lifetime\": 4000\n"
" }\n",
- // CONFIGURATION 42
+ // CONFIGURATION 48
"{\n"
" \"allocator\": \"iterative\",\n"
" \"calculate-tee-times\": true,\n"
" \"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"
" \"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"
" \"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"
" \"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"
" \"t2-percent\": 0.8,\n"
" \"valid-lifetime\": 7200\n"
" }\n",
- // CONFIGURATION 45
+ // CONFIGURATION 51
"{\n"
" \"allocator\": \"iterative\",\n"
" \"calculate-tee-times\": true,\n"
" \"t2-percent\": 0.8,\n"
" \"valid-lifetime\": 7200\n"
" }\n",
- // CONFIGURATION 46
+ // CONFIGURATION 52
"{\n"
" \"allocator\": \"iterative\",\n"
" \"calculate-tee-times\": true,\n"
" \"t2-percent\": 0.8,\n"
" \"valid-lifetime\": 7200\n"
" }\n",
- // CONFIGURATION 47
+ // CONFIGURATION 53
"{\n"
" \"allocator\": \"iterative\",\n"
" \"calculate-tee-times\": true,\n"
" \"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"
" \"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"
" \"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"
" \"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"
" \"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"
" \"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"
" \"t2-percent\": 0.8,\n"
" \"valid-lifetime\": 4000\n"
" }\n",
- // CONFIGURATION 51
+ // CONFIGURATION 57
"{\n"
" \"allocator\": \"iterative\",\n"
" \"calculate-tee-times\": true,\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"
+" \"user-context\": { }\n"
" }\n"
" ],\n"
" \"preferred-lifetime\": 3000,\n"
" \"t2-percent\": 0.8,\n"
" \"valid-lifetime\": 4000\n"
" }\n",
- // CONFIGURATION 52
+ // CONFIGURATION 58
"{\n"
" \"allocator\": \"iterative\",\n"
" \"calculate-tee-times\": true,\n"
" \"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"
" \"t2-percent\": 0.8,\n"
" \"valid-lifetime\": 4000\n"
" }\n",
- // CONFIGURATION 53
+ // CONFIGURATION 59
"{\n"
" \"allocator\": \"iterative\",\n"
" \"calculate-tee-times\": true,\n"
" \"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"
" \"t2-percent\": 0.8,\n"
" \"valid-lifetime\": 4000\n"
" }\n",
- // CONFIGURATION 54
+ // CONFIGURATION 60
"{\n"
" \"allocator\": \"iterative\",\n"
" \"calculate-tee-times\": true,\n"
" \"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"
" }\n"
" }\n"
" ],\n"
-" \"pools\": [ ],\n"
" \"preferred-lifetime\": 3000,\n"
" \"rapid-commit\": false,\n"
" \"rebind-timer\": 2000,\n"
" \"t2-percent\": 0.8,\n"
" \"valid-lifetime\": 4000\n"
" }\n",
- // CONFIGURATION 55
+ // CONFIGURATION 61
"{\n"
" \"allocator\": \"iterative\",\n"
" \"calculate-tee-times\": true,\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"
-" \"type\": \"mysql\",\n"
-" \"user\": \"keatest\"\n"
-" }\n"
-" ],\n"
" \"interfaces-config\": {\n"
" \"interfaces\": [ \"*\" ],\n"
" \"re-detect\": false\n"
" \"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"
" \"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"
" \"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"
" \"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"
" \"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"
" \"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"
" \"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"
" \"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"
" {\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"
" \"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"
" },\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"
" \"t2-percent\": 0.8,\n"
" \"valid-lifetime\": 4000\n"
" }\n",
- // CONFIGURATION 59
+ // CONFIGURATION 71
"{\n"
" \"allocator\": \"iterative\",\n"
" \"calculate-tee-times\": true,\n"
" \"t2-percent\": 0.8,\n"
" \"valid-lifetime\": 7200\n"
" }\n",
- // CONFIGURATION 60
+ // CONFIGURATION 72
"{\n"
" \"allocator\": \"iterative\",\n"
" \"calculate-tee-times\": true,\n"
" \"t2-percent\": 0.8,\n"
" \"valid-lifetime\": 7200\n"
" }\n",
- // CONFIGURATION 61
+ // CONFIGURATION 73
"{\n"
" \"allocator\": \"iterative\",\n"
" \"calculate-tee-times\": true,\n"
" \"t2-percent\": 0.8,\n"
" \"valid-lifetime\": 7200\n"
" }\n",
- // CONFIGURATION 62
+ // CONFIGURATION 74
"{\n"
" \"allocator\": \"iterative\",\n"
" \"calculate-tee-times\": true,\n"
" \"t2-percent\": 0.8,\n"
" \"valid-lifetime\": 7200\n"
" }\n",
- // CONFIGURATION 63
+ // CONFIGURATION 75
"{\n"
" \"allocator\": \"iterative\",\n"
" \"calculate-tee-times\": true,\n"
#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;
///
/// Exposes internal fields and installs stub implementation of the
/// @c CBControlDHCPv6 object.
-class NakedControlledDhcpv6Srv: public ControlledDhcpv6Srv {
+class NakedControlledDhcpv6Srv : public ControlledDhcpv6Srv {
public:
/// @brief Constructor.
}
};
-
+/// @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() {
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
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.
LeaseMgrFactory::instance().getType());
}
-
// This test verifies that backend specification can be added on
// server reconfiguration.
TEST_F(JSONFileBackendMySQLTest, reconfigureBackendUndefinedToMySQL) {
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());
}
}
.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") {
(keyword == "host") ||
(keyword == "name") ||
(keyword == "on-fail") ||
- (keyword == "retry-on-startup") ||
(keyword == "trust-anchor") ||
(keyword == "cert-file") ||
(keyword == "key-file") ||
"\"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"