blob: a2ec12bf675d32eb0b7beebf563490fb3bd7ecce [file] [log] [blame]
akmhoque3d06e792014-05-27 16:23:20 -05001/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
Davide Pesaventoaf7a2112019-03-19 14:55:20 -04002/*
Ashlesh Gawande0db4d4d2020-02-05 20:30:02 -08003 * Copyright (c) 2014-2020, The University of Memphis,
Nick Gordonf8b5bcd2016-08-11 15:06:50 -05004 * Regents of the University of California
akmhoque3d06e792014-05-27 16:23:20 -05005 *
6 * This file is part of NLSR (Named-data Link State Routing).
7 * See AUTHORS.md for complete list of NLSR authors and contributors.
8 *
9 * NLSR is free software: you can redistribute it and/or modify it under the terms
10 * of the GNU General Public License as published by the Free Software Foundation,
11 * either version 3 of the License, or (at your option) any later version.
12 *
13 * NLSR is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
14 * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
15 * PURPOSE. See the GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License along with
18 * NLSR, e.g., in COPYING.md file. If not, see <http://www.gnu.org/licenses/>.
Ashlesh Gawande0421bc62020-05-08 20:42:19 -070019 */
Davide Pesaventoa08dc3f2018-05-24 00:40:28 -040020
akmhoque53353462014-04-22 08:43:45 -050021#include "routing-table.hpp"
22#include "nlsr.hpp"
23#include "map.hpp"
akmhoque157b0a42014-05-13 00:26:37 -050024#include "conf-parameter.hpp"
akmhoque53353462014-04-22 08:43:45 -050025#include "routing-table-calculator.hpp"
26#include "routing-table-entry.hpp"
akmhoquec8a10f72014-04-25 18:42:55 -050027#include "name-prefix-table.hpp"
akmhoque674b0b12014-05-20 14:33:28 -050028#include "logger.hpp"
Ashlesh Gawande0421bc62020-05-08 20:42:19 -070029#include "tlv-nlsr.hpp"
akmhoque53353462014-04-22 08:43:45 -050030
Nick Gordon22b5c952017-08-10 17:48:15 -050031#include <list>
Nick Gordone98480b2017-05-24 11:23:03 -050032#include <string>
Nick Gordon22b5c952017-08-10 17:48:15 -050033
akmhoque53353462014-04-22 08:43:45 -050034namespace nlsr {
35
dmcoomescf8d0ed2017-02-21 11:39:01 -060036INIT_LOGGER(route.RoutingTable);
akmhoque674b0b12014-05-20 14:33:28 -050037
Ashlesh Gawande85998a12017-12-07 22:22:13 -060038RoutingTable::RoutingTable(ndn::Scheduler& scheduler, Fib& fib, Lsdb& lsdb,
39 NamePrefixTable& namePrefixTable, ConfParameter& confParam)
Davide Pesaventoa08dc3f2018-05-24 00:40:28 -040040 : afterRoutingChange{std::make_unique<AfterRoutingChange>()}
Nick Gordonb7b58392017-08-17 16:29:21 -050041 , m_scheduler(scheduler)
Ashlesh Gawande85998a12017-12-07 22:22:13 -060042 , m_fib(fib)
43 , m_lsdb(lsdb)
44 , m_namePrefixTable(namePrefixTable)
Ashlesh Gawande85998a12017-12-07 22:22:13 -060045 , m_routingCalcInterval{confParam.getRoutingCalcInterval()}
46 , m_isRoutingTableCalculating(false)
47 , m_isRouteCalculationScheduled(false)
48 , m_confParam(confParam)
Nick Gordonb7b58392017-08-17 16:29:21 -050049{
50}
51
akmhoque53353462014-04-22 08:43:45 -050052void
Ashlesh Gawande85998a12017-12-07 22:22:13 -060053RoutingTable::calculate()
akmhoque53353462014-04-22 08:43:45 -050054{
Ashlesh Gawande85998a12017-12-07 22:22:13 -060055 m_lsdb.writeCorLsdbLog();
56 m_lsdb.writeNameLsdbLog();
57 m_lsdb.writeAdjLsdbLog();
58 m_namePrefixTable.writeLog();
59 if (m_isRoutingTableCalculating == false) {
60 // setting routing table calculation
61 m_isRoutingTableCalculating = true;
Nick Gordone8e03ac2016-07-07 14:24:38 -050062
Ashlesh Gawande85998a12017-12-07 22:22:13 -060063 bool isHrEnabled = m_confParam.getHyperbolicState() != HYPERBOLIC_STATE_OFF;
Nick Gordone8e03ac2016-07-07 14:24:38 -050064
Ashlesh Gawande85998a12017-12-07 22:22:13 -060065 if ((!isHrEnabled &&
66 m_lsdb
67 .doesLsaExist(ndn::Name{m_confParam.getRouterPrefix()}
Ashlesh Gawande0db4d4d2020-02-05 20:30:02 -080068 .append(boost::lexical_cast<std::string>(Lsa::Type::ADJACENCY)), Lsa::Type::ADJACENCY))
Nick Gordone8e03ac2016-07-07 14:24:38 -050069 ||
Ashlesh Gawande85998a12017-12-07 22:22:13 -060070 (isHrEnabled &&
71 m_lsdb
72 .doesLsaExist(ndn::Name{m_confParam.getRouterPrefix()}
Ashlesh Gawande0db4d4d2020-02-05 20:30:02 -080073 .append(boost::lexical_cast<std::string>(Lsa::Type::COORDINATE)), Lsa::Type::COORDINATE))) {
Ashlesh Gawande85998a12017-12-07 22:22:13 -060074 if (m_lsdb.getIsBuildAdjLsaSheduled() != 1) {
dmcoomes5bcb39e2017-10-31 15:07:55 -050075 NLSR_LOG_TRACE("Clearing old routing table");
akmhoque53353462014-04-22 08:43:45 -050076 clearRoutingTable();
akmhoque157b0a42014-05-13 00:26:37 -050077 // for dry run options
78 clearDryRoutingTable();
Vince Lehman50df6b72015-03-03 12:06:40 -060079
dmcoomes5bcb39e2017-10-31 15:07:55 -050080 NLSR_LOG_DEBUG("Calculating routing table");
Vince Lehman50df6b72015-03-03 12:06:40 -060081
akmhoque53353462014-04-22 08:43:45 -050082 // calculate Link State routing
Ashlesh Gawande85998a12017-12-07 22:22:13 -060083 if ((m_confParam.getHyperbolicState() == HYPERBOLIC_STATE_OFF)
84 || (m_confParam.getHyperbolicState() == HYPERBOLIC_STATE_DRY_RUN)) {
85 calculateLsRoutingTable();
akmhoque53353462014-04-22 08:43:45 -050086 }
Ashlesh Gawande85998a12017-12-07 22:22:13 -060087 // calculate hyperbolic routing
88 if (m_confParam.getHyperbolicState() == HYPERBOLIC_STATE_ON) {
89 calculateHypRoutingTable(false);
akmhoque53353462014-04-22 08:43:45 -050090 }
Ashlesh Gawande85998a12017-12-07 22:22:13 -060091 // calculate dry hyperbolic routing
92 if (m_confParam.getHyperbolicState() == HYPERBOLIC_STATE_DRY_RUN) {
93 calculateHypRoutingTable(true);
akmhoque53353462014-04-22 08:43:45 -050094 }
Nick G97e34942016-07-11 14:46:27 -050095 // Inform the NPT that updates have been made
dmcoomes5bcb39e2017-10-31 15:07:55 -050096 NLSR_LOG_DEBUG("Calling Update NPT With new Route");
Nick Gordonb7b58392017-08-17 16:29:21 -050097 (*afterRoutingChange)(m_rTable);
Ashlesh Gawande0421bc62020-05-08 20:42:19 -070098 NLSR_LOG_DEBUG(*this);
Ashlesh Gawande85998a12017-12-07 22:22:13 -060099 m_namePrefixTable.writeLog();
100 m_fib.writeLog();
akmhoque53353462014-04-22 08:43:45 -0500101 }
akmhoque157b0a42014-05-13 00:26:37 -0500102 else {
Ashlesh Gawande0421bc62020-05-08 20:42:19 -0700103 NLSR_LOG_DEBUG("Adjacency building is scheduled, so routing table can not be calculated :(");
akmhoque53353462014-04-22 08:43:45 -0500104 }
105 }
akmhoque157b0a42014-05-13 00:26:37 -0500106 else {
Ashlesh Gawande0421bc62020-05-08 20:42:19 -0700107 NLSR_LOG_DEBUG("No Adj LSA of router itself, so Routing table can not be calculated :(");
akmhoque53353462014-04-22 08:43:45 -0500108 clearRoutingTable();
109 clearDryRoutingTable(); // for dry run options
110 // need to update NPT here
dmcoomes5bcb39e2017-10-31 15:07:55 -0500111 NLSR_LOG_DEBUG("Calling Update NPT With new Route");
Nick Gordonb7b58392017-08-17 16:29:21 -0500112 (*afterRoutingChange)(m_rTable);
Ashlesh Gawande0421bc62020-05-08 20:42:19 -0700113 NLSR_LOG_DEBUG(*this);
Ashlesh Gawande85998a12017-12-07 22:22:13 -0600114 m_namePrefixTable.writeLog();
115 m_fib.writeLog();
116 // debugging purpose end
akmhoque53353462014-04-22 08:43:45 -0500117 }
Ashlesh Gawande85998a12017-12-07 22:22:13 -0600118 m_isRouteCalculationScheduled = false; // clear scheduled flag
119 m_isRoutingTableCalculating = false; // unsetting routing table calculation
akmhoque53353462014-04-22 08:43:45 -0500120 }
akmhoque157b0a42014-05-13 00:26:37 -0500121 else {
Ashlesh Gawande85998a12017-12-07 22:22:13 -0600122 scheduleRoutingTableCalculation();
akmhoque53353462014-04-22 08:43:45 -0500123 }
124}
125
akmhoque53353462014-04-22 08:43:45 -0500126void
Ashlesh Gawande85998a12017-12-07 22:22:13 -0600127RoutingTable::calculateLsRoutingTable()
akmhoque53353462014-04-22 08:43:45 -0500128{
dmcoomes5bcb39e2017-10-31 15:07:55 -0500129 NLSR_LOG_DEBUG("RoutingTable::calculateLsRoutingTable Called");
Vince Lehman9a709032014-09-13 16:28:07 -0500130
131 Map map;
Ashlesh Gawande85998a12017-12-07 22:22:13 -0600132 map.createFromAdjLsdb(m_lsdb.getAdjLsdb().begin(), m_lsdb.getAdjLsdb().end());
Vince Lehman9a709032014-09-13 16:28:07 -0500133 map.writeLog();
134
135 size_t nRouters = map.getMapSize();
136
137 LinkStateRoutingTableCalculator calculator(nRouters);
138
Ashlesh Gawande85998a12017-12-07 22:22:13 -0600139 calculator.calculatePath(map, *this, m_confParam, m_lsdb.getAdjLsdb());
akmhoque53353462014-04-22 08:43:45 -0500140}
141
142void
Ashlesh Gawande85998a12017-12-07 22:22:13 -0600143RoutingTable::calculateHypRoutingTable(bool isDryRun)
akmhoque53353462014-04-22 08:43:45 -0500144{
Vince Lehman9a709032014-09-13 16:28:07 -0500145 Map map;
Ashlesh Gawande85998a12017-12-07 22:22:13 -0600146 map.createFromCoordinateLsdb(m_lsdb.getCoordinateLsdb().begin(),
147 m_lsdb.getCoordinateLsdb().end());
Vince Lehman9a709032014-09-13 16:28:07 -0500148 map.writeLog();
149
150 size_t nRouters = map.getMapSize();
151
Ashlesh Gawande85998a12017-12-07 22:22:13 -0600152 HyperbolicRoutingCalculator calculator(nRouters, isDryRun, m_confParam.getRouterPrefix());
Vince Lehman9a709032014-09-13 16:28:07 -0500153
Ashlesh Gawande85998a12017-12-07 22:22:13 -0600154 calculator.calculatePath(map, *this, m_lsdb, m_confParam.getAdjacencyList());
akmhoque53353462014-04-22 08:43:45 -0500155}
156
157void
Ashlesh Gawande85998a12017-12-07 22:22:13 -0600158RoutingTable::scheduleRoutingTableCalculation()
akmhoque53353462014-04-22 08:43:45 -0500159{
Davide Pesaventoaf7a2112019-03-19 14:55:20 -0400160 if (!m_isRouteCalculationScheduled) {
dmcoomes5bcb39e2017-10-31 15:07:55 -0500161 NLSR_LOG_DEBUG("Scheduling routing table calculation in " << m_routingCalcInterval);
Davide Pesaventoaf7a2112019-03-19 14:55:20 -0400162 m_scheduler.schedule(m_routingCalcInterval, [this] { calculate(); });
Ashlesh Gawande85998a12017-12-07 22:22:13 -0600163 m_isRouteCalculationScheduled = true;
akmhoque53353462014-04-22 08:43:45 -0500164 }
165}
166
167static bool
akmhoque31d1d4b2014-05-05 22:08:14 -0500168routingTableEntryCompare(RoutingTableEntry& rte, ndn::Name& destRouter)
akmhoque53353462014-04-22 08:43:45 -0500169{
170 return rte.getDestination() == destRouter;
171}
172
akmhoque53353462014-04-22 08:43:45 -0500173void
akmhoque31d1d4b2014-05-05 22:08:14 -0500174RoutingTable::addNextHop(const ndn::Name& destRouter, NextHop& nh)
akmhoque53353462014-04-22 08:43:45 -0500175{
dmcoomes5bcb39e2017-10-31 15:07:55 -0500176 NLSR_LOG_DEBUG("Adding " << nh << " for destination: " << destRouter);
Vince Lehman9a709032014-09-13 16:28:07 -0500177
akmhoqueb6450b12014-04-24 00:01:03 -0500178 RoutingTableEntry* rteChk = findRoutingTableEntry(destRouter);
Davide Pesaventoaf7a2112019-03-19 14:55:20 -0400179 if (rteChk == nullptr) {
akmhoque53353462014-04-22 08:43:45 -0500180 RoutingTableEntry rte(destRouter);
akmhoquefdbddb12014-05-02 18:35:19 -0500181 rte.getNexthopList().addNextHop(nh);
akmhoque53353462014-04-22 08:43:45 -0500182 m_rTable.push_back(rte);
183 }
akmhoque157b0a42014-05-13 00:26:37 -0500184 else {
akmhoquefdbddb12014-05-02 18:35:19 -0500185 rteChk->getNexthopList().addNextHop(nh);
akmhoque53353462014-04-22 08:43:45 -0500186 }
187}
188
akmhoqueb6450b12014-04-24 00:01:03 -0500189RoutingTableEntry*
akmhoque31d1d4b2014-05-05 22:08:14 -0500190RoutingTable::findRoutingTableEntry(const ndn::Name& destRouter)
akmhoque53353462014-04-22 08:43:45 -0500191{
Davide Pesaventoaf7a2112019-03-19 14:55:20 -0400192 auto it = std::find_if(m_rTable.begin(), m_rTable.end(),
193 std::bind(&routingTableEntryCompare, _1, destRouter));
akmhoque157b0a42014-05-13 00:26:37 -0500194 if (it != m_rTable.end()) {
akmhoqueb6450b12014-04-24 00:01:03 -0500195 return &(*it);
akmhoque53353462014-04-22 08:43:45 -0500196 }
Davide Pesaventoaf7a2112019-03-19 14:55:20 -0400197 return nullptr;
akmhoque53353462014-04-22 08:43:45 -0500198}
199
200void
akmhoque31d1d4b2014-05-05 22:08:14 -0500201RoutingTable::addNextHopToDryTable(const ndn::Name& destRouter, NextHop& nh)
akmhoque53353462014-04-22 08:43:45 -0500202{
dmcoomes5bcb39e2017-10-31 15:07:55 -0500203 NLSR_LOG_DEBUG("Adding " << nh << " to dry table for destination: " << destRouter);
Vince Lehman9a709032014-09-13 16:28:07 -0500204
Davide Pesaventoaf7a2112019-03-19 14:55:20 -0400205 auto it = std::find_if(m_dryTable.begin(), m_dryTable.end(),
206 std::bind(&routingTableEntryCompare, _1, destRouter));
akmhoque157b0a42014-05-13 00:26:37 -0500207 if (it == m_dryTable.end()) {
akmhoque53353462014-04-22 08:43:45 -0500208 RoutingTableEntry rte(destRouter);
akmhoquefdbddb12014-05-02 18:35:19 -0500209 rte.getNexthopList().addNextHop(nh);
akmhoque53353462014-04-22 08:43:45 -0500210 m_dryTable.push_back(rte);
211 }
akmhoque157b0a42014-05-13 00:26:37 -0500212 else {
Davide Pesaventoaf7a2112019-03-19 14:55:20 -0400213 it->getNexthopList().addNextHop(nh);
akmhoque53353462014-04-22 08:43:45 -0500214 }
215}
216
217void
akmhoque53353462014-04-22 08:43:45 -0500218RoutingTable::clearRoutingTable()
219{
akmhoque157b0a42014-05-13 00:26:37 -0500220 if (m_rTable.size() > 0) {
akmhoque53353462014-04-22 08:43:45 -0500221 m_rTable.clear();
222 }
223}
224
225void
226RoutingTable::clearDryRoutingTable()
227{
akmhoque157b0a42014-05-13 00:26:37 -0500228 if (m_dryTable.size() > 0) {
akmhoque53353462014-04-22 08:43:45 -0500229 m_dryTable.clear();
230 }
231}
232
Ashlesh Gawande0421bc62020-05-08 20:42:19 -0700233template<ndn::encoding::Tag TAG>
234size_t
235RoutingTableStatus::wireEncode(ndn::EncodingImpl<TAG>& block) const
236{
237 size_t totalLength = 0;
238
239 for (auto it = m_dryTable.rbegin(); it != m_dryTable.rend(); ++it) {
240 totalLength += it->wireEncode(block);
241 }
242
243 for (auto it = m_rTable.rbegin(); it != m_rTable.rend(); ++it) {
244 totalLength += it->wireEncode(block);
245 }
246
247 totalLength += block.prependVarNumber(totalLength);
248 totalLength += block.prependVarNumber(ndn::tlv::nlsr::RoutingTable);
249
250 return totalLength;
251}
252
253NDN_CXX_DEFINE_WIRE_ENCODE_INSTANTIATIONS(RoutingTableStatus);
254
255const ndn::Block&
256RoutingTableStatus::wireEncode() const
257{
258 if (m_wire.hasWire()) {
259 return m_wire;
260 }
261
262 ndn::EncodingEstimator estimator;
263 size_t estimatedSize = wireEncode(estimator);
264
265 ndn::EncodingBuffer buffer(estimatedSize, 0);
266 wireEncode(buffer);
267
268 m_wire = buffer.block();
269
270 return m_wire;
271}
272
273void
274RoutingTableStatus::wireDecode(const ndn::Block& wire)
275{
276 m_rTable.clear();
277
278 m_wire = wire;
279
280 if (m_wire.type() != ndn::tlv::nlsr::RoutingTable) {
281 std::stringstream error;
282 error << "Expected RoutingTableStatus Block, but Block is of a different type: #"
283 << m_wire.type();
284 BOOST_THROW_EXCEPTION(Error(error.str()));
285 }
286
287 m_wire.parse();
288
289 auto val = m_wire.elements_begin();
290
291 std::set<ndn::Name> destinations;
292 for (; val != m_wire.elements_end() && val->type() == ndn::tlv::nlsr::RoutingTableEntry; ++val) {
293 auto entry = RoutingTableEntry(*val);
294
295 if (destinations.emplace(entry.getDestination()).second) {
296 m_rTable.push_back(entry);
297 }
298 else {
299 // If destination already exists then this is the start of dry HR table
300 m_dryTable.push_back(entry);
301 }
302 }
303
304 if (val != m_wire.elements_end()) {
305 std::stringstream error;
306 error << "Expected the end of elements, but Block is of a different type: #"
307 << val->type();
308 BOOST_THROW_EXCEPTION(Error(error.str()));
309 }
310}
311
312std::ostream&
313operator<<(std::ostream& os, const RoutingTableStatus& rts)
314{
315 os << "Routing Table:\n";
316 for (const auto& rte : rts.getRoutingTableEntry()) {
317 os << rte;
318 }
319
320 if (!rts.getDryRoutingTableEntry().empty()) {
321 os << "Dry-Run Hyperbolic Routing Table:\n";
322 for (const auto& rte : rts.getDryRoutingTableEntry()) {
323 os << rte;
324 }
325 }
326 return os;
327}
328
Nick Gordonfad8e252016-08-11 14:21:38 -0500329} // namespace nlsr