Browse Source

[2995] Changes after review.

Tomek Mrugalski 12 years ago
parent
commit
0d98fbf5f9
3 changed files with 105 additions and 44 deletions
  1. 4 4
      src/bin/dhcp6/dhcp6_hooks.dox
  2. 27 9
      src/bin/dhcp6/dhcp6_srv.cc
  3. 74 31
      src/bin/dhcp6/tests/dhcp6_srv_unittest.cc

+ 4 - 4
src/bin/dhcp6/dhcp6_hooks.dox

@@ -19,7 +19,7 @@
  BIND10 features an API (the "Hooks" API) that allows user-written code to
  BIND10 features an API (the "Hooks" API) that allows user-written code to
  be integrated into BIND 10 and called at specific points in its processing.
  be integrated into BIND 10 and called at specific points in its processing.
  An overview of the API and a tutorial for writing generalised hook code can
  An overview of the API and a tutorial for writing generalised hook code can
- API can be found in @ref hookDevelopersGuide.
+ API can be found in @ref hooksDevelopersGuide and @ref hooksComponentDeveloperGuide.
 
 
  This manual is more specialised and is aimed at developers of hook
  This manual is more specialised and is aimed at developers of hook
  code for the DHCPv6 server. It describes each hook point, the callouts
  code for the DHCPv6 server. It describes each hook point, the callouts
@@ -51,7 +51,7 @@ packet processing. Hook points that are not specific to packet processing
  @subsection dhcpv6HooksPkt6Receive pkt6_receive
  @subsection dhcpv6HooksPkt6Receive pkt6_receive
 
 
  - @b Arguments:
  - @b Arguments:
-   - name: @b pkt6, type: isc::dhcp::Pkt6Ptr, direction: <b>in/out</b>
+   - name: @b query6, type: isc::dhcp::Pkt6Ptr, direction: <b>in/out</b>
 
 
  - @b Description: this callout is executed when an incoming DHCPv6
  - @b Description: this callout is executed when an incoming DHCPv6
    packet is received and its content is parsed. The sole argument -
    packet is received and its content is parsed. The sole argument -
@@ -71,7 +71,7 @@ packet processing. Hook points that are not specific to packet processing
 @subsection dhcpv6HooksSubnet6Select subnet6_select
 @subsection dhcpv6HooksSubnet6Select subnet6_select
 
 
  - @b Arguments:
  - @b Arguments:
-   - name: @b pkt6, type: isc::dhcp::Pkt6Ptr, direction: <b>in/out</b>
+   - name: @b query6, type: isc::dhcp::Pkt6Ptr, direction: <b>in/out</b>
    - name: @b subnet6, type: isc::dhcp::Subnet6Ptr, direction: <b>in/out</b>
    - name: @b subnet6, type: isc::dhcp::Subnet6Ptr, direction: <b>in/out</b>
    - name: @b subnet6collection, type: const isc::dhcp::Subnet6Collection&, direction: <b>in</b>
    - name: @b subnet6collection, type: const isc::dhcp::Subnet6Collection&, direction: <b>in</b>
 
 
@@ -113,7 +113,7 @@ packet processing. Hook points that are not specific to packet processing
 @subsection dhcpv6HooksPkt6Send pkt6_send
 @subsection dhcpv6HooksPkt6Send pkt6_send
 
 
  - @b Arguments:
  - @b Arguments:
-   - name: @b pkt6, type: isc::dhcp::Pkt6Ptr, direction: <b>in/out</b>
+   - name: @b response6, type: isc::dhcp::Pkt6Ptr, direction: <b>in/out</b>
 
 
  - @b Description: this callout is executed when server's response
  - @b Description: this callout is executed when server's response
    is about to be send back to the client. The sole argument - pkt6 -
    is about to be send back to the client. The sole argument - pkt6 -

+ 27 - 9
src/bin/dhcp6/dhcp6_srv.cc

