Commit f63a6cab authored by Tomek Mrugalski's avatar Tomek Mrugalski 🛰
Browse files

[2414] Allocation Engine is now used in dhcp6_srv.

parent 90bb56b1
......@@ -50,7 +50,7 @@ The IPv6 DHCP server tried to receive a packet but an error
occured during this attempt. The reason for the error is included in
the message.
% DHCP6_PACKET_RECEIVED %1 (type %2) packet received
% DHCP6_PACKET_RECEIVED %1 packet received
A debug message noting that the server has received the specified type
of packet. Note that a packet marked as UNKNOWN may well be a valid
DHCP packet, just a type not expected by the server (e.g. it will report
......@@ -66,10 +66,10 @@ This error is output if the server failed to assemble the data to be
returned to the client into a valid packet. The reason is most likely
to be to a programming error: please raise a bug report.
% DHCP6_QUERY_DATA received packet length %1, data length %2, data is <%3>
% DHCP6_QUERY_DATA received packet length %1, data length %2, data is %3
A debug message listing the data received from the client or relay.
% DHCP6_RESPONSE_DATA responding with packet type %1 data is <%2>
% DHCP6_RESPONSE_DATA responding with packet type %1 data is %2
A debug message listing the data returned to the client.
% DHCP6_SERVER_FAILED server failed: %1
......
......@@ -28,6 +28,12 @@
#include <util/io_utilities.h>
#include <util/range_utilities.h>
#include <dhcp/duid.h>
#include <dhcp/lease_mgr.h>
#include <dhcp/cfgmgr.h>
#include <dhcp/option6_iaaddr.h>
// @todo: Replace this with MySQL_LeaseMgr once it is merged
#include <dhcp/tests/memfile_lease_mgr.h>
using namespace isc;
using namespace isc::asiolink;
......@@ -35,20 +41,9 @@ using namespace isc::dhcp;
using namespace isc::util;
using namespace std;
const std::string HARDCODED_LEASE = "2001:db8:1::1234:abcd";
const uint32_t HARDCODED_T1 = 1500; // in seconds
const uint32_t HARDCODED_T2 = 2600; // in seconds
const uint32_t HARDCODED_PREFERRED_LIFETIME = 3600; // in seconds
const uint32_t HARDCODED_VALID_LIFETIME = 7200; // in seconds
const std::string HARDCODED_DNS_SERVER = "2001:db8:1::1";
Dhcpv6Srv::Dhcpv6Srv(uint16_t port) {
if (port == 0) {
// used for testing purposes. Some tests, e.g. configuration parser,
// require Dhcpv6Srv object, but they don't really need it to do
// anything. This speed up and simplifies the tests.
return;
}
LOG_DEBUG(dhcp6_logger, DBG_DHCP6_START, DHCP6_OPEN_SOCKET).arg(port);
......@@ -56,13 +51,18 @@ Dhcpv6Srv::Dhcpv6Srv(uint16_t port) {
// it may throw something if things go wrong
try {
if (IfaceMgr::instance().countIfaces() == 0) {
LOG_ERROR(dhcp6_logger, DHCP6_NO_INTERFACES);
shutdown_ = true;
return;
}
// used for testing purposes. Some tests, e.g. configuration parser,
// require Dhcpv6Srv object, but they don't really need it to do
// anything. This speed up and simplifies the tests.
if (port) {
if (IfaceMgr::instance().countIfaces() == 0) {
LOG_ERROR(dhcp6_logger, DHCP6_NO_INTERFACES);
shutdown_ = true;
return;
}
IfaceMgr::instance().openSockets6(port);
IfaceMgr::instance().openSockets6(port);
}
setServerID();
......@@ -74,11 +74,20 @@ Dhcpv6Srv::Dhcpv6Srv(uint16_t port) {
return;
}
// Instantiate LeaseMgr
// @todo: Replace this with MySQL_LeaseMgr once it is merged
new isc::dhcp::test::Memfile_LeaseMgr("");
// Instantiate allocation engine
alloc_engine_ = new AllocEngine(AllocEngine::ALLOC_ITERATIVE, 100);
shutdown_ = false;
}
Dhcpv6Srv::~Dhcpv6Srv() {
IfaceMgr::instance().closeSockets();
LeaseMgr::destroy_instance();
}
void Dhcpv6Srv::shutdown() {
......@@ -108,10 +117,9 @@ bool Dhcpv6Srv::run() {
continue;
}
LOG_DEBUG(dhcp6_logger, DBG_DHCP6_DETAIL, DHCP6_PACKET_RECEIVED)
.arg(serverReceivedPacketName(query->getType()))
.arg(query->getType());
.arg(serverReceivedPacketName(query->getType()));
LOG_DEBUG(dhcp6_logger, DBG_DHCP6_DETAIL_DATA, DHCP6_QUERY_DATA)
.arg(query->getType())
.arg(static_cast<int>(query->getType()))
.arg(query->getBuffer().getLength())
.arg(query->toText());
......@@ -301,33 +309,112 @@ void Dhcpv6Srv::appendRequestedOptions(const Pkt6Ptr& /*question*/, Pkt6Ptr& ans
answer->addOption(dnsservers);
}
OptionPtr Dhcpv6Srv::createStatusCode(uint16_t code, const std::string& text) {
// @todo: Implement Option6_StatusCode and rewrite this code here
vector<uint8_t> data(text.c_str(), text.c_str() + text.length());
data.insert(data.begin(), static_cast<uint8_t>(code % 256));
data.insert(data.begin(), static_cast<uint8_t>(code >> 8));
OptionPtr status(new Option(Option::V6, D6O_STATUS_CODE, data));
return (status);
}
Subnet6Ptr Dhcpv6Srv::getSubnet(const Pkt6Ptr& question) {
Subnet6Ptr subnet = CfgMgr::instance().getSubnet6(question->getRemoteAddr());
return (subnet);
}
void Dhcpv6Srv::assignLeases(const Pkt6Ptr& question, Pkt6Ptr& answer) {
/// TODO Rewrite this once LeaseManager is implemented.
// answer client's IA (this is mostly a dummy,
// so let's answer only first IA and hope there is only one)
boost::shared_ptr<Option> ia_opt = question->getOption(D6O_IA_NA);
if (ia_opt) {
// found IA
Option* tmp = ia_opt.get();
Option6IA* ia_req = dynamic_cast<Option6IA*>(tmp);
if (ia_req) {
boost::shared_ptr<Option6IA>
ia_rsp(new Option6IA(D6O_IA_NA, ia_req->getIAID()));
ia_rsp->setT1(HARDCODED_T1);
ia_rsp->setT2(HARDCODED_T2);
boost::shared_ptr<Option6IAAddr>
addr(new Option6IAAddr(D6O_IAADDR,
IOAddress(HARDCODED_LEASE),
HARDCODED_PREFERRED_LIFETIME,
HARDCODED_VALID_LIFETIME));
ia_rsp->addOption(addr);
answer->addOption(ia_rsp);
Subnet6Ptr subnet = getSubnet(question);
if (subnet) {
cout << "#### Selected subnet " << subnet->toText() << endl;
} else {
cout << "#### Failed to select a subnet" << endl;
}
// @todo: We should implement Option6Duid some day, but we can do without it
// just fine for now
DuidPtr duid;
OptionPtr opt_duid = question->getOption(D6O_CLIENTID);
if (opt_duid) {
duid = DuidPtr(new DUID(opt_duid->getData()));
}
if (duid) {
cout << "#### Processing request from client with duid=" << duid->toText() << endl;
} else {
cout << "#### Failed to find client-id :(" << endl;
}
for (Option::OptionCollection::iterator opt = question->options_.begin(); opt != question->options_.end(); ++opt) {
switch (opt->second->getType()) {
case D6O_IA_NA: {
OptionPtr answer_opt = handleIA_NA(subnet, duid, question, boost::dynamic_pointer_cast<Option6IA>(opt->second));
if (answer_opt) {
answer->addOption(answer_opt);
}
break;
}
default:
break;
}
}
}
OptionPtr Dhcpv6Srv::handleIA_NA(const Subnet6Ptr& subnet, const DuidPtr& duid, Pkt6Ptr question,
boost::shared_ptr<Option6IA> ia) {
if (!subnet) {
boost::shared_ptr<Option6IA> ia_rsp(new Option6IA(D6O_IA_NA, ia->getIAID()));
ia_rsp->addOption(createStatusCode(STATUS_NoAddrsAvail, "Sorry, no subnet available."));
return (ia_rsp);
}
boost::shared_ptr<Option6IAAddr> hintOpt = boost::dynamic_pointer_cast<Option6IAAddr>(ia->getOption(D6O_IAADDR));
IOAddress hint("::");
cout << "#### Processing request IA_NA: iaid=" << ia->getIAID();
if (hintOpt) {
hint = hintOpt->getAddress();
cout << ", hint=" << hint.toText() << endl;
} else {
cout << ", no hint provided" << endl;
}
bool fake_allocation = false;
if (question->getType() == DHCPV6_SOLICIT) {
/// @todo: Check if we support rapid commit
fake_allocation = true;
}
Lease6Ptr lease = alloc_engine_->allocateAddress6(subnet, duid, ia->getIAID(),
hint, fake_allocation);
boost::shared_ptr<Option6IA> ia_rsp(new Option6IA(D6O_IA_NA, ia->getIAID()));
if (lease) {
cout << "#### Allocated lease:" << lease->addr_.toText() << endl;
ia_rsp->setT1(subnet->getT1());
ia_rsp->setT2(subnet->getT2());
boost::shared_ptr<Option6IAAddr>
addr(new Option6IAAddr(D6O_IAADDR,
lease->addr_,
lease->preferred_lft_,
lease->valid_lft_));
ia_rsp->addOption(addr);
} else {
cout << "#### Failed to allocate a lease";
ia_rsp->addOption(createStatusCode(STATUS_NoAddrsAvail, "Sorry, no address could be allocated."));
}
return (ia_rsp);
}
Pkt6Ptr Dhcpv6Srv::processSolicit(const Pkt6Ptr& solicit) {
Pkt6Ptr advertise(new Pkt6(DHCPV6_ADVERTISE, solicit->getTransid()));
copyDefaultOptions(solicit, advertise);
......
......@@ -19,6 +19,10 @@
#include <dhcp/dhcp6.h>
#include <dhcp/pkt6.h>
#include <dhcp/option.h>
#include <dhcp/subnet.h>
#include <dhcp/duid.h>
#include <dhcp/option6_ia.h>
#include <dhcp/alloc_engine.h>
#include <iostream>
namespace isc {
......@@ -147,6 +151,36 @@ protected:
/// @param infRequest message received from client
Pkt6Ptr processInfRequest(const Pkt6Ptr& infRequest);
/// @brief creates status-code option
///
/// @param code status code value (see RFC3315)
/// @param text textual explanation (will be sent in status code option)
/// @return status-code option
OptionPtr createStatusCode(uint16_t code, const std::string& text);
/// @brief selects a subnet for a given client's packet
///
/// @return selected subnet (or NULL if no suitable subnet was found)
isc::dhcp::Subnet6Ptr getSubnet(const Pkt6Ptr& question);
/// @brief processes IA_NA option (and assigns addresses if necessary)
///
/// Generates response to IA_NA. This typically includes selecting (and
/// allocating a lease in case of REQUEST) a lease and creating
/// IAADDR option. In case of allocation failure, it may contain
/// status code option with non-zero status, denoting cause of the
/// allocation failure.
///
/// @param subnet subnet the client is connected to
/// @param duid client's duid
/// @param question client's message (typically SOLICIT or REQUEST)
/// @param ia pointer to client's IA_NA option (client's request)
/// @return IA_NA option (server's response)
OptionPtr handleIA_NA(const isc::dhcp::Subnet6Ptr& subnet,
const isc::dhcp::DuidPtr& duid,
isc::dhcp::Pkt6Ptr question,
boost::shared_ptr<Option6IA> ia);
/// @brief Copies required options from client message to server answer
///
/// Copies options that must appear in any server response (ADVERTISE, REPLY)
......@@ -202,6 +236,12 @@ protected:
/// server DUID (to be sent in server-identifier option)
boost::shared_ptr<isc::dhcp::Option> serverid_;
/// @brief Allocation Engine
/// Pointer to the allocation engine that we are currently using
/// It must be a pointer, because we will support changing engines
/// during normal operation (e.g. to use different allocators)
AllocEngine* alloc_engine_;
/// indicates if shutdown is in progress. Setting it to true will
/// initiate server shutdown procedure.
volatile bool shutdown_;
......
......@@ -39,6 +39,10 @@ libb10_dhcpsrv_la_SOURCES += pool.cc pool.h
libb10_dhcpsrv_la_SOURCES += subnet.cc subnet.h
libb10_dhcpsrv_la_SOURCES += triplet.h
libb10_dhcpsrv_la_SOURCES += lease_mgr.cc lease_mgr.h
# @todo: Remove this once MySQL LeaseMgr is merged
libb10_dhcpsrv_la_SOURCES += tests/memfile_lease_mgr.cc tests/memfile_lease_mgr.h
libb10_dhcpsrv_la_SOURCES += addr_utilities.cc addr_utilities.h
libb10_dhcpsrv_la_SOURCES += alloc_engine.cc alloc_engine.h
libb10_dhcpsrv_la_CXXFLAGS = $(AM_CXXFLAGS)
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment