Kea 2.7.5
test_control.h
Go to the documentation of this file.
1// Copyright (C) 2012-2024 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
12#include <perfdhcp/stats_mgr.h>
13#include <perfdhcp/receiver.h>
16
17#include <dhcp/iface_mgr.h>
18#include <dhcp/dhcp4.h>
19#include <dhcp/dhcp6.h>
20#include <dhcp/pkt4.h>
21#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 <random>
28#include <string>
29#include <vector>
30
31namespace isc {
32namespace perfdhcp {
33
35static const size_t DHCPV4_TRANSID_OFFSET = 4;
37static const size_t DHCPV4_RANDOMIZATION_OFFSET = 35;
39static const size_t DHCPV4_ELAPSED_TIME_OFFSET = 8;
41static const size_t DHCPV4_SERVERID_OFFSET = 54;
43static const size_t DHCPV4_REQUESTED_IP_OFFSET = 240;
45static const size_t DHCPV6_TRANSID_OFFSET = 1;
48static const size_t DHCPV6_RANDOMIZATION_OFFSET = 21;
50static const size_t DHCPV6_ELAPSED_TIME_OFFSET = 84;
52static const size_t DHCPV6_SERVERID_OFFSET = 22;
54static const size_t DHCPV6_IA_NA_OFFSET = 40;
55
117class TestControl : public boost::noncopyable {
118public:
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) :
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
188 public:
193 RandomGenerator(uint32_t min, uint32_t max) :
195 distribution_(min, max) {
196 // Initialize the randomness source with the current time.
197 randomness_generator_.seed(time(0));
198 }
199
203 virtual uint32_t generate() {
204 return distribution_(randomness_generator_);
205 }
206
207 private:
210 std::uniform_int_distribution<> distribution_;
211
215 std::mt19937 randomness_generator_;
216 };
217
222 static const uint8_t HW_ETHER_LEN = 6;
223
228 transid_gen_.reset();
229 transid_gen_ = generator;
230 }
231
239 macaddr_gen_.reset();
240 macaddr_gen_ = generator;
241 }
242
254 void cleanCachedPackets();
255
257 bool interrupted() const { return interrupted_; }
258
261
263 void start() { receiver_.start(); }
264
266 void stop() { receiver_.stop(); }
267
271 void runWrapped(bool do_stop = false) const;
272
274 bool serverIdReceived() const { return first_packet_serverid_.size() > 0; }
275
277 std::string getServerId() const { return vector2Hex(first_packet_serverid_); }
278
299 void sendPackets(const uint64_t packets_num,
300 const bool preload = false);
301
309 uint64_t sendMultipleMessages4(const uint32_t msg_type,
310 const uint64_t msg_num);
311
319 uint64_t sendMultipleMessages6(const uint32_t msg_type,
320 const uint64_t msg_num);
321
325 unsigned int consumeReceivedPackets();
326
332
338 void printStats() const;
339
344 void printTemplates() const;
345
347 std::set<std::string>& getAllUniqueAddrReply() {
349 }
350
352 std::set<std::string>& getAllUniqueAddrAdvert() {
353 return unique_address_;
354 }
355
362 static std::string byte2Hex(const uint8_t b);
363
370 static std::string vector2Hex(const std::vector<uint8_t>& vec,
371 const std::string& separator = "");
372
375 boost::posix_time::ptime exit_time_;
376
377 // We would really like following methods and members to be private but
378 // they have to be accessible for unit-testing. Another, possibly better,
379 // solution is to make this class friend of test class but this is not
380 // what's followed in other classes.
381protected:
389 dhcp::Pkt4Ptr createMessageFromAck(const uint16_t msg_type,
390 const dhcp::Pkt4Ptr& ack);
391
407 dhcp::Pkt6Ptr createMessageFromReply(const uint16_t msg_type,
408 const dhcp::Pkt6Ptr& reply);
409
423 static dhcp::OptionPtr
425 uint16_t type,
426 const dhcp::OptionBuffer& buf);
427
439 uint16_t type,
440 const dhcp::OptionBuffer& buf);
441
453 uint16_t type,
454 const dhcp::OptionBuffer& buf);
455
464 uint16_t type,
465 const dhcp::OptionBuffer& buf);
466
478 static dhcp::OptionPtr
480 uint16_t type,
481 const dhcp::OptionBuffer& buf);
482
494 uint16_t type,
495 const dhcp::OptionBuffer& buf);
496
497
515 uint16_t type,
516 const dhcp::OptionBuffer& buf);
517
527
543 std::vector<uint8_t> generateDuid(uint8_t& randomized);
544
559 std::vector<uint8_t> generateMacAddress(uint8_t& randomized);
560
567 uint32_t generateTransid() {
568 return (transid_gen_->generate());
569 }
570
578 TemplateBuffer getTemplateBuffer(const size_t idx) const;
579
590 void initPacketTemplates();
591
595 void printRate() const;
596
610 void processReceivedPacket4(const dhcp::Pkt4Ptr& pkt4);
611
619 bool validateIA(const dhcp::Pkt6Ptr& pkt6);
620
627 void address6Uniqueness(const dhcp::Pkt6Ptr& pkt6, ExchangeType xchg_type);
628
635 void address4Uniqueness(const dhcp::Pkt4Ptr& pkt4, ExchangeType xchg_type);
636
644 void addUniqeAddr(const std::set<std::string>& current, ExchangeType xchg_type) {
645 switch(xchg_type) {
646 case ExchangeType::SA: {
647 for (auto const& current_it : current) {
648 // addresses should be unique cross packets
649 auto ret = unique_address_.emplace(current_it);
650 if (!ret.second) {
652 }
653 }
654 break;
655 }
656 case ExchangeType::RR: {
657 for (auto const& current_it : current) {
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 }
667 case ExchangeType::RL: {
668 removeUniqueAddr(current);
669 break;
670 }
671 case ExchangeType::DO: {
672 for (auto const& current_it : current) {
673 // addresses should be unique cross packets
674 auto ret = unique_address_.emplace(current_it);
675 if (!ret.second) {
677 }
678 }
679 break;
680 }
681 case ExchangeType::RA: {
682 for (auto const& current_it : current) {
683 // addresses should be unique cross packets
684 auto ret = unique_reply_address_.emplace(current_it);
685 if (!ret.second) {
687 }
688 }
689 break;
690 }
692 case ExchangeType::RN:
693 default:
694 break;
695 }
696 }
697
704 void removeUniqueAddr(const std::set<std::string>& addr) {
705 for (auto const& addr_it : addr) {
706 auto it = unique_address_.find(addr_it);
707 if (it != unique_address_.end()) {
708 unique_address_.erase(it);
709 }
710
711 auto it2 = unique_reply_address_.find(addr_it);
712 if (it2 != unique_reply_address_.end()) {
713 unique_reply_address_.erase(it2);
714 }
715 }
716 }
717
728 void processReceivedPacket6(const dhcp::Pkt6Ptr& pkt6);
729
737 void registerOptionFactories4() const;
738
746 void registerOptionFactories6() const;
747
752 void registerOptionFactories() const;
753
758 void reset();
759
773 inline void saveFirstPacket(const dhcp::Pkt4Ptr& pkt);
774
788 inline void saveFirstPacket(const dhcp::Pkt6Ptr& pkt);
789
808 void sendDiscover4(const bool preload = false);
809
824 void sendDiscover4(const std::vector<uint8_t>& template_buf,
825 const bool preload = false);
826
833 bool sendMessageFromAck(const uint16_t msg_type);
834
845 bool sendMessageFromReply(const uint16_t msg_type);
846
860 void sendRequest4(const dhcp::Pkt4Ptr& discover_pkt4,
861 const dhcp::Pkt4Ptr& offer_pkt4);
862
874 void sendRequest4(const std::vector<uint8_t>& template_buf,
875 const dhcp::Pkt4Ptr& discover_pkt4,
876 const dhcp::Pkt4Ptr& offer_pkt4);
877
894 void sendRequest6(const dhcp::Pkt6Ptr& advertise_pkt6);
895
906 void sendRequest6(const std::vector<uint8_t>& template_buf,
907 const dhcp::Pkt6Ptr& advertise_pkt6);
908
925 void sendSolicit6(const bool preload = false);
926
937 void sendSolicit6(const std::vector<uint8_t>& template_buf,
938 const bool preload = false);
939
951 void setDefaults4(const dhcp::Pkt4Ptr& pkt);
952
964 void setDefaults6(const dhcp::Pkt6Ptr& pkt);
965
974 void addExtraOpts(const dhcp::Pkt4Ptr& pkt4);
975
984 void addExtraOpts(const dhcp::Pkt6Ptr& pkt6);
985
1002 void copyIaOptions(const dhcp::Pkt6Ptr& pkt_from, dhcp::Pkt6Ptr& pkt_to);
1003
1016 template<class T>
1017 uint32_t getElapsedTime(const T& pkt1, const T& pkt2);
1018
1022 int getElapsedTimeOffset() const;
1023
1027 int getRandomOffset(const int arg_idx) const;
1028
1032 int getRequestedIpOffset() const;
1033
1037 int getServerIdOffset() const;
1038
1045 int getTransactionIdOffset(const int arg_idx) const;
1046
1053 static void handleChild(int sig);
1054
1061 static void handleInterrupt(int sig);
1062
1066 void printDiagnostics() const;
1067
1071 void printTemplate(const uint8_t packet_type) const;
1072
1084 void readPacketTemplate(const std::string& file_name);
1085
1087 std::set<std::string> unique_address_;
1088
1090 std::set<std::string> unique_reply_address_;
1091
1094
1097
1099 boost::posix_time::ptime last_report_;
1100
1103
1105 PacketStorage<dhcp::Pkt4> ack_storage_;
1106
1108 PacketStorage<dhcp::Pkt6> reply_storage_;
1109
1113
1116
1119
1122
1125
1128
1130 std::map<uint8_t, dhcp::Pkt4Ptr> template_packets_v4_;
1131
1133 std::map<uint8_t, dhcp::Pkt6Ptr> template_packets_v6_;
1134
1136 static bool interrupted_;
1137
1140};
1141
1142} // namespace perfdhcp
1143} // namespace isc
1144
1145#endif // TEST_CONTROL_H
Universe
defines option universe DHCPv4 or DHCPv6
Definition option.h:90
Socket wrapper structure.
Definition perf_socket.h:26
A receiving DHCP packets class.
Definition receiver.h:34
void start()
Start a receiving thread in multi-thread mode.
Definition receiver.cc:24
void stop()
Stop a receiving thread in multi-thread mode.
Definition receiver.cc:36
void updateNonUniqueAddrNum(const ExchangeType xchg_type)
Increase total number of non unique addresses.
virtual uint32_t generate()=0
Generate number.
Random numbers generator class.
virtual uint32_t generate()
Generate number in range of [min, max].
RandomGenerator(uint32_t min, uint32_t max)
Constructor.
Sequential numbers generator class.
virtual uint32_t generate()
Generate number sequentially.
SequentialGenerator(uint32_t range=0xFFFFFFFF)
Constructor.
Test Control class.
void saveFirstPacket(const dhcp::Pkt4Ptr &pkt)
Save the first DHCPv4 sent packet of the specified type.
void address6Uniqueness(const dhcp::Pkt6Ptr &pkt6, ExchangeType xchg_type)
Process received v6 addresses uniqueness.
static const uint8_t HW_ETHER_LEN
Length of the Ethernet HW address (MAC) in bytes.
bool waitToExit()
Delay the exit by a fixed given time to catch up to all exchanges that were already started.
std::map< uint8_t, dhcp::Pkt4Ptr > template_packets_v4_
First packets send.
bool sendMessageFromReply(const uint16_t msg_type)
Send DHCPv6 Renew or Release message.
void addExtraOpts(const dhcp::Pkt4Ptr &pkt4)
Inserts extra options specified by user.
void printDiagnostics() const
Print main diagnostics data.
static void handleChild(int sig)
Handle child signal.
void registerOptionFactories4() const
Register option factory functions for DHCPv4.
bool interrupted() const
Get interrupted flag.
NumberGeneratorPtr transid_gen_
Transaction id generator.
NumberGeneratorPtr macaddr_gen_
Numbers generator for MAC address.
int getRequestedIpOffset() const
Return requested ip offset in a packet.
NumberGeneratorPtr random_generator_
Generate uniformly distributed integers in range of [min, max].
std::set< std::string > & getAllUniqueAddrReply()
Get set of unique replied addresses.
boost::shared_ptr< NumberGenerator > NumberGeneratorPtr
The default generator pointer.
std::string getServerId() const
Get received server id.
uint64_t sendMultipleMessages4(const uint32_t msg_type, const uint64_t msg_num)
Send number of DHCPREQUEST (renew) messages to a server.
bool validateIA(const dhcp::Pkt6Ptr &pkt6)
Process IA in received DHCPv6 packet.
dhcp::Pkt4Ptr createMessageFromAck(const uint16_t msg_type, const dhcp::Pkt4Ptr &ack)
Creates DHCPREQUEST from a DHCPACK message.
static bool interrupted_
Program interrupted flag.
void readPacketTemplate(const std::string &file_name)
Read DHCP message template from file.
TemplateBuffer getTemplateBuffer(const size_t idx) const
Return template buffer.
std::vector< uint8_t > generateMacAddress(uint8_t &randomized)
Generate MAC address.
void setDefaults4(const dhcp::Pkt4Ptr &pkt)
Set default DHCPv4 packet parameters.
boost::posix_time::ptime exit_time_
Initialized at first exit condition with the time perfdhcp should exit.
CommandOptions & options_
Command options.
Receiver receiver_
Receiver used to receive DHCP traffic.
static std::string vector2Hex(const std::vector< uint8_t > &vec, const std::string &separator="")
Convert vector in hexadecimal string.
uint64_t sendMultipleMessages6(const uint32_t msg_type, const uint64_t msg_num)
Send number of DHCPv6 Renew or Release messages to the server.
void start()
Start receiver.
void setMacAddrGenerator(const NumberGeneratorPtr &generator)
Set new MAC address generator.
void setDefaults6(const dhcp::Pkt6Ptr &pkt)
Set default DHCPv6 packet parameters.
boost::posix_time::ptime last_report_
Last intermediate report time.
bool haveAllPacketsBeenReceived() const
Checks if all expected packets were already received.
void cleanCachedPackets()
Removes cached DHCPv6 Reply packets every second.
void processReceivedPacket4(const dhcp::Pkt4Ptr &pkt4)
Process received DHCPv4 packet.
std::vector< TemplateBuffer > TemplateBufferCollection
Packet template buffers list.
void sendRequest6(const dhcp::Pkt6Ptr &advertise_pkt6)
Send DHCPv6 REQUEST message.
TestControl(CommandOptions &options, BasePerfSocket &socket)
Default constructor.
StatsMgr & getStatsMgr()
Get stats manager.
std::set< std::string > & getAllUniqueAddrAdvert()
Get set of unique advertised addresses.
static dhcp::OptionPtr factoryOptionRequestOption6(dhcp::Option::Universe u, uint16_t type, const dhcp::OptionBuffer &buf)
Factory function to create DHCPv6 ORO option.
void sendSolicit6(const bool preload=false)
Send DHCPv6 SOLICIT message.
static dhcp::OptionPtr factoryIapd6(dhcp::Option::Universe u, uint16_t type, const dhcp::OptionBuffer &buf)
Factory function to create IA_PD option.
std::map< uint8_t, dhcp::Pkt6Ptr > template_packets_v6_
Template for v6.
static dhcp::OptionPtr factoryRapidCommit6(dhcp::Option::Universe u, uint16_t type, const dhcp::OptionBuffer &buf)
Factory function to create DHCPv6 RAPID_COMMIT option instance.
PacketStorage< dhcp::Pkt6 > reply_storage_
Storage for reply messages.
void registerOptionFactories6() const
Register option factory functions for DHCPv6.
void sendPackets(const uint64_t packets_num, const bool preload=false)
Send number of packets to initiate new exchanges.
void registerOptionFactories() const
Register option factory functions for DHCPv4 or DHCPv6.
void stop()
Stop receiver.
std::vector< uint8_t > TemplateBuffer
Packet template buffer.
bool sendMessageFromAck(const uint16_t msg_type)
Send DHCPv4 renew (DHCPREQUEST).
void runWrapped(bool do_stop=false) const
Run wrapped command.
void processReceivedPacket6(const dhcp::Pkt6Ptr &pkt6)
Process received DHCPv6 packet.
uint32_t getElapsedTime(const T &pkt1, const T &pkt2)
Calculate elapsed time between two packets.
BasePerfSocket & socket_
Socket used for DHCP traffic.
void reset()
Resets internal state of the object.
void addUniqeAddr(const std::set< std::string > &current, ExchangeType xchg_type)
add unique address to already assigned list.
void address4Uniqueness(const dhcp::Pkt4Ptr &pkt4, ExchangeType xchg_type)
Process received v4 addresses uniqueness.
int getRandomOffset(const int arg_idx) const
Return randomization offset in a packet.
dhcp::Pkt6Ptr createMessageFromReply(const uint16_t msg_type, const dhcp::Pkt6Ptr &reply)
Creates DHCPv6 message from the Reply packet.
int getElapsedTimeOffset() const
Return elapsed time offset in a packet.
static std::string byte2Hex(const uint8_t b)
Convert binary value to hex string.
void printTemplates() const
Print templates information.
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.
TemplateBufferCollection template_buffers_
Packet template buffers.
StatsMgr stats_mgr_
Statistics Manager.
void printStats() const
Print performance statistics.
PacketStorage< dhcp::Pkt4 > ack_storage_
Storage for DHCPACK messages.
void copyIaOptions(const dhcp::Pkt6Ptr &pkt_from, dhcp::Pkt6Ptr &pkt_to)
Copies IA_NA or IA_PD option from one packet to another.
std::set< std::string > unique_reply_address_
Keep addresses and prefixes from reply msg for uniqueness checks.
void setTransidGenerator(const NumberGeneratorPtr &generator)
Set new transaction id generator.
static dhcp::OptionPtr factoryGeneric(dhcp::Option::Universe u, uint16_t type, const dhcp::OptionBuffer &buf)
Factory function to create generic option.
bool serverIdReceived() const
Get received server id flag.
static dhcp::OptionPtr factoryRequestList4(dhcp::Option::Universe u, uint16_t type, const dhcp::OptionBuffer &buf)
Factory function to create DHCPv4 Request List option.
static dhcp::OptionPtr factoryElapsedTime6(dhcp::Option::Universe u, uint16_t type, const dhcp::OptionBuffer &buf)
Factory function to create DHCPv6 ELAPSED_TIME option.
static void handleInterrupt(int sig)
Handle interrupt signal.
int getTransactionIdOffset(const int arg_idx) const
Return transaction id offset in a packet.
void initPacketTemplates()
Reads packet templates from files.
void printRate() const
Print rate statistics.
void printIntermediateStats()
Print intermediate statistics.
void printTemplate(const uint8_t packet_type) const
Print template information.
int getServerIdOffset() const
Return server id offset in a packet.
std::vector< uint8_t > generateDuid(uint8_t &randomized)
Generate DUID.
std::set< std::string > unique_address_
Keep addresses and prefixes from advertise msg for uniqueness checks.
void sendDiscover4(const bool preload=false)
Send DHCPv4 DISCOVER message.
dhcp::OptionPtr generateClientId(const dhcp::HWAddrPtr &hwaddr) const
Generate DHCPv4 client identifier from HW address.
void removeUniqueAddr(const std::set< std::string > &addr)
remove unique address from list.
dhcp::OptionBuffer first_packet_serverid_
Buffer holding server id received in first packet.
uint32_t generateTransid()
generate transaction id.
static dhcp::OptionPtr factoryIana6(dhcp::Option::Universe u, uint16_t type, const dhcp::OptionBuffer &buf)
Factory function to create IA_NA option.
boost::shared_ptr< Pkt4 > Pkt4Ptr
A pointer to Pkt4 object.
Definition pkt4.h:555
boost::shared_ptr< HWAddr > HWAddrPtr
Shared pointer to a hardware address structure.
Definition hwaddr.h:154
boost::shared_ptr< Pkt6 > Pkt6Ptr
A pointer to Pkt6 packet.
Definition pkt6.h:31
std::vector< uint8_t > OptionBuffer
buffer types used in DHCP code.
Definition option.h:24
boost::shared_ptr< Option > OptionPtr
Definition option.h:37
ExchangeType
DHCP packet exchange types.
@ RA
DHCPv4 REQUEST-ACK.
@ SA
DHCPv6 SOLICIT-ADVERTISE.
@ RNA
DHCPv4 REQUEST-ACK (renewal)
@ RL
DHCPv6 RELEASE-REPLY.
@ RN
DHCPv6 RENEW-REPLY.
@ DO
DHCPv4 DISCOVER-OFFER.
@ RR
DHCPv6 REQUEST-REPLY.
Defines the logger used by the top-level component of kea-lfc.