Add NACK processing
diff --git a/examples/ccnx-grid.cc b/examples/ccnx-grid.cc
index 5c02746..e60e962 100644
--- a/examples/ccnx-grid.cc
+++ b/examples/ccnx-grid.cc
@@ -24,6 +24,7 @@
 #include "ns3/NDNabstraction-module.h"
 #include "ns3/point-to-point-grid.h"
 #include "ns3/ipv4-global-routing-helper.h"
+#include "ns3/netanim-module.h"
 
 #include <iostream>
 #include <sstream>
@@ -42,6 +43,22 @@
   Simulator::Schedule (Seconds (10.0), PrintTime);
 }
 
+void PrintFIBs ()
+{
+  NS_LOG_INFO ("Outputing FIBs into [fibs.log]");
+  Ptr<OutputStreamWrapper> routingStream = Create<OutputStreamWrapper> ("fibs.log", std::ios::out);
+  for (NodeList::Iterator node = NodeList::Begin ();
+       node != NodeList::End ();
+       node++)
+    {
+      *routingStream->GetStream () << "Node " << (*node)->GetId () << "\n";
+
+      Ptr<CcnxFib> fib = (*node)->GetObject<CcnxFib> ();
+      NS_ASSERT_MSG (fib != 0, "Fire alarm");
+      *routingStream->GetStream () << *fib << "\n\n";
+    }
+}
+
 int 
 main (int argc, char *argv[])
 {
@@ -52,11 +69,13 @@
   Packet::EnableChecking();
   Packet::EnablePrinting();
 
+  std::string animationFile = "";
   CommandLine cmd;
   cmd.AddValue ("nGrid", "Number of grid nodes", nGrid);
   cmd.AddValue ("finish", "Finish time", finishTime);
+  cmd.AddValue ("netanim", "NetAnim filename", animationFile);
   cmd.Parse (argc, argv);
-
+  
   PointToPointHelper p2p;
 
   InternetStackHelper stack;
@@ -103,30 +122,29 @@
   // producers.Start(Seconds(0.0));
   // producers.Stop(finishTime);
 
-  NS_LOG_INFO ("Outputing FIBs into [fibs.log]");
-  Ptr<OutputStreamWrapper> routingStream = Create<OutputStreamWrapper> ("fibs.log", std::ios::out);
-  for (NodeList::Iterator node = NodeList::Begin ();
-       node != NodeList::End ();
-       node++)
-    {
-      *routingStream->GetStream () << "Node " << (*node)->GetId () << "\n";
-
-      Ptr<CcnxFib> fib = (*node)->GetObject<CcnxFib> ();
-      NS_ASSERT_MSG (fib != 0, "Fire alarm");
-      *routingStream->GetStream () << *fib << "\n\n";
-    }
-
+  Simulator::Schedule (Seconds (1.0), PrintFIBs);
+  
   Simulator::Schedule (Seconds (10.0), PrintTime);
   
   // NS_LOG_INFO ("FIB dump:\n" << *c.Get(0)->GetObject<CcnxFib> ());
   // NS_LOG_INFO ("FIB dump:\n" << *c.Get(1)->GetObject<CcnxFib> ());
     
   Simulator::Stop (finishTime);
-    
+
+  AnimationInterface *anim = 0;
+  if (animationFile != "")
+    {
+      anim = new AnimationInterface (animationFile);
+      anim->SetMobilityPollInterval (Seconds (1));
+    }
+
   NS_LOG_INFO ("Run Simulation.");
   Simulator::Run ();
   Simulator::Destroy ();
   NS_LOG_INFO ("Done!");
-    
+
+  if (anim != 0)
+    delete anim;
+  
   return 0;
 }
diff --git a/model/ccnx-face.h b/model/ccnx-face.h
index 132ef36..397a5b0 100644
--- a/model/ccnx-face.h
+++ b/model/ccnx-face.h
@@ -175,6 +175,9 @@
    */
   inline void
   LeakBucket (const Time &interval);
