Skip to content

Commit

Permalink
[sairedis] Client/Server support SAI query API (#848)
Browse files Browse the repository at this point in the history
  • Loading branch information
kcudnik authored Jul 1, 2021
1 parent 443ad36 commit 7da0894
Show file tree
Hide file tree
Showing 4 changed files with 269 additions and 11 deletions.
15 changes: 14 additions & 1 deletion lib/inc/ServerSai.h
Original file line number Diff line number Diff line change
Expand Up @@ -261,6 +261,8 @@ namespace sairedis
sai_status_t processSingleEvent(
_In_ const swss::KeyOpFieldsValuesTuple &kco);

// QUAD API

sai_status_t processQuadEvent(
_In_ sai_common_api_t api,
_In_ const swss::KeyOpFieldsValuesTuple &kco);
Expand Down Expand Up @@ -291,7 +293,7 @@ namespace sairedis
_In_ uint32_t attr_count,
_In_ sai_attribute_t *attr_list);

// BULK
// BULK API

sai_status_t processBulkQuadEvent(
_In_ sai_common_api_t api,
Expand Down Expand Up @@ -335,6 +337,17 @@ namespace sairedis
_In_ const sai_object_id_t* object_ids,
_In_ const sai_status_t* statuses);

// QUERY API

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

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

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

private:

bool m_apiInitialized;
Expand Down
4 changes: 2 additions & 2 deletions lib/src/Makefile.am
Original file line number Diff line number Diff line change
Expand Up @@ -92,9 +92,9 @@ libsairedis_la_SOURCES = \
sai_redis_vlan.cpp \
sai_redis_wred.cpp

libSaiRedis_a_CPPFLAGS = $(DBGFLAGS) $(AM_CPPFLAGS) $(CFLAGS_COMMON)
libSaiRedis_a_CPPFLAGS = $(DBGFLAGS) $(AM_CPPFLAGS) $(CFLAGS_COMMON) -std=c++14

libsairedis_la_CPPFLAGS = $(DBGFLAGS) $(AM_CPPFLAGS) $(CFLAGS_COMMON)
libsairedis_la_CPPFLAGS = $(DBGFLAGS) $(AM_CPPFLAGS) $(CFLAGS_COMMON) -std=c++14
libsairedis_la_LIBADD = -lhiredis -lswsscommon libSaiRedis.a


Expand Down
184 changes: 176 additions & 8 deletions lib/src/ServerSai.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,9 @@
#include "swss/select.h"
#include "swss/tokenize.h"

#include <iterator>
#include <algorithm>

using namespace sairedis;
using namespace saimeta;
using namespace std::placeholders;
Expand Down Expand Up @@ -698,14 +701,14 @@ sai_status_t ServerSai::processSingleEvent(
// if (op == REDIS_ASIC_STATE_COMMAND_FLUSH)
// return processFdbFlush(kco);
//
// if (op == REDIS_ASIC_STATE_COMMAND_ATTR_CAPABILITY_QUERY)
// return processAttrCapabilityQuery(kco);
//
// if (op == REDIS_ASIC_STATE_COMMAND_ATTR_ENUM_VALUES_CAPABILITY_QUERY)
// return processAttrEnumValuesCapabilityQuery(kco);
//
// if (op == REDIS_ASIC_STATE_COMMAND_OBJECT_TYPE_GET_AVAILABILITY_QUERY)
// return processObjectTypeGetAvailabilityQuery(kco);
if (op == REDIS_ASIC_STATE_COMMAND_ATTR_CAPABILITY_QUERY)
return processAttrCapabilityQuery(kco);

if (op == REDIS_ASIC_STATE_COMMAND_ATTR_ENUM_VALUES_CAPABILITY_QUERY)
return processAttrEnumValuesCapabilityQuery(kco);

if (op == REDIS_ASIC_STATE_COMMAND_OBJECT_TYPE_GET_AVAILABILITY_QUERY)
return processObjectTypeGetAvailabilityQuery(kco);

SWSS_LOG_THROW("event op '%s' is not implemented, FIXME", op.c_str());
}
Expand Down Expand Up @@ -1539,3 +1542,168 @@ void ServerSai::sendBulkApiResponse(

m_selectableChannel->set(strStatus, entry, REDIS_ASIC_STATE_COMMAND_GETRESPONSE);
}

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

auto& strSwitchOid = kfvKey(kco);

sai_object_id_t switchOid;
sai_deserialize_object_id(strSwitchOid, switchOid);

auto& values = kfvFieldsValues(kco);

if (values.size() != 2)
{
SWSS_LOG_ERROR("Invalid input: expected 2 arguments, received %zu", values.size());

m_selectableChannel->set(sai_serialize_status(SAI_STATUS_INVALID_PARAMETER), {}, REDIS_ASIC_STATE_COMMAND_ATTR_CAPABILITY_RESPONSE);

return SAI_STATUS_INVALID_PARAMETER;
}

sai_object_type_t objectType;
sai_deserialize_object_type(fvValue(values[0]), objectType);

sai_attr_id_t attrId;
sai_deserialize_attr_id(fvValue(values[1]), attrId);

sai_attr_capability_t capability;

sai_status_t status = m_sai->queryAttributeCapability(switchOid, objectType, attrId, &capability);

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

