Browse Source

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

Marcin Siodelski 12 years ago
parent
commit
6a3c2c6180

+ 32 - 23
tests/tools/perfdhcp/command_options.cc

@@ -56,8 +56,8 @@ CommandOptions::reset() {
     rate_ = 0;
     report_delay_ = 0;
     clients_num_ = 0;
-    mac_prefix_.assign(mac, mac + 6);
-    duid_prefix_.clear();
+    mac_template_.assign(mac, mac + 6);
+    duid_template_.clear();
     base_.clear();
     num_request_.clear();
     period_ = 0;
@@ -84,8 +84,8 @@ CommandOptions::reset() {
     diags_.clear();
     wrapped_.clear();
     server_name_.clear();
-
-    generateDuidPrefix();
+    generateDuidTemplate();
+    commandline_.clear();
 }
 
 void
@@ -132,9 +132,16 @@ CommandOptions::initialize(int argc, char** argv) {
     int offset_arg = 0;         // Temporary variable holding offset arguments
     std::string sarg;           // Temporary variable for string args
 
+    std::ostringstream stream;
+    stream << "perfdhcp";
+
     // In this section we collect argument values from command line
     // 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) {
+        stream << " -" << opt;
+        if (optarg) {
+            stream << " " << optarg;
+        }  
         switch (opt) {
         case 'v':
             version();
@@ -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
     // command line, assume IPv4.
     if (ipversion_ == 0) {
@@ -375,8 +384,8 @@ CommandOptions::initialize(int argc, char** argv) {
 
     // If DUID is not specified from command line we need to
     // generate one.
-    if (duid_prefix_.size() == 0) {
-        generateDuidPrefix();
+    if (duid_template_.size() == 0) {
+        generateDuidTemplate();
     }
 }
 
@@ -439,7 +448,7 @@ CommandOptions::decodeMac(const std::string& base) {
     // Decode mac address to vector of uint8_t
     std::istringstream s1(base.substr(found + 1));
     std::string token;
-    mac_prefix_.clear();
+    mac_template_.clear();
     // Get pieces of MAC address separated with : (or even ::)
     while (std::getline(s1, token, ':')) {
         unsigned int ui = 0;
@@ -454,17 +463,17 @@ CommandOptions::decodeMac(const std::string& base) {
 
             }
             // 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
-    check(mac_prefix_.size() != 6, errmsg);
+    check(mac_template_.size() != 6, errmsg);
 }
 
 void
 CommandOptions::decodeDuid(const std::string& base) {
     // Strip argument from duid=
-    std::vector<uint8_t> duid_prefix;
+    std::vector<uint8_t> duid_template;
     size_t found = base.find('=');
     check(found == std::string::npos, "expected -b<base> format for duid is -b duid=<duid>");
     std::string b = base.substr(found + 1);
@@ -484,26 +493,26 @@ CommandOptions::decodeDuid(const std::string& base) {
             isc_throw(isc::InvalidParameter,
                       "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.
-    std::swap(duid_prefix, duid_prefix_);
+    std::swap(duid_template, duid_template_);
 }
 
 void
-CommandOptions::generateDuidPrefix() {
+CommandOptions::generateDuidTemplate() {
     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
     //  regenerate it and discard previous value.
-    duid_prefix_.clear();
-    const uint8_t duid_prefix_len = 14;
-    duid_prefix_.resize(duid_prefix_len);
+    duid_template_.clear();
+    const uint8_t duid_template_len = 14;
+    duid_template_.resize(duid_template_len);
     // The first four octets consist of DUID LLT and hardware type.
-    duid_prefix_[0] = DUID_LLT >> 8;
-    duid_prefix_[1] = DUID_LLT & 0xff;
-    duid_prefix_[2] = HWTYPE_ETHERNET >> 8;
-    duid_prefix_[3] = HWTYPE_ETHERNET & 0xff;
+    duid_template_[0] = DUID_LLT >> 8;
+    duid_template_[1] = DUID_LLT & 0xff;
+    duid_template_[2] = HWTYPE_ETHERNET >> 8;
+    duid_template_[3] = HWTYPE_ETHERNET & 0xff;
     
     // As described in RFC3315: 'the time value is the time
     // that the DUID is generated represented in seconds
@@ -512,12 +521,12 @@ CommandOptions::generateDuidPrefix() {
     ptime duid_epoch(from_iso_string("20000101T000000"));
     time_period period(duid_epoch, now);
     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
     // randomized before sending a packet to simulate different
     // clients.
-    memcpy(&duid_prefix_[8], &mac_prefix_[0], 6);
+    memcpy(&duid_template_[8], &mac_template_[0], 6);
 }
 
 uint8_t

+ 120 - 117
tests/tools/perfdhcp/command_options.h

@@ -23,7 +23,7 @@
 namespace isc {
 namespace perfdhcp {
 
-/// \brief Command Options
+/// \brief Command Options.
 ///
 /// This class is responsible for parsing the command-line and storing the
 /// specified options.
@@ -49,64 +49,64 @@ public:
     /// command line options.
     void reset();
 
-    /// \brief Parse command line
+    /// \brief Parse command line.
     ///
     /// Parses the command line and stores the selected options
     /// in class data members.
     ///
     /// \param argc Argument count 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);
 
-    /// \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_; }
 
-    /// \brief Returns packet exchange mode
+    /// \brief Returns packet exchange mode.
     ///
-    /// \return packet exchange mode
+    /// \return packet 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_; }
 
-    /// \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_; }
 
-    /// \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_; }
 
-    /// \brief Returns MAC address prefix
+    /// \brief Returns MAC address template.
     ///
-    /// \ return MAC address prefix to simulate different clients
-    std::vector<uint8_t> getMacPrefix() const { return mac_prefix_; }
+    /// \return MAC address template to simulate different clients.
+    std::vector<uint8_t> getMacTemplate() const { return mac_template_; }
 
-    /// \brief Returns DUID prefix
+    /// \brief Returns DUID template.
     ///
-    /// \return DUID prefix to simulate different clients
-    std::vector<uint8_t> getDuidPrefix() const { return duid_prefix_; }
+    /// \return DUID template to simulate different clients.
+    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_; }
 
-    /// \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_; }
 
-    /// \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_; }
 
     /// \brief Returns drop time
@@ -114,139 +114,139 @@ public:
     /// The method returns maximum time elapsed from
     /// 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_; }
 
-    /// \brief Returns maximum drops number
+    /// \brief Returns maximum drops number.
     ///
     /// Returns maximum number of packet drops before
     /// aborting a test.
     ///
-    /// \return maximum number of dropped requests
+    /// \return maximum number of dropped requests.
     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
     /// before aborting a test.
     ///
-    /// \return maximum percentage of lost requests
+    /// \return maximum percentage of lost requests.
     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_; }
 
-    /// \brief Checks if interface name was used
+    /// \brief Checks if interface name was used.
     ///
     /// The method checks if interface name was used
     /// rather than address.
     ///
-    /// \return true if interface name was used
+    /// \return true if interface name was used.
     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_; }
 
-    /// \brief Returns aggressivity value
+    /// \brief Returns aggressivity value.
     ///
-    /// \return aggressivity value
+    /// \return aggressivity value.
     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_; }
 
-    /// \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_; }
 
-    /// \brief Returns radom seed
+    /// \brief Returns radom seed.
     ///
-    /// \return random seed
+    /// \return random 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_; }
 
-    /// \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_; }
 
-    /// \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_; }
 
-    /// \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_; }
 
-    /// 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_; }
 
-    /// \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_; }
 
-    /// \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_; }
 
-    /// \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_; }
 
-    /// \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_; }
 
-    /// \brief Returns diagnostic selectors
+    /// \brief Returns diagnostic selectors.
     ///
-    /// \return diagnostics selector
+    /// \return diagnostics selector.
     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_; }
 
-    /// \brief Returns server name
+    /// \brief Returns server name.
     ///
-    /// \return server name
+    /// \return server name.
     std::string getServerName() const { return server_name_; }
     
-    /// \brief Prints command line arguments.
+    /// \brief Print command line arguments.
     void printCommandLine() const;
 
-    /// \brief Print usage
+    /// \brief Print usage.
     ///
-    /// Prints perfdhcp usage
+    /// Prints perfdhcp usage.
     void usage() const;
 
-    /// \brief Print program version
+    /// \brief Print program version.
     ///
-    /// Prints perfdhcp version
+    /// Prints perfdhcp version.
     void version() const;
 
 private:
 
-    /// \brief Default Constructor
+    /// \brief Default Constructor.
     ///
     /// Private constructor as this is a singleton class.
     /// Use CommandOptions::instance() to get instance of it.
@@ -254,54 +254,54 @@ private:
         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 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);
 
-    /// \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;
 
-    /// \brief Throws !InvalidParameter exception if condition is true
+    /// \brief Throws !InvalidParameter exception if condition is true.
     ///
     /// 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 errmsg Error message in exception
-    /// \throws isc::InvalidParameter if condition argument true
+    /// \param condition Condition to be checked.
+    /// \param errmsg Error message in exception.
+    /// \throws isc::InvalidParameter if condition argument true.
     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
-    /// \throw InvalidParameter if lexical cast fails
+    /// \param errmsg Error message if lexical cast fails.
+    /// \throw InvalidParameter if lexical cast fails.
     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
-    /// \throw InvalidParameter if lexical cast fails
+    /// \param errmsg Error message if lexical cast fails.
+    /// \throw InvalidParameter if lexical cast fails.
     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
-    /// \throw InvalidParameter if string is empty
+    /// \param errmsg Error message if string is empty.
+    /// \throw InvalidParameter if string is empty.
     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
     /// (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();
 
     /// \brief Sets value indicating if interface name was given.
@@ -311,7 +311,7 @@ private:
     /// is set accordingly.
     void initIsInterface();
 
-    /// \brief Decodes base provided with -b<base>
+    /// \brief Decodes base provided with -b<base>.
     ///
     /// Function decodes argument of -b switch, which
     /// specifies a base value used to generate unique
@@ -321,45 +321,47 @@ private:
     /// - -b mac=00:01:02:03:04:05
     /// - -b duid=0F1234 (duid can be up to 128 hex digits)
     //  Function will decode 00:01:02:03:04:05 and/or
-    /// 0F1234 respectively and initialize mac_prefix_
-    /// and/or duid_prefix_ members
+    /// 0F1234 respectively and initialize mac_template_
+    /// and/or duid_template_ members.
     ///
-    /// \param base Base in string format
-    /// \throws isc::InvalidParameter if base is invalid
+    /// \param base Base in string format.
+    /// \throws isc::InvalidParameter if base is invalid.
     void decodeBase(const std::string& base);
 
-    /// \brief Decodes base MAC address provided with -b<base>
+    /// \brief Decodes base MAC address provided with -b<base>.
     ///
     /// Function decodes parameter given as -b mac=00:01:02:03:04:05
-    /// The function will decode 00:01:02:03:04:05 initialize mac_prefix_
+    /// The function will decode 00:01:02:03:04:05 initialize mac_template_
     /// class member.
-    /// Provided MAC address is for example only
+    /// Provided MAC address is for example only.
     ///
-    /// \param base Base string given as -b mac=00:01:02:03:04:05
-    /// \throws isc::InvalidParameter if mac address is invalid
+    /// \param base Base string given as -b mac=00:01:02:03:04:05.
+    /// \throws isc::InvalidParameter if mac address is invalid.
     void decodeMac(const std::string& base);
 
-    /// \brief Decodes base DUID provided with -b<base>
+    /// \brief Decodes base DUID provided with -b<base>.
     ///
-    /// Function decodes parameter given as -b duid=0F1234
-    /// The function will decode 0F1234 and initialize duid_prefix_
+    /// Function decodes parameter given as -b duid=0F1234.
+    /// The function will decode 0F1234 and initialize duid_template_
     /// class member.
     /// Provided DUID is for example only.
     ///
-    /// \param base Base string given as -b duid=0F1234
-    /// \throws isc::InvalidParameter if DUID is invalid
+    /// \param base Base string given as -b duid=0F1234.
+    /// \throws isc::InvalidParameter if DUID is invalid.
     void decodeDuid(const std::string& base);
     
     /// \brief Generates DUID-LLT (based on link layer address).
     ///
     /// Function generates DUID based on link layer address and
-    /// initiates duid_prefix_ value with it.
-    void generateDuidPrefix();
+    /// initiates duid_template_ value with it.
+    /// \todo add support to generate DUIDs other than based on
+    /// 6-octets long MACs (e.g. DUID-UUID.
+    void generateDuidTemplate();
 
-    /// \brief Converts two-digit hexadecimal string to a byte
+    /// \brief Converts two-digit hexadecimal string to a byte.
     ///
-    /// \param hex_text Hexadecimal string e.g. AF
-    /// \throw isc::InvalidParameter if string does not represent hex byte
+    /// \param hex_text Hexadecimal string e.g. AF.
+    /// \throw isc::InvalidParameter if string does not represent hex byte.
     uint8_t convertHexString(const std::string& hex_text) const;
 
     uint8_t ipversion_;                      ///< IP protocol version to be used, expected values are:
@@ -369,9 +371,9 @@ private:
     int report_delay_;                       ///< Delay between generation of two consecutive
                                              ///< performance reports
     uint32_t clients_num_;                   ///< Number of simulated clients (aka randomization range).
-    std::vector<uint8_t> mac_prefix_;        ///< MAC address prefix used to generate unique DUIDs
+    std::vector<uint8_t> mac_template_;      ///< MAC address template used to generate unique DUIDs
                                              ///< for simulated clients.
-    std::vector<uint8_t> duid_prefix_;       ///< DUID prefix used to generate unique DUIDs for
+    std::vector<uint8_t> duid_template_;     ///< DUID template used to generate unique DUIDs for
                                              ///< simulated clients
     std::vector<std::string> base_;          ///< Collection of base values specified with -b<value>
                                              ///< options. Supported "bases" are mac=<mac> and duid=<duid>
@@ -420,6 +422,7 @@ private:
     std::string wrapped_;                    ///< Wrapped command specified as -w<value>. Expected
                                              ///< values are start and stop.
     std::string server_name_;                ///< Server name specified as last argument of command line.
+    std::string commandline_;                ///< Entire command line as typed in by the user.
 };
 
 } // namespace perfdhcp

+ 27 - 52
tests/tools/perfdhcp/localized_option.h

@@ -44,30 +44,43 @@ namespace perfdhcp {
 ///
 class LocalizedOption : public dhcp::Option {
 public:
-    /// \brief Constructor, sets default (0) option offset
+
+    /// \brief Constructor, used to create localized option from buffer.
     ///
-    /// \param u specifies universe (V4 or V6)
-    /// \param type option type (0-255 for V4 and 0-65535 for V6)
-    /// \param data content of the option
+    /// This constructor creates localized option using whole provided
+    /// option buffer.
+    ///
+    /// \param u universe (V4 or V6).
+    /// \param type option type (0-255 for V4 and 0-65535 for V6).
+    /// Option values 0 and 255 (v4) and 0 (v6) are not valid option
+    /// codes but they are accepted here for the server testing purposes.
+    /// \param data content of the option.
+    /// \param offset location of option in a packet (zero is default).
     LocalizedOption(dhcp::Option::Universe u,
                     uint16_t type,
-                    const dhcp::OptionBuffer& data) :
+                    const dhcp::OptionBuffer& data,
+                    const size_t offset = 0) :
         dhcp::Option(u, type, data),
-        offset_(0), option_valid_(true) {
+        offset_(offset), option_valid_(true) {
     }
 
-
-    /// \brief Constructor, used to create localized option from buffer
+    /// \brief Constructor, used to create option from buffer iterators.
+    ///
+    /// This constructor creates localized option using part of the
+    /// option buffer pointed by iterators.
     ///
     /// \param u specifies universe (V4 or V6)
     /// \param type option type (0-255 for V4 and 0-65535 for V6)
-    /// \param data content of the option
-    /// \param offset location of option in a packet (zero is default)
+    /// \param first iterator to the first element that should be copied
+    /// \param last iterator to the next element after the last one
+    ///        to be copied.
+    /// \param offset offset of option in a packet (zero is default)
     LocalizedOption(dhcp::Option::Universe u,
                     uint16_t type,
-                    const dhcp::OptionBuffer& data,
-                    const size_t offset) :
-        dhcp::Option(u, type, data),
+                    dhcp::OptionBufferConstIter first,
+                    dhcp::OptionBufferConstIter last,
+                    const size_t offset = 0) :
+        dhcp::Option(u, type, first, last),
         offset_(offset), option_valid_(true) {
     }
 
@@ -113,44 +126,6 @@ public:
         }
     }
 
-    /// \brief Constructor, sets default (0) option offset
-    ///
-    /// This contructor is similar to the previous one, but it does not take
-    /// the whole vector<uint8_t>, but rather subset of it.
-    ///
-    /// \param u specifies universe (V4 or V6)
-    /// \param type option type (0-255 for V4 and 0-65535 for V6)
-    /// \param first iterator to the first element that should be copied
-    /// \param last iterator to the next element after the last one
-    ///        to be copied.
-    LocalizedOption(dhcp::Option::Universe u,
-                    uint16_t type,
-                    dhcp::OptionBufferConstIter first,
-                    dhcp::OptionBufferConstIter last) :
-        dhcp::Option(u, type, first, last),
-        offset_(0), option_valid_(true) {
-    }
-
-
-    /// \brief Constructor, used to create option from buffer iterators
-    ///
-    /// This contructor is similar to the previous one, but it does not take
-    /// the whole vector<uint8_t>, but rather subset of it.
-    ///
-    /// \param u specifies universe (V4 or V6)
-    /// \param type option type (0-255 for V4 and 0-65535 for V6)
-    /// \param first iterator to the first element that should be copied
-    /// \param last iterator to the next element after the last one
-    ///        to be copied.
-    /// \param offset offset of option in a packet (zero is default)
-    LocalizedOption(dhcp::Option::Universe u,
-                    uint16_t type,
-                    dhcp::OptionBufferConstIter first,
-                    dhcp::OptionBufferConstIter last, const size_t offset) :
-        dhcp::Option(u, type, first, last),
-        offset_(offset), option_valid_(true) {
-    }
-
     /// \brief Returns offset of an option in a DHCP packet.
     ///
     /// \return option offset in a packet
@@ -169,7 +144,7 @@ private:
 };
 
 
-} // namespace perfdhcp
+} // namespace isc::perfdhcp
 } // namespace isc
 
 #endif // __LOCALIZED_OPTION_H

