diff options
author | Rob Johnston <rob.johnston@joyent.com> | 2018-06-06 21:24:18 -0700 |
---|---|---|
committer | Richard Lowe <richlowe@richlowe.net> | 2018-06-28 22:44:13 +0000 |
commit | ea30102ce458697473b0435bcdc7647dce2551f4 (patch) | |
tree | a0e74fd0c0b7029d01d233762f0ff98a4eaae39e | |
parent | 4e0c5eff9af325c80994e9527b7cb8b3a1ffd1d4 (diff) | |
download | illumos-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.c | 98 | ||||
-rw-r--r-- | usr/src/lib/fm/topo/libtopo/common/topo_method.c | 73 | ||||
-rw-r--r-- | usr/src/lib/fm/topo/libtopo/common/topo_method.h | 12 | ||||
-rw-r--r-- | usr/src/lib/fm/topo/modules/common/fac_prov_ipmi/fac_prov_ipmi.c | 55 | ||||
-rw-r--r-- | usr/src/lib/libipmi/common/ipmi_sdr.c | 52 | ||||
-rw-r--r-- | usr/src/lib/libipmi/common/libipmi.h | 7 | ||||
-rw-r--r-- | usr/src/lib/libipmi/common/mapfile-vers | 1 |
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; |