if (status == SAI_STATUS_SUCCESS)
{
entry =
{
swss::FieldValueTuple("CREATE_IMPLEMENTED", (capability.create_implemented ? "true" : "false")),
swss::FieldValueTuple("SET_IMPLEMENTED", (capability.set_implemented ? "true" : "false")),
swss::FieldValueTuple("GET_IMPLEMENTED", (capability.get_implemented ? "true" : "false"))
};

SWSS_LOG_INFO("Sending response: create_implemented:%d, set_implemented:%d, get_implemented:%d",
capability.create_implemented, capability.set_implemented, capability.get_implemented);
}

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

return status;
}

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

auto& strSwitchOid = kfvKey(kco);

sai_object_id_t switchOid;
sai_deserialize_object_id(strSwitchOid, switchOid);

auto& values = kfvFieldsValues(kco);

if (values.size() != 3)
{
SWSS_LOG_ERROR("Invalid input: expected 3 arguments, received %zu", values.size());

m_selectableChannel->set(sai_serialize_status(SAI_STATUS_INVALID_PARAMETER), {}, REDIS_ASIC_STATE_COMMAND_ATTR_ENUM_VALUES_CAPABILITY_RESPONSE);

return SAI_STATUS_INVALID_PARAMETER;
}

sai_object_type_t objectType;
sai_deserialize_object_type(fvValue(values[0]), objectType);

sai_attr_id_t attrId;
sai_deserialize_attr_id(fvValue(values[1]), attrId);

uint32_t list_size = std::stoi(fvValue(values[2]));

std::vector<int32_t> enum_capabilities_list(list_size);

sai_s32_list_t enumCapList;

enumCapList.count = list_size;
enumCapList.list = enum_capabilities_list.data();

sai_status_t status = m_sai->queryAattributeEnumValuesCapability(switchOid, objectType, attrId, &enumCapList);

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

if (status == SAI_STATUS_SUCCESS)
{
std::vector<std::string> vec;
std::transform(enumCapList.list, enumCapList.list + enumCapList.count,
std::back_inserter(vec), [](auto&e) { return std::to_string(e); });

std::ostringstream join;
std::copy(vec.begin(), vec.end(), std::ostream_iterator<std::string>(join, ","));

auto strCap = join.str();

entry =
{
swss::FieldValueTuple("ENUM_CAPABILITIES", strCap),
swss::FieldValueTuple("ENUM_COUNT", std::to_string(enumCapList.count))
};

SWSS_LOG_DEBUG("Sending response: capabilities = '%s', count = %d", strCap.c_str(), enumCapList.count);
}

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

return status;
}

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

auto& strSwitchOid = kfvKey(kco);

sai_object_id_t switchOid;
sai_deserialize_object_id(strSwitchOid, switchOid);

std::vector<swss::FieldValueTuple> values = kfvFieldsValues(kco);

// needs to pop the object type off the end of the list in order to
// retrieve the attribute list

sai_object_type_t objectType;
sai_deserialize_object_type(fvValue(values.back()), objectType);

values.pop_back();

SaiAttributeList list(objectType, values, false);

sai_attribute_t *attr_list = list.get_attr_list();

uint32_t attr_count = list.get_attr_count();

uint64_t count;

sai_status_t status = m_sai->objectTypeGetAvailability(
switchOid,
objectType,
attr_count,
attr_list,
&count);

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

if (status == SAI_STATUS_SUCCESS)
{
entry.push_back(swss::FieldValueTuple("OBJECT_COUNT", std::to_string(count)));

SWSS_LOG_DEBUG("Sending response: count = %lu", count);
}

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

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

void test_bulk_create_vlan();

void test_query_api();

private:

int profileGetNextValue(
Expand Down Expand Up @@ -336,6 +338,79 @@ void TestClient::test_bulk_create_vlan()
ASSERT_SUCCESS(sai_api_uninitialize());
}

void TestClient::test_query_api()
{
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());

sai_attr_capability_t cap;

SWSS_LOG_NOTICE(" * sai_query_attribute_capability");

ASSERT_SUCCESS(sai_query_attribute_capability(
switch_id,
SAI_OBJECT_TYPE_SWITCH,
SAI_SWITCH_ATTR_INIT_SWITCH,
&cap));

int32_t vec[3];
sai_s32_list_t list;

list.count = 3;
list.list = vec;

SWSS_LOG_NOTICE(" * sai_query_attribute_enum_values_capability");

ASSERT_SUCCESS(sai_query_attribute_enum_values_capability(
switch_id,
SAI_OBJECT_TYPE_DEBUG_COUNTER,
SAI_DEBUG_COUNTER_ATTR_IN_DROP_REASON_LIST,
&list));

uint64_t count;

SWSS_LOG_NOTICE(" * sai_object_type_get_availability");

ASSERT_SUCCESS(sai_object_type_get_availability(
switch_id,
SAI_OBJECT_TYPE_DEBUG_COUNTER,
0,
NULL,
&count));

ASSERT_SUCCESS(sai_api_uninitialize());
}

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

tc.test_bulk_create_vlan();

tc.test_query_api();

return EXIT_SUCCESS;
}

0 comments on commit 7da0894

Please sign in to comment.