rib: Add RIB dataset publisher
refs: #1662
Change-Id: I97885c07af131a7ea78d074b39df884178f09416
diff --git a/rib/rib-manager.cpp b/rib/rib-manager.cpp
index fc62ace..d2e80c3 100644
--- a/rib/rib-manager.cpp
+++ b/rib/rib-manager.cpp
@@ -45,19 +45,30 @@
RibManager::COMMAND_UNSIGNED_NCOMPS +
4; // (timestamp, nonce, signed info tlv, signature tlv)
-const RibManager::VerbAndProcessor RibManager::COMMAND_VERBS[] =
+const RibManager::SignedVerbAndProcessor RibManager::SIGNED_COMMAND_VERBS[] =
{
- VerbAndProcessor(
- Name::Component("register"),
- &RibManager::registerEntry
- ),
+ SignedVerbAndProcessor(
+ Name::Component("register"),
+ &RibManager::registerEntry
+ ),
- VerbAndProcessor(
- Name::Component("unregister"),
- &RibManager::unregisterEntry
- ),
+ SignedVerbAndProcessor(
+ Name::Component("unregister"),
+ &RibManager::unregisterEntry
+ ),
};
+const RibManager::UnsignedVerbAndProcessor RibManager::UNSIGNED_COMMAND_VERBS[] =
+ {
+ UnsignedVerbAndProcessor(
+ Name::Component("list"),
+ &RibManager::listEntries
+ ),
+ };
+
+const Name RibManager::LIST_COMMAND_PREFIX("/localhost/nfd/rib/list");
+const size_t RibManager::LIST_COMMAND_NCOMPS = LIST_COMMAND_PREFIX.size();
+
RibManager::RibManager(ndn::Face& face)
: m_face(face)
, m_nfdController(m_face)
@@ -65,9 +76,14 @@
, m_localhopValidator(m_face)
, m_faceMonitor(m_face)
, m_isLocalhopEnabled(false)
+ , m_ribStatusPublisher(m_managedRib, face, LIST_COMMAND_PREFIX, m_keyChain)
, m_lastTransactionId(0)
- , m_verbDispatch(COMMAND_VERBS,
- COMMAND_VERBS + (sizeof(COMMAND_VERBS) / sizeof(VerbAndProcessor)))
+ , m_signedVerbDispatch(SIGNED_COMMAND_VERBS,
+ SIGNED_COMMAND_VERBS +
+ (sizeof(SIGNED_COMMAND_VERBS) / sizeof(SignedVerbAndProcessor)))
+ , m_unsignedVerbDispatch(UNSIGNED_COMMAND_VERBS,
+ UNSIGNED_COMMAND_VERBS +
+ (sizeof(UNSIGNED_COMMAND_VERBS) / sizeof(UnsignedVerbAndProcessor)))
{
}
@@ -156,9 +172,22 @@
void
RibManager::onLocalhostRequest(const Interest& request)
{
- m_localhostValidator.validate(request,
- bind(&RibManager::onCommandValidated, this, _1),
- bind(&RibManager::onCommandValidationFailed, this, _1, _2));
+ const Name& command = request.getName();
+ const Name::Component& verb = command.get(COMMAND_PREFIX.size());
+
+ UnsignedVerbDispatchTable::const_iterator unsignedVerbProcessor = m_unsignedVerbDispatch.find(verb);
+
+ if (unsignedVerbProcessor != m_unsignedVerbDispatch.end())
+ {
+ NFD_LOG_DEBUG("command result: processing unsigned verb: " << verb);
+ (unsignedVerbProcessor->second)(this, request);
+ }
+ else
+ {
+ m_localhostValidator.validate(request,
+ bind(&RibManager::onCommandValidated, this, _1),
+ bind(&RibManager::onCommandValidationFailed, this, _1, _2));
+ }
}
void
@@ -179,8 +208,8 @@
const Name::Component& verb = command[COMMAND_PREFIX.size()];
const Name::Component& parameterComponent = command[COMMAND_PREFIX.size() + 1];
- VerbDispatchTable::const_iterator verbProcessor = m_verbDispatch.find(verb);
- if (verbProcessor != m_verbDispatch.end())
+ SignedVerbDispatchTable::const_iterator verbProcessor = m_signedVerbDispatch.find(verb);
+ if (verbProcessor != m_signedVerbDispatch.end())
{
ControlParameters parameters;
if (!extractParameters(parameterComponent, parameters))
@@ -671,5 +700,22 @@
sendUpdatesToFib(shared_ptr<const Interest>(), parameters);
}
+void
+RibManager::listEntries(const Interest& request)
+{
+ const Name& command = request.getName();
+ const size_t commandNComps = command.size();
+
+ if (commandNComps < LIST_COMMAND_NCOMPS ||
+ !LIST_COMMAND_PREFIX.isPrefixOf(command))
+ {
+ NFD_LOG_DEBUG("command result: malformed");
+ sendResponse(command, 400, "Malformed command");
+ return;
+ }
+
+ m_ribStatusPublisher.publish();
+}
+
} // namespace rib
} // namespace nfd
diff --git a/rib/rib-manager.hpp b/rib/rib-manager.hpp
index 6566d1f..a19d211 100644
--- a/rib/rib-manager.hpp
+++ b/rib/rib-manager.hpp
@@ -29,6 +29,7 @@
#include "rib.hpp"
#include "face-monitor.hpp"
#include "core/config-file.hpp"
+#include "rib-status-publisher.hpp"
#include <ndn-cxx/security/validator-config.hpp>
#include <ndn-cxx/management/nfd-controller.hpp>
@@ -198,6 +199,9 @@
void
invalidateTransaction(const TransactionId transactionId);
+ void
+ listEntries(const Interest& request);
+
private:
Rib m_managedRib;
ndn::Face& m_face;
@@ -208,6 +212,8 @@
FaceMonitor m_faceMonitor;
bool m_isLocalhopEnabled;
+ RibStatusPublisher m_ribStatusPublisher;
+
/** \brief The last transaction ID for FIB update response messages.
* Each group of FIB updates applied to the FIB is assigned an incrementing
* ID that is used to track the number of successfully applied updates.
@@ -226,14 +232,14 @@
typedef function<void(RibManager*,
const shared_ptr<const Interest>& request,
- ControlParameters& parameters)> VerbProcessor;
+ ControlParameters& parameters)> SignedVerbProcessor;
- typedef std::map<name::Component, VerbProcessor> VerbDispatchTable;
+ typedef std::map<name::Component, SignedVerbProcessor> SignedVerbDispatchTable;
- typedef std::pair<name::Component, VerbProcessor> VerbAndProcessor;
+ typedef std::pair<name::Component, SignedVerbProcessor> SignedVerbAndProcessor;
- const VerbDispatchTable m_verbDispatch;
+ const SignedVerbDispatchTable m_signedVerbDispatch;
static const Name COMMAND_PREFIX; // /localhost/nrd
static const Name REMOTE_COMMAND_PREFIX; // /localhop/nrd
@@ -246,7 +252,17 @@
// 8 with signed Interest support.
static const size_t COMMAND_SIGNED_NCOMPS;
- static const VerbAndProcessor COMMAND_VERBS[];
+ static const SignedVerbAndProcessor SIGNED_COMMAND_VERBS[];
+
+ typedef function<void(RibManager*, const Interest&)> UnsignedVerbProcessor;
+ typedef std::map<Name::Component, UnsignedVerbProcessor> UnsignedVerbDispatchTable;
+ typedef std::pair<Name::Component, UnsignedVerbProcessor> UnsignedVerbAndProcessor;
+
+ const UnsignedVerbDispatchTable m_unsignedVerbDispatch;
+ static const UnsignedVerbAndProcessor UNSIGNED_COMMAND_VERBS[];
+
+ static const Name LIST_COMMAND_PREFIX;
+ static const size_t LIST_COMMAND_NCOMPS;
};
} // namespace rib
diff --git a/rib/rib-status-publisher.cpp b/rib/rib-status-publisher.cpp
new file mode 100644
index 0000000..76a164c
--- /dev/null
+++ b/rib/rib-status-publisher.cpp
@@ -0,0 +1,97 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/**
+ * Copyright (c) 2014, 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 "rib/rib-status-publisher.hpp"
+#include "rib/rib.hpp"
+#include "core/logger.hpp"
+
+#include <ndn-cxx/management/nfd-rib-entry.hpp>
+#include <ndn-cxx/face.hpp>
+
+namespace nfd {
+namespace rib {
+
+NFD_LOG_INIT("RibStatusPublisher");
+
+RibStatusPublisher::RibStatusPublisher(const Rib& rib,
+ ndn::Face& face,
+ const Name& prefix,
+ ndn::KeyChain& keyChain)
+ : SegmentPublisher<ndn::Face>(face, prefix, keyChain)
+ , m_rib(rib)
+{
+}
+
+RibStatusPublisher::~RibStatusPublisher()
+{
+}
+
+size_t
+RibStatusPublisher::generate(ndn::EncodingBuffer& outBuffer)
+{
+ size_t totalLength = 0;
+
+ for (Rib::const_iterator ribIt = m_rib.begin(); ribIt != m_rib.end(); ++ribIt)
+ {
+ RibEntry& entry = *ribIt->second;
+
+ const Name& prefix = entry.getName();
+ size_t ribEntryLength = 0;
+
+ ndn::nfd::RibEntry tlvEntry;
+ const RibEntry::FaceList& faces = entry.getFaces();
+
+ for (RibEntry::FaceList::const_iterator faceIt = faces.begin();
+ faceIt != faces.end(); ++faceIt)
+ {
+ const FaceEntry& face = *faceIt;
+
+ ndn::nfd::Route route;
+ route
+ .setFaceId(face.faceId)
+ .setOrigin(face.origin)
+ .setCost(face.cost)
+ .setFlags(face.flags);
+ if (face.expires < time::steady_clock::TimePoint::max()) {
+ route.setExpirationPeriod(time::duration_cast<time::milliseconds>
+ (face.expires - time::steady_clock::now()));
+ }
+ tlvEntry.addRoute(route);
+ }
+
+ tlvEntry.setName(prefix);
+ ribEntryLength += tlvEntry.wireEncode(outBuffer);
+
+ NFD_LOG_DEBUG("generate: rib entry length = " << ribEntryLength);
+
+ totalLength += ribEntryLength;
+ }
+ NFD_LOG_DEBUG("generate: Total length = " << totalLength);
+ return totalLength;
+}
+
+
+} // namespace rib
+} // namespace nfd
diff --git a/rib/rib-status-publisher.hpp b/rib/rib-status-publisher.hpp
new file mode 100644
index 0000000..8673983
--- /dev/null
+++ b/rib/rib-status-publisher.hpp
@@ -0,0 +1,60 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/**
+ * Copyright (c) 2014, 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_RIB_RIB_STATUS_PUBLISHER_HPP
+#define NFD_RIB_RIB_STATUS_PUBLISHER_HPP
+
+#include "core/segment-publisher.hpp"
+#include <ndn-cxx/face.hpp>
+
+namespace nfd {
+namespace rib {
+
+class Rib;
+
+class RibStatusPublisher : public SegmentPublisher<ndn::Face>
+{
+public:
+ RibStatusPublisher(const Rib& rib,
+ ndn::Face& face,
+ const Name& prefix,
+ ndn::KeyChain& keyChain);
+
+ virtual
+ ~RibStatusPublisher();
+
+protected:
+ virtual size_t
+ generate(ndn::EncodingBuffer& outBuffer);
+
+private:
+ const Rib& m_rib;
+};
+
+
+} // namespace rib
+} // namespace nfd
+
+#endif
diff --git a/tests/rib/rib-manager.cpp b/tests/rib/rib-manager.cpp
index 92188b1..797f01e 100644
--- a/tests/rib/rib-manager.cpp
+++ b/tests/rib/rib-manager.cpp
@@ -27,6 +27,7 @@
#include "tests/test-common.hpp"
#include "tests/dummy-face.hpp"
+#include "rib/rib-status-publisher-common.hpp"
namespace nfd {
namespace rib {
@@ -111,7 +112,7 @@
typedef RibManagerFixture UnauthorizedRibManager;
-BOOST_FIXTURE_TEST_SUITE(RibRibManager, RibManagerFixture)
+BOOST_FIXTURE_TEST_SUITE(RibManager, RibManagerFixture)
BOOST_FIXTURE_TEST_CASE(Basic, AuthorizedRibManager)
{
@@ -219,6 +220,39 @@
BOOST_REQUIRE_EQUAL(face->m_sentInterests.size(), 0);
}
+BOOST_FIXTURE_TEST_CASE(RibStatusRequest, AuthorizedRibManager)
+{
+ FaceEntry entry;
+ Name name("/");
+ entry.faceId = 1;
+ entry.origin = 128;
+ entry.cost = 32;
+ entry.flags = ndn::nfd::ROUTE_FLAG_CAPTURE;
+
+ ControlParameters parameters;
+ parameters
+ .setName(name)
+ .setFaceId(entry.faceId)
+ .setOrigin(entry.origin)
+ .setCost(entry.cost)
+ .setFlags(entry.flags)
+ .setExpirationPeriod(ndn::time::milliseconds::max());
+
+ Name commandName("/localhost/nfd/rib/register");
+
+ BOOST_REQUIRE_EQUAL(face->m_sentInterests.size(), 0);
+
+ receiveCommandInterest(commandName, parameters);
+ face->m_sentInterests.clear();
+ face->m_sentDatas.clear();
+
+ face->receive(Interest("/localhost/nfd/rib/list"));
+ face->processEvents(time::milliseconds(1));
+
+ BOOST_REQUIRE_EQUAL(face->m_sentDatas.size(), 1);
+ RibStatusPublisherFixture::decodeRibEntryBlock(face->m_sentDatas[0], name, entry);
+}
+
BOOST_AUTO_TEST_SUITE_END()
} // namespace tests
diff --git a/tests/rib/rib-status-publisher-common.hpp b/tests/rib/rib-status-publisher-common.hpp
new file mode 100644
index 0000000..11728a0
--- /dev/null
+++ b/tests/rib/rib-status-publisher-common.hpp
@@ -0,0 +1,93 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/**
+ * Copyright (c) 2014, 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 RIB_TESTS_UNIT_TESTS_RIB_STATUS_PUBLISHER_COMMON_HPP
+#define RIB_TESTS_UNIT_TESTS_RIB_STATUS_PUBLISHER_COMMON_HPP
+
+#include "rib/rib-status-publisher.hpp"
+
+#include "tests/test-common.hpp"
+#include "rib/rib.hpp"
+
+#include <ndn-cxx/management/nfd-control-parameters.hpp>
+#include <ndn-cxx/management/nfd-rib-entry.hpp>
+#include <ndn-cxx/encoding/tlv.hpp>
+
+namespace nfd {
+namespace rib {
+namespace tests {
+
+using ndn::nfd::ControlParameters;
+
+class RibStatusPublisherFixture : public nfd::tests::BaseFixture
+{
+public:
+ static void
+ validateRibEntry(const Block& block, const Name& referenceName, const FaceEntry& referenceFace)
+ {
+ ndn::nfd::RibEntry entry;
+ BOOST_REQUIRE_NO_THROW(entry.wireDecode(block));
+
+ BOOST_CHECK_EQUAL(entry.getName(), referenceName);
+
+ std::list<ndn::nfd::Route> routes = entry.getRoutes();
+
+ std::list<ndn::nfd::Route>::iterator it = routes.begin();
+ BOOST_CHECK_EQUAL(it->getFaceId(), referenceFace.faceId);
+ BOOST_CHECK_EQUAL(it->getOrigin(), referenceFace.origin);
+ BOOST_CHECK_EQUAL(it->getCost(), referenceFace.cost);
+ BOOST_CHECK_EQUAL(it->getFlags(), referenceFace.flags);
+ }
+
+ static void
+ decodeRibEntryBlock(const Data& data, const Name& referenceName, const FaceEntry& referenceFace)
+ {
+ ndn::EncodingBuffer buffer;
+
+ Block payload = data.getContent();
+
+ buffer.appendByteArray(payload.value(), payload.value_size());
+ buffer.prependVarNumber(buffer.size());
+ buffer.prependVarNumber(ndn::Tlv::Content);
+
+ ndn::Block parser(buffer.buf(), buffer.size());
+ parser.parse();
+
+ Block::element_const_iterator i = parser.elements_begin();
+
+ if (i->type() != ndn::tlv::nfd::RibEntry) {
+ BOOST_FAIL("expected RibEntry, got type #" << i->type());
+ }
+ else {
+ validateRibEntry(*i, referenceName, referenceFace);
+ }
+ }
+};
+
+#endif // RIB_TESTS_UNIT_TESTS_RIB_STATUS_PUBLISHER_COMMON_HPP
+
+} // namespace tests
+} // namespace rib
+} // namespace nfd
diff --git a/tests/rib/rib-status-publisher.cpp b/tests/rib/rib-status-publisher.cpp
new file mode 100644
index 0000000..ac68c63
--- /dev/null
+++ b/tests/rib/rib-status-publisher.cpp
@@ -0,0 +1,65 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/**
+ * Copyright (c) 2014, 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 "rib/rib-status-publisher.hpp"
+
+#include "rib-status-publisher-common.hpp"
+#include "tests/dummy-face.hpp"
+
+namespace nfd {
+namespace rib {
+namespace tests {
+
+BOOST_FIXTURE_TEST_SUITE(RibStatusPublisherSuite, RibStatusPublisherFixture)
+
+BOOST_AUTO_TEST_CASE(Basic)
+{
+ Rib rib;
+
+ FaceEntry entry;
+ Name name("/");
+ entry.faceId = 1;
+ entry.origin = 128;
+ entry.cost = 32;
+ entry.flags = ndn::nfd::ROUTE_FLAG_CAPTURE;
+ rib.insert(name, entry);
+
+ ndn::KeyChain keyChain;
+ shared_ptr<nfd::tests::DummyFace> face = nfd::tests::makeDummyFace();
+ RibStatusPublisher publisher(rib, *face, "/localhost/nfd/rib/list", keyChain);
+
+ publisher.publish();
+ face->processEvents(time::milliseconds(1));
+
+ BOOST_REQUIRE_EQUAL(face->m_sentDatas.size(), 1);
+ decodeRibEntryBlock(face->m_sentDatas[0], name, entry);
+}
+
+
+BOOST_AUTO_TEST_SUITE_END()
+
+} // namespace tests
+} // namespace rib
+} // namespace nfd