Commit fbbae39a authored by Marcin Siodelski's avatar Marcin Siodelski

[1959] Send request messages to server and corresponding unit tests.

parent 00e8a3eb
......@@ -47,8 +47,8 @@ namespace perfdhcp {
/// stored on the list of sent packets. When packets are matched the
/// round trip time can be calculated.
///
/// \tparam T class representing DHCPv4 or DHCPv6 packet.
template <class T>
/// \param T class representing DHCPv4 or DHCPv6 packet.
template <class T = dhcp::Pkt4>
class StatsMgr : public boost::noncopyable {
public:
......@@ -138,7 +138,7 @@ public:
/// \param packet packet which transaction id is to be hashed.
/// \throw isc::BadValue if packet is null.
/// \return transaction id hash.
static uint32_t hashTransid(const boost::shared_ptr<const T>& packet) {
static uint32_t hashTransid(const boost::shared_ptr<T>& packet) {
if (!packet) {
isc_throw(BadValue, "Packet is null");
}
......@@ -214,12 +214,12 @@ public:
/// }
/// \endcode
typedef boost::multi_index_container<
boost::shared_ptr<const T>,
boost::shared_ptr<T>,
boost::multi_index::indexed_by<
boost::multi_index::sequenced<>,
boost::multi_index::hashed_non_unique<
boost::multi_index::global_fun<
const boost::shared_ptr<const T>&,
const boost::shared_ptr<T>&,
uint32_t,
&ExchangeStats::hashTransid
>
......@@ -228,7 +228,7 @@ public:
> PktList;
/// Packet list iterator for sequencial access to elements.
typedef typename PktList::const_iterator PktListIterator;
typedef typename PktList::iterator PktListIterator;
/// Packet list index to search packets using transaction id hash.
typedef typename PktList::template nth_index<1>::type
PktListTransidHashIndex;
......@@ -267,7 +267,7 @@ public:
///
/// \param packet packet object to be added.
/// \throw isc::BadValue if packet is null.
void appendSent(const boost::shared_ptr<const T>& packet) {
void appendSent(const boost::shared_ptr<T>& packet) {
if (!packet) {
isc_throw(BadValue, "Packet is null");
}
......@@ -281,7 +281,7 @@ public:
///
/// \param packet packet object to be added.
/// \throw isc::BadValue if packet is null.
void appendRcvd(const boost::shared_ptr<const T>& packet) {
void appendRcvd(const boost::shared_ptr<T>& packet) {
if (!packet) {
isc_throw(BadValue, "Packet is null");
}
......@@ -297,8 +297,8 @@ public:
/// \param rcvd_packet received packet
/// \throw isc::BadValue if sent or received packet is null.
/// \throw isc::Unexpected if failed to calculate timestamps
void updateDelays(const boost::shared_ptr<const T>& sent_packet,
const boost::shared_ptr<const T>& rcvd_packet) {
void updateDelays(const boost::shared_ptr<T>& sent_packet,
const boost::shared_ptr<T>& rcvd_packet) {
if (!sent_packet) {
isc_throw(BadValue, "Sent packet is null");
}
......@@ -356,7 +356,8 @@ public:
/// \throw isc::BadValue if received packet is null.
/// \return packet having specified transaction or NULL if packet
/// not found
boost::shared_ptr<const T> matchPackets(const boost::shared_ptr<const T>& rcvd_packet) {
boost::shared_ptr<T>
matchPackets(const boost::shared_ptr<T>& rcvd_packet) {
if (!rcvd_packet) {
isc_throw(BadValue, "Received packet is null");
}
......@@ -367,7 +368,7 @@ public:
// that the received packet we got has no corresponding
// sent packet so orphans counter has to be updated.
++orphans_;
return(boost::shared_ptr<const T>());
return(boost::shared_ptr<T>());
} else if (next_sent_ == sent_packets_.end()) {
// Even if there are still many unmatched packets on the
// list we might hit the end of it because of unordered
......@@ -426,13 +427,13 @@ public:
// If we are here, it means that both ordered lookup and
// unordered lookup failed. Searched packet is not on the list.
++orphans_;
return(boost::shared_ptr<const T>());
return(boost::shared_ptr<T>());
}
// Packet is matched so we count it. We don't count unmatched packets
// as they are counted as orphans with a separate counter.
++rcvd_packets_num_;
boost::shared_ptr<const T> sent_packet(*next_sent_);
boost::shared_ptr<T> sent_packet(*next_sent_);
// If packet was found, we assume it will be never searched
// again. We want to delete this packet from the list to
// improve performance of future searches.
......@@ -549,6 +550,19 @@ public:
/// \return number of received packets.
uint64_t getRcvdPacketsNum() const { return(rcvd_packets_num_); }
/// \brief Return number of dropped packets.
///
/// Method returns number of dropped packets.
///
/// \return number of dropped packets.
uint64_t getDroppedPacketsNum() const {
uint64_t drops = 0;
if (getSentPacketsNum() > getRcvdPacketsNum()) {
drops = getSentPacketsNum() - getRcvdPacketsNum();
}
return(drops);
}
/// \brief Print main statistics for packet exchange.
///
/// Method prints main statistics for particular exchange.
......@@ -556,13 +570,9 @@ public:
/// number of dropped packets and number of orphans.
void printMainStats() const {
using namespace std;
uint64_t drops = 0;
if (getRcvdPacketsNum() >= getSentPacketsNum()) {
drops = getRcvdPacketsNum() - getSentPacketsNum();
}
cout << "sent packets: " << getSentPacketsNum() << endl
<< "received packets: " << getRcvdPacketsNum() << endl
<< "drops: " << drops << endl
<< "drops: " << getDroppedPacketsNum() << endl
<< "orphans: " << getOrphans() << endl;
}
......@@ -614,7 +624,7 @@ public:
for (PktListIterator it = rcvd_packets_.begin();
it != rcvd_packets_.end();
++it) {
boost::shared_ptr<const T> rcvd_packet = *it;
boost::shared_ptr<T> rcvd_packet = *it;
PktListTransidHashIndex& idx =
archived_packets_.template get<1>();
std::pair<PktListTransidHashIterator,
......@@ -625,7 +635,7 @@ public:
++it) {
if ((*it_archived)->getTransid() ==
rcvd_packet->getTransid()) {
boost::shared_ptr<const T> sent_packet = *it_archived;
boost::shared_ptr<T> sent_packet = *it_archived;
// Get sent and received packet times.
ptime sent_time = sent_packet->getTimestamp();
ptime rcvd_time = rcvd_packet->getTimestamp();
......@@ -839,7 +849,7 @@ public:
/// \throw isc::BadValue if invalid exchange type specified or
/// packet is null.
void passSentPacket(const ExchangeType xchg_type,
const boost::shared_ptr<const T>& packet) {
const boost::shared_ptr<T>& packet) {
ExchangeStatsPtr xchg_stats = getExchangeStats(xchg_type);
xchg_stats->appendSent(packet);
}
......@@ -857,10 +867,11 @@ public:
/// or packet is null.
/// \throw isc::Unexpected if corresponding packet was not
/// found on the list of sent packets.
void passRcvdPacket(const ExchangeType xchg_type,
const boost::shared_ptr<const T>& packet) {
boost::shared_ptr<T>
passRcvdPacket(const ExchangeType xchg_type,
const boost::shared_ptr<T>& packet) {
ExchangeStatsPtr xchg_stats = getExchangeStats(xchg_type);
boost::shared_ptr<const T> sent_packet
boost::shared_ptr<T> sent_packet
= xchg_stats->matchPackets(packet);
if (sent_packet) {
......@@ -869,6 +880,7 @@ public:
xchg_stats->appendRcvd(packet);
}
}
return(sent_packet);
}
/// \brief Return minumum delay between sent and received packet.
......@@ -1003,6 +1015,19 @@ public:
return(xchg_stats->getRcvdPacketsNum());
}
/// \brief Return total number of dropped packets.
///
/// Method returns total number of dropped packets for specified
/// exchange type.
///
/// \param xchg_type exchange type.
/// \throw isc::BadValue if invalid exchange type specified.
/// \return number of dropped packets.
uint64_t getDroppedPacketsNum(const ExchangeType xchg_type) const {
ExchangeStatsPtr xchg_stats = getExchangeStats(xchg_type);
return(xchg_stats->getDroppedPacketsNum());
}
/// \brief Return name of the exchange.
///
/// Method returns name of the specified exchange type.
......
......@@ -80,18 +80,104 @@ TestControl::instance() {
TestControl::TestControl() :
send_due_(microsec_clock::universal_time()),
last_sent_(send_due_) {
last_sent_(send_due_),
transid_gen_(new TransidGenerator()) {
}
bool
TestControl::checkExitConditions() const {
CommandOptions& options = CommandOptions::instance();
if ((options.getNumRequests().size() > 0) &&
(sent_packets_0_ >= options.getNumRequests()[0])) {
return(true);
} else if ((options.getNumRequests().size() == 2) &&
(sent_packets_1_ >= options.getNumRequests()[1])) {
return(true);
// Check if we reached maximum number of DISCOVER/SOLICIT sent.
if (options.getNumRequests().size() > 0) {
if (options.getIpVersion() == 4) {
if (getSentPacketsNum(StatsMgr4::XCHG_DO) >=
options.getNumRequests()[0]) {
return(true);
}
} else if (options.getIpVersion() == 6) {
if (stats_mgr6_->getSentPacketsNum(StatsMgr6::XCHG_SA) >=
options.getNumRequests()[0]) {
return(true);
}
}
}
// Check if we reached maximum number REQUEST packets.
if (options.getNumRequests().size() == 2) {
if (options.getIpVersion() == 4) {
if (stats_mgr4_->getSentPacketsNum(StatsMgr4::XCHG_RA) >=
options.getNumRequests()[1]) {
return(true);
}
} else if (options.getIpVersion() == 6) {
if (stats_mgr6_->getSentPacketsNum(StatsMgr6::XCHG_RR) >=
options.getNumRequests()[1]) {
return(true);
}
}
}
// Check if we reached maximum number of drops of OFFER/ADVERTISE packets.
if (options.getMaxDrop().size() > 0) {
if (options.getIpVersion() == 4) {
if (stats_mgr4_->getDroppedPacketsNum(StatsMgr4::XCHG_DO) >=
options.getMaxDrop()[0]) {
return(true);
}
} else if (options.getIpVersion() == 6) {
if (stats_mgr6_->getDroppedPacketsNum(StatsMgr6::XCHG_SA) >=
options.getMaxDrop()[0]) {
return(true);
}
}
}
// Check if we reached maximum number of drops of ACK/REPLY packets.
if (options.getMaxDrop().size() == 2) {
if (options.getIpVersion() == 4) {
if (stats_mgr4_->getDroppedPacketsNum(StatsMgr4::XCHG_RA) >=
options.getMaxDrop()[1]) {
return(true);
}
} else if (options.getIpVersion() == 6) {
if (stats_mgr6_->getDroppedPacketsNum(StatsMgr6::XCHG_RR) >=
options.getMaxDrop()[1]) {
return(true);
}
}
}
// Check if we reached maximum drops percentage of OFFER/ADVERTISE packets.
if (options.getMaxDropPercentage().size() > 0) {
if (options.getIpVersion() == 4) {
if ((stats_mgr4_->getSentPacketsNum(StatsMgr4::XCHG_DO) > 10) &&
((100. * stats_mgr4_->getDroppedPacketsNum(StatsMgr4::XCHG_DO) /
stats_mgr4_->getSentPacketsNum(StatsMgr4::XCHG_DO)) >=
options.getMaxDropPercentage()[0])) {
return(true);
}
} else if (options.getIpVersion() == 6) {
if ((stats_mgr6_->getSentPacketsNum(StatsMgr6::XCHG_SA) > 10) &&
((100. * stats_mgr6_->getDroppedPacketsNum(StatsMgr6::XCHG_SA) /
stats_mgr6_->getSentPacketsNum(StatsMgr6::XCHG_SA)) >=
options.getMaxDropPercentage()[0])) {
return(true);
}
}
}
// Check if we reached maximum drops percentage of ACK/REPLY packets.
if (options.getMaxDropPercentage().size() == 2) {
if (options.getIpVersion() == 4) {
if ((stats_mgr4_->getSentPacketsNum(StatsMgr4::XCHG_RA) > 10) &&
((100. * stats_mgr4_->getDroppedPacketsNum(StatsMgr4::XCHG_RA) /
stats_mgr4_->getSentPacketsNum(StatsMgr4::XCHG_RA)) >=
options.getMaxDropPercentage()[0])) {
return(true);
}
} else if (options.getIpVersion() == 6) {
if ((stats_mgr6_->getSentPacketsNum(StatsMgr6::XCHG_RR) > 10) &&
((100. * stats_mgr6_->getDroppedPacketsNum(StatsMgr6::XCHG_RR) /
stats_mgr6_->getSentPacketsNum(StatsMgr6::XCHG_RR)) >=
options.getMaxDropPercentage()[0])) {
return(true);
}
}
}
return(false);
}
......@@ -170,8 +256,6 @@ TestControl::factoryRequestList4(Option::Universe u,
return opt;
}
std::vector<uint8_t>
TestControl::generateMacAddress() const {
CommandOptions& options = CommandOptions::instance();
......@@ -268,6 +352,26 @@ TestControl::getNextExchangesNum() const {
return (0);
}
uint64_t
TestControl::getRcvdPacketsNum(const ExchangeType xchg_type) const {
uint8_t ip_version = CommandOptions::instance().getIpVersion();
if (ip_version == 4) {
return(stats_mgr4_->getRcvdPacketsNum(xchg_type));
}
return(stats_mgr6_->
getRcvdPacketsNum(static_cast<StatsMgr6::ExchangeType>(xchg_type)));
}
uint64_t
TestControl::getSentPacketsNum(const ExchangeType xchg_type) const {
uint8_t ip_version = CommandOptions::instance().getIpVersion();
if (ip_version == 4) {
return(stats_mgr4_->getSentPacketsNum(xchg_type));
}
return(stats_mgr6_->
getSentPacketsNum(static_cast<StatsMgr6::ExchangeType>(xchg_type)));
}
void
TestControl::initializeStatsMgr() {
CommandOptions& options = CommandOptions::instance();
......@@ -275,7 +379,7 @@ TestControl::initializeStatsMgr() {
stats_mgr4_.reset();
stats_mgr4_ = StatsMgr4Ptr(new StatsMgr4());
stats_mgr4_->addExchangeStats(StatsMgr4::XCHG_DO);
if (options.getExchangeMode() == CommandOptions::DO_SA) {
if (options.getExchangeMode() == CommandOptions::DORA_SARR) {
stats_mgr4_->addExchangeStats(StatsMgr4::XCHG_RA);
}
......@@ -283,9 +387,9 @@ TestControl::initializeStatsMgr() {
stats_mgr6_.reset();
stats_mgr6_ = StatsMgr6Ptr(new StatsMgr6());
stats_mgr6_->addExchangeStats(StatsMgr6::XCHG_SA);
if (options.getExchangeMode() == CommandOptions::DO_SA) {
if (options.getExchangeMode() == CommandOptions::DORA_SARR) {
stats_mgr6_->addExchangeStats(StatsMgr6::XCHG_RR);
}
}
}
}
......@@ -395,7 +499,8 @@ TestControl::printStats() const {
}
void
TestControl::receivePacket4(Pkt4Ptr& pkt4) {
TestControl::receivePacket4(const TestControlSocket&,
const Pkt4Ptr& pkt4) {
switch(pkt4->getType()) {
case DHCPOFFER :
stats_mgr4_->passRcvdPacket(StatsMgr4::XCHG_DO, pkt4);
......@@ -410,23 +515,25 @@ TestControl::receivePacket4(Pkt4Ptr& pkt4) {
}
void
TestControl::receivePacket6(Pkt6Ptr& pkt6) {
switch(pkt6->getType()) {
case DHCPV6_ADVERTISE :
stats_mgr6_->passRcvdPacket(StatsMgr6::XCHG_SA, pkt6);
break;
case DHCPV6_REPLY :
TestControl::receivePacket6(const TestControlSocket& socket,
const Pkt6Ptr& pkt6) {
uint8_t packet_type = pkt6->getType();
if (packet_type == DHCPV6_ADVERTISE) {
Pkt6Ptr solicit_pkt6(stats_mgr6_->passRcvdPacket(StatsMgr6::XCHG_SA,
pkt6));
if (solicit_pkt6) {
sendRequest6(socket, solicit_pkt6, pkt6);
}
} else if (packet_type == DHCPV6_REPLY) {
stats_mgr6_->passRcvdPacket(StatsMgr6::XCHG_RR, pkt6);
break;
default:
} else {
isc_throw(BadValue, "unknown type " << pkt6->getType()
<< " of received DHCPv6 packet");
}
}
void
TestControl::receivePackets() {
TestControl::receivePackets(const TestControlSocket& socket) {
int timeout = 0;
bool receiving = true;
while (receiving) {
......@@ -436,7 +543,7 @@ TestControl::receivePackets() {
receiving = false;
} else {
pkt4->unpack();
receivePacket4(pkt4);
receivePacket4(socket, pkt4);
}
} else if (CommandOptions::instance().getIpVersion() == 6) {
Pkt6Ptr pkt6 = IfaceMgr::instance().receive6(timeout);
......@@ -444,7 +551,7 @@ TestControl::receivePackets() {
receiving = false;
} else {
if (pkt6->unpack()) {
receivePacket6(pkt6);
receivePacket6(socket, pkt6);
}
}
}
......@@ -524,7 +631,7 @@ TestControl::run() {
}
registerOptionFactories();
TestControlSocket socket(openSocket());
initializeStatsMgr();
uint64_t packets_sent = 0;
for (;;) {
......@@ -534,7 +641,7 @@ TestControl::run() {
}
uint64_t packets_due = getNextExchangesNum();
receivePackets();
receivePackets(socket);
for (uint64_t i = packets_due; i > 0; --i) {
if (options.getIpVersion() == 4) {
......@@ -555,8 +662,8 @@ TestControl::sendDiscover4(const TestControlSocket& socket) {
// Generate the MAC address to be passed in the packet.
std::vector<uint8_t> mac_address = generateMacAddress();
// Generate trasnaction id to be set for the new exchange.
const uint32_t transid = static_cast<uint32_t>(random() % 0x00FFFFFF);
boost::shared_ptr<Pkt4> pkt4(new Pkt4(DHCPDISCOVER, transid));
const uint32_t transid = generateTransid();
Pkt4Ptr pkt4(new Pkt4(DHCPDISCOVER, transid));
if (!pkt4) {
isc_throw(Unexpected, "failed to create DISCOVER packet");
}
......@@ -580,6 +687,59 @@ TestControl::sendDiscover4(const TestControlSocket& socket) {
stats_mgr4_->passSentPacket(StatsMgr4::XCHG_DO, pkt4);
}
void
TestControl::sendRequest6(const TestControlSocket& socket,
const Pkt6Ptr& solicit_pkt6,
const Pkt6Ptr& advertise_pkt6) {
const uint32_t transid = static_cast<uint32_t>(random() % 0x00FFFFFF);
Pkt6Ptr pkt6(new Pkt6(DHCPV6_REQUEST, transid));
// Calculate elapsed time
ptime solicit_time = solicit_pkt6->getTimestamp();
ptime advertise_time = advertise_pkt6->getTimestamp();
if (solicit_time.is_not_a_date_time()) {
isc_throw(Unexpected, "timestamp was not set for SOLICIT packet");
}
if (advertise_time.is_not_a_date_time()) {
isc_throw(Unexpected, "timestamp was not set for ADVERTISE packet");
}
time_period period(solicit_time, advertise_time);
if (period.is_null()) {
pkt6->addOption(Option::factory(Option::V6, D6O_ELAPSED_TIME));
} else {
OptionBuffer buf();
const uint32_t elapsed_time = period.length().total_seconds();
OptionPtr opt_elapsed_time =
Option::factory(Option::V6, D6O_ELAPSED_TIME);
opt_elapsed_time->setUint16(static_cast<uint16_t>(elapsed_time));
pkt6->addOption(opt_elapsed_time);
}
OptionPtr opt_clientid = advertise_pkt6->getOption(D6O_CLIENTID);
if (!opt_clientid) {
isc_throw(Unexpected, "client id not found in received packet");
}
pkt6->addOption(opt_clientid);
OptionPtr opt_serverid = advertise_pkt6->getOption(D6O_SERVERID);
if (!opt_serverid) {
isc_throw(Unexpected, "server id not found in received packet");
}
pkt6->addOption(opt_serverid);
OptionPtr opt_ia_na = advertise_pkt6->getOption(D6O_IA_NA);
if (!opt_ia_na) {
isc_throw(Unexpected, "DHCPv6 IA_NA option not found in received "
"packet");
}
pkt6->addOption(opt_ia_na);
setDefaults6(socket, pkt6);
pkt6->pack();
IfaceMgr::instance().send(pkt6);
if (!stats_mgr6_) {
isc_throw(InvalidOperation, "Statistics Manager for DHCPv6 "
"hasn't been initialized");
}
stats_mgr6_->passSentPacket(StatsMgr6::XCHG_RR, pkt6);
}
void
TestControl::sendSolicit6(const TestControlSocket& socket) {
++sent_packets_0_;
......@@ -589,13 +749,13 @@ TestControl::sendSolicit6(const TestControlSocket& socket) {
// Generate DUID to be passed to the packet
std::vector<uint8_t> duid = generateDuid();
// Generate trasnaction id to be set for the new exchange.
const uint32_t transid = static_cast<uint32_t>(random() % 0x00FFFFFF);
boost::shared_ptr<Pkt6> pkt6(new Pkt6(DHCPV6_SOLICIT, transid));
const uint32_t transid = generateTransid();
Pkt6Ptr pkt6(new Pkt6(DHCPV6_SOLICIT, transid));
if (!pkt6) {
isc_throw(Unexpected, "failed to create SOLICIT packet");
}
pkt6->addOption(Option::factory(Option::V6, D6O_ELAPSED_TIME));
pkt6->addOption(Option::factory(Option::V6, D6O_RAPID_COMMIT));
// pkt6->addOption(Option::factory(Option::V6, D6O_RAPID_COMMIT));
pkt6->addOption(Option::factory(Option::V6, D6O_CLIENTID, duid));
pkt6->addOption(Option::factory(Option::V6, D6O_ORO));
pkt6->addOption(Option::factory(Option::V6, D6O_IA_NA));
......@@ -612,7 +772,7 @@ TestControl::sendSolicit6(const TestControlSocket& socket) {
void
TestControl::setDefaults4(const TestControlSocket& socket,
const boost::shared_ptr<Pkt4>& pkt) {
const Pkt4Ptr& pkt) {
CommandOptions& options = CommandOptions::instance();
// Interface name.
pkt->setIface(socket.getIface());
......@@ -634,7 +794,7 @@ TestControl::setDefaults4(const TestControlSocket& socket,
void
TestControl::setDefaults6(const TestControlSocket& socket,
const boost::shared_ptr<Pkt6>& pkt) {
const Pkt6Ptr& pkt) {
CommandOptions& options = CommandOptions::instance();
// Interface name.
pkt->setIface(socket.getIface());
......
......@@ -20,6 +20,7 @@
#include <boost/noncopyable.hpp>
#include <boost/shared_ptr.hpp>
#include <boost/function.hpp>
#include <boost/date_time/posix_time/posix_time.hpp>
#include <dhcp/dhcp6.h>
......@@ -55,6 +56,8 @@ public:
typedef StatsMgr<dhcp::Pkt6> StatsMgr6;
// Pointer to Statistics Manager for DHCPv6.
typedef boost::shared_ptr<StatsMgr6> StatsMgr6Ptr;
// Packet exchange type.
typedef StatsMgr<>::ExchangeType ExchangeType;
/// \brief Socket wrapper class.
///
......@@ -120,6 +123,26 @@ public:
asiolink::IOAddress addr_; ///< Address bound.
};
/// \brief Default transaction id generator class.
///
/// This is default transaction id generator class. The member
/// function is used to generate unique transaction id value.
/// Other generator classes should derive from this one to
/// override the standard generation algorithm (e.g. unit tests
/// override this class wih algorithm that produces more predictable
/// transaction id values).
class TransidGenerator {
public:
/// \brief generate transaction id.
///
/// \return generated transazction id value.
virtual uint32_t generate() {
return static_cast<uint32_t>(random() % 0x00FFFFFF);
}
};
typedef boost::shared_ptr<TransidGenerator> TransidGeneratorPtr;
/// \brief Length of the Ethernet HW address (MAC) in bytes.
static const uint8_t HW_ETHER_LEN = 6;
......@@ -129,7 +152,7 @@ public:
/// \return the only existing instance of test control
static TestControl& instance();
/// Run performance test.
/// brief\ Run performance test.
///
/// Method runs whole performance test. Command line options must
/// be parsed prior to running this function. Othewise function will
......@@ -139,6 +162,14 @@ public:
/// \throw isc::Unexpected if internal Test Controler error occured.
void run();
/// \brief Set new transaction id generator.
///
/// \param generator generator object to be used.
void setTransidGenerator(TransidGeneratorPtr& generator) {
transid_gen_.reset();
transid_gen_ = generator;
}
protected:
// We would really like these methods and members to be private but
......@@ -285,6 +316,13 @@ protected:
/// \return generated MAC address.
std::vector<uint8_t> generateMacAddress() const;
/// \brief generate transaction id.
///
/// \return generated transaction id.
uint32_t generateTransid() {
return(transid_gen_->generate());
}
/// \brief Returns number of exchanges to be started.
///
/// Method returns number of new exchanges to be started as soon
......@@ -329,14 +367,45 @@ protected:
/// not initialized.
void printStats() const;
void receivePacket4(dhcp::Pkt4Ptr& pkt4);
/// \brief Receive DHCPv4 packet.
///
/// Method performs reception of the DHCPv4 packet, updates
/// statistics and responsds to the server if required, e.g.
/// when OFFER packet arrives, this function will initiate
/// REQUEST message to the server.
///
/// \param socket socket to be used.
/// \param pkt4 object representing DHCPv4 packet received.
/// \throw isc::BadValue if unknown message type received.
/// \throw isc::Unexpected if unexpected error occured.
void receivePacket4(const TestControlSocket& socket,
const dhcp::Pkt4Ptr& pkt4);
void receivePacket6(dhcp::Pkt6Ptr& pkt4);
/// \brief Receive DHCPv6 packet.
///
/// Method performs reception of the DHCPv6 packet, updates
/// statistics and responsds to the server if required, e.g.
/// when ADVERTISE packet arrives, this function will initiate
/// REQUEST message to the server.
///
/// \param socket socket to be used.
/// \param pkt6 object representing DHCPv6 packet received.
/// \throw isc::BadValue if unknown message type received.
/// \throw isc::Unexpected if unexpected error occured.
void receivePacket6(const TestControlSocket& socket,
const dhcp::Pkt6Ptr& pkt6);
/// \brief Receive DHCPv4 or DHCPv6 packets from the server.
///
/// Method receives DHCPv4 or DHCPv6 packets from the server.
void receivePackets();
/// This function will call \ref receivePacket4 or
/// \ref receivePacket6 depending if DHCPv4 or DHCPv6 packet
/// has arrived.
///
/// \param socket socket to be used.
/// \throw::BadValue if unknown message type received.
/// \throw::Unexpected if unexpected error occured.
void receivePackets(const TestControlSocket& socket);