mirror of
https://gitlab.isc.org/isc-projects/kea
synced 2025-08-31 14:05:33 +00:00
[3795] Packet statistics implemented for DHCPv6
This commit is contained in:
@@ -80,6 +80,7 @@ kea_dhcp6_LDADD += $(top_builddir)/src/lib/util/libkea-util.la
|
||||
kea_dhcp6_LDADD += $(top_builddir)/src/lib/hooks/libkea-hooks.la
|
||||
kea_dhcp6_LDADD += $(top_builddir)/src/lib/cryptolink/libkea-cryptolink.la
|
||||
kea_dhcp6_LDADD += $(top_builddir)/src/bin/cfgrpt/libcfgrpt.la
|
||||
kea_dhcp6_LDADD += $(top_builddir)/src/lib/stats/libkea-stats.la
|
||||
|
||||
kea_dhcp6dir = $(pkgdatadir)
|
||||
kea_dhcp6_DATA = dhcp6.spec
|
||||
|
@@ -45,6 +45,7 @@
|
||||
#include <hooks/callout_handle.h>
|
||||
#include <hooks/hooks_log.h>
|
||||
#include <hooks/hooks_manager.h>
|
||||
#include <stats/stats_mgr.h>
|
||||
|
||||
#include <util/encode/hex.h>
|
||||
#include <util/io_utilities.h>
|
||||
@@ -330,6 +331,13 @@ bool Dhcpv6Srv::run() {
|
||||
.arg(query->getLocalPort())
|
||||
.arg(query->getIface());
|
||||
|
||||
// Log reception of the packet. We need to increase it early, as
|
||||
// any failures in unpacking will cause the packet to be dropped.
|
||||
// we will increase type specific packets further down the road.
|
||||
// See processStatsReceived().
|
||||
isc::stats::StatsMgr::instance().addValue("pkt6-received",
|
||||
static_cast<int64_t>(1));
|
||||
|
||||
} else {
|
||||
LOG_DEBUG(packet_logger, DBG_DHCP6_DETAIL, DHCP6_BUFFER_WAIT_INTERRUPTED)
|
||||
.arg(timeout);
|
||||
@@ -431,12 +439,26 @@ bool Dhcpv6Srv::run() {
|
||||
.arg(query->getLocalAddr().toText())
|
||||
.arg(query->getIface())
|
||||
.arg(e.what());
|
||||
|
||||
// Increase the statistics of parse failues and dropped packets.
|
||||
isc::stats::StatsMgr::instance().addValue("pkt6-parse-failed",
|
||||
static_cast<int64_t>(1));
|
||||
isc::stats::StatsMgr::instance().addValue("pkt6-receive-drop",
|
||||
static_cast<int64_t>(1));
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
// Update statistics accordingly for received packet.
|
||||
processStatsReceived(query);
|
||||
|
||||
// Check if received query carries server identifier matching
|
||||
// server identifier being used by the server.
|
||||
if (!testServerID(query)) {
|
||||
|
||||
// Increase the statistic of dropped packets.
|
||||
isc::stats::StatsMgr::instance().addValue("pkt6-receive-drop",
|
||||
static_cast<int64_t>(1));
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -444,6 +466,10 @@ bool Dhcpv6Srv::run() {
|
||||
// The Solicit, Confirm, Rebind and Information Request will be
|
||||
// discarded if sent to unicast address.
|
||||
if (!testUnicast(query)) {
|
||||
|
||||
// Increase the statistic of dropped packets.
|
||||
isc::stats::StatsMgr::instance().addValue("pkt6-receive-drop",
|
||||
static_cast<int64_t>(1));
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -541,6 +567,10 @@ bool Dhcpv6Srv::run() {
|
||||
.arg(query->getRemoteAddr().toText())
|
||||
.arg(e.what());
|
||||
|
||||
// Increase the statistic of dropped packets.
|
||||
isc::stats::StatsMgr::instance().addValue("pkt6-receive-drop",
|
||||
static_cast<int64_t>(1));
|
||||
|
||||
} catch (const isc::Exception& e) {
|
||||
|
||||
// Catch-all exception (at least for ones based on the isc Exception
|
||||
@@ -553,6 +583,10 @@ bool Dhcpv6Srv::run() {
|
||||
.arg(query->getName())
|
||||
.arg(query->getRemoteAddr().toText())
|
||||
.arg(e.what());
|
||||
|
||||
// Increase the statistic of dropped packets.
|
||||
isc::stats::StatsMgr::instance().addValue("pkt6-receive-drop",
|
||||
static_cast<int64_t>(1));
|
||||
}
|
||||
|
||||
if (rsp) {
|
||||
@@ -665,6 +699,10 @@ bool Dhcpv6Srv::run() {
|
||||
.arg(static_cast<int>(rsp->getType())).arg(rsp->toText());
|
||||
|
||||
sendPacket(rsp);
|
||||
|
||||
// Update statistics accordingly for sent packet.
|
||||
processStatsSent(rsp);
|
||||
|
||||
} catch (const std::exception& e) {
|
||||
LOG_ERROR(packet_logger, DHCP6_PACKET_SEND_FAIL)
|
||||
.arg(e.what());
|
||||
@@ -2898,5 +2936,77 @@ void Dhcpv6Srv::processRSOO(const Pkt6Ptr& query, const Pkt6Ptr& rsp) {
|
||||
}
|
||||
}
|
||||
|
||||
void Dhcpv6Srv::processStatsReceived(const Pkt6Ptr& query) {
|
||||
// Note that we're not bumping pkt4-received statistic as it was
|
||||
// increased early in the packet reception code.
|
||||
|
||||
string stat_name = "pkt6-unknown-received";
|
||||
switch (query->getType()) {
|
||||
case DHCPV6_SOLICIT:
|
||||
stat_name = "pkt6-solicit-received";
|
||||
break;
|
||||
case DHCPV6_ADVERTISE:
|
||||
// Should not happen, but let's keep a counter for it
|
||||
stat_name = "pkt6-advertise-received";
|
||||
break;
|
||||
case DHCPV6_REQUEST:
|
||||
stat_name = "pkt6-request-received";
|
||||
break;
|
||||
case DHCPV6_CONFIRM:
|
||||
stat_name = "pkt6-confirm-received";
|
||||
break;
|
||||
case DHCPV6_RENEW:
|
||||
stat_name = "pkt6-renew-received";
|
||||
break;
|
||||
case DHCPV6_REBIND:
|
||||
stat_name = "pkt6-rebind-received";
|
||||
break;
|
||||
case DHCPV6_REPLY:
|
||||
// Should not happen, but let's keep a counter for it
|
||||
stat_name = "pkt6-reply-received";
|
||||
break;
|
||||
case DHCPV6_RELEASE:
|
||||
stat_name = "pkt6-release-received";
|
||||
break;
|
||||
case DHCPV6_DECLINE:
|
||||
stat_name = "pkt6-decline-received";
|
||||
break;
|
||||
case DHCPV6_RECONFIGURE:
|
||||
stat_name = "pkt6-reconfigure-received";
|
||||
break;
|
||||
case DHCPV6_INFORMATION_REQUEST:
|
||||
stat_name = "pkt6-infrequest-received";
|
||||
break;
|
||||
default:
|
||||
; // do nothing
|
||||
}
|
||||
|
||||
isc::stats::StatsMgr::instance().addValue(stat_name,
|
||||
static_cast<int64_t>(1));
|
||||
}
|
||||
|
||||
void Dhcpv6Srv::processStatsSent(const Pkt6Ptr& response) {
|
||||
// Increase generic counter for sent packets.
|
||||
isc::stats::StatsMgr::instance().addValue("pkt6-sent",
|
||||
static_cast<int64_t>(1));
|
||||
|
||||
// Increase packet type specific counter for packets sent.
|
||||
string stat_name;
|
||||
switch (response->getType()) {
|
||||
case DHCPV6_ADVERTISE:
|
||||
stat_name = "pkt6-advertise-sent";
|
||||
break;
|
||||
case DHCPV6_REPLY:
|
||||
stat_name = "pkt6-reply-sent";
|
||||
break;
|
||||
default:
|
||||
// That should never happen
|
||||
return;
|
||||
}
|
||||
|
||||
isc::stats::StatsMgr::instance().addValue(stat_name,
|
||||
static_cast<int64_t>(1));
|
||||
}
|
||||
|
||||
};
|
||||
};
|
||||
|
@@ -740,6 +740,14 @@ private:
|
||||
Lease6Ptr& new_lease, const std::string& hostname,
|
||||
bool do_fwd, bool do_rev);
|
||||
|
||||
/// @brief Updates statistics for received packets
|
||||
/// @param query packet received
|
||||
static void processStatsReceived(const Pkt6Ptr& query);
|
||||
|
||||
/// @brief Updates statistics for transmitted packets
|
||||
/// @param query packet transmitted
|
||||
static void processStatsSent(const Pkt6Ptr& response);
|
||||
|
||||
/// @brief Allocation Engine.
|
||||
/// Pointer to the allocation engine that we are currently using
|
||||
/// It must be a pointer, because we will support changing engines
|
||||
|
@@ -109,6 +109,8 @@ dhcp6_unittests_LDADD += $(top_builddir)/src/lib/log/libkea-log.la
|
||||
dhcp6_unittests_LDADD += $(top_builddir)/src/lib/util/libkea-util.la
|
||||
dhcp6_unittests_LDADD += $(top_builddir)/src/lib/util/io/libkea-util-io.la
|
||||
dhcp6_unittests_LDADD += $(top_builddir)/src/bin/cfgrpt/libcfgrpt.la
|
||||
dhcp6_unittests_LDADD += $(top_builddir)/src/lib/stats/libkea-stats.la
|
||||
|
||||
endif
|
||||
|
||||
noinst_PROGRAMS = $(TESTS)
|
||||
|
@@ -37,7 +37,7 @@
|
||||
#include <dhcpsrv/utils.h>
|
||||
#include <util/buffer.h>
|
||||
#include <util/range_utilities.h>
|
||||
#include <hooks/server_hooks.h>
|
||||
#include <stats/stats_mgr.h>
|
||||
|
||||
#include <dhcp6/tests/dhcp6_test_utils.h>
|
||||
#include <dhcp6/tests/dhcp6_client.h>
|
||||
@@ -58,7 +58,6 @@ using namespace isc::asiolink;
|
||||
using namespace isc::dhcp;
|
||||
using namespace isc::dhcp::test;
|
||||
using namespace isc::util;
|
||||
using namespace isc::hooks;
|
||||
using namespace std;
|
||||
|
||||
namespace {
|
||||
@@ -2326,6 +2325,87 @@ TEST_F(Dhcpv6SrvTest, rsooOverride) {
|
||||
ASSERT_EQ(1, opt->getData().size());
|
||||
}
|
||||
|
||||
// Test checks if pkt6-advertise-received is bumped up correctly.
|
||||
// Note that in properly configured network the server never receives Advertise
|
||||
// messages.
|
||||
TEST_F(Dhcpv6SrvTest, receiveAdvertiseStat) {
|
||||
testReceiveStats(DHCPV6_ADVERTISE, "pkt6-advertise-received");
|
||||
}
|
||||
|
||||
// Test checks if pkt6-reply-received is bumped up correctly.
|
||||
// Note that in properly configured network the server never receives Reply
|
||||
// messages.
|
||||
TEST_F(Dhcpv6SrvTest, receiveReplyStat) {
|
||||
testReceiveStats(DHCPV6_ADVERTISE, "pkt6-advertise-received");
|
||||
}
|
||||
|
||||
// Test checks if pkt6-unknown-received is bumped up correctly.
|
||||
TEST_F(Dhcpv6SrvTest, receiveUnknownStat) {
|
||||
testReceiveStats(123, "pkt6-unknown-received");
|
||||
}
|
||||
|
||||
// Test checks if pkt6-renew-received is bumped up correctly.
|
||||
TEST_F(Dhcpv6SrvTest, receiveRenewStat) {
|
||||
testReceiveStats(DHCPV6_RENEW, "pkt6-renew-received");
|
||||
}
|
||||
|
||||
// Test checks if pkt6-rebind-received is bumped up correctly.
|
||||
TEST_F(Dhcpv6SrvTest, receiveRebindStat) {
|
||||
testReceiveStats(DHCPV6_REBIND, "pkt6-rebind-received");
|
||||
}
|
||||
|
||||
// Test checks if pkt6-release-received is bumped up correctly.
|
||||
TEST_F(Dhcpv6SrvTest, receiveReleaseStat) {
|
||||
testReceiveStats(DHCPV6_RELEASE, "pkt6-release-received");
|
||||
}
|
||||
|
||||
// Test checks if pkt6-decline-received is bumped up correctly.
|
||||
TEST_F(Dhcpv6SrvTest, receiveDeclineStat) {
|
||||
testReceiveStats(DHCPV6_DECLINE, "pkt6-decline-received");
|
||||
}
|
||||
|
||||
// Test checks if reception of a malformed packet increases pkt-parse-failed
|
||||
// and pkt6-receive-drop
|
||||
TEST_F(Dhcpv6SrvTest, receiveParseFailedStat) {
|
||||
using namespace isc::stats;
|
||||
StatsMgr& mgr = StatsMgr::instance();
|
||||
NakedDhcpv6Srv srv(0);
|
||||
|
||||
// Let's get a simple SOLICIT...
|
||||
Pkt6Ptr pkt = PktCaptures::captureSimpleSolicit();
|
||||
|
||||
// And pretend it's packet is only 3 bytes long.
|
||||
pkt->data_.resize(3);
|
||||
|
||||
// Check that those statistics are not set before the test
|
||||
ObservationPtr pkt6_rcvd = mgr.getObservation("pkt6-received");
|
||||
ObservationPtr parse_fail = mgr.getObservation("pkt6-parse-failed");
|
||||
ObservationPtr recv_drop = mgr.getObservation("pkt6-receive-drop");
|
||||
EXPECT_FALSE(pkt6_rcvd);
|
||||
EXPECT_FALSE(parse_fail);
|
||||
EXPECT_FALSE(recv_drop);
|
||||
|
||||
// Simulate that we have received that traffic
|
||||
srv.fakeReceive(pkt);
|
||||
|
||||
// Server will now process to run its normal loop, but instead of calling
|
||||
// IfaceMgr::receive6(), it will read all packets from the list set by
|
||||
// fakeReceive()
|
||||
srv.run();
|
||||
|
||||
// All expected statstics must be present.
|
||||
pkt6_rcvd = mgr.getObservation("pkt6-received");
|
||||
parse_fail = mgr.getObservation("pkt6-parse-failed");
|
||||
recv_drop = mgr.getObservation("pkt6-receive-drop");
|
||||
ASSERT_TRUE(pkt6_rcvd);
|
||||
ASSERT_TRUE(parse_fail);
|
||||
ASSERT_TRUE(recv_drop);
|
||||
|
||||
// They also must have expected values.
|
||||
EXPECT_EQ(1, pkt6_rcvd->getInteger().first);
|
||||
EXPECT_EQ(1, parse_fail->getInteger().first);
|
||||
EXPECT_EQ(1, recv_drop->getInteger().first);
|
||||
}
|
||||
|
||||
/// @todo: Add more negative tests for processX(), e.g. extend sanityCheck() test
|
||||
/// to call processX() methods.
|
||||
|
@@ -17,8 +17,10 @@
|
||||
#include <dhcp/option6_status_code.h>
|
||||
#include <dhcp6/tests/dhcp6_test_utils.h>
|
||||
#include <dhcp6/json_config_parser.h>
|
||||
#include <dhcp/tests/pkt_captures.h>
|
||||
#include <util/pointer_util.h>
|
||||
#include <cc/command_interpreter.h>
|
||||
#include <stats/stats_mgr.h>
|
||||
#include <string.h>
|
||||
|
||||
using namespace isc::data;
|
||||
@@ -28,6 +30,8 @@ using namespace isc::asiolink;
|
||||
namespace isc {
|
||||
namespace test {
|
||||
|
||||
const char* NakedDhcpv6SrvTest::DUID_FILE = "server-id-test.txt";
|
||||
|
||||
Dhcpv6SrvTest::Dhcpv6SrvTest()
|
||||
:srv_(0) {
|
||||
subnet_ = isc::dhcp::Subnet6Ptr
|
||||
@@ -741,6 +745,44 @@ Dhcpv6SrvTest::testReleaseReject(Lease::Type type, const IOAddress& addr) {
|
||||
EXPECT_TRUE(LeaseMgrFactory::instance().deleteLease(addr));
|
||||
}
|
||||
|
||||
void
|
||||
Dhcpv6SrvTest::testReceiveStats(uint8_t pkt_type, const std::string& stat_name) {
|
||||
|
||||
using namespace isc::stats;
|
||||
StatsMgr& mgr = StatsMgr::instance();
|
||||
NakedDhcpv6Srv srv(0);
|
||||
|
||||
// Let's get a simple SOLICIT...
|
||||
Pkt6Ptr pkt = PktCaptures::captureSimpleSolicit();
|
||||
|
||||
// And pretend it's packet of a different type
|
||||
pkt->data_[0] = pkt_type;
|
||||
|
||||
// Check that those statistics are not set before the test
|
||||
ObservationPtr pkt6_rcvd = mgr.getObservation("pkt6-received");
|
||||
ObservationPtr tested_stat = mgr.getObservation(stat_name);
|
||||
EXPECT_FALSE(pkt6_rcvd);
|
||||
EXPECT_FALSE(tested_stat);
|
||||
|
||||
// Simulate that we have received that traffic
|
||||
srv.fakeReceive(pkt);
|
||||
|
||||
// Server will now process to run its normal loop, but instead of calling
|
||||
// IfaceMgr::receive6(), it will read all packets from the list set by
|
||||
// fakeReceive()
|
||||
srv.run();
|
||||
|
||||
// All expected statstics must be present.
|
||||
pkt6_rcvd = mgr.getObservation("pkt6-received");
|
||||
tested_stat = mgr.getObservation(stat_name);
|
||||
ASSERT_TRUE(pkt6_rcvd);
|
||||
ASSERT_TRUE(tested_stat);
|
||||
|
||||
// They also must have expected values.
|
||||
EXPECT_EQ(1, pkt6_rcvd->getInteger().first);
|
||||
EXPECT_EQ(1, tested_stat->getInteger().first);
|
||||
}
|
||||
|
||||
void
|
||||
Dhcpv6SrvTest::configure(const std::string& config) {
|
||||
configure(config, srv_);
|
||||
@@ -761,6 +803,48 @@ Dhcpv6SrvTest::configure(const std::string& config, NakedDhcpv6Srv& srv) {
|
||||
CfgMgr::instance().commit();
|
||||
}
|
||||
|
||||
NakedDhcpv6SrvTest::NakedDhcpv6SrvTest()
|
||||
: rcode_(-1) {
|
||||
// it's ok if that fails. There should not be such a file anyway
|
||||
unlink(DUID_FILE);
|
||||
|
||||
const isc::dhcp::IfaceMgr::IfaceCollection& ifaces =
|
||||
isc::dhcp::IfaceMgr::instance().getIfaces();
|
||||
|
||||
// There must be some interface detected
|
||||
if (ifaces.empty()) {
|
||||
// We can't use ASSERT in constructor
|
||||
ADD_FAILURE() << "No interfaces detected.";
|
||||
}
|
||||
|
||||
valid_iface_ = (*ifaces.begin())->getName();
|
||||
|
||||
// Let's wipe all existing statistics.
|
||||
isc::stats::StatsMgr::instance().removeAll();
|
||||
}
|
||||
|
||||
NakedDhcpv6SrvTest::~NakedDhcpv6SrvTest() {
|
||||
// Let's wipe all existing statistics.
|
||||
isc::stats::StatsMgr::instance().removeAll();
|
||||
|
||||
// Let's clean up if there is such a file.
|
||||
unlink(DUID_FILE);
|
||||
isc::hooks::HooksManager::preCalloutsLibraryHandle()
|
||||
.deregisterAllCallouts("buffer6_receive");
|
||||
isc::hooks::HooksManager::preCalloutsLibraryHandle()
|
||||
.deregisterAllCallouts("buffer6_send");
|
||||
isc::hooks::HooksManager::preCalloutsLibraryHandle()
|
||||
.deregisterAllCallouts("lease6_renew");
|
||||
isc::hooks::HooksManager::preCalloutsLibraryHandle()
|
||||
.deregisterAllCallouts("lease6_release");
|
||||
isc::hooks::HooksManager::preCalloutsLibraryHandle()
|
||||
.deregisterAllCallouts("pkt6_receive");
|
||||
isc::hooks::HooksManager::preCalloutsLibraryHandle()
|
||||
.deregisterAllCallouts("pkt6_send");
|
||||
isc::hooks::HooksManager::preCalloutsLibraryHandle()
|
||||
.deregisterAllCallouts("subnet6_select");
|
||||
}
|
||||
|
||||
// Generate IA_NA option with specified parameters
|
||||
boost::shared_ptr<Option6IA>
|
||||
NakedDhcpv6SrvTest::generateIA(uint16_t type, uint32_t iaid, uint32_t t1,
|
||||
@@ -855,5 +939,6 @@ NakedDhcpv6SrvTest::checkIA_NAStatusCode(
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}; // end of isc::test namespace
|
||||
}; // end of isc namespace
|
||||
|
@@ -127,28 +127,16 @@ public:
|
||||
std::list<isc::dhcp::Pkt6Ptr> fake_sent_;
|
||||
};
|
||||
|
||||
static const char* DUID_FILE = "server-id-test.txt";
|
||||
|
||||
// test fixture for any tests requiring blank/empty configuration
|
||||
// serves as base class for additional tests
|
||||
/// @brief Test fixture for any tests requiring blank/empty configuration
|
||||
/// serves as base class for additional tests
|
||||
class NakedDhcpv6SrvTest : public ::testing::Test {
|
||||
public:
|
||||
|
||||
NakedDhcpv6SrvTest() : rcode_(-1) {
|
||||
// it's ok if that fails. There should not be such a file anyway
|
||||
unlink(DUID_FILE);
|
||||
/// @brief Constructor
|
||||
NakedDhcpv6SrvTest();
|
||||
|
||||
const isc::dhcp::IfaceMgr::IfaceCollection& ifaces =
|
||||
isc::dhcp::IfaceMgr::instance().getIfaces();
|
||||
|
||||
// There must be some interface detected
|
||||
if (ifaces.empty()) {
|
||||
// We can't use ASSERT in constructor
|
||||
ADD_FAILURE() << "No interfaces detected.";
|
||||
}
|
||||
|
||||
valid_iface_ = (*ifaces.begin())->getName();
|
||||
}
|
||||
/// @brief Location of a test DUID file
|
||||
static const char* DUID_FILE;
|
||||
|
||||
// Generate IA_NA or IA_PD option with specified parameters
|
||||
boost::shared_ptr<isc::dhcp::Option6IA> generateIA
|
||||
@@ -286,24 +274,7 @@ public:
|
||||
EXPECT_EQ(expected_transid, rsp->getTransid());
|
||||
}
|
||||
|
||||
virtual ~NakedDhcpv6SrvTest() {
|
||||
// Let's clean up if there is such a file.
|
||||
unlink(DUID_FILE);
|
||||
isc::hooks::HooksManager::preCalloutsLibraryHandle()
|
||||
.deregisterAllCallouts("buffer6_receive");
|
||||
isc::hooks::HooksManager::preCalloutsLibraryHandle()
|
||||
.deregisterAllCallouts("buffer6_send");
|
||||
isc::hooks::HooksManager::preCalloutsLibraryHandle()
|
||||
.deregisterAllCallouts("lease6_renew");
|
||||
isc::hooks::HooksManager::preCalloutsLibraryHandle()
|
||||
.deregisterAllCallouts("lease6_release");
|
||||
isc::hooks::HooksManager::preCalloutsLibraryHandle()
|
||||
.deregisterAllCallouts("pkt6_receive");
|
||||
isc::hooks::HooksManager::preCalloutsLibraryHandle()
|
||||
.deregisterAllCallouts("pkt6_send");
|
||||
isc::hooks::HooksManager::preCalloutsLibraryHandle()
|
||||
.deregisterAllCallouts("subnet6_select");
|
||||
};
|
||||
virtual ~NakedDhcpv6SrvTest();
|
||||
|
||||
// A DUID used in most tests (typically as client-id)
|
||||
isc::dhcp::DuidPtr duid_;
|
||||
@@ -539,6 +510,12 @@ public:
|
||||
testReleaseReject(isc::dhcp::Lease::Type type,
|
||||
const isc::asiolink::IOAddress& addr);
|
||||
|
||||
/// @brief simulates reception of a packet of specified type and checks statistic
|
||||
///
|
||||
/// @param pkt_type reception of a packet of this type will be simulated
|
||||
/// @param stat_name this statistic is expected to be set to 1
|
||||
void testReceiveStats(uint8_t pkt_type, const std::string& stat_name);
|
||||
|
||||
/// A subnet used in most tests
|
||||
isc::dhcp::Subnet6Ptr subnet_;
|
||||
|
||||
|
@@ -18,6 +18,7 @@
|
||||
#include <dhcp6/tests/dhcp6_client.h>
|
||||
#include <dhcp/option6_addrlst.h>
|
||||
#include <dhcp/option6_client_fqdn.h>
|
||||
#include <stats/stats_mgr.h>
|
||||
|
||||
using namespace isc;
|
||||
using namespace isc::dhcp;
|
||||
@@ -126,6 +127,17 @@ public:
|
||||
InfRequestTest()
|
||||
: Dhcpv6SrvTest(),
|
||||
iface_mgr_test_config_(true) {
|
||||
|
||||
// Let's wipe all existing statistics.
|
||||
isc::stats::StatsMgr::instance().removeAll();
|
||||
}
|
||||
|
||||
/// @brief Destructor.
|
||||
///
|
||||
/// Removes any statistics that may have been set.
|
||||
~InfRequestTest() {
|
||||
// Let's wipe all existing statistics.
|
||||
isc::stats::StatsMgr::instance().removeAll();
|
||||
}
|
||||
|
||||
/// @brief Interface Manager's fake configuration control.
|
||||
@@ -301,7 +313,53 @@ TEST_F(InfRequestTest, infRequestNoSubnets) {
|
||||
EXPECT_EQ("2001:db8::2", addrs[1].toText());
|
||||
}
|
||||
|
||||
/// Check that server processes correctly an incoming inf-request in a
|
||||
/// typical subnet that has also address and prefix pools.
|
||||
TEST_F(InfRequestTest, infRequestStats) {
|
||||
Dhcp6Client client;
|
||||
|
||||
// Configure client to request IA_PD.
|
||||
configure(CONFIGS[0], *client.getServer());
|
||||
// Make sure we ended-up having expected number of subnets configured.
|
||||
const Subnet6Collection* subnets = CfgMgr::instance().getCurrentCfg()->
|
||||
getCfgSubnets6()->getAll();
|
||||
ASSERT_EQ(1, subnets->size());
|
||||
|
||||
// Ok, let's check the statistics. None should be present.
|
||||
using namespace isc::stats;
|
||||
StatsMgr& mgr = StatsMgr::instance();
|
||||
ObservationPtr pkt6_rcvd = mgr.getObservation("pkt6-received");
|
||||
ObservationPtr pkt6_infreq_rcvd = mgr.getObservation("pkt6-infrequest-received");
|
||||
ObservationPtr pkt6_reply_sent = mgr.getObservation("pkt6-reply-sent");
|
||||
ObservationPtr pkt6_sent = mgr.getObservation("pkt6-sent");
|
||||
EXPECT_FALSE(pkt6_rcvd);
|
||||
EXPECT_FALSE(pkt6_infreq_rcvd);
|
||||
EXPECT_FALSE(pkt6_reply_sent);
|
||||
EXPECT_FALSE(pkt6_sent);
|
||||
|
||||
// Perform 2-way exchange (Inf-request/reply)
|
||||
client.requestOption(D6O_NAME_SERVERS);
|
||||
ASSERT_NO_THROW(client.doInfRequest());
|
||||
|
||||
// Confirm that there's a response
|
||||
Pkt6Ptr response = client.getContext().response_;
|
||||
ASSERT_TRUE(response);
|
||||
|
||||
pkt6_rcvd = mgr.getObservation("pkt6-received");
|
||||
pkt6_infreq_rcvd = mgr.getObservation("pkt6-infrequest-received");
|
||||
pkt6_reply_sent = mgr.getObservation("pkt6-reply-sent");
|
||||
pkt6_sent = mgr.getObservation("pkt6-sent");
|
||||
|
||||
ASSERT_TRUE(pkt6_rcvd);
|
||||
ASSERT_TRUE(pkt6_infreq_rcvd);
|
||||
ASSERT_TRUE(pkt6_reply_sent);
|
||||
ASSERT_TRUE(pkt6_sent);
|
||||
|
||||
// They also must have expected values.
|
||||
EXPECT_EQ(1, pkt6_rcvd->getInteger().first);
|
||||
EXPECT_EQ(1, pkt6_infreq_rcvd->getInteger().first);
|
||||
EXPECT_EQ(1, pkt6_reply_sent->getInteger().first);
|
||||
EXPECT_EQ(1, pkt6_sent->getInteger().first);
|
||||
}
|
||||
|
||||
} // end of anonymous namespace
|
||||
|
@@ -19,6 +19,7 @@
|
||||
#include <dhcp6/tests/dhcp6_client.h>
|
||||
#include <dhcpsrv/cfgmgr.h>
|
||||
#include <dhcpsrv/d2_client_mgr.h>
|
||||
#include <stats/stats_mgr.h>
|
||||
|
||||
using namespace isc;
|
||||
using namespace isc::dhcp;
|
||||
@@ -101,6 +102,8 @@ public:
|
||||
SARRTest()
|
||||
: Dhcpv6SrvTest(),
|
||||
iface_mgr_test_config_(true) {
|
||||
// Let's wipe all existing statistics.
|
||||
isc::stats::StatsMgr::instance().removeAll();
|
||||
}
|
||||
|
||||
/// @brief Destructor.
|
||||
@@ -109,6 +112,9 @@ public:
|
||||
virtual ~SARRTest() {
|
||||
D2ClientConfigPtr cfg(new D2ClientConfig());
|
||||
CfgMgr::instance().setD2ClientConfig(cfg);
|
||||
|
||||
// Let's wipe all existing statistics.
|
||||
isc::stats::StatsMgr::instance().removeAll();
|
||||
}
|
||||
|
||||
/// @brief Interface Manager's fake configuration control.
|
||||
@@ -276,5 +282,64 @@ TEST_F(SARRTest, rapidCommitDisable) {
|
||||
EXPECT_EQ(0, CfgMgr::instance().getD2ClientMgr().getQueueSize());
|
||||
}
|
||||
|
||||
// This test verifies that regular Solicit/Adv/Request/Reply exchange will
|
||||
// result in appropriately set statistics.
|
||||
TEST_F(SARRTest, sarrStats) {
|
||||
|
||||
// Let's use one of the existing configurations and tell the client to
|
||||
// as for an address.
|
||||
Dhcp6Client client;
|
||||
configure(CONFIGS[1], *client.getServer());
|
||||
client.setInterface("eth1");
|
||||
client.useNA();
|
||||
|
||||
// Make sure we ended-up having expected number of subnets configured.
|
||||
const Subnet6Collection* subnets = CfgMgr::instance().getCurrentCfg()->
|
||||
getCfgSubnets6()->getAll();
|
||||
ASSERT_EQ(2, subnets->size());
|
||||
|
||||
// Ok, let's check the statistics. None should be present.
|
||||
using namespace isc::stats;
|
||||
StatsMgr& mgr = StatsMgr::instance();
|
||||
ObservationPtr pkt6_rcvd = mgr.getObservation("pkt6-received");
|
||||
ObservationPtr pkt6_solicit_rcvd = mgr.getObservation("pkt6-solicit-received");
|
||||
ObservationPtr pkt6_adv_sent = mgr.getObservation("pkt6-advertise-sent");
|
||||
ObservationPtr pkt6_request_rcvd = mgr.getObservation("pkt6-request-received");
|
||||
ObservationPtr pkt6_reply_sent = mgr.getObservation("pkt6-reply-sent");
|
||||
ObservationPtr pkt6_sent = mgr.getObservation("pkt6-sent");
|
||||
EXPECT_FALSE(pkt6_rcvd);
|
||||
EXPECT_FALSE(pkt6_solicit_rcvd);
|
||||
EXPECT_FALSE(pkt6_adv_sent);
|
||||
EXPECT_FALSE(pkt6_request_rcvd);
|
||||
EXPECT_FALSE(pkt6_reply_sent);
|
||||
EXPECT_FALSE(pkt6_sent);
|
||||
|
||||
// Perform 4-way exchange.
|
||||
ASSERT_NO_THROW(client.doSARR());
|
||||
// Server should have assigned a prefix.
|
||||
ASSERT_EQ(1, client.getLeaseNum());
|
||||
|
||||
// All expected statstics must be present now.
|
||||
pkt6_rcvd = mgr.getObservation("pkt6-received");
|
||||
pkt6_solicit_rcvd = mgr.getObservation("pkt6-solicit-received");
|
||||
pkt6_adv_sent = mgr.getObservation("pkt6-advertise-sent");
|
||||
pkt6_request_rcvd = mgr.getObservation("pkt6-request-received");
|
||||
pkt6_reply_sent = mgr.getObservation("pkt6-reply-sent");
|
||||
pkt6_sent = mgr.getObservation("pkt6-sent");
|
||||
ASSERT_TRUE(pkt6_rcvd);
|
||||
ASSERT_TRUE(pkt6_solicit_rcvd);
|
||||
ASSERT_TRUE(pkt6_adv_sent);
|
||||
ASSERT_TRUE(pkt6_request_rcvd);
|
||||
ASSERT_TRUE(pkt6_reply_sent);
|
||||
ASSERT_TRUE(pkt6_sent);
|
||||
|
||||
// They also must have expected values.
|
||||
EXPECT_EQ(2, pkt6_rcvd->getInteger().first);
|
||||
EXPECT_EQ(1, pkt6_solicit_rcvd->getInteger().first);
|
||||
EXPECT_EQ(1, pkt6_adv_sent->getInteger().first);
|
||||
EXPECT_EQ(1, pkt6_request_rcvd->getInteger().first);
|
||||
EXPECT_EQ(1, pkt6_reply_sent->getInteger().first);
|
||||
EXPECT_EQ(2, pkt6_sent->getInteger().first);
|
||||
}
|
||||
|
||||
} // end of anonymous namespace
|
||||
|
Reference in New Issue
Block a user