blob: 3d9a1f44d3440b71cfd773597e8fbe02ab05ccdd [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"
33#include "ns3/ndn-content-object.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 Afanasyev5352af32013-07-15 09:51:28 -070047template<class T>
48static inline void
49NullDeleter (T *ptr)
50{
51}
Alexander Afanasyevc9d5c1a2012-11-21 18:00:26 -080052
53boost::tuple< boost::shared_ptr<std::ostream>, std::list<Ptr<L3RateTracer> > >
54L3RateTracer::InstallAll (const std::string &file, Time averagingPeriod/* = Seconds (0.5)*/)
55{
56 std::list<Ptr<L3RateTracer> > tracers;
Alexander Afanasyev5352af32013-07-15 09:51:28 -070057 boost::shared_ptr<std::ostream> outputStream;
58 if (file != "-")
59 {
60 boost::shared_ptr<std::ofstream> os (new std::ofstream ());
61 os->open (file.c_str (), std::ios_base::out | std::ios_base::trunc);
Alexander Afanasyevc9d5c1a2012-11-21 18:00:26 -080062
Alexander Afanasyev5352af32013-07-15 09:51:28 -070063 if (!os->is_open ())
Alexander Afanasyevfaa01f92013-07-10 18:34:31 -070064 return boost::make_tuple (outputStream, tracers);
Alexander Afanasyev5352af32013-07-15 09:51:28 -070065
66 outputStream = os;
67 }
68 else
69 {
70 outputStream = boost::shared_ptr<std::ostream> (&std::cout, NullDeleter<std::ostream>);
71 }
Alexander Afanasyevc9d5c1a2012-11-21 18:00:26 -080072
73 for (NodeList::Iterator node = NodeList::Begin ();
74 node != NodeList::End ();
75 node++)
76 {
Alexander Afanasyev5352af32013-07-15 09:51:28 -070077 Ptr<L3RateTracer> trace = Install (*node, outputStream, averagingPeriod);
Alexander Afanasyevc9d5c1a2012-11-21 18:00:26 -080078 tracers.push_back (trace);
79 }
80
81 if (tracers.size () > 0)
82 {
83 // *m_l3RateTrace << "# "; // not necessary for R's read.table
84 tracers.front ()->PrintHeader (*outputStream);
85 *outputStream << "\n";
86 }
87
88 return boost::make_tuple (outputStream, tracers);
89}
90
Alexander Afanasyev5352af32013-07-15 09:51:28 -070091boost::tuple< boost::shared_ptr<std::ostream>, std::list<Ptr<L3RateTracer> > >
92L3RateTracer::Install (const NodeContainer &nodes, const std::string &file, Time averagingPeriod/* = Seconds (0.5)*/)
93{
94 using namespace boost;
95 using namespace std;
96
97 std::list<Ptr<L3RateTracer> > tracers;
98 boost::shared_ptr<std::ostream> outputStream;
99 if (file != "-")
100 {
101 boost::shared_ptr<std::ofstream> os (new std::ofstream ());
102 os->open (file.c_str (), std::ios_base::out | std::ios_base::trunc);
103
104 if (!os->is_open ())
105 return boost::make_tuple (outputStream, tracers);
106
107 outputStream = os;
108 }
109 else
110 {
111 outputStream = boost::shared_ptr<std::ostream> (&std::cout, NullDeleter<std::ostream>);
112 }
113
114 for (NodeContainer::Iterator node = nodes.Begin ();
115 node != nodes.End ();
116 node++)
117 {
118 Ptr<L3RateTracer> trace = Install (*node, outputStream, averagingPeriod);
119 tracers.push_back (trace);
120 }
121
122 if (tracers.size () > 0)
123 {
124 // *m_l3RateTrace << "# "; // not necessary for R's read.table
125 tracers.front ()->PrintHeader (*outputStream);
126 *outputStream << "\n";
127 }
128
129 return boost::make_tuple (outputStream, tracers);
130}
131
132boost::tuple< boost::shared_ptr<std::ostream>, std::list<Ptr<L3RateTracer> > >
133L3RateTracer::Install (Ptr<Node> node, const std::string &file, Time averagingPeriod/* = Seconds (0.5)*/)
134{
135 using namespace boost;
136 using namespace std;
137
138 std::list<Ptr<L3RateTracer> > tracers;
139 boost::shared_ptr<std::ostream> outputStream;
140 if (file != "-")
141 {
142 boost::shared_ptr<std::ofstream> os (new std::ofstream ());
143 os->open (file.c_str (), std::ios_base::out | std::ios_base::trunc);
144
145 if (!os->is_open ())
146 return boost::make_tuple (outputStream, tracers);
147
148 outputStream = os;
149 }
150 else
151 {
152 outputStream = boost::shared_ptr<std::ostream> (&std::cout, NullDeleter<std::ostream>);
153 }
154
155 Ptr<L3RateTracer> trace = Install (node, outputStream, averagingPeriod);
156 tracers.push_back (trace);
157
158 if (tracers.size () > 0)
159 {
160 // *m_l3RateTrace << "# "; // not necessary for R's read.table
161 tracers.front ()->PrintHeader (*outputStream);
162 *outputStream << "\n";
163 }
164
165 return boost::make_tuple (outputStream, tracers);
166}
167
168
169Ptr<L3RateTracer>
170L3RateTracer::Install (Ptr<Node> node,
171 boost::shared_ptr<std::ostream> outputStream,
172 Time averagingPeriod/* = Seconds (0.5)*/)
173{
174 NS_LOG_DEBUG ("Node: " << node->GetId ());
175
176 Ptr<L3RateTracer> trace = Create<L3RateTracer> (outputStream, node);
177 trace->SetAveragingPeriod (averagingPeriod);
178
179 return trace;
180}
181
Alexander Afanasyevc9d5c1a2012-11-21 18:00:26 -0800182
183L3RateTracer::L3RateTracer (boost::shared_ptr<std::ostream> os, Ptr<Node> node)
184 : L3Tracer (node)
185 , m_os (os)
186{
187 SetAveragingPeriod (Seconds (1.0));
188}
189
190L3RateTracer::L3RateTracer (boost::shared_ptr<std::ostream> os, const std::string &node)
191 : L3Tracer (node)
192 , m_os (os)
193{
194 SetAveragingPeriod (Seconds (1.0));
195}
196
197L3RateTracer::~L3RateTracer ()
198{
199 m_printEvent.Cancel ();
200}
201
202void
203L3RateTracer::SetAveragingPeriod (const Time &period)
204{
205 m_period = period;
206 m_printEvent.Cancel ();
207 m_printEvent = Simulator::Schedule (m_period, &L3RateTracer::PeriodicPrinter, this);
208}
209
210void
211L3RateTracer::PeriodicPrinter ()
212{
213 Print (*m_os);
214 Reset ();
Alexander Afanasyev37b84c52013-04-26 13:38:52 -0700215
Alexander Afanasyevc9d5c1a2012-11-21 18:00:26 -0800216 m_printEvent = Simulator::Schedule (m_period, &L3RateTracer::PeriodicPrinter, this);
217}
218
219void
220L3RateTracer::PrintHeader (std::ostream &os) const
221{
222 os << "Time" << "\t"
223
224 << "Node" << "\t"
225 << "FaceId" << "\t"
226 << "FaceDescr" << "\t"
227
228 << "Type" << "\t"
229 << "Packets" << "\t"
230 << "Kilobytes" << "\t"
231 << "PacketRaw" << "\t"
232 << "KilobytesRaw";
233}
234
235void
236L3RateTracer::Reset ()
237{
238 for (std::map<Ptr<const Face>, boost::tuple<Stats, Stats, Stats, Stats> >::iterator stats = m_stats.begin ();
239 stats != m_stats.end ();
240 stats++)
241 {
242 stats->second.get<0> ().Reset ();
243 stats->second.get<1> ().Reset ();
244 }
245}
246
247const double alpha = 0.8;
248
249#define STATS(INDEX) stats->second.get<INDEX> ()
250#define RATE(INDEX, fieldName) STATS(INDEX).fieldName / m_period.ToDouble (Time::S)
251
252#define PRINTER(printName, fieldName) \
253 STATS(2).fieldName = /*new value*/alpha * RATE(0, fieldName) + /*old value*/(1-alpha) * STATS(2).fieldName; \
254 STATS(3).fieldName = /*new value*/alpha * RATE(1, fieldName) / 1024.0 + /*old value*/(1-alpha) * STATS(3).fieldName; \
255 \
256 os << time.ToDouble (Time::S) << "\t" \
Alexander Afanasyev37b84c52013-04-26 13:38:52 -0700257 << m_node << "\t"; \
258 if (stats->first) \
259 { \
260 os \
261 << stats->first->GetId () << "\t" \
262 << *stats->first << "\t"; \
263 } \
264 else \
265 { \
266 os << "-1\tall\t"; \
267 } \
268 os \
Alexander Afanasyevc9d5c1a2012-11-21 18:00:26 -0800269 << printName << "\t" \
270 << STATS(2).fieldName << "\t" \
271 << STATS(3).fieldName << "\t" \
272 << STATS(0).fieldName << "\t" \
Alexander Afanasyev59314802012-11-26 14:56:04 -0800273 << STATS(1).fieldName / 1024.0 << "\n";
Alexander Afanasyevc9d5c1a2012-11-21 18:00:26 -0800274
275void
276L3RateTracer::Print (std::ostream &os) const
277{
Alexander Afanasyev37b84c52013-04-26 13:38:52 -0700278 Time time = Simulator::Now ();
279
Alexander Afanasyevc9d5c1a2012-11-21 18:00:26 -0800280 for (std::map<Ptr<const Face>, boost::tuple<Stats, Stats, Stats, Stats> >::iterator stats = m_stats.begin ();
281 stats != m_stats.end ();
282 stats++)
283 {
Alexander Afanasyev37b84c52013-04-26 13:38:52 -0700284 if (!stats->first)
285 continue;
Alexander Afanasyevc9d5c1a2012-11-21 18:00:26 -0800286
287 PRINTER ("InInterests", m_inInterests);
288 PRINTER ("OutInterests", m_outInterests);
Alexander Afanasyevf1a4f1e2013-03-18 08:37:49 -0600289 PRINTER ("DropInterests", m_dropInterests);
Alexander Afanasyev37b84c52013-04-26 13:38:52 -0700290
Alexander Afanasyevc9d5c1a2012-11-21 18:00:26 -0800291 PRINTER ("InNacks", m_inNacks);
292 PRINTER ("OutNacks", m_outNacks);
Alexander Afanasyevf1a4f1e2013-03-18 08:37:49 -0600293 PRINTER ("DropNacks", m_dropNacks);
Alexander Afanasyevc9d5c1a2012-11-21 18:00:26 -0800294
295 PRINTER ("InData", m_inData);
296 PRINTER ("OutData", m_outData);
Alexander Afanasyevf1a4f1e2013-03-18 08:37:49 -0600297 PRINTER ("DropData", m_dropData);
Alexander Afanasyevbf939292013-07-15 10:10:01 -0700298
299 PRINTER ("InSatisfiedInterests", m_satisfiedInterests);
300 PRINTER ("InTimedOutInterests", m_timedOutInterests);
301
302 PRINTER ("OutSatisfiedInterests", m_outSatisfiedInterests);
303 PRINTER ("OutTimedOutInterests", m_outTimedOutInterests);
Alexander Afanasyevc9d5c1a2012-11-21 18:00:26 -0800304 }
Alexander Afanasyev37b84c52013-04-26 13:38:52 -0700305
306 {
307 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 -0700308 if (stats != m_stats.end ())
309 {
310 PRINTER ("SatisfiedInterests", m_satisfiedInterests);
311 PRINTER ("TimedOutInterests", m_timedOutInterests);
312 }
Alexander Afanasyev37b84c52013-04-26 13:38:52 -0700313 }
Alexander Afanasyevc9d5c1a2012-11-21 18:00:26 -0800314}
315
316
317void
Alexander Afanasyevfaa01f92013-07-10 18:34:31 -0700318L3RateTracer::OutInterests (Ptr<const Interest> interest, Ptr<const Face> face)
Alexander Afanasyevc9d5c1a2012-11-21 18:00:26 -0800319{
320 m_stats[face].get<0> ().m_outInterests ++;
Alexander Afanasyevfaa01f92013-07-10 18:34:31 -0700321 if (interest->GetWire ())
322 {
323 m_stats[face].get<1> ().m_outInterests += interest->GetWire ()->GetSize ();
324 }
Alexander Afanasyevc9d5c1a2012-11-21 18:00:26 -0800325}
326
327void
Alexander Afanasyevfaa01f92013-07-10 18:34:31 -0700328L3RateTracer::InInterests (Ptr<const Interest> interest, Ptr<const Face> face)
Alexander Afanasyevc9d5c1a2012-11-21 18:00:26 -0800329{
330 m_stats[face].get<0> ().m_inInterests ++;
Alexander Afanasyevfaa01f92013-07-10 18:34:31 -0700331 if (interest->GetWire ())
332 {
333 m_stats[face].get<1> ().m_inInterests += interest->GetWire ()->GetSize ();
334 }
Alexander Afanasyevc9d5c1a2012-11-21 18:00:26 -0800335}
336
337void
Alexander Afanasyevfaa01f92013-07-10 18:34:31 -0700338L3RateTracer::DropInterests (Ptr<const Interest> interest, Ptr<const Face> face)
Alexander Afanasyevc9d5c1a2012-11-21 18:00:26 -0800339{
340 m_stats[face].get<0> ().m_dropInterests ++;
Alexander Afanasyevfaa01f92013-07-10 18:34:31 -0700341 if (interest->GetWire ())
342 {
343 m_stats[face].get<1> ().m_dropInterests += interest->GetWire ()->GetSize ();
344 }
Alexander Afanasyevc9d5c1a2012-11-21 18:00:26 -0800345}
346
347void
Alexander Afanasyevfaa01f92013-07-10 18:34:31 -0700348L3RateTracer::OutNacks (Ptr<const Interest> interest, Ptr<const Face> face)
Alexander Afanasyevc9d5c1a2012-11-21 18:00:26 -0800349{
350 m_stats[face].get<0> ().m_outNacks ++;
Alexander Afanasyevfaa01f92013-07-10 18:34:31 -0700351 if (interest->GetWire ())
352 {
353 m_stats[face].get<1> ().m_outNacks += interest->GetWire ()->GetSize ();
354 }
Alexander Afanasyevc9d5c1a2012-11-21 18:00:26 -0800355}
356
357void
Alexander Afanasyevfaa01f92013-07-10 18:34:31 -0700358L3RateTracer::InNacks (Ptr<const Interest> interest, Ptr<const Face> face)
Alexander Afanasyevc9d5c1a2012-11-21 18:00:26 -0800359{
360 m_stats[face].get<0> ().m_inNacks ++;
Alexander Afanasyevfaa01f92013-07-10 18:34:31 -0700361 if (interest->GetWire ())
362 {
363 m_stats[face].get<1> ().m_inNacks += interest->GetWire ()->GetSize ();
364 }
Alexander Afanasyevc9d5c1a2012-11-21 18:00:26 -0800365}
366
367void
Alexander Afanasyevfaa01f92013-07-10 18:34:31 -0700368L3RateTracer::DropNacks (Ptr<const Interest> interest, Ptr<const Face> face)
Alexander Afanasyevc9d5c1a2012-11-21 18:00:26 -0800369{
370 m_stats[face].get<0> ().m_dropNacks ++;
Alexander Afanasyevfaa01f92013-07-10 18:34:31 -0700371 if (interest->GetWire ())
372 {
373 m_stats[face].get<1> ().m_dropNacks += interest->GetWire ()->GetSize ();
374 }
Alexander Afanasyevc9d5c1a2012-11-21 18:00:26 -0800375}
376
377void
Alexander Afanasyev772f51b2013-08-01 18:53:25 -0700378L3RateTracer::OutData (Ptr<const Data> data,
Alexander Afanasyevc9d5c1a2012-11-21 18:00:26 -0800379 bool fromCache, Ptr<const Face> face)
380{
Alexander Afanasyev59314802012-11-26 14:56:04 -0800381 m_stats[face].get<0> ().m_outData ++;
Alexander Afanasyevfaa01f92013-07-10 18:34:31 -0700382 if (data->GetWire ())
383 {
384 m_stats[face].get<1> ().m_outData += data->GetWire ()->GetSize ();
385 }
Alexander Afanasyevc9d5c1a2012-11-21 18:00:26 -0800386}
387
388void
Alexander Afanasyev772f51b2013-08-01 18:53:25 -0700389L3RateTracer::InData (Ptr<const Data> data,
Alexander Afanasyevc9d5c1a2012-11-21 18:00:26 -0800390 Ptr<const Face> face)
391{
Alexander Afanasyev59314802012-11-26 14:56:04 -0800392 m_stats[face].get<0> ().m_inData ++;
Alexander Afanasyevfaa01f92013-07-10 18:34:31 -0700393 if (data->GetWire ())
394 {
395 m_stats[face].get<1> ().m_inData += data->GetWire ()->GetSize ();
396 }
Alexander Afanasyevc9d5c1a2012-11-21 18:00:26 -0800397}
398
399void
Alexander Afanasyev772f51b2013-08-01 18:53:25 -0700400L3RateTracer::DropData (Ptr<const Data> data,
Alexander Afanasyevc9d5c1a2012-11-21 18:00:26 -0800401 Ptr<const Face> face)
402{
403 m_stats[face].get<0> ().m_dropData ++;
Alexander Afanasyevfaa01f92013-07-10 18:34:31 -0700404 if (data->GetWire ())
405 {
406 m_stats[face].get<1> ().m_dropData += data->GetWire ()->GetSize ();
407 }
Alexander Afanasyevc9d5c1a2012-11-21 18:00:26 -0800408}
409
Alexander Afanasyev37b84c52013-04-26 13:38:52 -0700410void
Alexander Afanasyevbf939292013-07-15 10:10:01 -0700411L3RateTracer::SatisfiedInterests (Ptr<const pit::Entry> entry)
Alexander Afanasyev37b84c52013-04-26 13:38:52 -0700412{
413 m_stats[0].get<0> ().m_satisfiedInterests ++;
414 // no "size" stats
Alexander Afanasyevbf939292013-07-15 10:10:01 -0700415
416 for (pit::Entry::in_container::const_iterator i = entry->GetIncoming ().begin ();
417 i != entry->GetIncoming ().end ();
418 i++)
419 {
420 m_stats[i->m_face].get<0> ().m_satisfiedInterests ++;
Alexander Afanasyevfaa01f92013-07-10 18:34:31 -0700421}
Alexander Afanasyevbf939292013-07-15 10:10:01 -0700422
423 for (pit::Entry::out_container::const_iterator i = entry->GetOutgoing ().begin ();
424 i != entry->GetOutgoing ().end ();
425 i++)
426 {
427 m_stats[i->m_face].get<0> ().m_outSatisfiedInterests ++;
428 }
Alexander Afanasyev37b84c52013-04-26 13:38:52 -0700429}
430
431void
Alexander Afanasyevbf939292013-07-15 10:10:01 -0700432L3RateTracer::TimedOutInterests (Ptr<const pit::Entry> entry)
Alexander Afanasyev37b84c52013-04-26 13:38:52 -0700433{
434 m_stats[0].get<0> ().m_timedOutInterests ++;
435 // no "size" stats
Alexander Afanasyevbf939292013-07-15 10:10:01 -0700436
437 for (pit::Entry::in_container::const_iterator i = entry->GetIncoming ().begin ();
438 i != entry->GetIncoming ().end ();
439 i++)
440 {
441 m_stats[i->m_face].get<0> ().m_timedOutInterests ++;
Alexander Afanasyevfaa01f92013-07-10 18:34:31 -0700442}
Alexander Afanasyevbf939292013-07-15 10:10:01 -0700443
444 for (pit::Entry::out_container::const_iterator i = entry->GetOutgoing ().begin ();
445 i != entry->GetOutgoing ().end ();
446 i++)
447 {
448 m_stats[i->m_face].get<0> ().m_outTimedOutInterests ++;
449 }
Alexander Afanasyev37b84c52013-04-26 13:38:52 -0700450}
451
452
Alexander Afanasyevc9d5c1a2012-11-21 18:00:26 -0800453} // namespace ndn
454} // namespace ns3