Merge remote-tracking branch 'git.irl/ilya'
diff --git a/apps/ccnx-consumer-batches.cc b/apps/ccnx-consumer-batches.cc
new file mode 100644
index 0000000..deb4a0d
--- /dev/null
+++ b/apps/ccnx-consumer-batches.cc
@@ -0,0 +1,89 @@
+/* -*-  Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2011 University of California, Los Angeles
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation;
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ * Author: Alexander Afanasyev <alexander.afanasyev@ucla.edu>
+ */
+
+#include "ccnx-consumer-batches.h"
+#include "ns3/ptr.h"
+#include "ns3/log.h"
+#include "ns3/simulator.h"
+#include "ns3/packet.h"
+#include "ns3/callback.h"
+#include "ns3/string.h"
+#include "ns3/uinteger.h"
+#include "ns3/double.h"
+#include "ns3/batches.h"
+
+NS_LOG_COMPONENT_DEFINE ("CcnxConsumerBatches");
+
+namespace ns3
+{    
+    
+NS_OBJECT_ENSURE_REGISTERED (CcnxConsumerBatches);
+    
+TypeId
+CcnxConsumerBatches::GetTypeId (void)
+{
+  static TypeId tid = TypeId ("ns3::CcnxConsumerBatches")
+    .SetParent<CcnxConsumer> ()
+    .AddConstructor<CcnxConsumerBatches> ()
+
+    .AddAttribute ("Batches", "Batches to schedule. Should be vector, containing pairs of time and amount",
+                   // TypeId::ATTR_SET, 
+                   StringValue (""),
+                   MakeBatchesAccessor (&CcnxConsumerBatches::GetBatch, &CcnxConsumerBatches::SetBatch),
+                   MakeBatchesChecker ())
+    ;
+
+  return tid;
+}
+
+CcnxConsumerBatches::CcnxConsumerBatches ()
+{
+}
+
+void
+CcnxConsumerBatches::SetBatch (const Batches &batches)
+{
+  // std::cout << "Batches: " << batches << "\n";
+  for (Batches::const_iterator i = batches.begin (); i != batches.end (); i++)
+    {
+      Simulator::Schedule (i->get<0> (), &CcnxConsumerBatches::AddBatch, this, i->get<1> ());
+    }
+}
+
+void
+CcnxConsumerBatches::AddBatch (uint32_t amount)
+{
+  // std::cout << Simulator::Now () << " adding batch of " << amount << "\n";
+  m_seqMax += amount;
+  ScheduleNextPacket ();
+}
+
+void
+CcnxConsumerBatches::ScheduleNextPacket ()
+{
+  if (!m_sendEvent.IsRunning ())
+    m_sendEvent = Simulator::Schedule (Seconds(0.00001), &CcnxConsumer::SendPacket, this);
+}
+
+///////////////////////////////////////////////////
+//          Process incoming packets             //
+///////////////////////////////////////////////////
+
+} // namespace ns3
diff --git a/apps/ccnx-consumer-batches.h b/apps/ccnx-consumer-batches.h
new file mode 100644
index 0000000..36d7643
--- /dev/null
+++ b/apps/ccnx-consumer-batches.h
@@ -0,0 +1,78 @@
+/* -*-  Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2011 University of California, Los Angeles
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation;
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ * Author: Alexander Afanasyev <alexander.afanasyev@ucla.edu>
+ */
+
+#ifndef CCNX_CONSUMER_BATCHES_H
+#define CCNX_CONSUMER_BATCHES_H
+
+#include "ccnx-consumer.h"
+#include "ns3/traced-value.h"
+#include "ns3/batches.h"
+
+namespace ns3 
+{
+
+/**
+ * @ingroup ccnx
+ * \brief CCNx application for sending out Interest packets in batches
+ */
+class CcnxConsumerBatches: public CcnxConsumer
+{
+public: 
+  static TypeId GetTypeId ();
+        
+  /**
+   * \brief Default constructor 
+   */
+  CcnxConsumerBatches ();
+
+  // From CcnxApp
+  // virtual void
+  // OnInterest (const Ptr<const CcnxInterestHeader> &interest);
+
+  // virtual void
+  // OnNack (const Ptr<const CcnxInterestHeader> &interest);
+
+  // virtual void
+  // OnContentObject (const Ptr<const CcnxContentObjectHeader> &contentObject,
+  //                  const Ptr<const Packet> &payload);
+
+  // virtual void
+  // OnTimeout (uint32_t sequenceNumber);
+
+private:
+  Batches
+  GetBatch () const { return Batches(); }
+
+  void
+  SetBatch (const Batches &batch);
+  
+  void
+  AddBatch (uint32_t amount);
+protected:
+  /**
+   * \brief Constructs the Interest packet and sends it using a callback to the underlying CCNx protocol
+   */
+  virtual void
+  ScheduleNextPacket ();
+};
+
+} // namespace ns3
+
+#endif
diff --git a/apps/ccnx-consumer-cbr.cc b/apps/ccnx-consumer-cbr.cc
index 5a2a759..a7b848c 100644
--- a/apps/ccnx-consumer-cbr.cc
+++ b/apps/ccnx-consumer-cbr.cc
@@ -48,61 +48,31 @@
     .SetParent<CcnxConsumer> ()
     .AddConstructor<CcnxConsumerCbr> ()
 
