@@ -114,6 +114,16 @@ FlexCounter::MACsecSAAttrIds::MACsecSAAttrIds(
114114 // empty intentionally
115115}
116116
117+ FlexCounter::TunnelCounterIds::TunnelCounterIds (
118+ _In_ sai_object_id_t tunnelRid,
119+ _In_ const std::vector<sai_tunnel_stat_t > &tunnelIds):
120+ m_tunnelId(tunnelRid),
121+ m_tunnelCounterIds(tunnelIds)
122+ {
123+ SWSS_LOG_ENTER ();
124+ // empty intentionally
125+ }
126+
117127void FlexCounter::setPollInterval (
118128 _In_ uint32_t pollInterval)
119129{
@@ -567,6 +577,47 @@ void FlexCounter::setBufferPoolCounterList(
567577 addCollectCountersHandler (BUFFER_POOL_COUNTER_ID_LIST, &FlexCounter::collectBufferPoolCounters);
568578}
569579
580+ void FlexCounter::setTunnelCounterList (
581+ _In_ sai_object_id_t tunnelVid,
582+ _In_ sai_object_id_t tunnelRid,
583+ _In_ const std::vector<sai_tunnel_stat_t > &counterIds)
584+ {
585+ SWSS_LOG_ENTER ();
586+
587+ updateSupportedTunnelCounters (tunnelRid, counterIds);
588+
589+ // Remove unsupported counters
590+ std::vector<sai_tunnel_stat_t > supportedIds;
591+
592+ for (auto &counter : counterIds)
593+ {
594+ if (isTunnelCounterSupported (counter))
595+ {
596+ supportedIds.push_back (counter);
597+ }
598+ }
599+
600+ if (supportedIds.empty ())
601+ {
602+ SWSS_LOG_NOTICE (" Tunnel %s does not have supported counters" , sai_serialize_object_id (tunnelRid).c_str ());
603+ return ;
604+ }
605+
606+ auto it = m_tunnelCounterIdsMap.find (tunnelVid);
607+
608+ if (it != m_tunnelCounterIdsMap.end ())
609+ {
610+ it->second ->m_tunnelCounterIds = supportedIds;
611+ return ;
612+ }
613+
614+ auto tunnelCounterIds = std::make_shared<TunnelCounterIds>(tunnelRid, supportedIds);
615+
616+ m_tunnelCounterIdsMap.emplace (tunnelVid, tunnelCounterIds);
617+
618+ addCollectCountersHandler (TUNNEL_COUNTER_ID_LIST, &FlexCounter::collectTunnelCounters);
619+ }
620+
570621void FlexCounter::removePort (
571622 _In_ sai_object_id_t portVid)
572623{
@@ -787,6 +838,27 @@ void FlexCounter::removeSwitchDebugCounters(
787838 }
788839}
789840
841+ void FlexCounter::removeTunnel (
842+ _In_ sai_object_id_t tunnelVid)
843+ {
844+ SWSS_LOG_ENTER ();
845+
846+ auto it = m_tunnelCounterIdsMap.find (tunnelVid);
847+
848+ if (it == m_tunnelCounterIdsMap.end ())
849+ {
850+ SWSS_LOG_NOTICE (" Trying to remove nonexisting tunnel counter from Id 0x%" PRIx64, tunnelVid);
851+ return ;
852+ }
853+
854+ m_tunnelCounterIdsMap.erase (it);
855+
856+ if (m_tunnelCounterIdsMap.empty ())
857+ {
858+ removeCollectCountersHandler (TUNNEL_COUNTER_ID_LIST);
859+ }
860+ }
861+
790862void FlexCounter::checkPluginRegistered (
791863 _In_ const std::string& sha) const
792864{
@@ -797,7 +869,8 @@ void FlexCounter::checkPluginRegistered(
797869 m_rifPlugins.find (sha) != m_rifPlugins.end () ||
798870 m_queuePlugins.find (sha) != m_queuePlugins.end () ||
799871 m_priorityGroupPlugins.find (sha) != m_priorityGroupPlugins.end () ||
800- m_bufferPoolPlugins.find (sha) != m_bufferPoolPlugins.end ()
872+ m_bufferPoolPlugins.find (sha) != m_bufferPoolPlugins.end () ||
873+ m_tunnelPlugins.find (sha) != m_tunnelPlugins.end ()
801874 )
802875 {
803876 SWSS_LOG_ERROR (" Plugin %s already registered" , sha.c_str ());
@@ -864,6 +937,18 @@ void FlexCounter::addBufferPoolCounterPlugin(
864937 SWSS_LOG_NOTICE (" Buffer pool counters plugin %s registered" , sha.c_str ());
865938}
866939
940+ void FlexCounter::addTunnelCounterPlugin (
941+ _In_ const std::string& sha)
942+ {
943+ SWSS_LOG_ENTER ();
944+
945+ checkPluginRegistered (sha);
946+
947+ m_tunnelPlugins.insert (sha);
948+
949+ SWSS_LOG_NOTICE (" Tunnel counters plugin %s registered" , sha.c_str ());
950+ }
951+
867952void FlexCounter::removeCounterPlugins ()
868953{
869954 MUTEX;
@@ -875,6 +960,7 @@ void FlexCounter::removeCounterPlugins()
875960 m_rifPlugins.clear ();
876961 m_priorityGroupPlugins.clear ();
877962 m_bufferPoolPlugins.clear ();
963+ m_tunnelPlugins.clear ();
878964
879965 m_isDiscarded = true ;
880966}
@@ -942,6 +1028,13 @@ void FlexCounter::addCounterPlugin(
9421028 addBufferPoolCounterPlugin (sha);
9431029 }
9441030 }
1031+ else if (field == TUNNEL_PLUGIN_FIELD)
1032+ {
1033+ for (auto & sha: shaStrings)
1034+ {
1035+ addTunnelCounterPlugin (sha);
1036+ }
1037+ }
9451038 else
9461039 {
9471040 SWSS_LOG_ERROR (" Field is not supported %s" , field.c_str ());
@@ -981,7 +1074,8 @@ bool FlexCounter::allIdsEmpty() const
9811074 m_rifCounterIdsMap.empty () &&
9821075 m_bufferPoolCounterIdsMap.empty () &&
9831076 m_switchDebugCounterIdsMap.empty () &&
984- m_macsecSAAttrIdsMap.empty ();
1077+ m_macsecSAAttrIdsMap.empty () &&
1078+ m_tunnelCounterIdsMap.empty ();
9851079}
9861080
9871081bool FlexCounter::allPluginsEmpty () const
@@ -992,7 +1086,8 @@ bool FlexCounter::allPluginsEmpty() const
9921086 m_queuePlugins.empty () &&
9931087 m_portPlugins.empty () &&
9941088 m_rifPlugins.empty () &&
995- m_bufferPoolPlugins.empty ();
1089+ m_bufferPoolPlugins.empty () &&
1090+ m_tunnelPlugins.empty ();
9961091}
9971092
9981093bool FlexCounter::isPortCounterSupported (sai_port_stat_t counter) const
@@ -1034,6 +1129,14 @@ bool FlexCounter::isBufferPoolCounterSupported(
10341129 return m_supportedBufferPoolCounters.count (counter) != 0 ;
10351130}
10361131
1132+ bool FlexCounter::isTunnelCounterSupported (
1133+ _In_ sai_tunnel_stat_t counter) const
1134+ {
1135+ SWSS_LOG_ENTER ();
1136+
1137+ return m_supportedTunnelCounters.count (counter) != 0 ;
1138+ }
1139+
10371140bool FlexCounter::isStatsModeSupported (
10381141 _In_ uint32_t statsMode,
10391142 _In_ sai_stats_mode_t statCapability)
@@ -1597,6 +1700,51 @@ void FlexCounter::collectBufferPoolCounters(
15971700 }
15981701}
15991702
1703+ void FlexCounter::collectTunnelCounters (
1704+ _In_ swss::Table &countersTable)
1705+ {
1706+ SWSS_LOG_ENTER ();
1707+
1708+ // Collect stats for every registered tunnel
1709+ for (const auto &kv: m_tunnelCounterIdsMap)
1710+ {
1711+ const auto &tunnelVid = kv.first ;
1712+ const auto &tunnelId = kv.second ->m_tunnelId ;
1713+ const auto &tunnelCounterIds = kv.second ->m_tunnelCounterIds ;
1714+
1715+ std::vector<uint64_t > tunnelStats (tunnelCounterIds.size ());
1716+
1717+ // Get tunnel stats
1718+ sai_status_t status = m_vendorSai->getStats (
1719+ SAI_OBJECT_TYPE_TUNNEL,
1720+ tunnelId,
1721+ static_cast <uint32_t >(tunnelCounterIds.size ()),
1722+ (const sai_stat_id_t *)tunnelCounterIds.data (),
1723+ tunnelStats.data ());
1724+
1725+ if (status != SAI_STATUS_SUCCESS)
1726+ {
1727+ SWSS_LOG_ERROR (" Failed to get stats of tunnel 0x%" PRIx64 " : %d" , tunnelId, status);
1728+ continue ;
1729+ }
1730+
1731+ // Push all counter values to a single vector
1732+ std::vector<swss::FieldValueTuple> values;
1733+
1734+ for (size_t i = 0 ; i != tunnelCounterIds.size (); i++)
1735+ {
1736+ const std::string &counterName = sai_serialize_tunnel_stat (tunnelCounterIds[i]);
1737+
1738+ values.emplace_back (counterName, std::to_string (tunnelStats[i]));
1739+ }
1740+
1741+ // Write counters to DB
1742+ std::string tunnelVidStr = sai_serialize_object_id (tunnelVid);
1743+
1744+ countersTable.set (tunnelVidStr, values, " " );
1745+ }
1746+ }
1747+
16001748void FlexCounter::runPlugins (
16011749 _In_ swss::DBConnector& counters_db)
16021750{
@@ -1675,6 +1823,17 @@ void FlexCounter::runPlugins(
16751823 {
16761824 runRedisScript (counters_db, sha, bufferPoolVids, argv);
16771825 }
1826+
1827+ std::vector<std::string> tunnelList;
1828+ tunnelList.reserve (m_tunnelCounterIdsMap.size ());
1829+ for (const auto & kv : m_tunnelCounterIdsMap)
1830+ {
1831+ tunnelList.push_back (sai_serialize_object_id (kv.first ));
1832+ }
1833+ for (const auto & sha : m_tunnelPlugins)
1834+ {
1835+ runRedisScript (counters_db, sha, tunnelList, argv);
1836+ }
16781837}
16791838
16801839void FlexCounter::flexCounterThreadRunFunction ()
@@ -2318,6 +2477,41 @@ void FlexCounter::getSupportedBufferPoolCounters(
23182477 }
23192478}
23202479
2480+ void FlexCounter::updateSupportedTunnelCounters (
2481+ _In_ sai_object_id_t tunnelRid,
2482+ _In_ const std::vector<sai_tunnel_stat_t > &counterIds)
2483+ {
2484+ SWSS_LOG_ENTER ();
2485+
2486+ if (m_supportedTunnelCounters.size ())
2487+ {
2488+ return ;
2489+ }
2490+
2491+ uint64_t value;
2492+ for (auto &counter: counterIds)
2493+ {
2494+ sai_status_t status = m_vendorSai->getStats (
2495+ SAI_OBJECT_TYPE_TUNNEL,
2496+ tunnelRid,
2497+ 1 ,
2498+ (const sai_stat_id_t *)&counter,
2499+ &value);
2500+
2501+ if (status != SAI_STATUS_SUCCESS)
2502+ {
2503+ SWSS_LOG_INFO (" Counter %s is not supported on tunnel RID %s: %s" ,
2504+ sai_serialize_tunnel_stat (counter).c_str (),
2505+ sai_serialize_object_id (tunnelRid).c_str (),
2506+ sai_serialize_status (status).c_str ());
2507+
2508+ continue ;
2509+ }
2510+
2511+ m_supportedTunnelCounters.insert (counter);
2512+ }
2513+ }
2514+
23212515void FlexCounter::updateSupportedBufferPoolCounters (
23222516 _In_ sai_object_id_t bufferPoolId,
23232517 _In_ const std::vector<sai_buffer_pool_stat_t > &counterIds,
@@ -2413,6 +2607,10 @@ void FlexCounter::removeCounter(
24132607 {
24142608 removeMACsecSA (vid);
24152609 }
2610+ else if (objectType == SAI_OBJECT_TYPE_TUNNEL)
2611+ {
2612+ removeTunnel (vid);
2613+ }
24162614 else
24172615 {
24182616 SWSS_LOG_ERROR (" Object type for removal not supported, %s" ,
@@ -2568,6 +2766,19 @@ void FlexCounter::addCounter(
25682766 {
25692767 statsMode = value;
25702768 }
2769+ else if (objectType == SAI_OBJECT_TYPE_TUNNEL && field == TUNNEL_COUNTER_ID_LIST)
2770+ {
2771+ std::vector<sai_tunnel_stat_t > tunnelCounterIds;
2772+
2773+ for (const auto &str : idStrings)
2774+ {
2775+ sai_tunnel_stat_t stat;
2776+ sai_deserialize_tunnel_stat (str.c_str (), &stat);
2777+ tunnelCounterIds.push_back (stat);
2778+ }
2779+
2780+ setTunnelCounterList (vid, rid, tunnelCounterIds);
2781+ }
25712782 else
25722783 {
25732784 SWSS_LOG_ERROR (" Object type and field combination is not supported, object type %s, field %s" ,
0 commit comments