blob: e743276e9861e7f77fad03228f9367d47e3cdd09 [file] [log] [blame]
akmhoque3d06e792014-05-27 16:23:20 -05001/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
2/**
Muktadir R Chowdhury800833b2016-07-29 13:43:59 -05003 * Copyright (c) 2014-2016, 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(),
48 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
142 NptEntryList::iterator nameItr = std::find_if(m_table.begin(),
143 m_table.end(),
144 bind(&npteCompare, _1, name));
145 if (nameItr != m_table.end()) {
146 _LOG_TRACE("Removing origin: " << rtpePtr->getDestination()
147 << " from prefix: " << *nameItr);
148
149 // Rather than iterating through the whole list periodically, just
150 // delete them here if they have no references.
151 if ((*nameItr).removeRoutingTableEntry(rtpePtr) == 0) {
152 deleteRtpeFromPool(rtpePtr);
153 }
154
155 // If the prefix is a router prefix and it does not have any other
156 // routing table entries, the Adjacency/Coordinate LSA associated
157 // with that origin router has been removed from the LSDB and so
158 // the router prefix should be removed from the Name Prefix Table.
159 //
160 // If the prefix is an advertised name prefix: If another router
161 // advertises this name prefix, the RteList should have another
162 // entry for that router; the next hops should be recalculated
163 // and installed in the FIB.
164 //
165 // If no other router advertises this name prefix, the RteList
166 // should be empty and the prefix can be removed from the Name
167 // Prefix Table. Once a new Name LSA advertises this prefix, a
168 // new entry for the prefix will be created.
169 //
170 if ((*nameItr).getRteListSize() == 0) {
171 _LOG_TRACE(*nameItr << " has no routing table entries;"
172 << " removing from table and FIB");
173 m_table.erase(nameItr);
174 m_nlsr.getFib().remove(name);
175 }
176 else {
177 _LOG_TRACE(*nameItr << " has other routing table entries;"
178 << " updating FIB with next hops");
179 (*nameItr).generateNhlfromRteList();
180 m_nlsr.getFib().update(name, (*nameItr).getNexthopList());
181 }
akmhoque53353462014-04-22 08:43:45 -0500182 }
akmhoque157b0a42014-05-13 00:26:37 -0500183 else {
Nick Gordonb50e51b2016-07-22 16:05:57 -0500184 _LOG_DEBUG("Attempted to remove origin: " << rtpePtr->getDestination()
185 << " from non-existant prefix: " << name);
akmhoque53353462014-04-22 08:43:45 -0500186 }
187}
188
189void
akmhoque31d1d4b2014-05-05 22:08:14 -0500190NamePrefixTable::updateWithNewRoute()
akmhoque53353462014-04-22 08:43:45 -0500191{
Vince Lehmancae33b62015-06-05 09:21:30 -0500192 _LOG_DEBUG("Updating table with newly calculated routes");
193
Nick Gordonb50e51b2016-07-22 16:05:57 -0500194 // Update each name prefix table entry in the NPT with the
195 // newly calculated next hops.
196 for (auto&& npte : m_table) {
197 // For each routing table pool entry in this NPT entry.
198 for (auto&& rtpe : npte.getRteList()) {
199 _LOG_TRACE("Updating next hops to origin: " << rtpe->getDestination()
200 << " for prefix: " << npte);
akmhoqueb6450b12014-04-24 00:01:03 -0500201 RoutingTableEntry* rteCheck =
Nick Gordonb50e51b2016-07-22 16:05:57 -0500202 m_nlsr.getRoutingTable().findRoutingTableEntry(rtpe->getDestination());
Vince Lehmancae33b62015-06-05 09:21:30 -0500203
Nick G97e34942016-07-11 14:46:27 -0500204 // If there is a routing table entry for this prefix, update the NPT with it.
Vince Lehmancae33b62015-06-05 09:21:30 -0500205 if (rteCheck != nullptr) {
Nick Gordonb50e51b2016-07-22 16:05:57 -0500206 rtpe->setNexthopList(rteCheck->getNexthopList());
akmhoque53353462014-04-22 08:43:45 -0500207 }
akmhoque157b0a42014-05-13 00:26:37 -0500208 else {
Nick Gordonb50e51b2016-07-22 16:05:57 -0500209 rtpe->getNexthopList().reset();
akmhoque53353462014-04-22 08:43:45 -0500210 }
Nick Gordonb50e51b2016-07-22 16:05:57 -0500211 addEntry(npte.getNamePrefix(), rtpe->getDestination());
akmhoque53353462014-04-22 08:43:45 -0500212 }
213 }
214}
215
Nick Gordonb50e51b2016-07-22 16:05:57 -0500216 // Inserts the routing table pool entry into the NPT's RTE storage
217 // pool. This cannot fail, so the pool is guaranteed to contain the
218 // item after this occurs.
219std::shared_ptr<RoutingTablePoolEntry>
220NamePrefixTable::addRtpeToPool(RoutingTablePoolEntry& rtpe)
221{
222 RtpEntryMap::iterator poolItr =
223 m_rtpool.insert(std::make_pair(rtpe.getDestination(),
224 std::make_shared<RoutingTablePoolEntry>
225 (rtpe)))
226 .first;
227 //| There's gotta be a more efficient way to do this
228 //std::shared_ptr<RoutingTablePoolEntry> poolPtr = &(poolItr->second);
229 return poolItr->second;
230}
231
232 // Removes the routing table pool entry from the storage pool. The
233 // postconditions of this function are guaranteed to include that
234 // the storage pool does not contain such an item. Additionally,
235 // this function cannot fail, but nonetheless debug information is
236 // given in the case that this function is called with an entry that
237 // isn't in the pool.
238void
239NamePrefixTable::deleteRtpeFromPool(std::shared_ptr<RoutingTablePoolEntry> rtpePtr)
240{
241 if (m_rtpool.erase(rtpePtr->getDestination()) != 1) {
242 _LOG_DEBUG("Attempted to delete non-existant origin: "
243 << rtpePtr->getDestination()
244 << " from NPT routing table entry storage pool.");
245 }
246}
247
akmhoque53353462014-04-22 08:43:45 -0500248void
akmhoque674b0b12014-05-20 14:33:28 -0500249NamePrefixTable::writeLog()
250{
Vince Lehmancae33b62015-06-05 09:21:30 -0500251 _LOG_DEBUG(*this);
akmhoque674b0b12014-05-20 14:33:28 -0500252}
253
Vince Lehmancae33b62015-06-05 09:21:30 -0500254std::ostream&
255operator<<(std::ostream& os, const NamePrefixTable& table)
256{
257 os << "----------------NPT----------------------\n";
258
259 for (const NamePrefixTableEntry& entry : table) {
260 os << entry << std::endl;
261 }
262
263 return os;
264}
265
266} // namespace nlsr