From: Francis Dupont Date: Thu, 16 May 2019 12:15:54 +0000 (+0200) Subject: [295-min-max-lease-time-configuration-options] checkpoint X-Git-Tag: Kea-1.6.0-beta2~252 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=80985ac8a71ed3dcab46ace54882c0f64e4d70b5;p=thirdparty%2Fkea.git [295-min-max-lease-time-configuration-options] checkpoint --- diff --git a/src/bin/dhcp6/dhcp6_srv.cc b/src/bin/dhcp6/dhcp6_srv.cc index 37ad8b9ffa..814e7a5cad 100644 --- a/src/bin/dhcp6/dhcp6_srv.cc +++ b/src/bin/dhcp6/dhcp6_srv.cc @@ -1065,11 +1065,12 @@ Dhcpv6Srv::buildCfgOptionList(const Pkt6Ptr& question, // Secondly, pool specific options. Pools are defined within a subnet, so // if there is no subnet, there is nothing to do. if (ctx.subnet_) { - BOOST_FOREACH(const AllocEngine::ResourceType& resource, - ctx.allocated_resources_) { - PoolPtr pool = ctx.subnet_->getPool(resource.second == 128 ? - Lease::TYPE_NA : Lease::TYPE_PD, - resource.first, false); + for (auto resource : ctx.allocated_resources_) { + PoolPtr pool = + ctx.subnet_->getPool(resource.getPrefixLength() == 128 ? + Lease::TYPE_NA : Lease::TYPE_PD, + resource.getAddress(), + false); if (pool && !pool->getCfgOption()->empty()) { co_list.push_back(pool->getCfgOption()); } @@ -1807,7 +1808,11 @@ Dhcpv6Srv::assignIA_NA(const Pkt6Ptr& query, const Pkt6Ptr& answer, // Set per-IA context values. ctx.createIAContext(); ctx.currentIA().iaid_ = ia->getIAID(); - ctx.currentIA().addHint(hint); + if (hint_opt) { + ctx.currentIA().addHint(hint_opt); + } else { + ctx.currentIA().addHint(hint); + } ctx.currentIA().type_ = Lease::TYPE_NA; // Use allocation engine to pick a lease for this client. Allocation engine @@ -1913,7 +1918,11 @@ Dhcpv6Srv::assignIA_PD(const Pkt6Ptr& query, const Pkt6Ptr& /*answer*/, // Set per-IA context values. ctx.createIAContext(); ctx.currentIA().iaid_ = ia->getIAID(); - ctx.currentIA().addHint(hint); + if (hint_opt) { + ctx.currentIA().addHint(hint_opt); + } else { + ctx.currentIA().addHint(hint); + } ctx.currentIA().type_ = Lease::TYPE_PD; // Use allocation engine to pick a lease for this client. Allocation engine @@ -2056,7 +2065,7 @@ Dhcpv6Srv::extendIA_NA(const Pkt6Ptr& query, const Pkt6Ptr& answer, // There's no way to protect against this. continue; } - ctx.currentIA().addHint(iaaddr->getAddress()); + ctx.currentIA().addHint(iaaddr); } Lease6Collection leases = alloc_engine_->renewLeases6(ctx); @@ -2095,7 +2104,7 @@ Dhcpv6Srv::extendIA_NA(const Pkt6Ptr& query, const Pkt6Ptr& answer, .arg(ia->getIAID()); // Now remove this prefix from the hints list. - AllocEngine::ResourceType hint_type((*l)->addr_, (*l)->prefixlen_); + AllocEngine::Resource hint_type((*l)->addr_, (*l)->prefixlen_); hints.erase(std::remove(hints.begin(), hints.end(), hint_type), hints.end()); } @@ -2114,7 +2123,7 @@ Dhcpv6Srv::extendIA_NA(const Pkt6Ptr& query, const Pkt6Ptr& answer, } // Now remove this address from the hints list. - AllocEngine::ResourceType hint_type((*l)->addr_, 128); + AllocEngine::Resource hint_type((*l)->addr_, 128); hints.erase(std::remove(hints.begin(), hints.end(), hint_type), hints.end()); // If the new FQDN settings have changed for the lease, we need to @@ -2138,7 +2147,7 @@ Dhcpv6Srv::extendIA_NA(const Pkt6Ptr& query, const Pkt6Ptr& answer, for (AllocEngine::HintContainer::const_iterator hint = hints.begin(); hint != hints.end(); ++hint) { Option6IAAddrPtr iaaddr(new Option6IAAddr(D6O_IAADDR, - hint->first, 0, 0)); + hint->getAddress(), 0, 0)); ia_rsp->addOption(iaaddr); } @@ -2231,7 +2240,7 @@ Dhcpv6Srv::extendIA_PD(const Pkt6Ptr& query, } // Put the client's prefix into the hints list. - ctx.currentIA().addHint(prf->getAddress(), prf->getLength()); + ctx.currentIA().addHint(prf); } // Call Allocation Engine and attempt to renew leases. Number of things @@ -2291,7 +2300,7 @@ Dhcpv6Srv::extendIA_PD(const Pkt6Ptr& query, .arg(ia->getIAID()); // Now remove this prefix from the hints list. - AllocEngine::ResourceType hint_type((*l)->addr_, (*l)->prefixlen_); + AllocEngine::Resource hint_type((*l)->addr_, (*l)->prefixlen_); hints.erase(std::remove(hints.begin(), hints.end(), hint_type), hints.end()); } @@ -2310,7 +2319,7 @@ Dhcpv6Srv::extendIA_PD(const Pkt6Ptr& query, } // Now remove this prefix from the hints list. - AllocEngine::ResourceType hint_type((*l)->addr_, (*l)->prefixlen_); + AllocEngine::Resource hint_type((*l)->addr_, (*l)->prefixlen_); hints.erase(std::remove(hints.begin(), hints.end(), hint_type), hints.end()); } @@ -2322,9 +2331,11 @@ Dhcpv6Srv::extendIA_PD(const Pkt6Ptr& query, // Send the prefix with the zero lifetimes only if the prefix // contains non-zero value. A zero value indicates that the hint was // for the prefix length. - if (!prefix->first.isV6Zero()) { - OptionPtr prefix_opt(new Option6IAPrefix(D6O_IAPREFIX, prefix->first, - prefix->second, 0, 0)); + if (!prefix->getAddress().isV6Zero()) { + OptionPtr prefix_opt(new Option6IAPrefix(D6O_IAPREFIX, + prefix->getAddress(), + prefix->getPrefixLength(), + 0, 0)); ia_rsp->addOption(prefix_opt); } } @@ -3502,13 +3513,12 @@ Dhcpv6Srv::requiredClassify(const Pkt6Ptr& pkt, AllocEngine::ClientContext6& ctx } // And finish by pools - BOOST_FOREACH(const AllocEngine::ResourceType& resource, - ctx.allocated_resources_) { - PoolPtr pool = ctx.subnet_->getPool(resource.second == 128 ? - Lease::TYPE_NA : - Lease::TYPE_PD, - resource.first, - false); + for (auto resource : ctx.allocated_resources_) { + PoolPtr pool = + ctx.subnet_->getPool(resource.getPrefixLength() == 128 ? + Lease::TYPE_NA : Lease::TYPE_PD, + resource.getAddress(), + false); if (pool) { const ClientClasses& to_add = pool->getRequiredClasses(); for (ClientClasses::const_iterator cclass = to_add.cbegin(); diff --git a/src/lib/dhcpsrv/alloc_engine.cc b/src/lib/dhcpsrv/alloc_engine.cc index 4b373fefb9..eda417398e 100644 --- a/src/lib/dhcpsrv/alloc_engine.cc +++ b/src/lib/dhcpsrv/alloc_engine.cc @@ -373,6 +373,16 @@ AllocEngine::AllocatorPtr AllocEngine::getAllocator(Lease::Type type) { return (alloc->second); } +AllocEngine::Resource::Resource(const Option6IAAddrPtr& iaaddr) + : address_(iaaddr->getAddress()), prefix_len_(128), + preferred_(iaaddr->getPreferred()), valid_(iaaddr->getValid()) { +} + +AllocEngine::Resource::Resource(const Option6IAPrefixPtr& iaprefix) + : address_(iaprefix->getAddress()), prefix_len_(iaprefix->getLength()), + preferred_(iaprefix->getPreferred()), valid_(iaprefix->getValid()) { +} + } // end of namespace isc::dhcp } // end of namespace isc @@ -461,23 +471,37 @@ AllocEngine::ClientContext6::IAContext::IAContext() void AllocEngine::ClientContext6:: IAContext::addHint(const asiolink::IOAddress& prefix, - const uint8_t prefix_len) { - hints_.push_back(std::make_pair(prefix, prefix_len)); + const uint8_t prefix_len, + const uint32_t preferred, + const uint32_t valid) { + hints_.push_back(Resource(prefix, prefix_len, preferred, valid)); +} + +void +AllocEngine::ClientContext6:: +IAContext::addHint(const Option6IAAddrPtr& iaaddr) { + hints_.push_back(Resource(iaaddr)); +} + +void +AllocEngine::ClientContext6:: +IAContext::addHint(const Option6IAPrefixPtr& iaprefix) { + hints_.push_back(Resource(iaprefix)); } void AllocEngine::ClientContext6:: addAllocatedResource(const asiolink::IOAddress& prefix, const uint8_t prefix_len) { - static_cast(allocated_resources_.insert(std::make_pair(prefix, - prefix_len))); + static_cast(allocated_resources_.insert(Resource(prefix, + prefix_len))); } bool AllocEngine::ClientContext6:: isAllocated(const asiolink::IOAddress& prefix, const uint8_t prefix_len) const { return (static_cast - (allocated_resources_.count(std::make_pair(prefix, prefix_len)))); + (allocated_resources_.count(Resource(prefix, prefix_len)))); } ConstHostPtr @@ -816,7 +840,7 @@ AllocEngine::allocateUnreservedLeases6(ClientContext6& ctx) { IOAddress hint = IOAddress::IPV6_ZERO_ADDRESS(); if (!ctx.currentIA().hints_.empty()) { /// @todo: We support only one hint for now - hint = ctx.currentIA().hints_[0].first; + hint = ctx.currentIA().hints_[0].getAddress(); } Subnet6Ptr original_subnet = ctx.subnet_; diff --git a/src/lib/dhcpsrv/alloc_engine.h b/src/lib/dhcpsrv/alloc_engine.h index f3fb6760f6..f228a9d3fb 100644 --- a/src/lib/dhcpsrv/alloc_engine.h +++ b/src/lib/dhcpsrv/alloc_engine.h @@ -1,4 +1,4 @@ -// Copyright (C) 2012-2018 Internet Systems Consortium, Inc. ("ISC") +// Copyright (C) 2012-2019 Internet Systems Consortium, Inc. ("ISC") // // This Source Code Form is subject to the terms of the Mozilla Public // License, v. 2.0. If a copy of the MPL was not distributed with this @@ -14,6 +14,8 @@ #include #include #include +#include +#include #include #include #include @@ -272,18 +274,125 @@ private: public: - /// @brief Defines a single hint (an address + prefix-length). + /// @brief Defines a single hint /// /// This is an entry that represents what the client had requested, /// either an address or a prefix. Prefix length is 128 for regular - /// addresses. - typedef std::pair ResourceType; + /// addresses. Optionally it provides wanted preferred and valid + /// lifetimes. + /// + /// @note Seems to be used only for DHCPv6. + class Resource { + public: + + /// @brief Default constructor. + /// + /// @param address the address or prefix + /// @param prefix_len the prefix length (128 for addresses) + /// @param preferred the optional preferred lifetime + /// @param valid the optional valid lifetime + Resource(const isc::asiolink::IOAddress& address, + const uint8_t prefix_len, + const uint32_t preferred = 0, + const uint32_t valid = 0) + : address_(address), prefix_len_(prefix_len), + preferred_(preferred), valid_(valid) { + } + + /// @brief Constructor from an IAADDR DHCPv6 option. + /// + /// @param iaaddr The pointer to the IAADDR option + Resource(const Option6IAAddrPtr& iaaddr); + + /// @brief Constructor from an IAPREFIX DHCPv6 option. + /// + /// @param iaprefix The pointer to the IAPREFIX option + Resource(const Option6IAPrefixPtr& iaprefix); + + /// @brief Returns the address. + /// + /// @return the address or prefix + isc::asiolink::IOAddress getAddress() const { + return (address_); + } + + /// @brief Returns the prefix length. + /// + /// @return the prefix length + uint8_t getPrefixLength() const { + return (prefix_len_); + } + + /// @brief Returns the optional preferred lifetime. + /// + /// @return the preferred lifetime (0 if not set) + uint32_t getPreferred() const { + return (preferred_); + } + + /// @brief Returns the optional valid lifetime. + /// + /// @return the valid lifetime (0 if not set) + uint32_t getValid() const { + return (valid_); + } + + /// @brief Compares two @c AllocEngine::Resource objects for equality. + /// + /// @param other object to be compared with this object + /// @return true if objects are equal, false otherwise. + bool equals(const Resource& other) const { + return (address_ == other.address_ && + prefix_len_ == other.prefix_len_); + } + + /// @brief Equality operator. + /// + /// @param other object to be compared with this object + /// @return true if objects are equal, false otherwise. + bool operator==(const Resource& other) const { + return (equals(other)); + } + + protected: + + /// @brief The address or prefix. + isc::asiolink::IOAddress address_; + + /// @brief The prefix length (128 for an address). + uint8_t prefix_len_; + + /// @brief The preferred lifetime (0 when not set). + uint32_t preferred_; + + /// @brief The valid lifetime (0 when not set). + uint32_t valid_; + }; + + /// @brief Resource compare class. + /// + /// Needed for using sets of Resource objets. + struct ResourceCompare { + /// @brief Compare operator + /// + /// @note Only the address/prefix part of resources is used. + /// @param lhr Left hand resource objet + /// @param rhr Right hand resource objet + /// @return true if lhr is less than rhr, false otherwise + bool operator() (const Resource& lhr, const Resource& rhr) const { + if (lhr.getAddress() == rhr.getAddress()) { + return (lhr.getPrefixLength() < rhr.getPrefixLength()); + } else { + return (lhr.getAddress() < rhr.getAddress()); + } + } + }; /// @brief Container for client's hints. - typedef std::vector HintContainer; + typedef std::vector HintContainer; /// @brief Container holding allocated prefixes or addresses. - typedef std::set ResourceContainer; + typedef std::set ResourceContainer; /// @brief A tuple holding host identifier type and value. typedef std::pair > IdentifierPair; @@ -428,8 +537,22 @@ public: /// /// @param prefix Prefix or address. /// @param prefix_len Prefix length. Default is 128 for addresses. + /// @param preferred Wanted preferred lifetime. Default 0. + /// @param valid Wanted valid lifetime. Default 0. void addHint(const asiolink::IOAddress& prefix, - const uint8_t prefix_len = 128); + const uint8_t prefix_len = 128, + const uint32_t preferred = 0, + const uint32_t valid = 0); + + /// @brief Convenience method adding new hint from IAADDR option. + /// + /// @param iaaddr Pointer to IAADDR. + void addHint(const Option6IAAddrPtr& iaaddr); + + /// @brief Convenience method adding new hint from IAPREFIX option. + /// + /// @param iaprefix Pointer to IAPREFIX. + void addHint(const Option6IAPrefixPtr& iaprefix); }; /// @brief Container holding IA specific contexts. diff --git a/src/lib/dhcpsrv/tests/alloc_engine6_unittest.cc b/src/lib/dhcpsrv/tests/alloc_engine6_unittest.cc index 39ef215470..eb68eaca02 100644 --- a/src/lib/dhcpsrv/tests/alloc_engine6_unittest.cc +++ b/src/lib/dhcpsrv/tests/alloc_engine6_unittest.cc @@ -28,8 +28,8 @@ TEST(ClientContext6Test, addHint) { ctx.currentIA().addHint(IOAddress("3000:1::"), 64); ASSERT_EQ(2, ctx.currentIA().hints_.size()); - EXPECT_EQ("2001:db8:1::1", ctx.currentIA().hints_[0].first.toText()); - EXPECT_EQ("3000:1::", ctx.currentIA().hints_[1].first.toText()); + EXPECT_EQ("2001:db8:1::1", ctx.currentIA().hints_[0].getAddress().toText()); + EXPECT_EQ("3000:1::", ctx.currentIA().hints_[1].getAddress().toText()); } // Test convenience method adding allocated prefixes and addresses to @@ -1031,7 +1031,7 @@ TEST_F(AllocEngine6Test, renewExtendLeaseLifetime) { // This is what the client will send in his renew message. AllocEngine::HintContainer hints; - hints.push_back(make_pair(IOAddress("2001:db8:1::15"), 128)); + hints.push_back(AllocEngine::Resource(IOAddress("2001:db8:1::15"), 128)); // Client should receive a lease. Lease6Collection renewed = renewTest(engine, pool_, hints, true); @@ -1064,7 +1064,7 @@ TEST_F(AllocEngine6Test, renewExtendLeaseLifetimeForReservation) { // This is what the client will send in his renew message. AllocEngine::HintContainer hints; - hints.push_back(make_pair(IOAddress("2001:db8:1::15"), 128)); + hints.push_back(AllocEngine::Resource(IOAddress("2001:db8:1::15"), 128)); // Client should receive a lease. Lease6Collection renewed = renewTest(engine, pool_, hints, true); @@ -1667,7 +1667,7 @@ TEST_F(AllocEngine6Test, addressRenewal) { // This is what the client will send in his renew message. AllocEngine::HintContainer hints; - hints.push_back(make_pair(leases[0]->addr_, 128)); + hints.push_back(AllocEngine::Resource(leases[0]->addr_, 128)); Lease6Collection renewed = renewTest(engine, pool_, hints, true); ASSERT_EQ(1, renewed.size()); @@ -1707,7 +1707,7 @@ TEST_F(AllocEngine6Test, reservedAddressRenewal) { // This is what the client will send in his renew message. AllocEngine::HintContainer hints; - hints.push_back(make_pair(leases[0]->addr_, 128)); + hints.push_back(AllocEngine::Resource(leases[0]->addr_, 128)); Lease6Collection renewed = renewTest(engine, pool_, hints, true); ASSERT_EQ(1, renewed.size()); @@ -1846,7 +1846,7 @@ TEST_F(AllocEngine6Test, reservedAddressRenewChange) { // This is what the client will send in his renew message. AllocEngine::HintContainer hints; - hints.push_back(make_pair(leases[0]->addr_, 128)); + hints.push_back(AllocEngine::Resource(leases[0]->addr_, 128)); // Create reservation for the client. This is in-pool reservation, // as the pool is 2001:db8:1::10 - 2001:db8:1::20. @@ -1870,7 +1870,7 @@ TEST_F(AllocEngine6Test, reservedAddressRenewReserved) { // This is what the client will send in his renew message. AllocEngine::HintContainer hints; - hints.push_back(make_pair(leases[0]->addr_, 128)); + hints.push_back(AllocEngine::Resource(leases[0]->addr_, 128)); // Create reservation for this address, but for another client. // This is in-pool reservation, as the pool is 2001:db8:1::10 - 2001:db8:1::20. @@ -2453,7 +2453,7 @@ TEST_F(SharedNetworkAlloc6Test, solicitSharedNetworkOutOfAddresses) { // Now, try requesting this address by providing a hint. The engine // should try to honor the hint even though we start from the subnet2. ctx.subnet_ = subnet2_; - ctx.currentIA().hints_.push_back(make_pair(IOAddress("2001:db8:1::1"), 128)); + ctx.currentIA().addHint(IOAddress("2001:db8:1::1")); ASSERT_NO_THROW(lease2 = expectOneLease(engine_.allocateLeases6(ctx))); ASSERT_TRUE(lease2); ASSERT_TRUE(subnet1_->inRange(lease2->addr_)); @@ -2830,7 +2830,7 @@ TEST_F(AllocEngine6Test, globalHostDynamicAddress) { // This is what the client will send in his renew message. AllocEngine::HintContainer hints; - hints.push_back(make_pair(IOAddress("2001:db8:1::10"), 128)); + hints.push_back(AllocEngine::Resource(IOAddress("2001:db8:1::10"), 128)); // Set test fixture hostname_ to the expected value. This gets checked in // renewTest. @@ -2893,7 +2893,7 @@ TEST_F(AllocEngine6Test, globalHostReservedAddress) { // This is what the client will send in his renew message. AllocEngine::HintContainer hints; - hints.push_back(make_pair(IOAddress("3001::1"), 128)); + hints.push_back(AllocEngine::Resource(IOAddress("3001::1"), 128)); // Set test fixture hostname_ to the expected value. This gets checked in // renewTest. @@ -2957,7 +2957,7 @@ TEST_F(AllocEngine6Test, globalHostReservedPrefix) { // This is what the client will send in his renew message. AllocEngine::HintContainer hints; - hints.push_back(make_pair(IOAddress("3001::"), 64)); + hints.push_back(AllocEngine::Resource(IOAddress("3001::"), 64)); // Set test fixture hostname_ to the expected value. This gets checked via // renewTest. diff --git a/src/lib/dhcpsrv/tests/alloc_engine_expiration_unittest.cc b/src/lib/dhcpsrv/tests/alloc_engine_expiration_unittest.cc index ab44236f12..1519163b23 100644 --- a/src/lib/dhcpsrv/tests/alloc_engine_expiration_unittest.cc +++ b/src/lib/dhcpsrv/tests/alloc_engine_expiration_unittest.cc @@ -1,4 +1,4 @@ -// Copyright (C) 2015-2018 Internet Systems Consortium, Inc. ("ISC") +// Copyright (C) 2015-2019 Internet Systems Consortium, Inc. ("ISC") // // This Source Code Form is subject to the terms of the Mozilla Public // License, v. 2.0. If a copy of the MPL was not distributed with this @@ -1422,7 +1422,7 @@ ExpirationAllocEngine6Test::testReclaimReusedLeases(const uint16_t msg_type, msg_type == DHCPV6_SOLICIT, Pkt6Ptr(new Pkt6(msg_type, 0x1234))); ctx.currentIA().iaid_ = 1; - ctx.currentIA().hints_.push_back(std::make_pair(leases_[i]->addr_, 128)); + ctx.currentIA().addHint(leases_[i]->addr_); // Depending on the message type, we will call a different function. if (msg_type == DHCPV6_RENEW) {