hello-protocol.cpp
Go to the documentation of this file.
1 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
2 /*
3  * Copyright (c) 2014-2019, The University of Memphis,
4  * Regents of the University of California
5  *
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/>.
19  **/
20 
21 #include "hello-protocol.hpp"
22 #include "nlsr.hpp"
23 #include "lsdb.hpp"
24 #include "utility/name-helper.hpp"
25 #include "logger.hpp"
26 
27 namespace nlsr {
28 
29 INIT_LOGGER(HelloProtocol);
30 
31 const std::string HelloProtocol::INFO_COMPONENT = "INFO";
32 const std::string HelloProtocol::NLSR_COMPONENT = "nlsr";
33 
34 HelloProtocol::HelloProtocol(ndn::Face& face, ndn::KeyChain& keyChain,
35  ndn::security::SigningInfo& signingInfo,
36  ConfParameter& confParam, RoutingTable& routingTable,
37  Lsdb& lsdb)
38  : m_face(face)
39  , m_scheduler(m_face.getIoService())
40  , m_keyChain(keyChain)
41  , m_signingInfo(signingInfo)
42  , m_confParam(confParam)
43  , m_routingTable(routingTable)
44  , m_lsdb(lsdb)
45  , m_adjacencyList(m_confParam.getAdjacencyList())
46 {
47 }
48 
49 void
50 HelloProtocol::expressInterest(const ndn::Name& interestName, uint32_t seconds)
51 {
52  NLSR_LOG_DEBUG("Expressing Interest: " << interestName);
53  ndn::Interest interest(interestName);
54  interest.setInterestLifetime(ndn::time::seconds(seconds));
55  interest.setMustBeFresh(true);
56  interest.setCanBePrefix(true);
57  m_face.expressInterest(interest,
58  std::bind(&HelloProtocol::onContent, this, _1, _2),
59  [this, seconds] (const ndn::Interest& interest, const ndn::lp::Nack& nack)
60  {
61  NDN_LOG_TRACE("Received Nack with reason: " << nack.getReason());
62  NDN_LOG_TRACE("Will treat as timeout in " << 2 * seconds << " seconds");
63  m_scheduler.schedule(ndn::time::seconds(2 * seconds),
64  [this, interest] { processInterestTimedOut(interest); });
65  },
66  std::bind(&HelloProtocol::processInterestTimedOut, this, _1));
67 
68  // increment SENT_HELLO_INTEREST
70 }
71 
72 void
73 HelloProtocol::sendHelloInterest(const ndn::Name& neighbor)
74 {
75  auto adjacent = m_adjacencyList.findAdjacent(neighbor);
76 
77  if (adjacent == m_adjacencyList.end()) {
78  return;
79  }
80 
81  // If this adjacency has a Face, just proceed as usual.
82  if(adjacent->getFaceId() != 0) {
83  // interest name: /<neighbor>/NLSR/INFO/<router>
84  ndn::Name interestName = adjacent->getName() ;
85  interestName.append(NLSR_COMPONENT);
86  interestName.append(INFO_COMPONENT);
87  interestName.append(m_confParam.getRouterPrefix().wireEncode());
88  expressInterest(interestName, m_confParam.getInterestResendTime());
89  NLSR_LOG_DEBUG("Sending HELLO interest: " << interestName);
90  }
91 
92  m_scheduler.schedule(ndn::time::seconds(m_confParam.getInfoInterestInterval()),
93  [this, neighbor] { sendHelloInterest(neighbor); });
94 }
95 
96 void
97 HelloProtocol::processInterest(const ndn::Name& name,
98  const ndn::Interest& interest)
99 {
100  // interest name: /<neighbor>/NLSR/INFO/<router>
101  const ndn::Name interestName = interest.getName();
102 
103  // increment RCV_HELLO_INTEREST
105 
106  NLSR_LOG_DEBUG("Interest Received for Name: " << interestName);
107  if (interestName.get(-2).toUri() != INFO_COMPONENT) {
108  NLSR_LOG_DEBUG("INFO_COMPONENT not found or interestName: " << interestName
109  << " does not match expression");
110  return;
111  }
112 
113  ndn::Name neighbor;
114  neighbor.wireDecode(interestName.get(-1).blockFromValue());
115  NLSR_LOG_DEBUG("Neighbor: " << neighbor);
116  if (m_adjacencyList.isNeighbor(neighbor)) {
117  std::shared_ptr<ndn::Data> data = std::make_shared<ndn::Data>();
118  data->setName(ndn::Name(interest.getName()).appendVersion());
119  data->setFreshnessPeriod(ndn::time::seconds(10)); // 10 sec
120  data->setContent(reinterpret_cast<const uint8_t*>(INFO_COMPONENT.c_str()),
121  INFO_COMPONENT.size());
122 
123  m_keyChain.sign(*data, m_signingInfo);
124 
125  NLSR_LOG_DEBUG("Sending out data for name: " << interest.getName());
126 
127  m_face.put(*data);
128  // increment SENT_HELLO_DATA
130 
131  auto adjacent = m_adjacencyList.findAdjacent(neighbor);
132  // If this neighbor was previously inactive, send our own hello interest, too
133  if (adjacent->getStatus() == Adjacent::STATUS_INACTIVE) {
134  // We can only do that if the neighbor currently has a face.
135  if(adjacent->getFaceId() != 0){
136  // interest name: /<neighbor>/NLSR/INFO/<router>
137  ndn::Name interestName(neighbor);
138  interestName.append(NLSR_COMPONENT);
139  interestName.append(INFO_COMPONENT);
140  interestName.append(m_confParam.getRouterPrefix().wireEncode());
141  expressInterest(interestName, m_confParam.getInterestResendTime());
142  }
143  }
144  }
145 }
146 
147 void
148 HelloProtocol::processInterestTimedOut(const ndn::Interest& interest)
149 {
150  // interest name: /<neighbor>/NLSR/INFO/<router>
151  const ndn::Name interestName(interest.getName());
152  NLSR_LOG_DEBUG("Interest timed out for Name: " << interestName);
153  if (interestName.get(-2).toUri() != INFO_COMPONENT) {
154  return;
155  }
156  ndn::Name neighbor = interestName.getPrefix(-3);
157  NLSR_LOG_DEBUG("Neighbor: " << neighbor);
158  m_adjacencyList.incrementTimedOutInterestCount(neighbor);
159 
160  Adjacent::Status status = m_adjacencyList.getStatusOfNeighbor(neighbor);
161 
162  uint32_t infoIntTimedOutCount = m_adjacencyList.getTimedOutInterestCount(neighbor);
163  NLSR_LOG_DEBUG("Status: " << status);
164  NLSR_LOG_DEBUG("Info Interest Timed out: " << infoIntTimedOutCount);
165  if (infoIntTimedOutCount <= m_confParam.getInterestRetryNumber()) {
166  // interest name: /<neighbor>/NLSR/INFO/<router>
167  ndn::Name interestName(neighbor);
168  interestName.append(NLSR_COMPONENT);
169  interestName.append(INFO_COMPONENT);
170  interestName.append(m_confParam.getRouterPrefix().wireEncode());
171  NLSR_LOG_DEBUG("Resending interest: " << interestName);
172  expressInterest(interestName, m_confParam.getInterestResendTime());
173  }
174  else if ((status == Adjacent::STATUS_ACTIVE) &&
175  (infoIntTimedOutCount == m_confParam.getInterestRetryNumber())) {
176  m_adjacencyList.setStatusOfNeighbor(neighbor, Adjacent::STATUS_INACTIVE);
177 
178  NLSR_LOG_DEBUG("Neighbor: " << neighbor << " status changed to INACTIVE");
179 
180  m_lsdb.scheduleAdjLsaBuild();
181  }
182 }
183 
184  // This is the first function that incoming Hello data will
185  // see. This checks if the data appears to be signed, and passes it
186  // on to validate the content of the data.
187 void
188 HelloProtocol::onContent(const ndn::Interest& interest, const ndn::Data& data)
189 {
190  NLSR_LOG_DEBUG("Received data for INFO(name): " << data.getName());
191  if (data.getSignature().hasKeyLocator() &&
192  data.getSignature().getKeyLocator().getType() == ndn::tlv::Name) {
193  NLSR_LOG_DEBUG("Data signed with: " << data.getSignature().getKeyLocator().getName());
194  }
195  m_confParam.getValidator().validate(data,
196  std::bind(&HelloProtocol::onContentValidated, this, _1),
197  std::bind(&HelloProtocol::onContentValidationFailed,
198  this, _1, _2));
199 }
200 
201 void
202 HelloProtocol::onContentValidated(const ndn::Data& data)
203 {
204  // data name: /<neighbor>/NLSR/INFO/<router>/<version>
205  ndn::Name dataName = data.getName();
206  NLSR_LOG_DEBUG("Data validation successful for INFO(name): " << dataName);
207 
208  if (dataName.get(-3).toUri() == INFO_COMPONENT) {
209  ndn::Name neighbor = dataName.getPrefix(-4);
210 
211  Adjacent::Status oldStatus = m_adjacencyList.getStatusOfNeighbor(neighbor);
212  m_adjacencyList.setStatusOfNeighbor(neighbor, Adjacent::STATUS_ACTIVE);
213  m_adjacencyList.setTimedOutInterestCount(neighbor, 0);
214  Adjacent::Status newStatus = m_adjacencyList.getStatusOfNeighbor(neighbor);
215 
216  NLSR_LOG_DEBUG("Neighbor : " << neighbor);
217  NLSR_LOG_DEBUG("Old Status: " << oldStatus << " New Status: " << newStatus);
218  // change in Adjacency list
219  if ((oldStatus - newStatus) != 0) {
220  if (m_confParam.getHyperbolicState() == HYPERBOLIC_STATE_ON) {
221  m_routingTable.scheduleRoutingTableCalculation();
222  }
223  else {
224  m_lsdb.scheduleAdjLsaBuild();
225  }
226  }
227 
228  onHelloDataValidated(neighbor);
229  }
230  // increment RCV_HELLO_DATA
232 }
233 
234 void
235 HelloProtocol::onContentValidationFailed(const ndn::Data& data,
236  const ndn::security::v2::ValidationError& ve)
237 {
238  NLSR_LOG_DEBUG("Validation Error: " << ve);
239 }
240 
241 } // namespace nlsr
uint32_t getInterestResendTime() const
void setTimedOutInterestCount(const ndn::Name &neighbor, uint32_t count)
ndn::security::ValidatorConfig & getValidator()
A class to house all the configuration parameters for NLSR.
void scheduleAdjLsaBuild()
Schedules a build of this router&#39;s LSA.
Definition: lsdb.cpp:555
ndn::util::signal::Signal< HelloProtocol, Statistics::PacketType > hpIncrementSignal
void scheduleRoutingTableCalculation()
Schedules a calculation event in the event scheduler only if one isn&#39;t already scheduled.
bool isNeighbor(const ndn::Name &adjName) const
#define NLSR_LOG_DEBUG(x)
Definition: logger.hpp:38
uint32_t getInfoInterestInterval() const
const ndn::Name & getRouterPrefix() const
Adjacent::Status getStatusOfNeighbor(const ndn::Name &neighbor) const
Copyright (c) 2014-2018, The University of Memphis, Regents of the University of California.
void expressInterest(const ndn::Name &interestNamePrefix, uint32_t seconds)
Sends a Hello Interest packet.
HelloProtocol(ndn::Face &face, ndn::KeyChain &keyChain, ndn::security::SigningInfo &signingInfo, ConfParameter &confParam, RoutingTable &routingTable, Lsdb &lsdb)
#define INIT_LOGGER(name)
Definition: logger.hpp:35
uint32_t getInterestRetryNumber() const
ndn::util::Signal< HelloProtocol, const ndn::Name & > onHelloDataValidated
void processInterest(const ndn::Name &name, const ndn::Interest &interest)
Processes a Hello Interest from a neighbor.
int32_t getTimedOutInterestCount(const ndn::Name &neighbor) const
void sendHelloInterest(const ndn::Name &neighbor)
Sends Hello Interests to all neighbors.
Copyright (c) 2014-2019, The University of Memphis, Regents of the University of California, Arizona Board of Regents.
AdjacencyList::iterator findAdjacent(const ndn::Name &adjName)
int32_t getHyperbolicState() const
void incrementTimedOutInterestCount(const ndn::Name &neighbor)
void setStatusOfNeighbor(const ndn::Name &neighbor, Adjacent::Status status)
const_iterator end() const