tracers: Extending helper API in tracers

Now all tracers can be installed on individual nodes.

It is also possible to specify "-" as a file name, leading to tracing on
standard output.

Refs #1007 (http://redmine.named-data.net)
diff --git a/utils/tracers/ipv4-l3-tracer.cc b/utils/tracers/ipv4-l3-tracer.cc
index 8e36d26..384d177 100644
--- a/utils/tracers/ipv4-l3-tracer.cc
+++ b/utils/tracers/ipv4-l3-tracer.cc
@@ -23,6 +23,7 @@
 #include "ns3/config.h"
 #include "ns3/names.h"
 #include "ns3/callback.h"
+#include "ns3/ipv4-l3-protocol.h"
 
 #include <boost/lexical_cast.hpp>
 
@@ -47,12 +48,10 @@
 void
 Ipv4L3Tracer::Connect ()
 {
-  Config::Connect ("/NodeList/"+m_node+"/$ns3::Ipv4L3Protocol/Tx",
-                   MakeCallback (&Ipv4L3Tracer::Tx, this));
-  Config::Connect ("/NodeList/"+m_node+"/$ns3::Ipv4L3Protocol/Rx",
-                   MakeCallback (&Ipv4L3Tracer::Rx, this));
-  Config::Connect ("/NodeList/"+m_node+"/$ns3::Ipv4L3Protocol/Drop",
-                   MakeCallback (&Ipv4L3Tracer::Drop, this));
+  Ptr<Ipv4L3Protocol> ip = m_nodePtr->GetObject<Ipv4L3Protocol> ();
+  ip->TraceConnectWithoutContext ("Tx",   MakeCallback (&Ipv4L3Tracer::Tx, this));
+  ip->TraceConnectWithoutContext ("Rx",   MakeCallback (&Ipv4L3Tracer::Rx, this));
+  ip->TraceConnectWithoutContext ("Drop", MakeCallback (&Ipv4L3Tracer::Drop, this));
 }
 
 } // namespace ns3
diff --git a/utils/tracers/ipv4-l3-tracer.h b/utils/tracers/ipv4-l3-tracer.h
index e5f3c74..2e08054 100644
--- a/utils/tracers/ipv4-l3-tracer.h
+++ b/utils/tracers/ipv4-l3-tracer.h
@@ -45,16 +45,13 @@
   Print (std::ostream &os) const = 0;
   
   virtual void
-  Rx  (std::string context,
-       Ptr<const Packet>, Ptr<Ipv4>,  uint32_t) = 0;
+  Rx  (Ptr<const Packet>, Ptr<Ipv4>,  uint32_t) = 0;
 
   virtual void
-  Tx   (std::string context,
-        Ptr<const Packet>, Ptr<Ipv4>,  uint32_t) = 0;
+  Tx   (Ptr<const Packet>, Ptr<Ipv4>,  uint32_t) = 0;
 
   virtual void
-  Drop (std::string context,
-        const Ipv4Header &, Ptr<const Packet>, Ipv4L3Protocol::DropReason, Ptr<Ipv4>, uint32_t) = 0;
+  Drop (const Ipv4Header &, Ptr<const Packet>, Ipv4L3Protocol::DropReason, Ptr<Ipv4>, uint32_t) = 0;
 
 protected:
   std::string m_node;
diff --git a/utils/tracers/ipv4-rate-l3-tracer.cc b/utils/tracers/ipv4-rate-l3-tracer.cc
index 280301d..0e2db8d 100644
--- a/utils/tracers/ipv4-rate-l3-tracer.cc
+++ b/utils/tracers/ipv4-rate-l3-tracer.cc
@@ -39,24 +39,37 @@
 
 namespace ns3 {
 
+template<class T>
+static inline void
+NullDeleter (T *ptr)
+{
+}
+
 boost::tuple< boost::shared_ptr<std::ostream>, std::list<Ptr<Ipv4RateL3Tracer> > >
 Ipv4RateL3Tracer::InstallAll (const std::string &file, Time averagingPeriod/* = Seconds (0.5)*/)
 {
   std::list<Ptr<Ipv4RateL3Tracer> > tracers;
-  boost::shared_ptr<std::ofstream> outputStream (new std::ofstream ());
-  outputStream->open (file.c_str (), std::ios_base::out | std::ios_base::trunc);
+  boost::shared_ptr<std::ostream> outputStream;
+  if (file != "-")
+    {
+      boost::shared_ptr<std::ofstream> os (new std::ofstream ());
+      os->open (file.c_str (), std::ios_base::out | std::ios_base::trunc);
 
-  if (!outputStream->is_open ())
-    return boost::make_tuple (outputStream, tracers);
+      if (!os->is_open ())
+        return boost::make_tuple (outputStream, tracers);
+
+      outputStream = os;
+    }
+  else
+    {
+      outputStream = boost::shared_ptr<std::ostream> (&std::cout, NullDeleter<std::ostream>);
+    }
 
   for (NodeList::Iterator node = NodeList::Begin ();
        node != NodeList::End ();
        node++)
     {
-      NS_LOG_DEBUG ("Node: " << lexical_cast<string> ((*node)->GetId ()));
-
-      Ptr<Ipv4RateL3Tracer> trace = Create<Ipv4RateL3Tracer> (outputStream, *node);
-      trace->SetAveragingPeriod (averagingPeriod);
+      Ptr<Ipv4RateL3Tracer> trace = Install (*node, outputStream, averagingPeriod);
       tracers.push_back (trace);
     }
 
@@ -70,6 +83,97 @@
   return boost::make_tuple (outputStream, tracers);
 }
 
+boost::tuple< boost::shared_ptr<std::ostream>, std::list<Ptr<Ipv4RateL3Tracer> > >
+Ipv4RateL3Tracer::Install (const NodeContainer &nodes, const std::string &file, Time averagingPeriod/* = Seconds (0.5)*/)
+{
+  using namespace boost;
+  using namespace std;
+
+  std::list<Ptr<Ipv4RateL3Tracer> > tracers;
+  boost::shared_ptr<std::ostream> outputStream;
+  if (file != "-")
+    {
+      boost::shared_ptr<std::ofstream> os (new std::ofstream ());
+      os->open (file.c_str (), std::ios_base::out | std::ios_base::trunc);
+
+      if (!os->is_open ())
+        return boost::make_tuple (outputStream, tracers);
+
+      outputStream = os;
+    }
+  else
+    {
+      outputStream = boost::shared_ptr<std::ostream> (&std::cout, NullDeleter<std::ostream>);
+    }
+
+  for (NodeContainer::Iterator node = nodes.Begin ();
+       node != nodes.End ();
+       node++)
+    {
+      Ptr<Ipv4RateL3Tracer> trace = Install (*node, outputStream, averagingPeriod);
+      tracers.push_back (trace);
+    }
+
+  if (tracers.size () > 0)
+    {
+      // *m_l3RateTrace << "# "; // not necessary for R's read.table
+      tracers.front ()->PrintHeader (*outputStream);
+      *outputStream << "\n";
+    }
+
+  return boost::make_tuple (outputStream, tracers);
+}
+
+boost::tuple< boost::shared_ptr<std::ostream>, std::list<Ptr<Ipv4RateL3Tracer> > >
+Ipv4RateL3Tracer::Install (Ptr<Node> node, const std::string &file, Time averagingPeriod/* = Seconds (0.5)*/)
+{
+  using namespace boost;
+  using namespace std;
+
+  std::list<Ptr<Ipv4RateL3Tracer> > tracers;
+  boost::shared_ptr<std::ostream> outputStream;
+  if (file != "-")
+    {
+      boost::shared_ptr<std::ofstream> os (new std::ofstream ());
+      os->open (file.c_str (), std::ios_base::out | std::ios_base::trunc);
+
+      if (!os->is_open ())
+        return boost::make_tuple (outputStream, tracers);
+
+      outputStream = os;
+    }
+  else
+    {
+      outputStream = boost::shared_ptr<std::ostream> (&std::cout, NullDeleter<std::ostream>);
+    }
+
+  Ptr<Ipv4RateL3Tracer> trace = Install (node, outputStream, averagingPeriod);
+  tracers.push_back (trace);
+
+  if (tracers.size () > 0)
+    {
+      // *m_l3RateTrace << "# "; // not necessary for R's read.table
+      tracers.front ()->PrintHeader (*outputStream);
+      *outputStream << "\n";
+    }
+
+  return boost::make_tuple (outputStream, tracers);
+}
+
+
+Ptr<Ipv4RateL3Tracer>
+Ipv4RateL3Tracer::Install (Ptr<Node> node,
+                           boost::shared_ptr<std::ostream> outputStream,
+                           Time averagingPeriod/* = Seconds (0.5)*/)
+{
+  NS_LOG_DEBUG ("Node: " << node->GetId ());
+
+  Ptr<Ipv4RateL3Tracer> trace = Create<Ipv4RateL3Tracer> (outputStream, node);
+  trace->SetAveragingPeriod (averagingPeriod);
+
+  return trace;
+}
+
 
 Ipv4RateL3Tracer::Ipv4RateL3Tracer (boost::shared_ptr<std::ostream> os, Ptr<Node> node)
   : Ipv4L3Tracer (node)
@@ -157,24 +261,21 @@
 }
 
 void
