From: Marcin Siodelski Date: Mon, 27 May 2019 13:13:21 +0000 (+0200) Subject: [#628,!341] Shared network parser supports interface-id. X-Git-Tag: Kea-1.6.0-beta~32 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=810c4aedc204a628fcc8426f54126c667fd29045;p=thirdparty%2Fkea.git [#628,!341] Shared network parser supports interface-id. --- diff --git a/src/lib/dhcpsrv/parsers/shared_network_parser.cc b/src/lib/dhcpsrv/parsers/shared_network_parser.cc index 15fd80d912..6572b05559 100644 --- a/src/lib/dhcpsrv/parsers/shared_network_parser.cc +++ b/src/lib/dhcpsrv/parsers/shared_network_parser.cc @@ -19,6 +19,7 @@ using namespace isc::asiolink; using namespace isc::data; +using namespace isc::util; namespace isc { namespace dhcp { @@ -205,6 +206,45 @@ SharedNetwork6Parser::parse(const data::ConstElementPtr& shared_network_data) { "preferred-lifetime")); } + // Get interface-id option content. For now we support string + // representation only + Optional ifaceid; + if (shared_network_data->contains("interface-id")) { + ifaceid = getString(shared_network_data, "interface-id"); + } + + Optional iface; + if (shared_network_data->contains("interface")) { + iface = getString(shared_network_data, "interface"); + } + + // Specifying both interface for locally reachable subnets and + // interface id for relays is mutually exclusive. Need to test for + // this condition. + if (!ifaceid.unspecified() && !iface.unspecified() && !ifaceid.empty() && + !iface.empty()) { + isc_throw(isc::dhcp::DhcpConfigError, + "parser error: interface (defined for locally reachable " + "subnets) and interface-id (defined for subnets reachable" + " via relays) cannot be defined at the same time for " + "shared network " << name << "(" + << shared_network_data->getPosition() << ")"); + } + + // Configure interface-id for remote interfaces, if defined + if (!ifaceid.unspecified() && !ifaceid.empty()) { + std::string ifaceid_value = ifaceid.get(); + OptionBuffer tmp(ifaceid_value.begin(), ifaceid_value.end()); + OptionPtr opt(new Option(Option::V6, D6O_INTERFACE_ID, tmp)); + shared_network->setInterfaceId(opt); + } + + // Get interface name. If it is defined, then the subnet is available + // directly over specified network interface. + if (!iface.unspecified() && !iface.empty()) { + shared_network->setIface(iface); + } + // Interface is an optional parameter if (shared_network_data->contains("interface")) { shared_network->setIface(getString(shared_network_data, "interface")); diff --git a/src/lib/dhcpsrv/tests/shared_network_parser_unittest.cc b/src/lib/dhcpsrv/tests/shared_network_parser_unittest.cc index 9b04036a6b..9c007727ad 100644 --- a/src/lib/dhcpsrv/tests/shared_network_parser_unittest.cc +++ b/src/lib/dhcpsrv/tests/shared_network_parser_unittest.cc @@ -220,7 +220,7 @@ TEST_F(SharedNetwork4ParserTest, parse) { SharedNetwork4Parser parser; SharedNetwork4Ptr network; - try { + try { network = parser.parse(config_element); } catch (const std::exception& ex) { std::cout << "kabook: " << ex.what() << std::endl; @@ -407,13 +407,19 @@ TEST_F(SharedNetwork4ParserTest, relayInfoTests) { class SharedNetwork6ParserTest : public SharedNetworkParserTest { public: + /// @brief Constructor. + SharedNetwork6ParserTest() + : SharedNetworkParserTest(), network_(), use_iface_id_(false) { + } + /// @brief Creates valid shared network configuration. /// /// @return Valid shared network configuration. virtual std::string getWorkingConfig() const { std::string config = "{" " \"client-class\": \"srv1\"," - " \"interface\": \"eth1\"," + + std::string(use_iface_id_ ? "\"interface-id\": " : "\"interface\": ") + + "\"eth1\"," " \"name\": \"bird\"," " \"preferred-lifetime\": 211," " \"rapid-commit\": true," @@ -479,8 +485,13 @@ public: return (*network_); } -private: +public: + SharedNetwork6Ptr network_; + + /// Boolean flag indicating if the interface-id should be used instead + /// of interface. + bool use_iface_id_; }; // This test verifies that shared network parser for IPv4 works properly @@ -550,6 +561,41 @@ TEST_F(SharedNetwork6ParserTest, parse) { EXPECT_EQ("2001:db8:1::cafe", addresses[0].toText()); } +// This test verifies that shared network parser for IPv4 works properly +// in a positive test scenario. +TEST_F(SharedNetwork6ParserTest, parseWithInterfaceId) { + // Use the configuration with interface-id instead of interface parameter. + use_iface_id_ = true; + std::string config = getWorkingConfig(); + ElementPtr config_element = Element::fromJSON(config); + + // Parse configuration specified above. + SharedNetwork6Parser parser; + SharedNetwork6Ptr network; + ASSERT_NO_THROW(network = parser.parse(config_element)); + ASSERT_TRUE(network); + + // Check that interface-id has been parsed. + auto opt_iface_id = network->getInterfaceId(); + ASSERT_TRUE(opt_iface_id); +} + +// This test verifies that error is returned when trying to configure a +// shared network with both interface and interface id. +TEST_F(SharedNetwork6ParserTest, mutuallyExclusiveInterfaceId) { + // Use the configuration with interface-id instead of interface parameter. + use_iface_id_ = true; + std::string config = getWorkingConfig(); + ElementPtr config_element = Element::fromJSON(config); + + // Add interface which is mutually exclusive with interface-id + config_element->set("interface", Element::create("eth1")); + + // Parse configuration specified above. + SharedNetwork6Parser parser; + EXPECT_THROW(parser.parse(config_element), DhcpConfigError); +} + // This test verifies that it's possible to specify client-class // on shared-network level. TEST_F(SharedNetwork6ParserTest, clientClass) {