A Discrete-Event Network Simulator
API
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Groups Pages
internet-stack-helper.cc
1 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
2 /*
3  * Copyright (c) 2008 INRIA
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  * Author: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
19  * Author: Faker Moatamri <faker.moatamri@sophia.inria.fr>
20  */
21 
151 #include "ns3/assert.h"
152 #include "ns3/log.h"
153 #include "ns3/object.h"
154 #include "ns3/names.h"
155 #include "ns3/ipv4.h"
156 #include "ns3/ipv6.h"
157 #include "ns3/packet-socket-factory.h"
158 #include "ns3/config.h"
159 #include "ns3/simulator.h"
160 #include "ns3/string.h"
161 #include "ns3/net-device.h"
162 #include "ns3/callback.h"
163 #include "ns3/node.h"
164 #include "ns3/node-list.h"
165 #include "ns3/core-config.h"
166 #include "ns3/arp-l3-protocol.h"
167 #include "internet-stack-helper.h"
168 #include "ns3/ipv4-global-routing.h"
169 #include "ns3/ipv4-list-routing-helper.h"
170 #include "ns3/ipv4-static-routing-helper.h"
171 #include "ns3/ipv4-global-routing-helper.h"
172 #include "ns3/ipv6-list-routing-helper.h"
173 #include "ns3/ipv6-static-routing-helper.h"
174 #include "ns3/ipv6-extension.h"
175 #include "ns3/ipv6-extension-demux.h"
176 #include "ns3/ipv6-extension-header.h"
177 #include "ns3/global-router-interface.h"
178 #include <limits>
179 #include <map>
180 
181 NS_LOG_COMPONENT_DEFINE ("InternetStackHelper");
182 
183 namespace ns3 {
184 
185 //
186 // Historically, the only context written to ascii traces was the protocol.
187 // Traces from the protocols include the interface, though. It is not
188 // possible to really determine where an event originated without including
189 // this. If you want the additional context information, define
190 // INTERFACE_CONTEXT. If you want compatibility with the old-style traces
191 // comment it out.
192 //
193 #define INTERFACE_CONTEXT
194 
195 //
196 // Things are going to work differently here with respect to trace file handling
197 // than in most places because the Tx and Rx trace sources we are interested in
198 // are going to multiplex receive and transmit callbacks for all Ipv4 and
199 // interface pairs through one callback. We want packets to or from each
200 // distinct pair to go to an individual file, so we have got to demultiplex the
201 // Ipv4 and interface pair into a corresponding Ptr<PcapFileWrapper> at the
202 // callback.
203 //
204 // A complication in this situation is that the trace sources are hooked on
205 // a protocol basis. There is no trace source hooked by an Ipv4 and interface
206 // pair. This means that if we naively proceed to hook, say, a drop trace
207 // for a given Ipv4 with interface 0, and then hook for Ipv4 with interface 1
208 // we will hook the drop trace twice and get two callbacks per event. What
209 // we need to do is to hook the event once, and that will result in a single
210 // callback per drop event, and the trace source will provide the interface
211 // which we filter on in the trace sink.
212 //
213 // This has got to continue to work properly after the helper has been
214 // destroyed; but must be cleaned up at the end of time to avoid leaks.
215 // Global maps of protocol/interface pairs to file objects seems to fit the
216 // bill.
217 //
218 typedef std::pair<Ptr<Ipv4>, uint32_t> InterfacePairIpv4;
219 typedef std::map<InterfacePairIpv4, Ptr<PcapFileWrapper> > InterfaceFileMapIpv4;
220 typedef std::map<InterfacePairIpv4, Ptr<OutputStreamWrapper> > InterfaceStreamMapIpv4;
221 
222 static InterfaceFileMapIpv4 g_interfaceFileMapIpv4;
223 static InterfaceStreamMapIpv4 g_interfaceStreamMapIpv4;
225 typedef std::pair<Ptr<Ipv6>, uint32_t> InterfacePairIpv6;
226 typedef std::map<InterfacePairIpv6, Ptr<PcapFileWrapper> > InterfaceFileMapIpv6;
227 typedef std::map<InterfacePairIpv6, Ptr<OutputStreamWrapper> > InterfaceStreamMapIpv6;
228 
229 static InterfaceFileMapIpv6 g_interfaceFileMapIpv6;
230 static InterfaceStreamMapIpv6 g_interfaceStreamMapIpv6;
233  : m_routing (0),
234  m_routingv6 (0),
235  m_ipv4Enabled (true),
236  m_ipv6Enabled (true)
237 {
238  Initialize ();
239 }
240 
241 // private method called by both constructor and Reset ()
242 void
243 InternetStackHelper::Initialize ()
244 {
245  SetTcp ("ns3::TcpL4Protocol");
246  Ipv4StaticRoutingHelper staticRouting;
247  Ipv4GlobalRoutingHelper globalRouting;
248  Ipv4ListRoutingHelper listRouting;
249  Ipv6ListRoutingHelper listRoutingv6;
250  Ipv6StaticRoutingHelper staticRoutingv6;
251  listRouting.Add (staticRouting, 0);
252  listRouting.Add (globalRouting, -10);
253  listRoutingv6.Add (staticRoutingv6, 0);
254  SetRoutingHelper (listRouting);
255  SetRoutingHelper (listRoutingv6);
256 }
257 
259 {
260  delete m_routing;
261  delete m_routingv6;
262 }
263 
265 {
266  m_routing = o.m_routing->Copy ();
267  m_routingv6 = o.m_routingv6->Copy ();
270  m_tcpFactory = o.m_tcpFactory;
271 }
272 
273 InternetStackHelper &
274 InternetStackHelper::operator = (const InternetStackHelper &o)
275 {
276  if (this == &o)
277  {
278  return *this;
279  }
280  m_routing = o.m_routing->Copy ();
281  m_routingv6 = o.m_routingv6->Copy ();
282  return *this;
283 }
284 
285 void
287 {
288  delete m_routing;
289  m_routing = 0;
290  delete m_routingv6;
291  m_routingv6 = 0;
292  m_ipv4Enabled = true;
293  m_ipv6Enabled = true;
294  Initialize ();
295 }
296 
297 void
299 {
300  delete m_routing;
301  m_routing = routing.Copy ();
302 }
303 
304 void
306 {
307  delete m_routingv6;
308  m_routingv6 = routing.Copy ();
309 }
310 
311 void
313 {
314  m_ipv4Enabled = enable;
315 }
316 
318 {
319  m_ipv6Enabled = enable;
320 }
321 
322 int64_t
324 {
325  int64_t currentStream = stream;
326  for (NodeContainer::Iterator i = c.Begin (); i != c.End (); ++i)
327  {
328  Ptr<Node> node = *i;
329  Ptr<GlobalRouter> router = node->GetObject<GlobalRouter> ();
330  if (router != 0)
331  {
332  Ptr<Ipv4GlobalRouting> gr = router->GetRoutingProtocol ();
333  if (gr != 0)
334  {
335  currentStream += gr->AssignStreams (currentStream);
336  }
337  }
339  if (demux != 0)
340  {
341  Ptr<Ipv6Extension> fe = demux->GetExtension (Ipv6ExtensionFragment::EXT_NUMBER);
342  NS_ASSERT (fe); // should always exist in the demux
343  currentStream += fe->AssignStreams (currentStream);
344  }
345  }
346  return (currentStream - stream);
347 }
348 
349 void
350 InternetStackHelper::SetTcp (const std::string tid)
351 {
352  m_tcpFactory.SetTypeId (tid);
353 }
354 
355 void
356 InternetStackHelper::SetTcp (std::string tid, std::string n0, const AttributeValue &v0)
357 {
358  m_tcpFactory.SetTypeId (tid);
359  m_tcpFactory.Set (n0,v0);
360 }
361 
362 void
364 {
365  for (NodeContainer::Iterator i = c.Begin (); i != c.End (); ++i)
366  {
367  Install (*i);
368  }
369 }
370 
371 void
373 {
374  for (NodeContainer::Iterator i = c.Begin (); i != c.End (); ++i)
375  {
376  InstallCR (repo, *i);
377  }
378 }
379 
380 void
382 {
384 }
385 
386 void
388 {
389  ObjectFactory factory;
390  factory.SetTypeId (typeId);
391  Ptr<Object> protocol = factory.Create <Object> ();
392  node->AggregateObject (protocol);
393 }
394 
395 void
397 {
398  if (m_ipv4Enabled)
399  {
400  if (node->GetObject<Ipv4> () != 0)
401  {
402  NS_FATAL_ERROR ("InternetStackHelper::Install (): Aggregating "
403  "an InternetStack to a node with an existing Ipv4 object");
404  return;
405  }
406 
407  CreateAndAggregateObjectFromTypeId (node, "ns3::ArpL3Protocol");
408  CreateAndAggregateObjectFromTypeId (node, "ns3::Ipv4L3Protocol");
409  CreateAndAggregateObjectFromTypeId (node, "ns3::Icmpv4L4Protocol");
410  // Set routing
411  Ptr<Ipv4> ipv4 = node->GetObject<Ipv4> ();
412  Ptr<Ipv4RoutingProtocol> ipv4Routing = m_routing->Create (node);
413  ipv4->SetRoutingProtocol (ipv4Routing);
414  }
415 
416  if (m_ipv6Enabled)
417  {
418  /* IPv6 stack */
419  if (node->GetObject<Ipv6> () != 0)
420  {
421  NS_FATAL_ERROR ("InternetStackHelper::Install (): Aggregating "
422  "an InternetStack to a node with an existing Ipv6 object");
423  return;
424  }
425 
426  CreateAndAggregateObjectFromTypeId (node, "ns3::Ipv6L3Protocol");
427  CreateAndAggregateObjectFromTypeId (node, "ns3::Icmpv6L4Protocol");
428  // Set routing
429  Ptr<Ipv6> ipv6 = node->GetObject<Ipv6> ();
430  Ptr<Ipv6RoutingProtocol> ipv6Routing = m_routingv6->Create (node);
431  ipv6->SetRoutingProtocol (ipv6Routing);
432 
433  /* register IPv6 extensions and options */
434  ipv6->RegisterExtensions ();
435  ipv6->RegisterOptions ();
436  }
437 
439  {
440  CreateAndAggregateObjectFromTypeId (node, "ns3::UdpL4Protocol");
441  node->AggregateObject (m_tcpFactory.Create<Object> ());
442  Ptr<PacketSocketFactory> factory = CreateObject<PacketSocketFactory> ();
443  node->AggregateObject (factory);
444  }
445 }
446 
447 void
449 {
450  Install (node);
451  node->GetObject <Ipv4>()->GetRoutingProtocol()->SetRepository(repo);
452 }
453 
454 void
455 InternetStackHelper::Install (std::string nodeName) const
456 {
457  Ptr<Node> node = Names::Find<Node> (nodeName);
458  Install (node);
459 }
460 
461 static void
462 Ipv4L3ProtocolRxTxSink (Ptr<const Packet> p, Ptr<Ipv4> ipv4, uint32_t interface)
463 {
464  NS_LOG_FUNCTION (p << ipv4 << interface);
465 
466  //
467  // Since trace sources are independent of interface, if we hook a source
468  // on a particular protocol we will get traces for all of its interfaces.
469  // We need to filter this to only report interfaces for which the user
470  // has expressed interest.
471  //
472  InterfacePairIpv4 pair = std::make_pair (ipv4, interface);
473  if (g_interfaceFileMapIpv4.find (pair) == g_interfaceFileMapIpv4.end ())
474  {
475  NS_LOG_INFO ("Ignoring packet to/from interface " << interface);
476  return;
477  }
478 
479  Ptr<PcapFileWrapper> file = g_interfaceFileMapIpv4[pair];
480  file->Write (Simulator::Now (), p);
481 }
482 
483 bool
485 {
486  for ( InterfaceFileMapIpv4::const_iterator i = g_interfaceFileMapIpv4.begin ();
487  i != g_interfaceFileMapIpv4.end ();
488  ++i)
489  {
490  if ((*i).first.first == ipv4)
491  {
492  return true;
493  }
494  }
495  return false;
496 }
497 
498 void
499 InternetStackHelper::EnablePcapIpv4Internal (std::string prefix, Ptr<Ipv4> ipv4, uint32_t interface, bool explicitFilename)
500 {
501  NS_LOG_FUNCTION (prefix << ipv4 << interface);
502 
503  if (!m_ipv4Enabled)
504  {
505  NS_LOG_INFO ("Call to enable Ipv4 pcap tracing but Ipv4 not enabled");
506  return;
507  }
508 
509  //
510  // We have to create a file and a mapping from protocol/interface to file
511  // irrespective of how many times we want to trace a particular protocol.
512  //
513  PcapHelper pcapHelper;
514 
515  std::string filename;
516  if (explicitFilename)
517  {
518  filename = prefix;
519  }
520  else
521  {
522  filename = pcapHelper.GetFilenameFromInterfacePair (prefix, ipv4, interface);
523  }
524 
525  Ptr<PcapFileWrapper> file = pcapHelper.CreateFile (filename, std::ios::out, PcapHelper::DLT_RAW);
526 
527  //
528  // However, we only hook the trace source once to avoid multiple trace sink
529  // calls per event (connect is independent of interface).
530  //
531  if (!PcapHooked (ipv4))
532  {
533  //
534  // Ptr<Ipv4> is aggregated to node and Ipv4L3Protocol is aggregated to
535  // node so we can get to Ipv4L3Protocol through Ipv4.
536  //
537  Ptr<Ipv4L3Protocol> ipv4L3Protocol = ipv4->GetObject<Ipv4L3Protocol> ();
538  NS_ASSERT_MSG (ipv4L3Protocol, "InternetStackHelper::EnablePcapIpv4Internal(): "
539  "m_ipv4Enabled and ipv4L3Protocol inconsistent");
540 
541  bool result = ipv4L3Protocol->TraceConnectWithoutContext ("Tx", MakeCallback (&Ipv4L3ProtocolRxTxSink));
542  NS_ASSERT_MSG (result == true, "InternetStackHelper::EnablePcapIpv4Internal(): "
543  "Unable to connect ipv4L3Protocol \"Tx\"");
544 
545  result = ipv4L3Protocol->TraceConnectWithoutContext ("Rx", MakeCallback (&Ipv4L3ProtocolRxTxSink));
546  NS_ASSERT_MSG (result == true, "InternetStackHelper::EnablePcapIpv4Internal(): "
547  "Unable to connect ipv4L3Protocol \"Rx\"");
548  }
549 
550  g_interfaceFileMapIpv4[std::make_pair (ipv4, interface)] = file;
551 }
552 
553 static void
554 Ipv6L3ProtocolRxTxSink (Ptr<const Packet> p, Ptr<Ipv6> ipv6, uint32_t interface)
555 {
556  NS_LOG_FUNCTION (p << ipv6 << interface);
557 
558  //
559  // Since trace sources are independent of interface, if we hook a source
560  // on a particular protocol we will get traces for all of its interfaces.
561  // We need to filter this to only report interfaces for which the user
562  // has expressed interest.
563  //
564  InterfacePairIpv6 pair = std::make_pair (ipv6, interface);
565  if (g_interfaceFileMapIpv6.find (pair) == g_interfaceFileMapIpv6.end ())
566  {
567  NS_LOG_INFO ("Ignoring packet to/from interface " << interface);
568  return;
569  }
570 
571  Ptr<PcapFileWrapper> file = g_interfaceFileMapIpv6[pair];
572  file->Write (Simulator::Now (), p);
573 }
574 
575 bool
577 {
578  for ( InterfaceFileMapIpv6::const_iterator i = g_interfaceFileMapIpv6.begin ();
579  i != g_interfaceFileMapIpv6.end ();
580  ++i)
581  {
582  if ((*i).first.first == ipv6)
583  {
584  return true;
585  }
586  }
587  return false;
588 }
589 
590 void
591 InternetStackHelper::EnablePcapIpv6Internal (std::string prefix, Ptr<Ipv6> ipv6, uint32_t interface, bool explicitFilename)
592 {
593  NS_LOG_FUNCTION (prefix << ipv6 << interface);
594 
595  if (!m_ipv6Enabled)
596  {
597  NS_LOG_INFO ("Call to enable Ipv6 pcap tracing but Ipv6 not enabled");
598  return;
599  }
600 
601  //
602  // We have to create a file and a mapping from protocol/interface to file
603  // irrespective of how many times we want to trace a particular protocol.
604  //
605  PcapHelper pcapHelper;
606 
607  std::string filename;
608  if (explicitFilename)
609  {
610  filename = prefix;
611  }
612  else
613  {
614  filename = pcapHelper.GetFilenameFromInterfacePair (prefix, ipv6, interface);
615  }
616 
617  Ptr<PcapFileWrapper> file = pcapHelper.CreateFile (filename, std::ios::out, PcapHelper::DLT_RAW);
618 
619  //
620  // However, we only hook the trace source once to avoid multiple trace sink
621  // calls per event (connect is independent of interface).
622  //
623  if (!PcapHooked (ipv6))
624  {
625  //
626  // Ptr<Ipv6> is aggregated to node and Ipv6L3Protocol is aggregated to
627  // node so we can get to Ipv6L3Protocol through Ipv6.
628  //
629  Ptr<Ipv6L3Protocol> ipv6L3Protocol = ipv6->GetObject<Ipv6L3Protocol> ();
630  NS_ASSERT_MSG (ipv6L3Protocol, "InternetStackHelper::EnablePcapIpv6Internal(): "
631  "m_ipv6Enabled and ipv6L3Protocol inconsistent");
632 
633  bool result = ipv6L3Protocol->TraceConnectWithoutContext ("Tx", MakeCallback (&Ipv6L3ProtocolRxTxSink));
634  NS_ASSERT_MSG (result == true, "InternetStackHelper::EnablePcapIpv6Internal(): "
635  "Unable to connect ipv6L3Protocol \"Tx\"");
636 
637  result = ipv6L3Protocol->TraceConnectWithoutContext ("Rx", MakeCallback (&Ipv6L3ProtocolRxTxSink));
638  NS_ASSERT_MSG (result == true, "InternetStackHelper::EnablePcapIpv6Internal(): "
639  "Unable to connect ipv6L3Protocol \"Rx\"");
640  }
641 
642  g_interfaceFileMapIpv6[std::make_pair (ipv6, interface)] = file;
643 }
644 
645 static void
646 Ipv4L3ProtocolDropSinkWithoutContext (
648  Ipv4Header const &header,
649  Ptr<const Packet> packet,
651  Ptr<Ipv4> ipv4,
652  uint32_t interface)
653 {
654  //
655  // Since trace sources are independent of interface, if we hook a source
656  // on a particular protocol we will get traces for all of its interfaces.
657  // We need to filter this to only report interfaces for which the user
658  // has expressed interest.
659  //
660  InterfacePairIpv4 pair = std::make_pair (ipv4, interface);
661  if (g_interfaceStreamMapIpv4.find (pair) == g_interfaceStreamMapIpv4.end ())
662  {
663  NS_LOG_INFO ("Ignoring packet to/from interface " << interface);
664  return;
665  }
666 
667  Ptr<Packet> p = packet->Copy ();
668  p->AddHeader (header);
669  *stream->GetStream () << "d " << Simulator::Now ().GetSeconds () << " " << *p << std::endl;
670 }
671 
672 static void
673 Ipv4L3ProtocolTxSinkWithoutContext (
674  Ptr<OutputStreamWrapper> stream,
675  Ptr<const Packet> packet,
676  Ptr<Ipv4> ipv4,
677  uint32_t interface)
678 {
679  InterfacePairIpv4 pair = std::make_pair (ipv4, interface);
680  if (g_interfaceStreamMapIpv4.find (pair) == g_interfaceStreamMapIpv4.end ())
681  {
682  NS_LOG_INFO ("Ignoring packet to/from interface " << interface);
683  return;
684  }
685 
686  *stream->GetStream () << "t " << Simulator::Now ().GetSeconds () << " " << *packet << std::endl;
687 }
688 
689 static void
690 Ipv4L3ProtocolRxSinkWithoutContext (
691  Ptr<OutputStreamWrapper> stream,
692  Ptr<const Packet> packet,
693  Ptr<Ipv4> ipv4,
694  uint32_t interface)
695 {
696  InterfacePairIpv4 pair = std::make_pair (ipv4, interface);
697  if (g_interfaceStreamMapIpv4.find (pair) == g_interfaceStreamMapIpv4.end ())
698  {
699  NS_LOG_INFO ("Ignoring packet to/from interface " << interface);
700  return;
701  }
702 
703  *stream->GetStream () << "r " << Simulator::Now ().GetSeconds () << " " << *packet << std::endl;
704 }
705 
706 static void
707 Ipv4L3ProtocolDropSinkWithContext (
708  Ptr<OutputStreamWrapper> stream,
709  std::string context,
710  Ipv4Header const &header,
711  Ptr<const Packet> packet,
713  Ptr<Ipv4> ipv4,
714  uint32_t interface)
715 {
716  //
717  // Since trace sources are independent of interface, if we hook a source
718  // on a particular protocol we will get traces for all of its interfaces.
719  // We need to filter this to only report interfaces for which the user
720  // has expressed interest.
721  //
722  InterfacePairIpv4 pair = std::make_pair (ipv4, interface);
723  if (g_interfaceStreamMapIpv4.find (pair) == g_interfaceStreamMapIpv4.end ())
724  {
725  NS_LOG_INFO ("Ignoring packet to/from interface " << interface);
726  return;
727  }
728 
729  Ptr<Packet> p = packet->Copy ();
730  p->AddHeader (header);
731 #ifdef INTERFACE_CONTEXT
732  *stream->GetStream () << "d " << Simulator::Now ().GetSeconds () << " " << context << "(" << interface << ") "
733  << *p << std::endl;
734 #else
735  *stream->GetStream () << "d " << Simulator::Now ().GetSeconds () << " " << context << " " << *p << std::endl;
736 #endif
737 }
738 
739 static void
740 Ipv4L3ProtocolTxSinkWithContext (
741  Ptr<OutputStreamWrapper> stream,
742  std::string context,
743  Ptr<const Packet> packet,
744  Ptr<Ipv4> ipv4,
745  uint32_t interface)
746 {
747  InterfacePairIpv4 pair = std::make_pair (ipv4, interface);
748  if (g_interfaceStreamMapIpv4.find (pair) == g_interfaceStreamMapIpv4.end ())
749  {
750  NS_LOG_INFO ("Ignoring packet to/from interface " << interface);
751  return;
752  }
753 
754 #ifdef INTERFACE_CONTEXT
755  *stream->GetStream () << "t " << Simulator::Now ().GetSeconds () << " " << context << "(" << interface << ") "
756  << *packet << std::endl;
757 #else
758  *stream->GetStream () << "t " << Simulator::Now ().GetSeconds () << " " << context << " " << *packet << std::endl;
759 #endif
760 }
761 
762 static void
763 Ipv4L3ProtocolRxSinkWithContext (
764  Ptr<OutputStreamWrapper> stream,
765  std::string context,
766  Ptr<const Packet> packet,
767  Ptr<Ipv4> ipv4,
768  uint32_t interface)
769 {
770  InterfacePairIpv4 pair = std::make_pair (ipv4, interface);
771  if (g_interfaceStreamMapIpv4.find (pair) == g_interfaceStreamMapIpv4.end ())
772  {
773  NS_LOG_INFO ("Ignoring packet to/from interface " << interface);
774  return;
775  }
776 
777 #ifdef INTERFACE_CONTEXT
778  *stream->GetStream () << "r " << Simulator::Now ().GetSeconds () << " " << context << "(" << interface << ") "
779  << *packet << std::endl;
780 #else
781  *stream->GetStream () << "r " << Simulator::Now ().GetSeconds () << " " << context << " " << *packet << std::endl;
782 #endif
783 }
784 
785 bool
787 {
788  for ( InterfaceStreamMapIpv4::const_iterator i = g_interfaceStreamMapIpv4.begin ();
789  i != g_interfaceStreamMapIpv4.end ();
790  ++i)
791  {
792  if ((*i).first.first == ipv4)
793  {
794  return true;
795  }
796  }
797  return false;
798 }
799 
800 void
802  Ptr<OutputStreamWrapper> stream,
803  std::string prefix,
804  Ptr<Ipv4> ipv4,
805  uint32_t interface,
806  bool explicitFilename)
807 {
808  if (!m_ipv4Enabled)
809  {
810  NS_LOG_INFO ("Call to enable Ipv4 ascii tracing but Ipv4 not enabled");
811  return;
812  }
813 
814  //
815  // Our trace sinks are going to use packet printing, so we have to
816  // make sure that is turned on.
817  //
819 
820  //
821  // If we are not provided an OutputStreamWrapper, we are expected to create
822  // one using the usual trace filename conventions and hook WithoutContext
823  // since there will be one file per context and therefore the context would
824  // be redundant.
825  //
826  if (stream == 0)
827  {
828  //
829  // Set up an output stream object to deal with private ofstream copy
830  // constructor and lifetime issues. Let the helper decide the actual
831  // name of the file given the prefix.
832  //
833  // We have to create a stream and a mapping from protocol/interface to
834  // stream irrespective of how many times we want to trace a particular
835  // protocol.
836  //
837  AsciiTraceHelper asciiTraceHelper;
838 
839  std::string filename;
840  if (explicitFilename)
841  {
842  filename = prefix;
843  }
844  else
845  {
846  filename = asciiTraceHelper.GetFilenameFromInterfacePair (prefix, ipv4, interface);
847  }
848 
849  Ptr<OutputStreamWrapper> theStream = asciiTraceHelper.CreateFileStream (filename);
850 
851  //
852  // However, we only hook the trace sources once to avoid multiple trace sink
853  // calls per event (connect is independent of interface).
854  //
855  if (!AsciiHooked (ipv4))
856  {
857  //
858  // We can use the default drop sink for the ArpL3Protocol since it has
859  // the usual signature. We can get to the Ptr<ArpL3Protocol> through
860  // our Ptr<Ipv4> since they must both be aggregated to the same node.
861  //
862  Ptr<ArpL3Protocol> arpL3Protocol = ipv4->GetObject<ArpL3Protocol> ();
863  asciiTraceHelper.HookDefaultDropSinkWithoutContext<ArpL3Protocol> (arpL3Protocol, "Drop", theStream);
864 
865  //
866  // The drop sink for the Ipv4L3Protocol uses a different signature than
867  // the default sink, so we have to cook one up for ourselves. We can get
868  // to the Ptr<Ipv4L3Protocol> through our Ptr<Ipv4> since they must both
869  // be aggregated to the same node.
870  //
871  Ptr<Ipv4L3Protocol> ipv4L3Protocol = ipv4->GetObject<Ipv4L3Protocol> ();
872  bool result = ipv4L3Protocol->TraceConnectWithoutContext ("Drop",
873  MakeBoundCallback (&Ipv4L3ProtocolDropSinkWithoutContext, theStream));
874  NS_ASSERT_MSG (result == true, "InternetStackHelper::EnableAsciiIpv4Internal(): "
875  "Unable to connect ipv4L3Protocol \"Drop\"");
876  result = ipv4L3Protocol->TraceConnectWithoutContext ("Tx",
877  MakeBoundCallback (&Ipv4L3ProtocolTxSinkWithoutContext, theStream));
878  NS_ASSERT_MSG (result == true, "InternetStackHelper::EnableAsciiIpv4Internal(): "
879  "Unable to connect ipv4L3Protocol \"Tx\"");
880  result = ipv4L3Protocol->TraceConnectWithoutContext ("Rx",
881  MakeBoundCallback (&Ipv4L3ProtocolRxSinkWithoutContext, theStream));
882  NS_ASSERT_MSG (result == true, "InternetStackHelper::EnableAsciiIpv4Internal(): "
883  "Unable to connect ipv4L3Protocol \"Rx\"");
884  }
885 
886  g_interfaceStreamMapIpv4[std::make_pair (ipv4, interface)] = theStream;
887  return;
888  }
889 
890  //
891  // If we are provided an OutputStreamWrapper, we are expected to use it, and
892  // to provide a context. We are free to come up with our own context if we
893  // want, and use the AsciiTraceHelper Hook*WithContext functions, but for
894  // compatibility and simplicity, we just use Config::Connect and let it deal
895  // with the context.
896  //
897  // We need to associate the ipv4/interface with a stream to express interest
898  // in tracing events on that pair, however, we only hook the trace sources
899  // once to avoid multiple trace sink calls per event (connect is independent
900  // of interface).
901  //
902  if (!AsciiHooked (ipv4))
903  {
904  Ptr<Node> node = ipv4->GetObject<Node> ();
905  std::ostringstream oss;
906 
907  //
908  // For the ARP Drop, we are going to use the default trace sink provided by
909  // the ascii trace helper. There is actually no AsciiTraceHelper in sight
910  // here, but the default trace sinks are actually publicly available static
911  // functions that are always there waiting for just such a case.
912  //
913  oss << "/NodeList/" << node->GetId () << "/$ns3::ArpL3Protocol/Drop";
914  Config::Connect (oss.str (), MakeBoundCallback (&AsciiTraceHelper::DefaultDropSinkWithContext, stream));
915 
916  //
917  // This has all kinds of parameters coming with, so we have to cook up our
918  // own sink.
919  //
920  oss.str ("");
921  oss << "/NodeList/" << node->GetId () << "/$ns3::Ipv4L3Protocol/Drop";
922  Config::Connect (oss.str (), MakeBoundCallback (&Ipv4L3ProtocolDropSinkWithContext, stream));
923  oss.str ("");
924  oss << "/NodeList/" << node->GetId () << "/$ns3::Ipv4L3Protocol/Tx";
925  Config::Connect (oss.str (), MakeBoundCallback (&Ipv4L3ProtocolTxSinkWithContext, stream));
926  oss.str ("");
927  oss << "/NodeList/" << node->GetId () << "/$ns3::Ipv4L3Protocol/Rx";
928  Config::Connect (oss.str (), MakeBoundCallback (&Ipv4L3ProtocolRxSinkWithContext, stream));
929  }
930 
931  g_interfaceStreamMapIpv4[std::make_pair (ipv4, interface)] = stream;
932 }
933 
934 static void
935 Ipv6L3ProtocolDropSinkWithoutContext (
937  Ipv6Header const &header,
938  Ptr<const Packet> packet,
940  Ptr<Ipv6> ipv6,
941  uint32_t interface)
942 {
943  //
944  // Since trace sources are independent of interface, if we hook a source
945  // on a particular protocol we will get traces for all of its interfaces.
946  // We need to filter this to only report interfaces for which the user
947  // has expressed interest.
948  //
949  InterfacePairIpv6 pair = std::make_pair (ipv6, interface);
950  if (g_interfaceStreamMapIpv6.find (pair) == g_interfaceStreamMapIpv6.end ())
951  {
952  NS_LOG_INFO ("Ignoring packet to/from interface " << interface);
953  return;
954  }
955 
956  Ptr<Packet> p = packet->Copy ();
957  p->AddHeader (header);
958  *stream->GetStream () << "d " << Simulator::Now ().GetSeconds () << " " << *p << std::endl;
959 }
960 
961 static void
962 Ipv6L3ProtocolTxSinkWithoutContext (
963  Ptr<OutputStreamWrapper> stream,
964  Ptr<const Packet> packet,
965  Ptr<Ipv6> ipv6,
966  uint32_t interface)
967 {
968  InterfacePairIpv6 pair = std::make_pair (ipv6, interface);
969  if (g_interfaceStreamMapIpv6.find (pair) == g_interfaceStreamMapIpv6.end ())
970  {
971  NS_LOG_INFO ("Ignoring packet to/from interface " << interface);
972  return;
973  }
974 
975  *stream->GetStream () << "t " << Simulator::Now ().GetSeconds () << " " << *packet << std::endl;
976 }
977 
978 static void
979 Ipv6L3ProtocolRxSinkWithoutContext (
980  Ptr<OutputStreamWrapper> stream,
981  Ptr<const Packet> packet,
982  Ptr<Ipv6> ipv6,
983  uint32_t interface)
984 {
985  InterfacePairIpv6 pair = std::make_pair (ipv6, interface);
986  if (g_interfaceStreamMapIpv6.find (pair) == g_interfaceStreamMapIpv6.end ())
987  {
988  NS_LOG_INFO ("Ignoring packet to/from interface " << interface);
989  return;
990  }
991 
992  *stream->GetStream () << "r " << Simulator::Now ().GetSeconds () << " " << *packet << std::endl;
993 }
994 
995 static void
996 Ipv6L3ProtocolDropSinkWithContext (
997  Ptr<OutputStreamWrapper> stream,
998  std::string context,
999  Ipv6Header const &header,
1000  Ptr<const Packet> packet,
1002  Ptr<Ipv6> ipv6,
1003  uint32_t interface)
1004 {
1005  //
1006  // Since trace sources are independent of interface, if we hook a source
1007  // on a particular protocol we will get traces for all of its interfaces.
1008  // We need to filter this to only report interfaces for which the user
1009  // has expressed interest.
1010  //
1011  InterfacePairIpv6 pair = std::make_pair (ipv6, interface);
1012  if (g_interfaceStreamMapIpv6.find (pair) == g_interfaceStreamMapIpv6.end ())
1013  {
1014  NS_LOG_INFO ("Ignoring packet to/from interface " << interface);
1015  return;
1016  }
1017 
1018  Ptr<Packet> p = packet->Copy ();
1019  p->AddHeader (header);
1020 #ifdef INTERFACE_CONTEXT
1021  *stream->GetStream () << "d " << Simulator::Now ().GetSeconds () << " " << context << "(" << interface << ") "
1022  << *p << std::endl;
1023 #else
1024  *stream->GetStream () << "d " << Simulator::Now ().GetSeconds () << " " << context << " " << *p << std::endl;
1025 #endif
1026 }
1027 
1028 static void
1029 Ipv6L3ProtocolTxSinkWithContext (
1030  Ptr<OutputStreamWrapper> stream,
1031  std::string context,
1032  Ptr<const Packet> packet,
1033  Ptr<Ipv6> ipv6,
1034  uint32_t interface)
1035 {
1036  InterfacePairIpv6 pair = std::make_pair (ipv6, interface);
1037  if (g_interfaceStreamMapIpv6.find (pair) == g_interfaceStreamMapIpv6.end ())
1038  {
1039  NS_LOG_INFO ("Ignoring packet to/from interface " << interface);
1040  return;
1041  }
1042 
1043 #ifdef INTERFACE_CONTEXT
1044  *stream->GetStream () << "t " << Simulator::Now ().GetSeconds () << " " << context << "(" << interface << ") "
1045  << *packet << std::endl;
1046 #else
1047  *stream->GetStream () << "t " << Simulator::Now ().GetSeconds () << " " << context << " " << *packet << std::endl;
1048 #endif
1049 }
1050 
1051 static void
1052 Ipv6L3ProtocolRxSinkWithContext (
1053  Ptr<OutputStreamWrapper> stream,
1054  std::string context,
1055  Ptr<const Packet> packet,
1056  Ptr<Ipv6> ipv6,
1057  uint32_t interface)
1058 {
1059  InterfacePairIpv6 pair = std::make_pair (ipv6, interface);
1060  if (g_interfaceStreamMapIpv6.find (pair) == g_interfaceStreamMapIpv6.end ())
1061  {
1062  NS_LOG_INFO ("Ignoring packet to/from interface " << interface);
1063  return;
1064  }
1065 
1066 #ifdef INTERFACE_CONTEXT
1067  *stream->GetStream () << "r " << Simulator::Now ().GetSeconds () << " " << context << "(" << interface << ") "
1068  << *packet << std::endl;
1069 #else
1070  *stream->GetStream () << "r " << Simulator::Now ().GetSeconds () << " " << context << " " << *packet << std::endl;
1071 #endif
1072 }
1073 
1074 bool
1076 {
1077  for ( InterfaceStreamMapIpv6::const_iterator i = g_interfaceStreamMapIpv6.begin ();
1078  i != g_interfaceStreamMapIpv6.end ();
1079  ++i)
1080  {
1081  if ((*i).first.first == ipv6)
1082  {
1083  return true;
1084  }
1085  }
1086  return false;
1087 }
1088 
1089 void
1091  Ptr<OutputStreamWrapper> stream,
1092  std::string prefix,
1093  Ptr<Ipv6> ipv6,
1094  uint32_t interface,
1095  bool explicitFilename)
1096 {
1097  if (!m_ipv6Enabled)
1098  {
1099  NS_LOG_INFO ("Call to enable Ipv6 ascii tracing but Ipv6 not enabled");
1100  return;
1101  }
1102 
1103  //
1104  // Our trace sinks are going to use packet printing, so we have to
1105  // make sure that is turned on.
1106  //
1108 
1109  //
1110  // If we are not provided an OutputStreamWrapper, we are expected to create
1111  // one using the usual trace filename conventions and do a hook WithoutContext
1112  // since there will be one file per context and therefore the context would
1113  // be redundant.
1114  //
1115  if (stream == 0)
1116  {
1117  //
1118  // Set up an output stream object to deal with private ofstream copy
1119  // constructor and lifetime issues. Let the helper decide the actual
1120  // name of the file given the prefix.
1121  //
1122  // We have to create a stream and a mapping from protocol/interface to
1123  // stream irrespective of how many times we want to trace a particular
1124  // protocol.
1125  //
1126  AsciiTraceHelper asciiTraceHelper;
1127 
1128  std::string filename;
1129  if (explicitFilename)
1130  {
1131  filename = prefix;
1132  }
1133  else
1134  {
1135  filename = asciiTraceHelper.GetFilenameFromInterfacePair (prefix, ipv6, interface);
1136  }
1137 
1138  Ptr<OutputStreamWrapper> theStream = asciiTraceHelper.CreateFileStream (filename);
1139 
1140  //
1141  // However, we only hook the trace sources once to avoid multiple trace sink
1142  // calls per event (connect is independent of interface).
1143  //
1144  if (!AsciiHooked (ipv6))
1145  {
1146  //
1147  // The drop sink for the Ipv6L3Protocol uses a different signature than
1148  // the default sink, so we have to cook one up for ourselves. We can get
1149  // to the Ptr<Ipv6L3Protocol> through our Ptr<Ipv6> since they must both
1150  // be aggregated to the same node.
1151  //
1152  Ptr<Ipv6L3Protocol> ipv6L3Protocol = ipv6->GetObject<Ipv6L3Protocol> ();
1153  bool result = ipv6L3Protocol->TraceConnectWithoutContext ("Drop",
1154  MakeBoundCallback (&Ipv6L3ProtocolDropSinkWithoutContext, theStream));
1155  NS_ASSERT_MSG (result == true, "InternetStackHelper::EnableAsciiIpv6Internal(): "
1156  "Unable to connect ipv6L3Protocol \"Drop\"");
1157  result = ipv6L3Protocol->TraceConnectWithoutContext ("Tx",
1158  MakeBoundCallback (&Ipv6L3ProtocolTxSinkWithoutContext, theStream));
1159  NS_ASSERT_MSG (result == true, "InternetStackHelper::EnableAsciiIpv6Internal(): "
1160  "Unable to connect ipv6L3Protocol \"Tx\"");
1161  result = ipv6L3Protocol->TraceConnectWithoutContext ("Rx",
1162  MakeBoundCallback (&Ipv6L3ProtocolRxSinkWithoutContext, theStream));
1163  NS_ASSERT_MSG (result == true, "InternetStackHelper::EnableAsciiIpv6Internal(): "
1164  "Unable to connect ipv6L3Protocol \"Rx\"");
1165  }
1166 
1167  g_interfaceStreamMapIpv6[std::make_pair (ipv6, interface)] = theStream;
1168  return;
1169  }
1170 
1171  //
1172  // If we are provided an OutputStreamWrapper, we are expected to use it, and
1173  // to provide a context. We are free to come up with our own context if we
1174  // want, and use the AsciiTraceHelper Hook*WithContext functions, but for
1175  // compatibility and simplicity, we just use Config::Connect and let it deal
1176  // with the context.
1177  //
1178  // We need to associate the ipv4/interface with a stream to express interest
1179  // in tracing events on that pair, however, we only hook the trace sources
1180  // once to avoid multiple trace sink calls per event (connect is independent
1181  // of interface).
1182  //
1183  if (!AsciiHooked (ipv6))
1184  {
1185  Ptr<Node> node = ipv6->GetObject<Node> ();
1186  std::ostringstream oss;
1187 
1188  oss.str ("");
1189  oss << "/NodeList/" << node->GetId () << "/$ns3::Ipv6L3Protocol/Drop";
1190  Config::Connect (oss.str (), MakeBoundCallback (&Ipv6L3ProtocolDropSinkWithContext, stream));
1191  oss.str ("");
1192  oss << "/NodeList/" << node->GetId () << "/$ns3::Ipv6L3Protocol/Tx";
1193  Config::Connect (oss.str (), MakeBoundCallback (&Ipv6L3ProtocolTxSinkWithContext, stream));
1194  oss.str ("");
1195  oss << "/NodeList/" << node->GetId () << "/$ns3::Ipv6L3Protocol/Rx";
1196  Config::Connect (oss.str (), MakeBoundCallback (&Ipv6L3ProtocolRxSinkWithContext, stream));
1197  }
1198 
1199  g_interfaceStreamMapIpv6[std::make_pair (ipv6, interface)] = stream;
1200 }
1201 
1202 } // namespace ns3
void InstallCR(Ptr< Repository > repo, Ptr< Node > node) const
int64_t AssignStreams(int64_t stream)
Manage ASCII trace files for device models.
Definition: trace-helper.h:109
Packet header for IPv6.
Definition: ipv6-header.h:33
virtual void EnablePcapIpv6Internal(std::string prefix, Ptr< Ipv6 > ipv6, uint32_t interface, bool explicitFilename)
Enable pcap output the indicated Ipv6 and interface pair.
#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 HookDefaultDropSinkWithoutContext(Ptr< T > object, std::string traceName, Ptr< OutputStreamWrapper > stream)
Hook a trace source to the default drop operation trace sink that does not accept nor log a trace con...
Definition: trace-helper.h:254
Access to the IPv6 forwarding table, interfaces, and configuration.
Definition: ipv6.h:79
static const uint8_t EXT_NUMBER
Fragmentation extension number.
Hold a value for an Attribute.
Definition: attribute.h:51
Manage pcap files for device models.
Definition: trace-helper.h:38
IPv6 layer implementation.
Demultiplexes IPv6 extensions.
virtual Ipv4RoutingHelper * Copy(void) const =0
virtual constructor
static InterfaceFileMapIpv4 g_interfaceFileMapIpv4
virtual Ipv6RoutingHelper * Copy(void) const =0
virtual constructor
#define NS_ASSERT(condition)
Definition: assert.h:64
#define NS_LOG_COMPONENT_DEFINE(name)
Definition: log.h:122
void SetTypeId(TypeId tid)
aggregate IP/TCP/UDP functionality to existing Nodes.
Iterator End(void) const
Get an iterator which indicates past-the-last Node in the container.
#define NS_LOG_INFO(msg)
Definition: log.h:264
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. ...
void Connect(std::string path, const CallbackBase &cb)
Definition: config.cc:728
static InterfaceStreamMapIpv4 g_interfaceStreamMapIpv4
#define NS_FATAL_ERROR(msg)
fatal error handling
Definition: fatal-error.h:72
static void CreateAndAggregateObjectFromTypeId(Ptr< Node > node, const std::string typeId)
DropReason
Reason why a packet has been dropped.
Packet header for IPv4.
Definition: ipv4-header.h:31
double GetSeconds(void) const
Definition: nstime.h:262
virtual void EnablePcapIpv4Internal(std::string prefix, Ptr< Ipv4 > ipv4, uint32_t interface, bool explicitFilename)
Enable pcap output the indicated Ipv4 and interface pair.
static void EnablePrinting(void)
Definition: packet.cc:575
Ptr< Object > Create(void) const
void SetIpv4StackInstall(bool enable)
Enable/disable IPv4 stack install.
static InterfaceFileMapIpv6 g_interfaceFileMapIpv6
A factory to create ns3::Ipv6RoutingProtocol objects.
bool PcapHooked(Ptr< Ipv4 > ipv4)
Callback< R > MakeCallback(R(T::*memPtr)(void), OBJ objPtr)
Definition: callback.h:502
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...
void AggregateObject(Ptr< Object > other)
Definition: object.cc:242
bool m_ipv6Enabled
IPv6 install state (enabled/disabled) ?
a factory to create ns3::Ipv4RoutingProtocol objects
Access to the Ipv4 forwarding table, interfaces, and configuration.
Definition: ipv4.h:75
Ptr< Packet > Copy(void) const
Definition: packet.cc:131
virtual Ptr< Ipv6RoutingProtocol > Create(Ptr< Node > node) const =0
bool TraceConnectWithoutContext(std::string name, const CallbackBase &cb)
Definition: object-base.cc:268
Implement the Ipv4 layer.
keep track of a set of node pointers.
Helper class that adds ns3::Ipv6StaticRouting objects.
Iterator Begin(void) const
Get an iterator which refers to the first Node in the container.
void SetTcp(std::string tid)
set the Tcp stack which will not need any other parameter.
void Install(std::string nodeName) const
void Set(std::string name, const AttributeValue &value)
static Time Now(void)
Definition: simulator.cc:179
void Add(const Ipv4RoutingHelper &routing, int16_t priority)
An interface aggregated to a node to provide global routing info.
#define NS_ASSERT_MSG(condition, message)
Definition: assert.h:86
static NodeContainer GetGlobal(void)
Create a NodeContainer that contains a list of all nodes created through NodeContainer::Create() and ...
void Add(const Ipv6RoutingHelper &routing, int16_t priority)
instantiate subclasses of ns3::Object.
const Ipv6RoutingHelper * m_routingv6
IPv6 routing helper.
int64_t AssignStreams(NodeContainer c, int64_t stream)
uint32_t GetId(void) const
Definition: node.cc:105
Helper class that adds ns3::Ipv4StaticRouting objects.
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 Ptr< Ipv4RoutingProtocol > Create(Ptr< Node > node) const =0
An implementation of the ARP protocol.
Helper class that adds ns3::Ipv4GlobalRouting objects.
Helper class that adds ns3::Ipv6ListRouting objects.
Helper class that adds ns3::Ipv4ListRouting objects.
bool AsciiHooked(Ptr< Ipv4 > ipv4)
virtual void EnableAsciiIpv6Internal(Ptr< OutputStreamWrapper > stream, std::string prefix, Ptr< Ipv6 > ipv6, uint32_t interface, bool explicitFilename)
Enable ascii trace output on the indicated Ipv6 and interface pair.
a base class which provides memory management and object aggregation
Definition: object.h:63
Ptr< T > GetObject(void) const
Definition: object.h:332
static InterfaceStreamMapIpv6 g_interfaceStreamMapIpv6
void SetRoutingHelper(const Ipv4RoutingHelper &routing)
std::ostream * GetStream(void)
void AddHeader(const Header &header)
Definition: packet.cc:270
bool m_ipv4Enabled
IPv4 install state (enabled/disabled) ?
virtual void EnableAsciiIpv4Internal(Ptr< OutputStreamWrapper > stream, std::string prefix, Ptr< Ipv4 > ipv4, uint32_t interface, bool explicitFilename)
Enable ascii trace output on the indicated Ipv4 and interface pair.
void SetIpv6StackInstall(bool enable)
Enable/disable IPv6 stack install.
DropReason
Reason why a packet has been dropped.