- Updates to the unit tests.
- Improved commentary in unit tests.
- Renamed methods and updated commentary in command_options.h/cc
- Hold the number of relay encapsulations configured with -A.
- Updated perfdhcp man page.
mac_template_.assign(mac, mac + 6);
duid_template_.clear();
base_.clear();
- mac_file_list_.clear();
+ mac_list_file_.clear();
mac_list_.clear();
num_request_.clear();
period_ = 0;
broadcast_ = false;
rapid_commit_ = false;
use_first_ = false;
- use_relayed_v6_ = false;
template_file_.clear();
rnd_offset_.clear();
xid_offset_.clear();
diags_.clear();
wrapped_.clear();
server_name_.clear();
+ v6_relay_encapsulation_level_ = 0;
generateDuidTemplate();
}
use_first_ = true;
break;
- // act as a relay Agent (single char option and R/r are taken already).
+ // Simulate DHCPv6 relayed traffic.
case 'A':
- use_relayed_v6_ = true;
- // TODO: actually use level, at the moment we support only 1 level.
+ // @todo: At the moment we only support simulating a single relay
+ // agent. In the future we should extend it to up to 32.
// See comment in https://github.com/isc-projects/kea/pull/22#issuecomment-243405600
- int level;
- level = positiveInteger(
- " -A<encapusulation_levels> must be a positive integer");
- if (level != 1) {
- isc_throw(isc::InvalidParameter, "-A only supports 1 at the moment.");
+ v6_relay_encapsulation_level_ =
+ static_cast<uint8_t>(positiveInteger("-A<encapusulation-level> must"
+ " be a positive integer"));
+ if (v6_relay_encapsulation_level_ != 1) {
+ isc_throw(isc::InvalidParameter, "-A only supports 1 at the moment.");
}
break;
case 'M':
check(num_mac_list_files >= 1, "only -M option can be specified");
num_mac_list_files++;
- mac_file_list_ = std::string(optarg);
+ mac_list_file_ = std::string(optarg);
loadMacs();
break;
void CommandOptions::loadMacs() {
std::string line;
- std::ifstream infile(mac_file_list_.c_str());
+ std::ifstream infile(mac_list_file_.c_str());
while (std::getline(infile, line)) {
check(decodeMacString(line), "invalid mac in input");
}
if (use_first_) {
std::cout << "use-first" << std::endl;
}
- if (!mac_file_list_.empty()) {
- std::cout << "mac-file-list=" << mac_file_list_ << std::endl;
+ if (!mac_list_file_.empty()) {
+ std::cout << "mac-list-file=" << mac_list_file_ << std::endl;
}
for (size_t i = 0; i < template_file_.size(); ++i) {
std::cout << "template-file[" << i << "]=" << template_file_[i] << std::endl;
void
CommandOptions::usage() const {
std::cout <<
- "perfdhcp [-hv] [-4|-6] [-A<encapusulation_levels>] [-e<lease-type>]"
+ "perfdhcp [-hv] [-4|-6] [-A<encapusulation-level>] [-e<lease-type>]"
" [-r<rate>] [-f<renew-rate>]\n"
" [-F<release-rate>] [-t<report>] [-R<range>] [-b<base>]\n"
" [-n<num-request>] [-p<test-period>] [-d<drop-time>]\n"
" [-D<max-drop>] [-l<local-addr|interface>] [-P<preload>]\n"
" [-a<aggressivity>] [-L<local-port>] [-s<seed>] [-i] [-B]\n"
- " [-c] [-1] [-M<mac_list_file>] [-T<template-file>]\n"
+ " [-c] [-1] [-M<mac-list-file>] [-T<template-file>]\n"
" [-X<xid-offset>] [-O<random-offset] [-E<time-offset>]\n"
" [-S<srvid-offset>] [-I<ip-offset>] [-x<diagnostic-selector>]\n"
" [-w<wrapped>] [server]\n"
" via which exchanges are initiated.\n"
"-L<local-port>: Specify the local port to use\n"
" (the value 0 means to use the default).\n"
- "-M<mac-file-list>: A text file containing a list of macs, one per line.\n"
- " If provided a random mac will be choosen for every exchange.\n"
- " Must not be used in conjunction with the -b parameter.\n"
- " In the v6 case MAC addresses are used to generate DUID-LLs.\n"
+ "-M<mac-list-file>: A text file containing a list of MAC addresses,\n"
+ " one per line. If provided, a MAC address will be choosen randomly\n"
+ " from this list for every new exchange. In the DHCPv6 case, MAC\n"
+ " addresses are used to generate DUID-LLs. This parameter must not be\n"
+ " used in conjunction with the -b parameter.\n"
"-O<random-offset>: Offset of the last octet to randomize in the template.\n"
"-P<preload>: Initiate first <preload> exchanges back to back at startup.\n"
"-r<rate>: Initiate <rate> DORA/SARR (or if -i is given, DO/SA)\n"
" the exchange rate (given by -r<rate>). Furthermore the sum of\n"
" this value and the renew-rate (given by -f<rate) must be equal\n"
" to or less than the exchange rate.\n"
- "-A<encapusulation_levels>: When acting in DHCPv6 mode, send out relay packets.\n"
- " <encapusulation_levels> specifies how many relays forwarded this message\n"
+ "-A<encapusulation-level>: Specifies that relayed traffic must be\n"
+ " generated. The argument specifies the level of encapsulation, i.e.\n"
+ " how many relay agents are simulated. Currently the only supported\n"
+ " <encapsulation-level> value is 1, which means that the generated\n"
+ " traffic is an equivalent of the traffic passing through a single\n"
+ " relay agent.\n"
"\n"
"The remaining options are used only in conjunction with -r:\n"
"\n"
class CommandOptions : public boost::noncopyable {
public:
+ /// @brief A vector holding MAC addresses.
+ typedef std::vector<std::vector<uint8_t> > MacAddrsVector;
+
/// \brief A class encapsulating the type of lease being requested from the
/// server.
///
/// \brief Check if generated DHCPv6 messages shuold appear as relayed.
///
/// \return true if generated traffic should appear as relayed.
- bool isUseRelayedV6() const { return use_relayed_v6_; }
+ bool isUseRelayedV6() const { return (v6_relay_encapsulation_level_ > 0); }
/// \brief Returns template file names.
///
/// \return template file names.
std::vector<std::string> getTemplateFiles() const { return template_file_; }
- /// \brief Returns location of the file containing list of MAC addresses
+ /// \brief Returns location of the file containing list of MAC addresses.
///
/// MAC addresses read from the file are used by the perfdhcp in message
/// exchanges with the DHCP server.
///
- /// \return mac_template file name.
- std::string getMacListFile() const { return mac_file_list_; }
+ /// \return Location of the file containing list of MAC addresses.
+ std::string getMacListFile() const { return mac_list_file_; }
- /// \brief Returns the list of macs, every mac is a vector<uint8_t>
+ /// \brief Returns reference to a vector of MAC addresses read from a file.
+ ///
+ /// Every MAC address is represented as a vector.
///
- /// \return mac_list_ vector of vectors.
- const std::vector<std::vector<uint8_t> >& getAllMacs() const { return mac_list_; }
+ /// \return Reference to a vector of vectors.
+ const MacAddrsVector& getMacsFromFile() const { return mac_list_; }
/// brief Returns template offsets for xid.
///
/// that are used for initiating exchanges. Template packets
/// read from files are later tuned with variable data.
std::vector<std::string> template_file_;
- /// A file containing a list of macs, one per line. This can be used if
- /// you don't want to genrate Mac starting from a base mac but rather provide
- /// the tool with a list of macs it should randomize on.
- std::string mac_file_list_;
+ /// Location of a file containing a list of MAC addresses, one per line.
+ /// This can be used if you don't want to generate MAC address from a
+ /// base MAC address, but rather provide the file with a list of MAC
+ /// addresses to be randomly picked. Note that in DHCPv6 those MAC
+ /// addresses will be used to generate DUID-LL.
+ std::string mac_list_file_;
+ /// List of MAC addresses loaded from a file.
std::vector<std::vector<uint8_t> > mac_list_;
/// Offset of transaction id in template files. First vector
/// element points to offset for DISCOVER/SOLICIT messages,
std::string wrapped_;
/// Server name specified as last argument of command line.
std::string server_name_;
- /// Controls whether generated dhcpv6 test traffic should be relayed.
- bool use_relayed_v6_;
+ /// Indicates how many DHCPv6 relay agents are simulated.
+ uint8_t v6_relay_encapsulation_level_;
};
} // namespace perfdhcp
<refentry>
<refentryinfo>
- <date>February 19, 2014</date>
+ <date>August 31, 2016</date>
</refentryinfo>
<refmeta>
<docinfo>
<copyright>
- <year>2014</year>
+ <year>2016</year>
<holder>Internet Systems Consortium, Inc. ("ISC")</holder>
</copyright>
</docinfo>
<command>perfdhcp</command>
<arg><option>-1</option></arg>
<arg><option>-4|-6</option></arg>
- <arg><option>-A</option></arg>
+ <arg><option>-A <replaceable class="parameter">encapsulation-level</replaceable></option></arg>
<arg><option>-a <replaceable class="parameter">aggressivity</replaceable></option></arg>
<arg><option>-b <replaceable class="parameter">base</replaceable></option></arg>
<arg><option>-B</option></arg>
<arg><option>-I <replaceable class="parameter">ip-offset</replaceable></option></arg>
<arg><option>-l <replaceable class="parameter">local-address|interface</replaceable></option></arg>
<arg><option>-L <replaceable class="parameter">local-port</replaceable></option></arg>
+ <arg><option>-M <replaceable class="parameter">mac-list-file</replaceable></option></arg>
<arg><option>-n <replaceable class="parameter">num-request</replaceable></option></arg>
<arg><option>-O <replaceable class="parameter">random-offset</replaceable></option></arg>
<arg><option>-p <replaceable class="parameter">test-period</replaceable></option></arg>
</listitem>
</varlistentry>
- <varlistentry>
- <term><option>-A</option></term>
- <listitem>
- <para>
- When acting as a DHCPv6 behave like a relay Agent.
- Send out packets as if they were relayed from an agent.
- </para>
- </listitem>
- </varlistentry>
-
<varlistentry>
<term><option>-a <replaceable class="parameter">aggressivity</replaceable></option></term>
<listitem>
</listitem>
</varlistentry>
+ <varlistentry>
+ <term><option>-M <replaceable class="parameter">mac-list-file</replaceable></option></term>
+ <listitem>
+ <para>
+ A text file containing a list of MAC addresses,
+ one per line. If provided, a MAC address will be choosen randomly
+ from this list for every new exchange. In the DHCPv6 case, MAC
+ addresses are used to generate DUID-LLs. This parameter must not be
+ used in conjunction with the -b parameter.
+ </para>
+ </listitem>
+ </varlistentry>
+
<varlistentry>
<term><option>-P <replaceable class="parameter">preload</replaceable></option></term>
<listitem>
</listitem>
</varlistentry>
+ <varlistentry>
+ <term><option>-A <replaceable class="parameter">encapsulation-level</replaceable></option></term>
+ <listitem>
+ <para>
+ Specifies that relayed traffic must be
+ generated. The argument specifies the level of encapsulation, i.e.
+ how many relay agents are simulated. Currently the only supported
+ <replaceable class="parameter">encapsulation-level</replaceable>
+ value is 1, which means that the generated traffic is an equivalent
+ of the traffic passing through a single relay agent.
+ </para>
+ </listitem>
+ </varlistentry>
+
</variablelist>
</refsect2>
}
TestControl::TestControl()
- : number_generator_(0, CommandOptions::instance().getAllMacs().size()) {
+ : number_generator_(0, CommandOptions::instance().getMacsFromFile().size()) {
reset();
}
TestControl::generateMacAddress(uint8_t& randomized) {
CommandOptions& options = CommandOptions::instance();
- vector<vector<uint8_t> > macs = options.getAllMacs();
+ const CommandOptions::MacAddrsVector& macs = options.getMacsFromFile();
// if we are using the -M option return a random one from the list...
if (macs.size() > 0) {
uint16_t r = number_generator_();
TestControl::generateDuid(uint8_t& randomized) {
CommandOptions& options = CommandOptions::instance();
std::vector<uint8_t> mac_addr(generateMacAddress(randomized));
- vector<vector<uint8_t> > macs = options.getAllMacs();
+ const CommandOptions::MacAddrsVector& macs = options.getMacsFromFile();
// pick a random mac address if we are using option -M..
if (macs.size() > 0) {
uint16_t r = number_generator_();
TEST_F(CommandOptionsTest, LoadMacsFromFile) {
CommandOptions &opt = CommandOptions::instance();
- std::string mac_list_full_path = getFullPath("mac_list.txt");
+ std::string mac_list_full_path = getFullPath("mac-list.txt");
std::ostringstream cmd;
cmd << "perfdhcp -M " << mac_list_full_path << " abc";
EXPECT_NO_THROW(process(cmd.str()));
EXPECT_EQ(mac_list_full_path, opt.getMacListFile());
- std::vector<std::vector<uint8_t> > m = opt.getAllMacs();
+ const CommandOptions::MacAddrsVector& m = opt.getMacsFromFile();
EXPECT_EQ(4, m.size());
}
#include <boost/date_time/posix_time/posix_time.hpp>
#include <boost/foreach.hpp>
+#include <algorithm>
#include <cstddef>
#include <stdint.h>
#include <string>
testDuid();
// Checks that the random mac address returned by generateDuid
- // is in the list of mac addresses in the mac_list.txt data file
- std::string mac_list_full_path = getFullPath("mac_list.txt");
+ // is in the list of mac addresses in the mac-list.txt data file
+ std::string mac_list_full_path = getFullPath("mac-list.txt");
std::ostringstream cmd;
cmd << "perfdhcp -M " << mac_list_full_path << " abc";
ASSERT_NO_THROW(processCmdLine(cmd.str()));
NakedTestControl tc;
uint8_t randomized = 0;
std::vector<uint8_t> generated_duid = tc.generateDuid(randomized);
- // check that generated_duid is DUID_LL
+
+ // Check that generated_duid is DUID_LL
+ ASSERT_EQ(10, generated_duid.size());
DuidPtr duid(new DUID(generated_duid));
ASSERT_EQ(duid->getType(), DUID::DUID_LL);
- // make sure it's on the list
+
+ // Make sure it's on the list
CommandOptions& options = CommandOptions::instance();
- vector<vector<uint8_t> > macs = options.getAllMacs();
- // duid_ll is made of 2 bytes of duid type, 2 bytes of hardwaretype,
- // then 6 bytes of mac
+ const CommandOptions::MacAddrsVector& macs = options.getMacsFromFile();
+ // DUID LL comprises 2 bytes of duid type, 2 bytes of hardware type,
+ // then 6 bytes of HW address.
vector<uint8_t> mac(6);
- std::copy(
- generated_duid.begin() + 4, generated_duid.begin() + 10, mac.begin());
- // check that mac is in macs
- ASSERT_TRUE(
- std::find(macs.begin(), macs.end(), mac) !=
- macs.end()
- );
+ std::copy(generated_duid.begin() + 4, generated_duid.begin() + 10,
+ mac.begin());
+ // Check that mac is in macs.
+ ASSERT_TRUE(std::find(macs.begin(), macs.end(), mac) != macs.end());
}
TEST_F(TestControlTest, MisMatchVerionServer) {
testMacAddress();
// Checks that the random mac address returned by generateMacAddress
- // is in the list of mac addresses in the mac_list.txt data file
- std::string mac_list_full_path = getFullPath("mac_list.txt");
+ // is in the list of mac addresses in the mac-list.txt data file
+ std::string mac_list_full_path = getFullPath("mac-list.txt");
std::ostringstream cmd;
cmd << "perfdhcp -M " << mac_list_full_path << " abc";
ASSERT_NO_THROW(processCmdLine(cmd.str()));
// Initialize Test Controller.
NakedTestControl tc;
uint8_t randomized = 0;
+ // Generate MAC adddress and sanity check its size.
std::vector<uint8_t> mac = tc.generateMacAddress(randomized);
+ ASSERT_EQ(6, mac.size());
+ // Make sure that the generated MAC address belongs to the MAC addresses
+ // read from a file.
CommandOptions& options = CommandOptions::instance();
- vector<vector<uint8_t> > macs = options.getAllMacs();
- // check that mac is in macs
- ASSERT_NE(std::find(macs.begin(), macs.end(), mac), macs.end());
+ const CommandOptions::MacAddrsVector& macs = options.getMacsFromFile();
+ ASSERT_TRUE(std::find(macs.begin(), macs.end(), mac) != macs.end());
}
TEST_F(TestControlTest, Options4) {
EXPECT_EQ(DHCP6_SERVER_PORT, pkt6->getRemotePort());
EXPECT_EQ(sock.addr_, pkt6->getLocalAddr());
EXPECT_EQ(asiolink::IOAddress("FF05::1:3"), pkt6->getRemoteAddr());
+ // Packet must not be relayed.
+ EXPECT_TRUE(pkt6->relay_info_.empty());
+
} else {
std::cout << "Unable to find the loopback interface. Skip test. "
<< std::endl;
EXPECT_EQ(DHCP6_SERVER_PORT, pkt6->getRemotePort());
EXPECT_EQ(sock.addr_, pkt6->getLocalAddr());
EXPECT_EQ(asiolink::IOAddress("FF05::1:3"), pkt6->getRemoteAddr());
- // check relay info
+ // Packet should be relayed.
EXPECT_EQ(pkt6->relay_info_.size(), 1);
EXPECT_EQ(pkt6->relay_info_[0].hop_count_, 1);
EXPECT_EQ(pkt6->relay_info_[0].msg_type_, DHCPV6_RELAY_FORW);
EXTRA_DIST = discover-example.hex request4-example.hex
EXTRA_DIST += solicit-example.hex request6-example.hex
-EXTRA_DIST += mac_list.txt
+EXTRA_DIST += mac-list.txt