blob: 7d113ee586d48539263e11aa095562f7fb9cc437 [file] [log] [blame]
akmhoque3d06e792014-05-27 16:23:20 -05001/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
Ashlesh Gawande57a87172020-05-09 19:47:06 -07002/*
Junxiao Shib5734842024-01-09 21:14:53 +00003 * Copyright (c) 2014-2024, The University of Memphis,
Vince Lehman41b173e2015-05-07 14:13:26 -05004 * 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 Gawande57a87172020-05-09 19:47:06 -070020 */
Nick Gordone40377d2017-08-11 15:10:02 -050021
Junxiao Shiaead5882024-02-21 12:32:02 +000022#include "routing-calculator.hpp"
Junxiao Shi4eb4eae2024-02-14 12:36:57 +000023#include "name-map.hpp"
akmhoque53353462014-04-22 08:43:45 -050024#include "nexthop.hpp"
akmhoque53353462014-04-22 08:43:45 -050025
Junxiao Shiaead5882024-02-21 12:32:02 +000026#include "adjacent.hpp"
27#include "logger.hpp"
28#include "nlsr.hpp"
29
Davide Pesaventoc1d0e8e2022-06-15 14:26:02 -040030#include <boost/lexical_cast.hpp>
Vince Lehman9a709032014-09-13 16:28:07 -050031
akmhoque53353462014-04-22 08:43:45 -050032namespace nlsr {
33
Junxiao Shiaead5882024-02-21 12:32:02 +000034INIT_LOGGER(route.RoutingCalculatorLinkState);
35
36class RoutingTableCalculator
37{
38public:
39 RoutingTableCalculator(size_t nRouters)
40 {
41 m_nRouters = nRouters;
42 }
43
44protected:
45 /*! \brief Allocate the space needed for the adj. matrix. */
46 void
47 allocateAdjMatrix();
48
49 /*! \brief set NON_ADJACENT_COST i.e. -12345 to every cell of the matrix to
50 ensure that the memory is safe. This is also to incorporate zero cost links */
51 void
52 initMatrix();
53
54 /*! \brief Constructs an adj. matrix to calculate with.
55 \param lsdb Reference to the Lsdb
56 \param pMap The map to populate with the adj. data.
57 */
58 void
59 makeAdjMatrix(const Lsdb& lsdb, NameMap& pMap);
60
61 /*! \brief Writes a formated adjacent matrix to DEBUG log
62 \param map The map containing adjacent matrix data
63 */
64 void
65 writeAdjMatrixLog(const NameMap& map) const;
66
67 /*! \brief Returns how many links a router in the matrix has.
68 \param sRouter The router to count the links of.
69 */
70 int
71 getNumOfLinkfromAdjMatrix(int sRouter);
72
73 void
74 freeAdjMatrix();
75 /*! \brief Adjust a link cost in the adj. matrix
76 \param source The source router whose adjacency to adjust.
77 \param link The adjacency of the source to adjust.
78 \param linkCost The cost to change to.
79 */
80 void
81 adjustAdMatrix(int source, int link, double linkCost);
82
83 /*! \brief Populates temp. variables with the link costs for some router.
84 \param source The router whose values are to be adjusted.
85 \param links An integer pointer array for the link mappingNos.
86 \param linkCosts A double pointer array that stores the link costs.
87
88 Obtains a sparse list of adjacencies and link costs for some
89 router. Since this is sparse, that means while generating these
90 arrays, if there is no adjacency at i in the matrix, these
91 temporary variables will not contain a NON_ADJACENT_COST (-12345) at i,
92 but rather will contain the values for the next valid adjacency.
93 */
94 void
95 getLinksFromAdjMatrix(int* links, double* linkCosts, int source);
96
97 /*! Allocates an array large enough to hold multipath calculation temps. */
98 void
99 allocateLinks();
100
101 void
102 allocateLinkCosts();
103
104 void
105 freeLinks();
106
107 void
108 freeLinksCosts();
109
110 void
111 setNoLink(int nl)
112 {
113 vNoLink = nl;
114 }
115
116protected:
117 double** adjMatrix;
118 size_t m_nRouters;
119
120 int vNoLink;
121 int* links;
122 double* linkCosts;
123
124};
125
126class LinkStateRoutingTableCalculator: public RoutingTableCalculator
127{
128public:
129 LinkStateRoutingTableCalculator(size_t nRouters)
130 : RoutingTableCalculator(nRouters)
131 {
132 }
133
134 void
135 calculatePath(NameMap& pMap, RoutingTable& rt, ConfParameter& confParam,
136 const Lsdb& lsdb);
137
138private:
139 /*! \brief Performs a Dijkstra's calculation over the adjacency matrix.
140 \param sourceRouter The origin router to compute paths from.
141 */
142 void
143 doDijkstraPathCalculation(int sourceRouter);
144
145 /*! \brief Sort the elements of a list.
146 \param Q The array that contains the elements to sort.
147 \param dist The array that contains the distances.
148 \param start The first element in the list to sort.
149 \param element The last element in the list to sort through.
150
151 Sorts the list based on distance. The distances are indexed by
152 their mappingNo in dist. Currently uses an insertion sort.
153
154 The cost between two nodes can be zero or greater than zero.
155
156 */
157 void
158 sortQueueByDistance(int* Q, double* dist, int start, int element);
159
160 /*! \brief Returns whether an element has been visited yet.
161 \param Q The list of elements to look through.
162 \param u The element to check.
163 \param start The start of list to look through.
164 \param element The end of the list to look through.
165 */
166 int
167 isNotExplored(int* Q, int u, int start, int element);
168
169 void
170 addAllLsNextHopsToRoutingTable(AdjacencyList& adjacencies, RoutingTable& rt,
171 NameMap& pMap, uint32_t sourceRouter);
172
173 /*! \brief Determines a destination's next hop.
174 \param dest The router whose next hop we want to determine.
175 \param source The router to determine a next path to.
176 */
177 int
178 getLsNextHop(int dest, int source);
179
180 void
181 allocateParent();
182
183 void
184 allocateDistance();
185
186 void
187 freeParent();
188
189 void
190 freeDistance();
191
192private:
193 int* m_parent;
194 double* m_distance;
195};
akmhoque53353462014-04-22 08:43:45 -0500196
Davide Pesavento658fd852023-05-10 22:15:03 -0400197constexpr int EMPTY_PARENT = -12345;
198constexpr double INF_DISTANCE = 2147483647;
199constexpr int NO_MAPPING_NUM = -1;
200constexpr int NO_NEXT_HOP = -12345;
dulalsaurabd0816a32019-07-26 13:11:24 +0000201
akmhoque53353462014-04-22 08:43:45 -0500202void
203RoutingTableCalculator::allocateAdjMatrix()
204{
Vince Lehman9a709032014-09-13 16:28:07 -0500205 adjMatrix = new double*[m_nRouters];
206
207 for (size_t i = 0; i < m_nRouters; ++i) {
208 adjMatrix[i] = new double[m_nRouters];
akmhoque53353462014-04-22 08:43:45 -0500209 }
210}
211
212void
213RoutingTableCalculator::initMatrix()
214{
Vince Lehman9a709032014-09-13 16:28:07 -0500215 for (size_t i = 0; i < m_nRouters; i++) {
216 for (size_t j = 0; j < m_nRouters; j++) {
dulalsaurabd0816a32019-07-26 13:11:24 +0000217 adjMatrix[i][j] = Adjacent::NON_ADJACENT_COST;
akmhoque157b0a42014-05-13 00:26:37 -0500218 }
akmhoque53353462014-04-22 08:43:45 -0500219 }
220}
221
222void
Junxiao Shi4eb4eae2024-02-14 12:36:57 +0000223RoutingTableCalculator::makeAdjMatrix(const Lsdb& lsdb, NameMap& pMap)
akmhoque53353462014-04-22 08:43:45 -0500224{
Nick G97e34942016-07-11 14:46:27 -0500225 // For each LSA represented in the map
Ashlesh Gawande57a87172020-05-09 19:47:06 -0700226 auto lsaRange = lsdb.getLsdbIterator<AdjLsa>();
227 for (auto lsaIt = lsaRange.first; lsaIt != lsaRange.second; ++lsaIt) {
228 auto adjLsa = std::static_pointer_cast<AdjLsa>(*lsaIt);
Davide Pesaventoc1d0e8e2022-06-15 14:26:02 -0400229 auto row = pMap.getMappingNoByRouterName(adjLsa->getOriginRouter());
Vince Lehman9a709032014-09-13 16:28:07 -0500230
Ashlesh Gawande57a87172020-05-09 19:47:06 -0700231 std::list<Adjacent> adl = adjLsa->getAdl().getAdjList();
Nick G97e34942016-07-11 14:46:27 -0500232 // For each adjacency represented in the LSA
Ashlesh Gawande85998a12017-12-07 22:22:13 -0600233 for (const auto& adjacent : adl) {
Davide Pesaventoc1d0e8e2022-06-15 14:26:02 -0400234 auto col = pMap.getMappingNoByRouterName(adjacent.getName());
Ashlesh Gawande85998a12017-12-07 22:22:13 -0600235 double cost = adjacent.getLinkCost();
Vince Lehman9a709032014-09-13 16:28:07 -0500236
Nick Gordone40377d2017-08-11 15:10:02 -0500237 if (row && col && *row < static_cast<int32_t>(m_nRouters)
Davide Pesaventoc1d0e8e2022-06-15 14:26:02 -0400238 && *col < static_cast<int32_t>(m_nRouters)) {
Nick Gordone40377d2017-08-11 15:10:02 -0500239 adjMatrix[*row][*col] = cost;
akmhoque53353462014-04-22 08:43:45 -0500240 }
241 }
242 }
Vince Lehman41b173e2015-05-07 14:13:26 -0500243
Nick G97e34942016-07-11 14:46:27 -0500244 // Links that do not have the same cost for both directions should
245 // have their costs corrected:
Vince Lehman41b173e2015-05-07 14:13:26 -0500246 //
dulalsaurabd0816a32019-07-26 13:11:24 +0000247 // If the cost of one side of the link is NON_ADJACENT_COST (i.e. broken) or negative,
248 // both direction of the link should have their cost corrected to NON_ADJACENT_COST.
Vince Lehman41b173e2015-05-07 14:13:26 -0500249 //
250 // Otherwise, both sides of the link should use the larger of the two costs.
251 //
Nick G97e34942016-07-11 14:46:27 -0500252 // Additionally, this means that we can halve the amount of space
253 // that the matrix uses by only maintaining a triangle.
254 // - But that is not yet implemented.
Vince Lehman41b173e2015-05-07 14:13:26 -0500255 for (size_t row = 0; row < m_nRouters; ++row) {
256 for (size_t col = 0; col < m_nRouters; ++col) {
257 double toCost = adjMatrix[row][col];
258 double fromCost = adjMatrix[col][row];
259
260 if (fromCost != toCost) {
dulalsaurabd0816a32019-07-26 13:11:24 +0000261 double correctedCost = Adjacent::NON_ADJACENT_COST;
Vince Lehman41b173e2015-05-07 14:13:26 -0500262
dulalsaurabd0816a32019-07-26 13:11:24 +0000263 if (toCost >= 0 && fromCost >= 0) {
264 // If both sides of the link are up, use the larger cost else break the link
Vince Lehman41b173e2015-05-07 14:13:26 -0500265 correctedCost = std::max(toCost, fromCost);
266 }
267
dmcoomes5bcb39e2017-10-31 15:07:55 -0500268 NLSR_LOG_WARN("Cost between [" << row << "][" << col << "] and [" << col << "][" << row <<
Vince Lehman41b173e2015-05-07 14:13:26 -0500269 "] are not the same (" << toCost << " != " << fromCost << "). " <<
270 "Correcting to cost: " << correctedCost);
271
272 adjMatrix[row][col] = correctedCost;
273 adjMatrix[col][row] = correctedCost;
274 }
275 }
276 }
akmhoque53353462014-04-22 08:43:45 -0500277}
278
279void
Junxiao Shi4eb4eae2024-02-14 12:36:57 +0000280RoutingTableCalculator::writeAdjMatrixLog(const NameMap& map) const
akmhoque53353462014-04-22 08:43:45 -0500281{
Ashlesh Gawandecba0ae22018-03-27 17:57:56 -0500282 if (!ndn_cxx_getLogger().isLevelEnabled(ndn::util::LogLevel::DEBUG)) {
Saurab Dulal9da6aa72018-01-12 17:25:51 +0000283 return;
284 }
285
286 NLSR_LOG_DEBUG("-----------Legend (routerName -> index)------");
287 std::string routerIndex;
288 std::string indexToNameMapping;
289 std::string lengthOfDash = "--";
290
Vince Lehman9a709032014-09-13 16:28:07 -0500291 for (size_t i = 0; i < m_nRouters; i++) {
Saurab Dulal9da6aa72018-01-12 17:25:51 +0000292 routerIndex += boost::lexical_cast<std::string>(i);
293 routerIndex += " ";
294 lengthOfDash += "--";
295 NLSR_LOG_DEBUG("Router:" + map.getRouterNameByMappingNo(i)->toUri() +
Ashlesh Gawandecba0ae22018-03-27 17:57:56 -0500296 " Index:" + boost::lexical_cast<std::string>(i));
Saurab Dulal9da6aa72018-01-12 17:25:51 +0000297 }
298 NLSR_LOG_DEBUG(" |" + routerIndex);
299 NLSR_LOG_DEBUG(lengthOfDash);
300
301 for (size_t i = 0; i < m_nRouters; i++) {
302 std::string line;
Vince Lehman9a709032014-09-13 16:28:07 -0500303 for (size_t j = 0; j < m_nRouters; j++) {
Davide Pesaventoc1d0e8e2022-06-15 14:26:02 -0400304 if (adjMatrix[i][j] == NO_NEXT_HOP) {
Ashlesh Gawande6b388fc2019-09-30 10:14:41 -0500305 line += "0 ";
306 }
307 else {
308 line += boost::lexical_cast<std::string>(adjMatrix[i][j]);
309 line += " ";
310 }
akmhoque157b0a42014-05-13 00:26:37 -0500311 }
Saurab Dulal9da6aa72018-01-12 17:25:51 +0000312 line = boost::lexical_cast<std::string>(i) + "|" + line;
dmcoomes5bcb39e2017-10-31 15:07:55 -0500313 NLSR_LOG_DEBUG(line);
akmhoque53353462014-04-22 08:43:45 -0500314 }
315}
316
317void
318RoutingTableCalculator::adjustAdMatrix(int source, int link, double linkCost)
319{
Vince Lehman9a709032014-09-13 16:28:07 -0500320 for (int i = 0; i < static_cast<int>(m_nRouters); i++) {
akmhoque157b0a42014-05-13 00:26:37 -0500321 if (i == link) {
akmhoque53353462014-04-22 08:43:45 -0500322 adjMatrix[source][i] = linkCost;
323 }
akmhoque157b0a42014-05-13 00:26:37 -0500324 else {
dulalsaurabd0816a32019-07-26 13:11:24 +0000325 // if "i" is not a link to the source, set it's cost to a non adjacent value.
326 adjMatrix[source][i] = Adjacent::NON_ADJACENT_COST;
akmhoque53353462014-04-22 08:43:45 -0500327 }
328 }
329}
330
331int
332RoutingTableCalculator::getNumOfLinkfromAdjMatrix(int sRouter)
333{
334 int noLink = 0;
Vince Lehman9a709032014-09-13 16:28:07 -0500335
336 for (size_t i = 0; i < m_nRouters; i++) {
dulalsaurabd0816a32019-07-26 13:11:24 +0000337 if (adjMatrix[sRouter][i] >= 0 && i != static_cast<size_t>(sRouter)) { // make sure "i" is not self
akmhoque53353462014-04-22 08:43:45 -0500338 noLink++;
339 }
340 }
341 return noLink;
342}
343
344void
345RoutingTableCalculator::getLinksFromAdjMatrix(int* links,
346 double* linkCosts, int source)
347{
348 int j = 0;
Vince Lehman9a709032014-09-13 16:28:07 -0500349
350 for (size_t i = 0; i < m_nRouters; i++) {
dulalsaurabd0816a32019-07-26 13:11:24 +0000351 if (adjMatrix[source][i] >= 0 && i != static_cast<size_t>(source)) {// make sure "i" is not self
akmhoque53353462014-04-22 08:43:45 -0500352 links[j] = i;
353 linkCosts[j] = adjMatrix[source][i];
354 j++;
355 }
356 }
357}
358
359void
360RoutingTableCalculator::freeAdjMatrix()
361{
Vince Lehman9a709032014-09-13 16:28:07 -0500362 for (size_t i = 0; i < m_nRouters; ++i) {
akmhoque53353462014-04-22 08:43:45 -0500363 delete [] adjMatrix[i];
364 }
365 delete [] adjMatrix;
366}
367
akmhoque53353462014-04-22 08:43:45 -0500368void
369RoutingTableCalculator::allocateLinks()
370{
371 links = new int[vNoLink];
372}
373
374void
375RoutingTableCalculator::allocateLinkCosts()
376{
377 linkCosts = new double[vNoLink];
378}
379
akmhoque53353462014-04-22 08:43:45 -0500380void
381RoutingTableCalculator::freeLinks()
382{
383 delete [] links;
384}
385void
386RoutingTableCalculator::freeLinksCosts()
387{
388 delete [] linkCosts;
389}
390
391void
Junxiao Shi4eb4eae2024-02-14 12:36:57 +0000392LinkStateRoutingTableCalculator::calculatePath(NameMap& pMap, RoutingTable& rt,
Ashlesh Gawande85998a12017-12-07 22:22:13 -0600393 ConfParameter& confParam,
Ashlesh Gawande57a87172020-05-09 19:47:06 -0700394 const Lsdb& lsdb)
akmhoque53353462014-04-22 08:43:45 -0500395{
dmcoomes5bcb39e2017-10-31 15:07:55 -0500396 NLSR_LOG_DEBUG("LinkStateRoutingTableCalculator::calculatePath Called");
akmhoque53353462014-04-22 08:43:45 -0500397 allocateAdjMatrix();
398 initMatrix();
Ashlesh Gawande57a87172020-05-09 19:47:06 -0700399 makeAdjMatrix(lsdb, pMap);
Saurab Dulal9da6aa72018-01-12 17:25:51 +0000400 writeAdjMatrixLog(pMap);
Davide Pesaventoc1d0e8e2022-06-15 14:26:02 -0400401 auto sourceRouter = pMap.getMappingNoByRouterName(confParam.getRouterPrefix());
Nick G97e34942016-07-11 14:46:27 -0500402 allocateParent(); // These two matrices are used in Dijkstra's algorithm.
403 allocateDistance(); //
Nick Gordone40377d2017-08-11 15:10:02 -0500404 // We only bother to do the calculation if we have a router by that name.
Ashlesh Gawande85998a12017-12-07 22:22:13 -0600405 if (sourceRouter && confParam.getMaxFacesPerPrefix() == 1) {
Nick G97e34942016-07-11 14:46:27 -0500406 // In the single path case we can simply run Dijkstra's algorithm.
Nick Gordone40377d2017-08-11 15:10:02 -0500407 doDijkstraPathCalculation(*sourceRouter);
Nick G97e34942016-07-11 14:46:27 -0500408 // Inform the routing table of the new next hops.
Ashlesh Gawande85998a12017-12-07 22:22:13 -0600409 addAllLsNextHopsToRoutingTable(confParam.getAdjacencyList(), rt, pMap, *sourceRouter);
akmhoque53353462014-04-22 08:43:45 -0500410 }
akmhoque157b0a42014-05-13 00:26:37 -0500411 else {
akmhoque53353462014-04-22 08:43:45 -0500412 // Multi Path
Nick Gordone40377d2017-08-11 15:10:02 -0500413 setNoLink(getNumOfLinkfromAdjMatrix(*sourceRouter));
akmhoque53353462014-04-22 08:43:45 -0500414 allocateLinks();
415 allocateLinkCosts();
Nick G97e34942016-07-11 14:46:27 -0500416 // Gets a sparse listing of adjacencies for path calculation
Nick Gordone40377d2017-08-11 15:10:02 -0500417 getLinksFromAdjMatrix(links, linkCosts, *sourceRouter);
akmhoque157b0a42014-05-13 00:26:37 -0500418 for (int i = 0 ; i < vNoLink; i++) {
Nick G97e34942016-07-11 14:46:27 -0500419 // Simulate that only the current neighbor is accessible
Nick Gordone40377d2017-08-11 15:10:02 -0500420 adjustAdMatrix(*sourceRouter, links[i], linkCosts[i]);
Saurab Dulal9da6aa72018-01-12 17:25:51 +0000421 writeAdjMatrixLog(pMap);
Nick G97e34942016-07-11 14:46:27 -0500422 // Do Dijkstra's algorithm using the current neighbor as your start.
Nick Gordone40377d2017-08-11 15:10:02 -0500423 doDijkstraPathCalculation(*sourceRouter);
Nick G97e34942016-07-11 14:46:27 -0500424 // Update the routing table with the calculations.
Ashlesh Gawande85998a12017-12-07 22:22:13 -0600425 addAllLsNextHopsToRoutingTable(confParam.getAdjacencyList(), rt, pMap, *sourceRouter);
akmhoque53353462014-04-22 08:43:45 -0500426 }
427 freeLinks();
428 freeLinksCosts();
429 }
430 freeParent();
431 freeDistance();
432 freeAdjMatrix();
433}
434
435void
436LinkStateRoutingTableCalculator::doDijkstraPathCalculation(int sourceRouter)
437{
438 int i;
439 int v, u;
Nick G97e34942016-07-11 14:46:27 -0500440 int* Q = new int[m_nRouters]; // Each cell represents the router with that mapping no.
akmhoque53353462014-04-22 08:43:45 -0500441 int head = 0;
Nick Gordone98480b2017-05-24 11:23:03 -0500442 // Initiate the parent
Vince Lehman9a709032014-09-13 16:28:07 -0500443 for (i = 0 ; i < static_cast<int>(m_nRouters); i++) {
akmhoque53353462014-04-22 08:43:45 -0500444 m_parent[i] = EMPTY_PARENT;
Nick G97e34942016-07-11 14:46:27 -0500445 // Array where the ith element is the distance to the router with mapping no i.
akmhoque53353462014-04-22 08:43:45 -0500446 m_distance[i] = INF_DISTANCE;
447 Q[i] = i;
448 }
akmhoque157b0a42014-05-13 00:26:37 -0500449 if (sourceRouter != NO_MAPPING_NUM) {
Nick G97e34942016-07-11 14:46:27 -0500450 // Distance to source from source is always 0.
akmhoque53353462014-04-22 08:43:45 -0500451 m_distance[sourceRouter] = 0;
Vince Lehman9a709032014-09-13 16:28:07 -0500452 sortQueueByDistance(Q, m_distance, head, m_nRouters);
Nick G97e34942016-07-11 14:46:27 -0500453 // While we haven't visited every node.
Vince Lehman9a709032014-09-13 16:28:07 -0500454 while (head < static_cast<int>(m_nRouters)) {
Nick G97e34942016-07-11 14:46:27 -0500455 u = Q[head]; // Set u to be the current node pointed to by head.
akmhoque157b0a42014-05-13 00:26:37 -0500456 if (m_distance[u] == INF_DISTANCE) {
Nick G97e34942016-07-11 14:46:27 -0500457 break; // This can only happen when there are no accessible nodes.
akmhoque53353462014-04-22 08:43:45 -0500458 }
Nick G97e34942016-07-11 14:46:27 -0500459 // Iterate over the adjacent nodes to u.
Vince Lehman9a709032014-09-13 16:28:07 -0500460 for (v = 0 ; v < static_cast<int>(m_nRouters); v++) {
Nick G97e34942016-07-11 14:46:27 -0500461 // If the current node is accessible.
dulalsaurabd0816a32019-07-26 13:11:24 +0000462 if (adjMatrix[u][v] >= 0) {
Nick G97e34942016-07-11 14:46:27 -0500463 // And we haven't visited it yet.
Vince Lehman9a709032014-09-13 16:28:07 -0500464 if (isNotExplored(Q, v, head + 1, m_nRouters)) {
Nick G97e34942016-07-11 14:46:27 -0500465 // And if the distance to this node + from this node to v
466 // is less than the distance from our source node to v
467 // that we got when we built the adj LSAs
akmhoque157b0a42014-05-13 00:26:37 -0500468 if (m_distance[u] + adjMatrix[u][v] < m_distance[v]) {
Nick G97e34942016-07-11 14:46:27 -0500469 // Set the new distance
akmhoque53353462014-04-22 08:43:45 -0500470 m_distance[v] = m_distance[u] + adjMatrix[u][v] ;
Nick G97e34942016-07-11 14:46:27 -0500471 // Set how we get there.
akmhoque53353462014-04-22 08:43:45 -0500472 m_parent[v] = u;
473 }
474 }
475 }
476 }
Nick G97e34942016-07-11 14:46:27 -0500477 // Increment the head position, resort the list by distance from where we are.
akmhoque53353462014-04-22 08:43:45 -0500478 head++;
Vince Lehman9a709032014-09-13 16:28:07 -0500479 sortQueueByDistance(Q, m_distance, head, m_nRouters);
akmhoque53353462014-04-22 08:43:45 -0500480 }
481 }
482 delete [] Q;
483}
484
485void
Ashlesh Gawande85998a12017-12-07 22:22:13 -0600486LinkStateRoutingTableCalculator::addAllLsNextHopsToRoutingTable(AdjacencyList& adjacencies,
Junxiao Shi4eb4eae2024-02-14 12:36:57 +0000487 RoutingTable& rt, NameMap& pMap,
Ashlesh Gawande85998a12017-12-07 22:22:13 -0600488 uint32_t sourceRouter)
akmhoque53353462014-04-22 08:43:45 -0500489{
dmcoomes5bcb39e2017-10-31 15:07:55 -0500490 NLSR_LOG_DEBUG("LinkStateRoutingTableCalculator::addAllNextHopsToRoutingTable Called");
Vince Lehman9a709032014-09-13 16:28:07 -0500491
akmhoque53353462014-04-22 08:43:45 -0500492 int nextHopRouter = 0;
Vince Lehman9a709032014-09-13 16:28:07 -0500493
Nick G97e34942016-07-11 14:46:27 -0500494 // For each router we have
Vince Lehman9a709032014-09-13 16:28:07 -0500495 for (size_t i = 0; i < m_nRouters ; i++) {
akmhoque157b0a42014-05-13 00:26:37 -0500496 if (i != sourceRouter) {
Vince Lehman9a709032014-09-13 16:28:07 -0500497
Nick G97e34942016-07-11 14:46:27 -0500498 // Obtain the next hop that was determined by the algorithm
akmhoque53353462014-04-22 08:43:45 -0500499 nextHopRouter = getLsNextHop(i, sourceRouter);
Nick G97e34942016-07-11 14:46:27 -0500500 // If this router is accessible at all
akmhoque157b0a42014-05-13 00:26:37 -0500501 if (nextHopRouter != NO_NEXT_HOP) {
Vince Lehman9a709032014-09-13 16:28:07 -0500502
Nick G97e34942016-07-11 14:46:27 -0500503 // Fetch its distance
akmhoque53353462014-04-22 08:43:45 -0500504 double routeCost = m_distance[i];
Nick G97e34942016-07-11 14:46:27 -0500505 // Fetch its actual name
Davide Pesaventoc1d0e8e2022-06-15 14:26:02 -0400506 auto nextHopRouterName = pMap.getRouterNameByMappingNo(nextHopRouter);
Nick Gordone40377d2017-08-11 15:10:02 -0500507 if (nextHopRouterName) {
Junxiao Shi6593a432023-08-21 10:50:28 +0000508 auto nextHopFace = adjacencies.getAdjacent(*nextHopRouterName).getFaceUri();
Nick Gordone40377d2017-08-11 15:10:02 -0500509 // Add next hop to routing table
510 NextHop nh(nextHopFace, routeCost);
511 rt.addNextHop(*(pMap.getRouterNameByMappingNo(i)), nh);
Nick Gordone40377d2017-08-11 15:10:02 -0500512 }
akmhoque53353462014-04-22 08:43:45 -0500513 }
514 }
515 }
516}
517
518int
519LinkStateRoutingTableCalculator::getLsNextHop(int dest, int source)
520{
521 int nextHop = NO_NEXT_HOP;
akmhoque157b0a42014-05-13 00:26:37 -0500522 while (m_parent[dest] != EMPTY_PARENT) {
akmhoque53353462014-04-22 08:43:45 -0500523 nextHop = dest;
524 dest = m_parent[dest];
525 }
akmhoque157b0a42014-05-13 00:26:37 -0500526 if (dest != source) {
akmhoque53353462014-04-22 08:43:45 -0500527 nextHop = NO_NEXT_HOP;
528 }
529 return nextHop;
530}
531
532void
akmhoque53353462014-04-22 08:43:45 -0500533LinkStateRoutingTableCalculator::sortQueueByDistance(int* Q,
akmhoque2f423352014-06-03 11:49:35 -0500534 double* dist,
535 int start, int element)
akmhoque53353462014-04-22 08:43:45 -0500536{
akmhoque157b0a42014-05-13 00:26:37 -0500537 for (int i = start ; i < element ; i++) {
538 for (int j = i + 1; j < element; j++) {
539 if (dist[Q[j]] < dist[Q[i]]) {
akmhoque53353462014-04-22 08:43:45 -0500540 int tempU = Q[j];
541 Q[j] = Q[i];
542 Q[i] = tempU;
543 }
544 }
545 }
546}
547
548int
549LinkStateRoutingTableCalculator::isNotExplored(int* Q,
550 int u, int start, int element)
551{
552 int ret = 0;
akmhoque157b0a42014-05-13 00:26:37 -0500553 for (int i = start; i < element; i++) {
554 if (Q[i] == u) {
akmhoque53353462014-04-22 08:43:45 -0500555 ret = 1;
556 break;
557 }
558 }
559 return ret;
560}
561
562void
563LinkStateRoutingTableCalculator::allocateParent()
564{
Vince Lehman9a709032014-09-13 16:28:07 -0500565 m_parent = new int[m_nRouters];
akmhoque53353462014-04-22 08:43:45 -0500566}
567
568void
569LinkStateRoutingTableCalculator::allocateDistance()
570{
Vince Lehman9a709032014-09-13 16:28:07 -0500571 m_distance = new double[m_nRouters];
akmhoque53353462014-04-22 08:43:45 -0500572}
573
574void
575LinkStateRoutingTableCalculator::freeParent()
576{
577 delete [] m_parent;
578}
579
580void LinkStateRoutingTableCalculator::freeDistance()
581{
582 delete [] m_distance;
583}
584
akmhoque53353462014-04-22 08:43:45 -0500585void
Junxiao Shiaead5882024-02-21 12:32:02 +0000586calculateLinkStateRoutingPath(NameMap& map, RoutingTable& rt, ConfParameter& confParam,
587 const Lsdb& lsdb)
akmhoque53353462014-04-22 08:43:45 -0500588{
Junxiao Shiaead5882024-02-21 12:32:02 +0000589 LinkStateRoutingTableCalculator calculator(map.size());
590 calculator.calculatePath(map, rt, confParam, lsdb);
akmhoque53353462014-04-22 08:43:45 -0500591}
592
Nick Gordonfad8e252016-08-11 14:21:38 -0500593} // namespace nlsr