Checkpoint. Max bad/good ratio is 1:10. Unknown stats implies 50%. If
anything is in a queue, item will be taken from it (no matter what is
the service count)
diff --git a/model/fw/fw-stats.cc b/model/fw/fw-stats.cc
index 367ba14..3ff136e 100644
--- a/model/fw/fw-stats.cc
+++ b/model/fw/fw-stats.cc
@@ -222,6 +222,25 @@
   super::RemoveFace (face);
 }
 
+void
+FwStats::DidReceiveValidNack (Ptr<Face> inFace,
+                              uint32_t nackCode,
+                              Ptr<pit::Entry> pitEntry)
+{
+  m_stats.Satisfy (pitEntry->GetPrefix ().cut (1));
+  ScheduleRefreshingIfNecessary ();
+  
+  // m_stats.UndoNewPitEntry (header->GetName ().cut (1));
+  // m_stats.UndoOutgoing (header->GetName ().cut (1), inFace);
+
+  // for (pit::Enty::in_container::iterator item = pitEntry->GetIncoming ().begin ();
+  //      item != pitEntry->GetIncoming ().end ();
+  //      item ++)
+  //   {
+  //     m_stats.UndoIncoming (header->GetName ().cut (1), item->m_face);
+  //   }
+}
+
 
 } // namespace fw
 } // namespace ndn
diff --git a/model/fw/fw-stats.h b/model/fw/fw-stats.h
index a54642a..6ad7ff0 100644
--- a/model/fw/fw-stats.h
+++ b/model/fw/fw-stats.h
@@ -102,6 +102,11 @@
                                Ptr<const InterestHeader> header,
                                Ptr<const Packet> origPacket,
                                Ptr<pit::Entry> pitEntry);
+
+  virtual void
+  DidReceiveValidNack (Ptr<Face> inFace,
+                       uint32_t nackCode,
+                       Ptr<pit::Entry> pitEntry);
   
   // from Object
   void
diff --git a/model/fw/per-fib-limits.cc b/model/fw/per-fib-limits.cc
index ed41eeb..89d4cc4 100644
--- a/model/fw/per-fib-limits.cc
+++ b/model/fw/per-fib-limits.cc
@@ -139,11 +139,11 @@
   // const ndnSIM::LoadStatsFace &stats = GetStatsTree ()[header->GetName ()].incoming ().find (inFace)->second;
   const ndnSIM::LoadStatsFace &stats = GetStatsTree ()["/"].incoming ().find (inFace)->second;
   double weight = std::min (1.0, stats.GetSatisfiedRatio ().get<0> ());
-  if (weight < 0)
-    {
-      // if stats is unknown, gracefully accept interest with normal priority
-      weight = 1.0;
-    }
+  // if (weight < 0)
+  //   {
+  //     // if stats is unknown, gracefully accept interest with normal priority
+  //     weight = 1.0;
+  //   }
   
   bool enqueued = m_pitQueues[outFace].Enqueue (inFace, pitEntry, weight);
 
@@ -191,7 +191,7 @@
   //         face->m_face->Send (pkt->Copy ());
   //       }
   //   }
