BIND 10 trac3183, updated. 235246a1c1aaf52a976896ab1bfc0df551abdb5a [3183] Send Renew messages.

BIND 10 source code commits bind10-changes at lists.isc.org
Tue Oct 8 10:56:23 UTC 2013


The branch, trac3183 has been updated
       via  235246a1c1aaf52a976896ab1bfc0df551abdb5a (commit)
      from  4527401f4afbd8f7a9dafb7296863d01da0d8c09 (commit)

Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.

- Log -----------------------------------------------------------------
commit 235246a1c1aaf52a976896ab1bfc0df551abdb5a
Author: Marcin Siodelski <marcin at isc.org>
Date:   Tue Oct 8 12:55:39 2013 +0200

    [3183] Send Renew messages.

-----------------------------------------------------------------------

Summary of changes:
 tests/tools/perfdhcp/command_options.h             |    5 +-
 tests/tools/perfdhcp/stats_mgr.h                   |   12 +-
 tests/tools/perfdhcp/test_control.cc               |   76 ++++++++-
 tests/tools/perfdhcp/test_control.h                |   48 +++++-
 .../tools/perfdhcp/tests/command_options_helper.h  |    8 +-
 .../tools/perfdhcp/tests/test_control_unittest.cc  |  180 ++++++++++++++++++--
 6 files changed, 299 insertions(+), 30 deletions(-)

-----------------------------------------------------------------------
diff --git a/tests/tools/perfdhcp/command_options.h b/tests/tools/perfdhcp/command_options.h
index 4912fc8..42a31c9 100644
--- a/tests/tools/perfdhcp/command_options.h
+++ b/tests/tools/perfdhcp/command_options.h
@@ -16,11 +16,12 @@
 #ifndef COMMAND_OPTIONS_H
 #define COMMAND_OPTIONS_H
 
+#include <boost/noncopyable.hpp>
+
+#include <stdint.h>
 #include <string>
 #include <vector>
 
