model: Implementing two more events for forwarding strategy: DidAddFibEntry and WillRemoveFibEntry

Currently, only DidAddFibEntry method is used and only in PerFibLimits
strategy.  Change logic in global routing helper: set per FIB limits only if
forwarding strategy has created a corresponding Limit object.
diff --git a/helper/ndn-global-routing-helper.cc b/helper/ndn-global-routing-helper.cc
index f87dfa8..35ed56d 100644
--- a/helper/ndn-global-routing-helper.cc
+++ b/helper/ndn-global-routing-helper.cc
@@ -281,17 +281,13 @@
                                     << " with delay " << i->second.get<2> ());
                     
                       Ptr<fib::Entry> entry = fib->Add (prefix, i->second.get<0> (), i->second.get<1> ());
-                      Ptr<Limits> limits = i->second.get<0> ()->GetObject<Limits> ();
-                    
-                      if (limits != 0 && limits->IsEnabled ())
+                      Ptr<Limits> faceLimits = i->second.get<0> ()->GetObject<Limits> ();
+
+                      Ptr<Limits> fibLimits = entry->GetObject<Limits> ();
+                      if (fibLimits != 0)
                         {
-                          ObjectFactory limitsFactory;
-                          limitsFactory.SetTypeId (limits->GetInstanceTypeId ());
-
-                          Ptr<Limits> entryLimits = limitsFactory.Create<Limits> ();
-                          entryLimits->SetLimits (limits->GetMaxRate (), 2*i->second.get<2> ());
-
-                          entry->AggregateObject (entryLimits);
+                          // if it was created by the forwarding strategy via DidAddFibEntry event
+                          fibLimits->SetLimits (faceLimits->GetMaxRate (), 2*i->second.get<2> () /*exact RTT*/);
                         }
                     }
 		}
diff --git a/model/fib/ndn-fib-impl.cc b/model/fib/ndn-fib-impl.cc
index 30004b5..3fc29a4 100644
--- a/model/fib/ndn-fib-impl.cc
+++ b/model/fib/ndn-fib-impl.cc
@@ -22,6 +22,7 @@
 
 #include "ns3/ndn-face.h"
 #include "ns3/ndn-interest.h"
+#include "ns3/ndn-forwarding-strategy.h"
 
 #include "ns3/node.h"
 #include "ns3/assert.h"
@@ -107,7 +108,14 @@
   
       super::modify (result.first,
                      ll::bind (&Entry::AddOrUpdateRoutingMetric, ll::_1, face, metric));
-    
+
+      if (result.second)
+        {
+          // notify forwarding strategy about new FIB entry
+          NS_ASSERT (this->GetObject<ForwardingStrategy> () != 0);
+          this->GetObject<ForwardingStrategy> ()->DidAddFibEntry (result.first->payload ());
+        }
+      
       return result.first->payload ();
     }
   else
@@ -119,7 +127,16 @@
 {
   NS_LOG_FUNCTION (this->GetObject<Node> ()->GetId () << boost::cref(*prefix));
 
-  super::erase (*prefix);
+  super::iterator fibEntry = super::find_exact (*prefix);
+  if (fibEntry != super::end ())
+    {
+      // notify forwarding strategy about soon be removed FIB entry
+      NS_ASSERT (this->GetObject<ForwardingStrategy> () != 0);
+      this->GetObject<ForwardingStrategy> ()->WillRemoveFibEntry (fibEntry->payload ());
+
+      super::erase (fibEntry);
+    }
+  // else do nothing
 }
 
 // void
@@ -182,6 +199,10 @@
       
       if (trieNode->payload ()->m_faces.size () == 0)
         {
+          // notify forwarding strategy about soon be removed FIB entry
+          NS_ASSERT (this->GetObject<ForwardingStrategy> () != 0);
+          this->GetObject<ForwardingStrategy> ()->WillRemoveFibEntry (trieNode->payload ());
+          
           trieNode = super::parent_trie::recursive_iterator (trieNode->erase ());
         }
     }
diff --git a/model/fib/ndn-fib-impl.h b/model/fib/ndn-fib-impl.h
index 8dcd21e..f47a7d1 100644
--- a/model/fib/ndn-fib-impl.h
+++ b/model/fib/ndn-fib-impl.h
@@ -139,9 +139,6 @@
    */
   void
   RemoveFace (super::parent_trie &item, Ptr<Face> face);
-  
-private:
-  Ptr<Node> m_node;
 };
 
 } // namespace fib
