blob: 6cb0d6bdb3888e77f18fbad1e09dc8b907886d98 [file] [log] [blame]
Alexander Afanasyev3ecec502014-04-16 13:42:44 -07001/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
2/**
3 * 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
10 *
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/>.
24 **/
25
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 Afanasyev3ecec502014-04-16 13:42:44 -070035const Name RibManager::COMMAND_PREFIX = "/localhost/nrd";
36const Name RibManager::REMOTE_COMMAND_PREFIX = "/localhop/nrd";
37
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"),
51 &RibManager::insertEntry
52 ),
53
54 VerbAndProcessor(
55 Name::Component("unregister"),
56 &RibManager::deleteEntry
57 ),
58 };
59
Alexander Afanasyev03ea3eb2014-04-17 18:19:06 -070060inline static void
61NullDeleter(boost::asio::io_service* variable)
62{
63 // do nothing
64}
65
Alexander Afanasyev3ecec502014-04-16 13:42:44 -070066RibManager::RibManager()
Alexander Afanasyev03ea3eb2014-04-17 18:19:06 -070067 : m_face(new ndn::Face(shared_ptr<boost::asio::io_service>(&getGlobalIoService(), &NullDeleter)))
Alexander Afanasyev3ecec502014-04-16 13:42:44 -070068 , m_nfdController(new ndn::nfd::Controller(*m_face))
69 , m_validator(m_face)
70 , m_faceMonitor(*m_face)
71 , m_verbDispatch(COMMAND_VERBS,
72 COMMAND_VERBS + (sizeof(COMMAND_VERBS) / sizeof(VerbAndProcessor)))
73{
74}
75
76void
77RibManager::registerWithNfd()
78{
79 //check whether the components of localhop and localhost prefixes are same
80 BOOST_ASSERT(COMMAND_PREFIX.size() == REMOTE_COMMAND_PREFIX.size());
81
Alexander Afanasyev89cf5e02014-04-17 12:08:57 -070082 NFD_LOG_INFO("Setting interest filter on: " << COMMAND_PREFIX.toUri());
Alexander Afanasyev3ecec502014-04-16 13:42:44 -070083 m_face->setController(m_nfdController);
84 m_face->setInterestFilter(COMMAND_PREFIX.toUri(),
85 bind(&RibManager::onRibRequest, this, _2),
86 bind(&RibManager::setInterestFilterFailed, this, _1, _2));
87
Alexander Afanasyev89cf5e02014-04-17 12:08:57 -070088 NFD_LOG_INFO("Setting interest filter on: " << REMOTE_COMMAND_PREFIX.toUri());
Alexander Afanasyev3ecec502014-04-16 13:42:44 -070089 m_face->setInterestFilter(REMOTE_COMMAND_PREFIX.toUri(),
90 bind(&RibManager::onRibRequest, this, _2),
91 bind(&RibManager::setInterestFilterFailed, this, _1, _2));
92
Alexander Afanasyev89cf5e02014-04-17 12:08:57 -070093 NFD_LOG_INFO("Start monitoring face create/destroy events");
Alexander Afanasyev3ecec502014-04-16 13:42:44 -070094 m_faceMonitor.addSubscriber(boost::bind(&RibManager::onNotification, this, _1));
95 m_faceMonitor.startNotifications();
96}
97
98void
99RibManager::setConfigFile(ConfigFile& configFile)
100{
Steve DiBenedetto34c95f72014-04-17 20:56:00 -0600101 configFile.addSectionHandler("rib_security",
Alexander Afanasyev3ecec502014-04-16 13:42:44 -0700102 bind(&RibManager::onConfig, this, _1, _2, _3));
103}
104
105void
106RibManager::onConfig(const ConfigSection& configSection,
107 bool isDryRun,
108 const std::string& filename)
109{
110 /// \todo remove check after validator-conf replaces settings on each load
111 if (!isDryRun)
112 m_validator.load(configSection, filename);
113}
114
115void
116RibManager::setInterestFilterFailed(const Name& name, const std::string& msg)
117{
Alexander Afanasyev89cf5e02014-04-17 12:08:57 -0700118 NFD_LOG_ERROR("Error in setting interest filter (" << name << "): " << msg);
Alexander Afanasyev3ecec502014-04-16 13:42:44 -0700119 m_face->shutdown();
120}
121
122void
123RibManager::sendResponse(const Name& name,
124 const ControlResponse& response)
125{
126 const Block& encodedControl = response.wireEncode();
127
128 Data responseData(name);
129 responseData.setContent(encodedControl);
130
131 m_keyChain.sign(responseData);
132 m_face->put(responseData);
133}
134
135void
136RibManager::sendResponse(const Name& name,
137 uint32_t code,
138 const std::string& text)
139{
140 ControlResponse response(code, text);
141 sendResponse(name, response);
142}
143
144void
145RibManager::onRibRequest(const Interest& request)
146{
147 m_validator.validate(request,
148 bind(&RibManager::onRibRequestValidated, this, _1),
149 bind(&RibManager::onRibRequestValidationFailed, this, _1, _2));
150}
151
152void
153RibManager::onRibRequestValidated(const shared_ptr<const Interest>& request)
154{
155 const Name& command = request->getName();
156
157 //REMOTE_COMMAND_PREFIX number of componenets are same as
158 // NRD_COMMAND_PREFIX's so no extra checks are required.
159 const Name::Component& verb = command.get(COMMAND_PREFIX.size());
160 VerbDispatchTable::const_iterator verbProcessor = m_verbDispatch.find(verb);
161
162 if (verbProcessor != m_verbDispatch.end())
163 {
Alexander Afanasyev89cf5e02014-04-17 12:08:57 -0700164 NFD_LOG_TRACE("Processing '" << verb << "' verb");
165
Alexander Afanasyev3ecec502014-04-16 13:42:44 -0700166 PrefixRegOptions options;
167 if (!extractOptions(*request, options))
168 {
Alexander Afanasyev89cf5e02014-04-17 12:08:57 -0700169 NFD_LOG_DEBUG("Error while extracting options, returning malformed command");
Alexander Afanasyev3ecec502014-04-16 13:42:44 -0700170 sendResponse(command, 400, "Malformed command");
171 return;
172 }
173
Alexander Afanasyev89cf5e02014-04-17 12:08:57 -0700174 NFD_LOG_DEBUG("Received options (name, faceid, cost): " << options.getName()
175 << ", " << options.getFaceId() << ", " << options.getCost());
Alexander Afanasyev3ecec502014-04-16 13:42:44 -0700176
177 ControlResponse response;
178 (verbProcessor->second)(this, *request, options);
179 }
180 else
181 {
Alexander Afanasyev89cf5e02014-04-17 12:08:57 -0700182 NFD_LOG_DEBUG("Unsupported command: " << verb);
Alexander Afanasyev3ecec502014-04-16 13:42:44 -0700183 sendResponse(request->getName(), 501, "Unsupported command");
184 }
185}
186
187void
188RibManager::onRibRequestValidationFailed(const shared_ptr<const Interest>& request,
189 const std::string& failureInfo)
190{
Alexander Afanasyev89cf5e02014-04-17 12:08:57 -0700191 NFD_LOG_DEBUG("RibRequestValidationFailed: " << failureInfo);
Alexander Afanasyev3ecec502014-04-16 13:42:44 -0700192 sendResponse(request->getName(), 403, failureInfo);
193}
194
195bool
196RibManager::extractOptions(const Interest& request,
197 PrefixRegOptions& extractedOptions)
198{
199 // const Name& command = request.getName();
200 //REMOTE_COMMAND_PREFIX is same in size of NRD_COMMAND_PREFIX
201 //so no extra processing is required.
202 const size_t optionCompIndex = COMMAND_PREFIX.size() + 1;
203
204 try
205 {
206 Block rawOptions = request.getName()[optionCompIndex].blockFromValue();
207 extractedOptions.wireDecode(rawOptions);
208 }
209 catch (const ndn::Tlv::Error& e)
210 {
211 return false;
212 }
213
214 if (extractedOptions.getFaceId() == 0)
215 {
Alexander Afanasyev89cf5e02014-04-17 12:08:57 -0700216 NFD_LOG_TRACE("IncomingFaceId: " << request.getIncomingFaceId());
Alexander Afanasyev3ecec502014-04-16 13:42:44 -0700217 extractedOptions.setFaceId(request.getIncomingFaceId());
218 }
219 return true;
220}
221
222void
223RibManager::onCommandError(uint32_t code, const std::string& error,
224 const Interest& request,
225 const PrefixRegOptions& options)
226{
Alexander Afanasyev89cf5e02014-04-17 12:08:57 -0700227 NFD_LOG_ERROR("NFD returned an error: " << error << " (code: " << code << ")");
Alexander Afanasyev3ecec502014-04-16 13:42:44 -0700228
229 ControlResponse response;
230
231 if (code == 404)
232 {
233 response.setCode(code);
234 response.setText(error);
235 }
236 else
237 {
238 response.setCode(533);
239 std::ostringstream os;
240 os << "Failure to update NFD " << "(NFD Error: " << code << " " << error << ")";
241 response.setText(os.str());
242 }
243
244 sendResponse(request.getName(), response);
245 m_managedRib.erase(options);
246}
247
248void
249RibManager::onUnRegSuccess(const Interest& request, const PrefixRegOptions& options)
250{
251 ControlResponse response;
252
253 response.setCode(200);
254 response.setText("Success");
255 response.setBody(options.wireEncode());
256
Alexander Afanasyev89cf5e02014-04-17 12:08:57 -0700257 NFD_LOG_DEBUG("onUnRegSuccess: Name unregistered (" << options.getName()
258 << ", " << options.getFaceId() << ")");
259
Alexander Afanasyev3ecec502014-04-16 13:42:44 -0700260 sendResponse(request.getName(), response);
261 m_managedRib.erase(options);
262}
263
264void
265RibManager::onRegSuccess(const Interest& request, const PrefixRegOptions& options)
266{
267 ControlResponse response;
268
269 response.setCode(200);
270 response.setText("Success");
271 response.setBody(options.wireEncode());
272
Alexander Afanasyev89cf5e02014-04-17 12:08:57 -0700273 NFD_LOG_DEBUG("onRegSuccess: Name registered (" << options.getName() << ", "
274 << options.getFaceId() << ")");
Alexander Afanasyev3ecec502014-04-16 13:42:44 -0700275 sendResponse(request.getName(), response);
276}
277
278void
279RibManager::insertEntry(const Interest& request, const PrefixRegOptions& options)
280{
281 // For right now, just pass the options to fib as it is,
282 // without processing flags. Later options will be first added to
283 // Rib tree, then nrd will generate fib updates based on flags and then
284 // will add next hops one by one..
285 m_managedRib.insert(options);
286 m_nfdController->start<ndn::nfd::FibAddNextHopCommand>(
287 ControlParameters()
288 .setName(options.getName())
289 .setFaceId(options.getFaceId())
290 .setCost(options.getCost()),
291 bind(&RibManager::onRegSuccess, this, request, options),
292 bind(&RibManager::onCommandError, this, _1, _2, request, options));
293}
294
295void
296RibManager::deleteEntry(const Interest& request, const PrefixRegOptions& options)
297{
298 m_nfdController->start<ndn::nfd::FibRemoveNextHopCommand>(
299 ControlParameters()
300 .setName(options.getName())
301 .setFaceId(options.getFaceId()),
302 bind(&RibManager::onUnRegSuccess, this, request, options),
303 bind(&RibManager::onCommandError, this, _1, _2, request, options));
304}
305
Alexander Afanasyev3ecec502014-04-16 13:42:44 -0700306void
307RibManager::onControlHeaderSuccess()
308{
Alexander Afanasyev89cf5e02014-04-17 12:08:57 -0700309 NFD_LOG_DEBUG("Local control header enabled");
Alexander Afanasyev3ecec502014-04-16 13:42:44 -0700310}
311
312void
313RibManager::onControlHeaderError(uint32_t code, const std::string& reason)
314{
Alexander Afanasyev89cf5e02014-04-17 12:08:57 -0700315 NFD_LOG_ERROR("Error: couldn't enable local control header "
316 << "(code: " << code << ", info: " << reason << ")");
Alexander Afanasyev3ecec502014-04-16 13:42:44 -0700317 m_face->shutdown();
318}
319
320void
321RibManager::enableLocalControlHeader()
322{
323 m_nfdController->start<ndn::nfd::FaceEnableLocalControlCommand>(
324 ControlParameters()
325 .setLocalControlFeature(ndn::nfd::LOCAL_CONTROL_FEATURE_INCOMING_FACE_ID),
326 bind(&RibManager::onControlHeaderSuccess, this),
327 bind(&RibManager::onControlHeaderError, this, _1, _2));
328}
329
330void
331RibManager::onNotification(const FaceEventNotification& notification)
332{
333 /// \todo A notification can be missed, in this case check Facelist
Alexander Afanasyev89cf5e02014-04-17 12:08:57 -0700334 NFD_LOG_TRACE("onNotification: " << notification);
Alexander Afanasyev3ecec502014-04-16 13:42:44 -0700335 if (notification.getKind() == ndn::nfd::FACE_EVENT_DESTROYED) { //face destroyed
336 m_managedRib.erase(notification.getFaceId());
337 }
338}
339
340} // namespace rib
341} // namespace nfd