-    .AddAttribute ("MeanRate", "Mean data packet rate (relies on the PayloadSize parameter)",
-                   StringValue ("100Kbps"),
-                   MakeDataRateAccessor (&CcnxConsumerCbr::GetDesiredRate, &CcnxConsumerCbr::SetDesiredRate),
-                   MakeDataRateChecker ())
+    .AddAttribute ("Frequency", "Frequency of interest packets",
+                   StringValue ("1.0"),
+                   MakeDoubleAccessor (&CcnxConsumerCbr::m_frequency),
+                   MakeDoubleChecker<double> ())
     ;
 
   return tid;
 }
     
 CcnxConsumerCbr::CcnxConsumerCbr ()
-  : m_desiredRate ("100Kbps")
+  : m_frequency (1.0)
 {
   NS_LOG_FUNCTION_NOARGS ();
-
-  UpdateMean ();
 }
 
-
-void
-CcnxConsumerCbr::UpdateMean ()
-{
-  double mean = 8.0 * m_payloadSize / m_desiredRate.GetBitRate ();
-  m_randExp = ExponentialVariable (mean, 100 * mean); // set upper limit to inter-arrival time
-}
-
-void
-CcnxConsumerCbr::SetPayloadSize (uint32_t payload)
-{
-  CcnxConsumer::SetPayloadSize (payload);
-  UpdateMean ();
-}
-
-void
-CcnxConsumerCbr::SetDesiredRate (DataRate rate)
-{
-  m_desiredRate = rate;
-  UpdateMean ();
-}
-
-DataRate
-CcnxConsumerCbr::GetDesiredRate () const
-{
-  return m_desiredRate;
-}
-
-
 void
 CcnxConsumerCbr::ScheduleNextPacket ()
 {
   // double mean = 8.0 * m_payloadSize / m_desiredRate.GetBitRate ();
+  // std::cout << "next: " << Simulator::Now().ToDouble(Time::S) + mean << "s\n";
 
   if (!m_sendEvent.IsRunning ())
     m_sendEvent = Simulator::Schedule (
-                                       Seconds(m_randExp.GetValue ()),
-                                       // Seconds(mean),
+                                       // Seconds(m_randExp.GetValue ()),
+                                       Seconds(1.0 / m_frequency),
                                        &CcnxConsumer::SendPacket, this);
 }
 
diff --git a/apps/ccnx-consumer-cbr.h b/apps/ccnx-consumer-cbr.h
index 59a06d7..03558ed 100644
--- a/apps/ccnx-consumer-cbr.h
+++ b/apps/ccnx-consumer-cbr.h
@@ -61,21 +61,21 @@
   ScheduleNextPacket ();
   
 private:
-  void
-  UpdateMean ();
+  // void
+  // UpdateMean ();
 
-  virtual void
-  SetPayloadSize (uint32_t payload);
+  // virtual void
+  // SetPayloadSize (uint32_t payload);
 
