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
39 std::ios::openmode filemode,
43{
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
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
82 {
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);
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{
529 Ptr<NetDevice> nd = Names::Find<NetDevice>(ndName);
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
629{
630 EnableAsciiImpl(stream, std::string(), nodeid, deviceid, false);
631}
632
633//
634// Public API
635//
636void
640 bool explicitFilename)
641{
642 EnableAsciiImpl(Ptr<OutputStreamWrapper>(), prefix, nodeid, deviceid, explicitFilename);
643}
644
645//
646// Private API
647//
648void
650 std::string prefix,
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 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
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.
Definition ptr.h:66
#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 > Create(Ts &&... args)
Create class instances by constructors with varying numbers of arguments and return them by Ptr.
Definition ptr.h:436
Every class exported by the ns3 library is enclosed in the ns3 namespace.