blob: 435a652af6492cb840b5abe8c067d8c1fd6273b1 [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 Afanasyevc9d5c1a2012-11-21 18:00:26 -080056L3RateTracer::InstallAll (const std::string &file, Time averagingPeriod/* = Seconds (0.5)*/)
57{
58 std::list<Ptr<L3RateTracer> > tracers;
Alexander Afanasyev5352af32013-07-15 09:51:28 -070059 boost::shared_ptr<std::ostream> outputStream;
60 if (file != "-")
61 {
62 boost::shared_ptr<std::ofstream> os (new std::ofstream ());
63 os->open (file.c_str (), std::ios_base::out | std::ios_base::trunc);
Alexander Afanasyevc9d5c1a2012-11-21 18:00:26 -080064
Alexander Afanasyev5352af32013-07-15 09:51:28 -070065 if (!os->is_open ())
Alexander Afanasyev3fe94dc2013-08-09 17:12:12 -070066 {
67 NS_LOG_ERROR ("File " << file << " cannot be opened for writing. Tracing disabled");
68 return;
69 }
Alexander Afanasyev5352af32013-07-15 09:51:28 -070070
71 outputStream = os;
72 }
73 else
74 {
75 outputStream = boost::shared_ptr<std::ostream> (&std::cout, NullDeleter<std::ostream>);
76 }
Alexander Afanasyevc9d5c1a2012-11-21 18:00:26 -080077
78 for (NodeList::Iterator node = NodeList::Begin ();
79 node != NodeList::End ();
80 node++)
81 {
Alexander Afanasyev5352af32013-07-15 09:51:28 -070082 Ptr<L3RateTracer> trace = Install (*node, outputStream, averagingPeriod);
Alexander Afanasyevc9d5c1a2012-11-21 18:00:26 -080083 tracers.push_back (trace);
84 }
85
86 if (tracers.size () > 0)
87 {
88 // *m_l3RateTrace << "# "; // not necessary for R's read.table
89 tracers.front ()->PrintHeader (*outputStream);
90 *outputStream << "\n";
91 }
92
Alexander Afanasyev3fe94dc2013-08-09 17:12:12 -070093 g_tracers.push_back (boost::make_tuple (outputStream, tracers));
Alexander Afanasyevc9d5c1a2012-11-21 18:00:26 -080094}
95
Alexander Afanasyev3fe94dc2013-08-09 17:12:12 -070096void
Alexander Afanasyev5352af32013-07-15 09:51:28 -070097L3RateTracer::Install (const NodeContainer &nodes, const std::string &file, Time averagingPeriod/* = Seconds (0.5)*/)
98{
99 using namespace boost;
100 using namespace std;
101
102 std::list<Ptr<L3RateTracer> > tracers;
103 boost::shared_ptr<std::ostream> outputStream;
104 if (file != "-")
105 {
106 boost::shared_ptr<std::ofstream> os (new std::ofstream ());
107 os->open (file.c_str (), std::ios_base::out | std::ios_base::trunc);
108
109 if (!os->is_open ())
Alexander Afanasyev3fe94dc2013-08-09 17:12:12 -0700110 {
111 NS_LOG_ERROR ("File " << file << " cannot be opened for writing. Tracing disabled");
112 return;
113 }
Alexander Afanasyev5352af32013-07-15 09:51:28 -0700114
115 outputStream = os;
116 }
117 else
118 {
119 outputStream = boost::shared_ptr<std::ostream> (&std::cout, NullDeleter<std::ostream>);
120 }
121
122 for (NodeContainer::Iterator node = nodes.Begin ();
123 node != nodes.End ();
124 node++)
125 {
126 Ptr<L3RateTracer> trace = Install (*node, outputStream, averagingPeriod);
127 tracers.push_back (trace);
128 }
129
130 if (tracers.size () > 0)
131 {
132 // *m_l3RateTrace << "# "; // not necessary for R's read.table
133 tracers.front ()->PrintHeader (*outputStream);
134 *outputStream << "\n";
135 }
136
Alexander Afanasyev3fe94dc2013-08-09 17:12:12 -0700137 g_tracers.push_back (boost::make_tuple (outputStream, tracers));
Alexander Afanasyev5352af32013-07-15 09:51:28 -0700138}
139
Alexander Afanasyev3fe94dc2013-08-09 17:12:12 -0700140void
Alexander Afanasyev5352af32013-07-15 09:51:28 -0700141L3RateTracer::Install (Ptr<Node> node, const std::string &file, Time averagingPeriod/* = Seconds (0.5)*/)
142{
143 using namespace boost;
144 using namespace std;
145
146 std::list<Ptr<L3RateTracer> > tracers;
147 boost::shared_ptr<std::ostream> outputStream;
148 if (file != "-")
149 {
150 boost::shared_ptr<std::ofstream> os (new std::ofstream ());
151 os->open (file.c_str (), std::ios_base::out | std::ios_base::trunc);
152
153 if (!os->is_open ())
Alexander Afanasyev3fe94dc2013-08-09 17:12:12 -0700154 {
155 NS_LOG_ERROR ("File " << file << " cannot be opened for writing. Tracing disabled");
156 return;
157 }
Alexander Afanasyev5352af32013-07-15 09:51:28 -0700158
159 outputStream = os;
160 }
161 else
162 {
163 outputStream = boost::shared_ptr<std::ostream> (&std::cout, NullDeleter<std::ostream>);
164 }
165
166 Ptr<L3RateTracer> trace = Install (node, outputStream, averagingPeriod);
167 tracers.push_back (trace);
168
169 if (tracers.size () > 0)
170 {
171 // *m_l3RateTrace << "# "; // not necessary for R's read.table
172 tracers.front ()->PrintHeader (*outputStream);
173 *outputStream << "\n";
174 }
175
Alexander Afanasyev3fe94dc2013-08-09 17:12:12 -0700176 g_tracers.push_back (boost::make_tuple (outputStream, tracers));
Alexander Afanasyev5352af32013-07-15 09:51:28 -0700177}
178
179
180Ptr<L3RateTracer>
181L3RateTracer::Install (Ptr<Node> node,
182 boost::shared_ptr<std::ostream> outputStream,
183 Time averagingPeriod/* = Seconds (0.5)*/)
184{
185 NS_LOG_DEBUG ("Node: " << node->GetId ());
186
187 Ptr<L3RateTracer> trace = Create<L3RateTracer> (outputStream, node);
188 trace->SetAveragingPeriod (averagingPeriod);
189
190 return trace;
191}
192
Alexander Afanasyevc9d5c1a2012-11-21 18:00:26 -0800193
194L3RateTracer::L3RateTracer (boost::shared_ptr<std::ostream> os, Ptr<Node> node)
195 : L3Tracer (node)
196 , m_os (os)
197{
198 SetAveragingPeriod (Seconds (1.0));
199}
200
201L3RateTracer::L3RateTracer (boost::shared_ptr<std::ostream> os, const std::string &node)
202 : L3Tracer (node)
203 , m_os (os)
204{
205 SetAveragingPeriod (Seconds (1.0));
206}
207
208L3RateTracer::~L3RateTracer ()
209{
210 m_printEvent.Cancel ();
211}
212
213void
214L3RateTracer::SetAveragingPeriod (const Time &period)
215{
216 m_period = period;
217 m_printEvent.Cancel ();
218 m_printEvent = Simulator::Schedule (m_period, &L3RateTracer::PeriodicPrinter, this);
219}
220
221void
222L3RateTracer::PeriodicPrinter ()
223{
224 Print (*m_os);
225 Reset ();
Alexander Afanasyev37b84c52013-04-26 13:38:52 -0700226
Alexander Afanasyevc9d5c1a2012-11-21 18:00:26 -0800227 m_printEvent = Simulator::Schedule (m_period, &L3RateTracer::PeriodicPrinter, this);
228}
229
230void
231L3RateTracer::PrintHeader (std::ostream &os) const
232{
233 os << "Time" << "\t"
234
235 << "Node" << "\t"
236 << "FaceId" << "\t"
237 << "FaceDescr" << "\t"
238
239 << "Type" << "\t"
240 << "Packets" << "\t"
241 << "Kilobytes" << "\t"
242 << "PacketRaw" << "\t"
243 << "KilobytesRaw";
244}
245
246void
247L3RateTracer::Reset ()
248{
249 for (std::map<Ptr<const Face>, boost::tuple<Stats, Stats, Stats, Stats> >::iterator stats = m_stats.begin ();
250 stats != m_stats.end ();
251 stats++)
252 {
253 stats->second.get<0> ().Reset ();
254 stats->second.get<1> ().Reset ();
255 }
256}
257
258const double alpha = 0.8;
259
260#define STATS(INDEX) stats->second.get<INDEX> ()
261#define RATE(INDEX, fieldName) STATS(INDEX).fieldName / m_period.ToDouble (Time::S)
262
263#define PRINTER(printName, fieldName) \
264 STATS(2).fieldName = /*new value*/alpha * RATE(0, fieldName) + /*old value*/(1-alpha) * STATS(2).fieldName; \
265 STATS(3).fieldName = /*new value*/alpha * RATE(1, fieldName) / 1024.0 + /*old value*/(1-alpha) * STATS(3).fieldName; \
266 \
267 os << time.ToDouble (Time::S) << "\t" \
Alexander Afanasyev37b84c52013-04-26 13:38:52 -0700268 << m_node << "\t"; \
269 if (stats->first) \
270 { \
271 os \
272 << stats->first->GetId () << "\t" \
273 << *stats->first << "\t"; \
274 } \
275 else \
276 { \
277 os << "-1\tall\t"; \
278 } \
279 os \
Alexander Afanasyevc9d5c1a2012-11-21 18:00:26 -0800280 << printName << "\t" \
281 << STATS(2).fieldName << "\t" \
282 << STATS(3).fieldName << "\t" \
283 << STATS(0).fieldName << "\t" \
Alexander Afanasyev59314802012-11-26 14:56:04 -0800284 << STATS(1).fieldName / 1024.0 << "\n";
Alexander Afanasyevc9d5c1a2012-11-21 18:00:26 -0800285
286void
287L3RateTracer::Print (std::ostream &os) const
288{
Alexander Afanasyev37b84c52013-04-26 13:38:52 -0700289 Time time = Simulator::Now ();
290
Alexander Afanasyevc9d5c1a2012-11-21 18:00:26 -0800291 for (std::map<Ptr<const Face>, boost::tuple<Stats, Stats, Stats, Stats> >::iterator stats = m_stats.begin ();
292 stats != m_stats.end ();
293 stats++)
294 {
Alexander Afanasyev37b84c52013-04-26 13:38:52 -0700295 if (!stats->first)
296 continue;
Alexander Afanasyevc9d5c1a2012-11-21 18:00:26 -0800297
298 PRINTER ("InInterests", m_inInterests);
299 PRINTER ("OutInterests", m_outInterests);
Alexander Afanasyevf1a4f1e2013-03-18 08:37:49 -0600300 PRINTER ("DropInterests", m_dropInterests);
Alexander Afanasyev37b84c52013-04-26 13:38:52 -0700301
Alexander Afanasyevc9d5c1a2012-11-21 18:00:26 -0800302 PRINTER ("InNacks", m_inNacks);
303 PRINTER ("OutNacks", m_outNacks);
Alexander Afanasyevf1a4f1e2013-03-18 08:37:49 -0600304 PRINTER ("DropNacks", m_dropNacks);
Alexander Afanasyevc9d5c1a2012-11-21 18:00:26 -0800305
306 PRINTER ("InData", m_inData);
307 PRINTER ("OutData", m_outData);
Alexander Afanasyevf1a4f1e2013-03-18 08:37:49 -0600308 PRINTER ("DropData", m_dropData);
Alexander Afanasyevbf939292013-07-15 10:10:01 -0700309
310 PRINTER ("InSatisfiedInterests", m_satisfiedInterests);
311 PRINTER ("InTimedOutInterests", m_timedOutInterests);
312
313 PRINTER ("OutSatisfiedInterests", m_outSatisfiedInterests);
314 PRINTER ("OutTimedOutInterests", m_outTimedOutInterests);
Alexander Afanasyevc9d5c1a2012-11-21 18:00:26 -0800315 }
Alexander Afanasyev37b84c52013-04-26 13:38:52 -0700316
317 {
318 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 -0700319 if (stats != m_stats.end ())
320 {
321 PRINTER ("SatisfiedInterests", m_satisfiedInterests);
322 PRINTER ("TimedOutInterests", m_timedOutInterests);
323 }
Alexander Afanasyev37b84c52013-04-26 13:38:52 -0700324 }
Alexander Afanasyevc9d5c1a2012-11-21 18:00:26 -0800325}
326
327
328void
Alexander Afanasyevfaa01f92013-07-10 18:34:31 -0700329L3RateTracer::OutInterests (Ptr<const Interest> interest, Ptr<const Face> face)
Alexander Afanasyevc9d5c1a2012-11-21 18:00:26 -0800330{
331 m_stats[face].get<0> ().m_outInterests ++;
Alexander Afanasyevfaa01f92013-07-10 18:34:31 -0700332 if (interest->GetWire ())
333 {
334 m_stats[face].get<1> ().m_outInterests += interest->GetWire ()->GetSize ();
335 }
Alexander Afanasyevc9d5c1a2012-11-21 18:00:26 -0800336}
337
338void
Alexander Afanasyevfaa01f92013-07-10 18:34:31 -0700339L3RateTracer::InInterests (Ptr<const Interest> interest, Ptr<const Face> face)
Alexander Afanasyevc9d5c1a2012-11-21 18:00:26 -0800340{
341 m_stats[face].get<0> ().m_inInterests ++;
Alexander Afanasyevfaa01f92013-07-10 18:34:31 -0700342 if (interest->GetWire ())
343 {
344 m_stats[face].get<1> ().m_inInterests += interest->GetWire ()->GetSize ();
345 }
Alexander Afanasyevc9d5c1a2012-11-21 18:00:26 -0800346}
347
348void
Alexander Afanasyevfaa01f92013-07-10 18:34:31 -0700349L3RateTracer::DropInterests (Ptr<const Interest> interest, Ptr<const Face> face)
Alexander Afanasyevc9d5c1a2012-11-21 18:00:26 -0800350{
351 m_stats[face].get<0> ().m_dropInterests ++;
Alexander Afanasyevfaa01f92013-07-10 18:34:31 -0700352 if (interest->GetWire ())
353 {
354 m_stats[face].get<1> ().m_dropInterests += interest->GetWire ()->GetSize ();
355 }
Alexander Afanasyevc9d5c1a2012-11-21 18:00:26 -0800356}
357
358void
Alexander Afanasyevfaa01f92013-07-10 18:34:31 -0700359L3RateTracer::OutNacks (Ptr<const Interest> interest, Ptr<const Face> face)
Alexander Afanasyevc9d5c1a2012-11-21 18:00:26 -0800360{
361 m_stats[face].get<0> ().m_outNacks ++;
Alexander Afanasyevfaa01f92013-07-10 18:34:31 -0700362 if (interest->GetWire ())
363 {
364 m_stats[face].get<1> ().m_outNacks += interest->GetWire ()->GetSize ();
365 }
Alexander Afanasyevc9d5c1a2012-11-21 18:00:26 -0800366}
367
368void
Alexander Afanasyevfaa01f92013-07-10 18:34:31 -0700369L3RateTracer::InNacks (Ptr<const Interest> interest, Ptr<const Face> face)
Alexander Afanasyevc9d5c1a2012-11-21 18:00:26 -0800370{
371 m_stats[face].get<0> ().m_inNacks ++;
Alexander Afanasyevfaa01f92013-07-10 18:34:31 -0700372 if (interest->GetWire ())
373 {
374 m_stats[face].get<1> ().m_inNacks += interest->GetWire ()->GetSize ();
375 }
Alexander Afanasyevc9d5c1a2012-11-21 18:00:26 -0800376}
377
378void
Alexander Afanasyevfaa01f92013-07-10 18:34:31 -0700379L3RateTracer::DropNacks (Ptr<const Interest> interest, Ptr<const Face> face)
Alexander Afanasyevc9d5c1a2012-11-21 18:00:26 -0800380{
381 m_stats[face].get<0> ().m_dropNacks ++;
Alexander Afanasyevfaa01f92013-07-10 18:34:31 -0700382 if (interest->GetWire ())
383 {
384 m_stats[face].get<1> ().m_dropNacks += interest->GetWire ()->GetSize ();
385 }
Alexander Afanasyevc9d5c1a2012-11-21 18:00:26 -0800386}
387
388void
Alexander Afanasyev772f51b2013-08-01 18:53:25 -0700389L3RateTracer::OutData (Ptr<const Data> data,
Alexander Afanasyevc9d5c1a2012-11-21 18:00:26 -0800390 bool fromCache, Ptr<const Face> face)
391{
Alexander Afanasyev59314802012-11-26 14:56:04 -0800392 m_stats[face].get<0> ().m_outData ++;
Alexander Afanasyevfaa01f92013-07-10 18:34:31 -0700393 if (data->GetWire ())
394 {
395 m_stats[face].get<1> ().m_outData += data->GetWire ()->GetSize ();
396 }
Alexander Afanasyevc9d5c1a2012-11-21 18:00:26 -0800397}
398
399void
Alexander Afanasyev772f51b2013-08-01 18:53:25 -0700400L3RateTracer::InData (Ptr<const Data> data,
Alexander Afanasyevc9d5c1a2012-11-21 18:00:26 -0800401 Ptr<const Face> face)
402{
Alexander Afanasyev59314802012-11-26 14:56:04 -0800403 m_stats[face].get<0> ().m_inData ++;
Alexander Afanasyevfaa01f92013-07-10 18:34:31 -0700404 if (data->GetWire ())
405 {
406 m_stats[face].get<1> ().m_inData += data->GetWire ()->GetSize ();
407 }
Alexander Afanasyevc9d5c1a2012-11-21 18:00:26 -0800408}
409
410void
Alexander Afanasyev772f51b2013-08-01 18:53:25 -0700411L3RateTracer::DropData (Ptr<const Data> data,
Alexander Afanasyevc9d5c1a2012-11-21 18:00:26 -0800412 Ptr<const Face> face)
413{
414 m_stats[face].get<0> ().m_dropData ++;
Alexander Afanasyevfaa01f92013-07-10 18:34:31 -0700415 if (data->GetWire ())
416 {
417 m_stats[face].get<1> ().m_dropData += data->GetWire ()->GetSize ();
418 }
Alexander Afanasyevc9d5c1a2012-11-21 18:00:26 -0800419}
420
Alexander Afanasyev37b84c52013-04-26 13:38:52 -0700421void
Alexander Afanasyevbf939292013-07-15 10:10:01 -0700422L3RateTracer::SatisfiedInterests (Ptr<const pit::Entry> entry)
Alexander Afanasyev37b84c52013-04-26 13:38:52 -0700423{
424 m_stats[0].get<0> ().m_satisfiedInterests ++;
425 // no "size" stats
Alexander Afanasyevbf939292013-07-15 10:10:01 -0700426
427 for (pit::Entry::in_container::const_iterator i = entry->GetIncoming ().begin ();
428 i != entry->GetIncoming ().end ();
429 i++)
430 {
431 m_stats[i->m_face].get<0> ().m_satisfiedInterests ++;
Alexander Afanasyevfaa01f92013-07-10 18:34:31 -0700432}
Alexander Afanasyevbf939292013-07-15 10:10:01 -0700433
434 for (pit::Entry::out_container::const_iterator i = entry->GetOutgoing ().begin ();
435 i != entry->GetOutgoing ().end ();
436 i++)
437 {
438 m_stats[i->m_face].get<0> ().m_outSatisfiedInterests ++;
439 }
Alexander Afanasyev37b84c52013-04-26 13:38:52 -0700440}
441
442void
Alexander Afanasyevbf939292013-07-15 10:10:01 -0700443L3RateTracer::TimedOutInterests (Ptr<const pit::Entry> entry)
Alexander Afanasyev37b84c52013-04-26 13:38:52 -0700444{
445 m_stats[0].get<0> ().m_timedOutInterests ++;
446 // no "size" stats
Alexander Afanasyevbf939292013-07-15 10:10:01 -0700447
448 for (pit::Entry::in_container::const_iterator i = entry->GetIncoming ().begin ();
449 i != entry->GetIncoming ().end ();
450 i++)
451 {
452 m_stats[i->m_face].get<0> ().m_timedOutInterests ++;
Alexander Afanasyevfaa01f92013-07-10 18:34:31 -0700453}
Alexander Afanasyevbf939292013-07-15 10:10:01 -0700454
455 for (pit::Entry::out_container::const_iterator i = entry->GetOutgoing ().begin ();
456 i != entry->GetOutgoing ().end ();
457 i++)
458 {
459 m_stats[i->m_face].get<0> ().m_outTimedOutInterests ++;
460 }
Alexander Afanasyev37b84c52013-04-26 13:38:52 -0700461}
462
463
Alexander Afanasyevc9d5c1a2012-11-21 18:00:26 -0800464} // namespace ndn
465} // namespace ns3