// Copyright (C) 2012-2015 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/. /// @namespace perfdhcp /// @page perfdhcpInternals perfdhcp Internals /// /// The perfdhcp utility provides a way of measuring the performance of /// DHCP servers by generating large amounts of traffic. Written in C++, /// its use is described in detail in the DHCP Performance Guide. /// /// This document is aimed at people wishing to understand the internals /// of the perfdhcp program. It describes the major components in the /// utility and their interaction. /// /// @section perfdhcpClasses perfdhcp Classes /// /// @subsection perfdhcpCommandOptions CommandOptions (Command Options) /// /// isc::perfdhcp::CommandOptions is a singleton class that parses /// the perfdhcp command line parameters and initializes its members /// accordingly. If the parameters are invalid, the parser method throws /// an exception. Usage is simple: /// /// @code int main(int argc, char* argv[]) { /// try { /// CommandOptions& command_options = CommandOptions::instance(); /// command_options.parse(argc, argv); /// } catch(const Exception& e) { /// ... /// } /// @endcode /// /// If the argument parsing is successful, the parsed values can be read /// from the isc::perfdhcp::CommandOptions singleton from any class or /// function in the program, e.g. /// /// @code /// int rate = CommandOptions::instance().getRate(); /// @endcode /// /// @subsection perfdhcpTestControl TestControl (Test Control) /// /// The isc::perfdhcp::TestControl singleton is responsible /// for test execution coordination. It relies on the /// isc::perfdhcp::CommandOptions object to get all required test /// parameters and for this reason, isc::perfdhcp::CommandOptions has /// to be initialized and isc::perfdhcp::CommandOptions::parse() called /// prior to calling isc::perfdhcp::TestControl::run(). /// /// isc::perfdhcp::TestControl::run() performs initialization of /// isc::perfdhcp::TestControl then executes the main program loop. In /// detail, isc::perfdhcp::TestControl::run() performs the following /// major operations: /// /// -# check if the command line has been parsed, /// -# print diagnostics if specified from command line, /// -# register DHCP options factory functions, /// -# read packet templates from files, /// -# initialize the isc::perfdhcp::StatisticsManager object, /// -# set interrupt signal handler (handle ^C), /// -# open and close socket for communication with server, /// -# coordinate sending and receiving packets, /// -# coordinate intermediate reporting, /// -# prints test statistics. /// /// isc::perfdhcp::TestControl is a singleton object, so there is one sole /// instance of it throughout the program. In order to allow the running /// of unit tests, where a single instance of isc::perfdhcp::TestControl /// is used multiple times with different command line options, a /// isc::perfdhcp::TestControl::reset() function is provided to reset /// the state of the class members. Also, functions that initialize /// various class members (such as Statistics Manager) will release /// any objects from previous test runs. /// /// @subsection perfStatsMgr StatsMgr (Statistics Manager) /// /// isc::perfdhcp::StatsMgr is a class that holds all performance /// statistics gathered throughout the test execution and is created /// in isc::perfdhcp::TestControl. isc::perfdhcp::TestControl posts all /// sent and received packets to isc::perfdhcp::StatsMgr: outgoing packets /// are recorded and incoming packets are matched with the corresponding /// outgoing packer to calculate calculate round trip time, number of /// packet drops etc. Apart from the standard counters implemented in /// isc::perfdhcp::StatsMgr, custom (named) counters can be specified and /// incremented by the calling class. isc::perfdhcp::StatsMgr also exposes /// multiple functions that print gathered statistics into the console. /// /// isc::perfdhcp::StatsMgr is a template class that takes an /// isc::dhcp::Pkt4, isc::dhcp::Pkt6, isc::perfdhcp::PerfPkt4 /// or isc::perfdhcp::PerfPkt6 as a typename. An instance of /// isc::perfdhcp::StatsMgr can be created by: /// /// @code /// typedef StatsMgr StatsMgr4; StatsMgr4 stats_mgr4 = /// boost::shared_ptr(new StatsMgr4()); try { /// stats_mgr->addExchangeStats(StatsMgr4::XCHG_DO); /// } catch(const Exception& e) { /// std::cout << e.what() << std::endl; /// } /// @endcode /// /// The isc::perfdhcp::StatsMgr instance created in the example above will be used /// for DHCPv4 testing (i.e. to collect DHCPv4 packets) and will be /// configured to monitor statistics for DISCOVER-OFFER packet exchanges. /// /// @subsection perfdhcpPkt PerfPkt4 and PerfPkt6 /// /// The isc::perfdhcp::PerfPkt4 and isc::perfdhcp::PerfPkt6 classes /// are derived from isc::dhcp::Pkt4 and isc::dhcp::Pkt6. They extend /// the parent class functionality by adding support for template /// files. Instances of these classes can be created using a raw buffer /// (read from a packet template file). Once the packet object is /// initialized, it is possible to replace parts of the on-wire data by /// using the isc::perfdhcp::LocalizedOption mechanism. /// /// @subsection perfdhcpLocalizedOption LocalizedOption (Localized Option) /// /// isc::perfdhcp::LocalizedOption derives from the isc::dhcp::Option /// class. It represents the DHCP option (v4 or v6) to be /// placed at specified position in the packet buffer (see @ref /// perfdhcpPkt). Such an option is added to the option collection in /// a isc::perfdhcp::PerfPkt4 or isc::perfdhcp::PerfPkt6 object; when /// any of PerfPktX::rawPack() functions are called their content is /// stored in the packet output buffer at the position pointed to by /// the isc::perfdhcp::LocalizedOption object. /// /// isc::perfdhcp::LocalizedOption also allows the reading of the /// on wire data in received packet at the specified position. In /// this case, isc::perfdhcp::LocalizedOption has to be created and /// added to the received packet. When PerfPktX::rawUnpack() is /// called, the contents of the buffer will be read and stored in a /// isc::perfdhcp::LocalizedOption object for further processing. /// /// The following code shows how to create a packet from a /// (template) buffer and replace option data in the buffer with /// isc::perfdhcp::LocalizedOption. /// /// @code /// OptionBuffer buf; // fill buf with data here. ... /// boost::scoped_ptr pkt(new PerfPkt4(&buf[0], buf.size()); /// const size_t offset_hostname = 240; /// OptionBuffer vec_hostname; /// // fill the hostname vector with data ... /// LocalizedOptionPtr opt_hostname(new LocalizedOption(Option::V4, /// DHO_HOST_NAME, /// vec_hostname, /// offset_hostname)); /// pkt->addOption(opt_hostname); /// // by calling rawPack() we replace the packet contents with option /// // contents at buffer position 240. /// pkt->rawPack(); /// @endcode /// /// @subsection perfdhcpPktTransform PktTransform (Packet Transform) /// /// The isc::perfdhcp::PktTransform helper class contains the /// static functions to pack and unpack DHCP options (specifically /// isc::perfdhcp::LocalizedOption) to and from the packet buffer. This /// logic has been moved away from isc::perfdhcp::PerfPkt4 and /// isc::perfdhcp::PerfPkt6 classes to isc::perfdhcp::PktTransform /// because PerfPktX classes share the logic here.