Skip to content

Commit 7da0894

Browse files
authored
[sairedis] Client/Server support SAI query API (sonic-net#848)
1 parent 443ad36 commit 7da0894

File tree

4 files changed

+269
-11
lines changed

4 files changed

+269
-11
lines changed

lib/inc/ServerSai.h

+14-1
Original file line numberDiff line numberDiff line change
@@ -261,6 +261,8 @@ namespace sairedis
261261
sai_status_t processSingleEvent(
262262
_In_ const swss::KeyOpFieldsValuesTuple &kco);
263263

264+
// QUAD API
265+
264266
sai_status_t processQuadEvent(
265267
_In_ sai_common_api_t api,
266268
_In_ const swss::KeyOpFieldsValuesTuple &kco);
@@ -291,7 +293,7 @@ namespace sairedis
291293
_In_ uint32_t attr_count,
292294
_In_ sai_attribute_t *attr_list);
293295

294-
// BULK
296+
// BULK API
295297

296298
sai_status_t processBulkQuadEvent(
297299
_In_ sai_common_api_t api,
@@ -335,6 +337,17 @@ namespace sairedis
335337
_In_ const sai_object_id_t* object_ids,
336338
_In_ const sai_status_t* statuses);
337339

340+
// QUERY API
341+
342+
sai_status_t processAttrCapabilityQuery(
343+
_In_ const swss::KeyOpFieldsValuesTuple &kco);
344+
345+
sai_status_t processAttrEnumValuesCapabilityQuery(
346+
_In_ const swss::KeyOpFieldsValuesTuple &kco);
347+
348+
sai_status_t processObjectTypeGetAvailabilityQuery(
349+
_In_ const swss::KeyOpFieldsValuesTuple &kco);
350+
338351
private:
339352

340353
bool m_apiInitialized;

lib/src/Makefile.am

+2-2
Original file line numberDiff line numberDiff line change
@@ -92,9 +92,9 @@ libsairedis_la_SOURCES = \
9292
sai_redis_vlan.cpp \
9393
sai_redis_wred.cpp
9494

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

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

100100

lib/src/ServerSai.cpp

+176-8
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,9 @@
1313
#include "swss/select.h"
1414
#include "swss/tokenize.h"
1515

