diff --git a/lib/ClientSai.cpp b/lib/ClientSai.cpp index cff4201fec4a..0586b1911e71 100644 --- a/lib/ClientSai.cpp +++ b/lib/ClientSai.cpp @@ -886,6 +886,16 @@ sai_status_t ClientSai::getStats( return waitForGetStatsResponse(number_of_counters, counters); } +sai_status_t ClientSai::queryStatsCapability( + _In_ sai_object_id_t switchId, + _In_ sai_object_type_t objectType, + _Inout_ sai_stat_capability_list_t *stats_capability) +{ + SWSS_LOG_ENTER(); + + return SAI_STATUS_NOT_IMPLEMENTED; +} + sai_status_t ClientSai::waitForGetStatsResponse( _In_ uint32_t number_of_counters, _Out_ uint64_t *counters) diff --git a/lib/ClientSai.h b/lib/ClientSai.h index 31e36946fea8..f051a51d5225 100644 --- a/lib/ClientSai.h +++ b/lib/ClientSai.h @@ -97,6 +97,11 @@ namespace sairedis _In_ const sai_stat_id_t *counter_ids, _Out_ uint64_t *counters) override; + virtual sai_status_t queryStatsCapability( + _In_ sai_object_id_t switch_id, + _In_ sai_object_type_t object_type, + _Inout_ sai_stat_capability_list_t *stats_capability) override; + virtual sai_status_t getStatsExt( _In_ sai_object_type_t object_type, _In_ sai_object_id_t object_id, diff --git a/lib/ClientServerSai.cpp b/lib/ClientServerSai.cpp index 93b3514ce984..71598a24e20d 100644 --- a/lib/ClientServerSai.cpp +++ b/lib/ClientServerSai.cpp @@ -247,6 +247,18 @@ sai_status_t ClientServerSai::getStats( counters); } +sai_status_t ClientServerSai::queryStatsCapability( + _In_ sai_object_id_t switchId, + _In_ sai_object_type_t objectType, + _Inout_ sai_stat_capability_list_t *stats_capability) +{ + MUTEX(); + SWSS_LOG_ENTER(); + REDIS_CHECK_API_INITIALIZED(); + + return SAI_STATUS_NOT_IMPLEMENTED; +} + sai_status_t ClientServerSai::getStatsExt( _In_ sai_object_type_t object_type, _In_ sai_object_id_t object_id, diff --git a/lib/ClientServerSai.h b/lib/ClientServerSai.h index 8f1386378106..e8fb16583566 100644 --- a/lib/ClientServerSai.h +++ b/lib/ClientServerSai.h @@ -89,6 +89,11 @@ namespace sairedis _In_ const sai_stat_id_t *counter_ids, _Out_ uint64_t *counters) override; + virtual sai_status_t queryStatsCapability( + _In_ sai_object_id_t switch_id, + _In_ sai_object_type_t object_type, + _Inout_ sai_stat_capability_list_t *stats_capability) override; + virtual sai_status_t getStatsExt( _In_ sai_object_type_t object_type, _In_ sai_object_id_t object_id, diff --git a/lib/RedisRemoteSaiInterface.cpp b/lib/RedisRemoteSaiInterface.cpp index d5f4c0eac5cb..4279f133eba4 100644 --- a/lib/RedisRemoteSaiInterface.cpp +++ b/lib/RedisRemoteSaiInterface.cpp @@ -1125,6 +1125,16 @@ sai_status_t RedisRemoteSaiInterface::getStats( return waitForGetStatsResponse(number_of_counters, counters); } +sai_status_t RedisRemoteSaiInterface::queryStatsCapability( + _In_ sai_object_id_t switchId, + _In_ sai_object_type_t objectType, + _Inout_ sai_stat_capability_list_t *stats_capability) +{ + SWSS_LOG_ENTER(); + + return SAI_STATUS_NOT_IMPLEMENTED; +} + sai_status_t RedisRemoteSaiInterface::waitForGetStatsResponse( _In_ uint32_t number_of_counters, _Out_ uint64_t *counters) diff --git a/lib/RedisRemoteSaiInterface.h b/lib/RedisRemoteSaiInterface.h index e4482ba1e886..eb3014f259a7 100644 --- a/lib/RedisRemoteSaiInterface.h +++ b/lib/RedisRemoteSaiInterface.h @@ -108,6 +108,11 @@ namespace sairedis _In_ const sai_stat_id_t *counter_ids, _Out_ uint64_t *counters) override; + virtual sai_status_t queryStatsCapability( + _In_ sai_object_id_t switch_id, + _In_ sai_object_type_t object_type, + _Inout_ sai_stat_capability_list_t *stats_capability) override; + virtual sai_status_t getStatsExt( _In_ sai_object_type_t object_type, _In_ sai_object_id_t object_id, diff --git a/lib/Sai.cpp b/lib/Sai.cpp index 3f146efd2c6f..ecbaed77fc3d 100644 --- a/lib/Sai.cpp +++ b/lib/Sai.cpp @@ -351,6 +351,16 @@ sai_status_t Sai::getStats( counters); } +sai_status_t Sai::queryStatsCapability( + _In_ sai_object_id_t switchId, + _In_ sai_object_type_t objectType, + _Inout_ sai_stat_capability_list_t *stats_capability) +{ + SWSS_LOG_ENTER(); + + return SAI_STATUS_NOT_IMPLEMENTED; +} + sai_status_t Sai::getStatsExt( _In_ sai_object_type_t object_type, _In_ sai_object_id_t object_id, diff --git a/lib/Sai.h b/lib/Sai.h index 00849f9055ed..3162ab30d023 100644 --- a/lib/Sai.h +++ b/lib/Sai.h @@ -98,6 +98,11 @@ namespace sairedis _In_ const sai_stat_id_t *counter_ids, _Out_ uint64_t *counters) override; + virtual sai_status_t queryStatsCapability( + _In_ sai_object_id_t switch_id, + _In_ sai_object_type_t object_type, + _Inout_ sai_stat_capability_list_t *stats_capability) override; + virtual sai_status_t getStatsExt( _In_ sai_object_type_t object_type, _In_ sai_object_id_t object_id, diff --git a/lib/ServerSai.cpp b/lib/ServerSai.cpp index f10b6c754a9e..0e17ef0bd6d1 100644 --- a/lib/ServerSai.cpp +++ b/lib/ServerSai.cpp @@ -269,6 +269,16 @@ sai_status_t ServerSai::getStats( counters); } +sai_status_t ServerSai::queryStatsCapability( + _In_ sai_object_id_t switchId, + _In_ sai_object_type_t objectType, + _Inout_ sai_stat_capability_list_t *stats_capability) +{ + SWSS_LOG_ENTER(); + + return SAI_STATUS_NOT_IMPLEMENTED; +} + sai_status_t ServerSai::getStatsExt( _In_ sai_object_type_t object_type, _In_ sai_object_id_t object_id, diff --git a/lib/ServerSai.h b/lib/ServerSai.h index 1626871932db..d9f27b4f8306 100644 --- a/lib/ServerSai.h +++ b/lib/ServerSai.h @@ -94,6 +94,11 @@ namespace sairedis _In_ const sai_stat_id_t *counter_ids, _Out_ uint64_t *counters) override; + virtual sai_status_t queryStatsCapability( + _In_ sai_object_id_t switch_id, + _In_ sai_object_type_t object_type, + _Inout_ sai_stat_capability_list_t *stats_capability) override; + virtual sai_status_t getStatsExt( _In_ sai_object_type_t object_type, _In_ sai_object_id_t object_id, diff --git a/meta/DummySaiInterface.cpp b/meta/DummySaiInterface.cpp index 671ba2dcf5ad..48148854731a 100644 --- a/meta/DummySaiInterface.cpp +++ b/meta/DummySaiInterface.cpp @@ -179,6 +179,16 @@ sai_status_t DummySaiInterface::getStats( return m_status; } +sai_status_t DummySaiInterface::queryStatsCapability( + _In_ sai_object_id_t switchId, + _In_ sai_object_type_t objectType, + _Inout_ sai_stat_capability_list_t *stats_capability) +{ + SWSS_LOG_ENTER(); + + return SAI_STATUS_NOT_IMPLEMENTED; +} + sai_status_t DummySaiInterface::getStatsExt( _In_ sai_object_type_t object_type, _In_ sai_object_id_t object_id, diff --git a/meta/DummySaiInterface.h b/meta/DummySaiInterface.h index 14bb89dab226..d40db5347677 100644 --- a/meta/DummySaiInterface.h +++ b/meta/DummySaiInterface.h @@ -98,6 +98,11 @@ namespace saimeta _In_ const sai_stat_id_t *counter_ids, _Out_ uint64_t *counters) override; + virtual sai_status_t queryStatsCapability( + _In_ sai_object_id_t switch_id, + _In_ sai_object_type_t object_type, + _Inout_ sai_stat_capability_list_t *stats_capability) override; + virtual sai_status_t getStatsExt( _In_ sai_object_type_t object_type, _In_ sai_object_id_t object_id, diff --git a/meta/Meta.cpp b/meta/Meta.cpp index bae66e7d0172..346d7201d089 100644 --- a/meta/Meta.cpp +++ b/meta/Meta.cpp @@ -1740,6 +1740,37 @@ sai_status_t Meta::meta_validate_stats( return SAI_STATUS_SUCCESS; } +sai_status_t Meta::meta_validate_query_stats_capability( + _In_ sai_object_type_t object_type, + _In_ sai_object_id_t object_id) +{ + SWSS_LOG_ENTER(); + + PARAMETER_CHECK_OBJECT_TYPE_VALID(object_type); + PARAMETER_CHECK_OID_OBJECT_TYPE(object_id, object_type); + PARAMETER_CHECK_OID_EXISTS(object_id, object_type); + + sai_object_id_t switch_id = switchIdQuery(object_id); + + // checks also if object type is OID + sai_status_t status = meta_sai_validate_oid(object_type, &object_id, switch_id, false); + + CHECK_STATUS_SUCCESS(status); + + auto info = sai_metadata_get_object_type_info(object_type); + + PARAMETER_CHECK_IF_NOT_NULL(info); + + if (info->statenum == nullptr) + { + SWSS_LOG_ERROR("%s does not support stats", info->objecttypename); + + return SAI_STATUS_INVALID_PARAMETER; + } + + return SAI_STATUS_SUCCESS; +} + sai_status_t Meta::getStats( _In_ sai_object_type_t object_type, _In_ sai_object_id_t object_id, @@ -1760,6 +1791,24 @@ sai_status_t Meta::getStats( return status; } +sai_status_t Meta::queryStatsCapability( + _In_ sai_object_id_t switchId, + _In_ sai_object_type_t objectType, + _Inout_ sai_stat_capability_list_t *stats_capability) +{ + SWSS_LOG_ENTER(); + + auto status = meta_validate_query_stats_capability(objectType, switchId); + + CHECK_STATUS_SUCCESS(status); + + status = m_implementation->queryStatsCapability(switchId, objectType, stats_capability); + + // no post validation required + + return status; +} + sai_status_t Meta::getStatsExt( _In_ sai_object_type_t object_type, _In_ sai_object_id_t object_id, diff --git a/meta/Meta.h b/meta/Meta.h index 22a9d066fcf2..2c928e8a645d 100644 --- a/meta/Meta.h +++ b/meta/Meta.h @@ -105,6 +105,11 @@ namespace saimeta _In_ const sai_stat_id_t *counter_ids, _Out_ uint64_t *counters) override; + virtual sai_status_t queryStatsCapability( + _In_ sai_object_id_t switch_id, + _In_ sai_object_type_t object_type, + _Inout_ sai_stat_capability_list_t *stats_capability) override; + virtual sai_status_t getStatsExt( _In_ sai_object_type_t object_type, _In_ sai_object_id_t object_id, @@ -394,6 +399,10 @@ namespace saimeta _Out_ uint64_t *counters, _In_ sai_stats_mode_t mode); + sai_status_t meta_validate_query_stats_capability( + _In_ sai_object_type_t object_type, + _In_ sai_object_id_t object_id); + private: // validate OID sai_status_t meta_sai_validate_oid( diff --git a/meta/SaiInterface.h b/meta/SaiInterface.h index 0b6dc5f1b8bd..fb8cdf0c423c 100644 --- a/meta/SaiInterface.h +++ b/meta/SaiInterface.h @@ -196,6 +196,11 @@ namespace sairedis _In_ const sai_stat_id_t *counter_ids, _Out_ uint64_t *counters) = 0; + virtual sai_status_t queryStatsCapability( + _In_ sai_object_id_t switch_id, + _In_ sai_object_type_t object_type, + _Inout_ sai_stat_capability_list_t *stats_capability) = 0; + virtual sai_status_t getStatsExt( _In_ sai_object_type_t object_type, _In_ sai_object_id_t object_id, diff --git a/syncd/FlexCounter.cpp b/syncd/FlexCounter.cpp index fd132b5368a0..679f03a6540a 100644 --- a/syncd/FlexCounter.cpp +++ b/syncd/FlexCounter.cpp @@ -7,6 +7,7 @@ #include "swss/tokenize.h" #include +#include using namespace syncd; @@ -1033,6 +1034,15 @@ bool FlexCounter::isBufferPoolCounterSupported( return m_supportedBufferPoolCounters.count(counter) != 0; } +bool FlexCounter::isStatsModeSupported( + _In_ uint32_t statsMode, + _In_ sai_stats_mode_t statCapability) +{ + SWSS_LOG_ENTER(); + + return statsMode & statCapability; +} + void FlexCounter::collectCounters( _In_ swss::Table &countersTable) { @@ -1757,15 +1767,52 @@ void FlexCounter::endFlexCounterThread(void) SWSS_LOG_INFO("Flex Counter thread ended"); } -void FlexCounter::updateSupportedPortCounters( +sai_status_t FlexCounter::querySupportedPortCounters( _In_ sai_object_id_t portRid) { SWSS_LOG_ENTER(); - if (m_supportedPortCounters.size()) + sai_stat_capability_list_t stats_capability; + stats_capability.count = 0; + stats_capability.list = nullptr; + + /* First call is to check the size needed to allocate */ + sai_status_t status = m_vendorSai->queryStatsCapability( + portRid, + SAI_OBJECT_TYPE_PORT, + &stats_capability); + + /* Second call is for query statistics capability */ + if (status == SAI_STATUS_BUFFER_OVERFLOW) { - return; + std::vector statCapabilityList(stats_capability.count); + stats_capability.list = statCapabilityList.data(); + status = m_vendorSai->queryStatsCapability( + portRid, + SAI_OBJECT_TYPE_PORT, + &stats_capability); + + if (status != SAI_STATUS_SUCCESS) + { + SWSS_LOG_INFO("Unable to get port supported counters for %s", + sai_serialize_object_id(portRid).c_str()); + } + else + { + for (auto statCapability: statCapabilityList) + { + sai_port_stat_t counter = static_cast(statCapability.stat_enum); + m_supportedPortCounters.insert(counter); + } + } } + return status; +} + +void FlexCounter::getSupportedPortCounters( + _In_ sai_object_id_t portRid) +{ + SWSS_LOG_ENTER(); uint64_t value; @@ -1789,6 +1836,25 @@ void FlexCounter::updateSupportedPortCounters( } } +void FlexCounter::updateSupportedPortCounters( + _In_ sai_object_id_t portRid) +{ + SWSS_LOG_ENTER(); + + if (m_supportedPortCounters.size()) + { + return; + } + + /* Query SAI supported port counters */ + sai_status_t status = querySupportedPortCounters(portRid); + if (status != SAI_STATUS_SUCCESS) + { + /* Fallback to legacy approach */ + getSupportedPortCounters(portRid); + } +} + std::vector FlexCounter::saiCheckSupportedPortDebugCounters( _In_ sai_object_id_t portId, _In_ const std::vector &counterIds) @@ -1831,7 +1897,54 @@ std::vector FlexCounter::saiCheckSupportedPortDebugCounters( return supportedPortDebugCounters; } -void FlexCounter::updateSupportedQueueCounters( +sai_status_t FlexCounter::querySupportedQueueCounters( + _In_ sai_object_id_t queueId) +{ + SWSS_LOG_ENTER(); + + sai_stat_capability_list_t stats_capability; + stats_capability.count = 0; + stats_capability.list = nullptr; + + /* First call is to check the size needed to allocate */ + sai_status_t status = m_vendorSai->queryStatsCapability( + queueId, + SAI_OBJECT_TYPE_QUEUE, + &stats_capability); + + /* Second call is for query statistics capability */ + if (status == SAI_STATUS_BUFFER_OVERFLOW) + { + std::vector statCapabilityList(stats_capability.count); + stats_capability.list = statCapabilityList.data(); + status = m_vendorSai->queryStatsCapability( + queueId, + SAI_OBJECT_TYPE_QUEUE, + &stats_capability); + + if (status != SAI_STATUS_SUCCESS) + { + SWSS_LOG_INFO("Unable to get queue supported counters for %s", + sai_serialize_object_id(queueId).c_str()); + } + else + { + for (auto statCapability: statCapabilityList) + { + auto currentStatModes = statCapability.stat_modes; + if (m_statsMode == SAI_STATS_MODE_READ_AND_CLEAR && !isStatsModeSupported(currentStatModes, SAI_STATS_MODE_READ_AND_CLEAR)) + { + continue; + } + sai_queue_stat_t counter = static_cast(statCapability.stat_enum); + m_supportedQueueCounters.insert(counter); + } + } + } + return status; +} + +void FlexCounter::getSupportedQueueCounters( _In_ sai_object_id_t queueId, _In_ const std::vector &counterIds) { @@ -1839,8 +1952,6 @@ void FlexCounter::updateSupportedQueueCounters( uint64_t value; - m_supportedQueueCounters.clear(); - for (auto &counter : counterIds) { sai_status_t status = m_vendorSai->getStats( @@ -1879,7 +1990,71 @@ void FlexCounter::updateSupportedQueueCounters( } } -void FlexCounter::updateSupportedPriorityGroupCounters( +void FlexCounter::updateSupportedQueueCounters( + _In_ sai_object_id_t queueId, + _In_ const std::vector &counterIds) +{ + SWSS_LOG_ENTER(); + + m_supportedQueueCounters.clear(); + + /* Query SAI supported queue counters */ + sai_status_t status = querySupportedQueueCounters(queueId); + if (status != SAI_STATUS_SUCCESS) + { + /* Fallback to legacy approach */ + getSupportedQueueCounters(queueId, counterIds); + } +} + +sai_status_t FlexCounter::querySupportedPriorityGroupCounters( + _In_ sai_object_id_t priorityGroupRid) +{ + SWSS_LOG_ENTER(); + + sai_stat_capability_list_t stats_capability; + stats_capability.count = 0; + stats_capability.list = nullptr; + + /* First call is to check the size needed to allocate */ + sai_status_t status = m_vendorSai->queryStatsCapability( + priorityGroupRid, + SAI_OBJECT_TYPE_INGRESS_PRIORITY_GROUP, + &stats_capability); + + /* Second call is for query statistics capability */ + if (status == SAI_STATUS_BUFFER_OVERFLOW) + { + std::vector statCapabilityList(stats_capability.count); + stats_capability.list = statCapabilityList.data(); + status = m_vendorSai->queryStatsCapability(priorityGroupRid, + SAI_OBJECT_TYPE_INGRESS_PRIORITY_GROUP, + &stats_capability); + + if (status != SAI_STATUS_SUCCESS) + { + SWSS_LOG_INFO("Unable to get priority group supported counters for %s", + sai_serialize_object_id(priorityGroupRid).c_str()); + } + else + { + + for (auto statCapability: statCapabilityList) + { + auto currentStatModes = statCapability.stat_modes; + if (m_statsMode == SAI_STATS_MODE_READ_AND_CLEAR && !isStatsModeSupported(currentStatModes, SAI_STATS_MODE_READ_AND_CLEAR)) + { + continue; + } + sai_ingress_priority_group_stat_t counter = static_cast(statCapability.stat_enum); + m_supportedPriorityGroupCounters.insert(counter); + } + } + } + return status; +} + +void FlexCounter::getSupportedPriorityGroupCounters( _In_ sai_object_id_t priorityGroupRid, _In_ const std::vector &counterIds) { @@ -1887,8 +2062,6 @@ void FlexCounter::updateSupportedPriorityGroupCounters( uint64_t value; - m_supportedPriorityGroupCounters.clear(); - for (auto &counter : counterIds) { sai_status_t status = m_vendorSai->getStats( @@ -1933,17 +2106,72 @@ void FlexCounter::updateSupportedPriorityGroupCounters( } } -void FlexCounter::updateSupportedRifCounters( +void FlexCounter::updateSupportedPriorityGroupCounters( + _In_ sai_object_id_t priorityGroupRid, + _In_ const std::vector &counterIds) +{ + SWSS_LOG_ENTER(); + + m_supportedPriorityGroupCounters.clear(); + + /* Query SAI supported priority group counters */ + sai_status_t status = querySupportedPriorityGroupCounters(priorityGroupRid); + if (status != SAI_STATUS_SUCCESS) + { + /* Fallback to legacy approach */ + getSupportedPriorityGroupCounters(priorityGroupRid, counterIds); + } +} + +sai_status_t FlexCounter::querySupportedRifCounters( _In_ sai_object_id_t rifRid) { SWSS_LOG_ENTER(); - if (m_supportedRifCounters.size()) + sai_stat_capability_list_t stats_capability; + stats_capability.count = 0; + stats_capability.list = nullptr; + + /* First call is to check the size needed to allocate */ + sai_status_t status = m_vendorSai->queryStatsCapability( + rifRid, + SAI_OBJECT_TYPE_ROUTER_INTERFACE, + &stats_capability); + + /* Second call is for query statistics capability */ + if (status == SAI_STATUS_BUFFER_OVERFLOW) { - return; + std::vector statCapabilityList(stats_capability.count); + stats_capability.list = statCapabilityList.data(); + status = m_vendorSai->queryStatsCapability( + rifRid, + SAI_OBJECT_TYPE_ROUTER_INTERFACE, + &stats_capability); + + if (status != SAI_STATUS_SUCCESS) + { + SWSS_LOG_INFO("Unable to get routed port supported counters for %s", + sai_serialize_object_id(rifRid).c_str()); + } + else + { + for (auto statCapability: statCapabilityList) + { + sai_router_interface_stat_t counter = static_cast(statCapability.stat_enum); + m_supportedRifCounters.insert(counter); + } + } } + return status; +} + +void FlexCounter::getSupportedRifCounters( + _In_ sai_object_id_t rifRid) +{ + SWSS_LOG_ENTER(); uint64_t value; + for (int cntr_id = SAI_ROUTER_INTERFACE_STAT_IN_OCTETS; cntr_id <= SAI_ROUTER_INTERFACE_STAT_OUT_ERROR_PACKETS; ++cntr_id) { sai_router_interface_stat_t counter = static_cast(cntr_id); @@ -1969,7 +2197,75 @@ void FlexCounter::updateSupportedRifCounters( } } -void FlexCounter::updateSupportedBufferPoolCounters( +void FlexCounter::updateSupportedRifCounters( + _In_ sai_object_id_t rifRid) +{ + SWSS_LOG_ENTER(); + + if (m_supportedRifCounters.size()) + { + return; + } + + /* Query SAI supported rif counters */ + sai_status_t status = querySupportedRifCounters(rifRid); + if (status != SAI_STATUS_SUCCESS) + { + /* Fallback to legacy approach */ + getSupportedRifCounters(rifRid); + } +} + +sai_status_t FlexCounter::querySupportedBufferPoolCounters( + _In_ sai_object_id_t bufferPoolId, + _In_ sai_stats_mode_t statsMode) +{ + SWSS_LOG_ENTER(); + + sai_stat_capability_list_t stats_capability; + stats_capability.count = 0; + stats_capability.list = nullptr; + + /* First call is to check the size needed to allocate */ + sai_status_t status = m_vendorSai->queryStatsCapability( + bufferPoolId, + SAI_OBJECT_TYPE_BUFFER_POOL, + &stats_capability); + + /* Second call is for query statistics capability */ + if (status == SAI_STATUS_BUFFER_OVERFLOW) + { + std::vector statCapabilityList(stats_capability.count); + stats_capability.list = statCapabilityList.data(); + status = m_vendorSai->queryStatsCapability( + bufferPoolId, + SAI_OBJECT_TYPE_BUFFER_POOL, + &stats_capability); + + if (status != SAI_STATUS_SUCCESS) + { + SWSS_LOG_INFO("Unable to get buffer pool supported counters for %s", + sai_serialize_object_id(bufferPoolId).c_str()); + } + else + { + for (auto statCapability: statCapabilityList) + { + auto currentStatModes = statCapability.stat_modes; + if ((m_statsMode == SAI_STATS_MODE_READ_AND_CLEAR || statsMode == SAI_STATS_MODE_READ_AND_CLEAR) && + !isStatsModeSupported(currentStatModes, SAI_STATS_MODE_READ_AND_CLEAR)) + { + continue; + } + sai_buffer_pool_stat_t counter = static_cast(statCapability.stat_enum); + m_supportedBufferPoolCounters.insert(counter); + } + } + } + return status; +} + +void FlexCounter::getSupportedBufferPoolCounters( _In_ sai_object_id_t bufferPoolId, _In_ const std::vector &counterIds, _In_ sai_stats_mode_t statsMode) @@ -1977,7 +2273,6 @@ void FlexCounter::updateSupportedBufferPoolCounters( SWSS_LOG_ENTER(); uint64_t value; - m_supportedBufferPoolCounters.clear(); for (const auto &counterId : counterIds) { @@ -2023,6 +2318,24 @@ void FlexCounter::updateSupportedBufferPoolCounters( } } +void FlexCounter::updateSupportedBufferPoolCounters( + _In_ sai_object_id_t bufferPoolId, + _In_ const std::vector &counterIds, + _In_ sai_stats_mode_t statsMode) +{ + SWSS_LOG_ENTER(); + + m_supportedBufferPoolCounters.clear(); + + /* Query SAI supported buffer pool counters */ + sai_status_t status = querySupportedBufferPoolCounters(bufferPoolId, statsMode); + if (status != SAI_STATUS_SUCCESS) + { + /* Fallback to legacy approach */ + getSupportedBufferPoolCounters(bufferPoolId, counterIds, statsMode); + } +} + std::vector FlexCounter::saiCheckSupportedSwitchDebugCounters( _In_ sai_object_id_t switchId, _In_ const std::vector &counterIds) diff --git a/syncd/FlexCounter.h b/syncd/FlexCounter.h index 4a30cf6c95ee..58483bb7df63 100644 --- a/syncd/FlexCounter.h +++ b/syncd/FlexCounter.h @@ -185,8 +185,18 @@ namespace syncd bool isBufferPoolCounterSupported( _In_ sai_buffer_pool_stat_t counter) const; + bool isStatsModeSupported( + _In_ uint32_t statsMode, + _In_ sai_stats_mode_t statCapability); + private: // update supported counters + sai_status_t querySupportedPortCounters( + _In_ sai_object_id_t portRid); + + void getSupportedPortCounters( + _In_ sai_object_id_t portRid); + void updateSupportedPortCounters( _In_ sai_object_id_t portRid); @@ -194,18 +204,46 @@ namespace syncd _In_ sai_object_id_t portRid, _In_ const std::vector &counterIds); + sai_status_t querySupportedQueueCounters( + _In_ sai_object_id_t queueId); + + void getSupportedQueueCounters( + _In_ sai_object_id_t queueId, const std::vector &counterIds); + void updateSupportedQueueCounters( _In_ sai_object_id_t queueRid, _In_ const std::vector &counterIds); + sai_status_t querySupportedRifCounters( + _In_ sai_object_id_t rifRid); + + void getSupportedRifCounters( + _In_ sai_object_id_t rifRid); + void updateSupportedRifCounters( _In_ sai_object_id_t rifRid); + sai_status_t querySupportedBufferPoolCounters( + _In_ sai_object_id_t bufferPoolId, + _In_ sai_stats_mode_t statsMode); + + void getSupportedBufferPoolCounters( + _In_ sai_object_id_t bufferPoolId, + _In_ const std::vector &counterIds, + _In_ sai_stats_mode_t statsMode); + void updateSupportedBufferPoolCounters( _In_ sai_object_id_t bufferPoolRid, _In_ const std::vector &counterIds, _In_ sai_stats_mode_t statsMode); + sai_status_t querySupportedPriorityGroupCounters( + _In_ sai_object_id_t priorityGroupRid); + + void getSupportedPriorityGroupCounters( + _In_ sai_object_id_t priorityGroupRid, + _In_ const std::vector &counterIds); + void updateSupportedPriorityGroupCounters( _In_ sai_object_id_t priorityGroupRid, _In_ const std::vector &counterIds); diff --git a/syncd/VendorSai.cpp b/syncd/VendorSai.cpp index d0ebefdd609e..f7e467eb8e32 100644 --- a/syncd/VendorSai.cpp +++ b/syncd/VendorSai.cpp @@ -427,6 +427,21 @@ sai_status_t VendorSai::getStats( return ptr(object_id, number_of_counters, counter_ids, counters); } +sai_status_t VendorSai::queryStatsCapability( + _In_ sai_object_id_t switchId, + _In_ sai_object_type_t objectType, + _Inout_ sai_stat_capability_list_t *stats_capability) +{ + MUTEX(); + SWSS_LOG_ENTER(); + VENDOR_CHECK_API_INITIALIZED(); + + return sai_query_stats_capability( + switchId, + objectType, + stats_capability); +} + sai_status_t VendorSai::getStatsExt( _In_ sai_object_type_t object_type, _In_ sai_object_id_t object_id, diff --git a/syncd/VendorSai.h b/syncd/VendorSai.h index cc6f7746ed52..091a2afda51b 100644 --- a/syncd/VendorSai.h +++ b/syncd/VendorSai.h @@ -95,6 +95,11 @@ namespace syncd _In_ const sai_stat_id_t *counter_ids, _Out_ uint64_t *counters) override; + virtual sai_status_t queryStatsCapability( + _In_ sai_object_id_t switch_id, + _In_ sai_object_type_t object_type, + _Inout_ sai_stat_capability_list_t *stats_capability) override; + virtual sai_status_t getStatsExt( _In_ sai_object_type_t object_type, _In_ sai_object_id_t object_id, diff --git a/vslib/Sai.cpp b/vslib/Sai.cpp index 09558f643f8a..79262ef8f4f5 100644 --- a/vslib/Sai.cpp +++ b/vslib/Sai.cpp @@ -466,6 +466,21 @@ sai_status_t Sai::getStats( counters); } +sai_status_t Sai::queryStatsCapability( + _In_ sai_object_id_t switchId, + _In_ sai_object_type_t objectType, + _Inout_ sai_stat_capability_list_t *stats_capability) +{ + MUTEX(); + SWSS_LOG_ENTER(); + VS_CHECK_API_INITIALIZED(); + + return m_meta->queryStatsCapability( + switchId, + objectType, + stats_capability); +} + sai_status_t Sai::getStatsExt( _In_ sai_object_type_t object_type, _In_ sai_object_id_t object_id, diff --git a/vslib/Sai.h b/vslib/Sai.h index 86c186c8934a..7af8e39c14b7 100644 --- a/vslib/Sai.h +++ b/vslib/Sai.h @@ -103,6 +103,11 @@ namespace saivs _In_ const sai_stat_id_t *counter_ids, _Out_ uint64_t *counters) override; + virtual sai_status_t queryStatsCapability( + _In_ sai_object_id_t switch_id, + _In_ sai_object_type_t object_type, + _Inout_ sai_stat_capability_list_t *stats_capability) override; + virtual sai_status_t getStatsExt( _In_ sai_object_type_t object_type, _In_ sai_object_id_t object_id, diff --git a/vslib/SwitchState.cpp b/vslib/SwitchState.cpp index fe42c5c45fe5..589eb6445087 100644 --- a/vslib/SwitchState.cpp +++ b/vslib/SwitchState.cpp @@ -278,6 +278,35 @@ sai_status_t SwitchState::getStatsExt( return SAI_STATUS_SUCCESS; } +sai_status_t SwitchState::queryStatsCapability( + _In_ sai_object_id_t switchId, + _In_ sai_object_type_t objectType, + _Inout_ sai_stat_capability_list_t *stats_capability) +{ + SWSS_LOG_ENTER(); + + auto info = sai_metadata_get_object_type_info(objectType); + + if (stats_capability->count == 0 || stats_capability->list == nullptr) + { + stats_capability->count = (uint32_t)info->statenum->valuescount; + return SAI_STATUS_BUFFER_OVERFLOW; + } + + SWSS_LOG_NOTICE("query counter capability for object ID %s of counter type %s", + sai_serialize_object_id(switchId).c_str(), + info->statenum->name); + + auto statenumlist = info->statenum->values; + + for (uint32_t i = 0; i < stats_capability->count; i++) + { + stats_capability->list[i].stat_enum = statenumlist[i]; + stats_capability->list[i].stat_modes = SAI_STATS_MODE_READ_AND_CLEAR; + } + return SAI_STATUS_SUCCESS; +} + std::shared_ptr SwitchState::getMeta() { SWSS_LOG_ENTER(); diff --git a/vslib/SwitchState.h b/vslib/SwitchState.h index 204aa814bffe..01c435a73ad4 100644 --- a/vslib/SwitchState.h +++ b/vslib/SwitchState.h @@ -56,6 +56,11 @@ namespace saivs _In_ sai_stats_mode_t mode, _Out_ uint64_t *counters); + sai_status_t queryStatsCapability( + _In_ sai_object_id_t switchId, + _In_ sai_object_type_t objectType, + _Inout_ sai_stat_capability_list_t *stats_capability); + public: sai_object_id_t getSwitchId() const; diff --git a/vslib/VirtualSwitchSaiInterface.cpp b/vslib/VirtualSwitchSaiInterface.cpp index bffdf069f526..77d81417d343 100644 --- a/vslib/VirtualSwitchSaiInterface.cpp +++ b/vslib/VirtualSwitchSaiInterface.cpp @@ -863,6 +863,28 @@ sai_status_t VirtualSwitchSaiInterface::getStats( counters); } +sai_status_t VirtualSwitchSaiInterface::queryStatsCapability( + _In_ sai_object_id_t switchId, + _In_ sai_object_type_t objectType, + _Inout_ sai_stat_capability_list_t *stats_capability) +{ + SWSS_LOG_ENTER(); + + if (m_switchStateMap.find(switchId) == m_switchStateMap.end()) + { + SWSS_LOG_ERROR("failed to find switch %s in switch state map", sai_serialize_object_id(switchId).c_str()); + + return SAI_STATUS_FAILURE; + } + + auto ss = m_switchStateMap.at(switchId); + + return ss->queryStatsCapability( + switchId, + objectType, + stats_capability); +} + sai_status_t VirtualSwitchSaiInterface::getStatsExt( _In_ sai_object_type_t object_type, _In_ sai_object_id_t object_id, diff --git a/vslib/VirtualSwitchSaiInterface.h b/vslib/VirtualSwitchSaiInterface.h index 518def4d2ef1..dc5d32c27131 100644 --- a/vslib/VirtualSwitchSaiInterface.h +++ b/vslib/VirtualSwitchSaiInterface.h @@ -102,6 +102,11 @@ namespace saivs _In_ const sai_stat_id_t *counter_ids, _Out_ uint64_t *counters) override; + virtual sai_status_t queryStatsCapability( + _In_ sai_object_id_t switch_id, + _In_ sai_object_type_t object_type, + _Inout_ sai_stat_capability_list_t *stats_capability) override; + virtual sai_status_t getStatsExt( _In_ sai_object_type_t object_type, _In_ sai_object_id_t object_id, diff --git a/vslib/sai_vs_interfacequery.cpp b/vslib/sai_vs_interfacequery.cpp index a42b8021ae84..42b9fa468921 100644 --- a/vslib/sai_vs_interfacequery.cpp +++ b/vslib/sai_vs_interfacequery.cpp @@ -182,3 +182,13 @@ sai_object_id_t sai_switch_id_query( return vs_sai->switchIdQuery(objectId); } + +sai_status_t sai_query_stats_capability( + _In_ sai_object_id_t switch_id, + _In_ sai_object_type_t object_type, + _Inout_ sai_stat_capability_list_t *stats_capability) +{ + SWSS_LOG_ENTER(); + + return vs_sai->queryStatsCapability(switch_id, object_type, stats_capability); +}