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 internal temperature sensors support #1517

Merged
merged 3 commits into from
Jan 4, 2021
Merged
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
9 changes: 8 additions & 1 deletion orchagent/orchdaemon.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -73,8 +73,15 @@ bool OrchDaemon::init()

string platform = getenv("platform") ? getenv("platform") : "";
TableConnector stateDbSwitchTable(m_stateDb, "SWITCH_CAPABILITY");
TableConnector app_switch_table(m_applDb, APP_SWITCH_TABLE_NAME);
TableConnector conf_asic_sensors(m_configDb, CFG_ASIC_SENSORS_TABLE_NAME);

gSwitchOrch = new SwitchOrch(m_applDb, APP_SWITCH_TABLE_NAME, stateDbSwitchTable);
vector<TableConnector> switch_tables = {
conf_asic_sensors,
app_switch_table
};

gSwitchOrch = new SwitchOrch(m_applDb, switch_tables, stateDbSwitchTable);

const int portsorch_base_pri = 40;

Expand Down
276 changes: 272 additions & 4 deletions orchagent/switchorch.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -33,17 +33,100 @@ const map<string, sai_packet_action_t> packet_action_map =
{"trap", SAI_PACKET_ACTION_TRAP}
};

SwitchOrch::SwitchOrch(DBConnector *db, string tableName, TableConnector switchTable):
Orch(db, tableName),
SwitchOrch::SwitchOrch(DBConnector *db, vector<TableConnector>& connectors, TableConnector switchTable):
Orch(connectors),
m_switchTable(switchTable.first, switchTable.second),
m_db(db)
m_db(db),
m_stateDb(new DBConnector(STATE_DB, DBConnector::DEFAULT_UNIXSOCKET, 0)),
m_asicSensorsTable(new Table(m_stateDb.get(), ASIC_TEMPERATURE_INFO_TABLE_NAME)),
m_sensorsPollerTimer (new SelectableTimer((timespec { .tv_sec = DEFAULT_ASIC_SENSORS_POLLER_INTERVAL, .tv_nsec = 0 })))
{
m_restartCheckNotificationConsumer = new NotificationConsumer(db, "RESTARTCHECK");
auto restartCheckNotifier = new Notifier(m_restartCheckNotificationConsumer, this, "RESTARTCHECK");
Orch::addExecutor(restartCheckNotifier);

initSensorsTable();
auto executorT = new ExecutableTimer(m_sensorsPollerTimer, this, "ASIC_SENSORS_POLL_TIMER");
Orch::addExecutor(executorT);
}

void SwitchOrch::doTask(Consumer &consumer)
void SwitchOrch::doCfgSensorsTableTask(Consumer &consumer)
{
SWSS_LOG_ENTER();

auto it = consumer.m_toSync.begin();
while (it != consumer.m_toSync.end())
{
KeyOpFieldsValuesTuple t = it->second;
string table_attr = kfvKey(t);
string op = kfvOp(t);

if (op == SET_COMMAND)
{
FieldValueTuple fvt = kfvFieldsValues(t)[0];
SWSS_LOG_NOTICE("ASIC sensors : set %s(%s) to %s", table_attr.c_str(), fvField(fvt).c_str(), fvValue(fvt).c_str());

if (table_attr == ASIC_SENSORS_POLLER_STATUS)
{
if (fvField(fvt) == "admin_status")
{
if (fvValue(fvt) == "enable" && !m_sensorsPollerEnabled)
{
m_sensorsPollerTimer->start();
m_sensorsPollerEnabled = true;
}
else if (fvValue(fvt) == "disable")
{
m_sensorsPollerEnabled = false;
}
else
{
SWSS_LOG_ERROR("ASIC sensors : unsupported operation for poller state %d",m_sensorsPollerEnabled);
}
}
else
{
SWSS_LOG_ERROR("ASIC sensors : unsupported field in attribute %s", ASIC_SENSORS_POLLER_STATUS);
}
}
else if (table_attr == ASIC_SENSORS_POLLER_INTERVAL)
{
uint32_t interval=to_uint<uint32_t>(fvValue(fvt));

if (fvField(fvt) == "interval")
{
if (interval != m_sensorsPollerInterval)
{
auto intervT = timespec { .tv_sec = interval , .tv_nsec = 0 };
m_sensorsPollerTimer->setInterval(intervT);
m_sensorsPollerInterval = interval;
m_sensorsPollerIntervalChanged = true;
}
else
{
SWSS_LOG_INFO("ASIC sensors : poller interval unchanged : %d seconds",m_sensorsPollerInterval);
}
}
else
{
SWSS_LOG_ERROR("ASIC sensors : unsupported field in attribute %s", ASIC_SENSORS_POLLER_INTERVAL);
}
}
else
{
SWSS_LOG_ERROR("ASIC sensors : unsupported attribute %s", table_attr.c_str());
}
}
else
{
SWSS_LOG_ERROR("ASIC sensors : unsupported operation %s",op.c_str());
}

it = consumer.m_toSync.erase(it);
}
}

