Commit 6a3c2c61 authored by Marcin Siodelski's avatar Marcin Siodelski

[1959] Implemented changes from the second part of code review.

parent 6ca3dadc
...@@ -56,8 +56,8 @@ CommandOptions::reset() { ...@@ -56,8 +56,8 @@ CommandOptions::reset() {
rate_ = 0; rate_ = 0;
report_delay_ = 0; report_delay_ = 0;
clients_num_ = 0; clients_num_ = 0;
mac_prefix_.assign(mac, mac + 6); mac_template_.assign(mac, mac + 6);
duid_prefix_.clear(); duid_template_.clear();
base_.clear(); base_.clear();
num_request_.clear(); num_request_.clear();
period_ = 0; period_ = 0;
...@@ -84,8 +84,8 @@ CommandOptions::reset() { ...@@ -84,8 +84,8 @@ CommandOptions::reset() {
diags_.clear(); diags_.clear();
wrapped_.clear(); wrapped_.clear();
server_name_.clear(); server_name_.clear();
generateDuidTemplate();
generateDuidPrefix(); commandline_.clear();
} }
void void
...@@ -132,9 +132,16 @@ CommandOptions::initialize(int argc, char** argv) { ...@@ -132,9 +132,16 @@ CommandOptions::initialize(int argc, char** argv) {
int offset_arg = 0; // Temporary variable holding offset arguments int offset_arg = 0; // Temporary variable holding offset arguments
std::string sarg; // Temporary variable for string args std::string sarg; // Temporary variable for string args
std::ostringstream stream;
stream << "perfdhcp";
// In this section we collect argument values from command line // In this section we collect argument values from command line
// they will be tuned and validated elsewhere // they will be tuned and validated elsewhere
while((opt = getopt(argc, argv, "hv46r:t:R:b:n:p:d:D:l:P:a:L:s:iBc1T:X:O:E:S:I:x:w:")) != -1) { while((opt = getopt(argc, argv, "hv46r:t:R:b:n:p:d:D:l:P:a:L:s:iBc1T:X:O:E:S:I:x:w:")) != -1) {
stream << " -" << opt;
if (optarg) {
stream << " " << optarg;
}
switch (opt) { switch (opt) {
case 'v': case 'v':
version(); version();
...@@ -318,6 +325,8 @@ CommandOptions::initialize(int argc, char** argv) { ...@@ -318,6 +325,8 @@ CommandOptions::initialize(int argc, char** argv) {
} }
} }
std::cout << "Running: " << stream.str() << std::endl;
// If the IP version was not specified in the // If the IP version was not specified in the
// command line, assume IPv4. // command line, assume IPv4.
if (ipversion_ == 0) { if (ipversion_ == 0) {
...@@ -375,8 +384,8 @@ CommandOptions::initialize(int argc, char** argv) { ...@@ -375,8 +384,8 @@ CommandOptions::initialize(int argc, char** argv) {
// If DUID is not specified from command line we need to // If DUID is not specified from command line we need to
// generate one. // generate one.
if (duid_prefix_.size() == 0) { if (duid_template_.size() == 0) {
generateDuidPrefix(); generateDuidTemplate();
} }
} }
...@@ -439,7 +448,7 @@ CommandOptions::decodeMac(const std::string& base) { ...@@ -439,7 +448,7 @@ CommandOptions::decodeMac(const std::string& base) {
// Decode mac address to vector of uint8_t // Decode mac address to vector of uint8_t
std::istringstream s1(base.substr(found + 1)); std::istringstream s1(base.substr(found + 1));
std::string token; std::string token;
mac_prefix_.clear(); mac_template_.clear();
// Get pieces of MAC address separated with : (or even ::) // Get pieces of MAC address separated with : (or even ::)
while (std::getline(s1, token, ':')) { while (std::getline(s1, token, ':')) {
unsigned int ui = 0; unsigned int ui = 0;
...@@ -454,17 +463,17 @@ CommandOptions::decodeMac(const std::string& base) { ...@@ -454,17 +463,17 @@ CommandOptions::decodeMac(const std::string& base) {
} }
// If conversion succeeded store byte value // If conversion succeeded store byte value
mac_prefix_.push_back(ui); mac_template_.push_back(ui);
} }
} }
// MAC address must consist of 6 octets, otherwise it is invalid // MAC address must consist of 6 octets, otherwise it is invalid
check(mac_prefix_.size() != 6, errmsg); check(mac_template_.size() != 6, errmsg);
} }
void void
CommandOptions::decodeDuid(const std::string& base) { CommandOptions::decodeDuid(const std::string& base) {
// Strip argument from duid= // Strip argument from duid=
std::vector<uint8_t> duid_prefix; std::vector<uint8_t> duid_template;
size_t found = base.find('='); size_t found = base.find('=');
check(found == std::string::npos, "expected -b<base> format for duid is -b duid=<duid>"); check(found == std::string::npos, "expected -b<base> format for duid is -b duid=<duid>");
std::string b = base.substr(found + 1); std::string b = base.substr(found + 1);
...@@ -484,26 +493,26 @@ CommandOptions::decodeDuid(const std::string& base) { ...@@ -484,26 +493,26 @@ CommandOptions::decodeDuid(const std::string& base) {
isc_throw(isc::InvalidParameter, isc_throw(isc::InvalidParameter,
"invalid characters in DUID provided, exepected hex digits"); "invalid characters in DUID provided, exepected hex digits");
} }
duid_prefix.push_back(static_cast<uint8_t>(ui)); duid_template.push_back(static_cast<uint8_t>(ui));
} }
// Assign the new duid only if successfully generated. // Assign the new duid only if successfully generated.
std::swap(duid_prefix, duid_prefix_); std::swap(duid_template, duid_template_);
} }
void void
CommandOptions::generateDuidPrefix() { CommandOptions::generateDuidTemplate() {
using namespace boost::posix_time; using namespace boost::posix_time;
// Duid prefix will be most likely generated only once but // Duid template will be most likely generated only once but
// it is ok if it is called more then once so we simply // it is ok if it is called more then once so we simply
// regenerate it and discard previous value. // regenerate it and discard previous value.
duid_prefix_.clear(); duid_template_.clear();
const uint8_t duid_prefix_len = 14; const uint8_t duid_template_len = 14;
duid_prefix_.resize(duid_prefix_len); duid_template_.resize(duid_template_len);
// The first four octets consist of DUID LLT and hardware type. // The first four octets consist of DUID LLT and hardware type.
duid_prefix_[0] = DUID_LLT >> 8; duid_template_[0] = DUID_LLT >> 8;
duid_prefix_[1] = DUID_LLT & 0xff; duid_template_[1] = DUID_LLT & 0xff;
duid_prefix_[2] = HWTYPE_ETHERNET >> 8; duid_template_[2] = HWTYPE_ETHERNET >> 8;
duid_prefix_[3] = HWTYPE_ETHERNET & 0xff; duid_template_[3] = HWTYPE_ETHERNET & 0xff;
// As described in RFC3315: 'the time value is the time // As described in RFC3315: 'the time value is the time
// that the DUID is generated represented in seconds // that the DUID is generated represented in seconds
...@@ -512,12 +521,12 @@ CommandOptions::generateDuidPrefix() { ...@@ -512,12 +521,12 @@ CommandOptions::generateDuidPrefix() {
ptime duid_epoch(from_iso_string("20000101T000000")); ptime duid_epoch(from_iso_string("20000101T000000"));
time_period period(duid_epoch, now); time_period period(duid_epoch, now);
uint32_t duration_sec = htonl(period.length().total_seconds()); uint32_t duration_sec = htonl(period.length().total_seconds());
memcpy(&duid_prefix_[4], &duration_sec, 4); memcpy(&duid_template_[4], &duration_sec, 4);
// Set link layer address (6 octets). This value may be // Set link layer address (6 octets). This value may be
// randomized before sending a packet to simulate different // randomized before sending a packet to simulate different
// clients. // clients.
memcpy(&duid_prefix_[8], &mac_prefix_[0], 6); memcpy(&duid_template_[8], &mac_template_[0], 6);
} }
uint8_t uint8_t
......
...@@ -23,7 +23,7 @@ ...@@ -23,7 +23,7 @@
namespace isc { namespace isc {
namespace perfdhcp { namespace perfdhcp {
/// \brief Command Options /// \brief Command Options.
/// ///
/// This class is responsible for parsing the command-line and storing the /// This class is responsible for parsing the command-line and storing the
/// specified options. /// specified options.
...@@ -49,64 +49,64 @@ public: ...@@ -49,64 +49,64 @@ public:
/// command line options. /// command line options.
void reset(); void reset();
/// \brief Parse command line /// \brief Parse command line.
/// ///
/// Parses the command line and stores the selected options /// Parses the command line and stores the selected options
/// in class data members. /// in class data members.
/// ///
/// \param argc Argument count passed to main(). /// \param argc Argument count passed to main().
/// \param argv Argument value array passed to main(). /// \param argv Argument value array passed to main().
/// \throws isc::InvalidParameter if parse fails /// \throws isc::InvalidParameter if parse fails.
void parse(int argc, char** const argv); void parse(int argc, char** const argv);
/// \brief Returns IP version /// \brief Returns IP version.
/// ///
/// \return IP version to be used /// \return IP version to be used.
uint8_t getIpVersion() const { return ipversion_; } uint8_t getIpVersion() const { return ipversion_; }
/// \brief Returns packet exchange mode /// \brief Returns packet exchange mode.
/// ///
/// \return packet exchange mode /// \return packet exchange mode.
ExchangeMode getExchangeMode() const { return exchange_mode_; } ExchangeMode getExchangeMode() const { return exchange_mode_; }
/// \brief Returns echange rate /// \brief Returns echange rate.
/// ///
/// \return exchange rate per second /// \return exchange rate per second.
int getRate() const { return rate_; } int getRate() const { return rate_; }
/// \brief Returns delay between two performance reports /// \brief Returns delay between two performance reports.
/// ///
/// \return delay between two consecutive performance reports /// \return delay between two consecutive performance reports.
int getReportDelay() const { return report_delay_; } int getReportDelay() const { return report_delay_; }
/// \brief Returns number of simulated clients /// \brief Returns number of simulated clients.
/// ///
/// \return number of simulated clients /// \return number of simulated clients.
uint32_t getClientsNum() const { return clients_num_; } uint32_t getClientsNum() const { return clients_num_; }
/// \brief Returns MAC address prefix /// \brief Returns MAC address template.
/// ///
/// \ return MAC address prefix to simulate different clients /// \return MAC address template to simulate different clients.
std::vector<uint8_t> getMacPrefix() const { return mac_prefix_; } std::vector<uint8_t> getMacTemplate() const { return mac_template_; }
/// \brief Returns DUID prefix /// \brief Returns DUID template.
/// ///
/// \return DUID prefix to simulate different clients /// \return DUID template to simulate different clients.
std::vector<uint8_t> getDuidPrefix() const { return duid_prefix_; } std::vector<uint8_t> getDuidTemplate() const { return duid_template_; }
/// \brief Returns base values /// \brief Returns base values.
/// ///
/// \return all base values specified /// \return all base values specified.
std::vector<std::string> getBase() const { return base_; } std::vector<std::string> getBase() const { return base_; }
/// \brief Returns maximum number of exchanges /// \brief Returns maximum number of exchanges.
/// ///
/// \return number of exchange requests before test is aborted /// \return number of exchange requests before test is aborted.
std::vector<int> getNumRequests() const { return num_request_; } std::vector<int> getNumRequests() const { return num_request_; }
/// \brief Returns test period /// \brief Returns test period.
/// ///
/// \return test period before it is aborted /// \return test period before it is aborted.
int getPeriod() const { return period_; } int getPeriod() const { return period_; }
/// \brief Returns drop time /// \brief Returns drop time
...@@ -114,139 +114,139 @@ public: ...@@ -114,139 +114,139 @@ public:
/// The method returns maximum time elapsed from /// The method returns maximum time elapsed from
/// sending the packet before it is assumed dropped. /// sending the packet before it is assumed dropped.
/// ///
/// \return return time before request is assumed dropped /// \return return time before request is assumed dropped.
std::vector<double> getDropTime() const { return drop_time_; } std::vector<double> getDropTime() const { return drop_time_; }
/// \brief Returns maximum drops number /// \brief Returns maximum drops number.
/// ///
/// Returns maximum number of packet drops before /// Returns maximum number of packet drops before
/// aborting a test. /// aborting a test.
/// ///
/// \return maximum number of dropped requests /// \return maximum number of dropped requests.
std::vector<int> getMaxDrop() const { return max_drop_; } std::vector<int> getMaxDrop() const { return max_drop_; }
/// \brief Returns maximal percentage of drops /// \brief Returns maximal percentage of drops.
/// ///
/// Returns maximal percentage of packet drops /// Returns maximal percentage of packet drops
/// before aborting a test. /// before aborting a test.
/// ///
/// \return maximum percentage of lost requests /// \return maximum percentage of lost requests.
std::vector<double> getMaxDropPercentage() const { return max_pdrop_; } std::vector<double> getMaxDropPercentage() const { return max_pdrop_; }
/// \brief Returns local address or interface name /// \brief Returns local address or interface name.
/// ///
/// \return local address or interface name /// \return local address or interface name.
std::string getLocalName() const { return localname_; } std::string getLocalName() const { return localname_; }
/// \brief Checks if interface name was used /// \brief Checks if interface name was used.
/// ///
/// The method checks if interface name was used /// The method checks if interface name was used
/// rather than address. /// rather than address.
/// ///
/// \return true if interface name was used /// \return true if interface name was used.
bool isInterface() const { return is_interface_; } bool isInterface() const { return is_interface_; }
/// \brief Returns number of preload exchanges /// \brief Returns number of preload exchanges.
/// ///
/// \return number of preload exchanges /// \return number of preload exchanges.
int getPreload() const { return preload_; } int getPreload() const { return preload_; }
/// \brief Returns aggressivity value /// \brief Returns aggressivity value.
/// ///
/// \return aggressivity value /// \return aggressivity value.
int getAggressivity() const { return aggressivity_; } int getAggressivity() const { return aggressivity_; }
/// \brief Returns local port number /// \brief Returns local port number.
/// ///
/// \return local port number /// \return local port number.
int getLocalPort() const { return local_port_; } int getLocalPort() const { return local_port_; }
/// \brief Checks if seed provided /// \brief Checks if seed provided.
/// ///
/// \return true if seed was provided /// \return true if seed was provided.
bool isSeeded() const { return seeded_; } bool isSeeded() const { return seeded_; }
/// \brief Returns radom seed /// \brief Returns radom seed.
/// ///
/// \return random seed /// \return random seed.
uint32_t getSeed() const { return seed_; } uint32_t getSeed() const { return seed_; }
/// \brief Checks if broadcast address is to be used /// \brief Checks if broadcast address is to be used.
/// ///
/// \return true if broadcast address is to be used /// \return true if broadcast address is to be used.
bool isBroadcast() const { return broadcast_; } bool isBroadcast() const { return broadcast_; }
/// \brief Check if rapid commit option used /// \brief Check if rapid commit option used.
/// ///
/// \return true if rapid commit option is used /// \return true if rapid commit option is used.
bool isRapidCommit() const { return rapid_commit_; } bool isRapidCommit() const { return rapid_commit_; }
/// \brief Check if server-ID to be taken from first package /// \brief Check if server-ID to be taken from first package.
/// ///
/// \return true if server-iD to be taken from first package /// \return true if server-iD to be taken from first package.
bool isUseFirst() const { return use_first_; } bool isUseFirst() const { return use_first_; }
/// \brief Returns template file names /// \brief Returns template file names.
/// ///
/// \return template file names /// \return template file names.
std::vector<std::string> getTemplateFiles() const { return template_file_; } std::vector<std::string> getTemplateFiles() const { return template_file_; }
/// brief Returns template offsets for xid /// brief Returns template offsets for xid.
/// ///
/// \return template offsets for xid /// \return template offsets for xid.
std::vector<int> getTransactionIdOffset() const { return xid_offset_; } std::vector<int> getTransactionIdOffset() const { return xid_offset_; }
/// \brief Returns template offsets for rnd /// \brief Returns template offsets for rnd.
/// ///
/// \return template offsets for rnd /// \return template offsets for rnd.
std::vector<int> getRandomOffset() const { return rnd_offset_; } std::vector<int> getRandomOffset() const { return rnd_offset_; }
/// \brief Returns template offset for elapsed time /// \brief Returns template offset for elapsed time.
/// ///
/// \return template offset for elapsed time /// \return template offset for elapsed time.
int getElapsedTimeOffset() const { return elp_offset_; } int getElapsedTimeOffset() const { return elp_offset_; }
/// \brief Returns template offset for server-ID /// \brief Returns template offset for server-ID.
/// ///
/// \return template offset for server-ID /// \return template offset for server-ID.
int getServerIdOffset() const { return sid_offset_; } int getServerIdOffset() const { return sid_offset_; }
/// \brief Returns template offset for requested IP /// \brief Returns template offset for requested IP.
/// ///
/// \return template offset for requested IP /// \return template offset for requested IP.
int getRequestedIpOffset() const { return rip_offset_; } int getRequestedIpOffset() const { return rip_offset_; }
/// \brief Returns diagnostic selectors /// \brief Returns diagnostic selectors.
/// ///
/// \return diagnostics selector /// \return diagnostics selector.
std::string getDiags() const { return diags_; } std::string getDiags() const { return diags_; }
/// \brief Returns wrapped command /// \brief Returns wrapped command.
/// ///
/// \return wrapped command (start/stop) /// \return wrapped command (start/stop).
std::string getWrapped() const { return wrapped_; } std::string getWrapped() const { return wrapped_; }
/// \brief Returns server name /// \brief Returns server name.
/// ///
/// \return server name /// \return server name.
std::string getServerName() const { return server_name_; } std::string getServerName() const { return server_name_; }
/// \brief Prints command line arguments. /// \brief Print command line arguments.
void printCommandLine() const; void printCommandLine() const;
/// \brief Print usage /// \brief Print usage.
/// ///
/// Prints perfdhcp usage /// Prints perfdhcp usage.
void usage() const; void usage() const;
/// \brief Print program version /// \brief Print program version.
/// ///
/// Prints perfdhcp version /// Prints perfdhcp version.
void version() const; void version() const;
private: private:
/// \brief Default Constructor /// \brief Default Constructor.
/// ///
/// Private constructor as this is a singleton class. /// Private constructor as this is a singleton class.
/// Use CommandOptions::instance() to get instance of it. /// Use CommandOptions::instance() to get instance of it.
...@@ -254,54 +254,54 @@ private: ...@@ -254,54 +254,54 @@ private:
reset(); reset();
} }
/// \brief Initializes class members based command line /// \brief Initializes class members based on the command line.
/// ///
/// Reads each command line parameter and sets class member values /// Reads each command line parameter and sets class member values.
/// ///
/// \param argc Argument count passed to main(). /// \param argc Argument count passed to main().
/// \param argv Argument value array passed to main(). /// \param argv Argument value array passed to main().
/// \throws isc::InvalidParameter if command line options initialization fails /// \throws isc::InvalidParameter if command line options initialization fails.
void initialize(int argc, char** argv); void initialize(int argc, char** argv);
/// \brief Validates initialized options /// \brief Validates initialized options.
/// ///
/// \throws isc::InvalidParameter if command line validation fails /// \throws isc::InvalidParameter if command line validation fails.
void validate() const; void validate() const;
/// \brief Throws !InvalidParameter exception if condition is true /// \brief Throws !InvalidParameter exception if condition is true.
/// ///
/// Convenience function that throws an InvalidParameter exception if /// Convenience function that throws an InvalidParameter exception if
/// the condition argument is true /// the condition argument is true.
/// ///
/// \param condition Condition to be checked /// \param condition Condition to be checked.
/// \param errmsg Error message in exception /// \param errmsg Error message in exception.
/// \throws isc::InvalidParameter if condition argument true /// \throws isc::InvalidParameter if condition argument true.
inline void check(bool condition, const std::string& errmsg) const; inline void check(bool condition, const std::string& errmsg) const;
/// \brief Casts command line argument to positive integer /// \brief Casts command line argument to positive integer.
/// ///
/// \param errmsg Error message if lexical cast fails /// \param errmsg Error message if lexical cast fails.
/// \throw InvalidParameter if lexical cast fails /// \throw InvalidParameter if lexical cast fails.
int positiveInteger(const std::string& errmsg) const; int positiveInteger(const std::string& errmsg) const;
/// \brief Casts command line argument to non-negative integer /// \brief Casts command line argument to non-negative integer.
/// ///
/// \param errmsg Error message if lexical cast fails /// \param errmsg Error message if lexical cast fails.
/// \throw InvalidParameter if lexical cast fails /// \throw InvalidParameter if lexical cast fails.
int nonNegativeInteger(const std::string& errmsg) const; int nonNegativeInteger(const std::string& errmsg) const;
/// \brief Returns command line string if it is not empty /// \brief Returns command line string if it is not empty.
/// ///
/// \param errmsg Error message if string is empty /// \param errmsg Error message if string is empty.
/// \throw InvalidParameter if string is empty /// \throw InvalidParameter if string is empty.
std::string nonEmptyString(const std::string& errmsg) const; std::string nonEmptyString(const std::string& errmsg) const;
/// \brief Set number of clients /// \brief Set number of clients.
/// ///
/// Interprets the getopt() "opt" global variable as the number of clients /// Interprets the getopt() "opt" global variable as the number of clients
/// (a non-negative number). This value is specified by the "-R" switch. /// (a non-negative number). This value is specified by the "-R" switch.
/// ///
/// \throw InvalidParameter if -R<value> is wrong /// \throw InvalidParameter if -R<value> is wrong.
void initClientsNum(); void initClientsNum();
/// \brief Sets value indicating if interface name was given. /// \brief Sets value indicating if interface name was given.
...@@ -311,7 +311,7 @@ private: ...@@ -311,7 +311,7 @@ private:
/// is set accordingly. /// is set accordingly.
void initIsInterface(); void initIsInterface();