test_control.h 47 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142
  1. // Copyright (C) 2012-2017 Internet Systems Consortium, Inc. ("ISC")
  2. //
  3. // This Source Code Form is subject to the terms of the Mozilla Public
  4. // License, v. 2.0. If a copy of the MPL was not distributed with this
  5. // file, You can obtain one at http://mozilla.org/MPL/2.0/.
  6. #ifndef TEST_CONTROL_H
  7. #define TEST_CONTROL_H
  8. #include "packet_storage.h"
  9. #include "rate_control.h"
  10. #include "stats_mgr.h"
  11. #include <dhcp/iface_mgr.h>
  12. #include <dhcp/dhcp6.h>
  13. #include <dhcp/pkt4.h>
  14. #include <dhcp/pkt6.h>
  15. #include <util/random/random_number_generator.h>
  16. #include <boost/noncopyable.hpp>
  17. #include <boost/shared_ptr.hpp>
  18. #include <boost/function.hpp>
  19. #include <boost/date_time/posix_time/posix_time.hpp>
  20. #include <string>
  21. #include <vector>
  22. namespace isc {
  23. namespace perfdhcp {
  24. /// Default transaction id offset in the packet template.
  25. static const size_t DHCPV4_TRANSID_OFFSET = 4;
  26. /// Default offset of MAC's last octet in the packet template..
  27. static const size_t DHCPV4_RANDOMIZATION_OFFSET = 35;
  28. /// Default elapsed time offset in the packet template.
  29. static const size_t DHCPV4_ELAPSED_TIME_OFFSET = 8;
  30. /// Default server id offset in the packet template.
  31. static const size_t DHCPV4_SERVERID_OFFSET = 54;
  32. /// Default requested ip offset in the packet template.
  33. static const size_t DHCPV4_REQUESTED_IP_OFFSET = 240;
  34. /// Default DHCPV6 transaction id offset in t the packet template.
  35. static const size_t DHCPV6_TRANSID_OFFSET = 1;
  36. /// Default DHCPV6 randomization offset (last octet of DUID)
  37. /// in the packet template.
  38. static const size_t DHCPV6_RANDOMIZATION_OFFSET = 21;
  39. /// Default DHCPV6 elapsed time offset in the packet template.
  40. static const size_t DHCPV6_ELAPSED_TIME_OFFSET = 84;
  41. /// Default DHCPV6 server id offset in the packet template.
  42. static const size_t DHCPV6_SERVERID_OFFSET = 22;
  43. /// Default DHCPV6 IA_NA offset in the packet template.
  44. static const size_t DHCPV6_IA_NA_OFFSET = 40;
  45. /// @brief Exception thrown when the required option is not found in a packet.
  46. class OptionNotFound : public Exception {
  47. public:
  48. OptionNotFound(const char* file, size_t line, const char* what) :
  49. isc::Exception(file, line, what) { };
  50. };
  51. /// \brief Test Control class.
  52. ///
  53. /// This singleton class is used to run the performance test with
  54. /// with \ref TestControl::run function. This function can be executed
  55. /// multiple times if desired because it resets TestControl's internal
  56. /// state every time it is executed. Prior to running \ref TestControl::run,
  57. /// one must make sure to parse command line options by calling
  58. /// \ref CommandOptions::parse. Failing to do this will result in an exception.
  59. ///
  60. /// The following major stages of the test are performed by this class:
  61. /// - set default transaction id and MAC address generators - the generator
  62. /// is an object of \ref TestControl::NumberGenerator type and it provides
  63. /// the custom randomization algorithms,
  64. /// - print command line arguments,
  65. /// - register option factory functions which are used to generate DHCP options
  66. /// being sent to a server,
  67. /// - create the socket for communication with a server,
  68. /// - read packet templates if user specified template files with '-T' command
  69. /// line option,
  70. /// - set the interrupt handler (invoked when ^C is pressed) which makes
  71. /// perfdhcp stop gracefully and print the test results before exiting,
  72. /// - executes an external command (if specified '-w' option), e.g. if user
  73. /// specified -w ./foo in the command line then program will execute
  74. /// "./foo start" at the beginning of the test and "./foo stop" when the test
  75. /// ends,
  76. /// - initialize the Statistics Manager,
  77. /// - executes the main loop:
  78. /// - calculate how many packets must be send to satisfy desired rate,
  79. /// - receive incoming packets from the server,
  80. /// - check the exit conditions - terminate the program if the exit criteria
  81. /// are fulfilled, e.g. reached maximum number of packet drops,
  82. /// - send the number of packets appropriate to satisfy the desired rate,
  83. /// - optionally print intermediate reports,
  84. /// - print statistics, e.g. achieved rate,
  85. /// - optionally print some diagnostics.
  86. ///
  87. /// With the '-w' command line option user may specify the external application
  88. /// or script to be executed. This is executed twice, first when the test starts
  89. /// and second time when the test ends. This external script or application must
  90. /// accept 'start' and 'stop' arguments. The first time it is called, it is
  91. /// called with the argument 'start' and the second time with the argument
  92. /// 'stop'.
  93. ///
  94. /// The application is executed by calling fork() to fork the current perfdhcp
  95. /// process and then call execlp() to replace the current process image with
  96. /// the new one.
  97. ///
  98. /// Option factory functions are registered using
  99. /// \ref dhcp::LibDHCP::OptionFactoryRegister. Registered factory functions
  100. /// provide a way to create options of the same type in the same way.
  101. /// When a new option instance is needed, the corresponding factory
  102. /// function is called to create it. This is done by calling
  103. /// \ref dhcp::Option::factory with DHCP message type specified as one of
  104. /// parameters. Some of the parameters passed to factory function
  105. /// may be ignored (e.g. option buffer).
  106. /// Please note that naming convention for factory functions within this
  107. /// class is as follows:
  108. /// - factoryABC4 - factory function for DHCPv4 option,
  109. /// - factoryDEF6 - factory function for DHCPv6 option,
  110. /// - factoryGHI - factory function that can be used to create either
  111. /// DHCPv4 or DHCPv6 option.
  112. class TestControl : public boost::noncopyable {
  113. public:
  114. /// Statistics Manager for DHCPv4.
  115. typedef StatsMgr<dhcp::Pkt4> StatsMgr4;
  116. /// Pointer to Statistics Manager for DHCPv4;
  117. typedef boost::shared_ptr<StatsMgr4> StatsMgr4Ptr;
  118. /// Statistics Manager for DHCPv6.
  119. typedef StatsMgr<dhcp::Pkt6> StatsMgr6;
  120. /// Pointer to Statistics Manager for DHCPv6.
  121. typedef boost::shared_ptr<StatsMgr6> StatsMgr6Ptr;
  122. /// Packet exchange type.
  123. typedef StatsMgr<>::ExchangeType ExchangeType;
  124. /// Packet template buffer.
  125. typedef std::vector<uint8_t> TemplateBuffer;
  126. /// Packet template buffers list.
  127. typedef std::vector<TemplateBuffer> TemplateBufferCollection;
  128. /// \brief Socket wrapper structure.
  129. ///
  130. /// This is the wrapper that holds descriptor of the socket
  131. /// used to run DHCP test. The wrapped socket is closed in
  132. /// the destructor. This prevents resource leaks when when
  133. /// function that created the socket ends (normally or
  134. /// when exception occurs). This structure extends parent
  135. /// structure with new field ifindex_ that holds interface
  136. /// index where socket is bound to.
  137. struct TestControlSocket : public dhcp::SocketInfo {
  138. /// Interface index.
  139. uint16_t ifindex_;
  140. /// Is socket valid. It will not be valid if the provided socket
  141. /// descriptor does not point to valid socket.
  142. bool valid_;
  143. /// \brief Constructor of socket wrapper class.
  144. ///
  145. /// This constructor uses provided socket descriptor to
  146. /// find the name of the interface where socket has been
  147. /// bound to. If provided socket descriptor is invalid then
  148. /// valid_ field is set to false;
  149. ///
  150. /// \param socket socket descriptor.
  151. TestControlSocket(const int socket);
  152. /// \brief Destructor of the socket wrapper class.
  153. ///
  154. /// Destructor closes wrapped socket.
  155. ~TestControlSocket();
  156. private:
  157. /// \brief Initialize socket data.
  158. ///
  159. /// This method initializes members of the class that Interface
  160. /// Manager holds: interface name, local address.
  161. ///
  162. /// \throw isc::BadValue if interface for specified socket
  163. /// descriptor does not exist.
  164. void initSocketData();
  165. };
  166. /// \brief Number generator class.
  167. ///
  168. /// This is default numbers generator class. The member function is
  169. /// used to generate uint32_t values. Other generator classes should
  170. /// derive from this one to implement generation algorithms
  171. /// (e.g. sequential or based on random function).
  172. class NumberGenerator {
  173. public:
  174. /// \brief Destructor.
  175. virtual ~NumberGenerator() { }
  176. /// \brief Generate number.
  177. ///
  178. /// \return Generate number.
  179. virtual uint32_t generate() = 0;
  180. };
  181. /// The default generator pointer.
  182. typedef boost::shared_ptr<NumberGenerator> NumberGeneratorPtr;
  183. /// \brief Sequential numbers generator class.
  184. class SequentialGenerator : public NumberGenerator {
  185. public:
  186. /// \brief Constructor.
  187. ///
  188. /// \param range maximum number generated. If 0 is given then
  189. /// range defaults to maximum uint32_t value.
  190. SequentialGenerator(uint32_t range = 0xFFFFFFFF) :
  191. NumberGenerator(),
  192. num_(0),
  193. range_(range) {
  194. if (range_ == 0) {
  195. range_ = 0xFFFFFFFF;
  196. }
  197. }
  198. /// \brief Generate number sequentially.
  199. ///
  200. /// \return generated number.
  201. virtual uint32_t generate() {
  202. uint32_t num = num_;
  203. num_ = (num_ + 1) % range_;
  204. return (num);
  205. }
  206. private:
  207. uint32_t num_; ///< Current number.
  208. uint32_t range_; ///< Number of unique numbers generated.
  209. };
  210. /// \brief Length of the Ethernet HW address (MAC) in bytes.
  211. ///
  212. /// \todo Make this variable length as there are cases when HW
  213. /// address is longer than this (e.g. 20 bytes).
  214. static const uint8_t HW_ETHER_LEN = 6;
  215. /// TestControl is a singleton class. This method returns reference
  216. /// to its sole instance.
  217. ///
  218. /// \return the only existing instance of test control
  219. static TestControl& instance();
  220. /// brief\ Run performance test.
  221. ///
  222. /// Method runs whole performance test. Command line options must
  223. /// be parsed prior to running this function. Otherwise function will
  224. /// throw exception.
  225. ///
  226. /// \throw isc::InvalidOperation if command line options are not parsed.
  227. /// \throw isc::Unexpected if internal Test Controller error occurred.
  228. /// \return error_code, 3 if number of received packets is not equal
  229. /// to number of sent packets, 0 if everything is ok.
  230. int run();
  231. /// \brief Set new transaction id generator.
  232. ///
  233. /// \param generator generator object to be used.
  234. void setTransidGenerator(const NumberGeneratorPtr& generator) {
  235. transid_gen_.reset();
  236. transid_gen_ = generator;
  237. }
  238. /// \brief Set new MAC address generator.
  239. ///
  240. /// Set numbers generator that will be used to generate various
  241. /// MAC addresses to simulate number of clients.
  242. ///
  243. /// \param generator object to be used.
  244. void setMacAddrGenerator(const NumberGeneratorPtr& generator) {
  245. macaddr_gen_.reset();
  246. macaddr_gen_ = generator;
  247. }
  248. // We would really like following methods and members to be private but
  249. // they have to be accessible for unit-testing. Another, possibly better,
  250. // solution is to make this class friend of test class but this is not
  251. // what's followed in other classes.
  252. protected:
  253. /// \brief Default constructor.
  254. ///
  255. /// Default constructor is protected as the object can be created
  256. /// only via \ref instance method.
  257. TestControl();
  258. /// Generate uniformly distributed integers in range of [min, max]
  259. isc::util::random::UniformRandomIntegerGenerator number_generator_;
  260. /// \brief Check if test exit conditions fulfilled.
  261. ///
  262. /// Method checks if the test exit conditions are fulfilled.
  263. /// Exit conditions are checked periodically from the
  264. /// main loop. Program should break the main loop when
  265. /// this method returns true. It is calling function
  266. /// responsibility to break main loop gracefully and
  267. /// cleanup after test execution.
  268. ///
  269. /// \return true if any of the exit conditions is fulfilled.
  270. bool checkExitConditions() const;
  271. /// \brief Removes cached DHCPv6 Reply packets every second.
  272. ///
  273. /// This function wipes cached Reply packets from the storage.
  274. /// The number of packets left in the storage after the call
  275. /// to this function should guarantee that the Renew packets
  276. /// can be sent at the given rate. Note that the Renew packets
  277. /// are generated for the existing leases, represented here as
  278. /// replies from the server.
  279. /// @todo Instead of cleaning packets periodically we could
  280. /// just stop adding new packets when the certain threshold
  281. /// has been reached.
  282. void cleanCachedPackets();
  283. /// \brief Creates DHCPREQUEST from a DHCPACK message.
  284. ///
  285. /// \param ack An instance of the DHCPACK message to be used to
  286. /// create a new message.
  287. ///
  288. /// \return Pointer to the created message.
  289. dhcp::Pkt4Ptr createRequestFromAck(const dhcp::Pkt4Ptr& ack);
  290. /// \brief Creates DHCPv6 message from the Reply packet.
  291. ///
  292. /// This function creates DHCPv6 Renew or Release message using the
  293. /// data from the Reply message by copying options from the Reply
  294. /// message.
  295. ///
  296. /// \param msg_type A type of the message to be created.
  297. /// \param reply An instance of the Reply packet which contents should
  298. /// be used to create an instance of the new message.
  299. ///
  300. /// \return created Release or Renew message
  301. /// \throw isc::BadValue if the msg_type is neither DHCPV6_RENEW nor
  302. /// DHCPV6_RELEASE or if the reply is NULL.
  303. /// \throw isc::Unexpected if mandatory options are missing in the
  304. /// Reply message.
  305. dhcp::Pkt6Ptr createMessageFromReply(const uint16_t msg_type,
  306. const dhcp::Pkt6Ptr& reply);
  307. /// \brief Factory function to create DHCPv6 ELAPSED_TIME option.
  308. ///
  309. /// This factory function creates DHCPv6 ELAPSED_TIME option instance.
  310. /// If empty buffer is passed the option buffer will be initialized
  311. /// to length 2 and values will be initialized to zeros. Otherwise
  312. /// function will initialize option buffer with values in passed buffer.
  313. ///
  314. /// \param u universe (ignored)
  315. /// \param type option-type (ignored).
  316. /// \param buf option-buffer containing option content (2 bytes) or
  317. /// empty buffer if option content has to be set to default (0) value.
  318. /// \throw if elapsed time buffer size is neither 2 nor 0.
  319. /// \return instance o the option.
  320. static dhcp::OptionPtr
  321. factoryElapsedTime6(dhcp::Option::Universe u,
  322. uint16_t type,
  323. const dhcp::OptionBuffer& buf);
  324. /// \brief Factory function to create generic option.
  325. ///
  326. /// This factory function creates option with specified universe,
  327. /// type and buf. It does not have any additional logic validating
  328. /// the buffer contents, size etc.
  329. ///
  330. /// \param u universe (V6 or V4).
  331. /// \param type option-type (ignored).
  332. /// \param buf option-buffer.
  333. /// \return instance o the option.
  334. static dhcp::OptionPtr factoryGeneric(dhcp::Option::Universe u,
  335. uint16_t type,
  336. const dhcp::OptionBuffer& buf);
  337. /// \brief Factory function to create IA_NA option.
  338. ///
  339. /// This factory function creates DHCPv6 IA_NA option instance.
  340. ///
  341. /// \todo add support for IA Address options.
  342. ///
  343. /// \param u universe (ignored).
  344. /// \param type option-type (ignored).
  345. /// \param buf option-buffer carrying IANA suboptions.
  346. /// \return instance of IA_NA option.
  347. static dhcp::OptionPtr factoryIana6(dhcp::Option::Universe u,
  348. uint16_t type,
  349. const dhcp::OptionBuffer& buf);
  350. /// \brief Factory function to create IA_PD option.
  351. ///
  352. /// this factory function creates DHCPv6 IA_PD option instance.
  353. ///
  354. /// \param u universe (ignored).
  355. /// \param type option-type (ignored).
  356. /// \param buf option-buffer carrying sub-options.
  357. static dhcp::OptionPtr factoryIapd6(dhcp::Option::Universe u,
  358. uint16_t type,
  359. const dhcp::OptionBuffer& buf);
  360. /// \brief Factory function to create DHCPv6 ORO option.
  361. ///
  362. /// This factory function creates DHCPv6 Option Request Option instance.
  363. /// The created option will contain the following set of requested options:
  364. /// - D6O_NAME_SERVERS
  365. /// - D6O_DOMAIN_SEARCH
  366. ///
  367. /// \param u universe (ignored).
  368. /// \param type option-type (ignored).
  369. /// \param buf option-buffer (ignored).
  370. /// \return instance of ORO option.
  371. static dhcp::OptionPtr
  372. factoryOptionRequestOption6(dhcp::Option::Universe u,
  373. uint16_t type,
  374. const dhcp::OptionBuffer& buf);
  375. /// \brief Factory function to create DHCPv6 RAPID_COMMIT option instance.
  376. ///
  377. /// This factory function creates DHCPv6 RAPID_COMMIT option instance.
  378. /// The buffer passed to this option must be empty because option does
  379. /// not have any payload.
  380. ///
  381. /// \param u universe (ignored).
  382. /// \param type option-type (ignored).
  383. /// \param buf option-buffer (ignored).
  384. /// \return instance of RAPID_COMMIT option..
  385. static dhcp::OptionPtr factoryRapidCommit6(dhcp::Option::Universe u,
  386. uint16_t type,
  387. const dhcp::OptionBuffer& buf);
  388. /// \brief Factory function to create DHCPv4 Request List option.
  389. ///
  390. /// This factory function creates DHCPv4 PARAMETER_REQUEST_LIST option
  391. /// instance with the following set of requested options:
  392. /// - DHO_SUBNET_MASK,
  393. /// - DHO_BROADCAST_ADDRESS,
  394. /// - DHO_TIME_OFFSET,
  395. /// - DHO_ROUTERS,
  396. /// - DHO_DOMAIN_NAME,
  397. /// - DHO_DOMAIN_NAME_SERVERS,
  398. /// - DHO_HOST_NAME.
  399. ///
  400. /// \param u universe (ignored).
  401. /// \param type option-type (ignored).
  402. /// \param buf option-buffer (ignored).
  403. /// \return instance o the generic option.
  404. static dhcp::OptionPtr factoryRequestList4(dhcp::Option::Universe u,
  405. uint16_t type,
  406. const dhcp::OptionBuffer& buf);
  407. /// \brief Generate DHCPv4 client identifier from HW address.
  408. ///
  409. /// This method generates DHCPv4 client identifier option from a
  410. /// HW address.
  411. ///
  412. /// \param hwaddr HW address.
  413. ///
  414. /// \return Pointer to an instance of the generated option.
  415. dhcp::OptionPtr generateClientId(const dhcp::HWAddrPtr& hwaddr) const;
  416. /// \brief Generate DUID.
  417. ///
  418. /// Method generates unique DUID. The number of DUIDs it can generate
  419. /// depends on the number of simulated clients, which is specified
  420. /// from the command line. It uses \ref CommandOptions object to retrieve
  421. /// number of clients. Since the last six octets of DUID are constructed
  422. /// from the MAC address, this function uses \ref generateMacAddress
  423. /// internally to randomize the DUID.
  424. ///
  425. /// \todo add support for other types of DUID.
  426. ///
  427. /// \param [out] randomized number of bytes randomized (initial value
  428. /// is ignored).
  429. /// \throw isc::BadValue if \ref generateMacAddress throws.
  430. /// \return vector representing DUID.
  431. std::vector<uint8_t> generateDuid(uint8_t& randomized);
  432. /// \brief Generate MAC address.
  433. ///
  434. /// This method generates MAC address. The number of unique
  435. /// MAC addresses it can generate is determined by the number
  436. /// simulated DHCP clients specified from command line. It uses
  437. /// \ref CommandOptions object to retrieve number of clients.
  438. /// Based on this the random value is generated and added to
  439. /// the MAC address template (default MAC address).
  440. ///
  441. /// \param [out] randomized number of bytes randomized (initial
  442. /// value is ignored).
  443. /// \throw isc::BadValue if MAC address template (default or specified
  444. /// from the command line) has invalid size (expected 6 octets).
  445. /// \return generated MAC address.
  446. std::vector<uint8_t> generateMacAddress(uint8_t& randomized);
  447. /// \brief generate transaction id.
  448. ///
  449. /// Generate transaction id value (32-bit for DHCPv4,
  450. /// 24-bit for DHCPv6).
  451. ///
  452. /// \return generated transaction id.
  453. uint32_t generateTransid() {
  454. return (transid_gen_->generate());
  455. }
  456. /// \brief Returns a timeout for packet reception.
  457. ///
  458. /// The calculation is based on the value of the timestamp
  459. /// when the next set of packets is to be sent. If no packet is
  460. /// received until then, new packets are sent.
  461. ///
  462. /// \return A current timeout in microseconds.
  463. uint32_t getCurrentTimeout() const;
  464. /// \brief Return template buffer.
  465. ///
  466. /// Method returns template buffer at specified index.
  467. ///
  468. /// \param idx index of template buffer.
  469. /// \throw isc::OutOfRange if buffer index out of bounds.
  470. /// \return reference to template buffer.
  471. TemplateBuffer getTemplateBuffer(const size_t idx) const;
  472. /// \brief Reads packet templates from files.
  473. ///
  474. /// Method iterates through all specified template files, reads
  475. /// their content and stores it in class internal buffers. Template
  476. /// file names are specified from the command line with -T option.
  477. ///
  478. /// \throw isc::BadValue if any of the template files does not exist,
  479. /// contains characters other than hexadecimal digits or spaces.
  480. /// \throw OutOfRange if any of the template files is empty or has
  481. /// odd number of hexadecimal digits.
  482. void initPacketTemplates();
  483. /// \brief Initializes Statistics Manager.
  484. ///
  485. /// This function initializes Statistics Manager. If there is
  486. /// the one initialized already it is released.
  487. void initializeStatsMgr();
  488. /// \brief Open socket to communicate with DHCP server.
  489. ///
  490. /// Method opens socket and binds it to local address. Function will
  491. /// use either interface name, local address or server address
  492. /// to create a socket, depending on what is available (specified
  493. /// from the command line). If socket can't be created for any
  494. /// reason, exception is thrown.
  495. /// If destination address is broadcast (for DHCPv4) or multicast
  496. /// (for DHCPv6) than broadcast or multicast option is set on
  497. /// the socket. Opened socket is registered and managed by IfaceMgr.
  498. ///
  499. /// \throw isc::BadValue if socket can't be created for given
  500. /// interface, local address or remote address.
  501. /// \throw isc::InvalidOperation if broadcast option can't be
  502. /// set for the v4 socket or if multicast option can't be set
  503. /// for the v6 socket.
  504. /// \throw isc::Unexpected if internal unexpected error occurred.
  505. /// \return socket descriptor.
  506. int openSocket() const;
  507. /// \brief Print intermediate statistics.
  508. ///
  509. /// Print brief statistics regarding number of sent packets,
  510. /// received packets and dropped packets so far.
  511. void printIntermediateStats();
  512. /// \brief Print rate statistics.
  513. ///
  514. /// Method print packet exchange rate statistics.
  515. void printRate() const;
  516. /// \brief Print performance statistics.
  517. ///
  518. /// Method prints performance statistics.
  519. /// \throws isc::InvalidOperation if Statistics Manager was
  520. /// not initialized.
  521. void printStats() const;
  522. /// \brief Process received DHCPv4 packet.
  523. ///
  524. /// Method performs processing of the received DHCPv4 packet,
  525. /// updates statistics and responds to the server if required,
  526. /// e.g. when OFFER packet arrives, this function will initiate
  527. /// REQUEST message to the server.
  528. ///
  529. /// \warning this method does not check if provided socket is
  530. /// valid (specifically if v4 socket for received v4 packet).
  531. ///
  532. /// \param [in] socket socket to be used.
  533. /// \param [in] pkt4 object representing DHCPv4 packet received.
  534. /// \throw isc::BadValue if unknown message type received.
  535. /// \throw isc::Unexpected if unexpected error occurred.
  536. void processReceivedPacket4(const TestControlSocket& socket,
  537. const dhcp::Pkt4Ptr& pkt4);
  538. /// \brief Process received DHCPv6 packet.
  539. ///
  540. /// Method performs processing of the received DHCPv6 packet,
  541. /// updates statistics and responds to the server if required,
  542. /// e.g. when ADVERTISE packet arrives, this function will initiate
  543. /// REQUEST message to the server.
  544. ///
  545. /// \warning this method does not check if provided socket is
  546. /// valid (specifically if v4 socket for received v4 packet).
  547. ///
  548. /// \param [in] socket socket to be used.
  549. /// \param [in] pkt6 object representing DHCPv6 packet received.
  550. /// \throw isc::BadValue if unknown message type received.
  551. /// \throw isc::Unexpected if unexpected error occurred.
  552. void processReceivedPacket6(const TestControlSocket& socket,
  553. const dhcp::Pkt6Ptr& pkt6);
  554. /// \brief Receive DHCPv4 or DHCPv6 packets from the server.
  555. ///
  556. /// Method receives DHCPv4 or DHCPv6 packets from the server.
  557. /// This function will call \ref processReceivedPacket4 or
  558. /// \ref processReceivedPacket6 depending if DHCPv4 or DHCPv6 packet
  559. /// has arrived.
  560. ///
  561. /// \warning this method does not check if provided socket is
  562. /// valid. Ensure that it is valid prior to calling it.
  563. ///
  564. /// \param socket socket to be used.
  565. /// \throw isc::BadValue if unknown message type received.
  566. /// \throw isc::Unexpected if unexpected error occurred.
  567. /// \return number of received packets.
  568. uint64_t receivePackets(const TestControlSocket& socket);
  569. /// \brief Register option factory functions for DHCPv4
  570. ///
  571. /// Method registers option factory functions for DHCPv4.
  572. /// These functions are called to create instances of DHCPv4
  573. /// options. Call \ref dhcp::Option::factory to invoke factory
  574. /// function for particular option. Don't use this function directly.
  575. /// Use \ref registerOptionFactories instead.
  576. void registerOptionFactories4() const;
  577. /// \brief Register option factory functions for DHCPv6
  578. ///
  579. /// Method registers option factory functions for DHCPv6.
  580. /// These functions are called to create instances of DHCPv6
  581. /// options. Call \ref dhcp::Option::factory to invoke factory
  582. /// function for particular option. Don't use this function directly.
  583. /// Use \ref registerOptionFactories instead.
  584. void registerOptionFactories6() const;
  585. /// \brief Register option factory functions for DHCPv4 or DHCPv6.
  586. ///
  587. /// Method registers option factory functions for DHCPv4 or DHCPv6,
  588. /// depending in which mode test is currently running.
  589. void registerOptionFactories() const;
  590. /// \brief Resets internal state of the object.
  591. ///
  592. /// Method resets internal state of the object. It has to be
  593. /// called before new test is started.
  594. void reset();
  595. /// \brief Save the first DHCPv4 sent packet of the specified type.
  596. ///
  597. /// This method saves first packet of the specified being sent
  598. /// to the server if user requested diagnostics flag 'T'. In
  599. /// such case program has to print contents of selected packets
  600. /// being sent to the server. It collects first packets of each
  601. /// type and keeps them around until test finishes. Then they
  602. /// are printed to the user. If packet of specified type has
  603. /// been already stored this function performs no operation.
  604. /// This function does not perform sanity check if packet
  605. /// pointer is valid. Make sure it is before calling it.
  606. ///
  607. /// \param pkt packet to be stored.
  608. inline void saveFirstPacket(const dhcp::Pkt4Ptr& pkt);
  609. /// \brief Save the first DHCPv6 sent packet of the specified type.
  610. ///
  611. /// This method saves first packet of the specified being sent
  612. /// to the server if user requested diagnostics flag 'T'. In
  613. /// such case program has to print contents of selected packets
  614. /// being sent to the server. It collects first packets of each
  615. /// type and keeps them around until test finishes. Then they
  616. /// are printed to the user. If packet of specified type has
  617. /// been already stored this function performs no operation.
  618. /// This function does not perform sanity check if packet
  619. /// pointer is valid. Make sure it is before calling it.
  620. ///
  621. /// \param pkt packet to be stored.
  622. inline void saveFirstPacket(const dhcp::Pkt6Ptr& pkt);
  623. /// \brief Send DHCPv4 DISCOVER message.
  624. ///
  625. /// Method creates and sends DHCPv4 DISCOVER message to the server
  626. /// with the following options:
  627. /// - MESSAGE_TYPE set to DHCPDISCOVER
  628. /// - PARAMETER_REQUEST_LIST with the same list of requested options
  629. /// as described in \ref factoryRequestList4.
  630. /// The transaction id and MAC address are randomly generated for
  631. /// the message. Range of unique MAC addresses generated depends
  632. /// on the number of clients specified from the command line.
  633. /// Copy of sent packet is stored in the stats_mgr4_ object to
  634. /// update statistics.
  635. ///
  636. /// \param socket socket to be used to send the message.
  637. /// \param preload preload mode, packets not included in statistics.
  638. ///
  639. /// \throw isc::Unexpected if failed to create new packet instance.
  640. /// \throw isc::BadValue if MAC address has invalid length.
  641. /// \throw isc::dhcp::SocketWriteError if failed to send the packet.
  642. void sendDiscover4(const TestControlSocket& socket,
  643. const bool preload = false);
  644. /// \brief Send DHCPv4 DISCOVER message from template.
  645. ///
  646. /// Method sends DHCPv4 DISCOVER message from template. The
  647. /// template data is expected to be in binary format. Provided
  648. /// buffer is copied and parts of it are replaced with actual
  649. /// data (e.g. MAC address, transaction id etc.).
  650. /// Copy of sent packet is stored in the stats_mgr4_ object to
  651. /// update statistics.
  652. ///
  653. /// \param socket socket to be used to send the message.
  654. /// \param template_buf buffer holding template packet.
  655. /// \param preload preload mode, packets not included in statistics.
  656. ///
  657. /// \throw isc::OutOfRange if randomization offset is out of bounds.
  658. /// \throw isc::dhcp::SocketWriteError if failed to send the packet.
  659. void sendDiscover4(const TestControlSocket& socket,
  660. const std::vector<uint8_t>& template_buf,
  661. const bool preload = false);
  662. /// \brief Send number of packets to initiate new exchanges.
  663. ///
  664. /// Method initiates the new DHCP exchanges by sending number
  665. /// of DISCOVER (DHCPv4) or SOLICIT (DHCPv6) packets. If preload
  666. /// mode was requested sent packets will not be counted in
  667. /// the statistics. The responses from the server will be
  668. /// received and counted as orphans because corresponding sent
  669. /// packets are not included in StatsMgr for match.
  670. /// When preload mode is disabled and diagnostics flag 'i' is
  671. /// specified then function will be trying to receive late packets
  672. /// before new packets are sent to the server. Statistics of
  673. /// late received packets is updated accordingly.
  674. ///
  675. /// \todo do not count responses in preload mode as orphans.
  676. ///
  677. /// \param socket socket to be used to send packets.
  678. /// \param packets_num number of packets to be sent.
  679. /// \param preload preload mode, packets not included in statistics.
  680. /// \throw isc::Unexpected if thrown by packet sending method.
  681. /// \throw isc::InvalidOperation if thrown by packet sending method.
  682. /// \throw isc::OutOfRange if thrown by packet sending method.
  683. void sendPackets(const TestControlSocket &socket,
  684. const uint64_t packets_num,
  685. const bool preload = false);
  686. /// \brief Send number of DHCPREQUEST (renew) messages to a server.
  687. ///
  688. /// \param socket An object representing socket to be used to send packets.
  689. /// \param msg_num A number of messages to be sent.
  690. ///
  691. /// \return A number of messages actually sent.
  692. uint64_t sendMultipleRequests(const TestControlSocket& socket,
  693. const uint64_t msg_num);
  694. /// \brief Send number of DHCPv6 Renew or Release messages to the server.
  695. ///
  696. /// \param socket An object representing socket to be used to send packets.
  697. /// \param msg_type A type of the messages to be sent (DHCPV6_RENEW or
  698. /// DHCPV6_RELEASE).
  699. /// \param msg_num A number of messages to be sent.
  700. ///
  701. /// \return A number of messages actually sent.
  702. uint64_t sendMultipleMessages6(const TestControlSocket& socket,
  703. const uint32_t msg_type,
  704. const uint64_t msg_num);
  705. /// \brief Send DHCPv4 renew (DHCPREQUEST) using specified socket.
  706. ///
  707. /// \param socket An object encapsulating socket to be used to send
  708. /// a packet.
  709. ///
  710. /// \return true if the message has been sent, false otherwise.
  711. bool sendRequestFromAck(const TestControlSocket& socket);
  712. /// \brief Send DHCPv6 Renew or Release message using specified socket.
  713. ///
  714. /// This method will select an existing lease from the Reply packet cache
  715. /// If there is no lease that can be renewed or released this method will
  716. /// return false.
  717. ///
  718. /// \param msg_type A type of the message to be sent (DHCPV6_RENEW or
  719. /// DHCPV6_RELEASE).
  720. /// \param socket An object encapsulating socket to be used to send
  721. /// a packet.
  722. ///
  723. /// \return true if the message has been sent, false otherwise.
  724. bool sendMessageFromReply(const uint16_t msg_type,
  725. const TestControlSocket& socket);
  726. /// \brief Send DHCPv4 REQUEST message.
  727. ///
  728. /// Method creates and sends DHCPv4 REQUEST message to the server.
  729. /// Copy of sent packet is stored in the stats_mgr4_ object to
  730. /// update statistics.
  731. ///
  732. /// \param socket socket to be used to send message.
  733. /// \param discover_pkt4 DISCOVER packet sent.
  734. /// \param offer_pkt4 OFFER packet object.
  735. ///
  736. /// \throw isc::Unexpected if unexpected error occurred.
  737. /// \throw isc::InvalidOperation if Statistics Manager has not been
  738. /// initialized.
  739. /// \throw isc::dhcp::SocketWriteError if failed to send the packet.
  740. void sendRequest4(const TestControlSocket& socket,
  741. const dhcp::Pkt4Ptr& discover_pkt4,
  742. const dhcp::Pkt4Ptr& offer_pkt4);
  743. /// \brief Send DHCPv4 REQUEST message from template.
  744. ///
  745. /// Method sends DHCPv4 REQUEST message from template.
  746. /// Copy of sent packet is stored in the stats_mgr4_ object to
  747. /// update statistics.
  748. ///
  749. /// \param socket socket to be used to send message.
  750. /// \param template_buf buffer holding template packet.
  751. /// \param discover_pkt4 DISCOVER packet sent.
  752. /// \param offer_pkt4 OFFER packet received.
  753. ///
  754. /// \throw isc::dhcp::SocketWriteError if failed to send the packet.
  755. void sendRequest4(const TestControlSocket& socket,
  756. const std::vector<uint8_t>& template_buf,
  757. const dhcp::Pkt4Ptr& discover_pkt4,
  758. const dhcp::Pkt4Ptr& offer_pkt4);
  759. /// \brief Send DHCPv6 REQUEST message.
  760. ///
  761. /// Method creates and sends DHCPv6 REQUEST message to the server
  762. /// with the following options:
  763. /// - D6O_ELAPSED_TIME
  764. /// - D6O_CLIENTID
  765. /// - D6O_SERVERID
  766. /// Copy of sent packet is stored in the stats_mgr6_ object to
  767. /// update statistics.
  768. ///
  769. /// \param socket socket to be used to send message.
  770. /// \param advertise_pkt6 ADVERTISE packet object.
  771. /// \throw isc::Unexpected if unexpected error occurred.
  772. /// \throw isc::InvalidOperation if Statistics Manager has not been
  773. /// initialized.
  774. ///
  775. /// \throw isc::dhcp::SocketWriteError if failed to send the packet.
  776. void sendRequest6(const TestControlSocket& socket,
  777. const dhcp::Pkt6Ptr& advertise_pkt6);
  778. /// \brief Send DHCPv6 REQUEST message from template.
  779. ///
  780. /// Method sends DHCPv6 REQUEST message from template.
  781. /// Copy of sent packet is stored in the stats_mgr6_ object to
  782. /// update statistics.
  783. ///
  784. /// \param socket socket to be used to send message.
  785. /// \param template_buf packet template buffer.
  786. /// \param advertise_pkt6 ADVERTISE packet object.
  787. ///
  788. /// \throw isc::dhcp::SocketWriteError if failed to send the packet.
  789. void sendRequest6(const TestControlSocket& socket,
  790. const std::vector<uint8_t>& template_buf,
  791. const dhcp::Pkt6Ptr& advertise_pkt6);
  792. /// \brief Send DHCPv6 SOLICIT message.
  793. ///
  794. /// Method creates and sends DHCPv6 SOLICIT message to the server
  795. /// with the following options:
  796. /// - D6O_ELAPSED_TIME,
  797. /// - D6O_RAPID_COMMIT if rapid commit is requested in command line,
  798. /// - D6O_CLIENTID,
  799. /// - D6O_ORO (Option Request Option),
  800. /// - D6O_IA_NA.
  801. /// Copy of sent packet is stored in the stats_mgr6_ object to
  802. /// update statistics.
  803. ///
  804. /// \param socket socket to be used to send the message.
  805. /// \param preload mode, packets not included in statistics.
  806. ///
  807. /// \throw isc::Unexpected if failed to create new packet instance.
  808. /// \throw isc::dhcp::SocketWriteError if failed to send the packet.
  809. void sendSolicit6(const TestControlSocket& socket,
  810. const bool preload = false);
  811. /// \brief Send DHCPv6 SOLICIT message from template.
  812. ///
  813. /// Method sends DHCPv6 SOLICIT message from template.
  814. /// Copy of sent packet is stored in the stats_mgr6_ object to
  815. /// update statistics.
  816. ///
  817. /// \param socket socket to be used to send the message.
  818. /// \param template_buf packet template buffer.
  819. /// \param preload mode, packets not included in statistics.
  820. ///
  821. /// \throw isc::dhcp::SocketWriteError if failed to send the packet.
  822. void sendSolicit6(const TestControlSocket& socket,
  823. const std::vector<uint8_t>& template_buf,
  824. const bool preload = false);
  825. /// \brief Set default DHCPv4 packet parameters.
  826. ///
  827. /// This method sets default parameters on the DHCPv4 packet:
  828. /// - interface name,
  829. /// - local port = 68 (DHCP client port),
  830. /// - remote port = 67 (DHCP server port),
  831. /// - server's address,
  832. /// - GIADDR = local address where socket is bound to,
  833. /// - hops = 1 (pretending that we are a relay)
  834. ///
  835. /// \param socket socket used to send the packet.
  836. /// \param pkt reference to packet to be configured.
  837. void setDefaults4(const TestControlSocket& socket,
  838. const dhcp::Pkt4Ptr& pkt);
  839. /// \brief Set default DHCPv6 packet parameters.
  840. ///
  841. /// This method sets default parameters on the DHCPv6 packet:
  842. /// - interface name,
  843. /// - interface index,
  844. /// - local port,
  845. /// - remote port,
  846. /// - local address,
  847. /// - remote address (server).
  848. ///
  849. /// \param socket socket used to send the packet.
  850. /// \param pkt reference to packet to be configured.
  851. void setDefaults6(const TestControlSocket& socket,
  852. const dhcp::Pkt6Ptr& pkt);
  853. /// \brief Find if diagnostic flag has been set.
  854. ///
  855. /// \param diag diagnostic flag (a,e,i,s,r,t,T).
  856. /// \return true if diagnostics flag has been set.
  857. bool testDiags(const char diag) const;
  858. protected:
  859. /// \brief Increments counter of late sent messages if required.
  860. ///
  861. /// This function checks if the message or set of messages of a given type,
  862. /// were sent later than their due time. If they were sent late, it is
  863. /// an indication that the perfdhcp doesn't catch up with the desired rate
  864. /// for sending messages.
  865. ///
  866. /// \param rate_control An object tracking due times for a particular
  867. /// type of messages.
  868. void checkLateMessages(RateControl& rate_control);
  869. /// \brief Copies IA_NA or IA_PD option from one packet to another.
  870. ///
  871. /// This function checks the lease-type specified in the command line
  872. /// with option -e<lease-type>. If 'address-only' value has been specified
  873. /// this function expects that IA_NA option is present in the packet
  874. /// encapsulated by pkt_from object. If 'prefix-only' value has been
  875. /// specified, this function expects that IA_PD option is present in the
  876. /// packet encapsulated by pkt_to object.
  877. ///
  878. /// \param [in] pkt_from A packet from which options should be copied.
  879. /// \param [out] pkt_to A packet to which options should be copied.
  880. ///
  881. /// \throw isc::perfdhcp::OptionNotFound if a required option is not
  882. /// found in the packet from which options should be copied.
  883. /// \throw isc::BadValue if any of the specified pointers to packets
  884. /// is NULL.
  885. void copyIaOptions(const dhcp::Pkt6Ptr& pkt_from, dhcp::Pkt6Ptr& pkt_to);
  886. /// \brief Convert binary value to hex string.
  887. ///
  888. /// \todo Consider moving this function to src/lib/util.
  889. ///
  890. /// \param b byte to convert.
  891. /// \return hex string.
  892. std::string byte2Hex(const uint8_t b) const;
  893. /// \brief Calculate elapsed time between two packets.
  894. ///
  895. /// This function calculates the time elapsed between two packets. If
  896. /// the timestamp of the pkt2 is greater than timestamp of the pkt1,
  897. /// the positive value is returned. If the pkt2 timestamp is equal or
  898. /// less than pkt1 timestamp, 0 is returned.
  899. ///
  900. /// \tparam T Pkt4Ptr or Pkt6Ptr class.
  901. /// \param pkt1 first packet.
  902. /// \param pkt2 second packet.
  903. /// \throw InvalidOperation if packet timestamps are invalid.
  904. /// \return elapsed time in milliseconds between pkt1 and pkt2.
  905. template<class T>
  906. uint32_t getElapsedTime(const T& pkt1, const T& pkt2);
  907. /// \brief Return elapsed time offset in a packet.
  908. ///
  909. /// \return elapsed time offset in packet.
  910. int getElapsedTimeOffset() const;
  911. /// \brief Return randomization offset in a packet.
  912. ///
  913. /// \return randomization offset in packet.
  914. int getRandomOffset(const int arg_idx) const;
  915. /// \brief Return requested ip offset in a packet.
  916. ///
  917. /// \return randomization offset in a packet.
  918. int getRequestedIpOffset() const;
  919. /// \brief Return server id offset in a packet.
  920. ///
  921. /// \return server id offset in packet.
  922. int getServerIdOffset() const;
  923. /// \brief Return transaction id offset in a packet.
  924. ///
  925. /// \param arg_idx command line argument index to be used.
  926. /// If multiple -X parameters specified it points to the
  927. /// one to be used.
  928. /// \return transaction id offset in packet.
  929. int getTransactionIdOffset(const int arg_idx) const;
  930. /// \brief Get number of received packets.
  931. ///
  932. /// Get the number of received packets from the Statistics Manager.
  933. /// Function may throw if Statistics Manager object is not
  934. /// initialized.
  935. ///
  936. /// \note The method parameter is non-const to suppress the cppcheck
  937. /// warning about the object being passed by value. However, passing
  938. /// an enum by reference doesn't make much sense. At the same time,
  939. /// removing the constness should be pretty safe for this function.
  940. ///
  941. /// \param xchg_type packet exchange type.
  942. /// \return number of received packets.
  943. uint64_t getRcvdPacketsNum(ExchangeType xchg_type) const;
  944. /// \brief Get number of sent packets.
  945. ///
  946. /// Get the number of sent packets from the Statistics Manager.
  947. /// Function may throw if Statistics Manager object is not
  948. /// initialized.
  949. ///
  950. /// \note The method parameter is non-const to suppress the cppcheck
  951. /// warning about the object being passed by value. However, passing
  952. /// an enum by reference doesn't make much sense. At the same time,
  953. /// removing the constness should be pretty safe for this function.
  954. ///
  955. /// \param xchg_type packet exchange type.
  956. /// \return number of sent packets.
  957. uint64_t getSentPacketsNum(ExchangeType xchg_type) const;
  958. /// \brief Handle child signal.
  959. ///
  960. /// Function handles child signal by waiting for
  961. /// the process to complete.
  962. ///
  963. /// \param sig signal (ignored)
  964. static void handleChild(int sig);
  965. /// \brief Handle interrupt signal.
  966. ///
  967. /// Function sets flag indicating that program has been
  968. /// interrupted.
  969. ///
  970. /// \param sig signal (ignored)
  971. static void handleInterrupt(int sig);
  972. /// \brief Print main diagnostics data.
  973. ///
  974. /// Method prints main diagnostics data.
  975. void printDiagnostics() const;
  976. /// \brief Print template information
  977. ///
  978. /// \param packet_type packet type.
  979. void printTemplate(const uint8_t packet_type) const;
  980. /// \brief Print templates information.
  981. ///
  982. /// Method prints information about data offsets
  983. /// in packet templates and their contents.
  984. void printTemplates() const;
  985. /// \brief Read DHCP message template from file.
  986. ///
  987. /// Method reads DHCP message template from file and
  988. /// converts it to binary format. Read data is appended
  989. /// to template_buffers_ vector.
  990. ///
  991. /// \param file_name name of the packet template file.
  992. /// \throw isc::OutOfRange if file is empty or has odd number
  993. /// of hexadecimal digits.
  994. /// \throw isc::BadValue if file contains characters other than
  995. /// spaces or hexadecimal digits.
  996. void readPacketTemplate(const std::string& file_name);
  997. /// \brief Run wrapped command.
  998. ///
  999. /// \param do_stop execute wrapped command with "stop" argument.
  1000. void runWrapped(bool do_stop = false) const;
  1001. /// \brief Convert vector in hexadecimal string.
  1002. ///
  1003. /// \todo Consider moving this function to src/lib/util.
  1004. ///
  1005. /// \param vec vector to be converted.
  1006. /// \param separator separator.
  1007. std::string vector2Hex(const std::vector<uint8_t>& vec,
  1008. const std::string& separator = "") const;
  1009. /// \brief A rate control class for Discover and Solicit messages.
  1010. RateControl basic_rate_control_;
  1011. /// \brief A rate control class for Renew messages.
  1012. RateControl renew_rate_control_;
  1013. /// \brief A rate control class for Release messages.
  1014. RateControl release_rate_control_;
  1015. boost::posix_time::ptime last_report_; ///< Last intermediate report time.
  1016. StatsMgr4Ptr stats_mgr4_; ///< Statistics Manager 4.
  1017. StatsMgr6Ptr stats_mgr6_; ///< Statistics Manager 6.
  1018. PacketStorage<dhcp::Pkt4> ack_storage_; ///< A storage for DHCPACK messages.
  1019. PacketStorage<dhcp::Pkt6> reply_storage_; ///< A storage for reply messages.
  1020. NumberGeneratorPtr transid_gen_; ///< Transaction id generator.
  1021. NumberGeneratorPtr macaddr_gen_; ///< Numbers generator for MAC address.
  1022. /// Buffer holding server id received in first packet
  1023. dhcp::OptionBuffer first_packet_serverid_;
  1024. /// Packet template buffers.
  1025. TemplateBufferCollection template_buffers_;
  1026. /// First packets send. They are used at the end of the test
  1027. /// to print packet templates when diagnostics flag T is specified.
  1028. std::map<uint8_t, dhcp::Pkt4Ptr> template_packets_v4_;
  1029. std::map<uint8_t, dhcp::Pkt6Ptr> template_packets_v6_;
  1030. static bool interrupted_; ///< Is program interrupted.
  1031. };
  1032. } // namespace perfdhcp
  1033. } // namespace isc
  1034. #endif // TEST_CONTROL_H