30 #include <ndn-cxx/mgmt/nfd/control-parameters.hpp> 39 const unsigned int FibUpdater::MAX_NUM_TIMEOUTS = 10;
40 const uint32_t FibUpdater::ERROR_FACE_NOT_FOUND = 410;
44 , m_controller(controller)
57 m_inheritedRoutes.clear();
60 m_updatesForBatchFaceId.clear();
61 m_updatesForNonBatchFaceId.clear();
63 computeUpdates(batch);
65 sendUpdatesForBatchFaceId(onSuccess, onFailure);
75 switch (update.getAction()) {
77 computeUpdatesForRegistration(update);
80 computeUpdatesForUnregistration(update);
83 computeUpdatesForUnregistration(update);
87 m_updatesForBatchFaceId.clear();
94 FibUpdater::computeUpdatesForRegistration(
const RibUpdate& update)
96 const Name& prefix = update.getName();
97 const Route& route = update.getRoute();
102 if (it != m_rib.
end()) {
103 shared_ptr<const RibEntry> entry(it->second);
108 if (existingRoute == entry->end()) {
110 bool willCaptureBeTurnedOn = (entry->hasCapture() ==
false && route.isRibCapture());
112 createFibUpdatesForNewRoute(*entry, route, willCaptureBeTurnedOn);
118 Route& routeToUpdate = *(entryCopy.findRoute(route));
120 routeToUpdate.flags = route.flags;
121 routeToUpdate.cost = route.cost;
122 routeToUpdate.expires = route.expires;
124 createFibUpdatesForUpdatedRoute(entryCopy, route, *existingRoute);
130 shared_ptr<RibEntry> parent = m_rib.
findParent(prefix);
135 for (
const auto& descendant : descendants) {
138 if (descendant->getParent() == parent) {
139 children.push_back(descendant);
143 createFibUpdatesForNewRibEntry(prefix, route, children);
148 FibUpdater::computeUpdatesForUnregistration(
const RibUpdate& update)
150 const Name& prefix = update.getName();
151 const Route& route = update.getRoute();
156 if (ribIt != m_rib.
end()) {
157 shared_ptr<const RibEntry> entry(ribIt->second);
159 const bool hadCapture = entry->hasCapture();
163 if (existing != entry->end()) {
167 temp.eraseRoute(route);
169 const bool captureWasTurnedOff = (hadCapture && !temp.hasCapture());
171 createFibUpdatesForErasedRoute(temp, *existing, captureWasTurnedOff);
175 const Route* next = entry->getRouteWithSecondLowestCostByFaceId(route.faceId);
177 if (next !=
nullptr) {
178 createFibUpdatesForNewRoute(temp, *next,
false);
182 if (entry->getNRoutes() == 1) {
183 createFibUpdatesForErasedRibEntry(*entry);
190 FibUpdater::sendUpdates(
const FibUpdateList& updates,
191 const FibUpdateSuccessCallback& onSuccess,
192 const FibUpdateFailureCallback& onFailure)
194 std::string updateString = (updates.size() == 1) ?
" update" :
" updates";
195 NFD_LOG_DEBUG(
"Applying " << updates.size() << updateString <<
" to FIB");
197 for (
const FibUpdate& update : updates) {
201 sendAddNextHopUpdate(update, onSuccess, onFailure);
204 sendRemoveNextHopUpdate(update, onSuccess, onFailure);
210 FibUpdater::sendUpdatesForBatchFaceId(
const FibUpdateSuccessCallback& onSuccess,
211 const FibUpdateFailureCallback& onFailure)
213 if (m_updatesForBatchFaceId.size() > 0) {
214 sendUpdates(m_updatesForBatchFaceId, onSuccess, onFailure);
217 sendUpdatesForNonBatchFaceId(onSuccess, onFailure);
222 FibUpdater::sendUpdatesForNonBatchFaceId(
const FibUpdateSuccessCallback& onSuccess,
223 const FibUpdateFailureCallback& onFailure)
225 if (m_updatesForNonBatchFaceId.size() > 0) {
226 sendUpdates(m_updatesForNonBatchFaceId, onSuccess, onFailure);
229 onSuccess(m_inheritedRoutes);
234 FibUpdater::sendAddNextHopUpdate(
const FibUpdate& update,
235 const FibUpdateSuccessCallback& onSuccess,
236 const FibUpdateFailureCallback& onFailure,
241 .setName(update.name)
242 .setFaceId(update.faceId)
243 .setCost(update.cost),
244 bind(&FibUpdater::onUpdateSuccess,
this, update, onSuccess, onFailure),
245 bind(&FibUpdater::onUpdateError,
this, update, onSuccess, onFailure, _1, nTimeouts));
249 FibUpdater::sendRemoveNextHopUpdate(
const FibUpdate& update,
250 const FibUpdateSuccessCallback& onSuccess,
251 const FibUpdateFailureCallback& onFailure,
256 .setName(update.name)
257 .setFaceId(update.faceId),
258 bind(&FibUpdater::onUpdateSuccess,
this, update, onSuccess, onFailure),
259 bind(&FibUpdater::onUpdateError,
this, update, onSuccess, onFailure, _1, nTimeouts));
263 FibUpdater::onUpdateSuccess(
const FibUpdate update,
264 const FibUpdateSuccessCallback& onSuccess,
265 const FibUpdateFailureCallback& onFailure)
267 if (update.faceId == m_batchFaceId) {
268 m_updatesForBatchFaceId.remove(update);
270 if (m_updatesForBatchFaceId.size() == 0) {
271 sendUpdatesForNonBatchFaceId(onSuccess, onFailure);
275 m_updatesForNonBatchFaceId.remove(update);
277 if (m_updatesForNonBatchFaceId.size() == 0) {
278 onSuccess(m_inheritedRoutes);
284 FibUpdater::onUpdateError(
const FibUpdate update,
285 const FibUpdateSuccessCallback& onSuccess,
286 const FibUpdateFailureCallback& onFailure,
289 uint32_t code = response.
getCode();
291 " (code: " << code <<
", error: " << response.
getText() <<
")");
294 sendAddNextHopUpdate(update, onSuccess, onFailure, ++nTimeouts);
296 else if (code == ERROR_FACE_NOT_FOUND) {
297 if (update.faceId == m_batchFaceId) {
298 onFailure(code, response.
getText());
301 m_updatesForNonBatchFaceId.remove(update);
303 if (m_updatesForNonBatchFaceId.size() == 0) {
304 onSuccess(m_inheritedRoutes);
309 BOOST_THROW_EXCEPTION(Error(
"Non-recoverable error: " + response.
getText() +
315 FibUpdater::addFibUpdate(FibUpdate update)
317 FibUpdateList& updates = (update.faceId == m_batchFaceId) ? m_updatesForBatchFaceId :
318 m_updatesForNonBatchFaceId;
323 [&update] (
const FibUpdate& other) {
324 return update.name == other.name && update.faceId == other.faceId;
327 if (it != updates.end()) {
328 FibUpdate& existingUpdate = *it;
329 existingUpdate.action = update.action;
330 existingUpdate.cost = update.cost;
333 updates.push_back(update);
340 for (
const Route& route : routesToAdd) {
342 if (!entry.hasFaceId(route.faceId)) {
344 addInheritedRoute(entry.getName(), route);
355 for (
const Route& route : routesToAdd) {
356 if (route.faceId != ignore.faceId) {
358 addInheritedRoute(
name, route);
366 FibUpdater::removeInheritedRoutes(
const RibEntry& entry,
const Rib::Rib::RouteSet& routesToRemove)
368 for (
const Route& route : routesToRemove) {
370 if (entry.hasInheritedRoute(route)) {
371 removeInheritedRoute(entry.getName(), route);
378 FibUpdater::createFibUpdatesForNewRibEntry(
const Name&
name,
const Route& route,
385 if (!route.isChildInherit() && !route.isRibCapture()) {
387 addInheritedRoutes(
name, m_rib.getAncestorRoutes(
name), route);
389 else if (route.isChildInherit() && route.isRibCapture()) {
392 routesToAdd.insert(route);
395 modifyChildrensInheritedRoutes(children, routesToAdd, m_rib.getAncestorRoutes(
name));
397 else if (route.isChildInherit()) {
401 addInheritedRoutes(
name, ancestorRoutes, route);
408 if (it != ancestorRoutes.end()) {
409 ancestorRoutes.erase(it);
413 ancestorRoutes.insert(route);
416 modifyChildrensInheritedRoutes(children, ancestorRoutes,
Rib::RouteSet());
418 else if (route.isRibCapture()) {
420 modifyChildrensInheritedRoutes(children,
Rib::RouteSet(), m_rib.getAncestorRoutes(
name));
425 FibUpdater::createFibUpdatesForNewRoute(
const RibEntry& entry,
const Route& route,
426 bool captureWasTurnedOn)
429 const Route* prevRoute = entry.getRouteWithLowestCostAndChildInheritByFaceId(route.faceId);
432 if (route.isChildInherit()) {
436 if (prevRoute ==
nullptr || route.cost <= prevRoute->cost) {
438 routesToAdd.insert(route);
443 if (captureWasTurnedOn) {
445 routesToRemove = m_rib.getAncestorRoutes(entry);
448 removeInheritedRoutes(entry, routesToRemove);
451 modifyChildrensInheritedRoutes(entry.getChildren(), routesToAdd, routesToRemove);
456 const Route* other = entry.getRouteWithLowestCostByFaceId(route.faceId);
458 if (other ==
nullptr || route.cost <= other->cost) {
464 FibUpdater::createFibUpdatesForUpdatedRoute(
const RibEntry& entry,
const Route& route,
465 const Route& existingRoute)
467 const bool costDidChange = (route.cost != existingRoute.cost);
470 const Route* prevRoute = entry.getRouteWithLowestCostAndChildInheritByFaceId(route.faceId);
473 if (route.flags == existingRoute.flags && !costDidChange) {
480 if (route.cost <= entry.getRouteWithLowestCostByFaceId(route.faceId)->cost) {
484 else if (existingRoute.cost < entry.getRouteWithLowestCostByFaceId(route.faceId)->cost) {
492 if (prevRoute ==
nullptr || route.cost <= prevRoute->cost) {
495 if ((route.flags == existingRoute.flags) && route.isChildInherit()) {
498 routesToAdd.insert(route);
499 modifyChildrensInheritedRoutes(entry.getChildren(), routesToAdd,
Rib::RouteSet());
507 if (!existingRoute.isChildInherit() && route.isChildInherit()) {
510 if (prevRoute ==
nullptr || route.cost <= prevRoute->cost) {
513 routesToAdd.insert(route);
514 modifyChildrensInheritedRoutes(entry.getChildren(), routesToAdd,
Rib::RouteSet());
517 else if (existingRoute.isChildInherit() && !route.isChildInherit()) {
520 routesToRemove.insert(route);
524 if (prevRoute !=
nullptr) {
525 routesToAdd.insert(*prevRoute);
529 const Rib::RouteSet ancestorRoutes = m_rib.getAncestorRoutes(entry);
533 if (it != ancestorRoutes.end()) {
534 routesToAdd.insert(*it);
538 modifyChildrensInheritedRoutes(entry.getChildren(), routesToAdd, routesToRemove);
542 if (!existingRoute.isRibCapture() && route.isRibCapture()) {
543 Rib::RouteSet ancestorRoutes = m_rib.getAncestorRoutes(entry);
546 removeInheritedRoutes(entry, ancestorRoutes);
549 modifyChildrensInheritedRoutes(entry.getChildren(),
Rib::RouteSet(), ancestorRoutes);
551 else if (existingRoute.isRibCapture() && !route.isRibCapture()) {
552 Rib::RouteSet ancestorRoutes = m_rib.getAncestorRoutes(entry);
555 addInheritedRoutes(entry, ancestorRoutes);
558 modifyChildrensInheritedRoutes(entry.getChildren(), ancestorRoutes,
Rib::RouteSet());
563 FibUpdater::createFibUpdatesForErasedRoute(
const RibEntry& entry,
const Route& route,
564 const bool captureWasTurnedOff)
568 if (route.isChildInherit() && route.isRibCapture()) {
571 routesToRemove.insert(route);
576 if (captureWasTurnedOff && entry.getNRoutes() != 0) {
578 routesToAdd = m_rib.getAncestorRoutes(entry);
581 addInheritedRoutes(entry, routesToAdd);
584 modifyChildrensInheritedRoutes(entry.getChildren(), routesToAdd, routesToRemove);
586 else if (route.isChildInherit()) {
589 if (!entry.hasCapture()) {
590 routesToAdd = m_rib.getAncestorRoutes(entry);
594 routesToRemove.insert(route);
597 modifyChildrensInheritedRoutes(entry.getChildren(), routesToAdd, routesToRemove);
599 else if (route.isRibCapture()) {
603 if (captureWasTurnedOff && entry.getNRoutes() != 0) {
605 routesToAdd = m_rib.getAncestorRoutes(entry);
608 addInheritedRoutes(entry, routesToAdd);
611 modifyChildrensInheritedRoutes(entry.getChildren(), routesToAdd,
Rib::RouteSet());
615 Rib::RouteSet ancestorRoutes = m_rib.getAncestorRoutes(entry);
618 if (!entry.hasCapture() && entry.getNRoutes() != 0) {
623 if (it != ancestorRoutes.end()) {
624 addInheritedRoute(entry.getName(), *it);
631 FibUpdater::createFibUpdatesForErasedRibEntry(
const RibEntry& entry)
633 for (
const Route& route : entry.getInheritedRoutes()) {
643 for (
const auto& child : children) {
644 traverseSubTree(*child, routesToAdd, routesToRemove);
649 FibUpdater::traverseSubTree(
const RibEntry& entry, Rib::Rib::RouteSet routesToAdd,
650 Rib::Rib::RouteSet routesToRemove)
653 if (entry.hasCapture()) {
658 for (Rib::RouteSet::const_iterator removeIt = routesToRemove.begin();
659 removeIt != routesToRemove.end(); )
663 if (entry.hasChildInheritOnFaceId(removeIt->faceId)) {
664 routesToRemove.erase(removeIt++);
669 if (entry.hasInheritedRoute(*removeIt)) {
670 removeInheritedRoute(entry.getName(), *removeIt);
678 for (Rib::RouteSet::const_iterator addIt = routesToAdd.begin(); addIt != routesToAdd.end(); ) {
681 if (entry.hasChildInheritOnFaceId(addIt->faceId)) {
682 routesToAdd.erase(addIt++);
687 if (!entry.hasFaceId(addIt->faceId)) {
688 addInheritedRoute(entry.getName(), *addIt);
695 modifyChildrensInheritedRoutes(entry.getChildren(), routesToAdd, routesToRemove);
699 FibUpdater::addInheritedRoute(
const Name&
name,
const Route& route)
706 m_inheritedRoutes.push_back(update);
710 FibUpdater::removeInheritedRoute(
const Name&
name,
const Route& route)
717 m_inheritedRoutes.push_back(update);
void start(const ControlParameters ¶meters, const CommandSucceedCallback &onSuccess, const CommandFailCallback &onFailure, const CommandOptions &options=CommandOptions())
start command execution
const_iterator end() const
FibUpdater(Rib &rib, ndn::nfd::Controller &controller)
represents the Routing Information Base
RibEntry
Copyright (c) 2014-2017, Regents of the University of California, Arizona Board of Regents...
represents a fib/add-nexthop command
represents a collection of RibUpdates to be applied to a single FaceId
const_iterator find(const Name &prefix) const
std::list< FibUpdate > FibUpdateList
std::function< void(RibUpdateList inheritedRoutes)> FibUpdateSuccessCallback
#define NFD_LOG_DEBUG(expression)
std::function< void(uint32_t code, const std::string &error)> FibUpdateFailureCallback
represents a fib/remove-nexthop command
static const uint32_t ERROR_TIMEOUT
error code for timeout
std::set< Route, RouteComparePredicate > RouteSet
Table::const_iterator iterator
std::list< shared_ptr< RibEntry > > RibEntryList
static FibUpdate createRemoveUpdate(const Name &name, const uint64_t faceId)
Copyright (c) 2011-2015 Regents of the University of California.
static FibUpdate createAddUpdate(const Name &name, const uint64_t faceId, const uint64_t cost)
shared_ptr< RibEntry > findParent(const Name &prefix) const
NFD Management protocol client.
RibTable::const_iterator const_iterator
RouteList::const_iterator const_iterator
const std::string & getText() const
std::list< shared_ptr< RibEntry > > findDescendantsForNonInsertedName(const Name &prefix) const
finds namespaces under the passed prefix
std::string to_string(const V &v)
An update triggered by a face destruction notification.
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 ...
#define NFD_LOG_INIT(name)
uint64_t getFaceId() const
void setFibUpdater(FibUpdater *updater)