blob: 5385cf1797d64249d880a6d6129d917a9995cfd0 [file] [log] [blame]
Alexander Afanasyev3ecec502014-04-16 13:42:44 -07001/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
Davide Pesaventoa3148082018-04-12 18:21:54 -04002/*
3 * Copyright (c) 2014-2018, Regents of the University of California,
Alexander Afanasyev7c10b3b2015-01-20 12:24:27 -08004 * 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.
Alexander Afanasyev3ecec502014-04-16 13:42:44 -070010 *
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/>.
Vince12e49462014-06-09 13:29:32 -050024 */
Alexander Afanasyev3ecec502014-04-16 13:42:44 -070025
26#include "rib.hpp"
Vince Lehman76c751c2014-11-18 17:36:38 -060027#include "fib-updater.hpp"
Vince Lehman281ded72014-08-21 12:17:08 -050028#include "core/logger.hpp"
29
Alexander Afanasyev3ecec502014-04-16 13:42:44 -070030namespace nfd {
31namespace rib {
32
Davide Pesaventoa3148082018-04-12 18:21:54 -040033NFD_LOG_INIT(Rib);
34
Junxiao Shi89c0ea02017-03-06 19:52:05 +000035bool
36operator<(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
Vince Lehman4387e782014-06-19 16:57:45 -050042static inline bool
Vince Lehman218be0a2015-01-15 17:25:20 -060043sortRoutes(const Route& lhs, const Route& rhs)
Vince Lehman4387e782014-06-19 16:57:45 -050044{
Vince Lehman218be0a2015-01-15 17:25:20 -060045 return lhs.faceId < rhs.faceId;
Vince Lehman4387e782014-06-19 16:57:45 -050046}
47
Alexander Afanasyev3ecec502014-04-16 13:42:44 -070048Rib::Rib()
Vince12e49462014-06-09 13:29:32 -050049 : m_nItems(0)
Vince Lehman76c751c2014-11-18 17:36:38 -060050 , m_isUpdateInProgress(false)
Alexander Afanasyev3ecec502014-04-16 13:42:44 -070051{
52}
53
Davide Pesaventoa3148082018-04-12 18:21:54 -040054Rib::~Rib() = default;
Vince Lehman76c751c2014-11-18 17:36:38 -060055
56void
57Rib::setFibUpdater(FibUpdater* updater)
58{
59 m_fibUpdater = updater;
60}
61
Alexander Afanasyev3ecec502014-04-16 13:42:44 -070062Rib::const_iterator
Vince12e49462014-06-09 13:29:32 -050063Rib::find(const Name& prefix) const
Alexander Afanasyev3ecec502014-04-16 13:42:44 -070064{
Vince12e49462014-06-09 13:29:32 -050065 return m_rib.find(prefix);
66}
67
Vince Lehman218be0a2015-01-15 17:25:20 -060068Route*
69Rib::find(const Name& prefix, const Route& route) const
Vince12e49462014-06-09 13:29:32 -050070{
Davide Pesaventoe4b22382018-06-10 14:37:24 -040071 auto ribIt = m_rib.find(prefix);
Vince12e49462014-06-09 13:29:32 -050072
73 // Name prefix exists
Vince Lehman76c751c2014-11-18 17:36:38 -060074 if (ribIt != m_rib.end()) {
75 shared_ptr<RibEntry> entry = ribIt->second;
Davide Pesaventoe4b22382018-06-10 14:37:24 -040076 auto routeIt = entry->findRoute(route);
Vince Lehman76c751c2014-11-18 17:36:38 -060077 if (routeIt != entry->end()) {
Davide Pesaventoe4b22382018-06-10 14:37:24 -040078 return &*routeIt;
Alexander Afanasyev3ecec502014-04-16 13:42:44 -070079 }
Vince Lehman76c751c2014-11-18 17:36:38 -060080 }
Vince Lehman218be0a2015-01-15 17:25:20 -060081
82 return nullptr;
Alexander Afanasyev3ecec502014-04-16 13:42:44 -070083}
84
Alexander Afanasyev3ecec502014-04-16 13:42:44 -070085void
Vince Lehman218be0a2015-01-15 17:25:20 -060086Rib::insert(const Name& prefix, const Route& route)
Alexander Afanasyev3ecec502014-04-16 13:42:44 -070087{
Davide Pesaventoe4b22382018-06-10 14:37:24 -040088 auto ribIt = m_rib.find(prefix);
Vince12e49462014-06-09 13:29:32 -050089
90 // Name prefix exists
Vince Lehman76c751c2014-11-18 17:36:38 -060091 if (ribIt != m_rib.end()) {
92 shared_ptr<RibEntry> entry(ribIt->second);
Vince12e49462014-06-09 13:29:32 -050093
Nick Gordon89c4cca2016-11-02 15:42:32 +000094 RibEntry::iterator entryIt;
95 bool didInsert = false;
96 std::tie(entryIt, didInsert) = entry->insertRoute(route);
Vince12e49462014-06-09 13:29:32 -050097
Nick Gordon89c4cca2016-11-02 15:42:32 +000098 if (didInsert) {
99 // The route was new and we successfully inserted it.
Vince Lehman76c751c2014-11-18 17:36:38 -0600100 m_nItems++;
Vince12e49462014-06-09 13:29:32 -0500101
Nick Gordon89c4cca2016-11-02 15:42:32 +0000102 afterAddRoute(RibRouteRef{entry, entryIt});
103
Vince12e49462014-06-09 13:29:32 -0500104 // Register with face lookup table
Vince Lehman218be0a2015-01-15 17:25:20 -0600105 m_faceMap[route.faceId].push_back(entry);
Alexander Afanasyev3ecec502014-04-16 13:42:44 -0700106 }
Vince Lehman76c751c2014-11-18 17:36:38 -0600107 else {
108 // Route exists, update fields
109 // First cancel old scheduled event, if any, then set the EventId to new one
Nick Gordon89c4cca2016-11-02 15:42:32 +0000110 if (static_cast<bool>(entryIt->getExpirationEvent())) {
Vince Lehman76c751c2014-11-18 17:36:38 -0600111 NFD_LOG_TRACE("Cancelling expiration event for " << entry->getName() << " "
Nick Gordon89c4cca2016-11-02 15:42:32 +0000112 << (*entryIt));
113 scheduler::cancel(entryIt->getExpirationEvent());
Vince Lehman76c751c2014-11-18 17:36:38 -0600114 }
115
Junxiao Shid47cd632018-09-11 03:10:00 +0000116 *entryIt = route;
117
Vince Lehman76c751c2014-11-18 17:36:38 -0600118 // No checks are required here as the iterator needs to be updated in all cases.
Nick Gordon89c4cca2016-11-02 15:42:32 +0000119 entryIt->setExpirationEvent(route.getExpirationEvent());
Vince Lehman76c751c2014-11-18 17:36:38 -0600120 }
121 }
122 else {
123 // New name prefix
Davide Pesaventoe4b22382018-06-10 14:37:24 -0400124 auto entry = make_shared<RibEntry>();
Vince Lehman76c751c2014-11-18 17:36:38 -0600125
126 m_rib[prefix] = entry;
127 m_nItems++;
128
129 entry->setName(prefix);
Davide Pesaventoe4b22382018-06-10 14:37:24 -0400130 auto routeIt = entry->insertRoute(route).first;
Vince Lehman76c751c2014-11-18 17:36:38 -0600131
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);
Nick Gordon89c4cca2016-11-02 15:42:32 +0000158 afterAddRoute(RibRouteRef{entry, routeIt});
Vince Lehman76c751c2014-11-18 17:36:38 -0600159 }
Alexander Afanasyev3ecec502014-04-16 13:42:44 -0700160}
161
Alexander Afanasyev3ecec502014-04-16 13:42:44 -0700162void
Vince Lehman218be0a2015-01-15 17:25:20 -0600163Rib::erase(const Name& prefix, const Route& route)
Alexander Afanasyev3ecec502014-04-16 13:42:44 -0700164{
Davide Pesaventoe4b22382018-06-10 14:37:24 -0400165 auto ribIt = m_rib.find(prefix);
Vince12e49462014-06-09 13:29:32 -0500166
167 // Name prefix exists
Vince Lehman76c751c2014-11-18 17:36:38 -0600168 if (ribIt != m_rib.end()) {
Davide Pesaventoe94804b2016-09-19 17:23:21 +0000169 shared_ptr<RibEntry> entry = ribIt->second;
Davide Pesaventoe4b22382018-06-10 14:37:24 -0400170 auto routeIt = entry->findRoute(route);
Vince Lehman4387e782014-06-19 16:57:45 -0500171
Vince Lehman76c751c2014-11-18 17:36:38 -0600172 if (routeIt != entry->end()) {
Nick Gordon89c4cca2016-11-02 15:42:32 +0000173 beforeRemoveRoute(RibRouteRef{entry, routeIt});
174
Davide Pesaventoe94804b2016-09-19 17:23:21 +0000175 auto faceId = route.faceId;
Vince Lehman76c751c2014-11-18 17:36:38 -0600176 entry->eraseRoute(routeIt);
177 m_nItems--;
Vince Lehman4387e782014-06-19 16:57:45 -0500178
Vince Lehman76c751c2014-11-18 17:36:38 -0600179 // If this RibEntry no longer has this faceId, unregister from face lookup table
Davide Pesaventoe94804b2016-09-19 17:23:21 +0000180 if (!entry->hasFaceId(faceId)) {
181 m_faceMap[faceId].remove(entry);
Vince Lehman76c751c2014-11-18 17:36:38 -0600182 }
Syed Obaid3313a372014-07-01 01:31:33 -0500183
Vince Lehman76c751c2014-11-18 17:36:38 -0600184 // If a RibEntry's route list is empty, remove it from the tree
Davide Pesaventoe94804b2016-09-19 17:23:21 +0000185 if (entry->getRoutes().empty()) {
Vince Lehman76c751c2014-11-18 17:36:38 -0600186 eraseEntry(ribIt);
187 }
Vince12e49462014-06-09 13:29:32 -0500188 }
Vince Lehman76c751c2014-11-18 17:36:38 -0600189 }
Vince12e49462014-06-09 13:29:32 -0500190}
191
192void
Vince Lehman76c751c2014-11-18 17:36:38 -0600193Rib::onRouteExpiration(const Name& prefix, const Route& route)
Vince12e49462014-06-09 13:29:32 -0500194{
Vince Lehman76c751c2014-11-18 17:36:38 -0600195 NFD_LOG_DEBUG(route << " for " << prefix << " has expired");
Vince12e49462014-06-09 13:29:32 -0500196
Vince Lehman76c751c2014-11-18 17:36:38 -0600197 RibUpdate update;
198 update.setAction(RibUpdate::UNREGISTER)
199 .setName(prefix)
200 .setRoute(route);
Vince12e49462014-06-09 13:29:32 -0500201
Vince Lehman76c751c2014-11-18 17:36:38 -0600202 beginApplyUpdate(update, nullptr, nullptr);
Vince12e49462014-06-09 13:29:32 -0500203}
204
205shared_ptr<RibEntry>
206Rib::findParent(const Name& prefix) const
207{
Vince Lehman76c751c2014-11-18 17:36:38 -0600208 for (int i = prefix.size() - 1; i >= 0; i--) {
Davide Pesaventoe4b22382018-06-10 14:37:24 -0400209 auto it = m_rib.find(prefix.getPrefix(i));
Vince Lehman76c751c2014-11-18 17:36:38 -0600210 if (it != m_rib.end()) {
Davide Pesaventoe4b22382018-06-10 14:37:24 -0400211 return it->second;
Vince12e49462014-06-09 13:29:32 -0500212 }
Vince Lehman76c751c2014-11-18 17:36:38 -0600213 }
Vince12e49462014-06-09 13:29:32 -0500214
Davide Pesaventoe4b22382018-06-10 14:37:24 -0400215 return nullptr;
Vince12e49462014-06-09 13:29:32 -0500216}
217
Davide Pesaventoe4b22382018-06-10 14:37:24 -0400218std::list<shared_ptr<RibEntry>>
Vince12e49462014-06-09 13:29:32 -0500219Rib::findDescendants(const Name& prefix) const
220{
Davide Pesaventoe4b22382018-06-10 14:37:24 -0400221 std::list<shared_ptr<RibEntry>> children;
Vince12e49462014-06-09 13:29:32 -0500222
223 RibTable::const_iterator it = m_rib.find(prefix);
Vince Lehman76c751c2014-11-18 17:36:38 -0600224 if (it != m_rib.end()) {
225 ++it;
226 for (; it != m_rib.end(); ++it) {
227 if (prefix.isPrefixOf(it->first)) {
228 children.push_back((it->second));
229 }
230 else {
231 break;
232 }
Alexander Afanasyev3ecec502014-04-16 13:42:44 -0700233 }
Vince Lehman76c751c2014-11-18 17:36:38 -0600234 }
235
236 return children;
237}
238
239std::list<shared_ptr<RibEntry>>
240Rib::findDescendantsForNonInsertedName(const Name& prefix) const
241{
242 std::list<shared_ptr<RibEntry>> children;
243
Davide Pesaventoe4b22382018-06-10 14:37:24 -0400244 for (const auto& pair : m_rib) {
Vince Lehman76c751c2014-11-18 17:36:38 -0600245 if (prefix.isPrefixOf(pair.first)) {
246 children.push_back(pair.second);
247 }
248 }
Vince12e49462014-06-09 13:29:32 -0500249
250 return children;
Alexander Afanasyev3ecec502014-04-16 13:42:44 -0700251}
252
Vince12e49462014-06-09 13:29:32 -0500253Rib::RibTable::iterator
254Rib::eraseEntry(RibTable::iterator it)
Alexander Afanasyev3ecec502014-04-16 13:42:44 -0700255{
Vince12e49462014-06-09 13:29:32 -0500256 // Entry does not exist
Vince Lehman76c751c2014-11-18 17:36:38 -0600257 if (it == m_rib.end()) {
258 return m_rib.end();
259 }
Vince12e49462014-06-09 13:29:32 -0500260
261 shared_ptr<RibEntry> entry(it->second);
262
263 shared_ptr<RibEntry> parent = entry->getParent();
264
265 // Remove self from parent's children
Vince Lehman76c751c2014-11-18 17:36:38 -0600266 if (parent != nullptr) {
267 parent->removeChild(entry);
268 }
269
270 for (auto childIt = entry->getChildren().begin(); childIt != entry->getChildren().end(); ) {
271 shared_ptr<RibEntry> child = *childIt;
272
273 // Advance iterator so it is not invalidated by removal
274 ++childIt;
275
276 // Remove children from self
277 entry->removeChild(child);
278
279 // Update parent's children
280 if (parent != nullptr) {
281 parent->addChild(child);
Vince12e49462014-06-09 13:29:32 -0500282 }
Vince Lehman76c751c2014-11-18 17:36:38 -0600283 }
Vince12e49462014-06-09 13:29:32 -0500284
Davide Pesaventoe4b22382018-06-10 14:37:24 -0400285 auto nextIt = m_rib.erase(it);
Vince12e49462014-06-09 13:29:32 -0500286
Yanbiao Lic17de832014-11-21 17:51:45 -0800287 // do something after erasing an entry.
288 afterEraseEntry(entry->getName());
289
Vince12e49462014-06-09 13:29:32 -0500290 return nextIt;
Alexander Afanasyev3ecec502014-04-16 13:42:44 -0700291}
292
Vince Lehman218be0a2015-01-15 17:25:20 -0600293Rib::RouteSet
294Rib::getAncestorRoutes(const RibEntry& entry) const
Vince Lehman4387e782014-06-19 16:57:45 -0500295{
Vince Lehman218be0a2015-01-15 17:25:20 -0600296 RouteSet ancestorRoutes(&sortRoutes);
Vince Lehman4387e782014-06-19 16:57:45 -0500297
298 shared_ptr<RibEntry> parent = entry.getParent();
299
Vince Lehman76c751c2014-11-18 17:36:38 -0600300 while (parent != nullptr) {
301 for (const Route& route : parent->getRoutes()) {
302 if (route.isChildInherit()) {
303 ancestorRoutes.insert(route);
Vince Lehman4387e782014-06-19 16:57:45 -0500304 }
Vince Lehman4387e782014-06-19 16:57:45 -0500305 }
306
Vince Lehman76c751c2014-11-18 17:36:38 -0600307 if (parent->hasCapture()) {
308 break;
Vince Lehman4387e782014-06-19 16:57:45 -0500309 }
Vince Lehman76c751c2014-11-18 17:36:38 -0600310
311 parent = parent->getParent();
312 }
313
314 return ancestorRoutes;
315}
316
317Rib::RouteSet
318Rib::getAncestorRoutes(const Name& name) const
319{
320 RouteSet ancestorRoutes(&sortRoutes);
321
322 shared_ptr<RibEntry> parent = findParent(name);
323
324 while (parent != nullptr) {
325 for (const Route& route : parent->getRoutes()) {
326 if (route.isChildInherit()) {
327 ancestorRoutes.insert(route);
328 }
329 }
330
331 if (parent->hasCapture()) {
332 break;
333 }
334
335 parent = parent->getParent();
336 }
337
338 return ancestorRoutes;
339}
340
341void
342Rib::beginApplyUpdate(const RibUpdate& update,
343 const Rib::UpdateSuccessCallback& onSuccess,
344 const Rib::UpdateFailureCallback& onFailure)
345{
346 BOOST_ASSERT(m_fibUpdater != nullptr);
347
348 addUpdateToQueue(update, onSuccess, onFailure);
349
350 sendBatchFromQueue();
351}
352
353void
354Rib::beginRemoveFace(uint64_t faceId)
355{
356 for (const auto& nameAndRoute : findRoutesWithFaceId(faceId)) {
357 RibUpdate update;
358 update.setAction(RibUpdate::REMOVE_FACE)
359 .setName(nameAndRoute.first)
360 .setRoute(nameAndRoute.second);
361
362 addUpdateToQueue(update, nullptr, nullptr);
363 }
364
365 sendBatchFromQueue();
366}
367
368void
369Rib::addUpdateToQueue(const RibUpdate& update,
370 const Rib::UpdateSuccessCallback& onSuccess,
371 const Rib::UpdateFailureCallback& onFailure)
372{
373 RibUpdateBatch batch(update.getRoute().faceId);
374 batch.add(update);
375
376 UpdateQueueItem item{batch, onSuccess, onFailure};
377 m_updateBatches.push_back(std::move(item));
378}
379
380void
381Rib::sendBatchFromQueue()
382{
383 if (m_updateBatches.empty() || m_isUpdateInProgress) {
384 return;
385 }
386
387 m_isUpdateInProgress = true;
388
389 UpdateQueueItem item = std::move(m_updateBatches.front());
390 m_updateBatches.pop_front();
391
392 RibUpdateBatch& batch = item.batch;
393
394 // Until task #1698, each RibUpdateBatch contains exactly one RIB update
395 BOOST_ASSERT(batch.size() == 1);
396
Junxiao Shi52009042018-09-10 12:33:56 +0000397 auto fibSuccessCb = bind(&Rib::onFibUpdateSuccess, this, batch, _1, item.managerSuccessCallback);
398 auto fibFailureCb = bind(&Rib::onFibUpdateFailure, this, item.managerFailureCallback, _1, _2);
Vince Lehman76c751c2014-11-18 17:36:38 -0600399
Junxiao Shi52009042018-09-10 12:33:56 +0000400#ifdef WITH_TESTS
401 if (mockFibResponse != nullptr) {
402 m_fibUpdater->computeAndSendFibUpdates(batch, bind([]{}), bind([]{}));
403 bool shouldFibSucceed = mockFibResponse(batch);
404 if (wantMockFibResponseOnce) {
405 mockFibResponse = nullptr;
406 }
407 if (shouldFibSucceed) {
408 fibSuccessCb(m_fibUpdater->m_inheritedRoutes);
409 }
410 else {
411 fibFailureCb(504, "mocked failure");
412 }
413 return;
Vince Lehman76c751c2014-11-18 17:36:38 -0600414 }
Junxiao Shi52009042018-09-10 12:33:56 +0000415#endif
416
417 m_fibUpdater->computeAndSendFibUpdates(batch, fibSuccessCb, fibFailureCb);
Vince Lehman76c751c2014-11-18 17:36:38 -0600418}
419
420void
421Rib::onFibUpdateSuccess(const RibUpdateBatch& batch,
422 const RibUpdateList& inheritedRoutes,
423 const Rib::UpdateSuccessCallback& onSuccess)
424{
425 for (const RibUpdate& update : batch) {
426 switch (update.getAction()) {
427 case RibUpdate::REGISTER:
428 insert(update.getName(), update.getRoute());
429 break;
430 case RibUpdate::UNREGISTER:
431 case RibUpdate::REMOVE_FACE:
432 erase(update.getName(), update.getRoute());
433 break;
434 }
435 }
436
437 // Add and remove precalculated inherited routes to RibEntries
438 modifyInheritedRoutes(inheritedRoutes);
439
440 m_isUpdateInProgress = false;
441
442 if (onSuccess != nullptr) {
443 onSuccess();
444 }
445
446 // Try to advance the batch queue
447 sendBatchFromQueue();
448}
449
450void
451Rib::onFibUpdateFailure(const Rib::UpdateFailureCallback& onFailure,
452 uint32_t code, const std::string& error)
453{
454 m_isUpdateInProgress = false;
455
456 if (onFailure != nullptr) {
457 onFailure(code, error);
458 }
459
460 // Try to advance the batch queue
461 sendBatchFromQueue();
462}
463
464void
465Rib::modifyInheritedRoutes(const RibUpdateList& inheritedRoutes)
466{
467 for (const RibUpdate& update : inheritedRoutes) {
Davide Pesaventoe4b22382018-06-10 14:37:24 -0400468 auto ribIt = m_rib.find(update.getName());
Vince Lehman76c751c2014-11-18 17:36:38 -0600469 BOOST_ASSERT(ribIt != m_rib.end());
470 shared_ptr<RibEntry> entry(ribIt->second);
471
472 switch (update.getAction()) {
473 case RibUpdate::REGISTER:
474 entry->addInheritedRoute(update.getRoute());
475 break;
476 case RibUpdate::UNREGISTER:
477 entry->removeInheritedRoute(update.getRoute());
478 break;
479 case RibUpdate::REMOVE_FACE:
480 break;
481 }
482 }
483}
484
485std::list<Rib::NameAndRoute>
486Rib::findRoutesWithFaceId(uint64_t faceId)
487{
488 std::list<NameAndRoute> routes;
489
Davide Pesaventoe4b22382018-06-10 14:37:24 -0400490 auto lookupIt = m_faceMap.find(faceId);
Vince Lehman76c751c2014-11-18 17:36:38 -0600491 if (lookupIt == m_faceMap.end()) {
Davide Pesaventoe4b22382018-06-10 14:37:24 -0400492 // No RIB entries have this face
Vince Lehman76c751c2014-11-18 17:36:38 -0600493 return routes;
494 }
495
Vince Lehman76c751c2014-11-18 17:36:38 -0600496 // For each RIB entry that has faceId
Davide Pesaventoe4b22382018-06-10 14:37:24 -0400497 for (const auto& entry : lookupIt->second) {
Vince Lehman76c751c2014-11-18 17:36:38 -0600498 // Find the routes in the entry
499 for (const Route& route : *entry) {
500 if (route.faceId == faceId) {
Davide Pesaventoe4b22382018-06-10 14:37:24 -0400501 routes.emplace_back(entry->getName(), route);
Vince Lehman76c751c2014-11-18 17:36:38 -0600502 }
503 }
504 }
505
506 return routes;
Vince Lehman4387e782014-06-19 16:57:45 -0500507}
508
Alexander Afanasyev20d31442014-04-19 17:00:53 -0700509std::ostream&
Vince12e49462014-06-09 13:29:32 -0500510operator<<(std::ostream& os, const Rib& rib)
Alexander Afanasyev20d31442014-04-19 17:00:53 -0700511{
Vince Lehman76c751c2014-11-18 17:36:38 -0600512 for (const auto& item : rib) {
Weiwei Liuaaa58a62016-11-28 23:15:15 -0700513 os << *item.second << "\n";
Vince Lehman76c751c2014-11-18 17:36:38 -0600514 }
Alexander Afanasyev20d31442014-04-19 17:00:53 -0700515
516 return os;
517}
518
Alexander Afanasyev3ecec502014-04-16 13:42:44 -0700519} // namespace rib
520} // namespace nfd