blob: 24bfd7f08ed717236d6f4b3e1828de7d353903ca [file] [log] [blame]
Yanbiao Li73860e32015-08-19 16:30:16 -07001/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
Eric Newberry944f38b2017-07-20 20:54:22 -04002/*
Davide Pesavento2c9d2ca2024-01-27 16:36:51 -05003 * Copyright (c) 2014-2024, Regents of the University of California,
Yanbiao Li73860e32015-08-19 16:30:16 -07004 * 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 "face-manager.hpp"
Davide Pesaventoa3148082018-04-12 18:21:54 -040027
Davide Pesavento2cae8ca2019-04-18 20:48:05 -040028#include "common/logger.hpp"
Junxiao Shi40cb61c2015-09-23 18:36:45 -070029#include "face/generic-link-service.hpp"
Junxiao Shib8590312016-12-29 21:22:25 +000030#include "face/protocol-factory.hpp"
Yukai Tu0a49d342015-09-13 12:54:22 +080031#include "fw/face-table.hpp"
Yanbiao Li73860e32015-08-19 16:30:16 -070032
Junxiao Shicbc8e942016-09-06 03:17:45 +000033#include <ndn-cxx/lp/tags.hpp>
Junxiao Shi25c6ce42016-09-09 13:49:59 +000034#include <ndn-cxx/mgmt/nfd/channel-status.hpp>
Davide Pesavento28181322018-11-08 16:44:50 -050035#include <ndn-cxx/mgmt/nfd/face-event-notification.hpp>
36#include <ndn-cxx/mgmt/nfd/face-query-filter.hpp>
37#include <ndn-cxx/mgmt/nfd/face-status.hpp>
Yanbiao Li73860e32015-08-19 16:30:16 -070038
Davide Pesavento2c9d2ca2024-01-27 16:36:51 -050039#include <limits>
40
Yanbiao Li73860e32015-08-19 16:30:16 -070041namespace nfd {
42
Davide Pesaventoa3148082018-04-12 18:21:54 -040043NFD_LOG_INIT(FaceManager);
Yanbiao Li73860e32015-08-19 16:30:16 -070044
Junxiao Shiea47bde2017-01-26 17:49:16 +000045FaceManager::FaceManager(FaceSystem& faceSystem,
Davide Pesavento78ddcab2019-02-28 22:00:03 -050046 Dispatcher& dispatcher, CommandAuthenticator& authenticator)
47 : ManagerBase("faces", dispatcher, authenticator)
Junxiao Shiea47bde2017-01-26 17:49:16 +000048 , m_faceSystem(faceSystem)
49 , m_faceTable(faceSystem.getFaceTable())
Yanbiao Li73860e32015-08-19 16:30:16 -070050{
Yanbiao Li58ba3f92017-02-15 14:27:18 +000051 // register handlers for ControlCommand
Davide Pesavento412c9822021-07-02 00:21:05 -040052 registerCommandHandler<ndn::nfd::FaceCreateCommand>("create",
Davide Pesaventoae430302023-05-11 01:42:46 -040053 [this] (auto&&, auto&&, auto&&, auto&&... args) { createFace(std::forward<decltype(args)>(args)...); });
Davide Pesavento412c9822021-07-02 00:21:05 -040054 registerCommandHandler<ndn::nfd::FaceUpdateCommand>("update",
Davide Pesaventoae430302023-05-11 01:42:46 -040055 [this] (auto&&, auto&&, auto&&... args) { updateFace(std::forward<decltype(args)>(args)...); });
Davide Pesavento412c9822021-07-02 00:21:05 -040056 registerCommandHandler<ndn::nfd::FaceDestroyCommand>("destroy",
Davide Pesaventoae430302023-05-11 01:42:46 -040057 [this] (auto&&, auto&&, auto&&, auto&&... args) { destroyFace(std::forward<decltype(args)>(args)...); });
Yanbiao Li73860e32015-08-19 16:30:16 -070058
Yanbiao Li58ba3f92017-02-15 14:27:18 +000059 // register handlers for StatusDataset
Davide Pesaventoae430302023-05-11 01:42:46 -040060 registerStatusDatasetHandler("list",
61 [this] (auto&&, auto&&, auto&&... args) { listFaces(std::forward<decltype(args)>(args)...); });
62 registerStatusDatasetHandler("channels",
63 [this] (auto&&, auto&&, auto&&... args) { listChannels(std::forward<decltype(args)>(args)...); });
64 registerStatusDatasetHandler("query",
65 [this] (auto&&, auto&&... args) { queryFaces(std::forward<decltype(args)>(args)...); });
Yanbiao Li73860e32015-08-19 16:30:16 -070066
Yanbiao Li58ba3f92017-02-15 14:27:18 +000067 // register notification stream
Junxiao Shiae04d342016-07-19 13:20:22 +000068 m_postNotification = registerNotificationStream("events");
Eric Newberry1b4ba052016-10-07 23:04:07 -070069 m_faceAddConn = m_faceTable.afterAdd.connect([this] (const Face& face) {
70 connectFaceStateChangeSignal(face);
71 notifyFaceEvent(face, ndn::nfd::FACE_EVENT_CREATED);
72 });
73 m_faceRemoveConn = m_faceTable.beforeRemove.connect([this] (const Face& face) {
74 notifyFaceEvent(face, ndn::nfd::FACE_EVENT_DESTROYED);
75 });
Yanbiao Li73860e32015-08-19 16:30:16 -070076}
77
78void
Davide Pesavento28181322018-11-08 16:44:50 -050079FaceManager::createFace(const ControlParameters& parameters,
Yanbiao Li73860e32015-08-19 16:30:16 -070080 const ndn::mgmt::CommandContinuation& done)
81{
Eric Newberry78e32b02017-04-01 14:34:44 +000082 FaceUri remoteUri;
83 if (!remoteUri.parse(parameters.getUri())) {
84 NFD_LOG_TRACE("failed to parse remote URI: " << parameters.getUri());
Eric Newberry42602412016-08-27 09:33:18 -070085 done(ControlResponse(400, "Malformed command"));
86 return;
Yanbiao Li73860e32015-08-19 16:30:16 -070087 }
88
Eric Newberry78e32b02017-04-01 14:34:44 +000089 if (!remoteUri.isCanonical()) {
90 NFD_LOG_TRACE("received non-canonical remote URI: " << remoteUri.toString());
91 done(ControlResponse(400, "Non-canonical remote URI"));
Eric Newberry42602412016-08-27 09:33:18 -070092 return;
Yanbiao Li73860e32015-08-19 16:30:16 -070093 }
94
Davide Pesaventob7bfcb92022-05-22 23:55:23 -040095 std::optional<FaceUri> localUri;
Eric Newberry78e32b02017-04-01 14:34:44 +000096 if (parameters.hasLocalUri()) {
97 localUri = FaceUri{};
98
99 if (!localUri->parse(parameters.getLocalUri())) {
100 NFD_LOG_TRACE("failed to parse local URI: " << parameters.getLocalUri());
101 done(ControlResponse(400, "Malformed command"));
102 return;
103 }
104
105 if (!localUri->isCanonical()) {
106 NFD_LOG_TRACE("received non-canonical local URI: " << localUri->toString());
107 done(ControlResponse(400, "Non-canonical local URI"));
108 return;
109 }
110 }
111
Davide Pesaventoe5eebad2017-04-06 20:23:26 -0400112 face::ProtocolFactory* factory = m_faceSystem.getFactoryByScheme(remoteUri.getScheme());
Junxiao Shib8590312016-12-29 21:22:25 +0000113 if (factory == nullptr) {
Eric Newberry78e32b02017-04-01 14:34:44 +0000114 NFD_LOG_TRACE("received create request for unsupported protocol: " << remoteUri.getScheme());
Eric Newberry42602412016-08-27 09:33:18 -0700115 done(ControlResponse(406, "Unsupported protocol"));
116 return;
Yanbiao Li73860e32015-08-19 16:30:16 -0700117 }
118
Davide Pesavento15b55052018-01-27 19:09:28 -0500119 face::FaceParams faceParams;
120 faceParams.persistency = parameters.getFacePersistency();
Eric Newberry0c3e57b2018-01-25 20:54:46 -0700121 if (parameters.hasBaseCongestionMarkingInterval()) {
122 faceParams.baseCongestionMarkingInterval = parameters.getBaseCongestionMarkingInterval();
123 }
124 if (parameters.hasDefaultCongestionThreshold()) {
125 faceParams.defaultCongestionThreshold = parameters.getDefaultCongestionThreshold();
126 }
Eric Newberry812d6152018-06-06 15:06:01 -0700127 if (parameters.hasMtu()) {
Eric Newberry13ff2592020-03-06 17:32:29 -0800128 // The face system limits MTUs to ssize_t, but the management protocol uses uint64_t
Eric Newberrycb6551e2020-03-02 14:12:16 -0800129 faceParams.mtu = std::min<uint64_t>(std::numeric_limits<ssize_t>::max(), parameters.getMtu());
Eric Newberry812d6152018-06-06 15:06:01 -0700130 }
Davide Pesavento15b55052018-01-27 19:09:28 -0500131 faceParams.wantLocalFields = parameters.hasFlagBit(ndn::nfd::BIT_LOCAL_FIELDS_ENABLED) &&
132 parameters.getFlagBit(ndn::nfd::BIT_LOCAL_FIELDS_ENABLED);
133 faceParams.wantLpReliability = parameters.hasFlagBit(ndn::nfd::BIT_LP_RELIABILITY_ENABLED) &&
134 parameters.getFlagBit(ndn::nfd::BIT_LP_RELIABILITY_ENABLED);
Eric Newberry0c3e57b2018-01-25 20:54:46 -0700135 if (parameters.hasFlagBit(ndn::nfd::BIT_CONGESTION_MARKING_ENABLED)) {
136 faceParams.wantCongestionMarking = parameters.getFlagBit(ndn::nfd::BIT_CONGESTION_MARKING_ENABLED);
137 }
Yanbiao Li73860e32015-08-19 16:30:16 -0700138 try {
Davide Pesavento15b55052018-01-27 19:09:28 -0500139 factory->createFace({remoteUri, localUri, faceParams},
Davide Pesavento28181322018-11-08 16:44:50 -0500140 [this, parameters, done] (const auto& face) {
141 this->afterCreateFaceSuccess(face, parameters, done);
142 },
143 [done] (uint32_t status, const std::string& reason) {
144 NFD_LOG_DEBUG("Face creation failed: " << reason);
145 done(ControlResponse(status, reason));
146 });
Yanbiao Li73860e32015-08-19 16:30:16 -0700147 }
148 catch (const std::runtime_error& error) {
Eric Newberry42602412016-08-27 09:33:18 -0700149 NFD_LOG_ERROR("Face creation failed: " << error.what());
150 done(ControlResponse(500, "Face creation failed due to internal error"));
151 return;
Yanbiao Li73860e32015-08-19 16:30:16 -0700152 }
153 catch (const std::logic_error& error) {
Eric Newberry42602412016-08-27 09:33:18 -0700154 NFD_LOG_ERROR("Face creation failed: " << error.what());
155 done(ControlResponse(500, "Face creation failed due to internal error"));
156 return;
Yanbiao Li73860e32015-08-19 16:30:16 -0700157 }
158}
159
Davide Pesavento28181322018-11-08 16:44:50 -0500160template<typename T>
161static void
162copyMtu(const Face& face, T& to)
163{
Eric Newberrycb6551e2020-03-02 14:12:16 -0800164 if (face.getMtu() >= 0) {
165 to.setMtu(std::min<size_t>(face.getMtu(), ndn::MAX_NDN_PACKET_SIZE));
Davide Pesavento28181322018-11-08 16:44:50 -0500166 }
Eric Newberrycb6551e2020-03-02 14:12:16 -0800167 else if (face.getMtu() == face::MTU_UNLIMITED) {
Davide Pesavento28181322018-11-08 16:44:50 -0500168 to.setMtu(ndn::MAX_NDN_PACKET_SIZE);
169 }
170}
171
172static ControlParameters
173makeUpdateFaceResponse(const Face& face)
174{
175 ControlParameters params;
176 params.setFaceId(face.getId())
177 .setFacePersistency(face.getPersistency());
Eric Newberry13ff2592020-03-06 17:32:29 -0800178 copyMtu(face, params);
Davide Pesavento28181322018-11-08 16:44:50 -0500179
180 auto linkService = dynamic_cast<face::GenericLinkService*>(face.getLinkService());
181 if (linkService != nullptr) {
182 const auto& options = linkService->getOptions();
183 params.setBaseCongestionMarkingInterval(options.baseCongestionMarkingInterval)
184 .setDefaultCongestionThreshold(options.defaultCongestionThreshold)
185 .setFlagBit(ndn::nfd::BIT_LOCAL_FIELDS_ENABLED, options.allowLocalFields, false)
186 .setFlagBit(ndn::nfd::BIT_LP_RELIABILITY_ENABLED, options.reliabilityOptions.isEnabled, false)
187 .setFlagBit(ndn::nfd::BIT_CONGESTION_MARKING_ENABLED, options.allowCongestionMarking, false);
188 }
189
190 return params;
191}
192
193static ControlParameters
194makeCreateFaceResponse(const Face& face)
195{
196 ControlParameters params = makeUpdateFaceResponse(face);
197 params.setUri(face.getRemoteUri().toString())
198 .setLocalUri(face.getLocalUri().toString());
199
Davide Pesavento28181322018-11-08 16:44:50 -0500200 return params;
201}
202
Yanbiao Li73860e32015-08-19 16:30:16 -0700203void
Davide Pesavento28181322018-11-08 16:44:50 -0500204FaceManager::afterCreateFaceSuccess(const shared_ptr<Face>& face,
205 const ControlParameters& parameters,
Yanbiao Li73860e32015-08-19 16:30:16 -0700206 const ndn::mgmt::CommandContinuation& done)
207{
Davide Pesavento28181322018-11-08 16:44:50 -0500208 if (face->getId() != face::INVALID_FACEID) { // Face already exists
Yanbiao Li58ba3f92017-02-15 14:27:18 +0000209 NFD_LOG_TRACE("Attempted to create duplicate face of " << face->getId());
Davide Pesavento28181322018-11-08 16:44:50 -0500210 ControlParameters response = makeCreateFaceResponse(*face);
Yanbiao Li58ba3f92017-02-15 14:27:18 +0000211 done(ControlResponse(409, "Face with remote URI already exists").setBody(response.wireEncode()));
212 return;
213 }
214
Eric Newberryf40551a2016-09-05 15:41:16 -0700215 // If scope non-local and flags set to enable local fields, request shouldn't
216 // have made it this far
217 BOOST_ASSERT(face->getScope() == ndn::nfd::FACE_SCOPE_LOCAL ||
218 !parameters.hasFlagBit(ndn::nfd::BIT_LOCAL_FIELDS_ENABLED) ||
219 (parameters.hasFlagBit(ndn::nfd::BIT_LOCAL_FIELDS_ENABLED) &&
220 !parameters.getFlagBit(ndn::nfd::BIT_LOCAL_FIELDS_ENABLED)));
221
222 m_faceTable.add(face);
223
Davide Pesavento28181322018-11-08 16:44:50 -0500224 ControlParameters response = makeCreateFaceResponse(*face);
Eric Newberry42602412016-08-27 09:33:18 -0700225 done(ControlResponse(200, "OK").setBody(response.wireEncode()));
226}
227
Davide Pesavento28181322018-11-08 16:44:50 -0500228static void
229updateLinkServiceOptions(Face& face, const ControlParameters& parameters)
Eric Newberry42602412016-08-27 09:33:18 -0700230{
Davide Pesavento28181322018-11-08 16:44:50 -0500231 auto linkService = dynamic_cast<face::GenericLinkService*>(face.getLinkService());
232 if (linkService == nullptr) {
233 return;
234 }
235 auto options = linkService->getOptions();
Eric Newberry42602412016-08-27 09:33:18 -0700236
Davide Pesavento28181322018-11-08 16:44:50 -0500237 if (parameters.hasFlagBit(ndn::nfd::BIT_LOCAL_FIELDS_ENABLED) &&
238 face.getScope() == ndn::nfd::FACE_SCOPE_LOCAL) {
239 options.allowLocalFields = parameters.getFlagBit(ndn::nfd::BIT_LOCAL_FIELDS_ENABLED);
240 }
241 if (parameters.hasFlagBit(ndn::nfd::BIT_LP_RELIABILITY_ENABLED)) {
242 options.reliabilityOptions.isEnabled = parameters.getFlagBit(ndn::nfd::BIT_LP_RELIABILITY_ENABLED);
243 }
244 if (parameters.hasFlagBit(ndn::nfd::BIT_CONGESTION_MARKING_ENABLED)) {
245 options.allowCongestionMarking = parameters.getFlagBit(ndn::nfd::BIT_CONGESTION_MARKING_ENABLED);
246 }
247 if (parameters.hasBaseCongestionMarkingInterval()) {
248 options.baseCongestionMarkingInterval = parameters.getBaseCongestionMarkingInterval();
249 }
250 if (parameters.hasDefaultCongestionThreshold()) {
251 options.defaultCongestionThreshold = parameters.getDefaultCongestionThreshold();
252 }
253
Eric Newberry13ff2592020-03-06 17:32:29 -0800254 if (parameters.hasMtu()) {
255 // The face system limits MTUs to ssize_t, but the management protocol uses uint64_t
256 options.overrideMtu = std::min<uint64_t>(std::numeric_limits<ssize_t>::max(), parameters.getMtu());
257 }
258
Davide Pesavento28181322018-11-08 16:44:50 -0500259 linkService->setOptions(options);
Yanbiao Li73860e32015-08-19 16:30:16 -0700260}
261
262void
Davide Pesavento28181322018-11-08 16:44:50 -0500263FaceManager::updateFace(const Interest& interest,
Eric Newberryb5aa7f52016-09-03 20:36:12 -0700264 const ControlParameters& parameters,
265 const ndn::mgmt::CommandContinuation& done)
266{
267 FaceId faceId = parameters.getFaceId();
Davide Pesaventoa3a7a4e2022-05-29 16:06:22 -0400268 if (faceId == face::INVALID_FACEID) { // Self-update
Davide Pesavento28181322018-11-08 16:44:50 -0500269 auto incomingFaceIdTag = interest.getTag<lp::IncomingFaceIdTag>();
Eric Newberryb5aa7f52016-09-03 20:36:12 -0700270 if (incomingFaceIdTag == nullptr) {
271 NFD_LOG_TRACE("unable to determine face for self-update");
272 done(ControlResponse(404, "No FaceId specified and IncomingFaceId not available"));
273 return;
274 }
275 faceId = *incomingFaceIdTag;
276 }
277
278 Face* face = m_faceTable.get(faceId);
Eric Newberryb5aa7f52016-09-03 20:36:12 -0700279 if (face == nullptr) {
280 NFD_LOG_TRACE("invalid face specified");
281 done(ControlResponse(404, "Specified face does not exist"));
282 return;
283 }
284
285 // Verify validity of requested changes
286 ControlParameters response;
287 bool areParamsValid = true;
288
Eric Newberryb5aa7f52016-09-03 20:36:12 -0700289 if (parameters.hasFlagBit(ndn::nfd::BIT_LOCAL_FIELDS_ENABLED) &&
290 parameters.getFlagBit(ndn::nfd::BIT_LOCAL_FIELDS_ENABLED) &&
291 face->getScope() != ndn::nfd::FACE_SCOPE_LOCAL) {
292 NFD_LOG_TRACE("received request to enable local fields on non-local face");
293 areParamsValid = false;
294 response.setFlagBit(ndn::nfd::BIT_LOCAL_FIELDS_ENABLED,
295 parameters.getFlagBit(ndn::nfd::BIT_LOCAL_FIELDS_ENABLED));
296 }
297
Yanbiao Li58ba3f92017-02-15 14:27:18 +0000298 // check whether the requested FacePersistency change is valid if it's present
299 if (parameters.hasFacePersistency()) {
300 auto persistency = parameters.getFacePersistency();
301 if (!face->getTransport()->canChangePersistencyTo(persistency)) {
302 NFD_LOG_TRACE("cannot change face persistency to " << persistency);
303 areParamsValid = false;
304 response.setFacePersistency(persistency);
305 }
306 }
307
Eric Newberry13ff2592020-03-06 17:32:29 -0800308 // check whether the requested MTU override is valid (if it's present)
309 if (parameters.hasMtu()) {
310 auto mtu = parameters.getMtu();
311 // The face system limits MTUs to ssize_t, but the management protocol uses uint64_t
312 auto actualMtu = std::min<uint64_t>(std::numeric_limits<ssize_t>::max(), mtu);
313 auto linkService = dynamic_cast<face::GenericLinkService*>(face->getLinkService());
314 if (linkService == nullptr || !linkService->canOverrideMtuTo(actualMtu)) {
315 NFD_LOG_TRACE("cannot override face MTU to " << mtu);
316 areParamsValid = false;
317 response.setMtu(mtu);
318 }
319 }
320
Eric Newberryb5aa7f52016-09-03 20:36:12 -0700321 if (!areParamsValid) {
322 done(ControlResponse(409, "Invalid properties specified").setBody(response.wireEncode()));
323 return;
324 }
325
326 // All specified properties are valid, so make changes
Yanbiao Li58ba3f92017-02-15 14:27:18 +0000327 if (parameters.hasFacePersistency()) {
328 face->setPersistency(parameters.getFacePersistency());
329 }
Davide Pesavento28181322018-11-08 16:44:50 -0500330 updateLinkServiceOptions(*face, parameters);
Eric Newberryb5aa7f52016-09-03 20:36:12 -0700331
Davide Pesavento28181322018-11-08 16:44:50 -0500332 // Prepare and send ControlResponse
333 response = makeUpdateFaceResponse(*face);
Eric Newberryb5aa7f52016-09-03 20:36:12 -0700334 done(ControlResponse(200, "OK").setBody(response.wireEncode()));
335}
336
337void
Davide Pesavento28181322018-11-08 16:44:50 -0500338FaceManager::destroyFace(const ControlParameters& parameters,
Junxiao Shi40cb61c2015-09-23 18:36:45 -0700339 const ndn::mgmt::CommandContinuation& done)
340{
Junxiao Shi5b43f9a2016-07-19 13:15:56 +0000341 Face* face = m_faceTable.get(parameters.getFaceId());
342 if (face != nullptr) {
343 face->close();
Junxiao Shi40cb61c2015-09-23 18:36:45 -0700344 }
345
346 done(ControlResponse(200, "OK").setBody(parameters.wireEncode()));
347}
348
Davide Pesavento28181322018-11-08 16:44:50 -0500349template<typename T>
350static void
351copyFaceProperties(const Face& face, T& to)
Eric Newberryb5aa7f52016-09-03 20:36:12 -0700352{
Davide Pesavento28181322018-11-08 16:44:50 -0500353 to.setFaceId(face.getId())
354 .setRemoteUri(face.getRemoteUri().toString())
355 .setLocalUri(face.getLocalUri().toString())
356 .setFaceScope(face.getScope())
357 .setFacePersistency(face.getPersistency())
358 .setLinkType(face.getLinkType());
Eric Newberryb5aa7f52016-09-03 20:36:12 -0700359
Davide Pesavento28181322018-11-08 16:44:50 -0500360 auto linkService = dynamic_cast<face::GenericLinkService*>(face.getLinkService());
361 if (linkService != nullptr) {
362 const auto& options = linkService->getOptions();
363 to.setFlagBit(ndn::nfd::BIT_LOCAL_FIELDS_ENABLED, options.allowLocalFields)
364 .setFlagBit(ndn::nfd::BIT_LP_RELIABILITY_ENABLED, options.reliabilityOptions.isEnabled)
365 .setFlagBit(ndn::nfd::BIT_CONGESTION_MARKING_ENABLED, options.allowCongestionMarking);
Eric Newberryb5aa7f52016-09-03 20:36:12 -0700366 }
Eric Newberryb5aa7f52016-09-03 20:36:12 -0700367}
368
Davide Pesavento28181322018-11-08 16:44:50 -0500369static ndn::nfd::FaceStatus
Davide Pesavento412c9822021-07-02 00:21:05 -0400370makeFaceStatus(const Face& face, const time::steady_clock::time_point& now)
Yanbiao Li58ba3f92017-02-15 14:27:18 +0000371{
Davide Pesavento28181322018-11-08 16:44:50 -0500372 ndn::nfd::FaceStatus status;
373 copyFaceProperties(face, status);
374
375 auto expirationTime = face.getExpirationTime();
Davide Pesavento412c9822021-07-02 00:21:05 -0400376 if (expirationTime != time::steady_clock::time_point::max()) {
Davide Pesavento28181322018-11-08 16:44:50 -0500377 status.setExpirationPeriod(std::max(0_ms,
378 time::duration_cast<time::milliseconds>(expirationTime - now)));
379 }
380
Yanbiao Li58ba3f92017-02-15 14:27:18 +0000381 auto linkService = dynamic_cast<face::GenericLinkService*>(face.getLinkService());
Davide Pesavento28181322018-11-08 16:44:50 -0500382 if (linkService != nullptr) {
383 const auto& options = linkService->getOptions();
384 status.setBaseCongestionMarkingInterval(options.baseCongestionMarkingInterval)
385 .setDefaultCongestionThreshold(options.defaultCongestionThreshold);
Eric Newberry812d6152018-06-06 15:06:01 -0700386 }
387
Davide Pesavento28181322018-11-08 16:44:50 -0500388 copyMtu(face, status);
389
390 const auto& counters = face.getCounters();
391 status.setNInInterests(counters.nInInterests)
392 .setNOutInterests(counters.nOutInterests)
393 .setNInData(counters.nInData)
394 .setNOutData(counters.nOutData)
395 .setNInNacks(counters.nInNacks)
396 .setNOutNacks(counters.nOutNacks)
397 .setNInBytes(counters.nInBytes)
398 .setNOutBytes(counters.nOutBytes);
399
400 return status;
Yanbiao Li58ba3f92017-02-15 14:27:18 +0000401}
402
Eric Newberryb5aa7f52016-09-03 20:36:12 -0700403void
Davide Pesavento28181322018-11-08 16:44:50 -0500404FaceManager::listFaces(ndn::mgmt::StatusDatasetContext& context)
Yanbiao Li73860e32015-08-19 16:30:16 -0700405{
Eric Newberryc64d30a2015-12-26 11:07:27 -0700406 auto now = time::steady_clock::now();
Davide Pesavento28181322018-11-08 16:44:50 -0500407 for (const auto& face : m_faceTable) {
408 ndn::nfd::FaceStatus status = makeFaceStatus(face, now);
Junxiao Shida93f1f2015-11-11 06:13:16 -0700409 context.append(status.wireEncode());
Yanbiao Li73860e32015-08-19 16:30:16 -0700410 }
411 context.end();
412}
413
414void
Davide Pesavento28181322018-11-08 16:44:50 -0500415FaceManager::listChannels(ndn::mgmt::StatusDatasetContext& context)
Yanbiao Li73860e32015-08-19 16:30:16 -0700416{
Davide Pesavento28181322018-11-08 16:44:50 -0500417 auto factories = m_faceSystem.listProtocolFactories();
Davide Pesaventoe5eebad2017-04-06 20:23:26 -0400418 for (const auto* factory : factories) {
Junxiao Shib8590312016-12-29 21:22:25 +0000419 for (const auto& channel : factory->getChannels()) {
420 ndn::nfd::ChannelStatus entry;
421 entry.setLocalUri(channel->getUri().toString());
422 context.append(entry.wireEncode());
Yanbiao Li73860e32015-08-19 16:30:16 -0700423 }
424 }
Yanbiao Li73860e32015-08-19 16:30:16 -0700425 context.end();
426}
427
Davide Pesavento28181322018-11-08 16:44:50 -0500428static bool
429matchFilter(const ndn::nfd::FaceQueryFilter& filter, const Face& face)
Yanbiao Li73860e32015-08-19 16:30:16 -0700430{
431 if (filter.hasFaceId() &&
Junxiao Shib84e6742016-07-19 13:16:22 +0000432 filter.getFaceId() != static_cast<uint64_t>(face.getId())) {
Yanbiao Li73860e32015-08-19 16:30:16 -0700433 return false;
434 }
435
436 if (filter.hasUriScheme() &&
Junxiao Shib84e6742016-07-19 13:16:22 +0000437 filter.getUriScheme() != face.getRemoteUri().getScheme() &&
438 filter.getUriScheme() != face.getLocalUri().getScheme()) {
Yanbiao Li73860e32015-08-19 16:30:16 -0700439 return false;
440 }
441
442 if (filter.hasRemoteUri() &&
Junxiao Shib84e6742016-07-19 13:16:22 +0000443 filter.getRemoteUri() != face.getRemoteUri().toString()) {
Yanbiao Li73860e32015-08-19 16:30:16 -0700444 return false;
445 }
446
447 if (filter.hasLocalUri() &&
Junxiao Shib84e6742016-07-19 13:16:22 +0000448 filter.getLocalUri() != face.getLocalUri().toString()) {
Yanbiao Li73860e32015-08-19 16:30:16 -0700449 return false;
450 }
451
452 if (filter.hasFaceScope() &&
Junxiao Shib84e6742016-07-19 13:16:22 +0000453 filter.getFaceScope() != face.getScope()) {
Yanbiao Li73860e32015-08-19 16:30:16 -0700454 return false;
455 }
456
457 if (filter.hasFacePersistency() &&
Junxiao Shib84e6742016-07-19 13:16:22 +0000458 filter.getFacePersistency() != face.getPersistency()) {
Yanbiao Li73860e32015-08-19 16:30:16 -0700459 return false;
460 }
461
462 if (filter.hasLinkType() &&
Junxiao Shib84e6742016-07-19 13:16:22 +0000463 filter.getLinkType() != face.getLinkType()) {
Yanbiao Li73860e32015-08-19 16:30:16 -0700464 return false;
465 }
466
467 return true;
468}
469
Junxiao Shicde37ad2015-12-24 01:02:05 -0700470void
Davide Pesavento28181322018-11-08 16:44:50 -0500471FaceManager::queryFaces(const Interest& interest,
472 ndn::mgmt::StatusDatasetContext& context)
Junxiao Shida93f1f2015-11-11 06:13:16 -0700473{
Davide Pesavento28181322018-11-08 16:44:50 -0500474 ndn::nfd::FaceQueryFilter faceFilter;
475 try {
476 faceFilter.wireDecode(interest.getName()[-1].blockFromValue());
Eric Newberry1b4ba052016-10-07 23:04:07 -0700477 }
Davide Pesavento28181322018-11-08 16:44:50 -0500478 catch (const tlv::Error& e) {
479 NFD_LOG_DEBUG("Malformed query filter: " << e.what());
480 return context.reject(ControlResponse(400, "Malformed filter"));
481 }
482
483 auto now = time::steady_clock::now();
484 for (const auto& face : m_faceTable) {
485 if (matchFilter(faceFilter, face)) {
486 ndn::nfd::FaceStatus status = makeFaceStatus(face, now);
487 context.append(status.wireEncode());
488 }
489 }
490 context.end();
Junxiao Shida93f1f2015-11-11 06:13:16 -0700491}
492
493void
Eric Newberry1b4ba052016-10-07 23:04:07 -0700494FaceManager::notifyFaceEvent(const Face& face, ndn::nfd::FaceEventKind kind)
Yanbiao Li73860e32015-08-19 16:30:16 -0700495{
496 ndn::nfd::FaceEventNotification notification;
Eric Newberry1b4ba052016-10-07 23:04:07 -0700497 notification.setKind(kind);
Davide Pesavento28181322018-11-08 16:44:50 -0500498 copyFaceProperties(face, notification);
Yanbiao Li73860e32015-08-19 16:30:16 -0700499
Junxiao Shiae04d342016-07-19 13:20:22 +0000500 m_postNotification(notification.wireEncode());
Yanbiao Li73860e32015-08-19 16:30:16 -0700501}
502
503void
Eric Newberry1b4ba052016-10-07 23:04:07 -0700504FaceManager::connectFaceStateChangeSignal(const Face& face)
Yanbiao Li73860e32015-08-19 16:30:16 -0700505{
Davide Pesavento3cf75dc2018-03-17 00:38:03 -0400506 using face::FaceState;
507
Eric Newberry1b4ba052016-10-07 23:04:07 -0700508 FaceId faceId = face.getId();
509 m_faceStateChangeConn[faceId] = face.afterStateChange.connect(
Davide Pesavento3cf75dc2018-03-17 00:38:03 -0400510 [this, faceId, &face] (FaceState oldState, FaceState newState) {
511 if (newState == FaceState::UP) {
Eric Newberry1b4ba052016-10-07 23:04:07 -0700512 notifyFaceEvent(face, ndn::nfd::FACE_EVENT_UP);
513 }
Davide Pesavento3cf75dc2018-03-17 00:38:03 -0400514 else if (newState == FaceState::DOWN) {
Eric Newberry1b4ba052016-10-07 23:04:07 -0700515 notifyFaceEvent(face, ndn::nfd::FACE_EVENT_DOWN);
516 }
Davide Pesavento3cf75dc2018-03-17 00:38:03 -0400517 else if (newState == FaceState::CLOSED) {
518 // cannot use face.getId() because it may already be reset to INVALID_FACEID
Eric Newberry1b4ba052016-10-07 23:04:07 -0700519 m_faceStateChangeConn.erase(faceId);
520 }
521 });
Yanbiao Li73860e32015-08-19 16:30:16 -0700522}
523
Davide Pesavento1d7e7af2015-10-10 23:54:08 +0200524} // namespace nfd