Skip to content

Commit

Permalink
Add get_stats SAI API support (sonic-net#247)
Browse files Browse the repository at this point in the history
* Add get_stats SAI API support

Signed-off-by: marian-pritsak <marianp@mellanox.com>

* Support for PG stats

Signed-off-by: marian-pritsak <marianp@mellanox.com>

* Address comments

Signed-off-by: marian-pritsak <marianp@mellanox.com>

* Change from macro to template

Signed-off-by: marian-pritsak <marianp@mellanox.com>

* Simplify traits

Signed-off-by: marian-pritsak <marianp@mellanox.com>
  • Loading branch information
marian-pritsak authored and qiluo-msft committed Nov 3, 2017
1 parent 9658f75 commit 996a81a
Show file tree
Hide file tree
Showing 12 changed files with 516 additions and 38 deletions.
10 changes: 10 additions & 0 deletions lib/inc/sai_redis.h
Original file line number Diff line number Diff line change
Expand Up @@ -219,6 +219,16 @@ sai_status_t redis_generic_get_route_entry(
_In_ uint32_t attr_count,
_Out_ sai_attribute_t *attr_list);

// get_stats

template <typename T>
sai_status_t redis_generic_get_stats(
_In_ sai_object_type_t object_type,
_In_ sai_object_id_t object_id,
_In_ uint32_t count,
_In_ const T* counter_id_list,
_Out_ uint64_t *counter_list);

// notifications

void handle_notification(
Expand Down
20 changes: 20 additions & 0 deletions lib/inc/sai_redis_internal.h
Original file line number Diff line number Diff line change
Expand Up @@ -139,3 +139,23 @@
redis_set_ ## ot ##_attribute, \
redis_get_ ## ot ##_attribute,

// stats

#define REDIS_GENERIC_GET_STATS(OBJECT_TYPE,object_type) \
sai_status_t redis_get_ ## object_type ## _stats( \
_In_ sai_object_id_t object_type ##_id, \
_In_ uint32_t count, \
_In_ const sai_ ## object_type ## _stat_t *counter_id_list, \
_Out_ uint64_t *counter_list) \
{ \
MUTEX(); \
SWSS_LOG_ENTER(); \
\
return meta_sai_get_stats_oid<sai_ ## object_type ## _stat_t>( \
SAI_OBJECT_TYPE_ ## OBJECT_TYPE, \
object_type ## _id, \
count, \
counter_id_list, \
counter_list, \
&redis_generic_get_stats); \
}
3 changes: 2 additions & 1 deletion lib/src/Makefile.am
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,8 @@ libsairedis_la_SOURCES = \
sai_redis_generic_set.cpp \
sai_redis_generic_get.cpp \
sai_redis_notifications.cpp \
sai_redis_record.cpp
sai_redis_record.cpp \
sai_redis_generic_get_stats.cpp

libsairedis_la_CPPFLAGS = $(DBGFLAGS) $(AM_CPPFLAGS) $(CFLAGS_COMMON)
libsairedis_la_LIBADD = -lhiredis -lswsscommon
15 changes: 2 additions & 13 deletions lib/src/sai_redis_buffer.cpp
Original file line number Diff line number Diff line change
@@ -1,18 +1,5 @@
#include "sai_redis.h"

sai_status_t redis_get_ingress_priority_group_stats(
_In_ sai_object_id_t ingress_pg_id,
_In_ uint32_t number_of_counters,
_In_ const sai_ingress_priority_group_stat_t *counter_ids,
_Out_ uint64_t *counters)
{
MUTEX();

SWSS_LOG_ENTER();

return SAI_STATUS_NOT_IMPLEMENTED;
}

