utils: Adding ability to install ndn::L3AggregateTracer on individual nodes
diff --git a/utils/tracers/ndn-l3-aggregate-tracer.cc b/utils/tracers/ndn-l3-aggregate-tracer.cc
index b64fc6b..646c516 100644
--- a/utils/tracers/ndn-l3-aggregate-tracer.cc
+++ b/utils/tracers/ndn-l3-aggregate-tracer.cc
@@ -58,10 +58,7 @@
        node != NodeList::End ();
        node++)
     {
-      NS_LOG_DEBUG ("Node: " << (*node)->GetId ());
-
-      Ptr<L3AggregateTracer> trace = Create<L3AggregateTracer> (outputStream, *node);
-      trace->SetAveragingPeriod (averagingPeriod);
+      Ptr<L3AggregateTracer> trace = Install (*node, outputStream, averagingPeriod);
       tracers.push_back (trace);
     }
 
@@ -75,7 +72,76 @@
   return boost::make_tuple (outputStream, tracers);
 }
 
+boost::tuple< boost::shared_ptr<std::ostream>, std::list<Ptr<L3AggregateTracer> > >
+L3AggregateTracer::Install (const NodeContainer &nodes, const std::string &file, Time averagingPeriod/* = Seconds (0.5)*/)
+{
+  using namespace boost;
+  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);
+
+  if (!outputStream->is_open ())
+    return boost::make_tuple (outputStream, tracers);
+
+  for (NodeContainer::Iterator node = nodes.Begin ();
+       node != nodes.End ();
+       node++)
+    {
+      Ptr<L3AggregateTracer> 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<L3AggregateTracer> > >
+L3AggregateTracer::Install (Ptr<Node> node, const std::string &file, Time averagingPeriod/* = Seconds (0.5)*/)
+{
+  using namespace boost;
+  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);
+
+  if (!outputStream->is_open ())
+    return boost::make_tuple (outputStream, tracers);
+
+  Ptr<L3AggregateTracer> 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<L3AggregateTracer>
+L3AggregateTracer::Install (Ptr<Node> node,
+                            boost::shared_ptr<std::ostream> outputStream,
+                            Time averagingPeriod/* = Seconds (0.5)*/)
+{
+  NS_LOG_DEBUG ("Node: " << node->GetId ());
+
+  Ptr<L3AggregateTracer> trace = Create<L3AggregateTracer> (outputStream, node);
+  trace->SetAveragingPeriod (averagingPeriod);
+
+  return trace;
+}
 
 L3AggregateTracer::L3AggregateTracer (boost::shared_ptr<std::ostream> os, Ptr<Node> node)
   : L3Tracer (node)
diff --git a/utils/tracers/ndn-l3-aggregate-tracer.h b/utils/tracers/ndn-l3-aggregate-tracer.h
index b7f6ed3..de0e260 100644
--- a/utils/tracers/ndn-l3-aggregate-tracer.h
+++ b/utils/tracers/ndn-l3-aggregate-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>
@@ -73,6 +74,38 @@
   static boost::tuple< boost::shared_ptr<std::ostream>, std::list<Ptr<L3AggregateTracer> > >
   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
+   * @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<L3AggregateTracer> > >
+  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
+   * @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<L3AggregateTracer> > >
+  Install (Ptr<Node> node, const std::string &file, Time averagingPeriod = Seconds (0.5));
+
+private:
+  static Ptr<L3AggregateTracer>
+  Install (Ptr<Node> node, boost::shared_ptr<std::ostream> outputStream, Time averagingPeriod = Seconds (0.5));
+
 protected:
   // from L3Tracer
   virtual void