29 #include <ndn-cxx/mgmt/nfd/control-parameters.hpp>
35 using ndn::nfd::ControlParameters;
42 , m_controller(controller)
55 m_inheritedRoutes.clear();
58 m_updatesForBatchFaceId.clear();
59 m_updatesForNonBatchFaceId.clear();
61 computeUpdates(batch);
63 sendUpdatesForBatchFaceId(onSuccess, onFailure);
73 switch (update.getAction()) {
75 computeUpdatesForRegistration(update);
78 computeUpdatesForUnregistration(update);
81 computeUpdatesForUnregistration(update);
85 m_updatesForBatchFaceId.clear();
92 FibUpdater::computeUpdatesForRegistration(
const RibUpdate& update)
94 const Name& prefix = update.getName();
95 const Route& route = update.getRoute();
97 auto it = m_rib.
find(prefix);
100 if (it != m_rib.
end()) {
101 shared_ptr<const RibEntry> entry(it->second);
103 auto existingRoute = entry->findRoute(route);
106 if (existingRoute == entry->end()) {
108 bool willCaptureBeTurnedOn = (entry->hasCapture() ==
false && route.isRibCapture());
110 createFibUpdatesForNewRoute(*entry, route, willCaptureBeTurnedOn);
114 RibEntry entryCopy = *entry;
116 Route& routeToUpdate = *entryCopy.findRoute(route);
117 routeToUpdate.flags = route.flags;
118 routeToUpdate.cost = route.cost;
119 routeToUpdate.expires = route.expires;
121 createFibUpdatesForUpdatedRoute(entryCopy, route, *existingRoute);
127 shared_ptr<RibEntry> parent = m_rib.
findParent(prefix);
132 for (
const auto& descendant : descendants) {
135 if (descendant->getParent() == parent) {
136 children.push_back(descendant);
140 createFibUpdatesForNewRibEntry(prefix, route, children);
145 FibUpdater::computeUpdatesForUnregistration(
const RibUpdate& update)
147 const Name& prefix = update.getName();
148 const Route& route = update.getRoute();
150 auto ribIt = m_rib.
find(prefix);
153 if (ribIt != m_rib.
end()) {
154 shared_ptr<const RibEntry> entry(ribIt->second);
155 const bool hadCapture = entry->hasCapture();
157 auto existing = entry->findRoute(route);
158 if (existing != entry->end()) {
159 RibEntry temp = *entry;
162 temp.eraseRoute(route);
164 const bool captureWasTurnedOff = (hadCapture && !temp.hasCapture());
166 createFibUpdatesForErasedRoute(temp, *existing, captureWasTurnedOff);
170 const Route* next = entry->getRouteWithSecondLowestCostByFaceId(route.faceId);
172 if (next !=
nullptr) {
173 createFibUpdatesForNewRoute(temp, *next,
false);
177 if (entry->getNRoutes() == 1) {
178 createFibUpdatesForErasedRibEntry(*entry);
185 FibUpdater::sendUpdates(
const FibUpdateList& updates,
186 const FibUpdateSuccessCallback& onSuccess,
187 const FibUpdateFailureCallback& onFailure)
189 std::string updateString = (updates.size() == 1) ?
" update" :
" updates";
190 NFD_LOG_DEBUG(
"Applying " << updates.size() << updateString <<
" to FIB");
192 for (
const FibUpdate& update : updates) {
196 sendAddNextHopUpdate(update, onSuccess, onFailure);
199 sendRemoveNextHopUpdate(update, onSuccess, onFailure);
205 FibUpdater::sendUpdatesForBatchFaceId(
const FibUpdateSuccessCallback& onSuccess,
206 const FibUpdateFailureCallback& onFailure)
208 if (m_updatesForBatchFaceId.size() > 0) {
209 sendUpdates(m_updatesForBatchFaceId, onSuccess, onFailure);
212 sendUpdatesForNonBatchFaceId(onSuccess, onFailure);
217 FibUpdater::sendUpdatesForNonBatchFaceId(
const FibUpdateSuccessCallback& onSuccess,
218 const FibUpdateFailureCallback& onFailure)
220 if (m_updatesForNonBatchFaceId.size() > 0) {
221 sendUpdates(m_updatesForNonBatchFaceId, onSuccess, onFailure);
224 onSuccess(m_inheritedRoutes);
229 FibUpdater::sendAddNextHopUpdate(
const FibUpdate& update,
230 const FibUpdateSuccessCallback& onSuccess,
231 const FibUpdateFailureCallback& onFailure,
234 m_controller.start<ndn::nfd::FibAddNextHopCommand>(
236 .setName(update.name)
237 .setFaceId(update.faceId)
238 .setCost(update.cost),
239 [=] (
const auto&) { onUpdateSuccess(update, onSuccess, onFailure); },
240 [=] (
const auto& resp) { onUpdateError(update, onSuccess, onFailure, resp, nTimeouts); });
244 FibUpdater::sendRemoveNextHopUpdate(
const FibUpdate& update,
245 const FibUpdateSuccessCallback& onSuccess,
246 const FibUpdateFailureCallback& onFailure,
249 m_controller.start<ndn::nfd::FibRemoveNextHopCommand>(
251 .setName(update.name)
252 .setFaceId(update.faceId),
253 [=] (
const auto&) { onUpdateSuccess(update, onSuccess, onFailure); },
254 [=] (
const auto& resp) { onUpdateError(update, onSuccess, onFailure, resp, nTimeouts); });
258 FibUpdater::onUpdateSuccess(
const FibUpdate& update,
259 const FibUpdateSuccessCallback& onSuccess,
260 const FibUpdateFailureCallback& onFailure)
262 if (update.faceId == m_batchFaceId) {
263 m_updatesForBatchFaceId.remove(update);
265 if (m_updatesForBatchFaceId.size() == 0) {
266 sendUpdatesForNonBatchFaceId(onSuccess, onFailure);
270 m_updatesForNonBatchFaceId.remove(update);
272 if (m_updatesForNonBatchFaceId.size() == 0) {
273 onSuccess(m_inheritedRoutes);
279 FibUpdater::onUpdateError(
const FibUpdate& update,
280 const FibUpdateSuccessCallback& onSuccess,
281 const FibUpdateFailureCallback& onFailure,
282 const ndn::nfd::ControlResponse& response, uint32_t nTimeouts)
284 uint32_t code = response.getCode();
286 " (code: " << code <<
", error: " << response.getText() <<
")");
288 if (code == ndn::nfd::Controller::ERROR_TIMEOUT && nTimeouts <
MAX_NUM_TIMEOUTS) {
289 sendAddNextHopUpdate(update, onSuccess, onFailure, ++nTimeouts);
292 if (update.faceId == m_batchFaceId) {
293 onFailure(code, response.getText());
296 m_updatesForNonBatchFaceId.remove(update);
298 if (m_updatesForNonBatchFaceId.size() == 0) {
299 onSuccess(m_inheritedRoutes);
304 NDN_THROW(Error(
"Non-recoverable error: " + response.getText() +
" code: " + to_string(code)));
309 FibUpdater::addFibUpdate(
const FibUpdate& update)
311 FibUpdateList& updates = (update.faceId == m_batchFaceId) ? m_updatesForBatchFaceId :
312 m_updatesForNonBatchFaceId;
315 auto it = std::find_if(updates.begin(), updates.end(),
316 [&update] (
const FibUpdate& other) {
317 return update.name == other.name && update.faceId == other.faceId;
320 if (it != updates.end()) {
321 FibUpdate& existingUpdate = *it;
322 existingUpdate.action = update.action;
323 existingUpdate.cost = update.cost;
326 updates.push_back(update);
331 FibUpdater::addInheritedRoutes(
const RibEntry& entry,
const Rib::RouteSet& routesToAdd)
333 for (
const Route& route : routesToAdd) {
335 if (!entry.hasFaceId(route.faceId)) {
337 addInheritedRoute(entry.getName(), route);
345 FibUpdater::addInheritedRoutes(
const Name& name,
const Rib::RouteSet& routesToAdd,
348 for (
const Route& route : routesToAdd) {
349 if (route.faceId != ignore.faceId) {
351 addInheritedRoute(name, route);
359 FibUpdater::removeInheritedRoutes(
const RibEntry& entry,
const Rib::Rib::RouteSet& routesToRemove)
361 for (
const Route& route : routesToRemove) {
363 if (entry.hasInheritedRoute(route)) {
364 removeInheritedRoute(entry.getName(), route);
371 FibUpdater::createFibUpdatesForNewRibEntry(
const Name& name,
const Route& route,
378 if (!route.isChildInherit() && !route.isRibCapture()) {
380 addInheritedRoutes(name, m_rib.getAncestorRoutes(name), route);
382 else if (route.isChildInherit() && route.isRibCapture()) {
384 Rib::RouteSet routesToAdd;
385 routesToAdd.insert(route);
388 modifyChildrensInheritedRoutes(children, routesToAdd, m_rib.getAncestorRoutes(name));
390 else if (route.isChildInherit()) {
391 Rib::RouteSet ancestorRoutes = m_rib.getAncestorRoutes(name);
394 addInheritedRoutes(name, ancestorRoutes, route);
398 auto it = ancestorRoutes.find(route);
401 if (it != ancestorRoutes.end()) {
402 ancestorRoutes.erase(it);
406 ancestorRoutes.insert(route);
409 modifyChildrensInheritedRoutes(children, ancestorRoutes, Rib::RouteSet());
411 else if (route.isRibCapture()) {
413 modifyChildrensInheritedRoutes(children, Rib::RouteSet(), m_rib.getAncestorRoutes(name));
418 FibUpdater::createFibUpdatesForNewRoute(
const RibEntry& entry,
const Route& route,
419 bool captureWasTurnedOn)
422 const Route* prevRoute = entry.getRouteWithLowestCostAndChildInheritByFaceId(route.faceId);
424 Rib::RouteSet routesToAdd;
425 if (route.isChildInherit()) {
429 if (prevRoute ==
nullptr || route.cost <= prevRoute->cost) {
431 routesToAdd.insert(route);
435 Rib::RouteSet routesToRemove;
436 if (captureWasTurnedOn) {
438 routesToRemove = m_rib.getAncestorRoutes(entry);
441 removeInheritedRoutes(entry, routesToRemove);
444 modifyChildrensInheritedRoutes(entry.getChildren(), routesToAdd, routesToRemove);
449 const Route* other = entry.getRouteWithLowestCostByFaceId(route.faceId);
451 if (other ==
nullptr || route.cost <= other->cost) {
457 FibUpdater::createFibUpdatesForUpdatedRoute(
const RibEntry& entry,
const Route& route,
458 const Route& existingRoute)
460 const bool costDidChange = (route.cost != existingRoute.cost);
463 const Route* prevRoute = entry.getRouteWithLowestCostAndChildInheritByFaceId(route.faceId);
466 if (route.flags == existingRoute.flags && !costDidChange) {
473 if (route.cost <= entry.getRouteWithLowestCostByFaceId(route.faceId)->cost) {
477 else if (existingRoute.cost < entry.getRouteWithLowestCostByFaceId(route.faceId)->cost) {
485 if (prevRoute ==
nullptr || route.cost <= prevRoute->cost) {
488 if ((route.flags == existingRoute.flags) && route.isChildInherit()) {
490 Rib::RouteSet routesToAdd;
491 routesToAdd.insert(route);
492 modifyChildrensInheritedRoutes(entry.getChildren(), routesToAdd, Rib::RouteSet());
500 if (!existingRoute.isChildInherit() && route.isChildInherit()) {
503 if (prevRoute ==
nullptr || route.cost <= prevRoute->cost) {
505 Rib::RouteSet routesToAdd;
506 routesToAdd.insert(route);
507 modifyChildrensInheritedRoutes(entry.getChildren(), routesToAdd, Rib::RouteSet());
510 else if (existingRoute.isChildInherit() && !route.isChildInherit()) {
512 Rib::RouteSet routesToRemove;
513 routesToRemove.insert(route);
515 Rib::RouteSet routesToAdd;
517 if (prevRoute !=
nullptr) {
518 routesToAdd.insert(*prevRoute);
522 const Rib::RouteSet ancestorRoutes = m_rib.getAncestorRoutes(entry);
523 auto it = ancestorRoutes.find(route);
526 if (it != ancestorRoutes.end()) {
527 routesToAdd.insert(*it);
531 modifyChildrensInheritedRoutes(entry.getChildren(), routesToAdd, routesToRemove);
535 if (!existingRoute.isRibCapture() && route.isRibCapture()) {
536 Rib::RouteSet ancestorRoutes = m_rib.getAncestorRoutes(entry);
539 removeInheritedRoutes(entry, ancestorRoutes);
542 modifyChildrensInheritedRoutes(entry.getChildren(), Rib::RouteSet(), ancestorRoutes);
544 else if (existingRoute.isRibCapture() && !route.isRibCapture()) {
545 Rib::RouteSet ancestorRoutes = m_rib.getAncestorRoutes(entry);
548 addInheritedRoutes(entry, ancestorRoutes);
551 modifyChildrensInheritedRoutes(entry.getChildren(), ancestorRoutes, Rib::RouteSet());
556 FibUpdater::createFibUpdatesForErasedRoute(
const RibEntry& entry,
const Route& route,
557 bool captureWasTurnedOff)
561 if (route.isChildInherit() && route.isRibCapture()) {
563 Rib::RouteSet routesToRemove;
564 routesToRemove.insert(route);
568 Rib::RouteSet routesToAdd;
569 if (captureWasTurnedOff && entry.getNRoutes() != 0) {
571 routesToAdd = m_rib.getAncestorRoutes(entry);
574 addInheritedRoutes(entry, routesToAdd);
577 modifyChildrensInheritedRoutes(entry.getChildren(), routesToAdd, routesToRemove);
579 else if (route.isChildInherit()) {
581 Rib::RouteSet routesToAdd;
582 if (!entry.hasCapture()) {
583 routesToAdd = m_rib.getAncestorRoutes(entry);
586 Rib::RouteSet routesToRemove;
587 routesToRemove.insert(route);
590 modifyChildrensInheritedRoutes(entry.getChildren(), routesToAdd, routesToRemove);
592 else if (route.isRibCapture()) {
595 Rib::RouteSet routesToAdd;
596 if (captureWasTurnedOff && entry.getNRoutes() != 0) {
598 routesToAdd = m_rib.getAncestorRoutes(entry);
601 addInheritedRoutes(entry, routesToAdd);
604 modifyChildrensInheritedRoutes(entry.getChildren(), routesToAdd, Rib::RouteSet());
608 Rib::RouteSet ancestorRoutes = m_rib.getAncestorRoutes(entry);
611 if (!entry.hasCapture() && entry.getNRoutes() != 0) {
614 auto it = ancestorRoutes.find(route);
616 if (it != ancestorRoutes.end()) {
617 addInheritedRoute(entry.getName(), *it);
624 FibUpdater::createFibUpdatesForErasedRibEntry(
const RibEntry& entry)
626 for (
const Route& route : entry.getInheritedRoutes()) {
633 const Rib::RouteSet& routesToAdd,
634 const Rib::RouteSet& routesToRemove)
636 for (
const auto& child : children) {
637 traverseSubTree(*child, routesToAdd, routesToRemove);
642 FibUpdater::traverseSubTree(
const RibEntry& entry, Rib::Rib::RouteSet routesToAdd,
643 Rib::Rib::RouteSet routesToRemove)
646 if (entry.hasCapture()) {
651 for (
auto removeIt = routesToRemove.begin(); removeIt != routesToRemove.end(); ) {
654 if (entry.hasChildInheritOnFaceId(removeIt->faceId)) {
655 removeIt = routesToRemove.erase(removeIt);
660 if (entry.hasInheritedRoute(*removeIt)) {
661 removeInheritedRoute(entry.getName(), *removeIt);
669 for (
auto addIt = routesToAdd.begin(); addIt != routesToAdd.end(); ) {
671 if (entry.hasChildInheritOnFaceId(addIt->faceId)) {
672 addIt = routesToAdd.erase(addIt);
677 if (!entry.hasFaceId(addIt->faceId)) {
678 addInheritedRoute(entry.getName(), *addIt);
685 modifyChildrensInheritedRoutes(entry.getChildren(), routesToAdd, routesToRemove);
689 FibUpdater::addInheritedRoute(
const Name& name,
const Route& route)
696 m_inheritedRoutes.push_back(update);
700 FibUpdater::removeInheritedRoute(
const Name& name,
const Route& route)
707 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
Represents a route that will be added to or removed from a namespace.
@ 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