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();
96 const Route& route = update.getRoute();
98 auto it = m_rib.
find(prefix);
101 if (it != m_rib.
end()) {
102 shared_ptr<const RibEntry> entry(it->second);
104 auto existingRoute = entry->findRoute(route);
107 if (existingRoute == entry->end()) {
109 bool willCaptureBeTurnedOn = (entry->hasCapture() ==
false && route.isRibCapture());
111 createFibUpdatesForNewRoute(*entry, route, willCaptureBeTurnedOn);
115 RibEntry entryCopy = *entry;
117 Route& routeToUpdate = *entryCopy.findRoute(route);
118 routeToUpdate.flags = route.flags;
119 routeToUpdate.cost = route.cost;
120 routeToUpdate.expires = route.expires;
122 createFibUpdatesForUpdatedRoute(entryCopy, route, *existingRoute);
128 shared_ptr<RibEntry> parent = m_rib.
findParent(prefix);
133 for (
const auto& descendant : descendants) {
136 if (descendant->getParent() == parent) {
137 children.push_back(descendant);
141 createFibUpdatesForNewRibEntry(prefix, route, children);
146 FibUpdater::computeUpdatesForUnregistration(
const RibUpdate& update)
148 const Name& prefix = update.getName();
149 const Route& route = update.getRoute();
151 auto ribIt = m_rib.
find(prefix);
154 if (ribIt != m_rib.
end()) {
155 shared_ptr<const RibEntry> entry(ribIt->second);
156 const bool hadCapture = entry->hasCapture();
158 auto existing = entry->findRoute(route);
159 if (existing != entry->end()) {
160 RibEntry temp = *entry;
163 temp.eraseRoute(route);
165 const bool captureWasTurnedOff = (hadCapture && !temp.hasCapture());
167 createFibUpdatesForErasedRoute(temp, *existing, captureWasTurnedOff);
171 const Route* next = entry->getRouteWithSecondLowestCostByFaceId(route.faceId);
173 if (next !=
nullptr) {
174 createFibUpdatesForNewRoute(temp, *next,
false);
178 if (entry->getNRoutes() == 1) {
179 createFibUpdatesForErasedRibEntry(*entry);
186 FibUpdater::sendUpdates(
const FibUpdateList& updates,
187 const FibUpdateSuccessCallback& onSuccess,
188 const FibUpdateFailureCallback& onFailure)
190 std::string updateString = (updates.size() == 1) ?
" update" :
" updates";
191 NFD_LOG_DEBUG(
"Applying " << updates.size() << updateString <<
" to FIB");
193 for (
const FibUpdate& update : updates) {
197 sendAddNextHopUpdate(update, onSuccess, onFailure);
200 sendRemoveNextHopUpdate(update, onSuccess, onFailure);
206 FibUpdater::sendUpdatesForBatchFaceId(
const FibUpdateSuccessCallback& onSuccess,
207 const FibUpdateFailureCallback& onFailure)
209 if (m_updatesForBatchFaceId.size() > 0) {
210 sendUpdates(m_updatesForBatchFaceId, onSuccess, onFailure);
213 sendUpdatesForNonBatchFaceId(onSuccess, onFailure);
218 FibUpdater::sendUpdatesForNonBatchFaceId(
const FibUpdateSuccessCallback& onSuccess,
219 const FibUpdateFailureCallback& onFailure)
221 if (m_updatesForNonBatchFaceId.size() > 0) {
222 sendUpdates(m_updatesForNonBatchFaceId, onSuccess, onFailure);
225 onSuccess(m_inheritedRoutes);
230 FibUpdater::sendAddNextHopUpdate(
const FibUpdate& update,
231 const FibUpdateSuccessCallback& onSuccess,
232 const FibUpdateFailureCallback& onFailure,
235 m_controller.start<ndn::nfd::FibAddNextHopCommand>(
237 .setName(update.name)
238 .setFaceId(update.faceId)
239 .setCost(update.cost),
240 [=] (
const auto&) { onUpdateSuccess(update, onSuccess, onFailure); },
241 [=] (
const auto& resp) { onUpdateError(update, onSuccess, onFailure, resp, nTimeouts); });
245 FibUpdater::sendRemoveNextHopUpdate(
const FibUpdate& update,
246 const FibUpdateSuccessCallback& onSuccess,
247 const FibUpdateFailureCallback& onFailure,
250 m_controller.start<ndn::nfd::FibRemoveNextHopCommand>(
252 .setName(update.name)
253 .setFaceId(update.faceId),
254 [=] (
const auto&) { onUpdateSuccess(update, onSuccess, onFailure); },
255 [=] (
const auto& resp) { onUpdateError(update, onSuccess, onFailure, resp, nTimeouts); });
259 FibUpdater::onUpdateSuccess(
const FibUpdate& update,
260 const FibUpdateSuccessCallback& onSuccess,
261 const FibUpdateFailureCallback& onFailure)
263 if (update.faceId == m_batchFaceId) {
264 m_updatesForBatchFaceId.remove(update);
266 if (m_updatesForBatchFaceId.size() == 0) {
267 sendUpdatesForNonBatchFaceId(onSuccess, onFailure);
271 m_updatesForNonBatchFaceId.remove(update);
273 if (m_updatesForNonBatchFaceId.size() == 0) {
274 onSuccess(m_inheritedRoutes);
280 FibUpdater::onUpdateError(
const FibUpdate& update,
281 const FibUpdateSuccessCallback& onSuccess,
282 const FibUpdateFailureCallback& onFailure,
283 const ndn::nfd::ControlResponse& response, uint32_t nTimeouts)
285 uint32_t code = response.getCode();
287 " (code: " << code <<
", error: " << response.getText() <<
")");
289 if (code == ndn::nfd::Controller::ERROR_TIMEOUT && nTimeouts <
MAX_NUM_TIMEOUTS) {
290 sendAddNextHopUpdate(update, onSuccess, onFailure, ++nTimeouts);
293 if (update.faceId == m_batchFaceId) {
294 onFailure(code, response.getText());
297 m_updatesForNonBatchFaceId.remove(update);
299 if (m_updatesForNonBatchFaceId.size() == 0) {
300 onSuccess(m_inheritedRoutes);
305 NDN_THROW(Error(
"Non-recoverable error: " + response.getText() +
" code: " + to_string(code)));
310 FibUpdater::addFibUpdate(
const FibUpdate& update)
312 FibUpdateList& updates = (update.faceId == m_batchFaceId) ? m_updatesForBatchFaceId :
313 m_updatesForNonBatchFaceId;
316 auto it = std::find_if(updates.begin(), updates.end(),
317 [&update] (
const FibUpdate& other) {
318 return update.name == other.name && update.faceId == other.faceId;
321 if (it != updates.end()) {
322 FibUpdate& existingUpdate = *it;
323 existingUpdate.action = update.action;
324 existingUpdate.cost = update.cost;
327 updates.push_back(update);
332 FibUpdater::addInheritedRoutes(
const RibEntry& entry,
const Rib::RouteSet& routesToAdd)
334 for (
const Route& route : routesToAdd) {
336 if (!entry.hasFaceId(route.faceId)) {
338 addInheritedRoute(entry.getName(), route);
346 FibUpdater::addInheritedRoutes(
const Name& name,
const Rib::RouteSet& routesToAdd,
349 for (
const Route& route : routesToAdd) {
350 if (route.faceId != ignore.faceId) {
352 addInheritedRoute(name, route);
360 FibUpdater::removeInheritedRoutes(
const RibEntry& entry,
const Rib::Rib::RouteSet& routesToRemove)
362 for (
const Route& route : routesToRemove) {
364 if (entry.hasInheritedRoute(route)) {
365 removeInheritedRoute(entry.getName(), route);
372 FibUpdater::createFibUpdatesForNewRibEntry(
const Name& name,
const Route& route,
379 if (!route.isChildInherit() && !route.isRibCapture()) {
381 addInheritedRoutes(name, m_rib.getAncestorRoutes(name), route);
383 else if (route.isChildInherit() && route.isRibCapture()) {
385 Rib::RouteSet routesToAdd;
386 routesToAdd.insert(route);
389 modifyChildrensInheritedRoutes(children, routesToAdd, m_rib.getAncestorRoutes(name));
391 else if (route.isChildInherit()) {
392 Rib::RouteSet ancestorRoutes = m_rib.getAncestorRoutes(name);
395 addInheritedRoutes(name, ancestorRoutes, route);
399 auto it = ancestorRoutes.find(route);
402 if (it != ancestorRoutes.end()) {
403 ancestorRoutes.erase(it);
407 ancestorRoutes.insert(route);
410 modifyChildrensInheritedRoutes(children, ancestorRoutes, Rib::RouteSet());
412 else if (route.isRibCapture()) {
414 modifyChildrensInheritedRoutes(children, Rib::RouteSet(), m_rib.getAncestorRoutes(name));
419 FibUpdater::createFibUpdatesForNewRoute(
const RibEntry& entry,
const Route& route,
420 bool captureWasTurnedOn)
423 const Route* prevRoute = entry.getRouteWithLowestCostAndChildInheritByFaceId(route.faceId);
425 Rib::RouteSet routesToAdd;
426 if (route.isChildInherit()) {
430 if (prevRoute ==
nullptr || route.cost <= prevRoute->cost) {
432 routesToAdd.insert(route);
436 Rib::RouteSet routesToRemove;
437 if (captureWasTurnedOn) {
439 routesToRemove = m_rib.getAncestorRoutes(entry);
442 removeInheritedRoutes(entry, routesToRemove);
445 modifyChildrensInheritedRoutes(entry.getChildren(), routesToAdd, routesToRemove);
450 const Route* other = entry.getRouteWithLowestCostByFaceId(route.faceId);
452 if (other ==
nullptr || route.cost <= other->cost) {
458 FibUpdater::createFibUpdatesForUpdatedRoute(
const RibEntry& entry,
const Route& route,
459 const Route& existingRoute)
461 const bool costDidChange = (route.cost != existingRoute.cost);
464 const Route* prevRoute = entry.getRouteWithLowestCostAndChildInheritByFaceId(route.faceId);
467 if (route.flags == existingRoute.flags && !costDidChange) {
474 if (route.cost <= entry.getRouteWithLowestCostByFaceId(route.faceId)->cost) {
478 else if (existingRoute.cost < entry.getRouteWithLowestCostByFaceId(route.faceId)->cost) {
486 if (prevRoute ==
nullptr || route.cost <= prevRoute->cost) {
489 if ((route.flags == existingRoute.flags) && route.isChildInherit()) {
491 Rib::RouteSet routesToAdd;
492 routesToAdd.insert(route);
493 modifyChildrensInheritedRoutes(entry.getChildren(), routesToAdd, Rib::RouteSet());
501 if (!existingRoute.isChildInherit() && route.isChildInherit()) {
504 if (prevRoute ==
nullptr || route.cost <= prevRoute->cost) {
506 Rib::RouteSet routesToAdd;
507 routesToAdd.insert(route);
508 modifyChildrensInheritedRoutes(entry.getChildren(), routesToAdd, Rib::RouteSet());
511 else if (existingRoute.isChildInherit() && !route.isChildInherit()) {
513 Rib::RouteSet routesToRemove;
514 routesToRemove.insert(route);
516 Rib::RouteSet routesToAdd;
518 if (prevRoute !=
nullptr) {
519 routesToAdd.insert(*prevRoute);
523 const Rib::RouteSet ancestorRoutes = m_rib.getAncestorRoutes(entry);
524 auto it = ancestorRoutes.find(route);
527 if (it != ancestorRoutes.end()) {
528 routesToAdd.insert(*it);
532 modifyChildrensInheritedRoutes(entry.getChildren(), routesToAdd, routesToRemove);
536 if (!existingRoute.isRibCapture() && route.isRibCapture()) {
537 Rib::RouteSet ancestorRoutes = m_rib.getAncestorRoutes(entry);
540 removeInheritedRoutes(entry, ancestorRoutes);
543 modifyChildrensInheritedRoutes(entry.getChildren(), Rib::RouteSet(), ancestorRoutes);
545 else if (existingRoute.isRibCapture() && !route.isRibCapture()) {
546 Rib::RouteSet ancestorRoutes = m_rib.getAncestorRoutes(entry);
549 addInheritedRoutes(entry, ancestorRoutes);
552 modifyChildrensInheritedRoutes(entry.getChildren(), ancestorRoutes, Rib::RouteSet());
557 FibUpdater::createFibUpdatesForErasedRoute(
const RibEntry& entry,
const Route& route,
558 const bool captureWasTurnedOff)
562 if (route.isChildInherit() && route.isRibCapture()) {
564 Rib::RouteSet routesToRemove;
565 routesToRemove.insert(route);
569 Rib::RouteSet routesToAdd;
570 if (captureWasTurnedOff && entry.getNRoutes() != 0) {
572 routesToAdd = m_rib.getAncestorRoutes(entry);
575 addInheritedRoutes(entry, routesToAdd);
578 modifyChildrensInheritedRoutes(entry.getChildren(), routesToAdd, routesToRemove);
580 else if (route.isChildInherit()) {
582 Rib::RouteSet routesToAdd;
583 if (!entry.hasCapture()) {
584 routesToAdd = m_rib.getAncestorRoutes(entry);
587 Rib::RouteSet routesToRemove;
588 routesToRemove.insert(route);
591 modifyChildrensInheritedRoutes(entry.getChildren(), routesToAdd, routesToRemove);
593 else if (route.isRibCapture()) {
596 Rib::RouteSet routesToAdd;
597 if (captureWasTurnedOff && entry.getNRoutes() != 0) {
599 routesToAdd = m_rib.getAncestorRoutes(entry);
602 addInheritedRoutes(entry, routesToAdd);
605 modifyChildrensInheritedRoutes(entry.getChildren(), routesToAdd, Rib::RouteSet());
609 Rib::RouteSet ancestorRoutes = m_rib.getAncestorRoutes(entry);
612 if (!entry.hasCapture() && entry.getNRoutes() != 0) {
615 auto it = ancestorRoutes.find(route);
617 if (it != ancestorRoutes.end()) {
618 addInheritedRoute(entry.getName(), *it);
625 FibUpdater::createFibUpdatesForErasedRibEntry(
const RibEntry& entry)
627 for (
const Route& route : entry.getInheritedRoutes()) {
634 const Rib::RouteSet& routesToAdd,
635 const Rib::RouteSet& routesToRemove)
637 for (
const auto& child : children) {
638 traverseSubTree(*child, routesToAdd, routesToRemove);
643 FibUpdater::traverseSubTree(
const RibEntry& entry, Rib::Rib::RouteSet routesToAdd,
644 Rib::Rib::RouteSet routesToRemove)
647 if (entry.hasCapture()) {
652 for (
auto removeIt = routesToRemove.begin(); removeIt != routesToRemove.end(); ) {
655 if (entry.hasChildInheritOnFaceId(removeIt->faceId)) {
656 removeIt = routesToRemove.erase(removeIt);
661 if (entry.hasInheritedRoute(*removeIt)) {
662 removeInheritedRoute(entry.getName(), *removeIt);
670 for (
auto addIt = routesToAdd.begin(); addIt != routesToAdd.end(); ) {
672 if (entry.hasChildInheritOnFaceId(addIt->faceId)) {
673 addIt = routesToAdd.erase(addIt);
678 if (!entry.hasFaceId(addIt->faceId)) {
679 addInheritedRoute(entry.getName(), *addIt);
686 modifyChildrensInheritedRoutes(entry.getChildren(), routesToAdd, routesToRemove);
690 FibUpdater::addInheritedRoute(
const Name& name,
const Route& route)
697 m_inheritedRoutes.push_back(update);
701 FibUpdater::removeInheritedRoute(
const Name& name,
const Route& route)
708 m_inheritedRoutes.push_back(update);
static FibUpdate createRemoveUpdate(const Name &name, const uint64_t faceId)
static FibUpdate createAddUpdate(const Name &name, const uint64_t faceId, const uint64_t cost)
std::function< void(RibUpdateList inheritedRoutes)> FibUpdateSuccessCallback
std::list< FibUpdate > FibUpdateList
FibUpdater(Rib &rib, ndn::nfd::Controller &controller)
std::function< void(uint32_t code, const std::string &error)> FibUpdateFailureCallback
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
represents the Routing Information Base
void setFibUpdater(FibUpdater *updater)
const_iterator end() const
std::list< shared_ptr< RibEntry > > RibEntryList
const_iterator find(const Name &prefix) const
shared_ptr< RibEntry > findParent(const Name &prefix) const
Represents a collection of RibUpdates to be applied to a single FaceId.
uint64_t getFaceId() const
@ REMOVE_FACE
An update triggered by a face destruction notification.
#define NFD_LOG_INIT(name)
constexpr uint32_t ERROR_FACE_NOT_FOUND
constexpr int MAX_NUM_TIMEOUTS
Copyright (c) 2014-2015, Regents of the University of California, Arizona Board of Regents,...