2
0
mirror of https://gitlab.isc.org/isc-projects/kea synced 2025-08-31 14:05:33 +00:00

[master] Merge branch 'trac4254'

This commit is contained in:
Marcin Siodelski
2016-02-08 15:57:54 +01:00
9 changed files with 490 additions and 133 deletions

View File

@@ -1,4 +1,4 @@
// Copyright (C) 2012-2015 Internet Systems Consortium, Inc. ("ISC")
// Copyright (C) 2012-2016 Internet Systems Consortium, Inc. ("ISC")
//
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
@@ -691,8 +691,6 @@ CommandOptions::validate() const {
"-B is not compatible with IPv6 (-6)");
check((getIpVersion() != 6) && (isRapidCommit() != 0),
"-6 (IPv6) must be set to use -c");
check((getIpVersion() != 6) && (getRenewRate() !=0),
"-f<renew-rate> may be used with -6 (IPv6) only");
check((getIpVersion() != 6) && (getReleaseRate() != 0),
"-F<release-rate> may be used with -6 (IPv6) only");
check((getExchangeMode() == DO_SA) && (getNumRequests().size() > 1),
@@ -963,6 +961,11 @@ CommandOptions::usage() const {
"-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"
"-f<renew-rate>: Rate at which DHCPv4 or DHCPv6 renew requests are sent\n"
" to a server. This value is only valid when used in conjunction\n"
" with the exchange rate (given by -r<rate>). Furthermore the sum of\n"
" this value and the release-rate (given by -F<rate) must be equal\n"
" to or less than the exchange rate.\n"
"-h: Print this help.\n"
"-i: Do only the initial part of an exchange: DO or SA, depending on\n"
" whether -6 is given.\n"
@@ -1010,11 +1013,6 @@ CommandOptions::usage() const {
"\n"
"DHCPv6 only options:\n"
"-c: Add a rapid commit option (exchanges will be SA).\n"
"-f<renew-rate>: Rate at which IPv6 Renew requests are sent to\n"
" a server. This value is only valid when used in conjunction with\n"
" the exchange rate (given by -r<rate>). Furthermore the sum of\n"
" this value and the release-rate (given by -F<rate) must be equal\n"
" to or less than the exchange rate.\n"
"-F<release-rate>: Rate at which IPv6 Release requests are sent to\n"
" a server. This value is only valid when used in conjunction with\n"
" the exchange rate (given by -r<rate>). Furthermore the sum of\n"

View File

@@ -318,6 +318,23 @@
</listitem>
</varlistentry>
<varlistentry>
<term><option>-f <replaceable class="parameter">renew-rate</replaceable></option></term>
<listitem>
<para>
Rate at which DHCPv4 or DHCPv6 renew requests are sent
to a server. This value is only valid when used in conjunction
with the exchange rate (given by <option>-r <replaceable
class="parameter">rate</replaceable></option>).
Furthermore the sum of this value and the release-rate
(given by <option>-F <replaceable class="parameter">
rate</replaceable></option>) must be equal to or less than
the exchange rate.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term><option>-h</option></term>
<listitem>
@@ -560,23 +577,6 @@
</listitem>
</varlistentry>
<varlistentry>
<term><option>-f <replaceable class="parameter">renew-rate</replaceable></option></term>
<listitem>
<para>
Rate at which IPv6 RENEW requests are sent
to a server. This value is only valid when
used in conjunction with the exchange
rate (given by <option>-r <replaceable
class="parameter">rate</replaceable></option>).
Furthermore the sum of this value and the
release-rate (given by <option>-F <replaceable
class="parameter">rate</replaceable></option>)
must be equal to or less than the exchange rate.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term><option>-F <replaceable class="parameter">release-rate</replaceable></option></term>
<listitem>

View File

@@ -1,4 +1,4 @@
// Copyright (C) 2012-2015 Internet Systems Consortium, Inc. ("ISC")
// Copyright (C) 2012-2016 Internet Systems Consortium, Inc. ("ISC")
//
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
@@ -22,6 +22,7 @@
#include <iostream>
#include <map>
#include <queue>
namespace isc {
@@ -114,6 +115,7 @@ public:
enum ExchangeType {
XCHG_DO, ///< DHCPv4 DISCOVER-OFFER
XCHG_RA, ///< DHCPv4 REQUEST-ACK
XCHG_RNA, ///< DHCPv4 REQUEST-ACK (renewal)
XCHG_SA, ///< DHCPv6 SOLICIT-ADVERTISE
XCHG_RR, ///< DHCPv6 REQUEST-REPLY
XCHG_RN, ///< DHCPv6 RENEW-REPLY
@@ -172,7 +174,7 @@ public:
/// 1023 values maximum. Search operation on this index generally
/// returns the range of packets that have the same transaction id
/// hash assigned but most often these ranges will be short so further
/// search within a range to find a packet with pacrticular transaction
/// search within a range to find a packet with particular transaction
/// id will not be intensive.
///
/// Example 1: Add elements to the list
@@ -188,7 +190,7 @@ public:
/// packets_collection.template get<0>().push_back(pkt2);
/// \endcode
///
/// Example 2: Access elements through sequencial index
/// Example 2: Access elements through sequential index
/// \code
/// PktList packets_collection();
/// ... # Add elements to the container
@@ -241,7 +243,7 @@ public:
>
> PktList;
/// Packet list iterator for sequencial access to elements.
/// Packet list iterator for sequential access to elements.
typedef typename PktList::iterator PktListIterator;
/// Packet list index to search packets using transaction id hash.
typedef typename PktList::template nth_index<1>::type
@@ -249,6 +251,9 @@ public:
/// Packet list iterator to access packets using transaction id hash.
typedef typename PktListTransidHashIndex::const_iterator
PktListTransidHashIterator;
/// Packet list iterator queue for removal.
typedef typename std::queue<PktListTransidHashIterator>
PktListRemovalQueue;
/// \brief Constructor
///
@@ -419,7 +424,7 @@ public:
// take a little more expensive approach to look packets using
// alternative index (transaction id & 1023).
PktListTransidHashIndex& idx = sent_packets_.template get<1>();
// Packets are grouped using trasaction id masked with value
// Packets are grouped using transaction id masked with value
// of 1023. For instance, packets with transaction id equal to
// 1, 1024 ... will belong to the same group (a.k.a. bucket).
// When using alternative index we don't find the packet but
@@ -437,6 +442,8 @@ public:
// bucket size the better. If bucket sizes appear to big we
// might want to increase number of buckets.
unordered_lookup_size_sum_ += std::distance(p.first, p.second);
// Removal can be done only after the loop
PktListRemovalQueue to_remove;
for (PktListTransidHashIterator it = p.first; it != p.second;
++it) {
if ((*it)->getTransid() == rcvd_packet->getTransid()) {
@@ -454,19 +461,30 @@ public:
(static_cast<double>(packet_period.length().fractional_seconds())
/ packet_period.length().ticks_per_second());
if (drop_time_ > 0 && (period_fractional > drop_time_)) {
// The packet pointed to by 'it' is timed out so we
// have to remove it. Removal may invalidate the
// next_sent_ pointer if it points to the packet
// being removed. So, we set the next_sent_ to point
// to the next packet after removed one. This
// pointer will be further updated in the following
// iterations, if the subsequent packets are also
// timed out.
next_sent_ = eraseSent(sent_packets_.template project<0>(it));
++collected_;
// Push the iterator on the removal queue.
to_remove.push(it);
}
}
}
// Deal with the removal queue
while (!to_remove.empty()) {
PktListTransidHashIterator it = to_remove.front();
to_remove.pop();
// The packet pointed to by 'it' is timed out so
// we have to remove it.
if (packet_found || !to_remove.empty()) {
eraseSent(sent_packets_.template project<0>(it));
} else {
// Removal may invalidate the next_sent_
// pointer if it points to the packet being
// removed. So, we set the next_sent_ to point
// to the next packet after removed one.
next_sent_ = eraseSent(sent_packets_.template project<0>(it));
}
++collected_;
}
}
if (!packet_found) {
@@ -487,14 +505,14 @@ public:
return(sent_packet);
}
/// \brief Return minumum delay between sent and received packet.
/// \brief Return minimum delay between sent and received packet.
///
/// Method returns minimum delay between sent and received packet.
///
/// \return minimum delay between packets.
double getMinDelay() const { return(min_delay_); }
/// \brief Return maxmimum delay between sent and received packet.
/// \brief Return maximum delay between sent and received packet.
///
/// Method returns maximum delay between sent and received packet.
///
@@ -535,13 +553,13 @@ public:
getAvgDelay() * getAvgDelay()));
}
/// \brief Return number of orphant packets.
/// \brief Return number of orphan packets.
///
/// Method returns number of received packets that had no matching
/// sent packet. It is possible that such packet was late or not
/// for us.
///
/// \return number of orphant received packets.
/// \return number of orphan received packets.
uint64_t getOrphans() const { return(orphans_); }
/// \brief Return number of garbage collected packets.
@@ -631,7 +649,8 @@ public:
/// orphans for the 4-way exchanges, which is wrong. We will need to
/// move the orphans counting out of the Statistics Manager so as
/// orphans counter is increased only if the particular message is
/// not identified as a reponse to any of the messages sent by perfdhcp.
/// not identified as a response to any of the messages sent by
/// perfdhcp.
void printMainStats() const {
using namespace std;
cout << "sent packets: " << getSentPacketsNum() << endl
@@ -752,7 +771,7 @@ public:
// when test is completed.
archived_packets_.push_back(*it);
}
// get<0>() template returns sequencial index to
// get<0>() template returns sequential index to
// container.
return(sent_packets_.template get<0>().erase(it));
}
@@ -785,7 +804,7 @@ public:
/// to keep all packets archived throughout the test.
bool archive_enabled_;
/// Maxmimum time elapsed between sending and receiving packet
/// Maximum time elapsed between sending and receiving packet
/// before packet is assumed dropped.
double drop_time_;
@@ -796,16 +815,16 @@ public:
double sum_delay_; ///< Sum of delays between sent
///< and received packets.
double sum_delay_squared_; ///< Squared sum of delays between
///< sent and recived packets.
///< sent and received packets.
uint64_t orphans_; ///< Number of orphant received packets.
uint64_t orphans_; ///< Number of orphan received packets.
uint64_t collected_; ///< Number of garbage collected packets.
/// Sum of unordered lookup sets. Needed to calculate mean size of
/// lookup set. It is desired that number of unordered lookups is
/// minimal for performance reasons. Tracking number of lookups and
/// mean size of the lookup set should give idea of packets serach
/// mean size of the lookup set should give idea of packets search
/// complexity.
uint64_t unordered_lookup_size_sum_;
@@ -823,7 +842,7 @@ public:
typedef boost::shared_ptr<ExchangeStats> ExchangeStatsPtr;
/// Map containing all specified exchange types.
typedef typename std::map<ExchangeType, ExchangeStatsPtr> ExchangesMap;
/// Iterator poiting to \ref ExchangesMap
/// Iterator pointing to \ref ExchangesMap
typedef typename ExchangesMap::const_iterator ExchangesMapIterator;
/// Map containing custom counters.
typedef typename std::map<std::string, CustomCounterPtr> CustomCountersMap;
@@ -876,7 +895,7 @@ public:
/// This method checks if the \ref ExchangeStats object of a particular type
/// exists (has been added using \ref addExchangeStats function).
///
/// \param xchg_type A type of the exchange being repersented by the
/// \param xchg_type A type of the exchange being represented by the
/// \ref ExchangeStats object.
///
/// \return true if the \ref ExchangeStats object has been added for a
@@ -902,9 +921,9 @@ public:
CustomCounterPtr(new CustomCounter(long_name));
}
/// \brief Check if any packet drops occured.
/// \brief Check if any packet drops occurred.
///
// \return true, if packet drops occured.
// \return true, if packet drops occurred.
bool droppedPackets() const {
for (ExchangesMapIterator it = exchanges_.begin();
it != exchanges_.end();
@@ -920,7 +939,7 @@ public:
///
/// Method returns specified counter.
///
/// \param counter_key key poiting to the counter in the counters map.
/// \param counter_key key pointing to the counter in the counters map.
/// The short counter name has to be used to access counter.
/// \return pointer to specified counter object.
CustomCounterPtr getCounter(const std::string& counter_key) {
@@ -936,7 +955,7 @@ public:
///
/// Increment counter value by one.
///
/// \param counter_key key poiting to the counter in the counters map.
/// \param counter_key key pointing to the counter in the counters map.
/// \param value value to increment counter by.
/// \return pointer to specified counter after incrementation.
const CustomCounter& incrementCounter(const std::string& counter_key,
@@ -991,7 +1010,7 @@ public:
return(sent_packet);
}
/// \brief Return minumum delay between sent and received packet.
/// \brief Return minimum delay between sent and received packet.
///
/// Method returns minimum delay between sent and received packet
/// for specified exchange type.
@@ -1004,7 +1023,7 @@ public:
return(xchg_stats->getMinDelay());
}
/// \brief Return maxmimum delay between sent and received packet.
/// \brief Return maximum delay between sent and received packet.
///
/// Method returns maximum delay between sent and received packet
/// for specified exchange type.
@@ -1039,14 +1058,14 @@ public:
return(xchg_stats->getStdDevDelay());
}
/// \brief Return number of orphant packets.
/// \brief Return number of orphan packets.
///
/// Method returns number of orphant packets for specified
/// Method returns number of orphan packets for specified
/// exchange type.
///
/// \param xchg_type exchange type.
/// \throw isc::BadValue if invalid exchange type specified.
/// \return number of orphant packets so far.
/// \return number of orphan packets so far.
uint64_t getOrphans(const ExchangeType xchg_type) const {
ExchangeStatsPtr xchg_stats = getExchangeStats(xchg_type);
return(xchg_stats->getOrphans());
@@ -1179,6 +1198,8 @@ public:
return("DISCOVER-OFFER");
case XCHG_RA:
return("REQUEST-ACK");
case XCHG_RNA:
return("REQUEST-ACK (renewal)");
case XCHG_SA:
return("SOLICIT-ADVERTISE");
case XCHG_RR:

View File

@@ -1,4 +1,4 @@
// Copyright (C) 2012-2015 Internet Systems Consortium, Inc. ("ISC")
// Copyright (C) 2012-2016 Internet Systems Consortium, Inc. ("ISC")
//
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
@@ -315,6 +315,22 @@ TestControl::checkExitConditions() const {
return (false);
}
Pkt4Ptr
TestControl::createRequestFromAck(const dhcp::Pkt4Ptr& ack) {
if (!ack) {
isc_throw(isc::BadValue, "Unable to create DHCPREQUEST from a"
" null DHCPACK message");
} else if (ack->getYiaddr().isV4Zero()) {
isc_throw(isc::BadValue, "Unable to create DHCPREQUEST from a"
" DHCPACK message containing yiaddr of 0");
}
Pkt4Ptr msg(new Pkt4(DHCPREQUEST, generateTransid()));
msg->setCiaddr(ack->getYiaddr());
msg->setHWAddr(ack->getHWAddr());
msg->addOption(generateClientId(msg->getHWAddr()));
return (msg);
}
Pkt6Ptr
TestControl::createMessageFromReply(const uint16_t msg_type,
const dhcp::Pkt6Ptr& reply) {
@@ -481,6 +497,15 @@ TestControl::generateMacAddress(uint8_t& randomized) const {
return (mac_addr);
}
OptionPtr
TestControl::generateClientId(const dhcp::HWAddrPtr& hwaddr) const {
std::vector<uint8_t> client_id(1, static_cast<uint8_t>(hwaddr->htype_));
client_id.insert(client_id.end(), hwaddr->hwaddr_.begin(),
hwaddr->hwaddr_.end());
return (OptionPtr(new Option(Option::V4, DHO_DHCP_CLIENT_IDENTIFIER,
client_id)));
}
std::vector<uint8_t>
TestControl::generateDuid(uint8_t& randomized) const {
CommandOptions& options = CommandOptions::instance();
@@ -663,6 +688,9 @@ TestControl::initializeStatsMgr() {
stats_mgr4_->addExchangeStats(StatsMgr4::XCHG_RA,
options.getDropTime()[1]);
}
if (options.getRenewRate() != 0) {
stats_mgr4_->addExchangeStats(StatsMgr4::XCHG_RNA);
}
} else if (options.getIpVersion() == 6) {
stats_mgr6_.reset();
@@ -725,7 +753,7 @@ TestControl::openSocket() const {
// Local name is specified along with '-l' option.
// It may point to interface name or local address.
if (!localname.empty()) {
// CommandOptions should be already aware wether local name
// CommandOptions should be already aware whether local name
// is interface name or address because it uses IfaceMgr to
// scan interfaces and get's their names.
if (options.isInterface()) {
@@ -798,7 +826,7 @@ TestControl::sendPackets(const TestControlSocket& socket,
for (uint64_t i = packets_num; i > 0; --i) {
if (options.getIpVersion() == 4) {
// No template packets means that no -T option was specified.
// We have to build packets ourselfs.
// We have to build packets ourselves.
if (template_buffers_.empty()) {
sendDiscover4(socket, preload);
} else {
@@ -808,7 +836,7 @@ TestControl::sendPackets(const TestControlSocket& socket,
}
} else {
// No template packets means that no -T option was specified.
// We have to build packets ourselfs.
// We have to build packets ourselves.
if (template_buffers_.empty()) {
sendSolicit6(socket, preload);
} else {
@@ -831,6 +859,17 @@ TestControl::sendPackets(const TestControlSocket& socket,
}
}
uint64_t
TestControl::sendMultipleRequests(const TestControlSocket& socket,
const uint64_t msg_num) {
for (uint64_t i = 0; i < msg_num; ++i) {
if (!sendRequestFromAck(socket)) {
return (i);
}
}
return (msg_num);
}
uint64_t
TestControl::sendMultipleMessages6(const TestControlSocket& socket,
const uint32_t msg_type,
@@ -1072,7 +1111,28 @@ TestControl::processReceivedPacket4(const TestControlSocket& socket,
}
}
} else if (pkt4->getType() == DHCPACK) {
stats_mgr4_->passRcvdPacket(StatsMgr4::XCHG_RA, pkt4);
// If received message is DHCPACK, we have to check if this is
// a response to 4-way exchange. We'll match this packet with
// a DHCPREQUEST sent as part of the 4-way exchanges.
if (stats_mgr4_->passRcvdPacket(StatsMgr4::XCHG_RA, pkt4)) {
// The DHCPACK belongs to DHCPREQUEST-DHCPACK exchange type.
// So, we may need to keep this DHCPACK in the storage if renews.
// Note that, DHCPACK messages hold the information about
// leases assigned. We use this information to renew.
if (stats_mgr4_->hasExchangeStats(StatsMgr4::XCHG_RNA)) {
// Renew messages are sent, because StatsMgr has the
// specific exchange type specified. Let's append the DHCPACK.
// message to a storage
ack_storage_.append(pkt4);
}
// The DHCPACK message is not a server's response to the DHCPREQUEST
// message sent within the 4-way exchange. It may be a response to a
// renewal. In this case we first check if StatsMgr has exchange type
// for renew specified, and if it has, if there is a corresponding
// renew message for the received DHCPACK.
} else if (stats_mgr4_->hasExchangeStats(StatsMgr4::XCHG_RNA)) {
stats_mgr4_->passRcvdPacket(StatsMgr4::XCHG_RNA, pkt4);
}
}
}
@@ -1364,12 +1424,17 @@ TestControl::run() {
// If -f<renew-rate> option was specified we have to check how many
// Renew packets should be sent to catch up with a desired rate.
if ((options.getIpVersion() == 6) && (options.getRenewRate() != 0)) {
if (options.getRenewRate() != 0) {
uint64_t renew_packets_due =
renew_rate_control_.getOutboundMessageCount();
checkLateMessages(renew_rate_control_);
// Send Renew messages.
sendMultipleMessages6(socket, DHCPV6_RENEW, renew_packets_due);
// Send multiple renews to satisfy the desired rate.
if (options.getIpVersion() == 4) {
sendMultipleRequests(socket, renew_packets_due);
} else {
sendMultipleMessages6(socket, DHCPV6_RENEW, renew_packets_due);
}
}
// If -F<release-rate> option was specified we have to check how many
@@ -1389,7 +1454,7 @@ TestControl::run() {
}
// If we are sending Renews to the server, the Reply packets are cached
// so as leases for which we send Renews can be idenitfied. The major
// so as leases for which we send Renews can be identified. The major
// issue with this approach is that most of the time we are caching
// more packets than we actually need. This function removes excessive
// Reply messages to reduce the memory and CPU utilization. Note that
@@ -1428,7 +1493,7 @@ TestControl::run() {
}
int ret_code = 0;
// Check if any packet drops occured.
// Check if any packet drops occurred.
if (options.getIpVersion() == 4) {
ret_code = stats_mgr4_->droppedPackets() ? 3 : 0;
} else if (options.getIpVersion() == 6) {
@@ -1479,7 +1544,7 @@ TestControl::sendDiscover4(const TestControlSocket& socket,
// Generate the MAC address to be passed in the packet.
uint8_t randomized = 0;
std::vector<uint8_t> mac_address = generateMacAddress(randomized);
// Generate trasnaction id to be set for the new exchange.
// Generate transaction id to be set for the new exchange.
const uint32_t transid = generateTransid();
Pkt4Ptr pkt4(new Pkt4(DHCPDISCOVER, transid));
if (!pkt4) {
@@ -1504,6 +1569,9 @@ TestControl::sendDiscover4(const TestControlSocket& socket,
// Set hardware address
pkt4->setHWAddr(HTYPE_ETHER, mac_address.size(), mac_address);
// Set client identifier
pkt4->addOption(generateClientId(pkt4->getHWAddr()));
pkt4->pack();
IfaceMgr::instance().send(pkt4);
if (!preload) {
@@ -1521,13 +1589,13 @@ TestControl::sendDiscover4(const TestControlSocket& socket,
const std::vector<uint8_t>& template_buf,
const bool preload /* = false */) {
basic_rate_control_.updateSendTime();
// Get the first argument if mulitple the same arguments specified
// Get the first argument if multiple the same arguments specified
// in the command line. First one refers to DISCOVER packets.
const uint8_t arg_idx = 0;
// Generate the MAC address to be passed in the packet.
uint8_t randomized = 0;
std::vector<uint8_t> mac_address = generateMacAddress(randomized);
// Generate trasnaction id to be set for the new exchange.
// Generate transaction id to be set for the new exchange.
const uint32_t transid = generateTransid();
// Get transaction id offset.
size_t transid_offset = getTransactionIdOffset(arg_idx);
@@ -1568,6 +1636,32 @@ TestControl::sendDiscover4(const TestControlSocket& socket,
saveFirstPacket(pkt4);
}
bool
TestControl::sendRequestFromAck(const TestControlSocket& socket) {
// Update timestamp of last sent renewal.
renew_rate_control_.updateSendTime();
// Get one of the recorded DHCPACK messages.
Pkt4Ptr ack = ack_storage_.getRandom();
if (!ack) {
return (false);
}
// Create message of the specified type.
Pkt4Ptr msg = createRequestFromAck(ack);
setDefaults4(socket, msg);
msg->pack();
// And send it.
IfaceMgr::instance().send(msg);
if (!stats_mgr4_) {
isc_throw(Unexpected, "Statistics Manager for DHCPv4 "
"hasn't been initialized");
}
stats_mgr4_->passSentPacket(StatsMgr4::XCHG_RNA, msg);
return (true);
}
bool
TestControl::sendMessageFromReply(const uint16_t msg_type,
const TestControlSocket& socket) {
@@ -1647,6 +1741,8 @@ TestControl::sendRequest4(const TestControlSocket& socket,
// Set hardware address
pkt4->setHWAddr(offer_pkt4->getHWAddr());
// Set client id.
pkt4->addOption(generateClientId(pkt4->getHWAddr()));
// Set elapsed time.
uint32_t elapsed_time = getElapsedTime<Pkt4Ptr>(discover_pkt4, offer_pkt4);
pkt4->setSecs(static_cast<uint16_t>(elapsed_time / 1000));
@@ -1677,7 +1773,7 @@ TestControl::sendRequest4(const TestControlSocket& socket,
// We need to go back by HW_ETHER_LEN (MAC address length)
// because this offset points to last octet of MAC address.
size_t rand_offset = getRandomOffset(arg_idx) - HW_ETHER_LEN + 1;
// Create temporaru buffer from the template.
// Create temporary buffer from the template.
std::vector<uint8_t> in_buf(template_buf.begin(),
template_buf.end());
// Check if given randomization offset is not out of bounds.
@@ -1946,7 +2042,7 @@ TestControl::sendSolicit6(const TestControlSocket& socket,
// Generate DUID to be passed to the packet
uint8_t randomized = 0;
std::vector<uint8_t> duid = generateDuid(randomized);
// Generate trasnaction id to be set for the new exchange.
// Generate transaction id to be set for the new exchange.
const uint32_t transid = generateTransid();
Pkt6Ptr pkt6(new Pkt6(DHCPV6_SOLICIT, transid));
if (!pkt6) {
@@ -1995,7 +2091,7 @@ TestControl::sendSolicit6(const TestControlSocket& socket,
const int arg_idx = 0;
// Get transaction id offset.
size_t transid_offset = getTransactionIdOffset(arg_idx);
// Generate trasnaction id to be set for the new exchange.
// Generate transaction id to be set for the new exchange.
const uint32_t transid = generateTransid();
// Create packet.
PerfPkt6Ptr pkt6(new PerfPkt6(&template_buf[0], template_buf.size(),
@@ -2005,7 +2101,7 @@ TestControl::sendSolicit6(const TestControlSocket& socket,
}
size_t rand_offset = getRandomOffset(arg_idx);
// randomized will pick number of bytes randomized so we can
// just use part of the generated duid and substitude a few bytes
// just use part of the generated duid and substitute a few bytes
/// in template.
uint8_t randomized = 0;
std::vector<uint8_t> duid = generateDuid(randomized);

View File

@@ -1,4 +1,4 @@
// Copyright (C) 2012-2015 Internet Systems Consortium, Inc. ("ISC")
// Copyright (C) 2012-2016 Internet Systems Consortium, Inc. ("ISC")
//
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
@@ -124,7 +124,7 @@ public:
typedef StatsMgr<dhcp::Pkt4> StatsMgr4;
/// Pointer to Statistics Manager for DHCPv4;
typedef boost::shared_ptr<StatsMgr4> StatsMgr4Ptr;
/// Statictics Manager for DHCPv6.
/// Statistics Manager for DHCPv6.
typedef StatsMgr<dhcp::Pkt6> StatsMgr6;
/// Pointer to Statistics Manager for DHCPv6.
typedef boost::shared_ptr<StatsMgr6> StatsMgr6Ptr;
@@ -246,7 +246,7 @@ public:
/// throw exception.
///
/// \throw isc::InvalidOperation if command line options are not parsed.
/// \throw isc::Unexpected if internal Test Controller error occured.
/// \throw isc::Unexpected if internal Test Controller error occurred.
/// \return error_code, 3 if number of received packets is not equal
/// to number of sent packets, 0 if everything is ok.
int run();
@@ -306,13 +306,21 @@ protected:
/// has been reached.
void cleanCachedPackets();
/// \brief Creates DHCPREQUEST from a DHCPACK message.
///
/// \param ack An instance of the DHCPACK message to be used to
/// create a new message.
///
/// \return Pointer to the created message.
dhcp::Pkt4Ptr createRequestFromAck(const dhcp::Pkt4Ptr& ack);
/// \brief Creates DHCPv6 message from the Reply packet.
///
/// This function creates DHCPv6 Renew or Release message using the
/// data from the Reply message by copying options from the Reply
/// message.
///
/// \param msg_type A type of the message to be createad.
/// \param msg_type A type of the message to be created.
/// \param reply An instance of the Reply packet which contents should
/// be used to create an instance of the new message.
///
@@ -432,6 +440,16 @@ protected:
uint16_t type,
const dhcp::OptionBuffer& buf);
/// \brief Generate DHCPv4 client identifier from HW address.
///
/// This method generates DHCPv4 client identifier option from a
/// HW address.
///
/// \param hwaddr HW address.
///
/// \return Pointer to an instance of the generated option.
dhcp::OptionPtr generateClientId(const dhcp::HWAddrPtr& hwaddr) const;
/// \brief Generate DUID.
///
/// Method generates unique DUID. The number of DUIDs it can generate
@@ -527,7 +545,7 @@ protected:
/// \throw isc::InvalidOperation if broadcast option can't be
/// set for the v4 socket or if multicast option can't be set
/// for the v6 socket.
/// \throw isc::Unexpected if interal unexpected error occured.
/// \throw isc::Unexpected if internal unexpected error occurred.
/// \return socket descriptor.
int openSocket() const;
@@ -562,7 +580,7 @@ protected:
/// \param [in] socket socket to be used.
/// \param [in] pkt4 object representing DHCPv4 packet received.
/// \throw isc::BadValue if unknown message type received.
/// \throw isc::Unexpected if unexpected error occured.
/// \throw isc::Unexpected if unexpected error occurred.
void processReceivedPacket4(const TestControlSocket& socket,
const dhcp::Pkt4Ptr& pkt4);
@@ -579,7 +597,7 @@ protected:
/// \param [in] socket socket to be used.
/// \param [in] pkt6 object representing DHCPv6 packet received.
/// \throw isc::BadValue if unknown message type received.
/// \throw isc::Unexpected if unexpected error occured.
/// \throw isc::Unexpected if unexpected error occurred.
void processReceivedPacket6(const TestControlSocket& socket,
const dhcp::Pkt6Ptr& pkt6);
@@ -595,7 +613,7 @@ protected:
///
/// \param socket socket to be used.
/// \throw isc::BadValue if unknown message type received.
/// \throw isc::Unexpected if unexpected error occured.
/// \throw isc::Unexpected if unexpected error occurred.
/// \return number of received packets.
uint64_t receivePackets(const TestControlSocket& socket);
@@ -726,6 +744,15 @@ protected:
const uint64_t packets_num,
const bool preload = false);
/// \brief Send number of DHCPREQUEST (renew) messages to a server.
///
/// \param socket An object representing socket to be used to send packets.
/// \param msg_num A number of messages to be sent.
///
/// \return A number of messages actually sent.
uint64_t sendMultipleRequests(const TestControlSocket& socket,
const uint64_t msg_num);
/// \brief Send number of DHCPv6 Renew or Release messages to the server.
///
/// \param socket An object representing socket to be used to send packets.
@@ -738,6 +765,14 @@ protected:
const uint32_t msg_type,
const uint64_t msg_num);
/// \brief Send DHCPv4 renew (DHCPREQUEST) using specified socket.
///
/// \param socket An object encapsulating socket to be used to send
/// a packet.
///
/// \return true if the message has been sent, false otherwise.
bool sendRequestFromAck(const TestControlSocket& socket);
/// \brief Send DHCPv6 Renew or Release message using specified socket.
///
/// This method will select an existing lease from the Reply packet cache
@@ -763,7 +798,7 @@ protected:
/// \param discover_pkt4 DISCOVER packet sent.
/// \param offer_pkt4 OFFER packet object.
///
/// \throw isc::Unexpected if unexpected error occured.
/// \throw isc::Unexpected if unexpected error occurred.
/// \throw isc::InvalidOperation if Statistics Manager has not been
/// initialized.
/// \throw isc::dhcp::SocketWriteError if failed to send the packet.
@@ -800,7 +835,7 @@ protected:
///
/// \param socket socket to be used to send message.
/// \param advertise_pkt6 ADVERTISE packet object.
/// \throw isc::Unexpected if unexpected error occured.
/// \throw isc::Unexpected if unexpected error occurred.
/// \throw isc::InvalidOperation if Statistics Manager has not been
/// initialized.
///
@@ -971,7 +1006,7 @@ protected:
/// \brief Return transaction id offset in a packet.
///
/// \param arg_idx command line argument index to be used.
/// If multiple -X parameters specifed it points to the
/// If multiple -X parameters specified it points to the
/// one to be used.
/// \return transaction id offset in packet.
int getTransactionIdOffset(const int arg_idx) const;
@@ -1077,6 +1112,7 @@ protected:
StatsMgr4Ptr stats_mgr4_; ///< Statistics Manager 4.
StatsMgr6Ptr stats_mgr6_; ///< Statistics Manager 6.
PacketStorage<dhcp::Pkt4> ack_storage_; ///< A storage for DHCPACK messages.
PacketStorage<dhcp::Pkt6> reply_storage_; ///< A storage for reply messages.
NumberGeneratorPtr transid_gen_; ///< Transaction id generator.
@@ -1089,7 +1125,7 @@ protected:
TemplateBufferCollection template_buffers_;
/// First packets send. They are used at the end of the test
/// to print packet templates when diagnostics flag T is specifed.
/// to print packet templates when diagnostics flag T is specified.
std::map<uint8_t, dhcp::Pkt4Ptr> template_packets_v4_;
std::map<uint8_t, dhcp::Pkt6Ptr> template_packets_v6_;

View File

@@ -1,4 +1,4 @@
// Copyright (C) 2012-2015 Internet Systems Consortium, Inc. ("ISC")
// Copyright (C) 2012-2016 Internet Systems Consortium, Inc. ("ISC")
//
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
@@ -341,6 +341,9 @@ TEST_F(CommandOptionsTest, RenewRate) {
// that order doesn't matter.
EXPECT_NO_THROW(process("perfdhcp -6 -f 5 -r 10 -l ethx all"));
EXPECT_EQ(5, opt.getRenewRate());
// Renew rate should also be accepted for DHCPv4 case.
EXPECT_NO_THROW(process("perfdhcp -4 -f 5 -r 10 -l ethx all"));
EXPECT_EQ(5, opt.getRenewRate());
// The renew rate should not be greater than the rate.
EXPECT_THROW(process("perfdhcp -6 -r 10 -f 11 -l ethx all"),
isc::InvalidParameter);
@@ -354,10 +357,6 @@ TEST_F(CommandOptionsTest, RenewRate) {
// be accepted.
EXPECT_THROW(process("perfdhcp -6 -f 10 -l ethx all"),
isc::InvalidParameter);
// Currently the -f<renew-rate> can be specified for IPv6 mode
// only.
EXPECT_THROW(process("perfdhcp -4 -r 10 -f 10 -l ethx all"),
isc::InvalidParameter);
// Renew rate should be specified.
EXPECT_THROW(process("perfdhcp -6 -r 10 -f -l ethx all"),
isc::InvalidParameter);
@@ -384,7 +383,7 @@ TEST_F(CommandOptionsTest, ReleaseRate) {
// The release-rate of 0 is invalid.
EXPECT_THROW(process("perfdhcp -6 -r 10 -F 0 -l ethx all"),
isc::InvalidParameter);
// The negative rlease-rate is invalid.
// The negative release-rate is invalid.
EXPECT_THROW(process("perfdhcp -6 -r 10 -F -5 -l ethx all"),
isc::InvalidParameter);
// If -r<rate> is not specified the -F<release-rate> should not
@@ -634,7 +633,7 @@ TEST_F(CommandOptionsTest, Seed) {
EXPECT_EQ(0, opt.getSeed());
EXPECT_FALSE(opt.isSeeded());
// Negtaive test cases
// Negative test cases
// Seed must be non-negative integer
EXPECT_THROW(process("perfdhcp -6 -P 2 -s -5 -l ethx all"),
isc::InvalidParameter);
@@ -768,7 +767,7 @@ TEST_F(CommandOptionsTest, Interface) {
// at least one interface name on OS where test is run.
// Interface Manager has ability to detect interfaces.
// Although we don't call initIsInterface explicitly
// here it is called by CommandOptions object interally
// here it is called by CommandOptions object internally
// so this function is covered by the test.
dhcp::IfaceMgr& iface_mgr = dhcp::IfaceMgr::instance();
const dhcp::IfaceMgr::IfaceCollection& ifaces = iface_mgr.getIfaces();

View File

@@ -68,7 +68,7 @@ public:
255, 255, 255, 255, // giaddr
};
// cppcheck-suppress variableScope
// cppcheck-suppress variableScope
uint8_t v4Opts[] = {
DHO_HOST_NAME, 3, 0, 1, 2, // Host name option.
DHO_BOOT_SIZE, 3, 10, 11, 12, // Boot file size option

View File

@@ -1,4 +1,4 @@
// Copyright (C) 2012-2015 Internet Systems Consortium, Inc. ("ISC")
// Copyright (C) 2012-2016 Internet Systems Consortium, Inc. ("ISC")
//
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
@@ -50,7 +50,7 @@ public:
// Packet timestamp is normally updated by interface
// manager on packets reception or send. Unit tests
// do not use interface manager so we need to do it
// ourselfs.
// ourselves.
pkt->updateTimestamp();
return pkt;
}
@@ -68,7 +68,7 @@ public:
// Packet timestamp is normally updated by interface
// manager on packets reception or send. Unit tests
// do not use interface manager so we need to do it
// ourselfs.
// ourselves.
pkt->updateTimestamp();
return pkt;
}
@@ -238,7 +238,7 @@ TEST_F(StatsMgrTest, MultipleExchanges) {
passMultiplePackets6(stats_mgr, StatsMgr6::XCHG_RR, DHCPV6_REQUEST,
request_packets_num);
// Check if all packets are successfuly passed to packet lists.
// Check if all packets are successfully passed to packet lists.
EXPECT_EQ(solicit_packets_num,
stats_mgr->getSentPacketsNum(StatsMgr6::XCHG_SA));
EXPECT_EQ(request_packets_num,
@@ -265,6 +265,9 @@ TEST_F(StatsMgrTest, ExchangeToString) {
EXPECT_EQ("DISCOVER-OFFER",
StatsMgr4::exchangeToString(StatsMgr4::XCHG_DO));
EXPECT_EQ("REQUEST-ACK", StatsMgr4::exchangeToString(StatsMgr4::XCHG_RA));
EXPECT_EQ("REQUEST-ACK (renewal)",
StatsMgr4::exchangeToString(StatsMgr4::XCHG_RNA));
// Test DHCPv6 specific exchange names.
EXPECT_EQ("SOLICIT-ADVERTISE",
@@ -375,7 +378,7 @@ TEST_F(StatsMgrTest, Delays) {
std::numeric_limits<double>::max());
EXPECT_GT(stats_mgr->getMinDelay(StatsMgr4::XCHG_DO), 1);
// Max delay is supposed to the same value as mininimum
// Max delay is supposed to the same value as minimum
// or maximum delay.
EXPECT_GT(stats_mgr->getMaxDelay(StatsMgr4::XCHG_DO), 1);

View File

@@ -1,4 +1,4 @@
// Copyright (C) 2012-2015 Internet Systems Consortium, Inc. ("ISC")
// Copyright (C) 2012-2016 Internet Systems Consortium, Inc. ("ISC")
//
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
@@ -69,7 +69,7 @@ public:
uint32_t transid_; ///< Last generated transaction id.
};
/// \brief Sets the due times for sedning Solicit, Renew and Release.
/// \brief Sets the due times for sending Solicit, Renew and Release.
///
/// There are three class members that hold the due time for sending DHCP
/// messages:
@@ -95,12 +95,14 @@ public:
using TestControl::checkExitConditions;
using TestControl::createMessageFromReply;
using TestControl::createRequestFromAck;
using TestControl::factoryElapsedTime6;
using TestControl::factoryGeneric;
using TestControl::factoryIana6;
using TestControl::factoryOptionRequestOption6;
using TestControl::factoryRapidCommit6;
using TestControl::factoryRequestList4;
using TestControl::generateClientId;
using TestControl::generateDuid;
using TestControl::generateMacAddress;
using TestControl::getCurrentTimeout;
@@ -114,6 +116,7 @@ public:
using TestControl::reset;
using TestControl::sendDiscover4;
using TestControl::sendPackets;
using TestControl::sendMultipleRequests;
using TestControl::sendMultipleMessages6;
using TestControl::sendRequest6;
using TestControl::sendSolicit6;
@@ -265,7 +268,7 @@ public:
/// \param requested_options reference buffer with options.
/// \param buf test buffer with options that will be matched.
/// \return number of options from the buffer matched with options in
/// the reference buffer or -1 if error occured.
/// the reference buffer or -1 if error occurred.
int matchRequestedOptions6(const dhcp::OptionBuffer& requested_options,
const dhcp::OptionBuffer& buf) const {
// Sanity check.
@@ -316,7 +319,7 @@ public:
return (cnt);
}
/// \brief Test generation of mulitple DUIDs
/// \brief Test generation of multiple DUIDs
///
/// This method checks the generation of multiple DUIDs. Number
/// of iterations depends on the number of simulated clients.
@@ -403,7 +406,7 @@ public:
// if randomization algorithm generates the same values but
// this would be an error in randomization algorithm.
total_dist += mismatch_dist;
// Mismatch may have occured on the DUID octet position
// Mismatch may have occurred on the DUID octet position
// up to calculated earlier unequal_pos.
ASSERT_LE(mismatch_dist, unequal_pos);
// unique will inform if tested DUID is unique.
@@ -433,7 +436,7 @@ public:
// Remember generated DUID.
duids.push_back(new_duid);
}
// If we have more than one client at least one mismatch occured.
// If we have more than one client at least one mismatch occurred.
if (clients_num < 2) {
EXPECT_EQ(0, total_dist);
}
@@ -580,7 +583,7 @@ public:
int clients_num = CommandOptions::instance().getClientsNum();
// The old_mac will be holding the value of previously generated
// 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
// to see if it changes when multiple clients are simulated or if it
// does not change when single client is simulated.
MacAddress old_mac(CommandOptions::instance().getMacTemplate());
// Holds the position if the octet on which two MAC addresses can
@@ -614,7 +617,7 @@ public:
// the case if randomization algorithm generates the same
// values but this would be an error in randomization algorithm.
total_dist += mismatch_dist;
// Mismatch may have occured on the MAC address'es octet position
// Mismatch may have occurred on the MAC address'es octet position
// up to calculated earlier unequal_pos.
ASSERT_LE(mismatch_dist, unequal_pos);
// unique will inform if tested DUID is unique.
@@ -650,7 +653,143 @@ public:
}
}
/// \brief Test that the DHCPv4 Release or Renew message is created
/// \brief Test sending DHCPv4 renews.
///
/// This function simulates acquiring 10 leases from the server. Returned
/// DHCPACK messages are cached and used to send renew messages.
/// The maximal number of messages which can be sent is equal to the
/// number of leases acquired (10). This function also checks that an
/// attempt to send more renew messages than the number of leases acquired
/// will fail.
void testSendRenew4() {
std::string loopback_iface(getLocalLoopback());
if (loopback_iface.empty()) {
std::cout << "Skipping the test because loopback interface could"
" not be detected" << std::endl;
return;
}
// Build a command line. Depending on the message type, we will use
// -f<renew-rate> or -F<release-rate> parameter.
std::ostringstream s;
s << "perfdhcp -4 -l " << loopback_iface << " -r 10 -f";
s << " 10 -R 10 -L 10067 -n 10 127.0.0.1";
ASSERT_NO_THROW(processCmdLine(s.str()));
// Create a test controller class.
NakedTestControl tc;
tc.initializeStatsMgr();
// Set the transaction id generator to sequential to control to
// guarantee that transaction ids are predictable.
boost::shared_ptr<NakedTestControl::IncrementalGenerator>
generator(new NakedTestControl::IncrementalGenerator());
tc.setTransidGenerator(generator);
// Socket has to be created so as we can actually send packets.
int sock_handle = 0;
ASSERT_NO_THROW(sock_handle = tc.openSocket());
TestControl::TestControlSocket sock(sock_handle);
// Send a number of DHCPDISCOVER messages. Each generated message will
// be assigned a different transaction id, starting from 1 to 10.
tc.sendPackets(sock, 10);
// Simulate DHCPOFFER responses from the server. Each DHCPOFFER is
// assigned a transaction id from the range of 1 to 10, so as they
// match the transaction ids from the DHCPDISCOVER messages.
for (unsigned i = generator->getNext() - 10;
i < generator->getNext(); ++i) {
Pkt4Ptr offer(createOfferPkt4(i));
// If DHCPOFFER is matched with the DHCPDISCOVER the call below
// will trigger a corresponding DHCPREQUEST. They will be assigned
// transaction ids from the range from 11 to 20 (the range of
// 1 to 10 has been used by DHCPDISCOVER-DHCPOFFER).
ASSERT_NO_THROW(tc.processReceivedPacket4(sock, offer));
}
// Requests have been sent, so now let's simulate responses from the
// server. Generate corresponding DHCPACK messages with the transaction
// ids from the range from 11 to 20.
for (unsigned i = generator->getNext() - 10;
i < generator->getNext(); ++i) {
Pkt4Ptr ack(createAckPkt4(i));
// Each DHCPACK packet corresponds to the new lease acquired. Since
// -f<renew-rate> option has been specified, received Reply
// messages are held so as renew messages can be sent for
// existing leases.
ASSERT_NO_THROW(tc.processReceivedPacket4(sock, ack));
}
uint64_t msg_num;
// Try to send 5 messages. It should be successful because 10
// DHCPREQUEST messages has been received. For each of them we
// should be able to send renewal.
ASSERT_NO_THROW(
msg_num = tc.sendMultipleRequests(sock, 5)
);
// Make sure that we have sent 5 messages.
EXPECT_EQ(5, msg_num);
// Try to do it again. We should still have 5 Reply packets for
// which renews haven't been sent yet.
ASSERT_NO_THROW(
msg_num = tc.sendMultipleRequests(sock, 5)
);
EXPECT_EQ(5, msg_num);
// We used all the DHCPACK packets (we sent renew or release for each of
// them already). Therefore, no further renew messages should be sent
// before we acquire new leases.
ASSERT_NO_THROW(
msg_num = tc.sendMultipleRequests(sock, 5)
);
// Make sure that no message has been sent.
EXPECT_EQ(0, msg_num);
}
/// \brief Test that the DHCPREQUEST message is created correctly and
/// comprises expected values.
void testCreateRequest() {
// This command line specifies that the Release/Renew messages should
// be sent with the same rate as the Solicit messages.
std::ostringstream s;
s << "perfdhcp -4 -l lo -r 10 -f 10";
s << " -R 10 -L 10067 -n 10 127.0.0.1";
ASSERT_NO_THROW(processCmdLine(s.str()));
// Create a test controller class.
NakedTestControl tc;
// Set the transaction id generator which will be used by the
// createRenew or createRelease function to generate transaction id.
boost::shared_ptr<NakedTestControl::IncrementalGenerator>
generator(new NakedTestControl::IncrementalGenerator());
tc.setTransidGenerator(generator);
Pkt4Ptr ack = createAckPkt4(1);
// Create DHCPREQUST from DHCPACK.
Pkt4Ptr request;
ASSERT_NO_THROW(request = tc.createRequestFromAck(ack));
// Make sure that the DHCPACK has been successfully created and that
// it holds expected data.
ASSERT_TRUE(request);
EXPECT_EQ("127.0.0.1", request->getCiaddr().toText());
// HW address.
HWAddrPtr hwaddr_ack = ack->getHWAddr();
ASSERT_TRUE(hwaddr_ack);
HWAddrPtr hwaddr_req = request->getHWAddr();
ASSERT_TRUE(hwaddr_req);
EXPECT_TRUE(hwaddr_ack->hwaddr_ == hwaddr_req->hwaddr_);
// Creating message from null DHCPACK should fail.
EXPECT_THROW(tc.createRequestFromAck(Pkt4Ptr()), isc::BadValue);
// Creating message from DHCPACK holding zero yiaddr should fail.
asiolink::IOAddress yiaddr = ack->getYiaddr();
ack->setYiaddr(asiolink::IOAddress::IPV4_ZERO_ADDRESS());
EXPECT_THROW(tc.createRequestFromAck(ack), isc::BadValue);
ack->setYiaddr(yiaddr);
}
/// \brief Test that the DHCPv6 Release or Renew message is created
/// correctly and comprises expected options.
///
/// \param msg_type A type of the message to be tested: DHCPV6_RELEASE
@@ -721,7 +860,7 @@ public:
///
/// This function simulates acquiring 10 leases from the server. Returned
/// Reply messages are cached and used to send Renew or Release messages.
/// The maxmimal number of Renew or Release messages which can be sent is
/// The maximal number of Renew or Release messages which can be sent is
/// equal to the number of leases acquired (10). This function also checks
/// that an attempt to send more Renew or Release messages than the number
/// of leases acquired will fail.
@@ -816,26 +955,47 @@ public:
/// \brief Parse command line string with CommandOptions.
///
/// \param cmdline command line string to be parsed.
/// \throw isc::Unexpected if unexpected error occured.
/// \throw isc::Unexpected if unexpected error occurred.
/// \throw isc::InvalidParameter if command line is invalid.
void processCmdLine(const std::string& cmdline) const {
CommandOptionsHelper::process(cmdline);
}
/// \brief Create DHCPOFFER or DHCPACK packet.
///
/// \param pkt_type DHCPOFFER or DHCPACK.
/// \param transid Transaction id.
///
/// \return Instance of the packet.
Pkt4Ptr
createResponsePkt4(const uint8_t pkt_type,
const uint32_t transid) const {
Pkt4Ptr pkt(new Pkt4(pkt_type, transid));
OptionPtr opt_serverid = Option::factory(Option::V4,
DHO_DHCP_SERVER_IDENTIFIER,
OptionBuffer(4, 1));
pkt->setYiaddr(asiolink::IOAddress("127.0.0.1"));
pkt->addOption(opt_serverid);
pkt->updateTimestamp();
return (pkt);
}
/// \brief Create DHCPv4 OFFER packet.
///
/// \param transid transaction id.
/// \return instance of the packet.
boost::shared_ptr<Pkt4>
Pkt4Ptr
createOfferPkt4(uint32_t transid) const {
boost::shared_ptr<Pkt4> offer(new Pkt4(DHCPOFFER, transid));
OptionPtr opt_serverid = Option::factory(Option::V4,
DHO_DHCP_SERVER_IDENTIFIER,
OptionBuffer(4, 1));
offer->setYiaddr(asiolink::IOAddress("127.0.0.1"));
offer->addOption(opt_serverid);
offer->updateTimestamp();
return (offer);
return (createResponsePkt4(DHCPOFFER, transid));
}
/// \brief Create DHCPACK packet.
///
/// \param transid transaction id.
/// \return instance of the packet.
Pkt4Ptr
createAckPkt4(const uint32_t transid) const {
return (createResponsePkt4(DHCPACK, transid));
}
/// \brief Create DHCPv6 ADVERTISE packet.
@@ -916,6 +1076,34 @@ TEST_F(TestControlTest, reset) {
}
// This test verifies that the client id is generated from the HW address.
TEST_F(TestControlTest, generateClientId) {
// Generate HW address.
std::vector<uint8_t> hwaddr;
for (unsigned int i = 0; i < 6; ++i) {
hwaddr.push_back(i);
}
HWAddrPtr hwaddr_ptr(new HWAddr(hwaddr, 5));
// Use generated HW address to generate client id.
NakedTestControl tc;
OptionPtr opt_client_id;
ASSERT_NO_THROW(opt_client_id = tc.generateClientId(hwaddr_ptr));
ASSERT_TRUE(opt_client_id);
// Extract the client id data.
const OptionBuffer& client_id = opt_client_id->getData();
ASSERT_EQ(7, client_id.size());
// Verify that the client identifier is generated correctly.
// First byte is the HW type.
EXPECT_EQ(5, client_id[0]);
// The rest of the client identifier should be equal to the HW address.
std::vector<uint8_t> sub(client_id.begin() + 1, client_id.end());
EXPECT_TRUE(hwaddr == sub);
}
TEST_F(TestControlTest, GenerateDuid) {
// Simple command line that simulates one client only. Always the
// same DUID will be generated.
@@ -1252,7 +1440,7 @@ TEST_F(TestControlTest, Packet6ExchangeFromTemplate) {
// 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.
// Simulate the number of Solicit-Advertise-Request-Reply (SARR) exchanges.
// 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
@@ -1287,14 +1475,14 @@ TEST_F(TestControlTest, Packet6Exchange) {
// This simulates no packet drops.
bool use_templates = false;
// Simulate the number of Solicit-Advertise-Request-Reply (SARR) echanges.
// Simulate the number of Solicit-Advertise-Request-Reply (SARR) exchanges.
// 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
// to simulate the IPv6 address acquisition and to verify that the IA_NA
// options returned by the server are processed correctly.
testPkt6Exchange(iterations_num, iterations_num, use_templates,
iterations_performed);
@@ -1323,7 +1511,7 @@ TEST_F(TestControlTest, Packet6ExchangePrefixDelegation) {
// This simulates no packet drops.
bool use_templates = false;
// Simulate the number of Solicit-Advertise-Request-Reply (SARR) echanges.
// Simulate the number of Solicit-Advertise-Request-Reply (SARR) exchanges.
// 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
@@ -1358,7 +1546,7 @@ TEST_F(TestControlTest, Packet6ExchangeAddressAndPrefix) {
// 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.
// Simulate the number of Solicit-Advertise-Request-Reply (SARR) exchanges.
// 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
@@ -1432,14 +1620,30 @@ TEST_F(TestControlTest, PacketTemplates) {
EXPECT_THROW(tc.initPacketTemplates(), isc::BadValue);
}
TEST_F(TestControlTest, processRenew) {
// This test verifies that DHCPv4 renew (DHCPREQUEST) messages can be
// sent for acquired leases.
TEST_F(TestControlTest, processRenew4) {
testSendRenew4();
}
// This test verifies that DHCPv6 Renew messages can be sent for acquired
// leases.
TEST_F(TestControlTest, processRenew6) {
testSendRenewRelease(DHCPV6_RENEW);
}
TEST_F(TestControlTest, processRelease) {
// This test verifies that DHCPv6 Release messages can be sent for acquired
// leases.
TEST_F(TestControlTest, processRelease6) {
testSendRenewRelease(DHCPV6_RELEASE);
}
// This test verifies that DHCPREQUEST is created correctly from the
// DHCPACK message.
TEST_F(TestControlTest, createRequest) {
testCreateRequest();
}
// This test verifies that the DHCPV6 Renew message is created correctly
// and that it comprises all required options.
TEST_F(TestControlTest, createRenew) {
@@ -1485,8 +1689,8 @@ TEST_F(TestControlTest, getCurrentTimeout) {
// server's responses is valid. In this case, we are simulating that perfdhcp
// sends Renew requests to the server, apart from the regular 4-way exchanges.
// The timeout value depends on both the due time to send next Solicit and the
// due time to send Renew - the timeout should be ajusted to the due time that
// occurs sooner.
// due time to send Renew - the timeout should be adjusted to the due time
// that occurs sooner.
TEST_F(TestControlTest, getCurrentTimeoutRenew) {
// Set the Solicit rate to 10 and the Renew rate 5.
ASSERT_NO_THROW(processCmdLine("perfdhcp -6 -l lo -r 10 -f 5 ::1"));