void SwitchOrch::doAppSwitchTableTask(Consumer &consumer)
{
SWSS_LOG_ENTER();

Expand Down Expand Up @@ -145,6 +228,26 @@ void SwitchOrch::doTask(Consumer &consumer)
}
}

void SwitchOrch::doTask(Consumer &consumer)
{
SWSS_LOG_ENTER();
const string & table_name = consumer.getTableName();

if (table_name == APP_SWITCH_TABLE_NAME)
{
doAppSwitchTableTask(consumer);
}
else if (table_name == CFG_ASIC_SENSORS_TABLE_NAME)
{
doCfgSensorsTableTask(consumer);
}
else
{
SWSS_LOG_ERROR("Unknown table : %s", table_name.c_str());
}

}

void SwitchOrch::doTask(NotificationConsumer& consumer)
{
SWSS_LOG_ENTER();
Expand Down Expand Up @@ -209,6 +312,171 @@ bool SwitchOrch::setAgingFDB(uint32_t sec)
return true;
}

void SwitchOrch::doTask(SelectableTimer &timer)
{
SWSS_LOG_ENTER();

if (&timer == m_sensorsPollerTimer)
{
if (m_sensorsPollerIntervalChanged)
{
m_sensorsPollerTimer->reset();
m_sensorsPollerIntervalChanged = false;
}

if (!m_sensorsPollerEnabled)
{
m_sensorsPollerTimer->stop();
return;
}

sai_attribute_t attr;
sai_status_t status;
std::vector<FieldValueTuple> values;

if (m_numTempSensors)
{
std::vector<int32_t> temp_list(m_numTempSensors);

memset(&attr, 0, sizeof(attr));
attr.id = SAI_SWITCH_ATTR_TEMP_LIST;
attr.value.s32list.count = m_numTempSensors;
attr.value.s32list.list = temp_list.data();

status = sai_switch_api->get_switch_attribute(gSwitchId , 1, &attr);
if (status == SAI_STATUS_SUCCESS)
{
for (size_t i = 0; i < attr.value.s32list.count ; i++) {
const std::string &fieldName = "temperature_" + std::to_string(i);
values.emplace_back(fieldName, std::to_string(temp_list[i]));
}
m_asicSensorsTable->set("",values);
}
else
{
SWSS_LOG_ERROR("ASIC sensors : failed to get SAI_SWITCH_ATTR_TEMP_LIST: %d", status);
}
}

if (m_sensorsMaxTempSupported)
{
memset(&attr, 0, sizeof(attr));
attr.id = SAI_SWITCH_ATTR_MAX_TEMP;

status = sai_switch_api->get_switch_attribute(gSwitchId, 1, &attr);
if (status == SAI_STATUS_SUCCESS)
{
const std::string &fieldName = "maximum_temperature";
values.emplace_back(fieldName, std::to_string(attr.value.s32));
m_asicSensorsTable->set("",values);
}
else if (status == SAI_STATUS_NOT_SUPPORTED || status == SAI_STATUS_NOT_IMPLEMENTED)
{
m_sensorsMaxTempSupported = false;
SWSS_LOG_INFO("ASIC sensors : SAI_SWITCH_ATTR_MAX_TEMP is not supported");
}
else
{
m_sensorsMaxTempSupported = false;
SWSS_LOG_ERROR("ASIC sensors : failed to get SAI_SWITCH_ATTR_MAX_TEMP: %d", status);
}
}

if (m_sensorsAvgTempSupported)
{
memset(&attr, 0, sizeof(attr));
attr.id = SAI_SWITCH_ATTR_AVERAGE_TEMP;

status = sai_switch_api->get_switch_attribute(gSwitchId, 1, &attr);
if (status == SAI_STATUS_SUCCESS)
{
const std::string &fieldName = "average_temperature";
values.emplace_back(fieldName, std::to_string(attr.value.s32));
m_asicSensorsTable->set("",values);
}
else if (status == SAI_STATUS_NOT_SUPPORTED || status == SAI_STATUS_NOT_IMPLEMENTED)
{
m_sensorsAvgTempSupported = false;
SWSS_LOG_INFO("ASIC sensors : SAI_SWITCH_ATTR_AVERAGE_TEMP is not supported");
}
else
{
m_sensorsAvgTempSupported = false;
SWSS_LOG_ERROR("ASIC sensors : failed to get SAI_SWITCH_ATTR_AVERAGE_TEMP: %d", status);
}
}
}
}

