29 #include <ndn-cxx/mgmt/nfd/control-parameters.hpp> 36 using ndn::nfd::ControlParameters;
43 , m_controller(controller)
56 m_inheritedRoutes.clear();
59 m_updatesForBatchFaceId.clear();
60 m_updatesForNonBatchFaceId.clear();
62 computeUpdates(batch);
64 sendUpdatesForBatchFaceId(onSuccess, onFailure);
74 switch (update.getAction()) {
76 computeUpdatesForRegistration(update);
79 computeUpdatesForUnregistration(update);
82 computeUpdatesForUnregistration(update);
86 m_updatesForBatchFaceId.clear();
93 FibUpdater::computeUpdatesForRegistration(
const RibUpdate& update)
95 const Name& prefix = update.
getName();
101 if (it != m_rib.
end()) {
102 shared_ptr<const RibEntry> entry(it->second);
107 if (existingRoute == entry->end()) {
109 bool willCaptureBeTurnedOn = (entry->hasCapture() ==
false && route.isRibCapture());
111 createFibUpdatesForNewRoute(*entry, route, willCaptureBeTurnedOn);
123 createFibUpdatesForUpdatedRoute(entryCopy, route, *existingRoute);
129 shared_ptr<RibEntry> parent = m_rib.
findParent(prefix);
134 for (
const auto& descendant : descendants) {
137 if (descendant->getParent() == parent) {
138 children.push_back(descendant);
142 createFibUpdatesForNewRibEntry(prefix, route, children);
147 FibUpdater::computeUpdatesForUnregistration(
const RibUpdate& update)
149 const Name& prefix = update.
getName();
155 if (ribIt != m_rib.
end()) {
156 shared_ptr<const RibEntry> entry(ribIt->second);
158 const bool hadCapture = entry->hasCapture();
162 if (existing != entry->end()) {
168 const bool captureWasTurnedOff = (hadCapture && !temp.
hasCapture());
170 createFibUpdatesForErasedRoute(temp, *existing, captureWasTurnedOff);
174 const Route* next = entry->getRouteWithSecondLowestCostByFaceId(route.
faceId);
176 if (next !=
nullptr) {
177 createFibUpdatesForNewRoute(temp, *next,
false);
181 if (entry->getNRoutes() == 1) {
182 createFibUpdatesForErasedRibEntry(*entry);
193 std::string updateString = (updates.size() == 1) ?
" update" :
" updates";
194 NFD_LOG_DEBUG(
"Applying " << updates.size() << updateString <<
" to FIB");
196 for (
const FibUpdate& update : updates) {
200 sendAddNextHopUpdate(update, onSuccess, onFailure);
203 sendRemoveNextHopUpdate(update, onSuccess, onFailure);
212 if (m_updatesForBatchFaceId.size() > 0) {
213 sendUpdates(m_updatesForBatchFaceId, onSuccess, onFailure);
216 sendUpdatesForNonBatchFaceId(onSuccess, onFailure);
224 if (m_updatesForNonBatchFaceId.size() > 0) {
225 sendUpdates(m_updatesForNonBatchFaceId, onSuccess, onFailure);
228 onSuccess(m_inheritedRoutes);
233 FibUpdater::sendAddNextHopUpdate(
const FibUpdate& update,
238 m_controller.start<ndn::nfd::FibAddNextHopCommand>(
240 .setName(update.
name)
242 .setCost(update.
cost),
243 bind(&FibUpdater::onUpdateSuccess,
this, update, onSuccess, onFailure),
244 bind(&FibUpdater::onUpdateError,
this, update, onSuccess, onFailure, _1, nTimeouts));
248 FibUpdater::sendRemoveNextHopUpdate(
const FibUpdate& update,
253 m_controller.start<ndn::nfd::FibRemoveNextHopCommand>(
255 .setName(update.
name)
256 .setFaceId(update.
faceId),
257 bind(&FibUpdater::onUpdateSuccess,
this, update, onSuccess, onFailure),
258 bind(&FibUpdater::onUpdateError,
this, update, onSuccess, onFailure, _1, nTimeouts));
262 FibUpdater::onUpdateSuccess(
const FibUpdate update,
266 if (update.
faceId == m_batchFaceId) {
267 m_updatesForBatchFaceId.remove(update);
269 if (m_updatesForBatchFaceId.size() == 0) {
270 sendUpdatesForNonBatchFaceId(onSuccess, onFailure);
274 m_updatesForNonBatchFaceId.remove(update);
276 if (m_updatesForNonBatchFaceId.size() == 0) {
277 onSuccess(m_inheritedRoutes);
283 FibUpdater::onUpdateError(
const FibUpdate update,
286 const ndn::nfd::ControlResponse& response, uint32_t nTimeouts)
288 uint32_t code = response.getCode();
290 " (code: " << code <<
", error: " << response.getText() <<
")");
292 if (code == ndn::nfd::Controller::ERROR_TIMEOUT && nTimeouts < MAX_NUM_TIMEOUTS) {
293 sendAddNextHopUpdate(update, onSuccess, onFailure, ++nTimeouts);
295 else if (code == ERROR_FACE_NOT_FOUND) {
296 if (update.
faceId == m_batchFaceId) {
297 onFailure(code, response.getText());
300 m_updatesForNonBatchFaceId.remove(update);
302 if (m_updatesForNonBatchFaceId.size() == 0) {
303 onSuccess(m_inheritedRoutes);
308 NDN_THROW(
Error(
"Non-recoverable error: " + response.getText() +
" code: " + to_string(code)));
313 FibUpdater::addFibUpdate(
FibUpdate update)
316 m_updatesForNonBatchFaceId;
320 FibUpdateList::iterator it = std::find_if(updates.begin(), updates.end(),
322 return update.
name == other.name && update.
faceId == other.faceId;
325 if (it != updates.end()) {
331 updates.push_back(update);
336 FibUpdater::addInheritedRoutes(
const RibEntry& entry,
const Rib::RouteSet& routesToAdd)
338 for (
const Route& route : routesToAdd) {
342 addInheritedRoute(entry.
getName(), route);
350 FibUpdater::addInheritedRoutes(
const Name& name,
const Rib::RouteSet& routesToAdd,
353 for (
const Route& route : routesToAdd) {
354 if (route.faceId != ignore.
faceId) {
356 addInheritedRoute(name, route);
364 FibUpdater::removeInheritedRoutes(
const RibEntry& entry,
const Rib::Rib::RouteSet& routesToRemove)
366 for (
const Route& route : routesToRemove) {
369 removeInheritedRoute(entry.
getName(), route);
376 FibUpdater::createFibUpdatesForNewRibEntry(
const Name& name,
const Route& route,
383 if (!route.isChildInherit() && !route.isRibCapture()) {
385 addInheritedRoutes(name, m_rib.getAncestorRoutes(name), route);
387 else if (route.isChildInherit() && route.isRibCapture()) {
389 Rib::RouteSet routesToAdd;
390 routesToAdd.insert(route);
393 modifyChildrensInheritedRoutes(children, routesToAdd, m_rib.getAncestorRoutes(name));
395 else if (route.isChildInherit()) {
396 Rib::RouteSet ancestorRoutes = m_rib.getAncestorRoutes(name);
399 addInheritedRoutes(name, ancestorRoutes, route);
403 Rib::RouteSet::iterator it = ancestorRoutes.find(route);
406 if (it != ancestorRoutes.end()) {
407 ancestorRoutes.erase(it);
411 ancestorRoutes.insert(route);
414 modifyChildrensInheritedRoutes(children, ancestorRoutes, Rib::RouteSet());
416 else if (route.isRibCapture()) {
418 modifyChildrensInheritedRoutes(children, Rib::RouteSet(), m_rib.getAncestorRoutes(name));
423 FibUpdater::createFibUpdatesForNewRoute(
const RibEntry& entry,
const Route& route,
424 bool captureWasTurnedOn)
429 Rib::RouteSet routesToAdd;
430 if (route.isChildInherit()) {
434 if (prevRoute ==
nullptr || route.
cost <= prevRoute->
cost) {
436 routesToAdd.insert(route);
440 Rib::RouteSet routesToRemove;
441 if (captureWasTurnedOn) {
443 routesToRemove = m_rib.getAncestorRoutes(entry);
446 removeInheritedRoutes(entry, routesToRemove);
449 modifyChildrensInheritedRoutes(entry.
getChildren(), routesToAdd, routesToRemove);
456 if (other ==
nullptr || route.
cost <= other->cost) {
462 FibUpdater::createFibUpdatesForUpdatedRoute(
const RibEntry& entry,
const Route& route,
463 const Route& existingRoute)
465 const bool costDidChange = (route.
cost != existingRoute.
cost);
471 if (route.
flags == existingRoute.
flags && !costDidChange) {
490 if (prevRoute ==
nullptr || route.
cost <= prevRoute->
cost) {
493 if ((route.
flags == existingRoute.
flags) && route.isChildInherit()) {
495 Rib::RouteSet routesToAdd;
496 routesToAdd.insert(route);
497 modifyChildrensInheritedRoutes(entry.
getChildren(), routesToAdd, Rib::RouteSet());
505 if (!existingRoute.isChildInherit() && route.isChildInherit()) {
508 if (prevRoute ==
nullptr || route.
cost <= prevRoute->
cost) {
510 Rib::RouteSet routesToAdd;
511 routesToAdd.insert(route);
512 modifyChildrensInheritedRoutes(entry.
getChildren(), routesToAdd, Rib::RouteSet());
515 else if (existingRoute.isChildInherit() && !route.isChildInherit()) {
517 Rib::RouteSet routesToRemove;
518 routesToRemove.insert(route);
520 Rib::RouteSet routesToAdd;
522 if (prevRoute !=
nullptr) {
523 routesToAdd.insert(*prevRoute);
527 const Rib::RouteSet ancestorRoutes = m_rib.getAncestorRoutes(entry);
528 Rib::RouteSet::iterator it = ancestorRoutes.find(route);
531 if (it != ancestorRoutes.end()) {
532 routesToAdd.insert(*it);
536 modifyChildrensInheritedRoutes(entry.
getChildren(), routesToAdd, routesToRemove);
540 if (!existingRoute.isRibCapture() && route.isRibCapture()) {
541 Rib::RouteSet ancestorRoutes = m_rib.getAncestorRoutes(entry);
544 removeInheritedRoutes(entry, ancestorRoutes);
547 modifyChildrensInheritedRoutes(entry.
getChildren(), Rib::RouteSet(), ancestorRoutes);
549 else if (existingRoute.isRibCapture() && !route.isRibCapture()) {
550 Rib::RouteSet ancestorRoutes = m_rib.getAncestorRoutes(entry);
553 addInheritedRoutes(entry, ancestorRoutes);
556 modifyChildrensInheritedRoutes(entry.
getChildren(), ancestorRoutes, Rib::RouteSet());
561 FibUpdater::createFibUpdatesForErasedRoute(
const RibEntry& entry,
const Route& route,
562 const bool captureWasTurnedOff)
566 if (route.isChildInherit() && route.isRibCapture()) {
568 Rib::RouteSet routesToRemove;
569 routesToRemove.insert(route);
573 Rib::RouteSet routesToAdd;
574 if (captureWasTurnedOff && entry.
getNRoutes() != 0) {
576 routesToAdd = m_rib.getAncestorRoutes(entry);
579 addInheritedRoutes(entry, routesToAdd);
582 modifyChildrensInheritedRoutes(entry.
getChildren(), routesToAdd, routesToRemove);
584 else if (route.isChildInherit()) {
586 Rib::RouteSet routesToAdd;
588 routesToAdd = m_rib.getAncestorRoutes(entry);
591 Rib::RouteSet routesToRemove;
592 routesToRemove.insert(route);
595 modifyChildrensInheritedRoutes(entry.
getChildren(), routesToAdd, routesToRemove);
597 else if (route.isRibCapture()) {
600 Rib::RouteSet routesToAdd;
601 if (captureWasTurnedOff && entry.
getNRoutes() != 0) {
603 routesToAdd = m_rib.getAncestorRoutes(entry);
606 addInheritedRoutes(entry, routesToAdd);
609 modifyChildrensInheritedRoutes(entry.
getChildren(), routesToAdd, Rib::RouteSet());
613 Rib::RouteSet ancestorRoutes = m_rib.getAncestorRoutes(entry);
619 Rib::RouteSet::iterator it = ancestorRoutes.find(route);
621 if (it != ancestorRoutes.end()) {
622 addInheritedRoute(entry.
getName(), *it);
629 FibUpdater::createFibUpdatesForErasedRibEntry(
const RibEntry& entry)
638 const Rib::RouteSet& routesToAdd,
639 const Rib::RouteSet& routesToRemove)
641 for (
const auto& child : children) {
642 traverseSubTree(*child, routesToAdd, routesToRemove);
647 FibUpdater::traverseSubTree(
const RibEntry& entry, Rib::Rib::RouteSet routesToAdd,
648 Rib::Rib::RouteSet routesToRemove)
656 for (
auto removeIt = routesToRemove.begin(); removeIt != routesToRemove.end(); ) {
660 removeIt = routesToRemove.erase(removeIt);
666 removeInheritedRoute(entry.
getName(), *removeIt);
674 for (
auto addIt = routesToAdd.begin(); addIt != routesToAdd.end(); ) {
677 addIt = routesToAdd.erase(addIt);
683 addInheritedRoute(entry.
getName(), *addIt);
690 modifyChildrensInheritedRoutes(entry.
getChildren(), routesToAdd, routesToRemove);
694 FibUpdater::addInheritedRoute(
const Name& name,
const Route& route)
701 m_inheritedRoutes.push_back(update);
705 FibUpdater::removeInheritedRoute(
const Name& name,
const Route& route)
712 m_inheritedRoutes.push_back(update);
const_iterator end() const
bool hasInheritedRoute(const Route &route) const
Determines if the entry has an inherited route with a matching face ID.
void eraseRoute(const Route &route)
erases a Route with the same faceId and origin
RibUpdate & setRoute(const Route &route)
const Route * getRouteWithLowestCostAndChildInheritByFaceId(uint64_t faceId) const
Returns the route with the lowest cost that has the passed face ID and its child inherit flag set...
represents the Routing Information Base
shared_ptr< RibEntry > findParent(const Name &prefix) const
const Name & getName() const
bool hasFaceId(const uint64_t faceId) const
std::function< void(RibUpdateList inheritedRoutes)> FibUpdateSuccessCallback
uint64_t getFaceId() const
RibTable::const_iterator const_iterator
std::function< void(uint32_t code, const std::string &error)> FibUpdateFailureCallback
RibUpdate & setAction(Action action)
An update triggered by a face destruction notification.
const Name & getName() const
constexpr int MAX_NUM_TIMEOUTS
Represents a collection of RibUpdates to be applied to a single FaceId.
void setFibUpdater(FibUpdater *updater)
std::list< shared_ptr< RibEntry > > RibEntryList
const Route * getRouteWithLowestCostByFaceId(uint64_t faceId) const
Returns the route with the lowest cost that has the passed face ID.
void computeAndSendFibUpdates(const RibUpdateBatch &batch, const FibUpdateSuccessCallback &onSuccess, const FibUpdateFailureCallback &onFailure)
computes FibUpdates using the provided RibUpdateBatch and then sends the updates to NFD's FIB ...
constexpr uint32_t ERROR_FACE_NOT_FOUND
const RouteList & getInheritedRoutes() const
Returns the routes this namespace has inherited.
RibUpdate & setName(const Name &name)
static FibUpdate createAddUpdate(const Name &name, const uint64_t faceId, const uint64_t cost)
optional< time::steady_clock::TimePoint > expires
Copyright (c) 2014-2015, Regents of the University of California, Arizona Board of Regents...
represents a route for a name prefix
bool hasChildInheritOnFaceId(uint64_t faceId) const
Determines if the entry has an inherited route with the passed face ID and its child inherit flag set...
RouteList::const_iterator const_iterator
size_t getNRoutes() const
std::list< FibUpdate > FibUpdateList
FibUpdater(Rib &rib, ndn::nfd::Controller &controller)
#define NFD_LOG_INIT(name)
Represents a RIB entry, which contains one or more Routes with the same prefix.
const std::list< shared_ptr< RibEntry > > & getChildren() const
const_iterator find(const Name &prefix) const
iterator findRoute(const Route &route)
std::underlying_type_t< ndn::nfd::RouteFlags > flags
static FibUpdate createRemoveUpdate(const Name &name, const uint64_t faceId)
const Route & getRoute() const