diff --git a/syncd/FlexCounter.cpp b/syncd/FlexCounter.cpp index 679f03a6540a..929eb78600d0 100644 --- a/syncd/FlexCounter.cpp +++ b/syncd/FlexCounter.cpp @@ -114,6 +114,16 @@ FlexCounter::MACsecSAAttrIds::MACsecSAAttrIds( // empty intentionally } +FlexCounter::TunnelCounterIds::TunnelCounterIds( + _In_ sai_object_id_t tunnelRid, + _In_ const std::vector &tunnelIds): + m_tunnelId(tunnelRid), + m_tunnelCounterIds(tunnelIds) +{ + SWSS_LOG_ENTER(); + // empty intentionally +} + void FlexCounter::setPollInterval( _In_ uint32_t pollInterval) { @@ -567,6 +577,47 @@ void FlexCounter::setBufferPoolCounterList( addCollectCountersHandler(BUFFER_POOL_COUNTER_ID_LIST, &FlexCounter::collectBufferPoolCounters); } +void FlexCounter::setTunnelCounterList( + _In_ sai_object_id_t tunnelVid, + _In_ sai_object_id_t tunnelRid, + _In_ const std::vector &counterIds) +{ + SWSS_LOG_ENTER(); + + updateSupportedTunnelCounters(tunnelRid, counterIds); + + // Remove unsupported counters + std::vector supportedIds; + + for (auto &counter : counterIds) + { + if (isTunnelCounterSupported(counter)) + { + supportedIds.push_back(counter); + } + } + + if (supportedIds.empty()) + { + SWSS_LOG_NOTICE("Tunnel %s does not have supported counters", sai_serialize_object_id(tunnelRid).c_str()); + return; + } + + auto it = m_tunnelCounterIdsMap.find(tunnelVid); + + if (it != m_tunnelCounterIdsMap.end()) + { + it->second->m_tunnelCounterIds = supportedIds; + return; + } + + auto tunnelCounterIds = std::make_shared(tunnelRid, supportedIds); + + m_tunnelCounterIdsMap.emplace(tunnelVid, tunnelCounterIds); + + addCollectCountersHandler(TUNNEL_COUNTER_ID_LIST, &FlexCounter::collectTunnelCounters); +} + void FlexCounter::removePort( _In_ sai_object_id_t portVid) { @@ -787,6 +838,27 @@ void FlexCounter::removeSwitchDebugCounters( } } +void FlexCounter::removeTunnel( + _In_ sai_object_id_t tunnelVid) +{ + SWSS_LOG_ENTER(); + + auto it = m_tunnelCounterIdsMap.find(tunnelVid); + + if (it == m_tunnelCounterIdsMap.end()) + { + SWSS_LOG_NOTICE("Trying to remove nonexisting tunnel counter from Id 0x%" PRIx64, tunnelVid); + return; + } + + m_tunnelCounterIdsMap.erase(it); + + if (m_tunnelCounterIdsMap.empty()) + { + removeCollectCountersHandler(TUNNEL_COUNTER_ID_LIST); + } +} + void FlexCounter::checkPluginRegistered( _In_ const std::string& sha) const { @@ -797,7 +869,8 @@ void FlexCounter::checkPluginRegistered( m_rifPlugins.find(sha) != m_rifPlugins.end() || m_queuePlugins.find(sha) != m_queuePlugins.end() || m_priorityGroupPlugins.find(sha) != m_priorityGroupPlugins.end() || - m_bufferPoolPlugins.find(sha) != m_bufferPoolPlugins.end() + m_bufferPoolPlugins.find(sha) != m_bufferPoolPlugins.end() || + m_tunnelPlugins.find(sha) != m_tunnelPlugins.end() ) { SWSS_LOG_ERROR("Plugin %s already registered", sha.c_str()); @@ -864,6 +937,18 @@ void FlexCounter::addBufferPoolCounterPlugin( SWSS_LOG_NOTICE("Buffer pool counters plugin %s registered", sha.c_str()); } +void FlexCounter::addTunnelCounterPlugin( + _In_ const std::string& sha) +{ + SWSS_LOG_ENTER(); + + checkPluginRegistered(sha); + + m_tunnelPlugins.insert(sha); + + SWSS_LOG_NOTICE("Tunnel counters plugin %s registered", sha.c_str()); +} + void FlexCounter::removeCounterPlugins() { MUTEX; @@ -875,6 +960,7 @@ void FlexCounter::removeCounterPlugins() m_rifPlugins.clear(); m_priorityGroupPlugins.clear(); m_bufferPoolPlugins.clear(); + m_tunnelPlugins.clear(); m_isDiscarded = true; } @@ -942,6 +1028,13 @@ void FlexCounter::addCounterPlugin( addBufferPoolCounterPlugin(sha); } } + else if (field == TUNNEL_PLUGIN_FIELD) + { + for (auto& sha: shaStrings) + { + addTunnelCounterPlugin(sha); + } + } else { SWSS_LOG_ERROR("Field is not supported %s", field.c_str()); @@ -981,7 +1074,8 @@ bool FlexCounter::allIdsEmpty() const m_rifCounterIdsMap.empty() && m_bufferPoolCounterIdsMap.empty() && m_switchDebugCounterIdsMap.empty() && - m_macsecSAAttrIdsMap.empty(); + m_macsecSAAttrIdsMap.empty() && + m_tunnelCounterIdsMap.empty(); } bool FlexCounter::allPluginsEmpty() const @@ -992,7 +1086,8 @@ bool FlexCounter::allPluginsEmpty() const m_queuePlugins.empty() && m_portPlugins.empty() && m_rifPlugins.empty() && - m_bufferPoolPlugins.empty(); + m_bufferPoolPlugins.empty() && + m_tunnelPlugins.empty(); } bool FlexCounter::isPortCounterSupported(sai_port_stat_t counter) const @@ -1034,6 +1129,14 @@ bool FlexCounter::isBufferPoolCounterSupported( return m_supportedBufferPoolCounters.count(counter) != 0; } +bool FlexCounter::isTunnelCounterSupported( + _In_ sai_tunnel_stat_t counter) const +{ + SWSS_LOG_ENTER(); + + return m_supportedTunnelCounters.count(counter) != 0; +} + bool FlexCounter::isStatsModeSupported( _In_ uint32_t statsMode, _In_ sai_stats_mode_t statCapability) @@ -1597,6 +1700,51 @@ void FlexCounter::collectBufferPoolCounters( } } +void FlexCounter::collectTunnelCounters( + _In_ swss::Table &countersTable) +{ + SWSS_LOG_ENTER(); + + // Collect stats for every registered tunnel + for (const auto &kv: m_tunnelCounterIdsMap) + { + const auto &tunnelVid = kv.first; + const auto &tunnelId = kv.second->m_tunnelId; + const auto &tunnelCounterIds = kv.second->m_tunnelCounterIds; + + std::vector tunnelStats(tunnelCounterIds.size()); + + // Get tunnel stats + sai_status_t status = m_vendorSai->getStats( + SAI_OBJECT_TYPE_TUNNEL, + tunnelId, + static_cast(tunnelCounterIds.size()), + (const sai_stat_id_t *)tunnelCounterIds.data(), + tunnelStats.data()); + + if (status != SAI_STATUS_SUCCESS) + { + SWSS_LOG_ERROR("Failed to get stats of tunnel 0x%" PRIx64 ": %d", tunnelId, status); + continue; + } + + // Push all counter values to a single vector + std::vector values; + + for (size_t i = 0; i != tunnelCounterIds.size(); i++) + { + const std::string &counterName = sai_serialize_tunnel_stat(tunnelCounterIds[i]); + + values.emplace_back(counterName, std::to_string(tunnelStats[i])); + } + + // Write counters to DB + std::string tunnelVidStr = sai_serialize_object_id(tunnelVid); + + countersTable.set(tunnelVidStr, values, ""); + } +} + void FlexCounter::runPlugins( _In_ swss::DBConnector& counters_db) { @@ -1675,6 +1823,17 @@ void FlexCounter::runPlugins( { runRedisScript(counters_db, sha, bufferPoolVids, argv); } + + std::vector tunnelList; + tunnelList.reserve(m_tunnelCounterIdsMap.size()); + for (const auto& kv : m_tunnelCounterIdsMap) + { + tunnelList.push_back(sai_serialize_object_id(kv.first)); + } + for (const auto& sha : m_tunnelPlugins) + { + runRedisScript(counters_db, sha, tunnelList, argv); + } } void FlexCounter::flexCounterThreadRunFunction() @@ -2318,6 +2477,41 @@ void FlexCounter::getSupportedBufferPoolCounters( } } +void FlexCounter::updateSupportedTunnelCounters( + _In_ sai_object_id_t tunnelRid, + _In_ const std::vector &counterIds) +{ + SWSS_LOG_ENTER(); + + if (m_supportedTunnelCounters.size()) + { + return; + } + + uint64_t value; + for (auto &counter: counterIds) + { + sai_status_t status = m_vendorSai->getStats( + SAI_OBJECT_TYPE_TUNNEL, + tunnelRid, + 1, + (const sai_stat_id_t *)&counter, + &value); + + if (status != SAI_STATUS_SUCCESS) + { + SWSS_LOG_INFO("Counter %s is not supported on tunnel RID %s: %s", + sai_serialize_tunnel_stat(counter).c_str(), + sai_serialize_object_id(tunnelRid).c_str(), + sai_serialize_status(status).c_str()); + + continue; + } + + m_supportedTunnelCounters.insert(counter); + } +} + void FlexCounter::updateSupportedBufferPoolCounters( _In_ sai_object_id_t bufferPoolId, _In_ const std::vector &counterIds, @@ -2413,6 +2607,10 @@ void FlexCounter::removeCounter( { removeMACsecSA(vid); } + else if (objectType == SAI_OBJECT_TYPE_TUNNEL) + { + removeTunnel(vid); + } else { SWSS_LOG_ERROR("Object type for removal not supported, %s", @@ -2568,6 +2766,19 @@ void FlexCounter::addCounter( { statsMode = value; } + else if (objectType == SAI_OBJECT_TYPE_TUNNEL && field == TUNNEL_COUNTER_ID_LIST) + { + std::vector tunnelCounterIds; + + for (const auto &str : idStrings) + { + sai_tunnel_stat_t stat; + sai_deserialize_tunnel_stat(str.c_str(), &stat); + tunnelCounterIds.push_back(stat); + } + + setTunnelCounterList(vid, rid, tunnelCounterIds); + } else { SWSS_LOG_ERROR("Object type and field combination is not supported, object type %s, field %s", diff --git a/syncd/FlexCounter.h b/syncd/FlexCounter.h index 58483bb7df63..3f302798d87f 100644 --- a/syncd/FlexCounter.h +++ b/syncd/FlexCounter.h @@ -78,6 +78,8 @@ namespace syncd void addQueueCounterPlugin( _In_ const std::string& sha); + void addTunnelCounterPlugin( + _In_ const std::string& sha); private: void checkPluginRegistered( @@ -113,6 +115,9 @@ namespace syncd void removeMACsecSA( _In_ sai_object_id_t macsecSAVid); + void removeTunnel( + _In_ sai_object_id_t tunnelVid); + private: // set counter list void setPortCounterList( @@ -151,6 +156,11 @@ namespace syncd _In_ const std::vector& counterIds, _In_ const std::string& statsMode); + void setTunnelCounterList( + _In_ sai_object_id_t tunnelVid, + _In_ sai_object_id_t tunnelRid, + _In_ const std::vector &counterIds); + private: // set attr list void setQueueAttrList( @@ -185,6 +195,9 @@ namespace syncd bool isBufferPoolCounterSupported( _In_ sai_buffer_pool_stat_t counter) const; + bool isTunnelCounterSupported( + _In_ sai_tunnel_stat_t counter) const; + bool isStatsModeSupported( _In_ uint32_t statsMode, _In_ sai_stats_mode_t statCapability); @@ -252,6 +265,9 @@ namespace syncd _In_ sai_object_id_t switchRid, _In_ const std::vector &counterIds); + void updateSupportedTunnelCounters( + _In_ sai_object_id_t tunnelRid, + _In_ const std::vector &counterIds); private: struct QueueCounterIds @@ -346,6 +362,15 @@ namespace syncd std::vector m_macsecSAAttrIds; }; + struct TunnelCounterIds + { + TunnelCounterIds( + _In_ sai_object_id_t tunnel, + _In_ const std::vector &tunnelIds); + + sai_object_id_t m_tunnelId; + std::vector m_tunnelCounterIds; + }; private: void collectCounters( @@ -390,6 +415,9 @@ namespace syncd void collectSwitchDebugCounters( _In_ swss::Table &countersTable); + void collectTunnelCounters( + _In_ swss::Table &countersTable); + private: // collect attributes void collectQueueAttrs( @@ -417,6 +445,7 @@ namespace syncd std::set m_rifPlugins; std::set m_priorityGroupPlugins; std::set m_bufferPoolPlugins; + std::set m_tunnelPlugins; private: // supported counters @@ -425,6 +454,7 @@ namespace syncd std::set m_supportedQueueCounters; std::set m_supportedRifCounters; std::set m_supportedBufferPoolCounters; + std::set m_supportedTunnelCounters; private: // registered VID maps @@ -435,6 +465,7 @@ namespace syncd std::map> m_rifCounterIdsMap; std::map> m_bufferPoolCounterIdsMap; std::map> m_switchDebugCounterIdsMap; + std::map> m_tunnelCounterIdsMap; std::map> m_queueAttrIdsMap; std::map> m_priorityGroupAttrIdsMap;