33 #include <ndn-cxx/lp/tags.hpp>
34 #include <ndn-cxx/mgmt/nfd/face-status.hpp>
35 #include <ndn-cxx/mgmt/nfd/rib-entry.hpp>
36 #include <ndn-cxx/security/certificate-fetcher-direct-fetch.hpp>
50 ndn::nfd::Controller& nfdController, Dispatcher& dispatcher)
53 , m_keyChain(keyChain)
54 , m_nfdController(nfdController)
55 , m_dispatcher(dispatcher)
57 , m_localhostValidator(face)
58 , m_localhopValidator(make_unique<
ndn::security::CertificateFetcherDirectFetch>(face))
59 , m_paValidator(make_unique<
ndn::security::CertificateFetcherDirectFetch>(face))
60 , m_isLocalhopEnabled(false)
62 registerCommandHandler<ndn::nfd::RibRegisterCommand>(
"register",
63 std::bind(&RibManager::registerEntry,
this, _2, _3, _4, _5));
64 registerCommandHandler<ndn::nfd::RibUnregisterCommand>(
"unregister",
65 std::bind(&RibManager::unregisterEntry,
this, _2, _3, _4, _5));
73 m_localhostValidator.load(section, filename);
79 m_localhopValidator.load(section, filename);
80 m_isLocalhopEnabled =
true;
86 m_isLocalhopEnabled =
false;
92 m_paValidator.load(section, filename);
100 if (m_isLocalhopEnabled) {
104 NFD_LOG_INFO(
"Start monitoring face create/destroy events");
105 m_faceMonitor.onNotification.connect([
this] (
const auto& notif) { onNotification(notif); });
106 m_faceMonitor.start();
114 m_nfdController.start<ndn::nfd::FaceUpdateCommand>(
115 ControlParameters().setFlagBit(ndn::nfd::BIT_LOCAL_FIELDS_ENABLED,
true),
116 [] (
const ControlParameters&) {
119 [] (
const ControlResponse& res) {
120 NDN_THROW(
Error(
"Couldn't enable local fields (" + to_string(res.getCode()) +
121 " " + res.getText() +
")"));
126 RibManager::beginAddRoute(
const Name& name,
Route route, std::optional<time::nanoseconds> expires,
127 const std::function<
void(RibUpdateResult)>& done)
130 route.
expires = time::steady_clock::now() + *expires;
133 expires = *route.
expires - time::steady_clock::now();
136 if (expires && *expires <= 0_s) {
138 return done(RibUpdateResult::EXPIRED);
142 " origin=" << route.
origin <<
" cost=" << route.
cost);
154 beginRibUpdate(update, done);
158 RibManager::beginRemoveRoute(
const Name& name,
const Route& route,
159 const std::function<
void(RibUpdateResult)>& done)
161 NFD_LOG_INFO(
"Removing route " << name <<
" nexthop=" << route.faceId <<
162 " origin=" << route.origin);
168 beginRibUpdate(update, done);
172 RibManager::beginRibUpdate(
const RibUpdate& update,
173 const std::function<
void(RibUpdateResult)>& done)
178 done(RibUpdateResult::OK);
180 [=] (uint32_t code,
const std::string& error) {
181 NFD_LOG_DEBUG(
"RIB update failed for " << update <<
" (" << code <<
" " << error <<
")");
184 scheduleActiveFaceFetch(1_s);
186 done(RibUpdateResult::ERROR);
191 RibManager::registerTopPrefix(
const Name& topPrefix)
194 m_nfdController.start<ndn::nfd::FibAddNextHopCommand>(
197 [=] (
const ControlParameters& res) {
198 NFD_LOG_DEBUG(
"Successfully registered " << topPrefix <<
" with NFD");
202 route.faceId = res.getFaceId();
203 route.origin = ndn::nfd::ROUTE_ORIGIN_APP;
204 route.flags = ndn::nfd::ROUTE_FLAG_CHILD_INHERIT;
206 m_rib.
insert(topPrefix, route);
208 [=] (
const ControlResponse& res) {
209 NDN_THROW(Error(
"Cannot add FIB entry " + topPrefix.toUri() +
" (" +
210 to_string(res.getCode()) +
" " + res.getText() +
")"));
214 m_dispatcher.addTopPrefix(topPrefix,
false);
218 RibManager::registerEntry(
const Name& topPrefix,
const Interest& interest,
219 ControlParameters parameters,
220 const ndn::mgmt::CommandContinuation& done)
223 done(ControlResponse(414,
"Route prefix cannot exceed " + to_string(
Fib::getMaxDepth()) +
228 setFaceForSelfRegistration(interest, parameters);
231 done(ControlResponse(200,
"Success").setBody(parameters.wireEncode()));
234 route.faceId = parameters.getFaceId();
235 route.origin = parameters.getOrigin();
236 route.cost = parameters.getCost();
237 route.flags = parameters.getFlags();
239 std::optional<time::nanoseconds> expires;
240 if (parameters.hasExpirationPeriod() &&
241 parameters.getExpirationPeriod() != time::milliseconds::max()) {
242 expires = time::duration_cast<time::nanoseconds>(parameters.getExpirationPeriod());
245 beginAddRoute(parameters.getName(), std::move(route), expires, [] (RibUpdateResult) {});
249 RibManager::unregisterEntry(
const Name&,
const Interest& interest,
250 ControlParameters parameters,
251 const ndn::mgmt::CommandContinuation& done)
253 setFaceForSelfRegistration(interest, parameters);
256 done(ControlResponse(200,
"Success").setBody(parameters.wireEncode()));
259 route.faceId = parameters.getFaceId();
260 route.origin = parameters.getOrigin();
262 beginRemoveRoute(parameters.getName(), route, [] (
auto&&...) {});
266 RibManager::listEntries(
const Name&,
const Interest&, ndn::mgmt::StatusDatasetContext& context)
268 auto now = time::steady_clock::now();
269 for (
const auto& kv : m_rib) {
270 const rib::RibEntry& entry = *kv.second;
271 ndn::nfd::RibEntry item;
272 item.setName(entry.getName());
273 for (
const Route& route : entry.getRoutes()) {
275 r.setFaceId(route.faceId);
276 r.setOrigin(route.origin);
277 r.setCost(route.cost);
278 r.setFlags(route.flags);
280 r.setExpirationPeriod(time::duration_cast<time::milliseconds>(*route.expires - now));
284 context.append(item.wireEncode());
290 RibManager::setFaceForSelfRegistration(
const Interest& request, ControlParameters& parameters)
292 bool isSelfRegistration = (parameters.getFaceId() == 0);
293 if (isSelfRegistration) {
294 shared_ptr<lp::IncomingFaceIdTag> incomingFaceIdTag = request.getTag<lp::IncomingFaceIdTag>();
298 BOOST_ASSERT(incomingFaceIdTag !=
nullptr);
299 parameters.setFaceId(*incomingFaceIdTag);
303 ndn::mgmt::Authorization
304 RibManager::makeAuthorization(
const std::string&)
306 return [
this] (
const Name& prefix,
const Interest& interest,
307 const ndn::mgmt::ControlParameters* params,
308 const ndn::mgmt::AcceptContinuation& accept,
309 const ndn::mgmt::RejectContinuation& reject) {
310 BOOST_ASSERT(params !=
nullptr);
311 BOOST_ASSERT(
typeid(*params) ==
typeid(ndn::nfd::ControlParameters));
315 validator.validate(interest,
316 [&interest, accept] (
auto&&...) { accept(
extractSigner(interest)); },
317 [reject] (
auto&&...) { reject(ndn::mgmt::RejectReply::STATUS403); });
328 return os <<
"ERROR";
330 return os <<
"VALIDATION_FAILURE";
332 return os <<
"EXPIRED";
334 return os <<
"NOT_FOUND";
336 NDN_THROW(std::invalid_argument(
"Unknown SlAnnounceResult"));
340 RibManager::getSlAnnounceResultFromRibUpdateResult(RibUpdateResult r)
343 case RibUpdateResult::OK:
345 case RibUpdateResult::ERROR:
347 case RibUpdateResult::EXPIRED:
357 BOOST_ASSERT(pa.getData());
359 m_paValidator.validate(*pa.getData(),
361 Route route(pa, faceId);
362 route.expires = std::min(route.annExpires, time::steady_clock::now() + maxLifetime);
363 beginAddRoute(pa.getAnnouncedName(), route, std::nullopt,
364 [=] (RibUpdateResult ribRes) {
365 auto res = getSlAnnounceResultFromRibUpdateResult(ribRes);
366 NFD_LOG_INFO(
"slAnnounce " << pa.getAnnouncedName() <<
" " << faceId <<
": " << res);
370 [=] (
const Data&, ndn::security::ValidationError err) {
371 NFD_LOG_INFO(
"slAnnounce " << pa.getAnnouncedName() <<
" " << faceId <<
372 " validation error: " << err);
373 cb(SlAnnounceResult::VALIDATION_FAILURE);
379 RibManager::slRenew(
const Name& name, uint64_t faceId, time::milliseconds maxLifetime,
383 routeQuery.
faceId = faceId;
384 routeQuery.
origin = ndn::nfd::ROUTE_ORIGIN_PREFIXANN;
385 Route* oldRoute = m_rib.findLongestPrefix(name, routeQuery);
388 NFD_LOG_DEBUG(
"slRenew " << name <<
" " << faceId <<
": not found");
389 return cb(SlAnnounceResult::NOT_FOUND);
391 Name routeName = oldRoute->
announcement->getAnnouncedName();
393 Route route = *oldRoute;
394 route.
expires = std::min(route.
annExpires, time::steady_clock::now() + maxLifetime);
395 beginAddRoute(routeName, route, std::nullopt,
396 [=] (RibUpdateResult ribRes) {
397 auto res = getSlAnnounceResultFromRibUpdateResult(ribRes);
398 NFD_LOG_INFO(
"slRenew " << name <<
" " << faceId <<
": " << res <<
" " << routeName);
406 shared_ptr<rib::RibEntry> entry;
407 auto exactMatch = m_rib.find(name);
408 if (exactMatch != m_rib.end()) {
409 entry = exactMatch->second;
412 entry = m_rib.findParent(name);
414 if (entry ==
nullptr) {
415 return cb(std::nullopt);
418 auto pa = entry->getPrefixAnnouncement();
419 pa.toData(m_keyChain);
424 RibManager::fetchActiveFaces()
428 m_nfdController.fetch<ndn::nfd::FaceDataset>(
429 std::bind(&RibManager::removeInvalidFaces,
this, _1),
430 std::bind(&RibManager::onFetchActiveFacesFailure,
this, _1, _2),
431 ndn::nfd::CommandOptions());
435 RibManager::onFetchActiveFacesFailure(uint32_t code,
const std::string& reason)
437 NFD_LOG_DEBUG(
"Face Status Dataset request failure " << code <<
" " << reason);
442 RibManager::scheduleActiveFaceFetch(
const time::seconds& timeToWait)
444 m_activeFaceFetchEvent =
getScheduler().schedule(timeToWait, [
this] { fetchActiveFaces(); });
448 RibManager::removeInvalidFaces(
const std::vector<ndn::nfd::FaceStatus>& activeFaces)
452 std::set<uint64_t> activeFaceIds;
453 for (
const auto& faceStatus : activeFaces) {
454 activeFaceIds.insert(faceStatus.getFaceId());
463 RibManager::onNotification(
const ndn::nfd::FaceEventNotification& notification)
467 if (notification.getKind() == ndn::nfd::FACE_EVENT_DESTROYED) {
468 NFD_LOG_DEBUG(
"Received notification for destroyed FaceId " << notification.getFaceId());
469 getGlobalIoService().post([
this,
id = notification.getFaceId()] { m_rib.beginRemoveFace(id); });
A collection of common functions shared by all NFD managers, such as communicating with the dispatche...
void registerStatusDatasetHandler(const std::string &verb, const ndn::mgmt::StatusDatasetHandler &handler)
static std::string extractSigner(const Interest &interest)
Extracts the name from the KeyLocator of a ControlCommand request.
std::function< void(SlAnnounceResult res)> SlAnnounceCallback
void registerWithNfd()
Start accepting commands and dataset requests.
void disableLocalhop()
Disallow accepting commands on /localhop/nfd/rib prefix.
RibManager(rib::Rib &rib, ndn::Face &face, ndn::KeyChain &keyChain, ndn::nfd::Controller &nfdController, Dispatcher &dispatcher)
static const Name LOCALHOP_TOP_PREFIX
void applyLocalhostConfig(const ConfigSection §ion, const std::string &filename)
Apply localhost_security configuration.
void enableLocalhop(const ConfigSection §ion, const std::string &filename)
Apply localhop_security configuration and allow accepting commands on /localhop/nfd/rib prefix.
void slAnnounce(const ndn::PrefixAnnouncement &pa, uint64_t faceId, time::milliseconds maxLifetime, const SlAnnounceCallback &cb)
Insert a route by prefix announcement from self-learning strategy.
std::function< void(std::optional< ndn::PrefixAnnouncement >)> SlFindAnnCallback
@ VALIDATION_FAILURE
the announcement cannot be verified against the trust schema
@ EXPIRED
the announcement has expired
@ NOT_FOUND
route does not exist (slRenew only)
@ OK
RIB and FIB have been updated.
void enableLocalFields()
Enable NDNLP IncomingFaceId field in order to support self-registration commands.
void applyPaConfig(const ConfigSection §ion, const std::string &filename)
Apply prefix_announcement_validation configuration.
static constexpr size_t getMaxDepth()
Maximum number of components in a FIB entry prefix.
Represents the Routing Information Base.
void insert(const Name &prefix, const Route &route)
void onRouteExpiration(const Name &prefix, const Route &route)
void beginApplyUpdate(const RibUpdate &update, const UpdateSuccessCallback &onSuccess, const UpdateFailureCallback &onFailure)
Passes the provided RibUpdateBatch to FibUpdater to calculate and send FibUpdates.
Represents a route for a name prefix.
ndn::nfd::RouteOrigin origin
time::steady_clock::time_point annExpires
Expiration time of the prefix announcement.
std::optional< time::steady_clock::time_point > expires
void setExpirationEvent(const scheduler::EventId &eid)
std::optional< ndn::PrefixAnnouncement > announcement
The prefix announcement that caused the creation of this route.
#define NFD_LOG_INIT(name)
boost::property_tree::ptree ConfigSection
A configuration file section.
const std::string MGMT_MODULE_NAME
constexpr time::seconds ACTIVE_FACE_FETCH_INTERVAL
std::ostream & operator<<(std::ostream &os, const Network &network)
boost::asio::io_service & getGlobalIoService()
Returns the global io_service instance for the calling thread.
Scheduler & getScheduler()
Returns the global Scheduler instance for the calling thread.
const Name LOCALHOST_TOP_PREFIX