-  void
-  SetDesiredRate (DataRate rate);
+  // void
+  // SetDesiredRate (DataRate rate);
 
-  DataRate
-  GetDesiredRate () const;
+  // DataRate
+  // GetDesiredRate () const;
   
 protected:
   ExponentialVariable m_randExp; // packet inter-arrival time generation (Poisson process)
-  DataRate            m_desiredRate;    // Desired data packet rate
+  double              m_frequency; // Frequency of interest packets (in hertz)
 };
 
 } // namespace ns3
diff --git a/apps/ccnx-consumer-window.cc b/apps/ccnx-consumer-window.cc
index 77f258c..060b2cc 100644
--- a/apps/ccnx-consumer-window.cc
+++ b/apps/ccnx-consumer-window.cc
@@ -47,6 +47,15 @@
                    MakeUintegerAccessor (&CcnxConsumerWindow::GetWindow, &CcnxConsumerWindow::SetWindow),
                    MakeUintegerChecker<uint32_t> ())
 
+    .AddAttribute ("PayloadSize", "Average size of content object size (to calculate interest generation rate)",
+                   UintegerValue (1040),
+                   MakeUintegerAccessor (&CcnxConsumerWindow::GetPayloadSize, &CcnxConsumerWindow::SetPayloadSize),
+                   MakeUintegerChecker<uint32_t>())
+    .AddAttribute ("Size", "Amount of data in megabytes to request (relies on PayloadSize parameter)",
+                   DoubleValue (-1), // don't impose limit by default
+                   MakeDoubleAccessor (&CcnxConsumerWindow::GetMaxSize, &CcnxConsumerWindow::SetMaxSize),
+                   MakeDoubleChecker<double> ())
+
     .AddTraceSource ("WindowTrace",
                      "Window that controls how many outstanding interests are allowed",
                      MakeTraceSourceAccessor (&CcnxConsumerWindow::m_window))
@@ -59,7 +68,8 @@
 }
 
 CcnxConsumerWindow::CcnxConsumerWindow ()
-  : m_inFlight (0)
+  : m_payloadSize (1040)
+  , m_inFlight (0)
 {
 }
 
@@ -75,6 +85,42 @@
   return m_window;
 }
 
+uint32_t
+CcnxConsumerWindow::GetPayloadSize () const
+{
+  return m_payloadSize;
+}
+
+void
+CcnxConsumerWindow::SetPayloadSize (uint32_t payload)
+{
+  m_payloadSize = payload;
+}
+
+double
+CcnxConsumerWindow::GetMaxSize () const
+{
+  if (m_seqMax == 0)
+    return -1.0;
+
+  return m_maxSize;
+}
+
+void
+CcnxConsumerWindow::SetMaxSize (double size)
+{
+  m_maxSize = size;
+  if (m_maxSize < 0)
+    {
+      m_seqMax = 0;
+      return;
+    }
+
+  m_seqMax = floor(1.0 + m_maxSize * 1024.0 * 1024.0 / m_payloadSize);
+  NS_LOG_DEBUG ("MaxSeqNo: " << m_seqMax);
+}
+
+
 void
 CcnxConsumerWindow::ScheduleNextPacket ()
 {
diff --git a/apps/ccnx-consumer-window.h b/apps/ccnx-consumer-window.h
index c3b0ddf..0c24551 100644
--- a/apps/ccnx-consumer-window.h
+++ b/apps/ccnx-consumer-window.h
@@ -69,8 +69,23 @@
 
   uint32_t
   GetWindow () const;
+
+  virtual void
+  SetPayloadSize (uint32_t payload);
+
+  uint32_t
+  GetPayloadSize () const;
+
+  double
+  GetMaxSize () const;
+
+  void
+  SetMaxSize (double size);
   
 protected:
+  uint32_t m_payloadSize; // expected payload size
+  double   m_maxSize; // max size to request
+
   TracedValue<uint32_t> m_window;
   TracedValue<uint32_t> m_inFlight;
 };
