blob: 7951213015728d339b79c68904c53994c5e8dbf8 [file] [log] [blame]
Alexander Afanasyevc9d5c1a2012-11-21 18:00:26 -08001/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil -*- */
2/*
3 * Copyright (c) 2011 UCLA
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License version 2 as
7 * published by the Free Software Foundation;
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17 *
18 * Author: Alexander Afanasyev <alexander.afanasyev@ucla.edu>
19 */
20
21#include "ndn-l3-rate-tracer.h"
22#include "ns3/node.h"
23#include "ns3/packet.h"
24#include "ns3/config.h"
25#include "ns3/callback.h"
26#include "ns3/simulator.h"
27#include "ns3/log.h"
28#include "ns3/node-list.h"
29
30#include "ns3/ndn-app.h"
31#include "ns3/ndn-face.h"
32#include "ns3/ndn-interest.h"
Alexander Afanasyev6eba36f2013-08-07 17:42:54 -070033#include "ns3/ndn-data.h"
Alexander Afanasyev37b84c52013-04-26 13:38:52 -070034#include "ns3/ndn-pit-entry.h"
Alexander Afanasyevc9d5c1a2012-11-21 18:00:26 -080035
36#include <fstream>
37#include <boost/lexical_cast.hpp>
38
39using namespace boost;
40using namespace std;
41
42NS_LOG_COMPONENT_DEFINE ("ndn.L3RateTracer");
43
44namespace ns3 {
45namespace ndn {
46
Alexander Afanasyev3fe94dc2013-08-09 17:12:12 -070047static std::list< boost::tuple< boost::shared_ptr<std::ostream>, std::list<Ptr<L3RateTracer> > > > g_tracers;
48
Alexander Afanasyev5352af32013-07-15 09:51:28 -070049template<class T>
50static inline void
51NullDeleter (T *ptr)
52{
53}
Alexander Afanasyevc9d5c1a2012-11-21 18:00:26 -080054
Alexander Afanasyev3fe94dc2013-08-09 17:12:12 -070055void
Alexander Afanasyevdb5f3b62013-08-09 17:42:12 -070056L3RateTracer::Destroy ()
57{
58 g_tracers.clear ();
59}
60
61void
Alexander Afanasyevc9d5c1a2012-11-21 18:00:26 -080062L3RateTracer::InstallAll (const std::string &file, Time averagingPeriod/* = Seconds (0.5)*/)
63{
64 std::list<Ptr<L3RateTracer> > tracers;
Alexander Afanasyev5352af32013-07-15 09:51:28 -070065 boost::shared_ptr<std::ostream> outputStream;
66 if (file != "-")
67 {
68 boost::shared_ptr<std::ofstream> os (new std::ofstream ());
69 os->open (file.c_str (), std::ios_base::out | std::ios_base::trunc);
Alexander Afanasyevc9d5c1a2012-11-21 18:00:26 -080070
Alexander Afanasyev5352af32013-07-15 09:51:28 -070071 if (!os->is_open ())
Alexander Afanasyev3fe94dc2013-08-09 17:12:12 -070072 {
73 NS_LOG_ERROR ("File " << file << " cannot be opened for writing. Tracing disabled");
74 return;
75 }
Alexander Afanasyev5352af32013-07-15 09:51:28 -070076
77 outputStream = os;
78 }
79 else
80 {
81 outputStream = boost::shared_ptr<std::ostream> (&std::cout, NullDeleter<std::ostream>);
82 }
Alexander Afanasyevc9d5c1a2012-11-21 18:00:26 -080083
84 for (NodeList::Iterator node = NodeList::Begin ();
85 node != NodeList::End ();
86 node++)
87 {
Alexander Afanasyev5352af32013-07-15 09:51:28 -070088 Ptr<L3RateTracer> trace = Install (*node, outputStream, averagingPeriod);
Alexander Afanasyevc9d5c1a2012-11-21 18:00:26 -080089 tracers.push_back (trace);
90 }
91
92 if (tracers.size () > 0)
93 {
94 // *m_l3RateTrace << "# "; // not necessary for R's read.table
95 tracers.front ()->PrintHeader (*outputStream);
96 *outputStream << "\n";
97 }
98
Alexander Afanasyev3fe94dc2013-08-09 17:12:12 -070099 g_tracers.push_back (boost::make_tuple (outputStream, tracers));
Alexander Afanasyevc9d5c1a2012-11-21 18:00:26 -0800100}
101
Alexander Afanasyev3fe94dc2013-08-09 17:12:12 -0700102void
Alexander Afanasyev5352af32013-07-15 09:51:28 -0700103L3RateTracer::Install (const NodeContainer &nodes, const std::string &file, Time averagingPeriod/* = Seconds (0.5)*/)
104{
105 using namespace boost;
106 using namespace std;
107
108 std::list<Ptr<L3RateTracer> > tracers;
109 boost::shared_ptr<std::ostream> outputStream;
110 if (file != "-")
111 {
112 boost::shared_ptr<std::ofstream> os (new std::ofstream ());
113 os->open (file.c_str (), std::ios_base::out | std::ios_base::trunc);
114
115 if (!os->is_open ())
Alexander Afanasyev3fe94dc2013-08-09 17:12:12 -0700116 {
117 NS_LOG_ERROR ("File " << file << " cannot be opened for writing. Tracing disabled");
118 return;
119 }
Alexander Afanasyev5352af32013-07-15 09:51:28 -0700120
121 outputStream = os;
122 }
123 else
124 {
125 outputStream = boost::shared_ptr<std::ostream> (&std::cout, NullDeleter<std::ostream>);
126 }
127
128 for (NodeContainer::Iterator node = nodes.Begin ();
129 node != nodes.End ();
130 node++)
131 {
132 Ptr<L3RateTracer> trace = Install (*node, outputStream, averagingPeriod);
133 tracers.push_back (trace);
134 }
135
136 if (tracers.size () > 0)
137 {
138 // *m_l3RateTrace << "# "; // not necessary for R's read.table
139 tracers.front ()->PrintHeader (*outputStream);
140 *outputStream << "\n";
141 }
142
Alexander Afanasyev3fe94dc2013-08-09 17:12:12 -0700143 g_tracers.push_back (boost::make_tuple (outputStream, tracers));
Alexander Afanasyev5352af32013-07-15 09:51:28 -0700144}
145
Alexander Afanasyev3fe94dc2013-08-09 17:12:12 -0700146void
Alexander Afanasyev5352af32013-07-15 09:51:28 -0700147L3RateTracer::Install (Ptr<Node> node, const std::string &file, Time averagingPeriod/* = Seconds (0.5)*/)
148{
149 using namespace boost;
150 using namespace std;
151
152 std::list<Ptr<L3RateTracer> > tracers;
153 boost::shared_ptr<std::ostream> outputStream;
154 if (file != "-")
155 {
156 boost::shared_ptr<std::ofstream> os (new std::ofstream ());
157 os->open (file.c_str (), std::ios_base::out | std::ios_base::trunc);
158
159 if (!os->is_open ())
Alexander Afanasyev3fe94dc2013-08-09 17:12:12 -0700160 {
161 NS_LOG_ERROR ("File " << file << " cannot be opened for writing. Tracing disabled");
162 return;
163 }
Alexander Afanasyev5352af32013-07-15 09:51:28 -0700164
165 outputStream = os;
166 }
167 else
168 {
169 outputStream = boost::shared_ptr<std::ostream> (&std::cout, NullDeleter<std::ostream>);
170 }
171
172 Ptr<L3RateTracer> trace = Install (node, outputStream, averagingPeriod);
173 tracers.push_back (trace);
174
175 if (tracers.size () > 0)
176 {
177 // *m_l3RateTrace << "# "; // not necessary for R's read.table
178 tracers.front ()->PrintHeader (*outputStream);
179 *outputStream << "\n";
180 }
181
Alexander Afanasyev3fe94dc2013-08-09 17:12:12 -0700182 g_tracers.push_back (boost::make_tuple (outputStream, tracers));
Alexander Afanasyev5352af32013-07-15 09:51:28 -0700183}
184
185
186Ptr<L3RateTracer>
187L3RateTracer::Install (Ptr<Node> node,
188 boost::shared_ptr<std::ostream> outputStream,
189 Time averagingPeriod/* = Seconds (0.5)*/)
190{
191 NS_LOG_DEBUG ("Node: " << node->GetId ());
192
193 Ptr<L3RateTracer> trace = Create<L3RateTracer> (outputStream, node);
194 trace->SetAveragingPeriod (averagingPeriod);
195
196 return trace;
197}
198
Alexander Afanasyevc9d5c1a2012-11-21 18:00:26 -0800199
200L3RateTracer::L3RateTracer (boost::shared_ptr<std::ostream> os, Ptr<Node> node)
201 : L3Tracer (node)
202 , m_os (os)
203{
204 SetAveragingPeriod (Seconds (1.0));
205}
206
207L3RateTracer::L3RateTracer (boost::shared_ptr<std::ostream> os, const std::string &node)
208 : L3Tracer (node)
209 , m_os (os)
210{
211 SetAveragingPeriod (Seconds (1.0));
212}
213
214L3RateTracer::~L3RateTracer ()
215{
216 m_printEvent.Cancel ();
217}
218
219void
220L3RateTracer::SetAveragingPeriod (const Time &period)
221{
222 m_period = period;
223 m_printEvent.Cancel ();
224 m_printEvent = Simulator::Schedule (m_period, &L3RateTracer::PeriodicPrinter, this);
225}
226
227void
228L3RateTracer::PeriodicPrinter ()
229{
230 Print (*m_os);
231 Reset ();
Alexander Afanasyev37b84c52013-04-26 13:38:52 -0700232
Alexander Afanasyevc9d5c1a2012-11-21 18:00:26 -0800233 m_printEvent = Simulator::Schedule (m_period, &L3RateTracer::PeriodicPrinter, this);
234}
235
236void
237L3RateTracer::PrintHeader (std::ostream &os) const
238{
239 os << "Time" << "\t"
240
241 << "Node" << "\t"
242 << "FaceId" << "\t"
243 << "FaceDescr" << "\t"
244
245 << "Type" << "\t"
246 << "Packets" << "\t"
247 << "Kilobytes" << "\t"
248 << "PacketRaw" << "\t"
249 << "KilobytesRaw";
250}
251
252void
253L3RateTracer::Reset ()
254{
255 for (std::map<Ptr<const Face>, boost::tuple<Stats, Stats, Stats, Stats> >::iterator stats = m_stats.begin ();
256 stats != m_stats.end ();
257 stats++)
258 {
259 stats->second.get<0> ().Reset ();
260 stats->second.get<1> ().Reset ();
261 }
262}
263
264const double alpha = 0.8;
265
266#define STATS(INDEX) stats->second.get<INDEX> ()
267#define RATE(INDEX, fieldName) STATS(INDEX).fieldName / m_period.ToDouble (Time::S)
268
269#define PRINTER(printName, fieldName) \
270 STATS(2).fieldName = /*new value*/alpha * RATE(0, fieldName) + /*old value*/(1-alpha) * STATS(2).fieldName; \
271 STATS(3).fieldName = /*new value*/alpha * RATE(1, fieldName) / 1024.0 + /*old value*/(1-alpha) * STATS(3).fieldName; \
272 \
273 os << time.ToDouble (Time::S) << "\t" \
Alexander Afanasyev37b84c52013-04-26 13:38:52 -0700274 << m_node << "\t"; \
275 if (stats->first) \
276 { \
277 os \
278 << stats->first->GetId () << "\t" \
279 << *stats->first << "\t"; \
280 } \
281 else \
282 { \
283 os << "-1\tall\t"; \
284 } \
285 os \
Alexander Afanasyevc9d5c1a2012-11-21 18:00:26 -0800286 << printName << "\t" \
287 << STATS(2).fieldName << "\t" \
288 << STATS(3).fieldName << "\t" \
289 << STATS(0).fieldName << "\t" \
Alexander Afanasyev59314802012-11-26 14:56:04 -0800290 << STATS(1).fieldName / 1024.0 << "\n";
Alexander Afanasyevc9d5c1a2012-11-21 18:00:26 -0800291
292void
293L3RateTracer::Print (std::ostream &os) const
294{
Alexander Afanasyev37b84c52013-04-26 13:38:52 -0700295 Time time = Simulator::Now ();
296
Alexander Afanasyevc9d5c1a2012-11-21 18:00:26 -0800297 for (std::map<Ptr<const Face>, boost::tuple<Stats, Stats, Stats, Stats> >::iterator stats = m_stats.begin ();
298 stats != m_stats.end ();
299 stats++)
300 {
Alexander Afanasyev37b84c52013-04-26 13:38:52 -0700301 if (!stats->first)
302 continue;
Alexander Afanasyevc9d5c1a2012-11-21 18:00:26 -0800303
304 PRINTER ("InInterests", m_inInterests);
305 PRINTER ("OutInterests", m_outInterests);
Alexander Afanasyevf1a4f1e2013-03-18 08:37:49 -0600306 PRINTER ("DropInterests", m_dropInterests);
Alexander Afanasyev37b84c52013-04-26 13:38:52 -0700307
Alexander Afanasyevc9d5c1a2012-11-21 18:00:26 -0800308 PRINTER ("InNacks", m_inNacks);
309 PRINTER ("OutNacks", m_outNacks);
Alexander Afanasyevf1a4f1e2013-03-18 08:37:49 -0600310 PRINTER ("DropNacks", m_dropNacks);
Alexander Afanasyevc9d5c1a2012-11-21 18:00:26 -0800311
312 PRINTER ("InData", m_inData);
313 PRINTER ("OutData", m_outData);
Alexander Afanasyevf1a4f1e2013-03-18 08:37:49 -0600314 PRINTER ("DropData", m_dropData);
Alexander Afanasyevbf939292013-07-15 10:10:01 -0700315
316 PRINTER ("InSatisfiedInterests", m_satisfiedInterests);
317 PRINTER ("InTimedOutInterests", m_timedOutInterests);
318
319 PRINTER ("OutSatisfiedInterests", m_outSatisfiedInterests);
320 PRINTER ("OutTimedOutInterests", m_outTimedOutInterests);
Alexander Afanasyevc9d5c1a2012-11-21 18:00:26 -0800321 }
Alexander Afanasyev37b84c52013-04-26 13:38:52 -0700322
323 {
324 std::map<Ptr<const Face>, boost::tuple<Stats, Stats, Stats, Stats> >::iterator stats = m_stats.find (Ptr<const Face> (0));
Alexander Afanasyev6692e0b2013-05-06 10:38:50 -0700325 if (stats != m_stats.end ())
326 {
327 PRINTER ("SatisfiedInterests", m_satisfiedInterests);
328 PRINTER ("TimedOutInterests", m_timedOutInterests);
329 }
Alexander Afanasyev37b84c52013-04-26 13:38:52 -0700330 }
Alexander Afanasyevc9d5c1a2012-11-21 18:00:26 -0800331}
332
333
334void
Alexander Afanasyevfaa01f92013-07-10 18:34:31 -0700335L3RateTracer::OutInterests (Ptr<const Interest> interest, Ptr<const Face> face)
Alexander Afanasyevc9d5c1a2012-11-21 18:00:26 -0800336{
337 m_stats[face].get<0> ().m_outInterests ++;
Alexander Afanasyevfaa01f92013-07-10 18:34:31 -0700338 if (interest->GetWire ())
339 {
340 m_stats[face].get<1> ().m_outInterests += interest->GetWire ()->GetSize ();
341 }
Alexander Afanasyevc9d5c1a2012-11-21 18:00:26 -0800342}
343
344void
Alexander Afanasyevfaa01f92013-07-10 18:34:31 -0700345L3RateTracer::InInterests (Ptr<const Interest> interest, Ptr<const Face> face)
Alexander Afanasyevc9d5c1a2012-11-21 18:00:26 -0800346{
347 m_stats[face].get<0> ().m_inInterests ++;
Alexander Afanasyevfaa01f92013-07-10 18:34:31 -0700348 if (interest->GetWire ())
349 {
350 m_stats[face].get<1> ().m_inInterests += interest->GetWire ()->GetSize ();
351 }
Alexander Afanasyevc9d5c1a2012-11-21 18:00:26 -0800352}
353
354void
Alexander Afanasyevfaa01f92013-07-10 18:34:31 -0700355L3RateTracer::DropInterests (Ptr<const Interest> interest, Ptr<const Face> face)
Alexander Afanasyevc9d5c1a2012-11-21 18:00:26 -0800356{
357 m_stats[face].get<0> ().m_dropInterests ++;
Alexander Afanasyevfaa01f92013-07-10 18:34:31 -0700358 if (interest->GetWire ())
359 {
360 m_stats[face].get<1> ().m_dropInterests += interest->GetWire ()->GetSize ();
361 }
Alexander Afanasyevc9d5c1a2012-11-21 18:00:26 -0800362}
363
364void
Alexander Afanasyevfaa01f92013-07-10 18:34:31 -0700365L3RateTracer::OutNacks (Ptr<const Interest> interest, Ptr<const Face> face)
Alexander Afanasyevc9d5c1a2012-11-21 18:00:26 -0800366{
367 m_stats[face].get<0> ().m_outNacks ++;
Alexander Afanasyevfaa01f92013-07-10 18:34:31 -0700368 if (interest->GetWire ())
369 {
370 m_stats[face].get<1> ().m_outNacks += interest->GetWire ()->GetSize ();
371 }
Alexander Afanasyevc9d5c1a2012-11-21 18:00:26 -0800372}
373
374void
Alexander Afanasyevfaa01f92013-07-10 18:34:31 -0700375L3RateTracer::InNacks (Ptr<const Interest> interest, Ptr<const Face> face)
Alexander Afanasyevc9d5c1a2012-11-21 18:00:26 -0800376{
377 m_stats[face].get<0> ().m_inNacks ++;
Alexander Afanasyevfaa01f92013-07-10 18:34:31 -0700378 if (interest->GetWire ())
379 {
380 m_stats[face].get<1> ().m_inNacks += interest->GetWire ()->GetSize ();
381 }
Alexander Afanasyevc9d5c1a2012-11-21 18:00:26 -0800382}
383
384void
Alexander Afanasyevfaa01f92013-07-10 18:34:31 -0700385L3RateTracer::DropNacks (Ptr<const Interest> interest, Ptr<const Face> face)
Alexander Afanasyevc9d5c1a2012-11-21 18:00:26 -0800386{
387 m_stats[face].get<0> ().m_dropNacks ++;
Alexander Afanasyevfaa01f92013-07-10 18:34:31 -0700388 if (interest->GetWire ())
389 {
390 m_stats[face].get<1> ().m_dropNacks += interest->GetWire ()->GetSize ();
391 }
Alexander Afanasyevc9d5c1a2012-11-21 18:00:26 -0800392}
393
394void
Alexander Afanasyev772f51b2013-08-01 18:53:25 -0700395L3RateTracer::OutData (Ptr<const Data> data,
Alexander Afanasyevc9d5c1a2012-11-21 18:00:26 -0800396 bool fromCache, Ptr<const Face> face)
397{
Alexander Afanasyev59314802012-11-26 14:56:04 -0800398 m_stats[face].get<0> ().m_outData ++;
Alexander Afanasyevfaa01f92013-07-10 18:34:31 -0700399 if (data->GetWire ())
400 {
401 m_stats[face].get<1> ().m_outData += data->GetWire ()->GetSize ();
402 }
Alexander Afanasyevc9d5c1a2012-11-21 18:00:26 -0800403}
404
405void
Alexander Afanasyev772f51b2013-08-01 18:53:25 -0700406L3RateTracer::InData (Ptr<const Data> data,
Alexander Afanasyevc9d5c1a2012-11-21 18:00:26 -0800407 Ptr<const Face> face)
408{
Alexander Afanasyev59314802012-11-26 14:56:04 -0800409 m_stats[face].get<0> ().m_inData ++;
Alexander Afanasyevfaa01f92013-07-10 18:34:31 -0700410 if (data->GetWire ())
411 {
412 m_stats[face].get<1> ().m_inData += data->GetWire ()->GetSize ();
413 }
Alexander Afanasyevc9d5c1a2012-11-21 18:00:26 -0800414}
415
416void
Alexander Afanasyev772f51b2013-08-01 18:53:25 -0700417L3RateTracer::DropData (Ptr<const Data> data,
Alexander Afanasyevc9d5c1a2012-11-21 18:00:26 -0800418 Ptr<const Face> face)
419{
420 m_stats[face].get<0> ().m_dropData ++;
Alexander Afanasyevfaa01f92013-07-10 18:34:31 -0700421 if (data->GetWire ())
422 {
423 m_stats[face].get<1> ().m_dropData += data->GetWire ()->GetSize ();
424 }
Alexander Afanasyevc9d5c1a2012-11-21 18:00:26 -0800425}
426
Alexander Afanasyev37b84c52013-04-26 13:38:52 -0700427void
Alexander Afanasyevbf939292013-07-15 10:10:01 -0700428L3RateTracer::SatisfiedInterests (Ptr<const pit::Entry> entry)
Alexander Afanasyev37b84c52013-04-26 13:38:52 -0700429{
430 m_stats[0].get<0> ().m_satisfiedInterests ++;
431 // no "size" stats
Alexander Afanasyevbf939292013-07-15 10:10:01 -0700432
433 for (pit::Entry::in_container::const_iterator i = entry->GetIncoming ().begin ();
434 i != entry->GetIncoming ().end ();
435 i++)
436 {
437 m_stats[i->m_face].get<0> ().m_satisfiedInterests ++;
Alexander Afanasyevfaa01f92013-07-10 18:34:31 -0700438}
Alexander Afanasyevbf939292013-07-15 10:10:01 -0700439
440 for (pit::Entry::out_container::const_iterator i = entry->GetOutgoing ().begin ();
441 i != entry->GetOutgoing ().end ();
442 i++)
443 {
444 m_stats[i->m_face].get<0> ().m_outSatisfiedInterests ++;
445 }
Alexander Afanasyev37b84c52013-04-26 13:38:52 -0700446}
447
448void
Alexander Afanasyevbf939292013-07-15 10:10:01 -0700449L3RateTracer::TimedOutInterests (Ptr<const pit::Entry> entry)
Alexander Afanasyev37b84c52013-04-26 13:38:52 -0700450{
451 m_stats[0].get<0> ().m_timedOutInterests ++;
452 // no "size" stats
Alexander Afanasyevbf939292013-07-15 10:10:01 -0700453
454 for (pit::Entry::in_container::const_iterator i = entry->GetIncoming ().begin ();
455 i != entry->GetIncoming ().end ();
456 i++)
457 {
458 m_stats[i->m_face].get<0> ().m_timedOutInterests ++;
Alexander Afanasyevfaa01f92013-07-10 18:34:31 -0700459}
Alexander Afanasyevbf939292013-07-15 10:10:01 -0700460
461 for (pit::Entry::out_container::const_iterator i = entry->GetOutgoing ().begin ();
462 i != entry->GetOutgoing ().end ();
463 i++)
464 {
465 m_stats[i->m_face].get<0> ().m_outTimedOutInterests ++;
466 }
Alexander Afanasyev37b84c52013-04-26 13:38:52 -0700467}
468
469
Alexander Afanasyevc9d5c1a2012-11-21 18:00:26 -0800470} // namespace ndn
471} // namespace ns3