rib: remote prefix registration
resolve 3 bugs:
There are redundant registrations/unregistrations if loading the
config file multiple times.
Remote registration/unregistration will fail if localhop_security
is enabled.
Unstable RemoteRegistrator/UnregisterAdvanced test case.
Change-Id: I4437292e9f6c0e340c761ef7556a9bdc703ac06c
refs: #2294
diff --git a/nfd.conf.sample.in b/nfd.conf.sample.in
index dafc88a..7edb379 100644
--- a/nfd.conf.sample.in
+++ b/nfd.conf.sample.in
@@ -288,6 +288,16 @@
; ; }
; }
+ ; The following localhop_security should be enabled when NFD runs on a hub,
+ ; which accepts all remote registrations and is a short-term solution.
+ ; localhop_security
+ ; {
+ ; trust-anchor
+ ; {
+ ; type any
+ ; }
+ ; }
+
remote_register
{
cost 15 ; forwarding cost of prefix registered on remote router
diff --git a/rib/remote-registrator.cpp b/rib/remote-registrator.cpp
index 2a5a12d..a587653 100644
--- a/rib/remote-registrator.cpp
+++ b/rib/remote-registrator.cpp
@@ -35,10 +35,9 @@
using ndn::nfd::ControlParameters;
using ndn::nfd::CommandOptions;
-
-const Name RemoteRegistrator::RM_LOCAL_PREFIX = "/localhost";
-const Name RemoteRegistrator::RM_HUB_PREFIX = "/localhop/nfd";
-const name::Component RemoteRegistrator::RM_IGNORE_COMMPONENT("rib");
+const Name RemoteRegistrator::LOCAL_REGISTRATION_PREFIX = "/localhost";
+const Name RemoteRegistrator::REMOTE_HUB_PREFIX = "/localhop/nfd/rib";
+const name::Component RemoteRegistrator::IGNORE_COMMPONENT("rib");
RemoteRegistrator::RemoteRegistrator(ndn::nfd::Controller& controller,
ndn::KeyChain& keyChain,
@@ -100,8 +99,14 @@
.setOrigin(ndn::nfd::ROUTE_ORIGIN_CLIENT)// set origin to client.
.setFaceId(0);// the remote hub will take the input face as the faceId.
+ Name commandPrefix = REMOTE_HUB_PREFIX;
+ if (IGNORE_COMMPONENT == commandPrefix.at(-1))
+ {
+ commandPrefix = commandPrefix.getPrefix(-1);
+ }
+
m_commandOptions
- .setPrefix(RM_HUB_PREFIX)
+ .setPrefix(commandPrefix)
.setTimeout(time::milliseconds(timeout));
m_nRetries = retry;
@@ -117,15 +122,38 @@
}
void
+RemoteRegistrator::enable()
+{
+ // do remote registration after an entry is inserted into the RIB.
+ m_afterInsertConnection =
+ m_rib.afterInsertEntry.connect([this] (const Name& prefix) {
+ registerPrefix(prefix);
+ });
+
+ // do remote unregistration after an entry is erased from the RIB.
+ m_afterEraseConnection =
+ m_rib.afterEraseEntry.connect([this] (const Name& prefix) {
+ unregisterPrefix(prefix);
+ });
+}
+
+void
+RemoteRegistrator::disable()
+{
+ m_afterInsertConnection.disconnect();
+ m_afterEraseConnection.disconnect();
+}
+
+void
RemoteRegistrator::registerPrefix(const Name& prefix)
{
- if (RM_LOCAL_PREFIX.isPrefixOf(prefix))
+ if (LOCAL_REGISTRATION_PREFIX.isPrefixOf(prefix))
{
NFD_LOG_INFO("local registration only for " << prefix);
return;
}
- bool isHubPrefix = prefix == RM_HUB_PREFIX;
+ bool isHubPrefix = prefix == REMOTE_HUB_PREFIX;
if (isHubPrefix)
{
@@ -181,7 +209,7 @@
void
RemoteRegistrator::unregisterPrefix(const Name& prefix)
{
- if (prefix == RM_HUB_PREFIX)
+ if (prefix == REMOTE_HUB_PREFIX)
{
NFD_LOG_INFO("disconnected to hub with prefix: " << prefix);
@@ -267,7 +295,7 @@
// longest prefix matching to all indenties.
for (auto&& i : identities)
{
- if (!i.empty() && RM_IGNORE_COMMPONENT == i.at(-1))
+ if (!i.empty() && IGNORE_COMMPONENT == i.at(-1))
{
isPrefix = i.getPrefix(-1).isPrefixOf(prefix);
curLength = i.size() - 1;
@@ -360,9 +388,9 @@
const CommandOptions& options,
int nRetries)
{
- NFD_LOG_INFO("fail to unregister " << parameters.getName()
- << "\n\t reason:" << reason
- << "\n\t remain retries:" << nRetries);
+ NFD_LOG_INFO("fail to register " << parameters.getName()
+ << "\n\t reason:" << reason
+ << "\n\t remain retries:" << nRetries);
if (nRetries > 0)
{
diff --git a/rib/remote-registrator.hpp b/rib/remote-registrator.hpp
index 41be218..0d9eea3 100644
--- a/rib/remote-registrator.hpp
+++ b/rib/remote-registrator.hpp
@@ -36,6 +36,7 @@
#include <ndn-cxx/management/nfd-control-command.hpp>
#include <ndn-cxx/management/nfd-control-parameters.hpp>
#include <ndn-cxx/management/nfd-command-options.hpp>
+#include <ndn-cxx/util/signal.hpp>
namespace nfd {
namespace rib {
@@ -72,6 +73,20 @@
loadConfig(const ConfigSection& configSection);
/**
+ * @brief enable remote registration/unregistration.
+ *
+ */
+ void
+ enable();
+
+ /**
+ * @brief disable remote registration/unregistration.
+ *
+ */
+ void
+ disable();
+
+ /**
* @brief register a prefix to remote hub(s).
*
* For the input prefix, we find the longest identity
@@ -197,7 +212,6 @@
void
clearRefreshEvents();
-
PUBLIC_WITH_TESTS_ELSE_PRIVATE:
/**
* When a locally registered prefix triggles remote
@@ -217,16 +231,17 @@
ndn::nfd::Controller& m_nfdController;
ndn::KeyChain& m_keyChain;
Rib& m_rib;
-
+ ndn::util::signal::ScopedConnection m_afterInsertConnection;
+ ndn::util::signal::ScopedConnection m_afterEraseConnection;
ndn::nfd::ControlParameters m_controlParameters;
ndn::nfd::CommandOptions m_commandOptions;
time::seconds m_refreshInterval;
bool m_hasConnectedHub;
int m_nRetries;
- static const Name RM_LOCAL_PREFIX; // /localhost
- static const Name RM_HUB_PREFIX; // /localhop/nfd
- static const name::Component RM_IGNORE_COMMPONENT; // rib
+ static const Name LOCAL_REGISTRATION_PREFIX; // /localhost
+ static const Name REMOTE_HUB_PREFIX; // /localhop/nfd/rib
+ static const name::Component IGNORE_COMMPONENT; // rib
};
} // namespace rib
diff --git a/rib/rib-manager.cpp b/rib/rib-manager.cpp
index 491739a..7d0f5b3 100644
--- a/rib/rib-manager.cpp
+++ b/rib/rib-manager.cpp
@@ -144,6 +144,8 @@
bool isDryRun,
const std::string& filename)
{
+ bool isRemoteRegisterEnabled = false;
+
for (ConfigSection::const_iterator i = configSection.begin();
i != configSection.end(); ++i)
{
@@ -157,21 +159,23 @@
else if (i->first == "remote_register")
{
m_remoteRegistrator.loadConfig(i->second);
+ isRemoteRegisterEnabled = true;
+ // avoid other actions when isDryRun == true
+ if (isDryRun)
+ {
+ continue;
+ }
- // register callback to the RIB.
- // do remote registration after an entry is inserted into the RIB.
- // do remote unregistration after an entry is erased from the RIB.
- m_managedRib.afterInsertEntry += [this] (const Name& prefix) {
- m_remoteRegistrator.registerPrefix(prefix);
- };
-
- m_managedRib.afterEraseEntry += [this] (const Name& prefix) {
- m_remoteRegistrator.unregisterPrefix(prefix);
- };
+ m_remoteRegistrator.enable();
}
else
throw Error("Unrecognized rib property: " + i->first);
}
+
+ if (!isRemoteRegisterEnabled)
+ {
+ m_remoteRegistrator.disable();
+ }
}
void
@@ -200,16 +204,7 @@
RibManager::onLocalhostRequest(const Interest& request)
{
const Name& command = request.getName();
-
- if (command.size() <= COMMAND_PREFIX.size())
- {
- // command is too short to have a verb
- NFD_LOG_DEBUG("command result: malformed");
- sendResponse(command, 400, "Malformed command");
- return;
- }
-
- const Name::Component& verb = command.at(COMMAND_PREFIX.size());
+ const Name::Component& verb = command.get(COMMAND_PREFIX.size());
UnsignedVerbDispatchTable::const_iterator unsignedVerbProcessor = m_unsignedVerbDispatch.find(verb);
diff --git a/rib/rib.hpp b/rib/rib.hpp
index ed9ca4e..2568b1a 100644
--- a/rib/rib.hpp
+++ b/rib/rib.hpp
@@ -30,6 +30,7 @@
#include "fib-update.hpp"
#include "common.hpp"
#include <ndn-cxx/management/nfd-control-command.hpp>
+#include <ndn-cxx/util/signal.hpp>
namespace nfd {
namespace rib {
@@ -137,8 +138,8 @@
removeInheritedFacesFromEntry(RibEntry& entry, const Rib::FaceSet& facesToRemove);
public:
- ndn::util::EventEmitter<Name> afterInsertEntry;
- ndn::util::EventEmitter<Name> afterEraseEntry;
+ ndn::util::signal::Signal<Rib, Name> afterInsertEntry;
+ ndn::util::signal::Signal<Rib, Name> afterEraseEntry;
private:
RibTable m_rib;
diff --git a/tests/rib/remote-registrator.cpp b/tests/rib/remote-registrator.cpp
index e0b4d3a..c0ef540 100644
--- a/tests/rib/remote-registrator.cpp
+++ b/tests/rib/remote-registrator.cpp
@@ -34,10 +34,11 @@
namespace tests {
class RemoteRegistratorFixture : public nfd::tests::IdentityManagementFixture
+ , public nfd::tests::UnitTestTimeFixture
{
public:
RemoteRegistratorFixture()
- : face(ndn::util::makeDummyClientFace())
+ : face(ndn::util::makeDummyClientFace(getGlobalIoService()))
, controller(make_shared<ndn::nfd::Controller>(std::ref(*face), m_keyChain))
, remoteRegistrator(make_shared<RemoteRegistrator>(std::ref(*controller),
m_keyChain,
@@ -48,41 +49,52 @@
{
readConfig();
- registerCallback();
+ remoteRegistrator->enable();
- face->processEvents(time::milliseconds(1));
+ advanceClocks(time::milliseconds(1));
face->sentInterests.clear();
}
void
- readConfig()
+ readConfig(bool isSetRetry = false)
{
ConfigFile config;
config.addSectionHandler("remote_register",
bind(&RemoteRegistrator::loadConfig, remoteRegistrator, _1));
- const std::string CONFIG_STRING =
- "remote_register\n"
- "{\n"
- " cost 15\n"
- " timeout 10000\n"
- " retry 2\n"
- " refresh_interval 5\n"
- "}";
- config.parse(CONFIG_STRING, true, "test-remote-register");
+ if (isSetRetry)
+ {
+ const std::string CONFIG_STRING =
+ "remote_register\n"
+ "{\n"
+ " cost 15\n"
+ " timeout 1000\n"
+ " retry 1\n"
+ " refresh_interval 5\n"
+ "}";
+
+ config.parse(CONFIG_STRING, true, "test-remote-register");
+ }
+ else
+ {
+ const std::string CONFIG_STRING =
+ "remote_register\n"
+ "{\n"
+ " cost 15\n"
+ " timeout 100000\n"
+ " retry 0\n"
+ " refresh_interval 5\n"
+ "}";
+
+ config.parse(CONFIG_STRING, true, "test-remote-register");
+ }
}
void
- registerCallback()
+ waitForTimeout()
{
- rib.afterInsertEntry += [this] (const Name& prefix) {
- remoteRegistrator->registerPrefix(prefix);
- };
-
- rib.afterEraseEntry += [this] (const Name& prefix) {
- remoteRegistrator->unregisterPrefix(prefix);
- };
+ advanceClocks(time::milliseconds(100), time::seconds(1));
}
void
@@ -97,7 +109,7 @@
rib.insert(identity.append(appName), faceEntry);
- face->processEvents(time::milliseconds(1));
+ advanceClocks(time::milliseconds(1));
}
void
@@ -110,7 +122,7 @@
rib.insert(identity.append(appName), faceEntry);
- face->processEvents(time::milliseconds(1));
+ advanceClocks(time::milliseconds(1));
}
void
@@ -125,7 +137,7 @@
rib.erase(identity.append(appName), faceEntry);
- face->processEvents(time::milliseconds(1));
+ advanceClocks(time::milliseconds(1));
}
void
@@ -138,7 +150,7 @@
rib.erase(identity.append(appName), faceEntry);
- face->processEvents(time::milliseconds(1));
+ advanceClocks(time::milliseconds(1));
}
void
@@ -146,23 +158,23 @@
{
rib.erase(faceId);
- face->processEvents(time::milliseconds(1));
+ advanceClocks(time::milliseconds(1));
}
void
connectToHub()
{
- rib.insert(Name("/localhop/nfd"), FaceEntry());
+ rib.insert(COMMAND_PREFIX, FaceEntry());
- face->processEvents(time::milliseconds(1));
+ advanceClocks(time::milliseconds(1));
}
void
disconnectToHub()
{
- rib.erase(Name("/localhop/nfd"), FaceEntry());
+ rib.erase(COMMAND_PREFIX, FaceEntry());
- face->processEvents(time::milliseconds(1));
+ advanceClocks(time::milliseconds(1));
}
void
@@ -270,6 +282,55 @@
BOOST_CHECK_EQUAL(extractedParameters.getName(), identity);
}
+BOOST_FIXTURE_TEST_CASE(RegisterWithRedundantCallback, RemoteRegistratorFixture)
+{
+ remoteRegistrator->enable();
+
+ connectToHub();
+
+ Name identity("/remote/register");
+ insertEntryWithIdentity(identity);
+
+ BOOST_REQUIRE_EQUAL(face->sentInterests.size(), 1);
+
+ Interest& request = face->sentInterests[0];
+
+ ndn::nfd::ControlParameters extractedParameters;
+ Name::Component verb;
+ extractParameters(request, verb, extractedParameters);
+
+ BOOST_CHECK_EQUAL(verb, REGISTER_VERB);
+ BOOST_CHECK_EQUAL(extractedParameters.getName(), identity);
+}
+
+BOOST_FIXTURE_TEST_CASE(RegisterRetry, RemoteRegistratorFixture)
+{
+ // setRetry
+ readConfig(true);
+
+ connectToHub();
+
+ Name identity("/remote/register");
+ insertEntryWithIdentity(identity);
+
+ waitForTimeout();
+
+ BOOST_REQUIRE_EQUAL(face->sentInterests.size(), 2);
+
+ Interest& requestFirst = face->sentInterests[0];
+ Interest& requestSecond = face->sentInterests[1];
+
+ ndn::nfd::ControlParameters extractedParametersFirst, extractedParametersSecond;
+ Name::Component verbFirst, verbSecond;
+ extractParameters(requestFirst, verbFirst, extractedParametersFirst);
+ extractParameters(requestSecond, verbSecond, extractedParametersSecond);
+
+ BOOST_CHECK_EQUAL(verbFirst, REGISTER_VERB);
+ BOOST_CHECK_EQUAL(verbSecond, REGISTER_VERB);
+ BOOST_CHECK_EQUAL(extractedParametersFirst.getName(), identity);
+ BOOST_CHECK_EQUAL(extractedParametersSecond.getName(), identity);
+}
+
BOOST_FIXTURE_TEST_CASE(UnregisterWithoutInsert, RemoteRegistratorFixture)
{
connectToHub();