-Ipv4RateL3Tracer::Rx  (std::string context,
-                       Ptr<const Packet> packet, Ptr<Ipv4> ipv4,  uint32_t iface)
+Ipv4RateL3Tracer::Rx  (Ptr<const Packet> packet, Ptr<Ipv4> ipv4,  uint32_t iface)
 {
   m_stats[iface].get<0> ().m_in ++;
   m_stats[iface].get<1> ().m_in += packet->GetSize ();
 }
 
 void
-Ipv4RateL3Tracer::Tx   (std::string context,
-                        Ptr<const Packet> packet, Ptr<Ipv4> ipv4,  uint32_t iface)
+Ipv4RateL3Tracer::Tx   (Ptr<const Packet> packet, Ptr<Ipv4> ipv4,  uint32_t iface)
 {
   m_stats[iface].get<0> ().m_out ++;
   m_stats[iface].get<1> ().m_out += packet->GetSize ();
 }
 
 void
-Ipv4RateL3Tracer::Drop (std::string context,
-                        const Ipv4Header &header, Ptr<const Packet> packet, Ipv4L3Protocol::DropReason, Ptr<Ipv4> ipv4, uint32_t iface)
+Ipv4RateL3Tracer::Drop (const Ipv4Header &header, Ptr<const Packet> packet, Ipv4L3Protocol::DropReason, Ptr<Ipv4> ipv4, uint32_t iface)
 {
   m_stats[iface].get<0> ().m_drop ++;
   m_stats[iface].get<1> ().m_drop += packet->GetSize ();
diff --git a/utils/tracers/ipv4-rate-l3-tracer.h b/utils/tracers/ipv4-rate-l3-tracer.h
index e624c3d..d4be0a9 100644
--- a/utils/tracers/ipv4-rate-l3-tracer.h
+++ b/utils/tracers/ipv4-rate-l3-tracer.h
@@ -25,6 +25,7 @@
 
 #include "ns3/nstime.h"
 #include "ns3/event-id.h"
+#include "ns3/node-container.h"
 
 #include <boost/tuple/tuple.hpp>
 #include <boost/shared_ptr.hpp>
@@ -59,6 +60,47 @@
   static boost::tuple< boost::shared_ptr<std::ostream>, std::list<Ptr<Ipv4RateL3Tracer> > >
   InstallAll (const std::string &file, Time averagingPeriod = Seconds (0.5));
 
+  /**
+   * @brief Helper method to install tracers on the selected simulation nodes
+   *
+   * @param nodes Nodes on which to install tracer
+   * @param file File to which traces will be written.  If filename is -, then std::out is used
+   * @param averagingPeriod How often data will be written into the trace file (default, every half second)
+   *
+   * @returns a tuple of reference to output stream and list of tracers. !!! Attention !!! This tuple needs to be preserved
+   *          for the lifetime of simulation, otherwise SEGFAULTs are inevitable
+   *
+   */
+  static boost::tuple< boost::shared_ptr<std::ostream>, std::list<Ptr<Ipv4RateL3Tracer> > >
+  Install (const NodeContainer &nodes, const std::string &file, Time averagingPeriod = Seconds (0.5));
+
+  /**
+   * @brief Helper method to install tracers on a specific simulation node
+   *
+   * @param nodes Nodes on which to install tracer
+   * @param file File to which traces will be written.  If filename is -, then std::out is used
+   * @param averagingPeriod How often data will be written into the trace file (default, every half second)
+   *
+   * @returns a tuple of reference to output stream and list of tracers. !!! Attention !!! This tuple needs to be preserved
+   *          for the lifetime of simulation, otherwise SEGFAULTs are inevitable
+   *
+   */
+  static boost::tuple< boost::shared_ptr<std::ostream>, std::list<Ptr<Ipv4RateL3Tracer> > >
+  Install (Ptr<Node> node, const std::string &file, Time averagingPeriod = Seconds (0.5));
+
+  /**
+   * @brief Helper method to install tracers on a specific simulation node
+   *
+   * @param nodes Nodes on which to install tracer
+   * @param outputStream Smart pointer to a stream
+   * @param averagingPeriod How often data will be written into the trace file (default, every half second)
+   *
+   * @returns a tuple of reference to output stream and list of tracers. !!! Attention !!! This tuple needs to be preserved
+   *          for the lifetime of simulation, otherwise SEGFAULTs are inevitable
+   */
+  static Ptr<Ipv4RateL3Tracer>
+  Install (Ptr<Node> node, boost::shared_ptr<std::ostream> outputStream, Time averagingPeriod = Seconds (0.5));
+  
   void
   SetAveragingPeriod (const Time &period);
 
@@ -69,16 +111,13 @@
   Print (std::ostream &os) const;
 
   virtual void
-  Rx  (std::string context,
-       Ptr<const Packet>, Ptr<Ipv4>,  uint32_t);
+  Rx  (Ptr<const Packet>, Ptr<Ipv4>,  uint32_t);
 
   virtual void
-  Tx   (std::string context,
-        Ptr<const Packet>, Ptr<Ipv4>,  uint32_t);
+  Tx   (Ptr<const Packet>, Ptr<Ipv4>,  uint32_t);
 
   virtual void
-  Drop (std::string context,
-        const Ipv4Header &, Ptr<const Packet>, Ipv4L3Protocol::DropReason, Ptr<Ipv4>, uint32_t);
+  Drop (const Ipv4Header &, Ptr<const Packet>, Ipv4L3Protocol::DropReason, Ptr<Ipv4>, uint32_t);
 
 private:
   void
diff --git a/utils/tracers/ndn-app-delay-tracer.cc b/utils/tracers/ndn-app-delay-tracer.cc
index d659247..b48d744 100644
--- a/utils/tracers/ndn-app-delay-tracer.cc
+++ b/utils/tracers/ndn-app-delay-tracer.cc
@@ -44,6 +44,11 @@
 namespace ns3 {
 namespace ndn {
 
+template<class T>
+static inline void
+NullDeleter (T *ptr)
+{
+}
 
 boost::tuple< boost::shared_ptr<std::ostream>, std::list<Ptr<AppDelayTracer> > >
 AppDelayTracer::InstallAll (const std::string &file)
@@ -52,19 +57,27 @@
   using namespace std;
 
   std::list<Ptr<AppDelayTracer> > tracers;
-  boost::shared_ptr<std::ofstream> outputStream = make_shared<std::ofstream> ();
+  boost::shared_ptr<std::ostream> outputStream;
+  if (file != "-")
+    {
+      boost::shared_ptr<std::ofstream> os (new std::ofstream ());
+      os->open (file.c_str (), std::ios_base::out | std::ios_base::trunc);
 
-  outputStream->open (file.c_str (), std::ios_base::out | std::ios_base::trunc);
-  if (!outputStream->is_open ())
-    return boost::make_tuple (outputStream, tracers);
+      if (!os->is_open ())
+        return boost::make_tuple (outputStream, tracers);
+
+      outputStream = os;
+    }
+  else
+    {
+      outputStream = boost::shared_ptr<std::ostream> (&std::cout, NullDeleter<std::ostream>);
+    }
 
   for (NodeList::Iterator node = NodeList::Begin ();
        node != NodeList::End ();
        node++)
     {
-      NS_LOG_DEBUG ("Node: " << (*node)->GetId ());
-
-      Ptr<AppDelayTracer> trace = Create<AppDelayTracer> (outputStream, *node);
+      Ptr<AppDelayTracer> trace = Install (*node, outputStream);
       tracers.push_back (trace);
     }
 
@@ -78,6 +91,95 @@
   return boost::make_tuple (outputStream, tracers);
 }
 
+boost::tuple< boost::shared_ptr<std::ostream>, std::list<Ptr<AppDelayTracer> > >
+AppDelayTracer::Install (const NodeContainer &nodes, const std::string &file)
+{
+  using namespace boost;
+  using namespace std;
+
+  std::list<Ptr<AppDelayTracer> > tracers;
+  boost::shared_ptr<std::ostream> outputStream;
+  if (file != "-")
+    {
+      boost::shared_ptr<std::ofstream> os (new std::ofstream ());
+      os->open (file.c_str (), std::ios_base::out | std::ios_base::trunc);
+
+      if (!os->is_open ())
+        return boost::make_tuple (outputStream, tracers);
+
+      outputStream = os;
+    }
+  else
+    {
+      outputStream = boost::shared_ptr<std::ostream> (&std::cout, NullDeleter<std::ostream>);
+    }
+
+  for (NodeContainer::Iterator node = nodes.Begin ();
+       node != nodes.End ();
+       node++)
+    {
+      Ptr<AppDelayTracer> trace = Install (*node, outputStream);
+      tracers.push_back (trace);
+    }
+
+  if (tracers.size () > 0)
+    {
+      // *m_l3RateTrace << "# "; // not necessary for R's read.table
+      tracers.front ()->PrintHeader (*outputStream);
+      *outputStream << "\n";
+    }
+
+  return boost::make_tuple (outputStream, tracers);
+}
+
+boost::tuple< boost::shared_ptr<std::ostream>, std::list<Ptr<AppDelayTracer> > >
+AppDelayTracer::Install (Ptr<Node> node, const std::string &file)
+{
+  using namespace boost;
+  using namespace std;
+
+  std::list<Ptr<AppDelayTracer> > tracers;
+  boost::shared_ptr<std::ostream> outputStream;
+  if (file != "-")
+    {
+      boost::shared_ptr<std::ofstream> os (new std::ofstream ());
+      os->open (file.c_str (), std::ios_base::out | std::ios_base::trunc);
+
+      if (!os->is_open ())
+        return boost::make_tuple (outputStream, tracers);
+
+      outputStream = os;
+    }
+  else
+    {
+      outputStream = boost::shared_ptr<std::ostream> (&std::cout, NullDeleter<std::ostream>);
+    }
+
+  Ptr<AppDelayTracer> trace = Install (node, outputStream);
+  tracers.push_back (trace);
+
+  if (tracers.size () > 0)
+    {
+      // *m_l3RateTrace << "# "; // not necessary for R's read.table
+      tracers.front ()->PrintHeader (*outputStream);
+      *outputStream << "\n";
+    }
+
+  return boost::make_tuple (outputStream, tracers);
+}
+
+
+Ptr<AppDelayTracer>
+AppDelayTracer::Install (Ptr<Node> node,
+                         boost::shared_ptr<std::ostream> outputStream)
+{
+  NS_LOG_DEBUG ("Node: " << node->GetId ());
+
+  Ptr<AppDelayTracer> trace = Create<AppDelayTracer> (outputStream, node);
+
+  return trace;
+}
+
 //////////////////////////////////////////////////////////////////////////////
 //////////////////////////////////////////////////////////////////////////////
 //////////////////////////////////////////////////////////////////////////////
diff --git a/utils/tracers/ndn-app-delay-tracer.h b/utils/tracers/ndn-app-delay-tracer.h
index c7a433c..7312225 100644
--- a/utils/tracers/ndn-app-delay-tracer.h
+++ b/utils/tracers/ndn-app-delay-tracer.h
@@ -25,6 +25,7 @@
 #include "ns3/simple-ref-count.h"
 #include <ns3/nstime.h>
 #include <ns3/event-id.h>
+#include <ns3/node-container.h>
 
 #include <boost/tuple/tuple.hpp>
 #include <boost/shared_ptr.hpp>
@@ -49,8 +50,7 @@
   /**
    * @brief Helper method to install tracers on all simulation nodes
    *
-   * @param file File to which traces will be written
-   * @param averagingPeriod How often data will be written into the trace file (default, every half second)
+   * @param file File to which traces will be written.  If filename is -, then std::out is used
    *
    * @returns a tuple of reference to output stream and list of tracers. !!! Attention !!! This tuple needs to be preserved
    *          for the lifetime of simulation, otherwise SEGFAULTs are inevitable
@@ -60,6 +60,46 @@
   InstallAll (const std::string &file);
 
   /**
+   * @brief Helper method to install tracers on the selected simulation nodes
+   *
+   * @param nodes Nodes on which to install tracer
+   * @param file File to which traces will be written.  If filename is -, then std::out is used
+   *
+   * @returns a tuple of reference to output stream and list of tracers. !!! Attention !!! This tuple needs to be preserved
+   *          for the lifetime of simulation, otherwise SEGFAULTs are inevitable
+   *
+   */
+  static boost::tuple< boost::shared_ptr<std::ostream>, std::list<Ptr<AppDelayTracer> > >
+  Install (const NodeContainer &nodes, const std::string &file);
+
+  /**
+   * @brief Helper method to install tracers on a specific simulation node
+   *
+   * @param nodes Nodes on which to install tracer
+   * @param file File to which traces will be written.  If filename is -, then std::out is used
+   * @param averagingPeriod How often data will be written into the trace file (default, every half second)
+   *
+   * @returns a tuple of reference to output stream and list of tracers. !!! Attention !!! This tuple needs to be preserved
+   *          for the lifetime of simulation, otherwise SEGFAULTs are inevitable
+   *
+   */
+  static boost::tuple< boost::shared_ptr<std::ostream>, std::list<Ptr<AppDelayTracer> > >
+  Install (Ptr<Node> node, const std::string &file);
+
+  /**
+   * @brief Helper method to install tracers on a specific simulation node
+   *
+   * @param nodes Nodes on which to install tracer
+   * @param outputStream Smart pointer to a stream
+   * @param averagingPeriod How often data will be written into the trace file (default, every half second)
+   *
+   * @returns a tuple of reference to output stream and list of tracers. !!! Attention !!! This tuple needs to be preserved
+   *          for the lifetime of simulation, otherwise SEGFAULTs are inevitable
+   */
+  static Ptr<AppDelayTracer>
+  Install (Ptr<Node> node, boost::shared_ptr<std::ostream> outputStream);
+  
+  /**
    * @brief Trace constructor that attaches to all applications on the node using node's pointer
    * @param os    reference to the output stream
    * @param node  pointer to the node
diff --git a/utils/tracers/ndn-cs-tracer.cc b/utils/tracers/ndn-cs-tracer.cc
index 80afe64..10b7448 100644
--- a/utils/tracers/ndn-cs-tracer.cc
+++ b/utils/tracers/ndn-cs-tracer.cc
@@ -44,6 +44,11 @@
 namespace ns3 {
 namespace ndn {
 
+template<class T>
+static inline void
+NullDeleter (T *ptr)
+{
+}
 
 boost::tuple< boost::shared_ptr<std::ostream>, std::list<Ptr<CsTracer> > >
 CsTracer::InstallAll (const std::string &file, Time averagingPeriod/* = Seconds (0.5)*/)
@@ -52,20 +57,27 @@
   using namespace std;
   
   std::list<Ptr<CsTracer> > tracers;
-  boost::shared_ptr<std::ofstream> outputStream (new std::ofstream ());
-  outputStream->open (file.c_str (), std::ios_base::out | std::ios_base::trunc);
+  boost::shared_ptr<std::ostream> outputStream;
+  if (file != "-")
+    {
+      boost::shared_ptr<std::ofstream> os (new std::ofstream ());
+      os->open (file.c_str (), std::ios_base::out | std::ios_base::trunc);
 
-  if (!outputStream->is_open ())
-    return boost::make_tuple (outputStream, tracers);
+      if (!os->is_open ())
+        return boost::make_tuple (outputStream, tracers);
+
+      outputStream = os;
+    }
+  else
+    {
+      outputStream = boost::shared_ptr<std::ostream> (&std::cout, NullDeleter<std::ostream>);
+    }
 
   for (NodeList::Iterator node = NodeList::Begin ();
        node != NodeList::End ();
        node++)
     {
-      NS_LOG_DEBUG ("Node: " << (*node)->GetId ());
-
-      Ptr<CsTracer> trace = Create<CsTracer> (outputStream, *node);
-      trace->SetAveragingPeriod (averagingPeriod);
+      Ptr<CsTracer> trace = Install (*node, outputStream, averagingPeriod);
       tracers.push_back (trace);
     }
 
@@ -79,6 +91,97 @@
   return boost::make_tuple (outputStream, tracers);
 }
 
