utils: Add tracing functionality of network-layer NACKs
Change-Id: I3d16bcf29f4858049d1040a3e421e1c7151a1ea1
Refs: #3872
diff --git a/tests/unit-tests/utils/tracers/ndn-l3-rate-tracer.t.cpp b/tests/unit-tests/utils/tracers/ndn-l3-rate-tracer.t.cpp
new file mode 100644
index 0000000..e941edc
--- /dev/null
+++ b/tests/unit-tests/utils/tracers/ndn-l3-rate-tracer.t.cpp
@@ -0,0 +1,125 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/**
+ * Copyright (c) 2011-2016 Regents of the University of California.
+ *
+ * This file is part of ndnSIM. See AUTHORS for complete list of ndnSIM authors and
+ * contributors.
+ *
+ * ndnSIM 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.
+ *
+ * ndnSIM 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
+ * ndnSIM, e.g., in COPYING.md file. If not, see <http://www.gnu.org/licenses/>.
+ **/
+
+#include "utils/tracers/ndn-l3-rate-tracer.hpp"
+
+#include <boost/filesystem.hpp>
+#include <boost/test/output_test_stream.hpp>
+
+#include "../../tests-common.hpp"
+
+namespace ns3 {
+namespace ndn {
+
+const boost::filesystem::path TEST_TRACE = boost::filesystem::path(TEST_CONFIG_PATH) / "trace.txt";
+
+class L3RateTracerFixture : public ScenarioHelperWithCleanupFixture
+{
+public:
+ L3RateTracerFixture()
+ {
+ boost::filesystem::create_directories(TEST_CONFIG_PATH);
+
+ // setting default parameters for PointToPoint links and channels
+ Config::SetDefault("ns3::PointToPointNetDevice::DataRate", StringValue("10Mbps"));
+ Config::SetDefault("ns3::PointToPointChannel::Delay", StringValue("10ms"));
+ Config::SetDefault("ns3::DropTailQueue::MaxPackets", StringValue("20"));
+
+ createTopology({
+ {"1"},
+ });
+
+ addApps({
+ {"1", "ns3::ndn::ConsumerCbr",
+ {{"Prefix", "/prefix"}, {"Frequency", "1"}},
+ "0s", "0.9s"} // send just one packet
+ });
+ }
+
+ ~L3RateTracerFixture()
+ {
+ boost::filesystem::remove(TEST_TRACE);
+ L3RateTracer::Destroy(); // additional cleanup
+ }
+};
+
+BOOST_FIXTURE_TEST_SUITE(UtilsTracersNdnL3RateTracer, L3RateTracerFixture)
+
+BOOST_AUTO_TEST_CASE(NackTracing)
+{
+ NodeContainer nodes;
+ nodes.Add(getNode("1"));
+
+ L3RateTracer::Install(nodes, TEST_TRACE.string(), Seconds(1));
+
+ Simulator::Stop(Seconds(1.5));
+ Simulator::Run();
+
+ L3RateTracer::Destroy(); // to force log to be written
+
+ boost::test_tools::output_test_stream os(TEST_TRACE.string().c_str(), true);
+
+ os << "Time Node FaceId FaceDescr Type Packets Kilobytes PacketRaw KilobytesRaw\n";
+ BOOST_CHECK(os.match_pattern());
+
+ os << "1 1 1 internal:// InInterests 0 0 0 0\n"
+ << "1 1 1 internal:// OutInterests 0 0 0 0\n"
+ << "1 1 1 internal:// InData 0 0 0 0\n"
+ << "1 1 1 internal:// OutData 0 0 0 0\n"
+ << "1 1 1 internal:// InNacks 0 0 0 0\n"
+ << "1 1 1 internal:// OutNacks 0 0 0 0\n"
+ << "1 1 1 internal:// InSatisfiedInterests 0 0 0 0\n"
+ << "1 1 1 internal:// InTimedOutInterests 0 0 0 0\n"
+ << "1 1 1 internal:// OutSatisfiedInterests 2.4 0 3 0\n"
+ << "1 1 1 internal:// OutTimedOutInterests 0 0 0 0\n";
+ BOOST_CHECK(os.match_pattern());
+
+ os << "1 1 256 internal:// InInterests 0 0 0 0\n"
+ << "1 1 256 internal:// OutInterests 0 0 0 0\n"
+ << "1 1 256 internal:// InData 0 0 0 0\n"
+ << "1 1 256 internal:// OutData 0 0 0 0\n"
+ << "1 1 256 internal:// InNacks 0 0 0 0\n"
+ << "1 1 256 internal:// OutNacks 0 0 0 0\n"
+ << "1 1 256 internal:// InSatisfiedInterests 2.4 0 3 0\n"
+ << "1 1 256 internal:// InTimedOutInterests 0 0 0 0\n"
+ << "1 1 256 internal:// OutSatisfiedInterests 0 0 0 0\n"
+ << "1 1 256 internal:// OutTimedOutInterests 0 0 0 0\n";
+ BOOST_CHECK(os.match_pattern());
+
+ os << "1 1 257 appFace:// InInterests 0.8 0 1 0\n"
+ << "1 1 257 appFace:// OutInterests 0 0 0 0\n"
+ << "1 1 257 appFace:// InData 0 0 0 0\n"
+ << "1 1 257 appFace:// OutData 0 0 0 0\n"
+ << "1 1 257 appFace:// InNacks 0 0 0 0\n"
+ << "1 1 257 appFace:// OutNacks 0.8 0 1 0\n"
+ << "1 1 257 appFace:// InSatisfiedInterests 0 0 0 0\n"
+ << "1 1 257 appFace:// InTimedOutInterests 0 0 0 0\n"
+ << "1 1 257 appFace:// OutSatisfiedInterests 0 0 0 0\n"
+ << "1 1 257 appFace:// OutTimedOutInterests 0 0 0 0\n";
+ BOOST_CHECK(os.match_pattern());
+
+ os << "1 1 -1 all SatisfiedInterests 3.2 0 4 0\n"
+ << "1 1 -1 all TimedOutInterests 0 0 0 0\n";
+ BOOST_CHECK(os.match_pattern());
+}
+
+BOOST_AUTO_TEST_SUITE_END()
+
+} // namespace ndn
+} // namespace ns3
diff --git a/utils/tracers/ndn-l3-rate-tracer.cpp b/utils/tracers/ndn-l3-rate-tracer.cpp
index efb09b1..c217dbb 100644
--- a/utils/tracers/ndn-l3-rate-tracer.cpp
+++ b/utils/tracers/ndn-l3-rate-tracer.cpp
@@ -1,6 +1,6 @@
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/**
- * Copyright (c) 2011-2015 Regents of the University of California.
+ * Copyright (c) 2011-2016 Regents of the University of California.
*
* This file is part of ndnSIM. See AUTHORS for complete list of ndnSIM authors and
* contributors.
@@ -25,6 +25,7 @@
#include "ns3/simulator.h"
#include "ns3/log.h"
#include "ns3/node-list.h"
+#include "ns3/ndnSIM/model/ndn-l3-protocol.hpp"
#include "daemon/table/pit-entry.hpp"
@@ -246,8 +247,10 @@
+ /*old value*/ (1 - alpha) * STATS(3).fieldName; \
\
os << time.ToDouble(Time::S) << "\t" << m_node << "\t"; \
- if (stats.first != nullptr) { \
- os << stats.first->getId() << "\t" << stats.first->getLocalUri() << "\t"; \
+ if (stats.first != nfd::face::INVALID_FACEID) { \
+ os << stats.first << "\t"; \
+ NS_ASSERT(m_faceInfos.find(stats.first) != m_faceInfos.end()); \
+ os << m_faceInfos.find(stats.first)->second << "\t"; \
} \
else { \
os << "-1\tall\t"; \
@@ -261,7 +264,7 @@
Time time = Simulator::Now();
for (auto& stats : m_stats) {
- if (stats.first == nullptr)
+ if (stats.first == nfd::face::INVALID_FACEID)
continue;
PRINTER("InInterests", m_inInterests);
@@ -270,6 +273,9 @@
PRINTER("InData", m_inData);
PRINTER("OutData", m_outData);
+ PRINTER("InNacks", m_inNack);
+ PRINTER("OutNacks", m_outNack);
+
PRINTER("InSatisfiedInterests", m_satisfiedInterests);
PRINTER("InTimedOutInterests", m_timedOutInterests);
@@ -278,7 +284,7 @@
}
{
- auto i = m_stats.find(nullptr);
+ auto i = m_stats.find(nfd::face::INVALID_FACEID);
if (i != m_stats.end()) {
auto& stats = *i;
PRINTER("SatisfiedInterests", m_satisfiedInterests);
@@ -290,9 +296,10 @@
void
L3RateTracer::OutInterests(const Interest& interest, const Face& face)
{
- std::get<0>(m_stats[face.shared_from_this()]).m_outInterests++;
+ AddInfo(face);
+ std::get<0>(m_stats[face.getId()]).m_outInterests++;
if (interest.hasWire()) {
- std::get<1>(m_stats[face.shared_from_this()]).m_outInterests +=
+ std::get<1>(m_stats[face.getId()]).m_outInterests +=
interest.wireEncode().size();
}
}
@@ -300,9 +307,10 @@
void
L3RateTracer::InInterests(const Interest& interest, const Face& face)
{
- std::get<0>(m_stats[face.shared_from_this()]).m_inInterests++;
+ AddInfo(face);
+ std::get<0>(m_stats[face.getId()]).m_inInterests++;
if (interest.hasWire()) {
- std::get<1>(m_stats[face.shared_from_this()]).m_inInterests +=
+ std::get<1>(m_stats[face.getId()]).m_inInterests +=
interest.wireEncode().size();
}
}
@@ -310,9 +318,10 @@
void
L3RateTracer::OutData(const Data& data, const Face& face)
{
- std::get<0>(m_stats[face.shared_from_this()]).m_outData++;
+ AddInfo(face);
+ std::get<0>(m_stats[face.getId()]).m_outData++;
if (data.hasWire()) {
- std::get<1>(m_stats[face.shared_from_this()]).m_outData +=
+ std::get<1>(m_stats[face.getId()]).m_outData +=
data.wireEncode().size();
}
}
@@ -320,40 +329,75 @@
void
L3RateTracer::InData(const Data& data, const Face& face)
{
- std::get<0>(m_stats[face.shared_from_this()]).m_inData++;
+ AddInfo(face);
+ std::get<0>(m_stats[face.getId()]).m_inData++;
if (data.hasWire()) {
- std::get<1>(m_stats[face.shared_from_this()]).m_inData +=
+ std::get<1>(m_stats[face.getId()]).m_inData +=
data.wireEncode().size();
}
}
void
+L3RateTracer::OutNack(const lp::Nack& nack, const Face& face)
+{
+ AddInfo(face);
+ std::get<0>(m_stats[face.getId()]).m_outNack++;
+ if (nack.getInterest().hasWire()) {
+ std::get<1>(m_stats[face.getId()]).m_outNack +=
+ nack.getInterest().wireEncode().size();
+ }
+}
+
+void
+L3RateTracer::InNack(const lp::Nack& nack, const Face& face)
+{
+ AddInfo(face);
+ std::get<0>(m_stats[face.getId()]).m_inNack++;
+ if (nack.getInterest().hasWire()) {
+ std::get<1>(m_stats[face.getId()]).m_inNack +=
+ nack.getInterest().wireEncode().size();
+ }
+}
+
+void
L3RateTracer::SatisfiedInterests(const nfd::pit::Entry& entry, const Face&, const Data&)
{
- std::get<0>(m_stats[nullptr]).m_satisfiedInterests++;
+ std::get<0>(m_stats[nfd::face::INVALID_FACEID]).m_satisfiedInterests++;
// no "size" stats
for (const auto& in : entry.getInRecords()) {
- std::get<0>(m_stats[(in.getFace()).shared_from_this()]).m_satisfiedInterests ++;
+ AddInfo(in.getFace());
+ std::get<0>(m_stats[(in.getFace()).getId()]).m_satisfiedInterests ++;
}
for (const auto& out : entry.getOutRecords()) {
- std::get<0>(m_stats[(out.getFace()).shared_from_this()]).m_outSatisfiedInterests ++;
+ AddInfo(out.getFace());
+ std::get<0>(m_stats[(out.getFace()).getId()]).m_outSatisfiedInterests ++;
}
}
void
L3RateTracer::TimedOutInterests(const nfd::pit::Entry& entry)
{
- std::get<0>(m_stats[nullptr]).m_timedOutInterests++;
+ std::get<0>(m_stats[nfd::face::INVALID_FACEID]).m_timedOutInterests++;
// no "size" stats
for (const auto& in : entry.getInRecords()) {
- std::get<0>(m_stats[(in.getFace()).shared_from_this()]).m_timedOutInterests++;
+ AddInfo(in.getFace());
+ std::get<0>(m_stats[(in.getFace()).getId()]).m_timedOutInterests++;
}
for (const auto& out : entry.getOutRecords()) {
- std::get<0>(m_stats[(out.getFace()).shared_from_this()]).m_outTimedOutInterests++;
+ AddInfo(out.getFace());
+ std::get<0>(m_stats[(out.getFace()).getId()]).m_outTimedOutInterests++;
+ }
+}
+
+void
+L3RateTracer::AddInfo(const Face& face)
+{
+ if (m_faceInfos.find(face.getId()) == m_faceInfos.end()) {
+ m_faceInfos.insert(make_pair(face.getId(), boost::lexical_cast<std::string>(face.getLocalUri())));
}
}
diff --git a/utils/tracers/ndn-l3-rate-tracer.hpp b/utils/tracers/ndn-l3-rate-tracer.hpp
index 6370c26..0615aed 100644
--- a/utils/tracers/ndn-l3-rate-tracer.hpp
+++ b/utils/tracers/ndn-l3-rate-tracer.hpp
@@ -1,6 +1,6 @@
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/**
- * Copyright (c) 2011-2015 Regents of the University of California.
+ * Copyright (c) 2011-2016 Regents of the University of California.
*
* This file is part of ndnSIM. See AUTHORS for complete list of ndnSIM authors and
* contributors.
@@ -140,6 +140,12 @@
InData(const Data& data, const Face& face);
virtual void
+ OutNack(const lp::Nack& nack, const Face& face);
+
+ virtual void
+ InNack(const lp::Nack& nack, const Face& face);
+
+ virtual void
SatisfiedInterests(const nfd::pit::Entry&, const Face&, const Data&);
virtual void
@@ -155,12 +161,16 @@
void
Reset();
+ void
+ AddInfo(const Face& face);
+
private:
shared_ptr<std::ostream> m_os;
Time m_period;
EventId m_printEvent;
- mutable std::map<shared_ptr<const Face>, std::tuple<Stats, Stats, Stats, Stats>> m_stats;
+ mutable std::map<nfd::FaceId, std::tuple<Stats, Stats, Stats, Stats>> m_stats;
+ std::map<nfd::FaceId, std::string> m_faceInfos; // needed, because face may no longer exists at the time of stat printing
};
} // namespace ndn
diff --git a/utils/tracers/ndn-l3-tracer.cpp b/utils/tracers/ndn-l3-tracer.cpp
index e19439b..64c93ce 100644
--- a/utils/tracers/ndn-l3-tracer.cpp
+++ b/utils/tracers/ndn-l3-tracer.cpp
@@ -61,6 +61,8 @@
l3->TraceConnectWithoutContext("InInterests", MakeCallback(&L3Tracer::InInterests, this));
l3->TraceConnectWithoutContext("OutData", MakeCallback(&L3Tracer::OutData, this));
l3->TraceConnectWithoutContext("InData", MakeCallback(&L3Tracer::InData, this));
+ l3->TraceConnectWithoutContext("OutNack", MakeCallback(&L3Tracer::OutNack, this));
+ l3->TraceConnectWithoutContext("InNack", MakeCallback(&L3Tracer::InNack, this));
// satisfied/timed out PIs
l3->TraceConnectWithoutContext("SatisfiedInterests",
diff --git a/utils/tracers/ndn-l3-tracer.hpp b/utils/tracers/ndn-l3-tracer.hpp
index ed8e35b..15dd41f 100644
--- a/utils/tracers/ndn-l3-tracer.hpp
+++ b/utils/tracers/ndn-l3-tracer.hpp
@@ -94,6 +94,12 @@
InData(const Data&, const Face&) = 0;
virtual void
+ OutNack(const lp::Nack& nack, const Face&) = 0;
+
+ virtual void
+ InNack(const lp::Nack&, const Face&) = 0;
+
+ virtual void
SatisfiedInterests(const nfd::pit::Entry&, const Face&, const Data&) = 0;
virtual void
@@ -111,6 +117,8 @@
m_outInterests = 0;
m_inData = 0;
m_outData = 0;
+ m_inNack = 0;
+ m_outNack = 0;
m_satisfiedInterests = 0;
m_timedOutInterests = 0;
@@ -122,6 +130,8 @@
double m_outInterests;
double m_inData;
double m_outData;
+ double m_inNack;
+ double m_outNack;
double m_satisfiedInterests;
double m_timedOutInterests;
double m_outSatisfiedInterests;