blob: 3b67bcb05f772d88c54cf0873a67c443625daf3e [file] [log] [blame]
akmhoque3d06e792014-05-27 16:23:20 -05001/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
2/**
Nick Gordonfeae5572017-01-13 12:06:26 -06003 * Copyright (c) 2014-2017, 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/>.
akmhoque3d06e792014-05-27 16:23:20 -050020 **/
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
akmhoque674b0b12014-05-20 14:33:28 -050034INIT_LOGGER("NamePrefixTable");
35
Nick Gordonb50e51b2016-07-22 16:05:57 -050036bool
Nick Gordonc0c6bcf2017-08-15 18:11:21 -050037npteCompare(std::shared_ptr<NamePrefixTableEntry>& npte, const ndn::Name& name)
akmhoque53353462014-04-22 08:43:45 -050038{
Nick Gordonc0c6bcf2017-08-15 18:11:21 -050039 return npte->getNamePrefix() == name;
akmhoque53353462014-04-22 08:43:45 -050040}
41
akmhoque53353462014-04-22 08:43:45 -050042void
akmhoque31d1d4b2014-05-05 22:08:14 -050043NamePrefixTable::addEntry(const ndn::Name& name, const ndn::Name& destRouter)
akmhoque53353462014-04-22 08:43:45 -050044{
Vince Lehmancae33b62015-06-05 09:21:30 -050045
Nick Gordonb50e51b2016-07-22 16:05:57 -050046 // Check if the advertised name prefix is in the table already.
Nick Gordonc0c6bcf2017-08-15 18:11:21 -050047 NptEntryList::iterator nameItr =
48 std::find_if(m_table.begin(),
49 m_table.end(),
50 [&] (const std::shared_ptr<NamePrefixTableEntry>& entry) {
51 return name == entry->getNamePrefix();
52 });
Vince Lehmancae33b62015-06-05 09:21:30 -050053
Nick Gordonb50e51b2016-07-22 16:05:57 -050054 // Attempt to find a routing table pool entry (RTPE) we can use.
Nick Gordonc0c6bcf2017-08-15 18:11:21 -050055 RoutingTableEntryPool::iterator rtpeItr = m_rtpool.find(destRouter);
Nick Gordonb50e51b2016-07-22 16:05:57 -050056
57 // These declarations just to make the compiler happy...
58 RoutingTablePoolEntry rtpe;
59 std::shared_ptr<RoutingTablePoolEntry> rtpePtr(nullptr);
60
61 // There isn't currently a routing table entry in the pool for this name
62 if (rtpeItr == m_rtpool.end()) {
63 // See if there is a routing table entry available we could use
64 RoutingTableEntry* routeEntryPtr = m_nlsr.getRoutingTable()
65 .findRoutingTableEntry(destRouter);
66
67 // We have to create a new routing table entry
68 if (routeEntryPtr == nullptr) {
69 rtpe = RoutingTablePoolEntry(destRouter, 0);
70 }
71 // There was already a usable one in the routing table
72 else {
73 rtpe = RoutingTablePoolEntry(*routeEntryPtr, 0);
74 }
75
76 // Add the new pool object to the pool.
77 rtpePtr = addRtpeToPool(rtpe);
78 }
79 // There was one already, so just fetch that one.
80 else {
81 rtpePtr = (*rtpeItr).second;
82 }
83
Nick Gordonc0c6bcf2017-08-15 18:11:21 -050084 std::shared_ptr<NamePrefixTableEntry> npte;
Nick Gordonb50e51b2016-07-22 16:05:57 -050085 // Either we have to make a new NPT entry or there already was one.
86 if (nameItr == m_table.end()) {
87 _LOG_DEBUG("Adding origin: " << rtpePtr->getDestination()
88 << " to a new name prefix: " << name);
Nick Gordonc0c6bcf2017-08-15 18:11:21 -050089 npte = make_shared<NamePrefixTableEntry>(name);
90 npte->addRoutingTableEntry(rtpePtr);
91 npte->generateNhlfromRteList();
Nick Gordonb50e51b2016-07-22 16:05:57 -050092 m_table.push_back(npte);
Nick Gordonb50e51b2016-07-22 16:05:57 -050093 // If this entry has next hops, we need to inform the FIB
Nick Gordonc0c6bcf2017-08-15 18:11:21 -050094 if (npte->getNexthopList().getSize() > 0) {
Nick Gordonb50e51b2016-07-22 16:05:57 -050095 _LOG_TRACE("Updating FIB with next hops for " << npte);
Nick Gordonc0c6bcf2017-08-15 18:11:21 -050096 m_nlsr.getFib().update(name, npte->getNexthopList());
Nick Gordonb50e51b2016-07-22 16:05:57 -050097 }
98 // The routing table may recalculate and add a routing table entry
99 // with no next hops to replace an existing routing table entry. In
100 // this case, the name prefix is no longer reachable through a next
101 // hop and should be removed from the FIB. But, the prefix should
102 // remain in the Name Prefix Table as a future routing table
103 // calculation may add next hops.
104 else {
Nick Gordonc0c6bcf2017-08-15 18:11:21 -0500105 _LOG_TRACE(*npte << " has no next hops; removing from FIB");
Nick Gordonb50e51b2016-07-22 16:05:57 -0500106 m_nlsr.getFib().remove(name);
107 }
akmhoque53353462014-04-22 08:43:45 -0500108 }
akmhoque157b0a42014-05-13 00:26:37 -0500109 else {
Nick Gordonc0c6bcf2017-08-15 18:11:21 -0500110 npte = *nameItr;
Nick Gordonb50e51b2016-07-22 16:05:57 -0500111 _LOG_TRACE("Adding origin: " << rtpePtr->getDestination()
112 << " to existing prefix: " << *nameItr);
Nick Gordonc0c6bcf2017-08-15 18:11:21 -0500113 (*nameItr)->addRoutingTableEntry(rtpePtr);
114 (*nameItr)->generateNhlfromRteList();
Nick Gordonb50e51b2016-07-22 16:05:57 -0500115
Nick Gordonc0c6bcf2017-08-15 18:11:21 -0500116 if ((*nameItr)->getNexthopList().getSize() > 0) {
Nick Gordonb50e51b2016-07-22 16:05:57 -0500117 _LOG_TRACE("Updating FIB with next hops for " << (*nameItr));
Nick Gordonc0c6bcf2017-08-15 18:11:21 -0500118 m_nlsr.getFib().update(name, (*nameItr)->getNexthopList());
Nick Gordonb50e51b2016-07-22 16:05:57 -0500119 }
120 else {
121 _LOG_TRACE((*nameItr) << " has no next hops; removing from FIB");
122 m_nlsr.getFib().remove(name);
123 }
akmhoque53353462014-04-22 08:43:45 -0500124 }
Nick Gordonc0c6bcf2017-08-15 18:11:21 -0500125 // Add the reference to this NPT to the RTPE.
126 rtpePtr->namePrefixTableEntries.emplace(
127 std::make_pair(npte->getNamePrefix(), std::weak_ptr<NamePrefixTableEntry>(npte)));
akmhoque53353462014-04-22 08:43:45 -0500128}
129
130void
akmhoque31d1d4b2014-05-05 22:08:14 -0500131NamePrefixTable::removeEntry(const ndn::Name& name, const ndn::Name& destRouter)
akmhoque53353462014-04-22 08:43:45 -0500132{
Vince Lehmancae33b62015-06-05 09:21:30 -0500133 _LOG_DEBUG("Removing origin: " << destRouter << " from " << name);
134
Nick Gordonb50e51b2016-07-22 16:05:57 -0500135 // Fetch an iterator to the appropriate pair object in the pool.
Nick Gordonc0c6bcf2017-08-15 18:11:21 -0500136 RoutingTableEntryPool::iterator rtpeItr = m_rtpool.find(destRouter);
Vince Lehmancae33b62015-06-05 09:21:30 -0500137
Nick Gordonb50e51b2016-07-22 16:05:57 -0500138 // Simple error checking to prevent any unusual behavior in the case
139 // that we try to remove an entry that isn't there.
140 if (rtpeItr == m_rtpool.end()) {
141 _LOG_DEBUG("No entry for origin: " << destRouter
142 << " found, so it cannot be removed from prefix: "
143 << name);
144 return;
145 }
146 std::shared_ptr<RoutingTablePoolEntry> rtpePtr = rtpeItr->second;
147
148 // Ensure that the entry exists
Nick Gordonc0c6bcf2017-08-15 18:11:21 -0500149 NptEntryList::iterator nameItr =
150 std::find_if(m_table.begin(), m_table.end(),
151 [&] (const std::shared_ptr<NamePrefixTableEntry>& entry) {
152 return entry->getNamePrefix() == name;
153 });
Nick Gordonb50e51b2016-07-22 16:05:57 -0500154 if (nameItr != m_table.end()) {
155 _LOG_TRACE("Removing origin: " << rtpePtr->getDestination()
Nick Gordonc0c6bcf2017-08-15 18:11:21 -0500156 << " from prefix: " << **nameItr);
Nick Gordonb50e51b2016-07-22 16:05:57 -0500157
158 // Rather than iterating through the whole list periodically, just
159 // delete them here if they have no references.
Nick Gordonc0c6bcf2017-08-15 18:11:21 -0500160 if ((*nameItr)->removeRoutingTableEntry(rtpePtr) == 0) {
Nick Gordonb50e51b2016-07-22 16:05:57 -0500161 deleteRtpeFromPool(rtpePtr);
162 }
163
164 // If the prefix is a router prefix and it does not have any other
165 // routing table entries, the Adjacency/Coordinate LSA associated
166 // with that origin router has been removed from the LSDB and so
167 // the router prefix should be removed from the Name Prefix Table.
168 //
169 // If the prefix is an advertised name prefix: If another router
170 // advertises this name prefix, the RteList should have another
171 // entry for that router; the next hops should be recalculated
172 // and installed in the FIB.
173 //
174 // If no other router advertises this name prefix, the RteList
175 // should be empty and the prefix can be removed from the Name
176 // Prefix Table. Once a new Name LSA advertises this prefix, a
177 // new entry for the prefix will be created.
178 //
Nick Gordonc0c6bcf2017-08-15 18:11:21 -0500179 if ((*nameItr)->getRteListSize() == 0) {
180 _LOG_TRACE(**nameItr << " has no routing table entries;"
Nick Gordonb50e51b2016-07-22 16:05:57 -0500181 << " removing from table and FIB");
182 m_table.erase(nameItr);
183 m_nlsr.getFib().remove(name);
184 }
185 else {
Nick Gordonc0c6bcf2017-08-15 18:11:21 -0500186 _LOG_TRACE(**nameItr << " has other routing table entries;"
Nick Gordonb50e51b2016-07-22 16:05:57 -0500187 << " updating FIB with next hops");
Nick Gordonc0c6bcf2017-08-15 18:11:21 -0500188 (*nameItr)->generateNhlfromRteList();
189 m_nlsr.getFib().update(name, (*nameItr)->getNexthopList());
Nick Gordonb50e51b2016-07-22 16:05:57 -0500190 }
akmhoque53353462014-04-22 08:43:45 -0500191 }
akmhoque157b0a42014-05-13 00:26:37 -0500192 else {
Nick Gordonb50e51b2016-07-22 16:05:57 -0500193 _LOG_DEBUG("Attempted to remove origin: " << rtpePtr->getDestination()
Ashlesh Gawande90173ad2017-08-09 15:19:50 -0500194 << " from non-existent prefix: " << name);
akmhoque53353462014-04-22 08:43:45 -0500195 }
196}
197
198void
akmhoque31d1d4b2014-05-05 22:08:14 -0500199NamePrefixTable::updateWithNewRoute()
akmhoque53353462014-04-22 08:43:45 -0500200{
Vince Lehmancae33b62015-06-05 09:21:30 -0500201 _LOG_DEBUG("Updating table with newly calculated routes");
202
Nick Gordonc0c6bcf2017-08-15 18:11:21 -0500203 // Iterate over each pool entry we have
204 for (auto&& poolEntryPair : m_rtpool) {
205 auto&& poolEntry = poolEntryPair.second;
206 RoutingTableEntry* sourceEntry =
207 m_nlsr.getRoutingTable().findRoutingTableEntry(poolEntry->getDestination());
208 // If this pool entry has a corresponding entry in the routing table now
209 if (sourceEntry != nullptr && poolEntry->getNexthopList() != sourceEntry->getNexthopList()) {
210 _LOG_DEBUG("Routing entry: " << poolEntry->getDestination() << " has changed next-hops.");
211 poolEntry->setNexthopList(sourceEntry->getNexthopList());
212 for (const auto& nameEntry : poolEntry->namePrefixTableEntries) {
213 auto nameEntryFullPtr = nameEntry.second.lock();
214 addEntry(nameEntryFullPtr->getNamePrefix(), poolEntry->getDestination());
215 }
216 }
217 else if (sourceEntry == nullptr) {
218 _LOG_DEBUG("Routing entry: " << poolEntry->getDestination() << " now has no next-hops.");
219 poolEntry->getNexthopList().reset();
220 for (const auto& nameEntry : poolEntry->namePrefixTableEntries) {
221 auto nameEntryFullPtr = nameEntry.second.lock();
222 addEntry(nameEntryFullPtr->getNamePrefix(), poolEntry->getDestination());
223 }
Vince Lehmancae33b62015-06-05 09:21:30 -0500224
Nick Gordonc0c6bcf2017-08-15 18:11:21 -0500225 }
226 else {
227 _LOG_TRACE("No change in routing entry:" << poolEntry->getDestination()
228 << ", no action necessary.");
akmhoque53353462014-04-22 08:43:45 -0500229 }
230 }
231}
232
Nick Gordonb50e51b2016-07-22 16:05:57 -0500233 // Inserts the routing table pool entry into the NPT's RTE storage
234 // pool. This cannot fail, so the pool is guaranteed to contain the
235 // item after this occurs.
236std::shared_ptr<RoutingTablePoolEntry>
237NamePrefixTable::addRtpeToPool(RoutingTablePoolEntry& rtpe)
238{
Nick Gordonc0c6bcf2017-08-15 18:11:21 -0500239 RoutingTableEntryPool::iterator poolItr =
Nick Gordonb50e51b2016-07-22 16:05:57 -0500240 m_rtpool.insert(std::make_pair(rtpe.getDestination(),
241 std::make_shared<RoutingTablePoolEntry>
242 (rtpe)))
243 .first;
Nick Gordonb50e51b2016-07-22 16:05:57 -0500244 return poolItr->second;
245}
246
247 // Removes the routing table pool entry from the storage pool. The
248 // postconditions of this function are guaranteed to include that
249 // the storage pool does not contain such an item. Additionally,
250 // this function cannot fail, but nonetheless debug information is
251 // given in the case that this function is called with an entry that
252 // isn't in the pool.
253void
254NamePrefixTable::deleteRtpeFromPool(std::shared_ptr<RoutingTablePoolEntry> rtpePtr)
255{
256 if (m_rtpool.erase(rtpePtr->getDestination()) != 1) {
Ashlesh Gawande90173ad2017-08-09 15:19:50 -0500257 _LOG_DEBUG("Attempted to delete non-existent origin: "
Nick Gordonb50e51b2016-07-22 16:05:57 -0500258 << rtpePtr->getDestination()
259 << " from NPT routing table entry storage pool.");
260 }
261}
262
akmhoque53353462014-04-22 08:43:45 -0500263void
akmhoque674b0b12014-05-20 14:33:28 -0500264NamePrefixTable::writeLog()
265{
Vince Lehmancae33b62015-06-05 09:21:30 -0500266 _LOG_DEBUG(*this);
akmhoque674b0b12014-05-20 14:33:28 -0500267}
268
Vince Lehmancae33b62015-06-05 09:21:30 -0500269std::ostream&
270operator<<(std::ostream& os, const NamePrefixTable& table)
271{
272 os << "----------------NPT----------------------\n";
273
Nick Gordonc0c6bcf2017-08-15 18:11:21 -0500274 for (const auto& entryPtr : table) {
275 os << *entryPtr << std::endl;
Vince Lehmancae33b62015-06-05 09:21:30 -0500276 }
277
278 return os;
279}
280
281} // namespace nlsr