A Discrete-Event Network Simulator
API
trace-helper.cc
Go to the documentation of this file.
1/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
2/*
3 * Copyright (c) 2010 University of Washington
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
19#include <stdint.h>
20#include <string>
21#include <fstream>
22
23#include "ns3/abort.h"
24#include "ns3/assert.h"
25#include "ns3/log.h"
26#include "ns3/ptr.h"
27#include "ns3/node.h"
28#include "ns3/names.h"
29#include "ns3/net-device.h"
30#include "ns3/pcap-file-wrapper.h"
31
32#include "trace-helper.h"
33
34namespace ns3 {
35
36NS_LOG_COMPONENT_DEFINE ("TraceHelper");
37
39{
41}
42
44{
46}
47
50 std::string filename,
51 std::ios::openmode filemode,
52 DataLinkType dataLinkType,
53 uint32_t snapLen,
54 int32_t tzCorrection)
55{
56 NS_LOG_FUNCTION (filename << filemode << dataLinkType << snapLen << tzCorrection);
57
58 Ptr<PcapFileWrapper> file = CreateObject<PcapFileWrapper> ();
59 file->Open (filename, filemode);
60 NS_ABORT_MSG_IF (file->Fail (), "Unable to Open " << filename << " for mode " << filemode);
61
62 file->Init (dataLinkType, snapLen, tzCorrection);
63 NS_ABORT_MSG_IF (file->Fail (), "Unable to Init " << filename);
64
65 //
66 // Note that the pcap helper promptly forgets all about the pcap file. We
67 // rely on the reference count of the file object which will soon be owned
68 // by the caller to keep the object alive. If the caller uses the file
69 // object to hook a trace source, ownership of the file object will be
70 // implicitly transferred to the callback which keeps the object alive.
71 // When the callback is destroyed (when either the trace is disconnected or
72 // the object with the trace source is deleted) the callback will be destroyed
73 // and the file object will be destroyed, releasing the pointer and closing
74 // the file.
75 //
76 return file;
77}
78
79std::string
80PcapHelper::GetFilenameFromDevice (std::string prefix, Ptr<NetDevice> device, bool useObjectNames)
81{
82 NS_LOG_FUNCTION (prefix << device << useObjectNames);
83 NS_ABORT_MSG_UNLESS (prefix.size (), "Empty prefix string");
84
85 std::ostringstream oss;
86 oss << prefix << "-";
87
88 std::string nodename;
89 std::string devicename;
90
91 Ptr<Node> node = device->GetNode ();
92
93 if (useObjectNames)
94 {
95 nodename = Names::FindName (node);
96 devicename = Names::FindName (device);
97 }
98
99 if (nodename.size ())
100 {
101 oss << nodename;
102 }
103 else
104 {
105 oss << node->GetId ();
106 }
107
108 oss << "-";
109
110 if (devicename.size ())
111 {
112 oss << devicename;
113 }
114 else
115 {
116 oss << device->GetIfIndex ();
117 }
118
119 oss << ".pcap";
120
121 return oss.str ();
122}
123
124std::string
125PcapHelper::GetFilenameFromInterfacePair (std::string prefix, Ptr<Object> object, uint32_t interface, bool useObjectNames)
126{
127 NS_LOG_FUNCTION (prefix << object << interface << useObjectNames);
128 NS_ABORT_MSG_UNLESS (prefix.size (), "Empty prefix string");
129
130 std::ostringstream oss;
131 oss << prefix << "-";
132
133 std::string objname;
134 std::string nodename;
135
136 Ptr<Node> node = object->GetObject<Node> ();
137
138 if (useObjectNames)
139 {
140 objname = Names::FindName (object);
141 nodename = Names::FindName (node);
142 }
143
144 if (objname.size ())
145 {
146 oss << objname;
147 }
148 else if (nodename.size ())
149 {
150 oss << nodename;
151 }
152 else
153 {
154 oss << "n" << node->GetId ();
155 }
156
157 oss << "-i" << interface << ".pcap";
158
159 return oss.str ();
160}
161
162//
163// The basic default trace sink. This one just writes the packet to the pcap
164// file which is good enough for most kinds of captures.
165//
166void
168{
169 NS_LOG_FUNCTION (file << p);
170 file->Write (Simulator::Now (), p);
171}
172
173void
175{
176 NS_LOG_FUNCTION (file << p);
177 file->Write (Simulator::Now (), header, p);
178}
179
181{
183}
184
186{
188}
189
191AsciiTraceHelper::CreateFileStream (std::string filename, std::ios::openmode filemode)
192{
193 NS_LOG_FUNCTION (filename << filemode);
194
195 Ptr<OutputStreamWrapper> StreamWrapper = Create<OutputStreamWrapper> (filename, filemode);
196
197 //
198 // Note that the ascii trace helper promptly forgets all about the trace file.
199 // We rely on the reference count of the file object which will soon be owned
200 // by the caller to keep the object alive. If the caller uses the stream
201 // object to hook a trace source, ownership of the stream object will be
202 // implicitly transferred to the callback which keeps the object alive.
203 // When the callback is destroyed (when either the trace is disconnected or
204 // the object with the trace source is deleted) the callback will be destroyed
205 // and the stream object will be destroyed, releasing the pointer and closing
206 // the underlying file.
207 //
208 return StreamWrapper;
209}
210
211std::string
212AsciiTraceHelper::GetFilenameFromDevice (std::string prefix, Ptr<NetDevice> device, bool useObjectNames)
213{
214 NS_LOG_FUNCTION (prefix << device << useObjectNames);
215 NS_ABORT_MSG_UNLESS (prefix.size (), "Empty prefix string");
216
217 std::ostringstream oss;
218 oss << prefix << "-";
219
220 std::string nodename;
221 std::string devicename;
222
223 Ptr<Node> node = device->GetNode ();
224
225 if (useObjectNames)
226 {
227 nodename = Names::FindName (node);
228 devicename = Names::FindName (device);
229 }
230
231 if (nodename.size ())
232 {
233 oss << nodename;
234 }
235 else
236 {
237 oss << node->GetId ();
238 }
239
240 oss << "-";
241
242 if (devicename.size ())
243 {
244 oss << devicename;
245 }
246 else
247 {
248 oss << device->GetIfIndex ();
249 }
250
251 oss << ".tr";
252
253 return oss.str ();
254}
255
256std::string
258 std::string prefix,
259 Ptr<Object> object,
260 uint32_t interface,
261 bool useObjectNames)
262{
263 NS_LOG_FUNCTION (prefix << object << interface << useObjectNames);
264 NS_ABORT_MSG_UNLESS (prefix.size (), "Empty prefix string");
265
266 std::ostringstream oss;
267 oss << prefix << "-";
268
269 std::string objname;
270 std::string nodename;
271
272 Ptr<Node> node = object->GetObject<Node> ();
273
274 if (useObjectNames)
275 {
276 objname = Names::FindName (object);
277 nodename = Names::FindName (node);
278 }
279
280 if (objname.size ())
281 {
282 oss << objname;
283 }
284 else if (nodename.size ())
285 {
286 oss << nodename;
287 }
288 else
289 {
290 oss << "n" << node->GetId ();
291 }
292
293 oss << "-i" << interface << ".tr";
294
295 return oss.str ();
296}
297
298//
299// One of the basic default trace sink sets. Enqueue:
300//
301// When a packet has been sent to a device for transmission, the device is
302// expected to place the packet onto a transmit queue even if it does not
303// have to delay the packet at all, if only to trigger this event. This
304// event will eventually translate into a '+' operation in the trace file.
305//
306// This is typically implemented by hooking the "TxQueue/Enqueue" trace hook
307// in the device (actually the Queue in the device).
308//
309void
311{
312 NS_LOG_FUNCTION (stream << p);
313 *stream->GetStream () << "+ " << Simulator::Now ().GetSeconds () << " " << *p << std::endl;
314}
315
316void
318{
319 NS_LOG_FUNCTION (stream << p);
320 *stream->GetStream () << "+ " << Simulator::Now ().GetSeconds () << " " << context << " " << *p << std::endl;
321}
322
323//
324// One of the basic default trace sink sets. Drop:
325//
326// When a packet has been sent to a device for transmission, the device is
327// expected to place the packet onto a transmit queue. If this queue is
328// full the packet will be dropped. The device is expected to trigger an
329// event to indicate that an outbound packet is being dropped. This event
330// will eventually translate into a 'd' operation in the trace file.
331//
332// This is typically implemented by hooking the "TxQueue/Drop" trace hook
333// in the device (actually the Queue in the device).
334//
335void
337{
338 NS_LOG_FUNCTION (stream << p);
339 *stream->GetStream () << "d " << Simulator::Now ().GetSeconds () << " " << *p << std::endl;
340}
341
342void
344{
345 NS_LOG_FUNCTION (stream << p);
346 *stream->GetStream () << "d " << Simulator::Now ().GetSeconds () << " " << context << " " << *p << std::endl;
347}
348
349//
350// One of the basic default trace sink sets. Dequeue:
351//
352// When a packet has been sent to a device for transmission, the device is
353// expected to place the packet onto a transmit queue even if it does not
354// have to delay the packet at all. The device removes the packet from the
355// transmit queue when the packet is ready to send, and this dequeue will
356// fire a corresponding event. This event will eventually translate into a
357// '-' operation in the trace file.
358//
359// This is typically implemented by hooking the "TxQueue/Dequeue" trace hook
360// in the device (actually the Queue in the device).
361//
362void
364{
365 NS_LOG_FUNCTION (stream << p);
366 *stream->GetStream () << "- " << Simulator::Now ().GetSeconds () << " " << *p << std::endl;
367}
368
369void
371{
372 NS_LOG_FUNCTION (stream << p);
373 *stream->GetStream () << "- " << Simulator::Now ().GetSeconds () << " " << context << " " << *p << std::endl;
374}
375
376//
377// One of the basic default trace sink sets. Receive:
378//
379// When a packet is received by a device for transmission, the device is
380// expected to trigger this event to indicate the reception has occurred.
381// This event will eventually translate into an 'r' operation in the trace
382// file.
383//
384// This is typically implemented by hooking the "MacRx" trace hook in the
385// device.
386void
388{
389 NS_LOG_FUNCTION (stream << p);
390 *stream->GetStream () << "r " << Simulator::Now ().GetSeconds () << " " << *p << std::endl;
391}
392
393void
395{
396 NS_LOG_FUNCTION (stream << p);
397 *stream->GetStream () << "r " << Simulator::Now ().GetSeconds () << " " << context << " " << *p << std::endl;
398}
399
400void
401PcapHelperForDevice::EnablePcap (std::string prefix, Ptr<NetDevice> nd, bool promiscuous, bool explicitFilename)
402{
403 EnablePcapInternal (prefix, nd, promiscuous, explicitFilename);
404}
405
406void
407PcapHelperForDevice::EnablePcap (std::string prefix, std::string ndName, bool promiscuous, bool explicitFilename)
408{
409 Ptr<NetDevice> nd = Names::Find<NetDevice> (ndName);
410 EnablePcap (prefix, nd, promiscuous, explicitFilename);
411}
412
413void
414PcapHelperForDevice::EnablePcap (std::string prefix, NetDeviceContainer d, bool promiscuous)
415{
416 for (NetDeviceContainer::Iterator i = d.Begin (); i != d.End (); ++i)
417 {
418 Ptr<NetDevice> dev = *i;
419 EnablePcap (prefix, dev, promiscuous);
420 }
421}
422
423void
424PcapHelperForDevice::EnablePcap (std::string prefix, NodeContainer n, bool promiscuous)
425{
427 for (NodeContainer::Iterator i = n.Begin (); i != n.End (); ++i)
428 {
429 Ptr<Node> node = *i;
430 for (uint32_t j = 0; j < node->GetNDevices (); ++j)
431 {
432 devs.Add (node->GetDevice (j));
433 }
434 }
435 EnablePcap (prefix, devs, promiscuous);
436}
437
438void
439PcapHelperForDevice::EnablePcapAll (std::string prefix, bool promiscuous)
440{
441 EnablePcap (prefix, NodeContainer::GetGlobal (), promiscuous);
442}
443
444void
445PcapHelperForDevice::EnablePcap (std::string prefix, uint32_t nodeid, uint32_t deviceid, bool promiscuous)
446{
448
449 for (NodeContainer::Iterator i = n.Begin (); i != n.End (); ++i)
450 {
451 Ptr<Node> node = *i;
452 if (node->GetId () != nodeid)
453 {
454 continue;
455 }
456
457 NS_ABORT_MSG_IF (deviceid >= node->GetNDevices (), "PcapHelperForDevice::EnablePcap(): Unknown deviceid = "
458 << deviceid);
459 Ptr<NetDevice> nd = node->GetDevice (deviceid);
460 EnablePcap (prefix, nd, promiscuous);
461 return;
462 }
463}
464
465//
466// Public API
467//
468void
469AsciiTraceHelperForDevice::EnableAscii (std::string prefix, Ptr<NetDevice> nd, bool explicitFilename)
470{
471 EnableAsciiInternal (Ptr<OutputStreamWrapper> (), prefix, nd, explicitFilename);
472}
473
474//
475// Public API
476//
477void
479{
480 EnableAsciiInternal (stream, std::string (), nd, false);
481}
482
483//
484// Public API
485//
486void
487AsciiTraceHelperForDevice::EnableAscii (std::string prefix, std::string ndName, bool explicitFilename)
488{
489 EnableAsciiImpl (Ptr<OutputStreamWrapper> (), prefix, ndName, explicitFilename);
490}
491
492//
493// Public API
494//
495void
497{
498 EnableAsciiImpl (stream, std::string (), ndName, false);
499}
500
501//
502// Private API
503//
504void
507 std::string prefix,
508 std::string ndName,
509 bool explicitFilename)
510{
511 Ptr<NetDevice> nd = Names::Find<NetDevice> (ndName);
512 EnableAsciiInternal (stream, prefix, nd, explicitFilename);
513}
514
515//
516// Public API
517//
518void
520{
522}
523
524//
525// Public API
526//
527void
529{
530 EnableAsciiImpl (stream, std::string (), d);
531}
532
533//
534// Private API
535//
536void
538{
539 for (NetDeviceContainer::Iterator i = d.Begin (); i != d.End (); ++i)
540 {
541 Ptr<NetDevice> dev = *i;
542 EnableAsciiInternal (stream, prefix, dev, false);
543 }
544}
545
546//
547// Public API
548//
549void
551{
553}
554
555//
556// Public API
557//
558void
560{
561 EnableAsciiImpl (stream, std::string (), n);
562}
563
564//
565// Private API
566//
567void
569{
571 for (NodeContainer::Iterator i = n.Begin (); i != n.End (); ++i)
572 {
573 Ptr<Node> node = *i;
574 for (uint32_t j = 0; j < node->GetNDevices (); ++j)
575 {
576 devs.Add (node->GetDevice (j));
577 }
578 }
579 EnableAsciiImpl (stream, prefix, devs);
580}
581
582//
583// Public API
584//
585void
587{
589}
590
591//
592// Public API
593//
594void
596{
597 EnableAsciiImpl (stream, std::string (), NodeContainer::GetGlobal ());
598}
599
600//
601// Public API
602//
603void
605{
606 EnableAsciiImpl (stream, std::string (), nodeid, deviceid, false);
607}
608
609//
610// Public API
611//
612void
614 std::string prefix,
615 uint32_t nodeid,
616 uint32_t deviceid,
617 bool explicitFilename)
618{
619 EnableAsciiImpl (Ptr<OutputStreamWrapper> (), prefix, nodeid, deviceid, explicitFilename);
620}
621
622//
623// Private API
624//
625void
628 std::string prefix,
629 uint32_t nodeid,
630 uint32_t deviceid,
631 bool explicitFilename)
632{
634
635 for (NodeContainer::Iterator i = n.Begin (); i != n.End (); ++i)
636 {
637 Ptr<Node> node = *i;
638 if (node->GetId () != nodeid)
639 {
640 continue;
641 }
642
643 NS_ABORT_MSG_IF (deviceid >= node->GetNDevices (),
644 "AsciiTraceHelperForDevice::EnableAscii(): Unknown deviceid = " << deviceid);
645
646 Ptr<NetDevice> nd = node->GetDevice (deviceid);
647
648 EnableAsciiInternal (stream, prefix, nd, explicitFilename);
649 return;
650 }
651}
652
653} // namespace ns3
654
void EnableAsciiImpl(Ptr< OutputStreamWrapper > stream, std::string prefix, uint32_t nodeid, uint32_t deviceid, bool explicitFilename)
Enable ascii trace output on the device specified by a global node-id (of a previously created node) ...
void EnableAscii(std::string prefix, Ptr< NetDevice > nd, bool explicitFilename=false)
Enable ascii trace output on the indicated net device.
void EnableAsciiAll(std::string prefix)
Enable ascii trace output on each device (which is of the appropriate type) in the set of all nodes c...
virtual void EnableAsciiInternal(Ptr< OutputStreamWrapper > stream, std::string prefix, Ptr< NetDevice > nd, bool explicitFilename)=0
Enable ascii trace output on the indicated net device.
std::string GetFilenameFromDevice(std::string prefix, Ptr< NetDevice > device, bool useObjectNames=true)
Let the ascii trace helper figure out a reasonable filename to use for an ascii trace file associated...
static void DefaultDropSinkWithContext(Ptr< OutputStreamWrapper > file, std::string context, Ptr< const Packet > p)
Basic Drop default trace sink.
std::string GetFilenameFromInterfacePair(std::string prefix, Ptr< Object > object, uint32_t interface, bool useObjectNames=true)
Let the ascii trace helper figure out a reasonable filename to use for an ascii trace file associated...
static void DefaultReceiveSinkWithContext(Ptr< OutputStreamWrapper > file, std::string context, Ptr< const Packet > p)
Basic Receive default trace sink.
Ptr< OutputStreamWrapper > CreateFileStream(std::string filename, std::ios::openmode filemode=std::ios::out)
Create and initialize an output stream object we'll use to write the traced bits.
AsciiTraceHelper()
Create an ascii trace helper.
static void DefaultDequeueSinkWithoutContext(Ptr< OutputStreamWrapper > file, Ptr< const Packet > p)
Basic Dequeue default trace sink.
static void DefaultEnqueueSinkWithContext(Ptr< OutputStreamWrapper > file, std::string context, Ptr< const Packet > p)
Basic Enqueue default trace sink.
static void DefaultDropSinkWithoutContext(Ptr< OutputStreamWrapper > file, Ptr< const Packet > p)
Basic Drop default trace sink.
static void DefaultDequeueSinkWithContext(Ptr< OutputStreamWrapper > file, std::string context, Ptr< const Packet > p)
Basic Dequeue default trace sink.
static void DefaultEnqueueSinkWithoutContext(Ptr< OutputStreamWrapper > file, Ptr< const Packet > p)
Basic Enqueue default trace sink.
~AsciiTraceHelper()
Destroy an ascii trace helper.
static void DefaultReceiveSinkWithoutContext(Ptr< OutputStreamWrapper > file, Ptr< const Packet > p)
Basic Receive default trace sink.
Protocol header serialization and deserialization.
Definition: header.h:43
static std::string FindName(Ptr< Object > object)
Given a pointer to an object, look to see if that object has a name associated with it and,...
Definition: names.cc:817
holds a vector of ns3::NetDevice pointers
std::vector< Ptr< NetDevice > >::const_iterator Iterator
NetDevice container iterator.
Iterator End(void) const
Get an iterator which indicates past-the-last NetDevice in the container.
Iterator Begin(void) const
Get an iterator which refers to the first NetDevice in the container.
void Add(NetDeviceContainer other)
Append the contents of another NetDeviceContainer to the end of this container.
virtual uint32_t GetIfIndex(void) const =0
virtual Ptr< Node > GetNode(void) const =0
keep track of a set of node pointers.
std::vector< Ptr< Node > >::const_iterator Iterator
Node container iterator.
Iterator Begin(void) const
Get an iterator which refers to the first Node in the container.
Iterator End(void) const
Get an iterator which indicates past-the-last Node in the container.
static NodeContainer GetGlobal(void)
Create a NodeContainer that contains a list of all nodes created through NodeContainer::Create() and ...
A network Node.
Definition: node.h:57
uint32_t GetId(void) const
Definition: node.cc:109
uint32_t GetNDevices(void) const
Definition: node.cc:152
Ptr< NetDevice > GetDevice(uint32_t index) const
Retrieve the index-th NetDevice associated to this node.
Definition: node.cc:144
Ptr< T > GetObject(void) const
Get a pointer to the requested aggregated Object.
Definition: object.h:470
std::ostream * GetStream(void)
Return a pointer to an ostream previously set in the wrapper.
void EnablePcapAll(std::string prefix, bool promiscuous=false)
Enable pcap output on each device (which is of the appropriate type) in the set of all nodes created ...
void EnablePcap(std::string prefix, Ptr< NetDevice > nd, bool promiscuous=false, bool explicitFilename=false)
Enable pcap output the indicated net device.
virtual void EnablePcapInternal(std::string prefix, Ptr< NetDevice > nd, bool promiscuous, bool explicitFilename)=0
Enable pcap output the indicated net device.
std::string GetFilenameFromDevice(std::string prefix, Ptr< NetDevice > device, bool useObjectNames=true)
Let the pcap helper figure out a reasonable filename to use for a pcap file associated with a device.
Definition: trace-helper.cc:80
Ptr< PcapFileWrapper > CreateFile(std::string filename, std::ios::openmode filemode, DataLinkType dataLinkType, uint32_t snapLen=std::numeric_limits< uint32_t >::max(), int32_t tzCorrection=0)
Create and initialize a pcap file.
Definition: trace-helper.cc:49
DataLinkType
This enumeration holds the data link types that will be written to the pcap file.
Definition: trace-helper.h:50
static void SinkWithHeader(Ptr< PcapFileWrapper > file, const Header &header, Ptr< const Packet > p)
This trace sink passes a header separately from the packet to prevent creating a new packet (for perf...
std::string GetFilenameFromInterfacePair(std::string prefix, Ptr< Object > object, uint32_t interface, bool useObjectNames=true)
Let the pcap helper figure out a reasonable filename to use for the pcap file associated with a node.
~PcapHelper()
Destroy a pcap helper.
Definition: trace-helper.cc:43
static void DefaultSink(Ptr< PcapFileWrapper > file, Ptr< const Packet > p)
The basic default trace sink.
PcapHelper()
Create a pcap helper.
Definition: trace-helper.cc:38
Smart pointer class similar to boost::intrusive_ptr.
Definition: ptr.h:74
static Time Now(void)
Return the current simulation virtual time.
Definition: simulator.cc:195
double GetSeconds(void) const
Get an approximation of the time stored in this instance in the indicated unit.
Definition: nstime.h:380
#define NS_ABORT_MSG_UNLESS(cond, msg)
Abnormal program termination if a condition is false, with a message.
Definition: abort.h:144
#define NS_ABORT_MSG_IF(cond, msg)
Abnormal program termination if a condition is true, with a message.
Definition: abort.h:108
#define NS_LOG_COMPONENT_DEFINE(name)
Define a Log component with a specific name.
Definition: log.h:205
#define NS_LOG_FUNCTION_NOARGS()
Output the name of the function.
#define NS_LOG_FUNCTION(parameters)
If log level LOG_FUNCTION is enabled, this macro will output all input parameters separated by ",...
Every class exported by the ns3 library is enclosed in the ns3 namespace.