diff --git a/apps/ccnx-consumer.cc b/apps/ccnx-consumer.cc
index 6fc3a40..6c58bc7 100644
--- a/apps/ccnx-consumer.cc
+++ b/apps/ccnx-consumer.cc
@@ -58,15 +58,6 @@
                    MakeIntegerAccessor(&CcnxConsumer::m_seq),
                    MakeIntegerChecker<int32_t>())
 
-    .AddAttribute ("PayloadSize", "Average size of content object size (to calculate interest generation rate)",
-                   UintegerValue (1040),
-                   MakeUintegerAccessor (&CcnxConsumer::GetPayloadSize, &CcnxConsumer::SetPayloadSize),
-                   MakeUintegerChecker<uint32_t>())
-    .AddAttribute ("Size", "Amount of data in megabytes to request (relies on PayloadSize parameter)",
-                   DoubleValue (-1), // don't impose limit by default
-                   MakeDoubleAccessor (&CcnxConsumer::GetMaxSize, &CcnxConsumer::SetMaxSize),
-                   MakeDoubleChecker<double> ())
-
     .AddAttribute ("Prefix","CcnxName of the Interest",
                    StringValue ("/"),
                    MakeCcnxNameComponentsAccessor (&CcnxConsumer::m_interestName),
@@ -94,7 +85,7 @@
 
     .AddAttribute ("RetxTimer",
                    "Timeout defining how frequent retransmission timeouts should be checked",
-                   StringValue ("1s"),
+                   StringValue ("1ms"),
                    MakeTimeAccessor (&CcnxConsumer::GetRetxTimer, &CcnxConsumer::SetRetxTimer),
                    MakeTimeChecker ())
 
@@ -107,12 +98,12 @@
     
 CcnxConsumer::CcnxConsumer ()
   : m_rand (0, std::numeric_limits<uint32_t>::max ())
-  , m_payloadSize (1040)
   , m_seq (0)
+  , m_seqMax (0) // don't request anything
 {
   NS_LOG_FUNCTION_NOARGS ();
   
-  m_rtt = CreateObject<RttMeanDeviation> (); 
+  m_rtt = CreateObject<RttMeanDeviation> ();
 }
 
 void
@@ -159,40 +150,6 @@
                                      &CcnxConsumer::CheckRetxTimeout, this); 
 }
 
-uint32_t
-CcnxConsumer::GetPayloadSize () const
-{
-  return m_payloadSize;
-}
-
-void
-CcnxConsumer::SetPayloadSize (uint32_t payload)
-{
-  m_payloadSize = payload;
-}
-
-double
-CcnxConsumer::GetMaxSize () const
-{
-  if (m_seqMax == 0)
-    return -1.0;
-
-  return m_seqMax * m_payloadSize / 1024.0 / 1024.0;
-}
-
-void
-CcnxConsumer::SetMaxSize (double size)
-{
-  if (size < 0)
-    {
-      m_seqMax = 0;
-      return;
-    }
-
-  m_seqMax = floor(1.0 + size * 1024.0 * 1024.0 / m_payloadSize);
-  NS_LOG_DEBUG ("MaxSeqNo: " << m_seqMax);
-}
-
 // Application Methods
 void 
 CcnxConsumer::StartApplication () // Called at time specified by Start
@@ -354,8 +311,8 @@
 void
 CcnxConsumer::OnTimeout (uint32_t sequenceNumber)
 {
-  // std::cout << "TO: " << sequenceNumber << "\n";
-  // std::cout << "Current RTO: " << m_rtt->RetransmitTimeout ().ToDouble (Time::S) << "s\n";
+  std::cout << Simulator::Now () << ", TO: " << sequenceNumber << ", current RTO: " << m_rtt->RetransmitTimeout ().ToDouble (Time::S) << "s\n";
+
   m_retxSeqs.insert (sequenceNumber);
   ScheduleNextPacket (); 
 }
diff --git a/apps/ccnx-consumer.h b/apps/ccnx-consumer.h
index 8fe885d..e53ff89 100644
--- a/apps/ccnx-consumer.h
+++ b/apps/ccnx-consumer.h
@@ -109,21 +109,8 @@
   Time
   GetRetxTimer () const;
   