+ 0 - 1
tests/tools/perfdhcp/perf_pkt4.h

@@ -113,7 +113,6 @@ public:
     void writeAt(size_t dest_pos,
                  std::vector<uint8_t>::iterator first,
                  std::vector<uint8_t>::iterator last);
-
     
     /// \brief Replace contents of buffer with value.
     ///

+ 1 - 6
tests/tools/perfdhcp/pkt_transform.cc

@@ -221,12 +221,7 @@ void
 PktTransform::writeAt(dhcp::OptionBuffer& in_buffer, size_t dest_pos,
                       dhcp::OptionBuffer::iterator first,
                       dhcp::OptionBuffer::iterator last) {
-    int i = 0;
-    for (std::vector<uint8_t>::iterator it = first;
-         it != last;
-         ++it, ++i) {
-        in_buffer[dest_pos + i] = *it;
-    }
+    memcpy(&in_buffer[dest_pos], &(*first), std::distance(first, last));
 }
 
 } // namespace perfdhcp

+ 1 - 1
tests/tools/perfdhcp/pkt_transform.h

@@ -115,7 +115,7 @@ public:
     static void writeValueAt(dhcp::OptionBuffer& in_buffer, size_t dest_pos,
                         T val) {
         for (int i = 0; i < sizeof(T); ++i) {
-            in_buffer[dest_pos + i] = (val >> (sizeof(T) - 8 * i - 1)) & 0xFF;
+            in_buffer[dest_pos + i] = (val >> 8 * (sizeof(T) - i - 1)) & 0xFF;
         }
     }
 

