Kea 3.3.1
test_control.h
Go to the documentation of this file.
1// Copyright (C) 2012-2026 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 vector2Hex(const std::vector<uint8_t>& vec,
363 const std::string& separator = "");
364
367 boost::posix_time::ptime exit_time_;
368
369 // We would really like following methods and members to be private but
370 // they have to be accessible for unit-testing. Another, possibly better,
371 // solution is to make this class friend of test class but this is not
372 // what's followed in other classes.
373protected:
381 dhcp::Pkt4Ptr createMessageFromAck(const uint16_t msg_type,
382 const dhcp::Pkt4Ptr& ack);
383
399 dhcp::Pkt6Ptr createMessageFromReply(const uint16_t msg_type,
400 const dhcp::Pkt6Ptr& reply);
401
415 static dhcp::OptionPtr
417 uint16_t type,
418 const dhcp::OptionBuffer& buf);
419
431 uint16_t type,
432 const dhcp::OptionBuffer& buf);
433
445 uint16_t type,
446 const dhcp::OptionBuffer& buf);
447
456 uint16_t type,
457 const dhcp::OptionBuffer& buf);
458
470 static dhcp::OptionPtr
472 uint16_t type,
473 const dhcp::OptionBuffer& buf);
474
486 uint16_t type,
487 const dhcp::OptionBuffer& buf);
488
489
507 uint16_t type,
508 const dhcp::OptionBuffer& buf);
509
519
535 std::vector<uint8_t> generateDuid(uint8_t& randomized);
536
551 std::vector<uint8_t> generateMacAddress(uint8_t& randomized);
552
559 uint32_t generateTransid() {
560 return (transid_gen_->generate());
561 }
562
570 TemplateBuffer getTemplateBuffer(const size_t idx) const;
571
582 void initPacketTemplates();
583
587 void printRate() const;
588
602 void processReceivedPacket4(const dhcp::Pkt4Ptr& pkt4);
603
611 bool validateIA(const dhcp::Pkt6Ptr& pkt6);
612
619 void address6Uniqueness(const dhcp::Pkt6Ptr& pkt6, ExchangeType xchg_type);
620
627 void address4Uniqueness(const dhcp::Pkt4Ptr& pkt4, ExchangeType xchg_type);
628
636 void addUniqeAddr(const std::set<std::string>& current, ExchangeType xchg_type) {
637 switch(xchg_type) {
638 case ExchangeType::SA: {
639 for (auto const& current_it : current) {
640 // addresses should be unique cross packets
641 auto ret = unique_address_.emplace(current_it);
642 if (!ret.second) {
643 stats_mgr_.updateNonUniqueAddrNum(ExchangeType::SA);
644 }
645 }
646 break;
647 }
648 case ExchangeType::RR: {
649 for (auto const& current_it : current) {
650 // addresses should be unique cross packets
651 auto ret = unique_reply_address_.emplace(current_it);
652 if (!ret.second) {
653 stats_mgr_.updateNonUniqueAddrNum(ExchangeType::RR);
654 }
655 }
656 break;
657 }
659 case ExchangeType::RL: {
660 removeUniqueAddr(current);
661 break;
662 }
663 case ExchangeType::DO: {
664 for (auto const& current_it : current) {
665 // addresses should be unique cross packets
666 auto ret = unique_address_.emplace(current_it);
667 if (!ret.second) {
668 stats_mgr_.updateNonUniqueAddrNum(ExchangeType::DO);
669 }
670 }
671 break;
672 }
673 case ExchangeType::RA: {
674 for (auto const& current_it : current) {
675 // addresses should be unique cross packets
676 auto ret = unique_reply_address_.emplace(current_it);
677 if (!ret.second) {
678 stats_mgr_.updateNonUniqueAddrNum(ExchangeType::RA);
679 }
680 }
681 break;
682 }
684 case ExchangeType::RN:
685 default:
686 break;
687 }
688 }
689
696 void removeUniqueAddr(const std::set<std::string>& addr) {
697 for (auto const& addr_it : addr) {
698 auto it = unique_address_.find(addr_it);
699 if (it != unique_address_.end()) {
700 unique_address_.erase(it);
701 }
702
703 auto it2 = unique_reply_address_.find(addr_it);
704 if (it2 != unique_reply_address_.end()) {
705 unique_reply_address_.erase(it2);
706 }
707 }
708 }
709
720 void processReceivedPacket6(const dhcp::Pkt6Ptr& pkt6);
721
729 void registerOptionFactories4() const;
730
738 void registerOptionFactories6() const;
739
744 void registerOptionFactories() const;
745
750 void reset();
751
765 inline void saveFirstPacket(const dhcp::Pkt4Ptr& pkt);
766
780 inline void saveFirstPacket(const dhcp::Pkt6Ptr& pkt);
781
800 void sendDiscover4(const bool preload = false);
801
816 void sendDiscover4(const std::vector<uint8_t>& template_buf,
817 const bool preload = false);
818
825 bool sendMessageFromAck(const uint16_t msg_type);
826
837 bool sendMessageFromReply(const uint16_t msg_type);
838
852 void sendRequest4(const dhcp::Pkt4Ptr& discover_pkt4,
853 const dhcp::Pkt4Ptr& offer_pkt4);
854
866 void sendRequest4(const std::vector<uint8_t>& template_buf,
867 const dhcp::Pkt4Ptr& discover_pkt4,
868 const dhcp::Pkt4Ptr& offer_pkt4);
869
886 void sendRequest6(const dhcp::Pkt6Ptr& advertise_pkt6);
887
898 void sendRequest6(const std::vector<uint8_t>& template_buf,
899 const dhcp::Pkt6Ptr& advertise_pkt6);
900
917 void sendSolicit6(const bool preload = false);
918
929 void sendSolicit6(const std::vector<uint8_t>& template_buf,
930 const bool preload = false);
931
943 void setDefaults4(const dhcp::Pkt4Ptr& pkt);
944
956 void setDefaults6(const dhcp::Pkt6Ptr& pkt);
957
966 void addExtraOpts(const dhcp::Pkt4Ptr& pkt4);
967
976 void addExtraOpts(const dhcp::Pkt6Ptr& pkt6);
977
994 void copyIaOptions(const dhcp::Pkt6Ptr& pkt_from, dhcp::Pkt6Ptr& pkt_to);
995
1008 template<class T>
1009 uint32_t getElapsedTime(const T& pkt1, const T& pkt2);
1010
1014 int getElapsedTimeOffset() const;
1015
1019 int getRandomOffset(const int arg_idx) const;
1020
1024 int getRequestedIpOffset() const;
1025
1029 int getServerIdOffset() const;
1030
1037 int getTransactionIdOffset(const int arg_idx) const;
1038
1045 static void handleChild(int sig);
1046
1053 static void handleInterrupt(int sig);
1054
1058 void printDiagnostics() const;
1059
1063 void printTemplate(const uint8_t packet_type) const;
1064
1076 void readPacketTemplate(const std::string& file_name);
1077
1079 std::set<std::string> unique_address_;
1080
1082 std::set<std::string> unique_reply_address_;
1083
1086
1089
1091 boost::posix_time::ptime last_report_;
1092
1095
1098
1101
1105
1108
1111
1114
1117
1120
1122 std::map<uint8_t, dhcp::Pkt4Ptr> template_packets_v4_;
1123
1125 std::map<uint8_t, dhcp::Pkt6Ptr> template_packets_v6_;
1126
1128 static bool interrupted_;
1129
1132};
1133
1134} // namespace perfdhcp
1135} // namespace isc
1136
1137#endif // TEST_CONTROL_H
Universe
defines option universe DHCPv4 or DHCPv6
Definition option.h:90
Socket wrapper structure.
Definition perf_socket.h:26
Represents a list of packets with a sequential and random access to list elements.
A receiving DHCP packets class.
Definition receiver.h:34
virtual uint32_t generate()=0
Generate number.
virtual uint32_t generate()
Generate number in range of [min, max].
RandomGenerator(uint32_t min, uint32_t max)
Constructor.
virtual uint32_t generate()
Generate number sequentially.
SequentialGenerator(uint32_t range=0xFFFFFFFF)
Constructor.
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.
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:556
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.
@ SA
DHCPv6 SOLICIT-ADVERTISE.
@ RNA
DHCPv4 REQUEST-ACK (renewal).
Defines the logger used by the top-level component of kea-lfc.