-  virtual void
-  SetPayloadSize (uint32_t payload);
-
-  uint32_t
-  GetPayloadSize () const;
-
-  double
-  GetMaxSize () const;
-
-  void
-  SetMaxSize (double size);
-  
 protected:
   UniformVariable m_rand; // nonce generator
-  uint32_t            m_payloadSize; // expected payload size
 
   uint32_t        m_seq;
   uint32_t        m_seqMax;    // maximum number of sequence number
diff --git a/apps/ccnx-hijacker.cc b/apps/ccnx-hijacker.cc
index c0d74d7..0bcad9d 100644
--- a/apps/ccnx-hijacker.cc
+++ b/apps/ccnx-hijacker.cc
@@ -31,6 +31,9 @@
 #include "ns3/ccnx-fib.h"
 
 #include <boost/ref.hpp>
+#include <boost/lambda/lambda.hpp>
+#include <boost/lambda/bind.hpp>
+namespace ll = boost::lambda;
 
 NS_LOG_COMPONENT_DEFINE ("CcnxHijacker");
 
@@ -75,7 +78,13 @@
 
   CcnxApp::StartApplication ();
 
-  GetNode ()->GetObject<CcnxFib> ()->Add (m_prefix, m_face, 0);
+  Ptr<CcnxFib> fib = GetNode ()->GetObject<CcnxFib> ();
+  CcnxFibEntryContainer::type::iterator fibEntry = fib->Add (m_prefix, m_face, 0);
+
+  // make face green, so it will be used primarily
+  fib->m_fib.modify (fibEntry,
+                     ll::bind (&CcnxFibEntry::UpdateStatus,
+                               ll::_1, m_face, CcnxFibFaceMetric::NDN_FIB_GREEN));
 }
 
 void
diff --git a/apps/ccnx-producer.cc b/apps/ccnx-producer.cc
index 3a37efd..48c8991 100644
--- a/apps/ccnx-producer.cc
+++ b/apps/ccnx-producer.cc
@@ -31,6 +31,9 @@
 #include "ns3/ccnx-fib.h"
 
 #include <boost/ref.hpp>
+#include <boost/lambda/lambda.hpp>
+#include <boost/lambda/bind.hpp>
+namespace ll = boost::lambda;
 
 NS_LOG_COMPONENT_DEFINE ("CcnxProducer");
 
@@ -75,7 +78,13 @@
 
   CcnxApp::StartApplication ();
 
-  GetNode ()->GetObject<CcnxFib> ()->Add (m_prefix, m_face, 0);
+  Ptr<CcnxFib> fib = GetNode ()->GetObject<CcnxFib> ();
+  CcnxFibEntryContainer::type::iterator fibEntry = fib->Add (m_prefix, m_face, 0);
+
+  // make face green, so it will be used primarily
+  fib->m_fib.modify (fibEntry,
+                     ll::bind (&CcnxFibEntry::UpdateStatus,
+                               ll::_1, m_face, CcnxFibFaceMetric::NDN_FIB_GREEN));
 }
 
 void
diff --git a/examples/base-experiment.h b/examples/base-experiment.h
index c00c127..fd8c1f0 100644
--- a/examples/base-experiment.h
+++ b/examples/base-experiment.h
@@ -111,8 +111,8 @@
       {
         guard ++;
 
-        uint32_t node1_num = m_rand.GetValue ();
-        uint32_t node2_num = m_rand.GetValue ();
+        uint32_t node1_num = m_rand.GetValue (); //43;//
+        uint32_t node2_num = m_rand.GetValue (); //38;//
 
         if (node1_num == node2_num)
           continue;
diff --git a/examples/blackhole-sprint.cc b/examples/blackhole-sprint.cc
index 9b8fcfc..8773ce3 100644
--- a/examples/blackhole-sprint.cc
+++ b/examples/blackhole-sprint.cc
@@ -255,6 +255,8 @@
         uint32_t node1_num = i->get<0> ();
         uint32_t node2_num = i->get<1> ();
 
+        cout << "Good: " << node1_num << ", bad: " << node2_num << "\n";
+        
         Ptr<Node> node1 = Names::Find<Node> ("/sprint", lexical_cast<string> (node1_num));
         Ptr<Node> node2 = Names::Find<Node> ("/sprint", lexical_cast<string> (node2_num));
 
@@ -271,19 +273,21 @@
         
         CcnxAppHelper fakeProducerHelper ("ns3::CcnxHijacker");
         fakeProducerHelper.SetPrefix (prefix);
-        apps.Add
-          (fakeProducerHelper.Install (node2));
+        ApplicationContainer hijacker = fakeProducerHelper.Install (node2);
+        apps.Add (hijacker);
+        hijacker.Start (Seconds(1.0));
         
         // one more trick. Need to install route to hijacker (aka "hijacker announces itself as a legitimate producer")
         CcnxStackHelper::InstallRouteTo (prefix, node1);
-        CcnxStackHelper::InstallRouteTo (prefix, node2);
+        Simulator::Schedule (Seconds(1.0), CcnxStackHelper::InstallRouteTo, prefix, node2);
+        // CcnxStackHelper::InstallRouteTo (prefix, node2);
 
         prefixes.push_back (prefix); // remember prefixes that consumers will be requesting
       }
 
     // All consumers request exactly 10 packets, to convert number interests packets to requested size:
     // size = 1040 * (max_number_of_packets-1) / 1024 / 1024
