blob: 9f09442e4ec52295bf6c6582f1ec36a83c395f22 [file] [log] [blame]
Alexander Afanasyev3ecec502014-04-16 13:42:44 -07001/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
2/**
Vince12e49462014-06-09 13:29:32 -05003 * Copyright (c) 2014, Regents of the University of California,
4 * Arizona Board of Regents,
5 * Colorado State University,
6 * University Pierre & Marie Curie, Sorbonne University,
7 * Washington University in St. Louis,
8 * Beijing Institute of Technology,
9 * The University of Memphis
Alexander Afanasyev3ecec502014-04-16 13:42:44 -070010 *
11 * This file is part of NFD (Named Data Networking Forwarding Daemon).
12 * See AUTHORS.md for complete list of NFD authors and contributors.
13 *
14 * NFD is free software: you can redistribute it and/or modify it under the terms
15 * of the GNU General Public License as published by the Free Software Foundation,
16 * either version 3 of the License, or (at your option) any later version.
17 *
18 * NFD is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
19 * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
20 * PURPOSE. See the GNU General Public License for more details.
21 *
22 * You should have received a copy of the GNU General Public License along with
23 * NFD, e.g., in COPYING.md file. If not, see <http://www.gnu.org/licenses/>.
Vince12e49462014-06-09 13:29:32 -050024 */
Alexander Afanasyev3ecec502014-04-16 13:42:44 -070025
26#include "rib-manager.hpp"
Alexander Afanasyev03ea3eb2014-04-17 18:19:06 -070027#include "core/global-io.hpp"
Alexander Afanasyev89cf5e02014-04-17 12:08:57 -070028#include "core/logger.hpp"
Alexander Afanasyev63108c42014-07-07 19:10:47 -070029#include "core/scheduler.hpp"
Vince Lehmancd613c52014-07-30 14:34:49 -050030#include <ndn-cxx/management/nfd-face-status.hpp>
Alexander Afanasyev3ecec502014-04-16 13:42:44 -070031
32namespace nfd {
33namespace rib {
34
Alexander Afanasyev89cf5e02014-04-17 12:08:57 -070035NFD_LOG_INIT("RibManager");
36
Alexander Afanasyev20d31442014-04-19 17:00:53 -070037const Name RibManager::COMMAND_PREFIX = "/localhost/nfd/rib";
38const Name RibManager::REMOTE_COMMAND_PREFIX = "/localhop/nfd/rib";
Vince Lehmancd613c52014-07-30 14:34:49 -050039const Name RibManager::FACES_LIST_DATASET_PREFIX = "/localhost/nfd/faces/list";
Alexander Afanasyev3ecec502014-04-16 13:42:44 -070040
41const size_t RibManager::COMMAND_UNSIGNED_NCOMPS =
42 RibManager::COMMAND_PREFIX.size() +
43 1 + // verb
44 1; // verb options
45
46const size_t RibManager::COMMAND_SIGNED_NCOMPS =
47 RibManager::COMMAND_UNSIGNED_NCOMPS +
48 4; // (timestamp, nonce, signed info tlv, signature tlv)
49
Vince Lehmancd16c832014-07-23 15:14:55 -070050const RibManager::SignedVerbAndProcessor RibManager::SIGNED_COMMAND_VERBS[] =
Alexander Afanasyev3ecec502014-04-16 13:42:44 -070051 {
Vince Lehmancd16c832014-07-23 15:14:55 -070052 SignedVerbAndProcessor(
53 Name::Component("register"),
54 &RibManager::registerEntry
55 ),
Alexander Afanasyev3ecec502014-04-16 13:42:44 -070056
Vince Lehmancd16c832014-07-23 15:14:55 -070057 SignedVerbAndProcessor(
58 Name::Component("unregister"),
59 &RibManager::unregisterEntry
60 ),
Alexander Afanasyev3ecec502014-04-16 13:42:44 -070061 };
62
Vince Lehmancd16c832014-07-23 15:14:55 -070063const RibManager::UnsignedVerbAndProcessor RibManager::UNSIGNED_COMMAND_VERBS[] =
64 {
65 UnsignedVerbAndProcessor(
66 Name::Component("list"),
67 &RibManager::listEntries
68 ),
69 };
70
71const Name RibManager::LIST_COMMAND_PREFIX("/localhost/nfd/rib/list");
72const size_t RibManager::LIST_COMMAND_NCOMPS = LIST_COMMAND_PREFIX.size();
73
Vince Lehman26b215c2014-08-17 15:00:41 -050074const time::seconds RibManager::ACTIVE_FACE_FETCH_INTERVAL = time::seconds(300);
75
Vince Lehman72446ec2014-07-09 10:50:02 -050076RibManager::RibManager(ndn::Face& face)
77 : m_face(face)
Alexander Afanasyevb3893c92014-05-15 01:49:54 -070078 , m_nfdController(m_face)
Yingdi Yue5224e92014-04-29 18:04:02 -070079 , m_localhostValidator(m_face)
80 , m_localhopValidator(m_face)
Yingdi Yuf4db0b52014-04-17 13:17:39 -070081 , m_faceMonitor(m_face)
Yingdi Yue5224e92014-04-29 18:04:02 -070082 , m_isLocalhopEnabled(false)
Vince Lehmancd16c832014-07-23 15:14:55 -070083 , m_ribStatusPublisher(m_managedRib, face, LIST_COMMAND_PREFIX, m_keyChain)
Vince Lehman4387e782014-06-19 16:57:45 -050084 , m_lastTransactionId(0)
Vince Lehmancd16c832014-07-23 15:14:55 -070085 , m_signedVerbDispatch(SIGNED_COMMAND_VERBS,
86 SIGNED_COMMAND_VERBS +
87 (sizeof(SIGNED_COMMAND_VERBS) / sizeof(SignedVerbAndProcessor)))
88 , m_unsignedVerbDispatch(UNSIGNED_COMMAND_VERBS,
89 UNSIGNED_COMMAND_VERBS +
90 (sizeof(UNSIGNED_COMMAND_VERBS) / sizeof(UnsignedVerbAndProcessor)))
Alexander Afanasyev3ecec502014-04-16 13:42:44 -070091{
92}
93
Vince Lehman26b215c2014-08-17 15:00:41 -050094RibManager::~RibManager()
95{
96 scheduler::cancel(m_activeFaceFetchEvent);
97}
98
Alexander Afanasyev3ecec502014-04-16 13:42:44 -070099void
Junxiao Shia3295742014-05-16 22:40:10 -0700100RibManager::startListening(const Name& commandPrefix, const ndn::OnInterest& onRequest)
101{
102 NFD_LOG_INFO("Listening on: " << commandPrefix);
103
104 m_nfdController.start<ndn::nfd::FibAddNextHopCommand>(
105 ControlParameters()
106 .setName(commandPrefix)
107 .setFaceId(0),
108 bind(&RibManager::onNrdCommandPrefixAddNextHopSuccess, this, cref(commandPrefix)),
109 bind(&RibManager::onNrdCommandPrefixAddNextHopError, this, cref(commandPrefix), _2));
110
111 m_face.setInterestFilter(commandPrefix, onRequest);
112}
113
114void
Alexander Afanasyev3ecec502014-04-16 13:42:44 -0700115RibManager::registerWithNfd()
116{
117 //check whether the components of localhop and localhost prefixes are same
118 BOOST_ASSERT(COMMAND_PREFIX.size() == REMOTE_COMMAND_PREFIX.size());
119
Junxiao Shia3295742014-05-16 22:40:10 -0700120 this->startListening(COMMAND_PREFIX, bind(&RibManager::onLocalhostRequest, this, _2));
Alexander Afanasyevb3893c92014-05-15 01:49:54 -0700121
Junxiao Shia3295742014-05-16 22:40:10 -0700122 if (m_isLocalhopEnabled) {
123 this->startListening(REMOTE_COMMAND_PREFIX,
124 bind(&RibManager::onLocalhopRequest, this, _2));
125 }
Alexander Afanasyev3ecec502014-04-16 13:42:44 -0700126
Alexander Afanasyev89cf5e02014-04-17 12:08:57 -0700127 NFD_LOG_INFO("Start monitoring face create/destroy events");
Junxiao Shi15b12e72014-08-09 19:56:24 -0700128 m_faceMonitor.onNotification += bind(&RibManager::onNotification, this, _1);
129 m_faceMonitor.start();
Vince Lehmancd613c52014-07-30 14:34:49 -0500130
Vince Lehman26b215c2014-08-17 15:00:41 -0500131 scheduleActiveFaceFetch(ACTIVE_FACE_FETCH_INTERVAL);
Alexander Afanasyev3ecec502014-04-16 13:42:44 -0700132}
133
134void
135RibManager::setConfigFile(ConfigFile& configFile)
136{
Yingdi Yue5224e92014-04-29 18:04:02 -0700137 configFile.addSectionHandler("rib",
Alexander Afanasyev3ecec502014-04-16 13:42:44 -0700138 bind(&RibManager::onConfig, this, _1, _2, _3));
139}
140
141void
142RibManager::onConfig(const ConfigSection& configSection,
Yingdi Yuf4db0b52014-04-17 13:17:39 -0700143 bool isDryRun,
144 const std::string& filename)
Alexander Afanasyev3ecec502014-04-16 13:42:44 -0700145{
Yingdi Yue5224e92014-04-29 18:04:02 -0700146 for (ConfigSection::const_iterator i = configSection.begin();
147 i != configSection.end(); ++i)
148 {
149 if (i->first == "localhost_security")
150 m_localhostValidator.load(i->second, filename);
151 else if (i->first == "localhop_security")
152 {
153 m_localhopValidator.load(i->second, filename);
154 m_isLocalhopEnabled = true;
155 }
156 else
157 throw Error("Unrecognized rib property: " + i->first);
158 }
Alexander Afanasyev3ecec502014-04-16 13:42:44 -0700159}
160
161void
Alexander Afanasyev3ecec502014-04-16 13:42:44 -0700162RibManager::sendResponse(const Name& name,
163 const ControlResponse& response)
164{
165 const Block& encodedControl = response.wireEncode();
166
Alexander Afanasyev97a9c2c2014-07-18 16:57:57 -0700167 shared_ptr<Data> responseData = make_shared<Data>(name);
168 responseData->setContent(encodedControl);
Alexander Afanasyev3ecec502014-04-16 13:42:44 -0700169
Alexander Afanasyev97a9c2c2014-07-18 16:57:57 -0700170 m_keyChain.sign(*responseData);
171 m_face.put(*responseData);
Alexander Afanasyev3ecec502014-04-16 13:42:44 -0700172}
173
174void
175RibManager::sendResponse(const Name& name,
176 uint32_t code,
177 const std::string& text)
178{
179 ControlResponse response(code, text);
180 sendResponse(name, response);
181}
182
183void
Yingdi Yue5224e92014-04-29 18:04:02 -0700184RibManager::onLocalhostRequest(const Interest& request)
Alexander Afanasyev3ecec502014-04-16 13:42:44 -0700185{
Vince Lehmancd16c832014-07-23 15:14:55 -0700186 const Name& command = request.getName();
187 const Name::Component& verb = command.get(COMMAND_PREFIX.size());
188
189 UnsignedVerbDispatchTable::const_iterator unsignedVerbProcessor = m_unsignedVerbDispatch.find(verb);
190
191 if (unsignedVerbProcessor != m_unsignedVerbDispatch.end())
192 {
193 NFD_LOG_DEBUG("command result: processing unsigned verb: " << verb);
194 (unsignedVerbProcessor->second)(this, request);
195 }
196 else
197 {
198 m_localhostValidator.validate(request,
199 bind(&RibManager::onCommandValidated, this, _1),
200 bind(&RibManager::onCommandValidationFailed, this, _1, _2));
201 }
Yingdi Yue5224e92014-04-29 18:04:02 -0700202}
203
204void
205RibManager::onLocalhopRequest(const Interest& request)
206{
207 m_localhopValidator.validate(request,
208 bind(&RibManager::onCommandValidated, this, _1),
209 bind(&RibManager::onCommandValidationFailed, this, _1, _2));
Alexander Afanasyev3ecec502014-04-16 13:42:44 -0700210}
211
212void
Alexander Afanasyev20d31442014-04-19 17:00:53 -0700213RibManager::onCommandValidated(const shared_ptr<const Interest>& request)
Alexander Afanasyev3ecec502014-04-16 13:42:44 -0700214{
Alexander Afanasyev20d31442014-04-19 17:00:53 -0700215 // REMOTE_COMMAND_PREFIX number of componenets are same as
Alexander Afanasyev3ecec502014-04-16 13:42:44 -0700216 // NRD_COMMAND_PREFIX's so no extra checks are required.
Alexander Afanasyev3ecec502014-04-16 13:42:44 -0700217
Alexander Afanasyev20d31442014-04-19 17:00:53 -0700218 const Name& command = request->getName();
219 const Name::Component& verb = command[COMMAND_PREFIX.size()];
220 const Name::Component& parameterComponent = command[COMMAND_PREFIX.size() + 1];
221
Vince Lehmancd16c832014-07-23 15:14:55 -0700222 SignedVerbDispatchTable::const_iterator verbProcessor = m_signedVerbDispatch.find(verb);
223 if (verbProcessor != m_signedVerbDispatch.end())
Alexander Afanasyev3ecec502014-04-16 13:42:44 -0700224 {
Alexander Afanasyev20d31442014-04-19 17:00:53 -0700225 ControlParameters parameters;
226 if (!extractParameters(parameterComponent, parameters))
Alexander Afanasyev3ecec502014-04-16 13:42:44 -0700227 {
Alexander Afanasyev20d31442014-04-19 17:00:53 -0700228 NFD_LOG_DEBUG("command result: malformed verb: " << verb);
Syed Obaid3313a372014-07-01 01:31:33 -0500229 if (static_cast<bool>(request))
230 sendResponse(command, 400, "Malformed command");
Alexander Afanasyev3ecec502014-04-16 13:42:44 -0700231 return;
232 }
233
Alexander Afanasyev20d31442014-04-19 17:00:53 -0700234 NFD_LOG_DEBUG("command result: processing verb: " << verb);
235 (verbProcessor->second)(this, request, parameters);
Alexander Afanasyev3ecec502014-04-16 13:42:44 -0700236 }
237 else
238 {
Alexander Afanasyev89cf5e02014-04-17 12:08:57 -0700239 NFD_LOG_DEBUG("Unsupported command: " << verb);
Syed Obaid3313a372014-07-01 01:31:33 -0500240 if (static_cast<bool>(request))
241 sendResponse(request->getName(), 501, "Unsupported command");
Alexander Afanasyev3ecec502014-04-16 13:42:44 -0700242 }
243}
244
245void
Alexander Afanasyev20d31442014-04-19 17:00:53 -0700246RibManager::registerEntry(const shared_ptr<const Interest>& request,
247 ControlParameters& parameters)
248{
249 ndn::nfd::RibRegisterCommand command;
250
251 if (!validateParameters(command, parameters))
252 {
253 NFD_LOG_DEBUG("register result: FAIL reason: malformed");
Vince Lehmancd613c52014-07-30 14:34:49 -0500254
Syed Obaid3313a372014-07-01 01:31:33 -0500255 if (static_cast<bool>(request))
Vince Lehmancd613c52014-07-30 14:34:49 -0500256 {
257 sendResponse(request->getName(), 400, "Malformed command");
258 }
259
Alexander Afanasyev20d31442014-04-19 17:00:53 -0700260 return;
261 }
262
Alexander Afanasyev483efd12014-08-14 10:51:18 -0700263 bool isSelfRegistration = (!parameters.hasFaceId() || parameters.getFaceId() == 0);
264 if (isSelfRegistration)
Alexander Afanasyevfb1c8082014-07-17 15:16:15 -0700265 {
266 parameters.setFaceId(request->getIncomingFaceId());
267 }
268
Vince12e49462014-06-09 13:29:32 -0500269 FaceEntry faceEntry;
270 faceEntry.faceId = parameters.getFaceId();
271 faceEntry.origin = parameters.getOrigin();
272 faceEntry.cost = parameters.getCost();
273 faceEntry.flags = parameters.getFlags();
Syed Obaid3313a372014-07-01 01:31:33 -0500274
Alexander Afanasyevf67cf082014-07-18 16:47:29 -0700275 if (parameters.hasExpirationPeriod() &&
276 parameters.getExpirationPeriod() != time::milliseconds::max())
Syed Obaid3313a372014-07-01 01:31:33 -0500277 {
278 faceEntry.expires = time::steady_clock::now() + parameters.getExpirationPeriod();
279
280 // Schedule a new event, the old one will be cancelled during rib insertion.
281 EventId eventId;
Syed Obaid3313a372014-07-01 01:31:33 -0500282 eventId = scheduler::schedule(parameters.getExpirationPeriod(),
Vince Lehman281ded72014-08-21 12:17:08 -0500283 bind(&RibManager::expireEntry,
Syed Obaid3313a372014-07-01 01:31:33 -0500284 this, shared_ptr<Interest>(), parameters));
Vince Lehman281ded72014-08-21 12:17:08 -0500285 NFD_LOG_TRACE("Scheduled unregistration at: " << faceEntry.expires <<
286 " with EventId: " << eventId);
Syed Obaid3313a372014-07-01 01:31:33 -0500287
288 //set the NewEventId of this entry
289 faceEntry.setExpirationEvent(eventId);
290 }
291 else
292 {
293 faceEntry.expires = time::steady_clock::TimePoint::max();
294 }
Alexander Afanasyev20d31442014-04-19 17:00:53 -0700295
Vince12e49462014-06-09 13:29:32 -0500296 NFD_LOG_TRACE("register prefix: " << faceEntry);
Alexander Afanasyev20d31442014-04-19 17:00:53 -0700297
Vince12e49462014-06-09 13:29:32 -0500298 m_managedRib.insert(parameters.getName(), faceEntry);
Vince Lehman26b215c2014-08-17 15:00:41 -0500299 m_registeredFaces.insert(faceEntry.faceId);
Vince Lehman4387e782014-06-19 16:57:45 -0500300
301 sendUpdatesToFib(request, parameters);
Alexander Afanasyev20d31442014-04-19 17:00:53 -0700302}
303
304void
Vince Lehman281ded72014-08-21 12:17:08 -0500305RibManager::expireEntry(const shared_ptr<const Interest>& request, ControlParameters& params)
306{
307 FaceEntry face;
308 face.faceId = params.getFaceId();
309 face.origin = params.getOrigin();
310 face.cost = params.getCost();
311 face.flags = params.getFlags();
312
313 NFD_LOG_DEBUG(face << " for " << params.getName() << " has expired");
314 unregisterEntry(request, params);
315}
316
317void
Alexander Afanasyev20d31442014-04-19 17:00:53 -0700318RibManager::unregisterEntry(const shared_ptr<const Interest>& request,
Syed Obaid3313a372014-07-01 01:31:33 -0500319 ControlParameters& params)
Alexander Afanasyev20d31442014-04-19 17:00:53 -0700320{
Alexander Afanasyevce7520e2014-04-28 09:40:06 -0700321 ndn::nfd::RibUnregisterCommand command;
Alexander Afanasyev20d31442014-04-19 17:00:53 -0700322
Syed Obaid3313a372014-07-01 01:31:33 -0500323 //passing all parameters gives error in validation.
324 //so passing only the required arguments.
325 ControlParameters parameters;
326 parameters.setName(params.getName());
Alexander Afanasyevb609f002014-07-18 16:56:34 -0700327 if (params.hasFaceId())
328 parameters.setFaceId(params.getFaceId());
329 if (params.hasOrigin())
330 parameters.setOrigin(params.getOrigin());
Syed Obaid3313a372014-07-01 01:31:33 -0500331
Alexander Afanasyev20d31442014-04-19 17:00:53 -0700332 if (!validateParameters(command, parameters))
333 {
Syed Obaid3313a372014-07-01 01:31:33 -0500334 NFD_LOG_DEBUG("unregister result: FAIL reason: malformed");
335 if (static_cast<bool>(request))
336 sendResponse(request->getName(), 400, "Malformed command");
Alexander Afanasyev20d31442014-04-19 17:00:53 -0700337 return;
338 }
339
Alexander Afanasyev483efd12014-08-14 10:51:18 -0700340 bool isSelfRegistration = (!parameters.hasFaceId() || parameters.getFaceId() == 0);
341 if (isSelfRegistration)
Alexander Afanasyevfb1c8082014-07-17 15:16:15 -0700342 {
343 parameters.setFaceId(request->getIncomingFaceId());
344 }
345
Vince12e49462014-06-09 13:29:32 -0500346 FaceEntry faceEntry;
347 faceEntry.faceId = parameters.getFaceId();
348 faceEntry.origin = parameters.getOrigin();
Alexander Afanasyev20d31442014-04-19 17:00:53 -0700349
Vince12e49462014-06-09 13:29:32 -0500350 NFD_LOG_TRACE("unregister prefix: " << faceEntry);
Alexander Afanasyev20d31442014-04-19 17:00:53 -0700351
Vince Lehman4387e782014-06-19 16:57:45 -0500352 m_managedRib.erase(parameters.getName(), faceEntry);
353
354 sendUpdatesToFib(request, parameters);
Alexander Afanasyev20d31442014-04-19 17:00:53 -0700355}
356
357void
358RibManager::onCommandValidationFailed(const shared_ptr<const Interest>& request,
359 const std::string& failureInfo)
Alexander Afanasyev3ecec502014-04-16 13:42:44 -0700360{
Alexander Afanasyev89cf5e02014-04-17 12:08:57 -0700361 NFD_LOG_DEBUG("RibRequestValidationFailed: " << failureInfo);
Syed Obaid3313a372014-07-01 01:31:33 -0500362 if (static_cast<bool>(request))
363 sendResponse(request->getName(), 403, failureInfo);
Alexander Afanasyev3ecec502014-04-16 13:42:44 -0700364}
365
Alexander Afanasyev3ecec502014-04-16 13:42:44 -0700366
Alexander Afanasyev20d31442014-04-19 17:00:53 -0700367bool
368RibManager::extractParameters(const Name::Component& parameterComponent,
369 ControlParameters& extractedParameters)
370{
Alexander Afanasyev3ecec502014-04-16 13:42:44 -0700371 try
372 {
Alexander Afanasyev20d31442014-04-19 17:00:53 -0700373 Block rawParameters = parameterComponent.blockFromValue();
374 extractedParameters.wireDecode(rawParameters);
Alexander Afanasyev3ecec502014-04-16 13:42:44 -0700375 }
Junxiao Shi67f11ac2014-10-19 09:29:13 -0700376 catch (const tlv::Error&)
Alexander Afanasyev3ecec502014-04-16 13:42:44 -0700377 {
378 return false;
379 }
380
Alexander Afanasyev20d31442014-04-19 17:00:53 -0700381 NFD_LOG_DEBUG("Parameters parsed OK");
382 return true;
383}
384
385bool
386RibManager::validateParameters(const ControlCommand& command,
387 ControlParameters& parameters)
388{
389 try
Alexander Afanasyev3ecec502014-04-16 13:42:44 -0700390 {
Alexander Afanasyev20d31442014-04-19 17:00:53 -0700391 command.validateRequest(parameters);
Alexander Afanasyev3ecec502014-04-16 13:42:44 -0700392 }
Alexander Afanasyev20d31442014-04-19 17:00:53 -0700393 catch (const ControlCommand::ArgumentError&)
394 {
395 return false;
396 }
397
398 command.applyDefaultsToRequest(parameters);
399
Alexander Afanasyev3ecec502014-04-16 13:42:44 -0700400 return true;
401}
402
403void
404RibManager::onCommandError(uint32_t code, const std::string& error,
Alexander Afanasyev20d31442014-04-19 17:00:53 -0700405 const shared_ptr<const Interest>& request,
Vince12e49462014-06-09 13:29:32 -0500406 const FaceEntry& faceEntry)
Alexander Afanasyev3ecec502014-04-16 13:42:44 -0700407{
Alexander Afanasyev89cf5e02014-04-17 12:08:57 -0700408 NFD_LOG_ERROR("NFD returned an error: " << error << " (code: " << code << ")");
Alexander Afanasyev3ecec502014-04-16 13:42:44 -0700409
410 ControlResponse response;
411
412 if (code == 404)
413 {
414 response.setCode(code);
415 response.setText(error);
416 }
417 else
418 {
419 response.setCode(533);
420 std::ostringstream os;
421 os << "Failure to update NFD " << "(NFD Error: " << code << " " << error << ")";
422 response.setText(os.str());
423 }
424
Syed Obaid3313a372014-07-01 01:31:33 -0500425 if (static_cast<bool>(request))
426 sendResponse(request->getName(), response);
Alexander Afanasyev3ecec502014-04-16 13:42:44 -0700427}
428
429void
Alexander Afanasyev20d31442014-04-19 17:00:53 -0700430RibManager::onRegSuccess(const shared_ptr<const Interest>& request,
431 const ControlParameters& parameters,
Vince12e49462014-06-09 13:29:32 -0500432 const FaceEntry& faceEntry)
Alexander Afanasyev3ecec502014-04-16 13:42:44 -0700433{
434 ControlResponse response;
435
436 response.setCode(200);
437 response.setText("Success");
Alexander Afanasyev20d31442014-04-19 17:00:53 -0700438 response.setBody(parameters.wireEncode());
Alexander Afanasyev3ecec502014-04-16 13:42:44 -0700439
Vince12e49462014-06-09 13:29:32 -0500440 NFD_LOG_TRACE("onRegSuccess: registered " << faceEntry);
Alexander Afanasyev89cf5e02014-04-17 12:08:57 -0700441
Syed Obaid3313a372014-07-01 01:31:33 -0500442 if (static_cast<bool>(request))
443 sendResponse(request->getName(), response);
Alexander Afanasyev3ecec502014-04-16 13:42:44 -0700444}
445
Alexander Afanasyev20d31442014-04-19 17:00:53 -0700446
Alexander Afanasyev3ecec502014-04-16 13:42:44 -0700447void
Alexander Afanasyev20d31442014-04-19 17:00:53 -0700448RibManager::onUnRegSuccess(const shared_ptr<const Interest>& request,
449 const ControlParameters& parameters,
Vince12e49462014-06-09 13:29:32 -0500450 const FaceEntry& faceEntry)
Alexander Afanasyev3ecec502014-04-16 13:42:44 -0700451{
452 ControlResponse response;
453
454 response.setCode(200);
455 response.setText("Success");
Alexander Afanasyev20d31442014-04-19 17:00:53 -0700456 response.setBody(parameters.wireEncode());
Alexander Afanasyev3ecec502014-04-16 13:42:44 -0700457
Vince12e49462014-06-09 13:29:32 -0500458 NFD_LOG_TRACE("onUnRegSuccess: unregistered " << faceEntry);
Alexander Afanasyev3ecec502014-04-16 13:42:44 -0700459
Syed Obaid3313a372014-07-01 01:31:33 -0500460 if (static_cast<bool>(request))
461 sendResponse(request->getName(), response);
Vince Lehman4387e782014-06-19 16:57:45 -0500462}
463
464void
465RibManager::sendSuccessResponse(const shared_ptr<const Interest>& request,
466 const ControlParameters& parameters)
467{
468 if (!static_cast<bool>(request))
469 {
470 return;
471 }
472
473 ControlResponse response;
474
475 response.setCode(200);
476 response.setText("Success");
477 response.setBody(parameters.wireEncode());
478
Syed Obaid3313a372014-07-01 01:31:33 -0500479 if (static_cast<bool>(request))
480 sendResponse(request->getName(), response);
Vince Lehman4387e782014-06-19 16:57:45 -0500481}
482
483void
484RibManager::sendErrorResponse(uint32_t code, const std::string& error,
485 const shared_ptr<const Interest>& request)
486{
487 NFD_LOG_ERROR("NFD returned an error: " << error << " (code: " << code << ")");
488
489 if (!static_cast<bool>(request))
490 {
491 return;
492 }
493
494 ControlResponse response;
495
496 if (code == 404)
497 {
498 response.setCode(code);
499 response.setText(error);
500 }
501 else
502 {
503 response.setCode(533);
504 std::ostringstream os;
505 os << "Failure to update NFD " << "(NFD Error: " << code << " " << error << ")";
506 response.setText(os.str());
507 }
508
Syed Obaid3313a372014-07-01 01:31:33 -0500509 if (static_cast<bool>(request))
510 sendResponse(request->getName(), response);
Alexander Afanasyev3ecec502014-04-16 13:42:44 -0700511}
512
Alexander Afanasyev3ecec502014-04-16 13:42:44 -0700513void
Alexander Afanasyevb3893c92014-05-15 01:49:54 -0700514RibManager::onNrdCommandPrefixAddNextHopSuccess(const Name& prefix)
515{
516 NFD_LOG_DEBUG("Successfully registered " + prefix.toUri() + " with NFD");
517}
518
519void
520RibManager::onNrdCommandPrefixAddNextHopError(const Name& name, const std::string& msg)
521{
522 throw Error("Error in setting interest filter (" + name.toUri() + "): " + msg);
523}
524
Vince Lehman4387e782014-06-19 16:57:45 -0500525bool
526RibManager::isTransactionComplete(const TransactionId transactionId)
Alexander Afanasyevb3893c92014-05-15 01:49:54 -0700527{
Vince Lehman4387e782014-06-19 16:57:45 -0500528 FibTransactionTable::iterator it = m_pendingFibTransactions.find(transactionId);
529
530 if (it != m_pendingFibTransactions.end())
531 {
532 int& updatesLeft = it->second;
533
534 updatesLeft--;
535
536 // All of the updates have been applied successfully
537 if (updatesLeft == 0)
538 {
539 m_pendingFibTransactions.erase(it);
540 return true;
541 }
542 }
543
544 return false;
Alexander Afanasyevb3893c92014-05-15 01:49:54 -0700545}
546
547void
Vince Lehman4387e782014-06-19 16:57:45 -0500548RibManager::invalidateTransaction(const TransactionId transactionId)
Alexander Afanasyevb3893c92014-05-15 01:49:54 -0700549{
Vince Lehman4387e782014-06-19 16:57:45 -0500550 FibTransactionTable::iterator it = m_pendingFibTransactions.find(transactionId);
551
552 if (it != m_pendingFibTransactions.end())
553 {
554 m_pendingFibTransactions.erase(it);
555 }
556}
557
558void
559RibManager::onAddNextHopSuccess(const shared_ptr<const Interest>& request,
560 const ControlParameters& parameters,
561 const TransactionId transactionId,
562 const bool shouldSendResponse)
563{
564 if (isTransactionComplete(transactionId) && shouldSendResponse)
565 {
566 sendSuccessResponse(request, parameters);
567 }
568}
569
570void
571RibManager::onAddNextHopError(uint32_t code, const std::string& error,
572 const shared_ptr<const Interest>& request,
573 const TransactionId transactionId, const bool shouldSendResponse)
574{
575 invalidateTransaction(transactionId);
576
577 if (shouldSendResponse)
578 {
579 sendErrorResponse(code, error, request);
580 }
Vince Lehman26b215c2014-08-17 15:00:41 -0500581
582 // Since the FIB rejected the update, clean up the invalid face
583 scheduleActiveFaceFetch(time::seconds(1));
Vince Lehman4387e782014-06-19 16:57:45 -0500584}
585
586void
587RibManager::onRemoveNextHopSuccess(const shared_ptr<const Interest>& request,
588 const ControlParameters& parameters,
589 const TransactionId transactionId,
590 const bool shouldSendResponse)
591{
592 if (isTransactionComplete(transactionId) && shouldSendResponse)
593 {
594 sendSuccessResponse(request, parameters);
595 }
596}
597
598void
599RibManager::onRemoveNextHopError(uint32_t code, const std::string& error,
600 const shared_ptr<const Interest>& request,
601 const TransactionId transactionId, const bool shouldSendResponse)
602{
603 invalidateTransaction(transactionId);
604
605 if (shouldSendResponse)
606 {
607 sendErrorResponse(code, error, request);
608 }
Alexander Afanasyevb3893c92014-05-15 01:49:54 -0700609}
610
611void
Alexander Afanasyev3ecec502014-04-16 13:42:44 -0700612RibManager::onControlHeaderSuccess()
613{
Alexander Afanasyev89cf5e02014-04-17 12:08:57 -0700614 NFD_LOG_DEBUG("Local control header enabled");
Alexander Afanasyev3ecec502014-04-16 13:42:44 -0700615}
616
617void
618RibManager::onControlHeaderError(uint32_t code, const std::string& reason)
619{
Alexander Afanasyevb3051652014-04-30 17:50:26 -0700620 std::ostringstream os;
621 os << "Couldn't enable local control header "
622 << "(code: " << code << ", info: " << reason << ")";
623 throw Error(os.str());
Alexander Afanasyev3ecec502014-04-16 13:42:44 -0700624}
625
626void
627RibManager::enableLocalControlHeader()
628{
Alexander Afanasyevb3893c92014-05-15 01:49:54 -0700629 m_nfdController.start<ndn::nfd::FaceEnableLocalControlCommand>(
Alexander Afanasyev3ecec502014-04-16 13:42:44 -0700630 ControlParameters()
631 .setLocalControlFeature(ndn::nfd::LOCAL_CONTROL_FEATURE_INCOMING_FACE_ID),
632 bind(&RibManager::onControlHeaderSuccess, this),
633 bind(&RibManager::onControlHeaderError, this, _1, _2));
634}
635
636void
637RibManager::onNotification(const FaceEventNotification& notification)
638{
Alexander Afanasyev89cf5e02014-04-17 12:08:57 -0700639 NFD_LOG_TRACE("onNotification: " << notification);
Vince Lehmancd613c52014-07-30 14:34:49 -0500640
Vince Lehman26b215c2014-08-17 15:00:41 -0500641 if (notification.getKind() == ndn::nfd::FACE_EVENT_DESTROYED)
Vince Lehmancd613c52014-07-30 14:34:49 -0500642 {
643 NFD_LOG_DEBUG("Received notification for destroyed faceId: " << notification.getFaceId());
Vince Lehmancd613c52014-07-30 14:34:49 -0500644
Alexander Afanasyev63108c42014-07-07 19:10:47 -0700645 scheduler::schedule(time::seconds(0),
646 bind(&RibManager::processErasureAfterNotification, this,
647 notification.getFaceId()));
Vince Lehman4387e782014-06-19 16:57:45 -0500648 }
649}
650
651void
Alexander Afanasyev63108c42014-07-07 19:10:47 -0700652RibManager::processErasureAfterNotification(uint64_t faceId)
653{
654 m_managedRib.erase(faceId);
Vince Lehman26b215c2014-08-17 15:00:41 -0500655 m_registeredFaces.erase(faceId);
Alexander Afanasyev63108c42014-07-07 19:10:47 -0700656
657 sendUpdatesToFibAfterFaceDestroyEvent();
658}
659
660void
Vince Lehman4387e782014-06-19 16:57:45 -0500661RibManager::sendUpdatesToFib(const shared_ptr<const Interest>& request,
662 const ControlParameters& parameters)
663{
664 const Rib::FibUpdateList& updates = m_managedRib.getFibUpdates();
665
666 // If no updates were generated, consider the operation a success
667 if (updates.empty())
668 {
669 sendSuccessResponse(request, parameters);
670 return;
671 }
672
673 bool shouldWaitToRespond = false;
674
675 // An application request should wait for all FIB updates to be applied
676 // successfully before sending a response
677 if (parameters.getOrigin() == ndn::nfd::ROUTE_ORIGIN_APP)
678 {
679 shouldWaitToRespond = true;
680 }
681 else // Respond immediately
682 {
683 sendSuccessResponse(request, parameters);
684 }
685
Vince Lehmanbc05b762014-08-15 15:37:02 -0500686 std::string updateString = (updates.size() == 1) ? " update" : " updates";
687 NFD_LOG_DEBUG("Applying " << updates.size() << updateString << " to FIB");
Vince Lehman4387e782014-06-19 16:57:45 -0500688
689 // Assign an ID to this FIB transaction
690 TransactionId currentTransactionId = ++m_lastTransactionId;
691
692 // Add this transaction to the transaction table
693 m_pendingFibTransactions[currentTransactionId] = updates.size();
694
695 for (Rib::FibUpdateList::const_iterator it = updates.begin(); it != updates.end(); ++it)
696 {
697 shared_ptr<const FibUpdate> update(*it);
Vince Lehmanbc05b762014-08-15 15:37:02 -0500698 NFD_LOG_DEBUG("Sending FIB update: " << *update);
Vince Lehman4387e782014-06-19 16:57:45 -0500699
700 if (update->action == FibUpdate::ADD_NEXTHOP)
701 {
702 FaceEntry faceEntry;
703 faceEntry.faceId = update->faceId;
704 faceEntry.cost = update->cost;
705
706 m_nfdController.start<ndn::nfd::FibAddNextHopCommand>(
707 ControlParameters()
708 .setName(update->name)
709 .setFaceId(faceEntry.faceId)
710 .setCost(faceEntry.cost),
711 bind(&RibManager::onAddNextHopSuccess, this, request,
712 parameters,
713 currentTransactionId,
714 shouldWaitToRespond),
715 bind(&RibManager::onAddNextHopError, this, _1, _2, request, currentTransactionId,
716 shouldWaitToRespond));
717 }
718 else if (update->action == FibUpdate::REMOVE_NEXTHOP)
719 {
720 FaceEntry faceEntry;
721 faceEntry.faceId = update->faceId;
722
723 m_nfdController.start<ndn::nfd::FibRemoveNextHopCommand>(
724 ControlParameters()
725 .setName(update->name)
726 .setFaceId(faceEntry.faceId),
727 bind(&RibManager::onRemoveNextHopSuccess, this, request,
728 parameters,
729 currentTransactionId,
730 shouldWaitToRespond),
731 bind(&RibManager::onRemoveNextHopError, this, _1, _2, request, currentTransactionId,
732 shouldWaitToRespond));
733 }
734 }
735
736 m_managedRib.clearFibUpdates();
737}
738
739void
740RibManager::sendUpdatesToFibAfterFaceDestroyEvent()
741{
742 ControlParameters parameters;
743 parameters.setOrigin(ndn::nfd::ROUTE_ORIGIN_STATIC);
744
745 sendUpdatesToFib(shared_ptr<const Interest>(), parameters);
Alexander Afanasyev3ecec502014-04-16 13:42:44 -0700746}
747
Vince Lehmancd16c832014-07-23 15:14:55 -0700748void
749RibManager::listEntries(const Interest& request)
750{
751 const Name& command = request.getName();
752 const size_t commandNComps = command.size();
753
754 if (commandNComps < LIST_COMMAND_NCOMPS ||
755 !LIST_COMMAND_PREFIX.isPrefixOf(command))
756 {
757 NFD_LOG_DEBUG("command result: malformed");
758 sendResponse(command, 400, "Malformed command");
759 return;
760 }
761
762 m_ribStatusPublisher.publish();
763}
764
Vince Lehmancd613c52014-07-30 14:34:49 -0500765void
Vince Lehman26b215c2014-08-17 15:00:41 -0500766RibManager::scheduleActiveFaceFetch(const time::seconds& timeToWait)
767{
768 scheduler::cancel(m_activeFaceFetchEvent);
769
770 m_activeFaceFetchEvent = scheduler::schedule(timeToWait,
771 bind(&RibManager::fetchActiveFaces, this));
772}
773
774void
Vince Lehmancd613c52014-07-30 14:34:49 -0500775RibManager::fetchActiveFaces()
776{
777 NFD_LOG_DEBUG("Fetching active faces");
778
779 Interest interest(FACES_LIST_DATASET_PREFIX);
780 interest.setChildSelector(1);
781 interest.setMustBeFresh(true);
782
783 shared_ptr<ndn::OBufferStream> buffer = make_shared<ndn::OBufferStream>();
784
785 m_face.expressInterest(interest,
786 bind(&RibManager::fetchSegments, this, _2, buffer),
787 bind(&RibManager::onFetchFaceStatusTimeout, this));
788}
789
790void
791RibManager::fetchSegments(const Data& data, shared_ptr<ndn::OBufferStream> buffer)
792{
793 buffer->write(reinterpret_cast<const char*>(data.getContent().value()),
794 data.getContent().value_size());
795
796 uint64_t currentSegment = data.getName().get(-1).toSegment();
797
798 const name::Component& finalBlockId = data.getMetaInfo().getFinalBlockId();
799 if (finalBlockId.empty() || finalBlockId.toSegment() > currentSegment)
800 {
801 m_face.expressInterest(data.getName().getPrefix(-1).appendSegment(currentSegment+1),
802 bind(&RibManager::fetchSegments, this, _2, buffer),
803 bind(&RibManager::onFetchFaceStatusTimeout, this));
804 }
805 else
806 {
Vince Lehman26b215c2014-08-17 15:00:41 -0500807 removeInvalidFaces(buffer);
Vince Lehmancd613c52014-07-30 14:34:49 -0500808 }
809}
810
811void
Vince Lehman26b215c2014-08-17 15:00:41 -0500812RibManager::removeInvalidFaces(shared_ptr<ndn::OBufferStream> buffer)
Vince Lehmancd613c52014-07-30 14:34:49 -0500813{
Vince Lehman26b215c2014-08-17 15:00:41 -0500814 NFD_LOG_DEBUG("Checking for invalid face registrations");
Vince Lehmancd613c52014-07-30 14:34:49 -0500815
816 ndn::ConstBufferPtr buf = buffer->buf();
817
818 Block block;
819 size_t offset = 0;
Vince Lehman26b215c2014-08-17 15:00:41 -0500820 FaceIdSet activeFaces;
Vince Lehmancd613c52014-07-30 14:34:49 -0500821
822 while (offset < buf->size())
823 {
824 if (!Block::fromBuffer(buf, offset, block))
825 {
826 std::cerr << "ERROR: cannot decode FaceStatus TLV" << std::endl;
827 break;
828 }
829
830 offset += block.size();
831
832 ndn::nfd::FaceStatus status(block);
Vince Lehmancd613c52014-07-30 14:34:49 -0500833 activeFaces.insert(status.getFaceId());
834 }
Vince Lehman26b215c2014-08-17 15:00:41 -0500835
836 // Look for face IDs that were registered but not active to find missed
837 // face destroyed events
838 for (FaceIdSet::iterator it = m_registeredFaces.begin(); it != m_registeredFaces.end(); ++it)
839 {
840 if (activeFaces.find(*it) == activeFaces.end())
841 {
842 NFD_LOG_DEBUG("Removing invalid face ID: " << *it);
843 scheduler::schedule(time::seconds(0),
844 bind(&RibManager::processErasureAfterNotification, this, *it));
845 }
846 }
847
848 // Reschedule the check for future clean up
849 scheduleActiveFaceFetch(ACTIVE_FACE_FETCH_INTERVAL);
Vince Lehmancd613c52014-07-30 14:34:49 -0500850}
851
852void
853RibManager::onFetchFaceStatusTimeout()
854{
855 std::cerr << "Face Status Dataset request timed out" << std::endl;
Vince Lehman26b215c2014-08-17 15:00:41 -0500856 scheduleActiveFaceFetch(ACTIVE_FACE_FETCH_INTERVAL);
Vince Lehmancd613c52014-07-30 14:34:49 -0500857}
858
Alexander Afanasyev3ecec502014-04-16 13:42:44 -0700859} // namespace rib
860} // namespace nfd