Skip to content

Commit b0fb392

Browse files
authored
[flex-counters] [202012] Delay flex counters stats init for faster boot time (#1804)
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 <shlomibi@nvidia.com>
1 parent bb383be commit b0fb392

9 files changed

Lines changed: 262 additions & 25 deletions

File tree

orchagent/flexcounterorch.cpp

Lines changed: 41 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,11 @@ extern IntfsOrch *gIntfsOrch;
1616
extern BufferOrch *gBufferOrch;
1717

1818
#define BUFFER_POOL_WATERMARK_KEY "BUFFER_POOL_WATERMARK"
19+
#define PORT_KEY "PORT"
20+
#define PORT_BUFFER_DROP_KEY "PORT_BUFFER_DROP"
21+
#define QUEUE_KEY "QUEUE"
22+
#define PG_WATERMARK_KEY "PG_WATERMARK"
23+
#define RIF_KEY "RIF"
1924

2025
unordered_map<string, string> flexCounterGroupMap =
2126
{
@@ -95,17 +100,32 @@ void FlexCounterOrch::doTask(Consumer &consumer)
95100
// which is automatically satisfied upon the creation of the orch object that requires
96101
// the syncd flex counter polling service
97102
// This postponement is introduced by design to accelerate the initialization process
98-
//
99-
// generateQueueMap() is called as long as a field "FLEX_COUNTER_STATUS" event is heard,
100-
// regardless of whether the key is "QUEUE" or whether the value is "enable" or "disable"
101-
// This can be because generateQueueMap() installs a fundamental list of queue stats
102-
// that need to be polled. So my doubt here is if queue watermark stats shall be piggybacked
103-
// into the same function as they may not be counted as fundamental
104-
gPortsOrch->generateQueueMap();
105-
gPortsOrch->generatePriorityGroupMap();
106-
gIntfsOrch->generateInterfaceMap();
107-
// Install COUNTER_ID_LIST/ATTR_ID_LIST only when hearing buffer pool watermark enable event
108-
if ((key == BUFFER_POOL_WATERMARK_KEY) && (value == "enable"))
103+
if(gPortsOrch && (value == "enable"))
104+
{
105+
if(key == PORT_KEY)
106+
{
107+
gPortsOrch->generatePortCounterMap();
108+
m_port_counter_enabled = true;
109+
}
110+
else if(key == PORT_BUFFER_DROP_KEY)
111+
{
112+
gPortsOrch->generatePortBufferDropCounterMap();
113+
m_port_buffer_drop_counter_enabled = true;
114+
}
115+
else if(key == QUEUE_KEY)
116+
{
117+
gPortsOrch->generateQueueMap();
118+
}
119+
else if(key == PG_WATERMARK_KEY)
120+
{
121+
gPortsOrch->generatePriorityGroupMap();
122+
}
123+
}
124+
if(gIntfsOrch && (key == RIF_KEY) && (value == "enable"))
125+
{
126+
gIntfsOrch->generateInterfaceMap();
127+
}
128+
if (gBufferOrch && (key == BUFFER_POOL_WATERMARK_KEY) && (value == "enable"))
109129
{
110130
gBufferOrch->generateBufferPoolWatermarkCounterIdList();
111131
}
@@ -124,3 +144,13 @@ void FlexCounterOrch::doTask(Consumer &consumer)
124144
consumer.m_toSync.erase(it++);
125145
}
126146
}
147+
148+
bool FlexCounterOrch::getPortCountersState() const
149+
{
150+
return m_port_counter_enabled;
151+
}
152+
153+
bool FlexCounterOrch::getPortBufferDropCountersState() const
154+
{
155+
return m_port_buffer_drop_counter_enabled;
156+
}

orchagent/flexcounterorch.h

Lines changed: 4 additions & 0 deletions
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

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -330,7 +330,11 @@ bool OrchDaemon::init()
330330
CFG_FLEX_COUNTER_TABLE_NAME
331331
};
332332

333-
m_orchList.push_back(new FlexCounterOrch(m_configDb, flex_counter_tables));
333+
auto* flexCounterOrch = new FlexCounterOrch(m_configDb, flex_counter_tables);
334+
m_orchList.push_back(flexCounterOrch);
335+
336+
gDirectory.set(flexCounterOrch);
337+
gDirectory.set(gPortsOrch);
334338