-    double requestSize = 1040.0 * (10 - 1) / 1024.0 / 1024.0;
+    // double requestSize = 1040.0 * (10 - 1) / 1024.0 / 1024.0;
     
     // Create Consumers
     NodeContainer nodes = reader->GetNodes ();
@@ -293,15 +297,15 @@
         if (m_usedNodes.count (namedId) > 0)
           continue;
 
-        CcnxAppHelper consumerHelper ("ns3::CcnxConsumerCbr");
+        CcnxAppHelper consumerHelper ("ns3::CcnxConsumerBatches");
+        consumerHelper.SetAttribute ("LifeTime", StringValue("100s"));
+        consumerHelper.SetAttribute ("Batches", StringValue("0s 10 2s 1"));
         BOOST_FOREACH (const string &prefix, prefixes)
           {
             consumerHelper.SetPrefix (prefix);
-            consumerHelper.SetAttribute ("MeanRate", StringValue ("1000Kbps")); // this is about 1 interest a second
-            consumerHelper.SetAttribute ("Size", DoubleValue(requestSize));
-            
-            apps.Add
-              (consumerHelper.Install (*node));
+
+            ApplicationContainer consumer = consumerHelper.Install (*node);
+            apps.Add (consumer);
           }
 
         // break;
@@ -317,7 +321,7 @@
   
   Config::SetDefault ("ns3::PointToPointNetDevice::DataRate", StringValue ("100Mbps"));
   Config::SetDefault ("ns3::DropTailQueue::MaxPackets", StringValue ("2000"));
-  Config::SetDefault ("ns3::RttEstimator::InitialEstimation", StringValue ("1s"));
+  Config::SetDefault ("ns3::RttEstimator::InitialEstimation", StringValue ("0.5s"));
 
   Config::SetDefault ("ns3::ConfigStore::Filename", StringValue ("attributes.xml"));
   Config::SetDefault ("ns3::ConfigStore::Mode", StringValue ("Save"));
@@ -334,18 +338,18 @@
   // config.ConfigureDefaults ();
 
   Experiment experiment;
-  for (uint32_t i = startRun; i < maxRuns; i++)
+  for (uint32_t run = startRun; run < startRun + maxRuns; run++)
     {
-      Config::SetGlobal ("RngRun", IntegerValue (i));
+      Config::SetGlobal ("RngRun", IntegerValue (run));
       cout << "seed = " << SeedManager::GetSeed () << ", run = " << SeedManager::GetRun () << endl;
 
       Experiment experiment;
-      experiment.GenerateRandomPairs (10);
+      experiment.GenerateRandomPairs (1);
       experiment.ComputeShortestWeightsPath(1,12);
       experiment.ComputeShortestDelayPath(1,12);
-      cout << "Run " << i << endl;
+      cout << "Run " << run << endl;
       
-      string prefix = "blackhole-" + lexical_cast<string> (i) + "-";
+      string prefix = "blackhole-" + lexical_cast<string> (run) + "-";
   
       experiment.ConfigureTopology ();
       experiment.InstallCcnxStack (false);
@@ -354,7 +358,7 @@
       //tracing
       CcnxTraceHelper traceHelper;
       // traceHelper.EnableRateL3All (prefix + "rate-trace.log");
-      traceHelper.EnableSeqsAppAll ("ns3::CcnxConsumerCbr", prefix + "consumers-seqs.log");
+      traceHelper.EnableSeqsAppAll ("ns3::CcnxConsumerBatches", prefix + "consumers-seqs.log");
       
       experiment.Run (Seconds(40.0));
     }
