BIND 10 master, updated. 4cc844f7cc82c8bd749296a2709ef67af8d9ba87 [master] Merge branch 'trac3173'

BIND 10 source code commits bind10-changes at lists.isc.org
Thu Sep 26 06:24:12 UTC 2013


The branch, master has been updated
       via  4cc844f7cc82c8bd749296a2709ef67af8d9ba87 (commit)
       via  57d3634c3d37f204f7cce1c62313036cd023faf0 (commit)
       via  b2686c2da77de241fbc4bc0f2d642daaf3c9d402 (commit)
       via  e898091a969a7f4d6481be297d1af3676480069a (commit)
       via  82a00e6ef79987b9de80c0b63950a8389592b3dc (commit)
       via  97c7bb8690967c253151462c72af68ec64da3bea (commit)
       via  33b1dda3335b747ca6fa0fb3fa421b50de867ce3 (commit)
       via  ef4ae0b32f759f25ba8fc20f1213406115fc6502 (commit)
       via  646763a3166e60b9a8920100b5ee1d02d10217c5 (commit)
       via  dcaf9bfe96a40471b82b2f97455c57828460fdd2 (commit)
       via  b6c658d2fd1bc056f66beca05ae11162a14afe09 (commit)
       via  d3f0e486be9ee295d1556ccb2afe11e843e16009 (commit)
      from  d84999478ba92ffc94741716d3b6ae8cea91f3fc (commit)

Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.

- Log -----------------------------------------------------------------
commit 4cc844f7cc82c8bd749296a2709ef67af8d9ba87
Merge: d849994 57d3634
Author: Marcin Siodelski <marcin at isc.org>
Date:   Wed Sep 25 20:45:35 2013 +0200

    [master] Merge branch 'trac3173'

-----------------------------------------------------------------------

Summary of changes:
 tests/tools/perfdhcp/command_options.cc            |  103 ++++++++++++--
 tests/tools/perfdhcp/command_options.h             |   92 +++++++++++-
 tests/tools/perfdhcp/stats_mgr.h                   |    7 +-
 tests/tools/perfdhcp/test_control.cc               |  102 ++++++++++---
 tests/tools/perfdhcp/test_control.h                |   56 ++++++--
 .../tools/perfdhcp/tests/command_options_helper.h  |    2 +-
 .../perfdhcp/tests/command_options_unittest.cc     |  135 +++++++++++++++++-
 tests/tools/perfdhcp/tests/stats_mgr_unittest.cc   |    7 +-
 .../tools/perfdhcp/tests/test_control_unittest.cc  |  150 ++++++++++++++++++--
 9 files changed, 594 insertions(+), 60 deletions(-)