-#include <boost/noncopyable.hpp>
-
 namespace isc {
 namespace perfdhcp {
 
diff --git a/tests/tools/perfdhcp/stats_mgr.h b/tests/tools/perfdhcp/stats_mgr.h
index d614ad0..3abcac3 100644
--- a/tests/tools/perfdhcp/stats_mgr.h
+++ b/tests/tools/perfdhcp/stats_mgr.h
@@ -15,8 +15,9 @@
 #ifndef STATS_MGR_H
 #define STATS_MGR_H
 
-#include <iostream>
-#include <map>
+#include <dhcp/pkt4.h>
+#include <dhcp/pkt6.h>
+#include <exceptions/exceptions.h>
 
 #include <boost/noncopyable.hpp>
 #include <boost/shared_ptr.hpp>
@@ -27,7 +28,9 @@
 #include <boost/multi_index/mem_fun.hpp>
 #include <boost/date_time/posix_time/posix_time.hpp>
 
-#include <exceptions/exceptions.h>
+#include <iostream>
+#include <map>
+
 
 namespace isc {
 namespace perfdhcp {
@@ -120,7 +123,8 @@ public:
         XCHG_DO,  ///< DHCPv4 DISCOVER-OFFER
         XCHG_RA,  ///< DHCPv4 REQUEST-ACK
         XCHG_SA,  ///< DHCPv6 SOLICIT-ADVERTISE
-        XCHG_RR   ///< DHCPv6 REQUEST-REPLY
+        XCHG_RR,  ///< DHCPv6 REQUEST-REPLY
+        XCHG_RN   ///< DHCPv6 RENEW-REPLY
     };
 
     /// \brief Exchange Statistics.
diff --git a/tests/tools/perfdhcp/test_control.cc b/tests/tools/perfdhcp/test_control.cc
index a126d51..398eade 100644
--- a/tests/tools/perfdhcp/test_control.cc
+++ b/tests/tools/perfdhcp/test_control.cc
@@ -283,6 +283,31 @@ TestControl::checkExitConditions() const {
     return (false);
 }
 
+Pkt6Ptr
+TestControl::createRenew(const Pkt6Ptr& reply) {
+    if (!reply) {
+        isc_throw(isc::BadValue,"Unable to create Renew packet from the Reply packet"
+                  " because the instance of the Reply is NULL");
+    }
+    Pkt6Ptr renew(new Pkt6(DHCPV6_RENEW, 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");
+    }
+    renew->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");
+    }
+    renew->addOption(opt_serverid);
+    copyIaOptions(reply, renew);
+    return (renew);
+}
+
 OptionPtr
 TestControl::factoryElapsedTime6(Option::Universe, uint16_t,
                                  const OptionBuffer& buf) {
@@ -616,6 +641,9 @@ TestControl::initializeStatsMgr() {
             stats_mgr6_->addExchangeStats(StatsMgr6::XCHG_RR,
                                           options.getDropTime()[1]);
         }
+        if (options.getRenewRate() != 0) {
+            stats_mgr6_->addExchangeStats(StatsMgr6::XCHG_RN);
+        }
     }
     if (testDiags('i')) {
         if (options.getIpVersion() == 4) {
@@ -769,6 +797,17 @@ TestControl::sendPackets(const TestControlSocket& socket,
     }
 }
 
+uint64_t
+TestControl::sendRenewPackets(const TestControlSocket& socket,
+                              const uint64_t packets_num) {
+    for (uint64_t i = 0; i < packets_num; ++i) {
+        if (!sendRenew(socket)) {
+            return (i);
+        }
+    }
+    return (packets_num);
+}
+
 void
 TestControl::printDiagnostics() const {
     CommandOptions& options = CommandOptions::instance();
@@ -1024,7 +1063,15 @@ TestControl::processReceivedPacket6(const TestControlSocket& socket,
             }
         }
     } else if (packet_type == DHCPV6_REPLY) {
-        stats_mgr6_->passRcvdPacket(StatsMgr6::XCHG_RR, pkt6);
+        Pkt6Ptr sent_packet = stats_mgr6_->passRcvdPacket(StatsMgr6::XCHG_RR,
+                                                          pkt6);
+        if (sent_packet) {
+            if (CommandOptions::instance().getRenewRate() != 0) {
+                reply_storage_.append(pkt6);
+            }
+        } else {
+            stats_mgr6_->passRcvdPacket(StatsMgr6::XCHG_RN, pkt6);
+        }
     }
 }
 
@@ -1249,6 +1296,15 @@ TestControl::run() {
         // Initiate new DHCP packet exchanges.
         sendPackets(socket, packets_due);
 
+        if ((options.getIpVersion() == 6) && (options.getRenewRate() != 0)) {
+            uint64_t renew_packets_due =
+                packets_due * options.getRenewRate() / options.getRate();
+            if (renew_packets_due == 0) {
+                renew_packets_due = 1;
+            }
+            sendRenewPackets(socket, renew_packets_due);
+        }
+
         // Report delay means that user requested printing number
         // of sent/received/dropped packets repeatedly.
         if (options.getReportDelay() > 0) {
@@ -1429,6 +1485,24 @@ TestControl::sendDiscover4(const TestControlSocket& socket,
     saveFirstPacket(pkt4);
 }
 
+bool
+TestControl::sendRenew(const TestControlSocket& socket) {
+    Pkt6Ptr reply = reply_storage_.getRandom();
+    if (!reply) {
+        return (false);
+    }
+    Pkt6Ptr renew = createRenew(reply);
+    setDefaults6(socket, renew);
+    renew->pack();
+    IfaceMgr::instance().send(renew);
+    if (!stats_mgr6_) {
+        isc_throw(Unexpected, "Statistics Manager for DHCPv6 "
+                  "hasn't been initialized");
+    }
+    stats_mgr6_->passSentPacket(StatsMgr6::XCHG_RN, renew);
+    return (true);
+}
+
 void
 TestControl::sendRequest4(const TestControlSocket& socket,
                           const dhcp::Pkt4Ptr& discover_pkt4,
diff --git a/tests/tools/perfdhcp/test_control.h b/tests/tools/perfdhcp/test_control.h
index 93509e6..5a87ac4 100644
--- a/tests/tools/perfdhcp/test_control.h
+++ b/tests/tools/perfdhcp/test_control.h
@@ -15,20 +15,21 @@
 #ifndef TEST_CONTROL_H
 #define TEST_CONTROL_H
 
-#include <string>
-#include <vector>
-
-#include <boost/noncopyable.hpp>
-#include <boost/shared_ptr.hpp>
-#include <boost/function.hpp>
-#include <boost/date_time/posix_time/posix_time.hpp>
+#include "packet_storage.h"
+#include "stats_mgr.h"
 
 #include <dhcp/iface_mgr.h>
 #include <dhcp/dhcp6.h>
 #include <dhcp/pkt4.h>
 #include <dhcp/pkt6.h>
 
-#include "stats_mgr.h"
+#include <boost/noncopyable.hpp>
+#include <boost/shared_ptr.hpp>
+#include <boost/function.hpp>
+#include <boost/date_time/posix_time/posix_time.hpp>
+
+#include <string>
+#include <vector>
 
 namespace isc {
 namespace perfdhcp {
@@ -299,6 +300,14 @@ protected:
     /// \return true if any of the exit conditions is fulfilled.
     bool checkExitConditions() const;
 
+    /// \brief Creates IPv6 packet using options from Reply packet.
+    ///
+    /// \param reply An instance of the Reply packet which contents should
+    /// be used to create an instance of the Renew packet.
+    ///
+    /// \return created Renew packet.
+    dhcp::Pkt6Ptr createRenew(const dhcp::Pkt6Ptr& reply);
+
     /// \brief Factory function to create DHCPv6 ELAPSED_TIME option.
     ///
     /// This factory function creates DHCPv6 ELAPSED_TIME option instance.
@@ -702,6 +711,27 @@ protected:
                      const uint64_t packets_num,
                      const bool preload = false);
 
+    /// \brief Send number of DHCPv6 Renew packets to the server.
+    ///
+    /// \param socket An object representing socket to be used to send packets.
+    /// \param packets_num A number of Renew packets to be send.
+    ///
+    /// \param A number of packets actually sent.
+    uint64_t sendRenewPackets(const TestControlSocket& socket,
+                          const uint64_t packets_num);
+
+    /// \brief Send a renew message using provided socket.
+    ///
+    /// This function will try to identify an existing lease for which a Renew
+    /// will be sent. If there is no lease that can be renewed this method will
+    /// return false.
+    ///
+    /// \param socket An object encapsulating socket to be used to send
+    /// a packet.
+    ///
+    /// \return true if packet has been sent, false otherwise.
+    bool sendRenew(const TestControlSocket& socket);
+
     /// \brief Send DHCPv4 REQUEST message.
     ///
     /// Method creates and sends DHCPv4 REQUEST message to the server.
@@ -1003,6 +1033,8 @@ private:
     StatsMgr4Ptr stats_mgr4_;  ///< Statistics Manager 4.
     StatsMgr6Ptr stats_mgr6_;  ///< Statistics Manager 6.
 
+    PacketStorage<dhcp::Pkt6> reply_storage_; ///< A storage for reply messages.
+
     NumberGeneratorPtr transid_gen_; ///< Transaction id generator.
     NumberGeneratorPtr macaddr_gen_; ///< Numbers generator for MAC address.
 
diff --git a/tests/tools/perfdhcp/tests/command_options_helper.h b/tests/tools/perfdhcp/tests/command_options_helper.h
index dbb5c42..afa0dd3 100644
--- a/tests/tools/perfdhcp/tests/command_options_helper.h
+++ b/tests/tools/perfdhcp/tests/command_options_helper.h
@@ -15,11 +15,15 @@
 #ifndef COMMAND_OPTIONS_HELPER_H
 #define COMMAND_OPTIONS_HELPER_H
 
+#include "../command_options.h"
+#include <exceptions/exceptions.h>
+
+#include <assert.h>
+#include <iterator>
+#include <cstring>
 #include <string>
 #include <vector>
 
-#include <exceptions/exceptions.h>
-#include "../command_options.h"
 
 namespace isc {
 namespace perfdhcp {
diff --git a/tests/tools/perfdhcp/tests/test_control_unittest.cc b/tests/tools/perfdhcp/tests/test_control_unittest.cc
index c0b7231..a6260ba 100644
--- a/tests/tools/perfdhcp/tests/test_control_unittest.cc
+++ b/tests/tools/perfdhcp/tests/test_control_unittest.cc
@@ -12,21 +12,22 @@
 // OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
 // PERFORMANCE OF THIS SOFTWARE.
 
+#include "command_options_helper.h"
+#include "../test_control.h"
+
+#include <asiolink/io_address.h>
+#include <exceptions/exceptions.h>
+#include <dhcp/dhcp4.h>
+#include <dhcp/iface_mgr.h>
+
+#include <boost/date_time/posix_time/posix_time.hpp>
+
 #include <cstddef>
 #include <stdint.h>
 #include <string>
 #include <fstream>
 #include <gtest/gtest.h>
 
-#include <boost/date_time/posix_time/posix_time.hpp>
-
-#include <exceptions/exceptions.h>
-#include <asiolink/io_address.h>
-#include <dhcp/dhcp4.h>
-#include <dhcp/iface_mgr.h>
-#include "command_options_helper.h"
-#include "../test_control.h"
-
 using namespace std;
 using namespace boost::posix_time;
 using namespace isc;
@@ -63,11 +64,18 @@ public:
         virtual uint32_t generate() {
             return (++transid_);
         }
+
+        /// \brief Return next transaction id value.
+        uint32_t getNext() const {
+            return (transid_ + 1);
+        }
+
     private:
         uint32_t transid_; ///< Last generated transaction id.
     };
 
     using TestControl::checkExitConditions;
+    using TestControl::createRenew;
     using TestControl::factoryElapsedTime6;
     using TestControl::factoryGeneric;
     using TestControl::factoryIana6;
@@ -85,6 +93,9 @@ public:
     using TestControl::processReceivedPacket6;
     using TestControl::registerOptionFactories;
     using TestControl::sendDiscover4;
+    using TestControl::sendPackets;
+    using TestControl::sendRenewPackets;
+    using TestControl::sendRequest6;
     using TestControl::sendSolicit6;
     using TestControl::setDefaults4;
     using TestControl::setDefaults6;
@@ -281,7 +292,7 @@ public:
         return (cnt);
     }
 
-    /// brief Test generation of mulitple DUIDs
+    /// \brief Test generation of mulitple DUIDs
     ///
     /// This method checks the generation of multiple DUIDs. Number
     /// of iterations depends on the number of simulated clients.
@@ -624,7 +635,6 @@ public:
         CommandOptionsHelper::process(cmdline);
     }
 
-private:
     /// \brief Create DHCPv4 OFFER packet.
     ///
     /// \param transid transaction id.
@@ -645,8 +655,8 @@ private:
     ///
     /// \param transid transaction id.
     /// \return instance of the packet.
-    boost::shared_ptr<Pkt6>
-    createAdvertisePkt6(uint32_t transid) const {
+    Pkt6Ptr
+    createAdvertisePkt6(const uint32_t transid) const {
         boost::shared_ptr<Pkt6> advertise(new Pkt6(DHCPV6_ADVERTISE, transid));
         // Add IA_NA if requested by the client.
         if (CommandOptions::instance().getLeaseType()
@@ -671,6 +681,33 @@ private:
         return (advertise);
     }
 
+    Pkt6Ptr
+    createReplyPkt6(const uint32_t transid) const {
+        Pkt6Ptr reply(new Pkt6(DHCPV6_REPLY, transid));
+        // Add IA_NA if requested by the client.
+        if (CommandOptions::instance().getLeaseType()
+            .includes(CommandOptions::LeaseType::ADDRESS)) {
+            OptionPtr opt_ia_na = Option::factory(Option::V6, D6O_IA_NA);
+            reply->addOption(opt_ia_na);
+        }
+        // Add IA_PD if requested by the client.
+        if (CommandOptions::instance().getLeaseType()
+            .includes(CommandOptions::LeaseType::PREFIX)) {
+            OptionPtr opt_ia_pd = Option::factory(Option::V6, D6O_IA_PD);
+            reply->addOption(opt_ia_pd);
+        }
+        OptionPtr opt_serverid(new Option(Option::V6, D6O_SERVERID));
+        NakedTestControl tc;
+        uint8_t randomized = 0;
+        std::vector<uint8_t> duid(tc.generateDuid(randomized));
+        OptionPtr opt_clientid(Option::factory(Option::V6, D6O_CLIENTID, duid));
+        reply->addOption(opt_serverid);
+        reply->addOption(opt_clientid);
+        reply->updateTimestamp();
+        return (reply);
+
+    }
+
 };
 
 TEST_F(TestControlTest, GenerateDuid) {
@@ -1213,3 +1250,120 @@ TEST_F(TestControlTest, RateControl) {
     EXPECT_LT(xchgs_num, options.getAggressivity());
     // @todo add more thorough checks for rate values.
 }
+
+TEST_F(TestControlTest, processRenew) {
+    std::string loopback_iface(getLocalLoopback());
+    if (loopback_iface.empty()) {
+        std::cout << "Skipping the test because loopback interface could"
+            " not be detected" << std::endl;
+        return;
+    }
+    // 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 " + loopback_iface +
+                                   " -r 10 -f 10 -R 10 -L 10547 -n 10 ::1"));
+    // Create a test controller class.
+    NakedTestControl tc;
+    tc.initializeStatsMgr();
+    // Set the transaction id generator to sequential to control to guarantee
+    // that transaction ids are predictable.
+    boost::shared_ptr<NakedTestControl::IncrementalGenerator>
+        generator(new NakedTestControl::IncrementalGenerator());
+    tc.setTransidGenerator(generator);
+    // Socket has to be created so as we can actually send packets.
+    int sock_handle = 0;
+    ASSERT_NO_THROW(sock_handle = tc.openSocket());
+    TestControl::TestControlSocket sock(sock_handle);
+
+    // Send a number of Solicit messages. Each generated Solicit will be
+    // assigned a different transaction id, starting from 1 to 10.
+    tc.sendPackets(sock, 10);
+
+    // Simulate Advertise responses from the server. Each advertise is assigned
+    // a transaction id from the range of 1 to 10, so as they match the
+    // transaction ids from the Solicit messages.
+    for (int i = generator->getNext() - 10; i < generator->getNext(); ++i) {
+        Pkt6Ptr advertise(createAdvertisePkt6(i));
+        // If Advertise is matched with the Solicit the call below will
+        // trigger a corresponding Request. They will be assigned
+        // transaction ids from the range from 11 to 20 (the range of
+        // 1 to 10 has been used by Solicit-Advertise).
+        ASSERT_NO_THROW(tc.processReceivedPacket6(sock, advertise));
+    }
+
+    // Requests have been sent, so now let's simulate responses from the server.
+    // Generate corresponding Reply messages with the transaction ids from the
+    // range from 11 to 20.
+    for (int i = generator->getNext() - 10; i < generator->getNext(); ++i) {
+        Pkt6Ptr reply(createReplyPkt6(i));
+        // Each Reply packet corresponds to the new lease acquired. Since
+        // -f<renew-rate> option has been specified, received Reply
+        // messages are held so as Renew messages can be sent for
+        // existing leases.
+        ASSERT_NO_THROW(tc.processReceivedPacket6(sock, reply));
+    }
+
+    uint64_t renew_num;
+    // Try to send 5 Renew packets. It should be successful because
+    // 10 Reply messages has been received. For each of them we should
+    // be able to send Renew.
+    ASSERT_NO_THROW(renew_num = tc.sendRenewPackets(sock, 5));
+    // Make sure that we have sent 5 packets.
+    EXPECT_EQ(5, renew_num);
+
+    // Try to do it again. We should still have 5 Reply packets for
+    // which Renews haven't been sent yet.
+    ASSERT_NO_THROW(renew_num = tc.sendRenewPackets(sock, 5));
+    EXPECT_EQ(5, renew_num);
+
+    // We used all the Reply packets (we sent Renew for each of them
+    // already). Therefore, no further Renew packets should be sent before
+    // We acquire new leases.
+    ASSERT_NO_THROW(renew_num = tc.sendRenewPackets(sock, 5));
+    // Make sure that no Renew has been sent.
+    EXPECT_EQ(0, renew_num);
+}
+
+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);
+
+    Pkt6Ptr reply = createReplyPkt6(1);
+    Pkt6Ptr renew;
+    ASSERT_NO_THROW(renew = tc.createRenew(reply));
+    ASSERT_TRUE(renew);
+    EXPECT_EQ(DHCPV6_RENEW, renew->getType());
+    EXPECT_EQ(1, renew->getTransid());
+
+    OptionPtr opt_clientid = renew->getOption(D6O_CLIENTID);
+    ASSERT_TRUE(opt_clientid);
+    EXPECT_TRUE(reply->getOption(D6O_CLIENTID)->getData() ==
+                opt_clientid->getData());
+
+    OptionPtr opt_serverid = renew->getOption(D6O_SERVERID);
+    ASSERT_TRUE(opt_serverid);
+    EXPECT_TRUE(reply->getOption(D6O_SERVERID)->getData() ==
+                opt_serverid->getData());
+
+    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());
+
+    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());
+
+}
+



More information about the bind10-changes mailing list