- determine maximum buffer length for SDR reading dynamically

- add support for "sensor get" command
- let sensor get and sensor thresh use sensor id as well as name
- build list of sdrs when searching, for use in xref of sel data
- fix memory leak during sensor list
This commit is contained in:
Duncan Laurie 2004-03-26 21:38:10 +00:00
parent 85d138da01
commit e09dc5950c
4 changed files with 166 additions and 41 deletions

View File

@ -98,7 +98,6 @@ struct sdr_get_rq {
unsigned short id; /* record ID */
unsigned char offset; /* offset into SDR */
#define GET_SDR_ENTIRE_RECORD 0xff
#define GET_SDR_MAX_LEN 30
unsigned char length; /* length to read */
} __attribute__ ((packed));
@ -630,7 +629,9 @@ float sdr_convert_sensor_reading(struct sdr_record_full_sensor * sensor, unsigne
unsigned char sdr_convert_sensor_value_to_raw(struct sdr_record_full_sensor * sensor, float val);
struct ipmi_rs * ipmi_sdr_get_sensor_reading(struct ipmi_intf * intf, unsigned char sensor);
const char * ipmi_sdr_get_sensor_type_desc(const unsigned char type);
struct sdr_record_full_sensor * ipmi_sdr_find_sdr(struct ipmi_intf * intf, char * id);
struct sdr_record_full_sensor *ipmi_sdr_find_sdr_byid(struct ipmi_intf * intf, char * id);
struct sdr_record_full_sensor *ipmi_sdr_find_sdr_bynum(struct ipmi_intf * intf, unsigned char num);
void ipmi_sdr_list_empty(void);
#endif /* IPMI_SDR_H */

View File

@ -88,5 +88,7 @@ struct sensor_set_thresh_rq {
int ipmi_sensor_main(struct ipmi_intf *, int, char **);
void ipmi_sensor_print_full(struct ipmi_intf *, struct sdr_record_full_sensor *);
void ipmi_sensor_print_compact(struct ipmi_intf *, struct sdr_record_compact_sensor *);
#endif /* IPMI_SENSOR_H */

View File

@ -47,6 +47,13 @@
#endif
extern int verbose;
static int sdr_max_read_len = GET_SDR_ENTIRE_RECORD;
struct sdr_records_full {
struct sdr_record_full_sensor * record;
struct sdr_records_full * next;
};
static struct sdr_records_full * sdr_list_head = NULL;
/* convert unsigned value to 2's complement signed */
int utos(unsigned val, unsigned bits)
@ -945,12 +952,12 @@ ipmi_sdr_get_record(struct ipmi_intf * intf, struct sdr_get_rs * header,
req.msg.data = (unsigned char *)&sdr_rq;
req.msg.data_len = sizeof(sdr_rq);
/* read SDR record with partial (30 byte) reads
* because a full read (0xff) exceeds the maximum
/* read SDR record with partial reads
* because a full read usually exceeds the maximum
* transport buffer size. (completion code 0xca)
*/
while (i < len) {
sdr_rq.length = (len-i < GET_SDR_MAX_LEN) ? len-i : GET_SDR_MAX_LEN;
sdr_rq.length = (len-i < sdr_max_read_len) ? len-i : sdr_max_read_len;
sdr_rq.offset = i+5; /* 5 header bytes */
if (verbose > 1)
printf("getting %d bytes from SDR at offset %d\n",
@ -962,9 +969,16 @@ ipmi_sdr_get_record(struct ipmi_intf * intf, struct sdr_get_rs * header,
return NULL;
}
if (rsp->ccode == 0xc5) {
switch (rsp->ccode) {
case 0xca:
/* read too many bytes at once */
sdr_max_read_len = (sdr_max_read_len >> 1) - 1;
continue;
case 0xc5:
/* lost reservation */
if (verbose > 1)
printf("SDR reserveration canceled. Sleeping a bit and retrying...\n");
printf("SDR reserveration canceled. "
"Sleeping a bit and retrying...\n");
sleep (rand () & 3);
@ -977,12 +991,12 @@ ipmi_sdr_get_record(struct ipmi_intf * intf, struct sdr_get_rs * header,
}
if (!rsp->data_len || rsp->ccode) {
free (data);
free(data);
return NULL;
}
memcpy(data+i, rsp->data+2, sdr_rq.length);
i+=GET_SDR_MAX_LEN;
i += sdr_max_read_len;
}
return data;
@ -994,29 +1008,100 @@ ipmi_sdr_end(struct ipmi_intf * intf, struct ipmi_sdr_iterator * itr)
free (itr);
}
struct sdr_record_full_sensor *
ipmi_sdr_find_sdr(struct ipmi_intf * intf, char * id)
int ipmi_sdr_list_fill(struct ipmi_intf * intf)
{
struct sdr_get_rs * header;
struct ipmi_sdr_iterator * itr;
struct sdr_get_rs * header;
struct ipmi_sdr_iterator * itr;
static struct sdr_records_full * sdr_list_tail;
itr = ipmi_sdr_start(intf);
if (!itr)
{
printf("Unable to open SDR for reading\n");
return;
}
itr = ipmi_sdr_start(intf);
if (!itr) {
printf("Unable to open SDR for reading\n");
return -1;
}
while (header = ipmi_sdr_get_next_header(intf, itr))
{
struct sdr_record_full_sensor * sdr;
if (header->type != SDR_RECORD_TYPE_FULL_SENSOR)
continue;
sdr = (struct sdr_record_full_sensor *)ipmi_sdr_get_record(intf, header, itr);
if (sdr && !strncmp(sdr->id_string, id, sdr->id_code & 0x3f))
return sdr;
}
return NULL;
while (header = ipmi_sdr_get_next_header(intf, itr)) {
struct sdr_record_full_sensor * sdr;
struct sdr_records_full * sdrr;
if (header->type != SDR_RECORD_TYPE_FULL_SENSOR)
continue;
sdr = (struct sdr_record_full_sensor *)ipmi_sdr_get_record(intf, header, itr);
if (!sdr)
continue;
sdrr = malloc(sizeof(struct sdr_records_full));
memset(sdrr, 0, sizeof(struct sdr_records_full));
sdrr->record = sdr;
if (!sdr_list_head)
sdr_list_head = sdrr;
else
sdr_list_tail->next = sdrr;
sdr_list_tail = sdrr;
if (verbose > 3)
printf("added list entry %x\n", sdrr->record->keys.sensor_num);
}
ipmi_sdr_end(intf, itr);
return 0;
}
struct sdr_record_full_sensor *
ipmi_sdr_find_sdr_byid(struct ipmi_intf * intf, char * id)
{
static struct sdr_records_full * e;
if (!sdr_list_head)
ipmi_sdr_list_fill(intf);
e = sdr_list_head;
while (e) {
if (!strncmp(e->record->id_string, id, e->record->id_code & 0x3f))
return e->record;
e = e->next;
}
return NULL;
}
struct sdr_record_full_sensor *
ipmi_sdr_find_sdr_bynum(struct ipmi_intf * intf, unsigned char num)
{
static struct sdr_records_full * e;
if (!sdr_list_head)
ipmi_sdr_list_fill(intf);
e = sdr_list_head;
while (e) {
if (e->record->keys.sensor_num == num)
return e->record;
e = e->next;
}
return NULL;
}
void ipmi_sdr_list_empty(void)
{
struct sdr_records_full *list, *next;
list = sdr_list_head;
while (list) {
if (verbose > 3)
printf("cleared sdr entry %x\n", list->record->keys.sensor_num);
if (list->record)
free(list->record);
next = list->next;
free(list);
list = next;
}
}
int ipmi_sdr_main(struct ipmi_intf * intf, int argc, char ** argv)

View File

@ -428,8 +428,7 @@ ipmi_sensor_print_full_analog(struct ipmi_intf * intf,
}
}
static void
ipmi_sensor_print_full(struct ipmi_intf * intf,
void ipmi_sensor_print_full(struct ipmi_intf * intf,
struct sdr_record_full_sensor * sensor)
{
if (sensor->unit.analog != 3)
@ -438,8 +437,7 @@ ipmi_sensor_print_full(struct ipmi_intf * intf,
ipmi_sensor_print_full_discrete(intf, sensor);
}
static void
ipmi_sensor_print_compact(struct ipmi_intf * intf,
void ipmi_sensor_print_compact(struct ipmi_intf * intf,
struct sdr_record_compact_sensor * sensor)
{
char id[17];
@ -596,11 +594,10 @@ ipmi_sensor_list(struct ipmi_intf * intf)
case SDR_RECORD_TYPE_COMPACT_SENSOR:
ipmi_sensor_print_compact(intf, (struct sdr_record_compact_sensor *) rec);
break;
default:
continue;
break;
}
free(rec);
}
ipmi_sdr_end(intf, itr);
}
const struct valstr threshold_vals[] = {
@ -626,7 +623,7 @@ ipmi_sensor_set_threshold(struct ipmi_intf * intf, int argc, char ** argv)
if (argc < 3 || !strncmp(argv[0], "help", 4))
{
printf("sensor thresh <id> <threshold> <setting>\n");
printf(" id : name of the sensor for which threshold is to be set\n");
printf(" id : name or number of the sensor for which threshold is to be set\n");
printf(" threshold : which threshold to set\n");
printf(" unr = upper non-recoverable\n");
printf(" ucr = upper critical\n");
@ -672,11 +669,18 @@ ipmi_sensor_set_threshold(struct ipmi_intf * intf, int argc, char ** argv)
}
printf("Locating sensor record...\n");
sdr = ipmi_sdr_find_sdr(intf, id);
/* lookup by sensor name */
sdr = ipmi_sdr_find_sdr_byid(intf, id);
if (!sdr)
{
/* lookup by sensor number */
unsigned char num = (unsigned char)strtol(id, NULL, 0);
sdr = ipmi_sdr_find_sdr_bynum(intf, num);
}
if (sdr)
{
printf("Setting sensor \"%s\" %s threshold to %.3f\n",
id, val2str(settingMask, threshold_vals), setting);
sdr->id_string, val2str(settingMask, threshold_vals), setting);
rsp = ipmi_sensor_set_sensor_thresholds(intf,
sdr->keys.sensor_num,
settingMask,
@ -687,8 +691,38 @@ ipmi_sensor_set_threshold(struct ipmi_intf * intf, int argc, char ** argv)
else
{
printf("Sensor data record not found!\n");
return;
}
ipmi_sdr_list_empty();
}
static void ipmi_sensor_get(struct ipmi_intf * intf, char * id)
{
struct sdr_record_full_sensor * sdr;
if (!id || !strncmp(id, "help", 4)) {
printf("sensor get <id>\n");
printf(" id : name or number desired sensor\n");
return;
}
printf("Locating sensor record...\n");
/* lookup by sensor name */
sdr = ipmi_sdr_find_sdr_byid(intf, id);
if (!sdr) {
/* lookup by sensor number */
unsigned char num = (unsigned char)strtol(id, NULL, 0);
sdr = ipmi_sdr_find_sdr_bynum(intf, num);
}
if (sdr) {
verbose = verbose ? : 1;
ipmi_sensor_print_full(intf, sdr);
} else {
printf("Sensor data record not found!\n");
}
ipmi_sdr_list_empty();
}
int
@ -697,7 +731,7 @@ ipmi_sensor_main(struct ipmi_intf * intf, int argc, char ** argv)
if (!argc)
ipmi_sensor_list(intf);
else if (!strncmp(argv[0], "help", 4)) {
printf("Sensor Commands: list thresh\n");
printf("Sensor Commands: list thresh get\n");
}
else if (!strncmp(argv[0], "list", 4)) {
ipmi_sensor_list(intf);
@ -705,6 +739,9 @@ ipmi_sensor_main(struct ipmi_intf * intf, int argc, char ** argv)
else if (!strncmp(argv[0], "thresh", 5)) {
ipmi_sensor_set_threshold(intf, argc-1, &argv[1]);
}
else if (!strncmp(argv[0], "get", 3)) {
ipmi_sensor_get(intf, argv[1]);
}
else
printf("Invalid sensor command: %s\n", argv[0]);
return 0;