Skip to content

Commit a39673d

Browse files
authored
[flex-counters] Delay flex counters stats init for faster boot time (sonic-net#1803)
What I did Update flex counters DB with counters stats only when counters are enabled. As long as the polling counters are not enabled, flex counters information will stored internally on PortsOrch. Why I did it Creating flex counters objects on the DB will trigger 'SYNCD' to access the HW for query statistics capabilities. This HW access takes time and will be better to finish boot before doing this (mainly for fast-reboot but good to have in general). The flex counters are not crucial at boot time, we can delay it to the end of the boot process. How I verified it Reboot a switch and observer the flex counters DB populated after counters are enabled. Signed-off-by: Shlomi Bitton <[email protected]>
1 parent 3226163 commit a39673d

9 files changed

+255
-30
lines changed

orchagent/flexcounterorch.cpp

+35-15
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,11 @@ extern IntfsOrch *gIntfsOrch;
1818
extern BufferOrch *gBufferOrch;
1919

2020
#define BUFFER_POOL_WATERMARK_KEY "BUFFER_POOL_WATERMARK"
21+
#define PORT_KEY "PORT"
22+
#define PORT_BUFFER_DROP_KEY "PORT_BUFFER_DROP"
23+
#define QUEUE_KEY "QUEUE"
24+
#define PG_WATERMARK_KEY "PG_WATERMARK"
25+
#define RIF_KEY "RIF"
2126

2227
unordered_map<string, string> flexCounterGroupMap =
2328
{
@@ -102,26 +107,31 @@ void FlexCounterOrch::doTask(Consumer &consumer)
102107
// which is automatically satisfied upon the creation of the orch object that requires
103108
// the syncd flex counter polling service
104109
// This postponement is introduced by design to accelerate the initialization process
105-
//
106-
// generateQueueMap() is called as long as a field "FLEX_COUNTER_STATUS" event is heard,
107-
// regardless of whether the key is "QUEUE" or whether the value is "enable" or "disable"
108-
// This can be because generateQueueMap() installs a fundamental list of queue stats
109-
// that need to be polled. So my doubt here is if queue watermark stats shall be piggybacked
110-
// into the same function as they may not be counted as fundamental
111-
if(gPortsOrch)
110+
if(gPortsOrch && (value == "enable"))
112111
{
113-
gPortsOrch->generateQueueMap();
114-
gPortsOrch->generatePriorityGroupMap();
112+
if(key == PORT_KEY)
113+
{
114+
gPortsOrch->generatePortCounterMap();
115+
m_port_counter_enabled = true;
116+
}
117+
else if(key == PORT_BUFFER_DROP_KEY)
118+
{
119+
gPortsOrch->generatePortBufferDropCounterMap();
120+
m_port_buffer_drop_counter_enabled = true;
121+
}
122+
else if(key == QUEUE_KEY)
123+
{
124+
gPortsOrch->generateQueueMap();
125+
}
126+
else if(key == PG_WATERMARK_KEY)
127+
{
128+
gPortsOrch->generatePriorityGroupMap();
129+
}
115130
}
116-
if(gPortsOrch)
117-
{
118-
gPortsOrch->generatePriorityGroupMap();
119-
}
120-
if(gIntfsOrch)
131+
if(gIntfsOrch && (key == RIF_KEY) && (value == "enable"))
121132
{
122133
gIntfsOrch->generateInterfaceMap();
123134
}
124-
// Install COUNTER_ID_LIST/ATTR_ID_LIST only when hearing buffer pool watermark enable event
125135
if (gBufferOrch && (key == BUFFER_POOL_WATERMARK_KEY) && (value == "enable"))
126136
{
127137
gBufferOrch->generateBufferPoolWatermarkCounterIdList();
@@ -144,3 +154,13 @@ void FlexCounterOrch::doTask(Consumer &consumer)
144154
consumer.m_toSync.erase(it++);
145155
}
146156
}
157+
158+
bool FlexCounterOrch::getPortCountersState() const
159+
{
160+
return m_port_counter_enabled;
161+
}
162+
163+
bool FlexCounterOrch::getPortBufferDropCountersState() const
164+
{
165+
return m_port_buffer_drop_counter_enabled;
166+
}

orchagent/flexcounterorch.h

+4
Original file line numberDiff line numberDiff line change
@@ -15,10 +15,14 @@ class FlexCounterOrch: public Orch
1515
void doTask(Consumer &consumer);
1616
FlexCounterOrch(swss::DBConnector *db, std::vector<std::string> &tableNames);
1717
virtual ~FlexCounterOrch(void);
18+
bool getPortCountersState() const;
19+
bool getPortBufferDropCountersState() const;
1820

1921
private:
2022
std::shared_ptr<swss::DBConnector> m_flexCounterDb = nullptr;
2123
std::shared_ptr<swss::ProducerTable> m_flexCounterGroupTable = nullptr;
24+
bool m_port_counter_enabled = false;
25+
bool m_port_buffer_drop_counter_enabled = false;
2226
};
2327

