34#include <boost/foreach.hpp>
35#include <boost/make_shared.hpp>
51namespace ph = std::placeholders;
56struct AllocEngineHooks {
57 int hook_index_lease4_select_;
58 int hook_index_lease4_renew_;
59 int hook_index_lease4_expire_;
60 int hook_index_lease4_recover_;
61 int hook_index_lease6_select_;
62 int hook_index_lease6_renew_;
63 int hook_index_lease6_rebind_;
64 int hook_index_lease6_expire_;
65 int hook_index_lease6_recover_;
69 hook_index_lease4_select_ = HooksManager::registerHook(
"lease4_select");
70 hook_index_lease4_renew_ = HooksManager::registerHook(
"lease4_renew");
71 hook_index_lease4_expire_ = HooksManager::registerHook(
"lease4_expire");
72 hook_index_lease4_recover_= HooksManager::registerHook(
"lease4_recover");
73 hook_index_lease6_select_ = HooksManager::registerHook(
"lease6_select");
74 hook_index_lease6_renew_ = HooksManager::registerHook(
"lease6_renew");
75 hook_index_lease6_rebind_ = HooksManager::registerHook(
"lease6_rebind");
76 hook_index_lease6_expire_ = HooksManager::registerHook(
"lease6_expire");
77 hook_index_lease6_recover_= HooksManager::registerHook(
"lease6_recover");
85AllocEngineHooks
Hooks;
93 : attempts_(attempts), incomplete_v4_reclamations_(0),
94 incomplete_v6_reclamations_(0) {
97 hook_index_lease4_select_ =
Hooks.hook_index_lease4_select_;
98 hook_index_lease6_select_ =
Hooks.hook_index_lease6_select_;
125 if (CfgMgr::instance().getCurrentCfg()->getCfgDbAccess()->getIPReservationsUnique()) {
126 auto host = HostMgr::instance().get6(subnet_id, address);
128 reserved.push_back(host);
131 auto hosts = HostMgr::instance().getAll6(subnet_id, address);
132 reserved.insert(reserved.end(), hosts.begin(), hosts.end());
151 const IOAddress& address,
bool check_subnet) {
155 auto const& classes = ctx.
query_->getClasses();
157 while (current_subnet) {
158 if (current_subnet->clientSupported(classes)) {
160 if (current_subnet->inPool(lease_type, address)) {
164 if (current_subnet->inPool(lease_type, address, classes)) {
170 current_subnet = current_subnet->getNextSubnet(ctx.
subnet_);
186 : query_(), fake_allocation_(false),
187 early_global_reservations_lookup_(false), subnet_(), host_subnet_(),
188 duid_(), hwaddr_(), host_identifiers_(), hosts_(),
189 fwd_dns_update_(false), rev_dns_update_(false), hostname_(),
190 callout_handle_(), ias_(), ddns_params_() {
197 const std::string& hostname,
198 const bool fake_allocation,
201 : query_(query), fake_allocation_(fake_allocation),
202 early_global_reservations_lookup_(false), subnet_(subnet),
203 duid_(duid), hwaddr_(), host_identifiers_(), hosts_(),
204 fwd_dns_update_(fwd_dns), rev_dns_update_(rev_dns), hostname_(hostname),
205 callout_handle_(callout_handle), allocated_resources_(), new_leases_(),
206 ias_(), ddns_params_() {
215 : iaid_(0), type_(
Lease::TYPE_NA), hints_(), old_leases_(),
216 changed_leases_(), new_resources_(), ia_rsp_() {
222 const uint8_t prefix_len,
223 const uint32_t preferred,
224 const uint32_t valid) {
225 hints_.push_back(
Resource(prefix, prefix_len, preferred, valid));
234 addHint(iaaddr->getAddress(), 128,
235 iaaddr->getPreferred(), iaaddr->getValid());
244 addHint(iaprefix->getAddress(), iaprefix->getLength(),
245 iaprefix->getPreferred(), iaprefix->getValid());
251 const uint8_t prefix_len) {
252 static_cast<void>(new_resources_.insert(
Resource(prefix, prefix_len)));
258 const uint8_t prefix_len)
const {
259 return (
static_cast<bool>(new_resources_.count(
Resource(prefix,
266 const uint8_t prefix_len) {
274 return (
static_cast<bool>
281 if (subnet && subnet->getReservationsInSubnet()) {
282 auto host =
hosts_.find(subnet->getID());
283 if (host !=
hosts_.cend()) {
284 return (host->second);
294 if (subnet &&
subnet_->getReservationsGlobal()) {
295 auto host =
hosts_.find(SUBNET_ID_GLOBAL);
296 if (host !=
hosts_.cend()) {
297 return (host->second);
307 return (ghost && ghost->hasReservation(resv));
313 if (ddns_params_ &&
subnet_ && (
subnet_->getID() == ddns_params_->getSubnetId())) {
314 return (ddns_params_);
320 return (ddns_params_);
339 !subnet->getReservationsInSubnet()) {
345 subnet->getReservationsGlobal()) {
348 ctx.
hosts_[SUBNET_ID_GLOBAL] = ghost;
351 if (!subnet->getReservationsInSubnet()) {
357 std::map<SubnetID, ConstHostPtr> host_map;
359 subnet->getSharedNetwork(network);
368 const bool use_single_query = network &&
372 if (use_single_query) {
376 id_pair.second.size());
380 for (
auto host = hosts.begin(); host != hosts.end(); ++host) {
381 if ((*host)->getIPv6SubnetID() != SUBNET_ID_GLOBAL) {
382 host_map[(*host)->getIPv6SubnetID()] = *host;
388 auto const& classes = ctx.
query_->getClasses();
395 if (subnet->clientSupported(classes) && subnet->getReservationsInSubnet()) {
398 if (use_single_query) {
399 if (host_map.count(subnet->getID()) > 0) {
400 ctx.
hosts_[subnet->getID()] = host_map[subnet->getID()];
408 id_pair.second.size());
411 ctx.
hosts_[subnet->getID()] = host;
421 subnet = subnet->getNextSubnet(ctx.
subnet_, classes);
427 for (
auto host : ctx.
hosts_) {
428 host.second->encapsulateOptions();
438 &id_pair.second[0], id_pair.second.size());
472 for (
auto l : all_leases) {
473 if ((l)->subnet_id_ == subnet->getID()) {
478 subnet = subnet->getNextSubnet(ctx.
subnet_);
498 if (leases.empty() && !ctx.
hosts_.empty()) {
502 .arg(ctx.
query_->getLabel());
507 allocateReservedLeases6(ctx, leases);
509 leases = updateLeaseData(ctx, leases);
524 }
else if (!leases.empty() && ctx.
hosts_.empty()) {
528 .arg(ctx.
query_->getLabel());
532 removeNonmatchingReservedLeases6(ctx, leases);
534 leases = updateLeaseData(ctx, leases);
543 }
else if (!leases.empty() && !ctx.
hosts_.empty()) {
547 .arg(ctx.
query_->getLabel());
551 allocateReservedLeases6(ctx, leases);
563 removeNonmatchingReservedLeases6(ctx, leases);
572 removeNonreservedLeases6(ctx, leases);
577 leases = updateLeaseData(ctx, leases);
590 if (leases.empty()) {
604 .arg(ctx.
query_->getLabel());
606 leases = allocateUnreservedLeases6(ctx);
609 if (!leases.empty()) {
624 .arg(ctx.
query_->getLabel())
637 uint8_t hint_prefix_length = 128;
638 if (!ctx.currentIA().hints_.empty()) {
640 hint = ctx.currentIA().hints_[0].getAddress();
641 hint_prefix_length = ctx.currentIA().hints_[0].getPrefixLength();
650 uint64_t total_attempts = 0;
654 uint64_t subnets_with_unavail_leases = 0;
657 uint64_t subnets_with_unavail_pools = 0;
667 bool search_hint_lease =
true;
674 if (hint_prefix_length == 128) {
675 hint_prefix_length = 0;
677 if (!hint_prefix_length) {
685 Lease6Ptr lease = allocateBestMatch(ctx, hint_lease, search_hint_lease,
686 hint, hint_prefix_length, subnet,
687 network, total_attempts,
688 subnets_with_unavail_leases,
689 subnets_with_unavail_pools,
690 callout_status, prefix_length_match);
698 lease = allocateBestMatch(ctx, hint_lease, search_hint_lease, hint,
699 hint_prefix_length, subnet, network,
700 total_attempts, subnets_with_unavail_leases,
701 subnets_with_unavail_pools, callout_status,
702 prefix_length_match);
711 lease = allocateBestMatch(ctx, hint_lease, search_hint_lease, hint,
712 hint_prefix_length, subnet, network,
713 total_attempts, subnets_with_unavail_leases,
714 subnets_with_unavail_pools, callout_status,
715 prefix_length_match);
719 leases.push_back(lease);
723 auto const& classes = ctx.query_->getClasses();
729 .arg(ctx.query_->getLabel())
730 .arg(network->getName())
731 .arg(subnets_with_unavail_leases)
732 .arg(subnets_with_unavail_pools);
733 StatsMgr::instance().addValue(
"v6-allocation-fail-shared-network",
734 static_cast<int64_t
>(1));
735 StatsMgr::instance().addValue(
736 StatsMgr::generateName(
"subnet", ctx.subnet_->getID(),
737 "v6-allocation-fail-shared-network"),
738 static_cast<int64_t
>(1));
742 std::string shared_network = ctx.subnet_->getSharedNetworkName();
743 if (shared_network.empty()) {
744 shared_network =
"(none)";
747 .arg(ctx.query_->getLabel())
748 .arg(ctx.subnet_->toText())
749 .arg(ctx.subnet_->getID())
750 .arg(shared_network);
751 StatsMgr::instance().addValue(
"v6-allocation-fail-subnet",
752 static_cast<int64_t
>(1));
753 StatsMgr::instance().addValue(
754 StatsMgr::generateName(
"subnet", ctx.subnet_->getID(),
755 "v6-allocation-fail-subnet"),
756 static_cast<int64_t
>(1));
758 if (total_attempts == 0) {
764 .arg(ctx.query_->getLabel());
765 StatsMgr::instance().addValue(
"v6-allocation-fail-no-pools",
766 static_cast<int64_t
>(1));
767 StatsMgr::instance().addValue(
768 StatsMgr::generateName(
"subnet", ctx.subnet_->getID(),
769 "v6-allocation-fail-no-pools"),
770 static_cast<int64_t
>(1));
777 .arg(ctx.query_->getLabel())
778 .arg(total_attempts);
779 StatsMgr::instance().addValue(
"v6-allocation-fail",
780 static_cast<int64_t
>(1));
781 StatsMgr::instance().addValue(
782 StatsMgr::generateName(
"subnet", ctx.subnet_->getID(),
783 "v6-allocation-fail"),
784 static_cast<int64_t
>(1));
787 if (!classes.empty()) {
789 .arg(ctx.query_->getLabel())
790 .arg(classes.toText());
791 StatsMgr::instance().addValue(
"v6-allocation-fail-classes",
792 static_cast<int64_t
>(1));
793 StatsMgr::instance().addValue(
794 StatsMgr::generateName(
"subnet", ctx.subnet_->getID(),
795 "v6-allocation-fail-classes"),
796 static_cast<int64_t
>(1));
806 bool& search_hint_lease,
808 uint8_t hint_prefix_length,
811 uint64_t& total_attempts,
812 uint64_t& subnets_with_unavail_leases,
813 uint64_t& subnets_with_unavail_pools,
816 auto const& classes = ctx.query_->getClasses();
821 if (!search_hint_lease) {
822 usable_hint_lease = hint_lease;
824 for (; subnet; subnet = subnet->getNextSubnet(original_subnet)) {
825 if (!subnet->clientSupported(classes)) {
829 ctx.subnet_ = subnet;
833 pool = boost::dynamic_pointer_cast<Pool6>
834 (subnet->getPool(ctx.currentIA().type_, classes, hint));
837 if (!pool || !pool->clientSupported(classes)) {
843 hint_prefix_length)) {
847 bool in_subnet = subnet->getReservationsInSubnet();
850 if (search_hint_lease) {
851 search_hint_lease =
false;
853 usable_hint_lease = hint_lease;
855 if (!usable_hint_lease) {
867 (!subnet->getReservationsOutOfPool() ||
868 !subnet->inPool(ctx.currentIA().type_, hint))) {
869 hosts = getIPv6Resrv(subnet->getID(), hint);
879 Lease6Ptr new_lease = createLease6(ctx, hint, pool->getLength(), callout_status);
892 .arg(ctx.query_->getLabel())
896 }
else if (usable_hint_lease->expired()) {
905 (!subnet->getReservationsOutOfPool() ||
906 !subnet->inPool(ctx.currentIA().type_, hint))) {
907 hosts = getIPv6Resrv(subnet->getID(), hint);
916 ctx.currentIA().old_leases_.push_back(old_lease);
919 Lease6Ptr lease = reuseExpiredLease(usable_hint_lease, ctx,
929 .arg(ctx.query_->getLabel())
938 bool check_reservation_first = MultiThreadingMgr::instance().getMode();
941 if (!check_reservation_first) {
955 original_subnet->getSharedNetwork(network);
962 original_subnet = network->getPreferredSubnet(original_subnet, ctx.currentIA().type_);
965 ctx.subnet_ = subnet = original_subnet;
967 for (; subnet; subnet = subnet->getNextSubnet(original_subnet)) {
968 if (!subnet->clientSupported(classes)) {
979 subnet->getPoolCapacity(ctx.currentIA().type_,
990 (attempts_ == 0 || possible_attempts < attempts_) ?
994 if (max_attempts > 0) {
997 ++subnets_with_unavail_leases;
1001 ++subnets_with_unavail_pools;
1005 bool in_subnet = subnet->getReservationsInSubnet();
1006 bool out_of_pool = subnet->getReservationsOutOfPool();
1011 if (ctx.callout_handle_) {
1012 ctx.callout_handle_->setStatus(CalloutHandle::NEXT_STEP_CONTINUE);
1015 for (uint64_t i = 0; i < max_attempts; ++i) {
1018 auto allocator = subnet->getAllocator(ctx.currentIA().type_);
1023 uint8_t prefix_len = 128;
1025 candidate = allocator->pickPrefix(classes, pool, ctx.duid_,
1026 prefix_length_match, hint,
1027 hint_prefix_length);
1029 prefix_len = pool->getLength();
1032 candidate = allocator->pickAddress(classes, ctx.duid_, hint);
1041 if (check_reservation_first && in_subnet && !out_of_pool) {
1042 auto hosts = getIPv6Resrv(subnet->getID(), candidate);
1043 if (!hosts.empty()) {
1052 if (MultiThreadingMgr::instance().getMode() &&
1053 !resource_handler.
tryLock(ctx.currentIA().type_, candidate)) {
1066 if (!check_reservation_first && in_subnet && !out_of_pool) {
1067 auto hosts = getIPv6Resrv(subnet->getID(), candidate);
1068 if (!hosts.empty()) {
1077 ctx.subnet_ = subnet;
1078 Lease6Ptr new_lease = createLease6(ctx, candidate, prefix_len, callout_status);
1082 ctx.currentIA().old_leases_.clear();
1086 }
else if (ctx.callout_handle_ &&
1087 (callout_status != CalloutHandle::NEXT_STEP_CONTINUE)) {
1095 }
else if (existing->expired()) {
1097 if (!check_reservation_first && in_subnet && !out_of_pool) {
1098 auto hosts = getIPv6Resrv(subnet->getID(), candidate);
1099 if (!hosts.empty()) {
1108 ctx.currentIA().old_leases_.push_back(old_lease);
1110 ctx.subnet_ = subnet;
1111 existing = reuseExpiredLease(existing, ctx, prefix_len,
1126 if (ctx.hosts_.empty()) {
1129 .arg(ctx.query_->getLabel());
1140 BOOST_FOREACH(
const Lease6Ptr& lease, existing_leases) {
1141 if ((lease->valid_lft_ != 0)) {
1142 if ((ctx.hosts_.count(lease->subnet_id_) > 0) &&
1143 ctx.hosts_[lease->subnet_id_]->hasReservation(
makeIPv6Resrv(*lease))) {
1148 .arg(ctx.query_->getLabel())
1149 .arg(lease->typeToText(lease->type_))
1150 .arg(lease->addr_.toText());
1156 if (!ctx.host_subnet_) {
1158 ctx.subnet_->getSharedNetwork(network);
1163 ctx.host_subnet_ = network->getSubnet(lease->subnet_id_);
1171 if (host && !host->getHostname().empty()) {
1178 qualifyName(host->getHostname(), *ctx.getDdnsParams(),
1179 static_cast<bool>(fqdn));
1193 auto const& classes = ctx.query_->getClasses();
1194 for (
Subnet6Ptr subnet = ctx.subnet_; subnet;
1195 subnet = subnet->getNextSubnet(ctx.subnet_)) {
1197 SubnetID subnet_id = subnet->getID();
1200 if (!subnet->clientSupported(classes) || ctx.hosts_.count(subnet_id) == 0) {
1206 bool in_subnet = subnet->getReservationsInSubnet();
1212 const IOAddress& addr = type_lease_tuple.second.getPrefix();
1213 uint8_t prefix_len = type_lease_tuple.second.getPrefixLen();
1217 if (ctx.isAllocated(addr, prefix_len)) {
1226 (subnet->getReservationsOutOfPool() &&
1227 subnet->inPool(ctx.currentIA().type_, addr))) {
1239 ctx.subnet_ = subnet;
1241 if (!ctx.host_subnet_) {
1242 ctx.host_subnet_ = subnet;
1243 if (!host->getHostname().empty()) {
1257 qualifyName(host->getHostname(), *ctx.getDdnsParams(),
1258 static_cast<bool>(fqdn));
1264 Lease6Ptr lease = createLease6(ctx, addr, prefix_len, callout_status);
1267 existing_leases.push_back(lease);
1272 .arg(ctx.query_->getLabel());
1276 .arg(
static_cast<int>(prefix_len))
1277 .arg(ctx.query_->getLabel());
1295 allocateGlobalReservedLeases6(ctx, existing_leases);
1310 BOOST_FOREACH(
const Lease6Ptr& lease, existing_leases) {
1311 if ((lease->valid_lft_ != 0) &&
1317 .arg(ctx.query_->getLabel())
1318 .arg(lease->typeToText(lease->type_))
1319 .arg(lease->addr_.toText());
1325 if (!ghost->getHostname().empty()) {
1332 qualifyName(ghost->getHostname(), *ctx.getDdnsParams(),
1333 static_cast<bool>(fqdn));
1348 const IPv6ResrvRange& reservs = ghost->getIPv6Reservations(type);
1351 const IOAddress& addr = type_lease_tuple.second.getPrefix();
1352 uint8_t prefix_len = type_lease_tuple.second.getPrefixLen();
1356 if (ctx.isAllocated(addr, prefix_len)) {
1368 bool valid_subnet =
false;
1369 auto subnet = ctx.subnet_;
1371 if (subnet->inRange(addr)) {
1372 valid_subnet =
true;
1376 subnet = subnet->getNextSubnet(ctx.subnet_);
1379 if (!valid_subnet) {
1387 ctx.subnet_ = subnet;
1390 if (!ghost->getHostname().empty()) {
1404 qualifyName(ghost->getHostname(), *ctx.getDdnsParams(),
1405 static_cast<bool>(fqdn));
1410 Lease6Ptr lease = createLease6(ctx, addr, prefix_len, callout_status);
1413 existing_leases.push_back(lease);
1418 .arg(ctx.query_->getLabel());
1422 .arg(
static_cast<int>(prefix_len))
1423 .arg(ctx.query_->getLabel());
1441AllocEngine::removeNonmatchingReservedLeases6(
ClientContext6& ctx,
1444 if (existing_leases.empty() || !ctx.subnet_) {
1449 if (!ctx.subnet_->getReservationsInSubnet() &&
1450 !ctx.subnet_->getReservationsGlobal()) {
1451 removeNonmatchingReservedNoHostLeases6(ctx, existing_leases);
1464 if ((ctx.hasGlobalReservation(resv)) ||
1465 ((ctx.hosts_.count(candidate->subnet_id_) > 0) &&
1466 (ctx.hosts_[candidate->subnet_id_]->hasReservation(resv)))) {
1475 auto hosts = getIPv6Resrv(ctx.subnet_->getID(), candidate->addr_);
1480 if (hosts.empty() && inAllowedPool(ctx, candidate->type_,
1481 candidate->addr_,
false)) {
1485 if (!hosts.empty()) {
1488 if (hosts.size() == 1) {
1491 .arg(candidate->addr_.toText())
1492 .arg(ctx.duid_->toText())
1493 .arg(hosts.front()->getIdentifierAsText());
1496 .arg(candidate->addr_.toText())
1497 .arg(
static_cast<int>(candidate->prefixlen_))
1498 .arg(ctx.duid_->toText())
1499 .arg(hosts.front()->getIdentifierAsText());
1504 .arg(candidate->addr_.toText())
1505 .arg(ctx.duid_->toText())
1509 .arg(candidate->addr_.toText())
1510 .arg(
static_cast<int>(candidate->prefixlen_))
1511 .arg(ctx.duid_->toText())
1529 StatsMgr::instance().addValue(
1530 StatsMgr::generateName(
"subnet", candidate->subnet_id_,
1532 "assigned-nas" :
"assigned-pds"),
1533 static_cast<int64_t
>(-1));
1537 const auto& pool = subnet->getPool(ctx.currentIA().type_, candidate->addr_,
false);
1539 StatsMgr::instance().addValue(
1540 StatsMgr::generateName(
"subnet", subnet->getID(),
1541 StatsMgr::generateName(ctx.currentIA().type_ ==
Lease::TYPE_NA ?
"pool" :
"pd-pool", pool->getID(),
1542 ctx.currentIA().type_ ==
Lease::TYPE_NA ?
"assigned-nas" :
"assigned-pds")),
1543 static_cast<int64_t
>(-1));
1553 ctx.currentIA().old_leases_.push_back(candidate);
1556 removeLeases(existing_leases, candidate->addr_);
1561AllocEngine::removeNonmatchingReservedNoHostLeases6(
ClientContext6& ctx,
1572 if (inAllowedPool(ctx, candidate->type_,
1573 candidate->addr_,
false)) {
1588 StatsMgr::instance().addValue(
1589 StatsMgr::generateName(
"subnet", candidate->subnet_id_,
1591 "assigned-nas" :
"assigned-pds"),
1592 static_cast<int64_t
>(-1));
1596 const auto& pool = subnet->getPool(candidate->type_, candidate->addr_,
false);
1598 StatsMgr::instance().addValue(
1599 StatsMgr::generateName(
"subnet", subnet->getID(),
1600 StatsMgr::generateName(candidate->type_ ==
Lease::TYPE_NA ?
"pool" :
"pd-pool", pool->getID(),
1601 candidate->type_ ==
Lease::TYPE_NA ?
"assigned-nas" :
"assigned-pds")),
1602 static_cast<int64_t
>(-1));
1607 ctx.currentIA().old_leases_.push_back(candidate);
1610 removeLeases(existing_leases, candidate->addr_);
1617 bool removed =
false;
1618 for (Lease6Collection::iterator lease = container.begin();
1619 lease != container.end(); ++lease) {
1620 if ((*lease)->addr_ == addr) {
1627 container.erase(std::remove(container.begin(), container.end(),
Lease6Ptr()),
1638 int total = existing_leases.size();
1645 for (Lease6Collection::iterator lease = existing_leases.begin();
1646 lease != existing_leases.end(); ++lease) {
1650 if (ctx.hasGlobalReservation(resv) ||
1651 ((ctx.hosts_.count((*lease)->subnet_id_) > 0) &&
1652 (ctx.hosts_[(*lease)->subnet_id_]->hasReservation(resv)))) {
1671 StatsMgr::instance().addValue(
1672 StatsMgr::generateName(
"subnet", (*lease)->subnet_id_,
1674 "assigned-nas" :
"assigned-pds"),
1675 static_cast<int64_t
>(-1));
1679 const auto& pool = subnet->getPool(ctx.currentIA().type_, (*lease)->addr_,
false);
1681 StatsMgr::instance().addValue(
1682 StatsMgr::generateName(
"subnet", subnet->getID(),
1683 StatsMgr::generateName(ctx.currentIA().type_ ==
Lease::TYPE_NA ?
"pool" :
"pd-pool", pool->getID(),
1684 ctx.currentIA().type_ ==
Lease::TYPE_NA ?
"assigned-nas" :
"assigned-pds")),
1685 static_cast<int64_t
>(-1));
1692 ctx.currentIA().old_leases_.push_back(*lease);
1707 existing_leases.erase(std::remove(existing_leases.begin(),
1708 existing_leases.end(),
Lease6Ptr()), existing_leases.end());
1716 if (!expired->expired()) {
1724 if (!ctx.fake_allocation_) {
1728 reclaimExpiredLease(expired, ctx.callout_handle_);
1732 expired->iaid_ = ctx.currentIA().iaid_;
1733 expired->duid_ = ctx.duid_;
1736 getLifetimes6(ctx, expired->preferred_lft_, expired->valid_lft_);
1737 expired->reuseable_valid_lft_ = 0;
1739 expired->cltt_ = time(NULL);
1740 expired->subnet_id_ = ctx.subnet_->getID();
1741 expired->hostname_ = ctx.hostname_;
1742 expired->fqdn_fwd_ = ctx.fwd_dns_update_;
1743 expired->fqdn_rev_ = ctx.rev_dns_update_;
1744 expired->prefixlen_ = prefix_len;
1749 .arg(ctx.query_->getLabel())
1750 .arg(expired->toText());
1753 if (ctx.callout_handle_ &&
1754 HooksManager::calloutsPresent(hook_index_lease6_select_)) {
1768 ctx.callout_handle_->setArgument(
"query6", ctx.query_);
1771 ctx.callout_handle_->setArgument(
"subnet6", ctx.subnet_);
1774 ctx.callout_handle_->setArgument(
"fake_allocation", ctx.fake_allocation_);
1777 ctx.callout_handle_->setArgument(
"lease6", expired);
1780 HooksManager::callCallouts(hook_index_lease6_select_, *ctx.callout_handle_);
1782 callout_status = ctx.callout_handle_->getStatus();
1787 if (callout_status == CalloutHandle::NEXT_STEP_SKIP) {
1799 ctx.callout_handle_->getArgument(
"lease6", expired);
1802 if (!ctx.fake_allocation_) {
1806 const auto& pool = ctx.subnet_->getPool(ctx.currentIA().type_, expired->addr_,
false);
1808 expired->pool_id_ = pool->getID();
1816 if (ctx.subnet_->inPool(ctx.currentIA().type_, expired->addr_)) {
1817 StatsMgr::instance().addValue(
1818 StatsMgr::generateName(
"subnet", ctx.subnet_->getID(),
1820 "assigned-nas" :
"assigned-pds"),
1821 static_cast<int64_t
>(1));
1823 StatsMgr::instance().addValue(
1824 StatsMgr::generateName(
"subnet", ctx.subnet_->getID(),
1826 "cumulative-assigned-nas" :
"cumulative-assigned-pds"),
1827 static_cast<int64_t
>(1));
1830 StatsMgr::instance().addValue(
1831 StatsMgr::generateName(
"subnet", ctx.subnet_->getID(),
1833 "pool" :
"pd-pool", pool->getID(),
1835 "assigned-nas" :
"assigned-pds")),
1836 static_cast<int64_t
>(1));
1838 StatsMgr::instance().addValue(
1839 StatsMgr::generateName(
"subnet", ctx.subnet_->getID(),
1841 "pool" :
"pd-pool", pool->getID(),
1843 "cumulative-assigned-nas" :
"cumulative-assigned-pds")),
1844 static_cast<int64_t
>(1));
1847 StatsMgr::instance().addValue(ctx.currentIA().type_ ==
Lease::TYPE_NA ?
1848 "cumulative-assigned-nas" :
"cumulative-assigned-pds",
1849 static_cast<int64_t
>(1));
1868 if (!classes.
empty()) {
1875 for (
auto name = classes.
cbegin();
1876 name != classes.
cend() && have_both < 2; ++name) {
1879 (cl && (!cl->getPreferred().unspecified()))) {
1880 candidate_preferred = cl->getPreferred();
1885 (cl && (!cl->getValid().unspecified()))) {
1886 candidate_valid = cl->getValid();
1893 if (!candidate_preferred) {
1894 candidate_preferred = ctx.
subnet_->getPreferred();
1898 if (!candidate_valid) {
1899 candidate_valid = ctx.
subnet_->getValid();
1903 preferred = candidate_preferred;
1904 valid = candidate_valid;
1919 if (!preferred || preferred > valid) {
1920 preferred = ((valid * 5)/8);
1923 .arg(ctx.
query_->getLabel())
1937 uint32_t preferred = 0;
1942 ctx.currentIA().iaid_, preferred,
1943 valid, ctx.subnet_->getID(),
1944 ctx.hwaddr_, prefix_len));
1946 lease->fqdn_fwd_ = ctx.fwd_dns_update_;
1947 lease->fqdn_rev_ = ctx.rev_dns_update_;
1948 lease->hostname_ = ctx.hostname_;
1951 if (ctx.callout_handle_ &&
1952 HooksManager::calloutsPresent(hook_index_lease6_select_)) {
1966 ctx.callout_handle_->setArgument(
"query6", ctx.query_);
1969 ctx.callout_handle_->setArgument(
"subnet6", ctx.subnet_);
1972 ctx.callout_handle_->setArgument(
"fake_allocation", ctx.fake_allocation_);
1975 ctx.callout_handle_->setArgument(
"lease6", lease);
1978 HooksManager::callCallouts(hook_index_lease6_select_, *ctx.callout_handle_);
1980 callout_status = ctx.callout_handle_->getStatus();
1985 if (callout_status == CalloutHandle::NEXT_STEP_SKIP) {
1992 ctx.callout_handle_->getArgument(
"lease6", lease);
1995 if (!ctx.fake_allocation_) {
1999 const auto& pool = ctx.subnet_->getPool(ctx.currentIA().type_, lease->addr_,
false);
2001 lease->pool_id_ = pool->getID();
2010 if (ctx.subnet_->inPool(ctx.currentIA().type_, addr)) {
2011 StatsMgr::instance().addValue(
2012 StatsMgr::generateName(
"subnet", ctx.subnet_->getID(),
2014 "assigned-nas" :
"assigned-pds"),
2015 static_cast<int64_t
>(1));
2017 StatsMgr::instance().addValue(
2018 StatsMgr::generateName(
"subnet", ctx.subnet_->getID(),
2020 "cumulative-assigned-nas" :
"cumulative-assigned-pds"),
2021 static_cast<int64_t
>(1));
2024 StatsMgr::instance().addValue(
2025 StatsMgr::generateName(
"subnet", ctx.subnet_->getID(),
2027 "pool" :
"pd-pool", pool->getID(),
2029 "assigned-nas" :
"assigned-pds")),
2030 static_cast<int64_t
>(1));
2032 StatsMgr::instance().addValue(
2033 StatsMgr::generateName(
"subnet", ctx.subnet_->getID(),
2035 "pool" :
"pd-pool", pool->getID(),
2037 "cumulative-assigned-nas" :
"cumulative-assigned-pds")),
2038 static_cast<int64_t
>(1));
2041 StatsMgr::instance().addValue(ctx.currentIA().type_ ==
Lease::TYPE_NA ?
2042 "cumulative-assigned-nas" :
"cumulative-assigned-pds",
2043 static_cast<int64_t
>(1));
2047 ctx.currentIA().addNewResource(addr, prefix_len);
2086 leases.insert(leases.end(), leases_subnet.begin(), leases_subnet.end());
2088 subnet = subnet->getNextSubnet(ctx.
subnet_);
2091 if (!leases.empty()) {
2094 .arg(ctx.
query_->getLabel());
2098 removeNonmatchingReservedLeases6(ctx, leases);
2101 if (!ctx.
hosts_.empty()) {
2105 .arg(ctx.
query_->getLabel());
2108 allocateReservedLeases6(ctx, leases);
2114 removeNonreservedLeases6(ctx, leases);
2121 if (leases.empty()) {
2125 .arg(ctx.
query_->getLabel());
2127 leases = allocateUnreservedLeases6(ctx);
2131 for (Lease6Collection::iterator l = leases.begin(); l != leases.end(); ++l) {
2133 (*l)->prefixlen_)) {
2139 .arg(ctx.
query_->getLabel())
2140 .arg((*l)->typeToText((*l)->type_))
2142 extendLease6(ctx, *l);
2145 if (!leases.empty()) {
2149 BOOST_FOREACH(
Lease6Ptr lease, leases) {
2161 .arg(ctx.
query_->getLabel())
2171 if (!lease || !ctx.subnet_) {
2177 if (ctx.subnet_->getID() != lease->subnet_id_) {
2179 ctx.subnet_->getSharedNetwork(network);
2185 ctx.subnet_ = subnet;
2193 (((lease->type_ !=
Lease::TYPE_PD) && !ctx.subnet_->inRange(lease->addr_)) ||
2194 !ctx.subnet_->clientSupported(ctx.query_->getClasses()))) {
2208 StatsMgr::instance().addValue(
2209 StatsMgr::generateName(
"subnet", ctx.subnet_->getID(),
2211 "assigned-nas" :
"assigned-pds"),
2212 static_cast<int64_t
>(-1));
2214 const auto& pool = ctx.subnet_->getPool(ctx.currentIA().type_, lease->addr_,
false);
2216 StatsMgr::instance().addValue(
2217 StatsMgr::generateName(
"subnet", ctx.subnet_->getID(),
2219 "pool" :
"pd-pool", pool->getID(),
2221 "assigned-nas" :
"assigned-pds")),
2222 static_cast<int64_t
>(-1));
2226 ctx.currentIA().old_leases_.push_back(lease);
2233 .arg(ctx.query_->getLabel())
2234 .arg(lease->toText());
2239 bool changed =
false;
2242 uint32_t current_preferred_lft = lease->preferred_lft_;
2243 getLifetimes6(ctx, lease->preferred_lft_, lease->valid_lft_);
2246 if ((lease->preferred_lft_ != current_preferred_lft) ||
2247 (lease->valid_lft_ != lease->current_valid_lft_)) {
2251 lease->cltt_ = time(NULL);
2252 if ((lease->fqdn_fwd_ != ctx.fwd_dns_update_) ||
2253 (lease->fqdn_rev_ != ctx.rev_dns_update_) ||
2254 (lease->hostname_ != ctx.hostname_)) {
2256 lease->hostname_ = ctx.hostname_;
2257 lease->fqdn_fwd_ = ctx.fwd_dns_update_;
2258 lease->fqdn_rev_ = ctx.rev_dns_update_;
2260 if ((!ctx.hwaddr_ && lease->hwaddr_) ||
2262 (!lease->hwaddr_ || (*ctx.hwaddr_ != *lease->hwaddr_)))) {
2264 lease->hwaddr_ = ctx.hwaddr_;
2272 .arg(ctx.query_->getLabel())
2273 .arg(lease->toText());
2277 int hook_point = ctx.query_->getType() ==
DHCPV6_RENEW ?
2278 Hooks.hook_index_lease6_renew_ :
Hooks.hook_index_lease6_rebind_;
2279 if (HooksManager::calloutsPresent(hook_point)) {
2292 callout_handle->setArgument(
"query6", ctx.query_);
2295 callout_handle->setArgument(
"lease6", lease);
2299 callout_handle->setArgument(
"ia_na", ctx.currentIA().ia_rsp_);
2301 callout_handle->setArgument(
"ia_pd", ctx.currentIA().ia_rsp_);
2305 HooksManager::callCallouts(hook_point, *callout_handle);
2310 if (callout_handle->getStatus() == CalloutHandle::NEXT_STEP_SKIP) {
2314 .arg(ctx.query_->getName());
2321 bool update_stats =
false;
2325 if (old_data->expired()) {
2326 reclaimExpiredLease(old_data, ctx.callout_handle_);
2330 if (ctx.subnet_->inPool(ctx.currentIA().type_, old_data->addr_)) {
2331 update_stats =
true;
2344 setLeaseReusable(lease, current_preferred_lft, ctx);
2349 if (lease->reuseable_valid_lft_ == 0) {
2350 const auto& pool = ctx.subnet_->getPool(ctx.currentIA().type_, lease->addr_,
false);
2352 lease->pool_id_ = pool->getID();
2358 StatsMgr::instance().addValue(
2359 StatsMgr::generateName(
"subnet", ctx.subnet_->getID(),
2361 "assigned-nas" :
"assigned-pds"),
2362 static_cast<int64_t
>(1));
2364 StatsMgr::instance().addValue(
2365 StatsMgr::generateName(
"subnet", ctx.subnet_->getID(),
2367 "cumulative-assigned-nas" :
"cumulative-assigned-pds"),
2368 static_cast<int64_t
>(1));
2370 const auto& pool = ctx.subnet_->getPool(ctx.currentIA().type_, lease->addr_,
false);
2372 StatsMgr::instance().addValue(
2373 StatsMgr::generateName(
"subnet", ctx.subnet_->getID(),
2375 "pool" :
"pd-pool", pool->getID(),
2377 "assigned-nas" :
"assigned-pds")),
2378 static_cast<int64_t
>(1));
2380 StatsMgr::instance().addValue(
2381 StatsMgr::generateName(
"subnet", ctx.subnet_->getID(),
2383 "pool" :
"pd-pool", pool->getID(),
2385 "cumulative-assigned-nas" :
"cumulative-assigned-pds")),
2386 static_cast<int64_t
>(1));
2389 StatsMgr::instance().addValue(ctx.currentIA().type_ ==
Lease::TYPE_NA ?
2390 "cumulative-assigned-nas" :
"cumulative-assigned-pds",
2391 static_cast<int64_t
>(1));
2404 ctx.currentIA().changed_leases_.push_back(old_data);
2410 for (Lease6Collection::const_iterator lease_it = leases.begin();
2411 lease_it != leases.end(); ++lease_it) {
2413 if (ctx.currentIA().isNewResource(lease->addr_, lease->prefixlen_)) {
2415 updated_leases.push_back(lease);
2419 lease->reuseable_valid_lft_ = 0;
2420 lease->fqdn_fwd_ = ctx.fwd_dns_update_;
2421 lease->fqdn_rev_ = ctx.rev_dns_update_;
2422 lease->hostname_ = ctx.hostname_;
2423 uint32_t current_preferred_lft = lease->preferred_lft_;
2424 if (lease->valid_lft_ == 0) {
2426 getLifetimes6(ctx, lease->preferred_lft_, lease->valid_lft_);
2428 if (!ctx.fake_allocation_) {
2429 bool update_stats =
false;
2437 if (inAllowedPool(ctx, ctx.currentIA().type_,
2438 lease->addr_,
true)) {
2439 update_stats =
true;
2444 !(lease->hasIdenticalFqdn(**lease_it)));
2446 lease->cltt_ = time(NULL);
2447 if (!fqdn_changed) {
2448 setLeaseReusable(lease, current_preferred_lft, ctx);
2450 if (lease->reuseable_valid_lft_ == 0) {
2451 ctx.currentIA().changed_leases_.push_back(*lease_it);
2456 StatsMgr::instance().addValue(
2457 StatsMgr::generateName(
"subnet", lease->subnet_id_,
2459 "assigned-nas" :
"assigned-pds"),
2460 static_cast<int64_t
>(1));
2462 StatsMgr::instance().addValue(
2463 StatsMgr::generateName(
"subnet", lease->subnet_id_,
2465 "cumulative-assigned-nas" :
"cumulative-assigned-pds"),
2466 static_cast<int64_t
>(1));
2468 const auto& pool = ctx.subnet_->getPool(ctx.currentIA().type_, lease->addr_,
false);
2470 StatsMgr::instance().addValue(
2471 StatsMgr::generateName(
"subnet", ctx.subnet_->getID(),
2473 "pool" :
"pd-pool", pool->getID(),
2475 "assigned-nas" :
"assigned-pds")),
2476 static_cast<int64_t
>(1));
2478 StatsMgr::instance().addValue(
2479 StatsMgr::generateName(
"subnet", ctx.subnet_->getID(),
2481 "pool" :
"pd-pool", pool->getID(),
2483 "cumulative-assigned-nas" :
"cumulative-assigned-pds")),
2484 static_cast<int64_t
>(1));
2487 StatsMgr::instance().addValue(ctx.currentIA().type_ ==
Lease::TYPE_NA ?
2488 "cumulative-assigned-nas" :
"cumulative-assigned-pds",
2489 static_cast<int64_t
>(1));
2493 updated_leases.push_back(lease);
2496 return (updated_leases);
2501 const uint16_t timeout,
2502 const bool remove_lease,
2503 const uint16_t max_unwarned_cycles) {
2512 max_unwarned_cycles);
2513 }
catch (
const std::exception& ex) {
2522 const uint16_t timeout,
2523 const bool remove_lease,
2524 const uint16_t max_unwarned_cycles) {
2534 bool incomplete_reclamation =
false;
2537 if (max_leases > 0) {
2546 if (leases.size() > max_leases) {
2548 incomplete_reclamation =
true;
2561 if (!leases.empty() &&
2562 HooksManager::calloutsPresent(
Hooks.hook_index_lease6_expire_)) {
2563 callout_handle = HooksManager::createCalloutHandle();
2566 size_t leases_processed = 0;
2567 BOOST_FOREACH(
Lease6Ptr lease, leases) {
2571 if (MultiThreadingMgr::instance().getMode()) {
2575 reclaimExpiredLease(lease, remove_lease, callout_handle);
2578 reclaimExpiredLease(lease, remove_lease, callout_handle);
2582 }
catch (
const std::exception& ex) {
2584 .arg(lease->addr_.toText())
2595 if (!incomplete_reclamation) {
2596 if (leases_processed < leases.size()) {
2597 incomplete_reclamation =
true;
2614 .arg(leases_processed)
2619 if (incomplete_reclamation) {
2620 ++incomplete_v6_reclamations_;
2623 if ((max_unwarned_cycles > 0) &&
2624 (incomplete_v6_reclamations_ > max_unwarned_cycles)) {
2626 .arg(max_unwarned_cycles);
2628 incomplete_v6_reclamations_ = 0;
2633 incomplete_v6_reclamations_ = 0;
2646 uint64_t deleted_leases = 0;
2652 }
catch (
const std::exception& ex) {
2659 .arg(deleted_leases);
2664 const uint16_t timeout,
2665 const bool remove_lease,
2666 const uint16_t max_unwarned_cycles) {
2675 max_unwarned_cycles);
2676 }
catch (
const std::exception& ex) {
2685 const uint16_t timeout,
2686 const bool remove_lease,
2687 const uint16_t max_unwarned_cycles) {
2697 bool incomplete_reclamation =
false;
2700 if (max_leases > 0) {
2709 if (leases.size() > max_leases) {
2711 incomplete_reclamation =
true;
2724 if (!leases.empty() &&
2725 HooksManager::calloutsPresent(
Hooks.hook_index_lease4_expire_)) {
2726 callout_handle = HooksManager::createCalloutHandle();
2729 size_t leases_processed = 0;
2730 BOOST_FOREACH(
Lease4Ptr lease, leases) {
2734 if (MultiThreadingMgr::instance().getMode()) {
2738 reclaimExpiredLease(lease, remove_lease, callout_handle);
2741 reclaimExpiredLease(lease, remove_lease, callout_handle);
2745 }
catch (
const std::exception& ex) {
2747 .arg(lease->addr_.toText())
2758 if (!incomplete_reclamation) {
2759 if (leases_processed < leases.size()) {
2760 incomplete_reclamation =
true;
2777 .arg(leases_processed)
2782 if (incomplete_reclamation) {
2783 ++incomplete_v4_reclamations_;
2786 if ((max_unwarned_cycles > 0) &&
2787 (incomplete_v4_reclamations_ > max_unwarned_cycles)) {
2789 .arg(max_unwarned_cycles);
2791 incomplete_v4_reclamations_ = 0;
2796 incomplete_v4_reclamations_ = 0;
2803template<
typename LeasePtrType>
2805AllocEngine::reclaimExpiredLease(
const LeasePtrType& lease,
const bool remove_lease,
2807 reclaimExpiredLease(lease, remove_lease ? DB_RECLAIM_REMOVE : DB_RECLAIM_UPDATE,
2811template<
typename LeasePtrType>
2813AllocEngine::reclaimExpiredLease(
const LeasePtrType& lease,
2818 if (!lease->stateExpiredReclaimed()) {
2819 reclaimExpiredLease(lease, DB_RECLAIM_LEAVE_UNCHANGED, callout_handle);
2824AllocEngine::reclaimExpiredLease(
const Lease6Ptr& lease,
2825 const DbReclaimMode& reclaim_mode,
2831 .arg(lease->addr_.toText())
2832 .arg(
static_cast<int>(lease->prefixlen_));
2838 bool skipped =
false;
2839 if (callout_handle) {
2847 callout_handle->deleteAllArguments();
2848 callout_handle->setArgument(
"lease6", lease);
2849 callout_handle->setArgument(
"remove_lease", reclaim_mode == DB_RECLAIM_REMOVE);
2851 HooksManager::callCallouts(
Hooks.hook_index_lease6_expire_,
2854 skipped = callout_handle->getStatus() == CalloutHandle::NEXT_STEP_SKIP;
2869 bool remove_lease = (reclaim_mode == DB_RECLAIM_REMOVE);
2879 remove_lease = reclaimDeclined(lease);
2882 if (reclaim_mode != DB_RECLAIM_LEAVE_UNCHANGED) {
2886 reclaimLeaseInDatabase<Lease6Ptr>(lease, remove_lease,
2888 &lease_mgr, ph::_1));
2897 StatsMgr::instance().addValue(StatsMgr::generateName(
"subnet",
2900 static_cast<int64_t
>(-1));
2904 const auto& pool = subnet->getPool(lease->type_, lease->addr_,
false);
2906 StatsMgr::instance().addValue(
2907 StatsMgr::generateName(
"subnet", subnet->getID(),
2908 StatsMgr::generateName(
"pool" , pool->getID(),
2910 static_cast<int64_t
>(-1));
2912 StatsMgr::instance().addValue(
2913 StatsMgr::generateName(
"subnet", subnet->getID(),
2914 StatsMgr::generateName(
"pool" , pool->getID(),
2915 "reclaimed-leases")),
2916 static_cast<int64_t
>(1));
2922 StatsMgr::instance().addValue(StatsMgr::generateName(
"subnet",
2925 static_cast<int64_t
>(-1));
2929 const auto& pool = subnet->getPool(lease->type_, lease->addr_,
false);
2931 StatsMgr::instance().addValue(
2932 StatsMgr::generateName(
"subnet", subnet->getID(),
2933 StatsMgr::generateName(
"pd-pool" , pool->getID(),
2935 static_cast<int64_t
>(-1));
2937 StatsMgr::instance().addValue(
2938 StatsMgr::generateName(
"subnet", subnet->getID(),
2939 StatsMgr::generateName(
"pd-pool" , pool->getID(),
2940 "reclaimed-leases")),
2941 static_cast<int64_t
>(1));
2947 StatsMgr::instance().addValue(StatsMgr::generateName(
"subnet",
2949 "reclaimed-leases"),
2950 static_cast<int64_t
>(1));
2953 StatsMgr::instance().addValue(
"reclaimed-leases",
static_cast<int64_t
>(1));
2957AllocEngine::reclaimExpiredLease(
const Lease4Ptr& lease,
2958 const DbReclaimMode& reclaim_mode,
2964 .arg(lease->addr_.toText());
2970 bool skipped =
false;
2971 if (callout_handle) {
2979 callout_handle->setArgument(
"lease4", lease);
2980 callout_handle->setArgument(
"remove_lease", reclaim_mode == DB_RECLAIM_REMOVE);
2982 HooksManager::callCallouts(
Hooks.hook_index_lease4_expire_,
2985 skipped = callout_handle->getStatus() == CalloutHandle::NEXT_STEP_SKIP;
2998 lease->hostname_.clear();
2999 lease->fqdn_fwd_ =
false;
3000 lease->fqdn_rev_ =
false;
3004 bool remove_lease = (reclaim_mode == DB_RECLAIM_REMOVE);
3014 remove_lease = reclaimDeclined(lease);
3017 if (reclaim_mode != DB_RECLAIM_LEAVE_UNCHANGED) {
3021 reclaimLeaseInDatabase<Lease4Ptr>(lease, remove_lease,
3023 &lease_mgr, ph::_1));
3030 StatsMgr::instance().addValue(StatsMgr::generateName(
"subnet",
3032 "assigned-addresses"),
3033 static_cast<int64_t
>(-1));
3036 StatsMgr::instance().addValue(StatsMgr::generateName(
"subnet",
3038 "reclaimed-leases"),
3039 static_cast<int64_t
>(1));
3043 const auto& pool = subnet->getPool(
Lease::TYPE_V4, lease->addr_,
false);
3045 StatsMgr::instance().addValue(
3046 StatsMgr::generateName(
"subnet", subnet->getID(),
3047 StatsMgr::generateName(
"pool" , pool->getID(),
3048 "assigned-addresses")),
3049 static_cast<int64_t
>(-1));
3051 StatsMgr::instance().addValue(
3052 StatsMgr::generateName(
"subnet", subnet->getID(),
3053 StatsMgr::generateName(
"pool" , pool->getID(),
3054 "reclaimed-leases")),
3055 static_cast<int64_t
>(1));
3060 StatsMgr::instance().addValue(
"reclaimed-leases",
static_cast<int64_t
>(1));
3069 uint64_t deleted_leases = 0;
3075 }
catch (
const std::exception& ex) {
3082 .arg(deleted_leases);
3086AllocEngine::reclaimDeclined(
const Lease4Ptr& lease) {
3091 if (HooksManager::calloutsPresent(
Hooks.hook_index_lease4_recover_)) {
3101 callout_handle->setArgument(
"lease4", lease);
3104 HooksManager::callCallouts(
Hooks.hook_index_lease4_recover_, *callout_handle);
3109 if (callout_handle->getStatus() == CalloutHandle::NEXT_STEP_SKIP) {
3111 .arg(lease->addr_.toText());
3117 .arg(lease->addr_.toText())
3118 .arg(lease->valid_lft_);
3120 StatsMgr& stats_mgr = StatsMgr::instance();
3123 stats_mgr.
addValue(StatsMgr::generateName(
"subnet", lease->subnet_id_,
3124 "declined-addresses"),
3125 static_cast<int64_t
>(-1));
3127 stats_mgr.
addValue(StatsMgr::generateName(
"subnet", lease->subnet_id_,
3128 "reclaimed-declined-addresses"),
3129 static_cast<int64_t
>(1));
3133 const auto& pool = subnet->getPool(
Lease::TYPE_V4, lease->addr_,
false);
3135 stats_mgr.
addValue(StatsMgr::generateName(
"subnet", subnet->getID(),
3136 StatsMgr::generateName(
"pool" , pool->getID(),
3137 "declined-addresses")),
3138 static_cast<int64_t
>(-1));
3140 stats_mgr.
addValue(StatsMgr::generateName(
"subnet", subnet->getID(),
3141 StatsMgr::generateName(
"pool" , pool->getID(),
3142 "reclaimed-declined-addresses")),
3143 static_cast<int64_t
>(1));
3148 stats_mgr.
addValue(
"declined-addresses",
static_cast<int64_t
>(-1));
3150 stats_mgr.
addValue(
"reclaimed-declined-addresses",
static_cast<int64_t
>(1));
3158AllocEngine::reclaimDeclined(
const Lease6Ptr& lease) {
3163 if (HooksManager::calloutsPresent(
Hooks.hook_index_lease6_recover_)) {
3173 callout_handle->setArgument(
"lease6", lease);
3176 HooksManager::callCallouts(
Hooks.hook_index_lease6_recover_, *callout_handle);
3181 if (callout_handle->getStatus() == CalloutHandle::NEXT_STEP_SKIP) {
3183 .arg(lease->addr_.toText());
3189 .arg(lease->addr_.toText())
3190 .arg(lease->valid_lft_);
3192 StatsMgr& stats_mgr = StatsMgr::instance();
3195 stats_mgr.
addValue(StatsMgr::generateName(
"subnet", lease->subnet_id_,
3196 "declined-addresses"),
3197 static_cast<int64_t
>(-1));
3199 stats_mgr.
addValue(StatsMgr::generateName(
"subnet", lease->subnet_id_,
3200 "reclaimed-declined-addresses"),
3201 static_cast<int64_t
>(1));
3205 const auto& pool = subnet->getPool(lease->type_, lease->addr_,
false);
3207 stats_mgr.
addValue(StatsMgr::generateName(
"subnet", subnet->getID(),
3208 StatsMgr::generateName(
"pool" , pool->getID(),
3209 "declined-addresses")),
3210 static_cast<int64_t
>(-1));
3212 stats_mgr.
addValue(StatsMgr::generateName(
"subnet", subnet->getID(),
3213 StatsMgr::generateName(
"pool" , pool->getID(),
3214 "reclaimed-declined-addresses")),
3215 static_cast<int64_t
>(1));
3220 stats_mgr.
addValue(
"declined-addresses",
static_cast<int64_t
>(-1));
3222 stats_mgr.
addValue(
"reclaimed-declined-addresses",
static_cast<int64_t
>(1));
3232 lease->relay_id_.clear();
3233 lease->remote_id_.clear();
3234 if (lease->getContext()) {
3241 if (lease->getContext()) {
3247template<
typename LeasePtrType>
3248void AllocEngine::reclaimLeaseInDatabase(
const LeasePtrType& lease,
3249 const bool remove_lease,
3250 const std::function<
void (
const LeasePtrType&)>&
3251 lease_update_fun)
const {
3259 }
else if (lease_update_fun) {
3262 lease->reuseable_valid_lft_ = 0;
3263 lease->hostname_.clear();
3264 lease->fqdn_fwd_ =
false;
3265 lease->fqdn_rev_ =
false;
3268 lease_update_fun(lease);
3277 .arg(lease->addr_.toText());
3283 return(
"<empty subnet>");
3287 subnet->getSharedNetwork(network);
3288 std::ostringstream ss;
3290 ss <<
"shared-network: " << network->getName();
3292 ss <<
"subnet id: " << subnet->getID();
3331 (!ctx.
subnet_->getReservationsOutOfPool() ||
3342 if (
CfgMgr::instance().getCurrentCfg()->getCfgDbAccess()->getIPReservationsUnique()) {
3346 hosts.push_back(host);
3353 for (
auto host : hosts) {
3357 if (id_pair.first == host->getIdentifierType() &&
3358 id_pair.second == host->getIdentifier()) {
3366 return (!hosts.empty());
3388 if (ctx.
hosts_.empty()) {
3393 auto global_host = ctx.
hosts_.find(SUBNET_ID_GLOBAL);
3394 auto global_host_address = ((global_host != ctx.
hosts_.end() && global_host->second) ?
3395 global_host->second->getIPv4Reservation() :
3404 if (subnet->getReservationsGlobal() &&
3406 (subnet->inRange(global_host_address))) {
3411 if (subnet->getReservationsInSubnet()) {
3412 auto host = ctx.
hosts_.find(subnet->getID());
3417 if (host != ctx.
hosts_.end() && host->second) {
3418 auto reservation = host->second->getIPv4Reservation();
3419 if (!reservation.isV4Zero() &&
3420 (!subnet->getReservationsOutOfPool() ||
3430 subnet = subnet->getNextSubnet(ctx.
subnet_, ctx.
query_->getClasses());
3436 .arg(ctx.
currentHost()->getIPv4Reservation().toText())
3463 auto const& classes = ctx.
query_->getClasses();
3467 bool try_clientid_lookup = (ctx.
clientid_ &&
3471 if (try_clientid_lookup) {
3479 for (
Subnet4Ptr subnet = original_subnet; subnet;
3480 subnet = subnet->getNextSubnet(original_subnet, classes)) {
3485 if (subnet->getMatchClientId()) {
3486 for (
auto l = leases_client_id.begin(); l != leases_client_id.end(); ++l) {
3487 if ((*l)->subnet_id_ == subnet->getID()) {
3489 client_lease = (*l);
3500 if (!client_lease && ctx.
hwaddr_) {
3505 for (
Subnet4Ptr subnet = original_subnet; subnet;
3506 subnet = subnet->getNextSubnet(original_subnet, classes)) {
3508 if (subnet->getMatchClientId()) {
3514 for (Lease4Collection::const_iterator client_lease_it = leases_hw_address.begin();
3515 client_lease_it != leases_hw_address.end(); ++client_lease_it) {
3516 Lease4Ptr existing_lease = *client_lease_it;
3517 if ((existing_lease->subnet_id_ == subnet->getID()) &&
3518 existing_lease->belongsToClient(ctx.
hwaddr_, client_id)) {
3520 client_lease = existing_lease;
3548 auto const& classes = ctx.
query_->getClasses();
3550 while (current_subnet) {
3559 current_subnet = current_subnet->getNextSubnet(ctx.
subnet_, classes);
3571 : early_global_reservations_lookup_(false),
3572 subnet_(), clientid_(), hwaddr_(),
3573 requested_address_(
IOAddress::IPV4_ZERO_ADDRESS()),
3574 fwd_dns_update_(false), rev_dns_update_(false),
3575 hostname_(
""), callout_handle_(), fake_allocation_(false), offer_lft_(0),
3576 old_lease_(), new_lease_(), hosts_(), conflicting_lease_(),
3577 query_(), host_identifiers_(), unknown_requested_addr_(false),
3586 const bool fwd_dns_update,
3587 const bool rev_dns_update,
3588 const std::string& hostname,
3589 const bool fake_allocation,
3590 const uint32_t offer_lft)
3591 : early_global_reservations_lookup_(false),
3592 subnet_(subnet), clientid_(clientid), hwaddr_(hwaddr),
3593 requested_address_(requested_addr),
3594 fwd_dns_update_(fwd_dns_update), rev_dns_update_(rev_dns_update),
3595 hostname_(hostname), callout_handle_(),
3596 fake_allocation_(fake_allocation), offer_lft_(offer_lft), old_lease_(), new_lease_(),
3597 hosts_(), host_identifiers_(), unknown_requested_addr_(false),
3608 if (subnet_ && subnet_->getReservationsInSubnet()) {
3609 auto host = hosts_.find(subnet_->getID());
3610 if (host != hosts_.cend()) {
3611 return (host->second);
3615 return (globalHost());
3620 if (subnet_ && subnet_->getReservationsGlobal()) {
3621 auto host = hosts_.find(SUBNET_ID_GLOBAL);
3622 if (host != hosts_.cend()) {
3623 return (host->second);
3633 if (ddns_params_ && subnet_ && (subnet_->getID() == ddns_params_->getSubnetId())) {
3634 return (ddns_params_);
3640 return (ddns_params_);
3662 auto const& classes = ctx.
query_->getClasses();
3663 if (subnet && !subnet->clientSupported(classes)) {
3664 ctx.
subnet_ = subnet->getNextSubnet(subnet, classes);
3685 .arg(ctx.
query_->getLabel())
3703 !subnet->getReservationsInSubnet()) {
3709 subnet->getReservationsGlobal()) {
3712 ctx.
hosts_[SUBNET_ID_GLOBAL] = ghost;
3715 if (!subnet->getReservationsInSubnet()) {
3721 std::map<SubnetID, ConstHostPtr> host_map;
3723 subnet->getSharedNetwork(network);
3732 const bool use_single_query = network &&
3736 if (use_single_query) {
3740 id_pair.second.size());
3744 for (
auto host = hosts.begin(); host != hosts.end(); ++host) {
3745 if ((*host)->getIPv4SubnetID() != SUBNET_ID_GLOBAL) {
3746 host_map[(*host)->getIPv4SubnetID()] = *host;
3752 auto const& classes = ctx.
query_->getClasses();
3758 if (subnet->clientSupported(classes) && subnet->getReservationsInSubnet()) {
3761 if (use_single_query) {
3762 if (host_map.count(subnet->getID()) > 0) {
3763 ctx.
hosts_[subnet->getID()] = host_map[subnet->getID()];
3771 id_pair.second.size());
3774 ctx.
hosts_[subnet->getID()] = host;
3784 subnet = subnet->getNextSubnet(ctx.
subnet_, classes);
3790 for (
auto host : ctx.
hosts_) {
3791 host.second->encapsulateOptions();
3801 &id_pair.second[0], id_pair.second.size());
3818 findClientLease(ctx, client_lease);
3831 if (hasAddressReservation(ctx)) {
3835 .arg(ctx.
query_->getLabel())
3836 .arg(ctx.
currentHost()->getIPv4Reservation().toText());
3842 if (!client_lease || (client_lease->addr_ != ctx.
currentHost()->getIPv4Reservation())) {
3849 new_lease = allocateOrReuseLease4(ctx.
currentHost()->getIPv4Reservation(), ctx,
3853 .arg(ctx.
query_->getLabel())
3854 .arg(ctx.
currentHost()->getIPv4Reservation().toText())
3857 StatsMgr::instance().addValue(StatsMgr::generateName(
"subnet",
3859 "v4-reservation-conflicts"),
3860 static_cast<int64_t
>(1));
3861 StatsMgr::instance().addValue(
"v4-reservation-conflicts",
3862 static_cast<int64_t
>(1));
3866 new_lease = renewLease4(client_lease, ctx);
3879 if (!new_lease && client_lease && inAllowedPool(ctx, client_lease->addr_) &&
3880 !addressReserved(client_lease->addr_, ctx)) {
3884 .arg(ctx.
query_->getLabel());
3890 (time(NULL) + ctx.
offer_lft_ < client_lease->getExpirationTime())) {
3894 new_lease = renewLease4(client_lease, ctx);
3911 .arg(ctx.
query_->getLabel());
3924 .arg(ctx.
query_->getLabel());
3926 new_lease = allocateUnreservedLease4(ctx);
3946 findClientLease(ctx, client_lease);
3962 .arg(ctx.
query_->getLabel())
3968 }
else if (hasAddressReservation(ctx)) {
3977 .arg(ctx.
query_->getLabel())
3989 if (existing && !existing->expired() &&
3990 !existing->belongsToClient(ctx.
hwaddr_, ctx.
subnet_->getMatchClientId() ?
3995 .arg(ctx.
query_->getLabel())
4005 if (hasAddressReservation(ctx) &&
4013 if (!existing || existing->expired()) {
4017 .arg(ctx.
query_->getLabel())
4018 .arg(ctx.
currentHost()->getIPv4Reservation().toText())
4028 if ((!hasAddressReservation(ctx) ||
4034 .arg(ctx.
query_->getLabel())
4054 ((hasAddressReservation(ctx) &&
4056 inAllowedPool(ctx, client_lease->addr_))) {
4060 .arg(ctx.
query_->getLabel())
4063 return (renewLease4(client_lease, ctx));
4077 .arg(ctx.
query_->getLabel())
4093 .arg(ctx.
query_->getLabel());
4098 new_lease = allocateUnreservedLease4(ctx);
4104 if (new_lease && client_lease) {
4109 .arg(ctx.
query_->getLabel())
4110 .arg(client_lease->addr_.toText());
4114 StatsMgr::instance().addValue(
4115 StatsMgr::generateName(
"subnet", client_lease->subnet_id_,
4116 "assigned-addresses"),
4117 static_cast<int64_t
>(-1));
4121 const auto& pool = subnet->getPool(
Lease::TYPE_V4, client_lease->addr_,
false);
4123 StatsMgr::instance().addValue(
4124 StatsMgr::generateName(
"subnet", subnet->getID(),
4125 StatsMgr::generateName(
"pool", pool->getID(),
4126 "assigned-addresses")),
4127 static_cast<int64_t
>(-1));
4150 if (!classes.
empty()) {
4157 name != classes.
cend(); ++name) {
4159 if (cl && (!cl->getOfferLft().unspecified())) {
4160 offer_lft = cl->getOfferLft();
4168 offer_lft = ctx.
subnet_->getOfferLft();
4177 if (ctx.
query_->inClass(
"BOOTP")) {
4182 uint32_t requested_lft = 0;
4185 OptionUint32Ptr opt_lft = boost::dynamic_pointer_cast<OptionInt<uint32_t> >(opt);
4187 requested_lft = opt_lft->getValue();
4195 if (!classes.
empty()) {
4202 name != classes.
cend(); ++name) {
4204 if (cl && (!cl->getValid().unspecified())) {
4205 candidate_lft = cl->getValid();
4212 if (!candidate_lft) {
4213 candidate_lft = ctx.
subnet_->getValid();
4218 if (requested_lft > 0) {
4219 return (candidate_lft.
get(requested_lft));
4223 return (candidate_lft.
get());
4227AllocEngine::createLease4(
const ClientContext4& ctx,
const IOAddress& addr,
4237 uint32_t valid_lft = (ctx.offer_lft_ ? ctx.offer_lft_ :
getValidLft(ctx));
4239 time_t now = time(NULL);
4242 if (ctx.subnet_->getMatchClientId()) {
4243 client_id = ctx.clientid_;
4247 valid_lft, now, ctx.subnet_->getID()));
4250 lease->fqdn_fwd_ = ctx.fwd_dns_update_;
4251 lease->fqdn_rev_ = ctx.rev_dns_update_;
4252 lease->hostname_ = ctx.hostname_;
4258 if (ctx.callout_handle_ &&
4259 HooksManager::calloutsPresent(hook_index_lease4_select_)) {
4272 ctx.callout_handle_->setArgument(
"query4", ctx.query_);
4278 Subnet4Ptr subnet4 = boost::dynamic_pointer_cast<Subnet4>(ctx.subnet_);
4279 ctx.callout_handle_->setArgument(
"subnet4", subnet4);
4282 ctx.callout_handle_->setArgument(
"fake_allocation", ctx.fake_allocation_);
4285 ctx.callout_handle_->setArgument(
"offer_lft", ctx.offer_lft_);
4288 ctx.callout_handle_->setArgument(
"lease4", lease);
4291 HooksManager::callCallouts(hook_index_lease4_select_, *ctx.callout_handle_);
4293 callout_status = ctx.callout_handle_->getStatus();
4298 if (callout_status == CalloutHandle::NEXT_STEP_SKIP) {
4305 ctx.callout_handle_->getArgument(
"lease4", lease);
4308 if (ctx.fake_allocation_ && ctx.offer_lft_) {
4312 lease->fqdn_fwd_ =
false;
4313 lease->fqdn_rev_ =
false;
4316 if (!ctx.fake_allocation_ || ctx.offer_lft_) {
4317 const auto& pool = ctx.subnet_->getPool(
Lease::TYPE_V4, lease->addr_,
false);
4319 lease->pool_id_ = pool->getID();
4326 StatsMgr::instance().addValue(
4327 StatsMgr::generateName(
"subnet", ctx.subnet_->getID(),
4328 "assigned-addresses"),
4329 static_cast<int64_t
>(1));
4331 StatsMgr::instance().addValue(
4332 StatsMgr::generateName(
"subnet", ctx.subnet_->getID(),
4333 "cumulative-assigned-addresses"),
4334 static_cast<int64_t
>(1));
4337 StatsMgr::instance().addValue(
4338 StatsMgr::generateName(
"subnet", ctx.subnet_->getID(),
4339 StatsMgr::generateName(
"pool", pool->getID(),
4340 "assigned-addresses")),
4341 static_cast<int64_t
>(1));
4343 StatsMgr::instance().addValue(
4344 StatsMgr::generateName(
"subnet", ctx.subnet_->getID(),
4345 StatsMgr::generateName(
"pool", pool->getID(),
4346 "cumulative-assigned-addresses")),
4347 static_cast<int64_t
>(1));
4350 StatsMgr::instance().addValue(
"cumulative-assigned-addresses",
4351 static_cast<int64_t
>(1));
4370AllocEngine::renewLease4(
const Lease4Ptr& lease,
4380 Lease4Ptr old_values = boost::make_shared<Lease4>(*lease);
4385 lease->reuseable_valid_lft_ = 0;
4386 if (!updateLease4Information(lease, ctx)) {
4387 setLeaseReusable(lease, ctx);
4403 if (HooksManager::calloutsPresent(
Hooks.hook_index_lease4_renew_)) {
4427 ctx.
callout_handle_->setArgument(
"clientid", subnet4->getMatchClientId() ?
4435 HooksManager::callCallouts(
Hooks.hook_index_lease4_renew_,
4441 if (ctx.
callout_handle_->getStatus() == CalloutHandle::NEXT_STEP_SKIP) {
4453 lease->pool_id_ = pool->getID();
4461 StatsMgr::instance().addValue(
4462 StatsMgr::generateName(
"subnet", ctx.
subnet_->getID(),
4463 "assigned-addresses"),
4464 static_cast<int64_t
>(1));
4466 StatsMgr::instance().addValue(
4467 StatsMgr::generateName(
"subnet", ctx.
subnet_->getID(),
4468 "cumulative-assigned-addresses"),
4469 static_cast<int64_t
>(1));
4472 StatsMgr::instance().addValue(
4473 StatsMgr::generateName(
"subnet", ctx.
subnet_->getID(),
4474 StatsMgr::generateName(
"pool", pool->getID(),
4475 "assigned-addresses")),
4476 static_cast<int64_t
>(1));
4478 StatsMgr::instance().addValue(
4479 StatsMgr::generateName(
"subnet", ctx.
subnet_->getID(),
4480 StatsMgr::generateName(
"pool", pool->getID(),
4481 "cumulative-assigned-addresses")),
4482 static_cast<int64_t
>(1));
4485 StatsMgr::instance().addValue(
"cumulative-assigned-addresses",
4486 static_cast<int64_t
>(1));
4492 *lease = *old_values;
4499AllocEngine::reuseExpiredLease4(
Lease4Ptr& expired,
4518 expired->reuseable_valid_lft_ = 0;
4519 static_cast<void>(updateLease4Information(expired, ctx));
4523 .arg(ctx.
query_->getLabel())
4524 .arg(expired->toText());
4528 HooksManager::calloutsPresent(hook_index_lease4_select_)) {
4558 HooksManager::callCallouts(hook_index_lease4_select_, *ctx.
callout_handle_);
4565 if (callout_status == CalloutHandle::NEXT_STEP_SKIP) {
4581 expired->pool_id_ = pool->getID();
4587 StatsMgr::instance().addValue(
4588 StatsMgr::generateName(
"subnet", ctx.
subnet_->getID(),
4589 "assigned-addresses"),
4590 static_cast<int64_t
>(1));
4592 StatsMgr::instance().addValue(
4593 StatsMgr::generateName(
"subnet", ctx.
subnet_->getID(),
4594 "cumulative-assigned-addresses"),
4595 static_cast<int64_t
>(1));
4598 StatsMgr::instance().addValue(
4599 StatsMgr::generateName(
"subnet", ctx.
subnet_->getID(),
4600 StatsMgr::generateName(
"pool", pool->getID(),
4601 "assigned-addresses")),
4602 static_cast<int64_t
>(1));
4604 StatsMgr::instance().addValue(
4605 StatsMgr::generateName(
"subnet", ctx.
subnet_->getID(),
4606 StatsMgr::generateName(
"pool", pool->getID(),
4607 "cumulative-assigned-addresses")),
4608 static_cast<int64_t
>(1));
4611 StatsMgr::instance().addValue(
"cumulative-assigned-addresses",
4612 static_cast<int64_t
>(1));
4624AllocEngine::allocateOrReuseLease4(
const IOAddress& candidate, ClientContext4& ctx,
4626 ctx.conflicting_lease_.reset();
4630 if (exist_lease->expired()) {
4635 ctx.old_lease_->hostname_.clear();
4636 ctx.old_lease_->fqdn_fwd_ =
false;
4637 ctx.old_lease_->fqdn_rev_ =
false;
4638 return (reuseExpiredLease4(exist_lease, ctx, callout_status));
4644 ctx.conflicting_lease_ = exist_lease;
4648 return (createLease4(ctx, candidate, callout_status));
4654AllocEngine::allocateUnreservedLease4(ClientContext4& ctx) {
4668 ctx.subnet_->getSharedNetwork(network);
4675 ctx.subnet_ = subnet = network->getPreferredSubnet(ctx.subnet_);
4681 bool check_reservation_first = MultiThreadingMgr::instance().getMode();
4689 uint64_t subnets_with_unavail_leases = 0;
4692 uint64_t subnets_with_unavail_pools = 0;
4694 auto const& classes = ctx.query_->getClasses();
4698 if (subnet->getMatchClientId()) {
4699 client_id = ctx.clientid_;
4711 (attempts_ == 0 || possible_attempts < attempts_) ?
4715 if (max_attempts > 0) {
4718 ++subnets_with_unavail_leases;
4722 ++subnets_with_unavail_pools;
4725 bool exclude_first_last_24 = ((subnet->get().second <= 24) &&
4730 for (
uint128_t i = 0; i < max_attempts; ++i) {
4735 IOAddress candidate = allocator->pickAddress(classes,
4737 ctx.requested_address_);
4744 if (exclude_first_last_24) {
4746 auto const& bytes = candidate.
toBytes();
4747 if ((bytes.size() != 4) ||
4748 (bytes[3] == 0) || (bytes[3] == 255U)) {
4755 if (check_reservation_first && addressReserved(candidate, ctx)) {
4763 if (MultiThreadingMgr::instance().getMode() &&
4764 !resource_handler.
tryLock4(candidate)) {
4773 if (check_reservation_first || !addressReserved(candidate, ctx)) {
4775 new_lease = createLease4(ctx, candidate, callout_status);
4779 if (exist_lease->expired() &&
4780 (check_reservation_first || !addressReserved(candidate, ctx))) {
4782 new_lease = reuseExpiredLease4(exist_lease, ctx, callout_status);
4791 if (ctx.callout_handle_ && (callout_status != CalloutHandle::NEXT_STEP_CONTINUE)) {
4800 subnet = subnet->getNextSubnet(original_subnet, classes);
4803 ctx.subnet_ = subnet;
4812 .arg(ctx.query_->getLabel())
4813 .arg(network->getName())
4814 .arg(subnets_with_unavail_leases)
4815 .arg(subnets_with_unavail_pools);
4816 StatsMgr::instance().addValue(
"v4-allocation-fail-shared-network",
4817 static_cast<int64_t
>(1));
4818 StatsMgr::instance().addValue(
4819 StatsMgr::generateName(
"subnet", ctx.subnet_->getID(),
4820 "v4-allocation-fail-shared-network"),
4821 static_cast<int64_t
>(1));
4825 std::string shared_network = ctx.subnet_->getSharedNetworkName();
4826 if (shared_network.empty()) {
4827 shared_network =
"(none)";
4830 .arg(ctx.query_->getLabel())
4831 .arg(ctx.subnet_->toText())
4832 .arg(ctx.subnet_->getID())
4833 .arg(shared_network);
4834 StatsMgr::instance().addValue(
"v4-allocation-fail-subnet",
4835 static_cast<int64_t
>(1));
4836 StatsMgr::instance().addValue(
4837 StatsMgr::generateName(
"subnet", ctx.subnet_->getID(),
4838 "v4-allocation-fail-subnet"),
4839 static_cast<int64_t
>(1));
4841 if (total_attempts == 0) {
4847 .arg(ctx.query_->getLabel());
4848 StatsMgr::instance().addValue(
"v4-allocation-fail-no-pools",
4849 static_cast<int64_t
>(1));
4850 StatsMgr::instance().addValue(
4851 StatsMgr::generateName(
"subnet", ctx.subnet_->getID(),
4852 "v4-allocation-fail-no-pools"),
4853 static_cast<int64_t
>(1));
4860 .arg(ctx.query_->getLabel())
4861 .arg(total_attempts);
4862 StatsMgr::instance().addValue(
"v4-allocation-fail",
4863 static_cast<int64_t
>(1));
4864 StatsMgr::instance().addValue(
4865 StatsMgr::generateName(
"subnet", ctx.subnet_->getID(),
4866 "v4-allocation-fail"),
4867 static_cast<int64_t
>(1));
4870 if (!classes.empty()) {
4872 .arg(ctx.query_->getLabel())
4873 .arg(classes.toText());
4874 StatsMgr::instance().addValue(
"v4-allocation-fail-classes",
4875 static_cast<int64_t
>(1));
4876 StatsMgr::instance().addValue(
4877 StatsMgr::generateName(
"subnet", ctx.subnet_->getID(),
4878 "v4-allocation-fail-classes"),
4879 static_cast<int64_t
>(1));
4886AllocEngine::updateLease4Information(
const Lease4Ptr& lease,
4888 bool changed =
false;
4889 if (lease->subnet_id_ != ctx.
subnet_->getID()) {
4891 lease->subnet_id_ = ctx.
subnet_->getID();
4893 if ((!ctx.
hwaddr_ && lease->hwaddr_) ||
4895 (!lease->hwaddr_ || (*ctx.
hwaddr_ != *lease->hwaddr_)))) {
4900 if (!lease->client_id_ || (*ctx.
clientid_ != *lease->client_id_)) {
4904 }
else if (lease->client_id_) {
4908 lease->cltt_ = time(NULL);
4914 if (lease->valid_lft_ != lease->current_valid_lft_) {
4938 bool changed =
false;
4941 if (!ctx.
subnet_->getStoreExtendedInfo()) {
4957 extended_info->set(
"sub-options", relay_agent);
4961 std::vector<uint8_t> bytes = remote_id->toBinary();
4962 lease->remote_id_ = bytes;
4963 if (bytes.size() > 0) {
4964 extended_info->set(
"remote-id",
4971 std::vector<uint8_t> bytes = relay_id->toBinary(
false);
4972 lease->relay_id_ = bytes;
4973 if (bytes.size() > 0) {
4974 extended_info->set(
"relay-id",
4982 if (user_context && (user_context->getType() ==
Element::map)) {
4983 mutable_user_context =
copy(user_context, 0);
4998 ConstElementPtr old_extended_info = mutable_isc->get(
"relay-agent-info");
4999 if (!old_extended_info || (*old_extended_info != *extended_info)) {
5001 mutable_isc->set(
"relay-agent-info", extended_info);
5002 mutable_user_context->set(
"ISC", mutable_isc);
5006 lease->setContext(mutable_user_context);
5018 if (!ctx.
subnet_->getStoreExtendedInfo()) {
5023 if (ctx.
query_->relay_info_.empty()) {
5038 for (
auto relay : ctx.
query_->relay_info_) {
5047 if (!relay.options_.empty()) {
5052 const uint8_t* cp =
static_cast<const uint8_t*
>(buf.
getData());
5053 std::vector<uint8_t> bytes;
5054 std::stringstream ss;
5062 if (remote_id_it != relay.options_.end()) {
5063 OptionPtr remote_id = remote_id_it->second;
5065 std::vector<uint8_t> bytes = remote_id->toBinary();
5066 if (bytes.size() > 0) {
5067 relay_elem->set(
"remote-id",
5074 if (relay_id_it != relay.options_.end()) {
5075 OptionPtr relay_id = relay_id_it->second;
5077 std::vector<uint8_t> bytes = relay_id->toBinary(
false);
5078 if (bytes.size() > 0) {
5079 relay_elem->set(
"relay-id",
5086 extended_info->add(relay_elem);
5092 if (user_context && (user_context->getType() ==
Element::map)) {
5093 mutable_user_context =
copy(user_context, 0);
5109 if (!old_extended_info || (*old_extended_info != *extended_info)) {
5111 mutable_isc->set(
"relay-info", extended_info);
5112 mutable_user_context->set(
"ISC", mutable_isc);
5116 lease->setContext(mutable_user_context);
5120AllocEngine::setLeaseReusable(
const Lease4Ptr& lease,
5121 const ClientContext4& ctx)
const {
5123 lease->reuseable_valid_lft_ = 0;
5139 if (lease->cltt_ < lease->current_cltt_) {
5143 uint32_t age = lease->cltt_ - lease->current_cltt_;
5145 if (age >= lease->current_valid_lft_) {
5150 uint32_t max_age = 0;
5151 if (!subnet->getCacheMaxAge().unspecified()) {
5152 max_age = subnet->getCacheMaxAge().get();
5153 if ((max_age == 0) || (age > max_age)) {
5159 if (!subnet->getCacheThreshold().unspecified()) {
5160 double threshold = subnet->getCacheThreshold().get();
5161 if ((threshold <= 0.) || (threshold > 1.)) {
5164 max_age = lease->valid_lft_ * threshold;
5165 if (age > max_age) {
5176 lease->reuseable_valid_lft_ = lease->current_valid_lft_ - age;
5180AllocEngine::setLeaseReusable(
const Lease6Ptr& lease,
5181 uint32_t current_preferred_lft,
5182 const ClientContext6& ctx)
const {
5184 lease->reuseable_valid_lft_ = 0;
5185 lease->reuseable_preferred_lft_ = 0;
5195 if (lease->cltt_ < lease->current_cltt_) {
5199 uint32_t age = lease->cltt_ - lease->current_cltt_;
5201 if (age >= lease->current_valid_lft_) {
5206 uint32_t max_age = 0;
5207 if (!subnet->getCacheMaxAge().unspecified()) {
5208 max_age = subnet->getCacheMaxAge().get();
5209 if ((max_age == 0) || (age > max_age)) {
5215 if (!subnet->getCacheThreshold().unspecified()) {
5216 double threshold = subnet->getCacheThreshold().get();
5217 if ((threshold <= 0.) || (threshold > 1.)) {
5220 max_age = lease->valid_lft_ * threshold;
5221 if (age > max_age) {
5233 (current_preferred_lft == 0)) {
5235 lease->reuseable_preferred_lft_ = current_preferred_lft;
5236 }
else if (current_preferred_lft > age) {
5237 lease->reuseable_preferred_lft_ = current_preferred_lft - age;
5245 lease->reuseable_valid_lft_ = lease->current_valid_lft_ - age;
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.
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.
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 uint32_t getOfferLft(const ClientContext4 &ctx)
Returns the offer lifetime based on the v4 context.
static std::string labelNetworkOrSubnet(SubnetPtr subnet)
Generates a label for subnet or shared-network from subnet.
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)
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.
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.
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.
ClientClassContainer::const_iterator const_iterator
Type of iterators.
bool empty() const
Check if classes is empty.
const_iterator cbegin() const
Iterators to the first element.
const_iterator cend() const
Iterators to the past the end element.
Convenience container for conveying DDNS behavioral parameters It is intended to be created per Packe...
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.
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.
Resource race avoidance RAII handler for DHCPv4.
bool tryLock4(const asiolink::IOAddress &addr)
Tries to acquires a resource.
Resource race avoidance RAII handler.
bool tryLock(Lease::Type type, const asiolink::IOAddress &addr)
Tries to acquires a resource.
RAII object enabling copying options retrieved from the packet.
static bool subnetsIncludeMatchClientId(const Subnet4Ptr &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.
Wrapper class around callout handle which automatically resets handle's state.
Statistics Manager class.
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.
size_t getLength() const
Return the length of data written in the buffer.
const void * getData() const
Return a pointer to the head of the data stored 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.
T get(T hint) const
Returns value with a hint.
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
boost::shared_ptr< Subnet > SubnetPtr
A generic pointer to either Subnet4 or Subnet6 object.
const isc::log::MessageID ALLOC_ENGINE_V6_REVOKED_SHARED_PREFIX_LEASE
boost::shared_ptr< Subnet4 > Subnet4Ptr
A pointer to a Subnet4 object.
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.