-  
+
   PitQueue::Remove (pitEntry);
   
   for (pit::Entry::out_container::iterator face = pitEntry->GetOutgoing ().begin ();
@@ -242,7 +242,12 @@
         {
           // now we have enqueued packet and have slot available. Send out delayed packet
           Ptr<pit::Entry> pitEntry = queue->second.Pop ();
-          NS_ASSERT_MSG (pitEntry != 0, "There *have to* be an entry in queue");
+          if (pitEntry == 0)
+            {
+              outFace->GetLimits ().RemoveOutstanding ();
+              NS_LOG_DEBUG ("Though there are Interests in queue, weighted round robin decided that packet is not allowed yet");
+              break;
+            }
 
           // hack
           // offset lifetime back, so PIT entry wouldn't prematurely expire
@@ -275,12 +280,14 @@
                                    uint32_t nackCode,
                                    Ptr<pit::Entry> pitEntry)
 {
+  super::DidReceiveValidNack (inFace, nackCode, pitEntry);
+  
   // NS_LOG_FUNCTION (this << pitEntry->GetPrefix ());
   PitQueue::Remove (pitEntry);
  
 
   Ptr<InterestHeader> nackHeader = Create<InterestHeader> (*pitEntry->GetInterest ());
-  nackHeader->SetNack (100);
+  // nackHeader->SetNack (100);
   Ptr<Packet> pkt = Create<Packet> ();
   pkt->AddHeader (*nackHeader);
 
diff --git a/utils/ndn-limits.cc b/utils/ndn-limits.cc
index d53e370..d1b19c7 100644
--- a/utils/ndn-limits.cc
+++ b/utils/ndn-limits.cc
@@ -149,6 +149,7 @@
       if (m_outstanding < value)
         {
           m_outstanding += 1.0;
+          // if (Simulator::GetContext () == 6) std::cout << "." << std::flush;
           return true;
         }
       else
@@ -166,6 +167,8 @@
 {
   if (!IsEnabled ()) return; //limits are disabled
   
+  // if (Simulator::GetContext () == 6) std::cout << "*" << std::flush;
+
   NS_LOG_DEBUG (m_outstanding);
   NS_ASSERT_MSG (m_outstanding >= 1, "Should not be possible, unless we decreasing this number twice somewhere");
   m_outstanding -= 1;
diff --git a/utils/ndn-pit-queue.cc b/utils/ndn-pit-queue.cc
index 0c7349f..ca0d755 100644
--- a/utils/ndn-pit-queue.cc
+++ b/utils/ndn-pit-queue.cc
@@ -35,7 +35,7 @@
 namespace ns3 {
 namespace ndn {
 
-const double MIN_WEIGHT = 0.01;
+const double MIN_WEIGHT = 0.1;
 
 PitQueue::PitQueue ()
   // : m_maxQueueSize (20)
@@ -61,6 +61,7 @@
 		   Ptr<pit::Entry> pitEntry,
                    double updatedWeight)
 {
+  if (updatedWeight < 0) updatedWeight = 0.5;
   if (updatedWeight < MIN_WEIGHT) updatedWeight = MIN_WEIGHT;
   
   PerInFaceQueue::iterator queue = m_queues.find (inFace);
@@ -101,9 +102,10 @@
   PerInFaceQueue::iterator queue = m_lastQueue;
 
   if (queue != m_queues.end () &&
-      true)
+      m_serviceCounter >= queue->second->get<2> ())
     {
-      queue ++; // actually implement round robin...
+      queue ++; // actually implement weighted round robin...
+      m_serviceCounter = 0;
     } 
 
   while (queue != m_queues.end () && queue->second->get<0> ().size () == 0) // advance iterator
@@ -124,11 +126,12 @@
       m_serviceCounter = 0;
     }
   
-  if (queue == m_queues.end ()) // e.g., begin () == end ()
-    return 0;
-
-  // if (Simulator::GetContext () == 7)
+  m_serviceCounter ++;
+  
+  // if (Simulator::GetContext () == 4)
   //   {
+  //     cout << "====== " << Simulator::Now ().ToDouble (Time::S) << "s " << *queue->first << endl;
+  //     cout << "       " << m_serviceCounter << " / " << queue->second->get<2> () << "\n";
   //     for (PerInFaceQueue::const_iterator somequeue = m_queues.begin ();
   //          somequeue != m_queues.end ();
   //          somequeue ++)
@@ -139,6 +142,9 @@
   //     cout << endl;
   //   }
 
+  if (queue == m_queues.end () || queue->second->get<0> ().size () == 0) 
+    return 0;
+  
   NS_ASSERT_MSG (queue->second->get<0> ().size () != 0, "Logic error");
 
   Ptr<pit::Entry> entry = *queue->second->get<0> ().begin ();
@@ -152,7 +158,7 @@
 #ifdef NS3_LOG_ENABLE
   NS_ASSERT_MSG (queue->second->get<0> ().size () == queueSize-1, "Queue size should be reduced by one");
 #endif
-    
+
   m_lastQueue = queue;
   return entry;
 }
@@ -235,8 +241,22 @@
        queue != m_queues.end ();
        queue ++)
     {
-      queue->second->get<2> () = static_cast<uint32_t>((queue->second->get<1> () + 0.5) / minWeight);
+      queue->second->get<2> () = static_cast<uint32_t>(queue->second->get<1> () / minWeight);
+      if (queue->second->get<2> () < 1)
+        queue->second->get<2> () = 1;
     }
+
+  // if (m_queues.size () > 1)
+  //   {
+  //     cout << "Node " << Simulator::GetContext () << " (min = " << minWeight << "): ";
+  //     for (PerInFaceQueue::const_iterator queue = m_queues.begin ();
+  //          queue != m_queues.end ();
+  //          queue ++)
+  //       {
+  //         cout << queue->second->get<1> () << "/" << queue->second->get<2> () << "  ";
+  //       }
+  //     cout << endl;
+  //   }
 }