A Discrete-Event Network Simulator
API
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Groups Pages
trace-helper.cc
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 NS_LOG_COMPONENT_DEFINE ("TraceHelper");
35 
36 namespace ns3 {
37 
39 {
41 }
42 
44 {
46 }
47 
50  std::string filename,
51  std::ios::openmode filemode,
52  uint32_t 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
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
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
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 
174 {
176 }
177 
179 {
181 }
182 
184 AsciiTraceHelper::CreateFileStream (std::string filename, std::ios::openmode filemode)
185 {
186  NS_LOG_FUNCTION (filename << filemode);
187 
188  Ptr<OutputStreamWrapper> StreamWrapper = Create<OutputStreamWrapper> (filename, filemode);
189 
190  //
191  // Note that the ascii trace helper promptly forgets all about the trace file.
192  // We rely on the reference count of the file object which will soon be owned
193  // by the caller to keep the object alive. If the caller uses the stream
194  // object to hook a trace source, ownership of the stream object will be
195  // implicitly transferred to the callback which keeps the object alive.
196  // When the callback is destroyed (when either the trace is disconnected or
197  // the object with the trace source is deleted) the callback will be destroyed
198  // and the stream object will be destroyed, releasing the pointer and closing
199  // the underlying file.
200  //
201  return StreamWrapper;
202 }
203 
204 std::string
205 AsciiTraceHelper::GetFilenameFromDevice (std::string prefix, Ptr<NetDevice> device, bool useObjectNames)
206 {
207  NS_LOG_FUNCTION (prefix << device << useObjectNames);
208  NS_ABORT_MSG_UNLESS (prefix.size (), "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.size ())
225  {
226  oss << nodename;
227  }
228  else
229  {
230  oss << node->GetId ();
231  }
232 
233  oss << "-";
234 
235  if (devicename.size ())
236  {
237  oss << devicename;
238  }
239  else
240  {
241  oss << device->GetIfIndex ();
242  }
243 
244  oss << ".tr";
245 
246  return oss.str ();
247 }
248 
249 std::string
251  std::string prefix,
252  Ptr<Object> object,
253  uint32_t interface,
254  bool useObjectNames)
255 {
256  NS_LOG_FUNCTION (prefix << object << interface << useObjectNames);
257  NS_ABORT_MSG_UNLESS (prefix.size (), "Empty prefix string");
258 
259  std::ostringstream oss;
260  oss << prefix << "-";
261 
262  std::string objname;
263  std::string nodename;
264 
265  Ptr<Node> node = object->GetObject<Node> ();
266 
267  if (useObjectNames)
268  {
269  objname = Names::FindName (object);
270  nodename = Names::FindName (node);
271  }
272 
273  if (objname.size ())
274  {
275  oss << objname;
276  }
277  else if (nodename.size ())
278  {
279  oss << nodename;
280  }
281  else
282  {
283  oss << "n" << node->GetId ();
284  }
285 
286  oss << "-i" << interface << ".tr";
287 
288  return oss.str ();
289 }
290 
291 //
292 // One of the basic default trace sink sets. Enqueue:
293 //
294 // When a packet has been sent to a device for transmission, the device is
295 // expected to place the packet onto a transmit queue even if it does not
296 // have to delay the packet at all, if only to trigger this event. This
297 // event will eventually translate into a '+' operation in the trace file.
298 //
299 // This is typically implemented by hooking the "TxQueue/Enqueue" trace hook
300 // in the device (actually the Queue in the device).
301 //
302 void
303 AsciiTraceHelper::DefaultEnqueueSinkWithoutContext (Ptr<OutputStreamWrapper> stream, Ptr<const Packet> p)
304 {
305  NS_LOG_FUNCTION (stream << p);
306  *stream->GetStream () << "+ " << Simulator::Now ().GetSeconds () << " " << *p << std::endl;
307 }
308 
309 void
310 AsciiTraceHelper::DefaultEnqueueSinkWithContext (Ptr<OutputStreamWrapper> stream, std::string context, Ptr<const Packet> p)
311 {
312  NS_LOG_FUNCTION (stream << p);
313  *stream->GetStream () << "+ " << Simulator::Now ().GetSeconds () << " " << context << " " << *p << std::endl;
314 }
315 
316 //
317 // One of the basic default trace sink sets. Drop:
318 //
319 // When a packet has been sent to a device for transmission, the device is
320 // expected to place the packet onto a transmit queue. If this queue is
321 // full the packet will be dropped. The device is expected to trigger an
322 // event to indicate that an outbound packet is being dropped. This event
323 // will eventually translate into a 'd' operation in the trace file.
324 //
325 // This is typically implemented by hooking the "TxQueue/Drop" trace hook
326 // in the device (actually the Queue in the device).
327 //
328 void
329 AsciiTraceHelper::DefaultDropSinkWithoutContext (Ptr<OutputStreamWrapper> stream, Ptr<const Packet> p)
330 {
331  NS_LOG_FUNCTION (stream << p);
332  *stream->GetStream () << "d " << Simulator::Now ().GetSeconds () << " " << *p << std::endl;
333 }
334 
335 void
336 AsciiTraceHelper::DefaultDropSinkWithContext (Ptr<OutputStreamWrapper> stream, std::string context, Ptr<const Packet> p)
337 {
338  NS_LOG_FUNCTION (stream << p);
339  *stream->GetStream () << "d " << Simulator::Now ().GetSeconds () << " " << context << " " << *p << std::endl;
340 }
341 
342 //
343 // One of the basic default trace sink sets. Dequeue:
344 //
345 // When a packet has been sent to a device for transmission, the device is
346 // expected to place the packet onto a transmit queue even if it does not
347 // have to delay the packet at all. The device removes the packet from the
348 // transmit queue when the packet is ready to send, and this dequeue will
349 // fire a corresponding event. This event will eventually translate into a
350 // '-' operation in the trace file.
351 //
352 // This is typically implemented by hooking the "TxQueue/Dequeue" trace hook
353 // in the device (actually the Queue in the device).
354 //
355 void
356 AsciiTraceHelper::DefaultDequeueSinkWithoutContext (Ptr<OutputStreamWrapper> stream, Ptr<const Packet> p)
357 {
358  NS_LOG_FUNCTION (stream << p);
359  *stream->GetStream () << "- " << Simulator::Now ().GetSeconds () << " " << *p << std::endl;
360 }
361 
362 void
363 AsciiTraceHelper::DefaultDequeueSinkWithContext (Ptr<OutputStreamWrapper> stream, std::string context, Ptr<const Packet> p)
364 {
365  NS_LOG_FUNCTION (stream << p);
366  *stream->GetStream () << "- " << Simulator::Now ().GetSeconds () << " " << context << " " << *p << std::endl;
367 }
368 
369 //
370 // One of the basic default trace sink sets. Receive:
371 //
372 // When a packet is received by a device for transmission, the device is
373 // expected to trigger this event to indicate the reception has occurred.
374 // This event will eventually translate into an 'r' operation in the trace
375 // file.
376 //
377 // This is typically implemented by hooking the "MacRx" trace hook in the
378 // device.
379 void
380 AsciiTraceHelper::DefaultReceiveSinkWithoutContext (Ptr<OutputStreamWrapper> stream, Ptr<const Packet> p)
381 {
382  NS_LOG_FUNCTION (stream << p);
383  *stream->GetStream () << "r " << Simulator::Now ().GetSeconds () << " " << *p << std::endl;
384 }
385 
386 void
387 AsciiTraceHelper::DefaultReceiveSinkWithContext (Ptr<OutputStreamWrapper> stream, std::string context, Ptr<const Packet> p)
388 {
389  NS_LOG_FUNCTION (stream << p);
390  *stream->GetStream () << "r " << Simulator::Now ().GetSeconds () << " " << context << " " << *p << std::endl;
391 }
392 
393 void
394 PcapHelperForDevice::EnablePcap (std::string prefix, Ptr<NetDevice> nd, bool promiscuous, bool explicitFilename)
395 {
396  EnablePcapInternal (prefix, nd, promiscuous, explicitFilename);
397 }
398 
399 void
400 PcapHelperForDevice::EnablePcap (std::string prefix, std::string ndName, bool promiscuous, bool explicitFilename)
401 {
402  Ptr<NetDevice> nd = Names::Find<NetDevice> (ndName);
403  EnablePcap (prefix, nd, promiscuous, explicitFilename);
404 }
405 
406 void
407 PcapHelperForDevice::EnablePcap (std::string prefix, NetDeviceContainer d, bool promiscuous)
408 {
409  for (NetDeviceContainer::Iterator i = d.Begin (); i != d.End (); ++i)
410  {
411  Ptr<NetDevice> dev = *i;
412  EnablePcap (prefix, dev, promiscuous);
413  }
414 }
415 
416 void
417 PcapHelperForDevice::EnablePcap (std::string prefix, NodeContainer n, bool promiscuous)
418 {
419  NetDeviceContainer devs;
420  for (NodeContainer::Iterator i = n.Begin (); i != n.End (); ++i)
421  {
422  Ptr<Node> node = *i;
423  for (uint32_t j = 0; j < node->GetNDevices (); ++j)
424  {
425  devs.Add (node->GetDevice (j));
426  }
427  }
428  EnablePcap (prefix, devs, promiscuous);
429 }
430 
431 void
432 PcapHelperForDevice::EnablePcapAll (std::string prefix, bool promiscuous)
433 {
434  EnablePcap (prefix, NodeContainer::GetGlobal (), promiscuous);
435 }
436 
437 void
438 PcapHelperForDevice::EnablePcap (std::string prefix, uint32_t nodeid, uint32_t deviceid, bool promiscuous)
439 {
441 
442  for (NodeContainer::Iterator i = n.Begin (); i != n.End (); ++i)
443  {
444  Ptr<Node> node = *i;
445  if (node->GetId () != nodeid)
446  {
447  continue;
448  }
449 
450  NS_ABORT_MSG_IF (deviceid >= node->GetNDevices (), "PcapHelperForDevice::EnablePcap(): Unknown deviceid = "
451  << deviceid);
452  Ptr<NetDevice> nd = node->GetDevice (deviceid);
453  EnablePcap (prefix, nd, promiscuous);
454  return;
455  }
456 }
457 
458 //
459 // Public API
460 //
461 void
462 AsciiTraceHelperForDevice::EnableAscii (std::string prefix, Ptr<NetDevice> nd, bool explicitFilename)
463 {
464  EnableAsciiInternal (Ptr<OutputStreamWrapper> (), prefix, nd, explicitFilename);
465 }
466 
467 //
468 // Public API
469 //
470 void
472 {
473  EnableAsciiInternal (stream, std::string (), nd, false);
474 }
475 
476 //
477 // Public API
478 //
479 void
480 AsciiTraceHelperForDevice::EnableAscii (std::string prefix, std::string ndName, bool explicitFilename)
481 {
482  EnableAsciiImpl (Ptr<OutputStreamWrapper> (), prefix, ndName, explicitFilename);
483 }
484 
485 //
486 // Public API
487 //
488 void
490 {
491  EnableAsciiImpl (stream, std::string (), ndName, false);
492 }
493 
494 //
495 // Private API
496 //
497 void
499  Ptr<OutputStreamWrapper> stream,
500  std::string prefix,
501  std::string ndName,
502  bool explicitFilename)
503 {
504  Ptr<NetDevice> nd = Names::Find<NetDevice> (ndName);
505  EnableAsciiInternal (stream, prefix, nd, explicitFilename);
506 }
507 
508 //
509 // Public API
510 //
511 void
513 {
515 }
516 
517 //
518 // Public API
519 //
520 void
522 {
523  EnableAsciiImpl (stream, std::string (), d);
524 }
525 
526 //
527 // Private API
528 //
529 void
531 {
532  for (NetDeviceContainer::Iterator i = d.Begin (); i != d.End (); ++i)
533  {
534  Ptr<NetDevice> dev = *i;
535  EnableAsciiInternal (stream, prefix, dev, false);
536  }
537 }
538 
539 //
540 // Public API
541 //
542 void
544 {
546 }
547 
548 //
549 // Public API
550 //
551 void
553 {
554  EnableAsciiImpl (stream, std::string (), n);
555 }
556 
557 //
558 // Private API
559 //
560 void
562 {
563  NetDeviceContainer devs;
564  for (NodeContainer::Iterator i = n.Begin (); i != n.End (); ++i)
565  {
566  Ptr<Node> node = *i;
567  for (uint32_t j = 0; j < node->GetNDevices (); ++j)
568  {
569  devs.Add (node->GetDevice (j));
570  }
571  }
572  EnableAsciiImpl (stream, prefix, devs);
573 }
574 
575 //
576 // Public API
577 //
578 void
580 {
582 }
583 
584 //
585 // Public API
586 //
587 void
589 {
590  EnableAsciiImpl (stream, std::string (), NodeContainer::GetGlobal ());
591 }
592 
593 //
594 // Public API
595 //
596 void
597 AsciiTraceHelperForDevice::EnableAscii (Ptr<OutputStreamWrapper> stream, uint32_t nodeid, uint32_t deviceid)
598 {
599  EnableAsciiImpl (stream, std::string (), nodeid, deviceid, false);
600 }
601 
602 //
603 // Public API
604 //
605 void
607  std::string prefix,
608  uint32_t nodeid,
609  uint32_t deviceid,
610  bool explicitFilename)
611 {
612  EnableAsciiImpl (Ptr<OutputStreamWrapper> (), prefix, nodeid, deviceid, explicitFilename);
613 }
614 
615 //
616 // Private API
617 //
618 void
620  Ptr<OutputStreamWrapper> stream,
621  std::string prefix,
622  uint32_t nodeid,
623  uint32_t deviceid,
624  bool explicitFilename)
625 {
627 
628  for (NodeContainer::Iterator i = n.Begin (); i != n.End (); ++i)
629  {
630  Ptr<Node> node = *i;
631  if (node->GetId () != nodeid)
632  {
633  continue;
634  }
635 
636  NS_ABORT_MSG_IF (deviceid >= node->GetNDevices (),
637  "AsciiTraceHelperForDevice::EnableAscii(): Unknown deviceid = " << deviceid);
638 
639  Ptr<NetDevice> nd = node->GetDevice (deviceid);
640 
641  EnableAsciiInternal (stream, prefix, nd, explicitFilename);
642  return;
643  }
644 }
645 
646 } // namespace ns3
647 
Iterator Begin(void) const
Get an iterator which refers to the first NetDevice in the container.
smart pointer class similar to boost::intrusive_ptr
Definition: ptr.h:59
#define NS_LOG_FUNCTION(parameters)
Definition: log.h:311
Ptr< PcapFileWrapper > CreateFile(std::string filename, std::ios::openmode filemode, uint32_t dataLinkType, uint32_t snapLen=65535, int32_t tzCorrection=0)
Create and initialize a pcap file.
Definition: trace-helper.cc:49
void EnableAsciiImpl(Ptr< OutputStreamWrapper > stream, std::string prefix, uint32_t nodeid, uint32_t deviceid, bool explicitFilename)
#define NS_LOG_COMPONENT_DEFINE(name)
Definition: log.h:122
Iterator End(void) const
Get an iterator which indicates past-the-last Node in the container.
#define NS_LOG_FUNCTION_NOARGS()
Definition: log.h:275
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. ...
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...
#define NS_ABORT_MSG_UNLESS(cond, msg)
Abnormal program termination if cond is false.
Definition: abort.h:131
double GetSeconds(void) const
Definition: nstime.h:262
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:80
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 Add(NetDeviceContainer other)
Append the contents of another NetDeviceContainer to the end of this container.
holds a vector of ns3::NetDevice pointers
Ptr< NetDevice > GetDevice(uint32_t index) const
Definition: node.cc:133
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...
uint32_t GetNDevices(void) const
Definition: node.cc:141
keep track of a set of node pointers.
Iterator Begin(void) const
Get an iterator which refers to the first Node in the container.
virtual void EnablePcapInternal(std::string prefix, Ptr< NetDevice > nd, bool promiscuous, bool explicitFilename)=0
Enable pcap output the indicated net device.
AsciiTraceHelper()
Create an ascii trace helper.
static Time Now(void)
Definition: simulator.cc:179
PcapHelper()
Create a pcap helper.
Definition: trace-helper.cc:38
static NodeContainer GetGlobal(void)
Create a NodeContainer that contains a list of all nodes created through NodeContainer::Create() and ...
void EnableAscii(std::string prefix, Ptr< NetDevice > nd, bool explicitFilename=false)
Enable ascii trace output on the indicated net device.
uint32_t GetId(void) const
Definition: node.cc:105
A network Node.
Definition: node.h:56
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...
virtual void EnableAsciiInternal(Ptr< OutputStreamWrapper > stream, std::string prefix, Ptr< NetDevice > nd, bool explicitFilename)=0
Enable ascii trace output on the indicated net device.
static std::string FindName(Ptr< Object > object)
Definition: names.cc:664
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...
void EnablePcap(std::string prefix, Ptr< NetDevice > nd, bool promiscuous=false, bool explicitFilename=false)
Enable pcap output the indicated net device.
#define NS_ABORT_MSG_IF(cond, msg)
Abnormal program termination if cond is true.
Definition: abort.h:98
Iterator End(void) const
Get an iterator which indicates past-the-last NetDevice in the container.
~AsciiTraceHelper()
Destroy an ascii trace helper.
Ptr< T > GetObject(void) const
Definition: object.h:332
~PcapHelper()
Destroy a pcap helper.
Definition: trace-helper.cc:43
std::ostream * GetStream(void)