blob: f588503c00626a6056a7a7620f98a7244e7504fa [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"
34
35#include <fstream>
36#include <boost/lexical_cast.hpp>
37
38using namespace boost;
39using namespace std;
40
41NS_LOG_COMPONENT_DEFINE ("ndn.L3RateTracer");
42
43namespace ns3 {
44namespace ndn {
45
46
47boost::tuple< boost::shared_ptr<std::ostream>, std::list<Ptr<L3RateTracer> > >
48L3RateTracer::InstallAll (const std::string &file, Time averagingPeriod/* = Seconds (0.5)*/)
49{
50 std::list<Ptr<L3RateTracer> > tracers;
51 boost::shared_ptr<std::ofstream> outputStream (new std::ofstream ());
52 outputStream->open (file.c_str (), std::ios_base::out | std::ios_base::trunc);
53
54 if (!outputStream->is_open ())
55 return boost::make_tuple (outputStream, tracers);
56
57 for (NodeList::Iterator node = NodeList::Begin ();
58 node != NodeList::End ();
59 node++)
60 {
61 NS_LOG_DEBUG ("Node: " << lexical_cast<string> ((*node)->GetId ()));
62
63 Ptr<L3RateTracer> trace = Create<L3RateTracer> (outputStream, *node);
64 trace->SetAveragingPeriod (averagingPeriod);
65 tracers.push_back (trace);
66 }
67
68 if (tracers.size () > 0)
69 {
70 // *m_l3RateTrace << "# "; // not necessary for R's read.table
71 tracers.front ()->PrintHeader (*outputStream);
72 *outputStream << "\n";
73 }
74
75 return boost::make_tuple (outputStream, tracers);
76}
77
78
79L3RateTracer::L3RateTracer (boost::shared_ptr<std::ostream> os, Ptr<Node> node)
80 : L3Tracer (node)
81 , m_os (os)
82{
83 SetAveragingPeriod (Seconds (1.0));
84}
85
86L3RateTracer::L3RateTracer (boost::shared_ptr<std::ostream> os, const std::string &node)
87 : L3Tracer (node)
88 , m_os (os)
89{
90 SetAveragingPeriod (Seconds (1.0));
91}
92
93L3RateTracer::~L3RateTracer ()
94{
95 m_printEvent.Cancel ();
96}
97
98void
99L3RateTracer::SetAveragingPeriod (const Time &period)
100{
101 m_period = period;
102 m_printEvent.Cancel ();
103 m_printEvent = Simulator::Schedule (m_period, &L3RateTracer::PeriodicPrinter, this);
104}
105
106void
107L3RateTracer::PeriodicPrinter ()
108{
109 Print (*m_os);
110 Reset ();
111
112 m_printEvent = Simulator::Schedule (m_period, &L3RateTracer::PeriodicPrinter, this);
113}
114
115void
116L3RateTracer::PrintHeader (std::ostream &os) const
117{
118 os << "Time" << "\t"
119
120 << "Node" << "\t"
121 << "FaceId" << "\t"
122 << "FaceDescr" << "\t"
123
124 << "Type" << "\t"
125 << "Packets" << "\t"
126 << "Kilobytes" << "\t"
127 << "PacketRaw" << "\t"
128 << "KilobytesRaw";
129}
130
131void
132L3RateTracer::Reset ()
133{
134 for (std::map<Ptr<const Face>, boost::tuple<Stats, Stats, Stats, Stats> >::iterator stats = m_stats.begin ();
135 stats != m_stats.end ();
136 stats++)
137 {
138 stats->second.get<0> ().Reset ();
139 stats->second.get<1> ().Reset ();
140 }
141}
142
143const double alpha = 0.8;
144
145#define STATS(INDEX) stats->second.get<INDEX> ()
146#define RATE(INDEX, fieldName) STATS(INDEX).fieldName / m_period.ToDouble (Time::S)
147
148#define PRINTER(printName, fieldName) \
149 STATS(2).fieldName = /*new value*/alpha * RATE(0, fieldName) + /*old value*/(1-alpha) * STATS(2).fieldName; \
150 STATS(3).fieldName = /*new value*/alpha * RATE(1, fieldName) / 1024.0 + /*old value*/(1-alpha) * STATS(3).fieldName; \
151 \
152 os << time.ToDouble (Time::S) << "\t" \
153 << m_node << "\t" \
154 << stats->first->GetId () << "\t" \
155 << *stats->first << "\t" \
156 << printName << "\t" \
157 << STATS(2).fieldName << "\t" \
158 << STATS(3).fieldName << "\t" \
159 << STATS(0).fieldName << "\t" \
Alexander Afanasyev59314802012-11-26 14:56:04 -0800160 << STATS(1).fieldName / 1024.0 << "\n";
Alexander Afanasyevc9d5c1a2012-11-21 18:00:26 -0800161
162void
163L3RateTracer::Print (std::ostream &os) const
164{
165 for (std::map<Ptr<const Face>, boost::tuple<Stats, Stats, Stats, Stats> >::iterator stats = m_stats.begin ();
166 stats != m_stats.end ();
167 stats++)
168 {
169 Time time = Simulator::Now ();
170
171 PRINTER ("InInterests", m_inInterests);
172 PRINTER ("OutInterests", m_outInterests);
173 // PRINTER ("DropInterests", m_dropInterests);
174
175 PRINTER ("InNacks", m_inNacks);
176 PRINTER ("OutNacks", m_outNacks);
177 // PRINTER ("DropNacks", m_dropNacks);
178
179 PRINTER ("InData", m_inData);
180 PRINTER ("OutData", m_outData);
181 // PRINTER ("DropData", m_dropData);
182 }
183}
184
185
186void
187L3RateTracer::OutInterests (std::string context,
188 Ptr<const InterestHeader> header, Ptr<const Face> face)
189{
190 m_stats[face].get<0> ().m_outInterests ++;
191 m_stats[face].get<1> ().m_outInterests += header->GetSerializedSize ();
192}
193
194void
195L3RateTracer::InInterests (std::string context,
196 Ptr<const InterestHeader> header, Ptr<const Face> face)
197{
198 m_stats[face].get<0> ().m_inInterests ++;
199 m_stats[face].get<1> ().m_inInterests += header->GetSerializedSize ();
200}
201
202void
203L3RateTracer::DropInterests (std::string context,
204 Ptr<const InterestHeader> header, Ptr<const Face> face)
205{
206 m_stats[face].get<0> ().m_dropInterests ++;
207 m_stats[face].get<1> ().m_dropInterests += header->GetSerializedSize ();
208}
209
210void
211L3RateTracer::OutNacks (std::string context,
212 Ptr<const InterestHeader> header, Ptr<const Face> face)
213{
214 m_stats[face].get<0> ().m_outNacks ++;
215 m_stats[face].get<1> ().m_outNacks += header->GetSerializedSize ();
216}
217
218void
219L3RateTracer::InNacks (std::string context,
220 Ptr<const InterestHeader> header, Ptr<const Face> face)
221{
222 m_stats[face].get<0> ().m_inNacks ++;
223 m_stats[face].get<1> ().m_inNacks += header->GetSerializedSize ();
224}
225
226void
227L3RateTracer::DropNacks (std::string context,
228 Ptr<const InterestHeader> header, Ptr<const Face> face)
229{
230 m_stats[face].get<0> ().m_dropNacks ++;
231 m_stats[face].get<1> ().m_dropNacks += header->GetSerializedSize ();
232}
233
234void
235L3RateTracer::OutData (std::string context,
236 Ptr<const ContentObjectHeader> header, Ptr<const Packet> payload,
237 bool fromCache, Ptr<const Face> face)
238{
Alexander Afanasyev59314802012-11-26 14:56:04 -0800239 m_stats[face].get<0> ().m_outData ++;
240 m_stats[face].get<1> ().m_outData += header->GetSerializedSize () + payload->GetSize ();
Alexander Afanasyevc9d5c1a2012-11-21 18:00:26 -0800241}
242
243void
244L3RateTracer::InData (std::string context,
245 Ptr<const ContentObjectHeader> header, Ptr<const Packet> payload,
246 Ptr<const Face> face)
247{
Alexander Afanasyev59314802012-11-26 14:56:04 -0800248 m_stats[face].get<0> ().m_inData ++;
249 m_stats[face].get<1> ().m_inData += header->GetSerializedSize () + payload->GetSize ();
Alexander Afanasyevc9d5c1a2012-11-21 18:00:26 -0800250}
251
252void
253L3RateTracer::DropData (std::string context,
254 Ptr<const ContentObjectHeader> header, Ptr<const Packet> payload,
255 Ptr<const Face> face)
256{
257 m_stats[face].get<0> ().m_dropData ++;
258 m_stats[face].get<1> ().m_dropData += header->GetSerializedSize () + payload->GetSize ();
259}
260
261} // namespace ndn
262} // namespace ns3