blob: 0e2db8df9cfecd5531ebaaa85b43e42b008235ff [file] [log] [blame]
Alexander Afanasyev7e71c752012-01-25 21:40:39 -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 "ipv4-rate-l3-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"
Alexander Afanasyev49165862013-01-31 00:38:20 -080027#include "ns3/node-list.h"
28#include "ns3/node.h"
29#include "ns3/log.h"
Alexander Afanasyev7e71c752012-01-25 21:40:39 -080030
31#include "ns3/ipv4-header.h"
32
Alexander Afanasyev49165862013-01-31 00:38:20 -080033#include <boost/lexical_cast.hpp>
34
35using namespace boost;
36using namespace std;
37
38NS_LOG_COMPONENT_DEFINE ("Ipv4RateL3Tracer");
39
Alexander Afanasyev7e71c752012-01-25 21:40:39 -080040namespace ns3 {
Alexander Afanasyev49165862013-01-31 00:38:20 -080041
Alexander Afanasyev5352af32013-07-15 09:51:28 -070042template<class T>
43static inline void
44NullDeleter (T *ptr)
45{
46}
47
Alexander Afanasyev49165862013-01-31 00:38:20 -080048boost::tuple< boost::shared_ptr<std::ostream>, std::list<Ptr<Ipv4RateL3Tracer> > >
49Ipv4RateL3Tracer::InstallAll (const std::string &file, Time averagingPeriod/* = Seconds (0.5)*/)
50{
51 std::list<Ptr<Ipv4RateL3Tracer> > tracers;
Alexander Afanasyev5352af32013-07-15 09:51:28 -070052 boost::shared_ptr<std::ostream> outputStream;
53 if (file != "-")
54 {
55 boost::shared_ptr<std::ofstream> os (new std::ofstream ());
56 os->open (file.c_str (), std::ios_base::out | std::ios_base::trunc);
Alexander Afanasyev49165862013-01-31 00:38:20 -080057
Alexander Afanasyev5352af32013-07-15 09:51:28 -070058 if (!os->is_open ())
59 return boost::make_tuple (outputStream, tracers);
60
61 outputStream = os;
62 }
63 else
64 {
65 outputStream = boost::shared_ptr<std::ostream> (&std::cout, NullDeleter<std::ostream>);
66 }
Alexander Afanasyev49165862013-01-31 00:38:20 -080067
68 for (NodeList::Iterator node = NodeList::Begin ();
69 node != NodeList::End ();
70 node++)
71 {
Alexander Afanasyev5352af32013-07-15 09:51:28 -070072 Ptr<Ipv4RateL3Tracer> trace = Install (*node, outputStream, averagingPeriod);
Alexander Afanasyev49165862013-01-31 00:38:20 -080073 tracers.push_back (trace);
74 }
75
76 if (tracers.size () > 0)
77 {
78 // *m_l3RateTrace << "# "; // not necessary for R's read.table
79 tracers.front ()->PrintHeader (*outputStream);
80 *outputStream << "\n";
81 }
82
83 return boost::make_tuple (outputStream, tracers);
84}
85
Alexander Afanasyev5352af32013-07-15 09:51:28 -070086boost::tuple< boost::shared_ptr<std::ostream>, std::list<Ptr<Ipv4RateL3Tracer> > >
87Ipv4RateL3Tracer::Install (const NodeContainer &nodes, const std::string &file, Time averagingPeriod/* = Seconds (0.5)*/)
88{
89 using namespace boost;
90 using namespace std;
91
92 std::list<Ptr<Ipv4RateL3Tracer> > tracers;
93 boost::shared_ptr<std::ostream> outputStream;
94 if (file != "-")
95 {
96 boost::shared_ptr<std::ofstream> os (new std::ofstream ());
97 os->open (file.c_str (), std::ios_base::out | std::ios_base::trunc);
98
99 if (!os->is_open ())
100 return boost::make_tuple (outputStream, tracers);
101
102 outputStream = os;
103 }
104 else
105 {
106 outputStream = boost::shared_ptr<std::ostream> (&std::cout, NullDeleter<std::ostream>);
107 }
108
109 for (NodeContainer::Iterator node = nodes.Begin ();
110 node != nodes.End ();
111 node++)
112 {
113 Ptr<Ipv4RateL3Tracer> trace = Install (*node, outputStream, averagingPeriod);
114 tracers.push_back (trace);
115 }
116
117 if (tracers.size () > 0)
118 {
119 // *m_l3RateTrace << "# "; // not necessary for R's read.table
120 tracers.front ()->PrintHeader (*outputStream);
121 *outputStream << "\n";
122 }
123
124 return boost::make_tuple (outputStream, tracers);
125}
126
127boost::tuple< boost::shared_ptr<std::ostream>, std::list<Ptr<Ipv4RateL3Tracer> > >
128Ipv4RateL3Tracer::Install (Ptr<Node> node, const std::string &file, Time averagingPeriod/* = Seconds (0.5)*/)
129{
130 using namespace boost;
131 using namespace std;
132
133 std::list<Ptr<Ipv4RateL3Tracer> > tracers;
134 boost::shared_ptr<std::ostream> outputStream;
135 if (file != "-")
136 {
137 boost::shared_ptr<std::ofstream> os (new std::ofstream ());
138 os->open (file.c_str (), std::ios_base::out | std::ios_base::trunc);
139
140 if (!os->is_open ())
141 return boost::make_tuple (outputStream, tracers);
142
143 outputStream = os;
144 }
145 else
146 {
147 outputStream = boost::shared_ptr<std::ostream> (&std::cout, NullDeleter<std::ostream>);
148 }
149
150 Ptr<Ipv4RateL3Tracer> trace = Install (node, outputStream, averagingPeriod);
151 tracers.push_back (trace);
152
153 if (tracers.size () > 0)
154 {
155 // *m_l3RateTrace << "# "; // not necessary for R's read.table
156 tracers.front ()->PrintHeader (*outputStream);
157 *outputStream << "\n";
158 }
159
160 return boost::make_tuple (outputStream, tracers);
161}
162
163
164Ptr<Ipv4RateL3Tracer>
165Ipv4RateL3Tracer::Install (Ptr<Node> node,
166 boost::shared_ptr<std::ostream> outputStream,
167 Time averagingPeriod/* = Seconds (0.5)*/)
168{
169 NS_LOG_DEBUG ("Node: " << node->GetId ());
170
171 Ptr<Ipv4RateL3Tracer> trace = Create<Ipv4RateL3Tracer> (outputStream, node);
172 trace->SetAveragingPeriod (averagingPeriod);
173
174 return trace;
175}
176
Alexander Afanasyev49165862013-01-31 00:38:20 -0800177
178Ipv4RateL3Tracer::Ipv4RateL3Tracer (boost::shared_ptr<std::ostream> os, Ptr<Node> node)
Alexander Afanasyev7e71c752012-01-25 21:40:39 -0800179 : Ipv4L3Tracer (node)
180 , m_os (os)
181{
182 SetAveragingPeriod (Seconds (1.0));
183}
184
185Ipv4RateL3Tracer::~Ipv4RateL3Tracer ()
186{
187 m_printEvent.Cancel ();
188}
189
190void
191Ipv4RateL3Tracer::SetAveragingPeriod (const Time &period)
192{
193 m_period = period;
194 m_printEvent.Cancel ();
195 m_printEvent = Simulator::Schedule (m_period, &Ipv4RateL3Tracer::PeriodicPrinter, this);
196}
197
198void
199Ipv4RateL3Tracer::PeriodicPrinter ()
200{
Alexander Afanasyev49165862013-01-31 00:38:20 -0800201 Print (*m_os);
Alexander Afanasyev7e71c752012-01-25 21:40:39 -0800202 Reset ();
Alexander Afanasyev49165862013-01-31 00:38:20 -0800203
Alexander Afanasyev7e71c752012-01-25 21:40:39 -0800204 m_printEvent = Simulator::Schedule (m_period, &Ipv4RateL3Tracer::PeriodicPrinter, this);
205}
206
207void
208Ipv4RateL3Tracer::PrintHeader (std::ostream &os) const
209{
210 os << "Time" << "\t"
211
212 << "Node" << "\t"
213 << "Interface" << "\t"
214
215 << "Type" << "\t"
216 << "Packets" << "\t"
217 << "Kilobytes";
218}
219
220void
221Ipv4RateL3Tracer::Reset ()
222{
223 for (std::map<uint32_t, boost::tuple<Stats, Stats, Stats, Stats> >::iterator stats = m_stats.begin ();
224 stats != m_stats.end ();
225 stats++)
226 {
227 stats->second.get<0> ().Reset ();
228 stats->second.get<1> ().Reset ();
229 }
230}
231
232const double alpha = 0.8;
233
234#define STATS(INDEX) stats->second.get<INDEX> ()
235#define RATE(INDEX, fieldName) STATS(INDEX).fieldName / m_period.ToDouble (Time::S)
236
237#define PRINTER(printName, fieldName) \
238STATS(2).fieldName = /*new value*/alpha * RATE(0, fieldName) + /*old value*/(1-alpha) * STATS(2).fieldName; \
239STATS(3).fieldName = /*new value*/alpha * RATE(1, fieldName) / 1024.0 + /*old value*/(1-alpha) * STATS(3).fieldName; \
240 \
241os << time.ToDouble (Time::S) << "\t" \
242 << m_node << "\t" \
243 << stats->first << "\t" \
244 << printName << "\t" \
245 << STATS(2).fieldName << "\t" \
246 << STATS(3).fieldName << "\n";
247
248void
249Ipv4RateL3Tracer::Print (std::ostream &os) const
250{
251 for (std::map<uint32_t, boost::tuple<Stats, Stats, Stats, Stats> >::iterator stats = m_stats.begin ();
252 stats != m_stats.end ();
253 stats++)
254 {
255 Time time = Simulator::Now ();
256
257 PRINTER ("In", m_in);
258 PRINTER ("Out", m_out);
259 PRINTER ("Drop", m_drop);
260 }
261}
262
263void
Alexander Afanasyev5352af32013-07-15 09:51:28 -0700264Ipv4RateL3Tracer::Rx (Ptr<const Packet> packet, Ptr<Ipv4> ipv4, uint32_t iface)
Alexander Afanasyev7e71c752012-01-25 21:40:39 -0800265{
266 m_stats[iface].get<0> ().m_in ++;
267 m_stats[iface].get<1> ().m_in += packet->GetSize ();
268}
269
270void
Alexander Afanasyev5352af32013-07-15 09:51:28 -0700271Ipv4RateL3Tracer::Tx (Ptr<const Packet> packet, Ptr<Ipv4> ipv4, uint32_t iface)
Alexander Afanasyev7e71c752012-01-25 21:40:39 -0800272{
273 m_stats[iface].get<0> ().m_out ++;
274 m_stats[iface].get<1> ().m_out += packet->GetSize ();
275}
276
277void
Alexander Afanasyev5352af32013-07-15 09:51:28 -0700278Ipv4RateL3Tracer::Drop (const Ipv4Header &header, Ptr<const Packet> packet, Ipv4L3Protocol::DropReason, Ptr<Ipv4> ipv4, uint32_t iface)
Alexander Afanasyev7e71c752012-01-25 21:40:39 -0800279{
280 m_stats[iface].get<0> ().m_drop ++;
281 m_stats[iface].get<1> ().m_drop += packet->GetSize ();
282}
283
284
285} // namespace ns3