testReleaseReject(Lease::TYPE_NA, IOAddress("2001:db8:1:1::dead"));
}
-// This test verifies that incoming (invalid) RELEASE with a prefix
-// can be handled properly.
+// This test verifies that incoming (invalid) RELEASE with a prefix can be
+// handled properly.
//
// This test checks 3 scenarios:
// 1. there is no such lease at all
// to DHCPDISCOVER (fake allocation)
TEST_F(AllocEngine4Test, discoverReuseDeclinedLease4) {
- AllocEnginePtr engine(new AllocEngine( 0));
+ AllocEnginePtr engine(new AllocEngine(0));
ASSERT_TRUE(engine);
// Now prepare a configuration with single address pool.
TEST_F(AllocEngine4Test, discoverReuseDeclinedLease4Stats) {
// Now prepare for DISCOVER processing
- AllocEnginePtr engine(new AllocEngine( 0));
+ AllocEnginePtr engine(new AllocEngine(0));
ASSERT_TRUE(engine);
// Now prepare a configuration with single address pool.
// to REQUEST (actual allocation)
TEST_F(AllocEngine4Test, requestReuseDeclinedLease4) {
- AllocEnginePtr engine(new AllocEngine( 0));
+ AllocEnginePtr engine(new AllocEngine(0));
ASSERT_TRUE(engine);
// Now prepare a configuration with single address pool.
// is reused when responding to DHCPREQUEST (actual allocation)
TEST_F(AllocEngine4Test, requestReuseDeclinedLease4Stats) {
- AllocEnginePtr engine(new AllocEngine( 0));
+ AllocEnginePtr engine(new AllocEngine(0));
ASSERT_TRUE(engine);
// Now prepare a configuration with single address pool.
// - Client has a reservation.
// - Client sends DHCPDISCOVER without requested IP Address.
// - Server returns DHCPOFFER with the reserved address.
-TEST_F(AllocEngine4Test,reservedAddressNoHintFakeAllocation) {
+TEST_F(AllocEngine4Test, reservedAddressNoHintFakeAllocation) {
// Create reservation for the client.
HostPtr host(new Host(&hwaddr_->hwaddr_[0], hwaddr_->hwaddr_.size(),
Host::IDENT_HWADDR, subnet_->getID(),
// Remove the default PD pool.
subnet_->delPools(Lease::TYPE_PD);
- // Configure the PD pool with the prefix length of /64 and the delegated
+ // Configure the PD pool with the prefix length of /80 and the delegated
// length /96.
Pool6Ptr pool(new Pool6(Lease::TYPE_PD, IOAddress("2001:db8:1:2::"), 80, 96));
subnet_->addPool(pool);
ASSERT_EQ(1, leases.size());
}
+// This test checks that the allocation engine can delegate the long prefix.
+// The pool with prefix of 64 and with long delegated prefix has a very
+// high capacity. The number of attempts that the allocation engine makes
+// to allocate the prefix for high capacity pools is equal to the capacity
+// value. This test verifies that the prefix can be allocated in that
+// case.
+TEST_F(AllocEngine6Test, largePdPoolPreferrSmaller) {
+ AllocEngine engine(0);
+
+ // Remove the default PD pool.
+ subnet_->delPools(Lease::TYPE_PD);
+
+ // Configure the PD pool with the prefix length of /80 and the delegated
+ // length /96.
+ Pool6Ptr pool(new Pool6(Lease::TYPE_PD, IOAddress("2001:db8:1:2::"), 80, 96));
+ subnet_->addPool(pool);
+
+ Pool6Ptr pool2(new Pool6(Lease::TYPE_PD, IOAddress("2001:db8:1:3::"), 72, 80));
+ subnet_->addPool(pool2);
+
+ // Let's create a lease and put it in the LeaseMgr
+ // Even if the lease is owned by the client, the non-matching prefix length
+ // in the hint should force allocation of other lease.
+ time_t now = time(NULL);
+ Lease6Ptr used(new Lease6(Lease::TYPE_PD, IOAddress("2001:db8:1:2::"),
+ duid_, 1, 2, now, subnet_->getID(), HWAddrPtr(), 96));
+ ASSERT_TRUE(LeaseMgrFactory::instance().addLease(used));
+
+ // We should have got exactly one lease.
+ Lease6Collection leases = allocateTest(engine, pool2, IOAddress("2001:db8:1:2::"),
+ false, true, 92);
+ ASSERT_EQ(1, leases.size());
+}
+
+// This test checks that the allocation engine can delegate the long prefix.
+// The pool with prefix of 64 and with long delegated prefix has a very
+// high capacity. The number of attempts that the allocation engine makes
+// to allocate the prefix for high capacity pools is equal to the capacity
+// value. This test verifies that the prefix can be allocated in that
+// case.
+TEST_F(AllocEngine6Test, largePdPoolPreferrEqual) {
+ AllocEngine engine(0);
+
+ // Remove the default PD pool.
+ subnet_->delPools(Lease::TYPE_PD);
+
+ // Configure the PD pool with the prefix length of /80 and the delegated
+ // length /96.
+ Pool6Ptr pool(new Pool6(Lease::TYPE_PD, IOAddress("2001:db8:1:2::"), 80, 96));
+ subnet_->addPool(pool);
+
+ Pool6Ptr pool2(new Pool6(Lease::TYPE_PD, IOAddress("2001:db8:1:3::"), 72, 80));
+ subnet_->addPool(pool2);
+
+ // Let's create a lease and put it in the LeaseMgr
+ // Even if the lease is owned by the client, the non-matching prefix length
+ // in the hint should force allocation of other lease.
+ time_t now = time(NULL);
+ Lease6Ptr used(new Lease6(Lease::TYPE_PD, IOAddress("2001:db8:1:2::"),
+ duid_, 1, 2, now, subnet_->getID(), HWAddrPtr(), 96));
+ ASSERT_TRUE(LeaseMgrFactory::instance().addLease(used));
+
+ // We should have got exactly one lease.
+ Lease6Collection leases = allocateTest(engine, pool2, IOAddress("2001:db8:1:2::"),
+ false, true, 80);
+ ASSERT_EQ(1, leases.size());
+}
+
+// This test checks that the allocation engine can delegate the long prefix.
+// The pool with prefix of 64 and with long delegated prefix has a very
+// high capacity. The number of attempts that the allocation engine makes
+// to allocate the prefix for high capacity pools is equal to the capacity
+// value. This test verifies that the prefix can be allocated in that
+// case.
+TEST_F(AllocEngine6Test, largePdPoolPreferrGreater) {
+ AllocEngine engine(0);
+
+ // Remove the default PD pool.
+ subnet_->delPools(Lease::TYPE_PD);
+
+ // Configure the PD pool with the prefix length of /80 and the delegated
+ // length /96.
+ Pool6Ptr pool(new Pool6(Lease::TYPE_PD, IOAddress("2001:db8:1:2::"), 80, 96));
+ subnet_->addPool(pool);
+
+ Pool6Ptr pool2(new Pool6(Lease::TYPE_PD, IOAddress("2001:db8:1:3::"), 72, 80));
+ subnet_->addPool(pool2);
+
+ // Let's create a lease and put it in the LeaseMgr
+ // Even if the lease is owned by the client, the non-matching prefix length
+ // in the hint should force allocation of other lease.
+ time_t now = time(NULL);
+ Lease6Ptr used(new Lease6(Lease::TYPE_PD, IOAddress("2001:db8:1:3::"),
+ duid_, 1, 2, now, subnet_->getID(), HWAddrPtr(), 80));
+ ASSERT_TRUE(LeaseMgrFactory::instance().addLease(used));
+
+ // We should have got exactly one lease.
+ Lease6Collection leases = allocateTest(engine, pool, IOAddress("2001:db8:1:3::"),
+ false, true, 64);
+ ASSERT_EQ(1, leases.size());
+}
+
// This test checks that the allocation engine can delegate addresses
// from ridiculously large pool. The configuration provides 2^80 or
// 1208925819614629174706176 addresses. We used to have a bug that would
<< "Lease lifetime was not extended, but it should";
}
+// Verifies that client with a global prefix reservation can get and
+// renew a lease for an arbitrary prefix even if using a wrong hint prefix
+// length.
+TEST_F(AllocEngine6Test, globalHostReservedPrefixDifferentPrefixLen) {
+ boost::scoped_ptr<AllocEngine> engine;
+ ASSERT_NO_THROW(engine.reset(new AllocEngine(100)));
+ ASSERT_TRUE(engine);
+
+ HostPtr host(new Host(&duid_->getDuid()[0], duid_->getDuid().size(),
+ Host::IDENT_DUID, SUBNET_ID_UNUSED, SUBNET_ID_GLOBAL,
+ asiolink::IOAddress("0.0.0.0")));
+ host->setHostname("ghost1");
+ IPv6Resrv resv(IPv6Resrv::TYPE_PD, asiolink::IOAddress("3001::"), 64);
+ host->addReservation(resv);
+
+ CfgMgr::instance().getStagingCfg()->getCfgHosts()->add(host);
+ CfgMgr::instance().commit();
+
+ subnet_->setReservationsGlobal(true);
+
+ // Create context which will be used to try to allocate leases
+ Pkt6Ptr query(new Pkt6(DHCPV6_REQUEST, 1234));
+ AllocEngine::ClientContext6 ctx(subnet_, duid_, false, false, "", false, query);
+ ctx.currentIA().type_ = Lease::TYPE_PD;
+ ctx.currentIA().iaid_ = iaid_;
+ // Using a different prefix length in the hint should have no effect
+ ctx.currentIA().addHint(asiolink::IOAddress("3001::"), 32);
+
+ // Look up the reservation.
+ findReservation(*engine, ctx);
+ // Make sure we found our host.
+ ConstHostPtr current = ctx.currentHost();
+ ASSERT_TRUE(current);
+ ASSERT_EQ("ghost1", current->getHostname());
+
+ // Check that we have been allocated the fixed address.
+ Lease6Ptr lease;
+ ASSERT_NO_THROW(lease = expectOneLease(engine->allocateLeases6(ctx)));
+ ASSERT_TRUE(lease);
+ EXPECT_EQ("3001::", lease->addr_.toText());
+
+ // We're going to rollback the clock a little so we can verify a renewal.
+ --lease->cltt_;
+ EXPECT_NO_THROW(LeaseMgrFactory::instance().updateLease6(lease));
+
+ // This is what the client will send in his renew message.
+ AllocEngine::HintContainer hints;
+ hints.push_back(AllocEngine::Resource(IOAddress("3001::"), 64));
+
+ // Set test fixture hostname_ to the expected value. This gets checked via
+ // renewTest.
+ hostname_ = "ghost1";
+
+ // We need a PD pool to fake renew_test
+ Pool6Ptr dummy_pool(new Pool6(Lease::TYPE_PD, IOAddress("2001:db8::"), 64, 64));
+
+ // Client should receive a lease.
+ Lease6Collection renewed = renewTest(*engine, dummy_pool, hints, false);
+ ASSERT_EQ(1, renewed.size());
+
+ // And the lease lifetime should be extended.
+ EXPECT_GT(renewed[0]->cltt_, lease->cltt_)
+ << "Lease lifetime was not extended, but it should";
+}
+
// Verifies that client with a subnet address reservation can get and
// renew a lease for an address in the subnet.
TEST_F(AllocEngine6Test, mixedHostReservedAddress) {
}
// Verifies that client with a subnet prefix reservation can get and
-// renew a lease for a prefix in the subnet.
+// renew a lease for a prefix in the subnet even if using a wrong hint prefix
+// length.
TEST_F(AllocEngine6Test, mixedHostReservedPrefix) {
boost::scoped_ptr<AllocEngine> engine;
ASSERT_NO_THROW(engine.reset(new AllocEngine(100)));
subnet_->setReservationsGlobal(true);
subnet_->setReservationsInSubnet(true);
+ // Create context which will be used to try to allocate leases
+ Pkt6Ptr query(new Pkt6(DHCPV6_REQUEST, 1234));
+ AllocEngine::ClientContext6 ctx(subnet_, duid_, false, false, "", false, query);
+ ctx.currentIA().type_ = Lease::TYPE_PD;
+ ctx.currentIA().iaid_ = iaid_;
+ // Using a different prefix length in the hint should have no effect
+ ctx.currentIA().addHint(asiolink::IOAddress("2001:db8:1:2::"), 32);
+
+ // Look up the reservation.
+ findReservation(*engine, ctx);
+ // Make sure we found our host.
+ ConstHostPtr current = ctx.currentHost();
+ ASSERT_TRUE(current);
+ ASSERT_EQ("mhost1", current->getHostname());
+
+ // Check that we have been allocated the fixed prefix.
+ Lease6Ptr lease;
+ ASSERT_NO_THROW(lease = expectOneLease(engine->allocateLeases6(ctx)));
+ ASSERT_TRUE(lease);
+ EXPECT_EQ("2001:db8:1:2::", lease->addr_.toText());
+
+ // We're going to rollback the clock a little so we can verify a renewal.
+ --lease->cltt_;
+ EXPECT_NO_THROW(LeaseMgrFactory::instance().updateLease6(lease));
+
+ // This is what the client will send in his renew message.
+ AllocEngine::HintContainer hints;
+ hints.push_back(AllocEngine::Resource(IOAddress("2001:db8:1:2::"), 64));
+
+ // Set test fixture hostname_ to the expected value. This gets checked via
+ // renewTest.
+ hostname_ = "mhost1";
+
+ // We need a PD pool to fake renew_test
+ Pool6Ptr dummy_pool(new Pool6(Lease::TYPE_PD, IOAddress("2001:db8::"), 64, 64));
+
+ // Client should receive a lease.
+ Lease6Collection renewed = renewTest(*engine, dummy_pool, hints, true);
+ ASSERT_EQ(1, renewed.size());
+
+ // And the lease lifetime should be extended.
+ EXPECT_GT(renewed[0]->cltt_, lease->cltt_)
+ << "Lease lifetime was not extended, but it should";
+}
+
+// Verifies that client with a subnet prefix reservation can get and
+// renew a lease for a prefix in the subnet.
+TEST_F(AllocEngine6Test, mixedHostReservedPrefixDifferentPrefixLen) {
+ boost::scoped_ptr<AllocEngine> engine;
+ ASSERT_NO_THROW(engine.reset(new AllocEngine(100)));
+ ASSERT_TRUE(engine);
+
+ HostPtr host(new Host(&duid_->getDuid()[0], duid_->getDuid().size(),
+ Host::IDENT_DUID, SUBNET_ID_UNUSED, subnet_->getID(),
+ asiolink::IOAddress("0.0.0.0")));
+ host->setHostname("mhost1");
+ IPv6Resrv resv(IPv6Resrv::TYPE_PD, asiolink::IOAddress("2001:db8:1:2::"), 64);
+ host->addReservation(resv);
+
+ CfgMgr::instance().getStagingCfg()->getCfgHosts()->add(host);
+ CfgMgr::instance().commit();
+
+ subnet_->setReservationsGlobal(true);
+ subnet_->setReservationsInSubnet(true);
+
// Create context which will be used to try to allocate leases
Pkt6Ptr query(new Pkt6(DHCPV6_REQUEST, 1234));
AllocEngine::ClientContext6 ctx(subnet_, duid_, false, false, "", false, query);
<< "Lease lifetime was not extended, but it should";
}
+// Verifies that client with a subnet and a global prefix reservation
+// can get and renew a lease for a prefix in the subnet even if using a wrong
+// hint prefix length.
+TEST_F(AllocEngine6Test, bothHostReservedPrefixDifferentPrefixLen) {
+ boost::scoped_ptr<AllocEngine> engine;
+ ASSERT_NO_THROW(engine.reset(new AllocEngine(100)));
+ ASSERT_TRUE(engine);
+
+ HostPtr ghost(new Host(&duid_->getDuid()[0], duid_->getDuid().size(),
+ Host::IDENT_DUID, SUBNET_ID_UNUSED, SUBNET_ID_GLOBAL,
+ asiolink::IOAddress("0.0.0.0")));
+ ghost->setHostname("ghost1");
+ IPv6Resrv gresv(IPv6Resrv::TYPE_PD, asiolink::IOAddress("3001::"), 64);
+ ghost->addReservation(gresv);
+
+ CfgMgr::instance().getStagingCfg()->getCfgHosts()->add(ghost);
+
+ HostPtr host(new Host(&duid_->getDuid()[0], duid_->getDuid().size(),
+ Host::IDENT_DUID, SUBNET_ID_UNUSED, subnet_->getID(),
+ asiolink::IOAddress("0.0.0.0")));
+ host->setHostname("mhost1");
+ IPv6Resrv resv(IPv6Resrv::TYPE_PD, asiolink::IOAddress("2001:db8:1:2::"), 64);
+ host->addReservation(resv);
+
+ CfgMgr::instance().getStagingCfg()->getCfgHosts()->add(host);
+ CfgMgr::instance().commit();
+
+ subnet_->setReservationsGlobal(true);
+ subnet_->setReservationsInSubnet(true);
+
+ // Create context which will be used to try to allocate leases
+ Pkt6Ptr query(new Pkt6(DHCPV6_REQUEST, 1234));
+ AllocEngine::ClientContext6 ctx(subnet_, duid_, false, false, "", false, query);
+ ctx.currentIA().type_ = Lease::TYPE_PD;
+ ctx.currentIA().iaid_ = iaid_;
+ // Using a different prefix length in the hint should have no effect
+ ctx.currentIA().addHint(asiolink::IOAddress("2001:db8:1:2::"), 32);
+
+ // Look up the reservation.
+ findReservation(*engine, ctx);
+ // Make sure we found our host.
+ ConstHostPtr current = ctx.currentHost();
+ ASSERT_TRUE(current);
+ ASSERT_EQ("mhost1", current->getHostname());
+
+ // Check that we have been allocated the fixed prefix.
+ Lease6Ptr lease;
+ ASSERT_NO_THROW(lease = expectOneLease(engine->allocateLeases6(ctx)));
+ ASSERT_TRUE(lease);
+ EXPECT_EQ("2001:db8:1:2::", lease->addr_.toText());
+
+ // We're going to rollback the clock a little so we can verify a renewal.
+ --lease->cltt_;
+ EXPECT_NO_THROW(LeaseMgrFactory::instance().updateLease6(lease));
+
+ // This is what the client will send in his renew message.
+ AllocEngine::HintContainer hints;
+ hints.push_back(AllocEngine::Resource(IOAddress("2001:db8:1:2::"), 64));
+
+ // Set test fixture hostname_ to the expected value. This gets checked via
+ // renewTest.
+ hostname_ = "mhost1";
+
+ // We need a PD pool to fake renew_test
+ Pool6Ptr dummy_pool(new Pool6(Lease::TYPE_PD, IOAddress("2001:db8::"), 64, 64));
+
+ // Client should receive a lease.
+ Lease6Collection renewed = renewTest(*engine, dummy_pool, hints, true);
+ ASSERT_EQ(1, renewed.size());
+
+ // And the lease lifetime should be extended.
+ EXPECT_GT(renewed[0]->cltt_, lease->cltt_)
+ << "Lease lifetime was not extended, but it should";
+}
+
/// @brief Test fixture class for testing storage of extended lease data.
/// It primarily creates several configuration items common to the
/// extended info tests.
" \"peer\": \"2001:db8::6\" } ] } }",
true
}
-};
+ };
// Allocate a lease.
Lease6Ptr lease;
// Add hint
ctx.currentIA().iaid_ = iaid_;
- // prefix,prefixlen, preferred, valid
+ // prefix, prefixlen, preferred, valid
ctx.currentIA().addHint(IOAddress("::"), 128, 0, scenario.requested_lft_);
Lease6Ptr lease;
// Add hint
ctx.currentIA().iaid_ = iaid_;
- // prefix,prefixlen, preferred, valid
+ // prefix, prefixlen, preferred, valid
ctx.currentIA().addHint(IOAddress("::"), 128, 0, scenario.requested_lft_);
Lease6Ptr lease;
// Add hint
ctx.currentIA().iaid_ = iaid_;
- // prefix,prefixlen, preferred, preferred
+ // prefix, prefixlen, preferred, valid
ctx.currentIA().addHint(IOAddress("::"), 128, scenario.requested_lft_, 0);
Lease6Ptr lease;
// Add hint
ctx.currentIA().iaid_ = iaid_;
- // prefix,prefixlen, preferred, preferred
+ // prefix, prefixlen, preferred, valid
ctx.currentIA().addHint(IOAddress("::"), 128, scenario.requested_lft_, 0);
Lease6Ptr lease;
Lease6Collection
AllocEngine6Test::allocateTest(AllocEngine& engine, const Pool6Ptr& pool,
const asiolink::IOAddress& hint, bool fake,
- bool in_pool) {
+ bool in_pool, uint8_t hint_prefix_length) {
Lease::Type type = pool->getType();
uint8_t expected_len = pool->getLength();
fake, query);
ctx.currentIA().iaid_ = iaid_;
ctx.currentIA().type_ = type;
- ctx.currentIA().addHint(hint);
+ ctx.currentIA().addHint(hint, hint_prefix_length);
Lease6Collection leases;
/// @param hint address to be used as a hint
/// @param fake true - this is fake allocation (SOLICIT)
/// @param in_pool specifies whether the lease is expected to be in pool
+ /// @param hint_prefix_length The hint prefix length that the client
+ /// provided.
/// @return allocated lease(s) (may be empty)
Lease6Collection allocateTest(AllocEngine& engine,
const Pool6Ptr& pool,
const asiolink::IOAddress& hint,
bool fake,
- bool in_pool = true);
+ bool in_pool = true,
+ uint8_t hint_prefix_length = 128);
/// @brief Checks if the allocation can be renewed.
///
}
}
+// 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
+// unless it runs out of pool space and must start over.
+TEST_F(IterativeAllocatorTest6, manyPools) {
+ NakedIterativeAllocator alloc(Lease::TYPE_NA, subnet_);
+
+ // let's start from 2, as there is 2001:db8:1::10 - 2001:db8:1::20 pool already.
+ for (int i = 2; i < 10; ++i) {
+ stringstream min, max;
+
+ min << "2001:db8:1::" << hex << i*16 + 1;
+ max << "2001:db8:1::" << hex << i*16 + 9;
+
+ Pool6Ptr pool(new Pool6(Lease::TYPE_NA, IOAddress(min.str()),
+ IOAddress(max.str())));
+ subnet_->addPool(pool);
+ }
+
+ int total = 17 + 8 * 9; // First pool (::10 - ::20) has 17 addresses in it,
+ // there are 8 extra pools with 9 addresses in each.
+
+ // Let's keep picked addresses here and check their uniqueness.
+ std::set<IOAddress> generated_addrs;
+ int cnt = 0;
+ while (++cnt) {
+ IOAddress candidate = alloc.pickAddress(cc_, duid_, IOAddress("::"));
+ 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 pools.
+ // cout << candidate.toText() << endl;
+
+ if (generated_addrs.find(candidate) == generated_addrs.end()) {
+ // We haven't had this.
+ generated_addrs.insert(candidate);
+ } else {
+ // We have seen this address before. That should mean that we
+ // iterated over all addresses.
+ if (generated_addrs.size() == total) {
+ // We have exactly the number of address in all pools.
+ break;
+ }
+ ADD_FAILURE() << "Too many or not enough unique addresses generated.";
+ break;
+ }
+
+ if ( cnt>total ) {
+ ADD_FAILURE() << "Too many unique addresses generated.";
+ break;
+ }
+ }
+}
+
// This test verifies that the allocator walks over the addresses in the
// non-contiguous pools.
TEST_F(IterativeAllocatorTest6, addrStep) {
alloc.pickPrefix(cc_, pool, duid_, Allocator::PREFIX_LEN_GREATER, IOAddress("::"), 0).toText());
}
+// This test verifies that the allocator picks delegated prefixes from several
+// pools.
+TEST_F(IterativeAllocatorTest6, prefixStepPreferrSmaller) {
+ subnet_ = Subnet6::create(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);
+
+ NakedIterativeAllocator alloc(Lease::TYPE_PD, subnet_);
+
+ Pool6Ptr pool;
+
+ // 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.pickPrefix(cc_, pool, duid_, Allocator::PREFIX_LEN_SMALLER, IOAddress("::"), 64).toText());
+ EXPECT_EQ("2001:db8:0:10::",
+ alloc.pickPrefix(cc_, pool, duid_, Allocator::PREFIX_LEN_SMALLER, IOAddress("::"), 64).toText());
+ EXPECT_EQ("2001:db8:0:20::",
+ alloc.pickPrefix(cc_, pool, duid_, Allocator::PREFIX_LEN_SMALLER, IOAddress("::"), 64).toText());
+ EXPECT_EQ("2001:db8:0:30::",
+ alloc.pickPrefix(cc_, pool, duid_, Allocator::PREFIX_LEN_SMALLER, IOAddress("::"), 64).toText());
+ EXPECT_EQ("2001:db8:0:40::",
+ alloc.pickPrefix(cc_, pool, duid_, Allocator::PREFIX_LEN_SMALLER, IOAddress("::"), 64).toText());
+ EXPECT_EQ("2001:db8:0:50::",
+ alloc.pickPrefix(cc_, pool, duid_, Allocator::PREFIX_LEN_SMALLER, IOAddress("::"), 64).toText());
+ EXPECT_EQ("2001:db8:0:60::",
+ alloc.pickPrefix(cc_, pool, duid_, Allocator::PREFIX_LEN_SMALLER, IOAddress("::"), 64).toText());
+ EXPECT_EQ("2001:db8:0:70::",
+ alloc.pickPrefix(cc_, pool, duid_, Allocator::PREFIX_LEN_SMALLER, IOAddress("::"), 64).toText());
+ EXPECT_EQ("2001:db8:0:80::",
+ alloc.pickPrefix(cc_, pool, duid_, Allocator::PREFIX_LEN_SMALLER, IOAddress("::"), 64).toText());
+ EXPECT_EQ("2001:db8:0:90::",
+ alloc.pickPrefix(cc_, pool, duid_, Allocator::PREFIX_LEN_SMALLER, IOAddress("::"), 64).toText());
+ EXPECT_EQ("2001:db8:0:a0::",
+ alloc.pickPrefix(cc_, pool, duid_, Allocator::PREFIX_LEN_SMALLER, IOAddress("::"), 64).toText());
+ EXPECT_EQ("2001:db8:0:b0::",
+ alloc.pickPrefix(cc_, pool, duid_, Allocator::PREFIX_LEN_SMALLER, IOAddress("::"), 64).toText());
+ EXPECT_EQ("2001:db8:0:c0::",
+ alloc.pickPrefix(cc_, pool, duid_, Allocator::PREFIX_LEN_SMALLER, IOAddress("::"), 64).toText());
+ EXPECT_EQ("2001:db8:0:d0::",
+ alloc.pickPrefix(cc_, pool, duid_, Allocator::PREFIX_LEN_SMALLER, IOAddress("::"), 64).toText());
+ EXPECT_EQ("2001:db8:0:e0::",
+ alloc.pickPrefix(cc_, pool, duid_, Allocator::PREFIX_LEN_SMALLER, IOAddress("::"), 64).toText());
+ EXPECT_EQ("2001:db8:0:f0::",
+ alloc.pickPrefix(cc_, pool, duid_, Allocator::PREFIX_LEN_SMALLER, IOAddress("::"), 64).toText());
+
+ // Second pool (just one lease here)
+ EXPECT_EQ("2001:db8:1::",
+ alloc.pickPrefix(cc_, pool, duid_, Allocator::PREFIX_LEN_SMALLER, IOAddress("::"), 64).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.pickPrefix(cc_, pool, duid_, Allocator::PREFIX_LEN_SMALLER, IOAddress("::"), 64).toText());
+ EXPECT_EQ("2001:db8:0:10::",
+ alloc.pickPrefix(cc_, pool, duid_, Allocator::PREFIX_LEN_SMALLER, IOAddress("::"), 64).toText());
+}
+
+// This test verifies that the allocator picks delegated prefixes from several
+// pools.
+TEST_F(IterativeAllocatorTest6, prefixStepPreferrEqual) {
+ subnet_ = Subnet6::create(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);
+
+ NakedIterativeAllocator alloc(Lease::TYPE_PD, subnet_);
+
+ Pool6Ptr pool;
+
+ // 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::)
+
+ // Second pool (just one lease here)
+ EXPECT_EQ("2001:db8:1::",
+ alloc.pickPrefix(cc_, pool, duid_, Allocator::PREFIX_LEN_EQUAL, IOAddress("::"), 48).toText());
+
+ // Ok, we've iterated over all prefixes in all pools. We now wrap around.
+ // We're looping over now (iterating over second pool again)
+ EXPECT_EQ("2001:db8:1::",
+ alloc.pickPrefix(cc_, pool, duid_, Allocator::PREFIX_LEN_EQUAL, IOAddress("::"), 48).toText());
+}
+
+// This test verifies that the allocator picks delegated prefixes from several
+// pools.
+TEST_F(IterativeAllocatorTest6, prefixStepPreferrGreater) {
+ subnet_ = Subnet6::create(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);
+
+ NakedIterativeAllocator alloc(Lease::TYPE_PD, subnet_);
+
+ Pool6Ptr pool;
+
+ // 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::)
+
+ // Third pool (256 leases, let's check first and last explicitly and the
+ // rest over in a pool
+ EXPECT_EQ("2001:db8:2::",
+ alloc.pickPrefix(cc_, pool, duid_, Allocator::PREFIX_LEN_GREATER, IOAddress("::"), 60).toText());
+ for (int i = 1; i < 255; i++) {
+ stringstream exp;
+ exp << "2001:db8:2:" << hex << i << dec << "::";
+ EXPECT_EQ(exp.str(),
+ alloc.pickPrefix(cc_, pool, duid_, Allocator::PREFIX_LEN_GREATER, IOAddress("::"), 60).toText());
+
+ }
+ EXPECT_EQ("2001:db8:2:ff::",
+ alloc.pickPrefix(cc_, pool, duid_, Allocator::PREFIX_LEN_GREATER, IOAddress("::"), 60).toText());
+
+ // Ok, we've iterated over all prefixes in all pools. We now wrap around.
+ // We're looping over now (iterating over third pool again)
+ EXPECT_EQ("2001:db8:2::",
+ alloc.pickPrefix(cc_, pool, duid_, Allocator::PREFIX_LEN_GREATER, IOAddress("::"), 60).toText());
+}
+
// This test verifies that the allocator picks delegated prefixes from the pools
// with class guards.
TEST_F(IterativeAllocatorTest6, prefixStepInClass) {
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
-// unless it runs out of pool space and must start over.
-TEST_F(IterativeAllocatorTest6, manyPools) {
- NakedIterativeAllocator alloc(Lease::TYPE_NA, subnet_);
-
- // let's start from 2, as there is 2001:db8:1::10 - 2001:db8:1::20 pool already.
- for (int i = 2; i < 10; ++i) {
- stringstream min, max;
-
- min << "2001:db8:1::" << hex << i*16 + 1;
- max << "2001:db8:1::" << hex << i*16 + 9;
-
- Pool6Ptr pool(new Pool6(Lease::TYPE_NA, IOAddress(min.str()),
- IOAddress(max.str())));
- subnet_->addPool(pool);
- }
-
- int total = 17 + 8 * 9; // First pool (::10 - ::20) has 17 addresses in it,
- // there are 8 extra pools with 9 addresses in each.
-
- // Let's keep picked addresses here and check their uniqueness.
- std::set<IOAddress> generated_addrs;
- int cnt = 0;
- while (++cnt) {
- IOAddress candidate = alloc.pickAddress(cc_, duid_, IOAddress("::"));
- 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 pools.
- // cout << candidate.toText() << endl;
-
- if (generated_addrs.find(candidate) == generated_addrs.end()) {
- // We haven't had this.
- generated_addrs.insert(candidate);
- } else {
- // We have seen this address before. That should mean that we
- // iterated over all addresses.
- if (generated_addrs.size() == total) {
- // We have exactly the number of address in all pools.
- break;
- }
- ADD_FAILURE() << "Too many or not enough unique addresses generated.";
- break;
- }
-
- if ( cnt>total ) {
- ADD_FAILURE() << "Too many unique addresses generated.";
- break;
- }
- }
-}
-
} // end of namespace isc::dhcp::test
} // end of namespace isc::dhcp
} // end of namespace isc
TEST_F(RandomAllocatorTest6, singlePdPool) {
RandomAllocator alloc(Lease::TYPE_PD, subnet_);
+ Pool6Ptr pool;
+
// Remember returned prefixes, so we can verify that unique addresses
// are returned.
std::set<IOAddress> prefixes;
for (auto i = 0; i < 66000; ++i) {
- IOAddress candidate = alloc.pickAddress(cc_, duid_, IOAddress("::"));
+ IOAddress candidate = alloc.pickPrefix(cc_, pool, duid_, Allocator::PREFIX_LEN_GREATER, IOAddress("::"), 0);
prefixes.insert(candidate);
EXPECT_TRUE(subnet_->inPool(Lease::TYPE_PD, candidate));
EXPECT_TRUE(subnet_->inPool(Lease::TYPE_PD, candidate, cc_));
for (auto i = 0; i < 10; ++i) {
ostringstream s;
- s << "300" << hex << i+1 << "::";
+ s << "300" << hex << i + 1 << "::";
auto pool = boost::make_shared<Pool6>(Lease::TYPE_PD,
IOAddress(s.str()),
120,
subnet_->addPool(pool);
}
- size_t total = 65536 + 10*256;
+ size_t total = 65536 + 10 * 256;
+
+ Pool6Ptr pool;
for (auto j = 0; j < 2; ++j) {
std::set<IOAddress> prefixes;
for (auto i = 0; i < total; ++i) {
- IOAddress candidate = alloc.pickAddress(cc_, duid_, IOAddress("::"));
+ IOAddress candidate = alloc.pickPrefix(cc_, pool, duid_, Allocator::PREFIX_LEN_GREATER, IOAddress("::"), 0);
+ prefixes.insert(candidate);
+ EXPECT_TRUE(subnet_->inPool(Lease::TYPE_PD, candidate));
+ EXPECT_TRUE(subnet_->inPool(Lease::TYPE_PD, candidate, cc_));
+ }
+ // Make sure that unique prefixes have been returned.
+ EXPECT_EQ(total, prefixes.size());
+ }
+}
+
+// Test allocating delegated prefixes from multiple pools.
+TEST_F(RandomAllocatorTest6, manyPdPoolsPreferrSmaller) {
+ RandomAllocator alloc(Lease::TYPE_PD, subnet_);
+
+ for (auto i = 0; i < 10; ++i) {
+ ostringstream s;
+ s << "300" << hex << i + 1 << "::";
+ auto pool = boost::make_shared<Pool6>(Lease::TYPE_PD,
+ IOAddress(s.str()),
+ 120,
+ 128);
+ subnet_->addPool(pool);
+ }
+
+ size_t total = 65536;
+
+ Pool6Ptr pool;
+
+ for (auto j = 0; j < 2; ++j) {
+ std::set<IOAddress> prefixes;
+ for (auto i = 0; i < total; ++i) {
+ IOAddress candidate = alloc.pickPrefix(cc_, pool, duid_, Allocator::PREFIX_LEN_SMALLER, IOAddress("::"), 120);
+ prefixes.insert(candidate);
+ EXPECT_TRUE(subnet_->inPool(Lease::TYPE_PD, candidate));
+ EXPECT_TRUE(subnet_->inPool(Lease::TYPE_PD, candidate, cc_));
+ }
+ // Make sure that unique prefixes have been returned.
+ EXPECT_EQ(total, prefixes.size());
+ }
+}
+
+// Test allocating delegated prefixes from multiple pools.
+TEST_F(RandomAllocatorTest6, manyPdPoolsPreferrEqual) {
+ RandomAllocator alloc(Lease::TYPE_PD, subnet_);
+
+ for (auto i = 0; i < 10; ++i) {
+ ostringstream s;
+ s << "300" << hex << i + 1 << "::";
+ auto pool = boost::make_shared<Pool6>(Lease::TYPE_PD,
+ IOAddress(s.str()),
+ 120,
+ 128);
+ subnet_->addPool(pool);
+ }
+
+ size_t total = 10 * 256;
+
+ Pool6Ptr pool;
+
+ for (auto j = 0; j < 2; ++j) {
+ std::set<IOAddress> prefixes;
+ for (auto i = 0; i < total; ++i) {
+ IOAddress candidate = alloc.pickPrefix(cc_, pool, duid_, Allocator::PREFIX_LEN_EQUAL, IOAddress("::"), 128);
+ prefixes.insert(candidate);
+ EXPECT_TRUE(subnet_->inPool(Lease::TYPE_PD, candidate));
+ EXPECT_TRUE(subnet_->inPool(Lease::TYPE_PD, candidate, cc_));
+ }
+ // Make sure that unique prefixes have been returned.
+ EXPECT_EQ(total, prefixes.size());
+ }
+}
+
+// Test allocating delegated prefixes from multiple pools.
+TEST_F(RandomAllocatorTest6, manyPdPoolsPreferrGreater) {
+ RandomAllocator alloc(Lease::TYPE_PD, subnet_);
+
+ for (auto i = 0; i < 10; ++i) {
+ ostringstream s;
+ s << "300" << hex << i + 1 << "::";
+ auto pool = boost::make_shared<Pool6>(Lease::TYPE_PD,
+ IOAddress(s.str()),
+ 120,
+ 128);
+ subnet_->addPool(pool);
+ }
+
+ size_t total = 10 * 256;
+
+ Pool6Ptr pool;
+
+ for (auto j = 0; j < 2; ++j) {
+ std::set<IOAddress> prefixes;
+ for (auto i = 0; i < total; ++i) {
+ IOAddress candidate = alloc.pickPrefix(cc_, pool, duid_, Allocator::PREFIX_LEN_GREATER, IOAddress("::"), 64);
prefixes.insert(candidate);
EXPECT_TRUE(subnet_->inPool(Lease::TYPE_PD, candidate));
EXPECT_TRUE(subnet_->inPool(Lease::TYPE_PD, candidate, cc_));
This debug message is issued when the server's connection filter rejects
a new connection based on the client's ip address.
-% TCP_CONNECTION_REJECTED_BY_FILTER connection from %1 has been denied by the connection filter.
-This debug message is issued when the server's connection filter rejects
-a new connection based on the client's ip address.
-
% TCP_CONNECTION_SHUTDOWN shutting down TCP connection from %1
This debug message is issued when one of the TCP connections is shut down.
The connection can be stopped as a result of an error or after the