blob: 8b7010a402ed16f4d54efb1351ee069118f15f16 [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 Afanasyev3ecec502014-04-16 13:42:44 -070029
30namespace nfd {
31namespace rib {
32
Alexander Afanasyev89cf5e02014-04-17 12:08:57 -070033NFD_LOG_INIT("RibManager");
34
Alexander Afanasyev20d31442014-04-19 17:00:53 -070035const Name RibManager::COMMAND_PREFIX = "/localhost/nfd/rib";
36const Name RibManager::REMOTE_COMMAND_PREFIX = "/localhop/nfd/rib";
Alexander Afanasyev3ecec502014-04-16 13:42:44 -070037
38const size_t RibManager::COMMAND_UNSIGNED_NCOMPS =
39 RibManager::COMMAND_PREFIX.size() +
40 1 + // verb
41 1; // verb options
42
43const size_t RibManager::COMMAND_SIGNED_NCOMPS =
44 RibManager::COMMAND_UNSIGNED_NCOMPS +
45 4; // (timestamp, nonce, signed info tlv, signature tlv)
46
47const RibManager::VerbAndProcessor RibManager::COMMAND_VERBS[] =
48 {
49 VerbAndProcessor(
50 Name::Component("register"),
Alexander Afanasyev20d31442014-04-19 17:00:53 -070051 &RibManager::registerEntry
Alexander Afanasyev3ecec502014-04-16 13:42:44 -070052 ),
53
54 VerbAndProcessor(
55 Name::Component("unregister"),
Alexander Afanasyev20d31442014-04-19 17:00:53 -070056 &RibManager::unregisterEntry
Alexander Afanasyev3ecec502014-04-16 13:42:44 -070057 ),
58 };
59
60RibManager::RibManager()
Alexander Afanasyevf6980282014-05-13 18:28:40 -070061 : m_face(getGlobalIoService())
Alexander Afanasyevb3893c92014-05-15 01:49:54 -070062 , m_nfdController(m_face)
Yingdi Yue5224e92014-04-29 18:04:02 -070063 , m_localhostValidator(m_face)
64 , m_localhopValidator(m_face)
Yingdi Yuf4db0b52014-04-17 13:17:39 -070065 , m_faceMonitor(m_face)
Yingdi Yue5224e92014-04-29 18:04:02 -070066 , m_isLocalhopEnabled(false)
Vince Lehman4387e782014-06-19 16:57:45 -050067 , m_lastTransactionId(0)
Alexander Afanasyev3ecec502014-04-16 13:42:44 -070068 , m_verbDispatch(COMMAND_VERBS,
69 COMMAND_VERBS + (sizeof(COMMAND_VERBS) / sizeof(VerbAndProcessor)))
70{
71}
72
73void
Junxiao Shia3295742014-05-16 22:40:10 -070074RibManager::startListening(const Name& commandPrefix, const ndn::OnInterest& onRequest)
75{
76 NFD_LOG_INFO("Listening on: " << commandPrefix);
77
78 m_nfdController.start<ndn::nfd::FibAddNextHopCommand>(
79 ControlParameters()
80 .setName(commandPrefix)
81 .setFaceId(0),
82 bind(&RibManager::onNrdCommandPrefixAddNextHopSuccess, this, cref(commandPrefix)),
83 bind(&RibManager::onNrdCommandPrefixAddNextHopError, this, cref(commandPrefix), _2));
84
85 m_face.setInterestFilter(commandPrefix, onRequest);
86}
87
88void
Alexander Afanasyev3ecec502014-04-16 13:42:44 -070089RibManager::registerWithNfd()
90{
91 //check whether the components of localhop and localhost prefixes are same
92 BOOST_ASSERT(COMMAND_PREFIX.size() == REMOTE_COMMAND_PREFIX.size());
93
Junxiao Shia3295742014-05-16 22:40:10 -070094 this->startListening(COMMAND_PREFIX, bind(&RibManager::onLocalhostRequest, this, _2));
Alexander Afanasyevb3893c92014-05-15 01:49:54 -070095
Junxiao Shia3295742014-05-16 22:40:10 -070096 if (m_isLocalhopEnabled) {
97 this->startListening(REMOTE_COMMAND_PREFIX,
98 bind(&RibManager::onLocalhopRequest, this, _2));
99 }
Alexander Afanasyev3ecec502014-04-16 13:42:44 -0700100
Alexander Afanasyev89cf5e02014-04-17 12:08:57 -0700101 NFD_LOG_INFO("Start monitoring face create/destroy events");
Alexander Afanasyevf6980282014-05-13 18:28:40 -0700102 m_faceMonitor.addSubscriber(bind(&RibManager::onNotification, this, _1));
Alexander Afanasyev3ecec502014-04-16 13:42:44 -0700103 m_faceMonitor.startNotifications();
104}
105
106void
107RibManager::setConfigFile(ConfigFile& configFile)
108{
Yingdi Yue5224e92014-04-29 18:04:02 -0700109 configFile.addSectionHandler("rib",
Alexander Afanasyev3ecec502014-04-16 13:42:44 -0700110 bind(&RibManager::onConfig, this, _1, _2, _3));
111}
112
113void
114RibManager::onConfig(const ConfigSection& configSection,
Yingdi Yuf4db0b52014-04-17 13:17:39 -0700115 bool isDryRun,
116 const std::string& filename)
Alexander Afanasyev3ecec502014-04-16 13:42:44 -0700117{
Yingdi Yue5224e92014-04-29 18:04:02 -0700118 for (ConfigSection::const_iterator i = configSection.begin();
119 i != configSection.end(); ++i)
120 {
121 if (i->first == "localhost_security")
122 m_localhostValidator.load(i->second, filename);
123 else if (i->first == "localhop_security")
124 {
125 m_localhopValidator.load(i->second, filename);
126 m_isLocalhopEnabled = true;
127 }
128 else
129 throw Error("Unrecognized rib property: " + i->first);
130 }
Alexander Afanasyev3ecec502014-04-16 13:42:44 -0700131}
132
133void
Alexander Afanasyev3ecec502014-04-16 13:42:44 -0700134RibManager::sendResponse(const Name& name,
135 const ControlResponse& response)
136{
137 const Block& encodedControl = response.wireEncode();
138
139 Data responseData(name);
140 responseData.setContent(encodedControl);
141
142 m_keyChain.sign(responseData);
Yingdi Yuf4db0b52014-04-17 13:17:39 -0700143 m_face.put(responseData);
Alexander Afanasyev3ecec502014-04-16 13:42:44 -0700144}
145
146void
147RibManager::sendResponse(const Name& name,
148 uint32_t code,
149 const std::string& text)
150{
151 ControlResponse response(code, text);
152 sendResponse(name, response);
153}
154
155void
Yingdi Yue5224e92014-04-29 18:04:02 -0700156RibManager::onLocalhostRequest(const Interest& request)
Alexander Afanasyev3ecec502014-04-16 13:42:44 -0700157{
Yingdi Yue5224e92014-04-29 18:04:02 -0700158 m_localhostValidator.validate(request,
159 bind(&RibManager::onCommandValidated, this, _1),
160 bind(&RibManager::onCommandValidationFailed, this, _1, _2));
161}
162
163void
164RibManager::onLocalhopRequest(const Interest& request)
165{
166 m_localhopValidator.validate(request,
167 bind(&RibManager::onCommandValidated, this, _1),
168 bind(&RibManager::onCommandValidationFailed, this, _1, _2));
Alexander Afanasyev3ecec502014-04-16 13:42:44 -0700169}
170
171void
Alexander Afanasyev20d31442014-04-19 17:00:53 -0700172RibManager::onCommandValidated(const shared_ptr<const Interest>& request)
Alexander Afanasyev3ecec502014-04-16 13:42:44 -0700173{
Alexander Afanasyev20d31442014-04-19 17:00:53 -0700174 // REMOTE_COMMAND_PREFIX number of componenets are same as
Alexander Afanasyev3ecec502014-04-16 13:42:44 -0700175 // NRD_COMMAND_PREFIX's so no extra checks are required.
Alexander Afanasyev3ecec502014-04-16 13:42:44 -0700176
Alexander Afanasyev20d31442014-04-19 17:00:53 -0700177 const Name& command = request->getName();
178 const Name::Component& verb = command[COMMAND_PREFIX.size()];
179 const Name::Component& parameterComponent = command[COMMAND_PREFIX.size() + 1];
180
181 VerbDispatchTable::const_iterator verbProcessor = m_verbDispatch.find(verb);
Alexander Afanasyev3ecec502014-04-16 13:42:44 -0700182 if (verbProcessor != m_verbDispatch.end())
183 {
Alexander Afanasyev20d31442014-04-19 17:00:53 -0700184 ControlParameters parameters;
185 if (!extractParameters(parameterComponent, parameters))
Alexander Afanasyev3ecec502014-04-16 13:42:44 -0700186 {
Alexander Afanasyev20d31442014-04-19 17:00:53 -0700187 NFD_LOG_DEBUG("command result: malformed verb: " << verb);
Alexander Afanasyev3ecec502014-04-16 13:42:44 -0700188 sendResponse(command, 400, "Malformed command");
189 return;
190 }
191
Alexander Afanasyev20d31442014-04-19 17:00:53 -0700192 if (!parameters.hasFaceId() || parameters.getFaceId() == 0)
193 {
194 parameters.setFaceId(request->getIncomingFaceId());
195 }
Alexander Afanasyev3ecec502014-04-16 13:42:44 -0700196
Alexander Afanasyev20d31442014-04-19 17:00:53 -0700197 NFD_LOG_DEBUG("command result: processing verb: " << verb);
198 (verbProcessor->second)(this, request, parameters);
Alexander Afanasyev3ecec502014-04-16 13:42:44 -0700199 }
200 else
201 {
Alexander Afanasyev89cf5e02014-04-17 12:08:57 -0700202 NFD_LOG_DEBUG("Unsupported command: " << verb);
Alexander Afanasyev3ecec502014-04-16 13:42:44 -0700203 sendResponse(request->getName(), 501, "Unsupported command");
204 }
205}
206
207void
Alexander Afanasyev20d31442014-04-19 17:00:53 -0700208RibManager::registerEntry(const shared_ptr<const Interest>& request,
209 ControlParameters& parameters)
210{
211 ndn::nfd::RibRegisterCommand command;
212
213 if (!validateParameters(command, parameters))
214 {
215 NFD_LOG_DEBUG("register result: FAIL reason: malformed");
216 sendResponse(request->getName(), 400, "Malformed command");
217 return;
218 }
219
Vince12e49462014-06-09 13:29:32 -0500220 FaceEntry faceEntry;
221 faceEntry.faceId = parameters.getFaceId();
222 faceEntry.origin = parameters.getOrigin();
223 faceEntry.cost = parameters.getCost();
224 faceEntry.flags = parameters.getFlags();
225 faceEntry.expires = time::steady_clock::now() + parameters.getExpirationPeriod();
Alexander Afanasyev20d31442014-04-19 17:00:53 -0700226
Vince12e49462014-06-09 13:29:32 -0500227 NFD_LOG_TRACE("register prefix: " << faceEntry);
Alexander Afanasyev20d31442014-04-19 17:00:53 -0700228
Vince12e49462014-06-09 13:29:32 -0500229 m_managedRib.insert(parameters.getName(), faceEntry);
Vince Lehman4387e782014-06-19 16:57:45 -0500230
231 sendUpdatesToFib(request, parameters);
Alexander Afanasyev20d31442014-04-19 17:00:53 -0700232}
233
234void
235RibManager::unregisterEntry(const shared_ptr<const Interest>& request,
236 ControlParameters& parameters)
237{
Alexander Afanasyevce7520e2014-04-28 09:40:06 -0700238 ndn::nfd::RibUnregisterCommand command;
Alexander Afanasyev20d31442014-04-19 17:00:53 -0700239
240 if (!validateParameters(command, parameters))
241 {
242 NFD_LOG_DEBUG("register result: FAIL reason: malformed");
243 sendResponse(request->getName(), 400, "Malformed command");
244 return;
245 }
246
Vince12e49462014-06-09 13:29:32 -0500247 FaceEntry faceEntry;
248 faceEntry.faceId = parameters.getFaceId();
249 faceEntry.origin = parameters.getOrigin();
Alexander Afanasyev20d31442014-04-19 17:00:53 -0700250
Vince12e49462014-06-09 13:29:32 -0500251 NFD_LOG_TRACE("unregister prefix: " << faceEntry);
Alexander Afanasyev20d31442014-04-19 17:00:53 -0700252
Vince Lehman4387e782014-06-19 16:57:45 -0500253 m_managedRib.erase(parameters.getName(), faceEntry);
254
255 sendUpdatesToFib(request, parameters);
Alexander Afanasyev20d31442014-04-19 17:00:53 -0700256}
257
258void
259RibManager::onCommandValidationFailed(const shared_ptr<const Interest>& request,
260 const std::string& failureInfo)
Alexander Afanasyev3ecec502014-04-16 13:42:44 -0700261{
Alexander Afanasyev89cf5e02014-04-17 12:08:57 -0700262 NFD_LOG_DEBUG("RibRequestValidationFailed: " << failureInfo);
Alexander Afanasyev3ecec502014-04-16 13:42:44 -0700263 sendResponse(request->getName(), 403, failureInfo);
264}
265
Alexander Afanasyev3ecec502014-04-16 13:42:44 -0700266
Alexander Afanasyev20d31442014-04-19 17:00:53 -0700267bool
268RibManager::extractParameters(const Name::Component& parameterComponent,
269 ControlParameters& extractedParameters)
270{
Alexander Afanasyev3ecec502014-04-16 13:42:44 -0700271 try
272 {
Alexander Afanasyev20d31442014-04-19 17:00:53 -0700273 Block rawParameters = parameterComponent.blockFromValue();
274 extractedParameters.wireDecode(rawParameters);
Alexander Afanasyev3ecec502014-04-16 13:42:44 -0700275 }
276 catch (const ndn::Tlv::Error& e)
277 {
278 return false;
279 }
280
Alexander Afanasyev20d31442014-04-19 17:00:53 -0700281 NFD_LOG_DEBUG("Parameters parsed OK");
282 return true;
283}
284
285bool
286RibManager::validateParameters(const ControlCommand& command,
287 ControlParameters& parameters)
288{
289 try
Alexander Afanasyev3ecec502014-04-16 13:42:44 -0700290 {
Alexander Afanasyev20d31442014-04-19 17:00:53 -0700291 command.validateRequest(parameters);
Alexander Afanasyev3ecec502014-04-16 13:42:44 -0700292 }
Alexander Afanasyev20d31442014-04-19 17:00:53 -0700293 catch (const ControlCommand::ArgumentError&)
294 {
295 return false;
296 }
297
298 command.applyDefaultsToRequest(parameters);
299
Alexander Afanasyev3ecec502014-04-16 13:42:44 -0700300 return true;
301}
302
303void
304RibManager::onCommandError(uint32_t code, const std::string& error,
Alexander Afanasyev20d31442014-04-19 17:00:53 -0700305 const shared_ptr<const Interest>& request,
Vince12e49462014-06-09 13:29:32 -0500306 const FaceEntry& faceEntry)
Alexander Afanasyev3ecec502014-04-16 13:42:44 -0700307{
Alexander Afanasyev89cf5e02014-04-17 12:08:57 -0700308 NFD_LOG_ERROR("NFD returned an error: " << error << " (code: " << code << ")");
Alexander Afanasyev3ecec502014-04-16 13:42:44 -0700309
310 ControlResponse response;
311
312 if (code == 404)
313 {
314 response.setCode(code);
315 response.setText(error);
316 }
317 else
318 {
319 response.setCode(533);
320 std::ostringstream os;
321 os << "Failure to update NFD " << "(NFD Error: " << code << " " << error << ")";
322 response.setText(os.str());
323 }
324
Alexander Afanasyev20d31442014-04-19 17:00:53 -0700325 sendResponse(request->getName(), response);
Alexander Afanasyev3ecec502014-04-16 13:42:44 -0700326}
327
328void
Alexander Afanasyev20d31442014-04-19 17:00:53 -0700329RibManager::onRegSuccess(const shared_ptr<const Interest>& request,
330 const ControlParameters& parameters,
Vince12e49462014-06-09 13:29:32 -0500331 const FaceEntry& faceEntry)
Alexander Afanasyev3ecec502014-04-16 13:42:44 -0700332{
333 ControlResponse response;
334
335 response.setCode(200);
336 response.setText("Success");
Alexander Afanasyev20d31442014-04-19 17:00:53 -0700337 response.setBody(parameters.wireEncode());
Alexander Afanasyev3ecec502014-04-16 13:42:44 -0700338
Vince12e49462014-06-09 13:29:32 -0500339 NFD_LOG_TRACE("onRegSuccess: registered " << faceEntry);
Alexander Afanasyev89cf5e02014-04-17 12:08:57 -0700340
Alexander Afanasyev20d31442014-04-19 17:00:53 -0700341 sendResponse(request->getName(), response);
Alexander Afanasyev3ecec502014-04-16 13:42:44 -0700342}
343
Alexander Afanasyev20d31442014-04-19 17:00:53 -0700344
Alexander Afanasyev3ecec502014-04-16 13:42:44 -0700345void
Alexander Afanasyev20d31442014-04-19 17:00:53 -0700346RibManager::onUnRegSuccess(const shared_ptr<const Interest>& request,
347 const ControlParameters& parameters,
Vince12e49462014-06-09 13:29:32 -0500348 const FaceEntry& faceEntry)
Alexander Afanasyev3ecec502014-04-16 13:42:44 -0700349{
350 ControlResponse response;
351
352 response.setCode(200);
353 response.setText("Success");
Alexander Afanasyev20d31442014-04-19 17:00:53 -0700354 response.setBody(parameters.wireEncode());
Alexander Afanasyev3ecec502014-04-16 13:42:44 -0700355
Vince12e49462014-06-09 13:29:32 -0500356 NFD_LOG_TRACE("onUnRegSuccess: unregistered " << faceEntry);
Alexander Afanasyev3ecec502014-04-16 13:42:44 -0700357
Alexander Afanasyev20d31442014-04-19 17:00:53 -0700358 sendResponse(request->getName(), response);
Vince Lehman4387e782014-06-19 16:57:45 -0500359}
360
361void
362RibManager::sendSuccessResponse(const shared_ptr<const Interest>& request,
363 const ControlParameters& parameters)
364{
365 if (!static_cast<bool>(request))
366 {
367 return;
368 }
369
370 ControlResponse response;
371
372 response.setCode(200);
373 response.setText("Success");
374 response.setBody(parameters.wireEncode());
375
376 sendResponse(request->getName(), response);
377}
378
379void
380RibManager::sendErrorResponse(uint32_t code, const std::string& error,
381 const shared_ptr<const Interest>& request)
382{
383 NFD_LOG_ERROR("NFD returned an error: " << error << " (code: " << code << ")");
384
385 if (!static_cast<bool>(request))
386 {
387 return;
388 }
389
390 ControlResponse response;
391
392 if (code == 404)
393 {
394 response.setCode(code);
395 response.setText(error);
396 }
397 else
398 {
399 response.setCode(533);
400 std::ostringstream os;
401 os << "Failure to update NFD " << "(NFD Error: " << code << " " << error << ")";
402 response.setText(os.str());
403 }
404
405 sendResponse(request->getName(), response);
Alexander Afanasyev3ecec502014-04-16 13:42:44 -0700406}
407
Alexander Afanasyev3ecec502014-04-16 13:42:44 -0700408void
Alexander Afanasyevb3893c92014-05-15 01:49:54 -0700409RibManager::onNrdCommandPrefixAddNextHopSuccess(const Name& prefix)
410{
411 NFD_LOG_DEBUG("Successfully registered " + prefix.toUri() + " with NFD");
412}
413
414void
415RibManager::onNrdCommandPrefixAddNextHopError(const Name& name, const std::string& msg)
416{
417 throw Error("Error in setting interest filter (" + name.toUri() + "): " + msg);
418}
419
Vince Lehman4387e782014-06-19 16:57:45 -0500420bool
421RibManager::isTransactionComplete(const TransactionId transactionId)
Alexander Afanasyevb3893c92014-05-15 01:49:54 -0700422{
Vince Lehman4387e782014-06-19 16:57:45 -0500423 FibTransactionTable::iterator it = m_pendingFibTransactions.find(transactionId);
424
425 if (it != m_pendingFibTransactions.end())
426 {
427 int& updatesLeft = it->second;
428
429 updatesLeft--;
430
431 // All of the updates have been applied successfully
432 if (updatesLeft == 0)
433 {
434 m_pendingFibTransactions.erase(it);
435 return true;
436 }
437 }
438
439 return false;
Alexander Afanasyevb3893c92014-05-15 01:49:54 -0700440}
441
442void
Vince Lehman4387e782014-06-19 16:57:45 -0500443RibManager::invalidateTransaction(const TransactionId transactionId)
Alexander Afanasyevb3893c92014-05-15 01:49:54 -0700444{
Vince Lehman4387e782014-06-19 16:57:45 -0500445 FibTransactionTable::iterator it = m_pendingFibTransactions.find(transactionId);
446
447 if (it != m_pendingFibTransactions.end())
448 {
449 m_pendingFibTransactions.erase(it);
450 }
451}
452
453void
454RibManager::onAddNextHopSuccess(const shared_ptr<const Interest>& request,
455 const ControlParameters& parameters,
456 const TransactionId transactionId,
457 const bool shouldSendResponse)
458{
459 if (isTransactionComplete(transactionId) && shouldSendResponse)
460 {
461 sendSuccessResponse(request, parameters);
462 }
463}
464
465void
466RibManager::onAddNextHopError(uint32_t code, const std::string& error,
467 const shared_ptr<const Interest>& request,
468 const TransactionId transactionId, const bool shouldSendResponse)
469{
470 invalidateTransaction(transactionId);
471
472 if (shouldSendResponse)
473 {
474 sendErrorResponse(code, error, request);
475 }
476}
477
478void
479RibManager::onRemoveNextHopSuccess(const shared_ptr<const Interest>& request,
480 const ControlParameters& parameters,
481 const TransactionId transactionId,
482 const bool shouldSendResponse)
483{
484 if (isTransactionComplete(transactionId) && shouldSendResponse)
485 {
486 sendSuccessResponse(request, parameters);
487 }
488}
489
490void
491RibManager::onRemoveNextHopError(uint32_t code, const std::string& error,
492 const shared_ptr<const Interest>& request,
493 const TransactionId transactionId, const bool shouldSendResponse)
494{
495 invalidateTransaction(transactionId);
496
497 if (shouldSendResponse)
498 {
499 sendErrorResponse(code, error, request);
500 }
Alexander Afanasyevb3893c92014-05-15 01:49:54 -0700501}
502
503void
Alexander Afanasyev3ecec502014-04-16 13:42:44 -0700504RibManager::onControlHeaderSuccess()
505{
Alexander Afanasyev89cf5e02014-04-17 12:08:57 -0700506 NFD_LOG_DEBUG("Local control header enabled");
Alexander Afanasyev3ecec502014-04-16 13:42:44 -0700507}
508
509void
510RibManager::onControlHeaderError(uint32_t code, const std::string& reason)
511{
Alexander Afanasyevb3051652014-04-30 17:50:26 -0700512 std::ostringstream os;
513 os << "Couldn't enable local control header "
514 << "(code: " << code << ", info: " << reason << ")";
515 throw Error(os.str());
Alexander Afanasyev3ecec502014-04-16 13:42:44 -0700516}
517
518void
519RibManager::enableLocalControlHeader()
520{
Alexander Afanasyevb3893c92014-05-15 01:49:54 -0700521 m_nfdController.start<ndn::nfd::FaceEnableLocalControlCommand>(
Alexander Afanasyev3ecec502014-04-16 13:42:44 -0700522 ControlParameters()
523 .setLocalControlFeature(ndn::nfd::LOCAL_CONTROL_FEATURE_INCOMING_FACE_ID),
524 bind(&RibManager::onControlHeaderSuccess, this),
525 bind(&RibManager::onControlHeaderError, this, _1, _2));
526}
527
528void
529RibManager::onNotification(const FaceEventNotification& notification)
530{
531 /// \todo A notification can be missed, in this case check Facelist
Alexander Afanasyev89cf5e02014-04-17 12:08:57 -0700532 NFD_LOG_TRACE("onNotification: " << notification);
Vince Lehman4387e782014-06-19 16:57:45 -0500533 if (notification.getKind() == ndn::nfd::FACE_EVENT_DESTROYED) //face destroyed
534 {
535 m_managedRib.erase(notification.getFaceId());
536
537 sendUpdatesToFibAfterFaceDestroyEvent();
538 }
539}
540
541void
542RibManager::sendUpdatesToFib(const shared_ptr<const Interest>& request,
543 const ControlParameters& parameters)
544{
545 const Rib::FibUpdateList& updates = m_managedRib.getFibUpdates();
546
547 // If no updates were generated, consider the operation a success
548 if (updates.empty())
549 {
550 sendSuccessResponse(request, parameters);
551 return;
552 }
553
554 bool shouldWaitToRespond = false;
555
556 // An application request should wait for all FIB updates to be applied
557 // successfully before sending a response
558 if (parameters.getOrigin() == ndn::nfd::ROUTE_ORIGIN_APP)
559 {
560 shouldWaitToRespond = true;
561 }
562 else // Respond immediately
563 {
564 sendSuccessResponse(request, parameters);
565 }
566
567 NFD_LOG_DEBUG("Applying " << updates.size() << " updates to FIB");
568
569 // Assign an ID to this FIB transaction
570 TransactionId currentTransactionId = ++m_lastTransactionId;
571
572 // Add this transaction to the transaction table
573 m_pendingFibTransactions[currentTransactionId] = updates.size();
574
575 for (Rib::FibUpdateList::const_iterator it = updates.begin(); it != updates.end(); ++it)
576 {
577 shared_ptr<const FibUpdate> update(*it);
578
579 if (update->action == FibUpdate::ADD_NEXTHOP)
580 {
581 FaceEntry faceEntry;
582 faceEntry.faceId = update->faceId;
583 faceEntry.cost = update->cost;
584
585 m_nfdController.start<ndn::nfd::FibAddNextHopCommand>(
586 ControlParameters()
587 .setName(update->name)
588 .setFaceId(faceEntry.faceId)
589 .setCost(faceEntry.cost),
590 bind(&RibManager::onAddNextHopSuccess, this, request,
591 parameters,
592 currentTransactionId,
593 shouldWaitToRespond),
594 bind(&RibManager::onAddNextHopError, this, _1, _2, request, currentTransactionId,
595 shouldWaitToRespond));
596 }
597 else if (update->action == FibUpdate::REMOVE_NEXTHOP)
598 {
599 FaceEntry faceEntry;
600 faceEntry.faceId = update->faceId;
601
602 m_nfdController.start<ndn::nfd::FibRemoveNextHopCommand>(
603 ControlParameters()
604 .setName(update->name)
605 .setFaceId(faceEntry.faceId),
606 bind(&RibManager::onRemoveNextHopSuccess, this, request,
607 parameters,
608 currentTransactionId,
609 shouldWaitToRespond),
610 bind(&RibManager::onRemoveNextHopError, this, _1, _2, request, currentTransactionId,
611 shouldWaitToRespond));
612 }
613 }
614
615 m_managedRib.clearFibUpdates();
616}
617
618void
619RibManager::sendUpdatesToFibAfterFaceDestroyEvent()
620{
621 ControlParameters parameters;
622 parameters.setOrigin(ndn::nfd::ROUTE_ORIGIN_STATIC);
623
624 sendUpdatesToFib(shared_ptr<const Interest>(), parameters);
Alexander Afanasyev3ecec502014-04-16 13:42:44 -0700625}
626
627} // namespace rib
628} // namespace nfd