2428
#endif

orchagent/orchdaemon.cpp

+5-1
Original file line numberDiff line numberDiff line change
@@ -358,7 +358,11 @@ bool OrchDaemon::init()
358358
CFG_FLEX_COUNTER_TABLE_NAME
359359
};
360360

361-
m_orchList.push_back(new FlexCounterOrch(m_configDb, flex_counter_tables));
361+
auto* flexCounterOrch = new FlexCounterOrch(m_configDb, flex_counter_tables);
362+
m_orchList.push_back(flexCounterOrch);
363+
364+
gDirectory.set(flexCounterOrch);
365+
gDirectory.set(gPortsOrch);
362366

363367
vector<string> pfc_wd_tables = {
364368
CFG_PFC_WD_TABLE_NAME

orchagent/portsorch.cpp

+80-13
Original file line numberDiff line numberDiff line change
@@ -284,9 +284,9 @@ static char* hostif_vlan_tag[] = {
284284
PortsOrch::PortsOrch(DBConnector *db, DBConnector *stateDb, vector<table_name_with_pri_t> &tableNames, DBConnector *chassisAppDb) :
285285
Orch(db, tableNames),
286286
m_portStateTable(stateDb, STATE_PORT_TABLE_NAME),
287-
port_stat_manager(PORT_STAT_COUNTER_FLEX_COUNTER_GROUP, StatsMode::READ, PORT_STAT_FLEX_COUNTER_POLLING_INTERVAL_MS, true),
288-
port_buffer_drop_stat_manager(PORT_BUFFER_DROP_STAT_FLEX_COUNTER_GROUP, StatsMode::READ, PORT_BUFFER_DROP_STAT_POLLING_INTERVAL_MS, true),
289-
queue_stat_manager(QUEUE_STAT_COUNTER_FLEX_COUNTER_GROUP, StatsMode::READ, QUEUE_STAT_FLEX_COUNTER_POLLING_INTERVAL_MS, true)
287+
port_stat_manager(PORT_STAT_COUNTER_FLEX_COUNTER_GROUP, StatsMode::READ, PORT_STAT_FLEX_COUNTER_POLLING_INTERVAL_MS, false),
288+
port_buffer_drop_stat_manager(PORT_BUFFER_DROP_STAT_FLEX_COUNTER_GROUP, StatsMode::READ, PORT_BUFFER_DROP_STAT_POLLING_INTERVAL_MS, false),
289+
queue_stat_manager(QUEUE_STAT_COUNTER_FLEX_COUNTER_GROUP, StatsMode::READ, QUEUE_STAT_FLEX_COUNTER_POLLING_INTERVAL_MS, false)
290290
{
291291
SWSS_LOG_ENTER();
292292

@@ -2273,19 +2273,21 @@ bool PortsOrch::initPort(const string &alias, const string &role, const int inde
22732273
vector<FieldValueTuple> fields;
22742274
fields.push_back(tuple);
22752275
m_counterTable->set("", fields);
2276+
22762277
// Install a flex counter for this port to track stats
2277-
std::unordered_set<std::string> counter_stats;
2278-
for (const auto& it: port_stat_ids)
2278+
auto flex_counters_orch = gDirectory.get<FlexCounterOrch*>();
2279+
/* Delay installing the counters if they are yet enabled
2280+
If they are enabled, install the counters immediately */
2281+
if (flex_counters_orch->getPortCountersState())
22792282
{
2280-
counter_stats.emplace(sai_serialize_port_stat(it));
2283+
auto port_counter_stats = generateCounterStats(PORT_STAT_COUNTER_FLEX_COUNTER_GROUP);
2284+
port_stat_manager.setCounterIdList(p.m_port_id, CounterType::PORT, port_counter_stats);
22812285
}
2282-
port_stat_manager.setCounterIdList(p.m_port_id, CounterType::PORT, counter_stats);
2283-
std::unordered_set<std::string> port_buffer_drop_stats;
2284-
for (const auto& it: port_buffer_drop_stat_ids)
2286+
if (flex_counters_orch->getPortBufferDropCountersState())
22852287
{
2286-
port_buffer_drop_stats.emplace(sai_serialize_port_stat(it));
2288+
auto port_buffer_drop_stats = generateCounterStats(PORT_BUFFER_DROP_STAT_FLEX_COUNTER_GROUP);
2289+
port_buffer_drop_stat_manager.setCounterIdList(p.m_port_id, CounterType::PORT, port_buffer_drop_stats);
22872290
}
2288-
port_buffer_drop_stat_manager.setCounterIdList(p.m_port_id, CounterType::PORT, port_buffer_drop_stats);
22892291

22902292
PortUpdate update = { p, true };
22912293
notify(SUBJECT_TYPE_PORT_CHANGE, static_cast<void *>(&update));
@@ -2318,8 +2320,11 @@ void PortsOrch::deInitPort(string alias, sai_object_id_t port_id)
23182320
p.m_port_id = port_id;
23192321

23202322
/* remove port from flex_counter_table for updating counters */
2321-
port_stat_manager.clearCounterIdList(p.m_port_id);
2322-
2323+
auto flex_counters_orch = gDirectory.get<FlexCounterOrch*>();
2324+
if ((flex_counters_orch->getPortCountersState()))
2325+
{
2326+
port_stat_manager.clearCounterIdList(p.m_port_id);
2327+
}
23232328
/* remove port name map from counter table */
23242329
m_counter_db->hdel(COUNTERS_PORT_NAME_MAP, alias);
23252330

@@ -5072,6 +5077,48 @@ void PortsOrch::generatePriorityGroupMapPerPort(const Port& port)
50725077
CounterCheckOrch::getInstance().addPort(port);
50735078
}
50745079

5080+
void PortsOrch::generatePortCounterMap()
5081+
{
5082+
if (m_isPortCounterMapGenerated)
5083+
{
5084+
return;
5085+
}
5086+
5087+
auto port_counter_stats = generateCounterStats(PORT_STAT_COUNTER_FLEX_COUNTER_GROUP);
5088+
for (const auto& it: m_portList)
5089+
{
5090+
// Set counter stats only for PHY ports to ensure syncd will not try to query the counter statistics from the HW for non-PHY ports.
5091+
if (it.second.m_type != Port::Type::PHY)
5092+
{
5093+
continue;
5094+
}
5095+
port_stat_manager.setCounterIdList(it.second.m_port_id, CounterType::PORT, port_counter_stats);
5096+
}
5097+
5098+
m_isPortCounterMapGenerated = true;
5099+
}
5100+
5101+
void PortsOrch::generatePortBufferDropCounterMap()
5102+
{
5103+
if (m_isPortBufferDropCounterMapGenerated)
5104+
{
5105+
return;
5106+
}
5107+
5108+
auto port_buffer_drop_stats = generateCounterStats(PORT_BUFFER_DROP_STAT_FLEX_COUNTER_GROUP);
5109+
for (const auto& it: m_portList)
5110+
{
5111+
// Set counter stats only for PHY ports to ensure syncd will not try to query the counter statistics from the HW for non-PHY ports.
5112+
if (it.second.m_type != Port::Type::PHY)
5113+
{
5114+
continue;
5115+
}
5116+
port_buffer_drop_stat_manager.setCounterIdList(it.second.m_port_id, CounterType::PORT, port_buffer_drop_stats);
5117+
}
5118+
5119+
m_isPortBufferDropCounterMapGenerated = true;
5120+
}
5121+
50755122
void PortsOrch::doTask(NotificationConsumer &consumer)
50765123
{
50775124
SWSS_LOG_ENTER();
@@ -6232,3 +6279,23 @@ void PortsOrch::voqSyncDelLagMember(Port &lag, Port &port)
62326279
string key = lag.m_system_lag_info.alias + ":" + port.m_system_port_info.alias;
62336280
m_tableVoqSystemLagMemberTable->del(key);
62346281
}
6282+
6283+
std::unordered_set<std::string> PortsOrch::generateCounterStats(const string& type)
6284+
{
6285+
std::unordered_set<std::string> counter_stats;
6286+
if (type == PORT_STAT_COUNTER_FLEX_COUNTER_GROUP)
6287+
{
6288+
for (const auto& it: port_stat_ids)
6289+
{
6290+
counter_stats.emplace(sai_serialize_port_stat(it));
6291+
}
6292+
}
6293+
else if (type == PORT_BUFFER_DROP_STAT_FLEX_COUNTER_GROUP)
6294+
{
6295+
for (const auto& it: port_buffer_drop_stat_ids)
6296+
{
6297+
counter_stats.emplace(sai_serialize_port_stat(it));
6298+
}
6299+
}
6300+
return counter_stats;
6301+
}

orchagent/portsorch.h

+8
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
#include "gearboxutils.h"
1414
#include "saihelper.h"
1515
#include "lagid.h"
16+
#include "flexcounterorch.h"
1617

1718

1819
#define FCS_LEN 4
@@ -125,6 +126,8 @@ class PortsOrch : public Orch, public Subject
125126

126127
void generateQueueMap();
127128
void generatePriorityGroupMap();
129+
void generatePortCounterMap();
130+
void generatePortBufferDropCounterMap();
128131

129132
void refreshPortStatus();
130133
bool removeAclTableGroup(const Port &p);
@@ -290,6 +293,9 @@ class PortsOrch : public Orch, public Subject
290293
bool m_isPriorityGroupMapGenerated = false;
291294
void generatePriorityGroupMapPerPort(const Port& port);
292295

296+
bool m_isPortCounterMapGenerated = false;
297+
bool m_isPortBufferDropCounterMapGenerated = false;
298+
293299
bool setPortAutoNeg(sai_object_id_t id, int an);
294300
bool setPortFecMode(sai_object_id_t id, int fec);
295301
bool setPortInterfaceType(sai_object_id_t id, sai_port_interface_type_t interface_type);
@@ -333,6 +339,8 @@ class PortsOrch : public Orch, public Subject
333339
void voqSyncDelLagMember(Port &lag, Port &port);
334340
unique_ptr<LagIdAllocator> m_lagIdAllocator;
335341

342+
std::unordered_set<std::string> generateCounterStats(const string& type);
343+
336344
};
337345
#endif /* SWSS_PORTSORCH_H */
338346

tests/mock_tests/mock_orchagent_main.h

+3
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,8 @@
1515
#include "vxlanorch.h"
1616
#include "policerorch.h"
1717
#include "fgnhgorch.h"
18+
#include "flexcounterorch.h"
19+
#include "directory.h"
1820

1921
extern int gBatchSize;
2022
extern bool gSwssRecord;
@@ -42,6 +44,7 @@ extern FdbOrch *gFdbOrch;
4244
extern MirrorOrch *gMirrorOrch;
4345
extern BufferOrch *gBufferOrch;
4446
extern VRFOrch *gVrfOrch;
47+
extern Directory<Orch*> gDirectory;
4548

4649
extern sai_acl_api_t *sai_acl_api;
4750
extern sai_switch_api_t *sai_switch_api;

tests/mock_tests/portsorch_ut.cpp

+6-1
Original file line numberDiff line numberDiff line change
@@ -146,8 +146,13 @@ namespace portsorch_test
146146

147147
ASSERT_EQ(gPortsOrch, nullptr);
148148

149-
gPortsOrch = new PortsOrch(m_app_db.get(), m_state_db.get(), ports_tables, m_chassis_app_db.get());
149+
vector<string> flex_counter_tables = {
150+
CFG_FLEX_COUNTER_TABLE_NAME
151+
};
152+
auto* flexCounterOrch = new FlexCounterOrch(m_config_db.get(), flex_counter_tables);
153+
gDirectory.set(flexCounterOrch);
150154

155+
gPortsOrch = new PortsOrch(m_app_db.get(), m_state_db.get(), ports_tables, m_chassis_app_db.get());
151156
vector<string> buffer_tables = { APP_BUFFER_POOL_TABLE_NAME,
152157
APP_BUFFER_PROFILE_TABLE_NAME,
153158
APP_BUFFER_QUEUE_TABLE_NAME,

0 commit comments

Comments
 (0)