]> git.ipfire.org Git - thirdparty/kea.git/commitdiff
[#3231] Core task 3 for perfmon
authorThomas Markwalder <tmark@isc.org>
Fri, 16 Feb 2024 19:13:29 +0000 (14:13 -0500)
committerThomas Markwalder <tmark@isc.org>
Tue, 20 Feb 2024 16:37:49 +0000 (11:37 -0500)
Add packet events and subnet callout argumments
to kea-dhcp4 and kea-dhcp6

src/bin/dhcp4/dhcp4_srv.*
    Dhcpv4Srv::runOne() - add mt_queued packet event to query in MT mode
    Dhcpv4Srv::processPacket() - add "process_started" event to query upon entry
    Dhcpv4Srv::processDhcp4Query() - pass selected subnet (if one) into processPacketPktSend()
    Dhcpv4Srv::sendResponseNoThrow() - add subnet parameter, pass it into processPacketPktSend9()
    Dhcpv4Srv::processPacketPktSend() - add subnet parameter, add "process_completed" event
    to query, add subnet to callout arguments

src/bin/dhcp4/tests/dhcp4_test_utils.cc
src/bin/dhcp4/tests/dhcp4_test_utils.h
src/bin/dhcp4/tests/hooks_unittest.cc
    Updates to verify packet events content add subnet4 callout argument

src/bin/dhcp6/dhcp6_srv.cc
    Dhcpv6Srv::runOne() - add mt_queued packet event to query in MT mode
    Dhcpv6Srv::processPacket() - add "process_started" event to query upon entry
    Dhcpv6Srv::processDhcp6Query() - pass selected subnet (if one) into processPacketPktSend()
    Dhcpv6Srv::sendResponseNoThrow() - add subnet parameter, pass it into processPacketPktSend9()
    Dhcpv6Srv::processPacketPktSend() - add subnet parameter, add "process_completed" event
    to query, add subnet to callout arguments

src/bin/dhcp6/tests/dhcp6_test_utils.cc
src/bin/dhcp6/tests/dhcp6_test_utils.h
src/bin/dhcp6/tests/hooks_unittest.cc
    Updates to verify packet events content add subnet4 callout argument

src/bin/dhcp4/dhcp4_hooks.dox
    Updated pkt4_send arguments

src/bin/dhcp6/dhcp6_hooks.dox
    Updated pkt6_send arguments

12 files changed:
src/bin/dhcp4/dhcp4_hooks.dox
src/bin/dhcp4/dhcp4_srv.cc
src/bin/dhcp4/dhcp4_srv.h
src/bin/dhcp4/tests/dhcp4_test_utils.cc
src/bin/dhcp4/tests/dhcp4_test_utils.h
src/bin/dhcp4/tests/hooks_unittest.cc
src/bin/dhcp6/dhcp6_hooks.dox
src/bin/dhcp6/dhcp6_srv.cc
src/bin/dhcp6/dhcp6_srv.h
src/bin/dhcp6/tests/dhcp6_test_utils.cc
src/bin/dhcp6/tests/dhcp6_test_utils.h
src/bin/dhcp6/tests/hooks_unittest.cc

index 4fe12b613fcde01fd3676e8567cd4ca5fdcd2235..3b24ad5bda85f419f3f8fb0d6a449e74052d031a 100644 (file)
@@ -370,11 +370,12 @@ called before "subnet4_select".
 @subsection dhcpv4HooksPkt4Send pkt4_send
 
  - @b Arguments:
-   - name: @b response4, type: isc::dhcp::Pkt4Ptr, direction: <b>in/out</b>
    - name: @b query4, type: isc::dhcp::Pkt4Ptr, direction: <b>in</b>
+   - name: @b response4, type: isc::dhcp::Pkt4Ptr, direction: <b>in/out</b>
+   - name: @b subnet4, type: isc::dhcp::Subnet4Ptr, direction: <b>in</b>
 
  - @b Description: this callout is executed when server's response
-   is about to be sent back to the client. The sole argument "response4"
+   is about to be sent back to the client. The argument "response4"
    contains a pointer to an isc::dhcp::Pkt4 object carrying the
    packet, with source and destination addresses set, interface over which
    it will be sent, and a list of all options and relay information.  All fields
@@ -385,6 +386,8 @@ called before "subnet4_select".
    The argument query4 contains a pointer to the corresponding query packet
    (allowing to perform correlation between response and query). This object
    cannot be modified.
+   The argument subnet4 contains a pointer to the selected subnet (if one).
+   This object cannot be modified.
 
  - <b>Next step action</b>: if any callout installed on the "pkt4_send" hook
    sets the next step action to SKIP, the server will not construct the raw
index b4222860345bd2ff760f6ffdaf2dc7913a014d9f..c0ae4630cebd0241543cfe0109b2062b4a8cded1 100644 (file)
@@ -1100,6 +1100,7 @@ Dhcpv4Srv::runOne() {
         return;
     } else {
         if (MultiThreadingMgr::instance().getMode()) {
+            query->addPktEvent("mt_queued");
             typedef function<void()> CallBack;
             boost::shared_ptr<CallBack> call_back =
                 boost::make_shared<CallBack>(std::bind(&Dhcpv4Srv::processPacketAndSendResponseNoThrow,
@@ -1134,11 +1135,14 @@ Dhcpv4Srv::processPacketAndSendResponse(Pkt4Ptr& query) {
     }
 
     CalloutHandlePtr callout_handle = getCalloutHandle(query);
+
     processPacketBufferSend(callout_handle, rsp);
 }
 
 void
 Dhcpv4Srv::processPacket(Pkt4Ptr& query, Pkt4Ptr& rsp, bool allow_packet_park) {
+    query->addPktEvent("process_started");
+
     // All packets belong to ALL.
     query->addClass("ALL");
 
@@ -1550,12 +1554,12 @@ Dhcpv4Srv::processDhcp4Query(Pkt4Ptr& query, Pkt4Ptr& rsp,
                             typedef function<void()> CallBack;
                             boost::shared_ptr<CallBack> call_back = boost::make_shared<CallBack>(
                                 std::bind(&Dhcpv4Srv::sendResponseNoThrow, this, callout_handle,
-                                          query, rsp));
+                                          query, rsp, ctx->subnet_));
                             callout_handle_state->on_completion_ = [call_back]() {
                                 MultiThreadingMgr::instance().getThreadPool().add(call_back);
                             };
                         } else {
-                            processPacketPktSend(callout_handle, query, rsp);
+                            processPacketPktSend(callout_handle, query, rsp, ctx->subnet_);
                             processPacketBufferSend(callout_handle, rsp);
                         }
                     });
@@ -1596,15 +1600,16 @@ Dhcpv4Srv::processDhcp4Query(Pkt4Ptr& query, Pkt4Ptr& rsp,
 
     // If we have a response prep it for shipment.
     if (rsp) {
-        processPacketPktSend(callout_handle, query, rsp);
+        Subnet4Ptr subnet = (ctx ? ctx->subnet_ : Subnet4Ptr());
+        processPacketPktSend(callout_handle, query, rsp, subnet);
     }
 }
 
 void
 Dhcpv4Srv::sendResponseNoThrow(hooks::CalloutHandlePtr& callout_handle,
-                               Pkt4Ptr& query, Pkt4Ptr& rsp) {
+                               Pkt4Ptr& query, Pkt4Ptr& rsp, Subnet4Ptr& subnet) {
     try {
-            processPacketPktSend(callout_handle, query, rsp);
+            processPacketPktSend(callout_handle, query, rsp, subnet);
             processPacketBufferSend(callout_handle, rsp);
         } catch (const std::exception& e) {
             LOG_ERROR(packet4_logger, DHCP4_PACKET_PROCESS_STD_EXCEPTION)
@@ -1616,7 +1621,8 @@ Dhcpv4Srv::sendResponseNoThrow(hooks::CalloutHandlePtr& callout_handle,
 
 void
 Dhcpv4Srv::processPacketPktSend(hooks::CalloutHandlePtr& callout_handle,
-                                Pkt4Ptr& query, Pkt4Ptr& rsp) {
+                                Pkt4Ptr& query, Pkt4Ptr& rsp, Subnet4Ptr& subnet) {
+    query->addPktEvent("process_completed");
     if (!rsp) {
         return;
     }
@@ -1643,6 +1649,9 @@ Dhcpv4Srv::processPacketPktSend(hooks::CalloutHandlePtr& callout_handle,
         // Set our response
         callout_handle->setArgument("response4", rsp);
 
+        // Pass in the selected subnet.
+        callout_handle->setArgument("subnet4", subnet);
+
         // Call all installed callouts
         HooksManager::callCallouts(Hooks.hook_index_pkt4_send_,
                                    *callout_handle);
index 0ed55adfe514437972dde555ead9d293fe593bde..b2c100e7694f7f30c01bc2cb8665872782634a11 100644 (file)
@@ -359,8 +359,9 @@ public:
     /// @param callout_handle pointer to the callout handle.
     /// @param query A pointer to the packet to be processed.
     /// @param rsp A pointer to the response.
+    /// @param subnet A pointer to selected subnet.
     void sendResponseNoThrow(hooks::CalloutHandlePtr& callout_handle,
-                             Pkt4Ptr& query, Pkt4Ptr& rsp);
+                             Pkt4Ptr& query, Pkt4Ptr& rsp, Subnet4Ptr& subnet);
 
     /// @brief Process a single incoming DHCPv4 packet.
     ///
@@ -1115,8 +1116,9 @@ protected:
     /// @param callout_handle pointer to the callout handle.
     /// @param query Pointer to a query.
     /// @param rsp Pointer to a response.
+    /// @param subnet A pointer to selected subnet.
     void processPacketPktSend(hooks::CalloutHandlePtr& callout_handle,
-                              Pkt4Ptr& query, Pkt4Ptr& rsp);
+                              Pkt4Ptr& query, Pkt4Ptr& rsp, Subnet4Ptr& subnet);
 
     /// @brief Executes buffer4_send callout and sends the response.
     ///
index c3aa7c44c89530d4dbb04f22c834713f8d53467a..798babfdb516850aa29eefed4a41c5008d5ef0ee 100644 (file)
@@ -33,6 +33,7 @@ using namespace std;
 using namespace isc::asiolink;
 using namespace isc::data;
 using namespace isc::util;
+using namespace boost::posix_time;
 
 namespace isc {
 namespace dhcp {
@@ -57,7 +58,7 @@ BaseServerTest::~BaseServerTest() {
 }
 
 Dhcpv4SrvTest::Dhcpv4SrvTest()
-    : rcode_(-1), srv_(0), multi_threading_(false) {
+    : rcode_(-1), srv_(0), multi_threading_(false), start_time_(PktEvent::now()) {
 
     // Wipe any existing statistics
     isc::stats::StatsMgr::instance().removeAll();
@@ -1006,6 +1007,21 @@ Dhcpv4SrvTest::pretendReceivingPkt(NakedDhcpv4Srv& srv, const std::string& confi
     EXPECT_EQ(1, tested_stat->getInteger().first);
 }
 
+void
+Dhcpv4SrvTest::checkPktEvents(const PktPtr& msg,
+                             std::list<std::string> expected_events) {
+    ASSERT_NE(start_time_, PktEvent::EMPTY_TIME());
+    auto events = msg->getPktEvents();
+    ASSERT_EQ(events.size(), expected_events.size());
+    ptime prev_time = start_time_;
+    auto expected_event = expected_events.begin();
+    for (const auto& event : events) {
+        ASSERT_EQ(event.label_, *expected_event);
+        EXPECT_GE(event.timestamp_, prev_time);
+        ++expected_event;
+    }
+}
+
 } // end of isc::dhcp::test namespace
 } // end of isc::dhcp namespace
 } // end of isc namespace
index 794cbfa86c6ca965e28bd3f0592407bbd1b272c2..d220f043869b10d6d3654c075d9a19d0aea9c7b7 100644 (file)
@@ -192,6 +192,8 @@ public:
     ///
     /// See fake_received_ field for description
     void fakeReceive(const Pkt4Ptr& pkt) {
+        pkt->addPktEvent(PktEvent::SOCKET_RECEIVED);
+        pkt->addPktEvent(PktEvent::BUFFER_READ);
         fake_received_.push_back(pkt);
     }
 
@@ -679,6 +681,16 @@ public:
         multi_threading_ = enabled;
     }
 
+    /// @brief Checks the contents of a packet's event stack agains a list
+    /// of expected events.
+    ///
+    /// @param msg pointer to the packet under test.
+    /// @param start_time system time prior to or equal to the timestamp
+    /// of the stack's first event (i.e. before packet was sent or received)
+    /// @param expected_events a list of the event labels in the order they
+    /// are expected to occur in the stack.
+    void checkPktEvents(const PktPtr& msg, std::list<std::string> expected_events);
+
     /// @brief A subnet used in most tests.
     Subnet4Ptr subnet_;
 
@@ -699,6 +711,9 @@ public:
 
     /// @brief The multi-threading flag.
     bool multi_threading_;
+
+    /// @brief Time the test started (UTC/microseconds)
+    boost::posix_time::ptime start_time_;
 };
 
 /// @brief Patch the server config to add interface-config/re-detect=false
index aa94f8eba76bfb4874da2f4144d7f9df7673d0f0..95fa3d386c144c81bd0595604fec29b4a82df410 100644 (file)
@@ -1536,6 +1536,7 @@ TEST_F(HooksDhcpv4SrvTest, pkt4SendSimple) {
     vector<string> expected_argument_names;
     expected_argument_names.push_back(string("query4"));
     expected_argument_names.push_back(string("response4"));
+    expected_argument_names.push_back(string("subnet4"));
     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_);
@@ -1544,6 +1545,14 @@ TEST_F(HooksDhcpv4SrvTest, pkt4SendSimple) {
     EXPECT_TRUE(callback_qry_options_copy_);
     EXPECT_TRUE(callback_resp_options_copy_);
 
+    // Verify that packet sent to callout had the expected packet events.
+    std::list<std::string> expected_events;
+    expected_events.push_back(PktEvent::SOCKET_RECEIVED);
+    expected_events.push_back(PktEvent::BUFFER_READ);
+    expected_events.push_back("process_started");
+    expected_events.push_back("process_completed");
+    checkPktEvents(callback_qry_pkt4_, expected_events);
+
     // Check if the callout handle state was reset after the callout.
     checkCalloutHandleReset(discover);
 }
index 4c5af6ff8bc410ef7cab88b91199b4350d56d88d..29fc2a0ec42913e3cdabf4dd362470f68eb6468e 100644 (file)
@@ -378,9 +378,10 @@ called before "subnet6_select".
  - @b Arguments:
    - name: @b query6, type: isc::dhcp::Pkt6Ptr, direction: <b>in</b>
    - name: @b response6, type: isc::dhcp::Pkt6Ptr, direction: <b>in/out</b>
+   - name: @b subnet6, type: isc::dhcp::Subnet6Ptr, direction: <b>in/out</b>
 
  - @b Description: This callout is executed when server's response
-   is about to be send back to the client. The sole argument "response6"
+   is about to be send back to the client. The argument "response6"
    contains a pointer to an @c isc::dhcp::Pkt6 object that contains the
    packet, with set source and destination addresses, interface over which
    it will be send, list of all options and relay information.  All fields
@@ -388,6 +389,12 @@ called before "subnet6_select".
    noted that unless the callout sets the skip flag (see below), anything
    placed in the @c buffer_out_ field will be overwritten when the callout
    returns. (buffer_out_ is scratch space used for constructing the packet.)
+   The argument query6 contains a pointer to the corresponding query packet
+   (allowing to perform correlation between response and query). This object
+   cannot be modified.
+   The argument subnet6 contains a pointer to the selected subnet (if one).
+   This object cannot be modified.
+
 
  - <b>Next step status</b>: If any callout sets the status to SKIP, the server
    will assume that the callout did pack the "transaction-id", "message type"
index 6f5574a1c67fadd437a1e1881833653c570bf2f7..fae5e93429a40d6343ec33f3961bd13e6c66f472 100644 (file)
@@ -693,6 +693,7 @@ Dhcpv6Srv::runOne() {
         return;
     } else {
         if (MultiThreadingMgr::instance().getMode()) {
+            query->addPktEvent("mt_queued");
             typedef function<void()> CallBack;
             boost::shared_ptr<CallBack> call_back =
                 boost::make_shared<CallBack>(std::bind(&Dhcpv6Srv::processPacketAndSendResponseNoThrow,
@@ -731,6 +732,8 @@ Dhcpv6Srv::processPacketAndSendResponse(Pkt6Ptr query) {
 
 Pkt6Ptr
 Dhcpv6Srv::processPacket(Pkt6Ptr query) {
+    query->addPktEvent("process_started");
+
     // All packets belong to ALL.
     query->addClass("ALL");
 
@@ -1228,18 +1231,19 @@ Dhcpv6Srv::processLocalizedQuery6(AllocEngine::ClientContext6& ctx) {
         // the callback (i.e. drop) unless the callout status is set to
         // NEXT_STEP_PARK.  Otherwise the callback we bind here will be
         // executed when the hook library unparks the packet.
+        Subnet6Ptr subnet = ctx.subnet_;
         HooksManager::park("leases6_committed", query,
-        [this, callout_handle, query, rsp, callout_handle_state]() mutable {
+        [this, callout_handle, query, rsp, callout_handle_state, subnet]() mutable {
             if (MultiThreadingMgr::instance().getMode()) {
                 typedef function<void()> CallBack;
                 boost::shared_ptr<CallBack> call_back =
                     boost::make_shared<CallBack>(std::bind(&Dhcpv6Srv::sendResponseNoThrow,
-                                                           this, callout_handle, query, rsp));
+                                                           this, callout_handle, query, rsp, subnet));
                 callout_handle_state->on_completion_ = [call_back]() {
                     MultiThreadingMgr::instance().getThreadPool().add(call_back);
                 };
             } else {
-                processPacketPktSend(callout_handle, query, rsp);
+                processPacketPktSend(callout_handle, query, rsp, subnet);
                 processPacketBufferSend(callout_handle, rsp);
             }
         });
@@ -1275,7 +1279,7 @@ Dhcpv6Srv::processLocalizedQuery6(AllocEngine::ClientContext6& ctx) {
 
     // If we have a response prep it for shipment.
     if (rsp) {
-        processPacketPktSend(callout_handle, query, rsp);
+        processPacketPktSend(callout_handle, query, rsp, ctx.subnet_);
     }
 
     return (rsp);
@@ -1283,9 +1287,9 @@ Dhcpv6Srv::processLocalizedQuery6(AllocEngine::ClientContext6& ctx) {
 
 void
 Dhcpv6Srv::sendResponseNoThrow(hooks::CalloutHandlePtr& callout_handle,
-                               Pkt6Ptr query, Pkt6Ptr& rsp) {
+                               Pkt6Ptr query, Pkt6Ptr& rsp, Subnet6Ptr& subnet) {
     try {
-            processPacketPktSend(callout_handle, query, rsp);
+            processPacketPktSend(callout_handle, query, rsp, subnet);
             processPacketBufferSend(callout_handle, rsp);
         } catch (const std::exception& e) {
             LOG_ERROR(packet6_logger, DHCP6_PACKET_PROCESS_STD_EXCEPTION)
@@ -1297,7 +1301,8 @@ Dhcpv6Srv::sendResponseNoThrow(hooks::CalloutHandlePtr& callout_handle,
 
 void
 Dhcpv6Srv::processPacketPktSend(hooks::CalloutHandlePtr& callout_handle,
-                                Pkt6Ptr& query, Pkt6Ptr& rsp) {
+                                Pkt6Ptr& query, Pkt6Ptr& rsp, Subnet6Ptr& subnet) {
+    query->addPktEvent("process_completed");
     if (!rsp) {
         return;
     }
@@ -1326,6 +1331,9 @@ Dhcpv6Srv::processPacketPktSend(hooks::CalloutHandlePtr& callout_handle,
         // Set our response
         callout_handle->setArgument("response6", rsp);
 
+        // Pass the selected subnet as an argument.
+        callout_handle->setArgument("subnet6", subnet);
+
         // Call all installed callouts
         HooksManager::callCallouts(Hooks.hook_index_pkt6_send_, *callout_handle);
 
index 1a124151af33d74d0269d081b376d2cfb5de85a1..a7608e34b20ed3d5da61aea600c7a81e7ca6c097 100644 (file)
@@ -170,8 +170,9 @@ public:
     /// @param callout_handle pointer to the callout handle.
     /// @param query A pointer to the packet to be processed.
     /// @param rsp A pointer to the response.
+    /// @param subnet A pointer to the selected subnet.
     void sendResponseNoThrow(hooks::CalloutHandlePtr& callout_handle,
-                             Pkt6Ptr query, Pkt6Ptr& rsp);
+                             Pkt6Ptr query, Pkt6Ptr& rsp, Subnet6Ptr& subnet);
 
     /// @brief Process a single incoming DHCPv6 packet.
     ///
@@ -1201,8 +1202,9 @@ protected:
     /// @param callout_handle pointer to the callout handle.
     /// @param query Pointer to a query.
     /// @param rsp Pointer to a response.
+    /// @param subnet A pointer to the selected subnet.
     void processPacketPktSend(hooks::CalloutHandlePtr& callout_handle,
-                              Pkt6Ptr& query, Pkt6Ptr& rsp);
+                              Pkt6Ptr& query, Pkt6Ptr& rsp, Subnet6Ptr& subnet);
 
     /// @brief Allocation Engine.
     /// Pointer to the allocation engine that we are currently using
index a10900db132147f4d2841c5e88b15263fccd00a7..2293cbacb3a26ff16d3f9ede7827284dceeee955 100644 (file)
@@ -24,6 +24,7 @@ using namespace isc::dhcp;
 using namespace isc::asiolink;
 using namespace isc::stats;
 using namespace isc::util;
+using namespace boost::posix_time;
 
 namespace isc {
 namespace dhcp {
@@ -1054,7 +1055,7 @@ Dhcpv6SrvTest::configure(const std::string& config,
 }
 
 NakedDhcpv6SrvTest::NakedDhcpv6SrvTest()
-    : rcode_(-1) {
+    : rcode_(-1), start_time_(PktEvent::now()) {
     // it's ok if that fails. There should not be such a file anyway
     static_cast<void>(remove(DUID_FILE));
 
@@ -1106,6 +1107,21 @@ NakedDhcpv6SrvTest::generateIA(uint16_t type, uint32_t iaid, uint32_t t1,
     return (ia);
 }
 
+void
+NakedDhcpv6SrvTest::checkPktEvents(const PktPtr& msg,
+                             std::list<std::string> expected_events) {
+    ASSERT_NE(start_time_, PktEvent::EMPTY_TIME());
+    auto events = msg->getPktEvents();
+    ASSERT_EQ(events.size(), expected_events.size());
+    ptime prev_time = start_time_;
+    auto expected_event = expected_events.begin();
+    for (const auto& event : events) {
+        ASSERT_EQ(event.label_, *expected_event);
+        EXPECT_GE(event.timestamp_, prev_time);
+        ++expected_event;
+    }
+}
+
 bool
 Dhcpv6SrvTest::compareOptions(const isc::dhcp::OptionPtr& option1,
                               const isc::dhcp::OptionPtr& option2) {
index 68b66456232af474c84034f04d54fc31dc7ea3fc..591a69d94ba514504f7602e696089bf74bf6bb40 100644 (file)
@@ -200,6 +200,9 @@ public:
     ///
     /// See fake_received_ field for description
     void fakeReceive(const isc::dhcp::Pkt6Ptr& pkt) {
+        // Add packet events normally set by PktFilter.
+        pkt->addPktEvent(PktEvent::SOCKET_RECEIVED);
+        pkt->addPktEvent(PktEvent::BUFFER_READ);
         fake_received_.push_back(pkt);
     }
 
@@ -549,6 +552,16 @@ public:
         EXPECT_EQ(expected_transid, rsp->getTransid());
     }
 
+    /// @brief Checks the contents of a packet's event stack agains a list
+    /// of expected events.
+    ///
+    /// @param msg pointer to the packet under test.
+    /// @param start_time system time prior to or equal to the timestamp
+    /// of the stack's first event (i.e. before packet was sent or received)
+    /// @param expected_events a list of the event labels in the order they
+    /// are expected to occur in the stack.
+    void checkPktEvents(const PktPtr& msg, std::list<std::string> expected_events);
+
     virtual ~NakedDhcpv6SrvTest();
 
     // A DUID used in most tests (typically as client-id)
@@ -562,6 +575,9 @@ public:
 
     // Index of a valid network interface
     unsigned int valid_ifindex_;
+
+    /// @brief Time the test started (UTC/microseconds)
+    boost::posix_time::ptime start_time_;
 };
 
 // We need to pass one reference to the Dhcp6Client, which is defined in
index 20ef2abcb8b98121b4c0246ac4584ca4fa1dae00..288ae8bd560c7c147a5c994f8ebd43416f988ad0 100644 (file)
@@ -402,6 +402,8 @@ public:
 
         callout_handle.getArgument("query6", callback_qry_pkt6_);
 
+        callout_handle.getArgument("subnet6", callback_subnet6_);
+
         callback_argument_names_ = callout_handle.getArgumentNames();
 
         if (callback_qry_pkt6_) {
@@ -1444,12 +1446,21 @@ TEST_F(HooksDhcpv6SrvTest, pkt6SendSimple) {
     vector<string> expected_argument_names;
     expected_argument_names.push_back(string("query6"));
     expected_argument_names.push_back(string("response6"));
+    expected_argument_names.push_back(string("subnet6"));
     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_);
 
+    // Verify that packet sent to callout has the expected packet events.
+    std::list<std::string> expected_events;
+    expected_events.push_back(PktEvent::SOCKET_RECEIVED);
+    expected_events.push_back(PktEvent::BUFFER_READ);
+    expected_events.push_back("process_started");
+    expected_events.push_back("process_completed");
+    checkPktEvents(callback_qry_pkt6_, expected_events);
+
     // Check if the callout handle state was reset after the callout.
     checkCalloutHandleReset(sol);
 }