1+ #include " pfchistoryorch.h"
2+ #include " portsorch.h"
3+
4+ #define DEFAULT_POLL_INTERVAL " 1000"
5+
6+ extern sai_object_id_t gSwitchId ;
7+ extern sai_port_api_t *sai_port_api;
8+ extern PortsOrch *gPortsOrch ;
9+
10+ PfcHistoryOrch& PfcHistoryOrch::getInstance (DBConnector *db)
11+ {
12+ SWSS_LOG_ENTER ();
13+ static std::vector<string> tableNames = {
14+ CFG_PFC_STAT_HISTORY_TABLE_NAME
15+ };
16+ static const std::vector<sai_port_stat_t > portStatIds =
17+ {
18+ SAI_PORT_STAT_PFC_0_RX_PKTS,
19+ SAI_PORT_STAT_PFC_1_RX_PKTS,
20+ SAI_PORT_STAT_PFC_2_RX_PKTS,
21+ SAI_PORT_STAT_PFC_3_RX_PKTS,
22+ SAI_PORT_STAT_PFC_4_RX_PKTS,
23+ SAI_PORT_STAT_PFC_5_RX_PKTS,
24+ SAI_PORT_STAT_PFC_6_RX_PKTS,
25+ SAI_PORT_STAT_PFC_7_RX_PKTS,
26+ };
27+ static PfcHistoryOrch *historyOrch = new PfcHistoryOrch (db, tableNames, portStatIds);
28+
29+ return *historyOrch;
30+ }
31+
32+ PfcHistoryOrch::PfcHistoryOrch (
33+ DBConnector *db,
34+ std::vector<string> &tableNames,
35+ const vector<sai_port_stat_t > &portStatIds
36+ ):
37+ Orch(db, tableNames),
38+ c_portStatIds(portStatIds),
39+ m_countersDb(new DBConnector(" COUNTERS_DB" , 0 ))
40+ {
41+ SWSS_LOG_ENTER ();
42+
43+ // clear history stats for safe restart
44+ removeAllPfcStatHistoryCounters ();
45+
46+ // if config_db has not yet been populated, provide the defaults so it is consistent with flex_counter_db
47+ swss::Table flexCounterTable (db, CFG_FLEX_COUNTER_TABLE_NAME);
48+ std::string poll_interval;
49+ if (!flexCounterTable.hget (PFC_STAT_HISTORY_FLEX_COUNTER_GROUP, POLL_INTERVAL_FIELD, poll_interval)){
50+ flexCounterTable.hset (PFC_STAT_HISTORY_FLEX_COUNTER_GROUP, POLL_INTERVAL_FIELD, DEFAULT_POLL_INTERVAL);
51+ }
52+ std::string status;
53+ if (!flexCounterTable.hget (PFC_STAT_HISTORY_FLEX_COUNTER_GROUP, FLEX_COUNTER_STATUS_FIELD, status)){
54+ flexCounterTable.hset (PFC_STAT_HISTORY_FLEX_COUNTER_GROUP, FLEX_COUNTER_STATUS_FIELD, " disable" );
55+ }
56+
57+ string pluginName = " pfc_stat_history.lua" ;
58+ string sha;
59+ try
60+ {
61+ string script = swss::loadLuaScript (pluginName);
62+ sha = swss::loadRedisScript (m_countersDb.get (), script);
63+ }
64+ catch (const runtime_error &e)
65+ {
66+ SWSS_LOG_ERROR (" PFC STAT HISTORY flex counter group not set successfully: %s" , e.what ());
67+ }
68+
69+ setFlexCounterGroupParameter (PFC_STAT_HISTORY_FLEX_COUNTER_GROUP,
70+ DEFAULT_POLL_INTERVAL, // this will be overwritten by the config_db entry regardless
71+ STATS_MODE_READ, // don't clear counters on read
72+ PORT_PLUGIN_FIELD, // "context name" in syncd, "plugin name" here
73+ sha);
74+ }
75+
76+ PfcHistoryOrch::~PfcHistoryOrch (void )
77+ {
78+ SWSS_LOG_ENTER ();
79+ }
80+
81+ // Remove all PFC Historical Stats from COUNTERS_DB
82+ void PfcHistoryOrch::removeAllPfcStatHistoryCounters ()
83+ {
84+ SWSS_LOG_ENTER ();
85+
86+ vector<string> keys;
87+ const auto pfcHistTable = std::make_unique<Table>(m_countersDb.get (), COUNTERS_PFC_STAT_HISTORY_TABLE);
88+ pfcHistTable->getKeys (keys);
89+ for (auto key : keys)
90+ {
91+ pfcHistTable->del (key);
92+ }
93+ }
94+
95+ void PfcHistoryOrch::doTask (Consumer& consumer){
96+ SWSS_LOG_ENTER ();
97+
98+ if (!gPortsOrch ->allPortsReady ())
99+ {
100+ return ;
101+ }
102+
103+ if ((consumer.getDbName () == " CONFIG_DB" )
104+ && consumer.getTableName () == CFG_PFC_STAT_HISTORY_TABLE_NAME
105+ )
106+ {
107+ auto it = consumer.m_toSync .begin ();
108+ while (it != consumer.m_toSync .end ())
109+ {
110+ KeyOpFieldsValuesTuple t = it->second ;
111+ string key = kfvKey (t);
112+ string op = kfvOp (t);
113+ std::vector<FieldValueTuple> fvt = kfvFieldsValues (t);
114+
115+ Port port;
116+ if (!gPortsOrch ->getPort (key, port))
117+ {
118+ return ;
119+ }
120+
121+ if (op == SET_COMMAND)
122+ {
123+ if (port.m_type != Port::PHY)
124+ {
125+ SWSS_LOG_ERROR (" %s not a physical port!" , sai_serialize_object_id (port.m_port_id ).c_str ());
126+ continue ;
127+ }
128+
129+ if (!c_portStatIds.empty ())
130+ {
131+ string key = string (PFC_STAT_HISTORY_FLEX_COUNTER_GROUP) + " :" + sai_serialize_object_id (port.m_port_id );
132+ string str = counterIdsToStr (c_portStatIds);
133+
134+ // FLEX_COUNTER_TABLE:PFC_STAT_HISTORY:oid:<port> : {PORT_COUNTER_ID_LIST: SAI_PORT_PFC_X_RX_PKTS}
135+ startFlexCounterPolling (gSwitchId , key, str, PORT_COUNTER_ID_LIST);
136+ }
137+ else {
138+ SWSS_LOG_ERROR (" No port stat ids provided, polling on %s not started" , sai_serialize_object_id (port.m_port_id ).c_str ());
139+ }
140+ }
141+ else if (op == DEL_COMMAND)
142+ {
143+ string key = string (PFC_STAT_HISTORY_FLEX_COUNTER_GROUP) + " :" + sai_serialize_object_id (port.m_port_id );
144+ // Unregister in syncd
145+ stopFlexCounterPolling (gSwitchId , key);
146+ }
147+ else
148+ {
149+ SWSS_LOG_ERROR (" Unknown operation type %s" , op.c_str ());
150+ }
151+ consumer.m_toSync .erase (it++);
152+ }
153+ }
154+ }
155+
156+ string PfcHistoryOrch::counterIdsToStr (const vector<sai_port_stat_t > ids)
157+ {
158+ SWSS_LOG_ENTER ();
159+
160+ string str;
161+
162+ for (const auto & i: ids)
163+ {
164+ str += sai_serialize_port_stat (i) + " ," ;
165+ }
166+
167+ // Remove trailing ','
168+ if (!str.empty ())
169+ {
170+ str.pop_back ();
171+ }
172+
173+ return str;
174+ }
0 commit comments