Kea  1.9.9-git
test_control.h
Go to the documentation of this file.
1 // Copyright (C) 2012-2020 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 
7 #ifndef TEST_CONTROL_H
8 #define TEST_CONTROL_H
9 
11 #include <perfdhcp/rate_control.h>
12 #include <perfdhcp/stats_mgr.h>
13 #include <perfdhcp/receiver.h>
15 #include <perfdhcp/perf_socket.h>
16 
17 #include <dhcp/iface_mgr.h>
18 #include <dhcp/dhcp6.h>
19 #include <dhcp/pkt4.h>
20 #include <dhcp/pkt6.h>
22 
23 #include <boost/noncopyable.hpp>
24 #include <boost/shared_ptr.hpp>
25 #include <boost/date_time/posix_time/posix_time.hpp>
26 
27 #include <string>
28 #include <vector>
29 #include <unordered_map>
30 
31 namespace isc {
32 namespace perfdhcp {
33 
35 static const size_t DHCPV4_TRANSID_OFFSET = 4;
37 static const size_t DHCPV4_RANDOMIZATION_OFFSET = 35;
39 static const size_t DHCPV4_ELAPSED_TIME_OFFSET = 8;
41 static const size_t DHCPV4_SERVERID_OFFSET = 54;
43 static const size_t DHCPV4_REQUESTED_IP_OFFSET = 240;
45 static const size_t DHCPV6_TRANSID_OFFSET = 1;
48 static const size_t DHCPV6_RANDOMIZATION_OFFSET = 21;
50 static const size_t DHCPV6_ELAPSED_TIME_OFFSET = 84;
52 static const size_t DHCPV6_SERVERID_OFFSET = 22;
54 static const size_t DHCPV6_IA_NA_OFFSET = 40;
55 
117 class TestControl : public boost::noncopyable {
118 public:
120  TestControl(CommandOptions& options, BasePerfSocket& socket);
121 
123  typedef std::vector<uint8_t> TemplateBuffer;
125  typedef std::vector<TemplateBuffer> TemplateBufferCollection;
126 
130  bool waitToExit();
131 
133  bool haveAllPacketsBeenReceived() const;
134 
142  public:
143 
145  virtual ~NumberGenerator() { }
146 
150  virtual uint32_t generate() = 0;
151  };
152 
154  typedef boost::shared_ptr<NumberGenerator> NumberGeneratorPtr;
155 
158  public:
163  SequentialGenerator(uint32_t range = 0xFFFFFFFF) :
164  NumberGenerator(),
165  num_(0),
166  range_(range) {
167  if (range_ == 0) {
168  range_ = 0xFFFFFFFF;
169  }
170  }
171 
175  virtual uint32_t generate() {
176  uint32_t num = num_;
177  num_ = (num_ + 1) % range_;
178  return (num);
179  }
180  private:
181  uint32_t num_;
182  uint32_t range_;
183  };
184 
189  static const uint8_t HW_ETHER_LEN = 6;
190 
194  void setTransidGenerator(const NumberGeneratorPtr& generator) {
195  transid_gen_.reset();
196  transid_gen_ = generator;
197  }
198 
205  void setMacAddrGenerator(const NumberGeneratorPtr& generator) {
206  macaddr_gen_.reset();
207  macaddr_gen_ = generator;
208  }
209 
221  void cleanCachedPackets();
222 
224  bool interrupted() const { return interrupted_; }
225 
228 
230  void start() { receiver_.start(); }
231 
233  void stop() { receiver_.stop(); }
234 
238  void runWrapped(bool do_stop = false) const;
239 
241  bool serverIdReceived() const { return first_packet_serverid_.size() > 0; }
242 
244  std::string getServerId() const { return vector2Hex(first_packet_serverid_); }
245 
266  void sendPackets(const uint64_t packets_num,
267  const bool preload = false);
268 
274  uint64_t sendMultipleRequests(const uint64_t msg_num);
275 
283  uint64_t sendMultipleMessages6(const uint32_t msg_type,
284  const uint64_t msg_num);
285 
289  unsigned int consumeReceivedPackets();
290 
295  void printIntermediateStats();
296 
302  void printStats() const;
303 
308  void printTemplates() const;
309 
311  std::set<std::string>& getAllUniqueAddrReply() {
312  return unique_reply_address_;
313  }
314 
316  std::set<std::string>& getAllUniqueAddrAdvert() {
317  return unique_address_;
318  }
319 
326  static std::string byte2Hex(const uint8_t b);
327 
334  static std::string vector2Hex(const std::vector<uint8_t>& vec,
335  const std::string& separator = "");
336 
339  boost::posix_time::ptime exit_time_;
340 
341  // We would really like following methods and members to be private but
342  // they have to be accessible for unit-testing. Another, possibly better,
343  // solution is to make this class friend of test class but this is not
344  // what's followed in other classes.
345 protected:
348 
356 
372  dhcp::Pkt6Ptr createMessageFromReply(const uint16_t msg_type,
373  const dhcp::Pkt6Ptr& reply);
374 
388  static dhcp::OptionPtr
390  uint16_t type,
391  const dhcp::OptionBuffer& buf);
392 
404  uint16_t type,
405  const dhcp::OptionBuffer& buf);
406 
418  uint16_t type,
419  const dhcp::OptionBuffer& buf);
420 
429  uint16_t type,
430  const dhcp::OptionBuffer& buf);
431 
443  static dhcp::OptionPtr
445  uint16_t type,
446  const dhcp::OptionBuffer& buf);
447 
459  uint16_t type,
460  const dhcp::OptionBuffer& buf);
461 
462 
480  uint16_t type,
481  const dhcp::OptionBuffer& buf);
482 
491  dhcp::OptionPtr generateClientId(const dhcp::HWAddrPtr& hwaddr) const;
492 
508  std::vector<uint8_t> generateDuid(uint8_t& randomized);
509 
524  std::vector<uint8_t> generateMacAddress(uint8_t& randomized);
525 
532  uint32_t generateTransid() {
533  return (transid_gen_->generate());
534  }
535 
543  TemplateBuffer getTemplateBuffer(const size_t idx) const;
544 
555  void initPacketTemplates();
556 
560  void printRate() const;
561 
575  void processReceivedPacket4(const dhcp::Pkt4Ptr& pkt4);
576 
584  bool validateIA(const dhcp::Pkt6Ptr& pkt6);
585 
592  void address6Uniqueness(const dhcp::Pkt6Ptr& pkt6, ExchangeType xchg_type);
593 
600  void address4Uniqueness(const dhcp::Pkt4Ptr& pkt4, ExchangeType xchg_type);
601 
609  void addUniqeAddr(const std::set<std::string>& current, ExchangeType xchg_type) {
610  switch(xchg_type) {
611  case ExchangeType::SA: {
612  for (auto current_it = current.begin();
613  current_it != current.end(); ++current_it) {
614  // addresses should be unique cross packets
615  auto ret = unique_address_.emplace(*current_it);
616  if (!ret.second) {
618  }
619  }
620  break;
621  }
622  case ExchangeType::RR: {
623  for (auto current_it = current.begin();
624  current_it != current.end(); ++current_it) {
625  // addresses should be unique cross packets
626  auto ret = unique_reply_address_.emplace(*current_it);
627  if (!ret.second) {
629  }
630  }
631  break;
632  }
633  case ExchangeType::RL: {
634  removeUniqueAddr(current);
635  break;
636  }
637  case ExchangeType::DO: {
638  for (auto current_it = current.begin();
639  current_it != current.end(); ++current_it) {
640  // addresses should be unique cross packets
641  auto ret = unique_address_.emplace(*current_it);
642  if (!ret.second) {
644  }
645  }
646  break;
647  }
648  case ExchangeType::RA: {
649  for (auto current_it = current.begin();
650  current_it != current.end(); ++current_it) {
651  // addresses should be unique cross packets
652  auto ret = unique_reply_address_.emplace(*current_it);
653  if (!ret.second) {
655  }
656  }
657  break;
658  }
659  case ExchangeType::RNA:
660  case ExchangeType::RN:
661  default:
662  break;
663  }
664  }
665 
672  void removeUniqueAddr(const std::set<std::string>& addr) {
673  for (auto addr_it = addr.begin(); addr_it != addr.end(); ++addr_it) {
674  auto it = unique_address_.find(*addr_it);
675  if (it != unique_address_.end()) {
676  unique_address_.erase(it);
677  }
678 
679  auto it2 = unique_reply_address_.find(*addr_it);
680  if (it2 != unique_reply_address_.end()) {
681  unique_reply_address_.erase(it2);
682  }
683  }
684  }
685 
696  void processReceivedPacket6(const dhcp::Pkt6Ptr& pkt6);
697 
705  void registerOptionFactories4() const;
706 
714  void registerOptionFactories6() const;
715 
720  void registerOptionFactories() const;
721 
726  void reset();
727 
741  inline void saveFirstPacket(const dhcp::Pkt4Ptr& pkt);
742 
756  inline void saveFirstPacket(const dhcp::Pkt6Ptr& pkt);
757 
776  void sendDiscover4(const bool preload = false);
777 
792  void sendDiscover4(const std::vector<uint8_t>& template_buf,
793  const bool preload = false);
794 
798  bool sendRequestFromAck();
799 
810  bool sendMessageFromReply(const uint16_t msg_type);
811 
825  void sendRequest4(const dhcp::Pkt4Ptr& discover_pkt4,
826  const dhcp::Pkt4Ptr& offer_pkt4);
827 
839  void sendRequest4(const std::vector<uint8_t>& template_buf,
840  const dhcp::Pkt4Ptr& discover_pkt4,
841  const dhcp::Pkt4Ptr& offer_pkt4);
842 
859  void sendRequest6(const dhcp::Pkt6Ptr& advertise_pkt6);
860 
871  void sendRequest6(const std::vector<uint8_t>& template_buf,
872  const dhcp::Pkt6Ptr& advertise_pkt6);
873 
890  void sendSolicit6(const bool preload = false);
891 
902  void sendSolicit6(const std::vector<uint8_t>& template_buf,
903  const bool preload = false);
904 
916  void setDefaults4(const dhcp::Pkt4Ptr& pkt);
917 
929  void setDefaults6(const dhcp::Pkt6Ptr& pkt);
930 
939  void addExtraOpts(const dhcp::Pkt4Ptr& pkt4);
940 
949  void addExtraOpts(const dhcp::Pkt6Ptr& pkt6);
950 
967  void copyIaOptions(const dhcp::Pkt6Ptr& pkt_from, dhcp::Pkt6Ptr& pkt_to);
968 
981  template<class T>
982  uint32_t getElapsedTime(const T& pkt1, const T& pkt2);
983 
987  int getElapsedTimeOffset() const;
988 
992  int getRandomOffset(const int arg_idx) const;
993 
997  int getRequestedIpOffset() const;
998 
1002  int getServerIdOffset() const;
1003 
1010  int getTransactionIdOffset(const int arg_idx) const;
1011 
1018  static void handleChild(int sig);
1019 
1026  static void handleInterrupt(int sig);
1027 
1031  void printDiagnostics() const;
1032 
1036  void printTemplate(const uint8_t packet_type) const;
1037 
1049  void readPacketTemplate(const std::string& file_name);
1050 
1052  std::set<std::string> unique_address_;
1053 
1055  std::set<std::string> unique_reply_address_;
1056 
1059 
1062 
1064  boost::posix_time::ptime last_report_;
1065 
1068 
1071 
1074 
1076  NumberGeneratorPtr transid_gen_;
1077 
1079  NumberGeneratorPtr macaddr_gen_;
1080 
1083 
1085  TemplateBufferCollection template_buffers_;
1086 
1089 
1091  std::map<uint8_t, dhcp::Pkt4Ptr> template_packets_v4_;
1092 
1094  std::map<uint8_t, dhcp::Pkt6Ptr> template_packets_v6_;
1095 
1097  static bool interrupted_;
1098 
1101 };
1102 
1103 } // namespace perfdhcp
1104 } // namespace isc
1105 
1106 #endif // TEST_CONTROL_H
void sendPackets(const uint64_t packets_num, const bool preload=false)
Send number of packets to initiate new exchanges.
NumberGeneratorPtr transid_gen_
Transaction id generator.
static dhcp::OptionPtr factoryGeneric(dhcp::Option::Universe u, uint16_t type, const dhcp::OptionBuffer &buf)
Factory function to create generic option.
boost::shared_ptr< NumberGenerator > NumberGeneratorPtr
The default generator pointer.
Definition: test_control.h:154
void address6Uniqueness(const dhcp::Pkt6Ptr &pkt6, ExchangeType xchg_type)
Process received v6 addresses uniqueness.
static bool interrupted_
Program interrupted flag.
uint32_t generateTransid()
generate transaction id.
Definition: test_control.h:532
void sendSolicit6(const bool preload=false)
Send DHCPv6 SOLICIT message.
std::set< std::string > unique_address_
Keep addresses and prefixes from advertise msg for uniqueness checks.
DHCPv6 SOLICIT-ADVERTISE.
ExchangeType
DHCP packet exchange types.
static dhcp::OptionPtr factoryIana6(dhcp::Option::Universe u, uint16_t type, const dhcp::OptionBuffer &buf)
Factory function to create IA_NA option.
void registerOptionFactories() const
Register option factory functions for DHCPv4 or DHCPv6.
virtual uint32_t generate()=0
Generate number.
void registerOptionFactories6() const
Register option factory functions for DHCPv6.
void printDiagnostics() const
Print main diagnostics data.
boost::shared_ptr< HWAddr > HWAddrPtr
Shared pointer to a hardware address structure.
Definition: hwaddr.h:154
PacketStorage< dhcp::Pkt4 > ack_storage_
Storage for DHCPACK messages.
std::vector< uint8_t > generateDuid(uint8_t &randomized)
Generate DUID.
void runWrapped(bool do_stop=false) const
Run wrapped command.
static std::string vector2Hex(const std::vector< uint8_t > &vec, const std::string &separator="")
Convert vector in hexadecimal string.
void printTemplate(const uint8_t packet_type) const
Print template information.
void stop()
Stop a receiving thread in multi-thread mode.
Definition: receiver.cc:36
void start()
Start receiver.
Definition: test_control.h:230
boost::shared_ptr< Option > OptionPtr
Definition: option.h:36
void setTransidGenerator(const NumberGeneratorPtr &generator)
Set new transaction id generator.
Definition: test_control.h:194
void setDefaults6(const dhcp::Pkt6Ptr &pkt)
Set default DHCPv6 packet parameters.
StatsMgr stats_mgr_
Statistics Manager.
bool serverIdReceived() const
Get received server id flag.
Definition: test_control.h:241
int getRequestedIpOffset() const
Return requested ip offset in a packet.
bool sendMessageFromReply(const uint16_t msg_type)
Send DHCPv6 Renew or Release message.
Universe
defines option universe DHCPv4 or DHCPv6
Definition: option.h:82
void stop()
Stop receiver.
Definition: test_control.h:233
void removeUniqueAddr(const std::set< std::string > &addr)
remove unique address from list.
Definition: test_control.h:672
void printIntermediateStats()
Print intermediate statistics.
std::set< std::string > & getAllUniqueAddrReply()
Get set of unique replied addresses.
Definition: test_control.h:311
static dhcp::OptionPtr factoryRapidCommit6(dhcp::Option::Universe u, uint16_t type, const dhcp::OptionBuffer &buf)
Factory function to create DHCPv6 RAPID_COMMIT option instance.
void printTemplates() const
Print templates information.
void address4Uniqueness(const dhcp::Pkt4Ptr &pkt4, ExchangeType xchg_type)
Process received v4 addresses uniqueness.
void initPacketTemplates()
Reads packet templates from files.
bool validateIA(const dhcp::Pkt6Ptr &pkt6)
Process IA in received DHCPv6 packet.
static std::string byte2Hex(const uint8_t b)
Convert binary value to hex string.
std::vector< uint8_t > OptionBuffer
buffer types used in DHCP code.
Definition: option.h:24
std::vector< TemplateBuffer > TemplateBufferCollection
Packet template buffers list.
Definition: test_control.h:125
bool waitToExit()
Delay the exit by a fixed given time to catch up to all exchanges that were already started...
Definition: test_control.cc:48
static dhcp::OptionPtr factoryElapsedTime6(dhcp::Option::Universe u, uint16_t type, const dhcp::OptionBuffer &buf)
Factory function to create DHCPv6 ELAPSED_TIME option.
TemplateBufferCollection template_buffers_
Packet template buffers.
dhcp::Pkt4Ptr createRequestFromAck(const dhcp::Pkt4Ptr &ack)
Creates DHCPREQUEST from a DHCPACK message.
void setDefaults4(const dhcp::Pkt4Ptr &pkt)
Set default DHCPv4 packet parameters.
uint64_t sendMultipleMessages6(const uint32_t msg_type, const uint64_t msg_num)
Send number of DHCPv6 Renew or Release messages to the server.
std::vector< uint8_t > TemplateBuffer
Packet template buffer.
Definition: test_control.h:123
boost::shared_ptr< Pkt6 > Pkt6Ptr
A pointer to Pkt6 packet.
Definition: pkt6.h:28
bool haveAllPacketsBeenReceived() const
Checks if all expected packets were already received.
Definition: test_control.cc:69
std::set< std::string > unique_reply_address_
Keep addresses and prefixes from reply msg for uniqueness checks.
DHCPv4 REQUEST-ACK (renewal)
DHCPv6 RELEASE-REPLY.
boost::posix_time::ptime last_report_
Last intermediate report time.
std::map< uint8_t, dhcp::Pkt6Ptr > template_packets_v6_
Template for v6.
boost::shared_ptr< Pkt4 > Pkt4Ptr
A pointer to Pkt4 object.
Definition: pkt4.h:544
boost::posix_time::ptime exit_time_
Initialized at first exit condition with the time perfdhcp should exit.
Definition: test_control.h:339
void processReceivedPacket4(const dhcp::Pkt4Ptr &pkt4)
Process received DHCPv4 packet.
void start()
Start a receiving thread in multi-thread mode.
Definition: receiver.cc:24
void sendDiscover4(const bool preload=false)
Send DHCPv4 DISCOVER message.
int getServerIdOffset() const
Return server id offset in a packet.
void registerOptionFactories4() const
Register option factory functions for DHCPv4.
Receiver receiver_
Receiver used to receive DHCP traffic.
std::vector< uint8_t > generateMacAddress(uint8_t &randomized)
Generate MAC address.
void sendRequest6(const dhcp::Pkt6Ptr &advertise_pkt6)
Send DHCPv6 REQUEST message.
TemplateBuffer getTemplateBuffer(const size_t idx) const
Return template buffer.
Defines the logger used by the top-level component of kea-dhcp-ddns.
static dhcp::OptionPtr factoryRequestList4(dhcp::Option::Universe u, uint16_t type, const dhcp::OptionBuffer &buf)
Factory function to create DHCPv4 Request List option.
void sendRequest4(const dhcp::Pkt4Ptr &discover_pkt4, const dhcp::Pkt4Ptr &offer_pkt4)
Send DHCPv4 REQUEST message.
unsigned int consumeReceivedPackets()
Pull packets from receiver and process them.
int getRandomOffset(const int arg_idx) const
Return randomization offset in a packet.
void copyIaOptions(const dhcp::Pkt6Ptr &pkt_from, dhcp::Pkt6Ptr &pkt_to)
Copies IA_NA or IA_PD option from one packet to another.
static void handleChild(int sig)
Handle child signal.
void cleanCachedPackets()
Removes cached DHCPv6 Reply packets every second.
Definition: test_control.cc:96
PacketStorage< dhcp::Pkt6 > reply_storage_
Storage for reply messages.
dhcp::OptionPtr generateClientId(const dhcp::HWAddrPtr &hwaddr) const
Generate DHCPv4 client identifier from HW address.
DHCPv4 DISCOVER-OFFER.
void saveFirstPacket(const dhcp::Pkt4Ptr &pkt)
Save the first DHCPv4 sent packet of the specified type.
bool sendRequestFromAck()
Send DHCPv4 renew (DHCPREQUEST).
DHCPv6 REQUEST-REPLY.
CommandOptions & options_
Command options.
StatsMgr & getStatsMgr()
Get stats manager.
Definition: test_control.h:227
void readPacketTemplate(const std::string &file_name)
Read DHCP message template from file.
Test Control class.
Definition: test_control.h:117
SequentialGenerator(uint32_t range=0xFFFFFFFF)
Constructor.
Definition: test_control.h:163
NumberGeneratorPtr macaddr_gen_
Numbers generator for MAC address.
isc::util::random::UniformRandomIntegerGenerator number_generator_
Generate uniformly distributed integers in range of [min, max].
Definition: test_control.h:347
static dhcp::OptionPtr factoryOptionRequestOption6(dhcp::Option::Universe u, uint16_t type, const dhcp::OptionBuffer &buf)
Factory function to create DHCPv6 ORO option.
static const uint8_t HW_ETHER_LEN
Length of the Ethernet HW address (MAC) in bytes.
Definition: test_control.h:189
void printRate() const
Print rate statistics.
void processReceivedPacket6(const dhcp::Pkt6Ptr &pkt6)
Process received DHCPv6 packet.
TestControl(CommandOptions &options, BasePerfSocket &socket)
Default constructor.
dhcp::OptionBuffer first_packet_serverid_
Buffer holding server id received in first packet.
static dhcp::OptionPtr factoryIapd6(dhcp::Option::Universe u, uint16_t type, const dhcp::OptionBuffer &buf)
Factory function to create IA_PD option.
Socket wrapper structure.
Definition: perf_socket.h:26
int getTransactionIdOffset(const int arg_idx) const
Return transaction id offset in a packet.
dhcp::Pkt6Ptr createMessageFromReply(const uint16_t msg_type, const dhcp::Pkt6Ptr &reply)
Creates DHCPv6 message from the Reply packet.
bool interrupted() const
Get interrupted flag.
Definition: test_control.h:224
void addUniqeAddr(const std::set< std::string > &current, ExchangeType xchg_type)
add unique address to already assigned list.
Definition: test_control.h:609
void printStats() const
Print performance statistics.
uint32_t getElapsedTime(const T &pkt1, const T &pkt2)
Calculate elapsed time between two packets.
void setMacAddrGenerator(const NumberGeneratorPtr &generator)
Set new MAC address generator.
Definition: test_control.h:205
int getElapsedTimeOffset() const
Return elapsed time offset in a packet.
void updateNonUniqueAddrNum(const ExchangeType xchg_type)
Increase total number of non unique addresses.
std::string getServerId() const
Get received server id.
Definition: test_control.h:244
std::set< std::string > & getAllUniqueAddrAdvert()
Get set of unique advertised addresses.
Definition: test_control.h:316
uint64_t sendMultipleRequests(const uint64_t msg_num)
Send number of DHCPREQUEST (renew) messages to a server.
std::map< uint8_t, dhcp::Pkt4Ptr > template_packets_v4_
First packets send.
BasePerfSocket & socket_
Socket used for DHCP traffic.
virtual uint32_t generate()
Generate number sequentially.
Definition: test_control.h:175
A receiving DHCP packets class.
Definition: receiver.h:34
void reset()
Resets internal state of the object.
static void handleInterrupt(int sig)
Handle interrupt signal.
Sequential numbers generator class.
Definition: test_control.h:157
void addExtraOpts(const dhcp::Pkt4Ptr &pkt4)
Inserts extra options specified by user.