16+
#include <iterator>
17+
#include <algorithm>
18+
1619
using namespace sairedis;
1720
using namespace saimeta;
1821
using namespace std::placeholders;
@@ -698,14 +701,14 @@ sai_status_t ServerSai::processSingleEvent(
698701
// if (op == REDIS_ASIC_STATE_COMMAND_FLUSH)
699702
// return processFdbFlush(kco);
700703
//
701-
// if (op == REDIS_ASIC_STATE_COMMAND_ATTR_CAPABILITY_QUERY)
702-
// return processAttrCapabilityQuery(kco);
703-
//
704-
// if (op == REDIS_ASIC_STATE_COMMAND_ATTR_ENUM_VALUES_CAPABILITY_QUERY)
705-
// return processAttrEnumValuesCapabilityQuery(kco);
706-
//
707-
// if (op == REDIS_ASIC_STATE_COMMAND_OBJECT_TYPE_GET_AVAILABILITY_QUERY)
708-
// return processObjectTypeGetAvailabilityQuery(kco);
704+
if (op == REDIS_ASIC_STATE_COMMAND_ATTR_CAPABILITY_QUERY)
705+
return processAttrCapabilityQuery(kco);
706+
707+
if (op == REDIS_ASIC_STATE_COMMAND_ATTR_ENUM_VALUES_CAPABILITY_QUERY)
708+
return processAttrEnumValuesCapabilityQuery(kco);
709+
710+
if (op == REDIS_ASIC_STATE_COMMAND_OBJECT_TYPE_GET_AVAILABILITY_QUERY)
711+
return processObjectTypeGetAvailabilityQuery(kco);
709712

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

15401543
m_selectableChannel->set(strStatus, entry, REDIS_ASIC_STATE_COMMAND_GETRESPONSE);
15411544
}
1545+
1546+
sai_status_t ServerSai::processAttrCapabilityQuery(
1547+
_In_ const swss::KeyOpFieldsValuesTuple &kco)
1548+
{
1549+
SWSS_LOG_ENTER();
1550+
1551+
auto& strSwitchOid = kfvKey(kco);
1552+
1553+
sai_object_id_t switchOid;
1554+
sai_deserialize_object_id(strSwitchOid, switchOid);
1555+
1556+
auto& values = kfvFieldsValues(kco);
1557+
1558+
if (values.size() != 2)
1559+
{
1560+
SWSS_LOG_ERROR("Invalid input: expected 2 arguments, received %zu", values.size());
1561+
1562+
m_selectableChannel->set(sai_serialize_status(SAI_STATUS_INVALID_PARAMETER), {}, REDIS_ASIC_STATE_COMMAND_ATTR_CAPABILITY_RESPONSE);
1563+
1564+
return SAI_STATUS_INVALID_PARAMETER;
1565+
}
1566+
1567+
sai_object_type_t objectType;
1568+
sai_deserialize_object_type(fvValue(values[0]), objectType);
1569+
1570+
sai_attr_id_t attrId;
1571+
sai_deserialize_attr_id(fvValue(values[1]), attrId);
1572+
1573+
sai_attr_capability_t capability;
1574+
1575+
sai_status_t status = m_sai->queryAttributeCapability(switchOid, objectType, attrId, &capability);
1576+
1577+
std::vector<swss::FieldValueTuple> entry;
1578+
1579+
if (status == SAI_STATUS_SUCCESS)
1580+
{
1581+
entry =
1582+
{
1583+
swss::FieldValueTuple("CREATE_IMPLEMENTED", (capability.create_implemented ? "true" : "false")),
1584+
swss::FieldValueTuple("SET_IMPLEMENTED", (capability.set_implemented ? "true" : "false")),
1585+
swss::FieldValueTuple("GET_IMPLEMENTED", (capability.get_implemented ? "true" : "false"))
1586+
};
1587+
1588+
SWSS_LOG_INFO("Sending response: create_implemented:%d, set_implemented:%d, get_implemented:%d",
1589+
capability.create_implemented, capability.set_implemented, capability.get_implemented);
1590+
}
1591+
1592+
m_selectableChannel->set(sai_serialize_status(status), entry, REDIS_ASIC_STATE_COMMAND_ATTR_CAPABILITY_RESPONSE);
1593+
1594+
return status;
1595+
}
1596+
1597+
sai_status_t ServerSai::processAttrEnumValuesCapabilityQuery(
1598+
_In_ const swss::KeyOpFieldsValuesTuple &kco)
1599+
{
1600+
SWSS_LOG_ENTER();
1601+
1602+
auto& strSwitchOid = kfvKey(kco);
1603+
1604+
sai_object_id_t switchOid;
1605+
sai_deserialize_object_id(strSwitchOid, switchOid);
1606+
1607+
auto& values = kfvFieldsValues(kco);
1608+
1609+
if (values.size() != 3)
1610+
{
1611+
SWSS_LOG_ERROR("Invalid input: expected 3 arguments, received %zu", values.size());
1612+
1613+
m_selectableChannel->set(sai_serialize_status(SAI_STATUS_INVALID_PARAMETER), {}, REDIS_ASIC_STATE_COMMAND_ATTR_ENUM_VALUES_CAPABILITY_RESPONSE);
1614+
1615+
return SAI_STATUS_INVALID_PARAMETER;
1616+
}
1617+
1618+
sai_object_type_t objectType;
1619+
sai_deserialize_object_type(fvValue(values[0]), objectType);
1620+
1621+
sai_attr_id_t attrId;
1622+
sai_deserialize_attr_id(fvValue(values[1]), attrId);
1623+
1624+
uint32_t list_size = std::stoi(fvValue(values[2]));
1625+
1626+
std::vector<int32_t> enum_capabilities_list(list_size);
1627+
1628+
sai_s32_list_t enumCapList;
1629+
1630+
enumCapList.count = list_size;
1631+
enumCapList.list = enum_capabilities_list.data();
1632+
1633+
sai_status_t status = m_sai->queryAattributeEnumValuesCapability(switchOid, objectType, attrId, &enumCapList);
1634+
1635+
std::vector<swss::FieldValueTuple> entry;
1636+
1637+
if (status == SAI_STATUS_SUCCESS)
1638+
{
1639+
std::vector<std::string> vec;
1640+
std::transform(enumCapList.list, enumCapList.list + enumCapList.count,
1641+
std::back_inserter(vec), [](auto&e) { return std::to_string(e); });
1642+
1643+
std::ostringstream join;
1644+
std::copy(vec.begin(), vec.end(), std::ostream_iterator<std::string>(join, ","));
1645+
1646+
auto strCap = join.str();
1647+
1648+
entry =
1649+
{
1650+
swss::FieldValueTuple("ENUM_CAPABILITIES", strCap),
1651+
swss::FieldValueTuple("ENUM_COUNT", std::to_string(enumCapList.count))
1652+
};
1653+
1654+
SWSS_LOG_DEBUG("Sending response: capabilities = '%s', count = %d", strCap.c_str(), enumCapList.count);
1655+
}
1656+
1657+
m_selectableChannel->set(sai_serialize_status(status), entry, REDIS_ASIC_STATE_COMMAND_ATTR_ENUM_VALUES_CAPABILITY_RESPONSE);
1658+
1659+
return status;
1660+
}
1661+
1662+
sai_status_t ServerSai::processObjectTypeGetAvailabilityQuery(
1663+
_In_ const swss::KeyOpFieldsValuesTuple &kco)
1664+
{
1665+
SWSS_LOG_ENTER();
1666+
1667+
auto& strSwitchOid = kfvKey(kco);
1668+
1669+
sai_object_id_t switchOid;
1670+
sai_deserialize_object_id(strSwitchOid, switchOid);
1671+
1672+
std::vector<swss::FieldValueTuple> values = kfvFieldsValues(kco);
1673+
1674+
// needs to pop the object type off the end of the list in order to
1675+
// retrieve the attribute list
1676+
1677+
sai_object_type_t objectType;
1678+
sai_deserialize_object_type(fvValue(values.back()), objectType);
1679+
1680+
values.pop_back();
1681+
1682+
SaiAttributeList list(objectType, values, false);
1683+
1684+
sai_attribute_t *attr_list = list.get_attr_list();
1685+
1686+
uint32_t attr_count = list.get_attr_count();
1687+
1688+
uint64_t count;
1689+
1690+
sai_status_t status = m_sai->objectTypeGetAvailability(
1691+
switchOid,
1692+
objectType,
1693+
attr_count,
1694+
attr_list,
1695+
&count);
1696+
1697+
std::vector<swss::FieldValueTuple> entry;
1698+
1699+
if (status == SAI_STATUS_SUCCESS)
1700+
{
1701+
entry.push_back(swss::FieldValueTuple("OBJECT_COUNT", std::to_string(count)));
1702+
1703+
SWSS_LOG_DEBUG("Sending response: count = %lu", count);
1704+
}
1705+
1706+
m_selectableChannel->set(sai_serialize_status(status), entry, REDIS_ASIC_STATE_COMMAND_OBJECT_TYPE_GET_AVAILABILITY_RESPONSE);
1707+
1708+
return status;
1709+
}

