BIND 10 trac2318, updated. 3271dcc47f185103c208585d1df8a92e50274f7a [2318] Implemented global options configuration.
BIND 10 source code commits
bind10-changes at lists.isc.org
Mon Oct 29 11:53:25 UTC 2012
The branch, trac2318 has been updated
via 3271dcc47f185103c208585d1df8a92e50274f7a (commit)
via ce0a6a9742cd2c18cb4c33ad0f174690ed1cbfc9 (commit)
from 4475bf75419cba6488628a2eb6f3b19fc795ae05 (commit)
Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.
- Log -----------------------------------------------------------------
commit 3271dcc47f185103c208585d1df8a92e50274f7a
Author: Marcin Siodelski <marcin at isc.org>
Date: Mon Oct 29 12:53:17 2012 +0100
[2318] Implemented global options configuration.
commit ce0a6a9742cd2c18cb4c33ad0f174690ed1cbfc9
Author: Marcin Siodelski <marcin at isc.org>
Date: Mon Oct 29 11:06:32 2012 +0100
[2318] Added global option values in dhcp6 spec.
-----------------------------------------------------------------------
Summary of changes:
src/bin/dhcp6/config_parser.cc | 42 ++++++++++++-
src/bin/dhcp6/dhcp6.spec | 78 ++++++++++++++++++-------
src/bin/dhcp6/tests/config_parser_unittest.cc | 65 +++++++++++++++++++++
3 files changed, 162 insertions(+), 23 deletions(-)
-----------------------------------------------------------------------
diff --git a/src/bin/dhcp6/config_parser.cc b/src/bin/dhcp6/config_parser.cc
index 490d8c0..9285105 100644
--- a/src/bin/dhcp6/config_parser.cc
+++ b/src/bin/dhcp6/config_parser.cc
@@ -61,6 +61,7 @@ typedef std::map<string, string> StringStorage;
/// no subnet object created yet to store them.
typedef std::vector<Pool6Ptr> PoolStorage;
+/// @brief Collection of options.
typedef std::vector<OptionPtr> OptionStorage;
/// @brief Global uint32 parameters that will be used as defaults.
@@ -69,6 +70,9 @@ Uint32Storage uint32_defaults;
/// @brief global string parameters that will be used as defaults.
StringStorage string_defaults;
+/// @brief Global storage for options that will be used as defaults.
+OptionStorage option_defaults;
+
/// @brief a dummy configuration parser
///
/// It is a debugging parser. It does not configure anything,
@@ -652,7 +656,8 @@ class OptionDataListParser : public DhcpConfigParser {
public:
/// @brief Constructor.
- OptionDataListParser(const std::string&) { }
+ OptionDataListParser(const std::string&)
+ : options_(&option_defaults) { }
/// @brief Parses entries that define options' data for a subnet.
///
@@ -798,10 +803,36 @@ public:
subnet->addPool6(*it);
}
+ // Add subnet specific options.
BOOST_FOREACH(OptionPtr option, options_) {
subnet->addOption(option);
}
+ // Get all options that we have added to subnet so far. We will
+ // use them to check which of the global options must be added to
+ // the subnet.
+ Subnet::OptionContainer options = subnet->getOptions();
+ // Get the search index #1 which is used to search options
+ // by their code (type).
+ Subnet::OptionContainerTypeIndex& idx = options.get<1>();
+ // Check all global options and add them to the subnet object if
+ // they have been configured in the global scope. If they have been
+ // configured in the subnet scope we don't add global option because
+ // the one configured in the subnet scope always takes precedense.
+ BOOST_FOREACH(OptionPtr option, option_defaults) {
+ // Get local option descriptors using global option code.
+ std::pair<Subnet::OptionContainerTypeIndex::const_iterator,
+ Subnet::OptionContainerTypeIndex::const_iterator> range =
+ idx.equal_range(option->getType());
+ // @todo: In the future we will be searching for options using either
+ // option code or namespace. Currently we have only the option
+ // code available so if there is at least one option found with the
+ // specific code we don't add globally configured option.
+ if (std::distance(range.first, range.second) == 0) {
+ subnet->addOption(option);
+ }
+ }
+
CfgMgr::instance().addSubnet6(subnet);
}
@@ -982,6 +1013,9 @@ DhcpConfigParser* createGlobalDhcpConfigParser(const std::string& config_id) {
"subnet6", Subnets6ListConfigParser::Factory));
factories.insert(pair<string, ParserFactory*>(
+ "option-data", OptionDataListParser::Factory));
+
+ factories.insert(pair<string, ParserFactory*>(
"version", StringParser::Factory));
FactoryMap::iterator f = factories.find(config_id);
@@ -1017,6 +1051,12 @@ configureDhcp6Server(Dhcpv6Srv& , ConstElementPtr config_set) {
"Null pointer is passed to configuration parser");
}
+ /// Reset global storage. Containers being reset below may contain
+ /// data from the previous configuration attempts.
+ option_defaults.clear();
+ uint32_defaults.clear();
+ string_defaults.clear();
+
/// @todo: append most essential info here (like "2 new subnets configured")
string config_details;
diff --git a/src/bin/dhcp6/dhcp6.spec b/src/bin/dhcp6/dhcp6.spec
index 818ea4b..c5e9565 100644
--- a/src/bin/dhcp6/dhcp6.spec
+++ b/src/bin/dhcp6/dhcp6.spec
@@ -40,6 +40,37 @@
"item_default": 4000
},
+ { "item_name": "option-data",
+ "item_type": "list",
+ "item_optional": false,
+ "item_default": [],
+ "list_item_spec":
+ {
+ "item_name": "single-option-data",
+ "item_type": "map",
+ "item_optional": false,
+ "item_default": {},
+ "map_item_spec": [
+ {
+ "item_name": "name",
+ "item_type": "string",
+ "item_optional": false,
+ "item_default": ""
+ },
+
+ { "item_name": "code",
+ "item_type": "integer",
+ "item_optional": false,
+ "item_default": 0
+ },
+ { "item_name": "data",
+ "item_type": "string",
+ "item_optional": false,
+ "item_default": ""
+ } ]
+ }
+ },
+
{ "item_name": "subnet6",
"item_type": "list",
"item_optional": false,
@@ -99,29 +130,32 @@
"item_default": [],
"list_item_spec":
{
- "item_name": "single-option-data",
- "item_type": "map",
+ "item_name": "single-option-data",
+ "item_type": "map",
+ "item_optional": false,
+ "item_default": {},
+ "map_item_spec": [
+ {
+ "item_name": "name",
+ "item_type": "string",
"item_optional": false,
- "item_default": {},
- "map_item_spec": [
- { "item_name": "name",
- "item_type": "string",
- "item_optional": false,
- "item_default": ""
- },
- { "item_name": "code",
- "item_type": "integer",
- "item_optional": false,
- "item_default": 0
- },
- { "item_name": "data",
- "item_type": "string",
- "item_optional": false,
- "item_default": ""
- } ]
- },
- } ]
- }
+ "item_default": ""
+ },
+ {
+ "item_name": "code",
+ "item_type": "integer",
+ "item_optional": false,
+ "item_default": 0
+ },
+ {
+ "item_name": "data",
+ "item_type": "string",
+ "item_optional": false,
+ "item_default": ""
+ } ]
+ }
+ } ]
+ }
}
],
"commands": [
diff --git a/src/bin/dhcp6/tests/config_parser_unittest.cc b/src/bin/dhcp6/tests/config_parser_unittest.cc
index 02ca20c..54389fb 100644
--- a/src/bin/dhcp6/tests/config_parser_unittest.cc
+++ b/src/bin/dhcp6/tests/config_parser_unittest.cc
@@ -336,12 +336,77 @@ TEST_F(Dhcp6ParserTest, poolPrefixLen) {
EXPECT_EQ(4000, subnet->getValid());
}
+TEST_F(Dhcp6ParserTest, optionDataDefaults) {
+ ConstElementPtr x;
+ string config = "{ \"interface\": [ \"all\" ],"
+ "\"preferred-lifetime\": 3000,"
+ "\"rebind-timer\": 2000,"
+ "\"renew-timer\": 1000,"
+ "\"option-data\": [ {"
+ " \"name\": \"option_foo\","
+ " \"code\": 100,"
+ " \"data\": \"AB CDEF0105\""
+ " },"
+ " {"
+ " \"name\": \"option_foo2\","
+ " \"code\": 101,"
+ " \"data\": \"01\""
+ " } ],"
+ "\"subnet6\": [ { "
+ " \"pool\": [ \"2001:db8:1::/80\" ],"
+ " \"subnet\": \"2001:db8:1::/64\""
+ " } ],"
+ "\"valid-lifetime\": 4000 }";
+
+ ElementPtr json = Element::fromJSON(config);
+
+ EXPECT_NO_THROW(x = configureDhcp6Server(*srv_, json));
+ ASSERT_TRUE(x);
+ comment_ = parseAnswer(rcode_, x);
+ ASSERT_EQ(0, rcode_);
+
+ Subnet6Ptr subnet = CfgMgr::instance().getSubnet6(IOAddress("2001:db8:1::5"));
+ ASSERT_TRUE(subnet);
+ const Subnet::OptionContainer& options = subnet->getOptions();
+ ASSERT_EQ(2, options.size());
+
+ // Get the search index. Index #1 is to search using option code.
+ const Subnet::OptionContainerTypeIndex& idx = options.get<1>();
+
+ // Get the options for specified index. Expecting one option to be
+ // returned but in theory we may have multiple options with the same
+ // code so we get the range.
+ std::pair<Subnet::OptionContainerTypeIndex::const_iterator,
+ Subnet::OptionContainerTypeIndex::const_iterator> range =
+ idx.equal_range(100);
+ // Expect single option with the code equal to 100.
+ ASSERT_EQ(1, std::distance(range.first, range.second));
+ const uint8_t foo_expected[] = {
+ 0xAB, 0xCD, 0xEF, 0x01, 0x05
+ };
+ // Check if option is valid in terms of code and carried data.
+ testOption(*range.first, 100, foo_expected, sizeof(foo_expected));
+
+ range = idx.equal_range(101);
+ ASSERT_EQ(1, std::distance(range.first, range.second));
+ // Do another round of testing with second option.
+ const uint8_t foo2_expected[] = {
+ 0x01
+ };
+ testOption(*range.first, 101, foo2_expected, sizeof(foo2_expected));
+}
+
TEST_F(Dhcp6ParserTest, optionDataInSingleSubnet) {
ConstElementPtr x;
string config = "{ \"interface\": [ \"all\" ],"
"\"preferred-lifetime\": 3000,"
"\"rebind-timer\": 2000, "
"\"renew-timer\": 1000, "
+ "\"option-data\": [ {"
+ " \"name\": \"option_foo\","
+ " \"code\": 100,"
+ " \"data\": \"AB\""
+ " } ],"
"\"subnet6\": [ { "
" \"pool\": [ \"2001:db8:1::/80\" ],"
" \"subnet\": \"2001:db8:1::/64\", "
More information about the bind10-changes
mailing list