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 | |
Davide Pesavento | c1d0e8e | 2022-06-15 14:26:02 -0400 | [diff] [blame] | 30 | #include <boost/lexical_cast.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 { |
| 33 | |
Junxiao Shi | aead588 | 2024-02-21 12:32:02 +0000 | [diff] [blame^] | 34 | INIT_LOGGER(route.RoutingCalculatorLinkState); |
| 35 | |
| 36 | class RoutingTableCalculator |
| 37 | { |
| 38 | public: |
| 39 | RoutingTableCalculator(size_t nRouters) |
| 40 | { |
| 41 | m_nRouters = nRouters; |
| 42 | } |
| 43 | |
| 44 | protected: |
| 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 | |
| 116 | protected: |
| 117 | double** adjMatrix; |
| 118 | size_t m_nRouters; |
| 119 | |
| 120 | int vNoLink; |
| 121 | int* links; |
| 122 | double* linkCosts; |
| 123 | |
| 124 | }; |
| 125 | |
| 126 | class LinkStateRoutingTableCalculator: public RoutingTableCalculator |
| 127 | { |
| 128 | public: |
| 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 | |
| 138 | private: |
| 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 | |
| 192 | private: |
| 193 | int* m_parent; |
| 194 | double* m_distance; |
| 195 | }; |
akmhoque | 5335346 | 2014-04-22 08:43:45 -0500 | [diff] [blame] | 196 | |
Davide Pesavento | 658fd85 | 2023-05-10 22:15:03 -0400 | [diff] [blame] | 197 | constexpr int EMPTY_PARENT = -12345; |
| 198 | constexpr double INF_DISTANCE = 2147483647; |
| 199 | constexpr int NO_MAPPING_NUM = -1; |
| 200 | constexpr int NO_NEXT_HOP = -12345; |
dulalsaurab | d0816a3 | 2019-07-26 13:11:24 +0000 | [diff] [blame] | 201 | |
akmhoque | 5335346 | 2014-04-22 08:43:45 -0500 | [diff] [blame] | 202 | void |
| 203 | RoutingTableCalculator::allocateAdjMatrix() |
| 204 | { |
Vince Lehman | 9a70903 | 2014-09-13 16:28:07 -0500 | [diff] [blame] | 205 | adjMatrix = new double*[m_nRouters]; |
| 206 | |
| 207 | for (size_t i = 0; i < m_nRouters; ++i) { |
| 208 | adjMatrix[i] = new double[m_nRouters]; |
akmhoque | 5335346 | 2014-04-22 08:43:45 -0500 | [diff] [blame] | 209 | } |
| 210 | } |
| 211 | |
| 212 | void |
| 213 | RoutingTableCalculator::initMatrix() |
| 214 | { |
Vince Lehman | 9a70903 | 2014-09-13 16:28:07 -0500 | [diff] [blame] | 215 | for (size_t i = 0; i < m_nRouters; i++) { |
| 216 | for (size_t j = 0; j < m_nRouters; j++) { |
dulalsaurab | d0816a3 | 2019-07-26 13:11:24 +0000 | [diff] [blame] | 217 | adjMatrix[i][j] = Adjacent::NON_ADJACENT_COST; |
akmhoque | 157b0a4 | 2014-05-13 00:26:37 -0500 | [diff] [blame] | 218 | } |
akmhoque | 5335346 | 2014-04-22 08:43:45 -0500 | [diff] [blame] | 219 | } |
| 220 | } |
| 221 | |
| 222 | void |
Junxiao Shi | 4eb4eae | 2024-02-14 12:36:57 +0000 | [diff] [blame] | 223 | RoutingTableCalculator::makeAdjMatrix(const Lsdb& lsdb, NameMap& pMap) |
akmhoque | 5335346 | 2014-04-22 08:43:45 -0500 | [diff] [blame] | 224 | { |
Nick G | 97e3494 | 2016-07-11 14:46:27 -0500 | [diff] [blame] | 225 | // For each LSA represented in the map |
Ashlesh Gawande | 57a8717 | 2020-05-09 19:47:06 -0700 | [diff] [blame] | 226 | 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 Pesavento | c1d0e8e | 2022-06-15 14:26:02 -0400 | [diff] [blame] | 229 | auto row = pMap.getMappingNoByRouterName(adjLsa->getOriginRouter()); |
Vince Lehman | 9a70903 | 2014-09-13 16:28:07 -0500 | [diff] [blame] | 230 | |
Ashlesh Gawande | 57a8717 | 2020-05-09 19:47:06 -0700 | [diff] [blame] | 231 | std::list<Adjacent> adl = adjLsa->getAdl().getAdjList(); |
Nick G | 97e3494 | 2016-07-11 14:46:27 -0500 | [diff] [blame] | 232 | // For each adjacency represented in the LSA |
Ashlesh Gawande | 85998a1 | 2017-12-07 22:22:13 -0600 | [diff] [blame] | 233 | for (const auto& adjacent : adl) { |
Davide Pesavento | c1d0e8e | 2022-06-15 14:26:02 -0400 | [diff] [blame] | 234 | auto col = pMap.getMappingNoByRouterName(adjacent.getName()); |
Ashlesh Gawande | 85998a1 | 2017-12-07 22:22:13 -0600 | [diff] [blame] | 235 | double cost = adjacent.getLinkCost(); |
Vince Lehman | 9a70903 | 2014-09-13 16:28:07 -0500 | [diff] [blame] | 236 | |
Nick Gordon | e40377d | 2017-08-11 15:10:02 -0500 | [diff] [blame] | 237 | if (row && col && *row < static_cast<int32_t>(m_nRouters) |
Davide Pesavento | c1d0e8e | 2022-06-15 14:26:02 -0400 | [diff] [blame] | 238 | && *col < static_cast<int32_t>(m_nRouters)) { |
Nick Gordon | e40377d | 2017-08-11 15:10:02 -0500 | [diff] [blame] | 239 | adjMatrix[*row][*col] = cost; |
akmhoque | 5335346 | 2014-04-22 08:43:45 -0500 | [diff] [blame] | 240 | } |
| 241 | } |
| 242 | } |
Vince Lehman | 41b173e | 2015-05-07 14:13:26 -0500 | [diff] [blame] | 243 | |
Nick G | 97e3494 | 2016-07-11 14:46:27 -0500 | [diff] [blame] | 244 | // Links that do not have the same cost for both directions should |
| 245 | // have their costs corrected: |
Vince Lehman | 41b173e | 2015-05-07 14:13:26 -0500 | [diff] [blame] | 246 | // |
dulalsaurab | d0816a3 | 2019-07-26 13:11:24 +0000 | [diff] [blame] | 247 | // 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 Lehman | 41b173e | 2015-05-07 14:13:26 -0500 | [diff] [blame] | 249 | // |
| 250 | // Otherwise, both sides of the link should use the larger of the two costs. |
| 251 | // |
Nick G | 97e3494 | 2016-07-11 14:46:27 -0500 | [diff] [blame] | 252 | // 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 Lehman | 41b173e | 2015-05-07 14:13:26 -0500 | [diff] [blame] | 255 | 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) { |
dulalsaurab | d0816a3 | 2019-07-26 13:11:24 +0000 | [diff] [blame] | 261 | double correctedCost = Adjacent::NON_ADJACENT_COST; |
Vince Lehman | 41b173e | 2015-05-07 14:13:26 -0500 | [diff] [blame] | 262 | |
dulalsaurab | d0816a3 | 2019-07-26 13:11:24 +0000 | [diff] [blame] | 263 | if (toCost >= 0 && fromCost >= 0) { |
| 264 | // If both sides of the link are up, use the larger cost else break the link |
Vince Lehman | 41b173e | 2015-05-07 14:13:26 -0500 | [diff] [blame] | 265 | correctedCost = std::max(toCost, fromCost); |
| 266 | } |
| 267 | |
dmcoomes | 5bcb39e | 2017-10-31 15:07:55 -0500 | [diff] [blame] | 268 | NLSR_LOG_WARN("Cost between [" << row << "][" << col << "] and [" << col << "][" << row << |
Vince Lehman | 41b173e | 2015-05-07 14:13:26 -0500 | [diff] [blame] | 269 | "] 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 | } |
akmhoque | 5335346 | 2014-04-22 08:43:45 -0500 | [diff] [blame] | 277 | } |
| 278 | |
| 279 | void |
Junxiao Shi | 4eb4eae | 2024-02-14 12:36:57 +0000 | [diff] [blame] | 280 | RoutingTableCalculator::writeAdjMatrixLog(const NameMap& map) const |
akmhoque | 5335346 | 2014-04-22 08:43:45 -0500 | [diff] [blame] | 281 | { |
Ashlesh Gawande | cba0ae2 | 2018-03-27 17:57:56 -0500 | [diff] [blame] | 282 | if (!ndn_cxx_getLogger().isLevelEnabled(ndn::util::LogLevel::DEBUG)) { |
Saurab Dulal | 9da6aa7 | 2018-01-12 17:25:51 +0000 | [diff] [blame] | 283 | return; |
| 284 | } |
| 285 | |
| 286 | NLSR_LOG_DEBUG("-----------Legend (routerName -> index)------"); |
| 287 | std::string routerIndex; |
| 288 | std::string indexToNameMapping; |
| 289 | std::string lengthOfDash = "--"; |
| 290 | |
Vince Lehman | 9a70903 | 2014-09-13 16:28:07 -0500 | [diff] [blame] | 291 | for (size_t i = 0; i < m_nRouters; i++) { |
Saurab Dulal | 9da6aa7 | 2018-01-12 17:25:51 +0000 | [diff] [blame] | 292 | routerIndex += boost::lexical_cast<std::string>(i); |
| 293 | routerIndex += " "; |
| 294 | lengthOfDash += "--"; |
| 295 | NLSR_LOG_DEBUG("Router:" + map.getRouterNameByMappingNo(i)->toUri() + |
Ashlesh Gawande | cba0ae2 | 2018-03-27 17:57:56 -0500 | [diff] [blame] | 296 | " Index:" + boost::lexical_cast<std::string>(i)); |
Saurab Dulal | 9da6aa7 | 2018-01-12 17:25:51 +0000 | [diff] [blame] | 297 | } |
| 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 Lehman | 9a70903 | 2014-09-13 16:28:07 -0500 | [diff] [blame] | 303 | for (size_t j = 0; j < m_nRouters; j++) { |
Davide Pesavento | c1d0e8e | 2022-06-15 14:26:02 -0400 | [diff] [blame] | 304 | if (adjMatrix[i][j] == NO_NEXT_HOP) { |
Ashlesh Gawande | 6b388fc | 2019-09-30 10:14:41 -0500 | [diff] [blame] | 305 | line += "0 "; |
| 306 | } |
| 307 | else { |
| 308 | line += boost::lexical_cast<std::string>(adjMatrix[i][j]); |
| 309 | line += " "; |
| 310 | } |
akmhoque | 157b0a4 | 2014-05-13 00:26:37 -0500 | [diff] [blame] | 311 | } |
Saurab Dulal | 9da6aa7 | 2018-01-12 17:25:51 +0000 | [diff] [blame] | 312 | line = boost::lexical_cast<std::string>(i) + "|" + line; |
dmcoomes | 5bcb39e | 2017-10-31 15:07:55 -0500 | [diff] [blame] | 313 | NLSR_LOG_DEBUG(line); |
akmhoque | 5335346 | 2014-04-22 08:43:45 -0500 | [diff] [blame] | 314 | } |
| 315 | } |
| 316 | |
| 317 | void |
| 318 | RoutingTableCalculator::adjustAdMatrix(int source, int link, double linkCost) |
| 319 | { |
Vince Lehman | 9a70903 | 2014-09-13 16:28:07 -0500 | [diff] [blame] | 320 | for (int i = 0; i < static_cast<int>(m_nRouters); i++) { |
akmhoque | 157b0a4 | 2014-05-13 00:26:37 -0500 | [diff] [blame] | 321 | if (i == link) { |
akmhoque | 5335346 | 2014-04-22 08:43:45 -0500 | [diff] [blame] | 322 | adjMatrix[source][i] = linkCost; |
| 323 | } |
akmhoque | 157b0a4 | 2014-05-13 00:26:37 -0500 | [diff] [blame] | 324 | else { |
dulalsaurab | d0816a3 | 2019-07-26 13:11:24 +0000 | [diff] [blame] | 325 | // 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; |
akmhoque | 5335346 | 2014-04-22 08:43:45 -0500 | [diff] [blame] | 327 | } |
| 328 | } |
| 329 | } |
| 330 | |
| 331 | int |
| 332 | RoutingTableCalculator::getNumOfLinkfromAdjMatrix(int sRouter) |
| 333 | { |
| 334 | int noLink = 0; |
Vince Lehman | 9a70903 | 2014-09-13 16:28:07 -0500 | [diff] [blame] | 335 | |
| 336 | for (size_t i = 0; i < m_nRouters; i++) { |
dulalsaurab | d0816a3 | 2019-07-26 13:11:24 +0000 | [diff] [blame] | 337 | if (adjMatrix[sRouter][i] >= 0 && i != static_cast<size_t>(sRouter)) { // make sure "i" is not self |
akmhoque | 5335346 | 2014-04-22 08:43:45 -0500 | [diff] [blame] | 338 | noLink++; |
| 339 | } |
| 340 | } |
| 341 | return noLink; |
| 342 | } |
| 343 | |
| 344 | void |
| 345 | RoutingTableCalculator::getLinksFromAdjMatrix(int* links, |
| 346 | double* linkCosts, int source) |
| 347 | { |
| 348 | int j = 0; |
Vince Lehman | 9a70903 | 2014-09-13 16:28:07 -0500 | [diff] [blame] | 349 | |
| 350 | for (size_t i = 0; i < m_nRouters; i++) { |
dulalsaurab | d0816a3 | 2019-07-26 13:11:24 +0000 | [diff] [blame] | 351 | if (adjMatrix[source][i] >= 0 && i != static_cast<size_t>(source)) {// make sure "i" is not self |
akmhoque | 5335346 | 2014-04-22 08:43:45 -0500 | [diff] [blame] | 352 | links[j] = i; |
| 353 | linkCosts[j] = adjMatrix[source][i]; |
| 354 | j++; |
| 355 | } |
| 356 | } |
| 357 | } |
| 358 | |
| 359 | void |
| 360 | RoutingTableCalculator::freeAdjMatrix() |
| 361 | { |
Vince Lehman | 9a70903 | 2014-09-13 16:28:07 -0500 | [diff] [blame] | 362 | for (size_t i = 0; i < m_nRouters; ++i) { |
akmhoque | 5335346 | 2014-04-22 08:43:45 -0500 | [diff] [blame] | 363 | delete [] adjMatrix[i]; |
| 364 | } |
| 365 | delete [] adjMatrix; |
| 366 | } |
| 367 | |
akmhoque | 5335346 | 2014-04-22 08:43:45 -0500 | [diff] [blame] | 368 | void |
| 369 | RoutingTableCalculator::allocateLinks() |
| 370 | { |
| 371 | links = new int[vNoLink]; |
| 372 | } |
| 373 | |
| 374 | void |
| 375 | RoutingTableCalculator::allocateLinkCosts() |
| 376 | { |
| 377 | linkCosts = new double[vNoLink]; |
| 378 | } |
| 379 | |
akmhoque | 5335346 | 2014-04-22 08:43:45 -0500 | [diff] [blame] | 380 | void |
| 381 | RoutingTableCalculator::freeLinks() |
| 382 | { |
| 383 | delete [] links; |
| 384 | } |
| 385 | void |
| 386 | RoutingTableCalculator::freeLinksCosts() |
| 387 | { |
| 388 | delete [] linkCosts; |
| 389 | } |
| 390 | |
| 391 | void |
Junxiao Shi | 4eb4eae | 2024-02-14 12:36:57 +0000 | [diff] [blame] | 392 | LinkStateRoutingTableCalculator::calculatePath(NameMap& pMap, RoutingTable& rt, |
Ashlesh Gawande | 85998a1 | 2017-12-07 22:22:13 -0600 | [diff] [blame] | 393 | ConfParameter& confParam, |
Ashlesh Gawande | 57a8717 | 2020-05-09 19:47:06 -0700 | [diff] [blame] | 394 | const Lsdb& lsdb) |
akmhoque | 5335346 | 2014-04-22 08:43:45 -0500 | [diff] [blame] | 395 | { |
dmcoomes | 5bcb39e | 2017-10-31 15:07:55 -0500 | [diff] [blame] | 396 | NLSR_LOG_DEBUG("LinkStateRoutingTableCalculator::calculatePath Called"); |
akmhoque | 5335346 | 2014-04-22 08:43:45 -0500 | [diff] [blame] | 397 | allocateAdjMatrix(); |
| 398 | initMatrix(); |
Ashlesh Gawande | 57a8717 | 2020-05-09 19:47:06 -0700 | [diff] [blame] | 399 | makeAdjMatrix(lsdb, pMap); |
Saurab Dulal | 9da6aa7 | 2018-01-12 17:25:51 +0000 | [diff] [blame] | 400 | writeAdjMatrixLog(pMap); |
Davide Pesavento | c1d0e8e | 2022-06-15 14:26:02 -0400 | [diff] [blame] | 401 | auto sourceRouter = pMap.getMappingNoByRouterName(confParam.getRouterPrefix()); |
Nick G | 97e3494 | 2016-07-11 14:46:27 -0500 | [diff] [blame] | 402 | allocateParent(); // These two matrices are used in Dijkstra's algorithm. |
| 403 | allocateDistance(); // |
Nick Gordon | e40377d | 2017-08-11 15:10:02 -0500 | [diff] [blame] | 404 | // We only bother to do the calculation if we have a router by that name. |
Ashlesh Gawande | 85998a1 | 2017-12-07 22:22:13 -0600 | [diff] [blame] | 405 | if (sourceRouter && confParam.getMaxFacesPerPrefix() == 1) { |
Nick G | 97e3494 | 2016-07-11 14:46:27 -0500 | [diff] [blame] | 406 | // In the single path case we can simply run Dijkstra's algorithm. |
Nick Gordon | e40377d | 2017-08-11 15:10:02 -0500 | [diff] [blame] | 407 | doDijkstraPathCalculation(*sourceRouter); |
Nick G | 97e3494 | 2016-07-11 14:46:27 -0500 | [diff] [blame] | 408 | // Inform the routing table of the new next hops. |
Ashlesh Gawande | 85998a1 | 2017-12-07 22:22:13 -0600 | [diff] [blame] | 409 | addAllLsNextHopsToRoutingTable(confParam.getAdjacencyList(), rt, pMap, *sourceRouter); |
akmhoque | 5335346 | 2014-04-22 08:43:45 -0500 | [diff] [blame] | 410 | } |
akmhoque | 157b0a4 | 2014-05-13 00:26:37 -0500 | [diff] [blame] | 411 | else { |
akmhoque | 5335346 | 2014-04-22 08:43:45 -0500 | [diff] [blame] | 412 | // Multi Path |
Nick Gordon | e40377d | 2017-08-11 15:10:02 -0500 | [diff] [blame] | 413 | setNoLink(getNumOfLinkfromAdjMatrix(*sourceRouter)); |
akmhoque | 5335346 | 2014-04-22 08:43:45 -0500 | [diff] [blame] | 414 | allocateLinks(); |
| 415 | allocateLinkCosts(); |
Nick G | 97e3494 | 2016-07-11 14:46:27 -0500 | [diff] [blame] | 416 | // Gets a sparse listing of adjacencies for path calculation |
Nick Gordon | e40377d | 2017-08-11 15:10:02 -0500 | [diff] [blame] | 417 | getLinksFromAdjMatrix(links, linkCosts, *sourceRouter); |
akmhoque | 157b0a4 | 2014-05-13 00:26:37 -0500 | [diff] [blame] | 418 | for (int i = 0 ; i < vNoLink; i++) { |
Nick G | 97e3494 | 2016-07-11 14:46:27 -0500 | [diff] [blame] | 419 | // Simulate that only the current neighbor is accessible |
Nick Gordon | e40377d | 2017-08-11 15:10:02 -0500 | [diff] [blame] | 420 | adjustAdMatrix(*sourceRouter, links[i], linkCosts[i]); |
Saurab Dulal | 9da6aa7 | 2018-01-12 17:25:51 +0000 | [diff] [blame] | 421 | writeAdjMatrixLog(pMap); |
Nick G | 97e3494 | 2016-07-11 14:46:27 -0500 | [diff] [blame] | 422 | // Do Dijkstra's algorithm using the current neighbor as your start. |
Nick Gordon | e40377d | 2017-08-11 15:10:02 -0500 | [diff] [blame] | 423 | doDijkstraPathCalculation(*sourceRouter); |
Nick G | 97e3494 | 2016-07-11 14:46:27 -0500 | [diff] [blame] | 424 | // Update the routing table with the calculations. |
Ashlesh Gawande | 85998a1 | 2017-12-07 22:22:13 -0600 | [diff] [blame] | 425 | addAllLsNextHopsToRoutingTable(confParam.getAdjacencyList(), rt, pMap, *sourceRouter); |
akmhoque | 5335346 | 2014-04-22 08:43:45 -0500 | [diff] [blame] | 426 | } |
| 427 | freeLinks(); |
| 428 | freeLinksCosts(); |
| 429 | } |
| 430 | freeParent(); |
| 431 | freeDistance(); |
| 432 | freeAdjMatrix(); |
| 433 | } |
| 434 | |
| 435 | void |
| 436 | LinkStateRoutingTableCalculator::doDijkstraPathCalculation(int sourceRouter) |
| 437 | { |
| 438 | int i; |
| 439 | int v, u; |
Nick G | 97e3494 | 2016-07-11 14:46:27 -0500 | [diff] [blame] | 440 | int* Q = new int[m_nRouters]; // Each cell represents the router with that mapping no. |
akmhoque | 5335346 | 2014-04-22 08:43:45 -0500 | [diff] [blame] | 441 | int head = 0; |
Nick Gordon | e98480b | 2017-05-24 11:23:03 -0500 | [diff] [blame] | 442 | // Initiate the parent |
Vince Lehman | 9a70903 | 2014-09-13 16:28:07 -0500 | [diff] [blame] | 443 | for (i = 0 ; i < static_cast<int>(m_nRouters); i++) { |
akmhoque | 5335346 | 2014-04-22 08:43:45 -0500 | [diff] [blame] | 444 | m_parent[i] = EMPTY_PARENT; |
Nick G | 97e3494 | 2016-07-11 14:46:27 -0500 | [diff] [blame] | 445 | // Array where the ith element is the distance to the router with mapping no i. |
akmhoque | 5335346 | 2014-04-22 08:43:45 -0500 | [diff] [blame] | 446 | m_distance[i] = INF_DISTANCE; |
| 447 | Q[i] = i; |
| 448 | } |
akmhoque | 157b0a4 | 2014-05-13 00:26:37 -0500 | [diff] [blame] | 449 | if (sourceRouter != NO_MAPPING_NUM) { |
Nick G | 97e3494 | 2016-07-11 14:46:27 -0500 | [diff] [blame] | 450 | // Distance to source from source is always 0. |
akmhoque | 5335346 | 2014-04-22 08:43:45 -0500 | [diff] [blame] | 451 | m_distance[sourceRouter] = 0; |
Vince Lehman | 9a70903 | 2014-09-13 16:28:07 -0500 | [diff] [blame] | 452 | sortQueueByDistance(Q, m_distance, head, m_nRouters); |
Nick G | 97e3494 | 2016-07-11 14:46:27 -0500 | [diff] [blame] | 453 | // While we haven't visited every node. |
Vince Lehman | 9a70903 | 2014-09-13 16:28:07 -0500 | [diff] [blame] | 454 | while (head < static_cast<int>(m_nRouters)) { |
Nick G | 97e3494 | 2016-07-11 14:46:27 -0500 | [diff] [blame] | 455 | u = Q[head]; // Set u to be the current node pointed to by head. |
akmhoque | 157b0a4 | 2014-05-13 00:26:37 -0500 | [diff] [blame] | 456 | if (m_distance[u] == INF_DISTANCE) { |
Nick G | 97e3494 | 2016-07-11 14:46:27 -0500 | [diff] [blame] | 457 | break; // This can only happen when there are no accessible nodes. |
akmhoque | 5335346 | 2014-04-22 08:43:45 -0500 | [diff] [blame] | 458 | } |
Nick G | 97e3494 | 2016-07-11 14:46:27 -0500 | [diff] [blame] | 459 | // Iterate over the adjacent nodes to u. |
Vince Lehman | 9a70903 | 2014-09-13 16:28:07 -0500 | [diff] [blame] | 460 | for (v = 0 ; v < static_cast<int>(m_nRouters); v++) { |
Nick G | 97e3494 | 2016-07-11 14:46:27 -0500 | [diff] [blame] | 461 | // If the current node is accessible. |
dulalsaurab | d0816a3 | 2019-07-26 13:11:24 +0000 | [diff] [blame] | 462 | if (adjMatrix[u][v] >= 0) { |
Nick G | 97e3494 | 2016-07-11 14:46:27 -0500 | [diff] [blame] | 463 | // And we haven't visited it yet. |
Vince Lehman | 9a70903 | 2014-09-13 16:28:07 -0500 | [diff] [blame] | 464 | if (isNotExplored(Q, v, head + 1, m_nRouters)) { |
Nick G | 97e3494 | 2016-07-11 14:46:27 -0500 | [diff] [blame] | 465 | // 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 |
akmhoque | 157b0a4 | 2014-05-13 00:26:37 -0500 | [diff] [blame] | 468 | if (m_distance[u] + adjMatrix[u][v] < m_distance[v]) { |
Nick G | 97e3494 | 2016-07-11 14:46:27 -0500 | [diff] [blame] | 469 | // Set the new distance |
akmhoque | 5335346 | 2014-04-22 08:43:45 -0500 | [diff] [blame] | 470 | m_distance[v] = m_distance[u] + adjMatrix[u][v] ; |
Nick G | 97e3494 | 2016-07-11 14:46:27 -0500 | [diff] [blame] | 471 | // Set how we get there. |
akmhoque | 5335346 | 2014-04-22 08:43:45 -0500 | [diff] [blame] | 472 | m_parent[v] = u; |
| 473 | } |
| 474 | } |
| 475 | } |
| 476 | } |
Nick G | 97e3494 | 2016-07-11 14:46:27 -0500 | [diff] [blame] | 477 | // Increment the head position, resort the list by distance from where we are. |
akmhoque | 5335346 | 2014-04-22 08:43:45 -0500 | [diff] [blame] | 478 | head++; |
Vince Lehman | 9a70903 | 2014-09-13 16:28:07 -0500 | [diff] [blame] | 479 | sortQueueByDistance(Q, m_distance, head, m_nRouters); |
akmhoque | 5335346 | 2014-04-22 08:43:45 -0500 | [diff] [blame] | 480 | } |
| 481 | } |
| 482 | delete [] Q; |
| 483 | } |
| 484 | |
| 485 | void |
Ashlesh Gawande | 85998a1 | 2017-12-07 22:22:13 -0600 | [diff] [blame] | 486 | LinkStateRoutingTableCalculator::addAllLsNextHopsToRoutingTable(AdjacencyList& adjacencies, |
Junxiao Shi | 4eb4eae | 2024-02-14 12:36:57 +0000 | [diff] [blame] | 487 | RoutingTable& rt, NameMap& pMap, |
Ashlesh Gawande | 85998a1 | 2017-12-07 22:22:13 -0600 | [diff] [blame] | 488 | uint32_t sourceRouter) |
akmhoque | 5335346 | 2014-04-22 08:43:45 -0500 | [diff] [blame] | 489 | { |
dmcoomes | 5bcb39e | 2017-10-31 15:07:55 -0500 | [diff] [blame] | 490 | NLSR_LOG_DEBUG("LinkStateRoutingTableCalculator::addAllNextHopsToRoutingTable Called"); |
Vince Lehman | 9a70903 | 2014-09-13 16:28:07 -0500 | [diff] [blame] | 491 | |
akmhoque | 5335346 | 2014-04-22 08:43:45 -0500 | [diff] [blame] | 492 | int nextHopRouter = 0; |
Vince Lehman | 9a70903 | 2014-09-13 16:28:07 -0500 | [diff] [blame] | 493 | |
Nick G | 97e3494 | 2016-07-11 14:46:27 -0500 | [diff] [blame] | 494 | // For each router we have |
Vince Lehman | 9a70903 | 2014-09-13 16:28:07 -0500 | [diff] [blame] | 495 | for (size_t i = 0; i < m_nRouters ; i++) { |
akmhoque | 157b0a4 | 2014-05-13 00:26:37 -0500 | [diff] [blame] | 496 | if (i != sourceRouter) { |
Vince Lehman | 9a70903 | 2014-09-13 16:28:07 -0500 | [diff] [blame] | 497 | |
Nick G | 97e3494 | 2016-07-11 14:46:27 -0500 | [diff] [blame] | 498 | // Obtain the next hop that was determined by the algorithm |
akmhoque | 5335346 | 2014-04-22 08:43:45 -0500 | [diff] [blame] | 499 | nextHopRouter = getLsNextHop(i, sourceRouter); |
Nick G | 97e3494 | 2016-07-11 14:46:27 -0500 | [diff] [blame] | 500 | // If this router is accessible at all |
akmhoque | 157b0a4 | 2014-05-13 00:26:37 -0500 | [diff] [blame] | 501 | if (nextHopRouter != NO_NEXT_HOP) { |
Vince Lehman | 9a70903 | 2014-09-13 16:28:07 -0500 | [diff] [blame] | 502 | |
Nick G | 97e3494 | 2016-07-11 14:46:27 -0500 | [diff] [blame] | 503 | // Fetch its distance |
akmhoque | 5335346 | 2014-04-22 08:43:45 -0500 | [diff] [blame] | 504 | double routeCost = m_distance[i]; |
Nick G | 97e3494 | 2016-07-11 14:46:27 -0500 | [diff] [blame] | 505 | // Fetch its actual name |
Davide Pesavento | c1d0e8e | 2022-06-15 14:26:02 -0400 | [diff] [blame] | 506 | auto nextHopRouterName = pMap.getRouterNameByMappingNo(nextHopRouter); |
Nick Gordon | e40377d | 2017-08-11 15:10:02 -0500 | [diff] [blame] | 507 | if (nextHopRouterName) { |
Junxiao Shi | 6593a43 | 2023-08-21 10:50:28 +0000 | [diff] [blame] | 508 | auto nextHopFace = adjacencies.getAdjacent(*nextHopRouterName).getFaceUri(); |
Nick Gordon | e40377d | 2017-08-11 15:10:02 -0500 | [diff] [blame] | 509 | // Add next hop to routing table |
| 510 | NextHop nh(nextHopFace, routeCost); |
| 511 | rt.addNextHop(*(pMap.getRouterNameByMappingNo(i)), nh); |
Nick Gordon | e40377d | 2017-08-11 15:10:02 -0500 | [diff] [blame] | 512 | } |
akmhoque | 5335346 | 2014-04-22 08:43:45 -0500 | [diff] [blame] | 513 | } |
| 514 | } |
| 515 | } |
| 516 | } |
| 517 | |
| 518 | int |
| 519 | LinkStateRoutingTableCalculator::getLsNextHop(int dest, int source) |
| 520 | { |
| 521 | int nextHop = NO_NEXT_HOP; |
akmhoque | 157b0a4 | 2014-05-13 00:26:37 -0500 | [diff] [blame] | 522 | while (m_parent[dest] != EMPTY_PARENT) { |
akmhoque | 5335346 | 2014-04-22 08:43:45 -0500 | [diff] [blame] | 523 | nextHop = dest; |
| 524 | dest = m_parent[dest]; |
| 525 | } |
akmhoque | 157b0a4 | 2014-05-13 00:26:37 -0500 | [diff] [blame] | 526 | if (dest != source) { |
akmhoque | 5335346 | 2014-04-22 08:43:45 -0500 | [diff] [blame] | 527 | nextHop = NO_NEXT_HOP; |
| 528 | } |
| 529 | return nextHop; |
| 530 | } |
| 531 | |
| 532 | void |
akmhoque | 5335346 | 2014-04-22 08:43:45 -0500 | [diff] [blame] | 533 | LinkStateRoutingTableCalculator::sortQueueByDistance(int* Q, |
akmhoque | 2f42335 | 2014-06-03 11:49:35 -0500 | [diff] [blame] | 534 | double* dist, |
| 535 | int start, int element) |
akmhoque | 5335346 | 2014-04-22 08:43:45 -0500 | [diff] [blame] | 536 | { |
akmhoque | 157b0a4 | 2014-05-13 00:26:37 -0500 | [diff] [blame] | 537 | for (int i = start ; i < element ; i++) { |
| 538 | for (int j = i + 1; j < element; j++) { |
| 539 | if (dist[Q[j]] < dist[Q[i]]) { |
akmhoque | 5335346 | 2014-04-22 08:43:45 -0500 | [diff] [blame] | 540 | int tempU = Q[j]; |
| 541 | Q[j] = Q[i]; |
| 542 | Q[i] = tempU; |
| 543 | } |
| 544 | } |
| 545 | } |
| 546 | } |
| 547 | |
| 548 | int |
| 549 | LinkStateRoutingTableCalculator::isNotExplored(int* Q, |
| 550 | int u, int start, int element) |
| 551 | { |
| 552 | int ret = 0; |
akmhoque | 157b0a4 | 2014-05-13 00:26:37 -0500 | [diff] [blame] | 553 | for (int i = start; i < element; i++) { |
| 554 | if (Q[i] == u) { |
akmhoque | 5335346 | 2014-04-22 08:43:45 -0500 | [diff] [blame] | 555 | ret = 1; |
| 556 | break; |
| 557 | } |
| 558 | } |
| 559 | return ret; |
| 560 | } |
| 561 | |
| 562 | void |
| 563 | LinkStateRoutingTableCalculator::allocateParent() |
| 564 | { |
Vince Lehman | 9a70903 | 2014-09-13 16:28:07 -0500 | [diff] [blame] | 565 | m_parent = new int[m_nRouters]; |
akmhoque | 5335346 | 2014-04-22 08:43:45 -0500 | [diff] [blame] | 566 | } |
| 567 | |
| 568 | void |
| 569 | LinkStateRoutingTableCalculator::allocateDistance() |
| 570 | { |
Vince Lehman | 9a70903 | 2014-09-13 16:28:07 -0500 | [diff] [blame] | 571 | m_distance = new double[m_nRouters]; |
akmhoque | 5335346 | 2014-04-22 08:43:45 -0500 | [diff] [blame] | 572 | } |
| 573 | |
| 574 | void |
| 575 | LinkStateRoutingTableCalculator::freeParent() |
| 576 | { |
| 577 | delete [] m_parent; |
| 578 | } |
| 579 | |
| 580 | void LinkStateRoutingTableCalculator::freeDistance() |
| 581 | { |
| 582 | delete [] m_distance; |
| 583 | } |
| 584 | |
akmhoque | 5335346 | 2014-04-22 08:43:45 -0500 | [diff] [blame] | 585 | void |
Junxiao Shi | aead588 | 2024-02-21 12:32:02 +0000 | [diff] [blame^] | 586 | calculateLinkStateRoutingPath(NameMap& map, RoutingTable& rt, ConfParameter& confParam, |
| 587 | const Lsdb& lsdb) |
akmhoque | 5335346 | 2014-04-22 08:43:45 -0500 | [diff] [blame] | 588 | { |
Junxiao Shi | aead588 | 2024-02-21 12:32:02 +0000 | [diff] [blame^] | 589 | LinkStateRoutingTableCalculator calculator(map.size()); |
| 590 | calculator.calculatePath(map, rt, confParam, lsdb); |
akmhoque | 5335346 | 2014-04-22 08:43:45 -0500 | [diff] [blame] | 591 | } |
| 592 | |
Nick Gordon | fad8e25 | 2016-08-11 14:21:38 -0500 | [diff] [blame] | 593 | } // namespace nlsr |