diff --git a/meta/sai_serialize.h b/meta/sai_serialize.h index cd7cda5cd..39658e4fa 100644 --- a/meta/sai_serialize.h +++ b/meta/sai_serialize.h @@ -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( + _In_ const sai_switch_attr_t switch_attr); + // serialize notifications std::string sai_serialize_fdb_event_ntf( @@ -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( + _In_ const std::string& s, + _Out_ sai_switch_attr_t& attr); + #endif // __SAI_SERIALIZE__ diff --git a/meta/saiserialize.cpp b/meta/saiserialize.cpp index 2b1688c09..399c6687e 100644 --- a/meta/saiserialize.cpp +++ b/meta/saiserialize.cpp @@ -1636,6 +1636,14 @@ std::string sai_serialize_object_meta_key( return key; } +std::string sai_serialize_switch_attr( + _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( @@ -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( + _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); +} diff --git a/syncd/syncd.cpp b/syncd/syncd.cpp index 0c0ced126..aa8ac9e8d 100644 --- a/syncd/syncd.cpp +++ b/syncd/syncd.cpp @@ -2907,6 +2907,17 @@ void processFlexCounterEvent( FlexCounter::setPriorityGroupAttrList(vid, rid, groupName, pgAttrIds); } + else if (objectType == SAI_OBJECT_TYPE_SWITCH && field == SWITCH_SENSOR_ID_LIST) + { + std::vector 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()); diff --git a/syncd/syncd_flex_counter.cpp b/syncd/syncd_flex_counter.cpp index 4db13103c..5dd2a721e 100644 --- a/syncd/syncd_flex_counter.cpp +++ b/syncd/syncd_flex_counter.cpp @@ -8,6 +8,7 @@ static std::map> g_flex_counters_map; static std::set supportedPortCounters; static std::set supportedQueueCounters; static std::set supportedPriorityGroupCounters; +static std::set supportedSwitchSensors; FlexCounter::PortCounterIds::PortCounterIds( _In_ sai_object_id_t port, @@ -49,6 +50,14 @@ FlexCounter::IngressPriorityGroupCounterIds::IngressPriorityGroupCounterIds( SWSS_LOG_ENTER(); } +FlexCounter::SwitchSensorIds::SwitchSensorIds( + _In_ sai_object_id_t switch_id, + _In_ const std::vector &SensorIds): + switchId(switch_id), switchSensorIds(SensorIds) +{ + SWSS_LOG_ENTER(); +} + void FlexCounter::setPollInterval( _In_ uint32_t pollInterval, _In_ std::string instanceId) @@ -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 &sensorIds) +{ + SWSS_LOG_ENTER(); + + FlexCounter &fc = getInstance(instanceId); + + fc.saiUpdateSupportedSwitchSensors(switchId, sensorIds); + + // Remove unsupported sensors + std::vector 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(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) @@ -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) @@ -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(); @@ -644,6 +742,7 @@ void FlexCounter::collectCounters( std::map> queueAttrIdsMap; std::map> priorityGroupCounterIdsMap; std::map> priorityGroupAttrIdsMap; + std::map> SwitchSensorIdsMap; { std::lock_guard lock(g_mutex); @@ -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 @@ -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 switchSensorValue(switchSensorIds.size()); + + // Push all counter values to a single vector + std::vector values; + + for (auto &sensor : switchSensorIds) + { + sai_attribute_t attr; + + if(SAI_SWITCH_ATTR_TEMP_LIST == sensor) { + std::vector 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(); } @@ -1094,3 +1248,51 @@ void FlexCounter::saiUpdateSupportedPriorityGroupCounters( } } } + +void FlexCounter::saiUpdateSupportedSwitchSensors( + _In_ sai_object_id_t switchId, + _In_ const std::vector &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); + } + } +} diff --git a/syncd/syncd_flex_counter.h b/syncd/syncd_flex_counter.h index fba93e928..576fa0574 100644 --- a/syncd/syncd_flex_counter.h +++ b/syncd/syncd_flex_counter.h @@ -42,6 +42,11 @@ class FlexCounter _In_ sai_object_id_t priorityGroupId, _In_ std::string instanceId, _In_ const std::vector &attrIds); + static void setSwitchSensorsList( + _In_ sai_object_id_t switchVid, + _In_ sai_object_id_t switchId, + _In_ std::string instanceId, + _In_ const std::vector &SwitchSensorIds); static void updateFlexCounterStatus( _In_ std::string status, _In_ std::string instanceId); @@ -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, @@ -130,6 +138,16 @@ class FlexCounter std::vector portCounterIds; }; + struct SwitchSensorIds + { + SwitchSensorIds( + _In_ sai_object_id_t switchId, + _In_ const std::vector &SensorIds); + + sai_object_id_t switchId; + std::vector switchSensorIds; + }; + FlexCounter(std::string instanceId); static FlexCounter& getInstance(std::string instanceId); static void removeInstance(std::string instanceId); @@ -143,9 +161,11 @@ class FlexCounter void saiUpdateSupportedPortCounters(sai_object_id_t portId); void saiUpdateSupportedQueueCounters(sai_object_id_t queueId, const std::vector &counterIds); void saiUpdateSupportedPriorityGroupCounters(sai_object_id_t priorityGroupId, const std::vector &counterIds); + void saiUpdateSupportedSwitchSensors(_In_ sai_object_id_t switchId, _In_ const std::vector &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 @@ -154,6 +174,10 @@ class FlexCounter std::map> m_queueAttrIdsMap; std::map> m_priorityGroupCounterIdsMap; std::map> m_priorityGroupAttrIdsMap; + std::map> m_switchSensorIdsMap; + + // Max number of temperature sensors + uint8_t max_temp_sensors; // Plugins std::set m_queuePlugins;