+boost::tuple< boost::shared_ptr<std::ostream>, std::list<Ptr<CsTracer> > >
+CsTracer::Install (const NodeContainer &nodes, const std::string &file, Time averagingPeriod/* = Seconds (0.5)*/)
+{
+  using namespace boost;
+  using namespace std;
+
+  std::list<Ptr<CsTracer> > tracers;
+  boost::shared_ptr<std::ostream> outputStream;
+  if (file != "-")
+    {
+      boost::shared_ptr<std::ofstream> os (new std::ofstream ());
+      os->open (file.c_str (), std::ios_base::out | std::ios_base::trunc);
+
+      if (!os->is_open ())
+        return boost::make_tuple (outputStream, tracers);
+
+      outputStream = os;
+    }
+  else
+    {
+      outputStream = boost::shared_ptr<std::ostream> (&std::cout, NullDeleter<std::ostream>);
+    }
+
+  for (NodeContainer::Iterator node = nodes.Begin ();
+       node != nodes.End ();
+       node++)
+    {
+      Ptr<CsTracer> trace = Install (*node, outputStream, averagingPeriod);
+      tracers.push_back (trace);
+    }
+
+  if (tracers.size () > 0)
+    {
+      // *m_l3RateTrace << "# "; // not necessary for R's read.table
+      tracers.front ()->PrintHeader (*outputStream);
+      *outputStream << "\n";
+    }
+
+  return boost::make_tuple (outputStream, tracers);
+}
+
+boost::tuple< boost::shared_ptr<std::ostream>, std::list<Ptr<CsTracer> > >
+CsTracer::Install (Ptr<Node> node, const std::string &file, Time averagingPeriod/* = Seconds (0.5)*/)
+{
+  using namespace boost;
+  using namespace std;
+
+  std::list<Ptr<CsTracer> > tracers;
+  boost::shared_ptr<std::ostream> outputStream;
+  if (file != "-")
+    {
+      boost::shared_ptr<std::ofstream> os (new std::ofstream ());
+      os->open (file.c_str (), std::ios_base::out | std::ios_base::trunc);
+
+      if (!os->is_open ())
+        return boost::make_tuple (outputStream, tracers);
+
+      outputStream = os;
+    }
+  else
+    {
+      outputStream = boost::shared_ptr<std::ostream> (&std::cout, NullDeleter<std::ostream>);
+    }
+
+  Ptr<CsTracer> trace = Install (node, outputStream, averagingPeriod);
+  tracers.push_back (trace);
+
+  if (tracers.size () > 0)
+    {
+      // *m_l3RateTrace << "# "; // not necessary for R's read.table
+      tracers.front ()->PrintHeader (*outputStream);
+      *outputStream << "\n";
+    }
+
+  return boost::make_tuple (outputStream, tracers);
+}
+
+
+Ptr<CsTracer>
+CsTracer::Install (Ptr<Node> node,
+                       boost::shared_ptr<std::ostream> outputStream,
+                       Time averagingPeriod/* = Seconds (0.5)*/)
+{
+  NS_LOG_DEBUG ("Node: " << node->GetId ());
+
+  Ptr<CsTracer> trace = Create<CsTracer> (outputStream, node);
+  trace->SetAveragingPeriod (averagingPeriod);
+
+  return trace;
+}
+
 //////////////////////////////////////////////////////////////////////////////
 //////////////////////////////////////////////////////////////////////////////
 //////////////////////////////////////////////////////////////////////////////
