diff --git a/doc/flex_counter/add_counter_object_flow.svg b/doc/flex_counter/add_counter_object_flow.svg new file mode 100644 index 00000000000..aa07a81b5ea --- /dev/null +++ b/doc/flex_counter/add_counter_object_flow.svg @@ -0,0 +1 @@ +
FlexCounterManager
FlexCounterManager
FlexCounter
FlexCounter
1.1 getCounterContext
1.1 getCounterContext
CounterContext
CounterContext
1.3 updateSupportedCounters
1.3 updateSupportedCounters
1.4 querySupportedCounters
1.4 querySupportedCounters
1.5 getSupportedCounters
1.5 getSupportedCounters
1.6 add/update counter IDs
1.6 add/update counter IDs
1. addCounter
1. addCounter
return
return
1.2 addObject
1.2 addObject
return
return
Viewer does not support full SVG 1.1
\ No newline at end of file diff --git a/doc/flex_counter/add_plugin_flow.svg b/doc/flex_counter/add_plugin_flow.svg new file mode 100644 index 00000000000..c697c5a0e09 --- /dev/null +++ b/doc/flex_counter/add_plugin_flow.svg @@ -0,0 +1 @@ +
FlexCounterManager
FlexCounterManager
FlexCounter
FlexCounter
1.1 getCounterContext
1.1 getCounterContext
CounterContext
CounterContext
1.3 save plugin
1.3 save plugin
1. addCounterPlugin
1. addCounterPlugin
return
return
1.2 addPlugin
1.2 addPlugin
return
return
Viewer does not support full SVG 1.1
\ No newline at end of file diff --git a/doc/flex_counter/flex_counter_current.svg b/doc/flex_counter/flex_counter_current.svg new file mode 100644 index 00000000000..38a5fed9a39 --- /dev/null +++ b/doc/flex_counter/flex_counter_current.svg @@ -0,0 +1 @@ +
FlexCounter
FlexCounter
Port CountersetPortCounterListremovePortgetSupportedPortCountersquerySupportedPortCountersupdateSupportedPortCounterscollectPortCountersaddPortCounterPluginm_portPluginsm_supportedPortCountersm_portCounterIdsMapstruct PortCounterIdsQueue CountersetQueueCounterListremoveQueuegetSupportedQueueCountersquerySupportedQueueCountersupdateSupportedQueueCounterscollectQueueCountersaddQueueCounterPluginm_queuePluginsm_supportedQueueCountersm_queueCounterIdsMapstruct QueueCounterIds
......
......
Viewer does not support full SVG 1.1
\ No newline at end of file diff --git a/doc/flex_counter/flex_counter_new.svg b/doc/flex_counter/flex_counter_new.svg new file mode 100644 index 00000000000..18dd5a804bd --- /dev/null +++ b/doc/flex_counter/flex_counter_new.svg @@ -0,0 +1 @@ +BaseCounterContext+ name: string+ object_type: sai_object_type_t+ plugins: set<string>+ addObject: void virtual+ removeObject: void virtual+ hasObject: bool virtual+ addPlugin: void+ removePlugins: void+ hasPlugin: bool+ runPlugin: void virtual+ collectData: void virtualFlexCounter+ counter_contex_map: map<string, BaseCounterContext>+ getCounterContext: void+ createCounterContext: BaseCounterContext+ hasCounterContext: bool
Relation
Relation
0..n
0..n
1
1
CounterContext<T>+ object_ids_map: map<sai_object_id_t, CounterIds<T>>+ supported_counters: set<T>+ addObject: void overide+ removeObject: void override+ hasObject: bool override+ runPlugin: void override+ collectData: void override+ updateSupportedCounters: void+ getSupportedCounters: void+ querySupportedCounters: void
Inherit
Inherit
AttrContext<T>+ addObject: void override+ collectData: void override
Inherit
Inherit
CounterIds<T>+ rid: sai_object_id_t+ counter_ids: vector<T>+ stats_mode: sai_stats_mode_t (Optional)
Relation
Relation
0..n
0..n
1
1
Viewer does not support full SVG 1.1
\ No newline at end of file diff --git a/doc/flex_counter/flex_counter_refactor.md b/doc/flex_counter/flex_counter_refactor.md new file mode 100644 index 00000000000..604ddb8b81e --- /dev/null +++ b/doc/flex_counter/flex_counter_refactor.md @@ -0,0 +1,252 @@ +# SONiC FlexCounter Refactor # + +## Table of Content + +### Revision + + | Rev | Date | Author | Change Description | + |:---:|:-----------:|:------------------:|-----------------------------------| + | 0.1 | | Junchao Chen | Initial version | + +### Scope + +This document is the design document for refactoring FlexCounter class in syncd of sonic-sairedis. + +### Definitions/Abbreviations + +N/A + +### Overview + +FlexCounter class is a representation of flex counter group which supports querying multiple types of statistic/attributes. It supports multiple statistic/attribute types such as port counter, port debug counter, queue counter, queue attribute and so on. For each statistic/attribute type, it defines several member functions: + +- setXXXCounterList: e.g. setPortCounterList, setPortDebugCounterList +- removeXXX: e.g. removePort, removeQueue +- collectXXXCounters: e.g. collectPortCounters, collectQueueCounters +- collectXXXAttr: e.g. collectQueueAttrs, collectPriorityGroupAttrs +- so on + +For different statistic/attribute types, these functions have very similar logic. This design document describes a proposal about how to refactor FlexCounter class by moving duplicate/similar logic to a single place. + +#### Challenge + +The major challenge of this refactor is that, different statistic/attributes types may have different SAI type. E.g. type of port counter is sai_port_stat_t, type of queue counter is sai_queue_stat_t, type of queue attribute is sai_port_attr_t. C++ does not allow to put different type of object into the same container. + +#### Benefit + +A POC shows that, the refactor brings a few benefits: + +- Code lines of FlexCounter.cpp change from ~4000 to ~1000 +- Code lines of FlexCounter.h change from ~600 to ~200 +- Supporting new flex counter would requires only change a few places instead of implementing all those setXXXCounterList/removeXXX/collectXXXCounter and so on + +### Requirements + +- The change shall be limited in FlexCounter class +- Public interfaces of FlexCounter class shall keep the same functional +- Other class/component of SONiC shall treat this change as transparent + +### Architecture Design + +Current design of FlexCounter class: + +![flex_counter_current](/doc/flex_counter/flex_counter_current.svg). + +New design: + +![flex_counter_new](/doc/flex_counter/flex_counter_new.svg). + +### High-Level Design + +Changes shall be made into sonic-sairedis. Affected files are: FlexCounter.cpp, FlexCounter.h. This chapter will describe that how the new architecture can perfectly replace the old functions. + +> Note: Code present in this design document is only for demonstrating the design idea, it is not production code. + +#### sonic-sairedis + +##### Store Counter Related Data + +Currently, there are several types of counter related data. + +- Counter IDs map: stores object vid, rid and a list of counter IDs that will be queried. E.g. m_portCounterIdsMap, m_queueCounterIdsMap... +- Plugins: stores redis lua SHA values that will be execute by redis. E.g. m_portPlugins, m_queuePlugins... +- Supported counters: stores supported counter IDs. E.g. m_supportedPortCounters, m_supportedQueueCounters... + +In the new design, each statistic/attribute type is represented by an instance of CounterContext/AttrContext which will be stored in counter_context_map. These data members are moved to CounterContext and AttrContext as data members: + +- object_ids_map +- plugins +- supported_counters + +##### Counter IDs Structure + +Currently, a few similar structures are defined in FlexCounter to represent rid, counter IDs as well as stats mode. + +```cpp +struct QueueCounterIds +{ + QueueCounterIds( + _In_ sai_object_id_t queue, + _In_ const std::vector &queueIds); + + sai_object_id_t queueId; + std::vector queueCounterIds; +}; + +struct PortCounterIds +{ + PortCounterIds( + _In_ sai_object_id_t port, + _In_ const std::vector &portIds); + + sai_object_id_t portId; + std::vector portCounterIds; +}; + +struct BufferPoolCounterIds +{ + BufferPoolCounterIds( + _In_ sai_object_id_t bufferPool, + _In_ const std::vector &bufferPoolIds, + _In_ sai_stats_mode_t statsMode); + + sai_object_id_t bufferPoolId; + sai_stats_mode_t bufferPoolStatsMode; + std::vector bufferPoolCounterIds; +}; + +... +``` + +In new design, two template structures are defined to replaces above structures. The second structure is for those statistic/attribute type which support per instance stats mode; the first structure is for other statistic/attribute type which use counter group level stats mode. + +```cpp +template +struct CounterIds +{ + CounterIds( + _In_ sai_object_id_t rid, + _In_ const std::vector &counter_ids + ): rid(rid), counter_ids(counter_ids) {} + sai_object_id_t rid; + std::vector counter_ids; +}; + +// CounterIds structure contains stats mode, now buffer pool is the only one +// has member stats_mode. +template +struct CounterIds::value>::type > +{ + CounterIds( + _In_ sai_object_id_t rid, + _In_ const std::vector &counter_ids + ): rid(rid), counter_ids(counter_ids) {} + sai_object_id_t rid; + std::vector counter_ids; + sai_stats_mode_t stats_mode; +}; +``` + +##### Handle Counter Object Change + +Each statistic/attribute type can have multiple counter objects. For example, Ethernet0 is a counter object of port statistic; Ethernet0 queue0 is a counter object of queue statistic. The most important information of a counter object are: + +- rid: SAI ID of the object (Real ID) +- vid: Syncd ID of the object (Virtual ID) +- counter_ids: SAI statistic IDs + +FlexCounter handles counter object change so that it queries relevant statistic/attribute from SAI. + +##### Add/Update Counter Object + +Currently, the flow of adding/updating counter object is like this: + +1. FlexCounterManager calls FlexCounter::addCounter +2. In `addCounter`, it calls setXXXCounterList according to the input parameters +3. In `setXXXCounterList`, it updates supported counters +4. In `updateXXXSuportedCounters`, it query statistic capability via SAI API +5. If step 4 fails, it fall back to `getXXXSupportedCounters`, in which is query statistic value for each input counter IDs +6. If supported counters is not empty, update the counter object to a proper counter IDs map + +In the new design, step 3 ~ step 6 are moved to CounterContext class, but the flow/function does not change at all. Here is the chart of the new design(the chart shows the design idea, it does not contain all details): + +![add_counter_object_flow](/doc/flex_counter/add_counter_object_flow.svg). + +For different statistic type, the flow is similar, but not exactly the same. So, there are special cases shall be handled in implementation: + +- Some statistic type query statistic capability via SAI API, while some do not. Need a flag in BaseCounterContext to handle this. +- Some statistic type always query statistic capability, while some only do it once. Need a flag in BaseCounterContext to handle this. +- Some statistic type use `getStats` querying statistic data, while some use `getStatsExt`. Need a flag in BaseCounterContext to handle this. +- Some statistic support per counter object stats mode, while some do not. Plan to use `if constexpr` to handle this. + +##### Remove Counter Object + +Currently, FlexCounter just remove counter object from m_XXXCounterIdsMap. In the new design, the flow/function is the same, but remove operation is moved to CounterContext/AttrContext. In new design, flow is like this: + +![remove_counter_object_flow](/doc/flex_counter/remove_counter_object_flow.svg). + +##### Handle Plugin Change + +Currently, FlexCounter just add plugin to m_XXXPlugins. In new design, the flow/function is the same, but add operation is moved to BaseCounterContext. In new design, the flow is like this: + +![add_plugin_flow](/doc/flex_counter/add_plugin_flow.svg). + +##### Handle Statistic/Attribute Collect + +Currently, FlexCounter collect counters by saving collectXXXCounters function pointer to a map and loop the map. In new design, that map is not needed anymore. New way: + +```cpp +void FlexCounter::collectCounters( + _In_ swss::Table &countersTable) +{ + for (const auto &it : m_counterContext) + { + it->second->collectData(countersTable); + } + + countersTable.flush(); +} +``` + +Currently, FlexCounter run redis plugins by looping each m_XXXPlugins one by one. New way: + +```cpp +void FlexCounter::runPlugins( + _In_ swss::DBConnector& counters_db) +{ + const std::vector argv = + { + std::to_string(counters_db.getDbId()), + COUNTERS_TABLE, + std::to_string(m_pollInterval) + }; + + for (const auto &it : m_counterContext) + { + it->second->runPlugin(counters_db, argv); + } +} +``` + +### SAI API + +N/A + +### Configuration and management + +N/A + +### Warmboot and Fastboot Design Impact + +N/A + +### Restrictions/Limitations + +N/A + +### Testing Requirements/Design + +#### Unit Test cases + +TBD diff --git a/doc/flex_counter/remove_counter_object_flow.svg b/doc/flex_counter/remove_counter_object_flow.svg new file mode 100644 index 00000000000..ac8d1d56d7f --- /dev/null +++ b/doc/flex_counter/remove_counter_object_flow.svg @@ -0,0 +1 @@ +
FlexCounterManager
FlexCounterManager
FlexCounter
FlexCounter
1.1 getCounterContext
1.1 getCounterContext
CounterContext
CounterContext
1.3 remove counter IDs
1.3 remove counter IDs
1. removeCounter
1. removeCounter
return
return
1.2 removeObject
1.2 removeObject
return
return
Viewer does not support full SVG 1.1
\ No newline at end of file