blob: bbd72f10fe35a2ed3402ec4c7ce7623e350011db [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
Vince Lehman76c751c2014-11-18 17:36:38 -060054void
55Rib::setFibUpdater(FibUpdater* updater)
56{
57 m_fibUpdater = updater;
58}
59
Alexander Afanasyev3ecec502014-04-16 13:42:44 -070060Rib::const_iterator
Vince12e49462014-06-09 13:29:32 -050061Rib::find(const Name& prefix) const
Alexander Afanasyev3ecec502014-04-16 13:42:44 -070062{
Vince12e49462014-06-09 13:29:32 -050063 return m_rib.find(prefix);
64}
65
Vince Lehman218be0a2015-01-15 17:25:20 -060066Route*
67Rib::find(const Name& prefix, const Route& route) const
Vince12e49462014-06-09 13:29:32 -050068{
Davide Pesaventoe4b22382018-06-10 14:37:24 -040069 auto ribIt = m_rib.find(prefix);
Vince12e49462014-06-09 13:29:32 -050070
71 // Name prefix exists
Vince Lehman76c751c2014-11-18 17:36:38 -060072 if (ribIt != m_rib.end()) {
73 shared_ptr<RibEntry> entry = ribIt->second;
Davide Pesaventoe4b22382018-06-10 14:37:24 -040074 auto routeIt = entry->findRoute(route);
Vince Lehman76c751c2014-11-18 17:36:38 -060075 if (routeIt != entry->end()) {
Davide Pesaventoe4b22382018-06-10 14:37:24 -040076 return &*routeIt;
Alexander Afanasyev3ecec502014-04-16 13:42:44 -070077 }
Vince Lehman76c751c2014-11-18 17:36:38 -060078 }
Vince Lehman218be0a2015-01-15 17:25:20 -060079
80 return nullptr;
Alexander Afanasyev3ecec502014-04-16 13:42:44 -070081}
82
Teng Lianga4e6ec32018-10-21 09:25:00 -070083Route*
84Rib::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
Alexander Afanasyev3ecec502014-04-16 13:42:44 -070097void
Vince Lehman218be0a2015-01-15 17:25:20 -060098Rib::insert(const Name& prefix, const Route& route)
Alexander Afanasyev3ecec502014-04-16 13:42:44 -070099{
Davide Pesaventoe4b22382018-06-10 14:37:24 -0400100 auto ribIt = m_rib.find(prefix);
Vince12e49462014-06-09 13:29:32 -0500101
102 // Name prefix exists
Vince Lehman76c751c2014-11-18 17:36:38 -0600103 if (ribIt != m_rib.end()) {
104 shared_ptr<RibEntry> entry(ribIt->second);
Vince12e49462014-06-09 13:29:32 -0500105
Nick Gordon89c4cca2016-11-02 15:42:32 +0000106 RibEntry::iterator entryIt;
107 bool didInsert = false;
108 std::tie(entryIt, didInsert) = entry->insertRoute(route);
Vince12e49462014-06-09 13:29:32 -0500109
Nick Gordon89c4cca2016-11-02 15:42:32 +0000110 if (didInsert) {
111 // The route was new and we successfully inserted it.
Vince Lehman76c751c2014-11-18 17:36:38 -0600112 m_nItems++;
Vince12e49462014-06-09 13:29:32 -0500113
Nick Gordon89c4cca2016-11-02 15:42:32 +0000114 afterAddRoute(RibRouteRef{entry, entryIt});
115
Vince12e49462014-06-09 13:29:32 -0500116 // Register with face lookup table
Vince Lehman218be0a2015-01-15 17:25:20 -0600117 m_faceMap[route.faceId].push_back(entry);
Alexander Afanasyev3ecec502014-04-16 13:42:44 -0700118 }
Vince Lehman76c751c2014-11-18 17:36:38 -0600119 else {
120 // Route exists, update fields
121 // First cancel old scheduled event, if any, then set the EventId to new one
Davide Pesaventoe1bdc082018-10-11 21:20:23 -0400122 if (entryIt->getExpirationEvent()) {
123 NFD_LOG_TRACE("Cancelling expiration event for " << entry->getName() << " " << *entryIt);
124 entryIt->cancelExpirationEvent();
Vince Lehman76c751c2014-11-18 17:36:38 -0600125 }
126
Junxiao Shid47cd632018-09-11 03:10:00 +0000127 *entryIt = route;
Vince Lehman76c751c2014-11-18 17:36:38 -0600128 }
129 }
130 else {
131 // New name prefix
Davide Pesaventoe4b22382018-06-10 14:37:24 -0400132 auto entry = make_shared<RibEntry>();
Vince Lehman76c751c2014-11-18 17:36:38 -0600133
134 m_rib[prefix] = entry;
135 m_nItems++;
136
137 entry->setName(prefix);
Davide Pesaventoe4b22382018-06-10 14:37:24 -0400138 auto routeIt = entry->insertRoute(route).first;
Vince Lehman76c751c2014-11-18 17:36:38 -0600139
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);
Nick Gordon89c4cca2016-11-02 15:42:32 +0000166 afterAddRoute(RibRouteRef{entry, routeIt});
Vince Lehman76c751c2014-11-18 17:36:38 -0600167 }
Alexander Afanasyev3ecec502014-04-16 13:42:44 -0700168}
169
Alexander Afanasyev3ecec502014-04-16 13:42:44 -0700170void
Vince Lehman218be0a2015-01-15 17:25:20 -0600171Rib::erase(const Name& prefix, const Route& route)
Alexander Afanasyev3ecec502014-04-16 13:42:44 -0700172{
Davide Pesaventoe4b22382018-06-10 14:37:24 -0400173 auto ribIt = m_rib.find(prefix);
Vince12e49462014-06-09 13:29:32 -0500174
175 // Name prefix exists
Vince Lehman76c751c2014-11-18 17:36:38 -0600176 if (ribIt != m_rib.end()) {
Davide Pesaventoe94804b2016-09-19 17:23:21 +0000177 shared_ptr<RibEntry> entry = ribIt->second;
Davide Pesaventoe4b22382018-06-10 14:37:24 -0400178 auto routeIt = entry->findRoute(route);
Vince Lehman4387e782014-06-19 16:57:45 -0500179
Vince Lehman76c751c2014-11-18 17:36:38 -0600180 if (routeIt != entry->end()) {
Nick Gordon89c4cca2016-11-02 15:42:32 +0000181 beforeRemoveRoute(RibRouteRef{entry, routeIt});
182
Davide Pesaventoe94804b2016-09-19 17:23:21 +0000183 auto faceId = route.faceId;
Vince Lehman76c751c2014-11-18 17:36:38 -0600184 entry->eraseRoute(routeIt);
185 m_nItems--;
Vince Lehman4387e782014-06-19 16:57:45 -0500186
Vince Lehman76c751c2014-11-18 17:36:38 -0600187 // If this RibEntry no longer has this faceId, unregister from face lookup table
Davide Pesaventoe94804b2016-09-19 17:23:21 +0000188 if (!entry->hasFaceId(faceId)) {
189 m_faceMap[faceId].remove(entry);
Vince Lehman76c751c2014-11-18 17:36:38 -0600190 }
Syed Obaid3313a372014-07-01 01:31:33 -0500191
Vince Lehman76c751c2014-11-18 17:36:38 -0600192 // If a RibEntry's route list is empty, remove it from the tree
Davide Pesaventoe94804b2016-09-19 17:23:21 +0000193 if (entry->getRoutes().empty()) {
Vince Lehman76c751c2014-11-18 17:36:38 -0600194 eraseEntry(ribIt);
195 }
Vince12e49462014-06-09 13:29:32 -0500196 }
Vince Lehman76c751c2014-11-18 17:36:38 -0600197 }
Vince12e49462014-06-09 13:29:32 -0500198}
199
200void
Vince Lehman76c751c2014-11-18 17:36:38 -0600201Rib::onRouteExpiration(const Name& prefix, const Route& route)
Vince12e49462014-06-09 13:29:32 -0500202{
Vince Lehman76c751c2014-11-18 17:36:38 -0600203 NFD_LOG_DEBUG(route << " for " << prefix << " has expired");
Vince12e49462014-06-09 13:29:32 -0500204
Vince Lehman76c751c2014-11-18 17:36:38 -0600205 RibUpdate update;
206 update.setAction(RibUpdate::UNREGISTER)
207 .setName(prefix)
208 .setRoute(route);
Vince12e49462014-06-09 13:29:32 -0500209
Vince Lehman76c751c2014-11-18 17:36:38 -0600210 beginApplyUpdate(update, nullptr, nullptr);
Vince12e49462014-06-09 13:29:32 -0500211}
212
213shared_ptr<RibEntry>
214Rib::findParent(const Name& prefix) const
215{
Vince Lehman76c751c2014-11-18 17:36:38 -0600216 for (int i = prefix.size() - 1; i >= 0; i--) {
Davide Pesaventoe4b22382018-06-10 14:37:24 -0400217 auto it = m_rib.find(prefix.getPrefix(i));
Vince Lehman76c751c2014-11-18 17:36:38 -0600218 if (it != m_rib.end()) {
Davide Pesaventoe4b22382018-06-10 14:37:24 -0400219 return it->second;
Vince12e49462014-06-09 13:29:32 -0500220 }
Vince Lehman76c751c2014-11-18 17:36:38 -0600221 }
Vince12e49462014-06-09 13:29:32 -0500222
Davide Pesaventoe4b22382018-06-10 14:37:24 -0400223 return nullptr;
Vince12e49462014-06-09 13:29:32 -0500224}
225
Davide Pesaventoe4b22382018-06-10 14:37:24 -0400226std::list<shared_ptr<RibEntry>>
Vince12e49462014-06-09 13:29:32 -0500227Rib::findDescendants(const Name& prefix) const
228{
Davide Pesaventoe4b22382018-06-10 14:37:24 -0400229 std::list<shared_ptr<RibEntry>> children;
Vince12e49462014-06-09 13:29:32 -0500230
231 RibTable::const_iterator it = m_rib.find(prefix);
Vince Lehman76c751c2014-11-18 17:36:38 -0600232 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 }
Alexander Afanasyev3ecec502014-04-16 13:42:44 -0700241 }
Vince Lehman76c751c2014-11-18 17:36:38 -0600242 }
243
244 return children;
245}
246
247std::list<shared_ptr<RibEntry>>
248Rib::findDescendantsForNonInsertedName(const Name& prefix) const
249{
250 std::list<shared_ptr<RibEntry>> children;
251
Davide Pesaventoe4b22382018-06-10 14:37:24 -0400252 for (const auto& pair : m_rib) {
Vince Lehman76c751c2014-11-18 17:36:38 -0600253 if (prefix.isPrefixOf(pair.first)) {
254 children.push_back(pair.second);
255 }
256 }
Vince12e49462014-06-09 13:29:32 -0500257
258 return children;
Alexander Afanasyev3ecec502014-04-16 13:42:44 -0700259}
260
Vince12e49462014-06-09 13:29:32 -0500261Rib::RibTable::iterator
262Rib::eraseEntry(RibTable::iterator it)
Alexander Afanasyev3ecec502014-04-16 13:42:44 -0700263{
Vince12e49462014-06-09 13:29:32 -0500264 // Entry does not exist
Vince Lehman76c751c2014-11-18 17:36:38 -0600265 if (it == m_rib.end()) {
266 return m_rib.end();
267 }
Vince12e49462014-06-09 13:29:32 -0500268
269 shared_ptr<RibEntry> entry(it->second);
270
271 shared_ptr<RibEntry> parent = entry->getParent();
272
273 // Remove self from parent's children
Vince Lehman76c751c2014-11-18 17:36:38 -0600274 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);
Vince12e49462014-06-09 13:29:32 -0500290 }
Vince Lehman76c751c2014-11-18 17:36:38 -0600291 }
Vince12e49462014-06-09 13:29:32 -0500292
Davide Pesaventoe4b22382018-06-10 14:37:24 -0400293 auto nextIt = m_rib.erase(it);
Vince12e49462014-06-09 13:29:32 -0500294
Yanbiao Lic17de832014-11-21 17:51:45 -0800295 // do something after erasing an entry.
296 afterEraseEntry(entry->getName());
297
Vince12e49462014-06-09 13:29:32 -0500298 return nextIt;
Alexander Afanasyev3ecec502014-04-16 13:42:44 -0700299}
300
Vince Lehman218be0a2015-01-15 17:25:20 -0600301Rib::RouteSet
302Rib::getAncestorRoutes(const RibEntry& entry) const
Vince Lehman4387e782014-06-19 16:57:45 -0500303{
Vince Lehman218be0a2015-01-15 17:25:20 -0600304 RouteSet ancestorRoutes(&sortRoutes);
Vince Lehman4387e782014-06-19 16:57:45 -0500305
306 shared_ptr<RibEntry> parent = entry.getParent();
307
Vince Lehman76c751c2014-11-18 17:36:38 -0600308 while (parent != nullptr) {
309 for (const Route& route : parent->getRoutes()) {
310 if (route.isChildInherit()) {
311 ancestorRoutes.insert(route);
Vince Lehman4387e782014-06-19 16:57:45 -0500312 }
Vince Lehman4387e782014-06-19 16:57:45 -0500313 }
314
Vince Lehman76c751c2014-11-18 17:36:38 -0600315 if (parent->hasCapture()) {
316 break;
Vince Lehman4387e782014-06-19 16:57:45 -0500317 }
Vince Lehman76c751c2014-11-18 17:36:38 -0600318
319 parent = parent->getParent();
320 }
321
322 return ancestorRoutes;
323}
324
325Rib::RouteSet
326Rib::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
349void
350Rib::beginApplyUpdate(const RibUpdate& update,
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
361void
362Rib::beginRemoveFace(uint64_t faceId)
363{
364 for (const auto& nameAndRoute : findRoutesWithFaceId(faceId)) {
365 RibUpdate update;
366 update.setAction(RibUpdate::REMOVE_FACE)
367 .setName(nameAndRoute.first)
368 .setRoute(nameAndRoute.second);
369
370 addUpdateToQueue(update, nullptr, nullptr);
371 }
372
373 sendBatchFromQueue();
374}
375
376void
377Rib::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
388void
389Rib::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
Junxiao Shi52009042018-09-10 12:33:56 +0000405 auto fibSuccessCb = bind(&Rib::onFibUpdateSuccess, this, batch, _1, item.managerSuccessCallback);
406 auto fibFailureCb = bind(&Rib::onFibUpdateFailure, this, item.managerFailureCallback, _1, _2);
Vince Lehman76c751c2014-11-18 17:36:38 -0600407
Junxiao Shi52009042018-09-10 12:33:56 +0000408#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;
Vince Lehman76c751c2014-11-18 17:36:38 -0600422 }
Junxiao Shi52009042018-09-10 12:33:56 +0000423#endif
424
425 m_fibUpdater->computeAndSendFibUpdates(batch, fibSuccessCb, fibFailureCb);
Vince Lehman76c751c2014-11-18 17:36:38 -0600426}
427
428void
429Rib::onFibUpdateSuccess(const RibUpdateBatch& batch,
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;
438 case RibUpdate::UNREGISTER:
439 case RibUpdate::REMOVE_FACE:
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
458void
459Rib::onFibUpdateFailure(const Rib::UpdateFailureCallback& onFailure,
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
472void
473Rib::modifyInheritedRoutes(const RibUpdateList& inheritedRoutes)
474{
475 for (const RibUpdate& update : inheritedRoutes) {
Davide Pesaventoe4b22382018-06-10 14:37:24 -0400476 auto ribIt = m_rib.find(update.getName());
Vince Lehman76c751c2014-11-18 17:36:38 -0600477 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;
484 case RibUpdate::UNREGISTER:
485 entry->removeInheritedRoute(update.getRoute());
486 break;
487 case RibUpdate::REMOVE_FACE:
488 break;
489 }
490 }
491}
492
493std::list<Rib::NameAndRoute>
494Rib::findRoutesWithFaceId(uint64_t faceId)
495{
496 std::list<NameAndRoute> routes;
497
Davide Pesaventoe4b22382018-06-10 14:37:24 -0400498 auto lookupIt = m_faceMap.find(faceId);
Vince Lehman76c751c2014-11-18 17:36:38 -0600499 if (lookupIt == m_faceMap.end()) {
Davide Pesaventoe4b22382018-06-10 14:37:24 -0400500 // No RIB entries have this face
Vince Lehman76c751c2014-11-18 17:36:38 -0600501 return routes;
502 }
503
Vince Lehman76c751c2014-11-18 17:36:38 -0600504 // For each RIB entry that has faceId
Davide Pesaventoe4b22382018-06-10 14:37:24 -0400505 for (const auto& entry : lookupIt->second) {
Vince Lehman76c751c2014-11-18 17:36:38 -0600506 // Find the routes in the entry
507 for (const Route& route : *entry) {
508 if (route.faceId == faceId) {
Davide Pesaventoe4b22382018-06-10 14:37:24 -0400509 routes.emplace_back(entry->getName(), route);
Vince Lehman76c751c2014-11-18 17:36:38 -0600510 }
511 }
512 }
513
514 return routes;
Vince Lehman4387e782014-06-19 16:57:45 -0500515}
516
Alexander Afanasyev20d31442014-04-19 17:00:53 -0700517std::ostream&
Vince12e49462014-06-09 13:29:32 -0500518operator<<(std::ostream& os, const Rib& rib)
Alexander Afanasyev20d31442014-04-19 17:00:53 -0700519{
Vince Lehman76c751c2014-11-18 17:36:38 -0600520 for (const auto& item : rib) {
Weiwei Liuaaa58a62016-11-28 23:15:15 -0700521 os << *item.second << "\n";
Vince Lehman76c751c2014-11-18 17:36:38 -0600522 }
Alexander Afanasyev20d31442014-04-19 17:00:53 -0700523
524 return os;
525}
526
Alexander Afanasyev3ecec502014-04-16 13:42:44 -0700527} // namespace rib
528} // namespace nfd