test_control.h 31 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793
  1. // Copyright (C) 2012 Internet Systems Consortium, Inc. ("ISC")
  2. //
  3. // Permission to use, copy, modify, and/or distribute this software for any
  4. // purpose with or without fee is hereby granted, provided that the above
  5. // copyright notice and this permission notice appear in all copies.
  6. //
  7. // THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
  8. // REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
  9. // AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
  10. // INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
  11. // LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
  12. // OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
  13. // PERFORMANCE OF THIS SOFTWARE.
  14. #ifndef __TEST_CONTROL_H
  15. #define __TEST_CONTROL_H
  16. #include <string>
  17. #include <vector>
  18. #include <boost/noncopyable.hpp>
  19. #include <boost/shared_ptr.hpp>
  20. #include <boost/function.hpp>
  21. #include <boost/date_time/posix_time/posix_time.hpp>
  22. #include <dhcp/iface_mgr.h>
  23. #include <dhcp/dhcp6.h>
  24. #include <dhcp/pkt4.h>
  25. #include <dhcp/pkt6.h>
  26. #include "stats_mgr.h"
  27. namespace isc {
  28. namespace perfdhcp {
  29. /// \brief Test Control class.
  30. ///
  31. /// This class is responsible for executing DHCP performance
  32. /// test end to end.
  33. ///
  34. /// Option factory functions are registered using
  35. /// \ref dhcp::LibDHCP::OptionFactoryRegister. Registered factory functions
  36. /// provide a way to create options of the same type in the same way.
  37. /// When new option instance is needed the corresponding factory
  38. /// function is called to create it. This is done by calling
  39. /// \ref dhcp::Option::factory with DHCP message type specified as one of
  40. /// parameters. Some of the parameters passed to factory function
  41. /// may be ignored (e.g. option buffer).
  42. class TestControl : public boost::noncopyable {
  43. public:
  44. /// Default transaction id offset.
  45. static const size_t DHCPV4_TRANSID_OFFSET = 4;
  46. /// Default offset of MAC's last octet.
  47. static const size_t DHCPV4_RANDOMIZATION_OFFSET = 35;
  48. /// Default elapsed time offset.
  49. static const size_t DHCPV4_ELAPSED_TIME_OFFSET = 8;
  50. /// Default server id offset.
  51. static const size_t DHCPV4_SERVERID_OFFSET = 54;
  52. /// Default requested ip offset.
  53. static const size_t DHCPV4_REQUESTED_IP_OFFSET = 240;
  54. /// Default DHCPV6 transaction id offset.
  55. static const size_t DHCPV6_TRANSID_OFFSET = 1;
  56. /// Default DHCPV6 randomization offset (last octet of DUID)
  57. static const size_t DHCPV6_RANDOMIZATION_OFFSET = 21;
  58. /// Default DHCPV6 elapsed time offset.
  59. static const size_t DHCPV6_ELAPSED_TIME_OFFSET = 84;
  60. /// Default DHCPV6 server id offset.
  61. static const size_t DHCPV6_SERVERID_OFFSET = 22;
  62. /// Default DHCPV6 IA_NA offset.
  63. static const size_t DHCPV6_IA_NA_OFFSET = 40;
  64. /// Statistics Manager for DHCPv4.
  65. typedef StatsMgr<dhcp::Pkt4> StatsMgr4;
  66. /// Pointer to Statistics Manager for DHCPv4;
  67. typedef boost::shared_ptr<StatsMgr4> StatsMgr4Ptr;
  68. /// Statictics Manager for DHCPv6.
  69. typedef StatsMgr<dhcp::Pkt6> StatsMgr6;
  70. /// Pointer to Statistics Manager for DHCPv6.
  71. typedef boost::shared_ptr<StatsMgr6> StatsMgr6Ptr;
  72. /// Packet exchange type.
  73. typedef StatsMgr<>::ExchangeType ExchangeType;
  74. /// Packet template buffer.
  75. typedef std::vector<uint8_t> TemplateBuffer;
  76. /// Packet template buffers list.
  77. typedef std::vector<TemplateBuffer> TemplateBufferCollection;
  78. /// \brief Socket wrapper structure.
  79. ///
  80. /// This is the wrapper that holds descriptor of the socket
  81. /// used to run DHCP test. The wrapped socket is closed in
  82. /// the destructor. This prevents resource leaks when when
  83. /// function that created the socket ends (normally or
  84. /// when exception occurs). This structure extends parent
  85. /// structure with new field ifindex_ that holds interface
  86. /// index where socket is bound to.
  87. struct TestControlSocket : public dhcp::IfaceMgr::SocketInfo {
  88. /// Interface index.
  89. uint16_t ifindex_;
  90. /// Is socket valid. It will not be valid if the provided socket
  91. /// descriptor does not point to valid socket.
  92. bool valid_;
  93. /// \brief Constructor of socket wrapper class.
  94. ///
  95. /// This constructor uses provided socket descriptor to
  96. /// find the name of the interface where socket has been
  97. /// bound to. If provided socket descriptor is invalid then
  98. /// valid_ field is set to false;
  99. ///
  100. /// \param socket socket descriptor.
  101. TestControlSocket(const int socket);
  102. /// \brief Destriuctor of the socket wrapper class.
  103. ///
  104. /// Destructor closes wrapped socket.
  105. ~TestControlSocket();
  106. private:
  107. /// \brief Initialize socket data.
  108. ///
  109. /// This method initializes members of the class that Interface
  110. /// Manager holds: interface name, local address.
  111. ///
  112. /// \throw isc::BadValue if interface for specified socket
  113. /// descriptor does not exist.
  114. void initSocketData();
  115. };
  116. /// \brief Number generator class.
  117. ///
  118. /// This is default numbers generator class. The member function is
  119. /// used to generate uint32_t values. Other generator classes should
  120. /// derive from this one to implement generation algorithms
  121. /// (e.g. sequencial or based on random function).
  122. class NumberGenerator {
  123. public:
  124. /// \brief Generate number.
  125. ///
  126. /// \return Generate number.
  127. virtual uint32_t generate() = 0;
  128. };
  129. /// The default generator pointer.
  130. typedef boost::shared_ptr<NumberGenerator> NumberGeneratorPtr;
  131. /// \brief Sequencial numbers generatorc class.
  132. class SequencialGenerator : public NumberGenerator {
  133. public:
  134. /// \brief Constructor.
  135. ///
  136. /// \param range maximum number generated. If 0 is given then
  137. /// range defaults to maximym uint32_t value.
  138. SequencialGenerator(uint32_t range = 0xFFFFFFFF) :
  139. NumberGenerator(),
  140. num_(0),
  141. range_(range) {
  142. if (range_ == 0) {
  143. range_ = 0xFFFFFFFF;
  144. }
  145. }
  146. /// \brief Generate number sequencialy.
  147. ///
  148. /// \return generated number.
  149. virtual uint32_t generate() {
  150. uint32_t num = num_;
  151. num_ = (num_ + 1) % range_;
  152. return (num);
  153. }
  154. private:
  155. uint32_t num_; ///< Current number.
  156. uint32_t range_; ///< Maximum number generated.
  157. };
  158. /// \brief Length of the Ethernet HW address (MAC) in bytes.
  159. ///
  160. /// \todo Make this variable length as there are cases when HW
  161. /// address is longer than this (e.g. 20 bytes).
  162. static const uint8_t HW_ETHER_LEN = 6;
  163. /// TestControl is a singleton class. This method returns reference
  164. /// to its sole instance.
  165. ///
  166. /// \return the only existing instance of test control
  167. static TestControl& instance();
  168. /// brief\ Run performance test.
  169. ///
  170. /// Method runs whole performance test. Command line options must
  171. /// be parsed prior to running this function. Othewise function will
  172. /// throw exception.
  173. ///
  174. /// \throw isc::InvalidOperation if command line options are not parsed.
  175. /// \throw isc::Unexpected if internal Test Controler error occured.
  176. void run();
  177. /// \brief Set new transaction id generator.
  178. ///
  179. /// \param generator generator object to be used.
  180. void setTransidGenerator(const NumberGeneratorPtr& generator) {
  181. transid_gen_.reset();
  182. transid_gen_ = generator;
  183. }
  184. /// \brief Set new MAC address generator.
  185. ///
  186. /// Set numbers generator that will be used to generate various
  187. /// MAC addresses to simulate number of clients.
  188. ///
  189. /// \param generator object to be used.
  190. void setMacAddrGenerator(const NumberGeneratorPtr& generator) {
  191. macaddr_gen_.reset();
  192. macaddr_gen_ = generator;
  193. }
  194. // We would really like following methods and members to be private but
  195. // they have to be accessible for unit-testing. Another, possibly better,
  196. // solution is to make this class friend of test class but this is not
  197. // what's followed in other classes.
  198. protected:
  199. /// \brief Default constructor.
  200. ///
  201. /// Default constructor is protected as the object can be created
  202. /// only via \ref instance method.
  203. TestControl();
  204. /// \brief Check if test exit condtitions fulfilled.
  205. ///
  206. /// Method checks if the test exit conditions are fulfiled.
  207. /// Exit conditions are checked periodically from the
  208. /// main loop. Program should break the main loop when
  209. /// this method returns true. It is calling function
  210. /// responsibility to break main loop gracefully and
  211. /// cleanup after test execution.
  212. ///
  213. /// \return true if any of the exit conditions is fulfiled.
  214. bool checkExitConditions() const;
  215. /// \brief Factory function to create DHCPv6 ELAPSED_TIME option.
  216. ///
  217. /// This factory function creates DHCPv6 ELAPSED_TIME option instance.
  218. /// If empty buffer is passed the option buffer will be initialized
  219. /// to length 2 and values will be initialized to zeros. Otherwise
  220. /// function will initialize option buffer with values in passed buffer.
  221. ///
  222. /// \param u universe (ignored)
  223. /// \param type option-type (ignored).
  224. /// \param buf option-buffer containing option content (2 bytes) or
  225. /// empty buffer if option content has to be set to default (0) value.
  226. /// \throw if elapsed time buffer size is neither 2 nor 0.
  227. /// \return instance o the option.
  228. static dhcp::OptionPtr
  229. factoryElapsedTime6(dhcp::Option::Universe u,
  230. uint16_t type,
  231. const dhcp::OptionBuffer& buf);
  232. /// \brief Factory function to create generic option.
  233. ///
  234. /// This factory function creates option with specified universe,
  235. /// type and buf. It does not have any additional logic validating
  236. /// the buffer contents, size etc.
  237. ///
  238. /// \param u universe (V6 or V4).
  239. /// \param type option-type (ignored).
  240. /// \param buf option-buffer.
  241. /// \return instance o the option.
  242. static dhcp::OptionPtr factoryGeneric(dhcp::Option::Universe u,
  243. uint16_t type,
  244. const dhcp::OptionBuffer& buf);
  245. /// \brief Factory function to create IA_NA option.
  246. ///
  247. /// This factory function creates DHCPv6 IA_NA option instance.
  248. ///
  249. /// \todo add support for IA Address options.
  250. ///
  251. /// \param u universe (ignored).
  252. /// \param type option-type (ignored).
  253. /// \param buf option-buffer carrying IANA suboptions.
  254. /// \return instance of IA_NA option.
  255. static dhcp::OptionPtr factoryIana6(dhcp::Option::Universe u,
  256. uint16_t type,
  257. const dhcp::OptionBuffer& buf);
  258. /// \brief Factory function to create DHCPv6 ORO option.
  259. ///
  260. /// This factory function creates DHCPv6 Option Request Option instance.
  261. /// The created option will contain the following set of requested options:
  262. /// - D6O_NAME_SERVERS
  263. /// - D6O_DOMAIN_SEARCH
  264. ///
  265. /// \param u universe (ignored).
  266. /// \param type option-type (ignored).
  267. /// \param buf option-buffer (ignored).
  268. /// \return instance of ORO option.
  269. static dhcp::OptionPtr
  270. factoryOptionRequestOption6(dhcp::Option::Universe u,
  271. uint16_t type,
  272. const dhcp::OptionBuffer& buf);
  273. /// \brief Factory function to create DHCPv6 RAPID_COMMIT option instance.
  274. ///
  275. /// This factory function creates DHCPv6 RAPID_COMMIT option instance.
  276. /// The buffer passed to this option must be empty because option does
  277. /// not have any payload.
  278. ///
  279. /// \param u universe (ignored).
  280. /// \param type option-type (ignored).
  281. /// \param buf option-buffer (ignored).
  282. /// \return instance of RAPID_COMMIT option..
  283. static dhcp::OptionPtr factoryRapidCommit6(dhcp::Option::Universe u,
  284. uint16_t type,
  285. const dhcp::OptionBuffer& buf);
  286. /// \brief Factory function to create DHCPv4 Request List option.
  287. ///
  288. /// This factory function creayes DHCPv4 PARAMETER_REQUEST_LIST option
  289. /// instance with the following set of requested options:
  290. /// - DHO_SUBNET_MASK,
  291. /// - DHO_BROADCAST_ADDRESS,
  292. /// - DHO_TIME_OFFSET,
  293. /// - DHO_ROUTERS,
  294. /// - DHO_DOMAIN_NAME,
  295. /// - DHO_DOMAIN_NAME_SERVERS,
  296. /// - DHO_HOST_NAME.
  297. ///
  298. /// \param u universe (ignored).
  299. /// \param type option-type (ignored).
  300. /// \param buf option-buffer (ignored).
  301. /// \return instance o the generic option.
  302. static dhcp::OptionPtr factoryRequestList4(dhcp::Option::Universe u,
  303. uint16_t type,
  304. const dhcp::OptionBuffer& buf);
  305. /// \brief Generate DUID.
  306. ///
  307. /// Method generates unique DUID. The number of DUIDs it can generate
  308. /// depends on the number of simulated clients, which is specified
  309. /// from the command line. It uses \ref CommandOptions object to retrieve
  310. /// number of clients. Since the last six octets of DUID are constructed
  311. /// from the MAC address, this function uses \ref generateMacAddress
  312. /// internally to randomize the DUID.
  313. ///
  314. /// \todo add support for other types of DUID.
  315. ///
  316. /// \param [out] randomized number of bytes randomized (initial value
  317. /// is ignored).
  318. /// \throw isc::BadValue if \ref generateMacAddress throws.
  319. /// \return vector representing DUID.
  320. std::vector<uint8_t> generateDuid(uint8_t& randomized) const;
  321. /// \brief Generate MAC address.
  322. ///
  323. /// This method generates MAC address. The number of unique
  324. /// MAC addresses it can generate is determined by the number
  325. /// simulated DHCP clients specified from command line. It uses
  326. /// \ref CommandOptions object to retrieve number of clients.
  327. /// Based on this the random value is generated and added to
  328. /// the MAC address template (default MAC address).
  329. ///
  330. /// \param [out] randomized number of bytes randomized (initial
  331. /// value is ignored).
  332. /// \throw isc::BadValue if MAC address template (default or specified
  333. /// from the command line) has invalid size (expected 6 octets).
  334. /// \return generated MAC address.
  335. std::vector<uint8_t> generateMacAddress(uint8_t& randomized) const;
  336. /// \brief generate transaction id.
  337. ///
  338. /// Generate transaction id value (32-bit for DHCPv4,
  339. /// 24-bit for DHCPv6).
  340. ///
  341. /// \return generated transaction id.
  342. uint32_t generateTransid() {
  343. return (transid_gen_->generate());
  344. }
  345. /// \brief Returns number of exchanges to be started.
  346. ///
  347. /// Method returns number of new exchanges to be started as soon
  348. /// as possible to satisfy expected rate. Calculation used here
  349. /// is based on current time, due time calculated with
  350. /// \ref updateSendDue function and expected rate.
  351. ///
  352. /// \return number of exchanges to be started immediately.
  353. uint64_t getNextExchangesNum() const;
  354. /// \brief Return template buffer.
  355. ///
  356. /// Method returns template buffer at specified index.
  357. ///
  358. /// \param idx index of template buffer.
  359. /// \throw isc::OutOfRange if buffer index out of bounds.
  360. /// \return reference to template buffer.
  361. TemplateBuffer getTemplateBuffer(const size_t idx) const;
  362. /// \brief Reads packet templates from files.
  363. ///
  364. /// Method iterates through all specified template files, reads
  365. /// their content and stores it in class internal buffers. Template
  366. /// file names are specified from the command line with -T option.
  367. ///
  368. /// \throw isc::BadValue if any of the template files does not exist
  369. void initPacketTemplates();
  370. /// \brief Initializes Statistics Manager.
  371. ///
  372. /// This function initializes Statistics Manager. If there is
  373. /// the one initialized already it is released.
  374. void initializeStatsMgr();
  375. /// \brief Open socket to communicate with DHCP server.
  376. ///
  377. /// Method opens socket and binds it to local address. Function will
  378. /// use either interface name, local address or server address
  379. /// to create a socket, depending on what is available (specified
  380. /// from the command line). If socket can't be created for any
  381. /// reason, exception is thrown.
  382. /// If destination address is broadcast (for DHCPv4) or multicast
  383. /// (for DHCPv6) than broadcast or multicast option is set on
  384. /// the socket. Opened socket is registered and managed by IfaceMgr.
  385. ///
  386. /// \throw isc::BadValue if socket can't be created for given
  387. /// interface, local address or remote address.
  388. /// \throw isc::InvalidOperation if broadcast option can't be
  389. /// set for the v4 socket or if multicast option cat't be set
  390. /// for the v6 socket.
  391. /// \throw isc::Unexpected if interal unexpected error occured.
  392. /// \return socket descriptor.
  393. int openSocket() const;
  394. /// \brief Print intermediate statistics.
  395. ///
  396. /// Print brief statistics regarding number of sent packets,
  397. /// received packets and dropped packets so far.
  398. void printIntermediateStats();
  399. /// \brief Print rate statistics.
  400. ///
  401. /// Method print packet exchange rate statistics.
  402. void printRate() const;
  403. /// \brief Print performance statistics.
  404. ///
  405. /// Method prints performance statistics.
  406. /// \throws isc::InvalidOperation if Statistics Manager was
  407. /// not initialized.
  408. void printStats() const;
  409. /// \brief Receive DHCPv4 packet.
  410. ///
  411. /// Method performs reception of the DHCPv4 packet, updates
  412. /// statistics and responsds to the server if required, e.g.
  413. /// when OFFER packet arrives, this function will initiate
  414. /// REQUEST message to the server.
  415. ///
  416. /// \warning this method does not check if provided socket is
  417. /// valid (specifically if v4 socket for received v4 packet).
  418. ///
  419. /// \param [in] socket socket to be used.
  420. /// \param [in] pkt4 object representing DHCPv4 packet received.
  421. /// \throw isc::BadValue if unknown message type received.
  422. /// \throw isc::Unexpected if unexpected error occured.
  423. void receivePacket4(const TestControlSocket& socket,
  424. const dhcp::Pkt4Ptr& pkt4);
  425. /// \brief Receive DHCPv6 packet.
  426. ///
  427. /// Method performs reception of the DHCPv6 packet, updates
  428. /// statistics and responsds to the server if required, e.g.
  429. /// when ADVERTISE packet arrives, this function will initiate
  430. /// REQUEST message to the server.
  431. ///
  432. /// \warning this method does not check if provided socket is
  433. /// valid (specifically if v4 socket for received v4 packet).
  434. ///
  435. /// \param [in] socket socket to be used.
  436. /// \param [in] pkt6 object representing DHCPv6 packet received.
  437. /// \throw isc::BadValue if unknown message type received.
  438. /// \throw isc::Unexpected if unexpected error occured.
  439. void receivePacket6(const TestControlSocket& socket,
  440. const dhcp::Pkt6Ptr& pkt6);
  441. /// \brief Receive DHCPv4 or DHCPv6 packets from the server.
  442. ///
  443. /// Method receives DHCPv4 or DHCPv6 packets from the server.
  444. /// This function will call \ref receivePacket4 or
  445. /// \ref receivePacket6 depending if DHCPv4 or DHCPv6 packet
  446. /// has arrived.
  447. ///
  448. /// \warning this method does not check if provided socket is
  449. /// valid. Ensure that it is valid prior to calling it.
  450. ///
  451. /// \param socket socket to be used.
  452. /// \throw isc::BadValue if unknown message type received.
  453. /// \throw isc::Unexpected if unexpected error occured.
  454. void receivePackets(const TestControlSocket& socket);
  455. /// \brief Register option factory functions for DHCPv4
  456. ///
  457. /// Method registers option factory functions for DHCPv4.
  458. /// These functions are called to create instances of DHCPv4
  459. /// options. Call \ref dhcp::Option::factory to invoke factory
  460. /// function for particular option. Don't use this function directly.
  461. /// Use \ref registerOptionFactories instead.
  462. void registerOptionFactories4() const;
  463. /// \brief Register option factory functions for DHCPv6
  464. ///
  465. /// Method registers option factory functions for DHCPv6.
  466. /// These functions are called to create instances of DHCPv6
  467. /// options. Call \ref dhcp::Option::factory to invoke factory
  468. /// function for particular option. Don't use this function directly.
  469. /// Use \ref registerOptionFactories instead.
  470. void registerOptionFactories6() const;
  471. /// \brief Register option factory functions for DHCPv4 or DHCPv6.
  472. ///
  473. /// Method registers option factory functions for DHCPv4 or DHCPv6,
  474. /// depending in whch mode test is currently running.
  475. void registerOptionFactories() const;
  476. /// \brief Resets internal state of the object.
  477. ///
  478. /// Method resets internal state of the object. It has to be
  479. /// called before new test is started.
  480. void reset();
  481. /// \brief Send DHCPv4 DISCOVER message.
  482. ///
  483. /// Method creates and sends DHCPv4 DISCOVER message to the server
  484. /// with the following options:
  485. /// - MESSAGE_TYPE set to DHCPDISCOVER
  486. /// - PARAMETER_REQUEST_LIST with the same list of requested options
  487. /// as described in \ref factoryRequestList4.
  488. /// The transaction id and MAC address are randomly generated for
  489. /// the message. Range of unique MAC addresses generated depends
  490. /// on the number of clients specified from the command line.
  491. /// Copy of sent packet is stored in the stats_mgr4_ object to
  492. /// update statistics.
  493. ///
  494. /// \param socket socket to be used to send the message.
  495. /// \param preload preload mode, packets not included in statistics.
  496. /// \throw isc::Unexpected if failed to create new packet instance.
  497. /// \throw isc::BadValue if MAC address has invalid length.
  498. void sendDiscover4(const TestControlSocket& socket,
  499. const bool preload = false);
  500. /// \brief Send DHCPv4 DISCOVER message from template.
  501. ///
  502. /// Method sends DHCPv4 DISCOVER message from template. The
  503. /// template data is exepcted to be in binary format. Provided
  504. /// buffer is copied and parts of it are replaced with actual
  505. /// data (e.g. MAC address, transaction id etc.).
  506. /// Copy of sent packet is stored in the stats_mgr4_ object to
  507. /// update statistics.
  508. ///
  509. /// \param socket socket to be used to send the message.
  510. /// \param template_buf buffer holding template packet.
  511. /// \param preload preload mode, packets not included in statistics.
  512. /// \throw isc::OutOfRange if randomization offset is out of bounds.
  513. void sendDiscover4(const TestControlSocket& socket,
  514. const std::vector<uint8_t>& template_buf,
  515. const bool preload = false);
  516. /// \brief Send DHCPv4 REQUEST message.
  517. ///
  518. /// Method creates and sends DHCPv4 REQUEST message to the server.
  519. /// Copy of sent packet is stored in the stats_mgr4_ object to
  520. /// update statistics.
  521. ///
  522. /// \param socket socket to be used to send message.
  523. /// \param discover_pkt4 DISCOVER packet sent.
  524. /// \param offer_pkt4 OFFER packet object.
  525. /// \throw isc::Unexpected if unexpected error occured.
  526. /// \throw isc::InvalidOperation if Statistics Manager has not been
  527. /// initialized.
  528. void sendRequest4(const TestControlSocket& socket,
  529. const dhcp::Pkt4Ptr& discover_pkt4,
  530. const dhcp::Pkt4Ptr& offer_pkt4);
  531. /// \brief Send DHCPv4 REQUEST message from template.
  532. ///
  533. /// Method sends DHCPv4 REQUEST message from template.
  534. /// Copy of sent packet is stored in the stats_mgr4_ object to
  535. /// update statistics.
  536. ///
  537. /// \param socket socket to be used to send message.
  538. /// \param template_buf buffer holding template packet.
  539. /// \param discover_pkt4 DISCOVER packet sent.
  540. /// \param offer_pkt4 OFFER packet received.
  541. void sendRequest4(const TestControlSocket& socket,
  542. const std::vector<uint8_t>& template_buf,
  543. const dhcp::Pkt4Ptr& discover_pkt4,
  544. const dhcp::Pkt4Ptr& offer_pkt4);
  545. /// \brief Send DHCPv6 REQUEST message.
  546. ///
  547. /// Method creates and sends DHCPv6 REQUEST message to the server
  548. /// with the following options:
  549. /// - D6O_ELAPSED_TIME
  550. /// - D6O_CLIENTID
  551. /// - D6O_SERVERID
  552. /// Copy of sent packet is stored in the stats_mgr6_ object to
  553. /// update statistics.
  554. ///
  555. /// \param socket socket to be used to send message.
  556. /// \param advertise_pkt6 ADVERTISE packet object.
  557. /// \throw isc::Unexpected if unexpected error occured.
  558. /// \throw isc::InvalidOperation if Statistics Manager has not been
  559. /// initialized.
  560. void sendRequest6(const TestControlSocket& socket,
  561. const dhcp::Pkt6Ptr& advertise_pkt6);
  562. /// \brief Send DHCPv6 REQUEST message from template.
  563. ///
  564. /// Method sends DHCPv6 REQUEST message from template.
  565. /// Copy of sent packet is stored in the stats_mgr6_ object to
  566. /// update statistics.
  567. ///
  568. /// \param socket socket to be used to send message.
  569. /// \param template_buf packet template buffer.
  570. /// \param advertise_pkt6 ADVERTISE packet object.
  571. void sendRequest6(const TestControlSocket& socket,
  572. const std::vector<uint8_t>& template_buf,
  573. const dhcp::Pkt6Ptr& advertise_pkt6);
  574. /// \brief Send DHCPv6 SOLICIT message.
  575. ///
  576. /// Method creates and sends DHCPv6 SOLICIT message to the server
  577. /// with the following options:
  578. /// - D6O_ELAPSED_TIME,
  579. /// - D6O_RAPID_COMMIT if rapid commit is requested in command line,
  580. /// - D6O_CLIENTID,
  581. /// - D6O_ORO (Option Request Option),
  582. /// - D6O_IA_NA.
  583. /// Copy of sent packet is stored in the stats_mgr6_ object to
  584. /// update statistics.
  585. ///
  586. /// \param socket socket to be used to send the message.
  587. /// \param preload mode, packets not included in statistics.
  588. /// \throw isc::Unexpected if failed to create new packet instance.
  589. void sendSolicit6(const TestControlSocket& socket,
  590. const bool preload = false);
  591. /// \brief Send DHCPv6 SOLICIT message from template.
  592. ///
  593. /// Method sends DHCPv6 SOLICIT message from template.
  594. /// Copy of sent packet is stored in the stats_mgr6_ object to
  595. /// update statistics.
  596. ///
  597. /// \param socket socket to be used to send the message.
  598. /// \param template_buf packet template buffer.
  599. /// \param preload mode, packets not included in statistics.
  600. void sendSolicit6(const TestControlSocket& socket,
  601. const std::vector<uint8_t>& template_buf,
  602. const bool preload = false);
  603. /// \brief Set default DHCPv4 packet parameters.
  604. ///
  605. /// This method sets default parameters on the DHCPv4 packet:
  606. /// - interface name,
  607. /// - local port = 68 (DHCP client port),
  608. /// - remote port = 67 (DHCP server port),
  609. /// - server's address,
  610. /// - GIADDR = local address where socket is bound to,
  611. /// - hops = 1 (pretending that we are a relay)
  612. ///
  613. /// \param socket socket used to send the packet.
  614. /// \param pkt reference to packet to be configured.
  615. void setDefaults4(const TestControlSocket& socket,
  616. const dhcp::Pkt4Ptr& pkt);
  617. /// \brief Set default DHCPv6 packet parameters.
  618. ///
  619. /// This method sets default parameters on the DHCPv6 packet:
  620. /// - interface name,
  621. /// - interface index,
  622. /// - local port,
  623. /// - remote port,
  624. /// - local address,
  625. /// - remote address (server).
  626. ///
  627. /// \param socket socket used to send the packet.
  628. /// \param pkt reference to packet to be configured.
  629. void setDefaults6(const TestControlSocket& socket,
  630. const dhcp::Pkt6Ptr& pkt);
  631. /// \brief Find if diagnostic flag has been set.
  632. ///
  633. /// \param diag diagnostic flag (a,e,i,s,r,t,T).
  634. /// \return true if diagnostics flag has been set.
  635. bool testDiags(const char diag) const;
  636. /// \brief Update due time to initiate next chunk of exchanges.
  637. ///
  638. /// Method updates due time to initiate next chunk of exchanges.
  639. /// Function takes current time, last sent packet's time and
  640. /// expected rate in its calculations.
  641. void updateSendDue();
  642. private:
  643. /// \brief Convert binary value to hex string.
  644. ///
  645. /// \param b byte to convert.
  646. /// \return hex string.
  647. std::string byte2Hex(const uint8_t b) const;
  648. /// \brief Calculate elapsed time between two packets.
  649. ///
  650. /// \param T Pkt4Ptr or Pkt6Ptr class.
  651. /// \param pkt1 first packet.
  652. /// \param pkt2 second packet.
  653. /// \throw InvalidOperation if packet timestamps are invalid.
  654. /// \return elapsed time in milliseconds between pkt1 and pkt2.
  655. template<class T>
  656. uint32_t getElapsedTime(const T& pkt1, const T& pkt2);
  657. /// \brief Get number of received packets.
  658. ///
  659. /// Get the number of received packets from the Statistics Manager.
  660. /// Function may throw if Statistics Manager object is not
  661. /// initialized.
  662. /// \param xchg_type packet exchange type.
  663. /// \return number of received packets.
  664. uint64_t getRcvdPacketsNum(const ExchangeType xchg_type) const;
  665. /// \brief Get number of sent packets.
  666. ///
  667. /// Get the number of sent packets from the Statistics Manager.
  668. /// Function may throw if Statistics Manager object is not
  669. /// initialized.
  670. /// \param xchg_type packet exchange type.
  671. /// \return number of sent packets.
  672. uint64_t getSentPacketsNum(const ExchangeType xchg_type) const;
  673. /// \brief Handle interrupt signal.
  674. ///
  675. /// Function sets flag indicating that program has been
  676. /// interupted.
  677. ///
  678. /// \param sig signal (ignored)
  679. static void handleInterrupt(int sig);
  680. /// \brief Print main diagnostics data.
  681. ///
  682. /// Method prints main diagnostics data.
  683. void printDiagnostics() const;
  684. /// \brief Read DHCP message template from file.
  685. ///
  686. /// Method reads DHCP message template from file and
  687. /// converts it to binary format. Read data is appended
  688. /// to template_buffers_ vector.
  689. void readPacketTemplate(const std::string& file_name);
  690. /// \brief Convert vector in hexadecimal string.
  691. ///
  692. /// \param vec vector to be converted.
  693. /// \param separator separator.
  694. std::string vector2Hex(const std::vector<uint8_t>& vec,
  695. const std::string& separator = "") const;
  696. boost::posix_time::ptime send_due_; ///< Due time to initiate next chunk
  697. ///< of exchanges.
  698. boost::posix_time::ptime last_sent_; ///< Indicates when the last exchange
  699. /// was initiated.
  700. boost::posix_time::ptime last_report_; ///< Last intermediate report time.
  701. StatsMgr4Ptr stats_mgr4_; ///< Statistics Manager 4.
  702. StatsMgr6Ptr stats_mgr6_; ///< Statistics Manager 6.
  703. NumberGeneratorPtr transid_gen_; ///< Transaction id generator.
  704. NumberGeneratorPtr macaddr_gen_; ///< Numbers generator for MAC address.
  705. /// Buffer holiding server id received in first packet
  706. dhcp::OptionBuffer first_packet_serverid_;
  707. /// Packet template buffers.
  708. TemplateBufferCollection template_buffers_;
  709. static bool interrupted_; ///< Is program interrupted.
  710. };
  711. } // namespace perfdhcp
  712. } // namespace isc
  713. #endif // __COMMAND_OPTIONS_H