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>
48 , m_faceSystem(faceSystem)
49 , m_faceTable(faceSystem.getFaceTable())
52 registerCommandHandler<ndn::nfd::FaceCreateCommand>(
"create",
53 [
this] (
auto&&,
auto&&,
auto&&,
auto&&... args) { createFace(std::forward<decltype(args)>(args)...); });
54 registerCommandHandler<ndn::nfd::FaceUpdateCommand>(
"update",
55 [
this] (
auto&&,
auto&&,
auto&&... args) { updateFace(std::forward<decltype(args)>(args)...); });
56 registerCommandHandler<ndn::nfd::FaceDestroyCommand>(
"destroy",
57 [
this] (
auto&&,
auto&&,
auto&&,
auto&&... args) { destroyFace(std::forward<decltype(args)>(args)...); });
61 [
this] (
auto&&,
auto&&,
auto&&... args) { listFaces(std::forward<decltype(args)>(args)...); });
63 [
this] (
auto&&,
auto&&,
auto&&... args) { listChannels(std::forward<decltype(args)>(args)...); });
65 [
this] (
auto&&,
auto&&... args) { queryFaces(std::forward<decltype(args)>(args)...); });
69 m_faceAddConn = m_faceTable.
afterAdd.connect([
this] (
const Face& face) {
70 connectFaceStateChangeSignal(face);
71 notifyFaceEvent(face, ndn::nfd::FACE_EVENT_CREATED);
73 m_faceRemoveConn = m_faceTable.
beforeRemove.connect([
this] (
const Face& face) {
74 notifyFaceEvent(face, ndn::nfd::FACE_EVENT_DESTROYED);
79 FaceManager::createFace(
const ControlParameters& parameters,
80 const ndn::mgmt::CommandContinuation& done)
83 if (!remoteUri.parse(parameters.getUri())) {
84 NFD_LOG_TRACE(
"failed to parse remote URI: " << parameters.getUri());
85 done(ControlResponse(400,
"Malformed command"));
89 if (!remoteUri.isCanonical()) {
90 NFD_LOG_TRACE(
"received non-canonical remote URI: " << remoteUri.toString());
91 done(ControlResponse(400,
"Non-canonical remote URI"));
95 std::optional<FaceUri> localUri;
96 if (parameters.hasLocalUri()) {
99 if (!localUri->parse(parameters.getLocalUri())) {
100 NFD_LOG_TRACE(
"failed to parse local URI: " << parameters.getLocalUri());
101 done(ControlResponse(400,
"Malformed command"));
105 if (!localUri->isCanonical()) {
106 NFD_LOG_TRACE(
"received non-canonical local URI: " << localUri->toString());
107 done(ControlResponse(400,
"Non-canonical local URI"));
112 face::ProtocolFactory* factory = m_faceSystem.
getFactoryByScheme(remoteUri.getScheme());
113 if (factory ==
nullptr) {
114 NFD_LOG_TRACE(
"received create request for unsupported protocol: " << remoteUri.getScheme());
115 done(ControlResponse(406,
"Unsupported protocol"));
119 face::FaceParams faceParams;
120 faceParams.persistency = parameters.getFacePersistency();
121 if (parameters.hasBaseCongestionMarkingInterval()) {
122 faceParams.baseCongestionMarkingInterval = parameters.getBaseCongestionMarkingInterval();
124 if (parameters.hasDefaultCongestionThreshold()) {
125 faceParams.defaultCongestionThreshold = parameters.getDefaultCongestionThreshold();
127 if (parameters.hasMtu()) {
129 faceParams.mtu = std::min<uint64_t>(std::numeric_limits<ssize_t>::max(), parameters.getMtu());
131 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);
135 if (parameters.hasFlagBit(ndn::nfd::BIT_CONGESTION_MARKING_ENABLED)) {
136 faceParams.wantCongestionMarking = parameters.getFlagBit(ndn::nfd::BIT_CONGESTION_MARKING_ENABLED);
139 factory->createFace({remoteUri, localUri, faceParams},
140 [
this, parameters, done] (
const auto& face) {
141 this->afterCreateFaceSuccess(face, parameters, done);
143 [done] (uint32_t status,
const std::string& reason) {
145 done(ControlResponse(status, reason));
148 catch (
const std::runtime_error& error) {
150 done(ControlResponse(500,
"Face creation failed due to internal error"));
153 catch (
const std::logic_error& error) {
155 done(ControlResponse(500,
"Face creation failed due to internal error"));
165 to.setMtu(std::min<size_t>(face.
getMtu(), ndn::MAX_NDN_PACKET_SIZE));
168 to.setMtu(ndn::MAX_NDN_PACKET_SIZE);
172 static ControlParameters
175 ControlParameters params;
176 params.setFaceId(face.
getId())
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);
193 static ControlParameters
204 FaceManager::afterCreateFaceSuccess(
const shared_ptr<Face>& face,
205 const ControlParameters& parameters,
206 const ndn::mgmt::CommandContinuation& done)
209 NFD_LOG_TRACE(
"Attempted to create duplicate face of " << face->getId());
211 done(ControlResponse(409,
"Face with remote URI already exists").setBody(response.wireEncode()));
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)));
222 m_faceTable.
add(face);
225 done(ControlResponse(200,
"OK").setBody(response.wireEncode()));
232 if (linkService ==
nullptr) {
237 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);
241 if (parameters.hasFlagBit(ndn::nfd::BIT_LP_RELIABILITY_ENABLED)) {
242 options.reliabilityOptions.isEnabled = parameters.getFlagBit(ndn::nfd::BIT_LP_RELIABILITY_ENABLED);
244 if (parameters.hasFlagBit(ndn::nfd::BIT_CONGESTION_MARKING_ENABLED)) {
245 options.allowCongestionMarking = parameters.getFlagBit(ndn::nfd::BIT_CONGESTION_MARKING_ENABLED);
247 if (parameters.hasBaseCongestionMarkingInterval()) {
248 options.baseCongestionMarkingInterval = parameters.getBaseCongestionMarkingInterval();
250 if (parameters.hasDefaultCongestionThreshold()) {
251 options.defaultCongestionThreshold = parameters.getDefaultCongestionThreshold();
254 if (parameters.hasMtu()) {
256 options.overrideMtu = std::min<uint64_t>(std::numeric_limits<ssize_t>::max(), parameters.getMtu());
259 linkService->setOptions(options);
263 FaceManager::updateFace(
const Interest& interest,
264 const ControlParameters& parameters,
265 const ndn::mgmt::CommandContinuation& done)
267 FaceId faceId = parameters.getFaceId();
269 auto incomingFaceIdTag = interest.getTag<lp::IncomingFaceIdTag>();
270 if (incomingFaceIdTag ==
nullptr) {
272 done(ControlResponse(404,
"No FaceId specified and IncomingFaceId not available"));
275 faceId = *incomingFaceIdTag;
278 Face* face = m_faceTable.
get(faceId);
279 if (face ==
nullptr) {
281 done(ControlResponse(404,
"Specified face does not exist"));
286 ControlParameters response;
287 bool areParamsValid =
true;
289 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));
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);
309 if (parameters.hasMtu()) {
310 auto mtu = parameters.getMtu();
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)) {
316 areParamsValid =
false;
317 response.setMtu(mtu);
321 if (!areParamsValid) {
322 done(ControlResponse(409,
"Invalid properties specified").setBody(response.wireEncode()));
327 if (parameters.hasFacePersistency()) {
328 face->setPersistency(parameters.getFacePersistency());
334 done(ControlResponse(200,
"OK").setBody(response.wireEncode()));
338 FaceManager::destroyFace(
const ControlParameters& parameters,
339 const ndn::mgmt::CommandContinuation& done)
341 Face* face = m_faceTable.
get(parameters.getFaceId());
342 if (face !=
nullptr) {
346 done(ControlResponse(200,
"OK").setBody(parameters.wireEncode()));
353 to.setFaceId(face.
getId())
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);
369 static ndn::nfd::FaceStatus
372 ndn::nfd::FaceStatus status;
376 if (expirationTime != time::steady_clock::time_point::max()) {
377 status.setExpirationPeriod(std::max(0_ms,
378 time::duration_cast<time::milliseconds>(expirationTime - now)));
382 if (linkService !=
nullptr) {
383 const auto& options = linkService->
getOptions();
384 status.setBaseCongestionMarkingInterval(options.baseCongestionMarkingInterval)
385 .setDefaultCongestionThreshold(options.defaultCongestionThreshold);
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);
404 FaceManager::listFaces(ndn::mgmt::StatusDatasetContext& context)
406 auto now = time::steady_clock::now();
407 for (
const auto& face : m_faceTable) {
409 context.append(status.wireEncode());
415 FaceManager::listChannels(ndn::mgmt::StatusDatasetContext& context)
418 for (
const auto* factory : factories) {
419 for (
const auto& channel : factory->getChannels()) {
420 ndn::nfd::ChannelStatus entry;
421 entry.setLocalUri(channel->getUri().toString());
422 context.append(entry.wireEncode());
431 if (filter.hasFaceId() &&
432 filter.getFaceId() !=
static_cast<uint64_t
>(face.
getId())) {
436 if (filter.hasUriScheme() &&
437 filter.getUriScheme() != face.
getRemoteUri().getScheme() &&
438 filter.getUriScheme() != face.
getLocalUri().getScheme()) {
442 if (filter.hasRemoteUri() &&
443 filter.getRemoteUri() != face.
getRemoteUri().toString()) {
447 if (filter.hasLocalUri() &&
448 filter.getLocalUri() != face.
getLocalUri().toString()) {
452 if (filter.hasFaceScope() &&
453 filter.getFaceScope() != face.
getScope()) {
457 if (filter.hasFacePersistency() &&
462 if (filter.hasLinkType() &&
471 FaceManager::queryFaces(
const Interest& interest,
472 ndn::mgmt::StatusDatasetContext& context)
474 ndn::nfd::FaceQueryFilter faceFilter;
476 faceFilter.wireDecode(interest.getName()[-1].blockFromValue());
478 catch (
const tlv::Error& e) {
480 return context.reject(ControlResponse(400,
"Malformed filter"));
483 auto now = time::steady_clock::now();
484 for (
const auto& face : m_faceTable) {
487 context.append(status.wireEncode());
494 FaceManager::notifyFaceEvent(
const Face& face, ndn::nfd::FaceEventKind kind)
496 ndn::nfd::FaceEventNotification notification;
497 notification.setKind(kind);
500 m_postNotification(notification.wireEncode());
504 FaceManager::connectFaceStateChangeSignal(
const Face& face)
508 FaceId faceId = face.getId();
509 m_faceStateChangeConn[faceId] = face.afterStateChange.connect(
511 if (newState == FaceState::UP) {
512 notifyFaceEvent(face, ndn::nfd::FACE_EVENT_UP);
514 else if (newState == FaceState::DOWN) {
515 notifyFaceEvent(face, ndn::nfd::FACE_EVENT_DOWN);
517 else if (newState == FaceState::CLOSED) {
519 m_faceStateChangeConn.erase(faceId);
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.
ndn::nfd::FaceScope getScope() const noexcept
Returns whether the face is local or non-local for scope control purposes.
FaceUri getLocalUri() const noexcept
Returns a FaceUri representing the local endpoint.
ndn::nfd::LinkType getLinkType() const noexcept
Returns the link type of the face (point-to-point, multi-access, ...).
FaceUri getRemoteUri() const noexcept
Returns a FaceUri representing the remote endpoint.
ssize_t getMtu() const
Returns the effective MTU of the face.
LinkService * getLinkService() const noexcept
FaceId getId() const noexcept
Returns the face ID.
void close()
Request that the face be closed.
const FaceCounters & getCounters() const noexcept
ndn::nfd::FacePersistency getPersistency() const noexcept
Returns the current persistency setting of the face.
time::steady_clock::time_point getExpirationTime() const noexcept
Returns the expiration time of the face.
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
GenericLinkService is a LinkService that implements the NDNLPv2 protocol.
const Options & getOptions() const
Get the options used by GenericLinkService.
#define NFD_LOG_INIT(name)
TransportState FaceState
Indicates the state of a face.
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.
static void copyFaceProperties(const Face &face, T &to)
static ControlParameters makeUpdateFaceResponse(const Face &face)
static void updateLinkServiceOptions(Face &face, const ControlParameters ¶meters)
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)
bool allowLocalFields
Enables encoding of IncomingFaceId, and decoding of NextHopFaceId and CachePolicy.