38 const unsigned int FibUpdater::MAX_NUM_TIMEOUTS = 10;
39 const uint32_t FibUpdater::ERROR_FACE_NOT_FOUND = 410;
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();
96 const Route& route = update.getRoute();
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);
117 Route& routeToUpdate = *(entryCopy.findRoute(route));
119 routeToUpdate.flags = route.flags;
120 routeToUpdate.cost = route.cost;
121 routeToUpdate.expires = route.expires;
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();
150 const Route& route = update.getRoute();
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()) {
166 temp.eraseRoute(route);
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);
189 FibUpdater::sendUpdates(
const FibUpdateList& updates,
190 const FibUpdateSuccessCallback& onSuccess,
191 const FibUpdateFailureCallback& onFailure)
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);
209 FibUpdater::sendUpdatesForBatchFaceId(
const FibUpdateSuccessCallback& onSuccess,
210 const FibUpdateFailureCallback& onFailure)
212 if (m_updatesForBatchFaceId.size() > 0) {
213 sendUpdates(m_updatesForBatchFaceId, onSuccess, onFailure);
216 sendUpdatesForNonBatchFaceId(onSuccess, onFailure);
221 FibUpdater::sendUpdatesForNonBatchFaceId(
const FibUpdateSuccessCallback& onSuccess,
222 const FibUpdateFailureCallback& onFailure)
224 if (m_updatesForNonBatchFaceId.size() > 0) {
225 sendUpdates(m_updatesForNonBatchFaceId, onSuccess, onFailure);
228 onSuccess(m_inheritedRoutes);
233 FibUpdater::sendAddNextHopUpdate(
const FibUpdate& update,
234 const FibUpdateSuccessCallback& onSuccess,
235 const FibUpdateFailureCallback& onFailure,
240 .setName(update.name)
241 .setFaceId(update.faceId)
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,
249 const FibUpdateSuccessCallback& onSuccess,
250 const FibUpdateFailureCallback& onFailure,
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,
263 const FibUpdateSuccessCallback& onSuccess,
264 const FibUpdateFailureCallback& onFailure)
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,
284 const FibUpdateSuccessCallback& onSuccess,
285 const FibUpdateFailureCallback& onFailure,
288 uint32_t code = response.
getCode();
290 " (code: " << code <<
", error: " << response.
getText() <<
")");
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 BOOST_THROW_EXCEPTION(Error(
"Non-recoverable error: " + response.
getText() +
314 FibUpdater::addFibUpdate(FibUpdate update)
316 FibUpdateList& updates = (update.faceId == m_batchFaceId) ? m_updatesForBatchFaceId :
317 m_updatesForNonBatchFaceId;
322 [&update] (
const FibUpdate& other) {
323 return update.name == other.name && update.faceId == other.faceId;
326 if (it != updates.end()) {
327 FibUpdate& existingUpdate = *it;
328 existingUpdate.action = update.action;
329 existingUpdate.cost = update.cost;
332 updates.push_back(update);
339 for (
const Route& route : routesToAdd) {
341 if (!entry.hasFaceId(route.faceId)) {
343 addInheritedRoute(entry.getName(), route);
354 for (
const Route& route : routesToAdd) {
355 if (route.faceId != ignore.faceId) {
357 addInheritedRoute(
name, route);
365 FibUpdater::removeInheritedRoutes(
const RibEntry& entry,
const Rib::Rib::RouteSet& routesToRemove)
367 for (
const Route& route : routesToRemove) {
369 if (entry.hasInheritedRoute(route)) {
370 removeInheritedRoute(entry.getName(), route);
377 FibUpdater::createFibUpdatesForNewRibEntry(
const Name&
name,
const Route& route,
384 if (!route.isChildInherit() && !route.isRibCapture()) {
386 addInheritedRoutes(
name, m_rib.getAncestorRoutes(
name), route);
388 else if (route.isChildInherit() && route.isRibCapture()) {
391 routesToAdd.insert(route);
394 modifyChildrensInheritedRoutes(children, routesToAdd, m_rib.getAncestorRoutes(
name));
396 else if (route.isChildInherit()) {
400 addInheritedRoutes(
name, ancestorRoutes, route);
407 if (it != ancestorRoutes.end()) {
408 ancestorRoutes.erase(it);
412 ancestorRoutes.insert(route);
415 modifyChildrensInheritedRoutes(children, ancestorRoutes,
Rib::RouteSet());
417 else if (route.isRibCapture()) {
419 modifyChildrensInheritedRoutes(children,
Rib::RouteSet(), m_rib.getAncestorRoutes(
name));
424 FibUpdater::createFibUpdatesForNewRoute(
const RibEntry& entry,
const Route& route,
425 bool captureWasTurnedOn)
428 const Route* prevRoute = entry.getRouteWithLowestCostAndChildInheritByFaceId(route.faceId);
431 if (route.isChildInherit()) {
435 if (prevRoute ==
nullptr || route.cost <= prevRoute->cost) {
437 routesToAdd.insert(route);
442 if (captureWasTurnedOn) {
444 routesToRemove = m_rib.getAncestorRoutes(entry);
447 removeInheritedRoutes(entry, routesToRemove);
450 modifyChildrensInheritedRoutes(entry.getChildren(), routesToAdd, routesToRemove);
455 const Route* other = entry.getRouteWithLowestCostByFaceId(route.faceId);
457 if (other ==
nullptr || route.cost <= other->cost) {
463 FibUpdater::createFibUpdatesForUpdatedRoute(
const RibEntry& entry,
const Route& route,
464 const Route& existingRoute)
466 const bool costDidChange = (route.cost != existingRoute.cost);
469 const Route* prevRoute = entry.getRouteWithLowestCostAndChildInheritByFaceId(route.faceId);
472 if (route.flags == existingRoute.flags && !costDidChange) {
479 if (route.cost <= entry.getRouteWithLowestCostByFaceId(route.faceId)->cost) {
483 else if (existingRoute.cost < entry.getRouteWithLowestCostByFaceId(route.faceId)->cost) {
491 if (prevRoute ==
nullptr || route.cost <= prevRoute->cost) {
494 if ((route.flags == existingRoute.flags) && route.isChildInherit()) {
497 routesToAdd.insert(route);
498 modifyChildrensInheritedRoutes(entry.getChildren(), routesToAdd,
Rib::RouteSet());
506 if (!existingRoute.isChildInherit() && route.isChildInherit()) {
509 if (prevRoute ==
nullptr || route.cost <= prevRoute->cost) {
512 routesToAdd.insert(route);
513 modifyChildrensInheritedRoutes(entry.getChildren(), routesToAdd,
Rib::RouteSet());
516 else if (existingRoute.isChildInherit() && !route.isChildInherit()) {
519 routesToRemove.insert(route);
523 if (prevRoute !=
nullptr) {
524 routesToAdd.insert(*prevRoute);
528 const Rib::RouteSet ancestorRoutes = m_rib.getAncestorRoutes(entry);
532 if (it != ancestorRoutes.end()) {
533 routesToAdd.insert(*it);
537 modifyChildrensInheritedRoutes(entry.getChildren(), routesToAdd, routesToRemove);
541 if (!existingRoute.isRibCapture() && route.isRibCapture()) {
542 Rib::RouteSet ancestorRoutes = m_rib.getAncestorRoutes(entry);
545 removeInheritedRoutes(entry, ancestorRoutes);
548 modifyChildrensInheritedRoutes(entry.getChildren(),
Rib::RouteSet(), ancestorRoutes);
550 else if (existingRoute.isRibCapture() && !route.isRibCapture()) {
551 Rib::RouteSet ancestorRoutes = m_rib.getAncestorRoutes(entry);
554 addInheritedRoutes(entry, ancestorRoutes);
557 modifyChildrensInheritedRoutes(entry.getChildren(), ancestorRoutes,
Rib::RouteSet());
562 FibUpdater::createFibUpdatesForErasedRoute(
const RibEntry& entry,
const Route& route,
563 const bool captureWasTurnedOff)
567 if (route.isChildInherit() && route.isRibCapture()) {
570 routesToRemove.insert(route);
575 if (captureWasTurnedOff && entry.getNRoutes() != 0) {
577 routesToAdd = m_rib.getAncestorRoutes(entry);
580 addInheritedRoutes(entry, routesToAdd);
583 modifyChildrensInheritedRoutes(entry.getChildren(), routesToAdd, routesToRemove);
585 else if (route.isChildInherit()) {
588 if (!entry.hasCapture()) {
589 routesToAdd = m_rib.getAncestorRoutes(entry);
593 routesToRemove.insert(route);
596 modifyChildrensInheritedRoutes(entry.getChildren(), routesToAdd, routesToRemove);
598 else if (route.isRibCapture()) {
602 if (captureWasTurnedOff && entry.getNRoutes() != 0) {
604 routesToAdd = m_rib.getAncestorRoutes(entry);
607 addInheritedRoutes(entry, routesToAdd);
610 modifyChildrensInheritedRoutes(entry.getChildren(), routesToAdd,
Rib::RouteSet());
614 Rib::RouteSet ancestorRoutes = m_rib.getAncestorRoutes(entry);
617 if (!entry.hasCapture() && entry.getNRoutes() != 0) {
622 if (it != ancestorRoutes.end()) {
623 addInheritedRoute(entry.getName(), *it);
630 FibUpdater::createFibUpdatesForErasedRibEntry(
const RibEntry& entry)
632 for (
const Route& route : entry.getInheritedRoutes()) {
642 for (
const auto& child : children) {
643 traverseSubTree(*child, routesToAdd, routesToRemove);
648 FibUpdater::traverseSubTree(
const RibEntry& entry, Rib::Rib::RouteSet routesToAdd,
649 Rib::Rib::RouteSet routesToRemove)
652 if (entry.hasCapture()) {
657 for (
auto removeIt = routesToRemove.begin(); removeIt != routesToRemove.end(); ) {
660 if (entry.hasChildInheritOnFaceId(removeIt->faceId)) {
661 removeIt = routesToRemove.erase(removeIt);
666 if (entry.hasInheritedRoute(*removeIt)) {
667 removeInheritedRoute(entry.getName(), *removeIt);
675 for (
auto addIt = routesToAdd.begin(); addIt != routesToAdd.end(); ) {
677 if (entry.hasChildInheritOnFaceId(addIt->faceId)) {
678 addIt = routesToAdd.erase(addIt);
683 if (!entry.hasFaceId(addIt->faceId)) {
684 addInheritedRoute(entry.getName(), *addIt);
691 modifyChildrensInheritedRoutes(entry.getChildren(), routesToAdd, routesToRemove);
695 FibUpdater::addInheritedRoute(
const Name&
name,
const Route& route)
702 m_inheritedRoutes.push_back(update);
706 FibUpdater::removeInheritedRoute(
const Name&
name,
const Route& route)
713 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
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
computes FibUpdates based on updates to the RIB and sends them to NFD
std::list< FibUpdate > FibUpdateList
std::function< void(RibUpdateList inheritedRoutes)> FibUpdateSuccessCallback
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)