fw: Forwarder processes Link for mobility
This commit also adds NetworkRegionTable to store producer region names,
and checks packets are well-formed before entering forwarding pipelines.
refs #3034, #3155
Change-Id: I8de4c482e8a289b922be70139675bc4661f9a301
diff --git a/daemon/fw/face-table.cpp b/daemon/fw/face-table.cpp
index 0f78f74..f256d20 100644
--- a/daemon/fw/face-table.cpp
+++ b/daemon/fw/face-table.cpp
@@ -85,8 +85,10 @@
NFD_LOG_INFO("Added face id=" << faceId << " remote=" << face->getRemoteUri()
<< " local=" << face->getLocalUri());
- face->onReceiveInterest.connect(bind(&Forwarder::onInterest, &m_forwarder, ref(*face), _1));
- face->onReceiveData.connect(bind(&Forwarder::onData, &m_forwarder, ref(*face), _1));
+ face->onReceiveInterest.connect(bind(&Forwarder::startProcessInterest,
+ &m_forwarder, ref(*face), _1));
+ face->onReceiveData.connect(bind(&Forwarder::startProcessData,
+ &m_forwarder, ref(*face), _1));
face->onFail.connectSingleShot(bind(&FaceTable::remove, this, face, _1));
this->onAdd(face);
diff --git a/daemon/fw/forwarder.cpp b/daemon/fw/forwarder.cpp
index 7e5d883..27bfa38 100644
--- a/daemon/fw/forwarder.cpp
+++ b/daemon/fw/forwarder.cpp
@@ -49,7 +49,34 @@
Forwarder::~Forwarder()
{
+}
+void
+Forwarder::startProcessInterest(Face& face, const Interest& interest)
+{
+ // check fields used by forwarding are well-formed
+ try {
+ if (interest.hasLink()) {
+ interest.getLink();
+ }
+ }
+ catch (tlv::Error&) {
+ NFD_LOG_DEBUG("startProcessInterest face=" << face.getId() <<
+ " interest=" << interest.getName() << " malformed");
+ // It's safe to call interest.getName() because Name has been fully parsed
+ return;
+ }
+
+ this->onIncomingInterest(face, interest);
+}
+
+void
+Forwarder::startProcessData(Face& face, const Data& data)
+{
+ // check fields used by forwarding are well-formed
+ // (none needed)
+
+ this->onIncomingData(face, data);
}
void
@@ -101,6 +128,16 @@
}
void
+Forwarder::onInterestLoop(Face& inFace, const Interest& interest,
+ shared_ptr<pit::Entry> pitEntry)
+{
+ NFD_LOG_DEBUG("onInterestLoop face=" << inFace.getId() <<
+ " interest=" << interest.getName());
+
+ // (drop)
+}
+
+void
Forwarder::onContentStoreMiss(const Face& inFace,
shared_ptr<pit::Entry> pitEntry,
const Interest& interest)
@@ -114,10 +151,55 @@
// set PIT unsatisfy timer
this->setUnsatisfyTimer(pitEntry);
- // FIB lookup
- shared_ptr<fib::Entry> fibEntry = m_fib.findLongestPrefixMatch(*pitEntry);
+ shared_ptr<fib::Entry> fibEntry;
+ // has Link object?
+ if (!interest.hasLink()) {
+ // FIB lookup with Interest name
+ fibEntry = m_fib.findLongestPrefixMatch(*pitEntry);
+ NFD_LOG_TRACE("onContentStoreMiss noLinkObject");
+ }
+ else {
+ const Link& link = interest.getLink();
+
+ // in producer region?
+ if (m_networkRegionTable.isInProducerRegion(link)) {
+ // FIB lookup with Interest name
+ fibEntry = m_fib.findLongestPrefixMatch(*pitEntry);
+ NFD_LOG_TRACE("onContentStoreMiss inProducerRegion");
+ }
+ // has SelectedDelegation?
+ else if (interest.hasSelectedDelegation()) {
+ // FIB lookup with SelectedDelegation
+ fibEntry = m_fib.findLongestPrefixMatch(interest.getSelectedDelegation());
+ NFD_LOG_TRACE("onContentStoreMiss hasSelectedDelegation=" << interest.getSelectedDelegation());
+ }
+ else {
+ // FIB lookup with first delegation Name
+ fibEntry = m_fib.findLongestPrefixMatch(link.getDelegations().begin()->second);
+
+ // in default-free zone?
+ bool isDefaultFreeZone = !(fibEntry->getPrefix().size() == 0 && fibEntry->hasNextHops());
+ if (isDefaultFreeZone) {
+ // choose and set SelectedDelegation
+ for (const std::pair<uint32_t, Name>& delegation : link.getDelegations()) {
+ const Name& delegationName = delegation.second;
+ fibEntry = m_fib.findLongestPrefixMatch(delegationName);
+ if (fibEntry->hasNextHops()) {
+ const_cast<Interest&>(interest).setSelectedDelegation(delegationName);
+ NFD_LOG_TRACE("onContentStoreMiss enterDefaultFreeZone"
+ << " setSelectedDelegation=" << delegationName);
+ break;
+ }
+ }
+ }
+ else {
+ NFD_LOG_TRACE("onContentStoreMiss inConsumerRegion");
+ }
+ }
+ }
// dispatch to strategy
+ BOOST_ASSERT(fibEntry != nullptr);
this->dispatchToStrategy(pitEntry, bind(&Strategy::afterReceiveInterest, _1,
cref(inFace), cref(interest), fibEntry, pitEntry));
}
@@ -140,16 +222,6 @@
this->onOutgoingData(data, *const_pointer_cast<Face>(inFace.shared_from_this()));
}
-void
-Forwarder::onInterestLoop(Face& inFace, const Interest& interest,
- shared_ptr<pit::Entry> pitEntry)
-{
- NFD_LOG_DEBUG("onInterestLoop face=" << inFace.getId() <<
- " interest=" << interest.getName());
-
- // (drop)
-}
-
/** \brief compare two InRecords for picking outgoing Interest
* \return true if b is preferred over a
*
diff --git a/daemon/fw/forwarder.hpp b/daemon/fw/forwarder.hpp
index aa5d19d..155ec4a 100644
--- a/daemon/fw/forwarder.hpp
+++ b/daemon/fw/forwarder.hpp
@@ -36,6 +36,7 @@
#include "table/measurements.hpp"
#include "table/strategy-choice.hpp"
#include "table/dead-nonce-list.hpp"
+#include "table/network-region-table.hpp"
namespace nfd {
@@ -77,11 +78,17 @@
addFace(shared_ptr<Face> face);
public: // forwarding entrypoints and tables
+ /** \brief start incoming Interest processing
+ * \param interest the incoming Interest, must be created with make_shared
+ */
void
- onInterest(Face& face, const Interest& interest);
+ startProcessInterest(Face& face, const Interest& interest);
+ /** \brief start incoming Data processing
+ * \param data the incoming Data, must be created with make_shared
+ */
void
- onData(Face& face, const Data& data);
+ startProcessData(Face& face, const Data& data);
NameTree&
getNameTree();
@@ -104,12 +111,21 @@
DeadNonceList&
getDeadNonceList();
+ NetworkRegionTable&
+ getNetworkRegionTable();
+
PUBLIC_WITH_TESTS_ELSE_PRIVATE: // pipelines
/** \brief incoming Interest pipeline
*/
VIRTUAL_WITH_TESTS void
onIncomingInterest(Face& inFace, const Interest& interest);
+ /** \brief Interest loop pipeline
+ */
+ VIRTUAL_WITH_TESTS void
+ onInterestLoop(Face& inFace, const Interest& interest,
+ shared_ptr<pit::Entry> pitEntry);
+
/** \brief Content Store miss pipeline
*/
void
@@ -121,12 +137,6 @@
onContentStoreHit(const Face& inFace, shared_ptr<pit::Entry> pitEntry,
const Interest& interest, const Data& data);
- /** \brief Interest loop pipeline
- */
- VIRTUAL_WITH_TESTS void
- onInterestLoop(Face& inFace, const Interest& interest,
- shared_ptr<pit::Entry> pitEntry);
-
/** \brief outgoing Interest pipeline
*/
VIRTUAL_WITH_TESTS void
@@ -202,13 +212,14 @@
FaceTable m_faceTable;
// tables
- NameTree m_nameTree;
- Fib m_fib;
- Pit m_pit;
- Cs m_cs;
- Measurements m_measurements;
- StrategyChoice m_strategyChoice;
- DeadNonceList m_deadNonceList;
+ NameTree m_nameTree;
+ Fib m_fib;
+ Pit m_pit;
+ Cs m_cs;
+ Measurements m_measurements;
+ StrategyChoice m_strategyChoice;
+ DeadNonceList m_deadNonceList;
+ NetworkRegionTable m_networkRegionTable;
static const Name LOCALHOST_NAME;
@@ -240,18 +251,6 @@
m_faceTable.add(face);
}
-inline void
-Forwarder::onInterest(Face& face, const Interest& interest)
-{
- this->onIncomingInterest(face, interest);
-}
-
-inline void
-Forwarder::onData(Face& face, const Data& data)
-{
- this->onIncomingData(face, data);
-}
-
inline NameTree&
Forwarder::getNameTree()
{
@@ -294,6 +293,12 @@
return m_deadNonceList;
}
+inline NetworkRegionTable&
+Forwarder::getNetworkRegionTable()
+{
+ return m_networkRegionTable;
+}
+
#ifdef WITH_TESTS
inline void
Forwarder::dispatchToStrategy(shared_ptr<pit::Entry> pitEntry, function<void(fw::Strategy*)> trigger)
diff --git a/daemon/table/network-region-table.cpp b/daemon/table/network-region-table.cpp
new file mode 100644
index 0000000..df6ca58
--- /dev/null
+++ b/daemon/table/network-region-table.cpp
@@ -0,0 +1,44 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/**
+ * Copyright (c) 2014-2015, 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 "network-region-table.hpp"
+#include <boost/range/adaptor/map.hpp>
+
+namespace nfd {
+
+bool
+NetworkRegionTable::isInProducerRegion(const Link& link) const
+{
+ for (const Name& regionName : *this) {
+ for (const Name& delegationName : boost::adaptors::values(link.getDelegations())) {
+ if (delegationName.isPrefixOf(regionName)) {
+ return true;
+ }
+ }
+ }
+ return false;
+}
+
+} // namespace nfd
diff --git a/daemon/table/network-region-table.hpp b/daemon/table/network-region-table.hpp
new file mode 100644
index 0000000..499c356
--- /dev/null
+++ b/daemon/table/network-region-table.hpp
@@ -0,0 +1,55 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/**
+ * Copyright (c) 2014-2015, 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/>.
+ */
+
+#ifndef NFD_DAEMON_TABLE_NETWORK_REGION_TABLE_HPP
+#define NFD_DAEMON_TABLE_NETWORK_REGION_TABLE_HPP
+
+#include "common.hpp"
+
+namespace nfd {
+
+/** \brief stores a collection of producer region names
+ *
+ * This table is used in forwarding to process Interests with Link objects.
+ */
+class NetworkRegionTable : public std::set<Name>
+{
+public:
+ /** \brief determines whether an Interest has reached a producer region
+ * \param link the Link object on an Interest
+ * \retval true the Interest has reached a producer region
+ * \retval false the Interest has not reached a producer region
+ *
+ * If any delegation names in the Link object is a prefix of any region name,
+ * the Interest has reached the producer region and should be forwarded according to its Name;
+ * otherwise, the Interest should be forwarded according to the delegations.
+ */
+ bool
+ isInProducerRegion(const Link& link) const;
+};
+
+} // namespace nfd
+
+#endif // NFD_DAEMON_TABLE_NETWORK_REGION_TABLE_HPP