summaryrefslogtreecommitdiffstats
path: root/src/bin/dhcp6/tests
diff options
context:
space:
mode:
authorTomek Mrugalski <tomasz@isc.org>2015-06-19 19:41:18 +0200
committerTomek Mrugalski <tomasz@isc.org>2015-06-19 19:41:18 +0200
commit7616e3b3b8dfc7bb4d95665651acd0056cd66408 (patch)
tree7813fbbc520af4b6935ae5201745e09c9f93a810 /src/bin/dhcp6/tests
parent[master] Forgotten cleanup for 3800: remove tabs. (diff)
parent[3795] Changes after review: (diff)
downloadkea-7616e3b3b8dfc7bb4d95665651acd0056cd66408.tar.xz
kea-7616e3b3b8dfc7bb4d95665651acd0056cd66408.zip
[master] Merge branch 'trac3795' (DHCPv6 statistics)
Conflicts: doc/guide/dhcp4-srv.xml
Diffstat (limited to 'src/bin/dhcp6/tests')
-rw-r--r--src/bin/dhcp6/tests/dhcp6_client.cc9
-rw-r--r--src/bin/dhcp6/tests/dhcp6_client.h14
-rw-r--r--src/bin/dhcp6/tests/dhcp6_srv_unittest.cc85
-rw-r--r--src/bin/dhcp6/tests/dhcp6_test_utils.cc85
-rw-r--r--src/bin/dhcp6/tests/dhcp6_test_utils.h49
-rw-r--r--src/bin/dhcp6/tests/infrequest_unittest.cc58
-rw-r--r--src/bin/dhcp6/tests/sarr_unittest.cc148
7 files changed, 409 insertions, 39 deletions
diff --git a/src/bin/dhcp6/tests/dhcp6_client.cc b/src/bin/dhcp6/tests/dhcp6_client.cc
index 1fc120a9be..9de4755c8b 100644
--- a/src/bin/dhcp6/tests/dhcp6_client.cc
+++ b/src/bin/dhcp6/tests/dhcp6_client.cc
@@ -295,6 +295,9 @@ Dhcp6Client::doSARR() {
void
Dhcp6Client::doSolicit() {
context_.query_ = createMsg(DHCPV6_SOLICIT);
+ if (forced_server_id_) {
+ context_.query_->addOption(forced_server_id_);
+ }
if (use_na_) {
context_.query_->addOption(Option6IAPtr(new Option6IA(D6O_IA_NA,
1234)));
@@ -327,7 +330,11 @@ Dhcp6Client::doSolicit() {
void
Dhcp6Client::doRequest() {
Pkt6Ptr query = createMsg(DHCPV6_REQUEST);
- query->addOption(context_.response_->getOption(D6O_SERVERID));
+ if (!forced_server_id_) {
+ query->addOption(context_.response_->getOption(D6O_SERVERID));
+ } else {
+ query->addOption(forced_server_id_);
+ }
copyIAs(context_.response_, query);
// Add Client FQDN if configured.
diff --git a/src/bin/dhcp6/tests/dhcp6_client.h b/src/bin/dhcp6/tests/dhcp6_client.h
index 98091db61e..35462321ce 100644
--- a/src/bin/dhcp6/tests/dhcp6_client.h
+++ b/src/bin/dhcp6/tests/dhcp6_client.h
@@ -448,6 +448,17 @@ public:
use_rapid_commit_ = rapid_commit;
}
+ /// @brief Specifies server-id to be used in send messages
+ ///
+ /// Overrides the server-id to be sent when server-id is expected to be
+ /// sent. May be NULL, which means use proper server-id sent in Advertise
+ /// (which is a normal client behavior).
+ ///
+ /// @param server_id server-id to be sent
+ void useServerId(const OptionPtr& server_id) {
+ forced_server_id_ = server_id;
+ }
+
/// @brief Creates an instance of the Client FQDN option to be included
/// in the client's message.
///
@@ -614,6 +625,9 @@ private:
/// to true. See @ref sendORO for details.
std::vector<uint16_t> oro_;
+ /// @brief forced (Overridden) value of the server-id option (may be NULL)
+ OptionPtr forced_server_id_;
+
/// @brief FQDN requested by the client.
Option6ClientFqdnPtr fqdn_;
};
diff --git a/src/bin/dhcp6/tests/dhcp6_srv_unittest.cc b/src/bin/dhcp6/tests/dhcp6_srv_unittest.cc
index eb308e711a..b587becb4f 100644
--- a/src/bin/dhcp6/tests/dhcp6_srv_unittest.cc
+++ b/src/bin/dhcp6/tests/dhcp6_srv_unittest.cc
@@ -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,88 @@ 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_REPLY, "pkt6-reply-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.
diff --git a/src/bin/dhcp6/tests/dhcp6_test_utils.cc b/src/bin/dhcp6/tests/dhcp6_test_utils.cc
index 550fb5244c..dd40b049b9 100644
--- a/src/bin/dhcp6/tests/dhcp6_test_utils.cc
+++ b/src/bin/dhcp6/tests/dhcp6_test_utils.cc
@@ -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
@@ -742,6 +746,44 @@ Dhcpv6SrvTest::testReleaseReject(Lease::Type type, const IOAddress& 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
diff --git a/src/bin/dhcp6/tests/dhcp6_test_utils.h b/src/bin/dhcp6/tests/dhcp6_test_utils.h
index 7f0b4a5a4b..d4e48319c6 100644
--- a/src/bin/dhcp6/tests/dhcp6_test_utils.h
+++ b/src/bin/dhcp6/tests/dhcp6_test_utils.h
@@ -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);
-
- 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.";
- }
+ /// @brief Constructor
+ NakedDhcpv6SrvTest();
- 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_;
diff --git a/src/bin/dhcp6/tests/infrequest_unittest.cc b/src/bin/dhcp6/tests/infrequest_unittest.cc
index ead363642d..8b15f7fb6e 100644
--- a/src/bin/dhcp6/tests/infrequest_unittest.cc
+++ b/src/bin/dhcp6/tests/infrequest_unittest.cc
@@ -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
diff --git a/src/bin/dhcp6/tests/sarr_unittest.cc b/src/bin/dhcp6/tests/sarr_unittest.cc
index 2035521383..71eb3e96d1 100644
--- a/src/bin/dhcp6/tests/sarr_unittest.cc
+++ b/src/bin/dhcp6/tests/sarr_unittest.cc
@@ -19,6 +19,8 @@
#include <dhcp6/tests/dhcp6_client.h>
#include <dhcpsrv/cfgmgr.h>
#include <dhcpsrv/d2_client_mgr.h>
+#include <asiolink/io_address.h>
+#include <stats/stats_mgr.h>
using namespace isc;
using namespace isc::dhcp;
@@ -101,6 +103,8 @@ public:
SARRTest()
: Dhcpv6SrvTest(),
iface_mgr_test_config_(true) {
+ // Let's wipe all existing statistics.
+ isc::stats::StatsMgr::instance().removeAll();
}
/// @brief Destructor.
@@ -109,6 +113,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 +283,146 @@ 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
+ // ask 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);
+}
+
+// This test verifies that pkt6-receive-drop is increased properly when the
+// client's packet is rejected due to mismatched server-id value.
+TEST_F(SARRTest, pkt6ReceiveDropStat1) {
+
+ // Dummy server-id (0xff repeated 10 times)
+ std::vector<uint8_t> data(10, 0xff);
+ OptionPtr bogus_srv_id(new Option(Option::V6, D6O_SERVERID, data));
+
+ // Let's use one of the existing configurations and tell the client to
+ // ask for an address.
+ Dhcp6Client client;
+ configure(CONFIGS[1], *client.getServer());
+ client.setInterface("eth1");
+ client.useNA();
+
+ client.doSolicit();
+ client.useServerId(bogus_srv_id);
+ client.doRequest();
+
+ // Ok, let's check the statistic. pkt6-receive-drop should be set to 1.
+ using namespace isc::stats;
+ StatsMgr& mgr = StatsMgr::instance();
+
+ ObservationPtr pkt6_recv_drop = mgr.getObservation("pkt6-receive-drop");
+ ASSERT_TRUE(pkt6_recv_drop);
+
+ EXPECT_EQ(1, pkt6_recv_drop->getInteger().first);
+}
+
+// This test verifies that pkt6-receive-drop is increased properly when the
+// client's packet is rejected due to being unicast communication.
+TEST_F(SARRTest, pkt6ReceiveDropStat2) {
+
+ // Let's use one of the existing configurations and tell the client to
+ // ask for an address.
+ Dhcp6Client client;
+ configure(CONFIGS[1], *client.getServer());
+ client.setInterface("eth1");
+ client.useNA();
+
+ client.setDestAddress(asiolink::IOAddress("2001:db8::1")); // Pretend it's unicast
+ client.doSolicit();
+
+ // Ok, let's check the statistic. pkt6-receive-drop should be set to 1.
+ using namespace isc::stats;
+ StatsMgr& mgr = StatsMgr::instance();
+
+ ObservationPtr pkt6_recv_drop = mgr.getObservation("pkt6-receive-drop");
+ ASSERT_TRUE(pkt6_recv_drop);
+
+ EXPECT_EQ(1, pkt6_recv_drop->getInteger().first);
+}
+
+// This test verifies that pkt6-receive-drop is increased properly when the
+// client's packet is rejected due to having too many client-id options
+// (exactly one is expected).
+TEST_F(SARRTest, pkt6ReceiveDropStat3) {
+
+ // Let's use one of the existing configurations and tell the client to
+ // ask for an address.
+ Dhcp6Client client;
+ configure(CONFIGS[1], *client.getServer());
+ client.setInterface("eth1");
+ client.useNA();
+
+ // Let's send our client-id as server-id. That will result in the
+ // packet containing the client-id twice. That should cause RFCViolation
+ // exception.
+ client.useServerId(client.getClientId());
+ client.doSolicit();
+
+ // Ok, let's check the statistic. pkt6-receive-drop should be set to 1.
+ using namespace isc::stats;
+ StatsMgr& mgr = StatsMgr::instance();
+
+ ObservationPtr pkt6_recv_drop = mgr.getObservation("pkt6-receive-drop");
+ ASSERT_TRUE(pkt6_recv_drop);
+
+ EXPECT_EQ(1, pkt6_recv_drop->getInteger().first);
+}
+
} // end of anonymous namespace