blob: 251bfc533942f1398746f28db40ddb29179f3a05 [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
akmhoque31d1d4b2014-05-05 22:08:14 -050037npteCompare(NamePrefixTableEntry& npte, const ndn::Name& name)
akmhoque53353462014-04-22 08:43:45 -050038{
39 return npte.getNamePrefix() == name;
40}
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.
47 NptEntryList::iterator nameItr = std::find(m_table.begin(),
Ashlesh Gawande90173ad2017-08-09 15:19:50 -050048 m_table.end(),
49 name);
Vince Lehmancae33b62015-06-05 09:21:30 -050050
Nick Gordonb50e51b2016-07-22 16:05:57 -050051 // Attempt to find a routing table pool entry (RTPE) we can use.
52 RtpEntryMap::iterator rtpeItr = m_rtpool.find(destRouter);
53
54 // These declarations just to make the compiler happy...
55 RoutingTablePoolEntry rtpe;
56 std::shared_ptr<RoutingTablePoolEntry> rtpePtr(nullptr);
57
58 // There isn't currently a routing table entry in the pool for this name
59 if (rtpeItr == m_rtpool.end()) {
60 // See if there is a routing table entry available we could use
61 RoutingTableEntry* routeEntryPtr = m_nlsr.getRoutingTable()
62 .findRoutingTableEntry(destRouter);
63
64 // We have to create a new routing table entry
65 if (routeEntryPtr == nullptr) {
66 rtpe = RoutingTablePoolEntry(destRouter, 0);
67 }
68 // There was already a usable one in the routing table
69 else {
70 rtpe = RoutingTablePoolEntry(*routeEntryPtr, 0);
71 }
72
73 // Add the new pool object to the pool.
74 rtpePtr = addRtpeToPool(rtpe);
75 }
76 // There was one already, so just fetch that one.
77 else {
78 rtpePtr = (*rtpeItr).second;
79 }
80
81 // Either we have to make a new NPT entry or there already was one.
82 if (nameItr == m_table.end()) {
83 _LOG_DEBUG("Adding origin: " << rtpePtr->getDestination()
84 << " to a new name prefix: " << name);
85 NamePrefixTableEntry npte(name);
86 npte.addRoutingTableEntry(rtpePtr);
87 npte.generateNhlfromRteList();
88 m_table.push_back(npte);
89
90 // If this entry has next hops, we need to inform the FIB
91 if (npte.getNexthopList().getSize() > 0) {
92 _LOG_TRACE("Updating FIB with next hops for " << npte);
93 m_nlsr.getFib().update(name, npte.getNexthopList());
94 }
95 // The routing table may recalculate and add a routing table entry
96 // with no next hops to replace an existing routing table entry. In
97 // this case, the name prefix is no longer reachable through a next
98 // hop and should be removed from the FIB. But, the prefix should
99 // remain in the Name Prefix Table as a future routing table
100 // calculation may add next hops.
101 else {
102 _LOG_TRACE(npte << " has no next hops; removing from FIB");
103 m_nlsr.getFib().remove(name);
104 }
akmhoque53353462014-04-22 08:43:45 -0500105 }
akmhoque157b0a42014-05-13 00:26:37 -0500106 else {
Nick Gordonb50e51b2016-07-22 16:05:57 -0500107 _LOG_TRACE("Adding origin: " << rtpePtr->getDestination()
108 << " to existing prefix: " << *nameItr);
109 nameItr->addRoutingTableEntry(rtpePtr);
110 nameItr->generateNhlfromRteList();
111
112 if (nameItr->getNexthopList().getSize() > 0) {
113 _LOG_TRACE("Updating FIB with next hops for " << (*nameItr));
114 m_nlsr.getFib().update(name, nameItr->getNexthopList());
115 }
116 else {
117 _LOG_TRACE((*nameItr) << " has no next hops; removing from FIB");
118 m_nlsr.getFib().remove(name);
119 }
akmhoque53353462014-04-22 08:43:45 -0500120 }
121}
122
123void
akmhoque31d1d4b2014-05-05 22:08:14 -0500124NamePrefixTable::removeEntry(const ndn::Name& name, const ndn::Name& destRouter)
akmhoque53353462014-04-22 08:43:45 -0500125{
Vince Lehmancae33b62015-06-05 09:21:30 -0500126 _LOG_DEBUG("Removing origin: " << destRouter << " from " << name);
127
Nick Gordonb50e51b2016-07-22 16:05:57 -0500128 // Fetch an iterator to the appropriate pair object in the pool.
129 RtpEntryMap::iterator rtpeItr = m_rtpool.find(destRouter);
Vince Lehmancae33b62015-06-05 09:21:30 -0500130
Nick Gordonb50e51b2016-07-22 16:05:57 -0500131 // Simple error checking to prevent any unusual behavior in the case
132 // that we try to remove an entry that isn't there.
133 if (rtpeItr == m_rtpool.end()) {
134 _LOG_DEBUG("No entry for origin: " << destRouter
135 << " found, so it cannot be removed from prefix: "
136 << name);
137 return;
138 }
139 std::shared_ptr<RoutingTablePoolEntry> rtpePtr = rtpeItr->second;
140
141 // Ensure that the entry exists
Ashlesh Gawande90173ad2017-08-09 15:19:50 -0500142 NptEntryList::iterator nameItr = std::find_if(m_table.begin(), m_table.end(),
143 std::bind(&npteCompare, _1, name));
Nick Gordonb50e51b2016-07-22 16:05:57 -0500144 if (nameItr != m_table.end()) {
145 _LOG_TRACE("Removing origin: " << rtpePtr->getDestination()
146 << " from prefix: " << *nameItr);
147
148 // Rather than iterating through the whole list periodically, just
149 // delete them here if they have no references.
150 if ((*nameItr).removeRoutingTableEntry(rtpePtr) == 0) {
151 deleteRtpeFromPool(rtpePtr);
152 }
153
154 // If the prefix is a router prefix and it does not have any other
155 // routing table entries, the Adjacency/Coordinate LSA associated
156 // with that origin router has been removed from the LSDB and so
157 // the router prefix should be removed from the Name Prefix Table.
158 //
159 // If the prefix is an advertised name prefix: If another router
160 // advertises this name prefix, the RteList should have another
161 // entry for that router; the next hops should be recalculated
162 // and installed in the FIB.
163 //
164 // If no other router advertises this name prefix, the RteList
165 // should be empty and the prefix can be removed from the Name
166 // Prefix Table. Once a new Name LSA advertises this prefix, a
167 // new entry for the prefix will be created.
168 //
169 if ((*nameItr).getRteListSize() == 0) {
170 _LOG_TRACE(*nameItr << " has no routing table entries;"
171 << " removing from table and FIB");
172 m_table.erase(nameItr);
173 m_nlsr.getFib().remove(name);
174 }
175 else {
176 _LOG_TRACE(*nameItr << " has other routing table entries;"
177 << " updating FIB with next hops");
178 (*nameItr).generateNhlfromRteList();
179 m_nlsr.getFib().update(name, (*nameItr).getNexthopList());
180 }
akmhoque53353462014-04-22 08:43:45 -0500181 }
akmhoque157b0a42014-05-13 00:26:37 -0500182 else {
Nick Gordonb50e51b2016-07-22 16:05:57 -0500183 _LOG_DEBUG("Attempted to remove origin: " << rtpePtr->getDestination()
Ashlesh Gawande90173ad2017-08-09 15:19:50 -0500184 << " from non-existent prefix: " << name);
akmhoque53353462014-04-22 08:43:45 -0500185 }
186}
187
188void
akmhoque31d1d4b2014-05-05 22:08:14 -0500189NamePrefixTable::updateWithNewRoute()
akmhoque53353462014-04-22 08:43:45 -0500190{
Vince Lehmancae33b62015-06-05 09:21:30 -0500191 _LOG_DEBUG("Updating table with newly calculated routes");
192
Nick Gordonb50e51b2016-07-22 16:05:57 -0500193 // Update each name prefix table entry in the NPT with the
194 // newly calculated next hops.
195 for (auto&& npte : m_table) {
196 // For each routing table pool entry in this NPT entry.
197 for (auto&& rtpe : npte.getRteList()) {
198 _LOG_TRACE("Updating next hops to origin: " << rtpe->getDestination()
199 << " for prefix: " << npte);
akmhoqueb6450b12014-04-24 00:01:03 -0500200 RoutingTableEntry* rteCheck =
Nick Gordonb50e51b2016-07-22 16:05:57 -0500201 m_nlsr.getRoutingTable().findRoutingTableEntry(rtpe->getDestination());
Vince Lehmancae33b62015-06-05 09:21:30 -0500202
Nick G97e34942016-07-11 14:46:27 -0500203 // If there is a routing table entry for this prefix, update the NPT with it.
Vince Lehmancae33b62015-06-05 09:21:30 -0500204 if (rteCheck != nullptr) {
Nick Gordonb50e51b2016-07-22 16:05:57 -0500205 rtpe->setNexthopList(rteCheck->getNexthopList());
akmhoque53353462014-04-22 08:43:45 -0500206 }
akmhoque157b0a42014-05-13 00:26:37 -0500207 else {
Nick Gordonb50e51b2016-07-22 16:05:57 -0500208 rtpe->getNexthopList().reset();
akmhoque53353462014-04-22 08:43:45 -0500209 }
Nick Gordonb50e51b2016-07-22 16:05:57 -0500210 addEntry(npte.getNamePrefix(), rtpe->getDestination());
akmhoque53353462014-04-22 08:43:45 -0500211 }
212 }
213}
214
Nick Gordonb50e51b2016-07-22 16:05:57 -0500215 // Inserts the routing table pool entry into the NPT's RTE storage
216 // pool. This cannot fail, so the pool is guaranteed to contain the
217 // item after this occurs.
218std::shared_ptr<RoutingTablePoolEntry>
219NamePrefixTable::addRtpeToPool(RoutingTablePoolEntry& rtpe)
220{
221 RtpEntryMap::iterator poolItr =
222 m_rtpool.insert(std::make_pair(rtpe.getDestination(),
223 std::make_shared<RoutingTablePoolEntry>
224 (rtpe)))
225 .first;
226 //| There's gotta be a more efficient way to do this
227 //std::shared_ptr<RoutingTablePoolEntry> poolPtr = &(poolItr->second);
228 return poolItr->second;
229}
230
231 // Removes the routing table pool entry from the storage pool. The
232 // postconditions of this function are guaranteed to include that
233 // the storage pool does not contain such an item. Additionally,
234 // this function cannot fail, but nonetheless debug information is
235 // given in the case that this function is called with an entry that
236 // isn't in the pool.
237void
238NamePrefixTable::deleteRtpeFromPool(std::shared_ptr<RoutingTablePoolEntry> rtpePtr)
239{
240 if (m_rtpool.erase(rtpePtr->getDestination()) != 1) {
Ashlesh Gawande90173ad2017-08-09 15:19:50 -0500241 _LOG_DEBUG("Attempted to delete non-existent origin: "
Nick Gordonb50e51b2016-07-22 16:05:57 -0500242 << rtpePtr->getDestination()
243 << " from NPT routing table entry storage pool.");
244 }
245}
246
akmhoque53353462014-04-22 08:43:45 -0500247void
akmhoque674b0b12014-05-20 14:33:28 -0500248NamePrefixTable::writeLog()
249{
Vince Lehmancae33b62015-06-05 09:21:30 -0500250 _LOG_DEBUG(*this);
akmhoque674b0b12014-05-20 14:33:28 -0500251}
252
Vince Lehmancae33b62015-06-05 09:21:30 -0500253std::ostream&
254operator<<(std::ostream& os, const NamePrefixTable& table)
255{
256 os << "----------------NPT----------------------\n";
257
258 for (const NamePrefixTableEntry& entry : table) {
259 os << entry << std::endl;
260 }
261
262 return os;
263}
264
265} // namespace nlsr