Commit 80985ac8 authored by Francis Dupont's avatar Francis Dupont
Browse files

[295-min-max-lease-time-configuration-options] checkpoint

parent da42fc31
......@@ -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();
......
......@@ -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<void>(allocated_resources_.insert(std::make_pair(prefix,
prefix_len)));
static_cast<void>(allocated_resources_.insert(Resource(prefix,
prefix_len)));
}
bool
AllocEngine::ClientContext6::
isAllocated(const asiolink::IOAddress& prefix, const uint8_t prefix_len) const {
return (static_cast<bool>
(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_;
......
// 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 <dhcp/pkt4.h>
#include <dhcp/pkt6.h>
#include <dhcp/option6_ia.h>
#include <dhcp/option6_iaaddr.h>
#include <dhcp/option6_iaprefix.h>
#include <dhcpsrv/host.h>
#include <dhcpsrv/subnet.h>
#include <dhcpsrv/lease_mgr.h>
......@@ -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<isc::asiolink::IOAddress, uint8_t> 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<ResourceType> HintContainer;
typedef std::vector<Resource> HintContainer;
/// @brief Container holding allocated prefixes or addresses.
typedef std::set<ResourceType> ResourceContainer;
typedef std::set<Resource, ResourceCompare> ResourceContainer;
/// @brief A tuple holding host identifier type and value.
typedef std::pair<Host::IdentifierType, std::vector<uint8_t> > 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.
......
......@@ -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.
......
// 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) {
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment