/// In this mode all packets are stored throughout the test execution.
ExchangeStats(const ExchangeType xchg_type, const bool archive_enabled)
: xchg_type_(xchg_type),
+ sent_packets_(),
+ rcvd_packets_(),
+ archived_packets_(),
+ archive_enabled_(archive_enabled),
min_delay_(std::numeric_limits<double>::max()),
max_delay_(0.),
sum_delay_(0.),
- orphans_(0),
sum_delay_squared_(0.),
- ordered_lookups_(0),
+ orphans_(0),
unordered_lookup_size_sum_(0),
unordered_lookups_(0),
+ ordered_lookups_(0),
sent_packets_num_(0),
- rcvd_packets_num_(0),
- sent_packets_(),
- rcvd_packets_(),
- archived_packets_(),
- archive_enabled_(archive_enabled) {
+ rcvd_packets_num_(0)
+ {
next_sent_ = sent_packets_.begin();
}
/// number of dropped packets and number of orphans.
void printMainStats() const {
using namespace std;
- uint64_t drops = getRcvdPacketsNum() - getSentPacketsNum();
+ uint64_t drops = 0;
+ if (getRcvdPacketsNum() >= getSentPacketsNum()) {
+ drops = getRcvdPacketsNum() - getSentPacketsNum();
+ }
cout << "sent packets: " << getSentPacketsNum() << endl
<< "received packets: " << getRcvdPacketsNum() << endl
<< "drops: " << drops << endl
return (0);
}
+void
+TestControl::initializeStatsMgr() {
+ CommandOptions& options = CommandOptions::instance();
+ if (options.getIpVersion() == 4) {
+ stats_mgr4_.reset();
+ stats_mgr4_ = StatsMgr4Ptr(new StatsMgr4());
+ stats_mgr4_->addExchangeStats(StatsMgr4::XCHG_DO);
+ if (options.getExchangeMode() == CommandOptions::DO_SA) {
+ stats_mgr4_->addExchangeStats(StatsMgr4::XCHG_RA);
+ }
+
+ } else if (options.getIpVersion() == 6) {
+ stats_mgr6_.reset();
+ stats_mgr6_ = StatsMgr6Ptr(new StatsMgr6());
+ stats_mgr6_->addExchangeStats(StatsMgr6::XCHG_SA);
+ if (options.getExchangeMode() == CommandOptions::DO_SA) {
+ stats_mgr6_->addExchangeStats(StatsMgr6::XCHG_RR);
+ }
+ }
+}
+
int
TestControl::openSocket(uint16_t port) const {
CommandOptions& options = CommandOptions::instance();
IOAddress remoteaddr(servername);
if (port == 0) {
if (options.getIpVersion() == 6) {
- port = 547;
- } else if (port == 0) {
- port = 67;
+ port = DHCP6_CLIENT_PORT;
+ } else if (options.getIpVersion() == 4) {
+ port = 67; // TODO: find out why port 68 is wrong here.
}
}
if (options.getIpVersion() == 6) {
}
}
}
+
return(sock);
}
+void
+TestControl::printStats() const {
+ CommandOptions& options = CommandOptions::instance();
+ if (options.getIpVersion() == 4) {
+ if (!stats_mgr4_) {
+ isc_throw(InvalidOperation, "Statistics Manager for DHCPv4 "
+ "hasn't been initialized");
+ }
+ stats_mgr4_->printStats();
+ } else if (options.getIpVersion() == 6) {
+ if (!stats_mgr6_) {
+ isc_throw(InvalidOperation, "Statistics Manager for DHCPv6 "
+ "hasn't been initialized");
+ }
+ stats_mgr6_->printStats();
+ }
+}
+
+void
+TestControl::receivePacket4(Pkt4Ptr& pkt4) {
+ switch(pkt4->getType()) {
+ case DHCPOFFER :
+ stats_mgr4_->passRcvdPacket(StatsMgr4::XCHG_DO, pkt4);
+ break;
+ case DHCPACK :
+ stats_mgr4_->passRcvdPacket(StatsMgr4::XCHG_RA, pkt4);
+ break;
+ default:
+ isc_throw(BadValue, "unknown type " << pkt4->getType()
+ << " of received DHCPv4 packet");
+ }
+}
+
+void
+TestControl::receivePacket6(Pkt6Ptr& pkt6) {
+ switch(pkt6->getType()) {
+ case DHCPV6_ADVERTISE :
+ stats_mgr6_->passRcvdPacket(StatsMgr6::XCHG_SA, pkt6);
+ break;
+ case DHCPV6_REPLY :
+ stats_mgr6_->passRcvdPacket(StatsMgr6::XCHG_RR, pkt6);
+ break;
+ default:
+ isc_throw(BadValue, "unknown type " << pkt6->getType()
+ << " of received DHCPv6 packet");
+ }
+
+}
+
void
TestControl::receivePackets() {
int timeout = 0;
if (!pkt4) {
receiving = false;
} else {
- // TODO: replace this with use of StatsMgr to increase
- // number of received packets. This can be done once
- // the 1958 ticket is reviewed and checked-in.
- std::cout << "Received packet" << std::endl;
+ pkt4->unpack();
+ receivePacket4(pkt4);
}
} else if (CommandOptions::instance().getIpVersion() == 6) {
Pkt6Ptr pkt6 = IfaceMgr::instance().receive6(timeout);
if (!pkt6) {
receiving = false;
} else {
- std::cout << "Received DHCPv6 packet" << std::endl;
+ if (pkt6->unpack()) {
+ receivePacket6(pkt6);
+ }
}
}
}
}
registerOptionFactories();
TestControlSocket socket(openSocket());
+
+ initializeStatsMgr();
uint64_t packets_sent = 0;
for (;;) {
updateSendDue();
sendSolicit6(socket);
}
++packets_sent;
- cout << "Packets sent " << packets_sent << endl;
}
}
+ printStats();
}
void
// 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());
+ const uint32_t transid = static_cast<uint32_t>(random() % 0x00FFFFFF);
boost::shared_ptr<Pkt4> pkt4(new Pkt4(DHCPDISCOVER, transid));
if (!pkt4) {
isc_throw(Unexpected, "failed to create DISCOVER packet");
setDefaults4(socket, pkt4);
pkt4->pack();
IfaceMgr::instance().send(pkt4);
+ if (!stats_mgr4_) {
+ isc_throw(InvalidOperation, "Statistics Manager for DHCPv4 "
+ "hasn't been initialized");
+ }
+ stats_mgr4_->passSentPacket(StatsMgr4::XCHG_DO, pkt4);
}
void
// 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());
+ const uint32_t transid = static_cast<uint32_t>(random() % 0x00FFFFFF);
boost::shared_ptr<Pkt6> pkt6(new Pkt6(DHCPV6_SOLICIT, transid));
if (!pkt6) {
isc_throw(Unexpected, "failed to create SOLICIT packet");
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_SA, pkt6);
}
void
#include <vector>
#include <boost/noncopyable.hpp>
+#include <boost/shared_ptr.hpp>
#include <boost/date_time/posix_time/posix_time.hpp>
#include <dhcp/dhcp6.h>
#include <dhcp/pkt4.h>
#include <dhcp/pkt6.h>
+#include "stats_mgr.h"
+
namespace isc {
namespace perfdhcp {
class TestControl : public boost::noncopyable {
public:
+ // Statistics Manager for DHCPv4.
+ typedef StatsMgr<dhcp::Pkt4> StatsMgr4;
+ // Pointer to Statistics Manager for DHCPv4;
+ typedef boost::shared_ptr<StatsMgr4> StatsMgr4Ptr;
+ // Statictics Manager for DHCPv6.
+ typedef StatsMgr<dhcp::Pkt6> StatsMgr6;
+ // Pointer to Statistics Manager for DHCPv6.
+ typedef boost::shared_ptr<StatsMgr6> StatsMgr6Ptr;
+
/// \brief Socket wrapper class.
///
/// This is wrapper class that holds descriptor of the socket
/// \return true if any of the exit conditions is fulfiled.
bool checkExitConditions() const;
-
/// \brief Factory function to create DHCPv6 ELAPSED_TIME option.
///
/// This factory function creates DHCPv6 ELAPSED_TIME option instance.
/// \return number of exchanges to be started immediatelly.
uint64_t getNextExchangesNum() const;
+ /// \brief Initializes Statistics Manager.
+ ///
+ /// This function initializes Statistics Manager. If there is
+ /// the one initialized already it is released.
+ void initializeStatsMgr();
+
/// \brief Open socket to communicate with DHCP server.
///
/// Method opens socket and binds it to local address. Function will
/// \return socket descriptor.
int openSocket(uint16_t port = 0) const;
+ /// \brief Print performance statistics.
+ ///
+ /// Method prints performance statistics.
+ /// \throws isc::InvalidOperation if Statistics Manager was
+ /// not initialized.
+ void printStats() const;
+
+ void receivePacket4(dhcp::Pkt4Ptr& pkt4);
+
+ void receivePacket6(dhcp::Pkt6Ptr& pkt4);
+
/// \brief Receive DHCPv4 or DHCPv6 packets from the server.
///
/// Method receives DHCPv4 or DHCPv6 packets from the server.
boost::posix_time::ptime last_sent_; ///< Indicates when the last exchange
/// was initiated.
+ StatsMgr4Ptr stats_mgr4_; /// Statistics Manager 4.
+ StatsMgr6Ptr stats_mgr6_; /// Statistics Manager 6.
+
uint64_t sent_packets_0_;
uint64_t sent_packets_1_;
};