Browse Source

[3181] Added common function to create DHCPv6 Release and Renew messages

Marcin Siodelski 11 years ago
parent
commit
ae4c064443

+ 28 - 13
tests/tools/perfdhcp/test_control.cc

@@ -316,28 +316,43 @@ TestControl::checkExitConditions() const {
 }
 
 Pkt6Ptr
-TestControl::createRenew(const Pkt6Ptr& reply) {
+TestControl::createMessageFromReply(const uint16_t msg_type,
+                                    const dhcp::Pkt6Ptr& reply) {
+    // Restrict messages to Release and Renew.
+    if (msg_type != DHCPV6_RENEW && msg_type != DHCPV6_RELEASE) {
+        isc_throw(isc::BadValue, "invalid message type " << msg_type
+                  << " to be created from Reply, expected DHCPV6_RENEW or"
+                  " DHCPV6_RELEASE");
+    }
+    // Get the string representation of the message - to be used for error
+    // logging purposes.
+    const char* msg_type_str = (msg_type == DHCPV6_RENEW ? "Renew" : "Release");
+    // Reply message must be specified.
     if (!reply) {
-        isc_throw(isc::BadValue,"Unable to create Renew packet from the Reply packet"
-                  " because the instance of the Reply is NULL");
+        isc_throw(isc::BadValue, "Unable to create " << msg_type_str
+                  << " message from the Reply message because the instance of"
+                  " the Reply message is NULL");
     }
-    Pkt6Ptr renew(new Pkt6(DHCPV6_RENEW, generateTransid()));
+
+    Pkt6Ptr msg(new Pkt6(msg_type, generateTransid()));
     // Client id.
     OptionPtr opt_clientid = reply->getOption(D6O_CLIENTID);
     if (!opt_clientid) {
-        isc_throw(isc::Unexpected, "failed to create Renew packet because client id"
-                  " option has not been found in the Reply from the server");
+        isc_throw(isc::Unexpected, "failed to create " << msg_type_str
+                  << " message because client id option has not been found"
+                  " in the Reply message");
     }
-    renew->addOption(opt_clientid);
+    msg->addOption(opt_clientid);
     // Server id.
     OptionPtr opt_serverid = reply->getOption(D6O_SERVERID);
     if (!opt_serverid) {
-        isc_throw(isc::Unexpected, "failed to create Renew packet because server id"
-                  " option has not been found in the Reply from the server");
+        isc_throw(isc::Unexpected, "failed to create " << msg_type_str
+                  << " because server id option has not been found in the"
+                  " Reply message");
     }
-    renew->addOption(opt_serverid);
-    copyIaOptions(reply, renew);
-    return (renew);
+    msg->addOption(opt_serverid);
+    copyIaOptions(reply, msg);
+    return (msg);
 }
 
 OptionPtr
@@ -1557,7 +1572,7 @@ TestControl::sendRenew(const TestControlSocket& socket) {
     if (!reply) {
         return (false);
     }
-    Pkt6Ptr renew = createRenew(reply);
+    Pkt6Ptr renew = createMessageFromReply(DHCPV6_RENEW, reply);
     setDefaults6(socket, renew);
     renew->pack();
     IfaceMgr::instance().send(renew);

+ 15 - 5
tests/tools/perfdhcp/test_control.h

@@ -313,13 +313,23 @@ protected:
     /// has been reached.
     void cleanCachedPackets();
 
-    /// \brief Creates IPv6 packet using options from Reply packet.
+    /// \brief Creates DHCPv6 message from the Reply packet.
     ///
-    /// \param reply An instance of the Reply packet which contents should
-    /// be used to create an instance of the Renew packet.
+    /// This function creates DHCPv6 Renew or Release message using the
+    /// data from the Reply message by copying options from the Reply
+    /// message.
     ///
-    /// \return created Renew packet.
-    dhcp::Pkt6Ptr createRenew(const dhcp::Pkt6Ptr& reply);
+    /// \param msg_type A type of the message to be createad.
+    /// \param reply An instance of the Reply packet which contents should
+    /// be used to create an instance of the new message.
+    ///
+    /// \return created Release or Renew message
+    /// \throw isc::BadValue if the msg_type is neither DHCPV6_RENEW nor
+    /// DHCPV6_RELEASE or if the reply is NULL.
+    /// \throw isc::Unexpected if mandatory options are missing in the
+    /// Reply message.
+    dhcp::Pkt6Ptr createMessageFromReply(const uint16_t msg_type,
+                                         const dhcp::Pkt6Ptr& reply);
 
     /// \brief Factory function to create DHCPv6 ELAPSED_TIME option.
     ///

+ 76 - 51
tests/tools/perfdhcp/tests/test_control_unittest.cc

@@ -75,7 +75,7 @@ public:
     };
 
     using TestControl::checkExitConditions;
-    using TestControl::createRenew;
+    using TestControl::createMessageFromReply;
     using TestControl::factoryElapsedTime6;
     using TestControl::factoryGeneric;
     using TestControl::factoryIana6;
@@ -631,6 +631,73 @@ public:
         }
     }
 
