Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

ASIC temperature sensors support #383

Closed
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions meta/sai_serialize.h
Original file line number Diff line number Diff line change
Expand Up @@ -138,6 +138,9 @@ std::string sai_serialize_ipmc_entry_type(
std::string sai_serialize_qos_map_item(
_In_ const sai_qos_map_t& qosmap);

std::string sai_serialize_switch_attr(
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

please remove we already have generic function to serialize attributes for all objects

_In_ const sai_switch_attr_t switch_attr);

// serialize notifications

std::string sai_serialize_fdb_event_ntf(
Expand Down Expand Up @@ -287,4 +290,8 @@ void sai_deserialize_queue_attr(
_In_ const std::string& s,
_Out_ sai_queue_attr_t& attr);

void sai_deserialize_switch_attr(
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

please remove we already have generic function to deserialize attributes for all objects

_In_ const std::string& s,
_Out_ sai_switch_attr_t& attr);

#endif // __SAI_SERIALIZE__
17 changes: 17 additions & 0 deletions meta/saiserialize.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1636,6 +1636,14 @@ std::string sai_serialize_object_meta_key(
return key;
}

std::string sai_serialize_switch_attr(
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

please remove we already have generic function to serialize attributes for all objects

_In_ const sai_switch_attr_t switch_attr)
{
SWSS_LOG_ENTER();

return sai_serialize_enum(switch_attr, &sai_metadata_enum_sai_switch_attr_t);
}

// deserialize

void sai_deserialize_bool(
Expand Down Expand Up @@ -2976,3 +2984,12 @@ void sai_deserialize_queue_attr(

sai_deserialize_enum(s, &sai_metadata_enum_sai_queue_attr_t, (int32_t&)attr);
}

void sai_deserialize_switch_attr(
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

please remove we already have generic function to deserialize attributes for all objects

_In_ const std::string& s,
_Out_ sai_switch_attr_t& attr)
{
SWSS_LOG_ENTER();

sai_deserialize_enum(s, &sai_metadata_enum_sai_switch_attr_t, (int32_t&)attr);
}
11 changes: 11 additions & 0 deletions syncd/syncd.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2907,6 +2907,17 @@ void processFlexCounterEvent(

FlexCounter::setPriorityGroupAttrList(vid, rid, groupName, pgAttrIds);
}
else if (objectType == SAI_OBJECT_TYPE_SWITCH && field == SWITCH_SENSOR_ID_LIST)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why we need this here as special case ?
also this solution for those cases here is getting bigger and bigger we should think of some generic approach

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I wasn't sure if there could be other (non thermal) attributes that may be of interest in the future.. Agree that there should be a generic approach to handle flex group events (a single table) instead of having to extend event/attribute handling multiple locations...

{
std::vector<sai_switch_attr_t> SwitchSensorIds;
for (const auto &str : idStrings)
{
sai_switch_attr_t attr;
sai_deserialize_switch_attr(str, attr);
SwitchSensorIds.push_back(attr);
}
FlexCounter::setSwitchSensorsList(vid, rid, groupName, SwitchSensorIds);
}
else
{
SWSS_LOG_ERROR("Object type and field combination is not supported, object type %s, field %s", objectTypeStr.c_str(), field.c_str());
Expand Down
202 changes: 202 additions & 0 deletions syncd/syncd_flex_counter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ static std::map<std::string, std::shared_ptr<FlexCounter>> g_flex_counters_map;
static std::set<sai_port_stat_t> supportedPortCounters;
static std::set<sai_queue_stat_t> supportedQueueCounters;
static std::set<sai_ingress_priority_group_stat_t> supportedPriorityGroupCounters;
static std::set<sai_switch_attr_t> supportedSwitchSensors;
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why temperature sensors are in counters ? i think we dont need this implementation here at all, seems like sensors are just another attribute and we can definitely query them

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ASIC sensor readings are not counters per-se - yes.. This is one of the few environmental variables that need to be retrieved thru' SAI : the list may grow but may not bloat. We wanted to leverage the existing flex counter infra (instead of creating a private poller).

Since thermal algorithms may typically need this every few seconds, having a script based daemon may be possible.

Can you point me to how a script may query attributes directly (rather than query the DB) ?

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

as script i dont know, i had in mind orchagent which would query those sensors using sai apis

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

since the load is low, ~8 values in maybe one minute. Moving to orchagent is better. agree with @kcudnik


FlexCounter::PortCounterIds::PortCounterIds(
_In_ sai_object_id_t port,
Expand Down Expand Up @@ -49,6 +50,14 @@ FlexCounter::IngressPriorityGroupCounterIds::IngressPriorityGroupCounterIds(
SWSS_LOG_ENTER();
}

FlexCounter::SwitchSensorIds::SwitchSensorIds(
_In_ sai_object_id_t switch_id,
_In_ const std::vector<sai_switch_attr_t> &SensorIds):
switchId(switch_id), switchSensorIds(SensorIds)
{
SWSS_LOG_ENTER();
}

void FlexCounter::setPollInterval(
_In_ uint32_t pollInterval,
_In_ std::string instanceId)
Expand Down Expand Up @@ -364,6 +373,59 @@ void FlexCounter::setPriorityGroupAttrList(
}
}

void FlexCounter::setSwitchSensorsList(
_In_ sai_object_id_t switchVid,
_In_ sai_object_id_t switchId,
_In_ std::string instanceId,
_In_ const std::vector<sai_switch_attr_t> &sensorIds)
{
SWSS_LOG_ENTER();

FlexCounter &fc = getInstance(instanceId);

fc.saiUpdateSupportedSwitchSensors(switchId, sensorIds);

// Remove unsupported sensors
std::vector<sai_switch_attr_t> supportedIds;
for (auto &sensor : sensorIds)
{
if (fc.isSwitchSensorSupported(sensor))
{
supportedIds.push_back(sensor);
}
}

if (supportedIds.size() == 0)
{
SWSS_LOG_ERROR("SWITCH %s does not has supported sensors", sai_serialize_object_id(switchId).c_str());

// Remove flex counter if all sensor IDs are unregistered
if (fc.isEmpty())
{
removeInstance(instanceId);
}

return;
}

auto it = fc.m_switchSensorIdsMap.find(switchVid);
if (it != fc.m_switchSensorIdsMap.end())
{
(*it).second->switchSensorIds = supportedIds;
return;
}

auto switchSensorIds = std::make_shared<SwitchSensorIds>(switchId, supportedIds);
fc.m_switchSensorIdsMap.emplace(switchVid, switchSensorIds);

// Start flex counter thread in case it was not running due to empty sensor IDs map
if (fc.m_pollInterval > 0)
{
fc.startFlexCounterThread();
SWSS_LOG_ERROR("setSwitchSensorsList startFlexCounterThread started");
}
}

void FlexCounter::removePort(
_In_ sai_object_id_t portVid,
_In_ std::string instanceId)
Expand Down Expand Up @@ -465,6 +527,35 @@ void FlexCounter::removePriorityGroup(
}
}

void FlexCounter::removeSwitch(
_In_ sai_object_id_t switchVid,
_In_ std::string instanceId)
{
SWSS_LOG_ENTER();

FlexCounter &fc = getInstance(instanceId);

auto it = fc.m_switchSensorIdsMap.find(switchVid);
if (it == fc.m_switchSensorIdsMap.end())
{
SWSS_LOG_NOTICE("Trying to remove nonexisting switch sensor Ids 0x%lx", switchVid);
// Remove flex counter if all counter IDs and plugins are unregistered
if (fc.isEmpty())
{
removeInstance(instanceId);
}
return;
}

fc.m_switchSensorIdsMap.erase(it);

// Remove flex counter if all switch sensor IDs are unregistered
if (fc.isEmpty())
{
removeInstance(instanceId);
}
}

void FlexCounter::addPortCounterPlugin(
_In_ std::string sha,
_In_ std::string instanceId)
Expand Down Expand Up @@ -609,6 +700,13 @@ bool FlexCounter::isPriorityGroupCounterSupported(sai_ingress_priority_group_sta
return supportedPriorityGroupCounters.count(counter) != 0;
}

bool FlexCounter::isSwitchSensorSupported(sai_switch_attr_t sensor) const
{
SWSS_LOG_ENTER();

return supportedSwitchSensors.count(sensor) != 0;
}

FlexCounter::FlexCounter(std::string instanceId) : m_instanceId(instanceId)
{
SWSS_LOG_ENTER();
Expand Down Expand Up @@ -644,6 +742,7 @@ void FlexCounter::collectCounters(
std::map<sai_object_id_t, std::shared_ptr<QueueAttrIds>> queueAttrIdsMap;
std::map<sai_object_id_t, std::shared_ptr<IngressPriorityGroupCounterIds>> priorityGroupCounterIdsMap;
std::map<sai_object_id_t, std::shared_ptr<IngressPriorityGroupAttrIds>> priorityGroupAttrIdsMap;
std::map<sai_object_id_t, std::shared_ptr<SwitchSensorIds>> SwitchSensorIdsMap;

{
std::lock_guard<std::mutex> lock(g_mutex);
Expand All @@ -652,6 +751,7 @@ void FlexCounter::collectCounters(
queueAttrIdsMap = m_queueAttrIdsMap;
priorityGroupCounterIdsMap = m_priorityGroupCounterIdsMap;
priorityGroupAttrIdsMap = m_priorityGroupAttrIdsMap;
SwitchSensorIdsMap = m_switchSensorIdsMap;
}

// Collect stats for every registered port
Expand Down Expand Up @@ -871,6 +971,60 @@ void FlexCounter::collectCounters(
countersTable.set(priorityGroupVidStr, values, "");
}

// Collect stats for every registered Switch Sensor
for (const auto &kv: SwitchSensorIdsMap)
{
const auto &switchVid = kv.first;
const auto &switchId = kv.second->switchId;
const auto &switchSensorIds = kv.second->switchSensorIds;

std::vector<uint32_t> switchSensorValue(switchSensorIds.size());

// Push all counter values to a single vector
std::vector<swss::FieldValueTuple> values;

for (auto &sensor : switchSensorIds)
{
sai_attribute_t attr;

if(SAI_SWITCH_ATTR_TEMP_LIST == sensor) {
std::vector<int32_t> temp_list(max_temp_sensors);

attr.id = SAI_SWITCH_ATTR_TEMP_LIST;
attr.value.s32list.count = max_temp_sensors;
attr.value.s32list.list = temp_list.data();

sai_status_t status = sai_metadata_sai_switch_api->get_switch_attribute(switchId , 1, &attr);
if (status != SAI_STATUS_SUCCESS)
{
SWSS_LOG_ERROR("Failed to get value of sensor 0x%lx: %d", sensor, status);
continue;
}

for (size_t i = 0; i < attr.value.s32list.count ; i++) {
const std::string &counterName = sai_serialize_switch_attr(sensor) + "_ITEM_" + std::to_string(i);
values.emplace_back(counterName, std::to_string(temp_list[i]));
}
} else {
attr.id = sensor;
sai_status_t status = sai_metadata_sai_switch_api->get_switch_attribute(switchId , 1, &attr);
if (status != SAI_STATUS_SUCCESS)
{
SWSS_LOG_ERROR("Failed to get value of sensor 0x%lx: %d", sensor, status);
continue;
}

const std::string &counterName = sai_serialize_switch_attr(sensor);
values.emplace_back(counterName, std::to_string(attr.value.s32));
}
}

// Write counters to DB
std::string switchVidStr = sai_serialize_object_id(switchVid);

countersTable.set(switchVidStr, values, "");
}

countersTable.flush();
}

Expand Down Expand Up @@ -1094,3 +1248,51 @@ void FlexCounter::saiUpdateSupportedPriorityGroupCounters(
}
}
}

void FlexCounter::saiUpdateSupportedSwitchSensors(
_In_ sai_object_id_t switchId,
_In_ const std::vector<sai_switch_attr_t> &sensorIds)
{
SWSS_LOG_ENTER();

sai_attribute_t attr;

supportedSwitchSensors.clear();

for (auto &sensor : sensorIds)
{
if(SAI_SWITCH_ATTR_TEMP_LIST == sensor) {
attr.id = SAI_SWITCH_ATTR_MAX_NUMBER_OF_TEMP_SENSORS;
sai_status_t status = sai_metadata_sai_switch_api->get_switch_attribute(switchId , 1, &attr);
if ((status != SAI_STATUS_SUCCESS) || (0 == attr.value.u8))
{
SWSS_LOG_INFO("Temperature sensor list is not supported");
continue;
} else {
max_temp_sensors = attr.value.u8;
}
}

attr.id = sensor;

sai_status_t status = sai_metadata_sai_switch_api->get_switch_attribute(switchId , 1, &attr);

if (status != SAI_STATUS_SUCCESS)
{
SWSS_LOG_INFO("Sensor %s is not supported on switch %s, rv: %s",
sai_serialize_switch_attr(sensor).c_str(),
sai_serialize_object_id(switchId).c_str(),
sai_serialize_status(status).c_str());

continue;
}
else
{
SWSS_LOG_ERROR("Sensor %s is supported on switch %s, rv: %s",
sai_serialize_switch_attr(sensor).c_str(),
sai_serialize_object_id(switchId).c_str(),
sai_serialize_status(status).c_str());
supportedSwitchSensors.insert(sensor);
}
}
}
24 changes: 24 additions & 0 deletions syncd/syncd_flex_counter.h
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,11 @@ class FlexCounter
_In_ sai_object_id_t priorityGroupId,
_In_ std::string instanceId,
_In_ const std::vector<sai_ingress_priority_group_attr_t> &attrIds);
static void setSwitchSensorsList(
_In_ sai_object_id_t switchVid,
_In_ sai_object_id_t switchId,
_In_ std::string instanceId,
_In_ const std::vector<sai_switch_attr_t> &SwitchSensorIds);
static void updateFlexCounterStatus(
_In_ std::string status,
_In_ std::string instanceId);
Expand All @@ -58,6 +63,9 @@ class FlexCounter
static void removePriorityGroup(
_In_ sai_object_id_t priorityGroupVid,
_In_ std::string instanceId);
static void removeSwitch(
_In_ sai_object_id_t SwitchVid,
_In_ std::string instanceId);

static void addPortCounterPlugin(
_In_ std::string sha,
Expand Down Expand Up @@ -130,6 +138,16 @@ class FlexCounter
std::vector<sai_port_stat_t> portCounterIds;
};

struct SwitchSensorIds
{
SwitchSensorIds(
_In_ sai_object_id_t switchId,
_In_ const std::vector<sai_switch_attr_t> &SensorIds);

sai_object_id_t switchId;
std::vector<sai_switch_attr_t> switchSensorIds;
};

FlexCounter(std::string instanceId);
static FlexCounter& getInstance(std::string instanceId);
static void removeInstance(std::string instanceId);
Expand All @@ -143,9 +161,11 @@ class FlexCounter
void saiUpdateSupportedPortCounters(sai_object_id_t portId);
void saiUpdateSupportedQueueCounters(sai_object_id_t queueId, const std::vector<sai_queue_stat_t> &counterIds);
void saiUpdateSupportedPriorityGroupCounters(sai_object_id_t priorityGroupId, const std::vector<sai_ingress_priority_group_stat_t> &counterIds);
void saiUpdateSupportedSwitchSensors(_In_ sai_object_id_t switchId, _In_ const std::vector<sai_switch_attr_t> &SwitchSensorIds);
bool isPortCounterSupported(sai_port_stat_t counter) const;
bool isQueueCounterSupported(sai_queue_stat_t counter) const;
bool isPriorityGroupCounterSupported(sai_ingress_priority_group_stat_t counter) const;
bool isSwitchSensorSupported(sai_switch_attr_t sensor) const;
bool isEmpty();

// Key is a Virtual ID
Expand All @@ -154,6 +174,10 @@ class FlexCounter
std::map<sai_object_id_t, std::shared_ptr<QueueAttrIds>> m_queueAttrIdsMap;
std::map<sai_object_id_t, std::shared_ptr<IngressPriorityGroupCounterIds>> m_priorityGroupCounterIdsMap;
std::map<sai_object_id_t, std::shared_ptr<IngressPriorityGroupAttrIds>> m_priorityGroupAttrIdsMap;
std::map<sai_object_id_t, std::shared_ptr<SwitchSensorIds>> m_switchSensorIdsMap;

// Max number of temperature sensors
uint8_t max_temp_sensors;

// Plugins
std::set<std::string> m_queuePlugins;
Expand Down