blob: 7aa6f4853fea1d70f2bec576e90ce31a94715681 [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 **/
Vince Lehman41b173e2015-05-07 14:13:26 -050021
akmhoque53353462014-04-22 08:43:45 -050022#include <iostream>
23#include <cmath>
24#include "lsdb.hpp"
25#include "routing-table-calculator.hpp"
26#include "map.hpp"
27#include "lsa.hpp"
28#include "nexthop.hpp"
29#include "nlsr.hpp"
akmhoque2f423352014-06-03 11:49:35 -050030#include "logger.hpp"
akmhoque53353462014-04-22 08:43:45 -050031
Vince Lehman9a709032014-09-13 16:28:07 -050032#include <boost/math/constants/constants.hpp>
33
akmhoque53353462014-04-22 08:43:45 -050034namespace nlsr {
35
akmhoque2f423352014-06-03 11:49:35 -050036INIT_LOGGER("RoutingTableCalculator");
akmhoque53353462014-04-22 08:43:45 -050037using namespace std;
38
39void
40RoutingTableCalculator::allocateAdjMatrix()
41{
Vince Lehman9a709032014-09-13 16:28:07 -050042 adjMatrix = new double*[m_nRouters];
43
44 for (size_t i = 0; i < m_nRouters; ++i) {
45 adjMatrix[i] = new double[m_nRouters];
akmhoque53353462014-04-22 08:43:45 -050046 }
47}
48
49void
50RoutingTableCalculator::initMatrix()
51{
Vince Lehman9a709032014-09-13 16:28:07 -050052 for (size_t i = 0; i < m_nRouters; i++) {
53 for (size_t j = 0; j < m_nRouters; j++) {
akmhoque53353462014-04-22 08:43:45 -050054 adjMatrix[i][j] = 0;
akmhoque157b0a42014-05-13 00:26:37 -050055 }
akmhoque53353462014-04-22 08:43:45 -050056 }
57}
58
59void
60RoutingTableCalculator::makeAdjMatrix(Nlsr& pnlsr, Map pMap)
61{
62 std::list<AdjLsa> adjLsdb = pnlsr.getLsdb().getAdjLsdb();
Nick G97e34942016-07-11 14:46:27 -050063 // For each LSA represented in the map
Vince Lehman9a709032014-09-13 16:28:07 -050064 for (std::list<AdjLsa>::iterator it = adjLsdb.begin(); it != adjLsdb.end() ; it++) {
65
Nick G97e34942016-07-11 14:46:27 -050066
Vince Lehman9a709032014-09-13 16:28:07 -050067 int32_t row = pMap.getMappingNoByRouterName((*it).getOrigRouter());
68
akmhoque53353462014-04-22 08:43:45 -050069 std::list<Adjacent> adl = (*it).getAdl().getAdjList();
Nick G97e34942016-07-11 14:46:27 -050070 // For each adjacency represented in the LSA
Vince Lehman9a709032014-09-13 16:28:07 -050071 for (std::list<Adjacent>::iterator itAdl = adl.begin(); itAdl != adl.end() ; itAdl++) {
72
73 int32_t col = pMap.getMappingNoByRouterName((*itAdl).getName());
akmhoque53353462014-04-22 08:43:45 -050074 double cost = (*itAdl).getLinkCost();
Vince Lehman9a709032014-09-13 16:28:07 -050075
76 if ((row >= 0 && row < static_cast<int32_t>(m_nRouters)) &&
77 (col >= 0 && col < static_cast<int32_t>(m_nRouters)))
78 {
akmhoque53353462014-04-22 08:43:45 -050079 adjMatrix[row][col] = cost;
80 }
81 }
82 }
Vince Lehman41b173e2015-05-07 14:13:26 -050083
Nick G97e34942016-07-11 14:46:27 -050084 // Links that do not have the same cost for both directions should
85 // have their costs corrected:
Vince Lehman41b173e2015-05-07 14:13:26 -050086 //
Nick G97e34942016-07-11 14:46:27 -050087 // If the cost of one side of the link is 0, both sides of the
88 // link should have their cost corrected to 0.
Vince Lehman41b173e2015-05-07 14:13:26 -050089 //
90 // Otherwise, both sides of the link should use the larger of the two costs.
91 //
Nick G97e34942016-07-11 14:46:27 -050092 // Additionally, this means that we can halve the amount of space
93 // that the matrix uses by only maintaining a triangle.
94 // - But that is not yet implemented.
Vince Lehman41b173e2015-05-07 14:13:26 -050095 for (size_t row = 0; row < m_nRouters; ++row) {
96 for (size_t col = 0; col < m_nRouters; ++col) {
97 double toCost = adjMatrix[row][col];
98 double fromCost = adjMatrix[col][row];
99
100 if (fromCost != toCost) {
101 double correctedCost = 0.0;
102
103 if (toCost != 0 && fromCost != 0) {
104 // If both sides of the link are up, use the larger cost
105 correctedCost = std::max(toCost, fromCost);
106 }
107
108 _LOG_WARN("Cost between [" << row << "][" << col << "] and [" << col << "][" << row <<
109 "] are not the same (" << toCost << " != " << fromCost << "). " <<
110 "Correcting to cost: " << correctedCost);
111
112 adjMatrix[row][col] = correctedCost;
113 adjMatrix[col][row] = correctedCost;
114 }
115 }
116 }
akmhoque53353462014-04-22 08:43:45 -0500117}
118
119void
akmhoque2f423352014-06-03 11:49:35 -0500120RoutingTableCalculator::writeAdjMatrixLog()
akmhoque53353462014-04-22 08:43:45 -0500121{
Vince Lehman9a709032014-09-13 16:28:07 -0500122 for (size_t i = 0; i < m_nRouters; i++) {
akmhoque2f423352014-06-03 11:49:35 -0500123 string line="";
Vince Lehman9a709032014-09-13 16:28:07 -0500124 for (size_t j = 0; j < m_nRouters; j++) {
akmhoque2f423352014-06-03 11:49:35 -0500125 line += boost::lexical_cast<std::string>(adjMatrix[i][j]);
126 line += " ";
akmhoque157b0a42014-05-13 00:26:37 -0500127 }
akmhoque2f423352014-06-03 11:49:35 -0500128 _LOG_DEBUG(line);
akmhoque53353462014-04-22 08:43:45 -0500129 }
130}
131
132void
133RoutingTableCalculator::adjustAdMatrix(int source, int link, double linkCost)
134{
Vince Lehman9a709032014-09-13 16:28:07 -0500135 for (int i = 0; i < static_cast<int>(m_nRouters); i++) {
akmhoque157b0a42014-05-13 00:26:37 -0500136 if (i == link) {
akmhoque53353462014-04-22 08:43:45 -0500137 adjMatrix[source][i] = linkCost;
138 }
akmhoque157b0a42014-05-13 00:26:37 -0500139 else {
akmhoque53353462014-04-22 08:43:45 -0500140 adjMatrix[source][i] = 0;
141 }
142 }
143}
144
145int
146RoutingTableCalculator::getNumOfLinkfromAdjMatrix(int sRouter)
147{
148 int noLink = 0;
Vince Lehman9a709032014-09-13 16:28:07 -0500149
150 for (size_t i = 0; i < m_nRouters; i++) {
akmhoque157b0a42014-05-13 00:26:37 -0500151 if (adjMatrix[sRouter][i] > 0) {
akmhoque53353462014-04-22 08:43:45 -0500152 noLink++;
153 }
154 }
155 return noLink;
156}
157
158void
159RoutingTableCalculator::getLinksFromAdjMatrix(int* links,
160 double* linkCosts, int source)
161{
162 int j = 0;
Vince Lehman9a709032014-09-13 16:28:07 -0500163
164 for (size_t i = 0; i < m_nRouters; i++) {
akmhoque157b0a42014-05-13 00:26:37 -0500165 if (adjMatrix[source][i] > 0) {
akmhoque53353462014-04-22 08:43:45 -0500166 links[j] = i;
167 linkCosts[j] = adjMatrix[source][i];
168 j++;
169 }
170 }
171}
172
173void
174RoutingTableCalculator::freeAdjMatrix()
175{
Vince Lehman9a709032014-09-13 16:28:07 -0500176 for (size_t i = 0; i < m_nRouters; ++i) {
akmhoque53353462014-04-22 08:43:45 -0500177 delete [] adjMatrix[i];
178 }
179 delete [] adjMatrix;
180}
181
akmhoque53353462014-04-22 08:43:45 -0500182void
183RoutingTableCalculator::allocateLinks()
184{
185 links = new int[vNoLink];
186}
187
188void
189RoutingTableCalculator::allocateLinkCosts()
190{
191 linkCosts = new double[vNoLink];
192}
193
194
195void
196RoutingTableCalculator::freeLinks()
197{
198 delete [] links;
199}
200void
201RoutingTableCalculator::freeLinksCosts()
202{
203 delete [] linkCosts;
204}
205
206void
207LinkStateRoutingTableCalculator::calculatePath(Map& pMap,
208 RoutingTable& rt, Nlsr& pnlsr)
209{
akmhoque2f423352014-06-03 11:49:35 -0500210 _LOG_DEBUG("LinkStateRoutingTableCalculator::calculatePath Called");
akmhoque53353462014-04-22 08:43:45 -0500211 allocateAdjMatrix();
212 initMatrix();
213 makeAdjMatrix(pnlsr, pMap);
akmhoque2f423352014-06-03 11:49:35 -0500214 writeAdjMatrixLog();
akmhoque31d1d4b2014-05-05 22:08:14 -0500215 int sourceRouter = 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(); //
akmhoque157b0a42014-05-13 00:26:37 -0500218 if (pnlsr.getConfParameter().getMaxFacesPerPrefix() == 1) {
Nick G97e34942016-07-11 14:46:27 -0500219 // In the single path case we can simply run Dijkstra's algorithm.
akmhoque53353462014-04-22 08:43:45 -0500220 doDijkstraPathCalculation(sourceRouter);
Nick G97e34942016-07-11 14:46:27 -0500221 // Inform the routing table of the new next hops.
akmhoque53353462014-04-22 08:43:45 -0500222 addAllLsNextHopsToRoutingTable(pnlsr, rt, pMap, sourceRouter);
223 }
akmhoque157b0a42014-05-13 00:26:37 -0500224 else {
akmhoque53353462014-04-22 08:43:45 -0500225 // Multi Path
226 setNoLink(getNumOfLinkfromAdjMatrix(sourceRouter));
227 allocateLinks();
228 allocateLinkCosts();
Nick G97e34942016-07-11 14:46:27 -0500229 // Gets a sparse listing of adjacencies for path calculation
akmhoque53353462014-04-22 08:43:45 -0500230 getLinksFromAdjMatrix(links, linkCosts, sourceRouter);
akmhoque157b0a42014-05-13 00:26:37 -0500231 for (int i = 0 ; i < vNoLink; i++) {
Nick G97e34942016-07-11 14:46:27 -0500232 // Simulate that only the current neighbor is accessible
akmhoque53353462014-04-22 08:43:45 -0500233 adjustAdMatrix(sourceRouter, links[i], linkCosts[i]);
akmhoque2f423352014-06-03 11:49:35 -0500234 writeAdjMatrixLog();
Nick G97e34942016-07-11 14:46:27 -0500235 // Do Dijkstra's algorithm using the current neighbor as your start.
akmhoque53353462014-04-22 08:43:45 -0500236 doDijkstraPathCalculation(sourceRouter);
Nick G97e34942016-07-11 14:46:27 -0500237 // Update the routing table with the calculations.
akmhoque53353462014-04-22 08:43:45 -0500238 addAllLsNextHopsToRoutingTable(pnlsr, rt, pMap, sourceRouter);
239 }
240 freeLinks();
241 freeLinksCosts();
242 }
243 freeParent();
244 freeDistance();
245 freeAdjMatrix();
246}
247
248void
249LinkStateRoutingTableCalculator::doDijkstraPathCalculation(int sourceRouter)
250{
251 int i;
252 int v, u;
Nick G97e34942016-07-11 14:46:27 -0500253 int* Q = new int[m_nRouters]; // Each cell represents the router with that mapping no.
akmhoque53353462014-04-22 08:43:45 -0500254 int head = 0;
Nick Gordone9733ed2017-04-26 10:48:39 -0500255 // Initiate the Parent
Vince Lehman9a709032014-09-13 16:28:07 -0500256 for (i = 0 ; i < static_cast<int>(m_nRouters); i++) {
akmhoque53353462014-04-22 08:43:45 -0500257 m_parent[i] = EMPTY_PARENT;
Nick G97e34942016-07-11 14:46:27 -0500258 // Array where the ith element is the distance to the router with mapping no i.
akmhoque53353462014-04-22 08:43:45 -0500259 m_distance[i] = INF_DISTANCE;
260 Q[i] = i;
261 }
akmhoque157b0a42014-05-13 00:26:37 -0500262 if (sourceRouter != NO_MAPPING_NUM) {
Nick G97e34942016-07-11 14:46:27 -0500263 // Distance to source from source is always 0.
akmhoque53353462014-04-22 08:43:45 -0500264 m_distance[sourceRouter] = 0;
Vince Lehman9a709032014-09-13 16:28:07 -0500265 sortQueueByDistance(Q, m_distance, head, m_nRouters);
Nick G97e34942016-07-11 14:46:27 -0500266 // While we haven't visited every node.
Vince Lehman9a709032014-09-13 16:28:07 -0500267 while (head < static_cast<int>(m_nRouters)) {
Nick G97e34942016-07-11 14:46:27 -0500268 u = Q[head]; // Set u to be the current node pointed to by head.
akmhoque157b0a42014-05-13 00:26:37 -0500269 if (m_distance[u] == INF_DISTANCE) {
Nick G97e34942016-07-11 14:46:27 -0500270 break; // This can only happen when there are no accessible nodes.
akmhoque53353462014-04-22 08:43:45 -0500271 }
Nick G97e34942016-07-11 14:46:27 -0500272 // Iterate over the adjacent nodes to u.
Vince Lehman9a709032014-09-13 16:28:07 -0500273 for (v = 0 ; v < static_cast<int>(m_nRouters); v++) {
Nick G97e34942016-07-11 14:46:27 -0500274 // If the current node is accessible.
akmhoque157b0a42014-05-13 00:26:37 -0500275 if (adjMatrix[u][v] > 0) {
Nick G97e34942016-07-11 14:46:27 -0500276 // And we haven't visited it yet.
Vince Lehman9a709032014-09-13 16:28:07 -0500277 if (isNotExplored(Q, v, head + 1, m_nRouters)) {
Nick G97e34942016-07-11 14:46:27 -0500278 // And if the distance to this node + from this node to v
279 // is less than the distance from our source node to v
280 // that we got when we built the adj LSAs
akmhoque157b0a42014-05-13 00:26:37 -0500281 if (m_distance[u] + adjMatrix[u][v] < m_distance[v]) {
Nick G97e34942016-07-11 14:46:27 -0500282 // Set the new distance
akmhoque53353462014-04-22 08:43:45 -0500283 m_distance[v] = m_distance[u] + adjMatrix[u][v] ;
Nick G97e34942016-07-11 14:46:27 -0500284 // Set how we get there.
akmhoque53353462014-04-22 08:43:45 -0500285 m_parent[v] = u;
286 }
287 }
288 }
289 }
Nick G97e34942016-07-11 14:46:27 -0500290 // Increment the head position, resort the list by distance from where we are.
akmhoque53353462014-04-22 08:43:45 -0500291 head++;
Vince Lehman9a709032014-09-13 16:28:07 -0500292 sortQueueByDistance(Q, m_distance, head, m_nRouters);
akmhoque53353462014-04-22 08:43:45 -0500293 }
294 }
295 delete [] Q;
296}
297
298void
Vince Lehman9a709032014-09-13 16:28:07 -0500299LinkStateRoutingTableCalculator::addAllLsNextHopsToRoutingTable(Nlsr& pnlsr, RoutingTable& rt,
300 Map& pMap, uint32_t sourceRouter)
akmhoque53353462014-04-22 08:43:45 -0500301{
akmhoque2f423352014-06-03 11:49:35 -0500302 _LOG_DEBUG("LinkStateRoutingTableCalculator::addAllNextHopsToRoutingTable Called");
Vince Lehman9a709032014-09-13 16:28:07 -0500303
akmhoque53353462014-04-22 08:43:45 -0500304 int nextHopRouter = 0;
Vince Lehman9a709032014-09-13 16:28:07 -0500305
Nick G97e34942016-07-11 14:46:27 -0500306 // For each router we have
Vince Lehman9a709032014-09-13 16:28:07 -0500307 for (size_t i = 0; i < m_nRouters ; i++) {
akmhoque157b0a42014-05-13 00:26:37 -0500308 if (i != sourceRouter) {
Vince Lehman9a709032014-09-13 16:28:07 -0500309
Nick G97e34942016-07-11 14:46:27 -0500310 // Obtain the next hop that was determined by the algorithm
akmhoque53353462014-04-22 08:43:45 -0500311 nextHopRouter = getLsNextHop(i, sourceRouter);
Vince Lehman9a709032014-09-13 16:28:07 -0500312
Nick G97e34942016-07-11 14:46:27 -0500313 // If this router is accessible at all
akmhoque157b0a42014-05-13 00:26:37 -0500314 if (nextHopRouter != NO_NEXT_HOP) {
Vince Lehman9a709032014-09-13 16:28:07 -0500315
Nick G97e34942016-07-11 14:46:27 -0500316 // Fetch its distance
akmhoque53353462014-04-22 08:43:45 -0500317 double routeCost = m_distance[i];
Nick G97e34942016-07-11 14:46:27 -0500318 // Fetch its actual name
akmhoque31d1d4b2014-05-05 22:08:14 -0500319 ndn::Name nextHopRouterName = pMap.getRouterNameByMappingNo(nextHopRouter);
akmhoque157b0a42014-05-13 00:26:37 -0500320 std::string nextHopFace =
Nick Gordone9733ed2017-04-26 10:48:39 -0500321 pnlsr.getAdjacencyList().getAdjacent(nextHopRouterName).getFaceUri().toString();
akmhoque53353462014-04-22 08:43:45 -0500322 // Add next hop to routing table
akmhoque157b0a42014-05-13 00:26:37 -0500323 NextHop nh(nextHopFace, routeCost);
akmhoque53353462014-04-22 08:43:45 -0500324 rt.addNextHop(pMap.getRouterNameByMappingNo(i), nh);
325 }
326 }
327 }
328}
329
330int
331LinkStateRoutingTableCalculator::getLsNextHop(int dest, int source)
332{
333 int nextHop = NO_NEXT_HOP;
akmhoque157b0a42014-05-13 00:26:37 -0500334 while (m_parent[dest] != EMPTY_PARENT) {
akmhoque53353462014-04-22 08:43:45 -0500335 nextHop = dest;
336 dest = m_parent[dest];
337 }
akmhoque157b0a42014-05-13 00:26:37 -0500338 if (dest != source) {
akmhoque53353462014-04-22 08:43:45 -0500339 nextHop = NO_NEXT_HOP;
340 }
341 return nextHop;
342}
343
344void
akmhoque53353462014-04-22 08:43:45 -0500345LinkStateRoutingTableCalculator::sortQueueByDistance(int* Q,
akmhoque2f423352014-06-03 11:49:35 -0500346 double* dist,
347 int start, int element)
akmhoque53353462014-04-22 08:43:45 -0500348{
akmhoque157b0a42014-05-13 00:26:37 -0500349 for (int i = start ; i < element ; i++) {
350 for (int j = i + 1; j < element; j++) {
351 if (dist[Q[j]] < dist[Q[i]]) {
akmhoque53353462014-04-22 08:43:45 -0500352 int tempU = Q[j];
353 Q[j] = Q[i];
354 Q[i] = tempU;
355 }
356 }
357 }
358}
359
360int
361LinkStateRoutingTableCalculator::isNotExplored(int* Q,
362 int u, int start, int element)
363{
364 int ret = 0;
akmhoque157b0a42014-05-13 00:26:37 -0500365 for (int i = start; i < element; i++) {
366 if (Q[i] == u) {
akmhoque53353462014-04-22 08:43:45 -0500367 ret = 1;
368 break;
369 }
370 }
371 return ret;
372}
373
374void
375LinkStateRoutingTableCalculator::allocateParent()
376{
Vince Lehman9a709032014-09-13 16:28:07 -0500377 m_parent = new int[m_nRouters];
akmhoque53353462014-04-22 08:43:45 -0500378}
379
380void
381LinkStateRoutingTableCalculator::allocateDistance()
382{
Vince Lehman9a709032014-09-13 16:28:07 -0500383 m_distance = new double[m_nRouters];
akmhoque53353462014-04-22 08:43:45 -0500384}
385
386void
387LinkStateRoutingTableCalculator::freeParent()
388{
389 delete [] m_parent;
390}
391
392void LinkStateRoutingTableCalculator::freeDistance()
393{
394 delete [] m_distance;
395}
396
Vince Lehman9a709032014-09-13 16:28:07 -0500397const double HyperbolicRoutingCalculator::MATH_PI = boost::math::constants::pi<double>();
akmhoque53353462014-04-22 08:43:45 -0500398
Vince Lehman9a709032014-09-13 16:28:07 -0500399const double HyperbolicRoutingCalculator::UNKNOWN_DISTANCE = -1.0;
400const double HyperbolicRoutingCalculator::UNKNOWN_RADIUS = -1.0;
401
402const int32_t HyperbolicRoutingCalculator::ROUTER_NOT_FOUND = -1.0;
akmhoque53353462014-04-22 08:43:45 -0500403
404void
Vince Lehman9a709032014-09-13 16:28:07 -0500405HyperbolicRoutingCalculator::calculatePaths(Map& map, RoutingTable& rt,
406 Lsdb& lsdb, AdjacencyList& adjacencies)
akmhoque53353462014-04-22 08:43:45 -0500407{
Vince Lehman9a709032014-09-13 16:28:07 -0500408 _LOG_TRACE("Calculating hyperbolic paths");
409
410 int thisRouter = map.getMappingNoByRouterName(m_thisRouterName);
411
412 // Iterate over directly connected neighbors
413 std::list<Adjacent> neighbors = adjacencies.getAdjList();
414 for (std::list<Adjacent>::iterator adj = neighbors.begin(); adj != neighbors.end(); ++adj) {
415
416 // Don't calculate nexthops using an inactive router
417 if (adj->getStatus() == Adjacent::STATUS_INACTIVE) {
418 _LOG_TRACE(adj->getName() << " is inactive; not using it as a nexthop");
419 continue;
420 }
421
422 ndn::Name srcRouterName = adj->getName();
423
424 // Don't calculate nexthops for this router to other routers
425 if (srcRouterName == m_thisRouterName) {
426 continue;
427 }
428
Nick Gordone9733ed2017-04-26 10:48:39 -0500429 std::string srcFaceUri = adj->getFaceUri().toString();
Vince Lehman9a709032014-09-13 16:28:07 -0500430
431 // Install nexthops for this router to the neighbor; direct neighbors have a 0 cost link
432 addNextHop(srcRouterName, srcFaceUri, 0, rt);
433
434 int src = map.getMappingNoByRouterName(srcRouterName);
435
436 if (src == ROUTER_NOT_FOUND) {
437 _LOG_WARN(adj->getName() << " does not exist in the router map!");
438 continue;
439 }
440
441 // Get hyperbolic distance from direct neighbor to every other router
442 for (int dest = 0; dest < static_cast<int>(m_nRouters); ++dest) {
443 // Don't calculate nexthops to this router or from a router to itself
444 if (dest != thisRouter && dest != src) {
445
446 ndn::Name destRouterName = map.getRouterNameByMappingNo(dest);
447
448 double distance = getHyperbolicDistance(map, lsdb, srcRouterName, destRouterName);
449
450 // Could not compute distance
451 if (distance == UNKNOWN_DISTANCE) {
452 _LOG_WARN("Could not calculate hyperbolic distance from " << srcRouterName << " to " <<
453 destRouterName);
454 continue;
akmhoque53353462014-04-22 08:43:45 -0500455 }
akmhoque53353462014-04-22 08:43:45 -0500456
Vince Lehman9a709032014-09-13 16:28:07 -0500457 addNextHop(destRouterName, srcFaceUri, distance, rt);
458 }
akmhoquedcee9362014-08-05 22:58:01 -0500459 }
akmhoque53353462014-04-22 08:43:45 -0500460 }
461}
462
463double
Vince Lehman9a709032014-09-13 16:28:07 -0500464HyperbolicRoutingCalculator::getHyperbolicDistance(Map& map, Lsdb& lsdb,
465 ndn::Name src, ndn::Name dest)
akmhoque53353462014-04-22 08:43:45 -0500466{
Vince Lehman9a709032014-09-13 16:28:07 -0500467 _LOG_TRACE("Calculating hyperbolic distance from " << src << " to " << dest);
akmhoquedcee9362014-08-05 22:58:01 -0500468
Vince Lehman9a709032014-09-13 16:28:07 -0500469 double distance = UNKNOWN_DISTANCE;
470
471 ndn::Name srcLsaKey = src;
472 srcLsaKey.append("coordinate");
473
474 CoordinateLsa* srcLsa = lsdb.findCoordinateLsa(srcLsaKey);
475
476 ndn::Name destLsaKey = dest;
477 destLsaKey.append("coordinate");
478
479 CoordinateLsa* destLsa = lsdb.findCoordinateLsa(destLsaKey);
480
481 // Coordinate LSAs do not exist for these routers
Nick Gordone9733ed2017-04-26 10:48:39 -0500482 if (srcLsa == nullptr || destLsa == nullptr) {
Vince Lehman9a709032014-09-13 16:28:07 -0500483 return UNKNOWN_DISTANCE;
akmhoquedcee9362014-08-05 22:58:01 -0500484 }
485
Muktadir R Chowdhuryb00dc2a2016-11-05 10:48:58 -0600486 std::vector<double> srcTheta = srcLsa->getCorTheta();
487 std::vector<double> destTheta = destLsa->getCorTheta();
Vince Lehman9a709032014-09-13 16:28:07 -0500488
489 double srcRadius = srcLsa->getCorRadius();
490 double destRadius = destLsa->getCorRadius();
491
Muktadir R Chowdhuryb00dc2a2016-11-05 10:48:58 -0600492 double diffTheta = calculateAngularDistance(srcTheta, destTheta);
493
494 if (srcRadius == UNKNOWN_RADIUS || destRadius == UNKNOWN_RADIUS ||
495 diffTheta == UNKNOWN_DISTANCE) {
Vince Lehman9a709032014-09-13 16:28:07 -0500496 return UNKNOWN_DISTANCE;
497 }
498
Muktadir R Chowdhuryb00dc2a2016-11-05 10:48:58 -0600499 // double r_i, double r_j, double delta_theta, double zeta = 1 (default)
500 distance = calculateHyperbolicDistance(srcRadius, destRadius, diffTheta);
Vince Lehman9a709032014-09-13 16:28:07 -0500501
502 _LOG_TRACE("Distance from " << src << " to " << dest << " is " << distance);
503
akmhoque53353462014-04-22 08:43:45 -0500504 return distance;
505}
506
Muktadir R Chowdhuryb00dc2a2016-11-05 10:48:58 -0600507double
508HyperbolicRoutingCalculator::calculateAngularDistance(std::vector<double> angleVectorI,
509 std::vector<double> angleVectorJ)
510{
511 // It is not possible for angle vector size to be zero as ensured by conf-file-processor
512
513 // https://en.wikipedia.org/wiki/N-sphere#Spherical_coordinates
514
515 // Check if two vector lengths are the same
516 if (angleVectorI.size() != angleVectorJ.size()) {
517 _LOG_ERROR("Angle vector sizes do not match");
518 return UNKNOWN_DISTANCE;
519 }
520
521 // Check if all angles are within the [0, PI] and [0, 2PI] ranges
522 if (angleVectorI.size() > 1) {
523 for (unsigned int k = 0; k < angleVectorI.size() - 1; k++) {
524 if ((angleVectorI[k] > M_PI && angleVectorI[k] < 0.0) ||
525 (angleVectorJ[k] > M_PI && angleVectorJ[k] < 0.0)) {
526 _LOG_ERROR("Angle outside [0, PI]");
527 return UNKNOWN_DISTANCE;
528 }
529 }
530 }
531 if (angleVectorI[angleVectorI.size()-1] > 2.*M_PI ||
532 angleVectorI[angleVectorI.size()-1] < 0.0) {
533 _LOG_ERROR("Angle not within [0, 2PI]");
534 return UNKNOWN_DISTANCE;
535 }
536
537 if (angleVectorI[angleVectorI.size()-1] > 2.*M_PI ||
538 angleVectorI[angleVectorI.size()-1] < 0.0) {
539 _LOG_ERROR("Angle not within [0, 2PI]");
540 return UNKNOWN_DISTANCE;
541 }
542
543 // deltaTheta = arccos(vectorI . vectorJ) -> do the inner product
544 double innerProduct = 0.0;
545
546 // Calculate x0 of the vectors
547 double x0i = std::cos(angleVectorI[0]);
548 double x0j = std::cos(angleVectorJ[0]);
549
550 // Calculate xn of the vectors
551 double xni = std::sin(angleVectorI[angleVectorI.size() - 1]);
552 double xnj = std::sin(angleVectorJ[angleVectorJ.size() - 1]);
553
554 // Do the aggregation of the (n-1) coordinates (if there is more than one angle)
555 // i.e contraction of all (n-1)-dimensional angular coordinates to one variable
556 for (unsigned int k = 0; k < angleVectorI.size() - 1; k++) {
557 xni *= std::sin(angleVectorI[k]);
558 xnj *= std::sin(angleVectorJ[k]);
559 }
560 innerProduct += (x0i * x0j) + (xni * xnj);
561
562 // If d > 1
563 if (angleVectorI.size() > 1) {
564 for (unsigned int m = 1; m < angleVectorI.size(); m++) {
565 // calculate euclidean coordinates given the angles and assuming R_sphere = 1
566 double xmi = std::cos(angleVectorI[m]);
567 double xmj = std::cos(angleVectorJ[m]);
568 for (unsigned int l = 0; l < m; l++) {
569 xmi *= std::sin(angleVectorI[l]);
570 xmj *= std::sin(angleVectorJ[l]);
571 }
572 innerProduct += xmi * xmj;
573 }
574 }
575
576 // ArcCos of the inner product gives the angular distance
577 // between two points on a d-dimensional sphere
578 return std::acos(innerProduct);
579}
580
581double
582HyperbolicRoutingCalculator::calculateHyperbolicDistance(double rI, double rJ,
583 double deltaTheta)
584{
585 if (deltaTheta == UNKNOWN_DISTANCE) {
586 return UNKNOWN_DISTANCE;
587 }
588
589 // Usually, we set zeta = 1 in all experiments
590 double zeta = 1;
591
592 if (deltaTheta <= 0.0 || rI <= 0.0 || rJ <= 0.0) {
593 _LOG_ERROR("Delta theta or rI or rJ is <= 0");
594 return UNKNOWN_DISTANCE;
595 }
596
597 double xij = (1. / zeta) * std::acosh(std::cosh(zeta*rI) * std::cosh(zeta*rJ) -
598 std::sinh(zeta*rI)*std::sinh(zeta*rJ)*std::cos(deltaTheta));
599 return xij;
600}
601
602void
603HyperbolicRoutingCalculator::addNextHop(ndn::Name dest, std::string faceUri,
604 double cost, RoutingTable& rt)
akmhoque53353462014-04-22 08:43:45 -0500605{
Vince Lehman9a709032014-09-13 16:28:07 -0500606 NextHop hop(faceUri, cost);
Vince Lehman20fe4a92014-09-09 15:57:59 -0500607 hop.setHyperbolic(true);
akmhoque53353462014-04-22 08:43:45 -0500608
Vince Lehman9a709032014-09-13 16:28:07 -0500609 _LOG_TRACE("Calculated " << hop << " for destination: " << dest);
akmhoque53353462014-04-22 08:43:45 -0500610
Vince Lehman9a709032014-09-13 16:28:07 -0500611 if (m_isDryRun) {
612 rt.addNextHopToDryTable(dest, hop);
613 }
614 else {
615 rt.addNextHop(dest, hop);
616 }
akmhoque53353462014-04-22 08:43:45 -0500617}
618
Nick Gordonfad8e252016-08-11 14:21:38 -0500619} // namespace nlsr