Repair two critical bug with Interest/NACK processing

- There was wrong selection of FIB face order in CcnxForwardingStrategy
- Stop reacting on NACK if there are no incoming faces (i.e., loop
  detected after interest is already satisfied)
diff --git a/model/ccnx-face.cc b/model/ccnx-face.cc
index 92bdfee..40ac57b 100644
--- a/model/ccnx-face.cc
+++ b/model/ccnx-face.cc
@@ -26,6 +26,8 @@
 #include "ns3/node.h"
 #include "ns3/assert.h"
 
+#include <boost/ref.hpp>
+
 NS_LOG_COMPONENT_DEFINE ("CcnxFace");
 
 namespace ns3 {
@@ -127,7 +129,7 @@
 bool
 CcnxFace::Send (Ptr<Packet> packet)
 {
-  NS_LOG_FUNCTION_NOARGS ();
+  NS_LOG_FUNCTION (boost::cref (*this) << packet << packet->GetSize ());
 
   /// \todo Implement tracing, if requested
 
@@ -141,7 +143,7 @@
 bool
 CcnxFace::Receive (const Ptr<const Packet> &packet)
 {
-  NS_LOG_FUNCTION_NOARGS ();
+  NS_LOG_FUNCTION (boost::cref (*this) << packet << packet->GetSize ());
 
   /// \todo Implement tracing, if requested
 
diff --git a/model/ccnx-fib.cc b/model/ccnx-fib.cc
index e4e36d5..0df2ded 100644
--- a/model/ccnx-fib.cc
+++ b/model/ccnx-fib.cc
@@ -112,6 +112,8 @@
 void
 CcnxFibEntry::UpdateStatus (Ptr<CcnxFace> face, CcnxFibFaceMetric::Status status)
 {
+  NS_LOG_FUNCTION (this << boost::cref(*face) << status);
+
   CcnxFibFaceMetricByFace::type::iterator record = m_faces.get<i_face> ().find (face);
   NS_ASSERT_MSG (record != m_faces.get<i_face> ().end (),
                  "Update status can be performed only on existing faces of CcxnFibEntry");
diff --git a/model/ccnx-flooding-strategy.cc b/model/ccnx-flooding-strategy.cc
index f2add5f..4a8dd50 100644
--- a/model/ccnx-flooding-strategy.cc
+++ b/model/ccnx-flooding-strategy.cc
@@ -67,19 +67,25 @@
     return true;
 
   // boo... :(
-  
   int propagatedCount = 0;
 
   BOOST_FOREACH (const CcnxFibFaceMetric &metricFace, pitEntry.m_fibEntry.m_faces.get<i_metric> ())
     {
+      NS_LOG_DEBUG ("Trying " << boost::cref(metricFace));
       if (metricFace.m_status == CcnxFibFaceMetric::NDN_FIB_RED) // all non-read faces are in front
         break;
       
       if (metricFace.m_face == incomingFace) 
-        continue; // same face as incoming, don't forward
+        {
+          NS_LOG_DEBUG ("continue (same as incoming)");
+          continue; // same face as incoming, don't forward
+        }
 
       if (pitEntry.m_incoming.find (metricFace.m_face) != pitEntry.m_incoming.end ()) 
-        continue; // don't forward to face that we received interest from
+        {
+          NS_LOG_DEBUG ("continue (same as previous incoming)");
+          continue; // don't forward to face that we received interest from
+        }
 
       CcnxPitEntryOutgoingFaceContainer::type::iterator outgoing =
         pitEntry.m_outgoing.find (metricFace.m_face);
@@ -87,8 +93,10 @@
       if (outgoing != pitEntry.m_outgoing.end () &&
           outgoing->m_retxCount >= pitEntry.m_maxRetxCount)
         {
+          NS_LOG_DEBUG ("continue (same as previous outgoing)");
           continue; // already forwarded before during this retransmission cycle
         }
+      NS_LOG_DEBUG ("max retx count: " << pitEntry.m_maxRetxCount);
 
       bool faceAvailable = metricFace.m_face->IsBelowLimit ();
       if (!faceAvailable) // huh...
diff --git a/model/ccnx-forwarding-strategy.cc b/model/ccnx-forwarding-strategy.cc
index 869e424..4a1c3a8 100644
--- a/model/ccnx-forwarding-strategy.cc
+++ b/model/ccnx-forwarding-strategy.cc
@@ -36,6 +36,8 @@
 
 namespace ns3 {
 
+using namespace __ccnx_private;
+
 NS_OBJECT_ENSURE_REGISTERED (CcnxForwardingStrategy);
 
 TypeId CcnxForwardingStrategy::GetTypeId (void)
@@ -67,11 +69,11 @@
                                                    Ptr<CcnxInterestHeader> &header,
                                                    const Ptr<const Packet> &packet)
 {
-  NS_LOG_FUNCTION (this);
+  // NS_LOG_FUNCTION (this);
 
   int propagatedCount = 0;
   
-  BOOST_FOREACH (const CcnxFibFaceMetric &metricFace, pitEntry.m_fibEntry.m_faces)
+  BOOST_FOREACH (const CcnxFibFaceMetric &metricFace, pitEntry.m_fibEntry.m_faces.get<i_metric> ())
     {
       if (metricFace.m_status == CcnxFibFaceMetric::NDN_FIB_RED ||
           metricFace.m_status == CcnxFibFaceMetric::NDN_FIB_YELLOW)
@@ -105,6 +107,13 @@
       break; // propagate only one interest
     }
 
+  // if (Simulator::GetContext ()==1)
+  //   {
+  //     if (propagatedCount > 0)
+  //       NS_LOG_DEBUG ("Propagate via a green face");
+  //     else 
+  //       NS_LOG_DEBUG ("Can't :(");
+  //   }
   return propagatedCount > 0;
 }
 
diff --git a/model/ccnx-interest-header.h b/model/ccnx-interest-header.h
index d93b42a..979dfdd 100644
--- a/model/ccnx-interest-header.h
+++ b/model/ccnx-interest-header.h
@@ -205,9 +205,9 @@
   enum
     {
       NORMAL_INTEREST = 0,
-      NACK_LOOP = 1,
-      NACK_CONGESTION,
-      NACK_GIVEUP_PIT,
+      NACK_LOOP = 10,
+      NACK_CONGESTION = 11,
+      NACK_GIVEUP_PIT = 12,
     };
 
   void
diff --git a/model/ccnx-l3-protocol.cc b/model/ccnx-l3-protocol.cc
index 7fb9aab..17dc335 100644
--- a/model/ccnx-l3-protocol.cc
+++ b/model/ccnx-l3-protocol.cc
@@ -303,7 +303,6 @@
   if (isNew || !isDuplicated) // potential flow
     {
       // somebody is doing something bad
-      NS_ASSERT (false); // temporary assert
       return;
     }
   
@@ -324,6 +323,8 @@
   //
   // incomingFace->LeakBucketByOnePacket ();
 
+  NS_LOG_ERROR ("Nack on " << boost::cref(*incomingFace));
+
   m_pit->modify (m_pit->iterator_to (pitEntry),
                  ll::bind (&CcnxPitEntry::SetWaitingInVain, ll::_1, outFace));
   
@@ -342,8 +343,15 @@
                  ll::bind (&CcnxFibEntry::UpdateStatus,
                            ll::_1, incomingFace, CcnxFibFaceMetric::NDN_FIB_YELLOW));
 
+  if (pitEntry.m_incoming.size () == 0) // interest was actually satisfied
+    {
+      // no need to do anything
+      return;
+    }
+
   if (!pitEntry.AreAllOutgoingInVain ()) // not all ougtoing are in vain
     {
+      NS_LOG_DEBUG ("Not all outgoing are in vain");
       // suppress
       // Don't do anything, we are still expecting data from some other face
       return;
@@ -358,11 +366,11 @@
   bool propagated = m_forwardingStrategy->
     PropagateInterest (pitEntry, incomingFace, header, nonNackInterest);
 
-  // ForwardingStrategy will try its best to forward packet to at least one interface.
-  // If no interests was propagated, then there is not other option for forwarding or
-  // ForwardingStrategy failed to find it. 
+  // // ForwardingStrategy will try its best to forward packet to at least one interface.
+  // // If no interests was propagated, then there is not other option for forwarding or
+  // // ForwardingStrategy failed to find it. 
   if (!propagated)
-    GiveUpInterest (pitEntry, header);
+     GiveUpInterest (pitEntry, header);
 }
 
 // Processing Interests
@@ -393,11 +401,12 @@
       // //Trace duplicate interest  
       // m_droppedInterestsTrace (header, NDN_DUPLICATE_INTEREST, m_node->GetObject<Ccnx> (), incomingFace);
 
+      NS_LOG_DEBUG ("Sending NACK_LOOP");
       header->SetNack (CcnxInterestHeader::NACK_LOOP);
-      Ptr<Packet> packet = Create<Packet> ();
-      packet->AddHeader (*header);
+      Ptr<Packet> nack = Create<Packet> ();
+      nack->AddHeader (*header);
 
-      incomingFace->Send (packet);
+      incomingFace->Send (nack);
       
       // //Trace duplicate interest  
       // m_droppedInterestsTrace (header, NDN_DUPLICATE_INTEREST, m_node->GetObject<Ccnx> (), incomingFace);
@@ -626,8 +635,7 @@
 void 
 CcnxL3Protocol::LeakBuckets ()
 {
-  NS_LOG_FUNCTION (this);
-  NS_LOG_ERROR ("Bucket Interval: " << m_bucketLeakInterval.ToDouble(Time::S));
+  // NS_LOG_FUNCTION (this);
 
   BOOST_FOREACH (const Ptr<CcnxFace> &face, m_faces)
     {
diff --git a/model/ccnx-net-device-face.cc b/model/ccnx-net-device-face.cc
index dff7694..468d8f1 100644
--- a/model/ccnx-net-device-face.cc
+++ b/model/ccnx-net-device-face.cc
@@ -95,6 +95,7 @@
                                          const Address &to,
                                          NetDevice::PacketType packetType)
 {
+  NS_LOG_FUNCTION (device << p << protocol << from << to << packetType);
   Receive (p);
 }
 
diff --git a/model/ccnx-pit-entry.cc b/model/ccnx-pit-entry.cc
index 5667c82..76c7997 100644
--- a/model/ccnx-pit-entry.cc
+++ b/model/ccnx-pit-entry.cc
@@ -106,6 +106,8 @@
 void
 CcnxPitEntry::SetWaitingInVain (CcnxPitEntryOutgoingFaceContainer::type::iterator face)
 {
+  NS_LOG_DEBUG (boost::cref (*face->m_face));
+
   m_outgoing.modify (face,
                      (&ll::_1)->*&CcnxPitEntryOutgoingFace::m_waitingInVain = true);
 }
@@ -113,6 +115,8 @@
 bool
 CcnxPitEntry::AreAllOutgoingInVain () const
 {
+  NS_LOG_DEBUG (m_outgoing.size ());
+
   bool inVain = true;
   std::for_each (m_outgoing.begin (), m_outgoing.end (),
                  ll::var(inVain) &= (&ll::_1)->*&CcnxPitEntryOutgoingFace::m_waitingInVain);