fw: localhop scope restriction in BestRouteStrategy2
localhop scope rules are implemented as wouldViolateScope function;
the old violatesScope function is now deprecated.
Strategy::sendInterest overload without specific Interest packet is also
deprecated. BestRouteStrategy2 has switched to use the new overload.
refs #3841, #1756
Change-Id: Ic117f01926eadddf1da3ccb580b52a3903a70c89
diff --git a/daemon/fw/algorithm.cpp b/daemon/fw/algorithm.cpp
new file mode 100644
index 0000000..7a1f2cc
--- /dev/null
+++ b/daemon/fw/algorithm.cpp
@@ -0,0 +1,147 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/**
+ * Copyright (c) 2014-2016, Regents of the University of California,
+ * Arizona Board of Regents,
+ * Colorado State University,
+ * University Pierre & Marie Curie, Sorbonne University,
+ * Washington University in St. Louis,
+ * Beijing Institute of Technology,
+ * The University of Memphis.
+ *
+ * This file is part of NFD (Named Data Networking Forwarding Daemon).
+ * See AUTHORS.md for complete list of NFD authors and contributors.
+ *
+ * NFD is free software: you can redistribute it and/or modify it under the terms
+ * of the GNU General Public License as published by the Free Software Foundation,
+ * either version 3 of the License, or (at your option) any later version.
+ *
+ * NFD is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
+ * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+ * PURPOSE. See the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * NFD, e.g., in COPYING.md file. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "algorithm.hpp"
+
+namespace nfd {
+namespace scope_prefix {
+const Name LOCALHOST("ndn:/localhost");
+const Name LOCALHOP("ndn:/localhop");
+} // namespace scope_prefix
+
+namespace fw {
+
+bool
+wouldViolateScope(const Face& inFace, const Interest& interest, const Face& outFace)
+{
+ if (outFace.getScope() == ndn::nfd::FACE_SCOPE_LOCAL) {
+ // forwarding to a local face is always allowed
+ return false;
+ }
+
+ if (scope_prefix::LOCALHOST.isPrefixOf(interest.getName())) {
+ // localhost Interests cannot be forwarded to a non-local face
+ return true;
+ }
+
+ if (scope_prefix::LOCALHOP.isPrefixOf(interest.getName())) {
+ // localhop Interests can be forwarded to a non-local face only if it comes from a local face
+ return inFace.getScope() != ndn::nfd::FACE_SCOPE_LOCAL;
+ }
+
+ // Interest name is not subject to scope control
+ return false;
+}
+
+bool
+violatesScope(const pit::Entry& pitEntry, const Face& outFace)
+{
+ if (outFace.getScope() == ndn::nfd::FACE_SCOPE_LOCAL) {
+ return false;
+ }
+ BOOST_ASSERT(outFace.getScope() == ndn::nfd::FACE_SCOPE_NON_LOCAL);
+
+ if (scope_prefix::LOCALHOST.isPrefixOf(pitEntry.getName())) {
+ // face is non-local, violates localhost scope
+ return true;
+ }
+
+ if (scope_prefix::LOCALHOP.isPrefixOf(pitEntry.getName())) {
+ // face is non-local, violates localhop scope unless PIT entry has local in-record
+ return std::none_of(pitEntry.in_begin(), pitEntry.in_end(),
+ [] (const pit::InRecord& inRecord) { return inRecord.getFace().getScope() == ndn::nfd::FACE_SCOPE_LOCAL; });
+ }
+
+ // Name is not subject to scope control
+ return false;
+}
+
+bool
+canForwardToLegacy(const pit::Entry& pitEntry, const Face& face)
+{
+ time::steady_clock::TimePoint now = time::steady_clock::now();
+
+ bool hasUnexpiredOutRecord = std::any_of(pitEntry.out_begin(), pitEntry.out_end(),
+ [&face, &now] (const pit::OutRecord& outRecord) {
+ return &outRecord.getFace() == &face && outRecord.getExpiry() >= now;
+ });
+ if (hasUnexpiredOutRecord) {
+ return false;
+ }
+
+ bool hasUnexpiredOtherInRecord = std::any_of(pitEntry.in_begin(), pitEntry.in_end(),
+ [&face, &now] (const pit::InRecord& inRecord) {
+ return &inRecord.getFace() != &face && inRecord.getExpiry() >= now;
+ });
+ if (!hasUnexpiredOtherInRecord) {
+ return false;
+ }
+
+ return !violatesScope(pitEntry, face);
+}
+
+int
+findDuplicateNonce(const pit::Entry& pitEntry, uint32_t nonce, const Face& face)
+{
+ int dnw = DUPLICATE_NONCE_NONE;
+
+ for (const pit::InRecord& inRecord : pitEntry.getInRecords()) {
+ if (inRecord.getLastNonce() == nonce) {
+ if (&inRecord.getFace() == &face) {
+ dnw |= DUPLICATE_NONCE_IN_SAME;
+ }
+ else {
+ dnw |= DUPLICATE_NONCE_IN_OTHER;
+ }
+ }
+ }
+
+ for (const pit::OutRecord& outRecord : pitEntry.getOutRecords()) {
+ if (outRecord.getLastNonce() == nonce) {
+ if (&outRecord.getFace() == &face) {
+ dnw |= DUPLICATE_NONCE_OUT_SAME;
+ }
+ else {
+ dnw |= DUPLICATE_NONCE_OUT_OTHER;
+ }
+ }
+ }
+
+ return dnw;
+}
+
+bool
+hasPendingOutRecords(const pit::Entry& pitEntry)
+{
+ time::steady_clock::TimePoint now = time::steady_clock::now();
+ return std::any_of(pitEntry.out_begin(), pitEntry.out_end(),
+ [&now] (const pit::OutRecord& outRecord) {
+ return outRecord.getExpiry() >= now &&
+ outRecord.getIncomingNack() == nullptr;
+ });
+}
+
+} // namespace fw
+} // namespace nfd