Skip to content

Commit f6c7422

Browse files
authored
ASIC internal temperature sensors support (sonic-net#1517)
**What I did** 1) ASICs have multiple internal thermal sensors. 2) With the help of configuration, a poller is introduced in Orchagent that will periodically retrieve values of these sensors with the help of SAI APIs (opencomputeproject/SAI#880). 3) These retrieved values are being populated to the state DB (In "ASIC_TEMPERATURE_INFO" table). **Why I did it** As part of ASIC Thermal Monitoring HLD.
1 parent 0aa9ef2 commit f6c7422

File tree

4 files changed

+311
-7
lines changed

4 files changed

+311
-7
lines changed

orchagent/orchdaemon.cpp

+8-1
Original file line numberDiff line numberDiff line change
@@ -74,8 +74,15 @@ bool OrchDaemon::init()
7474

7575
string platform = getenv("platform") ? getenv("platform") : "";
7676
TableConnector stateDbSwitchTable(m_stateDb, "SWITCH_CAPABILITY");
77+
TableConnector app_switch_table(m_applDb, APP_SWITCH_TABLE_NAME);
78+
TableConnector conf_asic_sensors(m_configDb, CFG_ASIC_SENSORS_TABLE_NAME);
7779

78-
gSwitchOrch = new SwitchOrch(m_applDb, APP_SWITCH_TABLE_NAME, stateDbSwitchTable);
80+
vector<TableConnector> switch_tables = {
81+
conf_asic_sensors,
82+
app_switch_table
83+
};
84+
85+
gSwitchOrch = new SwitchOrch(m_applDb, switch_tables, stateDbSwitchTable);
7986

8087
const int portsorch_base_pri = 40;
8188

orchagent/switchorch.cpp

+272-4
Original file line numberDiff line numberDiff line change
@@ -33,17 +33,100 @@ const map<string, sai_packet_action_t> packet_action_map =
3333
{"trap", SAI_PACKET_ACTION_TRAP}
3434
};
3535

36-
SwitchOrch::SwitchOrch(DBConnector *db, string tableName, TableConnector switchTable):
37-
Orch(db, tableName),
36+
SwitchOrch::SwitchOrch(DBConnector *db, vector<TableConnector>& connectors, TableConnector switchTable):
37+
Orch(connectors),
3838
m_switchTable(switchTable.first, switchTable.second),
39-
m_db(db)
39+
m_db(db),
40+
m_stateDb(new DBConnector(STATE_DB, DBConnector::DEFAULT_UNIXSOCKET, 0)),
41+
m_asicSensorsTable(new Table(m_stateDb.get(), ASIC_TEMPERATURE_INFO_TABLE_NAME)),
42+
m_sensorsPollerTimer (new SelectableTimer((timespec { .tv_sec = DEFAULT_ASIC_SENSORS_POLLER_INTERVAL, .tv_nsec = 0 })))
4043
{
4144
m_restartCheckNotificationConsumer = new NotificationConsumer(db, "RESTARTCHECK");
4245
auto restartCheckNotifier = new Notifier(m_restartCheckNotificationConsumer, this, "RESTARTCHECK");
4346
Orch::addExecutor(restartCheckNotifier);
47+
48+
initSensorsTable();
49+
auto executorT = new ExecutableTimer(m_sensorsPollerTimer, this, "ASIC_SENSORS_POLL_TIMER");
50+
Orch::addExecutor(executorT);
4451
}
4552

