blob: dce29c537860ab085e086be56c545dbad8fb421e [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
Junxiao Shiaead5882024-02-21 12:32:02 +000022#include "route/routing-calculator.hpp"
Vince Lehman41b173e2015-05-07 14:13:26 -050023
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
Junxiao Shiaead5882024-02-21 12:32:02 +0000116BOOST_FIXTURE_TEST_SUITE(TestRoutingCalculatorLinkState, LinkStateCalculatorFixture)
Vince Lehman41b173e2015-05-07 14:13:26 -0500117
118BOOST_AUTO_TEST_CASE(Basic)
119{
Junxiao Shiaead5882024-02-21 12:32:02 +0000120 calculateLinkStateRoutingPath(map, routingTable, conf, lsdb);
Vince Lehman41b173e2015-05-07 14:13:26 -0500121
122 RoutingTableEntry* entryB = routingTable.findRoutingTableEntry(ROUTER_B_NAME);
123 BOOST_REQUIRE(entryB != nullptr);
124
125 // Router A should be able to get to B through B and to B through C
126 NexthopList& bHopList = entryB->getNexthopList();
127 BOOST_REQUIRE_EQUAL(bHopList.getNextHops().size(), 2);
128
129 for (const NextHop& hop : bHopList) {
Junxiao Shi6593a432023-08-21 10:50:28 +0000130 auto faceUri = hop.getConnectingFaceUri();
Vince Lehman41b173e2015-05-07 14:13:26 -0500131 uint64_t cost = hop.getRouteCostAsAdjustedInteger();
132
133 BOOST_CHECK((faceUri == ROUTER_B_FACE && cost == LINK_AB_COST) ||
134 (faceUri == ROUTER_C_FACE && cost == LINK_AC_COST + LINK_BC_COST));
135
136 }
137
138 RoutingTableEntry* entryC = routingTable.findRoutingTableEntry(ROUTER_C_NAME);
139 BOOST_REQUIRE(entryC != nullptr);
140
141 // Router A should be able to get to C through C and to C through B
142 NexthopList& cHopList = entryC->getNexthopList();
143 BOOST_REQUIRE_EQUAL(cHopList.getNextHops().size(), 2);
144
145 for (const NextHop& hop : cHopList) {
Junxiao Shi6593a432023-08-21 10:50:28 +0000146 auto faceUri = hop.getConnectingFaceUri();
Vince Lehman41b173e2015-05-07 14:13:26 -0500147 uint64_t cost = hop.getRouteCostAsAdjustedInteger();
148
149 BOOST_CHECK((faceUri == ROUTER_C_FACE && cost == LINK_AC_COST) ||
150 (faceUri == ROUTER_B_FACE && cost == LINK_AB_COST + LINK_BC_COST));
151 }
152}
153
154BOOST_AUTO_TEST_CASE(Asymmetric)
155{
156 // Asymmetric link cost between B and C
Ashlesh Gawande57a87172020-05-09 19:47:06 -0700157 auto lsa = nlsr.m_lsdb.findLsa<AdjLsa>(ndn::Name(ROUTER_B_NAME));
Vince Lehman41b173e2015-05-07 14:13:26 -0500158 BOOST_REQUIRE(lsa != nullptr);
159
Ashlesh Gawande0db4d4d2020-02-05 20:30:02 -0800160 auto c = lsa->m_adl.findAdjacent(ROUTER_C_NAME);
Ashlesh Gawande85998a12017-12-07 22:22:13 -0600161 BOOST_REQUIRE(c != conf.getAdjacencyList().end());
Vince Lehman41b173e2015-05-07 14:13:26 -0500162
163 double higherLinkCost = LINK_BC_COST + 1;
164 c->setLinkCost(higherLinkCost);
165
166 // Calculation should consider the link between B and C as having cost = higherLinkCost
Junxiao Shiaead5882024-02-21 12:32:02 +0000167 calculateLinkStateRoutingPath(map, routingTable, conf, lsdb);
Vince Lehman41b173e2015-05-07 14:13:26 -0500168
169 RoutingTableEntry* entryB = routingTable.findRoutingTableEntry(ROUTER_B_NAME);
170 BOOST_REQUIRE(entryB != nullptr);
171
172 // Router A should be able to get to B through B and to B through C
173 NexthopList& bHopList = entryB->getNexthopList();
174 BOOST_REQUIRE_EQUAL(bHopList.getNextHops().size(), 2);
175
176 for (const NextHop& hop : bHopList) {
Junxiao Shi6593a432023-08-21 10:50:28 +0000177 auto faceUri = hop.getConnectingFaceUri();
Vince Lehman41b173e2015-05-07 14:13:26 -0500178 uint64_t cost = hop.getRouteCostAsAdjustedInteger();
179
180 BOOST_CHECK((faceUri == ROUTER_B_FACE && cost == LINK_AB_COST) ||
181 (faceUri == ROUTER_C_FACE && cost == LINK_AC_COST + higherLinkCost));
182
183 }
184
185 RoutingTableEntry* entryC = routingTable.findRoutingTableEntry(ROUTER_C_NAME);
186 BOOST_REQUIRE(entryC != nullptr);
187
188 // Router A should be able to get to C through C and to C through B
189 NexthopList& cHopList = entryC->getNexthopList();
190 BOOST_REQUIRE_EQUAL(cHopList.getNextHops().size(), 2);
191
192 for (const NextHop& hop : cHopList) {
Junxiao Shi6593a432023-08-21 10:50:28 +0000193 auto faceUri = hop.getConnectingFaceUri();
Vince Lehman41b173e2015-05-07 14:13:26 -0500194 uint64_t cost = hop.getRouteCostAsAdjustedInteger();
195
196 BOOST_CHECK((faceUri == ROUTER_C_FACE && cost == LINK_AC_COST) ||
197 (faceUri == ROUTER_B_FACE && cost == LINK_AB_COST + higherLinkCost));
198 }
199}
200
dulalsaurabd0816a32019-07-26 13:11:24 +0000201BOOST_AUTO_TEST_CASE(NonAdjacentCost)
Vince Lehman41b173e2015-05-07 14:13:26 -0500202{
203 // Asymmetric link cost between B and C
Ashlesh Gawande57a87172020-05-09 19:47:06 -0700204 auto lsa = nlsr.m_lsdb.findLsa<AdjLsa>(ROUTER_B_NAME);
Vince Lehman41b173e2015-05-07 14:13:26 -0500205 BOOST_REQUIRE(lsa != nullptr);
206
Ashlesh Gawande0db4d4d2020-02-05 20:30:02 -0800207 auto c = lsa->m_adl.findAdjacent(ROUTER_C_NAME);
Ashlesh Gawande85998a12017-12-07 22:22:13 -0600208 BOOST_REQUIRE(c != conf.getAdjacencyList().end());
Vince Lehman41b173e2015-05-07 14:13:26 -0500209
dulalsaurabd0816a32019-07-26 13:11:24 +0000210 // Break the link between B - C by setting it to a NON_ADJACENT_COST.
211 c->setLinkCost(Adjacent::NON_ADJACENT_COST);
Vince Lehman41b173e2015-05-07 14:13:26 -0500212
213 // Calculation should consider the link between B and C as down
Junxiao Shiaead5882024-02-21 12:32:02 +0000214 calculateLinkStateRoutingPath(map, routingTable, conf, lsdb);
Vince Lehman41b173e2015-05-07 14:13:26 -0500215
216 // Router A should be able to get to B through B but not through C
217 RoutingTableEntry* entryB = routingTable.findRoutingTableEntry(ROUTER_B_NAME);
218 BOOST_REQUIRE(entryB != nullptr);
219
dulalsaurabd0816a32019-07-26 13:11:24 +0000220 auto bHopList = entryB->getNexthopList();
Vince Lehman41b173e2015-05-07 14:13:26 -0500221 BOOST_REQUIRE_EQUAL(bHopList.getNextHops().size(), 1);
222
dulalsaurabd0816a32019-07-26 13:11:24 +0000223 const auto nextHopForB = bHopList.getNextHops().begin();
Vince Lehman41b173e2015-05-07 14:13:26 -0500224
dulalsaurabd0816a32019-07-26 13:11:24 +0000225 BOOST_CHECK(nextHopForB->getConnectingFaceUri() == ROUTER_B_FACE &&
226 nextHopForB->getRouteCostAsAdjustedInteger() == LINK_AB_COST);
Vince Lehman41b173e2015-05-07 14:13:26 -0500227
228 // Router A should be able to get to C through C but not through B
dulalsaurabd0816a32019-07-26 13:11:24 +0000229 auto entryC = routingTable.findRoutingTableEntry(ROUTER_C_NAME);
Vince Lehman41b173e2015-05-07 14:13:26 -0500230 BOOST_REQUIRE(entryC != nullptr);
231
232 NexthopList& cHopList = entryC->getNexthopList();
233 BOOST_REQUIRE_EQUAL(cHopList.getNextHops().size(), 1);
234
dulalsaurabd0816a32019-07-26 13:11:24 +0000235 const auto nextHopForC = cHopList.getNextHops().begin();
Vince Lehman41b173e2015-05-07 14:13:26 -0500236
dulalsaurabd0816a32019-07-26 13:11:24 +0000237 BOOST_CHECK(nextHopForC->getConnectingFaceUri() == ROUTER_C_FACE &&
238 nextHopForC->getRouteCostAsAdjustedInteger() == LINK_AC_COST);
239}
240
241BOOST_AUTO_TEST_CASE(AsymmetricZeroCostLink)
242{
243 // Asymmetric and zero link cost between B - C, and B - A.
Ashlesh Gawande57a87172020-05-09 19:47:06 -0700244 auto lsaB = nlsr.m_lsdb.findLsa<AdjLsa>(ROUTER_B_NAME);
dulalsaurabd0816a32019-07-26 13:11:24 +0000245 BOOST_REQUIRE(lsaB != nullptr);
246
Ashlesh Gawande0db4d4d2020-02-05 20:30:02 -0800247 auto c = lsaB->m_adl.findAdjacent(ROUTER_C_NAME);
dulalsaurabd0816a32019-07-26 13:11:24 +0000248 BOOST_REQUIRE(c != conf.getAdjacencyList().end());
249 // Re-adjust link cost to 0 from B-C. However, this should not set B-C cost 0 because C-B
250 // cost is greater that 0 i.e. 17
251 c->setLinkCost(0);
252
Ashlesh Gawande0db4d4d2020-02-05 20:30:02 -0800253 auto a = lsaB->m_adl.findAdjacent(ROUTER_A_NAME);
dulalsaurabd0816a32019-07-26 13:11:24 +0000254 BOOST_REQUIRE(a != conf.getAdjacencyList().end());
255
Ashlesh Gawande57a87172020-05-09 19:47:06 -0700256 auto lsaA = nlsr.m_lsdb.findLsa<AdjLsa>(ROUTER_A_NAME);
dulalsaurabd0816a32019-07-26 13:11:24 +0000257 BOOST_REQUIRE(lsaA != nullptr);
258
Ashlesh Gawande0db4d4d2020-02-05 20:30:02 -0800259 auto b = lsaA->m_adl.findAdjacent(ROUTER_B_NAME);
dulalsaurabd0816a32019-07-26 13:11:24 +0000260 BOOST_REQUIRE(b != conf.getAdjacencyList().end());
261
262 // Re-adjust link cost to 0 from both the direction i.e B-A and A-B
263 a->setLinkCost(0);
264 b->setLinkCost(0);
265
266 // Calculation should consider 0 link-cost between B and C
Junxiao Shiaead5882024-02-21 12:32:02 +0000267 calculateLinkStateRoutingPath(map, routingTable, conf, lsdb);
dulalsaurabd0816a32019-07-26 13:11:24 +0000268
269 // Router A should be able to get to B through B and C
270 RoutingTableEntry* entryB = routingTable.findRoutingTableEntry(ROUTER_B_NAME);
271 BOOST_REQUIRE(entryB != nullptr);
272
273 // Node can have neighbors with zero cost, so the nexthop count should be 2
274 NexthopList& bHopList = entryB->getNexthopList();
275 BOOST_REQUIRE_EQUAL(bHopList.getNextHops().size(), 2);
276
277 const auto nextHopForB = bHopList.getNextHops().begin();
278 // Check if the next hop via B is through A or not after the cost adjustment
279 BOOST_CHECK(nextHopForB->getConnectingFaceUri() == ROUTER_B_FACE &&
280 nextHopForB->getRouteCostAsAdjustedInteger() == 0);
281
282 // Router A should be able to get to C through C and B
283 auto entryC = routingTable.findRoutingTableEntry(ROUTER_C_NAME);
284 BOOST_REQUIRE(entryC != nullptr);
285
286 NexthopList& cHopList = entryC->getNexthopList();
287 BOOST_REQUIRE_EQUAL(cHopList.getNextHops().size(), 2);
288
289 const auto nextHopForC = cHopList.getNextHops().begin();
290 // Check if the nextHop from C is via A or not
291 BOOST_CHECK(nextHopForC->getConnectingFaceUri() == ROUTER_C_FACE &&
292 nextHopForC->getRouteCostAsAdjustedInteger() == LINK_AC_COST);
293
Vince Lehman41b173e2015-05-07 14:13:26 -0500294}
295
296BOOST_AUTO_TEST_SUITE_END()
297
Davide Pesavento288141a2024-02-13 17:30:35 -0500298} // namespace nlsr::tests