fib.cpp
Go to the documentation of this file.
1 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
21 #include "fib.hpp"
22 #include "adjacency-list.hpp"
23 #include "conf-parameter.hpp"
24 #include "logger.hpp"
25 #include "nexthop-list.hpp"
26 
27 #include <map>
28 #include <cmath>
29 #include <algorithm>
30 #include <iterator>
31 
32 namespace nlsr {
33 
34 INIT_LOGGER(route.Fib);
35 
36 const uint64_t Fib::GRACE_PERIOD = 10;
37 
38 Fib::Fib(ndn::Face& face, ndn::Scheduler& scheduler, AdjacencyList& adjacencyList,
39  ConfParameter& conf, ndn::security::v2::KeyChain& keyChain)
40  : m_scheduler(scheduler)
41  , m_refreshTime(2 * conf.getLsaRefreshTime())
42  , m_controller(face, keyChain)
43  , m_adjacencyList(adjacencyList)
44  , m_confParameter(conf)
45 {
46 }
47 
48 void
49 Fib::remove(const ndn::Name& name)
50 {
51  NLSR_LOG_DEBUG("Fib::remove called");
52  std::map<ndn::Name, FibEntry>::iterator it = m_table.find(name);
53 
54  // Only unregister the prefix if it ISN'T a neighbor.
55  if (it != m_table.end() && isNotNeighbor((it->second).getName())) {
56  for (const auto& nexthop : (it->second).getNexthopList().getNextHops()) {
57  unregisterPrefix((it->second).getName(), nexthop.getConnectingFaceUri());
58  }
59  cancelEntryRefresh(it->second);
60  m_table.erase(it);
61  }
62 }
63 
64 void
65 Fib::addNextHopsToFibEntryAndNfd(FibEntry& entry, const NexthopList& hopsToAdd)
66 {
67  const ndn::Name& name = entry.getName();
68 
69  bool shouldRegister = isNotNeighbor(name);
70 
71  for (const auto& hop : hopsToAdd.getNextHops())
72  {
73  // Add nexthop to FIB entry
74  entry.getNexthopList().addNextHop(hop);
75 
76  if (shouldRegister) {
77  // Add nexthop to NDN-FIB
78  registerPrefix(name, ndn::FaceUri(hop.getConnectingFaceUri()),
79  hop.getRouteCostAsAdjustedInteger(),
80  ndn::time::seconds(m_refreshTime + GRACE_PERIOD),
81  ndn::nfd::ROUTE_FLAG_CAPTURE, 0);
82  }
83  }
84 }
85 
86 void
87 Fib::update(const ndn::Name& name, const NexthopList& allHops)
88 {
89  NLSR_LOG_DEBUG("Fib::update called");
90 
91  // Get the max possible faces which is the minimum of the configuration setting and
92  // the length of the list of all next hops.
93  unsigned int maxFaces = getNumberOfFacesForName(allHops);
94 
95  NexthopList hopsToAdd;
96  unsigned int nFaces = 0;
97 
98  // Create a list of next hops to be installed with length == maxFaces
99  for (NexthopList::iterator it = allHops.cbegin(); it != allHops.cend() && nFaces < maxFaces;
100  ++it, ++nFaces) {
101  hopsToAdd.addNextHop(*it);
102  }
103 
104  std::map<ndn::Name, FibEntry>::iterator entryIt = m_table.find(name);
105 
106  // New FIB entry that has nextHops
107  if (entryIt == m_table.end() && hopsToAdd.size() != 0) {
108  NLSR_LOG_DEBUG("New FIB Entry");
109 
110  FibEntry entry(name);
111 
112  addNextHopsToFibEntryAndNfd(entry, hopsToAdd);
113 
114  m_table.emplace(name, entry);
115 
116  entryIt = m_table.find(name);
117  }
118  // Existing FIB entry that may or may not have nextHops
119  else {
120  // Existing FIB entry
121  NLSR_LOG_DEBUG("Existing FIB Entry");
122 
123  // Remove empty FIB entry
124  if (hopsToAdd.size() == 0) {
125  remove(name);
126  return;
127  }
128 
129  FibEntry& entry = (entryIt->second);
130  addNextHopsToFibEntryAndNfd(entry, hopsToAdd);
131 
132  std::set<NextHop, NextHopComparator> hopsToRemove;
133  std::set_difference(entry.getNexthopList().begin(), entry.getNexthopList().end(),
134  hopsToAdd.begin(), hopsToAdd.end(),
135  std::inserter(hopsToRemove, hopsToRemove.end()), NextHopComparator());
136 
137  bool isUpdatable = isNotNeighbor(entry.getName());
138  // Remove the uninstalled next hops from NFD and FIB entry
139  for (const auto& hop : hopsToRemove){
140  if (isUpdatable) {
141  unregisterPrefix(entry.getName(), hop.getConnectingFaceUri());
142  }
143  NLSR_LOG_DEBUG("Removing " << hop.getConnectingFaceUri() << " from " << entry.getName());
144  entry.getNexthopList().removeNextHop(hop);
145  }
146 
147  // Increment sequence number
148  entry.setSeqNo(entry.getSeqNo() + 1);
149 
150  entryIt = m_table.find(name);
151 
152  }
153  if (entryIt != m_table.end() &&
154  !entryIt->second.getRefreshEventId() &&
155  isNotNeighbor(entryIt->second.getName())) {
156  scheduleEntryRefresh(entryIt->second,
157  [this] (FibEntry& entry) {
158  scheduleLoop(entry);
159  });
160  }
161 }
162 
163 void
165 {
166  NLSR_LOG_DEBUG("Fib::clean called");
167  // can't use const ref here as getNexthopList can't be marked const
168  for (auto&& it : m_table) {
169  NLSR_LOG_DEBUG("Canceling Scheduled event. Name: " << it.second.getName());
170  cancelEntryRefresh(it.second);
171 
172  for (const auto& hop : it.second.getNexthopList().getNextHops()) {
173  unregisterPrefix(it.second.getName(), hop.getConnectingFaceUri());
174  }
175  }
176 }
177 
178 unsigned int
179 Fib::getNumberOfFacesForName(const NexthopList& nextHopList)
180 {
181  uint32_t nNextHops = static_cast<uint32_t>(nextHopList.getNextHops().size());
182  uint32_t nMaxFaces = m_confParameter.getMaxFacesPerPrefix();
183 
184  // Allow all faces
185  if (nMaxFaces == 0) {
186  return nNextHops;
187  }
188  else {
189  return std::min(nNextHops, nMaxFaces);
190  }
191 }
192 
193 bool
194 Fib::isNotNeighbor(const ndn::Name& name)
195 {
196  return !m_adjacencyList.isNeighbor(name);
197 }
198 
199 void
200 Fib::registerPrefix(const ndn::Name& namePrefix, const ndn::FaceUri& faceUri,
201  uint64_t faceCost,
202  const ndn::time::milliseconds& timeout,
203  uint64_t flags, uint8_t times)
204 {
205  uint64_t faceId = m_adjacencyList.getFaceId(ndn::FaceUri(faceUri));
206 
207  if (faceId != 0) {
208  ndn::nfd::ControlParameters faceParameters;
209  faceParameters
210  .setName(namePrefix)
211  .setFaceId(faceId)
212  .setFlags(flags)
213  .setCost(faceCost)
214  .setExpirationPeriod(timeout)
215  .setOrigin(ndn::nfd::ROUTE_ORIGIN_NLSR);
216 
217  NLSR_LOG_DEBUG("Registering prefix: " << faceParameters.getName() << " faceUri: " << faceUri);
218  m_controller.start<ndn::nfd::RibRegisterCommand>(faceParameters,
219  std::bind(&Fib::onRegistrationSuccess, this, _1,
220  "Successful in name registration",
221  faceUri),
222  std::bind(&Fib::onRegistrationFailure, this, _1,
223  "Failed in name registration",
224  faceParameters,
225  faceUri, times));
226  }
227  else {
228  NLSR_LOG_WARN("Error: No Face Id for face uri: " << faceUri);
229  }
230 }
231 
232 void
233 Fib::onRegistrationSuccess(const ndn::nfd::ControlParameters& commandSuccessResult,
234  const std::string& message, const ndn::FaceUri& faceUri)
235 {
236  NLSR_LOG_DEBUG(message << ": " << commandSuccessResult.getName() <<
237  " Face Uri: " << faceUri << " faceId: " << commandSuccessResult.getFaceId());
238 
239  AdjacencyList::iterator adjacent = m_adjacencyList.findAdjacent(faceUri);
240  if (adjacent != m_adjacencyList.end()) {
241  adjacent->setFaceId(commandSuccessResult.getFaceId());
242  }
243 
244  // Update the fast-access FaceMap with the new Face ID, too
245  m_faceMap.update(faceUri.toString(), commandSuccessResult.getFaceId());
246  m_faceMap.writeLog();
247 }
248 
249 void
250 Fib::onRegistrationFailure(const ndn::nfd::ControlResponse& response,
251  const std::string& message,
252  const ndn::nfd::ControlParameters& parameters,
253  const ndn::FaceUri& faceUri,
254  uint8_t times)
255 {
256  NLSR_LOG_DEBUG(message << ": " << response.getText() << " (code: " << response.getCode() << ")");
257  NLSR_LOG_DEBUG("Prefix: " << parameters.getName() << " failed for: " << times);
258  if (times < 3) {
259  NLSR_LOG_DEBUG("Trying to register again...");
260  registerPrefix(parameters.getName(), faceUri,
261  parameters.getCost(),
262  parameters.getExpirationPeriod(),
263  parameters.getFlags(), times+1);
264  }
265  else {
266  NLSR_LOG_DEBUG("Registration trial given up");
267  }
268 }
269 
270 void
271 Fib::unregisterPrefix(const ndn::Name& namePrefix, const std::string& faceUri)
272 {
273  uint32_t faceId = m_faceMap.getFaceId(faceUri);
274  NLSR_LOG_DEBUG("Unregister prefix: " << namePrefix << " Face Uri: " << faceUri);
275  if (faceId > 0) {
276  ndn::nfd::ControlParameters controlParameters;
277  controlParameters
278  .setName(namePrefix)
279  .setFaceId(faceId)
280  .setOrigin(ndn::nfd::ROUTE_ORIGIN_NLSR);
281  m_controller.start<ndn::nfd::RibUnregisterCommand>(controlParameters,
282  std::bind(&Fib::onUnregistrationSuccess, this, _1,
283  "Successful in unregistering name"),
284  std::bind(&Fib::onUnregistrationFailure,
285  this, _1,
286  "Failed in unregistering name"));
287  }
288 }
289 
290 void
291 Fib::onUnregistrationSuccess(const ndn::nfd::ControlParameters& commandSuccessResult,
292  const std::string& message)
293 {
294  NLSR_LOG_DEBUG("Unregister successful Prefix: " << commandSuccessResult.getName() <<
295  " Face Id: " << commandSuccessResult.getFaceId());
296 }
297 
298 void
299 Fib::onUnregistrationFailure(const ndn::nfd::ControlResponse& response,
300  const std::string& message)
301 {
302  NLSR_LOG_DEBUG(message << ": " << response.getText() << " (code: " << response.getCode() << ")");
303 }
304 
305 void
306 Fib::setStrategy(const ndn::Name& name, const std::string& strategy, uint32_t count)
307 {
308  ndn::nfd::ControlParameters parameters;
309  parameters
310  .setName(name)
311  .setStrategy(strategy);
312 
313  m_controller.start<ndn::nfd::StrategyChoiceSetCommand>(parameters,
314  std::bind(&Fib::onSetStrategySuccess, this, _1,
315  "Successfully set strategy choice"),
316  std::bind(&Fib::onSetStrategyFailure, this, _1,
317  parameters,
318  count,
319  "Failed to set strategy choice"));
320 }
321 
322 void
323 Fib::onSetStrategySuccess(const ndn::nfd::ControlParameters& commandSuccessResult,
324  const std::string& message)
325 {
326  NLSR_LOG_DEBUG(message << ": " << commandSuccessResult.getStrategy() <<
327  " for name: " << commandSuccessResult.getName());
328 }
329 
330 void
331 Fib::onSetStrategyFailure(const ndn::nfd::ControlResponse& response,
332  const ndn::nfd::ControlParameters& parameters,
333  uint32_t count,
334  const std::string& message)
335 {
336  NLSR_LOG_DEBUG(message << ": " << parameters.getStrategy() <<
337  " for name: " << parameters.getName());
338  if (count < 3) {
339  setStrategy(parameters.getName(), parameters.getStrategy().toUri(), count + 1);
340  }
341 }
342 
343 void
344 Fib::scheduleEntryRefresh(FibEntry& entry, const afterRefreshCallback& refreshCallback)
345 {
346  NLSR_LOG_DEBUG("Scheduling refresh for " << entry.getName() <<
347  " Seq Num: " << entry.getSeqNo() <<
348  " in " << m_refreshTime << " seconds");
349 
350  entry.setRefreshEventId(m_scheduler.scheduleEvent(ndn::time::seconds(m_refreshTime),
351  std::bind(&Fib::refreshEntry, this,
352  entry.getName(), refreshCallback)));
353 }
354 
355 void
356 Fib::scheduleLoop(FibEntry& entry)
357 {
358  scheduleEntryRefresh(entry, std::bind(&Fib::scheduleLoop, this, _1));
359 }
360 
361 void
362 Fib::cancelEntryRefresh(const FibEntry& entry)
363 {
364  NLSR_LOG_DEBUG("Canceling refresh for " << entry.getName() << " Seq Num: " << entry.getSeqNo());
365 
366  m_scheduler.cancelEvent(entry.getRefreshEventId());
367  entry.getRefreshEventId().reset();
368 }
369 
370 void
371 Fib::refreshEntry(const ndn::Name& name, afterRefreshCallback refreshCb)
372 {
373  std::map<ndn::Name, FibEntry>::iterator it = m_table.find(name);
374 
375  if (it == m_table.end()) {
376  return;
377  }
378 
379  FibEntry& entry = it->second;
380  NLSR_LOG_DEBUG("Refreshing " << entry.getName() << " Seq Num: " << entry.getSeqNo());
381 
382  // Increment sequence number
383  entry.setSeqNo(entry.getSeqNo() + 1);
384 
385  for (const NextHop& hop : entry) {
386  registerPrefix(entry.getName(),
387  ndn::FaceUri(hop.getConnectingFaceUri()),
388  hop.getRouteCostAsAdjustedInteger(),
389  ndn::time::seconds(m_refreshTime + GRACE_PERIOD),
390  ndn::nfd::ROUTE_FLAG_CAPTURE, 0);
391  }
392 
393  refreshCb(entry);
394 }
395 
396 void
398 {
399  NLSR_LOG_DEBUG("-------------------FIB-----------------------------");
400  for (const auto& entry : m_table) {
401  entry.second.writeLog();
402  }
403 }
404 
405 } // namespace nlsr
void writeLog()
Definition: fib.cpp:397
#define NLSR_LOG_WARN(x)
Definition: logger.hpp:40
A class to house all the configuration parameters for NLSR.
const std::set< NextHop, NextHopComparator > & getNextHops() const
void update(const ndn::Name &name, const NexthopList &allHops)
Set the nexthop list of a name.
Definition: fib.cpp:87
size_t size() const
const_iterator cend() const
bool isNeighbor(const ndn::Name &adjName) const
#define NLSR_LOG_DEBUG(x)
Definition: logger.hpp:38
void setStrategy(const ndn::Name &name, const std::string &strategy, uint32_t count)
Definition: fib.cpp:306
const_iterator cbegin() const
Copyright (c) 2014-2018, The University of Memphis, Regents of the University of California.
#define INIT_LOGGER(name)
Definition: logger.hpp:35
uint32_t getMaxFacesPerPrefix() const
ndn::EventId getRefreshEventId() const
Definition: fib-entry.hpp:66
NexthopList & getNexthopList()
Definition: fib-entry.hpp:54
void setSeqNo(int32_t fsn)
Definition: fib-entry.hpp:72
void setRefreshEventId(ndn::EventId id)
Definition: fib-entry.hpp:60
void clean()
Remove all entries from the FIB.
Definition: fib.cpp:164
int32_t getSeqNo() const
Definition: fib-entry.hpp:78
void writeLog()
Definition: face-map.cpp:35
Fib(ndn::Face &face, ndn::Scheduler &scheduler, AdjacencyList &adjacencyList, ConfParameter &conf, ndn::security::v2::KeyChain &keyChain)
Definition: fib.cpp:38
void writeLog() const
Definition: fib-entry.cpp:29
Copyright (c) 2014-2018, The University of Memphis, Regents of the University of California, Arizona Board of Regents.
const ndn::Name & getName() const
Definition: fib-entry.hpp:48
AdjacencyList::iterator findAdjacent(const ndn::Name &adjName)
void addNextHop(const NextHop &nh)
Adds a next hop to the list.
void remove(const ndn::Name &name)
Completely remove a name prefix from the FIB.
Definition: fib.cpp:49
std::set< NextHop, NextHopComparator >::iterator iterator
std::list< Adjacent >::iterator iterator
uint64_t getFaceId(const ndn::FaceUri &faceUri)
void removeNextHop(const NextHop &nh)
Remove a next hop from the Next Hop list.
void update(const std::string &faceUri, uint32_t faceId)
Definition: face-map.hpp:89
std::function< void(FibEntry &)> afterRefreshCallback
Definition: fib.hpp:34
const_iterator end() const
uint32_t getFaceId(const std::string &faceUri)
Definition: face-map.hpp:102
void registerPrefix(const ndn::Name &namePrefix, const ndn::FaceUri &faceUri, uint64_t faceCost, const ndn::time::milliseconds &timeout, uint64_t flags, uint8_t times)
Inform NFD of a next-hop.
Definition: fib.cpp:200