14 #include <boost/noncopyable.hpp> 15 #include <boost/shared_ptr.hpp> 16 #include <boost/multi_index_container.hpp> 17 #include <boost/multi_index/ordered_index.hpp> 18 #include <boost/multi_index/sequenced_index.hpp> 19 #include <boost/multi_index/global_fun.hpp> 20 #include <boost/multi_index/mem_fun.hpp> 21 #include <boost/date_time/posix_time/posix_time.hpp> 47 template <
class T = dhcp::Pkt4>
79 return (this_counter);
92 uint64_t
getValue()
const {
return(counter_); }
99 const std::string&
getName()
const {
return(name_); }
149 return(packet->getTransid() & 1023);
220 typedef boost::multi_index_container<
222 boost::shared_ptr<T>,
224 boost::multi_index::indexed_by<
227 boost::multi_index::sequenced<>,
232 boost::multi_index::ordered_non_unique<
236 boost::multi_index::global_fun<
239 const boost::shared_ptr<T>&,
252 typedef typename PktList::template nth_index<1>::type
255 typedef typename PktListTransidHashIndex::const_iterator
258 typedef typename std::queue<PktListTransidHashIterator>
270 const double drop_time,
271 const bool archive_enabled,
272 const boost::posix_time::ptime boot_time)
273 : xchg_type_(xchg_type),
277 archive_enabled_(archive_enabled),
278 drop_time_(drop_time),
279 min_delay_(std::numeric_limits<double>::max()),
282 sum_delay_squared_(0.),
285 unordered_lookup_size_sum_(0),
286 unordered_lookups_(0),
288 sent_packets_num_(0),
289 rcvd_packets_num_(0),
290 boot_time_(boot_time)
292 next_sent_ = sent_packets_.begin();
306 sent_packets_.template get<0>().push_back(packet);
319 rcvd_packets_.push_back(packet);
332 const boost::shared_ptr<T>& rcvd_packet) {
340 boost::posix_time::ptime sent_time = sent_packet->getTimestamp();
341 boost::posix_time::ptime rcvd_time = rcvd_packet->getTimestamp();
343 if (sent_time.is_not_a_date_time() ||
344 rcvd_time.is_not_a_date_time()) {
346 "Timestamp must be set for sent and " 347 "received packet to measure RTT");
349 boost::posix_time::time_period period(sent_time, rcvd_time);
354 static_cast<double>(period.length().total_nanoseconds()) / 1e9;
358 "greater than received packet's timestamp");
362 if (delta < min_delay_) {
366 if (delta > max_delay_) {
372 sum_delay_squared_ += delta * delta;
392 using namespace boost::posix_time;
398 if (sent_packets_.size() == 0) {
404 return(boost::shared_ptr<T>());
405 }
else if (next_sent_ == sent_packets_.end()) {
409 next_sent_ = sent_packets_.begin();
414 bool packet_found =
false;
421 if ((*next_sent_)->getTransid() == rcvd_packet->getTransid()) {
436 std::pair<PktListTransidHashIterator,PktListTransidHashIterator> p =
443 ++unordered_lookups_;
447 unordered_lookup_size_sum_ += std::distance(p.first, p.second);
448 bool non_expired_found =
false;
460 if (!packet_found && ((*it)->getTransid() == rcvd_packet->getTransid())) {
462 next_sent_ = sent_packets_.template project<0>(it);
465 if (!non_expired_found) {
468 ptime now = microsec_clock::universal_time();
469 ptime packet_time = (*it)->getTimestamp();
470 time_period packet_period(packet_time, now);
471 if (!packet_period.is_null()) {
472 double period_fractional =
473 packet_period.length().total_seconds() +
474 (static_cast<double>(packet_period.length().fractional_seconds())
475 / packet_period.length().ticks_per_second());
476 if (drop_time_ > 0 && (period_fractional > drop_time_)) {
485 non_expired_found =
true;
492 if (non_expired_found && packet_found) {
498 while (!to_remove.empty()) {
507 if (sent_packets_.template project<0>(it) != next_sent_) {
508 eraseSent(sent_packets_.template project<0>(it));
510 next_sent_ = eraseSent(sent_packets_.template project<0>(it));
513 packet_found =
false;
523 return(boost::shared_ptr<T>());
529 boost::shared_ptr<T> sent_packet(*next_sent_);
533 next_sent_ = eraseSent(next_sent_);
561 if (rcvd_packets_num_ == 0) {
564 return(sum_delay_ / rcvd_packets_num_);
578 if (rcvd_packets_num_ == 0) {
581 return(sqrt(sum_delay_squared_ / rcvd_packets_num_ -
615 if (unordered_lookups_ == 0) {
618 return(static_cast<double>(unordered_lookup_size_sum_) /
619 static_cast<double>(unordered_lookups_));
701 cout << fixed << setprecision(3)
702 <<
"min delay: " <<
getMinDelay() * 1e3 <<
" ms" << endl
703 <<
"avg delay: " <<
getAvgDelay() * 1e3 <<
" ms" << endl
704 <<
"max delay: " <<
getMaxDelay() * 1e3 <<
" ms" << endl
709 cout <<
"Delay summary unavailable! No packets received." << endl;
726 if (!archive_enabled_) {
728 "packets archive mode is disabled");
730 if (rcvd_packets_num_ == 0) {
731 std::cout <<
"Unavailable! No packets received." << std::endl;
734 using namespace boost::posix_time;
738 it != rcvd_packets_.end();
740 boost::shared_ptr<T> rcvd_packet = *it;
742 archived_packets_.template get<1>();
747 it_archived != p.second;
749 if ((*it_archived)->getTransid() ==
750 rcvd_packet->getTransid()) {
751 boost::shared_ptr<T> sent_packet = *it_archived;
753 ptime sent_time = sent_packet->getTimestamp();
754 ptime rcvd_time = rcvd_packet->getTimestamp();
758 if (sent_time.is_not_a_date_time() ||
759 rcvd_time.is_not_a_date_time()) {
761 "packet time is not set");
764 time_period sent_period(boot_time_, sent_time);
765 time_period rcvd_period(boot_time_, rcvd_time);
767 std::cout <<
"sent / received: " 768 << to_iso_string(sent_period.length())
770 << to_iso_string(rcvd_period.length())
794 if (archive_enabled_) {
801 archived_packets_.push_back(*it);
805 return(sent_packets_.template get<0>().erase(it));
834 bool archive_enabled_;
845 double sum_delay_squared_;
858 uint64_t unordered_lookup_size_sum_;
860 uint64_t unordered_lookups_;
861 uint64_t ordered_lookups_;
865 uint64_t sent_packets_num_;
866 uint64_t rcvd_packets_num_;
867 boost::posix_time::ptime boot_time_;
873 typedef typename std::map<ExchangeType, ExchangeStatsPtr>
ExchangesMap;
896 archive_enabled_(archive_enabled),
897 boot_time_(
boost::posix_time::microsec_clock::universal_time()) {
911 const double drop_time = -1) {
912 if (exchanges_.find(xchg_type) != exchanges_.end()) {
915 exchanges_[xchg_type] =
933 return (exchanges_.find(xchg_type) != exchanges_.end());
944 const std::string& long_name) {
945 if (custom_counters_.find(short_name) != custom_counters_.end()) {
947 "Custom counter " << short_name <<
" already added.");
949 custom_counters_[short_name] =
958 it != exchanges_.end();
960 if (it->second->getDroppedPacketsNum() > 0) {
976 if (it == custom_counters_.end()) {
978 "Custom counter " << counter_key <<
"does not exist");
991 const uint64_t value = 1) {
1008 const boost::shared_ptr<T>& packet) {
1010 xchg_stats->appendSent(packet);
1026 boost::shared_ptr<T>
1028 const boost::shared_ptr<T>& packet) {
1030 boost::shared_ptr<T> sent_packet
1031 = xchg_stats->matchPackets(packet);
1034 xchg_stats->updateDelays(sent_packet, packet);
1035 if (archive_enabled_) {
1036 xchg_stats->appendRcvd(packet);
1039 return(sent_packet);
1052 return(xchg_stats->getMinDelay());
1065 return(xchg_stats->getMaxDelay());
1076 return(xchg_stats->getAvgDelay());
1087 return(xchg_stats->getStdDevDelay());
1100 return(xchg_stats->getOrphans());
1114 return(xchg_stats->getAvgUnorderedLookupSetSize());
1129 return(xchg_stats->getUnorderedLookups());
1145 return(xchg_stats->getOrderedLookups());
1158 return(xchg_stats->getSentPacketsNum());
1171 return(xchg_stats->getRcvdPacketsNum());
1184 return(xchg_stats->getDroppedPacketsNum());
1199 return(xchg_stats->getCollectedNum());
1211 using namespace boost::posix_time;
1212 time_period test_period(boot_time_,
1213 microsec_clock::universal_time());
1227 return(
"DISCOVER-OFFER");
1229 return(
"REQUEST-ACK");
1231 return(
"REQUEST-ACK (renewal)");
1233 return(
"SOLICIT-ADVERTISE");
1235 return(
"REQUEST-REPLY");
1237 return(
"RENEW-REPLY");
1239 return(
"RELEASE-REPLY");
1241 return(
"Unknown exchange type");
1259 if (exchanges_.empty()) {
1261 "no exchange type added for tracking");
1264 it != exchanges_.end();
1268 <<
"***" << std::endl;
1269 xchg_stats->printMainStats();
1270 std::cout << std::endl;
1271 xchg_stats->printRTTStats();
1272 std::cout << std::endl;
1282 std::ostringstream stream_sent;
1283 std::ostringstream stream_rcvd;
1284 std::ostringstream stream_drops;
1285 std::string sep(
"");
1287 it != exchanges_.end(); ++it) {
1289 if (it != exchanges_.begin()) {
1292 stream_sent << sep << it->second->getSentPacketsNum();
1293 stream_rcvd << sep << it->second->getRcvdPacketsNum();
1294 stream_drops << sep << it->second->getDroppedPacketsNum();
1296 std::cout <<
"sent: " << stream_sent.str()
1297 <<
"; received: " << stream_rcvd.str()
1298 <<
"; drops: " << stream_drops.str()
1314 if (exchanges_.empty()) {
1316 "no exchange type added for tracking");
1319 it != exchanges_.end();
1322 std::cout <<
"***Timestamps for packets: " 1324 <<
"***" << std::endl;
1325 xchg_stats->printTimestamps();
1326 std::cout << std::endl;
1337 if (custom_counters_.empty()) {
1341 it != custom_counters_.end();
1344 std::cout << counter->getName() <<
": " << counter->getValue()
1360 if (it == exchanges_.end()) {
1378 bool archive_enabled_;
1380 boost::posix_time::ptime boot_time_;
1386 #endif // STATS_MGR_H void passSentPacket(const ExchangeType xchg_type, const boost::shared_ptr< T > &packet)
Adds new packet to the sent packets list.
uint64_t getRcvdPacketsNum() const
Return total number of received packets.
boost::shared_ptr< T > matchPackets(const boost::shared_ptr< T > &rcvd_packet)
Match received packet with the corresponding sent packet.
void printTimestamps() const
Print timestamps of all packets.
bool droppedPackets() const
Check if any packet drops occurred.
const CustomCounter & incrementCounter(const std::string &counter_key, const uint64_t value=1)
Increment specified counter.
double getMaxDelay() const
Return maximum delay between sent and received packet.
uint64_t getUnorderedLookups() const
Return number of unordered sent packets lookups.
static uint32_t hashTransid(const boost::shared_ptr< T > &packet)
Hash transaction id of the packet.
CustomCounter(const std::string &name)
Constructor.
std::queue< PktListTransidHashIterator > PktListRemovalQueue
Packet list iterator queue for removal.
ExchangeType
DHCP packet exchange types.
boost::posix_time::time_period getTestPeriod() const
Get time period since the start of test.
const CustomCounter & operator+=(int val)
uint64_t getOrderedLookups(const ExchangeType xchg_type) const
Return number of ordered sent packets lookups.
uint64_t getUnorderedLookups(const ExchangeType xchg_type) const
Return number of unordered sent packets lookups.
double getAvgDelay() const
Return average packet delay.
uint64_t getCollectedNum() const
Return number of garbage collected packets.
boost::shared_ptr< CustomCounter > CustomCounterPtr
static std::string exchangeToString(ExchangeType xchg_type)
Return name of the exchange.
PktListTransidHashIndex::const_iterator PktListTransidHashIterator
Packet list iterator to access packets using transaction id hash.
uint64_t getValue() const
Return counter value.
void appendRcvd(const boost::shared_ptr< T > &packet)
Add new packet to list of received packets.
#define isc_throw(type, stream)
A shortcut macro to insert known values into exception arguments.
A generic exception that is thrown if a parameter given to a method is considered invalid in that con...
uint64_t getCollectedNum(const ExchangeType xchg_type) const
Return number of garbage collected packets.
double getStdDevDelay() const
Return standard deviation of packet delay.
bool hasExchangeStats(const ExchangeType xchg_type) const
Check if the exchange type has been specified.
void printIntermediateStats() const
Print intermediate statistics.
A generic exception that is thrown when an unexpected error condition occurs.
uint64_t getSentPacketsNum(const ExchangeType xchg_type) const
Return total number of sent packets.
uint64_t getOrderedLookups() const
Return number of ordered sent packets lookups.
void printRTTStats() const
Print round trip time packets statistics.
uint64_t getRcvdPacketsNum(const ExchangeType xchg_type) const
Return total number of received packets.
double getAvgUnorderedLookupSetSize() const
Return average unordered lookup set size.
double getMaxDelay(const ExchangeType xchg_type) const
Return maximum delay between sent and received packet.
CustomCountersMap::const_iterator CustomCountersMapIterator
Iterator for CustomCountersMap.
double getMinDelay(const ExchangeType xchg_type) const
Return minimum delay between sent and received packet.
void printTimestamps()
Print timestamps for sent and received packets.
std::map< std::string, CustomCounterPtr > CustomCountersMap
Map containing custom counters.
ExchangeStats(const ExchangeType xchg_type, const double drop_time, const bool archive_enabled, const boost::posix_time::ptime boot_time)
Constructor.
This is a base class for exceptions thrown from the DNS library module.
const CustomCounter & operator++()
Increment operator.
Defines the logger used by the top-level component of kea-dhcp-ddns.
void printMainStats() const
Print main statistics for packet exchange.
void printCustomCounters() const
Print names and values of custom counters.
void printStats() const
Print statistics counters for all exchange types.
A generic exception that is thrown if a function is called in a prohibited way.
ExchangesMap::const_iterator ExchangesMapIterator
Iterator pointing to ExchangesMap.
boost::multi_index_container< boost::shared_ptr< T >, boost::multi_index::indexed_by< boost::multi_index::sequenced<>, boost::multi_index::ordered_non_unique< boost::multi_index::global_fun< const boost::shared_ptr< T > &, uint32_t, &ExchangeStats::hashTransid > > > > PktList
List of packets (sent or received).
double getMinDelay() const
Return minimum delay between sent and received packet.
PktList::template nth_index< 1 >::type PktListTransidHashIndex
Packet list index to search packets using transaction id hash.
uint64_t getOrphans(const ExchangeType xchg_type) const
Return number of orphan packets.
double getAvgDelay(const ExchangeType xchg_type) const
Return average packet delay.
void addExchangeStats(const ExchangeType xchg_type, const double drop_time=-1)
Specify new exchange type.
CustomCounterPtr getCounter(const std::string &counter_key)
Return specified counter.
void updateDelays(const boost::shared_ptr< T > &sent_packet, const boost::shared_ptr< T > &rcvd_packet)
Update delay counters.
uint64_t getDroppedPacketsNum(const ExchangeType xchg_type) const
Return total number of dropped packets.
boost::shared_ptr< T > passRcvdPacket(const ExchangeType xchg_type, const boost::shared_ptr< T > &packet)
Add new received packet and match with sent packet.
const std::string & getName() const
Return counter name.
PktList::iterator PktListIterator
Packet list iterator for sequential access to elements.
const CustomCounter & operator++(int)
Increment operator.
boost::shared_ptr< ExchangeStats > ExchangeStatsPtr
Pointer to ExchangeStats.
void appendSent(const boost::shared_ptr< T > &packet)
Add new packet to list of sent packets.
double getStdDevDelay(const ExchangeType xchg_type) const
Return standard deviation of packet delay.
DHCPv6 SOLICIT-ADVERTISE.
uint64_t getSentPacketsNum() const
Return total number of sent packets.
double getAvgUnorderedLookupSetSize(const ExchangeType xchg_type) const
Return average unordered lookup set size.
void addCustomCounter(const std::string &short_name, const std::string &long_name)
Add named custom uint64 counter.
uint64_t getOrphans() const
Return number of orphan packets.
std::map< ExchangeType, ExchangeStatsPtr > ExchangesMap
Map containing all specified exchange types.
uint64_t getDroppedPacketsNum() const
Return number of dropped packets.
StatsMgr(const bool archive_enabled=false)
Constructor.
DHCPv4 REQUEST-ACK (renewal)