-// Copyright (C) 2012-2013 Internet Systems Consortium, Inc. ("ISC")
+// Copyright (C) 2012-2014 Internet Systems Consortium, Inc. ("ISC")
//
// Permission to use, copy, modify, and/or distribute this software for any
// purpose with or without fee is hereby granted, provided that the above
if ((config_id.compare("preferred-lifetime") == 0) ||
(config_id.compare("valid-lifetime") == 0) ||
(config_id.compare("renew-timer") == 0) ||
- (config_id.compare("rebind-timer") == 0)) {
+ (config_id.compare("rebind-timer") == 0) ||
+ (config_id.compare("id") == 0)) {
parser = new Uint32Parser(config_id, uint32_values_);
} else if ((config_id.compare("subnet") == 0) ||
(config_id.compare("interface") == 0) ||
Triplet<uint32_t> t2 = getParam("rebind-timer");
Triplet<uint32_t> pref = getParam("preferred-lifetime");
Triplet<uint32_t> valid = getParam("valid-lifetime");
+ // Subnet ID is optional. If it is not supplied the value of 0 is used,
+ // which means autogenerate.
+ SubnetID subnet_id =
+ static_cast<SubnetID>(uint32_values_->getOptionalParam("id", 0));
// Get interface-id option content. For now we support string
// represenation only
LOG_INFO(dhcp6_logger, DHCP6_CONFIG_NEW_SUBNET).arg(tmp.str());
// Create a new subnet.
- Subnet6* subnet6 = new Subnet6(addr, len, t1, t2, pref, valid);
+ Subnet6* subnet6 = new Subnet6(addr, len, t1, t2, pref, valid,
+ subnet_id);
// Configure interface-id for remote interfaces, if defined
if (!ifaceid.empty()) {
EXPECT_EQ(1, subnet->getID());
}
-// Goal of this test is to verify that multiple subnets get unique
-// subnet-ids. Also, test checks that it's possible to do reconfiguration
-// multiple times.
TEST_F(Dhcp6ParserTest, multipleSubnets) {
ConstElementPtr x;
+ // Collection of four subnets for which ids should be autogenerated
+ // - ids are unspecified or set to 0.
string config = "{ \"interfaces\": [ \"*\" ],"
"\"preferred-lifetime\": 3000,"
"\"rebind-timer\": 2000, "
" },"
" {"
" \"pool\": [ \"2001:db8:2::/80\" ],"
- " \"subnet\": \"2001:db8:2::/64\" "
+ " \"subnet\": \"2001:db8:2::/64\", "
+ " \"id\": 0"
" },"
" {"
" \"pool\": [ \"2001:db8:3::/80\" ],"
} while (++cnt < 10);
}
+// This checks that it is possible to assign arbitrary ids for subnets.
+TEST_F(Dhcp6ParserTest, multipleSubnetsExplicitIDs) {
+ ConstElementPtr x;
+ // Collection of four subnets for which ids should be autogenerated
+ // - ids are unspecified or set to 0.
+ string config = "{ \"interfaces\": [ \"*\" ],"
+ "\"preferred-lifetime\": 3000,"
+ "\"rebind-timer\": 2000, "
+ "\"renew-timer\": 1000, "
+ "\"subnet6\": [ { "
+ " \"pool\": [ \"2001:db8:1::/80\" ],"
+ " \"subnet\": \"2001:db8:1::/64\", "
+ " \"id\": 1024"
+ " },"
+ " {"
+ " \"pool\": [ \"2001:db8:2::/80\" ],"
+ " \"subnet\": \"2001:db8:2::/64\", "
+ " \"id\": 100"
+ " },"
+ " {"
+ " \"pool\": [ \"2001:db8:3::/80\" ],"
+ " \"subnet\": \"2001:db8:3::/64\", "
+ " \"id\": 1"
+ " },"
+ " {"
+ " \"pool\": [ \"2001:db8:4::/80\" ],"
+ " \"subnet\": \"2001:db8:4::/64\", "
+ " \"id\": 34"
+ " } ],"
+ "\"valid-lifetime\": 4000 }";
+
+ int cnt = 0; // Number of reconfigurations
+
+ do {
+ ElementPtr json = Element::fromJSON(config);
+
+ EXPECT_NO_THROW(x = configureDhcp6Server(srv_, json));
+ ASSERT_TRUE(x);
+ comment_ = parseAnswer(rcode_, x);
+ ASSERT_EQ(0, rcode_);
+
+ const Subnet6Collection* subnets = CfgMgr::instance().getSubnets6();
+ ASSERT_TRUE(subnets);
+ ASSERT_EQ(4, subnets->size()); // We expect 4 subnets
+
+ // Check that subnet ids are as expected.
+ EXPECT_EQ(1024, subnets->at(0)->getID());
+ EXPECT_EQ(100, subnets->at(1)->getID());
+ EXPECT_EQ(1, subnets->at(2)->getID());
+ EXPECT_EQ(34, subnets->at(3)->getID());
+
+ // Repeat reconfiguration process 10 times and check that the subnet-id
+ // is set to the same value.
+ } while (++cnt < 10);
+}
+
+// CHeck that the configuration with two subnets having the same id is rejected.
+TEST_F(Dhcp6ParserTest, multipleSubnetsOverlapingIDs) {
+ ConstElementPtr x;
+ // Four subnets, two of them have the same id.
+ string config = "{ \"interfaces\": [ \"*\" ],"
+ "\"preferred-lifetime\": 3000,"
+ "\"rebind-timer\": 2000, "
+ "\"renew-timer\": 1000, "
+ "\"subnet6\": [ { "
+ " \"pool\": [ \"2001:db8:1::/80\" ],"
+ " \"subnet\": \"2001:db8:1::/64\", "
+ " \"id\": 1024"
+ " },"
+ " {"
+ " \"pool\": [ \"2001:db8:2::/80\" ],"
+ " \"subnet\": \"2001:db8:2::/64\", "
+ " \"id\": 100"
+ " },"
+ " {"
+ " \"pool\": [ \"2001:db8:3::/80\" ],"
+ " \"subnet\": \"2001:db8:3::/64\", "
+ " \"id\": 1024"
+ " },"
+ " {"
+ " \"pool\": [ \"2001:db8:4::/80\" ],"
+ " \"subnet\": \"2001:db8:4::/64\", "
+ " \"id\": 34"
+ " } ],"
+ "\"valid-lifetime\": 4000 }";
+
+ ElementPtr json = Element::fromJSON(config);
+
+ EXPECT_NO_THROW(x = configureDhcp6Server(srv_, json));
+ ASSERT_TRUE(x);
+ comment_ = parseAnswer(rcode_, x);
+ ASSERT_NE(rcode_, 0);
+}
+
+
// Goal of this test is to verify that a previously configured subnet can be
// deleted in subsequent reconfiguration.
TEST_F(Dhcp6ParserTest, reconfigureRemoveSubnet) {
"\"renew-timer\": 1000, "
"\"subnet6\": [ { "
" \"pool\": [ \"2001:db8:1::/80\" ],"
- " \"subnet\": \"2001:db8:1::/64\" "
+ " \"subnet\": \"2001:db8:1::/64\", "
+ " \"id\": 1"
" },"
" {"
" \"pool\": [ \"2001:db8:2::/80\" ],"
- " \"subnet\": \"2001:db8:2::/64\" "
+ " \"subnet\": \"2001:db8:2::/64\", "
+ " \"id\": 2"
" },"
" {"
" \"pool\": [ \"2001:db8:3::/80\" ],"
- " \"subnet\": \"2001:db8:3::/64\" "
+ " \"subnet\": \"2001:db8:3::/64\", "
+ " \"id\": 3"
" },"
" {"
" \"pool\": [ \"2001:db8:4::/80\" ],"
- " \"subnet\": \"2001:db8:4::/64\" "
+ " \"subnet\": \"2001:db8:4::/64\", "
+ " \"id\": 4"
" } ],"
"\"valid-lifetime\": 4000 }";
"\"renew-timer\": 1000, "
"\"subnet6\": [ { "
" \"pool\": [ \"2001:db8:1::/80\" ],"
- " \"subnet\": \"2001:db8:1::/64\" "
+ " \"subnet\": \"2001:db8:1::/64\", "
+ " \"id\": 1"
" },"
" {"
" \"pool\": [ \"2001:db8:2::/80\" ],"
- " \"subnet\": \"2001:db8:2::/64\" "
+ " \"subnet\": \"2001:db8:2::/64\", "
+ " \"id\": 2"
" },"
" {"
" \"pool\": [ \"2001:db8:3::/80\" ],"
- " \"subnet\": \"2001:db8:3::/64\" "
+ " \"subnet\": \"2001:db8:3::/64\", "
+ " \"id\": 3"
" } ],"
"\"valid-lifetime\": 4000 }";
"\"renew-timer\": 1000, "
"\"subnet6\": [ { "
" \"pool\": [ \"2001:db8:1::/80\" ],"
- " \"subnet\": \"2001:db8:1::/64\" "
+ " \"subnet\": \"2001:db8:1::/64\", "
+ " \"id\": 1"
" },"
" {"
" \"pool\": [ \"2001:db8:3::/80\" ],"
- " \"subnet\": \"2001:db8:3::/64\" "
+ " \"subnet\": \"2001:db8:3::/64\", "
+ " \"id\": 3"
" },"
" {"
" \"pool\": [ \"2001:db8:4::/80\" ],"
- " \"subnet\": \"2001:db8:4::/64\" "
+ " \"subnet\": \"2001:db8:4::/64\", "
+ " \"id\": 4"
" } ],"
"\"valid-lifetime\": 4000 }";
/// CASE 2: Configure 4 subnets, then reconfigure and remove one
/// from in between (not first, not last)
-#if 0
/// @todo: Uncomment subnet removal test as part of #3281.
json = Element::fromJSON(config4);
EXPECT_NO_THROW(x = configureDhcp6Server(srv_, json));
// The second subnet (with subnet-id = 2) is no longer there
EXPECT_EQ(3, subnets->at(1)->getID());
EXPECT_EQ(4, subnets->at(2)->getID());
-#endif
}