A Discrete-Event Network Simulator
API
Loading...
Searching...
No Matches
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.empty(), "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.empty())
99 {
100 oss << nodename;
101 }
102 else
103 {
104 oss << node->GetId();
105 }
106
107 oss << "-";
108
109 if (!devicename.empty())
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.empty(), "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.empty())
147 {
148 oss << objname;
149 }
150 else if (!nodename.empty())
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
169PcapHelper::DefaultSink(Ptr<PcapFileWrapper> file, Ptr<const Packet> p)
170{
171 NS_LOG_FUNCTION(file << p);
172 file->Write(Simulator::Now(), p);
173}
174
175void
176PcapHelper::SinkWithHeader(Ptr<PcapFileWrapper> file, const Header& header, Ptr<const Packet> p)
177{
178 NS_LOG_FUNCTION(file << p);
179 file->Write(Simulator::Now(), header, p);
180}
181
182AsciiTraceHelper::AsciiTraceHelper()
183{
184 NS_LOG_FUNCTION_NOARGS();
185}
186
187AsciiTraceHelper::~AsciiTraceHelper()
188{
189 NS_LOG_FUNCTION_NOARGS();
190}
191
192Ptr<OutputStreamWrapper>
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
214AsciiTraceHelper::GetFilenameFromDevice(std::string prefix,
215 Ptr<NetDevice> device,
216 bool useObjectNames)
217{
218 NS_LOG_FUNCTION(prefix << device << useObjectNames);
219 NS_ABORT_MSG_UNLESS(!prefix.empty(), "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.empty())
236 {
237 oss << nodename;
238 }
239 else
240 {
241 oss << node->GetId();
242 }
243
244 oss << "-";
245
246 if (!devicename.empty())
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
261AsciiTraceHelper::GetFilenameFromInterfacePair(std::string prefix,
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.empty(), "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.empty())
284 {
285 oss << objname;
286 }
287 else if (!nodename.empty())
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
313AsciiTraceHelper::DefaultEnqueueSinkWithoutContext(Ptr<OutputStreamWrapper> stream,
314 Ptr<const Packet> p)
315{
316 NS_LOG_FUNCTION(stream << p);
317 *stream->GetStream() << "+ " << Simulator::Now().GetSeconds() << " " << *p << std::endl;
318}
319
320void
321AsciiTraceHelper::DefaultEnqueueSinkWithContext(Ptr<OutputStreamWrapper> stream,
322 std::string context,
323 Ptr<const Packet> p)
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
343AsciiTraceHelper::DefaultDropSinkWithoutContext(Ptr<OutputStreamWrapper> stream,
344 Ptr<const Packet> p)
345{
346 NS_LOG_FUNCTION(stream << p);
347 *stream->GetStream() << "d " << Simulator::Now().GetSeconds() << " " << *p << std::endl;
348}
349
350void
351AsciiTraceHelper::DefaultDropSinkWithContext(Ptr<OutputStreamWrapper> stream,
352 std::string context,
353 Ptr<const Packet> p)
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
374AsciiTraceHelper::DefaultDequeueSinkWithoutContext(Ptr<OutputStreamWrapper> stream,
375 Ptr<const Packet> p)
376{
377 NS_LOG_FUNCTION(stream << p);
378 *stream->GetStream() << "- " << Simulator::Now().GetSeconds() << " " << *p << std::endl;
379}
380
381void
382AsciiTraceHelper::DefaultDequeueSinkWithContext(Ptr<OutputStreamWrapper> stream,
383 std::string context,
384 Ptr<const Packet> p)
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
402AsciiTraceHelper::DefaultReceiveSinkWithoutContext(Ptr<OutputStreamWrapper> stream,
403 Ptr<const Packet> p)
404{
405 NS_LOG_FUNCTION(stream << p);
406 *stream->GetStream() << "r " << Simulator::Now().GetSeconds() << " " << *p << std::endl;
407}
408
409void
410AsciiTraceHelper::DefaultReceiveSinkWithContext(Ptr<OutputStreamWrapper> stream,
411 std::string context,
412 Ptr<const Packet> p)
413{
414 NS_LOG_FUNCTION(stream << p);
415 *stream->GetStream() << "r " << Simulator::Now().GetSeconds() << " " << context << " " << *p
416 << std::endl;
417}
418
419void
420PcapHelperForDevice::EnablePcap(std::string prefix,
421 Ptr<NetDevice> nd,
422 bool promiscuous,
423 bool explicitFilename)
424{
425 EnablePcapInternal(prefix, nd, promiscuous, explicitFilename);
426}
427
428void
429PcapHelperForDevice::EnablePcap(std::string prefix,
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 (auto 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{
451 NetDeviceContainer devs;
452 for (auto 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
470PcapHelperForDevice::EnablePcap(std::string prefix,
471 uint32_t nodeid,
472 uint32_t deviceid,
473 bool promiscuous)
474{
475 NodeContainer n = NodeContainer::GetGlobal();
476
477 for (auto 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{
550 EnableAsciiImpl(Ptr<OutputStreamWrapper>(), prefix, d);
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 (auto 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{
583 EnableAsciiImpl(Ptr<OutputStreamWrapper>(), prefix, n);
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 (auto 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{
621 EnableAsciiImpl(Ptr<OutputStreamWrapper>(), prefix, NodeContainer::GetGlobal());
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 (auto 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...
Empty class, used as a default parent class for SimpleRefCount.
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:829
holds a vector of ns3::NetDevice pointers
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.
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:57
Base class providing common user-level pcap operations for helpers representing net devices.
Definition: trace-helper.h:624
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:52
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
PcapHelper()
Create a pcap helper.
Definition: trace-helper.cc:38
Smart pointer class similar to boost::intrusive_ptr.
Definition: ptr.h:77
#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.