]> git.ipfire.org Git - thirdparty/kea.git/commitdiff
perfdhcp avalanche: several improvements
authorMichal Nowikowski <godfryd@isc.org>
Thu, 14 Feb 2019 10:34:15 +0000 (11:34 +0100)
committerMichal Nowikowski <godfryd@isc.org>
Tue, 19 Feb 2019 20:54:31 +0000 (21:54 +0100)
- fixed restoring pkt timestamp,
- added base abstract class for scenarios,
- added comments

src/bin/perfdhcp/Makefile.am
src/bin/perfdhcp/abstract_scen.h [new file with mode: 0644]
src/bin/perfdhcp/avalanche_scen.cc
src/bin/perfdhcp/avalanche_scen.h
src/bin/perfdhcp/basic_scen.h
src/bin/perfdhcp/test_control.h

index 436f7c39104aac9543fb556f37c8b167d8ac0c01..d595588245f74317941605a75f4216ed07371a66 100644 (file)
@@ -27,6 +27,7 @@ libperfdhcp_la_SOURCES += stats_mgr.cc stats_mgr.h
 libperfdhcp_la_SOURCES += test_control.cc test_control.h
 libperfdhcp_la_SOURCES += receiver.cc receiver.h
 libperfdhcp_la_SOURCES += perf_socket.cc perf_socket.h
+libperfdhcp_la_SOURCES += abstract_scen.h
 libperfdhcp_la_SOURCES += avalanche_scen.cc avalanche_scen.h
 libperfdhcp_la_SOURCES += basic_scen.cc basic_scen.h
 
