face: Transport::getMtu
refs #3253
Change-Id: Ia4c5cfe210a99b798ce7d05f74ebdd7cfab214f4
diff --git a/daemon/face/multicast-udp-transport.cpp b/daemon/face/multicast-udp-transport.cpp
index 7befa78..a1f376b 100644
--- a/daemon/face/multicast-udp-transport.cpp
+++ b/daemon/face/multicast-udp-transport.cpp
@@ -24,6 +24,7 @@
*/
#include "multicast-udp-transport.hpp"
+#include "udp-protocol.hpp"
namespace nfd {
namespace face {
@@ -41,8 +42,10 @@
{
this->setLocalUri(FaceUri(localEndpoint));
this->setRemoteUri(FaceUri(multicastGroup));
+ this->setScope(ndn::nfd::FACE_SCOPE_NON_LOCAL);
this->setPersistency(ndn::nfd::FACE_PERSISTENCY_PERMANENT);
this->setLinkType(ndn::nfd::LINK_TYPE_MULTI_ACCESS);
+ this->setMtu(udp::computeMtu(localEndpoint));
NFD_LOG_FACE_INFO("Creating transport");
}
diff --git a/daemon/face/transport.cpp b/daemon/face/transport.cpp
index fa1159d..d6008f7 100644
--- a/daemon/face/transport.cpp
+++ b/daemon/face/transport.cpp
@@ -53,6 +53,7 @@
Transport::Packet::Packet(Block&& packet1)
: packet(std::move(packet1))
+ , remoteEndpoint(0)
{
}
@@ -62,9 +63,12 @@
, m_scope(ndn::nfd::FACE_SCOPE_NON_LOCAL)
, m_persistency(ndn::nfd::FACE_PERSISTENCY_PERSISTENT)
, m_linkType(ndn::nfd::LINK_TYPE_POINT_TO_POINT)
+ , m_mtu(MTU_UNLIMITED)
, m_state(TransportState::UP)
, m_counters(nullptr)
{
+ // warning: Subclass constructor must explicitly initialize all static properties
+ // using setters, and should not rely on the defaults here.
}
Transport::~Transport()
@@ -96,8 +100,17 @@
}
void
-Transport::send(Transport::Packet&& packet)
+Transport::send(Packet&& packet)
{
+ BOOST_ASSERT(this->getMtu() == MTU_UNLIMITED ||
+ packet.packet.size() <= static_cast<size_t>(this->getMtu()));
+
+ TransportState state = this->getState();
+ if (state != TransportState::UP && state != TransportState::DOWN) {
+ NFD_LOG_FACE_TRACE("send ignored in " << state << " state");
+ return;
+ }
+
// TODO#3177 increment LpPacket counter
m_counters->getNOutBytes() += packet.packet.size();
@@ -105,8 +118,11 @@
}
void
-Transport::receive(Transport::Packet&& packet)
+Transport::receive(Packet&& packet)
{
+ BOOST_ASSERT(this->getMtu() == MTU_UNLIMITED ||
+ packet.packet.size() <= static_cast<size_t>(this->getMtu()));
+
// TODO#3177 increment LpPacket counter
m_counters->getNInBytes() += packet.packet.size();
diff --git a/daemon/face/transport.hpp b/daemon/face/transport.hpp
index 144e0dc..b7f1c30 100644
--- a/daemon/face/transport.hpp
+++ b/daemon/face/transport.hpp
@@ -51,6 +51,10 @@
std::ostream&
operator<<(std::ostream& os, TransportState state);
+/** \brief indicates the transport has no limit on payload size
+ */
+const ssize_t MTU_UNLIMITED = -1;
+
/** \brief the lower part of an LpFace
* \sa LpFace
*/
@@ -125,12 +129,15 @@
close();
/** \brief send a link-layer packet
+ * \note This operation has no effect if \p getState() is neither UP nor DOWN
+ * \warning undefined behavior if packet size exceeds MTU limit
*/
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);
@@ -166,6 +173,18 @@
ndn::nfd::LinkType
getLinkType() const;
+ /** \return maximum payload size
+ * \retval MTU_UNLIMITED transport has no limit on payload size
+ *
+ * This size is the maximum packet size that can be sent or received through this transport.
+ *
+ * For a datagram-based transport, this is typically the Maximum Transmission Unit (MTU),
+ * after the overhead of headers introduced by the transport has been accounted for.
+ * For a stream-based transport, this is typically unlimited (MTU_UNLIMITED).
+ */
+ ssize_t
+ getMtu() const;
+
public: // dynamic properties
/** \return transport state
*/
@@ -189,6 +208,9 @@
void
setLinkType(ndn::nfd::LinkType linkType);
+ void
+ setMtu(ssize_t mtu);
+
/** \brief set transport state
*
* Only the following transitions are valid:
@@ -213,8 +235,11 @@
/** \brief performs Transport specific operations to close the transport
*
+ * This is invoked once by \p close() after changing state to CLOSING.
+ * It will not be invoked by Transport class if the transport is already CLOSING or CLOSED.
+ *
* When the cleanup procedure is complete, this method should change state to CLOSED.
- * This can happen synchronously or asynchronously.
+ * This transition can happen synchronously or asynchronously.
*/
virtual void
doClose() = 0;
@@ -222,6 +247,7 @@
private: // to be overridden by subclass
/** \brief performs Transport specific operations to send a packet
* \param packet the packet, which must be a well-formed TLV block
+ * \pre state is either UP or DOWN
*/
virtual void
doSend(Packet&& packet) = 0;
@@ -234,6 +260,7 @@
ndn::nfd::FaceScope m_scope;
ndn::nfd::FacePersistency m_persistency;
ndn::nfd::LinkType m_linkType;
+ ssize_t m_mtu;
TransportState m_state;
LinkLayerCounters* m_counters; // TODO#3177 change into LinkCounters
};
@@ -262,18 +289,36 @@
return m_localUri;
}
+inline void
+Transport::setLocalUri(const FaceUri& uri)
+{
+ m_localUri = uri;
+}
+
inline FaceUri
Transport::getRemoteUri() const
{
return m_remoteUri;
}
+inline void
+Transport::setRemoteUri(const FaceUri& uri)
+{
+ m_remoteUri = uri;
+}
+
inline ndn::nfd::FaceScope
Transport::getScope() const
{
return m_scope;
}
+inline void
+Transport::setScope(ndn::nfd::FaceScope scope)
+{
+ m_scope = scope;
+}
+
inline ndn::nfd::FacePersistency
Transport::getPersistency() const
{
@@ -293,36 +338,31 @@
return m_linkType;
}
-inline TransportState
-Transport::getState() const
-{
- return m_state;
-}
-
-inline void
-Transport::setLocalUri(const FaceUri& uri)
-{
- m_localUri = uri;
-}
-
-inline void
-Transport::setRemoteUri(const FaceUri& uri)
-{
- m_remoteUri = uri;
-}
-
-inline void
-Transport::setScope(ndn::nfd::FaceScope scope)
-{
- m_scope = scope;
-}
-
inline void
Transport::setLinkType(ndn::nfd::LinkType linkType)
{
m_linkType = linkType;
}
+inline ssize_t
+Transport::getMtu() const
+{
+ return m_mtu;
+}
+
+inline void
+Transport::setMtu(ssize_t mtu)
+{
+ BOOST_ASSERT(mtu == MTU_UNLIMITED || mtu > 0);
+ m_mtu = mtu;
+}
+
+inline TransportState
+Transport::getState() const
+{
+ return m_state;
+}
+
std::ostream&
operator<<(std::ostream& os, const FaceLogHelper<Transport>& flh);
diff --git a/daemon/face/udp-protocol.cpp b/daemon/face/udp-protocol.cpp
new file mode 100644
index 0000000..fb51a3a
--- /dev/null
+++ b/daemon/face/udp-protocol.cpp
@@ -0,0 +1,47 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/**
+ * Copyright (c) 2014-2015, Regents of the University of California,
+ * Arizona Board of Regents,
+ * Colorado State University,
+ * University Pierre & Marie Curie, Sorbonne University,
+ * Washington University in St. Louis,
+ * Beijing Institute of Technology,
+ * The University of Memphis.
+ *
+ * This file is part of NFD (Named Data Networking Forwarding Daemon).
+ * See AUTHORS.md for complete list of NFD authors and contributors.
+ *
+ * NFD is free software: you can redistribute it and/or modify it under the terms
+ * of the GNU General Public License as published by the Free Software Foundation,
+ * either version 3 of the License, or (at your option) any later version.
+ *
+ * NFD is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
+ * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+ * PURPOSE. See the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * NFD, e.g., in COPYING.md file. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "udp-protocol.hpp"
+
+namespace nfd {
+namespace udp {
+
+ssize_t
+computeMtu(const boost::asio::ip::udp::endpoint& localEndpoint)
+{
+ size_t mtu = 0;
+ if (localEndpoint.address().is_v4()) { // IPv4
+ mtu = std::numeric_limits<uint16_t>::max(); // maximum Total Length
+ mtu -= sizeof(uint32_t) * ((1 << 4) - 1); // maximum Internet Header Length
+ }
+ else { // IPv6
+ mtu = std::numeric_limits<uint16_t>::max(); // maximum Payload Length
+ }
+ mtu -= sizeof(uint16_t) * 4; // size of UDP header
+ return mtu;
+}
+
+} // namespace udp
+} // namespace nfd
diff --git a/daemon/face/udp-protocol.hpp b/daemon/face/udp-protocol.hpp
new file mode 100644
index 0000000..76a7bed
--- /dev/null
+++ b/daemon/face/udp-protocol.hpp
@@ -0,0 +1,42 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/**
+ * Copyright (c) 2014-2015, Regents of the University of California,
+ * Arizona Board of Regents,
+ * Colorado State University,
+ * University Pierre & Marie Curie, Sorbonne University,
+ * Washington University in St. Louis,
+ * Beijing Institute of Technology,
+ * The University of Memphis.
+ *
+ * This file is part of NFD (Named Data Networking Forwarding Daemon).
+ * See AUTHORS.md for complete list of NFD authors and contributors.
+ *
+ * NFD is free software: you can redistribute it and/or modify it under the terms
+ * of the GNU General Public License as published by the Free Software Foundation,
+ * either version 3 of the License, or (at your option) any later version.
+ *
+ * NFD is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
+ * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+ * PURPOSE. See the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * NFD, e.g., in COPYING.md file. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef NFD_DAEMON_FACE_UDP_PROTOCOL_HPP
+#define NFD_DAEMON_FACE_UDP_PROTOCOL_HPP
+
+#include "common.hpp"
+
+namespace nfd {
+namespace udp {
+
+/** \brief computes maximum payload size in a UDP packet
+ */
+ssize_t
+computeMtu(const boost::asio::ip::udp::endpoint& localEndpoint);
+
+} // namespace udp
+} // namespace nfd
+
+#endif // NFD_DAEMON_FACE_UDP_PROTOCOL_HPP
diff --git a/daemon/face/unicast-udp-transport.cpp b/daemon/face/unicast-udp-transport.cpp
index eb8ab66..a5fb3e7 100644
--- a/daemon/face/unicast-udp-transport.cpp
+++ b/daemon/face/unicast-udp-transport.cpp
@@ -24,6 +24,7 @@
*/
#include "unicast-udp-transport.hpp"
+#include "udp-protocol.hpp"
#ifdef __linux__
#include <cerrno> // for errno
@@ -47,8 +48,10 @@
{
this->setLocalUri(FaceUri(m_socket.local_endpoint()));
this->setRemoteUri(FaceUri(m_socket.remote_endpoint()));
+ 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()));
NFD_LOG_FACE_INFO("Creating transport");
diff --git a/daemon/face/unicast-udp-transport.hpp b/daemon/face/unicast-udp-transport.hpp
index 2622e4b..0a9beed 100644
--- a/daemon/face/unicast-udp-transport.hpp
+++ b/daemon/face/unicast-udp-transport.hpp
@@ -23,8 +23,8 @@
* NFD, e.g., in COPYING.md file. If not, see <http://www.gnu.org/licenses/>.
*/
-#ifndef NFD_DAEMON_FACE_UDP_TRANSPORT_HPP
-#define NFD_DAEMON_FACE_UDP_TRANSPORT_HPP
+#ifndef NFD_DAEMON_FACE_UNICAST_UDP_TRANSPORT_HPP
+#define NFD_DAEMON_FACE_UNICAST_UDP_TRANSPORT_HPP
#include "datagram-transport.hpp"
#include "core/scheduler.hpp"
@@ -35,7 +35,7 @@
/**
* \brief A Transport that communicates on a unicast UDP socket
*/
-class UnicastUdpTransport : public DatagramTransport<boost::asio::ip::udp>
+class UnicastUdpTransport : public DatagramTransport<boost::asio::ip::udp, Unicast>
{
public:
UnicastUdpTransport(protocol::socket&& socket,
@@ -55,4 +55,4 @@
} // namespace face
} // namespace nfd
-#endif // NFD_DAEMON_FACE_UDP_TRANSPORT_HPP
+#endif // NFD_DAEMON_FACE_UNICAST_UDP_TRANSPORT_HPP
diff --git a/daemon/face/unix-stream-transport.cpp b/daemon/face/unix-stream-transport.cpp
index 17351f0..e9e2eab 100644
--- a/daemon/face/unix-stream-transport.cpp
+++ b/daemon/face/unix-stream-transport.cpp
@@ -43,6 +43,8 @@
this->setRemoteUri(FaceUri::fromFd(m_socket.native_handle()));
this->setScope(ndn::nfd::FACE_SCOPE_LOCAL);
this->setPersistency(ndn::nfd::FACE_PERSISTENCY_ON_DEMAND);
+ this->setLinkType(ndn::nfd::LINK_TYPE_POINT_TO_POINT);
+ this->setMtu(MTU_UNLIMITED);
NFD_LOG_FACE_INFO("Creating Transport");
}