void GenericLinkService::checkCongestionLevel(lp::Packet& pkt) { ssize_t sendQueueLength = getTransport()->getSendQueueLength(); // This operation requires that the transport supports retrieving current send queue length if (sendQueueLength < 0) { return; } // To avoid overflowing the queue, set the congestion threshold to at least half of the send // queue capacity. size_t congestionThreshold = m_options.defaultCongestionThreshold; if (getTransport()->getSendQueueCapacity() >= 0) { congestionThreshold = std::min(congestionThreshold, static_cast<size_t>(getTransport()->getSendQueueCapacity()) / DEFAULT_CONGESTION_THRESHOLD_DIVISOR); } if (sendQueueLength > 0) { NFD_LOG_FACE_TRACE("txqlen=" << sendQueueLength << " threshold=" << congestionThreshold << " capacity=" << getTransport()->getSendQueueCapacity()); } if (static_cast<size_t>(sendQueueLength) > congestionThreshold) { // Send queue is congested const auto now = time::steady_clock::now(); if (now >= m_nextMarkTime || now >= m_lastMarkTime + m_options.baseCongestionMarkingInterval) { // Mark at most one initial packet per baseCongestionMarkingInterval if (m_nMarkedSinceInMarkingState == 0) { m_nextMarkTime = now; } // Time to mark packet pkt.set<lp::CongestionMarkField>(1); ++nCongestionMarked; NFD_LOG_FACE_DEBUG("LpPacket was marked as congested"); ++m_nMarkedSinceInMarkingState; // Decrease the marking interval by the inverse of the square root of the number of packets // marked in this incident of congestion m_nextMarkTime += time::nanoseconds(static_cast<time::nanoseconds::rep>( m_options.baseCongestionMarkingInterval.count() / std::sqrt(m_nMarkedSinceInMarkingState))); m_lastMarkTime = now; } } else if (m_nextMarkTime != time::steady_clock::TimePoint::max()) { // Congestion incident has ended, so reset NFD_LOG_FACE_DEBUG("Send queue length dropped below congestion threshold"); m_nextMarkTime = time::steady_clock::TimePoint::max(); m_nMarkedSinceInMarkingState = 0; } }
void DatagramTransport<T, U>::processErrorCode(const boost::system::error_code& error) { NFD_LOG_FACE_TRACE(__func__); if (getState() == TransportState::CLOSING || getState() == TransportState::FAILED || getState() == TransportState::CLOSED || error == boost::asio::error::operation_aborted) { // transport is shutting down, ignore any errors return; } if (getPersistency() == ndn::nfd::FACE_PERSISTENCY_PERMANENT) { NFD_LOG_FACE_DEBUG("Permanent face ignores error: " << error.message()); return; } NFD_LOG_FACE_ERROR("Send or receive operation failed: " << error.message()); this->setState(TransportState::FAILED); doClose(); }