Skip to content

Commit

Permalink
sonic-sairedis : Wred stats feature changes on Sai-redis and Syncd
Browse files Browse the repository at this point in the history
* Stats capability query API support is added

Signed-off-by: rpmarvell <[email protected]>
  • Loading branch information
rpmarvell committed Apr 24, 2023
1 parent dc93d4c commit d8bbe32
Show file tree
Hide file tree
Showing 18 changed files with 685 additions and 64 deletions.
154 changes: 144 additions & 10 deletions lib/ClientSai.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -886,16 +886,6 @@ sai_status_t ClientSai::getStats(
return waitForGetStatsResponse(number_of_counters, counters);
}

sai_status_t ClientSai::queryStatsCapability(
_In_ sai_object_id_t switchId,
_In_ sai_object_type_t objectType,
_Inout_ sai_stat_capability_list_t *stats_capability)
{
SWSS_LOG_ENTER();

return SAI_STATUS_NOT_IMPLEMENTED;
}

sai_status_t ClientSai::waitForGetStatsResponse(
_In_ uint32_t number_of_counters,
_Out_ uint64_t *counters)
Expand Down Expand Up @@ -924,6 +914,150 @@ sai_status_t ClientSai::waitForGetStatsResponse(
return status;
}

sai_status_t ClientSai::queryStatsCapability(
_In_ sai_object_id_t switchId,
_In_ sai_object_type_t objectType,
_Inout_ sai_stat_capability_list_t *stats_capability)
{
MUTEX();
SWSS_LOG_ENTER();
REDIS_CHECK_API_INITIALIZED();

if (stats_capability && stats_capability->list)
{
// clear input list, since we use serialize to transfer values
for (uint32_t idx = 0; idx < stats_capability->count; idx++)
{
stats_capability->list[idx].stat_enum = 0;
stats_capability->list[idx].stat_modes = 0;
}
}

auto switchIdStr = sai_serialize_object_id(switchId);
auto objectTypeStr = sai_serialize_object_type(objectType);
const std::string list_size = std::to_string(stats_capability->count);

const std::vector<swss::FieldValueTuple> entry =
{
swss::FieldValueTuple("OBJECT_TYPE", objectTypeStr),
swss::FieldValueTuple("LIST_SIZE", list_size)
};

SWSS_LOG_NOTICE( /* DEBUG */
"Query arguments: switch %s, object type: %s, count: %s",
switchIdStr.c_str(),
objectTypeStr.c_str(),
list_size.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_CAPABILITY_QUERY);

auto status = waitForQueryStatsCapabilityResponse(stats_capability);

return status;
}

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<swss::FieldValueTuple> &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]));