void SwitchOrch::initSensorsTable()
{
SWSS_LOG_ENTER();

sai_attribute_t attr;
sai_status_t status;
std::vector<FieldValueTuple> values;

if (!m_numTempSensorsInitialized)
{
memset(&attr, 0, sizeof(attr));
attr.id = SAI_SWITCH_ATTR_MAX_NUMBER_OF_TEMP_SENSORS;

status = sai_switch_api->get_switch_attribute(gSwitchId, 1, &attr);
if (status == SAI_STATUS_SUCCESS)
{
m_numTempSensors = attr.value.u8;
m_numTempSensorsInitialized = true;
}
else if (status == SAI_STATUS_NOT_SUPPORTED || status == SAI_STATUS_NOT_IMPLEMENTED)
{
m_numTempSensorsInitialized = true;
SWSS_LOG_INFO("ASIC sensors : SAI_SWITCH_ATTR_MAX_NUMBER_OF_TEMP_SENSORS is not supported");
}
else
{
SWSS_LOG_ERROR("ASIC sensors : failed to get SAI_SWITCH_ATTR_MAX_NUMBER_OF_TEMP_SENSORS: %d", status);
}
}

if (m_numTempSensors)
{
std::vector<int32_t> temp_list(m_numTempSensors);

memset(&attr, 0, sizeof(attr));
attr.id = SAI_SWITCH_ATTR_TEMP_LIST;
attr.value.s32list.count = m_numTempSensors;
attr.value.s32list.list = temp_list.data();

status = sai_switch_api->get_switch_attribute(gSwitchId , 1, &attr);
if (status == SAI_STATUS_SUCCESS)
{
for (size_t i = 0; i < attr.value.s32list.count ; i++) {
const std::string &fieldName = "temperature_" + std::to_string(i);
values.emplace_back(fieldName, std::to_string(0));
}
m_asicSensorsTable->set("",values);
}
else
{
SWSS_LOG_ERROR("ASIC sensors : failed to get SAI_SWITCH_ATTR_TEMP_LIST: %d", status);
}
}

if (m_sensorsMaxTempSupported)
{
const std::string &fieldName = "maximum_temperature";
values.emplace_back(fieldName, std::to_string(0));
m_asicSensorsTable->set("",values);
}

if (m_sensorsAvgTempSupported)
{
const std::string &fieldName = "average_temperature";
values.emplace_back(fieldName, std::to_string(0));
m_asicSensorsTable->set("",values);
}
}

