Commit 4dc3ba6b authored by Thomas Markwalder's avatar Thomas Markwalder
Browse files

[#42] Replaced use of QueueControl with ElementPtr

deleted:
    src/lib/dhcp/queue_control.cc
	src/lib/dhcp/queue_control.h
	src/lib/dhcp/tests/queue_control_unittest.cc

Updates is mulitple files
parent 90fd7ebf
......@@ -636,17 +636,17 @@ ControlledDhcpv4Srv::processConfig(isc::data::ConstElementPtr config) {
// Configure packet queue
try {
ConstQueueControlPtr qc;
data::ConstElementPtr qc;
qc = CfgMgr::instance().getStagingCfg()->getQueueControlInfo();
if (!qc) {
// For right now, we are maually constructing the default
// @todo For now we're manually constructing default queue config
// This probably needs to be built into the PQM?
QueueControl default_qc;
default_qc.setQueueType("kea-ring4");
default_qc.setCapacity(500);
data::ElementPtr default_qc = data::Element::createMap();
default_qc->set("queue-type", data::Element::create("kea-ring4"));
default_qc->set("capacity", data::Element::create(static_cast<long int>(500)));
PacketQueueMgr4::instance().createPacketQueue(default_qc);
} else {
PacketQueueMgr4::instance().createPacketQueue(*qc);
PacketQueueMgr4::instance().createPacketQueue(qc);
}
LOG_DEBUG(dhcp4_logger, DBG_DHCP4_BASIC, DHCP4_CONFIG_PACKET_QUEUE)
......
......@@ -383,8 +383,7 @@ configureDhcp4Server(Dhcpv4Srv& server, isc::data::ConstElementPtr config_set,
if (config_pair.first == "queue-control") {
QueueControlParser parser(AF_INET);
QueueControlPtr queue_control = parser.parse(config_pair.second);
srv_cfg->setQueueControlInfo(queue_control);
srv_cfg->setQueueControlInfo(parser.parse(config_pair.second));
continue;
}
......
......@@ -6364,7 +6364,7 @@ TEST_F(Dhcp4ParserTest, queueControl) {
"} \n";
// Let's check the default. It should be empty.
ConstQueueControlPtr control;
data::ConstElementPtr control;
control = CfgMgr::instance().getStagingCfg()->getQueueControlInfo();
ASSERT_FALSE(control);
......@@ -6380,17 +6380,14 @@ TEST_F(Dhcp4ParserTest, queueControl) {
configure(config_with_queue, CONTROL_RESULT_SUCCESS, "");
control = CfgMgr::instance().getStagingCfg()->getQueueControlInfo();
ASSERT_TRUE(control);
EXPECT_EQ(75, control->getCapacity());
EXPECT_FALSE(control->getContext());
// Clear the config
CfgMgr::instance().clear();
// Configuration with queue with context should be valid.
configure(config_with_context, CONTROL_RESULT_SUCCESS, "");
control = CfgMgr::instance().getStagingCfg()->getQueueControlInfo();
ASSERT_TRUE(control);
EXPECT_EQ(90, control->getCapacity());
EXPECT_TRUE(control->getContext());
}
// Check whether it is possible to configure server-tag
......
......@@ -55,7 +55,6 @@ libkea_dhcp___la_SOURCES += pkt_filter.h pkt_filter.cc
libkea_dhcp___la_SOURCES += pkt_filter6.h pkt_filter6.cc
libkea_dhcp___la_SOURCES += pkt_filter_inet.cc pkt_filter_inet.h
libkea_dhcp___la_SOURCES += pkt_filter_inet6.cc pkt_filter_inet6.h
libkea_dhcp___la_SOURCES += queue_control.cc queue_control.h
libkea_dhcp___la_SOURCES += socket_info.h
# Utilize Linux Packet Filtering on Linux.
......@@ -138,7 +137,6 @@ libkea_dhcp___include_HEADERS = \
pkt_filter6.h \
pkt_filter_inet.h \
pkt_filter_inet6.h \
queue_control.h \
protocol_util.h \
socket_info.h \
std_option_defs.h
......
......@@ -8,7 +8,6 @@
#define PACKET_QUEUE_H
#include <cc/data.h>
#include <dhcp/queue_control.h>
#include <dhcp/socket_info.h>
#include <dhcp/pkt4.h>
#include <dhcp/pkt6.h>
......
......@@ -7,6 +7,8 @@
#ifndef PACKET_QUEUE_MGR_H
#define PACKET_QUEUE_MGR_H
#include <cc/data.h>
#include <cc/simple_parser.h>
#include <dhcp/packet_queue.h>
#include <exceptions/exceptions.h>
#include <boost/shared_ptr.hpp>
......@@ -72,7 +74,7 @@ public:
///
/// Factory function returns a pointer to the instance of the configuration
/// backend created.
typedef std::function<PacketQueueTypePtr(const QueueControl&)> Factory;
typedef std::function<PacketQueueTypePtr(data::ConstElementPtr)> Factory;
/// @brief Constructor.
PacketQueueMgr()
......@@ -86,7 +88,7 @@ public:
/// in a hooks library. In such a case, this function should be called from
/// the @c load function in this library. When the queue impl is registered,
/// the server will use it when required by the configuration, i.e. a
/// user specifies it by name in "queue-control".
/// user specifies it in "queue-control:queue-type"
///
/// If the given queue type has already been registered, perhaps
/// by another hooks library, the PQM will refuse to register another
......@@ -139,32 +141,45 @@ public:
/// @brief Create an instance of a packet queue.
///
/// This method uses provided @c dbaccess string representing database
/// connection information to create an instance of the database
/// backend. If the specified backend type is not supported, i.e. there
/// is no relevant factory function registered, an exception is thrown.
/// Replace the current packet queue with a new one based on the
/// given configuration parameters. The set of parameters must
/// contain at least "queue-type". This value is used to locate
/// the registered queue factory to invoke to create the new queue.
///
/// @param dbaccess Database access string being a collection of
/// key=value pairs.
/// The factory is passed the parameters verbatim for its use in
/// creating the new queue. Factories are expected to throw exceptions
/// on creation failure. Note the existing queue is not altered or
/// replaced unless the new queue is successfully created.
///
/// @throw InvalidQueueType if the queue type requested is not supported
/// @throw InvalidQueueParameter if parameters is not map that contains
/// "queue-type", InvalidQueueType if the queue type requested is not
/// supported.
/// @throw Unexpected if the backend factory function returned NULL.
void createPacketQueue(const QueueControl& queue_control) {
void createPacketQueue(data::ConstElementPtr parameters) {
if (!parameters) {
isc_throw(Unexpected, "createPacketQueue - queue parameters is null");
}
// Get the database type to locate a factory function.
// easier if these are elements no?
std::string queue_type = queue_control.getQueueType();
std::string queue_type ;
try {
queue_type = data::SimpleParser::getString(parameters, "queue-type");
} catch (std::exception& ex) {
isc_throw(InvalidQueueParameter, "queue-type missing or invalid: " << ex.what());
}
// Look up the factory.
auto index = factories_.find(queue_type);
// No match?
// Punt if there is no matching factory.
if (index == factories_.end()) {
isc_throw(InvalidQueueType, "The type of the packet queue: '" <<
queue_type << "' is not supported");
}
queue_type << "' is not supported"); }
// Call the factory to create the new queue.
// Factories should throw InvalidQueueParameter if given
// bad values in the control.
auto new_queue = index->second(queue_control);
auto new_queue = index->second(parameters);
if (!new_queue) {
isc_throw(Unexpected, "Packet queue " << queue_type <<
" factory returned NULL");
......
......@@ -14,17 +14,25 @@ namespace dhcp {
PacketQueueMgr4::PacketQueueMgr4() {
// Register default queue factory
registerPacketQueueFactory("kea-ring4", [](const QueueControl& control)
registerPacketQueueFactory("kea-ring4", [](data::ConstElementPtr parameters)
-> PacketQueue4Ptr {
PacketQueue4Ptr queue(new PacketQueueRing4("kea-ring4", control.getCapacity()));
size_t capacity;
try {
capacity = data::SimpleParser::getInteger(parameters, "capacity");
} catch (const std::exception& ex) {
isc_throw(InvalidQueueParameter, "kea-ring4 factory:"
" 'capacity' parameter is missing/invalid: " << ex.what());
}
PacketQueue4Ptr queue(new PacketQueueRing4("kea-ring4", capacity));
return (queue);
});
QueueControl control;
control.setQueueType("kea-ring4");
// @todo default comes from ?
control.setCapacity(500);
createPacketQueue(control);
data::ElementPtr parameters = data::Element::createMap();
parameters->set("queue-type", data::Element::create("kea-ring4"));
parameters->set("capacity", data::Element::create(static_cast<long int>(500)));
createPacketQueue(parameters);
}
boost::scoped_ptr<PacketQueueMgr4>&
......
......@@ -27,7 +27,6 @@ namespace dhcp {
class PacketQueueMgr4 : public PacketQueueMgr<PacketQueue4Ptr>,
public boost::noncopyable {
public:
/// @brief virtual Destructor
virtual ~PacketQueueMgr4(){}
......
......@@ -14,17 +14,25 @@ namespace dhcp {
PacketQueueMgr6::PacketQueueMgr6() {
// Register default queue factory
registerPacketQueueFactory("kea-ring6", [](const QueueControl& control)
registerPacketQueueFactory("kea-ring6", [](data::ConstElementPtr parameters)
-> PacketQueue6Ptr {
PacketQueue6Ptr queue(new PacketQueueRing6("kea-ring6", control.getCapacity()));
size_t capacity;
try {
capacity = data::SimpleParser::getInteger(parameters, "capacity");
} catch (const std::exception& ex) {
isc_throw(InvalidQueueParameter, "kea-ring6 factory:"
" 'capacity' parameter is missing/invalid: " << ex.what());
}
PacketQueue6Ptr queue(new PacketQueueRing6("kea-ring6", capacity));
return (queue);
});
QueueControl control;
control.setQueueType("kea-ring6");
// @todo default comes from ?
control.setCapacity(500);
createPacketQueue(control);
data::ElementPtr parameters = data::Element::createMap();
parameters->set("queue-type", data::Element::create("kea-ring6"));
parameters->set("capacity", data::Element::create(static_cast<long int>(500)));
createPacketQueue(parameters);
}
boost::scoped_ptr<PacketQueueMgr6>&
......
// Copyright (C) 2018 Internet Systems Consortium, Inc. ("ISC")
//
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
#include <config.h>
#include <dhcp/queue_control.h>
using namespace isc::data;
namespace isc {
namespace dhcp {
QueueControl::QueueControl()
: queue_type_(""), capacity_(0) {
}
bool
QueueControl::equals(const QueueControl& other) const {
return (queue_type_ == other.queue_type_ &&
capacity_ == other.capacity_);
}
ElementPtr
QueueControl::toElement() const {
ElementPtr result = Element::createMap();
// Add "capacity"
result->set("queue-type", Element::create(queue_type_));
// Add "capacity"
result->set("capacity", Element::create(static_cast<long int>(capacity_)));
// Set user context
contextToElement(result);
return (result);
}
} // end of isc::dhcp namespace
} // end of isc namespace
// Copyright (C) 2018 Internet Systems Consortium, Inc. ("ISC")
//
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
#ifndef QUEUE_CONTROL_H
#define QUEUE_CONTROL_H
#include <cc/cfg_to_element.h>
#include <cc/user_context.h>
#include <boost/shared_ptr.hpp>
namespace isc {
namespace dhcp {
/// @brief Represents DHCP packet queue controls
///
/// This class manages the configurable parameters used to tailor the
/// behavior of DHCP packet queueing.
class QueueControl : public isc::data::UserContext, public isc::data::CfgToElement {
public:
/// @brief Constructor.
QueueControl();
/// @brief Destructor
~QueueControl(){};
/// @return true if objects are equal, false otherwise.
bool equals(const QueueControl& other) const;
/// @brief Fetches the queue type
///
/// @return string containg the queue type
std::string getQueueType() const {
return (queue_type_);
}
/// @brief Sets the queue type
///
/// @param queue_type new value for the queue type
void setQueueType(const std::string& queue_type) {
queue_type_ = queue_type;
}
/// @brief Fetches the maximum number of packets that the queue may hold.
///
/// @return the current capacity of the packet queue.
size_t getCapacity() const {
return (capacity_);
}
/// @brief Set the capacity of the DHCPv4 packet queue buffer.
///
/// Sets the maximum number of packets that the queue may hold.
///
/// @param capacity new value for the queue capacity
void setCapacity(const size_t capacity) {
capacity_ = capacity;
}
/// @brief Equality operator.
///
/// @param other Object to be compared with this object.
///
/// @return true if objects are equal, false otherwise.
bool operator==(const QueueControl& other) const {
return (equals(other));
}
/// @brief Inequality operator.
///
/// @param other Object to be compared with this object.
///
/// @return true if objects are not equal, false otherwise.
bool operator!=(const QueueControl& other) const {
return (!equals(other));
}
/// @brief Unparse a configuration object
///
/// @return a pointer to unparsed configuration
virtual isc::data::ElementPtr toElement() const;
private:
/// @brief Name of the queue type
/// This is the value used to uniquely identify/register
/// packet queue implementations
std::string queue_type_;
/// @brief A set of interface names specified by the user.
size_t capacity_;
};
/// @brief A pointer to the @c QueueControl .
typedef boost::shared_ptr<QueueControl> QueueControlPtr;
/// @brief A pointer to the const @c QueueControl.
typedef boost::shared_ptr<const QueueControl> ConstQueueControlPtr;
}
}
#endif // QUEUE_CONTROL_H
......@@ -84,7 +84,6 @@ libdhcp___unittests_SOURCES += pkt_filter_test_stub.cc pkt_filter_test_stub.h
libdhcp___unittests_SOURCES += pkt_filter6_test_stub.cc pkt_filter_test_stub.h
libdhcp___unittests_SOURCES += pkt_filter_test_utils.h pkt_filter_test_utils.cc
libdhcp___unittests_SOURCES += pkt_filter6_test_utils.h pkt_filter6_test_utils.cc
libdhcp___unittests_SOURCES += queue_control_unittest.cc
# Utilize Linux Packet Filtering on Linux.
if OS_LINUX
......
......@@ -15,6 +15,7 @@
using namespace std;
using namespace isc;
using namespace isc::dhcp;
using namespace isc::dhcp::test;
namespace {
......
......@@ -16,6 +16,7 @@
using namespace std;
using namespace isc;
using namespace isc::dhcp;
using namespace isc::dhcp::test;
namespace {
......
......@@ -15,6 +15,15 @@
using namespace std;
using namespace isc;
using namespace isc::dhcp;
using namespace isc::dhcp::test;
data::ElementPtr
isc::dhcp::test::makeQueueConfig(const std::string& queue_type, size_t capacity) {
data::ElementPtr config = data::Element::createMap();
config->set("queue-type", data::Element::create(queue_type));
config->set("capacity", data::Element::create(static_cast<long int>(capacity)));
return (config);
}
namespace {
......@@ -32,10 +41,25 @@ public:
bool addCustomQueueType(const std::string& queue_type) {
bool did_it =
mgr().registerPacketQueueFactory(queue_type,
[](const QueueControl& control)
[](data::ConstElementPtr parameters)
-> PacketQueue4Ptr {
return (PacketQueue4Ptr(new PacketQueueRing4(control.getQueueType(),
control.getCapacity())));
std::string queue_type ;
try {
queue_type = data::SimpleParser::getString(parameters, "queue-type");
} catch (std::exception& ex) {
isc_throw(InvalidQueueParameter,
"queue-type missing or invalid: " << ex.what());
}
size_t capacity;
try {
capacity = data::SimpleParser::getInteger(parameters, "capacity");
} catch (const std::exception& ex) {
isc_throw(InvalidQueueParameter,
"'capacity' missing or invalid: " << ex.what());
}
return (PacketQueue4Ptr(new PacketQueueRing4(queue_type, capacity)));
});
return did_it;
......@@ -56,12 +80,10 @@ TEST_F(PacketQueueMgr4Test, defaultQueue) {
// Verify that we have a default queue and its info is correct.
checkMyInfo("{ \"capacity\": 500, \"queue-type\": \"kea-ring4\", \"size\": 0 }");
QueueControl control;
control.setQueueType("kea-ring4");
control.setCapacity(2000);
data::ConstElementPtr config = makeQueueConfig("kea-ring4", 2000);
// Verify that we can replace the default queue with different capacity queue
ASSERT_NO_THROW(mgr().createPacketQueue(control));
ASSERT_NO_THROW(mgr().createPacketQueue(config));
checkMyInfo("{ \"capacity\": 2000, \"queue-type\": \"kea-ring4\", \"size\": 0 }");
// We should be able to recreate the manager.
......@@ -72,12 +94,10 @@ TEST_F(PacketQueueMgr4Test, defaultQueue) {
}
TEST_F(PacketQueueMgr4Test, customQueueType) {
QueueControl control;
control.setQueueType("custom-queue");
control.setCapacity(2000);
// Verify that we cannot create a queue for a non-existant type
ASSERT_THROW(mgr().createPacketQueue(control), InvalidQueueType);
data::ConstElementPtr config = makeQueueConfig("custom-queue", 2000);
ASSERT_THROW(mgr().createPacketQueue(config), InvalidQueueType);
// Register our adjustable-type factory
ASSERT_TRUE(addCustomQueueType("custom-queue"));
......@@ -86,7 +106,7 @@ TEST_F(PacketQueueMgr4Test, customQueueType) {
checkMyInfo("{ \"capacity\": 500, \"queue-type\": \"kea-ring4\", \"size\": 0 }");
// Verify that we can replace the default queue with a "custom-queue" queue
ASSERT_NO_THROW(mgr().createPacketQueue(control));
ASSERT_NO_THROW(mgr().createPacketQueue(config));
checkMyInfo("{ \"capacity\": 2000, \"queue-type\": \"custom-queue\", \"size\": 0 }");
// Now unregister the factory.
......@@ -96,11 +116,11 @@ TEST_F(PacketQueueMgr4Test, customQueueType) {
checkMyInfo("{ \"capacity\": 2000, \"queue-type\": \"custom-queue\", \"size\": 0 }");
// Try and recreate the custom queue, type should be invalid.
ASSERT_THROW(mgr().createPacketQueue(control), InvalidQueueType);
ASSERT_THROW(mgr().createPacketQueue(config), InvalidQueueType);
// Verify we can create a default type queue.
control.setQueueType("kea-ring4");
ASSERT_NO_THROW(mgr().createPacketQueue(control));
// Verify we can create a default type queue with non-default capacity.
config = makeQueueConfig("kea-ring4", 2000);
ASSERT_NO_THROW(mgr().createPacketQueue(config));
checkMyInfo("{ \"capacity\": 2000, \"queue-type\": \"kea-ring4\", \"size\": 0 }");
}
......
......@@ -7,6 +7,7 @@
#include <config.h>
#include <dhcp/packet_queue_mgr6.h>
#include <packet_queue_testutils.h>
#include <boost/shared_ptr.hpp>
#include <gtest/gtest.h>
......@@ -14,6 +15,7 @@
using namespace std;
using namespace isc;
using namespace isc::dhcp;
using namespace isc::dhcp::test;
namespace {
......@@ -31,10 +33,25 @@ public:
bool addCustomQueueType(const std::string& queue_type) {
bool did_it =
mgr().registerPacketQueueFactory(queue_type,
[](const QueueControl& control)
[](data::ConstElementPtr parameters)
-> PacketQueue6Ptr {
return (PacketQueue6Ptr(new PacketQueueRing6(control.getQueueType(),
control.getCapacity())));
std::string queue_type ;
try {
queue_type = data::SimpleParser::getString(parameters, "queue-type");
} catch (std::exception& ex) {
isc_throw(InvalidQueueParameter,
"queue-type missing or invalid: " << ex.what());
}
size_t capacity;
try {
capacity = data::SimpleParser::getInteger(parameters, "capacity");
} catch (const std::exception& ex) {
isc_throw(InvalidQueueParameter,
"'capacity' missing or invalid: " << ex.what());
}
return (PacketQueue6Ptr(new PacketQueueRing6(queue_type, capacity)));
});
return did_it;
......@@ -44,17 +61,8 @@ public:
return (PacketQueueMgr6::instance());
};
void checkInfo(const std::string& exp_json) {
// Fetch the queue info and verify it has all the expected values.
ASSERT_TRUE(mgr().getPacketQueue()) << " no packet queue!";
data::ElementPtr info;
ASSERT_NO_THROW(info = mgr().getPacketQueue()->getInfo());
ASSERT_TRUE(info);
data::ElementPtr exp_elems;
ASSERT_NO_THROW(exp_elems = data::Element::fromJSON(exp_json))
<< " exp_elems is invalid JSON : " << exp_json
<< " test is broken";
EXPECT_TRUE(exp_elems->equals(*info));
void checkMyInfo(const std::string& exp_json) {
checkInfo((mgr().getPacketQueue()), exp_json);
}
};
......@@ -62,54 +70,50 @@ public:
TEST_F(PacketQueueMgr6Test, defaultQueue) {
// Verify that we have a default queue and its info is correct.
checkInfo("{ \"capacity\": 500, \"queue-type\": \"kea-ring6\", \"size\": 0 }");
checkMyInfo("{ \"capacity\": 500, \"queue-type\": \"kea-ring6\", \"size\": 0 }");
QueueControl control;
control.setQueueType("kea-ring6");
control.setCapacity(2000);
data::ConstElementPtr config = makeQueueConfig("kea-ring6", 2000);
// Verify that we can replace the default queue with different capacity queue
ASSERT_NO_THROW(mgr().createPacketQueue(control));
checkInfo("{ \"capacity\": 2000, \"queue-type\": \"kea-ring6\", \"size\": 0 }");
ASSERT_NO_THROW(mgr().createPacketQueue(config));
checkMyInfo("{ \"capacity\": 2000, \"queue-type\": \"kea-ring6\", \"