sai_status_t redis_clear_ingress_priority_group_stats(
_In_ sai_object_id_t ingress_pg_id,
_In_ uint32_t number_of_counters,
Expand Down Expand Up @@ -54,6 +41,8 @@ REDIS_GENERIC_QUAD(BUFFER_POOL,buffer_pool);
REDIS_GENERIC_QUAD(INGRESS_PRIORITY_GROUP,ingress_priority_group);
REDIS_GENERIC_QUAD(BUFFER_PROFILE,buffer_profile);

REDIS_GENERIC_GET_STATS(INGRESS_PRIORITY_GROUP,ingress_priority_group);

const sai_buffer_api_t redis_buffer_api = {

REDIS_GENERIC_QUAD_API(buffer_pool)
Expand Down
217 changes: 217 additions & 0 deletions lib/src/sai_redis_generic_get_stats.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,217 @@
#include "sai_redis.h"
#include "meta/saiserialize.h"

sai_status_t internal_redis_get_stats_process(
_In_ sai_object_type_t object_type,
_In_ uint32_t count,
_Out_ uint64_t *counter_list,
_In_ swss::KeyOpFieldsValuesTuple &kco)
{
SWSS_LOG_ENTER();

// key: sai_status
// field: stat_id
// value: stat_value

const auto &key = kfvKey(kco);
const auto &values = kfvFieldsValues(kco);

auto str_sai_status = key;

sai_status_t status;

sai_deserialize_status(str_sai_status, status);

if (status == SAI_STATUS_SUCCESS)
{
uint32_t i = 0;
for (const auto &v : values)
{
if (i >= count)
{
SWSS_LOG_ERROR("Received more values than expected");
status = SAI_STATUS_FAILURE;
break;
}

uint64_t value = 0;

value = stoull(fvValue(v));
counter_list[i] = value;
i++;
}
}

return status;
}

template <class T> struct stat_traits {};

template <>
struct stat_traits<sai_port_stat_t>
{
typedef std::string (*serialize_stat)(sai_port_stat_t);
static constexpr serialize_stat serialize_stat_fn = sai_serialize_port_stat;
};

template <>
struct stat_traits<sai_queue_stat_t>
{
typedef std::string (*serialize_stat)(sai_queue_stat_t);
static constexpr serialize_stat serialize_stat_fn = sai_serialize_queue_stat;
};

template <>
struct stat_traits<sai_ingress_priority_group_stat_t>
{
typedef std::string (*serialize_stat)(sai_ingress_priority_group_stat_t);
static constexpr serialize_stat serialize_stat_fn = sai_serialize_ingress_priority_group_stat;
};


template <class T>
std::vector<swss::FieldValueTuple> serialize_counter_id_list(
_In_ uint32_t count,
_In_ const T *counter_id_list)
{
SWSS_LOG_ENTER();

std::vector<swss::FieldValueTuple> values;

for (uint32_t i = 0; i < count; i++)
{
std::string field = stat_traits<T>::serialize_stat_fn(counter_id_list[i]);
values.emplace_back(field, "");
}

return std::move(values);
}

template <typename T>
sai_status_t internal_redis_generic_get_stats(
_In_ sai_object_type_t object_type,
_In_ const std::string &serialized_object_id,
_In_ uint32_t count,
_In_ const T *counter_id_list,
_Out_ uint64_t *counter_list)
{
SWSS_LOG_ENTER();

std::vector<swss::FieldValueTuple> entry = serialize_counter_id_list(
count,
counter_id_list);

std::string str_object_type = sai_serialize_object_type(object_type);

std::string key = str_object_type + ":" + serialized_object_id;

SWSS_LOG_DEBUG("generic get stats key: %s, fields: %lu", key.c_str(), entry.size());

if (g_record)
{
// XXX don't know which character to use for get stats. For now its 'm'
recordLine("m|" + key + "|" + joinFieldValues(entry));
}

// get is special, it will not put data
// into asic view, only to message queue
g_asicState->set(key, entry, "get_stats");

// wait for response

swss::Select s;

s.addSelectable(g_redisGetConsumer.get());

while (true)
{
SWSS_LOG_DEBUG("wait for get_stats response");

swss::Selectable *sel;

int fd;

int result = s.select(&sel, &fd, GET_RESPONSE_TIMEOUT);

if (result == swss::Select::OBJECT)
{
swss::KeyOpFieldsValuesTuple kco;

g_redisGetConsumer->pop(kco);

const std::string &op = kfvOp(kco);
const std::string &opkey = kfvKey(kco);

SWSS_LOG_DEBUG("response: op = %s, key = %s", opkey.c_str(), op.c_str());

if (op != "getresponse") // ignore non response messages
{
continue;
}

sai_status_t status = internal_redis_get_stats_process(
object_type,
count,
counter_list,
kco);

if (g_record)
{
const auto &str_status = kfvKey(kco);
const auto &values = kfvFieldsValues(kco);

// first serialized is status
recordLine("M|" + str_status + "|" + joinFieldValues(values));
}

SWSS_LOG_DEBUG("generic get status: %d", status);

return status;
}

SWSS_LOG_ERROR("generic get failed due to SELECT operation result");
break;
}

if (g_record)
{
recordLine("M|SAI_STATUS_FAILURE");
}

SWSS_LOG_ERROR("generic get stats failed to get response");

return SAI_STATUS_FAILURE;
}

template <typename T>
sai_status_t redis_generic_get_stats(
_In_ sai_object_type_t object_type,
_In_ sai_object_id_t object_id,
_In_ uint32_t count,
_In_ const T* counter_id_list,
_Out_ uint64_t *counter_list)
{
SWSS_LOG_ENTER();

std::string str_object_id = sai_serialize_object_id(object_id);

return internal_redis_generic_get_stats(
object_type,
str_object_id,
count,
counter_id_list,
counter_list);
}

#define DECLARE_REDIS_GENERIC_GET_STATS(type) \
template \
sai_status_t redis_generic_get_stats<sai_ ## type ## _stat_t>( \
_In_ sai_object_type_t object_type, \
_In_ sai_object_id_t object_id, \
_In_ uint32_t count, \
_In_ const sai_ ## type ## _stat_t *counter_id_list, \
_Out_ uint64_t *counter_list); \

DECLARE_REDIS_GENERIC_GET_STATS(port);
DECLARE_REDIS_GENERIC_GET_STATS(queue);
DECLARE_REDIS_GENERIC_GET_STATS(ingress_priority_group);
13 changes: 2 additions & 11 deletions lib/src/sai_redis_port.cpp
Original file line number Diff line number Diff line change
@@ -1,16 +1,5 @@
#include "sai_redis.h"

sai_status_t redis_get_port_stats(
_In_ sai_object_id_t port_id,
_In_ uint32_t number_of_counters,
_In_ const sai_port_stat_t *counter_ids,
_Out_ uint64_t *counters)
{
SWSS_LOG_ENTER();

return SAI_STATUS_NOT_IMPLEMENTED;
}

sai_status_t redis_clear_port_stats(
_In_ sai_object_id_t port_id,
_In_ uint32_t number_of_counters,
Expand All @@ -35,6 +24,8 @@ sai_status_t redis_clear_port_all_stats(

REDIS_GENERIC_QUAD(PORT,port);

REDIS_GENERIC_GET_STATS(PORT, port);

const sai_port_api_t redis_port_api = {

REDIS_GENERIC_QUAD_API(port)
Expand Down
15 changes: 2 additions & 13 deletions lib/src/sai_redis_queue.cpp
Original file line number Diff line number Diff line change
@@ -1,19 +1,6 @@
#include "sai_redis.h"
#include "sai_redis_internal.h"

sai_status_t redis_get_queue_stats(
_In_ sai_object_id_t queue_id,
_In_ uint32_t number_of_counters,
_In_ const sai_queue_stat_t *counter_ids,
_Out_ uint64_t *counters)
{
MUTEX();

SWSS_LOG_ENTER();

return SAI_STATUS_NOT_IMPLEMENTED;
}

sai_status_t redis_clear_queue_stats(
_In_ sai_object_id_t queue_id,
_In_ uint32_t number_of_counters,
Expand All @@ -28,6 +15,8 @@ sai_status_t redis_clear_queue_stats(

REDIS_GENERIC_QUAD(QUEUE,queue);

REDIS_GENERIC_GET_STATS(QUEUE, queue);

const sai_queue_api_t redis_queue_api = {

REDIS_GENERIC_QUAD_API(queue)
Expand Down
Loading

0 comments on commit 996a81a

Please sign in to comment.