A Discrete-Event Network Simulator
API
trace-helper.cc
Go to the documentation of this file.
1/*
2 * Copyright (c) 2010 University of Washington
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License version 2 as
6 * published by the Free Software Foundation;
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
12 *
13 * You should have received a copy of the GNU General Public License
14 * along with this program; if not, write to the Free Software
15 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
16 */
17
18#include "trace-helper.h"
19
20#include "ns3/abort.h"
21#include "ns3/assert.h"
22#include "ns3/log.h"
23#include "ns3/names.h"
24#include "ns3/net-device.h"
25#include "ns3/node.h"
26#include "ns3/pcap-file-wrapper.h"
27#include "ns3/ptr.h"
28
29#include <fstream>
30#include <stdint.h>
31#include <string>
32
33namespace ns3
34{
35
36NS_LOG_COMPONENT_DEFINE("TraceHelper");
37
39{
41}
42
44{
46}
47
49PcapHelper::CreateFile(std::string filename,
50 std::ios::openmode filemode,
51 DataLinkType dataLinkType,
52 uint32_t snapLen,
53 int32_t tzCorrection)
54{
55 NS_LOG_FUNCTION(filename << filemode << dataLinkType << snapLen << tzCorrection);
56
57 Ptr<PcapFileWrapper> file = CreateObject<PcapFileWrapper>();
58 file->Open(filename, filemode);
59 NS_ABORT_MSG_IF(file->Fail(), "Unable to Open " << filename << " for mode " << filemode);
60
61 file->Init(dataLinkType, snapLen, tzCorrection);
62 NS_ABORT_MSG_IF(file->Fail(), "Unable to Init " << filename);
63
64 //
65 // Note that the pcap helper promptly forgets all about the pcap file. We
66 // rely on the reference count of the file object which will soon be owned
67 // by the caller to keep the object alive. If the caller uses the file
68 // object to hook a trace source, ownership of the file object will be
69 // implicitly transferred to the callback which keeps the object alive.
70 // When the callback is destroyed (when either the trace is disconnected or
71 // the object with the trace source is deleted) the callback will be destroyed
72 // and the file object will be destroyed, releasing the pointer and closing
73 // the file.
74 //
75 return file;
76}
77
78std::string
79PcapHelper::GetFilenameFromDevice(std::string prefix, Ptr<NetDevice> device, bool useObjectNames)
80{
81 NS_LOG_FUNCTION(prefix << device << useObjectNames);
82 NS_ABORT_MSG_UNLESS(prefix.size(), "Empty prefix string");
83
84 std::ostringstream oss;
85 oss << prefix << "-";
86
87 std::string nodename;
88 std::string devicename;
89
90 Ptr<Node> node = device->GetNode();
91
92 if (useObjectNames)
93 {
94 nodename = Names::FindName(node);
95 devicename = Names::FindName(device);
96 }
97
98 if (nodename.size())
99 {
100 oss << nodename;
101 }
102 else
103 {
104 oss << node->GetId();
105 }
106
107 oss << "-";
108
109 if (devicename.size())
110 {
111 oss << devicename;
112 }
113 else
114 {
115 oss << device->GetIfIndex();
116 }
117
118 oss << ".pcap";
119
120 return oss.str();
121}
122
123std::string
125 Ptr<Object> object,
126 uint32_t interface,
127 bool useObjectNames)
128{
129 NS_LOG_FUNCTION(prefix << object << interface << useObjectNames);
130 NS_ABORT_MSG_UNLESS(prefix.size(), "Empty prefix string");
131
132 std::ostringstream oss;
133 oss << prefix << "-";
134
135 std::string objname;
136 std::string nodename;
137
138 Ptr<Node> node = object->GetObject<Node>();
139
140 if (useObjectNames)
141 {
142 objname = Names::FindName(object);
143 nodename = Names::FindName(node);
144 }
145
146 if (objname.size())
147 {
148 oss << objname;
149 }
150 else if (nodename.size())
151 {
152 oss << nodename;
153 }
154 else
155 {
156 oss << "n" << node->GetId();
157 }
158
159 oss << "-i" << interface << ".pcap";
160
161 return oss.str();
162}
163
164//
165// The basic default trace sink. This one just writes the packet to the pcap
166// file which is good enough for most kinds of captures.
167//
168void
170{
171 NS_LOG_FUNCTION(file << p);
172 file->Write(Simulator::Now(), p);
173}
174
175void
177{
178 NS_LOG_FUNCTION(file << p);
179 file->Write(Simulator::Now(), header, p);
180}
181
183{
185}
186
188{
190}
191
193AsciiTraceHelper::CreateFileStream(std::string filename, std::ios::openmode filemode)
194{
195 NS_LOG_FUNCTION(filename << filemode);
196
197 Ptr<OutputStreamWrapper> StreamWrapper = Create<OutputStreamWrapper>(filename, filemode);
198
199 //
200 // Note that the ascii trace helper promptly forgets all about the trace file.
201 // We rely on the reference count of the file object which will soon be owned
202 // by the caller to keep the object alive. If the caller uses the stream
203 // object to hook a trace source, ownership of the stream object will be
204 // implicitly transferred to the callback which keeps the object alive.
205 // When the callback is destroyed (when either the trace is disconnected or
206 // the object with the trace source is deleted) the callback will be destroyed
207 // and the stream object will be destroyed, releasing the pointer and closing
208 // the underlying file.
209 //
210 return StreamWrapper;
211}
212
213std::string
215 Ptr<NetDevice> device,
216 bool useObjectNames)
217{
218 NS_LOG_FUNCTION(prefix << device << useObjectNames);
219 NS_ABORT_MSG_UNLESS(prefix.size(), "Empty prefix string");
220
221 std::ostringstream oss;
222 oss << prefix << "-";
223
224 std::string nodename;
225 std::string devicename;
226
227 Ptr<Node> node = device->GetNode();
228
229 if (useObjectNames)
230 {
231 nodename = Names::FindName(node);
232 devicename = Names::FindName(device);
233 }
234
235 if (nodename.size())
236 {
237 oss << nodename;
238 }
239 else
240 {
241 oss << node->GetId();
242 }
243
244 oss << "-";
245
246 if (devicename.size())
247 {
248 oss << devicename;
249 }
250 else
251 {
252 oss << device->GetIfIndex();
253 }
254
255 oss << ".tr";
256
257 return oss.str();
258}
259
260std::string
262 Ptr<Object> object,
263 uint32_t interface,
264 bool useObjectNames)
265{
266 NS_LOG_FUNCTION(prefix << object << interface << useObjectNames);
267 NS_ABORT_MSG_UNLESS(prefix.size(), "Empty prefix string");
268
269 std::ostringstream oss;
270 oss << prefix << "-";
271
272 std::string objname;
273 std::string nodename;
274
275 Ptr<Node> node = object->GetObject<Node>();
276
277 if (useObjectNames)
278 {
279 objname = Names::FindName(object);
280 nodename = Names::FindName(node);
281 }
282
283 if (objname.size())
284 {
285 oss << objname;
286 }
287 else if (nodename.size())
288 {
289 oss << nodename;
290 }
291 else
292 {
293 oss << "n" << node->GetId();
294 }
295
296 oss << "-i" << interface << ".tr";
297
298 return oss.str();
299}
300
301//
302// One of the basic default trace sink sets. Enqueue:
303//
304// When a packet has been sent to a device for transmission, the device is
305// expected to place the packet onto a transmit queue even if it does not
306// have to delay the packet at all, if only to trigger this event. This
307// event will eventually translate into a '+' operation in the trace file.
308//
309// This is typically implemented by hooking the "TxQueue/Enqueue" trace hook
310// in the device (actually the Queue in the device).
311//
312void
315{
316 NS_LOG_FUNCTION(stream << p);
317 *stream->GetStream() << "+ " << Simulator::Now().GetSeconds() << " " << *p << std::endl;
318}
319
320void
322 std::string context,
324{
325 NS_LOG_FUNCTION(stream << p);
326 *stream->GetStream() << "+ " << Simulator::Now().GetSeconds() << " " << context << " " << *p
327 << std::endl;
328}
329
330//
331// One of the basic default trace sink sets. Drop:
332//
333// When a packet has been sent to a device for transmission, the device is
334// expected to place the packet onto a transmit queue. If this queue is
335// full the packet will be dropped. The device is expected to trigger an
336// event to indicate that an outbound packet is being dropped. This event
337// will eventually translate into a 'd' operation in the trace file.
338//
339// This is typically implemented by hooking the "TxQueue/Drop" trace hook
340// in the device (actually the Queue in the device).
341//
342void
345{
346 NS_LOG_FUNCTION(stream << p);
347 *stream->GetStream() << "d " << Simulator::Now().GetSeconds() << " " << *p << std::endl;
348}
349
350void
352 std::string context,
354{
355 NS_LOG_FUNCTION(stream << p);
356 *stream->GetStream() << "d " << Simulator::Now().GetSeconds() << " " << context << " " << *p
357 << std::endl;
358}
359
360//
361// One of the basic default trace sink sets. Dequeue:
362//
363// When a packet has been sent to a device for transmission, the device is
364// expected to place the packet onto a transmit queue even if it does not
365// have to delay the packet at all. The device removes the packet from the
366// transmit queue when the packet is ready to send, and this dequeue will
367// fire a corresponding event. This event will eventually translate into a
368// '-' operation in the trace file.
369//
370// This is typically implemented by hooking the "TxQueue/Dequeue" trace hook
371// in the device (actually the Queue in the device).
372//
373void
376{
377 NS_LOG_FUNCTION(stream << p);
378 *stream->GetStream() << "- " << Simulator::Now().GetSeconds() << " " << *p << std::endl;
379}
380
381void
383 std::string context,
385{
386 NS_LOG_FUNCTION(stream << p);
387 *stream->GetStream() << "- " << Simulator::Now().GetSeconds() << " " << context << " " << *p
388 << std::endl;
389}
390
391//
392// One of the basic default trace sink sets. Receive:
393//
394// When a packet is received by a device for transmission, the device is
395// expected to trigger this event to indicate the reception has occurred.
396// This event will eventually translate into an 'r' operation in the trace
397// file.
398//
399// This is typically implemented by hooking the "MacRx" trace hook in the
400// device.
401void
404{
405 NS_LOG_FUNCTION(stream << p);
406 *stream->GetStream() << "r " << Simulator::Now().GetSeconds() << " " << *p << std::endl;
407}
408
409void
411 std::string context,
413{
414 NS_LOG_FUNCTION(stream << p);
415 *stream->GetStream() << "r " << Simulator::Now().GetSeconds() << " " << context << " " << *p
416 << std::endl;
417}
418
419void
422 bool promiscuous,
423 bool explicitFilename)
424{
425 EnablePcapInternal(prefix, nd, promiscuous, explicitFilename);
426}
427
428void
430 std::string ndName,
431 bool promiscuous,
432 bool explicitFilename)
433{
434 Ptr<NetDevice> nd = Names::Find<NetDevice>(ndName);
435 EnablePcap(prefix, nd, promiscuous, explicitFilename);
436}
437
438void
439PcapHelperForDevice::EnablePcap(std::string prefix, NetDeviceContainer d, bool promiscuous)
440{
441 for (NetDeviceContainer::Iterator i = d.Begin(); i != d.End(); ++i)
442 {
443 Ptr<NetDevice> dev = *i;
444 EnablePcap(prefix, dev, promiscuous);
445 }
446}
447
448void
449PcapHelperForDevice::EnablePcap(std::string prefix, NodeContainer n, bool promiscuous)
450{
452 for (NodeContainer::Iterator i = n.Begin(); i != n.End(); ++i)
453 {
454 Ptr<Node> node = *i;
455 for (uint32_t j = 0; j < node->GetNDevices(); ++j)
456 {
457 devs.Add(node->GetDevice(j));
458 }
459 }
460 EnablePcap(prefix, devs, promiscuous);
461}
462
463void
464PcapHelperForDevice::EnablePcapAll(std::string prefix, bool promiscuous)
465{
466 EnablePcap(prefix, NodeContainer::GetGlobal(), promiscuous);
467}
468
469void
471 uint32_t nodeid,
472 uint32_t deviceid,
473 bool promiscuous)
474{
476
477 for (NodeContainer::Iterator i = n.Begin(); i != n.End(); ++i)
478 {
479 Ptr<Node> node = *i;
480 if (node->GetId() != nodeid)
481 {
482 continue;
483 }
484
485 NS_ABORT_MSG_IF(deviceid >= node->GetNDevices(),
486 "PcapHelperForDevice::EnablePcap(): Unknown deviceid = " << deviceid);
487 Ptr<NetDevice> nd = node->GetDevice(deviceid);
488 EnablePcap(prefix, nd, promiscuous);
489 return;
490 }
491}
492
493//
494// Public API
495//
496void
497AsciiTraceHelperForDevice::EnableAscii(std::string prefix, Ptr<NetDevice> nd, bool explicitFilename)
498{
499 EnableAsciiInternal(Ptr<OutputStreamWrapper>(), prefix, nd, explicitFilename);
500}
501
502//
503// Public API
504//
505void
507{
508 EnableAsciiInternal(stream, std::string(), nd, false);
509}
510
511//
512// Public API
513//
514void
516 std::string ndName,
517 bool explicitFilename)
518{
519 EnableAsciiImpl(Ptr<OutputStreamWrapper>(), prefix, ndName, explicitFilename);
520}
521
522//
523// Public API
524//
525void
527{
528 EnableAsciiImpl(stream, std::string(), ndName, false);
529}
530
531//
532// Private API
533//
534void
536 std::string prefix,
537 std::string ndName,
538 bool explicitFilename)
539{
540 Ptr<NetDevice> nd = Names::Find<NetDevice>(ndName);
541 EnableAsciiInternal(stream, prefix, nd, explicitFilename);
542}
543
544//
545// Public API
546//
547void
549{
551}
552
553//
554// Public API
555//
556void
558{
559 EnableAsciiImpl(stream, std::string(), d);
560}
561
562//
563// Private API
564//
565void
567 std::string prefix,
569{
570 for (NetDeviceContainer::Iterator i = d.Begin(); i != d.End(); ++i)
571 {
572 Ptr<NetDevice> dev = *i;
573 EnableAsciiInternal(stream, prefix, dev, false);
574 }
575}
576
577//
578// Public API
579//
580void
582{
584}
585
586//
587// Public API
588//
589void
591{
592 EnableAsciiImpl(stream, std::string(), n);
593}
594
595//
596// Private API
597//
598void
600 std::string prefix,
602{
604 for (NodeContainer::Iterator i = n.Begin(); i != n.End(); ++i)
605 {
606 Ptr<Node> node = *i;
607 for (uint32_t j = 0; j < node->GetNDevices(); ++j)
608 {
609 devs.Add(node->GetDevice(j));
610 }
611 }
612 EnableAsciiImpl(stream, prefix, devs);
613}
614
615//
616// Public API
617//
618void
620{
622}
623
624//
625// Public API
626//
627void
629{
630 EnableAsciiImpl(stream, std::string(), NodeContainer::GetGlobal());
631}
632
633//
634// Public API
635//
636void
638 uint32_t nodeid,
639 uint32_t deviceid)
640{
641 EnableAsciiImpl(stream, std::string(), nodeid, deviceid, false);
642}
643
644//
645// Public API
646//
647void
649 uint32_t nodeid,
650 uint32_t deviceid,
651 bool explicitFilename)
652{
653 EnableAsciiImpl(Ptr<OutputStreamWrapper>(), prefix, nodeid, deviceid, explicitFilename);
654}
655
656//
657// Private API
658//
659void
661 std::string prefix,
662 uint32_t nodeid,
663 uint32_t deviceid,
664 bool explicitFilename)
665{
667
668 for (NodeContainer::Iterator i = n.Begin(); i != n.End(); ++i)
669 {
670 Ptr<Node> node = *i;
671 if (node->GetId() != nodeid)
672 {
673 continue;
674 }
675
677 deviceid >= node->GetNDevices(),
678 "AsciiTraceHelperForDevice::EnableAscii(): Unknown deviceid = " << deviceid);
679
680 Ptr<NetDevice> nd = node->GetDevice(deviceid);
681
682 EnableAsciiInternal(stream, prefix, nd, explicitFilename);
683 return;
684 }
685}
686
687} // namespace ns3
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:44
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:830
holds a vector of ns3::NetDevice pointers
std::vector< Ptr< NetDevice > >::const_iterator Iterator
NetDevice container iterator.
Iterator Begin() 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.
Iterator End() const
Get an iterator which indicates past-the-last NetDevice in the container.
keep track of a set of node pointers.
std::vector< Ptr< Node > >::const_iterator Iterator
Node container iterator.
Iterator End() const
Get an iterator which indicates past-the-last Node in the container.
static NodeContainer GetGlobal()
Create a NodeContainer that contains a list of all nodes created through NodeContainer::Create() and ...
Iterator Begin() const
Get an iterator which refers to the first Node in the container.
A network Node.
Definition: node.h:56
uint32_t GetNDevices() const
Definition: node.cc:162
uint32_t GetId() const
Definition: node.cc:117
Ptr< NetDevice > GetDevice(uint32_t index) const
Retrieve the index-th NetDevice associated to this node.
Definition: node.cc:152
Ptr< T > GetObject() const
Get a pointer to the requested aggregated Object.
Definition: object.h:471
std::ostream * GetStream()
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:79
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:51
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:78
static Time Now()
Return the current simulation virtual time.
Definition: simulator.cc:199
double GetSeconds() const
Get an approximation of the time stored in this instance in the indicated unit.
Definition: nstime.h:402
#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:202
#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.