46-
void SwitchOrch::doTask(Consumer &consumer)
53+
void SwitchOrch::doCfgSensorsTableTask(Consumer &consumer)
54+
{
55+
SWSS_LOG_ENTER();
56+
57+
auto it = consumer.m_toSync.begin();
58+
while (it != consumer.m_toSync.end())
59+
{
60+
KeyOpFieldsValuesTuple t = it->second;
61+
string table_attr = kfvKey(t);
62+
string op = kfvOp(t);
63+
64+
if (op == SET_COMMAND)
65+
{
66+
FieldValueTuple fvt = kfvFieldsValues(t)[0];
67+
SWSS_LOG_NOTICE("ASIC sensors : set %s(%s) to %s", table_attr.c_str(), fvField(fvt).c_str(), fvValue(fvt).c_str());
68+
69+
if (table_attr == ASIC_SENSORS_POLLER_STATUS)
70+
{
71+
if (fvField(fvt) == "admin_status")
72+
{
73+
if (fvValue(fvt) == "enable" && !m_sensorsPollerEnabled)
74+
{
75+
m_sensorsPollerTimer->start();
76+
m_sensorsPollerEnabled = true;
77+
}
78+
else if (fvValue(fvt) == "disable")
79+
{
80+
m_sensorsPollerEnabled = false;
81+
}
82+
else
83+
{
84+
SWSS_LOG_ERROR("ASIC sensors : unsupported operation for poller state %d",m_sensorsPollerEnabled);
85+
}
86+
}
87+
else
88+
{
89+
SWSS_LOG_ERROR("ASIC sensors : unsupported field in attribute %s", ASIC_SENSORS_POLLER_STATUS);
90+
}
91+
}
92+
else if (table_attr == ASIC_SENSORS_POLLER_INTERVAL)
93+
{
94+
uint32_t interval=to_uint<uint32_t>(fvValue(fvt));
95+
96+
if (fvField(fvt) == "interval")
97+
{
98+
if (interval != m_sensorsPollerInterval)
99+
{
100+
auto intervT = timespec { .tv_sec = interval , .tv_nsec = 0 };
101+
m_sensorsPollerTimer->setInterval(intervT);
102+
m_sensorsPollerInterval = interval;
103+
m_sensorsPollerIntervalChanged = true;
104+
}
105+
else
106+
{
107+
SWSS_LOG_INFO("ASIC sensors : poller interval unchanged : %d seconds",m_sensorsPollerInterval);
108+
}
109+
}
110+
else
111+
{
112+
SWSS_LOG_ERROR("ASIC sensors : unsupported field in attribute %s", ASIC_SENSORS_POLLER_INTERVAL);
113+
}
114+
}
115+
else
116+
{
117+
SWSS_LOG_ERROR("ASIC sensors : unsupported attribute %s", table_attr.c_str());
118+
}
119+
}
120+
else
121+
{
122+
SWSS_LOG_ERROR("ASIC sensors : unsupported operation %s",op.c_str());
123+
}
124+
125+
it = consumer.m_toSync.erase(it);
126+
}
127+
}
128+
129+
void SwitchOrch::doAppSwitchTableTask(Consumer &consumer)
47130
{
48131
SWSS_LOG_ENTER();
49132

@@ -145,6 +228,26 @@ void SwitchOrch::doTask(Consumer &consumer)
145228
}
146229
}
147230

231+
void SwitchOrch::doTask(Consumer &consumer)
232+
{
233+
SWSS_LOG_ENTER();
234+
const string & table_name = consumer.getTableName();
235+
236+
if (table_name == APP_SWITCH_TABLE_NAME)
237+
{
238+
doAppSwitchTableTask(consumer);
239+
}
240+
else if (table_name == CFG_ASIC_SENSORS_TABLE_NAME)
241+
{
242+
doCfgSensorsTableTask(consumer);
243+
}
244+
else
245+
{
246+
SWSS_LOG_ERROR("Unknown table : %s", table_name.c_str());
247+
}
248+
249+
}
250+
148251
void SwitchOrch::doTask(NotificationConsumer& consumer)
149252
{
150253
SWSS_LOG_ENTER();
@@ -209,6 +312,171 @@ bool SwitchOrch::setAgingFDB(uint32_t sec)
209312
return true;
210313
}
211314