diff --git a/src/bin/perfdhcp/abstract_scen.h b/src/bin/perfdhcp/abstract_scen.h
new file mode 100644 (file)
index 0000000..bb2f5c8
--- /dev/null
@@ -0,0 +1,39 @@
+// Copyright (C) 2019 Internet Systems Consortium, Inc. ("ISC")
+//
+// This Source Code Form is subject to the terms of the Mozilla Public
+// License, v. 2.0. If a copy of the MPL was not distributed with this
+// file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#ifndef ABSTRACT_SCEN_H
+#define ABSTRACT_SCEN_H
+
+
+#include <perfdhcp/test_control.h>
+
+
+namespace isc {
+namespace perfdhcp {
+
+
+/// \brief Abstract Scenario class.
+///
+/// This class must be inherited by scenario classes.
+class AbstractScen : public boost::noncopyable {
+public:
+    /// \brief Run performance test.
+    ///
+    /// Method runs whole performance test.
+    virtual int run() = 0;
+
+    /// \brief Trivial virtual destructor.
+    virtual ~AbstractScen() {};
+
+protected:
+    TestControl tc_;  ///< Object for controling sending and receiving packets.
+};
+
+
+}
+}
+
+#endif // ABSTRACT_SCEN_H
index d607fa8268a0cd7a88e8ecdcfac592d6bff9eef4..7145e228e3945aa7ef517bad962cc2bce3f629bb 100644 (file)
@@ -32,7 +32,7 @@ AvalancheScen::resendPackets(ExchangeType xchg_type) {
     auto& start_times = start_times_[xchg_type];
 
     int still_left_cnt = 0;
-    int resent_cnt = 0;
+    int current_cycle_resent_cnt = 0;
     for (auto it = begin_it; it != end_it; ++it) {
         still_left_cnt++;
 
@@ -40,18 +40,18 @@ AvalancheScen::resendPackets(ExchangeType xchg_type) {
         auto trans_id = pkt->getTransid();
 
         // get some things from previous retransmissions
-        bool first_resend = true;
         auto start_time = pkt->getTimestamp();
-        int retransmissions_count = 0;
+        int current_pkt_resent_cnt = 0;
         auto r_it = retrans.find(trans_id);
         if (r_it != retrans.end()) {
-            first_resend = false;
             start_time = (*start_times.find(trans_id)).second;
-            retransmissions_count = (*r_it).second;
+            current_pkt_resent_cnt = (*r_it).second;
+        } else {
+            start_times[trans_id] = start_time;
         }
 
         // estimate back off time for resending this packet
-        int delay = (1 << retransmissions_count); // in seconds
+        int delay = (1 << current_pkt_resent_cnt); // in seconds
         if (delay > 64) {
             delay = 64;
         }
@@ -61,15 +61,9 @@ AvalancheScen::resendPackets(ExchangeType xchg_type) {
         // if back-off time passed then resend
         auto now = microsec_clock::universal_time();
         if (now - start_time > milliseconds(delay)) {
-            resent_cnt++;
+            current_cycle_resent_cnt++;
             total_resent_++;
 
-            // remember sending time of original packet
-            boost::posix_time::ptime original_timestamp;
-            if (!first_resend) {
-                original_timestamp = pkt->getTimestamp();
-            }
-
             // do resend packet
             if (options.getIpVersion() == 4) {
                 Pkt4Ptr pkt4 = boost::dynamic_pointer_cast<Pkt4>(pkt);
@@ -80,20 +74,16 @@ AvalancheScen::resendPackets(ExchangeType xchg_type) {
             }
 
             // restore sending time of original packet
-            if (first_resend) {
-                start_times[trans_id] = pkt->getTimestamp();
-            } else {
-                pkt->setTimestamp(original_timestamp);
-            }
+            pkt->setTimestamp(start_time);
 
-            retransmissions_count++;
-            retrans[trans_id] = retransmissions_count;
+            current_pkt_resent_cnt++;
+            retrans[trans_id] = current_pkt_resent_cnt;
         }
     }
-    if (resent_cnt > 0) {
+    if (current_cycle_resent_cnt > 0) {
         auto now = microsec_clock::universal_time();
         std::cout << now << " " << xchg_type << ": still waiting for "
-                  << still_left_cnt << " answers, resent " << resent_cnt
+                  << still_left_cnt << " answers, resent " << current_cycle_resent_cnt
                   << ", retrying " << retrans.size() << std::endl;
     }
     return still_left_cnt;
@@ -103,6 +93,17 @@ AvalancheScen::resendPackets(ExchangeType xchg_type) {
 
 int
 AvalancheScen::run() {
+    // First indicated number of DISCOVER packets eg. 4000 are sent.
+    // Then in a loop responses to received packets (this is
+    // consumeReceivedPackets()) are sent and then for every 200ms it is checked
+    // if reponses to sent packets were received. If not packets are resent.
+    // This happens in resendPackets() method. For each packet it is checked
+    // how many times it was already resent and then back off time is calculated:
+    // 1, 2, 4, 8, 16, 64 (max) seconds. If estimated time has elapsed
+    // from previous sending then the packet is resent. Some stats are collected
+    // and printed during runtime. The whole procedure is stopeed when
+    // all packets got reponses.
+
     CommandOptions& options = CommandOptions::instance();
 
     uint32_t clients_num = options.getClientsNum() == 0 ?
index 037ee7daede09b08b1480ba884a825c3c0590339..d973ff81a7c08562a50b2e1e04be4a301a01a7cb 100644 (file)
@@ -9,36 +9,41 @@
 
 #include <config.h>
 
-#include <perfdhcp/test_control.h>
+#include <perfdhcp/abstract_scen.h>
 
 
 namespace isc {
 namespace perfdhcp {
 
 
-class AvalancheScen : public boost::noncopyable {
+/// \brief Avalanche Scenario class.
+///
+/// This class is used to run the performance test where DHCP server
+/// is first loaded with indicated bumer of Discover or Solicit messages
+/// and then the class is waiting till receiving all required responses.
+/// Full DORA and SARR message sequences are expected.
+class AvalancheScen : public AbstractScen {
 public:
+    /// Default and the only constructor of AvalancheScen.
     AvalancheScen(): total_resent_(0) {};
 
     /// brief\ Run performance test.
     ///
-    /// Method runs whole performance test. Command line options must
-    /// be parsed prior to running this function. Otherwise function will
-    /// throw exception.
-    ///
-    /// \throw isc::InvalidOperation if command line options are not parsed.
-    /// \throw isc::Unexpected if internal Test Controller error occurred.
-    /// \return error_code, 3 if number of received packets is not equal
-    /// to number of sent packets, 0 if everything is ok.
+    /// Method runs whole performance test.
     int run();
 
 private:
-    TestControl tc_;
 
+    /// A map xchg type -> (a map of trans id -> retransmissions count.
     std::unordered_map<ExchangeType, std::unordered_map<uint32_t, int>> retransmissions_;
+    /// A map xchg type -> (a map of trans id -> time of sending first packet.
     std::unordered_map<ExchangeType, std::unordered_map<uint32_t, boost::posix_time::ptime>> start_times_;
+
+    /// Total number of resent packets.
     int total_resent_;
 
+    /// Resend packets for given exchange type that did not receive
+    /// a response yet.
     int resendPackets(ExchangeType xchg_type);
 
 };
index 336be7eecac9ab2be9b18603173f07c9beb5dbbb..31df72eb229c5c121fec82a0006c8b8c8f4119ec 100644 (file)
@@ -9,29 +9,22 @@
 
 #include <config.h>
 
-#include <perfdhcp/test_control.h>
+#include <perfdhcp/abstract_scen.h>
 
 
 namespace isc {
 namespace perfdhcp {
 
 
-class BasicScen : public boost::noncopyable {
+/// \brief Basic Scenario class.
+///
+/// This class is used to run the performance test where DHCP server
+/// is continuously loaded with DHCP messages according to given rate.
+class BasicScen : public AbstractScen {
 public:
+    /// Default and the only constructor of BasicScen.
     BasicScen() {};
 
-    /// \brief Check if test exit conditions fulfilled.
-    ///
-    /// Method checks if the test exit conditions are fulfilled.
-    /// Exit conditions are checked periodically from the
-    /// main loop. Program should break the main loop when
-    /// this method returns true. It is calling function
-    /// responsibility to break main loop gracefully and
-    /// cleanup after test execution.
-    ///
-    /// \return true if any of the exit conditions is fulfilled.
-    bool checkExitConditions();
-
     /// brief\ Run performance test.
     ///
     /// Method runs whole performance test. Command line options must
@@ -45,8 +38,6 @@ public:
     int run();
 
 private:
-    TestControl tc_;
-
     /// \brief A rate control class for Discover and Solicit messages.
     RateControl basic_rate_control_;
     /// \brief A rate control class for Renew messages.
@@ -54,8 +45,17 @@ private:
     /// \brief A rate control class for Release messages.
     RateControl release_rate_control_;
 
-    int resendPackets(ExchangeType xchg_type);
-
+    /// \brief Check if test exit conditions fulfilled.
+    ///
+    /// Method checks if the test exit conditions are fulfilled.
+    /// Exit conditions are checked periodically from the
+    /// main loop. Program should break the main loop when
+    /// this method returns true. It is calling function
+    /// responsibility to break main loop gracefully and
+    /// cleanup after test execution.
+    ///
+    /// \return true if any of the exit conditions is fulfilled.
+    bool checkExitConditions();
 };
 
 }
index 4ece6157faab837a9775dfb458d1c6805800db9c..73dc968d91706bb7f018d22ca6ca4ec52f786a19 100644 (file)
@@ -62,7 +62,7 @@ public:
 
 /// \brief Test Control class.
 ///
-/// This singleton class is used to run the performance test with
+/// This class is used to run the performance test with
 /// with \ref TestControl::run function. This function can be executed
 /// multiple times if desired because it resets TestControl's internal
 /// state every time it is executed. Prior to running \ref TestControl::run,