// When the maximum count is 0 the maximum age (in seconds) applies.
"statistic-default-sample-age": 60,
+ // By default Kea processes packets on a single thread (default 'false'
+ // value for this option). To enable multi-threading, this option can be
+ // set ('true' value).
+ "enable-multi-threading": false,
+
+ // When multi-threading is enabled, Kea will process packets on a number of
+ // multiple threads configurable through this option. The value must be a
+ // positive integer (0 means auto detect).
+ "packet-thread-pool-size": 0,
+
+ // When multi-threading is enabled, Kea will read packets from the interface
+ // and append a working item to the thread pool. This option configures the
+ // maximum number of items that can be queued for each processing thread.
+ // The value must be a positive integer (0 means unlimited).
+ "packet-thread-queue-size": 0,
+
// Governs how the Kea DHCPv4 server should deal with the invalid
// data received from the client.
"sanity-checks": {
// When the maximum count is 0 the maximum age (in seconds) applies.
"statistic-default-sample-age": 60,
+ // By default Kea processes packets on a single thread (default 'false'
+ // value for this option). To enable multi-threading, this option can be
+ // set ('true' value).
+ "enable-multi-threading": false,
+
+ // When multi-threading is enabled, Kea will process packets on a number of
+ // multiple threads configurable through this option. The value must be a
+ // positive integer (0 means auto detect).
+ "packet-thread-pool-size": 0,
+
+ // When multi-threading is enabled, Kea will read packets from the interface
+ // and append a working item to the thread pool. This option configures the
+ // maximum number of items that can be queued for each processing thread.
+ // The value must be a positive integer (0 means unlimited).
+ "packet-thread-queue-size": 0,
+
// Governs how the Kea DHCPv6 server should deal with the invalid
// data received from the client.
"sanity-checks": {
"processCommand(\"config-set\", json)");
}
+ // command line parameters overwrite file and database configuration
bool enabled = false;
- if (srv_thread_count >= 0) {
+ if (Dhcpv4Srv::srv_thread_count_ >= 0) {
enabled = true;
}
if (enabled) {
- CfgMgr::instance().getCurrentCfg()->setServerThreadCount(srv_thread_count);
- CfgMgr::instance().getCurrentCfg()->setServerMaxThreadQueueSize(4);
+ CfgMgr::instance().getCurrentCfg()->setPktThreadPoolSize(Dhcpv4Srv::srv_thread_count_);
+ CfgMgr::instance().getCurrentCfg()->setPktThreadQueueSize(0);
LOG_FATAL(dhcp4_logger, DHCP4_MULTI_THREADING_WARNING);
+ } else {
+ enabled = CfgMgr::instance().getCurrentCfg()->getEnableMultiThreading();
}
MultiThreadingMgr::instance().apply(enabled,
- CfgMgr::instance().getCurrentCfg()->getServerThreadCount());
+ CfgMgr::instance().getCurrentCfg()->getPktThreadPoolSize());
// Now check is the returned result is successful (rcode=0) or not
// (see @ref isc::config::parseAnswer).
LOG_WARN(dhcp4_logger, DHCP4_MULTI_THREADING_INFO)
.arg(MultiThreadingMgr::instance().getMode() ? "yes" : "no")
.arg(MultiThreadingMgr::instance().getPktThreadPoolSize())
- .arg(CfgMgr::instance().getCurrentCfg()->getServerMaxThreadQueueSize());
+ .arg(CfgMgr::instance().getCurrentCfg()->getPktThreadQueueSize());
return (result);
}
}
}
+\"enable-multi-threading\" {
+ switch(driver.ctx_) {
+ case isc::dhcp::Parser4Context::DHCP4:
+ return isc::dhcp::Dhcp4Parser::make_ENABLE_MULTI_THREADING(driver.loc_);
+ default:
+ return isc::dhcp::Dhcp4Parser::make_STRING("enable-multi-threading", driver.loc_);
+ }
+}
+
+\"packet-thread-pool-size\" {
+ switch(driver.ctx_) {
+ case isc::dhcp::Parser4Context::DHCP4:
+ return isc::dhcp::Dhcp4Parser::make_PACKET_THREAD_POOL_SIZE(driver.loc_);
+ default:
+ return isc::dhcp::Dhcp4Parser::make_STRING("packet-thread-pool-size", driver.loc_);
+ }
+}
+
+\"packet-thread-queue-size\" {
+ switch(driver.ctx_) {
+ case isc::dhcp::Parser4Context::DHCP4:
+ return isc::dhcp::Dhcp4Parser::make_PACKET_THREAD_QUEUE_SIZE(driver.loc_);
+ default:
+ return isc::dhcp::Dhcp4Parser::make_STRING("packet-thread-queue-size", driver.loc_);
+ }
+}
+
\"control-socket\" {
switch(driver.ctx_) {
case isc::dhcp::Parser4Context::DHCP4:
}
}
-
-
{JSONString} {
/* A string has been matched. It contains the actual string and single quotes.
We need to get those quotes out of the way and just use its content, e.g.
DHCP4O6_PORT "dhcp4o6-port"
+ ENABLE_MULTI_THREADING "enable-multi-threading"
+ PACKET_THREAD_POOL_SIZE "packet-thread-pool-size"
+ PACKET_THREAD_QUEUE_SIZE "packet-thread-queue-size"
+
CONTROL_SOCKET "control-socket"
SOCKET_TYPE "socket-type"
SOCKET_NAME "socket-name"
| statistic_default_sample_count
| statistic_default_sample_age
| unknown_map_entry
+ | enable_multi_threading
+ | packet_thread_pool_size
+ | packet_thread_queue_size
;
valid_lifetime: VALID_LIFETIME COLON INTEGER {
ctx.stack_.back()->add(flex_id);
};
+enable_multi_threading: ENABLE_MULTI_THREADING COLON BOOLEAN {
+ ElementPtr b(new BoolElement($3, ctx.loc2pos(@3)));
+ ctx.stack_.back()->set("enable-multi-threading", b);
+};
+
+packet_thread_pool_size: PACKET_THREAD_POOL_SIZE COLON INTEGER {
+ ElementPtr prf(new IntElement($3, ctx.loc2pos(@3)));
+ ctx.stack_.back()->set("packet-thread-pool-size", prf);
+};
+
+packet_thread_queue_size: PACKET_THREAD_QUEUE_SIZE COLON INTEGER {
+ ElementPtr prf(new IntElement($3, ctx.loc2pos(@3)));
+ ctx.stack_.back()->set("packet-thread-queue-size", prf);
+};
+
hooks_libraries: HOOKS_LIBRARIES {
ElementPtr l(new ListElement(ctx.loc2pos(@1)));
ctx.stack_.back()->set("hooks-libraries", l);
// --- end of client classes ---------------------------------
-// was server-id but in is DHCPv6-only
-
dhcp4o6_port: DHCP4O6_PORT COLON INTEGER {
ElementPtr time(new IntElement($3, ctx.loc2pos(@3)));
ctx.stack_.back()->set("dhcp4o6-port", time);
ctx.leave();
};
+// Config control information element
+
config_control: CONFIG_CONTROL {
ElementPtr i(new MapElement(ctx.loc2pos(@1)));
ctx.stack_.back()->set("config-control", i);
ctx.leave();
};
-
%%
void
const std::string Dhcpv4Srv::VENDOR_CLASS_PREFIX("VENDOR_CLASS_");
+int Dhcpv4Srv::srv_thread_count_ = -1;
+
Dhcpv4Srv::Dhcpv4Srv(uint16_t server_port, uint16_t client_port,
const bool use_bcast, const bool direct_response_desired)
: io_service_(new IOService()), server_port_(server_port),
try {
bool read_pkt = true;
- // Do not read more packets from socket if there are enough
- // packets to be processed in the packet thread pool queue
- const int max_queue_size = CfgMgr::instance().getCurrentCfg()->getServerMaxThreadQueueSize();
+ // Do not read more packets from socket if there are enough packets to
+ // be processed in the packet thread pool queue
+ // max_queue_size = 0 means no limit
+ const int max_queue_size = CfgMgr::instance().getCurrentCfg()->getPktThreadQueueSize();
const int thread_count = MultiThreadingMgr::instance().getPktThreadPoolSize();
size_t pkt_queue_size = MultiThreadingMgr::instance().getPktThreadPool().count();
- if (thread_count && (pkt_queue_size >= thread_count * max_queue_size)) {
+ if (thread_count && max_queue_size && (pkt_queue_size >= thread_count * max_queue_size)) {
read_pkt = false;
}
CBControlDHCPv4Ptr cb_control_;
public:
+ /// @brief command line parameter thread count
+ /// when parameter is not specified, the default value is used
+ /// the default value is: -1 means disabled (single-threaded),
+ /// 0 means auto-detect, other values set thread count explicitly
+ static int srv_thread_count_;
+
/// Class methods for DHCPv4-over-DHCPv6 handler
/// @brief Updates statistics for received packets
#include <database/dbaccess_parser.h>
#include <database/backend_selector.h>
#include <database/server_selector.h>
+#include <dhcp/libdhcp++.h>
+#include <dhcp/option_definition.h>
#include <dhcp4/dhcp4_log.h>
#include <dhcp4/dhcp4_srv.h>
#include <dhcp4/json_config_parser.h>
-#include <dhcp/libdhcp++.h>
-#include <dhcp/option_definition.h>
#include <dhcpsrv/cb_ctl_dhcp4.h>
#include <dhcpsrv/cfg_option.h>
#include <dhcpsrv/cfgmgr.h>
#include <dhcpsrv/config_backend_dhcp4_mgr.h>
#include <dhcpsrv/db_type.h>
+#include <dhcpsrv/host_data_source_factory.h>
#include <dhcpsrv/parsers/client_class_def_parser.h>
#include <dhcpsrv/parsers/dhcp_parsers.h>
#include <dhcpsrv/parsers/expiration_config_parser.h>
#include <dhcpsrv/parsers/simple_parser4.h>
#include <dhcpsrv/parsers/shared_networks_list_parser.h>
#include <dhcpsrv/parsers/sanity_checks_parser.h>
-#include <dhcpsrv/host_data_source_factory.h>
#include <dhcpsrv/timer_mgr.h>
#include <process/config_ctl_parser.h>
#include <hooks/hooks_parser.h>
#include <util/encode/hex.h>
#include <util/strutil.h>
+#include <boost/algorithm/string.hpp>
#include <boost/foreach.hpp>
#include <boost/lexical_cast.hpp>
-#include <boost/algorithm/string.hpp>
-#include <limits>
#include <iostream>
-#include <iomanip>
+#include <limits>
+#include <map>
#include <netinet/in.h>
#include <vector>
-#include <map>
using namespace std;
using namespace isc;
-using namespace isc::dhcp;
using namespace isc::data;
+using namespace isc::dhcp;
using namespace isc::asiolink;
using namespace isc::hooks;
using namespace isc::process;
uint16_t dhcp4o6_port = getUint16(global, "dhcp4o6-port");
cfg->setDhcp4o6Port(dhcp4o6_port);
+ // Set enable multi threading flag.
+ bool enable_multi_threading = getBoolean(global, "enable-multi-threading");
+ cfg->setEnableMultiThreading(enable_multi_threading);
+
+ // Set packet thread pool size.
+ uint32_t packet_thread_pool_size = getUint32(global, "packet-thread-pool-size");
+ cfg->setPktThreadPoolSize(packet_thread_pool_size);
+
+ // Set packet thread queue size.
+ uint32_t packet_thread_queue_size = getUint32(global, "packet-thread-queue-size");
+ cfg->setPktThreadQueueSize(packet_thread_queue_size);
+
// Set the global user context.
ConstElementPtr user_context = global->get("user-context");
if (user_context) {
}
}
-
isc::data::ConstElementPtr
configureDhcp4Server(Dhcpv4Srv& server, isc::data::ConstElementPtr config_set,
bool check_only) {
// have to be restored to global storages.
bool rollback = false;
// config_pair holds the details of the current parser when iterating over
- // the parsers. It is declared outside the loops so in case of an error,
- // the name of the failing parser can be retrieved in the "catch" clause.
+ // the parsers. It is declared outside the loop so in case of error, the
+ // name of the failing parser can be retrieved within the "catch" clause.
ConfigPair config_pair;
ElementPtr mutable_cfg;
SrvConfigPtr srv_cfg;
try {
- // Get the staging configuration
+ // Get the staging configuration.
srv_cfg = CfgMgr::instance().getStagingCfg();
// This is a way to convert ConstElementPtr to ElementPtr.
// Relocate dhcp-ddns parameters that have moved to global scope.
// Rule is that a global value overrides the dhcp-ddns value, so
// we need to do this before we apply global defaults.
- // Note this is done for backward compatibilty.
+ // Note this is done for backward compatibility.
srv_cfg->moveDdnsParams(mutable_cfg);
// Set all default values if not specified by the user.
}
if (config_pair.first == "shared-networks") {
-
/// We need to create instance of SharedNetworks4ListParser
/// and parse the list of the shared networks into the
/// CfgSharedNetworks4 object. One additional step is then to
(config_pair.first == "ddns-qualifying-suffix") ||
(config_pair.first == "store-extended-info") ||
(config_pair.first == "statistic-default-sample-count") ||
- (config_pair.first == "statistic-default-sample-age")) {
+ (config_pair.first == "statistic-default-sample-age") ||
+ (config_pair.first == "enable-multi-threading") ||
+ (config_pair.first == "packet-thread-pool-size") ||
+ (config_pair.first == "packet-thread-queue-size")) {
CfgMgr::instance().getStagingCfg()->addConfiguredGlobal(config_pair.first,
config_pair.second);
continue;
-
}
// Nothing to configure for the user-context.
// defined as part of shared networks.
global_parser.sanityChecks(srv_cfg, mutable_cfg);
- // Validate D2 client confuguration.
+ // Validate D2 client configuration.
if (!d2_client_cfg) {
d2_client_cfg.reset(new D2ClientConfig());
}
cfg = CfgMgr::instance().getStagingCfg()->getD2ClientConfig();
CfgMgr::instance().setD2ClientConfig(cfg);
- // This occurs last as if it succeeds, there is no easy way
+ // This occurs last as if it succeeds, there is no easy way to
// revert it. As a result, the failure to commit a subsequent
// change causes problems when trying to roll back.
const HooksConfig& libraries =
catch (const isc::Exception& ex) {
LOG_ERROR(dhcp4_logger, DHCP4_PARSER_COMMIT_FAIL).arg(ex.what());
answer = isc::config::createAnswer(CONTROL_RESULT_ERROR, ex.what());
+ // An error occurred, so make sure to restore the original data.
rollback = true;
} catch (...) {
// For things like bad_cast in boost::lexical_cast
LOG_ERROR(dhcp4_logger, DHCP4_PARSER_COMMIT_EXCEPTION);
answer = isc::config::createAnswer(CONTROL_RESULT_ERROR, "undefined configuration"
" parsing error");
+ // An error occurred, so make sure to restore the original data.
rollback = true;
}
}
err << "during update from config backend database: " << ex.what();
LOG_ERROR(dhcp4_logger, DHCP4_PARSER_COMMIT_FAIL).arg(err.str());
answer = isc::config::createAnswer(CONTROL_RESULT_ERROR, err.str());
+ // An error occurred, so make sure to restore the original data.
rollback = true;
} catch (...) {
// For things like bad_cast in boost::lexical_cast
<< "undefined configuration parsing error";
LOG_ERROR(dhcp4_logger, DHCP4_PARSER_COMMIT_FAIL).arg(err.str());
answer = isc::config::createAnswer(CONTROL_RESULT_ERROR, err.str());
+ // An error occurred, so make sure to restore the original data.
rollback = true;
}
}
return (answer);
}
-int srv_thread_count = -1;
-
} // namespace dhcp
} // namespace isc
isc::data::ConstElementPtr config_set,
bool check_only = false);
-extern int srv_thread_count;
-
} // namespace dhcp
} // namespace isc
<< "], 0-65535 allowed." << endl;
usage();
} else {
- srv_thread_count = thread_count;
+ Dhcpv4Srv::srv_thread_count_ = thread_count;
}
break;
using namespace std;
namespace {
+
const char* PARSER_CONFIGS[] = {
// CONFIGURATION 0: one subnet with one pool, no user contexts
"{"
" \"subnet\": \"192.0.2.0/24\" } ],"
"\"valid-lifetime\": 4000 }";
-
ConstElementPtr json1;
ASSERT_NO_THROW(json1 = parseDHCP4(config_bogus1));
ConstElementPtr json2;
EXPECT_EQ(170, def->getCode());
EXPECT_EQ(OPT_STRING_TYPE, def->getType());
EXPECT_FALSE(def->getArrayType());
-
}
// Goal of this test is to verify that global option data is configured
testOption(*range2.first, 23, foo2_expected, sizeof(foo2_expected));
}
-
// Verify that empty option name is rejected in the configuration.
TEST_F(Dhcp4ParserTest, optionNameEmpty) {
// Empty option names not allowed.
" } ]"
"}";
-
ASSERT_NO_THROW(json = parseDHCP4(config));
extractConfig(config);
ASSERT_FALSE(desc2.option_);
}
-
// Tests of the hooks libraries configuration. All tests have the pre-
// condition (checked in the test fixture's SetUp() method) that no hooks
// libraries are loaded at the start of the tests.
return (buildHooksLibrariesConfig(libraries));
}
-
// The goal of this test is to verify the configuration of hooks libraries if
// none are specified.
TEST_F(Dhcp4ParserTest, NoHooksLibraries) {
EXPECT_TRUE(subnet->hasRelayAddress(IOAddress("192.0.3.124")));
}
-
// Goal of this test is to verify that multiple subnets can be configured
// with defined client classes.
TEST_F(Dhcp4ParserTest, classifySubnets) {
EXPECT_FALSE(hosts_cfg->get4(234, Host::IDENT_CIRCUIT_ID,
&circuit_id[0], circuit_id.size()));
-
// Repeat the test for the DUID based reservation in this subnet.
std::vector<uint8_t> duid_r(duid.rbegin(), duid.rend());
host = hosts_cfg->get4(542, Host::IDENT_DUID, &duid_r[0], duid_r.size());
EXPECT_EQ(Network::HR_OUT_OF_POOL, subnet->getHostReservationMode());
}
+/// Check that the multi-threading settings have a default value when not
+/// specified.
+TEST_F(Dhcp4ParserTest, multiThreadingDefaultSettings) {
+ ConstElementPtr status;
+
+ string config = "{ " + genIfaceConfig() + "," +
+ "\"subnet4\": [ ]"
+ "}";
+
+ ConstElementPtr json;
+ ASSERT_NO_THROW(json = parseDHCP4(config));
+ extractConfig(config);
+
+ EXPECT_NO_THROW(status = configureDhcp4Server(*srv_, json));
+
+ // returned value should be 0 (success)
+ checkResult(status, 0);
+
+ // The value of enable-multi-threading must be equal to the default value
+ // (false). The default value is defined in GLOBAL4_DEFAULTS in
+ // simple_parser4.cc.
+ EXPECT_EQ(false,
+ CfgMgr::instance().getStagingCfg()->getEnableMultiThreading());
+
+ // The value of packet-thread-pool-size must be equal to the default value
+ // (0). The default value is defined in GLOBAL4_DEFAULTS in
+ // simple_parser4.cc.
+ EXPECT_EQ(0, CfgMgr::instance().getStagingCfg()->getPktThreadPoolSize());
+
+ // The value of packet-thread-queue-size must be equal to the default value
+ // (4). The default value is defined in GLOBAL4_DEFAULTS in
+ // simple_parser4.cc.
+ EXPECT_EQ(4, CfgMgr::instance().getStagingCfg()->getPktThreadQueueSize());
+}
+
/// Check that the decline-probation-period has a default value when not
/// specified.
TEST_F(Dhcp4ParserTest, declineTimerDefault) {
checkResult(status, 0);
// The value of decline-probation-period must be equal to the
- // default value (86400). The default value is defined in GLOBAL6_DEFAULTS in
- // simple_parser6.cc.
+ // default value (86400). The default value is defined in GLOBAL4_DEFAULTS in
+ // simple_parser4.cc.
EXPECT_EQ(86400, CfgMgr::instance().getStagingCfg()->getDeclinePeriod());
}
EXPECT_EQ(0, CfgMgr::instance().getStagingCfg()->getDhcp4o6Port());
}
-
/// Check that the decline-probation-period value can be set properly.
TEST_F(Dhcp4ParserTest, declineTimer) {
ConstElementPtr status;
EXPECT_TRUE(errorContainsPosition(status, "<string>"));
}
-
// Checks if the DHCPv4 is able to parse the configuration without 4o6 parameters
// and does not set 4o6 fields at all.
TEST_F(Dhcp4ParserTest, 4o6default) {
checkResult(status, 1);
}
-
// Checks if the DHCPv4 is able to parse the configuration with 4o6 network
// interface defined.
TEST_F(Dhcp4ParserTest, 4o6iface) {
" } ] \n"
"} \n";
-
ConstElementPtr json;
ASSERT_NO_THROW(json = parseDHCP4(config));
extractConfig(config);
" \"pools\": [ { \"pool\": \"192.0.3.1-192.0.3.10\" } ]\n"
" }\n"
" ]\n"
-
" } ]\n"
"} \n";
// Fetch the queue control info.
staged_control = CfgMgr::instance().getStagingCfg()->getDHCPQueueControl();
+
// Make sure the staged queue config exists.
ASSERT_TRUE(staged_control);
+
// Now build the expected queue control content.
if (scenario.json_.empty()) {
exp_control = Element::createMap();
EXPECT_EQ("00:00:05",
util::durationToText(stats_mgr.getMaxSampleAgeDefault(), 0));
}
+
+/// Check that the multi threading settings can be set properly.
+TEST_F(Dhcp4ParserTest, multiThreadingSettings) {
+ ConstElementPtr status;
+
+ string config = "{ " + genIfaceConfig() + "," +
+ "\"enable-multi-threading\": true,"
+ "\"packet-thread-pool-size\": 256,"
+ "\"packet-thread-queue-size\": 256,"
+ "\"subnet4\": [ ]"
+ "}";
+
+ ConstElementPtr json;
+ ASSERT_NO_THROW(json = parseDHCP4(config));
+ extractConfig(config);
+
+ EXPECT_NO_THROW(status = configureDhcp4Server(*srv_, json));
+
+ // returned value should be 0 (success)
+ checkResult(status, 0);
+
+ // The value of multi-threading settings must be equal to the specified
+ // values
+ EXPECT_EQ(true,
+ CfgMgr::instance().getStagingCfg()->getEnableMultiThreading());
+ EXPECT_EQ(256,
+ CfgMgr::instance().getStagingCfg()->getPktThreadPoolSize());
+ EXPECT_EQ(256,
+ CfgMgr::instance().getStagingCfg()->getPktThreadQueueSize());
+}
}
"processCommand(\"config-set\", json)");
}
+ // command line parameters overwrite file and database configuration
bool enabled = false;
- if (srv_thread_count >= 0) {
+ if (Dhcpv6Srv::srv_thread_count_ >= 0) {
enabled = true;
}
if (enabled) {
- CfgMgr::instance().getCurrentCfg()->setServerThreadCount(srv_thread_count);
- CfgMgr::instance().getCurrentCfg()->setServerMaxThreadQueueSize(4);
+ CfgMgr::instance().getCurrentCfg()->setPktThreadPoolSize(Dhcpv6Srv::srv_thread_count_);
+ CfgMgr::instance().getCurrentCfg()->setPktThreadQueueSize(0);
LOG_FATAL(dhcp6_logger, DHCP6_MULTI_THREADING_WARNING);
+ } else {
+ enabled = CfgMgr::instance().getCurrentCfg()->getEnableMultiThreading();
}
MultiThreadingMgr::instance().apply(enabled,
- CfgMgr::instance().getCurrentCfg()->getServerThreadCount());
+ CfgMgr::instance().getCurrentCfg()->getPktThreadPoolSize());
// Now check is the returned result is successful (rcode=0) or not
// (see @ref isc::config::parseAnswer).
LOG_WARN(dhcp6_logger, DHCP6_MULTI_THREADING_INFO)
.arg(MultiThreadingMgr::instance().getMode() ? "yes" : "no")
.arg(MultiThreadingMgr::instance().getPktThreadPoolSize())
- .arg(CfgMgr::instance().getCurrentCfg()->getServerMaxThreadQueueSize());
+ .arg(CfgMgr::instance().getCurrentCfg()->getPktThreadQueueSize());
return (result);
}
}
}
-
\"parameters\" {
switch(driver.ctx_) {
case isc::dhcp::Parser6Context::HOOKS_LIBRARIES:
}
}
+\"enable-multi-threading\" {
+ switch(driver.ctx_) {
+ case isc::dhcp::Parser6Context::DHCP6:
+ return isc::dhcp::Dhcp6Parser::make_ENABLE_MULTI_THREADING(driver.loc_);
+ default:
+ return isc::dhcp::Dhcp6Parser::make_STRING("enable-multi-threading", driver.loc_);
+ }
+}
+
+\"packet-thread-pool-size\" {
+ switch(driver.ctx_) {
+ case isc::dhcp::Parser6Context::DHCP6:
+ return isc::dhcp::Dhcp6Parser::make_PACKET_THREAD_POOL_SIZE(driver.loc_);
+ default:
+ return isc::dhcp::Dhcp6Parser::make_STRING("packet-thread-pool-size", driver.loc_);
+ }
+}
+
+\"packet-thread-queue-size\" {
+ switch(driver.ctx_) {
+ case isc::dhcp::Parser6Context::DHCP6:
+ return isc::dhcp::Dhcp6Parser::make_PACKET_THREAD_QUEUE_SIZE(driver.loc_);
+ default:
+ return isc::dhcp::Dhcp6Parser::make_STRING("packet-thread-queue-size", driver.loc_);
+ }
+}
+
\"control-socket\" {
switch(driver.ctx_) {
case isc::dhcp::Parser6Context::DHCP6:
}
}
-
{JSONString} {
/* A string has been matched. It contains the actual string and single quotes.
We need to get those quotes out of the way and just use its content, e.g.
NULL_TYPE "null"
DHCP6 "Dhcp6"
+
DATA_DIRECTORY "data-directory"
CONFIG_CONTROL "config-control"
CONFIG_DATABASES "config-databases"
DHCP4O6_PORT "dhcp4o6-port"
+ ENABLE_MULTI_THREADING "enable-multi-threading"
+ PACKET_THREAD_POOL_SIZE "packet-thread-pool-size"
+ PACKET_THREAD_QUEUE_SIZE "packet-thread-queue-size"
+
CONTROL_SOCKET "control-socket"
SOCKET_TYPE "socket-type"
SOCKET_NAME "socket-name"
ctx.require("Dhcp6", ctx.loc2pos(@1), ctx.loc2pos(@4));
};
-// This represents top-level entries: Dhcp6, Dhcp4, DhcpDdns, Logging
+// This represents top-level entries: Control-agent, Dhcp6, Dhcp4,
+// DhcpDdns, Logging
global_objects: global_object
| global_objects COMMA global_object
;
| statistic_default_sample_count
| statistic_default_sample_age
| unknown_map_entry
+ | enable_multi_threading
+ | packet_thread_pool_size
+ | packet_thread_queue_size
;
data_directory: DATA_DIRECTORY {
ctx.stack_.back()->set("re-detect", b);
};
-
lease_database: LEASE_DATABASE {
ElementPtr i(new MapElement(ctx.loc2pos(@1)));
ctx.stack_.back()->set("lease-database", i);
ctx.leave();
};
+enable_multi_threading: ENABLE_MULTI_THREADING COLON BOOLEAN {
+ ElementPtr b(new BoolElement($3, ctx.loc2pos(@3)));
+ ctx.stack_.back()->set("enable-multi-threading", b);
+};
+
+packet_thread_pool_size: PACKET_THREAD_POOL_SIZE COLON INTEGER {
+ ElementPtr prf(new IntElement($3, ctx.loc2pos(@3)));
+ ctx.stack_.back()->set("packet-thread-pool-size", prf);
+};
+
+packet_thread_queue_size: PACKET_THREAD_QUEUE_SIZE COLON INTEGER {
+ ElementPtr prf(new IntElement($3, ctx.loc2pos(@3)));
+ ctx.stack_.back()->set("packet-thread-queue-size", prf);
+};
+
hooks_libraries: HOOKS_LIBRARIES {
ElementPtr l(new ListElement(ctx.loc2pos(@1)));
ctx.stack_.back()->set("hooks-libraries", l);
ctx.stack_.back()->set("rapid-commit", rc);
};
-
// ---- shared-networks ---------------------
shared_networks: SHARED_NETWORKS {
} pool_params RCURLY_BRACKET {
// The pool parameter is required.
ctx.require("pool", ctx.loc2pos(@1), ctx.loc2pos(@4));
+ // parsing completed
};
pool_params: pool_param
ctx.leave();
};
+
// --- dhcp-queue-control ---------------------------------------------
dhcp_queue_control: DHCP_QUEUE_CONTROL {
ctx.leave();
};
+
// JSON entries for Dhcp4 and DhcpDdns
dhcp4_json_object: DHCP4 {
const std::string Dhcpv6Srv::VENDOR_CLASS_PREFIX("VENDOR_CLASS_");
+int Dhcpv6Srv::srv_thread_count_ = -1;
+
Dhcpv6Srv::Dhcpv6Srv(uint16_t server_port, uint16_t client_port)
: io_service_(new IOService()), server_port_(server_port),
client_port_(client_port), serverid_(), shutdown_(true),
try {
bool read_pkt = true;
- // Do not read more packets from socket if there are enough
- // packets to be processed in the packet thread pool queue
- const int max_queue_size = CfgMgr::instance().getCurrentCfg()->getServerMaxThreadQueueSize();
+ // Do not read more packets from socket if there are enough packets to
+ // be processed in the packet thread pool queue
+ // max_queue_size = 0 means no limit
+ const int max_queue_size = CfgMgr::instance().getCurrentCfg()->getPktThreadQueueSize();
const int thread_count = MultiThreadingMgr::instance().getPktThreadPoolSize();
size_t pkt_queue_size = MultiThreadingMgr::instance().getPktThreadPool().count();
- if (thread_count && (pkt_queue_size >= thread_count * max_queue_size)) {
+ if (thread_count && max_queue_size && (pkt_queue_size >= thread_count * max_queue_size)) {
read_pkt = false;
}
uint16_t client_port_;
public:
+ /// @brief command line parameter thread count
+ /// when parameter is not specified, the default value is used
+ /// the default value is: -1 means disabled (single-threaded),
+ /// 0 means auto-detect, other values set thread count explicitly
+ static int srv_thread_count_;
+
/// @note used by DHCPv4-over-DHCPv6 so must be public and static
/// @brief Updates statistics for transmitted packets
#include <cc/command_interpreter.h>
#include <config/command_mgr.h>
#include <database/dbaccess_parser.h>
+#include <dhcp/iface_mgr.h>
#include <dhcp/libdhcp++.h>
-#include <dhcp6/json_config_parser.h>
#include <dhcp6/dhcp6_log.h>
#include <dhcp6/dhcp6_srv.h>
-#include <dhcp/iface_mgr.h>
+#include <dhcp6/json_config_parser.h>
#include <dhcpsrv/cb_ctl_dhcp4.h>
#include <dhcpsrv/cfg_option.h>
#include <dhcpsrv/cfgmgr.h>
#include <hooks/hooks_parser.h>
#include <log/logger_support.h>
#include <process/config_ctl_parser.h>
+
#include <util/encode/hex.h>
#include <util/strutil.h>
#include <boost/algorithm/string.hpp>
#include <boost/foreach.hpp>
#include <boost/lexical_cast.hpp>
-#include <boost/scoped_ptr.hpp>
-#include <boost/shared_ptr.hpp>
#include <iostream>
#include <limits>
#include <netinet/in.h>
#include <vector>
-#include <stdint.h>
-
using namespace std;
using namespace isc;
using namespace isc::data;
using namespace isc::dhcp;
using namespace isc::asiolink;
using namespace isc::hooks;
+using namespace isc::process;
+using namespace isc::config;
+using namespace isc::db;
namespace {
uint16_t dhcp4o6_port = getUint16(global, "dhcp4o6-port");
srv_config->setDhcp4o6Port(dhcp4o6_port);
+ // Set enable multi threading flag.
+ bool enable_multi_threading = getBoolean(global, "enable-multi-threading");
+ srv_config->setEnableMultiThreading(enable_multi_threading);
+
+ // Set packet thread pool size.
+ uint32_t packet_thread_pool_size = getUint32(global, "packet-thread-pool-size");
+ srv_config->setPktThreadPoolSize(packet_thread_pool_size);
+
+ // Set packet thread queue size.
+ uint32_t packet_thread_queue_size = getUint32(global, "packet-thread-queue-size");
+ srv_config->setPktThreadQueueSize(packet_thread_queue_size);
+
// Set the global user context.
ConstElementPtr user_context = global->get("user-context");
if (user_context) {
}
}
-
if (iface.empty()) {
iface = (*subnet)->getIface();
continue;
}
}
-
-
};
} // anonymous namespace
}
if (config_pair.first == "shared-networks") {
- /// We need to create instance of SharedNetworks4ListParser
+ /// We need to create instance of SharedNetworks6ListParser
/// and parse the list of the shared networks into the
- /// CfgSharedNetworks4 object. One additional step is then to
+ /// CfgSharedNetworks6 object. One additional step is then to
/// add subnets from the CfgSharedNetworks6 into CfgSubnets6
/// as well.
-
SharedNetworks6ListParser parser;
CfgSharedNetworks6Ptr cfg = srv_config->getCfgSharedNetworks6();
parser.parse(cfg, config_pair.second);
(config_pair.first == "ddns-qualifying-suffix") ||
(config_pair.first == "store-extended-info") ||
(config_pair.first == "statistic-default-sample-count") ||
- (config_pair.first == "statistic-default-sample-age")) {
+ (config_pair.first == "statistic-default-sample-age") ||
+ (config_pair.first == "enable-multi-threading") ||
+ (config_pair.first == "packet-thread-pool-size") ||
+ (config_pair.first == "packet-thread-queue-size")) {
CfgMgr::instance().getStagingCfg()->addConfiguredGlobal(config_pair.first,
config_pair.second);
continue;
// defined as part of shared networks.
global_parser.sanityChecks(srv_config, mutable_cfg);
- // Validate D2 client confuguration.
+ // Validate D2 client configuration.
if (!d2_client_cfg) {
d2_client_cfg.reset(new D2ClientConfig());
}
return (answer);
}
-int srv_thread_count = -1;
-
} // namespace dhcp
} // namespace isc
configureDhcp6Server(Dhcpv6Srv& server, isc::data::ConstElementPtr config_set,
bool check_only = false);
-extern int srv_thread_count;
-
} // namespace dhcp
} // namespace isc
<< "], 0-65535 allowed." << endl;
usage();
} else {
- srv_thread_count = thread_count;
+ Dhcpv6Srv::srv_thread_count_ = thread_count;
}
break;
/// @brief Create the simple configuration with single option.
///
/// This function allows to set one of the parameters that configure
- /// option value. These parameters are: "name", "code", "data" and
- /// "csv-format".
+ /// option value. These parameters are: "name", "code", "data",
+ /// "csv-format" and "space".
///
/// @param param_value string holding option parameter value to be
/// injected into the configuration string.
return (ReturnType());
}
-
/// @brief Test invalid option parameter value.
///
/// This test function constructs the simple configuration
ConstElementPtr status;
EXPECT_NO_THROW(status = configureDhcp6Server(srv_, json));
-
// returned value should be 0 (success)
checkResult(status, 0);
}
} while (++cnt < 10);
}
-// This checks that it is possible to assign arbitrary ids for subnets.
+// This test checks that it is possible to assign arbitrary ids for subnets.
TEST_F(Dhcp6ParserTest, multipleSubnetsExplicitIDs) {
ConstElementPtr x;
// Four subnets with arbitrary subnet ids.
EXPECT_TRUE(errorContainsPosition(x, "<string>"));
}
-
// Goal of this test is to verify that a previously configured subnet can be
// deleted in subsequent reconfiguration.
TEST_F(Dhcp6ParserTest, reconfigureRemoveSubnet) {
EXPECT_EQ(4, subnets->at(2)->getID());
}
-
-
// This test checks if it is possible to override global values
// on a per subnet basis.
TEST_F(Dhcp6ParserTest, subnetLocal) {
EXPECT_FALSE(subnet);
}
-
// This test checks if it is not allowed to define global interface
// parameter.
TEST_F(Dhcp6ParserTest, interfaceGlobal) {
EXPECT_THROW(parseDHCP6(config), Dhcp6ParseError);
}
-
// This test checks if it is possible to define a subnet with an
// interface-id option defined.
TEST_F(Dhcp6ParserTest, subnetInterfaceId) {
EXPECT_TRUE(selector.interface_id_->equals(subnet->getInterfaceId()));
}
-
// This test checks if it is not allowed to define global interface
// parameter.
TEST_F(Dhcp6ParserTest, interfaceIdGlobal) {
EXPECT_TRUE(subnets->at(0)->getPools(Lease::TYPE_PD).empty());
}
-
// Test verifies that a subnet with pool values that do not belong to that
// pool are rejected.
TEST_F(Dhcp6ParserTest, poolOutOfSubnet) {
" \"subnet\": \"2001:db8:1::/64\" } ],"
"\"valid-lifetime\": 4000 }";
-
ConstElementPtr json;
ASSERT_NO_THROW(json = parseDHCP6(config));
EXPECT_EQ(lastAddrInPrefix(prefixAddress, 64), p6->getLastAddress());
}
-
// Goal of this test is check for proper handling of invalid prefix delegation
// pool configuration. It uses an array of invalid configurations to check
// a variety of configuration errors.
checkResult(status, 0);
}
-
/// The goal of this test is to verify that the invalid encapsulated
/// option space name is not accepted.
TEST_F(Dhcp6ParserTest, optionDefInvalidEncapsulatedSpace) {
testOption(*range3.first, D6O_SUBSCRIBER_ID, subscriber_id_expected2,
sizeof(subscriber_id_expected2));
-
pool = subnet->getPool(Lease::TYPE_NA, IOAddress("2001:db8:1::300"));
ASSERT_TRUE(pool);
pool6 = boost::dynamic_pointer_cast<Pool6>(pool);
EXPECT_EQ("example.com.", optionCustom->readFqdn(4));
}
-
// This test checks if vendor options can be specified in the config file
// (in hex format), and later retrieved from configured subnet
TEST_F(Dhcp6ParserTest, vendorOptionsHex) {
// condition (checked in the test fixture's SetUp() method) that no hooks
// libraries are loaded at the start of the tests.
-
// Helper function to return a configuration containing an arbitrary number
// of hooks libraries.
std::string
return (buildHooksLibrariesConfig(libraries));
}
-
// The goal of this test is to verify the configuration of hooks libraries if
// none are specified.
TEST_F(Dhcp6ParserTest, NoHooksLibraries) {
}
-
// This test verifies that it is possible to select subset of interfaces on
// which server should listen.
TEST_F(Dhcp6ParserTest, selectedInterfaces) {
"\"renew-timer\": 1000, "
"\"valid-lifetime\": 4000 }";
-
ConstElementPtr json;
ASSERT_NO_THROW(json = parseDHCP6(config));
extractConfig(config);
"\"renew-timer\": 1000, "
"\"valid-lifetime\": 4000 }";
-
ConstElementPtr json;
ASSERT_NO_THROW(json = parseDHCP6(config));
extractConfig(config);
EXPECT_TRUE(test_config.socketOpen("eth1", AF_INET6));
}
-
// This test checks if it is possible to specify relay information
TEST_F(Dhcp6ParserTest, subnetRelayInfo) {
ASSERT_TRUE(opt_prf);
EXPECT_EQ(11, static_cast<int>(opt_prf->getValue()));
-
// The HW address used for one of the reservations in the subnet 542
// consists of numbers from 6 to 1. So, let's just reverse the order
// of the address from the previous test.
EXPECT_EQ(HWAddr::HWADDR_SOURCE_SUBSCRIBER_ID, sources[2]);
}
-
/// The goal of this test is to verify that empty MAC sources configuration
/// is rejected. If specified, this has to have at least one value.
TEST_F(Dhcp6ParserTest, macSourcesEmpty) {
EXPECT_NE(original_datadir, string(CfgMgr::instance().getDataDir()));
}
+/// Check that the multi-threading settings have a default value when not
+/// specified.
+TEST_F(Dhcp6ParserTest, multiThreadingDefaultSettings) {
+ ConstElementPtr status;
+
+ string config = "{ " + genIfaceConfig() + "," +
+ "\"subnet6\": [ ]"
+ "}";
+
+ ConstElementPtr json;
+ ASSERT_NO_THROW(json = parseDHCP6(config));
+ extractConfig(config);
+
+ EXPECT_NO_THROW(status = configureDhcp6Server(srv_, json));
+
+ // returned value should be 0 (success)
+ checkResult(status, 0);
+
+ // The value of enable-multi-threading must be equal to the default value
+ // (false). The default value is defined in GLOBAL6_DEFAULTS in
+ // simple_parser6.cc.
+ EXPECT_EQ(false,
+ CfgMgr::instance().getStagingCfg()->getEnableMultiThreading());
+
+ // The value of packet-thread-pool-size must be equal to the default value
+ // (0). The default value is defined in GLOBAL6_DEFAULTS in
+ // simple_parser6.cc.
+ EXPECT_EQ(0, CfgMgr::instance().getStagingCfg()->getPktThreadPoolSize());
+
+ // The value of packet-thread-queue-size must be equal to the default value
+ // (4). The default value is defined in GLOBAL6_DEFAULTS in
+ // simple_parser6.cc.
+ EXPECT_EQ(4, CfgMgr::instance().getStagingCfg()->getPktThreadQueueSize());
+}
+
/// Check that the decline-probation-period value has a default value if not
/// specified explicitly.
TEST_F(Dhcp6ParserTest, declineTimerDefault) {
// Verifies that simple list of valid classes parses and
// is staged for commit.
TEST_F(Dhcp6ParserTest, validClientClassDictionary) {
-
string config = "{ " + genIfaceConfig() + ","
"\"preferred-lifetime\": 3000, \n"
"\"rebind-timer\": 2000, \n"
EXPECT_EQ("", s->getIface().get());
}
-
// It is not allowed to have different values for interfaces names is subnets
// in the same shared network.
TEST_F(Dhcp6ParserTest, sharedNetworksInterfacesMixed) {
CfgSharedNetworks6Ptr cfg_net = CfgMgr::instance().getStagingCfg()
->getCfgSharedNetworks6();
- // Two shared networks are expeced.
+ // Two shared networks are expected.
ASSERT_TRUE(cfg_net);
const SharedNetwork6Collection* nets = cfg_net->getAll();
ASSERT_TRUE(nets);
ASSERT_TRUE(ctx_opt_desc->get("comment"));
EXPECT_EQ("\"Set option value\"", ctx_opt_desc->get("comment")->str());
- // And there there are some client classes.
+ // And there are some client classes.
const ClientClassDictionaryPtr& dict =
CfgMgr::instance().getStagingCfg()->getClientClassDictionary();
ASSERT_TRUE(dict);
registerBackendType(ConfigBackendDHCPv6Mgr::instance(),
"mysql"));
+ // Should parse ok, now that the factory has been registered.
configure(config, CONTROL_RESULT_SUCCESS, "");
// Make sure the config control info is there.
// Check whether it is possible to configure server-tag
TEST_F(Dhcp6ParserTest, serverTag) {
-
// Config without server-tag
string config_no_tag = "{ " + genIfaceConfig() + "," +
"\"subnet6\": [ ] "
"expecting boolean"
},
{
- "queue type not a string",
+ "queue enabled, type not a string",
"{ \n"
" \"enable-queue\": true, \n"
" \"queue-type\": 7777 \n"
util::durationToText(stats_mgr.getMaxSampleAgeDefault(), 0));
}
+/// Check that the multi threading settings can be set properly.
+TEST_F(Dhcp6ParserTest, multiThreadingSettings) {
+ ConstElementPtr status;
+
+ string config = "{ " + genIfaceConfig() + "," +
+ "\"enable-multi-threading\": true,"
+ "\"packet-thread-pool-size\": 256,"
+ "\"packet-thread-queue-size\": 256,"
+ "\"subnet6\": [ ]"
+ "}";
+
+ ConstElementPtr json;
+ ASSERT_NO_THROW(json = parseDHCP6(config));
+ extractConfig(config);
+
+ EXPECT_NO_THROW(status = configureDhcp6Server(srv_, json));
+
+ // returned value should be 0 (success)
+ checkResult(status, 0);
+
+ // The value of multi-threading settings must be equal to the specified
+ // values
+ EXPECT_EQ(true,
+ CfgMgr::instance().getStagingCfg()->getEnableMultiThreading());
+ EXPECT_EQ(256,
+ CfgMgr::instance().getStagingCfg()->getPktThreadPoolSize());
+ EXPECT_EQ(256,
+ CfgMgr::instance().getStagingCfg()->getPktThreadQueueSize());
+}
}
{ "ddns-qualifying-suffix", Element::string },
{ "store-extended-info", Element::boolean },
{ "statistic-default-sample-count", Element::integer },
- { "statistic-default-sample-age", Element::integer }
+ { "statistic-default-sample-age", Element::integer },
+ { "enable-multi-threading", Element::boolean },
+ { "packet-thread-pool-size", Element::integer },
+ { "packet-thread-queue-size", Element::integer }
};
/// @brief This table defines default global values for DHCPv4
{ "hostname-char-replacement", Element::string, "" },
{ "store-extended-info", Element::boolean, "false" },
{ "statistic-default-sample-count", Element::integer, "20" },
- { "statistic-default-sample-age", Element::integer, "0" }
+ { "statistic-default-sample-age", Element::integer, "0" },
+ { "enable-multi-threading", Element::boolean, "false" },
+ { "packet-thread-pool-size", Element::integer, "0" },
+ { "packet-thread-queue-size", Element::integer, "4" }
};
/// @brief This table defines all option definition parameters.
return (cnt);
}
-};
-};
+} // namespace dhcp
+} // namespace isc
{ "ddns-qualifying-suffix", Element::string },
{ "store-extended-info", Element::boolean },
{ "statistic-default-sample-count", Element::integer },
- { "statistic-default-sample-age", Element::integer }
+ { "statistic-default-sample-age", Element::integer },
+ { "enable-multi-threading", Element::boolean },
+ { "packet-thread-pool-size", Element::integer },
+ { "packet-thread-queue-size", Element::integer }
};
/// @brief This table defines default global values for DHCPv6
{ "hostname-char-replacement", Element::string, "" },
{ "store-extended-info", Element::boolean, "false" },
{ "statistic-default-sample-count", Element::integer, "20" },
- { "statistic-default-sample-age", Element::integer, "0" }
+ { "statistic-default-sample-age", Element::integer, "0" },
+ { "enable-multi-threading", Element::boolean, "false" },
+ { "packet-thread-pool-size", Element::integer, "0" },
+ { "packet-thread-queue-size", Element::integer, "4" }
};
/// @brief This table defines all option definition parameters.
return (cnt);
}
-};
-};
+} // namespace dhcp
+} // namespace isc
cfg_host_operations6_(CfgHostOperations::createConfig6()),
class_dictionary_(new ClientClassDictionary()),
decline_timer_(0), echo_v4_client_id_(true), dhcp4o6_port_(0),
- server_threads_(0),
- server_max_thread_queue_size_(0),
+ enable_multi_threading_(false),
+ pkt_thread_pool_size_(0), pkt_thread_queue_size_(0),
d2_client_config_(new D2ClientConfig()),
configured_globals_(Element::createMap()),
cfg_consist_(new CfgConsistency()) {
cfg_host_operations6_(CfgHostOperations::createConfig6()),
class_dictionary_(new ClientClassDictionary()),
decline_timer_(0), echo_v4_client_id_(true), dhcp4o6_port_(0),
- server_threads_(0),
- server_max_thread_queue_size_(0),
+ enable_multi_threading_(false),
+ pkt_thread_pool_size_(0), pkt_thread_queue_size_(0),
d2_client_config_(new D2ClientConfig()),
configured_globals_(Element::createMap()),
cfg_consist_(new CfgConsistency()) {
return (dhcp4o6_port_);
}
- /// @brief Sets the server thread count.
+ /// @brief Sets the enable multi threading flag.
///
- /// @param threads value of the server thread count
- void setServerThreadCount(uint32_t threads) {
- server_threads_ = threads;
+ /// @param size value of the enable multi threading flag
+ void setEnableMultiThreading(bool enabled) {
+ enable_multi_threading_ = enabled;
}
- /// @brief Retrieves the server thread count.
+ /// @brief Retrieves the enable multi threading flag.
///
- /// @return value of the server thread count
- uint32_t getServerThreadCount() const {
- return (server_threads_);
+ /// @return value of the enable multi threading flag
+ uint32_t getEnableMultiThreading() const {
+ return (enable_multi_threading_);
}
- /// @brief Sets the server max thread queue size.
+ /// @brief Sets the packet thread pool size.
///
- /// @param size max thread queue size
- void setServerMaxThreadQueueSize(uint32_t size) {
- server_max_thread_queue_size_ = size;
+ /// @param size value of the packet thread pool size
+ void setPktThreadPoolSize(uint32_t size) {
+ pkt_thread_pool_size_ = size;
}
- /// @brief Retrieves the server max thread queue size.
+ /// @brief Retrieves the packet thread pool size.
///
- /// @return value of the max thread queue size
- uint32_t getServerMaxThreadQueueSize() const {
- return (server_max_thread_queue_size_);
+ /// @return value of the packet thread pool size
+ uint32_t getPktThreadPoolSize() const {
+ return (pkt_thread_pool_size_);
+ }
+
+ /// @brief Sets the packet thread queue size.
+ ///
+ /// @param size value of the packet thread queue size
+ void setPktThreadQueueSize(uint32_t size) {
+ pkt_thread_queue_size_ = size;
+ }
+
+ /// @brief Retrieves the packet thread queue size.
+ ///
+ /// @return value of the packet thread queue size
+ uint32_t getPktThreadQueueSize() const {
+ return (pkt_thread_queue_size_);
}
/// @brief Returns pointer to the D2 client configuration
/// this socket is bound and connected to this port and port + 1
uint16_t dhcp4o6_port_;
- /// @brief The server thread count.
- uint32_t server_threads_;
+ /// @brief The enable multi threading flag.
+ bool enable_multi_threading_;
+
+ /// @brief The packet thread pool size.
+ uint32_t pkt_thread_pool_size_;
- /// @brief The server max thread queue size.
- uint32_t server_max_thread_queue_size_;
+ /// @brief The packet thread queue size.
+ uint32_t pkt_thread_queue_size_;
/// @brief Stores D2 client configuration
D2ClientConfigPtr d2_client_config_;