315+
void SwitchOrch::doTask(SelectableTimer &timer)
316+
{
317+
SWSS_LOG_ENTER();
318+
319+
if (&timer == m_sensorsPollerTimer)
320+
{
321+
if (m_sensorsPollerIntervalChanged)
322+
{
323+
m_sensorsPollerTimer->reset();
324+
m_sensorsPollerIntervalChanged = false;
325+
}
326+
327+
if (!m_sensorsPollerEnabled)
328+
{
329+
m_sensorsPollerTimer->stop();
330+
return;
331+
}
332+
333+
sai_attribute_t attr;
334+
sai_status_t status;
335+
std::vector<FieldValueTuple> values;
336+
337+
if (m_numTempSensors)
338+
{
339+
std::vector<int32_t> temp_list(m_numTempSensors);
340+
341+
memset(&attr, 0, sizeof(attr));
342+
attr.id = SAI_SWITCH_ATTR_TEMP_LIST;
343+
attr.value.s32list.count = m_numTempSensors;
344+
attr.value.s32list.list = temp_list.data();
345+
346+
status = sai_switch_api->get_switch_attribute(gSwitchId , 1, &attr);
347+
if (status == SAI_STATUS_SUCCESS)
348+
{
349+
for (size_t i = 0; i < attr.value.s32list.count ; i++) {
350+
const std::string &fieldName = "temperature_" + std::to_string(i);
351+
values.emplace_back(fieldName, std::to_string(temp_list[i]));
352+
}
353+
m_asicSensorsTable->set("",values);
354+
}
355+
else
356+
{
357+
SWSS_LOG_ERROR("ASIC sensors : failed to get SAI_SWITCH_ATTR_TEMP_LIST: %d", status);
358+
}
359+
}
360+
361+
if (m_sensorsMaxTempSupported)
362+
{
363+
memset(&attr, 0, sizeof(attr));
364+
attr.id = SAI_SWITCH_ATTR_MAX_TEMP;
365+
366+
status = sai_switch_api->get_switch_attribute(gSwitchId, 1, &attr);
367+
if (status == SAI_STATUS_SUCCESS)
368+
{
369+
const std::string &fieldName = "maximum_temperature";
370+
values.emplace_back(fieldName, std::to_string(attr.value.s32));
371+
m_asicSensorsTable->set("",values);
372+
}
373+
else if (status == SAI_STATUS_NOT_SUPPORTED || status == SAI_STATUS_NOT_IMPLEMENTED)
374+
{
375+
m_sensorsMaxTempSupported = false;
376+
SWSS_LOG_INFO("ASIC sensors : SAI_SWITCH_ATTR_MAX_TEMP is not supported");
377+
}
378+
else
379+
{
380+
m_sensorsMaxTempSupported = false;
381+
SWSS_LOG_ERROR("ASIC sensors : failed to get SAI_SWITCH_ATTR_MAX_TEMP: %d", status);
382+
}
383+
}
384+
385+
if (m_sensorsAvgTempSupported)
386+
{
387+
memset(&attr, 0, sizeof(attr));
388+
attr.id = SAI_SWITCH_ATTR_AVERAGE_TEMP;
389+
390+
status = sai_switch_api->get_switch_attribute(gSwitchId, 1, &attr);
391+
if (status == SAI_STATUS_SUCCESS)
392+
{
393+
const std::string &fieldName = "average_temperature";
394+
values.emplace_back(fieldName, std::to_string(attr.value.s32));
395+
m_asicSensorsTable->set("",values);
396+
}
397+
else if (status == SAI_STATUS_NOT_SUPPORTED || status == SAI_STATUS_NOT_IMPLEMENTED)
398+
{
399+
m_sensorsAvgTempSupported = false;
400+
SWSS_LOG_INFO("ASIC sensors : SAI_SWITCH_ATTR_AVERAGE_TEMP is not supported");
401+
}
402+
else
403+
{
404+
m_sensorsAvgTempSupported = false;
405+
SWSS_LOG_ERROR("ASIC sensors : failed to get SAI_SWITCH_ATTR_AVERAGE_TEMP: %d", status);
406+
}
407+
}
408+
}
409+
}
410+
411+
void SwitchOrch::initSensorsTable()
412+
{
413+
SWSS_LOG_ENTER();
414+
415+
sai_attribute_t attr;
416+
sai_status_t status;
417+
std::vector<FieldValueTuple> values;
418+
419+
if (!m_numTempSensorsInitialized)
420+
{
421+
memset(&attr, 0, sizeof(attr));
422+
attr.id = SAI_SWITCH_ATTR_MAX_NUMBER_OF_TEMP_SENSORS;
423+
424+
status = sai_switch_api->get_switch_attribute(gSwitchId, 1, &attr);
425+
if (status == SAI_STATUS_SUCCESS)
426+
{
427+
m_numTempSensors = attr.value.u8;
428+
m_numTempSensorsInitialized = true;
429+
}
430+
else if (status == SAI_STATUS_NOT_SUPPORTED || status == SAI_STATUS_NOT_IMPLEMENTED)
431+
{
432+
m_numTempSensorsInitialized = true;
433+
SWSS_LOG_INFO("ASIC sensors : SAI_SWITCH_ATTR_MAX_NUMBER_OF_TEMP_SENSORS is not supported");
434+
}
435+
else
436+
{
437+
SWSS_LOG_ERROR("ASIC sensors : failed to get SAI_SWITCH_ATTR_MAX_NUMBER_OF_TEMP_SENSORS: %d", status);
438+
}
439+
}
440+
441+
if (m_numTempSensors)
442+
{
443+
std::vector<int32_t> temp_list(m_numTempSensors);
444+
445+
memset(&attr, 0, sizeof(attr));
446+
attr.id = SAI_SWITCH_ATTR_TEMP_LIST;
447+
attr.value.s32list.count = m_numTempSensors;
448+
attr.value.s32list.list = temp_list.data();
449+
450+
status = sai_switch_api->get_switch_attribute(gSwitchId , 1, &attr);
451+
if (status == SAI_STATUS_SUCCESS)
452+
{
453+
for (size_t i = 0; i < attr.value.s32list.count ; i++) {
454+
const std::string &fieldName = "temperature_" + std::to_string(i);
455+
values.emplace_back(fieldName, std::to_string(0));
456+
}
457+
m_asicSensorsTable->set("",values);
458+
}
459+
else
460+
{
461+
SWSS_LOG_ERROR("ASIC sensors : failed to get SAI_SWITCH_ATTR_TEMP_LIST: %d", status);
462+
}
463+
}
464+
465+
if (m_sensorsMaxTempSupported)
466+
{
467+
const std::string &fieldName = "maximum_temperature";
468+
values.emplace_back(fieldName, std::to_string(0));
469+
m_asicSensorsTable->set("",values);
470+
}
471+
472+
if (m_sensorsAvgTempSupported)
473+
{
474+
const std::string &fieldName = "average_temperature";
475+
values.emplace_back(fieldName, std::to_string(0));
476+
m_asicSensorsTable->set("",values);
477+
}
478+
}
479+
212480
void SwitchOrch::set_switch_capability(const std::vector<FieldValueTuple>& values)
213481
{
214482
m_switchTable.set("switch", values);

orchagent/switchorch.h

+22-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,11 @@
11
#pragma once
22

33
#include "orch.h"
4+
#include "timer.h"
5+
6+
#define DEFAULT_ASIC_SENSORS_POLLER_INTERVAL 60
7+
#define ASIC_SENSORS_POLLER_STATUS "ASIC_SENSORS_POLLER_STATUS"
8+
#define ASIC_SENSORS_POLLER_INTERVAL "ASIC_SENSORS_POLLER_INTERVAL"
49

510
struct WarmRestartCheck
611
{
@@ -12,7 +17,7 @@ struct WarmRestartCheck
1217
class SwitchOrch : public Orch
1318
{
1419
public:
15-
SwitchOrch(swss::DBConnector *db, std::string tableName, TableConnector switchTable);
20+
SwitchOrch(swss::DBConnector *db, std::vector<TableConnector>& connectors, TableConnector switchTable);
1621
bool checkRestartReady() { return m_warmRestartCheck.checkRestartReadyState; }
1722
bool checkRestartNoFreeze() { return m_warmRestartCheck.noFreeze; }
1823
bool skipPendingTaskCheck() { return m_warmRestartCheck.skipPendingTaskCheck; }
@@ -22,12 +27,28 @@ class SwitchOrch : public Orch
2227
void set_switch_capability(const std::vector<swss::FieldValueTuple>& values);
2328
private:
2429
void doTask(Consumer &consumer);
30+
void doTask(swss::SelectableTimer &timer);
31+
void doCfgSensorsTableTask(Consumer &consumer);
32+
void doAppSwitchTableTask(Consumer &consumer);
33+
void initSensorsTable();
2534

2635
swss::NotificationConsumer* m_restartCheckNotificationConsumer;
2736
void doTask(swss::NotificationConsumer& consumer);
2837
swss::DBConnector *m_db;
2938
swss::Table m_switchTable;
3039

40+
// ASIC temperature sensors
41+
std::shared_ptr<swss::DBConnector> m_stateDb = nullptr;
42+
std::shared_ptr<swss::Table> m_asicSensorsTable= nullptr;
43+
swss::SelectableTimer* m_sensorsPollerTimer = nullptr;
44+
bool m_sensorsPollerEnabled = false;
45+
uint32_t m_sensorsPollerInterval = DEFAULT_ASIC_SENSORS_POLLER_INTERVAL;
46+
bool m_sensorsPollerIntervalChanged = false;
47+
uint8_t m_numTempSensors = 0;
48+
bool m_numTempSensorsInitialized = false;
49+
bool m_sensorsMaxTempSupported = true;
50+
bool m_sensorsAvgTempSupported = true;
51+
3152
// Information contained in the request from
3253
// external program for orchagent pre-shutdown state check
3354
WarmRestartCheck m_warmRestartCheck = {false, false, false};

tests/mock_tests/aclorch_ut.cpp

+9-1
Original file line numberDiff line numberDiff line change
@@ -286,8 +286,16 @@ namespace aclorch_test
286286
gVirtualRouterId = attr.value.oid;
287287

288288
TableConnector stateDbSwitchTable(m_state_db.get(), "SWITCH_CAPABILITY");
289+
TableConnector conf_asic_sensors(m_config_db.get(), CFG_ASIC_SENSORS_TABLE_NAME);
290+
TableConnector app_switch_table(m_app_db.get(), APP_SWITCH_TABLE_NAME);
291+
292+
vector<TableConnector> switch_tables = {
293+
conf_asic_sensors,
294+
app_switch_table
295+
};
296+
289297
ASSERT_EQ(gSwitchOrch, nullptr);
290-
gSwitchOrch = new SwitchOrch(m_app_db.get(), APP_SWITCH_TABLE_NAME, stateDbSwitchTable);
298+
gSwitchOrch = new SwitchOrch(m_app_db.get(), switch_tables, stateDbSwitchTable);
291299

292300
// Create dependencies ...
293301

0 commit comments

Comments
 (0)