2
0
mirror of https://gitlab.isc.org/isc-projects/kea synced 2025-08-23 10:27:36 +00:00

[4320] ClientContext6 now holds information about multiple IAs.

This commit is contained in:
Marcin Siodelski 2016-06-03 15:20:02 +02:00
parent 522f98247b
commit 1d77f223f5
9 changed files with 387 additions and 299 deletions

View File

@ -276,12 +276,16 @@ Dhcpv6Srv::testUnicast(const Pkt6Ptr& pkt) const {
return (true); return (true);
} }
AllocEngine::ClientContext6 void
Dhcpv6Srv::createContext(const Pkt6Ptr& pkt) { Dhcpv6Srv::initContext(const Pkt6Ptr& pkt, AllocEngine::ClientContext6& ctx) {
AllocEngine::ClientContext6 ctx;
ctx.subnet_ = selectSubnet(pkt); ctx.subnet_ = selectSubnet(pkt);
ctx.duid_ = pkt->getClientId(),
ctx.fwd_dns_update_ = false;
ctx.rev_dns_update_ = false;
ctx.fake_allocation_ = false;
ctx.hostname_ = "";
ctx.query_ = pkt; ctx.query_ = pkt;
ctx.duid_ = pkt->getClientId(); ctx.callout_handle_ = getCalloutHandle(pkt);
ctx.hwaddr_ = getMAC(pkt); ctx.hwaddr_ = getMAC(pkt);
// Collect host identifiers if host reservations enabled. The identifiers // Collect host identifiers if host reservations enabled. The identifiers
@ -314,8 +318,6 @@ Dhcpv6Srv::createContext(const Pkt6Ptr& pkt) {
// Find host reservations using specified identifiers. // Find host reservations using specified identifiers.
alloc_engine_->findReservation(ctx); alloc_engine_->findReservation(ctx);
} }
return (ctx);
} }
bool Dhcpv6Srv::run() { bool Dhcpv6Srv::run() {
@ -1283,7 +1285,7 @@ Dhcpv6Srv::getMAC(const Pkt6Ptr& pkt) {
OptionPtr OptionPtr
Dhcpv6Srv::assignIA_NA(const Pkt6Ptr& query, const Pkt6Ptr& answer, Dhcpv6Srv::assignIA_NA(const Pkt6Ptr& query, const Pkt6Ptr& answer,
AllocEngine::ClientContext6& orig_ctx, AllocEngine::ClientContext6& ctx,
boost::shared_ptr<Option6IA> ia) { boost::shared_ptr<Option6IA> ia) {
// Check if the client sent us a hint in his IA_NA. Clients may send an // Check if the client sent us a hint in his IA_NA. Clients may send an
@ -1302,8 +1304,7 @@ Dhcpv6Srv::assignIA_NA(const Pkt6Ptr& query, const Pkt6Ptr& answer,
.arg(hint_opt ? hint.toText() : "(no hint)"); .arg(hint_opt ? hint.toText() : "(no hint)");
// convenience values // convenience values
const Subnet6Ptr& subnet = orig_ctx.subnet_; const Subnet6Ptr& subnet = ctx.subnet_;
const DuidPtr& duid = orig_ctx.duid_;
// If there is no subnet selected for handling this IA_NA, the only thing left to do is // If there is no subnet selected for handling this IA_NA, the only thing left to do is
// to say that we are sorry, but the user won't get an address. As a convenience, we // to say that we are sorry, but the user won't get an address. As a convenience, we
@ -1351,14 +1352,13 @@ Dhcpv6Srv::assignIA_NA(const Pkt6Ptr& query, const Pkt6Ptr& answer,
// will try to honor the hint, but it is just a hint - some other address // will try to honor the hint, but it is just a hint - some other address
// may be used instead. If fake_allocation is set to false, the lease will // may be used instead. If fake_allocation is set to false, the lease will
// be inserted into the LeaseMgr as well. // be inserted into the LeaseMgr as well.
AllocEngine::ClientContext6 ctx(subnet, duid, ia->getIAID(), ctx.createIAContext();
hint, Lease::TYPE_NA, do_fwd, do_rev, ctx.fwd_dns_update_ = do_fwd;
orig_ctx.hostname_, fake_allocation); ctx.rev_dns_update_ = do_rev;
ctx.callout_handle_ = getCalloutHandle(query); ctx.fake_allocation_ = fake_allocation;
ctx.hwaddr_ = orig_ctx.hwaddr_; ctx.currentIA().iaid_ = ia->getIAID();
ctx.host_ = orig_ctx.host_; ctx.currentIA().addHint(hint);
ctx.query_ = orig_ctx.query_; ctx.currentIA().type_ = Lease::TYPE_NA;
ctx.host_identifiers_ = orig_ctx.host_identifiers_;
Lease6Collection leases = alloc_engine_->allocateLeases6(ctx); Lease6Collection leases = alloc_engine_->allocateLeases6(ctx);
@ -1417,7 +1417,7 @@ Dhcpv6Srv::assignIA_NA(const Pkt6Ptr& query, const Pkt6Ptr& answer,
OptionPtr OptionPtr
Dhcpv6Srv::assignIA_PD(const Pkt6Ptr& query, const Pkt6Ptr& answer, Dhcpv6Srv::assignIA_PD(const Pkt6Ptr& query, const Pkt6Ptr& answer,
AllocEngine::ClientContext6& orig_ctx, AllocEngine::ClientContext6& ctx,
boost::shared_ptr<Option6IA> ia) { boost::shared_ptr<Option6IA> ia) {
// Check if the client sent us a hint in his IA_PD. Clients may send an // Check if the client sent us a hint in his IA_PD. Clients may send an
@ -1437,8 +1437,7 @@ Dhcpv6Srv::assignIA_PD(const Pkt6Ptr& query, const Pkt6Ptr& answer,
.arg(hint_opt ? hint.toText() : "(no hint)"); .arg(hint_opt ? hint.toText() : "(no hint)");
const Subnet6Ptr& subnet = orig_ctx.subnet_; const Subnet6Ptr& subnet = ctx.subnet_;
const DuidPtr& duid = orig_ctx.duid_;
// Create IA_PD that we will put in the response. // Create IA_PD that we will put in the response.
// Do not use OptionDefinition to create option's instance so // Do not use OptionDefinition to create option's instance so
@ -1474,13 +1473,13 @@ Dhcpv6Srv::assignIA_PD(const Pkt6Ptr& query, const Pkt6Ptr& answer,
// will try to honor the hint, but it is just a hint - some other address // will try to honor the hint, but it is just a hint - some other address
// may be used instead. If fake_allocation is set to false, the lease will // may be used instead. If fake_allocation is set to false, the lease will
// be inserted into the LeaseMgr as well. // be inserted into the LeaseMgr as well.
AllocEngine::ClientContext6 ctx(subnet, duid, ia->getIAID(), hint, Lease::TYPE_PD,
false, false, string(), fake_allocation); ctx.createIAContext();
ctx.callout_handle_ = getCalloutHandle(query); ctx.fake_allocation_ = fake_allocation;
ctx.hwaddr_ = orig_ctx.hwaddr_; ctx.currentIA().iaid_ = ia->getIAID();
ctx.host_ = orig_ctx.host_; ctx.currentIA().addHint(hint);
ctx.query_ = orig_ctx.query_; ctx.currentIA().type_ = Lease::TYPE_PD;
ctx.host_identifiers_ = orig_ctx.host_identifiers_;
Lease6Collection leases = alloc_engine_->allocateLeases6(ctx); Lease6Collection leases = alloc_engine_->allocateLeases6(ctx);
@ -1532,7 +1531,7 @@ Dhcpv6Srv::assignIA_PD(const Pkt6Ptr& query, const Pkt6Ptr& answer,
OptionPtr OptionPtr
Dhcpv6Srv::extendIA_NA(const Pkt6Ptr& query, const Pkt6Ptr& answer, Dhcpv6Srv::extendIA_NA(const Pkt6Ptr& query, const Pkt6Ptr& answer,
AllocEngine::ClientContext6& orig_ctx, AllocEngine::ClientContext6& ctx,
boost::shared_ptr<Option6IA> ia) { boost::shared_ptr<Option6IA> ia) {
LOG_DEBUG(lease6_logger, DBG_DHCP6_DETAIL, DHCP6_PROCESS_IA_NA_EXTEND) LOG_DEBUG(lease6_logger, DBG_DHCP6_DETAIL, DHCP6_PROCESS_IA_NA_EXTEND)
@ -1540,8 +1539,7 @@ Dhcpv6Srv::extendIA_NA(const Pkt6Ptr& query, const Pkt6Ptr& answer,
.arg(ia->getIAID()); .arg(ia->getIAID());
// convenience values // convenience values
const Subnet6Ptr& subnet = orig_ctx.subnet_; const Subnet6Ptr& subnet = ctx.subnet_;
const DuidPtr& duid = orig_ctx.duid_;
// Create empty IA_NA option with IAID matching the request. // Create empty IA_NA option with IAID matching the request.
Option6IAPtr ia_rsp(new Option6IA(D6O_IA_NA, ia->getIAID())); Option6IAPtr ia_rsp(new Option6IA(D6O_IA_NA, ia->getIAID()));
@ -1575,16 +1573,12 @@ Dhcpv6Srv::extendIA_NA(const Pkt6Ptr& query, const Pkt6Ptr& answer,
do_fwd, do_rev); do_fwd, do_rev);
} }
// Create client context for this renewal ctx.createIAContext();
AllocEngine::ClientContext6 ctx(subnet, duid, ia->getIAID(), ctx.fwd_dns_update_ = do_fwd;
IOAddress::IPV6_ZERO_ADDRESS(), Lease::TYPE_NA, ctx.rev_dns_update_ = do_rev;
do_fwd, do_rev, orig_ctx.hostname_, false); ctx.currentIA().iaid_ = ia->getIAID();
ctx.currentIA().type_ = Lease::TYPE_NA;
ctx.callout_handle_ = getCalloutHandle(query); ctx.currentIA().ia_rsp_ = ia_rsp;
ctx.query_ = query;
ctx.ia_rsp_ = ia_rsp;
ctx.hwaddr_ = orig_ctx.hwaddr_;
ctx.host_ = orig_ctx.host_;
// Extract the addresses that the client is trying to obtain. // Extract the addresses that the client is trying to obtain.
OptionCollection addrs = ia->getOptions(); OptionCollection addrs = ia->getOptions();
@ -1603,7 +1597,7 @@ Dhcpv6Srv::extendIA_NA(const Pkt6Ptr& query, const Pkt6Ptr& answer,
// this. // this.
continue; continue;
} }
ctx.hints_.push_back(make_pair(iaaddr->getAddress(), 128)); ctx.currentIA().addHint(iaaddr->getAddress());
} }
Lease6Collection leases = alloc_engine_->renewLeases6(ctx); Lease6Collection leases = alloc_engine_->renewLeases6(ctx);
@ -1613,6 +1607,8 @@ Dhcpv6Srv::extendIA_NA(const Pkt6Ptr& query, const Pkt6Ptr& answer,
// - what we actually assigned in leases // - what we actually assigned in leases
// - old leases that are no longer valid in ctx.old_leases_ // - old leases that are no longer valid in ctx.old_leases_
AllocEngine::HintContainer hints = ctx.currentIA().hints_;
// For all leases we have now, add the IAADDR with non-zero lifetimes. // For all leases we have now, add the IAADDR with non-zero lifetimes.
for (Lease6Collection::const_iterator l = leases.begin(); l != leases.end(); ++l) { for (Lease6Collection::const_iterator l = leases.begin(); l != leases.end(); ++l) {
Option6IAAddrPtr iaaddr(new Option6IAAddr(D6O_IAADDR, Option6IAAddrPtr iaaddr(new Option6IAAddr(D6O_IAADDR,
@ -1624,22 +1620,21 @@ Dhcpv6Srv::extendIA_NA(const Pkt6Ptr& query, const Pkt6Ptr& answer,
.arg(ia_rsp->getIAID()); .arg(ia_rsp->getIAID());
// Now remove this address from the hints list. // Now remove this address from the hints list.
AllocEngine::HintType tmp((*l)->addr_, 128); AllocEngine::HintType hint_type((*l)->addr_, 128);
ctx.hints_.erase(std::remove(ctx.hints_.begin(), ctx.hints_.end(), tmp), hints.erase(std::remove(hints.begin(), hints.end(), hint_type),
ctx.hints_.end()); hints.end());
} }
// For the leases that we just retired, send the addresses with 0 lifetimes. // For the leases that we just retired, send the addresses with 0 lifetimes.
for (Lease6Collection::const_iterator l = ctx.old_leases_.begin(); for (Lease6Collection::const_iterator l = ctx.currentIA().old_leases_.begin();
l != ctx.old_leases_.end(); ++l) { l != ctx.currentIA().old_leases_.end(); ++l) {
Option6IAAddrPtr iaaddr(new Option6IAAddr(D6O_IAADDR, Option6IAAddrPtr iaaddr(new Option6IAAddr(D6O_IAADDR,
(*l)->addr_, 0, 0)); (*l)->addr_, 0, 0));
ia_rsp->addOption(iaaddr); ia_rsp->addOption(iaaddr);
// Now remove this address from the hints list. // Now remove this address from the hints list.
AllocEngine::HintType tmp((*l)->addr_, 128); AllocEngine::HintType hint_type((*l)->addr_, 128);
ctx.hints_.erase(std::remove(ctx.hints_.begin(), ctx.hints_.end(), tmp), hints.erase(std::remove(hints.begin(), hints.end(), hint_type), hints.end());
ctx.hints_.end());
// If the new FQDN settings have changed for the lease, we need to // If the new FQDN settings have changed for the lease, we need to
// delete any existing FQDN records for this lease. // delete any existing FQDN records for this lease.
@ -1659,8 +1654,8 @@ Dhcpv6Srv::extendIA_NA(const Pkt6Ptr& query, const Pkt6Ptr& answer,
// Finally, if there are any addresses requested that we haven't dealt with // Finally, if there are any addresses requested that we haven't dealt with
// already, inform the client that he can't have them. // already, inform the client that he can't have them.
for (AllocEngine::HintContainer::const_iterator hint = ctx.hints_.begin(); for (AllocEngine::HintContainer::const_iterator hint = hints.begin();
hint != ctx.hints_.end(); ++hint) { hint != hints.end(); ++hint) {
Option6IAAddrPtr iaaddr(new Option6IAAddr(D6O_IAADDR, Option6IAAddrPtr iaaddr(new Option6IAAddr(D6O_IAADDR,
hint->first, 0, 0)); hint->first, 0, 0));
ia_rsp->addOption(iaaddr); ia_rsp->addOption(iaaddr);
@ -1682,15 +1677,15 @@ Dhcpv6Srv::extendIA_NA(const Pkt6Ptr& query, const Pkt6Ptr& answer,
OptionPtr OptionPtr
Dhcpv6Srv::extendIA_PD(const Pkt6Ptr& query, Dhcpv6Srv::extendIA_PD(const Pkt6Ptr& query,
AllocEngine::ClientContext6& orig_ctx, AllocEngine::ClientContext6& ctx,
boost::shared_ptr<Option6IA> ia) { boost::shared_ptr<Option6IA> ia) {
LOG_DEBUG(lease6_logger, DBG_DHCP6_DETAIL, DHCP6_PROCESS_IA_PD_EXTEND) LOG_DEBUG(lease6_logger, DBG_DHCP6_DETAIL, DHCP6_PROCESS_IA_PD_EXTEND)
.arg(query->getLabel()) .arg(query->getLabel())
.arg(ia->getIAID()); .arg(ia->getIAID());
const Subnet6Ptr& subnet = orig_ctx.subnet_; const Subnet6Ptr& subnet = ctx.subnet_;
const DuidPtr& duid = orig_ctx.duid_; const DuidPtr& duid = ctx.duid_;
// Let's create a IA_PD response and fill it in later // Let's create a IA_PD response and fill it in later
Option6IAPtr ia_rsp(new Option6IA(D6O_IA_PD, ia->getIAID())); Option6IAPtr ia_rsp(new Option6IA(D6O_IA_PD, ia->getIAID()));
@ -1729,16 +1724,10 @@ Dhcpv6Srv::extendIA_PD(const Pkt6Ptr& query,
ia_rsp->setT1(subnet->getT1()); ia_rsp->setT1(subnet->getT1());
ia_rsp->setT2(subnet->getT2()); ia_rsp->setT2(subnet->getT2());
// Create client context for this renewal ctx.createIAContext();
static const IOAddress none("::"); ctx.currentIA().iaid_ = ia->getIAID();
AllocEngine::ClientContext6 ctx(subnet, duid, ia->getIAID(), none, ctx.currentIA().type_ = Lease::TYPE_PD;
Lease::TYPE_PD, false, false, string(""), ctx.currentIA().ia_rsp_ = ia_rsp;
false);
ctx.callout_handle_ = getCalloutHandle(query);
ctx.query_ = query;
ctx.ia_rsp_ = ia_rsp;
ctx.hwaddr_ = orig_ctx.hwaddr_;
ctx.host_ = orig_ctx.host_;
// Extract prefixes that the client is trying to renew. // Extract prefixes that the client is trying to renew.
OptionCollection addrs = ia->getOptions(); OptionCollection addrs = ia->getOptions();
@ -1759,7 +1748,7 @@ Dhcpv6Srv::extendIA_PD(const Pkt6Ptr& query,
} }
// Put the client's prefix into the hints list. // Put the client's prefix into the hints list.
ctx.hints_.push_back(make_pair(prf->getAddress(), prf->getLength())); ctx.currentIA().addHint(prf->getAddress(), prf->getLength());
} }
// Call Allocation Engine and attempt to renew leases. Number of things // Call Allocation Engine and attempt to renew leases. Number of things
@ -1772,6 +1761,8 @@ Dhcpv6Srv::extendIA_PD(const Pkt6Ptr& query,
// in PD context) // in PD context)
Lease6Collection leases = alloc_engine_->renewLeases6(ctx); Lease6Collection leases = alloc_engine_->renewLeases6(ctx);
AllocEngine::HintContainer hints = ctx.currentIA().hints_;
// For all the leases we have now, add the IAPPREFIX with non-zero lifetimes // For all the leases we have now, add the IAPPREFIX with non-zero lifetimes
for (Lease6Collection::const_iterator l = leases.begin(); l != leases.end(); ++l) { for (Lease6Collection::const_iterator l = leases.begin(); l != leases.end(); ++l) {
Option6IAPrefixPtr prf(new Option6IAPrefix(D6O_IAPREFIX, Option6IAPrefixPtr prf(new Option6IAPrefix(D6O_IAPREFIX,
@ -1785,9 +1776,9 @@ Dhcpv6Srv::extendIA_PD(const Pkt6Ptr& query,
.arg(ia->getIAID()); .arg(ia->getIAID());
// Now remove this address from the hints list. // Now remove this address from the hints list.
AllocEngine::HintType tmp((*l)->addr_, (*l)->prefixlen_); AllocEngine::HintType hint_type((*l)->addr_, (*l)->prefixlen_);
ctx.hints_.erase(std::remove(ctx.hints_.begin(), ctx.hints_.end(), tmp), hints.erase(std::remove(hints.begin(), hints.end(), hint_type),
ctx.hints_.end()); hints.end());
} }
/// @todo: Maybe we should iterate over ctx.old_leases_, i.e. the leases /// @todo: Maybe we should iterate over ctx.old_leases_, i.e. the leases
@ -1797,8 +1788,8 @@ Dhcpv6Srv::extendIA_PD(const Pkt6Ptr& query,
// zero lifetimes // zero lifetimes
// Finally, if there are any addresses requested that we haven't dealt with // Finally, if there are any addresses requested that we haven't dealt with
// already, inform the client that he can't have them. // already, inform the client that he can't have them.
for (AllocEngine::HintContainer::const_iterator prefix = ctx.hints_.begin(); for (AllocEngine::HintContainer::const_iterator prefix = hints.begin();
prefix != ctx.hints_.end(); ++prefix) { prefix != hints.end(); ++prefix) {
// Send the prefix with the zero lifetimes only if the prefix // Send the prefix with the zero lifetimes only if the prefix
// contains non-zero value. A zero value indicates that the hint was // contains non-zero value. A zero value indicates that the hint was
// for the prefix length. // for the prefix length.
@ -2238,7 +2229,8 @@ Dhcpv6Srv::processSolicit(const Pkt6Ptr& solicit) {
sanityCheck(solicit, MANDATORY, FORBIDDEN); sanityCheck(solicit, MANDATORY, FORBIDDEN);
// Let's create a simplified client context here. // Let's create a simplified client context here.
AllocEngine::ClientContext6 ctx = createContext(solicit); AllocEngine::ClientContext6 ctx;
initContext(solicit, ctx);
Pkt6Ptr response(new Pkt6(DHCPV6_ADVERTISE, solicit->getTransid())); Pkt6Ptr response(new Pkt6(DHCPV6_ADVERTISE, solicit->getTransid()));
@ -2282,7 +2274,8 @@ Dhcpv6Srv::processRequest(const Pkt6Ptr& request) {
sanityCheck(request, MANDATORY, MANDATORY); sanityCheck(request, MANDATORY, MANDATORY);
// Let's create a simplified client context here. // Let's create a simplified client context here.
AllocEngine::ClientContext6 ctx = createContext(request); AllocEngine::ClientContext6 ctx;
initContext(request, ctx);
Pkt6Ptr reply(new Pkt6(DHCPV6_REPLY, request->getTransid())); Pkt6Ptr reply(new Pkt6(DHCPV6_REPLY, request->getTransid()));
@ -2307,7 +2300,8 @@ Dhcpv6Srv::processRenew(const Pkt6Ptr& renew) {
sanityCheck(renew, MANDATORY, MANDATORY); sanityCheck(renew, MANDATORY, MANDATORY);
// Let's create a simplified client context here. // Let's create a simplified client context here.
AllocEngine::ClientContext6 ctx = createContext(renew); AllocEngine::ClientContext6 ctx;
initContext(renew, ctx);
Pkt6Ptr reply(new Pkt6(DHCPV6_REPLY, renew->getTransid())); Pkt6Ptr reply(new Pkt6(DHCPV6_REPLY, renew->getTransid()));
@ -2331,7 +2325,8 @@ Dhcpv6Srv::processRebind(const Pkt6Ptr& rebind) {
sanityCheck(rebind, MANDATORY, FORBIDDEN); sanityCheck(rebind, MANDATORY, FORBIDDEN);
// Let's create a simplified client context here. // Let's create a simplified client context here.
AllocEngine::ClientContext6 ctx = createContext(rebind); AllocEngine::ClientContext6 ctx;
initContext(rebind, ctx);
Pkt6Ptr reply(new Pkt6(DHCPV6_REPLY, rebind->getTransid())); Pkt6Ptr reply(new Pkt6(DHCPV6_REPLY, rebind->getTransid()));
@ -2355,7 +2350,8 @@ Dhcpv6Srv::processConfirm(const Pkt6Ptr& confirm) {
sanityCheck(confirm, MANDATORY, FORBIDDEN); sanityCheck(confirm, MANDATORY, FORBIDDEN);
// Let's create a simplified client context here. // Let's create a simplified client context here.
AllocEngine::ClientContext6 ctx = createContext(confirm); AllocEngine::ClientContext6 ctx;
initContext(confirm, ctx);
// Get IA_NAs from the Confirm. If there are none, the message is // Get IA_NAs from the Confirm. If there are none, the message is
// invalid and must be discarded. There is nothing more to do. // invalid and must be discarded. There is nothing more to do.
@ -2445,7 +2441,8 @@ Dhcpv6Srv::processRelease(const Pkt6Ptr& release) {
sanityCheck(release, MANDATORY, MANDATORY); sanityCheck(release, MANDATORY, MANDATORY);
// Let's create a simplified client context here. // Let's create a simplified client context here.
AllocEngine::ClientContext6 ctx = createContext(release); AllocEngine::ClientContext6 ctx;
initContext(release, ctx);
Pkt6Ptr reply(new Pkt6(DHCPV6_REPLY, release->getTransid())); Pkt6Ptr reply(new Pkt6(DHCPV6_REPLY, release->getTransid()));
@ -2472,7 +2469,8 @@ Dhcpv6Srv::processDecline(const Pkt6Ptr& decline) {
Pkt6Ptr reply(new Pkt6(DHCPV6_REPLY, decline->getTransid())); Pkt6Ptr reply(new Pkt6(DHCPV6_REPLY, decline->getTransid()));
// Let's create a simplified client context here. // Let's create a simplified client context here.
AllocEngine::ClientContext6 ctx = createContext(decline); AllocEngine::ClientContext6 ctx;
initContext(decline, ctx);
// Copy client options (client-id, also relay information if present) // Copy client options (client-id, also relay information if present)
copyClientOptions(decline, reply); copyClientOptions(decline, reply);
@ -2748,7 +2746,8 @@ Dhcpv6Srv::processInfRequest(const Pkt6Ptr& inf_request) {
sanityCheck(inf_request, OPTIONAL, OPTIONAL); sanityCheck(inf_request, OPTIONAL, OPTIONAL);
// Let's create a simplified client context here. // Let's create a simplified client context here.
AllocEngine::ClientContext6 ctx = createContext(inf_request); AllocEngine::ClientContext6 ctx;
initContext(inf_request, ctx);
// Create a Reply packet, with the same trans-id as the client's. // Create a Reply packet, with the same trans-id as the client's.
Pkt6Ptr reply(new Pkt6(DHCPV6_REPLY, inf_request->getTransid())); Pkt6Ptr reply(new Pkt6(DHCPV6_REPLY, inf_request->getTransid()));

View File

@ -307,13 +307,13 @@ protected:
/// @param answer server's response to the client's message. This /// @param answer server's response to the client's message. This
/// message should contain Client FQDN option being sent by the server /// message should contain Client FQDN option being sent by the server
/// to the client (if the client sent this option to the server). /// to the client (if the client sent this option to the server).
/// @param orig_ctx client context (contains subnet, duid and other parameters) /// @param ctx client context (contains subnet, duid and other parameters)
/// @param ia pointer to client's IA_NA option (client's request) /// @param ia pointer to client's IA_NA option (client's request)
/// ///
/// @return IA_NA option (server's response) /// @return IA_NA option (server's response)
OptionPtr assignIA_NA(const isc::dhcp::Pkt6Ptr& query, OptionPtr assignIA_NA(const isc::dhcp::Pkt6Ptr& query,
const isc::dhcp::Pkt6Ptr& answer, const isc::dhcp::Pkt6Ptr& answer,
AllocEngine::ClientContext6& orig_ctx, AllocEngine::ClientContext6& ctx,
Option6IAPtr ia); Option6IAPtr ia);
/// @brief Processes IA_PD option (and assigns prefixes if necessary). /// @brief Processes IA_PD option (and assigns prefixes if necessary).
@ -326,12 +326,12 @@ protected:
/// ///
/// @param query client's message (typically SOLICIT or REQUEST) /// @param query client's message (typically SOLICIT or REQUEST)
/// @param answer server's response to the client's message. /// @param answer server's response to the client's message.
/// @param orig_ctx client context (contains subnet, duid and other parameters) /// @param ctx client context (contains subnet, duid and other parameters)
/// @param ia pointer to client's IA_PD option (client's request) /// @param ia pointer to client's IA_PD option (client's request)
/// @return IA_PD option (server's response) /// @return IA_PD option (server's response)
OptionPtr assignIA_PD(const Pkt6Ptr& query, OptionPtr assignIA_PD(const Pkt6Ptr& query,
const isc::dhcp::Pkt6Ptr& answer, const isc::dhcp::Pkt6Ptr& answer,
AllocEngine::ClientContext6& orig_ctx, AllocEngine::ClientContext6& ctx,
boost::shared_ptr<Option6IA> ia); boost::shared_ptr<Option6IA> ia);
/// @brief Extends lifetime of the specific IA_NA option. /// @brief Extends lifetime of the specific IA_NA option.
@ -357,12 +357,12 @@ protected:
/// @param answer server's response to the client's message. This /// @param answer server's response to the client's message. This
/// message should contain Client FQDN option being sent by the server /// message should contain Client FQDN option being sent by the server
/// to the client (if the client sent this option to the server). /// to the client (if the client sent this option to the server).
/// @param orig_ctx client context (contains subnet, duid and other parameters) /// @param ctx client context (contains subnet, duid and other parameters)
/// @param ia IA_NA option which carries address for which lease lifetime /// @param ia IA_NA option which carries address for which lease lifetime
/// will be extended. /// will be extended.
/// @return IA_NA option (server's response) /// @return IA_NA option (server's response)
OptionPtr extendIA_NA(const Pkt6Ptr& query, const Pkt6Ptr& answer, OptionPtr extendIA_NA(const Pkt6Ptr& query, const Pkt6Ptr& answer,
AllocEngine::ClientContext6& orig_ctx, AllocEngine::ClientContext6& ctx,
Option6IAPtr ia); Option6IAPtr ia);
/// @brief Extends lifetime of the prefix. /// @brief Extends lifetime of the prefix.
@ -377,14 +377,14 @@ protected:
/// (see RFC3633, section 12.2. for details). /// (see RFC3633, section 12.2. for details).
/// ///
/// @param query client's message /// @param query client's message
/// @param orig_ctx client context (contains subnet, duid and other parameters) /// @param ctx client context (contains subnet, duid and other parameters)
/// @param ia IA_PD option that is being renewed /// @param ia IA_PD option that is being renewed
/// @return IA_PD option (server's response) /// @return IA_PD option (server's response)
/// @throw DHCPv6DiscardMessageError when the message being processed should /// @throw DHCPv6DiscardMessageError when the message being processed should
/// be discarded by the server, i.e. there is no binding for the client doing /// be discarded by the server, i.e. there is no binding for the client doing
/// Rebind. /// Rebind.
OptionPtr extendIA_PD(const Pkt6Ptr& query, OptionPtr extendIA_PD(const Pkt6Ptr& query,
AllocEngine::ClientContext6& orig_ctx, AllocEngine::ClientContext6& ctx,
Option6IAPtr ia); Option6IAPtr ia);
/// @brief Releases specific IA_NA option /// @brief Releases specific IA_NA option
@ -656,9 +656,9 @@ protected:
/// - there is no such option provided by the server) /// - there is no such option provided by the server)
void processRSOO(const Pkt6Ptr& query, const Pkt6Ptr& rsp); void processRSOO(const Pkt6Ptr& query, const Pkt6Ptr& rsp);
/// @brief Creates client context for specified packet /// @brief Initializes client context for specified packet
/// ///
/// Instantiates the ClientContext6 and then: /// This method:
/// - Performs the subnet selection and stores the result in context /// - Performs the subnet selection and stores the result in context
/// - Extracts the duid from the packet and saves it to the context /// - Extracts the duid from the packet and saves it to the context
/// - Extracts the hardware address from the packet and saves it to /// - Extracts the hardware address from the packet and saves it to
@ -666,8 +666,9 @@ protected:
/// - Performs host reservation lookup and stores the result in the /// - Performs host reservation lookup and stores the result in the
/// context /// context
/// ///
/// @return client context /// @param pkt pointer to a packet for which context will be created.
AllocEngine::ClientContext6 createContext(const Pkt6Ptr& pkt); /// @param [out] ctx reference to context object to be initialized.
void initContext(const Pkt6Ptr& pkt, AllocEngine::ClientContext6& ctx);
/// @brief this is a prefix added to the contend of vendor-class option /// @brief this is a prefix added to the contend of vendor-class option
/// ///

View File

@ -131,7 +131,7 @@ public:
using Dhcpv6Srv::shutdown_; using Dhcpv6Srv::shutdown_;
using Dhcpv6Srv::name_change_reqs_; using Dhcpv6Srv::name_change_reqs_;
using Dhcpv6Srv::VENDOR_CLASS_PREFIX; using Dhcpv6Srv::VENDOR_CLASS_PREFIX;
using Dhcpv6Srv::createContext; using Dhcpv6Srv::initContext;
/// @brief packets we pretend to receive /// @brief packets we pretend to receive
/// ///

View File

@ -35,6 +35,7 @@
#include <vector> #include <vector>
#include <stdint.h> #include <stdint.h>
#include <string.h> #include <string.h>
#include <utility>
using namespace isc::asiolink; using namespace isc::asiolink;
using namespace isc::dhcp; using namespace isc::dhcp;
@ -331,31 +332,24 @@ AllocEngine::findReservationInternal(ContextType& ctx,
// ########################################################################## // ##########################################################################
AllocEngine::ClientContext6::ClientContext6() AllocEngine::ClientContext6::ClientContext6()
: subnet_(), duid_(), iaid_(0), type_(Lease::TYPE_NA), hwaddr_(), : query_(), fake_allocation_(false), subnet_(), duid_(),
hints_(), fwd_dns_update_(false), rev_dns_update_(false), hostname_(""), hwaddr_(), host_identifiers_(), host_(), fwd_dns_update_(false),
callout_handle_(), fake_allocation_(false), old_leases_(), host_(), rev_dns_update_(false), hostname_(), callout_handle_(),
query_(), ia_rsp_(), host_identifiers_() { ias_() {
} }
AllocEngine::ClientContext6::ClientContext6(const Subnet6Ptr& subnet, const DuidPtr& duid, AllocEngine::ClientContext6::ClientContext6(const Subnet6Ptr& subnet,
const uint32_t iaid, const DuidPtr& duid,
const isc::asiolink::IOAddress& hint, const bool fwd_dns,
const Lease::Type type, const bool fwd_dns,
const bool rev_dns, const bool rev_dns,
const std::string& hostname, const std::string& hostname,
const bool fake_allocation): const bool fake_allocation,
subnet_(subnet), duid_(duid), iaid_(iaid), type_(type), hwaddr_(), const Pkt6Ptr& query,
hints_(), fwd_dns_update_(fwd_dns), rev_dns_update_(rev_dns), const CalloutHandlePtr& callout_handle)
hostname_(hostname), fake_allocation_(fake_allocation), : query_(query), fake_allocation_(fake_allocation), subnet_(subnet),
old_leases_(), host_(), query_(), ia_rsp_(), host_identifiers_() { duid_(duid), hwaddr_(), host_identifiers_(), host_(),
fwd_dns_update_(fwd_dns), rev_dns_update_(rev_dns),
static asiolink::IOAddress any("::"); hostname_(hostname), callout_handle_(callout_handle), ias_() {
if (hint != any) {
hints_.push_back(std::make_pair(hint, 128));
}
// callout_handle, host pointers initiated to NULL by their
// respective constructors.
// Initialize host identifiers. // Initialize host identifiers.
if (duid) { if (duid) {
@ -363,6 +357,17 @@ AllocEngine::ClientContext6::ClientContext6(const Subnet6Ptr& subnet, const Duid
} }
} }
AllocEngine::ClientContext6::IAContext::IAContext()
: iaid_(0), type_(Lease::TYPE_NA), hints_(), old_leases_(),
changed_leases_(), ia_rsp_() {
}
void
AllocEngine::ClientContext6::
IAContext::addHint(const asiolink::IOAddress& prefix,
const uint8_t prefix_len) {
hints_.push_back(std::make_pair(prefix, prefix_len));
}
void AllocEngine::findReservation(ClientContext6& ctx) { void AllocEngine::findReservation(ClientContext6& ctx) {
findReservationInternal(ctx, boost::bind(&HostMgr::get6, findReservationInternal(ctx, boost::bind(&HostMgr::get6,
@ -384,7 +389,9 @@ AllocEngine::allocateLeases6(ClientContext6& ctx) {
// Check if there are existing leases for that subnet/duid/iaid // Check if there are existing leases for that subnet/duid/iaid
// combination. // combination.
Lease6Collection leases = Lease6Collection leases =
LeaseMgrFactory::instance().getLeases6(ctx.type_, *ctx.duid_, ctx.iaid_, LeaseMgrFactory::instance().getLeases6(ctx.currentIA().type_,
*ctx.duid_,
ctx.currentIA().iaid_,
ctx.subnet_->getID()); ctx.subnet_->getID());
// Now do the checks: // Now do the checks:
@ -544,11 +551,11 @@ AllocEngine::allocateLeases6(ClientContext6& ctx) {
Lease6Collection Lease6Collection
AllocEngine::allocateUnreservedLeases6(ClientContext6& ctx) { AllocEngine::allocateUnreservedLeases6(ClientContext6& ctx) {
AllocatorPtr allocator = getAllocator(ctx.type_); AllocatorPtr allocator = getAllocator(ctx.currentIA().type_);
if (!allocator) { if (!allocator) {
isc_throw(InvalidOperation, "No allocator specified for " isc_throw(InvalidOperation, "No allocator specified for "
<< Lease6::typeToText(ctx.type_)); << Lease6::typeToText(ctx.currentIA().type_));
} }
// Check which host reservation mode is supported in this subnet. // Check which host reservation mode is supported in this subnet.
@ -557,19 +564,20 @@ AllocEngine::allocateUnreservedLeases6(ClientContext6& ctx) {
Lease6Collection leases; Lease6Collection leases;
IOAddress hint = IOAddress::IPV6_ZERO_ADDRESS(); IOAddress hint = IOAddress::IPV6_ZERO_ADDRESS();
if (!ctx.hints_.empty()) { if (!ctx.currentIA().hints_.empty()) {
/// @todo: We support only one hint for now /// @todo: We support only one hint for now
hint = ctx.hints_[0].first; hint = ctx.currentIA().hints_[0].first;
} }
// check if the hint is in pool and is available // check if the hint is in pool and is available
// This is equivalent of subnet->inPool(hint), but returns the pool // This is equivalent of subnet->inPool(hint), but returns the pool
Pool6Ptr pool = boost::dynamic_pointer_cast< Pool6Ptr pool = boost::dynamic_pointer_cast<
Pool6>(ctx.subnet_->getPool(ctx.type_, hint, false)); Pool6>(ctx.subnet_->getPool(ctx.currentIA().type_, hint, false));
if (pool) { if (pool) {
/// @todo: We support only one hint for now /// @todo: We support only one hint for now
Lease6Ptr lease = LeaseMgrFactory::instance().getLease6(ctx.type_, hint); Lease6Ptr lease = LeaseMgrFactory::instance().getLease6(ctx.currentIA().type_,
hint);
if (!lease) { if (!lease) {
// In-pool reservations: Check if this address is reserved for someone // In-pool reservations: Check if this address is reserved for someone
@ -623,7 +631,7 @@ AllocEngine::allocateUnreservedLeases6(ClientContext6& ctx) {
// Copy an existing, expired lease so as it can be returned // Copy an existing, expired lease so as it can be returned
// to the caller. // to the caller.
Lease6Ptr old_lease(new Lease6(*lease)); Lease6Ptr old_lease(new Lease6(*lease));
ctx.old_leases_.push_back(old_lease); ctx.currentIA().old_leases_.push_back(old_lease);
/// We found a lease and it is expired, so we can reuse it /// We found a lease and it is expired, so we can reuse it
lease = reuseExpiredLease(lease, ctx, pool->getLength()); lease = reuseExpiredLease(lease, ctx, pool->getLength());
@ -649,7 +657,7 @@ AllocEngine::allocateUnreservedLeases6(ClientContext6& ctx) {
// - we find an address for which the lease has expired // - we find an address for which the lease has expired
// - we exhaust number of tries // - we exhaust number of tries
uint64_t max_attempts = (attempts_ > 0 ? attempts_ : uint64_t max_attempts = (attempts_ > 0 ? attempts_ :
ctx.subnet_->getPoolCapacity(ctx.type_)); ctx.subnet_->getPoolCapacity(ctx.currentIA().type_));
for (uint64_t i = 0; i < max_attempts; ++i) for (uint64_t i = 0; i < max_attempts; ++i)
{ {
IOAddress candidate = allocator->pickAddress(ctx.subnet_, ctx.duid_, hint); IOAddress candidate = allocator->pickAddress(ctx.subnet_, ctx.duid_, hint);
@ -667,14 +675,14 @@ AllocEngine::allocateUnreservedLeases6(ClientContext6& ctx) {
// The first step is to find out prefix length. It is 128 for // The first step is to find out prefix length. It is 128 for
// non-PD leases. // non-PD leases.
uint8_t prefix_len = 128; uint8_t prefix_len = 128;
if (ctx.type_ == Lease::TYPE_PD) { if (ctx.currentIA().type_ == Lease::TYPE_PD) {
Pool6Ptr pool = boost::dynamic_pointer_cast<Pool6>( Pool6Ptr pool = boost::dynamic_pointer_cast<Pool6>(
ctx.subnet_->getPool(ctx.type_, candidate, false)); ctx.subnet_->getPool(ctx.currentIA().type_, candidate, false));
/// @todo: verify that the pool is non-null /// @todo: verify that the pool is non-null
prefix_len = pool->getLength(); prefix_len = pool->getLength();
} }
Lease6Ptr existing = LeaseMgrFactory::instance().getLease6(ctx.type_, Lease6Ptr existing = LeaseMgrFactory::instance().getLease6(ctx.currentIA().type_,
candidate); candidate);
if (!existing) { if (!existing) {
@ -685,7 +693,7 @@ AllocEngine::allocateUnreservedLeases6(ClientContext6& ctx) {
if (lease) { if (lease) {
// We are allocating a new lease (not renewing). So, the // We are allocating a new lease (not renewing). So, the
// old lease should be NULL. // old lease should be NULL.
ctx.old_leases_.clear(); ctx.currentIA().old_leases_.clear();
leases.push_back(lease); leases.push_back(lease);
return (leases); return (leases);
@ -699,7 +707,7 @@ AllocEngine::allocateUnreservedLeases6(ClientContext6& ctx) {
// Copy an existing, expired lease so as it can be returned // Copy an existing, expired lease so as it can be returned
// to the caller. // to the caller.
Lease6Ptr old_lease(new Lease6(*existing)); Lease6Ptr old_lease(new Lease6(*existing));
ctx.old_leases_.push_back(old_lease); ctx.currentIA().old_leases_.push_back(old_lease);
existing = reuseExpiredLease(existing, existing = reuseExpiredLease(existing,
ctx, ctx,
@ -723,7 +731,8 @@ AllocEngine::allocateUnreservedLeases6(ClientContext6& ctx) {
} }
void void
AllocEngine::allocateReservedLeases6(ClientContext6& ctx, Lease6Collection& existing_leases) { AllocEngine::allocateReservedLeases6(ClientContext6& ctx,
Lease6Collection& existing_leases) {
// If there are no reservations or the reservation is v4, there's nothing to do. // If there are no reservations or the reservation is v4, there's nothing to do.
if (!ctx.host_ || !ctx.host_->hasIPv6Reservation()) { if (!ctx.host_ || !ctx.host_->hasIPv6Reservation()) {
@ -734,7 +743,8 @@ AllocEngine::allocateReservedLeases6(ClientContext6& ctx, Lease6Collection& exis
} }
// Let's convert this from Lease::Type to IPv6Reserv::Type // Let's convert this from Lease::Type to IPv6Reserv::Type
IPv6Resrv::Type type = ctx.type_ == Lease::TYPE_NA ? IPv6Resrv::TYPE_NA : IPv6Resrv::TYPE_PD; IPv6Resrv::Type type = ctx.currentIA().type_ == Lease::TYPE_NA ?
IPv6Resrv::TYPE_NA : IPv6Resrv::TYPE_PD;
// Get the IPv6 reservations of specified type. // Get the IPv6 reservations of specified type.
const IPv6ResrvRange& reservs = ctx.host_->getIPv6Reservations(type); const IPv6ResrvRange& reservs = ctx.host_->getIPv6Reservations(type);
@ -767,14 +777,15 @@ AllocEngine::allocateReservedLeases6(ClientContext6& ctx, Lease6Collection& exis
// If there's a lease for this address, let's not create it. // If there's a lease for this address, let's not create it.
// It doesn't matter whether it is for this client or for someone else. // It doesn't matter whether it is for this client or for someone else.
if (!LeaseMgrFactory::instance().getLease6(ctx.type_, addr)) { if (!LeaseMgrFactory::instance().getLease6(ctx.currentIA().type_,
addr)) {
// Ok, let's create a new lease... // Ok, let's create a new lease...
Lease6Ptr lease = createLease6(ctx, addr, prefix_len); Lease6Ptr lease = createLease6(ctx, addr, prefix_len);
// ... and add it to the existing leases list. // ... and add it to the existing leases list.
existing_leases.push_back(lease); existing_leases.push_back(lease);
if (ctx.type_ == Lease::TYPE_NA) { if (ctx.currentIA().type_ == Lease::TYPE_NA) {
LOG_INFO(alloc_engine_logger, ALLOC_ENGINE_V6_HR_ADDR_GRANTED) LOG_INFO(alloc_engine_logger, ALLOC_ENGINE_V6_HR_ADDR_GRANTED)
.arg(addr.toText()) .arg(addr.toText())
.arg(ctx.query_->getLabel()); .arg(ctx.query_->getLabel());
@ -829,7 +840,7 @@ AllocEngine::removeNonmatchingReservedLeases6(ClientContext6& ctx,
// Ok, we have a problem. This host has a lease that is reserved // Ok, we have a problem. This host has a lease that is reserved
// for someone else. We need to recover from this. // for someone else. We need to recover from this.
if (ctx.type_ == Lease::TYPE_NA) { if (ctx.currentIA().type_ == Lease::TYPE_NA) {
LOG_INFO(alloc_engine_logger, ALLOC_ENGINE_V6_REVOKED_ADDR_LEASE) LOG_INFO(alloc_engine_logger, ALLOC_ENGINE_V6_REVOKED_ADDR_LEASE)
.arg((*candidate)->addr_.toText()).arg(ctx.duid_->toText()) .arg((*candidate)->addr_.toText()).arg(ctx.duid_->toText())
.arg(host->getIdentifierAsText()); .arg(host->getIdentifierAsText());
@ -850,8 +861,8 @@ AllocEngine::removeNonmatchingReservedLeases6(ClientContext6& ctx,
// Need to decrease statistic for assigned addresses. // Need to decrease statistic for assigned addresses.
StatsMgr::instance().addValue( StatsMgr::instance().addValue(
StatsMgr::generateName("subnet", ctx.subnet_->getID(), StatsMgr::generateName("subnet", ctx.subnet_->getID(),
ctx.type_ == Lease::TYPE_NA ? "assigned-nas" : ctx.currentIA().type_ == Lease::TYPE_NA ?
"assigned-pds"), "assigned-nas" : "assigned-pds"),
static_cast<int64_t>(-1)); static_cast<int64_t>(-1));
// In principle, we could trigger a hook here, but we will do this // In principle, we could trigger a hook here, but we will do this
@ -860,7 +871,7 @@ AllocEngine::removeNonmatchingReservedLeases6(ClientContext6& ctx,
// should not interfere with it. // should not interfere with it.
// Add this to the list of removed leases. // Add this to the list of removed leases.
ctx.old_leases_.push_back(*candidate); ctx.currentIA().old_leases_.push_back(*candidate);
// Let's remove this candidate from existing leases // Let's remove this candidate from existing leases
removeLeases(existing_leases, (*candidate)->addr_); removeLeases(existing_leases, (*candidate)->addr_);
@ -902,7 +913,8 @@ AllocEngine::removeNonreservedLeases6(ClientContext6& ctx,
// leases for deletion, by setting appropriate pointers to NULL. // leases for deletion, by setting appropriate pointers to NULL.
for (Lease6Collection::iterator lease = existing_leases.begin(); for (Lease6Collection::iterator lease = existing_leases.begin();
lease != existing_leases.end(); ++lease) { lease != existing_leases.end(); ++lease) {
IPv6Resrv resv(ctx.type_ == Lease::TYPE_NA ? IPv6Resrv::TYPE_NA : IPv6Resrv::TYPE_PD, IPv6Resrv resv(ctx.currentIA().type_ == Lease::TYPE_NA ?
IPv6Resrv::TYPE_NA : IPv6Resrv::TYPE_PD,
(*lease)->addr_, (*lease)->prefixlen_); (*lease)->addr_, (*lease)->prefixlen_);
if (!ctx.host_->hasReservation(resv)) { if (!ctx.host_->hasReservation(resv)) {
// We have reservations, but not for this lease. Release it. // We have reservations, but not for this lease. Release it.
@ -916,14 +928,14 @@ AllocEngine::removeNonreservedLeases6(ClientContext6& ctx,
// Need to decrease statistic for assigned addresses. // Need to decrease statistic for assigned addresses.
StatsMgr::instance().addValue( StatsMgr::instance().addValue(
StatsMgr::generateName("subnet", ctx.subnet_->getID(), StatsMgr::generateName("subnet", ctx.subnet_->getID(),
ctx.type_ == Lease::TYPE_NA ? "assigned-nas" : ctx.currentIA().type_ == Lease::TYPE_NA ?
"assigned-pds"), "assigned-nas" : "assigned-pds"),
static_cast<int64_t>(-1)); static_cast<int64_t>(-1));
/// @todo: Probably trigger a hook here /// @todo: Probably trigger a hook here
// Add this to the list of removed leases. // Add this to the list of removed leases.
ctx.old_leases_.push_back(*lease); ctx.currentIA().old_leases_.push_back(*lease);
// Set this pointer to NULL. The pointer is still valid. We're just // Set this pointer to NULL. The pointer is still valid. We're just
// setting the Lease6Ptr to NULL value. We'll remove all NULL // setting the Lease6Ptr to NULL value. We'll remove all NULL
@ -964,7 +976,7 @@ AllocEngine::reuseExpiredLease(Lease6Ptr& expired, ClientContext6& ctx,
} }
// address, lease type and prefixlen (0) stay the same // address, lease type and prefixlen (0) stay the same
expired->iaid_ = ctx.iaid_; expired->iaid_ = ctx.currentIA().iaid_;
expired->duid_ = ctx.duid_; expired->duid_ = ctx.duid_;
expired->preferred_lft_ = ctx.subnet_->getPreferred(); expired->preferred_lft_ = ctx.subnet_->getPreferred();
expired->valid_lft_ = ctx.subnet_->getValid(); expired->valid_lft_ = ctx.subnet_->getValid();
@ -1039,14 +1051,15 @@ Lease6Ptr AllocEngine::createLease6(ClientContext6& ctx,
const IOAddress& addr, const IOAddress& addr,
uint8_t prefix_len) { uint8_t prefix_len) {
if (ctx.type_ != Lease::TYPE_PD) { if (ctx.currentIA().type_ != Lease::TYPE_PD) {
prefix_len = 128; // non-PD lease types must be always /128 prefix_len = 128; // non-PD lease types must be always /128
} }
Lease6Ptr lease(new Lease6(ctx.type_, addr, ctx.duid_, ctx.iaid_, Lease6Ptr lease(new Lease6(ctx.currentIA().type_, addr, ctx.duid_,
ctx.subnet_->getPreferred(), ctx.subnet_->getValid(), ctx.currentIA().iaid_, ctx.subnet_->getPreferred(),
ctx.subnet_->getT1(), ctx.subnet_->getT2(), ctx.subnet_->getValid(), ctx.subnet_->getT1(),
ctx.subnet_->getID(), ctx.hwaddr_, prefix_len)); ctx.subnet_->getT2(), ctx.subnet_->getID(),
ctx.hwaddr_, prefix_len));
lease->fqdn_fwd_ = ctx.fwd_dns_update_; lease->fqdn_fwd_ = ctx.fwd_dns_update_;
lease->fqdn_rev_ = ctx.rev_dns_update_; lease->fqdn_rev_ = ctx.rev_dns_update_;
@ -1094,11 +1107,11 @@ Lease6Ptr AllocEngine::createLease6(ClientContext6& ctx,
if (status) { if (status) {
// The lease insertion succeeded - if the lease is in the // The lease insertion succeeded - if the lease is in the
// current subnet lets bump up the statistic. // current subnet lets bump up the statistic.
if (ctx.subnet_->inPool(ctx.type_, addr)) { if (ctx.subnet_->inPool(ctx.currentIA().type_, addr)) {
StatsMgr::instance().addValue( StatsMgr::instance().addValue(
StatsMgr::generateName("subnet", ctx.subnet_->getID(), StatsMgr::generateName("subnet", ctx.subnet_->getID(),
ctx.type_ == Lease::TYPE_NA ? "assigned-nas" : ctx.currentIA().type_ == Lease::TYPE_NA ?
"assigned-pds"), "assigned-nas" : "assigned-pds"),
static_cast<int64_t>(1)); static_cast<int64_t>(1));
} }
@ -1138,7 +1151,8 @@ AllocEngine::renewLeases6(ClientContext6& ctx) {
// Check if there are any leases for this client. // Check if there are any leases for this client.
Lease6Collection leases = LeaseMgrFactory::instance() Lease6Collection leases = LeaseMgrFactory::instance()
.getLeases6(ctx.type_, *ctx.duid_, ctx.iaid_, ctx.subnet_->getID()); .getLeases6(ctx.currentIA().type_, *ctx.duid_,
ctx.currentIA().iaid_, ctx.subnet_->getID());
if (!leases.empty()) { if (!leases.empty()) {
LOG_DEBUG(alloc_engine_logger, ALLOC_ENGINE_DBG_TRACE, LOG_DEBUG(alloc_engine_logger, ALLOC_ENGINE_DBG_TRACE,
@ -1226,7 +1240,7 @@ AllocEngine::extendLease6(ClientContext6& ctx, Lease6Ptr lease) {
static_cast<int64_t>(-1)); static_cast<int64_t>(-1));
// Add it to the removed leases list. // Add it to the removed leases list.
ctx.old_leases_.push_back(lease); ctx.currentIA().old_leases_.push_back(lease);
return; return;
} }
@ -1275,9 +1289,9 @@ AllocEngine::extendLease6(ClientContext6& ctx, Lease6Ptr lease) {
// Pass the IA option to be sent in response // Pass the IA option to be sent in response
if (lease->type_ == Lease::TYPE_NA) { if (lease->type_ == Lease::TYPE_NA) {
callout_handle->setArgument("ia_na", ctx.ia_rsp_); callout_handle->setArgument("ia_na", ctx.currentIA().ia_rsp_);
} else { } else {
callout_handle->setArgument("ia_pd", ctx.ia_rsp_); callout_handle->setArgument("ia_pd", ctx.currentIA().ia_rsp_);
} }
// Call all installed callouts // Call all installed callouts
@ -1334,7 +1348,7 @@ AllocEngine::updateLeaseData(ClientContext6& ctx, const Lease6Collection& leases
(lease->fqdn_fwd_ != (*lease_it)->fqdn_fwd_) || (lease->fqdn_fwd_ != (*lease_it)->fqdn_fwd_) ||
(lease->fqdn_rev_ != (*lease_it)->fqdn_rev_) || (lease->fqdn_rev_ != (*lease_it)->fqdn_rev_) ||
(lease->hostname_ != (*lease_it)->hostname_))) { (lease->hostname_ != (*lease_it)->hostname_))) {
ctx.changed_leases_.push_back(*lease_it); ctx.currentIA().changed_leases_.push_back(*lease_it);
LeaseMgrFactory::instance().updateLease6(lease); LeaseMgrFactory::instance().updateLease6(lease);
} }
updated_leases.push_back(lease); updated_leases.push_back(lease);

View File

@ -281,27 +281,40 @@ public:
/// that the big advantage of using the context structure to pass /// that the big advantage of using the context structure to pass
/// information to the allocation engine methods is that adding /// information to the allocation engine methods is that adding
/// new information doesn't modify the API of the allocation engine. /// new information doesn't modify the API of the allocation engine.
struct ClientContext6 { struct ClientContext6 : public boost::noncopyable {
/// @name Parameters pertaining to DHCPv6 message
//@{
/// @brief A pointer to the client's message
///
/// This is used exclusively for hook purposes.
Pkt6Ptr query_;
/// @brief Indicates if this is a real or fake allocation.
///
/// The real allocation is when the allocation engine is supposed
/// to make an update in a lease database: create new lease, or
/// update existing lease.
bool fake_allocation_;
/// @brief Subnet selected for the client by the server. /// @brief Subnet selected for the client by the server.
Subnet6Ptr subnet_; Subnet6Ptr subnet_;
/// @brief Client identifier /// @brief Client identifier
DuidPtr duid_; DuidPtr duid_;
/// @brief iaid IAID field from IA_NA or IA_PD that is being processed
uint32_t iaid_;
/// @brief Lease type (IA or PD)
Lease::Type type_;
/// @brief Hardware/MAC address (if available, may be NULL) /// @brief Hardware/MAC address (if available, may be NULL)
HWAddrPtr hwaddr_; HWAddrPtr hwaddr_;
/// @brief client's hints /// @brief A list holding host identifiers extracted from a message
/// received by the server.
IdentifierList host_identifiers_;
/// @brief A pointer to the object identifying host reservations.
/// ///
/// There will typically be just one address, but the protocol allows /// May be NULL if there are no reservations.
/// more than one address or prefix for each IA container. ConstHostPtr host_;
HintContainer hints_;
/// @brief A boolean value which indicates that server takes /// @brief A boolean value which indicates that server takes
/// responsibility for the forward DNS Update for this lease /// responsibility for the forward DNS Update for this lease
@ -322,45 +335,60 @@ public:
/// @brief Callout handle associated with the client's message. /// @brief Callout handle associated with the client's message.
hooks::CalloutHandlePtr callout_handle_; hooks::CalloutHandlePtr callout_handle_;
/// @brief Indicates if this is a real or fake allocation. //@}
///
/// The real allocation is when the allocation engine is supposed
/// to make an update in a lease database: create new lease, or
/// update existing lease.
bool fake_allocation_;
/// @brief A pointer to any old leases that the client had before update /// @brief Parameters pertaining to individual IAs.
/// but are no longer valid after the update/allocation. struct IAContext {
///
/// This collection is typically empty, except cases when we are doing
/// address reassignment, e.g. because there is a host reservation that
/// gives this address to someone else, so we had to return the address,
/// and give a new one to this client.
Lease6Collection old_leases_;
/// @brief A pointer to any leases that have changed FQDN information. /// @brief iaid IAID field from IA_NA or IA_PD that is being
/// /// processed
/// This list may contain old versions of the leases that are still uint32_t iaid_;
/// valid. In particular, it will contain a lease if the client's
/// FQDN has changed.
Lease6Collection changed_leases_;
/// @brief A pointer to the object identifying host reservations. /// @brief Lease type (IA or PD)
/// Lease::Type type_;
/// May be NULL if there are no reservations.
ConstHostPtr host_;
/// @brief A pointer to the client's message /// @brief client's hints
/// ///
/// This is used exclusively for hook purposes. /// There will typically be just one address, but the protocol
Pkt6Ptr query_; /// allows more than one address or prefix for each IA container.
HintContainer hints_;
/// @brief A pointer to the IA_NA/IA_PD option to be sent in response /// @brief A pointer to any old leases that the client had before
Option6IAPtr ia_rsp_; /// update but are no longer valid after the update/allocation.
///
/// This collection is typically empty, except cases when we are
/// doing address reassignment, e.g. because there is a host
/// reservation that gives this address to someone else, so we had
/// to return the address, and give a new one to this client.
Lease6Collection old_leases_;
/// @brief A list holding host identifiers extracted from a message /// @brief A pointer to any leases that have changed FQDN
/// received by the server. /// information.
IdentifierList host_identifiers_; ///
/// This list may contain old versions of the leases that are still
/// valid. In particular, it will contain a lease if the client's
/// FQDN has changed.
Lease6Collection changed_leases_;
/// @brief A pointer to the IA_NA/IA_PD option to be sent in
/// response
Option6IAPtr ia_rsp_;
/// @brief Default constructor.
///
/// Initializes @ref type_ to @c Lease::TYPE_NA and @ref iaid_ to 0.
IAContext();
/// @brief Convenience method adding new hint.
///
/// @param prefix Prefix or address.
/// @param prefix_len Prefix length. Default is 128 for addresses.
void addHint(const asiolink::IOAddress& prefix,
const uint8_t prefix_len = 128);
};
std::vector<IAContext> ias_;
/// @brief Conveniece function adding host identifier into /// @brief Conveniece function adding host identifier into
/// @ref host_identifiers_ list. /// @ref host_identifiers_ list.
@ -372,6 +400,17 @@ public:
host_identifiers_.push_back(IdentifierPair(id_type, identifier)); host_identifiers_.push_back(IdentifierPair(id_type, identifier));
} }
IAContext& currentIA() {
if (ias_.empty()) {
createIAContext();
}
return (ias_.back());
}
void createIAContext() {
ias_.push_back(IAContext());
};
/// @brief Default constructor. /// @brief Default constructor.
ClientContext6(); ClientContext6();
@ -383,9 +422,6 @@ public:
/// ///
/// @param subnet subnet the allocation should come from /// @param subnet subnet the allocation should come from
/// @param duid Client's DUID /// @param duid Client's DUID
/// @param iaid iaid field from the IA_NA container that client sent
/// @param hint a hint that the client provided
/// @param type lease type (IA, TA or PD)
/// @param fwd_dns A boolean value which indicates that server takes /// @param fwd_dns A boolean value which indicates that server takes
/// responsibility for the forward DNS Update for this lease /// responsibility for the forward DNS Update for this lease
/// (if true). /// (if true).
@ -393,13 +429,18 @@ public:
/// responsibility for the reverse DNS Update for this lease /// responsibility for the reverse DNS Update for this lease
/// (if true). /// (if true).
/// @param hostname A fully qualified domain-name of the client. /// @param hostname A fully qualified domain-name of the client.
/// @param fake_allocation is this real i.e. REQUEST (false) or just picking /// @param fake_allocation is this real i.e. REQUEST (false) or just
/// an address for SOLICIT that is not really allocated (true) /// picking an address for SOLICIT that is not really allocated
/// (true)
/// @param query Pointer to the DHCPv6 message being processed.
/// @param callout_handle Callout handle associated with a client's
/// message
ClientContext6(const Subnet6Ptr& subnet, const DuidPtr& duid, ClientContext6(const Subnet6Ptr& subnet, const DuidPtr& duid,
const uint32_t iaid, const isc::asiolink::IOAddress& hint, const bool fwd_dns, const bool rev_dns,
const Lease::Type type, const bool fwd_dns, const bool const std::string& hostname, const bool fake_allocation,
rev_dns, const std::string& hostname, const bool const Pkt6Ptr& query,
fake_allocation); const hooks::CalloutHandlePtr& callout_handle =
hooks::CalloutHandlePtr());
}; };
/// @brief Allocates IPv6 leases for a given IA container /// @brief Allocates IPv6 leases for a given IA container

View File

@ -147,16 +147,17 @@ TEST_F(AllocEngine6Test, allocateAddress6Nulls) {
// Allocations without subnet are not allowed // Allocations without subnet are not allowed
Lease6Ptr lease; Lease6Ptr lease;
AllocEngine::ClientContext6 ctx1(Subnet6Ptr(), duid_, iaid_, IOAddress("::"), AllocEngine::ClientContext6 ctx1(Subnet6Ptr(), duid_, false, false, "", false,
Lease::TYPE_NA, false, false, "", false); Pkt6Ptr(new Pkt6(DHCPV6_REQUEST, 1234)));
ctx1.query_.reset(new Pkt6(DHCPV6_REQUEST, 1234)); ctx1.currentIA().iaid_ = iaid_;
EXPECT_NO_THROW(lease = expectOneLease(engine->allocateLeases6(ctx1))); EXPECT_NO_THROW(lease = expectOneLease(engine->allocateLeases6(ctx1)));
ASSERT_FALSE(lease); ASSERT_FALSE(lease);
// Allocations without DUID are not allowed either // Allocations without DUID are not allowed either
AllocEngine::ClientContext6 ctx2(subnet_, DuidPtr(), iaid_, IOAddress("::"), AllocEngine::ClientContext6 ctx2(subnet_, DuidPtr(), false, false, "", false,
Lease::TYPE_NA, false, false, "", false); Pkt6Ptr(new Pkt6(DHCPV6_REQUEST, 1234)));
ctx2.query_.reset(new Pkt6(DHCPV6_REQUEST, 1234)); ctx2.currentIA().iaid_ = iaid_;
EXPECT_NO_THROW(lease = expectOneLease(engine->allocateLeases6(ctx2))); EXPECT_NO_THROW(lease = expectOneLease(engine->allocateLeases6(ctx2)));
ASSERT_FALSE(lease); ASSERT_FALSE(lease);
} }
@ -403,10 +404,10 @@ TEST_F(AllocEngine6Test, smallPool6) {
initFqdn("myhost.example.com", true, true); initFqdn("myhost.example.com", true, true);
Lease6Ptr lease; Lease6Ptr lease;
AllocEngine::ClientContext6 ctx(subnet_, duid_, iaid_, IOAddress("::"), AllocEngine::ClientContext6 ctx(subnet_, duid_, fqdn_fwd_, fqdn_rev_,
Lease::TYPE_NA, fqdn_fwd_, fqdn_rev_, hostname_, false,
hostname_, false); Pkt6Ptr(new Pkt6(DHCPV6_REQUEST, 1234)));
ctx.query_.reset(new Pkt6(DHCPV6_REQUEST, 1234)); ctx.currentIA().iaid_ = iaid_;
EXPECT_NO_THROW(lease = expectOneLease(engine->allocateLeases6(ctx))); EXPECT_NO_THROW(lease = expectOneLease(engine->allocateLeases6(ctx)));
// Check that we got that single lease // Check that we got that single lease
@ -427,7 +428,7 @@ TEST_F(AllocEngine6Test, smallPool6) {
// This is a new lease allocation. The old lease corresponding to a newly // This is a new lease allocation. The old lease corresponding to a newly
// allocated lease should be NULL. // allocated lease should be NULL.
ASSERT_TRUE(ctx.old_leases_.empty()); ASSERT_TRUE(ctx.currentIA().old_leases_.empty());
} }
// This test checks if all addresses in a pool are currently used, the attempt // This test checks if all addresses in a pool are currently used, the attempt
@ -458,11 +459,12 @@ TEST_F(AllocEngine6Test, outOfAddresses6) {
// There is just a single address in the pool and allocated it to someone // There is just a single address in the pool and allocated it to someone
// else, so the allocation should fail // else, so the allocation should fail
Lease6Ptr lease2; Pkt6Ptr query(new Pkt6(DHCPV6_REQUEST, 1234));
AllocEngine::ClientContext6 ctx(subnet_, duid_, iaid_, IOAddress("::"), AllocEngine::ClientContext6 ctx(subnet_, duid_, false, false, "", false,
Lease::TYPE_NA, false, false, "", false); query);
ctx.query_.reset(new Pkt6(DHCPV6_REQUEST, 1234)); ctx.currentIA().iaid_ = iaid_;
Lease6Ptr lease2;
EXPECT_NO_THROW(lease2 = expectOneLease(engine->allocateLeases6(ctx))); EXPECT_NO_THROW(lease2 = expectOneLease(engine->allocateLeases6(ctx)));
EXPECT_FALSE(lease2); EXPECT_FALSE(lease2);
@ -497,9 +499,9 @@ TEST_F(AllocEngine6Test, solicitReuseExpiredLease6) {
ASSERT_TRUE(lease->expired()); ASSERT_TRUE(lease->expired());
// CASE 1: Asking for any address // CASE 1: Asking for any address
AllocEngine::ClientContext6 ctx1(subnet_, duid_, iaid_, IOAddress("::"), AllocEngine::ClientContext6 ctx1(subnet_, duid_, fqdn_fwd_, fqdn_rev_, hostname_,
Lease::TYPE_NA, fqdn_fwd_, fqdn_rev_, hostname_, true); true, Pkt6Ptr(new Pkt6(DHCPV6_SOLICIT, 1234)));
ctx1.query_.reset(new Pkt6(DHCPV6_REQUEST, 1234)); ctx1.currentIA().iaid_ = iaid_;
EXPECT_NO_THROW(lease = expectOneLease(engine->allocateLeases6(ctx1))); EXPECT_NO_THROW(lease = expectOneLease(engine->allocateLeases6(ctx1)));
// Check that we got that single lease // Check that we got that single lease
@ -510,9 +512,11 @@ TEST_F(AllocEngine6Test, solicitReuseExpiredLease6) {
checkLease6(lease, Lease::TYPE_NA, 128); checkLease6(lease, Lease::TYPE_NA, 128);
// CASE 2: Asking specifically for this address // CASE 2: Asking specifically for this address
AllocEngine::ClientContext6 ctx2(subnet_, duid_, iaid_, addr, Lease::TYPE_NA, AllocEngine::ClientContext6 ctx2(subnet_, duid_, false, false, "", true,
false, false, "", true); Pkt6Ptr(new Pkt6(DHCPV6_REQUEST, 1234)));
ctx2.query_.reset(new Pkt6(DHCPV6_REQUEST, 1234)); ctx2.currentIA().iaid_ = iaid_;
ctx2.currentIA().addHint(addr);
EXPECT_NO_THROW(lease = expectOneLease(engine->allocateLeases6(ctx2))); EXPECT_NO_THROW(lease = expectOneLease(engine->allocateLeases6(ctx2)));
// Check that we got that single lease // Check that we got that single lease
@ -556,9 +560,11 @@ TEST_F(AllocEngine6Test, requestReuseExpiredLease6) {
StatsMgr::instance().setValue(name, static_cast<int64_t>(100)); StatsMgr::instance().setValue(name, static_cast<int64_t>(100));
// A client comes along, asking specifically for this address // A client comes along, asking specifically for this address
AllocEngine::ClientContext6 ctx(subnet_, duid_, iaid_, addr, Lease::TYPE_NA, AllocEngine::ClientContext6 ctx(subnet_, duid_, false, false, "", false,
false, false, "", false); Pkt6Ptr(new Pkt6(DHCPV6_REQUEST, 1234)));
ctx.query_.reset(new Pkt6(DHCPV6_REQUEST, 1234)); ctx.currentIA().iaid_ = iaid_;
ctx.currentIA().addHint(addr);
EXPECT_NO_THROW(lease = expectOneLease(engine->allocateLeases6(ctx))); EXPECT_NO_THROW(lease = expectOneLease(engine->allocateLeases6(ctx)));
// Check that he got that single lease // Check that he got that single lease
@ -570,7 +576,7 @@ TEST_F(AllocEngine6Test, requestReuseExpiredLease6) {
EXPECT_FALSE(lease->fqdn_rev_); EXPECT_FALSE(lease->fqdn_rev_);
// Check that the old lease has been returned. // Check that the old lease has been returned.
Lease6Ptr old_lease = expectOneLease(ctx.old_leases_); Lease6Ptr old_lease = expectOneLease(ctx.currentIA().old_leases_);
// It should at least have the same IPv6 address. // It should at least have the same IPv6 address.
EXPECT_EQ(lease->addr_, old_lease->addr_); EXPECT_EQ(lease->addr_, old_lease->addr_);
// Check that it carries not updated FQDN data. // Check that it carries not updated FQDN data.
@ -1170,9 +1176,11 @@ TEST_F(AllocEngine6Test, reservedAddress) {
int success = 0; int success = 0;
int failure = 0; int failure = 0;
for (int i = 0; i < 30; i++) { for (int i = 0; i < 30; i++) {
AllocEngine::ClientContext6 ctx(subnet_, clients[i], iaid_, IOAddress("::"), Pkt6Ptr query(new Pkt6(DHCPV6_REQUEST, 1234));
Lease::TYPE_NA, false, false, "", false); AllocEngine::ClientContext6 ctx(subnet_, clients[i], false, false, "",
ctx.query_.reset(new Pkt6(DHCPV6_REQUEST, 1234)); false, query);
ctx.currentIA().iaid_ = iaid_;
findReservation(engine, ctx); findReservation(engine, ctx);
Lease6Collection leases = engine.allocateLeases6(ctx); Lease6Collection leases = engine.allocateLeases6(ctx);
if (leases.empty()) { if (leases.empty()) {
@ -1194,9 +1202,9 @@ TEST_F(AllocEngine6Test, reservedAddress) {
// We're now pretty sure that any clients other than the reserved address // We're now pretty sure that any clients other than the reserved address
// will not get any service. Now let's check if the client that has the // will not get any service. Now let's check if the client that has the
// address reserved, will get it (despite the pool being depleted). // address reserved, will get it (despite the pool being depleted).
AllocEngine::ClientContext6 ctx(subnet_, duid_, iaid_, IOAddress("::"), AllocEngine::ClientContext6 ctx(subnet_, duid_, false, false, "", false,
Lease::TYPE_NA, false, false, "", false); Pkt6Ptr(new Pkt6(DHCPV6_REQUEST, 1234)));
ctx.query_.reset(new Pkt6(DHCPV6_REQUEST, 1234)); ctx.currentIA().iaid_ = iaid_;
findReservation(engine, ctx); findReservation(engine, ctx);
Lease6Collection leases = engine.allocateLeases6(ctx); Lease6Collection leases = engine.allocateLeases6(ctx);
@ -1209,9 +1217,10 @@ TEST_F(AllocEngine6Test, allocateLeasesInvalidData) {
AllocEngine engine(AllocEngine::ALLOC_ITERATIVE, 100, true); AllocEngine engine(AllocEngine::ALLOC_ITERATIVE, 100, true);
// That looks like a valid context. // That looks like a valid context.
AllocEngine::ClientContext6 ctx(subnet_, duid_, iaid_, IOAddress("::"), AllocEngine::ClientContext6 ctx(subnet_, duid_, false, false, "", false,
Lease::TYPE_NA, false, false, "", false); Pkt6Ptr(new Pkt6(DHCPV6_REQUEST, 1234)));
ctx.query_.reset(new Pkt6(DHCPV6_REQUEST, 1234)); ctx.currentIA().iaid_ = iaid_;
Lease6Collection leases; Lease6Collection leases;
// Let's break it! // Let's break it!
@ -1304,9 +1313,11 @@ TEST_F(AllocEngine6Test, DISABLED_reserved2AddressesSolicit) {
AllocEngine engine(AllocEngine::ALLOC_ITERATIVE, 100); AllocEngine engine(AllocEngine::ALLOC_ITERATIVE, 100);
AllocEngine::ClientContext6 ctx1(subnet_, duid_, iaid_, IOAddress("::"), AllocEngine::ClientContext6 ctx1(subnet_, duid_, false, false, "", true,
pool_->getType(), false, false, "", true); Pkt6Ptr(new Pkt6(DHCPV6_SOLICIT, 1234)));
ctx1.query_.reset(new Pkt6(DHCPV6_SOLICIT, 1234)); ctx1.currentIA().iaid_ = iaid_;
ctx1.currentIA().type_ = pool_->getType();
Lease6Collection leases1; Lease6Collection leases1;
findReservation(engine, ctx1); findReservation(engine, ctx1);
EXPECT_NO_THROW(leases1 = engine.allocateLeases6(ctx1)); EXPECT_NO_THROW(leases1 = engine.allocateLeases6(ctx1));
@ -1315,9 +1326,11 @@ TEST_F(AllocEngine6Test, DISABLED_reserved2AddressesSolicit) {
// Double check that repeating the same duid/type/iaid will end up with // Double check that repeating the same duid/type/iaid will end up with
// the same address. // the same address.
AllocEngine::ClientContext6 ctx2(subnet_, duid_, iaid_, IOAddress("::"), AllocEngine::ClientContext6 ctx2(subnet_, duid_, false, false, "", true,
pool_->getType(), false, false, "", true); Pkt6Ptr(new Pkt6(DHCPV6_SOLICIT, 1234)));
ctx2.query_.reset(new Pkt6(DHCPV6_SOLICIT, 1234)); ctx2.currentIA().iaid_ = iaid_;
ctx2.currentIA().type_ = pool_->getType();
Lease6Collection leases2; Lease6Collection leases2;
findReservation(engine, ctx2); findReservation(engine, ctx2);
EXPECT_NO_THROW(leases2 = engine.allocateLeases6(ctx2)); EXPECT_NO_THROW(leases2 = engine.allocateLeases6(ctx2));
@ -1326,9 +1339,11 @@ TEST_F(AllocEngine6Test, DISABLED_reserved2AddressesSolicit) {
// Ok, now the tricky part. Request allocation for the same duid and type, but // Ok, now the tricky part. Request allocation for the same duid and type, but
// different iaid. The second address should be assigned. // different iaid. The second address should be assigned.
AllocEngine::ClientContext6 ctx3(subnet_, duid_, iaid_ + 1, IOAddress("::"), AllocEngine::ClientContext6 ctx3(subnet_, duid_, false, false, "", true,
pool_->getType(), false, false, "", true); Pkt6Ptr(new Pkt6(DHCPV6_SOLICIT, 1234)));
ctx3.query_.reset(new Pkt6(DHCPV6_SOLICIT, 1234)); ctx3.currentIA().iaid_ = iaid_ + 1;
ctx3.currentIA().type_ = pool_->getType();
Lease6Collection leases3; Lease6Collection leases3;
findReservation(engine, ctx3); findReservation(engine, ctx3);
EXPECT_NO_THROW(leases3 = engine.allocateLeases6(ctx3)); EXPECT_NO_THROW(leases3 = engine.allocateLeases6(ctx3));
@ -1351,9 +1366,11 @@ TEST_F(AllocEngine6Test, reserved2Addresses) {
AllocEngine engine(AllocEngine::ALLOC_ITERATIVE, 100); AllocEngine engine(AllocEngine::ALLOC_ITERATIVE, 100);
AllocEngine::ClientContext6 ctx1(subnet_, duid_, iaid_, IOAddress("::"), AllocEngine::ClientContext6 ctx1(subnet_, duid_, false, false, "", false,
pool_->getType(), false, false, "", false); Pkt6Ptr(new Pkt6(DHCPV6_REQUEST, 1234)));
ctx1.query_.reset(new Pkt6(DHCPV6_REQUEST, 1234)); ctx1.currentIA().iaid_ = iaid_;
ctx1.currentIA().type_ = pool_->getType();
Lease6Collection leases1; Lease6Collection leases1;
findReservation(engine, ctx1); findReservation(engine, ctx1);
EXPECT_NO_THROW(leases1 = engine.allocateLeases6(ctx1)); EXPECT_NO_THROW(leases1 = engine.allocateLeases6(ctx1));
@ -1362,9 +1379,10 @@ TEST_F(AllocEngine6Test, reserved2Addresses) {
// Double check that repeating the same duid/type/iaid will end up with // Double check that repeating the same duid/type/iaid will end up with
// the same address. // the same address.
AllocEngine::ClientContext6 ctx2(subnet_, duid_, iaid_, IOAddress("::"), AllocEngine::ClientContext6 ctx2(subnet_, duid_, false, false, "", false,
pool_->getType(), false, false, "", false); Pkt6Ptr(new Pkt6(DHCPV6_REQUEST, 1234)));
ctx2.query_.reset(new Pkt6(DHCPV6_REQUEST, 1234)); ctx2.currentIA().iaid_ = iaid_;
ctx2.currentIA().type_ = pool_->getType();
Lease6Collection leases2; Lease6Collection leases2;
findReservation(engine, ctx2); findReservation(engine, ctx2);
@ -1374,9 +1392,10 @@ TEST_F(AllocEngine6Test, reserved2Addresses) {
// Ok, now the tricky part. Request allocation for the same duid and type, but // Ok, now the tricky part. Request allocation for the same duid and type, but
// different iaid. The second address should be assigned. // different iaid. The second address should be assigned.
AllocEngine::ClientContext6 ctx3(subnet_, duid_, iaid_ + 1, IOAddress("::"), AllocEngine::ClientContext6 ctx3(subnet_, duid_, false, false, "", false,
pool_->getType(), false, false, "", false); Pkt6Ptr(new Pkt6(DHCPV6_REQUEST, 1234)));
ctx3.query_.reset(new Pkt6(DHCPV6_REQUEST, 1234)); ctx3.currentIA().iaid_ = iaid_ + 1;
ctx3.currentIA().type_ = pool_->getType();
Lease6Collection leases3; Lease6Collection leases3;
findReservation(engine, ctx3); findReservation(engine, ctx3);

View File

@ -1415,14 +1415,13 @@ ExpirationAllocEngine6Test::testReclaimReusedLeases(const uint16_t msg_type,
for (unsigned int i = 0; i < TEST_LEASES_NUM; ++i) { for (unsigned int i = 0; i < TEST_LEASES_NUM; ++i) {
// Build the context. // Build the context.
AllocEngine::ClientContext6 ctx(subnet, leases_[i]->duid_, 1, AllocEngine::ClientContext6 ctx(subnet, leases_[i]->duid_,
leases_[i]->addr_,
Lease::TYPE_NA,
false, false, false, false,
leases_[i]->hostname_, leases_[i]->hostname_,
msg_type == DHCPV6_SOLICIT); msg_type == DHCPV6_SOLICIT,
// Query is needed for logging purposes. Pkt6Ptr(new Pkt6(msg_type, 0x1234)));
ctx.query_.reset(new Pkt6(msg_type, 0x1234)); ctx.currentIA().iaid_ = 1;
ctx.currentIA().hints_.push_back(std::make_pair(leases_[i]->addr_, 128));
// Depending on the message type, we will call a different function. // Depending on the message type, we will call a different function.
if (msg_type == DHCPV6_RENEW) { if (msg_type == DHCPV6_RENEW) {

View File

@ -148,13 +148,12 @@ TEST_F(HookAllocEngine6Test, lease6_select) {
EXPECT_NO_THROW(HooksManager::preCalloutsLibraryHandle().registerCallout( EXPECT_NO_THROW(HooksManager::preCalloutsLibraryHandle().registerCallout(
"lease6_select", lease6_select_callout)); "lease6_select", lease6_select_callout));
CalloutHandlePtr callout_handle = HooksManager::createCalloutHandle();
Lease6Ptr lease; Lease6Ptr lease;
AllocEngine::ClientContext6 ctx(subnet_, duid_, iaid_, IOAddress("::"), AllocEngine::ClientContext6 ctx(subnet_, duid_, false, false, "", false,
Lease::TYPE_NA, false, false, "", false); Pkt6Ptr(new Pkt6(DHCPV6_REQUEST, 1234)),
ctx.query_.reset(new Pkt6(DHCPV6_REQUEST, 1234)); HooksManager::createCalloutHandle());
ctx.callout_handle_ = callout_handle; ctx.currentIA().iaid_ = iaid_;
EXPECT_NO_THROW(lease = expectOneLease(engine->allocateLeases6(ctx))); EXPECT_NO_THROW(lease = expectOneLease(engine->allocateLeases6(ctx)));
// Check that we got a lease // Check that we got a lease
ASSERT_TRUE(lease); ASSERT_TRUE(lease);
@ -223,16 +222,12 @@ TEST_F(HookAllocEngine6Test, change_lease6_select) {
EXPECT_NO_THROW(HooksManager::preCalloutsLibraryHandle().registerCallout( EXPECT_NO_THROW(HooksManager::preCalloutsLibraryHandle().registerCallout(
"lease6_select", lease6_select_different_callout)); "lease6_select", lease6_select_different_callout));
// Normally, dhcpv6_srv would passed the handle when calling allocateLeases6,
// but in tests we need to create it on our own.
CalloutHandlePtr callout_handle = HooksManager::createCalloutHandle();
// Call allocateLeases6. Callouts should be triggered here. // Call allocateLeases6. Callouts should be triggered here.
Lease6Ptr lease; Lease6Ptr lease;
AllocEngine::ClientContext6 ctx(subnet_, duid_, iaid_, IOAddress("::"), AllocEngine::ClientContext6 ctx(subnet_, duid_, false, false, "", false,
Lease::TYPE_NA, false, false, "", false); Pkt6Ptr(new Pkt6(DHCPV6_REQUEST, 1234)),
ctx.query_.reset(new Pkt6(DHCPV6_REQUEST, 1234)); HooksManager::createCalloutHandle());
ctx.callout_handle_ = callout_handle; ctx.currentIA().iaid_ = iaid_;
EXPECT_NO_THROW(lease = expectOneLease(engine->allocateLeases6(ctx))); EXPECT_NO_THROW(lease = expectOneLease(engine->allocateLeases6(ctx)));
// Check that we got a lease // Check that we got a lease
ASSERT_TRUE(lease); ASSERT_TRUE(lease);

View File

@ -208,9 +208,13 @@ AllocEngine6Test::allocateTest(AllocEngine& engine, const Pool6Ptr& pool,
Lease::Type type = pool->getType(); Lease::Type type = pool->getType();
uint8_t expected_len = pool->getLength(); uint8_t expected_len = pool->getLength();
AllocEngine::ClientContext6 ctx(subnet_, duid_, iaid_, hint, type, Pkt6Ptr query(new Pkt6(fake ? DHCPV6_SOLICIT : DHCPV6_REQUEST, 1234));
false, false, "", fake);
ctx.query_.reset(new Pkt6(fake ? DHCPV6_SOLICIT : DHCPV6_REQUEST, 1234)); AllocEngine::ClientContext6 ctx(subnet_, duid_, false, false, "",
fake, query);
ctx.currentIA().iaid_ = iaid_;
ctx.currentIA().type_ = type;
ctx.currentIA().addHint(hint);
Lease6Collection leases; Lease6Collection leases;
@ -266,14 +270,17 @@ AllocEngine6Test::simpleAlloc6Test(const Pool6Ptr& pool, const IOAddress& hint,
return (Lease6Ptr()); return (Lease6Ptr());
} }
Lease6Ptr lease; Pkt6Ptr query(new Pkt6(fake ? DHCPV6_SOLICIT : DHCPV6_REQUEST, 1234));
AllocEngine::ClientContext6 ctx(subnet_, duid_, iaid_, hint, type,
false, false, "", fake); AllocEngine::ClientContext6 ctx(subnet_, duid_, false, false, "", fake, query);
ctx.hwaddr_ = hwaddr_; ctx.hwaddr_ = hwaddr_;
ctx.addHostIdentifier(Host::IDENT_HWADDR, hwaddr_->hwaddr_); ctx.addHostIdentifier(Host::IDENT_HWADDR, hwaddr_->hwaddr_);
ctx.query_.reset(new Pkt6(fake ? DHCPV6_SOLICIT : DHCPV6_REQUEST, 1234)); ctx.currentIA().iaid_ = iaid_;
ctx.currentIA().type_ = type;
ctx.currentIA().addHint(hint);
findReservation(*engine, ctx); findReservation(*engine, ctx);
Lease6Ptr lease;
EXPECT_NO_THROW(lease = expectOneLease(engine->allocateLeases6(ctx))); EXPECT_NO_THROW(lease = expectOneLease(engine->allocateLeases6(ctx)));
// Check that we got a lease // Check that we got a lease
@ -315,11 +322,12 @@ AllocEngine6Test::renewTest(AllocEngine& engine, const Pool6Ptr& pool,
Lease::Type type = pool->getType(); Lease::Type type = pool->getType();
uint8_t expected_len = pool->getLength(); uint8_t expected_len = pool->getLength();
AllocEngine::ClientContext6 ctx(subnet_, duid_, iaid_, IOAddress("::"), Pkt6Ptr query(new Pkt6(DHCPV6_RENEW, 1234));
type, false, false, "", false); AllocEngine::ClientContext6 ctx(subnet_, duid_, false, false, "",
ctx.hints_ = hints; false, query);
ctx.query_.reset(new Pkt6(DHCPV6_RENEW, 123)); ctx.currentIA().hints_ = hints;
ctx.query_.reset(new Pkt6(DHCPV6_RENEW, 1234)); ctx.currentIA().iaid_ = iaid_;
ctx.currentIA().type_ = type;
findReservation(engine, ctx); findReservation(engine, ctx);
Lease6Collection leases = engine.renewLeases6(ctx); Lease6Collection leases = engine.renewLeases6(ctx);
@ -366,10 +374,15 @@ AllocEngine6Test::allocWithUsedHintTest(Lease::Type type, IOAddress used_addr,
// Another client comes in and request an address that is in pool, but // Another client comes in and request an address that is in pool, but
// unfortunately it is used already. The same address must not be allocated // unfortunately it is used already. The same address must not be allocated
// twice. // twice.
Pkt6Ptr query(new Pkt6(DHCPV6_REQUEST, 1234));
AllocEngine::ClientContext6 ctx(subnet_, duid_, false, false, "", false,
query);
ctx.currentIA().iaid_ = iaid_;
ctx.currentIA().type_ = type;
ctx.currentIA().addHint(requested);
Lease6Ptr lease; Lease6Ptr lease;
AllocEngine::ClientContext6 ctx(subnet_, duid_, iaid_, requested, type,
false, false, "", false);
ctx.query_.reset(new Pkt6(DHCPV6_REQUEST, 1234));
EXPECT_NO_THROW(lease = expectOneLease(engine->allocateLeases6(ctx))); EXPECT_NO_THROW(lease = expectOneLease(engine->allocateLeases6(ctx)));
// Check that we got a lease // Check that we got a lease
@ -403,11 +416,15 @@ AllocEngine6Test::allocBogusHint6(Lease::Type type, asiolink::IOAddress hint,
// Client would like to get a 3000::abc lease, which does not belong to any // Client would like to get a 3000::abc lease, which does not belong to any
// supported lease. Allocation engine should ignore it and carry on // supported lease. Allocation engine should ignore it and carry on
// with the normal allocation // with the normal allocation
Lease6Ptr lease;
AllocEngine::ClientContext6 ctx(subnet_, duid_, iaid_, hint, type, false,
false, "", false);
ctx.query_.reset(new Pkt6(DHCPV6_REQUEST, 1234));
Pkt6Ptr query(new Pkt6(DHCPV6_REQUEST, 1234));
AllocEngine::ClientContext6 ctx(subnet_, duid_, false, false, "", false,
query);
ctx.currentIA().iaid_ = iaid_;
ctx.currentIA().type_ = type;
ctx.currentIA().addHint(hint);
Lease6Ptr lease;
EXPECT_NO_THROW(lease = expectOneLease(engine->allocateLeases6(ctx))); EXPECT_NO_THROW(lease = expectOneLease(engine->allocateLeases6(ctx)));
// Check that we got a lease // Check that we got a lease
@ -448,9 +465,12 @@ AllocEngine6Test::testReuseLease6(const AllocEnginePtr& engine,
} }
// A client comes along, asking specifically for a given address // A client comes along, asking specifically for a given address
AllocEngine::ClientContext6 ctx(subnet_, duid_, iaid_, IOAddress(addr),
Lease::TYPE_NA, false, false, "", fake_allocation); Pkt6Ptr query(new Pkt6(fake_allocation ? DHCPV6_SOLICIT : DHCPV6_REQUEST, 1234));
ctx.query_.reset(new Pkt6(fake_allocation ? DHCPV6_SOLICIT : DHCPV6_REQUEST, 1234)); AllocEngine::ClientContext6 ctx(subnet_, duid_, false, false, "",
fake_allocation, query);
ctx.currentIA().iaid_ = iaid_;
ctx.currentIA().addHint(IOAddress(addr));
Lease6Collection leases; Lease6Collection leases;