Skip to content

Commit

Permalink
[sairedis] Client/Server add support for SAI stats api (sonic-net#855)
Browse files Browse the repository at this point in the history
  • Loading branch information
kcudnik committed Jul 6, 2021
1 parent 59fedfa commit 1eacd05
Show file tree
Hide file tree
Showing 3 changed files with 163 additions and 6 deletions.
8 changes: 8 additions & 0 deletions lib/inc/ServerSai.h
Original file line number Diff line number Diff line change
Expand Up @@ -337,6 +337,14 @@ namespace sairedis
_In_ const sai_object_id_t* object_ids,
_In_ const sai_status_t* statuses);

// STATS API

sai_status_t processGetStatsEvent(
_In_ const swss::KeyOpFieldsValuesTuple &kco);

sai_status_t processClearStatsEvent(
_In_ const swss::KeyOpFieldsValuesTuple &kco);

// NON QUAD API

sai_status_t processFdbFlush(
Expand Down
108 changes: 102 additions & 6 deletions lib/src/ServerSai.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -691,12 +691,11 @@ sai_status_t ServerSai::processSingleEvent(
if (op == REDIS_ASIC_STATE_COMMAND_BULK_SET)
return processBulkQuadEvent(SAI_COMMON_API_BULK_SET, kco);

// TODO implement
// if (op == REDIS_ASIC_STATE_COMMAND_GET_STATS)
// return processGetStatsEvent(kco);
//
// if (op == REDIS_ASIC_STATE_COMMAND_CLEAR_STATS)
// return processClearStatsEvent(kco);
if (op == REDIS_ASIC_STATE_COMMAND_GET_STATS)
return processGetStatsEvent(kco);

if (op == REDIS_ASIC_STATE_COMMAND_CLEAR_STATS)
return processClearStatsEvent(kco);

if (op == REDIS_ASIC_STATE_COMMAND_FLUSH)
return processFdbFlush(kco);
Expand Down Expand Up @@ -1737,3 +1736,100 @@ sai_status_t ServerSai::processFdbFlush(

return status;
}

sai_status_t ServerSai::processClearStatsEvent(
_In_ const swss::KeyOpFieldsValuesTuple &kco)
{
SWSS_LOG_ENTER();

const std::string &key = kfvKey(kco);

sai_object_meta_key_t metaKey;
sai_deserialize_object_meta_key(key, metaKey);

auto info = sai_metadata_get_object_type_info(metaKey.objecttype);

if (info->isnonobjectid)
{
SWSS_LOG_THROW("non object id not supported on clear stats: %s, FIXME", key.c_str());
}

std::vector<sai_stat_id_t> counter_ids;

for (auto&v: kfvFieldsValues(kco))
{
int32_t val;
sai_deserialize_enum(fvField(v), info->statenum, val);

counter_ids.push_back(val);
}

auto status = m_sai->clearStats(
metaKey.objecttype,
metaKey.objectkey.key.object_id,
(uint32_t)counter_ids.size(),
counter_ids.data());

m_selectableChannel->set(sai_serialize_status(status), {}, REDIS_ASIC_STATE_COMMAND_GETRESPONSE);

return status;
}

sai_status_t ServerSai::processGetStatsEvent(
_In_ const swss::KeyOpFieldsValuesTuple &kco)
{
SWSS_LOG_ENTER();

const std::string &key = kfvKey(kco);

sai_object_meta_key_t metaKey;
sai_deserialize_object_meta_key(key, metaKey);

// TODO get stats on created object in init view mode could fail

auto info = sai_metadata_get_object_type_info(metaKey.objecttype);

if (info->isnonobjectid)
{
SWSS_LOG_THROW("non object id not supported on clear stats: %s, FIXME", key.c_str());
}

std::vector<sai_stat_id_t> counter_ids;

for (auto&v: kfvFieldsValues(kco))
{
int32_t val;
sai_deserialize_enum(fvField(v), info->statenum, val);

counter_ids.push_back(val);
}

std::vector<uint64_t> result(counter_ids.size());

auto status = m_sai->getStats(
metaKey.objecttype,
metaKey.objectkey.key.object_id,
(uint32_t)counter_ids.size(),
counter_ids.data(),
result.data());

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

if (status != SAI_STATUS_SUCCESS)
{
SWSS_LOG_ERROR("Failed to get stats");
}
else
{
const auto& values = kfvFieldsValues(kco);

for (size_t i = 0; i < values.size(); i++)
{
entry.emplace_back(fvField(values[i]), std::to_string(result[i]));
}
}

m_selectableChannel->set(sai_serialize_status(status), entry, REDIS_ASIC_STATE_COMMAND_GETRESPONSE);

return status;
}
53 changes: 53 additions & 0 deletions tests/testclient.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,8 @@ class TestClient

void test_fdb_flush();

void test_stats();

private:

int profileGetNextValue(
Expand Down Expand Up @@ -457,6 +459,55 @@ void TestClient::test_fdb_flush()
ASSERT_SUCCESS(sai_api_uninitialize());
}

void TestClient::test_stats()
{
SWSS_LOG_ENTER();

m_profileMap.clear();

m_profileMap[SAI_REDIS_KEY_ENABLE_CLIENT] = "true"; // act as a client

m_profileIter = m_profileMap.begin();

m_smt.profileGetValue = std::bind(&TestClient::profileGetValue, this, _1, _2);
m_smt.profileGetNextValue = std::bind(&TestClient::profileGetNextValue, this, _1, _2, _3);

m_test_services = m_smt.getServiceMethodTable();

ASSERT_SUCCESS(sai_api_initialize(0, &m_test_services));

sai_switch_api_t* switch_api;

ASSERT_SUCCESS(sai_api_query(SAI_API_SWITCH, (void**)&switch_api));

sai_attribute_t attr;

// connect to existing switch
attr.id = SAI_SWITCH_ATTR_INIT_SWITCH;
attr.value.booldata = false;

sai_object_id_t switch_id = SAI_NULL_OBJECT_ID;

ASSERT_SUCCESS(switch_api->create_switch(&switch_id, 1, &attr));

ASSERT_TRUE(switch_id != SAI_NULL_OBJECT_ID);

SWSS_LOG_NOTICE("switchId: %s", sai_serialize_object_id(switch_id).c_str());

uint64_t counters[1];
sai_stat_id_t counter_ids[1] = { SAI_SWITCH_STAT_ECC_DROP };

SWSS_LOG_NOTICE(" * get_switch_stats");

ASSERT_SUCCESS(switch_api->get_switch_stats(switch_id, 1, counter_ids, counters));

SWSS_LOG_NOTICE(" * clear_switch_stats");

ASSERT_SUCCESS(switch_api->clear_switch_stats(switch_id, 1, counter_ids));

ASSERT_SUCCESS(sai_api_uninitialize());
}

int main()
{
swss::Logger::getInstance().setMinPrio(swss::Logger::SWSS_DEBUG);
Expand All @@ -475,5 +526,7 @@ int main()

tc.test_fdb_flush();

tc.test_stats();

return EXIT_SUCCESS;
}

0 comments on commit 1eacd05

Please sign in to comment.