Kea  2.3.5-git
test_control.h
Go to the documentation of this file.
1 // Copyright (C) 2012-2022 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>
17 
18 #include <dhcp/iface_mgr.h>
19 #include <dhcp/dhcp4.h>
20 #include <dhcp/dhcp6.h>
21 #include <dhcp/pkt4.h>
22 #include <dhcp/pkt6.h>
23 
24 #include <boost/noncopyable.hpp>
25 #include <boost/shared_ptr.hpp>
26 #include <boost/date_time/posix_time/posix_time.hpp>
27 
28 #include <string>
29 #include <vector>
30 #include <unordered_map>
31 
32 namespace isc {
33 namespace perfdhcp {
34 
36 static const size_t DHCPV4_TRANSID_OFFSET = 4;
38 static const size_t DHCPV4_RANDOMIZATION_OFFSET = 35;
40 static const size_t DHCPV4_ELAPSED_TIME_OFFSET = 8;
42 static const size_t DHCPV4_SERVERID_OFFSET = 54;
44 static const size_t DHCPV4_REQUESTED_IP_OFFSET = 240;
46 static const size_t DHCPV6_TRANSID_OFFSET = 1;
49 static const size_t DHCPV6_RANDOMIZATION_OFFSET = 21;
51 static const size_t DHCPV6_ELAPSED_TIME_OFFSET = 84;
53 static const size_t DHCPV6_SERVERID_OFFSET = 22;
55 static const size_t DHCPV6_IA_NA_OFFSET = 40;
56 
118 class TestControl : public boost::noncopyable {
119 public:
121  TestControl(CommandOptions& options, BasePerfSocket& socket);
122 
124  typedef std::vector<uint8_t> TemplateBuffer;
126  typedef std::vector<TemplateBuffer> TemplateBufferCollection;
127 
131  bool waitToExit();
132 
134  bool haveAllPacketsBeenReceived() const;
135 
143  public:
144 
146  virtual ~NumberGenerator() { }
147 
151  virtual uint32_t generate() = 0;
152  };
153 
155  typedef boost::shared_ptr<NumberGenerator> NumberGeneratorPtr;
156 
159  public:
164  SequentialGenerator(uint32_t range = 0xFFFFFFFF) :
165  NumberGenerator(),
166  num_(0),
167  range_(range) {
168  if (range_ == 0) {
169  range_ = 0xFFFFFFFF;
170  }
171  }
172 
176  virtual uint32_t generate() {
177  uint32_t num = num_;
178  num_ = (num_ + 1) % range_;
179  return (num);
180  }
181  private:
182  uint32_t num_;
183  uint32_t range_;
184  };
185 
190  static const uint8_t HW_ETHER_LEN = 6;
191 
195  void setTransidGenerator(const NumberGeneratorPtr& generator) {
196  transid_gen_.reset();
197  transid_gen_ = generator;
198  }
199 
206  void setMacAddrGenerator(const NumberGeneratorPtr& generator) {
207  macaddr_gen_.reset();
208  macaddr_gen_ = generator;
209  }
210 
222  void cleanCachedPackets();
223 
225  bool interrupted() const { return interrupted_; }
226 
229 
231  void start() { receiver_.start(); }
232 
234  void stop() { receiver_.stop(); }
235 
239  void runWrapped(bool do_stop = false) const;
240 
242  bool serverIdReceived() const { return first_packet_serverid_.size() > 0; }
243 
245  std::string getServerId() const { return vector2Hex(first_packet_serverid_); }
246 
267  void sendPackets(const uint64_t packets_num,
268  const bool preload = false);
269 
277  uint64_t sendMultipleMessages4(const uint32_t msg_type,
278  const uint64_t msg_num);
279 
287  uint64_t sendMultipleMessages6(const uint32_t msg_type,
288  const uint64_t msg_num);
289 
293  unsigned int consumeReceivedPackets();
294 
299  void printIntermediateStats();
300 
306  void printStats() const;
307 
312  void printTemplates() const;
313 
315  std::set<std::string>& getAllUniqueAddrReply() {
316  return unique_reply_address_;
317  }
318 
320  std::set<std::string>& getAllUniqueAddrAdvert() {
321  return unique_address_;
322  }
323 
330  static std::string byte2Hex(const uint8_t b);
331 
338  static std::string vector2Hex(const std::vector<uint8_t>& vec,
339  const std::string& separator = "");
340 
343  boost::posix_time::ptime exit_time_;
344 
345  // We would really like following methods and members to be private but
346  // they have to be accessible for unit-testing. Another, possibly better,
347  // solution is to make this class friend of test class but this is not
348  // what's followed in other classes.
349 protected:
352 
360  dhcp::Pkt4Ptr createMessageFromAck(const uint16_t msg_type,
361  const dhcp::Pkt4Ptr& ack);
362 
378  dhcp::Pkt6Ptr createMessageFromReply(const uint16_t msg_type,
379  const dhcp::Pkt6Ptr& reply);
380 
394  static dhcp::OptionPtr
396  uint16_t type,
397  const dhcp::OptionBuffer& buf);
398 
410  uint16_t type,
411  const dhcp::OptionBuffer& buf);
412 
424  uint16_t type,
425  const dhcp::OptionBuffer& buf);
426 
435  uint16_t type,
436  const dhcp::OptionBuffer& buf);
437 
449  static dhcp::OptionPtr
451  uint16_t type,
452  const dhcp::OptionBuffer& buf);
453 
465  uint16_t type,
466  const dhcp::OptionBuffer& buf);
467 
468 
486  uint16_t type,
487  const dhcp::OptionBuffer& buf);
488 
497  dhcp::OptionPtr generateClientId(const dhcp::HWAddrPtr& hwaddr) const;
498 
514  std::vector<uint8_t> generateDuid(uint8_t& randomized);
515 
530  std::vector<uint8_t> generateMacAddress(uint8_t& randomized);
531 
538  uint32_t generateTransid() {
539  return (transid_gen_->generate());
540  }
541 
549  TemplateBuffer getTemplateBuffer(const size_t idx) const;
550 
561  void initPacketTemplates();
562 
566  void printRate() const;
567 
581  void processReceivedPacket4(const dhcp::Pkt4Ptr& pkt4);
582 
590  bool validateIA(const dhcp::Pkt6Ptr& pkt6);
591 
598  void address6Uniqueness(const dhcp::Pkt6Ptr& pkt6, ExchangeType xchg_type);
599 
606  void address4Uniqueness(const dhcp::Pkt4Ptr& pkt4, ExchangeType xchg_type);
607 
615  void addUniqeAddr(const std::set<std::string>& current, ExchangeType xchg_type) {
616  switch(xchg_type) {
617  case ExchangeType::SA: {
618  for (auto current_it = current.begin();
619  current_it != current.end(); ++current_it) {
620  // addresses should be unique cross packets
621  auto ret = unique_address_.emplace(*current_it);
622  if (!ret.second) {
624  }
625  }
626  break;
627  }
628  case ExchangeType::RR: {
629  for (auto current_it = current.begin();
630  current_it != current.end(); ++current_it) {
631  // addresses should be unique cross packets
632  auto ret = unique_reply_address_.emplace(*current_it);
633  if (!ret.second) {
635  }
636  }
637  break;
638  }
639  case ExchangeType::RLA:
640  case ExchangeType::RL: {
641  removeUniqueAddr(current);
642  break;
643  }
644  case ExchangeType::DO: {
645  for (auto current_it = current.begin();
646  current_it != current.end(); ++current_it) {
647  // addresses should be unique cross packets
648  auto ret = unique_address_.emplace(*current_it);
649  if (!ret.second) {
651  }
652  }
653  break;
654  }
655  case ExchangeType::RA: {
656  for (auto current_it = current.begin();
657  current_it != current.end(); ++current_it) {
658  // addresses should be unique cross packets
659  auto ret = unique_reply_address_.emplace(*current_it);
660  if (!ret.second) {
662  }
663  }
664  break;
665  }
666  case ExchangeType::RNA:
667  case ExchangeType::RN:
668  default:
669  break;
670  }
671  }
672 
679  void removeUniqueAddr(const std::set<std::string>& addr) {
680  for (auto addr_it = addr.begin(); addr_it != addr.end(); ++addr_it) {
681  auto it = unique_address_.find(*addr_it);
682  if (it != unique_address_.end()) {
683  unique_address_.erase(it);
684  }
685 
686  auto it2 = unique_reply_address_.find(*addr_it);
687  if (it2 != unique_reply_address_.end()) {
688  unique_reply_address_.erase(it2);
689  }
690  }
691  }
692 
703  void processReceivedPacket6(const dhcp::Pkt6Ptr& pkt6);
704 
712  void registerOptionFactories4() const;
713 
721  void registerOptionFactories6() const;
722 
727  void registerOptionFactories() const;
728 
733  void reset();
734 
748  inline void saveFirstPacket(const dhcp::Pkt4Ptr& pkt);
749 
763  inline void saveFirstPacket(const dhcp::Pkt6Ptr& pkt);
764 
783  void sendDiscover4(const bool preload = false);
784 
799  void sendDiscover4(const std::vector<uint8_t>& template_buf,
800  const bool preload = false);
801 
808  bool sendMessageFromAck(const uint16_t msg_type);
809 
820  bool sendMessageFromReply(const uint16_t msg_type);
821 
835  void sendRequest4(const dhcp::Pkt4Ptr& discover_pkt4,
836  const dhcp::Pkt4Ptr& offer_pkt4);
837 
849  void sendRequest4(const std::vector<uint8_t>& template_buf,
850  const dhcp::Pkt4Ptr& discover_pkt4,
851  const dhcp::Pkt4Ptr& offer_pkt4);
852 
869  void sendRequest6(const dhcp::Pkt6Ptr& advertise_pkt6);
870 
881  void sendRequest6(const std::vector<uint8_t>& template_buf,
882  const dhcp::Pkt6Ptr& advertise_pkt6);
883 
900  void sendSolicit6(const bool preload = false);
901 
912  void sendSolicit6(const std::vector<uint8_t>& template_buf,
913  const bool preload = false);
914 
926  void setDefaults4(const dhcp::Pkt4Ptr& pkt);
927 
939  void setDefaults6(const dhcp::Pkt6Ptr& pkt);
940 
949  void addExtraOpts(const dhcp::Pkt4Ptr& pkt4);
950 
959  void addExtraOpts(const dhcp::Pkt6Ptr& pkt6);
960 
977  void copyIaOptions(const dhcp::Pkt6Ptr& pkt_from, dhcp::Pkt6Ptr& pkt_to);
978 
991  template<class T>
992  uint32_t getElapsedTime(const T& pkt1, const T& pkt2);
993 
997  int getElapsedTimeOffset() const;
998 
1002  int getRandomOffset(const int arg_idx) const;
1003 
1007  int getRequestedIpOffset() const;
1008 
1012  int getServerIdOffset() const;
1013 
1020  int getTransactionIdOffset(const int arg_idx) const;
1021 
1028  static void handleChild(int sig);
1029 
1036  static void handleInterrupt(int sig);
1037 
1041  void printDiagnostics() const;
1042 
1046  void printTemplate(const uint8_t packet_type) const;
1047 
1059  void readPacketTemplate(const std::string& file_name);
1060 
1062  std::set<std::string> unique_address_;
1063 
1065  std::set<std::string> unique_reply_address_;
1066 
1069 
1072 
1074  boost::posix_time::ptime last_report_;
1075 
1078 
1081 
1084 
1086  NumberGeneratorPtr transid_gen_;
1087 
1089  NumberGeneratorPtr macaddr_gen_;
1090 
1093 
1095  TemplateBufferCollection template_buffers_;
1096 
1099 
1101  std::map<uint8_t, dhcp::Pkt4Ptr> template_packets_v4_;
1102 
1104  std::map<uint8_t, dhcp::Pkt6Ptr> template_packets_v6_;
1105 
1107  static bool interrupted_;
1108 
1111 };
1112 
1113 } // namespace perfdhcp
1114 } // namespace isc
1115 
1116 #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:155
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:538
void printTemplates() const
Print templates information.
void printStats() const
Print performance statistics.
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.
virtual uint32_t generate()=0
Generate number.
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.
bool sendMessageFromAck(const uint16_t msg_type)
Send DHCPv4 renew (DHCPREQUEST).
void registerOptionFactories4() const
Register option factory functions for DHCPv4.
static std::string vector2Hex(const std::vector< uint8_t > &vec, const std::string &separator="")
Convert vector in hexadecimal string.
void stop()
Stop a receiving thread in multi-thread mode.
Definition: receiver.cc:36
void start()
Start receiver.
Definition: test_control.h:231
boost::shared_ptr< Option > OptionPtr
Definition: option.h:36
void setTransidGenerator(const NumberGeneratorPtr &generator)
Set new transaction id generator.
Definition: test_control.h:195
void setDefaults6(const dhcp::Pkt6Ptr &pkt)
Set default DHCPv6 packet parameters.
StatsMgr stats_mgr_
Statistics Manager.
bool sendMessageFromReply(const uint16_t msg_type)
Send DHCPv6 Renew or Release message.
Universe
defines option universe DHCPv4 or DHCPv6
Definition: option.h:83
void stop()
Stop receiver.
Definition: test_control.h:234
void removeUniqueAddr(const std::set< std::string > &addr)
remove unique address from list.
Definition: test_control.h:679
void printIntermediateStats()
Print intermediate statistics.
std::set< std::string > & getAllUniqueAddrReply()
Get set of unique replied addresses.
Definition: test_control.h:315
static dhcp::OptionPtr factoryRapidCommit6(dhcp::Option::Universe u, uint16_t type, const dhcp::OptionBuffer &buf)
Factory function to create DHCPv6 RAPID_COMMIT option instance.
std::string getServerId() const
Get received server id.
Definition: test_control.h:245
void address4Uniqueness(const dhcp::Pkt4Ptr &pkt4, ExchangeType xchg_type)
Process received v4 addresses uniqueness.
uint64_t sendMultipleMessages4(const uint32_t msg_type, const uint64_t msg_num)
Send number of DHCPREQUEST (renew) messages to a server.
void initPacketTemplates()
Reads packet templates from files.
bool validateIA(const dhcp::Pkt6Ptr &pkt6)
Process IA in received DHCPv6 packet.
dhcp::OptionPtr generateClientId(const dhcp::HWAddrPtr &hwaddr) const
Generate DHCPv4 client identifier from HW address.
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:126
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.
void setDefaults4(const dhcp::Pkt4Ptr &pkt)
Set default DHCPv4 packet parameters.
void printRate() const
Print rate statistics.
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:124
dhcp::Pkt4Ptr createMessageFromAck(const uint16_t msg_type, const dhcp::Pkt4Ptr &ack)
Creates DHCPREQUEST from a DHCPACK message.
boost::shared_ptr< Pkt6 > Pkt6Ptr
A pointer to Pkt6 packet.
Definition: pkt6.h:28
int getRandomOffset(const int arg_idx) const
Return randomization offset in a packet.
std::set< std::string > unique_reply_address_
Keep addresses and prefixes from reply msg for uniqueness checks.
DHCPv4 REQUEST-ACK (renewal)
void runWrapped(bool do_stop=false) const
Run wrapped command.
DHCPv6 RELEASE-REPLY.
bool haveAllPacketsBeenReceived() const
Checks if all expected packets were already received.
Definition: test_control.cc:69
boost::posix_time::ptime last_report_
Last intermediate report time.
std::map< uint8_t, dhcp::Pkt6Ptr > template_packets_v6_
Template for v6.
UniformRandomIntegerGenerator number_generator_
Generate uniformly distributed integers in range of [min, max].
Definition: test_control.h:351
boost::shared_ptr< Pkt4 > Pkt4Ptr
A pointer to Pkt4 object.
Definition: pkt4.h:547
boost::posix_time::ptime exit_time_
Initialized at first exit condition with the time perfdhcp should exit.
Definition: test_control.h:343
TemplateBuffer getTemplateBuffer(const size_t idx) const
Return template buffer.
int getTransactionIdOffset(const int arg_idx) const
Return transaction id offset in a packet.
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.
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.
Defines the logger used by the top-level component of kea-lfc.
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.
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.
DHCPv4 DISCOVER-OFFER.
void saveFirstPacket(const dhcp::Pkt4Ptr &pkt)
Save the first DHCPv4 sent packet of the specified type.
bool interrupted() const
Get interrupted flag.
Definition: test_control.h:225
void registerOptionFactories() const
Register option factory functions for DHCPv4 or DHCPv6.
bool serverIdReceived() const
Get received server id flag.
Definition: test_control.h:242
void registerOptionFactories6() const
Register option factory functions for DHCPv6.
DHCPv6 REQUEST-REPLY.
CommandOptions & options_
Command options.
StatsMgr & getStatsMgr()
Get stats manager.
Definition: test_control.h:228
void printTemplate(const uint8_t packet_type) const
Print template information.
void readPacketTemplate(const std::string &file_name)
Read DHCP message template from file.
Test Control class.
Definition: test_control.h:118
SequentialGenerator(uint32_t range=0xFFFFFFFF)
Constructor.
Definition: test_control.h:164
NumberGeneratorPtr macaddr_gen_
Numbers generator for MAC address.
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:190
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
dhcp::Pkt6Ptr createMessageFromReply(const uint16_t msg_type, const dhcp::Pkt6Ptr &reply)
Creates DHCPv6 message from the Reply packet.
void printDiagnostics() const
Print main diagnostics data.
void addUniqeAddr(const std::set< std::string > &current, ExchangeType xchg_type)
add unique address to already assigned list.
Definition: test_control.h:615
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:206
void updateNonUniqueAddrNum(const ExchangeType xchg_type)
Increase total number of non unique addresses.
std::set< std::string > & getAllUniqueAddrAdvert()
Get set of unique advertised addresses.
Definition: test_control.h:320
std::map< uint8_t, dhcp::Pkt4Ptr > template_packets_v4_
First packets send.
int getRequestedIpOffset() const
Return requested ip offset in a packet.
BasePerfSocket & socket_
Socket used for DHCP traffic.
virtual uint32_t generate()
Generate number sequentially.
Definition: test_control.h:176
int getElapsedTimeOffset() const
Return elapsed time offset in a packet.
int getServerIdOffset() const
Return server id offset in a packet.
A receiving DHCP packets class.
Definition: receiver.h:34
void reset()
Resets internal state of the object.
Represents a list of packets with a sequential and random access to list elements.
static void handleInterrupt(int sig)
Handle interrupt signal.
Sequential numbers generator class.
Definition: test_control.h:158
void addExtraOpts(const dhcp::Pkt4Ptr &pkt4)
Inserts extra options specified by user.