From feeb918ea8664dab421630a908f1b3b0db922857 Mon Sep 17 00:00:00 2001 From: Eric Newberry Date: Sun, 29 Mar 2020 00:28:41 -0700 Subject: [PATCH] face: handle initially non-running Ethernet interfaces refs #5096 Change-Id: I27cc913cc2478baa8dfaad08e67bd1b9703c43f4 --- daemon/face/ethernet-transport.cpp | 3 ++ tests/daemon/face/ethernet-fixture.hpp | 45 ++++++++++++++--- .../face/multicast-ethernet-transport.t.cpp | 28 +++++------ .../face/unicast-ethernet-transport.t.cpp | 48 +++++++++++++++---- 4 files changed, 94 insertions(+), 30 deletions(-) diff --git a/daemon/face/ethernet-transport.cpp b/daemon/face/ethernet-transport.cpp index 01e175ba..5a810a3b 100644 --- a/daemon/face/ethernet-transport.cpp +++ b/daemon/face/ethernet-transport.cpp @@ -58,6 +58,9 @@ EthernetTransport::EthernetTransport(const ndn::net::NetworkInterface& localEndp NDN_THROW_NESTED(Error(e.what())); } + // Set initial transport state based upon the state of the underlying NetworkInterface + handleNetifStateChange(localEndpoint.getState()); + m_netifStateChangedConn = localEndpoint.onStateChanged.connect( [this] (ndn::net::InterfaceState, ndn::net::InterfaceState newState) { handleNetifStateChange(newState); diff --git a/tests/daemon/face/ethernet-fixture.hpp b/tests/daemon/face/ethernet-fixture.hpp index 1898d507..0c98c720 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-2019, Regents of the University of California, + * Copyright (c) 2014-2020, Regents of the University of California, * Arizona Board of Regents, * Colorado State University, * University Pierre & Marie Curie, Sorbonne University, @@ -58,17 +58,35 @@ protected: } } if (!netifs.empty()) { - netif = const_pointer_cast(netifs.front()); + defaultNetif = const_pointer_cast(netifs.front()); } } + /** \brief returns the first running interface + */ + shared_ptr + getRunningNetif() const + { + for (const auto& netif : netifs) { + if (netif->getState() == ndn::net::InterfaceState::RUNNING) { + return const_pointer_cast(netif); + } + } + + return nullptr; + } + /** \brief create a UnicastEthernetTransport */ void - initializeUnicast(ndn::nfd::FacePersistency persistency = ndn::nfd::FACE_PERSISTENCY_PERSISTENT, + initializeUnicast(shared_ptr netif = nullptr, + ndn::nfd::FacePersistency persistency = ndn::nfd::FACE_PERSISTENCY_PERSISTENT, ethernet::Address remoteAddr = {0x00, 0x00, 0x5e, 0x00, 0x53, 0x5e}) { - BOOST_ASSERT(netif != nullptr); + if (!netif) { + netif = defaultNetif; + } + localEp = netif->getName(); remoteEp = remoteAddr; transport = make_unique(*netif, remoteEp, persistency, 2_s); @@ -77,10 +95,14 @@ protected: /** \brief create a MulticastEthernetTransport */ void - initializeMulticast(ndn::nfd::LinkType linkType = ndn::nfd::LINK_TYPE_MULTI_ACCESS, + initializeMulticast(shared_ptr netif = nullptr, + ndn::nfd::LinkType linkType = ndn::nfd::LINK_TYPE_MULTI_ACCESS, ethernet::Address mcastGroup = {0x01, 0x00, 0x5e, 0x90, 0x10, 0x5e}) { - BOOST_ASSERT(netif != nullptr); + if (!netif) { + netif = defaultNetif; + } + localEp = netif->getName(); remoteEp = mcastGroup; transport = make_unique(*netif, remoteEp, linkType); @@ -93,7 +115,7 @@ protected: */ std::vector> netifs; - shared_ptr netif; + shared_ptr defaultNetif; unique_ptr transport; std::string localEp; ethernet::Address remoteEp; @@ -108,6 +130,15 @@ protected: } \ } while (false) +#define SKIP_IF_NO_RUNNING_ETHERNET_NETIF() \ + do { \ + if (!this->getRunningNetif()) { \ + BOOST_WARN_MESSAGE(false, "skipping assertions that require a running " \ + "EthernetTransport-capable network interface"); \ + return; \ + } \ + } while (false) + } // namespace tests } // namespace face } // namespace nfd diff --git a/tests/daemon/face/multicast-ethernet-transport.t.cpp b/tests/daemon/face/multicast-ethernet-transport.t.cpp index 4e0df3c6..84dead41 100644 --- a/tests/daemon/face/multicast-ethernet-transport.t.cpp +++ b/tests/daemon/face/multicast-ethernet-transport.t.cpp @@ -63,12 +63,12 @@ BOOST_AUTO_TEST_CASE(PersistencyChange) BOOST_AUTO_TEST_CASE(NetifStateChange) { - SKIP_IF_ETHERNET_NETIF_COUNT_LT(1); - initializeMulticast(); - BOOST_CHECK_EQUAL(transport->getState(), TransportState::UP); + SKIP_IF_NO_RUNNING_ETHERNET_NETIF(); + auto netif = getRunningNetif(); + initializeMulticast(netif); - // simulate 'ip link set IFNAME down' - getScheduler().schedule(10_ms, [this] { netif->setState(ndn::net::InterfaceState::DOWN); }); + // Simulate setting interface administratively down + getScheduler().schedule(10_ms, [netif] { netif->setState(ndn::net::InterfaceState::DOWN); }); transport->afterStateChange.connectSingleShot([this] (auto oldState, auto newState) { BOOST_CHECK_EQUAL(oldState, TransportState::UP); BOOST_CHECK_EQUAL(newState, TransportState::DOWN); @@ -77,9 +77,9 @@ BOOST_AUTO_TEST_CASE(NetifStateChange) BOOST_CHECK_EQUAL(limitedIo.run(1, 1_s), LimitedIo::EXCEED_OPS); BOOST_CHECK_EQUAL(transport->getState(), TransportState::DOWN); - // simulate 'ip link set IFNAME up' - getScheduler().schedule(10_ms, [this] { netif->setState(ndn::net::InterfaceState::NO_CARRIER); }); - getScheduler().schedule(80_ms, [this] { netif->setState(ndn::net::InterfaceState::RUNNING); }); + // Simulate setting interface administratively up + getScheduler().schedule(10_ms, [netif] { netif->setState(ndn::net::InterfaceState::NO_CARRIER); }); + getScheduler().schedule(80_ms, [netif] { netif->setState(ndn::net::InterfaceState::RUNNING); }); transport->afterStateChange.connectSingleShot([this] (auto oldState, auto newState) { BOOST_CHECK_EQUAL(oldState, TransportState::DOWN); BOOST_CHECK_EQUAL(newState, TransportState::UP); @@ -93,25 +93,25 @@ BOOST_AUTO_TEST_CASE(NetifMtuChange) { SKIP_IF_ETHERNET_NETIF_COUNT_LT(1); initializeMulticast(); - BOOST_CHECK_EQUAL(transport->getMtu(), netif->getMtu()); + BOOST_CHECK_EQUAL(transport->getMtu(), defaultNetif->getMtu()); // netif changes MTU from initial value to 1024 - netif->setMtu(1024); + defaultNetif->setMtu(1024); BOOST_CHECK_EQUAL(transport->getMtu(), 1024); // netif changes MTU from 1024 to 4000 - netif->setMtu(4000); + defaultNetif->setMtu(4000); BOOST_CHECK_EQUAL(transport->getMtu(), 4000); // netif changes MTU from 4000 to 0 - netif->setMtu(0); + defaultNetif->setMtu(0); BOOST_CHECK_EQUAL(transport->getMtu(), 0); } BOOST_AUTO_TEST_CASE(Close) { - SKIP_IF_ETHERNET_NETIF_COUNT_LT(1); - initializeMulticast(); + SKIP_IF_NO_RUNNING_ETHERNET_NETIF(); + initializeMulticast(getRunningNetif()); transport->afterStateChange.connectSingleShot([] (auto oldState, auto newState) { BOOST_CHECK_EQUAL(oldState, TransportState::UP); diff --git a/tests/daemon/face/unicast-ethernet-transport.t.cpp b/tests/daemon/face/unicast-ethernet-transport.t.cpp index 634a1198..79a0f380 100644 --- a/tests/daemon/face/unicast-ethernet-transport.t.cpp +++ b/tests/daemon/face/unicast-ethernet-transport.t.cpp @@ -27,6 +27,8 @@ #include "ethernet-fixture.hpp" +#include "common/global.hpp" + namespace nfd { namespace face { namespace tests { @@ -58,29 +60,57 @@ BOOST_AUTO_TEST_CASE(PersistencyChange) BOOST_CHECK_EQUAL(transport->canChangePersistencyTo(ndn::nfd::FACE_PERSISTENCY_PERMANENT), true); } +BOOST_AUTO_TEST_CASE(NetifStateChange) +{ + SKIP_IF_NO_RUNNING_ETHERNET_NETIF(); + auto netif = getRunningNetif(); + initializeUnicast(netif); + + // Simulate setting interface administratively down + getScheduler().schedule(10_ms, [netif] { netif->setState(ndn::net::InterfaceState::DOWN); }); + transport->afterStateChange.connectSingleShot([this] (auto oldState, auto newState) { + BOOST_CHECK_EQUAL(oldState, TransportState::UP); + BOOST_CHECK_EQUAL(newState, TransportState::DOWN); + this->limitedIo.afterOp(); + }); + BOOST_CHECK_EQUAL(limitedIo.run(1, 1_s), LimitedIo::EXCEED_OPS); + BOOST_CHECK_EQUAL(transport->getState(), TransportState::DOWN); + + // Simulate setting interface administratively up + getScheduler().schedule(10_ms, [netif] { netif->setState(ndn::net::InterfaceState::NO_CARRIER); }); + getScheduler().schedule(80_ms, [netif] { netif->setState(ndn::net::InterfaceState::RUNNING); }); + transport->afterStateChange.connectSingleShot([this] (auto oldState, auto newState) { + BOOST_CHECK_EQUAL(oldState, TransportState::DOWN); + BOOST_CHECK_EQUAL(newState, TransportState::UP); + this->limitedIo.afterOp(); + }); + BOOST_CHECK_EQUAL(limitedIo.run(1, 1_s), LimitedIo::EXCEED_OPS); + BOOST_CHECK_EQUAL(transport->getState(), TransportState::UP); +} + BOOST_AUTO_TEST_CASE(NetifMtuChange) { SKIP_IF_ETHERNET_NETIF_COUNT_LT(1); initializeUnicast(); - BOOST_CHECK_EQUAL(transport->getMtu(), netif->getMtu()); + BOOST_CHECK_EQUAL(transport->getMtu(), defaultNetif->getMtu()); // netif changes MTU from initial value to 1024 - netif->setMtu(1024); + defaultNetif->setMtu(1024); BOOST_CHECK_EQUAL(transport->getMtu(), 1024); // netif changes MTU from 1024 to 4000 - netif->setMtu(4000); + defaultNetif->setMtu(4000); BOOST_CHECK_EQUAL(transport->getMtu(), 4000); // netif changes MTU from 4000 to 0 - netif->setMtu(0); + defaultNetif->setMtu(0); BOOST_CHECK_EQUAL(transport->getMtu(), 0); } BOOST_AUTO_TEST_CASE(ExpirationTime) { SKIP_IF_ETHERNET_NETIF_COUNT_LT(1); - initializeUnicast(ndn::nfd::FACE_PERSISTENCY_ON_DEMAND); + initializeUnicast(nullptr, ndn::nfd::FACE_PERSISTENCY_ON_DEMAND); BOOST_CHECK_NE(transport->getExpirationTime(), time::steady_clock::TimePoint::max()); transport->setPersistency(ndn::nfd::FACE_PERSISTENCY_PERSISTENT); @@ -92,8 +122,8 @@ BOOST_AUTO_TEST_CASE(ExpirationTime) BOOST_AUTO_TEST_CASE(Close) { - SKIP_IF_ETHERNET_NETIF_COUNT_LT(1); - initializeUnicast(); + SKIP_IF_NO_RUNNING_ETHERNET_NETIF(); + initializeUnicast(getRunningNetif()); transport->afterStateChange.connectSingleShot([] (auto oldState, auto newState) { BOOST_CHECK_EQUAL(oldState, TransportState::UP); @@ -113,8 +143,8 @@ BOOST_AUTO_TEST_CASE(Close) BOOST_AUTO_TEST_CASE(IdleClose) { - SKIP_IF_ETHERNET_NETIF_COUNT_LT(1); - initializeUnicast(ndn::nfd::FACE_PERSISTENCY_ON_DEMAND); + SKIP_IF_NO_RUNNING_ETHERNET_NETIF(); + initializeUnicast(getRunningNetif(), ndn::nfd::FACE_PERSISTENCY_ON_DEMAND); int nStateChanges = 0; transport->afterStateChange.connect(