rib: Verify face before route registration
refs: #1811
Change-Id: If99f59734b29a46eca4f6139d35361a8563a9010
diff --git a/rib/rib-manager.cpp b/rib/rib-manager.cpp
index 993d84b..318198a 100644
--- a/rib/rib-manager.cpp
+++ b/rib/rib-manager.cpp
@@ -27,6 +27,7 @@
#include "core/global-io.hpp"
#include "core/logger.hpp"
#include "core/scheduler.hpp"
+#include <ndn-cxx/management/nfd-face-status.hpp>
namespace nfd {
namespace rib {
@@ -35,6 +36,7 @@
const Name RibManager::COMMAND_PREFIX = "/localhost/nfd/rib";
const Name RibManager::REMOTE_COMMAND_PREFIX = "/localhop/nfd/rib";
+const Name RibManager::FACES_LIST_DATASET_PREFIX = "/localhost/nfd/faces/list";
const size_t RibManager::COMMAND_UNSIGNED_NCOMPS =
RibManager::COMMAND_PREFIX.size() +
@@ -118,6 +120,8 @@
NFD_LOG_INFO("Start monitoring face create/destroy events");
m_faceMonitor.addSubscriber(bind(&RibManager::onNotification, this, _1));
m_faceMonitor.startNotifications();
+
+ fetchActiveFaces();
}
void
@@ -240,8 +244,12 @@
if (!validateParameters(command, parameters))
{
NFD_LOG_DEBUG("register result: FAIL reason: malformed");
+
if (static_cast<bool>(request))
- sendResponse(request->getName(), 400, "Malformed command");
+ {
+ sendResponse(request->getName(), 400, "Malformed command");
+ }
+
return;
}
@@ -250,6 +258,19 @@
parameters.setFaceId(request->getIncomingFaceId());
}
+ // Is the face valid?
+ if (activeFaces.find(parameters.getFaceId()) == activeFaces.end())
+ {
+ NFD_LOG_DEBUG("register result: FAIL reason: unknown faceId");
+
+ if (static_cast<bool>(request))
+ {
+ sendResponse(request->getName(), 410, "Face not found");
+ }
+
+ return;
+ }
+
FaceEntry faceEntry;
faceEntry.faceId = parameters.getFaceId();
faceEntry.origin = parameters.getOrigin();
@@ -311,6 +332,19 @@
parameters.setFaceId(request->getIncomingFaceId());
}
+ // Is the face valid?
+ if (activeFaces.find(parameters.getFaceId()) == activeFaces.end())
+ {
+ NFD_LOG_DEBUG("register result: FAIL reason: unknown faceId");
+
+ if (static_cast<bool>(request))
+ {
+ sendResponse(request->getName(), 410, "Face not found");
+ }
+
+ return;
+ }
+
FaceEntry faceEntry;
faceEntry.faceId = parameters.getFaceId();
faceEntry.origin = parameters.getOrigin();
@@ -603,8 +637,17 @@
{
/// \todo A notification can be missed, in this case check Facelist
NFD_LOG_TRACE("onNotification: " << notification);
- if (notification.getKind() == ndn::nfd::FACE_EVENT_DESTROYED) //face destroyed
+
+ if (notification.getKind() == ndn::nfd::FACE_EVENT_CREATED)
{
+ NFD_LOG_DEBUG("Received notification for created faceId: " << notification.getFaceId());
+ activeFaces.insert(notification.getFaceId());
+ }
+ else if (notification.getKind() == ndn::nfd::FACE_EVENT_DESTROYED)
+ {
+ NFD_LOG_DEBUG("Received notification for destroyed faceId: " << notification.getFaceId());
+ activeFaces.erase(notification.getFaceId());
+
scheduler::schedule(time::seconds(0),
bind(&RibManager::processErasureAfterNotification, this,
notification.getFaceId()));
@@ -722,5 +765,75 @@
m_ribStatusPublisher.publish();
}
+void
+RibManager::fetchActiveFaces()
+{
+ NFD_LOG_DEBUG("Fetching active faces");
+
+ Interest interest(FACES_LIST_DATASET_PREFIX);
+ interest.setChildSelector(1);
+ interest.setMustBeFresh(true);
+
+ shared_ptr<ndn::OBufferStream> buffer = make_shared<ndn::OBufferStream>();
+
+ m_face.expressInterest(interest,
+ bind(&RibManager::fetchSegments, this, _2, buffer),
+ bind(&RibManager::onFetchFaceStatusTimeout, this));
+}
+
+void
+RibManager::fetchSegments(const Data& data, shared_ptr<ndn::OBufferStream> buffer)
+{
+ buffer->write(reinterpret_cast<const char*>(data.getContent().value()),
+ data.getContent().value_size());
+
+ uint64_t currentSegment = data.getName().get(-1).toSegment();
+
+ const name::Component& finalBlockId = data.getMetaInfo().getFinalBlockId();
+ if (finalBlockId.empty() || finalBlockId.toSegment() > currentSegment)
+ {
+ m_face.expressInterest(data.getName().getPrefix(-1).appendSegment(currentSegment+1),
+ bind(&RibManager::fetchSegments, this, _2, buffer),
+ bind(&RibManager::onFetchFaceStatusTimeout, this));
+ }
+ else
+ {
+ updateActiveFaces(buffer);
+ }
+}
+
+void
+RibManager::updateActiveFaces(shared_ptr<ndn::OBufferStream> buffer)
+{
+ NFD_LOG_DEBUG("Updating active faces");
+
+ ndn::ConstBufferPtr buf = buffer->buf();
+
+ Block block;
+ size_t offset = 0;
+
+ while (offset < buf->size())
+ {
+ if (!Block::fromBuffer(buf, offset, block))
+ {
+ std::cerr << "ERROR: cannot decode FaceStatus TLV" << std::endl;
+ break;
+ }
+
+ offset += block.size();
+
+ ndn::nfd::FaceStatus status(block);
+
+ NFD_LOG_DEBUG("Adding faceId: " << status.getFaceId() << " to activeFaces");
+ activeFaces.insert(status.getFaceId());
+ }
+}
+
+void
+RibManager::onFetchFaceStatusTimeout()
+{
+ std::cerr << "Face Status Dataset request timed out" << std::endl;
+}
+
} // namespace rib
} // namespace nfd
diff --git a/rib/rib-manager.hpp b/rib/rib-manager.hpp
index a19d211..c31256e 100644
--- a/rib/rib-manager.hpp
+++ b/rib/rib-manager.hpp
@@ -202,6 +202,18 @@
void
listEntries(const Interest& request);
+ void
+ fetchActiveFaces();
+
+ void
+ fetchSegments(const Data& data, shared_ptr<ndn::OBufferStream> buffer);
+
+ void
+ updateActiveFaces(shared_ptr<ndn::OBufferStream> buffer);
+
+ void
+ onFetchFaceStatusTimeout();
+
private:
Rib m_managedRib;
ndn::Face& m_face;
@@ -263,6 +275,11 @@
static const Name LIST_COMMAND_PREFIX;
static const size_t LIST_COMMAND_NCOMPS;
+
+ static const Name FACES_LIST_DATASET_PREFIX;
+
+PUBLIC_WITH_TESTS_ELSE_PRIVATE:
+ std::set<int> activeFaces;
};
} // namespace rib
diff --git a/tests/rib/rib-manager.cpp b/tests/rib/rib-manager.cpp
index 797f01e..8a30684 100644
--- a/tests/rib/rib-manager.cpp
+++ b/tests/rib/rib-manager.cpp
@@ -48,6 +48,8 @@
face->processEvents(time::milliseconds(1));
face->m_sentInterests.clear();
+
+ manager->activeFaces.insert(1);
}
~RibManagerFixture()