+
+  inline void
+  LeakBucketByOnePacket ();
   
   /**
    * \brief Compare two faces. Only two faces on the same node could be compared.
@@ -252,6 +255,11 @@
   m_bucket -= std::max (0.0, m_bucket-leak); 
 }
 
+void
+CcnxFace::LeakBucketByOnePacket ()
+{
+  m_bucket -= std::max (0.0, m_bucket-1.0); 
+}
 
 } // namespace ns3
 
diff --git a/model/ccnx-interest-header.h b/model/ccnx-interest-header.h
index d7be5fe..d93b42a 100644
--- a/model/ccnx-interest-header.h
+++ b/model/ccnx-interest-header.h
@@ -207,6 +207,7 @@
       NORMAL_INTEREST = 0,
       NACK_LOOP = 1,
       NACK_CONGESTION,
+      NACK_GIVEUP_PIT,
     };
 
   void
diff --git a/model/ccnx-l3-protocol.cc b/model/ccnx-l3-protocol.cc
index e0e12c2..bba9ef9 100644
--- a/model/ccnx-l3-protocol.cc
+++ b/model/ccnx-l3-protocol.cc
@@ -287,58 +287,57 @@
 }
 
 void
-CcnxL3Protocol::OnNack (const Ptr<CcnxFace> &face,
+CcnxL3Protocol::OnNack (const Ptr<CcnxFace> &incomingFace,
                         Ptr<CcnxInterestHeader> &header,
-                        const Ptr<const Packet> &p)
+                        const Ptr<const Packet> &packet)
 {
-  NS_LOG_FUNCTION (face << header << p);
+  NS_LOG_FUNCTION (incomingFace << header << packet);
 
-  // Huh... Ignore all this for now
+  tuple<const CcnxPitEntry&,bool,bool> ret = m_pit->Lookup (*header);
+  CcnxPitEntry const& pitEntry = ret.get<0> ();
+  // bool isNew = ret.get<1> ();
+  bool isDuplicated = ret.get<2> ();
+
+  NS_ASSERT_MSG (isDuplicated,
+                 "NACK should be a duplicated interest");
   
-  /*if( header->IsCongested () == false )
-    m_pit->LeakBucket(incomingFace,1);
-        
-        
-    m_droppedInterestsTrace (header, DROP_CONGESTION,
-    m_node->GetObject<Ccnx> (), incomingFace);
-        
-    m_pit->modify(pitEntry, CcnxPitEntry::DeleteOutgoing(incomingFace));*/
+  // CcnxPitEntryIncomingFaceContainer::type::iterator inFace = pitEntry.m_incoming.find (incomingFace);
+  CcnxPitEntryOutgoingFaceContainer::type::iterator outFace = pitEntry.m_outgoing.find (incomingFace);
 
-  // No matter is it duplicate or not, if it is a NACK message, remove all possible incoming
-  // entries for this interface (NACK means that neighbor gave up trying and there is no
-  // point of sending data in this direction)
+  NS_ASSERT_MSG (outFace != pitEntry.m_outgoing.end (),
+                 "Outgoing entry should exist");
+
+  outFace->m_face->LeakBucketByOnePacket ();
+  // outFace->m_waitingInVain = true; // don't think that this is necessary
   
-  // NS_LOG_INFO("Before (header->IsNack()) && (pitEntry != m_pit->end ())");
-  // if ((header->IsNack()) && (pitEntry != m_pit->end ()))
-  //   {
-  //     //m_pit->erase (pitEntry);
-  //     NS_LOG_INFO("TRUE");
-  //     m_pit->modify(pitEntry, CcnxPitEntry::DeleteIncoming(incomingFace));
-  //   }
+  // m_droppedInterestsTrace (header, DROP_CONGESTION, m_node->GetObject<Ccnx> (), incomingFace);
 
-  //   m_fib->modify (m_fib->iterator_to (pitEntry->m_fibEntry),
-  // CcnxFibEntry::UpdateStatus(incomingFace, CcnxFibFaceMetric::NDN_FIB_YELLOW));
+  // If NACK is NACK_GIVEUP_PIT, then neighbor gave up trying to and removed it's PIT entry.
+  // So, if we had an incoming entry to this neighbor, then we can remove it now
 
