Commit e50d2ebe authored by Marcin Siodelski's avatar Marcin Siodelski
Browse files

[master] Merge branch 'trac4497_rebase'

parents 75a83504 978830d5
......@@ -291,4 +291,52 @@ packet processing. Hook points that are not specific to packet processing
expired leases will remain in the database and their recovery will
be attempted during the next reclaim cycle.
@section dhcpv4HooksOptionsAccess Accessing DHCPv4 Options within a Packet
When the server constructs a response message to a client it includes
DHCP options configured for this client in a response message. Apart
from the dynamically created options, such as Client FQDN option, it
typically includes many options specified in the server configuration
and held within the configuration structures by @c CfgMgr. Option
instances are created once, during server configuration, and the
@c CfgMgr holds pointers to those instances until the next server
reconfiguration.
When the server includes an option in a response message it copies
a pointer to the instance of this option, rather than entire option.
This ensures the good performance of response message creation. However,
it also implies that any modification to the option carried in the
DHCP response will affect an instance of this option in the server
configuration structures. This is obviously not desired as it would
affect all subsequent DHCP transactions involving this option. The
DHCP server code avoids modifying the options included in the messages
so it is possible to ensure good performance without a risk of
accidentally modifying server configuration. The situation is
different with hooks libraries which purpose is, in many cases,
to modify values of options inserted by the server.
Thus, @c Pkt class provides a mechanism to return a copy of an
option to a caller (e.g. a callout), rather than an instance
shared with the @c CfgMgr. This mechanism is enabled for all instances
of @c Pkt4 passed to the callouts, i.e. "query4" and "response4"
arguments. It is also automatically disabled when the callout
returns the control back to the server.
At every hook point, where the server passes an instance of a packet
to the callouts, the server calls
@c isc::dhcp::Pkt4::setCopyRetrievedOptions (true)
to force copying options retrieved by @c isc::dhcp::Pkt4::getOption
within callouts. The copied option replaces an original option within a
packet and any modification to the option content by the callout
would only affect the option instance associated with the packet.
On the other hand, copying each retrieved option may be expensive.
If performance of a hook library is a concern, it is possible for the
hook library to disable copying retrieved options by calling
@c isc::dhcp::Pkt4::setCopyRetrievedOptions (false) within a callout.
In this case however, the hook library implementer must be aware that any
modification of the option instance would affect the server configuration
and may disrupt server's operation. Thus, disabling copying of retrieved
options is not recommended unless the hook library is not intended
to modify configured options carried within a packet.
*/
......@@ -467,6 +467,9 @@ Dhcpv4Srv::selectSubnet(const Pkt4Ptr& query) const {
// We're reusing callout_handle from previous calls
callout_handle->deleteAllArguments();
// Enable copying options from the packet within hook library.
ScopedEnableOptionsCopy<Pkt4> query4_options_copy(query);
// Set new arguments
callout_handle->setArgument("query4", query);
callout_handle->setArgument("subnet4", subnet);
......@@ -735,6 +738,9 @@ Dhcpv4Srv::run_one() {
// Delete previously set arguments
callout_handle->deleteAllArguments();
// Enable copying options from the packet within hook library.
ScopedEnableOptionsCopy<Pkt4> resp4_options_copy(rsp);
// Pass incoming packet as argument
callout_handle->setArgument("response4", rsp);
......@@ -804,6 +810,9 @@ Dhcpv4Srv::processPacket(Pkt4Ptr& query, Pkt4Ptr& rsp) {
// Delete previously set arguments
callout_handle->deleteAllArguments();
// Enable copying options from the packet within hook library.
ScopedEnableOptionsCopy<Pkt4> query4_options_copy(query);
// Pass incoming packet as argument
callout_handle->setArgument("query4", query);
......@@ -894,6 +903,9 @@ Dhcpv4Srv::processPacket(Pkt4Ptr& query, Pkt4Ptr& rsp) {
// Delete previously set arguments
callout_handle->deleteAllArguments();
// Enable copying options from the packet within hook library.
ScopedEnableOptionsCopy<Pkt4> query4_options_copy(query);
// Pass incoming packet as argument
callout_handle->setArgument("query4", query);
......@@ -983,6 +995,10 @@ Dhcpv4Srv::processPacket(Pkt4Ptr& query, Pkt4Ptr& rsp) {
// Clear skip flag if it was set in previous callouts
callout_handle->setStatus(CalloutHandle::NEXT_STEP_CONTINUE);
// Enable copying options from the query and response packets within
// hook library.
ScopedEnableOptionsCopy<Pkt4> query_resp_options_copy(query, rsp);
// Set our response
callout_handle->setArgument("response4", rsp);
......@@ -2064,6 +2080,9 @@ Dhcpv4Srv::processRelease(Pkt4Ptr& release) {
// Delete all previous arguments
callout_handle->deleteAllArguments();
// Enable copying options from the packet within hook library.
ScopedEnableOptionsCopy<Pkt4> query4_options_copy(release);
// Pass the original packet
callout_handle->setArgument("query4", release);
......@@ -2207,6 +2226,9 @@ Dhcpv4Srv::declineLease(const Lease4Ptr& lease, const Pkt4Ptr& decline) {
// Delete previously set arguments
callout_handle->deleteAllArguments();
// Enable copying options from the packet within hook library.
ScopedEnableOptionsCopy<Pkt4> query4_options_copy(decline);
// Pass incoming Decline and the lease to be declined.
callout_handle->setArgument("lease4", lease);
callout_handle->setArgument("query4", decline);
......
......@@ -121,6 +121,9 @@ void Dhcp4to6Ipc::handler() {
// Delete previously set arguments
callout_handle->deleteAllArguments();
// Enable copying options from the packet within hook library.
ScopedEnableOptionsCopy<Pkt4> response4_options_copy(rsp);
// Pass incoming packet as argument
callout_handle->setArgument("response4", rsp);
......
......@@ -21,6 +21,7 @@
#include <gtest/gtest.h>
#include <stdint.h>
#include <utility>
using namespace isc;
using namespace isc::asiolink;
......@@ -64,6 +65,10 @@ public:
EXPECT_TRUE(srv);
// Let's wipe all existing statistics.
StatsMgr::instance().removeAll();
// Set the flags to false as we expect them to be set in callouts.
callback_recv_pkt_options_copy_ = std::make_pair(false, false);
callback_sent_pkt_options_copy_ = std::make_pair(false, false);
}
/// @brief Configure DHCP4o6 port.
......@@ -85,9 +90,17 @@ public:
///
/// @param callout_handle handle passed by the hooks framework
/// @return always 0
static int
buffer4_receive_callout(CalloutHandle& callout_handle) {
static int buffer4_receive_callout(CalloutHandle& callout_handle) {
callout_handle.getArgument("query4", callback_recv_pkt_);
Pkt4o6Ptr pkt4 = boost::dynamic_pointer_cast<Pkt4o6>(callback_recv_pkt_);
if (pkt4) {
callback_recv_pkt_options_copy_.first = pkt4->isCopyRetrievedOptions();
Pkt6Ptr pkt6 = pkt4->getPkt6();
if (pkt6) {
callback_recv_pkt_options_copy_.second =
pkt6->isCopyRetrievedOptions();
}
}
return (0);
}
......@@ -97,9 +110,17 @@ public:
///
/// @param callout_handle handle passed by the hooks framework
/// @return always 0
static int
buffer4_send_callout(CalloutHandle& callout_handle) {
static int buffer4_send_callout(CalloutHandle& callout_handle) {
callout_handle.getArgument("response4", callback_sent_pkt_);
Pkt4o6Ptr pkt4 = boost::dynamic_pointer_cast<Pkt4o6>(callback_sent_pkt_);
if (pkt4) {
callback_sent_pkt_options_copy_.first = pkt4->isCopyRetrievedOptions();
Pkt6Ptr pkt6 = pkt4->getPkt6();
if (pkt6) {
callback_sent_pkt_options_copy_.second =
pkt6->isCopyRetrievedOptions();
}
}
return (0);
}
......@@ -109,6 +130,14 @@ public:
/// @brief Response Pkt4 shared pointer returned in the send callout
static Pkt4Ptr callback_sent_pkt_;
/// Flags indicating if copying retrieved options was enabled for
/// a received packet during callout execution.
static std::pair<bool, bool> callback_recv_pkt_options_copy_;
/// Flags indicating if copying retrieved options was enabled for
/// a sent packet during callout execution.
static std::pair<bool, bool> callback_sent_pkt_options_copy_;
/// @brief reference to a controlled server
///
/// Dhcp4to6Ipc::handler() uses the instance of the controlled server
......@@ -124,6 +153,8 @@ private:
Pkt4Ptr Dhcp4to6IpcTest::callback_recv_pkt_;
Pkt4Ptr Dhcp4to6IpcTest::callback_sent_pkt_;
std::pair<bool, bool> Dhcp4to6IpcTest::callback_recv_pkt_options_copy_;
std::pair<bool, bool> Dhcp4to6IpcTest::callback_sent_pkt_options_copy_;
void
Dhcp4to6IpcTest::configurePort(uint16_t port) {
......@@ -192,6 +223,11 @@ TEST_F(Dhcp4to6IpcTest, receive) {
ASSERT_TRUE(pkt6_received);
EXPECT_EQ("eth0", pkt6_received->getIface());
EXPECT_EQ("2001:db8:1::123", pkt6_received->getRemoteAddr().toText());
// Both DHCP4o6 and encapsulated DHCPv6 packet should have the
// flag enabled.
EXPECT_TRUE(callback_recv_pkt_options_copy_.first);
EXPECT_TRUE(callback_recv_pkt_options_copy_.second);
}
// This test verifies that message with multiple DHCPv4 query options
......@@ -326,6 +362,11 @@ TEST_F(Dhcp4to6IpcTest, process) {
EXPECT_EQ("eth0", pkt6_sent->getIface());
EXPECT_EQ("2001:db8:1::123", pkt6_sent->getRemoteAddr().toText());
// Both DHCP4o6 and encapsulated DHCPv6 packet should have the
// flag enabled.
EXPECT_TRUE(callback_sent_pkt_options_copy_.first);
EXPECT_TRUE(callback_sent_pkt_options_copy_.second);
// Verify the 4o6 part
OptionCollection sent_msgs = pkt6_sent->getOptions(D6O_DHCPV4_MSG);
ASSERT_EQ(1, sent_msgs.size());
......
......@@ -200,6 +200,10 @@ public:
callout_handle.getArgument("query4", callback_qry_pkt4_);
callback_argument_names_ = callout_handle.getArgumentNames();
if (callback_qry_pkt4_) {
callback_qry_options_copy_ = callback_qry_pkt4_->isCopyRetrievedOptions();
}
return (0);
}
......@@ -245,6 +249,11 @@ public:
callout_handle.getArgument("query4", callback_qry_pkt4_);
callback_argument_names_ = callout_handle.getArgumentNames();
if (callback_qry_pkt4_) {
callback_qry_options_copy_ = callback_qry_pkt4_->isCopyRetrievedOptions();
}
return (0);
}
......@@ -312,6 +321,15 @@ public:
callout_handle.getArgument("query4", callback_qry_pkt4_);
callback_argument_names_ = callout_handle.getArgumentNames();
if (callback_qry_pkt4_) {
callback_qry_options_copy_ = callback_qry_pkt4_->isCopyRetrievedOptions();
}
if (callback_resp_pkt4_) {
callback_resp_options_copy_ = callback_resp_pkt4_->isCopyRetrievedOptions();
}
return (0);
}
......@@ -375,6 +393,11 @@ public:
callout_handle.getArgument("response4", callback_resp_pkt4_);
callback_argument_names_ = callout_handle.getArgumentNames();
if (callback_resp_pkt4_) {
callback_resp_options_copy_ = callback_resp_pkt4_->isCopyRetrievedOptions();
}
return (0);
}
......@@ -417,6 +440,11 @@ public:
callout_handle.getArgument("subnet4collection", callback_subnet4collection_);
callback_argument_names_ = callout_handle.getArgumentNames();
if (callback_qry_pkt4_) {
callback_qry_options_copy_ = callback_qry_pkt4_->isCopyRetrievedOptions();
}
return (0);
}
......@@ -454,6 +482,11 @@ public:
callout_handle.getArgument("lease4", callback_lease4_);
callback_argument_names_ = callout_handle.getArgumentNames();
if (callback_qry_pkt4_) {
callback_qry_options_copy_ = callback_qry_pkt4_->isCopyRetrievedOptions();
}
return (0);
}
......@@ -471,6 +504,11 @@ public:
callout_handle.getArgument("clientid", callback_clientid_);
callback_argument_names_ = callout_handle.getArgumentNames();
if (callback_qry_pkt4_) {
callback_qry_options_copy_ = callback_qry_pkt4_->isCopyRetrievedOptions();
}
return (0);
}
......@@ -484,6 +522,10 @@ public:
callout_handle.getArgument("query4", callback_qry_pkt4_);
callout_handle.getArgument("lease4", callback_lease4_);
if (callback_qry_pkt4_) {
callback_qry_options_copy_ = callback_qry_pkt4_->isCopyRetrievedOptions();
}
return (0);
}
......@@ -509,6 +551,8 @@ public:
callback_subnet4_.reset();
callback_subnet4collection_ = NULL;
callback_argument_names_.clear();
callback_qry_options_copy_ = false;
callback_resp_options_copy_ = false;
}
/// pointer to Dhcpv4Srv that is used in tests
......@@ -542,6 +586,15 @@ public:
/// A list of all received arguments
static vector<string> callback_argument_names_;
/// Flag indicating if copying retrieved options was enabled for
/// a query during callout execution.
static bool callback_qry_options_copy_;
/// 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.
......@@ -555,6 +608,8 @@ ClientIdPtr HooksDhcpv4SrvTest::callback_clientid_;
Lease4Ptr HooksDhcpv4SrvTest::callback_lease4_;
const Subnet4Collection* HooksDhcpv4SrvTest::callback_subnet4collection_;
vector<string> HooksDhcpv4SrvTest::callback_argument_names_;
bool HooksDhcpv4SrvTest::callback_qry_options_copy_;
bool HooksDhcpv4SrvTest::callback_resp_options_copy_;
/// @brief Fixture class used to do basic library load/unload tests
class LoadUnloadDhcpv4SrvTest : public ::testing::Test {
......@@ -623,6 +678,9 @@ TEST_F(HooksDhcpv4SrvTest, Buffer4ReceiveSimple) {
expected_argument_names.push_back(string("query4"));
EXPECT_TRUE(expected_argument_names == callback_argument_names_);
// Pkt passed to a callout must be configured to copy retrieved options.
EXPECT_TRUE(callback_qry_options_copy_);
}
// Checks if callouts installed on buffer4_receive is able to change
......@@ -728,6 +786,9 @@ TEST_F(HooksDhcpv4SrvTest, pkt4ReceiveSimple) {
expected_argument_names.push_back(string("query4"));
EXPECT_TRUE(expected_argument_names == callback_argument_names_);
// Pkt passed to a callout must be configured to copy retrieved options.
EXPECT_TRUE(callback_qry_options_copy_);
}
// Checks if callouts installed on pkt4_received is able to change
......@@ -865,6 +926,10 @@ TEST_F(HooksDhcpv4SrvTest, pkt4SendSimple) {
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_);
// Pkt passed to a callout must be configured to copy retrieved options.
EXPECT_TRUE(callback_qry_options_copy_);
EXPECT_TRUE(callback_resp_options_copy_);
}
// Checks if callouts installed on pkt4_send is able to change
......@@ -1006,6 +1071,9 @@ TEST_F(HooksDhcpv4SrvTest, buffer4SendSimple) {
vector<string> expected_argument_names;
expected_argument_names.push_back(string("response4"));
EXPECT_TRUE(expected_argument_names == callback_argument_names_);
// Pkt passed to a callout must be configured to copy retrieved options.
EXPECT_TRUE(callback_resp_options_copy_);
}
// Checks if callouts installed on buffer4_send are indeed called and that
......@@ -1139,6 +1207,9 @@ TEST_F(HooksDhcpv4SrvTest, subnet4SelectSimple) {
// Compare that the available subnets are reported as expected
EXPECT_TRUE((*exp_subnets)[0].get() == (*callback_subnet4collection_)[0].get());
EXPECT_TRUE((*exp_subnets)[1].get() == (*callback_subnet4collection_)[1].get());
// Pkt passed to a callout must be configured to copy retrieved options.
EXPECT_TRUE(callback_qry_options_copy_);
}
// This test checks if callout installed on subnet4_select hook point can pick
......@@ -1300,6 +1371,9 @@ TEST_F(HooksDhcpv4SrvTest, lease4RenewSimple) {
EXPECT_TRUE(callback_argument_names_ == expected_argument_names);
EXPECT_TRUE(LeaseMgrFactory::instance().deleteLease(addr));
// Pkt passed to a callout must be configured to copy retrieved options.
EXPECT_TRUE(callback_qry_options_copy_);
}
// This test verifies that a callout installed on lease4_renew can trigger
......@@ -1456,6 +1530,9 @@ TEST_F(HooksDhcpv4SrvTest, lease4ReleaseSimple) {
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_);
}
// This test verifies that skip flag returned by a callout installed on the
......@@ -1564,6 +1641,9 @@ TEST_F(HooksDhcpv4SrvTest, HooksDecline) {
// the lease manager) all match.
EXPECT_EQ(addr, from_mgr->addr_);
EXPECT_EQ(addr, callback_lease4_->addr_);
// Pkt passed to a callout must be configured to copy retrieved options.
EXPECT_TRUE(callback_qry_options_copy_);
}
// Checks that decline4 hook is able to drop the packet.
......
......@@ -333,4 +333,55 @@ packet processing. Hook points that are not specific to packet processing
expired leases will remain in the database and their recovery will
be attempted during the next reclaim cycle.
@section dhcpv6HooksOptionsAccess Accessing DHCPv6 Options within a Packet
When the server constructs a response message to a client it includes
DHCP options configured for this client in a response message. Apart
from the dynamically created options, such as IA_NA or ClientFQDN, it
typically includes many options specified in the server configuration
and held within the configuration structures by @c CfgMgr. Option
instances are created once, during server configuration, and the
@c CfgMgr holds pointers to those instances until the next server
reconfiguration.
When the server includes an option in a response message it copies
a pointer to the instance of this option, rather than entire option.
This ensures the good performance of response message creation. However,
it also implies that any modification to the option carried in the
DHCP response will affect an instance of this option in the server
configuration structures. This is obviously not desired as it would
affect all subsequent DHCP transactions involving this option. The
DHCP server code avoids modifying the options included in the messages
so it is possible to ensure good performance without a risk of
accidentally modifying server configuration. The situation is
different with hooks libraries which purpose is, in many cases,
to modify values of options inserted by the server.
Thus, @c Pkt class provides a mechanism to return a copy of an
option to a caller (e.g. a callout), rather than an instance
shared with the @c CfgMgr. This mechanism is enabled for all instances
of @c Pkt6 passed to the callouts, i.e. "query6" and "response6"
arguments. It is also automatically disabled when the callout
returns the control back to the server.
At every hook point, where the server passes an instance of a packet
to the callouts, the server calls
@c isc::dhcp::Pkt6::setCopyRetrievedOptions (true)
to force copying options retrieved by @c isc::dhcp::Pkt6::getOption,
@c isc::dhcp::Pkt6::getOptions, @c isc::dhcp::Pkt6::getRelayOption
and @c isc::dhcp::Pkt6::getAnyRelayOption within callouts. The copied
option replaces an original option within the packet and any
modification to the option content by the callout would only affect
the option instance associated with the packet.
On the other hand, copying each retrieved option may be expensive.
If performance of a hook library is a concern, it is possible for the
hook library to disable copying retrieved options by calling
@c isc::dhcp::Pkt6::setCopyRetrievedOptions (false) within a callout.
In this case however, the hook library implementer must be aware that
any modification of the option instance would affect the server
configuration and may disrupt server's operation. Thus, disabling
copying of retrieved options is not recommended unless the hook
library is not intended to modify configured options carried
within a packet.
*/
......@@ -438,6 +438,9 @@ void Dhcpv6Srv::run_one() {
// Delete previously set arguments
callout_handle->deleteAllArguments();
// Enable copying options from the packet within hook library.
ScopedEnableOptionsCopy<Pkt6> response6_options_copy(rsp);
// Pass incoming packet as argument
callout_handle->setArgument("response6", rsp);
......@@ -480,6 +483,9 @@ Dhcpv6Srv::processPacket(Pkt6Ptr& query, Pkt6Ptr& rsp) {
if (HooksManager::calloutsPresent(Hooks.hook_index_buffer6_receive_)) {
CalloutHandlePtr callout_handle = getCalloutHandle(query);
// Enable copying options from the packet within hook library.
ScopedEnableOptionsCopy<Pkt6> query6_options_copy(query);
// Delete previously set arguments
callout_handle->deleteAllArguments();
......@@ -575,6 +581,9 @@ Dhcpv6Srv::processPacket(Pkt6Ptr& query, Pkt6Ptr& rsp) {
// Delete previously set arguments
callout_handle->deleteAllArguments();
// Enable copying options from the packet within hook library.
ScopedEnableOptionsCopy<Pkt6> query6_options_copy(query);
// Pass incoming packet as argument
callout_handle->setArgument("query6", query);
......@@ -717,6 +726,9 @@ Dhcpv6Srv::processPacket(Pkt6Ptr& query, Pkt6Ptr& rsp) {
if (HooksManager::calloutsPresent(Hooks.hook_index_pkt6_send_)) {
CalloutHandlePtr callout_handle = getCalloutHandle(query);
// Enable copying options from the packets within hook library.
ScopedEnableOptionsCopy<Pkt6> query_resp_options_copy(query, rsp);
// Delete all previous arguments
callout_handle->deleteAllArguments();
......@@ -1014,6 +1026,9 @@ Dhcpv6Srv::selectSubnet(const Pkt6Ptr& question) {
// We're reusing callout_handle from previous calls
callout_handle->deleteAllArguments();
// Enable copying options from the packet within hook library.
ScopedEnableOptionsCopy<Pkt6> query6_options_copy(question);
// Set new arguments
callout_handle->setArgument("query6", question);
callout_handle->setArgument("subnet6", subnet);
......@@ -2023,6 +2038,9 @@ Dhcpv6Srv::releaseIA_NA(const DuidPtr& duid, const Pkt6Ptr& query,
if (HooksManager::calloutsPresent(Hooks.hook_index_lease6_release_)) {
CalloutHandlePtr callout_handle = getCalloutHandle(query);
// Enable copying options from the packet within hook library.
ScopedEnableOptionsCopy<Pkt6> query6_options_copy(query);
// Delete all previous arguments
callout_handle->deleteAllArguments();
......@@ -2184,6 +2202,9 @@ Dhcpv6Srv::releaseIA_PD(const DuidPtr& duid, const Pkt6Ptr& query,
// Delete all previous arguments
callout_handle->deleteAllArguments();
// Enable copying options from the packet within hook library.
ScopedEnableOptionsCopy<Pkt6> query6_options_copy(query);
// Pass the original packet
callout_handle->setArgument("query6", query);
......@@ -2706,6 +2727,9 @@ Dhcpv6Srv::declineLease(const Pkt6Ptr& decline, const Lease6Ptr lease,
// Delete previously set arguments
callout_handle->deleteAllArguments();
// Enable copying options from the packet within hook library.
ScopedEnableOptionsCopy<Pkt6> query6_options_copy(decline);
// Pass incoming packet as argument
callout_handle->setArgument("query6", decline);
callout_handle->setArgument("lease6", lease);
......
......@@ -107,6 +107,9 @@ void Dhcp6to4Ipc::handler() {
// Delete previously set arguments
callout_handle->deleteAllArguments();
// Enable copying options from the packet within hook library.
ScopedEnableOptionsCopy<Pkt6> response6_options_copy(pkt);
// Pass incoming packet as argument
callout_handle->setArgument("response6", pkt);
......
......@@ -55,6 +55,9 @@ public:
registerCallout("buffer6_send", buffer6_send_callout));
// Let's wipe all existing statistics.
StatsMgr::instance().removeAll();
// Reset the flag which we expect to be set in the callout.
callback_pkt_options_copy_ = false;
}
/// @brief Configure DHCP4o6 port.
......@@ -77,12 +80,19 @@ public:
static int
buffer6_send_callout(CalloutHandle& callout_handle) {
callout_handle.getArgument("response6", callback_pkt_);
if (callback_pkt_) {
callback_pkt_options_copy_ = callback_pkt_->isCopyRetrievedOptions();
}
return (0);
}
/// @brief Response Pkt6 shared pointer returned in the callout
static Pkt6Ptr callback_pkt_;
/// Flag indicating if copying retrieved options was enabled for
/// a received packet during callout execution.
static bool callback_pkt_options_copy_;
private:
/// @brief Provides fake configuration of interfaces.
......@@ -90,6 +100,7 @@ private:
};
Pkt6Ptr Dhcp6to4IpcTest::callback_pkt_;
bool Dhcp6to4IpcTest::callback_pkt_options_copy_;
void
Dhcp6to4IpcTest::configurePort(const uint16_t port) {
......@@ -153,6 +164,10 @@ TEST_F(Dhcp6to4IpcTest, receive) {
ASSERT_NO_THROW(src_ipc.send(pkt));
ASSERT_NO_THROW(IfaceMgr::instance().receive6(1, 0));
// Make sure that the received packet was configured to return copy of
// retrieved options within a callout.
E