Skip to content

Commit 996a81a

Browse files
marian-pritsakqiluo-msft
authored andcommitted
Add get_stats SAI API support (sonic-net#247)
* Add get_stats SAI API support Signed-off-by: marian-pritsak <[email protected]> * Support for PG stats Signed-off-by: marian-pritsak <[email protected]> * Address comments Signed-off-by: marian-pritsak <[email protected]> * Change from macro to template Signed-off-by: marian-pritsak <[email protected]> * Simplify traits Signed-off-by: marian-pritsak <[email protected]>
1 parent 9658f75 commit 996a81a

12 files changed

+516
-38
lines changed

lib/inc/sai_redis.h

+10
Original file line numberDiff line numberDiff line change
@@ -219,6 +219,16 @@ sai_status_t redis_generic_get_route_entry(
219219
_In_ uint32_t attr_count,
220220
_Out_ sai_attribute_t *attr_list);
221221

222+
// get_stats
223+
224+
template <typename T>
225+
sai_status_t redis_generic_get_stats(
226+
_In_ sai_object_type_t object_type,
227+
_In_ sai_object_id_t object_id,
228+
_In_ uint32_t count,
229+
_In_ const T* counter_id_list,
230+
_Out_ uint64_t *counter_list);
231+
222232
// notifications
223233

224234
void handle_notification(

lib/inc/sai_redis_internal.h

+20
Original file line numberDiff line numberDiff line change
@@ -139,3 +139,23 @@
139139
redis_set_ ## ot ##_attribute, \
140140
redis_get_ ## ot ##_attribute,
141141

142+
// stats
143+
144+
#define REDIS_GENERIC_GET_STATS(OBJECT_TYPE,object_type) \
145+
sai_status_t redis_get_ ## object_type ## _stats( \
146+
_In_ sai_object_id_t object_type ##_id, \
147+
_In_ uint32_t count, \
148+
_In_ const sai_ ## object_type ## _stat_t *counter_id_list, \
149+
_Out_ uint64_t *counter_list) \
150+
{ \
151+
MUTEX(); \
152+
SWSS_LOG_ENTER(); \
153+
\
154+
return meta_sai_get_stats_oid<sai_ ## object_type ## _stat_t>( \
155+
SAI_OBJECT_TYPE_ ## OBJECT_TYPE, \
156+
object_type ## _id, \
157+
count, \
158+
counter_id_list, \
159+
counter_list, \
160+
&redis_generic_get_stats); \
161+
}

lib/src/Makefile.am

+2-1
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,8 @@ libsairedis_la_SOURCES = \
4242
sai_redis_generic_set.cpp \
4343
sai_redis_generic_get.cpp \
4444
sai_redis_notifications.cpp \
45-
sai_redis_record.cpp
45+
sai_redis_record.cpp \
46+
sai_redis_generic_get_stats.cpp
4647

4748
libsairedis_la_CPPFLAGS = $(DBGFLAGS) $(AM_CPPFLAGS) $(CFLAGS_COMMON)
4849
libsairedis_la_LIBADD = -lhiredis -lswsscommon

lib/src/sai_redis_buffer.cpp

+2-13
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,5 @@
11
#include "sai_redis.h"
22

