summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRob Johnston <rob.johnston@joyent.com>2018-06-06 21:24:18 -0700
committerRichard Lowe <richlowe@richlowe.net>2018-06-28 22:44:13 +0000
commitea30102ce458697473b0435bcdc7647dce2551f4 (patch)
treea0e74fd0c0b7029d01d233762f0ff98a4eaae39e
parent4e0c5eff9af325c80994e9527b7cb8b3a1ffd1d4 (diff)
downloadillumos-joyent-ea30102ce458697473b0435bcdc7647dce2551f4.tar.gz
9586 need to handle SP's that present multiple sensors with the same entity name
9587 Add test mechanism to sensor-transport module for spoofing sensor states Reviewed by: Toomas Soome <tsoome@me.com> Reviewed by: Igor Kozhukhov <igor@dilos.org> Approved by: Richard Lowe <richlowe@richlowe.net>
-rw-r--r--usr/src/cmd/fm/modules/common/sensor-transport/sensor_transport.c98
-rw-r--r--usr/src/lib/fm/topo/libtopo/common/topo_method.c73
-rw-r--r--usr/src/lib/fm/topo/libtopo/common/topo_method.h12
-rw-r--r--usr/src/lib/fm/topo/modules/common/fac_prov_ipmi/fac_prov_ipmi.c55
-rw-r--r--usr/src/lib/libipmi/common/ipmi_sdr.c52
-rw-r--r--usr/src/lib/libipmi/common/libipmi.h7
-rw-r--r--usr/src/lib/libipmi/common/mapfile-vers1
7 files changed, 254 insertions, 44 deletions
diff --git a/usr/src/cmd/fm/modules/common/sensor-transport/sensor_transport.c b/usr/src/cmd/fm/modules/common/sensor-transport/sensor_transport.c
index 6bf4da305a..50383d4530 100644
--- a/usr/src/cmd/fm/modules/common/sensor-transport/sensor_transport.c
+++ b/usr/src/cmd/fm/modules/common/sensor-transport/sensor_transport.c
@@ -20,6 +20,7 @@
*/
/*
* Copyright (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2018, Joyent, Inc.
*/
#include <fm/fmd_api.h>
@@ -56,6 +57,7 @@ typedef struct sensor_transport {
* we'll tolerate before sending an ereport.
*/
uint32_t st_tolerance;
+ nvlist_t *st_spoofs;
} sensor_transport_t;
typedef struct st_stats {
@@ -72,6 +74,7 @@ st_stats_t st_stats = {
static int st_check_component_complaints;
static int have_complained;
+static char *spoof_prop = NULL;
static int
st_check_component(topo_hdl_t *thp, tnode_t *node, void *arg)
@@ -83,7 +86,7 @@ st_check_component(topo_hdl_t *thp, tnode_t *node, void *arg)
char *fmri;
int err, ret;
int32_t last_source, source = -1;
- boolean_t nonrecov, faulted, predictive, source_diff;
+ boolean_t nonrecov, faulted, predictive, source_diff, injected;
nvpair_t *nvp;
uint64_t ena;
nvlist_t *event;
@@ -117,7 +120,8 @@ st_check_component(topo_hdl_t *thp, tnode_t *node, void *arg)
}
if (topo_method_invoke(node, TOPO_METH_SENSOR_FAILURE,
- TOPO_METH_SENSOR_FAILURE_VERSION, NULL, &nvl, &err) != 0) {
+ TOPO_METH_SENSOR_FAILURE_VERSION, stp->st_spoofs, &nvl, &err) !=
+ 0) {
if (err == ETOPO_METHOD_NOTSUP) {
st_check_component_complaints++;
if (!have_complained) {
@@ -131,7 +135,7 @@ st_check_component(topo_hdl_t *thp, tnode_t *node, void *arg)
nvl = NULL;
}
- if (topo_node_fru(node, &fru, NULL, NULL) != 0) {
+ if (topo_node_fru(node, &fru, NULL, &err) != 0) {
st_stats.st_bad_fmri.fmds_value.ui64++;
nvlist_free(nvl);
nvlist_free(rsrc);
@@ -148,7 +152,7 @@ st_check_component(topo_hdl_t *thp, tnode_t *node, void *arg)
nvlist_free(fru);
- faulted = nonrecov = source_diff = B_FALSE;
+ faulted = nonrecov = source_diff = injected = B_FALSE;
predictive = B_TRUE;
if (nvl != NULL) {
nvp = NULL;
@@ -173,6 +177,9 @@ st_check_component(topo_hdl_t *thp, tnode_t *node, void *arg)
*
* 3) source will be set to unknown unless all facility
* nodes agree on the source
+ *
+ * 4) injected defaults to false, but will be set to
+ * true if any of the sensor states were injected.
*/
if (nonrecov == B_FALSE)
if (nvlist_lookup_boolean_value(props,
@@ -182,6 +189,8 @@ st_check_component(topo_hdl_t *thp, tnode_t *node, void *arg)
if (nvlist_lookup_boolean_value(props,
"predictive", &predictive) != 0)
predictive = B_FALSE;
+ (void) nvlist_lookup_boolean_value(props,
+ "injected", &injected);
last_source = source;
if (nvlist_lookup_uint32(props, "source",
@@ -209,10 +218,10 @@ st_check_component(topo_hdl_t *thp, tnode_t *node, void *arg)
/*
* We add this FRU to our list under two circumstances:
*
- * 1. This FRU is faulted and needs to be remembered to
+ * 1. This FRU is faulted and needs to be remembered to
* avoid duplicate ereports.
*
- * 2. This is the initial pass, and we want to repair the
+ * 2. This is the initial pass, and we want to repair the
* FRU in case it was repaired while we were offline.
*/
if (stp->st_first || faulted) {
@@ -260,7 +269,8 @@ st_check_component(topo_hdl_t *thp, tnode_t *node, void *arg)
(void) nvlist_add_uint64(event, FM_EREPORT_ENA, ena);
(void) nvlist_add_nvlist(event, FM_EREPORT_DETECTOR,
rsrc);
-
+ (void) nvlist_add_boolean_value(event, "__injected",
+ injected);
fmd_xprt_post(hdl, stp->st_xprt, event, 0);
fmd_hdl_debug(hdl, "posted ereport: %s",
ST_EREPORT_CLASS);
@@ -351,16 +361,81 @@ st_timeout(fmd_hdl_t *hdl, id_t id, void *data)
stp->st_timer = fmd_timer_install(hdl, NULL, NULL, stp->st_interval);
}
+/*
+ * Parse the value of the spoof-sensor-state module property and store the
+ * result in an nvlist of nvlists. The format of the value is 3-tuple,
+ * delimited by colons, as follows:
+ *
+ * FMRIPATTERN:SENSORNAME:SENSORSTATE;...
+ *
+ * where FMRIPATTERN can be a string with wildcards that matches the FMRI
+ * of a node associated with the target sensor facility.
+ *
+ * where SENSORNAME is the node name of the target sensor facility
+ *
+ * where SENSORSTATE is the desired sensor state value to spoof.
+ *
+ * Multiple tuples can be specifed, delimited by semicolons.
+ *
+ * If any errors are encountered while parsing the value, all parsing is
+ * ceased and an ereport will be generated indicating a failure to parse
+ * the value.
+ */
+/*ARGSUSED*/
+static int
+parse_spoof_param(fmd_hdl_t *hdl, char *param, sensor_transport_t *stp)
+{
+ char *sensor, *last_sensor, *field, *last_field;
+ nvlist_t *spoof;
+
+ if (nvlist_alloc(&stp->st_spoofs, NV_UNIQUE_NAME, 0) != NULL) {
+ return (-1);
+ }
+
+ sensor = strtok_r(param, ";", &last_sensor);
+ while (sensor != NULL) {
+ if (nvlist_alloc(&spoof, NV_UNIQUE_NAME, 0) != 0)
+ goto err;
+
+ if ((field = strtok_r(sensor, ":", &last_field)) == NULL ||
+ nvlist_add_string(spoof, ST_SPOOF_FMRI, field) != 0)
+ goto err;
+
+ if ((field = strtok_r(NULL, ":", &last_field)) == NULL ||
+ nvlist_add_string(spoof, ST_SPOOF_SENSOR, field) != 0)
+ goto err;
+
+ if ((field = strtok_r(NULL, ":", &last_field)) == NULL ||
+ nvlist_add_uint32(spoof, ST_SPOOF_STATE,
+ strtol(field, NULL, 0)) != 0)
+ goto err;
+
+ if (nvlist_add_nvlist(stp->st_spoofs, sensor, spoof) != 0)
+ goto err;
+
+ spoof = NULL;
+ sensor = strtok_r(NULL, ";", &last_sensor);
+ }
+
+ return (0);
+err:
+ nvlist_free(spoof);
+ nvlist_free(stp->st_spoofs);
+ stp->st_spoofs = NULL;
+ return (-1);
+}
+
static const fmd_prop_t fmd_props[] = {
{ "interval", FMD_TYPE_TIME, "1min" },
{ "tolerance", FMD_TYPE_UINT32, "1" },
+ { "spoof_sensor_state", FMD_TYPE_STRING, NULL },
{ NULL, 0, NULL }
};
static const fmd_hdl_ops_t fmd_ops = {
NULL, /* fmdo_recv */
st_timeout, /* fmdo_timeout */
- NULL, /* fmdo_close */
+ NULL, /* fmdo_close */
NULL, /* fmdo_stats */
NULL, /* fmdo_gc */
NULL, /* fmdo_send */
@@ -397,6 +472,10 @@ _fmd_init(fmd_hdl_t *hdl)
stp = fmd_hdl_zalloc(hdl, sizeof (sensor_transport_t), FMD_SLEEP);
stp->st_interval = fmd_prop_get_int64(hdl, "interval");
stp->st_tolerance = fmd_prop_get_int32(hdl, "tolerance");
+ spoof_prop = fmd_prop_get_string(hdl, "spoof_sensor_state");
+
+ if (spoof_prop != NULL && parse_spoof_param(hdl, spoof_prop, stp) != 0)
+ fmd_hdl_error(hdl, "Error parsing config file");
fmd_hdl_setspecific(hdl, stp);
@@ -424,7 +503,8 @@ _fmd_fini(fmd_hdl_t *hdl)
fmd_hdl_strfree(hdl, sfp->sf_fru);
fmd_hdl_free(hdl, sfp, sizeof (sensor_fault_t));
}
-
+ nvlist_free(stp->st_spoofs);
fmd_hdl_free(hdl, stp, sizeof (sensor_transport_t));
}
+ fmd_prop_free_string(hdl, spoof_prop);
}
diff --git a/usr/src/lib/fm/topo/libtopo/common/topo_method.c b/usr/src/lib/fm/topo/libtopo/common/topo_method.c
index 8d36e96d9a..79e10302af 100644
--- a/usr/src/lib/fm/topo/libtopo/common/topo_method.c
+++ b/usr/src/lib/fm/topo/libtopo/common/topo_method.c
@@ -22,11 +22,15 @@
* Copyright 2009 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
+/*
+ * Copyright (c) 2018, Joyent, Inc.
+ */
#include <pthread.h>
#include <assert.h>
#include <errno.h>
#include <dirent.h>
+#include <fnmatch.h>
#include <limits.h>
#include <alloca.h>
#include <unistd.h>
@@ -358,6 +362,44 @@ topo_sensor_failed(int32_t type, uint32_t state, struct sensor_errinfo *seinfo)
return (failed);
}
+static boolean_t
+topo_spoof_apply(topo_hdl_t *thp, tnode_t *node, tnode_t *facnode,
+ nvlist_t *in, uint32_t *state)
+{
+ nvpair_t *elem = NULL;
+ nvlist_t *spoof, *rsrc = NULL;
+ char *fmrimatch, *fmri, *facmatch;
+ uint32_t spoof_state;
+ int err;
+
+ while ((elem = nvlist_next_nvpair(in, elem)) != NULL) {
+ if (nvpair_value_nvlist(elem, &spoof) != 0)
+ return (B_FALSE);
+
+ if (nvlist_lookup_string(spoof, ST_SPOOF_FMRI, &fmrimatch) !=
+ 0 || nvlist_lookup_string(spoof, ST_SPOOF_SENSOR,
+ &facmatch) != 0 || nvlist_lookup_uint32(spoof,
+ ST_SPOOF_STATE, &spoof_state) != 0)
+ continue;
+
+ if (topo_node_resource(node, &rsrc, &err) != 0 ||
+ topo_fmri_nvl2str(thp, rsrc, &fmri, &err) != 0) {
+ nvlist_free(rsrc);
+ continue;
+ }
+ nvlist_free(rsrc);
+
+ if (fnmatch(fmrimatch, fmri, 0) == 0 &&
+ strcmp(facmatch, topo_node_name(facnode)) == 0) {
+ *state = spoof_state;
+ topo_hdl_strfree(thp, fmri);
+ return (B_TRUE);
+ }
+ topo_hdl_strfree(thp, fmri);
+ }
+ return (B_FALSE);
+}
+
/*
* Determine whether there are any sensors indicating failure. This function
* is used internally to determine whether a given component is usable, as well
@@ -365,23 +407,26 @@ topo_sensor_failed(int32_t type, uint32_t state, struct sensor_errinfo *seinfo)
* which sensors indicated failure. The return value is an nvlist of nvlists
* indexed by sensor name, each entry with the following contents:
*
- * type, state, units, reading
+ * type, state, units, reading
*
- * Identical to sensor node.
+ * Identical to sensor node.
*
- * nonrecov
+ * nonrecov
*
- * Boolean value that is set to indicate that the error is
- * non-recoverable (the unit is out of service). The default is
- * critical failure, which indicates a fault but the unit is still
- * operating.
+ * Boolean value that is set to indicate that the error is
+ * non-recoverable (the unit is out of service). The default is
+ * critical failure, which indicates a fault but the unit is still
+ * operating.
+ *
+ * injected
+ *
+ * Boolean value indicating that the sensor state was injected.
*/
/*ARGSUSED*/
int
topo_method_sensor_failure(topo_mod_t *mod, tnode_t *node,
topo_version_t version, nvlist_t *in, nvlist_t **out)
{
- const char *name = topo_node_name(node);
topo_faclist_t faclist, *fp;
int err;
nvlist_t *nvl, *props, *propval, *tmp;
@@ -390,12 +435,9 @@ topo_method_sensor_failure(topo_mod_t *mod, tnode_t *node,
nvpair_t *elem;
double reading;
char *propname;
- boolean_t has_reading;
+ boolean_t has_reading, is_spoofed = B_FALSE;
struct sensor_errinfo seinfo;
- if (strcmp(name, PSU) != 0 && strcmp(name, FAN) != 0)
- return (topo_mod_seterrno(mod, ETOPO_METHOD_NOTSUP));
-
if (topo_node_facility(mod->tm_hdl, node, TOPO_FAC_TYPE_SENSOR,
TOPO_FAC_TYPE_ANY, &faclist, &err) != 0)
return (topo_mod_seterrno(mod, ETOPO_METHOD_NOTSUP));
@@ -441,6 +483,10 @@ topo_method_sensor_failure(topo_mod_t *mod, tnode_t *node,
}
}
+ if (in != NULL)
+ is_spoofed = topo_spoof_apply(mod->tm_hdl, node,
+ fp->tf_node, in, &state);
+
if (topo_sensor_failed(type, state, &seinfo)) {
tmp = NULL;
if (topo_mod_nvalloc(mod, &tmp, NV_UNIQUE_NAME) != 0 ||
@@ -456,6 +502,8 @@ topo_method_sensor_failure(topo_mod_t *mod, tnode_t *node,
"predictive", seinfo.se_predictive) != 0 ||
nvlist_add_uint32(tmp, "source",
seinfo.se_src) != 0 ||
+ nvlist_add_boolean_value(nvl, "injected",
+ is_spoofed) != 0 ||
(has_reading && nvlist_add_double(tmp,
TOPO_SENSOR_READING, reading) != 0) ||
nvlist_add_nvlist(nvl, topo_node_name(fp->tf_node),
@@ -472,6 +520,7 @@ topo_method_sensor_failure(topo_mod_t *mod, tnode_t *node,
}
nvlist_free(props);
+ is_spoofed = B_FALSE;
}
*out = nvl;
diff --git a/usr/src/lib/fm/topo/libtopo/common/topo_method.h b/usr/src/lib/fm/topo/libtopo/common/topo_method.h
index ed0733375d..3cf14b92ec 100644
--- a/usr/src/lib/fm/topo/libtopo/common/topo_method.h
+++ b/usr/src/lib/fm/topo/libtopo/common/topo_method.h
@@ -23,7 +23,9 @@
* Copyright 2008 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
-
+/*
+ * Copyright (c) 2018, Joyent, Inc.
+ */
#ifndef _TOPO_METHOD_H
#define _TOPO_METHOD_H
@@ -54,6 +56,14 @@ extern int topo_prop_method_version_register(tnode_t *, const char *,
int *);
/*
+ * These are for the private consumption of the sensor-transport fmd plugin
+ * and topo_method_sensor_failure()
+ */
+#define ST_SPOOF_FMRI "spoof_resource_fmri"
+#define ST_SPOOF_SENSOR "spoof_sensor_name"
+#define ST_SPOOF_STATE "spoof_sensor_state"
+
+/*
* FMRI methods
*/
#define TOPO_METH_ASRU_COMPUTE "topo_asru_compute"
diff --git a/usr/src/lib/fm/topo/modules/common/fac_prov_ipmi/fac_prov_ipmi.c b/usr/src/lib/fm/topo/modules/common/fac_prov_ipmi/fac_prov_ipmi.c
index b394923833..434790fd65 100644
--- a/usr/src/lib/fm/topo/modules/common/fac_prov_ipmi/fac_prov_ipmi.c
+++ b/usr/src/lib/fm/topo/modules/common/fac_prov_ipmi/fac_prov_ipmi.c
@@ -113,6 +113,9 @@ static const topo_method_t ipmi_node_methods[] = {
{ "cs_ipmi_entity", TOPO_PROP_METH_DESC,
TOPO_METH_DIMM_IPMI_ENTITY_VERSION,
TOPO_STABILITY_INTERNAL, cs_ipmi_entity },
+ { TOPO_METH_SENSOR_FAILURE, TOPO_METH_SENSOR_FAILURE_DESC,
+ TOPO_METH_SENSOR_FAILURE_VERSION, TOPO_STABILITY_INTERNAL,
+ topo_method_sensor_failure },
{ NULL }
};
@@ -351,10 +354,12 @@ ipmi_sensor_state(topo_mod_t *mod, tnode_t *node, topo_version_t vers,
ipmi_handle_t *hdl;
int err, i;
uint8_t sensor_num;
+ uint32_t e_id, e_inst;
ipmi_sdr_full_sensor_t *fsensor;
ipmi_sdr_compact_sensor_t *csensor;
nvlist_t *nvl;
boolean_t found_sdr = B_FALSE;
+ tnode_t *pnode;
if (vers > TOPO_METH_IPMI_STATE_VERSION)
return (topo_mod_seterrno(mod, ETOPO_METHOD_VERNEW));
@@ -372,8 +377,18 @@ ipmi_sensor_state(topo_mod_t *mod, tnode_t *node, topo_version_t vers,
return (-1);
}
+ pnode = topo_node_parent(node);
+ if (topo_prop_get_uint32(pnode, TOPO_PGROUP_IPMI,
+ TOPO_PROP_IPMI_ENTITY_ID, &e_id, &err) != 0 ||
+ topo_prop_get_uint32(pnode, TOPO_PGROUP_IPMI,
+ TOPO_PROP_IPMI_ENTITY_INST, &e_inst, &err) != 0) {
+ e_id = IPMI_ET_UNSPECIFIED;
+ e_inst = 0;
+ }
+
for (i = 0; i < nelems; i++) {
- if ((sdr = ipmi_sdr_lookup(hdl, entity_refs[i])) != NULL) {
+ if ((sdr = ipmi_sdr_lookup_precise(hdl, entity_refs[i],
+ (uint8_t)e_id, (uint8_t)e_inst)) != NULL) {
found_sdr = B_TRUE;
break;
} else
@@ -438,12 +453,16 @@ ipmi_sensor_reading(topo_mod_t *mod, tnode_t *node, topo_version_t vers,
char **entity_refs, reading_str[BUFSZ];
uint_t nelems;
int err = 0, i;
- ipmi_sdr_full_sensor_t *sensor;
+ ipmi_sdr_t *sdr = NULL;
+ ipmi_sdr_full_sensor_t *fsensor;
ipmi_sensor_reading_t *reading;
double conv_reading;
ipmi_handle_t *hdl;
nvlist_t *nvl;
boolean_t found_sdr = B_FALSE;
+ uint8_t sensor_num;
+ uint32_t e_id, e_inst;
+ tnode_t *pnode;
if (vers > TOPO_METH_IPMI_READING_VERSION)
return (topo_mod_seterrno(mod, ETOPO_METHOD_VERNEW));
@@ -461,9 +480,18 @@ ipmi_sensor_reading(topo_mod_t *mod, tnode_t *node, topo_version_t vers,
return (-1);
}
+ pnode = topo_node_parent(node);
+ if (topo_prop_get_uint32(pnode, TOPO_PGROUP_IPMI,
+ TOPO_PROP_IPMI_ENTITY_ID, &e_id, &err) != 0 ||
+ topo_prop_get_uint32(pnode, TOPO_PGROUP_IPMI,
+ TOPO_PROP_IPMI_ENTITY_INST, &e_inst, &err) != 0) {
+ e_id = IPMI_ET_UNSPECIFIED;
+ e_inst = 0;
+ }
+
for (i = 0; i < nelems; i++) {
- if ((sensor = ipmi_sdr_lookup_full_sensor(hdl, entity_refs[i]))
- != NULL) {
+ if ((sdr = ipmi_sdr_lookup_precise(hdl, entity_refs[i],
+ (uint8_t)e_id, (uint8_t)e_inst)) != NULL) {
found_sdr = B_TRUE;
break;
} else
@@ -476,19 +504,30 @@ ipmi_sensor_reading(topo_mod_t *mod, tnode_t *node, topo_version_t vers,
topo_mod_ipmi_rele(mod);
return (-1);
}
+ switch (sdr->is_type) {
+ case IPMI_SDR_TYPE_FULL_SENSOR:
+ fsensor = (ipmi_sdr_full_sensor_t *)sdr->is_record;
+ sensor_num = fsensor->is_fs_number;
+ break;
+ default:
+ topo_mod_dprintf(mod, "%s does not refer to a full "
+ "sensor SDR\n", entity_refs[i]);
+ topo_mod_ipmi_rele(mod);
+ strarr_free(mod, entity_refs, nelems);
+ return (-1);
+ }
- if ((reading = ipmi_get_sensor_reading(hdl, sensor->is_fs_number))
- == NULL) {
+ if ((reading = ipmi_get_sensor_reading(hdl, sensor_num)) == NULL) {
topo_mod_dprintf(mod, "Failed to get sensor reading for sensor "
"%s, sensor_num=%d (%s)\n", entity_refs[i],
- sensor->is_fs_number, ipmi_errmsg(hdl));
+ sensor_num, ipmi_errmsg(hdl));
strarr_free(mod, entity_refs, nelems);
topo_mod_ipmi_rele(mod);
return (-1);
}
topo_mod_ipmi_rele(mod);
- if (ipmi_sdr_conv_reading(sensor, reading->isr_reading, &conv_reading)
+ if (ipmi_sdr_conv_reading(fsensor, reading->isr_reading, &conv_reading)
!= 0) {
topo_mod_dprintf(mod, "Failed to convert sensor reading for "
"sensor %s (%s)\n", entity_refs[i], ipmi_errmsg(hdl));
diff --git a/usr/src/lib/libipmi/common/ipmi_sdr.c b/usr/src/lib/libipmi/common/ipmi_sdr.c
index 2adab34f6c..14a5fbd8cc 100644
--- a/usr/src/lib/libipmi/common/ipmi_sdr.c
+++ b/usr/src/lib/libipmi/common/ipmi_sdr.c
@@ -23,6 +23,10 @@
* Copyright 2010 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
+/*
+ * Copyright (c) 2018, Joyent, Inc.
+ */
+
#include <libipmi.h>
#include <stddef.h>
@@ -83,6 +87,8 @@
typedef struct ipmi_sdr_cache_ent {
char *isc_name;
+ uint8_t isc_entity_id;
+ uint8_t isc_entity_inst;
struct ipmi_sdr *isc_sdr;
ipmi_hash_link_t isc_link;
} ipmi_sdr_cache_ent_t;
@@ -184,7 +190,7 @@ ipmi_sdr_refresh(ipmi_handle_t *ihp)
ipmi_sdr_t *sdr;
ipmi_sdr_cache_ent_t *ent;
size_t namelen;
- uint8_t type;
+ uint8_t type, e_id = 0, e_inst = 0;
char *name;
ipmi_sdr_info_t *sip;
uint32_t isi_add_ts, isi_erase_ts;
@@ -223,6 +229,8 @@ ipmi_sdr_refresh(ipmi_handle_t *ihp)
namelen = glp->is_gl_idlen;
type = glp->is_gl_idtype;
name = glp->is_gl_idstring;
+ e_id = glp->is_gl_entity;
+ e_inst = glp->is_gl_instance;
break;
}
@@ -234,6 +242,8 @@ ipmi_sdr_refresh(ipmi_handle_t *ihp)
namelen = flp->is_fl_idlen;
name = flp->is_fl_idstring;
type = flp->is_fl_idtype;
+ e_id = flp->is_fl_entity;
+ e_inst = flp->is_fl_instance;
break;
}
@@ -247,6 +257,8 @@ ipmi_sdr_refresh(ipmi_handle_t *ihp)
namelen = csp->is_cs_idlen;
type = csp->is_cs_idtype;
name = csp->is_cs_idstring;
+ e_id = csp->is_cs_entity_id;
+ e_inst = csp->is_cs_entity_instance;
tmp = LE_IN16(&csp->is_cs_assert_mask);
(void) memcpy(&csp->is_cs_assert_mask, &tmp,
@@ -272,6 +284,8 @@ ipmi_sdr_refresh(ipmi_handle_t *ihp)
namelen = fsp->is_fs_idlen;
type = fsp->is_fs_idtype;
name = fsp->is_fs_idstring;
+ e_id = fsp->is_fs_entity_id;
+ e_inst = fsp->is_fs_entity_instance;
tmp = LE_IN16(&fsp->is_fs_assert_mask);
(void) memcpy(&fsp->is_fs_assert_mask, &tmp,
@@ -295,6 +309,8 @@ ipmi_sdr_refresh(ipmi_handle_t *ihp)
namelen = esp->is_eo_idlen;
type = esp->is_eo_idtype;
name = esp->is_eo_idstring;
+ e_id = esp->is_eo_entity_id;
+ e_inst = esp->is_eo_entity_instance;
break;
}
@@ -306,6 +322,8 @@ ipmi_sdr_refresh(ipmi_handle_t *ihp)
namelen = msp->is_ml_idlen;
type = msp->is_ml_idtype;
name = msp->is_ml_idstring;
+ e_id = msp->is_ml_entity_id;
+ e_inst = msp->is_ml_entity_instance;
break;
}
@@ -334,6 +352,8 @@ ipmi_sdr_refresh(ipmi_handle_t *ihp)
}
ent->isc_sdr = sdr;
+ ent->isc_entity_id = e_id;
+ ent->isc_entity_inst = e_inst;
if (name != NULL) {
if ((ent->isc_name = ipmi_alloc(ihp, namelen + 1)) ==
@@ -407,18 +427,17 @@ ipmi_sdr_hash_compare(const void *a, const void *b)
return (-1);
/*
- * While it is strange for a service processor to report multiple
- * entries with the same name, we allow it by treating the (name, id)
- * as the unique identifier. When looking up by name, the SDR pointer
- * is NULL, and we return the first matching name.
+ * When looking up only by name we return the first matching name. For
+ * a more precise match, callers can optionally specify an IPMI entity
+ * ID and instance that must also match.
*/
- if (ap->isc_sdr == NULL || bp->isc_sdr == NULL)
- return (0);
-
- if (ap->isc_sdr->is_id == bp->isc_sdr->is_id)
- return (0);
- else
- return (-1);
+ if (ap->isc_entity_id != IPMI_ET_UNSPECIFIED &&
+ bp->isc_entity_id != IPMI_ET_UNSPECIFIED) {
+ if (ap->isc_entity_id != bp->isc_entity_id ||
+ ap->isc_entity_inst != bp->isc_entity_inst)
+ return (-1);
+ }
+ return (0);
}
int
@@ -564,6 +583,13 @@ ipmi_sdr_iter(ipmi_handle_t *ihp, int (*func)(ipmi_handle_t *,
ipmi_sdr_t *
ipmi_sdr_lookup(ipmi_handle_t *ihp, const char *idstr)
{
+ return (ipmi_sdr_lookup_precise(ihp, idstr, IPMI_ET_UNSPECIFIED, 0));
+}
+
+ipmi_sdr_t *
+ipmi_sdr_lookup_precise(ipmi_handle_t *ihp, const char *idstr, uint8_t e_id,
+ uint8_t e_inst)
+{
ipmi_sdr_cache_ent_t *ent, search;
if (ipmi_hash_first(ihp->ih_sdr_cache) == NULL &&
@@ -572,6 +598,8 @@ ipmi_sdr_lookup(ipmi_handle_t *ihp, const char *idstr)
search.isc_name = (char *)idstr;
search.isc_sdr = NULL;
+ search.isc_entity_id = e_id;
+ search.isc_entity_inst = e_inst;
if ((ent = ipmi_hash_lookup(ihp->ih_sdr_cache, &search)) == NULL) {
(void) ipmi_set_error(ihp, EIPMI_NOT_PRESENT, NULL);
return (NULL);
diff --git a/usr/src/lib/libipmi/common/libipmi.h b/usr/src/lib/libipmi/common/libipmi.h
index 92a43c6758..1e69e57854 100644
--- a/usr/src/lib/libipmi/common/libipmi.h
+++ b/usr/src/lib/libipmi/common/libipmi.h
@@ -1522,10 +1522,13 @@ extern int ipmi_sdr_iter(ipmi_handle_t *,
int (*)(ipmi_handle_t *, const char *, ipmi_sdr_t *, void *), void *);
/*
- * Lookup the given sensor type by name. These functions automatically read in
- * and cache the complete SDR repository.
+ * Lookup the given sensor type by name or a combination of name and entity
+ * ID/instance. These functions automatically read in and cache the complete
+ * SDR repository.
*/
extern ipmi_sdr_t *ipmi_sdr_lookup(ipmi_handle_t *, const char *);
+extern ipmi_sdr_t *ipmi_sdr_lookup_precise(ipmi_handle_t *, const char *,
+ uint8_t, uint8_t);
extern ipmi_sdr_fru_locator_t *ipmi_sdr_lookup_fru(ipmi_handle_t *,
const char *);
extern ipmi_sdr_generic_locator_t *ipmi_sdr_lookup_generic(ipmi_handle_t *,
diff --git a/usr/src/lib/libipmi/common/mapfile-vers b/usr/src/lib/libipmi/common/mapfile-vers
index 3852cf83f4..155fcbc471 100644
--- a/usr/src/lib/libipmi/common/mapfile-vers
+++ b/usr/src/lib/libipmi/common/mapfile-vers
@@ -80,6 +80,7 @@ SYMBOL_VERSION SUNWprivate_1.1 {
ipmi_sdr_lookup_full_sensor;
ipmi_sdr_lookup_fru;
ipmi_sdr_lookup_generic;
+ ipmi_sdr_lookup_precise;
ipmi_sdr_refresh;
ipmi_sel_get_entry;
ipmi_sel_get_info;