#include <config.h>
-#include <dhcp4/tests/dhcp4_test_utils.h>
-#include <dhcp4/ctrl_dhcp4_srv.h>
-#include <dhcp4/json_config_parser.h>
+#include <asiolink/io_address.h>
#include <asiolink/io_service.h>
#include <cc/command_interpreter.h>
#include <config/command_mgr.h>
-#include <hooks/server_hooks.h>
-#include <hooks/hooks_manager.h>
-#include <hooks/callout_manager.h>
-#include <dhcpsrv/cfgmgr.h>
#include <dhcp/tests/iface_mgr_test_config.h>
#include <dhcp/option.h>
-#include <asiolink/io_address.h>
+#include <dhcpsrv/cfgmgr.h>
+#include <dhcp4/ctrl_dhcp4_srv.h>
+#include <dhcp4/json_config_parser.h>
#include <dhcp4/tests/dhcp4_client.h>
+#include <dhcp4/tests/dhcp4_test_utils.h>
#include <dhcp4/tests/marker_file.h>
#include <dhcp4/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/multi_threading_mgr.h>
#include <vector>
-using namespace std;
+
using namespace isc::asiolink;
-using namespace isc::data;
-using namespace isc::hooks;
using namespace isc::config;
-using namespace isc::dhcp::test;
+using namespace isc::data;
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;
-// Checks if hooks are registered properly.
+// namespace has to be named, because friends are defined in Dhcpv6Srv class
+// Maybe it should be isc::test?
+namespace {
+
+// Checks if hooks are implemented properly.
TEST_F(Dhcpv4SrvTest, Hooks) {
NakedDhcpv4Srv srv(0);
// check if appropriate hooks are registered
- int hook_index_buffer4_receive = -1;
- int hook_index_pkt4_receive = -1;
- int hook_index_select_subnet = -1;
+ int hook_index_dhcp4_srv_configured = -1;
+ int hook_index_buffer4_receive = -1;
+ int hook_index_buffer4_send = -1;
+ int hook_index_lease4_renew = -1;
+ int hook_index_lease4_release = -1;
+ int hook_index_lease4_decline = -1;
+ int hook_index_pkt4_receive = -1;
+ int hook_index_pkt4_send = -1;
+ int hook_index_select_subnet = -1;
int hook_index_leases4_committed = -1;
- int hook_index_lease4_release = -1;
- int hook_index_pkt4_send = -1;
- int hook_index_buffer4_send = -1;
- int hook_index_host4_identifier = -1;
+ int hook_index_host4_identifier = -1;
// check if appropriate indexes are set
+ EXPECT_NO_THROW(hook_index_dhcp4_srv_configured = ServerHooks::getServerHooks()
+ .getIndex("dhcp4_srv_configured"));
EXPECT_NO_THROW(hook_index_buffer4_receive = ServerHooks::getServerHooks()
.getIndex("buffer4_receive"));
+ EXPECT_NO_THROW(hook_index_buffer4_send = ServerHooks::getServerHooks()
+ .getIndex("buffer4_send"));
+ EXPECT_NO_THROW(hook_index_lease4_renew = ServerHooks::getServerHooks()
+ .getIndex("lease4_renew"));
+ EXPECT_NO_THROW(hook_index_lease4_release = ServerHooks::getServerHooks()
+ .getIndex("lease4_release"));
+ EXPECT_NO_THROW(hook_index_lease4_decline = ServerHooks::getServerHooks()
+ .getIndex("lease4_decline"));
EXPECT_NO_THROW(hook_index_pkt4_receive = ServerHooks::getServerHooks()
.getIndex("pkt4_receive"));
+ EXPECT_NO_THROW(hook_index_pkt4_send = ServerHooks::getServerHooks()
+ .getIndex("pkt4_send"));
EXPECT_NO_THROW(hook_index_select_subnet = ServerHooks::getServerHooks()
.getIndex("subnet4_select"));
EXPECT_NO_THROW(hook_index_leases4_committed = ServerHooks::getServerHooks()
.getIndex("leases4_committed"));
- EXPECT_NO_THROW(hook_index_lease4_release = ServerHooks::getServerHooks()
- .getIndex("lease4_release"));
- EXPECT_NO_THROW(hook_index_pkt4_send = ServerHooks::getServerHooks()
- .getIndex("pkt4_send"));
- EXPECT_NO_THROW(hook_index_buffer4_send = ServerHooks::getServerHooks()
- .getIndex("buffer4_send"));
EXPECT_NO_THROW(hook_index_host4_identifier = ServerHooks::getServerHooks()
.getIndex("host4_identifier"));
+ EXPECT_TRUE(hook_index_dhcp4_srv_configured > 0);
EXPECT_TRUE(hook_index_buffer4_receive > 0);
+ EXPECT_TRUE(hook_index_buffer4_send > 0);
+ EXPECT_TRUE(hook_index_lease4_renew > 0);
+ EXPECT_TRUE(hook_index_lease4_release > 0);
+ EXPECT_TRUE(hook_index_lease4_decline > 0);
EXPECT_TRUE(hook_index_pkt4_receive > 0);
+ EXPECT_TRUE(hook_index_pkt4_send > 0);
EXPECT_TRUE(hook_index_select_subnet > 0);
EXPECT_TRUE(hook_index_leases4_committed > 0);
- EXPECT_TRUE(hook_index_lease4_release > 0);
- EXPECT_TRUE(hook_index_pkt4_send > 0);
- EXPECT_TRUE(hook_index_buffer4_send > 0);
EXPECT_TRUE(hook_index_host4_identifier > 0);
}
}
// Allocate new DHCPv4 Server
- srv_ = new NakedDhcpv4Srv(0);
+ srv_.reset(new NakedDhcpv4Srv(0));
- // clear static buffers
+ // Clear static buffers
resetCalloutBuffers();
io_service_ = boost::make_shared<IOService>();
+ // Reset the hook system in its original state
+ HooksManager::unloadLibraries();
+
// Clear statistics.
StatsMgr::instance().removeAll();
}
/// @brief destructor (deletes Dhcpv4Srv)
virtual ~HooksDhcpv4SrvTest() {
- // clear static buffers
+ // Clear static buffers
resetCalloutBuffers();
HooksManager::preCalloutsLibraryHandle().deregisterAllCallouts("dhcp4_srv_configured");
HooksManager::preCalloutsLibraryHandle().deregisterAllCallouts("pkt4_receive");
HooksManager::preCalloutsLibraryHandle().deregisterAllCallouts("pkt4_send");
HooksManager::preCalloutsLibraryHandle().deregisterAllCallouts("subnet4_select");
+ HooksManager::preCalloutsLibraryHandle().deregisterAllCallouts("leases4_committed");
HooksManager::preCalloutsLibraryHandle().deregisterAllCallouts("lease4_renew");
HooksManager::preCalloutsLibraryHandle().deregisterAllCallouts("lease4_release");
HooksManager::preCalloutsLibraryHandle().deregisterAllCallouts("lease4_decline");
HooksManager::preCalloutsLibraryHandle().deregisterAllCallouts("host4_identifier");
- delete srv_;
HooksManager::setTestMode(false);
bool status = HooksManager::unloadLibraries();
if (!status) {
/// @return pointer to create option object
static OptionPtr createOption(uint16_t option_code) {
- char payload[] = {
+ uint8_t payload[] = {
0xa, 0xb, 0xc, 0xe, 0xf, 0x10, 0x11, 0x12, 0x13, 0x14
};
if (callback_qry_pkt4_) {
callback_qry_options_copy_ = callback_qry_pkt4_->isCopyRetrievedOptions();
}
+
return (0);
}
return buffer4_receive_callout(callout_handle);
}
- /// Test callback that sets drop flag
+ /// Test callback that sets skip flag
/// @param callout_handle handle passed by the hooks framework
/// @return always 0
static int
- buffer4_receive_drop(CalloutHandle& callout_handle) {
+ buffer4_receive_skip(CalloutHandle& callout_handle) {
- callout_handle.setStatus(CalloutHandle::NEXT_STEP_DROP);
+ callout_handle.setStatus(CalloutHandle::NEXT_STEP_SKIP);
// Carry on as usual
return buffer4_receive_callout(callout_handle);
}
- /// Test callback that sets skip flag
+ /// Test callback that sets drop flag
/// @param callout_handle handle passed by the hooks framework
/// @return always 0
static int
- buffer4_receive_skip(CalloutHandle& callout_handle) {
+ buffer4_receive_drop(CalloutHandle& callout_handle) {
- callout_handle.setStatus(CalloutHandle::NEXT_STEP_SKIP);
+ callout_handle.setStatus(CalloutHandle::NEXT_STEP_DROP);
// Carry on as usual
return buffer4_receive_callout(callout_handle);
}
- /// test callback that stores received callout name and pkt4 value
+ /// Test callback that stores received callout name and pkt4 value
/// @param callout_handle handle passed by the hooks framework
/// @return always 0
static int
return (0);
}
- /// test callback that changes client-id value
+ /// Test callback that changes client-id value
/// @param callout_handle handle passed by the hooks framework
/// @return always 0
static int
Pkt4Ptr pkt;
callout_handle.getArgument("query4", pkt);
- // get rid of the old client-id
+ // Get rid of the old client-id
pkt->delOption(DHO_DHCP_CLIENT_IDENTIFIER);
- // add a new option
+ // Add a new option
pkt->addOption(createOption(DHO_DHCP_CLIENT_IDENTIFIER));
- // carry on as usual
+ // Carry on as usual
return pkt4_receive_callout(callout_handle);
}
- /// test callback that deletes client-id
+ /// Test callback that deletes client-id
/// @param callout_handle handle passed by the hooks framework
/// @return always 0
static int
Pkt4Ptr pkt;
callout_handle.getArgument("query4", pkt);
- // get rid of the old client-id (and no HWADDR)
+ // Get rid of the old client-id (and no HWADDR)
vector<uint8_t> mac;
pkt->delOption(DHO_DHCP_CLIENT_IDENTIFIER);
pkt->setHWAddr(1, 0, mac); // HWtype 1, hardware len = 0
- // carry on as usual
+ // Carry on as usual
return pkt4_receive_callout(callout_handle);
}
- /// test callback that sets drop flag
+ /// Test callback that sets skip flag
/// @param callout_handle handle passed by the hooks framework
/// @return always 0
static int
- pkt4_receive_drop(CalloutHandle& callout_handle) {
+ pkt4_receive_skip(CalloutHandle& callout_handle) {
Pkt4Ptr pkt;
callout_handle.getArgument("query4", pkt);
- callout_handle.setStatus(CalloutHandle::NEXT_STEP_DROP);
+ callout_handle.setStatus(CalloutHandle::NEXT_STEP_SKIP);
- // carry on as usual
+ // Carry on as usual
return pkt4_receive_callout(callout_handle);
}
- /// test callback that sets skip flag
+ /// Test callback that sets drop flag
/// @param callout_handle handle passed by the hooks framework
/// @return always 0
static int
- pkt4_receive_skip(CalloutHandle& callout_handle) {
+ pkt4_receive_drop(CalloutHandle& callout_handle) {
Pkt4Ptr pkt;
callout_handle.getArgument("query4", pkt);
- callout_handle.setStatus(CalloutHandle::NEXT_STEP_SKIP);
+ callout_handle.setStatus(CalloutHandle::NEXT_STEP_DROP);
- // carry on as usual
+ // Carry on as usual
return pkt4_receive_callout(callout_handle);
}
Pkt4Ptr pkt;
callout_handle.getArgument("response4", pkt);
- // get rid of the old server-id
+ // Get rid of the old server-id
pkt->delOption(DHO_DHCP_SERVER_IDENTIFIER);
- // add a new option
+ // Add a new option
pkt->addOption(createOption(DHO_DHCP_SERVER_IDENTIFIER));
- // carry on as usual
+ // Carry on as usual
return pkt4_send_callout(callout_handle);
}
- /// test callback that deletes server-id
+ /// Test callback that deletes server-id
/// @param callout_handle handle passed by the hooks framework
/// @return always 0
static int
Pkt4Ptr pkt;
callout_handle.getArgument("response4", pkt);
- // get rid of the old client-id
+ // Get rid of the old client-id
pkt->delOption(DHO_DHCP_SERVER_IDENTIFIER);
- // carry on as usual
+ // Carry on as usual
return pkt4_send_callout(callout_handle);
}
return pkt4_send_callout(callout_handle);
}
- /// Test callback that stores received callout name and pkt4 value
- /// @param callout_handle handle passed by the hooks framework
+ /// Test callback that stores response packet.
+ /// @param callout_handle handle passed by the hooks framework.
/// @return always 0
static int
buffer4_send_callout(CalloutHandle& callout_handle) {
return (0);
}
- /// Test callback that stores received callout name and pkt4 value
+ /// Test callback that sets skip flag
/// @param callout_handle handle passed by the hooks framework
/// @return always 0
static int
- skip_callout(CalloutHandle& callout_handle) {
+ buffer4_send_skip(CalloutHandle& callout_handle) {
callout_handle.setStatus(CalloutHandle::NEXT_STEP_SKIP);
- return (0);
+ // Carry on as usual
+ return buffer4_send_callout(callout_handle);
}
- /// Test callback that stores received callout name and pkt4 value
+ /// Test callback that sets drop flag
/// @param callout_handle handle passed by the hooks framework
/// @return always 0
static int
- drop_callout(CalloutHandle& callout_handle) {
+ buffer4_send_drop(CalloutHandle& callout_handle) {
callout_handle.setStatus(CalloutHandle::NEXT_STEP_DROP);
- return (0);
+ // carry on as usual
+ return buffer4_send_callout(callout_handle);
}
/// Test callback that stores received callout name and subnet4 values
/// @param callout_handle handle passed by the hooks framework
/// @return always 0
static int
- subnet4_select_different_subnet_callout(CalloutHandle& callout_handle) {
+ subnet4_select_different_subnet(CalloutHandle& callout_handle) {
// Call the basic callout to record all passed values
subnet4_select_callout(callout_handle);
return (0);
}
+ /// Test callback that sets skip flag
+ /// @param callout_handle handle passed by the hooks framework
+ /// @return always 0
+ static int
+ subnet4_select_skip(CalloutHandle& callout_handle) {
+
+ callout_handle.setStatus(CalloutHandle::NEXT_STEP_SKIP);
+
+ // Carry on as usual
+ return subnet4_select_callout(callout_handle);
+ }
+
/// Test callback that sets drop flag
+ /// @param callout_handle handle passed by the hooks framework
+ /// @return always 0
static int
- subnet4_select_drop_callout(CalloutHandle& callout_handle) {
+ subnet4_select_drop(CalloutHandle& callout_handle) {
callout_handle.setStatus(CalloutHandle::NEXT_STEP_DROP);
return subnet4_select_callout(callout_handle);
}
- /// Test callback that stores received callout name passed parameters
+ /// Test callback that stores received callout name and subnet4 values
/// @param callout_handle handle passed by the hooks framework
/// @return always 0
static int
- lease4_release_callout(CalloutHandle& callout_handle) {
- callback_name_ = string("lease4_release");
+ lease4_renew_callout(CalloutHandle& callout_handle) {
+ callback_name_ = string("lease4_renew");
callout_handle.getArgument("query4", callback_qry_pkt4_);
+ callout_handle.getArgument("subnet4", callback_subnet4_);
callout_handle.getArgument("lease4", callback_lease4_);
+ callout_handle.getArgument("hwaddr", callback_hwaddr_);
+ callout_handle.getArgument("clientid", callback_clientid_);
callback_argument_names_ = callout_handle.getArgumentNames();
return (0);
}
- /// Test callback that stores received callout name and subnet4 values
+ /// Test callback that sets the skip flag
/// @param callout_handle handle passed by the hooks framework
/// @return always 0
static int
- lease4_renew_callout(CalloutHandle& callout_handle) {
+ lease4_renew_skip_callout(CalloutHandle& callout_handle) {
callback_name_ = string("lease4_renew");
+ callout_handle.setStatus(CalloutHandle::NEXT_STEP_SKIP);
+
+ return (0);
+ }
+
+ /// Test callback that stores received callout name passed parameters
+ /// @param callout_handle handle passed by the hooks framework
+ /// @return always 0
+ static int
+ lease4_release_callout(CalloutHandle& callout_handle) {
+ callback_name_ = string("lease4_release");
+
callout_handle.getArgument("query4", callback_qry_pkt4_);
- callout_handle.getArgument("subnet4", callback_subnet4_);
callout_handle.getArgument("lease4", callback_lease4_);
- callout_handle.getArgument("hwaddr", callback_hwaddr_);
- callout_handle.getArgument("clientid", callback_clientid_);
callback_argument_names_ = callout_handle.getArgumentNames();
return (0);
}
+ /// Test callback that sets the skip flag
+ /// @param callout_handle handle passed by the hooks framework
+ /// @return always 0
+ static int
+ lease4_release_skip(CalloutHandle& callout_handle) {
+ callback_name_ = string("lease4_release");
+
+ callout_handle.setStatus(CalloutHandle::NEXT_STEP_SKIP);
+
+ return (0);
+ }
+
+ /// Test callback that sets the drop flag
+ /// @param callout_handle handle passed by the hooks framework
+ /// @return always 0
+ static int
+ lease4_release_drop(CalloutHandle& callout_handle) {
+ callback_name_ = string("lease4_release");
+
+ callout_handle.setStatus(CalloutHandle::NEXT_STEP_DROP);
+
+ return (0);
+ }
+
/// Test lease4_decline callback that stores received parameters.
///
/// @param callout_handle handle passed by the hooks framework
/// @param callout_handle handle passed by the hooks framework
/// @return always 0
static int
- lease4_decline_skip_callout(CalloutHandle& callout_handle) {
+ lease4_decline_skip(CalloutHandle& callout_handle) {
callout_handle.setStatus(CalloutHandle::NEXT_STEP_SKIP);
return (lease4_decline_callout(callout_handle));
/// @param callout_handle handle passed by the hooks framework
/// @return always 0
static int
- lease4_decline_drop_callout(CalloutHandle& callout_handle) {
+ lease4_decline_drop(CalloutHandle& callout_handle) {
callout_handle.setStatus(CalloutHandle::NEXT_STEP_DROP);
return (lease4_decline_callout(callout_handle));
static int
leases4_committed_callout(CalloutHandle& callout_handle) {
callback_name_ = string("leases4_committed");
+
callout_handle.getArgument("query4", callback_qry_pkt4_);
Lease4CollectionPtr leases4;
return (0);
}
- /// @brief Test host4_identifier callout by setting identifier to "foo"
+ /// @brief Test host4_identifier callback by setting identifier to "foo"
///
/// @param callout_handle handle passed by the hooks framework
/// @return always 0
std::vector<uint8_t> id_test;
handle.getArgument("id_value", id_test);
+ // Ok, now set the identifier.
std::vector<uint8_t> id = { 0x66, 0x6f, 0x6f }; // foo
handle.setArgument("id_value", id);
handle.setArgument("id_type", Host::IDENT_FLEX);
return (0);
}
-
- /// resets buffers used to store data received by callouts
+ /// Resets buffers used to store data received by callouts
void resetCalloutBuffers() {
callback_name_ = string("");
callback_qry_pkt4_.reset();
- callback_qry_pkt4_.reset();
+ callback_resp_pkt4_.reset();
+ callback_subnet4_.reset();
callback_lease4_.reset();
callback_deleted_lease4_.reset();
callback_hwaddr_.reset();
callback_clientid_.reset();
- callback_subnet4_.reset();
callback_subnet4collection_ = NULL;
callback_argument_names_.clear();
callback_qry_options_copy_ = false;
return (stat->getInteger().first);
}
- /// pointer to Dhcpv4Srv that is used in tests
- NakedDhcpv4Srv* srv_;
+ /// Pointer to Dhcpv4Srv that is used in tests
+ boost::shared_ptr<NakedDhcpv4Srv> srv_;
/// Pointer to the IO service used in the tests.
static IOServicePtr io_service_;
/// String name of the received callout
static string callback_name_;
- /// Client/query Pkt4 structure returned in the callout
+ /// Client's query Pkt4 structure returned in the callout
static Pkt4Ptr callback_qry_pkt4_;
- /// Server/response Pkt4 structure returned in the callout
+ /// Server's response Pkt4 structure returned in the callout
static Pkt4Ptr callback_resp_pkt4_;
- /// Lease4 structure returned in the leases4_committed callout
+ /// Pointer to lease4 structure returned in the leases4_committed callout
static Lease4Ptr callback_lease4_;
- /// Lease4 structure returned in the leases4_committed callout
+ /// Pointer to lease4 structure returned in the leases4_committed callout
static Lease4Ptr callback_deleted_lease4_;
/// Hardware address returned in the callout
/// Flag indicating if copying retrieved options was enabled for
/// a response during callout execution.
static bool callback_resp_options_copy_;
-
};
// The following fields are used in testing pkt4_receive_callout.
Pkt4Ptr HooksDhcpv4SrvTest::callback_qry_pkt4_;
Pkt4Ptr HooksDhcpv4SrvTest::callback_resp_pkt4_;
Subnet4Ptr HooksDhcpv4SrvTest::callback_subnet4_;
+const Subnet4Collection* HooksDhcpv4SrvTest::callback_subnet4collection_;
HWAddrPtr HooksDhcpv4SrvTest::callback_hwaddr_;
ClientIdPtr HooksDhcpv4SrvTest::callback_clientid_;
Lease4Ptr HooksDhcpv4SrvTest::callback_lease4_;
Lease4Ptr HooksDhcpv4SrvTest::callback_deleted_lease4_;
-const Subnet4Collection* HooksDhcpv4SrvTest::callback_subnet4collection_;
vector<string> HooksDhcpv4SrvTest::callback_argument_names_;
bool HooksDhcpv4SrvTest::callback_qry_options_copy_;
bool HooksDhcpv4SrvTest::callback_resp_options_copy_;
/// that no libraries are loaded and that any marker files are deleted.
void reset() {
// Unload any previously-loaded libraries.
- HooksManager::unloadLibraries();
+ EXPECT_TRUE(HooksManager::unloadLibraries());
// Get rid of any marker files.
static_cast<void>(remove(LOAD_MARKER_FILE));
static_cast<void>(remove(UNLOAD_MARKER_FILE));
static_cast<void>(remove(SRV_CONFIG_MARKER_FILE));
+
CfgMgr::instance().clear();
}
};
-
-// Checks if callouts installed on pkt4_receive are indeed called and the
+// Checks if callouts installed on buffer4_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 "buffer4_receive".
-TEST_F(HooksDhcpv4SrvTest, Buffer4ReceiveSimple) {
+TEST_F(HooksDhcpv4SrvTest, buffer4ReceiveSimple) {
IfaceMgrTestConfig test_config(true);
IfaceMgr::instance().openSockets4();
- // Install pkt4_receive_callout
+ // Install buffer4_receive_callout
EXPECT_NO_THROW(HooksManager::preCalloutsLibraryHandle().registerCallout(
"buffer4_receive", buffer4_receive_callout));
// Let's create a simple DISCOVER
- Pkt4Ptr dis = generateSimpleDiscover();
+ Pkt4Ptr discover = generateSimpleDiscover();
// Simulate that we have received that traffic
- srv_->fakeReceive(dis);
+ srv_->fakeReceive(discover);
// Server will now process to run its normal loop, but instead of calling
// IfaceMgr::receive4(), it will read all packets from the list set by
EXPECT_EQ("buffer4_receive", callback_name_);
// Check that pkt4 argument passing was successful and returned proper value
- EXPECT_TRUE(callback_qry_pkt4_.get() == dis.get());
+ EXPECT_TRUE(callback_qry_pkt4_.get() == discover.get());
// Check that all expected parameters are there
vector<string> expected_argument_names;
EXPECT_TRUE(callback_qry_options_copy_);
// Check if the callout handle state was reset after the callout.
- checkCalloutHandleReset(dis);
+ checkCalloutHandleReset(discover);
}
// Checks if callouts installed on buffer4_receive is able to change
}
// Checks if callouts installed on buffer4_receive is able to set skip flag that
-// will cause the server to not parse the packet. Even though the packet is valid,
-// the server should eventually drop it, because there won't be mandatory options
-// (or rather option objects) in it.
+// will cause the server to not process the packet (drop), even though it is valid.
TEST_F(HooksDhcpv4SrvTest, buffer4ReceiveSkip) {
IfaceMgrTestConfig test_config(true);
IfaceMgr::instance().openSockets4();
- // Install pkt4_receive_callout
+ // Install buffer4_receive_skip
EXPECT_NO_THROW(HooksManager::preCalloutsLibraryHandle().registerCallout(
"buffer4_receive", buffer4_receive_skip));
// Server will now process to run its normal loop, but instead of calling
// IfaceMgr::receive4(), it will read all packets from the list set by
// fakeReceive()
- // In particular, it should call registered pkt4_receive callback.
+ // In particular, it should call registered buffer4_receive callback.
srv_->run();
// Check that the server dropped the packet and did not produce any response
}
// Checks if callouts installed on buffer4_receive is able to set drop flag that
-// will cause the server to drop the packet.
+// will cause the server to not process the packet (drop), even though it is valid.
TEST_F(HooksDhcpv4SrvTest, buffer4ReceiveDrop) {
IfaceMgrTestConfig test_config(true);
IfaceMgr::instance().openSockets4();
- // Install pkt4_receive_callout
+ // Install buffer4_receive_drop
EXPECT_NO_THROW(HooksManager::preCalloutsLibraryHandle().registerCallout(
"buffer4_receive", buffer4_receive_drop));
// Server will now process to run its normal loop, but instead of calling
// IfaceMgr::receive4(), it will read all packets from the list set by
// fakeReceive()
- // In particular, it should call registered pkt4_receive callback.
+ // In particular, it should call registered buffer4_receive callback.
srv_->run();
// Check that the server dropped the packet and did not produce any response
"pkt4_receive", pkt4_receive_callout));
// Let's create a simple DISCOVER
- Pkt4Ptr sol = generateSimpleDiscover();
+ Pkt4Ptr discover = generateSimpleDiscover();
// Simulate that we have received that traffic
- srv_->fakeReceive(sol);
+ srv_->fakeReceive(discover);
// Server will now process to run its normal loop, but instead of calling
// IfaceMgr::receive4(), it will read all packets from the list set by
// In particular, it should call registered pkt4_receive callback.
srv_->run();
- // check that the callback called is indeed the one we installed
+ // Check that the callback called is indeed the one we installed
EXPECT_EQ("pkt4_receive", callback_name_);
- // check that pkt4 argument passing was successful and returned proper value
- EXPECT_TRUE(callback_qry_pkt4_.get() == sol.get());
+ // Check that pkt4 argument passing was successful and returned proper value
+ EXPECT_TRUE(callback_qry_pkt4_.get() == discover.get());
// Check that all expected parameters are there
vector<string> expected_argument_names;
EXPECT_TRUE(callback_qry_options_copy_);
// Check if the callout handle state was reset after the callout.
- checkCalloutHandleReset(sol);
+ checkCalloutHandleReset(discover);
}
// Checks if callouts installed on pkt4_received is able to change
// the values and the parameters are indeed used by the server.
-TEST_F(HooksDhcpv4SrvTest, valueChange_pkt4_receive) {
+TEST_F(HooksDhcpv4SrvTest, pkt4ReceiveValueChange) {
IfaceMgrTestConfig test_config(true);
IfaceMgr::instance().openSockets4();
"pkt4_receive", pkt4_receive_change_clientid));
// Let's create a simple DISCOVER
- Pkt4Ptr sol = generateSimpleDiscover();
+ Pkt4Ptr discover = generateSimpleDiscover();
// Simulate that we have received that traffic
- srv_->fakeReceive(sol);
+ srv_->fakeReceive(discover);
// Server will now process to run its normal loop, but instead of calling
// IfaceMgr::receive4(), it will read all packets from the list set by
// In particular, it should call registered pkt4_receive callback.
srv_->run();
- // check that the server did send a response
+ // Check that the server did send a response
ASSERT_EQ(1, srv_->fake_sent_.size());
// Make sure that we received a response
EXPECT_TRUE(clientid->equals(expected));
// Check if the callout handle state was reset after the callout.
- checkCalloutHandleReset(sol);
+ checkCalloutHandleReset(discover);
}
// Checks if callouts installed on pkt4_received is able to delete
IfaceMgrTestConfig test_config(true);
IfaceMgr::instance().openSockets4();
- // Install pkt4_receive_callout
+ // Install pkt4_receive_delete_clientid
EXPECT_NO_THROW(HooksManager::preCalloutsLibraryHandle().registerCallout(
"pkt4_receive", pkt4_receive_delete_clientid));
// Let's create a simple DISCOVER
- Pkt4Ptr sol = generateSimpleDiscover();
+ Pkt4Ptr discover = generateSimpleDiscover();
// Simulate that we have received that traffic
- srv_->fakeReceive(sol);
+ srv_->fakeReceive(discover);
// Server will now process to run its normal loop, but instead of calling
// IfaceMgr::receive4(), it will read all packets from the list set by
ASSERT_EQ(0, srv_->fake_sent_.size());
// Check if the callout handle state was reset after the callout.
- checkCalloutHandleReset(sol);
+ checkCalloutHandleReset(discover);
}
// Checks if callouts installed on pkt4_received is able to set skip flag that
IfaceMgrTestConfig test_config(true);
IfaceMgr::instance().openSockets4();
- // Install pkt4_receive_callout
+ // Install pkt4_receive_skip
EXPECT_NO_THROW(HooksManager::preCalloutsLibraryHandle().registerCallout(
"pkt4_receive", pkt4_receive_skip));
// Let's create a simple DISCOVER
- Pkt4Ptr sol = generateSimpleDiscover();
+ Pkt4Ptr discover = generateSimpleDiscover();
// Simulate that we have received that traffic
- srv_->fakeReceive(sol);
+ srv_->fakeReceive(discover);
// Server will now process to run its normal loop, but instead of calling
// IfaceMgr::receive4(), it will read all packets from the list set by
// In particular, it should call registered pkt4_receive callback.
srv_->run();
- // check that the server dropped the packet and did not produce any response
+ // Check that the server dropped the packet and did not produce any response
ASSERT_EQ(0, srv_->fake_sent_.size());
// Check if the callout handle state was reset after the callout.
- checkCalloutHandleReset(sol);
+ checkCalloutHandleReset(discover);
}
// Checks if callouts installed on pkt4_received is able to set drop flag that
IfaceMgrTestConfig test_config(true);
IfaceMgr::instance().openSockets4();
- // Install pkt4_receive_callout
+ // Install pkt4_receive_drop
EXPECT_NO_THROW(HooksManager::preCalloutsLibraryHandle().registerCallout(
"pkt4_receive", pkt4_receive_drop));
// Let's create a simple DISCOVER
- Pkt4Ptr sol = generateSimpleDiscover();
+ Pkt4Ptr discover = generateSimpleDiscover();
// Simulate that we have received that traffic
- srv_->fakeReceive(sol);
+ srv_->fakeReceive(discover);
// Server will now process to run its normal loop, but instead of calling
// IfaceMgr::receive4(), it will read all packets from the list set by
// In particular, it should call registered pkt4_receive callback.
srv_->run();
- // check that the server dropped the packet and did not produce any response
+ // Check that the server dropped the packet and did not produce any response
ASSERT_EQ(0, srv_->fake_sent_.size());
// Check if the callout handle state was reset after the callout.
- checkCalloutHandleReset(sol);
+ checkCalloutHandleReset(discover);
}
-
// Checks if callouts installed on pkt4_send are indeed called and the
// all necessary parameters are passed.
TEST_F(HooksDhcpv4SrvTest, pkt4SendSimple) {
IfaceMgrTestConfig test_config(true);
IfaceMgr::instance().openSockets4();
- // Install pkt4_receive_callout
+ // Install pkt4_send_callout
EXPECT_NO_THROW(HooksManager::preCalloutsLibraryHandle().registerCallout(
"pkt4_send", pkt4_send_callout));
// Let's create a simple DISCOVER
- Pkt4Ptr sol = generateSimpleDiscover();
+ Pkt4Ptr discover = generateSimpleDiscover();
// Simulate that we have received that traffic
- srv_->fakeReceive(sol);
+ srv_->fakeReceive(discover);
// Server will now process to run its normal loop, but instead of calling
// IfaceMgr::receive4(), it will read all packets from the list set by
// fakeReceive()
- // In particular, it should call registered pkt4_receive callback.
+ // In particular, it should call registered pkt4_send callback.
srv_->run();
// Check that the callback called is indeed the one we installed
ASSERT_EQ(1, srv_->fake_sent_.size());
Pkt4Ptr adv = srv_->fake_sent_.front();
- // Check that pkt4 argument passing was successful and returned proper value
+ // Check that pkt4 argument passing was successful and returned proper
+ // values
+ ASSERT_TRUE(callback_qry_pkt4_);
+ EXPECT_TRUE(callback_qry_pkt4_.get() == discover.get());
ASSERT_TRUE(callback_resp_pkt4_);
EXPECT_TRUE(callback_resp_pkt4_.get() == adv.get());
- // That that the query4 argument was correctly set to the Discover we sent.
- ASSERT_TRUE(callback_qry_pkt4_);
- EXPECT_TRUE(callback_qry_pkt4_.get() == sol.get());
-
// Check that all expected parameters are there
vector<string> expected_argument_names;
- expected_argument_names.push_back(string("response4"));
expected_argument_names.push_back(string("query4"));
+ expected_argument_names.push_back(string("response4"));
sort(callback_argument_names_.begin(), callback_argument_names_.end());
sort(expected_argument_names.begin(), expected_argument_names.end());
EXPECT_TRUE(expected_argument_names == callback_argument_names_);
EXPECT_TRUE(callback_resp_options_copy_);
// Check if the callout handle state was reset after the callout.
- checkCalloutHandleReset(sol);
+ checkCalloutHandleReset(discover);
}
// Checks if callouts installed on pkt4_send is able to change
IfaceMgrTestConfig test_config(true);
IfaceMgr::instance().openSockets4();
- // Install pkt4_receive_callout
+ // Install pkt4_send_change_serverid
EXPECT_NO_THROW(HooksManager::preCalloutsLibraryHandle().registerCallout(
"pkt4_send", pkt4_send_change_serverid));
// Let's create a simple DISCOVER
- Pkt4Ptr sol = generateSimpleDiscover();
+ Pkt4Ptr discover = generateSimpleDiscover();
// Simulate that we have received that traffic
- srv_->fakeReceive(sol);
+ srv_->fakeReceive(discover);
// Server will now process to run its normal loop, but instead of calling
// IfaceMgr::receive4(), it will read all packets from the list set by
// fakeReceive()
- // In particular, it should call registered pkt4_receive callback.
+ // In particular, it should call registered pkt4_send callback.
srv_->run();
- // check that the server did send a response
+ // Check that the server did send a response
ASSERT_EQ(1, srv_->fake_sent_.size());
// Make sure that we received a response
EXPECT_TRUE(clientid->equals(expected));
// Check if the callout handle state was reset after the callout.
- checkCalloutHandleReset(sol);
+ checkCalloutHandleReset(discover);
}
// Checks if callouts installed on pkt4_send is able to delete
IfaceMgrTestConfig test_config(true);
IfaceMgr::instance().openSockets4();
- // Install pkt4_receive_callout
+ // Install pkt4_send_delete_serverid
EXPECT_NO_THROW(HooksManager::preCalloutsLibraryHandle().registerCallout(
"pkt4_send", pkt4_send_delete_serverid));
// Let's create a simple DISCOVER
- Pkt4Ptr sol = generateSimpleDiscover();
+ Pkt4Ptr discover = generateSimpleDiscover();
// Simulate that we have received that traffic
- srv_->fakeReceive(sol);
+ srv_->fakeReceive(discover);
// Server will now process to run its normal loop, but instead of calling
// IfaceMgr::receive4(), it will read all packets from the list set by
// fakeReceive()
- // In particular, it should call registered pkt4_receive callback.
+ // In particular, it should call registered pkt4_send callback.
srv_->run();
// Check that the server indeed sent a malformed ADVERTISE
EXPECT_FALSE(adv->getOption(DHO_DHCP_SERVER_IDENTIFIER));
// Check if the callout handle state was reset after the callout.
- checkCalloutHandleReset(sol);
+ checkCalloutHandleReset(discover);
}
// Checks if callouts installed on pkt4_skip is able to set skip flag that
// will cause the server to not process the packet (drop), even though it is valid.
-TEST_F(HooksDhcpv4SrvTest, skip_pkt4_send) {
+TEST_F(HooksDhcpv4SrvTest, pkt4SendSkip) {
IfaceMgrTestConfig test_config(true);
IfaceMgr::instance().openSockets4();
- // Install pkt4_receive_callout
+ // Install pkt4_send_skip
EXPECT_NO_THROW(HooksManager::preCalloutsLibraryHandle().registerCallout(
"pkt4_send", pkt4_send_skip));
// Let's create a simple REQUEST
- Pkt4Ptr sol = generateSimpleDiscover();
+ Pkt4Ptr discover = generateSimpleDiscover();
// Simulate that we have received that traffic
- srv_->fakeReceive(sol);
+ srv_->fakeReceive(discover);
// Server will now process to run its normal loop, but instead of calling
// IfaceMgr::receive4(), it will read all packets from the list set by
// In particular, it should call registered pkt4_send callback.
srv_->run();
- // Check that the server sent the message
+ // Check that the server send the packet
ASSERT_EQ(1, srv_->fake_sent_.size());
// Get the first packet and check that it has zero length (i.e. the server
// did not do packing on its own)
Pkt4Ptr sent = srv_->fake_sent_.front();
+
+ // The actual size of sent packet should be 0
EXPECT_EQ(0, sent->getBuffer().getLength());
// Check if the callout handle state was reset after the callout.
- checkCalloutHandleReset(sol);
+ checkCalloutHandleReset(discover);
}
// Checks if callouts installed on pkt4_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(HooksDhcpv4SrvTest, drop_pkt4_send) {
+TEST_F(HooksDhcpv4SrvTest, pkt4SendDrop) {
IfaceMgrTestConfig test_config(true);
IfaceMgr::instance().openSockets4();
- // Install pkt4_receive_callout
+ // Install pkt4_send_drop
EXPECT_NO_THROW(HooksManager::preCalloutsLibraryHandle().registerCallout(
"pkt4_send", pkt4_send_drop));
// Let's create a simple REQUEST
- Pkt4Ptr sol = generateSimpleDiscover();
+ Pkt4Ptr discover = generateSimpleDiscover();
// Simulate that we have received that traffic
- srv_->fakeReceive(sol);
+ srv_->fakeReceive(discover);
// Server will now process to run its normal loop, but instead of calling
// IfaceMgr::receive4(), it will read all packets from the list set by
// In particular, it should call registered pkt4_send callback.
srv_->run();
- // Check that the server did not the message
- ASSERT_EQ(0, srv_->fake_sent_.size());
+ // Check that the server does not send the packet
+ EXPECT_EQ(0, srv_->fake_sent_.size());
// Check if the callout handle state was reset after the callout.
- checkCalloutHandleReset(sol);
+ checkCalloutHandleReset(discover);
}
// Checks if callouts installed on buffer4_send are indeed called and the
IfaceMgrTestConfig test_config(true);
IfaceMgr::instance().openSockets4();
- // Install pkt4_receive_callout
+ // Install buffer4_send_callout
EXPECT_NO_THROW(HooksManager::preCalloutsLibraryHandle().registerCallout(
"buffer4_send", buffer4_send_callout));
// Server will now process to run its normal loop, but instead of calling
// IfaceMgr::receive4(), it will read all packets from the list set by
// fakeReceive()
- // In particular, it should call registered pkt4_receive callback.
+ // In particular, it should call registered buffer4_send callback.
srv_->run();
// Check that the callback called is indeed the one we installed
// Checks if callouts installed on buffer4_send are indeed called and that
// the output buffer can be changed.
-TEST_F(HooksDhcpv4SrvTest, buffer4Send) {
+TEST_F(HooksDhcpv4SrvTest, buffer4SendChange) {
IfaceMgrTestConfig test_config(true);
IfaceMgr::instance().openSockets4();
- // Install pkt4_receive_callout
+ // Install buffer4_send_change_callout
EXPECT_NO_THROW(HooksManager::preCalloutsLibraryHandle().registerCallout(
"buffer4_send", buffer4_send_change_callout));
// Server will now process to run its normal loop, but instead of calling
// IfaceMgr::receive4(), it will read all packets from the list set by
// fakeReceive()
- // In particular, it should call registered pkt4_receive callback.
+ // In particular, it should call registered buffer4_send callback.
srv_->run();
// Check that there is one packet sent
IfaceMgrTestConfig test_config(true);
IfaceMgr::instance().openSockets4();
- // Install pkt4_receive_callout
+ // Install buffer4_send_skip
EXPECT_NO_THROW(HooksManager::preCalloutsLibraryHandle().registerCallout(
- "buffer4_send", skip_callout));
+ "buffer4_send", buffer4_send_skip));
// Let's create a simple DISCOVER
Pkt4Ptr discover = generateSimpleDiscover();
// Server will now process to run its normal loop, but instead of calling
// IfaceMgr::receive4(), it will read all packets from the list set by
// fakeReceive()
- // In particular, it should call registered pkt4_receive callback.
+ // In particular, it should call registered buffer4_send callback.
srv_->run();
+ // Check that the callback called is indeed the one we installed
+ EXPECT_EQ("buffer4_send", callback_name_);
+
// Check that there is no packet sent.
ASSERT_EQ(0, srv_->fake_sent_.size());
IfaceMgrTestConfig test_config(true);
IfaceMgr::instance().openSockets4();
- // Install pkt4_receive_callout
+ // Install buffer4_send_drop
EXPECT_NO_THROW(HooksManager::preCalloutsLibraryHandle().registerCallout(
- "buffer4_send", drop_callout));
+ "buffer4_send", buffer4_send_drop));
// Let's create a simple DISCOVER
Pkt4Ptr discover = generateSimpleDiscover();
// Server will now process to run its normal loop, but instead of calling
// IfaceMgr::receive4(), it will read all packets from the list set by
// fakeReceive()
- // In particular, it should call registered pkt4_receive callback.
+ // In particular, it should call registered buffer4_send callback.
srv_->run();
- // Check that there is no packet sent.
- ASSERT_EQ(0, srv_->fake_sent_.size());
+ // Check that the callback called is indeed the one we installed
+ EXPECT_EQ("buffer4_send", callback_name_);
+
+ // Check that there is no packet sent
+ EXPECT_EQ(0, srv_->fake_sent_.size());
// Check if the callout handle state was reset after the callout.
checkCalloutHandleReset(discover);
}
-
// This test checks if subnet4_select callout is triggered and reports
// valid parameters
TEST_F(HooksDhcpv4SrvTest, subnet4SelectSimple) {
// Commit the config
CfgMgr::instance().commit();
- // Install pkt4_receive_callout
+ // Install subnet4_select_callout
EXPECT_NO_THROW(HooksManager::preCalloutsLibraryHandle().registerCallout(
"subnet4_select", subnet4_select_callout));
// Prepare discover packet. Server should select first subnet for it
- Pkt4Ptr sol = Pkt4Ptr(new Pkt4(DHCPDISCOVER, 1234));
- sol->setRemoteAddr(IOAddress("192.0.2.1"));
- sol->setIface("eth1");
- sol->setIndex(ETH1_INDEX);
+ Pkt4Ptr discover = Pkt4Ptr(new Pkt4(DHCPDISCOVER, 1234));
+ discover->setRemoteAddr(IOAddress("192.0.2.1"));
+ discover->setIface("eth1");
+ discover->setIndex(ETH1_INDEX);
OptionPtr clientid = generateClientId();
- sol->addOption(clientid);
+ discover->addOption(clientid);
// Pass it to the server and get an advertise
- Pkt4Ptr adv = srv_->processDiscover(sol);
+ Pkt4Ptr adv = srv_->processDiscover(discover);
- // check if we get response at all
+ // Check if we get response at all
ASSERT_TRUE(adv);
// Check that the callback called is indeed the one we installed
EXPECT_EQ("subnet4_select", callback_name_);
// Check that pkt4 argument passing was successful and returned proper value
- EXPECT_TRUE(callback_qry_pkt4_.get() == sol.get());
+ EXPECT_TRUE(callback_qry_pkt4_.get() == discover.get());
const Subnet4Collection* exp_subnets =
CfgMgr::instance().getCurrentCfg()->getCfgSubnets4()->getAll();
// The server is supposed to pick the first subnet, because of matching
// interface. Check that the value is reported properly.
ASSERT_TRUE(callback_subnet4_);
- EXPECT_EQ(exp_subnets->begin()->get(), callback_subnet4_.get());
+ EXPECT_EQ(callback_subnet4_.get(), exp_subnets->begin()->get());
// Server is supposed to report two subnets
ASSERT_EQ(exp_subnets->size(), callback_subnet4collection_->size());
EXPECT_TRUE(callback_qry_options_copy_);
// Check if the callout handle state was reset after the callout.
- checkCalloutHandleReset(sol);
+ checkCalloutHandleReset(discover);
}
// This test checks if callout installed on subnet4_select hook point can pick
CfgMgr::instance().commit();
- // Install a callout
+ // Install subnet4_select_different_subnet
EXPECT_NO_THROW(HooksManager::preCalloutsLibraryHandle().registerCallout(
- "subnet4_select", subnet4_select_different_subnet_callout));
+ "subnet4_select", subnet4_select_different_subnet));
// Prepare discover packet. Server should select first subnet for it
- Pkt4Ptr sol = Pkt4Ptr(new Pkt4(DHCPDISCOVER, 1234));
- sol->setRemoteAddr(IOAddress("192.0.2.1"));
- sol->setIface("eth0");
- sol->setIndex(ETH0_INDEX);
+ Pkt4Ptr discover = Pkt4Ptr(new Pkt4(DHCPDISCOVER, 1234));
+ discover->setRemoteAddr(IOAddress("192.0.2.1"));
+ discover->setIface("eth0");
+ discover->setIndex(ETH0_INDEX);
OptionPtr clientid = generateClientId();
- sol->addOption(clientid);
+ discover->addOption(clientid);
// Pass it to the server and get an advertise
- Pkt4Ptr adv = srv_->processDiscover(sol);
+ Pkt4Ptr adv = srv_->processDiscover(discover);
- // check if we get response at all
+ // Check if we get response at all
ASSERT_TRUE(adv);
// The response should have an address from second pool, so let's check it
EXPECT_TRUE((*subnet)->inPool(Lease::TYPE_V4, addr));
// Check if the callout handle state was reset after the callout.
- checkCalloutHandleReset(sol);
+ checkCalloutHandleReset(discover);
+}
+
+// Checks that subnet4_select is able to drop the packet.
+TEST_F(HooksDhcpv4SrvTest, subnet4SelectDrop) {
+ IfaceMgrTestConfig test_config(true);
+ IfaceMgr::instance().openSockets4();
+
+ // Install subnet4_select_drop
+ EXPECT_NO_THROW(HooksManager::preCalloutsLibraryHandle().registerCallout(
+ "subnet4_select", subnet4_select_drop));
+
+ // Let's create a simple DISCOVER
+ Pkt4Ptr discover = generateSimpleDiscover();
+
+ // Simulate that we have received that traffic
+ srv_->fakeReceive(discover);
+
+ // Server will now process to run its normal loop, but instead of calling
+ // IfaceMgr::receive4(), it will read all packets from the list set by
+ // fakeReceive()
+ // In particular, it should call registered subnet4_select callback.
+ srv_->run();
+
+ // Check that the server dropped the packet and did not produce any response
+ ASSERT_EQ(0, srv_->fake_sent_.size());
+
+ // Check if the callout handle state was reset after the callout.
+ checkCalloutHandleReset(discover);
}
// This test verifies that the leases4_committed hook point is not triggered
IfaceMgrTestConfig test_config(true);
IfaceMgr::instance().openSockets4();
+ // Install leases4_committed callout
ASSERT_NO_THROW(HooksManager::preCalloutsLibraryHandle().registerCallout(
"leases4_committed", leases4_committed_callout));
-
Dhcp4Client client(Dhcp4Client::SELECTING);
client.setIfaceName("eth1");
client.setIfaceIndex(ETH1_INDEX);
ASSERT_NO_THROW(HooksManager::preCalloutsLibraryHandle().registerCallout(
"leases4_committed", leases4_committed_callout));
-
Dhcp4Client client(Dhcp4Client::SELECTING);
client.useRelay();
ASSERT_NO_THROW(client.doInform());
checkCalloutHandleReset(client.getContext().query_);
}
-// This test verifies that incoming (positive) REQUEST/Renewing can be handled
-// properly and that callout installed on lease4_renew is triggered with
-// expected parameters.
-TEST_F(HooksDhcpv4SrvTest, lease4RenewSimple) {
- IfaceMgrTestConfig test_config(true);
- IfaceMgr::instance().openSockets4();
-
- const IOAddress addr("192.0.2.106");
- const uint32_t temp_valid = 100;
- const time_t temp_timestamp = time(NULL) - 10;
-
- // Install a callout
- EXPECT_NO_THROW(HooksManager::preCalloutsLibraryHandle().registerCallout(
- "lease4_renew", lease4_renew_callout));
-
- // Generate client-id also sets client_id_ member
- OptionPtr clientid = generateClientId();
-
- // Check that the address we are about to use is indeed in pool
- ASSERT_TRUE(subnet_->inPool(Lease::TYPE_V4, addr));
-
- // let's create a lease and put it in the LeaseMgr
- uint8_t hwaddr2_data[] = { 0, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe};
- HWAddrPtr hwaddr2(new HWAddr(hwaddr2_data, sizeof(hwaddr2_data), HTYPE_ETHER));
- Lease4Ptr used(new Lease4(IOAddress("192.0.2.106"), hwaddr2,
- &client_id_->getDuid()[0], client_id_->getDuid().size(),
- temp_valid, temp_timestamp, subnet_->getID()));
- ASSERT_TRUE(LeaseMgrFactory::instance().addLease(used));
-
- // Check that the lease is really in the database
- Lease4Ptr l = LeaseMgrFactory::instance().getLease4(addr);
- ASSERT_TRUE(l);
-
- // Let's create a RENEW
- Pkt4Ptr req = Pkt4Ptr(new Pkt4(DHCPREQUEST, 1234));
- req->setRemoteAddr(IOAddress(addr));
- req->setYiaddr(addr);
- req->setCiaddr(addr); // client's address
- req->setIface("eth0");
- req->setIndex(ETH0_INDEX);
- req->setHWAddr(hwaddr2);
-
- req->addOption(clientid);
- req->addOption(srv_->getServerID());
-
- // Pass it to the server and hope for a REPLY
- Pkt4Ptr ack = srv_->processRequest(req);
-
- // Check if we get response at all
- checkResponse(ack, DHCPACK, 1234);
-
- // Check that the lease is really in the database
- l = checkLease(ack, clientid, req->getHWAddr(), addr);
- ASSERT_TRUE(l);
-
- // Check that preferred, valid and cltt were really updated
- EXPECT_EQ(l->valid_lft_, subnet_->getValid());
-
- // Check that the callback called is indeed the one we installed
- EXPECT_EQ("lease4_renew", callback_name_);
-
- // Check that query4 argument passing was successful and
- // returned proper value
- EXPECT_TRUE(callback_qry_pkt4_.get() == req.get());
-
- // Check that hwaddr parameter is passed properly
- ASSERT_TRUE(callback_hwaddr_);
- EXPECT_TRUE(*callback_hwaddr_ == *req->getHWAddr());
-
- // Check that the subnet is passed properly
- ASSERT_TRUE(callback_subnet4_);
- EXPECT_EQ(callback_subnet4_->toText(), subnet_->toText());
-
- ASSERT_TRUE(callback_clientid_);
- ASSERT_TRUE(client_id_);
- EXPECT_TRUE(*client_id_ == *callback_clientid_);
-
- // Check if all expected parameters were really received
- vector<string> expected_argument_names;
- expected_argument_names.push_back("query4");
- expected_argument_names.push_back("subnet4");
- expected_argument_names.push_back("clientid");
- expected_argument_names.push_back("hwaddr");
- expected_argument_names.push_back("lease4");
- 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);
-
- Lease4Ptr lease = LeaseMgrFactory::instance().getLease4(addr);
- EXPECT_TRUE(LeaseMgrFactory::instance().deleteLease(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 a callout installed on lease4_renew can trigger
-// the server to not renew a lease.
-TEST_F(HooksDhcpv4SrvTest, lease4RenewSkip) {
- IfaceMgrTestConfig test_config(true);
- IfaceMgr::instance().openSockets4();
-
- const IOAddress addr("192.0.2.106");
- const uint32_t temp_valid = 100;
- const time_t temp_timestamp = time(NULL) - 10;
-
- // Install a callout
- EXPECT_NO_THROW(HooksManager::preCalloutsLibraryHandle().registerCallout(
- "lease4_renew", skip_callout));
-
- // Generate client-id also sets client_id_ member
- OptionPtr clientid = generateClientId();
-
- // Check that the address we are about to use is indeed in pool
- ASSERT_TRUE(subnet_->inPool(Lease::TYPE_V4, addr));
-
- // let's create a lease and put it in the LeaseMgr
- uint8_t hwaddr2_data[] = { 0, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe};
- HWAddrPtr hwaddr2(new HWAddr(hwaddr2_data, sizeof(hwaddr2_data), HTYPE_ETHER));
- Lease4Ptr used(new Lease4(IOAddress("192.0.2.106"), hwaddr2,
- &client_id_->getDuid()[0], client_id_->getDuid().size(),
- temp_valid, temp_timestamp, subnet_->getID()));
- ASSERT_TRUE(LeaseMgrFactory::instance().addLease(used));
-
- // Check that the lease is really in the database
- Lease4Ptr l = LeaseMgrFactory::instance().getLease4(addr);
- ASSERT_TRUE(l);
-
- // Check that preferred, valid and cltt really set.
- // Constructed lease looks as if it was assigned 10 seconds ago
- EXPECT_EQ(l->valid_lft_, temp_valid);
- EXPECT_EQ(l->cltt_, temp_timestamp);
-
- // Let's create a RENEW
- Pkt4Ptr req = Pkt4Ptr(new Pkt4(DHCPREQUEST, 1234));
- req->setRemoteAddr(IOAddress(addr));
- req->setYiaddr(addr);
- req->setCiaddr(addr); // client's address
- req->setIface("eth0");
- req->setIndex(ETH0_INDEX);
- req->setHWAddr(hwaddr2);
-
- req->addOption(clientid);
- req->addOption(srv_->getServerID());
-
- // Pass it to the server and hope for a REPLY
- Pkt4Ptr ack = srv_->processRequest(req);
- ASSERT_TRUE(ack);
-
- // Check that the lease is really in the database
- l = checkLease(ack, clientid, req->getHWAddr(), addr);
- ASSERT_TRUE(l);
-
- // Check that valid and cltt were NOT updated
- EXPECT_EQ(temp_valid, l->valid_lft_);
- EXPECT_EQ(temp_timestamp, l->cltt_);
-
- Lease4Ptr lease = LeaseMgrFactory::instance().getLease4(addr);
- EXPECT_TRUE(LeaseMgrFactory::instance().deleteLease(lease));
-
- // Check if the callout handle state was reset after the callout.
- checkCalloutHandleReset(req);
-}
-
// This test verifies that the callout installed on the leases4_committed hook
// point is executed as a result of DHCPREQUEST message sent to allocate new
// lease or renew an existing lease.
ASSERT_NO_THROW(HooksManager::preCalloutsLibraryHandle().registerCallout(
"leases4_committed", leases4_committed_callout));
-
Dhcp4Client client(Dhcp4Client::SELECTING);
client.setIfaceName("eth1");
client.setIfaceIndex(ETH1_INDEX);
EXPECT_FALSE(callback_deleted_lease4_);
}
+// This test verifies that the leases4_committed callout is executed
+// with declined leases as argument when DHCPDECLINE is processed.
+TEST_F(HooksDhcpv4SrvTest, leases4CommittedDecline) {
+ IfaceMgrTestConfig test_config(true);
+ IfaceMgr::instance().openSockets4();
+
+ ASSERT_NO_THROW(HooksManager::preCalloutsLibraryHandle().registerCallout(
+ "leases4_committed", leases4_committed_callout));
+
+ Dhcp4Client client(Dhcp4Client::SELECTING);
+ client.useRelay();
+ ASSERT_NO_THROW(client.doDORA(boost::shared_ptr<IOAddress>(new IOAddress("192.0.2.100"))));
+
+ // Make sure that we received a response
+ ASSERT_TRUE(client.getContext().response_);
+
+ resetCalloutBuffers();
+
+ ASSERT_NO_THROW(client.doDecline());
+
+ // Check that the callback called is indeed the one we installed
+ EXPECT_EQ("leases4_committed", callback_name_);
+
+ // Check if all expected parameters were really received
+ vector<string> expected_argument_names;
+ expected_argument_names.push_back("query4");
+ expected_argument_names.push_back("deleted_leases4");
+ expected_argument_names.push_back("leases4");
+
+ sort(expected_argument_names.begin(), expected_argument_names.end());
+ EXPECT_TRUE(callback_argument_names_ == expected_argument_names);
+
+ // No new allocations.
+ ASSERT_TRUE(callback_lease4_);
+ EXPECT_EQ("192.0.2.100", callback_lease4_->addr_.toText());
+ EXPECT_EQ(Lease::STATE_DECLINED, callback_lease4_->state_);
+
+ // Released lease should be returned.
+ EXPECT_FALSE(callback_deleted_lease4_);
+
+ // 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 leases4_committed callout is executed
+// with deleted leases as argument when DHCPRELEASE is processed.
+TEST_F(HooksDhcpv4SrvTest, leases4CommittedRelease) {
+ IfaceMgrTestConfig test_config(true);
+ IfaceMgr::instance().openSockets4();
+
+ ASSERT_NO_THROW(HooksManager::preCalloutsLibraryHandle().registerCallout(
+ "leases4_committed", leases4_committed_callout));
+
+ Dhcp4Client client(Dhcp4Client::SELECTING);
+ client.setIfaceName("eth1");
+ client.setIfaceIndex(ETH1_INDEX);
+ ASSERT_NO_THROW(client.doDORA(boost::shared_ptr<IOAddress>(new IOAddress("192.0.2.100"))));
+
+ // Make sure that we received a response
+ ASSERT_TRUE(client.getContext().response_);
+
+ resetCalloutBuffers();
+
+ ASSERT_NO_THROW(client.doRelease());
+
+ // Check that the callback called is indeed the one we installed
+ EXPECT_EQ("leases4_committed", callback_name_);
+
+ // Check if all expected parameters were really received
+ vector<string> expected_argument_names;
+ expected_argument_names.push_back("query4");
+ expected_argument_names.push_back("deleted_leases4");
+ expected_argument_names.push_back("leases4");
+
+ sort(expected_argument_names.begin(), expected_argument_names.end());
+ EXPECT_TRUE(callback_argument_names_ == expected_argument_names);
+
+ // No new allocations.
+ EXPECT_FALSE(callback_lease4_);
+
+ // Released lease should be returned.
+ ASSERT_TRUE(callback_deleted_lease4_);
+ EXPECT_EQ("192.0.2.100", callback_deleted_lease4_->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 callout installed on the leases4_committed hook
-// point is executed as a result of DHCPREQUEST message sent to reuse
-// an existing lease.
+// point is executed as a result of DHCPREQUEST message sent to reuse an
+// existing lease.
TEST_F(HooksDhcpv4SrvTest, leases4CommittedCache) {
IfaceMgrTestConfig test_config(true);
IfaceMgr::instance().openSockets4();
ASSERT_NO_THROW(HooksManager::preCalloutsLibraryHandle().registerCallout(
"leases4_committed", leases4_committed_callout));
-
// Modify the subnet to reuse leases.
subnet_->setCacheThreshold(.25);
expected_argument_names.push_back("deleted_leases4");
expected_argument_names.push_back("leases4");
- sort(expected_argument_names.begin(), expected_argument_names.end());
- EXPECT_TRUE(callback_argument_names_ == expected_argument_names);
+ 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_lease4_);
+ EXPECT_EQ("192.0.2.100", callback_lease4_->addr_.toText());
+
+ // Deleted lease must not be present, because it is a new allocation.
+ EXPECT_FALSE(callback_deleted_lease4_);
+
+ // 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.
+ Dhcp4Client client2(client1.getServer(), Dhcp4Client::SELECTING);
+ client2.setIfaceName("eth1");
+ client2.setIfaceIndex(ETH1_INDEX);
+ ASSERT_NO_THROW(client2.doDORA(boost::shared_ptr<IOAddress>(new IOAddress("192.0.2.101"))));
+
+ // The DHCPOFFER should have been returned but not DHCPACK, as this
+ // packet got parked too.
+ ASSERT_FALSE(client2.getContext().response_);
+
+ // Check that the callback called is indeed the one we installed.
+ EXPECT_EQ("leases4_committed", callback_name_);
+
+ // There should be now two actions scheduled on our IO service
+ // by the invoked callouts. They unpark both DHCPACK messages.
+ ASSERT_NO_THROW(io_service_->poll());
+
+ // Receive and check the first response.
+ ASSERT_NO_THROW(client1.receiveResponse());
+ ASSERT_TRUE(client1.getContext().response_);
+ Pkt4Ptr rsp = client1.getContext().response_;
+ EXPECT_EQ(DHCPACK, rsp->getType());
+ EXPECT_EQ("192.0.2.100", rsp->getYiaddr().toText());
+
+ // Receive and check the second response.
+ ASSERT_NO_THROW(client2.receiveResponse());
+ ASSERT_TRUE(client2.getContext().response_);
+ rsp = client2.getContext().response_;
+ EXPECT_EQ(DHCPACK, rsp->getType());
+ EXPECT_EQ("192.0.2.101", rsp->getYiaddr().toText());
+
+ // Check if the callout handle state was reset after the callout.
+ checkCalloutHandleReset(client2.getContext().query_);
+}
+
+// This test verifies that incoming (positive) REQUEST/Renewing can be handled
+// properly and that callout installed on lease4_renew is triggered with
+// expected parameters.
+TEST_F(HooksDhcpv4SrvTest, lease4RenewSimple) {
+ IfaceMgrTestConfig test_config(true);
+ IfaceMgr::instance().openSockets4();
+
+ const IOAddress addr("192.0.2.106");
+ const uint32_t temp_valid = 100;
+ const time_t temp_timestamp = time(NULL) - 10;
+
+ // Install lease4_renew_callout
+ EXPECT_NO_THROW(HooksManager::preCalloutsLibraryHandle().registerCallout(
+ "lease4_renew", lease4_renew_callout));
+
+ // Generate client-id also sets client_id_ member
+ OptionPtr clientid = generateClientId();
+
+ // Check that the address we are about to use is indeed in pool
+ ASSERT_TRUE(subnet_->inPool(Lease::TYPE_V4, addr));
+
+ // let's create a lease and put it in the LeaseMgr
+ uint8_t hwaddr2_data[] = { 0, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe };
+ HWAddrPtr hwaddr2(new HWAddr(hwaddr2_data, sizeof(hwaddr2_data), HTYPE_ETHER));
+ Lease4Ptr used(new Lease4(IOAddress("192.0.2.106"), hwaddr2,
+ &client_id_->getDuid()[0], client_id_->getDuid().size(),
+ temp_valid, temp_timestamp, subnet_->getID()));
+ ASSERT_TRUE(LeaseMgrFactory::instance().addLease(used));
+
+ // Check that the lease is really in the database
+ Lease4Ptr l = LeaseMgrFactory::instance().getLease4(addr);
+ ASSERT_TRUE(l);
+
+ // Let's create a RENEW
+ Pkt4Ptr req = Pkt4Ptr(new Pkt4(DHCPREQUEST, 1234));
+ req->setRemoteAddr(IOAddress(addr));
+ req->setYiaddr(addr);
+ req->setCiaddr(addr); // client's address
+ req->setIface("eth0");
+ req->setIndex(ETH0_INDEX);
+ req->setHWAddr(hwaddr2);
+
+ req->addOption(clientid);
+ req->addOption(srv_->getServerID());
+
+ // Pass it to the server and hope for a REPLY
+ Pkt4Ptr ack = srv_->processRequest(req);
+
+ // Check if we get response at all
+ checkResponse(ack, DHCPACK, 1234);
+
+ // Check that the lease is really in the database
+ l = checkLease(ack, clientid, req->getHWAddr(), addr);
+ ASSERT_TRUE(l);
+
+ // Check that preferred, valid and cltt were really updated
+ EXPECT_EQ(l->valid_lft_, subnet_->getValid());
+
+ // Check that the callback called is indeed the one we installed
+ EXPECT_EQ("lease4_renew", callback_name_);
+
+ // Check that query4 argument passing was successful and
+ // returned proper value
+ EXPECT_TRUE(callback_qry_pkt4_.get() == req.get());
+
+ // Check that hwaddr parameter is passed properly
+ ASSERT_TRUE(callback_hwaddr_);
+ EXPECT_TRUE(*callback_hwaddr_ == *req->getHWAddr());
+
+ // Check that the subnet is passed properly
+ ASSERT_TRUE(callback_subnet4_);
+ EXPECT_EQ(callback_subnet4_->toText(), subnet_->toText());
+
+ ASSERT_TRUE(callback_clientid_);
+ ASSERT_TRUE(client_id_);
+ EXPECT_TRUE(*client_id_ == *callback_clientid_);
+
+ // Check if all expected parameters were really received
+ vector<string> expected_argument_names;
+ expected_argument_names.push_back("query4");
+ expected_argument_names.push_back("subnet4");
+ expected_argument_names.push_back("clientid");
+ expected_argument_names.push_back("hwaddr");
+ expected_argument_names.push_back("lease4");
+ 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);
+
+ Lease4Ptr lease = LeaseMgrFactory::instance().getLease4(addr);
+ EXPECT_TRUE(LeaseMgrFactory::instance().deleteLease(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 a callout installed on lease4_renew can trigger
+// the server to not renew a lease.
+TEST_F(HooksDhcpv4SrvTest, lease4RenewSkip) {
+ IfaceMgrTestConfig test_config(true);
+ IfaceMgr::instance().openSockets4();
+
+ const IOAddress addr("192.0.2.106");
+ const uint32_t temp_valid = 100;
+ const time_t temp_timestamp = time(NULL) - 10;
- // Newly allocated lease should be passed to the callout.
- ASSERT_TRUE(callback_lease4_);
- EXPECT_EQ("192.0.2.100", callback_lease4_->addr_.toText());
+ // Install lease4_renew_skip_callout
+ EXPECT_NO_THROW(HooksManager::preCalloutsLibraryHandle().registerCallout(
+ "lease4_renew", lease4_renew_skip_callout));
- // Deleted lease must not be present, because it is a new allocation.
- EXPECT_FALSE(callback_deleted_lease4_);
+ // Generate client-id also sets client_id_ member
+ OptionPtr clientid = generateClientId();
- // Pkt passed to a callout must be configured to copy retrieved options.
- EXPECT_TRUE(callback_qry_options_copy_);
+ // Check that the address we are about to use is indeed in pool
+ ASSERT_TRUE(subnet_->inPool(Lease::TYPE_V4, addr));
- // Check if the callout handle state was reset after the callout.
- checkCalloutHandleReset(client1.getContext().query_);
+ // let's create a lease and put it in the LeaseMgr
+ uint8_t hwaddr2_data[] = { 0, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe };
+ HWAddrPtr hwaddr2(new HWAddr(hwaddr2_data, sizeof(hwaddr2_data), HTYPE_ETHER));
+ Lease4Ptr used(new Lease4(IOAddress("192.0.2.106"), hwaddr2,
+ &client_id_->getDuid()[0], client_id_->getDuid().size(),
+ temp_valid, temp_timestamp, subnet_->getID()));
+ ASSERT_TRUE(LeaseMgrFactory::instance().addLease(used));
- // Reset all indicators because we'll be now creating a second client.
- resetCalloutBuffers();
+ // Check that the lease is really in the database
+ Lease4Ptr l = LeaseMgrFactory::instance().getLease4(addr);
+ ASSERT_TRUE(l);
- // Create the second client to test that it may communicate with the
- // server while the previous packet is parked.
- Dhcp4Client client2(client1.getServer(), Dhcp4Client::SELECTING);
- client2.setIfaceName("eth1");
- client2.setIfaceIndex(ETH1_INDEX);
- ASSERT_NO_THROW(client2.doDORA(boost::shared_ptr<IOAddress>(new IOAddress("192.0.2.101"))));
+ // Check that preferred, valid and cltt really set.
+ // Constructed lease looks as if it was assigned 10 seconds ago
+ EXPECT_EQ(l->valid_lft_, temp_valid);
+ EXPECT_EQ(l->cltt_, temp_timestamp);
- // The DHCPOFFER should have been returned but not DHCPACK, as this
- // packet got parked too.
- ASSERT_FALSE(client2.getContext().response_);
+ // Let's create a RENEW
+ Pkt4Ptr req = Pkt4Ptr(new Pkt4(DHCPREQUEST, 1234));
+ req->setRemoteAddr(IOAddress(addr));
+ req->setYiaddr(addr);
+ req->setCiaddr(addr); // client's address
+ req->setIface("eth0");
+ req->setIndex(ETH0_INDEX);
+ req->setHWAddr(hwaddr2);
- // Check that the callback called is indeed the one we installed.
- EXPECT_EQ("leases4_committed", callback_name_);
+ req->addOption(clientid);
+ req->addOption(srv_->getServerID());
- // There should be now two actions scheduled on our IO service
- // by the invoked callouts. They unpark both DHCPACK messages.
- ASSERT_NO_THROW(io_service_->poll());
+ // Pass it to the server and hope for a REPLY
+ Pkt4Ptr ack = srv_->processRequest(req);
+ ASSERT_TRUE(ack);
- // Receive and check the first response.
- ASSERT_NO_THROW(client1.receiveResponse());
- ASSERT_TRUE(client1.getContext().response_);
- Pkt4Ptr rsp = client1.getContext().response_;
- EXPECT_EQ(DHCPACK, rsp->getType());
- EXPECT_EQ("192.0.2.100", rsp->getYiaddr().toText());
+ // Check that the lease is really in the database
+ l = checkLease(ack, clientid, req->getHWAddr(), addr);
+ ASSERT_TRUE(l);
- // Receive and check the second response.
- ASSERT_NO_THROW(client2.receiveResponse());
- ASSERT_TRUE(client2.getContext().response_);
- rsp = client2.getContext().response_;
- EXPECT_EQ(DHCPACK, rsp->getType());
- EXPECT_EQ("192.0.2.101", rsp->getYiaddr().toText());
+ // Check that valid and cltt were NOT updated
+ EXPECT_EQ(temp_valid, l->valid_lft_);
+ EXPECT_EQ(temp_timestamp, l->cltt_);
+
+ Lease4Ptr lease = LeaseMgrFactory::instance().getLease4(addr);
+ EXPECT_TRUE(LeaseMgrFactory::instance().deleteLease(lease));
// Check if the callout handle state was reset after the callout.
- checkCalloutHandleReset(client2.getContext().query_);
+ checkCalloutHandleReset(req);
}
// This test verifies that valid RELEASE triggers lease4_release callouts
TEST_F(HooksDhcpv4SrvTest, lease4ReleaseSimple) {
IfaceMgrTestConfig test_config(true);
+ CfgMgr::instance().getCurrentCfg()->getCfgExpiration()->setFlushReclaimedTimerWaitTime(0);
+ CfgMgr::instance().getCurrentCfg()->getCfgExpiration()->setHoldReclaimedTime(0);
IfaceMgr::instance().openSockets4();
const IOAddress addr("192.0.2.106");
const uint32_t temp_valid = 100;
const time_t temp_timestamp = time(NULL) - 10;
- // Install a callout
+ // Install lease4_release_callout
EXPECT_NO_THROW(HooksManager::preCalloutsLibraryHandle().registerCallout(
"lease4_release", lease4_release_callout));
ASSERT_TRUE(subnet_->inPool(Lease::TYPE_V4, addr));
// Let's create a lease and put it in the LeaseMgr
- uint8_t mac_addr[] = { 0, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe};
+ uint8_t mac_addr[] = { 0, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe };
HWAddrPtr hw(new HWAddr(mac_addr, sizeof(mac_addr), HTYPE_ETHER));
Lease4Ptr used(new Lease4(addr, hw,
&client_id_->getDuid()[0], client_id_->getDuid().size(),
EXPECT_FALSE(l);
// Try to get the lease by hardware address
- // @todo: Uncomment this once trac2592 is implemented
- // Lease4Collection leases = LeaseMgrFactory::instance().getLease4(hw->hwaddr_);
- // EXPECT_EQ(leases.size(), 0);
+ Lease4Collection leases = LeaseMgrFactory::instance().getLease4(*hw);
+ EXPECT_EQ(leases.size(), 0);
// Try to get it by hw/subnet_id combination
- l = LeaseMgrFactory::instance().getLease4(hw->hwaddr_, subnet_->getID());
+ l = LeaseMgrFactory::instance().getLease4(*hw, subnet_->getID());
EXPECT_FALSE(l);
// Try by client-id
- // @todo: Uncomment this once trac2592 is implemented
- //Lease4Collection leases = LeaseMgrFactory::instance().getLease4(*client_id_);
- //EXPECT_EQ(leases.size(), 0);
+ leases = LeaseMgrFactory::instance().getLease4(*client_id_);
+ EXPECT_EQ(leases.size(), 0);
// Try by client-id/subnet-id
l = LeaseMgrFactory::instance().getLease4(*client_id_, subnet_->getID());
checkCalloutHandleReset(rel);
}
-// This test verifies that skip flag returned by a callout installed on the
-// lease4_release hook point will keep the lease
-TEST_F(HooksDhcpv4SrvTest, lease4ReleaseSkip) {
+// This test verifies that valid RELEASE triggers lease4_release callouts
+TEST_F(HooksDhcpv4SrvTest, lease4ReleaseSimpleNoDelete) {
IfaceMgrTestConfig test_config(true);
IfaceMgr::instance().openSockets4();
const uint32_t temp_valid = 100;
const time_t temp_timestamp = time(NULL) - 10;
- // Install a callout
+ // Install lease4_release_callout
EXPECT_NO_THROW(HooksManager::preCalloutsLibraryHandle().registerCallout(
- "lease4_release", skip_callout));
+ "lease4_release", lease4_release_callout));
// Generate client-id also duid_
OptionPtr clientid = generateClientId();
ASSERT_TRUE(subnet_->inPool(Lease::TYPE_V4, addr));
// Let's create a lease and put it in the LeaseMgr
- uint8_t mac_addr[] = { 0, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe};
+ uint8_t mac_addr[] = { 0, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe };
HWAddrPtr hw(new HWAddr(mac_addr, sizeof(mac_addr), HTYPE_ETHER));
Lease4Ptr used(new Lease4(addr, hw,
&client_id_->getDuid()[0], client_id_->getDuid().size(),
// Generate client-id also duid_
Pkt4Ptr rel = Pkt4Ptr(new Pkt4(DHCPRELEASE, 1234));
rel->setRemoteAddr(addr);
- rel->setYiaddr(addr);
+ rel->setCiaddr(addr);
rel->addOption(clientid);
rel->addOption(srv_->getServerID());
rel->setHWAddr(hw);
// Note: this is no response to RELEASE in DHCPv4
EXPECT_NO_THROW(srv_->processRelease(rel));
- // The lease should be still there
+ // The lease should not be gone from LeaseMgr
l = LeaseMgrFactory::instance().getLease4(addr);
EXPECT_TRUE(l);
- // Try by client-id/subnet-id
- l = LeaseMgrFactory::instance().getLease4(*client_id_, subnet_->getID());
- EXPECT_TRUE(l);
-
- // Try to get the lease by hardware address, should succeed
+ // Try to get the lease by hardware address
Lease4Collection leases = LeaseMgrFactory::instance().getLease4(*hw);
EXPECT_EQ(leases.size(), 1);
- // Try by client-id, should be successful as well.
+ // Try to get it by hw/subnet_id combination
+ l = LeaseMgrFactory::instance().getLease4(*hw, subnet_->getID());
+ EXPECT_TRUE(l);
+
+ // Try by client-id
leases = LeaseMgrFactory::instance().getLease4(*client_id_);
EXPECT_EQ(leases.size(), 1);
+ // Try by client-id/subnet-id
+ l = LeaseMgrFactory::instance().getLease4(*client_id_, subnet_->getID());
+ EXPECT_TRUE(l);
+
+ // Ok, the lease is *really* there.
+
+ // Check that the callback called is indeed the one we installed
+ EXPECT_EQ("lease4_release", callback_name_);
+
+ // Check that pkt4 argument passing was successful and returned proper value
+ EXPECT_TRUE(callback_qry_pkt4_.get() == rel.get());
+
+ // Check if all expected parameters were really received
+ vector<string> expected_argument_names;
+ expected_argument_names.push_back("query4");
+ expected_argument_names.push_back("lease4");
+ 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);
+
+ // 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(rel);
}
-// This test verifies that the leases4_committed callout is executed
-// with deleted leases as argument when DHCPRELEASE is processed.
-TEST_F(HooksDhcpv4SrvTest, leases4CommittedRelease) {
+// This test verifies that skip flag returned by a callout installed on the
+// lease4_release hook point will keep the lease.
+TEST_F(HooksDhcpv4SrvTest, lease4ReleaseSkip) {
IfaceMgrTestConfig test_config(true);
IfaceMgr::instance().openSockets4();
- ASSERT_NO_THROW(HooksManager::preCalloutsLibraryHandle().registerCallout(
- "leases4_committed", leases4_committed_callout));
+ const IOAddress addr("192.0.2.106");
+ const uint32_t temp_valid = 100;
+ const time_t temp_timestamp = time(NULL) - 10;
+ // Install lease4_release_skip
+ EXPECT_NO_THROW(HooksManager::preCalloutsLibraryHandle().registerCallout(
+ "lease4_release", lease4_release_skip));
- Dhcp4Client client(Dhcp4Client::SELECTING);
- client.setIfaceName("eth1");
- client.setIfaceIndex(ETH1_INDEX);
- ASSERT_NO_THROW(client.doDORA(boost::shared_ptr<IOAddress>(new IOAddress("192.0.2.100"))));
+ // Generate client-id also duid_
+ OptionPtr clientid = generateClientId();
- // Make sure that we received a response
- ASSERT_TRUE(client.getContext().response_);
+ // Check that the address we are about to use is indeed in pool
+ ASSERT_TRUE(subnet_->inPool(Lease::TYPE_V4, addr));
- resetCalloutBuffers();
+ // Let's create a lease and put it in the LeaseMgr
+ uint8_t mac_addr[] = { 0, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe };
+ HWAddrPtr hw(new HWAddr(mac_addr, sizeof(mac_addr), HTYPE_ETHER));
+ Lease4Ptr used(new Lease4(addr, hw,
+ &client_id_->getDuid()[0], client_id_->getDuid().size(),
+ temp_valid, temp_timestamp, subnet_->getID()));
+ ASSERT_TRUE(LeaseMgrFactory::instance().addLease(used));
- ASSERT_NO_THROW(client.doRelease());
+ // Check that the lease is really in the database
+ Lease4Ptr l = LeaseMgrFactory::instance().getLease4(addr);
+ ASSERT_TRUE(l);
- // Check that the callback called is indeed the one we installed
- EXPECT_EQ("leases4_committed", callback_name_);
+ // Let's create a RELEASE
+ // Generate client-id also duid_
+ Pkt4Ptr rel = Pkt4Ptr(new Pkt4(DHCPRELEASE, 1234));
+ rel->setRemoteAddr(addr);
+ rel->setYiaddr(addr);
+ rel->addOption(clientid);
+ rel->addOption(srv_->getServerID());
+ rel->setHWAddr(hw);
- // Check if all expected parameters were really received
- vector<string> expected_argument_names;
- expected_argument_names.push_back("query4");
- expected_argument_names.push_back("deleted_leases4");
- expected_argument_names.push_back("leases4");
+ // Pass it to the server and hope for a REPLY
+ // Note: this is no response to RELEASE in DHCPv4
+ EXPECT_NO_THROW(srv_->processRelease(rel));
- sort(expected_argument_names.begin(), expected_argument_names.end());
- EXPECT_TRUE(callback_argument_names_ == expected_argument_names);
+ // The lease should be still there
+ l = LeaseMgrFactory::instance().getLease4(addr);
+ EXPECT_TRUE(l);
- // No new allocations.
- EXPECT_FALSE(callback_lease4_);
+ // Try by client-id/subnet-id
+ l = LeaseMgrFactory::instance().getLease4(*client_id_, subnet_->getID());
+ EXPECT_TRUE(l);
- // Released lease should be returned.
- ASSERT_TRUE(callback_deleted_lease4_);
- EXPECT_EQ("192.0.2.100", callback_deleted_lease4_->addr_.toText());
+ // Try to get the lease by hardware address, should succeed
+ Lease4Collection leases = LeaseMgrFactory::instance().getLease4(*hw);
+ EXPECT_EQ(leases.size(), 1);
- // Pkt passed to a callout must be configured to copy retrieved options.
- EXPECT_TRUE(callback_qry_options_copy_);
+ // Try by client-id, should be successful as well.
+ leases = LeaseMgrFactory::instance().getLease4(*client_id_);
+ EXPECT_EQ(leases.size(), 1);
// Check if the callout handle state was reset after the callout.
- checkCalloutHandleReset(client.getContext().query_);
+ checkCalloutHandleReset(rel);
}
// This test verifies that drop flag returned by a callout installed on the
-// lease4_release hook point will keep the lease
+// lease4_release hook point will keep the lease.
TEST_F(HooksDhcpv4SrvTest, lease4ReleaseDrop) {
IfaceMgrTestConfig test_config(true);
IfaceMgr::instance().openSockets4();
const uint32_t temp_valid = 100;
const time_t temp_timestamp = time(NULL) - 10;
- // Install a callout
+ // Install lease4_release_drop
EXPECT_NO_THROW(HooksManager::preCalloutsLibraryHandle().registerCallout(
- "lease4_release", drop_callout));
+ "lease4_release", lease4_release_drop));
// Generate client-id also duid_
OptionPtr clientid = generateClientId();
ASSERT_TRUE(subnet_->inPool(Lease::TYPE_V4, addr));
// Let's create a lease and put it in the LeaseMgr
- uint8_t mac_addr[] = { 0, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe};
+ uint8_t mac_addr[] = { 0, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe };
HWAddrPtr hw(new HWAddr(mac_addr, sizeof(mac_addr), HTYPE_ETHER));
Lease4Ptr used(new Lease4(addr, hw,
&client_id_->getDuid()[0], client_id_->getDuid().size(),
checkCalloutHandleReset(rel);
}
-// Checks that decline4 hooks (lease4_decline) are triggered properly.
-TEST_F(HooksDhcpv4SrvTest, HooksDecline) {
+// This test checks that the basic decline hook (lease4_decline) is
+// triggered properly.
+TEST_F(HooksDhcpv4SrvTest, lease4DeclineSimple) {
IfaceMgrTestConfig test_config(true);
IfaceMgr::instance().openSockets4();
- // Install a callout
+ // Install lease4_decline callout
EXPECT_NO_THROW(HooksManager::preCalloutsLibraryHandle().registerCallout(
"lease4_decline", lease4_decline_callout));
checkCalloutHandleReset(client.getContext().query_);
}
-// Checks that decline4 hook is able to skip the packet.
-TEST_F(HooksDhcpv4SrvTest, HooksDeclineSkip) {
+// Test that the lease4_decline hook point can handle SKIP status.
+TEST_F(HooksDhcpv4SrvTest, lease4DeclineSkip) {
IfaceMgrTestConfig test_config(true);
IfaceMgr::instance().openSockets4();
- // Install a callout
+ // Install lease4_decline_skip callout. It will set the status to skip
EXPECT_NO_THROW(HooksManager::preCalloutsLibraryHandle().registerCallout(
- "lease4_decline", lease4_decline_skip_callout));
+ "lease4_decline", lease4_decline_skip));
HooksManager::setTestMode(true);
checkCalloutHandleReset(client.getContext().query_);
}
-// Checks that decline4 hook is able to drop the packet.
-TEST_F(HooksDhcpv4SrvTest, HooksDeclineDrop) {
+// Test that the lease4_decline hook point can handle DROP status.
+TEST_F(HooksDhcpv4SrvTest, lease4DeclineDrop) {
IfaceMgrTestConfig test_config(true);
IfaceMgr::instance().openSockets4();
- // Install a callout
+ // Install lease4_decline_drop callout. It will set the status to drop
EXPECT_NO_THROW(HooksManager::preCalloutsLibraryHandle().registerCallout(
- "lease4_decline", lease4_decline_drop_callout));
+ "lease4_decline", lease4_decline_drop));
HooksManager::setTestMode(true);
checkCalloutHandleReset(client.getContext().query_);
}
-// This test verifies that the leases4_committed callout is executed
-// with declined leases as argument when DHCPDECLINE is processed.
-TEST_F(HooksDhcpv4SrvTest, leases4CommittedDecline) {
- IfaceMgrTestConfig test_config(true);
- IfaceMgr::instance().openSockets4();
-
- ASSERT_NO_THROW(HooksManager::preCalloutsLibraryHandle().registerCallout(
- "leases4_committed", leases4_committed_callout));
-
-
- Dhcp4Client client(Dhcp4Client::SELECTING);
- client.useRelay();
- ASSERT_NO_THROW(client.doDORA(boost::shared_ptr<IOAddress>(new IOAddress("192.0.2.100"))));
-
- // Make sure that we received a response
- ASSERT_TRUE(client.getContext().response_);
-
- resetCalloutBuffers();
-
- ASSERT_NO_THROW(client.doDecline());
-
- // Check that the callback called is indeed the one we installed
- EXPECT_EQ("leases4_committed", callback_name_);
-
- // Check if all expected parameters were really received
- vector<string> expected_argument_names;
- expected_argument_names.push_back("query4");
- expected_argument_names.push_back("deleted_leases4");
- expected_argument_names.push_back("leases4");
-
- sort(expected_argument_names.begin(), expected_argument_names.end());
- EXPECT_TRUE(callback_argument_names_ == expected_argument_names);
-
- // No new allocations.
- ASSERT_TRUE(callback_lease4_);
- EXPECT_EQ("192.0.2.100", callback_lease4_->addr_.toText());
- EXPECT_EQ(Lease::STATE_DECLINED, callback_lease4_->state_);
-
- // Released lease should be returned.
- EXPECT_FALSE(callback_deleted_lease4_);
-
- // 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_);
-}
-
// Checks if callout installed on host4_identifier can generate an
// identifier and whether that identifier is actually used.
-TEST_F(HooksDhcpv4SrvTest, host4_identifier) {
+TEST_F(HooksDhcpv4SrvTest, host4Identifier) {
IfaceMgrTestConfig test_config(true);
IfaceMgr::instance().openSockets4();
"host4_identifier", host4_identifier_foo_callout));
// Let's create a simple DISCOVER
- Pkt4Ptr sol = generateSimpleDiscover();
+ Pkt4Ptr discover = generateSimpleDiscover();
// Simulate that we have received that traffic
- srv_->fakeReceive(sol);
+ srv_->fakeReceive(discover);
// Server will now process to run its normal loop, but instead of calling
// IfaceMgr::receive4(), it will read all packets from the list set by
EXPECT_EQ("192.0.2.201", adv->getYiaddr().toText());
// Check if the callout handle state was reset after the callout.
- checkCalloutHandleReset(sol);
+ checkCalloutHandleReset(discover);
}
-// Checks if callout installed on host4_identifier can generate identifier of
+// Checks if callout installed on host4_identifier can generate an identifier of
// other type. This particular callout always returns hwaddr.
-TEST_F(HooksDhcpv4SrvTest, host4_identifier_hwaddr) {
+TEST_F(HooksDhcpv4SrvTest, host4IdentifierHWAddr) {
IfaceMgrTestConfig test_config(true);
IfaceMgr::instance().openSockets4();
"host4_identifier", host4_identifier_hwaddr_callout));
// Let's create a simple DISCOVER
- Pkt4Ptr sol = generateSimpleDiscover();
+ Pkt4Ptr discover = generateSimpleDiscover();
// Simulate that we have received that traffic
- srv_->fakeReceive(sol);
+ srv_->fakeReceive(discover);
// Server will now process to run its normal loop, but instead of calling
// IfaceMgr::receive4(), it will read all packets from the list set by
EXPECT_EQ("192.0.2.201", adv->getYiaddr().toText());
// Check if the callout handle state was reset after the callout.
- checkCalloutHandleReset(sol);
+ checkCalloutHandleReset(discover);
}
-
// 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
}
// This test verifies that parked-packet-limit is properly enforced.
-TEST_F(HooksDhcpv4SrvTest, parkedPacketLimit) {
+TEST_F(HooksDhcpv4SrvTest, leases4ParkedPacketLimit) {
IfaceMgrTestConfig test_config(true);
// Configure 1 directly reachable subnet, parked-packet-limit of 1.
EXPECT_EQ(1, getStatistic("pkt4-receive-drop"));
}
+} // namespace
#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>
#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
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()
.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
public:
/// @brief creates Dhcpv6Srv and prepares buffers for callouts
- HooksDhcpv6SrvTest()
- : Dhcpv6SrvTest() {
-
+ HooksDhcpv6SrvTest() : Dhcpv6SrvTest() {
HooksManager::setTestMode(false);
bool status = HooksManager::unloadLibraries();
if (!status) {
// 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");
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
///
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_);
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_);
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
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();
}
callout_handle.setStatus(CalloutHandle::NEXT_STEP_SKIP);
- // carry on as usual
+ // Carry on as usual
return buffer6_send_callout(callout_handle);
}
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
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
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
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
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
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
return (0);
}
-
/// Resets buffers used to store data received by callouts
void resetCalloutBuffers() {
callback_name_ = string("");
/// 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
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_;
/// @brief Pointer to the tested server object
boost::shared_ptr<NakedDhcpv6Srv> server_;
- LoadUnloadDhcpv6SrvTest()
- : Dhcpv6SrvTest() {
+ LoadUnloadDhcpv6SrvTest() : Dhcpv6SrvTest() {
reset();
MultiThreadingMgr::instance().setMode(false);
}
}
};
-
// 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(
// 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(
// 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(
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(
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(
//
// 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(
// 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(
// 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(
// 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(
// 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(
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(
// 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
// 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(
// 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(
// 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(
// 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
// 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(
// 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(
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
// 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);
// 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)
comment_ = isc::config::parseAnswer(rcode_, status);
ASSERT_EQ(0, rcode_);
+ // Commit the config
CfgMgr::instance().commit();
// Install subnet6_select_callout
// 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());
}
// 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\": {"
"\"subnet6\": [ { "
" \"pools\": [ { \"pool\": \"2001:db8:1::/64\" } ],"
" \"subnet\": \"2001:db8:1::/48\", "
- " \"interface\": \"eth1\", "
- " \"cache-threshold\": .25 "
+ " \"interface\": \"eth1\" "
" } ],"
"\"valid-lifetime\": 4000 }";
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_);
// 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_);
// 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_);
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_);
// 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());
// Check if the callout handle state was reset after the callout.
checkCalloutHandleReset(client.getContext().query_);
+
+ resetCalloutBuffers();
+
+ // Renew 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());
+
+ // Make sure that we received a response
+ ASSERT_TRUE(client.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_);
+
+ 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(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) {
+// 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\": {"
"\"rebind-timer\": 2000, "
"\"renew-timer\": 1000, "
"\"subnet6\": [ { "
- " \"pools\": [ { \"pool\": \"2001:db8:1::/64\" } ],"
+ " \"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.requestAddress(0xabca, 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_);
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);
ASSERT_TRUE(lease);
- EXPECT_EQ("2001:db8:1::28", lease->addr_.toText());
+ 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_);
+
+ resetCalloutBuffers();
+
+ // 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_);
+
+ // Check that the callback called is indeed the one we installed
+ EXPECT_EQ("leases6_committed", callback_name_);
+
+ // 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_);
// Deleted lease must not be present, because it is a new allocation.
ASSERT_TRUE(callback_deleted_leases6_);
EXPECT_TRUE(callback_qry_options_copy_);
// Check if the callout handle state was reset after the callout.
- checkCalloutHandleReset(client1.getContext().query_);
+ checkCalloutHandleReset(client.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());
+ // 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::"));
- // The ADVERTISE should have been returned but not REPLAY, as this
- // packet got parked too.
- ASSERT_FALSE(client2.getContext().response_);
+ ASSERT_NO_THROW(client.doRenew());
- // Check that the callback called is indeed the one we installed.
+ // 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_);
- // 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());
+ // 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_);
- // 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")));
+ // The old lease is kept.
+ ASSERT_TRUE(callback_deleted_leases6_);
+ ASSERT_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.hasLeaseForAddress(IOAddress("2001:db8:1::29")));
+ // 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_);
+ checkCalloutHandleReset(client.getContext().query_);
+
+ resetCalloutBuffers();
+
+ // The renewed prefix is just a hint.
+ client.requestPrefix(0x5577, 64, IOAddress("4000::1"));
+
+ ASSERT_NO_THROW(client.doRenew());
+
+ // 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_);
+
+ 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());
+
+ // 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 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());
+
+ // Make sure that we received a response
+ ASSERT_TRUE(client.getContext().response_);
+
+ // Check the error.
+ EXPECT_EQ(STATUS_NoAddrsAvail, client.getStatusCode(0x1122));
+
+ // Check that the callback called is indeed the one we installed
+ EXPECT_EQ("leases6_committed", 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 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. 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 REBIND message sent to allocate new
+// lease or renew an existing lease.
+TEST_F(HooksDhcpv6SrvTest, leases6CommittedRebind) {
IfaceMgrTestConfig test_config(true);
string config = "{ \"interfaces-config\": {"
"\"rebind-timer\": 2000, "
"\"renew-timer\": 1000, "
"\"subnet6\": [ { "
- " \"pd-pools\": [ {"
- " \"prefix\": \"2001:db8:1::\", "
- " \"prefix-len\": 56, "
- " \"delegated-len\": 64 } ], "
+ " \"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.requestPrefix(0xabca, 64, IOAddress("2001:db8:1:28::"));
+ Dhcp6Client client;
+ client.setInterface("eth1");
+ client.requestAddress(0xabca, 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_);
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);
ASSERT_TRUE(lease);
- EXPECT_EQ("2001:db8:1:28::", lease->addr_.toText());
- EXPECT_EQ(64, lease->prefixlen_);
+ 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_qry_options_copy_);
// Check if the callout handle state was reset after the callout.
- checkCalloutHandleReset(client1.getContext().query_);
+ checkCalloutHandleReset(client.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());
+ // Rebind the lease and make sure that the callout has been executed.
+ ASSERT_NO_THROW(client.doRebind());
- // 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());
+ // 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());
- // 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_);
-}
+ checkCalloutHandleReset(client.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);
+ resetCalloutBuffers();
- // Install lease6_renew_callout
- EXPECT_NO_THROW(HooksManager::preCalloutsLibraryHandle().registerCallout(
- "lease6_renew", lease6_renew_callout));
+ // 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"));
- const IOAddress addr("2001:db8:1:1::cafe:babe");
- const uint32_t iaid = 234;
+ ASSERT_NO_THROW(client.doRebind());
- // Generate client-id also duid_
- OptionPtr clientid = generateClientId();
+ // Make sure that we received a response
+ ASSERT_TRUE(client.getContext().response_);
- // Check that the address we are about to use is indeed in pool
- ASSERT_TRUE(subnet_->inPool(Lease::TYPE_NA, addr));
+ // Check that the callback called is indeed the one we installed
+ EXPECT_EQ("leases6_committed", callback_name_);
- // 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));
+ // 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 the lease is really in the database
- Lease6Ptr l = LeaseMgrFactory::instance().getLease6(Lease::TYPE_NA,
- addr);
- ASSERT_TRUE(l);
+ // The old lease is kept.
+ ASSERT_TRUE(callback_deleted_leases6_);
+ ASSERT_TRUE(callback_deleted_leases6_->empty());
- // 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));
+ // Pkt passed to a callout must be configured to copy retrieved options.
+ EXPECT_TRUE(callback_qry_options_copy_);
- // 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);
+ // Check if the callout handle state was reset after the callout.
+ checkCalloutHandleReset(client.getContext().query_);
- 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());
+ resetCalloutBuffers();
- // Pass it to the server and hope for a REPLY
- Pkt6Ptr reply = srv.processRenew(req);
- ASSERT_TRUE(reply);
+ // The rebound address is just a hint.
+ client.requestAddress(0x5577, IOAddress("4000::2"));
+
+ ASSERT_NO_THROW(client.doRebind());
+
+ // 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_);
+ EXPECT_EQ("leases6_committed", 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_);
+ 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());
+
+ // 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();
+
+ // 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.doRebind());
+
+ // Make sure that we received a response
+ ASSERT_TRUE(client.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_);
+
+ 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(client.getContext().query_);
+}
+
+// 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);
+
+ 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 }";
+
+ 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("lease6");
- expected_argument_names.push_back("ia_na");
+ expected_argument_names.push_back("deleted_leases6");
+ expected_argument_names.push_back("leases6");
- 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);
+ // 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_);
- OptionPtr tmp = reply->getOption(D6O_IA_NA);
- ASSERT_TRUE(tmp);
+ // Deleted lease must not be present, because it is a new allocation.
+ ASSERT_TRUE(callback_deleted_leases6_);
+ EXPECT_TRUE(callback_deleted_leases6_->empty());
- // 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()));
+ // Pkt passed to a callout must be configured to copy retrieved options.
+ EXPECT_TRUE(callback_qry_options_copy_);
- 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 if the callout handle state was reset after the callout.
+ checkCalloutHandleReset(client.getContext().query_);
- // Check that the lease has been returned
- ASSERT_TRUE(callback_lease6_);
+ resetCalloutBuffers();
- // Check that the returned lease6 in callout is the same as the one in the
- // database
- EXPECT_TRUE(*callback_lease6_ == *l);
+ // 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_);
+
+ // Check that the callback called is indeed the one we installed
+ EXPECT_EQ("leases6_committed", callback_name_);
+
+ // 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_);
+
+ // 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(req);
-}
+ checkCalloutHandleReset(client.getContext().query_);
-// 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);
+ resetCalloutBuffers();
- // Install lease6_renew_update
- EXPECT_NO_THROW(HooksManager::preCalloutsLibraryHandle().registerCallout(
- "lease6_renew", lease6_renew_update));
+ // 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::"));
- const IOAddress addr("2001:db8:1:1::cafe:babe");
- const uint32_t iaid = 234;
+ ASSERT_NO_THROW(client.doRebind());
- // Generate client-id also duid_
- OptionPtr clientid = generateClientId();
+ // Make sure that we received a response
+ ASSERT_TRUE(client.getContext().response_);
- // Check that the address we are about to use is indeed in pool
- ASSERT_TRUE(subnet_->inPool(Lease::TYPE_NA, addr));
+ // Check that the callback called is indeed the one we installed
+ EXPECT_EQ("leases6_committed", callback_name_);
- // 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));
+ // 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 lease is really in the database
- Lease6Ptr l = LeaseMgrFactory::instance().getLease6(Lease::TYPE_NA,
- addr);
- ASSERT_TRUE(l);
+ // The old lease is kept.
+ ASSERT_TRUE(callback_deleted_leases6_);
+ ASSERT_TRUE(callback_deleted_leases6_->empty());
- // 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));
+ // Pkt passed to a callout must be configured to copy retrieved options.
+ EXPECT_TRUE(callback_qry_options_copy_);
- // 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);
+ // Check if the callout handle state was reset after the callout.
+ checkCalloutHandleReset(client.getContext().query_);
- OptionPtr renewed_addr_opt(new Option6IAAddr(D6O_IAADDR, addr, 300, 500));
- ia->addOption(renewed_addr_opt);
- req->addOption(ia);
- req->addOption(clientid);
+ resetCalloutBuffers();
- // Server-id is mandatory in RENEW
- req->addOption(srv.getServerID());
+ // The rebound prefix is just a hint.
+ client.requestPrefix(0x5577, 64, IOAddress("4000::1"));
- // 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);
+ ASSERT_NO_THROW(client.doRebind());
- // 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 if we get response at all
- checkResponse(reply, DHCPV6_REPLY, 1234);
+ // Check that the callback called is indeed the one we installed
+ EXPECT_EQ("leases6_committed", callback_name_);
- OptionPtr tmp = reply->getOption(D6O_IA_NA);
- ASSERT_TRUE(tmp);
+ 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 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));
+ // Pkt passed to a callout must be configured to copy retrieved options.
+ EXPECT_TRUE(callback_qry_options_copy_);
- 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 if the callout handle state was reset after the callout.
+ checkCalloutHandleReset(client.getContext().query_);
- // Check that we chose the distinct override values
- ASSERT_NE(override_preferred_, subnet_->getPreferred());
- EXPECT_NE(override_valid_, subnet_->getValid());
+ resetCalloutBuffers();
- // Check that preferred, valid were overridden the callout
- EXPECT_EQ(override_preferred_, l->preferred_lft_);
- EXPECT_EQ(override_valid_, l->valid_lft_);
+ // Rebind an address: this should lead to an error as no address pool
+ // is configured.
+ client.requestAddress(0x1122, IOAddress("2001:db8:1::28"));
- // 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_NO_THROW(client.doRebind());
+
+ // Make sure that we received a response
+ ASSERT_TRUE(client.getContext().response_);
+
+ // Check the error.
+ EXPECT_EQ(STATUS_NoAddrsAvail, client.getStatusCode(0x1122));
+
+ // Check that the callback called is indeed the one we installed
+ EXPECT_EQ("leases6_committed", 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 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. 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(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(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());
- 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);
+ checkCalloutHandleReset(client.getContext().query_);
}
-// 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;
+// 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);
- // Generate client-id also duid_
- OptionPtr clientid = generateClientId();
+ 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 address we are about to use is indeed in pool
- ASSERT_TRUE(subnet_->inPool(Lease::TYPE_NA, addr));
+ Dhcp6Client client;
+ client.setInterface("eth1");
+ client.requestAddress(0xabca, IOAddress("2001:db8:1::28"));
+ client.requestAddress(0x2233, IOAddress("2001:db8:1::29"));
- // 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));
+ ASSERT_NO_THROW(configure(config, *client.getServer()));
- // Check that the lease is really in the database
- Lease6Ptr l = LeaseMgrFactory::instance().getLease6(Lease::TYPE_NA,
- addr);
- ASSERT_TRUE(l);
+ ASSERT_NO_THROW(client.doSARR());
+ // Make sure that we received a response
+ ASSERT_TRUE(client.getContext().response_);
- // 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));
+ ASSERT_NO_THROW(HooksManager::preCalloutsLibraryHandle().registerCallout(
+ "leases6_committed", leases6_committed_callout));
- // 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);
+ ASSERT_NO_THROW(client.doDecline());
- OptionPtr renewed_addr_opt(new Option6IAAddr(D6O_IAADDR, addr, 300, 500));
- ia->addOption(renewed_addr_opt);
- req->addOption(ia);
- req->addOption(clientid);
+ // Check that the callback called is indeed the one we installed
+ EXPECT_EQ("leases6_committed", callback_name_);
- // Server-id is mandatory in RENEW
- req->addOption(srv.getServerID());
+ // 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");
- // Pass it to the server and hope for a REPLY
- Pkt6Ptr reply = srv.processRenew(req);
- ASSERT_TRUE(reply);
+ sort(expected_argument_names.begin(), expected_argument_names.end());
+ EXPECT_TRUE(callback_argument_names_ == expected_argument_names);
- // Check that our callback was called
- EXPECT_EQ("lease6_renew", callback_name_);
+ // No deleted leases.
+ ASSERT_TRUE(callback_deleted_leases6_);
+ ASSERT_TRUE(callback_deleted_leases6_->empty());
- l = LeaseMgrFactory::instance().getLease6(Lease::TYPE_NA, addr);
+ // 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());
- // 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));
+ // 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 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.
-TEST_F(HooksDhcpv6SrvTest, leases6CommittedRenew) {
+// This test verifies that the leases6_committed callout is executed
+// with deleted leases as argument when RELEASE is processed.
+TEST_F(HooksDhcpv6SrvTest, leases6CommittedRelease) {
IfaceMgrTestConfig test_config(true);
string config = "{ \"interfaces-config\": {"
// Make sure that we received a response
ASSERT_TRUE(client.getContext().response_);
+ ASSERT_NO_THROW(client.doRelease());
+
// Check that the callback called is indeed the one we installed
EXPECT_EQ("leases6_committed", callback_name_);
sort(expected_argument_names.begin(), expected_argument_names.end());
EXPECT_TRUE(callback_argument_names_ == expected_argument_names);
- // Newly allocated lease should be returned.
+ // No new allocations.
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());
+ ASSERT_TRUE(callback_new_leases6_->empty());
- // Deleted lease must not be present, because it is a new allocation.
+ // Released lease should be returned.
ASSERT_TRUE(callback_deleted_leases6_);
- EXPECT_TRUE(callback_deleted_leases6_->empty());
+ EXPECT_EQ(1, callback_deleted_leases6_->size());
+ Lease6Ptr lease = callback_deleted_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_);
+}
- resetCalloutBuffers();
+// This test verifies that the leases6_committed callout is executed
+// with deleted leases as argument when RELEASE is processed. Prefix variant.
+TEST_F(HooksDhcpv6SrvTest, leases6CommittedReleasePrefix) {
+ IfaceMgrTestConfig test_config(true);
- // Renew the lease and make sure that the callout has been executed.
- ASSERT_NO_THROW(client.doRenew());
+ 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 }";
+
+ Dhcp6Client client;
+ client.setInterface("eth1");
+ client.requestPrefix(0xabca, 64, 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.doRelease());
+
// Check that the callback called is indeed the one we installed
EXPECT_EQ("leases6_committed", callback_name_);
- // Renewed lease should be returned.
+ // 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 new allocations.
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());
+ ASSERT_TRUE(callback_new_leases6_->empty());
- // Deleted lease must not be present, because it is a new allocation.
+ // Released lease should be returned.
ASSERT_TRUE(callback_deleted_leases6_);
- EXPECT_TRUE(callback_deleted_leases6_->empty());
+ EXPECT_EQ(1, callback_deleted_leases6_->size());
+ Lease6Ptr lease = callback_deleted_leases6_->at(0);
+ ASSERT_TRUE(lease);
+ EXPECT_EQ("2001:db8:1:28::", lease->addr_.toText());
+ EXPECT_EQ(64, lease->prefixlen_);
// Pkt passed to a callout must be configured to copy retrieved options.
EXPECT_TRUE(callback_qry_options_copy_);
- resetCalloutBuffers();
+ // Check if the callout handle state was reset after the callout.
+ checkCalloutHandleReset(client.getContext().query_);
+}
- // Let's try to renew again but force the client to renew a different
- // address with a different IAID.
+// This test verifies that the leases6_committed callout is executed
+// with deleted leases as argument when RELEASE is processed.
+// Variant with two addresses and two prefixes.
+TEST_F(HooksDhcpv6SrvTest, leases6CommittedReleaseMultiple) {
+ 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\" } ],"
+ " \"pd-pools\": [ {"
+ " \"prefix\": \"2001:db8:2::\", "
+ " \"prefix-len\": 56, "
+ " \"delegated-len\": 64 } ], "
+ " \"subnet\": \"2001:db8::/32\", "
+ " \"interface\": \"eth1\" "
+ " } ],"
+ "\"valid-lifetime\": 4000 }";
+
+ Dhcp6Client client;
+ client.setInterface("eth1");
+ // In theory we can reuse the IAID but copyIAsFromLeases() copies
+ // only one lease...
+ client.requestAddress(0xabca, IOAddress("2001:db8:1::28"));
+ client.requestPrefix(0xabcb, 64, IOAddress("2001:db8:2:28::"));
client.requestAddress(0x2233, IOAddress("2001:db8:1::29"));
+ client.requestPrefix(0x2234, 64, IOAddress("2001:db8:2:29::"));
- ASSERT_NO_THROW(client.doRenew());
+ 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.doRelease());
+
// Check that the callback called is indeed the one we installed
EXPECT_EQ("leases6_committed", callback_name_);
- // New lease should be returned.
+ // 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 new allocations.
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());
+ ASSERT_TRUE(callback_new_leases6_->empty());
- // The old lease is kept.
+ // Released lease should be returned.
ASSERT_TRUE(callback_deleted_leases6_);
- ASSERT_TRUE(callback_deleted_leases6_->empty());
+ EXPECT_EQ(4, callback_deleted_leases6_->size());
// 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();
+// 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);
- // The renewed address is just a hint.
- client.requestAddress(0x5577, IOAddress("4000::2"));
+ 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 }";
- ASSERT_NO_THROW(client.doRenew());
+ 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_);
- EXPECT_EQ(3, callback_new_leases6_->size());
- lease = callback_new_leases6_->at(2);
+ ASSERT_EQ(1, callback_new_leases6_->size());
+ Lease6Ptr lease = callback_new_leases6_->at(0);
ASSERT_TRUE(lease);
- EXPECT_EQ("2001:db8:1::", lease->addr_.toText());
+ 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());
resetCalloutBuffers();
- // Renew 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());
+ // 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 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_);
+ // Requested lease should not be present, because it is reused.
ASSERT_TRUE(callback_new_leases6_);
- EXPECT_EQ(3, callback_new_leases6_->size());
+ 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 RENEW message sent to allocate new
-// lease or renew an existing lease. Prefix variant.
-TEST_F(HooksDhcpv6SrvTest, leases6CommittedRenewPrefix) {
+// 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\": {"
" \"prefix-len\": 56, "
" \"delegated-len\": 64 } ], "
" \"subnet\": \"2001:db8:1::/48\", "
- " \"interface\": \"eth1\" "
+ " \"interface\": \"eth1\", "
+ " \"cache-threshold\": .25 "
" } ],"
"\"valid-lifetime\": 4000 }";
// 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());
+ // 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_);
- // Renewed lease should be returned.
+ // Requested lease should not be present, because it is reused.
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_);
+ EXPECT_TRUE(callback_new_leases6_->empty());
- // Deleted lease must not be present, because it is a new allocation.
+ // Deleted lease must not be present, because it is renewed.
ASSERT_TRUE(callback_deleted_leases6_);
EXPECT_TRUE(callback_deleted_leases6_->empty());
// Check if the callout handle state was reset after the callout.
checkCalloutHandleReset(client.getContext().query_);
+}
- resetCalloutBuffers();
+// 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);
- // 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::"));
+ 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 }";
- ASSERT_NO_THROW(client.doRenew());
+ // Create first client and perform SARR.
+ Dhcp6Client client1;
+ client1.setInterface("eth1");
+ client1.requestAddress(0xabca, IOAddress("2001:db8:1::28"));
- // Make sure that we received a response
- ASSERT_TRUE(client.getContext().response_);
+ 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_);
- // New lease should be returned.
+ // 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(2, callback_new_leases6_->size());
- lease = callback_new_leases6_->at(1);
+ ASSERT_EQ(1, callback_new_leases6_->size());
+ Lease6Ptr lease = callback_new_leases6_->at(0);
ASSERT_TRUE(lease);
- EXPECT_EQ("2001:db8:1:29::", lease->addr_.toText());
- EXPECT_EQ(64, lease->prefixlen_);
+ EXPECT_EQ("2001:db8:1::28", lease->addr_.toText());
- // The old lease is kept.
+ // Deleted lease must not be present, because it is a new allocation.
ASSERT_TRUE(callback_deleted_leases6_);
- ASSERT_TRUE(callback_deleted_leases6_->empty());
+ 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_);
+ checkCalloutHandleReset(client1.getContext().query_);
+ // Reset all indicators because we'll be now creating a second client.
resetCalloutBuffers();
- // The renewed prefix is just a hint.
- client.requestPrefix(0x5577, 64, IOAddress("4000::1"));
+ // 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());
- 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.
+ 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_);
- EXPECT_EQ(3, callback_new_leases6_->size());
- lease = callback_new_leases6_->at(2);
+ ASSERT_EQ(1, callback_new_leases6_->size());
+ Lease6Ptr lease = callback_new_leases6_->at(0);
ASSERT_TRUE(lease);
- EXPECT_EQ("2001:db8:1::", lease->addr_.toText());
+ 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());
EXPECT_TRUE(callback_qry_options_copy_);
// Check if the callout handle state was reset after the callout.
- checkCalloutHandleReset(client.getContext().query_);
+ checkCalloutHandleReset(client1.getContext().query_);
+ // Reset all indicators because we'll be now creating a second client.
resetCalloutBuffers();
- // Renew an address: this should lead to an error as no address pool
- // is configured.
- client.requestAddress(0x1122, IOAddress("2001:db8:1::28"));
+ // 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());
- 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.
+ EXPECT_EQ("leases6_committed", callback_name_);
- // Check the error.
- EXPECT_EQ(STATUS_NoAddrsAvail, client.getStatusCode(0x1122));
+ // 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());
- // Check that the callback called is indeed the one we installed
- EXPECT_EQ("leases6_committed", callback_name_);
+ // 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));
- ASSERT_TRUE(callback_new_leases6_);
- EXPECT_EQ(3, callback_new_leases6_->size());
- 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));
// Check if the callout handle state was reset after the callout.
- checkCalloutHandleReset(client.getContext().query_);
+ checkCalloutHandleReset(client2.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) {
+// 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_release_callout
+ // Install lease6_renew_callout
EXPECT_NO_THROW(HooksManager::preCalloutsLibraryHandle().registerCallout(
- "lease6_release", lease6_release_callout));
+ "lease6_renew", lease6_renew_callout));
const IOAddress addr("2001:db8:1:1::cafe:babe");
const uint32_t iaid = 234;
addr);
ASSERT_TRUE(l);
- // Let's create a RELEASE
- Pkt6Ptr req = Pkt6Ptr(new Pkt6(DHCPV6_RELEASE, 1234));
+ // 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 released_addr_opt(new Option6IAAddr(D6O_IAADDR, addr, 300, 500));
- ia->addOption(released_addr_opt);
+ 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 RELEASE
+ // Server-id is mandatory in RENEW
req->addOption(srv.getServerID());
// Pass it to the server and hope for a REPLY
- Pkt6Ptr reply = srv.processRelease(req);
-
+ Pkt6Ptr reply = srv.processRenew(req);
ASSERT_TRUE(reply);
// Check that the callback called is indeed the one we installed
- EXPECT_EQ("lease6_release", callback_name_);
+ 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");
- 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_NA, addr);
- ASSERT_FALSE(l);
-
- // 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(req);
-}
-
-// 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));
-
- // 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("lease6_release", callback_name_);
-
- // Check that appropriate parameters are passed to the callouts
- EXPECT_TRUE(callback_qry_pkt6_);
- EXPECT_TRUE(callback_lease6_);
+ expected_argument_names.push_back("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");
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(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;
+ EXPECT_TRUE(callback_argument_names_ == expected_argument_names);
- // Generate client-id also duid_
- OptionPtr clientid = generateClientId();
+ // Check if we get response at all
+ checkResponse(reply, DHCPV6_REPLY, 1234);
- // Check that the address we are about to use is indeed in pool
- ASSERT_TRUE(subnet_->inPool(Lease::TYPE_NA, addr));
+ OptionPtr tmp = reply->getOption(D6O_IA_NA);
+ ASSERT_TRUE(tmp);
- // 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 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
- 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());
+ 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 drop flag returned by a callout installed on the
-// lease6_release hook point will keep the lease.
-TEST_F(HooksDhcpv6SrvTest, dropLease6Release) {
+// 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_release_drop
+ // Install lease6_renew_update
EXPECT_NO_THROW(HooksManager::preCalloutsLibraryHandle().registerCallout(
- "lease6_release", lease6_release_drop));
+ "lease6_renew", lease6_renew_update));
const IOAddress addr("2001:db8:1:1::cafe:babe");
const uint32_t iaid = 234;
addr);
ASSERT_TRUE(l);
- // Let's create a RELEASE
- Pkt6Ptr req = Pkt6Ptr(new Pkt6(DHCPV6_RELEASE, 1234));
+ // 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 released_addr_opt(new Option6IAAddr(D6O_IAADDR, addr, 300, 500));
- ia->addOption(released_addr_opt);
+ 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 RELEASE
+ // Server-id is mandatory in RENEW
req->addOption(srv.getServerID());
- // Pass it to the server and hope for a REPLY
- Pkt6Ptr reply = srv.processRelease(req);
+ // 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 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 the leases6_committed callout is executed
-// with deleted leases as argument when RELEASE is processed.
-TEST_F(HooksDhcpv6SrvTest, leases6CommittedRelease) {
- 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));
+ // Check if we get response at all
+ checkResponse(reply, DHCPV6_REPLY, 1234);
- ASSERT_NO_THROW(client.doRelease());
+ OptionPtr tmp = reply->getOption(D6O_IA_NA);
+ ASSERT_TRUE(tmp);
- // Check that the callback called is indeed the one we installed
- EXPECT_EQ("leases6_committed", callback_name_);
+ // 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));
- // 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");
+ 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);
- sort(expected_argument_names.begin(), expected_argument_names.end());
- EXPECT_TRUE(callback_argument_names_ == expected_argument_names);
+ // Check that we chose the distinct override values
+ ASSERT_NE(override_preferred_, subnet_->getPreferred());
+ EXPECT_NE(override_valid_, subnet_->getValid());
- // No new allocations.
- ASSERT_TRUE(callback_new_leases6_);
- ASSERT_TRUE(callback_new_leases6_->empty());
+ // Check that preferred, valid were overridden the callout
+ EXPECT_EQ(override_preferred_, l->preferred_lft_);
+ EXPECT_EQ(override_valid_, l->valid_lft_);
- // Released lease should be returned.
- ASSERT_TRUE(callback_deleted_leases6_);
- EXPECT_EQ(1, callback_deleted_leases6_->size());
- Lease6Ptr lease = callback_deleted_leases6_->at(0);
- ASSERT_TRUE(lease);
- EXPECT_EQ("2001:db8:1::28", lease->addr_.toText());
+ // 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));
- // Pkt passed to a callout must be configured to copy retrieved options.
- EXPECT_TRUE(callback_qry_options_copy_);
+ 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(client.getContext().query_);
+ checkCalloutHandleReset(req);
}
-// This test verifies that the leases6_committed callout is executed
-// with deleted leases as argument when RELEASE is processed. Prefix variant.
-TEST_F(HooksDhcpv6SrvTest, leases6CommittedReleasePrefix) {
- 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 }";
-
- Dhcp6Client client;
- client.setInterface("eth1");
- client.requestPrefix(0xabca, 64, 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.doRelease());
-
- // 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 new allocations.
- ASSERT_TRUE(callback_new_leases6_);
- ASSERT_TRUE(callback_new_leases6_->empty());
-
- // Released lease should be returned.
- ASSERT_TRUE(callback_deleted_leases6_);
- EXPECT_EQ(1, callback_deleted_leases6_->size());
- Lease6Ptr lease = callback_deleted_leases6_->at(0);
- ASSERT_TRUE(lease);
- EXPECT_EQ("2001:db8:1:28::", lease->addr_.toText());
- EXPECT_EQ(64, lease->prefixlen_);
-
- // Pkt passed to a callout must be configured to copy retrieved options.
- EXPECT_TRUE(callback_qry_options_copy_);
+// 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);
- // Check if the callout handle state was reset after the callout.
- checkCalloutHandleReset(client.getContext().query_);
-}
+ // Install lease6_renew_skip_callout
+ EXPECT_NO_THROW(HooksManager::preCalloutsLibraryHandle().registerCallout(
+ "lease6_renew", lease6_renew_skip_callout));
-// This test verifies that the leases6_committed callout is executed
-// with deleted leases as argument when RELEASE is processed.
-// Variant with two addresses and two prefixes.
-TEST_F(HooksDhcpv6SrvTest, leases6CommittedReleaseMultiple) {
- IfaceMgrTestConfig test_config(true);
+ const IOAddress addr("2001:db8:1:1::cafe:babe");
+ const uint32_t iaid = 234;
- string config = "{ \"interfaces-config\": {"
- " \"interfaces\": [ \"*\" ]"
- "},"
- "\"preferred-lifetime\": 3000,"
- "\"rebind-timer\": 2000, "
- "\"renew-timer\": 1000, "
- "\"subnet6\": [ { "
- " \"pools\": [ { \"pool\": \"2001:db8:1::/64\" } ],"
- " \"pd-pools\": [ {"
- " \"prefix\": \"2001:db8:2::\", "
- " \"prefix-len\": 56, "
- " \"delegated-len\": 64 } ], "
- " \"subnet\": \"2001:db8::/32\", "
- " \"interface\": \"eth1\" "
- " } ],"
- "\"valid-lifetime\": 4000 }";
+ // Generate client-id also duid_
+ OptionPtr clientid = generateClientId();
- Dhcp6Client client;
- client.setInterface("eth1");
- // In theory we can reuse the IAID but copyIAsFromLeases() copies
- // only one lease...
- client.requestAddress(0xabca, IOAddress("2001:db8:1::28"));
- client.requestPrefix(0xabcb, 64, IOAddress("2001:db8:2:28::"));
- client.requestAddress(0x2233, IOAddress("2001:db8:1::29"));
- client.requestPrefix(0x2234, 64, IOAddress("2001:db8:2:29::"));
+ // Check that the address we are about to use is indeed in pool
+ ASSERT_TRUE(subnet_->inPool(Lease::TYPE_NA, addr));
- ASSERT_NO_THROW(configure(config, *client.getServer()));
+ // 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));
- ASSERT_NO_THROW(client.doSARR());
- // 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);
- ASSERT_NO_THROW(HooksManager::preCalloutsLibraryHandle().registerCallout(
- "leases6_committed", leases6_committed_callout));
+ // 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));
- ASSERT_NO_THROW(client.doRelease());
+ // 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);
- // Check that the callback called is indeed the one we installed
- EXPECT_EQ("leases6_committed", callback_name_);
+ OptionPtr renewed_addr_opt(new Option6IAAddr(D6O_IAADDR, addr, 300, 500));
+ ia->addOption(renewed_addr_opt);
+ req->addOption(ia);
+ req->addOption(clientid);
- // 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");
+ // Server-id is mandatory in RENEW
+ req->addOption(srv.getServerID());
- sort(expected_argument_names.begin(), expected_argument_names.end());
- EXPECT_TRUE(callback_argument_names_ == expected_argument_names);
+ // Pass it to the server and hope for a REPLY
+ Pkt6Ptr reply = srv.processRenew(req);
+ ASSERT_TRUE(reply);
- // No new allocations.
- ASSERT_TRUE(callback_new_leases6_);
- ASSERT_TRUE(callback_new_leases6_->empty());
+ // Check that our callback was called
+ EXPECT_EQ("lease6_renew", callback_name_);
- // Released lease should be returned.
- ASSERT_TRUE(callback_deleted_leases6_);
- EXPECT_EQ(4, callback_deleted_leases6_->size());
+ l = LeaseMgrFactory::instance().getLease6(Lease::TYPE_NA, addr);
- // Pkt passed to a callout must be configured to copy retrieved options.
- EXPECT_TRUE(callback_qry_options_copy_);
+ // 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(client.getContext().query_);
+ 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
// 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
// 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
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;
+
+ // 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("leases6_committed", callback_name_);
+ EXPECT_EQ("lease6_release", callback_name_);
- // 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 appropriate parameters are passed to the callouts
+ EXPECT_TRUE(callback_qry_pkt6_);
+ EXPECT_TRUE(callback_lease6_);
- // Deleted lease must not be present, because it is a new allocation.
- ASSERT_TRUE(callback_deleted_leases6_);
- EXPECT_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_);
+ // Check if the callout handle state was reset after the callout.
+ checkCalloutHandleReset(req);
+}
+
+// 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);
+
+ // Install lease6_release_callout
+ EXPECT_NO_THROW(HooksManager::preCalloutsLibraryHandle().registerCallout(
+ "lease6_release", lease6_release_callout));
- resetCalloutBuffers();
+ const IOAddress prefix("2001:db8:1:2:1::");
+ const uint32_t iaid = 234;
- // 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"));
+ // Generate client-id also duid_
+ OptionPtr clientid = generateClientId();
- ASSERT_NO_THROW(client.doRebind());
+ // Check that the prefix we are about to use is indeed in pool
+ ASSERT_TRUE(subnet_->inPool(Lease::TYPE_PD, prefix));
- // Make sure that we received a response
- ASSERT_TRUE(client.getContext().response_);
+ // 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 that the callback called is indeed the one we installed
- EXPECT_EQ("leases6_committed", callback_name_);
+ // Check that the lease is really in the database
+ Lease6Ptr l = LeaseMgrFactory::instance().getLease6(Lease::TYPE_PD,
+ prefix);
+ ASSERT_TRUE(l);
- // 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());
+ // 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);
- // The old lease is kept.
- ASSERT_TRUE(callback_deleted_leases6_);
- ASSERT_TRUE(callback_deleted_leases6_->empty());
+ OptionPtr released_addr_opt(new Option6IAPrefix(D6O_IAPREFIX, prefix, 80,
+ 300, 500));
+ ia->addOption(released_addr_opt);
+ req->addOption(ia);
+ req->addOption(clientid);
- // Pkt passed to a callout must be configured to copy retrieved options.
- EXPECT_TRUE(callback_qry_options_copy_);
+ // Server-id is mandatory in RELEASE
+ req->addOption(srv.getServerID());
- // Check if the callout handle state was reset after the callout.
- checkCalloutHandleReset(client.getContext().query_);
+ // Pass it to the server and hope for a REPLY
+ Pkt6Ptr reply = srv.processRelease(req);
- resetCalloutBuffers();
+ ASSERT_TRUE(reply);
- // The rebound address is just a hint.
- client.requestAddress(0x5577, IOAddress("4000::2"));
+ // Check that the callback called is indeed the one we installed
+ EXPECT_EQ("lease6_release", callback_name_);
- ASSERT_NO_THROW(client.doRebind());
+ // Check that appropriate parameters are passed to the callouts
+ EXPECT_TRUE(callback_qry_pkt6_);
+ EXPECT_TRUE(callback_lease6_);
- // Make sure that we received a response
- ASSERT_TRUE(client.getContext().response_);
+ // 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 callback called is indeed the one we installed
- EXPECT_EQ("leases6_committed", callback_name_);
+ // 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);
- 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());
+ // 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_);
-
- resetCalloutBuffers();
-
- // 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.doRebind());
+ checkCalloutHandleReset(req);
+}
- // Make sure that we received a response
- ASSERT_TRUE(client.getContext().response_);
+// 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);
- // Check the error.
- EXPECT_EQ(STATUS_NoPrefixAvail, client.getStatusCode(0x1122));
+ // Install lease6_release_callout
+ EXPECT_NO_THROW(HooksManager::preCalloutsLibraryHandle().registerCallout(
+ "lease6_release", lease6_release_callout));
- // Check that the callback called is indeed the one we installed
- EXPECT_EQ("leases6_committed", callback_name_);
+ const IOAddress prefix("2001:db8:1:2:1::");
+ const uint32_t iaid = 234;
- ASSERT_TRUE(callback_new_leases6_);
- EXPECT_EQ(3, callback_new_leases6_->size());
- ASSERT_TRUE(callback_deleted_leases6_);
- EXPECT_TRUE(callback_deleted_leases6_->empty());
+ // Generate client-id also duid_
+ OptionPtr clientid = generateClientId();
- // Check if the callout handle state was reset after the callout.
- checkCalloutHandleReset(client.getContext().query_);
-}
+ // Check that the prefix we are about to use is indeed in pool
+ ASSERT_TRUE(subnet_->inPool(Lease::TYPE_PD, prefix));
-// 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);
+ // 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));
- 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 }";
+ // Check that the lease is really in the database
+ Lease6Ptr l = LeaseMgrFactory::instance().getLease6(Lease::TYPE_PD,
+ prefix);
+ ASSERT_TRUE(l);
- Dhcp6Client client;
- client.setInterface("eth1");
- client.requestPrefix(0xabca, 64, 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_PD, iaid, 1500, 3000);
- ASSERT_NO_THROW(configure(config, *client.getServer()));
+ 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(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);
// 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
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) {
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)
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));
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
}
}
-// 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);
EXPECT_EQ(1, getStatistic("pkt6-receive-drop"));
}
-
} // namespace