blob: 2d8ee1b2aae7e623c3e11cc7c48ffae1e611caf9 [file] [log] [blame]
Vince Lehman41b173e2015-05-07 14:13:26 -05001/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
2/**
Saurab Dulal427e0122019-11-28 11:58:02 -06003 * Copyright (c) 2014-2020, The University of Memphis,
Vince Lehman41b173e2015-05-07 14:13:26 -05004 * Regents of the University of California,
5 * Arizona Board of Regents.
6 *
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/>.
20 **/
21
22#include "route/routing-table-calculator.hpp"
23
24#include "adjacency-list.hpp"
25#include "lsa.hpp"
26#include "lsdb.hpp"
27#include "nlsr.hpp"
28#include "test-common.hpp"
29#include "route/map.hpp"
30#include "route/routing-table.hpp"
dulalsaurabd0816a32019-07-26 13:11:24 +000031#include "adjacent.hpp"
Vince Lehman41b173e2015-05-07 14:13:26 -050032
33#include <ndn-cxx/util/dummy-client-face.hpp>
34
35namespace nlsr {
36namespace test {
37
38static const ndn::time::system_clock::TimePoint MAX_TIME =
39 ndn::time::system_clock::TimePoint::max();
40
41class LinkStateCalculatorFixture : public BaseFixture
42{
43public:
44 LinkStateCalculatorFixture()
Muktadir Chowdhuryf04f9892017-08-20 20:42:56 -050045 : face(m_ioService, m_keyChain)
Saurab Dulal427e0122019-11-28 11:58:02 -060046 , conf(face, m_keyChain)
Ashlesh Gawande85998a12017-12-07 22:22:13 -060047 , confProcessor(conf)
48 , nlsr(face, m_keyChain, conf)
49 , routingTable(nlsr.m_routingTable)
50 , lsdb(nlsr.m_lsdb)
Vince Lehman41b173e2015-05-07 14:13:26 -050051 {
52 setUpTopology();
53 }
54
55 // Triangle topology with routers A, B, C connected
56 void setUpTopology()
57 {
Muktadir Chowdhuryf04f9892017-08-20 20:42:56 -050058 Adjacent a(ROUTER_A_NAME, ndn::FaceUri(ROUTER_A_FACE), 0, Adjacent::STATUS_ACTIVE, 0, 0);
59 Adjacent b(ROUTER_B_NAME, ndn::FaceUri(ROUTER_B_FACE), 0, Adjacent::STATUS_ACTIVE, 0, 0);
60 Adjacent c(ROUTER_C_NAME, ndn::FaceUri(ROUTER_C_FACE), 0, Adjacent::STATUS_ACTIVE, 0, 0);
Vince Lehman41b173e2015-05-07 14:13:26 -050061
62 // Router A
63 b.setLinkCost(LINK_AB_COST);
64 c.setLinkCost(LINK_AC_COST);
65
Ashlesh Gawande85998a12017-12-07 22:22:13 -060066 AdjacencyList& adjacencyListA = conf.getAdjacencyList();
Vince Lehman41b173e2015-05-07 14:13:26 -050067 adjacencyListA.insert(b);
68 adjacencyListA.insert(c);
69
Ashlesh Gawanded02c3882015-12-29 16:02:51 -060070 AdjLsa adjA(a.getName(), 1, MAX_TIME, 2, adjacencyListA);
Vince Lehman41b173e2015-05-07 14:13:26 -050071 lsdb.installAdjLsa(adjA);
72
73 // Router B
74 a.setLinkCost(LINK_AB_COST);
75 c.setLinkCost(LINK_BC_COST);
76
77 AdjacencyList adjacencyListB;
78 adjacencyListB.insert(a);
79 adjacencyListB.insert(c);
80
Ashlesh Gawanded02c3882015-12-29 16:02:51 -060081 AdjLsa adjB(b.getName(), 1, MAX_TIME, 2, adjacencyListB);
Vince Lehman41b173e2015-05-07 14:13:26 -050082 lsdb.installAdjLsa(adjB);
83
84 // Router C
85 a.setLinkCost(LINK_AC_COST);
86 b.setLinkCost(LINK_BC_COST);
87
88 AdjacencyList adjacencyListC;
89 adjacencyListC.insert(a);
90 adjacencyListC.insert(b);
91
Ashlesh Gawanded02c3882015-12-29 16:02:51 -060092 AdjLsa adjC(c.getName(), 1, MAX_TIME, 2, adjacencyListC);
Vince Lehman41b173e2015-05-07 14:13:26 -050093 lsdb.installAdjLsa(adjC);
94
Nick Gordon22b5c952017-08-10 17:48:15 -050095 map.createFromAdjLsdb(lsdb.getAdjLsdb().begin(), lsdb.getAdjLsdb().end());
Vince Lehman41b173e2015-05-07 14:13:26 -050096 }
97
98public:
Muktadir Chowdhuryf04f9892017-08-20 20:42:56 -050099 ndn::util::DummyClientFace face;
Ashlesh Gawande85998a12017-12-07 22:22:13 -0600100 ConfParameter conf;
101 DummyConfFileProcessor confProcessor;
Vince Lehman41b173e2015-05-07 14:13:26 -0500102 Nlsr nlsr;
103 Map map;
104
105 RoutingTable& routingTable;
106 Lsdb& lsdb;
107
108 static const ndn::Name ROUTER_A_NAME;
109 static const ndn::Name ROUTER_B_NAME;
110 static const ndn::Name ROUTER_C_NAME;
111
112 static const std::string ROUTER_A_FACE;
113 static const std::string ROUTER_B_FACE;
114 static const std::string ROUTER_C_FACE;
115
116 static const double LINK_AB_COST;
117 static const double LINK_AC_COST;
118 static const double LINK_BC_COST;
119};
120
Ashlesh Gawande85998a12017-12-07 22:22:13 -0600121const ndn::Name LinkStateCalculatorFixture::ROUTER_A_NAME = "/ndn/site/%C1.Router/this-router";
122const ndn::Name LinkStateCalculatorFixture::ROUTER_B_NAME = "/ndn/site/%C1.Router/b";
123const ndn::Name LinkStateCalculatorFixture::ROUTER_C_NAME = "/ndn/site/%C1.Router/c";
Vince Lehman41b173e2015-05-07 14:13:26 -0500124
Nick Gordone9733ed2017-04-26 10:48:39 -0500125const std::string LinkStateCalculatorFixture::ROUTER_A_FACE = "udp4://10.0.0.1";
126const std::string LinkStateCalculatorFixture::ROUTER_B_FACE = "udp4://10.0.0.2";
127const std::string LinkStateCalculatorFixture::ROUTER_C_FACE = "udp4://10.0.0.3";
Vince Lehman41b173e2015-05-07 14:13:26 -0500128
129const double LinkStateCalculatorFixture::LINK_AB_COST = 5;
130const double LinkStateCalculatorFixture::LINK_AC_COST = 10;
131const double LinkStateCalculatorFixture::LINK_BC_COST = 17;
132
133BOOST_FIXTURE_TEST_SUITE(TestLinkStateRoutingCalculator, LinkStateCalculatorFixture)
134
135BOOST_AUTO_TEST_CASE(Basic)
136{
137 LinkStateRoutingTableCalculator calculator(map.getMapSize());
Ashlesh Gawande85998a12017-12-07 22:22:13 -0600138 calculator.calculatePath(map, routingTable, conf, lsdb.getAdjLsdb());
Vince Lehman41b173e2015-05-07 14:13:26 -0500139
140 RoutingTableEntry* entryB = routingTable.findRoutingTableEntry(ROUTER_B_NAME);
141 BOOST_REQUIRE(entryB != nullptr);
142
143 // Router A should be able to get to B through B and to B through C
144 NexthopList& bHopList = entryB->getNexthopList();
145 BOOST_REQUIRE_EQUAL(bHopList.getNextHops().size(), 2);
146
147 for (const NextHop& hop : bHopList) {
148 std::string faceUri = hop.getConnectingFaceUri();
149 uint64_t cost = hop.getRouteCostAsAdjustedInteger();
150
151 BOOST_CHECK((faceUri == ROUTER_B_FACE && cost == LINK_AB_COST) ||
152 (faceUri == ROUTER_C_FACE && cost == LINK_AC_COST + LINK_BC_COST));
153
154 }
155
156 RoutingTableEntry* entryC = routingTable.findRoutingTableEntry(ROUTER_C_NAME);
157 BOOST_REQUIRE(entryC != nullptr);
158
159 // Router A should be able to get to C through C and to C through B
160 NexthopList& cHopList = entryC->getNexthopList();
161 BOOST_REQUIRE_EQUAL(cHopList.getNextHops().size(), 2);
162
163 for (const NextHop& hop : cHopList) {
164 std::string faceUri = hop.getConnectingFaceUri();
165 uint64_t cost = hop.getRouteCostAsAdjustedInteger();
166
167 BOOST_CHECK((faceUri == ROUTER_C_FACE && cost == LINK_AC_COST) ||
168 (faceUri == ROUTER_B_FACE && cost == LINK_AB_COST + LINK_BC_COST));
169 }
170}
171
172BOOST_AUTO_TEST_CASE(Asymmetric)
173{
174 // Asymmetric link cost between B and C
Nick Gordon727d4832017-10-13 18:04:25 -0500175 ndn::Name key = ndn::Name(ROUTER_B_NAME).append(std::to_string(Lsa::Type::ADJACENCY));
Ashlesh Gawande85998a12017-12-07 22:22:13 -0600176 AdjLsa* lsa = nlsr.m_lsdb.findAdjLsa(key);
Vince Lehman41b173e2015-05-07 14:13:26 -0500177 BOOST_REQUIRE(lsa != nullptr);
178
Nick Gordonc780a692017-04-27 18:03:02 -0500179 auto c = lsa->getAdl().findAdjacent(ROUTER_C_NAME);
Ashlesh Gawande85998a12017-12-07 22:22:13 -0600180 BOOST_REQUIRE(c != conf.getAdjacencyList().end());
Vince Lehman41b173e2015-05-07 14:13:26 -0500181
182 double higherLinkCost = LINK_BC_COST + 1;
183 c->setLinkCost(higherLinkCost);
184
185 // Calculation should consider the link between B and C as having cost = higherLinkCost
186 LinkStateRoutingTableCalculator calculator(map.getMapSize());
Ashlesh Gawande85998a12017-12-07 22:22:13 -0600187 calculator.calculatePath(map, routingTable, conf, lsdb.getAdjLsdb());
Vince Lehman41b173e2015-05-07 14:13:26 -0500188
189 RoutingTableEntry* entryB = routingTable.findRoutingTableEntry(ROUTER_B_NAME);
190 BOOST_REQUIRE(entryB != nullptr);
191
192 // Router A should be able to get to B through B and to B through C
193 NexthopList& bHopList = entryB->getNexthopList();
194 BOOST_REQUIRE_EQUAL(bHopList.getNextHops().size(), 2);
195
196 for (const NextHop& hop : bHopList) {
197 std::string faceUri = hop.getConnectingFaceUri();
198 uint64_t cost = hop.getRouteCostAsAdjustedInteger();
199
200 BOOST_CHECK((faceUri == ROUTER_B_FACE && cost == LINK_AB_COST) ||
201 (faceUri == ROUTER_C_FACE && cost == LINK_AC_COST + higherLinkCost));
202
203 }
204
205 RoutingTableEntry* entryC = routingTable.findRoutingTableEntry(ROUTER_C_NAME);
206 BOOST_REQUIRE(entryC != nullptr);
207
208 // Router A should be able to get to C through C and to C through B
209 NexthopList& cHopList = entryC->getNexthopList();
210 BOOST_REQUIRE_EQUAL(cHopList.getNextHops().size(), 2);
211
212 for (const NextHop& hop : cHopList) {
213 std::string faceUri = hop.getConnectingFaceUri();
214 uint64_t cost = hop.getRouteCostAsAdjustedInteger();
215
216 BOOST_CHECK((faceUri == ROUTER_C_FACE && cost == LINK_AC_COST) ||
217 (faceUri == ROUTER_B_FACE && cost == LINK_AB_COST + higherLinkCost));
218 }
219}
220
dulalsaurabd0816a32019-07-26 13:11:24 +0000221BOOST_AUTO_TEST_CASE(NonAdjacentCost)
Vince Lehman41b173e2015-05-07 14:13:26 -0500222{
223 // Asymmetric link cost between B and C
Nick Gordon727d4832017-10-13 18:04:25 -0500224 ndn::Name key = ndn::Name(ROUTER_B_NAME).append(std::to_string(Lsa::Type::ADJACENCY));
dulalsaurabd0816a32019-07-26 13:11:24 +0000225 auto lsa = nlsr.m_lsdb.findAdjLsa(key);
Vince Lehman41b173e2015-05-07 14:13:26 -0500226 BOOST_REQUIRE(lsa != nullptr);
227
Nick Gordonc780a692017-04-27 18:03:02 -0500228 auto c = lsa->getAdl().findAdjacent(ROUTER_C_NAME);
Ashlesh Gawande85998a12017-12-07 22:22:13 -0600229 BOOST_REQUIRE(c != conf.getAdjacencyList().end());
Vince Lehman41b173e2015-05-07 14:13:26 -0500230
dulalsaurabd0816a32019-07-26 13:11:24 +0000231 // Break the link between B - C by setting it to a NON_ADJACENT_COST.
232 c->setLinkCost(Adjacent::NON_ADJACENT_COST);
Vince Lehman41b173e2015-05-07 14:13:26 -0500233
234 // Calculation should consider the link between B and C as down
235 LinkStateRoutingTableCalculator calculator(map.getMapSize());
Ashlesh Gawande85998a12017-12-07 22:22:13 -0600236 calculator.calculatePath(map, routingTable, conf, lsdb.getAdjLsdb());
Vince Lehman41b173e2015-05-07 14:13:26 -0500237
238 // Router A should be able to get to B through B but not through C
239 RoutingTableEntry* entryB = routingTable.findRoutingTableEntry(ROUTER_B_NAME);
240 BOOST_REQUIRE(entryB != nullptr);
241
dulalsaurabd0816a32019-07-26 13:11:24 +0000242 auto bHopList = entryB->getNexthopList();
Vince Lehman41b173e2015-05-07 14:13:26 -0500243 BOOST_REQUIRE_EQUAL(bHopList.getNextHops().size(), 1);
244
dulalsaurabd0816a32019-07-26 13:11:24 +0000245 const auto nextHopForB = bHopList.getNextHops().begin();
Vince Lehman41b173e2015-05-07 14:13:26 -0500246
dulalsaurabd0816a32019-07-26 13:11:24 +0000247 BOOST_CHECK(nextHopForB->getConnectingFaceUri() == ROUTER_B_FACE &&
248 nextHopForB->getRouteCostAsAdjustedInteger() == LINK_AB_COST);
Vince Lehman41b173e2015-05-07 14:13:26 -0500249
250 // Router A should be able to get to C through C but not through B
dulalsaurabd0816a32019-07-26 13:11:24 +0000251 auto entryC = routingTable.findRoutingTableEntry(ROUTER_C_NAME);
Vince Lehman41b173e2015-05-07 14:13:26 -0500252 BOOST_REQUIRE(entryC != nullptr);
253
254 NexthopList& cHopList = entryC->getNexthopList();
255 BOOST_REQUIRE_EQUAL(cHopList.getNextHops().size(), 1);
256
dulalsaurabd0816a32019-07-26 13:11:24 +0000257 const auto nextHopForC = cHopList.getNextHops().begin();
Vince Lehman41b173e2015-05-07 14:13:26 -0500258
dulalsaurabd0816a32019-07-26 13:11:24 +0000259 BOOST_CHECK(nextHopForC->getConnectingFaceUri() == ROUTER_C_FACE &&
260 nextHopForC->getRouteCostAsAdjustedInteger() == LINK_AC_COST);
261}
262
263BOOST_AUTO_TEST_CASE(AsymmetricZeroCostLink)
264{
265 // Asymmetric and zero link cost between B - C, and B - A.
266 ndn::Name keyB = ndn::Name(ROUTER_B_NAME).append(std::to_string(Lsa::Type::ADJACENCY));
267 auto lsaB = nlsr.m_lsdb.findAdjLsa(keyB);
268 BOOST_REQUIRE(lsaB != nullptr);
269
270 auto c = lsaB->getAdl().findAdjacent(ROUTER_C_NAME);
271 BOOST_REQUIRE(c != conf.getAdjacencyList().end());
272 // Re-adjust link cost to 0 from B-C. However, this should not set B-C cost 0 because C-B
273 // cost is greater that 0 i.e. 17
274 c->setLinkCost(0);
275
276 auto a = lsaB->getAdl().findAdjacent(ROUTER_A_NAME);
277 BOOST_REQUIRE(a != conf.getAdjacencyList().end());
278
279 ndn::Name keyA = ndn::Name(ROUTER_A_NAME).append(std::to_string(Lsa::Type::ADJACENCY));
280 auto lsaA = nlsr.m_lsdb.findAdjLsa(keyA);
281 BOOST_REQUIRE(lsaA != nullptr);
282
283 auto b = lsaA->getAdl().findAdjacent(ROUTER_B_NAME);
284 BOOST_REQUIRE(b != conf.getAdjacencyList().end());
285
286 // Re-adjust link cost to 0 from both the direction i.e B-A and A-B
287 a->setLinkCost(0);
288 b->setLinkCost(0);
289
290 // Calculation should consider 0 link-cost between B and C
291 LinkStateRoutingTableCalculator calculator(map.getMapSize());
292 calculator.calculatePath(map, routingTable, conf, lsdb.getAdjLsdb());
293
294 // Router A should be able to get to B through B and C
295 RoutingTableEntry* entryB = routingTable.findRoutingTableEntry(ROUTER_B_NAME);
296 BOOST_REQUIRE(entryB != nullptr);
297
298 // Node can have neighbors with zero cost, so the nexthop count should be 2
299 NexthopList& bHopList = entryB->getNexthopList();
300 BOOST_REQUIRE_EQUAL(bHopList.getNextHops().size(), 2);
301
302 const auto nextHopForB = bHopList.getNextHops().begin();
303 // Check if the next hop via B is through A or not after the cost adjustment
304 BOOST_CHECK(nextHopForB->getConnectingFaceUri() == ROUTER_B_FACE &&
305 nextHopForB->getRouteCostAsAdjustedInteger() == 0);
306
307 // Router A should be able to get to C through C and B
308 auto entryC = routingTable.findRoutingTableEntry(ROUTER_C_NAME);
309 BOOST_REQUIRE(entryC != nullptr);
310
311 NexthopList& cHopList = entryC->getNexthopList();
312 BOOST_REQUIRE_EQUAL(cHopList.getNextHops().size(), 2);
313
314 const auto nextHopForC = cHopList.getNextHops().begin();
315 // Check if the nextHop from C is via A or not
316 BOOST_CHECK(nextHopForC->getConnectingFaceUri() == ROUTER_C_FACE &&
317 nextHopForC->getRouteCostAsAdjustedInteger() == LINK_AC_COST);
318
Vince Lehman41b173e2015-05-07 14:13:26 -0500319}
320
321BOOST_AUTO_TEST_SUITE_END()
322
Nick Gordonfad8e252016-08-11 14:21:38 -0500323} // namespace test
324} // namespace nlsr