route: handle zero cost links
refs: #4978
Change-Id: I461bdac9e10cb8362a7624b177ee68aa20d3ff3e
diff --git a/src/adjacent.cpp b/src/adjacent.cpp
index 950a7ae..4afe6d7 100644
--- a/src/adjacent.cpp
+++ b/src/adjacent.cpp
@@ -1,6 +1,6 @@
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/**
- * Copyright (c) 2014-2018, The University of Memphis,
+ * Copyright (c) 2014-2019, The University of Memphis,
* Regents of the University of California
*
* This file is part of NLSR (Named-data Link State Routing).
@@ -30,7 +30,8 @@
INIT_LOGGER(Adjacent);
-const float Adjacent::DEFAULT_LINK_COST = 10.0;
+const double Adjacent::DEFAULT_LINK_COST = 10.0;
+const double Adjacent::NON_ADJACENT_COST = -12345;
Adjacent::Adjacent()
: m_name()
@@ -56,13 +57,27 @@
Status s, uint32_t iton, uint64_t faceId)
: m_name(an)
, m_faceUri(faceUri)
- , m_linkCost(lc)
, m_status(s)
, m_interestTimedOutNo(iton)
, m_faceId(faceId)
{
+ this->setLinkCost(lc);
}
+void
+Adjacent::setLinkCost(double lc)
+{
+ // NON_ADJACENT_COST is a negative value and is used for nodes that aren't direct neighbors.
+ // But for direct/active neighbors, the cost cannot be negative.
+ if (lc < 0 && lc != NON_ADJACENT_COST)
+ {
+ NLSR_LOG_ERROR(" Neighbor's link-cost cannot be negative");
+ BOOST_THROW_EXCEPTION(ndn::tlv::Error("Neighbor's link-cost cannot be negative"));
+ }
+
+ m_linkCost = lc;
+}
+
bool
Adjacent::operator==(const Adjacent& adjacent) const
{
diff --git a/src/adjacent.hpp b/src/adjacent.hpp
index 72a8d98..c85f0ff 100644
--- a/src/adjacent.hpp
+++ b/src/adjacent.hpp
@@ -1,6 +1,6 @@
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/**
- * Copyright (c) 2014-2018, The University of Memphis,
+ * Copyright (c) 2014-2019, The University of Memphis,
* Regents of the University of California
*
* This file is part of NLSR (Named-data Link State Routing).
@@ -77,18 +77,14 @@
m_faceUri = faceUri;
}
- uint64_t
+ double
getLinkCost() const
{
- uint64_t linkCost = static_cast<uint64_t>(ceil(m_linkCost));
- return linkCost;
+ return ceil(m_linkCost);
}
void
- setLinkCost(double lc)
- {
- m_linkCost = lc;
- }
+ setLinkCost(double lc);
Status
getStatus() const
@@ -161,7 +157,8 @@
writeLog();
public:
- static const float DEFAULT_LINK_COST;
+ static const double DEFAULT_LINK_COST;
+ static const double NON_ADJACENT_COST;
private:
/*! m_name The NLSR-configured router name of the neighbor */
diff --git a/src/conf-parameter.hpp b/src/conf-parameter.hpp
index 1ecf6c8..6b63937 100644
--- a/src/conf-parameter.hpp
+++ b/src/conf-parameter.hpp
@@ -415,7 +415,8 @@
return m_stateFileDir;
}
- void setConfFileNameDynamic(const std::string& confFileDynamic)
+ void
+ setConfFileNameDynamic(const std::string& confFileDynamic)
{
m_confFileNameDynamic = confFileDynamic;
}
diff --git a/src/lsa.cpp b/src/lsa.cpp
index bee69db..5930e99 100644
--- a/src/lsa.cpp
+++ b/src/lsa.cpp
@@ -248,11 +248,16 @@
ndn::Name adjName(*tok_iter++);
std::string connectingFaceUri(*tok_iter++);
double linkCost = boost::lexical_cast<double>(*tok_iter++);
+
Adjacent adjacent(adjName, ndn::FaceUri(connectingFaceUri), linkCost,
Adjacent::STATUS_INACTIVE, 0, 0);
addAdjacent(adjacent);
}
}
+ // Ignore neighbors with negative cost received from the Adjacent LSA data.
+ catch (const ndn::tlv::Error& e) {
+ NLSR_LOG_ERROR(e.what());
+ }
catch (const std::exception& e) {
NLSR_LOG_ERROR("Could not deserialize from content: " << e.what());
return false;
diff --git a/src/lsdb.cpp b/src/lsdb.cpp
index 01c1ee0..1e3cf1b 100644
--- a/src/lsdb.cpp
+++ b/src/lsdb.cpp
@@ -218,12 +218,10 @@
m_namePrefixTable.addEntry(name, nlsa.getOrigRouter());
}
}
- }
- if (nlsa.getOrigRouter() != m_confParam.getRouterPrefix()) {
- ndn::time::system_clock::Duration duration = nlsa.getExpirationTimePoint() -
- ndn::time::system_clock::now();
+ auto duration = nlsa.getExpirationTimePoint() - ndn::time::system_clock::now();
timeToExpire = ndn::time::duration_cast<ndn::time::seconds>(duration);
}
+
nlsa.setExpiringEventId(scheduleNameLsaExpiration(nlsa.getKey(),
nlsa.getLsSeqNo(),
timeToExpire));
diff --git a/src/route/routing-table-calculator.cpp b/src/route/routing-table-calculator.cpp
index 68a7ca2..a079933 100644
--- a/src/route/routing-table-calculator.cpp
+++ b/src/route/routing-table-calculator.cpp
@@ -25,6 +25,7 @@
#include "nexthop.hpp"
#include "nlsr.hpp"
#include "logger.hpp"
+#include "adjacent.hpp"
#include <iostream>
#include <boost/math/constants/constants.hpp>
@@ -35,6 +36,11 @@
INIT_LOGGER(route.RoutingTableCalculator);
+const int LinkStateRoutingTableCalculator::EMPTY_PARENT = -12345;
+const double LinkStateRoutingTableCalculator::INF_DISTANCE = 2147483647;
+const int LinkStateRoutingTableCalculator::NO_MAPPING_NUM = -1;
+const int LinkStateRoutingTableCalculator::NO_NEXT_HOP = -12345;
+
void
RoutingTableCalculator::allocateAdjMatrix()
{
@@ -50,7 +56,7 @@
{
for (size_t i = 0; i < m_nRouters; i++) {
for (size_t j = 0; j < m_nRouters; j++) {
- adjMatrix[i][j] = 0;
+ adjMatrix[i][j] = Adjacent::NON_ADJACENT_COST;
}
}
}
@@ -79,8 +85,8 @@
// Links that do not have the same cost for both directions should
// have their costs corrected:
//
- // If the cost of one side of the link is 0, both sides of the
- // link should have their cost corrected to 0.
+ // If the cost of one side of the link is NON_ADJACENT_COST (i.e. broken) or negative,
+ // both direction of the link should have their cost corrected to NON_ADJACENT_COST.
//
// Otherwise, both sides of the link should use the larger of the two costs.
//
@@ -93,10 +99,10 @@
double fromCost = adjMatrix[col][row];
if (fromCost != toCost) {
- double correctedCost = 0.0;
+ double correctedCost = Adjacent::NON_ADJACENT_COST;
- if (toCost != 0 && fromCost != 0) {
- // If both sides of the link are up, use the larger cost
+ if (toCost >= 0 && fromCost >= 0) {
+ // If both sides of the link are up, use the larger cost else break the link
correctedCost = std::max(toCost, fromCost);
}
@@ -152,7 +158,8 @@
adjMatrix[source][i] = linkCost;
}
else {
- adjMatrix[source][i] = 0;
+ // if "i" is not a link to the source, set it's cost to a non adjacent value.
+ adjMatrix[source][i] = Adjacent::NON_ADJACENT_COST;
}
}
}
@@ -163,7 +170,7 @@
int noLink = 0;
for (size_t i = 0; i < m_nRouters; i++) {
- if (adjMatrix[sRouter][i] > 0) {
+ if (adjMatrix[sRouter][i] >= 0 && i != static_cast<size_t>(sRouter)) { // make sure "i" is not self
noLink++;
}
}
@@ -177,7 +184,7 @@
int j = 0;
for (size_t i = 0; i < m_nRouters; i++) {
- if (adjMatrix[source][i] > 0) {
+ if (adjMatrix[source][i] >= 0 && i != static_cast<size_t>(source)) {// make sure "i" is not self
links[j] = i;
linkCosts[j] = adjMatrix[source][i];
j++;
@@ -290,7 +297,7 @@
// Iterate over the adjacent nodes to u.
for (v = 0 ; v < static_cast<int>(m_nRouters); v++) {
// If the current node is accessible.
- if (adjMatrix[u][v] > 0) {
+ if (adjMatrix[u][v] >= 0) {
// And we haven't visited it yet.
if (isNotExplored(Q, v, head + 1, m_nRouters)) {
// And if the distance to this node + from this node to v
@@ -328,7 +335,6 @@
// Obtain the next hop that was determined by the algorithm
nextHopRouter = getLsNextHop(i, sourceRouter);
-
// If this router is accessible at all
if (nextHopRouter != NO_NEXT_HOP) {
@@ -469,11 +475,10 @@
// Could not compute distance
if (distance == UNKNOWN_DISTANCE) {
- NLSR_LOG_WARN("Could not calculate hyperbolic distance from " << srcRouterName << " to " <<
- *destRouterName);
+ NLSR_LOG_WARN("Could not calculate hyperbolic distance from " << srcRouterName
+ << " to " << *destRouterName);
continue;
}
-
addNextHop(*destRouterName, srcFaceUri, distance, rt);
}
}
diff --git a/src/route/routing-table-calculator.hpp b/src/route/routing-table-calculator.hpp
index dd1e658..0a40a1c 100644
--- a/src/route/routing-table-calculator.hpp
+++ b/src/route/routing-table-calculator.hpp
@@ -40,19 +40,18 @@
class RoutingTableCalculator
{
public:
- RoutingTableCalculator()
- {
- }
RoutingTableCalculator(size_t nRouters)
{
m_nRouters = nRouters;
}
+
protected:
/*! \brief Allocate the space needed for the adj. matrix. */
void
allocateAdjMatrix();
- /*! \brief Zero every cell of the matrix to ensure that the memory is safe. */
+ /*! \brief set NON_ADJACENT_COST i.e. -12345 to every cell of the matrix to
+ ensure that the memory is safe. This is also to incorporate zero cost links */
void
initMatrix();
@@ -63,6 +62,9 @@
void
makeAdjMatrix(const std::list<AdjLsa>& adjLsaList, Map& pMap);
+ /*! \brief Writes a formated adjacent matrix to DEBUG log
+ \param map The map containing adjacent matrix data
+ */
void
writeAdjMatrixLog(const Map& map) const;
@@ -90,8 +92,8 @@
Obtains a sparse list of adjacencies and link costs for some
router. Since this is sparse, that means while generating these
arrays, if there is no adjacency at i in the matrix, these
- temporary variables will not contain a 0 at i, but rather will
- contain the values for the next valid adjacency.
+ temporary variables will not contain a NON_ADJACENT_COST (-12345) at i,
+ but rather will contain the values for the next valid adjacency.
*/
void
getLinksFromAdjMatrix(int* links, double* linkCosts, int source);
@@ -122,6 +124,7 @@
int vNoLink;
int* links;
double* linkCosts;
+
};
class LinkStateRoutingTableCalculator: public RoutingTableCalculator
@@ -129,10 +132,6 @@
public:
LinkStateRoutingTableCalculator(size_t nRouters)
: RoutingTableCalculator(nRouters)
- , EMPTY_PARENT(-12345)
- , INF_DISTANCE(2147483647)
- , NO_MAPPING_NUM(-1)
- , NO_NEXT_HOP(-12345)
{
}
@@ -155,6 +154,9 @@
Sorts the list based on distance. The distances are indexed by
their mappingNo in dist. Currently uses an insertion sort.
+
+ The cost between two nodes can be zero or greater than zero.
+
*/
void
sortQueueByDistance(int* Q, double* dist, int start, int element);
@@ -195,10 +197,10 @@
int* m_parent;
double* m_distance;
- const int EMPTY_PARENT;
- const double INF_DISTANCE;
- const int NO_MAPPING_NUM;
- const int NO_NEXT_HOP;
+ static const int EMPTY_PARENT;
+ static const double INF_DISTANCE;
+ static const int NO_MAPPING_NUM;
+ static const int NO_NEXT_HOP;
};