@@ -886,16 +886,6 @@ sai_status_t ClientSai::getStats(
886886 return waitForGetStatsResponse (number_of_counters, counters);
887887}
888888
889- sai_status_t ClientSai::queryStatsCapability (
890- _In_ sai_object_id_t switchId,
891- _In_ sai_object_type_t objectType,
892- _Inout_ sai_stat_capability_list_t *stats_capability)
893- {
894- SWSS_LOG_ENTER ();
895-
896- return SAI_STATUS_NOT_IMPLEMENTED;
897- }
898-
899889sai_status_t ClientSai::waitForGetStatsResponse (
900890 _In_ uint32_t number_of_counters,
901891 _Out_ uint64_t *counters)
@@ -924,6 +914,150 @@ sai_status_t ClientSai::waitForGetStatsResponse(
924914 return status;
925915}
926916
917+ sai_status_t ClientSai::queryStatsCapability (
918+ _In_ sai_object_id_t switchId,
919+ _In_ sai_object_type_t objectType,
920+ _Inout_ sai_stat_capability_list_t *stats_capability)
921+ {
922+ MUTEX ();
923+ SWSS_LOG_ENTER ();
924+ REDIS_CHECK_API_INITIALIZED ();
925+
926+ if (stats_capability && stats_capability->list )
927+ {
928+ // clear input list, since we use serialize to transfer values
929+ for (uint32_t idx = 0 ; idx < stats_capability->count ; idx++)
930+ {
931+ stats_capability->list [idx].stat_enum = 0 ;
932+ stats_capability->list [idx].stat_modes = 0 ;
933+ }
934+ }
935+
936+ auto switchIdStr = sai_serialize_object_id (switchId);
937+ auto objectTypeStr = sai_serialize_object_type (objectType);
938+ const std::string list_size = std::to_string (stats_capability->count );
939+
940+ const std::vector<swss::FieldValueTuple> entry =
941+ {
942+ swss::FieldValueTuple (" OBJECT_TYPE" , objectTypeStr),
943+ swss::FieldValueTuple (" LIST_SIZE" , list_size)
944+ };
945+
946+ SWSS_LOG_NOTICE ( /* DEBUG */
947+ " Query arguments: switch %s, object type: %s, count: %s" ,
948+ switchIdStr.c_str (),
949+ objectTypeStr.c_str (),
950+ list_size.c_str ()
951+ );
952+
953+ // This query will not put any data into the ASIC view, just into the
954+ // message queue
955+
956+ m_communicationChannel->set (switchIdStr, entry, REDIS_ASIC_STATE_COMMAND_STATS_CAPABILITY_QUERY);
957+
958+ auto status = waitForQueryStatsCapabilityResponse (stats_capability);
959+
960+ return status;
961+ }
962+
963+ sai_status_t ClientSai::waitForQueryStatsCapabilityResponse (
964+ _Inout_ sai_stat_capability_list_t * stats_capability)
965+ {
966+ SWSS_LOG_ENTER ();
967+
968+ swss::KeyOpFieldsValuesTuple kco;
969+
970+ auto status = m_communicationChannel->wait (REDIS_ASIC_STATE_COMMAND_STATS_CAPABILITY_RESPONSE, kco);
971+
972+ if (status == SAI_STATUS_SUCCESS)
973+ {
974+ const std::vector<swss::FieldValueTuple> &values = kfvFieldsValues (kco);
975+
976+ if (values.size () != 3 )
977+ {
978+ SWSS_LOG_ERROR (" Invalid response from syncd: expected 3 value, received %zu" , values.size ());
979+
980+ return SAI_STATUS_FAILURE;
981+ }
982+
983+ const std::string &stat_enum_str = fvValue (values[0 ]);
984+ const std::string &stat_modes_str = fvValue (values[1 ]);
985+ const uint32_t num_capabilities = std::stoi (fvValue (values[2 ]));
986+
987+ /* DEBUG*/
988+ SWSS_LOG_NOTICE (" Received payload: stat_enums = '%s', stat_modes = '%s', count = %d" ,
989+ stat_enum_str.c_str (), stat_modes_str.c_str (), num_capabilities);
990+
991+ stats_capability->count = num_capabilities;
992+
993+ size_t stat_enum_position = 0 ;
994+ size_t stat_modes_position = 0 ;
995+ for (uint32_t i = 0 ; i < num_capabilities; i++)
996+ {
997+ /* Populate stat_enum */
998+ size_t old_stat_enum_position = stat_enum_position;
999+ stat_enum_position = stat_enum_str.find (" ," , old_stat_enum_position);
1000+ std::string stat_enum = stat_enum_str.substr (old_stat_enum_position,
1001+ stat_enum_position - old_stat_enum_position);
1002+ stats_capability->list [i].stat_enum = std::stoi (stat_enum);
1003+
1004+ // We have run out of values to add to our list
1005+ if (stat_enum_position == std::string::npos)
1006+ {
1007+ if (num_capabilities != i + 1 )
1008+ {
1009+ SWSS_LOG_WARN (" Query returned less stat_enums than expected: expected %d, received %d" ,
1010+ num_capabilities, i+1 );
1011+ }
1012+
1013+ break ;
1014+ }
1015+
1016+ /* Populate stat_modes */
1017+ size_t old_stat_modes_position = stat_modes_position;
1018+ stat_modes_position = stat_modes_str.find (" ," , old_stat_modes_position);
1019+ std::string stat_modes = stat_modes_str.substr (old_stat_modes_position,
1020+ stat_modes_position - old_stat_modes_position);
1021+ stats_capability->list [i].stat_modes = std::stoi (stat_modes);
1022+
1023+ // We have run out of values to add to our list
1024+ if (stat_modes_position == std::string::npos)
1025+ {
1026+ if (num_capabilities != i + 1 )
1027+ {
1028+ SWSS_LOG_WARN (" Query returned less stat_modes than expected: expected %d, received %d" ,
1029+ num_capabilities, i+1 );
1030+ }
1031+
1032+ break ;
1033+ }
1034+
1035+ // Skip the commas
1036+ stat_enum_position++;
1037+ stat_modes_position++;
1038+ }
1039+ }
1040+ else if (status == SAI_STATUS_BUFFER_OVERFLOW)
1041+ {
1042+ const std::vector<swss::FieldValueTuple> &values = kfvFieldsValues (kco);
1043+
1044+ if (values.size () != 1 )
1045+ {
1046+ SWSS_LOG_ERROR (" Invalid response from syncd: expected 1 value, received %zu" , values.size ());
1047+
1048+ return SAI_STATUS_FAILURE;
1049+ }
1050+
1051+ const uint32_t num_capabilities = std::stoi (fvValue (values[0 ]));
1052+
1053+ SWSS_LOG_DEBUG (" Received payload: count = %u" , num_capabilities);
1054+
1055+ stats_capability->count = num_capabilities;
1056+ }
1057+
1058+ return status;
1059+ }
1060+
9271061sai_status_t ClientSai::getStatsExt (
9281062 _In_ sai_object_type_t object_type,
9291063 _In_ sai_object_id_t object_id,
0 commit comments