99#include " producertable.h"
1010#include " table.h"
1111#include < inttypes.h>
12+ #include < type_traits>
13+ #include " sai_serialize.h"
14+ #include " saihelper.h"
1215
1316extern " C" {
1417#include " sai.h"
1518}
1619
1720enum class StatsMode
1821{
19- READ
22+ READ,
23+ READ_AND_CLEAR
2024};
2125
2226enum class CounterType
2327{
2428 PORT,
2529 QUEUE,
30+ QUEUE_ATTR,
31+ PRIORITY_GROUP,
2632 PORT_DEBUG,
2733 SWITCH_DEBUG,
2834 MACSEC_SA_ATTR,
@@ -35,13 +41,18 @@ enum class CounterType
3541 ENI
3642};
3743
44+ extern bool gTraditionalFlexCounter ;
45+ extern sai_object_id_t gSwitchId ;
46+
47+ struct CachedObjects ;
3848// FlexCounterManager allows users to manage a group of flex counters.
3949//
4050// TODO: FlexCounterManager doesn't currently support the full range of
4151// flex counter features. In particular, support for standard (i.e. non-debug)
4252// counters and support for plugins needs to be added.
4353class FlexCounterManager
4454{
55+ friend struct CachedObjects ;
4556 public:
4657 FlexCounterManager (
4758 const std::string& group_name,
@@ -69,12 +80,12 @@ class FlexCounterManager
6980 void enableFlexCounterGroup ();
7081 void disableFlexCounterGroup ();
7182
72- void setCounterIdList (
83+ virtual void setCounterIdList (
7384 const sai_object_id_t object_id,
7485 const CounterType counter_type,
7586 const std::unordered_set<std::string>& counter_stats,
7687 const sai_object_id_t switch_id=SAI_NULL_OBJECT_ID);
77- void clearCounterIdList (const sai_object_id_t object_id);
88+ virtual void clearCounterIdList (const sai_object_id_t object_id);
7889
7990 const std::string& getGroupName () const
8091 {
@@ -99,12 +110,9 @@ class FlexCounterManager
99110 protected:
100111 void applyGroupConfiguration ();
101112
102- private:
103113 std::string getFlexCounterTableKey (
104114 const std::string& group_name,
105115 const sai_object_id_t object_id) const ;
106- std::string serializeCounterStats (
107- const std::unordered_set<std::string>& counter_stats) const ;
108116
109117 std::string group_name;
110118 StatsMode stats_mode;
@@ -114,11 +122,235 @@ class FlexCounterManager
114122 std::unordered_map<sai_object_id_t , sai_object_id_t > installed_counters;
115123 bool is_gearbox;
116124
125+ static std::string serializeCounterStats (
126+ const std::unordered_set<std::string>& counter_stats);
127+
117128 static const std::unordered_map<StatsMode, std::string> stats_mode_lookup;
118129 static const std::unordered_map<bool , std::string> status_lookup;
119130 static const std::unordered_map<CounterType, std::string> counter_id_field_lookup;
120131};
121132
133+ struct CachedObjects
134+ {
135+ CounterType pending_counter_type;
136+ sai_object_id_t pending_switch_id;
137+ std::unordered_set<std::string> pending_counter_stats;
138+ std::unordered_set<sai_object_id_t > pending_sai_objects;
139+
140+ bool try_cache (const sai_object_id_t object_id,
141+ const CounterType counter_type,
142+ const std::unordered_set<std::string>& counter_stats,
143+ sai_object_id_t switch_id)
144+ {
145+ if (pending_sai_objects.empty ())
146+ {
147+ pending_counter_type = counter_type;
148+ pending_switch_id = switch_id;
149+ // Just to avoid recreating counter IDs
150+ if (pending_counter_stats != counter_stats)
151+ {
152+ pending_counter_stats = counter_stats;
153+ }
154+ }
155+ else if (counter_type != pending_counter_type ||
156+ switch_id != pending_switch_id ||
157+ counter_stats != pending_counter_stats)
158+ {
159+ return false ;
160+ }
161+
162+ cache (object_id);
163+
164+ return true ;
165+ }
166+
167+ bool is_cached (const sai_object_id_t object_id)
168+ {
169+ return pending_sai_objects.find (object_id) != pending_sai_objects.end ();
170+ }
171+
172+ void flush (const std::string &group_name)
173+ {
174+ if (pending_sai_objects.empty ())
175+ {
176+ return ;
177+ }
178+
179+ auto counter_ids = FlexCounterManager::serializeCounterStats (pending_counter_stats);
180+ auto counter_type_it = FlexCounterManager::counter_id_field_lookup.find (pending_counter_type);
181+
182+ auto counter_keys = group_name + " :" ;
183+ for (const auto & oid: pending_sai_objects)
184+ {
185+ counter_keys += sai_serialize_object_id (oid) + " ," ;
186+ }
187+ counter_keys.pop_back ();
188+
189+ startFlexCounterPolling (pending_switch_id, counter_keys, counter_ids, counter_type_it->second );
190+
191+ pending_sai_objects.clear ();
192+ }
193+
194+ void cache (sai_object_id_t object_id)
195+ {
196+ pending_sai_objects.emplace (object_id);
197+ }
198+ };
199+
200+ class FlexCounterCachedManager : public FlexCounterManager
201+ {
202+ public:
203+ FlexCounterCachedManager (
204+ const std::string& group_name,
205+ const StatsMode stats_mode,
206+ const uint polling_interval,
207+ const bool enabled,
208+ swss::FieldValueTuple fv_plugin = std::make_pair(" " ," " )) :
209+ FlexCounterManager (group_name, stats_mode, polling_interval, enabled, fv_plugin)
210+ {
211+ }
212+
213+ virtual void flush ()
214+ {
215+ }
216+
217+ protected:
218+ void flush (const std::string &group_name, struct CachedObjects &cached_objects)
219+ {
220+ cached_objects.flush (group_name);
221+ }
222+
223+ void setCounterIdList (
224+ struct CachedObjects &cached_objects,
225+ const sai_object_id_t object_id,
226+ const CounterType counter_type,
227+ const std::unordered_set<std::string>& counter_stats,
228+ const sai_object_id_t switch_id=SAI_NULL_OBJECT_ID)
229+ {
230+ if (gTraditionalFlexCounter )
231+ {
232+ // Unable to cache an object and initialize in bulk in traditional flex counter mode
233+ FlexCounterManager::setCounterIdList (object_id, counter_type, counter_stats, switch_id);
234+ return ;
235+ }
236+
237+ auto effective_switch_id = switch_id == SAI_NULL_OBJECT_ID ? gSwitchId : switch_id;
238+ installed_counters[object_id] = effective_switch_id;
239+ if (cached_objects.try_cache (object_id, counter_type, counter_stats, effective_switch_id))
240+ {
241+ return ;
242+ }
243+ else
244+ {
245+ flush (group_name, cached_objects);
246+ cached_objects.cache (object_id);
247+ }
248+ }
249+
250+ void clearCounterIdList (
251+ struct CachedObjects &cached_objects,
252+ const sai_object_id_t object_id)
253+ {
254+ auto search = cached_objects.pending_sai_objects .find (object_id);
255+ if (search == cached_objects.pending_sai_objects .end ())
256+ {
257+ FlexCounterManager::clearCounterIdList (object_id);
258+ }
259+ else
260+ {
261+ installed_counters.erase (object_id);
262+ cached_objects.pending_sai_objects .erase (search);
263+ }
264+ }
265+ };
266+
267+ template <typename TagType, typename Enable=void >
268+ class FlexCounterTaggedCachedManager : public FlexCounterCachedManager
269+ {
270+ public:
271+ FlexCounterTaggedCachedManager (
272+ const std::string& group_name,
273+ const StatsMode stats_mode,
274+ const uint polling_interval,
275+ const bool enabled,
276+ swss::FieldValueTuple fv_plugin = std::make_pair(" " ," " )) :
277+ FlexCounterCachedManager (group_name, stats_mode, polling_interval, enabled, fv_plugin)
278+ {
279+ }
280+
281+ void flush ()
282+ {
283+ FlexCounterCachedManager::flush (group_name, cached_objects);
284+ }
285+
286+ virtual void setCounterIdList (
287+ const sai_object_id_t object_id,
288+ const CounterType counter_type,
289+ const std::unordered_set<std::string>& counter_stats,
290+ const sai_object_id_t switch_id=SAI_NULL_OBJECT_ID)
291+ {
292+ FlexCounterCachedManager::setCounterIdList (cached_objects,
293+ object_id,
294+ counter_type,
295+ counter_stats);
296+ }
297+
298+ virtual void clearCounterIdList (
299+ const sai_object_id_t object_id)
300+ {
301+ FlexCounterCachedManager::clearCounterIdList (cached_objects, object_id);
302+ }
303+
304+ private:
305+ struct CachedObjects cached_objects;
306+ };
307+
308+ template <typename TagType>
309+ class FlexCounterTaggedCachedManager <TagType, typename std::enable_if_t <std::is_enum<TagType>::value>> : public FlexCounterCachedManager
310+ {
311+ public:
312+ FlexCounterTaggedCachedManager (
313+ const std::string& group_name,
314+ const StatsMode stats_mode,
315+ const uint polling_interval,
316+ const bool enabled,
317+ swss::FieldValueTuple fv_plugin = std::make_pair(" " ," " )) :
318+ FlexCounterCachedManager (group_name, stats_mode, polling_interval, enabled, fv_plugin)
319+ {
320+ }
321+
322+ void flush ()
323+ {
324+ for (auto &it : cached_objects)
325+ {
326+ FlexCounterCachedManager::flush (group_name, it.second );
327+ }
328+ }
329+
330+ void setCounterIdList (
331+ const sai_object_id_t object_id,
332+ const CounterType counter_type,
333+ const std::unordered_set<std::string>& counter_stats,
334+ const TagType tag,
335+ const sai_object_id_t switch_id=SAI_NULL_OBJECT_ID)
336+ {
337+ FlexCounterCachedManager::setCounterIdList (cached_objects[tag],
338+ object_id,
339+ counter_type,
340+ counter_stats);
341+ }
342+
343+ void clearCounterIdList (
344+ const sai_object_id_t object_id,
345+ const TagType tag)
346+ {
347+ FlexCounterCachedManager::clearCounterIdList (cached_objects[tag], object_id);
348+ }
349+
350+ private:
351+ std::map<TagType, struct CachedObjects > cached_objects;
352+ };
353+
122354class FlexManagerDirectory
123355{
124356 public:
0 commit comments