NS-3 based Named Data Networking (NDN) simulator
ndnSIM 2.0: NDN, CCN, CCNx, content centric networks
API Documentation
udp-face.cpp
Go to the documentation of this file.
1 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
26 #include "udp-face.hpp"
27 // #include "core/global-io.hpp" // for #1718 manual test below
28 
29 #ifdef __linux__
30 #include <cerrno> // for errno
31 #include <cstring> // for std::strerror()
32 #include <netinet/in.h> // for IP_MTU_DISCOVER and IP_PMTUDISC_DONT
33 #include <sys/socket.h> // for setsockopt()
34 #endif
35 
36 namespace nfd {
37 
38 NFD_LOG_INCLASS_TEMPLATE_SPECIALIZATION_DEFINE(DatagramFace, UdpFace::protocol, "UdpFace");
39 
40 UdpFace::UdpFace(const FaceUri& remoteUri, const FaceUri& localUri,
41  protocol::socket socket, ndn::nfd::FacePersistency persistency,
42  const time::seconds& idleTimeout)
43  : DatagramFace(remoteUri, localUri, std::move(socket))
44  , m_idleTimeout(idleTimeout)
45  , m_lastIdleCheck(time::steady_clock::now())
46 {
47  this->setPersistency(persistency);
48 
49 #ifdef __linux__
50  //
51  // By default, Linux does path MTU discovery on IPv4 sockets,
52  // and sets the DF (Don't Fragment) flag on datagrams smaller
53  // than the interface MTU. However this does not work for us,
54  // because we cannot properly respond to ICMP "packet too big"
55  // messages by fragmenting the packet at the application level,
56  // since we want to rely on IP for fragmentation and reassembly.
57  //
58  // Therefore, we disable PMTU discovery, which prevents the kernel
59  // from setting the DF flag on outgoing datagrams, and thus allows
60  // routers along the path to perform fragmentation as needed.
61  //
62  const int value = IP_PMTUDISC_DONT;
63  if (::setsockopt(m_socket.native_handle(), IPPROTO_IP,
64  IP_MTU_DISCOVER, &value, sizeof(value)) < 0) {
65  NFD_LOG_FACE_WARN("Failed to disable path MTU discovery: " << std::strerror(errno));
66  }
67 #endif
68 
69  if (this->getPersistency() == ndn::nfd::FACE_PERSISTENCY_ON_DEMAND && m_idleTimeout > time::seconds::zero()) {
70  m_closeIfIdleEvent = scheduler::schedule(m_idleTimeout, bind(&UdpFace::closeIfIdle, this));
71  }
72 }
73 
76 {
77  auto status = DatagramFace::getFaceStatus();
78 
80  time::milliseconds left = m_idleTimeout;
81  left -= time::duration_cast<time::milliseconds>(time::steady_clock::now() - m_lastIdleCheck);
82 
83  if (left < time::milliseconds::zero())
84  left = time::milliseconds::zero();
85 
86  if (hasBeenUsedRecently())
87  left += m_idleTimeout;
88 
89  status.setExpirationPeriod(left);
90  }
91 
92  return status;
93 }
94 
95 void
96 UdpFace::closeIfIdle()
97 {
98  // Face can be switched from on-demand to non-on-demand mode
99  // (non-on-demand -> on-demand transition is not allowed)
101  if (!hasBeenUsedRecently()) {
102  NFD_LOG_FACE_INFO("Closing for inactivity");
103  close();
104 
105  // #1718 manual test: uncomment, run NFD in valgrind, send in a UDP packet
106  // expect read-after-free error and crash
107  // getGlobalIoService().post([this] {
108  // NFD_LOG_FACE_ERROR("Remaining references: " << this->shared_from_this().use_count());
109  // });
110  }
111  else {
113 
114  m_lastIdleCheck = time::steady_clock::now();
115  m_closeIfIdleEvent = scheduler::schedule(m_idleTimeout, bind(&UdpFace::closeIfIdle, this));
116  }
117  }
118  // else do nothing and do not reschedule the event
119 }
120 
121 } // namespace nfd
virtual ndn::nfd::FaceStatus getFaceStatus() const
Definition: face.cpp:118
ndn::nfd::FacePersistency getPersistency() const
Get the persistency setting.
Definition: face.hpp:251
static time_point now() noexcept
Definition: time.cpp:79
represents the underlying protocol and address used by a Face
Definition: face-uri.hpp:44
void setPersistency(ndn::nfd::FacePersistency persistency)
Definition: face.hpp:257
ndn::nfd::FaceStatus getFaceStatus() const 1
Definition: udp-face.cpp:75
STL namespace.
#define NFD_LOG_FACE_INFO(msg)
Log a message at INFO level.
Definition: face.hpp:327
Copyright (c) 2011-2015 Regents of the University of California.
Definition: ndn-common.hpp:38
represents Face status
EventId schedule(const time::nanoseconds &after, const std::function< void()> &event)
schedule an event
Definition: scheduler.cpp:50
UdpFace(const FaceUri &remoteUri, const FaceUri &localUri, protocol::socket socket, ndn::nfd::FacePersistency persistency, const time::seconds &idleTimeout)
Definition: udp-face.cpp:40
#define NFD_LOG_FACE_WARN(msg)
Log a message at WARN level.
Definition: face.hpp:330
void resetRecentUsage()
Set m_hasBeenUsedRecently to false.