blob: 02df45ede8d4cec95aab4311c5763eb4aafe5f1b [file] [log] [blame]
Alexander Afanasyev3ecec502014-04-16 13:42:44 -07001/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
2/**
Vince12e49462014-06-09 13:29:32 -05003 * Copyright (c) 2014, 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
36sortFace(const FaceEntry& entry1, const FaceEntry& entry2)
37{
38 return entry1.faceId < entry2.faceId;
39}
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
Syed Obaid3313a372014-07-01 01:31:33 -050076FaceEntry*
Vince12e49462014-06-09 13:29:32 -050077Rib::find(const Name& prefix, const FaceEntry& face) const
78{
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 {
Vince12e49462014-06-09 13:29:32 -050084 shared_ptr<RibEntry> entry(ribIt->second);
85
Syed Obaid3313a372014-07-01 01:31:33 -050086 RibEntry::iterator faceIt = std::find_if(entry->begin(), entry->end(),
Vince12e49462014-06-09 13:29:32 -050087 bind(&compareFaceIdAndOrigin, _1, face));
88
89 if (faceIt != entry->end())
90 {
Syed Obaid3313a372014-07-01 01:31:33 -050091 return &((*faceIt));
Vince12e49462014-06-09 13:29:32 -050092 }
Alexander Afanasyev3ecec502014-04-16 13:42:44 -070093 }
Syed Obaid3313a372014-07-01 01:31:33 -050094 return 0;
Alexander Afanasyev3ecec502014-04-16 13:42:44 -070095}
96
Alexander Afanasyev3ecec502014-04-16 13:42:44 -070097void
Vince12e49462014-06-09 13:29:32 -050098Rib::insert(const Name& prefix, const FaceEntry& face)
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
107 RibEntry::iterator faceIt = std::find_if(entry->getFaces().begin(),
108 entry->getFaces().end(),
109 bind(&compareFaceIdAndOrigin, _1, face));
110
111 if (faceIt == entry->end())
112 {
Vince Lehman4387e782014-06-19 16:57:45 -0500113 // Will the new face change the namespace's capture flag?
114 bool captureWasTurnedOn = (entry->hasCapture() == false && isCaptureFlagSet(face.flags));
115
Vince12e49462014-06-09 13:29:32 -0500116 // New face
117 entry->insertFace(face);
118 m_nItems++;
119
120 // Register with face lookup table
121 m_faceMap[face.faceId].push_back(entry);
Vince Lehman4387e782014-06-19 16:57:45 -0500122
123 createFibUpdatesForNewFaceEntry(*entry, face, captureWasTurnedOn);
Vince12e49462014-06-09 13:29:32 -0500124 }
Vince Lehman4387e782014-06-19 16:57:45 -0500125 else // Entry exists, update fields
Vince12e49462014-06-09 13:29:32 -0500126 {
Syed Obaid3313a372014-07-01 01:31:33 -0500127 // First cancel old scheduled event, if any, then set the EventId to new one
128 if (static_cast<bool>(faceIt->getExpirationEvent()))
Vince Lehman281ded72014-08-21 12:17:08 -0500129 {
130 NFD_LOG_TRACE("Cancelling expiration event for " << entry->getName() << " "
131 << *faceIt);
Syed Obaid3313a372014-07-01 01:31:33 -0500132 scheduler::cancel(faceIt->getExpirationEvent());
Vince Lehman281ded72014-08-21 12:17:08 -0500133 }
Syed Obaid3313a372014-07-01 01:31:33 -0500134
135 // No checks are required here as the iterator needs to be updated in all cases.
136 faceIt->setExpirationEvent(face.getExpirationEvent());
137
Vince Lehman4387e782014-06-19 16:57:45 -0500138 // Save flags for update processing
139 uint64_t previousFlags = faceIt->flags;
140
141 // If the entry's cost didn't change and child inherit is not set,
142 // no need to traverse subtree.
143 uint64_t previousCost = faceIt->cost;
144
Vince12e49462014-06-09 13:29:32 -0500145 faceIt->flags = face.flags;
146 faceIt->cost = face.cost;
147 faceIt->expires = face.expires;
Vince Lehman4387e782014-06-19 16:57:45 -0500148
149 createFibUpdatesForUpdatedEntry(*entry, face, previousFlags, previousCost);
Vince12e49462014-06-09 13:29:32 -0500150 }
Alexander Afanasyev3ecec502014-04-16 13:42:44 -0700151 }
Vince12e49462014-06-09 13:29:32 -0500152 else // New name prefix
Alexander Afanasyev3ecec502014-04-16 13:42:44 -0700153 {
Vince12e49462014-06-09 13:29:32 -0500154 shared_ptr<RibEntry> entry(make_shared<RibEntry>(RibEntry()));
155
156 m_rib[prefix] = entry;
157 m_nItems++;
158
159 entry->setName(prefix);
160 entry->insertFace(face);
161
162 // Find prefix's parent
163 shared_ptr<RibEntry> parent = findParent(prefix);
164
165 // Add self to parent's children
166 if (static_cast<bool>(parent))
167 {
168 parent->addChild(entry);
169 }
170
171 RibEntryList children = findDescendants(prefix);
172
173 for (std::list<shared_ptr<RibEntry> >::iterator child = children.begin();
174 child != children.end(); ++child)
175 {
176 if ((*child)->getParent() == parent)
177 {
178 // Remove child from parent and inherit parent's child
179 if (static_cast<bool>(parent))
180 {
181 parent->removeChild((*child));
182 }
Vince12e49462014-06-09 13:29:32 -0500183 entry->addChild((*child));
184 }
185 }
186
187 // Register with face lookup table
188 m_faceMap[face.faceId].push_back(entry);
Vince Lehman4387e782014-06-19 16:57:45 -0500189
190 createFibUpdatesForNewRibEntry(*entry, face);
Yanbiao Lic17de832014-11-21 17:51:45 -0800191
192 // do something after inserting an entry
193 afterInsertEntry(prefix);
Alexander Afanasyev3ecec502014-04-16 13:42:44 -0700194 }
195}
196
Alexander Afanasyev3ecec502014-04-16 13:42:44 -0700197void
Vince12e49462014-06-09 13:29:32 -0500198Rib::erase(const Name& prefix, const FaceEntry& face)
Alexander Afanasyev3ecec502014-04-16 13:42:44 -0700199{
Vince12e49462014-06-09 13:29:32 -0500200 RibTable::iterator ribIt = m_rib.find(prefix);
201
202 // Name prefix exists
203 if (ribIt != m_rib.end())
204 {
205 shared_ptr<RibEntry> entry(ribIt->second);
206
Vince Lehman4387e782014-06-19 16:57:45 -0500207 const bool hadCapture = entry->hasCapture();
208
209 // Need to copy face to do FIB updates with correct cost and flags since nfdc does not
210 // pass flags or cost
211 RibEntry::iterator faceIt = entry->findFace(face);
Vince Lehman4387e782014-06-19 16:57:45 -0500212
213 if (faceIt != entry->end())
Vince12e49462014-06-09 13:29:32 -0500214 {
Syed Obaid3313a372014-07-01 01:31:33 -0500215 FaceEntry faceToErase = *faceIt;
216 faceToErase.flags = faceIt->flags;
217 faceToErase.cost = faceIt->cost;
218
Vince Lehman4387e782014-06-19 16:57:45 -0500219 entry->eraseFace(faceIt);
Vince Lehman281ded72014-08-21 12:17:08 -0500220
Vince12e49462014-06-09 13:29:32 -0500221 m_nItems--;
222
Vince Lehman4387e782014-06-19 16:57:45 -0500223 const bool captureWasTurnedOff = (hadCapture && !entry->hasCapture());
224
225 createFibUpdatesForErasedFaceEntry(*entry, faceToErase, captureWasTurnedOff);
226
Vince12e49462014-06-09 13:29:32 -0500227 // If this RibEntry no longer has this faceId, unregister from face lookup table
228 if (!entry->hasFaceId(face.faceId))
229 {
230 m_faceMap[face.faceId].remove(entry);
231 }
Vince Lehman4387e782014-06-19 16:57:45 -0500232 else
233 {
234 // The RibEntry still has the face ID; need to update FIB
235 // with lowest cost for the same face instead of removing the face from the FIB
236 shared_ptr<FaceEntry> lowCostFace = entry->getFaceWithLowestCostByFaceId(face.faceId);
237
238 BOOST_ASSERT(static_cast<bool>(lowCostFace));
239
240 createFibUpdatesForNewFaceEntry(*entry, *lowCostFace, false);
241 }
Vince12e49462014-06-09 13:29:32 -0500242
243 // If a RibEntry's facelist is empty, remove it from the tree
244 if (entry->getFaces().size() == 0)
245 {
246 eraseEntry(ribIt);
247 }
248 }
249 }
250}
251
252void
253Rib::erase(const uint64_t faceId)
254{
255 FaceLookupTable::iterator lookupIt = m_faceMap.find(faceId);
256
257 // No RIB entries have this face
258 if (lookupIt == m_faceMap.end())
259 {
260 return;
261 }
262
263 RibEntryList& ribEntries = lookupIt->second;
264
265 // For each RIB entry that has faceId, remove the face from the entry
266 for (RibEntryList::iterator entryIt = ribEntries.begin(); entryIt != ribEntries.end(); ++entryIt)
267 {
268 shared_ptr<RibEntry> entry = *entryIt;
269
Vince Lehman4387e782014-06-19 16:57:45 -0500270 const bool hadCapture = entry->hasCapture();
271
Vince12e49462014-06-09 13:29:32 -0500272 // Find the faces in the entry
273 for (RibEntry::iterator faceIt = entry->begin(); faceIt != entry->end(); ++faceIt)
274 {
275 if (faceIt->faceId == faceId)
276 {
Vince Lehman4387e782014-06-19 16:57:45 -0500277 FaceEntry copy = *faceIt;
278
Vince12e49462014-06-09 13:29:32 -0500279 faceIt = entry->eraseFace(faceIt);
Vince Lehman26b215c2014-08-17 15:00:41 -0500280 m_nItems--;
Vince Lehman4387e782014-06-19 16:57:45 -0500281
282 const bool captureWasTurnedOff = (hadCapture && !entry->hasCapture());
283 createFibUpdatesForErasedFaceEntry(*entry, copy, captureWasTurnedOff);
Vince12e49462014-06-09 13:29:32 -0500284 }
285 }
286
287 // If a RibEntry's facelist is empty, remove it from the tree
288 if (entry->getFaces().size() == 0)
289 {
290 eraseEntry(m_rib.find(entry->getName()));
291 }
292 }
293
294 // Face no longer exists, remove from face lookup table
295 FaceLookupTable::iterator entryToDelete = m_faceMap.find(faceId);
296
297 if (entryToDelete != m_faceMap.end())
298 {
299 m_faceMap.erase(entryToDelete);
300 }
301}
302
303shared_ptr<RibEntry>
304Rib::findParent(const Name& prefix) const
305{
306 for (int i = prefix.size() - 1; i >= 0; i--)
307 {
308 RibTable::const_iterator it = m_rib.find(prefix.getPrefix(i));
309 if (it != m_rib.end())
310 {
311 return (it->second);
312 }
313 }
314
315 return shared_ptr<RibEntry>();
316}
317
318std::list<shared_ptr<RibEntry> >
319Rib::findDescendants(const Name& prefix) const
320{
321 std::list<shared_ptr<RibEntry> > children;
322
323 RibTable::const_iterator it = m_rib.find(prefix);
324
Alexander Afanasyev3ecec502014-04-16 13:42:44 -0700325 if (it != m_rib.end())
326 {
Vince12e49462014-06-09 13:29:32 -0500327 ++it;
328 for (; it != m_rib.end(); ++it)
329 {
330 if (prefix.isPrefixOf(it->first))
331 {
332 children.push_back((it->second));
333 }
334 else
335 {
336 break;
337 }
338 }
Alexander Afanasyev3ecec502014-04-16 13:42:44 -0700339 }
Vince12e49462014-06-09 13:29:32 -0500340
341 return children;
Alexander Afanasyev3ecec502014-04-16 13:42:44 -0700342}
343
Vince12e49462014-06-09 13:29:32 -0500344Rib::RibTable::iterator
345Rib::eraseEntry(RibTable::iterator it)
Alexander Afanasyev3ecec502014-04-16 13:42:44 -0700346{
Vince12e49462014-06-09 13:29:32 -0500347 // Entry does not exist
348 if (it == m_rib.end())
349 {
350 return m_rib.end();
351 }
352
353 shared_ptr<RibEntry> entry(it->second);
354
Vince Lehman4387e782014-06-19 16:57:45 -0500355 // Remove inherited routes from namespace
356 createFibUpdatesForErasedRibEntry(*entry);
357
Vince12e49462014-06-09 13:29:32 -0500358 shared_ptr<RibEntry> parent = entry->getParent();
359
360 // Remove self from parent's children
361 if (static_cast<bool>(parent))
362 {
363 parent->removeChild(entry);
364 }
365
366 std::list<shared_ptr<RibEntry> > children = entry->getChildren();
367
368 for (RibEntryList::iterator child = children.begin(); child != children.end(); ++child)
369 {
370 // Remove children from self
371 entry->removeChild(*child);
372
373 // Update parent's children
374 if (static_cast<bool>(parent))
375 {
376 parent->addChild(*child);
377 }
378 }
379
380 // Must save and advance iterator to return a valid iterator
381 RibTable::iterator nextIt = it;
382 nextIt++;
383
384 m_rib.erase(it);
385
Yanbiao Lic17de832014-11-21 17:51:45 -0800386 // do something after erasing an entry.
387 afterEraseEntry(entry->getName());
388
Vince12e49462014-06-09 13:29:32 -0500389 return nextIt;
Alexander Afanasyev3ecec502014-04-16 13:42:44 -0700390}
391
Vince Lehman4387e782014-06-19 16:57:45 -0500392bool
393compareFibUpdates(const shared_ptr<const FibUpdate> lhs, const shared_ptr<const FibUpdate> rhs)
394{
395 return ((lhs->name == rhs->name) &&
396 (lhs->faceId == rhs->faceId));
397}
398
399void
400Rib::insertFibUpdate(shared_ptr<FibUpdate> update)
401{
402 // If an update with the same name and face already exists,
403 // replace it
404 FibUpdateList::iterator it = std::find_if(m_fibUpdateList.begin(), m_fibUpdateList.end(),
405 bind(&compareFibUpdates, _1, update));
406
407 if (it != m_fibUpdateList.end())
408 {
409 // Get rid of the const to alter the action, prevents copying or removal and
410 // insertion
411 FibUpdate& entry = const_cast<FibUpdate&>(*(*it));
412 entry.action = update->action;
413 entry.cost = update->cost;
414 }
415 else
416 {
417 m_fibUpdateList.push_back(update);
418 }
419}
420
421void
422Rib::createFibUpdatesForNewRibEntry(RibEntry& entry, const FaceEntry& face)
423{
424 // Create FIB update for new entry
425 insertFibUpdate(FibUpdate::createAddUpdate(entry.getName(), face.faceId, face.cost));
426
427 // No flags are set
428 if (!isAnyFlagSet(face.flags))
429 {
430 // Add ancestor faces to self
431 addInheritedFacesToEntry(entry, getAncestorFaces(entry));
432 }
433 else if (areBothFlagsSet(face.flags))
434 {
435 // Add face to children
436 FaceSet facesToAdd;
437 facesToAdd.insert(face);
438
439 // Remove faces blocked by capture and add self to children
440 modifyChildrensInheritedFaces(entry, facesToAdd, getAncestorFaces(entry));
441 }
442 else if (isChildInheritFlagSet(face.flags))
443 {
444 FaceSet ancestorFaces = getAncestorFaces(entry);
445
446 // Add ancestor faces to self
447 addInheritedFacesToEntry(entry, ancestorFaces);
448
449 // If there is an ancestor face which is the same as the new face, replace it
450 // with the new face
451 FaceSet::iterator it = ancestorFaces.find(face);
452
453 // There is a face that needs to be overwritten, erase and then replace
454 if (it != ancestorFaces.end())
455 {
456 ancestorFaces.erase(it);
457 }
458
459 // Add new face to ancestor list so it can be added to children
460 ancestorFaces.insert(face);
461
462 // Add ancestor faces to children
463 modifyChildrensInheritedFaces(entry, ancestorFaces, FaceSet());
464 }
465 else if (isCaptureFlagSet(face.flags))
466 {
467 // Remove faces blocked by capture
468 modifyChildrensInheritedFaces(entry, FaceSet(), getAncestorFaces(entry));
469 }
470}
471
472void
473Rib::createFibUpdatesForNewFaceEntry(RibEntry& entry, const FaceEntry& face,
474 bool captureWasTurnedOn)
475{
476 // Only update if the new face has a lower cost than a previously installed face
477 shared_ptr<FaceEntry> prevFace = entry.getFaceWithLowestCostAndChildInheritByFaceId(face.faceId);
478
479 FaceSet facesToAdd;
480 if (isChildInheritFlagSet(face.flags))
481 {
482 // Add to children if this new face doesn't override a previous lower cost, or
483 // add to children if this new is lower cost than a previous face.
484 // Less than equal, since entry may find this face
485 if (!static_cast<bool>(prevFace) || face.cost <= prevFace->cost)
486 {
487 // Add self to children
488 facesToAdd.insert(face);
489 }
490 }
491
492 FaceSet facesToRemove;
493 if (captureWasTurnedOn)
494 {
495 // Capture flag on
496 facesToRemove = getAncestorFaces(entry);
497
498 // Remove ancestor faces from self
499 removeInheritedFacesFromEntry(entry, facesToRemove);
500 }
501
502 modifyChildrensInheritedFaces(entry, facesToAdd, facesToRemove);
503
504 // If another face with same faceId and lower cost, don't update.
505 // Must be done last so that add updates replace removal updates
506 // Create FIB update for new entry
507 if (face.cost <= entry.getFaceWithLowestCostByFaceId(face.faceId)->cost)
508 {
509 insertFibUpdate(FibUpdate::createAddUpdate(entry.getName(), face.faceId, face.cost));
510 }
511}
512
513void
514Rib::createFibUpdatesForUpdatedEntry(RibEntry& entry, const FaceEntry& face,
515 const uint64_t previousFlags, const uint64_t previousCost)
516{
517 const bool costDidChange = (face.cost != previousCost);
518
519 // Look for an installed face with the lowest cost and child inherit set
520 shared_ptr<FaceEntry> prevFace = entry.getFaceWithLowestCostAndChildInheritByFaceId(face.faceId);
521
522 // No flags changed and cost didn't change, no change in FIB
523 if (face.flags == previousFlags && !costDidChange)
524 {
525 return;
526 }
527
528 // Cost changed so create update for the entry itself
529 if (costDidChange)
530 {
531 // Create update if this face's cost is lower than other faces
532 if (face.cost <= entry.getFaceWithLowestCostByFaceId(face.faceId)->cost)
533 {
534 // Create FIB update for the updated entry
535 insertFibUpdate(FibUpdate::createAddUpdate(entry.getName(), face.faceId, face.cost));
536 }
537 else if (previousCost < entry.getFaceWithLowestCostByFaceId(face.faceId)->cost)
538 {
539 // Create update if this face used to be the lowest face but is no longer
540 // the lowest cost face.
541 insertFibUpdate(FibUpdate::createAddUpdate(entry.getName(), prevFace->faceId,
542 prevFace->cost));
543 }
544
545 // If another face with same faceId and lower cost and ChildInherit exists,
546 // don't update children.
547 if (!static_cast<bool>(prevFace) || face.cost <= prevFace->cost)
548 {
549 // If no flags changed but child inheritance is set, need to update children
550 // with new cost
551 if ((face.flags == previousFlags) && isChildInheritFlagSet(face.flags))
552 {
553 // Add self to children
554 FaceSet facesToAdd;
555 facesToAdd.insert(face);
556 modifyChildrensInheritedFaces(entry, facesToAdd, FaceSet());
557
558 return;
559 }
560 }
561 }
562
563 // Child inherit was turned on
564 if (!isChildInheritFlagSet(previousFlags) && isChildInheritFlagSet(face.flags))
565 {
566 // If another face with same faceId and lower cost and ChildInherit exists,
567 // don't update children.
568 if (!static_cast<bool>(prevFace) || face.cost <= prevFace->cost)
569 {
570 // Add self to children
571 FaceSet facesToAdd;
572 facesToAdd.insert(face);
573 modifyChildrensInheritedFaces(entry, facesToAdd, FaceSet());
574 }
575
576 } // Child inherit was turned off
577 else if (isChildInheritFlagSet(previousFlags) && !isChildInheritFlagSet(face.flags))
578 {
579 // Remove self from children
580 FaceSet facesToRemove;
581 facesToRemove.insert(face);
582
583 FaceSet facesToAdd;
584 // If another face with same faceId and ChildInherit exists, update children with this face.
585 if (static_cast<bool>(prevFace))
586 {
587 facesToAdd.insert(*prevFace);
588 }
589 else
590 {
591 // Look for an ancestor that was blocked previously
592 const FaceSet ancestorFaces = getAncestorFaces(entry);
593 FaceSet::iterator it = ancestorFaces.find(face);
594
595 // If an ancestor is found, add it to children
596 if (it != ancestorFaces.end())
597 {
598 facesToAdd.insert(*it);
599 }
600 }
601
602 modifyChildrensInheritedFaces(entry, facesToAdd, facesToRemove);
603 }
604
605 // Capture was turned on
606 if (!isCaptureFlagSet(previousFlags) && isCaptureFlagSet(face.flags))
607 {
608 FaceSet ancestorFaces = getAncestorFaces(entry);
609
610 // Remove ancestor faces from self
611 removeInheritedFacesFromEntry(entry, ancestorFaces);
612
613 // Remove ancestor faces from children
614 modifyChildrensInheritedFaces(entry, FaceSet(), ancestorFaces);
615 } // Capture was turned off
616 else if (isCaptureFlagSet(previousFlags) && !isCaptureFlagSet(face.flags))
617 {
618 FaceSet ancestorFaces = getAncestorFaces(entry);
619
620 // Add ancestor faces to self
621 addInheritedFacesToEntry(entry, ancestorFaces);
622
623 // Add ancestor faces to children
624 modifyChildrensInheritedFaces(entry, ancestorFaces, FaceSet());
625 }
626}
627
628void
629Rib::createFibUpdatesForErasedFaceEntry(RibEntry& entry, const FaceEntry& face,
630 const bool captureWasTurnedOff)
631{
632 insertFibUpdate(FibUpdate::createRemoveUpdate(entry.getName(), face.faceId));
633
634 if (areBothFlagsSet(face.flags))
635 {
636 // Remove self from children
637 FaceSet facesToRemove;
638 facesToRemove.insert(face);
639
640 // If capture is turned off for the route, need to add ancestors
641 // to self and children
642 FaceSet facesToAdd;
643 if (captureWasTurnedOff)
644 {
645 // Look for an ancestors that were blocked previously
646 facesToAdd = getAncestorFaces(entry);
647
648 // Add ancestor faces to self
649 addInheritedFacesToEntry(entry, facesToAdd);
650 }
651
652 modifyChildrensInheritedFaces(entry, facesToAdd, facesToRemove);
653 }
654 else if (isChildInheritFlagSet(face.flags))
655 {
656 // If not blocked by capture, add inherited routes to children
657 FaceSet facesToAdd;
658 if (!entry.hasCapture())
659 {
660 facesToAdd = getAncestorFaces(entry);
661 }
662
663 FaceSet facesToRemove;
664 facesToRemove.insert(face);
665
666 // Add ancestor faces to children
667 modifyChildrensInheritedFaces(entry, facesToAdd, facesToRemove);
668 }
669 else if (isCaptureFlagSet(face.flags))
670 {
671 // If capture is turned off for the route, need to add ancestors
672 // to self and children
673 FaceSet facesToAdd;
674 if (captureWasTurnedOff)
675 {
676 // Look for an ancestors that were blocked previously
677 facesToAdd = getAncestorFaces(entry);
678
679 // Add ancestor faces to self
680 addInheritedFacesToEntry(entry, facesToAdd);
681 }
682
683 modifyChildrensInheritedFaces(entry, facesToAdd, FaceSet());
684 }
685
686 // Need to check if the removed face was blocking an inherited route
687 FaceSet ancestorFaces = getAncestorFaces(entry);
688
689 if (!entry.hasCapture())
690 {
691 // If there is an ancestor face which is the same as the erased face, add that face
692 // to the current entry
693 FaceSet::iterator it = ancestorFaces.find(face);
694
695 if (it != ancestorFaces.end())
696 {
697 entry.addInheritedFace(*it);
698 insertFibUpdate(FibUpdate::createAddUpdate(entry.getName(), it->faceId, it->cost));
699 }
700 }
701}
702
703void
704Rib::createFibUpdatesForErasedRibEntry(RibEntry& entry)
705{
706 for (RibEntry::FaceList::iterator it = entry.getInheritedFaces().begin();
707 it != entry.getInheritedFaces().end(); ++it)
708 {
709 insertFibUpdate(FibUpdate::createRemoveUpdate(entry.getName(), it->faceId));
710 }
711}
712
713Rib::FaceSet
714Rib::getAncestorFaces(const RibEntry& entry) const
715{
716 FaceSet ancestorFaces(&sortFace);
717
718 shared_ptr<RibEntry> parent = entry.getParent();
719
720 while (static_cast<bool>(parent))
721 {
722 for (RibEntry::iterator it = parent->getFaces().begin();
723 it != parent->getFaces().end(); ++it)
724 {
725 if (isChildInheritFlagSet(it->flags))
726 {
727 ancestorFaces.insert(*it);
728 }
729 }
730
731 if (parent->hasCapture())
732 {
733 break;
734 }
735
736 parent = parent->getParent();
737 }
738
739 return ancestorFaces;
740}
741
742void
743Rib::addInheritedFacesToEntry(RibEntry& entry, const Rib::FaceSet& facesToAdd)
744{
745 for (FaceSet::const_iterator it = facesToAdd.begin(); it != facesToAdd.end(); ++it)
746 {
747 // Don't add an ancestor faceId if the namespace has an entry for that faceId
748 if (!entry.hasFaceId(it->faceId))
749 {
750 entry.addInheritedFace(*it);
751 insertFibUpdate(FibUpdate::createAddUpdate(entry.getName(), it->faceId, it->cost));
752 }
753 }
754}
755
756void
757Rib::removeInheritedFacesFromEntry(RibEntry& entry, const Rib::FaceSet& facesToRemove)
758{
759 for (FaceSet::const_iterator it = facesToRemove.begin(); it != facesToRemove.end(); ++it)
760 {
761 // Only remove if the face has been inherited
762 if (entry.hasInheritedFace(*it))
763 {
764 entry.removeInheritedFace(*it);
765 insertFibUpdate(FibUpdate::createRemoveUpdate(entry.getName(), it->faceId));
766 }
767 }
768}
769
770void
771Rib::modifyChildrensInheritedFaces(RibEntry& entry, const Rib::FaceSet& facesToAdd,
772 const Rib::FaceSet& facesToRemove)
773{
774 RibEntryList children = entry.getChildren();
775
776 for (RibEntryList::iterator child = children.begin(); child != children.end(); ++child)
777 {
778 traverseSubTree(*(*child), facesToAdd, facesToRemove);
779 }
780}
781
782void
783Rib::traverseSubTree(RibEntry& entry, Rib::FaceSet facesToAdd,
784 Rib::FaceSet facesToRemove)
785{
786 // If a route on the namespace has the capture flag set, ignore self and children
787 if (entry.hasCapture())
788 {
789 return;
790 }
791
792 // Remove inherited faces from current namespace
793 for (Rib::FaceSet::const_iterator removeIt = facesToRemove.begin();
794 removeIt != facesToRemove.end(); )
795 {
796 // If a route on the namespace has the same face and child inheritance set, ignore this face
797 if (entry.hasChildInheritOnFaceId(removeIt->faceId))
798 {
799 facesToRemove.erase(removeIt++);
800 continue;
801 }
802
803 // Only remove face if it removes an existing inherited route
804 if (entry.hasInheritedFace(*removeIt))
805 {
806 entry.removeInheritedFace(*removeIt);
807 insertFibUpdate(FibUpdate::createRemoveUpdate(entry.getName(), removeIt->faceId));
808 }
809
810 ++removeIt;
811 }
812
813 // Add inherited faces to current namespace
814 for (Rib::FaceSet::const_iterator addIt = facesToAdd.begin();
815 addIt != facesToAdd.end(); )
816 {
817 // If a route on the namespace has the same face and child inherit set, ignore this face
818 if (entry.hasChildInheritOnFaceId(addIt->faceId))
819 {
820 facesToAdd.erase(addIt++);
821 continue;
822 }
823
824 // Only add face if it does not override an existing route
825 if (!entry.hasFaceId(addIt->faceId))
826 {
827 RibEntry::FaceList::iterator faceIt = entry.findInheritedFace(*addIt);
828
829 // If the entry already has the inherited face, just update the face
830 if (faceIt != entry.getInheritedFaces().end())
831 {
832 faceIt->cost = addIt->cost;
833 }
834 else // Otherwise, this is a newly inherited face
835 {
836 entry.addInheritedFace(*addIt);
837 }
838
839 insertFibUpdate(FibUpdate::createAddUpdate(entry.getName(), addIt->faceId, addIt->cost));
840 }
841
842 ++addIt;
843 }
844
845 Rib::RibEntryList children = entry.getChildren();
846
847 // Apply face operations to current namespace's children
848 for (Rib::RibEntryList::iterator child = children.begin(); child != children.end(); ++child)
849 {
850 traverseSubTree(*(*child), facesToAdd, facesToRemove);
851 }
852}
853
Alexander Afanasyev20d31442014-04-19 17:00:53 -0700854std::ostream&
Vince12e49462014-06-09 13:29:32 -0500855operator<<(std::ostream& os, const Rib& rib)
Alexander Afanasyev20d31442014-04-19 17:00:53 -0700856{
Vince12e49462014-06-09 13:29:32 -0500857 for (Rib::RibTable::const_iterator it = rib.begin(); it != rib.end(); ++it)
858 {
859 os << *(it->second) << "\n";
860 }
Alexander Afanasyev20d31442014-04-19 17:00:53 -0700861
862 return os;
863}
864
Alexander Afanasyev3ecec502014-04-16 13:42:44 -0700865} // namespace rib
866} // namespace nfd