Loading...
Searching...
No Matches
face-manager.cpp
Go to the documentation of this file.
1/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
2/*
3 * Copyright (c) 2014-2025, 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 "face-manager.hpp"
27
28#include "common/logger.hpp"
31#include "fw/face-table.hpp"
32
33#include <ndn-cxx/lp/tags.hpp>
34#include <ndn-cxx/mgmt/nfd/channel-status.hpp>
35#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>
38
39#include <limits>
40
41namespace nfd {
42
43NFD_LOG_INIT(FaceManager);
44
46 Dispatcher& dispatcher, CommandAuthenticator& authenticator)
47 : ManagerBase("faces", dispatcher, authenticator)
48 , m_faceSystem(faceSystem)
49 , m_faceTable(faceSystem.getFaceTable())
50{
51 // register handlers for ControlCommand
52 registerCommandHandler<ndn::nfd::FaceCreateCommand>([this] (auto&&, auto&&, auto&&... args) {
53 createFace(std::forward<decltype(args)>(args)...);
54 });
55 registerCommandHandler<ndn::nfd::FaceUpdateCommand>([this] (auto&&, auto&&... args) {
56 updateFace(std::forward<decltype(args)>(args)...);
57 });
58 registerCommandHandler<ndn::nfd::FaceDestroyCommand>([this] (auto&&, auto&&, auto&&... args) {
59 destroyFace(std::forward<decltype(args)>(args)...);
60 });
61
62 // register handlers for StatusDataset
64 [this] (auto&&, auto&&, auto&&... args) { listFaces(std::forward<decltype(args)>(args)...); });
66 [this] (auto&&, auto&&, auto&&... args) { listChannels(std::forward<decltype(args)>(args)...); });
68 [this] (auto&&, auto&&... args) { queryFaces(std::forward<decltype(args)>(args)...); });
69
70 // register notification stream
71 m_postNotification = registerNotificationStream("events");
72 m_faceAddConn = m_faceTable.afterAdd.connect([this] (const Face& face) {
73 connectFaceStateChangeSignal(face);
74 notifyFaceEvent(face, ndn::nfd::FACE_EVENT_CREATED);
75 });
76 m_faceRemoveConn = m_faceTable.beforeRemove.connect([this] (const Face& face) {
77 notifyFaceEvent(face, ndn::nfd::FACE_EVENT_DESTROYED);
78 });
79}
80
81void
82FaceManager::createFace(const ControlParameters& parameters,
83 const CommandContinuation& done)
84{
85 FaceUri remoteUri;
86 if (!remoteUri.parse(parameters.getUri())) {
87 NFD_LOG_TRACE("failed to parse remote URI: " << parameters.getUri());
88 done(ControlResponse(400, "Malformed command"));
89 return;
90 }
91
92 if (!remoteUri.isCanonical()) {
93 NFD_LOG_TRACE("received non-canonical remote URI: " << remoteUri.toString());
94 done(ControlResponse(400, "Non-canonical remote URI"));
95 return;
96 }
97
98 std::optional<FaceUri> localUri;
99 if (parameters.hasLocalUri()) {
100 localUri = FaceUri{};
101
102 if (!localUri->parse(parameters.getLocalUri())) {
103 NFD_LOG_TRACE("failed to parse local URI: " << parameters.getLocalUri());
104 done(ControlResponse(400, "Malformed command"));
105 return;
106 }
107
108 if (!localUri->isCanonical()) {
109 NFD_LOG_TRACE("received non-canonical local URI: " << localUri->toString());
110 done(ControlResponse(400, "Non-canonical local URI"));
111 return;
112 }
113 }
114
115 face::ProtocolFactory* factory = m_faceSystem.getFactoryByScheme(remoteUri.getScheme());
116 if (factory == nullptr) {
117 NFD_LOG_TRACE("received create request for unsupported protocol: " << remoteUri.getScheme());
118 done(ControlResponse(406, "Unsupported protocol"));
119 return;
120 }
121
122 face::FaceParams faceParams;
123 faceParams.persistency = parameters.getFacePersistency();
124 if (parameters.hasBaseCongestionMarkingInterval()) {
125 faceParams.baseCongestionMarkingInterval = parameters.getBaseCongestionMarkingInterval();
126 }
127 if (parameters.hasDefaultCongestionThreshold()) {
128 faceParams.defaultCongestionThreshold = parameters.getDefaultCongestionThreshold();
129 }
130 if (parameters.hasMtu()) {
131 // The face system limits MTUs to ssize_t, but the management protocol uses uint64_t
132 faceParams.mtu = std::min<uint64_t>(std::numeric_limits<ssize_t>::max(), parameters.getMtu());
133 }
134 faceParams.wantLocalFields = parameters.hasFlagBit(ndn::nfd::BIT_LOCAL_FIELDS_ENABLED) &&
135 parameters.getFlagBit(ndn::nfd::BIT_LOCAL_FIELDS_ENABLED);
136 faceParams.wantLpReliability = parameters.hasFlagBit(ndn::nfd::BIT_LP_RELIABILITY_ENABLED) &&
137 parameters.getFlagBit(ndn::nfd::BIT_LP_RELIABILITY_ENABLED);
138 if (parameters.hasFlagBit(ndn::nfd::BIT_CONGESTION_MARKING_ENABLED)) {
139 faceParams.wantCongestionMarking = parameters.getFlagBit(ndn::nfd::BIT_CONGESTION_MARKING_ENABLED);
140 }
141 try {
142 factory->createFace({remoteUri, localUri, faceParams},
143 [this, parameters, done] (const auto& face) {
144 this->afterCreateFaceSuccess(face, parameters, done);
145 },
146 [done] (uint32_t status, const std::string& reason) {
147 NFD_LOG_DEBUG("Face creation failed: " << reason);
148 done(ControlResponse(status, reason));
149 });
150 }
151 catch (const std::runtime_error& error) {
152 NFD_LOG_ERROR("Face creation failed: " << error.what());
153 done(ControlResponse(500, "Face creation failed due to internal error"));
154 return;
155 }
156 catch (const std::logic_error& error) {
157 NFD_LOG_ERROR("Face creation failed: " << error.what());
158 done(ControlResponse(500, "Face creation failed due to internal error"));
159 return;
160 }
161}
162
163template<typename T>
164static void
165copyMtu(const Face& face, T& to)
166{
167 if (face.getMtu() >= 0) {
168 to.setMtu(std::min<size_t>(face.getMtu(), ndn::MAX_NDN_PACKET_SIZE));
169 }
170 else if (face.getMtu() == face::MTU_UNLIMITED) {
171 to.setMtu(ndn::MAX_NDN_PACKET_SIZE);
172 }
173}
174
175static ControlParameters
177{
178 ControlParameters params;
179 params.setFaceId(face.getId())
180 .setFacePersistency(face.getPersistency());
181 copyMtu(face, params);
182
183 auto linkService = dynamic_cast<face::GenericLinkService*>(face.getLinkService());
184 if (linkService != nullptr) {
185 const auto& options = linkService->getOptions();
186 params.setBaseCongestionMarkingInterval(options.baseCongestionMarkingInterval)
187 .setDefaultCongestionThreshold(options.defaultCongestionThreshold)
188 .setFlagBit(ndn::nfd::BIT_LOCAL_FIELDS_ENABLED, options.allowLocalFields, false)
189 .setFlagBit(ndn::nfd::BIT_LP_RELIABILITY_ENABLED, options.reliabilityOptions.isEnabled, false)
190 .setFlagBit(ndn::nfd::BIT_CONGESTION_MARKING_ENABLED, options.allowCongestionMarking, false);
191 }
192
193 return params;
194}
195
196static ControlParameters
198{
199 ControlParameters params = makeUpdateFaceResponse(face);
200 params.setUri(face.getRemoteUri().toString())
201 .setLocalUri(face.getLocalUri().toString());
202
203 return params;
204}
205
206void
207FaceManager::afterCreateFaceSuccess(const shared_ptr<Face>& face,
208 const ControlParameters& parameters,
209 const CommandContinuation& done)
210{
211 if (face->getId() != face::INVALID_FACEID) { // Face already exists
212 NFD_LOG_TRACE("Attempted to create duplicate face of " << face->getId());
213 ControlParameters response = makeCreateFaceResponse(*face);
214 done(ControlResponse(409, "Face with remote URI already exists").setBody(response.wireEncode()));
215 return;
216 }
217
218 // If scope non-local and flags set to enable local fields, request shouldn't
219 // have made it this far
220 BOOST_ASSERT(face->getScope() == ndn::nfd::FACE_SCOPE_LOCAL ||
221 !parameters.hasFlagBit(ndn::nfd::BIT_LOCAL_FIELDS_ENABLED) ||
222 (parameters.hasFlagBit(ndn::nfd::BIT_LOCAL_FIELDS_ENABLED) &&
223 !parameters.getFlagBit(ndn::nfd::BIT_LOCAL_FIELDS_ENABLED)));
224
225 m_faceTable.add(face);
226
227 ControlParameters response = makeCreateFaceResponse(*face);
228 done(ControlResponse(200, "OK").setBody(response.wireEncode()));
229}
230
231static void
232updateLinkServiceOptions(Face& face, const ControlParameters& parameters)
233{
234 auto linkService = dynamic_cast<face::GenericLinkService*>(face.getLinkService());
235 if (linkService == nullptr) {
236 return;
237 }
238 auto options = linkService->getOptions();
239
240 if (parameters.hasFlagBit(ndn::nfd::BIT_LOCAL_FIELDS_ENABLED) &&
241 face.getScope() == ndn::nfd::FACE_SCOPE_LOCAL) {
242 options.allowLocalFields = parameters.getFlagBit(ndn::nfd::BIT_LOCAL_FIELDS_ENABLED);
243 }
244 if (parameters.hasFlagBit(ndn::nfd::BIT_LP_RELIABILITY_ENABLED)) {
245 options.reliabilityOptions.isEnabled = parameters.getFlagBit(ndn::nfd::BIT_LP_RELIABILITY_ENABLED);
246 }
247 if (parameters.hasFlagBit(ndn::nfd::BIT_CONGESTION_MARKING_ENABLED)) {
248 options.allowCongestionMarking = parameters.getFlagBit(ndn::nfd::BIT_CONGESTION_MARKING_ENABLED);
249 }
250 if (parameters.hasBaseCongestionMarkingInterval()) {
251 options.baseCongestionMarkingInterval = parameters.getBaseCongestionMarkingInterval();
252 }
253 if (parameters.hasDefaultCongestionThreshold()) {
254 options.defaultCongestionThreshold = parameters.getDefaultCongestionThreshold();
255 }
256
257 if (parameters.hasMtu()) {
258 // The face system limits MTUs to ssize_t, but the management protocol uses uint64_t
259 options.overrideMtu = std::min<uint64_t>(std::numeric_limits<ssize_t>::max(), parameters.getMtu());
260 }
261
262 linkService->setOptions(options);
263}
264
265void
266FaceManager::updateFace(const Interest& interest,
267 const ControlParameters& parameters,
268 const CommandContinuation& done)
269{
270 FaceId faceId = parameters.getFaceId();
271 if (faceId == face::INVALID_FACEID) { // Self-update
272 auto incomingFaceIdTag = interest.getTag<lp::IncomingFaceIdTag>();
273 if (incomingFaceIdTag == nullptr) {
274 NFD_LOG_TRACE("unable to determine face for self-update");
275 done(ControlResponse(404, "No FaceId specified and IncomingFaceId not available"));
276 return;
277 }
278 faceId = *incomingFaceIdTag;
279 }
280
281 Face* face = m_faceTable.get(faceId);
282 if (face == nullptr) {
283 NFD_LOG_TRACE("invalid face specified");
284 done(ControlResponse(404, "Specified face does not exist"));
285 return;
286 }
287
288 // Verify validity of requested changes
289 ControlParameters response;
290 bool areParamsValid = true;
291
292 if (parameters.hasFlagBit(ndn::nfd::BIT_LOCAL_FIELDS_ENABLED) &&
293 parameters.getFlagBit(ndn::nfd::BIT_LOCAL_FIELDS_ENABLED) &&
294 face->getScope() != ndn::nfd::FACE_SCOPE_LOCAL) {
295 NFD_LOG_TRACE("received request to enable local fields on non-local face");
296 areParamsValid = false;
297 response.setFlagBit(ndn::nfd::BIT_LOCAL_FIELDS_ENABLED,
298 parameters.getFlagBit(ndn::nfd::BIT_LOCAL_FIELDS_ENABLED));
299 }
300
301 // check whether the requested FacePersistency change is valid if it's present
302 if (parameters.hasFacePersistency()) {
303 auto persistency = parameters.getFacePersistency();
304 if (!face->getTransport()->canChangePersistencyTo(persistency)) {
305 NFD_LOG_TRACE("cannot change face persistency to " << persistency);
306 areParamsValid = false;
307 response.setFacePersistency(persistency);
308 }
309 }
310
311 // check whether the requested MTU override is valid (if it's present)
312 if (parameters.hasMtu()) {
313 auto mtu = parameters.getMtu();
314 // The face system limits MTUs to ssize_t, but the management protocol uses uint64_t
315 auto actualMtu = std::min<uint64_t>(std::numeric_limits<ssize_t>::max(), mtu);
316 auto linkService = dynamic_cast<face::GenericLinkService*>(face->getLinkService());
317 if (linkService == nullptr || !linkService->canOverrideMtuTo(actualMtu)) {
318 NFD_LOG_TRACE("cannot override face MTU to " << mtu);
319 areParamsValid = false;
320 response.setMtu(mtu);
321 }
322 }
323
324 if (!areParamsValid) {
325 done(ControlResponse(409, "Invalid properties specified").setBody(response.wireEncode()));
326 return;
327 }
328
329 // All specified properties are valid, so make changes
330 if (parameters.hasFacePersistency()) {
331 face->setPersistency(parameters.getFacePersistency());
332 }
333 updateLinkServiceOptions(*face, parameters);
334
335 // Prepare and send ControlResponse
336 response = makeUpdateFaceResponse(*face);
337 done(ControlResponse(200, "OK").setBody(response.wireEncode()));
338}
339
340void
341FaceManager::destroyFace(const ControlParameters& parameters,
342 const CommandContinuation& done)
343{
344 Face* face = m_faceTable.get(parameters.getFaceId());
345 if (face != nullptr) {
346 face->close();
347 }
348
349 done(ControlResponse(200, "OK").setBody(parameters.wireEncode()));
350}
351
352template<typename T>
353static void
354copyFaceProperties(const Face& face, T& to)
355{
356 to.setFaceId(face.getId())
357 .setRemoteUri(face.getRemoteUri().toString())
358 .setLocalUri(face.getLocalUri().toString())
359 .setFaceScope(face.getScope())
360 .setFacePersistency(face.getPersistency())
361 .setLinkType(face.getLinkType());
362
363 auto linkService = dynamic_cast<face::GenericLinkService*>(face.getLinkService());
364 if (linkService != nullptr) {
365 const auto& options = linkService->getOptions();
366 to.setFlagBit(ndn::nfd::BIT_LOCAL_FIELDS_ENABLED, options.allowLocalFields)
367 .setFlagBit(ndn::nfd::BIT_LP_RELIABILITY_ENABLED, options.reliabilityOptions.isEnabled)
368 .setFlagBit(ndn::nfd::BIT_CONGESTION_MARKING_ENABLED, options.allowCongestionMarking);
369 }
370}
371
372static ndn::nfd::FaceStatus
373makeFaceStatus(const Face& face, const time::steady_clock::time_point& now)
374{
375 ndn::nfd::FaceStatus status;
376 copyFaceProperties(face, status);
377
378 auto expirationTime = face.getExpirationTime();
379 if (expirationTime != time::steady_clock::time_point::max()) {
380 status.setExpirationPeriod(std::max(0_ms,
381 time::duration_cast<time::milliseconds>(expirationTime - now)));
382 }
383
384 auto linkService = dynamic_cast<face::GenericLinkService*>(face.getLinkService());
385 if (linkService != nullptr) {
386 const auto& options = linkService->getOptions();
387 status.setBaseCongestionMarkingInterval(options.baseCongestionMarkingInterval)
388 .setDefaultCongestionThreshold(options.defaultCongestionThreshold);
389 }
390
391 copyMtu(face, status);
392
393 const auto& counters = face.getCounters();
394 status.setNInInterests(counters.nInInterests)
395 .setNOutInterests(counters.nOutInterests)
396 .setNInData(counters.nInData)
397 .setNOutData(counters.nOutData)
398 .setNInNacks(counters.nInNacks)
399 .setNOutNacks(counters.nOutNacks)
400 .setNInBytes(counters.nInBytes)
401 .setNOutBytes(counters.nOutBytes);
402
403 return status;
404}
405
406void
407FaceManager::listFaces(ndn::mgmt::StatusDatasetContext& context)
408{
409 auto now = time::steady_clock::now();
410 for (const auto& face : m_faceTable) {
411 ndn::nfd::FaceStatus status = makeFaceStatus(face, now);
412 context.append(status.wireEncode());
413 }
414 context.end();
415}
416
417void
418FaceManager::listChannels(ndn::mgmt::StatusDatasetContext& context)
419{
420 auto factories = m_faceSystem.listProtocolFactories();
421 for (const auto* factory : factories) {
422 for (const auto& channel : factory->getChannels()) {
423 ndn::nfd::ChannelStatus entry;
424 entry.setLocalUri(channel->getUri().toString());
425 context.append(entry.wireEncode());
426 }
427 }
428 context.end();
429}
430
431static bool
432matchFilter(const ndn::nfd::FaceQueryFilter& filter, const Face& face)
433{
434 if (filter.hasFaceId() &&
435 filter.getFaceId() != static_cast<uint64_t>(face.getId())) {
436 return false;
437 }
438
439 if (filter.hasUriScheme() &&
440 filter.getUriScheme() != face.getRemoteUri().getScheme() &&
441 filter.getUriScheme() != face.getLocalUri().getScheme()) {
442 return false;
443 }
444
445 if (filter.hasRemoteUri() &&
446 filter.getRemoteUri() != face.getRemoteUri().toString()) {
447 return false;
448 }
449
450 if (filter.hasLocalUri() &&
451 filter.getLocalUri() != face.getLocalUri().toString()) {
452 return false;
453 }
454
455 if (filter.hasFaceScope() &&
456 filter.getFaceScope() != face.getScope()) {
457 return false;
458 }
459
460 if (filter.hasFacePersistency() &&
461 filter.getFacePersistency() != face.getPersistency()) {
462 return false;
463 }
464
465 if (filter.hasLinkType() &&
466 filter.getLinkType() != face.getLinkType()) {
467 return false;
468 }
469
470 return true;
471}
472
473void
474FaceManager::queryFaces(const Interest& interest,
475 ndn::mgmt::StatusDatasetContext& context)
476{
477 ndn::nfd::FaceQueryFilter faceFilter;
478 try {
479 faceFilter.wireDecode(interest.getName()[-1].blockFromValue());
480 }
481 catch (const tlv::Error& e) {
482 NFD_LOG_DEBUG("Malformed query filter: " << e.what());
483 return context.reject(ControlResponse(400, "Malformed filter"));
484 }
485
486 auto now = time::steady_clock::now();
487 for (const auto& face : m_faceTable) {
488 if (matchFilter(faceFilter, face)) {
489 ndn::nfd::FaceStatus status = makeFaceStatus(face, now);
490 context.append(status.wireEncode());
491 }
492 }
493 context.end();
494}
495
496void
497FaceManager::notifyFaceEvent(const Face& face, ndn::nfd::FaceEventKind kind)
498{
499 ndn::nfd::FaceEventNotification notification;
500 notification.setKind(kind);
501 copyFaceProperties(face, notification);
502
503 m_postNotification(notification.wireEncode());
504}
505
506void
507FaceManager::connectFaceStateChangeSignal(const Face& face)
508{
509 using face::FaceState;
510
511 FaceId faceId = face.getId();
512 m_faceStateChangeConn[faceId] = face.afterStateChange.connect(
513 [this, faceId, &face] (FaceState oldState, FaceState newState) {
514 if (newState == FaceState::UP) {
515 notifyFaceEvent(face, ndn::nfd::FACE_EVENT_UP);
516 }
517 else if (newState == FaceState::DOWN) {
518 notifyFaceEvent(face, ndn::nfd::FACE_EVENT_DOWN);
519 }
520 else if (newState == FaceState::CLOSED) {
521 // cannot use face.getId() because it may already be reset to INVALID_FACEID
522 m_faceStateChangeConn.erase(faceId);
523 }
524 });
525}
526
527} // namespace nfd
Provides ControlCommand authorization according to NFD's configuration file.
FaceManager(FaceSystem &faceSystem, Dispatcher &dispatcher, CommandAuthenticator &authenticator)
signal::Signal< FaceTable, Face > beforeRemove
Fires immediately before a face is removed.
signal::Signal< FaceTable, Face > afterAdd
Fires immediately after a face is added.
Face * get(FaceId id) const noexcept
Get face by FaceId.
void add(shared_ptr< Face > face)
Add a face.
A collection of common functions shared by all NFD managers, such as communicating with the dispatche...
ndn::mgmt::PostNotification registerNotificationStream(const std::string &verb)
void registerStatusDatasetHandler(const std::string &verb, const ndn::mgmt::StatusDatasetHandler &handler)
Generalization of a network interface.
Definition face.hpp:118
const FaceCounters & getCounters() const noexcept
Definition face.hpp:298
ndn::nfd::FaceScope getScope() const noexcept
Returns whether the face is local or non-local for scope control purposes.
Definition face.hpp:232
FaceUri getLocalUri() const noexcept
Returns a FaceUri representing the local endpoint.
Definition face.hpp:214
ndn::nfd::LinkType getLinkType() const noexcept
Returns the link type of the face (point-to-point, multi-access, ...).
Definition face.hpp:259
FaceUri getRemoteUri() const noexcept
Returns a FaceUri representing the remote endpoint.
Definition face.hpp:223
ssize_t getMtu() const
Returns the effective MTU of the face.
Definition face.hpp:270
FaceId getId() const noexcept
Returns the face ID.
Definition face.hpp:195
void close()
Request that the face be closed.
Definition face.hpp:145
ndn::nfd::FacePersistency getPersistency() const noexcept
Returns the current persistency setting of the face.
Definition face.hpp:241
LinkService * getLinkService() const noexcept
Definition face.hpp:123
time::steady_clock::time_point getExpirationTime() const noexcept
Returns the expiration time of the face.
Definition face.hpp:292
Entry point of NFD's face system.
std::set< const ProtocolFactory * > listProtocolFactories() const
Returns all ProtocolFactory objects owned by the face system.
ProtocolFactory * getFactoryByScheme(const std::string &scheme) const
#define NFD_LOG_ERROR
Definition logger.hpp:41
#define NFD_LOG_INIT(name)
Definition logger.hpp:31
#define NFD_LOG_DEBUG
Definition logger.hpp:38
#define NFD_LOG_TRACE
Definition logger.hpp:37
TransportState FaceState
Indicates the state of a face.
Definition face.hpp:41
constexpr FaceId INVALID_FACEID
Indicates an invalid FaceId.
constexpr ssize_t MTU_UNLIMITED
Indicates that the transport has no limit on payload size.
uint64_t FaceId
Identifies a face.
-status-http-server
Definition common.hpp:71
static void copyFaceProperties(const Face &face, T &to)
static ControlParameters makeUpdateFaceResponse(const Face &face)
static void updateLinkServiceOptions(Face &face, const ControlParameters &parameters)
static bool matchFilter(const ndn::nfd::FaceQueryFilter &filter, const Face &face)
static ControlParameters makeCreateFaceResponse(const Face &face)
static void copyMtu(const Face &face, T &to)
static ndn::nfd::FaceStatus makeFaceStatus(const Face &face, const time::steady_clock::time_point &now)