blob: f4442f585495c02768eae0405e4df6aa4b042559 [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 **/
akmhoque53353462014-04-22 08:43:45 -050021#include "routing-table-calculator.hpp"
Nick Gordone98480b2017-05-24 11:23:03 -050022#include "lsdb.hpp"
akmhoque53353462014-04-22 08:43:45 -050023#include "map.hpp"
24#include "lsa.hpp"
25#include "nexthop.hpp"
26#include "nlsr.hpp"
akmhoque2f423352014-06-03 11:49:35 -050027#include "logger.hpp"
akmhoque53353462014-04-22 08:43:45 -050028
Nick Gordone98480b2017-05-24 11:23:03 -050029#include <iostream>
Vince Lehman9a709032014-09-13 16:28:07 -050030#include <boost/math/constants/constants.hpp>
Nick Gordone98480b2017-05-24 11:23:03 -050031#include <cmath>
Vince Lehman9a709032014-09-13 16:28:07 -050032
akmhoque53353462014-04-22 08:43:45 -050033namespace nlsr {
34
akmhoque2f423352014-06-03 11:49:35 -050035INIT_LOGGER("RoutingTableCalculator");
akmhoque53353462014-04-22 08:43:45 -050036
37void
38RoutingTableCalculator::allocateAdjMatrix()
39{
Vince Lehman9a709032014-09-13 16:28:07 -050040 adjMatrix = new double*[m_nRouters];
41
42 for (size_t i = 0; i < m_nRouters; ++i) {
43 adjMatrix[i] = new double[m_nRouters];
akmhoque53353462014-04-22 08:43:45 -050044 }
45}
46
47void
48RoutingTableCalculator::initMatrix()
49{
Vince Lehman9a709032014-09-13 16:28:07 -050050 for (size_t i = 0; i < m_nRouters; i++) {
51 for (size_t j = 0; j < m_nRouters; j++) {
akmhoque53353462014-04-22 08:43:45 -050052 adjMatrix[i][j] = 0;
akmhoque157b0a42014-05-13 00:26:37 -050053 }
akmhoque53353462014-04-22 08:43:45 -050054 }
55}
56
57void
58RoutingTableCalculator::makeAdjMatrix(Nlsr& pnlsr, Map pMap)
59{
60 std::list<AdjLsa> adjLsdb = pnlsr.getLsdb().getAdjLsdb();
Nick G97e34942016-07-11 14:46:27 -050061 // For each LSA represented in the map
Vince Lehman9a709032014-09-13 16:28:07 -050062 for (std::list<AdjLsa>::iterator it = adjLsdb.begin(); it != adjLsdb.end() ; it++) {
63
Nick G97e34942016-07-11 14:46:27 -050064
Vince Lehman9a709032014-09-13 16:28:07 -050065 int32_t row = pMap.getMappingNoByRouterName((*it).getOrigRouter());
66
akmhoque53353462014-04-22 08:43:45 -050067 std::list<Adjacent> adl = (*it).getAdl().getAdjList();
Nick G97e34942016-07-11 14:46:27 -050068 // For each adjacency represented in the LSA
Vince Lehman9a709032014-09-13 16:28:07 -050069 for (std::list<Adjacent>::iterator itAdl = adl.begin(); itAdl != adl.end() ; itAdl++) {
70
71 int32_t col = pMap.getMappingNoByRouterName((*itAdl).getName());
akmhoque53353462014-04-22 08:43:45 -050072 double cost = (*itAdl).getLinkCost();
Vince Lehman9a709032014-09-13 16:28:07 -050073
74 if ((row >= 0 && row < static_cast<int32_t>(m_nRouters)) &&
75 (col >= 0 && col < static_cast<int32_t>(m_nRouters)))
76 {
akmhoque53353462014-04-22 08:43:45 -050077 adjMatrix[row][col] = cost;
78 }
79 }
80 }
Vince Lehman41b173e2015-05-07 14:13:26 -050081
Nick G97e34942016-07-11 14:46:27 -050082 // Links that do not have the same cost for both directions should
83 // have their costs corrected:
Vince Lehman41b173e2015-05-07 14:13:26 -050084 //
Nick G97e34942016-07-11 14:46:27 -050085 // If the cost of one side of the link is 0, both sides of the
86 // link should have their cost corrected to 0.
Vince Lehman41b173e2015-05-07 14:13:26 -050087 //
88 // Otherwise, both sides of the link should use the larger of the two costs.
89 //
Nick G97e34942016-07-11 14:46:27 -050090 // Additionally, this means that we can halve the amount of space
91 // that the matrix uses by only maintaining a triangle.
92 // - But that is not yet implemented.
Vince Lehman41b173e2015-05-07 14:13:26 -050093 for (size_t row = 0; row < m_nRouters; ++row) {
94 for (size_t col = 0; col < m_nRouters; ++col) {
95 double toCost = adjMatrix[row][col];
96 double fromCost = adjMatrix[col][row];
97
98 if (fromCost != toCost) {
99 double correctedCost = 0.0;
100
101 if (toCost != 0 && fromCost != 0) {
102 // If both sides of the link are up, use the larger cost
103 correctedCost = std::max(toCost, fromCost);
104 }
105
106 _LOG_WARN("Cost between [" << row << "][" << col << "] and [" << col << "][" << row <<
107 "] are not the same (" << toCost << " != " << fromCost << "). " <<
108 "Correcting to cost: " << correctedCost);
109
110 adjMatrix[row][col] = correctedCost;
111 adjMatrix[col][row] = correctedCost;
112 }
113 }
114 }
akmhoque53353462014-04-22 08:43:45 -0500115}
116
117void
akmhoque2f423352014-06-03 11:49:35 -0500118RoutingTableCalculator::writeAdjMatrixLog()
akmhoque53353462014-04-22 08:43:45 -0500119{
Vince Lehman9a709032014-09-13 16:28:07 -0500120 for (size_t i = 0; i < m_nRouters; i++) {
Nick Gordone98480b2017-05-24 11:23:03 -0500121 std::string line="";
Vince Lehman9a709032014-09-13 16:28:07 -0500122 for (size_t j = 0; j < m_nRouters; j++) {
akmhoque2f423352014-06-03 11:49:35 -0500123 line += boost::lexical_cast<std::string>(adjMatrix[i][j]);
124 line += " ";
akmhoque157b0a42014-05-13 00:26:37 -0500125 }
akmhoque2f423352014-06-03 11:49:35 -0500126 _LOG_DEBUG(line);
akmhoque53353462014-04-22 08:43:45 -0500127 }
128}
129
130void
131RoutingTableCalculator::adjustAdMatrix(int source, int link, double linkCost)
132{
Vince Lehman9a709032014-09-13 16:28:07 -0500133 for (int i = 0; i < static_cast<int>(m_nRouters); i++) {
akmhoque157b0a42014-05-13 00:26:37 -0500134 if (i == link) {
akmhoque53353462014-04-22 08:43:45 -0500135 adjMatrix[source][i] = linkCost;
136 }
akmhoque157b0a42014-05-13 00:26:37 -0500137 else {
akmhoque53353462014-04-22 08:43:45 -0500138 adjMatrix[source][i] = 0;
139 }
140 }
141}
142
143int
144RoutingTableCalculator::getNumOfLinkfromAdjMatrix(int sRouter)
145{
146 int noLink = 0;
Vince Lehman9a709032014-09-13 16:28:07 -0500147
148 for (size_t i = 0; i < m_nRouters; i++) {
akmhoque157b0a42014-05-13 00:26:37 -0500149 if (adjMatrix[sRouter][i] > 0) {
akmhoque53353462014-04-22 08:43:45 -0500150 noLink++;
151 }
152 }
153 return noLink;
154}
155
156void
157RoutingTableCalculator::getLinksFromAdjMatrix(int* links,
158 double* linkCosts, int source)
159{
160 int j = 0;
Vince Lehman9a709032014-09-13 16:28:07 -0500161
162 for (size_t i = 0; i < m_nRouters; i++) {
akmhoque157b0a42014-05-13 00:26:37 -0500163 if (adjMatrix[source][i] > 0) {
akmhoque53353462014-04-22 08:43:45 -0500164 links[j] = i;
165 linkCosts[j] = adjMatrix[source][i];
166 j++;
167 }
168 }
169}
170
171void
172RoutingTableCalculator::freeAdjMatrix()
173{
Vince Lehman9a709032014-09-13 16:28:07 -0500174 for (size_t i = 0; i < m_nRouters; ++i) {
akmhoque53353462014-04-22 08:43:45 -0500175 delete [] adjMatrix[i];
176 }
177 delete [] adjMatrix;
178}
179
akmhoque53353462014-04-22 08:43:45 -0500180void
181RoutingTableCalculator::allocateLinks()
182{
183 links = new int[vNoLink];
184}
185
186void
187RoutingTableCalculator::allocateLinkCosts()
188{
189 linkCosts = new double[vNoLink];
190}
191
192
193void
194RoutingTableCalculator::freeLinks()
195{
196 delete [] links;
197}
198void
199RoutingTableCalculator::freeLinksCosts()
200{
201 delete [] linkCosts;
202}
203
204void
205LinkStateRoutingTableCalculator::calculatePath(Map& pMap,
206 RoutingTable& rt, Nlsr& pnlsr)
207{
akmhoque2f423352014-06-03 11:49:35 -0500208 _LOG_DEBUG("LinkStateRoutingTableCalculator::calculatePath Called");
akmhoque53353462014-04-22 08:43:45 -0500209 allocateAdjMatrix();
210 initMatrix();
211 makeAdjMatrix(pnlsr, pMap);
akmhoque2f423352014-06-03 11:49:35 -0500212 writeAdjMatrixLog();
akmhoque31d1d4b2014-05-05 22:08:14 -0500213 int sourceRouter = pMap.getMappingNoByRouterName(pnlsr.getConfParameter().getRouterPrefix());
Nick G97e34942016-07-11 14:46:27 -0500214 allocateParent(); // These two matrices are used in Dijkstra's algorithm.
215 allocateDistance(); //
akmhoque157b0a42014-05-13 00:26:37 -0500216 if (pnlsr.getConfParameter().getMaxFacesPerPrefix() == 1) {
Nick G97e34942016-07-11 14:46:27 -0500217 // In the single path case we can simply run Dijkstra's algorithm.
akmhoque53353462014-04-22 08:43:45 -0500218 doDijkstraPathCalculation(sourceRouter);
Nick G97e34942016-07-11 14:46:27 -0500219 // Inform the routing table of the new next hops.
akmhoque53353462014-04-22 08:43:45 -0500220 addAllLsNextHopsToRoutingTable(pnlsr, rt, pMap, sourceRouter);
221 }
akmhoque157b0a42014-05-13 00:26:37 -0500222 else {
akmhoque53353462014-04-22 08:43:45 -0500223 // Multi Path
224 setNoLink(getNumOfLinkfromAdjMatrix(sourceRouter));
225 allocateLinks();
226 allocateLinkCosts();
Nick G97e34942016-07-11 14:46:27 -0500227 // Gets a sparse listing of adjacencies for path calculation
akmhoque53353462014-04-22 08:43:45 -0500228 getLinksFromAdjMatrix(links, linkCosts, sourceRouter);
akmhoque157b0a42014-05-13 00:26:37 -0500229 for (int i = 0 ; i < vNoLink; i++) {
Nick G97e34942016-07-11 14:46:27 -0500230 // Simulate that only the current neighbor is accessible
akmhoque53353462014-04-22 08:43:45 -0500231 adjustAdMatrix(sourceRouter, links[i], linkCosts[i]);
akmhoque2f423352014-06-03 11:49:35 -0500232 writeAdjMatrixLog();
Nick G97e34942016-07-11 14:46:27 -0500233 // Do Dijkstra's algorithm using the current neighbor as your start.
akmhoque53353462014-04-22 08:43:45 -0500234 doDijkstraPathCalculation(sourceRouter);
Nick G97e34942016-07-11 14:46:27 -0500235 // Update the routing table with the calculations.
akmhoque53353462014-04-22 08:43:45 -0500236 addAllLsNextHopsToRoutingTable(pnlsr, rt, pMap, sourceRouter);
237 }
238 freeLinks();
239 freeLinksCosts();
240 }
241 freeParent();
242 freeDistance();
243 freeAdjMatrix();
244}
245
246void
247LinkStateRoutingTableCalculator::doDijkstraPathCalculation(int sourceRouter)
248{
249 int i;
250 int v, u;
Nick G97e34942016-07-11 14:46:27 -0500251 int* Q = new int[m_nRouters]; // Each cell represents the router with that mapping no.
akmhoque53353462014-04-22 08:43:45 -0500252 int head = 0;
Nick Gordone98480b2017-05-24 11:23:03 -0500253 // Initiate the parent
Vince Lehman9a709032014-09-13 16:28:07 -0500254 for (i = 0 ; i < static_cast<int>(m_nRouters); i++) {
akmhoque53353462014-04-22 08:43:45 -0500255 m_parent[i] = EMPTY_PARENT;
Nick G97e34942016-07-11 14:46:27 -0500256 // Array where the ith element is the distance to the router with mapping no i.
akmhoque53353462014-04-22 08:43:45 -0500257 m_distance[i] = INF_DISTANCE;
258 Q[i] = i;
259 }
akmhoque157b0a42014-05-13 00:26:37 -0500260 if (sourceRouter != NO_MAPPING_NUM) {
Nick G97e34942016-07-11 14:46:27 -0500261 // Distance to source from source is always 0.
akmhoque53353462014-04-22 08:43:45 -0500262 m_distance[sourceRouter] = 0;
Vince Lehman9a709032014-09-13 16:28:07 -0500263 sortQueueByDistance(Q, m_distance, head, m_nRouters);
Nick G97e34942016-07-11 14:46:27 -0500264 // While we haven't visited every node.
Vince Lehman9a709032014-09-13 16:28:07 -0500265 while (head < static_cast<int>(m_nRouters)) {
Nick G97e34942016-07-11 14:46:27 -0500266 u = Q[head]; // Set u to be the current node pointed to by head.
akmhoque157b0a42014-05-13 00:26:37 -0500267 if (m_distance[u] == INF_DISTANCE) {
Nick G97e34942016-07-11 14:46:27 -0500268 break; // This can only happen when there are no accessible nodes.
akmhoque53353462014-04-22 08:43:45 -0500269 }
Nick G97e34942016-07-11 14:46:27 -0500270 // Iterate over the adjacent nodes to u.
Vince Lehman9a709032014-09-13 16:28:07 -0500271 for (v = 0 ; v < static_cast<int>(m_nRouters); v++) {
Nick G97e34942016-07-11 14:46:27 -0500272 // If the current node is accessible.
akmhoque157b0a42014-05-13 00:26:37 -0500273 if (adjMatrix[u][v] > 0) {
Nick G97e34942016-07-11 14:46:27 -0500274 // And we haven't visited it yet.
Vince Lehman9a709032014-09-13 16:28:07 -0500275 if (isNotExplored(Q, v, head + 1, m_nRouters)) {
Nick G97e34942016-07-11 14:46:27 -0500276 // And if the distance to this node + from this node to v
277 // is less than the distance from our source node to v
278 // that we got when we built the adj LSAs
akmhoque157b0a42014-05-13 00:26:37 -0500279 if (m_distance[u] + adjMatrix[u][v] < m_distance[v]) {
Nick G97e34942016-07-11 14:46:27 -0500280 // Set the new distance
akmhoque53353462014-04-22 08:43:45 -0500281 m_distance[v] = m_distance[u] + adjMatrix[u][v] ;
Nick G97e34942016-07-11 14:46:27 -0500282 // Set how we get there.
akmhoque53353462014-04-22 08:43:45 -0500283 m_parent[v] = u;
284 }
285 }
286 }
287 }
Nick G97e34942016-07-11 14:46:27 -0500288 // Increment the head position, resort the list by distance from where we are.
akmhoque53353462014-04-22 08:43:45 -0500289 head++;
Vince Lehman9a709032014-09-13 16:28:07 -0500290 sortQueueByDistance(Q, m_distance, head, m_nRouters);
akmhoque53353462014-04-22 08:43:45 -0500291 }
292 }
293 delete [] Q;
294}
295
296void
Vince Lehman9a709032014-09-13 16:28:07 -0500297LinkStateRoutingTableCalculator::addAllLsNextHopsToRoutingTable(Nlsr& pnlsr, RoutingTable& rt,
298 Map& pMap, uint32_t sourceRouter)
akmhoque53353462014-04-22 08:43:45 -0500299{
akmhoque2f423352014-06-03 11:49:35 -0500300 _LOG_DEBUG("LinkStateRoutingTableCalculator::addAllNextHopsToRoutingTable Called");
Vince Lehman9a709032014-09-13 16:28:07 -0500301
akmhoque53353462014-04-22 08:43:45 -0500302 int nextHopRouter = 0;
Vince Lehman9a709032014-09-13 16:28:07 -0500303
Nick G97e34942016-07-11 14:46:27 -0500304 // For each router we have
Vince Lehman9a709032014-09-13 16:28:07 -0500305 for (size_t i = 0; i < m_nRouters ; i++) {
akmhoque157b0a42014-05-13 00:26:37 -0500306 if (i != sourceRouter) {
Vince Lehman9a709032014-09-13 16:28:07 -0500307
Nick G97e34942016-07-11 14:46:27 -0500308 // Obtain the next hop that was determined by the algorithm
akmhoque53353462014-04-22 08:43:45 -0500309 nextHopRouter = getLsNextHop(i, sourceRouter);
Vince Lehman9a709032014-09-13 16:28:07 -0500310
Nick G97e34942016-07-11 14:46:27 -0500311 // If this router is accessible at all
akmhoque157b0a42014-05-13 00:26:37 -0500312 if (nextHopRouter != NO_NEXT_HOP) {
Vince Lehman9a709032014-09-13 16:28:07 -0500313
Nick G97e34942016-07-11 14:46:27 -0500314 // Fetch its distance
akmhoque53353462014-04-22 08:43:45 -0500315 double routeCost = m_distance[i];
Nick G97e34942016-07-11 14:46:27 -0500316 // Fetch its actual name
akmhoque31d1d4b2014-05-05 22:08:14 -0500317 ndn::Name nextHopRouterName = pMap.getRouterNameByMappingNo(nextHopRouter);
akmhoque157b0a42014-05-13 00:26:37 -0500318 std::string nextHopFace =
Nick Gordone9733ed2017-04-26 10:48:39 -0500319 pnlsr.getAdjacencyList().getAdjacent(nextHopRouterName).getFaceUri().toString();
akmhoque53353462014-04-22 08:43:45 -0500320 // Add next hop to routing table
akmhoque157b0a42014-05-13 00:26:37 -0500321 NextHop nh(nextHopFace, routeCost);
akmhoque53353462014-04-22 08:43:45 -0500322 rt.addNextHop(pMap.getRouterNameByMappingNo(i), nh);
323 }
324 }
325 }
326}
327
328int
329LinkStateRoutingTableCalculator::getLsNextHop(int dest, int source)
330{
331 int nextHop = NO_NEXT_HOP;
akmhoque157b0a42014-05-13 00:26:37 -0500332 while (m_parent[dest] != EMPTY_PARENT) {
akmhoque53353462014-04-22 08:43:45 -0500333 nextHop = dest;
334 dest = m_parent[dest];
335 }
akmhoque157b0a42014-05-13 00:26:37 -0500336 if (dest != source) {
akmhoque53353462014-04-22 08:43:45 -0500337 nextHop = NO_NEXT_HOP;
338 }
339 return nextHop;
340}
341
342void
akmhoque53353462014-04-22 08:43:45 -0500343LinkStateRoutingTableCalculator::sortQueueByDistance(int* Q,
akmhoque2f423352014-06-03 11:49:35 -0500344 double* dist,
345 int start, int element)
akmhoque53353462014-04-22 08:43:45 -0500346{
akmhoque157b0a42014-05-13 00:26:37 -0500347 for (int i = start ; i < element ; i++) {
348 for (int j = i + 1; j < element; j++) {
349 if (dist[Q[j]] < dist[Q[i]]) {
akmhoque53353462014-04-22 08:43:45 -0500350 int tempU = Q[j];
351 Q[j] = Q[i];
352 Q[i] = tempU;
353 }
354 }
355 }
356}
357
358int
359LinkStateRoutingTableCalculator::isNotExplored(int* Q,
360 int u, int start, int element)
361{
362 int ret = 0;
akmhoque157b0a42014-05-13 00:26:37 -0500363 for (int i = start; i < element; i++) {
364 if (Q[i] == u) {
akmhoque53353462014-04-22 08:43:45 -0500365 ret = 1;
366 break;
367 }
368 }
369 return ret;
370}
371
372void
373LinkStateRoutingTableCalculator::allocateParent()
374{
Vince Lehman9a709032014-09-13 16:28:07 -0500375 m_parent = new int[m_nRouters];
akmhoque53353462014-04-22 08:43:45 -0500376}
377
378void
379LinkStateRoutingTableCalculator::allocateDistance()
380{
Vince Lehman9a709032014-09-13 16:28:07 -0500381 m_distance = new double[m_nRouters];
akmhoque53353462014-04-22 08:43:45 -0500382}
383
384void
385LinkStateRoutingTableCalculator::freeParent()
386{
387 delete [] m_parent;
388}
389
390void LinkStateRoutingTableCalculator::freeDistance()
391{
392 delete [] m_distance;
393}
394
Vince Lehman9a709032014-09-13 16:28:07 -0500395const double HyperbolicRoutingCalculator::MATH_PI = boost::math::constants::pi<double>();
akmhoque53353462014-04-22 08:43:45 -0500396
Vince Lehman9a709032014-09-13 16:28:07 -0500397const double HyperbolicRoutingCalculator::UNKNOWN_DISTANCE = -1.0;
398const double HyperbolicRoutingCalculator::UNKNOWN_RADIUS = -1.0;
399
400const int32_t HyperbolicRoutingCalculator::ROUTER_NOT_FOUND = -1.0;
akmhoque53353462014-04-22 08:43:45 -0500401
402void
Vince Lehman9a709032014-09-13 16:28:07 -0500403HyperbolicRoutingCalculator::calculatePaths(Map& map, RoutingTable& rt,
404 Lsdb& lsdb, AdjacencyList& adjacencies)
akmhoque53353462014-04-22 08:43:45 -0500405{
Vince Lehman9a709032014-09-13 16:28:07 -0500406 _LOG_TRACE("Calculating hyperbolic paths");
407
408 int thisRouter = map.getMappingNoByRouterName(m_thisRouterName);
409
410 // Iterate over directly connected neighbors
411 std::list<Adjacent> neighbors = adjacencies.getAdjList();
412 for (std::list<Adjacent>::iterator adj = neighbors.begin(); adj != neighbors.end(); ++adj) {
413
414 // Don't calculate nexthops using an inactive router
415 if (adj->getStatus() == Adjacent::STATUS_INACTIVE) {
416 _LOG_TRACE(adj->getName() << " is inactive; not using it as a nexthop");
417 continue;
418 }
419
420 ndn::Name srcRouterName = adj->getName();
421
422 // Don't calculate nexthops for this router to other routers
423 if (srcRouterName == m_thisRouterName) {
424 continue;
425 }
426
Nick Gordone9733ed2017-04-26 10:48:39 -0500427 std::string srcFaceUri = adj->getFaceUri().toString();
Vince Lehman9a709032014-09-13 16:28:07 -0500428
429 // Install nexthops for this router to the neighbor; direct neighbors have a 0 cost link
430 addNextHop(srcRouterName, srcFaceUri, 0, rt);
431
432 int src = map.getMappingNoByRouterName(srcRouterName);
433
434 if (src == ROUTER_NOT_FOUND) {
435 _LOG_WARN(adj->getName() << " does not exist in the router map!");
436 continue;
437 }
438
439 // Get hyperbolic distance from direct neighbor to every other router
440 for (int dest = 0; dest < static_cast<int>(m_nRouters); ++dest) {
441 // Don't calculate nexthops to this router or from a router to itself
442 if (dest != thisRouter && dest != src) {
443
444 ndn::Name destRouterName = map.getRouterNameByMappingNo(dest);
445
446 double distance = getHyperbolicDistance(map, lsdb, srcRouterName, destRouterName);
447
448 // Could not compute distance
449 if (distance == UNKNOWN_DISTANCE) {
450 _LOG_WARN("Could not calculate hyperbolic distance from " << srcRouterName << " to " <<
451 destRouterName);
452 continue;
akmhoque53353462014-04-22 08:43:45 -0500453 }
akmhoque53353462014-04-22 08:43:45 -0500454
Vince Lehman9a709032014-09-13 16:28:07 -0500455 addNextHop(destRouterName, srcFaceUri, distance, rt);
456 }
akmhoquedcee9362014-08-05 22:58:01 -0500457 }
akmhoque53353462014-04-22 08:43:45 -0500458 }
459}
460
461double
Vince Lehman9a709032014-09-13 16:28:07 -0500462HyperbolicRoutingCalculator::getHyperbolicDistance(Map& map, Lsdb& lsdb,
463 ndn::Name src, ndn::Name dest)
akmhoque53353462014-04-22 08:43:45 -0500464{
Vince Lehman9a709032014-09-13 16:28:07 -0500465 _LOG_TRACE("Calculating hyperbolic distance from " << src << " to " << dest);
akmhoquedcee9362014-08-05 22:58:01 -0500466
Vince Lehman9a709032014-09-13 16:28:07 -0500467 double distance = UNKNOWN_DISTANCE;
468
469 ndn::Name srcLsaKey = src;
470 srcLsaKey.append("coordinate");
471
472 CoordinateLsa* srcLsa = lsdb.findCoordinateLsa(srcLsaKey);
473
474 ndn::Name destLsaKey = dest;
475 destLsaKey.append("coordinate");
476
477 CoordinateLsa* destLsa = lsdb.findCoordinateLsa(destLsaKey);
478
479 // Coordinate LSAs do not exist for these routers
Nick Gordone9733ed2017-04-26 10:48:39 -0500480 if (srcLsa == nullptr || destLsa == nullptr) {
Vince Lehman9a709032014-09-13 16:28:07 -0500481 return UNKNOWN_DISTANCE;
akmhoquedcee9362014-08-05 22:58:01 -0500482 }
483
Muktadir R Chowdhuryb00dc2a2016-11-05 10:48:58 -0600484 std::vector<double> srcTheta = srcLsa->getCorTheta();
485 std::vector<double> destTheta = destLsa->getCorTheta();
Vince Lehman9a709032014-09-13 16:28:07 -0500486
487 double srcRadius = srcLsa->getCorRadius();
488 double destRadius = destLsa->getCorRadius();
489
Muktadir R Chowdhuryb00dc2a2016-11-05 10:48:58 -0600490 double diffTheta = calculateAngularDistance(srcTheta, destTheta);
491
492 if (srcRadius == UNKNOWN_RADIUS || destRadius == UNKNOWN_RADIUS ||
493 diffTheta == UNKNOWN_DISTANCE) {
Vince Lehman9a709032014-09-13 16:28:07 -0500494 return UNKNOWN_DISTANCE;
495 }
496
Muktadir R Chowdhuryb00dc2a2016-11-05 10:48:58 -0600497 // double r_i, double r_j, double delta_theta, double zeta = 1 (default)
498 distance = calculateHyperbolicDistance(srcRadius, destRadius, diffTheta);
Vince Lehman9a709032014-09-13 16:28:07 -0500499
500 _LOG_TRACE("Distance from " << src << " to " << dest << " is " << distance);
501
akmhoque53353462014-04-22 08:43:45 -0500502 return distance;
503}
504
Muktadir R Chowdhuryb00dc2a2016-11-05 10:48:58 -0600505double
506HyperbolicRoutingCalculator::calculateAngularDistance(std::vector<double> angleVectorI,
507 std::vector<double> angleVectorJ)
508{
509 // It is not possible for angle vector size to be zero as ensured by conf-file-processor
510
511 // https://en.wikipedia.org/wiki/N-sphere#Spherical_coordinates
512
513 // Check if two vector lengths are the same
514 if (angleVectorI.size() != angleVectorJ.size()) {
515 _LOG_ERROR("Angle vector sizes do not match");
516 return UNKNOWN_DISTANCE;
517 }
518
519 // Check if all angles are within the [0, PI] and [0, 2PI] ranges
520 if (angleVectorI.size() > 1) {
521 for (unsigned int k = 0; k < angleVectorI.size() - 1; k++) {
522 if ((angleVectorI[k] > M_PI && angleVectorI[k] < 0.0) ||
523 (angleVectorJ[k] > M_PI && angleVectorJ[k] < 0.0)) {
524 _LOG_ERROR("Angle outside [0, PI]");
525 return UNKNOWN_DISTANCE;
526 }
527 }
528 }
529 if (angleVectorI[angleVectorI.size()-1] > 2.*M_PI ||
530 angleVectorI[angleVectorI.size()-1] < 0.0) {
531 _LOG_ERROR("Angle not within [0, 2PI]");
532 return UNKNOWN_DISTANCE;
533 }
534
535 if (angleVectorI[angleVectorI.size()-1] > 2.*M_PI ||
536 angleVectorI[angleVectorI.size()-1] < 0.0) {
537 _LOG_ERROR("Angle not within [0, 2PI]");
538 return UNKNOWN_DISTANCE;
539 }
540
541 // deltaTheta = arccos(vectorI . vectorJ) -> do the inner product
542 double innerProduct = 0.0;
543
544 // Calculate x0 of the vectors
545 double x0i = std::cos(angleVectorI[0]);
546 double x0j = std::cos(angleVectorJ[0]);
547
548 // Calculate xn of the vectors
549 double xni = std::sin(angleVectorI[angleVectorI.size() - 1]);
550 double xnj = std::sin(angleVectorJ[angleVectorJ.size() - 1]);
551
552 // Do the aggregation of the (n-1) coordinates (if there is more than one angle)
553 // i.e contraction of all (n-1)-dimensional angular coordinates to one variable
554 for (unsigned int k = 0; k < angleVectorI.size() - 1; k++) {
555 xni *= std::sin(angleVectorI[k]);
556 xnj *= std::sin(angleVectorJ[k]);
557 }
558 innerProduct += (x0i * x0j) + (xni * xnj);
559
560 // If d > 1
561 if (angleVectorI.size() > 1) {
562 for (unsigned int m = 1; m < angleVectorI.size(); m++) {
563 // calculate euclidean coordinates given the angles and assuming R_sphere = 1
564 double xmi = std::cos(angleVectorI[m]);
565 double xmj = std::cos(angleVectorJ[m]);
566 for (unsigned int l = 0; l < m; l++) {
567 xmi *= std::sin(angleVectorI[l]);
568 xmj *= std::sin(angleVectorJ[l]);
569 }
570 innerProduct += xmi * xmj;
571 }
572 }
573
574 // ArcCos of the inner product gives the angular distance
575 // between two points on a d-dimensional sphere
576 return std::acos(innerProduct);
577}
578
579double
580HyperbolicRoutingCalculator::calculateHyperbolicDistance(double rI, double rJ,
581 double deltaTheta)
582{
583 if (deltaTheta == UNKNOWN_DISTANCE) {
584 return UNKNOWN_DISTANCE;
585 }
586
587 // Usually, we set zeta = 1 in all experiments
588 double zeta = 1;
589
590 if (deltaTheta <= 0.0 || rI <= 0.0 || rJ <= 0.0) {
591 _LOG_ERROR("Delta theta or rI or rJ is <= 0");
592 return UNKNOWN_DISTANCE;
593 }
594
595 double xij = (1. / zeta) * std::acosh(std::cosh(zeta*rI) * std::cosh(zeta*rJ) -
596 std::sinh(zeta*rI)*std::sinh(zeta*rJ)*std::cos(deltaTheta));
597 return xij;
598}
599
600void
601HyperbolicRoutingCalculator::addNextHop(ndn::Name dest, std::string faceUri,
602 double cost, RoutingTable& rt)
akmhoque53353462014-04-22 08:43:45 -0500603{
Vince Lehman9a709032014-09-13 16:28:07 -0500604 NextHop hop(faceUri, cost);
Vince Lehman20fe4a92014-09-09 15:57:59 -0500605 hop.setHyperbolic(true);
akmhoque53353462014-04-22 08:43:45 -0500606
Vince Lehman9a709032014-09-13 16:28:07 -0500607 _LOG_TRACE("Calculated " << hop << " for destination: " << dest);
akmhoque53353462014-04-22 08:43:45 -0500608
Vince Lehman9a709032014-09-13 16:28:07 -0500609 if (m_isDryRun) {
610 rt.addNextHopToDryTable(dest, hop);
611 }
612 else {
613 rt.addNextHop(dest, hop);
614 }
akmhoque53353462014-04-22 08:43:45 -0500615}
616
Nick Gordonfad8e252016-08-11 14:21:38 -0500617} // namespace nlsr