src: Implement packet statistics collection
refs: #2955, #2956
Change-Id: I57476a63562dbd378e566ad0280c89ccc5883e3e
diff --git a/src/hello-protocol.cpp b/src/hello-protocol.cpp
index 4a995de..2e17e16 100644
--- a/src/hello-protocol.cpp
+++ b/src/hello-protocol.cpp
@@ -19,9 +19,9 @@
*
**/
+#include "hello-protocol.hpp"
#include "nlsr.hpp"
#include "lsdb.hpp"
-#include "hello-protocol.hpp"
#include "utility/name-helper.hpp"
#include "logger.hpp"
@@ -47,6 +47,9 @@
this, _1),
std::bind(&HelloProtocol::processInterestTimedOut,
this, _1));
+
+ // increment SENT_HELLO_INTEREST
+ hpIncrementSignal(Statistics::PacketType::SENT_HELLO_INTEREST);
}
void
@@ -85,12 +88,17 @@
{
// interest name: /<neighbor>/NLSR/INFO/<router>
const ndn::Name interestName = interest.getName();
+
+ // increment RCV_HELLO_INTEREST
+ hpIncrementSignal(Statistics::PacketType::RCV_HELLO_INTEREST);
+
_LOG_DEBUG("Interest Received for Name: " << interestName);
if (interestName.get(-2).toUri() != INFO_COMPONENT) {
_LOG_DEBUG("INFO_COMPONENT not found or interestName: " << interestName
<< " does not match expression");
return;
}
+
ndn::Name neighbor;
neighbor.wireDecode(interestName.get(-1).blockFromValue());
_LOG_DEBUG("Neighbor: " << neighbor);
@@ -103,6 +111,8 @@
m_nlsr.getKeyChain().sign(*data, m_nlsr.getDefaultCertName());
_LOG_DEBUG("Sending out data for name: " << interest.getName());
m_nlsr.getNlsrFace().put(*data);
+ // increment SENT_HELLO_DATA
+ hpIncrementSignal(Statistics::PacketType::SENT_HELLO_DATA);
auto adjacent = m_nlsr.getAdjacencyList().findAdjacent(neighbor);
// If this neighbor was previously inactive, send our own hello interest, too
@@ -209,6 +219,8 @@
}
}
}
+ // increment RCV_HELLO_DATA
+ hpIncrementSignal(Statistics::PacketType::RCV_HELLO_DATA);
}
// Simply logs a debug message that the content could not be
diff --git a/src/hello-protocol.hpp b/src/hello-protocol.hpp
index 808b843..dbc12d0 100644
--- a/src/hello-protocol.hpp
+++ b/src/hello-protocol.hpp
@@ -22,8 +22,10 @@
#ifndef NLSR_HELLO_PROTOCOL_HPP
#define NLSR_HELLO_PROTOCOL_HPP
+#include "statistics.hpp"
#include "test-access-control.hpp"
+#include <ndn-cxx/util/signal.hpp>
#include <ndn-cxx/face.hpp>
#include <ndn-cxx/mgmt/nfd/control-parameters.hpp>
#include <ndn-cxx/mgmt/nfd/control-response.hpp>
@@ -93,6 +95,8 @@
void
processInterest(const ndn::Name& name, const ndn::Interest& interest);
+ ndn::util::signal::Signal<HelloProtocol, Statistics::PacketType> hpIncrementSignal;
+
private:
void
processInterestTimedOut(const ndn::Interest& interest);
diff --git a/src/lsdb.cpp b/src/lsdb.cpp
index b71b48e..5cfc783 100644
--- a/src/lsdb.cpp
+++ b/src/lsdb.cpp
@@ -29,8 +29,6 @@
#include <ndn-cxx/security/signing-helpers.hpp>
#include <ndn-cxx/util/segment-fetcher.hpp>
-#include <string>
-
namespace nlsr {
INIT_LOGGER("Lsdb");
@@ -961,6 +959,9 @@
Lsdb::expressInterest(const ndn::Name& interestName, uint32_t timeoutCount,
steady_clock::TimePoint deadline)
{
+ // increment SENT_LSA_INTEREST
+ lsaIncrementSignal(Statistics::PacketType::SENT_LSA_INTEREST);
+
if (deadline == DEFAULT_LSA_RETRIEVAL_DEADLINE) {
deadline = steady_clock::now() + ndn::time::seconds(static_cast<int>(LSA_REFRESH_TIME_MAX));
}
@@ -991,11 +992,28 @@
std::bind(&Lsdb::afterFetchLsa, this, _1, interestName),
std::bind(&Lsdb::onFetchLsaError, this, _1, _2, interestName,
timeoutCount, deadline, lsaName, seqNo));
+ // increment a specific SENT_LSA_INTEREST
+ std::string typeLSA = interestName[-2].toUri();
+ if (typeLSA == AdjLsa::TYPE_STRING) {
+ lsaIncrementSignal(Statistics::PacketType::SENT_ADJ_LSA_INTEREST);
+ }
+ else if (typeLSA == CoordinateLsa::TYPE_STRING) {
+ lsaIncrementSignal(Statistics::PacketType::SENT_COORD_LSA_INTEREST);
+ }
+ else if (typeLSA == NameLsa::TYPE_STRING) {
+ lsaIncrementSignal(Statistics::PacketType::SENT_NAME_LSA_INTEREST);
+ }
+ else {
+ _LOG_ERROR("typeLSA " + typeLSA + " not recognized; failed Statistics::PacketType conversion");
+ }
}
void
Lsdb::processInterest(const ndn::Name& name, const ndn::Interest& interest)
{
+ // increment RCV_LSA_INTEREST
+ lsaIncrementSignal(Statistics::PacketType::RCV_LSA_INTEREST);
+
const ndn::Name& interestName(interest.getName());
_LOG_DEBUG("Interest received for LSA: " << interestName);
@@ -1014,7 +1032,6 @@
std::string interestedLsType = interestName[-2].toUri();
- // Passes the Interest off to the appropriate subprocessor
if (interestedLsType == NameLsa::TYPE_STRING) {
processInterestForNameLsa(interest, originRouter.append(interestedLsType), seqNo);
}
@@ -1027,6 +1044,7 @@
else {
_LOG_WARN("Received unrecognized LSA type: " << interestedLsType);
}
+ lsaIncrementSignal(Statistics::PacketType::SENT_LSA_DATA);
}
}
@@ -1056,13 +1074,16 @@
const ndn::Name& lsaKey,
uint64_t seqNo)
{
-
+ // increment RCV_NAME_LSA_INTEREST
+ lsaIncrementSignal(Statistics::PacketType::RCV_NAME_LSA_INTEREST);
_LOG_DEBUG("nameLsa interest " << interest << " received");
NameLsa* nameLsa = m_nlsr.getLsdb().findNameLsa(lsaKey);
if (nameLsa != 0) {
if (nameLsa->getLsSeqNo() == seqNo) {
std::string content = nameLsa->getData();
putLsaData(interest,content);
+ // increment SENT_NAME_LSA_DATA
+ lsaIncrementSignal(Statistics::PacketType::SENT_NAME_LSA_DATA);
}
else {
_LOG_TRACE("SeqNo for nameLsa does not match");
@@ -1087,12 +1108,16 @@
_LOG_ERROR("Received interest for an adjacency LSA when hyperbolic routing is enabled");
}
+ // increment RCV_ADJ_LSA_INTEREST
+ lsaIncrementSignal(Statistics::PacketType::RCV_ADJ_LSA_INTEREST);
_LOG_DEBUG("AdjLsa interest " << interest << " received");
AdjLsa* adjLsa = m_nlsr.getLsdb().findAdjLsa(lsaKey);
if (adjLsa != 0) {
if (adjLsa->getLsSeqNo() == seqNo) {
std::string content = adjLsa->getData();
putLsaData(interest,content);
+ // increment SENT_ADJ_LSA_DATA
+ lsaIncrementSignal(Statistics::PacketType::SENT_ADJ_LSA_DATA);
}
else {
_LOG_TRACE("SeqNo for AdjLsa does not match");
@@ -1117,12 +1142,16 @@
_LOG_ERROR("Received Interest for a coordinate LSA when link-state routing is enabled");
}
+ // increment RCV_COORD_LSA_INTEREST
+ lsaIncrementSignal(Statistics::PacketType::RCV_COORD_LSA_INTEREST);
_LOG_DEBUG("CoordinateLsa interest " << interest << " received");
CoordinateLsa* corLsa = m_nlsr.getLsdb().findCoordinateLsa(lsaKey);
if (corLsa != 0) {
if (corLsa->getLsSeqNo() == seqNo) {
std::string content = corLsa->getData();
putLsaData(interest,content);
+ // increment SENT_COORD_LSA_DATA
+ lsaIncrementSignal(Statistics::PacketType::SENT_COORD_LSA_DATA);
}
else {
_LOG_TRACE("SeqNo for CoordinateLsa does not match");
@@ -1166,6 +1195,9 @@
else {
_LOG_WARN("Received unrecognized LSA Type: " << interestedLsType);
}
+
+ // increment RCV_LSA_DATA
+ lsaIncrementSignal(Statistics::PacketType::RCV_LSA_DATA);
}
}
@@ -1173,6 +1205,8 @@
Lsdb::processContentNameLsa(const ndn::Name& lsaKey,
uint64_t lsSeqNo, std::string& dataContent)
{
+ // increment RCV_NAME_LSA_DATA
+ lsaIncrementSignal(Statistics::PacketType::RCV_NAME_LSA_DATA);
if (isNameLsaNew(lsaKey, lsSeqNo)) {
NameLsa nameLsa;
if (nameLsa.initializeFromContent(dataContent)) {
@@ -1188,6 +1222,8 @@
Lsdb::processContentAdjacencyLsa(const ndn::Name& lsaKey,
uint64_t lsSeqNo, std::string& dataContent)
{
+ // increment RCV_ADJ_LSA_DATA
+ lsaIncrementSignal(Statistics::PacketType::RCV_ADJ_LSA_DATA);
if (isAdjLsaNew(lsaKey, lsSeqNo)) {
AdjLsa adjLsa;
if (adjLsa.initializeFromContent(dataContent)) {
@@ -1203,6 +1239,8 @@
Lsdb::processContentCoordinateLsa(const ndn::Name& lsaKey,
uint64_t lsSeqNo, std::string& dataContent)
{
+ // increment RCV_COORD_LSA_DATA
+ lsaIncrementSignal(Statistics::PacketType::RCV_COORD_LSA_DATA);
if (isCoordinateLsaNew(lsaKey, lsSeqNo)) {
CoordinateLsa corLsa;
if (corLsa.initializeFromContent(dataContent)) {
diff --git a/src/lsdb.hpp b/src/lsdb.hpp
index 2b182bd..bb0b9d8 100644
--- a/src/lsdb.hpp
+++ b/src/lsdb.hpp
@@ -27,6 +27,14 @@
#include "sequencing-manager.hpp"
#include "test-access-control.hpp"
#include "communication/sync-logic-handler.hpp"
+#include "statistics.hpp"
+
+#include <ndn-cxx/security/key-chain.hpp>
+#include <ndn-cxx/util/signal.hpp>
+#include <ndn-cxx/util/time.hpp>
+
+#include <utility>
+#include <boost/cstdint.hpp>
#include <utility>
#include <boost/cstdint.hpp>
@@ -374,6 +382,8 @@
public:
static const ndn::Name::Component NAME_COMPONENT;
+ ndn::util::signal::Signal<Lsdb, Statistics::PacketType> lsaIncrementSignal;
+
private:
Nlsr& m_nlsr;
ndn::Scheduler& m_scheduler;
diff --git a/src/nlsr.cpp b/src/nlsr.cpp
index 55d426a..70648e3 100644
--- a/src/nlsr.cpp
+++ b/src/nlsr.cpp
@@ -81,6 +81,7 @@
, m_nfdRibCommandProcessor(m_localhostDispatcher,
m_namePrefixList,
m_nlsrLsdb)
+ , m_statsCollector(m_nlsrLsdb, m_helloProtocol)
, m_faceMonitor(m_nlsrFace)
, m_firstHelloInterval(FIRST_HELLO_INTERVAL_DEFAULT)
{
diff --git a/src/nlsr.hpp b/src/nlsr.hpp
index 1a3432a..54af8b4 100644
--- a/src/nlsr.hpp
+++ b/src/nlsr.hpp
@@ -38,6 +38,7 @@
#include "update/prefix-update-processor.hpp"
#include "update/nfd-rib-command-processor.hpp"
#include "utility/name-helper.hpp"
+#include "stats-collector.hpp"
#include <stdexcept>
@@ -376,6 +377,11 @@
canonizeNeighborUris(std::list<Adjacent>::iterator currentNeighbor,
std::function<void(std::list<Adjacent>::iterator)> then);
+ StatsCollector&
+ getStatsCollector()
+ {
+ return m_statsCollector;
+ }
PUBLIC_WITH_TESTS_ELSE_PRIVATE:
void
@@ -470,6 +476,7 @@
ndn::Name m_defaultCertName;
update::PrefixUpdateProcessor m_prefixUpdateProcessor;
update::NfdRibCommandProcessor m_nfdRibCommandProcessor;
+ StatsCollector m_statsCollector;
ndn::nfd::FaceMonitor m_faceMonitor;
diff --git a/src/statistics.cpp b/src/statistics.cpp
new file mode 100644
index 0000000..f5f5516
--- /dev/null
+++ b/src/statistics.cpp
@@ -0,0 +1,101 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/**
+ * Copyright (c) 2014-2017, The University of Memphis,
+ * Regents of the University of California,
+ * Arizona Board of Regents.
+ *
+ * This file is part of NLSR (Named-data Link State Routing).
+ * See AUTHORS.md for complete list of NLSR authors and contributors.
+ *
+ * NLSR is free software: you can redistribute it and/or modify it under the terms
+ * of the GNU General Public License as published by the Free Software Foundation,
+ * either version 3 of the License, or (at your option) any later version.
+ *
+ * NLSR is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
+ * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+ * PURPOSE. See the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * NLSR, e.g., in COPYING.md file. If not, see <http://www.gnu.org/licenses/>.
+ **/
+
+#include "statistics.hpp"
+#include "nlsr.hpp"
+#include "utility/name-helper.hpp"
+
+namespace nlsr {
+
+size_t
+Statistics::get(PacketType type) const
+{
+ std::map<PacketType,int>::const_iterator it = m_packetCounter.find(type);
+ if(it != m_packetCounter.end())
+ {
+ return it->second;
+ }
+ else
+ {
+ return 0;
+ }
+}
+
+void
+Statistics::increment(PacketType type)
+{
+ m_packetCounter[type]++;
+}
+
+void
+Statistics::resetAll()
+{
+ for (auto&& it : m_packetCounter )
+ {
+ it.second = 0;
+ }
+}
+
+std::ostream&
+operator<<(std::ostream& os, const Statistics& stats)
+{
+ using PacketType = Statistics::PacketType;
+
+ os << "++++++++++++++++++++++++++++++++++++++++\n"
+ << "+ +\n"
+ << "+ Statistics +\n"
+ << "+ +\n"
+ << "++++++++++++++++++++++++++++++++++++++++\n"
+ << "HELLO PROTOCOL\n"
+ << " Sent Hello Interests: " << stats.get(PacketType::SENT_HELLO_INTEREST) << "\n"
+ << " Sent Hello Data: " << stats.get(PacketType::SENT_HELLO_DATA) << "\n"
+ << "\n"
+ << " Received Hello Interests: " << stats.get(PacketType::RCV_HELLO_INTEREST) << "\n"
+ << " Received Hello Data: " << stats.get(PacketType::RCV_HELLO_DATA) << "\n"
+ << "\n"
+ << "LSDB\n"
+ << " Total Sent LSA Interests: " << stats.get(PacketType::SENT_LSA_INTEREST) << "\n"
+ << " Total Received LSA Interests: " << stats.get(PacketType::RCV_LSA_INTEREST) << "\n"
+ << "\n"
+ << " Total Sent LSA Data: " << stats.get(PacketType::SENT_LSA_DATA) << "\n"
+ << " Total Received LSA Data: " << stats.get(PacketType::RCV_LSA_DATA) << "\n"
+ << "\n"
+ << " Sent Adjacency LSA Interests: " << stats.get(PacketType::SENT_ADJ_LSA_INTEREST) << "\n"
+ << " Sent Coordinate LSA Interests: " << stats.get(PacketType::SENT_COORD_LSA_INTEREST) << "\n"
+ << " Sent Name LSA Interests: " << stats.get(PacketType::SENT_NAME_LSA_INTEREST) << "\n"
+ << "\n"
+ << " Received Adjacency LSA Interests: " << stats.get(PacketType::RCV_ADJ_LSA_INTEREST) << "\n"
+ << " Received Coordinate LSA Interests: " << stats.get(PacketType::RCV_COORD_LSA_INTEREST) << "\n"
+ << " Received Name LSA Interests: " << stats.get(PacketType::RCV_NAME_LSA_INTEREST) << "\n"
+ << "\n"
+ << " Sent Adjacency LSA Data: " << stats.get(PacketType::SENT_ADJ_LSA_DATA) << "\n"
+ << " Sent Coordinate LSA Data: " << stats.get(PacketType::SENT_COORD_LSA_DATA) << "\n"
+ << " Sent Name LSA Data: " << stats.get(PacketType::SENT_NAME_LSA_DATA) << "\n"
+ << "\n"
+ << " Received Adjacency LSA Data: " << stats.get(PacketType::RCV_ADJ_LSA_DATA) << "\n"
+ << " Received Coordinate LSA Data: " << stats.get(PacketType::RCV_COORD_LSA_DATA) << "\n"
+ << " Received Name LSA Data: " << stats.get(PacketType::RCV_NAME_LSA_DATA) << "\n"
+ << "++++++++++++++++++++++++++++++++++++++++\n";
+
+ return os;
+}
+
+} // namespace nlsr
diff --git a/src/statistics.hpp b/src/statistics.hpp
new file mode 100644
index 0000000..435938f
--- /dev/null
+++ b/src/statistics.hpp
@@ -0,0 +1,80 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/**
+ * Copyright (c) 2014-2017, The University of Memphis,
+ * Regents of the University of California,
+ * Arizona Board of Regents.
+ *
+ * This file is part of NLSR (Named-data Link State Routing).
+ * See AUTHORS.md for complete list of NLSR authors and contributors.
+ *
+ * NLSR is free software: you can redistribute it and/or modify it under the terms
+ * of the GNU General Public License as published by the Free Software Foundation,
+ * either version 3 of the License, or (at your option) any later version.
+ *
+ * NLSR is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
+ * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+ * PURPOSE. See the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * NLSR, e.g., in COPYING.md file. If not, see <http://www.gnu.org/licenses/>.
+ **/
+
+#ifndef NLSR_STATISTICS_HPP
+#define NLSR_STATISTICS_HPP
+
+#include <map>
+
+namespace nlsr {
+
+class Statistics
+{
+
+public:
+ enum class PacketType {
+ SENT_HELLO_INTEREST,
+ SENT_HELLO_DATA,
+ RCV_HELLO_INTEREST,
+ RCV_HELLO_DATA,
+ SENT_LSA_INTEREST,
+ SENT_ADJ_LSA_INTEREST,
+ SENT_COORD_LSA_INTEREST,
+ SENT_NAME_LSA_INTEREST,
+ SENT_LSA_DATA,
+ SENT_ADJ_LSA_DATA,
+ SENT_COORD_LSA_DATA,
+ SENT_NAME_LSA_DATA,
+ RCV_LSA_INTEREST,
+ RCV_ADJ_LSA_INTEREST,
+ RCV_COORD_LSA_INTEREST,
+ RCV_NAME_LSA_INTEREST,
+ RCV_LSA_DATA,
+ RCV_ADJ_LSA_DATA,
+ RCV_COORD_LSA_DATA,
+ RCV_NAME_LSA_DATA
+ };
+
+ size_t
+ get(PacketType) const;
+
+ void
+ resetAll();
+
+ void
+ increment(PacketType);
+
+ const std::map<PacketType,int>&
+ getCounter() const
+ {
+ return m_packetCounter;
+ }
+
+private:
+ std::map<PacketType,int> m_packetCounter;
+};
+
+std::ostream&
+operator<<(std::ostream&, const Statistics& stats);
+
+} // namespace nlsr
+
+#endif // NLSR_STATISTICS_HPP
diff --git a/src/stats-collector.cpp b/src/stats-collector.cpp
new file mode 100644
index 0000000..cb179ec
--- /dev/null
+++ b/src/stats-collector.cpp
@@ -0,0 +1,52 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/**
+ * Copyright (c) 2014-2017, The University of Memphis,
+ * Regents of the University of California
+ *
+ * This file is part of NLSR (Named-data Link State Routing).
+ * See AUTHORS.md for complete list of NLSR authors and contributors.
+ *
+ * NLSR is free software: you can redistribute it and/or modify it under the terms
+ * of the GNU General Public License as published by the Free Software Foundation,
+ * either version 3 of the License, or (at your option) any later version.
+ *
+ * NLSR is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
+ * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+ * PURPOSE. See the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * NLSR, e.g., in COPYING.md file. If not, see <http://www.gnu.org/licenses/>.
+ **/
+
+#include "stats-collector.hpp"
+#include "logger.hpp"
+#include <fstream>
+
+namespace nlsr {
+
+StatsCollector::StatsCollector(Lsdb& lsdb, HelloProtocol& hp)
+ : m_lsdb(lsdb)
+ , m_hp(hp)
+{
+ m_lsaIncrementConn =
+ this->m_lsdb.lsaIncrementSignal.connect(std::bind(&StatsCollector::statsIncrement,
+ this, _1));
+
+ m_helloIncrementConn =
+ this->m_hp.hpIncrementSignal.connect(std::bind(&StatsCollector::statsIncrement,
+ this, _1));
+}
+
+StatsCollector::~StatsCollector()
+{
+ m_lsaIncrementConn.disconnect();
+ m_helloIncrementConn.disconnect();
+}
+
+void
+StatsCollector::statsIncrement(Statistics::PacketType pType)
+{
+ m_stats.increment(pType);
+}
+
+} // namespace nlsr
diff --git a/src/stats-collector.hpp b/src/stats-collector.hpp
new file mode 100644
index 0000000..a2be959
--- /dev/null
+++ b/src/stats-collector.hpp
@@ -0,0 +1,72 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/**
+ * Copyright (c) 2014-2017, The University of Memphis,
+ * Regents of the University of California
+ *
+ * This file is part of NLSR (Named-data Link State Routing).
+ * See AUTHORS.md for complete list of NLSR authors and contributors.
+ *
+ * NLSR is free software: you can redistribute it and/or modify it under the terms
+ * of the GNU General Public License as published by the Free Software Foundation,
+ * either version 3 of the License, or (at your option) any later version.
+ *
+ * NLSR is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
+ * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+ * PURPOSE. See the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * NLSR, e.g., in COPYING.md file. If not, see <http://www.gnu.org/licenses/>.
+ **/
+
+#ifndef NLSR_STATS_COLLECTOR_HPP
+#define NLSR_STATS_COLLECTOR_HPP
+
+#include "statistics.hpp"
+#include "lsdb.hpp"
+#include "hello-protocol.hpp"
+#include <ndn-cxx/util/signal.hpp>
+
+namespace nlsr {
+
+// brief: a class designed to handle statistical signals in nlsr
+
+class StatsCollector
+{
+public:
+
+ StatsCollector(Lsdb& lsdb, HelloProtocol& hp);
+
+ ~StatsCollector();
+
+ Statistics&
+ getStatistics()
+ {
+ return m_stats;
+ }
+
+private:
+
+ /*!
+ * \brief: increments a Statistics::PacketType
+ *
+ * \param: pType is an enum value corresponding to a Statistics::PacketType
+ *
+ * This takes in a Statistics::PacketType emitted by a signal and increments
+ * the value in m_stats.
+ */
+ void
+ statsIncrement(Statistics::PacketType pType);
+
+private:
+
+ Lsdb& m_lsdb;
+ HelloProtocol& m_hp;
+ Statistics m_stats;
+
+ ndn::util::signal::ScopedConnection m_lsaIncrementConn;
+ ndn::util::signal::ScopedConnection m_helloIncrementConn;
+};
+
+} // namespace nlsr
+
+#endif // NLSR_STATS_COLLECTOR_HPP
diff --git a/tests/test-statistics.cpp b/tests/test-statistics.cpp
new file mode 100644
index 0000000..bcfc29c
--- /dev/null
+++ b/tests/test-statistics.cpp
@@ -0,0 +1,330 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/**
+ * Copyright (c) 2014-2017, The University of Memphis,
+ * Regents of the University of California,
+ * Arizona Board of Regents.
+ *
+ * This file is part of NLSR (Named-data Link State Routing).
+ * See AUTHORS.md for complete list of NLSR authors and contributors.
+ *
+ * NLSR is free software: you can redistribute it and/or modify it under the terms
+ * of the GNU General Public License as published by the Free Software Foundation,
+ * either version 3 of the License, or (at your option) any later version.
+ *
+ * NLSR is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
+ * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+ * PURPOSE. See the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * NLSR, e.g., in COPYING.md file. If not, see <http://www.gnu.org/licenses/>.
+ **/
+
+#include "statistics.hpp"
+#include "test-common.hpp"
+#include "hello-protocol.hpp"
+#include "lsdb.hpp"
+#include "nlsr.hpp"
+
+#include <ndn-cxx/util/dummy-client-face.hpp>
+
+namespace nlsr {
+namespace test {
+
+class StatisticsFixture : public BaseFixture
+{
+public:
+ StatisticsFixture()
+ : face(std::make_shared<ndn::util::DummyClientFace>(g_ioService))
+ , nlsr(g_ioService, g_scheduler, std::ref(*face), g_keyChain)
+ , lsdb(nlsr.getLsdb())
+ , hello(nlsr.m_helloProtocol)
+ , conf(nlsr.getConfParameter())
+ , collector(nlsr.getStatsCollector())
+ {
+ conf.setNetwork("/ndn");
+ conf.setSiteName("/site");
+ conf.setRouterName("/%C1.router/this-router");
+ conf.buildRouterPrefix();
+
+ nlsr.initialize();
+
+ face->processEvents(ndn::time::milliseconds(1));
+ face->sentInterests.clear();
+ }
+
+ /*!
+ * \brief Checks if lsa interest was received and data for interest was sent
+ *
+ * \param interestPrefix is an interest name prefix
+ * \param lsaType indicates whether the lsa is a name, adjacency, or coordinate
+ * \param seqNo sequence number that will be appended to an interest name
+ * \param receivedInterestType is the specific Statisitcs::PacketType interest that is received
+ * \param sentDataType is the Statistics::PacketType data being sent upon interest process
+ *
+ * This is a general function that can be used for all three types of lsa. Calling processInterest()
+ * from lsdb will cause the statsCollector to increment the incoming interest type and increment the
+ * outgoing data type.
+ */
+ void
+ receiveInterestAndCheckSentStats(const std::string& interestPrefix,
+ const std::string& lsaType,
+ uint32_t seqNo,
+ Statistics::PacketType receivedInterestType,
+ Statistics::PacketType sentDataType)
+ {
+ size_t rcvBefore = collector.getStatistics().get(receivedInterestType);
+ size_t sentBefore = collector.getStatistics().get(sentDataType);
+
+ ndn::Name interestName = ndn::Name(ndn::Name(interestPrefix + lsaType).appendNumber(seqNo));
+ lsdb.processInterest(ndn::Name(), ndn::Interest(interestName));
+ face->processEvents(ndn::time::milliseconds(1));
+
+ BOOST_CHECK_EQUAL(collector.getStatistics().get(receivedInterestType), rcvBefore + 1);
+ BOOST_CHECK_EQUAL(collector.getStatistics().get(sentDataType), sentBefore + 1);
+ }
+
+ /*!
+ * \brief Checks if statistics update after an lsa interest is sent
+ *
+ * \param prefix is an interest prefix
+ * \param lsaType indicates whether the lsa is a name, adjacency, or coordinate
+ * \param seqNo is the sequence number
+ * \param statsType is a statistical PacketType
+ *
+ * The function is called to initiate an expressInterest call in lsdb and to check if the
+ * expected statistical packetType was incremented.
+ */
+ void
+ sendInterestAndCheckStats(const std::string& prefix,
+ const std::string& lsaType,
+ uint32_t seqNo,
+ Statistics::PacketType statsType)
+ {
+ size_t sentBefore = collector.getStatistics().get(statsType);
+
+ lsdb.expressInterest(ndn::Name(prefix + lsaType).appendNumber(seqNo), 0,
+ ndn::time::steady_clock::TimePoint::min());
+ face->processEvents(ndn::time::milliseconds(1));
+
+ BOOST_CHECK_EQUAL(collector.getStatistics().get(statsType), sentBefore + 1);
+ }
+
+public:
+ std::shared_ptr<ndn::util::DummyClientFace> face;
+ Nlsr nlsr;
+
+ Lsdb& lsdb;
+ HelloProtocol& hello;
+ ConfParameter& conf;
+ StatsCollector& collector;
+};
+
+BOOST_FIXTURE_TEST_SUITE(TestStatistics, StatisticsFixture)
+
+
+// A statistical PacketType is directly incremented (without signals).
+BOOST_AUTO_TEST_CASE(StatsIncrement)
+{
+ Statistics stats;
+ BOOST_CHECK_EQUAL(stats.get(Statistics::PacketType::SENT_HELLO_INTEREST), 0);
+ stats.increment(Statistics::PacketType::SENT_HELLO_INTEREST);
+ BOOST_CHECK_EQUAL(stats.get(Statistics::PacketType::SENT_HELLO_INTEREST), 1);
+}
+
+/*
+ * After a PacketType has been incremented, the resetAll() function is called, which sets all
+ * statistical packetType counts to 0
+ */
+BOOST_AUTO_TEST_CASE(StatsReset)
+{
+ Statistics stats;
+ stats.increment(Statistics::PacketType::SENT_HELLO_INTEREST);
+ stats.resetAll();
+ BOOST_CHECK_EQUAL(stats.get(Statistics::PacketType::SENT_HELLO_INTEREST), 0);
+}
+
+
+/*
+ * This tests hello interests and hello data statistical collection by constructing an adjacency lsa
+ * and calling functions that trigger the sending and receiving hello of interests/data.
+ */
+BOOST_AUTO_TEST_CASE(SendHelloInterest)
+{
+ nlsr.initialize();
+
+ face->processEvents(ndn::time::milliseconds(1));
+ face->sentInterests.clear();
+
+ Adjacent other("/ndn/router/other", ndn::util::FaceUri("udp4://other"), 25, Adjacent::STATUS_INACTIVE, 0, 0);
+
+ // This router's Adjacency LSA
+ nlsr.getAdjacencyList().insert(other);
+
+ ndn::Name name(conf.getRouterPrefix());
+ name.append("NLSR");
+ name.append("INFO");
+ name.append(other.getName().wireEncode());
+
+ hello.expressInterest(name, 1);
+ face->processEvents(ndn::time::milliseconds(1));
+
+ BOOST_CHECK_EQUAL(collector.getStatistics().get(Statistics::PacketType::SENT_HELLO_INTEREST), 1);
+
+ ndn::Interest interest(name);
+ hello.processInterest(ndn::Name(), interest);
+
+ face->processEvents(ndn::time::milliseconds(1));
+
+ BOOST_CHECK_EQUAL(collector.getStatistics().get(Statistics::PacketType::RCV_HELLO_INTEREST), 1);
+ BOOST_CHECK_EQUAL(collector.getStatistics().get(Statistics::PacketType::SENT_HELLO_DATA), 1);
+
+ // Receive Hello Data
+ ndn::Name dataName = other.getName();
+ dataName.append("NLSR");
+ dataName.append("INFO");
+ dataName.append(conf.getRouterPrefix().wireEncode());
+
+ std::shared_ptr<ndn::Data> data = std::make_shared<ndn::Data>(dataName);
+ hello.onContentValidated(data);
+
+ BOOST_CHECK_EQUAL(collector.getStatistics().get(Statistics::PacketType::RCV_HELLO_DATA), 1);
+}
+
+/*
+ * An interest is sent for each lsa type (name, adjacency, coordinate). The respective statistics are
+ * totaled and checked.
+ */
+BOOST_AUTO_TEST_CASE(LsdbSendLsaInterest)
+{
+ const std::string interestPrefix("/ndn/NLSR/LSA/site/%C1.Router/router/");
+ uint32_t seqNo = 1;
+
+ // Adjacency LSA
+ sendInterestAndCheckStats(interestPrefix, AdjLsa::TYPE_STRING, seqNo, Statistics::PacketType::SENT_ADJ_LSA_INTEREST);
+
+ // Coordinate LSA
+ sendInterestAndCheckStats(interestPrefix, CoordinateLsa::TYPE_STRING, seqNo, Statistics::PacketType::SENT_COORD_LSA_INTEREST);
+
+ // Name LSA
+ sendInterestAndCheckStats(interestPrefix, NameLsa::TYPE_STRING, seqNo, Statistics::PacketType::SENT_NAME_LSA_INTEREST);
+
+ // 3 total lsa interests were sent
+ BOOST_CHECK_EQUAL(collector.getStatistics().get(Statistics::PacketType::SENT_LSA_INTEREST), 3);
+}
+
+/*
+ * Tests the statistics collected upon processing incoming lsa interests and respective outgoing data.
+ * This process will trigger both an increment for received lsa interest and sent lsa data.
+ *
+ * /sa receiveInterestAndCheckSentStats
+ */
+BOOST_AUTO_TEST_CASE(LsdbReceiveInterestSendData)
+{
+ std::string routerName("/ndn/site/%C1.Router/router");
+ ndn::time::system_clock::TimePoint MAX_TIME = ndn::time::system_clock::TimePoint::max();
+ uint32_t seqNo = 1;
+
+ // Adjacency LSA
+ Adjacent adjacency("adjacency");
+ adjacency.setStatus(Adjacent::STATUS_ACTIVE);
+
+ AdjacencyList adjacencies;
+ adjacencies.insert(adjacency);
+
+ AdjLsa adjLsa(routerName, seqNo, MAX_TIME, 1, adjacencies);
+ lsdb.installAdjLsa(adjLsa);
+
+ const std::string interestPrefix("/ndn/NLSR/LSA/site/%C1.Router/router/");
+
+ // Receive Adjacency LSA Interest
+ receiveInterestAndCheckSentStats(interestPrefix,
+ AdjLsa::TYPE_STRING,
+ seqNo,
+ Statistics::PacketType::RCV_ADJ_LSA_INTEREST,
+ Statistics::PacketType::SENT_ADJ_LSA_DATA);
+
+ // Name LSA
+ NamePrefixList prefixes;
+ prefixes.insert("/ndn/name");
+
+ NameLsa nameLsa(routerName, seqNo, MAX_TIME, prefixes);
+ lsdb.installNameLsa(nameLsa);
+
+ // Receive Name LSA Interest
+ receiveInterestAndCheckSentStats(interestPrefix,
+ NameLsa::TYPE_STRING,
+ seqNo,
+ Statistics::PacketType::RCV_NAME_LSA_INTEREST,
+ Statistics::PacketType::SENT_NAME_LSA_DATA);
+
+ // Coordinate LSA
+ std::vector<double> angles = {20.0, 30.0};
+ CoordinateLsa coordLsa(routerName, seqNo, MAX_TIME, 2.5, angles);
+ lsdb.installCoordinateLsa(coordLsa);
+
+ // Receive Adjacency LSA Interest
+ receiveInterestAndCheckSentStats(interestPrefix,
+ CoordinateLsa::TYPE_STRING,
+ seqNo,
+ Statistics::PacketType::RCV_COORD_LSA_INTEREST,
+ Statistics::PacketType::SENT_COORD_LSA_DATA);
+
+ // 3 different lsa type interests should be received
+ BOOST_CHECK_EQUAL(collector.getStatistics().get(Statistics::PacketType::RCV_LSA_INTEREST), 3);
+
+ // data should have been sent 3x, once per lsa type
+ BOOST_CHECK_EQUAL(collector.getStatistics().get(Statistics::PacketType::SENT_LSA_DATA), 3);
+}
+
+/*
+ * Data for each lsa type (name, adjacency, coordinate) is sent to the lsdb and statistics are
+ * checked to verify the respective statistical PacketType has been received.
+ */
+BOOST_AUTO_TEST_CASE(LsdbReceiveData)
+{
+ ndn::Name routerName("/ndn/cs/%C1.Router/router1");
+ uint32_t seqNo = 1;
+ ndn::time::system_clock::TimePoint MAX_TIME = ndn::time::system_clock::TimePoint::max();
+
+ // adjacency lsa
+ ndn::Name adjInterest("/ndn/NLSR/LSA/cs/%C1.Router/router1/adjacency/");
+ adjInterest.appendNumber(seqNo);
+ AdjLsa aLsa(routerName, seqNo, MAX_TIME, 1, nlsr.getAdjacencyList());
+ lsdb.installAdjLsa(aLsa);
+
+ const ndn::ConstBufferPtr aBuffer = std::make_shared<ndn::Buffer>(aLsa.getData().c_str(),
+ aLsa.getData().size());
+ lsdb.afterFetchLsa(aBuffer, adjInterest);
+ BOOST_CHECK_EQUAL(collector.getStatistics().get(Statistics::PacketType::RCV_ADJ_LSA_DATA), 1);
+
+ // coordinate lsa
+ ndn::Name coordInterest("/ndn/NLSR/LSA/cs/%C1.Router/router1/coordinate/");
+ coordInterest.appendNumber(seqNo);
+ std::vector<double> angles = {20.0, 30.0};
+ CoordinateLsa cLsa(routerName, seqNo, MAX_TIME, 2.5, angles);
+ lsdb.installCoordinateLsa(cLsa);
+
+ const ndn::ConstBufferPtr cBuffer = std::make_shared<ndn::Buffer>(cLsa.getData().c_str(),
+ cLsa.getData().size());
+ lsdb.afterFetchLsa(cBuffer, coordInterest);
+ BOOST_CHECK_EQUAL(collector.getStatistics().get(Statistics::PacketType::RCV_COORD_LSA_DATA), 1);
+
+ // name lsa
+ ndn::Name interestName("/ndn/NLSR/LSA/cs/%C1.Router/router1/name/");
+ interestName.appendNumber(seqNo);
+ NameLsa nLsa(routerName, seqNo, MAX_TIME, nlsr.getNamePrefixList());
+ lsdb.installNameLsa(nLsa);
+
+ const ndn::ConstBufferPtr nBuffer = std::make_shared<ndn::Buffer>(nLsa.getData().c_str(),
+ nLsa.getData().size());
+ lsdb.afterFetchLsa(nBuffer, interestName);
+ BOOST_CHECK_EQUAL(collector.getStatistics().get(Statistics::PacketType::RCV_NAME_LSA_DATA), 1);
+
+ // 3 lsa data types should be received
+ BOOST_CHECK_EQUAL(collector.getStatistics().get(Statistics::PacketType::RCV_LSA_DATA), 3);
+}
+
+BOOST_AUTO_TEST_SUITE_END()
+
+} // namespace test
+} // namespace nlsr