|
@@ -5,6 +5,7 @@
|
|
|
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
|
|
|
|
|
#include <config.h>
|
|
|
+
|
|
|
#include <asiolink/io_address.h>
|
|
|
#include <dhcp/pkt6.h>
|
|
|
#include <dhcp/iface_mgr.h>
|
|
@@ -13,6 +14,11 @@
|
|
|
#include <dhcp6/dhcp6to4_ipc.h>
|
|
|
#include <dhcpsrv/cfgmgr.h>
|
|
|
#include <dhcpsrv/testutils/dhcp4o6_test_ipc.h>
|
|
|
+#include <stats/stats_mgr.h>
|
|
|
+#include <hooks/callout_handle.h>
|
|
|
+#include <hooks/hooks_manager.h>
|
|
|
+#include <hooks/library_handle.h>
|
|
|
+
|
|
|
#include <gtest/gtest.h>
|
|
|
#include <stdint.h>
|
|
|
|
|
@@ -20,6 +26,8 @@ using namespace isc;
|
|
|
using namespace isc::asiolink;
|
|
|
using namespace isc::dhcp;
|
|
|
using namespace isc::dhcp::test;
|
|
|
+using namespace isc::stats;
|
|
|
+using namespace isc::hooks;
|
|
|
using namespace isc::util;
|
|
|
|
|
|
namespace {
|
|
@@ -42,6 +50,11 @@ public:
|
|
|
: iface_mgr_test_config_(true) {
|
|
|
IfaceMgr::instance().openSockets6();
|
|
|
configurePort(TEST_PORT);
|
|
|
+ // Install buffer6_send_callout
|
|
|
+ EXPECT_NO_THROW(HooksManager::preCalloutsLibraryHandle().
|
|
|
+ registerCallout("buffer6_send", buffer6_send_callout));
|
|
|
+ // Let's wipe all existing statistics.
|
|
|
+ StatsMgr::instance().removeAll();
|
|
|
}
|
|
|
|
|
|
/// @brief Configure DHCP4o6 port.
|
|
@@ -57,12 +70,27 @@ public:
|
|
|
/// @return Pointer to the instance of the DHCPv4-query Message option.
|
|
|
OptionPtr createDHCPv4MsgOption() const;
|
|
|
|
|
|
+ /// @brief Handler for the buffer6_send hook
|
|
|
+ ///
|
|
|
+ /// @param callout_handle handle passed by the hooks framework
|
|
|
+ /// @return always 0
|
|
|
+ static int
|
|
|
+ buffer6_send_callout(CalloutHandle& callout_handle) {
|
|
|
+ callout_handle.getArgument("response6", callback_pkt_);
|
|
|
+ return (0);
|
|
|
+ }
|
|
|
+
|
|
|
+ /// @brief Response Pkt6 shared pointer returned in the callout
|
|
|
+ static Pkt6Ptr callback_pkt_;
|
|
|
+
|
|
|
private:
|
|
|
|
|
|
/// @brief Provides fake configuration of interfaces.
|
|
|
IfaceMgrTestConfig iface_mgr_test_config_;
|
|
|
};
|
|
|
|
|
|
+Pkt6Ptr Dhcp6to4IpcTest::callback_pkt_;
|
|
|
+
|
|
|
void
|
|
|
Dhcp6to4IpcTest::configurePort(const uint16_t port) {
|
|
|
CfgMgr::instance().getStagingCfg()->setDhcp4o6Port(port);
|
|
@@ -104,23 +132,29 @@ TEST_F(Dhcp6to4IpcTest, receive) {
|
|
|
ASSERT_NO_THROW(ipc.open());
|
|
|
ASSERT_NO_THROW(src_ipc.open());
|
|
|
|
|
|
+ // Get statistics
|
|
|
+ StatsMgr& mgr = StatsMgr::instance();
|
|
|
+ ObservationPtr pkt6_snd = mgr.getObservation("pkt6-sent");
|
|
|
+ ObservationPtr d4_resp = mgr.getObservation("pkt6-dhcpv4-response-sent");
|
|
|
+ EXPECT_FALSE(pkt6_snd);
|
|
|
+ EXPECT_FALSE(d4_resp);
|
|
|
+
|
|
|
// Create message to be sent over IPC.
|
|
|
- Pkt6Ptr pkt(new Pkt6(DHCPV6_DHCPV4_QUERY, 1234));
|
|
|
+ Pkt6Ptr pkt(new Pkt6(DHCPV6_DHCPV4_RESPONSE, 1234));
|
|
|
pkt->addOption(createDHCPv4MsgOption());
|
|
|
pkt->setIface("eth0");
|
|
|
pkt->setRemoteAddr(IOAddress("2001:db8:1::123"));
|
|
|
ASSERT_NO_THROW(pkt->pack());
|
|
|
|
|
|
+ // Reset the callout cached packet
|
|
|
+ Dhcp6to4IpcTest::callback_pkt_.reset();
|
|
|
+
|
|
|
// Send and wait up to 1 second to receive it.
|
|
|
ASSERT_NO_THROW(src_ipc.send(pkt));
|
|
|
ASSERT_NO_THROW(IfaceMgr::instance().receive6(1, 0));
|
|
|
|
|
|
-#if 0
|
|
|
- // The stub packet filter exposes static function to retrieve messages
|
|
|
- // sent over the fake sockets/interfaces. This is the message that the
|
|
|
- // IPC endpoint should forward to the client after receiving it
|
|
|
- // from the DHCPv4 server.
|
|
|
- Pkt6Ptr forwarded = PktFilter6TestStub::popSent();
|
|
|
+ // Get the forwarded packet from the callout
|
|
|
+ Pkt6Ptr forwarded = Dhcp6to4IpcTest::callback_pkt_;
|
|
|
ASSERT_TRUE(forwarded);
|
|
|
|
|
|
// Verify the packet received.
|
|
@@ -129,7 +163,75 @@ TEST_F(Dhcp6to4IpcTest, receive) {
|
|
|
EXPECT_TRUE(forwarded->getOption(D6O_DHCPV4_MSG));
|
|
|
EXPECT_EQ("eth0", forwarded->getIface());
|
|
|
EXPECT_EQ("2001:db8:1::123", forwarded->getRemoteAddr().toText());
|
|
|
-#endif
|
|
|
+
|
|
|
+ // Verify statistics
|
|
|
+ pkt6_snd = mgr.getObservation("pkt6-sent");
|
|
|
+ d4_resp = mgr.getObservation("pkt6-dhcpv4-response-sent");
|
|
|
+ ASSERT_TRUE(pkt6_snd);
|
|
|
+ ASSERT_TRUE(d4_resp);
|
|
|
+ EXPECT_EQ(1, pkt6_snd->getInteger().first);
|
|
|
+ EXPECT_EQ(1, d4_resp->getInteger().first);
|
|
|
+}
|
|
|
+
|
|
|
+// This test verifies that the DHCPv4 endpoint of the DHCPv4o6 IPC can
|
|
|
+// receive relayed messages.
|
|
|
+// This is currently not supported: it is a known defect addressed by #4296.
|
|
|
+TEST_F(Dhcp6to4IpcTest, DISABLED_receiveRelayed) {
|
|
|
+ // Create instance of the IPC endpoint under test.
|
|
|
+ Dhcp6to4Ipc& ipc = Dhcp6to4Ipc::instance();
|
|
|
+ // Create instance of the IPC endpoint being used as a source of messages.
|
|
|
+ TestIpc src_ipc(TEST_PORT, TestIpc::ENDPOINT_TYPE_V4);
|
|
|
+
|
|
|
+ // Open both endpoints.
|
|
|
+ ASSERT_NO_THROW(ipc.open());
|
|
|
+ ASSERT_NO_THROW(src_ipc.open());
|
|
|
+
|
|
|
+ // Get statistics
|
|
|
+ StatsMgr& mgr = StatsMgr::instance();
|
|
|
+ ObservationPtr pkt6_snd = mgr.getObservation("pkt6-sent");
|
|
|
+ ObservationPtr d4_resp = mgr.getObservation("pkt6-dhcpv4-response-sent");
|
|
|
+ EXPECT_FALSE(pkt6_snd);
|
|
|
+ EXPECT_FALSE(d4_resp);
|
|
|
+
|
|
|
+ // Create relayed message to be sent over IPC.
|
|
|
+ Pkt6Ptr pkt(new Pkt6(DHCPV6_DHCPV4_RESPONSE, 1234));
|
|
|
+ pkt->addOption(createDHCPv4MsgOption());
|
|
|
+ Pkt6::RelayInfo relay;
|
|
|
+ relay.linkaddr_ = IOAddress("3000:1::1");
|
|
|
+ relay.peeraddr_ = IOAddress("fe80::1");
|
|
|
+ relay.msg_type_ = DHCPV6_RELAY_FORW;
|
|
|
+ relay.hop_count_ = 1;
|
|
|
+ pkt->relay_info_.push_back(relay);
|
|
|
+ pkt->setIface("eth0");
|
|
|
+ pkt->setRemoteAddr(IOAddress("2001:db8:1::123"));
|
|
|
+ ASSERT_NO_THROW(pkt->pack());
|
|
|
+
|
|
|
+ // Reset the callout cached packet
|
|
|
+ Dhcp6to4IpcTest::callback_pkt_.reset();
|
|
|
+
|
|
|
+ // Send and wait up to 1 second to receive it.
|
|
|
+ ASSERT_NO_THROW(src_ipc.send(pkt));
|
|
|
+ ASSERT_NO_THROW(IfaceMgr::instance().receive6(1, 0));
|
|
|
+
|
|
|
+ // Get the forwarded packet from the callout
|
|
|
+ Pkt6Ptr forwarded = Dhcp6to4IpcTest::callback_pkt_;
|
|
|
+ ASSERT_TRUE(forwarded);
|
|
|
+
|
|
|
+ // Verify the packet received.
|
|
|
+ EXPECT_EQ(DHCP6_CLIENT_PORT, forwarded->getRemotePort());
|
|
|
+ EXPECT_EQ(forwarded->getType(), pkt->getType());
|
|
|
+ EXPECT_TRUE(forwarded->getOption(D6O_DHCPV4_MSG));
|
|
|
+ EXPECT_EQ("eth0", forwarded->getIface());
|
|
|
+ EXPECT_EQ("2001:db8:1::123", forwarded->getRemoteAddr().toText());
|
|
|
+ EXPECT_EQ(DHCP6_CLIENT_PORT, forwarded->getRemotePort());
|
|
|
+
|
|
|
+ // Verify statistics
|
|
|
+ pkt6_snd = mgr.getObservation("pkt6-sent");
|
|
|
+ d4_resp = mgr.getObservation("pkt6-dhcpv4-response-sent");
|
|
|
+ ASSERT_TRUE(pkt6_snd);
|
|
|
+ ASSERT_TRUE(d4_resp);
|
|
|
+ EXPECT_EQ(1, pkt6_snd->getInteger().first);
|
|
|
+ EXPECT_EQ(1, d4_resp->getInteger().first);
|
|
|
}
|
|
|
|
|
|
} // end of anonymous namespace
|