Commit 90fd7ebf authored by Thomas Markwalder's avatar Thomas Markwalder

[#42] Implemented PacketQueueMgr class

New files:
    src/lib/dhcp/packet_queue_mgr.h
    src/lib/dhcp/packet_queue_mgr4.cc
    src/lib/dhcp/packet_queue_mgr4.h
    src/lib/dhcp/packet_queue_mgr6.cc
    src/lib/dhcp/packet_queue_mgr6.h
    src/lib/dhcp/tests/packet_queue_mgr4_unittest.cc
    src/lib/dhcp/tests/packet_queue_mgr6_unittest.cc
    src/lib/dhcp/tests/packet_queue_testutils.h

src/bin/dhcp4/ctrl_dhcp4_srv.cc
    Cleaned up packet queue config block

src/bin/dhcp4/dhcp4_lexer.ll
src/bin/dhcp4/dhcp4_parser.yy
src/bin/dhcp4/tests/config_parser_unittest.cc
    added queue-type

src/bin/dhcp4/dhcp4_messages.mes
    added DHCP4_CONFIG_PACKET_QUEUE message

src/lib/dhcp/Makefile.am
    packet_queue_mgr.h
    packet_queue_mgr4.cc packet_queue_mgr4.h
    packet_queue_mgr6.cc packet_queue_mgr6.h

src/lib/dhcp/iface_mgr.*
    Replaced packet queue members with PQM members
    Added PQM instantion to IfaceMgr ctor

src/lib/dhcp/packet_queue.h
    added getInfo,getInfoStr

src/lib/dhcp/tests/Makefile.am
    packet_queue_mgr4_unittest.cc
    packet_queue_mgr6_unittest.cc

src/lib/dhcpsrv/parsers/queue_control_parser.cc
    added queue-type
parent 036d249f
......@@ -634,20 +634,24 @@ ControlledDhcpv4Srv::processConfig(isc::data::ConstElementPtr config) {
return (isc::config::createAnswer(1, err.str()));
}
// Configure packet queue
try {
// @todo Consider making this a function and consider whether
// it should check for old gc != null and new gc null before
// calling setPacketQueueControl(). Or if we should even
// call it when it's null?
// Still grappling with what to if there is a custom queue
// loaded. Could have a flag in the control that means
// using custom impl, in which case we don't make the call
// at all. ... I dunno
ConstQueueControlPtr qc;
qc = CfgMgr::instance().getStagingCfg()->getQueueControlInfo();
IfaceMgr::instance().setPacketQueueControl4(qc);
qc = IfaceMgr::instance().getPacketQueueControl4();
std::cout << "TKM using capacity: " << qc->getCapacity() << std::endl;
if (!qc) {
// For right now, we are maually constructing the default
// This probably needs to be built into the PQM?
QueueControl default_qc;
default_qc.setQueueType("kea-ring4");
default_qc.setCapacity(500);
PacketQueueMgr4::instance().createPacketQueue(default_qc);
} else {
PacketQueueMgr4::instance().createPacketQueue(*qc);
}
LOG_DEBUG(dhcp4_logger, DBG_DHCP4_BASIC, DHCP4_CONFIG_PACKET_QUEUE)
.arg(PacketQueueMgr4::instance().getPacketQueue()->getInfoStr());
} catch (const std::exception& ex) {
err << "Error setting packet queue controls after server reconfiguration: "
<< ex.what();
......
This diff is collapsed.
......@@ -1250,6 +1250,15 @@ ControlCharacterFill [^"\\]|\\{JSONEscapeSequence}
}
}
\"queue-type\" {
switch(driver.ctx_) {
case isc::dhcp::Parser4Context::QUEUE_CONTROL:
return isc::dhcp::Dhcp4Parser::make_QUEUE_TYPE(driver.loc_);
default:
return isc::dhcp::Dhcp4Parser::make_STRING("queue-type", driver.loc_);
}
}
\"capacity\" {
switch(driver.ctx_) {
case isc::dhcp::Parser4Context::QUEUE_CONTROL:
......
......@@ -120,6 +120,11 @@ new configuration. It is output during server startup, and when an updated
configuration is committed by the administrator. Additional information
may be provided.
% DHCP4_CONFIG_PACKET_QUEUE DHCPv4 packet queue info after configuration: %1
This debug message is emitted during DHCPv4 server configuration, immediately
after configuring the DHCPv4 packet queue. The information shown depends
upon the packet queue type selected.
% DHCP4_CONFIG_LOAD_FAIL configuration error using file: %1, reason: %2
This error message indicates that the DHCPv4 configuration has failed.
If this is an initial configuration (during server's startup) the server
......
This diff is collapsed.
......@@ -461,60 +461,61 @@ namespace isc { namespace dhcp {
TOKEN_SOCKET_TYPE = 368,
TOKEN_SOCKET_NAME = 369,
TOKEN_QUEUE_CONTROL = 370,
TOKEN_CAPACITY = 371,
TOKEN_DHCP_DDNS = 372,
TOKEN_ENABLE_UPDATES = 373,
TOKEN_QUALIFYING_SUFFIX = 374,
TOKEN_SERVER_IP = 375,
TOKEN_SERVER_PORT = 376,
TOKEN_SENDER_IP = 377,
TOKEN_SENDER_PORT = 378,
TOKEN_MAX_QUEUE_SIZE = 379,
TOKEN_NCR_PROTOCOL = 380,
TOKEN_NCR_FORMAT = 381,
TOKEN_ALWAYS_INCLUDE_FQDN = 382,
TOKEN_OVERRIDE_NO_UPDATE = 383,
TOKEN_OVERRIDE_CLIENT_UPDATE = 384,
TOKEN_REPLACE_CLIENT_NAME = 385,
TOKEN_GENERATED_PREFIX = 386,
TOKEN_TCP = 387,
TOKEN_JSON = 388,
TOKEN_WHEN_PRESENT = 389,
TOKEN_NEVER = 390,
TOKEN_ALWAYS = 391,
TOKEN_WHEN_NOT_PRESENT = 392,
TOKEN_HOSTNAME_CHAR_SET = 393,
TOKEN_HOSTNAME_CHAR_REPLACEMENT = 394,
TOKEN_LOGGING = 395,
TOKEN_LOGGERS = 396,
TOKEN_OUTPUT_OPTIONS = 397,
TOKEN_OUTPUT = 398,
TOKEN_DEBUGLEVEL = 399,
TOKEN_SEVERITY = 400,
TOKEN_FLUSH = 401,
TOKEN_MAXSIZE = 402,
TOKEN_MAXVER = 403,
TOKEN_DHCP6 = 404,
TOKEN_DHCPDDNS = 405,
TOKEN_CONTROL_AGENT = 406,
TOKEN_TOPLEVEL_JSON = 407,
TOKEN_TOPLEVEL_DHCP4 = 408,
TOKEN_SUB_DHCP4 = 409,
TOKEN_SUB_INTERFACES4 = 410,
TOKEN_SUB_SUBNET4 = 411,
TOKEN_SUB_POOL4 = 412,
TOKEN_SUB_RESERVATION = 413,
TOKEN_SUB_OPTION_DEFS = 414,
TOKEN_SUB_OPTION_DEF = 415,
TOKEN_SUB_OPTION_DATA = 416,
TOKEN_SUB_HOOKS_LIBRARY = 417,
TOKEN_SUB_DHCP_DDNS = 418,
TOKEN_SUB_LOGGING = 419,
TOKEN_SUB_CONFIG_CONTROL = 420,
TOKEN_STRING = 421,
TOKEN_INTEGER = 422,
TOKEN_FLOAT = 423,
TOKEN_BOOLEAN = 424
TOKEN_QUEUE_TYPE = 371,
TOKEN_CAPACITY = 372,
TOKEN_DHCP_DDNS = 373,
TOKEN_ENABLE_UPDATES = 374,
TOKEN_QUALIFYING_SUFFIX = 375,
TOKEN_SERVER_IP = 376,
TOKEN_SERVER_PORT = 377,
TOKEN_SENDER_IP = 378,
TOKEN_SENDER_PORT = 379,
TOKEN_MAX_QUEUE_SIZE = 380,
TOKEN_NCR_PROTOCOL = 381,
TOKEN_NCR_FORMAT = 382,
TOKEN_ALWAYS_INCLUDE_FQDN = 383,
TOKEN_OVERRIDE_NO_UPDATE = 384,
TOKEN_OVERRIDE_CLIENT_UPDATE = 385,
TOKEN_REPLACE_CLIENT_NAME = 386,
TOKEN_GENERATED_PREFIX = 387,
TOKEN_TCP = 388,
TOKEN_JSON = 389,
TOKEN_WHEN_PRESENT = 390,
TOKEN_NEVER = 391,
TOKEN_ALWAYS = 392,
TOKEN_WHEN_NOT_PRESENT = 393,
TOKEN_HOSTNAME_CHAR_SET = 394,
TOKEN_HOSTNAME_CHAR_REPLACEMENT = 395,
TOKEN_LOGGING = 396,
TOKEN_LOGGERS = 397,
TOKEN_OUTPUT_OPTIONS = 398,
TOKEN_OUTPUT = 399,
TOKEN_DEBUGLEVEL = 400,
TOKEN_SEVERITY = 401,
TOKEN_FLUSH = 402,
TOKEN_MAXSIZE = 403,
TOKEN_MAXVER = 404,
TOKEN_DHCP6 = 405,
TOKEN_DHCPDDNS = 406,
TOKEN_CONTROL_AGENT = 407,
TOKEN_TOPLEVEL_JSON = 408,
TOKEN_TOPLEVEL_DHCP4 = 409,
TOKEN_SUB_DHCP4 = 410,
TOKEN_SUB_INTERFACES4 = 411,
TOKEN_SUB_SUBNET4 = 412,
TOKEN_SUB_POOL4 = 413,
TOKEN_SUB_RESERVATION = 414,
TOKEN_SUB_OPTION_DEFS = 415,
TOKEN_SUB_OPTION_DEF = 416,
TOKEN_SUB_OPTION_DATA = 417,
TOKEN_SUB_HOOKS_LIBRARY = 418,
TOKEN_SUB_DHCP_DDNS = 419,
TOKEN_SUB_LOGGING = 420,
TOKEN_SUB_CONFIG_CONTROL = 421,
TOKEN_STRING = 422,
TOKEN_INTEGER = 423,
TOKEN_FLOAT = 424,
TOKEN_BOOLEAN = 425
};
};
......@@ -1085,6 +1086,10 @@ namespace isc { namespace dhcp {
symbol_type
make_QUEUE_CONTROL (const location_type& l);
static inline
symbol_type
make_QUEUE_TYPE (const location_type& l);
static inline
symbol_type
make_CAPACITY (const location_type& l);
......@@ -1506,12 +1511,12 @@ namespace isc { namespace dhcp {
enum
{
yyeof_ = 0,
yylast_ = 1005, ///< Last index in yytable_.
yynnts_ = 377, ///< Number of nonterminal symbols.
yylast_ = 1029, ///< Last index in yytable_.
yynnts_ = 379, ///< Number of nonterminal symbols.
yyfinal_ = 30, ///< Termination state number.
yyterror_ = 1,
yyerrcode_ = 256,
yyntokens_ = 170 ///< Number of tokens.
yyntokens_ = 171 ///< Number of tokens.
};
......@@ -1570,9 +1575,9 @@ namespace isc { namespace dhcp {
135, 136, 137, 138, 139, 140, 141, 142, 143, 144,
145, 146, 147, 148, 149, 150, 151, 152, 153, 154,
155, 156, 157, 158, 159, 160, 161, 162, 163, 164,
165, 166, 167, 168, 169
165, 166, 167, 168, 169, 170
};
const unsigned int user_token_number_max_ = 424;
const unsigned int user_token_number_max_ = 425;
const token_number_type undef_token_ = 2;
if (static_cast<int>(t) <= yyeof_)
......@@ -1605,30 +1610,30 @@ namespace isc { namespace dhcp {
{
switch (other.type_get ())
{
case 186: // value
case 190: // map_value
case 230: // socket_type
case 233: // outbound_interface_value
case 255: // db_type
case 337: // hr_mode
case 489: // ncr_protocol_value
case 497: // replace_client_name_value
case 187: // value
case 191: // map_value
case 231: // socket_type
case 234: // outbound_interface_value
case 256: // db_type
case 338: // hr_mode
case 492: // ncr_protocol_value
case 500: // replace_client_name_value
value.copy< ElementPtr > (other.value);
break;
case 169: // "boolean"
case 170: // "boolean"
value.copy< bool > (other.value);
break;
case 168: // "floating point"
case 169: // "floating point"
value.copy< double > (other.value);
break;
case 167: // "integer"
case 168: // "integer"
value.copy< int64_t > (other.value);
break;
case 166: // "constant string"
case 167: // "constant string"
value.copy< std::string > (other.value);
break;
......@@ -1649,30 +1654,30 @@ namespace isc { namespace dhcp {
(void) v;
switch (this->type_get ())
{
case 186: // value
case 190: // map_value
case 230: // socket_type
case 233: // outbound_interface_value
case 255: // db_type
case 337: // hr_mode
case 489: // ncr_protocol_value
case 497: // replace_client_name_value
case 187: // value
case 191: // map_value
case 231: // socket_type
case 234: // outbound_interface_value
case 256: // db_type
case 338: // hr_mode
case 492: // ncr_protocol_value
case 500: // replace_client_name_value
value.copy< ElementPtr > (v);
break;
case 169: // "boolean"
case 170: // "boolean"
value.copy< bool > (v);
break;
case 168: // "floating point"
case 169: // "floating point"
value.copy< double > (v);
break;
case 167: // "integer"
case 168: // "integer"
value.copy< int64_t > (v);
break;
case 166: // "constant string"
case 167: // "constant string"
value.copy< std::string > (v);
break;
......@@ -1752,30 +1757,30 @@ namespace isc { namespace dhcp {
// Type destructor.
switch (yytype)
{
case 186: // value
case 190: // map_value
case 230: // socket_type
case 233: // outbound_interface_value
case 255: // db_type
case 337: // hr_mode
case 489: // ncr_protocol_value
case 497: // replace_client_name_value
case 187: // value
case 191: // map_value
case 231: // socket_type
case 234: // outbound_interface_value
case 256: // db_type
case 338: // hr_mode
case 492: // ncr_protocol_value
case 500: // replace_client_name_value
value.template destroy< ElementPtr > ();
break;
case 169: // "boolean"
case 170: // "boolean"
value.template destroy< bool > ();
break;
case 168: // "floating point"
case 169: // "floating point"
value.template destroy< double > ();
break;
case 167: // "integer"
case 168: // "integer"
value.template destroy< int64_t > ();
break;
case 166: // "constant string"
case 167: // "constant string"
value.template destroy< std::string > ();
break;
......@@ -1802,30 +1807,30 @@ namespace isc { namespace dhcp {
super_type::move(s);
switch (this->type_get ())
{
case 186: // value
case 190: // map_value
case 230: // socket_type
case 233: // outbound_interface_value
case 255: // db_type
case 337: // hr_mode
case 489: // ncr_protocol_value
case 497: // replace_client_name_value
case 187: // value
case 191: // map_value
case 231: // socket_type
case 234: // outbound_interface_value
case 256: // db_type
case 338: // hr_mode
case 492: // ncr_protocol_value
case 500: // replace_client_name_value
value.move< ElementPtr > (s.value);
break;
case 169: // "boolean"
case 170: // "boolean"
value.move< bool > (s.value);
break;
case 168: // "floating point"
case 169: // "floating point"
value.move< double > (s.value);
break;
case 167: // "integer"
case 168: // "integer"
value.move< int64_t > (s.value);
break;
case 166: // "constant string"
case 167: // "constant string"
value.move< std::string > (s.value);
break;
......@@ -1900,7 +1905,8 @@ namespace isc { namespace dhcp {
385, 386, 387, 388, 389, 390, 391, 392, 393, 394,
395, 396, 397, 398, 399, 400, 401, 402, 403, 404,
405, 406, 407, 408, 409, 410, 411, 412, 413, 414,
415, 416, 417, 418, 419, 420, 421, 422, 423, 424
415, 416, 417, 418, 419, 420, 421, 422, 423, 424,
425
};
return static_cast<token_type> (yytoken_number_[type]);
}
......@@ -2589,6 +2595,12 @@ namespace isc { namespace dhcp {
return symbol_type (token::TOKEN_QUEUE_CONTROL, l);
}
Dhcp4Parser::symbol_type
Dhcp4Parser::make_QUEUE_TYPE (const location_type& l)
{
return symbol_type (token::TOKEN_QUEUE_TYPE, l);
}
Dhcp4Parser::symbol_type
Dhcp4Parser::make_CAPACITY (const location_type& l)
{
......@@ -2916,7 +2928,7 @@ namespace isc { namespace dhcp {
#line 14 "dhcp4_parser.yy" // lalr1.cc:377
} } // isc::dhcp
#line 2920 "dhcp4_parser.h" // lalr1.cc:377
#line 2932 "dhcp4_parser.h" // lalr1.cc:377
......
......@@ -171,6 +171,7 @@ using namespace std;
SOCKET_NAME "socket-name"
QUEUE_CONTROL "queue-control"
QUEUE_TYPE "queue-type"
CAPACITY "capacity"
DHCP_DDNS "dhcp-ddns"
......@@ -1836,6 +1837,7 @@ queue_control: QUEUE_CONTROL {
ctx.stack_.push_back(m);
ctx.enter(ctx.QUEUE_CONTROL);
} COLON LCURLY_BRACKET queue_control_params RCURLY_BRACKET {
ctx.require("queue-type", ctx.loc2pos(@4), ctx.loc2pos(@6));
ctx.require("capacity", ctx.loc2pos(@4), ctx.loc2pos(@6));
ctx.stack_.pop_back();
ctx.leave();
......@@ -1845,12 +1847,21 @@ queue_control_params: queue_control_param
| queue_control_params COMMA queue_control_param
;
queue_control_param: capacity
queue_control_param: queue_type
| capacity
| user_context
| comment
| unknown_map_entry
;
queue_type : QUEUE_TYPE {
ctx.enter(ctx.NO_KEYWORD);
} COLON STRING {
ElementPtr qtype(new StringElement($4, ctx.loc2pos(@4)));
ctx.stack_.back()->set("queue-type", qtype);
ctx.leave();
};
capacity: CAPACITY COLON INTEGER {
ElementPtr i(new IntElement($3, ctx.loc2pos(@3)));
ctx.stack_.back()->set("capacity", i);
......
......@@ -6348,6 +6348,7 @@ TEST_F(Dhcp4ParserTest, queueControl) {
"{ " + genIfaceConfig() + ", \n" +
" \"subnet4\": [ ], \n"
" \"queue-control\": { \n"
" \"queue-type\": \"some-type\", \n"
" \"capacity\": 75 \n"
" } \n"
"} \n";
......@@ -6356,6 +6357,7 @@ TEST_F(Dhcp4ParserTest, queueControl) {
"{ " + genIfaceConfig() + ", \n" +
" \"subnet4\": [ ], \n"
" \"queue-control\": { \n"
" \"queue-type\": \"some-type\", \n"
" \"capacity\": 90, \n"
" \"user-context\": { \"comment\": \"some text\" } \n"
" } \n"
......@@ -6406,6 +6408,15 @@ TEST_F(Dhcp4ParserTest, queueControlInvalid) {
" \"queue-control\": 75 \n"
"} \n"
},
{
"queue type missing",
"{ " + genIfaceConfig() + ", \n" +
" \"subnet4\": [ ], \n"
" \"queue-control\": { \n"
" \"capacity\": 100 \n"
" } \n"
"} \n"
},
{
"capacity missing",
"{ " + genIfaceConfig() + ", \n" +
......
......@@ -44,6 +44,9 @@ libkea_dhcp___la_SOURCES += option_string.cc option_string.h
libkea_dhcp___la_SOURCES += option_vendor.cc option_vendor.h
libkea_dhcp___la_SOURCES += option_vendor_class.cc option_vendor_class.h
libkea_dhcp___la_SOURCES += packet_queue.h
libkea_dhcp___la_SOURCES += packet_queue_mgr.h
libkea_dhcp___la_SOURCES += packet_queue_mgr4.cc packet_queue_mgr4.h
libkea_dhcp___la_SOURCES += packet_queue_mgr6.cc packet_queue_mgr6.h
libkea_dhcp___la_SOURCES += pkt.cc pkt.h
libkea_dhcp___la_SOURCES += pkt4.cc pkt4.h
libkea_dhcp___la_SOURCES += pkt4o6.cc pkt4o6.h
......@@ -124,6 +127,9 @@ libkea_dhcp___include_HEADERS = \
option_vendor.h \
option_vendor_class.h \
packet_queue.h \
packet_queue_mgr.h \
packet_queue_mgr4.h \
packet_queue_mgr6.h \
pkt.h \
pkt4.h \
pkt4o6.h \
......
......@@ -185,9 +185,16 @@ IfaceMgr::IfaceMgr()
packet_filter6_(new PktFilterInet6()),
test_mode_(false),
allow_loopback_(false),
receiver_error_("no error"),
packet_queue4_(new PacketQueueRing4()),
packet_queue6_(new PacketQueueRing6()) {
receiver_error_("no error") {
// Ensure that PQMs have been created to guarantee we have
// default packet queues in place.
try {
PacketQueueMgr4::create();
PacketQueueMgr6::create();
} catch (const std::exception& ex) {
isc_throw(Unexpected, "Failed to create PacketQueueManagers: " << ex.what());
}
try {
......@@ -280,7 +287,7 @@ void IfaceMgr::closeSockets() {
}
}
void IfaceMgr::stopReceiver() {
void IfaceMgr::stopDHCPReceiver() {
if (receiver_thread_) {
terminate_watch_.markReady();
receiver_thread_->wait();
......@@ -288,15 +295,17 @@ void IfaceMgr::stopReceiver() {
error_watch_.clearReady();
}
receiver_error_ = "no error";
if (packet_queue4_) {
packet_queue4_->clear();
/* if(getPacketQueue4())*/ {
getPacketQueue4()->clear();
}
if (packet_queue6_) {
packet_queue6_->clear();
/* if (getPacketQueue6()) */ {
getPacketQueue4()->clear();
}
}
void
IfaceMgr::closeSockets(const uint16_t) {
isc_throw(NotImplemented, "closeSockets(family) is obsolete");
......@@ -306,8 +315,12 @@ IfaceMgr::~IfaceMgr() {
// control_buf_ is deleted automatically (scoped_ptr)
control_buf_len_ = 0;
stopReceiver();
stopDHCPReceiver();
closeSockets();
// Explicitly delete PQM singletons.
PacketQueueMgr4::destroy();
PacketQueueMgr6::destroy();
}
bool
......@@ -671,9 +684,17 @@ IfaceMgr::startDHCPReceiver(const uint16_t family) {
switch (family) {
case AF_INET:
if(!getPacketQueue4()) {
isc_throw(Unexpected, "startDHCPRecever - no packet queue?");
}
receiver_thread_.reset(new Thread(boost::bind(&IfaceMgr::receiveDHCP4Packets, this)));
break;
case AF_INET6:
if(!getPacketQueue6()) {
isc_throw(Unexpected, "startDHCPRecever - no packet queue?");
}
receiver_thread_.reset(new Thread(boost::bind(&IfaceMgr::receiveDHCP6Packets, this)));
break;
default:
......@@ -965,7 +986,7 @@ Pkt4Ptr IfaceMgr::receive4(uint32_t timeout_sec, uint32_t timeout_usec /* = 0 */
}
struct timeval select_timeout;
if (packet_queue4_->empty()) {
if (getPacketQueue4()->empty()) {
select_timeout.tv_sec = timeout_sec;
select_timeout.tv_usec = timeout_usec;
} else {
......@@ -978,7 +999,7 @@ Pkt4Ptr IfaceMgr::receive4(uint32_t timeout_sec, uint32_t timeout_usec /* = 0 */
int result = select(maxfd + 1, &sockets, NULL, NULL, &select_timeout);