mgmt+face: allow MTU of datagram faces to be overridden
refs #4005
Change-Id: I01d98b88cdee41b633f6fb9a5600088efe8de749
diff --git a/daemon/face/channel.hpp b/daemon/face/channel.hpp
index db97cc8..6d2c221 100644
--- a/daemon/face/channel.hpp
+++ b/daemon/face/channel.hpp
@@ -89,6 +89,7 @@
ndn::nfd::FacePersistency persistency = ndn::nfd::FACE_PERSISTENCY_PERSISTENT;
optional<time::nanoseconds> baseCongestionMarkingInterval;
optional<uint64_t> defaultCongestionThreshold;
+ optional<ssize_t> mtu;
bool wantLocalFields = false;
bool wantLpReliability = false;
boost::logic::tribool wantCongestionMarking = boost::logic::indeterminate;
diff --git a/daemon/face/ethernet-channel.cpp b/daemon/face/ethernet-channel.cpp
index 69c6f45..691b40b 100644
--- a/daemon/face/ethernet-channel.cpp
+++ b/daemon/face/ethernet-channel.cpp
@@ -203,7 +203,8 @@
auto linkService = make_unique<GenericLinkService>(options);
auto transport = make_unique<UnicastEthernetTransport>(*m_localEndpoint, remoteEndpoint,
- params.persistency, m_idleFaceTimeout);
+ params.persistency, m_idleFaceTimeout,
+ params.mtu);
auto face = make_shared<Face>(std::move(linkService), std::move(transport));
m_channelFaces[remoteEndpoint] = face;
diff --git a/daemon/face/ethernet-factory.cpp b/daemon/face/ethernet-factory.cpp
index f9767df..aab8aa4 100644
--- a/daemon/face/ethernet-factory.cpp
+++ b/daemon/face/ethernet-factory.cpp
@@ -200,6 +200,13 @@
return;
}
+ if (req.params.mtu && *req.params.mtu < Transport::MIN_MTU) {
+ // The specified MTU must be greater than the minimum possible
+ NFD_LOG_TRACE("createFace cannot create a face with an MTU less than " << Transport::MIN_MTU);
+ onFailure(406, "MTU cannot be less than " + to_string(Transport::MIN_MTU));
+ return;
+ }
+
for (const auto& i : m_channels) {
if (i.first == localEndpoint) {
i.second->connect(remoteEndpoint, req.params, onCreated, onFailure);
diff --git a/daemon/face/tcp-factory.cpp b/daemon/face/tcp-factory.cpp
index 369af43..5b56839 100644
--- a/daemon/face/tcp-factory.cpp
+++ b/daemon/face/tcp-factory.cpp
@@ -179,6 +179,12 @@
return;
}
+ if (req.params.mtu) {
+ NFD_LOG_TRACE("createFace cannot create a TCP face with an overridden MTU");
+ onFailure(406, "TCP faces do not support MTU overrides");
+ return;
+ }
+
// very simple logic for now
for (const auto& i : m_channels) {
if ((i.first.address().is_v4() && endpoint.address().is_v4()) ||
diff --git a/daemon/face/transport.cpp b/daemon/face/transport.cpp
index f615a10..457e162 100644
--- a/daemon/face/transport.cpp
+++ b/daemon/face/transport.cpp
@@ -126,12 +126,6 @@
m_service->receivePacket(std::move(packet));
}
-ssize_t
-Transport::getSendQueueLength()
-{
- return QUEUE_UNSUPPORTED;
-}
-
bool
Transport::canChangePersistencyTo(ndn::nfd::FacePersistency newPersistency) const
{
diff --git a/daemon/face/transport.hpp b/daemon/face/transport.hpp
index a9768e5..a0a97a0 100644
--- a/daemon/face/transport.hpp
+++ b/daemon/face/transport.hpp
@@ -202,13 +202,6 @@
void
send(Packet&& packet);
-protected: // upper interface to be invoked by subclass
- /** \brief receive a link-layer packet
- * \warning undefined behavior if packet size exceeds MTU limit
- */
- void
- receive(Packet&& packet);
-
public: // static properties
/** \return a FaceUri representing local endpoint
*/
@@ -291,7 +284,17 @@
* \retval QUEUE_ERROR transport was unable to retrieve the queue length
*/
virtual ssize_t
- getSendQueueLength();
+ getSendQueueLength()
+ {
+ return QUEUE_UNSUPPORTED;
+ }
+
+protected: // upper interface to be invoked by subclass
+ /** \brief receive a link-layer packet
+ * \warning undefined behavior if packet size exceeds MTU limit
+ */
+ void
+ receive(Packet&& packet);
protected: // properties to be set by subclass
void
@@ -363,6 +366,13 @@
virtual void
doSend(Packet&& packet) = 0;
+public:
+ /** \brief minimum MTU that may be set on a transport
+ *
+ * This is done to ensure the NDNLPv2 fragmentation feature functions properly.
+ */
+ static constexpr ssize_t MIN_MTU = 64;
+
private:
Face* m_face;
LinkService* m_service;
diff --git a/daemon/face/udp-channel.cpp b/daemon/face/udp-channel.cpp
index b87e697..eb4337f 100644
--- a/daemon/face/udp-channel.cpp
+++ b/daemon/face/udp-channel.cpp
@@ -160,6 +160,8 @@
socket.connect(remoteEndpoint);
GenericLinkService::Options options;
+ options.allowFragmentation = true;
+ options.allowReassembly = true;
options.reliabilityOptions.isEnabled = params.wantLpReliability;
if (boost::logic::indeterminate(params.wantCongestionMarking)) {
@@ -178,7 +180,8 @@
}
auto linkService = make_unique<GenericLinkService>(options);
- auto transport = make_unique<UnicastUdpTransport>(std::move(socket), params.persistency, m_idleFaceTimeout);
+ auto transport = make_unique<UnicastUdpTransport>(std::move(socket), params.persistency,
+ m_idleFaceTimeout, params.mtu);
auto face = make_shared<Face>(std::move(linkService), std::move(transport));
m_channelFaces[remoteEndpoint] = face;
diff --git a/daemon/face/udp-factory.cpp b/daemon/face/udp-factory.cpp
index 3660db5..e649871 100644
--- a/daemon/face/udp-factory.cpp
+++ b/daemon/face/udp-factory.cpp
@@ -270,6 +270,13 @@
return;
}
+ if (req.params.mtu && *req.params.mtu < Transport::MIN_MTU) {
+ // The specified MTU must be greater than the minimum possible
+ NFD_LOG_TRACE("createFace cannot create a face with MTU less than " << Transport::MIN_MTU);
+ onFailure(406, "MTU cannot be less than " + to_string(Transport::MIN_MTU));
+ return;
+ }
+
// very simple logic for now
for (const auto& i : m_channels) {
if ((i.first.address().is_v4() && endpoint.address().is_v4()) ||
diff --git a/daemon/face/unicast-ethernet-transport.cpp b/daemon/face/unicast-ethernet-transport.cpp
index e28fa93..60059bb 100644
--- a/daemon/face/unicast-ethernet-transport.cpp
+++ b/daemon/face/unicast-ethernet-transport.cpp
@@ -35,7 +35,8 @@
UnicastEthernetTransport::UnicastEthernetTransport(const ndn::net::NetworkInterface& localEndpoint,
const ethernet::Address& remoteEndpoint,
ndn::nfd::FacePersistency persistency,
- time::nanoseconds idleTimeout)
+ time::nanoseconds idleTimeout,
+ optional<ssize_t> overrideMtu)
: EthernetTransport(localEndpoint, remoteEndpoint)
, m_idleTimeout(idleTimeout)
{
@@ -44,7 +45,13 @@
this->setScope(ndn::nfd::FACE_SCOPE_NON_LOCAL);
this->setPersistency(persistency);
this->setLinkType(ndn::nfd::LINK_TYPE_POINT_TO_POINT);
- this->setMtu(localEndpoint.getMtu());
+
+ if (overrideMtu) {
+ this->setMtu(std::min<ssize_t>(localEndpoint.getMtu(), *overrideMtu));
+ }
+ else {
+ this->setMtu(localEndpoint.getMtu());
+ }
NFD_LOG_FACE_INFO("Creating transport");
diff --git a/daemon/face/unicast-ethernet-transport.hpp b/daemon/face/unicast-ethernet-transport.hpp
index 19617e3..5a148c9 100644
--- a/daemon/face/unicast-ethernet-transport.hpp
+++ b/daemon/face/unicast-ethernet-transport.hpp
@@ -1,6 +1,6 @@
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/*
- * Copyright (c) 2014-2017, Regents of the University of California,
+ * Copyright (c) 2014-2018, Regents of the University of California,
* Arizona Board of Regents,
* Colorado State University,
* University Pierre & Marie Curie, Sorbonne University,
@@ -44,7 +44,8 @@
UnicastEthernetTransport(const ndn::net::NetworkInterface& localEndpoint,
const ethernet::Address& remoteEndpoint,
ndn::nfd::FacePersistency persistency,
- time::nanoseconds idleTimeout);
+ time::nanoseconds idleTimeout,
+ optional<ssize_t> overrideMtu = {});
protected:
bool
diff --git a/daemon/face/unicast-udp-transport.cpp b/daemon/face/unicast-udp-transport.cpp
index 8e3d7d8..062c924 100644
--- a/daemon/face/unicast-udp-transport.cpp
+++ b/daemon/face/unicast-udp-transport.cpp
@@ -40,7 +40,8 @@
UnicastUdpTransport::UnicastUdpTransport(protocol::socket&& socket,
ndn::nfd::FacePersistency persistency,
- time::nanoseconds idleTimeout)
+ time::nanoseconds idleTimeout,
+ optional<ssize_t> overrideMtu)
: DatagramTransport(std::move(socket))
, m_idleTimeout(idleTimeout)
{
@@ -49,7 +50,14 @@
this->setScope(ndn::nfd::FACE_SCOPE_NON_LOCAL);
this->setPersistency(persistency);
this->setLinkType(ndn::nfd::LINK_TYPE_POINT_TO_POINT);
- this->setMtu(udp::computeMtu(m_socket.local_endpoint()));
+
+ if (overrideMtu) {
+ this->setMtu(std::min(udp::computeMtu(m_socket.local_endpoint()), *overrideMtu));
+ }
+ else {
+ this->setMtu(udp::computeMtu(m_socket.local_endpoint()));
+ }
+ BOOST_ASSERT(this->getMtu() >= MIN_MTU);
NFD_LOG_FACE_INFO("Creating transport");
diff --git a/daemon/face/unicast-udp-transport.hpp b/daemon/face/unicast-udp-transport.hpp
index b1eb672..03f1c86 100644
--- a/daemon/face/unicast-udp-transport.hpp
+++ b/daemon/face/unicast-udp-transport.hpp
@@ -42,7 +42,8 @@
public:
UnicastUdpTransport(protocol::socket&& socket,
ndn::nfd::FacePersistency persistency,
- time::nanoseconds idleTimeout);
+ time::nanoseconds idleTimeout,
+ optional<ssize_t> overrideMtu = {});
protected:
bool
diff --git a/daemon/mgmt/face-manager.cpp b/daemon/mgmt/face-manager.cpp
index 1d53eab..b1e934f 100644
--- a/daemon/mgmt/face-manager.cpp
+++ b/daemon/mgmt/face-manager.cpp
@@ -122,6 +122,9 @@
if (parameters.hasDefaultCongestionThreshold()) {
faceParams.defaultCongestionThreshold = parameters.getDefaultCongestionThreshold();
}
+ if (parameters.hasMtu()) {
+ faceParams.mtu = parameters.getMtu();
+ }
faceParams.wantLocalFields = parameters.hasFlagBit(ndn::nfd::BIT_LOCAL_FIELDS_ENABLED) &&
parameters.getFlagBit(ndn::nfd::BIT_LOCAL_FIELDS_ENABLED);
faceParams.wantLpReliability = parameters.hasFlagBit(ndn::nfd::BIT_LP_RELIABILITY_ENABLED) &&
@@ -243,6 +246,7 @@
// Set ControlResponse fields
response = collectFaceProperties(*face, false);
+ response.unsetMtu(); // This parameter is only included with the response to faces/create and FaceStatus
done(ControlResponse(200, "OK").setBody(response.wireEncode()));
}
@@ -294,6 +298,9 @@
BOOST_ASSERT(linkService != nullptr);
auto options = linkService->getOptions();
+ auto transport = face.getTransport();
+ BOOST_ASSERT(transport != nullptr);
+
ControlParameters params;
params.setFaceId(face.getId())
.setFacePersistency(face.getPersistency())
@@ -302,6 +309,14 @@
.setFlagBit(ndn::nfd::BIT_LOCAL_FIELDS_ENABLED, options.allowLocalFields, false)
.setFlagBit(ndn::nfd::BIT_LP_RELIABILITY_ENABLED, options.reliabilityOptions.isEnabled, false)
.setFlagBit(ndn::nfd::BIT_CONGESTION_MARKING_ENABLED, options.allowCongestionMarking, false);
+
+ if (transport->getMtu() > 0) {
+ params.setMtu(std::min<uint64_t>(transport->getMtu(), ndn::MAX_NDN_PACKET_SIZE));
+ }
+ else if (transport->getMtu() == face::MTU_UNLIMITED) {
+ params.setMtu(ndn::MAX_NDN_PACKET_SIZE);
+ }
+
if (wantUris) {
params.setUri(face.getRemoteUri().toString())
.setLocalUri(face.getLocalUri().toString());