/*DEBUG*/
SWSS_LOG_NOTICE("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;

size_t stat_enum_position = 0;
size_t stat_modes_position = 0;
for (uint32_t i = 0; i < num_capabilities; i++)
{
/* 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].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_WARN("Query returned less stat_enums than expected: expected %d, received %d",
num_capabilities, i+1);
}

break;
}

/* 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].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_WARN("Query returned less stat_modes than expected: expected %d, received %d",
num_capabilities, i+1);
}

break;
}

// Skip the commas
stat_enum_position++;
stat_modes_position++;
}
}
else if (status == SAI_STATUS_BUFFER_OVERFLOW)
{
const std::vector<swss::FieldValueTuple> &values = kfvFieldsValues(kco);

if (values.size() != 1)
{
SWSS_LOG_ERROR("Invalid response from syncd: expected 1 value, received %zu", values.size());

return SAI_STATUS_FAILURE;
}

const uint32_t num_capabilities = std::stoi(fvValue(values[0]));

SWSS_LOG_DEBUG("Received payload: count = %u", num_capabilities);

stats_capability->count = num_capabilities;
}

return status;
}

sai_status_t ClientSai::getStatsExt(
_In_ sai_object_type_t object_type,
_In_ sai_object_id_t object_id,
Expand Down
3 changes: 3 additions & 0 deletions lib/ClientSai.h
Original file line number Diff line number Diff line change
Expand Up @@ -285,6 +285,9 @@ namespace sairedis
sai_status_t waitForObjectTypeGetAvailabilityResponse(
_In_ uint64_t *count);

sai_status_t waitForQueryStatsCapabilityResponse(
_Inout_ sai_stat_capability_list_t* stats_capability);

private:

void handleNotification(
Expand Down
5 changes: 4 additions & 1 deletion lib/ClientServerSai.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -256,7 +256,10 @@ sai_status_t ClientServerSai::queryStatsCapability(
SWSS_LOG_ENTER();
REDIS_CHECK_API_INITIALIZED();

return SAI_STATUS_NOT_IMPLEMENTED;
return m_sai->queryStatsCapability(
switchId,
objectType,
stats_capability);
}

sai_status_t ClientServerSai::getStatsExt(
Expand Down
84 changes: 84 additions & 0 deletions lib/Recorder.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -370,6 +370,24 @@ void Recorder::recordObjectTypeGetAvailabilityResponse(
recordLine("Q|object_type_get_availability|" + sai_serialize_status(status) + "|" + Globals::joinFieldValues(arguments));
}

void Recorder::recordQueryStatsCapability(
_In_ const std::string& key,
_In_ const std::vector<swss::FieldValueTuple>& arguments)
{
SWSS_LOG_ENTER();

recordLine("q|stats_capability|" + key + "|" + Globals::joinFieldValues(arguments));
}

void Recorder::recordQueryStatsCapabilityResponse(
_In_ sai_status_t status,
_In_ const std::vector<swss::FieldValueTuple>& arguments)
{
SWSS_LOG_ENTER();

recordLine("Q|stats_capability|" + sai_serialize_status(status) + "|" + Globals::joinFieldValues(arguments));
}

void Recorder::recordNotifySyncd(
_In_ const std::string& key)
{
Expand Down Expand Up @@ -1089,6 +1107,72 @@ void Recorder::recordQueryAattributeEnumValuesCapabilityResponse(
recordQueryAttributeEnumValuesCapabilityResponse(status, values);
}

void Recorder::recordQueryStatsCapability(
_In_ sai_object_id_t switchId,
_In_ sai_object_type_t object_type,
_Inout_ sai_stat_capability_list_t* stats_capability)
{
SWSS_LOG_ENTER();

auto key = sai_serialize_object_type(SAI_OBJECT_TYPE_SWITCH) + ":" + sai_serialize_object_id(switchId);

auto object_type_str = sai_serialize_object_type(object_type);
const std::string list_size = std::to_string(stats_capability->count);
const std::vector<swss::FieldValueTuple> values =
{
swss::FieldValueTuple("OBJECT_TYPE", object_type_str),
swss::FieldValueTuple("LIST_SIZE", list_size)
};

/*DEBUG*/
SWSS_LOG_NOTICE("Query arguments: switch %s, object_type: %s, count: %s",
key.c_str(),
object_type_str.c_str(),
list_size.c_str());

recordQueryStatsCapability (key, values);
}

void Recorder::recordQueryStatsCapabilityResponse(
_In_ sai_status_t status,
_In_ sai_object_type_t objectType,
_In_ const sai_stat_capability_list_t *stats_capability)
{
SWSS_LOG_ENTER();
#if 0
std::vector<swss::FieldValueTuple> values;

auto meta = sai_metadata_get_attr_metadata(objectType, attrId);

if (meta == NULL)
{
SWSS_LOG_ERROR("Failed to find attribute metadata: object type %s, attr id %d",
sai_serialize_object_type(objectType).c_str(),
attrId);

return;
}

if (!meta->enummetadata)
{
SWSS_LOG_ERROR("Attribute %s is not enum/enumlist!", meta->attridname);
return;
}

bool countOnly = (status == SAI_STATUS_BUFFER_OVERFLOW);

if (status == SAI_STATUS_SUCCESS || status == SAI_STATUS_BUFFER_OVERFLOW)
{
auto str_attr_id = sai_serialize_attr_id(*meta);
auto str_enum_list = sai_serialize_enum_list(*enumValuesCapability, meta->enummetadata, countOnly);

values.emplace_back(str_attr_id, str_enum_list);
}

recordQueryAttributeEnumValuesCapabilityResponse(status, values);
#endif
}

void Recorder::recordNotifySyncd(
_In_ sai_object_id_t switchId,
_In_ sai_redis_notify_syncd_t redisNotifySyncd)
Expand Down
18 changes: 18 additions & 0 deletions lib/Recorder.h
Original file line number Diff line number Diff line change
Expand Up @@ -325,6 +325,16 @@ namespace sairedis
_In_ sai_attr_id_t attrId,
_In_ const sai_s32_list_t* enumValuesCapability);

void recordQueryStatsCapability(
_In_ sai_object_id_t switch_id,
_In_ sai_object_type_t object_type,
_Inout_ sai_stat_capability_list_t* stats_capability);

void recordQueryStatsCapabilityResponse(
_In_ sai_status_t status,
_In_ sai_object_type_t objectType,
_In_ const sai_stat_capability_list_t *stats_capability);

// TODO move to private
void recordQueryAttributeCapability(
_In_ const std::string& key,
Expand All @@ -350,6 +360,14 @@ namespace sairedis
_In_ sai_status_t status,
_In_ const std::vector<swss::FieldValueTuple>& arguments);

void recordQueryStatsCapability(
_In_ const std::string& key,
_In_ const std::vector<swss::FieldValueTuple>& arguments);

void recordQueryStatsCapabilityResponse(
_In_ sai_status_t status,
_In_ const std::vector<swss::FieldValueTuple>& arguments);

public: // SAI notifications

void recordNotification(
Expand Down
Loading

0 comments on commit d8bbe32

Please sign in to comment.