From: Marcin Siodelski Date: Fri, 20 Nov 2015 16:41:39 +0000 (+0100) Subject: [4204] Runtime option definitions are stored in LibDHCP. X-Git-Tag: trac4204fd_rebased^2~9 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=1e7bdebfd5f28e03f1c2fb1897aa1967072295a1;p=thirdparty%2Fkea.git [4204] Runtime option definitions are stored in LibDHCP. --- diff --git a/src/lib/dhcp/libdhcp++.cc b/src/lib/dhcp/libdhcp++.cc index a537417f2f..60ef9f6f82 100644 --- a/src/lib/dhcp/libdhcp++.cc +++ b/src/lib/dhcp/libdhcp++.cc @@ -32,6 +32,8 @@ #include #include +#include + using namespace std; using namespace isc::dhcp; using namespace isc::util; @@ -198,9 +200,47 @@ LibDHCP::getVendorOptionDef(const Option::Universe u, const uint32_t vendor_id, return (OptionDefinitionPtr()); } +OptionDefinitionPtr +LibDHCP::getRuntimeOptionDef(const std::string& space, const uint16_t code) { + OptionDefContainerPtr container = runtime_option_defs_.getItems(space); + const OptionDefContainerTypeIndex& index = container->get<1>(); + const OptionDefContainerTypeRange& range = index.equal_range(code); + if (range.first != range.second) { + return (*range.first); + } + + return (OptionDefinitionPtr()); +} + +OptionDefinitionPtr +LibDHCP::getRuntimeOptionDef(const std::string& space, const std::string& name) { + OptionDefContainerPtr container = runtime_option_defs_.getItems(space); + const OptionDefContainerNameIndex& index = container->get<2>(); + const OptionDefContainerNameRange& range = index.equal_range(name); + if (range.first != range.second) { + return (*range.first); + } + + return (OptionDefinitionPtr()); +} + +OptionDefContainerPtr +LibDHCP::getRuntimeOptionDefs(const std::string& space) { + return (runtime_option_defs_.getItems(space)); +} + void LibDHCP::setRuntimeOptionDefs(const OptionDefSpaceContainer& defs) { - + std::list option_space_names = defs.getOptionSpaceNames(); + for (std::list::const_iterator name = option_space_names.begin(); + name != option_space_names.end(); ++name) { + OptionDefContainerPtr container = defs.getItems(*name); + for (OptionDefContainer::const_iterator def = container->begin(); + def != container->end(); ++def) { + OptionDefinitionPtr def_copy(new OptionDefinition(**def)); + runtime_option_defs_.addItem(def_copy, *name); + } + } } void @@ -275,7 +315,14 @@ size_t LibDHCP::unpackOptions6(const OptionBuffer& buf, OptionDefContainer option_defs; if (option_space == "dhcp6") { option_defs = LibDHCP::getOptionDefs(Option::V6); + } else { + OptionDefContainerPtr option_defs_ptr = + LibDHCP::getRuntimeOptionDefs(option_space); + if (option_defs_ptr) { + option_defs = *option_defs_ptr; + } } + // @todo Once we implement other option spaces we should add else clause // here and gather option definitions for them. For now leaving option_defs // empty will imply creation of generic Option. diff --git a/src/lib/dhcp/libdhcp++.h b/src/lib/dhcp/libdhcp++.h index 45fda662e4..ec346d8fb4 100644 --- a/src/lib/dhcp/libdhcp++.h +++ b/src/lib/dhcp/libdhcp++.h @@ -91,6 +91,37 @@ public: const uint32_t vendor_id, const std::string& name); + + /// @brief Returns runtime (non-standard) option definition by space and + /// option code. + /// + /// @param space Option space name. + /// @param code Option code. + /// + /// @return Pointer to option definition or NULL if it doesn't exist. + static OptionDefinitionPtr getRuntimeOptionDef(const std::string& space, + const uint16_t code); + + /// @brief Returns runtime (non-standard) option definition by space and + /// option name. + /// + /// @param space Option space name. + /// @param name Option name. + /// + /// @return Pointer to option definition or NULL if it doesn't exist. + static OptionDefinitionPtr getRuntimeOptionDef(const std::string& space, + const std::string& name); + + /// @brief Returns runtime (non-standard) option definitions for specified + /// option space name. + /// + /// @param space Option space name. + /// + /// @return Pointer to the container holding option definitions or NULL. + static OptionDefContainerPtr + getRuntimeOptionDefs(const std::string& space); + + /// @brief Check if the specified option is a standard option. /// /// @param u universe (V4 or V6) diff --git a/src/lib/dhcp/tests/libdhcp++_unittest.cc b/src/lib/dhcp/tests/libdhcp++_unittest.cc index 048e31f361..a4290aa884 100644 --- a/src/lib/dhcp/tests/libdhcp++_unittest.cc +++ b/src/lib/dhcp/tests/libdhcp++_unittest.cc @@ -147,6 +147,60 @@ public: return (OptionBuffer(opt_data, opt_data + sizeof(opt_data))); } + /// @brief Create option definitions and store in the container. + /// + /// @param spaces_num Number of option spaces to be created. + /// @param defs_num Number of option definitions to be created for + /// each option space. + /// @param [out] defs Container to which option definitions should be + /// added. + static void createRuntimeOptionDefs(const uint16_t spaces_num, + const uint16_t defs_num, + OptionDefSpaceContainer& defs) { + for (uint16_t space = 0; space < spaces_num; ++space) { + std::ostringstream space_name; + space_name << "option-space-" << space; + for (uint16_t code = 0; code < defs_num; ++code) { + std::ostringstream name; + name << "name-for-option-" << code; + OptionDefinitionPtr opt_def(new OptionDefinition(name.str(), + code, "string")); + defs.addItem(opt_def, space_name.str()); + } + } + } + + /// @brief Test if runtime option definitions have been added. + /// + /// This method uses the same naming conventions for space names and + /// options names as @c createRuntimeOptionDefs method. + /// + /// @param spaces_num Number of option spaces to be tested. + /// @param defs_num Number of option definitions that should exist + /// in each option space. + /// @param should_exist Boolean value which indicates if option + /// definitions should exist. If this is false, this function will + /// check that they don't exist. + static void testRuntimeOptionDefs(const uint16_t spaces_num, + const uint16_t defs_num, + const bool should_exist) { + for (uint16_t space = 0; space < spaces_num; ++space) { + std::ostringstream space_name; + space_name << "option-space-" << space; + for (uint16_t code = 0; code < defs_num; ++code) { + std::ostringstream name; + name << "name-for-option-" << code; + OptionDefinitionPtr opt_def = + LibDHCP::getRuntimeOptionDef(space_name.str(), name.str()); + if (should_exist) { + ASSERT_TRUE(opt_def); + } else { + ASSERT_FALSE(opt_def); + } + } + } + } + private: /// @brief Test DHCPv4 or DHCPv6 option definition. @@ -1319,4 +1373,28 @@ TEST_F(LibDhcpTest, vendorClass6) { EXPECT_EQ("eRouter1.0", vclass->getTuple(0).getText()); } +// This test verifies that it is possible to add runtime option definitions, +// retrieve them and remove them. +TEST_F(LibDhcpTest, setRuntimeOptionDefs) { + // Create option definitions in 5 namespaces. + OptionDefSpaceContainer defs; + createRuntimeOptionDefs(5, 100, defs); + + // Apply option definitions. + ASSERT_NO_THROW(LibDHCP::setRuntimeOptionDefs(defs)); + + // Retrieve all inserted option definitions. + testRuntimeOptionDefs(5, 100, true); + + // Attempting to retrieve non existing definitions. + EXPECT_FALSE(LibDHCP::getRuntimeOptionDef("option-space-non-existent", 1)); + EXPECT_FALSE(LibDHCP::getRuntimeOptionDef("option-space-0", 145)); + + // Remove all runtime option definitions. + ASSERT_NO_THROW(LibDHCP::clearRuntimeOptionDefs()); + + // All option definitions should be gone now. + testRuntimeOptionDefs(5, 100, false); +} + } // end of anonymous space