blob: 78f37b1d144cf958e7a58995cb80ff4747450ccf [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/*
awlaned8174372023-05-23 13:37:54 -05003 * Copyright (c) 2014-2024, 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/>.
Alexander Afanasyev0ad01f32020-06-03 14:12:58 -040019 */
Junxiao Shi63bd0342016-08-17 16:57:14 +000020
Alejandro Gil Torrese0d20482016-03-06 23:56:19 -060021#include "hello-protocol.hpp"
akmhoque31d1d4b2014-05-05 22:08:14 -050022#include "nlsr.hpp"
23#include "lsdb.hpp"
akmhoque674b0b12014-05-20 14:33:28 -050024#include "logger.hpp"
Davide Pesaventoc1d0e8e2022-06-15 14:26:02 -040025#include "utility/name-helper.hpp"
akmhoque31d1d4b2014-05-05 22:08:14 -050026
Ashlesh Gawande214032e2020-12-22 17:20:14 -050027#include <ndn-cxx/encoding/nfd-constants.hpp>
28
akmhoque31d1d4b2014-05-05 22:08:14 -050029namespace nlsr {
30
dmcoomescf8d0ed2017-02-21 11:39:01 -060031INIT_LOGGER(HelloProtocol);
akmhoque674b0b12014-05-20 14:33:28 -050032
Ashlesh Gawande85998a12017-12-07 22:22:13 -060033HelloProtocol::HelloProtocol(ndn::Face& face, ndn::KeyChain& keyChain,
Ashlesh Gawande85998a12017-12-07 22:22:13 -060034 ConfParameter& confParam, RoutingTable& routingTable,
35 Lsdb& lsdb)
36 : m_face(face)
Davide Pesaventofd1e9402023-11-13 15:40:41 -050037 , m_scheduler(m_face.getIoContext())
Ashlesh Gawande85998a12017-12-07 22:22:13 -060038 , m_keyChain(keyChain)
Saurab Dulal427e0122019-11-28 11:58:02 -060039 , m_signingInfo(confParam.getSigningInfo())
Ashlesh Gawande85998a12017-12-07 22:22:13 -060040 , m_confParam(confParam)
41 , m_routingTable(routingTable)
42 , m_lsdb(lsdb)
Ashlesh Gawande6b388fc2019-09-30 10:14:41 -050043 , m_adjacencyList(m_confParam.getAdjacencyList())
Nick Gordone18296c2017-10-11 16:05:24 -050044{
Ashlesh Gawande214032e2020-12-22 17:20:14 -050045 ndn::Name name(m_confParam.getRouterPrefix());
46 name.append(NLSR_COMPONENT);
47 name.append(INFO_COMPONENT);
48
49 NLSR_LOG_DEBUG("Setting interest filter for Hello interest: " << name);
50
51 m_face.setInterestFilter(ndn::InterestFilter(name).allowLoopback(false),
52 [this] (const auto& name, const auto& interest) {
53 processInterest(name, interest);
54 },
55 [] (const auto& name) {
56 NLSR_LOG_DEBUG("Successfully registered prefix: " << name);
57 },
58 [] (const auto& name, const auto& resp) {
59 NLSR_LOG_ERROR("Failed to register prefix " << name);
60 NDN_THROW(std::runtime_error("Failed to register hello prefix: " + resp));
61 },
62 m_signingInfo, ndn::nfd::ROUTE_FLAG_CAPTURE);
Nick Gordone18296c2017-10-11 16:05:24 -050063}
64
akmhoque31d1d4b2014-05-05 22:08:14 -050065void
66HelloProtocol::expressInterest(const ndn::Name& interestName, uint32_t seconds)
67{
Ashlesh Gawande6b388fc2019-09-30 10:14:41 -050068 NLSR_LOG_DEBUG("Expressing Interest: " << interestName);
Ashlesh Gawande85998a12017-12-07 22:22:13 -060069 ndn::Interest interest(interestName);
70 interest.setInterestLifetime(ndn::time::seconds(seconds));
71 interest.setMustBeFresh(true);
72 interest.setCanBePrefix(true);
73 m_face.expressInterest(interest,
Ashlesh Gawande6b388fc2019-09-30 10:14:41 -050074 std::bind(&HelloProtocol::onContent, this, _1, _2),
Davide Pesaventofd1e9402023-11-13 15:40:41 -050075 [this, seconds] (const auto& interest, const auto& nack) {
Ashlesh Gawande6b388fc2019-09-30 10:14:41 -050076 NDN_LOG_TRACE("Received Nack with reason: " << nack.getReason());
77 NDN_LOG_TRACE("Will treat as timeout in " << 2 * seconds << " seconds");
78 m_scheduler.schedule(ndn::time::seconds(2 * seconds),
79 [this, interest] { processInterestTimedOut(interest); });
80 },
81 std::bind(&HelloProtocol::processInterestTimedOut, this, _1));
Alejandro Gil Torrese0d20482016-03-06 23:56:19 -060082
83 // increment SENT_HELLO_INTEREST
84 hpIncrementSignal(Statistics::PacketType::SENT_HELLO_INTEREST);
akmhoque31d1d4b2014-05-05 22:08:14 -050085}
86
87void
Ashlesh Gawande6b388fc2019-09-30 10:14:41 -050088HelloProtocol::sendHelloInterest(const ndn::Name& neighbor)
akmhoque31d1d4b2014-05-05 22:08:14 -050089{
Ashlesh Gawande6b388fc2019-09-30 10:14:41 -050090 auto adjacent = m_adjacencyList.findAdjacent(neighbor);
Ashlesh Gawande6b388fc2019-09-30 10:14:41 -050091 if (adjacent == m_adjacencyList.end()) {
92 return;
akmhoque31d1d4b2014-05-05 22:08:14 -050093 }
akmhoque31d1d4b2014-05-05 22:08:14 -050094
Ashlesh Gawande6b388fc2019-09-30 10:14:41 -050095 // If this adjacency has a Face, just proceed as usual.
96 if(adjacent->getFaceId() != 0) {
97 // interest name: /<neighbor>/NLSR/INFO/<router>
98 ndn::Name interestName = adjacent->getName() ;
99 interestName.append(NLSR_COMPONENT);
100 interestName.append(INFO_COMPONENT);
Davide Pesaventoe28d8752022-03-19 03:55:25 -0400101 interestName.append(ndn::tlv::GenericNameComponent, m_confParam.getRouterPrefix().wireEncode());
Ashlesh Gawande6b388fc2019-09-30 10:14:41 -0500102 expressInterest(interestName, m_confParam.getInterestResendTime());
103 NLSR_LOG_DEBUG("Sending HELLO interest: " << interestName);
104 }
Vince Lehman50df6b72015-03-03 12:06:40 -0600105
Ashlesh Gawande6b388fc2019-09-30 10:14:41 -0500106 m_scheduler.schedule(ndn::time::seconds(m_confParam.getInfoInterestInterval()),
107 [this, neighbor] { sendHelloInterest(neighbor); });
akmhoque31d1d4b2014-05-05 22:08:14 -0500108}
109
110void
111HelloProtocol::processInterest(const ndn::Name& name,
112 const ndn::Interest& interest)
113{
dmcoomes9f936662017-03-02 10:33:09 -0600114 // interest name: /<neighbor>/NLSR/INFO/<router>
akmhoque31d1d4b2014-05-05 22:08:14 -0500115 const ndn::Name interestName = interest.getName();
Alejandro Gil Torrese0d20482016-03-06 23:56:19 -0600116
117 // increment RCV_HELLO_INTEREST
118 hpIncrementSignal(Statistics::PacketType::RCV_HELLO_INTEREST);
119
Davide Pesaventofd1e9402023-11-13 15:40:41 -0500120 NLSR_LOG_DEBUG("Interest received for Name: " << interestName);
akmhoque157b0a42014-05-13 00:26:37 -0500121 if (interestName.get(-2).toUri() != INFO_COMPONENT) {
Davide Pesaventofd1e9402023-11-13 15:40:41 -0500122 NLSR_LOG_DEBUG("INFO_COMPONENT not found or Interest Name " << interestName
123 << " does not match expression");
akmhoque31d1d4b2014-05-05 22:08:14 -0500124 return;
125 }
Alejandro Gil Torrese0d20482016-03-06 23:56:19 -0600126
awlaned8174372023-05-23 13:37:54 -0500127 ndn::Name neighbor(interestName.get(-1).blockFromValue());
dmcoomes5bcb39e2017-10-31 15:07:55 -0500128 NLSR_LOG_DEBUG("Neighbor: " << neighbor);
Ashlesh Gawande6b388fc2019-09-30 10:14:41 -0500129 if (m_adjacencyList.isNeighbor(neighbor)) {
Davide Pesaventofd1e9402023-11-13 15:40:41 -0500130 auto data = std::make_shared<ndn::Data>();
akmhoque69c9aa92014-07-23 15:15:05 -0500131 data->setName(ndn::Name(interest.getName()).appendVersion());
awlaned8174372023-05-23 13:37:54 -0500132 // A Hello reply being cached longer than is needed to fufill an Interest
133 // can cause counterintuitive behavior. Consequently, we use the default
134 // minimum of 0 ms.
135 data->setFreshnessPeriod(0_ms);
Davide Pesaventoe28d8752022-03-19 03:55:25 -0400136 data->setContent(ndn::make_span(reinterpret_cast<const uint8_t*>(INFO_COMPONENT.data()),
137 INFO_COMPONENT.size()));
Muktadir Chowdhuryf04f9892017-08-20 20:42:56 -0500138
Ashlesh Gawande85998a12017-12-07 22:22:13 -0600139 m_keyChain.sign(*data, m_signingInfo);
Muktadir Chowdhuryf04f9892017-08-20 20:42:56 -0500140
dmcoomes5bcb39e2017-10-31 15:07:55 -0500141 NLSR_LOG_DEBUG("Sending out data for name: " << interest.getName());
Ashlesh Gawande85998a12017-12-07 22:22:13 -0600142 m_face.put(*data);
Alejandro Gil Torrese0d20482016-03-06 23:56:19 -0600143 // increment SENT_HELLO_DATA
144 hpIncrementSignal(Statistics::PacketType::SENT_HELLO_DATA);
Nick Gordonc780a692017-04-27 18:03:02 -0500145
Ashlesh Gawande6b388fc2019-09-30 10:14:41 -0500146 auto adjacent = m_adjacencyList.findAdjacent(neighbor);
Nick G97e34942016-07-11 14:46:27 -0500147 // If this neighbor was previously inactive, send our own hello interest, too
Vince Lehmancb76ade2014-08-28 21:24:41 -0500148 if (adjacent->getStatus() == Adjacent::STATUS_INACTIVE) {
Nick G97e34942016-07-11 14:46:27 -0500149 // We can only do that if the neighbor currently has a face.
awlaned8174372023-05-23 13:37:54 -0500150 if (adjacent->getFaceId() != 0) {
dmcoomes9f936662017-03-02 10:33:09 -0600151 // interest name: /<neighbor>/NLSR/INFO/<router>
akmhoquec04e7272014-07-02 11:00:14 -0500152 ndn::Name interestName(neighbor);
153 interestName.append(NLSR_COMPONENT);
154 interestName.append(INFO_COMPONENT);
Davide Pesaventoe28d8752022-03-19 03:55:25 -0400155 interestName.append(ndn::tlv::GenericNameComponent, m_confParam.getRouterPrefix().wireEncode());
Ashlesh Gawande85998a12017-12-07 22:22:13 -0600156 expressInterest(interestName, m_confParam.getInterestResendTime());
akmhoquec04e7272014-07-02 11:00:14 -0500157 }
akmhoque31d1d4b2014-05-05 22:08:14 -0500158 }
159 }
160}
161
162void
163HelloProtocol::processInterestTimedOut(const ndn::Interest& interest)
164{
dmcoomes9f936662017-03-02 10:33:09 -0600165 // interest name: /<neighbor>/NLSR/INFO/<router>
akmhoque31d1d4b2014-05-05 22:08:14 -0500166 const ndn::Name interestName(interest.getName());
dmcoomes5bcb39e2017-10-31 15:07:55 -0500167 NLSR_LOG_DEBUG("Interest timed out for Name: " << interestName);
akmhoque157b0a42014-05-13 00:26:37 -0500168 if (interestName.get(-2).toUri() != INFO_COMPONENT) {
akmhoque31d1d4b2014-05-05 22:08:14 -0500169 return;
170 }
akmhoque93f1a072014-06-19 16:24:28 -0500171 ndn::Name neighbor = interestName.getPrefix(-3);
dmcoomes5bcb39e2017-10-31 15:07:55 -0500172 NLSR_LOG_DEBUG("Neighbor: " << neighbor);
Ashlesh Gawande6b388fc2019-09-30 10:14:41 -0500173 m_adjacencyList.incrementTimedOutInterestCount(neighbor);
Vince Lehmancb76ade2014-08-28 21:24:41 -0500174
Ashlesh Gawande6b388fc2019-09-30 10:14:41 -0500175 Adjacent::Status status = m_adjacencyList.getStatusOfNeighbor(neighbor);
Vince Lehmancb76ade2014-08-28 21:24:41 -0500176
Ashlesh Gawande6b388fc2019-09-30 10:14:41 -0500177 uint32_t infoIntTimedOutCount = m_adjacencyList.getTimedOutInterestCount(neighbor);
dmcoomes5bcb39e2017-10-31 15:07:55 -0500178 NLSR_LOG_DEBUG("Status: " << status);
179 NLSR_LOG_DEBUG("Info Interest Timed out: " << infoIntTimedOutCount);
Ashlesh Gawande214032e2020-12-22 17:20:14 -0500180 if (infoIntTimedOutCount < m_confParam.getInterestRetryNumber()) {
dmcoomes9f936662017-03-02 10:33:09 -0600181 // interest name: /<neighbor>/NLSR/INFO/<router>
akmhoque31d1d4b2014-05-05 22:08:14 -0500182 ndn::Name interestName(neighbor);
akmhoque93f1a072014-06-19 16:24:28 -0500183 interestName.append(NLSR_COMPONENT);
akmhoque157b0a42014-05-13 00:26:37 -0500184 interestName.append(INFO_COMPONENT);
Davide Pesaventoe28d8752022-03-19 03:55:25 -0400185 interestName.append(ndn::tlv::GenericNameComponent, m_confParam.getRouterPrefix().wireEncode());
dmcoomes5bcb39e2017-10-31 15:07:55 -0500186 NLSR_LOG_DEBUG("Resending interest: " << interestName);
Ashlesh Gawande85998a12017-12-07 22:22:13 -0600187 expressInterest(interestName, m_confParam.getInterestResendTime());
akmhoque31d1d4b2014-05-05 22:08:14 -0500188 }
Ashlesh Gawande214032e2020-12-22 17:20:14 -0500189 else if (status == Adjacent::STATUS_ACTIVE) {
Ashlesh Gawande6b388fc2019-09-30 10:14:41 -0500190 m_adjacencyList.setStatusOfNeighbor(neighbor, Adjacent::STATUS_INACTIVE);
Vince Lehman50df6b72015-03-03 12:06:40 -0600191
dmcoomes5bcb39e2017-10-31 15:07:55 -0500192 NLSR_LOG_DEBUG("Neighbor: " << neighbor << " status changed to INACTIVE");
dmcoomes9eaf3f42017-02-21 11:39:01 -0600193
Ashlesh Gawande214032e2020-12-22 17:20:14 -0500194 if (m_confParam.getHyperbolicState() == HYPERBOLIC_STATE_ON) {
195 m_routingTable.scheduleRoutingTableCalculation();
196 }
197 else {
198 m_lsdb.scheduleAdjLsaBuild();
199 }
akmhoque31d1d4b2014-05-05 22:08:14 -0500200 }
201}
202
Davide Pesaventoc1d0e8e2022-06-15 14:26:02 -0400203// This is the first function that incoming Hello data will
204// see. This checks if the data appears to be signed, and passes it
205// on to validate the content of the data.
Yingdi Yu20e3a6e2014-05-26 23:16:10 -0700206void
207HelloProtocol::onContent(const ndn::Interest& interest, const ndn::Data& data)
208{
dmcoomes5bcb39e2017-10-31 15:07:55 -0500209 NLSR_LOG_DEBUG("Received data for INFO(name): " << data.getName());
Ashlesh Gawande7a231c02020-06-12 20:06:44 -0700210 auto kl = data.getKeyLocator();
211 if (kl && kl->getType() == ndn::tlv::Name) {
212 NLSR_LOG_DEBUG("Data signed with: " << kl->getName());
akmhoquedfe615f2014-07-27 14:12:21 -0500213 }
Ashlesh Gawande85998a12017-12-07 22:22:13 -0600214 m_confParam.getValidator().validate(data,
215 std::bind(&HelloProtocol::onContentValidated, this, _1),
216 std::bind(&HelloProtocol::onContentValidationFailed,
217 this, _1, _2));
Yingdi Yu20e3a6e2014-05-26 23:16:10 -0700218}
akmhoque31d1d4b2014-05-05 22:08:14 -0500219
220void
Muktadir Chowdhuryf04f9892017-08-20 20:42:56 -0500221HelloProtocol::onContentValidated(const ndn::Data& data)
akmhoque31d1d4b2014-05-05 22:08:14 -0500222{
dmcoomes9f936662017-03-02 10:33:09 -0600223 // data name: /<neighbor>/NLSR/INFO/<router>/<version>
Muktadir Chowdhuryf04f9892017-08-20 20:42:56 -0500224 ndn::Name dataName = data.getName();
dmcoomes5bcb39e2017-10-31 15:07:55 -0500225 NLSR_LOG_DEBUG("Data validation successful for INFO(name): " << dataName);
Muktadir Chowdhuryf04f9892017-08-20 20:42:56 -0500226
akmhoque157b0a42014-05-13 00:26:37 -0500227 if (dataName.get(-3).toUri() == INFO_COMPONENT) {
akmhoque93f1a072014-06-19 16:24:28 -0500228 ndn::Name neighbor = dataName.getPrefix(-4);
Vince Lehmancb76ade2014-08-28 21:24:41 -0500229
Ashlesh Gawande6b388fc2019-09-30 10:14:41 -0500230 Adjacent::Status oldStatus = m_adjacencyList.getStatusOfNeighbor(neighbor);
231 m_adjacencyList.setStatusOfNeighbor(neighbor, Adjacent::STATUS_ACTIVE);
232 m_adjacencyList.setTimedOutInterestCount(neighbor, 0);
233 Adjacent::Status newStatus = m_adjacencyList.getStatusOfNeighbor(neighbor);
Vince Lehmancb76ade2014-08-28 21:24:41 -0500234
Davide Pesaventofd1e9402023-11-13 15:40:41 -0500235 NLSR_LOG_DEBUG("Neighbor: " << neighbor);
236 NLSR_LOG_DEBUG("Old Status: " << oldStatus << ", New Status: " << newStatus);
akmhoque157b0a42014-05-13 00:26:37 -0500237 // change in Adjacency list
238 if ((oldStatus - newStatus) != 0) {
Ashlesh Gawande85998a12017-12-07 22:22:13 -0600239 if (m_confParam.getHyperbolicState() == HYPERBOLIC_STATE_ON) {
240 m_routingTable.scheduleRoutingTableCalculation();
Ashlesh Gawandec5fa3202016-12-05 13:21:51 -0600241 }
242 else {
Ashlesh Gawande85998a12017-12-07 22:22:13 -0600243 m_lsdb.scheduleAdjLsaBuild();
Ashlesh Gawandec5fa3202016-12-05 13:21:51 -0600244 }
Ashlesh Gawandee63b7fa2021-04-06 21:43:17 -0700245 onInitialHelloDataValidated(neighbor);
akmhoque31d1d4b2014-05-05 22:08:14 -0500246 }
247 }
Alejandro Gil Torrese0d20482016-03-06 23:56:19 -0600248 // increment RCV_HELLO_DATA
249 hpIncrementSignal(Statistics::PacketType::RCV_HELLO_DATA);
akmhoque31d1d4b2014-05-05 22:08:14 -0500250}
251
Yingdi Yu20e3a6e2014-05-26 23:16:10 -0700252void
Muktadir Chowdhuryf04f9892017-08-20 20:42:56 -0500253HelloProtocol::onContentValidationFailed(const ndn::Data& data,
Alexander Afanasyev0ad01f32020-06-03 14:12:58 -0400254 const ndn::security::ValidationError& ve)
Yingdi Yu20e3a6e2014-05-26 23:16:10 -0700255{
Davide Pesaventofd1e9402023-11-13 15:40:41 -0500256 NLSR_LOG_DEBUG("Validation error: " << ve);
Yingdi Yu20e3a6e2014-05-26 23:16:10 -0700257}
258
Nick Gordonfad8e252016-08-11 14:21:38 -0500259} // namespace nlsr