akmhoque | 3d06e79 | 2014-05-27 16:23:20 -0500 | [diff] [blame] | 1 | /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */ |
Ashlesh Gawande | 57a8717 | 2020-05-09 19:47:06 -0700 | [diff] [blame] | 2 | /* |
Junxiao Shi | b573484 | 2024-01-09 21:14:53 +0000 | [diff] [blame] | 3 | * Copyright (c) 2014-2024, The University of Memphis, |
Vince Lehman | 41b173e | 2015-05-07 14:13:26 -0500 | [diff] [blame] | 4 | * Regents of the University of California, |
| 5 | * Arizona Board of Regents. |
akmhoque | 3d06e79 | 2014-05-27 16:23:20 -0500 | [diff] [blame] | 6 | * |
| 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 Gawande | 57a8717 | 2020-05-09 19:47:06 -0700 | [diff] [blame] | 20 | */ |
Nick Gordon | e40377d | 2017-08-11 15:10:02 -0500 | [diff] [blame] | 21 | |
Junxiao Shi | aead588 | 2024-02-21 12:32:02 +0000 | [diff] [blame] | 22 | #include "routing-calculator.hpp" |
Junxiao Shi | 4eb4eae | 2024-02-14 12:36:57 +0000 | [diff] [blame] | 23 | #include "name-map.hpp" |
akmhoque | 5335346 | 2014-04-22 08:43:45 -0500 | [diff] [blame] | 24 | #include "nexthop.hpp" |
akmhoque | 5335346 | 2014-04-22 08:43:45 -0500 | [diff] [blame] | 25 | |
Junxiao Shi | aead588 | 2024-02-21 12:32:02 +0000 | [diff] [blame] | 26 | #include "adjacent.hpp" |
| 27 | #include "logger.hpp" |
| 28 | #include "nlsr.hpp" |
| 29 | |
Junxiao Shi | 29b91ff | 2024-02-22 04:11:47 +0000 | [diff] [blame] | 30 | #include <boost/multi_array.hpp> |
Vince Lehman | 9a70903 | 2014-09-13 16:28:07 -0500 | [diff] [blame] | 31 | |
akmhoque | 5335346 | 2014-04-22 08:43:45 -0500 | [diff] [blame] | 32 | namespace nlsr { |
Junxiao Shi | 29b91ff | 2024-02-22 04:11:47 +0000 | [diff] [blame] | 33 | namespace { |
akmhoque | 5335346 | 2014-04-22 08:43:45 -0500 | [diff] [blame] | 34 | |
Junxiao Shi | aead588 | 2024-02-21 12:32:02 +0000 | [diff] [blame] | 35 | INIT_LOGGER(route.RoutingCalculatorLinkState); |
| 36 | |
Davide Pesavento | 658fd85 | 2023-05-10 22:15:03 -0400 | [diff] [blame] | 37 | constexpr int EMPTY_PARENT = -12345; |
| 38 | constexpr double INF_DISTANCE = 2147483647; |
Davide Pesavento | 658fd85 | 2023-05-10 22:15:03 -0400 | [diff] [blame] | 39 | constexpr int NO_NEXT_HOP = -12345; |
dulalsaurab | d0816a3 | 2019-07-26 13:11:24 +0000 | [diff] [blame] | 40 | |
Junxiao Shi | 29b91ff | 2024-02-22 04:11:47 +0000 | [diff] [blame] | 41 | /** |
| 42 | * @brief Adjacency matrix. |
| 43 | * |
| 44 | * The matrix shall be a 2D array with N rows and N columns, where N is the number of routers. |
| 45 | * Element i,j is the cost from router i to router j. |
| 46 | */ |
| 47 | using AdjMatrix = boost::multi_array<double, 2>; |
Vince Lehman | 9a70903 | 2014-09-13 16:28:07 -0500 | [diff] [blame] | 48 | |
Junxiao Shi | 29b91ff | 2024-02-22 04:11:47 +0000 | [diff] [blame] | 49 | struct PrintAdjMatrix |
| 50 | { |
| 51 | const AdjMatrix& matrix; |
| 52 | const NameMap& map; |
| 53 | }; |
| 54 | |
| 55 | /** |
| 56 | * @brief Print adjacency matrix. |
| 57 | */ |
| 58 | std::ostream& |
| 59 | operator<<(std::ostream& os, const PrintAdjMatrix& p) |
| 60 | { |
| 61 | size_t nRouters = p.map.size(); |
| 62 | |
| 63 | os << "-----------Legend (routerName -> index)------\n"; |
| 64 | for (size_t i = 0; i < nRouters; ++i) { |
| 65 | os << "Router:" << *p.map.getRouterNameByMappingNo(i) |
| 66 | << " Index:" << i << "\n"; |
akmhoque | 5335346 | 2014-04-22 08:43:45 -0500 | [diff] [blame] | 67 | } |
Junxiao Shi | 29b91ff | 2024-02-22 04:11:47 +0000 | [diff] [blame] | 68 | os << " |"; |
| 69 | for (size_t i = 0; i < nRouters; ++i) { |
| 70 | os << i << " "; |
| 71 | } |
| 72 | os << "\n"; |
| 73 | os << "--"; |
| 74 | for (size_t i = 0; i < nRouters; ++i) { |
| 75 | os << "--"; |
| 76 | } |
| 77 | os << "\n"; |
akmhoque | 5335346 | 2014-04-22 08:43:45 -0500 | [diff] [blame] | 78 | |
Junxiao Shi | 29b91ff | 2024-02-22 04:11:47 +0000 | [diff] [blame] | 79 | for (size_t i = 0; i < nRouters; i++) { |
| 80 | os << i << "|"; |
| 81 | for (size_t j = 0; j < nRouters; j++) { |
| 82 | double cost = p.matrix[i][j]; |
| 83 | if (cost == NO_NEXT_HOP) { |
| 84 | os << "0 "; |
| 85 | } |
| 86 | else { |
| 87 | os << cost << " "; |
| 88 | } |
akmhoque | 157b0a4 | 2014-05-13 00:26:37 -0500 | [diff] [blame] | 89 | } |
Junxiao Shi | 29b91ff | 2024-02-22 04:11:47 +0000 | [diff] [blame] | 90 | os << "\n"; |
akmhoque | 5335346 | 2014-04-22 08:43:45 -0500 | [diff] [blame] | 91 | } |
Junxiao Shi | 29b91ff | 2024-02-22 04:11:47 +0000 | [diff] [blame] | 92 | |
| 93 | return os; |
akmhoque | 5335346 | 2014-04-22 08:43:45 -0500 | [diff] [blame] | 94 | } |
| 95 | |
Junxiao Shi | 29b91ff | 2024-02-22 04:11:47 +0000 | [diff] [blame] | 96 | /** |
| 97 | * @brief Allocate and populate adjacency matrix. |
| 98 | * |
| 99 | * The adjacency matrix is resized to match the number of routers in @p map . |
| 100 | * Costs from Adjacency LSAs are filled into the matrix; in case of a mismatch in bidirectional |
| 101 | * costs, the higher cost is assigned for both directions. |
| 102 | * All other elements are set to @c NON_ADJACENT_COST . |
| 103 | */ |
| 104 | AdjMatrix |
| 105 | makeAdjMatrix(const Lsdb& lsdb, NameMap& map) |
akmhoque | 5335346 | 2014-04-22 08:43:45 -0500 | [diff] [blame] | 106 | { |
Junxiao Shi | 29b91ff | 2024-02-22 04:11:47 +0000 | [diff] [blame] | 107 | // Create the matrix to have N rows and N columns, where N is number of routers. |
| 108 | size_t nRouters = map.size(); |
| 109 | AdjMatrix matrix(boost::extents[nRouters][nRouters]); |
| 110 | |
| 111 | // Initialize all elements to NON_ADJACENT_COST. |
| 112 | std::fill_n(matrix.origin(), matrix.num_elements(), Adjacent::NON_ADJACENT_COST); |
| 113 | |
Nick G | 97e3494 | 2016-07-11 14:46:27 -0500 | [diff] [blame] | 114 | // For each LSA represented in the map |
Ashlesh Gawande | 57a8717 | 2020-05-09 19:47:06 -0700 | [diff] [blame] | 115 | auto lsaRange = lsdb.getLsdbIterator<AdjLsa>(); |
| 116 | for (auto lsaIt = lsaRange.first; lsaIt != lsaRange.second; ++lsaIt) { |
| 117 | auto adjLsa = std::static_pointer_cast<AdjLsa>(*lsaIt); |
Junxiao Shi | 29b91ff | 2024-02-22 04:11:47 +0000 | [diff] [blame] | 118 | auto row = map.getMappingNoByRouterName(adjLsa->getOriginRouter()); |
Vince Lehman | 9a70903 | 2014-09-13 16:28:07 -0500 | [diff] [blame] | 119 | |
Ashlesh Gawande | 57a8717 | 2020-05-09 19:47:06 -0700 | [diff] [blame] | 120 | std::list<Adjacent> adl = adjLsa->getAdl().getAdjList(); |
Nick G | 97e3494 | 2016-07-11 14:46:27 -0500 | [diff] [blame] | 121 | // For each adjacency represented in the LSA |
Ashlesh Gawande | 85998a1 | 2017-12-07 22:22:13 -0600 | [diff] [blame] | 122 | for (const auto& adjacent : adl) { |
Junxiao Shi | 29b91ff | 2024-02-22 04:11:47 +0000 | [diff] [blame] | 123 | auto col = map.getMappingNoByRouterName(adjacent.getName()); |
Ashlesh Gawande | 85998a1 | 2017-12-07 22:22:13 -0600 | [diff] [blame] | 124 | double cost = adjacent.getLinkCost(); |
Vince Lehman | 9a70903 | 2014-09-13 16:28:07 -0500 | [diff] [blame] | 125 | |
Junxiao Shi | 29b91ff | 2024-02-22 04:11:47 +0000 | [diff] [blame] | 126 | if (row && col && *row < static_cast<int32_t>(nRouters) |
| 127 | && *col < static_cast<int32_t>(nRouters)) { |
| 128 | matrix[*row][*col] = cost; |
akmhoque | 5335346 | 2014-04-22 08:43:45 -0500 | [diff] [blame] | 129 | } |
| 130 | } |
| 131 | } |
Vince Lehman | 41b173e | 2015-05-07 14:13:26 -0500 | [diff] [blame] | 132 | |
Nick G | 97e3494 | 2016-07-11 14:46:27 -0500 | [diff] [blame] | 133 | // Links that do not have the same cost for both directions should |
| 134 | // have their costs corrected: |
Vince Lehman | 41b173e | 2015-05-07 14:13:26 -0500 | [diff] [blame] | 135 | // |
dulalsaurab | d0816a3 | 2019-07-26 13:11:24 +0000 | [diff] [blame] | 136 | // If the cost of one side of the link is NON_ADJACENT_COST (i.e. broken) or negative, |
| 137 | // both direction of the link should have their cost corrected to NON_ADJACENT_COST. |
Vince Lehman | 41b173e | 2015-05-07 14:13:26 -0500 | [diff] [blame] | 138 | // |
| 139 | // Otherwise, both sides of the link should use the larger of the two costs. |
| 140 | // |
Nick G | 97e3494 | 2016-07-11 14:46:27 -0500 | [diff] [blame] | 141 | // Additionally, this means that we can halve the amount of space |
| 142 | // that the matrix uses by only maintaining a triangle. |
| 143 | // - But that is not yet implemented. |
Junxiao Shi | 29b91ff | 2024-02-22 04:11:47 +0000 | [diff] [blame] | 144 | for (size_t row = 0; row < nRouters; ++row) { |
| 145 | for (size_t col = 0; col < nRouters; ++col) { |
| 146 | double& toCost = matrix[row][col]; |
| 147 | double& fromCost = matrix[col][row]; |
Vince Lehman | 41b173e | 2015-05-07 14:13:26 -0500 | [diff] [blame] | 148 | |
Junxiao Shi | 29b91ff | 2024-02-22 04:11:47 +0000 | [diff] [blame] | 149 | if (fromCost == toCost) { |
| 150 | continue; |
| 151 | } |
Vince Lehman | 41b173e | 2015-05-07 14:13:26 -0500 | [diff] [blame] | 152 | |
Junxiao Shi | 29b91ff | 2024-02-22 04:11:47 +0000 | [diff] [blame] | 153 | // If both sides of the link are up, use the larger cost else break the link |
| 154 | double correctedCost = Adjacent::NON_ADJACENT_COST; |
| 155 | if (toCost >= 0 && fromCost >= 0) { |
| 156 | correctedCost = std::max(toCost, fromCost); |
| 157 | } |
Vince Lehman | 41b173e | 2015-05-07 14:13:26 -0500 | [diff] [blame] | 158 | |
Junxiao Shi | 29b91ff | 2024-02-22 04:11:47 +0000 | [diff] [blame] | 159 | NLSR_LOG_WARN("Cost between [" << row << "][" << col << "] and [" << col << "][" << row << |
| 160 | "] are not the same (" << toCost << " != " << fromCost << "). " << |
| 161 | "Correcting to cost: " << correctedCost); |
Vince Lehman | 41b173e | 2015-05-07 14:13:26 -0500 | [diff] [blame] | 162 | |
Junxiao Shi | 29b91ff | 2024-02-22 04:11:47 +0000 | [diff] [blame] | 163 | toCost = correctedCost; |
| 164 | fromCost = correctedCost; |
| 165 | } |
| 166 | } |
| 167 | |
| 168 | return matrix; |
| 169 | } |
| 170 | |
| 171 | void |
| 172 | sortQueueByDistance(std::vector<int>& q, const std::vector<double>& dist, size_t start) |
| 173 | { |
| 174 | for (size_t i = start; i < q.size(); ++i) { |
| 175 | for (size_t j = i + 1; j < q.size(); ++j) { |
| 176 | if (dist[q[j]] < dist[q[i]]) { |
| 177 | std::swap(q[i], q[j]); |
Vince Lehman | 41b173e | 2015-05-07 14:13:26 -0500 | [diff] [blame] | 178 | } |
| 179 | } |
| 180 | } |
akmhoque | 5335346 | 2014-04-22 08:43:45 -0500 | [diff] [blame] | 181 | } |
| 182 | |
Junxiao Shi | 29b91ff | 2024-02-22 04:11:47 +0000 | [diff] [blame] | 183 | bool |
| 184 | isNotExplored(std::vector<int>& q, int u, size_t start) |
akmhoque | 5335346 | 2014-04-22 08:43:45 -0500 | [diff] [blame] | 185 | { |
Junxiao Shi | 29b91ff | 2024-02-22 04:11:47 +0000 | [diff] [blame] | 186 | for (size_t i = start; i < q.size(); i++) { |
| 187 | if (q[i] == u) { |
| 188 | return true; |
akmhoque | 157b0a4 | 2014-05-13 00:26:37 -0500 | [diff] [blame] | 189 | } |
akmhoque | 5335346 | 2014-04-22 08:43:45 -0500 | [diff] [blame] | 190 | } |
Junxiao Shi | 29b91ff | 2024-02-22 04:11:47 +0000 | [diff] [blame] | 191 | return false; |
akmhoque | 5335346 | 2014-04-22 08:43:45 -0500 | [diff] [blame] | 192 | } |
| 193 | |
Junxiao Shi | 29b91ff | 2024-02-22 04:11:47 +0000 | [diff] [blame] | 194 | struct Link |
akmhoque | 5335346 | 2014-04-22 08:43:45 -0500 | [diff] [blame] | 195 | { |
Junxiao Shi | 29b91ff | 2024-02-22 04:11:47 +0000 | [diff] [blame] | 196 | size_t index; |
| 197 | double cost; |
| 198 | }; |
| 199 | |
| 200 | /** |
| 201 | * @brief List adjacencies and link costs from a source router. |
| 202 | */ |
| 203 | std::vector<Link> |
| 204 | gatherLinks(const AdjMatrix& matrix, int sourceRouter) |
| 205 | { |
| 206 | size_t nRouters = matrix.size(); |
| 207 | std::vector<Link> result; |
| 208 | result.reserve(nRouters); |
| 209 | for (size_t i = 0; i < nRouters; ++i) { |
| 210 | if (i == static_cast<size_t>(sourceRouter)) { |
| 211 | continue; |
| 212 | } |
| 213 | double cost = matrix[sourceRouter][i]; |
| 214 | if (cost >= 0.0) { |
| 215 | result.emplace_back(Link{i, cost}); |
| 216 | } |
| 217 | } |
| 218 | return result; |
| 219 | } |
| 220 | |
| 221 | /** |
| 222 | * @brief Adjust link costs to simulate having only one accessible neighbor. |
| 223 | */ |
| 224 | void |
| 225 | simulateOneNeighbor(AdjMatrix& matrix, int sourceRouter, const Link& accessibleNeighbor) |
| 226 | { |
| 227 | size_t nRouters = matrix.size(); |
| 228 | for (size_t i = 0; i < nRouters; ++i) { |
| 229 | if (i == accessibleNeighbor.index) { |
| 230 | matrix[sourceRouter][i] = accessibleNeighbor.cost; |
akmhoque | 5335346 | 2014-04-22 08:43:45 -0500 | [diff] [blame] | 231 | } |
akmhoque | 157b0a4 | 2014-05-13 00:26:37 -0500 | [diff] [blame] | 232 | else { |
Junxiao Shi | 29b91ff | 2024-02-22 04:11:47 +0000 | [diff] [blame] | 233 | // if "i" is not a link to the source, set its cost to a non adjacent value. |
| 234 | matrix[sourceRouter][i] = Adjacent::NON_ADJACENT_COST; |
akmhoque | 5335346 | 2014-04-22 08:43:45 -0500 | [diff] [blame] | 235 | } |
| 236 | } |
| 237 | } |
| 238 | |
Junxiao Shi | 29b91ff | 2024-02-22 04:11:47 +0000 | [diff] [blame] | 239 | class DijkstraResult |
akmhoque | 5335346 | 2014-04-22 08:43:45 -0500 | [diff] [blame] | 240 | { |
Junxiao Shi | 29b91ff | 2024-02-22 04:11:47 +0000 | [diff] [blame] | 241 | public: |
| 242 | int |
| 243 | getNextHop(int dest, int source) const |
| 244 | { |
| 245 | int nextHop = NO_NEXT_HOP; |
| 246 | while (parent[dest] != EMPTY_PARENT) { |
| 247 | nextHop = dest; |
| 248 | dest = parent[dest]; |
akmhoque | 5335346 | 2014-04-22 08:43:45 -0500 | [diff] [blame] | 249 | } |
Junxiao Shi | 29b91ff | 2024-02-22 04:11:47 +0000 | [diff] [blame] | 250 | if (dest != source) { |
| 251 | nextHop = NO_NEXT_HOP; |
akmhoque | 5335346 | 2014-04-22 08:43:45 -0500 | [diff] [blame] | 252 | } |
Junxiao Shi | 29b91ff | 2024-02-22 04:11:47 +0000 | [diff] [blame] | 253 | return nextHop; |
akmhoque | 5335346 | 2014-04-22 08:43:45 -0500 | [diff] [blame] | 254 | } |
akmhoque | 5335346 | 2014-04-22 08:43:45 -0500 | [diff] [blame] | 255 | |
Junxiao Shi | 29b91ff | 2024-02-22 04:11:47 +0000 | [diff] [blame] | 256 | public: |
| 257 | std::vector<int> parent; |
| 258 | std::vector<double> distance; |
| 259 | }; |
| 260 | |
| 261 | /** |
| 262 | * @brief Compute the shortest path from a source router to every other router. |
| 263 | */ |
| 264 | DijkstraResult |
| 265 | calculateDijkstraPath(const AdjMatrix& matrix, int sourceRouter) |
akmhoque | 5335346 | 2014-04-22 08:43:45 -0500 | [diff] [blame] | 266 | { |
Junxiao Shi | 29b91ff | 2024-02-22 04:11:47 +0000 | [diff] [blame] | 267 | size_t nRouters = matrix.size(); |
| 268 | std::vector<int> parent(nRouters, EMPTY_PARENT); |
| 269 | // Array where the ith element is the distance to the router with mapping no i. |
| 270 | std::vector<double> distance(nRouters, INF_DISTANCE); |
| 271 | // Each cell represents the router with that mapping no. |
| 272 | std::vector<int> q(nRouters); |
| 273 | for (size_t i = 0 ; i < nRouters; ++i) { |
| 274 | q[i] = static_cast<int>(i); |
akmhoque | 5335346 | 2014-04-22 08:43:45 -0500 | [diff] [blame] | 275 | } |
akmhoque | 5335346 | 2014-04-22 08:43:45 -0500 | [diff] [blame] | 276 | |
Junxiao Shi | 29b91ff | 2024-02-22 04:11:47 +0000 | [diff] [blame] | 277 | size_t head = 0; |
| 278 | // Distance to source from source is always 0. |
| 279 | distance[sourceRouter] = 0; |
| 280 | sortQueueByDistance(q, distance, head); |
| 281 | // While we haven't visited every node. |
| 282 | while (head < nRouters) { |
| 283 | int u = q[head]; // Set u to be the current node pointed to by head. |
| 284 | if (distance[u] == INF_DISTANCE) { |
| 285 | break; // This can only happen when there are no accessible nodes. |
akmhoque | 5335346 | 2014-04-22 08:43:45 -0500 | [diff] [blame] | 286 | } |
Junxiao Shi | 29b91ff | 2024-02-22 04:11:47 +0000 | [diff] [blame] | 287 | // Iterate over the adjacent nodes to u. |
| 288 | for (size_t v = 0; v < nRouters; ++v) { |
| 289 | // If the current node is accessible and we haven't visited it yet. |
| 290 | if (matrix[u][v] >= 0 && isNotExplored(q, v, head + 1)) { |
| 291 | // And if the distance to this node + from this node to v |
| 292 | // is less than the distance from our source node to v |
| 293 | // that we got when we built the adj LSAs |
| 294 | double newDistance = distance[u] + matrix[u][v]; |
| 295 | if (newDistance < distance[v]) { |
| 296 | // Set the new distance |
| 297 | distance[v] = newDistance; |
| 298 | // Set how we get there. |
| 299 | parent[v] = u; |
akmhoque | 5335346 | 2014-04-22 08:43:45 -0500 | [diff] [blame] | 300 | } |
| 301 | } |
akmhoque | 5335346 | 2014-04-22 08:43:45 -0500 | [diff] [blame] | 302 | } |
Junxiao Shi | 29b91ff | 2024-02-22 04:11:47 +0000 | [diff] [blame] | 303 | // Increment the head position, resort the list by distance from where we are. |
| 304 | ++head; |
| 305 | sortQueueByDistance(q, distance, head); |
akmhoque | 5335346 | 2014-04-22 08:43:45 -0500 | [diff] [blame] | 306 | } |
Junxiao Shi | 29b91ff | 2024-02-22 04:11:47 +0000 | [diff] [blame] | 307 | |
| 308 | return DijkstraResult{std::move(parent), std::move(distance)}; |
akmhoque | 5335346 | 2014-04-22 08:43:45 -0500 | [diff] [blame] | 309 | } |
| 310 | |
Junxiao Shi | 29b91ff | 2024-02-22 04:11:47 +0000 | [diff] [blame] | 311 | /** |
| 312 | * @brief Insert shortest paths into the routing table. |
| 313 | */ |
akmhoque | 5335346 | 2014-04-22 08:43:45 -0500 | [diff] [blame] | 314 | void |
Junxiao Shi | 29b91ff | 2024-02-22 04:11:47 +0000 | [diff] [blame] | 315 | addNextHopsToRoutingTable(RoutingTable& rt, const NameMap& map, int sourceRouter, |
| 316 | const AdjacencyList& adjacencies, const DijkstraResult& dr) |
akmhoque | 5335346 | 2014-04-22 08:43:45 -0500 | [diff] [blame] | 317 | { |
Junxiao Shi | 29b91ff | 2024-02-22 04:11:47 +0000 | [diff] [blame] | 318 | NLSR_LOG_DEBUG("addNextHopsToRoutingTable Called"); |
| 319 | int nRouters = static_cast<int>(map.size()); |
Vince Lehman | 9a70903 | 2014-09-13 16:28:07 -0500 | [diff] [blame] | 320 | |
Nick G | 97e3494 | 2016-07-11 14:46:27 -0500 | [diff] [blame] | 321 | // For each router we have |
Junxiao Shi | 29b91ff | 2024-02-22 04:11:47 +0000 | [diff] [blame] | 322 | for (int i = 0; i < nRouters; ++i) { |
| 323 | if (i == sourceRouter) { |
| 324 | continue; |
akmhoque | 5335346 | 2014-04-22 08:43:45 -0500 | [diff] [blame] | 325 | } |
akmhoque | 5335346 | 2014-04-22 08:43:45 -0500 | [diff] [blame] | 326 | |
Junxiao Shi | 29b91ff | 2024-02-22 04:11:47 +0000 | [diff] [blame] | 327 | // Obtain the next hop that was determined by the algorithm |
| 328 | int nextHopRouter = dr.getNextHop(i, sourceRouter); |
| 329 | if (nextHopRouter == NO_NEXT_HOP) { |
| 330 | continue; |
akmhoque | 5335346 | 2014-04-22 08:43:45 -0500 | [diff] [blame] | 331 | } |
Junxiao Shi | 29b91ff | 2024-02-22 04:11:47 +0000 | [diff] [blame] | 332 | // If this router is accessible at all |
| 333 | |
| 334 | // Fetch its distance |
| 335 | double routeCost = dr.distance[i]; |
| 336 | // Fetch its actual name |
| 337 | auto nextHopRouterName = map.getRouterNameByMappingNo(nextHopRouter); |
| 338 | BOOST_ASSERT(nextHopRouterName.has_value()); |
| 339 | auto nextHopFace = adjacencies.getAdjacent(*nextHopRouterName).getFaceUri(); |
| 340 | // Add next hop to routing table |
| 341 | NextHop nh(nextHopFace, routeCost); |
| 342 | rt.addNextHop(*map.getRouterNameByMappingNo(i), nh); |
akmhoque | 5335346 | 2014-04-22 08:43:45 -0500 | [diff] [blame] | 343 | } |
| 344 | } |
| 345 | |
Junxiao Shi | 29b91ff | 2024-02-22 04:11:47 +0000 | [diff] [blame] | 346 | } // anonymous namespace |
akmhoque | 5335346 | 2014-04-22 08:43:45 -0500 | [diff] [blame] | 347 | |
akmhoque | 5335346 | 2014-04-22 08:43:45 -0500 | [diff] [blame] | 348 | void |
Junxiao Shi | aead588 | 2024-02-21 12:32:02 +0000 | [diff] [blame] | 349 | calculateLinkStateRoutingPath(NameMap& map, RoutingTable& rt, ConfParameter& confParam, |
| 350 | const Lsdb& lsdb) |
akmhoque | 5335346 | 2014-04-22 08:43:45 -0500 | [diff] [blame] | 351 | { |
Junxiao Shi | 29b91ff | 2024-02-22 04:11:47 +0000 | [diff] [blame] | 352 | NLSR_LOG_DEBUG("calculateLinkStateRoutingPath called"); |
| 353 | |
| 354 | auto sourceRouter = map.getMappingNoByRouterName(confParam.getRouterPrefix()); |
| 355 | if (!sourceRouter) { |
| 356 | NLSR_LOG_DEBUG("Source router is absent, nothing to do"); |
| 357 | return; |
| 358 | } |
| 359 | |
| 360 | AdjMatrix matrix = makeAdjMatrix(lsdb, map); |
| 361 | NLSR_LOG_DEBUG((PrintAdjMatrix{matrix, map})); |
| 362 | |
| 363 | if (confParam.getMaxFacesPerPrefix() == 1) { |
| 364 | // In the single path case we can simply run Dijkstra's algorithm. |
| 365 | auto dr = calculateDijkstraPath(matrix, *sourceRouter); |
| 366 | // Inform the routing table of the new next hops. |
| 367 | addNextHopsToRoutingTable(rt, map, *sourceRouter, confParam.getAdjacencyList(), dr); |
| 368 | } |
| 369 | else { |
| 370 | // Multi Path |
| 371 | // Gets a sparse listing of adjacencies for path calculation |
| 372 | auto links = gatherLinks(matrix, *sourceRouter); |
| 373 | for (const auto& link : links) { |
| 374 | // Simulate that only the current neighbor is accessible |
| 375 | simulateOneNeighbor(matrix, *sourceRouter, link); |
| 376 | NLSR_LOG_DEBUG((PrintAdjMatrix{matrix, map})); |
| 377 | // Do Dijkstra's algorithm using the current neighbor as your start. |
| 378 | auto dr = calculateDijkstraPath(matrix, *sourceRouter); |
| 379 | // Update the routing table with the calculations. |
| 380 | addNextHopsToRoutingTable(rt, map, *sourceRouter, confParam.getAdjacencyList(), dr); |
| 381 | } |
| 382 | } |
akmhoque | 5335346 | 2014-04-22 08:43:45 -0500 | [diff] [blame] | 383 | } |
| 384 | |
Nick Gordon | fad8e25 | 2016-08-11 14:21:38 -0500 | [diff] [blame] | 385 | } // namespace nlsr |