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