@@ -210,8 +210,13 @@ bool Dhcpv6Srv::run() {
             if (HooksManager::getHooksManager().calloutsPresent(hook_index_pkt6_receive_)) {
             if (HooksManager::getHooksManager().calloutsPresent(hook_index_pkt6_receive_)) {
                 CalloutHandlePtr callout_handle = getCalloutHandle(query);
                 CalloutHandlePtr callout_handle = getCalloutHandle(query);
 
 
-                // This is the first callout, so no need to clear any arguments
-                callout_handle->setArgument("pkt6", query);
+                // Delete previously set arguments
+                callout_handle->deleteAllArguments();
+
+                // Pass incoming packet as argument
+                callout_handle->setArgument("query6", query);
+
+                // Call callouts
                 HooksManager::getHooksManager().callCallouts(hook_index_pkt6_receive_,
                 HooksManager::getHooksManager().callCallouts(hook_index_pkt6_receive_,
                                                 *callout_handle);
                                                 *callout_handle);
 
 
@@ -223,7 +228,7 @@ bool Dhcpv6Srv::run() {
                     continue;
                     continue;
                 }
                 }
 
 
-                callout_handle->getArgument("pkt6", query);
+                callout_handle->getArgument("query6", query);
             }
             }
 
 
             try {
             try {
@@ -298,7 +303,7 @@ bool Dhcpv6Srv::run() {
 
 
                 // Execute all callouts registered for packet6_send
                 // Execute all callouts registered for packet6_send
                 if (HooksManager::getHooksManager().calloutsPresent(hook_index_pkt6_send_)) {
                 if (HooksManager::getHooksManager().calloutsPresent(hook_index_pkt6_send_)) {
-                    boost::shared_ptr<CalloutHandle> callout_handle = getCalloutHandle(query);
+                    CalloutHandlePtr callout_handle = getCalloutHandle(query);
 
 
                     // Delete all previous arguments
                     // Delete all previous arguments
                     callout_handle->deleteAllArguments();
                     callout_handle->deleteAllArguments();
@@ -307,7 +312,7 @@ bool Dhcpv6Srv::run() {
                     callout_handle->setSkip(false);
                     callout_handle->setSkip(false);
 
 
                     // Set our response
                     // Set our response
-                    callout_handle->setArgument("pkt6", rsp);
+                    callout_handle->setArgument("response6", rsp);
 
 
                     // Call all installed callouts
                     // Call all installed callouts
                     HooksManager::getHooksManager().callCallouts(hook_index_pkt6_send_,
                     HooksManager::getHooksManager().callCallouts(hook_index_pkt6_send_,
@@ -654,12 +659,17 @@ Dhcpv6Srv::selectSubnet(const Pkt6Ptr& question) {
 
 
     // Let's execute all callouts registered for packet_received
     // Let's execute all callouts registered for packet_received
     if (HooksManager::getHooksManager().calloutsPresent(hook_index_subnet6_select_)) {
     if (HooksManager::getHooksManager().calloutsPresent(hook_index_subnet6_select_)) {
-        boost::shared_ptr<CalloutHandle> callout_handle = getCalloutHandle(question);
+        CalloutHandlePtr callout_handle = getCalloutHandle(question);
+
+        // We're reusing callout_handle from previous calls
+        callout_handle->deleteAllArguments();
 
 
-        // This is the first callout, so no need to clear any arguments
-        callout_handle->setArgument("pkt6", question);
+        // Set new arguments
+        callout_handle->setArgument("query6", question);
         callout_handle->setArgument("subnet6", subnet);
         callout_handle->setArgument("subnet6", subnet);
         callout_handle->setArgument("subnet6collection", CfgMgr::instance().getSubnets6());
         callout_handle->setArgument("subnet6collection", CfgMgr::instance().getSubnets6());
+
+        // Call user (and server-side) callouts
         HooksManager::getHooksManager().callCallouts(hook_index_subnet6_select_,
         HooksManager::getHooksManager().callCallouts(hook_index_subnet6_select_,
                                         *callout_handle);
                                         *callout_handle);
 
 
@@ -1223,8 +1233,16 @@ Dhcpv6Srv::processInfRequest(const Pkt6Ptr& infRequest) {
 }
 }
 
 
 isc::hooks::CalloutHandlePtr Dhcpv6Srv::getCalloutHandle(const Pkt6Ptr& pkt) {
 isc::hooks::CalloutHandlePtr Dhcpv6Srv::getCalloutHandle(const Pkt6Ptr& pkt) {
-    CalloutHandlePtr callout_handle;
+    // This method returns a CalloutHandle for a given packet. It is guaranteed
+    // to return the same callout_handle (so user library contexts are
+    // preserved). This method works well if the server processes one packet
+    // at a time. Once the server architecture is extended to cover parallel
+    // packets processing (e.g. delayed-ack, some form of buffering etc.), this
+    // method has to be extended (e.g. store callouts in a map and use pkt as
+    // a key). Additional code would be required to release the callout handle
+    // once the server finished processing.
 
 
+    CalloutHandlePtr callout_handle;
     static Pkt6Ptr old_pointer;
     static Pkt6Ptr old_pointer;
 
 
     if (!callout_handle ||
     if (!callout_handle ||

+ 74 - 31
src/bin/dhcp6/tests/dhcp6_srv_unittest.cc

@@ -1831,11 +1831,17 @@ TEST_F(Dhcpv6SrvTest, Hooks) {
     NakedDhcpv6Srv srv(0);
     NakedDhcpv6Srv srv(0);
 
 
     // check if appropriate hooks are registered
     // check if appropriate hooks are registered
+    int hook_index_pkt6_received = -1;
+    int hook_index_select_subnet = -1;
+    int hook_index_pkt6_send     = -1;
 
 
     // check if appropriate indexes are set
     // check if appropriate indexes are set
-    int hook_index_pkt6_received = ServerHooks::getServerHooks().getIndex("pkt6_receive");
-    int hook_index_select_subnet = ServerHooks::getServerHooks().getIndex("subnet6_select");
-    int hook_index_pkt6_send     = ServerHooks::getServerHooks().getIndex("pkt6_send");
+    EXPECT_NO_THROW(hook_index_pkt6_received = ServerHooks::getServerHooks()
+                    .getIndex("pkt6_receive"));
+    EXPECT_NO_THROW(hook_index_select_subnet = ServerHooks::getServerHooks()
+                    .getIndex("subnet6_select"));
+    EXPECT_NO_THROW(hook_index_pkt6_send     = ServerHooks::getServerHooks()
+                    .getIndex("pkt6_send"));
 
 
     EXPECT_TRUE(hook_index_pkt6_received > 0);
     EXPECT_TRUE(hook_index_pkt6_received > 0);
     EXPECT_TRUE(hook_index_select_subnet > 0);
     EXPECT_TRUE(hook_index_select_subnet > 0);
@@ -1900,6 +1906,8 @@ Pkt6* captureSimpleSolicit() {
 class HooksDhcpv6SrvTest : public Dhcpv6SrvTest {
 class HooksDhcpv6SrvTest : public Dhcpv6SrvTest {
 
 
 public:
 public:
+
+    /// @brief creates Dhcpv6Srv and prepares buffers for callouts
     HooksDhcpv6SrvTest() {
     HooksDhcpv6SrvTest() {
 
 
         // Allocate new DHCPv6 Server
         // Allocate new DHCPv6 Server
@@ -1909,10 +1917,19 @@ public:
         resetCalloutBuffers();
         resetCalloutBuffers();
     }
     }
 
 
+    /// @brief destructor (deletes Dhcpv6Srv)
     ~HooksDhcpv6SrvTest() {
     ~HooksDhcpv6SrvTest() {
         delete srv_;
         delete srv_;
     }
     }
 
 
+    /// @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
+    ///
+    /// @param option_code code of option to be created
+    ///
+    /// @return pointer to create option object
     static OptionPtr createOption(uint16_t option_code) {
     static OptionPtr createOption(uint16_t option_code) {
 
 
         char payload[] = {
         char payload[] = {
@@ -1923,23 +1940,27 @@ public:
         return OptionPtr(new Option(Option::V6, option_code, tmp));
         return OptionPtr(new Option(Option::V6, option_code, tmp));
     }
     }
 
 
-    /// 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
     static int
     pkt6_receive_callout(CalloutHandle& callout_handle) {
     pkt6_receive_callout(CalloutHandle& callout_handle) {
         callback_name_ = string("pkt6_receive");
         callback_name_ = string("pkt6_receive");
 
 
-        callout_handle.getArgument("pkt6", callback_pkt6_);
+        callout_handle.getArgument("query6", callback_pkt6_);
 
 
         callback_argument_names_ = callout_handle.getArgumentNames();
         callback_argument_names_ = callout_handle.getArgumentNames();
         return (0);
         return (0);
     }
     }
 
 
-    // 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
     static int
     pkt6_receive_change_clientid(CalloutHandle& callout_handle) {
     pkt6_receive_change_clientid(CalloutHandle& callout_handle) {
 
 
         Pkt6Ptr pkt;
         Pkt6Ptr pkt;
-        callout_handle.getArgument("pkt6", pkt);
+        callout_handle.getArgument("query6", pkt);
 
 
         // get rid of the old client-id
         // get rid of the old client-id
         pkt->delOption(D6O_CLIENTID);
         pkt->delOption(D6O_CLIENTID);
@@ -1951,12 +1972,14 @@ public:
         return pkt6_receive_callout(callout_handle);
         return pkt6_receive_callout(callout_handle);
     }
     }
 
 
-    // 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
     static int
     pkt6_receive_delete_clientid(CalloutHandle& callout_handle) {
     pkt6_receive_delete_clientid(CalloutHandle& callout_handle) {
 
 
         Pkt6Ptr pkt;
         Pkt6Ptr pkt;
-        callout_handle.getArgument("pkt6", pkt);
+        callout_handle.getArgument("query6", pkt);
 
 
         // get rid of the old client-id
         // get rid of the old client-id
         pkt->delOption(D6O_CLIENTID);
         pkt->delOption(D6O_CLIENTID);
@@ -1965,12 +1988,14 @@ public:
         return pkt6_receive_callout(callout_handle);
         return pkt6_receive_callout(callout_handle);
     }
     }
 
 
-    // callback that sets skip flag
+    /// test callback that sets skip flag
+    /// @param callout_handle handle passed by the hooks framework
+    /// @return always 0
     static int
     static int
     pkt6_receive_skip(CalloutHandle& callout_handle) {
     pkt6_receive_skip(CalloutHandle& callout_handle) {
 
 
         Pkt6Ptr pkt;
         Pkt6Ptr pkt;
-        callout_handle.getArgument("pkt6", pkt);
+        callout_handle.getArgument("query6", pkt);
 
 
         callout_handle.setSkip(true);
         callout_handle.setSkip(true);
 
 
@@ -1978,23 +2003,27 @@ public:
         return pkt6_receive_callout(callout_handle);
         return pkt6_receive_callout(callout_handle);
     }
     }
 
 
-    // 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
     static int
     pkt6_send_callout(CalloutHandle& callout_handle) {
     pkt6_send_callout(CalloutHandle& callout_handle) {
         callback_name_ = string("pkt6_send");
         callback_name_ = string("pkt6_send");
 
 
-        callout_handle.getArgument("pkt6", callback_pkt6_);
+        callout_handle.getArgument("response6", callback_pkt6_);
 
 
         callback_argument_names_ = callout_handle.getArgumentNames();
         callback_argument_names_ = callout_handle.getArgumentNames();
         return (0);
         return (0);
     }
     }
 
 
-    // Callback that changes server-id
+    // Test callback that changes server-id
+    /// @param callout_handle handle passed by the hooks framework
+    /// @return always 0
     static int
     static int
     pkt6_send_change_serverid(CalloutHandle& callout_handle) {
     pkt6_send_change_serverid(CalloutHandle& callout_handle) {
 
 
         Pkt6Ptr pkt;
         Pkt6Ptr pkt;
-        callout_handle.getArgument("pkt6", pkt);
+        callout_handle.getArgument("response6", pkt);
 
 
         // get rid of the old server-id
         // get rid of the old server-id
         pkt->delOption(D6O_SERVERID);
         pkt->delOption(D6O_SERVERID);
@@ -2006,12 +2035,14 @@ public:
         return pkt6_send_callout(callout_handle);
         return pkt6_send_callout(callout_handle);
     }
     }
 
 
-    // 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
     static int
     pkt6_send_delete_serverid(CalloutHandle& callout_handle) {
     pkt6_send_delete_serverid(CalloutHandle& callout_handle) {
 
 
         Pkt6Ptr pkt;
         Pkt6Ptr pkt;
-        callout_handle.getArgument("pkt6", pkt);
+        callout_handle.getArgument("response6", pkt);
 
 
         // get rid of the old client-id
         // get rid of the old client-id
         pkt->delOption(D6O_SERVERID);
         pkt->delOption(D6O_SERVERID);
@@ -2020,12 +2051,14 @@ public:
         return pkt6_send_callout(callout_handle);
         return pkt6_send_callout(callout_handle);
     }
     }
 
 
-    // Callback that sets skip blag
+    /// Test callback that sets skip flag
+    /// @param callout_handle handle passed by the hooks framework
+    /// @return always 0
     static int
     static int
     pkt6_send_skip(CalloutHandle& callout_handle) {
     pkt6_send_skip(CalloutHandle& callout_handle) {
 
 
         Pkt6Ptr pkt;
         Pkt6Ptr pkt;
-        callout_handle.getArgument("pkt6", pkt);
+        callout_handle.getArgument("response6", pkt);
 
 
         callout_handle.setSkip(true);
         callout_handle.setSkip(true);
 
 
@@ -2033,12 +2066,14 @@ public:
         return pkt6_send_callout(callout_handle);
         return pkt6_send_callout(callout_handle);
     }
     }
 
 
-    // Callback that stores received callout name and subnet6 values
+    /// Test callback that stores received callout name and subnet6 values
+    /// @param callout_handle handle passed by the hooks framework
+    /// @return always 0
     static int
     static int
     subnet6_select_callout(CalloutHandle& callout_handle) {
     subnet6_select_callout(CalloutHandle& callout_handle) {
         callback_name_ = string("subnet6_select");
         callback_name_ = string("subnet6_select");
 
 
-        callout_handle.getArgument("pkt6", callback_pkt6_);
+        callout_handle.getArgument("query6", callback_pkt6_);
         callout_handle.getArgument("subnet6", callback_subnet6_);
         callout_handle.getArgument("subnet6", callback_subnet6_);
         callout_handle.getArgument("subnet6collection", callback_subnet6collection_);
         callout_handle.getArgument("subnet6collection", callback_subnet6collection_);
 
 
@@ -2046,7 +2081,9 @@ public:
         return (0);
         return (0);
     }
     }
 
 
-    // Callback that picks the other subnet if possible.
+    /// Test callback that picks the other subnet if possible.
+    /// @param callout_handle handle passed by the hooks framework
+    /// @return always 0
     static int
     static int
     subnet6_select_different_subnet_callout(CalloutHandle& callout_handle) {
     subnet6_select_different_subnet_callout(CalloutHandle& callout_handle) {
 
 
@@ -2067,6 +2104,7 @@ public:
         return (0);
         return (0);
     }
     }
 
 
+    /// resets buffers used to store data received by callouts
     void resetCalloutBuffers() {
     void resetCalloutBuffers() {
         callback_name_ = string("");
         callback_name_ = string("");
         callback_pkt6_.reset();
         callback_pkt6_.reset();
@@ -2075,28 +2113,33 @@ public:
         callback_argument_names_.clear();
         callback_argument_names_.clear();
     }
     }
 
 
+    /// pointer to Dhcpv6Srv that is used in tests
     NakedDhcpv6Srv* srv_;
     NakedDhcpv6Srv* srv_;
 
 
-    // Used in testing pkt6_receive_callout
-    static string callback_name_; ///< string name of the received callout
+    // The following fields are used in testing pkt6_receive_callout
+
+    /// String name of the received callout
+    static string callback_name_;
 
 
-    static Pkt6Ptr callback_pkt6_; ///< Pkt6 structure returned in the callout
+    /// Pkt6 structure returned in the callout
+    static Pkt6Ptr callback_pkt6_;
 
 
+    /// Pointer to a subnet received by callout
     static Subnet6Ptr callback_subnet6_;
     static Subnet6Ptr callback_subnet6_;
 
 
+    /// A list of all available subnets (received by callout)
     static Subnet6Collection callback_subnet6collection_;
     static Subnet6Collection callback_subnet6collection_;
 
 
+    /// A list of all received arguments
     static vector<string> callback_argument_names_;
     static vector<string> callback_argument_names_;
 };
 };
 
 
+// The following fields are used in testing pkt6_receive_callout.
+// See fields description in the class for details
 string HooksDhcpv6SrvTest::callback_name_;
 string HooksDhcpv6SrvTest::callback_name_;
-
 Pkt6Ptr HooksDhcpv6SrvTest::callback_pkt6_;
 Pkt6Ptr HooksDhcpv6SrvTest::callback_pkt6_;
-
 Subnet6Ptr HooksDhcpv6SrvTest::callback_subnet6_;
 Subnet6Ptr HooksDhcpv6SrvTest::callback_subnet6_;
-
 Subnet6Collection HooksDhcpv6SrvTest::callback_subnet6collection_;
 Subnet6Collection HooksDhcpv6SrvTest::callback_subnet6collection_;
-
 vector<string> HooksDhcpv6SrvTest::callback_argument_names_;
 vector<string> HooksDhcpv6SrvTest::callback_argument_names_;
 
 
 
 
@@ -2131,7 +2174,7 @@ TEST_F(HooksDhcpv6SrvTest, simple_pkt6_receive) {
 
 
     // Check that all expected parameters are there
     // Check that all expected parameters are there
     vector<string> expected_argument_names;
     vector<string> expected_argument_names;
-    expected_argument_names.push_back(string("pkt6"));
+    expected_argument_names.push_back(string("query6"));
 
 
     EXPECT_TRUE(expected_argument_names == callback_argument_names_);
     EXPECT_TRUE(expected_argument_names == callback_argument_names_);
 }
 }
@@ -2253,7 +2296,7 @@ TEST_F(HooksDhcpv6SrvTest, simple_pkt6_send) {
 
 
     // Check that all expected parameters are there
     // Check that all expected parameters are there
     vector<string> expected_argument_names;
     vector<string> expected_argument_names;
-    expected_argument_names.push_back(string("pkt6"));
+    expected_argument_names.push_back(string("response6"));
     EXPECT_TRUE(expected_argument_names == callback_argument_names_);
     EXPECT_TRUE(expected_argument_names == callback_argument_names_);
 }
 }