diff --git a/.github/workflows/codeql-analysis.yml b/.github/workflows/codeql-analysis.yml index adabaf91..26ea176e 100644 --- a/.github/workflows/codeql-analysis.yml +++ b/.github/workflows/codeql-analysis.yml @@ -16,7 +16,7 @@ on: jobs: analyze: name: Analyze - runs-on: ubuntu-20.04 + runs-on: ubuntu-22.04 permissions: actions: read contents: read @@ -55,11 +55,11 @@ jobs: libzmq3-dev \ libzmq5 \ swig4.0 \ - libpython2.7-dev \ + libpython3-dev \ libgtest-dev \ libgmock-dev \ - libboost1.71-dev \ - libboost-serialization1.71-dev \ + libboost-dev \ + libboost-serialization-dev \ dh-exec \ doxygen \ cdbs \ @@ -69,8 +69,7 @@ jobs: autoconf-archive \ uuid-dev \ libjansson-dev \ - nlohmann-json3-dev \ - python + nlohmann-json3-dev - if: matrix.language == 'cpp' name: Build sonic-swss-common @@ -79,7 +78,7 @@ jobs: git clone https://github.com/sonic-net/sonic-swss-common pushd sonic-swss-common ./autogen.sh - dpkg-buildpackage -rfakeroot -us -uc -b -j$(nproc) + dpkg-buildpackage -rfakeroot -us -uc -b -Pnoyangmod,nopython2 -j$(nproc) popd dpkg-deb -x libswsscommon_${SWSSCOMMON_VER}_amd64.deb $(dirname $GITHUB_WORKSPACE) dpkg-deb -x libswsscommon-dev_${SWSSCOMMON_VER}_amd64.deb $(dirname $GITHUB_WORKSPACE) diff --git a/.gitmodules b/.gitmodules index 1d075ba3..27a133e7 100644 --- a/.gitmodules +++ b/.gitmodules @@ -2,4 +2,4 @@ path = SAI url = https://github.com/opencomputeproject/SAI.git ignore = dirty - branch = v1.3 + branch = v1.16 diff --git a/SAI b/SAI index 7fac67d3..23d8579c 160000 --- a/SAI +++ b/SAI @@ -1 +1 @@ -Subproject commit 7fac67d39c44d7c0607bb91fb78a6d08a36000c1 +Subproject commit 23d8579cd02327b6cc99df174a72395b8fa3af64 diff --git a/configure.ac b/configure.ac index 73640684..63e07d59 100644 --- a/configure.ac +++ b/configure.ac @@ -267,11 +267,20 @@ AC_MSG_ERROR("SAI headers API version and library version mismatch")])], CXXFLAGS="$SAVED_FLAGS" ])]) -AM_COND_IF([SYNCD], [ -SAVED_FLAGS="$CXXFLAGS" -CXXFLAGS="-Xlinker --no-as-needed -lsai -I$srcdir/SAI/inc -I$srcdir/SAI/experimental -I$srcdir/SAI/meta" -AC_CHECK_FUNCS(sai_bulk_object_clear_stats sai_bulk_object_get_stats) -CXXFLAGS="$SAVED_FLAGS" +AM_COND_IF([SAIVS], +[ + AC_DEFINE([HAVE_SAI_BULK_OBJECT_CLEAR_STATS], [1], []) + AC_DEFINE([HAVE_SAI_BULK_OBJECT_GET_STATS], [1], []) + AC_DEFINE([HAVE_SAI_QUERY_STATS_ST_CAPABILITY], [1], []) + AC_DEFINE([HAVE_SAI_TAM_TELEMETRY_GET_DATA], [1], []) +], +[ + AM_COND_IF([SYNCD], [ + SAVED_FLAGS="$CXXFLAGS" + CXXFLAGS="-Xlinker --no-as-needed -lsai -I$srcdir/SAI/inc -I$srcdir/SAI/experimental -I$srcdir/SAI/meta" + AC_CHECK_FUNCS(sai_bulk_object_clear_stats sai_bulk_object_get_stats sai_query_stats_st_capability sai_tam_telemetry_get_data) + CXXFLAGS="$SAVED_FLAGS" + ]) ]) AC_DEFINE([SAIREDIS_GIT_REVISION], diff --git a/lib/ClientSai.cpp b/lib/ClientSai.cpp index 39da35e3..aff4265c 100644 --- a/lib/ClientSai.cpp +++ b/lib/ClientSai.cpp @@ -1060,6 +1060,58 @@ sai_status_t ClientSai::queryStatsCapability( return waitForQueryStatsCapabilityResponse(stats_capability); } +sai_status_t ClientSai::waitForQueryStatsCapabilityResponse( + _Inout_ sai_stat_capability_list_t* stats_capability) +{ + SWSS_LOG_ENTER(); + + swss::KeyOpFieldsValuesTuple kco; + + auto status = m_communicationChannel->wait(REDIS_ASIC_STATE_COMMAND_STATS_CAPABILITY_RESPONSE, kco); + + if (status == SAI_STATUS_SUCCESS) + { + const std::vector &values = kfvFieldsValues(kco); + + if (values.size() != 3) + { + SWSS_LOG_ERROR("Invalid response from syncd: expected 3 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 uint32_t num_capabilities = std::stoi(fvValue(values[2])); + + SWSS_LOG_DEBUG("Received payload: stat_enums = '%s', stat_modes = '%s', count = %d", + stat_enum_str.c_str(), stat_modes_str.c_str(), num_capabilities); + + stats_capability->count = num_capabilities; + + sai_deserialize_stats_capability_list(stats_capability, stat_enum_str, stat_modes_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::queryStatsStCapability( _In_ sai_object_id_t switchId, _In_ sai_object_type_t objectType, @@ -1078,43 +1130,71 @@ sai_status_t ClientSai::queryStatsStCapability( return SAI_STATUS_INVALID_PARAMETER; } - // TODO: Fix me + 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; + } + } - return SAI_STATUS_NOT_IMPLEMENTED; + 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::waitForQueryStatsCapabilityResponse( - _Inout_ sai_stat_capability_list_t* 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_CAPABILITY_RESPONSE, 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() != 3) + if (values.size() != 4) { - SWSS_LOG_ERROR("Invalid response from syncd: expected 3 value, received %zu", values.size()); + 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 uint32_t num_capabilities = std::stoi(fvValue(values[2])); + 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', count = %d", - stat_enum_str.c_str(), stat_modes_str.c_str(), num_capabilities); + 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_capability_list(stats_capability, stat_enum_str, stat_modes_str); + sai_deserialize_stats_st_capability_list(stats_capability, stat_enum_str, stat_modes_str, polling_interval_str); } - else if (status == SAI_STATUS_BUFFER_OVERFLOW) + else if (status == SAI_STATUS_BUFFER_OVERFLOW) { const std::vector &values = kfvFieldsValues(kco); 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..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) { @@ -1507,6 +1495,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 8bf8c791..2e979fae 100644 --- a/meta/Meta.cpp +++ b/meta/Meta.cpp @@ -8,11 +8,13 @@ #include +#include + #include // TODO add validation for all oids belong to the same switch -#define MAX_LIST_COUNT 0x1000 +#define MAX_LIST_COUNT (0x1<<24) // 16M #define CHECK_STATUS_SUCCESS(s) { if ((s) != SAI_STATUS_SUCCESS) return (s); } @@ -3093,6 +3095,25 @@ sai_status_t Meta::meta_sai_validate_pa_validation_entry( return SAI_STATUS_SUCCESS; } +sai_status_t Meta::meta_sai_validate_outbound_port_map_port_range_entry( + _In_ const sai_outbound_port_map_port_range_entry_t* outbound_port_map_entry, + _In_ bool create, + _In_ bool get) +{ + SWSS_LOG_ENTER(); + + if (outbound_port_map_entry == NULL) + { + SWSS_LOG_ERROR("outbound_port_map_entry pointer is NULL"); + + return SAI_STATUS_INVALID_PARAMETER; + } + + // TODO FIX ME + + return SAI_STATUS_NOT_IMPLEMENTED; +} + sai_status_t Meta::meta_sai_validate_outbound_routing_entry( _In_ const sai_outbound_routing_entry_t* outbound_routing_entry, _In_ bool create, @@ -3139,6 +3160,44 @@ sai_status_t Meta::meta_sai_validate_outbound_routing_entry( return SAI_STATUS_SUCCESS; } +sai_status_t Meta::meta_sai_validate_global_trusted_vni_entry( + _In_ const sai_global_trusted_vni_entry_t* global_trusted_vni_entry, + _In_ bool create, + _In_ bool get) +{ + SWSS_LOG_ENTER(); + + if (global_trusted_vni_entry == NULL) + { + SWSS_LOG_ERROR("global_trusted_vni_entry pointer is NULL"); + + return SAI_STATUS_INVALID_PARAMETER; + } + + // TODO FIX ME + + return SAI_STATUS_NOT_IMPLEMENTED; +} + +sai_status_t Meta::meta_sai_validate_eni_trusted_vni_entry( + _In_ const sai_eni_trusted_vni_entry_t* eni_trusted_vni_entry, + _In_ bool create, + _In_ bool get) +{ + SWSS_LOG_ENTER(); + + if (eni_trusted_vni_entry == NULL) + { + SWSS_LOG_ERROR("eni_trusted_vni_entry pointer is NULL"); + + return SAI_STATUS_INVALID_PARAMETER; + } + + // TODO FIX ME + + return SAI_STATUS_NOT_IMPLEMENTED; +} + sai_status_t Meta::meta_sai_validate_outbound_ca_to_pa_entry( _In_ const sai_outbound_ca_to_pa_entry_t* outbound_ca_to_pa_entry, _In_ bool create, @@ -3223,6 +3282,25 @@ sai_status_t Meta::meta_sai_validate_meter_bucket_entry( return SAI_STATUS_NOT_IMPLEMENTED; } +sai_status_t Meta::meta_sai_validate_prefix_compression_entry( + _In_ const sai_prefix_compression_entry_t* prefix_compression_entry, + _In_ bool create, + _In_ bool get) +{ + SWSS_LOG_ENTER(); + + if (prefix_compression_entry == NULL) + { + SWSS_LOG_ERROR("prefix_compression_entry pointer is NULL"); + + return SAI_STATUS_INVALID_PARAMETER; + } + + // TODO FIX ME + + return SAI_STATUS_NOT_IMPLEMENTED; +} + sai_status_t Meta::meta_generic_validation_create( _In_ const sai_object_meta_key_t& meta_key, _In_ sai_object_id_t switch_id, @@ -6744,24 +6822,14 @@ void Meta::meta_sai_on_port_state_change_single( auto ot = objectTypeQuery(data.port_id); - bool valid = false; + bool valid = isPortObjectIdValid(ot); - switch (ot) + if (!valid) { - // TODO hardcoded types, must advance SAI repository commit to get metadata for this - case SAI_OBJECT_TYPE_PORT: - case SAI_OBJECT_TYPE_BRIDGE_PORT: - case SAI_OBJECT_TYPE_LAG: - - valid = true; - break; - - default: - - SWSS_LOG_ERROR("data.port_id %s has unexpected type: %s, expected PORT, BRIDGE_PORT or LAG", - sai_serialize_object_id(data.port_id).c_str(), - sai_serialize_object_type(ot).c_str()); - break; + SWSS_LOG_ERROR("data.port_id %s has unexpected type: %s, expected: %s", + sai_serialize_object_id(data.port_id).c_str(), + sai_serialize_object_type(ot).c_str(), + boost::algorithm::join(getValidPortObjectTypes(), ",").c_str()); } if (valid && !m_oids.objectReferenceExists(data.port_id)) @@ -7004,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 { @@ -7181,3 +7285,46 @@ void Meta::populate( } } } + +bool Meta::isPortObjectIdValid( + _In_ sai_object_type_t object_type) +{ + SWSS_LOG_ENTER(); + + auto members = sai_metadata_struct_members_sai_port_oper_status_notification_t; + + for (size_t i = 0; members[i]; i++) + { + auto* mb = members[i]; + + if (mb->membername != std::string("port_id")) + continue; + + for (size_t idx = 0; idx < mb->allowedobjecttypeslength; idx++) + { + if (mb->allowedobjecttypes[idx] == object_type) + return true; + } + + return false; + } + + SWSS_LOG_THROW("port_id member not found on sai_port_oper_status_notification"); +} + +std::vector Meta::getValidPortObjectTypes() +{ + SWSS_LOG_ENTER(); + + auto md = sai_metadata_enum_sai_object_type_t; + + std::vector v; + + for (size_t i = 0; i < md.valuescount; i++) + { + if (isPortObjectIdValid((sai_object_type_t)md.values[i])) + v.push_back(md.valuesshortnames[i]); + } + + return v; +} diff --git a/meta/Meta.h b/meta/Meta.h index a459e734..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, @@ -320,6 +322,11 @@ namespace saimeta static bool is_ipv6_mask_valid( _In_ const uint8_t* mask); + static bool isPortObjectIdValid( + _In_ sai_object_type_t object_type); + + static std::vector getValidPortObjectTypes(); + private: // unit tests helpers bool meta_unittests_get_and_erase_set_readonly_flag( @@ -544,11 +551,26 @@ namespace saimeta _In_ bool create, _In_ bool get = false); + sai_status_t meta_sai_validate_outbound_port_map_port_range_entry( + _In_ const sai_outbound_port_map_port_range_entry_t* outbound_port_map_entry, + _In_ bool create, + _In_ bool get = false); + sai_status_t meta_sai_validate_outbound_routing_entry( _In_ const sai_outbound_routing_entry_t* outbound_routing_entry, _In_ bool create, _In_ bool get = false); + sai_status_t meta_sai_validate_global_trusted_vni_entry( + _In_ const sai_global_trusted_vni_entry_t* global_trusted_vni_entry, + _In_ bool create, + _In_ bool get = false); + + sai_status_t meta_sai_validate_eni_trusted_vni_entry( + _In_ const sai_eni_trusted_vni_entry_t* eni_trusted_vni_entry, + _In_ bool create, + _In_ bool get = false); + sai_status_t meta_sai_validate_outbound_ca_to_pa_entry( _In_ const sai_outbound_ca_to_pa_entry_t* outbound_ca_to_pa_entry, _In_ bool create, @@ -564,6 +586,11 @@ namespace saimeta _In_ bool create, _In_ bool get = false); + sai_status_t meta_sai_validate_prefix_compression_entry( + _In_ const sai_prefix_compression_entry_t* prefix_compression_entry, + _In_ bool create, + _In_ bool get = false); + public: /* 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..7790a75c --- /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 m_tam_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/SaiInterface.cpp b/meta/SaiInterface.cpp index 3a95bc01..c91d0827 100644 --- a/meta/SaiInterface.cpp +++ b/meta/SaiInterface.cpp @@ -378,3 +378,20 @@ sai_status_t SaiInterface::clearStats( return SAI_STATUS_NOT_IMPLEMENTED; } + +std::shared_ptr SaiInterface::getOptions( + _In_ const std::string& key) +{ + SWSS_LOG_ENTER(); + + return m_optionsMap[key]; +} + +void SaiInterface::setOptions( + _In_ const std::string& key, + _In_ std::shared_ptr options) +{ + SWSS_LOG_ENTER(); + + m_optionsMap[key] = options; +} diff --git a/meta/SaiInterface.h b/meta/SaiInterface.h index 7d4420a4..487eda6e 100644 --- a/meta/SaiInterface.h +++ b/meta/SaiInterface.h @@ -5,6 +5,12 @@ extern "C" { #include "saimetadata.h" } +#include "SaiOptions.h" + +#include +#include +#include + #define SAIREDIS_DECLARE_EVERY_ENTRY(_X) \ SAI_METADATA_DECLARE_EVERY_ENTRY(_X) @@ -345,5 +351,18 @@ namespace sairedis virtual sai_log_level_t logGet( _In_ sai_api_t api); + + public: // non SAI API - options helper + + std::shared_ptr getOptions( + _In_ const std::string& key); + + void setOptions( + _In_ const std::string& key, + _In_ std::shared_ptr options); + + private: + + std::map> m_optionsMap; }; } diff --git a/meta/SaiOptions.h b/meta/SaiOptions.h new file mode 100644 index 00000000..2d053c6c --- /dev/null +++ b/meta/SaiOptions.h @@ -0,0 +1,11 @@ +#pragma once + +namespace sairedis +{ + class SaiOptions + { + public: + + virtual ~SaiOptions() = default; + }; +} diff --git a/meta/SaiSerialize.cpp b/meta/SaiSerialize.cpp index 608bd3fd..6b54ed58 100644 --- a/meta/SaiSerialize.cpp +++ b/meta/SaiSerialize.cpp @@ -975,6 +975,20 @@ std::string sai_serialize_meter_bucket_entry( return j.dump(); } +std::string sai_serialize_prefix_compression_entry( + _In_ const sai_prefix_compression_entry_t &prefix_compression_entry) +{ + SWSS_LOG_ENTER(); + + json j; + + j["switch_id"] = sai_serialize_object_id(prefix_compression_entry.switch_id); + j["prefix_table_id"] = sai_serialize_object_id(prefix_compression_entry.prefix_table_id); + j["prefix"] = sai_serialize_ip_prefix(prefix_compression_entry.prefix); + + return j.dump(); +} + std::string sai_serialize_flow_entry( _In_ const sai_flow_entry_t &flow_entry) { @@ -1871,6 +1885,20 @@ std::string sai_serialize_pa_validation_entry( return j.dump(); } +std::string sai_serialize_outbound_port_map_port_range_entry( + _In_ const sai_outbound_port_map_port_range_entry_t &outbound_port_map_entry) +{ + SWSS_LOG_ENTER(); + + json j; + + j["switch_id"] = sai_serialize_object_id(outbound_port_map_entry.switch_id); + j["outbound_port_map_id"] = sai_serialize_object_id(outbound_port_map_entry.outbound_port_map_id); + j["dst_port_range"] = sai_serialize_range(outbound_port_map_entry.dst_port_range); + + return j.dump(); +} + std::string sai_serialize_outbound_routing_entry( _In_ const sai_outbound_routing_entry_t &outbound_routing_entry) { @@ -1885,6 +1913,33 @@ std::string sai_serialize_outbound_routing_entry( return j.dump(); } +std::string sai_serialize_global_trusted_vni_entry( + _In_ const sai_global_trusted_vni_entry_t &global_trusted_vni_entry) +{ + SWSS_LOG_ENTER(); + + json j; + + j["switch_id"] = sai_serialize_object_id(global_trusted_vni_entry.switch_id); + j["vni_range"] = sai_serialize_range(global_trusted_vni_entry.vni_range); + + return j.dump(); +} + +std::string sai_serialize_eni_trusted_vni_entry( + _In_ const sai_eni_trusted_vni_entry_t &eni_trusted_vni_entry) +{ + SWSS_LOG_ENTER(); + + json j; + + j["switch_id"] = sai_serialize_object_id(eni_trusted_vni_entry.switch_id); + j["eni_id"] = sai_serialize_object_id(eni_trusted_vni_entry.eni_id); + j["vni_range"] = sai_serialize_range(eni_trusted_vni_entry.vni_range); + + return j.dump(); +} + std::string sai_serialize_outbound_ca_to_pa_entry( _In_ const sai_outbound_ca_to_pa_entry_t &outbound_ca_to_pa_entry) { @@ -2678,6 +2733,10 @@ static bool sai_serialize_object_entry( key = sai_serialize_mcast_fdb_entry(key_entry.mcast_fdb_entry); return true; + case SAI_OBJECT_TYPE_PREFIX_COMPRESSION_ENTRY: + key = sai_serialize_prefix_compression_entry(key_entry.prefix_compression_entry); + return true; + default: return false; } @@ -2920,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) { @@ -4527,6 +4630,19 @@ void sai_deserialize_meter_bucket_entry( sai_deserialize_number(j["meter_class"], meter_bucket_entry.meter_class); } +void sai_deserialize_prefix_compression_entry( + _In_ const std::string& s, + _Out_ sai_prefix_compression_entry_t& prefix_compression_entry) +{ + SWSS_LOG_ENTER(); + + json j = json::parse(s); + + sai_deserialize_object_id(j["switch_id"], prefix_compression_entry.switch_id); + sai_deserialize_object_id(j["prefix_table_id"], prefix_compression_entry.prefix_table_id); + sai_deserialize_ip_prefix(j["prefix"], prefix_compression_entry.prefix); +} + void sai_deserialize_flow_entry( _In_ const std::string& s, _Out_ sai_flow_entry_t &flow_entry) @@ -4868,6 +4984,19 @@ void sai_deserialize_pa_validation_entry( sai_deserialize_ip_address(j["sip"], pa_validation_entry.sip); } +void sai_deserialize_outbound_port_map_port_range_entry( + _In_ const std::string &s, + _Out_ sai_outbound_port_map_port_range_entry_t &outbound_port_map_entry) +{ + SWSS_LOG_ENTER(); + + json j = json::parse(s); + + sai_deserialize_object_id(j["switch_id"], outbound_port_map_entry.switch_id); + sai_deserialize_object_id(j["outbound_port_map_id"], outbound_port_map_entry.outbound_port_map_id); + sai_deserialize_range(j["dst_port_range"], outbound_port_map_entry.dst_port_range); +} + void sai_deserialize_outbound_routing_entry( _In_ const std::string &s, _Out_ sai_outbound_routing_entry_t& outbound_routing_entry) @@ -4881,6 +5010,31 @@ void sai_deserialize_outbound_routing_entry( sai_deserialize_object_id(j["outbound_routing_group_id"], outbound_routing_entry.outbound_routing_group_id); } +void sai_deserialize_global_trusted_vni_entry( + _In_ const std::string &s, + _Out_ sai_global_trusted_vni_entry_t &global_trusted_vni_entry) +{ + SWSS_LOG_ENTER(); + + json j = json::parse(s); + + sai_deserialize_object_id(j["switch_id"], global_trusted_vni_entry.switch_id); + sai_deserialize_range(j["vni_range"], global_trusted_vni_entry.vni_range); +} + +void sai_deserialize_eni_trusted_vni_entry( + _In_ const std::string &s, + _Out_ sai_eni_trusted_vni_entry_t &eni_trusted_vni_entry) +{ + SWSS_LOG_ENTER(); + + json j = json::parse(s); + + sai_deserialize_object_id(j["switch_id"], eni_trusted_vni_entry.switch_id); + sai_deserialize_object_id(j["eni_id"], eni_trusted_vni_entry.eni_id); + sai_deserialize_range(j["vni_range"], eni_trusted_vni_entry.vni_range); +} + void sai_deserialize_outbound_ca_to_pa_entry( _In_ const std::string &s, _Out_ sai_outbound_ca_to_pa_entry_t& outbound_ca_to_pa_entry) @@ -4978,6 +5132,10 @@ bool sai_deserialize_object_entry( sai_deserialize_mcast_fdb_entry(object_id, meta_key.objectkey.key.mcast_fdb_entry); return true; + case SAI_OBJECT_TYPE_PREFIX_COMPRESSION_ENTRY: + sai_deserialize_prefix_compression_entry(object_id, meta_key.objectkey.key.prefix_compression_entry); + return true; + default: return false; } @@ -5806,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 721a6fce..1f9c0d14 100644 --- a/meta/sai_serialize.h +++ b/meta/sai_serialize.h @@ -72,6 +72,9 @@ std::string sai_serialize_fdb_entry( std::string sai_serialize_meter_bucket_entry( _In_ const sai_meter_bucket_entry_t &meter_bucket_entry); +std::string sai_serialize_prefix_compression_entry( + _In_ const sai_prefix_compression_entry_t &prefix_compression_entry); + std::string sai_serialize_flow_entry( _In_ const sai_flow_entry_t &flow_entry); @@ -168,9 +171,18 @@ std::string sai_serialize_inbound_routing_entry( std::string sai_serialize_pa_validation_entry( _In_ const sai_pa_validation_entry_t &pa_validation_entry); +std::string sai_serialize_outbound_port_map_port_range_entry( + _In_ const sai_outbound_port_map_port_range_entry_t &outbound_port_map_entry); + std::string sai_serialize_outbound_routing_entry( _In_ const sai_outbound_routing_entry_t &outbound_routing_entry); +std::string sai_serialize_global_trusted_vni_entry( + _In_ const sai_global_trusted_vni_entry_t &global_trusted_vni_entry); + +std::string sai_serialize_eni_trusted_vni_entry( + _In_ const sai_eni_trusted_vni_entry_t &eni_trusted_vni_entry); + std::string sai_serialize_outbound_ca_to_pa_entry( _In_ const sai_outbound_ca_to_pa_entry_t &outbound_ca_to_pa_entry); @@ -299,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( @@ -451,6 +468,10 @@ void sai_deserialize_meter_bucket_entry( _In_ const std::string& s, _Out_ sai_meter_bucket_entry_t& meter_bucket_entry); +void sai_deserialize_prefix_compression_entry( + _In_ const std::string& s, + _Out_ sai_prefix_compression_entry_t& prefix_compression_entry); + void sai_deserialize_flow_entry( _In_ const std::string& s, _Out_ sai_flow_entry_t &flow_entry); @@ -479,10 +500,22 @@ void sai_deserialize_pa_validation_entry( _In_ const std::string &s, _Out_ sai_pa_validation_entry_t& pa_validation_entry); +void sai_deserialize_outbound_port_map_port_range_entry( + _In_ const std::string &s, + _Out_ sai_outbound_port_map_port_range_entry_t &outbound_port_map_entry); + void sai_deserialize_outbound_routing_entry( _In_ const std::string &s, _Out_ sai_outbound_routing_entry_t& outbound_routing_entry); +void sai_deserialize_global_trusted_vni_entry( + _In_ const std::string &s, + _Out_ sai_global_trusted_vni_entry_t &global_trusted_vni_entry); + +void sai_deserialize_eni_trusted_vni_entry( + _In_ const std::string &s, + _Out_ sai_eni_trusted_vni_entry_t &eni_trusted_vni_entry); + void sai_deserialize_outbound_ca_to_pa_entry( _In_ const std::string &s, _Out_ sai_outbound_ca_to_pa_entry_t& outbound_ca_to_pa_entry); @@ -658,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/stub.pl b/stub.pl index 237c6292..40661caa 100755 --- a/stub.pl +++ b/stub.pl @@ -105,7 +105,7 @@ sub GetData sub SanitizeData { $DATA =~ s/SAI_OBJECT_TYPE_\w*(START|END|NULL|MAX)//gms; - $DATA =~ s/SAI_API_\w*(START|END|UNSPECIFIED|MAX|EXTENSIONS_RANGE_BASE)//gms; + $DATA =~ s/SAI_API_\w*(START|END|UNSPECIFIED|MAX|EXTENSIONS_RANGE_BASE|CUSTOM_RANGE_BASE)//gms; } sub ExtractData diff --git a/syncd/AttrVersionChecker.cpp b/syncd/AttrVersionChecker.cpp new file mode 100644 index 00000000..320afcaf --- /dev/null +++ b/syncd/AttrVersionChecker.cpp @@ -0,0 +1,107 @@ +#include "AttrVersionChecker.h" + +#include "swss/logger.h" + +using namespace syncd; + +AttrVersionChecker::AttrVersionChecker(): + m_enabled(false), + m_saiApiVersion(SAI_VERSION(0,0,0)) +{ + SWSS_LOG_ENTER(); + + // empty +} + +void AttrVersionChecker::enable( + _In_ bool enable) +{ + SWSS_LOG_ENTER(); + + m_enabled = enable; +} + +void AttrVersionChecker::setSaiApiVersion( + _In_ sai_api_version_t version) +{ + SWSS_LOG_ENTER(); + + m_saiApiVersion = version; +} + +void AttrVersionChecker::reset() +{ + SWSS_LOG_ENTER(); + + m_visitedAttributes.clear(); +} + +bool AttrVersionChecker::isSufficientVersion( + _In_ const sai_attr_metadata_t *md) +{ + SWSS_LOG_ENTER(); + + if (md == nullptr) + { + SWSS_LOG_ERROR("md is NULL"); + + return false; + } + + if (!m_enabled) + { + return true; + } + + if (SAI_METADATA_HAVE_ATTR_VERSION == 0) + { + // metadata does not contain attr versions, no check will be preformed + return true; + } + + // check attr version if metadata have version defined + + if (m_saiApiVersion > md->apiversion) + { + // ok, SAI version is bigger than attribute release version + + return true; + } + + if (m_saiApiVersion < md->apiversion) + { + // skip, SAI version is not sufficient + + if (m_visitedAttributes.find(md->attridname) == m_visitedAttributes.end()) + { + m_visitedAttributes.insert(md->attridname); + + // log only once + + SWSS_LOG_WARN("SAI version %lu, not sufficient to discover %s", m_saiApiVersion, md->attridname); + } + + return false; + } + + // m_saiApiVersion == md->apiversion + + if (md->nextrelease == false) + { + // ok, SAI version is equal to attribute version + return true; + } + + // next release == true + + if (m_visitedAttributes.find(md->attridname) == m_visitedAttributes.end()) + { + m_visitedAttributes.insert(md->attridname); + + // warn only once + + SWSS_LOG_WARN("%s is ment for next release after %lu, will not discover", md->attridname, m_saiApiVersion); + } + + return false; +} diff --git a/syncd/AttrVersionChecker.h b/syncd/AttrVersionChecker.h new file mode 100644 index 00000000..f2b65cdd --- /dev/null +++ b/syncd/AttrVersionChecker.h @@ -0,0 +1,40 @@ +#pragma once + +extern "C" { +#include "sai.h" +#include "saimetadata.h" +} + +#include +#include + +namespace syncd +{ + class AttrVersionChecker + { + public: + + AttrVersionChecker(); + + public: + + void enable( + _In_ bool enable); + + void setSaiApiVersion( + _In_ sai_api_version_t version); + + void reset(); + + bool isSufficientVersion( + _In_ const sai_attr_metadata_t *md); + + private: + + bool m_enabled; + + sai_api_version_t m_saiApiVersion; + + std::set m_visitedAttributes; + }; +} diff --git a/syncd/CommandLineOptions.cpp b/syncd/CommandLineOptions.cpp index 0c25c8ca..59ef2510 100644 --- a/syncd/CommandLineOptions.cpp +++ b/syncd/CommandLineOptions.cpp @@ -44,6 +44,9 @@ CommandLineOptions::CommandLineOptions() #endif // SAITHRIFT + m_supportingBulkCounterGroups = ""; + + m_enableAttrVersionCheck = false; } std::string CommandLineOptions::getCommandLineString() const @@ -67,6 +70,7 @@ std::string CommandLineOptions::getCommandLineString() const ss << " BreakConfig=" << m_breakConfig; ss << " WatchdogWarnTimeSpan=" << m_watchdogWarnTimeSpan; ss << " SupportingBulkCounters=" << m_supportingBulkCounterGroups; + ss << " EnableAttrVersionCheck=" << (m_enableAttrVersionCheck ? "YES" : "NO"); #ifdef SAITHRIFT diff --git a/syncd/CommandLineOptions.h b/syncd/CommandLineOptions.h index 99d0827d..72982ea5 100644 --- a/syncd/CommandLineOptions.h +++ b/syncd/CommandLineOptions.h @@ -100,5 +100,6 @@ namespace syncd std::string m_supportingBulkCounterGroups; + bool m_enableAttrVersionCheck; }; } diff --git a/syncd/CommandLineOptionsParser.cpp b/syncd/CommandLineOptionsParser.cpp index d4962433..66c13e49 100644 --- a/syncd/CommandLineOptionsParser.cpp +++ b/syncd/CommandLineOptionsParser.cpp @@ -19,9 +19,9 @@ std::shared_ptr CommandLineOptionsParser::parseCommandLine( auto options = std::make_shared(); #ifdef SAITHRIFT - const char* const optstring = "dp:t:g:x:b:B:w:uSUCsz:lrm:h"; + const char* const optstring = "dp:t:g:x:b:B:aw:uSUCsz:lrm:h"; #else - const char* const optstring = "dp:t:g:x:b:B:w:uSUCsz:lh"; + const char* const optstring = "dp:t:g:x:b:B:aw:uSUCsz:lh"; #endif // SAITHRIFT while (true) @@ -43,6 +43,7 @@ std::shared_ptr CommandLineOptionsParser::parseCommandLine( { "breakConfig", required_argument, 0, 'b' }, { "watchdogWarnTimeSpan", optional_argument, 0, 'w' }, { "supportingBulkCounters", required_argument, 0, 'B' }, + { "enableAttrVersionCheck", no_argument, 0, 'a' }, #ifdef SAITHRIFT { "rpcserver", no_argument, 0, 'r' }, { "portmap", required_argument, 0, 'm' }, @@ -138,6 +139,10 @@ std::shared_ptr CommandLineOptionsParser::parseCommandLine( options->m_supportingBulkCounterGroups = std::string(optarg); break; + case 'a': + options->m_enableAttrVersionCheck = true; + break; + case 'h': printUsage(); exit(EXIT_SUCCESS); @@ -196,6 +201,8 @@ void CommandLineOptionsParser::printUsage() std::cout << " Watchdog time span (in microseconds) to watch for execution" << std::endl; std::cout << " -B --supportingBulkCounters" << std::endl; std::cout << " Counter groups those support bulk polling" << std::endl; + std::cout << " -a --enableAttrVersionCheck" << std::endl; + std::cout << " Enable attribute SAI version check when performing SAI discovery" << std::endl; #ifdef SAITHRIFT diff --git a/syncd/FlexCounter.cpp b/syncd/FlexCounter.cpp index 6c480f27..292775f5 100644 --- a/syncd/FlexCounter.cpp +++ b/syncd/FlexCounter.cpp @@ -29,6 +29,7 @@ static const std::string COUNTER_TYPE_BUFFER_POOL = "Buffer Pool Counter"; static const std::string COUNTER_TYPE_ENI = "DASH ENI Counter"; static const std::string COUNTER_TYPE_METER_BUCKET = "DASH Meter Bucket Counter"; static const std::string COUNTER_TYPE_POLICER = "Policer Counter"; +static const std::string COUNTER_TYPE_SRV6 = "SRv6 Counter"; static const std::string ATTR_TYPE_QUEUE = "Queue Attribute"; static const std::string ATTR_TYPE_PG = "Priority Group Attribute"; static const std::string ATTR_TYPE_MACSEC_SA = "MACSEC SA Attribute"; @@ -64,7 +65,8 @@ const std::map, std::string> FlexCoun {{SAI_OBJECT_TYPE_POLICER, POLICER_COUNTER_ID_LIST}, COUNTER_TYPE_POLICER}, {{SAI_OBJECT_TYPE_TUNNEL, TUNNEL_COUNTER_ID_LIST}, COUNTER_TYPE_TUNNEL}, {{(sai_object_type_t)SAI_OBJECT_TYPE_ENI, ENI_COUNTER_ID_LIST}, COUNTER_TYPE_ENI}, - {{(sai_object_type_t)SAI_OBJECT_TYPE_ENI, DASH_METER_COUNTER_ID_LIST}, COUNTER_TYPE_METER_BUCKET} + {{(sai_object_type_t)SAI_OBJECT_TYPE_ENI, DASH_METER_COUNTER_ID_LIST}, COUNTER_TYPE_METER_BUCKET}, + {{SAI_OBJECT_TYPE_COUNTER, SRV6_COUNTER_ID_LIST}, COUNTER_TYPE_SRV6}, }; BaseCounterContext::BaseCounterContext(const std::string &name, const std::string &instance): @@ -1311,11 +1313,18 @@ class CounterContext : public BaseCounterContext { values.emplace_back(serializeStat(ctx.counter_ids[j]), std::to_string(ctx.counters[i * ctx.counter_ids.size() + j])); } - values.emplace_back(m_instanceId + "_time_stamp", std::to_string(time_stamp)); + countersTable.set(sai_serialize_object_id(vid), values, ""); values.clear(); } + // First generate the key, then replace spaces with underscores to avoid issues when Lua plugins handle the timestamp + std::string timestamp_key = m_instanceId + "_" + m_name + "_time_stamp"; + std::replace(timestamp_key.begin(), timestamp_key.end(), ' ', '_'); + + values.emplace_back(timestamp_key, std::to_string(time_stamp)); + countersTable.set("TIME_STAMP", values, ""); + SWSS_LOG_DEBUG("After pushing db %s %s %s", m_instanceId.c_str(), m_name.c_str(), ctx.name.c_str()); } @@ -2411,6 +2420,10 @@ std::shared_ptr FlexCounter::createCounterContext( { return std::make_shared>(context_name, instance, SAI_OBJECT_TYPE_POLICER, m_vendorSai.get(), m_statsMode); } + else if (context_name == COUNTER_TYPE_SRV6) + { + return std::make_shared>(context_name, instance, SAI_OBJECT_TYPE_COUNTER, m_vendorSai.get(), m_statsMode); + } SWSS_LOG_THROW("Invalid counter type %s", context_name.c_str()); // GCC 8.3 requires a return value here @@ -2704,6 +2717,11 @@ void FlexCounter::removeCounter( getCounterContext(COUNTER_TYPE_FLOW)->removeObject(vid); removeDataFromCountersDB(vid, ":TRAP"); } + + if (hasCounterContext(COUNTER_TYPE_SRV6)) + { + getCounterContext(COUNTER_TYPE_SRV6)->removeObject(vid); + } } else if (objectType == SAI_OBJECT_TYPE_POLICER) { diff --git a/syncd/Makefile.am b/syncd/Makefile.am index 1a969e73..f64a4456 100644 --- a/syncd/Makefile.am +++ b/syncd/Makefile.am @@ -17,6 +17,7 @@ noinst_LIBRARIES = libSyncd.a libSyncdRequestShutdown.a libMdioIpcClient.a libSyncd_a_SOURCES = \ AsicOperation.cpp \ AsicView.cpp \ + AttrVersionChecker.cpp \ BestCandidateFinder.cpp \ BreakConfig.cpp \ BreakConfigParser.cpp \ 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..beb49f37 100644 --- a/syncd/NotificationProcessor.cpp +++ b/syncd/NotificationProcessor.cpp @@ -781,6 +781,28 @@ 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()); + + sai_object_id_t rid; + sai_object_id_t vid; + sai_deserialize_object_id(data, rid); + + if (!m_translator->tryTranslateRidToVid(rid, vid)) + { + SWSS_LOG_ERROR("TAM_TEL_TYPE RID %s transalted to null VID!!!", sai_serialize_object_id(rid).c_str()); + return; + } + + std::string vid_data = sai_serialize_object_id(vid); + + sendNotification(SAI_SWITCH_NOTIFICATION_NAME_TAM_TEL_TYPE_CONFIG_CHANGE, vid_data); +} + void NotificationProcessor::processNotification( _In_ const swss::KeyOpFieldsValuesTuple& item) { @@ -837,6 +859,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/SaiDiscovery.cpp b/syncd/SaiDiscovery.cpp index b75f490d..ce768eb9 100644 --- a/syncd/SaiDiscovery.cpp +++ b/syncd/SaiDiscovery.cpp @@ -1,4 +1,5 @@ #include "SaiDiscovery.h" +#include "VendorSaiOptions.h" #include "swss/logger.h" @@ -24,7 +25,31 @@ SaiDiscovery::SaiDiscovery( { SWSS_LOG_ENTER(); - // empty + sai_api_version_t version = SAI_VERSION(0,0,0); + + sai_status_t status = m_sai->queryApiVersion(&version); + + if (status == SAI_STATUS_SUCCESS) + { + auto vso = std::dynamic_pointer_cast(sai->getOptions(VendorSaiOptions::OPTIONS_KEY)); + + // TODO check vso for null + + m_attrVersionChecker.enable(vso->m_checkAttrVersion); + m_attrVersionChecker.setSaiApiVersion(version); + + SWSS_LOG_NOTICE("check attr version %s, libsai api version: %lu", + (vso->m_checkAttrVersion ? "ENABLED" : "DISABLED"), + version); + } + else + { + m_attrVersionChecker.enable(false); + m_attrVersionChecker.setSaiApiVersion(SAI_API_VERSION); + + SWSS_LOG_WARN("failed to obtain libsai api version: %s, will discover all attributes", + sai_serialize_status(status).c_str()); + } } SaiDiscovery::~SaiDiscovery() @@ -117,6 +142,11 @@ void SaiDiscovery::discover( attr.id = md->attrid; + if (!m_attrVersionChecker.isSufficientVersion(md)) + { + continue; + } + if (md->attrvaluetype == SAI_ATTR_VALUE_TYPE_OBJECT_ID) { if (md->defaultvaluetype == SAI_DEFAULT_VALUE_TYPE_CONST) @@ -266,6 +296,8 @@ std::set SaiDiscovery::discover( m_defaultOidMap.clear(); + m_attrVersionChecker.reset(); + std::set discovered_rids; { diff --git a/syncd/SaiDiscovery.h b/syncd/SaiDiscovery.h index c48372b0..b6f8cf05 100644 --- a/syncd/SaiDiscovery.h +++ b/syncd/SaiDiscovery.h @@ -2,6 +2,8 @@ #include "meta/SaiInterface.h" +#include "AttrVersionChecker.h" + #include #include #include @@ -61,5 +63,7 @@ namespace syncd std::shared_ptr m_sai; DefaultOidMap m_defaultOidMap; + + AttrVersionChecker m_attrVersionChecker; }; } diff --git a/syncd/SaiSwitch.h b/syncd/SaiSwitch.h index 523e1fe1..d6bccfee 100644 --- a/syncd/SaiSwitch.h +++ b/syncd/SaiSwitch.h @@ -34,7 +34,7 @@ namespace syncd _In_ std::shared_ptr client, _In_ std::shared_ptr translator, _In_ std::shared_ptr vendorSai, - _In_ bool warmBoot = false); + _In_ bool warmBoot); virtual ~SaiSwitch() = default; diff --git a/syncd/SingleReiniter.cpp b/syncd/SingleReiniter.cpp index f757ba51..6f535573 100644 --- a/syncd/SingleReiniter.cpp +++ b/syncd/SingleReiniter.cpp @@ -317,7 +317,7 @@ void SingleReiniter::processSwitches() * object, so when doing discover we will get full default ASIC view. */ - m_sw = std::make_shared(m_switch_vid, m_switch_rid, m_client, m_translator, m_vendorSai); + m_sw = std::make_shared(m_switch_vid, m_switch_rid, m_client, m_translator, m_vendorSai, false); /* * We processed switch. We have switch vid/rid so we can process all 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 2dc2b7a5..8a1cb186 100644 --- a/syncd/Syncd.cpp +++ b/syncd/Syncd.cpp @@ -12,6 +12,7 @@ #include "RedisNotificationProducer.h" #include "ZeroMQNotificationProducer.h" #include "WatchdogScope.h" +#include "VendorSaiOptions.h" #include "sairediscommon.h" @@ -68,8 +69,6 @@ Syncd::Syncd( SWSS_LOG_NOTICE("sairedis git revision %s, SAI git revision: %s", SAIREDIS_GIT_REVISION, SAI_GIT_REVISION); - setSaiApiLogLevel(); - SWSS_LOG_NOTICE("command line: %s", m_commandLineOptions->getCommandLineString().c_str()); auto ccc = sairedis::ContextConfigContainer::loadFromFile(m_commandLineOptions->m_contextConfig.c_str()); @@ -110,6 +109,12 @@ Syncd::Syncd( m_enableSyncMode = true; } + auto vso = std::make_shared(); + + vso->m_checkAttrVersion = m_commandLineOptions->m_enableAttrVersionCheck; + + m_vendorSai->setOptions(VendorSaiOptions::OPTIONS_KEY, vso); + m_manager = std::make_shared(m_vendorSai, m_contextConfig->m_dbCounters, m_commandLineOptions->m_supportingBulkCounterGroups); loadProfileMap(); @@ -162,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()); @@ -207,6 +213,8 @@ Syncd::Syncd( abort(); } + setSaiApiLogLevel(); + sai_api_version_t apiVersion = SAI_VERSION(0,0,0); // invalid version status = m_vendorSai->queryApiVersion(&apiVersion); @@ -421,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()); } @@ -686,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) { @@ -3465,7 +3562,7 @@ sai_status_t Syncd::processOidCreate( * constructor, like getting all queues, ports, etc. */ - m_switches[switchVid] = std::make_shared(switchVid, objectRid, m_client, m_translator, m_vendorSai); + m_switches[switchVid] = std::make_shared(switchVid, objectRid, m_client, m_translator, m_vendorSai, false); m_mdioIpcServer->setSwitchId(objectRid); @@ -4854,7 +4951,7 @@ void Syncd::onSwitchCreateInInitViewMode( // make switch initialization and get all default data - m_switches[switchVid] = std::make_shared(switchVid, switchRid, m_client, m_translator, m_vendorSai); + m_switches[switchVid] = std::make_shared(switchVid, switchRid, m_client, m_translator, m_vendorSai, false); m_mdioIpcServer->setSwitchId(switchRid); 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 6c54b244..4499fdb0 100644 --- a/syncd/VendorSai.cpp +++ b/syncd/VendorSai.cpp @@ -53,9 +53,17 @@ VendorSai::VendorSai() .query_attribute_enum_values_capability = &sai_query_attribute_enum_values_capability, .query_object_stage = nullptr, .query_stats_capability = &sai_query_stats_capability, +#ifdef HAVE_SAI_QUERY_STATS_ST_CAPABILITY + .query_stats_st_capability = &sai_query_stats_st_capability, +#else .query_stats_st_capability = nullptr, +#endif .switch_id_query = &sai_switch_id_query, +#ifdef HAVE_SAI_TAM_TELEMETRY_GET_DATA + .tam_telemetry_get_data = &sai_tam_telemetry_get_data, +#else .tam_telemetry_get_data = nullptr, +#endif }; m_globalApis = ga; @@ -353,10 +361,12 @@ sai_status_t VendorSai::queryStatsStCapability( SWSS_LOG_ENTER(); VENDOR_CHECK_API_INITIALIZED(); - return m_globalApis.query_stats_st_capability( - switchId, - objectType, - stats_capability); + return (m_globalApis.query_stats_st_capability == nullptr) + ? SAI_STATUS_NOT_IMPLEMENTED + : m_globalApis.query_stats_st_capability( + switchId, + objectType, + stats_capability); } sai_status_t VendorSai::getStatsExt( @@ -1029,6 +1039,33 @@ sai_status_t VendorSai::bulkCreate( object_statuses); } +sai_status_t VendorSai::bulkCreate( + _In_ uint32_t object_count, + _In_ const sai_outbound_port_map_port_range_entry_t* entries, + _In_ const uint32_t *attr_count, + _In_ const sai_attribute_t **attr_list, + _In_ sai_bulk_op_error_mode_t mode, + _Out_ sai_status_t *object_statuses) +{ + MUTEX(); + SWSS_LOG_ENTER(); + VENDOR_CHECK_API_INITIALIZED(); + + if (!m_apis.dash_outbound_port_map_api->create_outbound_port_map_port_range_entries) + { + SWSS_LOG_INFO("create_outbound_port_map_port_range_entries is not supported"); + return SAI_STATUS_NOT_SUPPORTED; + } + + return m_apis.dash_outbound_port_map_api->create_outbound_port_map_port_range_entries( + object_count, + entries, + attr_count, + attr_list, + mode, + object_statuses); +} + sai_status_t VendorSai::bulkCreate( _In_ uint32_t object_count, _In_ const sai_outbound_routing_entry_t* entries, @@ -1056,6 +1093,60 @@ sai_status_t VendorSai::bulkCreate( object_statuses); } +sai_status_t VendorSai::bulkCreate( + _In_ uint32_t object_count, + _In_ const sai_global_trusted_vni_entry_t* entries, + _In_ const uint32_t *attr_count, + _In_ const sai_attribute_t **attr_list, + _In_ sai_bulk_op_error_mode_t mode, + _Out_ sai_status_t *object_statuses) +{ + MUTEX(); + SWSS_LOG_ENTER(); + VENDOR_CHECK_API_INITIALIZED(); + + if (!m_apis.dash_trusted_vni_api->create_global_trusted_vni_entries) + { + SWSS_LOG_INFO("create_global_trusted_vni_entries is not supported"); + return SAI_STATUS_NOT_SUPPORTED; + } + + return m_apis.dash_trusted_vni_api->create_global_trusted_vni_entries( + object_count, + entries, + attr_count, + attr_list, + mode, + object_statuses); +} + +sai_status_t VendorSai::bulkCreate( + _In_ uint32_t object_count, + _In_ const sai_eni_trusted_vni_entry_t* entries, + _In_ const uint32_t *attr_count, + _In_ const sai_attribute_t **attr_list, + _In_ sai_bulk_op_error_mode_t mode, + _Out_ sai_status_t *object_statuses) +{ + MUTEX(); + SWSS_LOG_ENTER(); + VENDOR_CHECK_API_INITIALIZED(); + + if (!m_apis.dash_trusted_vni_api->create_eni_trusted_vni_entries) + { + SWSS_LOG_INFO("create_eni_trusted_vni_entries is not supported"); + return SAI_STATUS_NOT_SUPPORTED; + } + + return m_apis.dash_trusted_vni_api->create_eni_trusted_vni_entries( + object_count, + entries, + attr_count, + attr_list, + mode, + object_statuses); +} + sai_status_t VendorSai::bulkCreate( _In_ uint32_t object_count, _In_ const sai_outbound_ca_to_pa_entry_t* entries, @@ -1137,6 +1228,33 @@ sai_status_t VendorSai::bulkCreate( object_statuses); } +sai_status_t VendorSai::bulkCreate( + _In_ uint32_t object_count, + _In_ const sai_prefix_compression_entry_t* entries, + _In_ const uint32_t *attr_count, + _In_ const sai_attribute_t **attr_list, + _In_ sai_bulk_op_error_mode_t mode, + _Out_ sai_status_t *object_statuses) +{ + MUTEX(); + SWSS_LOG_ENTER(); + VENDOR_CHECK_API_INITIALIZED(); + + if (!m_apis.prefix_compression_api->create_prefix_compression_entries) + { + SWSS_LOG_INFO("create_prefix_compression_entries is not supported"); + return SAI_STATUS_NOT_SUPPORTED; + } + + return m_apis.prefix_compression_api->create_prefix_compression_entries( + object_count, + entries, + attr_count, + attr_list, + mode, + object_statuses); +} + // BULK REMOVE sai_status_t VendorSai::bulkRemove( @@ -1393,6 +1511,29 @@ sai_status_t VendorSai::bulkRemove( object_statuses); } +sai_status_t VendorSai::bulkRemove( + _In_ uint32_t object_count, + _In_ const sai_outbound_port_map_port_range_entry_t *entries, + _In_ sai_bulk_op_error_mode_t mode, + _Out_ sai_status_t *object_statuses) +{ + MUTEX(); + SWSS_LOG_ENTER(); + VENDOR_CHECK_API_INITIALIZED(); + + if (!m_apis.dash_outbound_port_map_api->remove_outbound_port_map_port_range_entries) + { + SWSS_LOG_INFO("remove_outbound_port_map_port_range_entries is not supported"); + return SAI_STATUS_NOT_SUPPORTED; + } + + return m_apis.dash_outbound_port_map_api->remove_outbound_port_map_port_range_entries( + object_count, + entries, + mode, + object_statuses); +} + sai_status_t VendorSai::bulkRemove( _In_ uint32_t object_count, _In_ const sai_outbound_routing_entry_t *entries, @@ -1416,6 +1557,52 @@ sai_status_t VendorSai::bulkRemove( object_statuses); } +sai_status_t VendorSai::bulkRemove( + _In_ uint32_t object_count, + _In_ const sai_global_trusted_vni_entry_t *entries, + _In_ sai_bulk_op_error_mode_t mode, + _Out_ sai_status_t *object_statuses) +{ + MUTEX(); + SWSS_LOG_ENTER(); + VENDOR_CHECK_API_INITIALIZED(); + + if (!m_apis.dash_trusted_vni_api->remove_global_trusted_vni_entries) + { + SWSS_LOG_INFO("remove_global_trusted_vni_entries is not supported"); + return SAI_STATUS_NOT_SUPPORTED; + } + + return m_apis.dash_trusted_vni_api->remove_global_trusted_vni_entries( + object_count, + entries, + mode, + object_statuses); +} + +sai_status_t VendorSai::bulkRemove( + _In_ uint32_t object_count, + _In_ const sai_eni_trusted_vni_entry_t *entries, + _In_ sai_bulk_op_error_mode_t mode, + _Out_ sai_status_t *object_statuses) +{ + MUTEX(); + SWSS_LOG_ENTER(); + VENDOR_CHECK_API_INITIALIZED(); + + if (!m_apis.dash_trusted_vni_api->remove_eni_trusted_vni_entries) + { + SWSS_LOG_INFO("remove_eni_trusted_vni_entries is not supported"); + return SAI_STATUS_NOT_SUPPORTED; + } + + return m_apis.dash_trusted_vni_api->remove_eni_trusted_vni_entries( + object_count, + entries, + mode, + object_statuses); +} + sai_status_t VendorSai::bulkRemove( _In_ uint32_t object_count, _In_ const sai_outbound_ca_to_pa_entry_t *entries, @@ -1485,6 +1672,29 @@ sai_status_t VendorSai::bulkRemove( object_statuses); } +sai_status_t VendorSai::bulkRemove( + _In_ uint32_t object_count, + _In_ const sai_prefix_compression_entry_t *entries, + _In_ sai_bulk_op_error_mode_t mode, + _Out_ sai_status_t *object_statuses) +{ + MUTEX(); + SWSS_LOG_ENTER(); + VENDOR_CHECK_API_INITIALIZED(); + + if (!m_apis.prefix_compression_api->remove_prefix_compression_entries) + { + SWSS_LOG_INFO("remove_prefix_compression_entries is not supported"); + return SAI_STATUS_NOT_SUPPORTED; + } + + return m_apis.prefix_compression_api->remove_prefix_compression_entries( + object_count, + entries, + mode, + object_statuses); +} + // BULK SET sai_status_t VendorSai::bulkSet( @@ -1707,6 +1917,20 @@ sai_status_t VendorSai::bulkSet( return SAI_STATUS_NOT_SUPPORTED; } +sai_status_t VendorSai::bulkSet( + _In_ uint32_t object_count, + _In_ const sai_outbound_port_map_port_range_entry_t *entries, + _In_ const sai_attribute_t *attr_list, + _In_ sai_bulk_op_error_mode_t mode, + _Out_ sai_status_t *object_statuses) +{ + MUTEX(); + SWSS_LOG_ENTER(); + VENDOR_CHECK_API_INITIALIZED(); + + return SAI_STATUS_NOT_SUPPORTED; +} + sai_status_t VendorSai::bulkSet( _In_ uint32_t object_count, _In_ const sai_outbound_routing_entry_t *entries, @@ -1721,6 +1945,34 @@ sai_status_t VendorSai::bulkSet( return SAI_STATUS_NOT_SUPPORTED; } +sai_status_t VendorSai::bulkSet( + _In_ uint32_t object_count, + _In_ const sai_global_trusted_vni_entry_t *entries, + _In_ const sai_attribute_t *attr_list, + _In_ sai_bulk_op_error_mode_t mode, + _Out_ sai_status_t *object_statuses) +{ + MUTEX(); + SWSS_LOG_ENTER(); + VENDOR_CHECK_API_INITIALIZED(); + + return SAI_STATUS_NOT_SUPPORTED; +} + +sai_status_t VendorSai::bulkSet( + _In_ uint32_t object_count, + _In_ const sai_eni_trusted_vni_entry_t *entries, + _In_ const sai_attribute_t *attr_list, + _In_ sai_bulk_op_error_mode_t mode, + _Out_ sai_status_t *object_statuses) +{ + MUTEX(); + SWSS_LOG_ENTER(); + VENDOR_CHECK_API_INITIALIZED(); + + return SAI_STATUS_NOT_SUPPORTED; +} + sai_status_t VendorSai::bulkSet( _In_ uint32_t object_count, _In_ const sai_outbound_ca_to_pa_entry_t *entries, @@ -1763,6 +2015,20 @@ sai_status_t VendorSai::bulkSet( return SAI_STATUS_NOT_SUPPORTED; } +sai_status_t VendorSai::bulkSet( + _In_ uint32_t object_count, + _In_ const sai_prefix_compression_entry_t *entries, + _In_ const sai_attribute_t *attr_list, + _In_ sai_bulk_op_error_mode_t mode, + _Out_ sai_status_t *object_statuses) +{ + MUTEX(); + SWSS_LOG_ENTER(); + VENDOR_CHECK_API_INITIALIZED(); + + return SAI_STATUS_NOT_SUPPORTED; +} + // NON QUAD API sai_status_t VendorSai::flushFdbEntries( diff --git a/syncd/VendorSaiOptions.h b/syncd/VendorSaiOptions.h new file mode 100644 index 00000000..4c66e81d --- /dev/null +++ b/syncd/VendorSaiOptions.h @@ -0,0 +1,17 @@ +#pragma once + +#include "meta/SaiOptions.h" + +namespace syncd +{ + class VendorSaiOptions: + public sairedis::SaiOptions + { + public: + static constexpr const char *OPTIONS_KEY = "vok"; + + public: + + bool m_checkAttrVersion = false; + }; +} diff --git a/tests/TestClient.cpp b/tests/TestClient.cpp index 9361d046..65f9ff7a 100644 --- a/tests/TestClient.cpp +++ b/tests/TestClient.cpp @@ -374,7 +374,8 @@ void TestClient::test_query_api() m_switch_id, SAI_OBJECT_TYPE_QUEUE, &queue_stats_capability); - ASSERT_TRUE(rc == SAI_STATUS_BUFFER_OVERFLOW); + ASSERT_TRUE(rc == SAI_STATUS_BUFFER_OVERFLOW || + rc == SAI_STATUS_NOT_IMPLEMENTED); sai_stat_capability_t stat_initializer; stat_initializer.stat_enum = 0; @@ -389,6 +390,40 @@ 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); + + printf("rc: %s\n", sai_serialize_status(rc).c_str()); + + ASSERT_TRUE(rc == SAI_STATUS_BUFFER_OVERFLOW || + rc == SAI_STATUS_NOT_IMPLEMENTED); + + 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"); + + rc = sai_query_stats_st_capability( + m_switch_id, + SAI_OBJECT_TYPE_QUEUE, + &queue_stats_st_capability); + + ASSERT_TRUE(rc == SAI_STATUS_SUCCESS || + rc == SAI_STATUS_NOT_IMPLEMENTED); + teardown(); } diff --git a/tests/aspell.en.pws b/tests/aspell.en.pws index e29a4970..59a1b350 100644 --- a/tests/aspell.en.pws +++ b/tests/aspell.en.pws @@ -430,6 +430,7 @@ TXSC typedef uint uncomment +unicast uninitialize unistd unittest @@ -479,3 +480,9 @@ saiproxy submodule Enqueue deque +apiversion +vso +VxLAN +IPFIX +IPFix +ipfix diff --git a/tests/utils.pm b/tests/utils.pm index 489e5bb5..34b120bf 100644 --- a/tests/utils.pm +++ b/tests/utils.pm @@ -48,19 +48,19 @@ sub flush_redis sub start_syncd { print color('bright_blue') . "Starting syncd" . color('reset') . "\n"; - `./vssyncd -SUu -p "$DIR/vsprofile.ini" @_ >/dev/null 2>/dev/null &`; + `./vssyncd -aSUu -p "$DIR/vsprofile.ini" @_ >/dev/null 2>/dev/null &`; } sub start_syncd_bulk { print color('bright_blue') . "Starting syncd bulk" . color('reset') . "\n"; - `./vssyncd -SUul -p "$DIR/vsprofile.ini" @_ >/dev/null 2>/dev/null &`; + `./vssyncd -aSUul -p "$DIR/vsprofile.ini" @_ >/dev/null 2>/dev/null &`; } sub start_syncd_warm { print color('bright_blue') . "Starting syncd warm" . color('reset') . "\n"; - `./vssyncd -SUu -t warm -p "$DIR/vsprofile.ini" >/dev/null 2>/dev/null &`; + `./vssyncd -aSUu -t warm -p "$DIR/vsprofile.ini" >/dev/null 2>/dev/null &`; sleep 1; } @@ -68,13 +68,13 @@ sub start_syncd_warm sub sync_start_syncd { print color('bright_blue') . "Starting syncd" . color('reset') . "\n"; - `./vssyncd -s -SUu -p "$DIR/vsprofile.ini" >/dev/null 2>/dev/null &`; + `./vssyncd -s -aSUu -p "$DIR/vsprofile.ini" >/dev/null 2>/dev/null &`; } sub sync_start_syncd_warm { print color('bright_blue') . "Starting syncd warm" . color('reset') . "\n"; - `./vssyncd -s -SUu -t warm -p "$DIR/vsprofile.ini" >/dev/null 2>/dev/null &`; + `./vssyncd -s -aSUu -t warm -p "$DIR/vsprofile.ini" >/dev/null 2>/dev/null &`; sleep 1; } 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..da8e3861 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,7 @@ static sai_service_method_table_t test_services = { profile_get_next_value }; + TEST(ServerSai, bulkGet) { ServerSai sai; @@ -65,3 +70,36 @@ TEST(ServerSai, bulkGet) SAI_BULK_OP_ERROR_MODE_STOP_ON_ERROR, statuses)); } + + +#ifdef MOCK_METHOD +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, 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)); +} +#endif 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 6034ea17..009d9947 100644 --- a/unittest/meta/TestMeta.cpp +++ b/unittest/meta/TestMeta.cpp @@ -7,6 +7,8 @@ #include +#include + #include #define VLAN_ID 2 @@ -968,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()); @@ -1871,3 +1902,34 @@ TEST(Meta, remove_meter_bucket_entry) EXPECT_EQ(SAI_STATUS_INVALID_PARAMETER, sai.remove(e)); } + +TEST(Meta, remove_prefix_compression_entry) +{ + Meta sai(std::make_shared()); + + sai_prefix_compression_entry_t* e = nullptr; + + EXPECT_EQ(SAI_STATUS_INVALID_PARAMETER, sai.remove(e)); +} + +TEST(Meta, isPortObjectIdValid) +{ + EXPECT_EQ(Meta::isPortObjectIdValid(SAI_OBJECT_TYPE_PORT), true); + EXPECT_EQ(Meta::isPortObjectIdValid(SAI_OBJECT_TYPE_BRIDGE_PORT), true); + EXPECT_EQ(Meta::isPortObjectIdValid(SAI_OBJECT_TYPE_LAG), true); + + EXPECT_EQ(Meta::isPortObjectIdValid(SAI_OBJECT_TYPE_TUNNEL),false); + EXPECT_EQ(Meta::isPortObjectIdValid(SAI_OBJECT_TYPE_NULL), false); + EXPECT_EQ(Meta::isPortObjectIdValid(SAI_OBJECT_TYPE_VLAN), false); +} + +TEST(Meta, getValidPortObjectTypes) +{ + auto v = Meta::getValidPortObjectTypes(); + + EXPECT_EQ(v.size(), 3); + + auto s = boost::algorithm::join(v, ","); + + EXPECT_EQ(s, "PORT,LAG,BRIDGE_PORT"); +} diff --git a/unittest/meta/TestNotificationTam.cpp b/unittest/meta/TestNotificationTam.cpp new file mode 100644 index 00000000..203cce75 --- /dev/null +++ b/unittest/meta/TestNotificationTam.cpp @@ -0,0 +1,34 @@ +#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()); + ASSERT_EQ(tam_id, n.getAnyObjectId()); + n.processMetadata(meta); +} diff --git a/unittest/meta/TestSaiInterface.cpp b/unittest/meta/TestSaiInterface.cpp index 19a095ab..cf35fc11 100644 --- a/unittest/meta/TestSaiInterface.cpp +++ b/unittest/meta/TestSaiInterface.cpp @@ -117,3 +117,37 @@ TEST(SaiInterface, stats_meter_bucket_entry) EXPECT_EQ(SAI_STATUS_NOT_IMPLEMENTED, s->getStatsExt(m, 0, nullptr, SAI_STATS_MODE_READ, nullptr)); EXPECT_EQ(SAI_STATUS_NOT_IMPLEMENTED, s->clearStats(m, 0, nullptr)); } + +class Opt: + public SaiOptions +{ + public: + + int i; +}; + +TEST(SaiInterface, setOptions) +{ + DummySaiInterface ds; + + ds.setOptions("key", std::make_shared()); +} + +TEST(SaiInterface, getOptions) +{ + DummySaiInterface ds; + + auto opt = std::make_shared(); + + opt->i = 42; + + ds.setOptions("key", opt); + + auto o = std::dynamic_pointer_cast(ds.getOptions("key")); + + EXPECT_NE(o, nullptr); + + EXPECT_EQ(o->i, 42); + + EXPECT_EQ(ds.getOptions("foo"), nullptr); +} diff --git a/unittest/meta/TestSaiSerialize.cpp b/unittest/meta/TestSaiSerialize.cpp index 9f40d450..0f7a8f06 100644 --- a/unittest/meta/TestSaiSerialize.cpp +++ b/unittest/meta/TestSaiSerialize.cpp @@ -1348,6 +1348,17 @@ TEST(SaiSerialize, serialize_number) EXPECT_EQ(u, 0x12345678); } +TEST(SaiSerialize, sai_serialize_prefix_compression_entry) +{ + sai_prefix_compression_entry_t e; + + memset(&e, 0, sizeof(e)); + + auto s = sai_serialize_prefix_compression_entry(e); + + sai_deserialize_prefix_compression_entry(s, e); +} + TEST(SaiSerialize, serialize_stat_capability_list) { SWSS_LOG_ENTER(); @@ -1416,3 +1427,119 @@ TEST(SaiSerialize, serialize_stat_capability_list) } EXPECT_EQ(is_expected_enum, true); } + +TEST(SaiSerialize, sai_serialize_outbound_port_map_port_range_entry) +{ + sai_outbound_port_map_port_range_entry_t e; + + memset(&e, 0, sizeof(e)); + + auto s = sai_serialize_outbound_port_map_port_range_entry(e); + + sai_deserialize_outbound_port_map_port_range_entry(s, e); +} + +TEST(SaiSerialize, sai_serialize_global_trusted_vni_entry) +{ + sai_global_trusted_vni_entry_t e; + + memset(&e, 0, sizeof(e)); + + auto s = sai_serialize_global_trusted_vni_entry(e); + + sai_deserialize_global_trusted_vni_entry(s, e); +} + +TEST(SaiSerialize, sai_serialize_eni_trusted_vni_entry) +{ + sai_eni_trusted_vni_entry_t e; + + memset(&e, 0, sizeof(e)); + + auto s = sai_serialize_eni_trusted_vni_entry(e); + + 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/Makefile.am b/unittest/syncd/Makefile.am index b06a3ec0..13b0a43d 100644 --- a/unittest/syncd/Makefile.am +++ b/unittest/syncd/Makefile.am @@ -7,6 +7,7 @@ LDADD_GTEST = -L/usr/src/gtest -lgtest -lgtest_main -lgmock tests_SOURCES = main.cpp \ MockableSaiInterface.cpp \ MockHelper.cpp \ + TestAttrVersionChecker.cpp \ TestCommandLineOptions.cpp \ TestConcurrentQueue.cpp \ TestFlexCounter.cpp \ diff --git a/unittest/syncd/TestAttrVersionChecker.cpp b/unittest/syncd/TestAttrVersionChecker.cpp new file mode 100644 index 00000000..f1bc91ab --- /dev/null +++ b/unittest/syncd/TestAttrVersionChecker.cpp @@ -0,0 +1,132 @@ +#include + +#include +#include +#include + +#include + +#include "AttrVersionChecker.h" +#include "swss/logger.h" + +using namespace syncd; + +TEST(AttrVersionChecker, ctr) +{ + AttrVersionChecker avc; +} + +TEST(AttrVersionChecker, enable) +{ + AttrVersionChecker avc; + + avc.enable(true); + + avc.enable(false); +} + +TEST(AttrVersionChecker, setSaiApiVersion) +{ + AttrVersionChecker avc; + + avc.setSaiApiVersion(SAI_VERSION(1,13,0)); +} + +TEST(AttrVersionChecker, reset) +{ + AttrVersionChecker avc; + + avc.reset(); +} + +#define MD(x,v,n) \ + const sai_attr_metadata_t x = {\ + .objecttype = (sai_object_type_t)SAI_OBJECT_TYPE_BRIDGE,\ + .attrid = SAI_BRIDGE_ATTR_PORT_LIST,\ + .attridname = "SAI_BRIDGE_ATTR_PORT_LIST",\ + .brief = "List of bridge ports associated to this bridge.",\ + .attrvaluetype = SAI_ATTR_VALUE_TYPE_OBJECT_LIST,\ + .flags = (sai_attr_flags_t)(SAI_ATTR_FLAGS_READ_ONLY),\ + .allowedobjecttypes = NULL,\ + .allowedobjecttypeslength = 0,\ + .allowrepetitiononlist = false,\ + .allowmixedobjecttypes = false,\ + .allowemptylist = false,\ + .allownullobjectid = false,\ + .isoidattribute = (1 > 0),\ + .defaultvaluetype = SAI_DEFAULT_VALUE_TYPE_NONE,\ + .defaultvalue = NULL,\ + .defaultvalueobjecttype = SAI_OBJECT_TYPE_NULL,\ + .defaultvalueattrid = SAI_INVALID_ATTRIBUTE_ID,\ + .storedefaultvalue = false,\ + .isenum = false,\ + .isenumlist = false,\ + .enummetadata = NULL,\ + .conditiontype = SAI_ATTR_CONDITION_TYPE_NONE,\ + .conditions = NULL,\ + .conditionslength = 0,\ + .isconditional = (0 != 0),\ + .validonlytype = SAI_ATTR_CONDITION_TYPE_NONE,\ + .validonly = NULL,\ + .validonlylength = 0,\ + .isvalidonly = (0 != 0),\ + .getsave = false,\ + .isvlan = false,\ + .isaclfield = false,\ + .isaclaction = false,\ + .isaclmask = false,\ + .ismandatoryoncreate = false,\ + .iscreateonly = false,\ + .iscreateandset = false,\ + .isreadonly = true,\ + .iskey = false,\ + .isprimitive = false,\ + .notificationtype = -1,\ + .iscallback = false,\ + .pointertype = -1,\ + .capability = NULL,\ + .capabilitylength = 0,\ + .isextensionattr = false,\ + .isresourcetype = false,\ + .isdeprecated = false,\ + .isconditionrelaxed = false,\ + .iscustom = false,\ + .apiversion = (v),\ + .nextrelease = (n),\ + };\ + + +TEST(AttrVersionChecker, isSufficientVersion) +{ + AttrVersionChecker avc; + + avc.enable(true); + EXPECT_EQ(avc.isSufficientVersion(nullptr), false); + + avc.enable(false); + avc.setSaiApiVersion(SAI_VERSION(1,10,0)); + avc.enable(true); + + MD(md,SAI_VERSION(1,9,0),false); + EXPECT_EQ(avc.isSufficientVersion(&md), true); + + MD(md1,SAI_VERSION(1,11,0),false); + EXPECT_EQ(avc.isSufficientVersion(&md1),false); + + avc.enable(false); + EXPECT_EQ(avc.isSufficientVersion(&md1),true); + + avc.enable(true); + avc.setSaiApiVersion(SAI_VERSION(1,10,0)); + EXPECT_EQ(avc.isSufficientVersion(&md1),false); + + avc.setSaiApiVersion(SAI_VERSION(1,12,0)); + EXPECT_EQ(avc.isSufficientVersion(&md1),true); + + avc.setSaiApiVersion(SAI_VERSION(1,11,0)); + EXPECT_EQ(avc.isSufficientVersion(&md1),true); + + MD(md2,SAI_VERSION(1,11,0),true); + avc.setSaiApiVersion(SAI_VERSION(1,11,0)); + EXPECT_EQ(avc.isSufficientVersion(&md2),false); +} diff --git a/unittest/syncd/TestCommandLineOptions.cpp b/unittest/syncd/TestCommandLineOptions.cpp index 7c9088bf..0eb5aaef 100644 --- a/unittest/syncd/TestCommandLineOptions.cpp +++ b/unittest/syncd/TestCommandLineOptions.cpp @@ -38,6 +38,8 @@ R"(Usage: syncd [-d] [-p profile] [-t type] [-u] [-S] [-U] [-C] [-s] [-z mode] [ Watchdog time span (in microseconds) to watch for execution -B --supportingBulkCounters Counter groups those support bulk polling + -a --enableAttrVersionCheck + Enable attribute SAI version check when performing SAI discovery -h --help Print out this message )"; @@ -51,7 +53,7 @@ TEST(CommandLineOptions, getCommandLineString) EXPECT_EQ(str, " EnableDiagShell=NO EnableTempView=NO DisableExitSleep=NO EnableUnittests=NO" " EnableConsistencyCheck=NO EnableSyncMode=NO RedisCommunicationMode=redis_async" " EnableSaiBulkSuport=NO StartType=cold ProfileMapFile= GlobalContext=0 ContextConfig= BreakConfig=" - " WatchdogWarnTimeSpan=30000000 SupportingBulkCounters="); + " WatchdogWarnTimeSpan=30000000 SupportingBulkCounters= EnableAttrVersionCheck=NO"); } TEST(CommandLineOptions, startTypeStringToStartType) diff --git a/unittest/syncd/TestFlexCounter.cpp b/unittest/syncd/TestFlexCounter.cpp index 81794341..19f34ba7 100644 --- a/unittest/syncd/TestFlexCounter.cpp +++ b/unittest/syncd/TestFlexCounter.cpp @@ -77,6 +77,18 @@ std::vector generateOids( return object_ids; } +void removeTimeStamp(std::vector& keys, swss::Table& countersTable) +{ + SWSS_LOG_ENTER(); + + auto it = std::find(keys.begin(), keys.end(), "TIME_STAMP"); + if (it != keys.end()) + { + countersTable.del("TIME_STAMP"); + keys.erase(it); + } +} + void testAddRemoveCounter( unsigned int numOid, sai_object_type_t object_type, @@ -177,6 +189,8 @@ void testAddRemoveCounter( std::vector keys; countersTable.getKeys(keys); + // We have a dedicated item for all timestamps for counters using bulk counter polling + removeTimeStamp(keys, countersTable); EXPECT_EQ(keys.size(), object_ids.size()); for (size_t i = 0; i < object_ids.size(); i++) @@ -196,6 +210,7 @@ void testAddRemoveCounter( EXPECT_EQ(fc.isEmpty(), true); countersTable.getKeys(keys); + removeTimeStamp(keys, countersTable); ASSERT_TRUE(keys.empty()); } @@ -593,6 +608,26 @@ TEST(FlexCounter, addRemoveCounter) false, STATS_MODE_READ, true); + + testAddRemoveCounter( + 1, + SAI_OBJECT_TYPE_COUNTER, + SRV6_COUNTER_ID_LIST, + {"SAI_COUNTER_STAT_PACKETS", "SAI_COUNTER_STAT_BYTES"}, + {"100", "200"}, + counterVerifyFunc, + false); + + testAddRemoveCounter( + 1, + SAI_OBJECT_TYPE_COUNTER, + SRV6_COUNTER_ID_LIST, + {"SAI_COUNTER_STAT_PACKETS", "SAI_COUNTER_STAT_BYTES"}, + {"100", "200"}, + counterVerifyFunc, + false, + STATS_MODE_READ, + true); } TEST(FlexCounter, UpdateExistingCounterAddBulk) @@ -1047,6 +1082,8 @@ TEST(FlexCounter, bulkCounter) {"10", "20"}, counterVerifyFunc, false); + // buffer pool stats does not support bulk + EXPECT_EQ(false, clearCalled); capabilities = (SAI_STATS_MODE_READ|SAI_STATS_MODE_BULK_READ); testAddRemoveCounter( @@ -1060,8 +1097,15 @@ TEST(FlexCounter, bulkCounter) {"100", "200", "300", "400", "500", "600", "700", "800"}, counterVerifyFunc, false); - // buffer pool stats does not support bulk - EXPECT_EQ(false, clearCalled); + + testAddRemoveCounter( + 2, + SAI_OBJECT_TYPE_COUNTER, + SRV6_COUNTER_ID_LIST, + {"SAI_COUNTER_STAT_PACKETS", "SAI_COUNTER_STAT_BYTES"}, + {"100", "200"}, + counterVerifyFunc, + false); } TEST(FlexCounter, bulkChunksize) @@ -1719,6 +1763,7 @@ void testDashMeterAddRemoveCounter( std::vector keys; countersTable.getKeys(keys); + removeTimeStamp(keys, countersTable); ASSERT_TRUE(keys.empty()); } 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/syncd/TestVendorSai.cpp b/unittest/syncd/TestVendorSai.cpp index b610286d..9b09c61a 100644 --- a/unittest/syncd/TestVendorSai.cpp +++ b/unittest/syncd/TestVendorSai.cpp @@ -1567,6 +1567,21 @@ TEST(VendorSai, bulk_meter_rules) EXPECT_EQ(SAI_STATUS_SUCCESS, sai.remove((sai_object_type_t)SAI_OBJECT_TYPE_METER_POLICY, meter_policy1)); } +TEST_F(VendorSaiTest, bulk_prefix_compression_entry) +{ + sai_prefix_compression_entry_t *e = nullptr; + + // metadata will fail + EXPECT_EQ(SAI_STATUS_INVALID_PARAMETER, + m_vsai->bulkCreate(0, e, nullptr, nullptr, SAI_BULK_OP_ERROR_MODE_STOP_ON_ERROR, nullptr)); + + EXPECT_EQ(SAI_STATUS_INVALID_PARAMETER, + m_vsai->bulkRemove(0, e, SAI_BULK_OP_ERROR_MODE_STOP_ON_ERROR, nullptr)); + + EXPECT_EQ(SAI_STATUS_NOT_SUPPORTED, + m_vsai->bulkSet(0, e, nullptr, SAI_BULK_OP_ERROR_MODE_STOP_ON_ERROR, nullptr)); +} + TEST(VendorSai, logSet_logGet) { VendorSai sai; @@ -1577,3 +1592,70 @@ TEST(VendorSai, logSet_logGet) EXPECT_EQ(SAI_LOG_LEVEL_DEBUG, sai.logGet(SAI_API_PORT)); EXPECT_EQ(SAI_LOG_LEVEL_NOTICE, sai.logGet(SAI_API_SWITCH)); } + +TEST_F(VendorSaiTest, bulk_outbound_port_map_port_range_entry) +{ + sai_outbound_port_map_port_range_entry_t *e = nullptr; + + // metadata will fail + EXPECT_EQ(SAI_STATUS_INVALID_PARAMETER, + m_vsai->bulkCreate(0, e, nullptr, nullptr, SAI_BULK_OP_ERROR_MODE_STOP_ON_ERROR, nullptr)); + + EXPECT_EQ(SAI_STATUS_INVALID_PARAMETER, + m_vsai->bulkRemove(0, e, SAI_BULK_OP_ERROR_MODE_STOP_ON_ERROR, nullptr)); + + EXPECT_EQ(SAI_STATUS_NOT_SUPPORTED, + m_vsai->bulkSet(0, e, nullptr, SAI_BULK_OP_ERROR_MODE_STOP_ON_ERROR, nullptr)); +} + +TEST_F(VendorSaiTest, bulk_global_trusted_vni_entry) +{ + sai_global_trusted_vni_entry_t *e = nullptr; + + // metadata will fail + EXPECT_EQ(SAI_STATUS_INVALID_PARAMETER, + m_vsai->bulkCreate(0, e, nullptr, nullptr, SAI_BULK_OP_ERROR_MODE_STOP_ON_ERROR, nullptr)); + + EXPECT_EQ(SAI_STATUS_INVALID_PARAMETER, + m_vsai->bulkRemove(0, e, SAI_BULK_OP_ERROR_MODE_STOP_ON_ERROR, nullptr)); + + EXPECT_EQ(SAI_STATUS_NOT_SUPPORTED, + m_vsai->bulkSet(0, e, nullptr, SAI_BULK_OP_ERROR_MODE_STOP_ON_ERROR, nullptr)); +} + +TEST_F(VendorSaiTest, bulk_eni_trusted_vni_entry) +{ + sai_eni_trusted_vni_entry_t *e = nullptr; + + // metadata will fail + EXPECT_EQ(SAI_STATUS_INVALID_PARAMETER, + m_vsai->bulkCreate(0, e, nullptr, nullptr, SAI_BULK_OP_ERROR_MODE_STOP_ON_ERROR, nullptr)); + + EXPECT_EQ(SAI_STATUS_INVALID_PARAMETER, + m_vsai->bulkRemove(0, e, SAI_BULK_OP_ERROR_MODE_STOP_ON_ERROR, nullptr)); + + EXPECT_EQ(SAI_STATUS_NOT_SUPPORTED, + m_vsai->bulkSet(0, e, nullptr, SAI_BULK_OP_ERROR_MODE_STOP_ON_ERROR, nullptr)); +} + +TEST(VendorSai, queryStatsStCapability) +{ + VendorSai sai; + sai.apiInitialize(0, &test_services); + + sai_stat_st_capability_list_t st; + + sai_stat_st_capability_t item; + + st.count = 1; + st.list = &item; + + sai_status_t status = sai.queryStatsStCapability( + SAI_NULL_OBJECT_ID, // switch id + SAI_OBJECT_TYPE_QUEUE, + &st); + + // success expected, since always compiled against virtual switch + + EXPECT_EQ(SAI_STATUS_INVALID_PARAMETER, status); // switch is null +} diff --git a/unittest/vslib/Makefile.am b/unittest/vslib/Makefile.am index 092bcf04..3276e5fe 100644 --- a/unittest/vslib/Makefile.am +++ b/unittest/vslib/Makefile.am @@ -40,13 +40,15 @@ tests_SOURCES = main.cpp \ TestSwitch.cpp \ TestSwitchMLNX2700.cpp \ TestSwitchNvdaMBF2H536C.cpp \ + TestSwitchBCM56971B0.cpp \ TestSwitchBCM56850.cpp \ TestSwitchBCM81724.cpp \ TestSwitchStateBaseMACsec.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/TestSwitchBCM56850.cpp b/unittest/vslib/TestSwitchBCM56850.cpp index d2260f82..fba0e905 100644 --- a/unittest/vslib/TestSwitchBCM56850.cpp +++ b/unittest/vslib/TestSwitchBCM56850.cpp @@ -212,6 +212,53 @@ static bool getWarmBootState( return true; } +TEST(SwitchBCM56850, test_queue_number_get) +{ + auto sc = std::make_shared(0, ""); + auto signal = std::make_shared(); + auto eventQueue = std::make_shared(signal); + + sc->m_saiSwitchType = SAI_SWITCH_TYPE_NPU; + sc->m_switchType = SAI_VS_SWITCH_TYPE_BCM56850; + sc->m_bootType = SAI_VS_BOOT_TYPE_COLD; + sc->m_useTapDevice = false; + sc->m_laneMap = LaneMap::getDefaultLaneMap(0); + sc->m_eventQueue = eventQueue; + + auto scc = std::make_shared(); + + scc->insert(sc); + + SwitchBCM56850 sw( + 0x2100000000, + std::make_shared(0, scc), + sc); + + // Initialize switch state + ASSERT_EQ(sw.initialize_default_objects(0, nullptr), SAI_STATUS_SUCCESS); + + const sai_uint32_t uqNum = 10; + const sai_uint32_t mqNum = 10; + const sai_uint32_t qNum = uqNum + mqNum; + + sai_attribute_t attr; + + // Verify unicast queue number + attr.id = SAI_SWITCH_ATTR_NUMBER_OF_UNICAST_QUEUES; + ASSERT_EQ(sw.get(SAI_OBJECT_TYPE_SWITCH, 0x2100000000, 1, &attr), SAI_STATUS_SUCCESS); + ASSERT_EQ(attr.value.u32, uqNum); + + // Verify multicast queue number + attr.id = SAI_SWITCH_ATTR_NUMBER_OF_MULTICAST_QUEUES; + ASSERT_EQ(sw.get(SAI_OBJECT_TYPE_SWITCH, 0x2100000000, 1, &attr), SAI_STATUS_SUCCESS); + ASSERT_EQ(attr.value.u32, mqNum); + + // Verify total queue number + attr.id = SAI_SWITCH_ATTR_NUMBER_OF_QUEUES; + ASSERT_EQ(sw.get(SAI_OBJECT_TYPE_SWITCH, 0x2100000000, 1, &attr), SAI_STATUS_SUCCESS); + ASSERT_EQ(attr.value.u32, qNum); +} + TEST(SwitchBCM56850, warm_update_queues) { auto sc = std::make_shared(0, ""); diff --git a/unittest/vslib/TestSwitchBCM56971B0.cpp b/unittest/vslib/TestSwitchBCM56971B0.cpp new file mode 100644 index 00000000..a0d25f60 --- /dev/null +++ b/unittest/vslib/TestSwitchBCM56971B0.cpp @@ -0,0 +1,52 @@ +#include + +#include "SwitchBCM56971B0.h" + +using namespace saivs; + +TEST(SwitchBCM56971B0, test_queue_number_get) +{ + auto sc = std::make_shared(0, ""); + auto signal = std::make_shared(); + auto eventQueue = std::make_shared(signal); + + sc->m_saiSwitchType = SAI_SWITCH_TYPE_NPU; + sc->m_switchType = SAI_VS_SWITCH_TYPE_BCM56971B0; + sc->m_bootType = SAI_VS_BOOT_TYPE_COLD; + sc->m_useTapDevice = false; + sc->m_laneMap = LaneMap::getDefaultLaneMap(0); + sc->m_eventQueue = eventQueue; + + auto scc = std::make_shared(); + + scc->insert(sc); + + SwitchBCM56971B0 sw( + 0x2100000000, + std::make_shared(0, scc), + sc); + + // Initialize switch state + ASSERT_EQ(sw.initialize_default_objects(0, nullptr), SAI_STATUS_SUCCESS); + + const sai_uint32_t uqNum = 10; + const sai_uint32_t mqNum = 10; + const sai_uint32_t qNum = uqNum + mqNum; + + sai_attribute_t attr; + + // Verify unicast queue number + attr.id = SAI_SWITCH_ATTR_NUMBER_OF_UNICAST_QUEUES; + ASSERT_EQ(sw.get(SAI_OBJECT_TYPE_SWITCH, 0x2100000000, 1, &attr), SAI_STATUS_SUCCESS); + ASSERT_EQ(attr.value.u32, uqNum); + + // Verify multicast queue number + attr.id = SAI_SWITCH_ATTR_NUMBER_OF_MULTICAST_QUEUES; + ASSERT_EQ(sw.get(SAI_OBJECT_TYPE_SWITCH, 0x2100000000, 1, &attr), SAI_STATUS_SUCCESS); + ASSERT_EQ(attr.value.u32, mqNum); + + // Verify total queue number + attr.id = SAI_SWITCH_ATTR_NUMBER_OF_QUEUES; + ASSERT_EQ(sw.get(SAI_OBJECT_TYPE_SWITCH, 0x2100000000, 1, &attr), SAI_STATUS_SUCCESS); + ASSERT_EQ(attr.value.u32, qNum); +} diff --git a/unittest/vslib/TestSwitchMLNX2700.cpp b/unittest/vslib/TestSwitchMLNX2700.cpp index 157497ef..5e1cd23a 100644 --- a/unittest/vslib/TestSwitchMLNX2700.cpp +++ b/unittest/vslib/TestSwitchMLNX2700.cpp @@ -139,6 +139,33 @@ TEST_F(SwitchMLNX2700Test, portBulkAddRemove) } } +TEST_F(SwitchMLNX2700Test, switchQueueNumberGet) +{ + // Initialize switch state + ASSERT_EQ(m_ss->initialize_default_objects(0, nullptr), SAI_STATUS_SUCCESS); + + const sai_uint32_t uqNum = 8; + const sai_uint32_t mqNum = 8; + const sai_uint32_t qNum = uqNum + mqNum; + + sai_attribute_t attr; + + // Verify unicast queue number + attr.id = SAI_SWITCH_ATTR_NUMBER_OF_UNICAST_QUEUES; + ASSERT_EQ(m_ss->get(SAI_OBJECT_TYPE_SWITCH, m_swid, 1, &attr), SAI_STATUS_SUCCESS); + ASSERT_EQ(attr.value.u32, uqNum); + + // Verify multicast queue number + attr.id = SAI_SWITCH_ATTR_NUMBER_OF_MULTICAST_QUEUES; + ASSERT_EQ(m_ss->get(SAI_OBJECT_TYPE_SWITCH, m_swid, 1, &attr), SAI_STATUS_SUCCESS); + ASSERT_EQ(attr.value.u32, mqNum); + + // Verify total queue number + attr.id = SAI_SWITCH_ATTR_NUMBER_OF_QUEUES; + ASSERT_EQ(m_ss->get(SAI_OBJECT_TYPE_SWITCH, m_swid, 1, &attr), SAI_STATUS_SUCCESS); + ASSERT_EQ(attr.value.u32, qNum); +} + TEST(SwitchMLNX2700, ctr) { auto sc = std::make_shared(0, ""); @@ -600,17 +627,20 @@ TEST(SwitchMLNX2700, test_stats_query_capability) std::make_shared(0, scc), sc); - sai_stat_capability_t capability_list[91]; + std::vector capability_list; sai_stat_capability_list_t stats_capability; - stats_capability.count = 1; - stats_capability.list = capability_list; + /* Get queue stats capability */ + stats_capability.count = 0; + stats_capability.list = nullptr; + EXPECT_EQ(sw.queryStatsCapability(0x2100000000, SAI_OBJECT_TYPE_QUEUE, &stats_capability), SAI_STATUS_BUFFER_OVERFLOW); - stats_capability.count = SAI_QUEUE_STAT_DELAY_WATERMARK_NS; + capability_list.resize(stats_capability.count); + stats_capability.list = capability_list.data(); EXPECT_EQ(sw.queryStatsCapability(0x2100000000, SAI_OBJECT_TYPE_QUEUE, @@ -618,12 +648,16 @@ TEST(SwitchMLNX2700, test_stats_query_capability) SAI_STATUS_SUCCESS); /* Get port stats capability */ - stats_capability.count = 1; + stats_capability.count = 0; + stats_capability.list = nullptr; + EXPECT_EQ(sw.queryStatsCapability(0x2100000000, SAI_OBJECT_TYPE_PORT, &stats_capability), SAI_STATUS_BUFFER_OVERFLOW); - stats_capability.count = 91; + + capability_list.resize(stats_capability.count); + stats_capability.list = capability_list.data(); EXPECT_EQ(sw.queryStatsCapability(0x2100000000, SAI_OBJECT_TYPE_PORT, diff --git a/unittest/vslib/TestSwitchStateBase.cpp b/unittest/vslib/TestSwitchStateBase.cpp index 7772f673..771e79f5 100644 --- a/unittest/vslib/TestSwitchStateBase.cpp +++ b/unittest/vslib/TestSwitchStateBase.cpp @@ -174,6 +174,111 @@ TEST_F(SwitchStateBaseTest, switchHashAlgorithmCapabilitiesGet) ASSERT_EQ(haSet1, haSet2); } +TEST_F(SwitchStateBaseTest, switchPacketTrimmingDscpModeCapabilitiesGet) +{ + sai_s32_list_t data = { .count = 0, .list = nullptr }; + + auto status = m_ss->queryAttrEnumValuesCapability( + m_swid, SAI_OBJECT_TYPE_SWITCH, SAI_SWITCH_ATTR_PACKET_TRIM_DSCP_RESOLUTION_MODE, &data + ); + ASSERT_EQ(status, SAI_STATUS_BUFFER_OVERFLOW); + + std::vector qmList(data.count); + data.list = qmList.data(); + + status = m_ss->queryAttrEnumValuesCapability( + m_swid, SAI_OBJECT_TYPE_SWITCH, SAI_SWITCH_ATTR_PACKET_TRIM_DSCP_RESOLUTION_MODE, &data + ); + ASSERT_EQ(status, SAI_STATUS_SUCCESS); + + const std::set qmSet1 = { + SAI_PACKET_TRIM_DSCP_RESOLUTION_MODE_DSCP_VALUE, + SAI_PACKET_TRIM_DSCP_RESOLUTION_MODE_FROM_TC + }; + + std::set qmSet2; + + std::transform( + qmList.cbegin(), qmList.cend(), std::inserter(qmSet2, qmSet2.begin()), + [](sai_int32_t value) { return static_cast(value); } + ); + ASSERT_EQ(qmSet1, qmSet2); +} + +TEST_F(SwitchStateBaseTest, switchPacketTrimmingQueueModeCapabilitiesGet) +{ + sai_s32_list_t data = { .count = 0, .list = nullptr }; + + auto status = m_ss->queryAttrEnumValuesCapability( + m_swid, SAI_OBJECT_TYPE_SWITCH, SAI_SWITCH_ATTR_PACKET_TRIM_QUEUE_RESOLUTION_MODE, &data + ); + ASSERT_EQ(status, SAI_STATUS_BUFFER_OVERFLOW); + + std::vector qmList(data.count); + data.list = qmList.data(); + + status = m_ss->queryAttrEnumValuesCapability( + m_swid, SAI_OBJECT_TYPE_SWITCH, SAI_SWITCH_ATTR_PACKET_TRIM_QUEUE_RESOLUTION_MODE, &data + ); + ASSERT_EQ(status, SAI_STATUS_SUCCESS); + + const std::set qmSet1 = { + SAI_PACKET_TRIM_QUEUE_RESOLUTION_MODE_STATIC, + SAI_PACKET_TRIM_QUEUE_RESOLUTION_MODE_DYNAMIC + }; + + std::set qmSet2; + + std::transform( + qmList.cbegin(), qmList.cend(), std::inserter(qmSet2, qmSet2.begin()), + [](sai_int32_t value) { return static_cast(value); } + ); + ASSERT_EQ(qmSet1, qmSet2); +} + +TEST_F(SwitchStateBaseTest, bufferProfilePacketAdmissionFailActionCapabilitiesGet) +{ + sai_s32_list_t data = { .count = 0, .list = nullptr }; + + auto status = m_ss->queryAttrEnumValuesCapability( + m_swid, SAI_OBJECT_TYPE_BUFFER_PROFILE, SAI_BUFFER_PROFILE_ATTR_PACKET_ADMISSION_FAIL_ACTION, &data + ); + ASSERT_EQ(status, SAI_STATUS_BUFFER_OVERFLOW); + + std::vector paList(data.count); + data.list = paList.data(); + + status = m_ss->queryAttrEnumValuesCapability( + m_swid, SAI_OBJECT_TYPE_BUFFER_PROFILE, SAI_BUFFER_PROFILE_ATTR_PACKET_ADMISSION_FAIL_ACTION, &data + ); + ASSERT_EQ(status, SAI_STATUS_SUCCESS); + + const std::set paSet1 = { + SAI_BUFFER_PROFILE_PACKET_ADMISSION_FAIL_ACTION_DROP, + SAI_BUFFER_PROFILE_PACKET_ADMISSION_FAIL_ACTION_DROP_AND_TRIM + }; + + std::set paSet2; + + std::transform( + paList.cbegin(), paList.cend(), std::inserter(paSet2, paSet2.begin()), + [](sai_int32_t value) { return static_cast(value); } + ); + ASSERT_EQ(paSet1, paSet2); +} + +TEST_F(SwitchStateBaseTest, switchQoSMaxNumOfTrafficClasses) +{ + ASSERT_EQ(m_ss->set_maximum_number_of_traffic_classes(), SAI_STATUS_SUCCESS); + + sai_attribute_t attr; + attr.id = SAI_SWITCH_ATTR_QOS_MAX_NUMBER_OF_TRAFFIC_CLASSES; + ASSERT_EQ(m_ss->get(SAI_OBJECT_TYPE_SWITCH, sai_serialize_object_id(m_swid), 1, &attr), SAI_STATUS_SUCCESS); + + const sai_uint8_t maxTcNum = 16; + ASSERT_EQ(attr.value.u8, maxTcNum); +} + //Test the following function: //sai_status_t initialize_voq_switch_objects( // _In_ uint32_t attr_count, @@ -243,3 +348,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..b99dccca --- /dev/null +++ b/unittest/vslib/TestTAM.cpp @@ -0,0 +1,91 @@ +#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_id = 0x3c000000000001; + string tam_id_str = sai_serialize_object_id(tam_id); + + sai_object_id_t tam_tel_type_id = 0x4b000000000001; + string tam_tel_type_id_str = sai_serialize_object_id(tam_tel_type_id); + + sai_object_id_t tam_tel_id = 0x4b000000000002; + string tam_tel_id_str = sai_serialize_object_id(tam_tel_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, tam_id_str, switch_id, 0, nullptr)); + + EXPECT_EQ( + SAI_STATUS_SUCCESS, + ss.create(SAI_OBJECT_TYPE_TAM_TELEMETRY, tam_tel_id_str, switch_id, 0, nullptr)); + + 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)); + + + std::vector buffer(1024*1024*1024); + attr.id = SAI_TAM_TEL_TYPE_ATTR_IPFIX_TEMPLATES; + attr.value.u8list.count = static_cast(buffer.size()); + attr.value.u8list.list = buffer.data(); + EXPECT_EQ( + SAI_STATUS_SUCCESS, + ss.get(SAI_OBJECT_TYPE_TAM_TEL_TYPE, tam_tel_type_id_str, 1, &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 2b4427c4..8112b7e0 100644 --- a/unittest/vslib/TestVirtualSwitchSaiInterface.cpp +++ b/unittest/vslib/TestVirtualSwitchSaiInterface.cpp @@ -161,12 +161,12 @@ TEST_F(VirtualSwitchSaiInterfaceTest, bulkGet) TEST_F(VirtualSwitchSaiInterfaceTest, queryStatsCapability) { - sai_stat_capability_t capability_list[91]; + std::vector capability_list; sai_stat_capability_list_t stats_capability; - stats_capability.list = capability_list; /* Queue stats capability get */ - stats_capability.count = 1; + stats_capability.count = 0; + stats_capability.list = nullptr; EXPECT_EQ(SAI_STATUS_BUFFER_OVERFLOW, m_vssai->queryStatsCapability( @@ -174,6 +174,9 @@ TEST_F(VirtualSwitchSaiInterfaceTest, queryStatsCapability) SAI_OBJECT_TYPE_QUEUE, &stats_capability)); + capability_list.resize(stats_capability.count); + stats_capability.list = capability_list.data(); + EXPECT_EQ(SAI_STATUS_SUCCESS, m_vssai->queryStatsCapability( m_swid, @@ -181,7 +184,8 @@ TEST_F(VirtualSwitchSaiInterfaceTest, queryStatsCapability) &stats_capability)); /* Port stats capability get */ - stats_capability.count = 1; + stats_capability.count = 0; + stats_capability.list = nullptr; EXPECT_EQ(SAI_STATUS_BUFFER_OVERFLOW, m_vssai->queryStatsCapability( @@ -189,7 +193,9 @@ TEST_F(VirtualSwitchSaiInterfaceTest, queryStatsCapability) SAI_OBJECT_TYPE_PORT, &stats_capability)); - stats_capability.count = 91; + capability_list.resize(stats_capability.count); + stats_capability.list = capability_list.data(); + EXPECT_EQ(SAI_STATUS_SUCCESS, m_vssai->queryStatsCapability( m_swid, @@ -197,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/SwitchBCM56850.cpp b/vslib/SwitchBCM56850.cpp index 3ff0d520..38f949d3 100644 --- a/vslib/SwitchBCM56850.cpp +++ b/vslib/SwitchBCM56850.cpp @@ -36,7 +36,7 @@ sai_status_t SwitchBCM56850::create_qos_queues_per_port( sai_attribute_t attr; // 10 in and 10 out queues per port - const uint32_t port_qos_queues_count = 20; + const uint32_t port_qos_queues_count = m_unicastQueueNumber + m_multicastQueueNumber; std::vector queues; @@ -146,6 +146,36 @@ sai_status_t SwitchBCM56850::create_qos_queues() return SAI_STATUS_SUCCESS; } +sai_status_t SwitchBCM56850::set_number_of_queues() +{ + SWSS_LOG_ENTER(); + + SWSS_LOG_INFO("set number of unicast queues"); + + sai_attribute_t attr; + + attr.id = SAI_SWITCH_ATTR_NUMBER_OF_UNICAST_QUEUES; + attr.value.u32 = m_unicastQueueNumber; + + CHECK_STATUS(set(SAI_OBJECT_TYPE_SWITCH, m_switch_id, &attr)); + + SWSS_LOG_INFO("set number of multicast queues"); + + attr.id = SAI_SWITCH_ATTR_NUMBER_OF_MULTICAST_QUEUES; + attr.value.u32 = m_multicastQueueNumber; + + CHECK_STATUS(set(SAI_OBJECT_TYPE_SWITCH, m_switch_id, &attr)); + + SWSS_LOG_INFO("set number of queues"); + + attr.id = SAI_SWITCH_ATTR_NUMBER_OF_QUEUES; + attr.value.u32 = m_unicastQueueNumber + m_multicastQueueNumber; + + CHECK_STATUS(set(SAI_OBJECT_TYPE_SWITCH, m_switch_id, &attr)); + + return SAI_STATUS_SUCCESS; +} + sai_status_t SwitchBCM56850::create_port_serdes() { SWSS_LOG_ENTER(); diff --git a/vslib/SwitchBCM56850.h b/vslib/SwitchBCM56850.h index ce365142..20cc7239 100644 --- a/vslib/SwitchBCM56850.h +++ b/vslib/SwitchBCM56850.h @@ -32,6 +32,8 @@ namespace saivs virtual sai_status_t create_qos_queues() override; + virtual sai_status_t set_number_of_queues() override; + virtual sai_status_t create_scheduler_group_tree( _In_ const std::vector& sgs, _In_ sai_object_id_t port_id) override; @@ -51,5 +53,10 @@ namespace saivs virtual sai_status_t create_port_serdes_per_port( _In_ sai_object_id_t port_id) override; + + protected: + + constexpr static const uint32_t m_unicastQueueNumber = 10; + constexpr static const uint32_t m_multicastQueueNumber = 10; }; } diff --git a/vslib/SwitchBCM56971B0.cpp b/vslib/SwitchBCM56971B0.cpp index c9b33f1b..c5e2c40e 100644 --- a/vslib/SwitchBCM56971B0.cpp +++ b/vslib/SwitchBCM56971B0.cpp @@ -36,7 +36,7 @@ sai_status_t SwitchBCM56971B0::create_qos_queues_per_port( sai_attribute_t attr; // 10 in and 10 out queues per port - const uint32_t port_qos_queues_count = 20; + const uint32_t port_qos_queues_count = m_unicastQueueNumber + m_multicastQueueNumber; std::vector queues; @@ -146,6 +146,36 @@ sai_status_t SwitchBCM56971B0::create_qos_queues() return SAI_STATUS_SUCCESS; } +sai_status_t SwitchBCM56971B0::set_number_of_queues() +{ + SWSS_LOG_ENTER(); + + SWSS_LOG_INFO("set number of unicast queues"); + + sai_attribute_t attr; + + attr.id = SAI_SWITCH_ATTR_NUMBER_OF_UNICAST_QUEUES; + attr.value.u32 = m_unicastQueueNumber; + + CHECK_STATUS(set(SAI_OBJECT_TYPE_SWITCH, m_switch_id, &attr)); + + SWSS_LOG_INFO("set number of multicast queues"); + + attr.id = SAI_SWITCH_ATTR_NUMBER_OF_MULTICAST_QUEUES; + attr.value.u32 = m_multicastQueueNumber; + + CHECK_STATUS(set(SAI_OBJECT_TYPE_SWITCH, m_switch_id, &attr)); + + SWSS_LOG_INFO("set number of queues"); + + attr.id = SAI_SWITCH_ATTR_NUMBER_OF_QUEUES; + attr.value.u32 = m_unicastQueueNumber + m_multicastQueueNumber; + + CHECK_STATUS(set(SAI_OBJECT_TYPE_SWITCH, m_switch_id, &attr)); + + return SAI_STATUS_SUCCESS; +} + sai_status_t SwitchBCM56971B0::create_port_serdes() { SWSS_LOG_ENTER(); diff --git a/vslib/SwitchBCM56971B0.h b/vslib/SwitchBCM56971B0.h index 286146e4..0da6b46b 100644 --- a/vslib/SwitchBCM56971B0.h +++ b/vslib/SwitchBCM56971B0.h @@ -32,6 +32,8 @@ namespace saivs virtual sai_status_t create_qos_queues() override; + virtual sai_status_t set_number_of_queues() override; + virtual sai_status_t create_scheduler_group_tree( _In_ const std::vector& sgs, _In_ sai_object_id_t port_id) override; @@ -51,5 +53,10 @@ namespace saivs virtual sai_status_t create_port_serdes_per_port( _In_ sai_object_id_t port_id) override; + + protected: + + constexpr static const uint32_t m_unicastQueueNumber = 10; + constexpr static const uint32_t m_multicastQueueNumber = 10; }; } diff --git a/vslib/SwitchMLNX2700.cpp b/vslib/SwitchMLNX2700.cpp index 4ebdcba8..1d5cb403 100644 --- a/vslib/SwitchMLNX2700.cpp +++ b/vslib/SwitchMLNX2700.cpp @@ -34,7 +34,7 @@ sai_status_t SwitchMLNX2700::create_qos_queues_per_port( SWSS_LOG_ENTER(); // 8 in and 8 out queues per port - const uint32_t port_qos_queues_count = 16; + const uint32_t port_qos_queues_count = m_unicastQueueNumber + m_multicastQueueNumber; std::vector queues; for (uint32_t i = 0; i < port_qos_queues_count; ++i) @@ -91,6 +91,36 @@ sai_status_t SwitchMLNX2700::create_qos_queues() return SAI_STATUS_SUCCESS; } +sai_status_t SwitchMLNX2700::set_number_of_queues() +{ + SWSS_LOG_ENTER(); + + SWSS_LOG_INFO("set number of unicast queues"); + + sai_attribute_t attr; + + attr.id = SAI_SWITCH_ATTR_NUMBER_OF_UNICAST_QUEUES; + attr.value.u32 = m_unicastQueueNumber; + + CHECK_STATUS(set(SAI_OBJECT_TYPE_SWITCH, m_switch_id, &attr)); + + SWSS_LOG_INFO("set number of multicast queues"); + + attr.id = SAI_SWITCH_ATTR_NUMBER_OF_MULTICAST_QUEUES; + attr.value.u32 = m_multicastQueueNumber; + + CHECK_STATUS(set(SAI_OBJECT_TYPE_SWITCH, m_switch_id, &attr)); + + SWSS_LOG_INFO("set number of queues"); + + attr.id = SAI_SWITCH_ATTR_NUMBER_OF_QUEUES; + attr.value.u32 = m_unicastQueueNumber + m_multicastQueueNumber; + + CHECK_STATUS(set(SAI_OBJECT_TYPE_SWITCH, m_switch_id, &attr)); + + return SAI_STATUS_SUCCESS; +} + sai_status_t SwitchMLNX2700::create_scheduler_group_tree( _In_ const std::vector& sgs, _In_ sai_object_id_t port_id) diff --git a/vslib/SwitchMLNX2700.h b/vslib/SwitchMLNX2700.h index 26e1cc95..81a4a2b6 100644 --- a/vslib/SwitchMLNX2700.h +++ b/vslib/SwitchMLNX2700.h @@ -29,6 +29,8 @@ namespace saivs virtual sai_status_t create_qos_queues() override; + virtual sai_status_t set_number_of_queues() override; + virtual sai_status_t create_scheduler_group_tree( _In_ const std::vector& sgs, _In_ sai_object_id_t port_id) override; @@ -56,5 +58,9 @@ namespace saivs _Inout_ sai_s32_list_t *enum_values_capability) override; virtual sai_status_t queryPortAutonegFecOverrideSupportCapability( _Out_ sai_attr_capability_t *attr_capability) override; + + protected: + constexpr static const uint32_t m_unicastQueueNumber = 8; + constexpr static const uint32_t m_multicastQueueNumber = 8; }; } 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 d24f2f27..c1c6bd94 100644 --- a/vslib/SwitchStateBase.cpp +++ b/vslib/SwitchStateBase.cpp @@ -2,11 +2,14 @@ #include "swss/logger.h" #include "meta/sai_serialize.h" +#include "meta/NotificationTamTelTypeConfigChange.h" +#include "EventPayloadNotification.h" #include #include #include +#include #define SAI_VS_MAX_PORTS 1024 @@ -185,6 +188,20 @@ sai_status_t SwitchStateBase::create( return createVoqSystemNeighborEntry(serializedObjectId, switch_id, attr_count, attr_list); } + if (object_type == SAI_OBJECT_TYPE_TAM) + { + sai_object_id_t object_id; + sai_deserialize_object_id(serializedObjectId, object_id); + return createTam(object_id, switch_id, attr_count, attr_list); + } + + if (object_type == SAI_OBJECT_TYPE_TAM_TELEMETRY) + { + sai_object_id_t object_id; + sai_deserialize_object_id(serializedObjectId, object_id); + return createTamTelemetry(object_id, switch_id, attr_count, attr_list); + } + return create_internal(object_type, serializedObjectId, switch_id, attr_count, attr_list); } @@ -501,6 +518,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 +562,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 +1051,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; @@ -1109,6 +1153,18 @@ sai_status_t SwitchStateBase::set_static_crm_values() return set_static_acl_resource_list(SAI_SWITCH_ATTR_AVAILABLE_ACL_TABLE_GROUP, m_maxAclTableGroups); } +sai_status_t SwitchStateBase::set_initial_tam_objects() +{ + SWSS_LOG_ENTER(); + + sai_attribute_t attr; + attr.id = SAI_SWITCH_ATTR_TAM_OBJECT_ID; + attr.value.objlist.count = 0; + attr.value.objlist.list = nullptr; + + return set(SAI_OBJECT_TYPE_SWITCH, m_switch_id, &attr); +} + sai_status_t SwitchStateBase::set_static_acl_resource_list( _In_ sai_switch_attr_t acl_resource, _In_ int max_count) @@ -1294,6 +1350,11 @@ sai_status_t SwitchStateBase::create_ports() attr.value.u32 = SAI_PORT_HOST_TX_READY_STATUS_READY; CHECK_STATUS(set(SAI_OBJECT_TYPE_PORT, port_id, &attr)); + + attr.id = SAI_PORT_ATTR_AUTO_NEG_MODE; + attr.value.booldata = true; + + CHECK_STATUS(set(SAI_OBJECT_TYPE_PORT, port_id, &attr)); } return SAI_STATUS_SUCCESS; @@ -1622,6 +1683,15 @@ sai_status_t SwitchStateBase::create_qos_queues() return SAI_STATUS_NOT_IMPLEMENTED; } +sai_status_t SwitchStateBase::set_number_of_queues() +{ + SWSS_LOG_ENTER(); + + SWSS_LOG_ERROR("implement in child class"); + + return SAI_STATUS_NOT_IMPLEMENTED; +} + sai_status_t SwitchStateBase::create_scheduler_group_tree( _In_ const std::vector& sgs, _In_ sai_object_id_t port_id) @@ -1659,6 +1729,20 @@ sai_status_t SwitchStateBase::create_scheduler_groups() return SAI_STATUS_SUCCESS; } +sai_status_t SwitchStateBase::set_maximum_number_of_traffic_classes() +{ + SWSS_LOG_ENTER(); + + SWSS_LOG_INFO("set number of traffic classes"); + + sai_attribute_t attr; + + attr.id = SAI_SWITCH_ATTR_QOS_MAX_NUMBER_OF_TRAFFIC_CLASSES; + attr.value.u8 = 16; + + return set(SAI_OBJECT_TYPE_SWITCH, m_switch_id, &attr); +} + sai_status_t SwitchStateBase::set_maximum_number_of_childs_per_scheduler_group() { SWSS_LOG_ENTER(); @@ -1725,11 +1809,14 @@ sai_status_t SwitchStateBase::initialize_default_objects( CHECK_STATUS(set_acl_capabilities()); CHECK_STATUS(create_ingress_priority_groups()); CHECK_STATUS(create_qos_queues()); + CHECK_STATUS(set_number_of_queues()); + CHECK_STATUS(set_maximum_number_of_traffic_classes()); CHECK_STATUS(set_maximum_number_of_childs_per_scheduler_group()); CHECK_STATUS(set_number_of_ecmp_groups()); CHECK_STATUS(set_switch_default_attributes()); CHECK_STATUS(create_scheduler_groups()); CHECK_STATUS(set_static_crm_values()); + CHECK_STATUS(set_initial_tam_objects()); // Initialize switch for VOQ attributes @@ -1763,6 +1850,11 @@ sai_status_t SwitchStateBase::create_port_dependencies( CHECK_STATUS(set(SAI_OBJECT_TYPE_PORT, port_id, &attr)); + attr.id = SAI_PORT_ATTR_AUTO_NEG_MODE; + attr.value.booldata = true; + + CHECK_STATUS(set(SAI_OBJECT_TYPE_PORT, port_id, &attr)); + // attributes are not required since they will be set outside this function CHECK_STATUS(create_ingress_priority_groups_per_port(port_id)); @@ -2037,6 +2129,12 @@ sai_status_t SwitchStateBase::warm_update_switch() CHECK_STATUS(set_acl_capabilities()); } + attr.id = SAI_SWITCH_ATTR_TAM_OBJECT_ID; + if (get(SAI_OBJECT_TYPE_SWITCH, m_switch_id, 1, &attr) != SAI_STATUS_SUCCESS) + { + CHECK_STATUS(set_initial_tam_objects()); + } + // check for default supported object types attr.id = SAI_SWITCH_ATTR_SUPPORTED_OBJECT_TYPE_LIST; @@ -2431,10 +2529,16 @@ sai_status_t SwitchStateBase::refresh_read_only( case SAI_SWITCH_ATTR_NUMBER_OF_ECMP_GROUPS: return SAI_STATUS_SUCCESS; + case SAI_SWITCH_ATTR_NUMBER_OF_UNICAST_QUEUES: + case SAI_SWITCH_ATTR_NUMBER_OF_MULTICAST_QUEUES: + case SAI_SWITCH_ATTR_NUMBER_OF_QUEUES: + return SAI_STATUS_SUCCESS; + case SAI_SWITCH_ATTR_PORT_NUMBER: case SAI_SWITCH_ATTR_PORT_LIST: return refresh_port_list(meta); + case SAI_SWITCH_ATTR_QOS_MAX_NUMBER_OF_TRAFFIC_CLASSES: case SAI_SWITCH_ATTR_QOS_MAX_NUMBER_OF_CHILDS_PER_SCHEDULER_GROUP: return SAI_STATUS_SUCCESS; @@ -2571,6 +2675,11 @@ sai_status_t SwitchStateBase::refresh_read_only( return refresh_acl_table_counters(object_id); } + if (meta->objecttype == SAI_OBJECT_TYPE_TAM_TEL_TYPE && meta->attrid == SAI_TAM_TEL_TYPE_ATTR_IPFIX_TEMPLATES) + { + return refresh_tam_tel_ipfix_templates(object_id); + } + auto mmeta = m_meta.lock(); if (mmeta) @@ -3880,6 +3989,60 @@ sai_status_t SwitchStateBase::querySwitchHashAlgorithmCapability( return SAI_STATUS_SUCCESS; } +sai_status_t SwitchStateBase::querySwitchPacketTrimmingDscpResolutionModeCapability( + _Inout_ sai_s32_list_t *enum_values_capability) +{ + SWSS_LOG_ENTER(); + + if (enum_values_capability->count < 2) + { + enum_values_capability->count = 2; + return SAI_STATUS_BUFFER_OVERFLOW; + } + + enum_values_capability->count = 2; + enum_values_capability->list[0] = SAI_PACKET_TRIM_DSCP_RESOLUTION_MODE_DSCP_VALUE; + enum_values_capability->list[1] = SAI_PACKET_TRIM_DSCP_RESOLUTION_MODE_FROM_TC; + + return SAI_STATUS_SUCCESS; +} + +sai_status_t SwitchStateBase::querySwitchPacketTrimmingQueueResolutionModeCapability( + _Inout_ sai_s32_list_t *enum_values_capability) +{ + SWSS_LOG_ENTER(); + + if (enum_values_capability->count < 2) + { + enum_values_capability->count = 2; + return SAI_STATUS_BUFFER_OVERFLOW; + } + + enum_values_capability->count = 2; + enum_values_capability->list[0] = SAI_PACKET_TRIM_QUEUE_RESOLUTION_MODE_STATIC; + enum_values_capability->list[1] = SAI_PACKET_TRIM_QUEUE_RESOLUTION_MODE_DYNAMIC; + + return SAI_STATUS_SUCCESS; +} + +sai_status_t SwitchStateBase::queryBufferProfilePacketAdmissionFailActionCapability( + _Inout_ sai_s32_list_t *enum_values_capability) +{ + SWSS_LOG_ENTER(); + + if (enum_values_capability->count < 2) + { + enum_values_capability->count = 2; + return SAI_STATUS_BUFFER_OVERFLOW; + } + + enum_values_capability->count = 2; + enum_values_capability->list[0] = SAI_BUFFER_PROFILE_PACKET_ADMISSION_FAIL_ACTION_DROP; + enum_values_capability->list[1] = SAI_BUFFER_PROFILE_PACKET_ADMISSION_FAIL_ACTION_DROP_AND_TRIM; + + return SAI_STATUS_SUCCESS; +} + sai_status_t SwitchStateBase::queryAttrEnumValuesCapability( _In_ sai_object_id_t switch_id, _In_ sai_object_type_t object_type, @@ -3911,6 +4074,18 @@ sai_status_t SwitchStateBase::queryAttrEnumValuesCapability( { return querySwitchHashAlgorithmCapability(enum_values_capability); } + else if (object_type == SAI_OBJECT_TYPE_SWITCH && attr_id == SAI_SWITCH_ATTR_PACKET_TRIM_DSCP_RESOLUTION_MODE) + { + return querySwitchPacketTrimmingDscpResolutionModeCapability(enum_values_capability); + } + else if (object_type == SAI_OBJECT_TYPE_SWITCH && attr_id == SAI_SWITCH_ATTR_PACKET_TRIM_QUEUE_RESOLUTION_MODE) + { + return querySwitchPacketTrimmingQueueResolutionModeCapability(enum_values_capability); + } + else if (object_type == SAI_OBJECT_TYPE_BUFFER_PROFILE && attr_id == SAI_BUFFER_PROFILE_ATTR_PACKET_ADMISSION_FAIL_ACTION) + { + return queryBufferProfilePacketAdmissionFailActionCapability(enum_values_capability); + } return SAI_STATUS_NOT_SUPPORTED; } @@ -3934,154 +4109,361 @@ sai_status_t SwitchStateBase::queryAttributeCapability( return SAI_STATUS_SUCCESS; } +sai_status_t SwitchStateBase::queryPortStatsCapability( + _Inout_ sai_stat_capability_list_t *stats_capability) +{ + SWSS_LOG_ENTER(); + + static std::vector portStatList = { + SAI_PORT_STAT_IF_IN_OCTETS, + SAI_PORT_STAT_IF_IN_UCAST_PKTS, + SAI_PORT_STAT_IF_IN_NON_UCAST_PKTS, + SAI_PORT_STAT_IF_IN_DISCARDS, + SAI_PORT_STAT_IF_IN_ERRORS, + SAI_PORT_STAT_IF_IN_UNKNOWN_PROTOS, + SAI_PORT_STAT_IF_IN_BROADCAST_PKTS, + SAI_PORT_STAT_IF_IN_MULTICAST_PKTS, + SAI_PORT_STAT_IF_IN_VLAN_DISCARDS, + SAI_PORT_STAT_IF_OUT_OCTETS, + SAI_PORT_STAT_IF_OUT_UCAST_PKTS, + SAI_PORT_STAT_IF_OUT_NON_UCAST_PKTS, + SAI_PORT_STAT_IF_OUT_DISCARDS, + SAI_PORT_STAT_IF_OUT_ERRORS, + SAI_PORT_STAT_IF_OUT_QLEN, + SAI_PORT_STAT_IF_OUT_BROADCAST_PKTS, + SAI_PORT_STAT_IF_OUT_MULTICAST_PKTS, + SAI_PORT_STAT_ETHER_STATS_DROP_EVENTS, + SAI_PORT_STAT_ETHER_STATS_MULTICAST_PKTS, + SAI_PORT_STAT_ETHER_STATS_BROADCAST_PKTS, + SAI_PORT_STAT_ETHER_STATS_UNDERSIZE_PKTS, + SAI_PORT_STAT_ETHER_STATS_FRAGMENTS, + SAI_PORT_STAT_ETHER_STATS_PKTS_64_OCTETS, + SAI_PORT_STAT_ETHER_STATS_PKTS_65_TO_127_OCTETS, + SAI_PORT_STAT_ETHER_STATS_PKTS_128_TO_255_OCTETS, + SAI_PORT_STAT_ETHER_STATS_PKTS_256_TO_511_OCTETS, + SAI_PORT_STAT_ETHER_STATS_PKTS_512_TO_1023_OCTETS, + SAI_PORT_STAT_ETHER_STATS_PKTS_1024_TO_1518_OCTETS, + SAI_PORT_STAT_ETHER_STATS_PKTS_1519_TO_2047_OCTETS, + SAI_PORT_STAT_ETHER_STATS_PKTS_2048_TO_4095_OCTETS, + SAI_PORT_STAT_ETHER_STATS_PKTS_4096_TO_9216_OCTETS, + SAI_PORT_STAT_ETHER_STATS_PKTS_9217_TO_16383_OCTETS, + SAI_PORT_STAT_ETHER_STATS_OVERSIZE_PKTS, + SAI_PORT_STAT_ETHER_RX_OVERSIZE_PKTS, + SAI_PORT_STAT_ETHER_TX_OVERSIZE_PKTS, + SAI_PORT_STAT_ETHER_STATS_JABBERS, + SAI_PORT_STAT_ETHER_STATS_OCTETS, + SAI_PORT_STAT_ETHER_STATS_PKTS, + SAI_PORT_STAT_ETHER_STATS_COLLISIONS, + SAI_PORT_STAT_ETHER_STATS_CRC_ALIGN_ERRORS, + SAI_PORT_STAT_ETHER_STATS_TX_NO_ERRORS, + SAI_PORT_STAT_ETHER_STATS_RX_NO_ERRORS, + SAI_PORT_STAT_GREEN_WRED_DROPPED_PACKETS, + SAI_PORT_STAT_GREEN_WRED_DROPPED_BYTES, + SAI_PORT_STAT_YELLOW_WRED_DROPPED_PACKETS, + SAI_PORT_STAT_YELLOW_WRED_DROPPED_BYTES, + SAI_PORT_STAT_RED_WRED_DROPPED_PACKETS, + SAI_PORT_STAT_RED_WRED_DROPPED_BYTES, + SAI_PORT_STAT_WRED_DROPPED_PACKETS, + SAI_PORT_STAT_WRED_DROPPED_BYTES, + SAI_PORT_STAT_ECN_MARKED_PACKETS, + SAI_PORT_STAT_PFC_0_RX_PKTS, + SAI_PORT_STAT_PFC_0_TX_PKTS, + SAI_PORT_STAT_PFC_1_RX_PKTS, + SAI_PORT_STAT_PFC_1_TX_PKTS, + SAI_PORT_STAT_PFC_2_RX_PKTS, + SAI_PORT_STAT_PFC_2_TX_PKTS, + SAI_PORT_STAT_PFC_3_RX_PKTS, + SAI_PORT_STAT_PFC_3_TX_PKTS, + SAI_PORT_STAT_PFC_4_RX_PKTS, + SAI_PORT_STAT_PFC_4_TX_PKTS, + SAI_PORT_STAT_PFC_5_RX_PKTS, + SAI_PORT_STAT_PFC_5_TX_PKTS, + SAI_PORT_STAT_PFC_6_RX_PKTS, + SAI_PORT_STAT_PFC_6_TX_PKTS, + SAI_PORT_STAT_PFC_7_RX_PKTS, + SAI_PORT_STAT_PFC_7_TX_PKTS, + SAI_PORT_STAT_PFC_0_RX_PAUSE_DURATION_US, + SAI_PORT_STAT_PFC_0_TX_PAUSE_DURATION_US, + SAI_PORT_STAT_PFC_1_RX_PAUSE_DURATION_US, + SAI_PORT_STAT_PFC_1_TX_PAUSE_DURATION_US, + SAI_PORT_STAT_PFC_2_RX_PAUSE_DURATION_US, + SAI_PORT_STAT_PFC_2_TX_PAUSE_DURATION_US, + SAI_PORT_STAT_PFC_3_RX_PAUSE_DURATION_US, + SAI_PORT_STAT_PFC_3_TX_PAUSE_DURATION_US, + SAI_PORT_STAT_PFC_4_RX_PAUSE_DURATION_US, + SAI_PORT_STAT_PFC_4_TX_PAUSE_DURATION_US, + SAI_PORT_STAT_PFC_5_RX_PAUSE_DURATION_US, + SAI_PORT_STAT_PFC_5_TX_PAUSE_DURATION_US, + SAI_PORT_STAT_PFC_6_RX_PAUSE_DURATION_US, + SAI_PORT_STAT_PFC_6_TX_PAUSE_DURATION_US, + SAI_PORT_STAT_PFC_7_RX_PAUSE_DURATION_US, + SAI_PORT_STAT_PFC_7_TX_PAUSE_DURATION_US, + SAI_PORT_STAT_PFC_0_ON2OFF_RX_PKTS, + SAI_PORT_STAT_PFC_1_ON2OFF_RX_PKTS, + SAI_PORT_STAT_PFC_2_ON2OFF_RX_PKTS, + SAI_PORT_STAT_PFC_3_ON2OFF_RX_PKTS, + SAI_PORT_STAT_PFC_4_ON2OFF_RX_PKTS, + SAI_PORT_STAT_PFC_5_ON2OFF_RX_PKTS, + SAI_PORT_STAT_PFC_6_ON2OFF_RX_PKTS, + SAI_PORT_STAT_PFC_7_ON2OFF_RX_PKTS, + SAI_PORT_STAT_TRIM_PACKETS + }; + + if (stats_capability->count < portStatList.size()) + { + stats_capability->count = static_cast(portStatList.size()); + return SAI_STATUS_BUFFER_OVERFLOW; + } + + stats_capability->count = static_cast(portStatList.size()); + + for (std::uint32_t i = 0; i < portStatList.size(); i++) + { + stats_capability->list[i].stat_modes = SAI_STATS_MODE_READ_AND_CLEAR | SAI_STATS_MODE_READ; + stats_capability->list[i].stat_enum = static_cast(portStatList.at(i)); + } + + return SAI_STATUS_SUCCESS; +} + +sai_status_t SwitchStateBase::queryQueueStatsCapability( + _Inout_ sai_stat_capability_list_t *stats_capability) +{ + SWSS_LOG_ENTER(); + + static std::vector queueStatList = { + SAI_QUEUE_STAT_PACKETS, + SAI_QUEUE_STAT_BYTES, + SAI_QUEUE_STAT_DROPPED_PACKETS, + SAI_QUEUE_STAT_DROPPED_BYTES, + SAI_QUEUE_STAT_WRED_DROPPED_PACKETS, + SAI_QUEUE_STAT_WRED_DROPPED_BYTES, + SAI_QUEUE_STAT_CURR_OCCUPANCY_BYTES, + SAI_QUEUE_STAT_SHARED_WATERMARK_BYTES, + SAI_QUEUE_STAT_WRED_ECN_MARKED_PACKETS, + SAI_QUEUE_STAT_WRED_ECN_MARKED_BYTES, + SAI_QUEUE_STAT_CURR_OCCUPANCY_LEVEL, + SAI_QUEUE_STAT_WATERMARK_LEVEL, + SAI_QUEUE_STAT_CREDIT_WD_DELETED_PACKETS, + SAI_QUEUE_STAT_TRIM_PACKETS + }; + + if (stats_capability->count < queueStatList.size()) + { + stats_capability->count = static_cast(queueStatList.size()); + return SAI_STATUS_BUFFER_OVERFLOW; + } + + stats_capability->count = static_cast(queueStatList.size()); + + for (std::uint32_t i = 0; i < queueStatList.size(); i++) + { + stats_capability->list[i].stat_modes = SAI_STATS_MODE_READ_AND_CLEAR | SAI_STATS_MODE_READ; + stats_capability->list[i].stat_enum = static_cast(queueStatList.at(i)); + } + + return SAI_STATUS_SUCCESS; +} + sai_status_t SwitchStateBase::queryStatsCapability( _In_ sai_object_id_t switchId, _In_ sai_object_type_t objectType, _Inout_ sai_stat_capability_list_t *stats_capability) { SWSS_LOG_ENTER(); - uint32_t i = 0; - uint32_t stats_count = 0; if (objectType == SAI_OBJECT_TYPE_QUEUE) { - stats_count = SAI_QUEUE_STAT_DELAY_WATERMARK_NS; - if (stats_capability->count < stats_count ) - { - stats_capability->count = stats_count; - return SAI_STATUS_BUFFER_OVERFLOW; - } + return queryQueueStatsCapability(stats_capability); + } + else if (objectType == SAI_OBJECT_TYPE_PORT) + { + return queryPortStatsCapability(stats_capability); + } + + return SAI_STATUS_NOT_SUPPORTED; +} + +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_st_capability) +{ + SWSS_LOG_ENTER(); - stats_capability->count = stats_count; + 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(); - for(i = 0; i < stats_capability->count; i++) + 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_capability->list[i].stat_modes = SAI_STATS_MODE_READ_AND_CLEAR | SAI_STATS_MODE_READ ; - stats_capability->list[i].stat_enum = 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 SAI_STATUS_SUCCESS; + 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); } - else if (objectType == SAI_OBJECT_TYPE_PORT) + + 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) { - if (stats_capability->count < 91) - { - stats_capability->count = 91; - return SAI_STATUS_BUFFER_OVERFLOW; - } + 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)); +} + +sai_status_t SwitchStateBase::refresh_tam_tel_ipfix_templates(sai_object_id_t tam_tel_type_id) +{ + SWSS_LOG_ENTER(); + + std::vector ipfix_templates; + + // TODO: This is a placeholder for the actual logic to generate IPFIX templates. + std::random_device rd; + std::mt19937 gen(rd()); + std::uniform_int_distribution dist(0, 255); + ipfix_templates.resize(64 * 1024); + + for (size_t i = 0; i < ipfix_templates.size(); ++i) + { + ipfix_templates[i] = static_cast(dist(gen)); + } + + + sai_attribute_t attr; + attr.id = SAI_TAM_TEL_TYPE_ATTR_IPFIX_TEMPLATES; + attr.value.u8list.count = static_cast(ipfix_templates.size()); + attr.value.u8list.list = ipfix_templates.data(); + sai_status_t status = set(SAI_OBJECT_TYPE_TAM_TEL_TYPE, tam_tel_type_id, &attr); + if (status != SAI_STATUS_SUCCESS) + { + SWSS_LOG_ERROR("Failed to set IPFIX templates for TAM Tel Type %s, status: %s", + sai_serialize_object_id(tam_tel_type_id).c_str(), + sai_serialize_status(status).c_str()); + } + else + { + SWSS_LOG_INFO("Successfully set IPFIX templates for TAM Tel Type %s", + sai_serialize_object_id(tam_tel_type_id).c_str()); + } + + return status; +} + +sai_status_t SwitchStateBase::createTam( + sai_object_id_t tam_id, + sai_object_id_t switch_id, + uint32_t attr_count, + const sai_attribute_t *attr_list) +{ + SWSS_LOG_ENTER(); - stats_capability->count = 91; - stats_capability->list[0].stat_enum = SAI_PORT_STAT_IF_IN_OCTETS; - stats_capability->list[1].stat_enum = SAI_PORT_STAT_IF_IN_UCAST_PKTS; - stats_capability->list[2].stat_enum = SAI_PORT_STAT_IF_IN_NON_UCAST_PKTS; - stats_capability->list[3].stat_enum = SAI_PORT_STAT_IF_IN_DISCARDS; - stats_capability->list[4].stat_enum = SAI_PORT_STAT_IF_IN_ERRORS; - stats_capability->list[5].stat_enum = SAI_PORT_STAT_IF_IN_UNKNOWN_PROTOS; - stats_capability->list[6].stat_enum = SAI_PORT_STAT_IF_IN_BROADCAST_PKTS; - stats_capability->list[7].stat_enum = SAI_PORT_STAT_IF_IN_MULTICAST_PKTS; - stats_capability->list[8].stat_enum = SAI_PORT_STAT_IF_IN_VLAN_DISCARDS; - stats_capability->list[9].stat_enum = SAI_PORT_STAT_IF_OUT_OCTETS; - stats_capability->list[10].stat_enum = SAI_PORT_STAT_IF_OUT_UCAST_PKTS; - stats_capability->list[11].stat_enum = SAI_PORT_STAT_IF_OUT_NON_UCAST_PKTS; - stats_capability->list[12].stat_enum = SAI_PORT_STAT_IF_OUT_DISCARDS; - stats_capability->list[13].stat_enum = SAI_PORT_STAT_IF_OUT_ERRORS; - stats_capability->list[14].stat_enum = SAI_PORT_STAT_IF_OUT_QLEN; - stats_capability->list[15].stat_enum = SAI_PORT_STAT_IF_OUT_BROADCAST_PKTS; - stats_capability->list[16].stat_enum = SAI_PORT_STAT_IF_OUT_MULTICAST_PKTS; - stats_capability->list[17].stat_enum = SAI_PORT_STAT_ETHER_STATS_DROP_EVENTS; - stats_capability->list[18].stat_enum = SAI_PORT_STAT_ETHER_STATS_MULTICAST_PKTS; - stats_capability->list[19].stat_enum = SAI_PORT_STAT_ETHER_STATS_BROADCAST_PKTS; - stats_capability->list[20].stat_enum = SAI_PORT_STAT_ETHER_STATS_UNDERSIZE_PKTS; - stats_capability->list[21].stat_enum = SAI_PORT_STAT_ETHER_STATS_FRAGMENTS; - stats_capability->list[22].stat_enum = SAI_PORT_STAT_ETHER_STATS_PKTS_64_OCTETS; - stats_capability->list[23].stat_enum = SAI_PORT_STAT_ETHER_STATS_PKTS_65_TO_127_OCTETS; - stats_capability->list[24].stat_enum = SAI_PORT_STAT_ETHER_STATS_PKTS_128_TO_255_OCTETS; - stats_capability->list[25].stat_enum = SAI_PORT_STAT_ETHER_STATS_PKTS_256_TO_511_OCTETS; - stats_capability->list[26].stat_enum = SAI_PORT_STAT_ETHER_STATS_PKTS_512_TO_1023_OCTETS; - stats_capability->list[27].stat_enum = SAI_PORT_STAT_ETHER_STATS_PKTS_1024_TO_1518_OCTETS; - stats_capability->list[28].stat_enum = SAI_PORT_STAT_ETHER_STATS_PKTS_1519_TO_2047_OCTETS; - stats_capability->list[29].stat_enum = SAI_PORT_STAT_ETHER_STATS_PKTS_2048_TO_4095_OCTETS; - stats_capability->list[30].stat_enum = SAI_PORT_STAT_ETHER_STATS_PKTS_4096_TO_9216_OCTETS; - stats_capability->list[31].stat_enum = SAI_PORT_STAT_ETHER_STATS_PKTS_9217_TO_16383_OCTETS; - stats_capability->list[32].stat_enum = SAI_PORT_STAT_ETHER_STATS_OVERSIZE_PKTS; - stats_capability->list[33].stat_enum = SAI_PORT_STAT_ETHER_RX_OVERSIZE_PKTS; - stats_capability->list[34].stat_enum = SAI_PORT_STAT_ETHER_TX_OVERSIZE_PKTS; - stats_capability->list[35].stat_enum = SAI_PORT_STAT_ETHER_STATS_JABBERS; - stats_capability->list[36].stat_enum = SAI_PORT_STAT_ETHER_STATS_OCTETS; - stats_capability->list[37].stat_enum = SAI_PORT_STAT_ETHER_STATS_PKTS; - stats_capability->list[38].stat_enum = SAI_PORT_STAT_ETHER_STATS_COLLISIONS; - stats_capability->list[39].stat_enum = SAI_PORT_STAT_ETHER_STATS_CRC_ALIGN_ERRORS; - stats_capability->list[40].stat_enum = SAI_PORT_STAT_ETHER_STATS_TX_NO_ERRORS; - stats_capability->list[41].stat_enum = SAI_PORT_STAT_ETHER_STATS_RX_NO_ERRORS; - stats_capability->list[42].stat_enum = SAI_PORT_STAT_GREEN_WRED_DROPPED_PACKETS; - stats_capability->list[43].stat_enum = SAI_PORT_STAT_GREEN_WRED_DROPPED_BYTES; - stats_capability->list[44].stat_enum = SAI_PORT_STAT_YELLOW_WRED_DROPPED_PACKETS; - stats_capability->list[45].stat_enum = SAI_PORT_STAT_YELLOW_WRED_DROPPED_BYTES; - stats_capability->list[46].stat_enum = SAI_PORT_STAT_RED_WRED_DROPPED_PACKETS; - stats_capability->list[47].stat_enum = SAI_PORT_STAT_RED_WRED_DROPPED_BYTES; - stats_capability->list[48].stat_enum = SAI_PORT_STAT_WRED_DROPPED_PACKETS; - stats_capability->list[49].stat_enum = SAI_PORT_STAT_WRED_DROPPED_BYTES; - stats_capability->list[50].stat_enum = SAI_PORT_STAT_ECN_MARKED_PACKETS; - stats_capability->list[51].stat_enum = SAI_PORT_STAT_PFC_0_RX_PKTS; - stats_capability->list[52].stat_enum = SAI_PORT_STAT_PFC_0_TX_PKTS; - stats_capability->list[53].stat_enum = SAI_PORT_STAT_PFC_1_RX_PKTS; - stats_capability->list[54].stat_enum = SAI_PORT_STAT_PFC_1_TX_PKTS; - stats_capability->list[55].stat_enum = SAI_PORT_STAT_PFC_2_RX_PKTS; - stats_capability->list[56].stat_enum = SAI_PORT_STAT_PFC_2_TX_PKTS; - stats_capability->list[57].stat_enum = SAI_PORT_STAT_PFC_3_RX_PKTS; - stats_capability->list[58].stat_enum = SAI_PORT_STAT_PFC_3_TX_PKTS; - stats_capability->list[59].stat_enum = SAI_PORT_STAT_PFC_4_RX_PKTS; - stats_capability->list[60].stat_enum = SAI_PORT_STAT_PFC_4_TX_PKTS; - stats_capability->list[61].stat_enum = SAI_PORT_STAT_PFC_5_RX_PKTS; - stats_capability->list[62].stat_enum = SAI_PORT_STAT_PFC_5_TX_PKTS; - stats_capability->list[63].stat_enum = SAI_PORT_STAT_PFC_6_RX_PKTS; - stats_capability->list[64].stat_enum = SAI_PORT_STAT_PFC_6_TX_PKTS; - stats_capability->list[65].stat_enum = SAI_PORT_STAT_PFC_7_RX_PKTS; - stats_capability->list[66].stat_enum = SAI_PORT_STAT_PFC_7_TX_PKTS; - stats_capability->list[67].stat_enum = SAI_PORT_STAT_PFC_0_RX_PAUSE_DURATION_US; - stats_capability->list[68].stat_enum = SAI_PORT_STAT_PFC_0_TX_PAUSE_DURATION_US; - stats_capability->list[69].stat_enum = SAI_PORT_STAT_PFC_1_RX_PAUSE_DURATION_US; - stats_capability->list[70].stat_enum = SAI_PORT_STAT_PFC_1_TX_PAUSE_DURATION_US; - stats_capability->list[71].stat_enum = SAI_PORT_STAT_PFC_2_RX_PAUSE_DURATION_US; - stats_capability->list[72].stat_enum = SAI_PORT_STAT_PFC_2_TX_PAUSE_DURATION_US; - stats_capability->list[73].stat_enum = SAI_PORT_STAT_PFC_3_RX_PAUSE_DURATION_US; - stats_capability->list[74].stat_enum = SAI_PORT_STAT_PFC_3_TX_PAUSE_DURATION_US; - stats_capability->list[75].stat_enum = SAI_PORT_STAT_PFC_4_RX_PAUSE_DURATION_US; - stats_capability->list[76].stat_enum = SAI_PORT_STAT_PFC_4_TX_PAUSE_DURATION_US; - stats_capability->list[77].stat_enum = SAI_PORT_STAT_PFC_5_RX_PAUSE_DURATION_US; - stats_capability->list[78].stat_enum = SAI_PORT_STAT_PFC_5_TX_PAUSE_DURATION_US; - stats_capability->list[79].stat_enum = SAI_PORT_STAT_PFC_6_RX_PAUSE_DURATION_US; - stats_capability->list[80].stat_enum = SAI_PORT_STAT_PFC_6_TX_PAUSE_DURATION_US; - stats_capability->list[81].stat_enum = SAI_PORT_STAT_PFC_7_RX_PAUSE_DURATION_US; - stats_capability->list[82].stat_enum = SAI_PORT_STAT_PFC_7_TX_PAUSE_DURATION_US; - stats_capability->list[83].stat_enum = SAI_PORT_STAT_PFC_0_ON2OFF_RX_PKTS; - stats_capability->list[84].stat_enum = SAI_PORT_STAT_PFC_1_ON2OFF_RX_PKTS; - stats_capability->list[85].stat_enum = SAI_PORT_STAT_PFC_2_ON2OFF_RX_PKTS; - stats_capability->list[86].stat_enum = SAI_PORT_STAT_PFC_3_ON2OFF_RX_PKTS; - stats_capability->list[87].stat_enum = SAI_PORT_STAT_PFC_4_ON2OFF_RX_PKTS; - stats_capability->list[88].stat_enum = SAI_PORT_STAT_PFC_5_ON2OFF_RX_PKTS; - stats_capability->list[89].stat_enum = SAI_PORT_STAT_PFC_6_ON2OFF_RX_PKTS; - stats_capability->list[90].stat_enum = SAI_PORT_STAT_PFC_7_ON2OFF_RX_PKTS; - - for(i = 0; i < stats_capability->count; i++) + bool include_telemetry_object_list = false; + std::vector attrs(attr_list, attr_list + attr_count); + for (uint32_t i = 0; i < attr_count; i++) + { + if (attr_list[i].id == SAI_TAM_ATTR_TELEMETRY_OBJECTS_LIST) { - stats_capability->list[i].stat_modes = SAI_STATS_MODE_READ_AND_CLEAR | SAI_STATS_MODE_READ ; + include_telemetry_object_list = true; + break; } - - return SAI_STATUS_SUCCESS; + } + if (!include_telemetry_object_list) + { + sai_attribute_t attr; + attr.id = SAI_TAM_ATTR_TELEMETRY_OBJECTS_LIST; + attr.value.objlist.count = 0; + attr.value.objlist.list = nullptr; + attrs.push_back(attr); } - return SAI_STATUS_NOT_SUPPORTED; + return create_internal(SAI_OBJECT_TYPE_TAM, + sai_serialize_object_id(tam_id), + switch_id, + static_cast(attrs.size()), + attrs.data()); } -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) +sai_status_t SwitchStateBase::createTamTelemetry( + sai_object_id_t tam_telemetry_id, + sai_object_id_t switch_id, + uint32_t attr_count, + const sai_attribute_t *attr_list) { SWSS_LOG_ENTER(); - // TODO: Fix me + bool inlcude_tam_type_list = false; + std::vector attrs(attr_list, attr_list + attr_count); + for (uint32_t i = 0; i < attr_count; i++) + { + if (attr_list[i].id == SAI_TAM_TELEMETRY_ATTR_TAM_TYPE_LIST) + { + inlcude_tam_type_list = true; + break; + } + } + if (!inlcude_tam_type_list) + { + sai_attribute_t attr; + attr.id = SAI_TAM_TELEMETRY_ATTR_TAM_TYPE_LIST; + attr.value.objlist.count = 0; + attr.value.objlist.list = nullptr; + attrs.push_back(attr); + } - return SAI_STATUS_NOT_IMPLEMENTED; + return create_internal(SAI_OBJECT_TYPE_TAM_TELEMETRY, + sai_serialize_object_id(tam_telemetry_id), + switch_id, + static_cast(attrs.size()), + attrs.data()); } diff --git a/vslib/SwitchStateBase.h b/vslib/SwitchStateBase.h index b4439f4d..be351361 100644 --- a/vslib/SwitchStateBase.h +++ b/vslib/SwitchStateBase.h @@ -92,12 +92,16 @@ namespace saivs virtual sai_status_t set_acl_capabilities(); + virtual sai_status_t set_maximum_number_of_traffic_classes(); + virtual sai_status_t set_maximum_number_of_childs_per_scheduler_group(); virtual sai_status_t set_number_of_ecmp_groups(); virtual sai_status_t set_static_crm_values(); + virtual sai_status_t set_initial_tam_objects(); + virtual sai_status_t set_static_acl_resource_list( _In_ sai_switch_attr_t acl_resource, _In_ int max_count); @@ -210,6 +214,8 @@ namespace saivs virtual sai_status_t create_qos_queues(); + virtual sai_status_t set_number_of_queues(); + virtual sai_status_t create_scheduler_group_tree( _In_ const std::vector& sgs, _In_ sai_object_id_t port_id); @@ -543,6 +549,14 @@ namespace saivs void send_fdb_event_notification( _In_ const sai_fdb_event_notification_data_t& data); + protected: // Telemetry and Monitor + + void send_tam_tel_type_config_change( + _In_ sai_object_id_t tam_tel_type_id); + + sai_status_t refresh_tam_tel_ipfix_templates( + _In_ sai_object_id_t tam_tel_type_id); + protected: void findObjects( @@ -568,20 +582,36 @@ 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); + + sai_status_t createMACsecSA( _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( + sai_status_t createMACsecSC( _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 createMACsecSC( - _In_ sai_object_id_t macsec_sa_id, + sai_status_t createTam( + _In_ sai_object_id_t tam_id, + _In_ sai_object_id_t switch_id, + _In_ uint32_t attr_count, + _In_ const sai_attribute_t *attr_list); + + sai_status_t createTamTelemetry( + _In_ sai_object_id_t tam_telemetry_id, _In_ sai_object_id_t switch_id, _In_ uint32_t attr_count, _In_ const sai_attribute_t *attr_list); @@ -723,9 +753,26 @@ namespace saivs virtual sai_status_t querySwitchHashAlgorithmCapability( _Inout_ sai_s32_list_t *enum_values_capability); + virtual sai_status_t querySwitchPacketTrimmingDscpResolutionModeCapability( + _Inout_ sai_s32_list_t *enum_values_capability); + + virtual sai_status_t querySwitchPacketTrimmingQueueResolutionModeCapability( + _Inout_ sai_s32_list_t *enum_values_capability); + + virtual sai_status_t queryBufferProfilePacketAdmissionFailActionCapability( + _Inout_ sai_s32_list_t *enum_values_capability); + virtual sai_status_t queryPortAutonegFecOverrideSupportCapability( _Out_ sai_attr_capability_t *attr_capability); + protected: + + virtual sai_status_t queryPortStatsCapability( + _Inout_ sai_stat_capability_list_t *stats_capability); + + virtual sai_status_t queryQueueStatsCapability( + _Inout_ sai_stat_capability_list_t *stats_capability); + public: // TODO private std::set m_fdb_info_set; diff --git a/vslib/VirtualSwitchSaiInterface.cpp b/vslib/VirtualSwitchSaiInterface.cpp index 7ef72090..462fe6dc 100644 --- a/vslib/VirtualSwitchSaiInterface.cpp +++ b/vslib/VirtualSwitchSaiInterface.cpp @@ -990,133 +990,6 @@ sai_status_t VirtualSwitchSaiInterface::queryStatsCapability( auto ss = m_switchStateMap.at(switchId); - - if (objectType == SAI_OBJECT_TYPE_QUEUE) - { - if (stats_capability->count < SAI_OBJECT_TYPE_QUEUE) - { - stats_capability->count = SAI_QUEUE_STAT_DELAY_WATERMARK_NS; - return SAI_STATUS_BUFFER_OVERFLOW; - } - - stats_capability->count = SAI_QUEUE_STAT_DELAY_WATERMARK_NS; - - for(uint32_t i = 0; i < stats_capability->count; i++) - { - stats_capability->list[i].stat_modes = SAI_STATS_MODE_READ_AND_CLEAR | SAI_STATS_MODE_READ; - stats_capability->list[i].stat_enum = i; - } - - return SAI_STATUS_SUCCESS; - } - else if (objectType == SAI_OBJECT_TYPE_PORT) - { - if (stats_capability->count < 91) - { - stats_capability->count = 91; - return SAI_STATUS_BUFFER_OVERFLOW; - } - - stats_capability->count = 91; - stats_capability->list[0].stat_enum = SAI_PORT_STAT_IF_IN_OCTETS; - stats_capability->list[1].stat_enum = SAI_PORT_STAT_IF_IN_UCAST_PKTS; - stats_capability->list[2].stat_enum = SAI_PORT_STAT_IF_IN_NON_UCAST_PKTS; - stats_capability->list[3].stat_enum = SAI_PORT_STAT_IF_IN_DISCARDS; - stats_capability->list[4].stat_enum = SAI_PORT_STAT_IF_IN_ERRORS; - stats_capability->list[5].stat_enum = SAI_PORT_STAT_IF_IN_UNKNOWN_PROTOS; - stats_capability->list[6].stat_enum = SAI_PORT_STAT_IF_IN_BROADCAST_PKTS; - stats_capability->list[7].stat_enum = SAI_PORT_STAT_IF_IN_MULTICAST_PKTS; - stats_capability->list[8].stat_enum = SAI_PORT_STAT_IF_IN_VLAN_DISCARDS; - stats_capability->list[9].stat_enum = SAI_PORT_STAT_IF_OUT_OCTETS; - stats_capability->list[10].stat_enum = SAI_PORT_STAT_IF_OUT_UCAST_PKTS; - stats_capability->list[11].stat_enum = SAI_PORT_STAT_IF_OUT_NON_UCAST_PKTS; - stats_capability->list[12].stat_enum = SAI_PORT_STAT_IF_OUT_DISCARDS; - stats_capability->list[13].stat_enum = SAI_PORT_STAT_IF_OUT_ERRORS; - stats_capability->list[14].stat_enum = SAI_PORT_STAT_IF_OUT_QLEN; - stats_capability->list[15].stat_enum = SAI_PORT_STAT_IF_OUT_BROADCAST_PKTS; - stats_capability->list[16].stat_enum = SAI_PORT_STAT_IF_OUT_MULTICAST_PKTS; - stats_capability->list[17].stat_enum = SAI_PORT_STAT_ETHER_STATS_DROP_EVENTS; - stats_capability->list[18].stat_enum = SAI_PORT_STAT_ETHER_STATS_MULTICAST_PKTS; - stats_capability->list[19].stat_enum = SAI_PORT_STAT_ETHER_STATS_BROADCAST_PKTS; - stats_capability->list[20].stat_enum = SAI_PORT_STAT_ETHER_STATS_UNDERSIZE_PKTS; - stats_capability->list[21].stat_enum = SAI_PORT_STAT_ETHER_STATS_FRAGMENTS; - stats_capability->list[22].stat_enum = SAI_PORT_STAT_ETHER_STATS_PKTS_64_OCTETS; - stats_capability->list[23].stat_enum = SAI_PORT_STAT_ETHER_STATS_PKTS_65_TO_127_OCTETS; - stats_capability->list[24].stat_enum = SAI_PORT_STAT_ETHER_STATS_PKTS_128_TO_255_OCTETS; - stats_capability->list[25].stat_enum = SAI_PORT_STAT_ETHER_STATS_PKTS_256_TO_511_OCTETS; - stats_capability->list[26].stat_enum = SAI_PORT_STAT_ETHER_STATS_PKTS_512_TO_1023_OCTETS; - stats_capability->list[27].stat_enum = SAI_PORT_STAT_ETHER_STATS_PKTS_1024_TO_1518_OCTETS; - stats_capability->list[28].stat_enum = SAI_PORT_STAT_ETHER_STATS_PKTS_1519_TO_2047_OCTETS; - stats_capability->list[29].stat_enum = SAI_PORT_STAT_ETHER_STATS_PKTS_2048_TO_4095_OCTETS; - stats_capability->list[30].stat_enum = SAI_PORT_STAT_ETHER_STATS_PKTS_4096_TO_9216_OCTETS; - stats_capability->list[31].stat_enum = SAI_PORT_STAT_ETHER_STATS_PKTS_9217_TO_16383_OCTETS; - stats_capability->list[32].stat_enum = SAI_PORT_STAT_ETHER_STATS_OVERSIZE_PKTS; - stats_capability->list[33].stat_enum = SAI_PORT_STAT_ETHER_RX_OVERSIZE_PKTS; - stats_capability->list[34].stat_enum = SAI_PORT_STAT_ETHER_TX_OVERSIZE_PKTS; - stats_capability->list[35].stat_enum = SAI_PORT_STAT_ETHER_STATS_JABBERS; - stats_capability->list[36].stat_enum = SAI_PORT_STAT_ETHER_STATS_OCTETS; - stats_capability->list[37].stat_enum = SAI_PORT_STAT_ETHER_STATS_PKTS; - stats_capability->list[38].stat_enum = SAI_PORT_STAT_ETHER_STATS_COLLISIONS; - stats_capability->list[39].stat_enum = SAI_PORT_STAT_ETHER_STATS_CRC_ALIGN_ERRORS; - stats_capability->list[40].stat_enum = SAI_PORT_STAT_ETHER_STATS_TX_NO_ERRORS; - stats_capability->list[41].stat_enum = SAI_PORT_STAT_ETHER_STATS_RX_NO_ERRORS; - stats_capability->list[42].stat_enum = SAI_PORT_STAT_GREEN_WRED_DROPPED_PACKETS; - stats_capability->list[43].stat_enum = SAI_PORT_STAT_GREEN_WRED_DROPPED_BYTES; - stats_capability->list[44].stat_enum = SAI_PORT_STAT_YELLOW_WRED_DROPPED_PACKETS; - stats_capability->list[45].stat_enum = SAI_PORT_STAT_YELLOW_WRED_DROPPED_BYTES; - stats_capability->list[46].stat_enum = SAI_PORT_STAT_RED_WRED_DROPPED_PACKETS; - stats_capability->list[47].stat_enum = SAI_PORT_STAT_RED_WRED_DROPPED_BYTES; - stats_capability->list[48].stat_enum = SAI_PORT_STAT_WRED_DROPPED_PACKETS; - stats_capability->list[49].stat_enum = SAI_PORT_STAT_WRED_DROPPED_BYTES; - stats_capability->list[50].stat_enum = SAI_PORT_STAT_ECN_MARKED_PACKETS; - stats_capability->list[51].stat_enum = SAI_PORT_STAT_PFC_0_RX_PKTS; - stats_capability->list[52].stat_enum = SAI_PORT_STAT_PFC_0_TX_PKTS; - stats_capability->list[53].stat_enum = SAI_PORT_STAT_PFC_1_RX_PKTS; - stats_capability->list[54].stat_enum = SAI_PORT_STAT_PFC_1_TX_PKTS; - stats_capability->list[55].stat_enum = SAI_PORT_STAT_PFC_2_RX_PKTS; - stats_capability->list[56].stat_enum = SAI_PORT_STAT_PFC_2_TX_PKTS; - stats_capability->list[57].stat_enum = SAI_PORT_STAT_PFC_3_RX_PKTS; - stats_capability->list[58].stat_enum = SAI_PORT_STAT_PFC_3_TX_PKTS; - stats_capability->list[59].stat_enum = SAI_PORT_STAT_PFC_4_RX_PKTS; - stats_capability->list[60].stat_enum = SAI_PORT_STAT_PFC_4_TX_PKTS; - stats_capability->list[61].stat_enum = SAI_PORT_STAT_PFC_5_RX_PKTS; - stats_capability->list[62].stat_enum = SAI_PORT_STAT_PFC_5_TX_PKTS; - stats_capability->list[63].stat_enum = SAI_PORT_STAT_PFC_6_RX_PKTS; - stats_capability->list[64].stat_enum = SAI_PORT_STAT_PFC_6_TX_PKTS; - stats_capability->list[65].stat_enum = SAI_PORT_STAT_PFC_7_RX_PKTS; - stats_capability->list[66].stat_enum = SAI_PORT_STAT_PFC_7_TX_PKTS; - stats_capability->list[67].stat_enum = SAI_PORT_STAT_PFC_0_RX_PAUSE_DURATION_US; - stats_capability->list[68].stat_enum = SAI_PORT_STAT_PFC_0_TX_PAUSE_DURATION_US; - stats_capability->list[69].stat_enum = SAI_PORT_STAT_PFC_1_RX_PAUSE_DURATION_US; - stats_capability->list[70].stat_enum = SAI_PORT_STAT_PFC_1_TX_PAUSE_DURATION_US; - stats_capability->list[71].stat_enum = SAI_PORT_STAT_PFC_2_RX_PAUSE_DURATION_US; - stats_capability->list[72].stat_enum = SAI_PORT_STAT_PFC_2_TX_PAUSE_DURATION_US; - stats_capability->list[73].stat_enum = SAI_PORT_STAT_PFC_3_RX_PAUSE_DURATION_US; - stats_capability->list[74].stat_enum = SAI_PORT_STAT_PFC_3_TX_PAUSE_DURATION_US; - stats_capability->list[75].stat_enum = SAI_PORT_STAT_PFC_4_RX_PAUSE_DURATION_US; - stats_capability->list[76].stat_enum = SAI_PORT_STAT_PFC_4_TX_PAUSE_DURATION_US; - stats_capability->list[77].stat_enum = SAI_PORT_STAT_PFC_5_RX_PAUSE_DURATION_US; - stats_capability->list[78].stat_enum = SAI_PORT_STAT_PFC_5_TX_PAUSE_DURATION_US; - stats_capability->list[79].stat_enum = SAI_PORT_STAT_PFC_6_RX_PAUSE_DURATION_US; - stats_capability->list[80].stat_enum = SAI_PORT_STAT_PFC_6_TX_PAUSE_DURATION_US; - stats_capability->list[81].stat_enum = SAI_PORT_STAT_PFC_7_RX_PAUSE_DURATION_US; - stats_capability->list[82].stat_enum = SAI_PORT_STAT_PFC_7_TX_PAUSE_DURATION_US; - stats_capability->list[83].stat_enum = SAI_PORT_STAT_PFC_0_ON2OFF_RX_PKTS; - stats_capability->list[84].stat_enum = SAI_PORT_STAT_PFC_1_ON2OFF_RX_PKTS; - stats_capability->list[85].stat_enum = SAI_PORT_STAT_PFC_2_ON2OFF_RX_PKTS; - stats_capability->list[86].stat_enum = SAI_PORT_STAT_PFC_3_ON2OFF_RX_PKTS; - stats_capability->list[87].stat_enum = SAI_PORT_STAT_PFC_4_ON2OFF_RX_PKTS; - stats_capability->list[88].stat_enum = SAI_PORT_STAT_PFC_5_ON2OFF_RX_PKTS; - stats_capability->list[89].stat_enum = SAI_PORT_STAT_PFC_6_ON2OFF_RX_PKTS; - stats_capability->list[90].stat_enum = SAI_PORT_STAT_PFC_7_ON2OFF_RX_PKTS; - for(uint32_t i = 0; i < stats_capability->count; i++) - { - stats_capability->list[i].stat_modes = SAI_STATS_MODE_READ_AND_CLEAR | SAI_STATS_MODE_READ ; - } - - return SAI_STATUS_SUCCESS; - } - return ss->queryStatsCapability( switchId, objectType, @@ -1126,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(