nlsr: discover Faces from NFD
refs: #2954
Change-Id: I072972d88bce0e1012e96f33577657048b7df1e1
diff --git a/src/adjacent.hpp b/src/adjacent.hpp
index 4aded01..29d7567 100644
--- a/src/adjacent.hpp
+++ b/src/adjacent.hpp
@@ -115,7 +115,7 @@
}
uint64_t
- getFaceId()
+ getFaceId() const
{
return m_faceId;
}
diff --git a/src/conf-file-processor.cpp b/src/conf-file-processor.cpp
index 789efc4..5362a41 100644
--- a/src/conf-file-processor.cpp
+++ b/src/conf-file-processor.cpp
@@ -454,6 +454,33 @@
if (!adjLsaBuildInterval.parseFromConfigSection(section)) {
return false;
}
+ // Set the retry count for fetching the FaceStatus dataset
+ ConfigurationVariable<uint32_t> faceDatasetFetchTries("face-dataset-fetch-tries",
+ std::bind(&ConfParameter::setFaceDatasetFetchTries,
+ &m_nlsr.getConfParameter(),
+ _1));
+
+ faceDatasetFetchTries.setMinAndMaxValue(FACE_DATASET_FETCH_TRIES_MIN,
+ FACE_DATASET_FETCH_TRIES_MAX);
+ faceDatasetFetchTries.setOptional(FACE_DATASET_FETCH_TRIES_DEFAULT);
+
+ if (!faceDatasetFetchTries.parseFromConfigSection(section)) {
+ return false;
+ }
+
+ // Set the interval between FaceStatus dataset fetch attempts.
+ ConfigurationVariable<ndn::time::seconds> faceDatasetFetchInterval("face-dataset-fetch-interval",
+ bind(&ConfParameter::setFaceDatasetFetchInterval,
+ &m_nlsr.getConfParameter(),
+ _1));
+
+ faceDatasetFetchInterval.setMinAndMaxValue(ndn::time::seconds(FACE_DATASET_FETCH_INTERVAL_MIN),
+ ndn::time::seconds(FACE_DATASET_FETCH_INTERVAL_MAX));
+ faceDatasetFetchInterval.setOptional(ndn::time::seconds(FACE_DATASET_FETCH_INTERVAL_DEFAULT));
+
+ if (!faceDatasetFetchInterval.parseFromConfigSection(section)) {
+ return false;
+ }
// first-hello-interval
ConfigurationVariable<uint32_t> firstHelloInterval("first-hello-interval",
@@ -469,8 +496,7 @@
for (ConfigSection::const_iterator tn =
section.begin(); tn != section.end(); ++tn) {
- if (tn->first == "neighbor")
- {
+ if (tn->first == "neighbor") {
try {
ConfigSection CommandAttriTree = tn->second;
std::string name = CommandAttriTree.get<std::string>("name");
@@ -479,7 +505,7 @@
ndn::util::FaceUri faceUri;
try {
faceUri = ndn::util::FaceUri(uriString);
- } catch (ndn::util::FaceUri::Error e) {
+ } catch (const ndn::util::FaceUri::Error& e) {
std::cerr << "Malformed face-uri <" << uriString << "> for " << name << std::endl;
return false;
}
diff --git a/src/conf-parameter.hpp b/src/conf-parameter.hpp
index 9bcd95c..6ec21f5 100644
--- a/src/conf-parameter.hpp
+++ b/src/conf-parameter.hpp
@@ -62,6 +62,19 @@
ROUTING_CALC_INTERVAL_MAX = 15
};
+
+enum {
+ FACE_DATASET_FETCH_TRIES_MIN = 1,
+ FACE_DATASET_FETCH_TRIES_MAX = 10,
+ FACE_DATASET_FETCH_TRIES_DEFAULT = 3
+};
+
+enum {
+ FACE_DATASET_FETCH_INTERVAL_MIN = 1800,
+ FACE_DATASET_FETCH_INTERVAL_MAX = 5400,
+ FACE_DATASET_FETCH_INTERVAL_DEFAULT = 3600
+};
+
enum {
HELLO_RETRIES_MIN = 1,
HELLO_RETRIES_DEFAULT = 3,
@@ -261,6 +274,30 @@
}
void
+ setFaceDatasetFetchTries(uint32_t count)
+ {
+ m_faceDatasetFetchTries = count;
+ }
+
+ uint32_t
+ getFaceDatasetFetchTries() const
+ {
+ return m_faceDatasetFetchTries;
+ }
+
+ void
+ setFaceDatasetFetchInterval(ndn::time::seconds interval)
+ {
+ m_faceDatasetFetchInterval = interval;
+ }
+
+ const ndn::time::seconds
+ getFaceDatasetFetchInterval() const
+ {
+ return m_faceDatasetFetchInterval;
+ }
+
+ void
setLogLevel(const std::string& logLevel)
{
m_logLevel = logLevel;
@@ -423,6 +460,9 @@
uint32_t m_firstHelloInterval;
uint32_t m_routingCalcInterval;
+ uint32_t m_faceDatasetFetchTries;
+ ndn::time::seconds m_faceDatasetFetchInterval;
+
ndn::time::seconds m_lsaInterestLifetime;
uint32_t m_routerDeadInterval;
std::string m_logLevel;
diff --git a/src/hello-protocol.cpp b/src/hello-protocol.cpp
index 52e8997..4a995de 100644
--- a/src/hello-protocol.cpp
+++ b/src/hello-protocol.cpp
@@ -17,8 +17,6 @@
* You should have received a copy of the GNU General Public License along with
* NLSR, e.g., in COPYING.md file. If not, see <http://www.gnu.org/licenses/>.
*
- * \author A K M Mahmudul Hoque <ahoque1@memphis.edu>
- *
**/
#include "nlsr.hpp"
@@ -68,13 +66,6 @@
m_nlsr.getConfParameter().getInterestResendTime());
_LOG_DEBUG("Sending scheduled interest: " << interestName);
}
- // If it does not have a Face, we need to give it one. A
- // successful registration prompts a callback that sends the hello
- // Interest to the new Face.
- else {
- registerPrefixes((*it).getName(), (*it).getFaceUri().toString(),
- (*it).getLinkCost(), ndn::time::milliseconds::max());
- }
}
scheduleInterest(m_nlsr.getConfParameter().getInfoInterestInterval());
}
@@ -126,12 +117,6 @@
expressInterest(interestName,
m_nlsr.getConfParameter().getInterestResendTime());
}
- // If the originator of the Interest currently lacks a Face, we
- // need to give it one.
- else {
- registerPrefixes(adjacent->getName(), adjacent->getFaceUri().toString(),
- adjacent->getLinkCost(), ndn::time::milliseconds::max());
- }
}
}
}
@@ -235,82 +220,4 @@
_LOG_DEBUG("Validation Error: " << msg);
}
-
- // Asks the FIB to register the supplied adjacency (in other words,
- // create a Face for it).
-void
-HelloProtocol::registerPrefixes(const ndn::Name& adjName, const std::string& faceUri,
- double linkCost, const ndn::time::milliseconds& timeout)
-{
- m_nlsr.getFib().registerPrefix(adjName, faceUri, linkCost, timeout,
- ndn::nfd::ROUTE_FLAG_CAPTURE, 0,
- std::bind(&HelloProtocol::onRegistrationSuccess,
- this, _1, adjName,timeout),
- std::bind(&HelloProtocol::onRegistrationFailure,
- this, _1, adjName));
-}
-
- // After we create a new Face, we need to set it up for use. This
- // function sets the controlling strategy, registers prefixes in
- // sync, broadcast, and LSA.
-void
-HelloProtocol::onRegistrationSuccess(const ndn::nfd::ControlParameters& commandSuccessResult,
- const ndn::Name& neighbor,const ndn::time::milliseconds& timeout)
-{
- auto adjacent = m_nlsr.getAdjacencyList().findAdjacent(neighbor);
- if (adjacent != m_nlsr.getAdjacencyList().end()){
- adjacent->setFaceId(commandSuccessResult.getFaceId());
- ndn::Name broadcastKeyPrefix = DEFAULT_BROADCAST_PREFIX;
- broadcastKeyPrefix.append("KEYS");
- std::string faceUri = adjacent->getFaceUri().toString();
- double linkCost = adjacent->getLinkCost();
- m_nlsr.getFib().registerPrefix(m_nlsr.getConfParameter().getChronosyncPrefix(),
- faceUri, linkCost, timeout,
- ndn::nfd::ROUTE_FLAG_CAPTURE, 0);
- m_nlsr.getFib().registerPrefix(m_nlsr.getConfParameter().getLsaPrefix(),
- faceUri, linkCost, timeout,
- ndn::nfd::ROUTE_FLAG_CAPTURE, 0);
- m_nlsr.getFib().registerPrefix(broadcastKeyPrefix,
- faceUri, linkCost, timeout,
- ndn::nfd::ROUTE_FLAG_CAPTURE, 0);
-
- // Sends a Hello Interest to determine status before the next scheduled.
- // interest name: /<neighbor>/NLSR/INFO/<router>
- ndn::Name interestName(neighbor);
- interestName.append(NLSR_COMPONENT);
- interestName.append(INFO_COMPONENT);
- interestName.append(m_nlsr.getConfParameter().getRouterPrefix().wireEncode());
- expressInterest(interestName,
- m_nlsr.getConfParameter().getInterestResendTime());
- }
-}
-
-void
-HelloProtocol::onRegistrationFailure(const ndn::nfd::ControlResponse& response,
- const ndn::Name& name)
-{
- _LOG_DEBUG(response.getText() << " (code: " << response.getCode() << ")");
- /*
- * If NLSR can not create face for given faceUri then it will treat this
- * failure as one INFO interest timed out. So that NLSR can move on with
- * building Adj Lsa and calculate routing table. NLSR does not build Adj
- * Lsa unless all the neighbors are ACTIVE or DEAD. For considering the
- * missconfigured(link) neighbour dead this is required.
- */
- auto adjacent = m_nlsr.getAdjacencyList().findAdjacent(name);
- if (adjacent != m_nlsr.getAdjacencyList().end()) {
- adjacent->setInterestTimedOutNo(adjacent->getInterestTimedOutNo() + 1);
- Adjacent::Status status = adjacent->getStatus();
- uint32_t infoIntTimedOutCount = adjacent->getInterestTimedOutNo();
-
- if (infoIntTimedOutCount == m_nlsr.getConfParameter().getInterestRetryNumber()) {
- if (status == Adjacent::STATUS_ACTIVE) {
- adjacent->setStatus(Adjacent::STATUS_INACTIVE);
- }
-
- m_nlsr.getLsdb().scheduleAdjLsaBuild();
- }
- }
-}
-
} // namespace nlsr
diff --git a/src/hello-protocol.hpp b/src/hello-protocol.hpp
index 1817850..808b843 100644
--- a/src/hello-protocol.hpp
+++ b/src/hello-protocol.hpp
@@ -117,9 +117,6 @@
onRegistrationSuccess(const ndn::nfd::ControlParameters& commandSuccessResult,
const ndn::Name& neighbor, const ndn::time::milliseconds& timeout);
- void
- registerPrefixes(const ndn::Name& adjName, const std::string& faceUri,
- double linkCost, const ndn::time::milliseconds& timeout);
private:
Nlsr& m_nlsr;
ndn::Scheduler& m_scheduler;
diff --git a/src/nlsr-runner.cpp b/src/nlsr-runner.cpp
index 29e4737..827593a 100644
--- a/src/nlsr-runner.cpp
+++ b/src/nlsr-runner.cpp
@@ -75,7 +75,6 @@
std::cerr << "ERROR: " << e.what() << std::endl;
m_nlsr.getFib().clean();
- m_nlsr.destroyFaces();
}
}
diff --git a/src/nlsr.cpp b/src/nlsr.cpp
index ca829e0..5709313 100644
--- a/src/nlsr.cpp
+++ b/src/nlsr.cpp
@@ -29,6 +29,7 @@
#include "adjacent.hpp"
#include "logger.hpp"
+#include <ndn-cxx/util/face-uri.hpp>
namespace nlsr {
@@ -63,9 +64,12 @@
m_routerNameDispatcher,
m_nlsrFace,
m_keyChain)
+
, m_helloProtocol(*this, scheduler)
, m_certificateCache(new ndn::CertificateCacheTtl(ioService))
, m_validator(m_nlsrFace, DEFAULT_BROADCAST_PREFIX, m_certificateCache, m_certStore)
+ , m_controller(m_nlsrFace, m_keyChain, m_validator)
+ , m_faceDatasetController(m_nlsrFace, m_keyChain)
, m_prefixUpdateProcessor(m_nlsrFace,
m_namePrefixList,
m_nlsrLsdb,
@@ -252,6 +256,9 @@
setInfoInterestFilter();
setLsaInterestFilter();
+ initializeFaces(std::bind(&Nlsr::processFaceDataset, this, _1),
+ std::bind(&Nlsr::onFaceDatasetFetchTimeout, this, _1, _2, 0));
+
// Set event intervals
setFirstHelloInterval(m_confParam.getFirstHelloInterval());
m_nlsrLsdb.setAdjLsaBuildInterval(m_confParam.getAdjLsaBuildInterval());
@@ -377,78 +384,195 @@
}
void
-Nlsr::onDestroyFaceSuccess(const ndn::nfd::ControlParameters& commandSuccessResult)
-{
-}
-
-void
-Nlsr::onDestroyFaceFailure(const ndn::nfd::ControlResponse& response)
-{
- std::cerr << response.getText() << " (code: " << response.getCode() << ")";
- BOOST_THROW_EXCEPTION(Error("Error: Face destruction failed"));
-}
-
-void
-Nlsr::destroyFaces()
-{
- std::list<Adjacent>& adjacents = m_adjacencyList.getAdjList();
- for (std::list<Adjacent>::iterator it = adjacents.begin();
- it != adjacents.end(); it++) {
- m_fib.destroyFace((*it).getFaceUri().toString(),
- std::bind(&Nlsr::onDestroyFaceSuccess, this, _1),
- std::bind(&Nlsr::onDestroyFaceFailure, this, _1));
- }
-}
-
-void
Nlsr::onFaceEventNotification(const ndn::nfd::FaceEventNotification& faceEventNotification)
{
_LOG_TRACE("Nlsr::onFaceEventNotification called");
- ndn::nfd::FaceEventKind kind = faceEventNotification.getKind();
- if (kind == ndn::nfd::FACE_EVENT_DESTROYED) {
- uint64_t faceId = faceEventNotification.getFaceId();
+ switch (faceEventNotification.getKind()) {
+ case ndn::nfd::FACE_EVENT_DESTROYED: {
+ uint64_t faceId = faceEventNotification.getFaceId();
- auto adjacent = m_adjacencyList.findAdjacent(faceId);
+ auto adjacent = m_adjacencyList.findAdjacent(faceId);
- if (adjacent != m_adjacencyList.end()) {
- _LOG_DEBUG("Face to " << adjacent->getName() << " with face id: " << faceId << " destroyed");
+ if (adjacent != m_adjacencyList.end()) {
+ _LOG_DEBUG("Face to " << adjacent->getName() << " with face id: " << faceId << " destroyed");
- adjacent->setFaceId(0);
+ adjacent->setFaceId(0);
- // Only trigger an Adjacency LSA build if this node is changing
- // from ACTIVE to INACTIVE since this rebuild will effectively
- // cancel the previous Adjacency LSA refresh event and schedule
- // a new one further in the future.
- //
- // Continuously scheduling the refresh in the future will block
- // the router from refreshing its Adjacency LSA. Since other
- // routers' Name prefixes' expiration times are updated when
- // this router refreshes its Adjacency LSA, the other routers'
- // prefixes will expire and be removed from the RIB.
- //
- // This check is required to fix Bug #2733 for now. This check
- // would be unnecessary to fix Bug #2733 when Issue #2732 is
- // completed, but the check also helps with optimization so it
- // can remain even when Issue #2732 is implemented.
- if (adjacent->getStatus() == Adjacent::STATUS_ACTIVE) {
- adjacent->setStatus(Adjacent::STATUS_INACTIVE);
+ // Only trigger an Adjacency LSA build if this node is changing
+ // from ACTIVE to INACTIVE since this rebuild will effectively
+ // cancel the previous Adjacency LSA refresh event and schedule
+ // a new one further in the future.
+ //
+ // Continuously scheduling the refresh in the future will block
+ // the router from refreshing its Adjacency LSA. Since other
+ // routers' Name prefixes' expiration times are updated when
+ // this router refreshes its Adjacency LSA, the other routers'
+ // prefixes will expire and be removed from the RIB.
+ //
+ // This check is required to fix Bug #2733 for now. This check
+ // would be unnecessary to fix Bug #2733 when Issue #2732 is
+ // completed, but the check also helps with optimization so it
+ // can remain even when Issue #2732 is implemented.
+ if (adjacent->getStatus() == Adjacent::STATUS_ACTIVE) {
+ adjacent->setStatus(Adjacent::STATUS_INACTIVE);
- // A new adjacency LSA cannot be built until the neighbor is marked INACTIVE and
- // has met the HELLO retry threshold
- adjacent->setInterestTimedOutNo(m_confParam.getInterestRetryNumber());
+ // A new adjacency LSA cannot be built until the neighbor is marked INACTIVE and
+ // has met the HELLO retry threshold
+ adjacent->setInterestTimedOutNo(m_confParam.getInterestRetryNumber());
- if (m_confParam.getHyperbolicState() != HYPERBOLIC_STATE_OFF) {
- getRoutingTable().scheduleRoutingTableCalculation(*this);
- }
- else {
- m_nlsrLsdb.scheduleAdjLsaBuild();
+ if (m_confParam.getHyperbolicState() != HYPERBOLIC_STATE_OFF) {
+ getRoutingTable().scheduleRoutingTableCalculation(*this);
+ }
+ else {
+ m_nlsrLsdb.scheduleAdjLsaBuild();
+ }
}
}
+ break;
}
+ case ndn::nfd::FACE_EVENT_CREATED: {
+ // Find the neighbor in our adjacency list
+ _LOG_DEBUG("Face created event received.");
+ auto adjacent = m_adjacencyList.findAdjacent(
+ ndn::util::FaceUri(faceEventNotification.getRemoteUri()));
+ // If we have a neighbor by that FaceUri and it has no FaceId, we
+ // have a match.
+ if (adjacent != m_adjacencyList.end()) {
+ _LOG_DEBUG("Face creation event matches neighbor: " << adjacent->getName()
+ << ". New Face ID: " << faceEventNotification.getFaceId()
+ << ". Registering prefixes.");
+ adjacent->setFaceId(faceEventNotification.getFaceId());
+
+ registerAdjacencyPrefixes(*adjacent, ndn::time::milliseconds::max());
+ }
+ break;
+ }
+ default:
+ break;
}
}
+void
+Nlsr::initializeFaces(const FetchDatasetCallback& onFetchSuccess,
+ const FetchDatasetTimeoutCallback& onFetchFailure)
+{
+ _LOG_TRACE("Initializing Faces...");
+
+ m_faceDatasetController.fetch<ndn::nfd::FaceDataset>(onFetchSuccess, onFetchFailure);
+
+}
+
+void
+Nlsr::processFaceDataset(const std::vector<ndn::nfd::FaceStatus>& faces)
+{
+ // Iterate over each neighbor listed in nlsr.conf
+ bool anyFaceChanged = false;
+ for (auto&& adjacency : m_adjacencyList.getAdjList()) {
+
+ const std::string faceUriString = adjacency.getFaceUri().toString();
+ // Check the list of FaceStatus objects we got for a match
+ for (const ndn::nfd::FaceStatus& faceStatus : faces) {
+
+ // Set the adjacency FaceID if we find a URI match and it was
+ // previously unset. Change the boolean to true.
+ if (adjacency.getFaceId() == 0 && faceUriString == faceStatus.getRemoteUri()) {
+ adjacency.setFaceId(faceStatus.getFaceId());
+ anyFaceChanged = true;
+ // Register the prefixes for each neighbor
+ this->registerAdjacencyPrefixes(adjacency, ndn::time::milliseconds::max());
+ }
+ }
+ // If this adjacency has no information in this dataset, then one
+ // of two things is happening: 1. NFD is starting slowly and this
+ // Face wasn't ready yet, or 2. NFD is configured
+ // incorrectly and this Face isn't available.
+ if (adjacency.getFaceId() == 0) {
+ _LOG_WARN("The adjacency " << adjacency.getName() <<
+ " has no Face information in this dataset.");
+ }
+ }
+
+ if (anyFaceChanged) {
+ // Only do these things if something has changed. Schedule an
+ // adjacency LSA build to update with all of the new neighbors if
+ // HR is off.
+ if (m_confParam.getHyperbolicState() != HYPERBOLIC_STATE_OFF) {
+ getRoutingTable().scheduleRoutingTableCalculation(*this);
+ }
+ else {
+ m_nlsrLsdb.scheduleAdjLsaBuild();
+ }
+
+ // Begin the Hello Protocol loop immediately, so we don't wait.
+ m_helloProtocol.sendScheduledInterest(0);
+ }
+
+ scheduleDatasetFetch();
+}
+
+void
+Nlsr::registerAdjacencyPrefixes(const Adjacent& adj,
+ const ndn::time::milliseconds& timeout)
+{
+ std::string faceUri = adj.getFaceUri().toString();
+ double linkCost = adj.getLinkCost();
+
+ m_fib.registerPrefix(adj.getName(), faceUri, linkCost,
+ timeout, ndn::nfd::ROUTE_FLAG_CAPTURE, 0);
+
+ m_fib.registerPrefix(m_confParam.getChronosyncPrefix(),
+ faceUri, linkCost, timeout,
+ ndn::nfd::ROUTE_FLAG_CAPTURE, 0);
+
+ m_fib.registerPrefix(m_confParam.getLsaPrefix(),
+ faceUri, linkCost, timeout,
+ ndn::nfd::ROUTE_FLAG_CAPTURE, 0);
+
+ ndn::Name broadcastKeyPrefix = DEFAULT_BROADCAST_PREFIX;
+ broadcastKeyPrefix.append("KEYS");
+ m_fib.registerPrefix(broadcastKeyPrefix,
+ faceUri, linkCost, timeout,
+ ndn::nfd::ROUTE_FLAG_CAPTURE, 0);
+}
+
+void
+Nlsr::onFaceDatasetFetchTimeout(uint32_t code,
+ const std::string& msg,
+ uint32_t nRetriesSoFar)
+{
+ // If we have exceeded the maximum attempt count, do not try again.
+ if (nRetriesSoFar++ < m_confParam.getFaceDatasetFetchTries()) {
+ _LOG_DEBUG("Failed to fetch dataset: " << msg << ". Attempting retry #" << nRetriesSoFar);
+ m_faceDatasetController.fetch<ndn::nfd::FaceDataset>(std::bind(&Nlsr::processFaceDataset,
+ this, _1),
+ std::bind(&Nlsr::onFaceDatasetFetchTimeout,
+ this, _1, _2, nRetriesSoFar));
+ }
+ else {
+ _LOG_ERROR("Failed to fetch dataset: " << msg << ". Exceeded limit of " <<
+ m_confParam.getFaceDatasetFetchTries() << ", so not trying again this time.");
+ // If we fail to fetch it, just do nothing until the next
+ // interval. Since this is a backup mechanism, we aren't as
+ // concerned with retrying.
+ scheduleDatasetFetch();
+ }
+}
+
+void
+Nlsr::scheduleDatasetFetch()
+{
+ m_scheduler.scheduleEvent(m_confParam.getFaceDatasetFetchInterval(),
+ [this] {
+ this->initializeFaces(
+ [this] (const std::vector<ndn::nfd::FaceStatus>& faces) {
+ this->processFaceDataset(faces);
+ },
+ [this] (uint32_t code, const std::string& msg) {
+ this->onFaceDatasetFetchTimeout(code, msg, 0);
+ });
+ });
+}
void
Nlsr::startEventLoop()
diff --git a/src/nlsr.hpp b/src/nlsr.hpp
index 81629ae..bb67f2d 100644
--- a/src/nlsr.hpp
+++ b/src/nlsr.hpp
@@ -33,6 +33,9 @@
#include <ndn-cxx/mgmt/nfd/face-event-notification.hpp>
#include <ndn-cxx/mgmt/nfd/face-monitor.hpp>
#include <ndn-cxx/mgmt/dispatcher.hpp>
+#include <ndn-cxx/mgmt/nfd/face-status.hpp>
+#include <ndn-cxx/data.hpp>
+#include <ndn-cxx/encoding/block.hpp>
#include "adjacency-list.hpp"
#include "common.hpp"
@@ -57,7 +60,9 @@
class Nlsr
{
- friend class NlsrRunner;
+public:
+ using FetchDatasetCallback = std::function<void(const std::vector<ndn::nfd::FaceStatus>&)>;
+ using FetchDatasetTimeoutCallback = std::function<void(uint32_t, const std::string&)>;
class Error : public std::runtime_error
{
@@ -69,7 +74,6 @@
}
};
-public:
Nlsr(boost::asio::io_service& ioService, ndn::Scheduler& scheduler, ndn::Face& face, ndn::KeyChain& keyChain);
void
@@ -225,6 +229,51 @@
void
initialize();
+ /*! \brief Initializes neighbors' Faces using information from NFD.
+ * \sa Nlsr::initialize()
+ * \sa Nlsr::processFaceDataset()
+ *
+ * This function serves as the entry-point for initializing the
+ * neighbors listed in nlsr.conf during Nlsr::initialize(). NLSR
+ * will attempt to fetch a dataset of Faces from NFD, and configure
+ * each of its neighbors using information from that dataset. The
+ * explicit callbacks allow for better testability.
+ */
+ void
+ initializeFaces(const FetchDatasetCallback& onFetchSuccess,
+ const FetchDatasetTimeoutCallback& onFetchFailure);
+
+ void
+ onFaceDatasetFetchTimeout(uint32_t code,
+ const std::string& reason,
+ uint32_t nRetriesSoFar);
+
+ /*! \brief Consumes a Face StatusDataset to configure NLSR neighbors.
+ * \sa Nlsr::initializeFaces
+ * \param faces A Face Dataset that should conform to FaceMgmt specifications.
+ *
+ * This function processes a Face StatusDataset that should conform
+ * to the FaceMgmt specifications listed
+ * [here](https://redmine.named-data.net/projects/nfd/wiki/FaceMgmt#Face-Dataset).
+ * Any newly configured neighbors will have prefixes registered with NFD
+ * and be sent Hello Interests as well.
+ */
+ void
+ processFaceDataset(const std::vector<ndn::nfd::FaceStatus>& faces);
+
+ /*! \brief Registers NLSR-specific prefixes for a neighbor (Adjacent)
+ * \sa Nlsr::initializeFaces
+ * \param adj A reference to the neighbor to register prefixes for
+ * \param timeout The amount of time to give NFD to respond to *each* registration request.
+ *
+ * Registers the prefixes in NFD that NLSR needs to route with a
+ * neighbor. The timeout given is how long to set the timeout for
+ * *each* registration request that is made.
+ */
+ void
+ registerAdjacencyPrefixes(const Adjacent& adj,
+ const ndn::time::milliseconds& timeout);
+
void
initializeKey();
@@ -297,14 +346,6 @@
}
void
- createFace(const std::string& faceUri,
- const CommandSucceedCallback& onSuccess,
- const CommandFailCallback& onFailure);
-
- void
- destroyFaces();
-
- void
setStrategies();
void
@@ -316,8 +357,7 @@
return m_firstHelloInterval;
}
- /**
- * \brief Canonize the URI for this and all proceeding neighbors in a list.
+ /*! \brief Canonize the URI for this and all proceeding neighbors in a list.
*
* This function canonizes the URI of the Adjacent object pointed to
* by currentNeighbor. It then executes the then callback, providing
@@ -365,12 +405,6 @@
onKeyPrefixRegSuccess(const ndn::Name& name);
void
- onDestroyFaceSuccess(const ndn::nfd::ControlParameters& commandSuccessResult);
-
- void
- onDestroyFaceFailure(const ndn::nfd::ControlResponse& response);
-
- void
onFaceEventNotification(const ndn::nfd::FaceEventNotification& faceEventNotification);
void
@@ -379,8 +413,7 @@
m_firstHelloInterval = interval;
}
- /**
- * \brief Continues canonizing neighbor URIs.
+ /*! \brief Continues canonizing neighbor URIs.
*
* For testability reasons, we want what each instance of
* canonization does after completion to be controllable. The best
@@ -390,6 +423,9 @@
void
canonizeContinuation(std::list<Adjacent>::iterator iterator);
+ void
+ scheduleDatasetFetch();
+
public:
static const ndn::Name LOCALHOST_PREFIX;
@@ -421,7 +457,13 @@
private:
std::shared_ptr<ndn::CertificateCacheTtl> m_certificateCache;
security::CertificateStore m_certStore;
+
+PUBLIC_WITH_TESTS_ELSE_PRIVATE:
Validator m_validator;
+
+private:
+ ndn::nfd::Controller m_controller;
+ ndn::nfd::Controller m_faceDatasetController;
ndn::security::SigningInfo m_signingInfo;
ndn::Name m_defaultCertName;
update::PrefixUpdateProcessor m_prefixUpdateProcessor;
@@ -430,6 +472,8 @@
ndn::nfd::FaceMonitor m_faceMonitor;
uint32_t m_firstHelloInterval;
+
+ friend class NlsrRunner;
};
} // namespace nlsr
diff --git a/src/route/fib.cpp b/src/route/fib.cpp
index 73cde75..49ce647 100644
--- a/src/route/fib.cpp
+++ b/src/route/fib.cpp
@@ -209,37 +209,6 @@
}
void
-Fib::createFace(const std::string& faceUri,
- const CommandSucceedCallback& onSuccess,
- const CommandFailCallback& onFailure)
-{
- m_faceController.createFace(faceUri, onSuccess, onFailure);
-}
-
-void
-Fib::destroyFace(const std::string& faceUri,
- const CommandSucceedCallback& onSuccess,
- const CommandFailCallback& onFailure)
-{
- createFace(faceUri,
- std::bind(&Fib::destroyFaceInNfd, this, _1, onSuccess, onFailure),
- onFailure);
-}
-
-void
-Fib::destroyFaceInNfd(const ndn::nfd::ControlParameters& faceDestroyResult,
- const CommandSucceedCallback& onSuccess,
- const CommandFailCallback& onFailure)
-{
- ndn::nfd::ControlParameters faceParameters;
- faceParameters
- .setFaceId(faceDestroyResult.getFaceId());
- m_controller.start<ndn::nfd::FaceDestroyCommand>(faceParameters,
- onSuccess,
- onFailure);
-}
-
-void
Fib::registerPrefix(const ndn::Name& namePrefix, const std::string& faceUri,
uint64_t faceCost, const ndn::time::milliseconds& timeout,
uint64_t flags, uint8_t times)
@@ -264,35 +233,6 @@
}
}
-typedef void(Fib::*RegisterPrefixCallback)(const ndn::nfd::ControlParameters&,
- const ndn::nfd::ControlParameters&, uint8_t,
- const CommandSucceedCallback&,
- const CommandFailCallback&);
-
-void
-Fib::registerPrefix(const ndn::Name& namePrefix,
- const std::string& faceUri,
- uint64_t faceCost,
- const ndn::time::milliseconds& timeout,
- uint64_t flags,
- uint8_t times,
- const CommandSucceedCallback& onSuccess,
- const CommandFailCallback& onFailure)
-
-{
- ndn::nfd::ControlParameters parameters;
- parameters
- .setName(namePrefix)
- .setFlags(flags)
- .setCost(faceCost)
- .setExpirationPeriod(timeout)
- .setOrigin(ndn::nfd::ROUTE_ORIGIN_NLSR);
- createFace(faceUri,
- std::bind(static_cast<RegisterPrefixCallback>(&Fib::registerPrefixInNfd),
- this, _1, parameters, times, onSuccess, onFailure),
- onFailure);
-}
-
void
Fib::registerPrefixInNfd(ndn::nfd::ControlParameters& parameters,
const std::string& faceUri,
@@ -304,33 +244,13 @@
"Successful in name registration",
faceUri),
std::bind(&Fib::onRegistrationFailure,
- this, _1,
+ this, _1,
"Failed in name registration",
parameters,
faceUri, times));
}
void
-Fib::registerPrefixInNfd(const ndn::nfd::ControlParameters& faceCreateResult,
- const ndn::nfd::ControlParameters& parameters,
- uint8_t times,
- const CommandSucceedCallback& onSuccess,
- const CommandFailCallback& onFailure)
-{
- ndn::nfd::ControlParameters controlParameters;
- controlParameters
- .setName(parameters.getName())
- .setFaceId(faceCreateResult.getFaceId())
- .setCost(parameters.getCost())
- .setFlags(parameters.getFlags())
- .setExpirationPeriod(parameters.getExpirationPeriod())
- .setOrigin(ndn::nfd::ROUTE_ORIGIN_NLSR);
- m_controller.start<ndn::nfd::RibRegisterCommand>(controlParameters,
- onSuccess,
- onFailure);
-}
-
-void
Fib::unregisterPrefix(const ndn::Name& namePrefix, const std::string& faceUri)
{
uint32_t faceId = m_faceMap.getFaceId(faceUri);
@@ -374,6 +294,9 @@
_LOG_DEBUG("Register successful Prefix: " << commandSuccessResult.getName() <<
" Face Uri: " << faceUri);
+ // Update the adjacency list with the new Face ID
+ m_adjacencyList.findAdjacent(faceUri)->setFaceId(commandSuccessResult.getFaceId());
+ // Update the fast-access FaceMap with the new Face ID, too
m_faceMap.update(faceUri, commandSuccessResult.getFaceId());
m_faceMap.writeLog();
}
diff --git a/src/route/fib.hpp b/src/route/fib.hpp
index 10aa4fa..2705e47 100644
--- a/src/route/fib.hpp
+++ b/src/route/fib.hpp
@@ -26,15 +26,12 @@
#include "face-map.hpp"
#include "fib-entry.hpp"
#include "test-access-control.hpp"
-#include "utility/face-controller.hpp"
#include <ndn-cxx/mgmt/nfd/controller.hpp>
#include <ndn-cxx/util/time.hpp>
namespace nlsr {
-typedef ndn::nfd::Controller::CommandSucceedCallback CommandSucceedCallback;
-typedef ndn::nfd::Controller::CommandFailCallback CommandFailCallback;
typedef std::function<void(FibEntry&)> afterRefreshCallback;
class AdjacencyList;
@@ -49,7 +46,6 @@
: m_scheduler(scheduler)
, m_refreshTime(0)
, m_controller(face, keyChain)
- , m_faceController(face.getIoService(), m_controller)
, m_adjacencyList(adjacencyList)
, m_confParameter(conf)
{
@@ -82,26 +78,11 @@
uint8_t times);
void
- registerPrefix(const ndn::Name& namePrefix,
- const std::string& faceUri,
- uint64_t faceCost,
- const ndn::time::milliseconds& timeout,
- uint64_t flags,
- uint8_t times,
- const CommandSucceedCallback& onSuccess,
- const CommandFailCallback& onFailure);
-
- void
setStrategy(const ndn::Name& name, const std::string& strategy, uint32_t count);
void
writeLog();
- void
- destroyFace(const std::string& faceUri,
- const CommandSucceedCallback& onSuccess,
- const CommandFailCallback& onFailure);
-
private:
bool
isPrefixUpdatable(const ndn::Name& name);
@@ -113,28 +94,11 @@
getNumberOfFacesForName(NexthopList& nextHopList);
void
- createFace(const std::string& faceUri,
- const CommandSucceedCallback& onSuccess,
- const CommandFailCallback& onFailure);
-
- void
registerPrefixInNfd(ndn::nfd::ControlParameters& parameters,
const std::string& faceUri,
uint8_t times);
void
- registerPrefixInNfd(const ndn::nfd::ControlParameters& faceCreateResult,
- const ndn::nfd::ControlParameters& parameters,
- uint8_t times,
- const CommandSucceedCallback& onSuccess,
- const CommandFailCallback& onFailure);
-
- void
- destroyFaceInNfd(const ndn::nfd::ControlParameters& faceDestroyResult,
- const CommandSucceedCallback& onSuccess,
- const CommandFailCallback& onFailure);
-
- void
unregisterPrefix(const ndn::Name& namePrefix, const std::string& faceUri);
void
@@ -184,7 +148,6 @@
ndn::Scheduler& m_scheduler;
int32_t m_refreshTime;
ndn::nfd::Controller m_controller;
- util::FaceController m_faceController;
PUBLIC_WITH_TESTS_ELSE_PRIVATE:
FaceMap m_faceMap;
diff --git a/src/utility/face-controller.cpp b/src/utility/face-controller.cpp
deleted file mode 100644
index e6c0a8b..0000000
--- a/src/utility/face-controller.cpp
+++ /dev/null
@@ -1,93 +0,0 @@
-/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
-/**
- * Copyright (c) 2014-2017, The University of Memphis,
- * Regents of the University of California
- *
- * This file is part of NLSR (Named-data Link State Routing).
- * See AUTHORS.md for complete list of NLSR authors and contributors.
- *
- * NLSR 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.
- *
- * NLSR 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
- * NLSR, e.g., in COPYING.md file. If not, see <http://www.gnu.org/licenses/>.
- *
- **/
-
-#include "face-controller.hpp"
-
-#include "common.hpp"
-#include "logger.hpp"
-
-namespace nlsr {
-namespace util {
-
-INIT_LOGGER("FaceController");
-
-using ndn::util::FaceUri;
-
-void
-FaceController::createFace(const std::string& request,
- const CommandSuccessCallback& onSuccess,
- const CommandFailureCallback& onFailure)
-{
- FaceUri uri(request);
-
- _LOG_TRACE("Converting " << uri << " to canonical form");
- uri.canonize(std::bind(&FaceController::onCanonizeSuccess, this, _1, onSuccess, onFailure, uri),
- std::bind(&FaceController::onCanonizeFailure, this, _1, onSuccess, onFailure, uri),
- m_ioService, TIME_ALLOWED_FOR_CANONIZATION);
-}
-
-void
-FaceController::createFaceInNfd(const FaceUri& uri,
- const CommandSuccessCallback& onSuccess,
- const CommandFailureCallback& onFailure)
-{
- ndn::nfd::ControlParameters faceParameters;
- faceParameters.setUri(uri.toString());
-
- _LOG_DEBUG("Creating Face in NFD with face-uri: " << uri);
- m_controller.start<ndn::nfd::FaceCreateCommand>(faceParameters, onSuccess,
- [onSuccess, onFailure, uri] (const ndn::nfd::ControlResponse& response) {
- ndn::nfd::ControlParameters faceParams(response.getBody());
- if (response.getCode() == 409 && faceParams.getUri() == uri.toString()) {
- _LOG_DEBUG("Got 409 - treating as success");
- onSuccess(faceParams);
- }
- else {
- onFailure(response);
- }
- }
- );
-}
-
-void
-FaceController::onCanonizeSuccess(const FaceUri& uri,
- const CommandSuccessCallback& onSuccess,
- const CommandFailureCallback& onFailure,
- const FaceUri& request)
-{
- _LOG_DEBUG("Converted " << request << " to canonical form: " << uri);
-
- createFaceInNfd(uri, onSuccess, onFailure);
-}
-
-void
-FaceController::onCanonizeFailure(const std::string& reason,
- const CommandSuccessCallback& onSuccess,
- const CommandFailureCallback& onFailure,
- const FaceUri& request)
-{
- _LOG_WARN("Could not convert " << request << " to canonical form: " << reason);
- onFailure(ndn::nfd::ControlResponse(CANONIZE_ERROR_CODE,
- "Could not canonize face-uri: " + request.toString()));
-}
-
-} // namespace util
-} // namespace nlsr
diff --git a/src/utility/face-controller.hpp b/src/utility/face-controller.hpp
deleted file mode 100644
index d44c2ec..0000000
--- a/src/utility/face-controller.hpp
+++ /dev/null
@@ -1,76 +0,0 @@
-/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
-/**
- * Copyright (c) 2014-2017, The University of Memphis,
- * Regents of the University of California,
- * Arizona Board of Regents.
- *
- * This file is part of NLSR (Named-data Link State Routing).
- * See AUTHORS.md for complete list of NLSR authors and contributors.
- *
- * NLSR 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.
- *
- * NLSR 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
- * NLSR, e.g., in COPYING.md file. If not, see <http://www.gnu.org/licenses/>.
- **/
-
-#ifndef NLSR_UTIL_FACE_CONTROLLER_HPP
-#define NLSR_UTIL_FACE_CONTROLLER_HPP
-
-#include <ndn-cxx/util/face-uri.hpp>
-#include <ndn-cxx/mgmt/nfd/controller.hpp>
-
-namespace nlsr {
-namespace util {
-
-class FaceController : boost::noncopyable
-{
-public:
- typedef ndn::nfd::Controller::CommandSucceedCallback CommandSuccessCallback;
- typedef ndn::nfd::Controller::CommandFailCallback CommandFailureCallback;
-
- FaceController(boost::asio::io_service& io, ndn::nfd::Controller& controller)
- : m_ioService(io)
- , m_controller(controller)
- {
- }
-
- void
- createFace(const std::string& request,
- const CommandSuccessCallback& onSuccess,
- const CommandFailureCallback& onFailure);
-
-private:
- void
- createFaceInNfd(const ndn::util::FaceUri& uri,
- const CommandSuccessCallback& onSuccess,
- const CommandFailureCallback& onFailure);
-
- void
- onCanonizeSuccess(const ndn::util::FaceUri& uri,
- const CommandSuccessCallback& onSuccess,
- const CommandFailureCallback& onFailure,
- const ndn::util::FaceUri& request);
-
- void
- onCanonizeFailure(const std::string& reason,
- const CommandSuccessCallback& onSuccess,
- const CommandFailureCallback& onFailure,
- const ndn::util::FaceUri& request);
-
-private:
- boost::asio::io_service& m_ioService;
- ndn::nfd::Controller& m_controller;
-
- static const uint32_t CANONIZE_ERROR_CODE = 408;
-};
-
-} // namespace util
-} // namespace nlsr
-
-#endif // NLSR_UTIL_FACE_CONTROLLER_HPP
diff --git a/src/validator.cpp b/src/validator.cpp
new file mode 100644
index 0000000..a73c9ee
--- /dev/null
+++ b/src/validator.cpp
@@ -0,0 +1,89 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/**
+ * Copyright (c) 2014-2017, The University of Memphis,
+ * Regents of the University of California
+ *
+ * This file is part of NLSR (Named-data Link State Routing).
+ * See AUTHORS.md for complete list of NLSR authors and contributors.
+ *
+ * NLSR 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.
+ *
+ * NLSR 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
+ * NLSR, e.g., in COPYING.md file. If not, see <http://www.gnu.org/licenses/>.
+ **/
+
+#include "validator.hpp"
+
+namespace nlsr {
+
+void
+Validator::checkPolicy(const ndn::Data& data, int nSteps, const ndn::OnDataValidated& onValidated,
+ const ndn::OnDataValidationFailed& onValidationFailed,
+ std::vector<shared_ptr<ndn::ValidationRequest>>& nextSteps)
+{
+ if (!m_shouldValidate) {
+ onValidated(data.shared_from_this());
+ }
+ else {
+ ValidatorConfig::checkPolicy(data, nSteps, onValidated, onValidationFailed, nextSteps);
+ }
+}
+
+void
+Validator::afterCheckPolicy(const NextSteps& nextSteps, const OnFailure& onFailure)
+{
+ if (m_face == nullptr) {
+ onFailure("Require more information to validate the packet!");
+ return;
+ }
+
+ for (const std::shared_ptr<ndn::ValidationRequest>& request : nextSteps) {
+
+ ndn::Interest& interest = request->m_interest;
+
+ // Look for certificate in permanent storage
+ std::shared_ptr<const ndn::IdentityCertificate> cert = m_certStore.find(interest.getName());
+
+ if (cert != nullptr) {
+ // If the certificate is found, no reason to express interest
+ std::shared_ptr<ndn::Data> data = std::make_shared<ndn::Data>(interest.getName());
+ data->setContent(cert->wireEncode());
+
+ Validator::onData(interest, *data, request);
+ }
+ else {
+ // Prepend broadcast prefix to interest name
+ ndn::Name broadcastName = m_broadcastPrefix;
+ broadcastName.append(interest.getName());
+ interest.setName(broadcastName);
+
+ // Attempt to fetch the certificate
+ m_face->expressInterest(interest,
+ std::bind(&Validator::onData, this, _1, _2, request),
+ std::bind(&Validator::onTimeout, // Nack
+ this, _1, request->m_nRetries,
+ onFailure,
+ request),
+ std::bind(&Validator::onTimeout,
+ this, _1, request->m_nRetries,
+ onFailure,
+ request));
+ }
+ }
+}
+
+std::shared_ptr<const ndn::Data>
+Validator::preCertificateValidation(const ndn::Data& data)
+{
+ std::shared_ptr<ndn::Data> internalData = std::make_shared<ndn::Data>();
+ internalData->wireDecode(data.getContent().blockFromValue());
+ return internalData;
+}
+
+} // namespace nlsr
diff --git a/src/validator.hpp b/src/validator.hpp
index 4387ea5..c4f2a19 100644
--- a/src/validator.hpp
+++ b/src/validator.hpp
@@ -49,6 +49,7 @@
security::CertificateStore& certStore,
const int stepLimit = 10)
: ndn::ValidatorConfig(face, cache, ndn::ValidatorConfig::DEFAULT_GRACE_INTERVAL, stepLimit)
+ , m_shouldValidate(true)
, m_broadcastPrefix(broadcastPrefix)
, m_certStore(certStore)
{
@@ -75,57 +76,22 @@
protected:
typedef std::vector<std::shared_ptr<ndn::ValidationRequest>> NextSteps;
- virtual void
+ void
+ checkPolicy(const ndn::Data& data,
+ int nSteps,
+ const ndn::OnDataValidated& onValidated,
+ const ndn::OnDataValidationFailed& onValidationFailed,
+ std::vector<shared_ptr<ndn::ValidationRequest>>& nextSteps) override;
+
+ void
afterCheckPolicy(const NextSteps& nextSteps,
- const OnFailure& onFailure)
- {
- if (m_face == nullptr) {
- onFailure("Require more information to validate the packet!");
- return;
- }
+ const OnFailure& onFailure) override;
- for (const std::shared_ptr<ndn::ValidationRequest>& request : nextSteps) {
+ std::shared_ptr<const ndn::Data>
+ preCertificateValidation(const ndn::Data& data) override;
- ndn::Interest& interest = request->m_interest;
-
- // Look for certificate in permanent storage
- std::shared_ptr<const ndn::IdentityCertificate> cert = m_certStore.find(interest.getName());
-
- if (cert != nullptr) {
- // If the certificate is found, no reason to express interest
- std::shared_ptr<ndn::Data> data = std::make_shared<ndn::Data>(interest.getName());
- data->setContent(cert->wireEncode());
-
- Validator::onData(interest, *data, request);
- }
- else {
- // Prepend broadcast prefix to interest name
- ndn::Name broadcastName = m_broadcastPrefix;
- broadcastName.append(interest.getName());
- interest.setName(broadcastName);
-
- // Attempt to fetch the certificate
- m_face->expressInterest(interest,
- std::bind(&Validator::onData, this, _1, _2, request),
- std::bind(&Validator::onTimeout, // Nack
- this, _1, request->m_nRetries,
- onFailure,
- request),
- std::bind(&Validator::onTimeout,
- this, _1, request->m_nRetries,
- onFailure,
- request));
- }
- }
- }
-
- virtual std::shared_ptr<const ndn::Data>
- preCertificateValidation(const ndn::Data& data)
- {
- std::shared_ptr<ndn::Data> internalData = std::make_shared<ndn::Data>();
- internalData->wireDecode(data.getContent().blockFromValue());
- return internalData;
- }
+PUBLIC_WITH_TESTS_ELSE_PRIVATE:
+ bool m_shouldValidate;
private:
ndn::Name m_broadcastPrefix;