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