summaryrefslogtreecommitdiffstats
path: root/src/bin/dhcp6/tests/hooks_unittest.cc
diff options
context:
space:
mode:
Diffstat (limited to 'src/bin/dhcp6/tests/hooks_unittest.cc')
-rw-r--r--src/bin/dhcp6/tests/hooks_unittest.cc2707
1 files changed, 1447 insertions, 1260 deletions
diff --git a/src/bin/dhcp6/tests/hooks_unittest.cc b/src/bin/dhcp6/tests/hooks_unittest.cc
index fac2d438ac..99be8bd558 100644
--- a/src/bin/dhcp6/tests/hooks_unittest.cc
+++ b/src/bin/dhcp6/tests/hooks_unittest.cc
@@ -8,26 +8,28 @@
#include <asiolink/io_address.h>
#include <asiolink/io_service.h>
+#include <cc/command_interpreter.h>
+#include <config/command_mgr.h>
#include <dhcp/dhcp6.h>
#include <dhcp/duid.h>
-#include <dhcp6/json_config_parser.h>
+#include <dhcp/tests/iface_mgr_test_config.h>
+#include <dhcp/tests/pkt_captures.h>
#include <dhcpsrv/cfgmgr.h>
#include <dhcpsrv/lease_mgr.h>
#include <dhcpsrv/lease_mgr_factory.h>
#include <dhcpsrv/utils.h>
-#include <util/buffer.h>
-#include <util/range_utilities.h>
-#include <hooks/server_hooks.h>
-#include <hooks/callout_manager.h>
-#include <dhcp6/tests/dhcp6_test_utils.h>
-#include <dhcp6/tests/dhcp6_client.h>
#include <dhcp6/ctrl_dhcp6_srv.h>
-#include <dhcp/tests/iface_mgr_test_config.h>
-#include <dhcp/tests/pkt_captures.h>
-#include <cc/command_interpreter.h>
+#include <dhcp6/json_config_parser.h>
+#include <dhcp6/tests/dhcp6_client.h>
+#include <dhcp6/tests/dhcp6_test_utils.h>
#include <dhcp6/tests/marker_file.h>
#include <dhcp6/tests/test_libraries.h>
+#include <hooks/server_hooks.h>
+#include <hooks/hooks_manager.h>
+#include <hooks/callout_manager.h>
#include <stats/stats_mgr.h>
+#include <util/buffer.h>
+#include <util/range_utilities.h>
#include <util/multi_threading_mgr.h>
#include <boost/scoped_ptr.hpp>
@@ -37,15 +39,16 @@
#include <iostream>
#include <sstream>
-using namespace isc;
+
+using namespace isc::asiolink;
using namespace isc::config;
using namespace isc::data;
-using namespace isc::dhcp::test;
-using namespace isc::asiolink;
using namespace isc::dhcp;
-using namespace isc::util;
+using namespace isc::dhcp::test;
using namespace isc::hooks;
using namespace isc::stats;
+using namespace isc::util;
+
using namespace std;
// namespace has to be named, because friends are defined in Dhcpv6Srv class
@@ -57,19 +60,22 @@ TEST_F(Dhcpv6SrvTest, Hooks) {
NakedDhcpv6Srv srv(0);
// check if appropriate hooks are registered
- int hook_index_buffer6_receive = -1;
- int hook_index_buffer6_send = -1;
- int hook_index_lease6_renew = -1;
- int hook_index_lease6_release = -1;
- int hook_index_lease6_rebind = -1;
- int hook_index_lease6_decline = -1;
- int hook_index_pkt6_received = -1;
- int hook_index_select_subnet = -1;
+ int hook_index_dhcp6_srv_configured = -1;
+ int hook_index_buffer6_receive = -1;
+ int hook_index_buffer6_send = -1;
+ int hook_index_lease6_renew = -1;
+ int hook_index_lease6_release = -1;
+ int hook_index_lease6_rebind = -1;
+ int hook_index_lease6_decline = -1;
+ int hook_index_pkt6_receive = -1;
+ int hook_index_pkt6_send = -1;
+ int hook_index_select_subnet = -1;
int hook_index_leases6_committed = -1;
- int hook_index_pkt6_send = -1;
- int hook_index_host6_identifier = -1;
+ int hook_index_host6_identifier = -1;
// check if appropriate indexes are set
+ EXPECT_NO_THROW(hook_index_dhcp6_srv_configured = ServerHooks::getServerHooks()
+ .getIndex("dhcp6_srv_configured"));
EXPECT_NO_THROW(hook_index_buffer6_receive = ServerHooks::getServerHooks()
.getIndex("buffer6_receive"));
EXPECT_NO_THROW(hook_index_buffer6_send = ServerHooks::getServerHooks()
@@ -82,29 +88,29 @@ TEST_F(Dhcpv6SrvTest, Hooks) {
.getIndex("lease6_rebind"));
EXPECT_NO_THROW(hook_index_lease6_decline = ServerHooks::getServerHooks()
.getIndex("lease6_decline"));
- EXPECT_NO_THROW(hook_index_pkt6_received = ServerHooks::getServerHooks()
+ EXPECT_NO_THROW(hook_index_pkt6_receive = ServerHooks::getServerHooks()
.getIndex("pkt6_receive"));
+ EXPECT_NO_THROW(hook_index_pkt6_send = ServerHooks::getServerHooks()
+ .getIndex("pkt6_send"));
EXPECT_NO_THROW(hook_index_select_subnet = ServerHooks::getServerHooks()
.getIndex("subnet6_select"));
EXPECT_NO_THROW(hook_index_leases6_committed = ServerHooks::getServerHooks()
.getIndex("leases6_committed"));
- EXPECT_NO_THROW(hook_index_pkt6_send = ServerHooks::getServerHooks()
- .getIndex("pkt6_send"));
EXPECT_NO_THROW(hook_index_host6_identifier = ServerHooks::getServerHooks()
.getIndex("host6_identifier"));
-
- EXPECT_TRUE(hook_index_pkt6_received > 0);
- EXPECT_TRUE(hook_index_select_subnet > 0);
+ EXPECT_TRUE(hook_index_dhcp6_srv_configured > 0);
+ EXPECT_TRUE(hook_index_buffer6_receive > 0);
+ EXPECT_TRUE(hook_index_buffer6_send > 0);
+ EXPECT_TRUE(hook_index_lease6_renew > 0);
+ EXPECT_TRUE(hook_index_lease6_release > 0);
+ EXPECT_TRUE(hook_index_lease6_rebind > 0);
+ EXPECT_TRUE(hook_index_lease6_decline > 0);
+ EXPECT_TRUE(hook_index_pkt6_receive > 0);
+ EXPECT_TRUE(hook_index_pkt6_send > 0);
+ EXPECT_TRUE(hook_index_select_subnet > 0);
EXPECT_TRUE(hook_index_leases6_committed > 0);
- EXPECT_TRUE(hook_index_pkt6_send > 0);
- EXPECT_TRUE(hook_index_buffer6_receive > 0);
- EXPECT_TRUE(hook_index_buffer6_send > 0);
- EXPECT_TRUE(hook_index_lease6_renew > 0);
- EXPECT_TRUE(hook_index_lease6_release > 0);
- EXPECT_TRUE(hook_index_lease6_rebind > 0);
- EXPECT_TRUE(hook_index_lease6_decline > 0);
- EXPECT_TRUE(hook_index_host6_identifier > 0);
+ EXPECT_TRUE(hook_index_host6_identifier > 0);
}
/// @brief a class dedicated to Hooks testing in DHCPv6 server
@@ -120,9 +126,7 @@ class HooksDhcpv6SrvTest : public Dhcpv6SrvTest {
public:
/// @brief creates Dhcpv6Srv and prepares buffers for callouts
- HooksDhcpv6SrvTest()
- : Dhcpv6SrvTest() {
-
+ HooksDhcpv6SrvTest() : Dhcpv6SrvTest() {
HooksManager::setTestMode(false);
bool status = HooksManager::unloadLibraries();
if (!status) {
@@ -149,10 +153,11 @@ public:
// Clear static buffers
resetCalloutBuffers();
+ HooksManager::preCalloutsLibraryHandle().deregisterAllCallouts("dhcp6_srv_configured");
HooksManager::preCalloutsLibraryHandle().deregisterAllCallouts("buffer6_receive");
+ HooksManager::preCalloutsLibraryHandle().deregisterAllCallouts("buffer6_send");
HooksManager::preCalloutsLibraryHandle().deregisterAllCallouts("pkt6_receive");
HooksManager::preCalloutsLibraryHandle().deregisterAllCallouts("pkt6_send");
- HooksManager::preCalloutsLibraryHandle().deregisterAllCallouts("buffer6_send");
HooksManager::preCalloutsLibraryHandle().deregisterAllCallouts("subnet6_select");
HooksManager::preCalloutsLibraryHandle().deregisterAllCallouts("leases6_committed");
HooksManager::preCalloutsLibraryHandle().deregisterAllCallouts("lease6_renew");
@@ -161,20 +166,20 @@ public:
HooksManager::preCalloutsLibraryHandle().deregisterAllCallouts("lease6_decline");
HooksManager::preCalloutsLibraryHandle().deregisterAllCallouts("host6_identifier");
- // Clear statistics.
- StatsMgr::instance().removeAll();
-
HooksManager::setTestMode(false);
bool status = HooksManager::unloadLibraries();
if (!status) {
cerr << "(fixture dtor) unloadLibraries failed" << endl;
}
+
+ // Clear statistics.
+ StatsMgr::instance().removeAll();
}
/// @brief creates an option with specified option code
///
/// This method is static, because it is used from callouts
- /// that do not have a pointer to HooksDhcpv6SSrvTest object
+ /// that do not have a pointer to HooksDhcpv6SrvTest object
///
/// @param option_code code of option to be created
///
@@ -204,12 +209,12 @@ public:
EXPECT_TRUE(callout_handle->getArgumentNames().empty());
}
- /// test callback that stores received callout name and pkt6 value
+ /// Test callback that stores received callout name and pkt6 value
/// @param callout_handle handle passed by the hooks framework
/// @return always 0
static int
- pkt6_receive_callout(CalloutHandle& callout_handle) {
- callback_name_ = string("pkt6_receive");
+ buffer6_receive_callout(CalloutHandle& callout_handle) {
+ callback_name_ = string("buffer6_receive");
callout_handle.getArgument("query6", callback_qry_pkt6_);
@@ -222,77 +227,84 @@ public:
return (0);
}
- /// test callback that changes client-id value
+ /// Test callback that changes first byte of client-id value
/// @param callout_handle handle passed by the hooks framework
/// @return always 0
static int
- pkt6_receive_change_clientid(CalloutHandle& callout_handle) {
+ buffer6_receive_change_clientid(CalloutHandle& callout_handle) {
Pkt6Ptr pkt;
callout_handle.getArgument("query6", pkt);
- // Get rid of the old client-id
- pkt->delOption(D6O_CLIENTID);
-
- // Add a new option
- pkt->addOption(createOption(D6O_CLIENTID));
+ // If there is at least one option with data
+ if (pkt->data_.size() > Pkt6::DHCPV6_PKT_HDR_LEN + Option::OPTION6_HDR_LEN) {
+ // Offset of the first byte of the first option. Let's set this byte
+ // to some new value that we could later check
+ pkt->data_[Pkt6::DHCPV6_PKT_HDR_LEN + Option::OPTION6_HDR_LEN] = 0xff;
+ }
// Carry on as usual
- return pkt6_receive_callout(callout_handle);
+ return buffer6_receive_callout(callout_handle);
}
/// Test callback that deletes client-id
/// @param callout_handle handle passed by the hooks framework
/// @return always 0
static int
- pkt6_receive_delete_clientid(CalloutHandle& callout_handle) {
+ buffer6_receive_delete_clientid(CalloutHandle& callout_handle) {
Pkt6Ptr pkt;
callout_handle.getArgument("query6", pkt);
- // Get rid of the old client-id
- pkt->delOption(D6O_CLIENTID);
+ // this is modified SOLICIT (with missing mandatory client-id)
+ uint8_t data[] = {
+ 1, // type 1 = SOLICIT
+ 0xca, 0xfe, 0x01, // trans-id = 0xcafe01
+ 0, 3, // option type 3 (IA_NA)
+ 0, 12, // option length 12
+ 0, 0, 0, 1, // iaid = 1
+ 0, 0, 0, 0, // T1 = 0
+ 0, 0, 0, 0 // T2 = 0
+ };
+
+ OptionBuffer modifiedMsg(data, data + sizeof(data));
+
+ pkt->data_ = modifiedMsg;
// Carry on as usual
- return pkt6_receive_callout(callout_handle);
+ return buffer6_receive_callout(callout_handle);
}
/// Test callback that sets skip flag
/// @param callout_handle handle passed by the hooks framework
/// @return always 0
static int
- pkt6_receive_skip(CalloutHandle& callout_handle) {
-
- Pkt6Ptr pkt;
- callout_handle.getArgument("query6", pkt);
+ buffer6_receive_skip(CalloutHandle& callout_handle) {
callout_handle.setStatus(CalloutHandle::NEXT_STEP_SKIP);
// Carry on as usual
- return pkt6_receive_callout(callout_handle);
+ return buffer6_receive_callout(callout_handle);
}
/// Test callback that sets drop flag
/// @param callout_handle handle passed by the hooks framework
/// @return always 0
static int
- pkt6_receive_drop(CalloutHandle& callout_handle) {
-
- Pkt6Ptr pkt;
- callout_handle.getArgument("query6", pkt);
+ buffer6_receive_drop(CalloutHandle& callout_handle) {
callout_handle.setStatus(CalloutHandle::NEXT_STEP_DROP);
// Carry on as usual
- return pkt6_receive_callout(callout_handle);
+ return buffer6_receive_callout(callout_handle);
}
/// Test callback that stores received callout name and pkt6 value
/// @param callout_handle handle passed by the hooks framework
/// @return always 0
static int
- buffer6_receive_callout(CalloutHandle& callout_handle) {
- callback_name_ = string("buffer6_receive");
+ pkt6_receive_callout(CalloutHandle& callout_handle) {
+ callback_name_ = string("pkt6_receive");
callout_handle.getArgument("query6", callback_qry_pkt6_);
@@ -305,74 +317,69 @@ public:
return (0);
}
- /// Test callback that changes first byte of client-id value
+ /// Test callback that changes client-id value
/// @param callout_handle handle passed by the hooks framework
/// @return always 0
static int
- buffer6_receive_change_clientid(CalloutHandle& callout_handle) {
+ pkt6_receive_change_clientid(CalloutHandle& callout_handle) {
Pkt6Ptr pkt;
callout_handle.getArgument("query6", pkt);
- // If there is at least one option with data
- if (pkt->data_.size() > Pkt6::DHCPV6_PKT_HDR_LEN + Option::OPTION6_HDR_LEN) {
- // Offset of the first byte of the first option. Let's set this byte
- // to some new value that we could later check
- pkt->data_[Pkt6::DHCPV6_PKT_HDR_LEN + Option::OPTION6_HDR_LEN] = 0xff;
- }
+ // Get rid of the old client-id
+ pkt->delOption(D6O_CLIENTID);
+
+ // Add a new option
+ pkt->addOption(createOption(D6O_CLIENTID));
// Carry on as usual
- return buffer6_receive_callout(callout_handle);
+ return pkt6_receive_callout(callout_handle);
}
/// Test callback that deletes client-id
/// @param callout_handle handle passed by the hooks framework
/// @return always 0
static int
- buffer6_receive_delete_clientid(CalloutHandle& callout_handle) {
+ pkt6_receive_delete_clientid(CalloutHandle& callout_handle) {
Pkt6Ptr pkt;
callout_handle.getArgument("query6", pkt);
- // this is modified SOLICIT (with missing mandatory client-id)
- uint8_t data[] = {
- 1, // type 1 = SOLICIT
- 0xca, 0xfe, 0x01, // trans-id = 0xcafe01
- 0, 3, // option type 3 (IA_NA)
- 0, 12, // option length 12
- 0, 0, 0, 1, // iaid = 1
- 0, 0, 0, 0, // T1 = 0
- 0, 0, 0, 0 // T2 = 0
- };
-
- OptionBuffer modifiedMsg(data, data + sizeof(data));
-
- pkt->data_ = modifiedMsg;
+ // Get rid of the old client-id
+ pkt->delOption(D6O_CLIENTID);
- // carry on as usual
- return buffer6_receive_callout(callout_handle);
+ // Carry on as usual
+ return pkt6_receive_callout(callout_handle);
}
/// Test callback that sets skip flag
/// @param callout_handle handle passed by the hooks framework
/// @return always 0
static int
- buffer6_receive_skip(CalloutHandle& callout_handle) {
+ pkt6_receive_skip(CalloutHandle& callout_handle) {
+
+ Pkt6Ptr pkt;
+ callout_handle.getArgument("query6", pkt);
+
callout_handle.setStatus(CalloutHandle::NEXT_STEP_SKIP);
// Carry on as usual
- return buffer6_receive_callout(callout_handle);
+ return pkt6_receive_callout(callout_handle);
}
/// Test callback that sets drop flag
/// @param callout_handle handle passed by the hooks framework
/// @return always 0
static int
- buffer6_receive_drop(CalloutHandle& callout_handle) {
+ pkt6_receive_drop(CalloutHandle& callout_handle) {
+
+ Pkt6Ptr pkt;
+ callout_handle.getArgument("query6", pkt);
+
callout_handle.setStatus(CalloutHandle::NEXT_STEP_DROP);
// Carry on as usual
- return buffer6_receive_callout(callout_handle);
+ return pkt6_receive_callout(callout_handle);
}
/// Test callback that stores received callout name and pkt6 value
@@ -464,17 +471,17 @@ public:
return pkt6_send_callout(callout_handle);
}
- /// @brief Test callback that stores response packet.
+ /// Test callback that stores response packet.
/// @param callout_handle handle passed by the hooks framework.
/// @return always 0
static int
buffer6_send_callout(CalloutHandle& callout_handle) {
callback_name_ = string("buffer6_send");
- callback_argument_names_ = callout_handle.getArgumentNames();
-
callout_handle.getArgument("response6", callback_resp_pkt6_);
+ callback_argument_names_ = callout_handle.getArgumentNames();
+
if (callback_resp_pkt6_) {
callback_resp_options_copy_ = callback_resp_pkt6_->isCopyRetrievedOptions();
}
@@ -490,7 +497,7 @@ public:
callout_handle.setStatus(CalloutHandle::NEXT_STEP_SKIP);
- // carry on as usual
+ // Carry on as usual
return buffer6_send_callout(callout_handle);
}
@@ -573,7 +580,7 @@ public:
return subnet6_select_callout(callout_handle);
}
- /// Test callback that stores received callout name and pkt6 value
+ /// Test callback that stores received callout name and subnet6 values
/// @param callout_handle handle passed by the hooks framework
/// @return always 0
static int
@@ -709,7 +716,6 @@ public:
return (lease6_rebind_callout(callout_handle));
}
-
/// Test callback that stores received callout name passed parameters
/// @param callout_handle handle passed by the hooks framework
/// @return always 0
@@ -753,9 +759,7 @@ public:
return (0);
}
- /// Lease6_decline test callback
- ///
- /// Stores all parameters in callback_* fields.
+ /// Test lease6_decline callback that stores received parameters.
///
/// @param callout_handle handle passed by the hooks framework
/// @return always 0
@@ -772,7 +776,7 @@ public:
return (0);
}
- /// Lease6_decline callout that sets status to SKIP
+ /// Test lease6_decline callback that sets next step to SKIP.
///
/// @param callout_handle handle passed by the hooks framework
/// @return always 0
@@ -783,7 +787,7 @@ public:
return (lease6_decline_callout(callout_handle));
}
- /// Lease6_decline callout that sets status to DROP
+ /// Test lease6_decline callback that sets next step to DROP.
///
/// @param callout_handle handle passed by the hooks framework
/// @return always 0
@@ -848,7 +852,7 @@ public:
return (0);
}
- /// @brief Test host6_identifier by setting identifier to "foo"
+ /// @brief Test host6_identifier callback by setting identifier to "foo"
///
/// @param callout_handle handle passed by the hooks framework
/// @return always 0
@@ -904,7 +908,6 @@ public:
return (0);
}
-
/// Resets buffers used to store data received by callouts
void resetCalloutBuffers() {
callback_name_ = string("");
@@ -954,8 +957,10 @@ public:
/// Pointer to lease6 structure returned in the leases6_committed callout
static Lease6Ptr callback_lease6_;
- /// Pointers to lease6 structures returned in the leases6_committed callout
+ /// Pointer to lease6 structure returned in the leases6_committed callout
static Lease6CollectionPtr callback_new_leases6_;
+
+ /// Pointer to lease6 structure returned in the leases6_committed callout
static Lease6CollectionPtr callback_deleted_leases6_;
/// Pointer to IA_NA option being renewed or rebound
@@ -993,11 +998,11 @@ Pkt6Ptr HooksDhcpv6SrvTest::callback_qry_pkt6_;
Pkt6Ptr HooksDhcpv6SrvTest::callback_resp_pkt6_;
Subnet6Ptr HooksDhcpv6SrvTest::callback_subnet6_;
const Subnet6Collection* HooksDhcpv6SrvTest::callback_subnet6collection_;
-vector<string> HooksDhcpv6SrvTest::callback_argument_names_;
Lease6Ptr HooksDhcpv6SrvTest::callback_lease6_;
Lease6CollectionPtr HooksDhcpv6SrvTest::callback_new_leases6_;
Lease6CollectionPtr HooksDhcpv6SrvTest::callback_deleted_leases6_;
boost::shared_ptr<Option6IA> HooksDhcpv6SrvTest::callback_ia_na_;
+vector<string> HooksDhcpv6SrvTest::callback_argument_names_;
bool HooksDhcpv6SrvTest::callback_qry_options_copy_;
bool HooksDhcpv6SrvTest::callback_resp_options_copy_;
@@ -1007,8 +1012,7 @@ public:
/// @brief Pointer to the tested server object
boost::shared_ptr<NakedDhcpv6Srv> server_;
- LoadUnloadDhcpv6SrvTest()
- : Dhcpv6SrvTest() {
+ LoadUnloadDhcpv6SrvTest() : Dhcpv6SrvTest() {
reset();
MultiThreadingMgr::instance().setMode(false);
}
@@ -1037,13 +1041,12 @@ public:
}
};
-
// Checks if callouts installed on buffer6_receive are indeed called and the
// all necessary parameters are passed.
//
// Note that the test name does not follow test naming convention,
// but the proper hook name is "buffer6_receive".
-TEST_F(HooksDhcpv6SrvTest, simpleBuffer6Receive) {
+TEST_F(HooksDhcpv6SrvTest, buffer6ReceiveSimple) {
// Install buffer6_receive_callout
EXPECT_NO_THROW(HooksManager::preCalloutsLibraryHandle().registerCallout(
@@ -1082,7 +1085,7 @@ TEST_F(HooksDhcpv6SrvTest, simpleBuffer6Receive) {
// Checks if callouts installed on buffer6_receive is able to change
// the values and the parameters are indeed used by the server.
-TEST_F(HooksDhcpv6SrvTest, valueChangeBuffer6Receive) {
+TEST_F(HooksDhcpv6SrvTest, buffer6ReceiveValueChange) {
// Install buffer6_receive_change_clientid
EXPECT_NO_THROW(HooksManager::preCalloutsLibraryHandle().registerCallout(
@@ -1122,7 +1125,7 @@ TEST_F(HooksDhcpv6SrvTest, valueChangeBuffer6Receive) {
// Checks if callouts installed on buffer6_receive is able to delete
// existing options and that change impacts server processing (mandatory
// client-id option is deleted, so the packet is expected to be dropped)
-TEST_F(HooksDhcpv6SrvTest, deleteClientIdBuffer6Receive) {
+TEST_F(HooksDhcpv6SrvTest, buffer6ReceiveDeleteClientId) {
// Install buffer6_receive_delete_clientid
EXPECT_NO_THROW(HooksManager::preCalloutsLibraryHandle().registerCallout(
@@ -1147,9 +1150,9 @@ TEST_F(HooksDhcpv6SrvTest, deleteClientIdBuffer6Receive) {
checkCalloutHandleReset(sol);
}
-// Checks if callouts installed on buffer6_received is able to set skip flag that
+// Checks if callouts installed on buffer6_receive is able to set skip flag that
// will cause the server to not process the packet (drop), even though it is valid.
-TEST_F(HooksDhcpv6SrvTest, skipBuffer6Receive) {
+TEST_F(HooksDhcpv6SrvTest, buffer6ReceiveSkip) {
// Install buffer6_receive_skip
EXPECT_NO_THROW(HooksManager::preCalloutsLibraryHandle().registerCallout(
@@ -1174,9 +1177,9 @@ TEST_F(HooksDhcpv6SrvTest, skipBuffer6Receive) {
checkCalloutHandleReset(sol);
}
-// Checks if callouts installed on buffer6_received is able to set drop flag that
+// Checks if callouts installed on buffer6_receive is able to set drop flag that
// will cause the server to not process the packet (drop), even though it is valid.
-TEST_F(HooksDhcpv6SrvTest, dropBuffer6Receive) {
+TEST_F(HooksDhcpv6SrvTest, buffer6ReceiveDrop) {
// Install buffer6_receive_drop
EXPECT_NO_THROW(HooksManager::preCalloutsLibraryHandle().registerCallout(
@@ -1206,7 +1209,7 @@ TEST_F(HooksDhcpv6SrvTest, dropBuffer6Receive) {
//
// Note that the test name does not follow test naming convention,
// but the proper hook name is "pkt6_receive".
-TEST_F(HooksDhcpv6SrvTest, simplePkt6Receive) {
+TEST_F(HooksDhcpv6SrvTest, pkt6ReceiveSimple) {
// Install pkt6_receive_callout
EXPECT_NO_THROW(HooksManager::preCalloutsLibraryHandle().registerCallout(
@@ -1245,7 +1248,7 @@ TEST_F(HooksDhcpv6SrvTest, simplePkt6Receive) {
// Checks if callouts installed on pkt6_received is able to change
// the values and the parameters are indeed used by the server.
-TEST_F(HooksDhcpv6SrvTest, valueChangePkt6Receive) {
+TEST_F(HooksDhcpv6SrvTest, pkt6ReceiveValueChange) {
// Install pkt6_receive_change_clientid
EXPECT_NO_THROW(HooksManager::preCalloutsLibraryHandle().registerCallout(
@@ -1284,7 +1287,7 @@ TEST_F(HooksDhcpv6SrvTest, valueChangePkt6Receive) {
// Checks if callouts installed on pkt6_received is able to delete
// existing options and that change impacts server processing (mandatory
// client-id option is deleted, so the packet is expected to be dropped)
-TEST_F(HooksDhcpv6SrvTest, deleteClientIdPkt6Receive) {
+TEST_F(HooksDhcpv6SrvTest, pkt6ReceiveDeleteClientId) {
// Install pkt6_receive_delete_clientid
EXPECT_NO_THROW(HooksManager::preCalloutsLibraryHandle().registerCallout(
@@ -1311,7 +1314,7 @@ TEST_F(HooksDhcpv6SrvTest, deleteClientIdPkt6Receive) {
// Checks if callouts installed on pkt6_received is able to set skip flag that
// will cause the server to not process the packet (drop), even though it is valid.
-TEST_F(HooksDhcpv6SrvTest, skipPkt6Receive) {
+TEST_F(HooksDhcpv6SrvTest, pkt6ReceiveSkip) {
// Install pkt6_receive_skip
EXPECT_NO_THROW(HooksManager::preCalloutsLibraryHandle().registerCallout(
@@ -1338,7 +1341,7 @@ TEST_F(HooksDhcpv6SrvTest, skipPkt6Receive) {
// Checks if callouts installed on pkt6_received is able to set drop flag that
// will cause the server to not process the packet (drop), even though it is valid.
-TEST_F(HooksDhcpv6SrvTest, dropPkt6Receive) {
+TEST_F(HooksDhcpv6SrvTest, pkt6ReceiveDrop) {
// Install pkt6_receive_drop
EXPECT_NO_THROW(HooksManager::preCalloutsLibraryHandle().registerCallout(
@@ -1363,10 +1366,9 @@ TEST_F(HooksDhcpv6SrvTest, dropPkt6Receive) {
checkCalloutHandleReset(sol);
}
-
// Checks if callouts installed on pkt6_send are indeed called and the
// all necessary parameters are passed.
-TEST_F(HooksDhcpv6SrvTest, simplePkt6Send) {
+TEST_F(HooksDhcpv6SrvTest, pkt6SendSimple) {
// Install pkt6_send_callout
EXPECT_NO_THROW(HooksManager::preCalloutsLibraryHandle().registerCallout(
@@ -1393,7 +1395,9 @@ TEST_F(HooksDhcpv6SrvTest, simplePkt6Send) {
// Check that pkt6 argument passing was successful and returned proper
// values
+ ASSERT_TRUE(callback_qry_pkt6_);
EXPECT_TRUE(callback_qry_pkt6_.get() == sol.get());
+ ASSERT_TRUE(callback_resp_pkt6_);
EXPECT_TRUE(callback_resp_pkt6_.get() == adv.get());
// Check that all expected parameters are there
@@ -1412,7 +1416,7 @@ TEST_F(HooksDhcpv6SrvTest, simplePkt6Send) {
// Checks if callouts installed on pkt6_send is able to change
// the values and the packet sent contains those changes
-TEST_F(HooksDhcpv6SrvTest, valueChangePkt6Send) {
+TEST_F(HooksDhcpv6SrvTest, pkt6SendValueChange) {
// Install pkt6_send_change_serverid
EXPECT_NO_THROW(HooksManager::preCalloutsLibraryHandle().registerCallout(
@@ -1452,7 +1456,7 @@ TEST_F(HooksDhcpv6SrvTest, valueChangePkt6Send) {
// existing options and that server applies those changes. In particular,
// we are trying to send a packet without server-id. The packet should
// be sent
-TEST_F(HooksDhcpv6SrvTest, deleteServerIdPkt6Send) {
+TEST_F(HooksDhcpv6SrvTest, pkt6SendDeleteServerId) {
// Install pkt6_send_delete_serverid
EXPECT_NO_THROW(HooksManager::preCalloutsLibraryHandle().registerCallout(
@@ -1486,7 +1490,7 @@ TEST_F(HooksDhcpv6SrvTest, deleteServerIdPkt6Send) {
// Checks if callouts installed on pkt6_skip is able to set skip flag that
// will cause the server to send an empty response.
-TEST_F(HooksDhcpv6SrvTest, skipPkt6Send) {
+TEST_F(HooksDhcpv6SrvTest, pkt6SendSkip) {
// Install pkt6_send_skip
EXPECT_NO_THROW(HooksManager::preCalloutsLibraryHandle().registerCallout(
@@ -1507,8 +1511,8 @@ TEST_F(HooksDhcpv6SrvTest, skipPkt6Send) {
// Check that the server send the packet
ASSERT_EQ(1, srv_->fake_sent_.size());
- // But the sent packet should have 0 length (we told the server to
- // skip pack(), but did not do packing outselves)
+ // Get the first packet and check that it has zero length (i.e. the server
+ // did not do packing on its own)
Pkt6Ptr sent = srv_->fake_sent_.front();
// The actual size of sent packet should be 0
@@ -1520,7 +1524,7 @@ TEST_F(HooksDhcpv6SrvTest, skipPkt6Send) {
// Checks if callouts installed on pkt6_drop is able to set drop flag that
// will cause the server to not process the packet (drop), even though it is valid.
-TEST_F(HooksDhcpv6SrvTest, dropPkt6Send) {
+TEST_F(HooksDhcpv6SrvTest, pkt6SendDrop) {
// Install pkt6_send_drop
EXPECT_NO_THROW(HooksManager::preCalloutsLibraryHandle().registerCallout(
@@ -1547,7 +1551,7 @@ TEST_F(HooksDhcpv6SrvTest, dropPkt6Send) {
// Checks if callouts installed on buffer6_send are indeed called and the
// all necessary parameters are passed.
-TEST_F(HooksDhcpv6SrvTest, simpleBuffer6Send) {
+TEST_F(HooksDhcpv6SrvTest, buffer6SendSimple) {
// Install buffer6_send_callout
EXPECT_NO_THROW(HooksManager::preCalloutsLibraryHandle().registerCallout(
@@ -1572,8 +1576,7 @@ TEST_F(HooksDhcpv6SrvTest, simpleBuffer6Send) {
ASSERT_EQ(1, srv_->fake_sent_.size());
Pkt6Ptr adv = srv_->fake_sent_.front();
- // Check that pkt6 argument passing was successful and returned proper
- // values
+ // Check that pkt6 argument passing was successful and returned proper value
EXPECT_TRUE(callback_resp_pkt6_.get() == adv.get());
// Check that all expected parameters are there
@@ -1611,8 +1614,8 @@ TEST_F(HooksDhcpv6SrvTest, buffer6SendSkip) {
// Check that the callback called is indeed the one we installed
EXPECT_EQ("buffer6_send", callback_name_);
- // Check that there is no packet sent
- EXPECT_EQ(0, srv_->fake_sent_.size());
+ // Check that there is no packet sent.
+ ASSERT_EQ(0, srv_->fake_sent_.size());
// Check if the callout handle state was reset after the callout.
checkCalloutHandleReset(sol);
@@ -1650,7 +1653,7 @@ TEST_F(HooksDhcpv6SrvTest, buffer6SendDrop) {
// This test checks if subnet6_select callout is triggered and reports
// valid parameters
-TEST_F(HooksDhcpv6SrvTest, subnet6Select) {
+TEST_F(HooksDhcpv6SrvTest, subnet6SelectSimple) {
// Configure 2 subnets, both directly reachable over local interface
// (let's not complicate the matter with relays)
@@ -1680,6 +1683,7 @@ TEST_F(HooksDhcpv6SrvTest, subnet6Select) {
comment_ = isc::config::parseAnswer(rcode_, status);
ASSERT_EQ(0, rcode_);
+ // Commit the config
CfgMgr::instance().commit();
// Install subnet6_select_callout
@@ -1722,6 +1726,7 @@ TEST_F(HooksDhcpv6SrvTest, subnet6Select) {
// Server is supposed to report two subnets
ASSERT_EQ(exp_subnets->size(), callback_subnet6collection_->size());
+ ASSERT_GE(exp_subnets->size(), 2);
// Compare that the available subnets are reported as expected
EXPECT_TRUE((*exp_subnets->begin())->get() == (*callback_subnet6collection_->begin())->get());
@@ -2499,9 +2504,9 @@ TEST_F(HooksDhcpv6SrvTest, leases6CommittedRequestPrefix) {
}
// This test verifies that the callout installed on the leases6_committed hook
-// point is executed as a result of REQUEST message sent to reuse an
-// existing lease.
-TEST_F(HooksDhcpv6SrvTest, leases6CommittedCache) {
+// point is executed as a result of RENEW message sent to allocate new
+// lease or renew an existing lease.
+TEST_F(HooksDhcpv6SrvTest, leases6CommittedRenew) {
IfaceMgrTestConfig test_config(true);
string config = "{ \"interfaces-config\": {"
@@ -2513,8 +2518,7 @@ TEST_F(HooksDhcpv6SrvTest, leases6CommittedCache) {
"\"subnet6\": [ { "
" \"pools\": [ { \"pool\": \"2001:db8:1::/64\" } ],"
" \"subnet\": \"2001:db8:1::/48\", "
- " \"interface\": \"eth1\", "
- " \"cache-threshold\": .25 "
+ " \"interface\": \"eth1\" "
" } ],"
"\"valid-lifetime\": 4000 }";
@@ -2563,8 +2567,8 @@ TEST_F(HooksDhcpv6SrvTest, leases6CommittedCache) {
resetCalloutBuffers();
- // Request the lease and make sure that the callout has been executed.
- ASSERT_NO_THROW(client.doRequest());
+ // Renew the lease and make sure that the callout has been executed.
+ ASSERT_NO_THROW(client.doRenew());
// Make sure that we received a response
ASSERT_TRUE(client.getContext().response_);
@@ -2572,54 +2576,27 @@ TEST_F(HooksDhcpv6SrvTest, leases6CommittedCache) {
// Check that the callback called is indeed the one we installed
EXPECT_EQ("leases6_committed", callback_name_);
- // Requested lease should not be present, because it is reused.
+ // Renewed lease should be returned.
ASSERT_TRUE(callback_new_leases6_);
- EXPECT_TRUE(callback_new_leases6_->empty());
+ ASSERT_EQ(1, callback_new_leases6_->size());
+ lease = callback_new_leases6_->at(0);
+ ASSERT_TRUE(lease);
+ EXPECT_EQ("2001:db8:1::28", lease->addr_.toText());
- // Deleted lease must not be present, because it is renewed.
+ // Deleted lease must not be present, because it is a new allocation.
ASSERT_TRUE(callback_deleted_leases6_);
EXPECT_TRUE(callback_deleted_leases6_->empty());
// Pkt passed to a callout must be configured to copy retrieved options.
EXPECT_TRUE(callback_qry_options_copy_);
- // Check if the callout handle state was reset after the callout.
- checkCalloutHandleReset(client.getContext().query_);
-}
-
-// This test verifies that the callout installed on the leases6_committed hook
-// point is executed as a result of REQUEST message sent to reuse an
-// existing lease. Prefix variant.
-TEST_F(HooksDhcpv6SrvTest, leases6CommittedCachePrefix) {
- IfaceMgrTestConfig test_config(true);
-
- string config = "{ \"interfaces-config\": {"
- " \"interfaces\": [ \"*\" ]"
- "},"
- "\"preferred-lifetime\": 3000,"
- "\"rebind-timer\": 2000, "
- "\"renew-timer\": 1000, "
- "\"subnet6\": [ { "
- " \"pd-pools\": [ {"
- " \"prefix\": \"2001:db8:1::\", "
- " \"prefix-len\": 56, "
- " \"delegated-len\": 64 } ], "
- " \"subnet\": \"2001:db8:1::/48\", "
- " \"interface\": \"eth1\", "
- " \"cache-threshold\": .25 "
- " } ],"
- "\"valid-lifetime\": 4000 }";
-
- Dhcp6Client client;
- client.setInterface("eth1");
- client.requestPrefix(0xabca, 64, IOAddress("2001:db8:1:28::"));
-
- ASSERT_NO_THROW(configure(config, *client.getServer()));
+ resetCalloutBuffers();
- ASSERT_NO_THROW(HooksManager::preCalloutsLibraryHandle().registerCallout(
- "leases6_committed", leases6_committed_callout));
+ // Let's try to renew again but force the client to renew a different
+ // address with a different IAID.
+ client.requestAddress(0x2233, IOAddress("2001:db8:1::29"));
- ASSERT_NO_THROW(client.doSARR());
+ ASSERT_NO_THROW(client.doRenew());
// Make sure that we received a response
ASSERT_TRUE(client.getContext().response_);
@@ -2627,26 +2604,16 @@ TEST_F(HooksDhcpv6SrvTest, leases6CommittedCachePrefix) {
// Check that the callback called is indeed the one we installed
EXPECT_EQ("leases6_committed", callback_name_);
- // Check if all expected parameters were really received
- vector<string> expected_argument_names;
- expected_argument_names.push_back("query6");
- expected_argument_names.push_back("deleted_leases6");
- expected_argument_names.push_back("leases6");
-
- sort(expected_argument_names.begin(), expected_argument_names.end());
- EXPECT_TRUE(callback_argument_names_ == expected_argument_names);
-
- // Newly allocated lease should be returned.
+ // New lease should be returned.
ASSERT_TRUE(callback_new_leases6_);
- ASSERT_EQ(1, callback_new_leases6_->size());
- Lease6Ptr lease = callback_new_leases6_->at(0);
+ ASSERT_EQ(2, callback_new_leases6_->size());
+ lease = callback_new_leases6_->at(1);
ASSERT_TRUE(lease);
- EXPECT_EQ("2001:db8:1:28::", lease->addr_.toText());
- EXPECT_EQ(64, lease->prefixlen_);
+ EXPECT_EQ("2001:db8:1::29", lease->addr_.toText());
- // Deleted lease must not be present, because it is a new allocation.
+ // The old lease is kept.
ASSERT_TRUE(callback_deleted_leases6_);
- EXPECT_TRUE(callback_deleted_leases6_->empty());
+ ASSERT_TRUE(callback_deleted_leases6_->empty());
// Pkt passed to a callout must be configured to copy retrieved options.
EXPECT_TRUE(callback_qry_options_copy_);
@@ -2656,8 +2623,10 @@ TEST_F(HooksDhcpv6SrvTest, leases6CommittedCachePrefix) {
resetCalloutBuffers();
- // Request the lease and make sure that the callout has been executed.
- ASSERT_NO_THROW(client.doRequest());
+ // The renewed address is just a hint.
+ client.requestAddress(0x5577, IOAddress("4000::2"));
+
+ ASSERT_NO_THROW(client.doRenew());
// Make sure that we received a response
ASSERT_TRUE(client.getContext().response_);
@@ -2665,11 +2634,11 @@ TEST_F(HooksDhcpv6SrvTest, leases6CommittedCachePrefix) {
// Check that the callback called is indeed the one we installed
EXPECT_EQ("leases6_committed", callback_name_);
- // Requested lease should not be present, because it is reused.
ASSERT_TRUE(callback_new_leases6_);
- EXPECT_TRUE(callback_new_leases6_->empty());
-
- // Deleted lease must not be present, because it is renewed.
+ EXPECT_EQ(3, callback_new_leases6_->size());
+ lease = callback_new_leases6_->at(2);
+ ASSERT_TRUE(lease);
+ EXPECT_EQ("2001:db8:1::", lease->addr_.toText());
ASSERT_TRUE(callback_deleted_leases6_);
EXPECT_TRUE(callback_deleted_leases6_->empty());
@@ -2678,116 +2647,37 @@ TEST_F(HooksDhcpv6SrvTest, leases6CommittedCachePrefix) {
// Check if the callout handle state was reset after the callout.
checkCalloutHandleReset(client.getContext().query_);
-}
-
-// This test verifies that it is possible to park a packet as a result of
-// the leases6_committed callouts.
-TEST_F(HooksDhcpv6SrvTest, leases6CommittedParkRequests) {
- IfaceMgrTestConfig test_config(true);
-
- string config = "{ \"interfaces-config\": {"
- " \"interfaces\": [ \"*\" ]"
- "},"
- "\"preferred-lifetime\": 3000,"
- "\"rebind-timer\": 2000, "
- "\"renew-timer\": 1000, "
- "\"subnet6\": [ { "
- " \"pools\": [ { \"pool\": \"2001:db8:1::/64\" } ],"
- " \"subnet\": \"2001:db8:1::/48\", "
- " \"interface\": \"eth1\" "
- " } ],"
- "\"valid-lifetime\": 4000 }";
- // Create first client and perform SARR.
- Dhcp6Client client1;
- client1.setInterface("eth1");
- client1.requestAddress(0xabca, IOAddress("2001:db8:1::28"));
+ resetCalloutBuffers();
- ASSERT_NO_THROW(configure(config, *client1.getServer()));
+ // Renew a prefix: this should lead to an error as no prefix pool
+ // is configured.
+ client.requestPrefix(0x1122, 64, IOAddress("2001:db8:1000::"));
- // This callout uses provided IO service object to post a function
- // that unparks the packet. The packet is parked and can be unparked
- // by simply calling IOService::poll.
- ASSERT_NO_THROW(HooksManager::preCalloutsLibraryHandle().registerCallout(
- "leases6_committed", leases6_committed_park_callout));
+ ASSERT_NO_THROW(client.doRenew());
- ASSERT_NO_THROW(client1.doSARR());
+ // Make sure that we received a response
+ ASSERT_TRUE(client.getContext().response_);
- // We should be offered an address but the REPLY should not arrive
- // at this point, because the packet is parked.
- ASSERT_FALSE(client1.getContext().response_);
+ // Check the error.
+ EXPECT_EQ(STATUS_NoPrefixAvail, client.getStatusCode(0x1122));
// Check that the callback called is indeed the one we installed
EXPECT_EQ("leases6_committed", callback_name_);
- // Check if all expected parameters were really received
- vector<string> expected_argument_names;
- expected_argument_names.push_back("query6");
- expected_argument_names.push_back("deleted_leases6");
- expected_argument_names.push_back("leases6");
-
- sort(expected_argument_names.begin(), expected_argument_names.end());
- EXPECT_TRUE(callback_argument_names_ == expected_argument_names);
-
- // Newly allocated lease should be passed to the callout.
ASSERT_TRUE(callback_new_leases6_);
- ASSERT_EQ(1, callback_new_leases6_->size());
- Lease6Ptr lease = callback_new_leases6_->at(0);
- ASSERT_TRUE(lease);
- EXPECT_EQ("2001:db8:1::28", lease->addr_.toText());
-
- // Deleted lease must not be present, because it is a new allocation.
+ EXPECT_EQ(3, callback_new_leases6_->size());
ASSERT_TRUE(callback_deleted_leases6_);
EXPECT_TRUE(callback_deleted_leases6_->empty());
- // Pkt passed to a callout must be configured to copy retrieved options.
- EXPECT_TRUE(callback_qry_options_copy_);
-
// Check if the callout handle state was reset after the callout.
- checkCalloutHandleReset(client1.getContext().query_);
-
- // Reset all indicators because we'll be now creating a second client.
- resetCalloutBuffers();
-
- // Create the second client to test that it may communicate with the
- // server while the previous packet is parked.
- Dhcp6Client client2(client1.getServer());
- client2.setInterface("eth1");
- client2.requestAddress(0xabca, IOAddress("2001:db8:1::29"));
- ASSERT_NO_THROW(client2.doSARR());
-
- // The ADVERTISE should have been returned but not REPLAY, as this
- // packet got parked too.
- ASSERT_FALSE(client2.getContext().response_);
-
- // Check that the callback called is indeed the one we installed.
- EXPECT_EQ("leases6_committed", callback_name_);
-
- // There should be now two actions scheduled on our IO service
- // by the invoked callouts. They unpark both REPLY messages.
- ASSERT_NO_THROW(io_service_->poll());
-
- // Receive and check the first response.
- ASSERT_NO_THROW(client1.receiveResponse());
- ASSERT_TRUE(client1.getContext().response_);
- Pkt6Ptr rsp = client1.getContext().response_;
- EXPECT_EQ(DHCPV6_REPLY, rsp->getType());
- EXPECT_TRUE(client1.hasLeaseForAddress(IOAddress("2001:db8:1::28")));
-
- // Receive and check the second response.
- ASSERT_NO_THROW(client2.receiveResponse());
- ASSERT_TRUE(client2.getContext().response_);
- rsp = client2.getContext().response_;
- EXPECT_EQ(DHCPV6_REPLY, rsp->getType());
- EXPECT_TRUE(client2.hasLeaseForAddress(IOAddress("2001:db8:1::29")));
-
- // Check if the callout handle state was reset after the callout.
- checkCalloutHandleReset(client2.getContext().query_);
+ checkCalloutHandleReset(client.getContext().query_);
}
-// This test verifies that it is possible to park a packet as a result of
-// the leases6_committed callouts. Prefix variant.
-TEST_F(HooksDhcpv6SrvTest, leases6CommittedParkRequestsPrefixes) {
+// This test verifies that the callout installed on the leases6_committed hook
+// point is executed as a result of RENEW message sent to allocate new
+// lease or renew an existing lease. Prefix variant.
+TEST_F(HooksDhcpv6SrvTest, leases6CommittedRenewPrefix) {
IfaceMgrTestConfig test_config(true);
string config = "{ \"interfaces-config\": {"
@@ -2806,24 +2696,19 @@ TEST_F(HooksDhcpv6SrvTest, leases6CommittedParkRequestsPrefixes) {
" } ],"
"\"valid-lifetime\": 4000 }";
- // Create first client and perform SARR.
- Dhcp6Client client1;
- client1.setInterface("eth1");
- client1.requestPrefix(0xabca, 64, IOAddress("2001:db8:1:28::"));
+ Dhcp6Client client;
+ client.setInterface("eth1");
+ client.requestPrefix(0xabca, 64, IOAddress("2001:db8:1:28::"));
- ASSERT_NO_THROW(configure(config, *client1.getServer()));
+ ASSERT_NO_THROW(configure(config, *client.getServer()));
- // This callout uses provided IO service object to post a function
- // that unparks the packet. The packet is parked and can be unparked
- // by simply calling IOService::poll.
ASSERT_NO_THROW(HooksManager::preCalloutsLibraryHandle().registerCallout(
- "leases6_committed", leases6_committed_park_callout));
+ "leases6_committed", leases6_committed_callout));
- ASSERT_NO_THROW(client1.doSARR());
+ ASSERT_NO_THROW(client.doSARR());
- // We should be offered an address but the REPLY should not arrive
- // at this point, because the packet is parked.
- ASSERT_FALSE(client1.getContext().response_);
+ // Make sure that we received a response
+ ASSERT_TRUE(client.getContext().response_);
// Check that the callback called is indeed the one we installed
EXPECT_EQ("leases6_committed", callback_name_);
@@ -2837,7 +2722,7 @@ TEST_F(HooksDhcpv6SrvTest, leases6CommittedParkRequestsPrefixes) {
sort(expected_argument_names.begin(), expected_argument_names.end());
EXPECT_TRUE(callback_argument_names_ == expected_argument_names);
- // Newly allocated lease should be passed to the callout.
+ // Newly allocated lease should be returned.
ASSERT_TRUE(callback_new_leases6_);
ASSERT_EQ(1, callback_new_leases6_->size());
Lease6Ptr lease = callback_new_leases6_->at(0);
@@ -2852,331 +2737,125 @@ TEST_F(HooksDhcpv6SrvTest, leases6CommittedParkRequestsPrefixes) {
// Pkt passed to a callout must be configured to copy retrieved options.
EXPECT_TRUE(callback_qry_options_copy_);
- // Check if the callout handle state was reset after the callout.
- checkCalloutHandleReset(client1.getContext().query_);
-
- // Reset all indicators because we'll be now creating a second client.
resetCalloutBuffers();
- // Create the second client to test that it may communicate with the
- // server while the previous packet is parked.
- Dhcp6Client client2(client1.getServer());
- client2.setInterface("eth1");
- client2.requestPrefix(0xabca, 64, IOAddress("2001:db8:1:29::"));
- ASSERT_NO_THROW(client2.doSARR());
+ // Renew the lease and make sure that the callout has been executed.
+ ASSERT_NO_THROW(client.doRenew());
- // The ADVERTISE should have been returned but not REPLAY, as this
- // packet got parked too.
- ASSERT_FALSE(client2.getContext().response_);
+ // Make sure that we received a response
+ ASSERT_TRUE(client.getContext().response_);
- // Check that the callback called is indeed the one we installed.
+ // Check that the callback called is indeed the one we installed
EXPECT_EQ("leases6_committed", callback_name_);
- // There should be now two actions scheduled on our IO service
- // by the invoked callouts. They unpark both REPLY messages.
- ASSERT_NO_THROW(io_service_->poll());
+ // Renewed lease should be returned.
+ ASSERT_TRUE(callback_new_leases6_);
+ ASSERT_EQ(1, callback_new_leases6_->size());
+ lease = callback_new_leases6_->at(0);
+ ASSERT_TRUE(lease);
+ EXPECT_EQ("2001:db8:1:28::", lease->addr_.toText());
+ EXPECT_EQ(64, lease->prefixlen_);
- // Receive and check the first response.
- ASSERT_NO_THROW(client1.receiveResponse());
- ASSERT_TRUE(client1.getContext().response_);
- Pkt6Ptr rsp = client1.getContext().response_;
- EXPECT_EQ(DHCPV6_REPLY, rsp->getType());
- EXPECT_TRUE(client1.hasLeaseForPrefix(IOAddress("2001:db8:1:28::"), 64));
+ // Deleted lease must not be present, because it is a new allocation.
+ ASSERT_TRUE(callback_deleted_leases6_);
+ EXPECT_TRUE(callback_deleted_leases6_->empty());
- // Receive and check the second response.
- ASSERT_NO_THROW(client2.receiveResponse());
- ASSERT_TRUE(client2.getContext().response_);
- rsp = client2.getContext().response_;
- EXPECT_EQ(DHCPV6_REPLY, rsp->getType());
- EXPECT_TRUE(client2.hasLeaseForPrefix(IOAddress("2001:db8:1:29::"), 64));
+ // Pkt passed to a callout must be configured to copy retrieved options.
+ EXPECT_TRUE(callback_qry_options_copy_);
// Check if the callout handle state was reset after the callout.
- checkCalloutHandleReset(client2.getContext().query_);
-}
-
-// This test verifies that incoming (positive) RENEW can be handled properly,
-// and the lease6_renew callouts are triggered.
-TEST_F(HooksDhcpv6SrvTest, basicLease6Renew) {
- NakedDhcpv6Srv srv(0);
-
- // Install lease6_renew_callout
- EXPECT_NO_THROW(HooksManager::preCalloutsLibraryHandle().registerCallout(
- "lease6_renew", lease6_renew_callout));
-
- const IOAddress addr("2001:db8:1:1::cafe:babe");
- const uint32_t iaid = 234;
-
- // Generate client-id also duid_
- OptionPtr clientid = generateClientId();
-
- // Check that the address we are about to use is indeed in pool
- ASSERT_TRUE(subnet_->inPool(Lease::TYPE_NA, addr));
-
- // Note that preferred, valid, T1 and T2 timers and CLTT are set to invalid
- // value on purpose. They should be updated during RENEW.
- Lease6Ptr lease(new Lease6(Lease::TYPE_NA, addr, duid_, iaid,
- 501, 502, subnet_->getID(),
- HWAddrPtr(), 0));
- lease->cltt_ = 1234;
- ASSERT_TRUE(LeaseMgrFactory::instance().addLease(lease));
-
- // Check that the lease is really in the database
- Lease6Ptr l = LeaseMgrFactory::instance().getLease6(Lease::TYPE_NA,
- addr);
- ASSERT_TRUE(l);
+ checkCalloutHandleReset(client.getContext().query_);
- // Check that preferred, valid and cltt really set and not using
- // previous (500, 501, etc.) values
- EXPECT_NE(l->preferred_lft_, subnet_->getPreferred());
- EXPECT_NE(l->valid_lft_, subnet_->getValid());
- EXPECT_NE(l->cltt_, time(NULL));
+ resetCalloutBuffers();
- // Let's create a RENEW
- Pkt6Ptr req = Pkt6Ptr(new Pkt6(DHCPV6_RENEW, 1234));
- req->setRemoteAddr(IOAddress("fe80::abcd"));
- req->setIface("eth0");
- req->setIndex(ETH0_INDEX);
- boost::shared_ptr<Option6IA> ia = generateIA(D6O_IA_NA, iaid, 1500, 3000);
+ // Let's try to renew again but force the client to renew a different
+ // prefix with a different IAID.
+ client.requestPrefix(0x2233, 64, IOAddress("2001:db8:1:29::"));
- OptionPtr renewed_addr_opt(new Option6IAAddr(D6O_IAADDR, addr, 300, 500));
- ia->addOption(renewed_addr_opt);
- req->addOption(ia);
- req->addOption(clientid);
- // Server-id is mandatory in RENEW
- req->addOption(srv.getServerID());
+ ASSERT_NO_THROW(client.doRenew());
- // Pass it to the server and hope for a REPLY
- Pkt6Ptr reply = srv.processRenew(req);
- ASSERT_TRUE(reply);
+ // Make sure that we received a response
+ ASSERT_TRUE(client.getContext().response_);
// Check that the callback called is indeed the one we installed
- EXPECT_EQ("lease6_renew", callback_name_);
-
- // Check that appropriate parameters are passed to the callouts
- EXPECT_TRUE(callback_qry_pkt6_);
- EXPECT_TRUE(callback_lease6_);
- EXPECT_TRUE(callback_ia_na_);
-
- // Check if all expected parameters were really received
- vector<string> expected_argument_names;
- expected_argument_names.push_back("query6");
- expected_argument_names.push_back("lease6");
- expected_argument_names.push_back("ia_na");
-
- sort(callback_argument_names_.begin(), callback_argument_names_.end());
- sort(expected_argument_names.begin(), expected_argument_names.end());
-
- EXPECT_TRUE(callback_argument_names_ == expected_argument_names);
-
- // Check if we get response at all
- checkResponse(reply, DHCPV6_REPLY, 1234);
-
- OptionPtr tmp = reply->getOption(D6O_IA_NA);
- ASSERT_TRUE(tmp);
-
- // Check that IA_NA was returned and that there's an address included
- boost::shared_ptr<Option6IAAddr> addr_opt;
- ASSERT_NO_FATAL_FAILURE(addr_opt = checkIA_NA(reply, 234, subnet_->getT1(),
- subnet_->getT2()));
-
- ASSERT_TRUE(addr_opt);
- // Check that the lease is really in the database
- l = checkLease(duid_, reply->getOption(D6O_IA_NA), addr_opt);
- ASSERT_TRUE(l);
+ EXPECT_EQ("leases6_committed", callback_name_);
- // Check that the lease has been returned
- ASSERT_TRUE(callback_lease6_);
+ // New lease should be returned.
+ ASSERT_TRUE(callback_new_leases6_);
+ ASSERT_EQ(2, callback_new_leases6_->size());
+ lease = callback_new_leases6_->at(1);
+ ASSERT_TRUE(lease);
+ EXPECT_EQ("2001:db8:1:29::", lease->addr_.toText());
+ EXPECT_EQ(64, lease->prefixlen_);
- // Check that the returned lease6 in callout is the same as the one in the
- // database
- EXPECT_TRUE(*callback_lease6_ == *l);
+ // The old lease is kept.
+ ASSERT_TRUE(callback_deleted_leases6_);
+ ASSERT_TRUE(callback_deleted_leases6_->empty());
// Pkt passed to a callout must be configured to copy retrieved options.
EXPECT_TRUE(callback_qry_options_copy_);
// Check if the callout handle state was reset after the callout.
- checkCalloutHandleReset(req);
-}
-
-// This test verifies that incoming (positive) RENEW can be handled properly,
-// and the lease6_renew callouts are able to change the lease being updated.
-TEST_F(HooksDhcpv6SrvTest, leaseUpdateLease6Renew) {
- NakedDhcpv6Srv srv(0);
-
- // Install lease6_renew_update
- EXPECT_NO_THROW(HooksManager::preCalloutsLibraryHandle().registerCallout(
- "lease6_renew", lease6_renew_update));
-
- const IOAddress addr("2001:db8:1:1::cafe:babe");
- const uint32_t iaid = 234;
-
- // Generate client-id also duid_
- OptionPtr clientid = generateClientId();
-
- // Check that the address we are about to use is indeed in pool
- ASSERT_TRUE(subnet_->inPool(Lease::TYPE_NA, addr));
-
- // Note that preferred, valid, T1 and T2 timers and CLTT are set to invalid
- // value on purpose. They should be updated during RENEW.
- Lease6Ptr lease(new Lease6(Lease::TYPE_NA, addr, duid_, iaid,
- 501, 502, subnet_->getID(),
- HWAddrPtr(), 0));
- lease->cltt_ = 1234;
- ASSERT_TRUE(LeaseMgrFactory::instance().addLease(lease));
-
- // Check that the lease is really in the database
- Lease6Ptr l = LeaseMgrFactory::instance().getLease6(Lease::TYPE_NA,
- addr);
- ASSERT_TRUE(l);
-
- // Check that preferred, valid and cltt really set and not using
- // previous (500, 501, etc.) values
- EXPECT_NE(l->preferred_lft_, subnet_->getPreferred());
- EXPECT_NE(l->valid_lft_, subnet_->getValid());
- EXPECT_NE(l->cltt_, time(NULL));
-
- // Let's create a RENEW
- Pkt6Ptr req = Pkt6Ptr(new Pkt6(DHCPV6_RENEW, 1234));
- req->setRemoteAddr(IOAddress("fe80::abcd"));
- req->setIface("eth0");
- req->setIndex(ETH0_INDEX);
- boost::shared_ptr<Option6IA> ia = generateIA(D6O_IA_NA, iaid, 1500, 3000);
-
- OptionPtr renewed_addr_opt(new Option6IAAddr(D6O_IAADDR, addr, 300, 500));
- ia->addOption(renewed_addr_opt);
- req->addOption(ia);
- req->addOption(clientid);
-
- // Server-id is mandatory in RENEW
- req->addOption(srv.getServerID());
-
- // Turn on tee time calculation so we can see the effect of overriding
- // the lease life time.
- subnet_->setCalculateTeeTimes(true);
- Triplet<uint32_t> unspecified;
- subnet_->setT1(unspecified);
- subnet_->setT2(unspecified);
- subnet_->setT1Percent(0.60);
- subnet_->setT2Percent(0.80);
-
- // Pass it to the server and hope for a REPLY
- Pkt6Ptr reply = srv.processRenew(req);
- ASSERT_TRUE(reply);
-
- // Check if we get response at all
- checkResponse(reply, DHCPV6_REPLY, 1234);
+ checkCalloutHandleReset(client.getContext().query_);
- OptionPtr tmp = reply->getOption(D6O_IA_NA);
- ASSERT_TRUE(tmp);
+ resetCalloutBuffers();
- // Check that IA_NA was returned and that there's an address included
- boost::shared_ptr<Option6IAAddr> addr_opt;
- ASSERT_NO_FATAL_FAILURE(addr_opt = checkIA_NA(reply, 1000, 602, 802));
+ // The renewed prefix is just a hint.
+ client.requestPrefix(0x5577, 64, IOAddress("4000::1"));
- ASSERT_TRUE(addr_opt);
- // Check that the lease is really in the database
- l = checkLease(duid_, reply->getOption(D6O_IA_NA), addr_opt);
- ASSERT_TRUE(l);
+ ASSERT_NO_THROW(client.doRenew());
- // Check that we chose the distinct override values
- ASSERT_NE(override_preferred_, subnet_->getPreferred());
- EXPECT_NE(override_valid_, subnet_->getValid());
+ // Make sure that we received a response
+ ASSERT_TRUE(client.getContext().response_);
- // Check that preferred, valid were overridden the callout
- EXPECT_EQ(override_preferred_, l->preferred_lft_);
- EXPECT_EQ(override_valid_, l->valid_lft_);
+ // Check that the callback called is indeed the one we installed
+ EXPECT_EQ("leases6_committed", callback_name_);
- // Checking for CLTT is a bit tricky if we want to avoid off by 1 errors
- int32_t cltt = static_cast<int32_t>(l->cltt_);
- int32_t expected = static_cast<int32_t>(time(NULL));
- // Equality or difference by 1 between cltt and expected is ok.
- EXPECT_GE(1, abs(cltt - expected));
+ ASSERT_TRUE(callback_new_leases6_);
+ EXPECT_EQ(3, callback_new_leases6_->size());
+ lease = callback_new_leases6_->at(2);
+ ASSERT_TRUE(lease);
+ EXPECT_EQ("2001:db8:1::", lease->addr_.toText());
+ EXPECT_EQ(64, lease->prefixlen_);
+ ASSERT_TRUE(callback_deleted_leases6_);
+ EXPECT_TRUE(callback_deleted_leases6_->empty());
- Lease6Ptr deleted_lease =
- LeaseMgrFactory::instance().getLease6(Lease::TYPE_NA,
- addr_opt->getAddress());
- EXPECT_TRUE(LeaseMgrFactory::instance().deleteLease(deleted_lease));
+ // Pkt passed to a callout must be configured to copy retrieved options.
+ EXPECT_TRUE(callback_qry_options_copy_);
// Check if the callout handle state was reset after the callout.
- checkCalloutHandleReset(req);
-}
-
-// This test verifies that incoming (positive) RENEW can be handled properly,
-// and the lease6_renew callouts are able to set the skip flag that will
-// reject the renewal
-TEST_F(HooksDhcpv6SrvTest, skipLease6Renew) {
- NakedDhcpv6Srv srv(0);
-
- // Install lease6_renew_skip_callout
- EXPECT_NO_THROW(HooksManager::preCalloutsLibraryHandle().registerCallout(
- "lease6_renew", lease6_renew_skip_callout));
-
- const IOAddress addr("2001:db8:1:1::cafe:babe");
- const uint32_t iaid = 234;
-
- // Generate client-id also duid_
- OptionPtr clientid = generateClientId();
-
- // Check that the address we are about to use is indeed in pool
- ASSERT_TRUE(subnet_->inPool(Lease::TYPE_NA, addr));
-
- // Note that preferred, valid, T1 and T2 timers and CLTT are set to invalid
- // value on purpose. They should be updated during RENEW.
- Lease6Ptr lease(new Lease6(Lease::TYPE_NA, addr, duid_, iaid,
- 501, 502, subnet_->getID(),
- HWAddrPtr(), 0));
- lease->cltt_ = 1234;
- ASSERT_TRUE(LeaseMgrFactory::instance().addLease(lease));
-
- // Check that the lease is really in the database
- Lease6Ptr l = LeaseMgrFactory::instance().getLease6(Lease::TYPE_NA,
- addr);
- ASSERT_TRUE(l);
-
- // Check that preferred, valid and cltt are really set and not using
- // previous (500, 501, etc.) values
- EXPECT_NE(l->preferred_lft_, subnet_->getPreferred());
- EXPECT_NE(l->valid_lft_, subnet_->getValid());
- EXPECT_NE(l->cltt_, time(NULL));
+ checkCalloutHandleReset(client.getContext().query_);
- // Let's create a RENEW
- Pkt6Ptr req = Pkt6Ptr(new Pkt6(DHCPV6_RENEW, 1234));
- req->setRemoteAddr(IOAddress("fe80::abcd"));
- req->setIface("eth0");
- req->setIndex(ETH0_INDEX);
- boost::shared_ptr<Option6IA> ia = generateIA(D6O_IA_NA, iaid, 1500, 3000);
+ resetCalloutBuffers();
- OptionPtr renewed_addr_opt(new Option6IAAddr(D6O_IAADDR, addr, 300, 500));
- ia->addOption(renewed_addr_opt);
- req->addOption(ia);
- req->addOption(clientid);
+ // Renew an address: this should lead to an error as no address pool
+ // is configured.
+ client.requestAddress(0x1122, IOAddress("2001:db8:1::28"));
- // Server-id is mandatory in RENEW
- req->addOption(srv.getServerID());
+ ASSERT_NO_THROW(client.doRenew());
- // Pass it to the server and hope for a REPLY
- Pkt6Ptr reply = srv.processRenew(req);
- ASSERT_TRUE(reply);
+ // Make sure that we received a response
+ ASSERT_TRUE(client.getContext().response_);
- // Check that our callback was called
- EXPECT_EQ("lease6_renew", callback_name_);
+ // Check the error.
+ EXPECT_EQ(STATUS_NoAddrsAvail, client.getStatusCode(0x1122));
- l = LeaseMgrFactory::instance().getLease6(Lease::TYPE_NA, addr);
+ // Check that the callback called is indeed the one we installed
+ EXPECT_EQ("leases6_committed", callback_name_);
- // Check that the old values are still there and they were not
- // updated by the renewal
- EXPECT_NE(l->preferred_lft_, subnet_->getPreferred());
- EXPECT_NE(l->valid_lft_, subnet_->getValid());
- EXPECT_NE(l->cltt_, time(NULL));
+ ASSERT_TRUE(callback_new_leases6_);
+ EXPECT_EQ(3, callback_new_leases6_->size());
+ ASSERT_TRUE(callback_deleted_leases6_);
+ EXPECT_TRUE(callback_deleted_leases6_->empty());
// Check if the callout handle state was reset after the callout.
- checkCalloutHandleReset(req);
+ checkCalloutHandleReset(client.getContext().query_);
}
// This test verifies that the callout installed on the leases6_committed hook
-// point is executed as a result of RENEW message sent to allocate new
+// point is executed as a result of REBIND message sent to allocate new
// lease or renew an existing lease.
-TEST_F(HooksDhcpv6SrvTest, leases6CommittedRenew) {
+TEST_F(HooksDhcpv6SrvTest, leases6CommittedRebind) {
IfaceMgrTestConfig test_config(true);
string config = "{ \"interfaces-config\": {"
@@ -3237,8 +2916,8 @@ TEST_F(HooksDhcpv6SrvTest, leases6CommittedRenew) {
resetCalloutBuffers();
- // Renew the lease and make sure that the callout has been executed.
- ASSERT_NO_THROW(client.doRenew());
+ // Rebind the lease and make sure that the callout has been executed.
+ ASSERT_NO_THROW(client.doRebind());
// Make sure that we received a response
ASSERT_TRUE(client.getContext().response_);
@@ -3246,7 +2925,7 @@ TEST_F(HooksDhcpv6SrvTest, leases6CommittedRenew) {
// Check that the callback called is indeed the one we installed
EXPECT_EQ("leases6_committed", callback_name_);
- // Renewed lease should be returned.
+ // Rebound lease should be returned.
ASSERT_TRUE(callback_new_leases6_);
ASSERT_EQ(1, callback_new_leases6_->size());
lease = callback_new_leases6_->at(0);
@@ -3260,13 +2939,16 @@ TEST_F(HooksDhcpv6SrvTest, leases6CommittedRenew) {
// Pkt passed to a callout must be configured to copy retrieved options.
EXPECT_TRUE(callback_qry_options_copy_);
+ // Check if the callout handle state was reset after the callout.
+ checkCalloutHandleReset(client.getContext().query_);
+
resetCalloutBuffers();
- // Let's try to renew again but force the client to renew a different
+ // Let's try to rebind again but force the client to rebind a different
// address with a different IAID.
client.requestAddress(0x2233, IOAddress("2001:db8:1::29"));
- ASSERT_NO_THROW(client.doRenew());
+ ASSERT_NO_THROW(client.doRebind());
// Make sure that we received a response
ASSERT_TRUE(client.getContext().response_);
@@ -3293,10 +2975,10 @@ TEST_F(HooksDhcpv6SrvTest, leases6CommittedRenew) {
resetCalloutBuffers();
- // The renewed address is just a hint.
+ // The rebound address is just a hint.
client.requestAddress(0x5577, IOAddress("4000::2"));
- ASSERT_NO_THROW(client.doRenew());
+ ASSERT_NO_THROW(client.doRebind());
// Make sure that we received a response
ASSERT_TRUE(client.getContext().response_);
@@ -3320,11 +3002,11 @@ TEST_F(HooksDhcpv6SrvTest, leases6CommittedRenew) {
resetCalloutBuffers();
- // Renew a prefix: this should lead to an error as no prefix pool
+ // Rebind a prefix: this should lead to an error as no prefix pool
// is configured.
client.requestPrefix(0x1122, 64, IOAddress("2001:db8:1000::"));
- ASSERT_NO_THROW(client.doRenew());
+ ASSERT_NO_THROW(client.doRebind());
// Make sure that we received a response
ASSERT_TRUE(client.getContext().response_);
@@ -3345,9 +3027,9 @@ TEST_F(HooksDhcpv6SrvTest, leases6CommittedRenew) {
}
// This test verifies that the callout installed on the leases6_committed hook
-// point is executed as a result of RENEW message sent to allocate new
+// point is executed as a result of REBIND message sent to allocate new
// lease or renew an existing lease. Prefix variant.
-TEST_F(HooksDhcpv6SrvTest, leases6CommittedRenewPrefix) {
+TEST_F(HooksDhcpv6SrvTest, leases6CommittedRebindPrefix) {
IfaceMgrTestConfig test_config(true);
string config = "{ \"interfaces-config\": {"
@@ -3407,10 +3089,13 @@ TEST_F(HooksDhcpv6SrvTest, leases6CommittedRenewPrefix) {
// Pkt passed to a callout must be configured to copy retrieved options.
EXPECT_TRUE(callback_qry_options_copy_);
+ // Check if the callout handle state was reset after the callout.
+ checkCalloutHandleReset(client.getContext().query_);
+
resetCalloutBuffers();
- // Renew the lease and make sure that the callout has been executed.
- ASSERT_NO_THROW(client.doRenew());
+ // Rebind the lease and make sure that the callout has been executed.
+ ASSERT_NO_THROW(client.doRebind());
// Make sure that we received a response
ASSERT_TRUE(client.getContext().response_);
@@ -3418,7 +3103,7 @@ TEST_F(HooksDhcpv6SrvTest, leases6CommittedRenewPrefix) {
// Check that the callback called is indeed the one we installed
EXPECT_EQ("leases6_committed", callback_name_);
- // Renewed lease should be returned.
+ // Rebound lease should be returned.
ASSERT_TRUE(callback_new_leases6_);
ASSERT_EQ(1, callback_new_leases6_->size());
lease = callback_new_leases6_->at(0);
@@ -3438,11 +3123,11 @@ TEST_F(HooksDhcpv6SrvTest, leases6CommittedRenewPrefix) {
resetCalloutBuffers();
- // Let's try to renew again but force the client to renew a different
+ // Let's try to rebind again but force the client to rebind a different
// prefix with a different IAID.
client.requestPrefix(0x2233, 64, IOAddress("2001:db8:1:29::"));
- ASSERT_NO_THROW(client.doRenew());
+ ASSERT_NO_THROW(client.doRebind());
// Make sure that we received a response
ASSERT_TRUE(client.getContext().response_);
@@ -3470,10 +3155,10 @@ TEST_F(HooksDhcpv6SrvTest, leases6CommittedRenewPrefix) {
resetCalloutBuffers();
- // The renewed prefix is just a hint.
+ // The rebound prefix is just a hint.
client.requestPrefix(0x5577, 64, IOAddress("4000::1"));
- ASSERT_NO_THROW(client.doRenew());
+ ASSERT_NO_THROW(client.doRebind());
// Make sure that we received a response
ASSERT_TRUE(client.getContext().response_);
@@ -3498,11 +3183,11 @@ TEST_F(HooksDhcpv6SrvTest, leases6CommittedRenewPrefix) {
resetCalloutBuffers();
- // Renew an address: this should lead to an error as no address pool
+ // Rebind an address: this should lead to an error as no address pool
// is configured.
client.requestAddress(0x1122, IOAddress("2001:db8:1::28"));
- ASSERT_NO_THROW(client.doRenew());
+ ASSERT_NO_THROW(client.doRebind());
// Make sure that we received a response
ASSERT_TRUE(client.getContext().response_);
@@ -3522,308 +3207,136 @@ TEST_F(HooksDhcpv6SrvTest, leases6CommittedRenewPrefix) {
checkCalloutHandleReset(client.getContext().query_);
}
-// This test verifies that incoming (positive) RELEASE can be handled properly,
-// that a REPLY is generated, that the response has status code and that the
-// lease is indeed removed from the database.
-//
-// expected:
-// - returned REPLY message has copy of client-id
-// - returned REPLY message has server-id
-// - returned REPLY message has IA that does not include an IAADDR
-// - lease is actually removed from LeaseMgr
-TEST_F(HooksDhcpv6SrvTest, basicLease6Release) {
- NakedDhcpv6Srv srv(0);
-
- // Install lease6_release_callout
- EXPECT_NO_THROW(HooksManager::preCalloutsLibraryHandle().registerCallout(
- "lease6_release", lease6_release_callout));
-
- const IOAddress addr("2001:db8:1:1::cafe:babe");
- const uint32_t iaid = 234;
-
- // Generate client-id also duid_
- OptionPtr clientid = generateClientId();
-
- // Check that the address we are about to use is indeed in pool
- ASSERT_TRUE(subnet_->inPool(Lease::TYPE_NA, addr));
+// This test verifies that the leases6_committed callout is executed
+// when DECLINE is processed. The declined lease is expected to be passed
+// in leases6 argument to the callout.
+TEST_F(HooksDhcpv6SrvTest, leases6CommittedDecline) {
+ IfaceMgrTestConfig test_config(true);
- // Note that preferred, valid, T1 and T2 timers and CLTT are set to invalid
- // value on purpose. They should be updated during RENEW.
- Lease6Ptr lease(new Lease6(Lease::TYPE_NA, addr, duid_, iaid,
- 501, 502, subnet_->getID(),
- HWAddrPtr(), 0));
- lease->cltt_ = 1234;
- ASSERT_TRUE(LeaseMgrFactory::instance().addLease(lease));
+ string config = "{ \"interfaces-config\": {"
+ " \"interfaces\": [ \"*\" ]"
+ "},"
+ "\"preferred-lifetime\": 3000,"
+ "\"rebind-timer\": 2000, "
+ "\"renew-timer\": 1000, "
+ "\"subnet6\": [ { "
+ " \"pools\": [ { \"pool\": \"2001:db8:1::/64\" } ],"
+ " \"subnet\": \"2001:db8:1::/48\", "
+ " \"interface\": \"eth1\" "
+ " } ],"
+ "\"valid-lifetime\": 4000 }";
- // Check that the lease is really in the database
- Lease6Ptr l = LeaseMgrFactory::instance().getLease6(Lease::TYPE_NA,
- addr);
- ASSERT_TRUE(l);
+ Dhcp6Client client;
+ client.setInterface("eth1");
+ client.requestAddress(0xabca, IOAddress("2001:db8:1::28"));
- // Let's create a RELEASE
- Pkt6Ptr req = Pkt6Ptr(new Pkt6(DHCPV6_RELEASE, 1234));
- req->setRemoteAddr(IOAddress("fe80::abcd"));
- boost::shared_ptr<Option6IA> ia = generateIA(D6O_IA_NA, iaid, 1500, 3000);
+ ASSERT_NO_THROW(configure(config, *client.getServer()));
- OptionPtr released_addr_opt(new Option6IAAddr(D6O_IAADDR, addr, 300, 500));
- ia->addOption(released_addr_opt);
- req->addOption(ia);
- req->addOption(clientid);
+ ASSERT_NO_THROW(HooksManager::preCalloutsLibraryHandle().registerCallout(
+ "leases6_committed", leases6_committed_callout));
- // Server-id is mandatory in RELEASE
- req->addOption(srv.getServerID());
+ ASSERT_NO_THROW(client.doSARR());
- // Pass it to the server and hope for a REPLY
- Pkt6Ptr reply = srv.processRelease(req);
+ // Make sure that we received a response
+ ASSERT_TRUE(client.getContext().response_);
- ASSERT_TRUE(reply);
+ ASSERT_NO_THROW(client.doDecline());
// Check that the callback called is indeed the one we installed
- EXPECT_EQ("lease6_release", callback_name_);
-
- // Check that appropriate parameters are passed to the callouts
- EXPECT_TRUE(callback_qry_pkt6_);
- EXPECT_TRUE(callback_lease6_);
+ EXPECT_EQ("leases6_committed", callback_name_);
// Check if all expected parameters were really received
vector<string> expected_argument_names;
expected_argument_names.push_back("query6");
- expected_argument_names.push_back("lease6");
- sort(callback_argument_names_.begin(), callback_argument_names_.end());
+ expected_argument_names.push_back("deleted_leases6");
+ expected_argument_names.push_back("leases6");
+
sort(expected_argument_names.begin(), expected_argument_names.end());
EXPECT_TRUE(callback_argument_names_ == expected_argument_names);
- // Check that the lease is really gone in the database
- // get lease by address
- l = LeaseMgrFactory::instance().getLease6(Lease::TYPE_NA, addr);
- ASSERT_FALSE(l);
+ // No deleted leases.
+ ASSERT_TRUE(callback_deleted_leases6_);
+ ASSERT_TRUE(callback_deleted_leases6_->empty());
- // Get lease by subnetid/duid/iaid combination
- l = LeaseMgrFactory::instance().getLease6(Lease::TYPE_NA, *duid_, iaid,
- subnet_->getID());
- ASSERT_FALSE(l);
+ // Declined lease should be returned.
+ ASSERT_TRUE(callback_new_leases6_);
+ ASSERT_EQ(1, callback_new_leases6_->size());
+ Lease6Ptr lease = callback_new_leases6_->at(0);
+ ASSERT_TRUE(lease);
+ EXPECT_EQ("2001:db8:1::28", lease->addr_.toText());
// Pkt passed to a callout must be configured to copy retrieved options.
EXPECT_TRUE(callback_qry_options_copy_);
// Check if the callout handle state was reset after the callout.
- checkCalloutHandleReset(req);
+ checkCalloutHandleReset(client.getContext().query_);
}
-// This is a variant of the previous test that tests that callouts are
-// properly invoked for the prefix release case.
-TEST_F(HooksDhcpv6SrvTest, basicLease6ReleasePD) {
- NakedDhcpv6Srv srv(0);
-
- // Install lease6_release_callout
- EXPECT_NO_THROW(HooksManager::preCalloutsLibraryHandle().registerCallout(
- "lease6_release", lease6_release_callout));
-
- const IOAddress prefix("2001:db8:1:2:1::");
- const uint32_t iaid = 234;
-
- // Generate client-id also duid_
- OptionPtr clientid = generateClientId();
-
- // Check that the prefix we are about to use is indeed in pool
- ASSERT_TRUE(subnet_->inPool(Lease::TYPE_PD, prefix));
-
- // Note that preferred, valid, T1 and T2 timers and CLTT are set to invalid
- // value on purpose. They should be updated during RENEW.
- Lease6Ptr lease(new Lease6(Lease::TYPE_PD, prefix, duid_, iaid,
- 501, 502, subnet_->getID(),
- HWAddrPtr(), 80));
- lease->cltt_ = 1234;
- ASSERT_TRUE(LeaseMgrFactory::instance().addLease(lease));
+// This test verifies that the leases6_committed callout is executed
+// when DECLINE is processed. Variant with 2 IA_NAs.
+TEST_F(HooksDhcpv6SrvTest, leases6CommittedDeclineTwoNAs) {
+ IfaceMgrTestConfig test_config(true);
- // Check that the lease is really in the database
- Lease6Ptr l = LeaseMgrFactory::instance().getLease6(Lease::TYPE_PD,
- prefix);
- ASSERT_TRUE(l);
+ string config = "{ \"interfaces-config\": {"
+ " \"interfaces\": [ \"*\" ]"
+ "},"
+ "\"preferred-lifetime\": 3000,"
+ "\"rebind-timer\": 2000, "
+ "\"renew-timer\": 1000, "
+ "\"subnet6\": [ { "
+ " \"pools\": [ { \"pool\": \"2001:db8:1::/64\" } ],"
+ " \"subnet\": \"2001:db8:1::/48\", "
+ " \"interface\": \"eth1\" "
+ " } ],"
+ "\"valid-lifetime\": 4000 }";
- // Let's create a RELEASE
- Pkt6Ptr req = Pkt6Ptr(new Pkt6(DHCPV6_RELEASE, 1234));
- req->setRemoteAddr(IOAddress("fe80::abcd"));
- boost::shared_ptr<Option6IA> ia = generateIA(D6O_IA_PD, iaid, 1500, 3000);
+ Dhcp6Client client;
+ client.setInterface("eth1");
+ client.requestAddress(0xabca, IOAddress("2001:db8:1::28"));
+ client.requestAddress(0x2233, IOAddress("2001:db8:1::29"));
- OptionPtr released_addr_opt(new Option6IAPrefix(D6O_IAPREFIX, prefix, 80,
- 300, 500));
- ia->addOption(released_addr_opt);
- req->addOption(ia);
- req->addOption(clientid);
+ ASSERT_NO_THROW(configure(config, *client.getServer()));
- // Server-id is mandatory in RELEASE
- req->addOption(srv.getServerID());
+ ASSERT_NO_THROW(client.doSARR());
+ // Make sure that we received a response
+ ASSERT_TRUE(client.getContext().response_);
- // Pass it to the server and hope for a REPLY
- Pkt6Ptr reply = srv.processRelease(req);
+ ASSERT_NO_THROW(HooksManager::preCalloutsLibraryHandle().registerCallout(
+ "leases6_committed", leases6_committed_callout));
- ASSERT_TRUE(reply);
+ ASSERT_NO_THROW(client.doDecline());
// Check that the callback called is indeed the one we installed
- EXPECT_EQ("lease6_release", callback_name_);
-
- // Check that appropriate parameters are passed to the callouts
- EXPECT_TRUE(callback_qry_pkt6_);
- EXPECT_TRUE(callback_lease6_);
+ EXPECT_EQ("leases6_committed", callback_name_);
// Check if all expected parameters were really received
vector<string> expected_argument_names;
expected_argument_names.push_back("query6");
- expected_argument_names.push_back("lease6");
- sort(callback_argument_names_.begin(), callback_argument_names_.end());
+ expected_argument_names.push_back("deleted_leases6");
+ expected_argument_names.push_back("leases6");
+
sort(expected_argument_names.begin(), expected_argument_names.end());
EXPECT_TRUE(callback_argument_names_ == expected_argument_names);
- // Check that the lease is really gone in the database
- // get lease by address
- l = LeaseMgrFactory::instance().getLease6(Lease::TYPE_PD, prefix);
- ASSERT_FALSE(l);
+ // No deleted leases.
+ ASSERT_TRUE(callback_deleted_leases6_);
+ ASSERT_TRUE(callback_deleted_leases6_->empty());
- // Get lease by subnetid/duid/iaid combination
- l = LeaseMgrFactory::instance().getLease6(Lease::TYPE_PD, *duid_, iaid,
- subnet_->getID());
- ASSERT_FALSE(l);
+ // Declined lease should be returned.
+ ASSERT_TRUE(callback_new_leases6_);
+ ASSERT_EQ(2, callback_new_leases6_->size());
+ Lease6Ptr lease = callback_new_leases6_->at(0);
+ ASSERT_TRUE(lease);
+ EXPECT_EQ("2001:db8:1::28", lease->addr_.toText());
+ lease = callback_new_leases6_->at(1);
+ ASSERT_TRUE(lease);
+ EXPECT_EQ("2001:db8:1::29", lease->addr_.toText());
// Pkt passed to a callout must be configured to copy retrieved options.
EXPECT_TRUE(callback_qry_options_copy_);
// Check if the callout handle state was reset after the callout.
- checkCalloutHandleReset(req);
-}
-
-// This test verifies that skip flag returned by a callout installed on the
-// lease6_release hook point will keep the lease.
-TEST_F(HooksDhcpv6SrvTest, skipLease6Release) {
- NakedDhcpv6Srv srv(0);
-
- // Install lease6_release_skip
- EXPECT_NO_THROW(HooksManager::preCalloutsLibraryHandle().registerCallout(
- "lease6_release", lease6_release_skip));
-
- const IOAddress addr("2001:db8:1:1::cafe:babe");
- const uint32_t iaid = 234;
-
- // Generate client-id also duid_
- OptionPtr clientid = generateClientId();
-
- // Check that the address we are about to use is indeed in pool
- ASSERT_TRUE(subnet_->inPool(Lease::TYPE_NA, addr));
-
- // Note that preferred, valid, T1 and T2 timers and CLTT are set to invalid
- // value on purpose. They should be updated during RENEW.
- Lease6Ptr lease(new Lease6(Lease::TYPE_NA, addr, duid_, iaid,
- 501, 502, subnet_->getID(),
- HWAddrPtr(), 0));
- lease->cltt_ = 1234;
- ASSERT_TRUE(LeaseMgrFactory::instance().addLease(lease));
-
- // Check that the lease is really in the database
- Lease6Ptr l = LeaseMgrFactory::instance().getLease6(Lease::TYPE_NA,
- addr);
- ASSERT_TRUE(l);
-
- // Let's create a RELEASE
- Pkt6Ptr req = Pkt6Ptr(new Pkt6(DHCPV6_RELEASE, 1234));
- req->setRemoteAddr(IOAddress("fe80::abcd"));
- boost::shared_ptr<Option6IA> ia = generateIA(D6O_IA_NA, iaid, 1500, 3000);
-
- OptionPtr released_addr_opt(new Option6IAAddr(D6O_IAADDR, addr, 300, 500));
- ia->addOption(released_addr_opt);
- req->addOption(ia);
- req->addOption(clientid);
-
- // Server-id is mandatory in RELEASE
- req->addOption(srv.getServerID());
-
- // Pass it to the server and hope for a REPLY
- Pkt6Ptr reply = srv.processRelease(req);
-
- ASSERT_TRUE(reply);
-
- // Check that the callback called is indeed the one we installed
- EXPECT_EQ("lease6_release", callback_name_);
-
- // Check that the lease is still there
- // get lease by address
- l = LeaseMgrFactory::instance().getLease6(Lease::TYPE_NA,
- addr);
- ASSERT_TRUE(l);
-
- // Get lease by subnetid/duid/iaid combination
- l = LeaseMgrFactory::instance().getLease6(Lease::TYPE_NA, *duid_, iaid,
- subnet_->getID());
- ASSERT_TRUE(l);
-
- // Check if the callout handle state was reset after the callout.
- checkCalloutHandleReset(req);
-}
-
-// This test verifies that drop flag returned by a callout installed on the
-// lease6_release hook point will keep the lease.
-TEST_F(HooksDhcpv6SrvTest, dropLease6Release) {
- NakedDhcpv6Srv srv(0);
-
- // Install lease6_release_drop
- EXPECT_NO_THROW(HooksManager::preCalloutsLibraryHandle().registerCallout(
- "lease6_release", lease6_release_drop));
-
- const IOAddress addr("2001:db8:1:1::cafe:babe");
- const uint32_t iaid = 234;
-
- // Generate client-id also duid_
- OptionPtr clientid = generateClientId();
-
- // Check that the address we are about to use is indeed in pool
- ASSERT_TRUE(subnet_->inPool(Lease::TYPE_NA, addr));
-
- // Note that preferred, valid, T1 and T2 timers and CLTT are set to invalid
- // value on purpose. They should be updated during RENEW.
- Lease6Ptr lease(new Lease6(Lease::TYPE_NA, addr, duid_, iaid,
- 501, 502, subnet_->getID(),
- HWAddrPtr(), 0));
- lease->cltt_ = 1234;
- ASSERT_TRUE(LeaseMgrFactory::instance().addLease(lease));
-
- // Check that the lease is really in the database
- Lease6Ptr l = LeaseMgrFactory::instance().getLease6(Lease::TYPE_NA,
- addr);
- ASSERT_TRUE(l);
-
- // Let's create a RELEASE
- Pkt6Ptr req = Pkt6Ptr(new Pkt6(DHCPV6_RELEASE, 1234));
- req->setRemoteAddr(IOAddress("fe80::abcd"));
- boost::shared_ptr<Option6IA> ia = generateIA(D6O_IA_NA, iaid, 1500, 3000);
-
- OptionPtr released_addr_opt(new Option6IAAddr(D6O_IAADDR, addr, 300, 500));
- ia->addOption(released_addr_opt);
- req->addOption(ia);
- req->addOption(clientid);
-
- // Server-id is mandatory in RELEASE
- req->addOption(srv.getServerID());
-
- // Pass it to the server and hope for a REPLY
- Pkt6Ptr reply = srv.processRelease(req);
-
- ASSERT_TRUE(reply);
-
- // Check that the callback called is indeed the one we installed
- EXPECT_EQ("lease6_release", callback_name_);
-
- // Check that the lease is still there
- // get lease by address
- l = LeaseMgrFactory::instance().getLease6(Lease::TYPE_NA,
- addr);
- ASSERT_TRUE(l);
-
- // Get lease by subnetid/duid/iaid combination
- l = LeaseMgrFactory::instance().getLease6(Lease::TYPE_NA, *duid_, iaid,
- subnet_->getID());
- ASSERT_TRUE(l);
-
- // Check if the callout handle state was reset after the callout.
- checkCalloutHandleReset(req);
+ checkCalloutHandleReset(client.getContext().query_);
}
// This test verifies that the leases6_committed callout is executed
@@ -3850,13 +3363,14 @@ TEST_F(HooksDhcpv6SrvTest, leases6CommittedRelease) {
ASSERT_NO_THROW(configure(config, *client.getServer()));
+ ASSERT_NO_THROW(HooksManager::preCalloutsLibraryHandle().registerCallout(
+ "leases6_committed", leases6_committed_callout));
+
ASSERT_NO_THROW(client.doSARR());
+
// Make sure that we received a response
ASSERT_TRUE(client.getContext().response_);
- ASSERT_NO_THROW(HooksManager::preCalloutsLibraryHandle().registerCallout(
- "leases6_committed", leases6_committed_callout));
-
ASSERT_NO_THROW(client.doRelease());
// Check that the callback called is indeed the one we installed
@@ -3917,6 +3431,7 @@ TEST_F(HooksDhcpv6SrvTest, leases6CommittedReleasePrefix) {
ASSERT_NO_THROW(configure(config, *client.getServer()));
ASSERT_NO_THROW(client.doSARR());
+
// Make sure that we received a response
ASSERT_TRUE(client.getContext().response_);
@@ -4026,9 +3541,684 @@ TEST_F(HooksDhcpv6SrvTest, leases6CommittedReleaseMultiple) {
checkCalloutHandleReset(client.getContext().query_);
}
+// This test verifies that the callout installed on the leases6_committed hook
+// point is executed as a result of REQUEST message sent to reuse an
+// existing lease.
+TEST_F(HooksDhcpv6SrvTest, leases6CommittedCache) {
+ IfaceMgrTestConfig test_config(true);
+
+ string config = "{ \"interfaces-config\": {"
+ " \"interfaces\": [ \"*\" ]"
+ "},"
+ "\"preferred-lifetime\": 3000,"
+ "\"rebind-timer\": 2000, "
+ "\"renew-timer\": 1000, "
+ "\"subnet6\": [ { "
+ " \"pools\": [ { \"pool\": \"2001:db8:1::/64\" } ],"
+ " \"subnet\": \"2001:db8:1::/48\", "
+ " \"interface\": \"eth1\", "
+ " \"cache-threshold\": .25 "
+ " } ],"
+ "\"valid-lifetime\": 4000 }";
+
+ Dhcp6Client client;
+ client.setInterface("eth1");
+ client.requestAddress(0xabca, IOAddress("2001:db8:1::28"));
+
+ ASSERT_NO_THROW(configure(config, *client.getServer()));
+
+ ASSERT_NO_THROW(HooksManager::preCalloutsLibraryHandle().registerCallout(
+ "leases6_committed", leases6_committed_callout));
+
+ ASSERT_NO_THROW(client.doSARR());
+
+ // Make sure that we received a response
+ ASSERT_TRUE(client.getContext().response_);
+
+ // Check that the callback called is indeed the one we installed
+ EXPECT_EQ("leases6_committed", callback_name_);
+
+ // Check if all expected parameters were really received
+ vector<string> expected_argument_names;
+ expected_argument_names.push_back("query6");
+ expected_argument_names.push_back("deleted_leases6");
+ expected_argument_names.push_back("leases6");
+
+ sort(expected_argument_names.begin(), expected_argument_names.end());
+ EXPECT_TRUE(callback_argument_names_ == expected_argument_names);
+
+ // Newly allocated lease should be returned.
+ ASSERT_TRUE(callback_new_leases6_);
+ ASSERT_EQ(1, callback_new_leases6_->size());
+ Lease6Ptr lease = callback_new_leases6_->at(0);
+ ASSERT_TRUE(lease);
+ EXPECT_EQ("2001:db8:1::28", lease->addr_.toText());
+
+ // Deleted lease must not be present, because it is a new allocation.
+ ASSERT_TRUE(callback_deleted_leases6_);
+ EXPECT_TRUE(callback_deleted_leases6_->empty());
+
+ // Pkt passed to a callout must be configured to copy retrieved options.
+ EXPECT_TRUE(callback_qry_options_copy_);
+
+ // Check if the callout handle state was reset after the callout.
+ checkCalloutHandleReset(client.getContext().query_);
+
+ resetCalloutBuffers();
+
+ // Request the lease and make sure that the callout has been executed.
+ ASSERT_NO_THROW(client.doRequest());
+
+ // Make sure that we received a response
+ ASSERT_TRUE(client.getContext().response_);
+
+ // Check that the callback called is indeed the one we installed
+ EXPECT_EQ("leases6_committed", callback_name_);
+
+ // Requested lease should not be present, because it is reused.
+ ASSERT_TRUE(callback_new_leases6_);
+ EXPECT_TRUE(callback_new_leases6_->empty());
+
+ // Deleted lease must not be present, because it is renewed.
+ ASSERT_TRUE(callback_deleted_leases6_);
+ EXPECT_TRUE(callback_deleted_leases6_->empty());
+
+ // Pkt passed to a callout must be configured to copy retrieved options.
+ EXPECT_TRUE(callback_qry_options_copy_);
+
+ // Check if the callout handle state was reset after the callout.
+ checkCalloutHandleReset(client.getContext().query_);
+}
+
+// This test verifies that the callout installed on the leases6_committed hook
+// point is executed as a result of REQUEST message sent to reuse an
+// existing lease. Prefix variant.
+TEST_F(HooksDhcpv6SrvTest, leases6CommittedCachePrefix) {
+ IfaceMgrTestConfig test_config(true);
+
+ string config = "{ \"interfaces-config\": {"
+ " \"interfaces\": [ \"*\" ]"
+ "},"
+ "\"preferred-lifetime\": 3000,"
+ "\"rebind-timer\": 2000, "
+ "\"renew-timer\": 1000, "
+ "\"subnet6\": [ { "
+ " \"pd-pools\": [ {"
+ " \"prefix\": \"2001:db8:1::\", "
+ " \"prefix-len\": 56, "
+ " \"delegated-len\": 64 } ], "
+ " \"subnet\": \"2001:db8:1::/48\", "
+ " \"interface\": \"eth1\", "
+ " \"cache-threshold\": .25 "
+ " } ],"
+ "\"valid-lifetime\": 4000 }";
+
+ Dhcp6Client client;
+ client.setInterface("eth1");
+ client.requestPrefix(0xabca, 64, IOAddress("2001:db8:1:28::"));
+
+ ASSERT_NO_THROW(configure(config, *client.getServer()));
+
+ ASSERT_NO_THROW(HooksManager::preCalloutsLibraryHandle().registerCallout(
+ "leases6_committed", leases6_committed_callout));
+
+ ASSERT_NO_THROW(client.doSARR());
+
+ // Make sure that we received a response
+ ASSERT_TRUE(client.getContext().response_);
+
+ // Check that the callback called is indeed the one we installed
+ EXPECT_EQ("leases6_committed", callback_name_);
+
+ // Check if all expected parameters were really received
+ vector<string> expected_argument_names;
+ expected_argument_names.push_back("query6");
+ expected_argument_names.push_back("deleted_leases6");
+ expected_argument_names.push_back("leases6");
+
+ sort(expected_argument_names.begin(), expected_argument_names.end());
+ EXPECT_TRUE(callback_argument_names_ == expected_argument_names);
+
+ // Newly allocated lease should be returned.
+ ASSERT_TRUE(callback_new_leases6_);
+ ASSERT_EQ(1, callback_new_leases6_->size());
+ Lease6Ptr lease = callback_new_leases6_->at(0);
+ ASSERT_TRUE(lease);
+ EXPECT_EQ("2001:db8:1:28::", lease->addr_.toText());
+ EXPECT_EQ(64, lease->prefixlen_);
+
+ // Deleted lease must not be present, because it is a new allocation.
+ ASSERT_TRUE(callback_deleted_leases6_);
+ EXPECT_TRUE(callback_deleted_leases6_->empty());
+
+ // Pkt passed to a callout must be configured to copy retrieved options.
+ EXPECT_TRUE(callback_qry_options_copy_);
+
+ // Check if the callout handle state was reset after the callout.
+ checkCalloutHandleReset(client.getContext().query_);
+
+ resetCalloutBuffers();
+
+ // Request the lease and make sure that the callout has been executed.
+ ASSERT_NO_THROW(client.doRequest());
+
+ // Make sure that we received a response
+ ASSERT_TRUE(client.getContext().response_);
+
+ // Check that the callback called is indeed the one we installed
+ EXPECT_EQ("leases6_committed", callback_name_);
+
+ // Requested lease should not be present, because it is reused.
+ ASSERT_TRUE(callback_new_leases6_);
+ EXPECT_TRUE(callback_new_leases6_->empty());
+
+ // Deleted lease must not be present, because it is renewed.
+ ASSERT_TRUE(callback_deleted_leases6_);
+ EXPECT_TRUE(callback_deleted_leases6_->empty());
+
+ // Pkt passed to a callout must be configured to copy retrieved options.
+ EXPECT_TRUE(callback_qry_options_copy_);
+
+ // Check if the callout handle state was reset after the callout.
+ checkCalloutHandleReset(client.getContext().query_);
+}
+
+// This test verifies that it is possible to park a packet as a result of
+// the leases6_committed callouts.
+TEST_F(HooksDhcpv6SrvTest, leases6CommittedParkRequests) {
+ IfaceMgrTestConfig test_config(true);
+
+ string config = "{ \"interfaces-config\": {"
+ " \"interfaces\": [ \"*\" ]"
+ "},"
+ "\"preferred-lifetime\": 3000,"
+ "\"rebind-timer\": 2000, "
+ "\"renew-timer\": 1000, "
+ "\"subnet6\": [ { "
+ " \"pools\": [ { \"pool\": \"2001:db8:1::/64\" } ],"
+ " \"subnet\": \"2001:db8:1::/48\", "
+ " \"interface\": \"eth1\" "
+ " } ],"
+ "\"valid-lifetime\": 4000 }";
+
+ // Create first client and perform SARR.
+ Dhcp6Client client1;
+ client1.setInterface("eth1");
+ client1.requestAddress(0xabca, IOAddress("2001:db8:1::28"));
+
+ ASSERT_NO_THROW(configure(config, *client1.getServer()));
+
+ // This callout uses provided IO service object to post a function
+ // that unparks the packet. The packet is parked and can be unparked
+ // by simply calling IOService::poll.
+ ASSERT_NO_THROW(HooksManager::preCalloutsLibraryHandle().registerCallout(
+ "leases6_committed", leases6_committed_park_callout));
+
+ ASSERT_NO_THROW(client1.doSARR());
+
+ // We should be offered an address but the REPLY should not arrive
+ // at this point, because the packet is parked.
+ ASSERT_FALSE(client1.getContext().response_);
+
+ // Check that the callback called is indeed the one we installed
+ EXPECT_EQ("leases6_committed", callback_name_);
+
+ // Check if all expected parameters were really received
+ vector<string> expected_argument_names;
+ expected_argument_names.push_back("query6");
+ expected_argument_names.push_back("deleted_leases6");
+ expected_argument_names.push_back("leases6");
+
+ sort(expected_argument_names.begin(), expected_argument_names.end());
+ EXPECT_TRUE(callback_argument_names_ == expected_argument_names);
+
+ // Newly allocated lease should be passed to the callout.
+ ASSERT_TRUE(callback_new_leases6_);
+ ASSERT_EQ(1, callback_new_leases6_->size());
+ Lease6Ptr lease = callback_new_leases6_->at(0);
+ ASSERT_TRUE(lease);
+ EXPECT_EQ("2001:db8:1::28", lease->addr_.toText());
+
+ // Deleted lease must not be present, because it is a new allocation.
+ ASSERT_TRUE(callback_deleted_leases6_);
+ EXPECT_TRUE(callback_deleted_leases6_->empty());
+
+ // Pkt passed to a callout must be configured to copy retrieved options.
+ EXPECT_TRUE(callback_qry_options_copy_);
+
+ // Check if the callout handle state was reset after the callout.
+ checkCalloutHandleReset(client1.getContext().query_);
+
+ // Reset all indicators because we'll be now creating a second client.
+ resetCalloutBuffers();
+
+ // Create the second client to test that it may communicate with the
+ // server while the previous packet is parked.
+ Dhcp6Client client2(client1.getServer());
+ client2.setInterface("eth1");
+ client2.requestAddress(0xabca, IOAddress("2001:db8:1::29"));
+ ASSERT_NO_THROW(client2.doSARR());
+
+ // The ADVERTISE should have been returned but not REPLAY, as this
+ // packet got parked too.
+ ASSERT_FALSE(client2.getContext().response_);
+
+ // Check that the callback called is indeed the one we installed.
+ EXPECT_EQ("leases6_committed", callback_name_);
+
+ // There should be now two actions scheduled on our IO service
+ // by the invoked callouts. They unpark both REPLY messages.
+ ASSERT_NO_THROW(io_service_->poll());
+
+ // Receive and check the first response.
+ ASSERT_NO_THROW(client1.receiveResponse());
+ ASSERT_TRUE(client1.getContext().response_);
+ Pkt6Ptr rsp = client1.getContext().response_;
+ EXPECT_EQ(DHCPV6_REPLY, rsp->getType());
+ EXPECT_TRUE(client1.hasLeaseForAddress(IOAddress("2001:db8:1::28")));
+
+ // Receive and check the second response.
+ ASSERT_NO_THROW(client2.receiveResponse());
+ ASSERT_TRUE(client2.getContext().response_);
+ rsp = client2.getContext().response_;
+ EXPECT_EQ(DHCPV6_REPLY, rsp->getType());
+ EXPECT_TRUE(client2.hasLeaseForAddress(IOAddress("2001:db8:1::29")));
+
+ // Check if the callout handle state was reset after the callout.
+ checkCalloutHandleReset(client2.getContext().query_);
+}
+
+// This test verifies that it is possible to park a packet as a result of
+// the leases6_committed callouts. Prefix variant.
+TEST_F(HooksDhcpv6SrvTest, leases6CommittedParkRequestsPrefixes) {
+ IfaceMgrTestConfig test_config(true);
+
+ string config = "{ \"interfaces-config\": {"
+ " \"interfaces\": [ \"*\" ]"
+ "},"
+ "\"preferred-lifetime\": 3000,"
+ "\"rebind-timer\": 2000, "
+ "\"renew-timer\": 1000, "
+ "\"subnet6\": [ { "
+ " \"pd-pools\": [ {"
+ " \"prefix\": \"2001:db8:1::\", "
+ " \"prefix-len\": 56, "
+ " \"delegated-len\": 64 } ], "
+ " \"subnet\": \"2001:db8:1::/48\", "
+ " \"interface\": \"eth1\" "
+ " } ],"
+ "\"valid-lifetime\": 4000 }";
+
+ // Create first client and perform SARR.
+ Dhcp6Client client1;
+ client1.setInterface("eth1");
+ client1.requestPrefix(0xabca, 64, IOAddress("2001:db8:1:28::"));
+
+ ASSERT_NO_THROW(configure(config, *client1.getServer()));
+
+ // This callout uses provided IO service object to post a function
+ // that unparks the packet. The packet is parked and can be unparked
+ // by simply calling IOService::poll.
+ ASSERT_NO_THROW(HooksManager::preCalloutsLibraryHandle().registerCallout(
+ "leases6_committed", leases6_committed_park_callout));
+
+ ASSERT_NO_THROW(client1.doSARR());
+
+ // We should be offered an address but the REPLY should not arrive
+ // at this point, because the packet is parked.
+ ASSERT_FALSE(client1.getContext().response_);
+
+ // Check that the callback called is indeed the one we installed
+ EXPECT_EQ("leases6_committed", callback_name_);
+
+ // Check if all expected parameters were really received
+ vector<string> expected_argument_names;
+ expected_argument_names.push_back("query6");
+ expected_argument_names.push_back("deleted_leases6");
+ expected_argument_names.push_back("leases6");
+
+ sort(expected_argument_names.begin(), expected_argument_names.end());
+ EXPECT_TRUE(callback_argument_names_ == expected_argument_names);
+
+ // Newly allocated lease should be passed to the callout.
+ ASSERT_TRUE(callback_new_leases6_);
+ ASSERT_EQ(1, callback_new_leases6_->size());
+ Lease6Ptr lease = callback_new_leases6_->at(0);
+ ASSERT_TRUE(lease);
+ EXPECT_EQ("2001:db8:1:28::", lease->addr_.toText());
+ EXPECT_EQ(64, lease->prefixlen_);
+
+ // Deleted lease must not be present, because it is a new allocation.
+ ASSERT_TRUE(callback_deleted_leases6_);
+ EXPECT_TRUE(callback_deleted_leases6_->empty());
+
+ // Pkt passed to a callout must be configured to copy retrieved options.
+ EXPECT_TRUE(callback_qry_options_copy_);
+
+ // Check if the callout handle state was reset after the callout.
+ checkCalloutHandleReset(client1.getContext().query_);
+
+ // Reset all indicators because we'll be now creating a second client.
+ resetCalloutBuffers();
+
+ // Create the second client to test that it may communicate with the
+ // server while the previous packet is parked.
+ Dhcp6Client client2(client1.getServer());
+ client2.setInterface("eth1");
+ client2.requestPrefix(0xabca, 64, IOAddress("2001:db8:1:29::"));
+ ASSERT_NO_THROW(client2.doSARR());
+
+ // The ADVERTISE should have been returned but not REPLAY, as this
+ // packet got parked too.
+ ASSERT_FALSE(client2.getContext().response_);
+
+ // Check that the callback called is indeed the one we installed.
+ EXPECT_EQ("leases6_committed", callback_name_);
+
+ // There should be now two actions scheduled on our IO service
+ // by the invoked callouts. They unpark both REPLY messages.
+ ASSERT_NO_THROW(io_service_->poll());
+
+ // Receive and check the first response.
+ ASSERT_NO_THROW(client1.receiveResponse());
+ ASSERT_TRUE(client1.getContext().response_);
+ Pkt6Ptr rsp = client1.getContext().response_;
+ EXPECT_EQ(DHCPV6_REPLY, rsp->getType());
+ EXPECT_TRUE(client1.hasLeaseForPrefix(IOAddress("2001:db8:1:28::"), 64));
+
+ // Receive and check the second response.
+ ASSERT_NO_THROW(client2.receiveResponse());
+ ASSERT_TRUE(client2.getContext().response_);
+ rsp = client2.getContext().response_;
+ EXPECT_EQ(DHCPV6_REPLY, rsp->getType());
+ EXPECT_TRUE(client2.hasLeaseForPrefix(IOAddress("2001:db8:1:29::"), 64));
+
+ // Check if the callout handle state was reset after the callout.
+ checkCalloutHandleReset(client2.getContext().query_);
+}
+
+// This test verifies that incoming (positive) RENEW can be handled properly,
+// and the lease6_renew callouts are triggered.
+TEST_F(HooksDhcpv6SrvTest, lease6RenewSimple) {
+ NakedDhcpv6Srv srv(0);
+
+ // Install lease6_renew_callout
+ EXPECT_NO_THROW(HooksManager::preCalloutsLibraryHandle().registerCallout(
+ "lease6_renew", lease6_renew_callout));
+
+ const IOAddress addr("2001:db8:1:1::cafe:babe");
+ const uint32_t iaid = 234;
+
+ // Generate client-id also duid_
+ OptionPtr clientid = generateClientId();
+
+ // Check that the address we are about to use is indeed in pool
+ ASSERT_TRUE(subnet_->inPool(Lease::TYPE_NA, addr));
+
+ // Note that preferred, valid, T1 and T2 timers and CLTT are set to invalid
+ // value on purpose. They should be updated during RENEW.
+ Lease6Ptr lease(new Lease6(Lease::TYPE_NA, addr, duid_, iaid,
+ 501, 502, subnet_->getID(),
+ HWAddrPtr(), 0));
+ lease->cltt_ = 1234;
+ ASSERT_TRUE(LeaseMgrFactory::instance().addLease(lease));
+
+ // Check that the lease is really in the database
+ Lease6Ptr l = LeaseMgrFactory::instance().getLease6(Lease::TYPE_NA,
+ addr);
+ ASSERT_TRUE(l);
+
+ // Check that preferred, valid and cltt really set and not using
+ // previous (500, 501, etc.) values
+ EXPECT_NE(l->preferred_lft_, subnet_->getPreferred());
+ EXPECT_NE(l->valid_lft_, subnet_->getValid());
+ EXPECT_NE(l->cltt_, time(NULL));
+
+ // Let's create a RENEW
+ Pkt6Ptr req = Pkt6Ptr(new Pkt6(DHCPV6_RENEW, 1234));
+ req->setRemoteAddr(IOAddress("fe80::abcd"));
+ req->setIface("eth0");
+ req->setIndex(ETH0_INDEX);
+ boost::shared_ptr<Option6IA> ia = generateIA(D6O_IA_NA, iaid, 1500, 3000);
+
+ OptionPtr renewed_addr_opt(new Option6IAAddr(D6O_IAADDR, addr, 300, 500));
+ ia->addOption(renewed_addr_opt);
+ req->addOption(ia);
+ req->addOption(clientid);
+ // Server-id is mandatory in RENEW
+ req->addOption(srv.getServerID());
+
+ // Pass it to the server and hope for a REPLY
+ Pkt6Ptr reply = srv.processRenew(req);
+ ASSERT_TRUE(reply);
+
+ // Check that the callback called is indeed the one we installed
+ EXPECT_EQ("lease6_renew", callback_name_);
+
+ // Check that appropriate parameters are passed to the callouts
+ EXPECT_TRUE(callback_qry_pkt6_);
+ EXPECT_TRUE(callback_lease6_);
+ EXPECT_TRUE(callback_ia_na_);
+
+ // Check if all expected parameters were really received
+ vector<string> expected_argument_names;
+ expected_argument_names.push_back("query6");
+ expected_argument_names.push_back("lease6");
+ expected_argument_names.push_back("ia_na");
+
+ sort(callback_argument_names_.begin(), callback_argument_names_.end());
+ sort(expected_argument_names.begin(), expected_argument_names.end());
+
+ EXPECT_TRUE(callback_argument_names_ == expected_argument_names);
+
+ // Check if we get response at all
+ checkResponse(reply, DHCPV6_REPLY, 1234);
+
+ OptionPtr tmp = reply->getOption(D6O_IA_NA);
+ ASSERT_TRUE(tmp);
+
+ // Check that IA_NA was returned and that there's an address included
+ boost::shared_ptr<Option6IAAddr> addr_opt;
+ ASSERT_NO_FATAL_FAILURE(addr_opt = checkIA_NA(reply, 234, subnet_->getT1(),
+ subnet_->getT2()));
+
+ ASSERT_TRUE(addr_opt);
+ // Check that the lease is really in the database
+ l = checkLease(duid_, reply->getOption(D6O_IA_NA), addr_opt);
+ ASSERT_TRUE(l);
+
+ // Check that the lease has been returned
+ ASSERT_TRUE(callback_lease6_);
+
+ // Check that the returned lease6 in callout is the same as the one in the
+ // database
+ EXPECT_TRUE(*callback_lease6_ == *l);
+
+ // Pkt passed to a callout must be configured to copy retrieved options.
+ EXPECT_TRUE(callback_qry_options_copy_);
+
+ // Check if the callout handle state was reset after the callout.
+ checkCalloutHandleReset(req);
+}
+
+// This test verifies that incoming (positive) RENEW can be handled properly,
+// and the lease6_renew callouts are able to change the lease being updated.
+TEST_F(HooksDhcpv6SrvTest, lease6RenewLeaseUpdate) {
+ NakedDhcpv6Srv srv(0);
+
+ // Install lease6_renew_update
+ EXPECT_NO_THROW(HooksManager::preCalloutsLibraryHandle().registerCallout(
+ "lease6_renew", lease6_renew_update));
+
+ const IOAddress addr("2001:db8:1:1::cafe:babe");
+ const uint32_t iaid = 234;
+
+ // Generate client-id also duid_
+ OptionPtr clientid = generateClientId();
+
+ // Check that the address we are about to use is indeed in pool
+ ASSERT_TRUE(subnet_->inPool(Lease::TYPE_NA, addr));
+
+ // Note that preferred, valid, T1 and T2 timers and CLTT are set to invalid
+ // value on purpose. They should be updated during RENEW.
+ Lease6Ptr lease(new Lease6(Lease::TYPE_NA, addr, duid_, iaid,
+ 501, 502, subnet_->getID(),
+ HWAddrPtr(), 0));
+ lease->cltt_ = 1234;
+ ASSERT_TRUE(LeaseMgrFactory::instance().addLease(lease));
+
+ // Check that the lease is really in the database
+ Lease6Ptr l = LeaseMgrFactory::instance().getLease6(Lease::TYPE_NA,
+ addr);
+ ASSERT_TRUE(l);
+
+ // Check that preferred, valid and cltt really set and not using
+ // previous (500, 501, etc.) values
+ EXPECT_NE(l->preferred_lft_, subnet_->getPreferred());
+ EXPECT_NE(l->valid_lft_, subnet_->getValid());
+ EXPECT_NE(l->cltt_, time(NULL));
+
+ // Let's create a RENEW
+ Pkt6Ptr req = Pkt6Ptr(new Pkt6(DHCPV6_RENEW, 1234));
+ req->setRemoteAddr(IOAddress("fe80::abcd"));
+ req->setIface("eth0");
+ req->setIndex(ETH0_INDEX);
+ boost::shared_ptr<Option6IA> ia = generateIA(D6O_IA_NA, iaid, 1500, 3000);
+
+ OptionPtr renewed_addr_opt(new Option6IAAddr(D6O_IAADDR, addr, 300, 500));
+ ia->addOption(renewed_addr_opt);
+ req->addOption(ia);
+ req->addOption(clientid);
+
+ // Server-id is mandatory in RENEW
+ req->addOption(srv.getServerID());
+
+ // Turn on tee time calculation so we can see the effect of overriding
+ // the lease life time.
+ subnet_->setCalculateTeeTimes(true);
+ Triplet<uint32_t> unspecified;
+ subnet_->setT1(unspecified);
+ subnet_->setT2(unspecified);
+ subnet_->setT1Percent(0.60);
+ subnet_->setT2Percent(0.80);
+
+ // Pass it to the server and hope for a REPLY
+ Pkt6Ptr reply = srv.processRenew(req);
+ ASSERT_TRUE(reply);
+
+ // Check if we get response at all
+ checkResponse(reply, DHCPV6_REPLY, 1234);
+
+ OptionPtr tmp = reply->getOption(D6O_IA_NA);
+ ASSERT_TRUE(tmp);
+
+ // Check that IA_NA was returned and that there's an address included
+ boost::shared_ptr<Option6IAAddr> addr_opt;
+ ASSERT_NO_FATAL_FAILURE(addr_opt = checkIA_NA(reply, 1000, 602, 802));
+
+ ASSERT_TRUE(addr_opt);
+ // Check that the lease is really in the database
+ l = checkLease(duid_, reply->getOption(D6O_IA_NA), addr_opt);
+ ASSERT_TRUE(l);
+
+ // Check that we chose the distinct override values
+ ASSERT_NE(override_preferred_, subnet_->getPreferred());
+ EXPECT_NE(override_valid_, subnet_->getValid());
+
+ // Check that preferred, valid were overridden the callout
+ EXPECT_EQ(override_preferred_, l->preferred_lft_);
+ EXPECT_EQ(override_valid_, l->valid_lft_);
+
+ // Checking for CLTT is a bit tricky if we want to avoid off by 1 errors
+ int32_t cltt = static_cast<int32_t>(l->cltt_);
+ int32_t expected = static_cast<int32_t>(time(NULL));
+ // Equality or difference by 1 between cltt and expected is ok.
+ EXPECT_GE(1, abs(cltt - expected));
+
+ Lease6Ptr deleted_lease =
+ LeaseMgrFactory::instance().getLease6(Lease::TYPE_NA,
+ addr_opt->getAddress());
+ EXPECT_TRUE(LeaseMgrFactory::instance().deleteLease(deleted_lease));
+
+ // Check if the callout handle state was reset after the callout.
+ checkCalloutHandleReset(req);
+}
+
+// This test verifies that incoming (positive) RENEW can be handled properly,
+// and the lease6_renew callouts are able to set the skip flag that will
+// reject the renewal
+TEST_F(HooksDhcpv6SrvTest, lease6RenewSkip) {
+ NakedDhcpv6Srv srv(0);
+
+ // Install lease6_renew_skip_callout
+ EXPECT_NO_THROW(HooksManager::preCalloutsLibraryHandle().registerCallout(
+ "lease6_renew", lease6_renew_skip_callout));
+
+ const IOAddress addr("2001:db8:1:1::cafe:babe");
+ const uint32_t iaid = 234;
+
+ // Generate client-id also duid_
+ OptionPtr clientid = generateClientId();
+
+ // Check that the address we are about to use is indeed in pool
+ ASSERT_TRUE(subnet_->inPool(Lease::TYPE_NA, addr));
+
+ // Note that preferred, valid, T1 and T2 timers and CLTT are set to invalid
+ // value on purpose. They should be updated during RENEW.
+ Lease6Ptr lease(new Lease6(Lease::TYPE_NA, addr, duid_, iaid,
+ 501, 502, subnet_->getID(),
+ HWAddrPtr(), 0));
+ lease->cltt_ = 1234;
+ ASSERT_TRUE(LeaseMgrFactory::instance().addLease(lease));
+
+ // Check that the lease is really in the database
+ Lease6Ptr l = LeaseMgrFactory::instance().getLease6(Lease::TYPE_NA,
+ addr);
+ ASSERT_TRUE(l);
+
+ // Check that preferred, valid and cltt are really set and not using
+ // previous (500, 501, etc.) values
+ EXPECT_NE(l->preferred_lft_, subnet_->getPreferred());
+ EXPECT_NE(l->valid_lft_, subnet_->getValid());
+ EXPECT_NE(l->cltt_, time(NULL));
+
+ // Let's create a RENEW
+ Pkt6Ptr req = Pkt6Ptr(new Pkt6(DHCPV6_RENEW, 1234));
+ req->setRemoteAddr(IOAddress("fe80::abcd"));
+ req->setIface("eth0");
+ req->setIndex(ETH0_INDEX);
+ boost::shared_ptr<Option6IA> ia = generateIA(D6O_IA_NA, iaid, 1500, 3000);
+
+ OptionPtr renewed_addr_opt(new Option6IAAddr(D6O_IAADDR, addr, 300, 500));
+ ia->addOption(renewed_addr_opt);
+ req->addOption(ia);
+ req->addOption(clientid);
+
+ // Server-id is mandatory in RENEW
+ req->addOption(srv.getServerID());
+
+ // Pass it to the server and hope for a REPLY
+ Pkt6Ptr reply = srv.processRenew(req);
+ ASSERT_TRUE(reply);
+
+ // Check that our callback was called
+ EXPECT_EQ("lease6_renew", callback_name_);
+
+ l = LeaseMgrFactory::instance().getLease6(Lease::TYPE_NA, addr);
+
+ // Check that the old values are still there and they were not
+ // updated by the renewal
+ EXPECT_NE(l->preferred_lft_, subnet_->getPreferred());
+ EXPECT_NE(l->valid_lft_, subnet_->getValid());
+ EXPECT_NE(l->cltt_, time(NULL));
+
+ // Check if the callout handle state was reset after the callout.
+ checkCalloutHandleReset(req);
+}
+
// This test verifies that incoming (positive) REBIND can be handled properly,
// and the lease6_rebind callouts are triggered.
-TEST_F(HooksDhcpv6SrvTest, basicLease6Rebind) {
+TEST_F(HooksDhcpv6SrvTest, lease6RebindSimple) {
NakedDhcpv6Srv srv(0);
// Install lease6_rebind_callout
@@ -4127,7 +4317,7 @@ TEST_F(HooksDhcpv6SrvTest, basicLease6Rebind) {
// This test verifies that incoming (positive) REBIND can be handled properly,
// and the lease6_rebind callouts are able to change the lease being updated.
-TEST_F(HooksDhcpv6SrvTest, leaseUpdateLease6Rebind) {
+TEST_F(HooksDhcpv6SrvTest, lease6RebindLeaseUpdate) {
NakedDhcpv6Srv srv(0);
// Install lease6_rebind_update
@@ -4229,7 +4419,7 @@ TEST_F(HooksDhcpv6SrvTest, leaseUpdateLease6Rebind) {
// This test verifies that incoming (positive) REBIND can be handled properly,
// and the lease6_rebind callouts are able to set the skip flag that will
// reject the rebinding
-TEST_F(HooksDhcpv6SrvTest, skipLease6Rebind) {
+TEST_F(HooksDhcpv6SrvTest, lease6RebindSkip) {
NakedDhcpv6Srv srv(0);
// Install lease6_rebind_skip
@@ -4295,364 +4485,495 @@ TEST_F(HooksDhcpv6SrvTest, skipLease6Rebind) {
checkCalloutHandleReset(req);
}
-// This test verifies that the callout installed on the leases6_committed hook
-// point is executed as a result of REBIND message sent to allocate new
-// lease or renew an existing lease.
-TEST_F(HooksDhcpv6SrvTest, leases6CommittedRebind) {
- IfaceMgrTestConfig test_config(true);
+// This test verifies that incoming (positive) RELEASE can be handled properly,
+// that a REPLY is generated, that the response has status code and that the
+// lease is indeed removed from the database.
+//
+// expected:
+// - returned REPLY message has copy of client-id
+// - returned REPLY message has server-id
+// - returned REPLY message has IA that does not include an IAADDR
+// - lease is actually removed from LeaseMgr
+TEST_F(HooksDhcpv6SrvTest, lease6ReleaseSimple) {
+ NakedDhcpv6Srv srv(0);
+ CfgMgr::instance().getCurrentCfg()->getCfgExpiration()->setFlushReclaimedTimerWaitTime(0);
+ CfgMgr::instance().getCurrentCfg()->getCfgExpiration()->setHoldReclaimedTime(0);
- string config = "{ \"interfaces-config\": {"
- " \"interfaces\": [ \"*\" ]"
- "},"
- "\"preferred-lifetime\": 3000,"
- "\"rebind-timer\": 2000, "
- "\"renew-timer\": 1000, "
- "\"subnet6\": [ { "
- " \"pools\": [ { \"pool\": \"2001:db8:1::/64\" } ],"
- " \"subnet\": \"2001:db8:1::/48\", "
- " \"interface\": \"eth1\" "
- " } ],"
- "\"valid-lifetime\": 4000 }";
+ // Install lease6_release_callout
+ EXPECT_NO_THROW(HooksManager::preCalloutsLibraryHandle().registerCallout(
+ "lease6_release", lease6_release_callout));
- Dhcp6Client client;
- client.setInterface("eth1");
- client.requestAddress(0xabca, IOAddress("2001:db8:1::28"));
+ const IOAddress addr("2001:db8:1:1::cafe:babe");
+ const uint32_t iaid = 234;
- ASSERT_NO_THROW(configure(config, *client.getServer()));
+ // Generate client-id also duid_
+ OptionPtr clientid = generateClientId();
- ASSERT_NO_THROW(HooksManager::preCalloutsLibraryHandle().registerCallout(
- "leases6_committed", leases6_committed_callout));
+ // Check that the address we are about to use is indeed in pool
+ ASSERT_TRUE(subnet_->inPool(Lease::TYPE_NA, addr));
- ASSERT_NO_THROW(client.doSARR());
+ // Note that preferred, valid, T1 and T2 timers and CLTT are set to invalid
+ // value on purpose. They should be updated during RENEW.
+ Lease6Ptr lease(new Lease6(Lease::TYPE_NA, addr, duid_, iaid,
+ 501, 502, subnet_->getID(),
+ HWAddrPtr(), 0));
+ lease->cltt_ = 1234;
+ ASSERT_TRUE(LeaseMgrFactory::instance().addLease(lease));
- // Make sure that we received a response
- ASSERT_TRUE(client.getContext().response_);
+ // Check that the lease is really in the database
+ Lease6Ptr l = LeaseMgrFactory::instance().getLease6(Lease::TYPE_NA,
+ addr);
+ ASSERT_TRUE(l);
+
+ // Let's create a RELEASE
+ Pkt6Ptr rel = Pkt6Ptr(new Pkt6(DHCPV6_RELEASE, 1234));
+ rel->setRemoteAddr(IOAddress("fe80::abcd"));
+ boost::shared_ptr<Option6IA> ia = generateIA(D6O_IA_NA, iaid, 1500, 3000);
+
+ OptionPtr released_addr_opt(new Option6IAAddr(D6O_IAADDR, addr, 300, 500));
+ ia->addOption(released_addr_opt);
+ rel->addOption(ia);
+ rel->addOption(clientid);
+
+ // Server-id is mandatory in RELEASE
+ rel->addOption(srv.getServerID());
+
+ // Pass it to the server and hope for a REPLY
+ Pkt6Ptr reply = srv.processRelease(rel);
+
+ ASSERT_TRUE(reply);
// Check that the callback called is indeed the one we installed
- EXPECT_EQ("leases6_committed", callback_name_);
+ EXPECT_EQ("lease6_release", callback_name_);
+
+ // Check that appropriate parameters are passed to the callouts
+ EXPECT_TRUE(callback_qry_pkt6_);
+ EXPECT_TRUE(callback_lease6_);
// Check if all expected parameters were really received
vector<string> expected_argument_names;
expected_argument_names.push_back("query6");
- expected_argument_names.push_back("deleted_leases6");
- expected_argument_names.push_back("leases6");
-
+ expected_argument_names.push_back("lease6");
+ sort(callback_argument_names_.begin(), callback_argument_names_.end());
sort(expected_argument_names.begin(), expected_argument_names.end());
EXPECT_TRUE(callback_argument_names_ == expected_argument_names);
- // Newly allocated lease should be returned.
- ASSERT_TRUE(callback_new_leases6_);
- ASSERT_EQ(1, callback_new_leases6_->size());
- Lease6Ptr lease = callback_new_leases6_->at(0);
- ASSERT_TRUE(lease);
- EXPECT_EQ("2001:db8:1::28", lease->addr_.toText());
+ // Check that the lease is really gone in the database
+ // get lease by address
+ l = LeaseMgrFactory::instance().getLease6(Lease::TYPE_NA, addr);
+ ASSERT_FALSE(l);
- // Deleted lease must not be present, because it is a new allocation.
- ASSERT_TRUE(callback_deleted_leases6_);
- EXPECT_TRUE(callback_deleted_leases6_->empty());
+ // Get lease by subnetid/duid/iaid combination
+ l = LeaseMgrFactory::instance().getLease6(Lease::TYPE_NA, *duid_, iaid,
+ subnet_->getID());
+ ASSERT_FALSE(l);
// Pkt passed to a callout must be configured to copy retrieved options.
EXPECT_TRUE(callback_qry_options_copy_);
// Check if the callout handle state was reset after the callout.
- checkCalloutHandleReset(client.getContext().query_);
+ checkCalloutHandleReset(rel);
+}
- resetCalloutBuffers();
+// This test verifies that incoming (positive) RELEASE can be handled properly,
+// that a REPLY is generated, that the response has status code and that the
+// lease is indeed removed from the database.
+//
+// expected:
+// - returned REPLY message has copy of client-id
+// - returned REPLY message has server-id
+// - returned REPLY message has IA that does not include an IAADDR
+// - lease is actually removed from LeaseMgr
+TEST_F(HooksDhcpv6SrvTest, lease6ReleaseSimpleNoDelete) {
+ NakedDhcpv6Srv srv(0);
- // Rebind the lease and make sure that the callout has been executed.
- ASSERT_NO_THROW(client.doRebind());
+ // Install lease6_release_callout
+ EXPECT_NO_THROW(HooksManager::preCalloutsLibraryHandle().registerCallout(
+ "lease6_release", lease6_release_callout));
- // Make sure that we received a response
- ASSERT_TRUE(client.getContext().response_);
+ const IOAddress addr("2001:db8:1:1::cafe:babe");
+ const uint32_t iaid = 234;
- // Check that the callback called is indeed the one we installed
- EXPECT_EQ("leases6_committed", callback_name_);
+ // Generate client-id also duid_
+ OptionPtr clientid = generateClientId();
- // Rebound lease should be returned.
- ASSERT_TRUE(callback_new_leases6_);
- ASSERT_EQ(1, callback_new_leases6_->size());
- lease = callback_new_leases6_->at(0);
- ASSERT_TRUE(lease);
- EXPECT_EQ("2001:db8:1::28", lease->addr_.toText());
+ // Check that the address we are about to use is indeed in pool
+ ASSERT_TRUE(subnet_->inPool(Lease::TYPE_NA, addr));
- // Deleted lease must not be present, because it is a new allocation.
- ASSERT_TRUE(callback_deleted_leases6_);
- EXPECT_TRUE(callback_deleted_leases6_->empty());
+ // Note that preferred, valid, T1 and T2 timers and CLTT are set to invalid
+ // value on purpose. They should be updated during RENEW.
+ Lease6Ptr lease(new Lease6(Lease::TYPE_NA, addr, duid_, iaid,
+ 501, 502, subnet_->getID(),
+ HWAddrPtr(), 0));
+ lease->cltt_ = 1234;
+ ASSERT_TRUE(LeaseMgrFactory::instance().addLease(lease));
- // Pkt passed to a callout must be configured to copy retrieved options.
- EXPECT_TRUE(callback_qry_options_copy_);
+ // Check that the lease is really in the database
+ Lease6Ptr l = LeaseMgrFactory::instance().getLease6(Lease::TYPE_NA,
+ addr);
+ ASSERT_TRUE(l);
- // Check if the callout handle state was reset after the callout.
- checkCalloutHandleReset(client.getContext().query_);
+ // Let's create a RELEASE
+ Pkt6Ptr req = Pkt6Ptr(new Pkt6(DHCPV6_RELEASE, 1234));
+ req->setRemoteAddr(IOAddress("fe80::abcd"));
+ boost::shared_ptr<Option6IA> ia = generateIA(D6O_IA_NA, iaid, 1500, 3000);
- resetCalloutBuffers();
+ OptionPtr released_addr_opt(new Option6IAAddr(D6O_IAADDR, addr, 300, 500));
+ ia->addOption(released_addr_opt);
+ req->addOption(ia);
+ req->addOption(clientid);
- // Let's try to rebind again but force the client to rebind a different
- // address with a different IAID.
- client.requestAddress(0x2233, IOAddress("2001:db8:1::29"));
+ // Server-id is mandatory in RELEASE
+ req->addOption(srv.getServerID());
- ASSERT_NO_THROW(client.doRebind());
+ // Pass it to the server and hope for a REPLY
+ Pkt6Ptr reply = srv.processRelease(req);
- // Make sure that we received a response
- ASSERT_TRUE(client.getContext().response_);
+ ASSERT_TRUE(reply);
// Check that the callback called is indeed the one we installed
- EXPECT_EQ("leases6_committed", callback_name_);
+ EXPECT_EQ("lease6_release", callback_name_);
- // New lease should be returned.
- ASSERT_TRUE(callback_new_leases6_);
- ASSERT_EQ(2, callback_new_leases6_->size());
- lease = callback_new_leases6_->at(1);
- ASSERT_TRUE(lease);
- EXPECT_EQ("2001:db8:1::29", lease->addr_.toText());
+ // Check that appropriate parameters are passed to the callouts
+ EXPECT_TRUE(callback_qry_pkt6_);
+ EXPECT_TRUE(callback_lease6_);
- // The old lease is kept.
- ASSERT_TRUE(callback_deleted_leases6_);
- ASSERT_TRUE(callback_deleted_leases6_->empty());
+ // Check if all expected parameters were really received
+ vector<string> expected_argument_names;
+ expected_argument_names.push_back("query6");
+ expected_argument_names.push_back("lease6");
+ sort(callback_argument_names_.begin(), callback_argument_names_.end());
+ sort(expected_argument_names.begin(), expected_argument_names.end());
+ EXPECT_TRUE(callback_argument_names_ == expected_argument_names);
+
+ // Check that the lease is not gone in the database
+ // get lease by address
+ l = LeaseMgrFactory::instance().getLease6(Lease::TYPE_NA, addr);
+ ASSERT_TRUE(l);
+
+ EXPECT_TRUE(l->expired());
+
+ // Get lease by subnetid/duid/iaid combination
+ l = LeaseMgrFactory::instance().getLease6(Lease::TYPE_NA, *duid_, iaid,
+ subnet_->getID());
+ ASSERT_TRUE(l);
+
+ EXPECT_TRUE(l->expired());
// Pkt passed to a callout must be configured to copy retrieved options.
EXPECT_TRUE(callback_qry_options_copy_);
// Check if the callout handle state was reset after the callout.
- checkCalloutHandleReset(client.getContext().query_);
-
- resetCalloutBuffers();
+ checkCalloutHandleReset(req);
+}
- // The rebound address is just a hint.
- client.requestAddress(0x5577, IOAddress("4000::2"));
+// This is a variant of the previous test that tests that callouts are
+// properly invoked for the prefix release case.
+TEST_F(HooksDhcpv6SrvTest, lease6ReleasePrefixSimple) {
+ NakedDhcpv6Srv srv(0);
+ CfgMgr::instance().getCurrentCfg()->getCfgExpiration()->setFlushReclaimedTimerWaitTime(0);
+ CfgMgr::instance().getCurrentCfg()->getCfgExpiration()->setHoldReclaimedTime(0);
- ASSERT_NO_THROW(client.doRebind());
+ // Install lease6_release_callout
+ EXPECT_NO_THROW(HooksManager::preCalloutsLibraryHandle().registerCallout(
+ "lease6_release", lease6_release_callout));
- // Make sure that we received a response
- ASSERT_TRUE(client.getContext().response_);
+ const IOAddress prefix("2001:db8:1:2:1::");
+ const uint32_t iaid = 234;
- // Check that the callback called is indeed the one we installed
- EXPECT_EQ("leases6_committed", callback_name_);
+ // Generate client-id also duid_
+ OptionPtr clientid = generateClientId();
- ASSERT_TRUE(callback_new_leases6_);
- EXPECT_EQ(3, callback_new_leases6_->size());
- lease = callback_new_leases6_->at(2);
- ASSERT_TRUE(lease);
- EXPECT_EQ("2001:db8:1::", lease->addr_.toText());
- ASSERT_TRUE(callback_deleted_leases6_);
- EXPECT_TRUE(callback_deleted_leases6_->empty());
+ // Check that the prefix we are about to use is indeed in pool
+ ASSERT_TRUE(subnet_->inPool(Lease::TYPE_PD, prefix));
- // Pkt passed to a callout must be configured to copy retrieved options.
- EXPECT_TRUE(callback_qry_options_copy_);
+ // Note that preferred, valid, T1 and T2 timers and CLTT are set to invalid
+ // value on purpose. They should be updated during RENEW.
+ Lease6Ptr lease(new Lease6(Lease::TYPE_PD, prefix, duid_, iaid,
+ 501, 502, subnet_->getID(),
+ HWAddrPtr(), 80));
+ lease->cltt_ = 1234;
+ ASSERT_TRUE(LeaseMgrFactory::instance().addLease(lease));
- // Check if the callout handle state was reset after the callout.
- checkCalloutHandleReset(client.getContext().query_);
+ // Check that the lease is really in the database
+ Lease6Ptr l = LeaseMgrFactory::instance().getLease6(Lease::TYPE_PD,
+ prefix);
+ ASSERT_TRUE(l);
- resetCalloutBuffers();
+ // Let's create a RELEASE
+ Pkt6Ptr req = Pkt6Ptr(new Pkt6(DHCPV6_RELEASE, 1234));
+ req->setRemoteAddr(IOAddress("fe80::abcd"));
+ boost::shared_ptr<Option6IA> ia = generateIA(D6O_IA_PD, iaid, 1500, 3000);
- // Rebind a prefix: this should lead to an error as no prefix pool
- // is configured.
- client.requestPrefix(0x1122, 64, IOAddress("2001:db8:1000::"));
+ OptionPtr released_addr_opt(new Option6IAPrefix(D6O_IAPREFIX, prefix, 80,
+ 300, 500));
+ ia->addOption(released_addr_opt);
+ req->addOption(ia);
+ req->addOption(clientid);
- ASSERT_NO_THROW(client.doRebind());
+ // Server-id is mandatory in RELEASE
+ req->addOption(srv.getServerID());
- // Make sure that we received a response
- ASSERT_TRUE(client.getContext().response_);
+ // Pass it to the server and hope for a REPLY
+ Pkt6Ptr reply = srv.processRelease(req);
- // Check the error.
- EXPECT_EQ(STATUS_NoPrefixAvail, client.getStatusCode(0x1122));
+ ASSERT_TRUE(reply);
// Check that the callback called is indeed the one we installed
- EXPECT_EQ("leases6_committed", callback_name_);
+ EXPECT_EQ("lease6_release", callback_name_);
- ASSERT_TRUE(callback_new_leases6_);
- EXPECT_EQ(3, callback_new_leases6_->size());
- ASSERT_TRUE(callback_deleted_leases6_);
- EXPECT_TRUE(callback_deleted_leases6_->empty());
+ // Check that appropriate parameters are passed to the callouts
+ EXPECT_TRUE(callback_qry_pkt6_);
+ EXPECT_TRUE(callback_lease6_);
+
+ // Check if all expected parameters were really received
+ vector<string> expected_argument_names;
+ expected_argument_names.push_back("query6");
+ expected_argument_names.push_back("lease6");
+ sort(callback_argument_names_.begin(), callback_argument_names_.end());
+ sort(expected_argument_names.begin(), expected_argument_names.end());
+ EXPECT_TRUE(callback_argument_names_ == expected_argument_names);
+
+ // Check that the lease is really gone in the database
+ // get lease by address
+ l = LeaseMgrFactory::instance().getLease6(Lease::TYPE_PD, prefix);
+ ASSERT_FALSE(l);
+
+ // Get lease by subnetid/duid/iaid combination
+ l = LeaseMgrFactory::instance().getLease6(Lease::TYPE_PD, *duid_, iaid,
+ subnet_->getID());
+ ASSERT_FALSE(l);
+
+ // Pkt passed to a callout must be configured to copy retrieved options.
+ EXPECT_TRUE(callback_qry_options_copy_);
// Check if the callout handle state was reset after the callout.
- checkCalloutHandleReset(client.getContext().query_);
+ checkCalloutHandleReset(req);
}
-// This test verifies that the callout installed on the leases6_committed hook
-// point is executed as a result of REBIND message sent to allocate new
-// lease or renew an existing lease. Prefix variant.
-TEST_F(HooksDhcpv6SrvTest, leases6CommittedRebindPrefix) {
- IfaceMgrTestConfig test_config(true);
+// This is a variant of the previous test that tests that callouts are
+// properly invoked for the prefix release case.
+TEST_F(HooksDhcpv6SrvTest, lease6ReleasePrefixSimpleNoDelete) {
+ NakedDhcpv6Srv srv(0);
- string config = "{ \"interfaces-config\": {"
- " \"interfaces\": [ \"*\" ]"
- "},"
- "\"preferred-lifetime\": 3000,"
- "\"rebind-timer\": 2000, "
- "\"renew-timer\": 1000, "
- "\"subnet6\": [ { "
- " \"pd-pools\": [ {"
- " \"prefix\": \"2001:db8:1::\", "
- " \"prefix-len\": 56, "
- " \"delegated-len\": 64 } ], "
- " \"subnet\": \"2001:db8:1::/48\", "
- " \"interface\": \"eth1\" "
- " } ],"
- "\"valid-lifetime\": 4000 }";
+ // Install lease6_release_callout
+ EXPECT_NO_THROW(HooksManager::preCalloutsLibraryHandle().registerCallout(
+ "lease6_release", lease6_release_callout));
- Dhcp6Client client;
- client.setInterface("eth1");
- client.requestPrefix(0xabca, 64, IOAddress("2001:db8:1:28::"));
+ const IOAddress prefix("2001:db8:1:2:1::");
+ const uint32_t iaid = 234;
- ASSERT_NO_THROW(configure(config, *client.getServer()));
+ // Generate client-id also duid_
+ OptionPtr clientid = generateClientId();
- ASSERT_NO_THROW(HooksManager::preCalloutsLibraryHandle().registerCallout(
- "leases6_committed", leases6_committed_callout));
+ // Check that the prefix we are about to use is indeed in pool
+ ASSERT_TRUE(subnet_->inPool(Lease::TYPE_PD, prefix));
- ASSERT_NO_THROW(client.doSARR());
+ // Note that preferred, valid, T1 and T2 timers and CLTT are set to invalid
+ // value on purpose. They should be updated during RENEW.
+ Lease6Ptr lease(new Lease6(Lease::TYPE_PD, prefix, duid_, iaid,
+ 501, 502, subnet_->getID(),
+ HWAddrPtr(), 80));
+ lease->cltt_ = 1234;
+ ASSERT_TRUE(LeaseMgrFactory::instance().addLease(lease));
- // Make sure that we received a response
- ASSERT_TRUE(client.getContext().response_);
+ // Check that the lease is really in the database
+ Lease6Ptr l = LeaseMgrFactory::instance().getLease6(Lease::TYPE_PD,
+ prefix);
+ ASSERT_TRUE(l);
+
+ // Let's create a RELEASE
+ Pkt6Ptr req = Pkt6Ptr(new Pkt6(DHCPV6_RELEASE, 1234));
+ req->setRemoteAddr(IOAddress("fe80::abcd"));
+ boost::shared_ptr<Option6IA> ia = generateIA(D6O_IA_PD, iaid, 1500, 3000);
+
+ OptionPtr released_addr_opt(new Option6IAPrefix(D6O_IAPREFIX, prefix, 80,
+ 300, 500));
+ ia->addOption(released_addr_opt);
+ req->addOption(ia);
+ req->addOption(clientid);
+
+ // Server-id is mandatory in RELEASE
+ req->addOption(srv.getServerID());
+
+ // Pass it to the server and hope for a REPLY
+ Pkt6Ptr reply = srv.processRelease(req);
+
+ ASSERT_TRUE(reply);
// Check that the callback called is indeed the one we installed
- EXPECT_EQ("leases6_committed", callback_name_);
+ EXPECT_EQ("lease6_release", callback_name_);
+
+ // Check that appropriate parameters are passed to the callouts
+ EXPECT_TRUE(callback_qry_pkt6_);
+ EXPECT_TRUE(callback_lease6_);
// Check if all expected parameters were really received
vector<string> expected_argument_names;
expected_argument_names.push_back("query6");
- expected_argument_names.push_back("deleted_leases6");
- expected_argument_names.push_back("leases6");
-
+ expected_argument_names.push_back("lease6");
+ sort(callback_argument_names_.begin(), callback_argument_names_.end());
sort(expected_argument_names.begin(), expected_argument_names.end());
EXPECT_TRUE(callback_argument_names_ == expected_argument_names);
- // Newly allocated lease should be returned.
- ASSERT_TRUE(callback_new_leases6_);
- ASSERT_EQ(1, callback_new_leases6_->size());
- Lease6Ptr lease = callback_new_leases6_->at(0);
- ASSERT_TRUE(lease);
- EXPECT_EQ("2001:db8:1:28::", lease->addr_.toText());
- EXPECT_EQ(64, lease->prefixlen_);
+ // Check that the lease is not gone in the database
+ // get lease by address
+ l = LeaseMgrFactory::instance().getLease6(Lease::TYPE_PD, prefix);
+ ASSERT_TRUE(l);
- // Deleted lease must not be present, because it is a new allocation.
- ASSERT_TRUE(callback_deleted_leases6_);
- EXPECT_TRUE(callback_deleted_leases6_->empty());
+ EXPECT_TRUE(l->expired());
+
+ // Get lease by subnetid/duid/iaid combination
+ l = LeaseMgrFactory::instance().getLease6(Lease::TYPE_PD, *duid_, iaid,
+ subnet_->getID());
+ ASSERT_TRUE(l);
+
+ EXPECT_TRUE(l->expired());
// Pkt passed to a callout must be configured to copy retrieved options.
EXPECT_TRUE(callback_qry_options_copy_);
// Check if the callout handle state was reset after the callout.
- checkCalloutHandleReset(client.getContext().query_);
+ checkCalloutHandleReset(req);
+}
- resetCalloutBuffers();
+// This test verifies that skip flag returned by a callout installed on the
+// lease6_release hook point will keep the lease.
+TEST_F(HooksDhcpv6SrvTest, lease6ReleaseSkip) {
+ NakedDhcpv6Srv srv(0);
- // Rebind the lease and make sure that the callout has been executed.
- ASSERT_NO_THROW(client.doRebind());
+ // Install lease6_release_skip
+ EXPECT_NO_THROW(HooksManager::preCalloutsLibraryHandle().registerCallout(
+ "lease6_release", lease6_release_skip));
- // Make sure that we received a response
- ASSERT_TRUE(client.getContext().response_);
+ const IOAddress addr("2001:db8:1:1::cafe:babe");
+ const uint32_t iaid = 234;
- // Check that the callback called is indeed the one we installed
- EXPECT_EQ("leases6_committed", callback_name_);
+ // Generate client-id also duid_
+ OptionPtr clientid = generateClientId();
- // Rebound lease should be returned.
- ASSERT_TRUE(callback_new_leases6_);
- ASSERT_EQ(1, callback_new_leases6_->size());
- lease = callback_new_leases6_->at(0);
- ASSERT_TRUE(lease);
- EXPECT_EQ("2001:db8:1:28::", lease->addr_.toText());
- EXPECT_EQ(64, lease->prefixlen_);
+ // Check that the address we are about to use is indeed in pool
+ ASSERT_TRUE(subnet_->inPool(Lease::TYPE_NA, addr));
- // Deleted lease must not be present, because it is a new allocation.
- ASSERT_TRUE(callback_deleted_leases6_);
- EXPECT_TRUE(callback_deleted_leases6_->empty());
+ // Note that preferred, valid, T1 and T2 timers and CLTT are set to invalid
+ // value on purpose. They should be updated during RENEW.
+ Lease6Ptr lease(new Lease6(Lease::TYPE_NA, addr, duid_, iaid,
+ 501, 502, subnet_->getID(),
+ HWAddrPtr(), 0));
+ lease->cltt_ = 1234;
+ ASSERT_TRUE(LeaseMgrFactory::instance().addLease(lease));
- // Pkt passed to a callout must be configured to copy retrieved options.
- EXPECT_TRUE(callback_qry_options_copy_);
+ // Check that the lease is really in the database
+ Lease6Ptr l = LeaseMgrFactory::instance().getLease6(Lease::TYPE_NA,
+ addr);
+ ASSERT_TRUE(l);
- // Check if the callout handle state was reset after the callout.
- checkCalloutHandleReset(client.getContext().query_);
+ // Let's create a RELEASE
+ Pkt6Ptr rel = Pkt6Ptr(new Pkt6(DHCPV6_RELEASE, 1234));
+ rel->setRemoteAddr(IOAddress("fe80::abcd"));
+ boost::shared_ptr<Option6IA> ia = generateIA(D6O_IA_NA, iaid, 1500, 3000);
- resetCalloutBuffers();
+ OptionPtr released_addr_opt(new Option6IAAddr(D6O_IAADDR, addr, 300, 500));
+ ia->addOption(released_addr_opt);
+ rel->addOption(ia);
+ rel->addOption(clientid);
- // Let's try to rebind again but force the client to rebind a different
- // prefix with a different IAID.
- client.requestPrefix(0x2233, 64, IOAddress("2001:db8:1:29::"));
+ // Server-id is mandatory in RELEASE
+ rel->addOption(srv.getServerID());
- ASSERT_NO_THROW(client.doRebind());
+ // Pass it to the server and hope for a REPLY
+ Pkt6Ptr reply = srv.processRelease(rel);
- // Make sure that we received a response
- ASSERT_TRUE(client.getContext().response_);
+ ASSERT_TRUE(reply);
// Check that the callback called is indeed the one we installed
- EXPECT_EQ("leases6_committed", callback_name_);
-
- // New lease should be returned.
- ASSERT_TRUE(callback_new_leases6_);
- ASSERT_EQ(2, callback_new_leases6_->size());
- lease = callback_new_leases6_->at(1);
- ASSERT_TRUE(lease);
- EXPECT_EQ("2001:db8:1:29::", lease->addr_.toText());
- EXPECT_EQ(64, lease->prefixlen_);
+ EXPECT_EQ("lease6_release", callback_name_);
- // The old lease is kept.
- ASSERT_TRUE(callback_deleted_leases6_);
- ASSERT_TRUE(callback_deleted_leases6_->empty());
+ // Check that the lease is still there
+ // get lease by address
+ l = LeaseMgrFactory::instance().getLease6(Lease::TYPE_NA,
+ addr);
+ ASSERT_TRUE(l);
- // Pkt passed to a callout must be configured to copy retrieved options.
- EXPECT_TRUE(callback_qry_options_copy_);
+ // Get lease by subnetid/duid/iaid combination
+ l = LeaseMgrFactory::instance().getLease6(Lease::TYPE_NA, *duid_, iaid,
+ subnet_->getID());
+ ASSERT_TRUE(l);
// Check if the callout handle state was reset after the callout.
- checkCalloutHandleReset(client.getContext().query_);
-
- resetCalloutBuffers();
+ checkCalloutHandleReset(rel);
+}
- // The rebound prefix is just a hint.
- client.requestPrefix(0x5577, 64, IOAddress("4000::1"));
+// This test verifies that drop flag returned by a callout installed on the
+// lease6_release hook point will keep the lease.
+TEST_F(HooksDhcpv6SrvTest, lease6ReleaseDrop) {
+ NakedDhcpv6Srv srv(0);
- ASSERT_NO_THROW(client.doRebind());
+ // Install lease6_release_drop
+ EXPECT_NO_THROW(HooksManager::preCalloutsLibraryHandle().registerCallout(
+ "lease6_release", lease6_release_drop));
- // Make sure that we received a response
- ASSERT_TRUE(client.getContext().response_);
+ const IOAddress addr("2001:db8:1:1::cafe:babe");
+ const uint32_t iaid = 234;
- // Check that the callback called is indeed the one we installed
- EXPECT_EQ("leases6_committed", callback_name_);
+ // Generate client-id also duid_
+ OptionPtr clientid = generateClientId();
- ASSERT_TRUE(callback_new_leases6_);
- EXPECT_EQ(3, callback_new_leases6_->size());
- lease = callback_new_leases6_->at(2);
- ASSERT_TRUE(lease);
- EXPECT_EQ("2001:db8:1::", lease->addr_.toText());
- EXPECT_EQ(64, lease->prefixlen_);
- ASSERT_TRUE(callback_deleted_leases6_);
- EXPECT_TRUE(callback_deleted_leases6_->empty());
+ // Check that the address we are about to use is indeed in pool
+ ASSERT_TRUE(subnet_->inPool(Lease::TYPE_NA, addr));
- // Pkt passed to a callout must be configured to copy retrieved options.
- EXPECT_TRUE(callback_qry_options_copy_);
+ // Note that preferred, valid, T1 and T2 timers and CLTT are set to invalid
+ // value on purpose. They should be updated during RENEW.
+ Lease6Ptr lease(new Lease6(Lease::TYPE_NA, addr, duid_, iaid,
+ 501, 502, subnet_->getID(),
+ HWAddrPtr(), 0));
+ lease->cltt_ = 1234;
+ ASSERT_TRUE(LeaseMgrFactory::instance().addLease(lease));
- // Check if the callout handle state was reset after the callout.
- checkCalloutHandleReset(client.getContext().query_);
+ // Check that the lease is really in the database
+ Lease6Ptr l = LeaseMgrFactory::instance().getLease6(Lease::TYPE_NA,
+ addr);
+ ASSERT_TRUE(l);
- resetCalloutBuffers();
+ // Let's create a RELEASE
+ Pkt6Ptr rel = Pkt6Ptr(new Pkt6(DHCPV6_RELEASE, 1234));
+ rel->setRemoteAddr(IOAddress("fe80::abcd"));
+ boost::shared_ptr<Option6IA> ia = generateIA(D6O_IA_NA, iaid, 1500, 3000);
- // Rebind an address: this should lead to an error as no address pool
- // is configured.
- client.requestAddress(0x1122, IOAddress("2001:db8:1::28"));
+ OptionPtr released_addr_opt(new Option6IAAddr(D6O_IAADDR, addr, 300, 500));
+ ia->addOption(released_addr_opt);
+ rel->addOption(ia);
+ rel->addOption(clientid);
- ASSERT_NO_THROW(client.doRebind());
+ // Server-id is mandatory in RELEASE
+ rel->addOption(srv.getServerID());
- // Make sure that we received a response
- ASSERT_TRUE(client.getContext().response_);
+ // Pass it to the server and hope for a REPLY
+ Pkt6Ptr reply = srv.processRelease(rel);
- // Check the error.
- EXPECT_EQ(STATUS_NoAddrsAvail, client.getStatusCode(0x1122));
+ ASSERT_TRUE(reply);
// Check that the callback called is indeed the one we installed
- EXPECT_EQ("leases6_committed", callback_name_);
+ EXPECT_EQ("lease6_release", callback_name_);
- ASSERT_TRUE(callback_new_leases6_);
- EXPECT_EQ(3, callback_new_leases6_->size());
- ASSERT_TRUE(callback_deleted_leases6_);
- EXPECT_TRUE(callback_deleted_leases6_->empty());
+ // Check that the lease is still there
+ // get lease by address
+ l = LeaseMgrFactory::instance().getLease6(Lease::TYPE_NA,
+ addr);
+ ASSERT_TRUE(l);
+
+ // Get lease by subnetid/duid/iaid combination
+ l = LeaseMgrFactory::instance().getLease6(Lease::TYPE_NA, *duid_, iaid,
+ subnet_->getID());
+ ASSERT_TRUE(l);
// Check if the callout handle state was reset after the callout.
- checkCalloutHandleReset(client.getContext().query_);
+ checkCalloutHandleReset(rel);
}
// This test checks that the basic decline hook (lease6_decline) is
// triggered properly.
-TEST_F(HooksDhcpv6SrvTest, basicLease6Decline) {
+TEST_F(HooksDhcpv6SrvTest, lease6DeclineSimple) {
IfaceMgrTestConfig test_config(true);
// Install lease6_decline callout
@@ -4799,139 +5120,7 @@ TEST_F(HooksDhcpv6SrvTest, lease6DeclineDrop) {
checkCalloutHandleReset(client.getContext().query_);
}
-// This test verifies that the leases6_committed callout is executed
-// when DECLINE is processed. The declined lease is expected to be passed
-// in leases6 argument to the callout.
-TEST_F(HooksDhcpv6SrvTest, leases6CommittedDecline) {
- IfaceMgrTestConfig test_config(true);
-
- string config = "{ \"interfaces-config\": {"
- " \"interfaces\": [ \"*\" ]"
- "},"
- "\"preferred-lifetime\": 3000,"
- "\"rebind-timer\": 2000, "
- "\"renew-timer\": 1000, "
- "\"subnet6\": [ { "
- " \"pools\": [ { \"pool\": \"2001:db8:1::/64\" } ],"
- " \"subnet\": \"2001:db8:1::/48\", "
- " \"interface\": \"eth1\" "
- " } ],"
- "\"valid-lifetime\": 4000 }";
-
- Dhcp6Client client;
- client.setInterface("eth1");
- client.requestAddress(0xabca, IOAddress("2001:db8:1::28"));
-
- ASSERT_NO_THROW(configure(config, *client.getServer()));
-
- ASSERT_NO_THROW(client.doSARR());
- // Make sure that we received a response
- ASSERT_TRUE(client.getContext().response_);
-
- ASSERT_NO_THROW(HooksManager::preCalloutsLibraryHandle().registerCallout(
- "leases6_committed", leases6_committed_callout));
-
- ASSERT_NO_THROW(client.doDecline());
-
- // Check that the callback called is indeed the one we installed
- EXPECT_EQ("leases6_committed", callback_name_);
-
- // Check if all expected parameters were really received
- vector<string> expected_argument_names;
- expected_argument_names.push_back("query6");
- expected_argument_names.push_back("deleted_leases6");
- expected_argument_names.push_back("leases6");
-
- sort(expected_argument_names.begin(), expected_argument_names.end());
- EXPECT_TRUE(callback_argument_names_ == expected_argument_names);
-
- // No deleted leases.
- ASSERT_TRUE(callback_deleted_leases6_);
- ASSERT_TRUE(callback_deleted_leases6_->empty());
-
- // Declined lease should be returned.
- ASSERT_TRUE(callback_new_leases6_);
- ASSERT_EQ(1, callback_new_leases6_->size());
- Lease6Ptr lease = callback_new_leases6_->at(0);
- ASSERT_TRUE(lease);
- EXPECT_EQ("2001:db8:1::28", lease->addr_.toText());
-
- // Pkt passed to a callout must be configured to copy retrieved options.
- EXPECT_TRUE(callback_qry_options_copy_);
-
- // Check if the callout handle state was reset after the callout.
- checkCalloutHandleReset(client.getContext().query_);
-}
-
-// This test verifies that the leases6_committed callout is executed
-// when DECLINE is processed. Variant with 2 IA_NAs.
-TEST_F(HooksDhcpv6SrvTest, leases6CommittedDeclineTwoNAs) {
- IfaceMgrTestConfig test_config(true);
-
- string config = "{ \"interfaces-config\": {"
- " \"interfaces\": [ \"*\" ]"
- "},"
- "\"preferred-lifetime\": 3000,"
- "\"rebind-timer\": 2000, "
- "\"renew-timer\": 1000, "
- "\"subnet6\": [ { "
- " \"pools\": [ { \"pool\": \"2001:db8:1::/64\" } ],"
- " \"subnet\": \"2001:db8:1::/48\", "
- " \"interface\": \"eth1\" "
- " } ],"
- "\"valid-lifetime\": 4000 }";
-
- Dhcp6Client client;
- client.setInterface("eth1");
- client.requestAddress(0xabca, IOAddress("2001:db8:1::28"));
- client.requestAddress(0x2233, IOAddress("2001:db8:1::29"));
-
- ASSERT_NO_THROW(configure(config, *client.getServer()));
-
- ASSERT_NO_THROW(client.doSARR());
- // Make sure that we received a response
- ASSERT_TRUE(client.getContext().response_);
-
- ASSERT_NO_THROW(HooksManager::preCalloutsLibraryHandle().registerCallout(
- "leases6_committed", leases6_committed_callout));
-
- ASSERT_NO_THROW(client.doDecline());
-
- // Check that the callback called is indeed the one we installed
- EXPECT_EQ("leases6_committed", callback_name_);
-
- // Check if all expected parameters were really received
- vector<string> expected_argument_names;
- expected_argument_names.push_back("query6");
- expected_argument_names.push_back("deleted_leases6");
- expected_argument_names.push_back("leases6");
-
- sort(expected_argument_names.begin(), expected_argument_names.end());
- EXPECT_TRUE(callback_argument_names_ == expected_argument_names);
-
- // No deleted leases.
- ASSERT_TRUE(callback_deleted_leases6_);
- ASSERT_TRUE(callback_deleted_leases6_->empty());
-
- // Declined lease should be returned.
- ASSERT_TRUE(callback_new_leases6_);
- ASSERT_EQ(2, callback_new_leases6_->size());
- Lease6Ptr lease = callback_new_leases6_->at(0);
- ASSERT_TRUE(lease);
- EXPECT_EQ("2001:db8:1::28", lease->addr_.toText());
- lease = callback_new_leases6_->at(1);
- ASSERT_TRUE(lease);
- EXPECT_EQ("2001:db8:1::29", lease->addr_.toText());
-
- // Pkt passed to a callout must be configured to copy retrieved options.
- EXPECT_TRUE(callback_qry_options_copy_);
-
- // Check if the callout handle state was reset after the callout.
- checkCalloutHandleReset(client.getContext().query_);
-}
-
// Should test with one NA and two addresses but need an example first...
-
// Checks if callout installed on host6_identifier can generate an
// identifier and whether that identifier is actually used.
TEST_F(HooksDhcpv6SrvTest, host6Identifier) {
@@ -5015,9 +5204,9 @@ TEST_F(HooksDhcpv6SrvTest, host6Identifier) {
checkCalloutHandleReset(sol);
}
-// Checks if callout installed on host6_identifier can generate an identifier
+// Checks if callout installed on host6_identifier can generate an identifier of
// other type. This particular callout always returns hwaddr.
-TEST_F(HooksDhcpv6SrvTest, host6Identifier_hwaddr) {
+TEST_F(HooksDhcpv6SrvTest, host6IdentifierHWAddr) {
// Configure 2 subnets, both directly reachable over local interface
// (let's not complicate the matter with relays)
@@ -5053,7 +5242,7 @@ TEST_F(HooksDhcpv6SrvTest, host6Identifier_hwaddr) {
CfgMgr::instance().commit();
- // Install host6_identifier_foo_callout
+ // Install host6_identifier_hwaddr_callout
EXPECT_NO_THROW(HooksManager::preCalloutsLibraryHandle().registerCallout(
"host6_identifier", host6_identifier_hwaddr_callout));
@@ -5098,7 +5287,6 @@ TEST_F(HooksDhcpv6SrvTest, host6Identifier_hwaddr) {
checkCalloutHandleReset(sol);
}
-
// Verifies that libraries are unloaded by server destruction
// The callout libraries write their library index number to a marker
// file upon load and unload, making it simple to test whether or not
@@ -5270,7 +5458,7 @@ TEST_F(LoadUnloadDhcpv6SrvTest, Dhcpv6SrvConfigured) {
}
}
-// This test verifies that parked-packet-limit is enforced.
+// This test verifies that parked-packet-limit is properly enforced.
TEST_F(HooksDhcpv6SrvTest, leases6ParkedPacketLimit) {
IfaceMgrTestConfig test_config(true);
@@ -5400,5 +5588,4 @@ TEST_F(HooksDhcpv6SrvTest, leases6ParkedPacketLimit) {
EXPECT_EQ(1, getStatistic("pkt6-receive-drop"));
}
-
} // namespace