From: Marcin Siodelski Date: Mon, 4 Mar 2019 17:33:54 +0000 (+0100) Subject: [#488] Shared network parser stores parsed parameters in the object. X-Git-Tag: 494-dhcp4configparser-sharednetworkssanitychecks-is-buggy_base~13 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=f29512b1000004344cb2a6dacedddef442b73449;p=thirdparty%2Fkea.git [#488] Shared network parser stores parsed parameters in the object. --- diff --git a/src/lib/dhcpsrv/parsers/shared_network_parser.cc b/src/lib/dhcpsrv/parsers/shared_network_parser.cc index 640e341eea..75086f0c20 100644 --- a/src/lib/dhcpsrv/parsers/shared_network_parser.cc +++ b/src/lib/dhcpsrv/parsers/shared_network_parser.cc @@ -1,4 +1,4 @@ -// 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 @@ -15,23 +15,92 @@ #include #include #include +#include #include #include using namespace isc::data; +using namespace isc::util; namespace isc { namespace dhcp { +void +SharedNetworkParser::parseCommonTimers(const ConstElementPtr& shared_network_data, + NetworkPtr& network) { + Triplet t1; + if (shared_network_data->contains("renew-timer")) { + network->setT1(getInteger(shared_network_data, "renew-timer")); + } + + Triplet t2; + if (shared_network_data->contains("rebind-timer")) { + network->setT2(getInteger(shared_network_data, "rebind-timer")); + } + + Triplet 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 t2_percent; + if (shared_network_data->contains("t2-percent")) { + t2_percent = getDouble(shared_network_data, "t2-percent"); + } + + Optional 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(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")); @@ -105,6 +174,9 @@ SharedNetwork4Parser::parse(const data::ConstElementPtr& shared_network_data) { shared_network->setRelayInfo(*relay_info); } } + + parseTeePercents(shared_network_data, network); + } catch (const DhcpConfigError&) { // Position was already added throw; @@ -126,11 +198,26 @@ SharedNetwork6Parser::parse(const data::ConstElementPtr& shared_network_data) { std::string name = getString(shared_network_data, "name"); shared_network.reset(new SharedNetwork6(name)); + NetworkPtr network = boost::dynamic_pointer_cast(shared_network); + parseCommonTimers(shared_network_data, network); + + // preferred-lifetime + Triplet 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. @@ -189,6 +276,9 @@ SharedNetwork6Parser::parse(const data::ConstElementPtr& shared_network_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() << ")"); diff --git a/src/lib/dhcpsrv/parsers/shared_network_parser.h b/src/lib/dhcpsrv/parsers/shared_network_parser.h index 362bc4d580..88e3f4bb0f 100644 --- a/src/lib/dhcpsrv/parsers/shared_network_parser.h +++ b/src/lib/dhcpsrv/parsers/shared_network_parser.h @@ -1,4 +1,4 @@ -// 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 @@ -16,8 +16,47 @@ 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. @@ -32,7 +71,7 @@ public: }; /// @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. diff --git a/src/lib/dhcpsrv/tests/shared_network_parser_unittest.cc b/src/lib/dhcpsrv/tests/shared_network_parser_unittest.cc index df82864006..2a7e0dbddd 100644 --- a/src/lib/dhcpsrv/tests/shared_network_parser_unittest.cc +++ b/src/lib/dhcpsrv/tests/shared_network_parser_unittest.cc @@ -5,6 +5,7 @@ // file, You can obtain one at http://mozilla.org/MPL/2.0/. #include +#include #include #include #include @@ -17,6 +18,7 @@ #include using namespace isc; +using namespace isc::asiolink; using namespace isc::data; using namespace isc::dhcp; @@ -113,9 +115,24 @@ public: /// @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\"," @@ -212,9 +229,30 @@ TEST_F(SharedNetwork4ParserTest, parse) { 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(); @@ -373,9 +411,21 @@ public: /// @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\"," @@ -448,8 +498,27 @@ TEST_F(SharedNetwork6ParserTest, parse) { 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();