335339
vector<string> pfc_wd_tables = {
336340
CFG_PFC_WD_TABLE_NAME

orchagent/portsorch.cpp

Lines changed: 79 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -226,9 +226,9 @@ static char* hostif_vlan_tag[] = {
226226
*/
227227
PortsOrch::PortsOrch(DBConnector *db, vector<table_name_with_pri_t> &tableNames) :
228228
Orch(db, tableNames),
229-
port_stat_manager(PORT_STAT_COUNTER_FLEX_COUNTER_GROUP, StatsMode::READ, PORT_STAT_FLEX_COUNTER_POLLING_INTERVAL_MS, true),
230-
port_buffer_drop_stat_manager(PORT_BUFFER_DROP_STAT_FLEX_COUNTER_GROUP, StatsMode::READ, PORT_BUFFER_DROP_STAT_POLLING_INTERVAL_MS, true),
231-
queue_stat_manager(QUEUE_STAT_COUNTER_FLEX_COUNTER_GROUP, StatsMode::READ, QUEUE_STAT_FLEX_COUNTER_POLLING_INTERVAL_MS, true)
229+
port_stat_manager(PORT_STAT_COUNTER_FLEX_COUNTER_GROUP, StatsMode::READ, PORT_STAT_FLEX_COUNTER_POLLING_INTERVAL_MS, false),
230+
port_buffer_drop_stat_manager(PORT_BUFFER_DROP_STAT_FLEX_COUNTER_GROUP, StatsMode::READ, PORT_BUFFER_DROP_STAT_POLLING_INTERVAL_MS, false),
231+
queue_stat_manager(QUEUE_STAT_COUNTER_FLEX_COUNTER_GROUP, StatsMode::READ, QUEUE_STAT_FLEX_COUNTER_POLLING_INTERVAL_MS, false)
232232
{
233233
SWSS_LOG_ENTER();
234234

@@ -2012,19 +2012,21 @@ bool PortsOrch::initPort(const string &alias, const int index, const set<int> &l
20122012
vector<FieldValueTuple> fields;
20132013
fields.push_back(tuple);
20142014
m_counterTable->set("", fields);
2015+
20152016
// Install a flex counter for this port to track stats
2016-
std::unordered_set<std::string> counter_stats;
2017-
for (const auto& it: port_stat_ids)
2017+
auto flex_counters_orch = gDirectory.get<FlexCounterOrch*>();
2018+
/* Delay installing the counters if they are yet enabled
2019+
If they are enabled, install the counters immediately */
2020+
if (flex_counters_orch->getPortCountersState())
20182021
{
2019-
counter_stats.emplace(sai_serialize_port_stat(it));
2022+
auto port_counter_stats = generateCounterStats(PORT_STAT_COUNTER_FLEX_COUNTER_GROUP);
2023+
port_stat_manager.setCounterIdList(p.m_port_id, CounterType::PORT, port_counter_stats);
20202024
}
2021-
port_stat_manager.setCounterIdList(p.m_port_id, CounterType::PORT, counter_stats);
2022-
std::unordered_set<std::string> port_buffer_drop_stats;
2023-
for (const auto& it: port_buffer_drop_stat_ids)
2025+
if (flex_counters_orch->getPortBufferDropCountersState())
20242026
{
2025-
port_buffer_drop_stats.emplace(sai_serialize_port_stat(it));
2027+
auto port_buffer_drop_stats = generateCounterStats(PORT_BUFFER_DROP_STAT_FLEX_COUNTER_GROUP);
2028+
port_buffer_drop_stat_manager.setCounterIdList(p.m_port_id, CounterType::PORT, port_buffer_drop_stats);
20262029
}
2027-
port_buffer_drop_stat_manager.setCounterIdList(p.m_port_id, CounterType::PORT, port_buffer_drop_stats);
20282030

20292031
PortUpdate update = { p, true };
20302032
notify(SUBJECT_TYPE_PORT_CHANGE, static_cast<void *>(&update));
@@ -2057,8 +2059,11 @@ void PortsOrch::deInitPort(string alias, sai_object_id_t port_id)
20572059
p.m_port_id = port_id;
20582060

20592061
/* remove port from flex_counter_table for updating counters */
2060-
port_stat_manager.clearCounterIdList(p.m_port_id);
2061-
2062+
auto flex_counters_orch = gDirectory.get<FlexCounterOrch*>();
2063+
if ((flex_counters_orch->getPortCountersState()))
2064+
{
2065+
port_stat_manager.clearCounterIdList(p.m_port_id);
2066+
}
20622067
/* remove port name map from counter table */
20632068
m_counter_db->hdel(COUNTERS_PORT_NAME_MAP, alias);
20642069

@@ -4375,6 +4380,48 @@ void PortsOrch::generatePriorityGroupMapPerPort(const Port& port)
43754380
CounterCheckOrch::getInstance().addPort(port);
43764381
}
43774382

4383+
void PortsOrch::generatePortCounterMap()
4384+
{
4385+
if (m_isPortCounterMapGenerated)
4386+
{
4387+
return;
4388+
}
4389+
4390+
auto port_counter_stats = generateCounterStats(PORT_STAT_COUNTER_FLEX_COUNTER_GROUP);
4391+
for (const auto& it: m_portList)
4392+
{
4393+
// 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.
4394+
if (it.second.m_type != Port::Type::PHY)
4395+
{
4396+
continue;
4397+
}
4398+
port_stat_manager.setCounterIdList(it.second.m_port_id, CounterType::PORT, port_counter_stats);
4399+
}
4400+
4401+
m_isPortCounterMapGenerated = true;
4402+
}
4403+
4404+
void PortsOrch::generatePortBufferDropCounterMap()
4405+
{
4406+
if (m_isPortBufferDropCounterMapGenerated)
4407+
{
4408+
return;
4409+
}
4410+
4411+
auto port_buffer_drop_stats = generateCounterStats(PORT_BUFFER_DROP_STAT_FLEX_COUNTER_GROUP);
4412+
for (const auto& it: m_portList)
4413+
{
4414+
// 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.
4415+
if (it.second.m_type != Port::Type::PHY)
4416+
{
4417+
continue;
4418+
}
4419+
port_buffer_drop_stat_manager.setCounterIdList(it.second.m_port_id, CounterType::PORT, port_buffer_drop_stats);
4420+
}
4421+
4422+
m_isPortBufferDropCounterMapGenerated = true;
4423+
}
4424+
43784425
void PortsOrch::doTask(NotificationConsumer &consumer)
43794426
{
43804427
SWSS_LOG_ENTER();
@@ -4958,3 +5005,22 @@ bool PortsOrch::initGearboxPort(Port &port)
49585005
return true;
49595006
}
49605007

5008+
std::unordered_set<std::string> PortsOrch::generateCounterStats(const string& type)
5009+
{
5010+
std::unordered_set<std::string> counter_stats;
5011+
if (type == PORT_STAT_COUNTER_FLEX_COUNTER_GROUP)
5012+
{
5013+
for (const auto& it: port_stat_ids)
5014+
{
5015+
counter_stats.emplace(sai_serialize_port_stat(it));
5016+
}
5017+
}
5018+
else if (type == PORT_BUFFER_DROP_STAT_FLEX_COUNTER_GROUP)
5019+
{
5020+
for (const auto& it: port_buffer_drop_stat_ids)
5021+
{
5022+
counter_stats.emplace(sai_serialize_port_stat(it));
5023+
}
5024+
}
5025+
return counter_stats;
5026+
}

orchagent/portsorch.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
#include "flex_counter_manager.h"
1313
#include "gearboxutils.h"
1414
#include "saihelper.h"
15+
#include "flexcounterorch.h"
1516

1617

1718
#define FCS_LEN 4
@@ -123,6 +124,8 @@ class PortsOrch : public Orch, public Subject
123124

124125
void generateQueueMap();
125126
void generatePriorityGroupMap();
127+
void generatePortCounterMap();
128+
void generatePortBufferDropCounterMap();
126129

127130
void refreshPortStatus();
128131
bool removeAclTableGroup(const Port &p);
@@ -277,6 +280,9 @@ class PortsOrch : public Orch, public Subject
277280
bool m_isPriorityGroupMapGenerated = false;
278281
void generatePriorityGroupMapPerPort(const Port& port);
279282

283+
bool m_isPortCounterMapGenerated = false;
284+
bool m_isPortBufferDropCounterMapGenerated = false;
285+
280286
bool setPortAutoNeg(sai_object_id_t id, int an);
281287
bool setPortFecMode(sai_object_id_t id, int fec);
282288

@@ -296,6 +302,8 @@ class PortsOrch : public Orch, public Subject
296302
void initGearbox();
297303
bool initGearboxPort(Port &port);
298304

305+
std::unordered_set<std::string> generateCounterStats(const string& type);
306+
299307
};
300308
#endif /* SWSS_PORTSORCH_H */
301309

tests/mock_tests/mock_orchagent_main.h

Lines changed: 3 additions & 0 deletions
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

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -142,6 +142,14 @@ namespace portsorch_test
142142
};
143143

144144
ASSERT_EQ(gPortsOrch, nullptr);
145+
146+
vector<string> flex_counter_tables = {
147+
CFG_FLEX_COUNTER_TABLE_NAME
148+
};
149+
auto* flexCounterOrch = new FlexCounterOrch(m_config_db.get(), flex_counter_tables);
150+
151+
gDirectory.set(flexCounterOrch);
152+
145153
gPortsOrch = new PortsOrch(m_app_db.get(), ports_tables);
146154
vector<string> buffer_tables = { APP_BUFFER_POOL_TABLE_NAME,
147155
APP_BUFFER_PROFILE_TABLE_NAME,

0 commit comments

Comments
 (0)