From: Francis Dupont Date: Sun, 19 May 2019 22:46:54 +0000 (+0200) Subject: [295-min-max-lease-time-configuration-options] Added alloc/renew DHCPv6 tests X-Git-Tag: Kea-1.6.0-beta2~246 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=5c3080f1827dc25f381326ffd7bdb11ee224bd8f;p=thirdparty%2Fkea.git [295-min-max-lease-time-configuration-options] Added alloc/renew DHCPv6 tests --- diff --git a/src/lib/dhcpsrv/tests/alloc_engine6_unittest.cc b/src/lib/dhcpsrv/tests/alloc_engine6_unittest.cc index eb68eaca02..1e1e348de8 100644 --- a/src/lib/dhcpsrv/tests/alloc_engine6_unittest.cc +++ b/src/lib/dhcpsrv/tests/alloc_engine6_unittest.cc @@ -26,10 +26,14 @@ TEST(ClientContext6Test, addHint) { AllocEngine::ClientContext6 ctx; ctx.currentIA().addHint(IOAddress("2001:db8:1::1")); ctx.currentIA().addHint(IOAddress("3000:1::"), 64); + ctx.currentIA().addHint(IOAddress("3001:2::"), 64, 100, 200); - ASSERT_EQ(2, ctx.currentIA().hints_.size()); + ASSERT_EQ(3, ctx.currentIA().hints_.size()); EXPECT_EQ("2001:db8:1::1", ctx.currentIA().hints_[0].getAddress().toText()); EXPECT_EQ("3000:1::", ctx.currentIA().hints_[1].getAddress().toText()); + EXPECT_EQ("3001:2::", ctx.currentIA().hints_[2].getAddress().toText()); + EXPECT_EQ(100, ctx.currentIA().hints_[2].getPreferred()); + EXPECT_EQ(200, ctx.currentIA().hints_[2].getValid()); } // Test convenience method adding allocated prefixes and addresses to @@ -100,6 +104,26 @@ TEST_F(AllocEngine6Test, simpleAlloc6) { EXPECT_TRUE(testStatistics("assigned-nas", 2, subnet_->getID())); } +// This test checks that simple allocation uses default lifetimes. +TEST_F(AllocEngine6Test, defaultAlloc6) { + simpleAlloc6Test(pool_, IOAddress("::"), 0, 0, 300, 400); +} + +// This test checks that simple allocation uses specified lifetimes. +TEST_F(AllocEngine6Test, hintAlloc6) { + simpleAlloc6Test(pd_pool_, IOAddress("::"), 301, 399, 301, 399); +} + +// This test checks that simple allocation uses min lifetimes. +TEST_F(AllocEngine6Test, minAlloc6) { + simpleAlloc6Test(pool_, IOAddress("::"), 100, 200, 200, 300); +} + +// This test checks that simple allocation uses max lifetimes. +TEST_F(AllocEngine6Test, maxAlloc6) { + simpleAlloc6Test(pd_pool_, IOAddress("::"), 500, 600, 400, 500); +} + // This test checks if the simple PD allocation (REQUEST) can succeed // and the stats counter is properly bumped by 1 TEST_F(AllocEngine6Test, pdSimpleAlloc6) { @@ -889,6 +913,190 @@ TEST_F(AllocEngine6Test, solicitReuseExpiredLease6) { EXPECT_TRUE(testStatistics("reclaimed-leases", 0, subnet_->getID())); } +// This test checks if an expired lease can be reused using default lifetimes. +TEST_F(AllocEngine6Test, defaultReuseExpiredLease6) { + boost::scoped_ptr engine; + ASSERT_NO_THROW(engine.reset(new AllocEngine(AllocEngine::ALLOC_ITERATIVE, 100))); + ASSERT_TRUE(engine); + + IOAddress addr("2001:db8:1::ad"); + + // Create one subnet with a pool holding one address. + initSubnet(IOAddress("2001:db8:1::"), addr, addr); + subnet_->setPreferred(Triplet(200, 300, 400)); + subnet_->setValid(Triplet(300, 400, 500)); + + // Initialize FQDN data for the lease. + initFqdn("myhost.example.com", true, true); + + // Just a different duid + DuidPtr other_duid = DuidPtr(new DUID(vector(12, 0xff))); + const uint32_t other_iaid = 3568; + Lease6Ptr lease(new Lease6(Lease::TYPE_NA, addr, other_duid, other_iaid, + 501, 502, 503, 504, subnet_->getID(), + HWAddrPtr(), 0)); + lease->cltt_ = time(NULL) - 500; // Allocated 500 seconds ago + lease->valid_lft_ = 495; // Lease was valid for 495 seconds + ASSERT_TRUE(LeaseMgrFactory::instance().addLease(lease)); + + // Make sure that we really created expired lease + ASSERT_TRUE(lease->expired()); + + // Asking specifically for this address with zero lifetimes + AllocEngine::ClientContext6 ctx2(subnet_, duid_, false, false, "", true, + Pkt6Ptr(new Pkt6(DHCPV6_REQUEST, 1234))); + ctx2.currentIA().iaid_ = iaid_; + ctx2.currentIA().addHint(addr, 128, 0, 0); + + EXPECT_NO_THROW(lease = expectOneLease(engine->allocateLeases6(ctx2))); + + // Check that we got that single lease + ASSERT_TRUE(lease); + EXPECT_EQ(addr, lease->addr_); + + // Check lifetimes: defaults are expected. + EXPECT_EQ(300, lease->preferred_lft_); + EXPECT_EQ(400, lease->valid_lft_); +} + +// This test checks if an expired lease can be reused using specified lifetimes. +TEST_F(AllocEngine6Test, hintReuseExpiredLease6) { + boost::scoped_ptr engine; + ASSERT_NO_THROW(engine.reset(new AllocEngine(AllocEngine::ALLOC_ITERATIVE, 100))); + ASSERT_TRUE(engine); + + IOAddress addr("2001:db8:1::ad"); + + // Create one subnet with a pool holding one address. + initSubnet(IOAddress("2001:db8:1::"), addr, addr); + subnet_->setPreferred(Triplet(200, 300, 400)); + subnet_->setValid(Triplet(300, 400, 500)); + + // Initialize FQDN data for the lease. + initFqdn("myhost.example.com", true, true); + + // Just a different duid + DuidPtr other_duid = DuidPtr(new DUID(vector(12, 0xff))); + const uint32_t other_iaid = 3568; + Lease6Ptr lease(new Lease6(Lease::TYPE_NA, addr, other_duid, other_iaid, + 501, 502, 503, 504, subnet_->getID(), + HWAddrPtr(), 0)); + lease->cltt_ = time(NULL) - 500; // Allocated 500 seconds ago + lease->valid_lft_ = 495; // Lease was valid for 495 seconds + ASSERT_TRUE(LeaseMgrFactory::instance().addLease(lease)); + + // Make sure that we really created expired lease + ASSERT_TRUE(lease->expired()); + + // Asking specifically for this address with zero lifetimes + AllocEngine::ClientContext6 ctx2(subnet_, duid_, false, false, "", true, + Pkt6Ptr(new Pkt6(DHCPV6_REQUEST, 1234))); + ctx2.currentIA().iaid_ = iaid_; + ctx2.currentIA().addHint(addr, 128, 299, 401); + + EXPECT_NO_THROW(lease = expectOneLease(engine->allocateLeases6(ctx2))); + + // Check that we got that single lease + ASSERT_TRUE(lease); + EXPECT_EQ(addr, lease->addr_); + + // Check lifetimes: specified values are expected. + EXPECT_EQ(299, lease->preferred_lft_); + EXPECT_EQ(401, lease->valid_lft_); +} + +// This test checks if an expired lease can be reused using min lifetimes. +TEST_F(AllocEngine6Test, minReuseExpiredLease6) { + boost::scoped_ptr engine; + ASSERT_NO_THROW(engine.reset(new AllocEngine(AllocEngine::ALLOC_ITERATIVE, 100))); + ASSERT_TRUE(engine); + + IOAddress addr("2001:db8:1::ad"); + + // Create one subnet with a pool holding one address. + initSubnet(IOAddress("2001:db8:1::"), addr, addr); + subnet_->setPreferred(Triplet(200, 300, 400)); + subnet_->setValid(Triplet(300, 400, 500)); + + // Initialize FQDN data for the lease. + initFqdn("myhost.example.com", true, true); + + // Just a different duid + DuidPtr other_duid = DuidPtr(new DUID(vector(12, 0xff))); + const uint32_t other_iaid = 3568; + Lease6Ptr lease(new Lease6(Lease::TYPE_NA, addr, other_duid, other_iaid, + 501, 502, 503, 504, subnet_->getID(), + HWAddrPtr(), 0)); + lease->cltt_ = time(NULL) - 500; // Allocated 500 seconds ago + lease->valid_lft_ = 495; // Lease was valid for 495 seconds + ASSERT_TRUE(LeaseMgrFactory::instance().addLease(lease)); + + // Make sure that we really created expired lease + ASSERT_TRUE(lease->expired()); + + // Asking specifically for this address with zero lifetimes + AllocEngine::ClientContext6 ctx2(subnet_, duid_, false, false, "", true, + Pkt6Ptr(new Pkt6(DHCPV6_REQUEST, 1234))); + ctx2.currentIA().iaid_ = iaid_; + ctx2.currentIA().addHint(addr, 128, 100, 200); + + EXPECT_NO_THROW(lease = expectOneLease(engine->allocateLeases6(ctx2))); + + // Check that we got that single lease + ASSERT_TRUE(lease); + EXPECT_EQ(addr, lease->addr_); + + // Check lifetimes: min values are expected. + EXPECT_EQ(200, lease->preferred_lft_); + EXPECT_EQ(300, lease->valid_lft_); +} + +// This test checks if an expired lease can be reused using max lifetimes. +TEST_F(AllocEngine6Test, maxReuseExpiredLease6) { + boost::scoped_ptr engine; + ASSERT_NO_THROW(engine.reset(new AllocEngine(AllocEngine::ALLOC_ITERATIVE, 100))); + ASSERT_TRUE(engine); + + IOAddress addr("2001:db8:1::ad"); + + // Create one subnet with a pool holding one address. + initSubnet(IOAddress("2001:db8:1::"), addr, addr); + subnet_->setPreferred(Triplet(200, 300, 400)); + subnet_->setValid(Triplet(300, 400, 500)); + + // Initialize FQDN data for the lease. + initFqdn("myhost.example.com", true, true); + + // Just a different duid + DuidPtr other_duid = DuidPtr(new DUID(vector(12, 0xff))); + const uint32_t other_iaid = 3568; + Lease6Ptr lease(new Lease6(Lease::TYPE_NA, addr, other_duid, other_iaid, + 501, 502, 503, 504, subnet_->getID(), + HWAddrPtr(), 0)); + lease->cltt_ = time(NULL) - 500; // Allocated 500 seconds ago + lease->valid_lft_ = 495; // Lease was valid for 495 seconds + ASSERT_TRUE(LeaseMgrFactory::instance().addLease(lease)); + + // Make sure that we really created expired lease + ASSERT_TRUE(lease->expired()); + + // Asking specifically for this address with zero lifetimes + AllocEngine::ClientContext6 ctx2(subnet_, duid_, false, false, "", true, + Pkt6Ptr(new Pkt6(DHCPV6_REQUEST, 1234))); + ctx2.currentIA().iaid_ = iaid_; + ctx2.currentIA().addHint(addr, 128, 500, 600); + + EXPECT_NO_THROW(lease = expectOneLease(engine->allocateLeases6(ctx2))); + + // Check that we got that single lease + ASSERT_TRUE(lease); + EXPECT_EQ(addr, lease->addr_); + + // Check lifetimes: max values are expected. + EXPECT_EQ(400, lease->preferred_lft_); + EXPECT_EQ(500, lease->valid_lft_); +} + // This test checks if an expired lease can be reused in REQUEST (actual allocation) TEST_F(AllocEngine6Test, requestReuseExpiredLease6) { boost::scoped_ptr engine; @@ -1042,6 +1250,146 @@ TEST_F(AllocEngine6Test, renewExtendLeaseLifetime) { << "Lease lifetime was not extended, but it should"; } +// Checks that a renewed lease uses default lifetimes. +TEST_F(AllocEngine6Test, defaultRenewLeaseLifetime) { + // Create a lease for the client. + Lease6Ptr lease(new Lease6(Lease::TYPE_NA, IOAddress("2001:db8:1::15"), + duid_, iaid_, 300, 400, 100, 200, + subnet_->getID(), HWAddrPtr(), 128)); + + // Allocated 200 seconds ago - half of the lifetime. + time_t lease_cltt = time(NULL) - 200; + lease->cltt_ = lease_cltt; + + ASSERT_TRUE(LeaseMgrFactory::instance().addLease(lease)); + + AllocEngine engine(AllocEngine::ALLOC_ITERATIVE, 100); + subnet_->setPreferred(Triplet(200, 300, 400)); + subnet_->setValid(Triplet(300, 400, 500)); + + // This is what the client will send in his renew message. + AllocEngine::HintContainer hints; + hints.push_back(AllocEngine::Resource(IOAddress("2001:db8:1::15"), + 128, 0, 0)); + + // Client should receive a lease. + Lease6Collection renewed = renewTest(engine, 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"; + + // Checks that default values are used for lifetimes. + EXPECT_EQ(300, renewed[0]->preferred_lft_); + EXPECT_EQ(400, renewed[0]->valid_lft_); +} + +// Checks that a renewed lease uses specified lifetimes. +TEST_F(AllocEngine6Test, hintRenewLeaseLifetime) { + // Create a lease for the client. + Lease6Ptr lease(new Lease6(Lease::TYPE_NA, IOAddress("2001:db8:1::15"), + duid_, iaid_, 300, 400, 100, 200, + subnet_->getID(), HWAddrPtr(), 128)); + + // Allocated 200 seconds ago - half of the lifetime. + time_t lease_cltt = time(NULL) - 200; + lease->cltt_ = lease_cltt; + + ASSERT_TRUE(LeaseMgrFactory::instance().addLease(lease)); + + AllocEngine engine(AllocEngine::ALLOC_ITERATIVE, 100); + subnet_->setPreferred(Triplet(200, 300, 400)); + subnet_->setValid(Triplet(300, 400, 500)); + + // This is what the client will send in his renew message. + AllocEngine::HintContainer hints; + hints.push_back(AllocEngine::Resource(IOAddress("2001:db8:1::15"), + 128, 301, 399)); + + // Client should receive a lease. + Lease6Collection renewed = renewTest(engine, 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"; + + // Checks that specified values are used for lifetimes. + EXPECT_EQ(301, renewed[0]->preferred_lft_); + EXPECT_EQ(399, renewed[0]->valid_lft_); +} + +// Checks that a renewed lease uses min lifetimes. +TEST_F(AllocEngine6Test, minRenewLeaseLifetime) { + // Create a lease for the client. + Lease6Ptr lease(new Lease6(Lease::TYPE_NA, IOAddress("2001:db8:1::15"), + duid_, iaid_, 300, 400, 100, 200, + subnet_->getID(), HWAddrPtr(), 128)); + + // Allocated 200 seconds ago - half of the lifetime. + time_t lease_cltt = time(NULL) - 200; + lease->cltt_ = lease_cltt; + + ASSERT_TRUE(LeaseMgrFactory::instance().addLease(lease)); + + AllocEngine engine(AllocEngine::ALLOC_ITERATIVE, 100); + subnet_->setPreferred(Triplet(200, 300, 400)); + subnet_->setValid(Triplet(300, 400, 500)); + + // This is what the client will send in his renew message. + AllocEngine::HintContainer hints; + hints.push_back(AllocEngine::Resource(IOAddress("2001:db8:1::15"), + 128, 100, 200)); + + // Client should receive a lease. + Lease6Collection renewed = renewTest(engine, 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"; + + // Checks that min values are used for lifetimes. + EXPECT_EQ(200, renewed[0]->preferred_lft_); + EXPECT_EQ(300, renewed[0]->valid_lft_); +} + +// Checks that a renewed lease uses max lifetimes. +TEST_F(AllocEngine6Test, maxRenewLeaseLifetime) { + // Create a lease for the client. + Lease6Ptr lease(new Lease6(Lease::TYPE_NA, IOAddress("2001:db8:1::15"), + duid_, iaid_, 300, 400, 100, 200, + subnet_->getID(), HWAddrPtr(), 128)); + + // Allocated 200 seconds ago - half of the lifetime. + time_t lease_cltt = time(NULL) - 200; + lease->cltt_ = lease_cltt; + + ASSERT_TRUE(LeaseMgrFactory::instance().addLease(lease)); + + AllocEngine engine(AllocEngine::ALLOC_ITERATIVE, 100); + subnet_->setPreferred(Triplet(200, 300, 400)); + subnet_->setValid(Triplet(300, 400, 500)); + + // This is what the client will send in his renew message. + AllocEngine::HintContainer hints; + hints.push_back(AllocEngine::Resource(IOAddress("2001:db8:1::15"), + 128, 500, 600)); + + // Client should receive a lease. + Lease6Collection renewed = renewTest(engine, 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"; + + // Checks that max values are used for lifetimes. + EXPECT_EQ(400, renewed[0]->preferred_lft_); + EXPECT_EQ(500, renewed[0]->valid_lft_); +} + // Checks if the lease lifetime is extended when the client sends the // Renew and the client has a reservation for the lease. TEST_F(AllocEngine6Test, renewExtendLeaseLifetimeForReservation) { diff --git a/src/lib/dhcpsrv/tests/alloc_engine_utils.cc b/src/lib/dhcpsrv/tests/alloc_engine_utils.cc index 2e4960684f..b283f6c999 100644 --- a/src/lib/dhcpsrv/tests/alloc_engine_utils.cc +++ b/src/lib/dhcpsrv/tests/alloc_engine_utils.cc @@ -270,6 +270,58 @@ AllocEngine6Test::simpleAlloc6Test(const Pool6Ptr& pool, const IOAddress& hint, return (simpleAlloc6Test(pool, duid_, hint, fake, in_pool)); } +Lease6Ptr +AllocEngine6Test::simpleAlloc6Test(const Pool6Ptr& pool, const IOAddress& hint, + uint32_t preferred, uint32_t valid, + uint32_t exp_preferred, uint32_t exp_valid) { + Lease::Type type = pool->getType(); + uint8_t expected_len = pool->getLength(); + + boost::scoped_ptr 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()); + } + + Pkt6Ptr query(new Pkt6(DHCPV6_REQUEST, 1234)); + + AllocEngine::ClientContext6 ctx(subnet_, duid_, false, false, "", false, query); + ctx.hwaddr_ = hwaddr_; + ctx.addHostIdentifier(Host::IDENT_HWADDR, hwaddr_->hwaddr_); + ctx.currentIA().iaid_ = iaid_; + ctx.currentIA().type_ = type; + ctx.currentIA().addHint(hint, expected_len, preferred, valid); + subnet_->setPreferred(Triplet(200, 300, 400)); + subnet_->setValid(Triplet(300, 400, 500)); + + // Set some non-standard callout status to make sure it doesn't affect the + // allocation. + ctx.callout_handle_ = HooksManager::createCalloutHandle(); + ctx.callout_handle_->setStatus(CalloutHandle::NEXT_STEP_SKIP); + + findReservation(*engine, ctx); + Lease6Ptr lease; + EXPECT_NO_THROW(lease = expectOneLease(engine->allocateLeases6(ctx))); + + // Check that we got a lease + EXPECT_TRUE(lease); + if (!lease) { + return (Lease6Ptr()); + } + + // Do all checks on the lease + checkLease6(duid_, lease, type, expected_len, true, true); + + // Check expected preferred and valid lifetimes. + EXPECT_EQ(exp_preferred, lease->preferred_lft_); + EXPECT_EQ(exp_valid, lease->valid_lft_); + + return (lease); +} + Lease6Ptr AllocEngine6Test::simpleAlloc6Test(const Pool6Ptr& pool, const DuidPtr& duid, const IOAddress& hint, bool fake, bool in_pool) { diff --git a/src/lib/dhcpsrv/tests/alloc_engine_utils.h b/src/lib/dhcpsrv/tests/alloc_engine_utils.h index c9da292833..ad148b0611 100644 --- a/src/lib/dhcpsrv/tests/alloc_engine_utils.h +++ b/src/lib/dhcpsrv/tests/alloc_engine_utils.h @@ -269,6 +269,22 @@ public: const asiolink::IOAddress& hint, bool fake, bool in_pool = true); + /// @brief Checks if the simple allocation can succeed with lifetimes. + /// + /// 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 preferred preferred lifetime to be used as a hint + /// @param valid valid lifetime to be used as a hint + /// @param exp_preferred expected lease preferred lifetime + /// @param exp_valid expected lease valid lifetime + /// @return allocated lease (or NULL) + Lease6Ptr simpleAlloc6Test(const Pool6Ptr& pool, + const asiolink::IOAddress& hint, + uint32_t preferred, uint32_t valid, + uint32_t exp_preferred, uint32_t exp_valid); + /// @brief Checks if the simple allocation can succeed for custom DUID. /// /// The type of lease is determined by pool type (pool->getType())