]> git.ipfire.org Git - thirdparty/kea.git/commitdiff
[#1958] added unittests
authorRazvan Becheriu <razvan@isc.org>
Fri, 6 Jan 2023 11:27:18 +0000 (13:27 +0200)
committerRazvan Becheriu <razvan@isc.org>
Wed, 18 Jan 2023 15:12:01 +0000 (17:12 +0200)
src/bin/dhcp6/tests/dhcp6_srv_unittest.cc
src/lib/dhcpsrv/tests/alloc_engine4_unittest.cc
src/lib/dhcpsrv/tests/alloc_engine6_unittest.cc
src/lib/dhcpsrv/tests/alloc_engine_utils.cc
src/lib/dhcpsrv/tests/alloc_engine_utils.h
src/lib/dhcpsrv/tests/iterative_allocator_unittest.cc
src/lib/dhcpsrv/tests/random_allocator_unittest.cc
src/lib/tcp/tcp_messages.mes

index 07aabfda61d01f85cf3cc62c840e9deefb143ce1..6f827f73d55816a9f6865d35c382b3f7e761e8b4 100644 (file)
@@ -2088,8 +2088,8 @@ TEST_F(Dhcpv6SrvTest, ReleaseReject) {
     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
index 53c78b747e8f74c7e06c4900727dae71c59df1af..c013bdb158db92b173aa25cc5857f1e71cbe3b63 100644 (file)
@@ -1720,7 +1720,7 @@ TEST_F(AllocEngine4Test, requestReuseExpiredLease4) {
 // 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.
@@ -1757,7 +1757,7 @@ TEST_F(AllocEngine4Test, discoverReuseDeclinedLease4) {
 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.
@@ -1797,7 +1797,7 @@ TEST_F(AllocEngine4Test, discoverReuseDeclinedLease4Stats) {
 // 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.
@@ -1832,7 +1832,7 @@ TEST_F(AllocEngine4Test, requestReuseDeclinedLease4) {
 // 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.
@@ -2042,7 +2042,7 @@ TEST_F(AllocEngine4Test, reservedAddressNoHint) {
 // - 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(),
index 6d9a83496a79c840fc8fef4338f6b78a95e1b09f..006e586e6858f4b21f0ca2e95eb06e2781aead60 100644 (file)
@@ -2102,7 +2102,7 @@ TEST_F(AllocEngine6Test, largePdPool) {
     // 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);
@@ -2113,6 +2113,108 @@ TEST_F(AllocEngine6Test, largePdPool) {
     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
@@ -3227,6 +3329,71 @@ TEST_F(AllocEngine6Test, globalHostReservedPrefix) {
         << "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) {
@@ -3288,7 +3455,8 @@ 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)));
@@ -3307,6 +3475,71 @@ TEST_F(AllocEngine6Test, mixedHostReservedPrefix) {
     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);
@@ -3491,6 +3724,81 @@ TEST_F(AllocEngine6Test, bothHostReservedPrefix) {
         << "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.
@@ -3693,7 +4001,7 @@ TEST_F(AllocEngine6ExtendedInfoTest, updateExtendedInfo6) {
         " \"peer\": \"2001:db8::6\" } ] } }",
         true
     }
-};
+    };
 
     // Allocate a lease.
     Lease6Ptr lease;
@@ -4989,7 +5297,7 @@ TEST_F(AllocEngine6Test, getValidLifetime) {
             // 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;
@@ -5127,7 +5435,7 @@ TEST_F(AllocEngine6Test, getTemplateClassValidLifetime) {
             // 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;
@@ -5257,7 +5565,7 @@ TEST_F(AllocEngine6Test, getPreferredLifetime) {
             // 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;
@@ -5398,7 +5706,7 @@ TEST_F(AllocEngine6Test, getTemplateClassPreferredLifetime) {
             // 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;
index 2bca46fddb4114bc7502c786c288dd6dc304b05b..666a4eb3cebbe7109d73a45eb0f0c59271548afc 100644 (file)
@@ -225,7 +225,7 @@ AllocEngine6Test::createHost6HWAddr(bool add_to_host_mgr, IPv6Resrv::Type type,
 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();
 
@@ -235,7 +235,7 @@ AllocEngine6Test::allocateTest(AllocEngine& engine, const Pool6Ptr& pool,
                                     fake, query);
     ctx.currentIA().iaid_ = iaid_;
     ctx.currentIA().type_ = type;
-    ctx.currentIA().addHint(hint);
+    ctx.currentIA().addHint(hint, hint_prefix_length);
 
     Lease6Collection leases;
 
index 69c5167b1a1789e55b9625005c9d76d486d4a4c3..4ea2bf5de91ff468becc1f69f0e23229b15b4b90 100644 (file)
@@ -339,12 +339,15 @@ public:
     /// @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.
     ///
index bb13e2923f4dd3161b31ce02e05ade487549c444..7e53f6397cc002689bdc076a3402c1ce5e1e0764 100644 (file)
@@ -144,6 +144,60 @@ TEST_F(IterativeAllocatorTest6, clientClass) {
     }
 }
 
+// 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) {
@@ -371,6 +425,145 @@ TEST_F(IterativeAllocatorTest6, prefixStep) {
               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) {
@@ -608,60 +801,6 @@ TEST_F(IterativeAllocatorTest6, prefixIncrease) {
     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
index d795c5d276627c11fd0756c1a2e767522bc5f1e3..03cac06c8082c7bfe7b23bf8720c6129c39ee7da 100644 (file)
@@ -326,11 +326,13 @@ TEST_F(RandomAllocatorTest6, clientClasses) {
 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_));
@@ -345,7 +347,7 @@ TEST_F(RandomAllocatorTest6, manyPdPools) {
 
     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,
@@ -353,12 +355,107 @@ TEST_F(RandomAllocatorTest6, manyPdPools) {
         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_));
index 40dd700252ae2f6e9738058c042aaaf02b677468..6b6c77e53456d3542f2f4265198e99d42e7378f4 100644 (file)
@@ -34,10 +34,6 @@ error that should be submitted as a bug.
 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