fw: Check out record exists before calculating RTT in ASF
Change-Id: Ie7f2db50b21d314a5df998e4220f64de14861d3e
refs: #3829
diff --git a/daemon/fw/asf-measurements.cpp b/daemon/fw/asf-measurements.cpp
index c98ca86..e8bc8fd 100644
--- a/daemon/fw/asf-measurements.cpp
+++ b/daemon/fw/asf-measurements.cpp
@@ -114,6 +114,12 @@
{
// Calculate RTT
pit::OutRecordCollection::const_iterator outRecord = pitEntry->getOutRecord(inFace);
+
+ if (outRecord == pitEntry->out_end()) { // no out-record
+ NFD_LOG_TRACE(pitEntry->getInterest() << " dataFrom inFace=" << inFace.getId() << " no-out-record");
+ return;
+ }
+
time::steady_clock::Duration steadyRtt = time::steady_clock::now() - outRecord->getLastRenewed();
RttEstimator::Duration durationRtt = time::duration_cast<RttEstimator::Duration>(steadyRtt);
diff --git a/tests/daemon/fw/asf-strategy.t.cpp b/tests/daemon/fw/asf-strategy.t.cpp
index 601083d..f3765c3 100644
--- a/tests/daemon/fw/asf-strategy.t.cpp
+++ b/tests/daemon/fw/asf-strategy.t.cpp
@@ -181,6 +181,111 @@
BOOST_CHECK_GE(linkAD->getFace(nodeA).getCounters().nOutInterests, 2);
}
+BOOST_AUTO_TEST_CASE(NoPitOutRecord)
+{
+ /* +---------+
+ * | nodeD |
+ * +---------+
+ * |
+ * | 80ms
+ * |
+ * |
+ * +---------+
+ * +----->| nodeB |<------+
+ * | +---------+ |
+ * 15ms | | 16ms
+ * v v
+ * +---------+ +---------+
+ * | nodeA |--------------| nodeC |
+ * +---------+ 14ms +---------+
+ */
+
+ const Name PRODUCER_PREFIX = "/ndn/edu/nodeD/ping";
+
+ TopologyTester topo;
+ TopologyNode nodeA = topo.addForwarder("A"),
+ nodeB = topo.addForwarder("B"),
+ nodeC = topo.addForwarder("C"),
+ nodeD = topo.addForwarder("D");
+
+ for (TopologyNode node : {nodeA, nodeB, nodeC, nodeD}) {
+ topo.setStrategy<fw::AsfStrategy>(node);
+ }
+
+ shared_ptr<TopologyLink> linkAB = topo.addLink("AB", time::milliseconds(15), {nodeA, nodeB}),
+ linkAC = topo.addLink("AC", time::milliseconds(14), {nodeA, nodeC}),
+ linkBC = topo.addLink("BC", time::milliseconds(16), {nodeB, nodeC}),
+ linkBD = topo.addLink("BD", time::milliseconds(80), {nodeB, nodeD});
+
+ shared_ptr<TopologyAppLink> ping = topo.addAppFace("c", nodeA),
+ pingServer = topo.addAppFace("p", nodeD, PRODUCER_PREFIX);
+ topo.addEchoProducer(pingServer->getClientFace());
+
+ // Register prefixes
+ topo.registerPrefix(nodeA, linkAB->getFace(nodeA), PRODUCER_PREFIX, 15);
+ topo.registerPrefix(nodeA, linkAC->getFace(nodeA), PRODUCER_PREFIX, 14);
+ topo.registerPrefix(nodeC, linkBC->getFace(nodeC), PRODUCER_PREFIX, 16);
+ topo.registerPrefix(nodeB, linkBD->getFace(nodeB), PRODUCER_PREFIX, 80);
+
+ // Send 6 interest since probes can be scheduled b/w 0-5 seconds
+ for (int i = 1; i < 7; i++) {
+ // Send ping number i
+ Name name(PRODUCER_PREFIX);
+ name.appendTimestamp();
+ shared_ptr<Interest> interest = makeInterest(name);
+ ping->getClientFace().expressInterest(*interest, nullptr, nullptr, nullptr);
+
+ // 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
+ int j = 1;
+ while (linkAB->getFace(nodeA).getCounters().nOutInterests != 1) {
+ this->advanceClocks(time::milliseconds(1));
+ ++j;
+ // Probe was not scheduled with this ping interest
+ if (j > 1000) {
+ break;
+ }
+ }
+
+ // Check if probe is sent to B else send another ping
+ if (linkAB->getFace(nodeA).getCounters().nOutInterests == 1) {
+ // B should not have received the probe interest yet
+ BOOST_CHECK_EQUAL(linkAB->getFace(nodeB).getCounters().nInInterests, 0);
+
+ // i-1 interests through B when no probe
+ BOOST_CHECK_EQUAL(linkBD->getFace(nodeB).getCounters().nOutInterests, i - 1);
+
+ // After 15ms, B should get the probe interest
+ this->advanceClocks(time::milliseconds(1), time::milliseconds(15));
+ 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);
+
+ // Get outRecord associated with face towards D.
+ pit::OutRecordCollection::const_iterator outRecord = pitEntry->getOutRecord(linkBD->getFace(nodeB));
+
+ BOOST_CHECK(outRecord != pitEntry->out_end());
+
+ // RTT between B and D
+ this->advanceClocks(time::milliseconds(5), time::milliseconds(160));
+ outRecord = pitEntry->getOutRecord(linkBD->getFace(nodeB));
+
+ BOOST_CHECK_EQUAL(linkBD->getFace(nodeB).getCounters().nInData, i);
+
+ BOOST_CHECK(outRecord == pitEntry->out_end());
+
+ // Data is returned for the ping after 15 ms - will result in false measurement
+ // 14+16-15 = 15ms
+ // Since outRecord == pitEntry->out_end()
+ this->advanceClocks(time::milliseconds(1), time::milliseconds(15));
+ BOOST_CHECK_EQUAL(linkBD->getFace(nodeB).getCounters().nInData, i+1);
+
+ break;
+ }
+ }
+}
+
BOOST_AUTO_TEST_SUITE_END() // TestAsfStrategy
BOOST_AUTO_TEST_SUITE_END() // Fw