35#include <boost/foreach.hpp>
36#include <boost/make_shared.hpp>
53namespace ph = std::placeholders;
58struct AllocEngineHooks {
59 int hook_index_lease4_select_;
60 int hook_index_lease4_renew_;
61 int hook_index_lease4_expire_;
62 int hook_index_lease4_recover_;
63 int hook_index_lease6_select_;
64 int hook_index_lease6_renew_;
65 int hook_index_lease6_rebind_;
66 int hook_index_lease6_expire_;
67 int hook_index_lease6_recover_;
87AllocEngineHooks
Hooks;
95 : attempts_(attempts), incomplete_v4_reclamations_(0),
96 incomplete_v6_reclamations_(0) {
99 hook_index_lease4_select_ =
Hooks.hook_index_lease4_select_;
100 hook_index_lease6_select_ =
Hooks.hook_index_lease6_select_;
127 if (
CfgMgr::instance().getCurrentCfg()->getCfgDbAccess()->getIPReservationsUnique()) {
132 reserved.push_back(host);
143 reserved.insert(reserved.end(), hosts.begin(), hosts.end());
162 const IOAddress& address,
bool check_subnet) {
166 auto const& classes = ctx.
query_->getClasses();
168 while (current_subnet) {
169 if (current_subnet->clientSupported(classes)) {
171 if (current_subnet->inPool(lease_type, address)) {
175 if (current_subnet->inPool(lease_type, address, classes)) {
181 current_subnet = current_subnet->getNextSubnet(ctx.
subnet_);
197 : query_(), fake_allocation_(false),
198 early_global_reservations_lookup_(false), subnet_(), host_subnet_(),
199 duid_(), hwaddr_(), host_identifiers_(), hosts_(),
200 fwd_dns_update_(false), rev_dns_update_(false), hostname_(),
201 callout_handle_(), ias_(), ddns_params_() {
208 const std::string& hostname,
209 const bool fake_allocation,
212 : query_(query), fake_allocation_(fake_allocation),
213 early_global_reservations_lookup_(false), subnet_(subnet),
214 duid_(duid), hwaddr_(), host_identifiers_(), hosts_(),
215 fwd_dns_update_(fwd_dns), rev_dns_update_(rev_dns), hostname_(hostname),
216 callout_handle_(callout_handle), allocated_resources_(), new_leases_(),
217 ias_(), ddns_params_() {
226 : iaid_(0), type_(
Lease::TYPE_NA), hints_(), old_leases_(),
227 changed_leases_(), new_resources_(), ia_rsp_() {
233 const uint8_t prefix_len,
234 const uint32_t preferred,
235 const uint32_t valid) {
236 hints_.push_back(
Resource(prefix, prefix_len, preferred, valid));
245 addHint(iaaddr->getAddress(), 128,
246 iaaddr->getPreferred(), iaaddr->getValid());
255 addHint(iaprefix->getAddress(), iaprefix->getLength(),
256 iaprefix->getPreferred(), iaprefix->getValid());
262 const uint8_t prefix_len) {
263 static_cast<void>(new_resources_.insert(
Resource(prefix, prefix_len)));
269 const uint8_t prefix_len)
const {
270 return (
static_cast<bool>(new_resources_.count(
Resource(prefix,
277 const uint8_t prefix_len) {
285 return (
static_cast<bool>
292 if (subnet && subnet->getReservationsInSubnet()) {
293 auto host =
hosts_.find(subnet->getID());
294 if (host !=
hosts_.cend()) {
295 return (host->second);
305 if (subnet &&
subnet_->getReservationsGlobal()) {
306 auto host =
hosts_.find(SUBNET_ID_GLOBAL);
307 if (host !=
hosts_.cend()) {
308 return (host->second);
318 return (ghost && ghost->hasReservation(resv));
324 if (ddns_params_ &&
subnet_ && (
subnet_->getID() == ddns_params_->getSubnetId())) {
325 return (ddns_params_);
331 return (ddns_params_);
350 !subnet->getReservationsInSubnet()) {
356 subnet->getReservationsGlobal()) {
359 ctx.
hosts_[SUBNET_ID_GLOBAL] = ghost;
362 if (!subnet->getReservationsInSubnet()) {
368 std::map<SubnetID, ConstHostPtr> host_map;
370 subnet->getSharedNetwork(network);
379 const bool use_single_query = network &&
383 if (use_single_query) {
387 id_pair.second.size());
391 for (
auto const& host : hosts) {
392 if (host->getIPv6SubnetID() != SUBNET_ID_GLOBAL) {
393 host_map[host->getIPv6SubnetID()] = host;
399 auto const& classes = ctx.
query_->getClasses();
406 if (subnet->clientSupported(classes) && subnet->getReservationsInSubnet()) {
409 if (use_single_query) {
410 if (host_map.count(subnet->getID()) > 0) {
411 ctx.
hosts_[subnet->getID()] = host_map[subnet->getID()];
419 id_pair.second.size());
422 ctx.
hosts_[subnet->getID()] = host;
432 subnet = subnet->getNextSubnet(ctx.
subnet_, classes);
438 for (
auto const& host : ctx.
hosts_) {
439 host.second->encapsulateOptions();
449 &id_pair.second[0], id_pair.second.size());
483 for (
auto const& l : all_leases) {
484 if ((l)->subnet_id_ == subnet->getID()) {
489 subnet = subnet->getNextSubnet(ctx.
subnet_);
509 if (leases.empty() && !ctx.
hosts_.empty()) {
513 .arg(ctx.
query_->getLabel());
518 allocateReservedLeases6(ctx, leases);
520 leases = updateLeaseData(ctx, leases);
535 }
else if (!leases.empty() && ctx.
hosts_.empty()) {
539 .arg(ctx.
query_->getLabel());
543 removeNonmatchingReservedLeases6(ctx, leases);
545 leases = updateLeaseData(ctx, leases);
554 }
else if (!leases.empty() && !ctx.
hosts_.empty()) {
558 .arg(ctx.
query_->getLabel());
562 allocateReservedLeases6(ctx, leases);
574 removeNonmatchingReservedLeases6(ctx, leases);
583 removeNonreservedLeases6(ctx, leases);
588 leases = updateLeaseData(ctx, leases);
601 if (leases.empty()) {
615 .arg(ctx.
query_->getLabel());
617 leases = allocateUnreservedLeases6(ctx);
620 if (!leases.empty()) {
624 for (
auto const& lease : leases) {
635 .arg(ctx.
query_->getLabel())
648 uint8_t hint_prefix_length = 128;
649 if (!ctx.currentIA().hints_.empty()) {
651 hint = ctx.currentIA().hints_[0].getAddress();
652 hint_prefix_length = ctx.currentIA().hints_[0].getPrefixLength();
661 uint64_t total_attempts = 0;
665 uint64_t subnets_with_unavail_leases = 0;
668 uint64_t subnets_with_unavail_pools = 0;
678 bool search_hint_lease =
true;
685 if (hint_prefix_length == 128) {
686 hint_prefix_length = 0;
688 if (!hint_prefix_length) {
696 Lease6Ptr lease = allocateBestMatch(ctx, hint_lease, search_hint_lease,
697 hint, hint_prefix_length, subnet,
698 network, total_attempts,
699 subnets_with_unavail_leases,
700 subnets_with_unavail_pools,
701 callout_status, prefix_length_match);
709 lease = allocateBestMatch(ctx, hint_lease, search_hint_lease, hint,
710 hint_prefix_length, subnet, network,
711 total_attempts, subnets_with_unavail_leases,
712 subnets_with_unavail_pools, callout_status,
713 prefix_length_match);
722 lease = allocateBestMatch(ctx, hint_lease, search_hint_lease, hint,
723 hint_prefix_length, subnet, network,
724 total_attempts, subnets_with_unavail_leases,
725 subnets_with_unavail_pools, callout_status,
726 prefix_length_match);
730 leases.push_back(lease);
734 auto const& classes = ctx.query_->getClasses();
740 .arg(ctx.query_->getLabel())
741 .arg(network->getName())
742 .arg(subnets_with_unavail_leases)
743 .arg(subnets_with_unavail_pools);
745 static_cast<int64_t
>(1));
748 "v6-allocation-fail-shared-network"),
749 static_cast<int64_t
>(1));
753 std::string shared_network = ctx.subnet_->getSharedNetworkName();
754 if (shared_network.empty()) {
755 shared_network =
"(none)";
758 .arg(ctx.query_->getLabel())
759 .arg(ctx.subnet_->toText())
760 .arg(ctx.subnet_->getID())
761 .arg(shared_network);
763 static_cast<int64_t
>(1));
766 "v6-allocation-fail-subnet"),
767 static_cast<int64_t
>(1));
769 if (total_attempts == 0) {
775 .arg(ctx.query_->getLabel());
777 static_cast<int64_t
>(1));
780 "v6-allocation-fail-no-pools"),
781 static_cast<int64_t
>(1));
788 .arg(ctx.query_->getLabel())
789 .arg(total_attempts);
791 static_cast<int64_t
>(1));
794 "v6-allocation-fail"),
795 static_cast<int64_t
>(1));
798 if (!classes.empty()) {
800 .arg(ctx.query_->getLabel())
801 .arg(classes.toText());
803 static_cast<int64_t
>(1));
806 "v6-allocation-fail-classes"),
807 static_cast<int64_t
>(1));
817 bool& search_hint_lease,
819 uint8_t hint_prefix_length,
822 uint64_t& total_attempts,
823 uint64_t& subnets_with_unavail_leases,
824 uint64_t& subnets_with_unavail_pools,
827 auto const& classes = ctx.query_->getClasses();
832 if (!search_hint_lease) {
833 usable_hint_lease = hint_lease;
835 for (; subnet; subnet = subnet->getNextSubnet(original_subnet)) {
836 if (!subnet->clientSupported(classes)) {
840 ctx.subnet_ = subnet;
844 pool = boost::dynamic_pointer_cast<Pool6>
845 (subnet->getPool(ctx.currentIA().type_, classes, hint));
848 if (!pool || !pool->clientSupported(classes)) {
854 hint_prefix_length)) {
858 bool in_subnet = subnet->getReservationsInSubnet();
861 if (search_hint_lease) {
862 search_hint_lease =
false;
864 usable_hint_lease = hint_lease;
866 if (!usable_hint_lease) {
878 (!subnet->getReservationsOutOfPool() ||
879 !subnet->inPool(ctx.currentIA().type_, hint))) {
880 hosts = getIPv6Resrv(subnet->getID(), hint);
890 Lease6Ptr new_lease = createLease6(ctx, hint, pool->getLength(), callout_status);
903 .arg(ctx.query_->getLabel())
907 }
else if (usable_hint_lease->expired()) {
916 (!subnet->getReservationsOutOfPool() ||
917 !subnet->inPool(ctx.currentIA().type_, hint))) {
918 hosts = getIPv6Resrv(subnet->getID(), hint);
927 ctx.currentIA().old_leases_.push_back(old_lease);
930 Lease6Ptr lease = reuseExpiredLease(usable_hint_lease, ctx,
940 .arg(ctx.query_->getLabel())
952 if (!check_reservation_first) {
953 check_reservation_first =
CfgMgr::instance().getCurrentCfg()->getReservationsLookupFirst();
966 original_subnet->getSharedNetwork(network);
973 original_subnet = network->getPreferredSubnet(original_subnet, ctx.currentIA().type_);
976 ctx.subnet_ = subnet = original_subnet;
978 for (; subnet; subnet = subnet->getNextSubnet(original_subnet)) {
979 if (!subnet->clientSupported(classes)) {
990 subnet->getPoolCapacity(ctx.currentIA().type_,
1001 (attempts_ == 0 || possible_attempts < attempts_) ?
1005 if (max_attempts > 0) {
1008 ++subnets_with_unavail_leases;
1012 ++subnets_with_unavail_pools;
1016 bool in_subnet = subnet->getReservationsInSubnet();
1017 bool out_of_pool = subnet->getReservationsOutOfPool();
1022 if (ctx.callout_handle_) {
1026 for (uint64_t i = 0; i < max_attempts; ++i) {
1029 auto allocator = subnet->getAllocator(ctx.currentIA().type_);
1034 uint8_t prefix_len = 128;
1036 candidate = allocator->pickPrefix(classes, pool, ctx.duid_,
1037 prefix_length_match, hint,
1038 hint_prefix_length);
1040 prefix_len = pool->getLength();
1043 candidate = allocator->pickAddress(classes, ctx.duid_, hint);
1047 if (candidate.isV6Zero()) {
1052 if (check_reservation_first && in_subnet && !out_of_pool) {
1053 auto hosts = getIPv6Resrv(subnet->getID(), candidate);
1054 if (!hosts.empty()) {
1064 !resource_handler.tryLock(ctx.currentIA().type_, candidate)) {
1077 if (!check_reservation_first && in_subnet && !out_of_pool) {
1078 auto hosts = getIPv6Resrv(subnet->getID(), candidate);
1079 if (!hosts.empty()) {
1088 ctx.subnet_ = subnet;
1089 Lease6Ptr new_lease = createLease6(ctx, candidate, prefix_len, callout_status);
1093 ctx.currentIA().old_leases_.clear();
1097 }
else if (ctx.callout_handle_ &&
1106 }
else if (existing->expired()) {
1108 if (!check_reservation_first && in_subnet && !out_of_pool) {
1109 auto hosts = getIPv6Resrv(subnet->getID(), candidate);
1110 if (!hosts.empty()) {
1119 ctx.currentIA().old_leases_.push_back(old_lease);
1121 ctx.subnet_ = subnet;
1122 existing = reuseExpiredLease(existing, ctx, prefix_len,
1137 if (ctx.hosts_.empty()) {
1140 .arg(ctx.query_->getLabel());
1151 for (
auto const& lease : existing_leases) {
1152 if ((lease->valid_lft_ != 0)) {
1153 if ((ctx.hosts_.count(lease->subnet_id_) > 0) &&
1154 ctx.hosts_[lease->subnet_id_]->hasReservation(
makeIPv6Resrv(*lease))) {
1159 .arg(ctx.query_->getLabel())
1160 .arg(lease->typeToText(lease->type_))
1161 .arg(lease->addr_.toText());
1167 if (!ctx.host_subnet_) {
1169 ctx.subnet_->getSharedNetwork(network);
1174 ctx.host_subnet_ = network->getSubnet(lease->subnet_id_);
1182 if (host && !host->getHostname().empty()) {
1189 qualifyName(host->getHostname(), *ctx.getDdnsParams(),
1190 static_cast<bool>(fqdn));
1204 auto const& classes = ctx.query_->getClasses();
1205 for (
Subnet6Ptr subnet = ctx.subnet_; subnet;
1206 subnet = subnet->getNextSubnet(ctx.subnet_)) {
1208 SubnetID subnet_id = subnet->getID();
1211 if (!subnet->clientSupported(classes) || ctx.hosts_.count(subnet_id) == 0) {
1217 bool in_subnet = subnet->getReservationsInSubnet();
1221 BOOST_FOREACH(
auto const& type_lease_tuple, reservs) {
1223 const IOAddress& addr = type_lease_tuple.second.getPrefix();
1224 uint8_t prefix_len = type_lease_tuple.second.getPrefixLen();
1228 if (ctx.isAllocated(addr, prefix_len)) {
1237 (subnet->getReservationsOutOfPool() &&
1238 subnet->inPool(ctx.currentIA().type_, addr))) {
1250 ctx.subnet_ = subnet;
1252 if (!ctx.host_subnet_) {
1253 ctx.host_subnet_ = subnet;
1254 if (!host->getHostname().empty()) {
1268 qualifyName(host->getHostname(), *ctx.getDdnsParams(),
1269 static_cast<bool>(fqdn));
1275 Lease6Ptr lease = createLease6(ctx, addr, prefix_len, callout_status);
1278 existing_leases.push_back(lease);
1283 .arg(ctx.query_->getLabel());
1287 .arg(
static_cast<int>(prefix_len))
1288 .arg(ctx.query_->getLabel());
1306 allocateGlobalReservedLeases6(ctx, existing_leases);
1321 for (
auto const& lease : existing_leases) {
1322 if ((lease->valid_lft_ != 0) &&
1328 .arg(ctx.query_->getLabel())
1329 .arg(lease->typeToText(lease->type_))
1330 .arg(lease->addr_.toText());
1336 if (!ghost->getHostname().empty()) {
1343 qualifyName(ghost->getHostname(), *ctx.getDdnsParams(),
1344 static_cast<bool>(fqdn));
1359 const IPv6ResrvRange& reservs = ghost->getIPv6Reservations(type);
1360 BOOST_FOREACH(
auto const& type_lease_tuple, reservs) {
1362 const IOAddress& addr = type_lease_tuple.second.getPrefix();
1363 uint8_t prefix_len = type_lease_tuple.second.getPrefixLen();
1367 if (ctx.isAllocated(addr, prefix_len)) {
1379 bool valid_subnet =
false;
1380 auto subnet = ctx.subnet_;
1382 if (subnet->inRange(addr)) {
1383 valid_subnet =
true;
1387 subnet = subnet->getNextSubnet(ctx.subnet_);
1390 if (!valid_subnet) {
1393 .arg(ctx.query_->getLabel())
1399 ctx.subnet_ = subnet;
1402 if (!ghost->getHostname().empty()) {
1416 qualifyName(ghost->getHostname(), *ctx.getDdnsParams(),
1417 static_cast<bool>(fqdn));
1422 Lease6Ptr lease = createLease6(ctx, addr, prefix_len, callout_status);
1425 existing_leases.push_back(lease);
1430 .arg(ctx.query_->getLabel());
1434 .arg(
static_cast<int>(prefix_len))
1435 .arg(ctx.query_->getLabel());
1453AllocEngine::removeNonmatchingReservedLeases6(
ClientContext6& ctx,
1456 if (existing_leases.empty() || !ctx.subnet_) {
1461 if (!ctx.subnet_->getReservationsInSubnet() &&
1462 !ctx.subnet_->getReservationsGlobal()) {
1463 removeNonmatchingReservedNoHostLeases6(ctx, existing_leases);
1472 for (
auto const& candidate :
copy) {
1476 if ((ctx.hasGlobalReservation(resv)) ||
1477 ((ctx.hosts_.count(candidate->subnet_id_) > 0) &&
1478 (ctx.hosts_[candidate->subnet_id_]->hasReservation(resv)))) {
1487 auto hosts = getIPv6Resrv(ctx.subnet_->getID(), candidate->addr_);
1492 if (hosts.empty() && inAllowedPool(ctx, candidate->type_,
1493 candidate->addr_,
false)) {
1497 if (!hosts.empty()) {
1500 if (hosts.size() == 1) {
1503 .arg(ctx.query_->getLabel())
1504 .arg(candidate->addr_.toText())
1505 .arg(ctx.duid_->toText())
1506 .arg(hosts.front()->getIdentifierAsText());
1509 .arg(ctx.query_->getLabel())
1510 .arg(candidate->addr_.toText())
1511 .arg(
static_cast<int>(candidate->prefixlen_))
1512 .arg(ctx.duid_->toText())
1513 .arg(hosts.front()->getIdentifierAsText());
1518 .arg(ctx.query_->getLabel())
1519 .arg(candidate->addr_.toText())
1520 .arg(ctx.duid_->toText())
1524 .arg(ctx.query_->getLabel())
1525 .arg(candidate->addr_.toText())
1526 .arg(
static_cast<int>(candidate->prefixlen_))
1527 .arg(ctx.duid_->toText())
1548 "assigned-nas" :
"assigned-pds"),
1549 static_cast<int64_t>(-1));
1551 auto const& subnet =
CfgMgr::instance().getCurrentCfg()->getCfgSubnets4()->getBySubnetId(candidate->subnet_id_);
1553 auto const& pool = subnet->getPool(ctx.currentIA().type_, candidate->addr_,
false);
1558 ctx.
currentIA().type_ ==
Lease::TYPE_NA ?
"assigned-nas" :
"assigned-pds")),
1559 static_cast<int64_t>(-1));
1569 ctx.currentIA().old_leases_.push_back(candidate);
1572 removeLeases(existing_leases, candidate->addr_);
1577AllocEngine::removeNonmatchingReservedNoHostLeases6(
ClientContext6& ctx,
1584 for (
auto const& candidate :
copy) {
1588 if (inAllowedPool(ctx, candidate->type_,
1589 candidate->addr_,
false)) {
1607 "assigned-nas" :
"assigned-pds"),
1608 static_cast<int64_t>(-1));
1610 auto const& subnet =
CfgMgr::instance().getCurrentCfg()->getCfgSubnets6()->getBySubnetId(candidate->subnet_id_);
1612 auto const& pool = subnet->getPool(candidate->type_, candidate->addr_,
false);
1617 candidate->type_ ==
Lease::TYPE_NA ?
"assigned-nas" :
"assigned-pds")),
1618 static_cast<int64_t>(-1));
1623 ctx.currentIA().old_leases_.push_back(candidate);
1626 removeLeases(existing_leases, candidate->addr_);
1633 bool removed =
false;
1634 for (Lease6Collection::iterator lease = container.begin();
1635 lease != container.end(); ++lease) {
1636 if ((*lease)->addr_ == addr) {
1643 container.erase(std::remove(container.begin(), container.end(),
Lease6Ptr()),
1654 int total = existing_leases.size();
1661 for (Lease6Collection::iterator lease = existing_leases.begin();
1662 lease != existing_leases.end(); ++lease) {
1666 if (ctx.hasGlobalReservation(resv) ||
1667 ((ctx.hosts_.count((*lease)->subnet_id_) > 0) &&
1668 (ctx.hosts_[(*lease)->subnet_id_]->hasReservation(resv)))) {
1690 "assigned-nas" :
"assigned-pds"),
1691 static_cast<int64_t>(-1));
1693 auto const& subnet =
CfgMgr::instance().getCurrentCfg()->getCfgSubnets6()->getBySubnetId((*lease)->subnet_id_);
1695 auto const& pool = subnet->getPool(ctx.currentIA().type_, (*lease)->addr_,
false);
1700 ctx.
currentIA().type_ ==
Lease::TYPE_NA ?
"assigned-nas" :
"assigned-pds")),
1701 static_cast<int64_t>(-1));
1708 ctx.currentIA().old_leases_.push_back(*lease);
1723 existing_leases.erase(std::remove(existing_leases.begin(),
1724 existing_leases.end(),
Lease6Ptr()), existing_leases.end());
1732 if (!expired->expired()) {
1740 if (!ctx.fake_allocation_) {
1744 reclaimExpiredLease(expired, ctx.callout_handle_);
1748 expired->iaid_ = ctx.currentIA().iaid_;
1749 expired->duid_ = ctx.duid_;
1752 getLifetimes6(ctx, expired->preferred_lft_, expired->valid_lft_);
1753 expired->reuseable_valid_lft_ = 0;
1755 expired->cltt_ = time(NULL);
1756 expired->subnet_id_ = ctx.subnet_->getID();
1757 expired->hostname_ = ctx.hostname_;
1758 expired->fqdn_fwd_ = ctx.fwd_dns_update_;
1759 expired->fqdn_rev_ = ctx.rev_dns_update_;
1760 expired->prefixlen_ = prefix_len;
1765 .arg(ctx.query_->getLabel())
1766 .arg(expired->toText());
1769 if (ctx.callout_handle_ &&
1779 ScopedEnableOptionsCopy<Pkt6> query6_options_copy(ctx.query_);
1784 ctx.callout_handle_->setArgument(
"query6", ctx.query_);
1787 ctx.callout_handle_->setArgument(
"subnet6", ctx.subnet_);
1790 ctx.callout_handle_->setArgument(
"fake_allocation", ctx.fake_allocation_);
1793 ctx.callout_handle_->setArgument(
"lease6", expired);
1798 callout_status = ctx.callout_handle_->getStatus();
1815 ctx.callout_handle_->getArgument(
"lease6", expired);
1818 if (!ctx.fake_allocation_) {
1822 auto const& pool = ctx.subnet_->getPool(ctx.currentIA().type_, expired->addr_,
false);
1824 expired->pool_id_ = pool->getID();
1832 if (ctx.subnet_->inPool(ctx.currentIA().type_, expired->addr_)) {
1836 "assigned-nas" :
"assigned-pds"),
1837 static_cast<int64_t>(1));
1842 "cumulative-assigned-nas" :
"cumulative-assigned-pds"),
1843 static_cast<int64_t>(1));
1849 "pool" :
"pd-pool", pool->getID(),
1851 "assigned-nas" :
"assigned-pds")),
1852 static_cast<int64_t>(1));
1857 "pool" :
"pd-pool", pool->getID(),
1859 "cumulative-assigned-nas" :
"cumulative-assigned-pds")),
1860 static_cast<int64_t>(1));
1864 "cumulative-assigned-nas" :
"cumulative-assigned-pds",
1865 static_cast<int64_t>(1));
1881 Triplet<uint32_t> candidate_preferred;
1882 Triplet<uint32_t> candidate_valid;
1884 if (!classes.empty()) {
1891 for (
auto const& name : classes) {
1893 if (candidate_preferred.unspecified() &&
1894 (cl && (!cl->getPreferred().unspecified()))) {
1895 candidate_preferred = cl->getPreferred();
1899 if (candidate_valid.unspecified() &&
1900 (cl && (!cl->getValid().unspecified()))) {
1901 candidate_valid = cl->getValid();
1904 if (have_both == 2) {
1911 if (!candidate_preferred) {
1912 candidate_preferred = ctx.
subnet_->getPreferred();
1916 if (!candidate_valid) {
1917 candidate_valid = ctx.
subnet_->getValid();
1921 preferred = candidate_preferred;
1922 valid = candidate_valid;
1928 preferred = candidate_preferred.get(ctx.
currentIA().
hints_[0].getPreferred());
1937 if (!preferred || preferred > valid) {
1938 preferred = ((valid * 5)/8);
1941 .arg(ctx.
query_->getLabel())
1955 uint32_t preferred = 0;
1960 ctx.currentIA().iaid_, preferred,
1961 valid, ctx.subnet_->getID(),
1962 ctx.hwaddr_, prefix_len));
1964 lease->fqdn_fwd_ = ctx.fwd_dns_update_;
1965 lease->fqdn_rev_ = ctx.rev_dns_update_;
1966 lease->hostname_ = ctx.hostname_;
1969 if (ctx.callout_handle_ &&
1979 ScopedEnableOptionsCopy<Pkt6> query6_options_copy(ctx.query_);
1984 ctx.callout_handle_->setArgument(
"query6", ctx.query_);
1987 ctx.callout_handle_->setArgument(
"subnet6", ctx.subnet_);
1990 ctx.callout_handle_->setArgument(
"fake_allocation", ctx.fake_allocation_);
1993 ctx.callout_handle_->setArgument(
"lease6", lease);
1998 callout_status = ctx.callout_handle_->getStatus();
2010 ctx.callout_handle_->getArgument(
"lease6", lease);
2013 if (!ctx.fake_allocation_) {
2017 auto const& pool = ctx.subnet_->getPool(ctx.currentIA().type_, lease->addr_,
false);
2019 lease->pool_id_ = pool->getID();
2028 if (ctx.subnet_->inPool(ctx.currentIA().type_, addr)) {
2032 "assigned-nas" :
"assigned-pds"),
2033 static_cast<int64_t>(1));
2038 "cumulative-assigned-nas" :
"cumulative-assigned-pds"),
2039 static_cast<int64_t>(1));
2045 "pool" :
"pd-pool", pool->getID(),
2047 "assigned-nas" :
"assigned-pds")),
2048 static_cast<int64_t>(1));
2053 "pool" :
"pd-pool", pool->getID(),
2055 "cumulative-assigned-nas" :
"cumulative-assigned-pds")),
2056 static_cast<int64_t>(1));
2060 "cumulative-assigned-nas" :
"cumulative-assigned-pds",
2061 static_cast<int64_t>(1));
2065 ctx.currentIA().addNewResource(addr, prefix_len);
2104 leases.insert(leases.end(), leases_subnet.begin(), leases_subnet.end());
2106 subnet = subnet->getNextSubnet(ctx.
subnet_);
2109 if (!leases.empty()) {
2112 .arg(ctx.
query_->getLabel());
2116 removeNonmatchingReservedLeases6(ctx, leases);
2119 if (!ctx.
hosts_.empty()) {
2123 .arg(ctx.
query_->getLabel());
2126 allocateReservedLeases6(ctx, leases);
2132 removeNonreservedLeases6(ctx, leases);
2139 if (leases.empty()) {
2143 .arg(ctx.
query_->getLabel());
2145 leases = allocateUnreservedLeases6(ctx);
2149 for (
auto const& l : leases) {
2157 .arg(ctx.
query_->getLabel())
2158 .arg(l->typeToText(l->type_))
2160 extendLease6(ctx, l);
2163 if (!leases.empty()) {
2167 for (
auto const& lease : leases) {
2179 .arg(ctx.
query_->getLabel())
2189 if (!lease || !ctx.subnet_) {
2195 if (ctx.subnet_->getID() != lease->subnet_id_) {
2197 ctx.subnet_->getSharedNetwork(network);
2203 ctx.subnet_ = subnet;
2211 (((lease->type_ !=
Lease::TYPE_PD) && !ctx.subnet_->inRange(lease->addr_)) ||
2212 !ctx.subnet_->clientSupported(ctx.query_->getClasses()))) {
2229 "assigned-nas" :
"assigned-pds"),
2230 static_cast<int64_t>(-1));
2232 auto const& pool = ctx.subnet_->getPool(ctx.currentIA().type_, lease->addr_,
false);
2237 "pool" :
"pd-pool", pool->getID(),
2239 "assigned-nas" :
"assigned-pds")),
2240 static_cast<int64_t>(-1));
2244 ctx.currentIA().old_leases_.push_back(lease);
2251 .arg(ctx.query_->getLabel())
2252 .arg(lease->toText());
2257 bool changed =
false;
2260 uint32_t current_preferred_lft = lease->preferred_lft_;
2261 getLifetimes6(ctx, lease->preferred_lft_, lease->valid_lft_);
2264 if ((lease->preferred_lft_ != current_preferred_lft) ||
2265 (lease->valid_lft_ != lease->current_valid_lft_)) {
2269 lease->cltt_ = time(NULL);
2270 if ((lease->fqdn_fwd_ != ctx.fwd_dns_update_) ||
2271 (lease->fqdn_rev_ != ctx.rev_dns_update_) ||
2272 (lease->hostname_ != ctx.hostname_)) {
2274 lease->hostname_ = ctx.hostname_;
2275 lease->fqdn_fwd_ = ctx.fwd_dns_update_;
2276 lease->fqdn_rev_ = ctx.rev_dns_update_;
2278 if ((!ctx.hwaddr_ && lease->hwaddr_) ||
2280 (!lease->hwaddr_ || (*ctx.hwaddr_ != *lease->hwaddr_)))) {
2282 lease->hwaddr_ = ctx.hwaddr_;
2290 .arg(ctx.query_->getLabel())
2291 .arg(lease->toText());
2295 int hook_point = ctx.query_->getType() ==
DHCPV6_RENEW ?
2296 Hooks.hook_index_lease6_renew_ :
Hooks.hook_index_lease6_rebind_;
2307 ScopedEnableOptionsCopy<Pkt6> query6_options_copy(ctx.query_);
2310 callout_handle->setArgument(
"query6", ctx.query_);
2313 callout_handle->setArgument(
"lease6", lease);
2317 callout_handle->setArgument(
"ia_na", ctx.currentIA().ia_rsp_);
2319 callout_handle->setArgument(
"ia_pd", ctx.currentIA().ia_rsp_);
2332 .arg(ctx.query_->getName());
2339 bool update_stats =
false;
2343 if (old_data->expired()) {
2344 reclaimExpiredLease(old_data, ctx.callout_handle_);
2348 if (ctx.subnet_->inPool(ctx.currentIA().type_, old_data->addr_)) {
2349 update_stats =
true;
2362 setLeaseReusable(lease, current_preferred_lft, ctx);
2367 if (lease->reuseable_valid_lft_ == 0) {
2368 auto const& pool = ctx.subnet_->getPool(ctx.currentIA().type_, lease->addr_,
false);
2370 lease->pool_id_ = pool->getID();
2379 "assigned-nas" :
"assigned-pds"),
2380 static_cast<int64_t>(1));
2385 "cumulative-assigned-nas" :
"cumulative-assigned-pds"),
2386 static_cast<int64_t>(1));
2388 auto const& pool = ctx.subnet_->getPool(ctx.currentIA().type_, lease->addr_,
false);
2393 "pool" :
"pd-pool", pool->getID(),
2395 "assigned-nas" :
"assigned-pds")),
2396 static_cast<int64_t>(1));
2401 "pool" :
"pd-pool", pool->getID(),
2403 "cumulative-assigned-nas" :
"cumulative-assigned-pds")),
2404 static_cast<int64_t>(1));
2408 "cumulative-assigned-nas" :
"cumulative-assigned-pds",
2409 static_cast<int64_t>(1));
2422 ctx.currentIA().changed_leases_.push_back(old_data);
2428 for (
auto const& lease_it : leases) {
2430 if (ctx.currentIA().isNewResource(lease->addr_, lease->prefixlen_)) {
2432 updated_leases.push_back(lease);
2436 lease->reuseable_valid_lft_ = 0;
2437 lease->fqdn_fwd_ = ctx.fwd_dns_update_;
2438 lease->fqdn_rev_ = ctx.rev_dns_update_;
2439 lease->hostname_ = ctx.hostname_;
2440 uint32_t current_preferred_lft = lease->preferred_lft_;
2441 if (lease->valid_lft_ == 0) {
2443 getLifetimes6(ctx, lease->preferred_lft_, lease->valid_lft_);
2445 if (!ctx.fake_allocation_) {
2446 bool update_stats =
false;
2454 if (inAllowedPool(ctx, ctx.currentIA().type_,
2455 lease->addr_,
true)) {
2456 update_stats =
true;
2461 !(lease->hasIdenticalFqdn(*lease_it)));
2463 lease->cltt_ = time(NULL);
2464 if (!fqdn_changed) {
2465 setLeaseReusable(lease, current_preferred_lft, ctx);
2467 if (lease->reuseable_valid_lft_ == 0) {
2468 ctx.currentIA().changed_leases_.push_back(lease_it);
2476 "assigned-nas" :
"assigned-pds"),
2477 static_cast<int64_t>(1));
2482 "cumulative-assigned-nas" :
"cumulative-assigned-pds"),
2483 static_cast<int64_t>(1));
2485 auto const& pool = ctx.subnet_->getPool(ctx.currentIA().type_, lease->addr_,
false);
2490 "pool" :
"pd-pool", pool->getID(),
2492 "assigned-nas" :
"assigned-pds")),
2493 static_cast<int64_t>(1));
2498 "pool" :
"pd-pool", pool->getID(),
2500 "cumulative-assigned-nas" :
"cumulative-assigned-pds")),
2501 static_cast<int64_t>(1));
2505 "cumulative-assigned-nas" :
"cumulative-assigned-pds",
2506 static_cast<int64_t>(1));
2510 updated_leases.push_back(lease);
2513 return (updated_leases);
2518 const uint16_t timeout,
2519 const bool remove_lease,
2520 const uint16_t max_unwarned_cycles) {
2529 max_unwarned_cycles);
2530 }
catch (
const std::exception& ex) {
2539 const uint16_t timeout,
2540 const bool remove_lease,
2541 const uint16_t max_unwarned_cycles) {
2551 bool incomplete_reclamation =
false;
2554 if (max_leases > 0) {
2558 lease_mgr.getExpiredLeases6(leases, max_leases + 1);
2563 if (leases.size() > max_leases) {
2565 incomplete_reclamation =
true;
2572 lease_mgr.getExpiredLeases6(leases, max_leases);
2578 if (!leases.empty() &&
2583 size_t leases_processed = 0;
2584 for (
auto const& lease : leases) {
2592 reclaimExpiredLease(lease, remove_lease, callout_handle);
2595 reclaimExpiredLease(lease, remove_lease, callout_handle);
2599 }
catch (
const std::exception& ex) {
2601 .arg(lease->addr_.toText())
2608 if ((timeout > 0) && (stopwatch.getTotalMilliseconds() >= timeout)) {
2612 if (!incomplete_reclamation) {
2613 if (leases_processed < leases.size()) {
2614 incomplete_reclamation =
true;
2631 .arg(leases_processed)
2632 .arg(stopwatch.logFormatTotalDuration());
2636 if (incomplete_reclamation) {
2637 ++incomplete_v6_reclamations_;
2640 if ((max_unwarned_cycles > 0) &&
2641 (incomplete_v6_reclamations_ > max_unwarned_cycles)) {
2643 .arg(max_unwarned_cycles);
2645 incomplete_v6_reclamations_ = 0;
2650 incomplete_v6_reclamations_ = 0;
2663 uint64_t deleted_leases = 0;
2667 deleted_leases = lease_mgr.deleteExpiredReclaimedLeases6(secs);
2669 }
catch (
const std::exception& ex) {
2676 .arg(deleted_leases);
2681 const uint16_t timeout,
2682 const bool remove_lease,
2683 const uint16_t max_unwarned_cycles) {
2692 max_unwarned_cycles);
2693 }
catch (
const std::exception& ex) {
2702 const uint16_t timeout,
2703 const bool remove_lease,
2704 const uint16_t max_unwarned_cycles) {
2714 bool incomplete_reclamation =
false;
2717 if (max_leases > 0) {
2721 lease_mgr.getExpiredLeases4(leases, max_leases + 1);
2726 if (leases.size() > max_leases) {
2728 incomplete_reclamation =
true;
2735 lease_mgr.getExpiredLeases4(leases, max_leases);
2741 if (!leases.empty() &&
2746 size_t leases_processed = 0;
2747 for (
auto const& lease : leases) {
2755 reclaimExpiredLease(lease, remove_lease, callout_handle);
2758 reclaimExpiredLease(lease, remove_lease, callout_handle);
2762 }
catch (
const std::exception& ex) {
2764 .arg(lease->addr_.toText())
2771 if ((timeout > 0) && (stopwatch.getTotalMilliseconds() >= timeout)) {
2775 if (!incomplete_reclamation) {
2776 if (leases_processed < leases.size()) {
2777 incomplete_reclamation =
true;
2794 .arg(leases_processed)
2795 .arg(stopwatch.logFormatTotalDuration());
2799 if (incomplete_reclamation) {
2800 ++incomplete_v4_reclamations_;
2803 if ((max_unwarned_cycles > 0) &&
2804 (incomplete_v4_reclamations_ > max_unwarned_cycles)) {
2806 .arg(max_unwarned_cycles);
2808 incomplete_v4_reclamations_ = 0;
2813 incomplete_v4_reclamations_ = 0;
2820template<
typename LeasePtrType>
2822AllocEngine::reclaimExpiredLease(
const LeasePtrType& lease,
const bool remove_lease,
2824 reclaimExpiredLease(lease, remove_lease ? DB_RECLAIM_REMOVE : DB_RECLAIM_UPDATE,
2828template<
typename LeasePtrType>
2830AllocEngine::reclaimExpiredLease(
const LeasePtrType& lease,
2835 if (!lease->stateExpiredReclaimed()) {
2836 reclaimExpiredLease(lease, DB_RECLAIM_LEAVE_UNCHANGED, callout_handle);
2841AllocEngine::reclaimExpiredLease(
const Lease6Ptr& lease,
2842 const DbReclaimMode& reclaim_mode,
2848 .arg(lease->addr_.toText())
2849 .arg(
static_cast<int>(lease->prefixlen_));
2855 bool skipped =
false;
2856 if (callout_handle) {
2864 callout_handle->deleteAllArguments();
2865 callout_handle->setArgument(
"lease6", lease);
2866 callout_handle->setArgument(
"remove_lease", reclaim_mode == DB_RECLAIM_REMOVE);
2886 bool remove_lease = (reclaim_mode == DB_RECLAIM_REMOVE);
2896 remove_lease = reclaimDeclined(lease);
2899 if (reclaim_mode != DB_RECLAIM_LEAVE_UNCHANGED) {
2903 reclaimLeaseInDatabase<Lease6Ptr>(lease, remove_lease,
2905 &lease_mgr, ph::_1));
2914 "reclaimed-leases"),
2915 static_cast<int64_t
>(1));
2931 static_cast<int64_t
>(-1));
2933 auto const& subnet =
CfgMgr::instance().getCurrentCfg()->getCfgSubnets6()->getBySubnetId(lease->subnet_id_);
2935 auto const& pool = subnet->getPool(lease->type_, lease->addr_,
false);
2941 static_cast<int64_t
>(-1));
2946 "reclaimed-leases")),
2947 static_cast<int64_t
>(1));
2956 static_cast<int64_t
>(-1));
2958 auto const& subnet =
CfgMgr::instance().getCurrentCfg()->getCfgSubnets6()->getBySubnetId(lease->subnet_id_);
2960 auto const& pool = subnet->getPool(lease->type_, lease->addr_,
false);
2966 static_cast<int64_t
>(-1));
2971 "reclaimed-leases")),
2972 static_cast<int64_t
>(1));
2979AllocEngine::reclaimExpiredLease(
const Lease4Ptr& lease,
2980 const DbReclaimMode& reclaim_mode,
2986 .arg(lease->addr_.toText());
2992 bool skipped =
false;
2993 if (callout_handle) {
3001 callout_handle->setArgument(
"lease4", lease);
3002 callout_handle->setArgument(
"remove_lease", reclaim_mode == DB_RECLAIM_REMOVE);
3020 lease->hostname_.clear();
3021 lease->fqdn_fwd_ =
false;
3022 lease->fqdn_rev_ =
false;
3026 bool remove_lease = (reclaim_mode == DB_RECLAIM_REMOVE);
3036 remove_lease = reclaimDeclined(lease);
3039 if (reclaim_mode != DB_RECLAIM_LEAVE_UNCHANGED) {
3043 reclaimLeaseInDatabase<Lease4Ptr>(lease, remove_lease,
3045 &lease_mgr, ph::_1));
3057 "reclaimed-leases"),
3058 static_cast<int64_t
>(1));
3068 "assigned-addresses"),
3069 static_cast<int64_t
>(-1));
3071 auto const& subnet =
CfgMgr::instance().getCurrentCfg()->getCfgSubnets4()->getBySubnetId(lease->subnet_id_);
3073 auto const& pool = subnet->getPool(
Lease::TYPE_V4, lease->addr_,
false);
3078 "assigned-addresses")),
3079 static_cast<int64_t
>(-1));
3084 "reclaimed-leases")),
3085 static_cast<int64_t
>(1));
3096 uint64_t deleted_leases = 0;
3100 deleted_leases = lease_mgr.deleteExpiredReclaimedLeases4(secs);
3102 }
catch (
const std::exception& ex) {
3109 .arg(deleted_leases);
3113AllocEngine::reclaimDeclined(
const Lease4Ptr& lease) {
3128 callout_handle->setArgument(
"lease4", lease);
3138 .arg(lease->addr_.toText());
3144 .arg(lease->addr_.toText())
3145 .arg(lease->valid_lft_);
3151 "declined-addresses"),
3152 static_cast<int64_t
>(-1));
3155 "reclaimed-declined-addresses"),
3156 static_cast<int64_t
>(1));
3158 auto const& subnet =
CfgMgr::instance().getCurrentCfg()->getCfgSubnets4()->getBySubnetId(lease->subnet_id_);
3160 auto const& pool = subnet->getPool(
Lease::TYPE_V4, lease->addr_,
false);
3164 "declined-addresses")),
3165 static_cast<int64_t
>(-1));
3169 "reclaimed-declined-addresses")),
3170 static_cast<int64_t
>(1));
3175 stats_mgr.addValue(
"declined-addresses",
static_cast<int64_t
>(-1));
3177 stats_mgr.addValue(
"reclaimed-declined-addresses",
static_cast<int64_t
>(1));
3185AllocEngine::reclaimDeclined(
const Lease6Ptr& lease) {
3200 callout_handle->setArgument(
"lease6", lease);
3210 .arg(lease->addr_.toText());
3216 .arg(lease->addr_.toText())
3217 .arg(lease->valid_lft_);
3223 "declined-addresses"),
3224 static_cast<int64_t
>(-1));
3227 "reclaimed-declined-addresses"),
3228 static_cast<int64_t
>(1));
3230 auto const& subnet =
CfgMgr::instance().getCurrentCfg()->getCfgSubnets6()->getBySubnetId(lease->subnet_id_);
3232 auto const& pool = subnet->getPool(lease->type_, lease->addr_,
false);
3236 "declined-addresses")),
3237 static_cast<int64_t
>(-1));
3241 "reclaimed-declined-addresses")),
3242 static_cast<int64_t
>(1));
3247 stats_mgr.addValue(
"declined-addresses",
static_cast<int64_t
>(-1));
3249 stats_mgr.addValue(
"reclaimed-declined-addresses",
static_cast<int64_t
>(1));
3259 lease->relay_id_.clear();
3260 lease->remote_id_.clear();
3261 if (lease->getContext()) {
3268 if (lease->getContext()) {
3274template<
typename LeasePtrType>
3275void AllocEngine::reclaimLeaseInDatabase(
const LeasePtrType& lease,
3276 const bool remove_lease,
3277 const std::function<
void (
const LeasePtrType&)>&
3278 lease_update_fun)
const {
3285 lease_mgr.deleteLease(lease);
3286 }
else if (lease_update_fun) {
3289 lease->reuseable_valid_lft_ = 0;
3290 lease->hostname_.clear();
3291 lease->fqdn_fwd_ =
false;
3292 lease->fqdn_rev_ =
false;
3295 lease_update_fun(lease);
3304 .arg(lease->addr_.toText());
3310 return(
"<empty subnet>");
3314 subnet->getSharedNetwork(network);
3315 std::ostringstream ss;
3317 ss <<
"shared-network: " << network->getName();
3319 ss <<
"subnet id: " << subnet->getID();
3358 (!ctx.
subnet_->getReservationsOutOfPool() ||
3369 if (
CfgMgr::instance().getCurrentCfg()->getCfgDbAccess()->getIPReservationsUnique()) {
3374 hosts.push_back(host);
3388 for (
auto const& host : hosts) {
3392 if (id_pair.first == host->getIdentifierType() &&
3393 id_pair.second == host->getIdentifier()) {
3401 return (!hosts.empty());
3423 if (ctx.
hosts_.empty()) {
3428 auto global_host = ctx.
hosts_.find(SUBNET_ID_GLOBAL);
3429 auto global_host_address = ((global_host != ctx.
hosts_.end() && global_host->second) ?
3430 global_host->second->getIPv4Reservation() :
3439 if (subnet->getReservationsGlobal() &&
3441 (subnet->inRange(global_host_address))) {
3446 if (subnet->getReservationsInSubnet()) {
3447 auto host = ctx.
hosts_.find(subnet->getID());
3452 if (host != ctx.
hosts_.end() && host->second) {
3453 auto reservation = host->second->getIPv4Reservation();
3454 if (!reservation.isV4Zero() &&
3455 (!subnet->getReservationsOutOfPool() ||
3465 subnet = subnet->getNextSubnet(ctx.
subnet_, ctx.
query_->getClasses());
3471 .arg(ctx.
query_->getLabel())
3472 .arg(ctx.
currentHost()->getIPv4Reservation().toText())
3499 auto const& classes = ctx.
query_->getClasses();
3503 bool try_clientid_lookup = (ctx.
clientid_ &&
3507 if (try_clientid_lookup) {
3515 for (
Subnet4Ptr subnet = original_subnet; subnet;
3516 subnet = subnet->getNextSubnet(original_subnet, classes)) {
3521 if (subnet->getMatchClientId()) {
3522 for (
auto const& l : leases_client_id) {
3523 if (l->subnet_id_ == subnet->getID()) {
3536 if (!client_lease && ctx.
hwaddr_) {
3541 for (
Subnet4Ptr subnet = original_subnet; subnet;
3542 subnet = subnet->getNextSubnet(original_subnet, classes)) {
3544 if (subnet->getMatchClientId()) {
3550 for (
auto const& client_lease_it : leases_hw_address) {
3551 Lease4Ptr existing_lease = client_lease_it;
3552 if ((existing_lease->subnet_id_ == subnet->getID()) &&
3553 existing_lease->belongsToClient(ctx.
hwaddr_, client_id)) {
3555 client_lease = existing_lease;
3583 auto const& classes = ctx.
query_->getClasses();
3585 while (current_subnet) {
3594 current_subnet = current_subnet->getNextSubnet(ctx.
subnet_, classes);
3606 : early_global_reservations_lookup_(false),
3607 subnet_(), clientid_(), hwaddr_(),
3608 requested_address_(
IOAddress::IPV4_ZERO_ADDRESS()),
3609 fwd_dns_update_(false), rev_dns_update_(false),
3610 hostname_(
""), callout_handle_(), fake_allocation_(false), offer_lft_(0),
3611 old_lease_(), new_lease_(), hosts_(), conflicting_lease_(),
3612 query_(), host_identifiers_(), unknown_requested_addr_(false),
3621 const bool fwd_dns_update,
3622 const bool rev_dns_update,
3623 const std::string& hostname,
3624 const bool fake_allocation,
3625 const uint32_t offer_lft)
3626 : early_global_reservations_lookup_(false),
3627 subnet_(subnet), clientid_(clientid), hwaddr_(hwaddr),
3628 requested_address_(requested_addr),
3629 fwd_dns_update_(fwd_dns_update), rev_dns_update_(rev_dns_update),
3630 hostname_(hostname), callout_handle_(),
3631 fake_allocation_(fake_allocation), offer_lft_(offer_lft), old_lease_(), new_lease_(),
3632 hosts_(), host_identifiers_(), unknown_requested_addr_(false),
3643 if (subnet_ && subnet_->getReservationsInSubnet()) {
3644 auto host = hosts_.find(subnet_->getID());
3645 if (host != hosts_.cend()) {
3646 return (host->second);
3650 return (globalHost());
3655 if (subnet_ && subnet_->getReservationsGlobal()) {
3656 auto host = hosts_.find(SUBNET_ID_GLOBAL);
3657 if (host != hosts_.cend()) {
3658 return (host->second);
3668 if (ddns_params_ && subnet_ && (subnet_->getID() == ddns_params_->getSubnetId())) {
3669 return (ddns_params_);
3675 return (ddns_params_);
3697 auto const& classes = ctx.
query_->getClasses();
3698 if (subnet && !subnet->clientSupported(classes)) {
3699 ctx.
subnet_ = subnet->getNextSubnet(subnet, classes);
3720 .arg(ctx.
query_->getLabel())
3738 !subnet->getReservationsInSubnet()) {
3744 subnet->getReservationsGlobal()) {
3747 ctx.
hosts_[SUBNET_ID_GLOBAL] = ghost;
3750 if (!subnet->getReservationsInSubnet()) {
3756 std::map<SubnetID, ConstHostPtr> host_map;
3758 subnet->getSharedNetwork(network);
3767 const bool use_single_query = network &&
3771 if (use_single_query) {
3775 id_pair.second.size());
3779 for (
auto const& host : hosts) {
3780 if (host->getIPv4SubnetID() != SUBNET_ID_GLOBAL) {
3781 host_map[host->getIPv4SubnetID()] = host;
3787 auto const& classes = ctx.
query_->getClasses();
3793 if (subnet->clientSupported(classes) && subnet->getReservationsInSubnet()) {
3796 if (use_single_query) {
3797 if (host_map.count(subnet->getID()) > 0) {
3798 ctx.
hosts_[subnet->getID()] = host_map[subnet->getID()];
3806 id_pair.second.size());
3809 ctx.
hosts_[subnet->getID()] = host;
3819 subnet = subnet->getNextSubnet(ctx.
subnet_, classes);
3825 for (
auto const& host : ctx.
hosts_) {
3826 host.second->encapsulateOptions();
3836 &id_pair.second[0], id_pair.second.size());
3853 findClientLease(ctx, client_lease);
3866 if (hasAddressReservation(ctx)) {
3870 .arg(ctx.
query_->getLabel())
3871 .arg(ctx.
currentHost()->getIPv4Reservation().toText());
3877 if (!client_lease || (client_lease->addr_ != ctx.
currentHost()->getIPv4Reservation())) {
3884 new_lease = allocateOrReuseLease4(ctx.
currentHost()->getIPv4Reservation(), ctx,
3888 .arg(ctx.
query_->getLabel())
3889 .arg(ctx.
currentHost()->getIPv4Reservation().toText())
3894 "v4-reservation-conflicts"),
3895 static_cast<int64_t
>(1));
3897 static_cast<int64_t
>(1));
3901 new_lease = renewLease4(client_lease, ctx);
3914 if (!new_lease && client_lease && inAllowedPool(ctx, client_lease->addr_) &&
3915 !addressReserved(client_lease->addr_, ctx)) {
3919 .arg(ctx.
query_->getLabel());
3925 (time(NULL) + ctx.
offer_lft_ < client_lease->getExpirationTime())) {
3929 new_lease = renewLease4(client_lease, ctx);
3946 .arg(ctx.
query_->getLabel());
3959 .arg(ctx.
query_->getLabel());
3961 new_lease = allocateUnreservedLease4(ctx);
3981 findClientLease(ctx, client_lease);
3997 .arg(ctx.
query_->getLabel())
4003 }
else if (hasAddressReservation(ctx)) {
4012 .arg(ctx.
query_->getLabel())
4024 if (existing && !existing->expired() &&
4025 !existing->belongsToClient(ctx.
hwaddr_, ctx.
subnet_->getMatchClientId() ?
4030 .arg(ctx.
query_->getLabel())
4040 if (hasAddressReservation(ctx) &&
4048 if (!existing || existing->expired()) {
4052 .arg(ctx.
query_->getLabel())
4053 .arg(ctx.
currentHost()->getIPv4Reservation().toText())
4063 if ((!hasAddressReservation(ctx) ||
4069 .arg(ctx.
query_->getLabel())
4089 ((hasAddressReservation(ctx) &&
4091 inAllowedPool(ctx, client_lease->addr_))) {
4095 .arg(ctx.
query_->getLabel())
4098 return (renewLease4(client_lease, ctx));
4112 .arg(ctx.
query_->getLabel())
4128 .arg(ctx.
query_->getLabel());
4133 new_lease = allocateUnreservedLease4(ctx);
4139 if (new_lease && client_lease) {
4144 .arg(ctx.
query_->getLabel())
4145 .arg(client_lease->addr_.toText());
4151 "assigned-addresses"),
4152 static_cast<int64_t
>(-1));
4154 auto const& subnet =
CfgMgr::instance().getCurrentCfg()->getCfgSubnets4()->getBySubnetId(client_lease->subnet_id_);
4156 auto const& pool = subnet->getPool(
Lease::TYPE_V4, client_lease->addr_,
false);
4161 "assigned-addresses")),
4162 static_cast<int64_t
>(-1));
4185 if (!classes.empty()) {
4191 for (
auto const& name : classes) {
4193 if (cl && (!cl->getOfferLft().unspecified())) {
4194 offer_lft = cl->getOfferLft();
4201 if (offer_lft.unspecified()) {
4202 offer_lft = ctx.
subnet_->getOfferLft();
4205 return (offer_lft.unspecified() ? 0 : offer_lft.get());
4211 if (ctx.
query_->inClass(
"BOOTP")) {
4216 uint32_t requested_lft = 0;
4219 OptionUint32Ptr opt_lft = boost::dynamic_pointer_cast<OptionInt<uint32_t> >(opt);
4221 requested_lft = opt_lft->getValue();
4227 Triplet<uint32_t> candidate_lft;
4229 if (!classes.empty()) {
4235 for (
auto const& name : classes) {
4237 if (cl && (!cl->getValid().unspecified())) {
4238 candidate_lft = cl->getValid();
4245 if (!candidate_lft) {
4246 candidate_lft = ctx.
subnet_->getValid();
4251 if (requested_lft > 0) {
4252 return (candidate_lft.get(requested_lft));
4256 return (candidate_lft.get());
4260AllocEngine::createLease4(
const ClientContext4& ctx,
const IOAddress& addr,
4270 uint32_t valid_lft = (ctx.offer_lft_ ? ctx.offer_lft_ :
getValidLft(ctx));
4272 time_t now = time(NULL);
4275 if (ctx.subnet_->getMatchClientId()) {
4276 client_id = ctx.clientid_;
4280 valid_lft, now, ctx.subnet_->getID()));
4283 lease->fqdn_fwd_ = ctx.fwd_dns_update_;
4284 lease->fqdn_rev_ = ctx.rev_dns_update_;
4285 lease->hostname_ = ctx.hostname_;
4291 if (ctx.callout_handle_ &&
4301 ScopedEnableOptionsCopy<Pkt4> query4_options_copy(ctx.query_);
4305 ctx.callout_handle_->setArgument(
"query4", ctx.query_);
4311 Subnet4Ptr subnet4 = boost::dynamic_pointer_cast<Subnet4>(ctx.subnet_);
4312 ctx.callout_handle_->setArgument(
"subnet4", subnet4);
4315 ctx.callout_handle_->setArgument(
"fake_allocation", ctx.fake_allocation_);
4318 ctx.callout_handle_->setArgument(
"offer_lft", ctx.offer_lft_);
4321 ctx.callout_handle_->setArgument(
"lease4", lease);
4326 callout_status = ctx.callout_handle_->getStatus();
4338 ctx.callout_handle_->getArgument(
"lease4", lease);
4341 if (ctx.fake_allocation_ && ctx.offer_lft_) {
4345 lease->fqdn_fwd_ =
false;
4346 lease->fqdn_rev_ =
false;
4349 if (!ctx.fake_allocation_ || ctx.offer_lft_) {
4350 auto const& pool = ctx.subnet_->getPool(
Lease::TYPE_V4, lease->addr_,
false);
4352 lease->pool_id_ = pool->getID();
4361 "assigned-addresses"),
4362 static_cast<int64_t
>(1));
4366 "cumulative-assigned-addresses"),
4367 static_cast<int64_t
>(1));
4373 "assigned-addresses")),
4374 static_cast<int64_t
>(1));
4379 "cumulative-assigned-addresses")),
4380 static_cast<int64_t
>(1));
4384 static_cast<int64_t
>(1));
4403AllocEngine::renewLease4(
const Lease4Ptr& lease,
4413 Lease4Ptr old_values = boost::make_shared<Lease4>(*lease);
4418 lease->reuseable_valid_lft_ = 0;
4419 if (!updateLease4Information(lease, ctx)) {
4420 setLeaseReusable(lease, ctx);
4445 ScopedEnableOptionsCopy<Pkt4> query4_options_copy(ctx.
query_);
4460 ctx.
callout_handle_->setArgument(
"clientid", subnet4->getMatchClientId() ?
4486 lease->pool_id_ = pool->getID();
4496 "assigned-addresses"),
4497 static_cast<int64_t
>(1));
4501 "cumulative-assigned-addresses"),
4502 static_cast<int64_t
>(1));
4508 "assigned-addresses")),
4509 static_cast<int64_t
>(1));
4514 "cumulative-assigned-addresses")),
4515 static_cast<int64_t
>(1));
4519 static_cast<int64_t
>(1));
4525 *lease = *old_values;
4532AllocEngine::reuseExpiredLease4(
Lease4Ptr& expired,
4551 expired->reuseable_valid_lft_ = 0;
4552 static_cast<void>(updateLease4Information(expired, ctx));
4556 .arg(ctx.
query_->getLabel())
4557 .arg(expired->toText());
4564 ScopedEnableOptionsCopy<Pkt4> query4_options_copy(ctx.
query_);
4614 expired->pool_id_ = pool->getID();
4622 "assigned-addresses"),
4623 static_cast<int64_t
>(1));
4627 "cumulative-assigned-addresses"),
4628 static_cast<int64_t
>(1));
4634 "assigned-addresses")),
4635 static_cast<int64_t
>(1));
4640 "cumulative-assigned-addresses")),
4641 static_cast<int64_t
>(1));
4645 static_cast<int64_t
>(1));
4657AllocEngine::allocateOrReuseLease4(
const IOAddress& candidate, ClientContext4& ctx,
4659 ctx.conflicting_lease_.reset();
4663 if (exist_lease->expired()) {
4668 ctx.old_lease_->hostname_.clear();
4669 ctx.old_lease_->fqdn_fwd_ =
false;
4670 ctx.old_lease_->fqdn_rev_ =
false;
4671 return (reuseExpiredLease4(exist_lease, ctx, callout_status));
4677 ctx.conflicting_lease_ = exist_lease;
4681 return (createLease4(ctx, candidate, callout_status));
4687AllocEngine::allocateUnreservedLease4(ClientContext4& ctx) {
4701 ctx.subnet_->getSharedNetwork(network);
4708 ctx.subnet_ = subnet = network->getPreferredSubnet(ctx.subnet_);
4722 uint64_t subnets_with_unavail_leases = 0;
4725 uint64_t subnets_with_unavail_pools = 0;
4727 auto const& classes = ctx.query_->getClasses();
4731 if (subnet->getMatchClientId()) {
4732 client_id = ctx.clientid_;
4744 (attempts_ == 0 || possible_attempts < attempts_) ?
4748 if (max_attempts > 0) {
4751 ++subnets_with_unavail_leases;
4755 ++subnets_with_unavail_pools;
4758 bool exclude_first_last_24 = ((subnet->get().second <= 24) &&
4763 for (
uint128_t i = 0; i < max_attempts; ++i) {
4768 IOAddress candidate = allocator->pickAddress(classes,
4770 ctx.requested_address_);
4773 if (candidate.isV4Zero()) {
4777 if (exclude_first_last_24) {
4779 auto const& bytes = candidate.
toBytes();
4780 if ((bytes.size() != 4) ||
4781 (bytes[3] == 0) || (bytes[3] == 255U)) {
4788 if (check_reservation_first && addressReserved(candidate, ctx)) {
4797 !resource_handler.tryLock4(candidate)) {
4806 if (check_reservation_first || !addressReserved(candidate, ctx)) {
4808 new_lease = createLease4(ctx, candidate, callout_status);
4812 if (exist_lease->expired() &&
4813 (check_reservation_first || !addressReserved(candidate, ctx))) {
4815 new_lease = reuseExpiredLease4(exist_lease, ctx, callout_status);
4833 subnet = subnet->getNextSubnet(original_subnet, classes);
4836 ctx.subnet_ = subnet;
4845 .arg(ctx.query_->getLabel())
4846 .arg(network->getName())
4847 .arg(subnets_with_unavail_leases)
4848 .arg(subnets_with_unavail_pools);
4850 static_cast<int64_t
>(1));
4853 "v4-allocation-fail-shared-network"),
4854 static_cast<int64_t
>(1));
4858 std::string shared_network = ctx.subnet_->getSharedNetworkName();
4859 if (shared_network.empty()) {
4860 shared_network =
"(none)";
4863 .arg(ctx.query_->getLabel())
4864 .arg(ctx.subnet_->toText())
4865 .arg(ctx.subnet_->getID())
4866 .arg(shared_network);
4868 static_cast<int64_t
>(1));
4871 "v4-allocation-fail-subnet"),
4872 static_cast<int64_t
>(1));
4874 if (total_attempts == 0) {
4880 .arg(ctx.query_->getLabel());
4882 static_cast<int64_t
>(1));
4885 "v4-allocation-fail-no-pools"),
4886 static_cast<int64_t
>(1));
4893 .arg(ctx.query_->getLabel())
4894 .arg(total_attempts);
4896 static_cast<int64_t
>(1));
4899 "v4-allocation-fail"),
4900 static_cast<int64_t
>(1));
4903 if (!classes.empty()) {
4905 .arg(ctx.query_->getLabel())
4906 .arg(classes.toText());
4908 static_cast<int64_t
>(1));
4911 "v4-allocation-fail-classes"),
4912 static_cast<int64_t
>(1));
4919AllocEngine::updateLease4Information(
const Lease4Ptr& lease,
4921 bool changed =
false;
4922 if (lease->subnet_id_ != ctx.
subnet_->getID()) {
4924 lease->subnet_id_ = ctx.
subnet_->getID();
4926 if ((!ctx.
hwaddr_ && lease->hwaddr_) ||
4928 (!lease->hwaddr_ || (*ctx.
hwaddr_ != *lease->hwaddr_)))) {
4933 if (!lease->client_id_ || (*ctx.
clientid_ != *lease->client_id_)) {
4937 }
else if (lease->client_id_) {
4941 lease->cltt_ = time(NULL);
4947 if (lease->valid_lft_ != lease->current_valid_lft_) {
4971 bool changed =
false;
4974 if (!ctx.
subnet_->getStoreExtendedInfo()) {
4989 sao->boolValue() && ctx.
query_->inClass(
"STASH_AGENT_OPTIONS")) {
4998 extended_info->set(
"sub-options", relay_agent);
5002 std::vector<uint8_t> bytes = remote_id->toBinary();
5003 lease->remote_id_ = bytes;
5004 if (bytes.size() > 0) {
5005 extended_info->set(
"remote-id",
5012 std::vector<uint8_t> bytes = relay_id->toBinary(
false);
5013 lease->relay_id_ = bytes;
5014 if (bytes.size() > 0) {
5015 extended_info->set(
"relay-id",
5023 if (user_context && (user_context->getType() ==
Element::map)) {
5024 mutable_user_context =
copy(user_context, 0);
5039 ConstElementPtr old_extended_info = mutable_isc->get(
"relay-agent-info");
5040 if (!old_extended_info || (*old_extended_info != *extended_info)) {
5042 mutable_isc->set(
"relay-agent-info", extended_info);
5043 mutable_user_context->set(
"ISC", mutable_isc);
5047 lease->setContext(mutable_user_context);
5059 if (!ctx.
subnet_->getStoreExtendedInfo()) {
5064 if (ctx.
query_->relay_info_.empty()) {
5079 for (
auto const& relay : ctx.
query_->relay_info_) {
5088 if (!relay.options_.empty()) {
5092 if (buf.getLength() > 0) {
5093 const uint8_t* cp = buf.getData();
5094 std::vector<uint8_t> bytes;
5095 std::stringstream ss;
5097 bytes.assign(cp, cp + buf.getLength());
5103 if (remote_id_it != relay.options_.end()) {
5104 OptionPtr remote_id = remote_id_it->second;
5106 std::vector<uint8_t> bytes = remote_id->toBinary();
5107 if (bytes.size() > 0) {
5108 relay_elem->set(
"remote-id",
5115 if (relay_id_it != relay.options_.end()) {
5116 OptionPtr relay_id = relay_id_it->second;
5118 std::vector<uint8_t> bytes = relay_id->toBinary(
false);
5119 if (bytes.size() > 0) {
5120 relay_elem->set(
"relay-id",
5127 extended_info->add(relay_elem);
5133 if (user_context && (user_context->getType() ==
Element::map)) {
5134 mutable_user_context =
copy(user_context, 0);
5150 if (!old_extended_info || (*old_extended_info != *extended_info)) {
5152 mutable_isc->set(
"relay-info", extended_info);
5153 mutable_user_context->set(
"ISC", mutable_isc);
5157 lease->setContext(mutable_user_context);
5161AllocEngine::setLeaseReusable(
const Lease4Ptr& lease,
5162 const ClientContext4& ctx)
const {
5164 lease->reuseable_valid_lft_ = 0;
5180 if (lease->cltt_ < lease->current_cltt_) {
5184 uint32_t age = lease->cltt_ - lease->current_cltt_;
5186 if (age >= lease->current_valid_lft_) {
5191 uint32_t max_age = 0;
5192 if (!subnet->getCacheMaxAge().unspecified()) {
5193 max_age = subnet->getCacheMaxAge().get();
5194 if ((max_age == 0) || (age > max_age)) {
5200 if (!subnet->getCacheThreshold().unspecified()) {
5201 double threshold = subnet->getCacheThreshold().get();
5202 if ((threshold <= 0.) || (threshold > 1.)) {
5205 max_age = lease->valid_lft_ * threshold;
5206 if (age > max_age) {
5217 lease->reuseable_valid_lft_ = lease->current_valid_lft_ - age;
5221AllocEngine::setLeaseReusable(
const Lease6Ptr& lease,
5222 uint32_t current_preferred_lft,
5223 const ClientContext6& ctx)
const {
5225 lease->reuseable_valid_lft_ = 0;
5226 lease->reuseable_preferred_lft_ = 0;
5236 if (lease->cltt_ < lease->current_cltt_) {
5240 uint32_t age = lease->cltt_ - lease->current_cltt_;
5242 if (age >= lease->current_valid_lft_) {
5247 uint32_t max_age = 0;
5248 if (!subnet->getCacheMaxAge().unspecified()) {
5249 max_age = subnet->getCacheMaxAge().get();
5250 if ((max_age == 0) || (age > max_age)) {
5256 if (!subnet->getCacheThreshold().unspecified()) {
5257 double threshold = subnet->getCacheThreshold().get();
5258 if ((threshold <= 0.) || (threshold > 1.)) {
5261 max_age = lease->valid_lft_ * threshold;
5262 if (age > max_age) {
5274 (current_preferred_lft == 0)) {
5276 lease->reuseable_preferred_lft_ = current_preferred_lft;
5277 }
else if (current_preferred_lft > age) {
5278 lease->reuseable_preferred_lft_ = current_preferred_lft - age;
5286 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.
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.
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.
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.
static CfgMgr & instance()
returns a single instance of Configuration Manager
Container for storing client class names.
Convenience container for conveying DDNS behavioral parameters It is intended to be created per Packe...
static HostMgr & instance()
Returns a sole instance of the HostMgr.
IPv6 reservation for a host.
Type
Type of the reservation.
static TrackingLeaseMgr & instance()
Return current lease manager.
virtual void updateLease4(const Lease4Ptr &lease4)=0
Updates IPv4 lease.
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.
Resource race avoidance RAII handler.
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.
@ 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.
Statistics Manager class.
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.
A template representing an optional value.
The OutputBuffer class is a buffer abstraction for manipulating mutable data.
Utility class to measure code execution times.
Write mutex RAII handler.
#define isc_throw(type, stream)
A shortcut macro to insert known values into exception arguments.
boost::shared_ptr< OptionUint32 > OptionUint32Ptr
#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