fib-updater.cpp
Go to the documentation of this file.
1 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
2 /*
3  * Copyright (c) 2014-2022, Regents of the University of California,
4  * Arizona Board of Regents,
5  * Colorado State University,
6  * University Pierre & Marie Curie, Sorbonne University,
7  * Washington University in St. Louis,
8  * Beijing Institute of Technology,
9  * The University of Memphis.
10  *
11  * This file is part of NFD (Named Data Networking Forwarding Daemon).
12  * See AUTHORS.md for complete list of NFD authors and contributors.
13  *
14  * NFD is free software: you can redistribute it and/or modify it under the terms
15  * of the GNU General Public License as published by the Free Software Foundation,
16  * either version 3 of the License, or (at your option) any later version.
17  *
18  * NFD is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
19  * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
20  * PURPOSE. See the GNU General Public License for more details.
21  *
22  * You should have received a copy of the GNU General Public License along with
23  * NFD, e.g., in COPYING.md file. If not, see <http://www.gnu.org/licenses/>.
24  */
25 
26 #include "fib-updater.hpp"
27 #include "common/logger.hpp"
28 
29 #include <ndn-cxx/mgmt/nfd/control-parameters.hpp>
30 
31 namespace nfd::rib {
32 
33 NFD_LOG_INIT(FibUpdater);
34 
35 using ndn::nfd::ControlParameters;
36 
37 constexpr int MAX_NUM_TIMEOUTS = 10;
38 constexpr uint32_t ERROR_FACE_NOT_FOUND = 410;
39 
40 FibUpdater::FibUpdater(Rib& rib, ndn::nfd::Controller& controller)
41  : m_rib(rib)
42  , m_controller(controller)
43 {
44  rib.setFibUpdater(this);
45 }
46 
47 void
49  const FibUpdateSuccessCallback& onSuccess,
50  const FibUpdateFailureCallback& onFailure)
51 {
52  m_batchFaceId = batch.getFaceId();
53 
54  // Erase previously calculated inherited routes
55  m_inheritedRoutes.clear();
56 
57  // Erase previously calculated FIB updates
58  m_updatesForBatchFaceId.clear();
59  m_updatesForNonBatchFaceId.clear();
60 
61  computeUpdates(batch);
62 
63  sendUpdatesForBatchFaceId(onSuccess, onFailure);
64 }
65 
66 void
67 FibUpdater::computeUpdates(const RibUpdateBatch& batch)
68 {
69  NFD_LOG_DEBUG("Computing updates for batch with faceID: " << batch.getFaceId());
70 
71  // Compute updates and add to m_fibUpdates
72  for (const RibUpdate& update : batch) {
73  switch (update.getAction()) {
75  computeUpdatesForRegistration(update);
76  break;
78  computeUpdatesForUnregistration(update);
79  break;
81  computeUpdatesForUnregistration(update);
82 
83  // Do not apply updates with the same face ID as the destroyed face
84  // since they will be rejected by the FIB
85  m_updatesForBatchFaceId.clear();
86  break;
87  }
88  }
89 }
90 
91 void
92 FibUpdater::computeUpdatesForRegistration(const RibUpdate& update)
93 {
94  const Name& prefix = update.getName();
95  const Route& route = update.getRoute();
96 
97  auto it = m_rib.find(prefix);
98 
99  // Name prefix exists
100  if (it != m_rib.end()) {
101  shared_ptr<const RibEntry> entry(it->second);
102 
103  auto existingRoute = entry->findRoute(route);
104 
105  // Route will be new
106  if (existingRoute == entry->end()) {
107  // Will the new route change the namespace's capture flag?
108  bool willCaptureBeTurnedOn = (entry->hasCapture() == false && route.isRibCapture());
109 
110  createFibUpdatesForNewRoute(*entry, route, willCaptureBeTurnedOn);
111  }
112  else {
113  // Route already exists
114  RibEntry entryCopy = *entry;
115 
116  Route& routeToUpdate = *entryCopy.findRoute(route);
117  routeToUpdate.flags = route.flags;
118  routeToUpdate.cost = route.cost;
119  routeToUpdate.expires = route.expires;
120 
121  createFibUpdatesForUpdatedRoute(entryCopy, route, *existingRoute);
122  }
123  }
124  else {
125  // New name in RIB
126  // Find prefix's parent
127  shared_ptr<RibEntry> parent = m_rib.findParent(prefix);
128 
129  Rib::RibEntryList descendants = m_rib.findDescendantsForNonInsertedName(prefix);
130  Rib::RibEntryList children;
131 
132  for (const auto& descendant : descendants) {
133  // If the child has the same parent as the new entry,
134  // the new entry must be the child's new parent
135  if (descendant->getParent() == parent) {
136  children.push_back(descendant);
137  }
138  }
139 
140  createFibUpdatesForNewRibEntry(prefix, route, children);
141  }
142 }
143 
144 void
145 FibUpdater::computeUpdatesForUnregistration(const RibUpdate& update)
146 {
147  const Name& prefix = update.getName();
148  const Route& route = update.getRoute();
149 
150  auto ribIt = m_rib.find(prefix);
151 
152  // Name prefix exists
153  if (ribIt != m_rib.end()) {
154  shared_ptr<const RibEntry> entry(ribIt->second);
155  const bool hadCapture = entry->hasCapture();
156 
157  auto existing = entry->findRoute(route);
158  if (existing != entry->end()) {
159  RibEntry temp = *entry;
160 
161  // Erase route in temp entry
162  temp.eraseRoute(route);
163 
164  const bool captureWasTurnedOff = (hadCapture && !temp.hasCapture());
165 
166  createFibUpdatesForErasedRoute(temp, *existing, captureWasTurnedOff);
167 
168  // The RibEntry still has the face ID; need to update FIB
169  // with lowest cost for the same face instead of removing the face from the FIB
170  const Route* next = entry->getRouteWithSecondLowestCostByFaceId(route.faceId);
171 
172  if (next != nullptr) {
173  createFibUpdatesForNewRoute(temp, *next, false);
174  }
175 
176  // The RibEntry will be empty after this removal
177  if (entry->getNRoutes() == 1) {
178  createFibUpdatesForErasedRibEntry(*entry);
179  }
180  }
181  }
182 }
183 
184 void
185 FibUpdater::sendUpdates(const FibUpdateList& updates,
186  const FibUpdateSuccessCallback& onSuccess,
187  const FibUpdateFailureCallback& onFailure)
188 {
189  std::string updateString = (updates.size() == 1) ? " update" : " updates";
190  NFD_LOG_DEBUG("Applying " << updates.size() << updateString << " to FIB");
191 
192  for (const FibUpdate& update : updates) {
193  NFD_LOG_DEBUG("Sending FIB update: " << update);
194 
195  if (update.action == FibUpdate::ADD_NEXTHOP) {
196  sendAddNextHopUpdate(update, onSuccess, onFailure);
197  }
198  else if (update.action == FibUpdate::REMOVE_NEXTHOP) {
199  sendRemoveNextHopUpdate(update, onSuccess, onFailure);
200  }
201  }
202 }
203 
204 void
205 FibUpdater::sendUpdatesForBatchFaceId(const FibUpdateSuccessCallback& onSuccess,
206  const FibUpdateFailureCallback& onFailure)
207 {
208  if (m_updatesForBatchFaceId.size() > 0) {
209  sendUpdates(m_updatesForBatchFaceId, onSuccess, onFailure);
210  }
211  else {
212  sendUpdatesForNonBatchFaceId(onSuccess, onFailure);
213  }
214 }
215 
216 void
217 FibUpdater::sendUpdatesForNonBatchFaceId(const FibUpdateSuccessCallback& onSuccess,
218  const FibUpdateFailureCallback& onFailure)
219 {
220  if (m_updatesForNonBatchFaceId.size() > 0) {
221  sendUpdates(m_updatesForNonBatchFaceId, onSuccess, onFailure);
222  }
223  else {
224  onSuccess(m_inheritedRoutes);
225  }
226 }
227 
228 void
229 FibUpdater::sendAddNextHopUpdate(const FibUpdate& update,
230  const FibUpdateSuccessCallback& onSuccess,
231  const FibUpdateFailureCallback& onFailure,
232  uint32_t nTimeouts)
233 {
234  m_controller.start<ndn::nfd::FibAddNextHopCommand>(
235  ControlParameters()
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); });
241 }
242 
243 void
244 FibUpdater::sendRemoveNextHopUpdate(const FibUpdate& update,
245  const FibUpdateSuccessCallback& onSuccess,
246  const FibUpdateFailureCallback& onFailure,
247  uint32_t nTimeouts)
248 {
249  m_controller.start<ndn::nfd::FibRemoveNextHopCommand>(
250  ControlParameters()
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); });
255 }
256 
257 void
258 FibUpdater::onUpdateSuccess(const FibUpdate& update,
259  const FibUpdateSuccessCallback& onSuccess,
260  const FibUpdateFailureCallback& onFailure)
261 {
262  if (update.faceId == m_batchFaceId) {
263  m_updatesForBatchFaceId.remove(update);
264 
265  if (m_updatesForBatchFaceId.size() == 0) {
266  sendUpdatesForNonBatchFaceId(onSuccess, onFailure);
267  }
268  }
269  else {
270  m_updatesForNonBatchFaceId.remove(update);
271 
272  if (m_updatesForNonBatchFaceId.size() == 0) {
273  onSuccess(m_inheritedRoutes);
274  }
275  }
276 }
277 
278 void
279 FibUpdater::onUpdateError(const FibUpdate& update,
280  const FibUpdateSuccessCallback& onSuccess,
281  const FibUpdateFailureCallback& onFailure,
282  const ndn::nfd::ControlResponse& response, uint32_t nTimeouts)
283 {
284  uint32_t code = response.getCode();
285  NFD_LOG_DEBUG("Failed to apply " << update <<
286  " (code: " << code << ", error: " << response.getText() << ")");
287 
288  if (code == ndn::nfd::Controller::ERROR_TIMEOUT && nTimeouts < MAX_NUM_TIMEOUTS) {
289  sendAddNextHopUpdate(update, onSuccess, onFailure, ++nTimeouts);
290  }
291  else if (code == ERROR_FACE_NOT_FOUND) {
292  if (update.faceId == m_batchFaceId) {
293  onFailure(code, response.getText());
294  }
295  else {
296  m_updatesForNonBatchFaceId.remove(update);
297 
298  if (m_updatesForNonBatchFaceId.size() == 0) {
299  onSuccess(m_inheritedRoutes);
300  }
301  }
302  }
303  else {
304  NDN_THROW(Error("Non-recoverable error: " + response.getText() + " code: " + to_string(code)));
305  }
306 }
307 
308 void
309 FibUpdater::addFibUpdate(const FibUpdate& update)
310 {
311  FibUpdateList& updates = (update.faceId == m_batchFaceId) ? m_updatesForBatchFaceId :
312  m_updatesForNonBatchFaceId;
313 
314  // If an update with the same name and route already exists, replace it
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;
318  });
319 
320  if (it != updates.end()) {
321  FibUpdate& existingUpdate = *it;
322  existingUpdate.action = update.action;
323  existingUpdate.cost = update.cost;
324  }
325  else {
326  updates.push_back(update);
327  }
328 }
329 
330 void
331 FibUpdater::addInheritedRoutes(const RibEntry& entry, const Rib::RouteSet& routesToAdd)
332 {
333  for (const Route& route : routesToAdd) {
334  // Don't add an ancestor faceId if the namespace has an entry for that faceId
335  if (!entry.hasFaceId(route.faceId)) {
336  // Create a record of the inherited route so it can be added to the RIB later
337  addInheritedRoute(entry.getName(), route);
338 
339  addFibUpdate(FibUpdate::createAddUpdate(entry.getName(), route.faceId, route.cost));
340  }
341  }
342 }
343 
344 void
345 FibUpdater::addInheritedRoutes(const Name& name, const Rib::RouteSet& routesToAdd,
346  const Route& ignore)
347 {
348  for (const Route& route : routesToAdd) {
349  if (route.faceId != ignore.faceId) {
350  // Create a record of the inherited route so it can be added to the RIB later
351  addInheritedRoute(name, route);
352 
353  addFibUpdate(FibUpdate::createAddUpdate(name, route.faceId, route.cost));
354  }
355  }
356 }
357 
358 void
359 FibUpdater::removeInheritedRoutes(const RibEntry& entry, const Rib::Rib::RouteSet& routesToRemove)
360 {
361  for (const Route& route : routesToRemove) {
362  // Only remove if the route has been inherited
363  if (entry.hasInheritedRoute(route)) {
364  removeInheritedRoute(entry.getName(), route);
365  addFibUpdate(FibUpdate::createRemoveUpdate(entry.getName(), route.faceId));
366  }
367  }
368 }
369 
370 void
371 FibUpdater::createFibUpdatesForNewRibEntry(const Name& name, const Route& route,
372  const Rib::RibEntryList& children)
373 {
374  // Create FIB update for new entry
375  addFibUpdate(FibUpdate::createAddUpdate(name, route.faceId, route.cost));
376 
377  // No flags are set
378  if (!route.isChildInherit() && !route.isRibCapture()) {
379  // Add ancestor routes to self
380  addInheritedRoutes(name, m_rib.getAncestorRoutes(name), route);
381  }
382  else if (route.isChildInherit() && route.isRibCapture()) {
383  // Add route to children
384  Rib::RouteSet routesToAdd;
385  routesToAdd.insert(route);
386 
387  // Remove routes blocked by capture and add self to children
388  modifyChildrensInheritedRoutes(children, routesToAdd, m_rib.getAncestorRoutes(name));
389  }
390  else if (route.isChildInherit()) {
391  Rib::RouteSet ancestorRoutes = m_rib.getAncestorRoutes(name);
392 
393  // Add ancestor routes to self
394  addInheritedRoutes(name, ancestorRoutes, route);
395 
396  // If there is an ancestor route which is the same as the new route, replace it
397  // with the new route
398  auto it = ancestorRoutes.find(route);
399 
400  // There is a route that needs to be overwritten, erase and then replace
401  if (it != ancestorRoutes.end()) {
402  ancestorRoutes.erase(it);
403  }
404 
405  // Add new route to ancestor list so it can be added to children
406  ancestorRoutes.insert(route);
407 
408  // Add ancestor routes to children
409  modifyChildrensInheritedRoutes(children, ancestorRoutes, Rib::RouteSet());
410  }
411  else if (route.isRibCapture()) {
412  // Remove routes blocked by capture
413  modifyChildrensInheritedRoutes(children, Rib::RouteSet(), m_rib.getAncestorRoutes(name));
414  }
415 }
416 
417 void
418 FibUpdater::createFibUpdatesForNewRoute(const RibEntry& entry, const Route& route,
419  bool captureWasTurnedOn)
420 {
421  // Only update if the new route has a lower cost than a previously installed route
422  const Route* prevRoute = entry.getRouteWithLowestCostAndChildInheritByFaceId(route.faceId);
423 
424  Rib::RouteSet routesToAdd;
425  if (route.isChildInherit()) {
426  // Add to children if this new route doesn't override a previous lower cost, or
427  // add to children if this new route is lower cost than a previous route.
428  // Less than equal, since entry may find this route
429  if (prevRoute == nullptr || route.cost <= prevRoute->cost) {
430  // Add self to children
431  routesToAdd.insert(route);
432  }
433  }
434 
435  Rib::RouteSet routesToRemove;
436  if (captureWasTurnedOn) {
437  // Capture flag on
438  routesToRemove = m_rib.getAncestorRoutes(entry);
439 
440  // Remove ancestor routes from self
441  removeInheritedRoutes(entry, routesToRemove);
442  }
443 
444  modifyChildrensInheritedRoutes(entry.getChildren(), routesToAdd, routesToRemove);
445 
446  // If another route with same faceId and lower cost exists, don't update.
447  // Must be done last so that add updates replace removal updates
448  // Create FIB update for new entry
449  const Route* other = entry.getRouteWithLowestCostByFaceId(route.faceId);
450 
451  if (other == nullptr || route.cost <= other->cost) {
452  addFibUpdate(FibUpdate::createAddUpdate(entry.getName(), route.faceId, route.cost));
453  }
454 }
455 
456 void
457 FibUpdater::createFibUpdatesForUpdatedRoute(const RibEntry& entry, const Route& route,
458  const Route& existingRoute)
459 {
460  const bool costDidChange = (route.cost != existingRoute.cost);
461 
462  // Look for an installed route with the lowest cost and child inherit set
463  const Route* prevRoute = entry.getRouteWithLowestCostAndChildInheritByFaceId(route.faceId);
464 
465  // No flags changed and cost didn't change, no change in FIB
466  if (route.flags == existingRoute.flags && !costDidChange) {
467  return;
468  }
469 
470  // Cost changed so create update for the entry itself
471  if (costDidChange) {
472  // Create update if this route's cost is lower than other routes
473  if (route.cost <= entry.getRouteWithLowestCostByFaceId(route.faceId)->cost) {
474  // Create FIB update for the updated entry
475  addFibUpdate(FibUpdate::createAddUpdate(entry.getName(), route.faceId, route.cost));
476  }
477  else if (existingRoute.cost < entry.getRouteWithLowestCostByFaceId(route.faceId)->cost) {
478  // Create update if this route used to be the lowest route but is no longer
479  // the lowest cost route.
480  addFibUpdate(FibUpdate::createAddUpdate(entry.getName(), prevRoute->faceId, prevRoute->cost));
481  }
482 
483  // If another route with same faceId and lower cost and ChildInherit exists,
484  // don't update children.
485  if (prevRoute == nullptr || route.cost <= prevRoute->cost) {
486  // If no flags changed but child inheritance is set, need to update children
487  // with new cost
488  if ((route.flags == existingRoute.flags) && route.isChildInherit()) {
489  // Add self to children
490  Rib::RouteSet routesToAdd;
491  routesToAdd.insert(route);
492  modifyChildrensInheritedRoutes(entry.getChildren(), routesToAdd, Rib::RouteSet());
493 
494  return;
495  }
496  }
497  }
498 
499  // Child inherit was turned on
500  if (!existingRoute.isChildInherit() && route.isChildInherit()) {
501  // If another route with same faceId and lower cost and ChildInherit exists,
502  // don't update children.
503  if (prevRoute == nullptr || route.cost <= prevRoute->cost) {
504  // Add self to children
505  Rib::RouteSet routesToAdd;
506  routesToAdd.insert(route);
507  modifyChildrensInheritedRoutes(entry.getChildren(), routesToAdd, Rib::RouteSet());
508  }
509  } // Child inherit was turned off
510  else if (existingRoute.isChildInherit() && !route.isChildInherit()) {
511  // Remove self from children
512  Rib::RouteSet routesToRemove;
513  routesToRemove.insert(route);
514 
515  Rib::RouteSet routesToAdd;
516  // If another route with same faceId and ChildInherit exists, update children with this route.
517  if (prevRoute != nullptr) {
518  routesToAdd.insert(*prevRoute);
519  }
520  else {
521  // Look for an ancestor that was blocked previously
522  const Rib::RouteSet ancestorRoutes = m_rib.getAncestorRoutes(entry);
523  auto it = ancestorRoutes.find(route);
524 
525  // If an ancestor is found, add it to children
526  if (it != ancestorRoutes.end()) {
527  routesToAdd.insert(*it);
528  }
529  }
530 
531  modifyChildrensInheritedRoutes(entry.getChildren(), routesToAdd, routesToRemove);
532  }
533 
534  // Capture was turned on
535  if (!existingRoute.isRibCapture() && route.isRibCapture()) {
536  Rib::RouteSet ancestorRoutes = m_rib.getAncestorRoutes(entry);
537 
538  // Remove ancestor routes from self
539  removeInheritedRoutes(entry, ancestorRoutes);
540 
541  // Remove ancestor routes from children
542  modifyChildrensInheritedRoutes(entry.getChildren(), Rib::RouteSet(), ancestorRoutes);
543  } // Capture was turned off
544  else if (existingRoute.isRibCapture() && !route.isRibCapture()) {
545  Rib::RouteSet ancestorRoutes = m_rib.getAncestorRoutes(entry);
546 
547  // Add ancestor routes to self
548  addInheritedRoutes(entry, ancestorRoutes);
549 
550  // Add ancestor routes to children
551  modifyChildrensInheritedRoutes(entry.getChildren(), ancestorRoutes, Rib::RouteSet());
552  }
553 }
554 
555 void
556 FibUpdater::createFibUpdatesForErasedRoute(const RibEntry& entry, const Route& route,
557  bool captureWasTurnedOff)
558 {
559  addFibUpdate(FibUpdate::createRemoveUpdate(entry.getName(), route.faceId));
560 
561  if (route.isChildInherit() && route.isRibCapture()) {
562  // Remove self from children
563  Rib::RouteSet routesToRemove;
564  routesToRemove.insert(route);
565 
566  // If capture is turned off for the route and another route is installed in the RibEntry,
567  // add ancestors to self
568  Rib::RouteSet routesToAdd;
569  if (captureWasTurnedOff && entry.getNRoutes() != 0) {
570  // Look for an ancestors that were blocked previously
571  routesToAdd = m_rib.getAncestorRoutes(entry);
572 
573  // Add ancestor routes to self
574  addInheritedRoutes(entry, routesToAdd);
575  }
576 
577  modifyChildrensInheritedRoutes(entry.getChildren(), routesToAdd, routesToRemove);
578  }
579  else if (route.isChildInherit()) {
580  // If not blocked by capture, add inherited routes to children
581  Rib::RouteSet routesToAdd;
582  if (!entry.hasCapture()) {
583  routesToAdd = m_rib.getAncestorRoutes(entry);
584  }
585 
586  Rib::RouteSet routesToRemove;
587  routesToRemove.insert(route);
588 
589  // Add ancestor routes to children
590  modifyChildrensInheritedRoutes(entry.getChildren(), routesToAdd, routesToRemove);
591  }
592  else if (route.isRibCapture()) {
593  // If capture is turned off for the route and another route is installed in the RibEntry,
594  // add ancestors to self
595  Rib::RouteSet routesToAdd;
596  if (captureWasTurnedOff && entry.getNRoutes() != 0) {
597  // Look for an ancestors that were blocked previously
598  routesToAdd = m_rib.getAncestorRoutes(entry);
599 
600  // Add ancestor routes to self
601  addInheritedRoutes(entry, routesToAdd);
602  }
603 
604  modifyChildrensInheritedRoutes(entry.getChildren(), routesToAdd, Rib::RouteSet());
605  }
606 
607  // Need to check if the removed route was blocking an inherited route
608  Rib::RouteSet ancestorRoutes = m_rib.getAncestorRoutes(entry);
609 
610  // If the current entry has capture set or is pending removal, don't add inherited route
611  if (!entry.hasCapture() && entry.getNRoutes() != 0) {
612  // If there is an ancestor route which is the same as the erased route, add that route
613  // to the current entry
614  auto it = ancestorRoutes.find(route);
615 
616  if (it != ancestorRoutes.end()) {
617  addInheritedRoute(entry.getName(), *it);
618  addFibUpdate(FibUpdate::createAddUpdate(entry.getName(), it->faceId, it->cost));
619  }
620  }
621 }
622 
623 void
624 FibUpdater::createFibUpdatesForErasedRibEntry(const RibEntry& entry)
625 {
626  for (const Route& route : entry.getInheritedRoutes()) {
627  addFibUpdate(FibUpdate::createRemoveUpdate(entry.getName(), route.faceId));
628  }
629 }
630 
631 void
632 FibUpdater::modifyChildrensInheritedRoutes(const Rib::RibEntryList& children,
633  const Rib::RouteSet& routesToAdd,
634  const Rib::RouteSet& routesToRemove)
635 {
636  for (const auto& child : children) {
637  traverseSubTree(*child, routesToAdd, routesToRemove);
638  }
639 }
640 
641 void
642 FibUpdater::traverseSubTree(const RibEntry& entry, Rib::Rib::RouteSet routesToAdd,
643  Rib::Rib::RouteSet routesToRemove)
644 {
645  // If a route on the namespace has the capture flag set, ignore self and children
646  if (entry.hasCapture()) {
647  return;
648  }
649 
650  // Remove inherited routes from current namespace
651  for (auto removeIt = routesToRemove.begin(); removeIt != routesToRemove.end(); ) {
652  // If a route on the namespace has the same face ID and child inheritance set,
653  // ignore this route
654  if (entry.hasChildInheritOnFaceId(removeIt->faceId)) {
655  removeIt = routesToRemove.erase(removeIt);
656  continue;
657  }
658 
659  // Only remove route if it removes an existing inherited route
660  if (entry.hasInheritedRoute(*removeIt)) {
661  removeInheritedRoute(entry.getName(), *removeIt);
662  addFibUpdate(FibUpdate::createRemoveUpdate(entry.getName(), removeIt->faceId));
663  }
664 
665  ++removeIt;
666  }
667 
668  // Add inherited routes to current namespace
669  for (auto addIt = routesToAdd.begin(); addIt != routesToAdd.end(); ) {
670  // If a route on the namespace has the same face ID and child inherit set, ignore this face
671  if (entry.hasChildInheritOnFaceId(addIt->faceId)) {
672  addIt = routesToAdd.erase(addIt);
673  continue;
674  }
675 
676  // Only add route if it does not override an existing route
677  if (!entry.hasFaceId(addIt->faceId)) {
678  addInheritedRoute(entry.getName(), *addIt);
679  addFibUpdate(FibUpdate::createAddUpdate(entry.getName(), addIt->faceId, addIt->cost));
680  }
681 
682  ++addIt;
683  }
684 
685  modifyChildrensInheritedRoutes(entry.getChildren(), routesToAdd, routesToRemove);
686 }
687 
688 void
689 FibUpdater::addInheritedRoute(const Name& name, const Route& route)
690 {
691  RibUpdate update;
692  update.setAction(RibUpdate::REGISTER)
693  .setName(name)
694  .setRoute(route);
695 
696  m_inheritedRoutes.push_back(update);
697 }
698 
699 void
700 FibUpdater::removeInheritedRoute(const Name& name, const Route& route)
701 {
702  RibUpdate update;
703  update.setAction(RibUpdate::UNREGISTER)
704  .setName(name)
705  .setRoute(route);
706 
707  m_inheritedRoutes.push_back(update);
708 }
709 
710 } // namespace nfd::rib
static FibUpdate createRemoveUpdate(const Name &name, const uint64_t faceId)
Definition: fib-update.cpp:44
static FibUpdate createAddUpdate(const Name &name, const uint64_t faceId, const uint64_t cost)
Definition: fib-update.cpp:31
std::function< void(RibUpdateList inheritedRoutes)> FibUpdateSuccessCallback
Definition: fib-updater.hpp:51
std::list< FibUpdate > FibUpdateList
Definition: fib-updater.hpp:50
FibUpdater(Rib &rib, ndn::nfd::Controller &controller)
Definition: fib-updater.cpp:40
std::function< void(uint32_t code, const std::string &error)> FibUpdateFailureCallback
Definition: fib-updater.hpp:52
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.
Definition: fib-updater.cpp:48
Represents the Routing Information Base.
Definition: rib.hpp:62
void setFibUpdater(FibUpdater *updater)
Definition: rib.cpp:48
const_iterator end() const
Definition: rib.hpp:87
std::list< shared_ptr< RibEntry > > RibEntryList
Definition: rib.hpp:64
const_iterator find(const Name &prefix) const
Definition: rib.cpp:54
shared_ptr< RibEntry > findParent(const Name &prefix) const
Definition: rib.cpp:209
Represents a collection of RibUpdates to be applied to a single FaceId.
Represents a route that will be added to or removed from a namespace.
Definition: rib-update.hpp:39
@ REMOVE_FACE
An update triggered by a face destruction notification.
Definition: rib-update.hpp:48
#define NFD_LOG_INIT(name)
Definition: logger.hpp:31
#define NFD_LOG_DEBUG
Definition: logger.hpp:38
constexpr uint32_t ERROR_FACE_NOT_FOUND
Definition: fib-updater.cpp:38
constexpr int MAX_NUM_TIMEOUTS
Definition: fib-updater.cpp:37