fw: eliminate fibEntry in Strategy API

Strategy::lookupFib can be used to obtain FIB entry.
FIB lookup is skipped when strategy does not need it.

refs #3205

Change-Id: Icba67229cbc261d9def44ffa91461ea4b09982b2
diff --git a/daemon/fw/access-strategy.cpp b/daemon/fw/access-strategy.cpp
index 862e165..db8a192 100644
--- a/daemon/fw/access-strategy.cpp
+++ b/daemon/fw/access-strategy.cpp
@@ -49,16 +49,15 @@
 void
 AccessStrategy::afterReceiveInterest(const Face& inFace,
                                      const Interest& interest,
-                                     shared_ptr<fib::Entry> fibEntry,
                                      shared_ptr<pit::Entry> pitEntry)
 {
   RetxSuppression::Result suppressResult = m_retxSuppression.decide(inFace, interest, *pitEntry);
   switch (suppressResult) {
   case RetxSuppression::NEW:
-    this->afterReceiveNewInterest(inFace, interest, fibEntry, pitEntry);
+    this->afterReceiveNewInterest(inFace, interest, pitEntry);
     break;
   case RetxSuppression::FORWARD:
-    this->afterReceiveRetxInterest(inFace, interest, fibEntry, pitEntry);
+    this->afterReceiveRetxInterest(inFace, interest, pitEntry);
     break;
   case RetxSuppression::SUPPRESS:
     NFD_LOG_DEBUG(interest << " interestFrom " << inFace.getId() << " retx-suppress");
@@ -72,9 +71,9 @@
 void
 AccessStrategy::afterReceiveNewInterest(const Face& inFace,
                                         const Interest& interest,
-                                        shared_ptr<fib::Entry> fibEntry,
                                         shared_ptr<pit::Entry> pitEntry)
 {
+  const fib::Entry& fibEntry = this->lookupFib(*pitEntry);
   Name miName;
   shared_ptr<MtInfo> mi;
   std::tie(miName, mi) = this->findPrefixMeasurements(*pitEntry);
@@ -105,16 +104,16 @@
 void
 AccessStrategy::afterReceiveRetxInterest(const Face& inFace,
                                          const Interest& interest,
-                                         shared_ptr<fib::Entry> fibEntry,
                                          shared_ptr<pit::Entry> pitEntry)
 {
+  const fib::Entry& fibEntry = this->lookupFib(*pitEntry);
   NFD_LOG_DEBUG(interest << " interestFrom " << inFace.getId() << " retx-forward");
   this->multicast(pitEntry, fibEntry, {inFace.getId()});
 }
 
 bool
 AccessStrategy::sendToLastNexthop(const Face& inFace, shared_ptr<pit::Entry> pitEntry, MtInfo& mi,
-                                  shared_ptr<fib::Entry> fibEntry)
+                                  const fib::Entry& fibEntry)
 {
   if (mi.lastNexthop == face::INVALID_FACEID) {
     NFD_LOG_DEBUG(pitEntry->getInterest() << " no-last-nexthop");
@@ -127,7 +126,7 @@
   }
 
   shared_ptr<Face> face = this->getFace(mi.lastNexthop);
-  if (face == nullptr || !fibEntry->hasNextHop(face)) {
+  if (face == nullptr || !fibEntry.hasNextHop(face)) {
     NFD_LOG_DEBUG(pitEntry->getInterest() << " last-nexthop-gone");
     return false;
   }
@@ -147,24 +146,20 @@
   shared_ptr<PitInfo> pi = pitEntry->getOrCreateStrategyInfo<PitInfo>();
   pi->rtoTimer = scheduler::schedule(rto,
       bind(&AccessStrategy::afterRtoTimeout, this, weak_ptr<pit::Entry>(pitEntry),
-           weak_ptr<fib::Entry>(fibEntry), inFace.getId(), mi.lastNexthop));
+           inFace.getId(), mi.lastNexthop));
 
   return true;
 }
 
 void
-AccessStrategy::afterRtoTimeout(weak_ptr<pit::Entry> pitWeak, weak_ptr<fib::Entry> fibWeak,
+AccessStrategy::afterRtoTimeout(weak_ptr<pit::Entry> pitWeak,
                                 FaceId inFace, FaceId firstOutFace)
 {
   shared_ptr<pit::Entry> pitEntry = pitWeak.lock();
   BOOST_ASSERT(pitEntry != nullptr);
   // pitEntry can't become nullptr, because RTO timer should be cancelled upon pitEntry destruction
 
-  shared_ptr<fib::Entry> fibEntry = fibWeak.lock();
-  if (fibEntry == nullptr) {
-    NFD_LOG_DEBUG(pitEntry->getInterest() << " timeoutFrom " << firstOutFace << " fib-gone");
-    return;
-  }
+  const fib::Entry& fibEntry = this->lookupFib(*pitEntry);
 
   NFD_LOG_DEBUG(pitEntry->getInterest() << " timeoutFrom " << firstOutFace <<
                 " multicast-except " << inFace << ',' << firstOutFace);
@@ -172,10 +167,10 @@
 }
 
 void
-AccessStrategy::multicast(shared_ptr<pit::Entry> pitEntry, shared_ptr<fib::Entry> fibEntry,
+AccessStrategy::multicast(shared_ptr<pit::Entry> pitEntry, const fib::Entry& fibEntry,
                           std::unordered_set<FaceId> exceptFaces)
 {
-  for (const fib::NextHop& nexthop : fibEntry->getNextHops()) {
+  for (const fib::NextHop& nexthop : fibEntry.getNextHops()) {
     shared_ptr<Face> face = nexthop.getFace();
     if (exceptFaces.count(face->getId()) > 0) {
       continue;
diff --git a/daemon/fw/access-strategy.hpp b/daemon/fw/access-strategy.hpp
index 2df13ad..ca7a2e3 100644
--- a/daemon/fw/access-strategy.hpp
+++ b/daemon/fw/access-strategy.hpp
@@ -58,7 +58,6 @@
   virtual void
   afterReceiveInterest(const Face& inFace,
                        const Interest& interest,
-                       shared_ptr<fib::Entry> fibEntry,
                        shared_ptr<pit::Entry> pitEntry) override;
 
   virtual void
@@ -130,13 +129,11 @@
   void
   afterReceiveNewInterest(const Face& inFace,
                           const Interest& interest,
-                          shared_ptr<fib::Entry> fibEntry,
                           shared_ptr<pit::Entry> pitEntry);
 
   void
   afterReceiveRetxInterest(const Face& inFace,
                            const Interest& interest,
-                           shared_ptr<fib::Entry> fibEntry,
                            shared_ptr<pit::Entry> pitEntry);
 
   /** \brief send to last working nexthop
@@ -144,18 +141,17 @@
    */
   bool
   sendToLastNexthop(const Face& inFace, shared_ptr<pit::Entry> pitEntry, MtInfo& mi,
-                    shared_ptr<fib::Entry> fibEntry);
+                    const fib::Entry& fibEntry);
 
   void
-  afterRtoTimeout(weak_ptr<pit::Entry> pitWeak, weak_ptr<fib::Entry> fibWeak,
-                  FaceId inFace, FaceId firstOutFace);
+  afterRtoTimeout(weak_ptr<pit::Entry> pitWeak, FaceId inFace, FaceId firstOutFace);
 
   /** \brief multicast to all nexthops
    *  \param exceptFaces don't forward to those faces
    */
   void
   multicast(shared_ptr<pit::Entry> pitEntry,
-            shared_ptr<fib::Entry> fibEntry,
+            const fib::Entry& fibEntry,
             std::unordered_set<FaceId> exceptFaces = std::unordered_set<FaceId>());
 
   void
diff --git a/daemon/fw/asf-probing-module.cpp b/daemon/fw/asf-probing-module.cpp
index 4be41f0..f561b52 100644
--- a/daemon/fw/asf-probing-module.cpp
+++ b/daemon/fw/asf-probing-module.cpp
@@ -45,9 +45,9 @@
 }
 
 void
-ProbingModule::scheduleProbe(shared_ptr<fib::Entry> fibEntry, const time::milliseconds& interval)
+ProbingModule::scheduleProbe(const fib::Entry& fibEntry, const time::milliseconds& interval)
 {
-  ndn::Name prefix = fibEntry->getPrefix();
+  ndn::Name prefix = fibEntry.getPrefix();
 
   // Set the probing flag for the namespace to true after passed interval of time
   scheduler::schedule(interval, [this, prefix] {
@@ -67,7 +67,7 @@
 shared_ptr<Face>
 ProbingModule::getFaceToProbe(const Face& inFace,
                               const Interest& interest,
-                              shared_ptr<fib::Entry> fibEntry,
+                              const fib::Entry& fibEntry,
                               const Face& faceUsed)
 {
   FaceInfoFacePairSet rankedFaces(
@@ -83,7 +83,7 @@
 
   // Put eligible faces into rankedFaces. If a face does not have an RTT measurement,
   // immediately pick the face for probing
-  for (const fib::NextHop& hop : fibEntry->getNextHops()) {
+  for (const fib::NextHop& hop : fibEntry.getNextHops()) {
     const shared_ptr<Face>& hopFace = hop.getFace();
 
     // Don't send probe Interest back to the incoming face or use the same face
@@ -92,7 +92,7 @@
       continue;
     }
 
-    FaceInfo* info = m_measurements.getFaceInfo(*fibEntry, interest, *hopFace);
+    FaceInfo* info = m_measurements.getFaceInfo(fibEntry, interest, *hopFace);
 
     // If no RTT has been recorded, probe this face
     if (info == nullptr || !info->hasSrttMeasurement()) {
@@ -112,10 +112,10 @@
 }
 
 bool
-ProbingModule::isProbingNeeded(shared_ptr<fib::Entry> fibEntry, const ndn::Interest& interest)
+ProbingModule::isProbingNeeded(const fib::Entry& fibEntry, const ndn::Interest& interest)
 {
   // Return the probing status flag for a namespace
-  NamespaceInfo& info = m_measurements.getOrCreateNamespaceInfo(*fibEntry, interest);
+  NamespaceInfo& info = m_measurements.getOrCreateNamespaceInfo(fibEntry, interest);
 
   // If a first probe has not been scheduled for a namespace
   if (!info.isFirstProbeScheduled()) {
@@ -130,11 +130,11 @@
 }
 
 void
-ProbingModule::afterForwardingProbe(shared_ptr<fib::Entry> fibEntry, const ndn::Interest& interest)
+ProbingModule::afterForwardingProbe(const fib::Entry& fibEntry, const ndn::Interest& interest)
 {
   // After probing is done, need to set probing flag to false and
   // schedule another future probe
-  NamespaceInfo& info = m_measurements.getOrCreateNamespaceInfo(*fibEntry, interest);
+  NamespaceInfo& info = m_measurements.getOrCreateNamespaceInfo(fibEntry, interest);
   info.setIsProbingDue(false);
 
   scheduleProbe(fibEntry, m_probingInterval);
diff --git a/daemon/fw/asf-probing-module.hpp b/daemon/fw/asf-probing-module.hpp
index a10b1f8..585b76a 100644
--- a/daemon/fw/asf-probing-module.hpp
+++ b/daemon/fw/asf-probing-module.hpp
@@ -41,19 +41,19 @@
   ProbingModule(AsfMeasurements& measurements);
 
   void
-  scheduleProbe(shared_ptr<fib::Entry> fibEntry, const time::milliseconds& interval);
+  scheduleProbe(const fib::Entry& fibEntry, const time::milliseconds& interval);
 
   shared_ptr<Face>
   getFaceToProbe(const Face& inFace,
                  const Interest& interest,
-                 shared_ptr<fib::Entry> fibEntry,
+                 const fib::Entry& fibEntry,
                  const Face& faceUsed);
 
   bool
-  isProbingNeeded(shared_ptr<fib::Entry> fibEntry, const ndn::Interest& interest);
+  isProbingNeeded(const fib::Entry& fibEntry, const ndn::Interest& interest);
 
   void
-  afterForwardingProbe(shared_ptr<fib::Entry> fibEntry, const ndn::Interest& interest);
+  afterForwardingProbe(const fib::Entry& fibEntry, const ndn::Interest& interest);
 
 private:
   // Used to associate FaceInfo with the face in a NextHop
diff --git a/daemon/fw/asf-strategy.cpp b/daemon/fw/asf-strategy.cpp
index 6a45c7e..cf616e8 100644
--- a/daemon/fw/asf-strategy.cpp
+++ b/daemon/fw/asf-strategy.cpp
@@ -56,7 +56,6 @@
 void
 AsfStrategy::afterReceiveInterest(const Face& inFace,
                                   const Interest& interest,
-                                  shared_ptr<fib::Entry> fibEntry,
                                   shared_ptr<pit::Entry> pitEntry)
 {
   // Should the Interest be suppressed?
@@ -71,7 +70,8 @@
     return;
   }
 
-  const fib::NextHopList& nexthops = fibEntry->getNextHops();
+  const fib::Entry& fibEntry = this->lookupFib(*pitEntry);
+  const fib::NextHopList& nexthops = fibEntry.getNextHops();
 
   if (nexthops.size() == 0) {
     sendNoRouteNack(inFace, interest, pitEntry);
@@ -79,7 +79,7 @@
     return;
   }
 
-  const shared_ptr<Face> faceToUse = getBestFaceForForwarding(*fibEntry, interest, inFace);
+  const shared_ptr<Face> faceToUse = getBestFaceForForwarding(fibEntry, interest, inFace);
 
   if (faceToUse == nullptr) {
     sendNoRouteNack(inFace, interest, pitEntry);
@@ -87,18 +87,18 @@
     return;
   }
 
-  forwardInterest(interest, *fibEntry, pitEntry, faceToUse);
+  forwardInterest(interest, fibEntry, pitEntry, faceToUse);
 
   // If necessary, send probe
   if (m_probing.isProbingNeeded(fibEntry, interest)) {
     shared_ptr<Face> faceToProbe = m_probing.getFaceToProbe(inFace, interest, fibEntry, *faceToUse);
 
     if (faceToProbe != nullptr) {
-      NFD_LOG_TRACE("Sending probe for " << fibEntry->getPrefix()
+      NFD_LOG_TRACE("Sending probe for " << fibEntry.getPrefix()
                                          << " to FaceId: " << faceToProbe->getId());
 
       bool wantNewNonce = true;
-      forwardInterest(interest, *fibEntry, pitEntry, faceToProbe, wantNewNonce);
+      forwardInterest(interest, fibEntry, pitEntry, faceToProbe, wantNewNonce);
       m_probing.afterForwardingProbe(fibEntry, interest);
     }
   }
@@ -130,7 +130,6 @@
 
 void
 AsfStrategy::afterReceiveNack(const Face& inFace, const lp::Nack& nack,
-                              shared_ptr<fib::Entry> fibEntry,
                               shared_ptr<pit::Entry> pitEntry)
 {
   NFD_LOG_DEBUG("Nack for " << nack.getInterest() << " from=" << inFace.getId() << ": " << nack.getReason());
diff --git a/daemon/fw/asf-strategy.hpp b/daemon/fw/asf-strategy.hpp
index 1e028cc..cb50e01 100644
--- a/daemon/fw/asf-strategy.hpp
+++ b/daemon/fw/asf-strategy.hpp
@@ -54,7 +54,6 @@
   virtual void
   afterReceiveInterest(const Face& inFace,
                        const Interest& interest,
-                       shared_ptr<fib::Entry> fibEntry,
                        shared_ptr<pit::Entry> pitEntry) override;
 
   virtual void
@@ -63,7 +62,6 @@
 
   virtual void
   afterReceiveNack(const Face& inFace, const lp::Nack& nack,
-                   shared_ptr<fib::Entry> fibEntry,
                    shared_ptr<pit::Entry> pitEntry) override;
 
 private:
diff --git a/daemon/fw/best-route-strategy.cpp b/daemon/fw/best-route-strategy.cpp
index d6d9bb0..bae5262 100644
--- a/daemon/fw/best-route-strategy.cpp
+++ b/daemon/fw/best-route-strategy.cpp
@@ -44,7 +44,6 @@
 void
 BestRouteStrategy::afterReceiveInterest(const Face& inFace,
                                         const Interest& interest,
-                                        shared_ptr<fib::Entry> fibEntry,
                                         shared_ptr<pit::Entry> pitEntry)
 {
   if (hasPendingOutRecords(*pitEntry)) {
@@ -52,7 +51,8 @@
     return;
   }
 
-  const fib::NextHopList& nexthops = fibEntry->getNextHops();
+  const fib::Entry& fibEntry = this->lookupFib(*pitEntry);
+  const fib::NextHopList& nexthops = fibEntry.getNextHops();
   fib::NextHopList::const_iterator it = std::find_if(nexthops.begin(), nexthops.end(),
     [&pitEntry] (const fib::NextHop& nexthop) { return canForwardToLegacy(*pitEntry, *nexthop.getFace()); });
 
diff --git a/daemon/fw/best-route-strategy.hpp b/daemon/fw/best-route-strategy.hpp
index 6214f30..9480b96 100644
--- a/daemon/fw/best-route-strategy.hpp
+++ b/daemon/fw/best-route-strategy.hpp
@@ -53,7 +53,6 @@
   virtual void
   afterReceiveInterest(const Face& inFace,
                        const Interest& interest,
-                       shared_ptr<fib::Entry> fibEntry,
                        shared_ptr<pit::Entry> pitEntry) override;
 
 public:
diff --git a/daemon/fw/best-route-strategy2.cpp b/daemon/fw/best-route-strategy2.cpp
index 0644ba9..ef68175 100644
--- a/daemon/fw/best-route-strategy2.cpp
+++ b/daemon/fw/best-route-strategy2.cpp
@@ -106,13 +106,19 @@
 void
 BestRouteStrategy2::afterReceiveInterest(const Face& inFace,
                                          const Interest& interest,
-                                         shared_ptr<fib::Entry> fibEntry,
                                          shared_ptr<pit::Entry> pitEntry)
 {
-  const fib::NextHopList& nexthops = fibEntry->getNextHops();
+  RetxSuppression::Result suppression = m_retxSuppression.decide(inFace, interest, *pitEntry);
+  if (suppression == RetxSuppression::SUPPRESS) {
+    NFD_LOG_DEBUG(interest << " from=" << inFace.getId()
+                           << " suppressed");
+    return;
+  }
+
+  const fib::Entry& fibEntry = this->lookupFib(*pitEntry);
+  const fib::NextHopList& nexthops = fibEntry.getNextHops();
   fib::NextHopList::const_iterator it = nexthops.end();
 
-  RetxSuppression::Result suppression = m_retxSuppression.decide(inFace, interest, *pitEntry);
   if (suppression == RetxSuppression::NEW) {
     // forward to nexthop with lowest cost except downstream
     it = std::find_if(nexthops.begin(), nexthops.end(),
@@ -137,12 +143,6 @@
     return;
   }
 
-  if (suppression == RetxSuppression::SUPPRESS) {
-    NFD_LOG_DEBUG(interest << " from=" << inFace.getId()
-                           << " suppressed");
-    return;
-  }
-
   // find an unused upstream with lowest cost except downstream
   it = std::find_if(nexthops.begin(), nexthops.end(),
                     bind(&predicate_NextHop_eligible, pitEntry, _1, inFace.getId(),
@@ -186,7 +186,6 @@
 
 void
 BestRouteStrategy2::afterReceiveNack(const Face& inFace, const lp::Nack& nack,
-                                     shared_ptr<fib::Entry> fibEntry,
                                      shared_ptr<pit::Entry> pitEntry)
 {
   int nOutRecordsNotNacked = 0;
diff --git a/daemon/fw/best-route-strategy2.hpp b/daemon/fw/best-route-strategy2.hpp
index 0be6490..8c6a778 100644
--- a/daemon/fw/best-route-strategy2.hpp
+++ b/daemon/fw/best-route-strategy2.hpp
@@ -56,12 +56,10 @@
 
   virtual void
   afterReceiveInterest(const Face& inFace, const Interest& interest,
-                       shared_ptr<fib::Entry> fibEntry,
                        shared_ptr<pit::Entry> pitEntry) override;
 
   virtual void
   afterReceiveNack(const Face& inFace, const lp::Nack& nack,
-                   shared_ptr<fib::Entry> fibEntry,
                    shared_ptr<pit::Entry> pitEntry) override;
 
 public:
diff --git a/daemon/fw/broadcast-strategy.cpp b/daemon/fw/broadcast-strategy.cpp
index 3c40186..3a3249c 100644
--- a/daemon/fw/broadcast-strategy.cpp
+++ b/daemon/fw/broadcast-strategy.cpp
@@ -1,6 +1,6 @@
 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
 /**
- * Copyright (c) 2014-2015,  Regents of the University of California,
+ * Copyright (c) 2014-2016,  Regents of the University of California,
  *                           Arizona Board of Regents,
  *                           Colorado State University,
  *                           University Pierre & Marie Curie, Sorbonne University,
@@ -42,7 +42,6 @@
 void
 BroadcastStrategy::afterReceiveInterest(const Face& inFace,
                    const Interest& interest,
-                   shared_ptr<fib::Entry> fibEntry,
                    shared_ptr<pit::Entry> pitEntry)
 {
   if (m_isFirstUse) {
@@ -51,7 +50,7 @@
     m_isFirstUse = false;
   }
 
-  this->MulticastStrategy::afterReceiveInterest(inFace, interest, fibEntry, pitEntry);
+  this->MulticastStrategy::afterReceiveInterest(inFace, interest, pitEntry);
 }
 
 } // namespace fw
diff --git a/daemon/fw/broadcast-strategy.hpp b/daemon/fw/broadcast-strategy.hpp
index bbfd0c6..1f868b5 100644
--- a/daemon/fw/broadcast-strategy.hpp
+++ b/daemon/fw/broadcast-strategy.hpp
@@ -42,7 +42,6 @@
   virtual void
   afterReceiveInterest(const Face& inFace,
                        const Interest& interest,
-                       shared_ptr<fib::Entry> fibEntry,
                        shared_ptr<pit::Entry> pitEntry) override;
 
 public:
diff --git a/daemon/fw/client-control-strategy.cpp b/daemon/fw/client-control-strategy.cpp
index 1066efa..044e065 100644
--- a/daemon/fw/client-control-strategy.cpp
+++ b/daemon/fw/client-control-strategy.cpp
@@ -1,6 +1,6 @@
 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
 /**
- * Copyright (c) 2014-2015,  Regents of the University of California,
+ * Copyright (c) 2014-2016,  Regents of the University of California,
  *                           Arizona Board of Regents,
  *                           Colorado State University,
  *                           University Pierre & Marie Curie, Sorbonne University,
@@ -47,12 +47,11 @@
 void
 ClientControlStrategy::afterReceiveInterest(const Face& inFace,
                                             const Interest& interest,
-                                            shared_ptr<fib::Entry> fibEntry,
                                             shared_ptr<pit::Entry> pitEntry)
 {
   shared_ptr<lp::NextHopFaceIdTag> tag = interest.getTag<lp::NextHopFaceIdTag>();
   if (tag == nullptr) {
-    this->BestRouteStrategy::afterReceiveInterest(inFace, interest, fibEntry, pitEntry);
+    this->BestRouteStrategy::afterReceiveInterest(inFace, interest, pitEntry);
     return;
   }
 
diff --git a/daemon/fw/client-control-strategy.hpp b/daemon/fw/client-control-strategy.hpp
index 402b54f..2a3bbb2 100644
--- a/daemon/fw/client-control-strategy.hpp
+++ b/daemon/fw/client-control-strategy.hpp
@@ -48,7 +48,6 @@
   virtual void
   afterReceiveInterest(const Face& inFace,
                        const Interest& interest,
-                       shared_ptr<fib::Entry> fibEntry,
                        shared_ptr<pit::Entry> pitEntry) override;
 
 public:
diff --git a/daemon/fw/forwarder.cpp b/daemon/fw/forwarder.cpp
index adcb134..3bb580d 100644
--- a/daemon/fw/forwarder.cpp
+++ b/daemon/fw/forwarder.cpp
@@ -187,12 +187,8 @@
   this->setUnsatisfyTimer(pitEntry);
 
   // dispatch to strategy: after incoming Interest
-  const fib::Entry& fibEntry = this->lookupFib(*pitEntry);
-  shared_ptr<fib::Entry> fibEntryP = const_cast<fib::Entry&>(fibEntry).shared_from_this();
   this->dispatchToStrategy(pitEntry,
-    [&] (fw::Strategy* strategy) {
-      strategy->afterReceiveInterest(inFace, interest, fibEntryP, pitEntry);
-    });
+    [&] (fw::Strategy* strategy) { strategy->afterReceiveInterest(inFace, interest, pitEntry); });
 }
 
 void
@@ -469,12 +465,8 @@
   outRecord->setIncomingNack(nack);
 
   // trigger strategy: after receive NACK
-  const fib::Entry& fibEntry = this->lookupFib(*pitEntry);
-  shared_ptr<fib::Entry> fibEntryP = const_cast<fib::Entry&>(fibEntry).shared_from_this();
   this->dispatchToStrategy(pitEntry,
-    [&] (fw::Strategy* strategy) {
-      strategy->afterReceiveNack(inFace, nack, fibEntryP, pitEntry);
-    });
+    [&] (fw::Strategy* strategy) { strategy->afterReceiveNack(inFace, nack, pitEntry); });
 }
 
 void
diff --git a/daemon/fw/multicast-strategy.cpp b/daemon/fw/multicast-strategy.cpp
index 3c92130..9b89049 100644
--- a/daemon/fw/multicast-strategy.cpp
+++ b/daemon/fw/multicast-strategy.cpp
@@ -40,10 +40,10 @@
 void
 MulticastStrategy::afterReceiveInterest(const Face& inFace,
                                         const Interest& interest,
-                                        shared_ptr<fib::Entry> fibEntry,
                                         shared_ptr<pit::Entry> pitEntry)
 {
-  const fib::NextHopList& nexthops = fibEntry->getNextHops();
+  const fib::Entry& fibEntry = this->lookupFib(*pitEntry);
+  const fib::NextHopList& nexthops = fibEntry.getNextHops();
 
   for (fib::NextHopList::const_iterator it = nexthops.begin(); it != nexthops.end(); ++it) {
     shared_ptr<Face> outFace = it->getFace();
diff --git a/daemon/fw/multicast-strategy.hpp b/daemon/fw/multicast-strategy.hpp
index ef3ba16..1330186 100644
--- a/daemon/fw/multicast-strategy.hpp
+++ b/daemon/fw/multicast-strategy.hpp
@@ -41,7 +41,6 @@
   virtual void
   afterReceiveInterest(const Face& inFace,
                        const Interest& interest,
-                       shared_ptr<fib::Entry> fibEntry,
                        shared_ptr<pit::Entry> pitEntry) override;
 
 public:
diff --git a/daemon/fw/ncc-strategy.cpp b/daemon/fw/ncc-strategy.cpp
index c096fe1..a459552 100644
--- a/daemon/fw/ncc-strategy.cpp
+++ b/daemon/fw/ncc-strategy.cpp
@@ -50,10 +50,10 @@
 void
 NccStrategy::afterReceiveInterest(const Face& inFace,
                                   const Interest& interest,
-                                  shared_ptr<fib::Entry> fibEntry,
                                   shared_ptr<pit::Entry> pitEntry)
 {
-  const fib::NextHopList& nexthops = fibEntry->getNextHops();
+  const fib::Entry& fibEntry = this->lookupFib(*pitEntry);
+  const fib::NextHopList& nexthops = fibEntry.getNextHops();
   if (nexthops.size() == 0) {
     this->rejectPendingInterest(pitEntry);
     return;
@@ -74,7 +74,7 @@
   size_t nUpstreams = nexthops.size();
 
   shared_ptr<Face> bestFace = measurementsEntryInfo->getBestFace();
-  if (static_cast<bool>(bestFace) && fibEntry->hasNextHop(bestFace) &&
+  if (bestFace != nullptr && fibEntry.hasNextHop(bestFace) &&
       canForwardToLegacy(*pitEntry, *bestFace)) {
     // TODO Should we use `randlow = 100 + nrand48(h->seed) % 4096U;` ?
     deferFirst = measurementsEntryInfo->prediction;
@@ -97,7 +97,7 @@
   }
 
   shared_ptr<Face> previousFace = measurementsEntryInfo->previousFace.lock();
-  if (static_cast<bool>(previousFace) && fibEntry->hasNextHop(previousFace) &&
+  if (previousFace != nullptr && fibEntry.hasNextHop(previousFace) &&
       canForwardToLegacy(*pitEntry, *previousFace)) {
     --nUpstreams;
   }
@@ -114,36 +114,33 @@
   }
   pitEntryInfo->propagateTimer = scheduler::schedule(deferFirst,
     bind(&NccStrategy::doPropagate, this,
-         weak_ptr<pit::Entry>(pitEntry), weak_ptr<fib::Entry>(fibEntry)));
+         weak_ptr<pit::Entry>(pitEntry)));
 }
 
 void
-NccStrategy::doPropagate(weak_ptr<pit::Entry> pitEntryWeak, weak_ptr<fib::Entry> fibEntryWeak)
+NccStrategy::doPropagate(weak_ptr<pit::Entry> pitEntryWeak)
 {
   shared_ptr<pit::Entry> pitEntry = pitEntryWeak.lock();
-  if (!static_cast<bool>(pitEntry)) {
+  if (pitEntry == nullptr) {
     return;
   }
-  shared_ptr<fib::Entry> fibEntry = fibEntryWeak.lock();
-  if (!static_cast<bool>(fibEntry)) {
-    return;
-  }
+  const fib::Entry& fibEntry = this->lookupFib(*pitEntry);
 
   shared_ptr<PitEntryInfo> pitEntryInfo = pitEntry->getStrategyInfo<PitEntryInfo>();
   // pitEntryInfo is guaranteed to exist here, because doPropagate is triggered
   // from a timer set by NccStrategy.
-  BOOST_ASSERT(static_cast<bool>(pitEntryInfo));
+  BOOST_ASSERT(pitEntryInfo != nullptr);
 
   shared_ptr<MeasurementsEntryInfo> measurementsEntryInfo =
     this->getMeasurementsEntryInfo(pitEntry);
 
   shared_ptr<Face> previousFace = measurementsEntryInfo->previousFace.lock();
-  if (static_cast<bool>(previousFace) && fibEntry->hasNextHop(previousFace) &&
+  if (previousFace != nullptr && fibEntry.hasNextHop(previousFace) &&
       canForwardToLegacy(*pitEntry, *previousFace)) {
     this->sendInterest(pitEntry, previousFace);
   }
 
-  const fib::NextHopList& nexthops = fibEntry->getNextHops();
+  const fib::NextHopList& nexthops = fibEntry.getNextHops();
   bool isForwarded = false;
   for (fib::NextHopList::const_iterator it = nexthops.begin(); it != nexthops.end(); ++it) {
     shared_ptr<Face> face = it->getFace();
@@ -160,7 +157,7 @@
     time::nanoseconds deferNext = time::nanoseconds(dist(getGlobalRng()));
     pitEntryInfo->propagateTimer = scheduler::schedule(deferNext,
     bind(&NccStrategy::doPropagate, this,
-         weak_ptr<pit::Entry>(pitEntry), weak_ptr<fib::Entry>(fibEntry)));
+         weak_ptr<pit::Entry>(pitEntry)));
   }
 }
 
diff --git a/daemon/fw/ncc-strategy.hpp b/daemon/fw/ncc-strategy.hpp
index 9e58494..bfbb06d 100644
--- a/daemon/fw/ncc-strategy.hpp
+++ b/daemon/fw/ncc-strategy.hpp
@@ -44,7 +44,6 @@
   virtual void
   afterReceiveInterest(const Face& inFace,
                        const Interest& interest,
-                       shared_ptr<fib::Entry> fibEntry,
                        shared_ptr<pit::Entry> pitEntry) override;
 
   virtual void
@@ -126,7 +125,7 @@
 
   /// propagate to another upstream
   void
-  doPropagate(weak_ptr<pit::Entry> pitEntryWeak, weak_ptr<fib::Entry> fibEntryWeak);
+  doPropagate(weak_ptr<pit::Entry> pitEntryWeak);
 
   /// best face did not reply within prediction
   void
diff --git a/daemon/fw/strategy.cpp b/daemon/fw/strategy.cpp
index e0dca89..2a40517 100644
--- a/daemon/fw/strategy.cpp
+++ b/daemon/fw/strategy.cpp
@@ -62,7 +62,7 @@
 
 void
 Strategy::afterReceiveNack(const Face& inFace, const lp::Nack& nack,
-                           shared_ptr<fib::Entry> fibEntry, shared_ptr<pit::Entry> pitEntry)
+                           shared_ptr<pit::Entry> pitEntry)
 {
   NFD_LOG_DEBUG("afterReceiveNack inFace=" << inFace.getId() <<
                 " pitEntry=" << pitEntry->getName());
diff --git a/daemon/fw/strategy.hpp b/daemon/fw/strategy.hpp
index 8ce9850..3a11568 100644
--- a/daemon/fw/strategy.hpp
+++ b/daemon/fw/strategy.hpp
@@ -1,6 +1,6 @@
 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
 /**
- * Copyright (c) 2014-2015,  Regents of the University of California,
+ * Copyright (c) 2014-2016,  Regents of the University of California,
  *                           Arizona Board of Regents,
  *                           Colorado State University,
  *                           University Pierre & Marie Curie, Sorbonne University,
@@ -69,16 +69,11 @@
    *  - If strategy concludes that this Interest cannot be forwarded,
    *    invoke this->rejectPendingInterest so that PIT entry will be deleted shortly
    *
-   *  \note The strategy is permitted to store a weak reference to fibEntry.
-   *        Do not store a shared reference, because FIB entry may be deleted at any moment.
-   *        fibEntry is passed by value to allow obtaining a weak reference from it.
    *  \note The strategy is permitted to store a shared reference to pitEntry.
    *        pitEntry is passed by value to reflect this fact.
    */
   virtual void
-  afterReceiveInterest(const Face& inFace,
-                       const Interest& interest,
-                       shared_ptr<fib::Entry> fibEntry,
+  afterReceiveInterest(const Face& inFace, const Interest& interest,
                        shared_ptr<pit::Entry> pitEntry) = 0;
 
   /** \brief trigger before PIT entry is satisfied
@@ -120,15 +115,12 @@
    *
    *  In this base class this method does nothing.
    *
-   *  \note The strategy is permitted to store a weak reference to fibEntry.
-   *        Do not store a shared reference, because PIT entry may be deleted at any moment.
-   *        fibEntry is passed by value to allow obtaining a weak reference from it.
    *  \note The strategy is permitted to store a shared reference to pitEntry.
    *        pitEntry is passed by value to reflect this fact.
    */
   virtual void
   afterReceiveNack(const Face& inFace, const lp::Nack& nack,
-                   shared_ptr<fib::Entry> fibEntry, shared_ptr<pit::Entry> pitEntry);
+                   shared_ptr<pit::Entry> pitEntry);
 
 protected: // actions
   /** \brief send Interest to outFace
@@ -173,6 +165,9 @@
             std::initializer_list<const Face*> exceptFaces = std::initializer_list<const Face*>());
 
 protected: // accessors
+  const fib::Entry&
+  lookupFib(const pit::Entry& pitEntry);
+
   MeasurementsAccessor&
   getMeasurements();
 
@@ -225,6 +220,12 @@
   m_forwarder.onOutgoingNack(pitEntry, outFace, header);
 }
 
+inline const fib::Entry&
+Strategy::lookupFib(const pit::Entry& pitEntry)
+{
+  return m_forwarder.lookupFib(pitEntry);
+}
+
 inline MeasurementsAccessor&
 Strategy::getMeasurements()
 {