BIND 10 master, updated. 9b7cc4afda911d762394c8e432fc429d027a106c [master] Merge branch 'trac3171' (DHCPv6-PD support in Allocation Engine)
BIND 10 source code commits
bind10-changes at lists.isc.org
Thu Oct 3 16:35:18 UTC 2013
The branch, master has been updated
via 9b7cc4afda911d762394c8e432fc429d027a106c (commit)
via 7d1431b4c887f0c7ee1b26b9b82d3d3b8464b34f (commit)
via 15c8b6ac63fd8f81b085fec8a0fd6d22085ea898 (commit)
via 7ae935a62c0f2fb0638cfee0d53c6b1fd63dfceb (commit)
via a019cd162f1ad9584dcc67732ee545c6395bebb4 (commit)
via b48106123d817b95de69c2d58aeb24ef26a186e7 (commit)
via e09660860573d1b76c65a200d3682d3592406b67 (commit)
via c83724e334548f586781ee77813348c75c111836 (commit)
via 7509a8d1bc64d4f688f6746d195987e5e22d4933 (commit)
via cbda6551031656b6d03f7d5578d0389c562a4238 (commit)
via a282ac7153171ac4445c6b6eb2220937d097fd74 (commit)
via 8ed4c169acd688c7d9389991272c2e699a4dd8fc (commit)
via 3e08c03f168623554f4dac564cbfd4bc5160bf76 (commit)
via 4b7664ccfdf1640cbdd914ddd032989149a3f0ef (commit)
via e295438305b351d4959001113670c6455f4a0abb (commit)
from b825c117ad54e0503e5629d74dd86d8f41102d60 (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 9b7cc4afda911d762394c8e432fc429d027a106c
Merge: b825c11 7d1431b
Author: Tomek Mrugalski <tomasz at isc.org>
Date: Thu Oct 3 18:35:06 2013 +0200
[master] Merge branch 'trac3171' (DHCPv6-PD support in Allocation Engine)
Conflicts:
ChangeLog
-----------------------------------------------------------------------
Summary of changes:
ChangeLog | 5 +
src/bin/dhcp4/dhcp4_srv.cc | 10 +-
src/bin/dhcp4/tests/dhcp4_srv_unittest.cc | 18 +-
src/bin/dhcp6/dhcp6_srv.cc | 14 +-
src/bin/dhcp6/tests/dhcp6_srv_unittest.cc | 56 ++-
src/bin/dhcp6/tests/dhcp6_test_utils.h | 3 +-
src/bin/dhcp6/tests/hooks_unittest.cc | 12 +-
src/lib/dhcpsrv/alloc_engine.cc | 158 ++++--
src/lib/dhcpsrv/alloc_engine.h | 77 ++-
src/lib/dhcpsrv/lease.h | 2 +-
src/lib/dhcpsrv/libdhcpsrv.dox | 54 +-
src/lib/dhcpsrv/pool.cc | 18 +
src/lib/dhcpsrv/pool.h | 10 +
src/lib/dhcpsrv/subnet.cc | 64 ++-
src/lib/dhcpsrv/subnet.h | 47 +-
src/lib/dhcpsrv/tests/alloc_engine_unittest.cc | 626 +++++++++++++++++-------
src/lib/dhcpsrv/tests/pool_unittest.cc | 21 +-
src/lib/dhcpsrv/tests/subnet_unittest.cc | 24 +-
18 files changed, 860 insertions(+), 359 deletions(-)
-----------------------------------------------------------------------
diff --git a/ChangeLog b/ChangeLog
index 94951e2..0a2a652 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,8 @@
+685. [func] tomek
+ libdhcpsrv: Allocation Engine is now able to handle IPv6 prefixes.
+ This will be used in Prefix Delegation.
+ (Trac #3171, git 7d1431b4c887f0c7ee1b26b9b82d3d3b8464b34f)
+
684. [func] muks, vorner
API support to delete zone data has been added. With this,
DomainTree and RdataSet which form the central zone data
diff --git a/src/bin/dhcp4/dhcp4_srv.cc b/src/bin/dhcp4/dhcp4_srv.cc
index 7d13631..edd9af4 100644
--- a/src/bin/dhcp4/dhcp4_srv.cc
+++ b/src/bin/dhcp4/dhcp4_srv.cc
@@ -718,11 +718,11 @@ Dhcpv4Srv::assignLease(const Pkt4Ptr& question, Pkt4Ptr& answer) {
// be inserted into the LeaseMgr as well.
// @todo pass the actual FQDN data.
Lease4Ptr old_lease;
- Lease4Ptr lease = alloc_engine_->allocateAddress4(subnet, client_id, hwaddr,
- hint, false, false, "",
- fake_allocation,
- callout_handle,
- old_lease);
+ Lease4Ptr lease = alloc_engine_->allocateLease4(subnet, client_id, hwaddr,
+ hint, false, false, "",
+ fake_allocation,
+ callout_handle,
+ old_lease);
if (lease) {
// We have a lease! Let's set it in the packet and send it back to
diff --git a/src/bin/dhcp4/tests/dhcp4_srv_unittest.cc b/src/bin/dhcp4/tests/dhcp4_srv_unittest.cc
index 0abeb10..08961a2 100644
--- a/src/bin/dhcp4/tests/dhcp4_srv_unittest.cc
+++ b/src/bin/dhcp4/tests/dhcp4_srv_unittest.cc
@@ -390,7 +390,7 @@ public:
// Technically inPool implies inRange, but let's be on the safe
// side and check both.
EXPECT_TRUE(subnet->inRange(rsp->getYiaddr()));
- EXPECT_TRUE(subnet->inPool(rsp->getYiaddr()));
+ EXPECT_TRUE(subnet->inPool(Lease::TYPE_V4, rsp->getYiaddr()));
// Check lease time
OptionPtr opt = rsp->getOption(DHO_DHCP_LEASE_TIME);
@@ -1333,7 +1333,7 @@ TEST_F(Dhcpv4SrvTest, RenewBasic) {
OptionPtr clientid = generateClientId();
// Check that the address we are about to use is indeed in pool
- ASSERT_TRUE(subnet_->inPool(addr));
+ ASSERT_TRUE(subnet_->inPool(Lease::TYPE_V4, addr));
// let's create a lease and put it in the LeaseMgr
uint8_t hwaddr2[] = { 0, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe};
@@ -1444,7 +1444,7 @@ TEST_F(Dhcpv4SrvTest, ReleaseBasic) {
OptionPtr clientid = generateClientId();
// Check that the address we are about to use is indeed in pool
- ASSERT_TRUE(subnet_->inPool(addr));
+ ASSERT_TRUE(subnet_->inPool(Lease::TYPE_V4, addr));
// Let's create a lease and put it in the LeaseMgr
uint8_t mac_addr[] = { 0, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe};
@@ -1520,7 +1520,7 @@ TEST_F(Dhcpv4SrvTest, ReleaseReject) {
OptionPtr clientid = generateClientId();
// Check that the address we are about to use is indeed in pool
- ASSERT_TRUE(subnet_->inPool(addr));
+ ASSERT_TRUE(subnet_->inPool(Lease::TYPE_V4, addr));
// Let's create a RELEASE
// Generate client-id also duid_
@@ -2696,7 +2696,7 @@ TEST_F(HooksDhcpv4SrvTest, subnet4SelectChange) {
// Advertised address must belong to the second pool (in subnet's range,
// in dynamic pool)
EXPECT_TRUE((*subnets)[1]->inRange(addr));
- EXPECT_TRUE((*subnets)[1]->inPool(addr));
+ EXPECT_TRUE((*subnets)[1]->inPool(Lease::TYPE_V4, addr));
}
// This test verifies that incoming (positive) REQUEST/Renewing can be handled
@@ -2718,7 +2718,7 @@ TEST_F(HooksDhcpv4SrvTest, lease4RenewSimple) {
OptionPtr clientid = generateClientId();
// Check that the address we are about to use is indeed in pool
- ASSERT_TRUE(subnet_->inPool(addr));
+ ASSERT_TRUE(subnet_->inPool(Lease::TYPE_V4, addr));
// let's create a lease and put it in the LeaseMgr
uint8_t hwaddr2[] = { 0, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe};
@@ -2802,7 +2802,7 @@ TEST_F(HooksDhcpv4SrvTest, lease4RenewSkip) {
OptionPtr clientid = generateClientId();
// Check that the address we are about to use is indeed in pool
- ASSERT_TRUE(subnet_->inPool(addr));
+ ASSERT_TRUE(subnet_->inPool(Lease::TYPE_V4, addr));
// let's create a lease and put it in the LeaseMgr
uint8_t hwaddr2[] = { 0, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe};
@@ -2866,7 +2866,7 @@ TEST_F(HooksDhcpv4SrvTest, lease4ReleaseSimple) {
OptionPtr clientid = generateClientId();
// Check that the address we are about to use is indeed in pool
- ASSERT_TRUE(subnet_->inPool(addr));
+ ASSERT_TRUE(subnet_->inPool(Lease::TYPE_V4, addr));
// Let's create a lease and put it in the LeaseMgr
uint8_t mac_addr[] = { 0, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe};
@@ -2951,7 +2951,7 @@ TEST_F(HooksDhcpv4SrvTest, lease4ReleaseSkip) {
OptionPtr clientid = generateClientId();
// Check that the address we are about to use is indeed in pool
- ASSERT_TRUE(subnet_->inPool(addr));
+ ASSERT_TRUE(subnet_->inPool(Lease::TYPE_V4, addr));
// Let's create a lease and put it in the LeaseMgr
uint8_t mac_addr[] = { 0, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe};
diff --git a/src/bin/dhcp6/dhcp6_srv.cc b/src/bin/dhcp6/dhcp6_srv.cc
index 2da5c8b..a584c81 100644
--- a/src/bin/dhcp6/dhcp6_srv.cc
+++ b/src/bin/dhcp6/dhcp6_srv.cc
@@ -1223,13 +1223,13 @@ Dhcpv6Srv::assignIA_NA(const Subnet6Ptr& subnet, const DuidPtr& duid,
// will try to honour the hint, but it is just a hint - some other address
// may be used instead. If fake_allocation is set to false, the lease will
// be inserted into the LeaseMgr as well.
- Lease6Collection leases = alloc_engine_->allocateAddress6(subnet, duid,
- ia->getIAID(),
- hint, Lease::TYPE_NA,
- do_fwd, do_rev,
- hostname,
- fake_allocation,
- callout_handle);
+ Lease6Collection leases = alloc_engine_->allocateLeases6(subnet, duid,
+ ia->getIAID(),
+ hint, Lease::TYPE_NA,
+ do_fwd, do_rev,
+ hostname,
+ fake_allocation,
+ callout_handle);
/// @todo: Handle more than one lease
Lease6Ptr lease;
if (!leases.empty()) {
diff --git a/src/bin/dhcp6/tests/dhcp6_srv_unittest.cc b/src/bin/dhcp6/tests/dhcp6_srv_unittest.cc
index 3869d2b..607b70b 100644
--- a/src/bin/dhcp6/tests/dhcp6_srv_unittest.cc
+++ b/src/bin/dhcp6/tests/dhcp6_srv_unittest.cc
@@ -265,7 +265,7 @@ public:
// Check that we have got the address we requested.
checkIAAddr(addr, IOAddress("2001:db8:1:1::dead:beef"),
- subnet_->getPreferred(),
+ Lease::TYPE_NA, subnet_->getPreferred(),
subnet_->getValid());
if (msg_type != DHCPV6_SOLICIT) {
@@ -663,7 +663,8 @@ TEST_F(Dhcpv6SrvTest, SolicitBasic) {
ASSERT_TRUE(addr);
// Check that the assigned address is indeed from the configured pool
- checkIAAddr(addr, addr->getAddress(), subnet_->getPreferred(), subnet_->getValid());
+ checkIAAddr(addr, addr->getAddress(), Lease::TYPE_NA, subnet_->getPreferred(),
+ subnet_->getValid());
// check DUIDs
checkServerId(reply, srv.getServerID());
@@ -695,7 +696,7 @@ TEST_F(Dhcpv6SrvTest, SolicitHint) {
// with a valid hint
IOAddress hint("2001:db8:1:1::dead:beef");
- ASSERT_TRUE(subnet_->inPool(hint));
+ ASSERT_TRUE(subnet_->inPool(Lease::TYPE_NA, hint));
OptionPtr hint_opt(new Option6IAAddr(D6O_IAADDR, hint, 300, 500));
ia->addOption(hint_opt);
sol->addOption(ia);
@@ -717,7 +718,8 @@ TEST_F(Dhcpv6SrvTest, SolicitHint) {
ASSERT_TRUE(addr);
// check that we've got the address we requested
- checkIAAddr(addr, hint, subnet_->getPreferred(), subnet_->getValid());
+ checkIAAddr(addr, hint, Lease::TYPE_NA, subnet_->getPreferred(),
+ subnet_->getValid());
// check DUIDs
checkServerId(reply, srv.getServerID());
@@ -747,7 +749,7 @@ TEST_F(Dhcpv6SrvTest, SolicitInvalidHint) {
sol->setRemoteAddr(IOAddress("fe80::abcd"));
boost::shared_ptr<Option6IA> ia = generateIA(234, 1500, 3000);
IOAddress hint("2001:db8:1::cafe:babe");
- ASSERT_FALSE(subnet_->inPool(hint));
+ ASSERT_FALSE(subnet_->inPool(Lease::TYPE_NA, hint));
OptionPtr hint_opt(new Option6IAAddr(D6O_IAADDR, hint, 300, 500));
ia->addOption(hint_opt);
sol->addOption(ia);
@@ -766,8 +768,9 @@ TEST_F(Dhcpv6SrvTest, SolicitInvalidHint) {
ASSERT_TRUE(addr);
// Check that the assigned address is indeed from the configured pool
- checkIAAddr(addr, addr->getAddress(), subnet_->getPreferred(), subnet_->getValid());
- EXPECT_TRUE(subnet_->inPool(addr->getAddress()));
+ checkIAAddr(addr, addr->getAddress(), Lease::TYPE_NA, subnet_->getPreferred(),
+ subnet_->getValid());
+ EXPECT_TRUE(subnet_->inPool(Lease::TYPE_NA, addr->getAddress()));
// check DUIDs
checkServerId(reply, srv.getServerID());
@@ -830,9 +833,12 @@ TEST_F(Dhcpv6SrvTest, ManySolicits) {
ASSERT_TRUE(addr3);
// Check that the assigned address is indeed from the configured pool
- checkIAAddr(addr1, addr1->getAddress(), subnet_->getPreferred(), subnet_->getValid());
- checkIAAddr(addr2, addr2->getAddress(), subnet_->getPreferred(), subnet_->getValid());
- checkIAAddr(addr3, addr3->getAddress(), subnet_->getPreferred(), subnet_->getValid());
+ checkIAAddr(addr1, addr1->getAddress(), Lease::TYPE_NA,
+ subnet_->getPreferred(), subnet_->getValid());
+ checkIAAddr(addr2, addr2->getAddress(), Lease::TYPE_NA,
+ subnet_->getPreferred(), subnet_->getValid());
+ checkIAAddr(addr3, addr3->getAddress(), Lease::TYPE_NA,
+ subnet_->getPreferred(), subnet_->getValid());
// check DUIDs
checkServerId(reply1, srv.getServerID());
@@ -876,7 +882,7 @@ TEST_F(Dhcpv6SrvTest, RequestBasic) {
// with a valid hint
IOAddress hint("2001:db8:1:1::dead:beef");
- ASSERT_TRUE(subnet_->inPool(hint));
+ ASSERT_TRUE(subnet_->inPool(Lease::TYPE_NA, hint));
OptionPtr hint_opt(new Option6IAAddr(D6O_IAADDR, hint, 300, 500));
ia->addOption(hint_opt);
req->addOption(ia);
@@ -896,12 +902,14 @@ TEST_F(Dhcpv6SrvTest, RequestBasic) {
ASSERT_TRUE(tmp);
// check that IA_NA was returned and that there's an address included
- boost::shared_ptr<Option6IAAddr> addr = checkIA_NA(reply, 234, subnet_->getT1(),
- subnet_->getT2());
+ boost::shared_ptr<Option6IAAddr> addr = checkIA_NA(reply, 234,
+ subnet_->getT1(),
+ subnet_->getT2());
ASSERT_TRUE(addr);
// check that we've got the address we requested
- checkIAAddr(addr, hint, subnet_->getPreferred(), subnet_->getValid());
+ checkIAAddr(addr, hint, Lease::TYPE_NA, subnet_->getPreferred(),
+ subnet_->getValid());
// check DUIDs
checkServerId(reply, srv.getServerID());
@@ -974,9 +982,12 @@ TEST_F(Dhcpv6SrvTest, ManyRequests) {
ASSERT_TRUE(addr3);
// Check that the assigned address is indeed from the configured pool
- checkIAAddr(addr1, addr1->getAddress(), subnet_->getPreferred(), subnet_->getValid());
- checkIAAddr(addr2, addr2->getAddress(), subnet_->getPreferred(), subnet_->getValid());
- checkIAAddr(addr3, addr3->getAddress(), subnet_->getPreferred(), subnet_->getValid());
+ checkIAAddr(addr1, addr1->getAddress(), Lease::TYPE_NA,
+ subnet_->getPreferred(), subnet_->getValid());
+ checkIAAddr(addr2, addr2->getAddress(), Lease::TYPE_NA,
+ subnet_->getPreferred(), subnet_->getValid());
+ checkIAAddr(addr3, addr3->getAddress(), Lease::TYPE_NA,
+ subnet_->getPreferred(), subnet_->getValid());
// check DUIDs
checkServerId(reply1, srv.getServerID());
@@ -1014,7 +1025,7 @@ TEST_F(Dhcpv6SrvTest, RenewBasic) {
OptionPtr clientid = generateClientId();
// Check that the address we are about to use is indeed in pool
- ASSERT_TRUE(subnet_->inPool(addr));
+ ASSERT_TRUE(subnet_->inPool(Lease::TYPE_NA, addr));
// Note that preferred, valid, T1 and T2 timers and CLTT are set to invalid
// value on purpose. They should be updated during RENEW.
@@ -1065,7 +1076,8 @@ TEST_F(Dhcpv6SrvTest, RenewBasic) {
ASSERT_TRUE(addr_opt);
// Check that we've got the address we requested
- checkIAAddr(addr_opt, addr, subnet_->getPreferred(), subnet_->getValid());
+ checkIAAddr(addr_opt, addr, Lease::TYPE_NA, subnet_->getPreferred(),
+ subnet_->getValid());
// Check DUIDs
checkServerId(reply, srv.getServerID());
@@ -1111,7 +1123,7 @@ TEST_F(Dhcpv6SrvTest, RenewReject) {
const uint32_t bogus_iaid = 456;
// Quick sanity check that the address we're about to use is ok
- ASSERT_TRUE(subnet_->inPool(addr));
+ ASSERT_TRUE(subnet_->inPool(Lease::TYPE_NA, addr));
// GenerateClientId() also sets duid_
OptionPtr clientid = generateClientId();
@@ -1218,7 +1230,7 @@ TEST_F(Dhcpv6SrvTest, ReleaseBasic) {
OptionPtr clientid = generateClientId();
// Check that the address we are about to use is indeed in pool
- ASSERT_TRUE(subnet_->inPool(addr));
+ ASSERT_TRUE(subnet_->inPool(Lease::TYPE_NA, addr));
// Note that preferred, valid, T1 and T2 timers and CLTT are set to invalid
// value on purpose. They should be updated during RENEW.
@@ -1299,7 +1311,7 @@ TEST_F(Dhcpv6SrvTest, ReleaseReject) {
const uint32_t bogus_iaid = 456;
// Quick sanity check that the address we're about to use is ok
- ASSERT_TRUE(subnet_->inPool(addr));
+ ASSERT_TRUE(subnet_->inPool(Lease::TYPE_NA, addr));
// GenerateClientId() also sets duid_
OptionPtr clientid = generateClientId();
diff --git a/src/bin/dhcp6/tests/dhcp6_test_utils.h b/src/bin/dhcp6/tests/dhcp6_test_utils.h
index 0e5ad7c..eb40d71 100644
--- a/src/bin/dhcp6/tests/dhcp6_test_utils.h
+++ b/src/bin/dhcp6/tests/dhcp6_test_utils.h
@@ -358,6 +358,7 @@ public:
// and lifetime values match the configured subnet
void checkIAAddr(const boost::shared_ptr<Option6IAAddr>& addr,
const IOAddress& expected_addr,
+ Lease::Type type,
uint32_t /* expected_preferred */,
uint32_t /* expected_valid */) {
@@ -365,7 +366,7 @@ public:
// Note that when comparing addresses, we compare the textual
// representation. IOAddress does not support being streamed to
// an ostream, which means it can't be used in EXPECT_EQ.
- EXPECT_TRUE(subnet_->inPool(addr->getAddress()));
+ EXPECT_TRUE(subnet_->inPool(type, addr->getAddress()));
EXPECT_EQ(expected_addr.toText(), addr->getAddress().toText());
EXPECT_EQ(addr->getPreferred(), subnet_->getPreferred());
EXPECT_EQ(addr->getValid(), subnet_->getValid());
diff --git a/src/bin/dhcp6/tests/hooks_unittest.cc b/src/bin/dhcp6/tests/hooks_unittest.cc
index 767560f..a9df50f 100644
--- a/src/bin/dhcp6/tests/hooks_unittest.cc
+++ b/src/bin/dhcp6/tests/hooks_unittest.cc
@@ -1047,7 +1047,7 @@ TEST_F(HooksDhcpv6SrvTest, subnet_select_change) {
// Advertised address must belong to the second pool (in subnet's range,
// in dynamic pool)
EXPECT_TRUE((*subnets)[1]->inRange(addr_opt->getAddress()));
- EXPECT_TRUE((*subnets)[1]->inPool(addr_opt->getAddress()));
+ EXPECT_TRUE((*subnets)[1]->inPool(Lease::TYPE_NA, addr_opt->getAddress()));
}
// This test verifies that incoming (positive) RENEW can be handled properly,
@@ -1066,7 +1066,7 @@ TEST_F(HooksDhcpv6SrvTest, basic_lease6_renew) {
OptionPtr clientid = generateClientId();
// Check that the address we are about to use is indeed in pool
- ASSERT_TRUE(subnet_->inPool(addr));
+ ASSERT_TRUE(subnet_->inPool(Lease::TYPE_NA, addr));
// Note that preferred, valid, T1 and T2 timers and CLTT are set to invalid
// value on purpose. They should be updated during RENEW.
@@ -1163,7 +1163,7 @@ TEST_F(HooksDhcpv6SrvTest, leaseUpdate_lease6_renew) {
OptionPtr clientid = generateClientId();
// Check that the address we are about to use is indeed in pool
- ASSERT_TRUE(subnet_->inPool(addr));
+ ASSERT_TRUE(subnet_->inPool(Lease::TYPE_NA, addr));
// Note that preferred, valid, T1 and T2 timers and CLTT are set to invalid
// value on purpose. They should be updated during RENEW.
@@ -1254,7 +1254,7 @@ TEST_F(HooksDhcpv6SrvTest, skip_lease6_renew) {
OptionPtr clientid = generateClientId();
// Check that the address we are about to use is indeed in pool
- ASSERT_TRUE(subnet_->inPool(addr));
+ ASSERT_TRUE(subnet_->inPool(Lease::TYPE_NA, addr));
// Note that preferred, valid, T1 and T2 timers and CLTT are set to invalid
// value on purpose. They should be updated during RENEW.
@@ -1330,7 +1330,7 @@ TEST_F(HooksDhcpv6SrvTest, basic_lease6_release) {
OptionPtr clientid = generateClientId();
// Check that the address we are about to use is indeed in pool
- ASSERT_TRUE(subnet_->inPool(addr));
+ ASSERT_TRUE(subnet_->inPool(Lease::TYPE_NA, addr));
// Note that preferred, valid, T1 and T2 timers and CLTT are set to invalid
// value on purpose. They should be updated during RENEW.
@@ -1411,7 +1411,7 @@ TEST_F(HooksDhcpv6SrvTest, skip_lease6_release) {
OptionPtr clientid = generateClientId();
// Check that the address we are about to use is indeed in pool
- ASSERT_TRUE(subnet_->inPool(addr));
+ ASSERT_TRUE(subnet_->inPool(Lease::TYPE_NA, addr));
// Note that preferred, valid, T1 and T2 timers and CLTT are set to invalid
// value on purpose. They should be updated during RENEW.
diff --git a/src/lib/dhcpsrv/alloc_engine.cc b/src/lib/dhcpsrv/alloc_engine.cc
index 2f41a85..dd1481e 100644
--- a/src/lib/dhcpsrv/alloc_engine.cc
+++ b/src/lib/dhcpsrv/alloc_engine.cc
@@ -85,12 +85,71 @@ AllocEngine::IterativeAllocator::increaseAddress(const isc::asiolink::IOAddress&
return (IOAddress::fromBytes(addr.getFamily(), packed));
}
+isc::asiolink::IOAddress
+AllocEngine::IterativeAllocator::increasePrefix(const isc::asiolink::IOAddress& prefix,
+ const uint8_t prefix_len) {
+ if (!prefix.isV6()) {
+ isc_throw(BadValue, "Prefix operations are for IPv6 only (attempted to "
+ "increase prefix " << prefix.toText() << ")");
+ }
+
+ // Get a buffer holding an address.
+ const std::vector<uint8_t>& vec = prefix.toBytes();
+
+ if (prefix_len < 1 || prefix_len > 128) {
+ isc_throw(BadValue, "Cannot increase prefix: invalid prefix length: "
+ << prefix_len);
+ }
+
+ // Brief explanation what happens here:
+ // http://www.youtube.com/watch?v=NFQCYpIHLNQ
+
+ uint8_t n_bytes = (prefix_len - 1)/8;
+ uint8_t n_bits = 8 - (prefix_len - n_bytes*8);
+ uint8_t mask = 1 << n_bits;
+
+ // Longer explanation: n_bytes specifies number of full bytes that are
+ // in-prefix. They can also be used as an offset for the first byte that
+ // is not in prefix. n_bits specifies number of bits on the last byte that
+ // is (often partially) in prefix. For example for a /125 prefix, the values
+ // are 15 and 3, respectively. Mask is a bitmask that has the least
+ // significant bit from the prefix set.
+
+ uint8_t packed[V6ADDRESS_LEN];
+
+ // Copy the address. It must be V6, but we already checked that.
+ std::memcpy(packed, &vec[0], V6ADDRESS_LEN);
+
+ // Can we safely increase only the last byte in prefix without overflow?
+ if (packed[n_bytes] + uint16_t(mask) < 256u) {
+ packed[n_bytes] += mask;
+ return (IOAddress::fromBytes(AF_INET6, packed));
+ }
+
+ // Overflow (done on uint8_t, but the sum is greater than 255)
+ packed[n_bytes] += mask;
+
+ // Deal with the overflow. Start increasing the least significant byte
+ for (int i = n_bytes - 1; i >= 0; --i) {
+ ++packed[i];
+ // If we haven't overflowed (0xff->0x0) the next byte, then we are done
+ if (packed[i] != 0) {
+ break;
+ }
+ }
+
+ return (IOAddress::fromBytes(AF_INET6, packed));
+}
+
isc::asiolink::IOAddress
AllocEngine::IterativeAllocator::pickAddress(const SubnetPtr& subnet,
const DuidPtr&,
const IOAddress&) {
+ // Is this prefix allocation?
+ bool prefix = pool_type_ == Lease::TYPE_PD;
+
// Let's get the last allocated address. It is usually set correctly,
// but there are times when it won't be (like after removing a pool or
// perhaps restarting the server).
@@ -123,7 +182,19 @@ AllocEngine::IterativeAllocator::pickAddress(const SubnetPtr& subnet,
// Ok, we have a pool that the last address belonged to, let's use it.
- IOAddress next = increaseAddress(last); // basically addr++
+ IOAddress next("::");
+ if (!prefix) {
+ next = increaseAddress(last); // basically addr++
+ } else {
+ Pool6Ptr pool6 = boost::dynamic_pointer_cast<Pool6>(*it);
+ if (!pool6) {
+ // Something is gravely wrong here
+ isc_throw(Unexpected, "Wrong type of pool: " << (*it)->toText()
+ << " is not Pool6");
+ }
+ // Get the next prefix
+ next = increasePrefix(last, pool6->getLength());
+ }
if ((*it)->inRange(next)) {
// the next one is in the pool as well, so we haven't hit pool boundary yet
subnet->setLastAllocated(pool_type_, next);
@@ -222,16 +293,12 @@ AllocEngine::AllocEngine(AllocType engine_type, unsigned int attempts,
}
Lease6Collection
-AllocEngine::allocateAddress6(const Subnet6Ptr& subnet,
- const DuidPtr& duid,
- uint32_t iaid,
- const IOAddress& hint,
- Lease::Type type,
- const bool fwd_dns_update,
- const bool rev_dns_update,
- const std::string& hostname,
- bool fake_allocation,
- const isc::hooks::CalloutHandlePtr& callout_handle) {
+AllocEngine::allocateLeases6(const Subnet6Ptr& subnet, const DuidPtr& duid,
+ uint32_t iaid, const IOAddress& hint,
+ Lease::Type type, const bool fwd_dns_update,
+ const bool rev_dns_update,
+ const std::string& hostname, bool fake_allocation,
+ const isc::hooks::CalloutHandlePtr& callout_handle) {
try {
AllocatorPtr allocator = getAllocator(type);
@@ -261,8 +328,10 @@ AllocEngine::allocateAddress6(const Subnet6Ptr& subnet,
}
// check if the hint is in pool and is available
- if (subnet->inPool(hint)) {
+ // This is equivalent of subnet->inPool(hint), but returns the pool
+ Pool6Ptr pool = boost::dynamic_pointer_cast<Pool6>(subnet->getPool(type, hint, false));
+ if (pool) {
/// @todo: We support only one hint for now
Lease6Ptr lease = LeaseMgrFactory::instance().getLease6(type, hint);
if (!lease) {
@@ -270,10 +339,9 @@ AllocEngine::allocateAddress6(const Subnet6Ptr& subnet,
/// implemented
// the hint is valid and not currently used, let's create a lease for it
- /// @todo: We support only one lease per ia for now
- lease = createLease6(subnet, duid, iaid, hint, type, fwd_dns_update,
- rev_dns_update, hostname, callout_handle,
- fake_allocation);
+ lease = createLease6(subnet, duid, iaid, hint, pool->getLength(),
+ type, fwd_dns_update, rev_dns_update,
+ hostname, callout_handle, fake_allocation);
// It can happen that the lease allocation failed (we could have lost
// the race condition. That means that the hint is lo longer usable and
@@ -288,6 +356,7 @@ AllocEngine::allocateAddress6(const Subnet6Ptr& subnet,
if (lease->expired()) {
/// We found a lease and it is expired, so we can reuse it
lease = reuseExpiredLease(lease, subnet, duid, iaid,
+ pool->getLength(),
fwd_dns_update, rev_dns_update,
hostname, callout_handle,
fake_allocation);
@@ -324,13 +393,24 @@ AllocEngine::allocateAddress6(const Subnet6Ptr& subnet,
/// @todo: check if the address is reserved once we have host support
/// implemented
+ // The first step is to find out prefix length. It is 128 for
+ // non-PD leases.
+ uint8_t prefix_len = 128;
+ if (type == Lease::TYPE_PD) {
+ Pool6Ptr pool = boost::dynamic_pointer_cast<Pool6>(
+ subnet->getPool(type, candidate, false));
+ prefix_len = pool->getLength();
+ }
+
Lease6Ptr existing = LeaseMgrFactory::instance().getLease6(type,
candidate);
if (!existing) {
+
// there's no existing lease for selected candidate, so it is
// free. Let's allocate it.
+
Lease6Ptr lease = createLease6(subnet, duid, iaid, candidate,
- type, fwd_dns_update,
+ prefix_len, type, fwd_dns_update,
rev_dns_update, hostname,
callout_handle, fake_allocation);
if (lease) {
@@ -345,9 +425,9 @@ AllocEngine::allocateAddress6(const Subnet6Ptr& subnet,
} else {
if (existing->expired()) {
existing = reuseExpiredLease(existing, subnet, duid, iaid,
- fwd_dns_update, rev_dns_update,
- hostname, callout_handle,
- fake_allocation);
+ prefix_len, fwd_dns_update,
+ rev_dns_update, hostname,
+ callout_handle, fake_allocation);
Lease6Collection collection;
collection.push_back(existing);
return (collection);
@@ -372,16 +452,12 @@ AllocEngine::allocateAddress6(const Subnet6Ptr& subnet,
}
Lease4Ptr
-AllocEngine::allocateAddress4(const SubnetPtr& subnet,
- const ClientIdPtr& clientid,
- const HWAddrPtr& hwaddr,
- const IOAddress& hint,
- const bool fwd_dns_update,
- const bool rev_dns_update,
- const std::string& hostname,
- bool fake_allocation,
- const isc::hooks::CalloutHandlePtr& callout_handle,
- Lease4Ptr& old_lease) {
+AllocEngine::allocateLease4(const SubnetPtr& subnet, const ClientIdPtr& clientid,
+ const HWAddrPtr& hwaddr, const IOAddress& hint,
+ const bool fwd_dns_update, const bool rev_dns_update,
+ const std::string& hostname, bool fake_allocation,
+ const isc::hooks::CalloutHandlePtr& callout_handle,
+ Lease4Ptr& old_lease) {
// The NULL pointer indicates that the old lease didn't exist. It may
// be later set to non NULL value if existing lease is found in the
@@ -444,7 +520,7 @@ AllocEngine::allocateAddress4(const SubnetPtr& subnet,
}
// check if the hint is in pool and is available
- if (subnet->inPool(hint)) {
+ if (subnet->inPool(Lease::TYPE_V4, hint)) {
existing = LeaseMgrFactory::instance().getLease4(hint);
if (!existing) {
/// @todo: Check if the hint is reserved once we have host support
@@ -620,7 +696,8 @@ Lease4Ptr AllocEngine::renewLease4(const SubnetPtr& subnet,
Lease6Ptr AllocEngine::reuseExpiredLease(Lease6Ptr& expired,
const Subnet6Ptr& subnet,
const DuidPtr& duid,
- uint32_t iaid,
+ const uint32_t iaid,
+ uint8_t prefix_len,
const bool fwd_dns_update,
const bool rev_dns_update,
const std::string& hostname,
@@ -631,6 +708,10 @@ Lease6Ptr AllocEngine::reuseExpiredLease(Lease6Ptr& expired,
isc_throw(BadValue, "Attempt to recycle lease that is still valid");
}
+ if (expired->type_ != Lease::TYPE_PD) {
+ prefix_len = 128; // non-PD lease types must be always /128
+ }
+
// address, lease type and prefixlen (0) stay the same
expired->iaid_ = iaid;
expired->duid_ = duid;
@@ -644,6 +725,7 @@ Lease6Ptr AllocEngine::reuseExpiredLease(Lease6Ptr& expired,
expired->hostname_ = hostname;
expired->fqdn_fwd_ = fwd_dns_update;
expired->fqdn_rev_ = rev_dns_update;
+ expired->prefixlen_ = prefix_len;
/// @todo: log here that the lease was reused (there's ticket #2524 for
/// logging in libdhcpsrv)
@@ -777,18 +859,24 @@ Lease4Ptr AllocEngine::reuseExpiredLease(Lease4Ptr& expired,
Lease6Ptr AllocEngine::createLease6(const Subnet6Ptr& subnet,
const DuidPtr& duid,
- uint32_t iaid,
+ const uint32_t iaid,
const IOAddress& addr,
- Lease::Type type,
+ uint8_t prefix_len,
+ const Lease::Type type,
const bool fwd_dns_update,
const bool rev_dns_update,
const std::string& hostname,
const isc::hooks::CalloutHandlePtr& callout_handle,
bool fake_allocation /*= false */ ) {
+ if (type != Lease::TYPE_PD) {
+ prefix_len = 128; // non-PD lease types must be always /128
+ }
+
Lease6Ptr lease(new Lease6(type, addr, duid, iaid,
subnet->getPreferred(), subnet->getValid(),
- subnet->getT1(), subnet->getT2(), subnet->getID()));
+ subnet->getT1(), subnet->getT2(), subnet->getID(),
+ prefix_len));
lease->fqdn_fwd_ = fwd_dns_update;
lease->fqdn_rev_ = rev_dns_update;
diff --git a/src/lib/dhcpsrv/alloc_engine.h b/src/lib/dhcpsrv/alloc_engine.h
index faf9c55..8299bb8 100644
--- a/src/lib/dhcpsrv/alloc_engine.h
+++ b/src/lib/dhcpsrv/alloc_engine.h
@@ -70,6 +70,14 @@ protected:
/// again if necessary. The number of times this method is called will
/// increase as the number of available leases will decrease.
///
+ /// This method can also be used to pick a prefix. We should not rename
+ /// it to pickLease(), because at this early stage there is no concept
+ /// of a lease yet. Here it is a matter of selecting one address or
+ /// prefix from the defined pool, without going into details who it is
+ /// for or who uses it. I thought that pickAddress() is less confusing
+ /// than pickResource(), because nobody would immediately know what the
+ /// resource means in this context.
+ ///
/// @param subnet next address will be returned from pool of that subnet
/// @param duid Client's DUID
/// @param hint client's hint
@@ -124,13 +132,31 @@ protected:
pickAddress(const SubnetPtr& subnet,
const DuidPtr& duid,
const isc::asiolink::IOAddress& hint);
- private:
+ protected:
- /// @brief returns an address by one
+ /// @brief Returns an address increased by one
+ ///
+ /// This method works for both IPv4 and IPv6 addresses. For example,
+ /// increase 192.0.2.255 will become 192.0.3.0.
+ ///
/// @param addr address to be increased
/// @return address increased by one
- isc::asiolink::IOAddress increaseAddress(const isc::asiolink::IOAddress& addr);
+ static isc::asiolink::IOAddress
+ increaseAddress(const isc::asiolink::IOAddress& addr);
+ /// @brief Returns the next prefix
+ ///
+ /// This method works for IPv6 addresses only. It increases
+ /// specified prefix by a given prefix_len. For example, 2001:db8::
+ /// increased by prefix length /32 will become 2001:db9::. This method
+ /// is used to iterate over IPv6 prefix pools
+ ///
+ /// @param prefix prefix to be increased
+ /// @param prefix_len length of the prefix to be increased
+ /// @return result prefix
+ static isc::asiolink::IOAddress
+ increasePrefix(const isc::asiolink::IOAddress& prefix,
+ const uint8_t prefix_len);
};
/// @brief Address/prefix allocator that gets an address based on a hash
@@ -249,16 +275,13 @@ protected:
///
/// @return Allocated IPv4 lease (or NULL if allocation failed)
Lease4Ptr
- allocateAddress4(const SubnetPtr& subnet,
- const ClientIdPtr& clientid,
- const HWAddrPtr& hwaddr,
- const isc::asiolink::IOAddress& hint,
- const bool fwd_dns_update,
- const bool rev_dns_update,
- const std::string& hostname,
- bool fake_allocation,
- const isc::hooks::CalloutHandlePtr& callout_handle,
- Lease4Ptr& old_lease);
+ allocateLease4(const SubnetPtr& subnet, const ClientIdPtr& clientid,
+ const HWAddrPtr& hwaddr,
+ const isc::asiolink::IOAddress& hint,
+ const bool fwd_dns_update, const bool rev_dns_update,
+ const std::string& hostname, bool fake_allocation,
+ const isc::hooks::CalloutHandlePtr& callout_handle,
+ Lease4Ptr& old_lease);
/// @brief Renews a IPv4 lease
///
@@ -318,16 +341,11 @@ protected:
///
/// @return Allocated IPv6 leases (may be empty if allocation failed)
Lease6Collection
- allocateAddress6(const Subnet6Ptr& subnet,
- const DuidPtr& duid,
- uint32_t iaid,
- const isc::asiolink::IOAddress& hint,
- Lease::Type type,
- const bool fwd_dns_update,
- const bool rev_dns_update,
- const std::string& hostname,
- bool fake_allocation,
- const isc::hooks::CalloutHandlePtr& callout_handle);
+ allocateLeases6(const Subnet6Ptr& subnet, const DuidPtr& duid, uint32_t iaid,
+ const isc::asiolink::IOAddress& hint, Lease::Type type,
+ const bool fwd_dns_update, const bool rev_dns_update,
+ const std::string& hostname, bool fake_allocation,
+ const isc::hooks::CalloutHandlePtr& callout_handle);
/// @brief returns allocator for a given pool type
/// @param type type of pool (V4, IA, TA or PD)
@@ -381,6 +399,8 @@ private:
/// @param iaid IAID from the IA_NA container the client sent to us
/// @param addr an address that was selected and is confirmed to be
/// available
+ /// @param prefix_len length of the prefix (for PD only)
+ /// should be 128 for other lease types
/// @param type lease type (IA, TA or PD)
/// @param fwd_dns_update A boolean value which indicates that server takes
/// responsibility for the forward DNS Update for this lease
@@ -397,9 +417,9 @@ private:
/// @return allocated lease (or NULL in the unlikely case of the lease just
/// became unavailable)
Lease6Ptr createLease6(const Subnet6Ptr& subnet, const DuidPtr& duid,
- uint32_t iaid, const isc::asiolink::IOAddress& addr,
- Lease::Type type, const bool fwd_dns_update,
- const bool rev_dns_update,
+ const uint32_t iaid, const isc::asiolink::IOAddress& addr,
+ const uint8_t prefix_len, const Lease::Type type,
+ const bool fwd_dns_update, const bool rev_dns_update,
const std::string& hostname,
const isc::hooks::CalloutHandlePtr& callout_handle,
bool fake_allocation = false);
@@ -445,6 +465,8 @@ private:
/// @param subnet subnet the lease is allocated from
/// @param duid client's DUID
/// @param iaid IAID from the IA_NA container the client sent to us
+ /// @param prefix_len prefix length (for PD leases)
+ /// Should be 128 for other lease types
/// @param fwd_dns_update A boolean value which indicates that server takes
/// responsibility for the forward DNS Update for this lease
/// (if true).
@@ -459,7 +481,8 @@ private:
/// @return refreshed lease
/// @throw BadValue if trying to recycle lease that is still valid
Lease6Ptr reuseExpiredLease(Lease6Ptr& expired, const Subnet6Ptr& subnet,
- const DuidPtr& duid, uint32_t iaid,
+ const DuidPtr& duid, const uint32_t iaid,
+ uint8_t prefix_len,
const bool fwd_dns_update,
const bool rev_dns_update,
const std::string& hostname,
diff --git a/src/lib/dhcpsrv/lease.h b/src/lib/dhcpsrv/lease.h
index b6efa8d..496f38a 100644
--- a/src/lib/dhcpsrv/lease.h
+++ b/src/lib/dhcpsrv/lease.h
@@ -289,7 +289,7 @@ struct Lease6 : public Lease {
/// @param prefixlen An address prefix length.
Lease6(Type type, const isc::asiolink::IOAddress& addr, DuidPtr duid,
uint32_t iaid, uint32_t preferred, uint32_t valid, uint32_t t1,
- uint32_t t2, SubnetID subnet_id, uint8_t prefixlen = 0);
+ uint32_t t2, SubnetID subnet_id, uint8_t prefixlen = 128);
/// @brief Constructor, including FQDN data.
///
diff --git a/src/lib/dhcpsrv/libdhcpsrv.dox b/src/lib/dhcpsrv/libdhcpsrv.dox
index e3d3429..d56029a 100644
--- a/src/lib/dhcpsrv/libdhcpsrv.dox
+++ b/src/lib/dhcpsrv/libdhcpsrv.dox
@@ -61,19 +61,21 @@ separate module, called allocator. Its sole purpose is to pick an address from
a pool. Allocation engine will then check if the picked address is free and if
it is not, then will ask allocator to pick again.
-At lease 3 allocators will be implemented:
-
-- Iterative - it iterates over all addresses in available pools, one
-by one. The advantages of this approach are speed (typically it only needs to
-increase last address), the guarantee to cover all addresses and predictability.
-This allocator behaves very good in case of nearing depletion. Even when pools
-are almost completely allocated, it still will be able to allocate outstanding
-leases efficiently. Predictability can also be considered a serious flaw in
-some environments, as prediction of the next address is trivial and can be
-leveraged by an attacker. Another drawback of this allocator is that it does
-not attempt to give the same address to returning clients (clients that released
-or expired their leases and are requesting a new lease will likely to get a
-different lease). This allocator is implemented in \ref isc::dhcp::AllocEngine::IterativeAllocator.
+At least 3 allocators will be implemented:
+
+- Iterative - it iterates over all resources (addresses or prefixes) in
+available pools, one by one. The advantages of this approach are: speed
+(typically it only needs to increase address just one), the guarantee to cover
+all addresses and predictability. This allocator behaves reasonably good in
+case of nearing depletion. Even when pools are almost completely allocated, it
+still will be able to allocate outstanding leases efficiently. Predictability
+can also be considered a serious flaw in some environments, as prediction of the
+next address is trivial and can be leveraged by an attacker. Another drawback of
+this allocator is that it does not attempt to give the same address to returning
+clients (clients that released or expired their leases and are requesting a new
+lease will likely to get a different lease). This allocator is not suitable for
+temporary addresses, which must be randomized. This allocator is implemented
+in \ref isc::dhcp::AllocEngine::IterativeAllocator.
- Hashed - ISC-DHCP uses hash of the client-id or DUID to determine, which
address is tried first. If that address is not available, the result is hashed
@@ -81,13 +83,13 @@ again. That procedure is repeated until available address is found or there
are no more addresses left. The benefit of that approach is that it provides
a relative lease stability, so returning old clients are likely to get the same
address again. The drawbacks are increased computation cost, as each iteration
-requires use of a hashing function. That is especially difficult when the
+requires use of a hashing function. That is especially difficult when the
pools are almost depleted. It also may be difficult to guarantee that the
repeated hashing will iterate over all available addresses in all pools. Flawed
hash algorithm can go into cycles that iterate over only part of the addresses.
It is difficult to detect such issues as only some initial seed (client-id
or DUID) values may trigger short cycles. This allocator is currently not
-implemented.
+implemented. This will be the only allocator allowed for temporary addresses.
- Random - Another possible approach to address selection is randomization. This
allocator can pick an address randomly from the configured pool. The benefit
@@ -97,4 +99,26 @@ returning clients are almost guaranteed to get a different address. Another
drawback is that with almost depleted pools it is increasingly difficult to
"guess" an address that is free. This allocator is currently not implemented.
+ at subsection allocEngineTypes Different lease types support
+
+Allocation Engine has been extended to support different types of leases. Four
+types are supported: TYPE_V4 (IPv4 addresses), TYPE_NA (normal IPv6 addresses),
+TYPE_TA (temporary IPv6 addresses) and TYPE_PD (delegated prefixes). Support for
+TYPE_TA is partial. Some routines are able to handle it, while other are
+not. The major missing piece is the RandomAllocator, so there is no way to randomly
+generate an address. This defeats the purpose of using temporary addresses for now.
+
+ at subsection allocEnginePD Prefix Delegation support in AllocEngine
+
+The Allocation Engine supports allocation of the IPv6 addresses and prefixes.
+For a prefix pool, the iterative allocator "walks over"
+every available pool. It is similar to how it iterates over address pool,
+but instead of increasing address by just one, it walks over the whole delegated
+prefix length in one step. This is implemented in
+isc::dhcp::AllocEngine::IterativeAllocator::increasePrefix(). Functionally the
+increaseAddress(addr) call is equivalent to increasePrefix(addr, 128)
+(increasing by a /128 prefix, i.e. a single address). However, both methods are
+kept, because increaseAddress() is faster and this is a routine that may be
+called many hundred thousands times per second.
+
*/
diff --git a/src/lib/dhcpsrv/pool.cc b/src/lib/dhcpsrv/pool.cc
index 53c4d09..f1ba871 100644
--- a/src/lib/dhcpsrv/pool.cc
+++ b/src/lib/dhcpsrv/pool.cc
@@ -31,6 +31,14 @@ bool Pool::inRange(const isc::asiolink::IOAddress& addr) const {
return (first_.smallerEqual(addr) && addr.smallerEqual(last_));
}
+std::string
+Pool::toText() const {
+ std::stringstream tmp;
+ tmp << "type=" << Lease::typeToText(type_) << ", " << first_.toText()
+ << "-" << last_.toText();
+ return (tmp.str());
+}
+
Pool4::Pool4(const isc::asiolink::IOAddress& first,
const isc::asiolink::IOAddress& last)
:Pool(Lease::TYPE_V4, first, last) {
@@ -132,5 +140,15 @@ Pool6::Pool6(Lease::Type type, const isc::asiolink::IOAddress& prefix,
last_ = lastAddrInPrefix(prefix, prefix_len);
}
+std::string
+Pool6::toText() const {
+ std::stringstream tmp;
+ tmp << "type=" << Lease::typeToText(type_) << ", " << first_.toText()
+ << "-" << last_.toText() << ", delegated_len="
+ << static_cast<int>(prefix_len_);
+ return (tmp.str());
+}
+
+
}; // end of isc::dhcp namespace
}; // end of isc namespace
diff --git a/src/lib/dhcpsrv/pool.h b/src/lib/dhcpsrv/pool.h
index 0d73b40..ae8cb58 100644
--- a/src/lib/dhcpsrv/pool.h
+++ b/src/lib/dhcpsrv/pool.h
@@ -66,6 +66,11 @@ public:
return (type_);
}
+ /// @brief returns textual representation of the pool
+ ///
+ /// @return textual representation
+ virtual std::string toText() const;
+
/// @brief virtual destructor
///
/// We need Pool to be a polymorphic class, so we could dynamic cast
@@ -204,6 +209,11 @@ public:
return (prefix_len_);
}
+ /// @brief returns textual representation of the pool
+ ///
+ /// @return textual representation
+ virtual std::string toText() const;
+
private:
/// @brief Defines prefix length (for TYPE_PD only)
uint8_t prefix_len_;
diff --git a/src/lib/dhcpsrv/subnet.cc b/src/lib/dhcpsrv/subnet.cc
index 5704fa9..4320733 100644
--- a/src/lib/dhcpsrv/subnet.cc
+++ b/src/lib/dhcpsrv/subnet.cc
@@ -164,38 +164,42 @@ const PoolCollection& Subnet::getPools(Lease::Type type) const {
case Lease::TYPE_PD:
return (pools_pd_);
default:
- isc_throw(BadValue, "Unsupported pool type: " << type);
+ isc_throw(BadValue, "Unsupported pool type: "
+ << static_cast<int>(type));
}
}
-PoolPtr Subnet::getPool(Lease::Type type, isc::asiolink::IOAddress hint) {
+PoolCollection& Subnet::getPoolsWritable(Lease::Type type) {
// check if the type is valid (and throw if it isn't)
checkType(type);
- PoolCollection* pools = NULL;
-
switch (type) {
case Lease::TYPE_V4:
case Lease::TYPE_NA:
- pools = &pools_;
- break;
+ return (pools_);
case Lease::TYPE_TA:
- pools = &pools_ta_;
- break;
+ return (pools_ta_);
case Lease::TYPE_PD:
- pools = &pools_pd_;
- break;
+ return (pools_pd_);
default:
- isc_throw(BadValue, "Failed to select pools. Unknown pool type: "
- << type);
+ isc_throw(BadValue, "Invalid pool type specified: "
+ << static_cast<int>(type));
}
+}
+
+const PoolPtr Subnet::getPool(Lease::Type type, const isc::asiolink::IOAddress& hint,
+ bool anypool /* true */) const {
+ // check if the type is valid (and throw if it isn't)
+ checkType(type);
+
+ const PoolCollection& pools = getPools(type);
PoolPtr candidate;
- for (PoolCollection::const_iterator pool = pools->begin();
- pool != pools->end(); ++pool) {
+ for (PoolCollection::const_iterator pool = pools.begin();
+ pool != pools.end(); ++pool) {
// if we won't find anything better, then let's just use the first pool
- if (!candidate) {
+ if (anypool && !candidate) {
candidate = *pool;
}
@@ -225,21 +229,13 @@ Subnet::addPool(const PoolPtr& pool) {
// check if the type is valid (and throw if it isn't)
checkType(pool->getType());
- switch (pool->getType()) {
- case Lease::TYPE_V4:
- case Lease::TYPE_NA:
- pools_.push_back(pool);
- return;
- case Lease::TYPE_TA:
- pools_ta_.push_back(pool);
- return;
- case Lease::TYPE_PD:
- pools_pd_.push_back(pool);
- return;
- default:
- isc_throw(BadValue, "Invalid pool type specified: "
- << static_cast<int>(pool->getType()));
- }
+ // Add the pool to the appropriate pools collection
+ getPoolsWritable(pool->getType()).push_back(pool);
+}
+
+void
+Subnet::delPools(Lease::Type type) {
+ getPoolsWritable(type).clear();
}
void
@@ -264,15 +260,17 @@ Subnet4::validateOption(const OptionPtr& option) const {
}
bool
-Subnet::inPool(const isc::asiolink::IOAddress& addr) const {
+Subnet::inPool(Lease::Type type, const isc::asiolink::IOAddress& addr) const {
// Let's start with checking if it even belongs to that subnet.
if (!inRange(addr)) {
return (false);
}
- for (PoolCollection::const_iterator pool = pools_.begin();
- pool != pools_.end(); ++pool) {
+ const PoolCollection& pools = getPools(type);
+
+ for (PoolCollection::const_iterator pool = pools.begin();
+ pool != pools.end(); ++pool) {
if ((*pool)->inRange(addr)) {
return (true);
}
diff --git a/src/lib/dhcpsrv/subnet.h b/src/lib/dhcpsrv/subnet.h
index 923e3d1..ac6de03 100644
--- a/src/lib/dhcpsrv/subnet.h
+++ b/src/lib/dhcpsrv/subnet.h
@@ -192,22 +192,23 @@ public:
/// is not always true. For the given example, 2001::1234:abcd would return
/// true for inSubnet(), but false for inPool() check.
///
+ /// @param type type of pools to iterate over
/// @param addr this address will be checked if it belongs to any pools in
/// that subnet
/// @return true if the address is in any of the pools
- bool inPool(const isc::asiolink::IOAddress& addr) const;
+ bool inPool(Lease::Type type, const isc::asiolink::IOAddress& addr) const;
- /// @brief return valid-lifetime for addresses in that prefix
+ /// @brief Return valid-lifetime for addresses in that prefix
Triplet<uint32_t> getValid() const {
return (valid_);
}
- /// @brief returns T1 (renew timer), expressed in seconds
+ /// @brief Returns T1 (renew timer), expressed in seconds
Triplet<uint32_t> getT1() const {
return (t1_);
}
- /// @brief returns T2 (rebind timer), expressed in seconds
+ /// @brief Returns T2 (rebind timer), expressed in seconds
Triplet<uint32_t> getT2() const {
return (t2_);
}
@@ -257,11 +258,11 @@ public:
void setLastAllocated(Lease::Type type,
const isc::asiolink::IOAddress& addr);
- /// @brief returns unique ID for that subnet
+ /// @brief Returns unique ID for that subnet
/// @return unique ID for that subnet
SubnetID getID() const { return (id_); }
- /// @brief returns subnet parameters (prefix and prefix length)
+ /// @brief Returns subnet parameters (prefix and prefix length)
///
/// @return (prefix, prefix length) pair
std::pair<isc::asiolink::IOAddress, uint8_t> get() const {
@@ -272,15 +273,29 @@ public:
/// @param pool pool to be added
void addPool(const PoolPtr& pool);
+
+ /// @brief Deletes all pools of specified type
+ ///
+ /// This method is used for testing purposes only
+ /// @param type type of pools to be deleted
+ void delPools(Lease::Type type);
+
/// @brief Returns a pool that specified address belongs to
///
/// If there is no pool that the address belongs to (hint is invalid), other
/// pool of specified type will be returned.
///
+ /// With anypool set to true, this is means give me a pool, preferably
+ /// the one that addr belongs to. With anypool set to false, it means
+ /// give me a pool that addr belongs to (or NULL if here is no such pool)
+ ///
/// @param type pool type that the pool is looked for
/// @param addr address that the returned pool should cover (optional)
+ /// @param anypool other pool may be returned as well, not only the one
+ /// that addr belongs to
/// @return found pool (or NULL)
- PoolPtr getPool(Lease::Type type, isc::asiolink::IOAddress addr);
+ const PoolPtr getPool(Lease::Type type, const isc::asiolink::IOAddress& addr,
+ bool anypool = true) const;
/// @brief Returns a pool without any address specified
///
@@ -296,7 +311,7 @@ public:
/// and 0.0.0.0 for Subnet4)
virtual isc::asiolink::IOAddress default_pool() const = 0;
- /// @brief returns all pools
+ /// @brief Returns all pools (const variant)
///
/// The reference is only valid as long as the object that returned it.
///
@@ -304,24 +319,32 @@ public:
/// @return a collection of all pools
const PoolCollection& getPools(Lease::Type type) const;
- /// @brief sets name of the network interface for directly attached networks
+ /// @brief Sets name of the network interface for directly attached networks
///
/// @param iface_name name of the interface
void setIface(const std::string& iface_name);
- /// @brief network interface name used to reach subnet (or "" for remote
+ /// @brief Network interface name used to reach subnet (or "" for remote
/// subnets)
/// @return network interface name for directly attached subnets or ""
std::string getIface() const;
- /// @brief returns textual representation of the subnet (e.g.
+ /// @brief Returns textual representation of the subnet (e.g.
/// "2001:db8::/64")
///
/// @return textual representation
virtual std::string toText() const;
protected:
- /// @brief protected constructor
+ /// @brief Returns all pools (non-const variant)
+ ///
+ /// The reference is only valid as long as the object that returned it.
+ ///
+ /// @param type lease type to be set
+ /// @return a collection of all pools
+ PoolCollection& getPoolsWritable(Lease::Type type);
+
+ /// @brief Protected constructor
//
/// By making the constructor protected, we make sure that noone will
/// ever instantiate that class. Pool4 and Pool6 should be used instead.
diff --git a/src/lib/dhcpsrv/tests/alloc_engine_unittest.cc b/src/lib/dhcpsrv/tests/alloc_engine_unittest.cc
index 3141f05..fda8d59 100644
--- a/src/lib/dhcpsrv/tests/alloc_engine_unittest.cc
+++ b/src/lib/dhcpsrv/tests/alloc_engine_unittest.cc
@@ -65,6 +65,20 @@ public:
using AllocEngine::Allocator;
using AllocEngine::IterativeAllocator;
using AllocEngine::getAllocator;
+
+ /// @brief IterativeAllocator with internal methods exposed
+ class NakedIterativeAllocator: public AllocEngine::IterativeAllocator {
+ public:
+
+ /// @brief constructor
+ /// @param type pool types that will be interated
+ NakedIterativeAllocator(Lease::Type type)
+ :IterativeAllocator(type) {
+ }
+
+ using AllocEngine::IterativeAllocator::increaseAddress;
+ using AllocEngine::IterativeAllocator::increasePrefix;
+ };
};
/// @brief Used in Allocation Engine tests for IPv6
@@ -83,10 +97,16 @@ public:
// instantiate cfg_mgr
CfgMgr& cfg_mgr = CfgMgr::instance();
+ // Configure normal address pool
subnet_ = Subnet6Ptr(new Subnet6(IOAddress("2001:db8:1::"), 56, 1, 2, 3, 4));
pool_ = Pool6Ptr(new Pool6(Lease::TYPE_NA, IOAddress("2001:db8:1::10"),
IOAddress("2001:db8:1::20")));
subnet_->addPool(pool_);
+
+ // Configure PD pool
+ pd_pool_ = Pool6Ptr(new Pool6(Lease::TYPE_PD, IOAddress("2001:db8:1::"), 56, 64));
+ subnet_->addPool(pd_pool_);
+
cfg_mgr.addSubnet6(subnet_);
factory_.create("type=memfile");
@@ -113,24 +133,216 @@ public:
/// @brief checks if Lease6 matches expected configuration
///
/// @param lease lease to be checked
- void checkLease6(const Lease6Ptr& lease) {
+ /// @param exp_type expected lease type
+ /// @param exp_pd_len expected prefix length
+ void checkLease6(const Lease6Ptr& lease, Lease::Type exp_type,
+ uint8_t exp_pd_len = 128) {
+
// that is belongs to the right subnet
EXPECT_EQ(lease->subnet_id_, subnet_->getID());
EXPECT_TRUE(subnet_->inRange(lease->addr_));
- EXPECT_TRUE(subnet_->inPool(lease->addr_));
+ EXPECT_TRUE(subnet_->inPool(exp_type, lease->addr_));
// that it have proper parameters
+ EXPECT_EQ(exp_type, lease->type_);
EXPECT_EQ(iaid_, lease->iaid_);
EXPECT_EQ(subnet_->getValid(), lease->valid_lft_);
EXPECT_EQ(subnet_->getPreferred(), lease->preferred_lft_);
EXPECT_EQ(subnet_->getT1(), lease->t1_);
EXPECT_EQ(subnet_->getT2(), lease->t2_);
- EXPECT_EQ(0, lease->prefixlen_); // this is IA_NA, not IA_PD
+ EXPECT_EQ(exp_pd_len, lease->prefixlen_);
EXPECT_TRUE(false == lease->fqdn_fwd_);
EXPECT_TRUE(false == lease->fqdn_rev_);
EXPECT_TRUE(*lease->duid_ == *duid_);
// @todo: check cltt
- }
+ }
+
+ /// @brief Checks if specified address is increased properly
+ ///
+ /// Method uses gtest macros to mark check failure.
+ ///
+ /// @param alloc IterativeAllocator that is tested
+ /// @param input address to be increased
+ /// @param exp_output expected address after increase
+ void
+ checkAddrIncrease(NakedAllocEngine::NakedIterativeAllocator& alloc,
+ std::string input, std::string exp_output) {
+ EXPECT_EQ(exp_output, alloc.increaseAddress(IOAddress(input)).toText());
+ }
+
+ /// @brief Checks if increasePrefix() works as expected
+ ///
+ /// Method uses gtest macros to mark check failure.
+ ///
+ /// @param alloc allocator to be tested
+ /// @param input IPv6 prefix (as a string)
+ /// @param prefix_len prefix len
+ /// @param exp_output expected output (string)
+ void
+ checkPrefixIncrease(NakedAllocEngine::NakedIterativeAllocator& alloc,
+ std::string input, uint8_t prefix_len,
+ std::string exp_output) {
+ EXPECT_EQ(exp_output, alloc.increasePrefix(IOAddress(input), prefix_len)
+ .toText());
+ }
+
+ /// @brief Checks if the simple allocation can succeed
+ ///
+ /// The type of lease is determined by pool type (pool->getType()
+ ///
+ /// @param pool pool from which the lease will be allocated from
+ /// @param hint address to be used as a hint
+ /// @param fake true - this is fake allocation (SOLICIT)
+ /// @return allocated lease (or NULL)
+ Lease6Ptr simpleAlloc6Test(const Pool6Ptr& pool, const IOAddress& hint,
+ bool fake) {
+ Lease::Type type = pool->getType();
+ uint8_t expected_len = pool->getLength();
+
+ boost::scoped_ptr<AllocEngine> engine;
+ EXPECT_NO_THROW(engine.reset(new AllocEngine(AllocEngine::ALLOC_ITERATIVE,
+ 100)));
+ // We can't use ASSERT macros in non-void methods
+ EXPECT_TRUE(engine);
+ if (!engine) {
+ return (Lease6Ptr());
+ }
+
+ Lease6Ptr lease;
+ EXPECT_NO_THROW(lease = expectOneLease(engine->allocateLeases6(subnet_,
+ duid_, iaid_, hint, type, false, false,
+ "", fake, CalloutHandlePtr())));
+
+ // Check that we got a lease
+ EXPECT_TRUE(lease);
+ if (!lease) {
+ return (Lease6Ptr());
+ }
+
+ // Do all checks on the lease
+ checkLease6(lease, type, expected_len);
+
+ // Check that the lease is indeed in LeaseMgr
+ Lease6Ptr from_mgr = LeaseMgrFactory::instance().getLease6(type,
+ lease->addr_);
+ if (!fake) {
+ // This is a real (REQUEST) allocation, the lease must be in the DB
+ EXPECT_TRUE(from_mgr);
+ if (!from_mgr) {
+ return (Lease6Ptr());
+ }
+
+ // Now check that the lease in LeaseMgr has the same parameters
+ detailCompareLease(lease, from_mgr);
+ } else {
+ // This is a fake (SOLICIT) allocation, the lease must not be in DB
+ EXPECT_FALSE(from_mgr);
+ if (from_mgr) {
+ return (Lease6Ptr());
+ }
+ }
+
+ return (lease);
+ }
+
+ /// @brief Checks if the address allocation with a hint that is in range,
+ /// in pool, but is currently used, can succeed
+ ///
+ /// Method uses gtest macros to mark check failure.
+ ///
+ /// @param type lease type
+ /// @param used_addr address should be preallocated (simulates prior
+ /// allocation by some other user)
+ /// @param requested address requested by the client
+ /// @param expected_pd_len expected PD len (128 for addresses)
+ void allocWithUsedHintTest(Lease::Type type, IOAddress used_addr,
+ IOAddress requested, uint8_t expected_pd_len) {
+ boost::scoped_ptr<AllocEngine> engine;
+ ASSERT_NO_THROW(engine.reset(new AllocEngine(AllocEngine::ALLOC_ITERATIVE,
+ 100)));
+ ASSERT_TRUE(engine);
+
+ // Let's create a lease and put it in the LeaseMgr
+ DuidPtr duid2 = boost::shared_ptr<DUID>(new DUID(vector<uint8_t>(8, 0xff)));
+ time_t now = time(NULL);
+ Lease6Ptr used(new Lease6(type, used_addr,
+ duid2, 1, 2, 3, 4, now, subnet_->getID()));
+ ASSERT_TRUE(LeaseMgrFactory::instance().addLease(used));
+
+ // Another client comes in and request an address that is in pool, but
+ // unfortunately it is used already. The same address must not be allocated
+ // twice.
+ Lease6Ptr lease;
+ EXPECT_NO_THROW(lease = expectOneLease(engine->allocateLeases6(subnet_,
+ duid_, iaid_, requested, type, false, false, "", false,
+ CalloutHandlePtr())));
+
+ // Check that we got a lease
+ ASSERT_TRUE(lease);
+
+ // Allocated address must be different
+ EXPECT_NE(used_addr.toText(), lease->addr_.toText());
+
+ // We should NOT get what we asked for, because it is used already
+ EXPECT_NE(requested.toText(), lease->addr_.toText());
+
+ // Do all checks on the lease
+ checkLease6(lease, type, expected_pd_len);
+
+ // Check that the lease is indeed in LeaseMgr
+ Lease6Ptr from_mgr = LeaseMgrFactory::instance().getLease6(lease->type_,
+ lease->addr_);
+ ASSERT_TRUE(from_mgr);
+
+ // Now check that the lease in LeaseMgr has the same parameters
+ detailCompareLease(lease, from_mgr);
+ }
+
+ /// @brief checks if bogus hint can be ignored and the allocation succeeds
+ ///
+ /// This test checks if the allocation with a hing that is out of the blue
+ /// can succeed. The invalid hint should be ingored completely.
+ ///
+ /// @param type Lease type
+ /// @param hint hint (as send by a client)
+ /// @param expectd_pd_len (used in validation)
+ void allocBogusHint6(Lease::Type type, IOAddress hint,
+ uint8_t expected_pd_len) {
+ boost::scoped_ptr<AllocEngine> engine;
+ ASSERT_NO_THROW(engine.reset(new AllocEngine(AllocEngine::ALLOC_ITERATIVE,
+ 100)));
+ ASSERT_TRUE(engine);
+
+ // Client would like to get a 3000::abc lease, which does not belong to any
+ // supported lease. Allocation engine should ignore it and carry on
+ // with the normal allocation
+ Lease6Ptr lease;
+ EXPECT_NO_THROW(lease = expectOneLease(engine->allocateLeases6(subnet_,
+ duid_, iaid_, hint, type, false,
+ false, "", false, CalloutHandlePtr())));
+
+ // Check that we got a lease
+ ASSERT_TRUE(lease);
+
+ // We should NOT get what we asked for, because it is used already
+ EXPECT_NE(hint.toText(), lease->addr_.toText());
+
+ // Do all checks on the lease
+ checkLease6(lease, type, expected_pd_len);
+
+ // Check that the lease is indeed in LeaseMgr
+ Lease6Ptr from_mgr = LeaseMgrFactory::instance().getLease6(lease->type_,
+ lease->addr_);
+ ASSERT_TRUE(from_mgr);
+
+ // Now check that the lease in LeaseMgr has the same parameters
+ detailCompareLease(lease, from_mgr);
+
+
+
+
+ }
+
virtual ~AllocEngine6Test() {
factory_.destroy();
@@ -139,7 +351,8 @@ public:
DuidPtr duid_; ///< client-identifier (value used in tests)
uint32_t iaid_; ///< IA identifier (value used in tests)
Subnet6Ptr subnet_; ///< subnet6 (used in tests)
- Pool6Ptr pool_; ///< pool belonging to subnet_
+ Pool6Ptr pool_; ///< NA pool belonging to subnet_
+ Pool6Ptr pd_pool_; ///< PD pool belonging to subnet_
LeaseMgrFactory factory_; ///< pointer to LeaseMgr factory
};
@@ -179,7 +392,7 @@ public:
// Check that is belongs to the right subnet
EXPECT_EQ(lease->subnet_id_, subnet_->getID());
EXPECT_TRUE(subnet_->inRange(lease->addr_));
- EXPECT_TRUE(subnet_->inPool(lease->addr_));
+ EXPECT_TRUE(subnet_->inPool(Lease::TYPE_V4, lease->addr_));
// Check that it has proper parameters
EXPECT_EQ(subnet_->getValid(), lease->valid_lft_);
@@ -234,160 +447,68 @@ TEST_F(AllocEngine6Test, constructor) {
EXPECT_THROW(x->getAllocator(Lease::TYPE_V4), BadValue);
}
-// This test checks if the simple allocation can succeed
+// This test checks if the simple allocation (REQUEST) can succeed
TEST_F(AllocEngine6Test, simpleAlloc6) {
- boost::scoped_ptr<AllocEngine> engine;
- ASSERT_NO_THROW(engine.reset(new AllocEngine(AllocEngine::ALLOC_ITERATIVE, 100)));
- ASSERT_TRUE(engine);
-
- Lease6Ptr lease;
- EXPECT_NO_THROW(lease = expectOneLease(engine->allocateAddress6(subnet_,
- duid_, iaid_, IOAddress("::"), Lease::TYPE_NA, false, false,
- "", false, CalloutHandlePtr())));
-
- // Check that we got a lease
- ASSERT_TRUE(lease);
-
- // Do all checks on the lease
- checkLease6(lease);
-
- // Check that the lease is indeed in LeaseMgr
- Lease6Ptr from_mgr = LeaseMgrFactory::instance().getLease6(lease->type_,
- lease->addr_);
- ASSERT_TRUE(from_mgr);
+ simpleAlloc6Test(pool_, IOAddress("::"), false);
+}
- // Now check that the lease in LeaseMgr has the same parameters
- detailCompareLease(lease, from_mgr);
+// This test checks if the simple PD allocation (REQUEST) can succeed
+TEST_F(AllocEngine6Test, pdSimpleAlloc6) {
+ simpleAlloc6Test(pd_pool_, IOAddress("::"), false);
}
// This test checks if the fake allocation (for SOLICIT) can succeed
TEST_F(AllocEngine6Test, fakeAlloc6) {
- boost::scoped_ptr<AllocEngine> engine;
- ASSERT_NO_THROW(engine.reset(new AllocEngine(AllocEngine::ALLOC_ITERATIVE, 100)));
- ASSERT_TRUE(engine);
-
- Lease6Ptr lease;
- EXPECT_NO_THROW(lease = expectOneLease(engine->allocateAddress6(subnet_,
- duid_, iaid_, IOAddress("::"), Lease::TYPE_NA, false, false,
- "", true, CalloutHandlePtr())));
-
- // Check that we got a lease
- ASSERT_TRUE(lease);
-
- // Do all checks on the lease
- checkLease6(lease);
- // Check that the lease is NOT in LeaseMgr
- Lease6Ptr from_mgr = LeaseMgrFactory::instance().getLease6(lease->type_,
- lease->addr_);
- ASSERT_FALSE(from_mgr);
+ simpleAlloc6Test(pool_, IOAddress("::"), true);
}
+// This test checks if the fake PD allocation (for SOLICIT) can succeed
+TEST_F(AllocEngine6Test, pdFakeAlloc6) {
+ simpleAlloc6Test(pd_pool_, IOAddress("::"), true);
+};
+
// This test checks if the allocation with a hint that is valid (in range,
// in pool and free) can succeed
TEST_F(AllocEngine6Test, allocWithValidHint6) {
- boost::scoped_ptr<AllocEngine> engine;
- ASSERT_NO_THROW(engine.reset(new AllocEngine(AllocEngine::ALLOC_ITERATIVE, 100)));
- ASSERT_TRUE(engine);
-
- Lease6Ptr lease;
- EXPECT_NO_THROW(lease = expectOneLease(engine->allocateAddress6(subnet_,
- duid_, iaid_, IOAddress("2001:db8:1::15"),
- Lease::TYPE_NA, false, false, "", false,
- CalloutHandlePtr())));
- // Check that we got a lease
- ASSERT_TRUE(lease);
+ Lease6Ptr lease = simpleAlloc6Test(pool_, IOAddress("2001:db8:1::15"),
+ false);
// We should get what we asked for
EXPECT_EQ(lease->addr_.toText(), "2001:db8:1::15");
-
- // Do all checks on the lease
- checkLease6(lease);
-
- // Check that the lease is indeed in LeaseMgr
- Lease6Ptr from_mgr = LeaseMgrFactory::instance().getLease6(lease->type_,
- lease->addr_);
- ASSERT_TRUE(from_mgr);
-
- // Now check that the lease in LeaseMgr has the same parameters
- detailCompareLease(lease, from_mgr);
}
-// This test checks if the allocation with a hint that is in range,
-// in pool, but is currently used) can succeed
+// This test checks if the address allocation with a hint that is in range,
+// in pool, but is currently used, can succeed
TEST_F(AllocEngine6Test, allocWithUsedHint6) {
- boost::scoped_ptr<AllocEngine> engine;
- ASSERT_NO_THROW(engine.reset(new AllocEngine(AllocEngine::ALLOC_ITERATIVE, 100)));
- ASSERT_TRUE(engine);
-
- // Let's create a lease and put it in the LeaseMgr
- DuidPtr duid2 = boost::shared_ptr<DUID>(new DUID(vector<uint8_t>(8, 0xff)));
- time_t now = time(NULL);
- Lease6Ptr used(new Lease6(Lease::TYPE_NA, IOAddress("2001:db8:1::1f"),
- duid2, 1, 2, 3, 4, now, subnet_->getID()));
- ASSERT_TRUE(LeaseMgrFactory::instance().addLease(used));
-
- // Another client comes in and request an address that is in pool, but
- // unfortunately it is used already. The same address must not be allocated
- // twice.
- Lease6Ptr lease;
- EXPECT_NO_THROW(lease = expectOneLease(engine->allocateAddress6(subnet_,
- duid_, iaid_, IOAddress("2001:db8:1::1f"), Lease::TYPE_NA,
- false, false, "", false, CalloutHandlePtr())));
-
- // Check that we got a lease
- ASSERT_TRUE(lease);
-
- // Allocated address must be different
- EXPECT_TRUE(used->addr_.toText() != lease->addr_.toText());
-
- // We should NOT get what we asked for, because it is used already
- EXPECT_TRUE(lease->addr_.toText() != "2001:db8:1::1f");
-
- // Do all checks on the lease
- checkLease6(lease);
-
- // Check that the lease is indeed in LeaseMgr
- Lease6Ptr from_mgr = LeaseMgrFactory::instance().getLease6(lease->type_,
- lease->addr_);
- ASSERT_TRUE(from_mgr);
+ allocWithUsedHintTest(Lease::TYPE_NA,
+ IOAddress("2001:db8:1::1f"), // allocate this as used
+ IOAddress("2001:db8:1::1f"), // request this addr
+ 128);
+}
- // Now check that the lease in LeaseMgr has the same parameters
- detailCompareLease(lease, from_mgr);
+// This test checks if the PD allocation with a hint that is in range,
+// in pool, but is currently used, can succeed
+TEST_F(AllocEngine6Test, pdAllocWithUsedHint6) {
+ allocWithUsedHintTest(Lease::TYPE_PD,
+ IOAddress("2001:db8:1::"), // allocate this prefix as used
+ IOAddress("2001:db8:1::"), // request this prefix
+ 64);
}
// This test checks if the allocation with a hint that is out the blue
// can succeed. The invalid hint should be ignored completely.
TEST_F(AllocEngine6Test, allocBogusHint6) {
- boost::scoped_ptr<AllocEngine> engine;
- ASSERT_NO_THROW(engine.reset(new AllocEngine(AllocEngine::ALLOC_ITERATIVE, 100)));
- ASSERT_TRUE(engine);
- // Client would like to get a 3000::abc lease, which does not belong to any
- // supported lease. Allocation engine should ignore it and carry on
- // with the normal allocation
- Lease6Ptr lease;
- EXPECT_NO_THROW(lease = expectOneLease(engine->allocateAddress6(subnet_,
- duid_, iaid_, IOAddress("3000::abc"), Lease::TYPE_NA, false,
- false, "", false, CalloutHandlePtr())));
-
- // Check that we got a lease
- ASSERT_TRUE(lease);
-
- // We should NOT get what we asked for, because it is used already
- EXPECT_TRUE(lease->addr_.toText() != "3000::abc");
-
- // Do all checks on the lease
- checkLease6(lease);
+ allocBogusHint6(Lease::TYPE_NA, IOAddress("3000::abc"), 128);
+}
- // Check that the lease is indeed in LeaseMgr
- Lease6Ptr from_mgr = LeaseMgrFactory::instance().getLease6(lease->type_,
- lease->addr_);
- ASSERT_TRUE(from_mgr);
+// This test checks if the allocation with a hint that is out the blue
+// can succeed. The invalid hint should be ignored completely.
+TEST_F(AllocEngine6Test, pdAllocBogusHint6) {
- // Now check that the lease in LeaseMgr has the same parameters
- detailCompareLease(lease, from_mgr);
+ allocBogusHint6(Lease::TYPE_PD, IOAddress("3000::abc"), 64);
}
// This test checks that NULL values are handled properly
@@ -398,13 +519,13 @@ TEST_F(AllocEngine6Test, allocateAddress6Nulls) {
// Allocations without subnet are not allowed
Lease6Ptr lease;
- EXPECT_NO_THROW(lease = expectOneLease(engine->allocateAddress6(
+ EXPECT_NO_THROW(lease = expectOneLease(engine->allocateLeases6(
Subnet6Ptr(), duid_, iaid_, IOAddress("::"), Lease::TYPE_NA,
false, false, "", false, CalloutHandlePtr())));
ASSERT_FALSE(lease);
// Allocations without DUID are not allowed either
- EXPECT_NO_THROW(lease = expectOneLease(engine->allocateAddress6(subnet_,
+ EXPECT_NO_THROW(lease = expectOneLease(engine->allocateLeases6(subnet_,
DuidPtr(), iaid_, IOAddress("::"), Lease::TYPE_NA, false,
false, "", false, CalloutHandlePtr())));
ASSERT_FALSE(lease);
@@ -419,10 +540,169 @@ TEST_F(AllocEngine6Test, IterativeAllocator) {
for (int i = 0; i < 1000; ++i) {
IOAddress candidate = alloc->pickAddress(subnet_, duid_, IOAddress("::"));
- EXPECT_TRUE(subnet_->inPool(candidate));
+ EXPECT_TRUE(subnet_->inPool(Lease::TYPE_NA, candidate));
+ }
+}
+
+TEST_F(AllocEngine6Test, IterativeAllocatorAddrStep) {
+ NakedAllocEngine::NakedIterativeAllocator alloc(Lease::TYPE_NA);
+
+ subnet_->delPools(Lease::TYPE_NA); // Get rid of default pool
+
+ Pool6Ptr pool1(new Pool6(Lease::TYPE_NA, IOAddress("2001:db8:1::1"),
+ IOAddress("2001:db8:1::5")));
+ Pool6Ptr pool2(new Pool6(Lease::TYPE_NA, IOAddress("2001:db8:1::100"),
+ IOAddress("2001:db8:1::100")));
+ Pool6Ptr pool3(new Pool6(Lease::TYPE_NA, IOAddress("2001:db8:1::105"),
+ IOAddress("2001:db8:1::106")));
+ subnet_->addPool(pool1);
+ subnet_->addPool(pool2);
+ subnet_->addPool(pool3);
+
+ // Let's check the first pool (5 addresses here)
+ EXPECT_EQ("2001:db8:1::1", alloc.pickAddress(subnet_, duid_, IOAddress("::")).toText());
+ EXPECT_EQ("2001:db8:1::2", alloc.pickAddress(subnet_, duid_, IOAddress("::")).toText());
+ EXPECT_EQ("2001:db8:1::3", alloc.pickAddress(subnet_, duid_, IOAddress("::")).toText());
+ EXPECT_EQ("2001:db8:1::4", alloc.pickAddress(subnet_, duid_, IOAddress("::")).toText());
+ EXPECT_EQ("2001:db8:1::5", alloc.pickAddress(subnet_, duid_, IOAddress("::")).toText());
+
+ // The second pool is easy - only one address here
+ EXPECT_EQ("2001:db8:1::100", alloc.pickAddress(subnet_, duid_, IOAddress("::")).toText());
+
+ // This is the third and last pool, with 2 addresses in it
+ EXPECT_EQ("2001:db8:1::105", alloc.pickAddress(subnet_, duid_, IOAddress("::")).toText());
+ EXPECT_EQ("2001:db8:1::106", alloc.pickAddress(subnet_, duid_, IOAddress("::")).toText());
+
+ // We iterated over all addresses and reached to the end of the last pool.
+ // Let's wrap around and start from the beginning
+ EXPECT_EQ("2001:db8:1::1", alloc.pickAddress(subnet_, duid_, IOAddress("::")).toText());
+ EXPECT_EQ("2001:db8:1::2", alloc.pickAddress(subnet_, duid_, IOAddress("::")).toText());
+}
+
+TEST_F(AllocEngine6Test, IterativeAllocatorPrefixStep) {
+ NakedAllocEngine::NakedIterativeAllocator alloc(Lease::TYPE_PD);
+
+ subnet_.reset(new Subnet6(IOAddress("2001:db8::"), 32, 1, 2, 3, 4));
+
+ Pool6Ptr pool1(new Pool6(Lease::TYPE_PD, IOAddress("2001:db8::"), 56, 60));
+ Pool6Ptr pool2(new Pool6(Lease::TYPE_PD, IOAddress("2001:db8:1::"), 48, 48));
+ Pool6Ptr pool3(new Pool6(Lease::TYPE_PD, IOAddress("2001:db8:2::"), 56, 64));
+ subnet_->addPool(pool1);
+ subnet_->addPool(pool2);
+ subnet_->addPool(pool3);
+
+ // We have a 2001:db8::/48 subnet that has 3 pools defined in it:
+ // 2001:db8::/56 split into /60 prefixes (16 leases) (or 2001:db8:0:X0::)
+ // 2001:db8:1::/48 split into a single /48 prefix (just 1 lease)
+ // 2001:db8:2::/56 split into /64 prefixes (256 leases) (or 2001:db8:2:XX::)
+
+ // First pool check (Let's check over all 16 leases)
+ EXPECT_EQ("2001:db8::", alloc.pickAddress(subnet_, duid_, IOAddress("::")).toText());
+ EXPECT_EQ("2001:db8:0:10::", alloc.pickAddress(subnet_, duid_, IOAddress("::")).toText());
+ EXPECT_EQ("2001:db8:0:20::", alloc.pickAddress(subnet_, duid_, IOAddress("::")).toText());
+ EXPECT_EQ("2001:db8:0:30::", alloc.pickAddress(subnet_, duid_, IOAddress("::")).toText());
+ EXPECT_EQ("2001:db8:0:40::", alloc.pickAddress(subnet_, duid_, IOAddress("::")).toText());
+ EXPECT_EQ("2001:db8:0:50::", alloc.pickAddress(subnet_, duid_, IOAddress("::")).toText());
+ EXPECT_EQ("2001:db8:0:60::", alloc.pickAddress(subnet_, duid_, IOAddress("::")).toText());
+ EXPECT_EQ("2001:db8:0:70::", alloc.pickAddress(subnet_, duid_, IOAddress("::")).toText());
+ EXPECT_EQ("2001:db8:0:80::", alloc.pickAddress(subnet_, duid_, IOAddress("::")).toText());
+ EXPECT_EQ("2001:db8:0:90::", alloc.pickAddress(subnet_, duid_, IOAddress("::")).toText());
+ EXPECT_EQ("2001:db8:0:a0::", alloc.pickAddress(subnet_, duid_, IOAddress("::")).toText());
+ EXPECT_EQ("2001:db8:0:b0::", alloc.pickAddress(subnet_, duid_, IOAddress("::")).toText());
+ EXPECT_EQ("2001:db8:0:c0::", alloc.pickAddress(subnet_, duid_, IOAddress("::")).toText());
+ EXPECT_EQ("2001:db8:0:d0::", alloc.pickAddress(subnet_, duid_, IOAddress("::")).toText());
+ EXPECT_EQ("2001:db8:0:e0::", alloc.pickAddress(subnet_, duid_, IOAddress("::")).toText());
+ EXPECT_EQ("2001:db8:0:f0::", alloc.pickAddress(subnet_, duid_, IOAddress("::")).toText());
+
+ // Second pool (just one lease here)
+ EXPECT_EQ("2001:db8:1::", alloc.pickAddress(subnet_, duid_, IOAddress("::")).toText());
+
+ // Third pool (256 leases, let's check first and last explictly and the
+ // rest over in a pool
+ EXPECT_EQ("2001:db8:2::", alloc.pickAddress(subnet_, duid_, IOAddress("::")).toText());
+ for (int i = 1; i < 255; i++) {
+ stringstream exp;
+ exp << "2001:db8:2:" << hex << i << dec << "::";
+ EXPECT_EQ(exp.str(), alloc.pickAddress(subnet_, duid_, IOAddress("::")).toText());
+
}
+ EXPECT_EQ("2001:db8:2:ff::", alloc.pickAddress(subnet_, duid_, IOAddress("::")).toText());
+
+ // Ok, we've iterated over all prefixes in all pools. We now wrap around.
+ // We're looping over now (iterating over first pool again)
+ EXPECT_EQ("2001:db8::", alloc.pickAddress(subnet_, duid_, IOAddress("::")).toText());
+ EXPECT_EQ("2001:db8:0:10::", alloc.pickAddress(subnet_, duid_, IOAddress("::")).toText());
+}
+
+// This test verifies that the iterative allocator can step over addresses
+TEST_F(AllocEngine6Test, IterativeAllocatorAddressIncrease) {
+ NakedAllocEngine::NakedIterativeAllocator alloc(Lease::TYPE_NA);
+
+ // Let's pick the first address
+ IOAddress addr1 = alloc.pickAddress(subnet_, duid_, IOAddress("2001:db8:1::10"));
+
+ // Check that we can indeed pick the first address from the pool
+ EXPECT_EQ("2001:db8:1::10", addr1.toText());
+
+ // Check that addresses can be increased properly
+ checkAddrIncrease(alloc, "2001:db8::9", "2001:db8::a");
+ checkAddrIncrease(alloc, "2001:db8::f", "2001:db8::10");
+ checkAddrIncrease(alloc, "2001:db8::10", "2001:db8::11");
+ checkAddrIncrease(alloc, "2001:db8::ff", "2001:db8::100");
+ checkAddrIncrease(alloc, "2001:db8::ffff", "2001:db8::1:0");
+ checkAddrIncrease(alloc, "::", "::1");
+ checkAddrIncrease(alloc, "ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff", "::");
}
+// This test verifies that the allocator can step over prefixes
+TEST_F(AllocEngine6Test, IterativeAllocatorPrefixIncrease) {
+ NakedAllocEngine::NakedIterativeAllocator alloc(Lease::TYPE_PD);
+
+ // For /128 prefix, increasePrefix should work the same as addressIncrease
+ checkPrefixIncrease(alloc, "2001:db8::9", 128, "2001:db8::a");
+ checkPrefixIncrease(alloc, "2001:db8::f", 128, "2001:db8::10");
+ checkPrefixIncrease(alloc, "2001:db8::10", 128, "2001:db8::11");
+ checkPrefixIncrease(alloc, "2001:db8::ff", 128, "2001:db8::100");
+ checkPrefixIncrease(alloc, "2001:db8::ffff", 128, "2001:db8::1:0");
+ checkPrefixIncrease(alloc, "::", 128, "::1");
+ checkPrefixIncrease(alloc, "ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff", 128, "::");
+
+ // Check that /64 prefixes can be generated
+ checkPrefixIncrease(alloc, "2001:db8::", 64, "2001:db8:0:1::");
+
+ // Check that prefix length not divisible by 8 are working
+ checkPrefixIncrease(alloc, "2001:db8::", 128, "2001:db8::1");
+ checkPrefixIncrease(alloc, "2001:db8::", 127, "2001:db8::2");
+ checkPrefixIncrease(alloc, "2001:db8::", 126, "2001:db8::4");
+ checkPrefixIncrease(alloc, "2001:db8::", 125, "2001:db8::8");
+ checkPrefixIncrease(alloc, "2001:db8::", 124, "2001:db8::10");
+ checkPrefixIncrease(alloc, "2001:db8::", 123, "2001:db8::20");
+ checkPrefixIncrease(alloc, "2001:db8::", 122, "2001:db8::40");
+ checkPrefixIncrease(alloc, "2001:db8::", 121, "2001:db8::80");
+ checkPrefixIncrease(alloc, "2001:db8::", 120, "2001:db8::100");
+
+ // These are not really useful cases, because there are bits set
+ // int the last (128 - prefix_len) bits. Nevertheless, it shows
+ // that the algorithm is working even in such cases
+ checkPrefixIncrease(alloc, "2001:db8::1", 128, "2001:db8::2");
+ checkPrefixIncrease(alloc, "2001:db8::1", 127, "2001:db8::3");
+ checkPrefixIncrease(alloc, "2001:db8::1", 126, "2001:db8::5");
+ checkPrefixIncrease(alloc, "2001:db8::1", 125, "2001:db8::9");
+ checkPrefixIncrease(alloc, "2001:db8::1", 124, "2001:db8::11");
+ checkPrefixIncrease(alloc, "2001:db8::1", 123, "2001:db8::21");
+ checkPrefixIncrease(alloc, "2001:db8::1", 122, "2001:db8::41");
+ checkPrefixIncrease(alloc, "2001:db8::1", 121, "2001:db8::81");
+ checkPrefixIncrease(alloc, "2001:db8::1", 120, "2001:db8::101");
+
+ // Let's try out couple real life scenarios
+ checkPrefixIncrease(alloc, "2001:db8:1:abcd::", 64, "2001:db8:1:abce::");
+ checkPrefixIncrease(alloc, "2001:db8:1:abcd::", 60, "2001:db8:1:abdd::");
+ checkPrefixIncrease(alloc, "2001:db8:1:abcd::", 56, "2001:db8:1:accd::");
+ checkPrefixIncrease(alloc, "2001:db8:1:abcd::", 52, "2001:db8:1:bbcd::");
+
+ // And now let's try something over the top
+ checkPrefixIncrease(alloc, "::", 1, "8000::");
+}
// This test verifies that the iterative allocator really walks over all addresses
// in all pools in specified subnet. It also must not pick the same address twice
@@ -450,11 +730,11 @@ TEST_F(AllocEngine6Test, IterativeAllocator_manyPools6) {
int cnt = 0;
while (++cnt) {
IOAddress candidate = alloc.pickAddress(subnet_, duid_, IOAddress("::"));
- EXPECT_TRUE(subnet_->inPool(candidate));
+ EXPECT_TRUE(subnet_->inPool(Lease::TYPE_NA, candidate));
// One way to easily verify that the iterative allocator really works is
// to uncomment the following line and observe its output that it
- // covers all defined subnets.
+ // covers all defined pools.
// cout << candidate.toText() << endl;
if (generated_addrs.find(candidate) == generated_addrs.end()) {
@@ -495,7 +775,7 @@ TEST_F(AllocEngine6Test, smallPool6) {
cfg_mgr.addSubnet6(subnet_);
Lease6Ptr lease;
- EXPECT_NO_THROW(lease = expectOneLease(engine->allocateAddress6(subnet_,
+ EXPECT_NO_THROW(lease = expectOneLease(engine->allocateLeases6(subnet_,
duid_, iaid_, IOAddress("::"), Lease::TYPE_NA, false, false,
"", false, CalloutHandlePtr())));
@@ -505,7 +785,7 @@ TEST_F(AllocEngine6Test, smallPool6) {
EXPECT_EQ("2001:db8:1::ad", lease->addr_.toText());
// Do all checks on the lease
- checkLease6(lease);
+ checkLease6(lease, Lease::TYPE_NA, 128);
// Check that the lease is indeed in LeaseMgr
Lease6Ptr from_mgr = LeaseMgrFactory::instance().getLease6(lease->type_,
@@ -544,7 +824,7 @@ TEST_F(AllocEngine6Test, outOfAddresses6) {
// There is just a single address in the pool and allocated it to someone
// else, so the allocation should fail
Lease6Ptr lease2;
- EXPECT_NO_THROW(lease2 = expectOneLease(engine->allocateAddress6(subnet_,
+ EXPECT_NO_THROW(lease2 = expectOneLease(engine->allocateLeases6(subnet_,
duid_, iaid_, IOAddress("::"), Lease::TYPE_NA, false, false,
"", false, CalloutHandlePtr())));
EXPECT_FALSE(lease2);
@@ -579,7 +859,7 @@ TEST_F(AllocEngine6Test, solicitReuseExpiredLease6) {
ASSERT_TRUE(lease->expired());
// CASE 1: Asking for any address
- EXPECT_NO_THROW(lease = expectOneLease(engine->allocateAddress6(subnet_,
+ EXPECT_NO_THROW(lease = expectOneLease(engine->allocateLeases6(subnet_,
duid_, iaid_, IOAddress("::"), Lease::TYPE_NA, false, false, "", true,
CalloutHandlePtr())));
// Check that we got that single lease
@@ -587,10 +867,10 @@ TEST_F(AllocEngine6Test, solicitReuseExpiredLease6) {
EXPECT_EQ(addr.toText(), lease->addr_.toText());
// Do all checks on the lease (if subnet-id, preferred/valid times are ok etc.)
- checkLease6(lease);
+ checkLease6(lease, Lease::TYPE_NA, 128);
// CASE 2: Asking specifically for this address
- EXPECT_NO_THROW(lease = expectOneLease(engine->allocateAddress6(subnet_,
+ EXPECT_NO_THROW(lease = expectOneLease(engine->allocateLeases6(subnet_,
duid_, iaid_, addr, Lease::TYPE_NA, false, false, "",
true, CalloutHandlePtr())));
@@ -626,7 +906,7 @@ TEST_F(AllocEngine6Test, requestReuseExpiredLease6) {
ASSERT_TRUE(LeaseMgrFactory::instance().addLease(lease));
// A client comes along, asking specifically for this address
- EXPECT_NO_THROW(lease = expectOneLease(engine->allocateAddress6(subnet_,
+ EXPECT_NO_THROW(lease = expectOneLease(engine->allocateLeases6(subnet_,
duid_, iaid_, addr, Lease::TYPE_NA, false, false, "",
false, CalloutHandlePtr())));
@@ -678,7 +958,7 @@ TEST_F(AllocEngine4Test, simpleAlloc4) {
100, false)));
ASSERT_TRUE(engine);
- Lease4Ptr lease = engine->allocateAddress4(subnet_, clientid_, hwaddr_,
+ Lease4Ptr lease = engine->allocateLease4(subnet_, clientid_, hwaddr_,
IOAddress("0.0.0.0"),
false, true,
"somehost.example.com.",
@@ -708,7 +988,7 @@ TEST_F(AllocEngine4Test, fakeAlloc4) {
100, false)));
ASSERT_TRUE(engine);
- Lease4Ptr lease = engine->allocateAddress4(subnet_, clientid_, hwaddr_,
+ Lease4Ptr lease = engine->allocateLease4(subnet_, clientid_, hwaddr_,
IOAddress("0.0.0.0"),
false, true, "host.example.com.",
true, CalloutHandlePtr(),
@@ -737,7 +1017,7 @@ TEST_F(AllocEngine4Test, allocWithValidHint4) {
100, false)));
ASSERT_TRUE(engine);
- Lease4Ptr lease = engine->allocateAddress4(subnet_, clientid_, hwaddr_,
+ Lease4Ptr lease = engine->allocateLease4(subnet_, clientid_, hwaddr_,
IOAddress("192.0.2.105"),
true, true, "host.example.com.",
false, CalloutHandlePtr(),
@@ -782,7 +1062,7 @@ TEST_F(AllocEngine4Test, allocWithUsedHint4) {
// Another client comes in and request an address that is in pool, but
// unfortunately it is used already. The same address must not be allocated
// twice.
- Lease4Ptr lease = engine->allocateAddress4(subnet_, clientid_, hwaddr_,
+ Lease4Ptr lease = engine->allocateLease4(subnet_, clientid_, hwaddr_,
IOAddress("192.0.2.106"),
false, false, "",
false, CalloutHandlePtr(),
@@ -823,7 +1103,7 @@ TEST_F(AllocEngine4Test, allocBogusHint4) {
// Client would like to get a 3000::abc lease, which does not belong to any
// supported lease. Allocation engine should ignore it and carry on
// with the normal allocation
- Lease4Ptr lease = engine->allocateAddress4(subnet_, clientid_, hwaddr_,
+ Lease4Ptr lease = engine->allocateLease4(subnet_, clientid_, hwaddr_,
IOAddress("10.1.1.1"),
false, false, "",
false, CalloutHandlePtr(),
@@ -850,14 +1130,14 @@ TEST_F(AllocEngine4Test, allocBogusHint4) {
// This test checks that NULL values are handled properly
-TEST_F(AllocEngine4Test, allocateAddress4Nulls) {
+TEST_F(AllocEngine4Test, allocateLease4Nulls) {
boost::scoped_ptr<AllocEngine> engine;
ASSERT_NO_THROW(engine.reset(new AllocEngine(AllocEngine::ALLOC_ITERATIVE,
100, false)));
ASSERT_TRUE(engine);
// Allocations without subnet are not allowed
- Lease4Ptr lease = engine->allocateAddress4(SubnetPtr(), clientid_, hwaddr_,
+ Lease4Ptr lease = engine->allocateLease4(SubnetPtr(), clientid_, hwaddr_,
IOAddress("0.0.0.0"),
false, false, "",
false, CalloutHandlePtr(),
@@ -865,7 +1145,7 @@ TEST_F(AllocEngine4Test, allocateAddress4Nulls) {
EXPECT_FALSE(lease);
// Allocations without HW address are not allowed
- lease = engine->allocateAddress4(subnet_, clientid_, HWAddrPtr(),
+ lease = engine->allocateLease4(subnet_, clientid_, HWAddrPtr(),
IOAddress("0.0.0.0"),
false, false, "",
false, CalloutHandlePtr(),
@@ -875,7 +1155,7 @@ TEST_F(AllocEngine4Test, allocateAddress4Nulls) {
// Allocations without client-id are allowed
clientid_ = ClientIdPtr();
- lease = engine->allocateAddress4(subnet_, ClientIdPtr(), hwaddr_,
+ lease = engine->allocateLease4(subnet_, ClientIdPtr(), hwaddr_,
IOAddress("0.0.0.0"),
true, true, "myhost.example.com.",
false, CalloutHandlePtr(),
@@ -907,7 +1187,7 @@ TEST_F(AllocEngine4Test, IterativeAllocator) {
for (int i = 0; i < 1000; ++i) {
IOAddress candidate = alloc->pickAddress(subnet_, clientid_,
IOAddress("0.0.0.0"));
- EXPECT_TRUE(subnet_->inPool(candidate));
+ EXPECT_TRUE(subnet_->inPool(Lease::TYPE_V4, candidate));
}
}
@@ -939,7 +1219,7 @@ TEST_F(AllocEngine4Test, IterativeAllocator_manyPools4) {
int cnt = 0;
while (++cnt) {
IOAddress candidate = alloc.pickAddress(subnet_, clientid_, IOAddress("0.0.0.0"));
- EXPECT_TRUE(subnet_->inPool(candidate));
+ EXPECT_TRUE(subnet_->inPool(Lease::TYPE_V4, candidate));
// One way to easily verify that the iterative allocator really works is
// to uncomment the following line and observe its output that it
@@ -985,7 +1265,7 @@ TEST_F(AllocEngine4Test, smallPool4) {
subnet_->addPool(pool_);
cfg_mgr.addSubnet4(subnet_);
- Lease4Ptr lease = engine->allocateAddress4(subnet_, clientid_, hwaddr_,
+ Lease4Ptr lease = engine->allocateLease4(subnet_, clientid_, hwaddr_,
IOAddress("0.0.0.0"),
true, true, "host.example.com.",
false, CalloutHandlePtr(),
@@ -1041,7 +1321,7 @@ TEST_F(AllocEngine4Test, outOfAddresses4) {
// There is just a single address in the pool and allocated it to someone
// else, so the allocation should fail
- Lease4Ptr lease2 = engine->allocateAddress4(subnet_, clientid_, hwaddr_,
+ Lease4Ptr lease2 = engine->allocateLease4(subnet_, clientid_, hwaddr_,
IOAddress("0.0.0.0"),
false, false, "",
false, CalloutHandlePtr(),
@@ -1084,7 +1364,7 @@ TEST_F(AllocEngine4Test, discoverReuseExpiredLease4) {
ASSERT_TRUE(LeaseMgrFactory::instance().addLease(lease));
// CASE 1: Asking for any address
- lease = engine->allocateAddress4(subnet_, clientid_, hwaddr_,
+ lease = engine->allocateLease4(subnet_, clientid_, hwaddr_,
IOAddress("0.0.0.0"),
false, false, "",
true, CalloutHandlePtr(),
@@ -1103,7 +1383,7 @@ TEST_F(AllocEngine4Test, discoverReuseExpiredLease4) {
checkLease4(lease);
// CASE 2: Asking specifically for this address
- lease = engine->allocateAddress4(subnet_, clientid_, hwaddr_,
+ lease = engine->allocateLease4(subnet_, clientid_, hwaddr_,
IOAddress(addr.toText()),
false, false, "",
true, CalloutHandlePtr(),
@@ -1144,7 +1424,7 @@ TEST_F(AllocEngine4Test, requestReuseExpiredLease4) {
ASSERT_TRUE(LeaseMgrFactory::instance().addLease(lease));
// A client comes along, asking specifically for this address
- lease = engine->allocateAddress4(subnet_, clientid_, hwaddr_,
+ lease = engine->allocateLease4(subnet_, clientid_, hwaddr_,
IOAddress(addr.toText()),
false, true, "host.example.com.",
false, CalloutHandlePtr(),
@@ -1341,14 +1621,14 @@ TEST_F(HookAllocEngine6Test, lease6_select) {
CalloutHandlePtr callout_handle = HooksManager::createCalloutHandle();
Lease6Ptr lease;
- EXPECT_NO_THROW(lease = expectOneLease(engine->allocateAddress6(subnet_,
+ EXPECT_NO_THROW(lease = expectOneLease(engine->allocateLeases6(subnet_,
duid_, iaid_, IOAddress("::"), Lease::TYPE_NA, false, false,
"", false, callout_handle)));
// Check that we got a lease
ASSERT_TRUE(lease);
// Do all checks on the lease
- checkLease6(lease);
+ checkLease6(lease, Lease::TYPE_NA, 128);
// Check that the lease is indeed in LeaseMgr
Lease6Ptr from_mgr = LeaseMgrFactory::instance().getLease6(lease->type_,
@@ -1406,13 +1686,13 @@ TEST_F(HookAllocEngine6Test, change_lease6_select) {
EXPECT_NO_THROW(HooksManager::preCalloutsLibraryHandle().registerCallout(
"lease6_select", lease6_select_different_callout));
- // Normally, dhcpv6_srv would passed the handle when calling allocateAddress6,
+ // Normally, dhcpv6_srv would passed the handle when calling allocateLeases6,
// but in tests we need to create it on our own.
CalloutHandlePtr callout_handle = HooksManager::createCalloutHandle();
- // Call allocateAddress6. Callouts should be triggered here.
+ // Call allocateLeases6. Callouts should be triggered here.
Lease6Ptr lease;
- EXPECT_NO_THROW(lease = expectOneLease(engine->allocateAddress6(subnet_,
+ EXPECT_NO_THROW(lease = expectOneLease(engine->allocateLeases6(subnet_,
duid_, iaid_, IOAddress("::"), Lease::TYPE_NA, false, false,
"", false, callout_handle)));
// Check that we got a lease
@@ -1567,7 +1847,7 @@ TEST_F(HookAllocEngine4Test, lease4_select) {
CalloutHandlePtr callout_handle = HooksManager::createCalloutHandle();
- Lease4Ptr lease = engine->allocateAddress4(subnet_, clientid_, hwaddr_,
+ Lease4Ptr lease = engine->allocateLease4(subnet_, clientid_, hwaddr_,
IOAddress("0.0.0.0"),
false, false, "",
false, callout_handle,
@@ -1629,16 +1909,16 @@ TEST_F(HookAllocEngine4Test, change_lease4_select) {
EXPECT_NO_THROW(HooksManager::preCalloutsLibraryHandle().registerCallout(
"lease4_select", lease4_select_different_callout));
- // Normally, dhcpv4_srv would passed the handle when calling allocateAddress4,
+ // Normally, dhcpv4_srv would passed the handle when calling allocateLease4,
// but in tests we need to create it on our own.
CalloutHandlePtr callout_handle = HooksManager::createCalloutHandle();
- // Call allocateAddress4. Callouts should be triggered here.
- Lease4Ptr lease = engine->allocateAddress4(subnet_, clientid_, hwaddr_,
- IOAddress("0.0.0.0"),
- false, false, "",
- false, callout_handle,
- old_lease_);
+ // Call allocateLease4. Callouts should be triggered here.
+ Lease4Ptr lease = engine->allocateLease4(subnet_, clientid_, hwaddr_,
+ IOAddress("0.0.0.0"),
+ false, false, "",
+ false, callout_handle,
+ old_lease_);
// Check that we got a lease
ASSERT_TRUE(lease);
diff --git a/src/lib/dhcpsrv/tests/pool_unittest.cc b/src/lib/dhcpsrv/tests/pool_unittest.cc
index bf89508..402ca2a 100644
--- a/src/lib/dhcpsrv/tests/pool_unittest.cc
+++ b/src/lib/dhcpsrv/tests/pool_unittest.cc
@@ -99,9 +99,16 @@ TEST(Pool4Test, unique_id) {
}
}
}
-
}
+// Simple check if toText returns reasonable values
+TEST(Poo4Test,toText) {
+ Pool4 pool1(IOAddress("192.0.2.7"), IOAddress("192.0.2.17"));
+ EXPECT_EQ("type=V4, 192.0.2.7-192.0.2.17", pool1.toText());
+
+ Pool4 pool2(IOAddress("192.0.2.128"), 28);
+ EXPECT_EQ("type=V4, 192.0.2.128-192.0.2.143", pool2.toText());
+}
TEST(Pool6Test, constructor_first_last) {
@@ -244,4 +251,16 @@ TEST(Pool6Test, unique_id) {
}
+// Simple check if toText returns reasonable values
+TEST(Poo6Test,toText) {
+ Pool6 pool1(Lease::TYPE_NA, IOAddress("2001:db8::1"),
+ IOAddress("2001:db8::2"));
+ EXPECT_EQ("type=IA_NA, 2001:db8::1-2001:db8::2, delegated_len=128",
+ pool1.toText());
+
+ Pool6 pool2(Lease::TYPE_PD, IOAddress("2001:db8:1::"), 96, 112);
+ EXPECT_EQ("type=IA_PD, 2001:db8:1::-2001:db8:1::ffff:ffff, delegated_len=112",
+ pool2.toText());
+}
+
}; // end of anonymous namespace
diff --git a/src/lib/dhcpsrv/tests/subnet_unittest.cc b/src/lib/dhcpsrv/tests/subnet_unittest.cc
index a3dcbdc..0af8191 100644
--- a/src/lib/dhcpsrv/tests/subnet_unittest.cc
+++ b/src/lib/dhcpsrv/tests/subnet_unittest.cc
@@ -140,27 +140,27 @@ TEST(Subnet4Test, inRangeinPool) {
EXPECT_TRUE(subnet->inRange(IOAddress("192.1.1.1")));
// ... but it does not belong to any pool within
- EXPECT_FALSE(subnet->inPool(IOAddress("192.1.1.1")));
+ EXPECT_FALSE(subnet->inPool(Lease::TYPE_V4, IOAddress("192.1.1.1")));
// the last address that is in range, but out of pool
EXPECT_TRUE(subnet->inRange(IOAddress("192.1.255.255")));
- EXPECT_FALSE(subnet->inPool(IOAddress("192.1.255.255")));
+ EXPECT_FALSE(subnet->inPool(Lease::TYPE_V4, IOAddress("192.1.255.255")));
// the first address that is in range, in pool
EXPECT_TRUE(subnet->inRange(IOAddress("192.2.0.0")));
- EXPECT_TRUE (subnet->inPool(IOAddress("192.2.0.0")));
+ EXPECT_TRUE (subnet->inPool(Lease::TYPE_V4, IOAddress("192.2.0.0")));
// let's try something in the middle as well
EXPECT_TRUE(subnet->inRange(IOAddress("192.2.3.4")));
- EXPECT_TRUE (subnet->inPool(IOAddress("192.2.3.4")));
+ EXPECT_TRUE (subnet->inPool(Lease::TYPE_V4, IOAddress("192.2.3.4")));
// the last address that is in range, in pool
EXPECT_TRUE(subnet->inRange(IOAddress("192.2.255.255")));
- EXPECT_TRUE (subnet->inPool(IOAddress("192.2.255.255")));
+ EXPECT_TRUE (subnet->inPool(Lease::TYPE_V4, IOAddress("192.2.255.255")));
// the first address that is in range, but out of pool
EXPECT_TRUE(subnet->inRange(IOAddress("192.3.0.0")));
- EXPECT_FALSE(subnet->inPool(IOAddress("192.3.0.0")));
+ EXPECT_FALSE(subnet->inPool(Lease::TYPE_V4, IOAddress("192.3.0.0")));
}
// This test checks if the toText() method returns text representation
@@ -609,27 +609,27 @@ TEST(Subnet6Test, inRangeinPool) {
// 192.1.1.1 belongs to the subnet...
EXPECT_TRUE(subnet->inRange(IOAddress("2001:db8::1")));
// ... but it does not belong to any pool within
- EXPECT_FALSE(subnet->inPool(IOAddress("2001:db8::1")));
+ EXPECT_FALSE(subnet->inPool(Lease::TYPE_NA, IOAddress("2001:db8::1")));
// the last address that is in range, but out of pool
EXPECT_TRUE(subnet->inRange(IOAddress("2001:db8::f")));
- EXPECT_FALSE(subnet->inPool(IOAddress("2001:db8::f")));
+ EXPECT_FALSE(subnet->inPool(Lease::TYPE_NA, IOAddress("2001:db8::f")));
// the first address that is in range, in pool
EXPECT_TRUE(subnet->inRange(IOAddress("2001:db8::10")));
- EXPECT_TRUE (subnet->inPool(IOAddress("2001:db8::10")));
+ EXPECT_TRUE (subnet->inPool(Lease::TYPE_NA, IOAddress("2001:db8::10")));
// let's try something in the middle as well
EXPECT_TRUE(subnet->inRange(IOAddress("2001:db8::18")));
- EXPECT_TRUE (subnet->inPool(IOAddress("2001:db8::18")));
+ EXPECT_TRUE (subnet->inPool(Lease::TYPE_NA, IOAddress("2001:db8::18")));
// the last address that is in range, in pool
EXPECT_TRUE(subnet->inRange(IOAddress("2001:db8::20")));
- EXPECT_TRUE (subnet->inPool(IOAddress("2001:db8::20")));
+ EXPECT_TRUE (subnet->inPool(Lease::TYPE_NA, IOAddress("2001:db8::20")));
// the first address that is in range, but out of pool
EXPECT_TRUE(subnet->inRange(IOAddress("2001:db8::21")));
- EXPECT_FALSE(subnet->inPool(IOAddress("2001:db8::21")));
+ EXPECT_FALSE(subnet->inPool(Lease::TYPE_NA, IOAddress("2001:db8::21")));
}
// This test checks if the toText() method returns text representation
More information about the bind10-changes
mailing list