fw: honor NextHopFaceId universally

NextHopFaceId usage no longer depends on client-control strategy.

refs #3783

Change-Id: Ie49c453f90fa34b517b576fe401c8e4e8f23eab7
diff --git a/daemon/fw/forwarder.cpp b/daemon/fw/forwarder.cpp
index f0186f5..9ef3c75 100644
--- a/daemon/fw/forwarder.cpp
+++ b/daemon/fw/forwarder.cpp
@@ -201,6 +201,18 @@
   // set PIT unsatisfy timer
   this->setUnsatisfyTimer(pitEntry);
 
+  // has NextHopFaceId?
+  shared_ptr<lp::NextHopFaceIdTag> nextHopTag = interest.getTag<lp::NextHopFaceIdTag>();
+  if (nextHopTag != nullptr) {
+    // chosen NextHop face exists?
+    Face* nextHopFace = m_faceTable.get(*nextHopTag);
+    if (nextHopFace != nullptr) {
+      // go to outgoing Interest pipeline
+      this->onOutgoingInterest(pitEntry, *nextHopFace);
+    }
+    return;
+  }
+
   // dispatch to strategy: after incoming Interest
   this->dispatchToStrategy(*pitEntry,
     [&] (fw::Strategy& strategy) { strategy.afterReceiveInterest(inFace, interest, pitEntry); });
diff --git a/tests/daemon/fw/forwarder.t.cpp b/tests/daemon/fw/forwarder.t.cpp
index 497952a..1b81f1f 100644
--- a/tests/daemon/fw/forwarder.t.cpp
+++ b/tests/daemon/fw/forwarder.t.cpp
@@ -170,6 +170,30 @@
   BOOST_CHECK_EQUAL(face1->sentInterests.back().getNonce(), 9102);
 }
 
+BOOST_AUTO_TEST_CASE(NextHopFaceId)
+{
+  Forwarder forwarder;
+
+  auto face1 = make_shared<DummyFace>();
+  auto face2 = make_shared<DummyFace>();
+  auto face3 = make_shared<DummyFace>();
+  forwarder.addFace(face1);
+  forwarder.addFace(face2);
+  forwarder.addFace(face3);
+
+  Fib& fib = forwarder.getFib();
+  fib.insert("/A").first->addNextHop(*face3, 0);
+
+  shared_ptr<Interest> interest = makeInterest("/A/B");
+  interest->setTag(make_shared<lp::NextHopFaceIdTag>(face2->getId()));
+
+  face1->receiveInterest(*interest);
+  this->advanceClocks(time::milliseconds(100), time::seconds(1));
+  BOOST_CHECK_EQUAL(face3->sentInterests.size(), 0);
+  BOOST_REQUIRE_EQUAL(face2->sentInterests.size(), 1);
+  BOOST_CHECK_EQUAL(face2->sentInterests.front().getName(), "/A/B");
+}
+
 class ScopeLocalhostIncomingTestForwarder : public Forwarder
 {
 public: