NS-3 based Named Data Networking (NDN) simulator
ndnSIM 2.3: NDN, CCN, CCNx, content centric networks
API Documentation
rib-manager.cpp
Go to the documentation of this file.
1 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
26 #include "rib-manager.hpp"
27 #include "core/global-io.hpp"
28 #include "core/logger.hpp"
29 #include "core/scheduler.hpp"
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>
33 
34 namespace nfd {
35 namespace rib {
36 
37 NFD_LOG_INIT("RibManager");
38 
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);
44 
46  ndn::Face& face,
47  ndn::KeyChain& keyChain)
48  : ManagerBase(dispatcher, MGMT_MODULE_NAME)
49  , m_face(face)
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);
60  })
61 {
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));
66 
67  registerStatusDatasetHandler("list", bind(&RibManager::listEntries, this, _1, _2, _3));
68 }
69 
71 {
72  scheduler::cancel(m_activeFaceFetchEvent);
73 }
74 
75 void
77 {
78  registerTopPrefix(LOCAL_HOST_TOP_PREFIX);
79 
80  if (m_isLocalhopEnabled) {
81  registerTopPrefix(LOCAL_HOP_TOP_PREFIX);
82  }
83 
84  NFD_LOG_INFO("Start monitoring face create/destroy events");
85  m_faceMonitor.onNotification.connect(bind(&RibManager::onNotification, this, _1));
86  m_faceMonitor.start();
87 
88  scheduleActiveFaceFetch(ACTIVE_FACE_FETCH_INTERVAL);
89 }
90 
91 void
93 {
94  m_nfdController.start<ndn::nfd::FaceUpdateCommand>(
96  .setFlagBit(ndn::nfd::BIT_LOCAL_FIELDS_ENABLED, true),
97  bind(&RibManager::onEnableLocalFieldsSuccess, this),
98  bind(&RibManager::onEnableLocalFieldsError, this, _1));
99 }
100 
101 void
103 {
104  configFile.addSectionHandler("rib",
105  bind(&RibManager::onConfig, this, _1, _2, _3));
106 }
107 
108 void
110 {
111  NFD_LOG_DEBUG("RIB update succeeded for " << update);
112 }
113 
114 void
115 RibManager::onRibUpdateFailure(const RibUpdate& update, uint32_t code, const std::string& error)
116 {
117  NFD_LOG_DEBUG("RIB update failed for " << update << " (code: " << code
118  << ", error: " << error << ")");
119 
120  // Since the FIB rejected the update, clean up invalid routes
121  scheduleActiveFaceFetch(time::seconds(1));
122 }
123 
124 void
125 RibManager::onConfig(const ConfigSection& configSection,
126  bool isDryRun,
127  const std::string& filename)
128 {
129  bool isAutoPrefixPropagatorEnabled = false;
130 
131  for (const auto& item : configSection) {
132  if (item.first == "localhost_security") {
133  m_localhostValidator.load(item.second, filename);
134  }
135  else if (item.first == "localhop_security") {
136  m_localhopValidator.load(item.second, filename);
137  m_isLocalhopEnabled = true;
138  }
139  else if (item.first == "auto_prefix_propagate") {
140  m_prefixPropagator.loadConfig(item.second);
141  isAutoPrefixPropagatorEnabled = true;
142 
143  // Avoid other actions when isDryRun == true
144  if (isDryRun) {
145  continue;
146  }
147 
148  m_prefixPropagator.enable();
149  }
150  else {
151  BOOST_THROW_EXCEPTION(Error("Unrecognized rib property: " + item.first));
152  }
153  }
154 
155  if (!isAutoPrefixPropagatorEnabled) {
156  m_prefixPropagator.disable();
157  }
158 }
159 
160 void
161 RibManager::registerTopPrefix(const Name& topPrefix)
162 {
163  // register entry to the FIB
164  m_nfdController.start<ndn::nfd::FibAddNextHopCommand>(
166  .setName(Name(topPrefix).append(MGMT_MODULE_NAME))
167  .setFaceId(0),
168  bind(&RibManager::onCommandPrefixAddNextHopSuccess, this, cref(topPrefix), _1),
169  bind(&RibManager::onCommandPrefixAddNextHopError, this, cref(topPrefix), _1));
170 
171  // add top prefix to the dispatcher
172  m_addTopPrefix(topPrefix);
173 }
174 
175 void
176 RibManager::registerEntry(const Name& topPrefix, const Interest& interest,
177  ControlParameters parameters,
178  const ndn::mgmt::CommandContinuation& done)
179 {
180  setFaceForSelfRegistration(interest, parameters);
181 
182  // Respond since command is valid and authorized
183  done(ControlResponse(200, "Success").setBody(parameters.wireEncode()));
184 
185  Route route;
186  route.faceId = parameters.getFaceId();
187  route.origin = parameters.getOrigin();
188  route.cost = parameters.getCost();
189  route.flags = parameters.getFlags();
190 
191  if (parameters.hasExpirationPeriod() &&
192  parameters.getExpirationPeriod() != time::milliseconds::max())
193  {
194  route.expires = time::steady_clock::now() + parameters.getExpirationPeriod();
195 
196  // Schedule a new event, the old one will be cancelled during rib insertion.
198  bind(&Rib::onRouteExpiration, &m_rib, parameters.getName(), route));
199 
200  NFD_LOG_TRACE("Scheduled unregistration at: " << route.expires <<
201  " with EventId: " << eventId);
202 
203  // Set the NewEventId of this entry
204  route.setExpirationEvent(eventId);
205  }
206  else {
207  route.expires = time::steady_clock::TimePoint::max();
208  }
209 
210  NFD_LOG_INFO("Adding route " << parameters.getName() << " nexthop=" << route.faceId
211  << " origin=" << route.origin
212  << " cost=" << route.cost);
213 
214  RibUpdate update;
216  .setName(parameters.getName())
217  .setRoute(route);
218 
219  m_rib.beginApplyUpdate(update,
220  bind(&RibManager::onRibUpdateSuccess, this, update),
221  bind(&RibManager::onRibUpdateFailure, this, update, _1, _2));
222 
223  m_registeredFaces.insert(route.faceId);
224 }
225 
226 void
227 RibManager::unregisterEntry(const Name& topPrefix, const Interest& interest,
228  ControlParameters parameters,
229  const ndn::mgmt::CommandContinuation& done)
230 {
231  setFaceForSelfRegistration(interest, parameters);
232 
233  // Respond since command is valid and authorized
234  done(ControlResponse(200, "Success").setBody(parameters.wireEncode()));
235 
236  Route route;
237  route.faceId = parameters.getFaceId();
238  route.origin = parameters.getOrigin();
239 
240  NFD_LOG_INFO("Removing route " << parameters.getName() << " nexthop=" << route.faceId
241  << " origin=" << route.origin);
242 
243  RibUpdate update;
245  .setName(parameters.getName())
246  .setRoute(route);
247 
248  m_rib.beginApplyUpdate(update,
249  bind(&RibManager::onRibUpdateSuccess, this, update),
250  bind(&RibManager::onRibUpdateFailure, this, update, _1, _2));
251 }
252 
253 void
254 RibManager::listEntries(const Name& topPrefix, const Interest& interest,
256 {
257  for (auto&& ribTableEntry : m_rib) {
258  const auto& ribEntry = *ribTableEntry.second;
259  ndn::nfd::RibEntry record;
260 
261  for (auto&& route : ribEntry) {
262  ndn::nfd::Route routeElement;
263  routeElement.setFaceId(route.faceId)
264  .setOrigin(route.origin)
265  .setCost(route.cost)
266  .setFlags(route.flags);
267 
268  if (route.expires < time::steady_clock::TimePoint::max()) {
269  routeElement.setExpirationPeriod(time::duration_cast<time::milliseconds>(
270  route.expires - time::steady_clock::now()));
271  }
272 
273  record.addRoute(routeElement);
274  }
275 
276  record.setName(ribEntry.getName());
277  context.append(record.wireEncode());
278  }
279 
280  context.end();
281 }
282 
283 void
284 RibManager::setFaceForSelfRegistration(const Interest& request, ControlParameters& parameters)
285 {
286  bool isSelfRegistration = (parameters.getFaceId() == 0);
287  if (isSelfRegistration) {
288  shared_ptr<lp::IncomingFaceIdTag> incomingFaceIdTag = request.getTag<lp::IncomingFaceIdTag>();
289  // NDNLPv2 says "application MUST be prepared to receive a packet without IncomingFaceId field",
290  // but it's fine to assert IncomingFaceId is available, because InternalFace lives inside NFD
291  // and is initialized synchronously with IncomingFaceId field enabled.
292  BOOST_ASSERT(incomingFaceIdTag != nullptr);
293  parameters.setFaceId(*incomingFaceIdTag);
294  }
295 }
296 
298 RibManager::makeAuthorization(const std::string& verb)
299 {
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);
307 
308  ndn::ValidatorConfig& validator = prefix == LOCAL_HOST_TOP_PREFIX ?
309  m_localhostValidator : m_localhopValidator;
310  validator.validate(interest,
311  bind([&interest, this, accept] { extractRequester(interest, accept); }),
312  bind([reject] { reject(ndn::mgmt::RejectReply::STATUS403); }));
313  };
314 }
315 
316 void
317 RibManager::fetchActiveFaces()
318 {
319  NFD_LOG_DEBUG("Fetching active faces");
320 
321  m_nfdController.fetch<ndn::nfd::FaceDataset>(
322  bind(&RibManager::removeInvalidFaces, this, _1),
323  bind(&RibManager::onFetchActiveFacesFailure, this, _1, _2),
325 }
326 
327 void
328 RibManager::onFetchActiveFacesFailure(uint32_t code, const std::string& reason)
329 {
330  NFD_LOG_DEBUG("Face Status Dataset request failure " << code << " " << reason);
331  scheduleActiveFaceFetch(ACTIVE_FACE_FETCH_INTERVAL);
332 }
333 
334 void
335 RibManager::onFaceDestroyedEvent(uint64_t faceId)
336 {
337  m_rib.beginRemoveFace(faceId);
338  m_registeredFaces.erase(faceId);
339 }
340 
341 void
342 RibManager::scheduleActiveFaceFetch(const time::seconds& timeToWait)
343 {
344  scheduler::cancel(m_activeFaceFetchEvent);
345 
346  m_activeFaceFetchEvent = scheduler::schedule(timeToWait,
347  bind(&RibManager::fetchActiveFaces, this));
348 }
349 
350 void
351 RibManager::removeInvalidFaces(const std::vector<ndn::nfd::FaceStatus>& activeFaces)
352 {
353  NFD_LOG_DEBUG("Checking for invalid face registrations");
354 
355  FaceIdSet activeFaceIds;
356  for (const ndn::nfd::FaceStatus& item : activeFaces) {
357  activeFaceIds.insert(item.getFaceId());
358  }
359 
360  // Look for face IDs that were registered but not active to find missed
361  // face destroyed events
362  for (auto&& faceId : m_registeredFaces) {
363  if (activeFaceIds.count(faceId) == 0) {
364  NFD_LOG_DEBUG("Removing invalid face ID: " << faceId);
365 
366  scheduler::schedule(time::seconds(0),
367  bind(&RibManager::onFaceDestroyedEvent, this, faceId));
368  }
369  }
370 
371  // Reschedule the check for future clean up
372  scheduleActiveFaceFetch(ACTIVE_FACE_FETCH_INTERVAL);
373 }
374 
375 void
376 RibManager::onNotification(const FaceEventNotification& notification)
377 {
378  NFD_LOG_TRACE("onNotification: " << notification);
379 
380  if (notification.getKind() == ndn::nfd::FACE_EVENT_DESTROYED) {
381  NFD_LOG_DEBUG("Received notification for destroyed faceId: " << notification.getFaceId());
382 
383  scheduler::schedule(time::seconds(0),
384  bind(&RibManager::onFaceDestroyedEvent, this, notification.getFaceId()));
385  }
386 }
387 
388 void
389 RibManager::onCommandPrefixAddNextHopSuccess(const Name& prefix,
390  const ndn::nfd::ControlParameters& result)
391 {
392  NFD_LOG_DEBUG("Successfully registered " + prefix.toUri() + " with NFD");
393 
394  // Routes must be inserted into the RIB so route flags can be applied
395  Route route;
396  route.faceId = result.getFaceId();
397  route.origin = ndn::nfd::ROUTE_ORIGIN_APP;
398  route.expires = time::steady_clock::TimePoint::max();
400 
401  m_rib.insert(prefix, route);
402 
403  m_registeredFaces.insert(route.faceId);
404 }
405 
406 void
407 RibManager::onCommandPrefixAddNextHopError(const Name& name,
408  const ndn::nfd::ControlResponse& response)
409 {
410  BOOST_THROW_EXCEPTION(Error("Error in setting interest filter (" + name.toUri() +
411  "): " + response.getText()));
412 }
413 
414 void
415 RibManager::onEnableLocalFieldsSuccess()
416 {
417  NFD_LOG_DEBUG("Local fields enabled");
418 }
419 
420 void
421 RibManager::onEnableLocalFieldsError(const ndn::nfd::ControlResponse& response)
422 {
423  BOOST_THROW_EXCEPTION(Error("Couldn't enable local fields (code: " +
424  to_string(response.getCode()) + ", info: " + response.getText() +
425  ")"));
426 }
427 
428 } // namespace rib
429 } // namespace nfd
void start(const ControlParameters &parameters, const CommandSucceedCallback &onSuccess, const CommandFailCallback &onFailure, const CommandOptions &options=CommandOptions())
start command execution
Definition: controller.hpp:75
ControlParameters & setFaceId(uint64_t faceId)
void validate(const Data &data, const OnDataValidated &onValidated, const OnDataValidationFailed &onValidationFailed)
Validate Data and call either onValidated or onValidationFailed.
Definition: validator.hpp:81
a collection of common functions shared by all NFD managers and RIB manager, such as communicating wi...
std::string toUri() const
Encode this name as a URI.
Definition: name.cpp:171
shared_ptr< T > getTag() const
get a tag item
Definition: tag-host.hpp:67
void load(const std::string &filename)
represents a fib/add-nexthop command
void setExpirationEvent(const scheduler::EventId eid)
Definition: route.hpp:55
void beginApplyUpdate(const RibUpdate &update, const UpdateSuccessCallback &onSuccess, const UpdateFailureCallback &onFailure)
passes the provided RibUpdateBatch to FibUpdater to calculate and send FibUpdates.
Definition: rib.cpp:344
represents parameters in a ControlCommand request or response
time::steady_clock::TimePoint expires
Definition: route.hpp:83
void cancel(const EventId &eventId)
cancel a scheduled event
Definition: scheduler.cpp:53
represents a dispatcher on server side of NFD Management protocol
Definition: dispatcher.hpp:129
static time_point now() noexcept
Definition: time.cpp:79
void extractRequester(const Interest &interest, ndn::mgmt::AcceptContinuation accept)
extract a requester from a ControlCommand request
The validator which can be set up via a configuration file.
reply with a ControlResponse where StatusCode is 403
configuration file parsing utility
Definition: config-file.hpp:50
size_t wireEncode(EncodingImpl< TAG > &encoder) const
The packet signing interface.
Definition: key-chain.hpp:47
std::enable_if< std::is_default_constructible< Dataset >::value >::type fetch(const std::function< void(typename Dataset::ResultType)> &onSuccess, const DatasetFailCallback &onFailure, const CommandOptions &options=CommandOptions())
start dataset fetching
Definition: controller.hpp:88
RibManager(Dispatcher &dispatcher, ndn::Face &face, ndn::KeyChain &keyChain)
Definition: rib-manager.cpp:45
RibEntry & setName(const Name &prefix)
Definition: rib-entry.hpp:218
represents a Face status change notification
uint64_t cost
Definition: route.hpp:82
uint64_t faceId
Definition: route.hpp:79
represents an Interest packet
Definition: interest.hpp:42
#define NFD_LOG_DEBUG(expression)
Definition: logger.hpp:55
std::function< void(RejectReply act)> RejectContinuation
a function to be called if authorization is rejected
Definition: dispatcher.hpp:60
std::function< void(const std::string &requester)> AcceptContinuation
a function to be called if authorization is successful
Definition: dispatcher.hpp:45
void start()
start or resume receiving notifications
Data abstraction for Route.
Definition: rib-entry.hpp:51
void disable()
disable automatic prefix propagation
void onRibUpdateSuccess(const RibUpdate &update)
Route & setFaceId(uint64_t faceId)
Definition: rib-entry.hpp:75
signal::Signal< NotificationSubscriber, Notification > onNotification
fires when a Notification is received
#define NFD_LOG_INFO(expression)
Definition: logger.hpp:56
Route & setExpirationPeriod(const time::milliseconds &expirationPeriod)
Definition: rib-entry.hpp:139
Route & setFlags(uint64_t flags)
set route inheritance flags
Definition: rib-entry.hpp:123
provides a tag type for simple types
Definition: tag.hpp:58
std::shared_ptr< ns3::EventId > EventId
Definition: scheduler.hpp:39
#define NFD_LOG_TRACE(expression)
Definition: logger.hpp:54
ndn::mgmt::ControlResponse ControlResponse
void insert(const Name &prefix, const Route &route)
Definition: rib.cpp:84
contains options for ControlCommand execution
Copyright (c) 2011-2015 Regents of the University of California.
Definition: ndn-common.hpp:40
void addSectionHandler(const std::string &sectionName, ConfigSectionHandler subscriber)
setup notification of configuration file sections
Definition: config-file.cpp:79
size_t wireEncode(EncodingImpl< TAG > &block) const
Definition: rib-entry.cpp:221
uint64_t origin
Definition: route.hpp:80
void end()
end the response successfully after appending zero or more blocks
RibUpdate & setAction(Action action)
Definition: rib-update.hpp:81
void loadConfig(const ConfigSection &configSection)
load the "auto_prefix_propagate" section from config file
represents a route for a name prefix
Definition: route.hpp:37
Provide a communication channel with local or remote NDN forwarder.
Definition: face.hpp:125
void addTopPrefix(const Name &prefix, bool wantRegister=true, const security::SigningInfo &signingInfo=security::SigningInfo())
add a top-level prefix
Definition: dispatcher.cpp:74
represents Face status
Definition: face-status.hpp:37
boost::property_tree::ptree ConfigSection
Name abstraction to represent an absolute name.
Definition: name.hpp:46
void beginRemoveFace(uint64_t faceId)
starts the FIB update process when a face has been destroyed
Definition: rib.cpp:356
std::function< void(const ControlResponse &resp)> CommandContinuation
a function to be called after ControlCommandHandler completes
Definition: dispatcher.hpp:95
base class for a struct that contains ControlCommand parameters
represents a faces/update command
RibEntry & addRoute(const Route &route)
Definition: rib-entry.hpp:232
void enable()
enable automatic prefix propagation
uint64_t flags
Definition: route.hpp:81
EventId schedule(const time::nanoseconds &after, const Scheduler::Event &event)
schedule an event
Definition: scheduler.cpp:47
const time::milliseconds & getExpirationPeriod() const
RibUpdate & setName(const Name &name)
Definition: rib-update.hpp:94
void onRouteExpiration(const Name &prefix, const Route &route)
Definition: rib.cpp:193
void append(const Block &block)
append a Block to the response
Route & setCost(uint64_t cost)
Definition: rib-entry.hpp:106
const std::string & getText() const
represents a faces/list dataset
std::string to_string(const V &v)
Definition: backports.hpp:51
ControlCommand response.
provides a context for generating response to a StatusDataset request
uint64_t getFaceId() const
Definition: face-traits.hpp:59
#define NFD_LOG_INIT(name)
Definition: logger.hpp:34
Route & setOrigin(uint64_t origin)
set Origin
Definition: rib-entry.hpp:92
bit that controls whether local fields are enabled on a face
std::function< void(const Name &prefix, const Interest &interest, const ControlParameters *params, const AcceptContinuation &accept, const RejectContinuation &reject)> Authorization
a function that performs authorization
Definition: dispatcher.hpp:77
void registerStatusDatasetHandler(const std::string &verb, const ndn::mgmt::StatusDatasetHandler &handler)
void onRibUpdateFailure(const RibUpdate &update, uint32_t code, const std::string &error)
Data abstraction for RIB entry.
Definition: rib-entry.hpp:192
void setConfigFile(ConfigFile &configFile)