NS-3 based Named Data Networking (NDN) simulator
ndnSIM 2.3: NDN, CCN, CCNx, content centric networks
API Documentation
rib.cpp
Go to the documentation of this file.
1 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
26 #include "rib.hpp"
27 
28 #include "fib-updater.hpp"
29 #include "core/logger.hpp"
30 
31 NFD_LOG_INIT("Rib");
32 
33 namespace nfd {
34 namespace rib {
35 
36 static inline bool
37 sortRoutes(const Route& lhs, const Route& rhs)
38 {
39  return lhs.faceId < rhs.faceId;
40 }
41 
43  : m_nItems(0)
44  , m_isUpdateInProgress(false)
45 {
46 }
47 
49 {
50 }
51 
52 void
54 {
55  m_fibUpdater = updater;
56 }
57 
59 Rib::find(const Name& prefix) const
60 {
61  return m_rib.find(prefix);
62 }
63 
64 Route*
65 Rib::find(const Name& prefix, const Route& route) const
66 {
67  RibTable::const_iterator ribIt = m_rib.find(prefix);
68 
69  // Name prefix exists
70  if (ribIt != m_rib.end()) {
71  shared_ptr<RibEntry> entry = ribIt->second;
72 
73  RibEntry::iterator routeIt = entry->findRoute(route);
74 
75  if (routeIt != entry->end()) {
76  return &((*routeIt));
77  }
78  }
79 
80  return nullptr;
81 }
82 
83 void
84 Rib::insert(const Name& prefix, const Route& route)
85 {
86  RibTable::iterator ribIt = m_rib.find(prefix);
87 
88  // Name prefix exists
89  if (ribIt != m_rib.end()) {
90  shared_ptr<RibEntry> entry(ribIt->second);
91 
92  RibEntry::iterator entryIt;
93  bool didInsert = false;
94  std::tie(entryIt, didInsert) = entry->insertRoute(route);
95 
96  if (didInsert) {
97  // The route was new and we successfully inserted it.
98  m_nItems++;
99 
100  afterAddRoute(RibRouteRef{entry, entryIt});
101 
102  // Register with face lookup table
103  m_faceMap[route.faceId].push_back(entry);
104  }
105  else {
106  // Route exists, update fields
107  // First cancel old scheduled event, if any, then set the EventId to new one
108  if (static_cast<bool>(entryIt->getExpirationEvent())) {
109  NFD_LOG_TRACE("Cancelling expiration event for " << entry->getName() << " "
110  << (*entryIt));
111  scheduler::cancel(entryIt->getExpirationEvent());
112  }
113 
114  // No checks are required here as the iterator needs to be updated in all cases.
115  entryIt->setExpirationEvent(route.getExpirationEvent());
116 
117  entryIt->flags = route.flags;
118  entryIt->cost = route.cost;
119  entryIt->expires = route.expires;
120  }
121  }
122  else {
123  // New name prefix
124  shared_ptr<RibEntry> entry = make_shared<RibEntry>();
125 
126  m_rib[prefix] = entry;
127  m_nItems++;
128 
129  entry->setName(prefix);
130  RibEntry::iterator routeIt = entry->insertRoute(route).first;
131 
132  // Find prefix's parent
133  shared_ptr<RibEntry> parent = findParent(prefix);
134 
135  // Add self to parent's children
136  if (parent != nullptr) {
137  parent->addChild(entry);
138  }
139 
140  RibEntryList children = findDescendants(prefix);
141 
142  for (const auto& child : children) {
143  if (child->getParent() == parent) {
144  // Remove child from parent and inherit parent's child
145  if (parent != nullptr) {
146  parent->removeChild(child);
147  }
148 
149  entry->addChild(child);
150  }
151  }
152 
153  // Register with face lookup table
154  m_faceMap[route.faceId].push_back(entry);
155 
156  // do something after inserting an entry
157  afterInsertEntry(prefix);
158  afterAddRoute(RibRouteRef{entry, routeIt});
159  }
160 }
161 
162 void
163 Rib::erase(const Name& prefix, const Route& route)
164 {
165  RibTable::iterator ribIt = m_rib.find(prefix);
166 
167  // Name prefix exists
168  if (ribIt != m_rib.end()) {
169  shared_ptr<RibEntry> entry = ribIt->second;
170  RibEntry::iterator routeIt = entry->findRoute(route);
171 
172  if (routeIt != entry->end()) {
173  beforeRemoveRoute(RibRouteRef{entry, routeIt});
174 
175  auto faceId = route.faceId;
176  entry->eraseRoute(routeIt);
177  m_nItems--;
178 
179  // If this RibEntry no longer has this faceId, unregister from face lookup table
180  if (!entry->hasFaceId(faceId)) {
181  m_faceMap[faceId].remove(entry);
182  }
183 
184  // If a RibEntry's route list is empty, remove it from the tree
185  if (entry->getRoutes().empty()) {
186  eraseEntry(ribIt);
187  }
188  }
189  }
190 }
191 
192 void
193 Rib::onRouteExpiration(const Name& prefix, const Route& route)
194 {
195  NFD_LOG_DEBUG(route << " for " << prefix << " has expired");
196 
197  RibUpdate update;
199  .setName(prefix)
200  .setRoute(route);
201 
202  beginApplyUpdate(update, nullptr, nullptr);
203 }
204 
205 shared_ptr<RibEntry>
206 Rib::findParent(const Name& prefix) const
207 {
208  for (int i = prefix.size() - 1; i >= 0; i--) {
209  RibTable::const_iterator it = m_rib.find(prefix.getPrefix(i));
210 
211  if (it != m_rib.end()) {
212  return (it->second);
213  }
214  }
215 
216  return shared_ptr<RibEntry>();
217 }
218 
219 std::list<shared_ptr<RibEntry> >
220 Rib::findDescendants(const Name& prefix) const
221 {
222  std::list<shared_ptr<RibEntry> > children;
223 
224  RibTable::const_iterator it = m_rib.find(prefix);
225 
226  if (it != m_rib.end()) {
227  ++it;
228  for (; it != m_rib.end(); ++it) {
229  if (prefix.isPrefixOf(it->first)) {
230  children.push_back((it->second));
231  }
232  else {
233  break;
234  }
235  }
236  }
237 
238  return children;
239 }
240 
241 std::list<shared_ptr<RibEntry>>
243 {
244  std::list<shared_ptr<RibEntry>> children;
245 
246  for (std::pair<Name, shared_ptr<RibEntry>> pair : m_rib) {
247  if (prefix.isPrefixOf(pair.first)) {
248  children.push_back(pair.second);
249  }
250  }
251 
252  return children;
253 }
254 
256 Rib::eraseEntry(RibTable::iterator it)
257 {
258  // Entry does not exist
259  if (it == m_rib.end()) {
260  return m_rib.end();
261  }
262 
263  shared_ptr<RibEntry> entry(it->second);
264 
265  shared_ptr<RibEntry> parent = entry->getParent();
266 
267  // Remove self from parent's children
268  if (parent != nullptr) {
269  parent->removeChild(entry);
270  }
271 
272  for (auto childIt = entry->getChildren().begin(); childIt != entry->getChildren().end(); ) {
273  shared_ptr<RibEntry> child = *childIt;
274 
275  // Advance iterator so it is not invalidated by removal
276  ++childIt;
277 
278  // Remove children from self
279  entry->removeChild(child);
280 
281  // Update parent's children
282  if (parent != nullptr) {
283  parent->addChild(child);
284  }
285  }
286 
287  RibTable::iterator nextIt = m_rib.erase(it);
288 
289  // do something after erasing an entry.
290  afterEraseEntry(entry->getName());
291 
292  return nextIt;
293 }
294 
296 Rib::getAncestorRoutes(const RibEntry& entry) const
297 {
298  RouteSet ancestorRoutes(&sortRoutes);
299 
300  shared_ptr<RibEntry> parent = entry.getParent();
301 
302  while (parent != nullptr) {
303  for (const Route& route : parent->getRoutes()) {
304  if (route.isChildInherit()) {
305  ancestorRoutes.insert(route);
306  }
307  }
308 
309  if (parent->hasCapture()) {
310  break;
311  }
312 
313  parent = parent->getParent();
314  }
315 
316  return ancestorRoutes;
317 }
318 
320 Rib::getAncestorRoutes(const Name& name) const
321 {
322  RouteSet ancestorRoutes(&sortRoutes);
323 
324  shared_ptr<RibEntry> parent = findParent(name);
325 
326  while (parent != nullptr) {
327  for (const Route& route : parent->getRoutes()) {
328  if (route.isChildInherit()) {
329  ancestorRoutes.insert(route);
330  }
331  }
332 
333  if (parent->hasCapture()) {
334  break;
335  }
336 
337  parent = parent->getParent();
338  }
339 
340  return ancestorRoutes;
341 }
342 
343 void
345  const Rib::UpdateSuccessCallback& onSuccess,
346  const Rib::UpdateFailureCallback& onFailure)
347 {
348  BOOST_ASSERT(m_fibUpdater != nullptr);
349 
350  addUpdateToQueue(update, onSuccess, onFailure);
351 
352  sendBatchFromQueue();
353 }
354 
355 void
356 Rib::beginRemoveFace(uint64_t faceId)
357 {
358  for (const auto& nameAndRoute : findRoutesWithFaceId(faceId)) {
359  RibUpdate update;
361  .setName(nameAndRoute.first)
362  .setRoute(nameAndRoute.second);
363 
364  addUpdateToQueue(update, nullptr, nullptr);
365  }
366 
367  sendBatchFromQueue();
368 }
369 
370 void
371 Rib::addUpdateToQueue(const RibUpdate& update,
372  const Rib::UpdateSuccessCallback& onSuccess,
373  const Rib::UpdateFailureCallback& onFailure)
374 {
375  RibUpdateBatch batch(update.getRoute().faceId);
376  batch.add(update);
377 
378  UpdateQueueItem item{batch, onSuccess, onFailure};
379  m_updateBatches.push_back(std::move(item));
380 }
381 
382 void
383 Rib::sendBatchFromQueue()
384 {
385  if (m_updateBatches.empty() || m_isUpdateInProgress) {
386  return;
387  }
388 
389  m_isUpdateInProgress = true;
390 
391  UpdateQueueItem item = std::move(m_updateBatches.front());
392  m_updateBatches.pop_front();
393 
394  RibUpdateBatch& batch = item.batch;
395 
396  // Until task #1698, each RibUpdateBatch contains exactly one RIB update
397  BOOST_ASSERT(batch.size() == 1);
398 
399  const Rib::UpdateSuccessCallback& managerSuccessCallback = item.managerSuccessCallback;
400  const Rib::UpdateFailureCallback& managerFailureCallback = item.managerFailureCallback;
401 
402  m_fibUpdater->computeAndSendFibUpdates(batch,
403  bind(&Rib::onFibUpdateSuccess, this,
404  batch, _1, managerSuccessCallback),
405  bind(&Rib::onFibUpdateFailure, this,
406  managerFailureCallback, _1, _2));
407 
408  if (m_onSendBatchFromQueue != nullptr) {
409  m_onSendBatchFromQueue(batch);
410  }
411 }
412 
413 void
415  const RibUpdateList& inheritedRoutes,
416  const Rib::UpdateSuccessCallback& onSuccess)
417 {
418  for (const RibUpdate& update : batch) {
419  switch (update.getAction()) {
420  case RibUpdate::REGISTER:
421  insert(update.getName(), update.getRoute());
422  break;
425  erase(update.getName(), update.getRoute());
426  break;
427  }
428  }
429 
430  // Add and remove precalculated inherited routes to RibEntries
431  modifyInheritedRoutes(inheritedRoutes);
432 
433  m_isUpdateInProgress = false;
434 
435  if (onSuccess != nullptr) {
436  onSuccess();
437  }
438 
439  // Try to advance the batch queue
440  sendBatchFromQueue();
441 }
442 
443 void
445  uint32_t code, const std::string& error)
446 {
447  m_isUpdateInProgress = false;
448 
449  if (onFailure != nullptr) {
450  onFailure(code, error);
451  }
452 
453  // Try to advance the batch queue
454  sendBatchFromQueue();
455 }
456 
457 void
458 Rib::modifyInheritedRoutes(const RibUpdateList& inheritedRoutes)
459 {
460  for (const RibUpdate& update : inheritedRoutes) {
461  RibTable::iterator ribIt = m_rib.find(update.getName());
462 
463  BOOST_ASSERT(ribIt != m_rib.end());
464  shared_ptr<RibEntry> entry(ribIt->second);
465 
466  switch (update.getAction()) {
467  case RibUpdate::REGISTER:
468  entry->addInheritedRoute(update.getRoute());
469  break;
471  entry->removeInheritedRoute(update.getRoute());
472  break;
474  break;
475  }
476  }
477 }
478 
479 std::list<Rib::NameAndRoute>
480 Rib::findRoutesWithFaceId(uint64_t faceId)
481 {
482  std::list<NameAndRoute> routes;
483 
484  FaceLookupTable::iterator lookupIt = m_faceMap.find(faceId);
485 
486  // No RIB entries have this face
487  if (lookupIt == m_faceMap.end()) {
488  return routes;
489  }
490 
491  RibEntryList& ribEntries = lookupIt->second;
492 
493  // For each RIB entry that has faceId
494  for (const shared_ptr<RibEntry>& entry : ribEntries) {
495  // Find the routes in the entry
496  for (const Route& route : *entry) {
497  if (route.faceId == faceId) {
498  routes.push_back(NameAndRoute(entry->getName(), route));
499  }
500  }
501  }
502 
503  return routes;
504 }
505 
506 std::ostream&
507 operator<<(std::ostream& os, const Rib& rib)
508 {
509  for (const auto& item : rib) {
510  os << item.second << "\n";
511  }
512 
513  return os;
514 }
515 
516 } // namespace rib
517 } // namespace nfd
RibUpdate & setRoute(const Route &route)
Definition: rib-update.hpp:107
std::list< shared_ptr< RibEntry > > findDescendants(const Name &prefix) const
finds namespaces under the passed prefix
Definition: rib.cpp:220
PartialName getPrefix(ssize_t nComponents) const
Extract a prefix (PartialName) of the name, containing first nComponents components.
Definition: name.hpp:241
shared_ptr< RibEntry > getParent() const
Definition: rib-entry.hpp:217
represents the Routing Information Base
Definition: rib.hpp:56
const scheduler::EventId & getExpirationEvent() const
Definition: route.hpp:61
const Route & getRoute() const
Definition: rib-update.hpp:114
void beginApplyUpdate(const RibUpdate &update, const UpdateSuccessCallback &onSuccess, const UpdateFailureCallback &onFailure)
passes the provided RibUpdateBatch to FibUpdater to calculate and send FibUpdates.
Definition: rib.cpp:344
time::steady_clock::TimePoint expires
Definition: route.hpp:83
void cancel(const EventId &eventId)
cancel a scheduled event
Definition: scheduler.cpp:53
void add(const RibUpdate &update)
static bool sortRoutes(const Route &lhs, const Route &rhs)
Definition: rib.cpp:37
represents a collection of RibUpdates to be applied to a single FaceId
std::ostream & operator<<(std::ostream &os, const FibUpdate &update)
Definition: fib-update.hpp:74
const_iterator find(const Name &prefix) const
Definition: rib.cpp:59
ndn::util::signal::Signal< Rib, RibRouteRef > afterAddRoute
signals after a Route is added
Definition: rib.hpp:234
bool isChildInherit() const
Definition: route.hpp:67
computes FibUpdates based on updates to the RIB and sends them to NFD
Definition: fib-updater.hpp:41
uint64_t cost
Definition: route.hpp:82
uint64_t faceId
Definition: route.hpp:79
#define NFD_LOG_DEBUG(expression)
Definition: logger.hpp:55
void onFibUpdateSuccess(const RibUpdateBatch &batch, const RibUpdateList &inheritedRoutes, const Rib::UpdateSuccessCallback &onSuccess)
Definition: rib.cpp:414
references a route
Definition: rib.hpp:43
RouteList::iterator iterator
Definition: rib-entry.hpp:40
function< void(uint32_t code, const std::string &error)> UpdateFailureCallback
Definition: rib.hpp:113
std::set< Route, RouteComparePredicate > RouteSet
Definition: rib.hpp:64
Table::const_iterator iterator
Definition: cs-internal.hpp:41
function< void()> UpdateSuccessCallback
Definition: rib.hpp:112
std::list< shared_ptr< RibEntry > > RibEntryList
Definition: rib.hpp:59
#define NFD_LOG_TRACE(expression)
Definition: logger.hpp:54
const Name & getName() const
Definition: rib-update.hpp:101
std::list< RibUpdate > RibUpdateList
void insert(const Name &prefix, const Route &route)
Definition: rib.cpp:84
Copyright (c) 2011-2015 Regents of the University of California.
Definition: ndn-common.hpp:40
RibUpdate & setAction(Action action)
Definition: rib-update.hpp:81
represents a RIB entry, which contains one or more Routes with the same prefix
Definition: rib-entry.hpp:36
represents a route for a name prefix
Definition: route.hpp:37
shared_ptr< RibEntry > findParent(const Name &prefix) const
Definition: rib.cpp:206
Name abstraction to represent an absolute name.
Definition: name.hpp:46
bool isPrefixOf(const Name &name) const
Check if the N components of this name are the same as the first N components of the given name...
Definition: name.cpp:308
RibTable::const_iterator const_iterator
Definition: rib.hpp:61
void beginRemoveFace(uint64_t faceId)
starts the FIB update process when a face has been destroyed
Definition: rib.cpp:356
ndn::util::signal::Signal< Rib, Name > afterInsertEntry
signals after a RIB entry is inserted
Definition: rib.hpp:222
size_t size() const
Get the number of components.
Definition: name.hpp:400
void onFibUpdateFailure(const Rib::UpdateFailureCallback &onFailure, uint32_t code, const std::string &error)
Definition: rib.cpp:444
ndn::util::signal::Signal< Rib, Name > afterEraseEntry
signals after a RIB entry is erased
Definition: rib.hpp:230
uint64_t flags
Definition: route.hpp:81
RibUpdate & setName(const Name &name)
Definition: rib-update.hpp:94
void onRouteExpiration(const Name &prefix, const Route &route)
Definition: rib.cpp:193
std::list< shared_ptr< RibEntry > > findDescendantsForNonInsertedName(const Name &prefix) const
finds namespaces under the passed prefix
Definition: rib.cpp:242
An update triggered by a face destruction notification.
Definition: rib-update.hpp:51
void computeAndSendFibUpdates(const RibUpdateBatch &batch, const FibUpdateSuccessCallback &onSuccess, const FibUpdateFailureCallback &onFailure)
computes FibUpdates using the provided RibUpdateBatch and then sends the updates to NFD&#39;s FIB ...
Definition: fib-updater.cpp:50
#define NFD_LOG_INIT(name)
Definition: logger.hpp:34
ndn::util::signal::Signal< Rib, RibRouteRef > beforeRemoveRoute
signals before a route is removed
Definition: rib.hpp:238
void setFibUpdater(FibUpdater *updater)
Definition: rib.cpp:53
Action getAction() const
Definition: rib-update.hpp:88