-----------------------------------------------------------------------
diff --git a/tests/tools/perfdhcp/command_options.cc b/tests/tools/perfdhcp/command_options.cc
index c0ae6fa..7df1ea4 100644
--- a/tests/tools/perfdhcp/command_options.cc
+++ b/tests/tools/perfdhcp/command_options.cc
@@ -32,6 +32,63 @@ using namespace isc;
 namespace isc {
 namespace perfdhcp {
 
+CommandOptions::LeaseType::LeaseType()
+    : type_(ADDRESS) {
+}
+
+CommandOptions::LeaseType::LeaseType(const Type lease_type)
+    : type_(lease_type) {
+}
+
+bool
+CommandOptions::LeaseType::is(const Type lease_type) const {
+    return (lease_type == type_);
+}
+
+bool
+CommandOptions::LeaseType::includes(const Type lease_type) const {
+    return (is(ADDRESS_AND_PREFIX) || (lease_type == type_));
+}
+
+void
+CommandOptions::LeaseType::set(const Type lease_type) {
+    type_ = lease_type;
+}
+
+void
+CommandOptions::LeaseType::fromCommandLine(const std::string& cmd_line_arg) {
+    if (cmd_line_arg == "address-only") {
+        type_ = ADDRESS;
+
+    } else if (cmd_line_arg == "prefix-only") {
+        type_ = PREFIX;
+
+    } else if (cmd_line_arg == "address-and-prefix") {
+        type_ = ADDRESS_AND_PREFIX;
+
+    } else {
+        isc_throw(isc::InvalidParameter, "value of lease-type: -e<lease-type>,"
+                  " must be one of the following: 'address-only' or"
+                  " 'prefix-only'");
+    }
+}
+
+std::string
+CommandOptions::LeaseType::toText() const {
+    switch (type_) {
+    case ADDRESS:
+        return ("address-only (IA_NA option added to the client's request)");
+    case PREFIX:
+        return ("prefix-only (IA_PD option added to the client's request)");
+    case ADDRESS_AND_PREFIX:
+        return ("address-and-prefix (Both IA_NA and IA_PD options added to the"
+                " client's request)");
+    default:
+        isc_throw(Unexpected, "internal error: undefined lease type code when"
+                  " returning textual representation of the lease type");
+    }
+}
+
 CommandOptions&
 CommandOptions::instance() {
     static CommandOptions options;
@@ -52,6 +109,7 @@ CommandOptions::reset() {
     // will need to reset all members many times to perform unit tests
     ipversion_ = 0;
     exchange_mode_ = DORA_SARR;
+    lease_type_.set(LeaseType::ADDRESS);
     rate_ = 0;
     report_delay_ = 0;
     clients_num_ = 0;
@@ -150,7 +208,7 @@ CommandOptions::initialize(int argc, char** argv, bool print_cmd_line) {
     // 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) {
+                        "s:iBc1T:X:O:E:S:I:x:w:e:")) != -1) {
         stream << " -" << static_cast<char>(opt);
         if (optarg) {
             stream << " " << optarg;
@@ -232,6 +290,10 @@ CommandOptions::initialize(int argc, char** argv, bool print_cmd_line) {
             }
             break;
 
+        case 'e':
+            initLeaseType();
+            break;
+
         case 'E':
             elp_offset_ = nonNegativeInteger("value of time-offset: -E<value>"
                                              " must not be a negative integer");
@@ -438,7 +500,7 @@ CommandOptions::initialize(int argc, char** argv, bool print_cmd_line) {
 
     // If DUID is not specified from command line we need to
     // generate one.
-    if (duid_template_.size() == 0) {
+    if (duid_template_.empty()) {
         generateDuidTemplate();
     }
     return (false);
@@ -506,9 +568,9 @@ CommandOptions::decodeMac(const std::string& base) {
     mac_template_.clear();
     // Get pieces of MAC address separated with : (or even ::)
     while (std::getline(s1, token, ':')) {
-        unsigned int ui = 0;
         // Convert token to byte value using std::istringstream
         if (token.length() > 0) {
+            unsigned int ui = 0;
             try {
                 // Do actual conversion
                 ui = convertHexString(token);
@@ -620,6 +682,12 @@ CommandOptions::validate() const {
           "-6 (IPv6) must be set to use -c");
     check((getExchangeMode() == DO_SA) && (getNumRequests().size() > 1),
           "second -n<num-request> is not compatible with -i");
+    check((getIpVersion() == 4) && !getLeaseType().is(LeaseType::ADDRESS),
+          "-6 option must be used if lease type other than '-e address-only'"
+          " is specified");
+    check(!getTemplateFiles().empty() &&
+          !getLeaseType().is(LeaseType::ADDRESS),
+          "template files may be only used with '-e address-only'");
     check((getExchangeMode() == DO_SA) && (getDropTime()[1] != 1.),
           "second -d<drop-time> is not compatible with -i");
     check((getExchangeMode() == DO_SA) &&
@@ -706,6 +774,12 @@ CommandOptions::nonEmptyString(const std::string& errmsg) const {
 }
 
 void
+CommandOptions::initLeaseType() {
+    std::string lease_type_arg = optarg;
+    lease_type_.fromCommandLine(lease_type_arg);
+}
+
+void
 CommandOptions::printCommandLine() const {
     std::cout << "IPv" << static_cast<int>(ipversion_) << std::endl;
     if (exchange_mode_ == DO_SA) {
@@ -715,6 +789,7 @@ CommandOptions::printCommandLine() const {
             std::cout << "SOLICIT-ADVERETISE only" << std::endl;
         }
     }
+    std::cout << "lease-type=" << getLeaseType().toText() << std::endl;
     if (rate_ != 0) {
         std::cout << "rate[1/s]=" << rate_ <<  std::endl;
     }
@@ -800,13 +875,13 @@ CommandOptions::printCommandLine() const {
 void
 CommandOptions::usage() const {
     std::cout <<
-        "perfdhcp [-hv] [-4|-6] [-r<rate>] [-t<report>] [-R<range>] [-b<base>]\n"
-        "    [-n<num-request>] [-p<test-period>] [-d<drop-time>] [-D<max-drop>]\n"
-        "    [-l<local-addr|interface>] [-P<preload>] [-a<aggressivity>]\n"
-        "    [-L<local-port>] [-s<seed>] [-i] [-B] [-c] [-1]\n"
-        "    [-T<template-file>] [-X<xid-offset>] [-O<random-offset]\n"
-        "    [-E<time-offset>] [-S<srvid-offset>] [-I<ip-offset>]\n"
-        "    [-x<diagnostic-selector>] [-w<wrapped>] [server]\n"
+        "perfdhcp [-hv] [-4|-6] [-e<lease-type>] [-r<rate>] [-t<report>]\n"
+        "    [-R<range>] [-b<base>] [-n<num-request>] [-p<test-period>]\n"
+        "    [-d<drop-time>] [-D<max-drop>] [-l<local-addr|interface>]\n"
+        "    [-P<preload>] [-a<aggressivity>] [-L<local-port>] [-s<seed>]\n"
+        "    [-i] [-B] [-c] [-1] [-T<template-file>] [-X<xid-offset>]\n"
+        "    [-O<random-offset] [-E<time-offset>] [-S<srvid-offset>]\n"
+        "    [-I<ip-offset>] [-x<diagnostic-selector>] [-w<wrapped>] [server]\n"
         "\n"
         "The [server] argument is the name/address of the DHCP server to\n"
         "contact.  For DHCPv4 operation, exchanges are initiated by\n"
@@ -838,6 +913,14 @@ CommandOptions::usage() const {
         "-d<drop-time>: Specify the time after which a requeqst is treated as\n"
         "    having been lost.  The value is given in seconds and may contain a\n"
         "    fractional component.  The default is 1 second.\n"
+        "-e<lease-type>: A type of lease being requested from the server. It\n"
+        "    may be one of the following: address-only, prefix-only or\n"
+        "    address-and-prefix. The address-only indicates that the regular\n"
+        "    address (v4 or v6) will be requested. The prefix-only indicates\n"
+        "    that the IPv6 prefix will be requested. The address-and-prefix\n"
+        "    indicates that both IPv6 address and prefix will be requested.\n"
+        "    The '-e prefix-only' and -'e address-and-prefix' must not be\n"
+        "    used with -4.\n"
         "-E<time-offset>: Offset of the (DHCPv4) secs field / (DHCPv6)\n"
         "    elapsed-time option in the (second/request) template.\n"
         "    The value 0 disables it.\n"
diff --git a/tests/tools/perfdhcp/command_options.h b/tests/tools/perfdhcp/command_options.h
index 246fea3..7431057 100644
--- a/tests/tools/perfdhcp/command_options.h
+++ b/tests/tools/perfdhcp/command_options.h
@@ -1,3 +1,4 @@
+
 // Copyright (C) 2012-2013 Internet Systems Consortium, Inc. ("ISC")
 //
 // Permission to use, copy, modify, and/or distribute this software for any
@@ -30,6 +31,79 @@ namespace perfdhcp {
 ///
 class CommandOptions : public boost::noncopyable {
 public:
+
+    /// \brief A class encapsulating the type of lease being requested from the
+    /// server.
+    ///
+    /// This class comprises convenience functions to convert the lease type
+    /// to the textual format and to match the appropriate lease type with the
+    /// value of the -e<lease-type> parameter specified from the command line.
+    class LeaseType {
+    public:
+
+        /// The lease type code.
+        enum Type {
+            ADDRESS,
+            PREFIX,
+            ADDRESS_AND_PREFIX
+        };
+
+        LeaseType();
+
+        /// \brief Constructor from lease type code.
+        ///
+        /// \param lease_type A lease type code.
+        LeaseType(const Type lease_type);
+
+        /// \brief Checks if lease type has the specified code.
+        ///
+        /// \param lease_type A lease type code to be checked.
+        ///
+        /// \return true if lease type is matched with the specified code.
+        bool is(const Type lease_type) const;
+
+        /// \brief Checks if lease type implies request for the address,
+        /// prefix (or both) as specified by the function argument.
+        ///
+        /// This is a convenience function to check that, for the lease type
+        /// specified from the command line, the address or prefix
+        /// (IA_NA or IA_PD) option should be sent to the server.
+        /// For example, if user specified '-e address-and-prefix' in the
+        /// command line this function will return true for both ADDRESS
+        /// and PREFIX, because both address and prefix is requested from
+        /// the server.
+        ///
+        /// \param lease_type A lease type.
+        ///
+        /// \return true if the lease type implies creation of the address,
+        /// prefix or both as specified by the argument.
+        bool includes(const Type lease_type) const;
+
+        /// \brief Sets the lease type code.
+        ///
+        /// \param lease_type A lease type code.
+        void set(const Type lease_type);
+
+        /// \brief Sets the lease type from the command line argument.
+        ///
+        /// \param cmd_line_arg An argument specified in the command line
+        /// as -e<lease-type>:
+        /// - address-only
+        /// - prefix-only
+        ///
+        /// \throw isc::InvalidParameter if the specified argument is invalid.
+        void fromCommandLine(const std::string& cmd_line_arg);
+
+        /// \brief Return textual representation of the lease type.
+        ///
+        /// \return A textual representation of the lease type.
+        std::string toText() const;
+
+    private:
+        Type type_; ///< A lease type code.
+
+    };
+
     /// 2-way (cmd line param -i) or 4-way exchanges
     enum ExchangeMode {
         DO_SA,
@@ -71,6 +145,11 @@ public:
     /// \return packet exchange mode.
     ExchangeMode getExchangeMode() const { return exchange_mode_; }
 
+    /// \ brief Returns the type of lease being requested.
+    ///
+    /// \return type of lease being requested by perfdhcp.
+    LeaseType getLeaseType() const { return (lease_type_); }
+
     /// \brief Returns echange rate.
     ///
     /// \return exchange rate per second.
@@ -300,6 +379,11 @@ private:
     /// \throw InvalidParameter if string is empty.
     std::string nonEmptyString(const std::string& errmsg) const;
 
+    /// \brief Decodes the lease type requested by perfdhcp from optarg.
+    ///
+    /// \throw InvalidParameter if lease type value specified is invalid.
+    void initLeaseType();
+
     /// \brief Set number of clients.
     ///
     /// Interprets the getopt() "opt" global variable as the number of clients
@@ -373,6 +457,8 @@ private:
     uint8_t ipversion_;
     /// Packet exchange mode (e.g. DORA/SARR)
     ExchangeMode exchange_mode_;
+    /// Lease Type to be obtained: address only, IPv6 prefix only.
+    LeaseType lease_type_;
     /// Rate in exchange per second
     int rate_;
     /// Delay between generation of two consecutive
@@ -396,7 +482,7 @@ private:
     /// Indicates number of -d<value> parameters specified by user.
     /// If this value goes above 2, command line parsing fails.
     uint8_t drop_time_set_;
-    /// Time to elapse before request is lost. The fisrt value of
+    /// Time to elapse before request is lost. The first value of
     /// two-element vector refers to DO/SA exchanges,
     /// second value refers to RA/RR. Default values are { 1, 1 }
     std::vector<double> drop_time_;
@@ -433,12 +519,12 @@ private:
     /// Indicates that we take server id from first received packet.
     bool use_first_;
     /// Packet template file names. These files store template packets
-    /// that are used for initiating echanges. Template packets
+    /// that are used for initiating exchanges. Template packets
     /// read from files are later tuned with variable data.
     std::vector<std::string> template_file_;
     /// Offset of transaction id in template files. First vector
     /// element points to offset for DISCOVER/SOLICIT messages,
-    /// second element points to trasaction id offset for
+    /// second element points to transaction id offset for
     /// REQUEST messages
     std::vector<int> xid_offset_;
     /// Random value offset in templates. Random value offset
diff --git a/tests/tools/perfdhcp/stats_mgr.h b/tests/tools/perfdhcp/stats_mgr.h
index a8b5d98..d614ad0 100644
--- a/tests/tools/perfdhcp/stats_mgr.h
+++ b/tests/tools/perfdhcp/stats_mgr.h
@@ -260,6 +260,7 @@ public:
         /// assumed dropped. Negative value disables it.
         /// \param archive_enabled if true packets archive mode is enabled.
         /// In this mode all packets are stored throughout the test execution.
+        /// \param boot_time Holds the timestamp when perfdhcp has been started.
         ExchangeStats(const ExchangeType xchg_type,
                       const double drop_time,
                       const bool archive_enabled,
@@ -1183,7 +1184,7 @@ public:
     /// \throw isc::InvalidOperation if no exchange type added to
     /// track statistics.
      void printStats() const {
-        if (exchanges_.size() == 0) {
+        if (exchanges_.empty()) {
             isc_throw(isc::InvalidOperation,
                       "no exchange type added for tracking");
         }
@@ -1238,7 +1239,7 @@ public:
     /// \throw isc::InvalidOperation if no exchange type added to
     /// track statistics or packets archive mode is disabled.
     void printTimestamps() const {
-        if (exchanges_.size() == 0) {
+        if (exchanges_.empty()) {
             isc_throw(isc::InvalidOperation,
                       "no exchange type added for tracking");
         }
@@ -1261,7 +1262,7 @@ public:
     ///
     /// \throw isc::InvalidOperation if no custom counters added for tracking.
     void printCustomCounters() const {
-        if (custom_counters_.size() == 0) {
+        if (custom_counters_.empty()) {
             isc_throw(isc::InvalidOperation, "no custom counters specified");
         }
         for (CustomCountersMapIterator it = custom_counters_.begin();
diff --git a/tests/tools/perfdhcp/test_control.cc b/tests/tools/perfdhcp/test_control.cc
index 925e9b6..a126d51 100644
--- a/tests/tools/perfdhcp/test_control.cc
+++ b/tests/tools/perfdhcp/test_control.cc
@@ -1,4 +1,4 @@
-// Copyright (C) 2012 Internet Systems Consortium, Inc. ("ISC")
+// Copyright (C) 2012-2013 Internet Systems Consortium, Inc. ("ISC")
 //
 // Permission to use, copy, modify, and/or distribute this software for any
 // purpose with or without fee is hereby granted, provided that the above
@@ -97,6 +97,36 @@ TestControl::TestControl() {
     reset();
 }
 
+void
+TestControl::copyIaOptions(const Pkt6Ptr& pkt_from, Pkt6Ptr& pkt_to) {
+    if (!pkt_from || !pkt_to) {
+        isc_throw(BadValue, "NULL pointers must not be specified as arguments"
+                  " for the copyIaOptions function");
+    }
+    // IA_NA
+    if (CommandOptions::instance().getLeaseType()
+        .includes(CommandOptions::LeaseType::ADDRESS)) {
+        OptionPtr option = pkt_from->getOption(D6O_IA_NA);
+        if (!option) {
+            isc_throw(OptionNotFound, "IA_NA option not found in the"
+                      " server's response");
+        }
+        pkt_to->addOption(option);
+    }
+    // IA_PD
+    if (CommandOptions::instance().getLeaseType()
+        .includes(CommandOptions::LeaseType::PREFIX)) {
+        OptionPtr option = pkt_from->getOption(D6O_IA_PD);
+        if (!option) {
+            isc_throw(OptionNotFound, "IA_PD option not found in the"
+                      " server's response");
+        }
+        pkt_to->addOption(option);
+    }
+
+
+}
+
 std::string
 TestControl::byte2Hex(const uint8_t b) const {
     const int b1 = b / 16;
@@ -290,6 +320,22 @@ TestControl::factoryIana6(Option::Universe, uint16_t,
 }
 
 OptionPtr
+TestControl::factoryIapd6(Option::Universe, uint16_t,
+                          const OptionBuffer& buf) {
+    // @todo allow different values of T1, T2 and IAID.
+    static const uint8_t buf_array[] = {
+        0, 0, 0, 1,                     // IAID = 1
+        0, 0, 3600 >> 8, 3600 & 0xff,   // T1 = 3600
+        0, 0, 5400 >> 8, 5400 & 0xff,   // T2 = 5400
+    };
+    OptionBuffer buf_ia_pd(buf_array, buf_array + sizeof(buf_array));
+    // Append sub-options to IA_PD.
+    buf_ia_pd.insert(buf_ia_pd.end(), buf.begin(), buf.end());
+    return (OptionPtr(new Option(Option::V6, D6O_IA_PD, buf_ia_pd)));
+}
+
+
+OptionPtr
 TestControl::factoryRapidCommit6(Option::Universe, uint16_t,
                                  const OptionBuffer&) {
     return (OptionPtr(new Option(Option::V6, D6O_RAPID_COMMIT, OptionBuffer())));
@@ -412,11 +458,11 @@ TestControl::getElapsedTime(const T& pkt1, const T& pkt2) {
 uint64_t
 TestControl::getNextExchangesNum() const {
     CommandOptions& options = CommandOptions::instance();
-    // Reset number of exchanges.
-    uint64_t due_exchanges = 0;
     // Get current time.
     ptime now(microsec_clock::universal_time());
     if (now >= send_due_) {
+        // Reset number of exchanges.
+        uint64_t due_exchanges = 0;
         // If rate is specified from the command line we have to
         // synchornize with it.
         if (options.getRate() != 0) {
@@ -594,15 +640,15 @@ TestControl::openSocket() const {
     uint16_t port = options.getLocalPort();
     int sock = 0;
 
-    uint8_t family = (options.getIpVersion() == 6) ? AF_INET6 : AF_INET; 
+    uint8_t family = (options.getIpVersion() == 6) ? AF_INET6 : AF_INET;
     IOAddress remoteaddr(servername);
-    
+
     // Check for mismatch between IP option and server address
     if (family != remoteaddr.getFamily()) {
-        isc_throw(InvalidParameter, 
-                  "Values for IP version: " <<  
+        isc_throw(InvalidParameter,
+                  "Values for IP version: " <<
                   static_cast<unsigned int>(options.getIpVersion()) <<
-                  " and server address: " << servername << " are mismatched."); 
+                  " and server address: " << servername << " are mismatched.");
     }
 
     if (port == 0) {
@@ -691,7 +737,7 @@ TestControl::sendPackets(const TestControlSocket& socket,
         if (options.getIpVersion() == 4) {
             // No template packets means that no -T option was specified.
             // We have to build packets ourselfs.
-            if (template_buffers_.size() == 0) {
+            if (template_buffers_.empty()) {
                 sendDiscover4(socket, preload);
             } else {
                 // @todo add defines for packet type index that can be
@@ -701,7 +747,7 @@ TestControl::sendPackets(const TestControlSocket& socket,
         } else {
             // No template packets means that no -T option was specified.
             // We have to build packets ourselfs.
-            if (template_buffers_.size() == 0) {
+            if (template_buffers_.empty()) {
                 sendSolicit6(socket, preload);
             } else {
                 // @todo add defines for packet type index that can be
@@ -920,7 +966,7 @@ TestControl::readPacketTemplate(const std::string& file_name) {
     // Expect even number of digits.
     if (hex_digits.size() % 2 != 0) {
         isc_throw(OutOfRange, "odd number of digits in template file");
-    } else if (hex_digits.size() == 0) {
+    } else if (hex_digits.empty()) {
         isc_throw(OutOfRange, "template file " << file_name << " is empty");
     }
     std::vector<uint8_t> binary_stream;
@@ -1079,6 +1125,11 @@ TestControl::registerOptionFactories6() const {
                                        D6O_IA_NA,
                                        &TestControl::factoryIana6);
 
+        // D6O_IA_PD option factory.
+        LibDHCP::OptionFactoryRegister(Option::V6,
+                                       D6O_IA_PD,
+                                       &TestControl::factoryIapd6);
+
 
     }
     factories_registered = true;
@@ -1577,13 +1628,13 @@ TestControl::sendRequest6(const TestControlSocket& socket,
         }
         pkt6->addOption(opt_serverid);
     }
-    // Set IA_NA option.
-    OptionPtr opt_ia_na = advertise_pkt6->getOption(D6O_IA_NA);
-    if (!opt_ia_na) {
-        isc_throw(Unexpected, "DHCPv6 IA_NA option not found in received "
-                  "packet");
-    }
-    pkt6->addOption(opt_ia_na);
+
+    // Copy IA_NA or IA_PD option from the Advertise message to the Request
+    // message being sent to the server. This will throw exception if the
+    // option to be copied is not found. Note that this function will copy
+    // one of IA_NA or IA_PD options, depending on the lease-type value
+    // specified in the command line.
+    copyIaOptions(advertise_pkt6, pkt6);
 
     // Set default packet data.
     setDefaults6(socket, pkt6);
@@ -1732,7 +1783,20 @@ TestControl::sendSolicit6(const TestControlSocket& socket,
     }
     pkt6->addOption(Option::factory(Option::V6, D6O_CLIENTID, duid));
     pkt6->addOption(Option::factory(Option::V6, D6O_ORO));
-    pkt6->addOption(Option::factory(Option::V6, D6O_IA_NA));
+
+    // Depending on the lease-type option specified, we should request
+    // IPv6 address (with IA_NA) or IPv6 prefix (IA_PD) or both.
+
+    // IA_NA
+    if (CommandOptions::instance().getLeaseType()
+        .includes(CommandOptions::LeaseType::ADDRESS)) {
+        pkt6->addOption(Option::factory(Option::V6, D6O_IA_NA));
+    }
+    // IA_PD
+    if (CommandOptions::instance().getLeaseType()
+        .includes(CommandOptions::LeaseType::PREFIX)) {
+        pkt6->addOption(Option::factory(Option::V6, D6O_IA_PD));
+    }
 
     setDefaults6(socket, pkt6);
     pkt6->pack();
diff --git a/tests/tools/perfdhcp/test_control.h b/tests/tools/perfdhcp/test_control.h
index 3983fa6..93509e6 100644
--- a/tests/tools/perfdhcp/test_control.h
+++ b/tests/tools/perfdhcp/test_control.h
@@ -1,4 +1,4 @@
-// Copyright (C) 2012 Internet Systems Consortium, Inc. ("ISC")
+// Copyright (C) 2012-2013 Internet Systems Consortium, Inc. ("ISC")
 //
 // Permission to use, copy, modify, and/or distribute this software for any
 // purpose with or without fee is hereby granted, provided that the above
@@ -55,6 +55,13 @@ static const size_t DHCPV6_SERVERID_OFFSET = 22;
 /// Default DHCPV6 IA_NA offset in the packet template.
 static const size_t DHCPV6_IA_NA_OFFSET = 40;
 
+/// @brief Exception thrown when the required option is not found in a packet.
+class OptionNotFound : public Exception {
+public:
+    OptionNotFound(const char* file, size_t line, const char* what) :
+        isc::Exception(file, line, what) { };
+};
+
 /// \brief Test Control class.
 ///
 /// This singleton class is used to run the performance test with
@@ -160,7 +167,7 @@ public:
         /// \param socket socket descriptor.
         TestControlSocket(const int socket);
 
-        /// \brief Destriuctor of the socket wrapper class.
+        /// \brief Destructor of the socket wrapper class.
         ///
         /// Destructor closes wrapped socket.
         ~TestControlSocket();
@@ -197,7 +204,7 @@ public:
     /// The default generator pointer.
     typedef boost::shared_ptr<NumberGenerator> NumberGeneratorPtr;
 
-    /// \brief Sequential numbers generatorc class.
+    /// \brief Sequential numbers generator class.
     class SequentialGenerator : public NumberGenerator {
     public:
         /// \brief Constructor.
@@ -213,7 +220,7 @@ public:
             }
         }
 
-        /// \brief Generate number sequentialy.
+        /// \brief Generate number sequentially.
         ///
         /// \return generated number.
         virtual uint32_t generate() {
@@ -241,7 +248,7 @@ public:
     /// brief\ Run performance test.
     ///
     /// Method runs whole performance test. Command line options must
-    /// be parsed prior to running this function. Othewise function will
+    /// be parsed prior to running this function. Otherwise function will
     /// throw exception.
     ///
     /// \throw isc::InvalidOperation if command line options are not parsed.
@@ -280,7 +287,7 @@ protected:
     /// only via \ref instance method.
     TestControl();
 
-    /// \brief Check if test exit condtitions fulfilled.
+    /// \brief Check if test exit conditions fulfilled.
     ///
     /// Method checks if the test exit conditions are fulfilled.
     /// Exit conditions are checked periodically from the
@@ -338,6 +345,17 @@ protected:
                                         uint16_t type,
                                         const dhcp::OptionBuffer& buf);
 
+    /// \brief Factory function to create IA_PD option.
+    ///
+    /// this factory function creates DHCPv6 IA_PD option instance.
+    ///
+    /// \param u universe (ignored).
+    /// \param type option-type (ignored).
+    /// \param buf option-buffer carrying sub-options.
+    static dhcp::OptionPtr factoryIapd6(dhcp::Option::Universe u,
+                                        uint16_t type,
+                                        const dhcp::OptionBuffer& buf);
+
     /// \brief Factory function to create DHCPv6 ORO option.
     ///
     /// This factory function creates DHCPv6 Option Request Option instance.
@@ -371,7 +389,7 @@ protected:
 
     /// \brief Factory function to create DHCPv4 Request List option.
     ///
-    /// This factory function creayes DHCPv4 PARAMETER_REQUEST_LIST option
+    /// This factory function creates DHCPv4 PARAMETER_REQUEST_LIST option
     /// instance with the following set of requested options:
     /// - DHO_SUBNET_MASK,
     /// - DHO_BROADCAST_ADDRESS,
@@ -527,7 +545,7 @@ protected:
     /// \brief Process received DHCPv6 packet.
     ///
     /// Method performs processing of the received DHCPv6 packet,
-    /// updates statistics and responsds to the server if required,
+    /// updates statistics and responds to the server if required,
     /// e.g. when ADVERTISE packet arrives, this function will initiate
     /// REQUEST message to the server.
     ///
@@ -578,7 +596,7 @@ protected:
     /// \brief Register option factory functions for DHCPv4 or DHCPv6.
     ///
     /// Method registers option factory functions for DHCPv4 or DHCPv6,
-    /// depending in whch mode test is currently running.
+    /// depending in which mode test is currently running.
     void registerOptionFactories() const;
 
 
@@ -612,7 +630,7 @@ protected:
     /// type and keeps them around until test finishes. Then they
     /// are printed to the user. If packet of specified type has
     /// been already stored this function perfroms no operation.
-    /// This function does not perform sainty check if packet
+    /// This function does not perform sanity check if packet
     /// pointer is valid. Make sure it is before calling it.
     ///
     /// \param pkt packet to be stored.
@@ -834,6 +852,24 @@ protected:
 
 private:
 
+    /// \brief Copies IA_NA or IA_PD option from one packet to another.
+    ///
+    /// This function checks the lease-type specified in the command line
+    /// with option -e<lease-type>. If 'address-only' value has been specified
+    /// this function expects that IA_NA option is present in the packet
+    /// encapsulated by pkt_from object. If 'prefix-only' value has been
+    /// specified, this function expects that IA_PD option is present in the
+    /// packet encapsulated by pkt_to object.
+    ///
+    /// \param [in] pkt_from A packet from which options should be copied.
+    /// \param [out] pkt_to A packet to which options should be copied.
+    ///
+    /// \throw isc::perfdhcp::OptionNotFound if a required option is not
+    /// found in the packet from which options should be copied.
+    /// \throw isc::BadValue if any of the specified pointers to packets
+    /// is NULL.
+    void copyIaOptions(const dhcp::Pkt6Ptr& pkt_from, dhcp::Pkt6Ptr& pkt_to);
+
     /// \brief Convert binary value to hex string.
     ///
     /// \todo Consider moving this function to src/lib/util.
diff --git a/tests/tools/perfdhcp/tests/command_options_helper.h b/tests/tools/perfdhcp/tests/command_options_helper.h
index 253fe12..dbb5c42 100644
--- a/tests/tools/perfdhcp/tests/command_options_helper.h
+++ b/tests/tools/perfdhcp/tests/command_options_helper.h
@@ -115,7 +115,7 @@ private:
         // Tokenize string (space is a separator) using begin and end iteratos
         std::vector<std::string> tokens(text_iterator, text_end);
 
-        if (tokens.size() > 0) {
+        if (!tokens.empty()) {
             // Allocate array of C-strings where we will store tokens
             results = new char*[tokens.size()];
             // Store tokens in C-strings array
diff --git a/tests/tools/perfdhcp/tests/command_options_unittest.cc b/tests/tools/perfdhcp/tests/command_options_unittest.cc
index 7a109fb..d323782 100644
--- a/tests/tools/perfdhcp/tests/command_options_unittest.cc
+++ b/tests/tools/perfdhcp/tests/command_options_unittest.cc
@@ -1,4 +1,4 @@
-// Copyright (C) 2012 Internet Systems Consortium, Inc. ("ISC")
+// Copyright (C) 2012-2013 Internet Systems Consortium, Inc. ("ISC")
 //
 // Permission to use, copy, modify, and/or distribute this software for any
 // purpose with or without fee is hereby granted, provided that the above
@@ -28,6 +28,112 @@ using namespace isc;
 using namespace isc::perfdhcp;
 using namespace boost::posix_time;
 
+// Verify that default constructor sets lease type to the expected value.
+TEST(LeaseTypeTest, defaultConstructor) {
+    CommandOptions::LeaseType lease_type;
+    EXPECT_TRUE(lease_type.is(CommandOptions::LeaseType::ADDRESS));
+}
+
+// Verify that the constructor sets the lease type to the specified value.
+TEST(LeaseTypeTest, constructor) {
+    CommandOptions::LeaseType
+        lease_type1(CommandOptions::LeaseType::ADDRESS);
+    EXPECT_TRUE(lease_type1.is(CommandOptions::LeaseType::ADDRESS));
+
+    CommandOptions::LeaseType
+        lease_type2(CommandOptions::LeaseType::PREFIX);
+    EXPECT_TRUE(lease_type2.is(CommandOptions::LeaseType::PREFIX));
+}
+
+// Verify that the lease type can be modified using set() function.
+TEST(LeaseTypeTest, set) {
+    CommandOptions::LeaseType
+        lease_type(CommandOptions::LeaseType::ADDRESS);
+    EXPECT_TRUE(lease_type.is(CommandOptions::LeaseType::ADDRESS));
+
+    lease_type.set(CommandOptions::LeaseType::PREFIX);
+    EXPECT_TRUE(lease_type.is(CommandOptions::LeaseType::PREFIX));
+}
+
+// Verify that the includes() function returns true when the lease type
+// specified with the function argument is the same as the lease type
+// encapsulated by the LeaseType object on which include function is called
+// or when the lease type value encapsulated by this object is
+// ADDRESS_AND_PREFIX.
+TEST(LeaseTypeTest, includes) {
+    // Lease type: ADDRESS
+    CommandOptions::LeaseType lease_type(CommandOptions::LeaseType::ADDRESS);
+    // Lease type IS ADDRESS.
+    ASSERT_TRUE(lease_type.is(CommandOptions::LeaseType::ADDRESS));
+    // Lease type includes the ADDRESS.
+    EXPECT_TRUE(lease_type.includes(CommandOptions::LeaseType::ADDRESS));
+    // Lease type does not include PREFIX.
+    EXPECT_FALSE(lease_type.includes(CommandOptions::LeaseType::PREFIX));
+    // Lease type does not include ADDRESS_AND_PREFIX.
+    EXPECT_FALSE(
+        lease_type.includes(CommandOptions::LeaseType::ADDRESS_AND_PREFIX)
+    );
+
+    // Do the same check for PREFIX.
+    lease_type.set(CommandOptions::LeaseType::PREFIX);
+    EXPECT_FALSE(lease_type.includes(CommandOptions::LeaseType::ADDRESS));
+    EXPECT_TRUE(lease_type.includes(CommandOptions::LeaseType::PREFIX));
+    EXPECT_FALSE(
+        lease_type.includes(CommandOptions::LeaseType::ADDRESS_AND_PREFIX)
+    );
+
+    // When lease type is set to 'address-and-prefix' it means that client
+    // requests both address and prefix (IA_NA and IA_PD). Therefore, the
+    // LeaseType::includes() function should return true for both ADDRESS
+    // and PREFIX.
+    lease_type.set(CommandOptions::LeaseType::ADDRESS_AND_PREFIX);
+    EXPECT_TRUE(lease_type.includes(CommandOptions::LeaseType::ADDRESS));
+    EXPECT_TRUE(lease_type.includes(CommandOptions::LeaseType::PREFIX));
+    EXPECT_TRUE(
+        lease_type.includes(CommandOptions::LeaseType::ADDRESS_AND_PREFIX)
+    );
+
+}
+
+// Verify that the LeaseType::fromCommandLine() function parses the lease-type
+// argument specified as -e<lease-type>.
+TEST(LeaseTypeTest, fromCommandLine) {
+    CommandOptions::LeaseType
+        lease_type(CommandOptions::LeaseType::ADDRESS);
+    ASSERT_TRUE(lease_type.is(CommandOptions::LeaseType::ADDRESS));
+
+    lease_type.fromCommandLine("prefix-only");
+    ASSERT_TRUE(lease_type.is(CommandOptions::LeaseType::PREFIX));
+
+    lease_type.fromCommandLine("address-only");
+    EXPECT_TRUE(lease_type.is(CommandOptions::LeaseType::ADDRESS));
+
+    lease_type.fromCommandLine("address-and-prefix");
+    EXPECT_TRUE(lease_type.is(CommandOptions::LeaseType::ADDRESS_AND_PREFIX));
+
+    EXPECT_THROW(lease_type.fromCommandLine("bogus-parameter"),
+                 isc::InvalidParameter);
+
+}
+
+// Verify that the LeaseType::toText() function returns the textual
+// representation of the lease type specified.
+TEST(LeaseTypeTest, toText) {
+    CommandOptions::LeaseType lease_type;
+    ASSERT_TRUE(lease_type.is(CommandOptions::LeaseType::ADDRESS));
+    EXPECT_EQ("address-only (IA_NA option added to the client's request)",
+              lease_type.toText());
+
+    lease_type.set(CommandOptions::LeaseType::PREFIX);
+    EXPECT_EQ("prefix-only (IA_PD option added to the client's request)",
+              lease_type.toText());
+
+    lease_type.set(CommandOptions::LeaseType::ADDRESS_AND_PREFIX);
+    EXPECT_EQ("address-and-prefix (Both IA_NA and IA_PD options added to the"
+              " client's request)", lease_type.toText());
+
+}
+
 /// \brief Test Fixture Class
 ///
 /// This test fixture class is used to perform
@@ -60,6 +166,7 @@ protected:
         EXPECT_NO_THROW(process("perfdhcp 192.168.0.1"));
         EXPECT_EQ(4, opt.getIpVersion());
         EXPECT_EQ(CommandOptions::DORA_SARR, opt.getExchangeMode());
+        EXPECT_TRUE(opt.getLeaseType().is(CommandOptions::LeaseType::ADDRESS));
         EXPECT_EQ(0, opt.getRate());
         EXPECT_EQ(0, opt.getReportDelay());
         EXPECT_EQ(0, opt.getClientsNum());
@@ -181,6 +288,32 @@ TEST_F(CommandOptionsTest, IpVersion) {
     EXPECT_THROW(process("perfdhcp -c -l ethx all"), isc::InvalidParameter);
 }
 
+TEST_F(CommandOptionsTest, LeaseType) {
+    CommandOptions& opt = CommandOptions::instance();
+    // Check that the -e address-only works for IPv6.
+    ASSERT_NO_THROW(process("perfdhcp -6 -l etx -e address-only all"));
+    EXPECT_EQ(6, opt.getIpVersion());
+    EXPECT_EQ("etx", opt.getLocalName());
+    EXPECT_TRUE(opt.getLeaseType().is(CommandOptions::LeaseType::ADDRESS));
+    // Check that the -e address-only works for IPv4.
+    ASSERT_NO_THROW(process("perfdhcp -4 -l etx -e address-only all"));
+    EXPECT_EQ(4, opt.getIpVersion());
+    EXPECT_EQ("etx", opt.getLocalName());
+    EXPECT_TRUE(opt.getLeaseType().is(CommandOptions::LeaseType::ADDRESS));
+    // Check that the -e prefix-only works.
+    ASSERT_NO_THROW(process("perfdhcp -6 -l etx -e prefix-only all"));
+    EXPECT_EQ(6, opt.getIpVersion());
+    EXPECT_EQ("etx", opt.getLocalName());
+    EXPECT_TRUE(opt.getLeaseType().is(CommandOptions::LeaseType::PREFIX));
+    // Check that -e prefix-only must not coexist with -4 option.
+    EXPECT_THROW(process("perfdhcp -4 -l ethx -e prefix-only all"),
+                 InvalidParameter);
+    // Check that -e prefix-only must not coexist with -T options.
+    EXPECT_THROW(process("perfdhcp -6 -l ethx -e prefix-only -T file1.hex"
+                         " -T file2.hex -E 4 all"), InvalidParameter);
+
+}
+
 TEST_F(CommandOptionsTest, Rate) {
     CommandOptions& opt = CommandOptions::instance();
     EXPECT_NO_THROW(process("perfdhcp -4 -r 10 -l ethx all"));
diff --git a/tests/tools/perfdhcp/tests/stats_mgr_unittest.cc b/tests/tools/perfdhcp/tests/stats_mgr_unittest.cc
index ebb4f34..41aac82 100644
--- a/tests/tools/perfdhcp/tests/stats_mgr_unittest.cc
+++ b/tests/tools/perfdhcp/tests/stats_mgr_unittest.cc
@@ -81,6 +81,10 @@ public:
     ///
     /// Method simulates sending or receiving  multiple DHCPv6 packets.
     ///
+    /// \note The xchg_type parameter is passed as non-const value to avoid
+    /// false cppcheck errors which expect enum value being passed by reference.
+    /// This error is not reported when non-const enum is passed by value.
+    ///
     /// \param stats_mgr Statistics Manager instance to be used.
     /// \param xchg_type packet exchange types.
     /// \param packet_type DHCPv6 packet type.
@@ -88,7 +92,7 @@ public:
     /// \param receive simulated packets are received (if true)
     /// or sent (if false)
     void passMultiplePackets6(const boost::shared_ptr<StatsMgr6> stats_mgr,
-                              const StatsMgr6::ExchangeType xchg_type,
+                              StatsMgr6::ExchangeType xchg_type,
                               const uint8_t packet_type,
                               const int num_packets,
                               const bool receive = false) {
@@ -347,7 +351,6 @@ TEST_F(StatsMgrTest, Delays) {
 
     // Send DISCOVER, wait 2s and receive OFFER. This will affect
     // counters in Stats Manager.
-    const unsigned int delay1 = 2;
     passDOPacketsWithDelay(stats_mgr, 2, common_transid);
 
     // Initially min delay is equal to MAX_DOUBLE. After first packets
diff --git a/tests/tools/perfdhcp/tests/test_control_unittest.cc b/tests/tools/perfdhcp/tests/test_control_unittest.cc
index 6aff71c..c0b7231 100644
--- a/tests/tools/perfdhcp/tests/test_control_unittest.cc
+++ b/tests/tools/perfdhcp/tests/test_control_unittest.cc
@@ -40,7 +40,7 @@ using namespace isc::perfdhcp;
 class NakedTestControl: public TestControl {
 public:
 
-    /// \brief Incremental transaction id generaator.
+    /// \brief Incremental transaction id generator.
     ///
     /// This is incremental transaction id generator. It overrides
     /// the default transaction id generator that generates transaction
@@ -123,7 +123,7 @@ public:
     /// truncated.
     ///
     /// \param filename template file to be created.
-    /// \param buffer with binary datato be stored in file.
+    /// \param buffer with binary data to be stored in file.
     /// \param size target size of the file.
     /// \param invalid_chars inject invalid chars to the template file.
     /// \return true if file creation successful.
@@ -283,7 +283,7 @@ public:
 
     /// brief Test generation of mulitple DUIDs
     ///
-    /// Thie method checks the generation of multiple DUIDs. Number
+    /// This method checks the generation of multiple DUIDs. Number
     /// of iterations depends on the number of simulated clients.
     /// It is expected that DUID's size is 14 (consists of DUID-LLT
     /// HW type field, 4 octets of time value and MAC address). The
@@ -497,7 +497,7 @@ public:
 
         // Incremental transaction id generator will generate
         // predictable values of transaction id for each iteration.
-        // This is important because we need to simulate reponses
+        // This is important because we need to simulate responses
         // from the server and use the same transaction ids as in
         // packets sent by client.
         TestControl::NumberGeneratorPtr
@@ -521,7 +521,8 @@ public:
                 boost::shared_ptr<Pkt6>
                     advertise_pkt6(createAdvertisePkt6(transid));
                 // Receive ADVERTISE and send REQUEST.
-                ASSERT_NO_THROW(tc.processReceivedPacket6(sock, advertise_pkt6));
+                ASSERT_NO_THROW(tc.processReceivedPacket6(sock,
+                                                          advertise_pkt6));
                 ++transid;
             }
             if (tc.checkExitConditions()) {
@@ -646,14 +647,24 @@ private:
     /// \return instance of the packet.
     boost::shared_ptr<Pkt6>
     createAdvertisePkt6(uint32_t transid) const {
-        OptionPtr opt_ia_na = Option::factory(Option::V6, D6O_IA_NA);
+        boost::shared_ptr<Pkt6> advertise(new Pkt6(DHCPV6_ADVERTISE, transid));
+        // Add IA_NA if requested by the client.
+        if (CommandOptions::instance().getLeaseType()
+            .includes(CommandOptions::LeaseType::ADDRESS)) {
+            OptionPtr opt_ia_na = Option::factory(Option::V6, D6O_IA_NA);
+            advertise->addOption(opt_ia_na);
+        }
+        // Add IA_PD if requested by the client.
+        if (CommandOptions::instance().getLeaseType()
+            .includes(CommandOptions::LeaseType::PREFIX)) {
+            OptionPtr opt_ia_pd = Option::factory(Option::V6, D6O_IA_PD);
+            advertise->addOption(opt_ia_pd);
+        }
         OptionPtr opt_serverid(new Option(Option::V6, D6O_SERVERID));
         NakedTestControl tc;
         uint8_t randomized = 0;
         std::vector<uint8_t> duid(tc.generateDuid(randomized));
         OptionPtr opt_clientid(Option::factory(Option::V6, D6O_CLIENTID, duid));
-        boost::shared_ptr<Pkt6> advertise(new Pkt6(DHCPV6_ADVERTISE, transid));
-        advertise->addOption(opt_ia_na);
         advertise->addOption(opt_serverid);
         advertise->addOption(opt_clientid);
         advertise->updateTimestamp();
@@ -737,7 +748,7 @@ TEST_F(TestControlTest, Options4) {
 
     // Get the option buffer. It should hold the combination of values
     // listed in requested_options array. However their order can be
-    // different in general so we need to search each value separatelly.
+    // different in general so we need to search each value separately.
     const OptionBuffer& requested_options_buf =
         opt_requested_options->getData();
     EXPECT_EQ(requested_options_ref.size(), requested_options_buf.size());
@@ -963,7 +974,7 @@ TEST_F(TestControlTest, Packet4Exchange) {
     EXPECT_EQ(12, iterations_performed);
 }
 
-TEST_F(TestControlTest, Packet6Exchange) {
+TEST_F(TestControlTest, Packet6ExchangeFromTemplate) {
     // Get the local loopback interface to open socket on
     // it and test packets exchanges. We don't want to fail
     // the test if interface is not available.
@@ -998,11 +1009,128 @@ TEST_F(TestControlTest, Packet6Exchange) {
     // then test should be interrupted and actual number of iterations will
     // be 6.
     const int received_num = 3;
+    // Simulate the number of Solicit-Advertise-Request-Reply (SARR) echanges.
+    // The test function generates server's responses and passes it to the
+    // TestControl class methods for processing. The number of exchanges
+    // actually performed is returned in 'iterations_performed' argument. If
+    // processing is successful, the number of performed iterations should be
+    // equal to the number of exchanges specified with the '-n' command line
+    // parameter (10 in this case). All exchanged packets carry the IA_NA option
+    // to simulate the IPv6 address acquisition and to verify that the
+    // IA_NA options returned by the server are processed correctly.
     testPkt6Exchange(iterations_num, received_num, use_templates,
                      iterations_performed);
     EXPECT_EQ(6, iterations_performed);
 }
 
+TEST_F(TestControlTest, Packet6Exchange) {
+    // Get the local loopback interface to open socket on
+    // it and test packets exchanges. We don't want to fail
+    // the test if interface is not available.
+    std::string loopback_iface(getLocalLoopback());
+    if (loopback_iface.empty()) {
+        std::cout << "Unable to find the loopback interface. Skip test."
+                  << std::endl;
+        return;
+    }
+
+    const int iterations_num = 100;
+    // Set number of iterations to 10.
+    processCmdLine("perfdhcp -l " + loopback_iface
+                   + " -e address-only"
+                   + " -6 -r 100 -n 10 -R 20 -L 10547 ::1");
+    int iterations_performed = 0;
+    // Set number of received packets equal to number of iterations.
+    // This simulates no packet drops.
+    bool use_templates = false;
+
+    // Simulate the number of Solicit-Advertise-Request-Reply (SARR) echanges.
+    // The test function generates server's responses and passes it to the
+    // TestControl class methods for processing. The number of exchanges
+    // actually performed is returned in 'iterations_performed' argument. If
+    // processing is successful, the number of performed iterations should be
+    // equal to the number of exchanges specified with the '-n' command line
+    // parameter (10 in this case). All exchanged packets carry the IA_NA option
+    // to simulate the IPv6 address acqusition and to verify that the IA_NA
+    // options returned by the server are processed correctly.
+    testPkt6Exchange(iterations_num, iterations_num, use_templates,
+                     iterations_performed);
+    // Actual number of iterations should be 10.
+    EXPECT_EQ(10, iterations_performed);
+}
+
+TEST_F(TestControlTest, Packet6ExchangePrefixDelegation) {
+    // Get the local loopback interface to open socket on
+    // it and test packets exchanges. We don't want to fail
+    // the test if interface is not available.
+    std::string loopback_iface(getLocalLoopback());
+    if (loopback_iface.empty()) {
+        std::cout << "Unable to find the loopback interface. Skip test."
+                  << std::endl;
+        return;
+    }
+
+    const int iterations_num = 100;
+    // Set number of iterations to 10.
+    processCmdLine("perfdhcp -l " + loopback_iface
+                   + " -e prefix-only"
+                   + " -6 -r 100 -n 10 -R 20 -L 10547 ::1");
+    int iterations_performed = 0;
+    // Set number of received packets equal to number of iterations.
+    // This simulates no packet drops.
+    bool use_templates = false;
+
+    // Simulate the number of Solicit-Advertise-Request-Reply (SARR) echanges.
+    // The test function generates server's responses and passes it to the
+    // TestControl class methods for processing. The number of exchanges
+    // actually performed is returned in 'iterations_performed' argument. If
+    // processing is successful, the number of performed iterations should be
+    // equal to the number of exchanges specified with the '-n' command line
+    // parameter (10 in this case). All exchanged packets carry the IA_PD option
+    // to simulate the Prefix Delegation and to verify that the IA_PD options
+    // returned by the server are processed correctly.
+    testPkt6Exchange(iterations_num, iterations_num, use_templates,
+                     iterations_performed);
+    // Actual number of iterations should be 10.
+    EXPECT_EQ(10, iterations_performed);
+}
+
+TEST_F(TestControlTest, Packet6ExchangeAddressAndPrefix) {
+    // Get the local loopback interface to open socket on
+    // it and test packets exchanges. We don't want to fail
+    // the test if interface is not available.
+    std::string loopback_iface(getLocalLoopback());
+    if (loopback_iface.empty()) {
+        std::cout << "Unable to find the loopback interface. Skip test."
+                  << std::endl;
+        return;
+    }
+
+    const int iterations_num = 100;
+    // Set number of iterations to 10.
+    processCmdLine("perfdhcp -l " + loopback_iface
+                   + " -e address-and-prefix"
+                   + " -6 -r 100 -n 10 -R 20 -L 10547 ::1");
+    int iterations_performed = 0;
+    // Set number of received packets equal to number of iterations.
+    // This simulates no packet drops.
+    bool use_templates = false;
+    // Simulate the number of Solicit-Advertise-Request-Reply (SARR) echanges.
+    // The test function generates server's responses and passes it to the
+    // TestControl class methods for processing. The number of exchanges
+    // actually performed is returned in 'iterations_performed' argument. If
+    // processing is successful, the number of performed iterations should be
+    // equal to the number of exchanges specified with the '-n' command line
+    // parameter (10 in this case).  All exchanged packets carry either IA_NA
+    // or IA_PD options to simulate the address and prefix acquisition with
+    // the single message and to verify that the IA_NA and IA_PD options
+    // returned by the server are processed correctly.
+    testPkt6Exchange(iterations_num, iterations_num, use_templates,
+                     iterations_performed);
+    // Actual number of iterations should be 10.
+    EXPECT_EQ(10, iterations_performed);
+}
+
 TEST_F(TestControlTest, PacketTemplates) {
     std::vector<uint8_t> template1(256);
     std::string file1("test1.hex");
@@ -1017,7 +1145,7 @@ TEST_F(TestControlTest, PacketTemplates) {
     // Size of the file is 2 times larger than binary data size.
     ASSERT_TRUE(createTemplateFile(file1, template1, template1.size() * 2));
     ASSERT_TRUE(createTemplateFile(file2, template2, template2.size() * 2));
-    CommandOptions& options = CommandOptions::instance();
+
     NakedTestControl tc;
 
     ASSERT_NO_THROW(



More information about the bind10-changes mailing list