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:
@@ -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"
|
||||
|
@@ -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>
|
||||
|
@@ -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:
|
||||
|
@@ -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);
|
||||
|
@@ -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_;
|
||||
|
||||
|
@@ -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();
|
||||
|
@@ -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
|
||||
|
@@ -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);
|
||||
|
||||
|
@@ -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"));
|
||||
|
Reference in New Issue
Block a user