3-
sai_status_t redis_get_ingress_priority_group_stats(
4-
_In_ sai_object_id_t ingress_pg_id,
5-
_In_ uint32_t number_of_counters,
6-
_In_ const sai_ingress_priority_group_stat_t *counter_ids,
7-
_Out_ uint64_t *counters)
8-
{
9-
MUTEX();
10-
11-
SWSS_LOG_ENTER();
12-
13-
return SAI_STATUS_NOT_IMPLEMENTED;
14-
}
15-
163
sai_status_t redis_clear_ingress_priority_group_stats(
174
_In_ sai_object_id_t ingress_pg_id,
185
_In_ uint32_t number_of_counters,
@@ -54,6 +41,8 @@ REDIS_GENERIC_QUAD(BUFFER_POOL,buffer_pool);
5441
REDIS_GENERIC_QUAD(INGRESS_PRIORITY_GROUP,ingress_priority_group);
5542
REDIS_GENERIC_QUAD(BUFFER_PROFILE,buffer_profile);
5643

44+
REDIS_GENERIC_GET_STATS(INGRESS_PRIORITY_GROUP,ingress_priority_group);
45+
5746
const sai_buffer_api_t redis_buffer_api = {
5847

5948
REDIS_GENERIC_QUAD_API(buffer_pool)
+217
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,217 @@
1+
#include "sai_redis.h"
2+
#include "meta/saiserialize.h"
3+
4+
sai_status_t internal_redis_get_stats_process(
5+
_In_ sai_object_type_t object_type,
6+
_In_ uint32_t count,
7+
_Out_ uint64_t *counter_list,
8+
_In_ swss::KeyOpFieldsValuesTuple &kco)
9+
{
10+
SWSS_LOG_ENTER();
11+
12+
// key: sai_status
13+
// field: stat_id
14+
// value: stat_value
15+
16+
const auto &key = kfvKey(kco);
17+
const auto &values = kfvFieldsValues(kco);
18+
19+
auto str_sai_status = key;
20+
21+
sai_status_t status;
22+
23+
sai_deserialize_status(str_sai_status, status);
24+
25+
if (status == SAI_STATUS_SUCCESS)
26+
{
27+
uint32_t i = 0;
28+
for (const auto &v : values)
29+
{
30+
if (i >= count)
31+
{
32+
SWSS_LOG_ERROR("Received more values than expected");
33+
status = SAI_STATUS_FAILURE;
34+
break;
35+
}
36+
37+
uint64_t value = 0;
38+
39+
value = stoull(fvValue(v));
40+
counter_list[i] = value;
41+
i++;
42+
}
43+
}
44+
45+
return status;
46+
}
47+
48+
template <class T> struct stat_traits {};
49+
50+
template <>
51+
struct stat_traits<sai_port_stat_t>
52+
{
53+
typedef std::string (*serialize_stat)(sai_port_stat_t);
54+
static constexpr serialize_stat serialize_stat_fn = sai_serialize_port_stat;
55+
};
56+
57+
template <>
58+
struct stat_traits<sai_queue_stat_t>
59+
{
60+
typedef std::string (*serialize_stat)(sai_queue_stat_t);
61+
static constexpr serialize_stat serialize_stat_fn = sai_serialize_queue_stat;
62+
};
63+
64+
template <>
65+
struct stat_traits<sai_ingress_priority_group_stat_t>
66+
{
67+
typedef std::string (*serialize_stat)(sai_ingress_priority_group_stat_t);
68+
static constexpr serialize_stat serialize_stat_fn = sai_serialize_ingress_priority_group_stat;
69+
};
70+
71+
72+
template <class T>
73+
std::vector<swss::FieldValueTuple> serialize_counter_id_list(
74+
_In_ uint32_t count,
75+
_In_ const T *counter_id_list)
76+
{
77+
SWSS_LOG_ENTER();
78+
79+
std::vector<swss::FieldValueTuple> values;
80+
81+
for (uint32_t i = 0; i < count; i++)
82+
{
83+
std::string field = stat_traits<T>::serialize_stat_fn(counter_id_list[i]);
84+
values.emplace_back(field, "");
85+
}
86+
87+
return std::move(values);
88+
}
89+
90+
template <typename T>
91+
sai_status_t internal_redis_generic_get_stats(
92+
_In_ sai_object_type_t object_type,
93+
_In_ const std::string &serialized_object_id,
94+
_In_ uint32_t count,
95+
_In_ const T *counter_id_list,
96+
_Out_ uint64_t *counter_list)
97+
{
98+
SWSS_LOG_ENTER();
99+
100+
std::vector<swss::FieldValueTuple> entry = serialize_counter_id_list(
101+
count,
102+
counter_id_list);
103+
104+
std::string str_object_type = sai_serialize_object_type(object_type);
105+
106+
std::string key = str_object_type + ":" + serialized_object_id;
107+
108+
SWSS_LOG_DEBUG("generic get stats key: %s, fields: %lu", key.c_str(), entry.size());
109+
110+
if (g_record)
111+
{
112+
// XXX don't know which character to use for get stats. For now its 'm'
113+
recordLine("m|" + key + "|" + joinFieldValues(entry));
114+
}
115+
116+
// get is special, it will not put data
117+
// into asic view, only to message queue
118+
g_asicState->set(key, entry, "get_stats");
119+
120+
// wait for response
121+
122+
swss::Select s;
123+
124+
s.addSelectable(g_redisGetConsumer.get());
125+
126+
while (true)
127+
{
128+
SWSS_LOG_DEBUG("wait for get_stats response");
129+
130+
swss::Selectable *sel;
131+
132+
int fd;
133+
134+
int result = s.select(&sel, &fd, GET_RESPONSE_TIMEOUT);
135+
136+
if (result == swss::Select::OBJECT)
137+
{
138+
swss::KeyOpFieldsValuesTuple kco;
139+
140+
g_redisGetConsumer->pop(kco);
141+
142+
const std::string &op = kfvOp(kco);
143+
const std::string &opkey = kfvKey(kco);
144+
145+
SWSS_LOG_DEBUG("response: op = %s, key = %s", opkey.c_str(), op.c_str());
146+
147+
if (op != "getresponse") // ignore non response messages
148+
{
149+
continue;
150+
}
151+
152+
sai_status_t status = internal_redis_get_stats_process(
153+
object_type,
154+
count,
155+
counter_list,
156+
kco);
157+
158+
if (g_record)
159+
{
160+
const auto &str_status = kfvKey(kco);
161+
const auto &values = kfvFieldsValues(kco);
162+
163+
// first serialized is status
164+
recordLine("M|" + str_status + "|" + joinFieldValues(values));
165+
}
166+
167+
SWSS_LOG_DEBUG("generic get status: %d", status);
168+
169+
return status;
170+
}
171+
172+
SWSS_LOG_ERROR("generic get failed due to SELECT operation result");
173+
break;
174+
}
175+
176+
if (g_record)
177+
{
178+
recordLine("M|SAI_STATUS_FAILURE");
179+
}
180+
181+
SWSS_LOG_ERROR("generic get stats failed to get response");
182+
183+
return SAI_STATUS_FAILURE;
184+
}
185+
186+
template <typename T>
187+
sai_status_t redis_generic_get_stats(
188+
_In_ sai_object_type_t object_type,
189+
_In_ sai_object_id_t object_id,
190+
_In_ uint32_t count,
191+
_In_ const T* counter_id_list,
192+
_Out_ uint64_t *counter_list)
193+
{
194+
SWSS_LOG_ENTER();
195+
196+
std::string str_object_id = sai_serialize_object_id(object_id);
197+
198+
return internal_redis_generic_get_stats(
199+
object_type,
200+
str_object_id,
201+
count,
202+
counter_id_list,
203+
counter_list);
204+
}
205+
206+
#define DECLARE_REDIS_GENERIC_GET_STATS(type) \
207+
template \
208+
sai_status_t redis_generic_get_stats<sai_ ## type ## _stat_t>( \
209+
_In_ sai_object_type_t object_type, \
210+
_In_ sai_object_id_t object_id, \
211+
_In_ uint32_t count, \
212+
_In_ const sai_ ## type ## _stat_t *counter_id_list, \
213+
_Out_ uint64_t *counter_list); \
214+
215+
DECLARE_REDIS_GENERIC_GET_STATS(port);
216+
DECLARE_REDIS_GENERIC_GET_STATS(queue);
217+
DECLARE_REDIS_GENERIC_GET_STATS(ingress_priority_group);

lib/src/sai_redis_port.cpp

+2-11
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,5 @@
11
#include "sai_redis.h"
22

3-
sai_status_t redis_get_port_stats(
4-
_In_ sai_object_id_t port_id,
5-
_In_ uint32_t number_of_counters,
6-
_In_ const sai_port_stat_t *counter_ids,
7-
_Out_ uint64_t *counters)
8-
{
9-
SWSS_LOG_ENTER();
10-
11-
return SAI_STATUS_NOT_IMPLEMENTED;
12-
}
13-
143
sai_status_t redis_clear_port_stats(
154
_In_ sai_object_id_t port_id,
165
_In_ uint32_t number_of_counters,
@@ -35,6 +24,8 @@ sai_status_t redis_clear_port_all_stats(
3524

3625
REDIS_GENERIC_QUAD(PORT,port);
3726

27+
REDIS_GENERIC_GET_STATS(PORT, port);
28+
3829
const sai_port_api_t redis_port_api = {
3930

4031
REDIS_GENERIC_QUAD_API(port)

lib/src/sai_redis_queue.cpp

+2-13
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,6 @@
11
#include "sai_redis.h"
22
#include "sai_redis_internal.h"
33

4-
sai_status_t redis_get_queue_stats(
5-
_In_ sai_object_id_t queue_id,
6-
_In_ uint32_t number_of_counters,
7-
_In_ const sai_queue_stat_t *counter_ids,
8-
_Out_ uint64_t *counters)
9-
{
10-
MUTEX();
11-
12-
SWSS_LOG_ENTER();
13-
14-
return SAI_STATUS_NOT_IMPLEMENTED;
15-
}
16-
174
sai_status_t redis_clear_queue_stats(
185
_In_ sai_object_id_t queue_id,
196
_In_ uint32_t number_of_counters,
@@ -28,6 +15,8 @@ sai_status_t redis_clear_queue_stats(
2815

2916
REDIS_GENERIC_QUAD(QUEUE,queue);
3017

18+
REDIS_GENERIC_GET_STATS(QUEUE, queue);
19+
3120
const sai_queue_api_t redis_queue_api = {
3221

3322
REDIS_GENERIC_QUAD_API(queue)

0 commit comments

Comments
 (0)