diff --git a/utils/tracers/ndn-cs-tracer.h b/utils/tracers/ndn-cs-tracer.h
index eb6f0b3..87c290e 100644
--- a/utils/tracers/ndn-cs-tracer.h
+++ b/utils/tracers/ndn-cs-tracer.h
@@ -26,6 +26,7 @@
 #include "ns3/simple-ref-count.h"
 #include <ns3/nstime.h>
 #include <ns3/event-id.h>
+#include <ns3/node-container.h>
 
 #include <boost/tuple/tuple.hpp>
 #include <boost/shared_ptr.hpp>
@@ -70,7 +71,7 @@
   /**
    * @brief Helper method to install tracers on all simulation nodes
    *
-   * @param file File to which traces will be written
+   * @param file File to which traces will be written.  If filename is -, then std::out is used
    * @param averagingPeriod How often data will be written into the trace file (default, every half second)
    *
    * @returns a tuple of reference to output stream and list of tracers. !!! Attention !!! This tuple needs to be preserved
@@ -81,6 +82,47 @@
   InstallAll (const std::string &file, Time averagingPeriod = Seconds (0.5));
 
   /**
+   * @brief Helper method to install tracers on the selected simulation nodes
+   *
+   * @param nodes Nodes on which to install tracer
+   * @param file File to which traces will be written.  If filename is -, then std::out is used
+   * @param averagingPeriod How often data will be written into the trace file (default, every half second)
+   *
+   * @returns a tuple of reference to output stream and list of tracers. !!! Attention !!! This tuple needs to be preserved
+   *          for the lifetime of simulation, otherwise SEGFAULTs are inevitable
+   *
+   */
+  static boost::tuple< boost::shared_ptr<std::ostream>, std::list<Ptr<CsTracer> > >
+  Install (const NodeContainer &nodes, const std::string &file, Time averagingPeriod = Seconds (0.5));
+
+  /**
+   * @brief Helper method to install tracers on a specific simulation node
+   *
+   * @param nodes Nodes on which to install tracer
+   * @param file File to which traces will be written.  If filename is -, then std::out is used
+   * @param averagingPeriod How often data will be written into the trace file (default, every half second)
+   *
+   * @returns a tuple of reference to output stream and list of tracers. !!! Attention !!! This tuple needs to be preserved
+   *          for the lifetime of simulation, otherwise SEGFAULTs are inevitable
+   *
+   */
+  static boost::tuple< boost::shared_ptr<std::ostream>, std::list<Ptr<CsTracer> > >
+  Install (Ptr<Node> node, const std::string &file, Time averagingPeriod = Seconds (0.5));
+
+  /**
+   * @brief Helper method to install tracers on a specific simulation node
+   *
+   * @param nodes Nodes on which to install tracer
+   * @param outputStream Smart pointer to a stream
+   * @param averagingPeriod How often data will be written into the trace file (default, every half second)
+   *
+   * @returns a tuple of reference to output stream and list of tracers. !!! Attention !!! This tuple needs to be preserved
+   *          for the lifetime of simulation, otherwise SEGFAULTs are inevitable
+   */
+  static Ptr<CsTracer>
+  Install (Ptr<Node> node, boost::shared_ptr<std::ostream> outputStream, Time averagingPeriod = Seconds (0.5));
+  
+  /**
    * @brief Trace constructor that attaches to the node using node pointer
    * @param os    reference to the output stream
    * @param node  pointer to the node
diff --git a/utils/tracers/ndn-l3-aggregate-tracer.cc b/utils/tracers/ndn-l3-aggregate-tracer.cc
index 646c516..5ece34c 100644
--- a/utils/tracers/ndn-l3-aggregate-tracer.cc
+++ b/utils/tracers/ndn-l3-aggregate-tracer.cc
@@ -41,6 +41,12 @@
 namespace ns3 {
 namespace ndn {
 
+template<class T>
+static inline void
+NullDeleter (T *ptr)
+{
+}
+
 boost::tuple< boost::shared_ptr<std::ostream>, std::list<Ptr<L3AggregateTracer> > >
 L3AggregateTracer::InstallAll (const std::string &file, Time averagingPeriod/* = Seconds (0.5)*/)
 {
@@ -48,11 +54,21 @@
   using namespace std;
 
   std::list<Ptr<L3AggregateTracer> > tracers;
-  boost::shared_ptr<std::ofstream> outputStream (new std::ofstream ());
-  outputStream->open (file.c_str (), std::ios_base::out | std::ios_base::trunc);
+  boost::shared_ptr<std::ostream> outputStream;
+  if (file != "-")
+    {
+      boost::shared_ptr<std::ofstream> os (new std::ofstream ());
+      os->open (file.c_str (), std::ios_base::out | std::ios_base::trunc);
 
-  if (!outputStream->is_open ())
-    return boost::make_tuple (outputStream, tracers);
+      if (!os->is_open ())
+        return boost::make_tuple (outputStream, tracers);
+
+      outputStream = os;
+    }
+  else
+    {
+      outputStream = boost::shared_ptr<std::ostream> (&std::cout, NullDeleter<std::ostream>);
+    }
 
   for (NodeList::Iterator node = NodeList::Begin ();
        node != NodeList::End ();
@@ -79,11 +95,21 @@
   using namespace std;
 
   std::list<Ptr<L3AggregateTracer> > tracers;
-  boost::shared_ptr<std::ofstream> outputStream (new std::ofstream ());
-  outputStream->open (file.c_str (), std::ios_base::out | std::ios_base::trunc);
+  boost::shared_ptr<std::ostream> outputStream;
+  if (file != "-")
+    {
+      boost::shared_ptr<std::ofstream> os (new std::ofstream ());
+      os->open (file.c_str (), std::ios_base::out | std::ios_base::trunc);
 
-  if (!outputStream->is_open ())
-    return boost::make_tuple (outputStream, tracers);
+      if (!os->is_open ())
+        return boost::make_tuple (outputStream, tracers);
+
+      outputStream = os;
+    }
+  else
+    {
+      outputStream = boost::shared_ptr<std::ostream> (&std::cout, NullDeleter<std::ostream>);
+    }
 
   for (NodeContainer::Iterator node = nodes.Begin ();
        node != nodes.End ();
@@ -110,11 +136,21 @@
   using namespace std;
 
   std::list<Ptr<L3AggregateTracer> > tracers;
-  boost::shared_ptr<std::ofstream> outputStream (new std::ofstream ());
-  outputStream->open (file.c_str (), std::ios_base::out | std::ios_base::trunc);
+  boost::shared_ptr<std::ostream> outputStream;
+  if (file != "-")
+    {
+      boost::shared_ptr<std::ofstream> os (new std::ofstream ());
+      os->open (file.c_str (), std::ios_base::out | std::ios_base::trunc);
 
-  if (!outputStream->is_open ())
-    return boost::make_tuple (outputStream, tracers);
+      if (!os->is_open ())
+        return boost::make_tuple (outputStream, tracers);
+
+      outputStream = os;
+    }
+  else
+    {
+      outputStream = boost::shared_ptr<std::ostream> (&std::cout, NullDeleter<std::ostream>);
+    }
 
   Ptr<L3AggregateTracer> trace = Install (node, outputStream, averagingPeriod);
   tracers.push_back (trace);
@@ -262,56 +298,49 @@
 }
 
 void
-L3AggregateTracer::OutInterests  (std::string context,
-                                  Ptr<const Interest> header, Ptr<const Face> face)
+L3AggregateTracer::OutInterests  (Ptr<const Interest> header, Ptr<const Face> face)
 {
   m_stats[face].get<0> ().m_outInterests ++;
   m_stats[face].get<1> ().m_outInterests += header->GetSerializedSize ();
 }
 
 void
-L3AggregateTracer::InInterests   (std::string context,
-                                  Ptr<const Interest> header, Ptr<const Face> face)
+L3AggregateTracer::InInterests   (Ptr<const Interest> header, Ptr<const Face> face)
 {
   m_stats[face].get<0> ().m_inInterests ++;
   m_stats[face].get<1> ().m_inInterests += header->GetSerializedSize ();
 }
 
 void
-L3AggregateTracer::DropInterests (std::string context,
-                                  Ptr<const Interest> header, Ptr<const Face> face)
+L3AggregateTracer::DropInterests (Ptr<const Interest> header, Ptr<const Face> face)
 {
   m_stats[face].get<0> ().m_dropInterests ++;
   m_stats[face].get<1> ().m_dropInterests += header->GetSerializedSize ();
 }
 
 void
-L3AggregateTracer::OutNacks  (std::string context,
-                              Ptr<const Interest> header, Ptr<const Face> face)
+L3AggregateTracer::OutNacks  (Ptr<const Interest> header, Ptr<const Face> face)
 {
   m_stats[face].get<0> ().m_outNacks ++;
   m_stats[face].get<1> ().m_outNacks += header->GetSerializedSize ();
 }
 
 void
-L3AggregateTracer::InNacks   (std::string context,
-                              Ptr<const Interest> header, Ptr<const Face> face)
+L3AggregateTracer::InNacks   (Ptr<const Interest> header, Ptr<const Face> face)
 {
   m_stats[face].get<0> ().m_inNacks ++;
   m_stats[face].get<1> ().m_inNacks += header->GetSerializedSize ();
 }
 
 void
-L3AggregateTracer::DropNacks (std::string context,
-                              Ptr<const Interest> header, Ptr<const Face> face)
+L3AggregateTracer::DropNacks (Ptr<const Interest> header, Ptr<const Face> face)
 {
   m_stats[face].get<0> ().m_dropNacks ++;
   m_stats[face].get<1> ().m_dropNacks += header->GetSerializedSize ();
 }
 
 void
-L3AggregateTracer::OutData  (std::string context,
-                             Ptr<const ContentObject> header, Ptr<const Packet> payload,
+L3AggregateTracer::OutData  (Ptr<const ContentObject> header, Ptr<const Packet> payload,
                              bool fromCache, Ptr<const Face> face)
 {
   m_stats[face].get<0> ().m_outData ++;
@@ -319,8 +348,7 @@
 }
 
 void
-L3AggregateTracer::InData   (std::string context,
-                             Ptr<const ContentObject> header, Ptr<const Packet> payload,
+L3AggregateTracer::InData   (Ptr<const ContentObject> header, Ptr<const Packet> payload,
                              Ptr<const Face> face)
 {
   m_stats[face].get<0> ().m_inData ++;
@@ -328,8 +356,7 @@
 }
 
 void
-L3AggregateTracer::DropData (std::string context,
-                             Ptr<const ContentObject> header, Ptr<const Packet> payload,
+L3AggregateTracer::DropData (Ptr<const ContentObject> header, Ptr<const Packet> payload,
                              Ptr<const Face> face)
 {
   m_stats[face].get<0> ().m_dropData ++;
diff --git a/utils/tracers/ndn-l3-aggregate-tracer.h b/utils/tracers/ndn-l3-aggregate-tracer.h
index de0e260..03f7a9a 100644
--- a/utils/tracers/ndn-l3-aggregate-tracer.h
+++ b/utils/tracers/ndn-l3-aggregate-tracer.h
@@ -64,7 +64,7 @@
   /**
    * @brief Helper method to install tracers on all simulation nodes
    *
-   * @param file File to which traces will be written
+   * @param file File to which traces will be written.  If filename is -, then std::out is used
    * @param averagingPeriod How often data will be written into the trace file (default, every half second)
    *
    * @returns a tuple of reference to output stream and list of tracers. !!! Attention !!! This tuple needs to be preserved
@@ -78,7 +78,7 @@
    * @brief Helper method to install tracers on the selected simulation nodes
    *
    * @param nodes Nodes on which to install tracer
-   * @param file File to which traces will be written
+   * @param file File to which traces will be written.  If filename is -, then std::out is used
    * @param averagingPeriod How often data will be written into the trace file (default, every half second)
    *
    * @returns a tuple of reference to output stream and list of tracers. !!! Attention !!! This tuple needs to be preserved
@@ -92,7 +92,7 @@
    * @brief Helper method to install tracers on a specific simulation node
    *
    * @param nodes Nodes on which to install tracer
-   * @param file File to which traces will be written
+   * @param file File to which traces will be written.  If filename is -, then std::out is used
    * @param averagingPeriod How often data will be written into the trace file (default, every half second)
    *
    * @returns a tuple of reference to output stream and list of tracers. !!! Attention !!! This tuple needs to be preserved
@@ -102,7 +102,16 @@
   static boost::tuple< boost::shared_ptr<std::ostream>, std::list<Ptr<L3AggregateTracer> > >
   Install (Ptr<Node> node, const std::string &file, Time averagingPeriod = Seconds (0.5));
 
-private:
+  /**
+   * @brief Helper method to install tracers on a specific simulation node
+   *
+   * @param nodes Nodes on which to install tracer
+   * @param outputStream Smart pointer to a stream
+   * @param averagingPeriod How often data will be written into the trace file (default, every half second)
+   *
+   * @returns a tuple of reference to output stream and list of tracers. !!! Attention !!! This tuple needs to be preserved
+   *          for the lifetime of simulation, otherwise SEGFAULTs are inevitable
+   */
   static Ptr<L3AggregateTracer>
   Install (Ptr<Node> node, boost::shared_ptr<std::ostream> outputStream, Time averagingPeriod = Seconds (0.5));
 
@@ -115,40 +124,31 @@
   Print (std::ostream &os) const;
 
   virtual void
-  OutInterests  (std::string context,
-                 Ptr<const Interest>, Ptr<const Face>);
+  OutInterests  (Ptr<const Interest>, Ptr<const Face>);
 
   virtual void
-  InInterests   (std::string context,
-                 Ptr<const Interest>, Ptr<const Face>);
+  InInterests   (Ptr<const Interest>, Ptr<const Face>);
 
   virtual void
-  DropInterests (std::string context,
-                 Ptr<const Interest>, Ptr<const Face>);
+  DropInterests (Ptr<const Interest>, Ptr<const Face>);
 
   virtual void
-  OutNacks  (std::string context,
-             Ptr<const Interest>, Ptr<const Face>);
+  OutNacks  (Ptr<const Interest>, Ptr<const Face>);
 
   virtual void
-  InNacks   (std::string context,
-             Ptr<const Interest>, Ptr<const Face>);
+  InNacks   (Ptr<const Interest>, Ptr<const Face>);
 
   virtual void
-  DropNacks (std::string context,
-             Ptr<const Interest>, Ptr<const Face>);
+  DropNacks (Ptr<const Interest>, Ptr<const Face>);
 
   virtual void
-  OutData  (std::string context,
-            Ptr<const ContentObject>, Ptr<const Packet>, bool fromCache, Ptr<const Face>);
+  OutData  (Ptr<const ContentObject>, Ptr<const Packet>, bool fromCache, Ptr<const Face>);
 
   virtual void
-  InData   (std::string context,
-            Ptr<const ContentObject>, Ptr<const Packet>, Ptr<const Face>);
+  InData   (Ptr<const ContentObject>, Ptr<const Packet>, Ptr<const Face>);
 
   virtual void
-  DropData (std::string context,
-            Ptr<const ContentObject>, Ptr<const Packet>, Ptr<const Face>);
+  DropData (Ptr<const ContentObject>, Ptr<const Packet>, Ptr<const Face>);
 
 
   virtual void
diff --git a/utils/tracers/ndn-l3-rate-tracer.cc b/utils/tracers/ndn-l3-rate-tracer.cc
index 1e45f55..91f057a 100644
--- a/utils/tracers/ndn-l3-rate-tracer.cc
+++ b/utils/tracers/ndn-l3-rate-tracer.cc
@@ -44,25 +44,37 @@
 namespace ns3 {
 namespace ndn {
 
+template<class T>
+static inline void
+NullDeleter (T *ptr)
+{
+}
 
 boost::tuple< boost::shared_ptr<std::ostream>, std::list<Ptr<L3RateTracer> > >
 L3RateTracer::InstallAll (const std::string &file, Time averagingPeriod/* = Seconds (0.5)*/)
 {
   std::list<Ptr<L3RateTracer> > tracers;
-  boost::shared_ptr<std::ofstream> outputStream (new std::ofstream ());
-  outputStream->open (file.c_str (), std::ios_base::out | std::ios_base::trunc);
+  boost::shared_ptr<std::ostream> outputStream;
+  if (file != "-")
+    {
+      boost::shared_ptr<std::ofstream> os (new std::ofstream ());
+      os->open (file.c_str (), std::ios_base::out | std::ios_base::trunc);
 
-  if (!outputStream->is_open ())
-    return boost::make_tuple (outputStream, tracers);
+      if (!os->is_open ())
+        return boost::make_tuple (outputStream, tracers);
+
+      outputStream = os;
+    }
+  else
+    {
+      outputStream = boost::shared_ptr<std::ostream> (&std::cout, NullDeleter<std::ostream>);
+    }
 
   for (NodeList::Iterator node = NodeList::Begin ();
        node != NodeList::End ();
        node++)
     {
-      NS_LOG_DEBUG ("Node: " << lexical_cast<string> ((*node)->GetId ()));
-
-      Ptr<L3RateTracer> trace = Create<L3RateTracer> (outputStream, *node);
-      trace->SetAveragingPeriod (averagingPeriod);
+      Ptr<L3RateTracer> trace = Install (*node, outputStream, averagingPeriod);
       tracers.push_back (trace);
     }
 
@@ -76,6 +88,97 @@
   return boost::make_tuple (outputStream, tracers);
 }
 
+boost::tuple< boost::shared_ptr<std::ostream>, std::list<Ptr<L3RateTracer> > >
+L3RateTracer::Install (const NodeContainer &nodes, const std::string &file, Time averagingPeriod/* = Seconds (0.5)*/)
+{
+  using namespace boost;
+  using namespace std;
+
+  std::list<Ptr<L3RateTracer> > tracers;
+  boost::shared_ptr<std::ostream> outputStream;
+  if (file != "-")
+    {
+      boost::shared_ptr<std::ofstream> os (new std::ofstream ());
+      os->open (file.c_str (), std::ios_base::out | std::ios_base::trunc);
+
+      if (!os->is_open ())
+        return boost::make_tuple (outputStream, tracers);
+
+      outputStream = os;
+    }
+  else
+    {
+      outputStream = boost::shared_ptr<std::ostream> (&std::cout, NullDeleter<std::ostream>);
+    }
+
+  for (NodeContainer::Iterator node = nodes.Begin ();
+       node != nodes.End ();
+       node++)
+    {
+      Ptr<L3RateTracer> trace = Install (*node, outputStream, averagingPeriod);
+      tracers.push_back (trace);
+    }
+
+  if (tracers.size () > 0)
+    {
+      // *m_l3RateTrace << "# "; // not necessary for R's read.table
+      tracers.front ()->PrintHeader (*outputStream);
+      *outputStream << "\n";
+    }
+
+  return boost::make_tuple (outputStream, tracers);
+}
+
+boost::tuple< boost::shared_ptr<std::ostream>, std::list<Ptr<L3RateTracer> > >
+L3RateTracer::Install (Ptr<Node> node, const std::string &file, Time averagingPeriod/* = Seconds (0.5)*/)
+{
+  using namespace boost;
+  using namespace std;
+
+  std::list<Ptr<L3RateTracer> > tracers;
+  boost::shared_ptr<std::ostream> outputStream;
+  if (file != "-")
+    {
+      boost::shared_ptr<std::ofstream> os (new std::ofstream ());
+      os->open (file.c_str (), std::ios_base::out | std::ios_base::trunc);
+
+      if (!os->is_open ())
+        return boost::make_tuple (outputStream, tracers);
+
+      outputStream = os;
+    }
+  else
+    {
+      outputStream = boost::shared_ptr<std::ostream> (&std::cout, NullDeleter<std::ostream>);
+    }
+
+  Ptr<L3RateTracer> trace = Install (node, outputStream, averagingPeriod);
+  tracers.push_back (trace);
+
+  if (tracers.size () > 0)
+    {
+      // *m_l3RateTrace << "# "; // not necessary for R's read.table
+      tracers.front ()->PrintHeader (*outputStream);
+      *outputStream << "\n";
+    }
+
+  return boost::make_tuple (outputStream, tracers);
+}
+
+
+Ptr<L3RateTracer>
+L3RateTracer::Install (Ptr<Node> node,
+                            boost::shared_ptr<std::ostream> outputStream,
+                            Time averagingPeriod/* = Seconds (0.5)*/)
+{
+  NS_LOG_DEBUG ("Node: " << node->GetId ());
+
+  Ptr<L3RateTracer> trace = Create<L3RateTracer> (outputStream, node);
+  trace->SetAveragingPeriod (averagingPeriod);
+
+  return trace;
+}
+
 
 L3RateTracer::L3RateTracer (boost::shared_ptr<std::ostream> os, Ptr<Node> node)
   : L3Tracer (node)
@@ -206,56 +309,49 @@
 
 
 void
-L3RateTracer::OutInterests  (std::string context,
-                             Ptr<const Interest> header, Ptr<const Face> face)
+L3RateTracer::OutInterests  (Ptr<const Interest> header, Ptr<const Face> face)
 {
   m_stats[face].get<0> ().m_outInterests ++;
   m_stats[face].get<1> ().m_outInterests += header->GetSerializedSize ();
 }
 
 void
-L3RateTracer::InInterests   (std::string context,
-                             Ptr<const Interest> header, Ptr<const Face> face)
+L3RateTracer::InInterests   (Ptr<const Interest> header, Ptr<const Face> face)
 {
   m_stats[face].get<0> ().m_inInterests ++;
   m_stats[face].get<1> ().m_inInterests += header->GetSerializedSize ();
 }
 
 void
-L3RateTracer::DropInterests (std::string context,
-                             Ptr<const Interest> header, Ptr<const Face> face)
+L3RateTracer::DropInterests (Ptr<const Interest> header, Ptr<const Face> face)
 {
   m_stats[face].get<0> ().m_dropInterests ++;
   m_stats[face].get<1> ().m_dropInterests += header->GetSerializedSize ();
 }
 
 void
-L3RateTracer::OutNacks  (std::string context,
-                         Ptr<const Interest> header, Ptr<const Face> face)
+L3RateTracer::OutNacks  (Ptr<const Interest> header, Ptr<const Face> face)
 {
   m_stats[face].get<0> ().m_outNacks ++;
   m_stats[face].get<1> ().m_outNacks += header->GetSerializedSize ();
 }
 
 void
-L3RateTracer::InNacks   (std::string context,
-                         Ptr<const Interest> header, Ptr<const Face> face)
+L3RateTracer::InNacks   (Ptr<const Interest> header, Ptr<const Face> face)
 {
   m_stats[face].get<0> ().m_inNacks ++;
   m_stats[face].get<1> ().m_inNacks += header->GetSerializedSize ();
 }
 
 void
-L3RateTracer::DropNacks (std::string context,
-                         Ptr<const Interest> header, Ptr<const Face> face)
+L3RateTracer::DropNacks (Ptr<const Interest> header, Ptr<const Face> face)
 {
   m_stats[face].get<0> ().m_dropNacks ++;
   m_stats[face].get<1> ().m_dropNacks += header->GetSerializedSize ();
 }
 
 void
-L3RateTracer::OutData  (std::string context,
-                        Ptr<const ContentObject> header, Ptr<const Packet> payload,
+L3RateTracer::OutData  (Ptr<const ContentObject> header, Ptr<const Packet> payload,
                         bool fromCache, Ptr<const Face> face)
 {
   m_stats[face].get<0> ().m_outData ++;
@@ -263,8 +359,7 @@
 }
 
 void
-L3RateTracer::InData   (std::string context,
-                        Ptr<const ContentObject> header, Ptr<const Packet> payload,
+L3RateTracer::InData   (Ptr<const ContentObject> header, Ptr<const Packet> payload,
                         Ptr<const Face> face)
 {
   m_stats[face].get<0> ().m_inData ++;
@@ -272,8 +367,7 @@
 }
 
 void
-L3RateTracer::DropData (std::string context,
-                        Ptr<const ContentObject> header, Ptr<const Packet> payload,
+L3RateTracer::DropData (Ptr<const ContentObject> header, Ptr<const Packet> payload,
                         Ptr<const Face> face)
 {
   m_stats[face].get<0> ().m_dropData ++;
diff --git a/utils/tracers/ndn-l3-rate-tracer.h b/utils/tracers/ndn-l3-rate-tracer.h
index 4db4e70..64e5177 100644
--- a/utils/tracers/ndn-l3-rate-tracer.h
+++ b/utils/tracers/ndn-l3-rate-tracer.h
@@ -25,6 +25,7 @@
 
 #include "ns3/nstime.h"
 #include "ns3/event-id.h"
+#include <ns3/node-container.h>
 
 #include <boost/tuple/tuple.hpp>
 #include <boost/shared_ptr.hpp>
@@ -63,7 +64,7 @@
   /**
    * @brief Helper method to install tracers on all simulation nodes
    *
-   * @param file File to which traces will be written
+   * @param file File to which traces will be written.  If filename is -, then std::out is used
    * @param averagingPeriod Defines averaging period for the rate calculation,
    *        as well as how often data will be written into the trace file (default, every half second)
    *
@@ -74,6 +75,47 @@
   static boost::tuple< boost::shared_ptr<std::ostream>, std::list<Ptr<L3RateTracer> > >
   InstallAll (const std::string &file, Time averagingPeriod = Seconds (0.5));
 
+  /**
+   * @brief Helper method to install tracers on the selected simulation nodes
+   *
+   * @param nodes Nodes on which to install tracer
+   * @param file File to which traces will be written.  If filename is -, then std::out is used
+   * @param averagingPeriod How often data will be written into the trace file (default, every half second)
+   *
+   * @returns a tuple of reference to output stream and list of tracers. !!! Attention !!! This tuple needs to be preserved
+   *          for the lifetime of simulation, otherwise SEGFAULTs are inevitable
+   *
+   */
+  static boost::tuple< boost::shared_ptr<std::ostream>, std::list<Ptr<L3RateTracer> > >
+  Install (const NodeContainer &nodes, const std::string &file, Time averagingPeriod = Seconds (0.5));
+
+  /**
+   * @brief Helper method to install tracers on a specific simulation node
+   *
+   * @param nodes Nodes on which to install tracer
+   * @param file File to which traces will be written.  If filename is -, then std::out is used
+   * @param averagingPeriod How often data will be written into the trace file (default, every half second)
+   *
+   * @returns a tuple of reference to output stream and list of tracers. !!! Attention !!! This tuple needs to be preserved
+   *          for the lifetime of simulation, otherwise SEGFAULTs are inevitable
+   *
+   */
+  static boost::tuple< boost::shared_ptr<std::ostream>, std::list<Ptr<L3RateTracer> > >
+  Install (Ptr<Node> node, const std::string &file, Time averagingPeriod = Seconds (0.5));
+
+  /**
+   * @brief Helper method to install tracers on a specific simulation node
+   *
+   * @param nodes Nodes on which to install tracer
+   * @param outputStream Smart pointer to a stream
+   * @param averagingPeriod How often data will be written into the trace file (default, every half second)
+   *
+   * @returns a tuple of reference to output stream and list of tracers. !!! Attention !!! This tuple needs to be preserved
+   *          for the lifetime of simulation, otherwise SEGFAULTs are inevitable
+   */
+  static Ptr<L3RateTracer>
+  Install (Ptr<Node> node, boost::shared_ptr<std::ostream> outputStream, Time averagingPeriod = Seconds (0.5));
+  
   // from L3Tracer
   virtual void
   PrintHeader (std::ostream &os) const;
@@ -84,40 +126,31 @@
 protected:
   // from L3Tracer
   virtual void
-  OutInterests  (std::string context,
-                 Ptr<const Interest>, Ptr<const Face>);
+  OutInterests  (Ptr<const Interest>, Ptr<const Face>);
 
   virtual void
-  InInterests   (std::string context,
-                 Ptr<const Interest>, Ptr<const Face>);
+  InInterests   (Ptr<const Interest>, Ptr<const Face>);
 
   virtual void
-  DropInterests (std::string context,
-                 Ptr<const Interest>, Ptr<const Face>);
+  DropInterests (Ptr<const Interest>, Ptr<const Face>);
 
   virtual void
-  OutNacks  (std::string context,
-             Ptr<const Interest>, Ptr<const Face>);
+  OutNacks  (Ptr<const Interest>, Ptr<const Face>);
 
   virtual void
-  InNacks   (std::string context,
-             Ptr<const Interest>, Ptr<const Face>);
+  InNacks   (Ptr<const Interest>, Ptr<const Face>);
 
   virtual void
-  DropNacks (std::string context,
-             Ptr<const Interest>, Ptr<const Face>);
+  DropNacks (Ptr<const Interest>, Ptr<const Face>);
 
   virtual void
-  OutData  (std::string context,
-            Ptr<const ContentObject>, Ptr<const Packet>, bool fromCache, Ptr<const Face>);
+  OutData  (Ptr<const ContentObject>, Ptr<const Packet>, bool fromCache, Ptr<const Face>);
 
   virtual void
-  InData   (std::string context,
-            Ptr<const ContentObject>, Ptr<const Packet>, Ptr<const Face>);
+  InData   (Ptr<const ContentObject>, Ptr<const Packet>, Ptr<const Face>);
 
   virtual void
-  DropData (std::string context,
-            Ptr<const ContentObject>, Ptr<const Packet>, Ptr<const Face>);
+  DropData (Ptr<const ContentObject>, Ptr<const Packet>, Ptr<const Face>);
 
   virtual void
   SatisfiedInterests (Ptr<const pit::Entry>);
diff --git a/utils/tracers/ndn-l3-tracer.cc b/utils/tracers/ndn-l3-tracer.cc
index 455f684..bd45113 100644
--- a/utils/tracers/ndn-l3-tracer.cc
+++ b/utils/tracers/ndn-l3-tracer.cc
@@ -24,6 +24,7 @@
 #include "ns3/config.h"
 #include "ns3/names.h"
 #include "ns3/callback.h"
+#include "ns3/ndn-forwarding-strategy.h"
 
 #include <boost/lexical_cast.hpp>
 
@@ -65,33 +66,24 @@
 void
 L3Tracer::Connect ()
 {
-  Config::Connect ("/NodeList/"+m_node+"/$ns3::ndn::ForwardingStrategy/OutInterests",
-                   MakeCallback (&L3Tracer::OutInterests, this));
-  Config::Connect ("/NodeList/"+m_node+"/$ns3::ndn::ForwardingStrategy/InInterests",
-                   MakeCallback (&L3Tracer::InInterests, this));
-  Config::Connect ("/NodeList/"+m_node+"/$ns3::ndn::ForwardingStrategy/DropInterests",
-                   MakeCallback (&L3Tracer::DropInterests, this));
-
-  Config::Connect ("/NodeList/"+m_node+"/$ns3::ndn::ForwardingStrategy/OutData",
-                   MakeCallback (&L3Tracer::OutData, this));
-  Config::Connect ("/NodeList/"+m_node+"/$ns3::ndn::ForwardingStrategy/InData",
-                   MakeCallback (&L3Tracer::InData, this));
-  Config::Connect ("/NodeList/"+m_node+"/$ns3::ndn::ForwardingStrategy/DropData",
-                   MakeCallback (&L3Tracer::DropData, this));
+  Ptr<ForwardingStrategy> fw = m_nodePtr->GetObject<ForwardingStrategy> ();
+  
+  fw->TraceConnectWithoutContext ("OutInterests",  MakeCallback (&L3Tracer::OutInterests, this));
+  fw->TraceConnectWithoutContext ("InInterests",   MakeCallback (&L3Tracer::InInterests, this));
+  fw->TraceConnectWithoutContext ("DropInterests", MakeCallback (&L3Tracer::DropInterests, this));
+                                                                           
+  fw->TraceConnectWithoutContext ("OutData",  MakeCallback (&L3Tracer::OutData, this));
+  fw->TraceConnectWithoutContext ("InData",   MakeCallback (&L3Tracer::InData, this));
+  fw->TraceConnectWithoutContext ("DropData", MakeCallback (&L3Tracer::DropData, this));
 
   // only for some strategies
-  Config::Connect ("/NodeList/"+m_node+"/$ns3::ndn::ForwardingStrategy/OutNacks",
-                   MakeCallback (&L3Tracer::OutNacks, this));
-  Config::Connect ("/NodeList/"+m_node+"/$ns3::ndn::ForwardingStrategy/InNacks",
-                   MakeCallback (&L3Tracer::InNacks, this));
-  Config::Connect ("/NodeList/"+m_node+"/$ns3::ndn::ForwardingStrategy/DropNacks",
-                   MakeCallback (&L3Tracer::DropNacks, this));
-
+  fw->TraceConnectWithoutContext ("OutNacks",  MakeCallback (&L3Tracer::OutNacks, this));
+  fw->TraceConnectWithoutContext ("InNacks",   MakeCallback (&L3Tracer::InNacks, this));
+  fw->TraceConnectWithoutContext ("DropNacks", MakeCallback (&L3Tracer::DropNacks, this));
+  
   // satisfied/timed out PIs
-  Config::ConnectWithoutContext ("/NodeList/"+m_node+"/$ns3::ndn::ForwardingStrategy/SatisfiedInterests",
-                                 MakeCallback (&L3Tracer::SatisfiedInterests, this));
-  Config::ConnectWithoutContext ("/NodeList/"+m_node+"/$ns3::ndn::ForwardingStrategy/TimedOutInterests",
-                                 MakeCallback (&L3Tracer::TimedOutInterests, this));
+  fw->TraceConnectWithoutContext ("SatisfiedInterests", MakeCallback (&L3Tracer::SatisfiedInterests, this));
+  fw->TraceConnectWithoutContext ("TimedOutInterests", MakeCallback (&L3Tracer::TimedOutInterests, this));
 }
 
 } // namespace ndn
diff --git a/utils/tracers/ndn-l3-tracer.h b/utils/tracers/ndn-l3-tracer.h
index af840f4..bca0022 100644
--- a/utils/tracers/ndn-l3-tracer.h
+++ b/utils/tracers/ndn-l3-tracer.h
@@ -18,8 +18,8 @@
  * Author:  Alexander Afanasyev <alexander.afanasyev@ucla.edu>
  */
 
-#ifndef CCNX_L3_TRACER_H
-#define CCNX_L3_TRACER_H
+#ifndef NDN_L3_TRACER_H
+#define NDN_L3_TRACER_H
 
 #include "ns3/ptr.h"
 #include "ns3/simple-ref-count.h"
@@ -40,9 +40,6 @@
 class Interest;
 class ContentObject;
 
-typedef Interest InterestHeader;
-typedef ContentObject ContentObjectHeader;
-
 /**
  * @brief Base class for network-layer (incoming/outgoing Interests and Data) tracing of NDN stack
  */
@@ -87,41 +84,32 @@
   Connect ();
 
   virtual void
-  OutInterests  (std::string context,
-                 Ptr<const Interest>, Ptr<const Face>) = 0;
+  OutInterests  (Ptr<const Interest>, Ptr<const Face>) = 0;
 
   virtual void
-  InInterests   (std::string context,
-                 Ptr<const Interest>, Ptr<const Face>) = 0;
+  InInterests   (Ptr<const Interest>, Ptr<const Face>) = 0;
 
   virtual void
-  DropInterests (std::string context,
-                 Ptr<const Interest>, Ptr<const Face>) = 0;
+  DropInterests (Ptr<const Interest>, Ptr<const Face>) = 0;
 
   virtual void
-  OutNacks  (std::string context,
-             Ptr<const Interest>, Ptr<const Face>) = 0;
+  OutNacks  (Ptr<const Interest>, Ptr<const Face>) = 0;
 
   virtual void
-  InNacks   (std::string context,
-             Ptr<const Interest>, Ptr<const Face>) = 0;
+  InNacks   (Ptr<const Interest>, Ptr<const Face>) = 0;
 
   virtual void
-  DropNacks (std::string context,
-             Ptr<const Interest>, Ptr<const Face>) = 0;
+  DropNacks (Ptr<const Interest>, Ptr<const Face>) = 0;
 
 
   virtual void
-  OutData  (std::string context,
-            Ptr<const ContentObject>, Ptr<const Packet>, bool fromCache, Ptr<const Face>) = 0;
+  OutData  (Ptr<const ContentObject>, Ptr<const Packet>, bool fromCache, Ptr<const Face>) = 0;
 
   virtual void
-  InData   (std::string context,
-            Ptr<const ContentObject>, Ptr<const Packet>, Ptr<const Face>) = 0;
+  InData   (Ptr<const ContentObject>, Ptr<const Packet>, Ptr<const Face>) = 0;
 
   virtual void
-  DropData (std::string context,
-            Ptr<const ContentObject>, Ptr<const Packet>, Ptr<const Face>) = 0;
+  DropData (Ptr<const ContentObject>, Ptr<const Packet>, Ptr<const Face>) = 0;
 
   virtual void
   SatisfiedInterests (Ptr<const pit::Entry>) = 0;
@@ -180,4 +168,4 @@
 } // namespace ndn
 } // namespace ns3
 
-#endif // CCNX_L3_TRACER_H
+#endif // NDN_L3_TRACER_H