fw: localhop scope restriction in ASF strategy

refs: #3841, #1756

Change-Id: Ic82e7055ace9d3f8eca8f9bad94603692ff321d5
diff --git a/daemon/fw/asf-probing-module.cpp b/daemon/fw/asf-probing-module.cpp
index 485a3e9..f29d0e7 100644
--- a/daemon/fw/asf-probing-module.cpp
+++ b/daemon/fw/asf-probing-module.cpp
@@ -25,6 +25,7 @@
 
 #include "asf-probing-module.hpp"
 #include "core/random.hpp"
+#include "algorithm.hpp"
 
 namespace nfd {
 namespace fw {
@@ -84,8 +85,9 @@
     Face& hopFace = hop.getFace();
 
     // Don't send probe Interest back to the incoming face or use the same face
-    // as the forwarded Interest
-    if (hopFace.getId() == inFace.getId() || hopFace.getId() == faceUsed.getId()) {
+    // as the forwarded Interest or use a face that violates scope
+    if (hopFace.getId() == inFace.getId() || hopFace.getId() == faceUsed.getId() ||
+        wouldViolateScope(inFace, interest, hopFace)) {
       continue;
     }
 
diff --git a/daemon/fw/asf-strategy.cpp b/daemon/fw/asf-strategy.cpp
index 657656c..acab918 100644
--- a/daemon/fw/asf-strategy.cpp
+++ b/daemon/fw/asf-strategy.cpp
@@ -24,6 +24,7 @@
  */
 
 #include "asf-strategy.hpp"
+#include "algorithm.hpp"
 
 #include "core/logger.hpp"
 
@@ -89,9 +90,6 @@
     Face* faceToProbe = m_probing.getFaceToProbe(inFace, interest, fibEntry, *faceToUse);
 
     if (faceToProbe != nullptr) {
-      NFD_LOG_TRACE("Sending probe for " << fibEntry.getPrefix()
-                                         << " to FaceId: " << faceToProbe->getId());
-
       bool wantNewNonce = true;
       forwardInterest(interest, fibEntry, pitEntry, *faceToProbe, wantNewNonce);
       m_probing.afterForwardingProbe(fibEntry, interest);
@@ -140,7 +138,17 @@
                              Face& outFace,
                              bool wantNewNonce)
 {
-  this->sendInterest(pitEntry, outFace, wantNewNonce);
+  if (wantNewNonce) {
+    //Send probe: interest with new Nonce
+    Interest probeInterest(interest);
+    probeInterest.refreshNonce();
+    NFD_LOG_TRACE("Sending probe for " << probeInterest << probeInterest.getNonce()
+                                       << " to FaceId: " << outFace.getId());
+    this->sendInterest(pitEntry, outFace, probeInterest);
+  }
+  else {
+    this->sendInterest(pitEntry, outFace, interest);
+  }
 
   FaceInfo& faceInfo = m_measurements.getOrCreateFaceInfo(fibEntry, interest, outFace);
 
@@ -219,7 +227,7 @@
   for (const fib::NextHop& hop : fibEntry.getNextHops()) {
     Face& hopFace = hop.getFace();
 
-    if (hopFace.getId() == inFace.getId()) {
+    if (hopFace.getId() == inFace.getId() || wouldViolateScope(inFace, interest, hopFace)) {
       continue;
     }
 
diff --git a/tests/daemon/fw/asf-strategy.t.cpp b/tests/daemon/fw/asf-strategy.t.cpp
index f3765c3..dddacf1 100644
--- a/tests/daemon/fw/asf-strategy.t.cpp
+++ b/tests/daemon/fw/asf-strategy.t.cpp
@@ -181,7 +181,7 @@
   BOOST_CHECK_GE(linkAD->getFace(nodeA).getCounters().nOutInterests, 2);
 }
 
-BOOST_AUTO_TEST_CASE(NoPitOutRecord)
+BOOST_AUTO_TEST_CASE(NoPitOutRecordAndProbeInterestNewNonce)
 {
   /*                 +---------+
   *                  |  nodeD  |
@@ -227,6 +227,8 @@
   topo.registerPrefix(nodeC, linkBC->getFace(nodeC), PRODUCER_PREFIX, 16);
   topo.registerPrefix(nodeB, linkBD->getFace(nodeB), PRODUCER_PREFIX, 80);
 
+  uint32_t nonce;
+
   // Send 6 interest since probes can be scheduled b/w 0-5 seconds
   for (int i = 1; i < 7; i++) {
     // Send ping number i
@@ -234,6 +236,7 @@
     name.appendTimestamp();
     shared_ptr<Interest> interest = makeInterest(name);
     ping->getClientFace().expressInterest(*interest, nullptr, nullptr, nullptr);
+    nonce = interest->getNonce();
 
     // Don't know when the probe will be triggered since it is random between 0-5 seconds
     // or whether it will be triggered for this interest
@@ -249,6 +252,16 @@
 
     // Check if probe is sent to B else send another ping
     if (linkAB->getFace(nodeA).getCounters().nOutInterests == 1) {
+      // Get pitEntry of node A
+      shared_ptr<pit::Entry> pitEntry = topo.getForwarder(nodeA).getPit().find(*interest);
+      //get outRecord associated with face towards B
+      pit::OutRecordCollection::const_iterator outRecord = pitEntry->getOutRecord(linkAB->getFace(nodeA));
+
+      BOOST_CHECK(outRecord != pitEntry->out_end());
+
+      //Check that Nonce of interest is not equal to Nonce of Probe
+      BOOST_CHECK_NE(nonce, outRecord->getLastNonce());
+
       // B should not have received the probe interest yet
       BOOST_CHECK_EQUAL(linkAB->getFace(nodeB).getCounters().nInInterests, 0);
 
@@ -260,10 +273,10 @@
       BOOST_CHECK_EQUAL(linkAB->getFace(nodeB).getCounters().nInInterests, 1);
       BOOST_CHECK_EQUAL(linkBD->getFace(nodeB).getCounters().nOutInterests, i);
 
-      shared_ptr<pit::Entry> pitEntry = topo.getForwarder(nodeB).getPit().find(*interest);
+      pitEntry = topo.getForwarder(nodeB).getPit().find(*interest);
 
       // Get outRecord associated with face towards D.
-      pit::OutRecordCollection::const_iterator outRecord = pitEntry->getOutRecord(linkBD->getFace(nodeB));
+      outRecord = pitEntry->getOutRecord(linkBD->getFace(nodeB));
 
       BOOST_CHECK(outRecord != pitEntry->out_end());
 
diff --git a/tests/daemon/fw/strategy-scope-control.t.cpp b/tests/daemon/fw/strategy-scope-control.t.cpp
index 8694322..2311ff7 100644
--- a/tests/daemon/fw/strategy-scope-control.t.cpp
+++ b/tests/daemon/fw/strategy-scope-control.t.cpp
@@ -29,6 +29,7 @@
 
 // Strategies implementing namespace-based scope control, sorted alphabetically.
 #include "fw/access-strategy.hpp"
+#include "fw/asf-strategy.hpp"
 #include "fw/best-route-strategy.hpp"
 #include "fw/best-route-strategy2.hpp"
 #include "fw/multicast-strategy.hpp"
@@ -130,6 +131,7 @@
 
 using Tests = boost::mpl::vector<
   Test<AccessStrategy, false, false>,
+  Test<AsfStrategy, true, false>,
   Test<BestRouteStrategy, false, false>,
   Test<BestRouteStrategy2, true, true>,
   Test<MulticastStrategy, false, false>,