17#include <boost/foreach.hpp>
34 switch (exchange_type) {
47 "unrecognized exchange type '" << exchange_type <<
"'");
55 return(os <<
"DISCOVER-OFFER");
57 return(os <<
"REQUEST-ACK");
59 return(os <<
"REQUEST-ACK (renewal)");
61 return(os <<
"RELEASE");
63 return(os <<
"SOLICIT-ADVERTISE");
65 return(os <<
"REQUEST-REPLY");
67 return(os <<
"RENEW-REPLY");
69 return(os <<
"RELEASE-REPLY");
71 return(os <<
"Unknown exchange type");
77 const double drop_time,
78 const bool archive_enabled,
79 const boost::posix_time::ptime boot_time)
80 : xchg_type_(xchg_type),
84 archive_enabled_(archive_enabled),
85 drop_time_(drop_time),
86 min_delay_(std::numeric_limits<double>::max()),
89 sum_delay_squared_(0.),
92 unordered_lookup_size_sum_(0),
93 unordered_lookups_(0),
97 non_unique_addr_num_(0),
98 rejected_leases_num_(0),
101 next_sent_ = sent_packets_.begin();
106 const PktPtr& rcvd_packet) {
114 boost::posix_time::ptime sent_time = sent_packet->getTimestamp();
115 boost::posix_time::ptime rcvd_time = rcvd_packet->getTimestamp();
117 if (sent_time.is_not_a_date_time() ||
118 rcvd_time.is_not_a_date_time()) {
120 "Timestamp must be set for sent and "
121 "received packet to measure RTT,"
122 <<
" sent: " << sent_time
123 <<
" recv: " << rcvd_time);
125 boost::posix_time::time_period period(sent_time, rcvd_time);
130 static_cast<double>(period.length().total_nanoseconds()) / 1e9;
134 "greater than received packet's timestamp in "
135 << xchg_type_ <<
".\nTime difference: "
136 << delta <<
", sent: " << sent_time <<
", rcvd: "
137 << rcvd_time <<
".\nTrans ID: " << sent_packet->getTransid()
142 if (delta < min_delay_) {
146 if (delta > max_delay_) {
152 sum_delay_squared_ += delta * delta;
157 using namespace boost::posix_time;
163 if (sent_packets_.size() == 0) {
170 }
else if (next_sent_ == sent_packets_.end()) {
174 next_sent_ = sent_packets_.begin();
179 bool packet_found =
false;
186 if ((*next_sent_)->getTransid() == rcvd_packet->getTransid()) {
201 std::pair<PktListTransidHashIterator,PktListTransidHashIterator> p =
208 ++unordered_lookups_;
212 unordered_lookup_size_sum_ += std::distance(p.first, p.second);
213 bool non_expired_found =
false;
224 if (!packet_found && ((*it)->getTransid() == rcvd_packet->getTransid())) {
226 next_sent_ = sent_packets_.template project<0>(it);
229 if (!non_expired_found) {
232 ptime now = microsec_clock::universal_time();
233 ptime packet_time = (*it)->getTimestamp();
234 time_period packet_period(packet_time, now);
235 if (!packet_period.is_null()) {
236 double period_fractional =
237 packet_period.length().total_seconds() +
238 (
static_cast<double>(packet_period.length().fractional_seconds())
239 / packet_period.length().ticks_per_second());
240 if (drop_time_ > 0 && (period_fractional > drop_time_)) {
249 non_expired_found =
true;
256 if (non_expired_found && packet_found) {
262 while (!to_remove.empty()) {
271 if (sent_packets_.template project<0>(it) != next_sent_) {
272 eraseSent(sent_packets_.template project<0>(it));
274 next_sent_ = eraseSent(sent_packets_.template project<0>(it));
277 packet_found =
false;
293 PktPtr sent_packet(*next_sent_);
297 next_sent_ = eraseSent(next_sent_);
306 if (!archive_enabled_) {
308 "packets archive mode is disabled");
310 if (rcvd_packets_num_ == 0) {
311 std::cout <<
"Unavailable! No packets received." << std::endl;
314 using namespace boost::posix_time;
317 for (
auto const& it : rcvd_packets_) {
320 archived_packets_.template get<1>();
324 BOOST_FOREACH(
auto const& it_archived, p) {
325 if (it_archived->getTransid() == rcvd_packet->getTransid()) {
326 PktPtr sent_packet = it_archived;
328 ptime sent_time = sent_packet->getTimestamp();
329 ptime rcvd_time = rcvd_packet->getTimestamp();
333 if (sent_time.is_not_a_date_time() ||
334 rcvd_time.is_not_a_date_time()) {
336 "packet time is not set");
339 time_period sent_period(boot_time_, sent_time);
340 time_period rcvd_period(boot_time_, rcvd_time);
342 std::cout <<
"sent / received: "
343 << to_iso_string(sent_period.length())
345 << to_iso_string(rcvd_period.length())
355 boot_time_(
boost::posix_time::microsec_clock::universal_time())
363 addExchangeStats(ExchangeType::DO, options.getDropTime()[0]);
364 if (options.getExchangeMode() == CommandOptions::DORA_SARR) {
365 addExchangeStats(ExchangeType::RA, options.getDropTime()[1]);
368 addExchangeStats(ExchangeType::RNA);
371 addExchangeStats(ExchangeType::RLA);
373 }
else if (options.getIpVersion() == 6) {
374 addExchangeStats(ExchangeType::SA, options.getDropTime()[0]);
375 if (options.getExchangeMode() == CommandOptions::DORA_SARR) {
376 addExchangeStats(ExchangeType::RR, options.getDropTime()[1]);
378 if (options.getRenewRate() != 0) {
379 addExchangeStats(ExchangeType::RN);
381 if (options.getReleaseRate() != 0) {
382 addExchangeStats(ExchangeType::RL);
385 if (options.testDiags(
'i')) {
386 addCustomCounter(
"shortwait",
"Short waits for packets");
391ExchangeStats::receivedLeases()
const {
395 std::stringstream result;
397 for (
PktPtr const& packet : rcvd_packets_) {
402 packet->getOption(DHO_DHCP_CLIENT_IDENTIFIER));
403 if (client_id_option) {
404 result << TestControl::vector2Hex(client_id_option->getData());
408 if (client_id_option) {
409 result <<
DUID(client_id_option->getData()).
toText();
418 Pkt4Ptr const& packet4(boost::dynamic_pointer_cast<Pkt4>(packet));
420 result << packet4->getYiaddr().toText();
426 boost::dynamic_pointer_cast<Option6IAAddr>(
429 result << iaaddr->getAddress().toText();
439 boost::dynamic_pointer_cast<Option6IAPrefix>(
442 result << iaprefix->getAddress().toText();
453ExchangeStats::printLeases()
const {
454 std::cout << receivedLeases() << std::endl;
457void StatsMgr::printLeases()
const {
458 for (
auto const& exchange : exchanges_) {
459 std::cout <<
"***Leases for " << exchange.first <<
"***" << std::endl;
460 std::cout <<
"client_id,adrress,prefix" << std::endl;
461 exchange.second->printLeases();
462 std::cout << std::endl;
466int ExchangeStats::malformed_pkts_{0};
A generic exception that is thrown if a parameter given to a method is considered invalid in that con...
A generic exception that is thrown if a function is called in a prohibited way.
A generic exception that is thrown when an unexpected error condition occurs.
Holds DUID (DHCPv6 Unique Identifier)
std::string toText() const
Returns textual representation of the identifier (e.g.
Class that represents IAPREFIX option in DHCPv6.
Represents DHCPv4 packet.
bool testDiags(const char diag)
Find if diagnostic flag has been set.
int getRenewRate() const
Returns a rate at which DHCPv6 Renew messages are sent.
uint8_t getIpVersion() const
Returns IP version.
int getReleaseRate() const
Returns a rate at which DHCPv6 Release messages are sent.
static uint32_t hashTransid(const dhcp::PktPtr &packet)
Hash transaction id of the packet.
std::queue< PktListTransidHashIterator > PktListRemovalQueue
Packet list iterator queue for removal.
void printTimestamps()
Print timestamps for sent and received packets.
PktListTransidHashIndex::const_iterator PktListTransidHashIterator
Packet list iterator to access packets using transaction id hash.
PktList::template nth_index< 1 >::type PktListTransidHashIndex
Packet list index to search packets using transaction id hash.
dhcp::PktPtr matchPackets(const dhcp::PktPtr &rcvd_packet)
Match received packet with the corresponding sent packet.
void updateDelays(const dhcp::PktPtr &sent_packet, const dhcp::PktPtr &rcvd_packet)
Update delay counters.
StatsMgr(CommandOptions &options)
Constructor.
#define isc_throw(type, stream)
A shortcut macro to insert known values into exception arguments.
boost::shared_ptr< isc::dhcp::Pkt > PktPtr
A pointer to either Pkt4 or Pkt6 packet.
@ DHO_DHCP_CLIENT_IDENTIFIER
boost::shared_ptr< Pkt4 > Pkt4Ptr
A pointer to Pkt4 object.
boost::shared_ptr< Option6IAPrefix > Option6IAPrefixPtr
Pointer to the Option6IAPrefix object.
boost::shared_ptr< Option6IAAddr > Option6IAAddrPtr
A pointer to the isc::dhcp::Option6IAAddr object.
boost::shared_ptr< Option > OptionPtr
int dhcpVersion(ExchangeType const exchange_type)
Get the DHCP version that fits the exchange type.
ExchangeType
DHCP packet exchange types.
@ SA
DHCPv6 SOLICIT-ADVERTISE.
@ RNA
DHCPv4 REQUEST-ACK (renewal)
@ RL
DHCPv6 RELEASE-REPLY.
@ DO
DHCPv4 DISCOVER-OFFER.
@ RR
DHCPv6 REQUEST-REPLY.
std::ostream & operator<<(std::ostream &os, ExchangeType xchg_type)
Return name of the exchange.
Defines the logger used by the top-level component of kea-lfc.