-  // if (!pitEntry.AreThereMoreFacesToTry ())
-  //   {
-  //     BOOST_FOREACH (const CcnxPitEntryIncomingFace face, pitEntry.m_incoming)
-  //       {
-  //         // check all entries if the name of RIT entry matches the name of interest
-  //         for (CcnxRitByNonce::type::iterator it = m_rit->begin(); it != m_rit->end(); it++)
-  //           {
-  //             if (it->m_prefix == iter->GetPrefix() )
-  //               {
-  //                 header->SetNonce(it->m_nonce);
-  //                 header->SetNack(true);
-  //                 face.m_face->Send (packet->Copy());
-  //               }
-  //           }
-  //       }
+  if (header->GetNack () == CcnxInterestHeader::NACK_GIVEUP_PIT)
+    {
+      m_pit->modify (m_pit->iterator_to (pitEntry),
+                     ll::bind (&CcnxPitEntry::RemoveIncoming, ll::_1, incomingFace));
+    }
 
-  //     m_pit->erase(pitEntry);
+  m_fib->modify(m_fib->iterator_to (pitEntry.m_fibEntry),
+                ll::bind (&CcnxFibEntry::UpdateStatus,
+                          ll::_1, incomingFace, CcnxFibFaceMetric::NDN_FIB_YELLOW));
+  
+  NS_ASSERT_MSG (m_forwardingStrategy != 0, "Need a forwarding protocol object to process packets");
 
-  //     return;
-  //   }
+  Ptr<Packet> nonNackInterest = Create<Packet> ();
+  header->SetNack (CcnxInterestHeader::NORMAL_INTEREST);
+  nonNackInterest->AddHeader (*header);
+  
+  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. 
+  if (!propagated) GiveUpInterest (pitEntry, header);
 }
 
 // Processing Interests
@@ -454,30 +453,35 @@
   // 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)
-    {
-      Ptr<Packet> packet = Create<Packet> ();
-      header->SetNack (CcnxInterestHeader::NACK_CONGESTION);
-      packet->AddHeader (*header);
-
-      BOOST_FOREACH (const CcnxPitEntryIncomingFace &incoming, pitEntry.m_incoming)
-        {
-          incoming.m_face->Send (packet->Copy ());
-
-          // m_droppedInterestsTrace (header, DROP_CONGESTION,
-          //                          m_node->GetObject<Ccnx> (), incomingFace);
-        }
-      // All incoming interests cannot be satisfied. Remove them
-      m_pit->modify (m_pit->iterator_to (pitEntry),
-                     ll::bind (&CcnxPitEntry::ClearIncoming, ll::_1));
-
-      // Set pruning timout on PIT entry (instead of deleting the record)
-      m_pit->modify (m_pit->iterator_to (pitEntry),
-                     ll::bind (&CcnxPitEntry::SetExpireTime, ll::_1,
-                           Simulator::Now () + m_pit->GetPitEntryPruningTimeout ()));
-    }
+  if (!propagated) GiveUpInterest (pitEntry, header);
 }
 
