blob: 40ed32f594af7a8896faab53c2bfacba5b28efef [file] [log] [blame]
Vince Lehman41b173e2015-05-07 14:13:26 -05001/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
Ashlesh Gawande0421bc62020-05-08 20:42:19 -07002/*
Junxiao Shib8752932024-01-07 15:18:46 +00003 * Copyright (c) 2014-2024, 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/>.
Ashlesh Gawande0421bc62020-05-08 20:42:19 -070020 */
Vince Lehman41b173e2015-05-07 14:13:26 -050021
22#include "route/routing-table-calculator.hpp"
23
24#include "adjacency-list.hpp"
Davide Pesavento8de8a8b2022-05-12 01:26:43 -040025#include "adjacent.hpp"
Vince Lehman41b173e2015-05-07 14:13:26 -050026#include "lsdb.hpp"
27#include "nlsr.hpp"
Junxiao Shi4eb4eae2024-02-14 12:36:57 +000028#include "route/name-map.hpp"
Vince Lehman41b173e2015-05-07 14:13:26 -050029#include "route/routing-table.hpp"
30
Davide Pesavento8de8a8b2022-05-12 01:26:43 -040031#include "tests/io-key-chain-fixture.hpp"
32#include "tests/test-common.hpp"
Vince Lehman41b173e2015-05-07 14:13:26 -050033
Davide Pesavento288141a2024-02-13 17:30:35 -050034namespace nlsr::tests {
Vince Lehman41b173e2015-05-07 14:13:26 -050035
Davide Pesavento288141a2024-02-13 17:30:35 -050036constexpr time::system_clock::time_point MAX_TIME = time::system_clock::time_point::max();
Junxiao Shi6593a432023-08-21 10:50:28 +000037static const ndn::Name ROUTER_A_NAME = "/ndn/site/%C1.Router/this-router";
38static const ndn::Name ROUTER_B_NAME = "/ndn/site/%C1.Router/b";
39static const ndn::Name ROUTER_C_NAME = "/ndn/site/%C1.Router/c";
40static const ndn::FaceUri ROUTER_A_FACE("udp4://10.0.0.1");
41static const ndn::FaceUri ROUTER_B_FACE("udp4://10.0.0.2");
42static const ndn::FaceUri ROUTER_C_FACE("udp4://10.0.0.3");
43constexpr double LINK_AB_COST = 5;
44constexpr double LINK_AC_COST = 10;
45constexpr double LINK_BC_COST = 17;
Vince Lehman41b173e2015-05-07 14:13:26 -050046
Davide Pesavento8de8a8b2022-05-12 01:26:43 -040047class LinkStateCalculatorFixture : public IoKeyChainFixture
Vince Lehman41b173e2015-05-07 14:13:26 -050048{
49public:
50 LinkStateCalculatorFixture()
Davide Pesavento8de8a8b2022-05-12 01:26:43 -040051 : face(m_io, m_keyChain)
Saurab Dulal427e0122019-11-28 11:58:02 -060052 , conf(face, m_keyChain)
Ashlesh Gawande85998a12017-12-07 22:22:13 -060053 , confProcessor(conf)
54 , nlsr(face, m_keyChain, conf)
55 , routingTable(nlsr.m_routingTable)
56 , lsdb(nlsr.m_lsdb)
Vince Lehman41b173e2015-05-07 14:13:26 -050057 {
58 setUpTopology();
59 }
60
61 // Triangle topology with routers A, B, C connected
62 void setUpTopology()
63 {
Junxiao Shi6593a432023-08-21 10:50:28 +000064 Adjacent a(ROUTER_A_NAME, ROUTER_A_FACE, 0, Adjacent::STATUS_ACTIVE, 0, 0);
65 Adjacent b(ROUTER_B_NAME, ROUTER_B_FACE, 0, Adjacent::STATUS_ACTIVE, 0, 0);
66 Adjacent c(ROUTER_C_NAME, ROUTER_C_FACE, 0, Adjacent::STATUS_ACTIVE, 0, 0);
Vince Lehman41b173e2015-05-07 14:13:26 -050067
68 // Router A
69 b.setLinkCost(LINK_AB_COST);
70 c.setLinkCost(LINK_AC_COST);
71
Ashlesh Gawande85998a12017-12-07 22:22:13 -060072 AdjacencyList& adjacencyListA = conf.getAdjacencyList();
Vince Lehman41b173e2015-05-07 14:13:26 -050073 adjacencyListA.insert(b);
74 adjacencyListA.insert(c);
75
Junxiao Shib8752932024-01-07 15:18:46 +000076 AdjLsa adjA(a.getName(), 1, MAX_TIME, adjacencyListA);
Ashlesh Gawande57a87172020-05-09 19:47:06 -070077 lsdb.installLsa(std::make_shared<AdjLsa>(adjA));
Vince Lehman41b173e2015-05-07 14:13:26 -050078
79 // Router B
80 a.setLinkCost(LINK_AB_COST);
81 c.setLinkCost(LINK_BC_COST);
82
83 AdjacencyList adjacencyListB;
84 adjacencyListB.insert(a);
85 adjacencyListB.insert(c);
86
Junxiao Shib8752932024-01-07 15:18:46 +000087 AdjLsa adjB(b.getName(), 1, MAX_TIME, adjacencyListB);
Ashlesh Gawande57a87172020-05-09 19:47:06 -070088 lsdb.installLsa(std::make_shared<AdjLsa>(adjB));
Vince Lehman41b173e2015-05-07 14:13:26 -050089
90 // Router C
91 a.setLinkCost(LINK_AC_COST);
92 b.setLinkCost(LINK_BC_COST);
93
94 AdjacencyList adjacencyListC;
95 adjacencyListC.insert(a);
96 adjacencyListC.insert(b);
97
Junxiao Shib8752932024-01-07 15:18:46 +000098 AdjLsa adjC(c.getName(), 1, MAX_TIME, adjacencyListC);
Ashlesh Gawande57a87172020-05-09 19:47:06 -070099 lsdb.installLsa(std::make_shared<AdjLsa>(adjC));
Vince Lehman41b173e2015-05-07 14:13:26 -0500100
Ashlesh Gawande57a87172020-05-09 19:47:06 -0700101 auto lsaRange = lsdb.getLsdbIterator<AdjLsa>();
Junxiao Shi4eb4eae2024-02-14 12:36:57 +0000102 map = NameMap::createFromAdjLsdb(lsaRange.first, lsaRange.second);
Vince Lehman41b173e2015-05-07 14:13:26 -0500103 }
104
105public:
Junxiao Shi43f37a02023-08-09 00:09:00 +0000106 ndn::DummyClientFace face;
Ashlesh Gawande85998a12017-12-07 22:22:13 -0600107 ConfParameter conf;
108 DummyConfFileProcessor confProcessor;
Vince Lehman41b173e2015-05-07 14:13:26 -0500109 Nlsr nlsr;
Junxiao Shi4eb4eae2024-02-14 12:36:57 +0000110 NameMap map;
Vince Lehman41b173e2015-05-07 14:13:26 -0500111
112 RoutingTable& routingTable;
113 Lsdb& lsdb;
Vince Lehman41b173e2015-05-07 14:13:26 -0500114};
115
Vince Lehman41b173e2015-05-07 14:13:26 -0500116BOOST_FIXTURE_TEST_SUITE(TestLinkStateRoutingCalculator, LinkStateCalculatorFixture)
117
118BOOST_AUTO_TEST_CASE(Basic)
119{
Junxiao Shid6922b52024-01-14 19:50:34 +0000120 LinkStateRoutingTableCalculator calculator(map.size());
Ashlesh Gawande57a87172020-05-09 19:47:06 -0700121 calculator.calculatePath(map, routingTable, conf, lsdb);
Vince Lehman41b173e2015-05-07 14:13:26 -0500122
123 RoutingTableEntry* entryB = routingTable.findRoutingTableEntry(ROUTER_B_NAME);
124 BOOST_REQUIRE(entryB != nullptr);
125
126 // Router A should be able to get to B through B and to B through C
127 NexthopList& bHopList = entryB->getNexthopList();
128 BOOST_REQUIRE_EQUAL(bHopList.getNextHops().size(), 2);
129
130 for (const NextHop& hop : bHopList) {
Junxiao Shi6593a432023-08-21 10:50:28 +0000131 auto faceUri = hop.getConnectingFaceUri();
Vince Lehman41b173e2015-05-07 14:13:26 -0500132 uint64_t cost = hop.getRouteCostAsAdjustedInteger();
133
134 BOOST_CHECK((faceUri == ROUTER_B_FACE && cost == LINK_AB_COST) ||
135 (faceUri == ROUTER_C_FACE && cost == LINK_AC_COST + LINK_BC_COST));
136
137 }
138
139 RoutingTableEntry* entryC = routingTable.findRoutingTableEntry(ROUTER_C_NAME);
140 BOOST_REQUIRE(entryC != nullptr);
141
142 // Router A should be able to get to C through C and to C through B
143 NexthopList& cHopList = entryC->getNexthopList();
144 BOOST_REQUIRE_EQUAL(cHopList.getNextHops().size(), 2);
145
146 for (const NextHop& hop : cHopList) {
Junxiao Shi6593a432023-08-21 10:50:28 +0000147 auto faceUri = hop.getConnectingFaceUri();
Vince Lehman41b173e2015-05-07 14:13:26 -0500148 uint64_t cost = hop.getRouteCostAsAdjustedInteger();
149
150 BOOST_CHECK((faceUri == ROUTER_C_FACE && cost == LINK_AC_COST) ||
151 (faceUri == ROUTER_B_FACE && cost == LINK_AB_COST + LINK_BC_COST));
152 }
153}
154
155BOOST_AUTO_TEST_CASE(Asymmetric)
156{
157 // Asymmetric link cost between B and C
Ashlesh Gawande57a87172020-05-09 19:47:06 -0700158 auto lsa = nlsr.m_lsdb.findLsa<AdjLsa>(ndn::Name(ROUTER_B_NAME));
Vince Lehman41b173e2015-05-07 14:13:26 -0500159 BOOST_REQUIRE(lsa != nullptr);
160
Ashlesh Gawande0db4d4d2020-02-05 20:30:02 -0800161 auto c = lsa->m_adl.findAdjacent(ROUTER_C_NAME);
Ashlesh Gawande85998a12017-12-07 22:22:13 -0600162 BOOST_REQUIRE(c != conf.getAdjacencyList().end());
Vince Lehman41b173e2015-05-07 14:13:26 -0500163
164 double higherLinkCost = LINK_BC_COST + 1;
165 c->setLinkCost(higherLinkCost);
166
167 // Calculation should consider the link between B and C as having cost = higherLinkCost
Junxiao Shid6922b52024-01-14 19:50:34 +0000168 LinkStateRoutingTableCalculator calculator(map.size());
Ashlesh Gawande57a87172020-05-09 19:47:06 -0700169 calculator.calculatePath(map, routingTable, conf, lsdb);
Vince Lehman41b173e2015-05-07 14:13:26 -0500170
171 RoutingTableEntry* entryB = routingTable.findRoutingTableEntry(ROUTER_B_NAME);
172 BOOST_REQUIRE(entryB != nullptr);
173
174 // Router A should be able to get to B through B and to B through C
175 NexthopList& bHopList = entryB->getNexthopList();
176 BOOST_REQUIRE_EQUAL(bHopList.getNextHops().size(), 2);
177
178 for (const NextHop& hop : bHopList) {
Junxiao Shi6593a432023-08-21 10:50:28 +0000179 auto faceUri = hop.getConnectingFaceUri();
Vince Lehman41b173e2015-05-07 14:13:26 -0500180 uint64_t cost = hop.getRouteCostAsAdjustedInteger();
181
182 BOOST_CHECK((faceUri == ROUTER_B_FACE && cost == LINK_AB_COST) ||
183 (faceUri == ROUTER_C_FACE && cost == LINK_AC_COST + higherLinkCost));
184
185 }
186
187 RoutingTableEntry* entryC = routingTable.findRoutingTableEntry(ROUTER_C_NAME);
188 BOOST_REQUIRE(entryC != nullptr);
189
190 // Router A should be able to get to C through C and to C through B
191 NexthopList& cHopList = entryC->getNexthopList();
192 BOOST_REQUIRE_EQUAL(cHopList.getNextHops().size(), 2);
193
194 for (const NextHop& hop : cHopList) {
Junxiao Shi6593a432023-08-21 10:50:28 +0000195 auto faceUri = hop.getConnectingFaceUri();
Vince Lehman41b173e2015-05-07 14:13:26 -0500196 uint64_t cost = hop.getRouteCostAsAdjustedInteger();
197
198 BOOST_CHECK((faceUri == ROUTER_C_FACE && cost == LINK_AC_COST) ||
199 (faceUri == ROUTER_B_FACE && cost == LINK_AB_COST + higherLinkCost));
200 }
201}
202
dulalsaurabd0816a32019-07-26 13:11:24 +0000203BOOST_AUTO_TEST_CASE(NonAdjacentCost)
Vince Lehman41b173e2015-05-07 14:13:26 -0500204{
205 // Asymmetric link cost between B and C
Ashlesh Gawande57a87172020-05-09 19:47:06 -0700206 auto lsa = nlsr.m_lsdb.findLsa<AdjLsa>(ROUTER_B_NAME);
Vince Lehman41b173e2015-05-07 14:13:26 -0500207 BOOST_REQUIRE(lsa != nullptr);
208
Ashlesh Gawande0db4d4d2020-02-05 20:30:02 -0800209 auto c = lsa->m_adl.findAdjacent(ROUTER_C_NAME);
Ashlesh Gawande85998a12017-12-07 22:22:13 -0600210 BOOST_REQUIRE(c != conf.getAdjacencyList().end());
Vince Lehman41b173e2015-05-07 14:13:26 -0500211
dulalsaurabd0816a32019-07-26 13:11:24 +0000212 // Break the link between B - C by setting it to a NON_ADJACENT_COST.
213 c->setLinkCost(Adjacent::NON_ADJACENT_COST);
Vince Lehman41b173e2015-05-07 14:13:26 -0500214
215 // Calculation should consider the link between B and C as down
Junxiao Shid6922b52024-01-14 19:50:34 +0000216 LinkStateRoutingTableCalculator calculator(map.size());
Ashlesh Gawande57a87172020-05-09 19:47:06 -0700217 calculator.calculatePath(map, routingTable, conf, lsdb);
Vince Lehman41b173e2015-05-07 14:13:26 -0500218
219 // Router A should be able to get to B through B but not through C
220 RoutingTableEntry* entryB = routingTable.findRoutingTableEntry(ROUTER_B_NAME);
221 BOOST_REQUIRE(entryB != nullptr);
222
dulalsaurabd0816a32019-07-26 13:11:24 +0000223 auto bHopList = entryB->getNexthopList();
Vince Lehman41b173e2015-05-07 14:13:26 -0500224 BOOST_REQUIRE_EQUAL(bHopList.getNextHops().size(), 1);
225
dulalsaurabd0816a32019-07-26 13:11:24 +0000226 const auto nextHopForB = bHopList.getNextHops().begin();
Vince Lehman41b173e2015-05-07 14:13:26 -0500227
dulalsaurabd0816a32019-07-26 13:11:24 +0000228 BOOST_CHECK(nextHopForB->getConnectingFaceUri() == ROUTER_B_FACE &&
229 nextHopForB->getRouteCostAsAdjustedInteger() == LINK_AB_COST);
Vince Lehman41b173e2015-05-07 14:13:26 -0500230
231 // Router A should be able to get to C through C but not through B
dulalsaurabd0816a32019-07-26 13:11:24 +0000232 auto entryC = routingTable.findRoutingTableEntry(ROUTER_C_NAME);
Vince Lehman41b173e2015-05-07 14:13:26 -0500233 BOOST_REQUIRE(entryC != nullptr);
234
235 NexthopList& cHopList = entryC->getNexthopList();
236 BOOST_REQUIRE_EQUAL(cHopList.getNextHops().size(), 1);
237
dulalsaurabd0816a32019-07-26 13:11:24 +0000238 const auto nextHopForC = cHopList.getNextHops().begin();
Vince Lehman41b173e2015-05-07 14:13:26 -0500239
dulalsaurabd0816a32019-07-26 13:11:24 +0000240 BOOST_CHECK(nextHopForC->getConnectingFaceUri() == ROUTER_C_FACE &&
241 nextHopForC->getRouteCostAsAdjustedInteger() == LINK_AC_COST);
242}
243
244BOOST_AUTO_TEST_CASE(AsymmetricZeroCostLink)
245{
246 // Asymmetric and zero link cost between B - C, and B - A.
Ashlesh Gawande57a87172020-05-09 19:47:06 -0700247 auto lsaB = nlsr.m_lsdb.findLsa<AdjLsa>(ROUTER_B_NAME);
dulalsaurabd0816a32019-07-26 13:11:24 +0000248 BOOST_REQUIRE(lsaB != nullptr);
249
Ashlesh Gawande0db4d4d2020-02-05 20:30:02 -0800250 auto c = lsaB->m_adl.findAdjacent(ROUTER_C_NAME);
dulalsaurabd0816a32019-07-26 13:11:24 +0000251 BOOST_REQUIRE(c != conf.getAdjacencyList().end());
252 // Re-adjust link cost to 0 from B-C. However, this should not set B-C cost 0 because C-B
253 // cost is greater that 0 i.e. 17
254 c->setLinkCost(0);
255
Ashlesh Gawande0db4d4d2020-02-05 20:30:02 -0800256 auto a = lsaB->m_adl.findAdjacent(ROUTER_A_NAME);
dulalsaurabd0816a32019-07-26 13:11:24 +0000257 BOOST_REQUIRE(a != conf.getAdjacencyList().end());
258
Ashlesh Gawande57a87172020-05-09 19:47:06 -0700259 auto lsaA = nlsr.m_lsdb.findLsa<AdjLsa>(ROUTER_A_NAME);
dulalsaurabd0816a32019-07-26 13:11:24 +0000260 BOOST_REQUIRE(lsaA != nullptr);
261
Ashlesh Gawande0db4d4d2020-02-05 20:30:02 -0800262 auto b = lsaA->m_adl.findAdjacent(ROUTER_B_NAME);
dulalsaurabd0816a32019-07-26 13:11:24 +0000263 BOOST_REQUIRE(b != conf.getAdjacencyList().end());
264
265 // Re-adjust link cost to 0 from both the direction i.e B-A and A-B
266 a->setLinkCost(0);
267 b->setLinkCost(0);
268
269 // Calculation should consider 0 link-cost between B and C
Junxiao Shid6922b52024-01-14 19:50:34 +0000270 LinkStateRoutingTableCalculator calculator(map.size());
Ashlesh Gawande57a87172020-05-09 19:47:06 -0700271 calculator.calculatePath(map, routingTable, conf, lsdb);
dulalsaurabd0816a32019-07-26 13:11:24 +0000272
273 // Router A should be able to get to B through B and C
274 RoutingTableEntry* entryB = routingTable.findRoutingTableEntry(ROUTER_B_NAME);
275 BOOST_REQUIRE(entryB != nullptr);
276
277 // Node can have neighbors with zero cost, so the nexthop count should be 2
278 NexthopList& bHopList = entryB->getNexthopList();
279 BOOST_REQUIRE_EQUAL(bHopList.getNextHops().size(), 2);
280
281 const auto nextHopForB = bHopList.getNextHops().begin();
282 // Check if the next hop via B is through A or not after the cost adjustment
283 BOOST_CHECK(nextHopForB->getConnectingFaceUri() == ROUTER_B_FACE &&
284 nextHopForB->getRouteCostAsAdjustedInteger() == 0);
285
286 // Router A should be able to get to C through C and B
287 auto entryC = routingTable.findRoutingTableEntry(ROUTER_C_NAME);
288 BOOST_REQUIRE(entryC != nullptr);
289
290 NexthopList& cHopList = entryC->getNexthopList();
291 BOOST_REQUIRE_EQUAL(cHopList.getNextHops().size(), 2);
292
293 const auto nextHopForC = cHopList.getNextHops().begin();
294 // Check if the nextHop from C is via A or not
295 BOOST_CHECK(nextHopForC->getConnectingFaceUri() == ROUTER_C_FACE &&
296 nextHopForC->getRouteCostAsAdjustedInteger() == LINK_AC_COST);
297
Vince Lehman41b173e2015-05-07 14:13:26 -0500298}
299
300BOOST_AUTO_TEST_SUITE_END()
301
Davide Pesavento288141a2024-02-13 17:30:35 -0500302} // namespace nlsr::tests