mac_list_file_.clear();
mac_list_.clear();
num_request_.clear();
+ late_exit_delay_ = 0;
period_ = 0;
drop_time_set_ = 0;
drop_time_.assign(dt, dt + 2);
// In this section we collect argument values from command line
// they will be tuned and validated elsewhere
- while((opt = getopt(argc, argv, "hv46A:r:t:R:b:n:p:d:D:l:P:a:L:M:"
+ while((opt = getopt(argc, argv, "hv46A:r:t:R:b:n:p:d:D:l:P:a:L:M:m:"
"s:iBc1T:X:O:E:S:I:x:w:e:f:F:")) != -1) {
stream << " -" << static_cast<char>(opt);
if (optarg) {
max_pdrop_.push_back(drop_percent);
} else {
num_drops = positiveInteger("value of max drops number:"
- " -d<value> must be a positive integer");
+ " -D<value> must be a positive integer");
max_drop_.push_back(num_drops);
}
break;
loadMacs();
break;
+ case 'm':
+ // 'm' for moratorium
+ late_exit_delay_ = nonNegativeInteger("value of late exit delay: "
+ "-m<value> must not be a "
+ "negative integer");
+ break;
+
case 'n':
num_req = positiveInteger("value of num-request:"
" -n<value> must be a positive integer");
" [-n<num-request>] [-p<test-period>] [-d<drop-time>]\n"
" [-D<max-drop>] [-l<local-addr|interface>] [-P<preload>]\n"
" [-a<aggressivity>] [-L<local-port>] [-s<seed>] [-i] [-B]\n"
+ " [-m<late-exit-delay>]\n"
" [-c] [-1] [-M<mac-list-file>] [-T<template-file>]\n"
" [-X<xid-offset>] [-O<random-offset] [-E<time-offset>]\n"
" [-S<srvid-offset>] [-I<ip-offset>] [-x<diagnostic-selector>]\n"
"\n"
"The remaining options are used only in conjunction with -r:\n"
"\n"
- "-D<max-drop>: Abort the test if more than <max-drop> requests have\n"
- " been dropped. Use -D0 to abort if even a single request has been\n"
- " dropped. If <max-drop> includes the suffix '%', it specifies a\n"
- " maximum percentage of requests that may be dropped before abort.\n"
- " In this case, testing of the threshold begins after 10 requests\n"
- " have been expected to be received.\n"
+ "-D<max-drop>: Abort the test immediately if max-drop requests have\n"
+ " been dropped. max-drop must be a positive integer. If max-drop\n"
+ " includes the suffix '%', it specifies a maximum percentage of\n"
+ " requests that may be dropped before abort. In this case, testing\n"
+ " of the threshold begins after 10 requests have been expected to\n"
+ " be received.\n"
"-n<num-request>: Initiate <num-request> transactions. No report is\n"
" generated until all transactions have been initiated/waited-for,\n"
" after which a report is generated and the program terminates.\n"
std::cout << "VERSION: " << VERSION << std::endl;
}
-
-} // namespace perfdhcp
-} // namespace isc
+} // namespace perfdhcp
+} // namespace isc
/// \return local port number.
int getLocalPort() const { return local_port_; }
+ /// @brief Returns the time in microseconds to delay the program by.
+ ///
+ /// @return the time in microseconds to delay the program by.
+ int getLateExitDelay() const { return late_exit_delay_; }
+
/// \brief Checks if seed provided.
///
/// \return true if seed was provided.
/// Collection of base values specified with -b<value>
/// options. Supported "bases" are mac=<mac> and duid=<duid>
std::vector<std::string> base_;
+ /// Number of microseconds by which you should delay the exit
+ int late_exit_delay_;
/// Number of 2 or 4-way exchanges to perform.
std::vector<int> num_request_;
/// Test period in seconds
uint8_t v6_relay_encapsulation_level_;
};
-} // namespace perfdhcp
-} // namespace isc
+} // namespace perfdhcp
+} // namespace isc
#endif // COMMAND_OPTIONS_H
<term><option>-D <replaceable class="parameter">max-drop</replaceable></option></term>
<listitem>
<para>
- Abort the test if more than <replaceable
- class="parameter">max-drop</replaceable>
- requests have been dropped. Use <option>-D
- 0</option> to abort if even a single
- request has been dropped. If <replaceable
+ Abort the test immediately if <replaceable
+ class="parameter">max-drop</replaceable> requests
+ have been dropped. <replaceable
+ class="parameter">max-drop</replaceable> must be a
+ positive integer. If <replaceable
class="parameter">max-drop</replaceable> includes
- the suffix '%', it specifies a maximum percentage
- of requests that may be dropped before abort.
- In this case, testing of the threshold begins after
- 10 requests have been expected to be received.
+ the suffix '%', it specifies a maximum percentage of
+ requests that may be dropped before abort. In this
+ case, testing of the threshold begins after 10
+ requests have been expected to be received.
</para>
</listitem>
</varlistentry>
bool TestControl::interrupted_ = false;
+ptime late_exit_target_time_ = ptime(not_a_date_time);
+
+bool
+TestControl::hasLateExitCommenced() const {
+ return !late_exit_target_time_.is_not_a_date_time();
+}
+
+bool
+TestControl::lateExit() const {
+ if (haveAllPacketsBeenReceived()) {
+ return true;
+ }
+ const ptime now = microsec_clock::universal_time();
+ if (late_exit_target_time_.is_not_a_date_time()) {
+ CommandOptions& options = CommandOptions::instance();
+ late_exit_target_time_ =
+ now + time_duration(microseconds(options.getLateExitDelay()));
+ }
+ if (late_exit_target_time_ <= now) {
+ return true;
+ }
+ return false;
+}
+
+bool
+TestControl::haveAllPacketsBeenReceived() const {
+ const CommandOptions& options = CommandOptions::instance();
+ const uint8_t& ipversion = options.getIpVersion();
+ const std::vector<int>& num_request = options.getNumRequests();
+ const size_t& num_request_size = num_request.size();
+
+ if (num_request_size == 0) {
+ return false;
+ }
+
+ const uint32_t& request_count_DO_SA = num_request[0];
+ uint32_t request_count_RA_RR;
+ if (num_request_size >= 2) {
+ request_count_RA_RR = num_request[1];
+ } else {
+ request_count_RA_RR = num_request[0];
+ }
+
+ if (ipversion == 4) {
+ if (stats_mgr4_->getRcvdPacketsNum(StatsMgr4::XCHG_DO) !=
+ request_count_DO_SA ||
+ stats_mgr4_->getRcvdPacketsNum(StatsMgr4::XCHG_RA) !=
+ request_count_RA_RR) {
+ return false;
+ }
+ } else if (ipversion == 6) {
+ if (stats_mgr6_->getRcvdPacketsNum(StatsMgr6::XCHG_SA) !=
+ request_count_DO_SA ||
+ stats_mgr6_->getRcvdPacketsNum(StatsMgr6::XCHG_RR) !=
+ request_count_RA_RR) {
+ return false;
+ }
+ }
+
+ return true;
+}
+
TestControl::TestControlSocket::TestControlSocket(const int socket) :
SocketInfo(asiolink::IOAddress("127.0.0.1"), 0, socket),
ifindex_(0), valid_(true) {
if (testDiags('e')) {
std::cout << "reached test-period." << std::endl;
}
- return (true);
+ if (lateExit()) {
+ return true;
+ }
}
bool max_requests = false;
if (testDiags('e')) {
std::cout << "Reached max requests limit." << std::endl;
}
- return (true);
+ if (lateExit()) {
+ return true;
+ }
}
// Check if we reached maximum number of drops of OFFER/ADVERTISE packets.
if (testDiags('e')) {
std::cout << "Reached maximum drops number." << std::endl;
}
- return (true);
+ if (lateExit()) {
+ return true;
+ }
}
// Check if we reached maximum drops percentage of OFFER/ADVERTISE packets.
if (testDiags('e')) {
std::cout << "Reached maximum percentage of drops." << std::endl;
}
- return (true);
+ if (lateExit()) {
+ return true;
+ }
}
return (false);
}
break;
}
- // Initiate new DHCP packet exchanges.
- sendPackets(socket, packets_due);
+ if (!hasLateExitCommenced()) {
+ // Initiate new DHCP packet exchanges.
+ sendPackets(socket, packets_due);
+ }
// If -f<renew-rate> option was specified we have to check how many
// Renew packets should be sent to catch up with a desired rate.
return (false);
}
-} // namespace perfdhcp
-} // namespace isc
+} // namespace perfdhcp
+} // namespace isc
/// Packet template buffers list.
typedef std::vector<TemplateBuffer> TemplateBufferCollection;
+ /// @brief Delay the exit by a fixed given time to catch up to all exchanges
+ /// that were already started.
+ bool lateExit() const;
+
+ /// @brief Check if the program is in that period where the program was
+ /// bound to exit, but was delayed by lateExit().
+ bool hasLateExitCommenced() const;
+
+ /// @brief Delay the exit by a fixed given time to catch up to all exchanges
+ /// that were already started.
+ bool haveAllPacketsBeenReceived() const;
+
/// \brief Socket wrapper structure.
///
/// This is the wrapper that holds descriptor of the socket
static bool interrupted_; ///< Is program interrupted.
};
-} // namespace perfdhcp
-} // namespace isc
+} // namespace perfdhcp
+} // namespace isc
#endif // TEST_CONTROL_H