+void
+CcnxL3Protocol::GiveUpInterest (const CcnxPitEntry &pitEntry,
+                                Ptr<CcnxInterestHeader> header)
+{
+  Ptr<Packet> packet = Create<Packet> ();
+  header->SetNack (CcnxInterestHeader::NACK_GIVEUP_PIT);
+  packet->AddHeader (*header);
+
+  BOOST_FOREACH (const CcnxPitEntryIncomingFace &incoming, pitEntry.m_incoming)
+    {
+      incoming.m_face->Send (packet->Copy ());
+
+      // m_droppedInterestsTrace (header, DROP_CONGESTION,
+      //                          m_node->GetObject<Ccnx> (), incomingFace);
+    }
+  // All incoming interests cannot be satisfied. Remove them
+  m_pit->modify (m_pit->iterator_to (pitEntry),
+                 ll::bind (&CcnxPitEntry::ClearIncoming, ll::_1));
+
+  // Set pruning timout on PIT entry (instead of deleting the record)
+  m_pit->modify (m_pit->iterator_to (pitEntry),
+                 ll::bind (&CcnxPitEntry::SetExpireTime, ll::_1,
+                           Simulator::Now () + m_pit->GetPitEntryPruningTimeout ()));
+}
+
+
 // Processing ContentObjects
 void
 CcnxL3Protocol::OnData (const Ptr<CcnxFace> &incomingFace,
diff --git a/model/ccnx-l3-protocol.h b/model/ccnx-l3-protocol.h
index 272a0be..f5c19d9 100644
--- a/model/ccnx-l3-protocol.h
+++ b/model/ccnx-l3-protocol.h
@@ -219,7 +219,12 @@
   GetBucketLeakInterval () const;
   
   /// \brief Periodically generate pre-calculated number of tokens (leak buckets)
-  void LeakBuckets( );
+  void
+  LeakBuckets ();
+
+  void
+  GiveUpInterest (const CcnxPitEntry &pitEntry,
+                  Ptr<CcnxInterestHeader> header);
 
 private:
   uint32_t m_faceCounter; ///< \brief counter of faces. Increased every time a new face is added to the stack
diff --git a/model/ccnx-pit-entry-outgoing-face.cc b/model/ccnx-pit-entry-outgoing-face.cc
index ccdfb08..c15df71 100644
--- a/model/ccnx-pit-entry-outgoing-face.cc
+++ b/model/ccnx-pit-entry-outgoing-face.cc
@@ -27,7 +27,7 @@
 CcnxPitEntryOutgoingFace::CcnxPitEntryOutgoingFace (Ptr<CcnxFace> face)
   : m_face (face)
   , m_sendTime (Simulator::Now ())
-  , m_retxNum (0)
+  // , m_retxNum (0)
   // , m_nonce (nonce)
   // , m_outstanding (true)
   // , m_waitingInVain (false)
diff --git a/model/ccnx-pit-entry-outgoing-face.h b/model/ccnx-pit-entry-outgoing-face.h
index 502f333..de1dd4b 100644
--- a/model/ccnx-pit-entry-outgoing-face.h
+++ b/model/ccnx-pit-entry-outgoing-face.h
@@ -38,10 +38,10 @@
   Time m_sendTime;          ///< \brief time when the first outgoing interest is sent (for RTT measurements)
                             ///< \todo handle problem of retransmitted interests... Probably, we should include something similar
                             ///<       to TimeStamp TCP option for retransmitted (i.e., only lost interests will suffer)
-  uint32_t m_retxNum;       ///< \brief number of retransmission
+  // uint32_t m_retxNum;       ///< \brief number of retransmission
   // int m_nonce;              ///< \brief nonce of the outgoing Interest
   // bool m_outstanding;		///< \brief flag to indicate that this interest is currently pending
-  // bool m_waitingInVain;		///< \brief when flag is set, we do not expect data for this interest, only a small hope that it will happen
+  // bool m_waitingInVain;     ///< \brief when flag is set, we do not expect data for this interest, only a small hope that it will happen
 	
 public:
   CcnxPitEntryOutgoingFace (Ptr<CcnxFace> face);
diff --git a/model/ccnx-pit-entry.cc b/model/ccnx-pit-entry.cc
index a4db50a..61b4fcc 100644
--- a/model/ccnx-pit-entry.cc
+++ b/model/ccnx-pit-entry.cc
@@ -49,6 +49,13 @@
   return ret.first;
 }
 
+void
+CcnxPitEntry::RemoveIncoming (Ptr<CcnxFace> face)
+{
+  m_incoming.erase (face);
+}
+
+
 CcnxPitEntryOutgoingFaceContainer::type::iterator
 CcnxPitEntry::AddOutgoing (Ptr<CcnxFace> face)
 {
diff --git a/model/ccnx-pit-entry.h b/model/ccnx-pit-entry.h
index 9f05e1e..bb42a6a 100644
--- a/model/ccnx-pit-entry.h
+++ b/model/ccnx-pit-entry.h
@@ -164,6 +164,12 @@
   AddIncoming (Ptr<CcnxFace> face);
 
   /**
+   * @brief Remove incoming entry for face `face`
+   */
+  void
+  RemoveIncoming (Ptr<CcnxFace> face);
+
+  /**
    * @brief Clear all incoming faces either after all of them were satisfied or NACKed
    */
   void
diff --git a/wscript b/wscript
index 3264657..77b33ad 100644
--- a/wscript
+++ b/wscript
@@ -30,7 +30,7 @@
 def build(bld):
     deps = ['core', 'network', 'point-to-point',
             'topology-read','internet','applications',
-            'point-to-point-layout']
+            'point-to-point-layout', 'netanim']
     if bld.env['ENABLE_PYTHON_BINDINGS']:
         deps.append ('visualizer')