+ 4 - 5
tests/tools/perfdhcp/stats_mgr.h

@@ -1102,13 +1102,12 @@ public:
     /// Statistics includes sent, received and dropped packets
     /// counters.
     void printIntermediateStats() const {
-        std::ostringstream stream_sent("");
-        std::ostringstream stream_rcvd("");
-        std::ostringstream stream_drops("");
+        std::ostringstream stream_sent;
+        std::ostringstream stream_rcvd;
+        std::ostringstream stream_drops;
         std::string sep("");
         for (ExchangesMapIterator it = exchanges_.begin();
-             it != exchanges_.end();
-             ++it) {
+             it != exchanges_.end(); ++it) {
 
             if (it != exchanges_.begin()) {
                 sep = "/";

+ 9 - 9
tests/tools/perfdhcp/test_control.cc

@@ -325,12 +325,12 @@ TestControl::generateMacAddress(uint8_t& randomized) const {
     CommandOptions& options = CommandOptions::instance();
     uint32_t clients_num = options.getClientsNum();
     if ((clients_num == 0) || (clients_num == 1)) {
-        return (options.getMacPrefix());
+        return (options.getMacTemplate());
     }
     // Get the base MAC address. We are going to randomize part of it.
-    std::vector<uint8_t> mac_addr(options.getMacPrefix());
+    std::vector<uint8_t> mac_addr(options.getMacTemplate());
     if (mac_addr.size() != HW_ETHER_LEN) {
-        isc_throw(BadValue, "invalid MAC address prefix specified");
+        isc_throw(BadValue, "invalid MAC address template specified");
     }
     uint32_t r = random();
     // The random number must be in the range 0..clients_num. This
@@ -364,10 +364,11 @@ TestControl::generateDuid(uint8_t& randomized) const {
     CommandOptions& options = CommandOptions::instance();
     uint32_t clients_num = options.getClientsNum();
     if ((clients_num == 0) || (clients_num == 1)) {
-        return (options.getDuidPrefix());
+        return (options.getDuidTemplate());
     }
     // Get the base DUID. We are going to randomize part of it.
-    std::vector<uint8_t> duid(options.getDuidPrefix());
+    std::vector<uint8_t> duid(options.getDuidTemplate());
+    // @todo: add support for DUIDs of different sizes.
     std::vector<uint8_t> mac_addr(generateMacAddress(randomized));
     duid.resize(duid.size() - mac_addr.size());
     for (int i = 0; i < mac_addr.size(); ++i) {
@@ -589,12 +590,11 @@ TestControl::printDiagnostics() const {
         // Print all command line parameters.
         options.printCommandLine();
         // Print MAC and DUID.
-        std::cout << "Set MAC to " << vector2Hex(options.getMacPrefix(), "::")
+        std::cout << "Set MAC to " << vector2Hex(options.getMacTemplate(), "::")
                   << std::endl;
-        if (options.getDuidPrefix().size() > 0) {
-            std::cout << "Set DUID to " << vector2Hex(options.getDuidPrefix()) << std::endl; 
+        if (options.getDuidTemplate().size() > 0) {
+            std::cout << "Set DUID to " << vector2Hex(options.getDuidTemplate()) << std::endl; 
         }
-
     }
 }
 

+ 2 - 2
tests/tools/perfdhcp/test_control.h

@@ -335,10 +335,10 @@ protected:
     /// simulated DHCP clients specified from command line. It uses
     /// \ref CommandOptions object to retrieve number of clients.
     /// Based on this the random value is generated and added to
-    /// the MAC address prefix (default MAC address).
+    /// the MAC address template (default MAC address).
     ///
     /// \param randomized number of bytes randomized.
-    /// \throw isc::BadValue if MAC address prefix (default or specified
+    /// \throw isc::BadValue if MAC address template (default or specified
     /// from the command line) has invalid size (expected 6 octets).
     /// \return generated MAC address.
     std::vector<uint8_t> generateMacAddress(uint8_t& randomized) const;

+ 24 - 5
tests/tools/perfdhcp/tests/command_options_unittest.cc

@@ -16,6 +16,7 @@
 #include <stdint.h>
 #include <string>
 #include <gtest/gtest.h>
+#include <boost/date_time/posix_time/posix_time.hpp>
 
 #include <dhcp/iface_mgr.h>
 #include <exceptions/exceptions.h>
@@ -25,6 +26,7 @@
 using namespace std;
 using namespace isc;
 using namespace isc::perfdhcp;
+using namespace boost::posix_time;
 
 /// \brief Test Fixture Class
 ///
@@ -72,7 +74,7 @@ protected:
 
         // default mac
         const uint8_t mac[6] = { 0x00, 0x0C, 0x01, 0x02, 0x03, 0x04 };
-        std::vector<uint8_t> v1 = opt.getMacPrefix();
+        std::vector<uint8_t> v1 = opt.getMacTemplate();
         ASSERT_EQ(6, v1.size());
         EXPECT_TRUE(std::equal(v1.begin(), v1.end(), mac));
 
@@ -85,10 +87,27 @@ protected:
         // of time value and 6 octets of variable link layer (MAC)
         // address.
         const int duid_llt_size = 14; 
-        std::vector<uint8_t> v2 = opt.getDuidPrefix();
-        ASSERT_EQ(duid_llt_size, opt.getDuidPrefix().size());
+        std::vector<uint8_t> v2 = opt.getDuidTemplate();
+        ASSERT_EQ(duid_llt_size, opt.getDuidTemplate().size());
         EXPECT_TRUE(std::equal(v2.begin(), v2.begin() + 4,
                                duid_llt_and_hw));
+        // Check time field contents.
+        ptime now = microsec_clock::universal_time();
+        ptime duid_epoch(from_iso_string("20000101T000000"));
+        time_period period(duid_epoch, now);
+        uint32_t duration_sec = period.length().total_seconds();
+        // Read time from the template generated.
+        uint32_t duration_from_template = 0;
+        memcpy(&duration_from_template, &v2[4], 4);
+        duration_from_template = htonl(duration_from_template);
+        // In special cases, we may have overflow in time field
+        // so we give ourselves the margin of 10 seconds here.
+        // If time value has been set more then 10 seconds back
+        // it is safe to compare it with the time value generated
+        // from now.
+        if (duration_from_template > 10) {
+            EXPECT_GE(duration_sec, duration_from_template);
+        }
 
         EXPECT_EQ(0, opt.getBase().size());
         EXPECT_EQ(0, opt.getNumRequests().size());
@@ -249,7 +268,7 @@ TEST_F(CommandOptionsTest, Base) {
                           0x01, 0x01, 0x01, 0x10, 0x11, 0x1F, 0x14 };
 
     // Test Mac
-    std::vector<uint8_t> v1 = opt.getMacPrefix();
+    std::vector<uint8_t> v1 = opt.getMacTemplate();
     ASSERT_EQ(6, v1.size());
     EXPECT_TRUE(std::equal(v1.begin(), v1.end(), mac));
     // "3x" is invalid value in MAC address
@@ -260,7 +279,7 @@ TEST_F(CommandOptionsTest, Base) {
     EXPECT_NO_THROW(
         process("perfdhcp -b duid=0101010101010101010110111F14 -l 127.0.0.1 all")
     );
-    std::vector<uint8_t> v2 = opt.getDuidPrefix();
+    std::vector<uint8_t> v2 = opt.getDuidTemplate();
     ASSERT_EQ(sizeof(duid) / sizeof(uint8_t), v2.size());
     EXPECT_TRUE(std::equal(v2.begin(), v2.end(), duid));
     // "t" is invalid character in DUID

+ 46 - 0
tests/tools/perfdhcp/tests/perf_pkt4_unittest.cc

@@ -381,4 +381,50 @@ TEST_F(PerfPkt4Test, UnpackTransactionId) {
     EXPECT_FALSE(pkt2->rawUnpack());
 }
 
+TEST_F(PerfPkt4Test, Writes) {
+    // Initialize intput buffer with 260 elements set to value 1.
+    dhcp::OptionBuffer in_data(260, 1);
+    // Initialize buffer to be used for write: 1,2,3,4,...,9
+    dhcp::OptionBuffer write_buf(10);
+    for (int i = 0; i < write_buf.size(); ++i) {
+        write_buf[i] = i;
+    }
+    // Create packet from the input buffer.
+    const size_t transid_offset = 4;
+    boost::scoped_ptr<PerfPkt4> pkt1(new PerfPkt4(&in_data[0],
+                                                  in_data.size(),
+                                                  transid_offset));
+    // Write numbers 4,5,6,7 to the packet's input buffer at position 10.
+    pkt1->writeAt(10, write_buf.begin() + 3, write_buf.begin() + 7);
+    // We have to pack data to output buffer here because Pkt4 provides no
+    // way to retrieve input buffer. If we pack data it will go to
+    // output buffer that has getter available.
+    ASSERT_TRUE(pkt1->rawPack());
+    const util::OutputBuffer& out_buf = pkt1->getBuffer();
+    ASSERT_EQ(in_data.size(), out_buf.getLength());
+    // Verify that 4,5,6,7 has been written to the packet's buffer.
+    const char* out_data = static_cast<const char*>(out_buf.getData());
+    EXPECT_TRUE(std::equal(write_buf.begin() + 3, write_buf.begin() + 7,
+                          out_data + 10));
+    // Write 1 octet (0x51) at position 10.
+    pkt1->writeValueAt<uint8_t>(10, 0x51);
+    ASSERT_TRUE(pkt1->rawPack());
+    ASSERT_EQ(in_data.size(), pkt1->getBuffer().getLength());
+    EXPECT_EQ(0x51, pkt1->getBuffer()[10]);
+    // Write 2 octets (0x5251) at position 20.
+    pkt1->writeValueAt<uint16_t>(20, 0x5251);
+    ASSERT_TRUE(pkt1->rawPack());
+    ASSERT_EQ(in_data.size(), pkt1->getBuffer().getLength());
+    EXPECT_EQ(0x52, pkt1->getBuffer()[20]);
+    EXPECT_EQ(0x51, pkt1->getBuffer()[21]);
+    // Write 4 octets (0x54535251) at position 30.
+    pkt1->writeValueAt<uint32_t>(30, 0x54535251);
+    ASSERT_TRUE(pkt1->rawPack());
+    ASSERT_EQ(in_data.size(), pkt1->getBuffer().getLength());
+    EXPECT_EQ(0x54, pkt1->getBuffer()[30]);
+    EXPECT_EQ(0x53, pkt1->getBuffer()[31]);
+    EXPECT_EQ(0x52, pkt1->getBuffer()[32]);
+    EXPECT_EQ(0x51, pkt1->getBuffer()[33]);
+}
+
 }

+ 3 - 3
tests/tools/perfdhcp/tests/test_control_unittest.cc

@@ -215,7 +215,7 @@ public:
         // The old duid will be holding the previously generated DUID.
         // It will be used to compare against the new one. If we have
         // multiple clients we want to make sure that duids differ.
-        Duid old_duid(CommandOptions::instance().getDuidPrefix());
+        Duid old_duid(CommandOptions::instance().getDuidTemplate());
         Duid new_duid(0);
         // total_dist shows the total difference between generated duid.
         // It has to be greater than zero if multiple clients are simulated.
@@ -439,7 +439,7 @@ public:
         // MAC address. We will be comparing the newly generated one with it
         // to see if it changes when mulitple clients are simulated or if it
         // does not change when single client is simulated.
-        MacAddress old_mac(CommandOptions::instance().getMacPrefix());
+        MacAddress old_mac(CommandOptions::instance().getMacTemplate());
         // Holds the position if the octet on which two MAC addresses can
         // be different. If number of clients is 256 or less it is last MAC
         // octet (except for single client when subsequent MAC addresses
@@ -652,7 +652,7 @@ TEST_F(TestControlTest, Options6) {
     EXPECT_THROW(opt_rapid_commit->getUint8(), isc::OutOfRange);
 
     // Validate the D6O_CLIENTID option.
-    OptionBuffer duid(CommandOptions::instance().getDuidPrefix());
+    OptionBuffer duid(CommandOptions::instance().getDuidTemplate());
     OptionPtr opt_clientid(Option::factory(Option::V6, D6O_CLIENTID, duid));
     EXPECT_EQ(Option::V6, opt_clientid->getUniverse());
     EXPECT_EQ(D6O_CLIENTID, opt_clientid->getType());