-// Copyright (C) 2017-2018 Internet Systems Consortium, Inc. ("ISC")
+// Copyright (C) 2017-2019 Internet Systems Consortium, Inc. ("ISC")
//
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
#include <dhcpsrv/parsers/option_data_parser.h>
#include <dhcpsrv/parsers/shared_network_parser.h>
#include <dhcpsrv/shared_network.h>
+#include <util/optional.h>
#include <boost/pointer_cast.hpp>
#include <string>
using namespace isc::data;
+using namespace isc::util;
namespace isc {
namespace dhcp {
+void
+SharedNetworkParser::parseCommonTimers(const ConstElementPtr& shared_network_data,
+ NetworkPtr& network) {
+ Triplet<uint32_t> t1;
+ if (shared_network_data->contains("renew-timer")) {
+ network->setT1(getInteger(shared_network_data, "renew-timer"));
+ }
+
+ Triplet<uint32_t> t2;
+ if (shared_network_data->contains("rebind-timer")) {
+ network->setT2(getInteger(shared_network_data, "rebind-timer"));
+ }
+
+ Triplet<uint32_t> valid;
+ if (shared_network_data->contains("valid-lifetime")) {
+ network->setValid(getInteger(shared_network_data, "valid-lifetime"));
+ }
+}
+
+void
+SharedNetworkParser::parseTeePercents(const ConstElementPtr& shared_network_data,
+ NetworkPtr& network) {
+ bool calculate_tee_times = network->getCalculateTeeTimes();
+ if (shared_network_data->contains("calculate-tee-times")) {
+ bool calculate_tee_times = getBoolean(shared_network_data, "calculate-tee-times");
+ network->setCalculateTeeTimes(calculate_tee_times);
+ }
+
+ Optional<double> t2_percent;
+ if (shared_network_data->contains("t2-percent")) {
+ t2_percent = getDouble(shared_network_data, "t2-percent");
+ }
+
+ Optional<double> t1_percent;
+ if (shared_network_data->contains("t1-percent")) {
+ t1_percent = getDouble(shared_network_data, "t1-percent");
+ }
+ if (calculate_tee_times) {
+ if (!t2_percent.unspecified() && ((t2_percent.get() <= 0.0) ||
+ (t2_percent.get() >= 1.0))) {
+ isc_throw(DhcpConfigError, "t2-percent: " << t2_percent.get()
+ << " is invalid, it must be greater than 0.0 and less than 1.0");
+ }
+
+ if (!t1_percent.unspecified() && ((t1_percent.get() <= 0.0) ||
+ (t1_percent.get() >= 1.0))) {
+ isc_throw(DhcpConfigError, "t1-percent: " << t1_percent.get()
+ << " is invalid it must be greater than 0.0 and less than 1.0");
+ }
+
+ if (!t1_percent.unspecified() && !t2_percent.unspecified() &&
+ (t1_percent.get() >= t2_percent.get())) {
+ isc_throw(DhcpConfigError, "t1-percent: " << t1_percent.get()
+ << " is invalid, it must be less than t2-percent: "
+ << t2_percent.get());
+ }
+ }
+
+ network->setT2Percent(t2_percent);
+ network->setT1Percent(t1_percent);
+}
+
SharedNetwork4Ptr
SharedNetwork4Parser::parse(const data::ConstElementPtr& shared_network_data) {
SharedNetwork4Ptr shared_network;
try {
+
// Make sure that the network name has been specified. The name is required
// to create a SharedNetwork4 object.
std::string name = getString(shared_network_data, "name");
shared_network.reset(new SharedNetwork4(name));
+ // Parse timers.
+ NetworkPtr network = boost::dynamic_pointer_cast<Network>(shared_network);
+ parseCommonTimers(shared_network_data, network);
+
// interface is an optional parameter
if (shared_network_data->contains("interface")) {
shared_network->setIface(getString(shared_network_data, "interface"));
shared_network->setRelayInfo(*relay_info);
}
}
+
+ parseTeePercents(shared_network_data, network);
+
} catch (const DhcpConfigError&) {
// Position was already added
throw;
std::string name = getString(shared_network_data, "name");
shared_network.reset(new SharedNetwork6(name));
+ NetworkPtr network = boost::dynamic_pointer_cast<Network>(shared_network);
+ parseCommonTimers(shared_network_data, network);
+
+ // preferred-lifetime
+ Triplet<uint32_t> preferred;
+ if (shared_network_data->contains("preferred-lifetime")) {
+ shared_network->setPreferred(getInteger(shared_network_data,
+ "preferred-lifetime"));
+ }
+
// Interface is an optional parameter
if (shared_network_data->contains("interface")) {
shared_network->setIface(getString(shared_network_data, "interface"));
}
+ if (shared_network_data->contains("rapid-commit")) {
+ shared_network->setRapidCommit(getBoolean(shared_network_data,
+ "rapid-commit"));
+ }
+
if (shared_network_data->contains("option-data")) {
auto json = shared_network_data->get("option-data");
// Create parser instance for option-data.
shared_network->setRelayInfo(*relay_info);
}
}
+
+ parseTeePercents(shared_network_data, network);
+
} catch (const std::exception& ex) {
isc_throw(DhcpConfigError, ex.what() << " ("
<< shared_network_data->getPosition() << ")");
-// Copyright (C) 2017 Internet Systems Consortium, Inc. ("ISC")
+// Copyright (C) 2017-2019 Internet Systems Consortium, Inc. ("ISC")
//
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
namespace isc {
namespace dhcp {
+/// @brief Common parser for IPv4 and IPv6 shared networks.
+///
+/// It contains common functions for parsing the shared networks.
+/// DHCPv4 and DHCPv6 specific implementations derive from it.
+class SharedNetworkParser : public isc::data::SimpleParser {
+protected:
+
+ /// @brief Parses common DHCP timers.
+ ///
+ /// The parsed parameters are:
+ /// - renew-timer,
+ /// - rebind-timer,
+ /// - valid-lifetime
+ ///
+ /// @param shared_network_data Data element holding shared network
+ /// configuration to be parsed.
+ /// @param [out] network Pointer to a network in which parsed data is
+ /// to be stored.
+ void parseCommonTimers(const data::ConstElementPtr& shared_network_data,
+ NetworkPtr& network);
+
+ /// @brief Parses parameters related to "percent" timers settngs.
+ ///
+ /// The parsed parameters are:
+ /// - calculate-tee-times,
+ /// - t1-percent,
+ /// - t2-percent.
+ ///
+ /// @param shared_network_data Data element holding shared network
+ /// configuration to be parsed.
+ /// @param [out] network Pointer to a network in which parsed data is
+ /// to be stored.
+ ///
+ /// @throw DhcpConfigError if configuration of these parameters is
+ /// invalid.
+ void parseTeePercents(const data::ConstElementPtr& shared_network_data,
+ NetworkPtr& network);
+};
+
/// @brief Implements parser for IPv4 shared networks.
-class SharedNetwork4Parser : isc::data::SimpleParser {
+class SharedNetwork4Parser : public SharedNetworkParser {
public:
/// @brief Parses shared configuration information for IPv4 shared network.
};
/// @brief Implements parser for IPv6 shared networks.
-class SharedNetwork6Parser : isc::data::SimpleParser {
+class SharedNetwork6Parser : public SharedNetworkParser {
public:
/// @brief Parses shared configuration information for IPv6 shared network.
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
#include <config.h>
+#include <asiolink/io_address.h>
#include <cc/data.h>
#include <dhcp/dhcp4.h>
#include <dhcp/dhcp6.h>
#include <string>
using namespace isc;
+using namespace isc::asiolink;
using namespace isc::data;
using namespace isc::dhcp;
/// @return Valid shared network configuration.
virtual std::string getWorkingConfig() const {
std::string config = "{"
- " \"user-context\": { \"comment\": \"example\" },"
- " \"name\": \"bird\","
+ " \"authoritative\": true,"
+ " \"boot-file-name\": \"/dev/null\","
+ " \"client-class\": \"srv1\","
" \"interface\": \"eth1\","
+ " \"match-client-id\": true,"
+ " \"name\": \"bird\","
+ " \"next-server\": \"10.0.0.1\","
+ " \"rebind-timer\": 199,"
+ " \"relay\": { \"ip-addresses\": [ \"10.1.1.1\" ] },"
+ " \"renew-timer\": 99,"
+ " \"reservation-mode\": \"out-of-pool\","
+ " \"server-hostname\": \"example.org\","
+ " \"require-client-classes\": [ \"runner\" ],"
+ " \"user-context\": { \"comment\": \"example\" },"
+ " \"valid-lifetime\": 399,"
+ " \"calculate-tee-times\": true,"
+ " \"t1-percent\": 0.345,"
+ " \"t2-percent\": 0.721,"
" \"option-data\": ["
" {"
" \"name\": \"domain-name-servers\","
ASSERT_NO_THROW(network = parser.parse(config_element));
ASSERT_TRUE(network);
+ /// @todo Validate next-server, server-hostname, boot-file-name once
+ /// they become a part of the shared network.
+
// Check basic parameters.
+ EXPECT_TRUE(network->getAuthoritative());
+ EXPECT_EQ("srv1", network->getClientClass().get());
EXPECT_EQ("bird", network->getName());
EXPECT_EQ("eth1", network->getIface().get());
+ EXPECT_EQ(99, network->getT1());
+ EXPECT_EQ(199, network->getT2());
+ EXPECT_EQ(399, network->getValid());
+ EXPECT_TRUE(network->getCalculateTeeTimes());
+ EXPECT_EQ(0.345, network->getT1Percent());
+ EXPECT_EQ(0.721, network->getT2Percent());
+
+ // Relay information.
+ auto relay_info = network->getRelayInfo();
+ EXPECT_EQ(1, relay_info.getAddresses().size());
+ EXPECT_TRUE(relay_info.containsAddress(IOAddress("10.1.1.1")));
+
+ // Required client classes.
+ auto required = network->getRequiredClasses();
+ ASSERT_EQ(1, required.size());
+ EXPECT_EQ("runner", *required.cbegin());
// Check user context.
ConstElementPtr context = network->getContext();
/// @return Valid shared network configuration.
virtual std::string getWorkingConfig() const {
std::string config = "{"
- " \"name\": \"bird\","
+ " \"client-class\": \"srv1\","
" \"interface\": \"eth1\","
+ " \"name\": \"bird\","
+ " \"preferred-lifetime\": 211,"
+ " \"rapid-commit\": true,"
+ " \"rebind-timer\": 199,"
+ " \"relay\": { \"ip-addresses\": [ \"2001:db8:1::1\" ] },"
+ " \"renew-timer\": 99,"
+ " \"require-client-classes\": [ \"runner\" ],"
+ " \"reservation-mode\": \"out-of-pool\","
" \"user-context\": { },"
+ " \"valid-lifetime\": 399,"
+ " \"calculate-tee-times\": true,"
+ " \"t1-percent\": 0.345,"
+ " \"t2-percent\": 0.721,"
" \"option-data\": ["
" {"
" \"name\": \"dns-servers\","
ASSERT_TRUE(network);
// Check basic parameters.
+ EXPECT_EQ("srv1", network->getClientClass().get());
EXPECT_EQ("bird", network->getName());
EXPECT_EQ("eth1", network->getIface().get());
+ EXPECT_EQ(211, network->getPreferred());
+ EXPECT_TRUE(network->getRapidCommit());
+ EXPECT_EQ(99, network->getT1());
+ EXPECT_EQ(199, network->getT2());
+ EXPECT_EQ(399, network->getValid());
+ EXPECT_TRUE(network->getCalculateTeeTimes());
+ EXPECT_EQ(0.345, network->getT1Percent());
+ EXPECT_EQ(0.721, network->getT2Percent());
+
+ // Relay information.
+ auto relay_info = network->getRelayInfo();
+ EXPECT_EQ(1, relay_info.getAddresses().size());
+ EXPECT_TRUE(relay_info.containsAddress(IOAddress("2001:db8:1::1")));
+
+ // Required client classes.
+ auto required = network->getRequiredClasses();
+ ASSERT_EQ(1, required.size());
+ EXPECT_EQ("runner", *required.cbegin());
// Check user context.
ConstElementPtr context = network->getContext();