blob: c6fafd0fec93f775f916da26ce541ba319a70812 [file] [log] [blame]
Vince Lehman41b173e2015-05-07 14:13:26 -05001/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
2/**
dmcoomescf8d0ed2017-02-21 11:39:01 -06003 * Copyright (c) 2014-2018, 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"
31
32#include <ndn-cxx/util/dummy-client-face.hpp>
33
34namespace nlsr {
35namespace test {
36
37static const ndn::time::system_clock::TimePoint MAX_TIME =
38 ndn::time::system_clock::TimePoint::max();
39
40class LinkStateCalculatorFixture : public BaseFixture
41{
42public:
43 LinkStateCalculatorFixture()
Muktadir Chowdhuryf04f9892017-08-20 20:42:56 -050044 : face(m_ioService, m_keyChain)
45 , nlsr(m_ioService, m_scheduler, face, m_keyChain)
Vince Lehman41b173e2015-05-07 14:13:26 -050046 , routingTable(nlsr.getRoutingTable())
47 , lsdb(nlsr.getLsdb())
48 {
49 setUpTopology();
50 }
51
52 // Triangle topology with routers A, B, C connected
53 void setUpTopology()
54 {
Vince Lehman41b173e2015-05-07 14:13:26 -050055 ConfParameter& conf = nlsr.getConfParameter();
56 conf.setNetwork("/ndn");
57 conf.setSiteName("/router");
58 conf.setRouterName("/a");
59 conf.buildRouterPrefix();
60
Muktadir Chowdhuryf04f9892017-08-20 20:42:56 -050061 Adjacent a(ROUTER_A_NAME, ndn::FaceUri(ROUTER_A_FACE), 0, Adjacent::STATUS_ACTIVE, 0, 0);
62 Adjacent b(ROUTER_B_NAME, ndn::FaceUri(ROUTER_B_FACE), 0, Adjacent::STATUS_ACTIVE, 0, 0);
63 Adjacent c(ROUTER_C_NAME, ndn::FaceUri(ROUTER_C_FACE), 0, Adjacent::STATUS_ACTIVE, 0, 0);
Vince Lehman41b173e2015-05-07 14:13:26 -050064
65 // Router A
66 b.setLinkCost(LINK_AB_COST);
67 c.setLinkCost(LINK_AC_COST);
68
69 AdjacencyList& adjacencyListA = nlsr.getAdjacencyList();
70 adjacencyListA.insert(b);
71 adjacencyListA.insert(c);
72
Ashlesh Gawanded02c3882015-12-29 16:02:51 -060073 AdjLsa adjA(a.getName(), 1, MAX_TIME, 2, adjacencyListA);
Vince Lehman41b173e2015-05-07 14:13:26 -050074 lsdb.installAdjLsa(adjA);
75
76 // Router B
77 a.setLinkCost(LINK_AB_COST);
78 c.setLinkCost(LINK_BC_COST);
79
80 AdjacencyList adjacencyListB;
81 adjacencyListB.insert(a);
82 adjacencyListB.insert(c);
83
Ashlesh Gawanded02c3882015-12-29 16:02:51 -060084 AdjLsa adjB(b.getName(), 1, MAX_TIME, 2, adjacencyListB);
Vince Lehman41b173e2015-05-07 14:13:26 -050085 lsdb.installAdjLsa(adjB);
86
87 // Router C
88 a.setLinkCost(LINK_AC_COST);
89 b.setLinkCost(LINK_BC_COST);
90
91 AdjacencyList adjacencyListC;
92 adjacencyListC.insert(a);
93 adjacencyListC.insert(b);
94
Ashlesh Gawanded02c3882015-12-29 16:02:51 -060095 AdjLsa adjC(c.getName(), 1, MAX_TIME, 2, adjacencyListC);
Vince Lehman41b173e2015-05-07 14:13:26 -050096 lsdb.installAdjLsa(adjC);
97
Nick Gordon22b5c952017-08-10 17:48:15 -050098 map.createFromAdjLsdb(lsdb.getAdjLsdb().begin(), lsdb.getAdjLsdb().end());
Vince Lehman41b173e2015-05-07 14:13:26 -050099 }
100
101public:
Muktadir Chowdhuryf04f9892017-08-20 20:42:56 -0500102 ndn::util::DummyClientFace face;
Vince Lehman41b173e2015-05-07 14:13:26 -0500103 Nlsr nlsr;
104 Map map;
105
106 RoutingTable& routingTable;
107 Lsdb& lsdb;
108
109 static const ndn::Name ROUTER_A_NAME;
110 static const ndn::Name ROUTER_B_NAME;
111 static const ndn::Name ROUTER_C_NAME;
112
113 static const std::string ROUTER_A_FACE;
114 static const std::string ROUTER_B_FACE;
115 static const std::string ROUTER_C_FACE;
116
117 static const double LINK_AB_COST;
118 static const double LINK_AC_COST;
119 static const double LINK_BC_COST;
120};
121
122const ndn::Name LinkStateCalculatorFixture::ROUTER_A_NAME = "/ndn/router/a";
123const ndn::Name LinkStateCalculatorFixture::ROUTER_B_NAME = "/ndn/router/b";
124const ndn::Name LinkStateCalculatorFixture::ROUTER_C_NAME = "/ndn/router/c";
125
Nick Gordone9733ed2017-04-26 10:48:39 -0500126const std::string LinkStateCalculatorFixture::ROUTER_A_FACE = "udp4://10.0.0.1";
127const std::string LinkStateCalculatorFixture::ROUTER_B_FACE = "udp4://10.0.0.2";
128const std::string LinkStateCalculatorFixture::ROUTER_C_FACE = "udp4://10.0.0.3";
Vince Lehman41b173e2015-05-07 14:13:26 -0500129
130const double LinkStateCalculatorFixture::LINK_AB_COST = 5;
131const double LinkStateCalculatorFixture::LINK_AC_COST = 10;
132const double LinkStateCalculatorFixture::LINK_BC_COST = 17;
133
134BOOST_FIXTURE_TEST_SUITE(TestLinkStateRoutingCalculator, LinkStateCalculatorFixture)
135
136BOOST_AUTO_TEST_CASE(Basic)
137{
138 LinkStateRoutingTableCalculator calculator(map.getMapSize());
139 calculator.calculatePath(map, routingTable, nlsr);
140
141 RoutingTableEntry* entryB = routingTable.findRoutingTableEntry(ROUTER_B_NAME);
142 BOOST_REQUIRE(entryB != nullptr);
143
144 // Router A should be able to get to B through B and to B through C
145 NexthopList& bHopList = entryB->getNexthopList();
146 BOOST_REQUIRE_EQUAL(bHopList.getNextHops().size(), 2);
147
148 for (const NextHop& hop : bHopList) {
149 std::string faceUri = hop.getConnectingFaceUri();
150 uint64_t cost = hop.getRouteCostAsAdjustedInteger();
151
152 BOOST_CHECK((faceUri == ROUTER_B_FACE && cost == LINK_AB_COST) ||
153 (faceUri == ROUTER_C_FACE && cost == LINK_AC_COST + LINK_BC_COST));
154
155 }
156
157 RoutingTableEntry* entryC = routingTable.findRoutingTableEntry(ROUTER_C_NAME);
158 BOOST_REQUIRE(entryC != nullptr);
159
160 // Router A should be able to get to C through C and to C through B
161 NexthopList& cHopList = entryC->getNexthopList();
162 BOOST_REQUIRE_EQUAL(cHopList.getNextHops().size(), 2);
163
164 for (const NextHop& hop : cHopList) {
165 std::string faceUri = hop.getConnectingFaceUri();
166 uint64_t cost = hop.getRouteCostAsAdjustedInteger();
167
168 BOOST_CHECK((faceUri == ROUTER_C_FACE && cost == LINK_AC_COST) ||
169 (faceUri == ROUTER_B_FACE && cost == LINK_AB_COST + LINK_BC_COST));
170 }
171}
172
173BOOST_AUTO_TEST_CASE(Asymmetric)
174{
175 // Asymmetric link cost between B and C
Nick Gordon727d4832017-10-13 18:04:25 -0500176 ndn::Name key = ndn::Name(ROUTER_B_NAME).append(std::to_string(Lsa::Type::ADJACENCY));
Vince Lehman41b173e2015-05-07 14:13:26 -0500177 AdjLsa* lsa = nlsr.getLsdb().findAdjLsa(key);
178 BOOST_REQUIRE(lsa != nullptr);
179
Nick Gordonc780a692017-04-27 18:03:02 -0500180 auto c = lsa->getAdl().findAdjacent(ROUTER_C_NAME);
181 BOOST_REQUIRE(c != nlsr.getAdjacencyList().end());
Vince Lehman41b173e2015-05-07 14:13:26 -0500182
183 double higherLinkCost = LINK_BC_COST + 1;
184 c->setLinkCost(higherLinkCost);
185
186 // Calculation should consider the link between B and C as having cost = higherLinkCost
187 LinkStateRoutingTableCalculator calculator(map.getMapSize());
188 calculator.calculatePath(map, routingTable, nlsr);
189
190 RoutingTableEntry* entryB = routingTable.findRoutingTableEntry(ROUTER_B_NAME);
191 BOOST_REQUIRE(entryB != nullptr);
192
193 // Router A should be able to get to B through B and to B through C
194 NexthopList& bHopList = entryB->getNexthopList();
195 BOOST_REQUIRE_EQUAL(bHopList.getNextHops().size(), 2);
196
197 for (const NextHop& hop : bHopList) {
198 std::string faceUri = hop.getConnectingFaceUri();
199 uint64_t cost = hop.getRouteCostAsAdjustedInteger();
200
201 BOOST_CHECK((faceUri == ROUTER_B_FACE && cost == LINK_AB_COST) ||
202 (faceUri == ROUTER_C_FACE && cost == LINK_AC_COST + higherLinkCost));
203
204 }
205
206 RoutingTableEntry* entryC = routingTable.findRoutingTableEntry(ROUTER_C_NAME);
207 BOOST_REQUIRE(entryC != nullptr);
208
209 // Router A should be able to get to C through C and to C through B
210 NexthopList& cHopList = entryC->getNexthopList();
211 BOOST_REQUIRE_EQUAL(cHopList.getNextHops().size(), 2);
212
213 for (const NextHop& hop : cHopList) {
214 std::string faceUri = hop.getConnectingFaceUri();
215 uint64_t cost = hop.getRouteCostAsAdjustedInteger();
216
217 BOOST_CHECK((faceUri == ROUTER_C_FACE && cost == LINK_AC_COST) ||
218 (faceUri == ROUTER_B_FACE && cost == LINK_AB_COST + higherLinkCost));
219 }
220}
221
222BOOST_AUTO_TEST_CASE(AsymmetricZeroCost)
223{
224 // Asymmetric link cost between B and C
Nick Gordon727d4832017-10-13 18:04:25 -0500225 ndn::Name key = ndn::Name(ROUTER_B_NAME).append(std::to_string(Lsa::Type::ADJACENCY));
Vince Lehman41b173e2015-05-07 14:13:26 -0500226 AdjLsa* lsa = nlsr.getLsdb().findAdjLsa(key);
227 BOOST_REQUIRE(lsa != nullptr);
228
Nick Gordonc780a692017-04-27 18:03:02 -0500229 auto c = lsa->getAdl().findAdjacent(ROUTER_C_NAME);
230 BOOST_REQUIRE(c != nlsr.getAdjacencyList().end());
Vince Lehman41b173e2015-05-07 14:13:26 -0500231
232 c->setLinkCost(0);
233
234 // Calculation should consider the link between B and C as down
235 LinkStateRoutingTableCalculator calculator(map.getMapSize());
236 calculator.calculatePath(map, routingTable, nlsr);
237
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
242 NexthopList& bHopList = entryB->getNexthopList();
243 BOOST_REQUIRE_EQUAL(bHopList.getNextHops().size(), 1);
244
Vince Lehmanef21d8e2015-04-01 15:59:39 -0500245 const NextHop& nextHopForB = *(bHopList.getNextHops().begin());
Vince Lehman41b173e2015-05-07 14:13:26 -0500246
247 BOOST_CHECK(nextHopForB.getConnectingFaceUri() == ROUTER_B_FACE &&
248 nextHopForB.getRouteCostAsAdjustedInteger() == LINK_AB_COST);
249
250 // Router A should be able to get to C through C but not through B
251 RoutingTableEntry* entryC = routingTable.findRoutingTableEntry(ROUTER_C_NAME);
252 BOOST_REQUIRE(entryC != nullptr);
253
254 NexthopList& cHopList = entryC->getNexthopList();
255 BOOST_REQUIRE_EQUAL(cHopList.getNextHops().size(), 1);
256
Vince Lehmanef21d8e2015-04-01 15:59:39 -0500257 const NextHop& nextHopForC = *(cHopList.getNextHops().begin());
Vince Lehman41b173e2015-05-07 14:13:26 -0500258
259 BOOST_CHECK(nextHopForC.getConnectingFaceUri() == ROUTER_C_FACE &&
260 nextHopForC.getRouteCostAsAdjustedInteger() == LINK_AC_COST);
261}
262
263BOOST_AUTO_TEST_SUITE_END()
264
Nick Gordonfad8e252016-08-11 14:21:38 -0500265} // namespace test
266} // namespace nlsr