.arg(ia->getIAID())
.arg(Lease::lifetimeToText(lease->valid_lft_));
} else {
- auto age = lease->valid_lft_ - lease->remaining_valid_lft_;
lease->valid_lft_ = lease->remaining_valid_lft_;
- lease->preferred_lft_ -= age;
+ lease->preferred_lft_ = lease->remaining_preferred_lft_;
LOG_INFO(lease6_logger, DHCP6_LEASE_REUSE)
.arg(query->getLabel())
.arg(lease->addr_.toText())
.arg(ia->getIAID())
.arg(Lease::lifetimeToText((*l)->valid_lft_));
} else {
- auto age = (*l)->valid_lft_ - (*l)->remaining_valid_lft_;
(*l)->valid_lft_ = (*l)->remaining_valid_lft_;
- (*l)->preferred_lft_ -= age;
+ (*l)->preferred_lft_ = (*l)->remaining_preferred_lft_;
LOG_INFO(lease6_logger, DHCP6_PD_LEASE_REUSE)
.arg(query->getLabel())
.arg((*l)->addr_.toText())
.arg((*l)->addr_.toText())
.arg(ia->getIAID());
} else {
- auto age = (*l)->valid_lft_ - (*l)->remaining_valid_lft_;
(*l)->valid_lft_ = (*l)->remaining_valid_lft_;
- (*l)->preferred_lft_ -= age;
+ (*l)->preferred_lft_ = (*l)->remaining_preferred_lft_;
LOG_INFO(lease6_logger, DHCP6_LEASE_REUSE)
.arg(query->getLabel())
.arg((*l)->addr_.toText())
.arg(static_cast<int>((*l)->prefixlen_))
.arg(ia->getIAID());
} else {
- auto age = (*l)->valid_lft_ - (*l)->remaining_valid_lft_;
(*l)->valid_lft_ = (*l)->remaining_valid_lft_;
- (*l)->preferred_lft_ -= age;
+ (*l)->preferred_lft_ = (*l)->remaining_preferred_lft_;
LOG_INFO(lease6_logger, DHCP6_PD_LEASE_REUSE)
.arg(query->getLabel())
.arg((*l)->addr_.toText())
}
void
-AllocEngine::setLeaseRemainingLife(Lease& lease, const SubnetPtr& subnet) const {
+AllocEngine::setLeaseRemainingLife(const Lease4Ptr& lease,
+ const ClientContext4& ctx) const {
// Sanity.
- lease.remaining_valid_lft_ = 0;
+ lease->remaining_valid_lft_ = 0;
+ const Subnet4Ptr& subnet = ctx.subnet_;
if (!subnet) {
return;
}
// Always reuse infinite lifetime leases.
- if (lease.valid_lft_ == Lease::INFINITY_LFT) {
- lease.remaining_valid_lft_ = Lease::INFINITY_LFT;
+ if (lease->valid_lft_ == Lease::INFINITY_LFT) {
+ lease->remaining_valid_lft_ = Lease::INFINITY_LFT;
+ return;
}
- // Refuse time going backward.
- if (lease.cltt_ > lease.current_cltt_) {
+ // Refuse time not going forward.
+ if (lease->cltt_ >= lease->current_cltt_) {
return;
}
- uint32_t age = lease.current_cltt_ - lease.cltt_;
+
+ uint32_t age = lease->current_cltt_ - lease->cltt_;
// Already expired.
- if (age > lease.current_valid_lft_) {
+ if (age >= lease->current_valid_lft_) {
return;
}
if ((threshold <= 0.) || (threshold > 1.)) {
return;
}
- max_age = lease.valid_lft_ * threshold;
+ max_age = lease->valid_lft_ * threshold;
if (age > max_age) {
return;
}
}
// Seems to be reusable.
- lease.remaining_valid_lft_ = lease.current_cltt_ - age;
+ lease->remaining_valid_lft_ = lease->current_valid_lft_ - age;
+}
+
+void
+AllocEngine::setLeaseRemainingLife(const Lease6Ptr& lease,
+ const ClientContext6& ctx) const {
+ // Sanity.
+ lease->remaining_valid_lft_ = 0;
+ const Subnet6Ptr& subnet = ctx.subnet_;
+ if (!subnet) {
+ return;
+ }
+
+ // Refuse time not going forward.
+ if (lease->cltt_ >= lease->current_cltt_) {
+ return;
+ }
+
+ uint32_t age = lease->current_cltt_ - lease->cltt_;
+ // Already expired.
+ if (age >= lease->current_valid_lft_) {
+ return;
+ }
+
+ // Try cache max age.
+ uint32_t max_age = 0;
+ if (!subnet->getCacheMaxAge().unspecified()) {
+ max_age = subnet->getCacheMaxAge().get();
+ if ((max_age == 0) || (age > max_age)) {
+ return;
+ }
+ }
+
+ // Try cache threshold.
+ if (!subnet->getCacheThreshold().unspecified()) {
+ double threshold = subnet->getCacheThreshold().get();
+ if ((threshold <= 0.) || (threshold > 1.)) {
+ return;
+ }
+ max_age = lease->valid_lft_ * threshold;
+ if (age > max_age) {
+ return;
+ }
+ }
+
+ // Seems to be reusable.
+ if ((lease->remaining_preferred_lft_ == Lease::INFINITY_LFT) ||
+ (lease->remaining_preferred_lft_ == 0)) {
+ // Keep these values.
+ } else if (lease->remaining_preferred_lft_ > age) {
+ lease->remaining_preferred_lft_ -= age;
+ } else {
+ // Can be a misconfiguration so stay safe...
+ return;
+ }
+ if (lease->current_valid_lft_ == Lease::INFINITY_LFT) {
+ lease->remaining_valid_lft_ = Lease::INFINITY_LFT;
+ } else {
+ lease->remaining_valid_lft_ = lease->current_valid_lft_ - age;
+ }
}
} // namespace dhcp
/// - the lease is not updated in the lease database.
/// - the previous value of the lease can be returned to the client.
///
- /// @param [in,out] lease The lease to be updated.
+ /// @param [in,out] lease A pointer to the lease to be updated.
/// @param subnet A pointer to the lease subnet.
- void setLeaseRemainingLife(Lease& lease, const SubnetPtr& subnet) const;
+ void setLeaseRemainingLife(const Lease4Ptr& lease,
+ const ClientContext4& ctx) const;
+
+ /// @brief Try to reuse an already allocated lease.
+ ///
+ /// This function computes and sets when acceptable the remaining
+ /// valid lifetime of an already allocated lease.
+ /// This uses the cache-threshold and cache-max-age parameters.
+ ///
+ /// A not zero value for the remaining valid lifetime means the
+ /// lease can reuse i.e.:
+ /// - the lease is not updated in the lease database.
+ /// - the previous value of the lease can be returned to the client.
+ ///
+ /// @note: there is no current_preferred_lft_ field in the lease
+ /// so the remaining_preferred_lft_ is used too for this:
+ /// - it must be set to the previous preferred lifetime before call.
+ /// - after call it must be ignored if remaining valid lifetime is zero.
+ ///
+ /// @param [in,out] lease A pointer to the lease to be updated.
+ /// @param subnet A pointer to the lease subnet.
+ void setLeaseRemainingLife(const Lease6Ptr& lease,
+ const ClientContext6& ctx) const;
private:
SubnetID subnet_id, const HWAddrPtr& hwaddr, uint8_t prefixlen)
: Lease(addr, valid, subnet_id, 0/*cltt*/, false, false, "", hwaddr),
type_(type), prefixlen_(prefixlen), iaid_(iaid), duid_(duid),
- preferred_lft_(preferred) {
+ preferred_lft_(preferred), remaining_preferred_lft_(0) {
if (!duid) {
isc_throw(InvalidOperation, "DUID is mandatory for an IPv6 lease");
}
: Lease(addr, valid, subnet_id, 0/*cltt*/,
fqdn_fwd, fqdn_rev, hostname, hwaddr),
type_(type), prefixlen_(prefixlen), iaid_(iaid), duid_(duid),
- preferred_lft_(preferred) {
+ preferred_lft_(preferred), remaining_preferred_lft_(0) {
if (!duid) {
isc_throw(InvalidOperation, "DUID is mandatory for an IPv6 lease");
}
Lease6::Lease6()
: Lease(isc::asiolink::IOAddress("::"), 0, 0, 0, false, false, "",
HWAddrPtr()), type_(TYPE_NA), prefixlen_(0), iaid_(0),
- duid_(DuidPtr()), preferred_lft_(0) {
+ duid_(DuidPtr()), preferred_lft_(0), remaining_preferred_lft_(0) {
}
std::string
prefixlen_ == other.prefixlen_ &&
iaid_ == other.iaid_ &&
preferred_lft_ == other.preferred_lft_ &&
+ remaining_preferred_lft_ == other.remaining_preferred_lft_ &&
valid_lft_ == other.valid_lft_ &&
current_valid_lft_ == other.current_valid_lft_ &&
remaining_valid_lft_ == other.remaining_valid_lft_ &&
/// @brief Client identifier
DuidPtr duid_;
- /// @brief preferred lifetime
+ /// @brief Preferred lifetime
///
/// This parameter specifies the preferred lifetime since the lease was
/// assigned or renewed (cltt), expressed in seconds.
uint32_t preferred_lft_;
+ /// @brief Remaining preferred lifetime
+ ///
+ /// Expressed as number of seconds since current time, also
+ /// preferred lifetime - age where age is old cltt - new cltt.
+ uint32_t remaining_preferred_lft_;
+
/// @todo: Add DHCPv6 failover related fields here
/// @brief Constructor