Skip to content

Commit

Permalink
[pfcwd]: Log PFC frame for a lossy queue (sonic-net#422)
Browse files Browse the repository at this point in the history
* [pfcwd]: Log PFC frame for a lossy queue

Signed-off-by: marian-pritsak <marianp@mellanox.com>
  • Loading branch information
marian-pritsak authored and lguohan committed Jan 10, 2018
1 parent 0e6183e commit b21fa47
Show file tree
Hide file tree
Showing 2 changed files with 117 additions and 2 deletions.
106 changes: 105 additions & 1 deletion orchagent/pfcwdorch.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -31,6 +31,108 @@ PfcWdOrch<DropHandler, ForwardHandler>::PfcWdOrch(DBConnector *db, vector<string
m_countersTable(new Table(m_countersDb.get(), COUNTERS_TABLE))
{
SWSS_LOG_ENTER();

auto interv = timespec { .tv_sec = PFC_WD_LOSSY_POLL_TIMEOUT_SEC, .tv_nsec = 0 };
auto timer = new SelectableTimer(interv);
auto executor = new ExecutableTimer(timer, this);
Orch::addExecutor("", executor);
timer->start();
}

template <typename DropHandler, typename ForwardHandler>
PfcFrameCounters PfcWdOrch<DropHandler, ForwardHandler>::getPfcFrameCounters(sai_object_id_t portId)
{
SWSS_LOG_ENTER();

vector<FieldValueTuple> fieldValues;
PfcFrameCounters counters;
counters.fill(numeric_limits<uint64_t>::max());

static const array<string, PFC_WD_TC_MAX> 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 <typename DropHandler, typename ForwardHandler>
void PfcWdOrch<DropHandler, ForwardHandler>::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<uint64_t>::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 <typename DropHandler, typename ForwardHandler>
Expand Down Expand Up @@ -232,6 +334,8 @@ void PfcWdOrch<DropHandler, ForwardHandler>::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());
}

Expand Down
13 changes: 12 additions & 1 deletion orchagent/pfcwdorch.h
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,10 @@
#include "pfcactionhandler.h"
#include "producerstatetable.h"
#include "notificationconsumer.h"
#include "timer.h"
#include <array>

#define PFC_WD_TC_MAX 8

extern "C" {
#include "sai.h"
Expand All @@ -19,6 +23,8 @@ enum class PfcWdAction
PFC_WD_ACTION_ALERT,
};

typedef array<uint64_t, PFC_WD_TC_MAX> PfcFrameCounters;

template <typename DropHandler, typename ForwardHandler>
class PfcWdOrch: public Orch
{
Expand All @@ -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;
Expand All @@ -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<FieldValueTuple>& data);
void createEntry(const string& key, const vector<FieldValueTuple>& data);
void deleteEntry(const string& name);
PfcFrameCounters getPfcFrameCounters(sai_object_id_t portId);

shared_ptr<DBConnector> m_countersDb = nullptr;
shared_ptr<Table> m_countersTable = nullptr;

map<sai_object_id_t, PfcFrameCounters> m_pfcFrameCountersMap;
};

template <typename DropHandler, typename ForwardHandler>
Expand Down

0 comments on commit b21fa47

Please sign in to comment.