void SwitchOrch::set_switch_capability(const std::vector<FieldValueTuple>& values)
{
m_switchTable.set("switch", values);
Expand Down
23 changes: 22 additions & 1 deletion orchagent/switchorch.h
Original file line number Diff line number Diff line change
@@ -1,6 +1,11 @@
#pragma once

#include "orch.h"
#include "timer.h"

#define DEFAULT_ASIC_SENSORS_POLLER_INTERVAL 60
#define ASIC_SENSORS_POLLER_STATUS "ASIC_SENSORS_POLLER_STATUS"
#define ASIC_SENSORS_POLLER_INTERVAL "ASIC_SENSORS_POLLER_INTERVAL"

struct WarmRestartCheck
{
Expand All @@ -12,7 +17,7 @@ struct WarmRestartCheck
class SwitchOrch : public Orch
{
public:
SwitchOrch(swss::DBConnector *db, std::string tableName, TableConnector switchTable);
SwitchOrch(swss::DBConnector *db, std::vector<TableConnector>& connectors, TableConnector switchTable);
bool checkRestartReady() { return m_warmRestartCheck.checkRestartReadyState; }
bool checkRestartNoFreeze() { return m_warmRestartCheck.noFreeze; }
bool skipPendingTaskCheck() { return m_warmRestartCheck.skipPendingTaskCheck; }
Expand All @@ -22,12 +27,28 @@ class SwitchOrch : public Orch
void set_switch_capability(const std::vector<swss::FieldValueTuple>& values);
private:
void doTask(Consumer &consumer);
void doTask(swss::SelectableTimer &timer);
void doCfgSensorsTableTask(Consumer &consumer);
void doAppSwitchTableTask(Consumer &consumer);
void initSensorsTable();

swss::NotificationConsumer* m_restartCheckNotificationConsumer;
void doTask(swss::NotificationConsumer& consumer);
swss::DBConnector *m_db;
swss::Table m_switchTable;

// ASIC temperature sensors
std::shared_ptr<swss::DBConnector> m_stateDb = nullptr;
std::shared_ptr<swss::Table> m_asicSensorsTable= nullptr;
swss::SelectableTimer* m_sensorsPollerTimer = nullptr;
bool m_sensorsPollerEnabled = false;
uint32_t m_sensorsPollerInterval = DEFAULT_ASIC_SENSORS_POLLER_INTERVAL;
bool m_sensorsPollerIntervalChanged = false;
uint8_t m_numTempSensors = 0;
bool m_numTempSensorsInitialized = false;
bool m_sensorsMaxTempSupported = true;
bool m_sensorsAvgTempSupported = true;

// Information contained in the request from
// external program for orchagent pre-shutdown state check
WarmRestartCheck m_warmRestartCheck = {false, false, false};
Expand Down
10 changes: 9 additions & 1 deletion tests/mock_tests/aclorch_ut.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -286,8 +286,16 @@ namespace aclorch_test
gVirtualRouterId = attr.value.oid;

TableConnector stateDbSwitchTable(m_state_db.get(), "SWITCH_CAPABILITY");
TableConnector conf_asic_sensors(m_config_db.get(), CFG_ASIC_SENSORS_TABLE_NAME);
TableConnector app_switch_table(m_app_db.get(), APP_SWITCH_TABLE_NAME);

vector<TableConnector> switch_tables = {
conf_asic_sensors,
app_switch_table
};

ASSERT_EQ(gSwitchOrch, nullptr);
gSwitchOrch = new SwitchOrch(m_app_db.get(), APP_SWITCH_TABLE_NAME, stateDbSwitchTable);
gSwitchOrch = new SwitchOrch(m_app_db.get(), switch_tables, stateDbSwitchTable);

// Create dependencies ...

Expand Down