BIND 10 master, updated. d90e9a0642fbb16a4e664160b4812f61fb81f1aa [master] Merge branch 'trac3281'
BIND 10 source code commits
bind10-changes at lists.isc.org
Mon Mar 31 19:33:44 UTC 2014
The branch, master has been updated
via d90e9a0642fbb16a4e664160b4812f61fb81f1aa (commit)
via 29dfbd1cf13eba290dcabd4dbecbc7321b4f1294 (commit)
via 1d9abefeca557f2ab2865cd364c08969d3027b88 (commit)
via 0a5a96b356fb3e7aae62209d8b28b4d026a79c62 (commit)
via ac941ce473d0d9cb922eec8f6352e1d80a02bd4a (commit)
via f4ba810511f61a1cefbeccd669f9c3cb40e07906 (commit)
via 30a20ce29360184cd0cef67a8dc53882a0e1b58d (commit)
via 17282104c6ecb2921fce4108104d74074571056f (commit)
via 9ecdae6cef285121647cb2b12722bb1e3cf5fa40 (commit)
from 70f1f297bfbaa8c2e8ad3decf92383fc550dad78 (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 d90e9a0642fbb16a4e664160b4812f61fb81f1aa
Merge: 70f1f29 29dfbd1
Author: Marcin Siodelski <marcin at isc.org>
Date: Mon Mar 31 20:59:26 2014 +0200
[master] Merge branch 'trac3281'
Conflicts:
doc/guide/bind10-guide.xml
-----------------------------------------------------------------------
Summary of changes:
doc/guide/bind10-guide.xml | 108 ++++++++++++++-----
src/bin/dhcp4/config_parser.cc | 9 +-
src/bin/dhcp4/dhcp4.spec | 6 ++
src/bin/dhcp4/tests/config_parser_unittest.cc | 134 ++++++++++++++++++++----
src/bin/dhcp6/config_parser.cc | 12 ++-
src/bin/dhcp6/dhcp6.spec | 6 ++
src/bin/dhcp6/tests/config_parser_unittest.cc | 139 +++++++++++++++++++++----
src/lib/dhcpsrv/cfgmgr.cc | 31 ++++++
src/lib/dhcpsrv/cfgmgr.h | 21 ++++
src/lib/dhcpsrv/subnet.cc | 17 +--
src/lib/dhcpsrv/subnet.h | 17 ++-
src/lib/dhcpsrv/tests/cfgmgr_unittest.cc | 35 +++++++
src/lib/dhcpsrv/tests/subnet_unittest.cc | 58 ++++++++++-
13 files changed, 509 insertions(+), 84 deletions(-)
-----------------------------------------------------------------------
diff --git a/doc/guide/bind10-guide.xml b/doc/guide/bind10-guide.xml
index 6c64525..6c95e73 100644
--- a/doc/guide/bind10-guide.xml
+++ b/doc/guide/bind10-guide.xml
@@ -3848,6 +3848,42 @@ Dhcp4/dhcp-ddns/qualifying-suffix "example.com" string
</para>
</section>
+ <section id="ipv4-subnet-id">
+ <title>IPv4 Subnet Identifier</title>
+ <para>
+ Subnet identifier is a unique number associated with a particular subnet.
+ In principle, it is used to associate clients' leases with respective subnets.
+ When subnet identifier is not specified for a subnet being configured, it will
+ be automatically assigned by the configuration mechanism. The identifiers
+ are assigned from 1 and are monotonically increased for each subsequent
+ subnet: 1, 2, 3 ....
+ </para>
+ <para>
+ If there are multiple subnets configured with auto-generated identifiers and
+ one of them is removed, the subnet identifiers may be renumbered. For example:
+ if there are 4 subnets and 3rd is removed the last subnet will be assigned
+ identifier that the 3rd subnet had before removal. As a result, the leases
+ stored in the lease database for subnet 3 are now associated with the
+ subnet 4, which may have unexpected consequences. In the future it is planned
+ to implement the mechanism to preserve auto-generated subnet ids upon removal
+ of one of the subnets. Currently, the only remedy for this issue is to
+ manually specify the unique subnet identifier for each subnet.
+ </para>
+ <para>
+ The following configuration:
+ <screen>
+> <userinput>config add Dhcp4/subnet4</userinput>
+> <userinput>config set Dhcp4/subnet4[0]/subnet "192.0.2.0/24"</userinput>
+> <userinput>config set Dhcp4/subnet4[0]/id 1024</userinput>
+> <userinput>config commit</userinput>
+ </screen>
+ will assign the arbitrary subnet identifier to the newly configured subnet.
+ This identifier will not change for this subnet until "id" parameter is
+ removed or set to 0. The value of 0 forces auto-generation of subnet
+ identifier.
+ </para>
+ </section>
+
<section id="dhcp4-address-config">
<title>Configuration of IPv4 Address Pools</title>
<para>
@@ -5016,19 +5052,11 @@ Dhcp4/dhcp-ddns/qualifying-suffix "example.com" string
yet</quote>, rather than actual limitations.</para>
<itemizedlist>
<listitem> <!-- see tickets #3234, #3281 -->
- <para>
- On-line configuration has some limitations. Adding new subnets or
- modifying existing ones work, as is removing the last subnet from
- the list. However, removing non-last (e.g. removing subnet 1,2 or 3 if
- there are 4 subnets configured) will cause issues. The problem is
- caused by simplistic subnet-id assignment. The subnets are always
- numbered, starting from 1. That subnet-id is then used in leases
- that are stored in the lease database. Removing non-last subnet will
- cause the configuration information to mismatch data in the lease
- database. It is possible to manually update subnet-id fields in
- MySQL database, but it is awkward and error prone process. A better
- reconfiguration support is planned.
- </para>
+ <simpara>
+ Removal of a subnet during server reconfiguration may cause renumbering
+ of auto-generated subnet identifiers, as described in section
+ <xref linkend="ipv4-subnet-id"/>.
+ </simpara>
</listitem>
<listitem>
<simpara>
@@ -5296,6 +5324,42 @@ Dhcp6/dhcp-ddns/qualifying-suffix "example.com" string
</para>
</section>
+ <section id="ipv6-subnet-id">
+ <title>IPv6 Subnet Identifier</title>
+ <para>
+ Subnet identifier is a unique number associated with a particular subnet.
+ In principle, it is used to associate clients' leases with respective subnets.
+ When subnet identifier is not specified for a subnet being configured, it will
+ be automatically assigned by the configuration mechanism. The identifiers
+ are assigned from 1 and are monotonically increased for each subsequent
+ subnet: 1, 2, 3 ....
+ </para>
+ <para>
+ If there are multiple subnets configured with auto-generated identifiers and
+ one of them is removed, the subnet identifiers may be renumbered. For example:
+ if there are 4 subnets and 3rd is removed the last subnet will be assigned
+ identifier that the 3rd subnet had before removal. As a result, the leases
+ stored in the lease database for subnet 3 are now associated with the
+ subnet 4, which may have unexpected consequences. In the future it is planned
+ to implement the mechanism to preserve auto-generated subnet ids upon removal
+ of one of the subnets. Currently, the only remedy for this issue is to
+ manually specify the unique subnet identifier for each subnet.
+ </para>
+ <para>
+ The following configuration:
+ <screen>
+> <userinput>config add Dhcp6/subnet6</userinput>
+> <userinput>config set Dhcp6/subnet6[0]/subnet "2001:db8:1::/64"</userinput>
+> <userinput>config set Dhcp6/subnet6[0]/id 1024</userinput>
+> <userinput>config commit</userinput>
+ </screen>
+ will assign the arbitrary subnet identifier to the newly configured subnet.
+ This identifier will not change for this subnet until "id" parameter is
+ removed or set to 0. The value of 0 forces auto-generation of subnet
+ identifier.
+ </para>
+ </section>
+
<section id="dhcp6-unicast">
<title>Unicast traffic support</title>
<para>
@@ -6439,19 +6503,11 @@ Dhcp6/dhcp-ddns/qualifying-suffix "example.com" string
<itemizedlist>
<listitem> <!-- see tickets #3234, #3281 -->
- <simpara>
- On-line configuration has some limitations. Adding new subnets or
- modifying existing ones work, as is removing the last subnet from
- the list. However, removing non-last (e.g. removing subnet 1,2 or 3 if
- there are 4 subnets configured) will cause issues. The problem is
- caused by simplistic subnet-id assignment. The subnets are always
- numbered, starting from 1. That subnet-id is then used in leases
- that are stored in the lease database. Removing non-last subnet will
- cause the configuration information to mismatch data in the lease
- database. It is possible to manually update subnet-id fields in
- MySQL database, but it is awkward and error prone process. A better
- reconfiguration support is planned.
- </simpara>
+ <simpara>
+ Removal of a subnet during server reconfiguration may cause renumbering
+ of auto-generated subnet identifiers, as described in section
+ <xref linkend="ipv6-subnet-id"/>.
+ </simpara>
</listitem>
<listitem>
<simpara>
diff --git a/src/bin/dhcp4/config_parser.cc b/src/bin/dhcp4/config_parser.cc
index 1d010f3..d22fef2 100644
--- a/src/bin/dhcp4/config_parser.cc
+++ b/src/bin/dhcp4/config_parser.cc
@@ -201,7 +201,8 @@ protected:
DhcpConfigParser* parser = NULL;
if ((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) ||
@@ -271,6 +272,10 @@ protected:
Triplet<uint32_t> t1 = getParam("renew-timer");
Triplet<uint32_t> t2 = getParam("rebind-timer");
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));
stringstream tmp;
tmp << addr << "/" << (int)len
@@ -278,7 +283,7 @@ protected:
LOG_INFO(dhcp4_logger, DHCP4_CONFIG_NEW_SUBNET).arg(tmp.str());
- Subnet4Ptr subnet4(new Subnet4(addr, len, t1, t2, valid));
+ Subnet4Ptr subnet4(new Subnet4(addr, len, t1, t2, valid, subnet_id));
subnet_ = subnet4;
// Try global value first
diff --git a/src/bin/dhcp4/dhcp4.spec b/src/bin/dhcp4/dhcp4.spec
index 5de65b2..1eae833 100644
--- a/src/bin/dhcp4/dhcp4.spec
+++ b/src/bin/dhcp4/dhcp4.spec
@@ -213,6 +213,12 @@
"item_default": ""
},
+ { "item_name": "id",
+ "item_type": "integer",
+ "item_optional": false,
+ "item_default": 0
+ },
+
{ "item_name": "renew-timer",
"item_type": "integer",
"item_optional": false,
diff --git a/src/bin/dhcp4/tests/config_parser_unittest.cc b/src/bin/dhcp4/tests/config_parser_unittest.cc
index e16ae17..e01c1dd 100644
--- a/src/bin/dhcp4/tests/config_parser_unittest.cc
+++ b/src/bin/dhcp4/tests/config_parser_unittest.cc
@@ -550,6 +550,8 @@ TEST_F(Dhcp4ParserTest, subnetGlobalDefaults) {
// multiple times.
TEST_F(Dhcp4ParserTest, multipleSubnets) {
ConstElementPtr x;
+ // Collection of four subnets for which subnet ids should be
+ // autogenerated - ids are unspecified or set to 0.
string config = "{ \"interfaces\": [ \"*\" ],"
"\"rebind-timer\": 2000, "
"\"renew-timer\": 1000, "
@@ -559,7 +561,8 @@ TEST_F(Dhcp4ParserTest, multipleSubnets) {
" },"
" {"
" \"pool\": [ \"192.0.3.101 - 192.0.3.150\" ],"
- " \"subnet\": \"192.0.3.0/24\" "
+ " \"subnet\": \"192.0.3.0/24\", "
+ " \"id\": 0 "
" },"
" {"
" \"pool\": [ \"192.0.4.101 - 192.0.4.150\" ],"
@@ -573,16 +576,9 @@ TEST_F(Dhcp4ParserTest, multipleSubnets) {
ElementPtr json = Element::fromJSON(config);
- EXPECT_NO_THROW(x = configureDhcp4Server(*srv_, json));
- ASSERT_TRUE(x);
- comment_ = parseAnswer(rcode_, x);
- ASSERT_EQ(0, rcode_);
-
int cnt = 0; // Number of reconfigurations
do {
- ElementPtr json = Element::fromJSON(config);
-
EXPECT_NO_THROW(x = configureDhcp4Server(*srv_, json));
ASSERT_TRUE(x);
comment_ = parseAnswer(rcode_, x);
@@ -605,6 +601,96 @@ TEST_F(Dhcp4ParserTest, multipleSubnets) {
} while (++cnt < 10);
}
+// This test checks that it is possible to assign arbitrary ids for subnets.
+TEST_F(Dhcp4ParserTest, multipleSubnetsExplicitIDs) {
+ ConstElementPtr x;
+ // Four subnets with arbitrary subnet ids.
+ string config = "{ \"interfaces\": [ \"*\" ],"
+ "\"rebind-timer\": 2000, "
+ "\"renew-timer\": 1000, "
+ "\"subnet4\": [ { "
+ " \"pool\": [ \"192.0.2.1 - 192.0.2.100\" ],"
+ " \"subnet\": \"192.0.2.0/24\", "
+ " \"id\": 1024 "
+ " },"
+ " {"
+ " \"pool\": [ \"192.0.3.101 - 192.0.3.150\" ],"
+ " \"subnet\": \"192.0.3.0/24\", "
+ " \"id\": 100 "
+ " },"
+ " {"
+ " \"pool\": [ \"192.0.4.101 - 192.0.4.150\" ],"
+ " \"subnet\": \"192.0.4.0/24\", "
+ " \"id\": 1 "
+ " },"
+ " {"
+ " \"pool\": [ \"192.0.5.101 - 192.0.5.150\" ],"
+ " \"subnet\": \"192.0.5.0/24\", "
+ " \"id\": 34 "
+ " } ],"
+ "\"valid-lifetime\": 4000 }";
+
+ ElementPtr json = Element::fromJSON(config);
+
+ int cnt = 0; // Number of reconfigurations
+ do {
+ EXPECT_NO_THROW(x = configureDhcp4Server(*srv_, json));
+ ASSERT_TRUE(x);
+ comment_ = parseAnswer(rcode_, x);
+ ASSERT_EQ(0, rcode_);
+
+ const Subnet4Collection* subnets = CfgMgr::instance().getSubnets4();
+ ASSERT_TRUE(subnets);
+ ASSERT_EQ(4, subnets->size()); // We expect 4 subnets
+
+ // Verify 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 < 3);
+}
+
+// Check that the configuration with two subnets having the same id is rejected.
+TEST_F(Dhcp4ParserTest, multipleSubnetsOverlapingIDs) {
+ ConstElementPtr x;
+ // Four subnets, two of them having the same id.
+ string config = "{ \"interfaces\": [ \"*\" ],"
+ "\"rebind-timer\": 2000, "
+ "\"renew-timer\": 1000, "
+ "\"subnet4\": [ { "
+ " \"pool\": [ \"192.0.2.1 - 192.0.2.100\" ],"
+ " \"subnet\": \"192.0.2.0/24\", "
+ " \"id\": 1024 "
+ " },"
+ " {"
+ " \"pool\": [ \"192.0.3.101 - 192.0.3.150\" ],"
+ " \"subnet\": \"192.0.3.0/24\", "
+ " \"id\": 100 "
+ " },"
+ " {"
+ " \"pool\": [ \"192.0.4.101 - 192.0.4.150\" ],"
+ " \"subnet\": \"192.0.4.0/24\", "
+ " \"id\": 1024 "
+ " },"
+ " {"
+ " \"pool\": [ \"192.0.5.101 - 192.0.5.150\" ],"
+ " \"subnet\": \"192.0.5.0/24\", "
+ " \"id\": 34 "
+ " } ],"
+ "\"valid-lifetime\": 4000 }";
+
+ ElementPtr json = Element::fromJSON(config);
+
+ EXPECT_NO_THROW(x = configureDhcp4Server(*srv_, json));
+ ASSERT_TRUE(x);
+ comment_ = parseAnswer(rcode_, x);
+ EXPECT_NE(rcode_, 0);
+}
+
// Goal of this test is to verify that a previously configured subnet can be
// deleted in subsequent reconfiguration.
TEST_F(Dhcp4ParserTest, reconfigureRemoveSubnet) {
@@ -616,19 +702,23 @@ TEST_F(Dhcp4ParserTest, reconfigureRemoveSubnet) {
"\"renew-timer\": 1000, "
"\"subnet4\": [ { "
" \"pool\": [ \"192.0.2.1 - 192.0.2.100\" ],"
- " \"subnet\": \"192.0.2.0/24\" "
+ " \"subnet\": \"192.0.2.0/24\", "
+ " \"id\": 1 "
" },"
" {"
" \"pool\": [ \"192.0.3.101 - 192.0.3.150\" ],"
- " \"subnet\": \"192.0.3.0/24\" "
+ " \"subnet\": \"192.0.3.0/24\", "
+ " \"id\": 2 "
" },"
" {"
" \"pool\": [ \"192.0.4.101 - 192.0.4.150\" ],"
- " \"subnet\": \"192.0.4.0/24\" "
+ " \"subnet\": \"192.0.4.0/24\", "
+ " \"id\": 3 "
" },"
" {"
" \"pool\": [ \"192.0.5.101 - 192.0.5.150\" ],"
- " \"subnet\": \"192.0.5.0/24\" "
+ " \"subnet\": \"192.0.5.0/24\", "
+ " \"id\": 4 "
" } ],"
"\"valid-lifetime\": 4000 }";
@@ -638,15 +728,18 @@ TEST_F(Dhcp4ParserTest, reconfigureRemoveSubnet) {
"\"renew-timer\": 1000, "
"\"subnet4\": [ { "
" \"pool\": [ \"192.0.2.1 - 192.0.2.100\" ],"
- " \"subnet\": \"192.0.2.0/24\" "
+ " \"subnet\": \"192.0.2.0/24\", "
+ " \"id\": 1 "
" },"
" {"
" \"pool\": [ \"192.0.3.101 - 192.0.3.150\" ],"
- " \"subnet\": \"192.0.3.0/24\" "
+ " \"subnet\": \"192.0.3.0/24\", "
+ " \"id\": 2 "
" },"
" {"
" \"pool\": [ \"192.0.4.101 - 192.0.4.150\" ],"
- " \"subnet\": \"192.0.4.0/24\" "
+ " \"subnet\": \"192.0.4.0/24\", "
+ " \"id\": 3 "
" } ],"
"\"valid-lifetime\": 4000 }";
@@ -656,15 +749,18 @@ TEST_F(Dhcp4ParserTest, reconfigureRemoveSubnet) {
"\"renew-timer\": 1000, "
"\"subnet4\": [ { "
" \"pool\": [ \"192.0.2.1 - 192.0.2.100\" ],"
- " \"subnet\": \"192.0.2.0/24\" "
+ " \"subnet\": \"192.0.2.0/24\", "
+ " \"id\": 1 "
" },"
" {"
" \"pool\": [ \"192.0.4.101 - 192.0.4.150\" ],"
- " \"subnet\": \"192.0.4.0/24\" "
+ " \"subnet\": \"192.0.4.0/24\", "
+ " \"id\": 3 "
" },"
" {"
" \"pool\": [ \"192.0.5.101 - 192.0.5.150\" ],"
- " \"subnet\": \"192.0.5.0/24\" "
+ " \"subnet\": \"192.0.5.0/24\", "
+ " \"id\": 4 "
" } ],"
"\"valid-lifetime\": 4000 }";
@@ -700,7 +796,6 @@ TEST_F(Dhcp4ParserTest, reconfigureRemoveSubnet) {
/// 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 = configureDhcp4Server(*srv_, json));
@@ -723,7 +818,6 @@ TEST_F(Dhcp4ParserTest, reconfigureRemoveSubnet) {
// 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
}
diff --git a/src/bin/dhcp6/config_parser.cc b/src/bin/dhcp6/config_parser.cc
index 2aa5513..9897f63 100644
--- a/src/bin/dhcp6/config_parser.cc
+++ b/src/bin/dhcp6/config_parser.cc
@@ -1,4 +1,4 @@
-// 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
@@ -406,7 +406,8 @@ protected:
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) ||
@@ -480,6 +481,10 @@ protected:
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
@@ -518,7 +523,8 @@ protected:
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()) {
diff --git a/src/bin/dhcp6/dhcp6.spec b/src/bin/dhcp6/dhcp6.spec
index 7462daa..5efc740 100644
--- a/src/bin/dhcp6/dhcp6.spec
+++ b/src/bin/dhcp6/dhcp6.spec
@@ -207,6 +207,12 @@
"item_default": ""
},
+ { "item_name": "id",
+ "item_type": "integer",
+ "item_optional": false,
+ "item_default": 0
+ },
+
{ "item_name": "interface",
"item_type": "string",
"item_optional": false,
diff --git a/src/bin/dhcp6/tests/config_parser_unittest.cc b/src/bin/dhcp6/tests/config_parser_unittest.cc
index 3829609..42ba112 100644
--- a/src/bin/dhcp6/tests/config_parser_unittest.cc
+++ b/src/bin/dhcp6/tests/config_parser_unittest.cc
@@ -569,11 +569,10 @@ TEST_F(Dhcp6ParserTest, subnetGlobalDefaults) {
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, "
@@ -584,7 +583,8 @@ TEST_F(Dhcp6ParserTest, multipleSubnets) {
" },"
" {"
" \"pool\": [ \"2001:db8:2::/80\" ],"
- " \"subnet\": \"2001:db8:2::/64\" "
+ " \"subnet\": \"2001:db8:2::/64\", "
+ " \"id\": 0"
" },"
" {"
" \"pool\": [ \"2001:db8:3::/80\" ],"
@@ -598,9 +598,9 @@ TEST_F(Dhcp6ParserTest, multipleSubnets) {
int cnt = 0; // Number of reconfigurations
- do {
- ElementPtr json = Element::fromJSON(config);
+ ElementPtr json = Element::fromJSON(config);
+ do {
EXPECT_NO_THROW(x = configureDhcp6Server(srv_, json));
ASSERT_TRUE(x);
comment_ = parseAnswer(rcode_, x);
@@ -623,6 +623,100 @@ TEST_F(Dhcp6ParserTest, multipleSubnets) {
} while (++cnt < 10);
}
+// This checks that it is possible to assign arbitrary ids for subnets.
+TEST_F(Dhcp6ParserTest, multipleSubnetsExplicitIDs) {
+ ConstElementPtr x;
+ // Four subnets with arbitrary subnet ids.
+ 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
+
+ ElementPtr json = Element::fromJSON(config);
+
+ do {
+ 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 < 3);
+}
+
+// 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) {
@@ -635,19 +729,23 @@ 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 }";
@@ -658,15 +756,18 @@ 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"
" } ],"
"\"valid-lifetime\": 4000 }";
@@ -677,15 +778,18 @@ 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: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 }";
@@ -720,8 +824,6 @@ TEST_F(Dhcp6ParserTest, reconfigureRemoveSubnet) {
/// 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));
ASSERT_TRUE(x);
@@ -743,7 +845,6 @@ TEST_F(Dhcp6ParserTest, reconfigureRemoveSubnet) {
// 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
}
diff --git a/src/lib/dhcpsrv/cfgmgr.cc b/src/lib/dhcpsrv/cfgmgr.cc
index 65b9dd7..12f1e5b 100644
--- a/src/lib/dhcpsrv/cfgmgr.cc
+++ b/src/lib/dhcpsrv/cfgmgr.cc
@@ -219,6 +219,10 @@ void CfgMgr::addSubnet6(const Subnet6Ptr& subnet) {
/// @todo: Check that this new subnet does not cross boundaries of any
/// other already defined subnet.
/// @todo: Check that there is no subnet with the same interface-id
+ if (isDuplicate(*subnet)) {
+ isc_throw(isc::dhcp::DuplicateSubnetID, "ID of the new IPv6 subnet '"
+ << subnet->getID() << "' is already in use");
+ }
LOG_DEBUG(dhcpsrv_logger, DHCPSRV_DBG_TRACE, DHCPSRV_CFGMGR_ADD_SUBNET6)
.arg(subnet->toText());
subnets6_.push_back(subnet);
@@ -282,6 +286,10 @@ CfgMgr::getSubnet4(const std::string& iface_name,
void CfgMgr::addSubnet4(const Subnet4Ptr& subnet) {
/// @todo: Check that this new subnet does not cross boundaries of any
/// other already defined subnet.
+ if (isDuplicate(*subnet)) {
+ isc_throw(isc::dhcp::DuplicateSubnetID, "ID of the new IPv4 subnet '"
+ << subnet->getID() << "' is already in use");
+ }
LOG_DEBUG(dhcpsrv_logger, DHCPSRV_DBG_TRACE, DHCPSRV_CFGMGR_ADD_SUBNET4)
.arg(subnet->toText());
subnets4_.push_back(subnet);
@@ -377,6 +385,29 @@ CfgMgr::isIfaceListedActive(const std::string& iface) const {
return (false);
}
+bool
+CfgMgr::isDuplicate(const Subnet4& subnet) const {
+ for (Subnet4Collection::const_iterator subnet_it = subnets4_.begin();
+ subnet_it != subnets4_.end(); ++subnet_it) {
+ if ((*subnet_it)->getID() == subnet.getID()) {
+ return (true);
+ }
+ }
+ return (false);
+}
+
+bool
+CfgMgr::isDuplicate(const Subnet6& subnet) const {
+ for (Subnet6Collection::const_iterator subnet_it = subnets6_.begin();
+ subnet_it != subnets6_.end(); ++subnet_it) {
+ if ((*subnet_it)->getID() == subnet.getID()) {
+ return (true);
+ }
+ }
+ return (false);
+}
+
+
const isc::asiolink::IOAddress*
CfgMgr::getUnicast(const std::string& iface) const {
UnicastIfacesCollection::const_iterator addr = unicast_addrs_.find(iface);
diff --git a/src/lib/dhcpsrv/cfgmgr.h b/src/lib/dhcpsrv/cfgmgr.h
index 31ef534..3331135 100644
--- a/src/lib/dhcpsrv/cfgmgr.h
+++ b/src/lib/dhcpsrv/cfgmgr.h
@@ -47,6 +47,13 @@ public:
isc::Exception(file, line, what) { };
};
+/// @brief Exception thrown upon attempt to add subnet with an ID that belongs
+/// to the subnet that already exists.
+class DuplicateSubnetID : public Exception {
+public:
+ DuplicateSubnetID(const char* file, size_t line, const char* what) :
+ isc::Exception(file, line, what) { };
+};
/// @brief Configuration Manager
///
@@ -458,6 +465,20 @@ private:
/// @c CfgMgr::active_ifaces_.
bool isIfaceListedActive(const std::string& iface) const;
+ /// @brief Checks that the IPv4 subnet with the given id already exists.
+ ///
+ /// @param subnet Subnet for which this function will check if the other
+ /// subnet with equal id already exists.
+ /// @return true if the duplicate subnet exists.
+ bool isDuplicate(const Subnet4& subnet) const;
+
+ /// @brief Checks that the IPv6 subnet with the given id already exists.
+ ///
+ /// @param subnet Subnet for which this function will check if the other
+ /// subnet with equal id already exists.
+ /// @return true if the duplicate subnet exists.
+ bool isDuplicate(const Subnet6& subnet) const;
+
/// @brief A collection of option definitions.
///
/// A collection of option definitions that can be accessed
diff --git a/src/lib/dhcpsrv/subnet.cc b/src/lib/dhcpsrv/subnet.cc
index f181a3a..ceba9af 100644
--- a/src/lib/dhcpsrv/subnet.cc
+++ b/src/lib/dhcpsrv/subnet.cc
@@ -31,8 +31,9 @@ Subnet::Subnet(const isc::asiolink::IOAddress& prefix, uint8_t len,
const Triplet<uint32_t>& t1,
const Triplet<uint32_t>& t2,
const Triplet<uint32_t>& valid_lifetime,
- const isc::dhcp::Subnet::RelayInfo& relay)
- :id_(generateNextID()), prefix_(prefix), prefix_len_(len),
+ const isc::dhcp::Subnet::RelayInfo& relay,
+ const SubnetID id)
+ :id_(id == 0 ? generateNextID() : id), prefix_(prefix), prefix_len_(len),
t1_(t1), t2_(t2), valid_(valid_lifetime),
last_allocated_ia_(lastAddrInPrefix(prefix, len)),
last_allocated_ta_(lastAddrInPrefix(prefix, len)),
@@ -211,9 +212,10 @@ void Subnet4::checkType(Lease::Type type) const {
Subnet4::Subnet4(const isc::asiolink::IOAddress& prefix, uint8_t length,
const Triplet<uint32_t>& t1,
const Triplet<uint32_t>& t2,
- const Triplet<uint32_t>& valid_lifetime)
+ const Triplet<uint32_t>& valid_lifetime,
+ const SubnetID id)
:Subnet(prefix, length, t1, t2, valid_lifetime,
- RelayInfo(IOAddress("0.0.0.0"))), siaddr_(IOAddress("0.0.0.0")) {
+ RelayInfo(IOAddress("0.0.0.0")), id), siaddr_(IOAddress("0.0.0.0")) {
if (!prefix.isV4()) {
isc_throw(BadValue, "Non IPv4 prefix " << prefix.toText()
<< " specified in subnet4");
@@ -363,9 +365,10 @@ Subnet6::Subnet6(const isc::asiolink::IOAddress& prefix, uint8_t length,
const Triplet<uint32_t>& t1,
const Triplet<uint32_t>& t2,
const Triplet<uint32_t>& preferred_lifetime,
- const Triplet<uint32_t>& valid_lifetime)
-:Subnet(prefix, length, t1, t2, valid_lifetime, RelayInfo(IOAddress("::"))),
- preferred_(preferred_lifetime){
+ const Triplet<uint32_t>& valid_lifetime,
+ const SubnetID id)
+:Subnet(prefix, length, t1, t2, valid_lifetime, RelayInfo(IOAddress("::")), id),
+ preferred_(preferred_lifetime) {
if (!prefix.isV6()) {
isc_throw(BadValue, "Non IPv6 prefix " << prefix
<< " specified in subnet6");
diff --git a/src/lib/dhcpsrv/subnet.h b/src/lib/dhcpsrv/subnet.h
index ae90761..35be8fa 100644
--- a/src/lib/dhcpsrv/subnet.h
+++ b/src/lib/dhcpsrv/subnet.h
@@ -466,7 +466,7 @@ protected:
/// @brief Protected constructor
//
- /// By making the constructor protected, we make sure that noone will
+ /// By making the constructor protected, we make sure that no one will
/// ever instantiate that class. Subnet4 and Subnet6 should be used instead.
///
/// This constructor assigns a new subnet-id (see @ref generateNextID).
@@ -480,11 +480,14 @@ protected:
/// @param t2 T2 (rebind-time) timer, expressed in seconds
/// @param valid_lifetime valid lifetime of leases in this subnet (in seconds)
/// @param relay optional relay information (currently with address only)
+ /// @param id arbitraty subnet id, value of 0 triggers autogeneration
+ /// of subnet id
Subnet(const isc::asiolink::IOAddress& prefix, uint8_t len,
const Triplet<uint32_t>& t1,
const Triplet<uint32_t>& t2,
const Triplet<uint32_t>& valid_lifetime,
- const isc::dhcp::Subnet::RelayInfo& relay);
+ const isc::dhcp::Subnet::RelayInfo& relay,
+ const SubnetID id);
/// @brief virtual destructor
///
@@ -637,10 +640,13 @@ public:
/// @param t1 renewal timer (in seconds)
/// @param t2 rebind timer (in seconds)
/// @param valid_lifetime preferred lifetime of leases (in seconds)
+ /// @param id arbitraty subnet id, default value of 0 triggers
+ /// autogeneration of subnet id
Subnet4(const isc::asiolink::IOAddress& prefix, uint8_t length,
const Triplet<uint32_t>& t1,
const Triplet<uint32_t>& t2,
- const Triplet<uint32_t>& valid_lifetime);
+ const Triplet<uint32_t>& valid_lifetime,
+ const SubnetID id = 0);
/// @brief Sets siaddr for the Subnet4
///
@@ -704,11 +710,14 @@ public:
/// @param t2 rebind timer (in seconds)
/// @param preferred_lifetime preferred lifetime of leases (in seconds)
/// @param valid_lifetime preferred lifetime of leases (in seconds)
+ /// @param id arbitraty subnet id, default value of 0 triggers
+ /// autogeneration of subnet id
Subnet6(const isc::asiolink::IOAddress& prefix, uint8_t length,
const Triplet<uint32_t>& t1,
const Triplet<uint32_t>& t2,
const Triplet<uint32_t>& preferred_lifetime,
- const Triplet<uint32_t>& valid_lifetime);
+ const Triplet<uint32_t>& valid_lifetime,
+ const SubnetID id = 0);
/// @brief Returns preverred lifetime (in seconds)
///
diff --git a/src/lib/dhcpsrv/tests/cfgmgr_unittest.cc b/src/lib/dhcpsrv/tests/cfgmgr_unittest.cc
index 6cffed5..ca06e46 100644
--- a/src/lib/dhcpsrv/tests/cfgmgr_unittest.cc
+++ b/src/lib/dhcpsrv/tests/cfgmgr_unittest.cc
@@ -1053,6 +1053,41 @@ TEST_F(CfgMgrTest, getSubnet4ForInterface) {
}
+// Checks that detection of duplicated subnet IDs works as expected. It should
+// not be possible to add two IPv4 subnets holding the same ID to the config
+// manager.
+TEST_F(CfgMgrTest, subnet4Duplication) {
+ CfgMgr& cfg_mgr = CfgMgr::instance();
+
+ Subnet4Ptr subnet1(new Subnet4(IOAddress("192.0.2.0"), 26, 1, 2, 3, 123));
+ Subnet4Ptr subnet2(new Subnet4(IOAddress("192.0.2.64"), 26, 1, 2, 3, 124));
+ Subnet4Ptr subnet3(new Subnet4(IOAddress("192.0.2.128"), 26, 1, 2, 3, 123));
+
+ ASSERT_NO_THROW(cfg_mgr.addSubnet4(subnet1));
+ EXPECT_NO_THROW(cfg_mgr.addSubnet4(subnet2));
+ // Subnet 3 has the same ID as subnet 1. It shouldn't be able to add it.
+ EXPECT_THROW(cfg_mgr.addSubnet4(subnet3), isc::dhcp::DuplicateSubnetID);
+}
+
+// Checks that detection of duplicated subnet IDs works as expected. It should
+// not be possible to add two IPv6 subnets holding the same ID to the config
+// manager.
+TEST_F(CfgMgrTest, subnet6Duplication) {
+ CfgMgr& cfg_mgr = CfgMgr::instance();
+
+ Subnet6Ptr subnet1(new Subnet6(IOAddress("2001:db8:1::"), 64, 1, 2, 3,
+ 4, 123));
+ Subnet6Ptr subnet2(new Subnet6(IOAddress("2001:db8:2::"), 64, 1, 2, 3,
+ 4, 124));
+ Subnet6Ptr subnet3(new Subnet6(IOAddress("2001:db8:3::"), 64, 1, 2, 3,
+ 4, 123));
+
+ ASSERT_NO_THROW(cfg_mgr.addSubnet6(subnet1));
+ EXPECT_NO_THROW(cfg_mgr.addSubnet6(subnet2));
+ // Subnet 3 has the same ID as subnet 1. It shouldn't be able to add it.
+ EXPECT_THROW(cfg_mgr.addSubnet6(subnet3), isc::dhcp::DuplicateSubnetID);
+}
+
/// @todo Add unit-tests for testing:
/// - addActiveIface() with invalid interface name
diff --git a/src/lib/dhcpsrv/tests/subnet_unittest.cc b/src/lib/dhcpsrv/tests/subnet_unittest.cc
index a16f1a0..99332e7 100644
--- a/src/lib/dhcpsrv/tests/subnet_unittest.cc
+++ b/src/lib/dhcpsrv/tests/subnet_unittest.cc
@@ -34,7 +34,7 @@ namespace {
TEST(Subnet4Test, constructor) {
EXPECT_NO_THROW(Subnet4 subnet1(IOAddress("192.0.2.2"), 16,
- 1, 2, 3));
+ 1, 2, 3, 10));
EXPECT_THROW(Subnet4 subnet2(IOAddress("192.0.2.0"), 33, 1, 2, 3),
BadValue); // invalid prefix length
@@ -42,7 +42,33 @@ TEST(Subnet4Test, constructor) {
BadValue); // IPv6 addresses are not allowed in Subnet4
}
-TEST(Subnet4Test, in_range) {
+// Checks that the subnet id can be either autogenerated or set to an
+// arbitrary value through the constructor.
+TEST(Subnet4Test, subnetID) {
+ // Create subnet and don't specify id, so as it is autogenerated.
+ Subnet4Ptr subnet(new Subnet4(IOAddress("192.0.2.0"), 24, 1000, 2000,
+ 3000));
+ SubnetID id0 = subnet->getID();
+
+ // Create another subnet and let id be autogenerated.
+ subnet.reset(new Subnet4(IOAddress("192.0.3.0"), 24, 1000, 2000,
+ 3000));
+ SubnetID id1 = subnet->getID();
+
+ // The autogenerated ids must not be equal.
+ EXPECT_NE(id0, id1);
+
+ // Create third subnet but this time select an arbitrary id. The id
+ // we use the one of the second subnet. That way we ensure that the
+ // subnet id we provide via constructor is used and it is not
+ // autogenerated - if it was autogenerated we would get id other
+ // than id1 because id1 has already been used.
+ subnet.reset(new Subnet4(IOAddress("192.0.4.0"), 24, 1000, 2000,
+ 3000, id1));
+ EXPECT_EQ(id1, subnet->getID());
+}
+
+TEST(Subnet4Test, inRange) {
Subnet4 subnet(IOAddress("192.0.2.1"), 24, 1000, 2000, 3000);
EXPECT_EQ(1000, subnet.getT1());
@@ -362,7 +388,33 @@ TEST(Subnet6Test, constructor) {
BadValue); // IPv4 addresses are not allowed in Subnet6
}
-TEST(Subnet6Test, in_range) {
+// Checks that the subnet id can be either autogenerated or set to an
+// arbitrary value through the constructor.
+TEST(Subnet6Test, subnetID) {
+ // Create subnet and don't specify id, so as it is autogenerated.
+ Subnet6Ptr subnet(new Subnet6(IOAddress("2001:db8:1::"), 64, 1000, 2000,
+ 3000, 4000));
+ SubnetID id0 = subnet->getID();
+
+ // Create another subnet and let id be autogenerated.
+ subnet.reset(new Subnet6(IOAddress("2001:db8:2::"), 64, 1000, 2000,
+ 3000, 4000));
+ SubnetID id1 = subnet->getID();
+
+ // The autogenerated ids must not be equal.
+ EXPECT_NE(id0, id1);
+
+ // Create third subnet but this time select an arbitrary id. The id
+ // we use us the one of second subnet. That way we ensure that the
+ // subnet id we provide via constructor is used and it is not
+ // autogenerated - if it was autogenerated we would get id other
+ // than id1 because id1 has already been used.
+ subnet.reset(new Subnet6(IOAddress("2001:db8:3::"), 64, 1000, 2000,
+ 3000, 4000, id1));
+ EXPECT_EQ(id1, subnet->getID());
+}
+
+TEST(Subnet6Test, inRange) {
Subnet6 subnet(IOAddress("2001:db8:1::"), 64, 1000, 2000, 3000, 4000);
EXPECT_EQ(1000, subnet.getT1());
More information about the bind10-changes
mailing list