routing-table-calculator.cpp
Go to the documentation of this file.
1 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
23 #include "lsdb.hpp"
24 #include "map.hpp"
25 #include "nexthop.hpp"
26 #include "nlsr.hpp"
27 #include "logger.hpp"
28 
29 #include <iostream>
30 #include <boost/math/constants/constants.hpp>
31 #include <ndn-cxx/util/logger.hpp>
32 #include <cmath>
33 
34 namespace nlsr {
35 
36 INIT_LOGGER(route.RoutingTableCalculator);
37 
38 void
40 {
41  adjMatrix = new double*[m_nRouters];
42 
43  for (size_t i = 0; i < m_nRouters; ++i) {
44  adjMatrix[i] = new double[m_nRouters];
45  }
46 }
47 
48 void
50 {
51  for (size_t i = 0; i < m_nRouters; i++) {
52  for (size_t j = 0; j < m_nRouters; j++) {
53  adjMatrix[i][j] = 0;
54  }
55  }
56 }
57 
58 void
59 RoutingTableCalculator::makeAdjMatrix(const std::list<AdjLsa>& adjLsaList, Map& pMap)
60 {
61  // For each LSA represented in the map
62  for (const auto& adjLsa : adjLsaList) {
63  ndn::optional<int32_t> row = pMap.getMappingNoByRouterName(adjLsa.getOrigRouter());
64 
65  std::list<Adjacent> adl = adjLsa.getAdl().getAdjList();
66  // For each adjacency represented in the LSA
67  for (const auto& adjacent : adl) {
68  ndn::optional<int32_t> col = pMap.getMappingNoByRouterName(adjacent.getName());
69  double cost = adjacent.getLinkCost();
70 
71  if (row && col && *row < static_cast<int32_t>(m_nRouters)
72  && *col < static_cast<int32_t>(m_nRouters))
73  {
74  adjMatrix[*row][*col] = cost;
75  }
76  }
77  }
78 
79  // Links that do not have the same cost for both directions should
80  // have their costs corrected:
81  //
82  // If the cost of one side of the link is 0, both sides of the
83  // link should have their cost corrected to 0.
84  //
85  // Otherwise, both sides of the link should use the larger of the two costs.
86  //
87  // Additionally, this means that we can halve the amount of space
88  // that the matrix uses by only maintaining a triangle.
89  // - But that is not yet implemented.
90  for (size_t row = 0; row < m_nRouters; ++row) {
91  for (size_t col = 0; col < m_nRouters; ++col) {
92  double toCost = adjMatrix[row][col];
93  double fromCost = adjMatrix[col][row];
94 
95  if (fromCost != toCost) {
96  double correctedCost = 0.0;
97 
98  if (toCost != 0 && fromCost != 0) {
99  // If both sides of the link are up, use the larger cost
100  correctedCost = std::max(toCost, fromCost);
101  }
102 
103  NLSR_LOG_WARN("Cost between [" << row << "][" << col << "] and [" << col << "][" << row <<
104  "] are not the same (" << toCost << " != " << fromCost << "). " <<
105  "Correcting to cost: " << correctedCost);
106 
107  adjMatrix[row][col] = correctedCost;
108  adjMatrix[col][row] = correctedCost;
109  }
110  }
111  }
112 }
113 
114 void
116 {
117  if (!ndn_cxx_getLogger().isLevelEnabled(ndn::util::LogLevel::DEBUG)) {
118  return;
119  }
120 
121  NLSR_LOG_DEBUG("-----------Legend (routerName -> index)------");
122  std::string routerIndex;
123  std::string indexToNameMapping;
124  std::string lengthOfDash = "--";
125 
126  for (size_t i = 0; i < m_nRouters; i++) {
127  routerIndex += boost::lexical_cast<std::string>(i);
128  routerIndex += " ";
129  lengthOfDash += "--";
130  NLSR_LOG_DEBUG("Router:" + map.getRouterNameByMappingNo(i)->toUri() +
131  " Index:" + boost::lexical_cast<std::string>(i));
132  }
133  NLSR_LOG_DEBUG(" |" + routerIndex);
134  NLSR_LOG_DEBUG(lengthOfDash);
135 
136  for (size_t i = 0; i < m_nRouters; i++) {
137  std::string line;
138  for (size_t j = 0; j < m_nRouters; j++) {
139  line += boost::lexical_cast<std::string>(adjMatrix[i][j]);
140  line += " ";
141  }
142  line = boost::lexical_cast<std::string>(i) + "|" + line;
143  NLSR_LOG_DEBUG(line);
144  }
145 }
146 
147 void
148 RoutingTableCalculator::adjustAdMatrix(int source, int link, double linkCost)
149 {
150  for (int i = 0; i < static_cast<int>(m_nRouters); i++) {
151  if (i == link) {
152  adjMatrix[source][i] = linkCost;
153  }
154  else {
155  adjMatrix[source][i] = 0;
156  }
157  }
158 }
159 
160 int
162 {
163  int noLink = 0;
164 
165  for (size_t i = 0; i < m_nRouters; i++) {
166  if (adjMatrix[sRouter][i] > 0) {
167  noLink++;
168  }
169  }
170  return noLink;
171 }
172 
173 void
175  double* linkCosts, int source)
176 {
177  int j = 0;
178 
179  for (size_t i = 0; i < m_nRouters; i++) {
180  if (adjMatrix[source][i] > 0) {
181  links[j] = i;
182  linkCosts[j] = adjMatrix[source][i];
183  j++;
184  }
185  }
186 }
187 
188 void
190 {
191  for (size_t i = 0; i < m_nRouters; ++i) {
192  delete [] adjMatrix[i];
193  }
194  delete [] adjMatrix;
195 }
196 
197 void
199 {
200  links = new int[vNoLink];
201 }
202 
203 void
205 {
206  linkCosts = new double[vNoLink];
207 }
208 
209 
210 void
212 {
213  delete [] links;
214 }
215 void
217 {
218  delete [] linkCosts;
219 }
220 
221 void
223  ConfParameter& confParam,
224  const std::list<AdjLsa>& adjLsaList)
225 {
226  NLSR_LOG_DEBUG("LinkStateRoutingTableCalculator::calculatePath Called");
228  initMatrix();
229  makeAdjMatrix(adjLsaList, pMap);
230  writeAdjMatrixLog(pMap);
231  ndn::optional<int32_t> sourceRouter =
232  pMap.getMappingNoByRouterName(confParam.getRouterPrefix());
233  allocateParent(); // These two matrices are used in Dijkstra's algorithm.
234  allocateDistance(); //
235  // We only bother to do the calculation if we have a router by that name.
236  if (sourceRouter && confParam.getMaxFacesPerPrefix() == 1) {
237  // In the single path case we can simply run Dijkstra's algorithm.
238  doDijkstraPathCalculation(*sourceRouter);
239  // Inform the routing table of the new next hops.
240  addAllLsNextHopsToRoutingTable(confParam.getAdjacencyList(), rt, pMap, *sourceRouter);
241  }
242  else {
243  // Multi Path
244  setNoLink(getNumOfLinkfromAdjMatrix(*sourceRouter));
245  allocateLinks();
247  // Gets a sparse listing of adjacencies for path calculation
248  getLinksFromAdjMatrix(links, linkCosts, *sourceRouter);
249  for (int i = 0 ; i < vNoLink; i++) {
250  // Simulate that only the current neighbor is accessible
251  adjustAdMatrix(*sourceRouter, links[i], linkCosts[i]);
252  writeAdjMatrixLog(pMap);
253  // Do Dijkstra's algorithm using the current neighbor as your start.
254  doDijkstraPathCalculation(*sourceRouter);
255  // Update the routing table with the calculations.
256  addAllLsNextHopsToRoutingTable(confParam.getAdjacencyList(), rt, pMap, *sourceRouter);
257  }
258  freeLinks();
259  freeLinksCosts();
260  }
261  freeParent();
262  freeDistance();
263  freeAdjMatrix();
264 }
265 
266 void
267 LinkStateRoutingTableCalculator::doDijkstraPathCalculation(int sourceRouter)
268 {
269  int i;
270  int v, u;
271  int* Q = new int[m_nRouters]; // Each cell represents the router with that mapping no.
272  int head = 0;
273  // Initiate the parent
274  for (i = 0 ; i < static_cast<int>(m_nRouters); i++) {
275  m_parent[i] = EMPTY_PARENT;
276  // Array where the ith element is the distance to the router with mapping no i.
277  m_distance[i] = INF_DISTANCE;
278  Q[i] = i;
279  }
280  if (sourceRouter != NO_MAPPING_NUM) {
281  // Distance to source from source is always 0.
282  m_distance[sourceRouter] = 0;
283  sortQueueByDistance(Q, m_distance, head, m_nRouters);
284  // While we haven't visited every node.
285  while (head < static_cast<int>(m_nRouters)) {
286  u = Q[head]; // Set u to be the current node pointed to by head.
287  if (m_distance[u] == INF_DISTANCE) {
288  break; // This can only happen when there are no accessible nodes.
289  }
290  // Iterate over the adjacent nodes to u.
291  for (v = 0 ; v < static_cast<int>(m_nRouters); v++) {
292  // If the current node is accessible.
293  if (adjMatrix[u][v] > 0) {
294  // And we haven't visited it yet.
295  if (isNotExplored(Q, v, head + 1, m_nRouters)) {
296  // And if the distance to this node + from this node to v
297  // is less than the distance from our source node to v
298  // that we got when we built the adj LSAs
299  if (m_distance[u] + adjMatrix[u][v] < m_distance[v]) {
300  // Set the new distance
301  m_distance[v] = m_distance[u] + adjMatrix[u][v] ;
302  // Set how we get there.
303  m_parent[v] = u;
304  }
305  }
306  }
307  }
308  // Increment the head position, resort the list by distance from where we are.
309  head++;
310  sortQueueByDistance(Q, m_distance, head, m_nRouters);
311  }
312  }
313  delete [] Q;
314 }
315 
316 void
317 LinkStateRoutingTableCalculator::addAllLsNextHopsToRoutingTable(AdjacencyList& adjacencies,
318  RoutingTable& rt, Map& pMap,
319  uint32_t sourceRouter)
320 {
321  NLSR_LOG_DEBUG("LinkStateRoutingTableCalculator::addAllNextHopsToRoutingTable Called");
322 
323  int nextHopRouter = 0;
324 
325  // For each router we have
326  for (size_t i = 0; i < m_nRouters ; i++) {
327  if (i != sourceRouter) {
328 
329  // Obtain the next hop that was determined by the algorithm
330  nextHopRouter = getLsNextHop(i, sourceRouter);
331 
332  // If this router is accessible at all
333  if (nextHopRouter != NO_NEXT_HOP) {
334 
335  // Fetch its distance
336  double routeCost = m_distance[i];
337  // Fetch its actual name
338  ndn::optional<ndn::Name> nextHopRouterName= pMap.getRouterNameByMappingNo(nextHopRouter);
339  if (nextHopRouterName) {
340  std::string nextHopFace =
341  adjacencies.getAdjacent(*nextHopRouterName).getFaceUri().toString();
342  // Add next hop to routing table
343  NextHop nh(nextHopFace, routeCost);
344  rt.addNextHop(*(pMap.getRouterNameByMappingNo(i)), nh);
345 
346  }
347  }
348  }
349  }
350 }
351 
352 int
353 LinkStateRoutingTableCalculator::getLsNextHop(int dest, int source)
354 {
355  int nextHop = NO_NEXT_HOP;
356  while (m_parent[dest] != EMPTY_PARENT) {
357  nextHop = dest;
358  dest = m_parent[dest];
359  }
360  if (dest != source) {
361  nextHop = NO_NEXT_HOP;
362  }
363  return nextHop;
364 }
365 
366 void
367 LinkStateRoutingTableCalculator::sortQueueByDistance(int* Q,
368  double* dist,
369  int start, int element)
370 {
371  for (int i = start ; i < element ; i++) {
372  for (int j = i + 1; j < element; j++) {
373  if (dist[Q[j]] < dist[Q[i]]) {
374  int tempU = Q[j];
375  Q[j] = Q[i];
376  Q[i] = tempU;
377  }
378  }
379  }
380 }
381 
382 int
383 LinkStateRoutingTableCalculator::isNotExplored(int* Q,
384  int u, int start, int element)
385 {
386  int ret = 0;
387  for (int i = start; i < element; i++) {
388  if (Q[i] == u) {
389  ret = 1;
390  break;
391  }
392  }
393  return ret;
394 }
395 
396 void
397 LinkStateRoutingTableCalculator::allocateParent()
398 {
399  m_parent = new int[m_nRouters];
400 }
401 
402 void
403 LinkStateRoutingTableCalculator::allocateDistance()
404 {
405  m_distance = new double[m_nRouters];
406 }
407 
408 void
409 LinkStateRoutingTableCalculator::freeParent()
410 {
411  delete [] m_parent;
412 }
413 
414 void LinkStateRoutingTableCalculator::freeDistance()
415 {
416  delete [] m_distance;
417 }
418 
419 const double HyperbolicRoutingCalculator::MATH_PI = boost::math::constants::pi<double>();
420 
421 const double HyperbolicRoutingCalculator::UNKNOWN_DISTANCE = -1.0;
422 const double HyperbolicRoutingCalculator::UNKNOWN_RADIUS = -1.0;
423 
424 void
426  Lsdb& lsdb, AdjacencyList& adjacencies)
427 {
428  NLSR_LOG_TRACE("Calculating hyperbolic paths");
429 
430  ndn::optional<int32_t> thisRouter = map.getMappingNoByRouterName(m_thisRouterName);
431 
432  // Iterate over directly connected neighbors
433  std::list<Adjacent> neighbors = adjacencies.getAdjList();
434  for (std::list<Adjacent>::iterator adj = neighbors.begin(); adj != neighbors.end(); ++adj) {
435 
436  // Don't calculate nexthops using an inactive router
437  if (adj->getStatus() == Adjacent::STATUS_INACTIVE) {
438  NLSR_LOG_TRACE(adj->getName() << " is inactive; not using it as a nexthop");
439  continue;
440  }
441 
442  ndn::Name srcRouterName = adj->getName();
443 
444  // Don't calculate nexthops for this router to other routers
445  if (srcRouterName == m_thisRouterName) {
446  continue;
447  }
448 
449  std::string srcFaceUri = adj->getFaceUri().toString();
450 
451  // Install nexthops for this router to the neighbor; direct neighbors have a 0 cost link
452  addNextHop(srcRouterName, srcFaceUri, 0, rt);
453 
454  ndn::optional<int32_t> src = map.getMappingNoByRouterName(srcRouterName);
455 
456  if (!src) {
457  NLSR_LOG_WARN(adj->getName() << " does not exist in the router map!");
458  continue;
459  }
460 
461  // Get hyperbolic distance from direct neighbor to every other router
462  for (int dest = 0; dest < static_cast<int>(m_nRouters); ++dest) {
463  // Don't calculate nexthops to this router or from a router to itself
464  if (thisRouter && dest != *thisRouter && dest != *src) {
465 
466  ndn::optional<ndn::Name> destRouterName = map.getRouterNameByMappingNo(dest);
467  if (destRouterName) {
468  double distance = getHyperbolicDistance(lsdb, srcRouterName, *destRouterName);
469 
470  // Could not compute distance
471  if (distance == UNKNOWN_DISTANCE) {
472  NLSR_LOG_WARN("Could not calculate hyperbolic distance from " << srcRouterName << " to " <<
473  *destRouterName);
474  continue;
475  }
476 
477  addNextHop(*destRouterName, srcFaceUri, distance, rt);
478  }
479  }
480  }
481  }
482 }
483 
484 double
485 HyperbolicRoutingCalculator::getHyperbolicDistance(Lsdb& lsdb, ndn::Name src, ndn::Name dest)
486 {
487  NLSR_LOG_TRACE("Calculating hyperbolic distance from " << src << " to " << dest);
488 
489  double distance = UNKNOWN_DISTANCE;
490 
491  ndn::Name srcLsaKey = src;
492  srcLsaKey.append(std::to_string(Lsa::Type::COORDINATE));
493 
494  CoordinateLsa* srcLsa = lsdb.findCoordinateLsa(srcLsaKey);
495 
496  ndn::Name destLsaKey = dest;
497  destLsaKey.append(std::to_string(Lsa::Type::COORDINATE));
498 
499  CoordinateLsa* destLsa = lsdb.findCoordinateLsa(destLsaKey);
500 
501  // Coordinate LSAs do not exist for these routers
502  if (srcLsa == nullptr || destLsa == nullptr) {
503  return UNKNOWN_DISTANCE;
504  }
505 
506  std::vector<double> srcTheta = srcLsa->getCorTheta();
507  std::vector<double> destTheta = destLsa->getCorTheta();
508 
509  double srcRadius = srcLsa->getCorRadius();
510  double destRadius = destLsa->getCorRadius();
511 
512  double diffTheta = calculateAngularDistance(srcTheta, destTheta);
513 
514  if (srcRadius == UNKNOWN_RADIUS || destRadius == UNKNOWN_RADIUS ||
515  diffTheta == UNKNOWN_DISTANCE) {
516  return UNKNOWN_DISTANCE;
517  }
518 
519  // double r_i, double r_j, double delta_theta, double zeta = 1 (default)
520  distance = calculateHyperbolicDistance(srcRadius, destRadius, diffTheta);
521 
522  NLSR_LOG_TRACE("Distance from " << src << " to " << dest << " is " << distance);
523 
524  return distance;
525 }
526 
527 double
528 HyperbolicRoutingCalculator::calculateAngularDistance(std::vector<double> angleVectorI,
529  std::vector<double> angleVectorJ)
530 {
531  // It is not possible for angle vector size to be zero as ensured by conf-file-processor
532 
533  // https://en.wikipedia.org/wiki/N-sphere#Spherical_coordinates
534 
535  // Check if two vector lengths are the same
536  if (angleVectorI.size() != angleVectorJ.size()) {
537  NLSR_LOG_ERROR("Angle vector sizes do not match");
538  return UNKNOWN_DISTANCE;
539  }
540 
541  // Check if all angles are within the [0, PI] and [0, 2PI] ranges
542  if (angleVectorI.size() > 1) {
543  for (unsigned int k = 0; k < angleVectorI.size() - 1; k++) {
544  if ((angleVectorI[k] > M_PI && angleVectorI[k] < 0.0) ||
545  (angleVectorJ[k] > M_PI && angleVectorJ[k] < 0.0)) {
546  NLSR_LOG_ERROR("Angle outside [0, PI]");
547  return UNKNOWN_DISTANCE;
548  }
549  }
550  }
551  if (angleVectorI[angleVectorI.size()-1] > 2.*M_PI ||
552  angleVectorI[angleVectorI.size()-1] < 0.0) {
553  NLSR_LOG_ERROR("Angle not within [0, 2PI]");
554  return UNKNOWN_DISTANCE;
555  }
556 
557  if (angleVectorI[angleVectorI.size()-1] > 2.*M_PI ||
558  angleVectorI[angleVectorI.size()-1] < 0.0) {
559  NLSR_LOG_ERROR("Angle not within [0, 2PI]");
560  return UNKNOWN_DISTANCE;
561  }
562 
563  // deltaTheta = arccos(vectorI . vectorJ) -> do the inner product
564  double innerProduct = 0.0;
565 
566  // Calculate x0 of the vectors
567  double x0i = std::cos(angleVectorI[0]);
568  double x0j = std::cos(angleVectorJ[0]);
569 
570  // Calculate xn of the vectors
571  double xni = std::sin(angleVectorI[angleVectorI.size() - 1]);
572  double xnj = std::sin(angleVectorJ[angleVectorJ.size() - 1]);
573 
574  // Do the aggregation of the (n-1) coordinates (if there is more than one angle)
575  // i.e contraction of all (n-1)-dimensional angular coordinates to one variable
576  for (unsigned int k = 0; k < angleVectorI.size() - 1; k++) {
577  xni *= std::sin(angleVectorI[k]);
578  xnj *= std::sin(angleVectorJ[k]);
579  }
580  innerProduct += (x0i * x0j) + (xni * xnj);
581 
582  // If d > 1
583  if (angleVectorI.size() > 1) {
584  for (unsigned int m = 1; m < angleVectorI.size(); m++) {
585  // calculate euclidean coordinates given the angles and assuming R_sphere = 1
586  double xmi = std::cos(angleVectorI[m]);
587  double xmj = std::cos(angleVectorJ[m]);
588  for (unsigned int l = 0; l < m; l++) {
589  xmi *= std::sin(angleVectorI[l]);
590  xmj *= std::sin(angleVectorJ[l]);
591  }
592  innerProduct += xmi * xmj;
593  }
594  }
595 
596  // ArcCos of the inner product gives the angular distance
597  // between two points on a d-dimensional sphere
598  return std::acos(innerProduct);
599 }
600 
601 double
602 HyperbolicRoutingCalculator::calculateHyperbolicDistance(double rI, double rJ,
603  double deltaTheta)
604 {
605  if (deltaTheta == UNKNOWN_DISTANCE) {
606  return UNKNOWN_DISTANCE;
607  }
608 
609  // Usually, we set zeta = 1 in all experiments
610  double zeta = 1;
611 
612  if (deltaTheta <= 0.0 || rI <= 0.0 || rJ <= 0.0) {
613  NLSR_LOG_ERROR("Delta theta or rI or rJ is <= 0");
614  NLSR_LOG_ERROR("Please make sure that no two nodes have the exact same HR coordinates");
615  return UNKNOWN_DISTANCE;
616  }
617 
618  double xij = (1. / zeta) * std::acosh(std::cosh(zeta*rI) * std::cosh(zeta*rJ) -
619  std::sinh(zeta*rI)*std::sinh(zeta*rJ)*std::cos(deltaTheta));
620  return xij;
621 }
622 
623 void
624 HyperbolicRoutingCalculator::addNextHop(ndn::Name dest, std::string faceUri,
625  double cost, RoutingTable& rt)
626 {
627  NextHop hop(faceUri, cost);
628  hop.setHyperbolic(true);
629 
630  NLSR_LOG_TRACE("Calculated " << hop << " for destination: " << dest);
631 
632  if (m_isDryRun) {
633  rt.addNextHopToDryTable(dest, hop);
634  }
635  else {
636  rt.addNextHop(dest, hop);
637  }
638 }
639 
640 } // namespace nlsr
void writeAdjMatrixLog(const Map &map) const
#define NLSR_LOG_WARN(x)
Definition: logger.hpp:40
A class to house all the configuration parameters for NLSR.
void getLinksFromAdjMatrix(int *links, double *linkCosts, int source)
Populates temp. variables with the link costs for some router.
ndn::optional< ndn::Name > getRouterNameByMappingNo(int32_t mn) const
Definition: map.cpp:48
void calculatePath(Map &map, RoutingTable &rt, Lsdb &lsdb, AdjacencyList &adjacencies)
const ndn::FaceUri & getFaceUri() const
Definition: adjacent.hpp:69
void allocateAdjMatrix()
Allocate the space needed for the adj. matrix.
void adjustAdMatrix(int source, int link, double linkCost)
Adjust a link cost in the adj. matrix.
AdjacencyList & getAdjacencyList()
ndn::optional< int32_t > getMappingNoByRouterName(const ndn::Name &rName)
Definition: map.cpp:61
#define NLSR_LOG_DEBUG(x)
Definition: logger.hpp:38
const ndn::Name & getRouterPrefix() const
Copyright (c) 2014-2018, The University of Memphis, Regents of the University of California.
Adjacent getAdjacent(const ndn::Name &adjName)
#define INIT_LOGGER(name)
Definition: logger.hpp:35
void makeAdjMatrix(const std::list< AdjLsa > &adjLsaList, Map &pMap)
Constructs an adj. matrix to calculate with.
uint32_t getMaxFacesPerPrefix() const
void initMatrix()
Zero every cell of the matrix to ensure that the memory is safe.
CoordinateLsa * findCoordinateLsa(const ndn::Name &key)
Finds a cor. LSA in the LSDB.
Definition: lsdb.cpp:402
#define NLSR_LOG_ERROR(x)
Definition: logger.hpp:41
Copyright (c) 2014-2018, The University of Memphis, Regents of the University of California, Arizona Board of Regents.
void calculatePath(Map &pMap, RoutingTable &rt, ConfParameter &confParam, const std::list< AdjLsa > &adjLsaList)
const std::vector< double > getCorTheta() const
Definition: lsa.hpp:362
void addNextHopToDryTable(const ndn::Name &destRouter, NextHop &nh)
Adds a next hop to a routing table entry in a dry run scenario.
int getNumOfLinkfromAdjMatrix(int sRouter)
Returns how many links a router in the matrix has.
void setHyperbolic(bool b)
void addNextHop(const ndn::Name &destRouter, NextHop &nh)
Adds a next hop to a routing table entry.
std::list< Adjacent > & getAdjList()
#define NLSR_LOG_TRACE(x)
Definition: logger.hpp:37
double getCorRadius() const
Definition: lsa.hpp:350