blob: f47d84038fc53d93f47331ac4c66127aa1cdd075 [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
28namespace nfd {
29namespace rib {
30
31Rib::Rib()
Vince12e49462014-06-09 13:29:32 -050032 : m_nItems(0)
Alexander Afanasyev3ecec502014-04-16 13:42:44 -070033{
34}
35
36
37Rib::~Rib()
38{
39}
40
Alexander Afanasyev3ecec502014-04-16 13:42:44 -070041Rib::const_iterator
Vince12e49462014-06-09 13:29:32 -050042Rib::find(const Name& prefix) const
Alexander Afanasyev3ecec502014-04-16 13:42:44 -070043{
Vince12e49462014-06-09 13:29:32 -050044 return m_rib.find(prefix);
45}
46
47shared_ptr<FaceEntry>
48Rib::find(const Name& prefix, const FaceEntry& face) const
49{
50 RibTable::const_iterator ribIt = m_rib.find(prefix);
51
52 // Name prefix exists
53 if (ribIt != m_rib.end())
Alexander Afanasyev3ecec502014-04-16 13:42:44 -070054 {
Vince12e49462014-06-09 13:29:32 -050055 shared_ptr<RibEntry> entry(ribIt->second);
56
57 RibEntry::const_iterator faceIt = std::find_if(entry->begin(), entry->end(),
58 bind(&compareFaceIdAndOrigin, _1, face));
59
60 if (faceIt != entry->end())
61 {
62 return make_shared<FaceEntry>(*faceIt);
63 }
Alexander Afanasyev3ecec502014-04-16 13:42:44 -070064 }
Vince12e49462014-06-09 13:29:32 -050065
66 return shared_ptr<FaceEntry>();
Alexander Afanasyev3ecec502014-04-16 13:42:44 -070067}
68
69
70void
Vince12e49462014-06-09 13:29:32 -050071Rib::insert(const Name& prefix, const FaceEntry& face)
Alexander Afanasyev3ecec502014-04-16 13:42:44 -070072{
Vince12e49462014-06-09 13:29:32 -050073 RibTable::iterator ribIt = m_rib.find(prefix);
74
75 // Name prefix exists
76 if (ribIt != m_rib.end())
Alexander Afanasyev3ecec502014-04-16 13:42:44 -070077 {
Vince12e49462014-06-09 13:29:32 -050078 shared_ptr<RibEntry> entry(ribIt->second);
79
80 RibEntry::iterator faceIt = std::find_if(entry->getFaces().begin(),
81 entry->getFaces().end(),
82 bind(&compareFaceIdAndOrigin, _1, face));
83
84 if (faceIt == entry->end())
85 {
86 // New face
87 entry->insertFace(face);
88 m_nItems++;
89
90 // Register with face lookup table
91 m_faceMap[face.faceId].push_back(entry);
92 }
93 else
94 {
95 // Entry exists, update other fields
96 faceIt->flags = face.flags;
97 faceIt->cost = face.cost;
98 faceIt->expires = face.expires;
99 }
Alexander Afanasyev3ecec502014-04-16 13:42:44 -0700100 }
Vince12e49462014-06-09 13:29:32 -0500101 else // New name prefix
Alexander Afanasyev3ecec502014-04-16 13:42:44 -0700102 {
Vince12e49462014-06-09 13:29:32 -0500103 shared_ptr<RibEntry> entry(make_shared<RibEntry>(RibEntry()));
104
105 m_rib[prefix] = entry;
106 m_nItems++;
107
108 entry->setName(prefix);
109 entry->insertFace(face);
110
111 // Find prefix's parent
112 shared_ptr<RibEntry> parent = findParent(prefix);
113
114 // Add self to parent's children
115 if (static_cast<bool>(parent))
116 {
117 parent->addChild(entry);
118 }
119
120 RibEntryList children = findDescendants(prefix);
121
122 for (std::list<shared_ptr<RibEntry> >::iterator child = children.begin();
123 child != children.end(); ++child)
124 {
125 if ((*child)->getParent() == parent)
126 {
127 // Remove child from parent and inherit parent's child
128 if (static_cast<bool>(parent))
129 {
130 parent->removeChild((*child));
131 }
132
133 entry->addChild((*child));
134 }
135 }
136
137 // Register with face lookup table
138 m_faceMap[face.faceId].push_back(entry);
Alexander Afanasyev3ecec502014-04-16 13:42:44 -0700139 }
140}
141
142
143void
Vince12e49462014-06-09 13:29:32 -0500144Rib::erase(const Name& prefix, const FaceEntry& face)
Alexander Afanasyev3ecec502014-04-16 13:42:44 -0700145{
Vince12e49462014-06-09 13:29:32 -0500146 RibTable::iterator ribIt = m_rib.find(prefix);
147
148 // Name prefix exists
149 if (ribIt != m_rib.end())
150 {
151 shared_ptr<RibEntry> entry(ribIt->second);
152
153 if (entry->eraseFace(face))
154 {
155 m_nItems--;
156
157 // If this RibEntry no longer has this faceId, unregister from face lookup table
158 if (!entry->hasFaceId(face.faceId))
159 {
160 m_faceMap[face.faceId].remove(entry);
161 }
162
163 // If a RibEntry's facelist is empty, remove it from the tree
164 if (entry->getFaces().size() == 0)
165 {
166 eraseEntry(ribIt);
167 }
168 }
169 }
170}
171
172void
173Rib::erase(const uint64_t faceId)
174{
175 FaceLookupTable::iterator lookupIt = m_faceMap.find(faceId);
176
177 // No RIB entries have this face
178 if (lookupIt == m_faceMap.end())
179 {
180 return;
181 }
182
183 RibEntryList& ribEntries = lookupIt->second;
184
185 // For each RIB entry that has faceId, remove the face from the entry
186 for (RibEntryList::iterator entryIt = ribEntries.begin(); entryIt != ribEntries.end(); ++entryIt)
187 {
188 shared_ptr<RibEntry> entry = *entryIt;
189
190 // Find the faces in the entry
191 for (RibEntry::iterator faceIt = entry->begin(); faceIt != entry->end(); ++faceIt)
192 {
193 if (faceIt->faceId == faceId)
194 {
195 faceIt = entry->eraseFace(faceIt);
196 }
197 }
198
199 // If a RibEntry's facelist is empty, remove it from the tree
200 if (entry->getFaces().size() == 0)
201 {
202 eraseEntry(m_rib.find(entry->getName()));
203 }
204 }
205
206 // Face no longer exists, remove from face lookup table
207 FaceLookupTable::iterator entryToDelete = m_faceMap.find(faceId);
208
209 if (entryToDelete != m_faceMap.end())
210 {
211 m_faceMap.erase(entryToDelete);
212 }
213}
214
215shared_ptr<RibEntry>
216Rib::findParent(const Name& prefix) const
217{
218 for (int i = prefix.size() - 1; i >= 0; i--)
219 {
220 RibTable::const_iterator it = m_rib.find(prefix.getPrefix(i));
221 if (it != m_rib.end())
222 {
223 return (it->second);
224 }
225 }
226
227 return shared_ptr<RibEntry>();
228}
229
230std::list<shared_ptr<RibEntry> >
231Rib::findDescendants(const Name& prefix) const
232{
233 std::list<shared_ptr<RibEntry> > children;
234
235 RibTable::const_iterator it = m_rib.find(prefix);
236
Alexander Afanasyev3ecec502014-04-16 13:42:44 -0700237 if (it != m_rib.end())
238 {
Vince12e49462014-06-09 13:29:32 -0500239 ++it;
240 for (; it != m_rib.end(); ++it)
241 {
242 if (prefix.isPrefixOf(it->first))
243 {
244 children.push_back((it->second));
245 }
246 else
247 {
248 break;
249 }
250 }
Alexander Afanasyev3ecec502014-04-16 13:42:44 -0700251 }
Vince12e49462014-06-09 13:29:32 -0500252
253 return children;
Alexander Afanasyev3ecec502014-04-16 13:42:44 -0700254}
255
Vince12e49462014-06-09 13:29:32 -0500256Rib::RibTable::iterator
257Rib::eraseEntry(RibTable::iterator it)
Alexander Afanasyev3ecec502014-04-16 13:42:44 -0700258{
Vince12e49462014-06-09 13:29:32 -0500259 // Entry does not exist
260 if (it == m_rib.end())
261 {
262 return m_rib.end();
263 }
264
265 shared_ptr<RibEntry> entry(it->second);
266
267 shared_ptr<RibEntry> parent = entry->getParent();
268
269 // Remove self from parent's children
270 if (static_cast<bool>(parent))
271 {
272 parent->removeChild(entry);
273 }
274
275 std::list<shared_ptr<RibEntry> > children = entry->getChildren();
276
277 for (RibEntryList::iterator child = children.begin(); child != children.end(); ++child)
278 {
279 // Remove children from self
280 entry->removeChild(*child);
281
282 // Update parent's children
283 if (static_cast<bool>(parent))
284 {
285 parent->addChild(*child);
286 }
287 }
288
289 // Must save and advance iterator to return a valid iterator
290 RibTable::iterator nextIt = it;
291 nextIt++;
292
293 m_rib.erase(it);
294
295 return nextIt;
Alexander Afanasyev3ecec502014-04-16 13:42:44 -0700296}
297
Alexander Afanasyev20d31442014-04-19 17:00:53 -0700298std::ostream&
Vince12e49462014-06-09 13:29:32 -0500299operator<<(std::ostream& os, const Rib& rib)
Alexander Afanasyev20d31442014-04-19 17:00:53 -0700300{
Vince12e49462014-06-09 13:29:32 -0500301 for (Rib::RibTable::const_iterator it = rib.begin(); it != rib.end(); ++it)
302 {
303 os << *(it->second) << "\n";
304 }
Alexander Afanasyev20d31442014-04-19 17:00:53 -0700305
306 return os;
307}
308
Alexander Afanasyev3ecec502014-04-16 13:42:44 -0700309} // namespace rib
310} // namespace nfd