NS-3 based Named Data Networking (NDN) simulator
ndnSIM 2.5: NDN, CCN, CCNx, content centric networks
API Documentation
ndn-l3-rate-tracer.cpp
Go to the documentation of this file.
1 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
20 #include "ndn-l3-rate-tracer.hpp"
21 #include "ns3/node.h"
22 #include "ns3/packet.h"
23 #include "ns3/config.h"
24 #include "ns3/callback.h"
25 #include "ns3/simulator.h"
26 #include "ns3/log.h"
27 #include "ns3/node-list.h"
28 #include "ns3/ndnSIM/model/ndn-l3-protocol.hpp"
29 
31 
32 #include <fstream>
33 #include <boost/lexical_cast.hpp>
34 
35 NS_LOG_COMPONENT_DEFINE("ndn.L3RateTracer");
36 
37 namespace ns3 {
38 namespace ndn {
39 
40 static std::list<std::tuple<shared_ptr<std::ostream>, std::list<Ptr<L3RateTracer>>>>
42 
43 void
45 {
46  g_tracers.clear();
47 }
48 
49 void
50 L3RateTracer::InstallAll(const std::string& file, Time averagingPeriod /* = Seconds (0.5)*/)
51 {
52  std::list<Ptr<L3RateTracer>> tracers;
53  shared_ptr<std::ostream> outputStream;
54  if (file != "-") {
55  shared_ptr<std::ofstream> os(new std::ofstream());
56  os->open(file.c_str(), std::ios_base::out | std::ios_base::trunc);
57 
58  if (!os->is_open()) {
59  NS_LOG_ERROR("File " << file << " cannot be opened for writing. Tracing disabled");
60  return;
61  }
62 
63  outputStream = os;
64  }
65  else {
66  outputStream = shared_ptr<std::ostream>(&std::cout, std::bind([]{}));
67  }
68 
69  for (NodeList::Iterator node = NodeList::Begin(); node != NodeList::End(); node++) {
70  Ptr<L3RateTracer> trace = Install(*node, outputStream, averagingPeriod);
71  tracers.push_back(trace);
72  }
73 
74  if (tracers.size() > 0) {
75  // *m_l3RateTrace << "# "; // not necessary for R's read.table
76  tracers.front()->PrintHeader(*outputStream);
77  *outputStream << "\n";
78  }
79 
80  g_tracers.push_back(std::make_tuple(outputStream, tracers));
81 }
82 
83 void
84 L3RateTracer::Install(const NodeContainer& nodes, const std::string& file,
85  Time averagingPeriod /* = Seconds (0.5)*/)
86 {
87  using namespace boost;
88  using namespace std;
89 
90  std::list<Ptr<L3RateTracer>> tracers;
91  shared_ptr<std::ostream> outputStream;
92  if (file != "-") {
93  shared_ptr<std::ofstream> os(new std::ofstream());
94  os->open(file.c_str(), std::ios_base::out | std::ios_base::trunc);
95 
96  if (!os->is_open()) {
97  NS_LOG_ERROR("File " << file << " cannot be opened for writing. Tracing disabled");
98  return;
99  }
100 
101  outputStream = os;
102  }
103  else {
104  outputStream = shared_ptr<std::ostream>(&std::cout, std::bind([]{}));
105  }
106 
107  for (NodeContainer::Iterator node = nodes.Begin(); node != nodes.End(); node++) {
108  Ptr<L3RateTracer> trace = Install(*node, outputStream, averagingPeriod);
109  tracers.push_back(trace);
110  }
111 
112  if (tracers.size() > 0) {
113  // *m_l3RateTrace << "# "; // not necessary for R's read.table
114  tracers.front()->PrintHeader(*outputStream);
115  *outputStream << "\n";
116  }
117 
118  g_tracers.push_back(std::make_tuple(outputStream, tracers));
119 }
120 
121 void
122 L3RateTracer::Install(Ptr<Node> node, const std::string& file,
123  Time averagingPeriod /* = Seconds (0.5)*/)
124 {
125  using namespace boost;
126  using namespace std;
127 
128  std::list<Ptr<L3RateTracer>> tracers;
129  shared_ptr<std::ostream> outputStream;
130  if (file != "-") {
131  shared_ptr<std::ofstream> os(new std::ofstream());
132  os->open(file.c_str(), std::ios_base::out | std::ios_base::trunc);
133 
134  if (!os->is_open()) {
135  NS_LOG_ERROR("File " << file << " cannot be opened for writing. Tracing disabled");
136  return;
137  }
138 
139  outputStream = os;
140  }
141  else {
142  outputStream = shared_ptr<std::ostream>(&std::cout, std::bind([]{}));
143  }
144 
145  Ptr<L3RateTracer> trace = Install(node, outputStream, averagingPeriod);
146  tracers.push_back(trace);
147 
148  if (tracers.size() > 0) {
149  // *m_l3RateTrace << "# "; // not necessary for R's read.table
150  tracers.front()->PrintHeader(*outputStream);
151  *outputStream << "\n";
152  }
153 
154  g_tracers.push_back(std::make_tuple(outputStream, tracers));
155 }
156 
157 Ptr<L3RateTracer>
158 L3RateTracer::Install(Ptr<Node> node, shared_ptr<std::ostream> outputStream,
159  Time averagingPeriod /* = Seconds (0.5)*/)
160 {
161  NS_LOG_DEBUG("Node: " << node->GetId());
162 
163  Ptr<L3RateTracer> trace = Create<L3RateTracer>(outputStream, node);
164  trace->SetAveragingPeriod(averagingPeriod);
165 
166  return trace;
167 }
168 
169 L3RateTracer::L3RateTracer(shared_ptr<std::ostream> os, Ptr<Node> node)
170  : L3Tracer(node)
171  , m_os(os)
172 {
173  SetAveragingPeriod(Seconds(1.0));
174 }
175 
176 L3RateTracer::L3RateTracer(shared_ptr<std::ostream> os, const std::string& node)
177  : L3Tracer(node)
178  , m_os(os)
179 {
180  SetAveragingPeriod(Seconds(1.0));
181 }
182 
184 {
185  m_printEvent.Cancel();
186 }
187 
188 void
189 L3RateTracer::SetAveragingPeriod(const Time& period)
190 {
191  m_period = period;
192  m_printEvent.Cancel();
193  m_printEvent = Simulator::Schedule(m_period, &L3RateTracer::PeriodicPrinter, this);
194 }
195 
196 void
197 L3RateTracer::PeriodicPrinter()
198 {
199  Print(*m_os);
200  Reset();
201 
202  m_printEvent = Simulator::Schedule(m_period, &L3RateTracer::PeriodicPrinter, this);
203 }
204 
205 void
206 L3RateTracer::PrintHeader(std::ostream& os) const
207 {
208  os << "Time"
209  << "\t"
210 
211  << "Node"
212  << "\t"
213  << "FaceId"
214  << "\t"
215  << "FaceDescr"
216  << "\t"
217 
218  << "Type"
219  << "\t"
220  << "Packets"
221  << "\t"
222  << "Kilobytes"
223  << "\t"
224  << "PacketRaw"
225  << "\t"
226  << "KilobytesRaw";
227 }
228 
229 void
230 L3RateTracer::Reset()
231 {
232  for (auto& stats : m_stats) {
233  std::get<0>(stats.second).Reset();
234  std::get<1>(stats.second).Reset();
235  }
236 }
237 
238 const double alpha = 0.8;
239 
240 #define STATS(INDEX) std::get<INDEX>(stats.second)
241 #define RATE(INDEX, fieldName) STATS(INDEX).fieldName / m_period.ToDouble(Time::S)
242 
243 #define PRINTER(printName, fieldName) \
244  STATS(2).fieldName = \
245  /*new value*/ alpha * RATE(0, fieldName) + /*old value*/ (1 - alpha) * STATS(2).fieldName; \
246  STATS(3).fieldName = /*new value*/ alpha * RATE(1, fieldName) / 1024.0 \
247  + /*old value*/ (1 - alpha) * STATS(3).fieldName; \
248  \
249  os << time.ToDouble(Time::S) << "\t" << m_node << "\t"; \
250  if (stats.first != nfd::face::INVALID_FACEID) { \
251  os << stats.first << "\t"; \
252  NS_ASSERT(m_faceInfos.find(stats.first) != m_faceInfos.end()); \
253  os << m_faceInfos.find(stats.first)->second << "\t"; \
254  } \
255  else { \
256  os << "-1\tall\t"; \
257  } \
258  os << printName << "\t" << STATS(2).fieldName << "\t" << STATS(3).fieldName << "\t" \
259  << STATS(0).fieldName << "\t" << STATS(1).fieldName / 1024.0 << "\n";
260 
261 void
262 L3RateTracer::Print(std::ostream& os) const
263 {
264  Time time = Simulator::Now();
265 
266  for (auto& stats : m_stats) {
267  if (stats.first == nfd::face::INVALID_FACEID)
268  continue;
269 
270  PRINTER("InInterests", m_inInterests);
271  PRINTER("OutInterests", m_outInterests);
272 
273  PRINTER("InData", m_inData);
274  PRINTER("OutData", m_outData);
275 
276  PRINTER("InNacks", m_inNack);
277  PRINTER("OutNacks", m_outNack);
278 
279  PRINTER("InSatisfiedInterests", m_satisfiedInterests);
280  PRINTER("InTimedOutInterests", m_timedOutInterests);
281 
282  PRINTER("OutSatisfiedInterests", m_outSatisfiedInterests);
283  PRINTER("OutTimedOutInterests", m_outTimedOutInterests);
284  }
285 
286  {
287  auto i = m_stats.find(nfd::face::INVALID_FACEID);
288  if (i != m_stats.end()) {
289  auto& stats = *i;
290  PRINTER("SatisfiedInterests", m_satisfiedInterests);
291  PRINTER("TimedOutInterests", m_timedOutInterests);
292  }
293  }
294 }
295 
296 void
298 {
299  AddInfo(face);
300  std::get<0>(m_stats[face.getId()]).m_outInterests++;
301  if (interest.hasWire()) {
302  std::get<1>(m_stats[face.getId()]).m_outInterests +=
303  interest.wireEncode().size();
304  }
305 }
306 
307 void
308 L3RateTracer::InInterests(const Interest& interest, const Face& face)
309 {
310  AddInfo(face);
311  std::get<0>(m_stats[face.getId()]).m_inInterests++;
312  if (interest.hasWire()) {
313  std::get<1>(m_stats[face.getId()]).m_inInterests +=
314  interest.wireEncode().size();
315  }
316 }
317 
318 void
319 L3RateTracer::OutData(const Data& data, const Face& face)
320 {
321  AddInfo(face);
322  std::get<0>(m_stats[face.getId()]).m_outData++;
323  if (data.hasWire()) {
324  std::get<1>(m_stats[face.getId()]).m_outData +=
325  data.wireEncode().size();
326  }
327 }
328 
329 void
330 L3RateTracer::InData(const Data& data, const Face& face)
331 {
332  AddInfo(face);
333  std::get<0>(m_stats[face.getId()]).m_inData++;
334  if (data.hasWire()) {
335  std::get<1>(m_stats[face.getId()]).m_inData +=
336  data.wireEncode().size();
337  }
338 }
339 
340 void
342 {
343  AddInfo(face);
344  std::get<0>(m_stats[face.getId()]).m_outNack++;
345  if (nack.getInterest().hasWire()) {
346  std::get<1>(m_stats[face.getId()]).m_outNack +=
347  nack.getInterest().wireEncode().size();
348  }
349 }
350 
351 void
353 {
354  AddInfo(face);
355  std::get<0>(m_stats[face.getId()]).m_inNack++;
356  if (nack.getInterest().hasWire()) {
357  std::get<1>(m_stats[face.getId()]).m_inNack +=
358  nack.getInterest().wireEncode().size();
359  }
360 }
361 
362 void
364 {
365  std::get<0>(m_stats[nfd::face::INVALID_FACEID]).m_satisfiedInterests++;
366  // no "size" stats
367 
368  for (const auto& in : entry.getInRecords()) {
369  AddInfo(in.getFace());
370  std::get<0>(m_stats[(in.getFace()).getId()]).m_satisfiedInterests ++;
371  }
372 
373  for (const auto& out : entry.getOutRecords()) {
374  AddInfo(out.getFace());
375  std::get<0>(m_stats[(out.getFace()).getId()]).m_outSatisfiedInterests ++;
376  }
377 }
378 
379 void
381 {
382  std::get<0>(m_stats[nfd::face::INVALID_FACEID]).m_timedOutInterests++;
383  // no "size" stats
384 
385  for (const auto& in : entry.getInRecords()) {
386  AddInfo(in.getFace());
387  std::get<0>(m_stats[(in.getFace()).getId()]).m_timedOutInterests++;
388  }
389 
390  for (const auto& out : entry.getOutRecords()) {
391  AddInfo(out.getFace());
392  std::get<0>(m_stats[(out.getFace()).getId()]).m_outTimedOutInterests++;
393  }
394 }
395 
396 void
397 L3RateTracer::AddInfo(const Face& face)
398 {
399  if (m_faceInfos.find(face.getId()) == m_faceInfos.end()) {
400  m_faceInfos.insert(make_pair(face.getId(), boost::lexical_cast<std::string>(face.getLocalUri())));
401  }
402 }
403 
404 } // namespace ndn
405 } // namespace ns3
virtual ~L3RateTracer()
Destructor.
Copyright (c) 2011-2015 Regents of the University of California.
static void Destroy()
Explicit request to remove all statically created tracers.
const InRecordCollection & getInRecords() const
Definition: pit-entry.hpp:93
virtual void SatisfiedInterests(const nfd::pit::Entry &, const Face &, const Data &)
STL namespace.
virtual void OutNack(const lp::Nack &nack, const Face &face)
Base class for network-layer (incoming/outgoing Interests and Data) tracing of NDN stack...
represents a Network Nack
Definition: nack.hpp:40
ndn Face
Definition: face-impl.hpp:42
an Interest table entry
Definition: pit-entry.hpp:57
static std::list< std::tuple< shared_ptr< std::ostream >, std::list< Ptr< AppDelayTracer > > > > g_tracers
const double alpha
Copyright (c) 2011-2015 Regents of the University of California.
static void Install(const NodeContainer &nodes, const std::string &file, Time averagingPeriod=Seconds(0.5))
Helper method to install tracers on the selected simulation nodes.
virtual void Print(std::ostream &os) const
Print current trace data.
virtual void InInterests(const Interest &interest, const Face &face)
bool hasWire() const
Check if this instance has cached wire encoding.
Definition: interest.hpp:93
virtual void OutData(const Data &data, const Face &face)
size_t wireEncode(EncodingImpl< TAG > &encoder) const
Prepend wire encoding to encoder in NDN Packet Format v0.2.
Definition: interest.cpp:56
virtual void TimedOutInterests(const nfd::pit::Entry &)
#define PRINTER(printName, fieldName)
L3RateTracer(shared_ptr< std::ostream > os, Ptr< Node > node)
Trace constructor that attaches to the node using node pointer.
static void InstallAll(const std::string &file, Time averagingPeriod=Seconds(0.5))
Helper method to install tracers on all simulation nodes.
virtual void PrintHeader(std::ostream &os) const
Print head of the trace (e.g., for post-processing)
const FaceId INVALID_FACEID
indicates an invalid FaceId
Definition: face.hpp:42
const Interest & getInterest() const
Definition: nack.hpp:53
const OutRecordCollection & getOutRecords() const
Definition: pit-entry.hpp:159
virtual void OutInterests(const Interest &interest, const Face &face)
virtual void InNack(const lp::Nack &nack, const Face &face)
virtual void InData(const Data &data, const Face &face)