From: Michal Nowikowski Date: Thu, 14 Feb 2019 10:34:15 +0000 (+0100) Subject: perfdhcp avalanche: several improvements X-Git-Tag: 397-cb-implement-mysqlconfigbackenddhcpv6_base~38 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=098ff98fef692bac8de284ff6bf94985a3aa61cb;p=thirdparty%2Fkea.git perfdhcp avalanche: several improvements - fixed restoring pkt timestamp, - added base abstract class for scenarios, - added comments --- diff --git a/src/bin/perfdhcp/Makefile.am b/src/bin/perfdhcp/Makefile.am index 436f7c3910..d595588245 100644 --- a/src/bin/perfdhcp/Makefile.am +++ b/src/bin/perfdhcp/Makefile.am @@ -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 index 0000000000..bb2f5c892f --- /dev/null +++ b/src/bin/perfdhcp/abstract_scen.h @@ -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 + + +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 diff --git a/src/bin/perfdhcp/avalanche_scen.cc b/src/bin/perfdhcp/avalanche_scen.cc index d607fa8268..7145e228e3 100644 --- a/src/bin/perfdhcp/avalanche_scen.cc +++ b/src/bin/perfdhcp/avalanche_scen.cc @@ -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(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 ? diff --git a/src/bin/perfdhcp/avalanche_scen.h b/src/bin/perfdhcp/avalanche_scen.h index 037ee7daed..d973ff81a7 100644 --- a/src/bin/perfdhcp/avalanche_scen.h +++ b/src/bin/perfdhcp/avalanche_scen.h @@ -9,36 +9,41 @@ #include -#include +#include 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> retransmissions_; + /// A map xchg type -> (a map of trans id -> time of sending first packet. std::unordered_map> 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); }; diff --git a/src/bin/perfdhcp/basic_scen.h b/src/bin/perfdhcp/basic_scen.h index 336be7eeca..31df72eb22 100644 --- a/src/bin/perfdhcp/basic_scen.h +++ b/src/bin/perfdhcp/basic_scen.h @@ -9,29 +9,22 @@ #include -#include +#include 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(); }; } diff --git a/src/bin/perfdhcp/test_control.h b/src/bin/perfdhcp/test_control.h index 4ece6157fa..73dc968d91 100644 --- a/src/bin/perfdhcp/test_control.h +++ b/src/bin/perfdhcp/test_control.h @@ -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,