tests/testclient.cpp

+77
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,8 @@ class TestClient
2323

2424
void test_bulk_create_vlan();
2525

26+
void test_query_api();
27+
2628
private:
2729

2830
int profileGetNextValue(
@@ -336,6 +338,79 @@ void TestClient::test_bulk_create_vlan()
336338
ASSERT_SUCCESS(sai_api_uninitialize());
337339
}
338340

341+
void TestClient::test_query_api()
342+
{
343+
SWSS_LOG_ENTER();
344+
345+
m_profileMap.clear();
346+
347+
m_profileMap[SAI_REDIS_KEY_ENABLE_CLIENT] = "true"; // act as a client
348+
349+
m_profileIter = m_profileMap.begin();
350+
351+
m_smt.profileGetValue = std::bind(&TestClient::profileGetValue, this, _1, _2);
352+
m_smt.profileGetNextValue = std::bind(&TestClient::profileGetNextValue, this, _1, _2, _3);
353+
354+
m_test_services = m_smt.getServiceMethodTable();
355+
356+
ASSERT_SUCCESS(sai_api_initialize(0, &m_test_services));
357+
358+
sai_switch_api_t* switch_api;
359+
360+
ASSERT_SUCCESS(sai_api_query(SAI_API_SWITCH, (void**)&switch_api));
361+
362+
sai_attribute_t attr;
363+
364+
// connect to existing switch
365+
attr.id = SAI_SWITCH_ATTR_INIT_SWITCH;
366+
attr.value.booldata = false;
367+
368+
sai_object_id_t switch_id = SAI_NULL_OBJECT_ID;
369+
370+
ASSERT_SUCCESS(switch_api->create_switch(&switch_id, 1, &attr));
371+
372+
ASSERT_TRUE(switch_id != SAI_NULL_OBJECT_ID);
373+
374+
SWSS_LOG_NOTICE("switchId: %s", sai_serialize_object_id(switch_id).c_str());
375+
376+
sai_attr_capability_t cap;
377+
378+
SWSS_LOG_NOTICE(" * sai_query_attribute_capability");
379+
380+
ASSERT_SUCCESS(sai_query_attribute_capability(
381+
switch_id,
382+
SAI_OBJECT_TYPE_SWITCH,
383+
SAI_SWITCH_ATTR_INIT_SWITCH,
384+
&cap));
385+
386+
int32_t vec[3];
387+
sai_s32_list_t list;
388+
389+
list.count = 3;
390+
list.list = vec;
391+
392+
SWSS_LOG_NOTICE(" * sai_query_attribute_enum_values_capability");
393+
394+
ASSERT_SUCCESS(sai_query_attribute_enum_values_capability(
395+
switch_id,
396+
SAI_OBJECT_TYPE_DEBUG_COUNTER,
397+
SAI_DEBUG_COUNTER_ATTR_IN_DROP_REASON_LIST,
398+
&list));
399+
400+
uint64_t count;
401+
402+
SWSS_LOG_NOTICE(" * sai_object_type_get_availability");
403+
404+
ASSERT_SUCCESS(sai_object_type_get_availability(
405+
switch_id,
406+
SAI_OBJECT_TYPE_DEBUG_COUNTER,
407+
0,
408+
NULL,
409+
&count));
410+
411+
ASSERT_SUCCESS(sai_api_uninitialize());
412+
}
413+
339414
int main()
340415
{
341416
swss::Logger::getInstance().setMinPrio(swss::Logger::SWSS_DEBUG);
@@ -350,5 +425,7 @@ int main()
350425

351426
tc.test_bulk_create_vlan();
352427

428+
tc.test_query_api();
429+
353430
return EXIT_SUCCESS;
354431
}

0 commit comments

Comments
 (0)