diff --git a/meta/saiserialize.cpp b/meta/saiserialize.cpp index 6352fe4e56..92b3bf20b4 100644 --- a/meta/saiserialize.cpp +++ b/meta/saiserialize.cpp @@ -716,6 +716,14 @@ std::string sai_serialize_queue_stat( return sai_serialize_enum(counter, &sai_metadata_enum_sai_queue_stat_t); } +std::string sai_serialize_queue_attr( + _In_ const sai_queue_attr_t attr) +{ + SWSS_LOG_ENTER(); + + return sai_serialize_enum(attr, &sai_metadata_enum_sai_queue_attr_t); +} + std::string sai_serialize_switch_oper_status( _In_ sai_object_id_t switch_id, _In_ sai_switch_oper_status_t status) @@ -2804,3 +2812,11 @@ void sai_deserialize_queue_stat( sai_deserialize_enum(s, &sai_metadata_enum_sai_queue_stat_t, (int32_t&)stat); } +void sai_deserialize_queue_attr( + _In_ const std::string& s, + _Out_ sai_queue_attr_t& attr) +{ + SWSS_LOG_ENTER(); + + sai_deserialize_enum(s, &sai_metadata_enum_sai_queue_attr_t, (int32_t&)attr); +} diff --git a/meta/saiserialize.h b/meta/saiserialize.h index c4270af9c9..f7d093364d 100644 --- a/meta/saiserialize.h +++ b/meta/saiserialize.h @@ -75,6 +75,9 @@ std::string sai_serialize_port_stat( std::string sai_serialize_queue_stat( _In_ const sai_queue_stat_t counter); +std::string sai_serialize_queue_attr( + _In_ const sai_queue_attr_t attr); + std::string sai_serialize_switch_oper_status( _In_ sai_object_id_t switch_id, _In_ sai_switch_oper_status_t status); @@ -220,4 +223,7 @@ void sai_deserialize_queue_stat( _In_ const std::string& s, _Out_ sai_queue_stat_t& stat); +void sai_deserialize_queue_attr( + _In_ const std::string& s, + _Out_ sai_queue_attr_t& attr); #endif // __SAI_SERIALIZE__ diff --git a/syncd/syncd.cpp b/syncd/syncd.cpp index ee5940c5f6..e181bc08f4 100644 --- a/syncd/syncd.cpp +++ b/syncd/syncd.cpp @@ -2410,6 +2410,18 @@ void processPfcWdEvent( } PfcWatchdog::setQueueCounterList(vid, rid, queueCounterIds); } + else if (objectType == SAI_OBJECT_TYPE_QUEUE && field == PFC_WD_QUEUE_ATTR_ID_LIST) + { + std::vector queueAttrIds; + for (const auto &str : idStrings) + { + sai_queue_attr_t attr; + sai_deserialize_queue_attr(str, attr); + queueAttrIds.push_back(attr); + } + + PfcWatchdog::setQueueAttrList(vid, rid, queueAttrIds); + } else { SWSS_LOG_ERROR("Object type not supported"); diff --git a/syncd/syncd_pfc_watchdog.cpp b/syncd/syncd_pfc_watchdog.cpp index cc557ae473..6c58b6ec6a 100644 --- a/syncd/syncd_pfc_watchdog.cpp +++ b/syncd/syncd_pfc_watchdog.cpp @@ -18,6 +18,13 @@ PfcWatchdog::QueueCounterIds::QueueCounterIds( { } +PfcWatchdog::QueueAttrIds::QueueAttrIds( + _In_ sai_object_id_t queue, + _In_ const std::vector &queueIds): + queueId(queue), queueAttrIds(queueIds) +{ +} + void PfcWatchdog::setPortCounterList( _In_ sai_object_id_t portVid, _In_ sai_object_id_t portId, @@ -64,6 +71,30 @@ void PfcWatchdog::setQueueCounterList( wd.startWatchdogThread(); } +void PfcWatchdog::setQueueAttrList( + _In_ sai_object_id_t queueVid, + _In_ sai_object_id_t queueId, + _In_ const std::vector &attrIds) +{ + SWSS_LOG_ENTER(); + + PfcWatchdog &wd = getInstance(); + + auto it = wd.m_queueAttrIdsMap.find(queueVid); + if (it != wd.m_queueAttrIdsMap.end()) + { + (*it).second->queueAttrIds = attrIds; + return; + } + + auto queueAttrIds = std::make_shared(queueId, attrIds); + wd.m_queueAttrIdsMap.emplace(queueVid, queueAttrIds); + + // Start watchdog thread in case it was not running due to empty counter IDs map + wd.startWatchdogThread(); +} + + void PfcWatchdog::removePort( _In_ sai_object_id_t portVid) { @@ -81,7 +112,7 @@ void PfcWatchdog::removePort( wd.m_portCounterIdsMap.erase(it); // Stop watchdog thread if counter IDs map is empty - if (wd.m_queueCounterIdsMap.empty() && wd.m_portCounterIdsMap.empty()) + if (wd.m_queueCounterIdsMap.empty() && wd.m_portCounterIdsMap.empty() && wd.m_queueAttrIdsMap.empty()) { wd.endWatchdogThread(); } @@ -94,17 +125,26 @@ void PfcWatchdog::removeQueue( PfcWatchdog &wd = getInstance(); - auto it = wd.m_queueCounterIdsMap.find(queueVid); - if (it == wd.m_queueCounterIdsMap.end()) + auto counterIter = wd.m_queueCounterIdsMap.find(queueVid); + if (counterIter == wd.m_queueCounterIdsMap.end()) { SWSS_LOG_ERROR("Trying to remove nonexisting queue counter Ids 0x%lx", queueVid); return; } - wd.m_queueCounterIdsMap.erase(it); + wd.m_queueCounterIdsMap.erase(counterIter); + + auto attrIter = wd.m_queueAttrIdsMap.find(queueVid); + if (attrIter == wd.m_queueAttrIdsMap.end()) + { + SWSS_LOG_ERROR("Trying to remove nonexisting queue attr Ids 0x%lx", queueVid); + return; + } + + wd.m_queueAttrIdsMap.erase(attrIter); // Stop watchdog thread if counter IDs map is empty - if (wd.m_queueCounterIdsMap.empty() && wd.m_portCounterIdsMap.empty()) + if (wd.m_queueCounterIdsMap.empty() && wd.m_portCounterIdsMap.empty() && wd.m_queueAttrIdsMap.empty()) { wd.endWatchdogThread(); } @@ -176,8 +216,6 @@ void PfcWatchdog::collectCounters( { SWSS_LOG_ENTER(); - std::lock_guard lock(g_mutex); - // Collect stats for every registered port for (const auto &kv: m_portCounterIdsMap) { @@ -249,6 +287,49 @@ void PfcWatchdog::collectCounters( countersTable.set(queueVidStr, values, ""); } + + // Collect stats for every registered queue + for (const auto &kv: m_queueAttrIdsMap) + { + const auto &queueVid = kv.first; + const auto &queueId = kv.second->queueId; + const auto &queueAttrIds = kv.second->queueAttrIds; + + std::vector queueAttr(queueAttrIds.size()); + + for (uint64_t i =0; i< queueAttrIds.size(); i++) + { + queueAttr[i].id = queueAttrIds[i]; + } + + // Get queue attr + sai_status_t status = sai_metadata_sai_queue_api->get_queue_attribute( + queueId, + static_cast(queueAttrIds.size()), + queueAttr.data()); + + if (status != SAI_STATUS_SUCCESS) + { + SWSS_LOG_ERROR("Failed to get attr of queue 0x%lx: %d", queueVid, status); + continue; + } + + // Push all counter values to a single vector + std::vector values; + + for (size_t i = 0; i != queueAttrIds.size(); i++) + { + const std::string &counterName = sai_serialize_queue_attr(queueAttrIds[i]); + auto meta = sai_metadata_get_attr_metadata(SAI_OBJECT_TYPE_QUEUE, queueAttr[i].id); + + values.emplace_back(counterName, sai_serialize_attr_value(*meta, queueAttr[i])); + } + // Write counters to DB + std::string queueVidStr = sai_serialize_object_id(queueVid); + + countersTable.set(queueVidStr, values, ""); + } + } void PfcWatchdog::runPlugins( @@ -256,8 +337,6 @@ void PfcWatchdog::runPlugins( { SWSS_LOG_ENTER(); - std::lock_guard lock(g_mutex); - const std::vector argv = { std::to_string(COUNTERS_DB), @@ -299,6 +378,8 @@ void PfcWatchdog::pfcWatchdogThread(void) while (m_runPfcWatchdogThread) { + + std::lock_guard lock(g_mutex); collectCounters(countersTable); runPlugins(db); diff --git a/syncd/syncd_pfc_watchdog.h b/syncd/syncd_pfc_watchdog.h index bb6d2cdb40..5af1e91cfc 100644 --- a/syncd/syncd_pfc_watchdog.h +++ b/syncd/syncd_pfc_watchdog.h @@ -22,6 +22,11 @@ class PfcWatchdog _In_ sai_object_id_t queueVid, _In_ sai_object_id_t queueId, _In_ const std::vector &counterIds); + static void setQueueAttrList( + _In_ sai_object_id_t queueVid, + _In_ sai_object_id_t queueId, + _In_ const std::vector &attrIds); + static void removePort( _In_ sai_object_id_t portVid); static void removeQueue( @@ -49,6 +54,16 @@ class PfcWatchdog std::vector queueCounterIds; }; + struct QueueAttrIds + { + QueueAttrIds( + _In_ sai_object_id_t queue, + _In_ const std::vector &queueIds); + + sai_object_id_t queueId; + std::vector queueAttrIds; + }; + struct PortCounterIds { PortCounterIds( @@ -72,6 +87,7 @@ class PfcWatchdog // Key is a Virtual ID std::map> m_portCounterIdsMap; std::map> m_queueCounterIdsMap; + std::map> m_queueAttrIdsMap; // Plugins std::set m_queuePlugins;