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-2024, 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  NFD_LOG_DEBUG("Applying " << updates.size() << " FIB update(s)");
190 
191  for (const FibUpdate& update : updates) {
192  NFD_LOG_DEBUG("Sending " << update);
193 
194  if (update.action == FibUpdate::ADD_NEXTHOP) {
195  sendAddNextHopUpdate(update, onSuccess, onFailure);
196  }
197  else if (update.action == FibUpdate::REMOVE_NEXTHOP) {
198  sendRemoveNextHopUpdate(update, onSuccess, onFailure);
199  }
200  }
201 }
202 
203 void
204 FibUpdater::sendUpdatesForBatchFaceId(const FibUpdateSuccessCallback& onSuccess,
205  const FibUpdateFailureCallback& onFailure)
206 {
207  if (m_updatesForBatchFaceId.size() > 0) {
208  sendUpdates(m_updatesForBatchFaceId, onSuccess, onFailure);
209  }
210  else {
211  sendUpdatesForNonBatchFaceId(onSuccess, onFailure);
212  }
213 }
214 
215 void
216 FibUpdater::sendUpdatesForNonBatchFaceId(const FibUpdateSuccessCallback& onSuccess,
217  const FibUpdateFailureCallback& onFailure)
218 {
219  if (m_updatesForNonBatchFaceId.size() > 0) {
220  sendUpdates(m_updatesForNonBatchFaceId, onSuccess, onFailure);
221  }
222  else {
223  onSuccess(m_inheritedRoutes);
224  }
225 }
226 
227 void
228 FibUpdater::sendAddNextHopUpdate(const FibUpdate& update,
229  const FibUpdateSuccessCallback& onSuccess,
230  const FibUpdateFailureCallback& onFailure,
231  uint32_t nTimeouts)
232 {
233  m_controller.start<ndn::nfd::FibAddNextHopCommand>(
234  ControlParameters()
235  .setName(update.name)
236  .setFaceId(update.faceId)
237  .setCost(update.cost),
238  [=] (const auto&) { onUpdateSuccess(update, onSuccess, onFailure); },
239  [=] (const auto& resp) { onUpdateError(update, onSuccess, onFailure, resp, nTimeouts); });
240 }
241 
242 void
243 FibUpdater::sendRemoveNextHopUpdate(const FibUpdate& update,
244  const FibUpdateSuccessCallback& onSuccess,
245  const FibUpdateFailureCallback& onFailure,
246  uint32_t nTimeouts)
247 {
248  m_controller.start<ndn::nfd::FibRemoveNextHopCommand>(
249  ControlParameters()
250  .setName(update.name)
251  .setFaceId(update.faceId),
252  [=] (const auto&) { onUpdateSuccess(update, onSuccess, onFailure); },
253  [=] (const auto& resp) { onUpdateError(update, onSuccess, onFailure, resp, nTimeouts); });
254 }
255 
256 void
257 FibUpdater::onUpdateSuccess(const FibUpdate& update,
258  const FibUpdateSuccessCallback& onSuccess,
259  const FibUpdateFailureCallback& onFailure)
260 {
261  if (update.faceId == m_batchFaceId) {
262  m_updatesForBatchFaceId.remove(update);
263 
264  if (m_updatesForBatchFaceId.size() == 0) {
265  sendUpdatesForNonBatchFaceId(onSuccess, onFailure);
266  }
267  }
268  else {
269  m_updatesForNonBatchFaceId.remove(update);
270 
271  if (m_updatesForNonBatchFaceId.size() == 0) {
272  onSuccess(m_inheritedRoutes);
273  }
274  }
275 }
276 
277 void
278 FibUpdater::onUpdateError(const FibUpdate& update,
279  const FibUpdateSuccessCallback& onSuccess,
280  const FibUpdateFailureCallback& onFailure,
281  const ndn::nfd::ControlResponse& response, uint32_t nTimeouts)
282 {
283  uint32_t code = response.getCode();
284  NFD_LOG_DEBUG("Failed to apply " << update <<
285  " [code: " << code << ", error: " << response.getText() << "]");
286 
287  if (code == ndn::nfd::Controller::ERROR_TIMEOUT && nTimeouts < MAX_NUM_TIMEOUTS) {
288  sendAddNextHopUpdate(update, onSuccess, onFailure, ++nTimeouts);
289  }
290  else if (code == ERROR_FACE_NOT_FOUND) {
291  if (update.faceId == m_batchFaceId) {
292  onFailure(code, response.getText());
293  }
294  else {
295  m_updatesForNonBatchFaceId.remove(update);
296 
297  if (m_updatesForNonBatchFaceId.size() == 0) {
298  onSuccess(m_inheritedRoutes);
299  }
300  }
301  }
302  else {
303  NDN_THROW(Error("Non-recoverable error " + std::to_string(code) + ": " + response.getText()));
304  }
305 }
306 
307 void
308 FibUpdater::addFibUpdate(const FibUpdate& update)
309 {
310  FibUpdateList& updates = (update.faceId == m_batchFaceId) ? m_updatesForBatchFaceId :
311  m_updatesForNonBatchFaceId;
312 
313  // If an update with the same name and route already exists, replace it
314  auto it = std::find_if(updates.begin(), updates.end(),
315  [&update] (const FibUpdate& other) {
316  return update.name == other.name && update.faceId == other.faceId;
317  });
318 
319  if (it != updates.end()) {
320  FibUpdate& existingUpdate = *it;
321  existingUpdate.action = update.action;
322  existingUpdate.cost = update.cost;
323  }
324  else {
325  updates.push_back(update);
326  }
327 }
328 
329 void
330 FibUpdater::addInheritedRoutes(const RibEntry& entry, const Rib::RouteSet& routesToAdd)
331 {
332  for (const Route& route : routesToAdd) {
333  // Don't add an ancestor faceId if the namespace has an entry for that faceId
334  if (!entry.hasFaceId(route.faceId)) {
335  // Create a record of the inherited route so it can be added to the RIB later
336  addInheritedRoute(entry.getName(), route);
337 
338  addFibUpdate(FibUpdate::createAddUpdate(entry.getName(), route.faceId, route.cost));
339  }
340  }
341 }
342 
343 void
344 FibUpdater::addInheritedRoutes(const Name& name, const Rib::RouteSet& routesToAdd,
345  const Route& ignore)
346 {
347  for (const Route& route : routesToAdd) {
348  if (route.faceId != ignore.faceId) {
349  // Create a record of the inherited route so it can be added to the RIB later
350  addInheritedRoute(name, route);
351 
352  addFibUpdate(FibUpdate::createAddUpdate(name, route.faceId, route.cost));
353  }
354  }
355 }
356 
357 void
358 FibUpdater::removeInheritedRoutes(const RibEntry& entry, const Rib::Rib::RouteSet& routesToRemove)
359 {
360  for (const Route& route : routesToRemove) {
361  // Only remove if the route has been inherited
362  if (entry.hasInheritedRoute(route)) {
363  removeInheritedRoute(entry.getName(), route);
364  addFibUpdate(FibUpdate::createRemoveUpdate(entry.getName(), route.faceId));
365  }
366  }
367 }
368 
369 void
370 FibUpdater::createFibUpdatesForNewRibEntry(const Name& name, const Route& route,
371  const Rib::RibEntryList& children)
372 {
373  // Create FIB update for new entry
374  addFibUpdate(FibUpdate::createAddUpdate(name, route.faceId, route.cost));
375 
376  // No flags are set
377  if (!route.isChildInherit() && !route.isRibCapture()) {
378  // Add ancestor routes to self
379  addInheritedRoutes(name, m_rib.getAncestorRoutes(name), route);
380  }
381  else if (route.isChildInherit() && route.isRibCapture()) {
382  // Add route to children
383  Rib::RouteSet routesToAdd;
384  routesToAdd.insert(route);
385 
386  // Remove routes blocked by capture and add self to children
387  modifyChildrensInheritedRoutes(children, routesToAdd, m_rib.getAncestorRoutes(name));
388  }
389  else if (route.isChildInherit()) {
390  Rib::RouteSet ancestorRoutes = m_rib.getAncestorRoutes(name);
391 
392  // Add ancestor routes to self
393  addInheritedRoutes(name, ancestorRoutes, route);
394 
395  // If there is an ancestor route which is the same as the new route, replace it
396  // with the new route
397  auto it = ancestorRoutes.find(route);
398 
399  // There is a route that needs to be overwritten, erase and then replace
400  if (it != ancestorRoutes.end()) {
401  ancestorRoutes.erase(it);
402  }
403 
404  // Add new route to ancestor list so it can be added to children
405  ancestorRoutes.insert(route);
406 
407  // Add ancestor routes to children
408  modifyChildrensInheritedRoutes(children, ancestorRoutes, Rib::RouteSet());
409  }
410  else if (route.isRibCapture()) {
411  // Remove routes blocked by capture
412  modifyChildrensInheritedRoutes(children, Rib::RouteSet(), m_rib.getAncestorRoutes(name));
413  }
414 }
415 
416 void
417 FibUpdater::createFibUpdatesForNewRoute(const RibEntry& entry, const Route& route,
418  bool captureWasTurnedOn)
419 {
420  // Only update if the new route has a lower cost than a previously installed route
421  const Route* prevRoute = entry.getRouteWithLowestCostAndChildInheritByFaceId(route.faceId);
422 
423  Rib::RouteSet routesToAdd;
424  if (route.isChildInherit()) {
425  // Add to children if this new route doesn't override a previous lower cost, or
426  // add to children if this new route is lower cost than a previous route.
427  // Less than equal, since entry may find this route
428  if (prevRoute == nullptr || route.cost <= prevRoute->cost) {
429  // Add self to children
430  routesToAdd.insert(route);
431  }
432  }
433 
434  Rib::RouteSet routesToRemove;
435  if (captureWasTurnedOn) {
436  // Capture flag on
437  routesToRemove = m_rib.getAncestorRoutes(entry);
438 
439  // Remove ancestor routes from self
440  removeInheritedRoutes(entry, routesToRemove);
441  }
442 
443  modifyChildrensInheritedRoutes(entry.getChildren(), routesToAdd, routesToRemove);
444 
445  // If another route with same faceId and lower cost exists, don't update.
446  // Must be done last so that add updates replace removal updates
447  // Create FIB update for new entry
448  const Route* other = entry.getRouteWithLowestCostByFaceId(route.faceId);
449 
450  if (other == nullptr || route.cost <= other->cost) {
451  addFibUpdate(FibUpdate::createAddUpdate(entry.getName(), route.faceId, route.cost));
452  }
453 }
454 
455 void
456 FibUpdater::createFibUpdatesForUpdatedRoute(const RibEntry& entry, const Route& route,
457  const Route& existingRoute)
458 {
459  const bool costDidChange = (route.cost != existingRoute.cost);
460 
461  // Look for an installed route with the lowest cost and child inherit set
462  const Route* prevRoute = entry.getRouteWithLowestCostAndChildInheritByFaceId(route.faceId);
463 
464  // No flags changed and cost didn't change, no change in FIB
465  if (route.flags == existingRoute.flags && !costDidChange) {
466  return;
467  }
468 
469  // Cost changed so create update for the entry itself
470  if (costDidChange) {
471  // Create update if this route's cost is lower than other routes
472  if (route.cost <= entry.getRouteWithLowestCostByFaceId(route.faceId)->cost) {
473  // Create FIB update for the updated entry
474  addFibUpdate(FibUpdate::createAddUpdate(entry.getName(), route.faceId, route.cost));
475  }
476  else if (existingRoute.cost < entry.getRouteWithLowestCostByFaceId(route.faceId)->cost) {
477  // Create update if this route used to be the lowest route but is no longer
478  // the lowest cost route.
479  addFibUpdate(FibUpdate::createAddUpdate(entry.getName(), prevRoute->faceId, prevRoute->cost));
480  }
481 
482  // If another route with same faceId and lower cost and ChildInherit exists,
483  // don't update children.
484  if (prevRoute == nullptr || route.cost <= prevRoute->cost) {
485  // If no flags changed but child inheritance is set, need to update children
486  // with new cost
487  if ((route.flags == existingRoute.flags) && route.isChildInherit()) {
488  // Add self to children
489  Rib::RouteSet routesToAdd;
490  routesToAdd.insert(route);
491  modifyChildrensInheritedRoutes(entry.getChildren(), routesToAdd, Rib::RouteSet());
492 
493  return;
494  }
495  }
496  }
497 
498  // Child inherit was turned on
499  if (!existingRoute.isChildInherit() && route.isChildInherit()) {
500  // If another route with same faceId and lower cost and ChildInherit exists,
501  // don't update children.
502  if (prevRoute == nullptr || route.cost <= prevRoute->cost) {
503  // Add self to children
504  Rib::RouteSet routesToAdd;
505  routesToAdd.insert(route);
506  modifyChildrensInheritedRoutes(entry.getChildren(), routesToAdd, Rib::RouteSet());
507  }
508  } // Child inherit was turned off
509  else if (existingRoute.isChildInherit() && !route.isChildInherit()) {
510  // Remove self from children
511  Rib::RouteSet routesToRemove;
512  routesToRemove.insert(route);
513 
514  Rib::RouteSet routesToAdd;
515  // If another route with same faceId and ChildInherit exists, update children with this route.
516  if (prevRoute != nullptr) {
517  routesToAdd.insert(*prevRoute);
518  }
519  else {
520  // Look for an ancestor that was blocked previously
521  const Rib::RouteSet ancestorRoutes = m_rib.getAncestorRoutes(entry);
522  auto it = ancestorRoutes.find(route);
523 
524  // If an ancestor is found, add it to children
525  if (it != ancestorRoutes.end()) {
526  routesToAdd.insert(*it);
527  }
528  }
529 
530  modifyChildrensInheritedRoutes(entry.getChildren(), routesToAdd, routesToRemove);
531  }
532 
533  // Capture was turned on
534  if (!existingRoute.isRibCapture() && route.isRibCapture()) {
535  Rib::RouteSet ancestorRoutes = m_rib.getAncestorRoutes(entry);
536 
537  // Remove ancestor routes from self
538  removeInheritedRoutes(entry, ancestorRoutes);
539 
540  // Remove ancestor routes from children
541  modifyChildrensInheritedRoutes(entry.getChildren(), Rib::RouteSet(), ancestorRoutes);
542  } // Capture was turned off
543  else if (existingRoute.isRibCapture() && !route.isRibCapture()) {
544  Rib::RouteSet ancestorRoutes = m_rib.getAncestorRoutes(entry);
545 
546  // Add ancestor routes to self
547  addInheritedRoutes(entry, ancestorRoutes);
548 
549  // Add ancestor routes to children
550  modifyChildrensInheritedRoutes(entry.getChildren(), ancestorRoutes, Rib::RouteSet());
551  }
552 }
553 
554 void
555 FibUpdater::createFibUpdatesForErasedRoute(const RibEntry& entry, const Route& route,
556  bool captureWasTurnedOff)
557 {
558  addFibUpdate(FibUpdate::createRemoveUpdate(entry.getName(), route.faceId));
559 
560  if (route.isChildInherit() && route.isRibCapture()) {
561  // Remove self from children
562  Rib::RouteSet routesToRemove;
563  routesToRemove.insert(route);
564 
565  // If capture is turned off for the route and another route is installed in the RibEntry,
566  // add ancestors to self
567  Rib::RouteSet routesToAdd;
568  if (captureWasTurnedOff && entry.getNRoutes() != 0) {
569  // Look for an ancestors that were blocked previously
570  routesToAdd = m_rib.getAncestorRoutes(entry);
571 
572  // Add ancestor routes to self
573  addInheritedRoutes(entry, routesToAdd);
574  }
575 
576  modifyChildrensInheritedRoutes(entry.getChildren(), routesToAdd, routesToRemove);
577  }
578  else if (route.isChildInherit()) {
579  // If not blocked by capture, add inherited routes to children
580  Rib::RouteSet routesToAdd;
581  if (!entry.hasCapture()) {
582  routesToAdd = m_rib.getAncestorRoutes(entry);
583  }
584 
585  Rib::RouteSet routesToRemove;
586  routesToRemove.insert(route);
587 
588  // Add ancestor routes to children
589  modifyChildrensInheritedRoutes(entry.getChildren(), routesToAdd, routesToRemove);
590  }
591  else if (route.isRibCapture()) {
592  // If capture is turned off for the route and another route is installed in the RibEntry,
593  // add ancestors to self
594  Rib::RouteSet routesToAdd;
595  if (captureWasTurnedOff && entry.getNRoutes() != 0) {
596  // Look for an ancestors that were blocked previously
597  routesToAdd = m_rib.getAncestorRoutes(entry);
598 
599  // Add ancestor routes to self
600  addInheritedRoutes(entry, routesToAdd);
601  }
602 
603  modifyChildrensInheritedRoutes(entry.getChildren(), routesToAdd, Rib::RouteSet());
604  }
605 
606  // Need to check if the removed route was blocking an inherited route
607  Rib::RouteSet ancestorRoutes = m_rib.getAncestorRoutes(entry);
608 
609  // If the current entry has capture set or is pending removal, don't add inherited route
610  if (!entry.hasCapture() && entry.getNRoutes() != 0) {
611  // If there is an ancestor route which is the same as the erased route, add that route
612  // to the current entry
613  auto it = ancestorRoutes.find(route);
614 
615  if (it != ancestorRoutes.end()) {
616  addInheritedRoute(entry.getName(), *it);
617  addFibUpdate(FibUpdate::createAddUpdate(entry.getName(), it->faceId, it->cost));
618  }
619  }
620 }
621 
622 void
623 FibUpdater::createFibUpdatesForErasedRibEntry(const RibEntry& entry)
624 {
625  for (const Route& route : entry.getInheritedRoutes()) {
626  addFibUpdate(FibUpdate::createRemoveUpdate(entry.getName(), route.faceId));
627  }
628 }
629 
630 void
631 FibUpdater::modifyChildrensInheritedRoutes(const Rib::RibEntryList& children,
632  const Rib::RouteSet& routesToAdd,
633  const Rib::RouteSet& routesToRemove)
634 {
635  for (const auto& child : children) {
636  traverseSubTree(*child, routesToAdd, routesToRemove);
637  }
638 }
639 
640 void
641 FibUpdater::traverseSubTree(const RibEntry& entry, Rib::Rib::RouteSet routesToAdd,
642  Rib::Rib::RouteSet routesToRemove)
643 {
644  // If a route on the namespace has the capture flag set, ignore self and children
645  if (entry.hasCapture()) {
646  return;
647  }
648 
649  // Remove inherited routes from current namespace
650  for (auto removeIt = routesToRemove.begin(); removeIt != routesToRemove.end(); ) {
651  // If a route on the namespace has the same face ID and child inheritance set,
652  // ignore this route
653  if (entry.hasChildInheritOnFaceId(removeIt->faceId)) {
654  removeIt = routesToRemove.erase(removeIt);
655  continue;
656  }
657 
658  // Only remove route if it removes an existing inherited route
659  if (entry.hasInheritedRoute(*removeIt)) {
660  removeInheritedRoute(entry.getName(), *removeIt);
661  addFibUpdate(FibUpdate::createRemoveUpdate(entry.getName(), removeIt->faceId));
662  }
663 
664  ++removeIt;
665  }
666 
667  // Add inherited routes to current namespace
668  for (auto addIt = routesToAdd.begin(); addIt != routesToAdd.end(); ) {
669  // If a route on the namespace has the same face ID and child inherit set, ignore this face
670  if (entry.hasChildInheritOnFaceId(addIt->faceId)) {
671  addIt = routesToAdd.erase(addIt);
672  continue;
673  }
674 
675  // Only add route if it does not override an existing route
676  if (!entry.hasFaceId(addIt->faceId)) {
677  addInheritedRoute(entry.getName(), *addIt);
678  addFibUpdate(FibUpdate::createAddUpdate(entry.getName(), addIt->faceId, addIt->cost));
679  }
680 
681  ++addIt;
682  }
683 
684  modifyChildrensInheritedRoutes(entry.getChildren(), routesToAdd, routesToRemove);
685 }
686 
687 void
688 FibUpdater::addInheritedRoute(const Name& name, const Route& route)
689 {
690  RibUpdate update;
691  update.setAction(RibUpdate::REGISTER)
692  .setName(name)
693  .setRoute(route);
694 
695  m_inheritedRoutes.push_back(update);
696 }
697 
698 void
699 FibUpdater::removeInheritedRoute(const Name& name, const Route& route)
700 {
701  RibUpdate update;
702  update.setAction(RibUpdate::UNREGISTER)
703  .setName(name)
704  .setRoute(route);
705 
706  m_inheritedRoutes.push_back(update);
707 }
708 
709 } // namespace nfd::rib
static FibUpdate createRemoveUpdate(const Name &name, uint64_t faceId)
Definition: fib-update.cpp:42
static FibUpdate createAddUpdate(const Name &name, uint64_t faceId, 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:70
void setFibUpdater(FibUpdater *updater)
Definition: rib.cpp:41
const_iterator end() const
Definition: rib.hpp:95
std::list< shared_ptr< RibEntry > > RibEntryList
Definition: rib.hpp:72
const_iterator find(const Name &prefix) const
Definition: rib.cpp:47
shared_ptr< RibEntry > findParent(const Name &prefix) const
Definition: rib.cpp:202
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