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
34 namespace ns3 {
35
36 NS_LOG_COMPONENT_DEFINE ("TraceHelper");
37
PcapHelper()38 PcapHelper::PcapHelper ()
39 {
40 NS_LOG_FUNCTION_NOARGS ();
41 }
42
~PcapHelper()43 PcapHelper::~PcapHelper ()
44 {
45 NS_LOG_FUNCTION_NOARGS ();
46 }
47
48 Ptr<PcapFileWrapper>
CreateFile(std::string filename,std::ios::openmode filemode,DataLinkType dataLinkType,uint32_t snapLen,int32_t tzCorrection)49 PcapHelper::CreateFile (
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
79 std::string
GetFilenameFromDevice(std::string prefix,Ptr<NetDevice> device,bool useObjectNames)80 PcapHelper::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
124 std::string
GetFilenameFromInterfacePair(std::string prefix,Ptr<Object> object,uint32_t interface,bool useObjectNames)125 PcapHelper::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 //
166 void
DefaultSink(Ptr<PcapFileWrapper> file,Ptr<const Packet> p)167 PcapHelper::DefaultSink (Ptr<PcapFileWrapper> file, Ptr<const Packet> p)
168 {
169 NS_LOG_FUNCTION (file << p);
170 file->Write (Simulator::Now (), p);
171 }
172
173 void
SinkWithHeader(Ptr<PcapFileWrapper> file,const Header & header,Ptr<const Packet> p)174 PcapHelper::SinkWithHeader (Ptr<PcapFileWrapper> file, const Header &header, Ptr<const Packet> p)
175 {
176 NS_LOG_FUNCTION (file << p);
177 file->Write (Simulator::Now (), header, p);
178 }
179
AsciiTraceHelper()180 AsciiTraceHelper::AsciiTraceHelper ()
181 {
182 NS_LOG_FUNCTION_NOARGS ();
183 }
184
~AsciiTraceHelper()185 AsciiTraceHelper::~AsciiTraceHelper ()
186 {
187 NS_LOG_FUNCTION_NOARGS ();
188 }
189
190 Ptr<OutputStreamWrapper>
CreateFileStream(std::string filename,std::ios::openmode filemode)191 AsciiTraceHelper::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
211 std::string
GetFilenameFromDevice(std::string prefix,Ptr<NetDevice> device,bool useObjectNames)212 AsciiTraceHelper::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
256 std::string
GetFilenameFromInterfacePair(std::string prefix,Ptr<Object> object,uint32_t interface,bool useObjectNames)257 AsciiTraceHelper::GetFilenameFromInterfacePair (
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 //
309 void
DefaultEnqueueSinkWithoutContext(Ptr<OutputStreamWrapper> stream,Ptr<const Packet> p)310 AsciiTraceHelper::DefaultEnqueueSinkWithoutContext (Ptr<OutputStreamWrapper> stream, Ptr<const Packet> p)
311 {
312 NS_LOG_FUNCTION (stream << p);
313 *stream->GetStream () << "+ " << Simulator::Now ().GetSeconds () << " " << *p << std::endl;
314 }
315
316 void
DefaultEnqueueSinkWithContext(Ptr<OutputStreamWrapper> stream,std::string context,Ptr<const Packet> p)317 AsciiTraceHelper::DefaultEnqueueSinkWithContext (Ptr<OutputStreamWrapper> stream, std::string context, Ptr<const Packet> p)
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 //
335 void
DefaultDropSinkWithoutContext(Ptr<OutputStreamWrapper> stream,Ptr<const Packet> p)336 AsciiTraceHelper::DefaultDropSinkWithoutContext (Ptr<OutputStreamWrapper> stream, Ptr<const Packet> p)
337 {
338 NS_LOG_FUNCTION (stream << p);
339 *stream->GetStream () << "d " << Simulator::Now ().GetSeconds () << " " << *p << std::endl;
340 }
341
342 void
DefaultDropSinkWithContext(Ptr<OutputStreamWrapper> stream,std::string context,Ptr<const Packet> p)343 AsciiTraceHelper::DefaultDropSinkWithContext (Ptr<OutputStreamWrapper> stream, std::string context, Ptr<const Packet> p)
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 //
362 void
DefaultDequeueSinkWithoutContext(Ptr<OutputStreamWrapper> stream,Ptr<const Packet> p)363 AsciiTraceHelper::DefaultDequeueSinkWithoutContext (Ptr<OutputStreamWrapper> stream, Ptr<const Packet> p)
364 {
365 NS_LOG_FUNCTION (stream << p);
366 *stream->GetStream () << "- " << Simulator::Now ().GetSeconds () << " " << *p << std::endl;
367 }
368
369 void
DefaultDequeueSinkWithContext(Ptr<OutputStreamWrapper> stream,std::string context,Ptr<const Packet> p)370 AsciiTraceHelper::DefaultDequeueSinkWithContext (Ptr<OutputStreamWrapper> stream, std::string context, Ptr<const Packet> p)
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.
386 void
DefaultReceiveSinkWithoutContext(Ptr<OutputStreamWrapper> stream,Ptr<const Packet> p)387 AsciiTraceHelper::DefaultReceiveSinkWithoutContext (Ptr<OutputStreamWrapper> stream, Ptr<const Packet> p)
388 {
389 NS_LOG_FUNCTION (stream << p);
390 *stream->GetStream () << "r " << Simulator::Now ().GetSeconds () << " " << *p << std::endl;
391 }
392
393 void
DefaultReceiveSinkWithContext(Ptr<OutputStreamWrapper> stream,std::string context,Ptr<const Packet> p)394 AsciiTraceHelper::DefaultReceiveSinkWithContext (Ptr<OutputStreamWrapper> stream, std::string context, Ptr<const Packet> p)
395 {
396 NS_LOG_FUNCTION (stream << p);
397 *stream->GetStream () << "r " << Simulator::Now ().GetSeconds () << " " << context << " " << *p << std::endl;
398 }
399
400 void
EnablePcap(std::string prefix,Ptr<NetDevice> nd,bool promiscuous,bool explicitFilename)401 PcapHelperForDevice::EnablePcap (std::string prefix, Ptr<NetDevice> nd, bool promiscuous, bool explicitFilename)
402 {
403 EnablePcapInternal (prefix, nd, promiscuous, explicitFilename);
404 }
405
406 void
EnablePcap(std::string prefix,std::string ndName,bool promiscuous,bool explicitFilename)407 PcapHelperForDevice::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
413 void
EnablePcap(std::string prefix,NetDeviceContainer d,bool promiscuous)414 PcapHelperForDevice::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
423 void
EnablePcap(std::string prefix,NodeContainer n,bool promiscuous)424 PcapHelperForDevice::EnablePcap (std::string prefix, NodeContainer n, bool promiscuous)
425 {
426 NetDeviceContainer devs;
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
438 void
EnablePcapAll(std::string prefix,bool promiscuous)439 PcapHelperForDevice::EnablePcapAll (std::string prefix, bool promiscuous)
440 {
441 EnablePcap (prefix, NodeContainer::GetGlobal (), promiscuous);
442 }
443
444 void
EnablePcap(std::string prefix,uint32_t nodeid,uint32_t deviceid,bool promiscuous)445 PcapHelperForDevice::EnablePcap (std::string prefix, uint32_t nodeid, uint32_t deviceid, bool promiscuous)
446 {
447 NodeContainer n = NodeContainer::GetGlobal ();
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 //
468 void
EnableAscii(std::string prefix,Ptr<NetDevice> nd,bool explicitFilename)469 AsciiTraceHelperForDevice::EnableAscii (std::string prefix, Ptr<NetDevice> nd, bool explicitFilename)
470 {
471 EnableAsciiInternal (Ptr<OutputStreamWrapper> (), prefix, nd, explicitFilename);
472 }
473
474 //
475 // Public API
476 //
477 void
EnableAscii(Ptr<OutputStreamWrapper> stream,Ptr<NetDevice> nd)478 AsciiTraceHelperForDevice::EnableAscii (Ptr<OutputStreamWrapper> stream, Ptr<NetDevice> nd)
479 {
480 EnableAsciiInternal (stream, std::string (), nd, false);
481 }
482
483 //
484 // Public API
485 //
486 void
EnableAscii(std::string prefix,std::string ndName,bool explicitFilename)487 AsciiTraceHelperForDevice::EnableAscii (std::string prefix, std::string ndName, bool explicitFilename)
488 {
489 EnableAsciiImpl (Ptr<OutputStreamWrapper> (), prefix, ndName, explicitFilename);
490 }
491
492 //
493 // Public API
494 //
495 void
EnableAscii(Ptr<OutputStreamWrapper> stream,std::string ndName)496 AsciiTraceHelperForDevice::EnableAscii (Ptr<OutputStreamWrapper> stream, std::string ndName)
497 {
498 EnableAsciiImpl (stream, std::string (), ndName, false);
499 }
500
501 //
502 // Private API
503 //
504 void
EnableAsciiImpl(Ptr<OutputStreamWrapper> stream,std::string prefix,std::string ndName,bool explicitFilename)505 AsciiTraceHelperForDevice::EnableAsciiImpl (
506 Ptr<OutputStreamWrapper> stream,
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 //
518 void
EnableAscii(std::string prefix,NetDeviceContainer d)519 AsciiTraceHelperForDevice::EnableAscii (std::string prefix, NetDeviceContainer d)
520 {
521 EnableAsciiImpl (Ptr<OutputStreamWrapper> (), prefix, d);
522 }
523
524 //
525 // Public API
526 //
527 void
EnableAscii(Ptr<OutputStreamWrapper> stream,NetDeviceContainer d)528 AsciiTraceHelperForDevice::EnableAscii (Ptr<OutputStreamWrapper> stream, NetDeviceContainer d)
529 {
530 EnableAsciiImpl (stream, std::string (), d);
531 }
532
533 //
534 // Private API
535 //
536 void
EnableAsciiImpl(Ptr<OutputStreamWrapper> stream,std::string prefix,NetDeviceContainer d)537 AsciiTraceHelperForDevice::EnableAsciiImpl (Ptr<OutputStreamWrapper> stream, std::string prefix, NetDeviceContainer d)
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 //
549 void
EnableAscii(std::string prefix,NodeContainer n)550 AsciiTraceHelperForDevice::EnableAscii (std::string prefix, NodeContainer n)
551 {
552 EnableAsciiImpl (Ptr<OutputStreamWrapper> (), prefix, n);
553 }
554
555 //
556 // Public API
557 //
558 void
EnableAscii(Ptr<OutputStreamWrapper> stream,NodeContainer n)559 AsciiTraceHelperForDevice::EnableAscii (Ptr<OutputStreamWrapper> stream, NodeContainer n)
560 {
561 EnableAsciiImpl (stream, std::string (), n);
562 }
563
564 //
565 // Private API
566 //
567 void
EnableAsciiImpl(Ptr<OutputStreamWrapper> stream,std::string prefix,NodeContainer n)568 AsciiTraceHelperForDevice::EnableAsciiImpl (Ptr<OutputStreamWrapper> stream, std::string prefix, NodeContainer n)
569 {
570 NetDeviceContainer devs;
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 //
585 void
EnableAsciiAll(std::string prefix)586 AsciiTraceHelperForDevice::EnableAsciiAll (std::string prefix)
587 {
588 EnableAsciiImpl (Ptr<OutputStreamWrapper> (), prefix, NodeContainer::GetGlobal ());
589 }
590
591 //
592 // Public API
593 //
594 void
EnableAsciiAll(Ptr<OutputStreamWrapper> stream)595 AsciiTraceHelperForDevice::EnableAsciiAll (Ptr<OutputStreamWrapper> stream)
596 {
597 EnableAsciiImpl (stream, std::string (), NodeContainer::GetGlobal ());
598 }
599
600 //
601 // Public API
602 //
603 void
EnableAscii(Ptr<OutputStreamWrapper> stream,uint32_t nodeid,uint32_t deviceid)604 AsciiTraceHelperForDevice::EnableAscii (Ptr<OutputStreamWrapper> stream, uint32_t nodeid, uint32_t deviceid)
605 {
606 EnableAsciiImpl (stream, std::string (), nodeid, deviceid, false);
607 }
608
609 //
610 // Public API
611 //
612 void
EnableAscii(std::string prefix,uint32_t nodeid,uint32_t deviceid,bool explicitFilename)613 AsciiTraceHelperForDevice::EnableAscii (
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 //
625 void
EnableAsciiImpl(Ptr<OutputStreamWrapper> stream,std::string prefix,uint32_t nodeid,uint32_t deviceid,bool explicitFilename)626 AsciiTraceHelperForDevice::EnableAsciiImpl (
627 Ptr<OutputStreamWrapper> stream,
628 std::string prefix,
629 uint32_t nodeid,
630 uint32_t deviceid,
631 bool explicitFilename)
632 {
633 NodeContainer n = NodeContainer::GetGlobal ();
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
655