face: set EthernetTransport UP/DOWN based on netif state
refs #3352
Change-Id: I24476ee293d229cd9222996f91f31cfb15728c47
diff --git a/daemon/face/ethernet-transport.cpp b/daemon/face/ethernet-transport.cpp
index 7d1f7cb..412bcba 100644
--- a/daemon/face/ethernet-transport.cpp
+++ b/daemon/face/ethernet-transport.cpp
@@ -58,6 +58,11 @@
BOOST_THROW_EXCEPTION(Error(e.what()));
}
+ m_netifStateConn = localEndpoint.onStateChanged.connect(
+ [=] (ndn::net::InterfaceState, ndn::net::InterfaceState newState) {
+ handleNetifStateChange(newState);
+ });
+
asyncRead();
}
@@ -83,6 +88,20 @@
}
void
+EthernetTransport::handleNetifStateChange(ndn::net::InterfaceState netifState)
+{
+ NFD_LOG_FACE_TRACE("netif is " << netifState);
+ if (netifState == ndn::net::InterfaceState::RUNNING) {
+ if (getState() == TransportState::DOWN) {
+ this->setState(TransportState::UP);
+ }
+ }
+ else if (getState() == TransportState::UP) {
+ this->setState(TransportState::DOWN);
+ }
+}
+
+void
EthernetTransport::doSend(Transport::Packet&& packet)
{
NFD_LOG_FACE_TRACE(__func__);
diff --git a/daemon/face/ethernet-transport.hpp b/daemon/face/ethernet-transport.hpp
index 63658d0..798b937 100644
--- a/daemon/face/ethernet-transport.hpp
+++ b/daemon/face/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,
@@ -81,6 +81,9 @@
private:
void
+ handleNetifStateChange(ndn::net::InterfaceState netifState);
+
+ void
doSend(Transport::Packet&& packet) final;
/**
@@ -106,6 +109,7 @@
std::string m_interfaceName;
private:
+ signal::ScopedConnection m_netifStateConn;
bool m_hasRecentlyReceived;
#ifdef _DEBUG
/// number of frames dropped by the kernel, as reported by libpcap
diff --git a/tests/daemon/face/ethernet-fixture.hpp b/tests/daemon/face/ethernet-fixture.hpp
index 60402a6..993352d 100644
--- a/tests/daemon/face/ethernet-fixture.hpp
+++ b/tests/daemon/face/ethernet-fixture.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,
@@ -57,6 +57,9 @@
}
}
}
+ if (!netifs.empty()) {
+ netif = const_pointer_cast<ndn::net::NetworkInterface>(netifs.front());
+ }
}
/** \brief create a UnicastEthernetTransport
@@ -65,10 +68,10 @@
initializeUnicast(ndn::nfd::FacePersistency persistency = ndn::nfd::FACE_PERSISTENCY_PERSISTENT,
ethernet::Address remoteAddr = {0x00, 0x00, 0x5e, 0x00, 0x53, 0x5e})
{
- BOOST_ASSERT(netifs.size() > 0);
- localEp = netifs.front()->getName();
+ BOOST_ASSERT(netif != nullptr);
+ localEp = netif->getName();
remoteEp = remoteAddr;
- transport = make_unique<UnicastEthernetTransport>(*netifs.front(), remoteEp, persistency, time::seconds(2));
+ transport = make_unique<UnicastEthernetTransport>(*netif, remoteEp, persistency, time::seconds(2));
}
/** \brief create a MulticastEthernetTransport
@@ -77,10 +80,10 @@
initializeMulticast(ndn::nfd::LinkType linkType = ndn::nfd::LINK_TYPE_MULTI_ACCESS,
ethernet::Address mcastGroup = {0x01, 0x00, 0x5e, 0x90, 0x10, 0x5e})
{
- BOOST_ASSERT(netifs.size() > 0);
- localEp = netifs.front()->getName();
+ BOOST_ASSERT(netif != nullptr);
+ localEp = netif->getName();
remoteEp = mcastGroup;
- transport = make_unique<MulticastEthernetTransport>(*netifs.front(), remoteEp, linkType);
+ transport = make_unique<MulticastEthernetTransport>(*netif, remoteEp, linkType);
}
protected:
@@ -90,6 +93,7 @@
*/
std::vector<shared_ptr<const ndn::net::NetworkInterface>> netifs;
+ shared_ptr<ndn::net::NetworkInterface> netif;
unique_ptr<EthernetTransport> transport;
std::string localEp;
ethernet::Address remoteEp;
diff --git a/tests/daemon/face/multicast-ethernet-transport.t.cpp b/tests/daemon/face/multicast-ethernet-transport.t.cpp
index 511f57a..d4e1fce 100644
--- a/tests/daemon/face/multicast-ethernet-transport.t.cpp
+++ b/tests/daemon/face/multicast-ethernet-transport.t.cpp
@@ -59,6 +59,34 @@
BOOST_CHECK_EQUAL(transport->canChangePersistencyTo(ndn::nfd::FACE_PERSISTENCY_PERMANENT), true);
}
+BOOST_AUTO_TEST_CASE(NetifStateChange)
+{
+ SKIP_IF_ETHERNET_NETIF_COUNT_LT(1);
+ initializeMulticast();
+ BOOST_CHECK_EQUAL(transport->getState(), TransportState::UP);
+
+ // simulate 'ip link set IFNAME down'
+ scheduler::schedule(10_ms, [=] { netif->setState(ndn::net::InterfaceState::DOWN); });
+ transport->afterStateChange.connectSingleShot([&] (TransportState oldState, TransportState newState) {
+ BOOST_CHECK_EQUAL(oldState, TransportState::UP);
+ BOOST_CHECK_EQUAL(newState, TransportState::DOWN);
+ limitedIo.afterOp();
+ });
+ BOOST_CHECK_EQUAL(limitedIo.run(1, 1_s), LimitedIo::EXCEED_OPS);
+ BOOST_CHECK_EQUAL(transport->getState(), TransportState::DOWN);
+
+ // simulate 'ip link set IFNAME up'
+ scheduler::schedule(10_ms, [=] { netif->setState(ndn::net::InterfaceState::NO_CARRIER); });
+ scheduler::schedule(80_ms, [=] { netif->setState(ndn::net::InterfaceState::RUNNING); });
+ transport->afterStateChange.connectSingleShot([&] (TransportState oldState, TransportState newState) {
+ BOOST_CHECK_EQUAL(oldState, TransportState::DOWN);
+ BOOST_CHECK_EQUAL(newState, TransportState::UP);
+ limitedIo.afterOp();
+ });
+ BOOST_CHECK_EQUAL(limitedIo.run(1, 1_s), LimitedIo::EXCEED_OPS);
+ BOOST_CHECK_EQUAL(transport->getState(), TransportState::UP);
+}
+
BOOST_AUTO_TEST_CASE(Close)
{
SKIP_IF_ETHERNET_NETIF_COUNT_LT(1);
diff --git a/tests/daemon/face/test-netif.cpp b/tests/daemon/face/test-netif.cpp
index 56b9081..b3e6fde 100644
--- a/tests/daemon/face/test-netif.cpp
+++ b/tests/daemon/face/test-netif.cpp
@@ -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,
@@ -26,13 +26,24 @@
#include "test-netif.hpp"
#include "core/global-io.hpp"
-#include <ndn-cxx/net/network-monitor.hpp>
-
namespace nfd {
namespace face {
namespace tests {
std::vector<shared_ptr<const NetworkInterface>>
+enumerateNetworkInterfaces(NetworkMonitor& netmon)
+{
+ if ((netmon.getCapabilities() & NetworkMonitor::CAP_ENUM) == 0) {
+ BOOST_THROW_EXCEPTION(NetworkMonitor::Error("NetworkMonitor::CAP_ENUM is unavailable"));
+ }
+
+ netmon.onEnumerationCompleted.connect([] { getGlobalIoService().stop(); });
+ getGlobalIoService().run();
+ getGlobalIoService().reset();
+ return netmon.listNetworkInterfaces();
+}
+
+std::vector<shared_ptr<const NetworkInterface>>
collectNetworkInterfaces(bool allowCached)
{
using ndn::net::NetworkMonitor;
@@ -44,15 +55,7 @@
if (!allowCached || cached.empty()) {
NetworkMonitor netmon(getGlobalIoService());
- if ((netmon.getCapabilities() & NetworkMonitor::CAP_ENUM) == 0) {
- BOOST_THROW_EXCEPTION(NetworkMonitor::Error("NetworkMonitor::CAP_ENUM is unavailable"));
- }
-
- netmon.onEnumerationCompleted.connect([] { getGlobalIoService().stop(); });
- getGlobalIoService().run();
- getGlobalIoService().reset();
-
- cached = netmon.listNetworkInterfaces();
+ cached = enumerateNetworkInterfaces(netmon);
}
return cached;
diff --git a/tests/daemon/face/test-netif.hpp b/tests/daemon/face/test-netif.hpp
index d30d865..7c926e6 100644
--- a/tests/daemon/face/test-netif.hpp
+++ b/tests/daemon/face/test-netif.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,
@@ -30,6 +30,7 @@
#include <ndn-cxx/net/network-address.hpp>
#include <ndn-cxx/net/network-interface.hpp>
+#include <ndn-cxx/net/network-monitor.hpp>
namespace nfd {
namespace face {
@@ -37,10 +38,21 @@
using ndn::net::NetworkAddress;
using ndn::net::NetworkInterface;
+using ndn::net::NetworkMonitor;
+
+/** \brief Enumerate network interfaces using the given NetworkMonitor
+ * \param netmon a NetworkMonitor constructed on the global io_service.
+ * \note This function is blocking
+ * \warning Signals are supported if caller keeps NetworkMonitor running
+ * \throw ndn::net::NetworkMonitor::Error NetworkMonitor::CAP_ENUM is unavailable
+ */
+std::vector<shared_ptr<const NetworkInterface>>
+enumerateNetworkInterfaces(NetworkMonitor& netmon);
/** \brief Collect information about network interfaces
* \param allowCached if true, previously collected information can be returned
* \note This function is blocking if \p allowCached is false or no previous information exists
+ * \warning Signals are not triggered on returned NetworkInterfaces because NetworkMonitor is not running
* \throw ndn::net::NetworkMonitor::Error NetworkMonitor::CAP_ENUM is unavailable
*/
std::vector<shared_ptr<const NetworkInterface>>