blob: c5f8e09be1bdd5488cd118a483d6d9b5aa2a3d6e [file] [log] [blame]
akmhoque3d06e792014-05-27 16:23:20 -05001/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
2/**
Nick Gordonfeae5572017-01-13 12:06:26 -06003 * Copyright (c) 2014-2017, The University of Memphis,
Vince 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/>.
akmhoque3d06e792014-05-27 16:23:20 -050020 **/
Nick Gordone40377d2017-08-11 15:10:02 -050021
akmhoque53353462014-04-22 08:43:45 -050022#include "routing-table-calculator.hpp"
Nick Gordone98480b2017-05-24 11:23:03 -050023#include "lsdb.hpp"
akmhoque53353462014-04-22 08:43:45 -050024#include "map.hpp"
25#include "lsa.hpp"
26#include "nexthop.hpp"
27#include "nlsr.hpp"
akmhoque2f423352014-06-03 11:49:35 -050028#include "logger.hpp"
akmhoque53353462014-04-22 08:43:45 -050029
Nick Gordone98480b2017-05-24 11:23:03 -050030#include <iostream>
Vince Lehman9a709032014-09-13 16:28:07 -050031#include <boost/math/constants/constants.hpp>
Nick Gordone98480b2017-05-24 11:23:03 -050032#include <cmath>
Vince Lehman9a709032014-09-13 16:28:07 -050033
akmhoque53353462014-04-22 08:43:45 -050034namespace nlsr {
35
akmhoque2f423352014-06-03 11:49:35 -050036INIT_LOGGER("RoutingTableCalculator");
akmhoque53353462014-04-22 08:43:45 -050037
38void
39RoutingTableCalculator::allocateAdjMatrix()
40{
Vince Lehman9a709032014-09-13 16:28:07 -050041 adjMatrix = new double*[m_nRouters];
42
43 for (size_t i = 0; i < m_nRouters; ++i) {
44 adjMatrix[i] = new double[m_nRouters];
akmhoque53353462014-04-22 08:43:45 -050045 }
46}
47
48void
49RoutingTableCalculator::initMatrix()
50{
Vince Lehman9a709032014-09-13 16:28:07 -050051 for (size_t i = 0; i < m_nRouters; i++) {
52 for (size_t j = 0; j < m_nRouters; j++) {
akmhoque53353462014-04-22 08:43:45 -050053 adjMatrix[i][j] = 0;
akmhoque157b0a42014-05-13 00:26:37 -050054 }
akmhoque53353462014-04-22 08:43:45 -050055 }
56}
57
58void
59RoutingTableCalculator::makeAdjMatrix(Nlsr& pnlsr, Map pMap)
60{
61 std::list<AdjLsa> adjLsdb = pnlsr.getLsdb().getAdjLsdb();
Nick G97e34942016-07-11 14:46:27 -050062 // For each LSA represented in the map
Vince Lehman9a709032014-09-13 16:28:07 -050063 for (std::list<AdjLsa>::iterator it = adjLsdb.begin(); it != adjLsdb.end() ; it++) {
64
Nick G97e34942016-07-11 14:46:27 -050065
Nick Gordone40377d2017-08-11 15:10:02 -050066 ndn::optional<int32_t> row = pMap.getMappingNoByRouterName((*it).getOrigRouter());
Vince Lehman9a709032014-09-13 16:28:07 -050067
akmhoque53353462014-04-22 08:43:45 -050068 std::list<Adjacent> adl = (*it).getAdl().getAdjList();
Nick G97e34942016-07-11 14:46:27 -050069 // For each adjacency represented in the LSA
Vince Lehman9a709032014-09-13 16:28:07 -050070 for (std::list<Adjacent>::iterator itAdl = adl.begin(); itAdl != adl.end() ; itAdl++) {
71
Nick Gordone40377d2017-08-11 15:10:02 -050072 ndn::optional<int32_t> col = pMap.getMappingNoByRouterName((*itAdl).getName());
akmhoque53353462014-04-22 08:43:45 -050073 double cost = (*itAdl).getLinkCost();
Vince Lehman9a709032014-09-13 16:28:07 -050074
Nick Gordone40377d2017-08-11 15:10:02 -050075 if (row && col && *row < static_cast<int32_t>(m_nRouters)
76 && *col < static_cast<int32_t>(m_nRouters))
Vince Lehman9a709032014-09-13 16:28:07 -050077 {
Nick Gordone40377d2017-08-11 15:10:02 -050078 adjMatrix[*row][*col] = cost;
akmhoque53353462014-04-22 08:43:45 -050079 }
80 }
81 }
Vince Lehman41b173e2015-05-07 14:13:26 -050082
Nick G97e34942016-07-11 14:46:27 -050083 // Links that do not have the same cost for both directions should
84 // have their costs corrected:
Vince Lehman41b173e2015-05-07 14:13:26 -050085 //
Nick G97e34942016-07-11 14:46:27 -050086 // If the cost of one side of the link is 0, both sides of the
87 // link should have their cost corrected to 0.
Vince Lehman41b173e2015-05-07 14:13:26 -050088 //
89 // Otherwise, both sides of the link should use the larger of the two costs.
90 //
Nick G97e34942016-07-11 14:46:27 -050091 // Additionally, this means that we can halve the amount of space
92 // that the matrix uses by only maintaining a triangle.
93 // - But that is not yet implemented.
Vince Lehman41b173e2015-05-07 14:13:26 -050094 for (size_t row = 0; row < m_nRouters; ++row) {
95 for (size_t col = 0; col < m_nRouters; ++col) {
96 double toCost = adjMatrix[row][col];
97 double fromCost = adjMatrix[col][row];
98
99 if (fromCost != toCost) {
100 double correctedCost = 0.0;
101
102 if (toCost != 0 && fromCost != 0) {
103 // If both sides of the link are up, use the larger cost
104 correctedCost = std::max(toCost, fromCost);
105 }
106
107 _LOG_WARN("Cost between [" << row << "][" << col << "] and [" << col << "][" << row <<
108 "] are not the same (" << toCost << " != " << fromCost << "). " <<
109 "Correcting to cost: " << correctedCost);
110
111 adjMatrix[row][col] = correctedCost;
112 adjMatrix[col][row] = correctedCost;
113 }
114 }
115 }
akmhoque53353462014-04-22 08:43:45 -0500116}
117
118void
akmhoque2f423352014-06-03 11:49:35 -0500119RoutingTableCalculator::writeAdjMatrixLog()
akmhoque53353462014-04-22 08:43:45 -0500120{
Vince Lehman9a709032014-09-13 16:28:07 -0500121 for (size_t i = 0; i < m_nRouters; i++) {
Nick Gordone98480b2017-05-24 11:23:03 -0500122 std::string line="";
Vince Lehman9a709032014-09-13 16:28:07 -0500123 for (size_t j = 0; j < m_nRouters; j++) {
akmhoque2f423352014-06-03 11:49:35 -0500124 line += boost::lexical_cast<std::string>(adjMatrix[i][j]);
125 line += " ";
akmhoque157b0a42014-05-13 00:26:37 -0500126 }
akmhoque2f423352014-06-03 11:49:35 -0500127 _LOG_DEBUG(line);
akmhoque53353462014-04-22 08:43:45 -0500128 }
129}
130
131void
132RoutingTableCalculator::adjustAdMatrix(int source, int link, double linkCost)
133{
Vince Lehman9a709032014-09-13 16:28:07 -0500134 for (int i = 0; i < static_cast<int>(m_nRouters); i++) {
akmhoque157b0a42014-05-13 00:26:37 -0500135 if (i == link) {
akmhoque53353462014-04-22 08:43:45 -0500136 adjMatrix[source][i] = linkCost;
137 }
akmhoque157b0a42014-05-13 00:26:37 -0500138 else {
akmhoque53353462014-04-22 08:43:45 -0500139 adjMatrix[source][i] = 0;
140 }
141 }
142}
143
144int
145RoutingTableCalculator::getNumOfLinkfromAdjMatrix(int sRouter)
146{
147 int noLink = 0;
Vince Lehman9a709032014-09-13 16:28:07 -0500148
149 for (size_t i = 0; i < m_nRouters; i++) {
akmhoque157b0a42014-05-13 00:26:37 -0500150 if (adjMatrix[sRouter][i] > 0) {
akmhoque53353462014-04-22 08:43:45 -0500151 noLink++;
152 }
153 }
154 return noLink;
155}
156
157void
158RoutingTableCalculator::getLinksFromAdjMatrix(int* links,
159 double* linkCosts, int source)
160{
161 int j = 0;
Vince Lehman9a709032014-09-13 16:28:07 -0500162
163 for (size_t i = 0; i < m_nRouters; i++) {
akmhoque157b0a42014-05-13 00:26:37 -0500164 if (adjMatrix[source][i] > 0) {
akmhoque53353462014-04-22 08:43:45 -0500165 links[j] = i;
166 linkCosts[j] = adjMatrix[source][i];
167 j++;
168 }
169 }
170}
171
172void
173RoutingTableCalculator::freeAdjMatrix()
174{
Vince Lehman9a709032014-09-13 16:28:07 -0500175 for (size_t i = 0; i < m_nRouters; ++i) {
akmhoque53353462014-04-22 08:43:45 -0500176 delete [] adjMatrix[i];
177 }
178 delete [] adjMatrix;
179}
180
akmhoque53353462014-04-22 08:43:45 -0500181void
182RoutingTableCalculator::allocateLinks()
183{
184 links = new int[vNoLink];
185}
186
187void
188RoutingTableCalculator::allocateLinkCosts()
189{
190 linkCosts = new double[vNoLink];
191}
192
193
194void
195RoutingTableCalculator::freeLinks()
196{
197 delete [] links;
198}
199void
200RoutingTableCalculator::freeLinksCosts()
201{
202 delete [] linkCosts;
203}
204
205void
206LinkStateRoutingTableCalculator::calculatePath(Map& pMap,
207 RoutingTable& rt, Nlsr& pnlsr)
208{
akmhoque2f423352014-06-03 11:49:35 -0500209 _LOG_DEBUG("LinkStateRoutingTableCalculator::calculatePath Called");
akmhoque53353462014-04-22 08:43:45 -0500210 allocateAdjMatrix();
211 initMatrix();
212 makeAdjMatrix(pnlsr, pMap);
akmhoque2f423352014-06-03 11:49:35 -0500213 writeAdjMatrixLog();
Nick Gordone40377d2017-08-11 15:10:02 -0500214 ndn::optional<int32_t> sourceRouter =
215 pMap.getMappingNoByRouterName(pnlsr.getConfParameter().getRouterPrefix());
Nick G97e34942016-07-11 14:46:27 -0500216 allocateParent(); // These two matrices are used in Dijkstra's algorithm.
217 allocateDistance(); //
Nick Gordone40377d2017-08-11 15:10:02 -0500218 // We only bother to do the calculation if we have a router by that name.
219 if (sourceRouter && pnlsr.getConfParameter().getMaxFacesPerPrefix() == 1) {
Nick G97e34942016-07-11 14:46:27 -0500220 // In the single path case we can simply run Dijkstra's algorithm.
Nick Gordone40377d2017-08-11 15:10:02 -0500221 doDijkstraPathCalculation(*sourceRouter);
Nick G97e34942016-07-11 14:46:27 -0500222 // Inform the routing table of the new next hops.
Nick Gordone40377d2017-08-11 15:10:02 -0500223 addAllLsNextHopsToRoutingTable(pnlsr, rt, pMap, *sourceRouter);
akmhoque53353462014-04-22 08:43:45 -0500224 }
akmhoque157b0a42014-05-13 00:26:37 -0500225 else {
akmhoque53353462014-04-22 08:43:45 -0500226 // Multi Path
Nick Gordone40377d2017-08-11 15:10:02 -0500227 setNoLink(getNumOfLinkfromAdjMatrix(*sourceRouter));
akmhoque53353462014-04-22 08:43:45 -0500228 allocateLinks();
229 allocateLinkCosts();
Nick G97e34942016-07-11 14:46:27 -0500230 // Gets a sparse listing of adjacencies for path calculation
Nick Gordone40377d2017-08-11 15:10:02 -0500231 getLinksFromAdjMatrix(links, linkCosts, *sourceRouter);
akmhoque157b0a42014-05-13 00:26:37 -0500232 for (int i = 0 ; i < vNoLink; i++) {
Nick G97e34942016-07-11 14:46:27 -0500233 // Simulate that only the current neighbor is accessible
Nick Gordone40377d2017-08-11 15:10:02 -0500234 adjustAdMatrix(*sourceRouter, links[i], linkCosts[i]);
akmhoque2f423352014-06-03 11:49:35 -0500235 writeAdjMatrixLog();
Nick G97e34942016-07-11 14:46:27 -0500236 // Do Dijkstra's algorithm using the current neighbor as your start.
Nick Gordone40377d2017-08-11 15:10:02 -0500237 doDijkstraPathCalculation(*sourceRouter);
Nick G97e34942016-07-11 14:46:27 -0500238 // Update the routing table with the calculations.
Nick Gordone40377d2017-08-11 15:10:02 -0500239 addAllLsNextHopsToRoutingTable(pnlsr, rt, pMap, *sourceRouter);
akmhoque53353462014-04-22 08:43:45 -0500240 }
241 freeLinks();
242 freeLinksCosts();
243 }
244 freeParent();
245 freeDistance();
246 freeAdjMatrix();
247}
248
249void
250LinkStateRoutingTableCalculator::doDijkstraPathCalculation(int sourceRouter)
251{
252 int i;
253 int v, u;
Nick G97e34942016-07-11 14:46:27 -0500254 int* Q = new int[m_nRouters]; // Each cell represents the router with that mapping no.
akmhoque53353462014-04-22 08:43:45 -0500255 int head = 0;
Nick Gordone98480b2017-05-24 11:23:03 -0500256 // Initiate the parent
Vince Lehman9a709032014-09-13 16:28:07 -0500257 for (i = 0 ; i < static_cast<int>(m_nRouters); i++) {
akmhoque53353462014-04-22 08:43:45 -0500258 m_parent[i] = EMPTY_PARENT;
Nick G97e34942016-07-11 14:46:27 -0500259 // Array where the ith element is the distance to the router with mapping no i.
akmhoque53353462014-04-22 08:43:45 -0500260 m_distance[i] = INF_DISTANCE;
261 Q[i] = i;
262 }
akmhoque157b0a42014-05-13 00:26:37 -0500263 if (sourceRouter != NO_MAPPING_NUM) {
Nick G97e34942016-07-11 14:46:27 -0500264 // Distance to source from source is always 0.
akmhoque53353462014-04-22 08:43:45 -0500265 m_distance[sourceRouter] = 0;
Vince Lehman9a709032014-09-13 16:28:07 -0500266 sortQueueByDistance(Q, m_distance, head, m_nRouters);
Nick G97e34942016-07-11 14:46:27 -0500267 // While we haven't visited every node.
Vince Lehman9a709032014-09-13 16:28:07 -0500268 while (head < static_cast<int>(m_nRouters)) {
Nick G97e34942016-07-11 14:46:27 -0500269 u = Q[head]; // Set u to be the current node pointed to by head.
akmhoque157b0a42014-05-13 00:26:37 -0500270 if (m_distance[u] == INF_DISTANCE) {
Nick G97e34942016-07-11 14:46:27 -0500271 break; // This can only happen when there are no accessible nodes.
akmhoque53353462014-04-22 08:43:45 -0500272 }
Nick G97e34942016-07-11 14:46:27 -0500273 // Iterate over the adjacent nodes to u.
Vince Lehman9a709032014-09-13 16:28:07 -0500274 for (v = 0 ; v < static_cast<int>(m_nRouters); v++) {
Nick G97e34942016-07-11 14:46:27 -0500275 // If the current node is accessible.
akmhoque157b0a42014-05-13 00:26:37 -0500276 if (adjMatrix[u][v] > 0) {
Nick G97e34942016-07-11 14:46:27 -0500277 // And we haven't visited it yet.
Vince Lehman9a709032014-09-13 16:28:07 -0500278 if (isNotExplored(Q, v, head + 1, m_nRouters)) {
Nick G97e34942016-07-11 14:46:27 -0500279 // And if the distance to this node + from this node to v
280 // is less than the distance from our source node to v
281 // that we got when we built the adj LSAs
akmhoque157b0a42014-05-13 00:26:37 -0500282 if (m_distance[u] + adjMatrix[u][v] < m_distance[v]) {
Nick G97e34942016-07-11 14:46:27 -0500283 // Set the new distance
akmhoque53353462014-04-22 08:43:45 -0500284 m_distance[v] = m_distance[u] + adjMatrix[u][v] ;
Nick G97e34942016-07-11 14:46:27 -0500285 // Set how we get there.
akmhoque53353462014-04-22 08:43:45 -0500286 m_parent[v] = u;
287 }
288 }
289 }
290 }
Nick G97e34942016-07-11 14:46:27 -0500291 // Increment the head position, resort the list by distance from where we are.
akmhoque53353462014-04-22 08:43:45 -0500292 head++;
Vince Lehman9a709032014-09-13 16:28:07 -0500293 sortQueueByDistance(Q, m_distance, head, m_nRouters);
akmhoque53353462014-04-22 08:43:45 -0500294 }
295 }
296 delete [] Q;
297}
298
299void
Vince Lehman9a709032014-09-13 16:28:07 -0500300LinkStateRoutingTableCalculator::addAllLsNextHopsToRoutingTable(Nlsr& pnlsr, RoutingTable& rt,
301 Map& pMap, uint32_t sourceRouter)
akmhoque53353462014-04-22 08:43:45 -0500302{
akmhoque2f423352014-06-03 11:49:35 -0500303 _LOG_DEBUG("LinkStateRoutingTableCalculator::addAllNextHopsToRoutingTable Called");
Vince Lehman9a709032014-09-13 16:28:07 -0500304
akmhoque53353462014-04-22 08:43:45 -0500305 int nextHopRouter = 0;
Vince Lehman9a709032014-09-13 16:28:07 -0500306
Nick G97e34942016-07-11 14:46:27 -0500307 // For each router we have
Vince Lehman9a709032014-09-13 16:28:07 -0500308 for (size_t i = 0; i < m_nRouters ; i++) {
akmhoque157b0a42014-05-13 00:26:37 -0500309 if (i != sourceRouter) {
Vince Lehman9a709032014-09-13 16:28:07 -0500310
Nick G97e34942016-07-11 14:46:27 -0500311 // Obtain the next hop that was determined by the algorithm
akmhoque53353462014-04-22 08:43:45 -0500312 nextHopRouter = getLsNextHop(i, sourceRouter);
Vince Lehman9a709032014-09-13 16:28:07 -0500313
Nick G97e34942016-07-11 14:46:27 -0500314 // If this router is accessible at all
akmhoque157b0a42014-05-13 00:26:37 -0500315 if (nextHopRouter != NO_NEXT_HOP) {
Vince Lehman9a709032014-09-13 16:28:07 -0500316
Nick G97e34942016-07-11 14:46:27 -0500317 // Fetch its distance
akmhoque53353462014-04-22 08:43:45 -0500318 double routeCost = m_distance[i];
Nick G97e34942016-07-11 14:46:27 -0500319 // Fetch its actual name
Nick Gordone40377d2017-08-11 15:10:02 -0500320 ndn::optional<ndn::Name> nextHopRouterName= pMap.getRouterNameByMappingNo(nextHopRouter);
321 if (nextHopRouterName) {
322 std::string nextHopFace =
323 pnlsr.getAdjacencyList().getAdjacent(*nextHopRouterName).getFaceUri().toString();
324 // Add next hop to routing table
325 NextHop nh(nextHopFace, routeCost);
326 rt.addNextHop(*(pMap.getRouterNameByMappingNo(i)), nh);
327
328 }
akmhoque53353462014-04-22 08:43:45 -0500329 }
330 }
331 }
332}
333
334int
335LinkStateRoutingTableCalculator::getLsNextHop(int dest, int source)
336{
337 int nextHop = NO_NEXT_HOP;
akmhoque157b0a42014-05-13 00:26:37 -0500338 while (m_parent[dest] != EMPTY_PARENT) {
akmhoque53353462014-04-22 08:43:45 -0500339 nextHop = dest;
340 dest = m_parent[dest];
341 }
akmhoque157b0a42014-05-13 00:26:37 -0500342 if (dest != source) {
akmhoque53353462014-04-22 08:43:45 -0500343 nextHop = NO_NEXT_HOP;
344 }
345 return nextHop;
346}
347
348void
akmhoque53353462014-04-22 08:43:45 -0500349LinkStateRoutingTableCalculator::sortQueueByDistance(int* Q,
akmhoque2f423352014-06-03 11:49:35 -0500350 double* dist,
351 int start, int element)
akmhoque53353462014-04-22 08:43:45 -0500352{
akmhoque157b0a42014-05-13 00:26:37 -0500353 for (int i = start ; i < element ; i++) {
354 for (int j = i + 1; j < element; j++) {
355 if (dist[Q[j]] < dist[Q[i]]) {
akmhoque53353462014-04-22 08:43:45 -0500356 int tempU = Q[j];
357 Q[j] = Q[i];
358 Q[i] = tempU;
359 }
360 }
361 }
362}
363
364int
365LinkStateRoutingTableCalculator::isNotExplored(int* Q,
366 int u, int start, int element)
367{
368 int ret = 0;
akmhoque157b0a42014-05-13 00:26:37 -0500369 for (int i = start; i < element; i++) {
370 if (Q[i] == u) {
akmhoque53353462014-04-22 08:43:45 -0500371 ret = 1;
372 break;
373 }
374 }
375 return ret;
376}
377
378void
379LinkStateRoutingTableCalculator::allocateParent()
380{
Vince Lehman9a709032014-09-13 16:28:07 -0500381 m_parent = new int[m_nRouters];
akmhoque53353462014-04-22 08:43:45 -0500382}
383
384void
385LinkStateRoutingTableCalculator::allocateDistance()
386{
Vince Lehman9a709032014-09-13 16:28:07 -0500387 m_distance = new double[m_nRouters];
akmhoque53353462014-04-22 08:43:45 -0500388}
389
390void
391LinkStateRoutingTableCalculator::freeParent()
392{
393 delete [] m_parent;
394}
395
396void LinkStateRoutingTableCalculator::freeDistance()
397{
398 delete [] m_distance;
399}
400
Vince Lehman9a709032014-09-13 16:28:07 -0500401const double HyperbolicRoutingCalculator::MATH_PI = boost::math::constants::pi<double>();
akmhoque53353462014-04-22 08:43:45 -0500402
Vince Lehman9a709032014-09-13 16:28:07 -0500403const double HyperbolicRoutingCalculator::UNKNOWN_DISTANCE = -1.0;
404const double HyperbolicRoutingCalculator::UNKNOWN_RADIUS = -1.0;
405
akmhoque53353462014-04-22 08:43:45 -0500406void
Vince Lehman9a709032014-09-13 16:28:07 -0500407HyperbolicRoutingCalculator::calculatePaths(Map& map, RoutingTable& rt,
408 Lsdb& lsdb, AdjacencyList& adjacencies)
akmhoque53353462014-04-22 08:43:45 -0500409{
Vince Lehman9a709032014-09-13 16:28:07 -0500410 _LOG_TRACE("Calculating hyperbolic paths");
411
Nick Gordone40377d2017-08-11 15:10:02 -0500412 ndn::optional<int32_t> thisRouter = map.getMappingNoByRouterName(m_thisRouterName);
Vince Lehman9a709032014-09-13 16:28:07 -0500413
414 // Iterate over directly connected neighbors
415 std::list<Adjacent> neighbors = adjacencies.getAdjList();
416 for (std::list<Adjacent>::iterator adj = neighbors.begin(); adj != neighbors.end(); ++adj) {
417
418 // Don't calculate nexthops using an inactive router
419 if (adj->getStatus() == Adjacent::STATUS_INACTIVE) {
420 _LOG_TRACE(adj->getName() << " is inactive; not using it as a nexthop");
421 continue;
422 }
423
424 ndn::Name srcRouterName = adj->getName();
425
426 // Don't calculate nexthops for this router to other routers
427 if (srcRouterName == m_thisRouterName) {
428 continue;
429 }
430
Nick Gordone9733ed2017-04-26 10:48:39 -0500431 std::string srcFaceUri = adj->getFaceUri().toString();
Vince Lehman9a709032014-09-13 16:28:07 -0500432
433 // Install nexthops for this router to the neighbor; direct neighbors have a 0 cost link
434 addNextHop(srcRouterName, srcFaceUri, 0, rt);
435
Nick Gordone40377d2017-08-11 15:10:02 -0500436 ndn::optional<int32_t> src = map.getMappingNoByRouterName(srcRouterName);
Vince Lehman9a709032014-09-13 16:28:07 -0500437
Nick Gordone40377d2017-08-11 15:10:02 -0500438 if (!src) {
Vince Lehman9a709032014-09-13 16:28:07 -0500439 _LOG_WARN(adj->getName() << " does not exist in the router map!");
440 continue;
441 }
442
443 // Get hyperbolic distance from direct neighbor to every other router
444 for (int dest = 0; dest < static_cast<int>(m_nRouters); ++dest) {
445 // Don't calculate nexthops to this router or from a router to itself
Nick Gordone40377d2017-08-11 15:10:02 -0500446 if (thisRouter && dest != *thisRouter && dest != *src) {
Vince Lehman9a709032014-09-13 16:28:07 -0500447
Nick Gordone40377d2017-08-11 15:10:02 -0500448 ndn::optional<ndn::Name> destRouterName = map.getRouterNameByMappingNo(dest);
449 if (destRouterName) {
450 double distance = getHyperbolicDistance(map, lsdb, srcRouterName, *destRouterName);
Vince Lehman9a709032014-09-13 16:28:07 -0500451
Nick Gordone40377d2017-08-11 15:10:02 -0500452 // Could not compute distance
453 if (distance == UNKNOWN_DISTANCE) {
454 _LOG_WARN("Could not calculate hyperbolic distance from " << srcRouterName << " to " <<
455 *destRouterName);
456 continue;
457 }
Vince Lehman9a709032014-09-13 16:28:07 -0500458
Nick Gordone40377d2017-08-11 15:10:02 -0500459 addNextHop(*destRouterName, srcFaceUri, distance, rt);
akmhoque53353462014-04-22 08:43:45 -0500460 }
Vince Lehman9a709032014-09-13 16:28:07 -0500461 }
akmhoquedcee9362014-08-05 22:58:01 -0500462 }
akmhoque53353462014-04-22 08:43:45 -0500463 }
464}
465
466double
Vince Lehman9a709032014-09-13 16:28:07 -0500467HyperbolicRoutingCalculator::getHyperbolicDistance(Map& map, Lsdb& lsdb,
468 ndn::Name src, ndn::Name dest)
akmhoque53353462014-04-22 08:43:45 -0500469{
Vince Lehman9a709032014-09-13 16:28:07 -0500470 _LOG_TRACE("Calculating hyperbolic distance from " << src << " to " << dest);
akmhoquedcee9362014-08-05 22:58:01 -0500471
Vince Lehman9a709032014-09-13 16:28:07 -0500472 double distance = UNKNOWN_DISTANCE;
473
474 ndn::Name srcLsaKey = src;
Nick Gordon727d4832017-10-13 18:04:25 -0500475 srcLsaKey.append(std::to_string(Lsa::Type::COORDINATE));
Vince Lehman9a709032014-09-13 16:28:07 -0500476
477 CoordinateLsa* srcLsa = lsdb.findCoordinateLsa(srcLsaKey);
478
479 ndn::Name destLsaKey = dest;
Nick Gordon727d4832017-10-13 18:04:25 -0500480 destLsaKey.append(std::to_string(Lsa::Type::COORDINATE));
Vince Lehman9a709032014-09-13 16:28:07 -0500481
482 CoordinateLsa* destLsa = lsdb.findCoordinateLsa(destLsaKey);
483
484 // Coordinate LSAs do not exist for these routers
Nick Gordone9733ed2017-04-26 10:48:39 -0500485 if (srcLsa == nullptr || destLsa == nullptr) {
Vince Lehman9a709032014-09-13 16:28:07 -0500486 return UNKNOWN_DISTANCE;
akmhoquedcee9362014-08-05 22:58:01 -0500487 }
488
Muktadir R Chowdhuryb00dc2a2016-11-05 10:48:58 -0600489 std::vector<double> srcTheta = srcLsa->getCorTheta();
490 std::vector<double> destTheta = destLsa->getCorTheta();
Vince Lehman9a709032014-09-13 16:28:07 -0500491
492 double srcRadius = srcLsa->getCorRadius();
493 double destRadius = destLsa->getCorRadius();
494
Muktadir R Chowdhuryb00dc2a2016-11-05 10:48:58 -0600495 double diffTheta = calculateAngularDistance(srcTheta, destTheta);
496
497 if (srcRadius == UNKNOWN_RADIUS || destRadius == UNKNOWN_RADIUS ||
498 diffTheta == UNKNOWN_DISTANCE) {
Vince Lehman9a709032014-09-13 16:28:07 -0500499 return UNKNOWN_DISTANCE;
500 }
501
Muktadir R Chowdhuryb00dc2a2016-11-05 10:48:58 -0600502 // double r_i, double r_j, double delta_theta, double zeta = 1 (default)
503 distance = calculateHyperbolicDistance(srcRadius, destRadius, diffTheta);
Vince Lehman9a709032014-09-13 16:28:07 -0500504
505 _LOG_TRACE("Distance from " << src << " to " << dest << " is " << distance);
506
akmhoque53353462014-04-22 08:43:45 -0500507 return distance;
508}
509
Muktadir R Chowdhuryb00dc2a2016-11-05 10:48:58 -0600510double
511HyperbolicRoutingCalculator::calculateAngularDistance(std::vector<double> angleVectorI,
512 std::vector<double> angleVectorJ)
513{
514 // It is not possible for angle vector size to be zero as ensured by conf-file-processor
515
516 // https://en.wikipedia.org/wiki/N-sphere#Spherical_coordinates
517
518 // Check if two vector lengths are the same
519 if (angleVectorI.size() != angleVectorJ.size()) {
520 _LOG_ERROR("Angle vector sizes do not match");
521 return UNKNOWN_DISTANCE;
522 }
523
524 // Check if all angles are within the [0, PI] and [0, 2PI] ranges
525 if (angleVectorI.size() > 1) {
526 for (unsigned int k = 0; k < angleVectorI.size() - 1; k++) {
527 if ((angleVectorI[k] > M_PI && angleVectorI[k] < 0.0) ||
528 (angleVectorJ[k] > M_PI && angleVectorJ[k] < 0.0)) {
529 _LOG_ERROR("Angle outside [0, PI]");
530 return UNKNOWN_DISTANCE;
531 }
532 }
533 }
534 if (angleVectorI[angleVectorI.size()-1] > 2.*M_PI ||
535 angleVectorI[angleVectorI.size()-1] < 0.0) {
536 _LOG_ERROR("Angle not within [0, 2PI]");
537 return UNKNOWN_DISTANCE;
538 }
539
540 if (angleVectorI[angleVectorI.size()-1] > 2.*M_PI ||
541 angleVectorI[angleVectorI.size()-1] < 0.0) {
542 _LOG_ERROR("Angle not within [0, 2PI]");
543 return UNKNOWN_DISTANCE;
544 }
545
546 // deltaTheta = arccos(vectorI . vectorJ) -> do the inner product
547 double innerProduct = 0.0;
548
549 // Calculate x0 of the vectors
550 double x0i = std::cos(angleVectorI[0]);
551 double x0j = std::cos(angleVectorJ[0]);
552
553 // Calculate xn of the vectors
554 double xni = std::sin(angleVectorI[angleVectorI.size() - 1]);
555 double xnj = std::sin(angleVectorJ[angleVectorJ.size() - 1]);
556
557 // Do the aggregation of the (n-1) coordinates (if there is more than one angle)
558 // i.e contraction of all (n-1)-dimensional angular coordinates to one variable
559 for (unsigned int k = 0; k < angleVectorI.size() - 1; k++) {
560 xni *= std::sin(angleVectorI[k]);
561 xnj *= std::sin(angleVectorJ[k]);
562 }
563 innerProduct += (x0i * x0j) + (xni * xnj);
564
565 // If d > 1
566 if (angleVectorI.size() > 1) {
567 for (unsigned int m = 1; m < angleVectorI.size(); m++) {
568 // calculate euclidean coordinates given the angles and assuming R_sphere = 1
569 double xmi = std::cos(angleVectorI[m]);
570 double xmj = std::cos(angleVectorJ[m]);
571 for (unsigned int l = 0; l < m; l++) {
572 xmi *= std::sin(angleVectorI[l]);
573 xmj *= std::sin(angleVectorJ[l]);
574 }
575 innerProduct += xmi * xmj;
576 }
577 }
578
579 // ArcCos of the inner product gives the angular distance
580 // between two points on a d-dimensional sphere
581 return std::acos(innerProduct);
582}
583
584double
585HyperbolicRoutingCalculator::calculateHyperbolicDistance(double rI, double rJ,
586 double deltaTheta)
587{
588 if (deltaTheta == UNKNOWN_DISTANCE) {
589 return UNKNOWN_DISTANCE;
590 }
591
592 // Usually, we set zeta = 1 in all experiments
593 double zeta = 1;
594
595 if (deltaTheta <= 0.0 || rI <= 0.0 || rJ <= 0.0) {
596 _LOG_ERROR("Delta theta or rI or rJ is <= 0");
597 return UNKNOWN_DISTANCE;
598 }
599
600 double xij = (1. / zeta) * std::acosh(std::cosh(zeta*rI) * std::cosh(zeta*rJ) -
601 std::sinh(zeta*rI)*std::sinh(zeta*rJ)*std::cos(deltaTheta));
602 return xij;
603}
604
605void
606HyperbolicRoutingCalculator::addNextHop(ndn::Name dest, std::string faceUri,
607 double cost, RoutingTable& rt)
akmhoque53353462014-04-22 08:43:45 -0500608{
Vince Lehman9a709032014-09-13 16:28:07 -0500609 NextHop hop(faceUri, cost);
Vince Lehman20fe4a92014-09-09 15:57:59 -0500610 hop.setHyperbolic(true);
akmhoque53353462014-04-22 08:43:45 -0500611
Vince Lehman9a709032014-09-13 16:28:07 -0500612 _LOG_TRACE("Calculated " << hop << " for destination: " << dest);
akmhoque53353462014-04-22 08:43:45 -0500613
Vince Lehman9a709032014-09-13 16:28:07 -0500614 if (m_isDryRun) {
615 rt.addNextHopToDryTable(dest, hop);
616 }
617 else {
618 rt.addNextHop(dest, hop);
619 }
akmhoque53353462014-04-22 08:43:45 -0500620}
621
Nick Gordonfad8e252016-08-11 14:21:38 -0500622} // namespace nlsr