A Discrete-Event Network Simulator
API
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Groups Pages
trace-helper.cc
Go to the documentation of this file.
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
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
304 {
305  NS_LOG_FUNCTION (stream << p);
306  *stream->GetStream () << "+ " << Simulator::Now ().GetSeconds () << " " << *p << std::endl;
307 }
308 
309 void
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
330 {
331  NS_LOG_FUNCTION (stream << p);
332  *stream->GetStream () << "d " << Simulator::Now ().GetSeconds () << " " << *p << std::endl;
333 }
334 
335 void
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
357 {
358  NS_LOG_FUNCTION (stream << p);
359  *stream->GetStream () << "- " << Simulator::Now ().GetSeconds () << " " << *p << std::endl;
360 }
361 
362 void
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
381 {
382  NS_LOG_FUNCTION (stream << p);
383  *stream->GetStream () << "r " << Simulator::Now ().GetSeconds () << " " << *p << std::endl;
384 }
385 
386 void
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