diff --git a/helper/ccnx-stack-helper.cc b/helper/ccnx-stack-helper.cc
index 3714f64..bc03c9d 100644
--- a/helper/ccnx-stack-helper.cc
+++ b/helper/ccnx-stack-helper.cc
@@ -306,7 +306,6 @@
     }
 }
 
-
 void
 CcnxStackHelper::InstallRoutesToAll ()
 {
diff --git a/model/batches.cc b/model/batches.cc
new file mode 100644
index 0000000..1dbccfa
--- /dev/null
+++ b/model/batches.cc
@@ -0,0 +1,57 @@
+/* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil -*- */
+/*
+ * Copyright (c) 2011,2012 University of California, Los Angeles
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation;
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ * Author: Alexander Afanasyev <alexander.afanasyev@ucla.edu>
+ */
+
+#include "ns3/batches.h"
+
+namespace ns3 {
+
+ATTRIBUTE_HELPER_CPP (Batches);
+
+std::ostream &
+operator << (std::ostream &os, const Batches &batch)
+{
+  for (Batches::const_iterator i = batch.begin (); i != batch.end (); i++)
+    os << i->get<0> () << " " << i->get<1> () << " ";
+
+  return os;
+}
+
+/**
+ * \brief Read components from input and add them to components. Will read input stream till eof
+ * Substrings separated by slashes will become separate components
+ */
+std::istream &
+operator >> (std::istream &is, Batches &batch)
+{
+  Time time;
+  uint32_t amount;
+  while (!is.eof ())
+    {
+      is >> time >> amount;
+      batch.Add (time, amount);
+      // std::cout << time << ", " << amount << ". \n";
+    }
+  
+  is.clear ();
+  return is;
+}
+
+
+}
diff --git a/model/batches.h b/model/batches.h
new file mode 100644
index 0000000..d481a47
--- /dev/null
+++ b/model/batches.h
@@ -0,0 +1,58 @@
+/* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil -*- */
+/*
+ * Copyright (c) 2011,2012 University of California, Los Angeles
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation;
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ * Author: Alexander Afanasyev <alexander.afanasyev@ucla.edu>
+ */
+
+#ifndef _BATCHES_H_
+#define _BATCHES_H_
+
+#include "ns3/attribute.h"
+#include "ns3/attribute-helper.h"
+#include "ns3/nstime.h"
+#include <list>
+#include <boost/tuple/tuple.hpp>
+
+namespace ns3 {
+
+class Batches : public std::list<boost::tuple<Time, uint32_t> >
+{
+public:
+  Batches () { };
+
+  void
+  Add (const Time &when, uint32_t amount)
+  {
+    push_back (boost::make_tuple<Time, uint32_t> (when, amount));
+  }
+};
+
+ATTRIBUTE_HELPER_HEADER (Batches);
+
+std::ostream &
+operator << (std::ostream &os, const Batches &batch);
+
+/**
+ * \brief Read components from input and add them to components. Will read input stream till eof
+ * Substrings separated by slashes will become separate components
+ */
+std::istream &
+operator >> (std::istream &is, Batches &batch);
+
+} // namespace ns3
+
+#endif // _BATCHES_H_
diff --git a/wscript b/wscript
index e33af19..d4b9bc9 100644
--- a/wscript
+++ b/wscript
@@ -80,6 +80,8 @@
 
         "model/rocketfuel-weights-reader.h",
         "model/annotated-topology-reader.h",
+
+        "model/batches.h"
         ]
 
     tests.source = bld.path.ant_glob('test/*.cc');