face: implement close-on-idle and persistency change for Ethernet unicast
Change-Id: I255024990a72b8cea5a44fa89f515ad91aadba66
Refs: #4011
diff --git a/daemon/face/ethernet-transport.cpp b/daemon/face/ethernet-transport.cpp
index 9f6d465..a4c4006 100644
--- a/daemon/face/ethernet-transport.cpp
+++ b/daemon/face/ethernet-transport.cpp
@@ -47,6 +47,7 @@
, m_srcAddress(localEndpoint.etherAddress)
, m_destAddress(remoteEndpoint)
, m_interfaceName(localEndpoint.name)
+ , m_hasBeenUsedRecently(false)
#ifdef _DEBUG
, m_nDropped(0)
#endif
@@ -114,9 +115,10 @@
// send the frame
int sent = pcap_inject(m_pcap, buffer.buf(), buffer.size());
if (sent < 0)
- NFD_LOG_FACE_ERROR("pcap_inject failed: " << m_pcap.getLastError());
+ handleError("Send operation failed: " + m_pcap.getLastError());
else if (static_cast<size_t>(sent) < buffer.size())
- NFD_LOG_FACE_ERROR("Failed to send the full frame: size=" << buffer.size() << " sent=" << sent);
+ handleError("Failed to send the full frame: size=" + to_string(buffer.size()) +
+ " sent=" + to_string(sent));
else
// print block size because we don't want to count the padding in buffer
NFD_LOG_FACE_TRACE("Successfully sent: " << block.size() << " bytes");
@@ -133,8 +135,17 @@
void
EthernetTransport::handleRead(const boost::system::error_code& error)
{
- if (error)
- return processErrorCode(error);
+ if (error) {
+ // boost::asio::error::operation_aborted must be checked first: in that case, the Transport
+ // may already have been destructed, therefore it's unsafe to call getState() or do logging.
+ if (error != boost::asio::error::operation_aborted &&
+ getState() != TransportState::CLOSING &&
+ getState() != TransportState::FAILED &&
+ getState() != TransportState::CLOSED) {
+ handleError("Receive operation failed: " + error.message());
+ }
+ return;
+ }
const uint8_t* pkt;
size_t len;
@@ -142,14 +153,14 @@
std::tie(pkt, len, err) = m_pcap.readNextPacket();
if (pkt == nullptr) {
- NFD_LOG_FACE_ERROR("Read error: " << err);
+ NFD_LOG_FACE_WARN("Read error: " << err);
}
else {
const ether_header* eh;
std::tie(eh, err) = ethernet::checkFrameHeader(pkt, len, m_srcAddress,
m_destAddress.isMulticast() ? m_destAddress : m_srcAddress);
if (eh == nullptr) {
- NFD_LOG_FACE_DEBUG(err);
+ NFD_LOG_FACE_WARN(err);
}
else {
ethernet::Address sender(eh->ether_shost);
@@ -173,15 +184,17 @@
EthernetTransport::receivePayload(const uint8_t* payload, size_t length,
const ethernet::Address& sender)
{
+ NFD_LOG_FACE_TRACE("Received: " << length << " bytes from " << sender);
+
bool isOk = false;
Block element;
std::tie(isOk, element) = Block::fromBuffer(payload, length);
if (!isOk) {
- NFD_LOG_FACE_WARN("Received invalid packet from " << sender);
+ NFD_LOG_FACE_WARN("Failed to parse incoming packet from " << sender);
+ // This packet won't extend the face lifetime
return;
}
-
- NFD_LOG_FACE_TRACE("Received: " << element.size() << " bytes from " << sender);
+ m_hasBeenUsedRecently = true;
Transport::Packet tp(std::move(element));
static_assert(sizeof(tp.remoteEndpoint) >= ethernet::ADDR_LEN,
@@ -193,19 +206,16 @@
}
void
-EthernetTransport::processErrorCode(const boost::system::error_code& error)
+EthernetTransport::handleError(const std::string& errorMessage)
{
- // boost::asio::error::operation_aborted must be checked first. In that situation, the Transport
- // may already have been destructed, and it's unsafe to call getState() or do logging.
- if (error == boost::asio::error::operation_aborted ||
- getState() == TransportState::CLOSING ||
- getState() == TransportState::FAILED ||
- getState() == TransportState::CLOSED) {
- // transport is shutting down, ignore any errors
+ if (getPersistency() == ndn::nfd::FACE_PERSISTENCY_PERMANENT) {
+ NFD_LOG_FACE_DEBUG("Permanent face ignores error: " << errorMessage);
return;
}
- NFD_LOG_FACE_WARN("Receive operation failed: " << error.message());
+ NFD_LOG_FACE_ERROR(errorMessage);
+ this->setState(TransportState::FAILED);
+ doClose();
}
int