30 #include <ndn-cxx/lp/tags.hpp>
31 #include <ndn-cxx/mgmt/nfd/face-status.hpp>
32 #include <ndn-cxx/mgmt/nfd/rib-entry.hpp>
39 const Name RibManager::LOCAL_HOST_TOP_PREFIX =
"/localhost/nfd";
40 const Name RibManager::LOCAL_HOP_TOP_PREFIX =
"/localhop/nfd";
41 const std::string RibManager::MGMT_MODULE_NAME =
"rib";
42 const Name RibManager::FACES_LIST_DATASET_PREFIX =
"/localhost/nfd/faces/list";
43 const time::seconds RibManager::ACTIVE_FACE_FETCH_INTERVAL = time::seconds(300);
47 ndn::KeyChain& keyChain)
50 , m_keyChain(keyChain)
51 , m_nfdController(m_face, m_keyChain)
52 , m_faceMonitor(m_face)
53 , m_localhostValidator(m_face)
54 , m_localhopValidator(m_face)
55 , m_isLocalhopEnabled(false)
56 , m_prefixPropagator(m_nfdController, m_keyChain, m_rib)
57 , m_fibUpdater(m_rib, m_nfdController)
58 , m_addTopPrefix([&dispatcher] (const Name& topPrefix) {
59 dispatcher.addTopPrefix(topPrefix,
false);
62 registerCommandHandler<ndn::nfd::RibRegisterCommand>(
"register",
63 bind(&RibManager::registerEntry,
this, _2, _3, _4, _5));
64 registerCommandHandler<ndn::nfd::RibUnregisterCommand>(
"unregister",
65 bind(&RibManager::unregisterEntry,
this, _2, _3, _4, _5));
67 registerStatusDatasetHandler(
"list", bind(&RibManager::listEntries,
this, _1, _2, _3));
78 registerTopPrefix(LOCAL_HOST_TOP_PREFIX);
80 if (m_isLocalhopEnabled) {
81 registerTopPrefix(LOCAL_HOP_TOP_PREFIX);
84 NFD_LOG_INFO(
"Start monitoring face create/destroy events");
85 m_faceMonitor.onNotification.connect(bind(&RibManager::onNotification,
this, _1));
86 m_faceMonitor.start();
88 scheduleActiveFaceFetch(ACTIVE_FACE_FETCH_INTERVAL);
94 m_nfdController.start<ndn::nfd::FaceEnableLocalControlCommand>(
96 .setLocalControlFeature(ndn::nfd::LOCAL_CONTROL_FEATURE_INCOMING_FACE_ID),
97 bind(&RibManager::onControlHeaderSuccess,
this),
98 bind(&RibManager::onControlHeaderError,
this, _1));
105 bind(&RibManager::onConfig,
this, _1, _2, _3));
117 NFD_LOG_DEBUG(
"RIB update failed for " << update <<
" (code: " << code
118 <<
", error: " << error <<
")");
121 scheduleActiveFaceFetch(time::seconds(1));
127 const std::string& filename)
129 bool isAutoPrefixPropagatorEnabled =
false;
131 for (
const auto& item : configSection) {
132 if (item.first ==
"localhost_security") {
133 m_localhostValidator.load(item.second, filename);
135 else if (item.first ==
"localhop_security") {
136 m_localhopValidator.load(item.second, filename);
137 m_isLocalhopEnabled =
true;
139 else if (item.first ==
"auto_prefix_propagate") {
141 isAutoPrefixPropagatorEnabled =
true;
148 m_prefixPropagator.
enable();
151 BOOST_THROW_EXCEPTION(Error(
"Unrecognized rib property: " + item.first));
155 if (!isAutoPrefixPropagatorEnabled) {
161 RibManager::registerTopPrefix(
const Name& topPrefix)
164 m_nfdController.start<ndn::nfd::FibAddNextHopCommand>(
166 .setName(Name(topPrefix).append(MGMT_MODULE_NAME))
168 bind(&RibManager::onCommandPrefixAddNextHopSuccess,
this, cref(topPrefix), _1),
169 bind(&RibManager::onCommandPrefixAddNextHopError,
this, cref(topPrefix), _1));
172 m_addTopPrefix(topPrefix);
176 RibManager::registerEntry(
const Name& topPrefix,
const Interest& interest,
177 ControlParameters parameters,
178 const ndn::mgmt::CommandContinuation& done)
180 setFaceForSelfRegistration(interest, parameters);
183 done(ControlResponse(200,
"Success").setBody(parameters.wireEncode()));
186 route.faceId = parameters.getFaceId();
187 route.origin = parameters.getOrigin();
188 route.cost = parameters.getCost();
189 route.flags = parameters.getFlags();
191 if (parameters.hasExpirationPeriod() &&
192 parameters.getExpirationPeriod() != time::milliseconds::max())
194 route.expires = time::steady_clock::now() + parameters.getExpirationPeriod();
200 NFD_LOG_TRACE(
"Scheduled unregistration at: " << route.expires <<
201 " with EventId: " << eventId);
204 route.setExpirationEvent(eventId);
207 route.expires = time::steady_clock::TimePoint::max();
210 NFD_LOG_INFO(
"Adding route " << parameters.getName() <<
" nexthop=" << route.faceId
211 <<
" origin=" << route.origin
212 <<
" cost=" << route.cost);
216 .setName(parameters.getName())
223 m_registeredFaces.insert(route.faceId);
227 RibManager::unregisterEntry(
const Name& topPrefix,
const Interest& interest,
228 ControlParameters parameters,
229 const ndn::mgmt::CommandContinuation& done)
231 setFaceForSelfRegistration(interest, parameters);
234 done(ControlResponse(200,
"Success").setBody(parameters.wireEncode()));
237 route.faceId = parameters.getFaceId();
238 route.origin = parameters.getOrigin();
240 NFD_LOG_INFO(
"Removing route " << parameters.getName() <<
" nexthop=" << route.faceId
241 <<
" origin=" << route.origin);
245 .setName(parameters.getName())
254 RibManager::listEntries(
const Name& topPrefix,
const Interest& interest,
255 ndn::mgmt::StatusDatasetContext& context)
257 for (
auto&& ribTableEntry : m_rib) {
258 const auto& ribEntry = *ribTableEntry.second;
259 ndn::nfd::RibEntry record;
261 for (
auto&& route : ribEntry) {
262 ndn::nfd::Route routeElement;
263 routeElement.setFaceId(route.faceId)
264 .setOrigin(route.origin)
266 .setFlags(route.flags);
268 if (route.expires < time::steady_clock::TimePoint::max()) {
269 routeElement.setExpirationPeriod(time::duration_cast<time::milliseconds>(
270 route.expires - time::steady_clock::now()));
273 record.addRoute(routeElement);
276 record.setName(ribEntry.getName());
277 context.append(record.wireEncode());
284 RibManager::setFaceForSelfRegistration(
const Interest& request, ControlParameters& parameters)
286 bool isSelfRegistration = (parameters.getFaceId() == 0);
287 if (isSelfRegistration) {
288 shared_ptr<lp::IncomingFaceIdTag> incomingFaceIdTag = request.getTag<lp::IncomingFaceIdTag>();
292 BOOST_ASSERT(incomingFaceIdTag !=
nullptr);
293 parameters.setFaceId(*incomingFaceIdTag);
297 ndn::mgmt::Authorization
298 RibManager::makeAuthorization(
const std::string& verb)
300 return [
this] (
const Name& prefix,
const Interest& interest,
301 const ndn::mgmt::ControlParameters* params,
302 const ndn::mgmt::AcceptContinuation& accept,
303 const ndn::mgmt::RejectContinuation& reject) {
304 BOOST_ASSERT(params !=
nullptr);
305 BOOST_ASSERT(
typeid(*params) ==
typeid(ndn::nfd::ControlParameters));
306 BOOST_ASSERT(prefix == LOCAL_HOST_TOP_PREFIX || prefix == LOCAL_HOP_TOP_PREFIX);
308 ndn::ValidatorConfig& validator = prefix == LOCAL_HOST_TOP_PREFIX ?
309 m_localhostValidator : m_localhopValidator;
310 validator.validate(interest,
312 bind([reject] { reject(ndn::mgmt::RejectReply::STATUS403); }));
317 RibManager::fetchActiveFaces()
321 Interest interest(FACES_LIST_DATASET_PREFIX);
322 interest.setChildSelector(1);
323 interest.setMustBeFresh(
true);
325 shared_ptr<ndn::OBufferStream> buffer = make_shared<ndn::OBufferStream>();
327 m_face.expressInterest(interest,
328 bind(&RibManager::fetchSegments,
this, _2, buffer),
329 bind(&RibManager::onFetchFaceStatusTimeout,
this));
333 RibManager::fetchSegments(
const Data& data, shared_ptr<ndn::OBufferStream> buffer)
335 buffer->write(reinterpret_cast<const char*>(data.getContent().value()),
336 data.getContent().value_size());
338 uint64_t currentSegment = data.getName().get(-1).toSegment();
340 const name::Component& finalBlockId = data.getMetaInfo().getFinalBlockId();
342 if (finalBlockId.empty() || finalBlockId.toSegment() > currentSegment) {
343 m_face.expressInterest(data.getName().getPrefix(-1).appendSegment(currentSegment+1),
344 bind(&RibManager::fetchSegments,
this, _2, buffer),
345 bind(&RibManager::onFetchFaceStatusTimeout,
this));
348 removeInvalidFaces(buffer);
353 RibManager::onFetchFaceStatusTimeout()
355 std::cerr <<
"Face Status Dataset request timed out" << std::endl;
356 scheduleActiveFaceFetch(ACTIVE_FACE_FETCH_INTERVAL);
360 RibManager::onFaceDestroyedEvent(uint64_t faceId)
362 m_rib.beginRemoveFace(faceId);
363 m_registeredFaces.erase(faceId);
367 RibManager::scheduleActiveFaceFetch(
const time::seconds& timeToWait)
372 bind(&RibManager::fetchActiveFaces,
this));
376 RibManager::removeInvalidFaces(shared_ptr<ndn::OBufferStream> buffer)
380 ndn::ConstBufferPtr buf = buffer->buf();
384 FaceIdSet activeFaces;
386 while (offset < buf->size()) {
388 std::tie(isOk, block) = Block::fromBuffer(buf, offset);
390 std::cerr <<
"ERROR: cannot decode FaceStatus TLV" << std::endl;
394 offset += block.size();
396 ndn::nfd::FaceStatus status(block);
397 activeFaces.insert(status.getFaceId());
402 for (
auto&& faceId : m_registeredFaces) {
403 if (activeFaces.find(faceId) == activeFaces.end()) {
407 bind(&RibManager::onFaceDestroyedEvent,
this, faceId));
412 scheduleActiveFaceFetch(ACTIVE_FACE_FETCH_INTERVAL);
416 RibManager::onNotification(
const FaceEventNotification& notification)
420 if (notification.getKind() == ndn::nfd::FACE_EVENT_DESTROYED) {
421 NFD_LOG_DEBUG(
"Received notification for destroyed faceId: " << notification.getFaceId());
424 bind(&RibManager::onFaceDestroyedEvent,
this, notification.getFaceId()));
429 RibManager::onCommandPrefixAddNextHopSuccess(
const Name& prefix,
430 const ndn::nfd::ControlParameters& result)
432 NFD_LOG_DEBUG(
"Successfully registered " + prefix.toUri() +
" with NFD");
436 route.faceId = result.getFaceId();
437 route.origin = ndn::nfd::ROUTE_ORIGIN_APP;
438 route.expires = time::steady_clock::TimePoint::max();
439 route.flags = ndn::nfd::ROUTE_FLAG_CHILD_INHERIT;
441 m_rib.insert(prefix, route);
443 m_registeredFaces.insert(route.faceId);
447 RibManager::onCommandPrefixAddNextHopError(
const Name& name,
448 const ndn::nfd::ControlResponse& response)
450 BOOST_THROW_EXCEPTION(Error(
"Error in setting interest filter (" + name.toUri() +
451 "): " + response.getText()));
455 RibManager::onControlHeaderSuccess()
461 RibManager::onControlHeaderError(
const ndn::nfd::ControlResponse& response)
463 std::ostringstream os;
464 os <<
"Couldn't enable local control header "
465 <<
"(code: " << response.getCode() <<
", info: " << response.getText() <<
")";
466 BOOST_THROW_EXCEPTION(Error(os.str()));
void addSectionHandler(const std::string §ionName, ConfigSectionHandler subscriber)
setup notification of configuration file sections
#define NFD_LOG_DEBUG(expression)
configuration file parsing utility
void cancel(const EventId &eventId)
cancel a scheduled event
void disable()
disable automatic prefix propagation
void enable()
enable automatic prefix propagation
void enableLocalControlHeader()
a collection of common functions shared by all NFD managers and RIB manager, such as communicating wi...
#define NFD_LOG_INFO(expression)
Copyright (c) 2014-2015, Regents of the University of California, Arizona Board of Regents...
void onRibUpdateFailure(const RibUpdate &update, uint32_t code, const std::string &error)
void loadConfig(const ConfigSection &configSection)
load the "auto_prefix_propagate" section from config file
boost::property_tree::ptree ConfigSection
void extractRequester(const Interest &interest, ndn::mgmt::AcceptContinuation accept)
extract a requester from a ControlCommand request
void setConfigFile(ConfigFile &configFile)
#define NFD_LOG_INIT(name)
EventId schedule(const time::nanoseconds &after, const Scheduler::Event &event)
schedule an event
#define NFD_LOG_TRACE(expression)
void onRibUpdateSuccess(const RibUpdate &update)
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.
RibManager(Dispatcher &dispatcher, ndn::Face &face, ndn::KeyChain &keyChain)