diff --git a/model/fw/ndn-forwarding-strategy.cc b/model/fw/ndn-forwarding-strategy.cc
index b3e7940..4bab0a1 100644
--- a/model/fw/ndn-forwarding-strategy.cc
+++ b/model/fw/ndn-forwarding-strategy.cc
@@ -564,5 +564,18 @@
   // do nothing here
 }
 
+void
+ForwardingStrategy::DidAddFibEntry (Ptr<fib::Entry> fibEntry)
+{
+  // do nothing here
+}
+
+void
+ForwardingStrategy::WillRemoveFibEntry (Ptr<fib::Entry> fibEntry)
+{
+  // do nothing here
+}
+
+
 } // namespace ndn
 } // namespace ns3
diff --git a/model/fw/ndn-forwarding-strategy.h b/model/fw/ndn-forwarding-strategy.h
index d3b5c37..b838565 100644
--- a/model/fw/ndn-forwarding-strategy.h
+++ b/model/fw/ndn-forwarding-strategy.h
@@ -36,6 +36,7 @@
 namespace pit { class Entry; }
 class FibFaceMetric;
 class Fib;
+namespace fib { class Entry; }
 class ContentStore;
 
 /**
@@ -109,6 +110,20 @@
    */
   virtual void
   RemoveFace (Ptr<Face> face);
+
+  /**
+   * @brief Event fired every time a FIB entry is added to FIB
+   * @param fibEntry FIB entry that was added
+   */
+  virtual void
+  DidAddFibEntry (Ptr<fib::Entry> fibEntry);
+
+  /**
+   * @brief Fired just before FIB entry will be removed from FIB
+   * @param fibEntry FIB entry that will be removed
+   */
+  virtual void
+  WillRemoveFibEntry (Ptr<fib::Entry> fibEntry);
   
 protected:
   /**
diff --git a/model/fw/per-fib-limits.h b/model/fw/per-fib-limits.h
index 3632a87..47f9ee6 100644
--- a/model/fw/per-fib-limits.h
+++ b/model/fw/per-fib-limits.h
@@ -80,6 +80,19 @@
         exit (1);
       }
   }
+
+  /// \copydoc ForwardingStrategy::DidAddFibEntry
+  virtual void
+  DidAddFibEntry (Ptr<fib::Entry> fibEntry)
+  {
+    ObjectFactory factory;
+    factory.SetTypeId (fibEntry->m_faces.begin ()->m_face->GetObject<Limits> ()->GetInstanceTypeId ());
+    
+    Ptr<Limits> limits = factory.template Create<Limits> ();
+    fibEntry->AggregateObject (limits);
+
+    super::DidAddFibEntry (fibEntry);
+  }
   
 protected:
   /// \copydoc ForwardingStrategy::CanSendOutInterest
diff --git a/model/fw/per-out-face-limits.h b/model/fw/per-out-face-limits.h
index 534768b..2c4a935 100644
--- a/model/fw/per-out-face-limits.h
+++ b/model/fw/per-out-face-limits.h
@@ -133,10 +133,10 @@
 template<class Parent>
 bool
 PerOutFaceLimits<Parent>::CanSendOutInterest (Ptr<Face> inFace,
-                                          Ptr<Face> outFace,
-                                          Ptr<const InterestHeader> header,
-                                          Ptr<const Packet> origPacket,
-                                          Ptr<pit::Entry> pitEntry)
+                                              Ptr<Face> outFace,
+                                              Ptr<const InterestHeader> header,
+                                              Ptr<const Packet> origPacket,
+                                              Ptr<pit::Entry> pitEntry)
 {
   NS_LOG_FUNCTION (this << pitEntry->GetPrefix ());
   
diff --git a/utils/trie/trie-with-policy.h b/utils/trie/trie-with-policy.h
index 8afa6f8..08cb21c 100644
--- a/utils/trie/trie-with-policy.h
+++ b/utils/trie/trie-with-policy.h
@@ -116,6 +116,22 @@
     policy_.update (position);
     return true;
   }
+
+  /**
+   * @brief Find a node that has the exact match with the key
+   */
+  inline iterator
+  find_exact (const FullKey &key)
+  {
+    iterator foundItem, lastItem;
+    bool reachLast;
+    boost::tie (foundItem, reachLast, lastItem) = trie_.find (key);
+    
+    if (!reachLast || lastItem->payload () == PayloadTraits::empty_payload)
+      return end ();
+
+    return lastItem;
+  }
   
   /**
    * @brief Find a node that has the longest common prefix with key (FIB/PIT lookup)