ipmitool/lib/ipmi_sensor.c
eyjhbb@gmail.com 6f336d04f1 sensor: Refactor ipmi_sensor_print_fc_threshold()
Break the function into smaller pieces to reduce
complexity.
2018-09-25 14:32:46 +03:00

1068 lines
30 KiB
C

/*
* Copyright (c) 2003 Sun Microsystems, Inc. All Rights Reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* Redistribution of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* Redistribution in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* Neither the name of Sun Microsystems, Inc. or the names of
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* This software is provided "AS IS," without a warranty of any kind.
* ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES,
* INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A
* PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED.
* SUN MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE
* FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING
* OR DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL
* SUN OR ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA,
* OR FOR DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR
* PUNITIVE DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF
* LIABILITY, ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE,
* EVEN IF SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
*/
#include <string.h>
#include <math.h>
#include <ipmitool/ipmi.h>
#include <ipmitool/helper.h>
#include <ipmitool/log.h>
#include <ipmitool/ipmi_intf.h>
#include <ipmitool/ipmi_sdr.h>
#include <ipmitool/ipmi_sel.h>
#include <ipmitool/ipmi_sensor.h>
extern int verbose;
void print_sensor_get_usage();
void print_sensor_thresh_usage();
// Macro's for Reading the current sensor Data.
#define SCANNING_DISABLED 0x40
#define READING_UNAVAILABLE 0x20
#define INVALID_THRESHOLD "Invalid Threshold data values. Cannot Set Threshold Data."
// static
int
ipmi_sensor_get_sensor_reading_factors(
struct ipmi_intf * intf,
struct sdr_record_full_sensor * sensor,
uint8_t reading)
{
struct ipmi_rq req;
struct ipmi_rs * rsp;
uint8_t req_data[2];
char id[17];
if (!intf || !sensor)
return -1;
memset(id, 0, sizeof(id));
memcpy(id, sensor->id_string, 16);
req_data[0] = sensor->cmn.keys.sensor_num;
req_data[1] = reading;
memset(&req, 0, sizeof(req));
req.msg.netfn = IPMI_NETFN_SE;
req.msg.lun = sensor->cmn.keys.lun;
req.msg.cmd = GET_SENSOR_FACTORS;
req.msg.data = req_data;
req.msg.data_len = sizeof(req_data);
rsp = intf->sendrecv(intf, &req);
if (!rsp) {
lprintf(LOG_ERR, "Error updating reading factor for sensor %s (#%02x)",
id, sensor->cmn.keys.sensor_num);
return -1;
} else if (rsp->ccode) {
return -1;
} else {
/* Update SDR copy with updated Reading Factors for this reading */
/* Note:
* The Format of the returned data is exactly as in the SDR definition (Little Endian Format),
* therefore we can use raw copy operation here.
* Note: rsp->data[0] would point to the next valid entry in the sampling table
*/
// BUGBUG: uses 'hardcoded' length information from SDR Definition
memcpy(&sensor->mtol, &rsp->data[1], sizeof(sensor->mtol));
memcpy(&sensor->bacc, &rsp->data[3], sizeof(sensor->bacc));
return 0;
}
}
static
struct ipmi_rs *
ipmi_sensor_set_sensor_thresholds(struct ipmi_intf *intf,
uint8_t sensor,
uint8_t threshold, uint8_t setting,
uint8_t target, uint8_t lun, uint8_t channel)
{
struct ipmi_rq req;
static struct sensor_set_thresh_rq set_thresh_rq;
struct ipmi_rs *rsp;
uint8_t bridged_request = 0;
uint32_t save_addr;
uint32_t save_channel;
memset(&set_thresh_rq, 0, sizeof (set_thresh_rq));
set_thresh_rq.sensor_num = sensor;
set_thresh_rq.set_mask = threshold;
if (threshold == UPPER_NON_RECOV_SPECIFIED)
set_thresh_rq.upper_non_recov = setting;
else if (threshold == UPPER_CRIT_SPECIFIED)
set_thresh_rq.upper_crit = setting;
else if (threshold == UPPER_NON_CRIT_SPECIFIED)
set_thresh_rq.upper_non_crit = setting;
else if (threshold == LOWER_NON_CRIT_SPECIFIED)
set_thresh_rq.lower_non_crit = setting;
else if (threshold == LOWER_CRIT_SPECIFIED)
set_thresh_rq.lower_crit = setting;
else if (threshold == LOWER_NON_RECOV_SPECIFIED)
set_thresh_rq.lower_non_recov = setting;
else
return NULL;
if (BRIDGE_TO_SENSOR(intf, target, channel)) {
bridged_request = 1;
save_addr = intf->target_addr;
intf->target_addr = target;
save_channel = intf->target_channel;
intf->target_channel = channel;
}
memset(&req, 0, sizeof (req));
req.msg.netfn = IPMI_NETFN_SE;
req.msg.lun = lun;
req.msg.cmd = SET_SENSOR_THRESHOLDS;
req.msg.data = (uint8_t *) & set_thresh_rq;
req.msg.data_len = sizeof (set_thresh_rq);
rsp = intf->sendrecv(intf, &req);
if (bridged_request) {
intf->target_addr = save_addr;
intf->target_channel = save_channel;
}
return rsp;
}
static int
ipmi_sensor_print_fc_discrete(struct ipmi_intf *intf,
struct sdr_record_common_sensor *sensor,
uint8_t sdr_record_type)
{
struct sensor_reading *sr;
sr = ipmi_sdr_read_sensor_value(intf, sensor, sdr_record_type, 3);
if (!sr) {
return -1;
}
if (csv_output) {
printf("%s", sr->s_id);
if (sr->s_reading_valid) {
if (sr->s_has_analog_value) {
/* don't show discrete component */
printf(",%s,%s,%s",
sr->s_a_str, sr->s_a_units, "ok");
} else {
printf(",0x%x,%s,0x%02x%02x",
sr->s_reading, "discrete",
sr->s_data2, sr->s_data3);
}
} else {
printf(",%s,%s,%s",
"na", "discrete", "na");
}
printf(",%s,%s,%s,%s,%s,%s",
"na", "na", "na", "na", "na", "na");
printf("\n");
} else {
if (verbose == 0) {
/* output format
* id value units status thresholds....
*/
printf("%-16s ", sr->s_id);
if (sr->s_reading_valid) {
if (sr->s_has_analog_value) {
/* don't show discrete component */
printf("| %-10s | %-10s | %-6s",
sr->s_a_str, sr->s_a_units, "ok");
} else {
printf("| 0x%-8x | %-10s | 0x%02x%02x",
sr->s_reading, "discrete",
sr->s_data2, sr->s_data3);
}
} else {
printf("| %-10s | %-10s | %-6s",
"na", "discrete", "na");
}
printf("| %-10s| %-10s| %-10s| %-10s| %-10s| %-10s",
"na", "na", "na", "na", "na", "na");
printf("\n");
} else {
printf("Sensor ID : %s (0x%x)\n",
sr->s_id, sensor->keys.sensor_num);
printf(" Entity ID : %d.%d\n",
sensor->entity.id, sensor->entity.instance);
printf(" Sensor Type (Discrete): %s\n",
ipmi_get_sensor_type(intf, sensor->sensor.
type));
if( sr->s_reading_valid )
{
if (sr->s_has_analog_value) {
printf(" Sensor Reading : %s %s\n", sr->s_a_str, sr->s_a_units);
}
ipmi_sdr_print_discrete_state(intf, "States Asserted",
sensor->sensor.type,
sensor->event_type,
sr->s_data2,
sr->s_data3);
printf("\n");
} else {
printf(" Unable to read sensor: Device Not Present\n\n");
}
}
}
return (sr->s_reading_valid ? 0 : -1 );
}
static void
print_thresh_setting(struct sdr_record_full_sensor *full,
uint8_t thresh_is_avail, uint8_t setting,
const char *field_sep,
const char *analog_fmt,
const char *discrete_fmt,
const char *na_fmt)
{
printf("%s", field_sep);
if (!thresh_is_avail) {
printf(na_fmt, "na");
return;
}
if (full && !UNITS_ARE_DISCRETE(&full->cmn)) {
printf(analog_fmt, sdr_convert_sensor_reading (full, setting));
} else {
printf(discrete_fmt, setting);
}
}
static void
dump_sensor_fc_thredshold_csv(
int thresh_available,
const char *thresh_status,
struct ipmi_rs *rsp,
struct sensor_reading *sr)
{
printf("%s", sr->s_id);
if (sr->s_reading_valid) {
if (sr->s_has_analog_value)
printf(",%.3f,%s,%s",
sr->s_a_val, sr->s_a_units, thresh_status);
else
printf(",0x%x,%s,%s",
sr->s_reading, sr->s_a_units, thresh_status);
} else {
printf(",%s,%s,%s",
"na", sr->s_a_units, "na");
}
if (thresh_available && sr->full) {
#define PTS(bit, dataidx) { \
print_thresh_setting(sr->full, rsp->data[0] & (bit), \
rsp->data[(dataidx)], ",", "%.3f", "0x%x", "%s"); \
}
PTS(LOWER_NON_RECOV_SPECIFIED, 3);
PTS(LOWER_CRIT_SPECIFIED, 2);
PTS(LOWER_NON_CRIT_SPECIFIED, 1);
PTS(UPPER_NON_CRIT_SPECIFIED, 4);
PTS(UPPER_CRIT_SPECIFIED, 5);
PTS(UPPER_NON_RECOV_SPECIFIED, 6);
#undef PTS
} else {
printf(",%s,%s,%s,%s,%s,%s",
"na", "na", "na", "na", "na", "na");
}
printf("\n");
}
/* output format
* id value units status thresholds....
*/
static void
dump_sensor_fc_thredshold(
int thresh_available,
const char *thresh_status,
struct ipmi_rs *rsp,
struct sensor_reading *sr)
{
printf("%-16s ", sr->s_id);
if (sr->s_reading_valid) {
if (sr->s_has_analog_value)
printf("| %-10.3f | %-10s | %-6s",
sr->s_a_val, sr->s_a_units, thresh_status);
else
printf("| 0x%-8x | %-10s | %-6s",
sr->s_reading, sr->s_a_units, thresh_status);
} else {
printf("| %-10s | %-10s | %-6s",
"na", sr->s_a_units, "na");
}
if (thresh_available && sr->full) {
#define PTS(bit, dataidx) { \
print_thresh_setting(sr->full, rsp->data[0] & (bit), \
rsp->data[(dataidx)], "| ", "%-10.3f", "0x%-8x", "%-10s"); \
}
PTS(LOWER_NON_RECOV_SPECIFIED, 3);
PTS(LOWER_CRIT_SPECIFIED, 2);
PTS(LOWER_NON_CRIT_SPECIFIED, 1);
PTS(UPPER_NON_CRIT_SPECIFIED, 4);
PTS(UPPER_CRIT_SPECIFIED, 5);
PTS(UPPER_NON_RECOV_SPECIFIED, 6);
#undef PTS
} else {
printf("| %-10s| %-10s| %-10s| %-10s| %-10s| %-10s",
"na", "na", "na", "na", "na", "na");
}
printf("\n");
}
static void
dump_sensor_fc_thredshold_verbose(
int thresh_available,
const char *thresh_status,
struct ipmi_intf *intf,
struct sdr_record_common_sensor *sensor,
struct ipmi_rs *rsp,
struct sensor_reading *sr)
{
printf("Sensor ID : %s (0x%x)\n",
sr->s_id, sensor->keys.sensor_num);
printf(" Entity ID : %d.%d\n",
sensor->entity.id, sensor->entity.instance);
printf(" Sensor Type (Threshold) : %s\n",
ipmi_get_sensor_type(intf, sensor->sensor.type));
printf(" Sensor Reading : ");
if (sr->s_reading_valid) {
if (sr->full) {
uint16_t raw_tol = __TO_TOL(sr->full->mtol);
if (sr->s_has_analog_value) {
double tol =
sdr_convert_sensor_tolerance(sr->full,
raw_tol);
printf("%.*f (+/- %.*f) %s\n",
(sr->s_a_val == (int)
sr->s_a_val) ? 0 : 3,
sr->s_a_val,
(tol == (int) tol) ? 0 : 3, tol,
sr->s_a_units);
} else {
printf("0x%x (+/- 0x%x) %s\n",
sr->s_reading,
raw_tol,
sr->s_a_units);
}
} else {
printf("0x%x %s\n",
sr->s_reading, sr->s_a_units);
}
printf(" Status : %s\n", thresh_status);
if (thresh_available) {
if (sr->full) {
#define PTS(bit, dataidx, str) { \
print_thresh_setting(sr->full, rsp->data[0] & (bit), \
rsp->data[(dataidx)], \
(str), "%.3f\n", "0x%x\n", "%s\n"); \
}
PTS(LOWER_NON_RECOV_SPECIFIED, 3, " Lower Non-Recoverable : ");
PTS(LOWER_CRIT_SPECIFIED, 2, " Lower Critical : ");
PTS(LOWER_NON_CRIT_SPECIFIED, 1, " Lower Non-Critical : ");
PTS(UPPER_NON_CRIT_SPECIFIED, 4, " Upper Non-Critical : ");
PTS(UPPER_CRIT_SPECIFIED, 5, " Upper Critical : ");
PTS(UPPER_NON_RECOV_SPECIFIED, 6, " Upper Non-Recoverable : ");
#undef PTS
}
ipmi_sdr_print_sensor_hysteresis(sensor, sr->full,
sr->full ? sr->full->threshold.hysteresis.positive :
sr->compact->threshold.hysteresis.positive,
"Positive Hysteresis");
ipmi_sdr_print_sensor_hysteresis(sensor, sr->full,
sr->full ? sr->full->threshold.hysteresis.negative :
sr->compact->threshold.hysteresis.negative,
"Negative Hysteresis");
} else {
printf(" Sensor Threshold Settings not available\n");
}
} else {
printf(" Unable to read sensor: Device Not Present\n\n");
}
ipmi_sdr_print_sensor_event_status(intf,
sensor->keys.
sensor_num,
sensor->sensor.type,
sensor->event_type,
ANALOG_SENSOR,
sensor->keys.owner_id,
sensor->keys.lun,
sensor->keys.channel);
ipmi_sdr_print_sensor_event_enable(intf,
sensor->keys.
sensor_num,
sensor->sensor.type,
sensor->event_type,
ANALOG_SENSOR,
sensor->keys.owner_id,
sensor->keys.lun,
sensor->keys.channel);
printf("\n");
}
static int
ipmi_sensor_print_fc_threshold(struct ipmi_intf *intf,
struct sdr_record_common_sensor *sensor,
uint8_t sdr_record_type)
{
int thresh_available = 1;
struct ipmi_rs *rsp;
struct sensor_reading *sr;
sr = ipmi_sdr_read_sensor_value(intf, sensor, sdr_record_type, 3);
if (!sr) {
return -1;
}
const char *thresh_status = ipmi_sdr_get_thresh_status(sr, "ns");
/*
* Get sensor thresholds
*/
rsp = ipmi_sdr_get_sensor_thresholds(intf,
sensor->keys.sensor_num, sensor->keys.owner_id,
sensor->keys.lun, sensor->keys.channel);
if (!rsp || rsp->ccode || !rsp->data_len)
thresh_available = 0;
if (csv_output) {
dump_sensor_fc_thredshold_csv(thresh_available, thresh_status, rsp, sr);
} else {
if (verbose == 0) {
dump_sensor_fc_thredshold(thresh_available, thresh_status, rsp, sr);
} else {
dump_sensor_fc_thredshold_verbose(thresh_available, thresh_status,
intf, sensor, rsp, sr);
}
}
return (sr->s_reading_valid ? 0 : -1 );
}
int
ipmi_sensor_print_fc(struct ipmi_intf *intf,
struct sdr_record_common_sensor *sensor,
uint8_t sdr_record_type)
{
if (IS_THRESHOLD_SENSOR(sensor))
return ipmi_sensor_print_fc_threshold(intf, sensor, sdr_record_type);
else
return ipmi_sensor_print_fc_discrete(intf, sensor, sdr_record_type);
}
static int
ipmi_sensor_list(struct ipmi_intf *intf)
{
struct sdr_get_rs *header;
struct ipmi_sdr_iterator *itr;
int rc = 0;
lprintf(LOG_DEBUG, "Querying SDR for sensor list");
itr = ipmi_sdr_start(intf, 0);
if (!itr) {
lprintf(LOG_ERR, "Unable to open SDR for reading");
return -1;
}
while ((header = ipmi_sdr_get_next_header(intf, itr))) {
uint8_t *rec;
rec = ipmi_sdr_get_record(intf, header, itr);
if (!rec) {
lprintf(LOG_DEBUG, "rec == NULL");
continue;
}
switch (header->type) {
case SDR_RECORD_TYPE_FULL_SENSOR:
case SDR_RECORD_TYPE_COMPACT_SENSOR:
ipmi_sensor_print_fc(intf,
(struct
sdr_record_common_sensor *)
rec,
header->type);
break;
}
free(rec);
rec = NULL;
/* fix for CR6604909: */
/* mask failure of individual reads in sensor list command */
/* rc = (r == 0) ? rc : r; */
}
ipmi_sdr_end(intf, itr);
return rc;
}
static const struct valstr threshold_vals[] = {
{UPPER_NON_RECOV_SPECIFIED, "Upper Non-Recoverable"},
{UPPER_CRIT_SPECIFIED, "Upper Critical"},
{UPPER_NON_CRIT_SPECIFIED, "Upper Non-Critical"},
{LOWER_NON_RECOV_SPECIFIED, "Lower Non-Recoverable"},
{LOWER_CRIT_SPECIFIED, "Lower Critical"},
{LOWER_NON_CRIT_SPECIFIED, "Lower Non-Critical"},
{0x00, NULL},
};
static int
__ipmi_sensor_set_threshold(struct ipmi_intf *intf,
uint8_t num, uint8_t mask, uint8_t setting,
uint8_t target, uint8_t lun, uint8_t channel)
{
struct ipmi_rs *rsp;
rsp = ipmi_sensor_set_sensor_thresholds(intf, num, mask, setting,
target, lun, channel);
if (!rsp) {
lprintf(LOG_ERR, "Error setting threshold");
return -1;
}
if (rsp->ccode) {
lprintf(LOG_ERR, "Error setting threshold: %s",
val2str(rsp->ccode, completion_code_vals));
return -1;
}
return 0;
}
static uint8_t
__ipmi_sensor_threshold_value_to_raw(struct sdr_record_full_sensor *full, double value)
{
if (!UNITS_ARE_DISCRETE(&full->cmn)) { /* Has an analog reading */
/* Has an analog reading and supports mx+b */
return sdr_convert_sensor_value_to_raw(full, value);
}
else {
/* Does not have an analog reading and/or does not support mx+b */
if (value > 255) {
return 255;
}
else if (value < 0) {
return 0;
}
else {
return (uint8_t )value;
}
}
}
static int
ipmi_sensor_set_threshold(struct ipmi_intf *intf, int argc, char **argv)
{
char *id, *thresh;
uint8_t settingMask = 0;
double setting1 = 0.0, setting2 = 0.0, setting3 = 0.0;
int allUpper = 0, allLower = 0;
int ret = 0;
struct ipmi_rs *rsp;
int i =0;
double val[10] = {0};
struct sdr_record_list *sdr;
if (argc < 3 || strncmp(argv[0], "help", 4) == 0) {
print_sensor_thresh_usage();
return 0;
}
id = argv[0];
thresh = argv[1];
if (strncmp(thresh, "upper", 5) == 0) {
if (argc < 5) {
lprintf(LOG_ERR,
"usage: sensor thresh <id> upper <unc> <ucr> <unr>");
return -1;
}
allUpper = 1;
if (str2double(argv[2], &setting1) != 0) {
lprintf(LOG_ERR, "Given unc '%s' is invalid.",
argv[2]);
return (-1);
}
if (str2double(argv[3], &setting2) != 0) {
lprintf(LOG_ERR, "Given ucr '%s' is invalid.",
argv[3]);
return (-1);
}
if (str2double(argv[4], &setting3) != 0) {
lprintf(LOG_ERR, "Given unr '%s' is invalid.",
argv[4]);
return (-1);
}
} else if (strncmp(thresh, "lower", 5) == 0) {
if (argc < 5) {
lprintf(LOG_ERR,
"usage: sensor thresh <id> lower <lnr> <lcr> <lnc>");
return -1;
}
allLower = 1;
if (str2double(argv[2], &setting1) != 0) {
lprintf(LOG_ERR, "Given lnc '%s' is invalid.",
argv[2]);
return (-1);
}
if (str2double(argv[3], &setting2) != 0) {
lprintf(LOG_ERR, "Given lcr '%s' is invalid.",
argv[3]);
return (-1);
}
if (str2double(argv[4], &setting3) != 0) {
lprintf(LOG_ERR, "Given lnr '%s' is invalid.",
argv[4]);
return (-1);
}
} else {
if (strncmp(thresh, "unr", 3) == 0)
settingMask = UPPER_NON_RECOV_SPECIFIED;
else if (strncmp(thresh, "ucr", 3) == 0)
settingMask = UPPER_CRIT_SPECIFIED;
else if (strncmp(thresh, "unc", 3) == 0)
settingMask = UPPER_NON_CRIT_SPECIFIED;
else if (strncmp(thresh, "lnc", 3) == 0)
settingMask = LOWER_NON_CRIT_SPECIFIED;
else if (strncmp(thresh, "lcr", 3) == 0)
settingMask = LOWER_CRIT_SPECIFIED;
else if (strncmp(thresh, "lnr", 3) == 0)
settingMask = LOWER_NON_RECOV_SPECIFIED;
else {
lprintf(LOG_ERR,
"Valid threshold '%s' for sensor '%s' not specified!",
thresh, id);
return -1;
}
if (str2double(argv[2], &setting1) != 0) {
lprintf(LOG_ERR,
"Given %s threshold value '%s' is invalid.",
thresh, argv[2]);
return (-1);
}
}
printf("Locating sensor record '%s'...\n", id);
/* lookup by sensor name */
sdr = ipmi_sdr_find_sdr_byid(intf, id);
if (!sdr) {
lprintf(LOG_ERR, "Sensor data record not found!");
return -1;
}
if (sdr->type != SDR_RECORD_TYPE_FULL_SENSOR) {
lprintf(LOG_ERR, "Invalid sensor type %02x", sdr->type);
return -1;
}
if (!IS_THRESHOLD_SENSOR(sdr->record.common)) {
lprintf(LOG_ERR, "Invalid sensor event type %02x", sdr->record.common->event_type);
return -1;
}
if (allUpper) {
settingMask = UPPER_NON_CRIT_SPECIFIED;
printf("Setting sensor \"%s\" %s threshold to %.3f\n",
sdr->record.full->id_string,
val2str(settingMask, threshold_vals), setting1);
ret = __ipmi_sensor_set_threshold(intf,
sdr->record.common->keys.
sensor_num, settingMask,
__ipmi_sensor_threshold_value_to_raw(sdr->record.full, setting1),
sdr->record.common->keys.owner_id,
sdr->record.common->keys.lun,
sdr->record.common->keys.channel);
settingMask = UPPER_CRIT_SPECIFIED;
printf("Setting sensor \"%s\" %s threshold to %.3f\n",
sdr->record.full->id_string,
val2str(settingMask, threshold_vals), setting2);
ret = __ipmi_sensor_set_threshold(intf,
sdr->record.common->keys.
sensor_num, settingMask,
__ipmi_sensor_threshold_value_to_raw(sdr->record.full, setting2),
sdr->record.common->keys.owner_id,
sdr->record.common->keys.lun,
sdr->record.common->keys.channel);
settingMask = UPPER_NON_RECOV_SPECIFIED;
printf("Setting sensor \"%s\" %s threshold to %.3f\n",
sdr->record.full->id_string,
val2str(settingMask, threshold_vals), setting3);
ret = __ipmi_sensor_set_threshold(intf,
sdr->record.common->keys.
sensor_num, settingMask,
__ipmi_sensor_threshold_value_to_raw(sdr->record.full, setting3),
sdr->record.common->keys.owner_id,
sdr->record.common->keys.lun,
sdr->record.common->keys.channel);
} else if (allLower) {
settingMask = LOWER_NON_RECOV_SPECIFIED;
printf("Setting sensor \"%s\" %s threshold to %.3f\n",
sdr->record.full->id_string,
val2str(settingMask, threshold_vals), setting1);
ret = __ipmi_sensor_set_threshold(intf,
sdr->record.common->keys.
sensor_num, settingMask,
__ipmi_sensor_threshold_value_to_raw(sdr->record.full, setting1),
sdr->record.common->keys.owner_id,
sdr->record.common->keys.lun,
sdr->record.common->keys.channel);
settingMask = LOWER_CRIT_SPECIFIED;
printf("Setting sensor \"%s\" %s threshold to %.3f\n",
sdr->record.full->id_string,
val2str(settingMask, threshold_vals), setting2);
ret = __ipmi_sensor_set_threshold(intf,
sdr->record.common->keys.
sensor_num, settingMask,
__ipmi_sensor_threshold_value_to_raw(sdr->record.full, setting2),
sdr->record.common->keys.owner_id,
sdr->record.common->keys.lun,
sdr->record.common->keys.channel);
settingMask = LOWER_NON_CRIT_SPECIFIED;
printf("Setting sensor \"%s\" %s threshold to %.3f\n",
sdr->record.full->id_string,
val2str(settingMask, threshold_vals), setting3);
ret = __ipmi_sensor_set_threshold(intf,
sdr->record.common->keys.
sensor_num, settingMask,
__ipmi_sensor_threshold_value_to_raw(sdr->record.full, setting3),
sdr->record.common->keys.owner_id,
sdr->record.common->keys.lun,
sdr->record.common->keys.channel);
} else {
/*
* Current implementation doesn't check for the valid setting of upper non critical and other thresholds.
* In the below logic:
* Get all the current reading of the sensor i.e. unc, uc, lc,lnc.
* Validate the values given by the user.
* If the values are not correct, then popup with the Error message and return.
*/
/*
* Get current reading
*/
rsp = ipmi_sdr_get_sensor_reading_ipmb(intf,
sdr->record.common->keys.sensor_num,
sdr->record.common->keys.owner_id,
sdr->record.common->keys.lun,sdr->record.common->keys.channel);
rsp = ipmi_sdr_get_sensor_thresholds(intf,
sdr->record.common->keys.sensor_num,
sdr->record.common->keys.owner_id,
sdr->record.common->keys.lun,
sdr->record.common->keys.channel);
if (!rsp || rsp->ccode) {
lprintf(LOG_ERR, "Sensor data record not found!");
return -1;
}
for(i=1;i<=6;i++) {
val[i] = sdr_convert_sensor_reading(sdr->record.full, rsp->data[i]);
if(val[i] < 0)
val[i] = 0;
}
/* Check for the valid Upper non recovarable Value.*/
if( (settingMask & UPPER_NON_RECOV_SPECIFIED) ) {
if( (rsp->data[0] & UPPER_NON_RECOV_SPECIFIED) &&
(( (rsp->data[0] & UPPER_CRIT_SPECIFIED) && ( setting1 <= val[5])) ||
( (rsp->data[0] & UPPER_NON_CRIT_SPECIFIED) && ( setting1 <= val[4]))) )
{
lprintf(LOG_ERR, INVALID_THRESHOLD);
return -1;
}
} else if( (settingMask & UPPER_CRIT_SPECIFIED) ) { /* Check for the valid Upper critical Value.*/
if( (rsp->data[0] & UPPER_CRIT_SPECIFIED) &&
(((rsp->data[0] & UPPER_NON_RECOV_SPECIFIED)&& ( setting1 >= val[6])) ||
((rsp->data[0] & UPPER_NON_CRIT_SPECIFIED)&&( setting1 <= val[4]))) )
{
lprintf(LOG_ERR, INVALID_THRESHOLD);
return -1;
}
} else if( (settingMask & UPPER_NON_CRIT_SPECIFIED) ) { /* Check for the valid Upper non critical Value.*/
if( (rsp->data[0] & UPPER_NON_CRIT_SPECIFIED) &&
(((rsp->data[0] & UPPER_NON_RECOV_SPECIFIED)&&( setting1 >= val[6])) ||
((rsp->data[0] & UPPER_CRIT_SPECIFIED)&&( setting1 >= val[5])) ||
((rsp->data[0] & LOWER_NON_CRIT_SPECIFIED)&&( setting1 <= val[1]))) )
{
lprintf(LOG_ERR, INVALID_THRESHOLD);
return -1;
}
} else if( (settingMask & LOWER_NON_CRIT_SPECIFIED) ) { /* Check for the valid lower non critical Value.*/
if( (rsp->data[0] & LOWER_NON_CRIT_SPECIFIED) &&
(((rsp->data[0] & LOWER_CRIT_SPECIFIED)&&( setting1 <= val[2])) ||
((rsp->data[0] & LOWER_NON_RECOV_SPECIFIED)&&( setting1 <= val[3]))||
((rsp->data[0] & UPPER_NON_CRIT_SPECIFIED)&&( setting1 >= val[4]))) )
{
lprintf(LOG_ERR, INVALID_THRESHOLD);
return -1;
}
} else if( (settingMask & LOWER_CRIT_SPECIFIED) ) { /* Check for the valid lower critical Value.*/
if( (rsp->data[0] & LOWER_CRIT_SPECIFIED) &&
(((rsp->data[0] & LOWER_NON_CRIT_SPECIFIED)&&( setting1 >= val[1])) ||
((rsp->data[0] & LOWER_NON_RECOV_SPECIFIED)&&( setting1 <= val[3]))) )
{
lprintf(LOG_ERR, INVALID_THRESHOLD);
return -1;
}
} else if( (settingMask & LOWER_NON_RECOV_SPECIFIED) ) { /* Check for the valid lower non recovarable Value.*/
if( (rsp->data[0] & LOWER_NON_RECOV_SPECIFIED) &&
(((rsp->data[0] & LOWER_NON_CRIT_SPECIFIED)&&( setting1 >= val[1])) ||
((rsp->data[0] & LOWER_CRIT_SPECIFIED)&&( setting1 >= val[2]))) )
{
lprintf(LOG_ERR, INVALID_THRESHOLD);
return -1;
}
} else { /* None of this Then Return with error messages.*/
lprintf(LOG_ERR, INVALID_THRESHOLD);
return -1;
}
printf("Setting sensor \"%s\" %s threshold to %.3f\n",
sdr->record.full->id_string,
val2str(settingMask, threshold_vals), setting1);
ret = __ipmi_sensor_set_threshold(intf,
sdr->record.common->keys.
sensor_num, settingMask,
__ipmi_sensor_threshold_value_to_raw(sdr->record.full, setting1),
sdr->record.common->keys.owner_id,
sdr->record.common->keys.lun,
sdr->record.common->keys.channel);
}
return ret;
}
static int
ipmi_sensor_get_reading(struct ipmi_intf *intf, int argc, char **argv)
{
struct sdr_record_list *sdr;
int i, rc=0;
if (argc < 1 || strncmp(argv[0], "help", 4) == 0) {
lprintf(LOG_NOTICE, "sensor reading <id> ... [id]");
lprintf(LOG_NOTICE, " id : name of desired sensor");
return -1;
}
for (i = 0; i < argc; i++) {
sdr = ipmi_sdr_find_sdr_byid(intf, argv[i]);
if (!sdr) {
lprintf(LOG_ERR, "Sensor \"%s\" not found!",
argv[i]);
rc = -1;
continue;
}
switch (sdr->type) {
case SDR_RECORD_TYPE_FULL_SENSOR:
case SDR_RECORD_TYPE_COMPACT_SENSOR:
{
struct sensor_reading *sr;
struct sdr_record_common_sensor *sensor = sdr->record.common;
sr = ipmi_sdr_read_sensor_value(intf, sensor, sdr->type, 3);
if (!sr) {
rc = -1;
continue;
}
if (!sr->full)
continue;
if (!sr->s_reading_valid)
continue;
if (!sr->s_has_analog_value) {
lprintf(LOG_ERR, "Sensor \"%s\" is a discrete sensor!", argv[i]);
continue;
}
if (csv_output)
printf("%s,%s\n", argv[i], sr->s_a_str);
else
printf("%-16s | %s\n", argv[i], sr->s_a_str);
break;
}
default:
continue;
}
}
return rc;
}
static int
ipmi_sensor_get(struct ipmi_intf *intf, int argc, char **argv)
{
int i, v;
int rc = 0;
struct sdr_record_list *sdr;
if (argc < 1) {
lprintf(LOG_ERR, "Not enough parameters given.");
print_sensor_get_usage();
return (-1);
} else if (strcmp(argv[0], "help") == 0) {
print_sensor_get_usage();
return 0;
}
printf("Locating sensor record...\n");
/* lookup by sensor name */
for (i = 0; i < argc; i++) {
sdr = ipmi_sdr_find_sdr_byid(intf, argv[i]);
if (!sdr) {
lprintf(LOG_ERR, "Sensor data record \"%s\" not found!",
argv[i]);
rc = -1;
continue;
}
/* need to set verbose level to 1 */
v = verbose;
verbose = 1;
switch (sdr->type) {
case SDR_RECORD_TYPE_FULL_SENSOR:
case SDR_RECORD_TYPE_COMPACT_SENSOR:
if (ipmi_sensor_print_fc(intf,
(struct sdr_record_common_sensor *) sdr->record.common,
sdr->type)) {
rc = -1;
}
break;
default:
if (ipmi_sdr_print_listentry(intf, sdr) < 0) {
rc = (-1);
}
break;
}
verbose = v;
sdr = NULL;
}
return rc;
}
int
ipmi_sensor_main(struct ipmi_intf *intf, int argc, char **argv)
{
int rc = 0;
if (argc == 0) {
rc = ipmi_sensor_list(intf);
} else if (strncmp(argv[0], "help", 4) == 0) {
lprintf(LOG_NOTICE, "Sensor Commands: list thresh get reading");
} else if (strncmp(argv[0], "list", 4) == 0) {
rc = ipmi_sensor_list(intf);
} else if (strncmp(argv[0], "thresh", 5) == 0) {
rc = ipmi_sensor_set_threshold(intf, argc - 1, &argv[1]);
} else if (strncmp(argv[0], "get", 3) == 0) {
rc = ipmi_sensor_get(intf, argc - 1, &argv[1]);
} else if (strncmp(argv[0], "reading", 7) == 0) {
rc = ipmi_sensor_get_reading(intf, argc - 1, &argv[1]);
} else {
lprintf(LOG_ERR, "Invalid sensor command: %s", argv[0]);
rc = -1;
}
return rc;
}
/* print_sensor_get_usage - print usage for # ipmitool sensor get NAC;
*
* @returns: void
*/
void
print_sensor_get_usage()
{
lprintf(LOG_NOTICE, "sensor get <id> ... [id]");
lprintf(LOG_NOTICE, " id : name of desired sensor");
}
/* print_sensor_thresh_set_usage - print usage for # ipmitool sensor thresh;
*
* @returns: void
*/
void
print_sensor_thresh_usage()
{
lprintf(LOG_NOTICE,
"sensor thresh <id> <threshold> <setting>");
lprintf(LOG_NOTICE,
" id : name of the sensor for which threshold is to be set");
lprintf(LOG_NOTICE,
" threshold : which threshold to set");
lprintf(LOG_NOTICE,
" unr = upper non-recoverable");
lprintf(LOG_NOTICE,
" ucr = upper critical");
lprintf(LOG_NOTICE,
" unc = upper non-critical");
lprintf(LOG_NOTICE,
" lnc = lower non-critical");
lprintf(LOG_NOTICE,
" lcr = lower critical");
lprintf(LOG_NOTICE,
" lnr = lower non-recoverable");
lprintf(LOG_NOTICE,
" setting : the value to set the threshold to");
lprintf(LOG_NOTICE,
"");
lprintf(LOG_NOTICE,
"sensor thresh <id> lower <lnr> <lcr> <lnc>");
lprintf(LOG_NOTICE,
" Set all lower thresholds at the same time");
lprintf(LOG_NOTICE,
"");
lprintf(LOG_NOTICE,
"sensor thresh <id> upper <unc> <ucr> <unr>");
lprintf(LOG_NOTICE,
" Set all upper thresholds at the same time");
lprintf(LOG_NOTICE, "");
}