Skip to content

Commit 58870d9

Browse files
committed
Add port counters collector thread (sonic-net#12)
* Add port counters collector thread * Use VID for port ID counter statistics * Get only supported counters, allow tune interval
1 parent 8aca74a commit 58870d9

File tree

6 files changed

+289
-4
lines changed

6 files changed

+289
-4
lines changed

common/saiserialize.cpp

+119
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
#include "saiserialize.h"
22

3+
#include <vector>
4+
35
sai_serialization_map_t g_serialization_map = sai_get_serialization_map();
46
sai_object_type_to_string_map_t g_object_type_map = sai_get_object_type_map();
57

@@ -128,6 +130,123 @@ sai_status_t sai_get_object_type_string(sai_object_type_t object_type, std::stri
128130
return SAI_STATUS_SUCCESS;
129131
}
130132

133+
static std::vector<std::string> sai_get_port_stat_counter_names()
134+
{
135+
SWSS_LOG_ENTER();
136+
137+
std::vector<std::string> v;
138+
139+
v.resize(SAI_PORT_STAT_ETHER_OUT_PKTS_9217_TO_16383_OCTETS + 1);
140+
141+
#define ENTRY(x) v[x] = std::string( #x )
142+
143+
ENTRY(SAI_PORT_STAT_IF_IN_OCTETS);
144+
ENTRY(SAI_PORT_STAT_IF_IN_UCAST_PKTS);
145+
ENTRY(SAI_PORT_STAT_IF_IN_NON_UCAST_PKTS);
146+
ENTRY(SAI_PORT_STAT_IF_IN_DISCARDS);
147+
ENTRY(SAI_PORT_STAT_IF_IN_ERRORS);
148+
ENTRY(SAI_PORT_STAT_IF_IN_UNKNOWN_PROTOS);
149+
ENTRY(SAI_PORT_STAT_IF_IN_BROADCAST_PKTS);
150+
ENTRY(SAI_PORT_STAT_IF_IN_MULTICAST_PKTS);
151+
ENTRY(SAI_PORT_STAT_IF_IN_VLAN_DISCARDS);
152+
ENTRY(SAI_PORT_STAT_IF_OUT_OCTETS);
153+
ENTRY(SAI_PORT_STAT_IF_OUT_UCAST_PKTS);
154+
ENTRY(SAI_PORT_STAT_IF_OUT_NON_UCAST_PKTS);
155+
ENTRY(SAI_PORT_STAT_IF_OUT_DISCARDS);
156+
ENTRY(SAI_PORT_STAT_IF_OUT_ERRORS);
157+
ENTRY(SAI_PORT_STAT_IF_OUT_QLEN);
158+
ENTRY(SAI_PORT_STAT_IF_OUT_BROADCAST_PKTS);
159+
ENTRY(SAI_PORT_STAT_IF_OUT_MULTICAST_PKTS);
160+
ENTRY(SAI_PORT_STAT_ETHER_STATS_DROP_EVENTS);
161+
ENTRY(SAI_PORT_STAT_ETHER_STATS_MULTICAST_PKTS);
162+
ENTRY(SAI_PORT_STAT_ETHER_STATS_BROADCAST_PKTS);
163+
ENTRY(SAI_PORT_STAT_ETHER_STATS_UNDERSIZE_PKTS);
164+
ENTRY(SAI_PORT_STAT_ETHER_STATS_FRAGMENTS);
165+
ENTRY(SAI_PORT_STAT_ETHER_STATS_PKTS_64_OCTETS);
166+
ENTRY(SAI_PORT_STAT_ETHER_STATS_PKTS_65_TO_127_OCTETS);
167+
ENTRY(SAI_PORT_STAT_ETHER_STATS_PKTS_128_TO_255_OCTETS);
168+
ENTRY(SAI_PORT_STAT_ETHER_STATS_PKTS_256_TO_511_OCTETS);
169+
ENTRY(SAI_PORT_STAT_ETHER_STATS_PKTS_512_TO_1023_OCTETS);
170+
ENTRY(SAI_PORT_STAT_ETHER_STATS_PKTS_1024_TO_1518_OCTETS);
171+
ENTRY(SAI_PORT_STAT_ETHER_STATS_PKTS_1519_TO_2047_OCTETS);
172+
ENTRY(SAI_PORT_STAT_ETHER_STATS_PKTS_2048_TO_4095_OCTETS);
173+
ENTRY(SAI_PORT_STAT_ETHER_STATS_PKTS_4096_TO_9216_OCTETS);
174+
ENTRY(SAI_PORT_STAT_ETHER_STATS_PKTS_9217_TO_16383_OCTETS);
175+
ENTRY(SAI_PORT_STAT_ETHER_STATS_OVERSIZE_PKTS);
176+
ENTRY(SAI_PORT_STAT_ETHER_RX_OVERSIZE_PKTS);
177+
ENTRY(SAI_PORT_STAT_ETHER_TX_OVERSIZE_PKTS);
178+
ENTRY(SAI_PORT_STAT_ETHER_STATS_JABBERS);
179+
ENTRY(SAI_PORT_STAT_ETHER_STATS_OCTETS);
180+
ENTRY(SAI_PORT_STAT_ETHER_STATS_PKTS);
181+
ENTRY(SAI_PORT_STAT_ETHER_STATS_COLLISIONS);
182+
ENTRY(SAI_PORT_STAT_ETHER_STATS_CRC_ALIGN_ERRORS);
183+
ENTRY(SAI_PORT_STAT_ETHER_STATS_TX_NO_ERRORS);
184+
ENTRY(SAI_PORT_STAT_ETHER_STATS_RX_NO_ERRORS);
185+
ENTRY(SAI_PORT_STAT_IP_IN_RECEIVES);
186+
ENTRY(SAI_PORT_STAT_IP_IN_OCTETS);
187+
ENTRY(SAI_PORT_STAT_IP_IN_UCAST_PKTS);
188+
ENTRY(SAI_PORT_STAT_IP_IN_NON_UCAST_PKTS);
189+
ENTRY(SAI_PORT_STAT_IP_IN_DISCARDS);
190+
ENTRY(SAI_PORT_STAT_IP_OUT_OCTETS);
191+
ENTRY(SAI_PORT_STAT_IP_OUT_UCAST_PKTS);
192+
ENTRY(SAI_PORT_STAT_IP_OUT_NON_UCAST_PKTS);
193+
ENTRY(SAI_PORT_STAT_IP_OUT_DISCARDS);
194+
ENTRY(SAI_PORT_STAT_IPV6_IN_RECEIVES);
195+
ENTRY(SAI_PORT_STAT_IPV6_IN_OCTETS);
196+
ENTRY(SAI_PORT_STAT_IPV6_IN_UCAST_PKTS);
197+
ENTRY(SAI_PORT_STAT_IPV6_IN_NON_UCAST_PKTS);
198+
ENTRY(SAI_PORT_STAT_IPV6_IN_MCAST_PKTS);
199+
ENTRY(SAI_PORT_STAT_IPV6_IN_DISCARDS);
200+
ENTRY(SAI_PORT_STAT_IPV6_OUT_OCTETS);
201+
ENTRY(SAI_PORT_STAT_IPV6_OUT_UCAST_PKTS);
202+
ENTRY(SAI_PORT_STAT_IPV6_OUT_NON_UCAST_PKTS);
203+
ENTRY(SAI_PORT_STAT_IPV6_OUT_MCAST_PKTS);
204+
ENTRY(SAI_PORT_STAT_IPV6_OUT_DISCARDS);
205+
ENTRY(SAI_PORT_STAT_GREEN_DISCARD_DROPPED_PACKETS);
206+
ENTRY(SAI_PORT_STAT_GREEN_DISCARD_DROPPED_BYTES);
207+
ENTRY(SAI_PORT_STAT_YELLOW_DISCARD_DROPPED_PACKETS);
208+
ENTRY(SAI_PORT_STAT_YELLOW_DISCARD_DROPPED_BYTES);
209+
ENTRY(SAI_PORT_STAT_RED_DISCARD_DROPPED_PACKETS);
210+
ENTRY(SAI_PORT_STAT_RED_DISCARD_DROPPED_BYTES);
211+
ENTRY(SAI_PORT_STAT_DISCARD_DROPPED_PACKETS);
212+
ENTRY(SAI_PORT_STAT_DISCARD_DROPPED_BYTES);
213+
ENTRY(SAI_PORT_STAT_ETHER_IN_PKTS_64_OCTETS);
214+
ENTRY(SAI_PORT_STAT_ETHER_IN_PKTS_65_TO_127_OCTETS);
215+
ENTRY(SAI_PORT_STAT_ETHER_IN_PKTS_128_TO_255_OCTETS);
216+
ENTRY(SAI_PORT_STAT_ETHER_IN_PKTS_256_TO_511_OCTETS);
217+
ENTRY(SAI_PORT_STAT_ETHER_IN_PKTS_512_TO_1023_OCTETS);
218+
ENTRY(SAI_PORT_STAT_ETHER_IN_PKTS_1024_TO_1518_OCTETS);
219+
ENTRY(SAI_PORT_STAT_ETHER_IN_PKTS_1519_TO_2047_OCTETS);
220+
ENTRY(SAI_PORT_STAT_ETHER_IN_PKTS_2048_TO_4095_OCTETS);
221+
ENTRY(SAI_PORT_STAT_ETHER_IN_PKTS_4096_TO_9216_OCTETS);
222+
ENTRY(SAI_PORT_STAT_ETHER_IN_PKTS_9217_TO_16383_OCTETS);
223+
ENTRY(SAI_PORT_STAT_ETHER_OUT_PKTS_64_OCTETS);
224+
ENTRY(SAI_PORT_STAT_ETHER_OUT_PKTS_65_TO_127_OCTETS);
225+
ENTRY(SAI_PORT_STAT_ETHER_OUT_PKTS_128_TO_255_OCTETS);
226+
ENTRY(SAI_PORT_STAT_ETHER_OUT_PKTS_256_TO_511_OCTETS);
227+
ENTRY(SAI_PORT_STAT_ETHER_OUT_PKTS_512_TO_1023_OCTETS);
228+
ENTRY(SAI_PORT_STAT_ETHER_OUT_PKTS_1024_TO_1518_OCTETS);
229+
ENTRY(SAI_PORT_STAT_ETHER_OUT_PKTS_1519_TO_2047_OCTETS);
230+
ENTRY(SAI_PORT_STAT_ETHER_OUT_PKTS_2048_TO_4095_OCTETS);
231+
ENTRY(SAI_PORT_STAT_ETHER_OUT_PKTS_4096_TO_9216_OCTETS);
232+
ENTRY(SAI_PORT_STAT_ETHER_OUT_PKTS_9217_TO_16383_OCTETS);
233+
234+
return std::move(v);
235+
}
236+
237+
static std::vector<std::string> g_port_stat_counter_names = sai_get_port_stat_counter_names();
238+
239+
std::string sai_get_port_stat_counter_name(sai_port_stat_counter_t counter)
240+
{
241+
if (counter < g_port_stat_counter_names.size())
242+
return g_port_stat_counter_names[counter];
243+
244+
SWSS_LOG_WARN("unable to find counter name: %d", counter);
245+
246+
// TODO exit here ?
247+
return std::to_string(counter);
248+
}
249+
131250
sai_status_t sai_get_serialization_type(
132251
_In_ const sai_object_type_t object_type,
133252
_In_ const sai_attr_id_t attr_id,

common/saiserialize.h

+2
Original file line numberDiff line numberDiff line change
@@ -334,4 +334,6 @@ void transfer_attributes(
334334
_In_ sai_attribute_t *dst_attr_list,
335335
_In_ bool countOnly);
336336

337+
std::string sai_get_port_stat_counter_name(sai_port_stat_counter_t counter);
338+
337339
#endif // __SAI_SERIALIZE__

syncd/Makefile.am

+1
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ syncd_SOURCES = syncd.cpp \
2222
syncd_reinit.cpp \
2323
syncd_hard_reinit.cpp \
2424
syncd_notifications.cpp \
25+
syncd_counters.cpp \
2526
../common/redisclient.cpp \
2627
../common/saiserialize.cpp \
2728
../common/saiattribute.cpp \

syncd/syncd.cpp

+32-4
Original file line numberDiff line numberDiff line change
@@ -902,7 +902,9 @@ void notifySyncd(swss::NotificationConsumer &consumer)
902902

903903
struct cmdOptions
904904
{
905+
int countersThreadIntervalInSeconds;
905906
bool diagShell;
907+
bool disableCountersThread;
906908
std::string profileMapFile;
907909
};
908910

@@ -912,24 +914,35 @@ cmdOptions handleCmdLine(int argc, char **argv)
912914

913915
cmdOptions options = {};
914916

917+
const int defaultCountersThreadIntervalInSeconds = 1;
918+
919+
options.countersThreadIntervalInSeconds = defaultCountersThreadIntervalInSeconds;
920+
915921
while(true)
916922
{
917923
static struct option long_options[] =
918924
{
919-
{"diag", no_argument, 0, 'd' },
920-
{"profile", required_argument, 0, 'p' },
921-
{0, 0, 0, 0}
925+
{ "diag", no_argument, 0, 'd' },
926+
{ "nocounters", no_argument, 0, 'N' },
927+
{ "profile", required_argument, 0, 'p' },
928+
{ "countersInterval", required_argument, 0, 'i' },
929+
{ 0, 0, 0, 0 }
922930
};
923931

924932
int option_index = 0;
925933

926-
int c = getopt_long(argc, argv, "dp:", long_options, &option_index);
934+
int c = getopt_long(argc, argv, "dNp:i:", long_options, &option_index);
927935

928936
if (c == -1)
929937
break;
930938

931939
switch (c)
932940
{
941+
case 'N':
942+
SWSS_LOG_INFO("disable counters thread");
943+
options.disableCountersThread = true;
944+
break;
945+
933946
case 'd':
934947
SWSS_LOG_INFO("enable diag shell");
935948
options.diagShell = true;
@@ -940,6 +953,12 @@ cmdOptions handleCmdLine(int argc, char **argv)
940953
options.profileMapFile = std::string(optarg);
941954
break;
942955

956+
case 'i':
957+
SWSS_LOG_INFO("counters thread interval: %s", optarg);
958+
options.countersThreadIntervalInSeconds =
959+
std::max(defaultCountersThreadIntervalInSeconds, std::stoi(std::string(optarg)));
960+
break;
961+
943962
case '?':
944963
SWSS_LOG_WARN("unknown get opti option %c", optopt);
945964
exit(EXIT_FAILURE);
@@ -1057,6 +1076,13 @@ int main(int argc, char **argv)
10571076

10581077
SWSS_LOG_INFO("syncd listening for events");
10591078

1079+
if (options.disableCountersThread == false)
1080+
{
1081+
SWSS_LOG_INFO("starting counters thread");
1082+
1083+
startCountersThread(options.countersThreadIntervalInSeconds);
1084+
}
1085+
10601086
swss::Select s;
10611087

10621088
s.addSelectable(getRequest);
@@ -1088,5 +1114,7 @@ int main(int argc, char **argv)
10881114
SWSS_LOG_ERROR("Runtime error: %s", e.what());
10891115
}
10901116

1117+
endCountersThread();
1118+
10911119
sai_api_uninitialize();
10921120
}

syncd/syncd.h

+5
Original file line numberDiff line numberDiff line change
@@ -145,4 +145,9 @@ extern swss::DBConnector *db;
145145
void initialize_common_api_pointers();
146146
void populate_sai_apis();
147147

148+
void startCountersThread(int intervalInSeconds);
149+
void endCountersThread();
150+
151+
std::vector<sai_object_id_t> saiGetPortList();
152+
148153
#endif // __SYNCD_H__

syncd/syncd_counters.cpp

+130
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,130 @@
1+
#include "syncd.h"
2+
3+
void collectCounters(swss::Table &countersTable,
4+
const std::vector<sai_port_stat_counter_t> &supportedCounters)
5+
{
6+
// collect counters should be under mutex
7+
// sice configuration can change and we
8+
// don't want that during counters collection
9+
std::lock_guard<std::mutex> lock(g_mutex);
10+
11+
SWSS_LOG_ENTER();
12+
13+
SWSS_LOG_TIMER("get counters");
14+
15+
uint32_t countersSize = supportedCounters.size();
16+
17+
std::vector<uint64_t> counters;
18+
19+
counters.resize(countersSize);
20+
21+
auto ports = saiGetPortList();
22+
23+
for (auto &portId: ports)
24+
{
25+
sai_status_t status = sai_port_api->get_port_stats(portId, supportedCounters.data(), countersSize, counters.data());
26+
27+
if (status != SAI_STATUS_SUCCESS)
28+
{
29+
SWSS_LOG_ERROR("failed to collect counters for port %llx: %d", portId, status);
30+
return;
31+
}
32+
33+
sai_object_id_t vid = translate_rid_to_vid(portId);
34+
35+
std::string strPortId;
36+
sai_serialize_primitive(vid, strPortId);
37+
38+
std::vector<swss::FieldValueTuple> values;
39+
40+
for (size_t idx = 0; idx < counters.size(); idx++)
41+
{
42+
std::string field = sai_get_port_stat_counter_name(supportedCounters[idx]);
43+
std::string value = std::to_string(counters[idx]);
44+
45+
swss::FieldValueTuple fvt(field, value);
46+
47+
values.push_back(fvt);
48+
}
49+
50+
countersTable.set(strPortId, values, "");
51+
}
52+
}
53+
54+
std::vector<sai_port_stat_counter_t> getSupportedCounters(sai_object_id_t portId)
55+
{
56+
SWSS_LOG_ENTER();
57+
58+
std::vector<sai_port_stat_counter_t> supportedCounters;
59+
60+
for (int idx = SAI_PORT_STAT_IF_IN_OCTETS;
61+
idx <= SAI_PORT_STAT_ETHER_OUT_PKTS_9217_TO_16383_OCTETS;
62+
++idx)
63+
{
64+
sai_port_stat_counter_t counter = (sai_port_stat_counter_t)idx;
65+
66+
uint64_t value;
67+
68+
sai_status_t status = sai_port_api->get_port_stats(portId, &counter, 1, &value);
69+
70+
if (status != SAI_STATUS_SUCCESS)
71+
{
72+
const std::string &name = sai_get_port_stat_counter_name(counter);
73+
74+
SWSS_LOG_WARN("counter %s is not supported on port RID %llx: %d", name.c_str(), portId, status);
75+
continue;
76+
}
77+
78+
supportedCounters.push_back(counter);
79+
}
80+
81+
return std::move(supportedCounters);
82+
}
83+
84+
static volatile bool g_runCountersThread = false;
85+
static std::shared_ptr<std::thread> g_countersThread = NULL;
86+
87+
void collectCountersThread(int intervalInSeconds)
88+
{
89+
SWSS_LOG_ENTER();
90+
91+
swss::DBConnector db(COUNTERS_DB, "localhost", 6379, 0);
92+
swss::Table countersTable(&db, "COUNTERS");
93+
94+
auto ports = saiGetPortList();
95+
96+
// get supported counters on first port
97+
// we assume that all ports will support those counters
98+
const auto &supportedCounters = getSupportedCounters(ports.at(0));
99+
100+
SWSS_LOG_INFO("supported counters count: %ld", supportedCounters.size());
101+
102+
while(g_runCountersThread)
103+
{
104+
collectCounters(countersTable, supportedCounters);
105+
106+
// collect counters every second
107+
sleep(intervalInSeconds);
108+
}
109+
}
110+
111+
void startCountersThread(int intervalInSeconds)
112+
{
113+
SWSS_LOG_ENTER();
114+
115+
g_runCountersThread = true;
116+
117+
g_countersThread = std::shared_ptr<std::thread>(new std::thread(collectCountersThread, intervalInSeconds));
118+
}
119+
120+
void endCountersThread()
121+
{
122+
SWSS_LOG_ENTER();
123+
124+
g_runCountersThread = false;
125+
126+
if (g_countersThread != NULL)
127+
{
128+
g_countersThread->join();
129+
}
130+
}

0 commit comments

Comments
 (0)