- added usleep to main loop in run function when nothing is to be done to not overload CPU
- changed includes to use <...>
- changed socket desctructor to be virtual
- updated docs
- changed rate type to unsigned
- other minor fixes
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
-#include "better_socket.h"
+#include <perfdhcp/better_socket.h>
#include <dhcp/iface_mgr.h>
}
}
}
- isc_throw(BadValue, "interface for for specified socket "
- "descriptor not found");
+ isc_throw(BadValue, "interface for specified socket descriptor not found");
}
}
/// \brief Destructor of the socket wrapper class.
///
/// Destructor closes wrapped socket.
- ~BetterSocket();
+ virtual ~BetterSocket();
private:
/// \brief Initialize socket data.
#include <config.h>
-#include "command_options.h"
+#include <perfdhcp/command_options.h>
+
#include <exceptions/exceptions.h>
#include <dhcp/iface_mgr.h>
#include <dhcp/duid.h>
#include <boost/lexical_cast.hpp>
#include <boost/date_time/posix_time/posix_time.hpp>
-
#include <sstream>
#include <stdio.h>
#include <stdlib.h>
" to or less than the exchange rate.\n"
"-g Select thread mode: 'single' or 'multi'. In multi-thread mode packets\n"
" are received in separate thread. This allows better utilisation of CPUs."
- " If more than 1 CPU is present then multi-thread mode is default otherwise"
- " single-thread is default."
+ " If more than 1 CPU is present then multi-thread mode is the default,"
+ " otherwise single-thread is the default."
"-h: Print this help.\n"
"-i: Do only the initial part of an exchange: DO or SA, depending on\n"
" whether -6 is given.\n"
#ifndef COMMAND_OPTIONS_H
#define COMMAND_OPTIONS_H
-#include <boost/noncopyable.hpp>
-
#include <dhcp/option.h>
+
+#include <boost/noncopyable.hpp>
#include <stdint.h>
#include <string>
#include <vector>
LeaseType lease_type_;
/// Rate in exchange per second
- int rate_;
+ unsigned int rate_;
/// A rate at which DHCPv6 Renew messages are sent.
- int renew_rate_;
+ unsigned int renew_rate_;
/// A rate at which DHCPv6 Release messages are sent.
- int release_rate_;
+ unsigned int release_rate_;
/// Delay between generation of two consecutive performance reports
int report_delay_;
// 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/.
-#include <iostream>
-#include <stdint.h>
-
#include <config.h>
+
+#include <perfdhcp/test_control.h>
+#include <perfdhcp/command_options.h>
+
#include <exceptions/exceptions.h>
-#include "test_control.h"
-#include "command_options.h"
+#include <iostream>
+#include <stdint.h>
using namespace isc::perfdhcp;
#include <config.h>
+#include <perfdhcp/perf_pkt4.h>
+
#include <dhcp/libdhcp++.h>
#include <dhcp/dhcp4.h>
-#include "perf_pkt4.h"
-
using namespace std;
using namespace isc;
using namespace dhcp;
#ifndef PERF_PKT4_H
#define PERF_PKT4_H
-#include <time.h>
-#include <boost/shared_ptr.hpp>
+#include <perfdhcp/localized_option.h>
+#include <perfdhcp/pkt_transform.h>
+
#include <dhcp/pkt4.h>
-#include "localized_option.h"
-#include "pkt_transform.h"
+#include <boost/shared_ptr.hpp>
+#include <time.h>
+
namespace isc {
namespace perfdhcp {
#include <config.h>
-#include <iostream>
+#include <perfdhcp/perf_pkt6.h>
+#include <perfdhcp/pkt_transform.h>
+
#include <exceptions/exceptions.h>
#include <dhcp/libdhcp++.h>
#include <dhcp/dhcp6.h>
-#include "perf_pkt6.h"
-#include "pkt_transform.h"
+#include <iostream>
using namespace std;
using namespace isc;
#ifndef PERF_PKT6_H
#define PERF_PKT6_H
-#include <time.h>
-#include <boost/shared_ptr.hpp>
+#include <perfdhcp/localized_option.h>
+#include <perfdhcp/pkt_transform.h>
+
#include <dhcp/pkt6.h>
-#include "localized_option.h"
-#include "pkt_transform.h"
+#include <time.h>
+#include <boost/shared_ptr.hpp>
namespace isc {
namespace perfdhcp {
<term><option>-g <replaceable class="parameter">thread-mode</replaceable></option></term>
<listitem>
<para>
- Thread operation mode can be either 'single' or 'multi'. In multi-thread mode packets
- are received in separate thread. This allows better utilisation of CPUs.
- In single CPU system it is better to run in 1 thread to avoid blocking of threads each other.
- If more than 1 CPU is present in the system then multi-thread mode is default otherwise
- single-thread is default.
+ <replaceable class="parameter">thread-mode</replaceable> can be either 'single' or 'multi'.
+ In multi-thread mode packets are received in separate thread. This allows better utilisation of CPUs.
+ In single CPU system it is better to run in 1 thread to avoid blocking of threads each other.
+ If more than 1 CPU is present in the system then multi-thread mode is default otherwise
+ single-thread is default.
</para>
</listitem>
</varlistentry>
#include <config.h>
-#include <iostream>
+#include <perfdhcp/pkt_transform.h>
+#include <perfdhcp/localized_option.h>
#include <exceptions/exceptions.h>
#include <dhcp/option.h>
#include <dhcp/libdhcp++.h>
#include <dhcp/dhcp6.h>
-#include "pkt_transform.h"
-#include "localized_option.h"
+#include <iostream>
+
using namespace std;
using namespace isc;
#ifndef PKT_TRANSFORM_H
#define PKT_TRANSFORM_H
-#include <dhcp/option.h>
+#include <perfdhcp/localized_option.h>
-#include "localized_option.h"
+#include <dhcp/option.h>
namespace isc {
namespace perfdhcp {
#include <config.h>
+#include <perfdhcp/rate_control.h>
+
#include <exceptions/exceptions.h>
-#include "rate_control.h"
+
namespace isc {
namespace perfdhcp {
: rate_(0), total_pkts_sent_count_(0) {
}
-RateControl::RateControl(const int rate)
+RateControl::RateControl(const unsigned int rate)
: rate_(rate), total_pkts_sent_count_(0) {
- if (rate_ < 0) {
- isc_throw(isc::BadValue, "invalid value of rate " << rate
- << ", expected non-negative value");
- }
}
uint64_t
/// \brief Constructor which sets desired rate.
///
/// \param rate A desired rate.
- RateControl(const int rate);
+ RateControl(const unsigned int rate);
/// \brief Returns number of messages to be sent "now".
///
uint64_t getOutboundMessageCount();
/// \brief Returns the rate.
- int getRate() const {
+ unsigned int getRate() const {
return (rate_);
}
boost::posix_time::ptime currentTime();
/// \brief Holds a desired rate value.
- int rate_;
+ unsigned int rate_;
/// \brief Holds number of packets send from the beginning.
// 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/.
-#include "receiver.h"
-#include "command_options.h"
+#include <perfdhcp/receiver.h>
+#include <perfdhcp/command_options.h>
#include <dhcp/iface_mgr.h>
using namespace std;
+using namespace isc::dhcp;
namespace isc {
namespace perfdhcp {
Receiver::getPkt() {
if (single_threaded_) {
// In single thread mode read packet directly from the socket and return it.
- auto pkt = readPktFromSocket();
- return pkt;
+ return readPktFromSocket();
} else {
// In multi thread mode read packet from the queue which is feed by Receiver thread.
unique_lock<mutex> lock(pkt_queue_mutex_);
if (pkt_queue_.empty()) {
if (CommandOptions::instance().getIpVersion() == 4) {
- return Pkt4Ptr{nullptr};
+ return Pkt4Ptr();
} else {
- return Pkt6Ptr{nullptr};
+ return Pkt6Ptr();
}
}
auto pkt = pkt_queue_.front();
while (run_flag_.test_and_set()) {
receivePackets();
}
+ } catch (const exception& e) {
+ cerr << "Something went wrong: " << e.what() << endl;
+ usleep(1000);
} catch (...) {
- cout << "SOMETHING WENT WRONG" << endl;
+ cerr << "Something went wrong" << endl;
+ usleep(1000);
}
}
pkt = IfaceMgr::instance().receive6(0, timeout);
}
} catch (const Exception& e) {
- cerr << "Failed to receive DHCP packet: " << e.what() << endl;
+ cerr << "Failed to receive DHCP packet: " << e.what() << endl;
}
if (!pkt) {
return nullptr;
break;
}
- // Drop packet if not supported.
+ // Drop the packet if not supported. Do not bother main thread about it.
if (pkt->getType() == DHCPOFFER || pkt->getType() == DHCPACK ||
pkt->getType() == DHCPV6_ADVERTISE || pkt->getType() == DHCPV6_REPLY) {
- // Otherwise push to another thread.
+ // Otherwise push the packet to the queue, to main thread.
unique_lock<mutex> lock(pkt_queue_mutex_);
pkt_queue_.push(pkt);
}
#pragma once
-#include "better_socket.h"
-#include "command_options.h"
+#include <perfdhcp/better_socket.h>
+#include <perfdhcp/command_options.h>
#include <dhcp/pkt4.h>
#include <dhcp/pkt6.h>
#include <mutex>
#include <boost/atomic.hpp>
-using namespace std;
-using namespace isc::dhcp;
-
namespace isc {
namespace perfdhcp {
-typedef boost::shared_ptr<Pkt> PktPtr;
+typedef boost::shared_ptr<isc::dhcp::Pkt> PktPtr;
/// \brief A receviving DHCP packets class.
///
boost::atomic_flag run_flag_;
/// \brief Thread for receiving packets.
- unique_ptr<thread> recv_thread_;
+ std::unique_ptr<std::thread> recv_thread_;
/// \brief Queue for passing packets from receiver thread to main thread.
- queue<PktPtr> pkt_queue_;
+ std::queue<PktPtr> pkt_queue_;
/// \brief Mutex for controlling access to the queue.
- mutex pkt_queue_mutex_;
+ std::mutex pkt_queue_mutex_;
/// \brief Single- or thread-mode indicator.
bool single_threaded_;
using namespace std;
auto sent = getSentPacketsNum();
auto drops = getDroppedPacketsNum();
- double drops_ratio = 100 * static_cast<double>(drops) / static_cast<double>(sent);
+ double drops_ratio = 100.0 * static_cast<double>(drops) / static_cast<double>(sent);
cout << "sent packets: " << sent << endl
<< "received packets: " << getRcvdPacketsNum() << endl
#include <config.h>
+#include <perfdhcp/test_control.h>
+#include <perfdhcp/receiver.h>
+#include <perfdhcp/command_options.h>
+#include <perfdhcp/perf_pkt4.h>
+#include <perfdhcp/perf_pkt6.h>
+
#include <exceptions/exceptions.h>
#include <asiolink/io_address.h>
#include <dhcp/libdhcp++.h>
#include <dhcp/dhcp4.h>
#include <dhcp/option6_ia.h>
#include <util/unittests/check_valgrind.h>
-#include "test_control.h"
-#include "receiver.h"
-#include "command_options.h"
-#include "perf_pkt4.h"
-#include "perf_pkt6.h"
#include <boost/date_time/posix_time/posix_time.hpp>
-
#include <algorithm>
#include <fstream>
#include <stdio.h>
}
}
-void
+unsigned int
TestControl::consumeReceivedPackets(Receiver& receiver, const BetterSocket& socket) {
+ unsigned int pkt_count = 0;
PktPtr pkt;
while ((pkt = receiver.getPkt())) {
+ pkt_count += 1;
if (CommandOptions::instance().getIpVersion() == 4) {
Pkt4Ptr pkt4 = boost::dynamic_pointer_cast<Pkt4>(pkt);
processReceivedPacket4(socket, pkt4);
processReceivedPacket6(socket, pkt6);
}
}
+ return pkt_count;
}
void
TestControl::registerOptionFactories4() const {
// Pull some packets from receiver thread, process them, update some stats
// and respond to the server if needed.
- consumeReceivedPackets(receiver, socket);
+ auto pkt_count = consumeReceivedPackets(receiver, socket);
+
+ // If there is nothing to do in this loop iteration then do some sleep to make
+ // CPU idle for a moment, to not consume 100% CPU all the time
+ // but only if it is not that high request rate expected.
+ if (options.getRate() < 10000 && packets_due == 0 && pkt_count == 0) {
+ usleep(1);
+ }
// If test period finished, maximum number of packet drops
// has been reached or test has been interrupted we have to
#ifndef TEST_CONTROL_H
#define TEST_CONTROL_H
-#include "packet_storage.h"
-#include "rate_control.h"
-#include "stats_mgr.h"
-#include "receiver.h"
+#include <perfdhcp/packet_storage.h>
+#include <perfdhcp/rate_control.h>
+#include <perfdhcp/stats_mgr.h>
+#include <perfdhcp/receiver.h>
#include <dhcp/iface_mgr.h>
#include <dhcp/dhcp6.h>
/// \brief Pull packets from receiver and process them.
/// It runs in a loop until there are no packets in receiver.
- void consumeReceivedPackets(Receiver& receiver, const BetterSocket& socket);
+ unsigned int consumeReceivedPackets(Receiver& receiver, const BetterSocket& socket);
/// \brief Process received DHCPv4 packet.
///
SUBDIRS = . testdata
-AM_CPPFLAGS = -I$(top_builddir)/src/lib -I$(top_srcdir)/src/lib
+AM_CPPFLAGS = -I$(top_builddir)/src/lib -I$(top_srcdir)/src/lib -I$(top_builddir)/src/bin -I$(top_srcdir)/src/bin
AM_CPPFLAGS += -I$(srcdir)/.. -I$(builddir)/..
AM_CPPFLAGS += -DTEST_DATA_DIR=\"$(abs_srcdir)/testdata\"
AM_CPPFLAGS += $(BOOST_INCLUDES)
// will be set correctly.
NakedRateControl rc2(5);
EXPECT_EQ(5, rc2.getRate());
-
- // The negative value of rate is not acceptable.
- EXPECT_THROW(RateControl(-1), isc::BadValue);
}
// Check the rate accessor.