Kea 2.7.5
basic_scen.cc
Go to the documentation of this file.
1// Copyright (C) 2012-2021 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#include <config.h>
8
10
11#include <boost/date_time/posix_time/posix_time.hpp>
12
13using namespace std;
14using namespace boost::posix_time;
15using namespace isc;
16using namespace isc::dhcp;
17
18
19namespace isc {
20namespace perfdhcp {
21
22
23bool
25 if (tc_.interrupted()) {
26 return (true);
27 }
28
29 const StatsMgr& stats_mgr(tc_.getStatsMgr());
30
31 // Check if test period passed.
32 if (options_.getPeriod() != 0) {
33 time_period period(stats_mgr.getTestPeriod());
34 if (period.length().total_seconds() >= options_.getPeriod()) {
35 if (options_.testDiags('e')) {
36 std::cout << "reached test-period." << std::endl;
37 }
38 if (!tc_.waitToExit()) {
39 return true;
40 }
41 }
42 }
43
44 bool max_requests = false;
45 // Check if we reached maximum number of DISCOVER/SOLICIT sent.
46 if (options_.getNumRequests().size() > 0) {
47 if (stats_mgr.getSentPacketsNum(stage1_xchg_) >=
49 max_requests = true;
50 }
51 }
52 // Check if we reached maximum number REQUEST packets.
53 if (options_.getNumRequests().size() > 1) {
54 if (stats_mgr.getSentPacketsNum(stage2_xchg_) >=
56 max_requests = true;
57 }
58 }
59 if (max_requests) {
60 if (options_.testDiags('e')) {
61 std::cout << "Reached max requests limit." << std::endl;
62 }
63 if (!tc_.waitToExit()) {
64 return true;
65 }
66 }
67
68 // Check if we reached maximum number of drops of OFFER/ADVERTISE packets.
69 bool max_drops = false;
70 if (options_.getMaxDrop().size() > 0) {
71 if (stats_mgr.getDroppedPacketsNum(stage1_xchg_) >=
72 options_.getMaxDrop()[0]) {
73 max_drops = true;
74 }
75 }
76 // Check if we reached maximum number of drops of ACK/REPLY packets.
77 if (options_.getMaxDrop().size() > 1) {
78 if (stats_mgr.getDroppedPacketsNum(stage2_xchg_) >=
79 options_.getMaxDrop()[1]) {
80 max_drops = true;
81 }
82 }
83 if (max_drops) {
84 if (options_.testDiags('e')) {
85 std::cout << "Reached maximum drops number." << std::endl;
86 }
87 if (!tc_.waitToExit()) {
88 return true;
89 }
90 }
91
92 // Check if we reached maximum drops percentage of OFFER/ADVERTISE packets.
93 bool max_pdrops = false;
94 if (options_.getMaxDropPercentage().size() > 0) {
95 if ((stats_mgr.getSentPacketsNum(stage1_xchg_) > 10) &&
96 ((100. * stats_mgr.getDroppedPacketsNum(stage1_xchg_) /
97 stats_mgr.getSentPacketsNum(stage1_xchg_)) >=
99 {
100 max_pdrops = true;
101 }
102 }
103 // Check if we reached maximum drops percentage of ACK/REPLY packets.
104 if (options_.getMaxDropPercentage().size() > 1) {
105 if ((stats_mgr.getSentPacketsNum(stage2_xchg_) > 10) &&
106 ((100. * stats_mgr.getDroppedPacketsNum(stage2_xchg_) /
107 stats_mgr.getSentPacketsNum(stage2_xchg_)) >=
109 {
110 max_pdrops = true;
111 }
112 }
113 if (max_pdrops) {
114 if (options_.testDiags('e')) {
115 std::cout << "Reached maximum percentage of drops." << std::endl;
116 }
117 if (!tc_.waitToExit()) {
118 return true;
119 }
120 }
121 return (false);
122}
123
124int
126 StatsMgr& stats_mgr(tc_.getStatsMgr());
127
128 // Preload server with the number of packets.
129 if (options_.getPreload() > 0) {
131 }
132
133 // Fork and run command specified with -w<wrapped-command>
134 if (!options_.getWrapped().empty()) {
135 tc_.runWrapped();
136 }
137
138 tc_.start();
139
140 for (;;) {
141 // Calculate number of packets to be sent to stay
142 // catch up with rate.
143 uint64_t packets_due =
145 if ((packets_due == 0) && options_.testDiags('i')) {
146 stats_mgr.incrementCounter("shortwait");
147 }
148
149 // Pull some packets from receiver thread, process them, update some stats
150 // and respond to the server if needed.
151 auto pkt_count = tc_.consumeReceivedPackets();
152
153 // If there is nothing to do in this loop iteration then do some sleep to make
154 // CPU idle for a moment, to not consume 100% CPU all the time
155 // but only if it is not that high request rate expected.
156 if (options_.getRate() < 10000 && packets_due == 0 && pkt_count == 0) {
159 usleep(1);
160 }
161
162 // If test period finished, maximum number of packet drops
163 // has been reached or test has been interrupted we have to
164 // finish the test.
165 if (checkExitConditions()) {
166 break;
167 }
168
169 // Initiate new DHCP packet exchanges.
170 tc_.sendPackets(packets_due);
171
172 // If -f<renew-rate> option was specified we have to check how many
173 // Renew packets should be sent to catch up with a desired rate.
174 if (options_.getRenewRate() != 0) {
175 uint64_t renew_packets_due =
177
178 // Send multiple renews to satisfy the desired rate.
179 if (options_.getIpVersion() == 4) {
180 tc_.sendMultipleMessages4(DHCPREQUEST, renew_packets_due);
181 } else {
182 tc_.sendMultipleMessages6(DHCPV6_RENEW, renew_packets_due);
183 }
184 }
185
186 // If -F<release-rate> option was specified we have to check how many
187 // Release messages should be sent to catch up with a desired rate.
188 if (options_.getReleaseRate() != 0) {
189 uint64_t release_packets_due =
191 // Send Release messages.
192
193 if (options_.getIpVersion() == 4) {
194 tc_.sendMultipleMessages4(DHCPRELEASE, release_packets_due);
195 } else {
196 tc_.sendMultipleMessages6(DHCPV6_RELEASE, release_packets_due);
197 }
198 }
199
200 // Report delay means that user requested printing number
201 // of sent/received/dropped packets repeatedly.
202 if (options_.getReportDelay() > 0) {
204 }
205
206 // If we are sending Renews to the server, the Reply packets are cached
207 // so as leases for which we send Renews can be identified. The major
208 // issue with this approach is that most of the time we are caching
209 // more packets than we actually need. This function removes excessive
210 // Reply messages to reduce the memory and CPU utilization. Note that
211 // searches in the long list of Reply packets increases CPU utilization.
213 }
214
215 tc_.stop();
216
217 tc_.printStats();
218
219 if (!options_.getWrapped().empty()) {
220 // true means that we execute wrapped command with 'stop' argument.
221 tc_.runWrapped(true);
222 }
223
224 // Print packet timestamps
225 if (options_.testDiags('t')) {
226 stats_mgr.printTimestamps();
227 }
228
229 // Print server id.
230 if (options_.testDiags('s') && tc_.serverIdReceived()) {
231 std::cout << "Server id: " << tc_.getServerId() << std::endl;
232 }
233
234 // Diagnostics flag 'e' means show exit reason.
235 if (options_.testDiags('e')) {
236 std::cout << "Interrupted" << std::endl;
237 }
238 // Print packet templates. Even if -T options have not been specified the
239 // dynamically build packet will be printed if at least one has been sent.
240 if (options_.testDiags('T')) {
242 }
243
244 // Print any received leases.
245 if (options_.testDiags('l')) {
246 stats_mgr.printLeases();
247 }
248
249 int ret_code = 0;
250 // Check if any packet drops occurred.
251 ret_code = stats_mgr.droppedPackets() ? 3 : 0;
252 return (ret_code);
253}
254
255} // namespace perfdhcp
256} // namespace isc
TestControl tc_
Object for controlling sending and receiving packets.
CommandOptions & options_
Reference to commandline options.
RateControl renew_rate_control_
A rate control class for Renew messages.
Definition basic_scen.h:52
int run() override
brief\ Run performance test.
bool checkExitConditions()
Check if test exit conditions fulfilled.
Definition basic_scen.cc:24
RateControl release_rate_control_
A rate control class for Release messages.
Definition basic_scen.h:54
RateControl basic_rate_control_
A rate control class for Discover and Solicit messages.
Definition basic_scen.h:50
bool testDiags(const char diag)
Find if diagnostic flag has been set.
std::string getWrapped() const
Returns wrapped command.
int getRenewRate() const
Returns a rate at which DHCPv6 Renew messages are sent.
uint8_t getIpVersion() const
Returns IP version.
int getRate() const
Returns exchange rate.
int getReportDelay() const
Returns delay between two performance reports.
std::vector< double > getMaxDropPercentage() const
Returns maximal percentage of drops.
std::vector< int > getNumRequests() const
Returns maximum number of exchanges.
int getPreload() const
Returns number of preload exchanges.
std::vector< int > getMaxDrop() const
Returns maximum drops number.
int getPeriod() const
Returns test period.
int getReleaseRate() const
Returns a rate at which DHCPv6 Release messages are sent.
uint64_t getOutboundMessageCount(bool const waiting_to_exit=false)
Returns number of messages to be sent "now".
bool waitToExit()
Delay the exit by a fixed given time to catch up to all exchanges that were already started.
bool interrupted() const
Get interrupted flag.
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.
boost::posix_time::ptime exit_time_
Initialized at first exit condition with the time perfdhcp should exit.
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 cleanCachedPackets()
Removes cached DHCPv6 Reply packets every second.
StatsMgr & getStatsMgr()
Get stats manager.
void sendPackets(const uint64_t packets_num, const bool preload=false)
Send number of packets to initiate new exchanges.
void stop()
Stop receiver.
void runWrapped(bool do_stop=false) const
Run wrapped command.
void printTemplates() const
Print templates information.
unsigned int consumeReceivedPackets()
Pull packets from receiver and process them.
void printStats() const
Print performance statistics.
bool serverIdReceived() const
Get received server id flag.
void printIntermediateStats()
Print intermediate statistics.
@ DHCPV6_RENEW
Definition dhcp6.h:202
@ DHCPV6_RELEASE
Definition dhcp6.h:205
@ DHCPREQUEST
Definition dhcp4.h:237
@ DHCPRELEASE
Definition dhcp4.h:241
Defines the logger used by the top-level component of kea-lfc.