]> git.ipfire.org Git - thirdparty/kea.git/commitdiff
[#488] Shared network parser stores parsed parameters in the object.
authorMarcin Siodelski <marcin@isc.org>
Mon, 4 Mar 2019 17:33:54 +0000 (18:33 +0100)
committerMarcin Siodelski <marcin@isc.org>
Thu, 7 Mar 2019 13:00:35 +0000 (08:00 -0500)
src/lib/dhcpsrv/parsers/shared_network_parser.cc
src/lib/dhcpsrv/parsers/shared_network_parser.h
src/lib/dhcpsrv/tests/shared_network_parser_unittest.cc

index 640e341eea50f764fdabbbb72a525fbff0200ce7..75086f0c20bf092773fa9b3ee2edf6792fda06b6 100644 (file)
@@ -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
 #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"));
@@ -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<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.
@@ -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() << ")");
index 362bc4d580aef531d9712f4594c1dbd4cd441cc3..88e3f4bb0f9c8f8427efe8d009308b8c94bb5fc4 100644 (file)
@@ -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
 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.
index df828640065ab1a6d06906acdf7b9f9404071141..2a7e0dbddd444dc78ac0041a6bb78b4adf37c3e0 100644 (file)
@@ -5,6 +5,7 @@
 // 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>
@@ -17,6 +18,7 @@
 #include <string>
 
 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();