11
11
#include " timer.h"
12
12
13
13
#define FABRIC_POLLING_INTERVAL_DEFAULT (30 )
14
+ #define FABRIC_PORT_PREFIX " PORT"
14
15
#define FABRIC_PORT_ERROR 0
15
16
#define FABRIC_PORT_SUCCESS 1
16
17
#define FABRIC_PORT_STAT_COUNTER_FLEX_COUNTER_GROUP " FABRIC_PORT_STAT_COUNTER"
17
18
#define FABRIC_PORT_STAT_FLEX_COUNTER_POLLING_INTERVAL_MS 10000
18
19
#define FABRIC_QUEUE_STAT_COUNTER_FLEX_COUNTER_GROUP " FABRIC_QUEUE_STAT_COUNTER"
19
20
#define FABRIC_QUEUE_STAT_FLEX_COUNTER_POLLING_INTERVAL_MS 100000
20
- #define FABRIC_PORT_TABLE " FABRIC_PORT_TABLE"
21
21
22
22
extern sai_object_id_t gSwitchId ;
23
23
extern sai_switch_api_t *sai_switch_api;
24
24
extern sai_port_api_t *sai_port_api;
25
+ extern sai_queue_api_t *sai_queue_api;
25
26
26
27
const vector<sai_port_stat_t > port_stat_ids =
27
28
{
@@ -42,7 +43,8 @@ static const vector<sai_queue_stat_t> queue_stat_ids =
42
43
SAI_QUEUE_STAT_CURR_OCCUPANCY_LEVEL,
43
44
};
44
45
45
- FabricPortsOrch::FabricPortsOrch (DBConnector *appl_db, vector<table_name_with_pri_t > &tableNames) :
46
+ FabricPortsOrch::FabricPortsOrch (DBConnector *appl_db, vector<table_name_with_pri_t > &tableNames,
47
+ bool fabricPortStatEnabled, bool fabricQueueStatEnabled) :
46
48
Orch(appl_db, tableNames),
47
49
port_stat_manager(FABRIC_PORT_STAT_COUNTER_FLEX_COUNTER_GROUP, StatsMode::READ,
48
50
FABRIC_PORT_STAT_FLEX_COUNTER_POLLING_INTERVAL_MS, true ),
@@ -55,14 +57,17 @@ FabricPortsOrch::FabricPortsOrch(DBConnector *appl_db, vector<table_name_with_pr
55
57
SWSS_LOG_NOTICE ( " FabricPortsOrch constructor" );
56
58
57
59
m_state_db = shared_ptr<DBConnector>(new DBConnector (" STATE_DB" , 0 ));
58
- m_stateTable = unique_ptr<Table>(new Table (m_state_db.get (), FABRIC_PORT_TABLE ));
60
+ m_stateTable = unique_ptr<Table>(new Table (m_state_db.get (), APP_FABRIC_PORT_TABLE_NAME ));
59
61
60
62
m_counter_db = shared_ptr<DBConnector>(new DBConnector (" COUNTERS_DB" , 0 ));
61
- m_laneQueueCounterTable = unique_ptr<Table>(new Table (m_counter_db.get (), COUNTERS_QUEUE_NAME_MAP ));
62
- m_lanePortCounterTable = unique_ptr<Table>(new Table (m_counter_db.get (), COUNTERS_QUEUE_PORT_MAP ));
63
+ m_portNameQueueCounterTable = unique_ptr<Table>(new Table (m_counter_db.get (), COUNTERS_FABRIC_QUEUE_NAME_MAP ));
64
+ m_portNamePortCounterTable = unique_ptr<Table>(new Table (m_counter_db.get (), COUNTERS_FABRIC_PORT_NAME_MAP ));
63
65
64
66
m_flex_db = shared_ptr<DBConnector>(new DBConnector (" FLEX_COUNTER_DB" , 0 ));
65
- m_flexCounterTable = unique_ptr<ProducerTable>(new ProducerTable (m_flex_db.get (), FABRIC_PORT_TABLE));
67
+ m_flexCounterTable = unique_ptr<ProducerTable>(new ProducerTable (m_flex_db.get (), APP_FABRIC_PORT_TABLE_NAME));
68
+
69
+ m_fabricPortStatEnabled = fabricPortStatEnabled;
70
+ m_fabricQueueStatEnabled = fabricQueueStatEnabled;
66
71
67
72
getFabricPortList ();
68
73
@@ -147,32 +152,96 @@ bool FabricPortsOrch::allPortsReady()
147
152
148
153
void FabricPortsOrch::generatePortStats ()
149
154
{
150
- // FIX_ME: This function installs flex counters for port stats
151
- // on fabric ports for fabric asics and voq asics (that connect
152
- // to fabric asics via fabric ports). These counters will be
153
- // installed in FLEX_COUNTER_DB, and queried by syncd and updated
154
- // to COUNTERS_DB.
155
- // However, currently BCM SAI doesn't update its code to query
156
- // port stats (metrics in list port_stat_ids) yet.
157
- // Also, BCM sets too low value for "Max logical port count" (256),
158
- // causing syncd to crash on voq asics that now include regular front
159
- // panel ports, fabric ports, and multiple logical ports.
160
- // So, this function will just do nothing for now, and we will readd
161
- // code to install port stats counters when BCM completely supports.
155
+ if (!m_fabricPortStatEnabled) return ;
156
+
157
+ SWSS_LOG_NOTICE (" Generate fabric port stats" );
158
+
159
+ vector<FieldValueTuple> portNamePortCounterMap;
160
+ for (auto p : m_fabricLanePortMap)
161
+ {
162
+ int lane = p.first ;
163
+ sai_object_id_t port = p.second ;
164
+
165
+ std::ostringstream portName;
166
+ portName << FABRIC_PORT_PREFIX << lane;
167
+ portNamePortCounterMap.emplace_back (portName.str (), sai_serialize_object_id (port));
168
+
169
+ // Install flex counters for port stats
170
+ std::unordered_set<std::string> counter_stats;
171
+ for (const auto & it: port_stat_ids)
172
+ {
173
+ counter_stats.emplace (sai_serialize_port_stat (it));
174
+ }
175
+ port_stat_manager.setCounterIdList (port, CounterType::PORT, counter_stats);
176
+ }
177
+ m_portNamePortCounterTable->set (" " , portNamePortCounterMap);
162
178
}
163
179
164
180
void FabricPortsOrch::generateQueueStats ()
165
181
{
182
+ if (!m_fabricQueueStatEnabled) return ;
166
183
if (m_isQueueStatsGenerated) return ;
167
184
if (!m_getFabricPortListDone) return ;
168
185
169
- // FIX_ME: Similar to generatePortStats(), generateQueueStats() installs
170
- // flex counters for queue stats on fabric ports for fabric asics and voq asics.
171
- // However, currently BCM SAI doesn't fully support queue stats query.
172
- // Query on queue type and index is not supported for fabric asics while
173
- // voq asics are not completely supported.
174
- // So, this function will just do nothing for now, and we will readd
175
- // code to install queue stats counters when BCM completely supports.
186
+ SWSS_LOG_NOTICE (" Generate queue map for fabric ports" );
187
+
188
+ sai_status_t status;
189
+ sai_attribute_t attr;
190
+
191
+ for (auto p : m_fabricLanePortMap)
192
+ {
193
+ int lane = p.first ;
194
+ sai_object_id_t port = p.second ;
195
+
196
+ // Each serdes has some pipes (queues) for unicast and multicast.
197
+ // But normally fabric serdes uses only one pipe.
198
+ attr.id = SAI_PORT_ATTR_QOS_NUMBER_OF_QUEUES;
199
+ status = sai_port_api->get_port_attribute (port, 1 , &attr);
200
+ if (status != SAI_STATUS_SUCCESS)
201
+ {
202
+ throw runtime_error (" FabricPortsOrch get port queue number failure" );
203
+ }
204
+ int num_queues = attr.value .u32 ;
205
+
206
+ if (num_queues > 0 )
207
+ {
208
+ vector<sai_object_id_t > m_queue_ids;
209
+ m_queue_ids.resize (num_queues);
210
+
211
+ attr.id = SAI_PORT_ATTR_QOS_QUEUE_LIST;
212
+ attr.value .objlist .count = (uint32_t ) num_queues;
213
+ attr.value .objlist .list = m_queue_ids.data ();
214
+
215
+ status = sai_port_api->get_port_attribute (port, 1 , &attr);
216
+ if (status != SAI_STATUS_SUCCESS)
217
+ {
218
+ throw runtime_error (" FabricPortsOrch get port queue list failure" );
219
+ }
220
+
221
+ // Maintain queue map and install flex counters for queue stats
222
+ vector<FieldValueTuple> portNameQueueMap;
223
+
224
+ // Fabric serdes queue type is SAI_QUEUE_TYPE_FABRIC_TX. Since we always
225
+ // maintain only one queue for fabric serdes, m_queue_ids size is 1.
226
+ // And so, there is no need to query SAI_QUEUE_ATTR_TYPE and SAI_QUEUE_ATTR_INDEX
227
+ // for queue. Actually, SAI does not support query these attributes on fabric serdes.
228
+ int queueIndex = 0 ;
229
+ std::ostringstream portName;
230
+ portName << FABRIC_PORT_PREFIX << lane << " :" << queueIndex;
231
+ const auto queue = sai_serialize_object_id (m_queue_ids[queueIndex]);
232
+ portNameQueueMap.emplace_back (portName.str (), queue);
233
+
234
+ // We collect queue counters like occupancy level
235
+ std::unordered_set<string> counter_stats;
236
+ for (const auto & it: queue_stat_ids)
237
+ {
238
+ counter_stats.emplace (sai_serialize_queue_stat (it));
239
+ }
240
+ queue_stat_manager.setCounterIdList (m_queue_ids[queueIndex], CounterType::QUEUE, counter_stats);
241
+
242
+ m_portNameQueueCounterTable->set (" " , portNameQueueMap);
243
+ }
244
+ }
176
245
177
246
m_isQueueStatsGenerated = true ;
178
247
}
@@ -199,7 +268,7 @@ void FabricPortsOrch::updateFabricPortState()
199
268
int lane = p.first ;
200
269
sai_object_id_t port = p.second ;
201
270
202
- string key = " PORT " + to_string (lane);
271
+ string key = FABRIC_PORT_PREFIX + to_string (lane);
203
272
std::vector<FieldValueTuple> values;
204
273
uint32_t remote_peer;
205
274
uint32_t remote_port;
0 commit comments