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 * SPDX-License-Identifier: GPL-2.0-only
5 */
6
7#include "trace-helper.h"
8
9#include "ns3/abort.h"
10#include "ns3/assert.h"
11#include "ns3/log.h"
12#include "ns3/names.h"
13#include "ns3/net-device.h"
14#include "ns3/node.h"
15#include "ns3/pcap-file-wrapper.h"
16#include "ns3/ptr.h"
17
18#include <fstream>
19#include <stdint.h>
20#include <string>
21
22namespace ns3
23{
24
25NS_LOG_COMPONENT_DEFINE("TraceHelper");
26
31
36
38PcapHelper::CreateFile(std::string filename,
39 std::ios::openmode filemode,
40 DataLinkType dataLinkType,
41 uint32_t snapLen,
42 int32_t tzCorrection)
43{
44 NS_LOG_FUNCTION(filename << filemode << dataLinkType << snapLen << tzCorrection);
45
47 file->Open(filename, filemode);
48 NS_ABORT_MSG_IF(file->Fail(), "Unable to Open " << filename << " for mode " << filemode);
49
50 file->Init(dataLinkType, snapLen, tzCorrection);
51 NS_ABORT_MSG_IF(file->Fail(), "Unable to Init " << filename);
52
53 //
54 // Note that the pcap helper promptly forgets all about the pcap file. We
55 // rely on the reference count of the file object which will soon be owned
56 // by the caller to keep the object alive. If the caller uses the file
57 // object to hook a trace source, ownership of the file object will be
58 // implicitly transferred to the callback which keeps the object alive.
59 // When the callback is destroyed (when either the trace is disconnected or
60 // the object with the trace source is deleted) the callback will be destroyed
61 // and the file object will be destroyed, releasing the pointer and closing
62 // the file.
63 //
64 return file;
65}
66
67std::string
68PcapHelper::GetFilenameFromDevice(std::string prefix, Ptr<NetDevice> device, bool useObjectNames)
69{
70 NS_LOG_FUNCTION(prefix << device << useObjectNames);
71 NS_ABORT_MSG_UNLESS(!prefix.empty(), "Empty prefix string");
72
73 std::ostringstream oss;
74 oss << prefix << "-";
75
76 std::string nodename;
77 std::string devicename;
78
79 Ptr<Node> node = device->GetNode();
80
81 if (useObjectNames)
82 {
83 nodename = Names::FindName(node);
84 devicename = Names::FindName(device);
85 }
86
87 if (!nodename.empty())
88 {
89 oss << nodename;
90 }
91 else
92 {
93 oss << node->GetId();
94 }
95
96 oss << "-";
97
98 if (!devicename.empty())
99 {
100 oss << devicename;
101 }
102 else
103 {
104 oss << device->GetIfIndex();
105 }
106
107 oss << ".pcap";
108
109 return oss.str();
110}
111
112std::string
114 Ptr<Object> object,
115 uint32_t interface,
116 bool useObjectNames)
117{
118 NS_LOG_FUNCTION(prefix << object << interface << useObjectNames);
119 NS_ABORT_MSG_UNLESS(!prefix.empty(), "Empty prefix string");
120
121 std::ostringstream oss;
122 oss << prefix << "-";
123
124 std::string objname;
125 std::string nodename;
126
127 Ptr<Node> node = object->GetObject<Node>();
128
129 if (useObjectNames)
130 {
131 objname = Names::FindName(object);
132 nodename = Names::FindName(node);
133 }
134
135 if (!objname.empty())
136 {
137 oss << objname;
138 }
139 else if (!nodename.empty())
140 {
141 oss << nodename;
142 }
143 else
144 {
145 oss << "n" << node->GetId();
146 }
147
148 oss << "-i" << interface << ".pcap";
149
150 return oss.str();
151}
152
153//
154// The basic default trace sink. This one just writes the packet to the pcap
155// file which is good enough for most kinds of captures.
156//
157void
158PcapHelper::DefaultSink(Ptr<PcapFileWrapper> file, Ptr<const Packet> p)
159{
160 NS_LOG_FUNCTION(file << p);
161 file->Write(Simulator::Now(), p);
162}
163
164void
165PcapHelper::SinkWithHeader(Ptr<PcapFileWrapper> file, const Header& header, Ptr<const Packet> p)
166{
167 NS_LOG_FUNCTION(file << p);
168 file->Write(Simulator::Now(), header, p);
169}
170
171AsciiTraceHelper::AsciiTraceHelper()
172{
173 NS_LOG_FUNCTION_NOARGS();
174}
175
176AsciiTraceHelper::~AsciiTraceHelper()
177{
178 NS_LOG_FUNCTION_NOARGS();
179}
180
181Ptr<OutputStreamWrapper>
182AsciiTraceHelper::CreateFileStream(std::string filename, std::ios::openmode filemode)
183{
184 NS_LOG_FUNCTION(filename << filemode);
185
186 Ptr<OutputStreamWrapper> StreamWrapper = Create<OutputStreamWrapper>(filename, filemode);
187
188 //
189 // Note that the ascii trace helper promptly forgets all about the trace file.
190 // We rely on the reference count of the file object which will soon be owned
191 // by the caller to keep the object alive. If the caller uses the stream
192 // object to hook a trace source, ownership of the stream object will be
193 // implicitly transferred to the callback which keeps the object alive.
194 // When the callback is destroyed (when either the trace is disconnected or
195 // the object with the trace source is deleted) the callback will be destroyed
196 // and the stream object will be destroyed, releasing the pointer and closing
197 // the underlying file.
198 //
199 return StreamWrapper;
200}
201
202std::string
203AsciiTraceHelper::GetFilenameFromDevice(std::string prefix,
204 Ptr<NetDevice> device,
205 bool useObjectNames)
206{
207 NS_LOG_FUNCTION(prefix << device << useObjectNames);
208 NS_ABORT_MSG_UNLESS(!prefix.empty(), "Empty prefix string");
209
210 std::ostringstream oss;
211 oss << prefix << "-";
212
213 std::string nodename;
214 std::string devicename;
215
216 Ptr<Node> node = device->GetNode();
217
218 if (useObjectNames)
219 {
220 nodename = Names::FindName(node);
221 devicename = Names::FindName(device);
222 }
223
224 if (!nodename.empty())
225 {
226 oss << nodename;
227 }
228 else
229 {
230 oss << node->GetId();
231 }
232
233 oss << "-";
234
235 if (!devicename.empty())
236 {
237 oss << devicename;
238 }
239 else
240 {
241 oss << device->GetIfIndex();
242 }
243
244 oss << ".tr";
245
246 return oss.str();
247}
248
249std::string
250AsciiTraceHelper::GetFilenameFromInterfacePair(std::string prefix,
251 Ptr<Object> object,
252 uint32_t interface,
253 bool useObjectNames)
254{
255 NS_LOG_FUNCTION(prefix << object << interface << useObjectNames);
256 NS_ABORT_MSG_UNLESS(!prefix.empty(), "Empty prefix string");
257
258 std::ostringstream oss;
259 oss << prefix << "-";
260
261 std::string objname;
262 std::string nodename;
263
264 Ptr<Node> node = object->GetObject<Node>();
265
266 if (useObjectNames)
267 {
268 objname = Names::FindName(object);
269 nodename = Names::FindName(node);
270 }
271
272 if (!objname.empty())
273 {
274 oss << objname;
275 }
276 else if (!nodename.empty())
277 {
278 oss << nodename;
279 }
280 else
281 {
282 oss << "n" << node->GetId();
283 }
284
285 oss << "-i" << interface << ".tr";
286
287 return oss.str();
288}
289
290//
291// One of the basic default trace sink sets. Enqueue:
292//
293// When a packet has been sent to a device for transmission, the device is
294// expected to place the packet onto a transmit queue even if it does not
295// have to delay the packet at all, if only to trigger this event. This
296// event will eventually translate into a '+' operation in the trace file.
297//
298// This is typically implemented by hooking the "TxQueue/Enqueue" trace hook
299// in the device (actually the Queue in the device).
300//
301void
302AsciiTraceHelper::DefaultEnqueueSinkWithoutContext(Ptr<OutputStreamWrapper> stream,
303 Ptr<const Packet> p)
304{
305 NS_LOG_FUNCTION(stream << p);
306 *stream->GetStream() << "+ " << Simulator::Now().GetSeconds() << " " << *p << std::endl;
307}
308
309void
310AsciiTraceHelper::DefaultEnqueueSinkWithContext(Ptr<OutputStreamWrapper> stream,
311 std::string context,
312 Ptr<const Packet> p)
313{
314 NS_LOG_FUNCTION(stream << p);
315 *stream->GetStream() << "+ " << Simulator::Now().GetSeconds() << " " << context << " " << *p
316 << std::endl;
317}
318
319//
320// One of the basic default trace sink sets. Drop:
321//
322// When a packet has been sent to a device for transmission, the device is
323// expected to place the packet onto a transmit queue. If this queue is
324// full the packet will be dropped. The device is expected to trigger an
325// event to indicate that an outbound packet is being dropped. This event
326// will eventually translate into a 'd' operation in the trace file.
327//
328// This is typically implemented by hooking the "TxQueue/Drop" trace hook
329// in the device (actually the Queue in the device).
330//
331void
332AsciiTraceHelper::DefaultDropSinkWithoutContext(Ptr<OutputStreamWrapper> stream,
333 Ptr<const Packet> p)
334{
335 NS_LOG_FUNCTION(stream << p);
336 *stream->GetStream() << "d " << Simulator::Now().GetSeconds() << " " << *p << std::endl;
337}
338
339void
340AsciiTraceHelper::DefaultDropSinkWithContext(Ptr<OutputStreamWrapper> stream,
341 std::string context,
342 Ptr<const Packet> p)
343{
344 NS_LOG_FUNCTION(stream << p);
345 *stream->GetStream() << "d " << Simulator::Now().GetSeconds() << " " << context << " " << *p
346 << 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
363AsciiTraceHelper::DefaultDequeueSinkWithoutContext(Ptr<OutputStreamWrapper> stream,
364 Ptr<const Packet> p)
365{
366 NS_LOG_FUNCTION(stream << p);
367 *stream->GetStream() << "- " << Simulator::Now().GetSeconds() << " " << *p << std::endl;
368}
369
370void
371AsciiTraceHelper::DefaultDequeueSinkWithContext(Ptr<OutputStreamWrapper> stream,
372 std::string context,
373 Ptr<const Packet> p)
374{
375 NS_LOG_FUNCTION(stream << p);
376 *stream->GetStream() << "- " << Simulator::Now().GetSeconds() << " " << context << " " << *p
377 << std::endl;
378}
379
380//
381// One of the basic default trace sink sets. Receive:
382//
383// When a packet is received by a device for transmission, the device is
384// expected to trigger this event to indicate the reception has occurred.
385// This event will eventually translate into an 'r' operation in the trace
386// file.
387//
388// This is typically implemented by hooking the "MacRx" trace hook in the
389// device.
390void
391AsciiTraceHelper::DefaultReceiveSinkWithoutContext(Ptr<OutputStreamWrapper> stream,
392 Ptr<const Packet> p)
393{
394 NS_LOG_FUNCTION(stream << p);
395 *stream->GetStream() << "r " << Simulator::Now().GetSeconds() << " " << *p << std::endl;
396}
397
398void
399AsciiTraceHelper::DefaultReceiveSinkWithContext(Ptr<OutputStreamWrapper> stream,
400 std::string context,
401 Ptr<const Packet> p)
402{
403 NS_LOG_FUNCTION(stream << p);
404 *stream->GetStream() << "r " << Simulator::Now().GetSeconds() << " " << context << " " << *p
405 << std::endl;
406}
407
408void
409PcapHelperForDevice::EnablePcap(std::string prefix,
410 Ptr<NetDevice> nd,
411 bool promiscuous,
412 bool explicitFilename)
413{
414 EnablePcapInternal(prefix, nd, promiscuous, explicitFilename);
415}
416
417void
418PcapHelperForDevice::EnablePcap(std::string prefix,
419 std::string ndName,
420 bool promiscuous,
421 bool explicitFilename)
422{
423 Ptr<NetDevice> nd = Names::Find<NetDevice>(ndName);
424 EnablePcap(prefix, nd, promiscuous, explicitFilename);
425}
426
427void
428PcapHelperForDevice::EnablePcap(std::string prefix, NetDeviceContainer d, bool promiscuous)
429{
430 for (auto i = d.Begin(); i != d.End(); ++i)
431 {
432 Ptr<NetDevice> dev = *i;
433 EnablePcap(prefix, dev, promiscuous);
434 }
435}
436
437void
438PcapHelperForDevice::EnablePcap(std::string prefix, NodeContainer n, bool promiscuous)
439{
440 NetDeviceContainer devs;
441 for (auto i = n.Begin(); i != n.End(); ++i)
442 {
443 Ptr<Node> node = *i;
444 for (uint32_t j = 0; j < node->GetNDevices(); ++j)
445 {
446 devs.Add(node->GetDevice(j));
447 }
448 }
449 EnablePcap(prefix, devs, promiscuous);
450}
451
452void
453PcapHelperForDevice::EnablePcapAll(std::string prefix, bool promiscuous)
454{
455 EnablePcap(prefix, NodeContainer::GetGlobal(), promiscuous);
456}
457
458void
459PcapHelperForDevice::EnablePcap(std::string prefix,
460 uint32_t nodeid,
461 uint32_t deviceid,
462 bool promiscuous)
463{
464 NodeContainer n = NodeContainer::GetGlobal();
465
466 for (auto i = n.Begin(); i != n.End(); ++i)
467 {
468 Ptr<Node> node = *i;
469 if (node->GetId() != nodeid)
470 {
471 continue;
472 }
473
474 NS_ABORT_MSG_IF(deviceid >= node->GetNDevices(),
475 "PcapHelperForDevice::EnablePcap(): Unknown deviceid = " << deviceid);
476 Ptr<NetDevice> nd = node->GetDevice(deviceid);
477 EnablePcap(prefix, nd, promiscuous);
478 return;
479 }
480}
481
482//
483// Public API
484//
485void
486AsciiTraceHelperForDevice::EnableAscii(std::string prefix, Ptr<NetDevice> nd, bool explicitFilename)
487{
488 EnableAsciiInternal(Ptr<OutputStreamWrapper>(), prefix, nd, explicitFilename);
489}
490
491//
492// Public API
493//
494void
496{
497 EnableAsciiInternal(stream, std::string(), nd, false);
498}
499
500//
501// Public API
502//
503void
505 std::string ndName,
506 bool explicitFilename)
507{
508 EnableAsciiImpl(Ptr<OutputStreamWrapper>(), prefix, ndName, explicitFilename);
509}
510
511//
512// Public API
513//
514void
516{
517 EnableAsciiImpl(stream, std::string(), ndName, false);
518}
519
520//
521// Private API
522//
523void
525 std::string prefix,
526 std::string ndName,
527 bool explicitFilename)
528{
530 EnableAsciiInternal(stream, prefix, nd, explicitFilename);
531}
532
533//
534// Public API
535//
536void
538{
539 EnableAsciiImpl(Ptr<OutputStreamWrapper>(), prefix, d);
540}
541
542//
543// Public API
544//
545void
547{
548 EnableAsciiImpl(stream, std::string(), d);
549}
550
551//
552// Private API
553//
554void
556 std::string prefix,
558{
559 for (auto i = d.Begin(); i != d.End(); ++i)
560 {
561 Ptr<NetDevice> dev = *i;
562 EnableAsciiInternal(stream, prefix, dev, false);
563 }
564}
565
566//
567// Public API
568//
569void
571{
572 EnableAsciiImpl(Ptr<OutputStreamWrapper>(), prefix, n);
573}
574
575//
576// Public API
577//
578void
580{
581 EnableAsciiImpl(stream, std::string(), n);
582}
583
584//
585// Private API
586//
587void
589 std::string prefix,
591{
593 for (auto i = n.Begin(); i != n.End(); ++i)
594 {
595 Ptr<Node> node = *i;
596 for (uint32_t j = 0; j < node->GetNDevices(); ++j)
597 {
598 devs.Add(node->GetDevice(j));
599 }
600 }
601 EnableAsciiImpl(stream, prefix, devs);
602}
603
604//
605// Public API
606//
607void
609{
610 EnableAsciiImpl(Ptr<OutputStreamWrapper>(), prefix, NodeContainer::GetGlobal());
611}
612
613//
614// Public API
615//
616void
618{
619 EnableAsciiImpl(stream, std::string(), NodeContainer::GetGlobal());
620}
621
622//
623// Public API
624//
625void
627 uint32_t nodeid,
628 uint32_t deviceid)
629{
630 EnableAsciiImpl(stream, std::string(), nodeid, deviceid, false);
631}
632
633//
634// Public API
635//
636void
638 uint32_t nodeid,
639 uint32_t deviceid,
640 bool explicitFilename)
641{
642 EnableAsciiImpl(Ptr<OutputStreamWrapper>(), prefix, nodeid, deviceid, explicitFilename);
643}
644
645//
646// Private API
647//
648void
650 std::string prefix,
651 uint32_t nodeid,
652 uint32_t deviceid,
653 bool explicitFilename)
654{
656
657 for (auto i = n.Begin(); i != n.End(); ++i)
658 {
659 Ptr<Node> node = *i;
660 if (node->GetId() != nodeid)
661 {
662 continue;
663 }
664
666 deviceid >= node->GetNDevices(),
667 "AsciiTraceHelperForDevice::EnableAscii(): Unknown deviceid = " << deviceid);
668
669 Ptr<NetDevice> nd = node->GetDevice(deviceid);
670
671 EnableAsciiInternal(stream, prefix, nd, explicitFilename);
672 return;
673 }
674}
675
676} // 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 Ptr< T > Find(std::string path)
Given a name path string, look to see if there's an object in the system with that associated to it.
Definition names.h:443
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:818
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:46
Base class providing common user-level pcap operations for helpers representing net devices.
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.
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.
DataLinkType
This enumeration holds the data link types that will be written to the pcap file.
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.
PcapHelper()
Create a pcap helper.
Smart pointer class similar to boost::intrusive_ptr.
#define NS_ABORT_MSG_UNLESS(cond, msg)
Abnormal program termination if a condition is false, with a message.
Definition abort.h:133
#define NS_ABORT_MSG_IF(cond, msg)
Abnormal program termination if a condition is true, with a message.
Definition abort.h:97
#define NS_LOG_COMPONENT_DEFINE(name)
Define a Log component with a specific name.
Definition log.h:191
#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 ",...
Ptr< T > CreateObject(Args &&... args)
Create an object by type, with varying number of constructor parameters.
Definition object.h:619
Every class exported by the ns3 library is enclosed in the ns3 namespace.