BOOST_FOREACH(ConfigPair param, pd_pool_->mapValue()) {
std::string entry(param.first);
ParserPtr parser;
- if (entry == "prefix") {
+ if (entry == "prefix" || entry =="excluded-prefix") {
StringParserPtr str_parser(new StringParser(entry,
string_values_));
parser = str_parser;
- } else if (entry == "prefix-len" || entry == "delegated-len") {
+ } else if (entry == "prefix-len" || entry == "delegated-len" ||
+ entry == "excluded-prefix-len") {
Uint32ParserPtr code_parser(new Uint32Parser(entry,
uint32_values_));
parser = code_parser;
// Try to obtain the pool parameters. It will throw an exception if any
// of the required parameters are not present or invalid.
try {
- std::string addr_str = string_values_->getParam("prefix");
- uint32_t prefix_len = uint32_values_->getParam("prefix-len");
- uint32_t delegated_len = uint32_values_->getParam("delegated-len");
+ const std::string addr_str = string_values_->getParam("prefix");
+ const uint32_t prefix_len = uint32_values_->getParam("prefix-len");
+ const uint32_t delegated_len = uint32_values_->getParam("delegated-len");
+ const std::string excluded_prefix_str =
+ string_values_->getOptionalParam("excluded-prefix", "::");
+ const uint32_t excluded_prefix_len =
+ uint32_values_->getOptionalParam("excluded-prefix-len", 0);
// Attempt to construct the local pool.
- pool_.reset(new Pool6(Lease::TYPE_PD, IOAddress(addr_str),
- prefix_len, delegated_len));
+ pool_.reset(new Pool6(IOAddress(addr_str), prefix_len,
+ delegated_len, IOAddress(excluded_prefix_str),
+ excluded_prefix_len));
} catch (const std::exception& ex) {
// Some parameters don't exist or are invalid. Since we are not
// aware whether they don't exist or are invalid, let's append
}
if (!code) {
- OptionDefinitionPtr def = LibDHCP::getOptionDef(Option::V6, option_str);
+ const OptionDefinitionPtr def = LibDHCP::getOptionDef(Option::V6,
+ option_str);
if (def) {
code = def->getCode();
} else {
EXPECT_EQ(lastAddrInPrefix(prefixAddress, 64), p6->getLastAddress());
}
+// This test verifies that it is possible to specify a prefix pool with an
+// excluded prefix (see RFC6603).
+TEST_F(Dhcp6ParserTest, pdPoolPrefixExclude) {
+
+ ConstElementPtr x;
+
+ // Define a single valid pd pool.
+ string config =
+ "{ " + genIfaceConfig() + ","
+ "\"preferred-lifetime\": 3000,"
+ "\"rebind-timer\": 2000, "
+ "\"renew-timer\": 1000, "
+ "\"subnet6\": [ { "
+ " \"subnet\": \"2001:db8:1::/64\","
+ " \"pd-pools\": ["
+ " { \"prefix\": \"3000::\", "
+ " \"prefix-len\": 48, "
+ " \"delegated-len\": 64,"
+ " \"excluded-prefix\": \"3000:1::\","
+ " \"excluded-prefix-len\": 72"
+ " } ],"
+ "\"valid-lifetime\": 4000 }"
+ "] }";
+
+ // Convert the JSON string into Elements.
+ ElementPtr json;
+ ASSERT_NO_THROW(json = Element::fromJSON(config));
+
+ // Verify that DHCP6 configuration processing succeeds.
+ // Returned value must be non-empty ConstElementPtr to config result.
+ // rcode should be 0 which indicates successful configuration processing.
+ EXPECT_NO_THROW(x = configureDhcp6Server(srv_, json));
+ checkResult(x, 0);
+
+ // Test that we can retrieve the subnet.
+ Subnet6Ptr subnet = CfgMgr::instance().getStagingCfg()->getCfgSubnets6()->
+ selectSubnet(IOAddress("2001:db8:1::5"), classify_);
+ ASSERT_TRUE(subnet);
+
+ // Fetch the collection of PD pools. It should have 1 entry.
+ PoolCollection pc;
+ ASSERT_NO_THROW(pc = subnet->getPools(Lease::TYPE_PD));
+ EXPECT_EQ(1, pc.size());
+
+ // Get a pointer to the pd pool instance, and verify its contents.
+ Pool6Ptr p6;
+ ASSERT_NO_THROW(p6 = boost::dynamic_pointer_cast<Pool6>(pc[0]));
+ ASSERT_TRUE(p6);
+ EXPECT_EQ("3000::", p6->getFirstAddress().toText());
+ EXPECT_EQ(64, p6->getLength());
+ EXPECT_EQ("3000:1::", p6->getExcludedPrefix().toText());
+ EXPECT_EQ(72, static_cast<unsigned>(p6->getExcludedPrefixLength()));
+}
+
// Goal of this test is verify that a list of PD pools can be configured.
// It also verifies that a subnet may be configured with both regular pools
// and pd pools.