From b21fa4750a220a3a959f0a4c0b1d597fa1c0f6c8 Mon Sep 17 00:00:00 2001 From: Marian Pritsak Date: Wed, 10 Jan 2018 09:16:34 +0200 Subject: [PATCH] [pfcwd]: Log PFC frame for a lossy queue (#422) * [pfcwd]: Log PFC frame for a lossy queue Signed-off-by: marian-pritsak --- orchagent/pfcwdorch.cpp | 106 +++++++++++++++++++++++++++++++++++++++- orchagent/pfcwdorch.h | 13 ++++- 2 files changed, 117 insertions(+), 2 deletions(-) diff --git a/orchagent/pfcwdorch.cpp b/orchagent/pfcwdorch.cpp index 77a33696acda..63fb6c0acea8 100644 --- a/orchagent/pfcwdorch.cpp +++ b/orchagent/pfcwdorch.cpp @@ -16,8 +16,8 @@ #define PFC_WD_DETECTION_TIME_MIN 100 #define PFC_WD_RESTORATION_TIME_MAX (60 * 1000) #define PFC_WD_RESTORATION_TIME_MIN 100 -#define PFC_WD_TC_MAX 8 #define PFC_WD_POLL_TIMEOUT 5000 +#define PFC_WD_LOSSY_POLL_TIMEOUT_SEC (5 * 60) extern sai_port_api_t *sai_port_api; extern sai_queue_api_t *sai_queue_api; @@ -31,6 +31,108 @@ PfcWdOrch::PfcWdOrch(DBConnector *db, vectorstart(); +} + +template +PfcFrameCounters PfcWdOrch::getPfcFrameCounters(sai_object_id_t portId) +{ + SWSS_LOG_ENTER(); + + vector fieldValues; + PfcFrameCounters counters; + counters.fill(numeric_limits::max()); + + static const array counterNames = + { + "SAI_PORT_STAT_PFC_0_RX_PKTS", + "SAI_PORT_STAT_PFC_1_RX_PKTS", + "SAI_PORT_STAT_PFC_2_RX_PKTS", + "SAI_PORT_STAT_PFC_3_RX_PKTS", + "SAI_PORT_STAT_PFC_4_RX_PKTS", + "SAI_PORT_STAT_PFC_5_RX_PKTS", + "SAI_PORT_STAT_PFC_6_RX_PKTS", + "SAI_PORT_STAT_PFC_7_RX_PKTS" + }; + + if (!m_countersTable->get(sai_serialize_object_id(portId), fieldValues)) + { + return move(counters); + } + + for (const auto& fv : fieldValues) + { + const auto field = fvField(fv); + const auto value = fvValue(fv); + + + for (size_t prio = 0; prio != counterNames.size(); prio++) + { + if (field == counterNames[prio]) + { + counters[prio] = stoul(value); + } + } + } + + return move(counters); +} + +template +void PfcWdOrch::doTask(SelectableTimer &timer) +{ + SWSS_LOG_ENTER(); + + sai_attribute_t attr; + attr.id = SAI_PORT_ATTR_PRIORITY_FLOW_CONTROL; + + for (auto& i : m_pfcFrameCountersMap) + { + auto oid = i.first; + auto counters = i.second; + auto newCounters = getPfcFrameCounters(oid); + + Port port; + if (!gPortsOrch->getPort(oid, port)) + { + SWSS_LOG_ERROR("Invalid port oid 0x%lx", oid); + continue; + } + + sai_status_t status = sai_port_api->get_port_attribute(port.m_port_id, 1, &attr); + if (status != SAI_STATUS_SUCCESS) + { + SWSS_LOG_ERROR("Failed to get PFC mask on port %s: %d", port.m_alias.c_str(), status); + continue; + } + + uint8_t pfcMask = attr.value.u8; + + for (size_t prio = 0; prio != counters.size(); prio++) + { + bool isLossy = ((1 << prio) & pfcMask) == 0; + if (newCounters[prio] == numeric_limits::max()) + { + SWSS_LOG_WARN("Could not retreive PFC frame count on queue %lu port %s", + prio, + port.m_alias.c_str()); + } + else if (isLossy && counters[prio] < newCounters[prio]) + { + SWSS_LOG_WARN("Got PFC %lu frame(s) on lossy queue %lu port %s", + newCounters[prio] - counters[prio], + prio, + port.m_alias.c_str()); + } + } + + i.second = newCounters; + } } template @@ -232,6 +334,8 @@ void PfcWdOrch::createEntry(const string& key, return; } + m_pfcFrameCountersMap.emplace(port.m_port_id, getPfcFrameCounters(port.m_port_id)); + SWSS_LOG_NOTICE("Started PFC Watchdog on port %s", port.m_alias.c_str()); } diff --git a/orchagent/pfcwdorch.h b/orchagent/pfcwdorch.h index 4be07185268d..a32abe7729d0 100644 --- a/orchagent/pfcwdorch.h +++ b/orchagent/pfcwdorch.h @@ -6,6 +6,10 @@ #include "pfcactionhandler.h" #include "producerstatetable.h" #include "notificationconsumer.h" +#include "timer.h" +#include + +#define PFC_WD_TC_MAX 8 extern "C" { #include "sai.h" @@ -19,6 +23,8 @@ enum class PfcWdAction PFC_WD_ACTION_ALERT, }; +typedef array PfcFrameCounters; + template class PfcWdOrch: public Orch { @@ -27,6 +33,7 @@ class PfcWdOrch: public Orch virtual ~PfcWdOrch(void); virtual void doTask(Consumer& consumer); + virtual void doTask(SelectableTimer &timer); virtual bool startWdOnPort(const Port& port, uint32_t detectionTime, uint32_t restorationTime, PfcWdAction action) = 0; virtual bool stopWdOnPort(const Port& port) = 0; @@ -43,12 +50,16 @@ class PfcWdOrch: public Orch static PfcWdAction deserializeAction(const string& key); static string serializeAction(const PfcWdAction &action); + private: - void createEntry(const string& key, const vector& data); + void createEntry(const string& key, const vector& data); void deleteEntry(const string& name); + PfcFrameCounters getPfcFrameCounters(sai_object_id_t portId); shared_ptr m_countersDb = nullptr; shared_ptr m_countersTable = nullptr; + + map m_pfcFrameCountersMap; }; template