+    /// \brief Test that the DHCPv4 Release or Renew message is created
+    /// correctly and comprises expected options.
+    ///
+    /// \param msg_type A type of the message to be tested: DHCPV6_RELEASE
+    /// or DHCPV6_RENEW.
+    void testCreateRenewRelease(const uint16_t msg_type) {
+        // This command line specifies that the Release/Renew messages should
+        // be sent with the same rate as the Solicit messages.
+        std::ostringstream s;
+        s << "perfdhcp -6 -l lo -r 10 ";
+        s << (msg_type == DHCPV6_RELEASE ? "-F" : "-f") << " 10 ";
+        s << "-R 10 -L 10547 -n 10 -e address-and-prefix ::1";
+        ASSERT_NO_THROW(processCmdLine(s.str()));
+        // Create a test controller class.
+        NakedTestControl tc;
+        // Set the transaction id generator which will be used by the
+        // createRenew or createRelease function to generate transaction id.
+        boost::shared_ptr<NakedTestControl::IncrementalGenerator>
+            generator(new NakedTestControl::IncrementalGenerator());
+        tc.setTransidGenerator(generator);
+
+        // Create a Reply packet. The createRelease or createReply function will
+        // need Reply packet to create a corresponding Release or Reply.
+        Pkt6Ptr reply = createReplyPkt6(1);
+
+        Pkt6Ptr msg;
+        // Check that the message is created.
+        ASSERT_NO_THROW(msg = tc.createMessageFromReply(msg_type, reply));
+
+        ASSERT_TRUE(msg);
+        // Check that the message type and transaction id is correct.
+        EXPECT_EQ(msg_type, msg->getType());
+        EXPECT_EQ(1, msg->getTransid());
+
+        // Check that the message has expected options. These are the same for
+        // Release and Renew.
+
+        // Client Identifier.
+        OptionPtr opt_clientid = msg->getOption(D6O_CLIENTID);
+        ASSERT_TRUE(opt_clientid);
+        EXPECT_TRUE(reply->getOption(D6O_CLIENTID)->getData() ==
+                    opt_clientid->getData());
+
+        // Server identifier
+        OptionPtr opt_serverid = msg->getOption(D6O_SERVERID);
+        ASSERT_TRUE(opt_serverid);
+        EXPECT_TRUE(reply->getOption(D6O_SERVERID)->getData() ==
+                opt_serverid->getData());
+
+        // IA_NA
+        OptionPtr opt_ia_na = msg->getOption(D6O_IA_NA);
+        ASSERT_TRUE(opt_ia_na);
+        EXPECT_TRUE(reply->getOption(D6O_IA_NA)->getData() ==
+                    opt_ia_na->getData());
+
+        // IA_PD
+        OptionPtr opt_ia_pd = msg->getOption(D6O_IA_PD);
+        ASSERT_TRUE(opt_ia_pd);
+        EXPECT_TRUE(reply->getOption(D6O_IA_PD)->getData() ==
+                    opt_ia_pd->getData());
+
+        // Make sure that exception is thrown if the Reply message is NULL.
+        EXPECT_THROW(tc.createMessageFromReply(msg_type, Pkt6Ptr()),
+                     isc::BadValue);
+
+    }
+
     /// \brief Parse command line string with CommandOptions.
     ///
     /// \param cmdline command line string to be parsed.
@@ -1331,58 +1398,16 @@ TEST_F(TestControlTest, processRenew) {
     EXPECT_EQ(0, renew_num);
 }
 
+// This test verifies that the DHCPV6 Renew message is created correctly
+// and that it comprises all required options.
 TEST_F(TestControlTest, createRenew) {
-    // This command line specifies that the Renew messages should be sent
-    // with the same rate as the Solicit messages.
-    ASSERT_NO_THROW(processCmdLine("perfdhcp -6 -l lo -r 10 -f 10 -R 10"
-                                   " -L 10547 -n 10 -e address-and-prefix"
-                                   " ::1"));
-    // Create a test controller class.
-    NakedTestControl tc;
-    // Set the transaction id generator because createRenew function requires
-    // it to generate the transaction id for the Renew packet.
-    boost::shared_ptr<NakedTestControl::IncrementalGenerator>
-        generator(new NakedTestControl::IncrementalGenerator());
-    tc.setTransidGenerator(generator);
-
-    // Create a Reply packet. The createRenew function will need Reply
-    // packet to create a corresponding Renew.
-    Pkt6Ptr reply = createReplyPkt6(1);
-    Pkt6Ptr renew;
-    // Check that Renew is created.
-    ASSERT_NO_THROW(renew = tc.createRenew(reply));
-    ASSERT_TRUE(renew);
-    EXPECT_EQ(DHCPV6_RENEW, renew->getType());
-    EXPECT_EQ(1, renew->getTransid());
-
-    // Now check that the Renew packet created, has expected options. The
-    // payload of these options should be the same as the payload of the
-    // options in the Reply.
-
-    // Client Identifier
-    OptionPtr opt_clientid = renew->getOption(D6O_CLIENTID);
-    ASSERT_TRUE(opt_clientid);
-    EXPECT_TRUE(reply->getOption(D6O_CLIENTID)->getData() ==
-                opt_clientid->getData());
-
-    // Server identifier
-    OptionPtr opt_serverid = renew->getOption(D6O_SERVERID);
-    ASSERT_TRUE(opt_serverid);
-    EXPECT_TRUE(reply->getOption(D6O_SERVERID)->getData() ==
-                opt_serverid->getData());
-
-    // IA_NA
-    OptionPtr opt_ia_na = renew->getOption(D6O_IA_NA);
-    ASSERT_TRUE(opt_ia_na);
-    EXPECT_TRUE(reply->getOption(D6O_IA_NA)->getData() ==
-                opt_ia_na->getData());
-
-    // IA_PD
-    OptionPtr opt_ia_pd = renew->getOption(D6O_IA_PD);
-    ASSERT_TRUE(opt_ia_pd);
-    EXPECT_TRUE(reply->getOption(D6O_IA_PD)->getData() ==
-                opt_ia_pd->getData());
+    testCreateRenewRelease(DHCPV6_RENEW);
+}
 
+// This test verifies that the DHCPv6 Release message is created correctly
+// and that it comprises all required options.
+TEST_F(TestControlTest, createRelease) {
+    testCreateRenewRelease(DHCPV6_RELEASE);
 }
 
 // This test verifies that the current timeout value for waiting for