From 0e542d6f8a94025d567bb8f13a19f1f4eb27dda3 Mon Sep 17 00:00:00 2001 From: Ze Gan Date: Mon, 14 Apr 2025 18:57:30 +1000 Subject: [PATCH 1/2] [SAI]: Update SAI to support QUERY_STATS_ST_CAPABILITY and TAM (#1573) [SAI]: Update SAI to support QUERY_STATS_ST_CAPABILITY and TAM --------- Signed-off-by: Ze Gan --- lib/ClientSai.cpp | 103 ++++++++++++++ lib/ClientSai.h | 5 +- lib/Recorder.cpp | 78 ++++++++++ lib/Recorder.h | 20 ++- lib/RedisRemoteSaiInterface.cpp | 107 ++++++++++++++ lib/RedisRemoteSaiInterface.h | 5 +- lib/ServerSai.cpp | 87 ++++++++++++ lib/ServerSai.h | 3 + lib/sairediscommon.h | 3 + meta/DummySaiInterface.cpp | 16 +++ meta/Makefile.am | 1 + meta/Meta.cpp | 36 +++++ meta/Meta.h | 6 +- meta/NotificationFactory.cpp | 4 + meta/NotificationTamTelTypeConfigChange.cpp | 49 +++++++ meta/NotificationTamTelTypeConfigChange.h | 31 ++++ meta/SaiSerialize.cpp | 133 ++++++++++++++++++ meta/sai_serialize.h | 11 ++ proxylib/Proxy.cpp | 11 ++ proxylib/Proxy.h | 3 + proxylib/Sai.cpp | 2 - pyext/pysairedis.cpp | 16 +++ syncd/NotificationHandler.cpp | 10 ++ syncd/NotificationHandler.h | 3 + syncd/NotificationProcessor.cpp | 14 ++ syncd/NotificationProcessor.h | 3 + syncd/SwitchNotifications.cpp | 9 ++ syncd/SwitchNotifications.h | 19 ++- syncd/Syncd.cpp | 90 ++++++++++++ syncd/Syncd.h | 3 + syncd/VendorSai.cpp | 4 +- tests/TestClient.cpp | 27 ++++ unittest/lib/Makefile.am | 2 +- unittest/lib/TestClientServerSai.cpp | 22 +++ unittest/lib/TestRedisRemoteSaiInterface.cpp | 71 ++++++++++ unittest/lib/TestServerSai.cpp | 35 +++++ unittest/lib/TestSwitch.cpp | 7 +- unittest/meta/Makefile.am | 1 + unittest/meta/TestDummySaiInterface.cpp | 18 ++- unittest/meta/TestMeta.cpp | 29 ++++ unittest/meta/TestNotificationTam.cpp | 33 +++++ unittest/meta/TestSaiSerialize.cpp | 83 +++++++++++ unittest/proxylib/TestProxy.cpp | 17 ++- unittest/proxylib/TestSai.cpp | 19 ++- unittest/syncd/TestSyncd.cpp | 37 +++++ unittest/vslib/Makefile.am | 3 +- unittest/vslib/TestSwitchStateBase.cpp | 27 ++++ unittest/vslib/TestTAM.cpp | 68 +++++++++ .../vslib/TestVirtualSwitchSaiInterface.cpp | 38 +++++ vslib/SwitchState.cpp | 30 ++++ vslib/SwitchStateBase.cpp | 101 ++++++++++++- vslib/SwitchStateBase.h | 17 ++- vslib/VirtualSwitchSaiInterface.cpp | 38 ++++- 53 files changed, 1578 insertions(+), 30 deletions(-) create mode 100644 meta/NotificationTamTelTypeConfigChange.cpp create mode 100644 meta/NotificationTamTelTypeConfigChange.h create mode 100644 unittest/meta/TestNotificationTam.cpp create mode 100644 unittest/vslib/TestTAM.cpp diff --git a/lib/ClientSai.cpp b/lib/ClientSai.cpp index 39da35e3..be0e13af 100644 --- a/lib/ClientSai.cpp +++ b/lib/ClientSai.cpp @@ -1135,6 +1135,109 @@ sai_status_t ClientSai::waitForQueryStatsCapabilityResponse( return status; } +sai_status_t ClientSai::queryStatsStCapability( + _In_ sai_object_id_t switchId, + _In_ sai_object_type_t objectType, + _Inout_ sai_stat_st_capability_list_t *stats_capability) +{ + MUTEX(); + SWSS_LOG_ENTER(); + REDIS_CHECK_API_INITIALIZED(); + + auto switchIdStr = sai_serialize_object_id(switchId); + auto objectTypeStr = sai_serialize_object_type(objectType); + + if (stats_capability == NULL) + { + SWSS_LOG_ERROR("Failed to find stats-capability: switch %s object type %s", switchIdStr.c_str(), objectTypeStr.c_str()); + return SAI_STATUS_INVALID_PARAMETER; + } + + if (stats_capability && stats_capability->list && (stats_capability->count)) + { + // clear input list, since we use serialize to transfer values + for (uint32_t idx = 0; idx < stats_capability->count; idx++) + { + stats_capability->list[idx].capability.stat_enum = 0; + stats_capability->list[idx].capability.stat_modes = 0; + stats_capability->list[idx].minimal_polling_interval = 0; + } + } + + const std::string listSize = std::to_string(stats_capability->count); + + const std::vector entry = + { + swss::FieldValueTuple("OBJECT_TYPE", objectTypeStr), + swss::FieldValueTuple("LIST_SIZE", listSize)}; + + SWSS_LOG_DEBUG( + "Query arguments: switch %s, object type: %s, count: %s", + switchIdStr.c_str(), + objectTypeStr.c_str(), + listSize.c_str()); + + // This query will not put any data into the ASIC view, just into the + // message queue + + m_communicationChannel->set(switchIdStr, entry, REDIS_ASIC_STATE_COMMAND_STATS_ST_CAPABILITY_QUERY); + + return waitForQueryStatsStCapabilityResponse(stats_capability); +} + +sai_status_t ClientSai::waitForQueryStatsStCapabilityResponse( + _Inout_ sai_stat_st_capability_list_t *stats_capability) +{ + SWSS_LOG_ENTER(); + + swss::KeyOpFieldsValuesTuple kco; + + auto status = m_communicationChannel->wait(REDIS_ASIC_STATE_COMMAND_STATS_ST_CAPABILITY_RESPONSE, kco); + + if (status == SAI_STATUS_SUCCESS) + { + const std::vector &values = kfvFieldsValues(kco); + + if (values.size() != 4) + { + SWSS_LOG_ERROR("Invalid response from syncd: expected 4 value, received %zu", values.size()); + + return SAI_STATUS_FAILURE; + } + + const std::string &stat_enum_str = fvValue(values[0]); + const std::string &stat_modes_str = fvValue(values[1]); + const std::string &polling_interval_str = fvValue(values[2]); + const uint32_t num_capabilities = std::stoi(fvValue(values[3])); + + SWSS_LOG_DEBUG("Received payload: stat_enums = '%s', stat_modes = '%s', minimal_polling_intervals = '%s' count = %d", + stat_enum_str.c_str(), stat_modes_str.c_str(), polling_interval_str.c_str(), num_capabilities); + + stats_capability->count = num_capabilities; + + sai_deserialize_stats_st_capability_list(stats_capability, stat_enum_str, stat_modes_str, polling_interval_str); + } + else if (status == SAI_STATUS_BUFFER_OVERFLOW) + { + const std::vector &values = kfvFieldsValues(kco); + + if (values.size() != 1) + { + SWSS_LOG_ERROR("Invalid response from syncd: expected 1 value, received %zu", values.size()); + + return SAI_STATUS_FAILURE; + } + + const uint32_t num_capabilities = std::stoi(fvValue(values[0])); + + SWSS_LOG_DEBUG("Received payload: count = %u", num_capabilities); + + stats_capability->count = num_capabilities; + } + + return status; +} + sai_status_t ClientSai::getStatsExt( _In_ sai_object_type_t object_type, _In_ sai_object_id_t object_id, diff --git a/lib/ClientSai.h b/lib/ClientSai.h index 0033cc54..864334ef 100644 --- a/lib/ClientSai.h +++ b/lib/ClientSai.h @@ -305,7 +305,10 @@ namespace sairedis sai_status_t waitForQueryStatsCapabilityResponse( _Inout_ sai_stat_capability_list_t* stats_capability); - private: + sai_status_t waitForQueryStatsStCapabilityResponse( + _Inout_ sai_stat_st_capability_list_t *stats_capability); + + private: void handleNotification( _In_ const std::string &name, diff --git a/lib/Recorder.cpp b/lib/Recorder.cpp index b4e1e016..d1646674 100644 --- a/lib/Recorder.cpp +++ b/lib/Recorder.cpp @@ -388,6 +388,24 @@ void Recorder::recordQueryStatsCapabilityResponse( recordLine("Q|stats_capability|" + sai_serialize_status(status) + "|" + arguments); } +void Recorder::recordQueryStatsStCapability( + _In_ const std::string &key, + _In_ const std::vector &arguments) +{ + SWSS_LOG_ENTER(); + + recordLine("q|stats_st_capability|" + key + "|" + Globals::joinFieldValues(arguments)); +} + +void Recorder::recordQueryStatsStCapabilityResponse( + _In_ sai_status_t status, + _In_ const std::string &arguments) +{ + SWSS_LOG_ENTER(); + + recordLine("Q|stats_st_capability|" + sai_serialize_status(status) + "|" + arguments); +} + void Recorder::recordNotifySyncd( _In_ const std::string& key) { @@ -1217,6 +1235,66 @@ void Recorder::recordQueryStatsCapabilityResponse( recordQueryStatsCapabilityResponse(status, str_stats_list); } +void Recorder::recordQueryStatsStCapability( + _In_ sai_object_id_t switch_id, + _In_ sai_object_type_t object_type, + _Inout_ sai_stat_st_capability_list_t *stats_capability) +{ + SWSS_LOG_ENTER(); + + auto key = sai_serialize_object_type(SAI_OBJECT_TYPE_SWITCH) + ":" + sai_serialize_object_id(switch_id); + + auto object_type_str = sai_serialize_object_type(object_type); + const std::string list_size = std::to_string(stats_capability->count); + const std::vector values = + { + swss::FieldValueTuple("OBJECT_TYPE", object_type_str), + swss::FieldValueTuple("LIST_SIZE", list_size)}; + + SWSS_LOG_DEBUG("Query arguments: switch %s, object_type: %s, count: %s", + key.c_str(), + object_type_str.c_str(), + list_size.c_str()); + + recordQueryStatsStCapability(key, values); +} + +void Recorder::recordQueryStatsStCapabilityResponse( + _In_ sai_status_t status, + _In_ sai_object_type_t objectType, + _In_ const sai_stat_st_capability_list_t *stats_capability) +{ + SWSS_LOG_ENTER(); + + std::string str_stats_list; + + auto meta = sai_metadata_get_object_type_info(objectType); + + if (meta == NULL) + { + SWSS_LOG_ERROR("Failed to find object metadata: object type %s", + sai_serialize_object_type(objectType).c_str()); + + return; + } + + if (meta->statenum == NULL) + { + SWSS_LOG_ERROR("%s does not support stats", meta->objecttypename); + + return; + } + + bool countOnly = (status == SAI_STATUS_BUFFER_OVERFLOW); + + if (status == SAI_STATUS_SUCCESS || status == SAI_STATUS_BUFFER_OVERFLOW) + { + str_stats_list = sai_serialize_stats_st_capability_list(*stats_capability, meta->statenum, countOnly); + } + + recordQueryStatsStCapabilityResponse(status, str_stats_list); +} + void Recorder::recordNotifySyncd( _In_ sai_object_id_t switchId, _In_ sai_redis_notify_syncd_t redisNotifySyncd) diff --git a/lib/Recorder.h b/lib/Recorder.h index 5b6ef18d..8f41cd87 100644 --- a/lib/Recorder.h +++ b/lib/Recorder.h @@ -316,6 +316,16 @@ namespace sairedis _In_ sai_object_type_t objectType, _In_ const sai_stat_capability_list_t *stats_capability); + void recordQueryStatsStCapability( + _In_ sai_object_id_t switch_id, + _In_ sai_object_type_t object_type, + _Inout_ sai_stat_st_capability_list_t *stats_capability); + + void recordQueryStatsStCapabilityResponse( + _In_ sai_status_t status, + _In_ sai_object_type_t objectType, + _In_ const sai_stat_st_capability_list_t *stats_capability); + // TODO move to private void recordQueryAttributeCapability( _In_ const std::string& key, @@ -349,7 +359,15 @@ namespace sairedis _In_ sai_status_t status, _In_ const std::string& arguments); - public: // SAI notifications + void recordQueryStatsStCapability( + _In_ const std::string &key, + _In_ const std::vector &arguments); + + void recordQueryStatsStCapabilityResponse( + _In_ sai_status_t status, + _In_ const std::string &arguments); + + public: // SAI notifications void recordNotification( _In_ const std::string &name, diff --git a/lib/RedisRemoteSaiInterface.cpp b/lib/RedisRemoteSaiInterface.cpp index f2942ecd..e20a3bf1 100644 --- a/lib/RedisRemoteSaiInterface.cpp +++ b/lib/RedisRemoteSaiInterface.cpp @@ -1507,6 +1507,113 @@ sai_status_t RedisRemoteSaiInterface::waitForQueryStatsCapabilityResponse( return status; } +sai_status_t RedisRemoteSaiInterface::queryStatsStCapability( + _In_ sai_object_id_t switchId, + _In_ sai_object_type_t objectType, + _Inout_ sai_stat_st_capability_list_t *stats_capability) +{ + SWSS_LOG_ENTER(); + + auto switchIdStr = sai_serialize_object_id(switchId); + auto objectTypeStr = sai_serialize_object_type(objectType); + + if (stats_capability == NULL) + { + SWSS_LOG_ERROR("Failed to find stats-capability: switch %s, object type %s", switchIdStr.c_str(), objectTypeStr.c_str()); + return SAI_STATUS_INVALID_PARAMETER; + } + + if (stats_capability && stats_capability->list && (stats_capability->count)) + { + // clear input list, since we use serialize to transfer the values + for (uint32_t idx = 0; idx < stats_capability->count; idx++) + { + stats_capability->list[idx].capability.stat_enum = 0; + stats_capability->list[idx].capability.stat_modes = 0; + stats_capability->list[idx].minimal_polling_interval = 0; + } + } + + const std::string listSize = std::to_string(stats_capability->count); + + const std::vector entry = + { + swss::FieldValueTuple("OBJECT_TYPE", objectTypeStr), + swss::FieldValueTuple("LIST_SIZE", listSize)}; + + SWSS_LOG_DEBUG( + "Query arguments: switch %s, object type: %s, count: %s", + switchIdStr.c_str(), + objectTypeStr.c_str(), + listSize.c_str()); + + // This query will not put any data into the ASIC view, just into the + // message queue + + m_recorder->recordQueryStatsStCapability(switchId, objectType, stats_capability); + + m_communicationChannel->set(switchIdStr, entry, REDIS_ASIC_STATE_COMMAND_STATS_ST_CAPABILITY_QUERY); + + auto status = waitForQueryStatsStCapabilityResponse(stats_capability); + + m_recorder->recordQueryStatsStCapabilityResponse(status, objectType, stats_capability); + + return status; +} + +sai_status_t RedisRemoteSaiInterface::waitForQueryStatsStCapabilityResponse( + _Inout_ sai_stat_st_capability_list_t *stats_capability) +{ + SWSS_LOG_ENTER(); + + swss::KeyOpFieldsValuesTuple kco; + + auto status = m_communicationChannel->wait(REDIS_ASIC_STATE_COMMAND_STATS_ST_CAPABILITY_RESPONSE, kco); + + if (status == SAI_STATUS_SUCCESS) + { + const std::vector &values = kfvFieldsValues(kco); + + if (values.size() != 4) + { + SWSS_LOG_ERROR("Invalid response from syncd: expected 4 value, received %zu", values.size()); + + return SAI_STATUS_FAILURE; + } + + const std::string &stat_enum_str = fvValue(values[0]); + const std::string &stat_modes_str = fvValue(values[1]); + const std::string &polling_interval_str = fvValue(values[2]); + const uint32_t num_capabilities = std::stoi(fvValue(values[3])); + + SWSS_LOG_DEBUG("Received payload: stat_enums = '%s', stat_modes = '%s', minimal_polling_intervals = '%s' count = %d", + stat_enum_str.c_str(), stat_modes_str.c_str(), polling_interval_str.c_str(), num_capabilities); + + stats_capability->count = num_capabilities; + + sai_deserialize_stats_st_capability_list(stats_capability, stat_enum_str, stat_modes_str, polling_interval_str); + } + else if (status == SAI_STATUS_BUFFER_OVERFLOW) + { + const std::vector &values = kfvFieldsValues(kco); + + if (values.size() != 1) + { + SWSS_LOG_ERROR("Invalid response from syncd: expected 1 value, received %zu", values.size()); + + return SAI_STATUS_FAILURE; + } + + const uint32_t num_capabilities = std::stoi(fvValue(values[0])); + + SWSS_LOG_DEBUG("Received payload: count = %u", num_capabilities); + + stats_capability->count = num_capabilities; + } + + return status; +} + sai_status_t RedisRemoteSaiInterface::getStatsExt( _In_ sai_object_type_t object_type, _In_ sai_object_id_t object_id, diff --git a/lib/RedisRemoteSaiInterface.h b/lib/RedisRemoteSaiInterface.h index 1f55ca6a..b800eaf7 100644 --- a/lib/RedisRemoteSaiInterface.h +++ b/lib/RedisRemoteSaiInterface.h @@ -373,7 +373,10 @@ namespace sairedis sai_status_t waitForQueryStatsCapabilityResponse( _Inout_ sai_stat_capability_list_t* stats_capability); - private: // notify syncd response + sai_status_t waitForQueryStatsStCapabilityResponse( + _Inout_ sai_stat_st_capability_list_t *stats_capability); + + private: // notify syncd response sai_status_t waitForNotifySyncdResponse(); diff --git a/lib/ServerSai.cpp b/lib/ServerSai.cpp index a1920510..06294e38 100644 --- a/lib/ServerSai.cpp +++ b/lib/ServerSai.cpp @@ -805,6 +805,9 @@ sai_status_t ServerSai::processSingleEvent( if (op == REDIS_ASIC_STATE_COMMAND_STATS_CAPABILITY_QUERY) return processStatsCapabilityQuery(kco); + if (op == REDIS_ASIC_STATE_COMMAND_STATS_ST_CAPABILITY_QUERY) + return processStatsStCapabilityQuery(kco); + SWSS_LOG_THROW("event op '%s' is not implemented, FIXME", op.c_str()); } @@ -2184,6 +2187,90 @@ sai_status_t ServerSai::processStatsCapabilityQuery( return status; } +sai_status_t ServerSai::processStatsStCapabilityQuery( + _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_STATS_ST_CAPABILITY_RESPONSE); + + return SAI_STATUS_INVALID_PARAMETER; + } + + sai_object_type_t objectType; + sai_deserialize_object_type(fvValue(values[0]), objectType); + + uint32_t list_size = std::stoi(fvValue(values[1])); + + std::vector stat_capability_list(list_size); + + sai_stat_st_capability_list_t statCapList; + + statCapList.count = list_size; + statCapList.list = stat_capability_list.data(); + + sai_status_t status = m_sai->queryStatsStCapability(switchOid, objectType, &statCapList); + + std::vector entry; + + if (status == SAI_STATUS_SUCCESS) + { + std::vector vec_stat_enum; + std::vector vec_stat_modes; + std::vector vec_minimal_polling_intervals; + + for (uint32_t it = 0; it < statCapList.count; it++) + { + vec_stat_enum.push_back(std::to_string(statCapList.list[it].capability.stat_enum)); + vec_stat_modes.push_back(std::to_string(statCapList.list[it].capability.stat_modes)); + vec_minimal_polling_intervals.push_back(std::to_string(statCapList.list[it].minimal_polling_interval)); + } + + std::ostringstream join_stat_enum; + std::copy(vec_stat_enum.begin(), vec_stat_enum.end(), std::ostream_iterator(join_stat_enum, ",")); + auto strCapEnum = join_stat_enum.str(); + + std::ostringstream join_stat_modes; + std::copy(vec_stat_modes.begin(), vec_stat_modes.end(), std::ostream_iterator(join_stat_modes, ",")); + auto strCapModes = join_stat_modes.str(); + + std::ostringstream join_minimal_polling_intervals; + std::copy(vec_minimal_polling_intervals.begin(), vec_minimal_polling_intervals.end(), std::ostream_iterator(join_minimal_polling_intervals, ",")); + auto strCapMinPollInt = join_minimal_polling_intervals.str(); + + entry = + { + swss::FieldValueTuple("STAT_ENUM", strCapEnum), + swss::FieldValueTuple("STAT_MODES", strCapModes), + swss::FieldValueTuple("MINIMAL_POLLING_INTERVALS", strCapMinPollInt), + swss::FieldValueTuple("STAT_COUNT", std::to_string(statCapList.count))}; + + SWSS_LOG_DEBUG("Sending response: stat_enums = '%s', stat_modes = '%s', minimal_polling_intervals = '%s' count = %d", + strCapEnum.c_str(), strCapModes.c_str(), strCapMinPollInt.c_str(), statCapList.count); + } + else if (status == SAI_STATUS_BUFFER_OVERFLOW) + { + entry = {swss::FieldValueTuple("STAT_COUNT", std::to_string(statCapList.count))}; + + SWSS_LOG_DEBUG("Sending response: count = %u", statCapList.count); + } + + m_selectableChannel->set(sai_serialize_status(status), entry, REDIS_ASIC_STATE_COMMAND_STATS_ST_CAPABILITY_RESPONSE); + + return status; +} + sai_status_t ServerSai::processFdbFlush( _In_ const swss::KeyOpFieldsValuesTuple &kco) { diff --git a/lib/ServerSai.h b/lib/ServerSai.h index cf4c1601..53ce32a6 100644 --- a/lib/ServerSai.h +++ b/lib/ServerSai.h @@ -320,6 +320,9 @@ namespace sairedis sai_status_t processStatsCapabilityQuery( _In_ const swss::KeyOpFieldsValuesTuple &kco); + sai_status_t processStatsStCapabilityQuery( + _In_ const swss::KeyOpFieldsValuesTuple &kco); + std::shared_ptr m_selectableChannel; std::shared_ptr m_sai; diff --git a/lib/sairediscommon.h b/lib/sairediscommon.h index f9bc6cde..4594cab5 100644 --- a/lib/sairediscommon.h +++ b/lib/sairediscommon.h @@ -61,6 +61,9 @@ #define REDIS_ASIC_STATE_COMMAND_STATS_CAPABILITY_QUERY "stats_capability_query" #define REDIS_ASIC_STATE_COMMAND_STATS_CAPABILITY_RESPONSE "stats_capability_response" +#define REDIS_ASIC_STATE_COMMAND_STATS_ST_CAPABILITY_QUERY "stats_st_capability_query" +#define REDIS_ASIC_STATE_COMMAND_STATS_ST_CAPABILITY_RESPONSE "stats_st_capability_response" + /** * @brief Redis virtual object id counter key name. * diff --git a/meta/DummySaiInterface.cpp b/meta/DummySaiInterface.cpp index 3395e912..59f87e8d 100644 --- a/meta/DummySaiInterface.cpp +++ b/meta/DummySaiInterface.cpp @@ -878,6 +878,22 @@ void DummySaiInterface::sendNotification( } break; + case SAI_SWITCH_ATTR_TAM_TEL_TYPE_CONFIG_CHANGE_NOTIFY: + + if (sn.on_tam_tel_type_config_change) + { + SWSS_LOG_NOTICE("sending sn.on_tam_tel_type_config_change"); + + sai_object_id_t oid = 0x1; + + sn.on_tam_tel_type_config_change(oid); + } + else + { + SWSS_LOG_WARN("pointer sn.on_tam_tel_type_config_change"); + } + break; + default: SWSS_LOG_WARN("notification for SWITCH attr id: %d (%s) is not supported, FIXME", id, (m ? m->attridname : "UNKNOWN")); diff --git a/meta/Makefile.am b/meta/Makefile.am index f62d0cbd..f44c40b0 100644 --- a/meta/Makefile.am +++ b/meta/Makefile.am @@ -38,6 +38,7 @@ libsaimeta_la_SOURCES = \ NotificationBfdSessionStateChange.cpp \ NotificationTwampSessionEvent.cpp \ NotificationPortHostTxReadyEvent.cpp \ + NotificationTamTelTypeConfigChange.cpp \ NumberOidIndexGenerator.cpp \ OidRefCounter.cpp \ PerformanceIntervalTimer.cpp \ diff --git a/meta/Meta.cpp b/meta/Meta.cpp index c8044e9d..724ebe7d 100644 --- a/meta/Meta.cpp +++ b/meta/Meta.cpp @@ -7072,6 +7072,42 @@ void Meta::meta_sai_on_twamp_session_event( } } +void Meta::meta_sai_on_tam_tel_type_config_change(_In_ sai_object_id_t m_tam_id) +{ + SWSS_LOG_ENTER(); + + if (m_tam_id == SAI_NULL_OBJECT_ID) + { + SWSS_LOG_ERROR("m_tam_id is NULL"); + return; + } + + auto ot = objectTypeQuery(m_tam_id); + + if (ot != SAI_OBJECT_TYPE_NULL) + { + SWSS_LOG_ERROR("m_tam_id %s has unexpected type: %s, expected TAM_TEL_TYPE", + sai_serialize_object_id(m_tam_id).c_str(), + sai_serialize_object_type(ot).c_str()); + return; + } + + if (!m_oids.objectReferenceExists(m_tam_id)) + { + SWSS_LOG_NOTICE("m_tam_id %s is not present in local DB (snoop!)", + sai_serialize_object_id(m_tam_id).c_str()); + + sai_object_meta_key_t key = {.objecttype = (sai_object_type_t)ot, .objectkey = {.key = {.object_id = m_tam_id}}}; + + m_oids.objectReferenceInsert(m_tam_id); + + if (!m_saiObjectCollection.objectExists(key)) + { + m_saiObjectCollection.createObject(key); + } + } +} + int32_t Meta::getObjectReferenceCount( _In_ sai_object_id_t oid) const { diff --git a/meta/Meta.h b/meta/Meta.h index 1a0beb41..1391b06e 100644 --- a/meta/Meta.h +++ b/meta/Meta.h @@ -254,7 +254,9 @@ namespace saimeta _In_ uint32_t count, _In_ const sai_twamp_session_event_notification_data_t *data); - private: // notifications helpers + void meta_sai_on_tam_tel_type_config_change(_In_ sai_object_id_t m_tam_id); + + private: // notifications helpers void meta_sai_on_fdb_flush_event_consolidated( _In_ const sai_fdb_event_notification_data_t& data); @@ -280,7 +282,7 @@ namespace saimeta void meta_sai_on_twamp_session_event_single( _In_ const sai_twamp_session_event_notification_data_t& data); - private: // validation helpers + private: // validation helpers sai_status_t meta_generic_validation_objlist( _In_ const sai_attr_metadata_t& md, diff --git a/meta/NotificationFactory.cpp b/meta/NotificationFactory.cpp index 0c9f9572..9a22f97b 100644 --- a/meta/NotificationFactory.cpp +++ b/meta/NotificationFactory.cpp @@ -9,6 +9,7 @@ #include "NotificationBfdSessionStateChange.h" #include "NotificationTwampSessionEvent.h" #include "NotificationPortHostTxReadyEvent.h" +#include "NotificationTamTelTypeConfigChange.h" #include "sairediscommon.h" #include "swss/logger.h" @@ -51,5 +52,8 @@ std::shared_ptr NotificationFactory::deserialize( if (name == SAI_SWITCH_NOTIFICATION_NAME_TWAMP_SESSION_EVENT) return std::make_shared(serializedNotification); + if (name == SAI_SWITCH_NOTIFICATION_NAME_TAM_TEL_TYPE_CONFIG_CHANGE) + return std::make_shared(serializedNotification); + SWSS_LOG_THROW("unknown notification: '%s', FIXME", name.c_str()); } diff --git a/meta/NotificationTamTelTypeConfigChange.cpp b/meta/NotificationTamTelTypeConfigChange.cpp new file mode 100644 index 00000000..70a16583 --- /dev/null +++ b/meta/NotificationTamTelTypeConfigChange.cpp @@ -0,0 +1,49 @@ +#include "NotificationTamTelTypeConfigChange.h" + +#include "swss/logger.h" + +#include "sai_serialize.h" + +using namespace sairedis; + +NotificationTamTelTypeConfigChange::NotificationTamTelTypeConfigChange( + _In_ const std::string &serializedNotification) : Notification(SAI_SWITCH_NOTIFICATION_TYPE_TAM_TEL_TYPE_CONFIG_CHANGE, + serializedNotification) +{ + SWSS_LOG_ENTER(); + + sai_deserialize_object_id(serializedNotification, m_tam_id); +} + +sai_object_id_t NotificationTamTelTypeConfigChange::getSwitchId() const +{ + SWSS_LOG_ENTER(); + + return SAI_NULL_OBJECT_ID; +} + +sai_object_id_t NotificationTamTelTypeConfigChange::getAnyObjectId() const +{ + SWSS_LOG_ENTER(); + + return SAI_NULL_OBJECT_ID; +} + +void NotificationTamTelTypeConfigChange::processMetadata( + _In_ std::shared_ptr meta) const +{ + SWSS_LOG_ENTER(); + + meta->meta_sai_on_tam_tel_type_config_change(m_tam_id); +} + +void NotificationTamTelTypeConfigChange::executeCallback( + _In_ const sai_switch_notifications_t& switchNotifications) const +{ + SWSS_LOG_ENTER(); + + if (switchNotifications.on_tam_tel_type_config_change) + { + switchNotifications.on_tam_tel_type_config_change(m_tam_id); + } +} diff --git a/meta/NotificationTamTelTypeConfigChange.h b/meta/NotificationTamTelTypeConfigChange.h new file mode 100644 index 00000000..e95fff41 --- /dev/null +++ b/meta/NotificationTamTelTypeConfigChange.h @@ -0,0 +1,31 @@ +#pragma once + +#include "Notification.h" + +namespace sairedis +{ + class NotificationTamTelTypeConfigChange : public Notification + { + public: + NotificationTamTelTypeConfigChange( + _In_ const std::string &serializedNotification); + + virtual ~NotificationTamTelTypeConfigChange() = default; + + public: + + virtual sai_object_id_t getSwitchId() const override; + + virtual sai_object_id_t getAnyObjectId() const override; + + virtual void processMetadata( + _In_ std::shared_ptr meta) const override; + + virtual void executeCallback( + _In_ const sai_switch_notifications_t& switchNotifications) const override; + + private: + + sai_object_id_t m_tam_id; + }; +} diff --git a/meta/SaiSerialize.cpp b/meta/SaiSerialize.cpp index 373badd8..6b54ed58 100644 --- a/meta/SaiSerialize.cpp +++ b/meta/SaiSerialize.cpp @@ -2979,6 +2979,50 @@ std::string sai_serialize_stats_capability_list( return j.dump(); } +json sai_serialize_stat_st_capability( + _In_ const sai_stat_st_capability_t &stat_capability, + _In_ const sai_enum_metadata_t *meta) +{ + SWSS_LOG_ENTER(); + + json j = sai_serialize_stat_capability(stat_capability.capability, meta); + j["minimal_polling_interval"] = sai_serialize_number(stat_capability.minimal_polling_interval, false); + + return j; +} + +std::string sai_serialize_stats_st_capability_list( + _In_ const sai_stat_st_capability_list_t &stat_capability_list, + _In_ const sai_enum_metadata_t *meta, + _In_ bool countOnly) +{ + SWSS_LOG_ENTER(); + + json j; + + j["count"] = stat_capability_list.count; + + if (stat_capability_list.list == NULL || countOnly) + { + j["list"] = nullptr; + + return j.dump(); + } + + json arr = json::array(); + + for (uint32_t i = 0; i < stat_capability_list.count; ++i) + { + json item = sai_serialize_stat_st_capability(stat_capability_list.list[i], meta); + + arr.push_back(item); + } + + j["list"] = arr; + + return j.dump(); +} + std::string sai_serialize_poe_port_active_channel_type( _In_ const sai_poe_port_active_channel_type_t value) { @@ -5920,3 +5964,92 @@ void sai_deserialize_stats_capability_list( stat_modes_position++; } } + +/** + * @brief deserialize the stats st capability list + * + * Iterates thru stat_enum_str and populate + * the stats_capability with respective + * stat_enum (String to Enum conversion). + * Also iterates thru stat_modes_str and populate + * the stats_capability with respective + * stat_modes (String to Enum conversion) + * + * @param stats_capability stats stream telemetry capability enum list + * @param stat_enum_str SAI stat enum list as string + * @param stat_modes_str SAI stat mode list as string + * @param minimal_polling_interval_str SAI minimal polling interval list as string + * @return Void + */ +void sai_deserialize_stats_st_capability_list( + _Inout_ sai_stat_st_capability_list_t *stats_capability, + _In_ const std::string &stat_enum_str, + _In_ const std::string &stat_modes_str, + _In_ const std::string &minimal_polling_interval_str) +{ + SWSS_LOG_ENTER(); + + if (stats_capability == NULL) + { + SWSS_LOG_THROW("Stats capability pointer in deserialize is NULL"); + } + + uint32_t num_capabilities = stats_capability->count; + size_t stat_enum_position = 0; + size_t stat_modes_position = 0; + size_t stat_polling_interval_position = 0; + + for (uint32_t i = 0; i < num_capabilities; i++) + { + /* 1. Populate stat_enum */ + size_t old_stat_enum_position = stat_enum_position; + stat_enum_position = stat_enum_str.find(",", old_stat_enum_position); + std::string stat_enum = stat_enum_str.substr(old_stat_enum_position, + stat_enum_position - old_stat_enum_position); + stats_capability->list[i].capability.stat_enum = std::stoi(stat_enum); + + /* We have run out of values to add to our list */ + if (stat_enum_position == std::string::npos) + { + if (num_capabilities != i + 1) + { + SWSS_LOG_THROW("Lesser stat_enums than expected: expected %d, received %d", + num_capabilities, i + 1); + } + + break; + } + + /* 2. Populate stat_modes */ + size_t old_stat_modes_position = stat_modes_position; + stat_modes_position = stat_modes_str.find(",", old_stat_modes_position); + std::string stat_modes = stat_modes_str.substr(old_stat_modes_position, + stat_modes_position - old_stat_modes_position); + stats_capability->list[i].capability.stat_modes = std::stoi(stat_modes); + + /* We have run out of values to add to our list */ + if (stat_modes_position == std::string::npos) + { + if (num_capabilities != i + 1) + { + SWSS_LOG_THROW("Lesser stat_modes than expected: expected %d, received %d", + num_capabilities, i + 1); + } + + break; + } + + /* 3. Populate minimal polling interval */ + size_t old_stat_polling_interval_position = stat_polling_interval_position; + stat_polling_interval_position = minimal_polling_interval_str.find(",", old_stat_polling_interval_position); + std::string minimal_polling_interval = minimal_polling_interval_str.substr(old_stat_polling_interval_position, + stat_polling_interval_position - old_stat_polling_interval_position); + stats_capability->list[i].minimal_polling_interval = std::stoull(minimal_polling_interval); + + + /* Skip the commas */ + stat_enum_position++; + stat_modes_position++; + stat_polling_interval_position++; + } +} diff --git a/meta/sai_serialize.h b/meta/sai_serialize.h index 3fd45a06..1f9c0d14 100644 --- a/meta/sai_serialize.h +++ b/meta/sai_serialize.h @@ -311,6 +311,11 @@ std::string sai_serialize_stats_capability_list( _In_ const sai_enum_metadata_t* meta, _In_ bool countOnly); +std::string sai_serialize_stats_st_capability_list( + _In_ const sai_stat_st_capability_list_t &stat_capability_list, + _In_ const sai_enum_metadata_t *meta, + _In_ bool countOnly); + // serialize notifications std::string sai_serialize_fdb_event_ntf( @@ -686,3 +691,9 @@ void sai_deserialize_stats_capability_list( _Inout_ sai_stat_capability_list_t *stats_capability, _In_ const std::string& stat_enum_str, _In_ const std::string& stat_modes_str); + +void sai_deserialize_stats_st_capability_list( + _Inout_ sai_stat_st_capability_list_t *stats_capability, + _In_ const std::string &stat_enum_str, + _In_ const std::string &stat_modes_str, + _In_ const std::string &minimal_polling_interval_str); diff --git a/proxylib/Proxy.cpp b/proxylib/Proxy.cpp index ab3a280e..b1aad84a 100644 --- a/proxylib/Proxy.cpp +++ b/proxylib/Proxy.cpp @@ -65,6 +65,7 @@ Proxy::Proxy( m_swNtf.onBfdSessionStateChange = std::bind(&Proxy::onBfdSessionStateChange, this, _1, _2); m_swNtf.onPortHostTxReady = std::bind(&Proxy::onPortHostTxReady, this, _1, _2, _3); m_swNtf.onTwampSessionEvent = std::bind(&Proxy::onTwampSessionEvent, this, _1, _2); + m_swNtf.onTamTelTypeConfigChange = std::bind(&Proxy::onTamTelTypeConfigChange, this, _1); m_sn = m_swNtf.getSwitchNotifications(); @@ -1214,6 +1215,16 @@ void Proxy::onTwampSessionEvent( sendNotification(SAI_SWITCH_NOTIFICATION_NAME_TWAMP_SESSION_EVENT, s); } +void Proxy::onTamTelTypeConfigChange( + _In_ sai_object_id_t tam_tel_id) +{ + SWSS_LOG_ENTER(); + + std::string s = sai_serialize_object_id(tam_tel_id); + + sendNotification(SAI_SWITCH_NOTIFICATION_NAME_TAM_TEL_TYPE_CONFIG_CHANGE, s); +} + void Proxy::sendNotification( _In_ const std::string& op, _In_ const std::string& data) diff --git a/proxylib/Proxy.h b/proxylib/Proxy.h index 02977263..01b8222c 100644 --- a/proxylib/Proxy.h +++ b/proxylib/Proxy.h @@ -152,6 +152,9 @@ namespace saiproxy _In_ uint32_t count, _In_ const sai_twamp_session_event_notification_data_t *data); + void onTamTelTypeConfigChange( + _In_ sai_object_id_t tam_tel_id); + void sendNotification( _In_ const std::string& op, _In_ const std::string& data); diff --git a/proxylib/Sai.cpp b/proxylib/Sai.cpp index 7295845f..dc2e3484 100644 --- a/proxylib/Sai.cpp +++ b/proxylib/Sai.cpp @@ -560,8 +560,6 @@ sai_status_t Sai::queryStatsStCapability( SWSS_LOG_ERROR("not implemented, FIXME"); - // TODO: Fix me - return SAI_STATUS_NOT_IMPLEMENTED; } diff --git a/pyext/pysairedis.cpp b/pyext/pysairedis.cpp index 582ed19e..efff11d0 100644 --- a/pyext/pysairedis.cpp +++ b/pyext/pysairedis.cpp @@ -104,6 +104,7 @@ static PyObject * py_queue_pfc_deadlock_notification = NULL; static PyObject * py_switch_shutdown_request_notification = NULL; static PyObject * py_switch_state_change_notification = NULL; static PyObject * py_bfd_session_state_change_notification = NULL; +static PyObject * py_tam_tel_type_config_change_notification = NULL; void call_python(PyObject* callObject, PyObject* arglist) { @@ -206,6 +207,16 @@ static void sai_bfd_session_state_change_notification( Py_DECREF(arglist); } +static void sai_tam_tel_type_config_change_notification( + _In_ sai_object_id_t tam_tel_type_id) +{ + PyObject *arglist = Py_BuildValue("(l)", tam_tel_type_id); + + call_python(py_tam_tel_type_config_change_notification, arglist); + + Py_DECREF(arglist); +} + sai_pointer_t sai_get_notification_pointer( sai_attr_id_t id, PyObject*callback) @@ -249,6 +260,11 @@ sai_pointer_t sai_get_notification_pointer( py_bfd_session_state_change_notification = callback; return (void*)&sai_bfd_session_state_change_notification; + case SAI_SWITCH_ATTR_TAM_TEL_TYPE_CONFIG_CHANGE_NOTIFY: + Py_XDECREF(py_tam_tel_type_config_change_notification); + py_tam_tel_type_config_change_notification = callback; + return (void*)&sai_tam_tel_type_config_change_notification; + default: Py_XDECREF(callback); break; diff --git a/syncd/NotificationHandler.cpp b/syncd/NotificationHandler.cpp index 2815d8e3..972c68fc 100644 --- a/syncd/NotificationHandler.cpp +++ b/syncd/NotificationHandler.cpp @@ -216,6 +216,16 @@ void NotificationHandler::onTwampSessionEvent( enqueueNotification(SAI_SWITCH_NOTIFICATION_NAME_TWAMP_SESSION_EVENT, s); } +void NotificationHandler::onTamTelTypeConfigChange( + _In_ sai_object_id_t tam_tel_id) +{ + SWSS_LOG_ENTER(); + + std::string s = sai_serialize_object_id(tam_tel_id); + + enqueueNotification(SAI_SWITCH_NOTIFICATION_NAME_TAM_TEL_TYPE_CONFIG_CHANGE, s); +} + void NotificationHandler::enqueueNotification( _In_ const std::string& op, _In_ const std::string& data) diff --git a/syncd/NotificationHandler.h b/syncd/NotificationHandler.h index 970dd552..88bd3863 100644 --- a/syncd/NotificationHandler.h +++ b/syncd/NotificationHandler.h @@ -87,6 +87,9 @@ namespace syncd _In_ uint32_t count, _In_ const sai_twamp_session_event_notification_data_t *data); + void onTamTelTypeConfigChange( + _In_ sai_object_id_t tam_tel_id); + private: void enqueueNotification( diff --git a/syncd/NotificationProcessor.cpp b/syncd/NotificationProcessor.cpp index f9b9be39..b5dc5e29 100644 --- a/syncd/NotificationProcessor.cpp +++ b/syncd/NotificationProcessor.cpp @@ -781,6 +781,16 @@ void NotificationProcessor::handle_twamp_session_event( sai_deserialize_free_twamp_session_event_ntf(count, twampsessionevent); } +void NotificationProcessor::handle_tam_tel_type_config_change( + _In_ const std::string &data) +{ + SWSS_LOG_ENTER(); + + SWSS_LOG_DEBUG("TAM telemesai_serialize_object_id(tam_type_id)try type config change on TAM id %s", data.c_str()); + + sendNotification(SAI_SWITCH_NOTIFICATION_NAME_TAM_TEL_TYPE_CONFIG_CHANGE, data); +} + void NotificationProcessor::processNotification( _In_ const swss::KeyOpFieldsValuesTuple& item) { @@ -837,6 +847,10 @@ void NotificationProcessor::syncProcessNotification( { handle_twamp_session_event(data); } + else if (notification == SAI_SWITCH_NOTIFICATION_NAME_TAM_TEL_TYPE_CONFIG_CHANGE) + { + handle_tam_tel_type_config_change(data); + } else { SWSS_LOG_ERROR("unknown notification: %s", notification.c_str()); diff --git a/syncd/NotificationProcessor.h b/syncd/NotificationProcessor.h index 0c89260a..837a6e38 100644 --- a/syncd/NotificationProcessor.h +++ b/syncd/NotificationProcessor.h @@ -144,6 +144,9 @@ namespace syncd void handle_twamp_session_event( _In_ const std::string &data); + void handle_tam_tel_type_config_change( + _In_ const std::string &data); + void processNotification( _In_ const swss::KeyOpFieldsValuesTuple& item); diff --git a/syncd/SwitchNotifications.cpp b/syncd/SwitchNotifications.cpp index 9204825f..257ee571 100644 --- a/syncd/SwitchNotifications.cpp +++ b/syncd/SwitchNotifications.cpp @@ -141,6 +141,15 @@ void SwitchNotifications::SlotBase::onTwampSessionEvent( return m_slots.at(context)->m_handler->onTwampSessionEvent(count, data); } +void SwitchNotifications::SlotBase::onTamTelTypeConfigChange( + _In_ int context, + _In_ sai_object_id_t tam_tel_id) +{ + SWSS_LOG_ENTER(); + + return m_slots.at(context)->m_handler->onTamTelTypeConfigChange(tam_tel_id); +} + const sai_switch_notifications_t& SwitchNotifications::SlotBase::getSwitchNotifications() const { SWSS_LOG_ENTER(); diff --git a/syncd/SwitchNotifications.h b/syncd/SwitchNotifications.h index 4a504343..73af025c 100644 --- a/syncd/SwitchNotifications.h +++ b/syncd/SwitchNotifications.h @@ -90,7 +90,11 @@ namespace syncd _In_ uint32_t count, _In_ const sai_twamp_session_event_notification_data_t *data); - protected: + static void onTamTelTypeConfigChange( + _In_ int context, + _In_ sai_object_id_t tam_tel_id); + + protected: SwitchNotifications* m_handler; @@ -120,7 +124,7 @@ namespace syncd .on_twamp_session_event = &Slot::onTwampSessionEvent, .on_icmp_echo_session_state_change = nullptr, .on_extended_port_state_change = nullptr, - .on_tam_tel_type_config_change = nullptr, + .on_tam_tel_type_config_change = &Slot::onTamTelTypeConfigChange, .on_ha_set_event = nullptr, .on_ha_scope_event = nullptr, }) { } @@ -228,6 +232,14 @@ namespace syncd return SlotBase::onTwampSessionEvent(context, count, data); } + + static void onTamTelTypeConfigChange( + _In_ sai_object_id_t tam_tel_id) + { + SWSS_LOG_ENTER(); + + return SlotBase::onTamTelTypeConfigChange(context, tam_tel_id); + } }; static std::vector m_slots; @@ -259,8 +271,9 @@ namespace syncd std::function onSwitchStateChange; std::function onBfdSessionStateChange; std::function onTwampSessionEvent; + std::function onTamTelTypeConfigChange; - private: + private: SlotBase*m_slot; }; diff --git a/syncd/Syncd.cpp b/syncd/Syncd.cpp index 37ec2612..8a1cb186 100644 --- a/syncd/Syncd.cpp +++ b/syncd/Syncd.cpp @@ -167,6 +167,7 @@ Syncd::Syncd( m_sn.onBfdSessionStateChange = std::bind(&NotificationHandler::onBfdSessionStateChange, m_handler.get(), _1, _2); m_sn.onPortHostTxReady = std::bind(&NotificationHandler::onPortHostTxReady, m_handler.get(), _1, _2, _3); m_sn.onTwampSessionEvent = std::bind(&NotificationHandler::onTwampSessionEvent, m_handler.get(), _1, _2); + m_sn.onTamTelTypeConfigChange = std::bind(&NotificationHandler::onTamTelTypeConfigChange, m_handler.get(), _1); m_handler->setSwitchNotifications(m_sn.getSwitchNotifications()); @@ -428,6 +429,9 @@ sai_status_t Syncd::processSingleEvent( if (op == REDIS_ASIC_STATE_COMMAND_STATS_CAPABILITY_QUERY) return processStatsCapabilityQuery(kco); + if (op == REDIS_ASIC_STATE_COMMAND_STATS_ST_CAPABILITY_QUERY) + return processStatsStCapabilityQuery(kco); + SWSS_LOG_THROW("event op '%s' is not implemented, FIXME", op.c_str()); } @@ -693,6 +697,92 @@ sai_status_t Syncd::processStatsCapabilityQuery( return status; } +sai_status_t Syncd::processStatsStCapabilityQuery( + _In_ const swss::KeyOpFieldsValuesTuple &kco) +{ + SWSS_LOG_ENTER(); + + auto &strSwitchVid = kfvKey(kco); + + sai_object_id_t switchVid; + sai_deserialize_object_id(strSwitchVid, switchVid); + + sai_object_id_t switchRid = m_translator->translateVidToRid(switchVid); + + 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_STATS_ST_CAPABILITY_RESPONSE); + + return SAI_STATUS_INVALID_PARAMETER; + } + + sai_object_type_t objectType; + sai_deserialize_object_type(fvValue(values[0]), objectType); + + uint32_t list_size = std::stoi(fvValue(values[1])); + + std::vector stat_capability_list(list_size); + + sai_stat_st_capability_list_t statCapList; + + statCapList.count = list_size; + statCapList.list = stat_capability_list.data(); + + sai_status_t status = m_vendorSai->queryStatsStCapability(switchRid, objectType, &statCapList); + + std::vector entry; + + if (status == SAI_STATUS_SUCCESS) + { + std::vector vec_stat_enum; + std::vector vec_stat_modes; + std::vector vec_minimal_polling_intervals; + + for (uint32_t it = 0; it < statCapList.count; it++) + { + vec_stat_enum.push_back(std::to_string(statCapList.list[it].capability.stat_enum)); + vec_stat_modes.push_back(std::to_string(statCapList.list[it].capability.stat_modes)); + vec_minimal_polling_intervals.push_back(std::to_string(statCapList.list[it].minimal_polling_interval)); + } + + std::ostringstream join_stat_enum; + std::copy(vec_stat_enum.begin(), vec_stat_enum.end(), std::ostream_iterator(join_stat_enum, ",")); + auto strCapEnum = join_stat_enum.str(); + + std::ostringstream join_stat_modes; + std::copy(vec_stat_modes.begin(), vec_stat_modes.end(), std::ostream_iterator(join_stat_modes, ",")); + auto strCapModes = join_stat_modes.str(); + + std::ostringstream join_minimal_polling_intervals; + std::copy(vec_minimal_polling_intervals.begin(), vec_minimal_polling_intervals.end(), std::ostream_iterator(join_minimal_polling_intervals, ",")); + auto strCapMinPollInt = join_minimal_polling_intervals.str(); + + entry = + { + swss::FieldValueTuple("STAT_ENUM", strCapEnum), + swss::FieldValueTuple("STAT_MODES", strCapModes), + swss::FieldValueTuple("MINIMAL_POLLING_INTERVALS", strCapMinPollInt), + swss::FieldValueTuple("STAT_COUNT", std::to_string(statCapList.count))}; + + SWSS_LOG_DEBUG("Sending response: stat_enums = '%s', stat_modes = '%s', minimal_polling_intervals = '%s' count = %d", + strCapEnum.c_str(), strCapModes.c_str(), strCapMinPollInt.c_str(), statCapList.count); + } + else if (status == SAI_STATUS_BUFFER_OVERFLOW) + { + entry = {swss::FieldValueTuple("STAT_COUNT", std::to_string(statCapList.count))}; + + SWSS_LOG_DEBUG("Sending response: count = %u", statCapList.count); + } + + m_selectableChannel->set(sai_serialize_status(status), entry, REDIS_ASIC_STATE_COMMAND_STATS_ST_CAPABILITY_RESPONSE); + + return status; +} + sai_status_t Syncd::processFdbFlush( _In_ const swss::KeyOpFieldsValuesTuple &kco) { diff --git a/syncd/Syncd.h b/syncd/Syncd.h index 12b98d86..bd59fcc2 100644 --- a/syncd/Syncd.h +++ b/syncd/Syncd.h @@ -139,6 +139,9 @@ namespace syncd sai_status_t processStatsCapabilityQuery( _In_ const swss::KeyOpFieldsValuesTuple &kco); + sai_status_t processStatsStCapabilityQuery( + _In_ const swss::KeyOpFieldsValuesTuple &kco); + sai_status_t processFdbFlush( _In_ const swss::KeyOpFieldsValuesTuple &kco); diff --git a/syncd/VendorSai.cpp b/syncd/VendorSai.cpp index bf7b163c..17d3ee5d 100644 --- a/syncd/VendorSai.cpp +++ b/syncd/VendorSai.cpp @@ -53,9 +53,9 @@ VendorSai::VendorSai() .query_attribute_enum_values_capability = &sai_query_attribute_enum_values_capability, .query_object_stage = nullptr, .query_stats_capability = &sai_query_stats_capability, - .query_stats_st_capability = nullptr, + .query_stats_st_capability = &sai_query_stats_st_capability, .switch_id_query = &sai_switch_id_query, - .tam_telemetry_get_data = nullptr, + .tam_telemetry_get_data = &sai_tam_telemetry_get_data, }; m_globalApis = ga; diff --git a/tests/TestClient.cpp b/tests/TestClient.cpp index 9361d046..49568412 100644 --- a/tests/TestClient.cpp +++ b/tests/TestClient.cpp @@ -389,6 +389,33 @@ void TestClient::test_query_api() SAI_OBJECT_TYPE_QUEUE, &queue_stats_capability)); + /* Test queue stats capability get */ + sai_stat_st_capability_list_t queue_stats_st_capability; + + queue_stats_st_capability.count = 1; + queue_stats_st_capability.list = nullptr; + + SWSS_LOG_NOTICE(" * sai_query_stats_st_capability"); + + rc = sai_query_stats_st_capability( + m_switch_id, + SAI_OBJECT_TYPE_QUEUE, + &queue_stats_st_capability); + ASSERT_TRUE(rc == SAI_STATUS_BUFFER_OVERFLOW); + + sai_stat_st_capability_t stat_st_initializer; + stat_st_initializer.capability.stat_enum = 0; + stat_st_initializer.capability.stat_modes = 0; + std::vector qstat_st_cap_list(queue_stats_st_capability.count, stat_st_initializer); + queue_stats_st_capability.list = qstat_st_cap_list.data(); + + SWSS_LOG_NOTICE(" * sai_query_stats_st_capability"); + + ASSERT_SUCCESS(sai_query_stats_st_capability( + m_switch_id, + SAI_OBJECT_TYPE_QUEUE, + &queue_stats_st_capability)); + teardown(); } diff --git a/unittest/lib/Makefile.am b/unittest/lib/Makefile.am index 60882483..8fbada14 100644 --- a/unittest/lib/Makefile.am +++ b/unittest/lib/Makefile.am @@ -29,7 +29,7 @@ tests_SOURCES = \ TestSai.cpp \ MockSaiInterface.cpp -tests_CXXFLAGS = $(DBGFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS_COMMON) +tests_CXXFLAGS = $(DBGFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS_COMMON) -fno-access-control tests_LDADD = $(LDADD_GTEST) $(top_srcdir)/lib/libSaiRedis.a -lhiredis -lswsscommon -lpthread -L$(top_srcdir)/meta/.libs -lsaimetadata -lsaimeta -lzmq $(CODE_COVERAGE_LIBS) TESTS = tests diff --git a/unittest/lib/TestClientServerSai.cpp b/unittest/lib/TestClientServerSai.cpp index baebec2e..3eb65733 100644 --- a/unittest/lib/TestClientServerSai.cpp +++ b/unittest/lib/TestClientServerSai.cpp @@ -113,6 +113,28 @@ TEST(ClientServerSai, queryStatsCapability) EXPECT_EQ(SAI_STATUS_FAILURE, css->queryStatsCapability(SAI_NULL_OBJECT_ID, SAI_OBJECT_TYPE_QUEUE, &queue_stats_capability)); } +TEST(ClientServerSai, queryStatsStCapability) +{ + auto css = std::make_shared(); + + sai_stat_st_capability_list_t queue_stats_capability; + sai_stat_st_capability_t stat_initializer; + stat_initializer.capability.stat_enum = 0; + stat_initializer.capability.stat_modes = 0; + stat_initializer.minimal_polling_interval = 0; + std::vector qstat_cap_list(2, stat_initializer); + queue_stats_capability.count = 2; + queue_stats_capability.list = qstat_cap_list.data(); + queue_stats_capability.list[0].capability.stat_enum = SAI_QUEUE_STAT_WRED_ECN_MARKED_PACKETS; + queue_stats_capability.list[0].capability.stat_modes = SAI_STATS_MODE_READ; + queue_stats_capability.list[0].minimal_polling_interval = 1000; + queue_stats_capability.list[1].capability.stat_enum = SAI_QUEUE_STAT_PACKETS; + queue_stats_capability.list[1].capability.stat_modes = SAI_STATS_MODE_READ; + queue_stats_capability.list[1].minimal_polling_interval = 1000; + + EXPECT_EQ(SAI_STATUS_FAILURE, css->queryStatsStCapability(SAI_NULL_OBJECT_ID, SAI_OBJECT_TYPE_QUEUE, &queue_stats_capability)); +} + TEST(ClientServerSai, logSet) { auto css = std::make_shared(); diff --git a/unittest/lib/TestRedisRemoteSaiInterface.cpp b/unittest/lib/TestRedisRemoteSaiInterface.cpp index b9f7df02..aa50c083 100644 --- a/unittest/lib/TestRedisRemoteSaiInterface.cpp +++ b/unittest/lib/TestRedisRemoteSaiInterface.cpp @@ -1,9 +1,38 @@ #include "RedisRemoteSaiInterface.h" #include "ContextConfigContainer.h" +#include "sairediscommon.h" #include +#include using namespace sairedis; +using namespace std; +using namespace swss; + +class TestRedisRemoteSaiInterfaceMockChannel : public RedisChannel +{ +public: + TestRedisRemoteSaiInterfaceMockChannel(_In_ const string &dbAsic, + _In_ Channel::Callback callback) : RedisChannel(dbAsic, callback) { + SWSS_LOG_ENTER(); + } + + sai_status_t wait( + _In_ const string &command, + _Out_ KeyOpFieldsValuesTuple &kco) + { + SWSS_LOG_ENTER(); + + if (m_wait_mock) + { + return m_wait_mock(command, kco); + } + return SAI_STATUS_SUCCESS; + } + + function m_wait_mock; +}; + TEST(RedisRemoteSaiInterface, queryStatsCapabilityNegative) { @@ -17,3 +46,45 @@ TEST(RedisRemoteSaiInterface, queryStatsCapabilityNegative) SAI_OBJECT_TYPE_NULL, 0)); } + +TEST(RedisRemoteSaiInterface, queryStatsStCapability) +{ + SWSS_LOG_ENTER(); + + auto ctx = ContextConfigContainer::loadFromFile("foo"); + auto rec = make_shared(); + + RedisRemoteSaiInterface sai(ctx->get(0), nullptr, rec); + + sai.m_communicationChannel = std::make_shared( + sai.m_contextConfig->m_dbAsic, + std::bind(&RedisRemoteSaiInterface::handleNotification, &sai, placeholders::_1, placeholders::_2, placeholders::_3)); + + EXPECT_EQ(SAI_STATUS_INVALID_PARAMETER, + sai.queryStatsStCapability(0, + SAI_OBJECT_TYPE_NULL, + 0)); + + dynamic_cast(*sai.m_communicationChannel).m_wait_mock = + [](const string &command, KeyOpFieldsValuesTuple &kco) -> sai_status_t + { + SWSS_LOG_ENTER(); + + kfvFieldsValues(kco).push_back(make_pair("", "0,1")); + kfvFieldsValues(kco).push_back(make_pair("", "0,1")); + kfvFieldsValues(kco).push_back(make_pair("", "100,100")); + kfvFieldsValues(kco).push_back(make_pair("", "2")); + + return SAI_STATUS_SUCCESS; + }; + + vector buffer; + buffer.resize(96); + sai_stat_st_capability_list_t stats_capability; + stats_capability.count = static_cast(buffer.size()); + stats_capability.list = buffer.data(); + EXPECT_EQ(SAI_STATUS_SUCCESS, + sai.queryStatsStCapability(0, + SAI_OBJECT_TYPE_PORT, + &stats_capability)); +} diff --git a/unittest/lib/TestServerSai.cpp b/unittest/lib/TestServerSai.cpp index 2eb9dbab..224018fe 100644 --- a/unittest/lib/TestServerSai.cpp +++ b/unittest/lib/TestServerSai.cpp @@ -9,11 +9,13 @@ #include "swss/dbconnector.h" #include "sairediscommon.h" +#include "meta/SelectableChannel.h" #include "MockSaiInterface.h" #include "SelectableChannel.h" #include "swss/dbconnector.h" #include "swss/redisreply.h" +#include "swss/logger.h" #include #include @@ -21,6 +23,8 @@ using namespace sairedis; +using namespace std; +using namespace swss; static const char* profile_get_value( _In_ sai_switch_profile_id_t profile_id, @@ -44,6 +48,18 @@ static sai_service_method_table_t test_services = { profile_get_next_value }; +class TestServerSaiMockChannel : public SelectableChannel +{ +public: + MOCK_METHOD(bool, empty, (), (override)); + MOCK_METHOD(void, pop, (swss::KeyOpFieldsValuesTuple & kco, bool initViewMode), (override)); + MOCK_METHOD(void, set, (const std::string &key, const std::vector &values, const std::string &op), (override)); + MOCK_METHOD(int, getFd, (), (override)); + MOCK_METHOD(uint64_t, readData, (), (override)); + +}; + + TEST(ServerSai, bulkGet) { ServerSai sai; @@ -65,3 +81,22 @@ TEST(ServerSai, bulkGet) SAI_BULK_OP_ERROR_MODE_STOP_ON_ERROR, statuses)); } + +TEST(ServerSai, stats_st_capability_query) +{ + SWSS_LOG_ENTER(); + + ServerSai sai; + + sai.apiInitialize(0, &test_services); + sai.m_selectableChannel = make_shared(); + sai.m_sai = make_shared(); + + KeyOpFieldsValuesTuple kco; + kfvKey(kco) = "oid:0x21000000000000"; + kfvFieldsValues(kco).push_back(make_pair("OBJECT_TYPE", "SAI_OBJECT_TYPE_PORT")); + kfvFieldsValues(kco).push_back(make_pair("LIST_SIZE", "96")); + + EXPECT_EQ(SAI_STATUS_SUCCESS, + sai.processStatsStCapabilityQuery(kco)); +} diff --git a/unittest/lib/TestSwitch.cpp b/unittest/lib/TestSwitch.cpp index d6ec9d9b..14cd7567 100644 --- a/unittest/lib/TestSwitch.cpp +++ b/unittest/lib/TestSwitch.cpp @@ -22,7 +22,7 @@ TEST(Switch, updateNotifications) { auto s = std::make_shared(7); - sai_attribute_t attrs[11]; + sai_attribute_t attrs[12]; attrs[0].id = 10000; @@ -39,6 +39,7 @@ TEST(Switch, updateNotifications) attrs[8].value.ptr = (void*)1; attrs[9].value.ptr = (void*)1; attrs[10].value.ptr = (void*)1; + attrs[11].value.ptr = (void *)1; attrs[0].id = SAI_SWITCH_ATTR_SWITCH_STATE_CHANGE_NOTIFY; attrs[1].id = SAI_SWITCH_ATTR_SHUTDOWN_REQUEST_NOTIFY; @@ -51,8 +52,9 @@ TEST(Switch, updateNotifications) attrs[8].id = SAI_SWITCH_ATTR_PORT_HOST_TX_READY_NOTIFY; attrs[9].id = SAI_SWITCH_ATTR_SWITCH_ASIC_SDK_HEALTH_EVENT_NOTIFY; attrs[10].id = SAI_SWITCH_ATTR_INIT_SWITCH; + attrs[11].id = SAI_SWITCH_ATTR_TAM_TEL_TYPE_CONFIG_CHANGE_NOTIFY; - s->updateNotifications(10, attrs); + s->updateNotifications(12, attrs); auto sn = s->getSwitchNotifications(); @@ -66,4 +68,5 @@ TEST(Switch, updateNotifications) EXPECT_EQ((void*)1, sn.on_nat_event); EXPECT_EQ((void*)1, sn.on_port_host_tx_ready); EXPECT_EQ((void*)1, sn.on_switch_asic_sdk_health_event); + EXPECT_EQ((void*)1, sn.on_tam_tel_type_config_change); } diff --git a/unittest/meta/Makefile.am b/unittest/meta/Makefile.am index 60f0cd50..eccac4df 100644 --- a/unittest/meta/Makefile.am +++ b/unittest/meta/Makefile.am @@ -26,6 +26,7 @@ tests_SOURCES = \ TestNotificationSwitchAsicSdkHealthEvent.cpp \ TestNotificationSwitchStateChange.cpp \ TestNotificationBfdSessionStateChange.cpp \ + TestNotificationTam.cpp \ TestOidRefCounter.cpp \ TestPerformanceIntervalTimer.cpp \ TestPortRelatedSet.cpp \ diff --git a/unittest/meta/TestDummySaiInterface.cpp b/unittest/meta/TestDummySaiInterface.cpp index 4c8ca1ca..9bf75360 100644 --- a/unittest/meta/TestDummySaiInterface.cpp +++ b/unittest/meta/TestDummySaiInterface.cpp @@ -208,6 +208,16 @@ void onTwampSessionEvent( ntfCounter++; } +void onTamTelTypeConfigChange( + _In_ sai_object_id_t tam_tel_id) +{ + SWSS_LOG_ENTER(); + + SWSS_LOG_NOTICE("received: onTamTelTypeConfigChange"); + + ntfCounter++; +} + TEST(DummySaiInterface, sendNotification) { DummySaiInterface sai; @@ -231,6 +241,8 @@ TEST(DummySaiInterface, sendNotification) EXPECT_EQ(sai.enqueueNotificationToSend(SAI_SWITCH_ATTR_PORT_STATE_CHANGE_NOTIFY), SAI_STATUS_SUCCESS); EXPECT_EQ(sai.enqueueNotificationToSend(SAI_SWITCH_ATTR_SHUTDOWN_REQUEST_NOTIFY), SAI_STATUS_SUCCESS); + EXPECT_EQ(sai.enqueueNotificationToSend(SAI_SWITCH_ATTR_TAM_TEL_TYPE_CONFIG_CHANGE_NOTIFY), SAI_STATUS_SUCCESS); + sai_attribute_t attr; sai_object_id_t switch_id = 0x1; @@ -276,11 +288,15 @@ TEST(DummySaiInterface, sendNotification) attr.value.ptr = (void*)&onTwampSessionEvent; sai.set(SAI_OBJECT_TYPE_SWITCH, switch_id, &attr); + attr.id = SAI_SWITCH_ATTR_TAM_TEL_TYPE_CONFIG_CHANGE_NOTIFY; + attr.value.ptr = (void*)&onTamTelTypeConfigChange; + sai.set(SAI_OBJECT_TYPE_SWITCH, switch_id, &attr); + EXPECT_EQ(sai.start(), SAI_STATUS_SUCCESS); sleep(1); EXPECT_EQ(sai.stop(), SAI_STATUS_SUCCESS); - EXPECT_EQ(ntfCounter, 4 + 6); + EXPECT_EQ(ntfCounter, 4 + 6 + 1); } diff --git a/unittest/meta/TestMeta.cpp b/unittest/meta/TestMeta.cpp index f12d79e7..009d9947 100644 --- a/unittest/meta/TestMeta.cpp +++ b/unittest/meta/TestMeta.cpp @@ -970,6 +970,35 @@ TEST(Meta, queryStatsCapability) } +TEST(Meta, queryStatsStCapability) +{ + Meta m(std::make_shared()); + + sai_object_id_t switchId = 0; + + sai_attribute_t attr; + + attr.id = SAI_SWITCH_ATTR_INIT_SWITCH; + attr.value.booldata = true; + + EXPECT_EQ(SAI_STATUS_SUCCESS, m.create(SAI_OBJECT_TYPE_SWITCH, &switchId, SAI_NULL_OBJECT_ID, 1, &attr)); + + sai_stat_st_capability_list_t queue_stats_capability; + sai_stat_st_capability_t stat_initializer; + stat_initializer.capability.stat_enum = 0; + stat_initializer.capability.stat_modes = 0; + stat_initializer.minimal_polling_interval = 0; + std::vector qstat_cap_list(20, stat_initializer); + queue_stats_capability.count = 15; + queue_stats_capability.list = qstat_cap_list.data(); + + EXPECT_EQ(SAI_STATUS_SUCCESS, m.queryStatsStCapability(switchId, SAI_OBJECT_TYPE_QUEUE, &queue_stats_capability)); + + queue_stats_capability.list = nullptr; + + EXPECT_EQ(SAI_STATUS_INVALID_PARAMETER, m.queryStatsStCapability(switchId, SAI_OBJECT_TYPE_QUEUE, &queue_stats_capability)); +} + TEST(Meta, meta_validate_stats) { MockMeta m(std::make_shared()); diff --git a/unittest/meta/TestNotificationTam.cpp b/unittest/meta/TestNotificationTam.cpp new file mode 100644 index 00000000..3ba9eeaf --- /dev/null +++ b/unittest/meta/TestNotificationTam.cpp @@ -0,0 +1,33 @@ +#include "NotificationTamTelTypeConfigChange.h" +#include "Meta.h" +#include "MetaTestSaiInterface.h" + +#include "sairediscommon.h" +#include "sai_serialize.h" + +#include + +using namespace sairedis; +using namespace saimeta; + +TEST(NotificationTamTelTypeConfigChange, processMetadata) +{ + auto sai = std::make_shared(); + auto meta = std::make_shared(sai); + + sai_object_id_t switch_id; + sai_object_id_t tam_id; + + sai_attribute_t attr; + attr.id = SAI_SWITCH_ATTR_INIT_SWITCH; + attr.value.booldata = true; + + sai->create(SAI_OBJECT_TYPE_SWITCH, &switch_id, SAI_NULL_OBJECT_ID, 1, &attr); + sai->create(SAI_OBJECT_TYPE_TAM_TEL_TYPE, &tam_id, switch_id, 0, nullptr); + + std::stringstream ss; + ss << "oid:0x" << std::hex << tam_id; + + NotificationTamTelTypeConfigChange n(ss.str()); + n.processMetadata(meta); +} diff --git a/unittest/meta/TestSaiSerialize.cpp b/unittest/meta/TestSaiSerialize.cpp index 39d50256..0f7a8f06 100644 --- a/unittest/meta/TestSaiSerialize.cpp +++ b/unittest/meta/TestSaiSerialize.cpp @@ -1460,3 +1460,86 @@ TEST(SaiSerialize, sai_serialize_eni_trusted_vni_entry) sai_deserialize_eni_trusted_vni_entry(s, e); } + +TEST(SaiSerialize, serialize_stat_st_capability_list) +{ + SWSS_LOG_ENTER(); + + extern const sai_enum_metadata_t sai_metadata_enum_sai_stats_mode_t; + sai_stat_st_capability_list_t queue_stats_capability; + sai_stat_st_capability_t stat_initializer; + stat_initializer.capability.stat_enum = 0; + stat_initializer.capability.stat_modes = 0; + stat_initializer.minimal_polling_interval = 0; + std::vector + qstat_cap_list(2, stat_initializer); + queue_stats_capability.count = 2; + queue_stats_capability.list = qstat_cap_list.data(); + queue_stats_capability.list[0].capability.stat_enum = SAI_QUEUE_STAT_WRED_ECN_MARKED_PACKETS; + queue_stats_capability.list[0].capability.stat_modes = SAI_STATS_MODE_READ; + queue_stats_capability.list[0].minimal_polling_interval = 100; + queue_stats_capability.list[1].capability.stat_enum = SAI_QUEUE_STAT_PACKETS; + queue_stats_capability.list[1].capability.stat_modes = SAI_STATS_MODE_READ; + queue_stats_capability.list[1].minimal_polling_interval = 200; + + std::string capab_count = sai_serialize_stats_st_capability_list(queue_stats_capability, &sai_metadata_enum_sai_stats_mode_t, true); + std::string capab_str = sai_serialize_stats_st_capability_list(queue_stats_capability, &sai_metadata_enum_sai_stats_mode_t, false); + + std::string exp_count_str = "{\"count\":2,\"list\":null}"; + EXPECT_EQ(capab_count, exp_count_str); + + std::string exp_capab_str = "{\"count\":2,\"list\":[{\"minimal_polling_interval\":\"100\",\"stat_enum\":\"34\",\"stat_modes\":[\"SAI_STATS_MODE_READ\"]},{\"minimal_polling_interval\":\"200\",\"stat_enum\":\"0\",\"stat_modes\":[\"SAI_STATS_MODE_READ\"]}]}"; + EXPECT_EQ(capab_str, exp_capab_str); + + std::vector vec_stat_enum; + std::vector vec_stat_modes; + std::vector vec_minimal_polling_intervals; + + for (uint32_t it = 0; it < queue_stats_capability.count; it++) + { + vec_stat_enum.push_back(std::to_string(queue_stats_capability.list[it].capability.stat_enum)); + vec_stat_modes.push_back(std::to_string(queue_stats_capability.list[it].capability.stat_modes)); + vec_minimal_polling_intervals.push_back(std::to_string(queue_stats_capability.list[it].minimal_polling_interval)); + } + + std::ostringstream join_stat_enum; + std::copy(vec_stat_enum.begin(), vec_stat_enum.end(), std::ostream_iterator(join_stat_enum, ",")); + auto strCapEnum = join_stat_enum.str(); + + std::ostringstream join_stat_modes; + std::copy(vec_stat_modes.begin(), vec_stat_modes.end(), std::ostream_iterator(join_stat_modes, ",")); + auto strCapModes = join_stat_modes.str(); + + std::ostringstream join_minimal_polling_intervals; + std::copy(vec_minimal_polling_intervals.begin(), vec_minimal_polling_intervals.end(), std::ostream_iterator(join_minimal_polling_intervals, ",")); + auto strCapMinPollInt = join_minimal_polling_intervals.str(); + + sai_stat_st_capability_list_t stats_capability; + std::vector stat_cap_list(queue_stats_capability.count, stat_initializer); + stats_capability.count = queue_stats_capability.count; + stats_capability.list = stat_cap_list.data(); + + // deserialize + EXPECT_THROW(sai_deserialize_stats_st_capability_list(NULL, strCapEnum, strCapModes, strCapMinPollInt), std::runtime_error); + + sai_deserialize_stats_st_capability_list(&stats_capability, strCapEnum, strCapModes, strCapMinPollInt); + + EXPECT_EQ(stats_capability.count, queue_stats_capability.count); + EXPECT_EQ(stats_capability.list[0].capability.stat_modes, SAI_STATS_MODE_READ); + EXPECT_EQ(stats_capability.list[1].capability.stat_modes, SAI_STATS_MODE_READ); + int is_expected_enum = false; + + if ((stats_capability.list[0].capability.stat_enum == SAI_QUEUE_STAT_WRED_ECN_MARKED_PACKETS)||(stats_capability.list[1].capability.stat_enum == SAI_QUEUE_STAT_PACKETS)) + { + is_expected_enum = true; + } + if ((stats_capability.list[1].capability.stat_enum == SAI_QUEUE_STAT_WRED_ECN_MARKED_PACKETS)||(stats_capability.list[0].capability.stat_enum == SAI_QUEUE_STAT_PACKETS)) + { + is_expected_enum = true; + } + EXPECT_EQ(is_expected_enum, true); + + EXPECT_EQ(stats_capability.list[0].minimal_polling_interval, 100); + EXPECT_EQ(stats_capability.list[1].minimal_polling_interval, 200); +} + diff --git a/unittest/proxylib/TestProxy.cpp b/unittest/proxylib/TestProxy.cpp index 097b07a0..c17b8f0d 100644 --- a/unittest/proxylib/TestProxy.cpp +++ b/unittest/proxylib/TestProxy.cpp @@ -174,6 +174,16 @@ static void onTwampSessionEvent( ntfCounter++; } +static void onTamTelTypeConfigChange( + _In_ sai_object_id_t tam_tel_id) +{ + SWSS_LOG_ENTER(); + + SWSS_LOG_NOTICE("received: onTamTelTypeConfigChange"); + + ntfCounter++; +} + TEST(Proxy, notifications) { Sai sai; @@ -194,6 +204,7 @@ TEST(Proxy, notifications) EXPECT_EQ(dummy->enqueueNotificationToSend(SAI_SWITCH_ATTR_QUEUE_PFC_DEADLOCK_NOTIFY), SAI_STATUS_SUCCESS); EXPECT_EQ(dummy->enqueueNotificationToSend(SAI_SWITCH_ATTR_BFD_SESSION_STATE_CHANGE_NOTIFY), SAI_STATUS_SUCCESS); EXPECT_EQ(dummy->enqueueNotificationToSend(SAI_SWITCH_ATTR_TWAMP_SESSION_EVENT_NOTIFY), SAI_STATUS_SUCCESS); + EXPECT_EQ(dummy->enqueueNotificationToSend(SAI_SWITCH_ATTR_TAM_TEL_TYPE_CONFIG_CHANGE_NOTIFY), SAI_STATUS_SUCCESS); auto thread = std::make_shared(fun,proxy); @@ -257,6 +268,10 @@ TEST(Proxy, notifications) attr.value.ptr = (void*)&onTwampSessionEvent; sai.set(SAI_OBJECT_TYPE_SWITCH, switch_id, &attr); + attr.id = SAI_SWITCH_ATTR_TAM_TEL_TYPE_CONFIG_CHANGE_NOTIFY; + attr.value.ptr = (void*)&onTamTelTypeConfigChange; + sai.set(SAI_OBJECT_TYPE_SWITCH, switch_id, &attr); + // dummy start sending notifications EXPECT_EQ(dummy->start(), SAI_STATUS_SUCCESS); @@ -265,7 +280,7 @@ TEST(Proxy, notifications) // dummy stop sending notifications EXPECT_EQ(dummy->stop(), SAI_STATUS_SUCCESS); - EXPECT_EQ(proxy->getNotificationsSentCount(), 4+6); + EXPECT_EQ(proxy->getNotificationsSentCount(), 4+6+1); proxy->stop(); diff --git a/unittest/proxylib/TestSai.cpp b/unittest/proxylib/TestSai.cpp index 80f89b08..23e1f8df 100644 --- a/unittest/proxylib/TestSai.cpp +++ b/unittest/proxylib/TestSai.cpp @@ -716,6 +716,16 @@ static void onTwampSessionEvent( ntfCounter++; } +static void onTamTelTypeConfigChange( + _In_ sai_object_id_t tam_tel_id) +{ + SWSS_LOG_ENTER(); + + SWSS_LOG_NOTICE("received: onTamTelTypeConfigChange"); + + ntfCounter++; +} + TEST(Sai, handleNotification) { Sai sai; @@ -736,6 +746,7 @@ TEST(Sai, handleNotification) EXPECT_EQ(dummy->enqueueNotificationToSend(SAI_SWITCH_ATTR_QUEUE_PFC_DEADLOCK_NOTIFY), SAI_STATUS_SUCCESS); EXPECT_EQ(dummy->enqueueNotificationToSend(SAI_SWITCH_ATTR_BFD_SESSION_STATE_CHANGE_NOTIFY), SAI_STATUS_SUCCESS); EXPECT_EQ(dummy->enqueueNotificationToSend(SAI_SWITCH_ATTR_TWAMP_SESSION_EVENT_NOTIFY), SAI_STATUS_SUCCESS); + EXPECT_EQ(dummy->enqueueNotificationToSend(SAI_SWITCH_ATTR_TAM_TEL_TYPE_CONFIG_CHANGE_NOTIFY), SAI_STATUS_SUCCESS); auto thread = std::make_shared(fun, proxy); @@ -799,6 +810,10 @@ TEST(Sai, handleNotification) attr.value.ptr = (void*)&onTwampSessionEvent; sai.set(SAI_OBJECT_TYPE_SWITCH, switch_id, &attr); + attr.id = SAI_SWITCH_ATTR_TAM_TEL_TYPE_CONFIG_CHANGE_NOTIFY; + attr.value.ptr = (void*)&onTamTelTypeConfigChange; + sai.set(SAI_OBJECT_TYPE_SWITCH, switch_id, &attr); + // dummy start sending notifications EXPECT_EQ(dummy->start(), SAI_STATUS_SUCCESS); @@ -807,10 +822,10 @@ TEST(Sai, handleNotification) // dummy stop sending notifications EXPECT_EQ(dummy->stop(), SAI_STATUS_SUCCESS); - EXPECT_EQ(proxy->getNotificationsSentCount(), 10); + EXPECT_EQ(proxy->getNotificationsSentCount(), 11); // important check, whether Sai class processed notifications correctly - EXPECT_EQ(ntfCounter, 10); + EXPECT_EQ(ntfCounter, 11); proxy->stop(); diff --git a/unittest/syncd/TestSyncd.cpp b/unittest/syncd/TestSyncd.cpp index ead13f21..22fa5618 100644 --- a/unittest/syncd/TestSyncd.cpp +++ b/unittest/syncd/TestSyncd.cpp @@ -321,6 +321,43 @@ TEST_F(SyncdTest, processStatsCapabilityQuery) syncd_object.processEvent(consumer); } +TEST_F(SyncdTest, processStatsStCapabilityQuery) +{ + auto sai = std::make_shared(); + auto opt = std::make_shared(); + opt->m_enableTempView = true; + opt->m_startType = SAI_START_TYPE_FASTFAST_BOOT; + syncd::Syncd syncd_object(sai, opt, false); + + auto translator = syncd_object.m_translator; + translator->insertRidAndVid(0x11000000000000, 0x21000000000000); + + MockSelectableChannel consumer; + EXPECT_CALL(consumer, empty()).WillOnce(testing::Return(true)); + EXPECT_CALL(consumer, pop(testing::_, testing::_)) + .Times(1) + .WillRepeatedly(testing::Invoke([](swss::KeyOpFieldsValuesTuple &kco, bool initViewMode) + { + static int callCount = 0; + if (callCount == 0) + { + kfvKey(kco) = "oid:0x21000000000000"; + kfvOp(kco) = REDIS_ASIC_STATE_COMMAND_STATS_ST_CAPABILITY_QUERY; + kfvFieldsValues(kco) = { + std::make_pair("OBJECT_TYPE", "SAI_OBJECT_TYPE_QUEUE"), + std::make_pair("LIST_SIZE", "1") + }; + } + else + { + kfvKey(kco) = ""; + kfvOp(kco) = ""; + kfvFieldsValues(kco).clear(); + } + ++callCount; })); + syncd_object.processEvent(consumer); +} + TEST_F(SyncdTest, BulkCreateTest) { m_opt->m_enableSaiBulkSupport = true; diff --git a/unittest/vslib/Makefile.am b/unittest/vslib/Makefile.am index 092bcf04..ed1052a0 100644 --- a/unittest/vslib/Makefile.am +++ b/unittest/vslib/Makefile.am @@ -46,7 +46,8 @@ tests_SOURCES = main.cpp \ TestMACsecManager.cpp \ TestSwitchStateBase.cpp \ TestSai.cpp \ - TestVirtualSwitchSaiInterface.cpp + TestVirtualSwitchSaiInterface.cpp \ + TestTAM.cpp tests_CXXFLAGS = $(DBGFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS_COMMON) -fno-access-control tests_LDADD = $(LDADD_GTEST) $(top_srcdir)/vslib/libSaiVS.a -lhiredis -lswsscommon -lnl-genl-3 -lnl-nf-3 -lnl-route-3 -lnl-3 \ diff --git a/unittest/vslib/TestSwitchStateBase.cpp b/unittest/vslib/TestSwitchStateBase.cpp index 9979675c..fee5b09e 100644 --- a/unittest/vslib/TestSwitchStateBase.cpp +++ b/unittest/vslib/TestSwitchStateBase.cpp @@ -305,3 +305,30 @@ TEST(SwitchStateBase, initialize_voq_switch) EXPECT_EQ(SAI_STATUS_SUCCESS, ss.initialize_voq_switch_objects((uint32_t)attrs.size(), attrs.data())); } + +TEST(SwitchStateBase, query_stats_st_capability) +{ + auto sc = std::make_shared(0, ""); + auto scc = std::make_shared(); + + SwitchStateBase ss( + 0x2100000000, + std::make_shared(0, scc), + sc); + + sai_stat_st_capability_list_t stats_capability; + std::vector buffer; + buffer.resize(96); + stats_capability.count = static_cast(buffer.size()); + stats_capability.list = buffer.data(); + + EXPECT_EQ(SAI_STATUS_SUCCESS, + ss.queryStatsStCapability(0, + SAI_OBJECT_TYPE_PORT, + &stats_capability)); + + EXPECT_EQ(SAI_STATUS_SUCCESS, + static_cast(ss).queryStatsStCapability(0, + SAI_OBJECT_TYPE_PORT, + &stats_capability)); +} diff --git a/unittest/vslib/TestTAM.cpp b/unittest/vslib/TestTAM.cpp new file mode 100644 index 00000000..9da223cc --- /dev/null +++ b/unittest/vslib/TestTAM.cpp @@ -0,0 +1,68 @@ +#include +#include +#include + +#include + +#include + +using namespace saivs; +using namespace std; + +static sai_object_id_t notified_tam_tel_type_id = SAI_NULL_OBJECT_ID; + +static void notify_tam_tel_type_config_change( + _In_ sai_object_id_t tam_tel_type_id) +{ + SWSS_LOG_ENTER(); + + notified_tam_tel_type_id = tam_tel_type_id; +} + +TEST(TAM, TAMTelTypeConfigNotification) +{ + vector attrs; + sai_attribute_t attr; + sai_object_id_t switch_id = 0x2100000000; + auto signal = std::make_shared(); + auto eventQueue = std::make_shared(signal); + auto sc = make_shared(0, ""); + sc->m_eventQueue = eventQueue; + auto scc = make_shared(); + SwitchStateBase ss( + switch_id, + make_shared(0, scc), + sc); + + sai_object_id_t tam_tel_type_id = 0x4b000000000001; + string tam_tel_type_id_str = sai_serialize_object_id(tam_tel_type_id); + + attrs.clear(); + attr.id = SAI_SWITCH_ATTR_TAM_TEL_TYPE_CONFIG_CHANGE_NOTIFY; + attr.value.ptr = reinterpret_cast(notify_tam_tel_type_config_change); + attrs.push_back(attr); + + EXPECT_EQ( + SAI_STATUS_SUCCESS, + ss.create(SAI_OBJECT_TYPE_SWITCH, sai_serialize_object_id(switch_id), 0, static_cast(attrs.size()), attrs.data())); + + EXPECT_EQ( + SAI_STATUS_SUCCESS, + ss.create(SAI_OBJECT_TYPE_TAM_TEL_TYPE, tam_tel_type_id_str, switch_id, 0, nullptr)); + + attr.id = SAI_TAM_TEL_TYPE_ATTR_STATE; + attr.value.s32 = SAI_TAM_TEL_TYPE_STATE_CREATE_CONFIG; + + EXPECT_EQ( + SAI_STATUS_SUCCESS, + ss.set(SAI_OBJECT_TYPE_TAM_TEL_TYPE, tam_tel_type_id_str, &attr)); + + auto event = eventQueue->dequeue(); + EXPECT_EQ(event->getType(), EventType::EVENT_TYPE_NOTIFICATION); + auto payload = dynamic_pointer_cast(event->getPayload()); + + auto switchNotifications = payload->getSwitchNotifications(); + auto ntf = payload->getNotification(); + ntf->executeCallback(switchNotifications); + EXPECT_EQ(notified_tam_tel_type_id, tam_tel_type_id); +} diff --git a/unittest/vslib/TestVirtualSwitchSaiInterface.cpp b/unittest/vslib/TestVirtualSwitchSaiInterface.cpp index 52d1afde..8112b7e0 100644 --- a/unittest/vslib/TestVirtualSwitchSaiInterface.cpp +++ b/unittest/vslib/TestVirtualSwitchSaiInterface.cpp @@ -203,3 +203,41 @@ TEST_F(VirtualSwitchSaiInterfaceTest, queryStatsCapability) &stats_capability)); } +TEST_F(VirtualSwitchSaiInterfaceTest, queryStatsStCapability) +{ + sai_stat_st_capability_t capability_list[91]; + sai_stat_st_capability_list_t stats_capability; + stats_capability.list = capability_list; + + /* Queue stats capability get */ + stats_capability.count = 1; + + EXPECT_EQ(SAI_STATUS_BUFFER_OVERFLOW, + m_vssai->queryStatsStCapability( + m_swid, + SAI_OBJECT_TYPE_QUEUE, + &stats_capability)); + + EXPECT_EQ(SAI_STATUS_SUCCESS, + m_vssai->queryStatsStCapability( + m_swid, + SAI_OBJECT_TYPE_QUEUE, + &stats_capability)); + + /* Port stats capability get */ + stats_capability.count = 1; + + EXPECT_EQ(SAI_STATUS_BUFFER_OVERFLOW, + m_vssai->queryStatsStCapability( + m_swid, + SAI_OBJECT_TYPE_PORT, + &stats_capability)); + + stats_capability.count = 91; + EXPECT_EQ(SAI_STATUS_SUCCESS, + m_vssai->queryStatsStCapability( + m_swid, + SAI_OBJECT_TYPE_PORT, + &stats_capability)); + EXPECT_EQ(stats_capability.list[0].minimal_polling_interval, static_cast(1e6 * 100)); +} diff --git a/vslib/SwitchState.cpp b/vslib/SwitchState.cpp index 886c8a2f..478c7be0 100644 --- a/vslib/SwitchState.cpp +++ b/vslib/SwitchState.cpp @@ -392,6 +392,36 @@ sai_status_t SwitchState::queryStatsCapability( return SAI_STATUS_SUCCESS; } +sai_status_t SwitchState::queryStatsStCapability( + _In_ sai_object_id_t switchId, + _In_ sai_object_type_t objectType, + _Inout_ sai_stat_st_capability_list_t *stats_capability) +{ + SWSS_LOG_ENTER(); + + auto info = sai_metadata_get_object_type_info(objectType); + + if (stats_capability->count == 0 || stats_capability->list == nullptr) + { + stats_capability->count = (uint32_t)info->statenum->valuescount; + return SAI_STATUS_BUFFER_OVERFLOW; + } + + SWSS_LOG_NOTICE("query counter st capability for object ID %s of counter type %s", + sai_serialize_object_id(switchId).c_str(), + info->statenum->name); + + auto statenumlist = info->statenum->values; + + for (uint32_t i = 0; i < stats_capability->count; i++) + { + stats_capability->list[i].capability.stat_enum = statenumlist[i]; + stats_capability->list[i].capability.stat_modes = SAI_STATS_MODE_READ_AND_CLEAR; + stats_capability->list[i].minimal_polling_interval = static_cast(1e6 * 100); + } + return SAI_STATUS_SUCCESS; +} + std::shared_ptr SwitchState::getMeta() { SWSS_LOG_ENTER(); diff --git a/vslib/SwitchStateBase.cpp b/vslib/SwitchStateBase.cpp index e21c9e99..2287bbb7 100644 --- a/vslib/SwitchStateBase.cpp +++ b/vslib/SwitchStateBase.cpp @@ -2,6 +2,8 @@ #include "swss/logger.h" #include "meta/sai_serialize.h" +#include "meta/NotificationTamTelTypeConfigChange.h" +#include "EventPayloadNotification.h" #include #include @@ -501,6 +503,22 @@ sai_status_t SwitchStateBase::setAclEntry( return set_internal(SAI_OBJECT_TYPE_ACL_ENTRY, sid, attr); } +sai_status_t SwitchStateBase::setTamTelType( + _In_ sai_object_id_t tam_tel_type_id, + _In_ const sai_attribute_t *attr) +{ + SWSS_LOG_ENTER(); + + if (attr->id == SAI_TAM_TEL_TYPE_ATTR_STATE && attr->value.s32 == SAI_TAM_TEL_TYPE_STATE_CREATE_CONFIG) + { + send_tam_tel_type_config_change(tam_tel_type_id); + } + + auto sid = sai_serialize_object_id(tam_tel_type_id); + + return set_internal(SAI_OBJECT_TYPE_TAM_TEL_TYPE, sid, attr); +} + sai_status_t SwitchStateBase::set( _In_ sai_object_type_t objectType, _In_ const std::string &serializedObjectId, @@ -529,6 +547,13 @@ sai_status_t SwitchStateBase::set( return setMACsecSA(objectId, attr); } + if (objectType == SAI_OBJECT_TYPE_TAM_TEL_TYPE) + { + sai_object_id_t objectId; + sai_deserialize_object_id(serializedObjectId, objectId); + return setTamTelType(objectId, attr); + } + return set_internal(objectType, serializedObjectId, attr); } @@ -1011,6 +1036,10 @@ sai_status_t SwitchStateBase::set_switch_default_attributes() CHECK_STATUS(set(SAI_OBJECT_TYPE_SWITCH, m_switch_id, &attr)); + attr.id = SAI_SWITCH_ATTR_TAM_TEL_TYPE_CONFIG_CHANGE_NOTIFY; + + CHECK_STATUS(set(SAI_OBJECT_TYPE_SWITCH, m_switch_id, &attr)); + attr.id = SAI_SWITCH_ATTR_FDB_AGING_TIME; attr.value.u32 = 0; @@ -4166,11 +4195,77 @@ sai_status_t SwitchStateBase::queryStatsCapability( sai_status_t SwitchStateBase::queryStatsStCapability( _In_ sai_object_id_t switchId, _In_ sai_object_type_t objectType, - _Inout_ sai_stat_st_capability_list_t *stats_capability) + _Inout_ sai_stat_st_capability_list_t *stats_st_capability) { SWSS_LOG_ENTER(); - // TODO: Fix me + sai_stat_capability_list_t stats_capability; + std::vector stats_list(stats_st_capability->count); + stats_capability.count = stats_st_capability->count; + stats_capability.list = stats_list.data(); - return SAI_STATUS_NOT_IMPLEMENTED; + sai_status_t status = queryStatsCapability( + switchId, + objectType, + &stats_capability); + + if (status == SAI_STATUS_SUCCESS) + { + for (uint32_t i = 0; i < stats_capability.count; i++) + { + stats_st_capability->list[i].capability.stat_enum = stats_capability.list[i].stat_enum; + stats_st_capability->list[i].capability.stat_modes = stats_capability.list[i].stat_modes; + stats_st_capability->list[i].minimal_polling_interval = static_cast(1e6 * 100); + ; // 100ms + } + } + else + { + SWSS_LOG_WARN("Failed to query stats capability for object type %s, status: %s", + sai_serialize_object_type(objectType).c_str(), + sai_serialize_status(status).c_str()); + } + + return status; +} + +void SwitchStateBase::send_tam_tel_type_config_change( + _In_ sai_object_id_t tam_tel_type_id) +{ + SWSS_LOG_ENTER(); + + auto meta = getMeta(); + + if (meta) + { + meta->meta_sai_on_tam_tel_type_config_change(tam_tel_type_id); + } + + sai_attribute_t attr; + + attr.id = SAI_SWITCH_ATTR_TAM_TEL_TYPE_CONFIG_CHANGE_NOTIFY; + + sai_status_t status = get(SAI_OBJECT_TYPE_SWITCH, m_switch_id, 1, &attr); + + if (status != SAI_STATUS_SUCCESS) + { + SWSS_LOG_ERROR("unable to get SAI_SWITCH_ATTR_TAM_TEL_TYPE_CONFIG_CHANGE_NOTIFY attribute for %s", + sai_serialize_object_id(m_switch_id).c_str()); + + return; + } + + auto str = sai_serialize_object_id(tam_tel_type_id); + + sai_switch_notifications_t sn = {}; + + sn.on_tam_tel_type_config_change = (sai_tam_tel_type_config_change_notification_fn)attr.value.ptr; + + SWSS_LOG_INFO("send event SAI_SWITCH_ATTR_TAM_TEL_TYPE_CONFIG_CHANGE_NOTIFY %s", str.c_str()); + + auto ntf = std::make_shared(str); + + auto payload = std::make_shared(ntf, sn); + + m_switchConfig->m_eventQueue->enqueue(std::make_shared(EVENT_TYPE_NOTIFICATION, payload)); } diff --git a/vslib/SwitchStateBase.h b/vslib/SwitchStateBase.h index 167952e6..ac0a3400 100644 --- a/vslib/SwitchStateBase.h +++ b/vslib/SwitchStateBase.h @@ -543,6 +543,11 @@ namespace saivs void send_fdb_event_notification( _In_ const sai_fdb_event_notification_data_t& data); + public: // Telemetry and Monitor + + void send_tam_tel_type_config_change( + _In_ sai_object_id_t tam_tel_type_id); + protected: void findObjects( @@ -568,11 +573,15 @@ namespace saivs _In_ sai_object_id_t macsec_sa_id, _In_ const sai_attribute_t* attr); + sai_status_t setTamTelType( + _In_ sai_object_id_t tam_tel_type_id, + _In_ const sai_attribute_t *attr); + sai_status_t createMACsecPort( - _In_ sai_object_id_t macsec_sa_id, - _In_ sai_object_id_t switch_id, - _In_ uint32_t attr_count, - _In_ const sai_attribute_t *attr_list); + _In_ sai_object_id_t macsec_sa_id, + _In_ sai_object_id_t switch_id, + _In_ uint32_t attr_count, + _In_ const sai_attribute_t *attr_list); sai_status_t createMACsecSA( _In_ sai_object_id_t macsec_sa_id, diff --git a/vslib/VirtualSwitchSaiInterface.cpp b/vslib/VirtualSwitchSaiInterface.cpp index e0c568dc..462fe6dc 100644 --- a/vslib/VirtualSwitchSaiInterface.cpp +++ b/vslib/VirtualSwitchSaiInterface.cpp @@ -999,13 +999,45 @@ sai_status_t VirtualSwitchSaiInterface::queryStatsCapability( sai_status_t VirtualSwitchSaiInterface::queryStatsStCapability( _In_ sai_object_id_t switchId, _In_ sai_object_type_t objectType, - _Inout_ sai_stat_st_capability_list_t *stats_capability) + _Inout_ sai_stat_st_capability_list_t *stats_st_capability) { SWSS_LOG_ENTER(); - // TODO: Fix me + sai_stat_capability_list_t stats_capability; + std::vector stats_list(stats_st_capability->count); + stats_capability.count = stats_st_capability->count; + stats_capability.list = stats_list.data(); - return SAI_STATUS_NOT_IMPLEMENTED; + sai_status_t status = queryStatsCapability( + switchId, + objectType, + &stats_capability); + + if (status == SAI_STATUS_SUCCESS) + { + stats_st_capability->count = stats_capability.count; + for (uint32_t i = 0; i < stats_capability.count; i++) + { + stats_st_capability->list[i].capability.stat_enum = stats_capability.list[i].stat_enum; + stats_st_capability->list[i].capability.stat_modes = stats_capability.list[i].stat_modes; + stats_st_capability->list[i].minimal_polling_interval = static_cast(1e6 * 100); // 100ms + } + } + else if (status == SAI_STATUS_BUFFER_OVERFLOW) + { + stats_st_capability->count = stats_capability.count; + SWSS_LOG_WARN("Buffer overflow for object type %s, count: %u", + sai_serialize_object_type(objectType).c_str(), + stats_st_capability->count); + } + else + { + SWSS_LOG_WARN("Failed to query stats capability for object type %s, status: %s", + sai_serialize_object_type(objectType).c_str(), + sai_serialize_status(status).c_str()); + } + + return status; } sai_status_t VirtualSwitchSaiInterface::getStatsExt( From 9c417d18e54fdbf789ea54b21ddf8d08574afeb4 Mon Sep 17 00:00:00 2001 From: Ze Gan Date: Thu, 19 Jun 2025 00:44:05 +0000 Subject: [PATCH 2/2] Fix conflict Signed-off-by: Ze Gan --- lib/ClientSai.cpp | 23 ----------------------- lib/RedisRemoteSaiInterface.cpp | 12 ------------ 2 files changed, 35 deletions(-) diff --git a/lib/ClientSai.cpp b/lib/ClientSai.cpp index be0e13af..aff4265c 100644 --- a/lib/ClientSai.cpp +++ b/lib/ClientSai.cpp @@ -1060,29 +1060,6 @@ sai_status_t ClientSai::queryStatsCapability( return waitForQueryStatsCapabilityResponse(stats_capability); } -sai_status_t ClientSai::queryStatsStCapability( - _In_ sai_object_id_t switchId, - _In_ sai_object_type_t objectType, - _Inout_ sai_stat_st_capability_list_t *stats_capability) -{ - MUTEX(); - SWSS_LOG_ENTER(); - REDIS_CHECK_API_INITIALIZED(); - - auto switchIdStr = sai_serialize_object_id(switchId); - auto objectTypeStr = sai_serialize_object_type(objectType); - - if (stats_capability == NULL) - { - SWSS_LOG_ERROR("Failed to find stats-capability: switch %s object type %s", switchIdStr.c_str(), objectTypeStr.c_str()); - return SAI_STATUS_INVALID_PARAMETER; - } - - // TODO: Fix me - - return SAI_STATUS_NOT_IMPLEMENTED; -} - sai_status_t ClientSai::waitForQueryStatsCapabilityResponse( _Inout_ sai_stat_capability_list_t* stats_capability) { diff --git a/lib/RedisRemoteSaiInterface.cpp b/lib/RedisRemoteSaiInterface.cpp index e20a3bf1..ed8b3eb5 100644 --- a/lib/RedisRemoteSaiInterface.cpp +++ b/lib/RedisRemoteSaiInterface.cpp @@ -1443,18 +1443,6 @@ sai_status_t RedisRemoteSaiInterface::queryStatsCapability( return status; } -sai_status_t RedisRemoteSaiInterface::queryStatsStCapability( - _In_ sai_object_id_t switchId, - _In_ sai_object_type_t objectType, - _Inout_ sai_stat_st_capability_list_t *stats_capability) -{ - SWSS_LOG_ENTER(); - - // TODO: Fix me - - return SAI_STATUS_NOT_IMPLEMENTED; -} - sai_status_t RedisRemoteSaiInterface::waitForQueryStatsCapabilityResponse( _Inout_ sai_stat_capability_list_t* stats_capability) {