blob: 5d578ab29a6a297fec234de60d33363cc63417bd [file] [log] [blame]
Alexander Afanasyev3ecec502014-04-16 13:42:44 -07001/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
2/**
Alexander Afanasyev7c10b3b2015-01-20 12:24:27 -08003 * Copyright (c) 2014-2015, 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.
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"
27
Vince Lehman281ded72014-08-21 12:17:08 -050028#include "core/logger.hpp"
29
30NFD_LOG_INIT("Rib");
31
Alexander Afanasyev3ecec502014-04-16 13:42:44 -070032namespace nfd {
33namespace rib {
34
Vince Lehman4387e782014-06-19 16:57:45 -050035static inline bool
Vince Lehman218be0a2015-01-15 17:25:20 -060036sortRoutes(const Route& lhs, const Route& rhs)
Vince Lehman4387e782014-06-19 16:57:45 -050037{
Vince Lehman218be0a2015-01-15 17:25:20 -060038 return lhs.faceId < rhs.faceId;
Vince Lehman4387e782014-06-19 16:57:45 -050039}
40
41static inline bool
42isChildInheritFlagSet(uint64_t flags)
43{
44 return flags & ndn::nfd::ROUTE_FLAG_CHILD_INHERIT;
45}
46
47static inline bool
48isCaptureFlagSet(uint64_t flags)
49{
50 return flags & ndn::nfd::ROUTE_FLAG_CAPTURE;
51}
52
53static inline bool
54isAnyFlagSet(uint64_t flags)
55{
56 return isChildInheritFlagSet(flags) || isCaptureFlagSet(flags);
57}
58
59static inline bool
60areBothFlagsSet(uint64_t flags)
61{
62 return isChildInheritFlagSet(flags) && isCaptureFlagSet(flags);
63}
64
Alexander Afanasyev3ecec502014-04-16 13:42:44 -070065Rib::Rib()
Vince12e49462014-06-09 13:29:32 -050066 : m_nItems(0)
Alexander Afanasyev3ecec502014-04-16 13:42:44 -070067{
68}
69
Alexander Afanasyev3ecec502014-04-16 13:42:44 -070070Rib::const_iterator
Vince12e49462014-06-09 13:29:32 -050071Rib::find(const Name& prefix) const
Alexander Afanasyev3ecec502014-04-16 13:42:44 -070072{
Vince12e49462014-06-09 13:29:32 -050073 return m_rib.find(prefix);
74}
75
Vince Lehman218be0a2015-01-15 17:25:20 -060076Route*
77Rib::find(const Name& prefix, const Route& route) const
Vince12e49462014-06-09 13:29:32 -050078{
79 RibTable::const_iterator ribIt = m_rib.find(prefix);
80
81 // Name prefix exists
82 if (ribIt != m_rib.end())
Alexander Afanasyev3ecec502014-04-16 13:42:44 -070083 {
Vince Lehman218be0a2015-01-15 17:25:20 -060084 shared_ptr<RibEntry> entry = ribIt->second;
Vince12e49462014-06-09 13:29:32 -050085
Vince Lehman218be0a2015-01-15 17:25:20 -060086 RibEntry::iterator routeIt = entry->findRoute(route);
Vince12e49462014-06-09 13:29:32 -050087
Vince Lehman218be0a2015-01-15 17:25:20 -060088 if (routeIt != entry->end())
Vince12e49462014-06-09 13:29:32 -050089 {
Vince Lehman218be0a2015-01-15 17:25:20 -060090 return &((*routeIt));
Vince12e49462014-06-09 13:29:32 -050091 }
Alexander Afanasyev3ecec502014-04-16 13:42:44 -070092 }
Vince Lehman218be0a2015-01-15 17:25:20 -060093
94 return nullptr;
Alexander Afanasyev3ecec502014-04-16 13:42:44 -070095}
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{
Vince12e49462014-06-09 13:29:32 -0500100 RibTable::iterator ribIt = m_rib.find(prefix);
101
102 // Name prefix exists
103 if (ribIt != m_rib.end())
Alexander Afanasyev3ecec502014-04-16 13:42:44 -0700104 {
Vince12e49462014-06-09 13:29:32 -0500105 shared_ptr<RibEntry> entry(ribIt->second);
106
Vince Lehman218be0a2015-01-15 17:25:20 -0600107 RibEntry::iterator routeIt = entry->findRoute(route);
Vince12e49462014-06-09 13:29:32 -0500108
Vince Lehman218be0a2015-01-15 17:25:20 -0600109 if (routeIt == entry->end())
Vince12e49462014-06-09 13:29:32 -0500110 {
Vince Lehman218be0a2015-01-15 17:25:20 -0600111 // Will the new route change the namespace's capture flag?
112 bool captureWasTurnedOn = (entry->hasCapture() == false && isCaptureFlagSet(route.flags));
Vince Lehman4387e782014-06-19 16:57:45 -0500113
Vince Lehman218be0a2015-01-15 17:25:20 -0600114 // New route
115 entry->insertRoute(route);
Vince12e49462014-06-09 13:29:32 -0500116 m_nItems++;
117
118 // Register with face lookup table
Vince Lehman218be0a2015-01-15 17:25:20 -0600119 m_faceMap[route.faceId].push_back(entry);
Vince Lehman4387e782014-06-19 16:57:45 -0500120
Vince Lehman218be0a2015-01-15 17:25:20 -0600121 createFibUpdatesForNewRoute(*entry, route, captureWasTurnedOn);
Vince12e49462014-06-09 13:29:32 -0500122 }
Vince Lehman218be0a2015-01-15 17:25:20 -0600123 else // Route exists, update fields
Vince12e49462014-06-09 13:29:32 -0500124 {
Syed Obaid3313a372014-07-01 01:31:33 -0500125 // First cancel old scheduled event, if any, then set the EventId to new one
Vince Lehman218be0a2015-01-15 17:25:20 -0600126 if (static_cast<bool>(routeIt->getExpirationEvent()))
Vince Lehman281ded72014-08-21 12:17:08 -0500127 {
128 NFD_LOG_TRACE("Cancelling expiration event for " << entry->getName() << " "
Vince Lehman218be0a2015-01-15 17:25:20 -0600129 << *routeIt);
130 scheduler::cancel(routeIt->getExpirationEvent());
Vince Lehman281ded72014-08-21 12:17:08 -0500131 }
Syed Obaid3313a372014-07-01 01:31:33 -0500132
133 // No checks are required here as the iterator needs to be updated in all cases.
Vince Lehman218be0a2015-01-15 17:25:20 -0600134 routeIt->setExpirationEvent(route.getExpirationEvent());
Syed Obaid3313a372014-07-01 01:31:33 -0500135
Vince Lehman4387e782014-06-19 16:57:45 -0500136 // Save flags for update processing
Vince Lehman218be0a2015-01-15 17:25:20 -0600137 uint64_t previousFlags = routeIt->flags;
Vince Lehman4387e782014-06-19 16:57:45 -0500138
Vince Lehman218be0a2015-01-15 17:25:20 -0600139 // If the route's cost didn't change and child inherit is not set,
Vince Lehman4387e782014-06-19 16:57:45 -0500140 // no need to traverse subtree.
Vince Lehman218be0a2015-01-15 17:25:20 -0600141 uint64_t previousCost = routeIt->cost;
Vince Lehman4387e782014-06-19 16:57:45 -0500142
Vince Lehman218be0a2015-01-15 17:25:20 -0600143 routeIt->flags = route.flags;
144 routeIt->cost = route.cost;
145 routeIt->expires = route.expires;
Vince Lehman4387e782014-06-19 16:57:45 -0500146
Vince Lehman218be0a2015-01-15 17:25:20 -0600147 createFibUpdatesForUpdatedRoute(*entry, route, previousFlags, previousCost);
Vince12e49462014-06-09 13:29:32 -0500148 }
Alexander Afanasyev3ecec502014-04-16 13:42:44 -0700149 }
Vince12e49462014-06-09 13:29:32 -0500150 else // New name prefix
Alexander Afanasyev3ecec502014-04-16 13:42:44 -0700151 {
Vince12e49462014-06-09 13:29:32 -0500152 shared_ptr<RibEntry> entry(make_shared<RibEntry>(RibEntry()));
153
154 m_rib[prefix] = entry;
155 m_nItems++;
156
157 entry->setName(prefix);
Vince Lehman218be0a2015-01-15 17:25:20 -0600158 entry->insertRoute(route);
Vince12e49462014-06-09 13:29:32 -0500159
160 // Find prefix's parent
161 shared_ptr<RibEntry> parent = findParent(prefix);
162
163 // Add self to parent's children
164 if (static_cast<bool>(parent))
165 {
166 parent->addChild(entry);
167 }
168
169 RibEntryList children = findDescendants(prefix);
170
171 for (std::list<shared_ptr<RibEntry> >::iterator child = children.begin();
172 child != children.end(); ++child)
173 {
174 if ((*child)->getParent() == parent)
175 {
176 // Remove child from parent and inherit parent's child
177 if (static_cast<bool>(parent))
178 {
179 parent->removeChild((*child));
180 }
Vince12e49462014-06-09 13:29:32 -0500181 entry->addChild((*child));
182 }
183 }
184
185 // Register with face lookup table
Vince Lehman218be0a2015-01-15 17:25:20 -0600186 m_faceMap[route.faceId].push_back(entry);
Vince Lehman4387e782014-06-19 16:57:45 -0500187
Vince Lehman218be0a2015-01-15 17:25:20 -0600188 createFibUpdatesForNewRibEntry(*entry, route);
Yanbiao Lic17de832014-11-21 17:51:45 -0800189
190 // do something after inserting an entry
191 afterInsertEntry(prefix);
Alexander Afanasyev3ecec502014-04-16 13:42:44 -0700192 }
193}
194
Alexander Afanasyev3ecec502014-04-16 13:42:44 -0700195void
Vince Lehman218be0a2015-01-15 17:25:20 -0600196Rib::erase(const Name& prefix, const Route& route)
Alexander Afanasyev3ecec502014-04-16 13:42:44 -0700197{
Vince12e49462014-06-09 13:29:32 -0500198 RibTable::iterator ribIt = m_rib.find(prefix);
199
200 // Name prefix exists
201 if (ribIt != m_rib.end())
202 {
203 shared_ptr<RibEntry> entry(ribIt->second);
204
Vince Lehman4387e782014-06-19 16:57:45 -0500205 const bool hadCapture = entry->hasCapture();
206
Vince Lehman218be0a2015-01-15 17:25:20 -0600207 // Need to copy route to do FIB updates with correct cost and flags since nfdc does not
Vince Lehman4387e782014-06-19 16:57:45 -0500208 // pass flags or cost
Vince Lehman218be0a2015-01-15 17:25:20 -0600209 RibEntry::iterator routeIt = entry->findRoute(route);
Vince Lehman4387e782014-06-19 16:57:45 -0500210
Vince Lehman218be0a2015-01-15 17:25:20 -0600211 if (routeIt != entry->end())
Vince12e49462014-06-09 13:29:32 -0500212 {
Vince Lehman218be0a2015-01-15 17:25:20 -0600213 Route routeToErase = *routeIt;
214 routeToErase.flags = routeIt->flags;
215 routeToErase.cost = routeIt->cost;
Syed Obaid3313a372014-07-01 01:31:33 -0500216
Vince Lehman218be0a2015-01-15 17:25:20 -0600217 entry->eraseRoute(routeIt);
Vince Lehman281ded72014-08-21 12:17:08 -0500218
Vince12e49462014-06-09 13:29:32 -0500219 m_nItems--;
220
Vince Lehman4387e782014-06-19 16:57:45 -0500221 const bool captureWasTurnedOff = (hadCapture && !entry->hasCapture());
222
Vince Lehman218be0a2015-01-15 17:25:20 -0600223 createFibUpdatesForErasedRoute(*entry, routeToErase, captureWasTurnedOff);
Vince Lehman4387e782014-06-19 16:57:45 -0500224
Vince12e49462014-06-09 13:29:32 -0500225 // If this RibEntry no longer has this faceId, unregister from face lookup table
Vince Lehman218be0a2015-01-15 17:25:20 -0600226 if (!entry->hasFaceId(route.faceId))
Vince12e49462014-06-09 13:29:32 -0500227 {
Vince Lehman218be0a2015-01-15 17:25:20 -0600228 m_faceMap[route.faceId].remove(entry);
Vince12e49462014-06-09 13:29:32 -0500229 }
Vince Lehman4387e782014-06-19 16:57:45 -0500230 else
231 {
232 // The RibEntry still has the face ID; need to update FIB
Vince Lehman218be0a2015-01-15 17:25:20 -0600233 // with lowest cost for the same route instead of removing the route from the FIB
234 shared_ptr<Route> lowCostRoute = entry->getRouteWithLowestCostByFaceId(route.faceId);
Vince Lehman4387e782014-06-19 16:57:45 -0500235
Vince Lehman218be0a2015-01-15 17:25:20 -0600236 BOOST_ASSERT(static_cast<bool>(lowCostRoute));
Vince Lehman4387e782014-06-19 16:57:45 -0500237
Vince Lehman218be0a2015-01-15 17:25:20 -0600238 createFibUpdatesForNewRoute(*entry, *lowCostRoute, false);
Vince Lehman4387e782014-06-19 16:57:45 -0500239 }
Vince12e49462014-06-09 13:29:32 -0500240
Vince Lehman218be0a2015-01-15 17:25:20 -0600241 // If a RibEntry's route list is empty, remove it from the tree
242 if (entry->getRoutes().size() == 0)
Vince12e49462014-06-09 13:29:32 -0500243 {
244 eraseEntry(ribIt);
245 }
246 }
247 }
248}
249
250void
251Rib::erase(const uint64_t faceId)
252{
253 FaceLookupTable::iterator lookupIt = m_faceMap.find(faceId);
254
255 // No RIB entries have this face
256 if (lookupIt == m_faceMap.end())
257 {
258 return;
259 }
260
261 RibEntryList& ribEntries = lookupIt->second;
262
263 // For each RIB entry that has faceId, remove the face from the entry
Vince Lehman218be0a2015-01-15 17:25:20 -0600264 for (shared_ptr<RibEntry>& entry : ribEntries)
Vince12e49462014-06-09 13:29:32 -0500265 {
Vince Lehman4387e782014-06-19 16:57:45 -0500266 const bool hadCapture = entry->hasCapture();
267
Vince Lehman218be0a2015-01-15 17:25:20 -0600268 // Find the routes in the entry
269 for (RibEntry::iterator routeIt = entry->begin(); routeIt != entry->end(); ++routeIt)
Vince12e49462014-06-09 13:29:32 -0500270 {
Vince Lehman218be0a2015-01-15 17:25:20 -0600271 if (routeIt->faceId == faceId)
Vince12e49462014-06-09 13:29:32 -0500272 {
Vince Lehman218be0a2015-01-15 17:25:20 -0600273 Route copy = *routeIt;
Vince Lehman4387e782014-06-19 16:57:45 -0500274
Vince Lehman218be0a2015-01-15 17:25:20 -0600275 routeIt = entry->eraseRoute(routeIt);
Vince Lehman26b215c2014-08-17 15:00:41 -0500276 m_nItems--;
Vince Lehman4387e782014-06-19 16:57:45 -0500277
278 const bool captureWasTurnedOff = (hadCapture && !entry->hasCapture());
Vince Lehman218be0a2015-01-15 17:25:20 -0600279 createFibUpdatesForErasedRoute(*entry, copy, captureWasTurnedOff);
Vince12e49462014-06-09 13:29:32 -0500280 }
281 }
282
Vince Lehman218be0a2015-01-15 17:25:20 -0600283 // If a RibEntry's route list is empty, remove it from the tree
284 if (entry->getRoutes().size() == 0)
Vince12e49462014-06-09 13:29:32 -0500285 {
286 eraseEntry(m_rib.find(entry->getName()));
287 }
288 }
289
290 // Face no longer exists, remove from face lookup table
Vince Lehman218be0a2015-01-15 17:25:20 -0600291 m_faceMap.erase(lookupIt);
Vince12e49462014-06-09 13:29:32 -0500292}
293
294shared_ptr<RibEntry>
295Rib::findParent(const Name& prefix) const
296{
297 for (int i = prefix.size() - 1; i >= 0; i--)
298 {
299 RibTable::const_iterator it = m_rib.find(prefix.getPrefix(i));
300 if (it != m_rib.end())
301 {
302 return (it->second);
303 }
304 }
305
306 return shared_ptr<RibEntry>();
307}
308
309std::list<shared_ptr<RibEntry> >
310Rib::findDescendants(const Name& prefix) const
311{
312 std::list<shared_ptr<RibEntry> > children;
313
314 RibTable::const_iterator it = m_rib.find(prefix);
315
Alexander Afanasyev3ecec502014-04-16 13:42:44 -0700316 if (it != m_rib.end())
317 {
Vince12e49462014-06-09 13:29:32 -0500318 ++it;
319 for (; it != m_rib.end(); ++it)
320 {
321 if (prefix.isPrefixOf(it->first))
322 {
323 children.push_back((it->second));
324 }
325 else
326 {
327 break;
328 }
329 }
Alexander Afanasyev3ecec502014-04-16 13:42:44 -0700330 }
Vince12e49462014-06-09 13:29:32 -0500331
332 return children;
Alexander Afanasyev3ecec502014-04-16 13:42:44 -0700333}
334
Vince12e49462014-06-09 13:29:32 -0500335Rib::RibTable::iterator
336Rib::eraseEntry(RibTable::iterator it)
Alexander Afanasyev3ecec502014-04-16 13:42:44 -0700337{
Vince12e49462014-06-09 13:29:32 -0500338 // Entry does not exist
339 if (it == m_rib.end())
340 {
341 return m_rib.end();
342 }
343
344 shared_ptr<RibEntry> entry(it->second);
345
Vince Lehman4387e782014-06-19 16:57:45 -0500346 // Remove inherited routes from namespace
347 createFibUpdatesForErasedRibEntry(*entry);
348
Vince12e49462014-06-09 13:29:32 -0500349 shared_ptr<RibEntry> parent = entry->getParent();
350
351 // Remove self from parent's children
352 if (static_cast<bool>(parent))
353 {
354 parent->removeChild(entry);
355 }
356
357 std::list<shared_ptr<RibEntry> > children = entry->getChildren();
358
359 for (RibEntryList::iterator child = children.begin(); child != children.end(); ++child)
360 {
361 // Remove children from self
362 entry->removeChild(*child);
363
364 // Update parent's children
365 if (static_cast<bool>(parent))
366 {
367 parent->addChild(*child);
368 }
369 }
370
371 // Must save and advance iterator to return a valid iterator
372 RibTable::iterator nextIt = it;
373 nextIt++;
374
375 m_rib.erase(it);
376
Yanbiao Lic17de832014-11-21 17:51:45 -0800377 // do something after erasing an entry.
378 afterEraseEntry(entry->getName());
379
Vince12e49462014-06-09 13:29:32 -0500380 return nextIt;
Alexander Afanasyev3ecec502014-04-16 13:42:44 -0700381}
382
Vince Lehman4387e782014-06-19 16:57:45 -0500383bool
384compareFibUpdates(const shared_ptr<const FibUpdate> lhs, const shared_ptr<const FibUpdate> rhs)
385{
386 return ((lhs->name == rhs->name) &&
387 (lhs->faceId == rhs->faceId));
388}
389
390void
391Rib::insertFibUpdate(shared_ptr<FibUpdate> update)
392{
Vince Lehman218be0a2015-01-15 17:25:20 -0600393 // If an update with the same name and Face ID already exists, replace it
Vince Lehman4387e782014-06-19 16:57:45 -0500394 FibUpdateList::iterator it = std::find_if(m_fibUpdateList.begin(), m_fibUpdateList.end(),
395 bind(&compareFibUpdates, _1, update));
396
397 if (it != m_fibUpdateList.end())
398 {
399 // Get rid of the const to alter the action, prevents copying or removal and
400 // insertion
401 FibUpdate& entry = const_cast<FibUpdate&>(*(*it));
402 entry.action = update->action;
403 entry.cost = update->cost;
404 }
405 else
406 {
407 m_fibUpdateList.push_back(update);
408 }
409}
410
411void
Vince Lehman218be0a2015-01-15 17:25:20 -0600412Rib::createFibUpdatesForNewRibEntry(RibEntry& entry, const Route& route)
Vince Lehman4387e782014-06-19 16:57:45 -0500413{
414 // Create FIB update for new entry
Vince Lehman218be0a2015-01-15 17:25:20 -0600415 insertFibUpdate(FibUpdate::createAddUpdate(entry.getName(), route.faceId, route.cost));
Vince Lehman4387e782014-06-19 16:57:45 -0500416
417 // No flags are set
Vince Lehman218be0a2015-01-15 17:25:20 -0600418 if (!isAnyFlagSet(route.flags))
Vince Lehman4387e782014-06-19 16:57:45 -0500419 {
Vince Lehman218be0a2015-01-15 17:25:20 -0600420 // Add ancestor routes to self
421 addInheritedRoutesToEntry(entry, getAncestorRoutes(entry));
Vince Lehman4387e782014-06-19 16:57:45 -0500422 }
Vince Lehman218be0a2015-01-15 17:25:20 -0600423 else if (areBothFlagsSet(route.flags))
Vince Lehman4387e782014-06-19 16:57:45 -0500424 {
Vince Lehman218be0a2015-01-15 17:25:20 -0600425 // Add route to children
426 RouteSet routesToAdd;
427 routesToAdd.insert(route);
Vince Lehman4387e782014-06-19 16:57:45 -0500428
Vince Lehman218be0a2015-01-15 17:25:20 -0600429 // Remove routes blocked by capture and add self to children
430 modifyChildrensInheritedRoutes(entry, routesToAdd, getAncestorRoutes(entry));
Vince Lehman4387e782014-06-19 16:57:45 -0500431 }
Vince Lehman218be0a2015-01-15 17:25:20 -0600432 else if (isChildInheritFlagSet(route.flags))
Vince Lehman4387e782014-06-19 16:57:45 -0500433 {
Vince Lehman218be0a2015-01-15 17:25:20 -0600434 RouteSet ancestorRoutes = getAncestorRoutes(entry);
Vince Lehman4387e782014-06-19 16:57:45 -0500435
Vince Lehman218be0a2015-01-15 17:25:20 -0600436 // Add ancestor routes to self
437 addInheritedRoutesToEntry(entry, ancestorRoutes);
Vince Lehman4387e782014-06-19 16:57:45 -0500438
Vince Lehman218be0a2015-01-15 17:25:20 -0600439 // If there is an ancestor route with the same Face ID as the new route, replace it
440 // with the new route
441 RouteSet::iterator it = ancestorRoutes.find(route);
Vince Lehman4387e782014-06-19 16:57:45 -0500442
Vince Lehman218be0a2015-01-15 17:25:20 -0600443 // There is a route that needs to be overwritten, erase and then replace
444 if (it != ancestorRoutes.end())
Vince Lehman4387e782014-06-19 16:57:45 -0500445 {
Vince Lehman218be0a2015-01-15 17:25:20 -0600446 ancestorRoutes.erase(it);
Vince Lehman4387e782014-06-19 16:57:45 -0500447 }
448
Vince Lehman218be0a2015-01-15 17:25:20 -0600449 // Add new route to ancestor list so it can be added to children
450 ancestorRoutes.insert(route);
Vince Lehman4387e782014-06-19 16:57:45 -0500451
Vince Lehman218be0a2015-01-15 17:25:20 -0600452 // Add ancestor routes to children
453 modifyChildrensInheritedRoutes(entry, ancestorRoutes, RouteSet());
Vince Lehman4387e782014-06-19 16:57:45 -0500454 }
Vince Lehman218be0a2015-01-15 17:25:20 -0600455 else if (isCaptureFlagSet(route.flags))
Vince Lehman4387e782014-06-19 16:57:45 -0500456 {
Vince Lehman218be0a2015-01-15 17:25:20 -0600457 // Remove routes blocked by capture
458 modifyChildrensInheritedRoutes(entry, RouteSet(), getAncestorRoutes(entry));
Vince Lehman4387e782014-06-19 16:57:45 -0500459 }
460}
461
462void
Vince Lehman218be0a2015-01-15 17:25:20 -0600463Rib::createFibUpdatesForNewRoute(RibEntry& entry, const Route& route, bool captureWasTurnedOn)
Vince Lehman4387e782014-06-19 16:57:45 -0500464{
Vince Lehman218be0a2015-01-15 17:25:20 -0600465 // Only update if the new route has a lower cost than a previously installed route
466 shared_ptr<Route> prevRoute = entry.getRouteWithLowestCostAndChildInheritByFaceId(route.faceId);
Vince Lehman4387e782014-06-19 16:57:45 -0500467
Vince Lehman218be0a2015-01-15 17:25:20 -0600468 RouteSet routesToAdd;
469 if (isChildInheritFlagSet(route.flags))
Vince Lehman4387e782014-06-19 16:57:45 -0500470 {
Vince Lehman218be0a2015-01-15 17:25:20 -0600471 // Add to children if this new route doesn't override a previous lower cost, or
472 // add to children if this new route is lower cost than a previous route.
473 // Less than equal, since entry may find this route
474 if (prevRoute == nullptr || route.cost <= prevRoute->cost)
Vince Lehman4387e782014-06-19 16:57:45 -0500475 {
476 // Add self to children
Vince Lehman218be0a2015-01-15 17:25:20 -0600477 routesToAdd.insert(route);
Vince Lehman4387e782014-06-19 16:57:45 -0500478 }
479 }
480
Vince Lehman218be0a2015-01-15 17:25:20 -0600481 RouteSet routesToRemove;
Vince Lehman4387e782014-06-19 16:57:45 -0500482 if (captureWasTurnedOn)
483 {
484 // Capture flag on
Vince Lehman218be0a2015-01-15 17:25:20 -0600485 routesToRemove = getAncestorRoutes(entry);
Vince Lehman4387e782014-06-19 16:57:45 -0500486
Vince Lehman218be0a2015-01-15 17:25:20 -0600487 // Remove ancestor routes from self
488 removeInheritedRoutesFromEntry(entry, routesToRemove);
Vince Lehman4387e782014-06-19 16:57:45 -0500489 }
490
Vince Lehman218be0a2015-01-15 17:25:20 -0600491 modifyChildrensInheritedRoutes(entry, routesToAdd, routesToRemove);
Vince Lehman4387e782014-06-19 16:57:45 -0500492
Vince Lehman218be0a2015-01-15 17:25:20 -0600493 // If another route with same faceId and lower cost, don't update.
Vince Lehman4387e782014-06-19 16:57:45 -0500494 // Must be done last so that add updates replace removal updates
495 // Create FIB update for new entry
Vince Lehman218be0a2015-01-15 17:25:20 -0600496 if (route.cost <= entry.getRouteWithLowestCostByFaceId(route.faceId)->cost)
Vince Lehman4387e782014-06-19 16:57:45 -0500497 {
Vince Lehman218be0a2015-01-15 17:25:20 -0600498 insertFibUpdate(FibUpdate::createAddUpdate(entry.getName(), route.faceId, route.cost));
Vince Lehman4387e782014-06-19 16:57:45 -0500499 }
500}
501
502void
Vince Lehman218be0a2015-01-15 17:25:20 -0600503Rib::createFibUpdatesForUpdatedRoute(RibEntry& entry, const Route& route,
Vince Lehman4387e782014-06-19 16:57:45 -0500504 const uint64_t previousFlags, const uint64_t previousCost)
505{
Vince Lehman218be0a2015-01-15 17:25:20 -0600506 const bool costDidChange = (route.cost != previousCost);
Vince Lehman4387e782014-06-19 16:57:45 -0500507
Vince Lehman218be0a2015-01-15 17:25:20 -0600508 // Look for the installed route with the lowest cost and child inherit set
509 shared_ptr<Route> prevRoute = entry.getRouteWithLowestCostAndChildInheritByFaceId(route.faceId);
Vince Lehman4387e782014-06-19 16:57:45 -0500510
511 // No flags changed and cost didn't change, no change in FIB
Vince Lehman218be0a2015-01-15 17:25:20 -0600512 if (route.flags == previousFlags && !costDidChange)
Vince Lehman4387e782014-06-19 16:57:45 -0500513 {
514 return;
515 }
516
517 // Cost changed so create update for the entry itself
518 if (costDidChange)
519 {
Vince Lehman218be0a2015-01-15 17:25:20 -0600520 // Create update if this route's cost is lower than other routes
521 if (route.cost <= entry.getRouteWithLowestCostByFaceId(route.faceId)->cost)
Vince Lehman4387e782014-06-19 16:57:45 -0500522 {
523 // Create FIB update for the updated entry
Vince Lehman218be0a2015-01-15 17:25:20 -0600524 insertFibUpdate(FibUpdate::createAddUpdate(entry.getName(), route.faceId, route.cost));
Vince Lehman4387e782014-06-19 16:57:45 -0500525 }
Vince Lehman218be0a2015-01-15 17:25:20 -0600526 else if (previousCost < entry.getRouteWithLowestCostByFaceId(route.faceId)->cost)
Vince Lehman4387e782014-06-19 16:57:45 -0500527 {
Vince Lehman218be0a2015-01-15 17:25:20 -0600528 // Create update if this route used to be the lowest cost route but is no longer
529 // the lowest cost route.
530 insertFibUpdate(FibUpdate::createAddUpdate(entry.getName(), prevRoute->faceId,
531 prevRoute->cost));
Vince Lehman4387e782014-06-19 16:57:45 -0500532 }
533
Vince Lehman218be0a2015-01-15 17:25:20 -0600534 // If another route with same faceId and lower cost and ChildInherit exists,
Vince Lehman4387e782014-06-19 16:57:45 -0500535 // don't update children.
Vince Lehman218be0a2015-01-15 17:25:20 -0600536 if (prevRoute == nullptr || route.cost <= prevRoute->cost)
Vince Lehman4387e782014-06-19 16:57:45 -0500537 {
538 // If no flags changed but child inheritance is set, need to update children
539 // with new cost
Vince Lehman218be0a2015-01-15 17:25:20 -0600540 if ((route.flags == previousFlags) && isChildInheritFlagSet(route.flags))
Vince Lehman4387e782014-06-19 16:57:45 -0500541 {
542 // Add self to children
Vince Lehman218be0a2015-01-15 17:25:20 -0600543 RouteSet routesToAdd;
544 routesToAdd.insert(route);
545 modifyChildrensInheritedRoutes(entry, routesToAdd, RouteSet());
Vince Lehman4387e782014-06-19 16:57:45 -0500546
547 return;
548 }
549 }
550 }
551
552 // Child inherit was turned on
Vince Lehman218be0a2015-01-15 17:25:20 -0600553 if (!isChildInheritFlagSet(previousFlags) && isChildInheritFlagSet(route.flags))
Vince Lehman4387e782014-06-19 16:57:45 -0500554 {
Vince Lehman218be0a2015-01-15 17:25:20 -0600555 // If another route with same faceId and lower cost and ChildInherit exists,
Vince Lehman4387e782014-06-19 16:57:45 -0500556 // don't update children.
Vince Lehman218be0a2015-01-15 17:25:20 -0600557 if (prevRoute == nullptr || route.cost <= prevRoute->cost)
Vince Lehman4387e782014-06-19 16:57:45 -0500558 {
559 // Add self to children
Vince Lehman218be0a2015-01-15 17:25:20 -0600560 RouteSet routesToAdd;
561 routesToAdd.insert(route);
562 modifyChildrensInheritedRoutes(entry, routesToAdd, RouteSet());
Vince Lehman4387e782014-06-19 16:57:45 -0500563 }
564
565 } // Child inherit was turned off
Vince Lehman218be0a2015-01-15 17:25:20 -0600566 else if (isChildInheritFlagSet(previousFlags) && !isChildInheritFlagSet(route.flags))
Vince Lehman4387e782014-06-19 16:57:45 -0500567 {
568 // Remove self from children
Vince Lehman218be0a2015-01-15 17:25:20 -0600569 RouteSet routesToRemove;
570 routesToRemove.insert(route);
Vince Lehman4387e782014-06-19 16:57:45 -0500571
Vince Lehman218be0a2015-01-15 17:25:20 -0600572 RouteSet routesToAdd;
573 // If another route with same faceId and ChildInherit exists, update children with this route.
574 if (prevRoute != nullptr)
Vince Lehman4387e782014-06-19 16:57:45 -0500575 {
Vince Lehman218be0a2015-01-15 17:25:20 -0600576 routesToAdd.insert(*prevRoute);
Vince Lehman4387e782014-06-19 16:57:45 -0500577 }
578 else
579 {
580 // Look for an ancestor that was blocked previously
Vince Lehman218be0a2015-01-15 17:25:20 -0600581 const RouteSet ancestorRoutes = getAncestorRoutes(entry);
582 RouteSet::iterator it = ancestorRoutes.find(route);
Vince Lehman4387e782014-06-19 16:57:45 -0500583
584 // If an ancestor is found, add it to children
Vince Lehman218be0a2015-01-15 17:25:20 -0600585 if (it != ancestorRoutes.end())
Vince Lehman4387e782014-06-19 16:57:45 -0500586 {
Vince Lehman218be0a2015-01-15 17:25:20 -0600587 routesToAdd.insert(*it);
Vince Lehman4387e782014-06-19 16:57:45 -0500588 }
589 }
590
Vince Lehman218be0a2015-01-15 17:25:20 -0600591 modifyChildrensInheritedRoutes(entry, routesToAdd, routesToRemove);
Vince Lehman4387e782014-06-19 16:57:45 -0500592 }
593
594 // Capture was turned on
Vince Lehman218be0a2015-01-15 17:25:20 -0600595 if (!isCaptureFlagSet(previousFlags) && isCaptureFlagSet(route.flags))
Vince Lehman4387e782014-06-19 16:57:45 -0500596 {
Vince Lehman218be0a2015-01-15 17:25:20 -0600597 RouteSet ancestorRoutes = getAncestorRoutes(entry);
Vince Lehman4387e782014-06-19 16:57:45 -0500598
Vince Lehman218be0a2015-01-15 17:25:20 -0600599 // Remove ancestor routes from self
600 removeInheritedRoutesFromEntry(entry, ancestorRoutes);
Vince Lehman4387e782014-06-19 16:57:45 -0500601
Vince Lehman218be0a2015-01-15 17:25:20 -0600602 // Remove ancestor routes from children
603 modifyChildrensInheritedRoutes(entry, RouteSet(), ancestorRoutes);
Vince Lehman4387e782014-06-19 16:57:45 -0500604 } // Capture was turned off
Vince Lehman218be0a2015-01-15 17:25:20 -0600605 else if (isCaptureFlagSet(previousFlags) && !isCaptureFlagSet(route.flags))
Vince Lehman4387e782014-06-19 16:57:45 -0500606 {
Vince Lehman218be0a2015-01-15 17:25:20 -0600607 RouteSet ancestorRoutes = getAncestorRoutes(entry);
Vince Lehman4387e782014-06-19 16:57:45 -0500608
Vince Lehman218be0a2015-01-15 17:25:20 -0600609 // Add ancestor routes to self
610 addInheritedRoutesToEntry(entry, ancestorRoutes);
Vince Lehman4387e782014-06-19 16:57:45 -0500611
Vince Lehman218be0a2015-01-15 17:25:20 -0600612 // Add ancestor routes to children
613 modifyChildrensInheritedRoutes(entry, ancestorRoutes, RouteSet());
Vince Lehman4387e782014-06-19 16:57:45 -0500614 }
615}
616
617void
Vince Lehman218be0a2015-01-15 17:25:20 -0600618Rib::createFibUpdatesForErasedRoute(RibEntry& entry, const Route& route,
619 const bool captureWasTurnedOff)
Vince Lehman4387e782014-06-19 16:57:45 -0500620{
Vince Lehman218be0a2015-01-15 17:25:20 -0600621 insertFibUpdate(FibUpdate::createRemoveUpdate(entry.getName(), route.faceId));
Vince Lehman4387e782014-06-19 16:57:45 -0500622
Vince Lehman218be0a2015-01-15 17:25:20 -0600623 if (areBothFlagsSet(route.flags))
Vince Lehman4387e782014-06-19 16:57:45 -0500624 {
625 // Remove self from children
Vince Lehman218be0a2015-01-15 17:25:20 -0600626 RouteSet routesToRemove;
627 routesToRemove.insert(route);
Vince Lehman4387e782014-06-19 16:57:45 -0500628
629 // If capture is turned off for the route, need to add ancestors
630 // to self and children
Vince Lehman218be0a2015-01-15 17:25:20 -0600631 RouteSet routesToAdd;
Vince Lehman4387e782014-06-19 16:57:45 -0500632 if (captureWasTurnedOff)
633 {
Vince Lehman218be0a2015-01-15 17:25:20 -0600634 // Look for ancestors that were blocked previously
635 routesToAdd = getAncestorRoutes(entry);
Vince Lehman4387e782014-06-19 16:57:45 -0500636
Vince Lehman218be0a2015-01-15 17:25:20 -0600637 // Add ancestor routes to self
638 addInheritedRoutesToEntry(entry, routesToAdd);
Vince Lehman4387e782014-06-19 16:57:45 -0500639 }
640
Vince Lehman218be0a2015-01-15 17:25:20 -0600641 modifyChildrensInheritedRoutes(entry, routesToAdd, routesToRemove);
Vince Lehman4387e782014-06-19 16:57:45 -0500642 }
Vince Lehman218be0a2015-01-15 17:25:20 -0600643 else if (isChildInheritFlagSet(route.flags))
Vince Lehman4387e782014-06-19 16:57:45 -0500644 {
645 // If not blocked by capture, add inherited routes to children
Vince Lehman218be0a2015-01-15 17:25:20 -0600646 RouteSet routesToAdd;
Vince Lehman4387e782014-06-19 16:57:45 -0500647 if (!entry.hasCapture())
648 {
Vince Lehman218be0a2015-01-15 17:25:20 -0600649 routesToAdd = getAncestorRoutes(entry);
Vince Lehman4387e782014-06-19 16:57:45 -0500650 }
651
Vince Lehman218be0a2015-01-15 17:25:20 -0600652 RouteSet routesToRemove;
653 routesToRemove.insert(route);
Vince Lehman4387e782014-06-19 16:57:45 -0500654
Vince Lehman218be0a2015-01-15 17:25:20 -0600655 // Add ancestor routes to children
656 modifyChildrensInheritedRoutes(entry, routesToAdd, routesToRemove);
Vince Lehman4387e782014-06-19 16:57:45 -0500657 }
Vince Lehman218be0a2015-01-15 17:25:20 -0600658 else if (isCaptureFlagSet(route.flags))
Vince Lehman4387e782014-06-19 16:57:45 -0500659 {
660 // If capture is turned off for the route, need to add ancestors
661 // to self and children
Vince Lehman218be0a2015-01-15 17:25:20 -0600662 RouteSet routesToAdd;
Vince Lehman4387e782014-06-19 16:57:45 -0500663 if (captureWasTurnedOff)
664 {
665 // Look for an ancestors that were blocked previously
Vince Lehman218be0a2015-01-15 17:25:20 -0600666 routesToAdd = getAncestorRoutes(entry);
Vince Lehman4387e782014-06-19 16:57:45 -0500667
Vince Lehman218be0a2015-01-15 17:25:20 -0600668 // Add ancestor routes to self
669 addInheritedRoutesToEntry(entry, routesToAdd);
Vince Lehman4387e782014-06-19 16:57:45 -0500670 }
671
Vince Lehman218be0a2015-01-15 17:25:20 -0600672 modifyChildrensInheritedRoutes(entry, routesToAdd, RouteSet());
Vince Lehman4387e782014-06-19 16:57:45 -0500673 }
674
Vince Lehman218be0a2015-01-15 17:25:20 -0600675 // Need to check if the removed route was blocking an inherited route
676 RouteSet ancestorRoutes = getAncestorRoutes(entry);
Vince Lehman4387e782014-06-19 16:57:45 -0500677
678 if (!entry.hasCapture())
679 {
Vince Lehman218be0a2015-01-15 17:25:20 -0600680 // If there is an ancestor route with the same Face ID as the erased route, add that route
Vince Lehman4387e782014-06-19 16:57:45 -0500681 // to the current entry
Vince Lehman218be0a2015-01-15 17:25:20 -0600682 RouteSet::iterator it = ancestorRoutes.find(route);
Vince Lehman4387e782014-06-19 16:57:45 -0500683
Vince Lehman218be0a2015-01-15 17:25:20 -0600684 if (it != ancestorRoutes.end())
Vince Lehman4387e782014-06-19 16:57:45 -0500685 {
Vince Lehman218be0a2015-01-15 17:25:20 -0600686 entry.addInheritedRoute(*it);
Vince Lehman4387e782014-06-19 16:57:45 -0500687 insertFibUpdate(FibUpdate::createAddUpdate(entry.getName(), it->faceId, it->cost));
688 }
689 }
690}
691
692void
693Rib::createFibUpdatesForErasedRibEntry(RibEntry& entry)
694{
Vince Lehman218be0a2015-01-15 17:25:20 -0600695 for (RibEntry::RouteList::iterator it = entry.getInheritedRoutes().begin();
696 it != entry.getInheritedRoutes().end(); ++it)
Vince Lehman4387e782014-06-19 16:57:45 -0500697 {
698 insertFibUpdate(FibUpdate::createRemoveUpdate(entry.getName(), it->faceId));
699 }
700}
701
Vince Lehman218be0a2015-01-15 17:25:20 -0600702Rib::RouteSet
703Rib::getAncestorRoutes(const RibEntry& entry) const
Vince Lehman4387e782014-06-19 16:57:45 -0500704{
Vince Lehman218be0a2015-01-15 17:25:20 -0600705 RouteSet ancestorRoutes(&sortRoutes);
Vince Lehman4387e782014-06-19 16:57:45 -0500706
707 shared_ptr<RibEntry> parent = entry.getParent();
708
709 while (static_cast<bool>(parent))
710 {
Vince Lehman218be0a2015-01-15 17:25:20 -0600711 for (RibEntry::iterator it = parent->getRoutes().begin();
712 it != parent->getRoutes().end(); ++it)
Vince Lehman4387e782014-06-19 16:57:45 -0500713 {
714 if (isChildInheritFlagSet(it->flags))
715 {
Vince Lehman218be0a2015-01-15 17:25:20 -0600716 ancestorRoutes.insert(*it);
Vince Lehman4387e782014-06-19 16:57:45 -0500717 }
718 }
719
720 if (parent->hasCapture())
721 {
722 break;
723 }
724
725 parent = parent->getParent();
726 }
727
Vince Lehman218be0a2015-01-15 17:25:20 -0600728 return ancestorRoutes;
Vince Lehman4387e782014-06-19 16:57:45 -0500729}
730
731void
Vince Lehman218be0a2015-01-15 17:25:20 -0600732Rib::addInheritedRoutesToEntry(RibEntry& entry, const Rib::RouteSet& routesToAdd)
Vince Lehman4387e782014-06-19 16:57:45 -0500733{
Vince Lehman218be0a2015-01-15 17:25:20 -0600734 for (RouteSet::const_iterator it = routesToAdd.begin(); it != routesToAdd.end(); ++it)
Vince Lehman4387e782014-06-19 16:57:45 -0500735 {
Vince Lehman218be0a2015-01-15 17:25:20 -0600736 // Don't add an ancestor route if the namespace has a route with that Face ID
Vince Lehman4387e782014-06-19 16:57:45 -0500737 if (!entry.hasFaceId(it->faceId))
738 {
Vince Lehman218be0a2015-01-15 17:25:20 -0600739 entry.addInheritedRoute(*it);
Vince Lehman4387e782014-06-19 16:57:45 -0500740 insertFibUpdate(FibUpdate::createAddUpdate(entry.getName(), it->faceId, it->cost));
741 }
742 }
743}
744
745void
Vince Lehman218be0a2015-01-15 17:25:20 -0600746Rib::removeInheritedRoutesFromEntry(RibEntry& entry, const Rib::RouteSet& routesToRemove)
Vince Lehman4387e782014-06-19 16:57:45 -0500747{
Vince Lehman218be0a2015-01-15 17:25:20 -0600748 for (RouteSet::const_iterator it = routesToRemove.begin(); it != routesToRemove.end(); ++it)
Vince Lehman4387e782014-06-19 16:57:45 -0500749 {
Vince Lehman218be0a2015-01-15 17:25:20 -0600750 // Only remove if the route has been inherited
751 if (entry.hasInheritedRoute(*it))
Vince Lehman4387e782014-06-19 16:57:45 -0500752 {
Vince Lehman218be0a2015-01-15 17:25:20 -0600753 entry.removeInheritedRoute(*it);
Vince Lehman4387e782014-06-19 16:57:45 -0500754 insertFibUpdate(FibUpdate::createRemoveUpdate(entry.getName(), it->faceId));
755 }
756 }
757}
758
759void
Vince Lehman218be0a2015-01-15 17:25:20 -0600760Rib::modifyChildrensInheritedRoutes(RibEntry& entry, const Rib::RouteSet& routesToAdd,
761 const Rib::RouteSet& routesToRemove)
Vince Lehman4387e782014-06-19 16:57:45 -0500762{
763 RibEntryList children = entry.getChildren();
764
765 for (RibEntryList::iterator child = children.begin(); child != children.end(); ++child)
766 {
Vince Lehman218be0a2015-01-15 17:25:20 -0600767 traverseSubTree(*(*child), routesToAdd, routesToRemove);
Vince Lehman4387e782014-06-19 16:57:45 -0500768 }
769}
770
771void
Vince Lehman218be0a2015-01-15 17:25:20 -0600772Rib::traverseSubTree(RibEntry& entry, Rib::RouteSet routesToAdd, Rib::RouteSet routesToRemove)
Vince Lehman4387e782014-06-19 16:57:45 -0500773{
774 // If a route on the namespace has the capture flag set, ignore self and children
775 if (entry.hasCapture())
776 {
777 return;
778 }
779
Vince Lehman218be0a2015-01-15 17:25:20 -0600780 // Remove inherited routes from current namespace
781 for (Rib::RouteSet::const_iterator removeIt = routesToRemove.begin();
782 removeIt != routesToRemove.end(); )
Vince Lehman4387e782014-06-19 16:57:45 -0500783 {
Vince Lehman218be0a2015-01-15 17:25:20 -0600784 // If a route on the namespace has the same face and child inheritance set, ignore this route
Vince Lehman4387e782014-06-19 16:57:45 -0500785 if (entry.hasChildInheritOnFaceId(removeIt->faceId))
786 {
Vince Lehman218be0a2015-01-15 17:25:20 -0600787 routesToRemove.erase(removeIt++);
Vince Lehman4387e782014-06-19 16:57:45 -0500788 continue;
789 }
790
Vince Lehman218be0a2015-01-15 17:25:20 -0600791 // Only remove route if it removes an existing inherited route
792 if (entry.hasInheritedRoute(*removeIt))
Vince Lehman4387e782014-06-19 16:57:45 -0500793 {
Vince Lehman218be0a2015-01-15 17:25:20 -0600794 entry.removeInheritedRoute(*removeIt);
Vince Lehman4387e782014-06-19 16:57:45 -0500795 insertFibUpdate(FibUpdate::createRemoveUpdate(entry.getName(), removeIt->faceId));
796 }
797
798 ++removeIt;
799 }
800
Vince Lehman218be0a2015-01-15 17:25:20 -0600801 // Add inherited routes to current namespace
802 for (Rib::RouteSet::const_iterator addIt = routesToAdd.begin(); addIt != routesToAdd.end(); )
Vince Lehman4387e782014-06-19 16:57:45 -0500803 {
Vince Lehman218be0a2015-01-15 17:25:20 -0600804 // If a route on the namespace has the same face and child inherit set, ignore this route
Vince Lehman4387e782014-06-19 16:57:45 -0500805 if (entry.hasChildInheritOnFaceId(addIt->faceId))
806 {
Vince Lehman218be0a2015-01-15 17:25:20 -0600807 routesToAdd.erase(addIt++);
Vince Lehman4387e782014-06-19 16:57:45 -0500808 continue;
809 }
810
Vince Lehman218be0a2015-01-15 17:25:20 -0600811 // Only add route if it does not override an existing route
Vince Lehman4387e782014-06-19 16:57:45 -0500812 if (!entry.hasFaceId(addIt->faceId))
813 {
Vince Lehman218be0a2015-01-15 17:25:20 -0600814 RibEntry::RouteList::iterator routeIt = entry.findInheritedRoute(*addIt);
Vince Lehman4387e782014-06-19 16:57:45 -0500815
Vince Lehman218be0a2015-01-15 17:25:20 -0600816 // If the entry already has the inherited route, just update the route
817 if (routeIt != entry.getInheritedRoutes().end())
Vince Lehman4387e782014-06-19 16:57:45 -0500818 {
Vince Lehman218be0a2015-01-15 17:25:20 -0600819 routeIt->cost = addIt->cost;
Vince Lehman4387e782014-06-19 16:57:45 -0500820 }
Vince Lehman218be0a2015-01-15 17:25:20 -0600821 else // Otherwise, this is a newly inherited route
Vince Lehman4387e782014-06-19 16:57:45 -0500822 {
Vince Lehman218be0a2015-01-15 17:25:20 -0600823 entry.addInheritedRoute(*addIt);
Vince Lehman4387e782014-06-19 16:57:45 -0500824 }
825
826 insertFibUpdate(FibUpdate::createAddUpdate(entry.getName(), addIt->faceId, addIt->cost));
827 }
828
829 ++addIt;
830 }
831
832 Rib::RibEntryList children = entry.getChildren();
833
Vince Lehman218be0a2015-01-15 17:25:20 -0600834 // Apply route operations to current namespace's children
Vince Lehman4387e782014-06-19 16:57:45 -0500835 for (Rib::RibEntryList::iterator child = children.begin(); child != children.end(); ++child)
836 {
Vince Lehman218be0a2015-01-15 17:25:20 -0600837 traverseSubTree(*(*child), routesToAdd, routesToRemove);
Vince Lehman4387e782014-06-19 16:57:45 -0500838 }
839}
840
Alexander Afanasyev20d31442014-04-19 17:00:53 -0700841std::ostream&
Vince12e49462014-06-09 13:29:32 -0500842operator<<(std::ostream& os, const Rib& rib)
Alexander Afanasyev20d31442014-04-19 17:00:53 -0700843{
Vince12e49462014-06-09 13:29:32 -0500844 for (Rib::RibTable::const_iterator it = rib.begin(); it != rib.end(); ++it)
845 {
846 os << *(it->second) << "\n";
847 }
Alexander Afanasyev20d31442014-04-19 17:00:53 -0700848
849 return os;
850}
851
Alexander Afanasyev3ecec502014-04-16 13:42:44 -0700852} // namespace rib
853} // namespace nfd