blob: 91e6210b45c6311cd96ed7821a43ac8e6739534a [file] [log] [blame]
akmhoque3d06e792014-05-27 16:23:20 -05001/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
Ashlesh Gawande0421bc62020-05-08 20:42:19 -07002/*
Davide Pesaventod90338d2021-01-07 17:50:05 -05003 * Copyright (c) 2014-2021, The University of Memphis,
Vince Lehmanc2e51f62015-01-20 15:03:11 -06004 * Regents of the University of California,
5 * Arizona Board of Regents.
akmhoque3d06e792014-05-27 16:23:20 -05006 *
7 * This file is part of NLSR (Named-data Link State Routing).
8 * See AUTHORS.md for complete list of NLSR authors and contributors.
9 *
10 * NLSR is free software: you can redistribute it and/or modify it under the terms
11 * of the GNU General Public License as published by the Free Software Foundation,
12 * either version 3 of the License, or (at your option) any later version.
13 *
14 * NLSR is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
15 * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
16 * PURPOSE. See the GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License along with
19 * NLSR, e.g., in COPYING.md file. If not, see <http://www.gnu.org/licenses/>.
Ashlesh Gawande0421bc62020-05-08 20:42:19 -070020 */
Vince Lehmanc2e51f62015-01-20 15:03:11 -060021
Vince Lehmancae33b62015-06-05 09:21:30 -050022#include "name-prefix-table.hpp"
23
24#include "logger.hpp"
25#include "nlsr.hpp"
26#include "routing-table.hpp"
27
28#include <algorithm>
akmhoque53353462014-04-22 08:43:45 -050029#include <list>
30#include <utility>
akmhoque53353462014-04-22 08:43:45 -050031
32namespace nlsr {
33
dmcoomescf8d0ed2017-02-21 11:39:01 -060034INIT_LOGGER(route.NamePrefixTable);
akmhoque674b0b12014-05-20 14:33:28 -050035
Ashlesh Gawande85998a12017-12-07 22:22:13 -060036NamePrefixTable::NamePrefixTable(Fib& fib, RoutingTable& routingTable,
Nick Gordond40a5882017-09-05 15:34:58 -050037 std::unique_ptr<AfterRoutingChange>& afterRoutingChangeSignal)
Ashlesh Gawande85998a12017-12-07 22:22:13 -060038 : m_fib(fib)
39 , m_routingTable(routingTable)
Nick Gordonb7b58392017-08-17 16:29:21 -050040{
41 m_afterRoutingChangeConnection = afterRoutingChangeSignal->connect(
42 [this] (const std::list<RoutingTableEntry>& entries) {
43 updateWithNewRoute(entries);
44 });
45}
46
47NamePrefixTable::~NamePrefixTable()
48{
49 m_afterRoutingChangeConnection.disconnect();
50}
51
akmhoque53353462014-04-22 08:43:45 -050052void
akmhoque31d1d4b2014-05-05 22:08:14 -050053NamePrefixTable::addEntry(const ndn::Name& name, const ndn::Name& destRouter)
akmhoque53353462014-04-22 08:43:45 -050054{
Vince Lehmancae33b62015-06-05 09:21:30 -050055
Nick Gordonb50e51b2016-07-22 16:05:57 -050056 // Check if the advertised name prefix is in the table already.
Nick Gordonc0c6bcf2017-08-15 18:11:21 -050057 NptEntryList::iterator nameItr =
58 std::find_if(m_table.begin(),
59 m_table.end(),
60 [&] (const std::shared_ptr<NamePrefixTableEntry>& entry) {
61 return name == entry->getNamePrefix();
62 });
Vince Lehmancae33b62015-06-05 09:21:30 -050063
Nick Gordonb50e51b2016-07-22 16:05:57 -050064 // Attempt to find a routing table pool entry (RTPE) we can use.
Nick Gordonc0c6bcf2017-08-15 18:11:21 -050065 RoutingTableEntryPool::iterator rtpeItr = m_rtpool.find(destRouter);
Nick Gordonb50e51b2016-07-22 16:05:57 -050066
67 // These declarations just to make the compiler happy...
68 RoutingTablePoolEntry rtpe;
69 std::shared_ptr<RoutingTablePoolEntry> rtpePtr(nullptr);
70
71 // There isn't currently a routing table entry in the pool for this name
72 if (rtpeItr == m_rtpool.end()) {
73 // See if there is a routing table entry available we could use
Ashlesh Gawande85998a12017-12-07 22:22:13 -060074 RoutingTableEntry* routeEntryPtr = m_routingTable.findRoutingTableEntry(destRouter);
Nick Gordonb50e51b2016-07-22 16:05:57 -050075
76 // We have to create a new routing table entry
77 if (routeEntryPtr == nullptr) {
78 rtpe = RoutingTablePoolEntry(destRouter, 0);
79 }
80 // There was already a usable one in the routing table
81 else {
82 rtpe = RoutingTablePoolEntry(*routeEntryPtr, 0);
83 }
84
85 // Add the new pool object to the pool.
86 rtpePtr = addRtpeToPool(rtpe);
87 }
88 // There was one already, so just fetch that one.
89 else {
90 rtpePtr = (*rtpeItr).second;
91 }
92
Nick Gordonc0c6bcf2017-08-15 18:11:21 -050093 std::shared_ptr<NamePrefixTableEntry> npte;
Nick Gordonb50e51b2016-07-22 16:05:57 -050094 // Either we have to make a new NPT entry or there already was one.
95 if (nameItr == m_table.end()) {
dmcoomes5bcb39e2017-10-31 15:07:55 -050096 NLSR_LOG_DEBUG("Adding origin: " << rtpePtr->getDestination()
Davide Pesaventod90338d2021-01-07 17:50:05 -050097 << " to a new name prefix: " << name);
98 npte = std::make_shared<NamePrefixTableEntry>(name);
Nick Gordonc0c6bcf2017-08-15 18:11:21 -050099 npte->addRoutingTableEntry(rtpePtr);
100 npte->generateNhlfromRteList();
Nick Gordonb50e51b2016-07-22 16:05:57 -0500101 m_table.push_back(npte);
Davide Pesaventod90338d2021-01-07 17:50:05 -0500102
Nick Gordonb50e51b2016-07-22 16:05:57 -0500103 // If this entry has next hops, we need to inform the FIB
Nick Gordonff9a6272017-10-12 13:38:29 -0500104 if (npte->getNexthopList().size() > 0) {
Ashlesh Gawandee8d8bd52018-08-09 17:18:51 -0500105 NLSR_LOG_TRACE("Updating FIB with next hops for " << npte->getNamePrefix());
Ashlesh Gawande85998a12017-12-07 22:22:13 -0600106 m_fib.update(name, npte->getNexthopList());
Nick Gordonb50e51b2016-07-22 16:05:57 -0500107 }
108 // The routing table may recalculate and add a routing table entry
109 // with no next hops to replace an existing routing table entry. In
110 // this case, the name prefix is no longer reachable through a next
111 // hop and should be removed from the FIB. But, the prefix should
112 // remain in the Name Prefix Table as a future routing table
113 // calculation may add next hops.
114 else {
Ashlesh Gawandee8d8bd52018-08-09 17:18:51 -0500115 NLSR_LOG_TRACE(npte->getNamePrefix() << " has no next hops; removing from FIB");
Ashlesh Gawande85998a12017-12-07 22:22:13 -0600116 m_fib.remove(name);
Nick Gordonb50e51b2016-07-22 16:05:57 -0500117 }
akmhoque53353462014-04-22 08:43:45 -0500118 }
akmhoque157b0a42014-05-13 00:26:37 -0500119 else {
Nick Gordonc0c6bcf2017-08-15 18:11:21 -0500120 npte = *nameItr;
Ashlesh Gawandee5002b32018-12-20 21:07:31 -0600121 NLSR_LOG_TRACE("Adding origin: " << rtpePtr->getDestination() <<
122 " to existing prefix: " << **nameItr);
Nick Gordonc0c6bcf2017-08-15 18:11:21 -0500123 (*nameItr)->addRoutingTableEntry(rtpePtr);
124 (*nameItr)->generateNhlfromRteList();
Nick Gordonb50e51b2016-07-22 16:05:57 -0500125
Nick Gordonff9a6272017-10-12 13:38:29 -0500126 if ((*nameItr)->getNexthopList().size() > 0) {
Ashlesh Gawandee5002b32018-12-20 21:07:31 -0600127 NLSR_LOG_TRACE("Updating FIB with next hops for " << (**nameItr));
Ashlesh Gawande85998a12017-12-07 22:22:13 -0600128 m_fib.update(name, (*nameItr)->getNexthopList());
Nick Gordonb50e51b2016-07-22 16:05:57 -0500129 }
130 else {
Ashlesh Gawandee8d8bd52018-08-09 17:18:51 -0500131 NLSR_LOG_TRACE(npte->getNamePrefix() << " has no next hops; removing from FIB");
Ashlesh Gawande85998a12017-12-07 22:22:13 -0600132 m_fib.remove(name);
Nick Gordonb50e51b2016-07-22 16:05:57 -0500133 }
akmhoque53353462014-04-22 08:43:45 -0500134 }
Davide Pesaventod90338d2021-01-07 17:50:05 -0500135
Nick Gordonc0c6bcf2017-08-15 18:11:21 -0500136 // Add the reference to this NPT to the RTPE.
137 rtpePtr->namePrefixTableEntries.emplace(
138 std::make_pair(npte->getNamePrefix(), std::weak_ptr<NamePrefixTableEntry>(npte)));
akmhoque53353462014-04-22 08:43:45 -0500139}
140
141void
akmhoque31d1d4b2014-05-05 22:08:14 -0500142NamePrefixTable::removeEntry(const ndn::Name& name, const ndn::Name& destRouter)
akmhoque53353462014-04-22 08:43:45 -0500143{
dmcoomes5bcb39e2017-10-31 15:07:55 -0500144 NLSR_LOG_DEBUG("Removing origin: " << destRouter << " from " << name);
Vince Lehmancae33b62015-06-05 09:21:30 -0500145
Nick Gordonb50e51b2016-07-22 16:05:57 -0500146 // Fetch an iterator to the appropriate pair object in the pool.
Nick Gordonc0c6bcf2017-08-15 18:11:21 -0500147 RoutingTableEntryPool::iterator rtpeItr = m_rtpool.find(destRouter);
Vince Lehmancae33b62015-06-05 09:21:30 -0500148
Nick Gordonb50e51b2016-07-22 16:05:57 -0500149 // Simple error checking to prevent any unusual behavior in the case
150 // that we try to remove an entry that isn't there.
151 if (rtpeItr == m_rtpool.end()) {
dmcoomes5bcb39e2017-10-31 15:07:55 -0500152 NLSR_LOG_DEBUG("No entry for origin: " << destRouter
Nick Gordonb50e51b2016-07-22 16:05:57 -0500153 << " found, so it cannot be removed from prefix: "
154 << name);
155 return;
156 }
157 std::shared_ptr<RoutingTablePoolEntry> rtpePtr = rtpeItr->second;
158
159 // Ensure that the entry exists
Nick Gordonc0c6bcf2017-08-15 18:11:21 -0500160 NptEntryList::iterator nameItr =
161 std::find_if(m_table.begin(), m_table.end(),
162 [&] (const std::shared_ptr<NamePrefixTableEntry>& entry) {
163 return entry->getNamePrefix() == name;
164 });
Nick Gordonb50e51b2016-07-22 16:05:57 -0500165 if (nameItr != m_table.end()) {
dmcoomes5bcb39e2017-10-31 15:07:55 -0500166 NLSR_LOG_TRACE("Removing origin: " << rtpePtr->getDestination()
Nick Gordonc0c6bcf2017-08-15 18:11:21 -0500167 << " from prefix: " << **nameItr);
Nick Gordonb50e51b2016-07-22 16:05:57 -0500168
169 // Rather than iterating through the whole list periodically, just
170 // delete them here if they have no references.
Nick Gordonc0c6bcf2017-08-15 18:11:21 -0500171 if ((*nameItr)->removeRoutingTableEntry(rtpePtr) == 0) {
Nick Gordonb50e51b2016-07-22 16:05:57 -0500172 deleteRtpeFromPool(rtpePtr);
173 }
174
175 // If the prefix is a router prefix and it does not have any other
176 // routing table entries, the Adjacency/Coordinate LSA associated
177 // with that origin router has been removed from the LSDB and so
178 // the router prefix should be removed from the Name Prefix Table.
179 //
180 // If the prefix is an advertised name prefix: If another router
181 // advertises this name prefix, the RteList should have another
182 // entry for that router; the next hops should be recalculated
183 // and installed in the FIB.
184 //
185 // If no other router advertises this name prefix, the RteList
186 // should be empty and the prefix can be removed from the Name
187 // Prefix Table. Once a new Name LSA advertises this prefix, a
188 // new entry for the prefix will be created.
189 //
Nick Gordonc0c6bcf2017-08-15 18:11:21 -0500190 if ((*nameItr)->getRteListSize() == 0) {
dmcoomes5bcb39e2017-10-31 15:07:55 -0500191 NLSR_LOG_TRACE(**nameItr << " has no routing table entries;"
Nick Gordonb50e51b2016-07-22 16:05:57 -0500192 << " removing from table and FIB");
193 m_table.erase(nameItr);
Ashlesh Gawande85998a12017-12-07 22:22:13 -0600194 m_fib.remove(name);
Nick Gordonb50e51b2016-07-22 16:05:57 -0500195 }
196 else {
dmcoomes5bcb39e2017-10-31 15:07:55 -0500197 NLSR_LOG_TRACE(**nameItr << " has other routing table entries;"
Nick Gordonb50e51b2016-07-22 16:05:57 -0500198 << " updating FIB with next hops");
Nick Gordonc0c6bcf2017-08-15 18:11:21 -0500199 (*nameItr)->generateNhlfromRteList();
Ashlesh Gawande85998a12017-12-07 22:22:13 -0600200 m_fib.update(name, (*nameItr)->getNexthopList());
Nick Gordonb50e51b2016-07-22 16:05:57 -0500201 }
akmhoque53353462014-04-22 08:43:45 -0500202 }
akmhoque157b0a42014-05-13 00:26:37 -0500203 else {
dmcoomes5bcb39e2017-10-31 15:07:55 -0500204 NLSR_LOG_DEBUG("Attempted to remove origin: " << rtpePtr->getDestination()
Ashlesh Gawande90173ad2017-08-09 15:19:50 -0500205 << " from non-existent prefix: " << name);
akmhoque53353462014-04-22 08:43:45 -0500206 }
207}
208
209void
Nick Gordonb7b58392017-08-17 16:29:21 -0500210NamePrefixTable::updateWithNewRoute(const std::list<RoutingTableEntry>& entries)
akmhoque53353462014-04-22 08:43:45 -0500211{
dmcoomes5bcb39e2017-10-31 15:07:55 -0500212 NLSR_LOG_DEBUG("Updating table with newly calculated routes");
Vince Lehmancae33b62015-06-05 09:21:30 -0500213
Nick Gordonc0c6bcf2017-08-15 18:11:21 -0500214 // Iterate over each pool entry we have
215 for (auto&& poolEntryPair : m_rtpool) {
216 auto&& poolEntry = poolEntryPair.second;
Nick Gordonb7b58392017-08-17 16:29:21 -0500217 auto sourceEntry = std::find_if(entries.begin(), entries.end(),
218 [&poolEntry] (const RoutingTableEntry& entry) {
219 return poolEntry->getDestination() == entry.getDestination();
220 });
Nick Gordonc0c6bcf2017-08-15 18:11:21 -0500221 // If this pool entry has a corresponding entry in the routing table now
Nick Gordonb7b58392017-08-17 16:29:21 -0500222 if (sourceEntry != entries.end()
223 && poolEntry->getNexthopList() != sourceEntry->getNexthopList()) {
dmcoomes5bcb39e2017-10-31 15:07:55 -0500224 NLSR_LOG_DEBUG("Routing entry: " << poolEntry->getDestination() << " has changed next-hops.");
Nick Gordonc0c6bcf2017-08-15 18:11:21 -0500225 poolEntry->setNexthopList(sourceEntry->getNexthopList());
226 for (const auto& nameEntry : poolEntry->namePrefixTableEntries) {
227 auto nameEntryFullPtr = nameEntry.second.lock();
228 addEntry(nameEntryFullPtr->getNamePrefix(), poolEntry->getDestination());
229 }
230 }
Nick Gordonb7b58392017-08-17 16:29:21 -0500231 else if (sourceEntry == entries.end()) {
dmcoomes5bcb39e2017-10-31 15:07:55 -0500232 NLSR_LOG_DEBUG("Routing entry: " << poolEntry->getDestination() << " now has no next-hops.");
Ashlesh Gawande0421bc62020-05-08 20:42:19 -0700233 poolEntry->getNexthopList().clear();
Nick Gordonc0c6bcf2017-08-15 18:11:21 -0500234 for (const auto& nameEntry : poolEntry->namePrefixTableEntries) {
235 auto nameEntryFullPtr = nameEntry.second.lock();
236 addEntry(nameEntryFullPtr->getNamePrefix(), poolEntry->getDestination());
237 }
Nick Gordonc0c6bcf2017-08-15 18:11:21 -0500238 }
239 else {
dmcoomes5bcb39e2017-10-31 15:07:55 -0500240 NLSR_LOG_TRACE("No change in routing entry:" << poolEntry->getDestination()
Nick Gordonc0c6bcf2017-08-15 18:11:21 -0500241 << ", no action necessary.");
akmhoque53353462014-04-22 08:43:45 -0500242 }
243 }
244}
245
Nick Gordonb50e51b2016-07-22 16:05:57 -0500246 // Inserts the routing table pool entry into the NPT's RTE storage
247 // pool. This cannot fail, so the pool is guaranteed to contain the
248 // item after this occurs.
249std::shared_ptr<RoutingTablePoolEntry>
250NamePrefixTable::addRtpeToPool(RoutingTablePoolEntry& rtpe)
251{
Nick Gordonc0c6bcf2017-08-15 18:11:21 -0500252 RoutingTableEntryPool::iterator poolItr =
Nick Gordonb50e51b2016-07-22 16:05:57 -0500253 m_rtpool.insert(std::make_pair(rtpe.getDestination(),
254 std::make_shared<RoutingTablePoolEntry>
255 (rtpe)))
256 .first;
Nick Gordonb50e51b2016-07-22 16:05:57 -0500257 return poolItr->second;
258}
259
260 // Removes the routing table pool entry from the storage pool. The
261 // postconditions of this function are guaranteed to include that
262 // the storage pool does not contain such an item. Additionally,
263 // this function cannot fail, but nonetheless debug information is
264 // given in the case that this function is called with an entry that
265 // isn't in the pool.
266void
267NamePrefixTable::deleteRtpeFromPool(std::shared_ptr<RoutingTablePoolEntry> rtpePtr)
268{
269 if (m_rtpool.erase(rtpePtr->getDestination()) != 1) {
dmcoomes5bcb39e2017-10-31 15:07:55 -0500270 NLSR_LOG_DEBUG("Attempted to delete non-existent origin: "
Nick Gordonb50e51b2016-07-22 16:05:57 -0500271 << rtpePtr->getDestination()
272 << " from NPT routing table entry storage pool.");
273 }
274}
275
akmhoque53353462014-04-22 08:43:45 -0500276void
akmhoque674b0b12014-05-20 14:33:28 -0500277NamePrefixTable::writeLog()
278{
dmcoomes5bcb39e2017-10-31 15:07:55 -0500279 NLSR_LOG_DEBUG(*this);
akmhoque674b0b12014-05-20 14:33:28 -0500280}
281
Vince Lehmancae33b62015-06-05 09:21:30 -0500282std::ostream&
283operator<<(std::ostream& os, const NamePrefixTable& table)
284{
285 os << "----------------NPT----------------------\n";
286
Nick Gordonc0c6bcf2017-08-15 18:11:21 -0500287 for (const auto& entryPtr : table) {
288 os << *entryPtr << std::endl;
Vince Lehmancae33b62015-06-05 09:21:30 -0500289 }
290
291 return os;
292}
293
294} // namespace nlsr