36#include <boost/foreach.hpp>
37#include <boost/make_shared.hpp>
54namespace ph = std::placeholders;
59struct AllocEngineHooks {
60 int hook_index_lease4_select_;
61 int hook_index_lease4_renew_;
62 int hook_index_lease4_expire_;
63 int hook_index_lease4_recover_;
64 int hook_index_lease6_select_;
65 int hook_index_lease6_renew_;
66 int hook_index_lease6_rebind_;
67 int hook_index_lease6_expire_;
68 int hook_index_lease6_recover_;
88AllocEngineHooks
Hooks;
96 : attempts_(attempts), incomplete_v4_reclamations_(0),
97 incomplete_v6_reclamations_(0) {
100 hook_index_lease4_select_ =
Hooks.hook_index_lease4_select_;
101 hook_index_lease6_select_ =
Hooks.hook_index_lease6_select_;
128 if (
CfgMgr::instance().getCurrentCfg()->getCfgDbAccess()->getIPReservationsUnique()) {
133 reserved.push_back(host);
144 reserved.insert(reserved.end(), hosts.begin(), hosts.end());
163 const IOAddress& address,
bool check_subnet) {
167 auto const& classes = ctx.
query_->getClasses();
169 while (current_subnet) {
170 if (current_subnet->clientSupported(classes)) {
172 if (current_subnet->inPool(lease_type, address)) {
176 if (current_subnet->inPool(lease_type, address, classes)) {
182 current_subnet = current_subnet->getNextSubnet(ctx.
subnet_);
209 const std::string& hostname,
210 const bool fake_allocation,
218 ias_(), ddns_params_() {
234 const uint8_t prefix_len,
235 const uint32_t preferred,
236 const uint32_t valid) {
246 addHint(iaaddr->getAddress(), 128,
247 iaaddr->getPreferred(), iaaddr->getValid());
256 addHint(iaprefix->getAddress(), iaprefix->getLength(),
257 iaprefix->getPreferred(), iaprefix->getValid());
263 const uint8_t prefix_len) {
270 const uint8_t prefix_len)
const {
278 const uint8_t prefix_len) {
286 return (
static_cast<bool>
293 if (subnet && subnet->getReservationsInSubnet()) {
294 auto host =
hosts_.find(subnet->getID());
295 if (host !=
hosts_.cend()) {
296 return (host->second);
306 if (subnet &&
subnet_->getReservationsGlobal()) {
307 auto host =
hosts_.find(SUBNET_ID_GLOBAL);
308 if (host !=
hosts_.cend()) {
309 return (host->second);
319 return (ghost && ghost->hasReservation(resv));
325 if (ddns_params_ &&
subnet_ && (
subnet_->getID() == ddns_params_->getSubnetId())) {
326 return (ddns_params_);
332 return (ddns_params_);
351 !subnet->getReservationsInSubnet()) {
357 subnet->getReservationsGlobal()) {
360 ctx.
hosts_[SUBNET_ID_GLOBAL] = ghost;
363 if (!subnet->getReservationsInSubnet()) {
369 std::map<SubnetID, ConstHostPtr> host_map;
371 subnet->getSharedNetwork(network);
380 const bool use_single_query = network &&
384 if (use_single_query) {
388 id_pair.second.size());
392 for (
auto const& host : hosts) {
393 if (host->getIPv6SubnetID() != SUBNET_ID_GLOBAL) {
394 host_map[host->getIPv6SubnetID()] = host;
400 auto const& classes = ctx.
query_->getClasses();
407 if (subnet->clientSupported(classes) && subnet->getReservationsInSubnet()) {
410 if (use_single_query) {
411 if (host_map.count(subnet->getID()) > 0) {
412 ctx.
hosts_[subnet->getID()] = host_map[subnet->getID()];
420 id_pair.second.size());
423 ctx.
hosts_[subnet->getID()] = host;
433 subnet = subnet->getNextSubnet(ctx.
subnet_, classes);
439 for (
auto const& host : ctx.
hosts_) {
440 host.second->encapsulateOptions();
450 &id_pair.second[0], id_pair.second.size());
484 for (
auto const& l : all_leases) {
486 ((l)->subnet_id_ == subnet->getID())) {
491 subnet = subnet->getNextSubnet(ctx.
subnet_);
511 if (leases.empty() && !ctx.
hosts_.empty()) {
515 .arg(ctx.
query_->getLabel());
520 allocateReservedLeases6(ctx, leases);
522 leases = updateLeaseData(ctx, leases);
537 }
else if (!leases.empty() && ctx.
hosts_.empty()) {
541 .arg(ctx.
query_->getLabel());
545 removeNonmatchingReservedLeases6(ctx, leases);
547 leases = updateLeaseData(ctx, leases);
556 }
else if (!leases.empty() && !ctx.
hosts_.empty()) {
560 .arg(ctx.
query_->getLabel());
564 allocateReservedLeases6(ctx, leases);
576 removeNonmatchingReservedLeases6(ctx, leases);
585 removeNonreservedLeases6(ctx, leases);
590 leases = updateLeaseData(ctx, leases);
603 if (leases.empty()) {
617 .arg(ctx.
query_->getLabel());
619 leases = allocateUnreservedLeases6(ctx);
622 if (!leases.empty()) {
626 for (
auto const& lease : leases) {
640 .arg(ctx.
query_->getLabel())
653 uint8_t hint_prefix_length = 128;
654 if (!ctx.currentIA().hints_.empty()) {
656 hint = ctx.currentIA().hints_[0].getAddress();
657 hint_prefix_length = ctx.currentIA().hints_[0].getPrefixLength();
666 uint64_t total_attempts = 0;
670 uint64_t subnets_with_unavail_leases = 0;
673 uint64_t subnets_with_unavail_pools = 0;
683 bool search_hint_lease =
true;
690 if (hint_prefix_length == 128) {
691 hint_prefix_length = 0;
693 if (!hint_prefix_length) {
701 Lease6Ptr lease = allocateBestMatch(ctx, hint_lease, search_hint_lease,
702 hint, hint_prefix_length, subnet,
703 network, total_attempts,
704 subnets_with_unavail_leases,
705 subnets_with_unavail_pools,
706 callout_status, prefix_length_match);
714 lease = allocateBestMatch(ctx, hint_lease, search_hint_lease, hint,
715 hint_prefix_length, subnet, network,
716 total_attempts, subnets_with_unavail_leases,
717 subnets_with_unavail_pools, callout_status,
718 prefix_length_match);
727 lease = allocateBestMatch(ctx, hint_lease, search_hint_lease, hint,
728 hint_prefix_length, subnet, network,
729 total_attempts, subnets_with_unavail_leases,
730 subnets_with_unavail_pools, callout_status,
731 prefix_length_match);
735 leases.push_back(lease);
739 auto const& classes = ctx.query_->getClasses();
745 .arg(ctx.query_->getLabel())
746 .arg(network->getName())
747 .arg(subnets_with_unavail_leases)
748 .arg(subnets_with_unavail_pools);
750 static_cast<int64_t
>(1));
753 "v6-allocation-fail-shared-network"),
754 static_cast<int64_t
>(1));
758 std::string shared_network = ctx.subnet_->getSharedNetworkName();
759 if (shared_network.empty()) {
760 shared_network =
"(none)";
763 .arg(ctx.query_->getLabel())
764 .arg(ctx.subnet_->toText())
765 .arg(ctx.subnet_->getID())
766 .arg(shared_network);
768 static_cast<int64_t
>(1));
771 "v6-allocation-fail-subnet"),
772 static_cast<int64_t
>(1));
774 if (total_attempts == 0) {
780 .arg(ctx.query_->getLabel());
782 static_cast<int64_t
>(1));
785 "v6-allocation-fail-no-pools"),
786 static_cast<int64_t
>(1));
793 .arg(ctx.query_->getLabel())
794 .arg(total_attempts);
796 static_cast<int64_t
>(1));
799 "v6-allocation-fail"),
800 static_cast<int64_t
>(1));
803 if (!classes.empty()) {
805 .arg(ctx.query_->getLabel())
806 .arg(classes.toText());
808 static_cast<int64_t
>(1));
811 "v6-allocation-fail-classes"),
812 static_cast<int64_t
>(1));
822 bool& search_hint_lease,
823 const isc::asiolink::IOAddress& hint,
824 uint8_t hint_prefix_length,
827 uint64_t& total_attempts,
828 uint64_t& subnets_with_unavail_leases,
829 uint64_t& subnets_with_unavail_pools,
832 auto const& classes = ctx.query_->getClasses();
837 if (!search_hint_lease) {
838 usable_hint_lease = hint_lease;
840 for (; subnet; subnet = subnet->getNextSubnet(original_subnet)) {
841 if (!subnet->clientSupported(classes)) {
845 ctx.subnet_ = subnet;
849 pool = boost::dynamic_pointer_cast<Pool6>
850 (subnet->getPool(ctx.currentIA().type_, classes, hint));
853 if (!pool || !pool->clientSupported(classes)) {
859 hint_prefix_length)) {
863 bool in_subnet = subnet->getReservationsInSubnet();
866 if (search_hint_lease) {
867 search_hint_lease =
false;
869 usable_hint_lease = hint_lease;
871 if (!usable_hint_lease) {
883 (!subnet->getReservationsOutOfPool() ||
884 !subnet->inPool(ctx.currentIA().type_, hint))) {
885 hosts = getIPv6Resrv(subnet->getID(), hint);
895 Lease6Ptr new_lease = createLease6(ctx, hint, pool->getLength(), callout_status);
908 .arg(ctx.query_->getLabel())
912 }
else if (usable_hint_lease->expired() &&
922 (!subnet->getReservationsOutOfPool() ||
923 !subnet->inPool(ctx.currentIA().type_, hint))) {
924 hosts = getIPv6Resrv(subnet->getID(), hint);
932 Lease6Ptr old_lease(
new Lease6(*usable_hint_lease));
933 ctx.currentIA().old_leases_.push_back(old_lease);
936 Lease6Ptr lease = reuseExpiredLease(usable_hint_lease, ctx,
946 .arg(ctx.query_->getLabel())
958 if (!check_reservation_first) {
972 original_subnet->getSharedNetwork(network);
979 original_subnet = network->getPreferredSubnet(original_subnet, ctx.currentIA().type_);
982 ctx.subnet_ = subnet = original_subnet;
984 for (; subnet; subnet = subnet->getNextSubnet(original_subnet)) {
985 if (!subnet->clientSupported(classes)) {
996 subnet->getPoolCapacity(ctx.currentIA().type_,
1007 (attempts_ == 0 || possible_attempts < attempts_) ?
1011 if (max_attempts > 0) {
1014 ++subnets_with_unavail_leases;
1018 ++subnets_with_unavail_pools;
1022 bool in_subnet = subnet->getReservationsInSubnet();
1023 bool out_of_pool = subnet->getReservationsOutOfPool();
1028 if (ctx.callout_handle_) {
1032 for (uint64_t i = 0; i < max_attempts; ++i) {
1035 auto allocator = subnet->getAllocator(ctx.currentIA().type_);
1040 uint8_t prefix_len = 128;
1042 candidate = allocator->pickPrefix(classes, pool, ctx.duid_,
1043 prefix_length_match, hint,
1044 hint_prefix_length);
1046 prefix_len = pool->getLength();
1049 candidate = allocator->pickAddress(classes, ctx.duid_, hint);
1058 if (check_reservation_first && in_subnet && !out_of_pool) {
1059 auto hosts = getIPv6Resrv(subnet->getID(), candidate);
1060 if (!hosts.empty()) {
1068 ResourceHandler resource_handler;
1070 !resource_handler.
tryLock(ctx.currentIA().type_, candidate)) {
1083 if (!check_reservation_first && in_subnet && !out_of_pool) {
1084 auto hosts = getIPv6Resrv(subnet->getID(), candidate);
1085 if (!hosts.empty()) {
1094 ctx.subnet_ = subnet;
1095 Lease6Ptr new_lease = createLease6(ctx, candidate, prefix_len, callout_status);
1099 ctx.currentIA().old_leases_.clear();
1103 }
else if (ctx.callout_handle_ &&
1112 }
else if (existing->expired() &&
1115 if (!check_reservation_first && in_subnet && !out_of_pool) {
1116 auto hosts = getIPv6Resrv(subnet->getID(), candidate);
1117 if (!hosts.empty()) {
1125 Lease6Ptr old_lease(
new Lease6(*existing));
1126 ctx.currentIA().old_leases_.push_back(old_lease);
1128 ctx.subnet_ = subnet;
1129 existing = reuseExpiredLease(existing, ctx, prefix_len,
1144 if (ctx.hosts_.empty()) {
1147 .arg(ctx.query_->getLabel());
1158 for (
auto const& lease : existing_leases) {
1159 if ((lease->valid_lft_ != 0)) {
1160 if ((ctx.hosts_.count(lease->subnet_id_) > 0) &&
1161 ctx.hosts_[lease->subnet_id_]->hasReservation(
makeIPv6Resrv(*lease))) {
1166 .arg(ctx.query_->getLabel())
1167 .arg(lease->typeToText(lease->type_))
1168 .arg(lease->addr_.toText());
1174 if (!ctx.host_subnet_) {
1176 ctx.subnet_->getSharedNetwork(network);
1181 ctx.host_subnet_ = network->getSubnet(lease->subnet_id_);
1189 if (host && !host->getHostname().empty()) {
1196 qualifyName(host->getHostname(), *ctx.getDdnsParams(),
1197 static_cast<bool>(fqdn));
1211 auto const& classes = ctx.query_->getClasses();
1213 subnet = subnet->getNextSubnet(ctx.subnet_)) {
1215 SubnetID subnet_id = subnet->getID();
1218 if (!subnet->clientSupported(classes) || ctx.hosts_.count(subnet_id) == 0) {
1224 bool in_subnet = subnet->getReservationsInSubnet();
1228 BOOST_FOREACH(
auto const& type_lease_tuple, reservs) {
1230 const IOAddress& addr = type_lease_tuple.second.getPrefix();
1231 uint8_t prefix_len = type_lease_tuple.second.getPrefixLen();
1235 if (ctx.isAllocated(addr, prefix_len)) {
1244 (subnet->getReservationsOutOfPool() &&
1245 subnet->inPool(ctx.currentIA().type_, addr))) {
1257 ctx.subnet_ = subnet;
1259 if (!ctx.host_subnet_) {
1260 ctx.host_subnet_ = subnet;
1261 if (!host->getHostname().empty()) {
1275 qualifyName(host->getHostname(), *ctx.getDdnsParams(),
1276 static_cast<bool>(fqdn));
1282 Lease6Ptr lease = createLease6(ctx, addr, prefix_len, callout_status);
1285 existing_leases.push_back(lease);
1290 .arg(ctx.query_->getLabel());
1294 .arg(
static_cast<int>(prefix_len))
1295 .arg(ctx.query_->getLabel());
1313 allocateGlobalReservedLeases6(ctx, existing_leases);
1328 for (
auto const& lease : existing_leases) {
1329 if ((lease->valid_lft_ != 0) &&
1335 .arg(ctx.query_->getLabel())
1336 .arg(lease->typeToText(lease->type_))
1337 .arg(lease->addr_.toText());
1343 if (!ghost->getHostname().empty()) {
1350 qualifyName(ghost->getHostname(), *ctx.getDdnsParams(),
1351 static_cast<bool>(fqdn));
1366 const IPv6ResrvRange& reservs = ghost->getIPv6Reservations(type);
1367 BOOST_FOREACH(
auto const& type_lease_tuple, reservs) {
1369 const IOAddress& addr = type_lease_tuple.second.getPrefix();
1370 uint8_t prefix_len = type_lease_tuple.second.getPrefixLen();
1374 if (ctx.isAllocated(addr, prefix_len)) {
1386 bool valid_subnet =
false;
1387 auto subnet = ctx.subnet_;
1389 if (subnet->inRange(addr)) {
1390 valid_subnet =
true;
1394 subnet = subnet->getNextSubnet(ctx.subnet_);
1397 if (!valid_subnet) {
1400 .arg(ctx.query_->getLabel())
1406 ctx.subnet_ = subnet;
1409 if (!ghost->getHostname().empty()) {
1423 qualifyName(ghost->getHostname(), *ctx.getDdnsParams(),
1424 static_cast<bool>(fqdn));
1429 Lease6Ptr lease = createLease6(ctx, addr, prefix_len, callout_status);
1432 existing_leases.push_back(lease);
1437 .arg(ctx.query_->getLabel());
1441 .arg(
static_cast<int>(prefix_len))
1442 .arg(ctx.query_->getLabel());
1460AllocEngine::removeNonmatchingReservedLeases6(
ClientContext6& ctx,
1463 if (existing_leases.empty() || !ctx.subnet_) {
1468 if (!ctx.subnet_->getReservationsInSubnet() &&
1469 !ctx.subnet_->getReservationsGlobal()) {
1470 removeNonmatchingReservedNoHostLeases6(ctx, existing_leases);
1479 for (
auto const& candidate :
copy) {
1483 if ((ctx.hasGlobalReservation(resv)) ||
1484 ((ctx.hosts_.count(candidate->subnet_id_) > 0) &&
1485 (ctx.hosts_[candidate->subnet_id_]->hasReservation(resv)))) {
1494 auto hosts = getIPv6Resrv(ctx.subnet_->getID(), candidate->addr_);
1499 if (hosts.empty() && inAllowedPool(ctx, candidate->type_,
1500 candidate->addr_,
false)) {
1504 if (!hosts.empty()) {
1507 if (hosts.size() == 1) {
1510 .arg(ctx.query_->getLabel())
1511 .arg(candidate->addr_.
toText())
1512 .arg(ctx.duid_->toText())
1513 .arg(hosts.front()->getIdentifierAsText());
1516 .arg(ctx.query_->getLabel())
1517 .arg(candidate->addr_.
toText())
1518 .arg(
static_cast<int>(candidate->prefixlen_))
1519 .arg(ctx.duid_->toText())
1520 .arg(hosts.front()->getIdentifierAsText());
1525 .arg(ctx.query_->getLabel())
1526 .arg(candidate->addr_.
toText())
1527 .arg(ctx.duid_->toText())
1531 .arg(ctx.query_->getLabel())
1532 .arg(candidate->addr_.
toText())
1533 .arg(
static_cast<int>(candidate->prefixlen_))
1534 .arg(ctx.duid_->toText())
1555 "assigned-nas" :
"assigned-pds"),
1556 static_cast<int64_t
>(-1));
1560 auto const& pool = subnet->getPool(ctx.currentIA().type_, candidate->addr_,
false);
1565 "pool" :
"pd-pool", pool->getID(),
1567 "assigned-nas" :
"assigned-pds")),
1568 static_cast<int64_t
>(-1));
1578 ctx.currentIA().old_leases_.push_back(candidate);
1581 removeLeases(existing_leases, candidate->addr_);
1586AllocEngine::removeNonmatchingReservedNoHostLeases6(
ClientContext6& ctx,
1593 for (
auto const& candidate :
copy) {
1597 if (inAllowedPool(ctx, candidate->type_,
1598 candidate->addr_,
false)) {
1616 "assigned-nas" :
"assigned-pds"),
1617 static_cast<int64_t
>(-1));
1621 auto const& pool = subnet->getPool(candidate->type_, candidate->addr_,
false);
1626 "pool" :
"pd-pool", pool->getID(),
1628 "assigned-nas" :
"assigned-pds")),
1629 static_cast<int64_t
>(-1));
1634 ctx.currentIA().old_leases_.push_back(candidate);
1637 removeLeases(existing_leases, candidate->addr_);
1642AllocEngine::removeLeases(
Lease6Collection& container,
const asiolink::IOAddress& addr) {
1644 bool removed =
false;
1645 for (Lease6Collection::iterator lease = container.begin();
1646 lease != container.end(); ++lease) {
1647 if ((*lease)->addr_ == addr) {
1654 container.erase(std::remove(container.begin(), container.end(),
Lease6Ptr()),
1665 int total = existing_leases.size();
1672 for (Lease6Collection::iterator lease = existing_leases.begin();
1673 lease != existing_leases.end(); ++lease) {
1677 if (ctx.hasGlobalReservation(resv) ||
1678 ((ctx.hosts_.count((*lease)->subnet_id_) > 0) &&
1679 (ctx.hosts_[(*lease)->subnet_id_]->hasReservation(resv)))) {
1701 "assigned-nas" :
"assigned-pds"),
1702 static_cast<int64_t
>(-1));
1706 auto const& pool = subnet->getPool(ctx.currentIA().type_, (*lease)->addr_,
false);
1711 "pool" :
"pd-pool", pool->getID(),
1713 "assigned-nas" :
"assigned-pds")),
1714 static_cast<int64_t
>(-1));
1721 ctx.currentIA().old_leases_.push_back(*lease);
1736 existing_leases.erase(std::remove(existing_leases.begin(),
1737 existing_leases.end(),
Lease6Ptr()), existing_leases.end());
1742useMinLifetimes6(AllocEngine::ClientContext6& ctx,
const IOAddress& addr,
1743 uint8_t prefix_len) {
1744 auto const& threshold = ctx.
subnet_->getAdaptiveLeaseTimeThreshold();
1745 if (!threshold.unspecified() && (threshold < 1.0)) {
1747 getOccupancyRate(addr, prefix_len, ctx.
query_->getClasses());
1748 if (occupancy >= threshold) {
1761 if (!expired->expired()) {
1762 isc_throw(BadValue,
"Attempt to recycle lease that is still valid");
1766 isc_throw(BadValue,
"Attempt to recycle registered address");
1773 if (!ctx.fake_allocation_) {
1777 reclaimExpiredLease(expired, ctx.callout_handle_);
1781 expired->iaid_ = ctx.currentIA().iaid_;
1782 expired->duid_ = ctx.duid_;
1783 expired->hwaddr_ = ctx.hwaddr_;
1786 expired->preferred_lft_ = 0;
1787 expired->valid_lft_ = 0;
1789 useMinLifetimes6(ctx, expired->addr_, prefix_len)) {
1792 getLifetimes6(ctx, expired->preferred_lft_, expired->valid_lft_);
1794 expired->reuseable_valid_lft_ = 0;
1796 expired->cltt_ = time(0);
1797 expired->subnet_id_ = ctx.subnet_->getID();
1798 expired->hostname_ = ctx.hostname_;
1799 expired->fqdn_fwd_ = ctx.fwd_dns_update_;
1800 expired->fqdn_rev_ = ctx.rev_dns_update_;
1801 expired->prefixlen_ = prefix_len;
1806 .arg(ctx.query_->getLabel())
1807 .arg(expired->toText());
1810 if (ctx.callout_handle_ &&
1817 ScopedCalloutHandleState callout_handle_state(ctx.callout_handle_);
1820 ScopedEnableOptionsCopy<Pkt6> query6_options_copy(ctx.query_);
1825 ctx.callout_handle_->setArgument(
"query6", ctx.query_);
1828 ctx.callout_handle_->setArgument(
"subnet6", ctx.subnet_);
1831 ctx.callout_handle_->setArgument(
"fake_allocation", ctx.fake_allocation_);
1834 ctx.callout_handle_->setArgument(
"lease6", expired);
1839 callout_status = ctx.callout_handle_->getStatus();
1856 ctx.callout_handle_->getArgument(
"lease6", expired);
1859 if (!ctx.fake_allocation_) {
1863 auto const& pool = ctx.subnet_->getPool(ctx.currentIA().type_, expired->addr_,
false);
1865 expired->pool_id_ = pool->getID();
1873 if (ctx.subnet_->inPool(ctx.currentIA().type_, expired->addr_)) {
1877 "assigned-nas" :
"assigned-pds"),
1878 static_cast<int64_t
>(1));
1883 "cumulative-assigned-nas" :
"cumulative-assigned-pds"),
1884 static_cast<int64_t
>(1));
1890 "pool" :
"pd-pool", pool->getID(),
1892 "assigned-nas" :
"assigned-pds")),
1893 static_cast<int64_t
>(1));
1898 "pool" :
"pd-pool", pool->getID(),
1900 "cumulative-assigned-nas" :
"cumulative-assigned-pds")),
1901 static_cast<int64_t
>(1));
1905 "cumulative-assigned-nas" :
"cumulative-assigned-pds",
1906 static_cast<int64_t
>(1));
1919void sanitizeLifetimes6(AllocEngine::ClientContext6& ctx,
1920 uint32_t& preferred, uint32_t& valid) {
1922 if (!preferred || preferred > valid) {
1923 preferred = ((valid * 5)/8);
1926 .arg(ctx.
query_->getLabel())
1939 if (!classes.
empty()) {
1946 for (
auto const& name : classes) {
1949 (cl && (!cl->getPreferred().unspecified()))) {
1950 candidate_preferred = cl->getPreferred();
1955 (cl && (!cl->getValid().unspecified()))) {
1956 candidate_valid = cl->getValid();
1959 if (have_both == 2) {
1966 if (!candidate_preferred) {
1967 candidate_preferred = ctx.
subnet_->getPreferred();
1971 if (!candidate_valid) {
1972 candidate_valid = ctx.
subnet_->getValid();
1976 preferred = candidate_preferred;
1977 valid = candidate_valid;
1991 sanitizeLifetimes6(ctx, preferred, valid);
2002 if (!classes.
empty()) {
2009 for (
auto const& name : classes) {
2012 (cl && (!cl->getPreferred().unspecified()))) {
2013 candidate_preferred = cl->getPreferred();
2018 (cl && (!cl->getValid().unspecified()))) {
2019 candidate_valid = cl->getValid();
2022 if (have_both == 2) {
2029 if (!candidate_preferred) {
2030 candidate_preferred = ctx.
subnet_->getPreferred();
2034 if (!candidate_valid) {
2035 candidate_valid = ctx.
subnet_->getValid();
2039 uint32_t remain_preferred(preferred);
2040 uint32_t remain_valid(valid);
2043 preferred = candidate_preferred.
getMin();
2044 valid = candidate_valid.
getMin();
2047 if (remain_preferred > preferred) {
2048 preferred = remain_preferred;
2050 if (remain_valid > valid) {
2051 valid = remain_valid;
2054 sanitizeLifetimes6(ctx, preferred, valid);
2066 uint32_t preferred = 0;
2069 useMinLifetimes6(ctx, addr, prefix_len)) {
2075 Lease6Ptr lease(
new Lease6(ctx.currentIA().type_, addr, ctx.duid_,
2076 ctx.currentIA().iaid_, preferred,
2077 valid, ctx.subnet_->getID(),
2078 ctx.hwaddr_, prefix_len));
2080 lease->fqdn_fwd_ = ctx.fwd_dns_update_;
2081 lease->fqdn_rev_ = ctx.rev_dns_update_;
2082 lease->hostname_ = ctx.hostname_;
2085 if (ctx.callout_handle_ &&
2092 ScopedCalloutHandleState callout_handle_state(ctx.callout_handle_);
2095 ScopedEnableOptionsCopy<Pkt6> query6_options_copy(ctx.query_);
2100 ctx.callout_handle_->setArgument(
"query6", ctx.query_);
2103 ctx.callout_handle_->setArgument(
"subnet6", ctx.subnet_);
2106 ctx.callout_handle_->setArgument(
"fake_allocation", ctx.fake_allocation_);
2109 ctx.callout_handle_->setArgument(
"lease6", lease);
2114 callout_status = ctx.callout_handle_->getStatus();
2126 ctx.callout_handle_->getArgument(
"lease6", lease);
2129 if (!ctx.fake_allocation_) {
2133 auto const& pool = ctx.subnet_->getPool(ctx.currentIA().type_, lease->addr_,
false);
2135 lease->pool_id_ = pool->getID();
2144 if (ctx.subnet_->inPool(ctx.currentIA().type_, addr)) {
2148 "assigned-nas" :
"assigned-pds"),
2149 static_cast<int64_t
>(1));
2154 "cumulative-assigned-nas" :
"cumulative-assigned-pds"),
2155 static_cast<int64_t
>(1));
2161 "pool" :
"pd-pool", pool->getID(),
2163 "assigned-nas" :
"assigned-pds")),
2164 static_cast<int64_t
>(1));
2169 "pool" :
"pd-pool", pool->getID(),
2171 "cumulative-assigned-nas" :
"cumulative-assigned-pds")),
2172 static_cast<int64_t
>(1));
2176 "cumulative-assigned-nas" :
"cumulative-assigned-pds",
2177 static_cast<int64_t
>(1));
2181 ctx.currentIA().addNewResource(addr, prefix_len);
2208 time_t now = time(0);
2210 if (lease->cltt_ > now) {
2213 uint32_t age = now - lease->cltt_;
2215 if (age >= lease->valid_lft_) {
2218 valid = lease->valid_lft_ - age;
2219 if (age >= lease->preferred_lft_) {
2222 preferred = lease->preferred_lft_ - age;
2245 for (
auto const& l : leases_subnet) {
2247 leases.push_back(l);
2250 subnet = subnet->getNextSubnet(ctx.
subnet_);
2253 if (!leases.empty()) {
2256 .arg(ctx.
query_->getLabel());
2260 removeNonmatchingReservedLeases6(ctx, leases);
2263 if (!ctx.
hosts_.empty()) {
2267 .arg(ctx.
query_->getLabel());
2270 allocateReservedLeases6(ctx, leases);
2276 removeNonreservedLeases6(ctx, leases);
2283 if (leases.empty()) {
2287 .arg(ctx.
query_->getLabel());
2289 leases = allocateUnreservedLeases6(ctx);
2293 for (
auto const& l : leases) {
2301 .arg(ctx.
query_->getLabel())
2302 .arg(l->typeToText(l->type_))
2304 extendLease6(ctx, l);
2307 if (!leases.empty()) {
2311 for (
auto const& lease : leases) {
2326 .arg(ctx.
query_->getLabel())
2336 if (!lease || !ctx.subnet_) {
2342 if (ctx.subnet_->getID() != lease->subnet_id_) {
2344 ctx.subnet_->getSharedNetwork(network);
2347 network->getSubnet(
SubnetID(lease->subnet_id_));
2351 ctx.subnet_ = subnet;
2359 (((lease->type_ !=
Lease::TYPE_PD) && !ctx.subnet_->inRange(lease->addr_)) ||
2360 !ctx.subnet_->clientSupported(ctx.query_->getClasses()))) {
2377 "assigned-nas" :
"assigned-pds"),
2378 static_cast<int64_t
>(-1));
2380 auto const& pool = ctx.subnet_->getPool(ctx.currentIA().type_, lease->addr_,
false);
2385 "pool" :
"pd-pool", pool->getID(),
2387 "assigned-nas" :
"assigned-pds")),
2388 static_cast<int64_t
>(-1));
2392 ctx.currentIA().old_leases_.push_back(lease);
2399 .arg(ctx.query_->getLabel())
2400 .arg(lease->toText());
2405 bool changed =
false;
2408 uint32_t current_preferred_lft = lease->preferred_lft_;
2410 useMinLifetimes6(ctx, lease->addr_, lease->prefixlen_)) {
2411 uint32_t remain_preferred_lft(0);
2412 uint32_t remain_valid_lft(0);
2413 getRemaining(lease, remain_preferred_lft, remain_valid_lft);
2414 lease->preferred_lft_ = remain_preferred_lft;
2415 lease->valid_lft_ = remain_valid_lft;
2418 getLifetimes6(ctx, lease->preferred_lft_, lease->valid_lft_);
2422 if ((lease->preferred_lft_ != current_preferred_lft) ||
2423 (lease->valid_lft_ != lease->current_valid_lft_)) {
2427 lease->cltt_ = time(NULL);
2428 if ((lease->fqdn_fwd_ != ctx.fwd_dns_update_) ||
2429 (lease->fqdn_rev_ != ctx.rev_dns_update_) ||
2430 (lease->hostname_ != ctx.hostname_)) {
2432 lease->hostname_ = ctx.hostname_;
2433 lease->fqdn_fwd_ = ctx.fwd_dns_update_;
2434 lease->fqdn_rev_ = ctx.rev_dns_update_;
2436 if ((!ctx.hwaddr_ && lease->hwaddr_) ||
2438 (!lease->hwaddr_ || (*ctx.hwaddr_ != *lease->hwaddr_)))) {
2440 lease->hwaddr_ = ctx.hwaddr_;
2448 .arg(ctx.query_->getLabel())
2449 .arg(lease->toText());
2453 int hook_point = ctx.query_->getType() ==
DHCPV6_RENEW ?
2454 Hooks.hook_index_lease6_renew_ :
Hooks.hook_index_lease6_rebind_;
2462 ScopedCalloutHandleState callout_handle_state(callout_handle);
2465 ScopedEnableOptionsCopy<Pkt6> query6_options_copy(ctx.query_);
2468 callout_handle->setArgument(
"query6", ctx.query_);
2471 callout_handle->setArgument(
"lease6", lease);
2475 callout_handle->setArgument(
"ia_na", ctx.currentIA().ia_rsp_);
2477 callout_handle->setArgument(
"ia_pd", ctx.currentIA().ia_rsp_);
2490 .arg(ctx.query_->getName());
2497 bool update_stats =
false;
2501 if (old_data->expired()) {
2502 reclaimExpiredLease(old_data, ctx.callout_handle_);
2506 if (ctx.subnet_->inPool(ctx.currentIA().type_, old_data->addr_)) {
2507 update_stats =
true;
2520 setLeaseReusable(lease, current_preferred_lft, ctx);
2525 if (lease->reuseable_valid_lft_ == 0) {
2526 auto const& pool = ctx.subnet_->getPool(ctx.currentIA().type_, lease->addr_,
false);
2528 lease->pool_id_ = pool->getID();
2534 old_data->reuseable_valid_lft_ = lease->reuseable_valid_lft_;
2541 "assigned-nas" :
"assigned-pds"),
2542 static_cast<int64_t
>(1));
2547 "cumulative-assigned-nas" :
"cumulative-assigned-pds"),
2548 static_cast<int64_t
>(1));
2550 auto const& pool = ctx.subnet_->getPool(ctx.currentIA().type_, lease->addr_,
false);
2555 "pool" :
"pd-pool", pool->getID(),
2557 "assigned-nas" :
"assigned-pds")),
2558 static_cast<int64_t
>(1));
2563 "pool" :
"pd-pool", pool->getID(),
2565 "cumulative-assigned-nas" :
"cumulative-assigned-pds")),
2566 static_cast<int64_t
>(1));
2570 "cumulative-assigned-nas" :
"cumulative-assigned-pds",
2571 static_cast<int64_t
>(1));
2584 ctx.currentIA().changed_leases_.push_back(old_data);
2590 for (
auto const& lease_it : leases) {
2592 if (ctx.currentIA().isNewResource(lease->addr_, lease->prefixlen_)) {
2594 updated_leases.push_back(lease);
2598 lease->reuseable_valid_lft_ = 0;
2599 lease->fqdn_fwd_ = ctx.fwd_dns_update_;
2600 lease->fqdn_rev_ = ctx.rev_dns_update_;
2601 lease->hostname_ = ctx.hostname_;
2602 uint32_t current_preferred_lft = lease->preferred_lft_;
2603 if (lease->valid_lft_ == 0) {
2605 lease->preferred_lft_ = 0;
2607 useMinLifetimes6(ctx, lease->addr_, lease->prefixlen_)) {
2610 getLifetimes6(ctx, lease->preferred_lft_, lease->valid_lft_);
2613 if (!ctx.fake_allocation_) {
2614 bool update_stats =
false;
2622 if (inAllowedPool(ctx, ctx.currentIA().type_,
2623 lease->addr_,
true)) {
2624 update_stats =
true;
2629 !(lease->hasIdenticalFqdn(*lease_it)));
2631 lease->cltt_ = time(NULL);
2632 if (!fqdn_changed) {
2633 setLeaseReusable(lease, current_preferred_lft, ctx);
2636 if (lease->reuseable_valid_lft_ == 0) {
2637 ctx.currentIA().changed_leases_.push_back(lease_it);
2641 ctx.currentIA().reused_leases_.push_back(lease_it);
2648 "assigned-nas" :
"assigned-pds"),
2649 static_cast<int64_t
>(1));
2654 "cumulative-assigned-nas" :
"cumulative-assigned-pds"),
2655 static_cast<int64_t
>(1));
2657 auto const& pool = ctx.subnet_->getPool(ctx.currentIA().type_, lease->addr_,
false);
2662 "pool" :
"pd-pool", pool->getID(),
2664 "assigned-nas" :
"assigned-pds")),
2665 static_cast<int64_t
>(1));
2670 "pool" :
"pd-pool", pool->getID(),
2672 "cumulative-assigned-nas" :
"cumulative-assigned-pds")),
2673 static_cast<int64_t
>(1));
2677 "cumulative-assigned-nas" :
"cumulative-assigned-pds",
2678 static_cast<int64_t
>(1));
2682 updated_leases.push_back(lease);
2685 return (updated_leases);
2690 const uint16_t timeout,
2691 const bool remove_lease,
2692 const uint16_t max_unwarned_cycles) {
2701 max_unwarned_cycles);
2702 }
catch (
const std::exception& ex) {
2711 const uint16_t timeout,
2712 const bool remove_lease,
2713 const uint16_t max_unwarned_cycles) {
2723 bool incomplete_reclamation =
false;
2726 if (max_leases > 0) {
2735 if (leases.size() > max_leases) {
2737 incomplete_reclamation =
true;
2750 if (!leases.empty() &&
2755 size_t leases_processed = 0;
2756 for (
auto const& lease : leases) {
2764 reclaimExpiredLease(lease, remove_lease, callout_handle);
2767 reclaimExpiredLease(lease, remove_lease, callout_handle);
2771 }
catch (
const std::exception& ex) {
2773 .arg(lease->addr_.toText())
2784 if (!incomplete_reclamation) {
2785 if (leases_processed < leases.size()) {
2786 incomplete_reclamation =
true;
2803 .arg(leases_processed)
2808 if (incomplete_reclamation) {
2809 ++incomplete_v6_reclamations_;
2812 if ((max_unwarned_cycles > 0) &&
2813 (incomplete_v6_reclamations_ > max_unwarned_cycles)) {
2815 .arg(max_unwarned_cycles);
2817 incomplete_v6_reclamations_ = 0;
2822 incomplete_v6_reclamations_ = 0;
2835 uint64_t deleted_leases = 0;
2841 }
catch (
const std::exception& ex) {
2848 .arg(deleted_leases);
2853 const uint16_t timeout,
2854 const bool remove_lease,
2855 const uint16_t max_unwarned_cycles) {
2864 max_unwarned_cycles);
2865 }
catch (
const std::exception& ex) {
2874 const uint16_t timeout,
2875 const bool remove_lease,
2876 const uint16_t max_unwarned_cycles) {
2886 bool incomplete_reclamation =
false;
2889 if (max_leases > 0) {
2898 if (leases.size() > max_leases) {
2900 incomplete_reclamation =
true;
2913 if (!leases.empty() &&
2918 size_t leases_processed = 0;
2919 for (
auto const& lease : leases) {
2927 reclaimExpiredLease(lease, remove_lease, callout_handle);
2930 reclaimExpiredLease(lease, remove_lease, callout_handle);
2934 }
catch (
const std::exception& ex) {
2936 .arg(lease->addr_.toText())
2947 if (!incomplete_reclamation) {
2948 if (leases_processed < leases.size()) {
2949 incomplete_reclamation =
true;
2966 .arg(leases_processed)
2971 if (incomplete_reclamation) {
2972 ++incomplete_v4_reclamations_;
2975 if ((max_unwarned_cycles > 0) &&
2976 (incomplete_v4_reclamations_ > max_unwarned_cycles)) {
2978 .arg(max_unwarned_cycles);
2980 incomplete_v4_reclamations_ = 0;
2985 incomplete_v4_reclamations_ = 0;
2992template<
typename LeasePtrType>
2994AllocEngine::reclaimExpiredLease(
const LeasePtrType& lease,
const bool remove_lease,
2996 reclaimExpiredLease(lease, remove_lease ? DB_RECLAIM_REMOVE : DB_RECLAIM_UPDATE,
3000template<
typename LeasePtrType>
3002AllocEngine::reclaimExpiredLease(
const LeasePtrType& lease,
3007 if (!lease->stateExpiredReclaimed()) {
3008 reclaimExpiredLease(lease, DB_RECLAIM_LEAVE_UNCHANGED, callout_handle);
3013AllocEngine::reclaimExpiredLease(
const Lease6Ptr& lease,
3014 const DbReclaimMode& reclaim_mode,
3020 .arg(lease->addr_.toText())
3021 .arg(
static_cast<int>(lease->prefixlen_));
3027 bool skipped =
false;
3029 if (callout_handle) {
3035 ScopedCalloutHandleState callout_handle_state(callout_handle);
3037 callout_handle->deleteAllArguments();
3038 callout_handle->setArgument(
"lease6", lease);
3039 callout_handle->setArgument(
"remove_lease", reclaim_mode == DB_RECLAIM_REMOVE);
3059 bool remove_lease = (reclaim_mode == DB_RECLAIM_REMOVE);
3069 remove_lease = reclaimDeclined(lease);
3071 if (reclaim_mode == DB_RECLAIM_LEAVE_UNCHANGED) {
3072 isc_throw(Unexpected,
"attempt to reuse a registered lease");
3075 remove_lease =
true;
3078 if (reclaim_mode != DB_RECLAIM_LEAVE_UNCHANGED) {
3082 reclaimLeaseInDatabase<Lease6Ptr>(lease, remove_lease,
3084 &lease_mgr, ph::_1));
3096 "reclaimed-leases"),
3097 static_cast<int64_t
>(1));
3103 auto const& pool = subnet->getPool(lease->type_, lease->addr_,
false);
3109 pool->getID(),
"reclaimed-leases")),
3110 static_cast<int64_t
>(1));
3126 static_cast<int64_t
>(-1));
3131 "assigned-nas" :
"assigned-pds"),
3132 static_cast<int64_t
>(-1));
3135 auto const& pool = subnet->getPool(lease->type_, lease->addr_,
false);
3140 "pool" :
"pd-pool", pool->getID(),
3142 "assigned-nas" :
"assigned-pds")),
3143 static_cast<int64_t
>(-1));
3150AllocEngine::reclaimExpiredLease(
const Lease4Ptr& lease,
3151 const DbReclaimMode& reclaim_mode,
3157 .arg(lease->addr_.toText());
3163 bool skipped =
false;
3165 if (callout_handle) {
3171 ScopedCalloutHandleState callout_handle_state(callout_handle);
3173 callout_handle->setArgument(
"lease4", lease);
3174 callout_handle->setArgument(
"remove_lease", reclaim_mode == DB_RECLAIM_REMOVE);
3192 lease->hostname_.clear();
3193 lease->fqdn_fwd_ =
false;
3194 lease->fqdn_rev_ =
false;
3198 bool remove_lease = (reclaim_mode == DB_RECLAIM_REMOVE);
3208 remove_lease = reclaimDeclined(lease);
3211 if (reclaim_mode != DB_RECLAIM_LEAVE_UNCHANGED) {
3215 reclaimLeaseInDatabase<Lease4Ptr>(lease, remove_lease,
3217 &lease_mgr, ph::_1));
3229 "reclaimed-leases"),
3230 static_cast<int64_t
>(1));
3235 auto const& pool = subnet->getPool(
Lease::TYPE_V4, lease->addr_,
false);
3240 "reclaimed-leases")),
3241 static_cast<int64_t
>(1));
3253 "assigned-addresses"),
3254 static_cast<int64_t
>(-1));
3257 auto const& pool = subnet->getPool(
Lease::TYPE_V4, lease->addr_,
false);
3262 "assigned-addresses")),
3263 static_cast<int64_t
>(-1));
3274 uint64_t deleted_leases = 0;
3280 }
catch (
const std::exception& ex) {
3287 .arg(deleted_leases);
3291AllocEngine::reclaimDeclined(
const Lease4Ptr& lease) {
3306 callout_handle->setArgument(
"lease4", lease);
3316 .arg(lease->addr_.toText());
3322 .arg(lease->addr_.toText())
3323 .arg(lease->valid_lft_);
3329 "declined-addresses"),
3330 static_cast<int64_t
>(-1));
3333 "reclaimed-declined-addresses"),
3334 static_cast<int64_t
>(1));
3338 auto const& pool = subnet->getPool(
Lease::TYPE_V4, lease->addr_,
false);
3342 "declined-addresses")),
3343 static_cast<int64_t
>(-1));
3347 "reclaimed-declined-addresses")),
3348 static_cast<int64_t
>(1));
3353 stats_mgr.
addValue(
"declined-addresses",
static_cast<int64_t
>(-1));
3355 stats_mgr.
addValue(
"reclaimed-declined-addresses",
static_cast<int64_t
>(1));
3363AllocEngine::reclaimDeclined(
const Lease6Ptr& lease) {
3375 ScopedCalloutHandleState callout_handle_state(callout_handle);
3378 callout_handle->setArgument(
"lease6", lease);
3388 .arg(lease->addr_.toText());
3394 .arg(lease->addr_.toText())
3395 .arg(lease->valid_lft_);
3401 "declined-addresses"),
3402 static_cast<int64_t
>(-1));
3405 "reclaimed-declined-addresses"),
3406 static_cast<int64_t
>(1));
3410 auto const& pool = subnet->getPool(lease->type_, lease->addr_,
false);
3414 "declined-addresses")),
3415 static_cast<int64_t
>(-1));
3419 "reclaimed-declined-addresses")),
3420 static_cast<int64_t
>(1));
3425 stats_mgr.
addValue(
"declined-addresses",
static_cast<int64_t
>(-1));
3427 stats_mgr.
addValue(
"reclaimed-declined-addresses",
static_cast<int64_t
>(1));
3437 lease->relay_id_.clear();
3438 lease->remote_id_.clear();
3439 if (lease->getContext()) {
3446 if (lease->getContext()) {
3452template<
typename LeasePtrType>
3453void AllocEngine::reclaimLeaseInDatabase(
const LeasePtrType& lease,
3454 const bool remove_lease,
3455 const std::function<
void (
const LeasePtrType&)>&
3456 lease_update_fun)
const {
3464 }
else if (lease_update_fun) {
3467 lease->reuseable_valid_lft_ = 0;
3468 lease->hostname_.clear();
3469 lease->fqdn_fwd_ =
false;
3470 lease->fqdn_rev_ =
false;
3473 lease_update_fun(lease);
3482 .arg(lease->addr_.toText());
3488 return(
"<empty subnet>");
3492 subnet->getSharedNetwork(network);
3493 std::ostringstream ss;
3495 ss <<
"shared-network: " << network->getName();
3497 ss <<
"subnet id: " << subnet->getID();
3536 (!ctx.
subnet_->getReservationsOutOfPool() ||
3547 if (
CfgMgr::instance().getCurrentCfg()->getCfgDbAccess()->getIPReservationsUnique()) {
3552 hosts.push_back(host);
3566 for (
auto const& host : hosts) {
3570 if (id_pair.first == host->getIdentifierType() &&
3571 id_pair.second == host->getIdentifier()) {
3579 return (!hosts.empty());
3601 if (ctx.
hosts_.empty()) {
3606 auto global_host = ctx.
hosts_.find(SUBNET_ID_GLOBAL);
3607 auto global_host_address = ((global_host != ctx.
hosts_.end() && global_host->second) ?
3608 global_host->second->getIPv4Reservation() :
3617 if (subnet->getReservationsGlobal() &&
3619 (subnet->inRange(global_host_address))) {
3624 if (subnet->getReservationsInSubnet()) {
3625 auto host = ctx.
hosts_.find(subnet->getID());
3630 if (host != ctx.
hosts_.end() && host->second) {
3631 auto reservation = host->second->getIPv4Reservation();
3632 if (!reservation.isV4Zero() &&
3633 (!subnet->getReservationsOutOfPool() ||
3643 subnet = subnet->getNextSubnet(ctx.
subnet_, ctx.
query_->getClasses());
3649 .arg(ctx.
query_->getLabel())
3650 .arg(global_host_address.toText())
3677 auto const& classes = ctx.
query_->getClasses();
3681 bool try_clientid_lookup = (ctx.
clientid_ &&
3685 if (try_clientid_lookup) {
3694 subnet = subnet->getNextSubnet(original_subnet, classes)) {
3699 if (subnet->getMatchClientId()) {
3700 for (
auto const& l : leases_client_id) {
3701 if (l->subnet_id_ == subnet->getID()) {
3714 if (!client_lease && ctx.
hwaddr_) {
3720 subnet = subnet->getNextSubnet(original_subnet, classes)) {
3722 if (subnet->getMatchClientId()) {
3728 for (
auto const& client_lease_it : leases_hw_address) {
3729 Lease4Ptr existing_lease = client_lease_it;
3730 if ((existing_lease->subnet_id_ == subnet->getID()) &&
3731 existing_lease->belongsToClient(ctx.
hwaddr_, client_id)) {
3733 client_lease = existing_lease;
3761 auto const& classes = ctx.
query_->getClasses();
3763 while (current_subnet) {
3772 current_subnet = current_subnet->getNextSubnet(ctx.
subnet_, classes);
3799 const bool fwd_dns_update,
3800 const bool rev_dns_update,
3801 const std::string& hostname,
3802 const bool fake_allocation,
3803 const uint32_t offer_lft)
3823 if (host !=
hosts_.cend()) {
3824 return (host->second);
3834 auto host =
hosts_.find(SUBNET_ID_GLOBAL);
3835 if (host !=
hosts_.cend()) {
3836 return (host->second);
3846 if (ddns_params_ &&
subnet_ && (
subnet_->getID() == ddns_params_->getSubnetId())) {
3847 return (ddns_params_);
3853 return (ddns_params_);
3875 auto const& classes = ctx.
query_->getClasses();
3876 if (subnet && !subnet->clientSupported(classes)) {
3877 ctx.
subnet_ = subnet->getNextSubnet(subnet, classes);
3901 .arg(ctx.
query_->getLabel())
3919 !subnet->getReservationsInSubnet()) {
3925 subnet->getReservationsGlobal()) {
3928 ctx.
hosts_[SUBNET_ID_GLOBAL] = ghost;
3931 if (!subnet->getReservationsInSubnet()) {
3937 std::map<SubnetID, ConstHostPtr> host_map;
3939 subnet->getSharedNetwork(network);
3948 const bool use_single_query = network &&
3952 if (use_single_query) {
3956 id_pair.second.size());
3960 for (
auto const& host : hosts) {
3961 if (host->getIPv4SubnetID() != SUBNET_ID_GLOBAL) {
3962 host_map[host->getIPv4SubnetID()] = host;
3968 auto const& classes = ctx.
query_->getClasses();
3974 if (subnet->clientSupported(classes) && subnet->getReservationsInSubnet()) {
3977 if (use_single_query) {
3978 if (host_map.count(subnet->getID()) > 0) {
3979 ctx.
hosts_[subnet->getID()] = host_map[subnet->getID()];
3987 id_pair.second.size());
3990 ctx.
hosts_[subnet->getID()] = host;
4000 subnet = subnet->getNextSubnet(ctx.
subnet_, classes);
4006 for (
auto const& host : ctx.
hosts_) {
4007 host.second->encapsulateOptions();
4017 &id_pair.second[0], id_pair.second.size());
4034 findClientLease(ctx, client_lease);
4047 if (hasAddressReservation(ctx)) {
4051 .arg(ctx.
query_->getLabel())
4052 .arg(ctx.
currentHost()->getIPv4Reservation().toText());
4058 if (!client_lease || (client_lease->addr_ != ctx.
currentHost()->getIPv4Reservation())) {
4065 new_lease = allocateOrReuseLease4(ctx.
currentHost()->getIPv4Reservation(), ctx,
4069 .arg(ctx.
query_->getLabel())
4070 .arg(ctx.
currentHost()->getIPv4Reservation().toText())
4075 "v4-reservation-conflicts"),
4076 static_cast<int64_t
>(1));
4078 static_cast<int64_t
>(1));
4082 new_lease = renewLease4(client_lease, ctx);
4095 if (!new_lease && client_lease && inAllowedPool(ctx, client_lease->addr_) &&
4096 !addressReserved(client_lease->addr_, ctx)) {
4100 .arg(ctx.
query_->getLabel());
4106 (time(NULL) + ctx.
offer_lft_ < client_lease->getExpirationTime())) {
4110 new_lease = renewLease4(client_lease, ctx);
4127 .arg(ctx.
query_->getLabel());
4140 .arg(ctx.
query_->getLabel());
4142 new_lease = allocateUnreservedLease4(ctx);
4161 "assigned-addresses"),
4162 static_cast<int64_t
>(-1));
4165 ->getBySubnetId(lease->subnet_id_);
4167 auto const& pool = subnet->getPool(
Lease::TYPE_V4, lease->addr_,
false);
4171 "assigned-addresses")),
4172 static_cast<int64_t
>(-1));
4184 findClientLease(ctx, client_lease);
4200 .arg(ctx.
query_->getLabel())
4206 }
else if (hasAddressReservation(ctx)) {
4215 .arg(ctx.
query_->getLabel())
4227 if (existing && !existing->expired() &&
4228 !existing->belongsToClient(ctx.
hwaddr_, ctx.
subnet_->getMatchClientId() ?
4233 .arg(ctx.
query_->getLabel())
4243 if (hasAddressReservation(ctx) &&
4251 if (!existing || existing->expired()) {
4255 .arg(ctx.
query_->getLabel())
4256 .arg(ctx.
currentHost()->getIPv4Reservation().toText())
4266 if ((!hasAddressReservation(ctx) ||
4272 .arg(ctx.
query_->getLabel())
4284 if (((client_lease && existing) && (client_lease->addr_ != existing->addr_) &&
4286 (existing->belongsToClient(ctx.
hwaddr_, ctx.
subnet_->getMatchClientId() ?
4289 auto conflicted_lease = client_lease;
4290 client_lease = existing;
4307 ((hasAddressReservation(ctx) &&
4309 inAllowedPool(ctx, client_lease->addr_))) {
4313 .arg(ctx.
query_->getLabel())
4315 return (renewLease4(client_lease, ctx));
4329 .arg(ctx.
query_->getLabel())
4344 .arg(ctx.
query_->getLabel());
4349 new_lease = allocateUnreservedLease4(ctx);
4355 if (new_lease && client_lease) {
4360 .arg(ctx.
query_->getLabel())
4361 .arg(client_lease->addr_.toText());
4382 if (!classes.
empty()) {
4388 for (
auto const& name : classes) {
4390 if (cl && (!cl->getOfferLft().unspecified())) {
4391 offer_lft = cl->getOfferLft();
4399 offer_lft = ctx.
subnet_->getOfferLft();
4408 if (ctx.
query_->inClass(
"BOOTP")) {
4413 uint32_t requested_lft = 0;
4416 OptionUint32Ptr opt_lft = boost::dynamic_pointer_cast<OptionInt<uint32_t> >(opt);
4418 requested_lft = opt_lft->getValue();
4426 if (!classes.
empty()) {
4432 for (
auto const& name : classes) {
4434 if (cl && (!cl->getValid().unspecified())) {
4435 candidate_lft = cl->getValid();
4442 if (!candidate_lft) {
4443 candidate_lft = ctx.
subnet_->getValid();
4448 if (requested_lft > 0) {
4449 return (candidate_lft.
get(requested_lft));
4453 return (candidate_lft.
get());
4459 if (ctx.
query_->inClass(
"BOOTP")) {
4468 if (!classes.
empty()) {
4474 for (
auto const& name : classes) {
4476 if (cl && (!cl->getValid().unspecified())) {
4477 candidate_lft = cl->getValid();
4484 if (!candidate_lft) {
4485 candidate_lft = ctx.
subnet_->getValid();
4489 uint32_t remain(valid);
4492 valid = candidate_lft.
getMin();
4495 if (remain > valid) {
4503 auto const& threshold = ctx.
subnet_->getAdaptiveLeaseTimeThreshold();
4504 if (!threshold.unspecified() && (threshold < 1.0)) {
4506 getOccupancyRate(addr, ctx.
query_->getClasses());
4507 if (occupancy >= threshold) {
4516AllocEngine::createLease4(
const ClientContext4& ctx,
const IOAddress& addr,
4519 isc_throw(BadValue,
"Can't create a lease with NULL HW address");
4522 isc_throw(BadValue,
"Can't create a lease without a subnet");
4526 uint32_t valid_lft = ctx.offer_lft_;
4528 if (useMinValidLft(ctx, addr)) {
4535 time_t now = time(0);
4538 if (ctx.subnet_->getMatchClientId()) {
4539 client_id = ctx.clientid_;
4542 Lease4Ptr lease(
new Lease4(addr, ctx.hwaddr_, client_id,
4543 valid_lft, now, ctx.subnet_->getID()));
4546 lease->fqdn_fwd_ = ctx.fwd_dns_update_;
4547 lease->fqdn_rev_ = ctx.rev_dns_update_;
4548 lease->hostname_ = ctx.hostname_;
4554 if (ctx.callout_handle_ &&
4561 ScopedCalloutHandleState callout_handle_state(ctx.callout_handle_);
4564 ScopedEnableOptionsCopy<Pkt4> query4_options_copy(ctx.query_);
4568 ctx.callout_handle_->setArgument(
"query4", ctx.query_);
4575 boost::dynamic_pointer_cast<const Subnet4>(ctx.subnet_);
4576 ctx.callout_handle_->setArgument(
"subnet4", subnet4);
4579 ctx.callout_handle_->setArgument(
"fake_allocation", ctx.fake_allocation_);
4582 ctx.callout_handle_->setArgument(
"offer_lft", ctx.offer_lft_);
4585 ctx.callout_handle_->setArgument(
"lease4", lease);
4590 callout_status = ctx.callout_handle_->getStatus();
4602 ctx.callout_handle_->getArgument(
"lease4", lease);
4605 if (ctx.fake_allocation_ && ctx.offer_lft_) {
4609 lease->fqdn_fwd_ =
false;
4610 lease->fqdn_rev_ =
false;
4613 if (!ctx.fake_allocation_ || ctx.offer_lft_) {
4614 auto const& pool = ctx.subnet_->getPool(
Lease::TYPE_V4, lease->addr_,
false);
4616 lease->pool_id_ = pool->getID();
4625 "assigned-addresses"),
4626 static_cast<int64_t
>(1));
4630 "cumulative-assigned-addresses"),
4631 static_cast<int64_t
>(1));
4637 "assigned-addresses")),
4638 static_cast<int64_t
>(1));
4643 "cumulative-assigned-addresses")),
4644 static_cast<int64_t
>(1));
4648 static_cast<int64_t
>(1));
4677 time_t now = time(0);
4679 if (lease->cltt_ > now) {
4682 uint32_t age = now - lease->cltt_;
4684 if (age >= lease->valid_lft_) {
4687 valid = lease->valid_lft_ - age;
4691AllocEngine::renewLease4(
const Lease4Ptr& lease,
4701 Lease4Ptr old_values = boost::make_shared<Lease4>(*lease);
4706 lease->reuseable_valid_lft_ = 0;
4707 if (!updateLease4Information(lease, ctx)) {
4708 setLeaseReusable(lease, ctx);
4733 ScopedEnableOptionsCopy<Pkt4> query4_options_copy(ctx.
query_);
4740 boost::dynamic_pointer_cast<const Subnet4>(ctx.
subnet_);
4749 ctx.
callout_handle_->setArgument(
"clientid", subnet4->getMatchClientId() ?
4775 lease->pool_id_ = pool->getID();
4785 "assigned-addresses"),
4786 static_cast<int64_t
>(1));
4790 "cumulative-assigned-addresses"),
4791 static_cast<int64_t
>(1));
4797 "assigned-addresses")),
4798 static_cast<int64_t
>(1));
4803 "cumulative-assigned-addresses")),
4804 static_cast<int64_t
>(1));
4808 static_cast<int64_t
>(1));
4814 *lease = *old_values;
4821AllocEngine::reuseExpiredLease4(
Lease4Ptr& expired,
4822 AllocEngine::ClientContext4& ctx,
4825 isc_throw(BadValue,
"null lease specified for reuseExpiredLease");
4829 isc_throw(BadValue,
"null subnet specified for the reuseExpiredLease");
4840 expired->reuseable_valid_lft_ = 0;
4841 static_cast<void>(updateLease4Information(expired, ctx));
4845 .arg(ctx.
query_->getLabel())
4846 .arg(expired->toText());
4853 ScopedEnableOptionsCopy<Pkt4> query4_options_copy(ctx.
query_);
4870 boost::dynamic_pointer_cast<const Subnet4>(ctx.
subnet_);
4904 expired->pool_id_ = pool->getID();
4912 "assigned-addresses"),
4913 static_cast<int64_t
>(1));
4917 "cumulative-assigned-addresses"),
4918 static_cast<int64_t
>(1));
4924 "assigned-addresses")),
4925 static_cast<int64_t
>(1));
4930 "cumulative-assigned-addresses")),
4931 static_cast<int64_t
>(1));
4935 static_cast<int64_t
>(1));
4947AllocEngine::allocateOrReuseLease4(
const IOAddress& candidate,
ClientContext4& ctx,
4949 ctx.conflicting_lease_.reset();
4953 if (exist_lease->expired()) {
4954 ctx.old_lease_ =
Lease4Ptr(
new Lease4(*exist_lease));
4958 ctx.old_lease_->hostname_.clear();
4959 ctx.old_lease_->fqdn_fwd_ =
false;
4960 ctx.old_lease_->fqdn_rev_ =
false;
4961 return (reuseExpiredLease4(exist_lease, ctx, callout_status));
4967 ctx.conflicting_lease_ = exist_lease;
4971 return (createLease4(ctx, candidate, callout_status));
4991 ctx.subnet_->getSharedNetwork(network);
4998 ctx.subnet_ = subnet = network->getPreferredSubnet(ctx.subnet_);
5012 uint64_t subnets_with_unavail_leases = 0;
5015 uint64_t subnets_with_unavail_pools = 0;
5017 auto const& classes = ctx.query_->getClasses();
5021 if (subnet->getMatchClientId()) {
5022 client_id = ctx.clientid_;
5034 (attempts_ == 0 || possible_attempts < attempts_) ?
5038 if (max_attempts > 0) {
5041 ++subnets_with_unavail_leases;
5045 ++subnets_with_unavail_pools;
5048 bool exclude_first_last_24 = ((subnet->get().second <= 24) &&
5053 for (
uint128_t i = 0; i < max_attempts; ++i) {
5058 IOAddress candidate = allocator->pickAddress(classes,
5060 ctx.requested_address_);
5067 if (exclude_first_last_24) {
5069 auto const& bytes = candidate.
toBytes();
5070 if ((bytes.size() != 4) ||
5071 (bytes[3] == 0) || (bytes[3] == 255U)) {
5078 if (check_reservation_first && addressReserved(candidate, ctx)) {
5085 ResourceHandler4 resource_handler;
5087 !resource_handler.
tryLock4(candidate)) {
5096 if (check_reservation_first || !addressReserved(candidate, ctx)) {
5098 new_lease = createLease4(ctx, candidate, callout_status);
5102 if (exist_lease->expired() &&
5103 (check_reservation_first || !addressReserved(candidate, ctx))) {
5104 ctx.old_lease_ =
Lease4Ptr(
new Lease4(*exist_lease));
5105 new_lease = reuseExpiredLease4(exist_lease, ctx, callout_status);
5123 subnet = subnet->getNextSubnet(original_subnet, classes);
5126 ctx.subnet_ = subnet;
5135 .arg(ctx.query_->getLabel())
5136 .arg(network->getName())
5137 .arg(subnets_with_unavail_leases)
5138 .arg(subnets_with_unavail_pools);
5140 static_cast<int64_t
>(1));
5143 "v4-allocation-fail-shared-network"),
5144 static_cast<int64_t
>(1));
5148 std::string shared_network = ctx.subnet_->getSharedNetworkName();
5149 if (shared_network.empty()) {
5150 shared_network =
"(none)";
5153 .arg(ctx.query_->getLabel())
5154 .arg(ctx.subnet_->toText())
5155 .arg(ctx.subnet_->getID())
5156 .arg(shared_network);
5158 static_cast<int64_t
>(1));
5161 "v4-allocation-fail-subnet"),
5162 static_cast<int64_t
>(1));
5164 if (total_attempts == 0) {
5170 .arg(ctx.query_->getLabel());
5172 static_cast<int64_t
>(1));
5175 "v4-allocation-fail-no-pools"),
5176 static_cast<int64_t
>(1));
5183 .arg(ctx.query_->getLabel())
5184 .arg(total_attempts);
5186 static_cast<int64_t
>(1));
5189 "v4-allocation-fail"),
5190 static_cast<int64_t
>(1));
5193 if (!classes.empty()) {
5195 .arg(ctx.query_->getLabel())
5196 .arg(classes.toText());
5198 static_cast<int64_t
>(1));
5201 "v4-allocation-fail-classes"),
5202 static_cast<int64_t
>(1));
5209AllocEngine::updateLease4Information(
const Lease4Ptr& lease,
5210 AllocEngine::ClientContext4& ctx)
const {
5211 bool changed =
false;
5212 if (lease->subnet_id_ != ctx.
subnet_->getID()) {
5214 lease->subnet_id_ = ctx.
subnet_->getID();
5216 if ((!ctx.
hwaddr_ && lease->hwaddr_) ||
5218 (!lease->hwaddr_ || (*ctx.
hwaddr_ != *lease->hwaddr_)))) {
5223 if (!lease->client_id_ || (*ctx.
clientid_ != *lease->client_id_)) {
5227 }
else if (lease->client_id_) {
5231 uint32_t remain_lft(0);
5233 lease->cltt_ = time(0);
5237 if (!lease->valid_lft_) {
5238 if (useMinValidLft(ctx, lease->addr_)) {
5239 lease->valid_lft_ = remain_lft;
5247 if (lease->valid_lft_ != lease->current_valid_lft_) {
5271 bool changed =
false;
5274 if (!ctx.
subnet_->getStoreExtendedInfo()) {
5289 sao->boolValue() && ctx.
query_->inClass(
"STASH_AGENT_OPTIONS")) {
5298 extended_info->set(
"sub-options", relay_agent);
5302 std::vector<uint8_t> bytes = remote_id->toBinary();
5303 lease->remote_id_ = bytes;
5304 if (bytes.size() > 0) {
5305 extended_info->set(
"remote-id",
5312 std::vector<uint8_t> bytes = relay_id->toBinary(
false);
5313 lease->relay_id_ = bytes;
5314 if (bytes.size() > 0) {
5315 extended_info->set(
"relay-id",
5321 return (lease->updateUserContextISC(
"relay-agent-info", extended_info));
5331 if (!ctx.
subnet_->getStoreExtendedInfo()) {
5336 if (ctx.
query_->relay_info_.empty()) {
5351 for (
auto const& relay : ctx.
query_->relay_info_) {
5360 if (!relay.options_.empty()) {
5365 const uint8_t* cp = buf.
getData();
5366 std::vector<uint8_t> bytes;
5367 std::stringstream ss;
5375 if (remote_id_it != relay.options_.end()) {
5376 OptionPtr remote_id = remote_id_it->second;
5378 std::vector<uint8_t> bytes = remote_id->toBinary();
5379 if (bytes.size() > 0) {
5380 relay_elem->set(
"remote-id",
5387 if (relay_id_it != relay.options_.end()) {
5388 OptionPtr relay_id = relay_id_it->second;
5390 std::vector<uint8_t> bytes = relay_id->toBinary(
false);
5391 if (bytes.size() > 0) {
5392 relay_elem->set(
"relay-id",
5399 extended_info->add(relay_elem);
5403 if (lease->updateUserContextISC(
"relay-info", extended_info)) {
5409AllocEngine::setLeaseReusable(
const Lease4Ptr& lease,
5410 const ClientContext4& ctx)
const {
5412 lease->reuseable_valid_lft_ = 0;
5428 if (lease->cltt_ < lease->current_cltt_) {
5432 uint32_t age = lease->cltt_ - lease->current_cltt_;
5434 if (age >= lease->current_valid_lft_) {
5439 uint32_t max_age = 0;
5440 if (!subnet->getCacheMaxAge().unspecified()) {
5441 max_age = subnet->getCacheMaxAge().get();
5442 if ((max_age == 0) || (age > max_age)) {
5448 if (!subnet->getCacheThreshold().unspecified()) {
5449 double threshold = subnet->getCacheThreshold().get();
5450 if ((threshold <= 0.) || (threshold > 1.)) {
5453 max_age = lease->valid_lft_ * threshold;
5454 if (age > max_age) {
5465 lease->reuseable_valid_lft_ = lease->current_valid_lft_ - age;
5469AllocEngine::setLeaseReusable(
const Lease6Ptr& lease,
5470 uint32_t current_preferred_lft,
5473 lease->reuseable_valid_lft_ = 0;
5474 lease->reuseable_preferred_lft_ = 0;
5484 if (lease->cltt_ < lease->current_cltt_) {
5488 uint32_t age = lease->cltt_ - lease->current_cltt_;
5490 if (age >= lease->current_valid_lft_) {
5495 uint32_t max_age = 0;
5496 if (!subnet->getCacheMaxAge().unspecified()) {
5497 max_age = subnet->getCacheMaxAge().get();
5498 if ((max_age == 0) || (age > max_age)) {
5504 if (!subnet->getCacheThreshold().unspecified()) {
5505 double threshold = subnet->getCacheThreshold().get();
5506 if ((threshold <= 0.) || (threshold > 1.)) {
5509 max_age = lease->valid_lft_ * threshold;
5510 if (age > max_age) {
5522 (current_preferred_lft == 0)) {
5524 lease->reuseable_preferred_lft_ = current_preferred_lft;
5525 }
else if (current_preferred_lft > age) {
5526 lease->reuseable_preferred_lft_ = current_preferred_lft - age;
5534 lease->reuseable_valid_lft_ = lease->current_valid_lft_ - age;
CalloutNextStep
Specifies allowed next steps.
@ NEXT_STEP_CONTINUE
continue normally
@ NEXT_STEP_SKIP
skip the next processing step
A generic exception that is thrown if a parameter given to a method is considered invalid in that con...
This is a base class for exceptions thrown from the DNS library module.
virtual const char * what() const
Returns a C-style character string of the cause of the exception.
A generic exception that is thrown if a function is called in a prohibited way.
The IOAddress class represents an IP addresses (version agnostic)
static const IOAddress & IPV4_ZERO_ADDRESS()
Returns an address set to all zeros.
bool isV4Zero() const
Convenience function to check if it is an IPv4 zero address.
std::string toText() const
Convert the address to a string.
std::vector< uint8_t > toBytes() const
Return address as set of bytes.
bool isV6Zero() const
Convenience function to check if it is an IPv4 zero address.
static const IOAddress & IPV6_ZERO_ADDRESS()
Returns an IPv6 zero address.
static ElementPtr create(const Position &pos=ZERO_POSITION())
static ElementPtr createMap(const Position &pos=ZERO_POSITION())
Creates an empty MapElement type ElementPtr.
static ElementPtr createList(const Position &pos=ZERO_POSITION())
Creates an empty ListElement type ElementPtr.
Notes: IntElement type is changed to int64_t.
Multiple lease records found where one expected.
static IPv6Resrv makeIPv6Resrv(const Lease6 &lease)
Creates an IPv6Resrv instance from a Lease6.
void updateLease6ExtendedInfo(const Lease6Ptr &lease, const ClientContext6 &ctx) const
Stores additional client query parameters on a V6 lease.
static void getMinValidLft(const ClientContext4 &ctx, uint32_t &valid)
Returns the valid lifetime based on the v4 context when the pool occupancy is over the adaptive lease...
void reclaimExpiredLeases6Internal(const size_t max_leases, const uint16_t timeout, const bool remove_lease, const uint16_t max_unwarned_cycles=0)
Body of reclaimExpiredLeases6.
bool updateLease4ExtendedInfo(const Lease4Ptr &lease, const ClientContext4 &ctx) const
Stores additional client query parameters on a V4 lease.
static ConstHostPtr findGlobalReservation(ClientContext6 &ctx)
Attempts to find the host reservation for the client.
AllocEngine(isc::util::uint128_t const &attempts)
Constructor.
std::pair< Host::IdentifierType, std::vector< uint8_t > > IdentifierPair
A tuple holding host identifier type and value.
void clearReclaimedExtendedInfo(const Lease4Ptr &lease) const
Clear extended info from a reclaimed V4 lease.
isc::util::ReadWriteMutex rw_mutex_
The read-write mutex.
static void getLifetimes6(ClientContext6 &ctx, uint32_t &preferred, uint32_t &valid)
Determines the preferred and valid v6 lease lifetimes.
static void findReservation(ClientContext6 &ctx)
static uint32_t getOfferLft(const ClientContext4 &ctx, bool only_on_discover=true)
Returns the offer lifetime based on the v4 context.
void reclaimExpiredLeases4Internal(const size_t max_leases, const uint16_t timeout, const bool remove_lease, const uint16_t max_unwarned_cycles=0)
Body of reclaimExpiredLeases4.
void deleteExpiredReclaimedLeases4(const uint32_t secs)
Deletes reclaimed leases expired more than specified amount of time ago.
static uint32_t getValidLft(const ClientContext4 &ctx)
Returns the valid lifetime based on the v4 context.
void reclaimExpiredLeases6(const size_t max_leases, const uint16_t timeout, const bool remove_lease, const uint16_t max_unwarned_cycles=0)
Reclaims expired IPv6 leases.
static std::string labelNetworkOrSubnet(ConstSubnetPtr subnet)
Generates a label for subnet or shared-network from subnet.
void reclaimExpiredLeases4(const size_t max_leases, const uint16_t timeout, const bool remove_lease, const uint16_t max_unwarned_cycles=0)
Reclaims expired IPv4 leases.
static void getMinLifetimes6(ClientContext6 &ctx, uint32_t &preferred, uint32_t &valid)
Determines the preferred and valid v6 lease lifetimes when the pool occupancy is over the adaptive le...
static void getRemaining(const Lease4Ptr &lease, uint32_t &valid)
Set remaining valid life time.
Lease4Ptr allocateLease4(ClientContext4 &ctx)
Returns IPv4 lease.
void deleteExpiredReclaimedLeases6(const uint32_t secs)
Deletes reclaimed leases expired more than specified amount of time ago.
Lease6Collection allocateLeases6(ClientContext6 &ctx)
Allocates IPv6 leases for a given IA container.
Lease6Collection renewLeases6(ClientContext6 &ctx)
Renews existing DHCPv6 leases for a given IA.
PrefixLenMatchType
Type of preferred PD-pool prefix length selection criteria.
static bool isValidPrefixPool(Allocator::PrefixLenMatchType prefix_length_match, PoolPtr pool, uint8_t hint_prefix_length)
Check if the pool matches the selection criteria relative to the provided hint prefix length.
D2ClientMgr & getD2ClientMgr()
Fetches the DHCP-DDNS manager.
static CfgMgr & instance()
returns a single instance of Configuration Manager
SrvConfigPtr getCurrentCfg()
Returns a pointer to the current configuration.
Container for storing client class names.
bool empty() const
Check if classes is empty.
Convenience container for conveying DDNS behavioral parameters It is intended to be created per Packe...
ConstHostCollection getAll6(const SubnetID &subnet_id, const HostMgrOperationTarget target) const
Return all hosts in a DHCPv6 subnet.
ConstHostCollection getAll4(const SubnetID &subnet_id, const HostMgrOperationTarget target) const
Return all hosts in a DHCPv4 subnet.
ConstHostCollection getAll(const Host::IdentifierType &identifier_type, const uint8_t *identifier_begin, const size_t identifier_len, const HostMgrOperationTarget target) const
Return all hosts connected to any subnet for which reservations have been made using a specified iden...
bool getDisableSingleQuery() const
Returns the disable single query flag.
static HostMgr & instance()
Returns a sole instance of the HostMgr.
ConstHostPtr get4(const SubnetID &subnet_id, const Host::IdentifierType &identifier_type, const uint8_t *identifier_begin, const size_t identifier_len, const HostMgrOperationTarget target) const
Returns a host connected to the IPv4 subnet.
ConstHostPtr get6(const SubnetID &subnet_id, const Host::IdentifierType &identifier_type, const uint8_t *identifier_begin, const size_t identifier_len, const HostMgrOperationTarget target) const
Returns a host connected to the IPv6 subnet.
IPv6 reservation for a host.
Type
Type of the reservation.
static TrackingLeaseMgr & instance()
Return current lease manager.
virtual Lease6Collection getLeases6(Lease::Type type, const DUID &duid, uint32_t iaid) const =0
Returns existing IPv6 leases for a given DUID+IA combination.
virtual void getExpiredLeases6(Lease6Collection &expired_leases, const size_t max_leases) const =0
Returns a collection of expired DHCPv6 leases.
virtual uint64_t deleteExpiredReclaimedLeases6(const uint32_t secs)=0
Deletes all expired and reclaimed DHCPv6 leases.
virtual Lease4Ptr getLease4(const isc::asiolink::IOAddress &addr) const =0
Returns an IPv4 lease for specified IPv4 address.
virtual uint64_t deleteExpiredReclaimedLeases4(const uint32_t secs)=0
Deletes all expired and reclaimed DHCPv4 leases.
virtual bool addLease(const Lease4Ptr &lease)=0
Adds an IPv4 lease.
virtual bool deleteLease(const Lease4Ptr &lease)=0
Deletes an IPv4 lease.
virtual void getExpiredLeases4(Lease4Collection &expired_leases, const size_t max_leases) const =0
Returns a collection of expired DHCPv4 leases.
virtual void updateLease4(const Lease4Ptr &lease4)=0
Updates IPv4 lease.
virtual Lease6Ptr getLease6(Lease::Type type, const isc::asiolink::IOAddress &addr) const =0
Returns existing IPv6 lease for a given IPv6 address.
virtual void updateLease6(const Lease6Ptr &lease6)=0
Updates IPv6 lease.
static void packOptions6(isc::util::OutputBuffer &buf, const isc::dhcp::OptionCollection &options)
Stores DHCPv6 options in a buffer.
Attempt to update lease that was not there.
static std::string makeLabel(const HWAddrPtr &hwaddr, const ClientIdPtr &client_id, const uint32_t transid)
Returns text representation of the given packet identifiers.
static std::string makeLabel(const DuidPtr duid, const uint32_t transid, const HWAddrPtr &hwaddr)
Returns text representation of the given packet identifiers.
bool tryLock4(const asiolink::IOAddress &addr)
Tries to acquires a resource.
bool tryLock(Lease::Type type, const asiolink::IOAddress &addr)
Tries to acquires a resource.
static bool subnetsIncludeMatchClientId(const ConstSubnet4Ptr &first_subnet, const ClientClasses &client_classes)
Checks if the shared network includes a subnet with the match client ID flag set to true.
CalloutNextStep
Specifies allowed next steps.
@ NEXT_STEP_CONTINUE
continue normally
@ NEXT_STEP_SKIP
skip the next processing step
static int registerHook(const std::string &name)
Register Hook.
static bool calloutsPresent(int index)
Are callouts present?
static boost::shared_ptr< CalloutHandle > createCalloutHandle()
Return callout handle.
static void callCallouts(int index, CalloutHandle &handle)
Calls the callouts for a given hook.
Wrapper class around callout handle which automatically resets handle's state.
static StatsMgr & instance()
Statistics Manager accessor method.
static std::string generateName(const std::string &context, Type index, const std::string &stat_name)
Generates statistic name in a given context.
static MultiThreadingMgr & instance()
Returns a single instance of Multi Threading Manager.
bool getMode() const
Get the multi-threading mode.
A template representing an optional value.
T get() const
Retrieves the encapsulated value.
void unspecified(bool unspecified)
Modifies the flag that indicates whether the value is specified or unspecified.
The OutputBuffer class is a buffer abstraction for manipulating mutable data.
const uint8_t * getData() const
Return a pointer to the head of the data stored in the buffer.
size_t getLength() const
Return the length of data written in the buffer.
Utility class to measure code execution times.
long getTotalMilliseconds() const
Retrieves the total measured duration in milliseconds.
void stop()
Stops the stopwatch.
std::string logFormatTotalDuration() const
Returns the total measured duration in the format directly usable in the log messages.
This template specifies a parameter value.
T get(T hint) const
Returns value with a hint.
T getMin() const
Returns a minimum allowed value.
Write mutex RAII handler.
#define isc_throw(type, stream)
A shortcut macro to insert known values into exception arguments.
boost::shared_ptr< OptionUint32 > OptionUint32Ptr
void addValue(const std::string &name, const int64_t value)
Records incremental integer observation.
#define LOG_ERROR(LOGGER, MESSAGE)
Macro to conveniently test error output and log it.
#define LOG_INFO(LOGGER, MESSAGE)
Macro to conveniently test info output and log it.
#define LOG_WARN(LOGGER, MESSAGE)
Macro to conveniently test warn output and log it.
#define LOG_DEBUG(LOGGER, LEVEL, MESSAGE)
Macro to conveniently test debug output and log it.
ElementPtr copy(ConstElementPtr from, int level)
Copy the data up to a nesting level.
boost::shared_ptr< const Element > ConstElementPtr
boost::shared_ptr< Element > ElementPtr
const isc::log::MessageID ALLOC_ENGINE_V6_ALLOC_NO_LEASES_HR
const isc::log::MessageID ALLOC_ENGINE_V4_REQUEST_INVALID
const isc::log::MessageID ALLOC_ENGINE_V4_LEASE_RECLAMATION_FAILED
isc::log::Logger dhcpsrv_logger("dhcpsrv")
DHCP server library Logger.
const isc::log::MessageID ALLOC_ENGINE_V4_ALLOC_FAIL_NO_POOLS
const isc::log::MessageID ALLOC_ENGINE_IGNORING_UNSUITABLE_GLOBAL_ADDRESS6
const isc::log::MessageID DHCPSRV_HOOK_LEASE4_RECOVER_SKIP
const isc::log::MessageID ALLOC_ENGINE_V4_REQUEST_EXTEND_LEASE
const isc::log::MessageID ALLOC_ENGINE_V4_REQUEST_IN_USE
const isc::log::MessageID ALLOC_ENGINE_V6_ALLOC_HR_LEASE_EXISTS
const isc::log::MessageID ALLOC_ENGINE_V6_RECLAIMED_LEASES_DELETE_FAILED
const isc::log::MessageID ALLOC_ENGINE_V6_RENEW_HR
const isc::log::MessageID ALLOC_ENGINE_V6_EXTEND_LEASE_DATA
const isc::log::MessageID ALLOC_ENGINE_V4_REUSE_EXPIRED_LEASE_DATA
const isc::log::MessageID ALLOC_ENGINE_V6_EXTEND_LEASE
const isc::log::MessageID ALLOC_ENGINE_V6_REVOKED_SHARED_PREFIX_LEASE
const isc::log::MessageID ALLOC_ENGINE_V6_REUSE_EXPIRED_LEASE_DATA
const isc::log::MessageID ALLOC_ENGINE_V6_ALLOC_NO_V6_HR
const isc::log::MessageID ALLOC_ENGINE_V6_REVOKED_SHARED_ADDR_LEASE
const isc::log::MessageID ALLOC_ENGINE_V4_ALLOC_ERROR
const isc::log::MessageID ALLOC_ENGINE_V6_HINT_RESERVED
const isc::log::MessageID ALLOC_ENGINE_V4_REQUEST_OUT_OF_POOL
const isc::log::MessageID ALLOC_ENGINE_V6_LEASES_RECLAMATION_SLOW
const isc::log::MessageID ALLOC_ENGINE_V4_REQUEST_ADDRESS_RESERVED
isc::log::Logger alloc_engine_logger("alloc-engine")
Logger for the AllocEngine.
void queueNCR(const NameChangeType &chg_type, const Lease4Ptr &lease)
Creates name change request from the DHCPv4 lease.
const isc::log::MessageID ALLOC_ENGINE_V4_OFFER_REQUESTED_LEASE
const isc::log::MessageID ALLOC_ENGINE_LEASE_RECLAIMED
const int ALLOC_ENGINE_DBG_TRACE
Logging levels for the AllocEngine.
boost::shared_ptr< const Subnet6 > ConstSubnet6Ptr
A const pointer to a Subnet6 object.
const isc::log::MessageID ALLOC_ENGINE_V4_LEASES_RECLAMATION_COMPLETE
const isc::log::MessageID ALLOC_ENGINE_IGNORING_UNSUITABLE_GLOBAL_ADDRESS
const isc::log::MessageID ALLOC_ENGINE_V4_RECLAIMED_LEASES_DELETE_COMPLETE
std::vector< ConstHostPtr > ConstHostCollection
Collection of the const Host objects.
boost::shared_ptr< const Subnet4 > ConstSubnet4Ptr
A const pointer to a Subnet4 object.
const isc::log::MessageID ALLOC_ENGINE_V6_EXTEND_ERROR
const isc::log::MessageID ALLOC_ENGINE_V4_ALLOC_FAIL
const isc::log::MessageID ALLOC_ENGINE_V6_ALLOC_LEASES_HR
boost::shared_ptr< DUID > DuidPtr
const isc::log::MessageID ALLOC_ENGINE_V6_EXTEND_ALLOC_UNRESERVED
boost::shared_ptr< Lease6 > Lease6Ptr
Pointer to a Lease6 structure.
std::vector< Lease6Ptr > Lease6Collection
A collection of IPv6 leases.
const isc::log::MessageID ALLOC_ENGINE_V4_DECLINED_RECOVERED
const isc::log::MessageID DHCPSRV_HOOK_LEASE6_SELECT_SKIP
const isc::log::MessageID ALLOC_ENGINE_V4_LEASES_RECLAMATION_SLOW
const isc::log::MessageID ALLOC_ENGINE_V4_REQUEST_USE_HR
const isc::log::MessageID ALLOC_ENGINE_V4_LEASES_RECLAMATION_TIMEOUT
boost::shared_ptr< ClientClassDef > ClientClassDefPtr
a pointer to an ClientClassDef
boost::shared_ptr< DdnsParams > DdnsParamsPtr
Defines a pointer for DdnsParams instances.
const isc::log::MessageID ALLOC_ENGINE_V4_LEASES_RECLAMATION_START
boost::shared_ptr< Option6IAPrefix > Option6IAPrefixPtr
Pointer to the Option6IAPrefix object.
const isc::log::MessageID ALLOC_ENGINE_V6_RENEW_REMOVE_RESERVED
std::pair< IPv6ResrvIterator, IPv6ResrvIterator > IPv6ResrvRange
const isc::log::MessageID ALLOC_ENGINE_V6_LEASE_RECLAIM
const isc::log::MessageID ALLOC_ENGINE_V4_LEASE_RECLAIM
const isc::log::MessageID ALLOC_ENGINE_V4_DISCOVER_HR
boost::shared_ptr< HWAddr > HWAddrPtr
Shared pointer to a hardware address structure.
const isc::log::MessageID ALLOC_ENGINE_V6_LEASES_RECLAMATION_TIMEOUT
const isc::log::MessageID DHCPSRV_CFGMGR_IP_RESERVATIONS_UNIQUE_DUPLICATES_DETECTED
const isc::log::MessageID ALLOC_ENGINE_V6_HR_ADDR_GRANTED
const isc::log::MessageID ALLOC_ENGINE_V6_ALLOC_FAIL_CLASSES
const isc::log::MessageID ALLOC_ENGINE_V6_NO_MORE_EXPIRED_LEASES
const isc::log::MessageID ALLOC_ENGINE_V4_RECLAIMED_LEASES_DELETE
boost::shared_ptr< SharedNetwork6 > SharedNetwork6Ptr
Pointer to SharedNetwork6 object.
const isc::log::MessageID ALLOC_ENGINE_V6_EXTEND_NEW_LEASE_DATA
const isc::log::MessageID ALLOC_ENGINE_V6_ALLOC_ERROR
const isc::log::MessageID ALLOC_ENGINE_V6_REVOKED_ADDR_LEASE
const isc::log::MessageID ALLOC_ENGINE_V4_OFFER_EXISTING_LEASE
const isc::log::MessageID ALLOC_ENGINE_V6_ALLOC_FAIL_NO_POOLS
const isc::log::MessageID ALLOC_ENGINE_V6_ALLOC_FAIL_SHARED_NETWORK
const isc::log::MessageID ALLOC_ENGINE_V6_EXPIRED_HINT_RESERVED
boost::shared_ptr< ClientClassDictionary > ClientClassDictionaryPtr
Defines a pointer to a ClientClassDictionary.
const int ALLOC_ENGINE_DBG_TRACE_DETAIL_DATA
Records detailed results of various operations.
const int DHCPSRV_DBG_HOOKS
const isc::log::MessageID ALLOC_ENGINE_V6_LEASES_RECLAMATION_FAILED
const isc::log::MessageID ALLOC_ENGINE_V6_RECLAIMED_LEASES_DELETE_COMPLETE
uint32_t SubnetID
Defines unique IPv4 or IPv6 subnet identifier.
const isc::log::MessageID ALLOC_ENGINE_V6_REVOKED_PREFIX_LEASE
boost::shared_ptr< ClientId > ClientIdPtr
Shared pointer to a Client ID.
const isc::log::MessageID ALLOC_ENGINE_V4_NO_MORE_EXPIRED_LEASES
const isc::log::MessageID DHCPSRV_HOOK_LEASE6_EXTEND_SKIP
const isc::log::MessageID ALLOC_ENGINE_V4_REQUEST_PICK_ADDRESS
const isc::log::MessageID ALLOC_ENGINE_V4_OFFER_NEW_LEASE
boost::shared_ptr< Option6IAAddr > Option6IAAddrPtr
A pointer to the isc::dhcp::Option6IAAddr object.
const isc::log::MessageID DHCPSRV_HOOK_LEASE4_SELECT_SKIP
boost::shared_ptr< const Host > ConstHostPtr
Const pointer to the Host object.
const isc::log::MessageID ALLOC_ENGINE_V6_ALLOC_FAIL
const isc::log::MessageID DHCPSRV_HOOK_LEASE6_RECOVER_SKIP
const isc::log::MessageID ALLOC_ENGINE_V4_RECLAIMED_LEASES_DELETE_FAILED
const isc::log::MessageID ALLOC_ENGINE_V6_LEASES_RECLAMATION_COMPLETE
const isc::log::MessageID ALLOC_ENGINE_V4_LEASES_RECLAMATION_FAILED
const isc::log::MessageID ALLOC_ENGINE_V6_CALCULATED_PREFERRED_LIFETIME
void deleteAssignedLease(Lease4Ptr lease)
const isc::log::MessageID ALLOC_ENGINE_V6_ALLOC_UNRESERVED
const isc::log::MessageID ALLOC_ENGINE_V6_DECLINED_RECOVERED
boost::shared_ptr< const Subnet > ConstSubnetPtr
A generic pointer to either const Subnet4 or const Subnet6 object.
const isc::log::MessageID ALLOC_ENGINE_V6_LEASES_RECLAMATION_START
boost::shared_ptr< Pkt6 > Pkt6Ptr
A pointer to Pkt6 packet.
const isc::log::MessageID ALLOC_ENGINE_V6_LEASE_RECLAMATION_FAILED
boost::shared_ptr< SharedNetwork4 > SharedNetwork4Ptr
Pointer to SharedNetwork4 object.
std::vector< Lease4Ptr > Lease4Collection
A collection of IPv4 leases.
const isc::log::MessageID ALLOC_ENGINE_V4_REQUEST_ALLOC_REQUESTED
const isc::log::MessageID ALLOC_ENGINE_V6_ALLOC_LEASES_NO_HR
const isc::log::MessageID ALLOC_ENGINE_V4_ALLOC_FAIL_SUBNET
const isc::log::MessageID ALLOC_ENGINE_V4_DISCOVER_ADDRESS_CONFLICT
const isc::log::MessageID DHCPSRV_HOOK_LEASE4_RENEW_SKIP
boost::shared_ptr< Lease4 > Lease4Ptr
Pointer to a Lease4 structure.
const isc::log::MessageID ALLOC_ENGINE_V4_REQUEST_REMOVE_LEASE
const isc::log::MessageID ALLOC_ENGINE_V6_RECLAIMED_LEASES_DELETE
boost::shared_ptr< Option > OptionPtr
const isc::log::MessageID ALLOC_ENGINE_V6_ALLOC_FAIL_SUBNET
const int ALLOC_ENGINE_DBG_TRACE_DETAIL
Record detailed traces.
const isc::log::MessageID ALLOC_ENGINE_V4_ALLOC_FAIL_SHARED_NETWORK
const isc::log::MessageID ALLOC_ENGINE_V6_HR_PREFIX_GRANTED
const isc::log::MessageID ALLOC_ENGINE_V4_ALLOC_FAIL_CLASSES
boost::shared_ptr< Pool6 > Pool6Ptr
a pointer an IPv6 Pool
boost::shared_ptr< CalloutHandle > CalloutHandlePtr
A shared pointer to a CalloutHandle object.
string encodeHex(const vector< uint8_t > &binary)
Encode binary data in the base16 format.
boost::multiprecision::checked_uint128_t uint128_t
Defines the logger used by the top-level component of kea-lfc.
This file provides the classes needed to embody, compose, and decompose DNS update requests that are ...
Context information for the DHCPv4 lease allocation.
ClientIdPtr clientid_
Client identifier from the DHCP message.
DdnsParamsPtr getDdnsParams()
Returns the set of DDNS behavioral parameters based on the selected subnet.
bool early_global_reservations_lookup_
Indicates if early global reservation is enabled.
ConstHostPtr currentHost() const
Returns host for currently selected subnet.
ClientContext4()
Default constructor.
Pkt4Ptr query_
A pointer to the client's message.
Lease4Ptr new_lease_
A pointer to a newly allocated lease.
std::string hostname_
Hostname.
std::map< SubnetID, ConstHostPtr > hosts_
Holds a map of hosts belonging to the client within different subnets.
ConstSubnet4Ptr subnet_
Subnet selected for the client by the server.
bool rev_dns_update_
Perform reverse DNS update.
uint32_t offer_lft_
If not zero, then we will allocate on DISCOVER for this amount of time.
bool fake_allocation_
Indicates if this is a real or fake allocation.
hooks::CalloutHandlePtr callout_handle_
Callout handle associated with the client's message.
bool unknown_requested_addr_
True when the address DHCPREQUEST'ed by client is not within a dynamic pool the server knows about.
Lease4Ptr old_lease_
A pointer to an old lease that the client had before update.
ConstHostPtr globalHost() const
Returns global host reservation if there is one.
bool fwd_dns_update_
Perform forward DNS update.
asiolink::IOAddress requested_address_
An address that the client desires.
Lease4Ptr conflicting_lease_
A pointer to the object representing a lease in conflict.
void addHostIdentifier(const Host::IdentifierType &id_type, const std::vector< uint8_t > &identifier)
Convenience function adding host identifier into host_identifiers_ list.
IdentifierList host_identifiers_
A list holding host identifiers extracted from a message received by the server.
HWAddrPtr hwaddr_
HW address from the DHCP message.
IAContext()
Default constructor.
Lease6Collection old_leases_
A pointer to any old leases that the client had before update but are no longer valid after the updat...
Option6IAPtr ia_rsp_
A pointer to the IA_NA/IA_PD option to be sent in response.
Lease::Type type_
Lease type (IA or PD)
ResourceContainer new_resources_
Holds addresses and prefixes allocated for this IA.
bool isNewResource(const asiolink::IOAddress &prefix, const uint8_t prefix_len=128) const
Checks if specified address or prefix was new.
Lease6Collection changed_leases_
A pointer to any leases that have changed FQDN information.
void addHint(const asiolink::IOAddress &prefix, const uint8_t prefix_len=128, const uint32_t preferred=0, const uint32_t valid=0)
Convenience method adding new hint.
void addNewResource(const asiolink::IOAddress &prefix, const uint8_t prefix_len=128)
Convenience method adding new prefix or address.
Lease6Collection reused_leases_
Set of leases marked for reuse by lease caching.
HintContainer hints_
Client's hints.
uint32_t iaid_
The IAID field from IA_NA or IA_PD that is being processed.
Context information for the DHCPv6 leases allocation.
IAContext & currentIA()
Returns IA specific context for the currently processed IA.
std::vector< IAContext > ias_
Container holding IA specific contexts.
void addHostIdentifier(const Host::IdentifierType &id_type, const std::vector< uint8_t > &identifier)
Convenience function adding host identifier into host_identifiers_ list.
bool fake_allocation_
Indicates if this is a real or fake allocation.
ConstHostPtr currentHost() const
Returns host from the most preferred subnet.
ClientContext6()
Default constructor.
DuidPtr duid_
Client identifier.
void addAllocatedResource(const asiolink::IOAddress &prefix, const uint8_t prefix_len=128)
Convenience method adding allocated prefix or address.
Lease6Collection new_leases_
A collection of newly allocated leases.
HWAddrPtr hwaddr_
Hardware/MAC address (if available, may be NULL)
hooks::CalloutHandlePtr callout_handle_
Callout handle associated with the client's message.
bool isAllocated(const asiolink::IOAddress &prefix, const uint8_t prefix_len=128) const
Checks if specified address or prefix was allocated.
bool hasGlobalReservation(const IPv6Resrv &resv) const
Determines if a global reservation exists.
ResourceContainer allocated_resources_
Holds addresses and prefixes allocated for all IAs.
bool rev_dns_update_
A boolean value which indicates that server takes responsibility for the reverse DNS Update for this ...
DdnsParamsPtr getDdnsParams()
Returns the set of DDNS behavioral parameters based on the selected subnet.
ConstHostPtr globalHost() const
Returns global host reservation if there is one.
Pkt6Ptr query_
A pointer to the client's message.
bool early_global_reservations_lookup_
Indicates if early global reservation is enabled.
std::string hostname_
Hostname.
ConstSubnet6Ptr host_subnet_
Subnet from which host reservations should be retrieved.
IdentifierList host_identifiers_
A list holding host identifiers extracted from a message received by the server.
ConstSubnet6Ptr subnet_
Subnet selected for the client by the server.
std::map< SubnetID, ConstHostPtr > hosts_
Holds a map of hosts belonging to the client within different subnets.
bool fwd_dns_update_
A boolean value which indicates that server takes responsibility for the forward DNS Update for this ...
Structure that holds a lease for IPv4 address.
@ ACTION_UPDATE
update extended info tables.
@ ACTION_DELETE
delete reference to the lease
@ ACTION_IGNORE
ignore extended info,
a common structure for IPv4 and IPv6 leases
static const uint32_t INFINITY_LFT
Infinity (means static, i.e. never expire)
static const uint32_t STATE_DEFAULT
A lease in the default state.
static const uint32_t STATE_DECLINED
Declined lease.
static const uint32_t STATE_RELEASED
Released lease held in the database for lease affinity.
static const uint32_t STATE_EXPIRED_RECLAIMED
Expired and reclaimed lease.
Type
Type of lease or pool.
@ TYPE_PD
the lease contains IPv6 prefix (for prefix delegation)
@ TYPE_NA
the lease contains non-temporary IPv6 address
static const uint32_t STATE_REGISTERED
Registered self-generated lease.