10d63ce2bSvenki /*
20d63ce2bSvenki * CDDL HEADER START
30d63ce2bSvenki *
40d63ce2bSvenki * The contents of this file are subject to the terms of the
50d63ce2bSvenki * Common Development and Distribution License (the "License").
60d63ce2bSvenki * You may not use this file except in compliance with the License.
70d63ce2bSvenki *
80d63ce2bSvenki * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
90d63ce2bSvenki * or http://www.opensolaris.org/os/licensing.
100d63ce2bSvenki * See the License for the specific language governing permissions
110d63ce2bSvenki * and limitations under the License.
120d63ce2bSvenki *
130d63ce2bSvenki * When distributing Covered Code, include this CDDL HEADER in each
140d63ce2bSvenki * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
150d63ce2bSvenki * If applicable, add the following below this CDDL HEADER, with the
160d63ce2bSvenki * fields enclosed by brackets "[]" replaced with your own identifying
170d63ce2bSvenki * information: Portions Copyright [yyyy] [name of copyright owner]
180d63ce2bSvenki *
190d63ce2bSvenki * CDDL HEADER END
200d63ce2bSvenki */
210d63ce2bSvenki
220d63ce2bSvenki /*
23*34f1a571SMichael Bergknoff * Copyright 2010 Sun Microsystems, Inc. All rights reserved.
240d63ce2bSvenki * Use is subject to license terms.
250d63ce2bSvenki */
260d63ce2bSvenki
270d63ce2bSvenki /*
280d63ce2bSvenki * The SNMP picl plugin connects to the agent on the SP and creates
290d63ce2bSvenki * and populates the /physical-platform subtree in picl tree for use
300d63ce2bSvenki * by picl consumers.
310d63ce2bSvenki */
320d63ce2bSvenki
330d63ce2bSvenki #include <stdio.h>
340d63ce2bSvenki #include <stdlib.h>
350d63ce2bSvenki #include <string.h>
360d63ce2bSvenki #include <syslog.h>
370d63ce2bSvenki #include <stdarg.h>
380d63ce2bSvenki #include <libgen.h>
390d63ce2bSvenki #include <libintl.h>
400d63ce2bSvenki #include <thread.h>
410d63ce2bSvenki #include <synch.h>
420d63ce2bSvenki #include <errno.h>
43817697f4SKelly Moyer #include <time.h>
44*34f1a571SMichael Bergknoff #include <signal.h>
450d63ce2bSvenki
460d63ce2bSvenki #include <picldefs.h>
470d63ce2bSvenki #include <picl.h>
480d63ce2bSvenki #include <picltree.h>
490d63ce2bSvenki
500d63ce2bSvenki #include "picloids.h"
510d63ce2bSvenki #include "libpiclsnmp.h"
520d63ce2bSvenki #include "snmpplugin.h"
530d63ce2bSvenki
540d63ce2bSvenki #pragma init(snmpplugin_register) /* place in .init section */
550d63ce2bSvenki
560d63ce2bSvenki picld_plugin_reg_t snmpplugin_reg = {
570d63ce2bSvenki PICLD_PLUGIN_VERSION_1,
580d63ce2bSvenki PICLD_PLUGIN_NON_CRITICAL,
590d63ce2bSvenki "snmp_plugin",
600d63ce2bSvenki snmpplugin_init,
610d63ce2bSvenki snmpplugin_fini
620d63ce2bSvenki };
630d63ce2bSvenki
640d63ce2bSvenki static picl_snmphdl_t hdl;
650d63ce2bSvenki
660d63ce2bSvenki /*
670d63ce2bSvenki * The stale_tree_rwlp protects the stale_xxx vars. The 'stale_tree' flag
680d63ce2bSvenki * and the 'rebuild_tree' flag below are both initialized to B_TRUE to
690d63ce2bSvenki * let the tree_builder() thread build the initial tree without blocking.
700d63ce2bSvenki */
710d63ce2bSvenki static rwlock_t stale_tree_rwlp;
720d63ce2bSvenki static boolean_t stale_tree = B_TRUE;
730d63ce2bSvenki
740d63ce2bSvenki /*
750d63ce2bSvenki * vol_props, volprop_ndx and n_vol_props are protected by the stale_tree
760d63ce2bSvenki * flag. They are read only when the stale_tree flag is B_FALSE and written
770d63ce2bSvenki * to only when the flag is B_TRUE.
780d63ce2bSvenki *
790d63ce2bSvenki * The change_time (last changed time) is read by only one thread at a
800d63ce2bSvenki * time when stale_tree is B_FALSE (protected by stale_tree_rwlp). It is
810d63ce2bSvenki * written by only one thread (the tree builder) when stale_tree is B_TRUE.
820d63ce2bSvenki *
830d63ce2bSvenki * Note that strictly speaking, change_time should be uint_t (timeticks32).
840d63ce2bSvenki * But keeping it as int is fine, since we don't do any arithmetic on it
850d63ce2bSvenki * except equality check.
860d63ce2bSvenki */
870d63ce2bSvenki static vol_prophdl_t *vol_props = NULL;
880d63ce2bSvenki static int volprop_ndx = 0, n_vol_props = 0;
890d63ce2bSvenki static int change_time = 0;
901c60fca8Sfw157321 static time_t change_time_check;
910d63ce2bSvenki
920d63ce2bSvenki /*
930d63ce2bSvenki * The rebuild_tree_lock and cv are used by the tree builder thread.
940d63ce2bSvenki * rebuild_tree has to be initialized to B_TRUE to let the tree_builder
950d63ce2bSvenki * do the first build without blocking.
960d63ce2bSvenki */
970d63ce2bSvenki static mutex_t rebuild_tree_lock;
980d63ce2bSvenki static cond_t rebuild_tree_cv;
990d63ce2bSvenki static boolean_t rebuild_tree = B_TRUE;
100d2b9c676Sfw157321 static boolean_t tree_builder_thr_exit = B_FALSE;
101d2b9c676Sfw157321 static thread_t tree_builder_thr_id;
1020d63ce2bSvenki
1030d63ce2bSvenki /*
104817697f4SKelly Moyer * The cache_refresh thread periodically queries the snmp cache refresh work
105817697f4SKelly Moyer * queue and processes jobs from it to keep cache entries from expiring. It
106817697f4SKelly Moyer * attempts to run in cycles of CACHE_REFRESH_CYCLE seconds each, first
107817697f4SKelly Moyer * processing cache refresh jobs and then sleeping for the remainder of the
108817697f4SKelly Moyer * cycle once the next refresh job expiration is at least
109817697f4SKelly Moyer * CACHE_REFRESH_MIN_WINDOW seconds in the future.
110817697f4SKelly Moyer *
111817697f4SKelly Moyer * NOTE: By using a thread to keep the SNMP cache refreshed in the background,
112817697f4SKelly Moyer * we are both adding load to the system and reducing the system's ability to
113817697f4SKelly Moyer * operate in power-saving mode when there is minimal load. While these
114817697f4SKelly Moyer * tradeoffs are acceptable at this time in light of customer concerns about
115817697f4SKelly Moyer * performance, it may be desirable in the future to move this work into the
116817697f4SKelly Moyer * firmware. Also, while the current cycle times performed well on the largest
117817697f4SKelly Moyer * sun4v config currently available (Batoka), they may need to be revisited for
118817697f4SKelly Moyer * future systems if the number of sensors increases significantly.
119817697f4SKelly Moyer */
120817697f4SKelly Moyer #define CACHE_REFRESH_CYCLE 60
121817697f4SKelly Moyer #define CACHE_REFRESH_MIN_WINDOW 75
122817697f4SKelly Moyer static mutex_t cache_refresh_lock;
123817697f4SKelly Moyer static cond_t cache_refresh_cv;
124817697f4SKelly Moyer static boolean_t cache_refresh_thr_exit = B_FALSE;
125817697f4SKelly Moyer static thread_t cache_refresh_thr_id;
126817697f4SKelly Moyer
127817697f4SKelly Moyer /*
1280d63ce2bSvenki * These two should really not be global
1290d63ce2bSvenki */
1300d63ce2bSvenki static picl_nodehdl_t *physplat_nodes = NULL;
1310d63ce2bSvenki static int n_physplat_nodes = 0;
1320d63ce2bSvenki
1330d63ce2bSvenki static char *group1[] = {
1340d63ce2bSvenki OID_entPhysicalDescr,
1350d63ce2bSvenki OID_entPhysicalContainedIn,
1360d63ce2bSvenki OID_entPhysicalClass,
1370d63ce2bSvenki OID_entPhysicalName,
1380d63ce2bSvenki OID_entPhysicalHardwareRev,
1390d63ce2bSvenki OID_entPhysicalFirmwareRev,
1400d63ce2bSvenki OID_entPhysicalSerialNum,
1410d63ce2bSvenki OID_entPhysicalMfgName,
1420d63ce2bSvenki OID_entPhysicalModelName,
1430d63ce2bSvenki OID_entPhysicalIsFRU,
1440d63ce2bSvenki 0
1450d63ce2bSvenki };
1460d63ce2bSvenki
1470d63ce2bSvenki static char *group2[] = {
1480d63ce2bSvenki OID_sunPlatEquipmentHolderAcceptableTypes,
1490d63ce2bSvenki OID_sunPlatCircuitPackReplaceable,
1500d63ce2bSvenki OID_sunPlatCircuitPackHotSwappable,
1510d63ce2bSvenki OID_sunPlatPhysicalClass,
1520d63ce2bSvenki OID_sunPlatSensorClass,
1530d63ce2bSvenki OID_sunPlatSensorType,
1540d63ce2bSvenki OID_sunPlatAlarmType,
1550d63ce2bSvenki OID_sunPlatPowerSupplyClass,
1560d63ce2bSvenki 0
1570d63ce2bSvenki };
1580d63ce2bSvenki
1591c60fca8Sfw157321 static char *group3[] = {
1601c60fca8Sfw157321 OID_sunPlatNumericSensorEnabledThresholds,
1611c60fca8Sfw157321 OID_sunPlatNumericSensorBaseUnits,
1621c60fca8Sfw157321 OID_sunPlatNumericSensorRateUnits,
1631c60fca8Sfw157321 0
1641c60fca8Sfw157321 };
1651c60fca8Sfw157321
1661c60fca8Sfw157321 static char *group4[] = {
1671c60fca8Sfw157321 OID_sunPlatBinarySensorInterpretTrue,
1681c60fca8Sfw157321 OID_sunPlatBinarySensorInterpretFalse,
169c8268b2cSKelly Moyer 0
1701c60fca8Sfw157321 };
1711c60fca8Sfw157321
1720d63ce2bSvenki static char *volgroup1[] = {
1730d63ce2bSvenki OID_sunPlatBinarySensorCurrent,
1740d63ce2bSvenki OID_sunPlatBinarySensorExpected,
1750d63ce2bSvenki 0
1760d63ce2bSvenki };
1770d63ce2bSvenki
1780d63ce2bSvenki static char *volgroup2[] = {
1790d63ce2bSvenki OID_sunPlatNumericSensorExponent,
1800d63ce2bSvenki OID_sunPlatNumericSensorCurrent,
1810d63ce2bSvenki OID_sunPlatNumericSensorLowerThresholdFatal,
1820d63ce2bSvenki OID_sunPlatNumericSensorLowerThresholdCritical,
1830d63ce2bSvenki OID_sunPlatNumericSensorLowerThresholdNonCritical,
1840d63ce2bSvenki OID_sunPlatNumericSensorUpperThresholdNonCritical,
1850d63ce2bSvenki OID_sunPlatNumericSensorUpperThresholdCritical,
1860d63ce2bSvenki OID_sunPlatNumericSensorUpperThresholdFatal,
1870d63ce2bSvenki 0
1880d63ce2bSvenki };
1890d63ce2bSvenki
1901c60fca8Sfw157321 static char *volgroup3[] = {
1911c60fca8Sfw157321 OID_sunPlatEquipmentOperationalState,
1921c60fca8Sfw157321 0
1931c60fca8Sfw157321 };
1941c60fca8Sfw157321
1951c60fca8Sfw157321 static char *volgroup4[] = {
1961c60fca8Sfw157321 OID_sunPlatAlarmState,
1971c60fca8Sfw157321 0
1981c60fca8Sfw157321 };
1991c60fca8Sfw157321
2001c60fca8Sfw157321 static char *volgroup5[] = {
2011c60fca8Sfw157321 OID_sunPlatBatteryStatus,
2021c60fca8Sfw157321 0
2031c60fca8Sfw157321 };
2041c60fca8Sfw157321
2050d63ce2bSvenki /*
2060d63ce2bSvenki * The following two items must match the Sun Platform MIB specification
2070d63ce2bSvenki * in their indices and values.
2080d63ce2bSvenki */
2090d63ce2bSvenki static char *sensor_baseunits[] = {
2100d63ce2bSvenki "", "other", "unknown", "degC", "degF", "degK", "volts", "amps",
2110d63ce2bSvenki "watts", "joules", "coulombs", "va", "nits", "lumens", "lux",
2120d63ce2bSvenki "candelas", "kPa", "psi", "newtons", "cfm", "rpm", "hertz",
2130d63ce2bSvenki "seconds", "minutes", "hours", "days", "weeks", "mils", "inches",
2140d63ce2bSvenki "feet", "cubicInches", "cubicFeet", "meters", "cubicCentimeters",
2150d63ce2bSvenki "cubicMeters", "liters", "fluidOunces", "radians", "steradians",
2160d63ce2bSvenki "revolutions", "cycles", "gravities", "ounces", "pounds", "footPounds",
2170d63ce2bSvenki "ounceInches", "gauss", "gilberts", "henries", "farads", "ohms",
2180d63ce2bSvenki "siemens", "moles", "becquerels", "ppm", "decibels", "dBA", "dbC",
2190d63ce2bSvenki "grays", "sieverts", "colorTemperatureDegK", "bits", "bytes", "words",
2200d63ce2bSvenki "doubleWords", "quadWords", "percentage"
2210d63ce2bSvenki };
2220d63ce2bSvenki static const int n_baseunits = sizeof (sensor_baseunits) / sizeof (char *);
2230d63ce2bSvenki
2240d63ce2bSvenki static char *sensor_rateunits[] = {
2250d63ce2bSvenki "",
2260d63ce2bSvenki "none",
2270d63ce2bSvenki "perMicroSecond",
2280d63ce2bSvenki "perMilliSecond",
2290d63ce2bSvenki "perSecond",
2300d63ce2bSvenki "perMinute",
2310d63ce2bSvenki "perHour",
2320d63ce2bSvenki "perDay",
2330d63ce2bSvenki "perWeek",
2340d63ce2bSvenki "perMonth",
2350d63ce2bSvenki "perYear"
2360d63ce2bSvenki };
2370d63ce2bSvenki static const int n_rateunits = sizeof (sensor_rateunits) / sizeof (char *);
2380d63ce2bSvenki
2390d63ce2bSvenki /*
2400d63ce2bSvenki * Local declarations
2410d63ce2bSvenki */
2420d63ce2bSvenki static void snmpplugin_register(void);
2430d63ce2bSvenki static void register_group(char **g, int is_volatile);
2440d63ce2bSvenki static void *tree_builder(void *arg);
2450d63ce2bSvenki static int build_physplat(picl_nodehdl_t *subtree_rootp);
2460d63ce2bSvenki static void free_resources(picl_nodehdl_t subtree_root);
2470d63ce2bSvenki
2480d63ce2bSvenki static picl_nodehdl_t make_node(picl_nodehdl_t subtree_root, int row,
2490d63ce2bSvenki int *snmp_syserr_p);
2500d63ce2bSvenki static void save_nodeh(picl_nodehdl_t nodeh, int row);
2510d63ce2bSvenki static picl_nodehdl_t lookup_nodeh(int row);
2520d63ce2bSvenki
2530d63ce2bSvenki static void save_volprop(picl_prophdl_t prop, char *oidstr, int row,
2540d63ce2bSvenki int proptype);
2551c60fca8Sfw157321 static void check_for_stale_data(boolean_t nocache);
2560d63ce2bSvenki static int read_volprop(ptree_rarg_t *parg, void *buf);
2570d63ce2bSvenki
2580d63ce2bSvenki static void threshold(picl_nodehdl_t node, char *oidstr, int row,
2590d63ce2bSvenki char *propname, int *snmp_syserr_p);
2600d63ce2bSvenki static void add_thresholds(picl_nodehdl_t node, int row, int *snmp_syserr_p);
2610d63ce2bSvenki
2620d63ce2bSvenki static char *get_slot_type(int row, int *snmp_syserr_p);
2630d63ce2bSvenki static int add_volatile_prop(picl_nodehdl_t nodeh, char *name,
2640d63ce2bSvenki int type, int access, int size, int (*rdfunc)(ptree_rarg_t *, void *),
2650d63ce2bSvenki int (*wrfunc)(ptree_warg_t *, const void *), picl_prophdl_t *propp);
2660d63ce2bSvenki static int add_string_prop(picl_nodehdl_t node, char *propname, char *propval);
2670d63ce2bSvenki static int add_void_prop(picl_nodehdl_t node, char *propname);
2680d63ce2bSvenki static void add_prop(picl_nodehdl_t nodeh, picl_prophdl_t *php, char *label,
2690d63ce2bSvenki int row, sp_propid_t pp, int *snmp_syserr_p);
2700d63ce2bSvenki
271817697f4SKelly Moyer static void *cache_refresher(void *arg);
272817697f4SKelly Moyer static void cache_refresher_fini(void);
273817697f4SKelly Moyer
2740d63ce2bSvenki static void log_msg(int pri, const char *fmt, ...);
2750d63ce2bSvenki
2760d63ce2bSvenki #ifdef SNMPPLUGIN_DEBUG
2770d63ce2bSvenki static mutex_t snmpplugin_dbuf_lock;
2780d63ce2bSvenki static char *snmpplugin_dbuf = NULL;
2790d63ce2bSvenki static char *snmpplugin_dbuf_curp = NULL;
2800d63ce2bSvenki static int snmpplugin_dbuf_sz = 0;
2810d63ce2bSvenki static int snmpplugin_dbuf_overflow = 0;
2820d63ce2bSvenki static char snmpplugin_lbuf[SNMPPLUGIN_DMAX_LINE];
2830d63ce2bSvenki
2840d63ce2bSvenki static void snmpplugin_log_init(void);
2850d63ce2bSvenki static void snmpplugin_log(const char *fmt, ...);
2860d63ce2bSvenki static void snmpplugin_log_append(void);
2870d63ce2bSvenki static void snmpplugin_dbuf_realloc(void);
2880d63ce2bSvenki #endif
2890d63ce2bSvenki
2900d63ce2bSvenki static void
snmpplugin_register(void)2910d63ce2bSvenki snmpplugin_register(void)
2920d63ce2bSvenki {
2930d63ce2bSvenki (void) picld_plugin_register(&snmpplugin_reg);
2940d63ce2bSvenki }
2950d63ce2bSvenki
2960d63ce2bSvenki static void
register_group(char ** g,int is_volatile)2970d63ce2bSvenki register_group(char **g, int is_volatile)
2980d63ce2bSvenki {
2990d63ce2bSvenki int i, len = 0;
3000d63ce2bSvenki int n_oids;
3010d63ce2bSvenki char *p, *oidstrs;
3020d63ce2bSvenki
3030d63ce2bSvenki for (i = 0; g[i]; i++)
3040d63ce2bSvenki len += strlen(g[i]) + 1;
3050d63ce2bSvenki n_oids = i;
3060d63ce2bSvenki
3070d63ce2bSvenki if ((oidstrs = (char *)calloc(1, len)) == NULL)
3080d63ce2bSvenki return;
3090d63ce2bSvenki
3100d63ce2bSvenki for (p = oidstrs, i = 0; g[i]; i++) {
3110d63ce2bSvenki (void) strcpy(p, g[i]);
3120d63ce2bSvenki p += strlen(g[i]) + 1;
3130d63ce2bSvenki }
3140d63ce2bSvenki
3150d63ce2bSvenki snmp_register_group(hdl, oidstrs, n_oids, is_volatile);
3162ea390f3SMichael Bergknoff free(oidstrs);
3170d63ce2bSvenki }
3180d63ce2bSvenki
3190d63ce2bSvenki void
snmpplugin_init(void)3200d63ce2bSvenki snmpplugin_init(void)
3210d63ce2bSvenki {
3220d63ce2bSvenki int ret;
3230d63ce2bSvenki
3240d63ce2bSvenki (void) mutex_init(&rebuild_tree_lock, USYNC_THREAD, NULL);
3250d63ce2bSvenki (void) cond_init(&rebuild_tree_cv, USYNC_THREAD, NULL);
3260d63ce2bSvenki (void) rwlock_init(&stale_tree_rwlp, USYNC_THREAD, NULL);
327d2b9c676Sfw157321 tree_builder_thr_exit = B_FALSE;
328d2b9c676Sfw157321
3290d63ce2bSvenki LOGINIT();
3300d63ce2bSvenki
3310d63ce2bSvenki /*
3320d63ce2bSvenki * Create the tree-builder thread and let it take over
3330d63ce2bSvenki */
3340d63ce2bSvenki LOGPRINTF("Tree-builder thread being created.\n");
3350d63ce2bSvenki if ((ret = thr_create(NULL, NULL, tree_builder, NULL,
336d2b9c676Sfw157321 THR_BOUND, &tree_builder_thr_id)) < 0) {
3370d63ce2bSvenki log_msg(LOG_ERR, SNMPP_CANT_CREATE_TREE_BUILDER, ret);
3380d63ce2bSvenki snmp_fini(hdl);
339d2b9c676Sfw157321 hdl = NULL;
340d2b9c676Sfw157321 (void) rwlock_destroy(&stale_tree_rwlp);
341d2b9c676Sfw157321 (void) cond_destroy(&rebuild_tree_cv);
342d2b9c676Sfw157321 (void) mutex_destroy(&rebuild_tree_lock);
343d2b9c676Sfw157321 tree_builder_thr_exit = B_TRUE;
344817697f4SKelly Moyer
345817697f4SKelly Moyer return;
346817697f4SKelly Moyer }
347817697f4SKelly Moyer
348817697f4SKelly Moyer /*
349817697f4SKelly Moyer * While the cache refresher thread does improve performance, it is not
350817697f4SKelly Moyer * integral to the proper function of the plugin. If we fail to create
351817697f4SKelly Moyer * the thread for some reason, we will simply continue without
352817697f4SKelly Moyer * refreshing.
353817697f4SKelly Moyer */
354817697f4SKelly Moyer (void) mutex_init(&cache_refresh_lock, USYNC_THREAD, NULL);
355817697f4SKelly Moyer (void) cond_init(&cache_refresh_cv, USYNC_THREAD, NULL);
356817697f4SKelly Moyer cache_refresh_thr_exit = B_FALSE;
357817697f4SKelly Moyer
358817697f4SKelly Moyer LOGPRINTF("Cache refresher thread being created.\n");
359817697f4SKelly Moyer if (thr_create(NULL, NULL, cache_refresher, NULL, THR_BOUND,
360817697f4SKelly Moyer &cache_refresh_thr_id) < 0) {
361817697f4SKelly Moyer (void) cond_destroy(&cache_refresh_cv);
362817697f4SKelly Moyer (void) mutex_destroy(&cache_refresh_lock);
363817697f4SKelly Moyer cache_refresh_thr_exit = B_TRUE;
3640d63ce2bSvenki }
3650d63ce2bSvenki }
3660d63ce2bSvenki
3670d63ce2bSvenki void
snmpplugin_fini(void)3680d63ce2bSvenki snmpplugin_fini(void)
3690d63ce2bSvenki {
3700d63ce2bSvenki
371d2b9c676Sfw157321 if (tree_builder_thr_exit == B_TRUE)
372d2b9c676Sfw157321 return;
373d2b9c676Sfw157321
374d2b9c676Sfw157321 /*
375d2b9c676Sfw157321 * Make reads of volatile properties return PICL_PROPUNAVAILABLE
376d2b9c676Sfw157321 * since we're about to recycle the plug-in. No need to worry
377d2b9c676Sfw157321 * about removing /physical-platform since tree_builder() will
378d2b9c676Sfw157321 * take care of recycling it for us.
379d2b9c676Sfw157321 */
380d2b9c676Sfw157321 (void) rw_wrlock(&stale_tree_rwlp);
381d2b9c676Sfw157321 stale_tree = B_TRUE;
382d2b9c676Sfw157321 if (vol_props) {
383d2b9c676Sfw157321 free(vol_props);
384d2b9c676Sfw157321 }
385d2b9c676Sfw157321 vol_props = NULL;
386d2b9c676Sfw157321 volprop_ndx = 0;
387d2b9c676Sfw157321 n_vol_props = 0;
388d2b9c676Sfw157321 (void) rw_unlock(&stale_tree_rwlp);
389d2b9c676Sfw157321
390817697f4SKelly Moyer /* clean up the cache_refresher thread and structures */
391817697f4SKelly Moyer cache_refresher_fini();
392817697f4SKelly Moyer
393d2b9c676Sfw157321 /* wake up the tree_builder thread, tell it to exit */
394d2b9c676Sfw157321 (void) mutex_lock(&rebuild_tree_lock);
395d2b9c676Sfw157321 rebuild_tree = B_TRUE;
396d2b9c676Sfw157321 tree_builder_thr_exit = B_TRUE;
397dc6ca969Sfw157321 (void) cond_signal(&rebuild_tree_cv);
398d2b9c676Sfw157321 (void) mutex_unlock(&rebuild_tree_lock);
399d2b9c676Sfw157321
400*34f1a571SMichael Bergknoff /* send SIGUSR1 to get tree_builder out of a blocked system call */
401*34f1a571SMichael Bergknoff (void) thr_kill(tree_builder_thr_id, SIGUSR1);
402*34f1a571SMichael Bergknoff
403d2b9c676Sfw157321 /* reap the thread */
404d2b9c676Sfw157321 (void) thr_join(tree_builder_thr_id, NULL, NULL);
405d2b9c676Sfw157321
406d2b9c676Sfw157321 /* close the channel */
407d2b9c676Sfw157321 if (hdl != NULL) {
408d2b9c676Sfw157321 snmp_fini(hdl);
409d2b9c676Sfw157321 hdl = NULL;
410d2b9c676Sfw157321 }
411d2b9c676Sfw157321
412d2b9c676Sfw157321 /* finish cleanup... */
4130d63ce2bSvenki (void) rwlock_destroy(&stale_tree_rwlp);
4140d63ce2bSvenki (void) cond_destroy(&rebuild_tree_cv);
4150d63ce2bSvenki (void) mutex_destroy(&rebuild_tree_lock);
4160d63ce2bSvenki }
4170d63ce2bSvenki
4180d63ce2bSvenki /*ARGSUSED*/
419*34f1a571SMichael Bergknoff static void
usr1_handler(int sig,siginfo_t * siginfo,void * sigctx)420*34f1a571SMichael Bergknoff usr1_handler(int sig, siginfo_t *siginfo, void *sigctx)
421*34f1a571SMichael Bergknoff {
422*34f1a571SMichael Bergknoff /*
423*34f1a571SMichael Bergknoff * Nothing to do here.
424*34f1a571SMichael Bergknoff * The act of catching the signal causes any cond_wait() or blocked
425*34f1a571SMichael Bergknoff * system call to return EINTR. This is used to trigger early exit from
426*34f1a571SMichael Bergknoff * the tree builder thread which may be blocked in snmp_init. More work
427*34f1a571SMichael Bergknoff * would be required to allow early exit if the tree builder thread is
428*34f1a571SMichael Bergknoff * already in its main processing loop and not blocked in cond_wait.
429*34f1a571SMichael Bergknoff */
430*34f1a571SMichael Bergknoff }
431*34f1a571SMichael Bergknoff
432*34f1a571SMichael Bergknoff /*ARGSUSED*/
4330d63ce2bSvenki static void *
tree_builder(void * arg)4340d63ce2bSvenki tree_builder(void *arg)
4350d63ce2bSvenki {
4360d63ce2bSvenki int ret, rv;
4370d63ce2bSvenki picl_nodehdl_t root_node;
4380d63ce2bSvenki picl_nodehdl_t physplat_root;
4390d63ce2bSvenki picl_nodehdl_t old_physplat_root;
440*34f1a571SMichael Bergknoff struct sigaction act;
441*34f1a571SMichael Bergknoff
442*34f1a571SMichael Bergknoff /*
443*34f1a571SMichael Bergknoff * catch SIGUSR1 to allow early exit from snmp_init which may block
444*34f1a571SMichael Bergknoff * indefinitely in a guest domain.
445*34f1a571SMichael Bergknoff */
446*34f1a571SMichael Bergknoff act.sa_sigaction = usr1_handler;
447*34f1a571SMichael Bergknoff (void) sigemptyset(&act.sa_mask);
448*34f1a571SMichael Bergknoff act.sa_flags = 0;
449*34f1a571SMichael Bergknoff if (sigaction(SIGUSR1, &act, NULL) == -1) {
450*34f1a571SMichael Bergknoff syslog(LOG_ERR, SIGACT_FAILED, strsignal(SIGUSR1),
451*34f1a571SMichael Bergknoff strerror(errno));
452*34f1a571SMichael Bergknoff }
4530d63ce2bSvenki
4540d63ce2bSvenki /*
4550d63ce2bSvenki * Initialize SNMP service
4560d63ce2bSvenki */
4570d63ce2bSvenki LOGPRINTF("Initializing SNMP service.\n");
4580d63ce2bSvenki if ((hdl = snmp_init()) == NULL) {
4590d63ce2bSvenki log_msg(LOG_ERR, SNMPP_CANT_INIT);
4600d63ce2bSvenki return ((void *)-1);
4610d63ce2bSvenki }
4620d63ce2bSvenki
4630d63ce2bSvenki /*
4640d63ce2bSvenki * Register OID groupings for BULKGET optimizations
4650d63ce2bSvenki */
4660d63ce2bSvenki LOGPRINTF("Registering OID groups.\n");
4670d63ce2bSvenki register_group(group1, 0);
4680d63ce2bSvenki register_group(group2, 0);
4691c60fca8Sfw157321 register_group(group3, 0);
4701c60fca8Sfw157321 register_group(group4, 0);
4710d63ce2bSvenki register_group(volgroup1, 1);
4720d63ce2bSvenki register_group(volgroup2, 1);
4731c60fca8Sfw157321 register_group(volgroup3, 1);
4741c60fca8Sfw157321 register_group(volgroup4, 1);
4751c60fca8Sfw157321 register_group(volgroup5, 1);
4760d63ce2bSvenki
4770d63ce2bSvenki (void) mutex_lock(&rebuild_tree_lock);
4780d63ce2bSvenki
4790d63ce2bSvenki for (;;) {
4800d63ce2bSvenki LOGPRINTF("tree_builder: check whether to rebuild subtree\n");
4810d63ce2bSvenki while (rebuild_tree == B_FALSE)
4820d63ce2bSvenki (void) cond_wait(&rebuild_tree_cv, &rebuild_tree_lock);
4830d63ce2bSvenki
4840d63ce2bSvenki LOGPRINTF("tree_builder: woke up\n");
4850d63ce2bSvenki
486d2b9c676Sfw157321 if (tree_builder_thr_exit == B_TRUE) {
487d2b9c676Sfw157321 (void) mutex_unlock(&rebuild_tree_lock);
488d2b9c676Sfw157321 LOGPRINTF("tree_builder: time to exit\n");
489d2b9c676Sfw157321 return (NULL);
490d2b9c676Sfw157321 }
491d2b9c676Sfw157321
4920d63ce2bSvenki old_physplat_root = NULL;
4930d63ce2bSvenki physplat_root = NULL;
4940d63ce2bSvenki
4950d63ce2bSvenki LOGPRINTF("tree_builder: getting root node\n");
4960d63ce2bSvenki if ((ret = ptree_get_root(&root_node)) != PICL_SUCCESS) {
497d2b9c676Sfw157321 (void) mutex_unlock(&rebuild_tree_lock);
4980d63ce2bSvenki log_msg(LOG_ERR, SNMPP_NO_ROOT, ret);
4990d63ce2bSvenki return ((void *)-2);
5000d63ce2bSvenki }
5010d63ce2bSvenki
5020d63ce2bSvenki LOGPRINTF("tree_builder: getting existing physplat node\n");
5030d63ce2bSvenki rv = ptree_find_node(root_node, PICL_PROP_NAME,
5040d63ce2bSvenki PICL_PTYPE_CHARSTRING, PICL_NODE_PHYSPLAT,
5050d63ce2bSvenki sizeof (PICL_NODE_PHYSPLAT), &old_physplat_root);
5060d63ce2bSvenki
5070d63ce2bSvenki LOGPRINTF("tree_builder: building physical-platform\n");
5080d63ce2bSvenki if ((ret = build_physplat(&physplat_root)) < 0) {
509d2b9c676Sfw157321 (void) mutex_unlock(&rebuild_tree_lock);
5100d63ce2bSvenki log_msg(LOG_ERR, SNMPP_CANT_CREATE_PHYSPLAT, ret);
511817697f4SKelly Moyer cache_refresher_fini();
5120d63ce2bSvenki snmp_fini(hdl);
513d2b9c676Sfw157321 hdl = NULL;
5140d63ce2bSvenki return ((void *)-3);
5150d63ce2bSvenki }
5160d63ce2bSvenki
5170d63ce2bSvenki if (rv == PICL_SUCCESS && old_physplat_root != NULL) {
5180d63ce2bSvenki LOGPRINTF("tree_builder: destroying existing nodes\n");
5190d63ce2bSvenki ptree_delete_node(old_physplat_root);
5200d63ce2bSvenki ptree_destroy_node(old_physplat_root);
5210d63ce2bSvenki }
5220d63ce2bSvenki
5230d63ce2bSvenki LOGPRINTF("tree_builder: attaching new subtree\n");
5240d63ce2bSvenki if ((ret = ptree_add_node(root_node, physplat_root)) < 0) {
525d2b9c676Sfw157321 (void) mutex_unlock(&rebuild_tree_lock);
5260d63ce2bSvenki free_resources(physplat_root);
5270d63ce2bSvenki log_msg(LOG_ERR, SNMPP_CANT_CREATE_PHYSPLAT, ret);
528817697f4SKelly Moyer cache_refresher_fini();
5290d63ce2bSvenki snmp_fini(hdl);
530d2b9c676Sfw157321 hdl = NULL;
5310d63ce2bSvenki return ((void *)-4);
5320d63ce2bSvenki }
5330d63ce2bSvenki
5340d63ce2bSvenki LOGPRINTF("tree_builder: setting stale_tree to FALSE\n");
5350d63ce2bSvenki (void) rw_wrlock(&stale_tree_rwlp);
5360d63ce2bSvenki stale_tree = B_FALSE;
5370d63ce2bSvenki (void) rw_unlock(&stale_tree_rwlp);
5380d63ce2bSvenki
5390d63ce2bSvenki LOGPRINTF("tree_builder: setting rebuild_tree to FALSE\n");
5400d63ce2bSvenki rebuild_tree = B_FALSE;
5410d63ce2bSvenki }
5420d63ce2bSvenki
5430d63ce2bSvenki /*NOTREACHED*/
5440d63ce2bSvenki return (NULL);
5450d63ce2bSvenki }
5460d63ce2bSvenki
5470d63ce2bSvenki static int
build_physplat(picl_nodehdl_t * subtree_rootp)5480d63ce2bSvenki build_physplat(picl_nodehdl_t *subtree_rootp)
5490d63ce2bSvenki {
5500d63ce2bSvenki int change_time1;
5510d63ce2bSvenki int row, nxtrow;
5520d63ce2bSvenki int clr_linkreset = 0;
5530d63ce2bSvenki int ret = 0;
5540d63ce2bSvenki int snmp_syserr = 0;
5550d63ce2bSvenki
5560d63ce2bSvenki retry:
5570d63ce2bSvenki (void) snmp_reinit(hdl, clr_linkreset);
5580d63ce2bSvenki clr_linkreset = 0;
5590d63ce2bSvenki
5600d63ce2bSvenki /*
5610d63ce2bSvenki * Record LastChangeTime before we start building the tree
5620d63ce2bSvenki */
5630d63ce2bSvenki ret = snmp_get_int(hdl, OID_entLastChangeTime, 0,
5640d63ce2bSvenki &change_time1, &snmp_syserr);
5650d63ce2bSvenki if (ret < 0) {
5660d63ce2bSvenki if (snmp_syserr == ECANCELED) {
567806db1d7Sfw157321 LOGPRINTF(SNMPP_LINK_RESET);
5680d63ce2bSvenki clr_linkreset = 1;
5690d63ce2bSvenki goto retry;
5701c60fca8Sfw157321 }
5711c60fca8Sfw157321 log_msg(LOG_WARNING, SNMPP_CANT_FETCH_OBJECT_VAL,
5721c60fca8Sfw157321 snmp_syserr ? snmp_syserr : ret, OID_entLastChangeTime, 0);
5730d63ce2bSvenki }
5740d63ce2bSvenki
5750d63ce2bSvenki /*
5760d63ce2bSvenki * Create the physical-platform node
5770d63ce2bSvenki */
5780d63ce2bSvenki ret = ptree_create_node(PICL_NODE_PHYSPLAT, PICL_CLASS_PICL,
5790d63ce2bSvenki subtree_rootp);
5800d63ce2bSvenki if (ret != PICL_SUCCESS)
5810d63ce2bSvenki return (-1);
5820d63ce2bSvenki
5830d63ce2bSvenki /*
5840d63ce2bSvenki * Scan entPhysicalTable and build the "physical-platform" subtree
5850d63ce2bSvenki */
5860d63ce2bSvenki ret = 0;
5870d63ce2bSvenki for (row = -1; ret == 0; row = nxtrow) {
5880d63ce2bSvenki ret = snmp_get_nextrow(hdl, OID_entPhysicalDescr,
5890d63ce2bSvenki row, &nxtrow, &snmp_syserr);
590a1c54725Sfw157321 if (ret == 0)
5910d63ce2bSvenki (void) make_node(*subtree_rootp, nxtrow, &snmp_syserr);
592a1c54725Sfw157321 switch (snmp_syserr) {
593a1c54725Sfw157321 case ECANCELED:
5940d63ce2bSvenki /*
5950d63ce2bSvenki * If we get this error, a link reset must've
5960d63ce2bSvenki * happened and we need to throw away everything
5970d63ce2bSvenki * we have now and rebuild the tree again.
5980d63ce2bSvenki */
5990d63ce2bSvenki log_msg(LOG_WARNING, SNMPP_LINK_RESET);
6000d63ce2bSvenki free_resources(*subtree_rootp);
6010d63ce2bSvenki clr_linkreset = 1;
6020d63ce2bSvenki goto retry;
603a1c54725Sfw157321 /*NOTREACHED*/
604a1c54725Sfw157321 break;
605a1c54725Sfw157321 case ENOSPC: /* end of MIB */
606a1c54725Sfw157321 LOGPRINTF("build_physplat: end of MIB\n");
607a1c54725Sfw157321 break;
608a1c54725Sfw157321 case ENOENT: /* end of table */
609a1c54725Sfw157321 LOGPRINTF("build_physplat: end of table\n");
610a1c54725Sfw157321 break;
611a1c54725Sfw157321 default:
612a1c54725Sfw157321 /*
613a1c54725Sfw157321 * make_node() will print messages so don't
614a1c54725Sfw157321 * repeat that exercise here.
615a1c54725Sfw157321 */
616a1c54725Sfw157321 if (ret == -1) {
617a1c54725Sfw157321 log_msg(LOG_WARNING,
618a1c54725Sfw157321 SNMPP_CANT_FETCH_OBJECT_VAL,
6191c60fca8Sfw157321 snmp_syserr ? snmp_syserr : ret,
6201c60fca8Sfw157321 OID_entPhysicalDescr, row);
6210d63ce2bSvenki }
622a1c54725Sfw157321 }
623a1c54725Sfw157321 }
6240d63ce2bSvenki
6250d63ce2bSvenki /*
6260d63ce2bSvenki * Record LastChangeTime after we're done building the tree
6270d63ce2bSvenki */
6280d63ce2bSvenki ret = snmp_get_int(hdl, OID_entLastChangeTime, 0,
6290d63ce2bSvenki &change_time, &snmp_syserr);
6300d63ce2bSvenki if (ret < 0) {
6310d63ce2bSvenki if (snmp_syserr == ECANCELED) {
6320d63ce2bSvenki log_msg(LOG_WARNING, SNMPP_LINK_RESET);
6330d63ce2bSvenki free_resources(*subtree_rootp);
6340d63ce2bSvenki clr_linkreset = 1;
6350d63ce2bSvenki goto retry;
6360d63ce2bSvenki } else
6371c60fca8Sfw157321 log_msg(LOG_WARNING, SNMPP_CANT_FETCH_OBJECT_VAL,
6381c60fca8Sfw157321 snmp_syserr ? snmp_syserr : ret,
6391c60fca8Sfw157321 OID_entLastChangeTime, row);
6400d63ce2bSvenki }
6410d63ce2bSvenki
6420d63ce2bSvenki /*
6430d63ce2bSvenki * If they don't match, some hotplugging must've happened,
6440d63ce2bSvenki * free resources we've created and still holding, then go
6450d63ce2bSvenki * back and retry
6460d63ce2bSvenki */
6470d63ce2bSvenki if (change_time != change_time1) {
6480d63ce2bSvenki LOGPRINTF("build_physplat: entLastChangeTime has changed!\n");
6490d63ce2bSvenki free_resources(*subtree_rootp);
6500d63ce2bSvenki change_time1 = change_time;
6510d63ce2bSvenki goto retry;
6520d63ce2bSvenki }
6530d63ce2bSvenki
6540d63ce2bSvenki /*
6550d63ce2bSvenki * The physplat_nodes table is no longer needed, free it
6560d63ce2bSvenki */
6570d63ce2bSvenki if (physplat_nodes) {
6580d63ce2bSvenki free(physplat_nodes);
6590d63ce2bSvenki physplat_nodes = NULL;
6600d63ce2bSvenki n_physplat_nodes = 0;
6610d63ce2bSvenki }
6620d63ce2bSvenki
6630d63ce2bSvenki return (0);
6640d63ce2bSvenki }
6650d63ce2bSvenki
6660d63ce2bSvenki /*
6670d63ce2bSvenki * Destroy all resources that were created during the building
6680d63ce2bSvenki * of the subtree
6690d63ce2bSvenki */
6700d63ce2bSvenki static void
free_resources(picl_nodehdl_t subtree_root)6710d63ce2bSvenki free_resources(picl_nodehdl_t subtree_root)
6720d63ce2bSvenki {
6730d63ce2bSvenki if (physplat_nodes) {
6740d63ce2bSvenki free(physplat_nodes);
6750d63ce2bSvenki physplat_nodes = NULL;
6760d63ce2bSvenki n_physplat_nodes = 0;
6770d63ce2bSvenki }
6780d63ce2bSvenki
6790d63ce2bSvenki if (subtree_root) {
6800d63ce2bSvenki (void) ptree_delete_node(subtree_root);
6810d63ce2bSvenki (void) ptree_destroy_node(subtree_root);
6820d63ce2bSvenki }
6830d63ce2bSvenki
6840d63ce2bSvenki if (vol_props) {
6850d63ce2bSvenki free(vol_props);
6865413ab1bSMichael Bergknoff vol_props = NULL;
6870d63ce2bSvenki n_vol_props = 0;
6880d63ce2bSvenki volprop_ndx = 0;
6890d63ce2bSvenki }
6900d63ce2bSvenki }
6910d63ce2bSvenki
6920d63ce2bSvenki static picl_nodehdl_t
make_node(picl_nodehdl_t subtree_root,int row,int * snmp_syserr_p)6930d63ce2bSvenki make_node(picl_nodehdl_t subtree_root, int row, int *snmp_syserr_p)
6940d63ce2bSvenki {
6950d63ce2bSvenki picl_nodehdl_t nodeh, parenth;
6960d63ce2bSvenki picl_prophdl_t proph;
6970d63ce2bSvenki char *phys_name, *node_name;
6980d63ce2bSvenki int parent_row;
6990d63ce2bSvenki int ent_physclass, sunplat_physclass;
7000d63ce2bSvenki int sensor_class, sensor_type;
7010d63ce2bSvenki int alarm_type;
7020d63ce2bSvenki int ps_class;
7030d63ce2bSvenki int ret;
7040d63ce2bSvenki
7050d63ce2bSvenki /*
7060d63ce2bSvenki * If we've already created this picl node, just return it
7070d63ce2bSvenki */
7080d63ce2bSvenki if ((nodeh = lookup_nodeh(row)) != NULL)
7090d63ce2bSvenki return (nodeh);
7100d63ce2bSvenki
7110d63ce2bSvenki /*
7120d63ce2bSvenki * If we are creating it only now, make sure we have the parent
7130d63ce2bSvenki * created first; if there's no parent, then parent it to the
7140d63ce2bSvenki * subtree's root node
7150d63ce2bSvenki */
7160d63ce2bSvenki ret = snmp_get_int(hdl, OID_entPhysicalContainedIn, row,
7170d63ce2bSvenki &parent_row, snmp_syserr_p);
7180d63ce2bSvenki CHECK_LINKRESET(snmp_syserr_p, NULL)
7190d63ce2bSvenki if (ret < 0 || parent_row <= 0)
7200d63ce2bSvenki parenth = subtree_root;
7210d63ce2bSvenki else {
7220d63ce2bSvenki parenth = make_node(subtree_root, parent_row, snmp_syserr_p);
7230d63ce2bSvenki CHECK_LINKRESET(snmp_syserr_p, NULL)
7240d63ce2bSvenki if (parenth == NULL)
7250d63ce2bSvenki parenth = subtree_root;
7260d63ce2bSvenki }
7270d63ce2bSvenki
7280d63ce2bSvenki /*
7290d63ce2bSvenki * Figure out the physical-platform node name from entPhysicalName;
7300d63ce2bSvenki * all rows in the MIB that have a valid entPhysicalIndex should
7310d63ce2bSvenki * have a physical name.
7320d63ce2bSvenki */
7330d63ce2bSvenki ret = snmp_get_str(hdl, OID_entPhysicalName, row,
7340d63ce2bSvenki &phys_name, snmp_syserr_p);
7350d63ce2bSvenki CHECK_LINKRESET(snmp_syserr_p, NULL)
7360d63ce2bSvenki if (ret < 0 || phys_name == NULL) {
7370d63ce2bSvenki log_msg(LOG_WARNING, SNMPP_NO_ENTPHYSNAME, row);
7380d63ce2bSvenki return (NULL);
7390d63ce2bSvenki }
7400d63ce2bSvenki
7410d63ce2bSvenki node_name = basename(phys_name);
7420d63ce2bSvenki
7430d63ce2bSvenki ret = snmp_get_int(hdl, OID_entPhysicalClass, row,
7440d63ce2bSvenki &ent_physclass, snmp_syserr_p);
7450d63ce2bSvenki CHECK_LINKRESET(snmp_syserr_p, NULL)
7460d63ce2bSvenki if (ret < 0) {
7471c60fca8Sfw157321 log_msg(LOG_WARNING, SNMPP_CANT_FETCH_OBJECT_VAL,
7481c60fca8Sfw157321 *snmp_syserr_p ? *snmp_syserr_p : ret,
7491c60fca8Sfw157321 OID_entPhysicalClass, row);
7500d63ce2bSvenki free(phys_name);
7510d63ce2bSvenki return (NULL);
7520d63ce2bSvenki }
7530d63ce2bSvenki
7540d63ce2bSvenki switch (ent_physclass) {
7550d63ce2bSvenki case SPC_OTHER:
7560d63ce2bSvenki ret = snmp_get_int(hdl, OID_sunPlatPhysicalClass, row,
7570d63ce2bSvenki &sunplat_physclass, snmp_syserr_p);
7580d63ce2bSvenki CHECK_LINKRESET(snmp_syserr_p, NULL)
7590d63ce2bSvenki if (ret < 0) {
7601c60fca8Sfw157321 log_msg(LOG_WARNING, SNMPP_CANT_FETCH_OBJECT_VAL,
7611c60fca8Sfw157321 *snmp_syserr_p ? *snmp_syserr_p : ret,
7621c60fca8Sfw157321 OID_sunPlatPhysicalClass, row);
7630d63ce2bSvenki free(phys_name);
7640d63ce2bSvenki return (NULL);
7650d63ce2bSvenki }
7660d63ce2bSvenki
7670d63ce2bSvenki if (sunplat_physclass == SSPC_ALARM) {
7680d63ce2bSvenki ret = snmp_get_int(hdl, OID_sunPlatAlarmType,
7690d63ce2bSvenki row, &alarm_type, snmp_syserr_p);
7700d63ce2bSvenki CHECK_LINKRESET(snmp_syserr_p, NULL)
7710d63ce2bSvenki if (ret < 0) {
7720d63ce2bSvenki log_msg(LOG_WARNING,
7731c60fca8Sfw157321 SNMPP_CANT_FETCH_OBJECT_VAL,
7741c60fca8Sfw157321 *snmp_syserr_p ? *snmp_syserr_p : ret,
7751c60fca8Sfw157321 OID_sunPlatAlarmType, row);
7760d63ce2bSvenki free(phys_name);
7770d63ce2bSvenki return (NULL);
7780d63ce2bSvenki }
7790d63ce2bSvenki
7800d63ce2bSvenki if (alarm_type == SSAT_VISIBLE) {
7810d63ce2bSvenki ADD_NODE(PICL_CLASS_LED)
7820d63ce2bSvenki } else {
7830d63ce2bSvenki ADD_NODE(PICL_CLASS_ALARM)
7840d63ce2bSvenki }
7850d63ce2bSvenki
7860d63ce2bSvenki add_prop(nodeh, &proph, node_name, row, PP_STATE,
7870d63ce2bSvenki snmp_syserr_p);
7880d63ce2bSvenki CHECK_LINKRESET(snmp_syserr_p, NULL)
7890d63ce2bSvenki } else {
7900d63ce2bSvenki ADD_NODE(PICL_CLASS_OTHER)
7910d63ce2bSvenki }
7920d63ce2bSvenki
7930d63ce2bSvenki add_prop(nodeh, &proph, node_name, row, PP_OPSTATUS,
7940d63ce2bSvenki snmp_syserr_p);
7950d63ce2bSvenki CHECK_LINKRESET(snmp_syserr_p, NULL)
7960d63ce2bSvenki break;
7970d63ce2bSvenki
7980d63ce2bSvenki case SPC_UNKNOWN:
7990d63ce2bSvenki ADD_NODE(PICL_CLASS_UNKNOWN)
8000d63ce2bSvenki break;
8010d63ce2bSvenki
8020d63ce2bSvenki case SPC_CHASSIS:
8030d63ce2bSvenki ADD_NODE(PICL_CLASS_CHASSIS)
8040d63ce2bSvenki add_prop(nodeh, &proph, node_name, row, PP_OPSTATUS,
8050d63ce2bSvenki snmp_syserr_p);
8060d63ce2bSvenki CHECK_LINKRESET(snmp_syserr_p, NULL)
8070d63ce2bSvenki break;
8080d63ce2bSvenki
8090d63ce2bSvenki case SPC_BACKPLANE:
8100d63ce2bSvenki ADD_NODE(PICL_CLASS_BACKPLANE)
8110d63ce2bSvenki add_prop(nodeh, &proph, node_name, row, PP_OPSTATUS,
8120d63ce2bSvenki snmp_syserr_p);
8130d63ce2bSvenki CHECK_LINKRESET(snmp_syserr_p, NULL)
8140d63ce2bSvenki break;
8150d63ce2bSvenki
8160d63ce2bSvenki case SPC_CONTAINER:
8170d63ce2bSvenki ADD_NODE(PICL_CLASS_CONTAINER)
8180d63ce2bSvenki
8190d63ce2bSvenki add_prop(nodeh, &proph, node_name, row, PP_OPSTATUS,
8200d63ce2bSvenki snmp_syserr_p);
8210d63ce2bSvenki CHECK_LINKRESET(snmp_syserr_p, NULL)
8220d63ce2bSvenki
8230d63ce2bSvenki add_prop(nodeh, &proph, node_name, row, PP_SLOT_TYPE,
8240d63ce2bSvenki snmp_syserr_p);
8250d63ce2bSvenki CHECK_LINKRESET(snmp_syserr_p, NULL)
8260d63ce2bSvenki break;
8270d63ce2bSvenki
8280d63ce2bSvenki case SPC_POWERSUPPLY:
8290d63ce2bSvenki ret = snmp_get_int(hdl, OID_sunPlatPowerSupplyClass,
8300d63ce2bSvenki row, &ps_class, snmp_syserr_p);
8310d63ce2bSvenki CHECK_LINKRESET(snmp_syserr_p, NULL)
8320d63ce2bSvenki if (ret < 0) {
8331c60fca8Sfw157321 log_msg(LOG_WARNING, SNMPP_CANT_FETCH_OBJECT_VAL,
8341c60fca8Sfw157321 *snmp_syserr_p ? *snmp_syserr_p : ret,
8351c60fca8Sfw157321 OID_sunPlatPowerSupplyClass, row);
8360d63ce2bSvenki free(phys_name);
8370d63ce2bSvenki return (NULL);
8380d63ce2bSvenki }
8390d63ce2bSvenki
8400d63ce2bSvenki if (ps_class == SSPSC_BATTERY) {
8410d63ce2bSvenki ADD_NODE(PICL_CLASS_BATTERY)
8420d63ce2bSvenki add_prop(nodeh, &proph, node_name, row,
8430d63ce2bSvenki PP_BATT_STATUS, snmp_syserr_p);
8440d63ce2bSvenki CHECK_LINKRESET(snmp_syserr_p, NULL)
8450d63ce2bSvenki } else {
8460d63ce2bSvenki ADD_NODE(PICL_CLASS_POWERSUPPLY)
8470d63ce2bSvenki }
8480d63ce2bSvenki add_prop(nodeh, &proph, node_name, row, PP_OPSTATUS,
8490d63ce2bSvenki snmp_syserr_p);
8500d63ce2bSvenki CHECK_LINKRESET(snmp_syserr_p, NULL)
8510d63ce2bSvenki break;
8520d63ce2bSvenki
8530d63ce2bSvenki case SPC_FAN:
8540d63ce2bSvenki ADD_NODE(PICL_CLASS_FAN)
8550d63ce2bSvenki add_prop(nodeh, &proph, node_name, row, PP_OPSTATUS,
8560d63ce2bSvenki snmp_syserr_p);
8570d63ce2bSvenki CHECK_LINKRESET(snmp_syserr_p, NULL)
8580d63ce2bSvenki break;
8590d63ce2bSvenki
8600d63ce2bSvenki case SPC_SENSOR:
8610d63ce2bSvenki ret = snmp_get_int(hdl, OID_sunPlatSensorClass,
8620d63ce2bSvenki row, &sensor_class, snmp_syserr_p);
8630d63ce2bSvenki CHECK_LINKRESET(snmp_syserr_p, NULL)
8640d63ce2bSvenki if (ret < 0) {
8651c60fca8Sfw157321 log_msg(LOG_WARNING, SNMPP_CANT_FETCH_OBJECT_VAL,
8661c60fca8Sfw157321 *snmp_syserr_p ? *snmp_syserr_p : ret,
8671c60fca8Sfw157321 OID_sunPlatSensorClass, row);
8680d63ce2bSvenki free(phys_name);
8690d63ce2bSvenki return (NULL);
8700d63ce2bSvenki }
8710d63ce2bSvenki
8720d63ce2bSvenki ret = snmp_get_int(hdl, OID_sunPlatSensorType,
8730d63ce2bSvenki row, &sensor_type, snmp_syserr_p);
8740d63ce2bSvenki CHECK_LINKRESET(snmp_syserr_p, NULL)
8750d63ce2bSvenki if (ret < 0) {
8761c60fca8Sfw157321 log_msg(LOG_WARNING, SNMPP_CANT_FETCH_OBJECT_VAL,
8771c60fca8Sfw157321 *snmp_syserr_p ? *snmp_syserr_p : ret,
8781c60fca8Sfw157321 OID_sunPlatSensorType, row);
8790d63ce2bSvenki free(phys_name);
8800d63ce2bSvenki return (NULL);
8810d63ce2bSvenki }
8820d63ce2bSvenki
8830d63ce2bSvenki if (sensor_class == SSSC_NUMERIC) {
8840d63ce2bSvenki if (sensor_type == SSST_TEMPERATURE) {
8850d63ce2bSvenki ADD_NODE(PICL_CLASS_TEMPERATURE_SENSOR)
8860d63ce2bSvenki add_prop(nodeh, &proph, node_name, row,
8870d63ce2bSvenki PP_TEMPERATURE, snmp_syserr_p);
8880d63ce2bSvenki } else if (sensor_type == SSST_VOLTAGE) {
8890d63ce2bSvenki ADD_NODE(PICL_CLASS_VOLTAGE_SENSOR)
8900d63ce2bSvenki add_prop(nodeh, &proph, node_name, row,
8910d63ce2bSvenki PP_VOLTAGE, snmp_syserr_p);
8920d63ce2bSvenki } else if (sensor_type == SSST_CURRENT) {
8930d63ce2bSvenki ADD_NODE(PICL_CLASS_CURRENT_SENSOR)
8940d63ce2bSvenki add_prop(nodeh, &proph, node_name, row,
8950d63ce2bSvenki PP_CURRENT, snmp_syserr_p);
8960d63ce2bSvenki } else if (sensor_type == SSST_TACHOMETER) {
8970d63ce2bSvenki ADD_NODE(PICL_CLASS_RPM_SENSOR)
8980d63ce2bSvenki add_prop(nodeh, &proph, node_name, row,
8990d63ce2bSvenki PP_SPEED, snmp_syserr_p);
9000d63ce2bSvenki } else {
9010d63ce2bSvenki ADD_NODE(PICL_CLASS_SENSOR)
9020d63ce2bSvenki add_prop(nodeh, &proph, node_name, row,
9030d63ce2bSvenki PP_SENSOR_VALUE, snmp_syserr_p);
9040d63ce2bSvenki }
9050d63ce2bSvenki CHECK_LINKRESET(snmp_syserr_p, NULL)
9060d63ce2bSvenki
9070d63ce2bSvenki add_prop(nodeh, &proph, node_name, row,
9080d63ce2bSvenki PP_OPSTATUS, snmp_syserr_p);
9090d63ce2bSvenki CHECK_LINKRESET(snmp_syserr_p, NULL)
9100d63ce2bSvenki
9110d63ce2bSvenki add_prop(nodeh, &proph, node_name, row,
9120d63ce2bSvenki PP_BASE_UNITS, snmp_syserr_p);
9130d63ce2bSvenki CHECK_LINKRESET(snmp_syserr_p, NULL)
9140d63ce2bSvenki
9150d63ce2bSvenki add_prop(nodeh, &proph, node_name, row,
9160d63ce2bSvenki PP_EXPONENT, snmp_syserr_p);
9170d63ce2bSvenki CHECK_LINKRESET(snmp_syserr_p, NULL)
9180d63ce2bSvenki
9190d63ce2bSvenki add_prop(nodeh, &proph, node_name, row,
9200d63ce2bSvenki PP_RATE_UNITS, snmp_syserr_p);
9210d63ce2bSvenki CHECK_LINKRESET(snmp_syserr_p, NULL)
9220d63ce2bSvenki
9230d63ce2bSvenki add_thresholds(nodeh, row, snmp_syserr_p);
9240d63ce2bSvenki CHECK_LINKRESET(snmp_syserr_p, NULL)
9250d63ce2bSvenki
9260d63ce2bSvenki } else if (sensor_class == SSSC_BINARY) {
9270d63ce2bSvenki if (sensor_type == SSST_TEMPERATURE) {
9280d63ce2bSvenki ADD_NODE(PICL_CLASS_TEMPERATURE_INDICATOR)
9290d63ce2bSvenki } else if (sensor_type == SSST_VOLTAGE) {
9300d63ce2bSvenki ADD_NODE(PICL_CLASS_VOLTAGE_INDICATOR)
9310d63ce2bSvenki } else if (sensor_type == SSST_CURRENT) {
9320d63ce2bSvenki ADD_NODE(PICL_CLASS_CURRENT_INDICATOR)
9330d63ce2bSvenki } else if (sensor_type == SSST_TACHOMETER) {
9340d63ce2bSvenki ADD_NODE(PICL_CLASS_RPM_INDICATOR)
9350d63ce2bSvenki } else if (sensor_type == SSST_PRESENCE) {
9360d63ce2bSvenki ADD_NODE(PICL_CLASS_PRESENCE_INDICATOR)
9370d63ce2bSvenki } else {
9380d63ce2bSvenki ADD_NODE(PICL_CLASS_INDICATOR)
9390d63ce2bSvenki }
9400d63ce2bSvenki
9410d63ce2bSvenki add_prop(nodeh, &proph, node_name, row, PP_OPSTATUS,
9420d63ce2bSvenki snmp_syserr_p);
9430d63ce2bSvenki CHECK_LINKRESET(snmp_syserr_p, NULL)
9440d63ce2bSvenki
9450d63ce2bSvenki add_prop(nodeh, &proph, node_name, row, PP_CONDITION,
9460d63ce2bSvenki snmp_syserr_p);
9470d63ce2bSvenki CHECK_LINKRESET(snmp_syserr_p, NULL)
9480d63ce2bSvenki
9490d63ce2bSvenki add_prop(nodeh, &proph, node_name, row, PP_EXPECTED,
9500d63ce2bSvenki snmp_syserr_p);
9510d63ce2bSvenki CHECK_LINKRESET(snmp_syserr_p, NULL)
9520d63ce2bSvenki } else {
9530d63ce2bSvenki log_msg(LOG_ERR,
9540d63ce2bSvenki SNMPP_UNSUPP_SENSOR_CLASS, sensor_class, row);
9550d63ce2bSvenki return (NULL);
9560d63ce2bSvenki }
9570d63ce2bSvenki break;
9580d63ce2bSvenki
9590d63ce2bSvenki case SPC_MODULE:
9600d63ce2bSvenki ADD_NODE(PICL_CLASS_MODULE)
9610d63ce2bSvenki
9620d63ce2bSvenki add_prop(nodeh, &proph, node_name, row, PP_OPSTATUS,
9630d63ce2bSvenki snmp_syserr_p);
9640d63ce2bSvenki CHECK_LINKRESET(snmp_syserr_p, NULL)
9650d63ce2bSvenki
9660d63ce2bSvenki add_prop(nodeh, &proph, node_name, row, PP_REPLACEABLE,
9670d63ce2bSvenki snmp_syserr_p);
9680d63ce2bSvenki CHECK_LINKRESET(snmp_syserr_p, NULL)
9690d63ce2bSvenki
9700d63ce2bSvenki add_prop(nodeh, &proph, node_name, row, PP_HOTSWAPPABLE,
9710d63ce2bSvenki snmp_syserr_p);
9720d63ce2bSvenki CHECK_LINKRESET(snmp_syserr_p, NULL)
9730d63ce2bSvenki break;
9740d63ce2bSvenki
9750d63ce2bSvenki case SPC_PORT:
9760d63ce2bSvenki ADD_NODE(PICL_CLASS_PORT)
9770d63ce2bSvenki break;
9780d63ce2bSvenki
9790d63ce2bSvenki case SPC_STACK:
9800d63ce2bSvenki ADD_NODE(PICL_CLASS_STACK)
9810d63ce2bSvenki break;
9820d63ce2bSvenki
9830d63ce2bSvenki default:
9840d63ce2bSvenki log_msg(LOG_WARNING,
9850d63ce2bSvenki SNMPP_UNKNOWN_ENTPHYSCLASS, ent_physclass, row);
9860d63ce2bSvenki free(phys_name);
9870d63ce2bSvenki return (NULL);
9880d63ce2bSvenki }
9890d63ce2bSvenki
9900d63ce2bSvenki add_prop(nodeh, &proph, node_name, row, PP_DESCRIPTION, snmp_syserr_p);
9910d63ce2bSvenki CHECK_LINKRESET(snmp_syserr_p, NULL)
9920d63ce2bSvenki
9930d63ce2bSvenki add_prop(nodeh, &proph, node_name, row, PP_LABEL, snmp_syserr_p);
9940d63ce2bSvenki CHECK_LINKRESET(snmp_syserr_p, NULL)
9950d63ce2bSvenki
9960d63ce2bSvenki add_prop(nodeh, &proph, node_name, row, PP_HW_REVISION, snmp_syserr_p);
9970d63ce2bSvenki CHECK_LINKRESET(snmp_syserr_p, NULL)
9980d63ce2bSvenki
9990d63ce2bSvenki add_prop(nodeh, &proph, node_name, row, PP_FW_REVISION, snmp_syserr_p);
10000d63ce2bSvenki CHECK_LINKRESET(snmp_syserr_p, NULL)
10010d63ce2bSvenki
10020d63ce2bSvenki add_prop(nodeh, &proph, node_name, row, PP_SERIAL_NUM, snmp_syserr_p);
10030d63ce2bSvenki CHECK_LINKRESET(snmp_syserr_p, NULL)
10040d63ce2bSvenki
10050d63ce2bSvenki add_prop(nodeh, &proph, node_name, row, PP_MFG_NAME, snmp_syserr_p);
10060d63ce2bSvenki CHECK_LINKRESET(snmp_syserr_p, NULL)
10070d63ce2bSvenki
10080d63ce2bSvenki add_prop(nodeh, &proph, node_name, row, PP_MODEL_NAME, snmp_syserr_p);
10090d63ce2bSvenki CHECK_LINKRESET(snmp_syserr_p, NULL)
10100d63ce2bSvenki
10110d63ce2bSvenki add_prop(nodeh, &proph, node_name, row, PP_IS_FRU, snmp_syserr_p);
10120d63ce2bSvenki CHECK_LINKRESET(snmp_syserr_p, NULL)
10130d63ce2bSvenki
10140d63ce2bSvenki free(phys_name);
10150d63ce2bSvenki save_nodeh(nodeh, row);
10160d63ce2bSvenki
10170d63ce2bSvenki return (nodeh);
10180d63ce2bSvenki }
10190d63ce2bSvenki
10200d63ce2bSvenki /*
10210d63ce2bSvenki * Saves the node handle and the row id into physplat_nodes[]. If we're
10220d63ce2bSvenki * doing this in response to a hotplug event, we should've freed the
10230d63ce2bSvenki * old physplat_nodes before entering here to save the first node of the
10240d63ce2bSvenki * new physplat subtree.
10250d63ce2bSvenki */
10260d63ce2bSvenki static void
save_nodeh(picl_nodehdl_t nodeh,int row)10270d63ce2bSvenki save_nodeh(picl_nodehdl_t nodeh, int row)
10280d63ce2bSvenki {
10290d63ce2bSvenki size_t sz, count;
10300d63ce2bSvenki picl_nodehdl_t *p;
10310d63ce2bSvenki
10320d63ce2bSvenki if (row >= n_physplat_nodes) {
10330d63ce2bSvenki count = (((size_t)row >> NODE_BLOCK_SHIFT) + 1) *
10340d63ce2bSvenki N_ELEMS_IN_NODE_BLOCK;
10350d63ce2bSvenki sz = count * sizeof (picl_nodehdl_t);
10360d63ce2bSvenki
10370d63ce2bSvenki p = (picl_nodehdl_t *)calloc(count, sizeof (picl_nodehdl_t));
10380d63ce2bSvenki if (p == NULL) {
10390d63ce2bSvenki log_msg(LOG_ERR, SNMPP_NO_MEM, sz);
10400d63ce2bSvenki return;
10410d63ce2bSvenki }
10420d63ce2bSvenki
10430d63ce2bSvenki if (physplat_nodes) {
10440d63ce2bSvenki (void) memcpy((void *) p, (void *) physplat_nodes,
10450d63ce2bSvenki n_physplat_nodes * sizeof (picl_nodehdl_t));
10460d63ce2bSvenki free((void *) physplat_nodes);
10470d63ce2bSvenki }
10480d63ce2bSvenki
10490d63ce2bSvenki physplat_nodes = p;
10500d63ce2bSvenki n_physplat_nodes = count;
10510d63ce2bSvenki }
10520d63ce2bSvenki
10530d63ce2bSvenki physplat_nodes[row] = nodeh;
10540d63ce2bSvenki }
10550d63ce2bSvenki
10560d63ce2bSvenki static picl_nodehdl_t
lookup_nodeh(int row)10570d63ce2bSvenki lookup_nodeh(int row)
10580d63ce2bSvenki {
10590d63ce2bSvenki if (row >= n_physplat_nodes)
10600d63ce2bSvenki return (NULL);
10610d63ce2bSvenki
10620d63ce2bSvenki return (physplat_nodes[row]);
10630d63ce2bSvenki }
10640d63ce2bSvenki
10650d63ce2bSvenki /*
10660d63ce2bSvenki * We enter this routine only when we are building the physical-platform
10670d63ce2bSvenki * subtree, whether for the first time or in response to a hotplug event.
10680d63ce2bSvenki * If we're here for rebuilding the tree, we have already set stale_tree
10690d63ce2bSvenki * to be B_TRUE, so no one else would be accessing vol_props, n_vol_props
10700d63ce2bSvenki * or volprop_ndx. If we're here to build the tree for the first time,
10710d63ce2bSvenki * picld hasn't yet created doors and is running single-threaded, so no
10720d63ce2bSvenki * one else would be accessing them anyway.
10730d63ce2bSvenki */
10740d63ce2bSvenki static void
save_volprop(picl_prophdl_t prop,char * oidstr,int row,int proptype)10750d63ce2bSvenki save_volprop(picl_prophdl_t prop, char *oidstr, int row, int proptype)
10760d63ce2bSvenki {
10770d63ce2bSvenki vol_prophdl_t *p;
10780d63ce2bSvenki int count;
10790d63ce2bSvenki
10800d63ce2bSvenki if (volprop_ndx == n_vol_props) {
10810d63ce2bSvenki count = n_vol_props + N_ELEMS_IN_VOLPROP_BLOCK;
10820d63ce2bSvenki p = (vol_prophdl_t *)calloc(count, sizeof (vol_prophdl_t));
10830d63ce2bSvenki if (p == NULL) {
10840d63ce2bSvenki log_msg(LOG_ERR, SNMPP_NO_MEM,
10850d63ce2bSvenki count * sizeof (vol_prophdl_t));
10860d63ce2bSvenki return;
10870d63ce2bSvenki }
10880d63ce2bSvenki
10890d63ce2bSvenki if (vol_props) {
10900d63ce2bSvenki (void) memcpy((void *) p, (void *) vol_props,
10910d63ce2bSvenki n_vol_props * sizeof (vol_prophdl_t));
10920d63ce2bSvenki free((void *) vol_props);
10930d63ce2bSvenki }
10940d63ce2bSvenki
10950d63ce2bSvenki vol_props = p;
10960d63ce2bSvenki n_vol_props += N_ELEMS_IN_VOLPROP_BLOCK;
10970d63ce2bSvenki }
10980d63ce2bSvenki
10990d63ce2bSvenki vol_props[volprop_ndx].prop = prop;
11000d63ce2bSvenki vol_props[volprop_ndx].oidstr = oidstr;
11010d63ce2bSvenki vol_props[volprop_ndx].row = row;
11020d63ce2bSvenki vol_props[volprop_ndx].proptype = proptype;
11030d63ce2bSvenki
11040d63ce2bSvenki volprop_ndx++;
11050d63ce2bSvenki }
11060d63ce2bSvenki
11070d63ce2bSvenki static void
check_for_stale_data(boolean_t nocache)11081c60fca8Sfw157321 check_for_stale_data(boolean_t nocache)
11090d63ce2bSvenki {
11100d63ce2bSvenki int cur_change_time;
11110d63ce2bSvenki int ret;
11120d63ce2bSvenki int snmp_syserr;
11130d63ce2bSvenki
11140d63ce2bSvenki (void) rw_wrlock(&stale_tree_rwlp);
11150d63ce2bSvenki
11160d63ce2bSvenki /*
11170d63ce2bSvenki * Check if some other thread beat us to it
11180d63ce2bSvenki */
11190d63ce2bSvenki if (stale_tree == B_TRUE) {
11200d63ce2bSvenki (void) rw_unlock(&stale_tree_rwlp);
11210d63ce2bSvenki return;
11220d63ce2bSvenki }
11230d63ce2bSvenki
11240d63ce2bSvenki /*
11251c60fca8Sfw157321 * Cache OID_entLastChangeTime for up to 10 seconds before
11261c60fca8Sfw157321 * fetching it from ILOM again. This prevents us from fetching
11271c60fca8Sfw157321 * this value from ILOM when the we're filling or refreshing a
11281c60fca8Sfw157321 * whole bunch of items in the cache around the same time.
11291c60fca8Sfw157321 */
11301c60fca8Sfw157321 if (nocache == B_FALSE && time(NULL) - change_time_check <= 10) {
11311c60fca8Sfw157321 (void) rw_unlock(&stale_tree_rwlp);
11321c60fca8Sfw157321 return;
11331c60fca8Sfw157321 }
11341c60fca8Sfw157321
11351c60fca8Sfw157321 /*
11360d63ce2bSvenki * Check if mib data has changed (hotplug? link-reset?)
11370d63ce2bSvenki */
1138af71cc4eSMichael Bergknoff do {
1139af71cc4eSMichael Bergknoff snmp_syserr = 0;
1140af71cc4eSMichael Bergknoff ret = snmp_get_int(hdl, OID_entLastChangeTime, 0,
1141af71cc4eSMichael Bergknoff &cur_change_time, &snmp_syserr);
11421c60fca8Sfw157321 (void) time(&change_time_check);
11430d63ce2bSvenki if ((ret == 0) && (cur_change_time == change_time)) {
11440d63ce2bSvenki (void) rw_unlock(&stale_tree_rwlp);
11450d63ce2bSvenki return;
11460d63ce2bSvenki }
1147af71cc4eSMichael Bergknoff } while (ret != 0 && snmp_syserr == EINTR);
11480d63ce2bSvenki
11490d63ce2bSvenki /*
11500d63ce2bSvenki * If we can't read entLastChangeTime we assume we need to rebuild
11510d63ce2bSvenki * the tree. This will also cover the case when we need to rebuild
11520d63ce2bSvenki * the tree because a link reset had happened.
11530d63ce2bSvenki */
11540d63ce2bSvenki LOGPRINTF2("check_for_stale_data: LastChange times have changed, "
11550d63ce2bSvenki "(%#x != %#x)\n", change_time, cur_change_time);
11560d63ce2bSvenki
11570d63ce2bSvenki /*
11580d63ce2bSvenki * If the mib data has changed, we need to rebuild the physical-platform
11590d63ce2bSvenki * subtree. To do this, we set a flag to mark the tree stale,
11600d63ce2bSvenki * so that any future reads to get value of volatile properties will
11610d63ce2bSvenki * return PICL_PROPVALUNAVAILABLE, until the stale_tree flag
11620d63ce2bSvenki * is reset by the tree builder thread.
11630d63ce2bSvenki */
11640d63ce2bSvenki stale_tree = B_TRUE;
11650d63ce2bSvenki if (vol_props) {
11660d63ce2bSvenki free(vol_props);
11670d63ce2bSvenki }
11680d63ce2bSvenki vol_props = NULL;
11690d63ce2bSvenki volprop_ndx = 0;
11700d63ce2bSvenki n_vol_props = 0;
11710d63ce2bSvenki
11720d63ce2bSvenki (void) rw_unlock(&stale_tree_rwlp);
11730d63ce2bSvenki
11740d63ce2bSvenki (void) mutex_lock(&rebuild_tree_lock);
11750d63ce2bSvenki rebuild_tree = B_TRUE;
11760d63ce2bSvenki (void) cond_signal(&rebuild_tree_cv);
11770d63ce2bSvenki LOGPRINTF("check_for_stale_data: signalled tree builder\n");
11780d63ce2bSvenki (void) mutex_unlock(&rebuild_tree_lock);
11790d63ce2bSvenki }
11800d63ce2bSvenki
11810d63ce2bSvenki /*
11820d63ce2bSvenki * This is the critical routine. This callback is invoked by picl whenever
11830d63ce2bSvenki * it needs to fetch the value of a volatile property. The first thing we
11840d63ce2bSvenki * must do, however, is to see if there has been a hotplug or a link-reset
11850d63ce2bSvenki * event since the last time we built the tree and whether we need to
11860d63ce2bSvenki * rebuild the tree. If so, we do whatever is necessary to make that happen,
11870d63ce2bSvenki * but return PICL_PROPVALUNAVAILABLE for now, without making any further
11880d63ce2bSvenki * snmp requests or accessing any globals.
11890d63ce2bSvenki */
11900d63ce2bSvenki static int
read_volprop(ptree_rarg_t * parg,void * buf)11910d63ce2bSvenki read_volprop(ptree_rarg_t *parg, void *buf)
11920d63ce2bSvenki {
11930d63ce2bSvenki char *pstr;
11940d63ce2bSvenki int propval;
11950d63ce2bSvenki int i, ndx;
11960d63ce2bSvenki int ret;
11970d63ce2bSvenki int snmp_syserr = 0;
11980d63ce2bSvenki
11990d63ce2bSvenki /*
12000d63ce2bSvenki * First check for any event that would make us throw away
12010d63ce2bSvenki * the existing /physical-platform subtree and rebuild
12020d63ce2bSvenki * another one. If we are rebuilding the subtree, we just
12030d63ce2bSvenki * return the stale value until the tree is fully built.
12040d63ce2bSvenki */
12051c60fca8Sfw157321 check_for_stale_data(B_FALSE);
12060d63ce2bSvenki
12070d63ce2bSvenki (void) rw_rdlock(&stale_tree_rwlp);
12080d63ce2bSvenki
12090d63ce2bSvenki if (stale_tree == B_TRUE) {
12100d63ce2bSvenki (void) rw_unlock(&stale_tree_rwlp);
12110d63ce2bSvenki return (PICL_PROPVALUNAVAILABLE);
12120d63ce2bSvenki }
12130d63ce2bSvenki
12140d63ce2bSvenki for (i = 0; i < volprop_ndx; i++) {
12150d63ce2bSvenki if (vol_props[i].prop == parg->proph) {
12160d63ce2bSvenki ndx = i;
12170d63ce2bSvenki break;
12180d63ce2bSvenki }
12190d63ce2bSvenki }
12200d63ce2bSvenki if (i == volprop_ndx) {
12211c60fca8Sfw157321 (void) rw_unlock(&stale_tree_rwlp);
12220d63ce2bSvenki log_msg(LOG_ERR, SNMPP_CANT_FIND_VOLPROP, parg->proph);
12230d63ce2bSvenki return (PICL_FAILURE);
12240d63ce2bSvenki }
12250d63ce2bSvenki
12260d63ce2bSvenki /*
12270d63ce2bSvenki * If we can't read the value, return failure. Even if this was
12280d63ce2bSvenki * due to a link reset, between the check for stale data and now,
12290d63ce2bSvenki * the next volatile callback by picl will initiate a tree-rebuild.
12300d63ce2bSvenki */
12310d63ce2bSvenki ret = snmp_get_int(hdl, vol_props[ndx].oidstr, vol_props[ndx].row,
12320d63ce2bSvenki &propval, &snmp_syserr);
12330d63ce2bSvenki if (ret < 0) {
12341c60fca8Sfw157321 (void) rw_unlock(&stale_tree_rwlp);
12351c60fca8Sfw157321 check_for_stale_data(B_TRUE);
12361c60fca8Sfw157321 if (stale_tree == B_TRUE) {
12371c60fca8Sfw157321 return (PICL_PROPVALUNAVAILABLE);
12381c60fca8Sfw157321 }
12391c60fca8Sfw157321 log_msg(LOG_ERR, SNMPP_CANT_FETCH_OBJECT_VAL,
12401c60fca8Sfw157321 snmp_syserr ? snmp_syserr : ret,
12411c60fca8Sfw157321 vol_props[ndx].oidstr, vol_props[ndx].row);
12420d63ce2bSvenki return (PICL_FAILURE);
12430d63ce2bSvenki }
12440d63ce2bSvenki
12450d63ce2bSvenki switch (vol_props[ndx].proptype) {
12460d63ce2bSvenki case VPT_PLATOPSTATE:
12470d63ce2bSvenki if (propval == SSOS_DISABLED) {
12480d63ce2bSvenki (void) strlcpy(buf, STR_SSOS_DISABLED, MAX_OPSTATE_LEN);
12490d63ce2bSvenki } else if (propval == SSOS_ENABLED) {
12500d63ce2bSvenki (void) strlcpy(buf, STR_SSOS_ENABLED, MAX_OPSTATE_LEN);
12510d63ce2bSvenki } else {
12521c60fca8Sfw157321 (void) rw_unlock(&stale_tree_rwlp);
12530d63ce2bSvenki log_msg(LOG_ERR, SNMPP_INV_PLAT_EQUIP_OPSTATE,
12540d63ce2bSvenki propval, vol_props[ndx].row);
12550d63ce2bSvenki return (PICL_FAILURE);
12560d63ce2bSvenki }
12570d63ce2bSvenki break;
12580d63ce2bSvenki
12590d63ce2bSvenki case VPT_NUMSENSOR:
12600d63ce2bSvenki (void) memcpy(buf, &propval, sizeof (propval));
12610d63ce2bSvenki break;
12620d63ce2bSvenki
12630d63ce2bSvenki case VPT_BINSENSOR:
12640d63ce2bSvenki if (propval == ST_TRUE) {
12650d63ce2bSvenki ret = snmp_get_str(hdl,
12660d63ce2bSvenki OID_sunPlatBinarySensorInterpretTrue,
12670d63ce2bSvenki vol_props[ndx].row, &pstr, &snmp_syserr);
12681c60fca8Sfw157321 if (snmp_syserr == ECANCELED) {
12691c60fca8Sfw157321 (void) rw_unlock(&stale_tree_rwlp);
12701c60fca8Sfw157321 if (pstr)
12711c60fca8Sfw157321 free(pstr);
12720d63ce2bSvenki return (PICL_FAILURE);
12731c60fca8Sfw157321 }
12740d63ce2bSvenki if (ret < 0 || pstr == NULL) {
12751c60fca8Sfw157321 log_msg(LOG_ERR, SNMPP_CANT_FETCH_OBJECT_VAL,
12761c60fca8Sfw157321 snmp_syserr ? snmp_syserr : ret,
12771c60fca8Sfw157321 OID_sunPlatBinarySensorInterpretTrue,
12781c60fca8Sfw157321 vol_props[ndx].row);
12790d63ce2bSvenki (void) strlcpy(buf, STR_ST_TRUE,
12800d63ce2bSvenki MAX_TRUTHVAL_LEN);
12810d63ce2bSvenki } else {
12820d63ce2bSvenki (void) strlcpy(buf, pstr, MAX_TRUTHVAL_LEN);
12830d63ce2bSvenki }
12841c60fca8Sfw157321 if (pstr)
12851c60fca8Sfw157321 free(pstr);
12860d63ce2bSvenki } else if (propval == ST_FALSE) {
12870d63ce2bSvenki ret = snmp_get_str(hdl,
12880d63ce2bSvenki OID_sunPlatBinarySensorInterpretFalse,
12890d63ce2bSvenki vol_props[ndx].row, &pstr, &snmp_syserr);
12901c60fca8Sfw157321 if (snmp_syserr == ECANCELED) {
12911c60fca8Sfw157321 (void) rw_unlock(&stale_tree_rwlp);
12921c60fca8Sfw157321 if (pstr)
12931c60fca8Sfw157321 free(pstr);
12940d63ce2bSvenki return (PICL_FAILURE);
12951c60fca8Sfw157321 }
12960d63ce2bSvenki if (ret < 0 || pstr == NULL) {
12971c60fca8Sfw157321 log_msg(LOG_ERR, SNMPP_CANT_FETCH_OBJECT_VAL,
12981c60fca8Sfw157321 snmp_syserr ? snmp_syserr : ret,
12991c60fca8Sfw157321 OID_sunPlatBinarySensorInterpretFalse,
13001c60fca8Sfw157321 vol_props[ndx].row);
13010d63ce2bSvenki (void) strlcpy(buf, STR_ST_FALSE,
13020d63ce2bSvenki MAX_TRUTHVAL_LEN);
13030d63ce2bSvenki } else {
13040d63ce2bSvenki (void) strlcpy(buf, pstr, MAX_TRUTHVAL_LEN);
13050d63ce2bSvenki }
13061c60fca8Sfw157321 if (pstr)
13071c60fca8Sfw157321 free(pstr);
13080d63ce2bSvenki } else {
13091c60fca8Sfw157321 (void) rw_unlock(&stale_tree_rwlp);
13100d63ce2bSvenki log_msg(LOG_ERR, SNMPP_INV_PLAT_BINSNSR_CURRENT,
13110d63ce2bSvenki propval, vol_props[ndx].row);
13120d63ce2bSvenki return (PICL_FAILURE);
13130d63ce2bSvenki }
13140d63ce2bSvenki break;
13150d63ce2bSvenki
13160d63ce2bSvenki case VPT_ALARMSTATE:
13170d63ce2bSvenki if (propval == SSAS_OFF) {
13180d63ce2bSvenki (void) strlcpy(buf, STR_SSAS_OFF, MAX_ALARMSTATE_LEN);
13190d63ce2bSvenki } else if (propval == SSAS_STEADY) {
13200d63ce2bSvenki (void) strlcpy(buf, STR_SSAS_STEADY,
13210d63ce2bSvenki MAX_ALARMSTATE_LEN);
13220d63ce2bSvenki } else if (propval == SSAS_ALTERNATING) {
13230d63ce2bSvenki (void) strlcpy(buf, STR_SSAS_ALTERNATING,
13240d63ce2bSvenki MAX_ALARMSTATE_LEN);
13250d63ce2bSvenki } else {
13260d63ce2bSvenki (void) strlcpy(buf, STR_SSAS_UNKNOWN,
13270d63ce2bSvenki MAX_ALARMSTATE_LEN);
13280d63ce2bSvenki }
13290d63ce2bSvenki break;
13300d63ce2bSvenki
13310d63ce2bSvenki case VPT_BATTERYSTATUS:
13320d63ce2bSvenki switch (propval) {
13330d63ce2bSvenki case SSBS_OTHER:
13340d63ce2bSvenki (void) strlcpy(buf, STR_SSBS_OTHER,
13350d63ce2bSvenki MAX_BATTERYSTATUS_LEN);
13360d63ce2bSvenki break;
13370d63ce2bSvenki case SSBS_FULLYCHARGED:
13380d63ce2bSvenki (void) strlcpy(buf, STR_SSBS_FULLYCHARGED,
13390d63ce2bSvenki MAX_BATTERYSTATUS_LEN);
13400d63ce2bSvenki break;
13410d63ce2bSvenki case SSBS_LOW:
13420d63ce2bSvenki (void) strlcpy(buf, STR_SSBS_LOW,
13430d63ce2bSvenki MAX_BATTERYSTATUS_LEN);
13440d63ce2bSvenki break;
13450d63ce2bSvenki case SSBS_CRITICAL:
13460d63ce2bSvenki (void) strlcpy(buf, STR_SSBS_CRITICAL,
13470d63ce2bSvenki MAX_BATTERYSTATUS_LEN);
13480d63ce2bSvenki break;
13490d63ce2bSvenki case SSBS_CHARGING:
13500d63ce2bSvenki (void) strlcpy(buf, STR_SSBS_CHARGING,
13510d63ce2bSvenki MAX_BATTERYSTATUS_LEN);
13520d63ce2bSvenki break;
13530d63ce2bSvenki case SSBS_CHARGING_AND_LOW:
13540d63ce2bSvenki (void) strlcpy(buf, STR_SSBS_CHARGING_AND_LOW,
13550d63ce2bSvenki MAX_BATTERYSTATUS_LEN);
13560d63ce2bSvenki break;
13570d63ce2bSvenki case SSBS_CHARGING_AND_HIGH:
13580d63ce2bSvenki (void) strlcpy(buf, STR_SSBS_CHARGING_AND_HIGH,
13590d63ce2bSvenki MAX_BATTERYSTATUS_LEN);
13600d63ce2bSvenki break;
13610d63ce2bSvenki case SSBS_CHARGING_AND_CRITICAL:
13620d63ce2bSvenki (void) strlcpy(buf, STR_SSBS_CHARGING_AND_CRITICAL,
13630d63ce2bSvenki MAX_BATTERYSTATUS_LEN);
13640d63ce2bSvenki break;
13650d63ce2bSvenki case SSBS_UNDEFINED:
13660d63ce2bSvenki (void) strlcpy(buf, STR_SSBS_UNDEFINED,
13670d63ce2bSvenki MAX_BATTERYSTATUS_LEN);
13680d63ce2bSvenki break;
13690d63ce2bSvenki case SSBS_PARTIALLY_CHARGED:
13700d63ce2bSvenki (void) strlcpy(buf, STR_SSBS_PARTIALLY_CHARGED,
13710d63ce2bSvenki MAX_BATTERYSTATUS_LEN);
13720d63ce2bSvenki break;
13730d63ce2bSvenki case SSBS_UNKNOWN:
13740d63ce2bSvenki default:
13750d63ce2bSvenki (void) strlcpy(buf, STR_SSBS_UNKNOWN,
13760d63ce2bSvenki MAX_BATTERYSTATUS_LEN);
13770d63ce2bSvenki break;
13780d63ce2bSvenki }
13790d63ce2bSvenki break;
13800d63ce2bSvenki }
13810d63ce2bSvenki
13820d63ce2bSvenki (void) rw_unlock(&stale_tree_rwlp);
13830d63ce2bSvenki
13840d63ce2bSvenki return (PICL_SUCCESS);
13850d63ce2bSvenki }
13860d63ce2bSvenki
13870d63ce2bSvenki static void
threshold(picl_nodehdl_t node,char * oidstr,int row,char * propname,int * snmp_syserr_p)13880d63ce2bSvenki threshold(picl_nodehdl_t node, char *oidstr, int row, char *propname,
13890d63ce2bSvenki int *snmp_syserr_p)
13900d63ce2bSvenki {
13910d63ce2bSvenki picl_prophdl_t prop;
13920d63ce2bSvenki int err;
13930d63ce2bSvenki int val;
13940d63ce2bSvenki
13951c60fca8Sfw157321 if ((err = snmp_get_int(hdl, oidstr, row, &val, snmp_syserr_p)) != -1) {
13960d63ce2bSvenki err = add_volatile_prop(node, propname, PICL_PTYPE_INT,
13970d63ce2bSvenki PICL_READ, sizeof (int), read_volprop, NULL, &prop);
13980d63ce2bSvenki if (err == PICL_SUCCESS)
13990d63ce2bSvenki save_volprop(prop, oidstr, row, VPT_NUMSENSOR);
14001c60fca8Sfw157321 } else
14011c60fca8Sfw157321 log_msg(LOG_ERR, SNMPP_CANT_FETCH_OBJECT_VAL,
14021c60fca8Sfw157321 *snmp_syserr_p ? *snmp_syserr_p : err, oidstr, row);
14030d63ce2bSvenki }
14040d63ce2bSvenki
14050d63ce2bSvenki static void
add_thresholds(picl_nodehdl_t node,int row,int * snmp_syserr_p)14060d63ce2bSvenki add_thresholds(picl_nodehdl_t node, int row, int *snmp_syserr_p)
14070d63ce2bSvenki {
14080d63ce2bSvenki uchar_t *bitstr = NULL;
14090d63ce2bSvenki uchar_t enabled;
14100d63ce2bSvenki uint_t nbytes;
14110d63ce2bSvenki int ret;
14120d63ce2bSvenki
14131c60fca8Sfw157321 ret = snmp_get_str(hdl,
14141c60fca8Sfw157321 OID_sunPlatNumericSensorEnabledThresholds,
14151c60fca8Sfw157321 row, (char **)&bitstr, snmp_syserr_p);
14161c60fca8Sfw157321 if (ret == -1) {
14171c60fca8Sfw157321 log_msg(LOG_ERR, SNMPP_CANT_FETCH_OBJECT_VAL,
14181c60fca8Sfw157321 *snmp_syserr_p ? *snmp_syserr_p : ret,
14191c60fca8Sfw157321 OID_sunPlatNumericSensorEnabledThresholds, row);
14201c60fca8Sfw157321 } else {
14211c60fca8Sfw157321 nbytes = strlen((const char *)bitstr);
14221c60fca8Sfw157321 }
14230d63ce2bSvenki
14241c60fca8Sfw157321 CHECK_LINKRESET_VOID(snmp_syserr_p);
14251c60fca8Sfw157321
14261c60fca8Sfw157321 /*
14271c60fca8Sfw157321 * No bit string of threshold masks was returned, so we can't
14281c60fca8Sfw157321 * assume that any thresholds exist.
14291c60fca8Sfw157321 *
14301c60fca8Sfw157321 * This mask prevents us from attempting to fetch thresholds
14311c60fca8Sfw157321 * which don't apply to the sensor or that aren't there anyway,
14321c60fca8Sfw157321 * That speeds up the plug-in significantly since otherwise it
14331c60fca8Sfw157321 * takes several seconds to time out.
14341c60fca8Sfw157321 */
14351c60fca8Sfw157321 if (ret < 0 || bitstr == NULL || nbytes == 0 || 2 < nbytes) {
14361c60fca8Sfw157321 if (bitstr)
14371c60fca8Sfw157321 free(bitstr);
14381c60fca8Sfw157321 return;
14391c60fca8Sfw157321 } else if (nbytes == 1) {
14400d63ce2bSvenki /*
14410d63ce2bSvenki * The ALOM snmp agent doesn't adhere to the BER rules for
14420d63ce2bSvenki * encoding bit strings. While the BER states that bitstrings
14430d63ce2bSvenki * must begin from the second octet after length, and the
14440d63ce2bSvenki * first octet after length must indicate the number of unused
14450d63ce2bSvenki * bits in the last octet, the snmp agent simply sends the
14460d63ce2bSvenki * bitstring data as if it were octet string -- that is, the
14470d63ce2bSvenki * "unused bits" octet is missing.
14480d63ce2bSvenki */
14490d63ce2bSvenki enabled = bitstr[0];
14500d63ce2bSvenki } else if (nbytes == 2)
14510d63ce2bSvenki enabled = bitstr[1];
14520d63ce2bSvenki
14530d63ce2bSvenki if (bitstr) {
14540d63ce2bSvenki free(bitstr);
14550d63ce2bSvenki }
14560d63ce2bSvenki
14570d63ce2bSvenki if (enabled & LOWER_FATAL) {
14580d63ce2bSvenki threshold(node,
14590d63ce2bSvenki OID_sunPlatNumericSensorLowerThresholdFatal, row,
14600d63ce2bSvenki PICL_PROP_LOW_POWER_OFF, snmp_syserr_p);
14610d63ce2bSvenki CHECK_LINKRESET_VOID(snmp_syserr_p)
14620d63ce2bSvenki }
14630d63ce2bSvenki if (enabled & LOWER_CRITICAL) {
14640d63ce2bSvenki threshold(node,
14650d63ce2bSvenki OID_sunPlatNumericSensorLowerThresholdCritical, row,
14660d63ce2bSvenki PICL_PROP_LOW_SHUTDOWN, snmp_syserr_p);
14670d63ce2bSvenki CHECK_LINKRESET_VOID(snmp_syserr_p)
14680d63ce2bSvenki }
14690d63ce2bSvenki if (enabled & LOWER_NON_CRITICAL) {
14700d63ce2bSvenki threshold(node,
14710d63ce2bSvenki OID_sunPlatNumericSensorLowerThresholdNonCritical, row,
14720d63ce2bSvenki PICL_PROP_LOW_WARNING, snmp_syserr_p);
14730d63ce2bSvenki CHECK_LINKRESET_VOID(snmp_syserr_p)
14740d63ce2bSvenki }
14750d63ce2bSvenki if (enabled & UPPER_NON_CRITICAL) {
14760d63ce2bSvenki threshold(node,
14770d63ce2bSvenki OID_sunPlatNumericSensorUpperThresholdNonCritical, row,
1478aaba19e2Sfw157321 PICL_PROP_HIGH_WARNING, snmp_syserr_p);
14790d63ce2bSvenki CHECK_LINKRESET_VOID(snmp_syserr_p)
14800d63ce2bSvenki }
14810d63ce2bSvenki if (enabled & UPPER_CRITICAL) {
14820d63ce2bSvenki threshold(node,
14830d63ce2bSvenki OID_sunPlatNumericSensorUpperThresholdCritical, row,
14840d63ce2bSvenki PICL_PROP_HIGH_SHUTDOWN, snmp_syserr_p);
14850d63ce2bSvenki CHECK_LINKRESET_VOID(snmp_syserr_p)
14860d63ce2bSvenki }
14870d63ce2bSvenki if (enabled & UPPER_FATAL) {
14880d63ce2bSvenki threshold(node,
14890d63ce2bSvenki OID_sunPlatNumericSensorUpperThresholdFatal, row,
1490aaba19e2Sfw157321 PICL_PROP_HIGH_POWER_OFF, snmp_syserr_p);
14910d63ce2bSvenki CHECK_LINKRESET_VOID(snmp_syserr_p)
14920d63ce2bSvenki }
14930d63ce2bSvenki }
14940d63ce2bSvenki
14950d63ce2bSvenki static char *
get_slot_type(int row,int * snmp_syserr_p)14960d63ce2bSvenki get_slot_type(int row, int *snmp_syserr_p)
14970d63ce2bSvenki {
14980d63ce2bSvenki char *p;
14990d63ce2bSvenki char *slott = NULL;
15000d63ce2bSvenki int ret;
15010d63ce2bSvenki
15020d63ce2bSvenki ret = snmp_get_str(hdl, OID_sunPlatEquipmentHolderAcceptableTypes,
15030d63ce2bSvenki row, &p, snmp_syserr_p);
15040d63ce2bSvenki CHECK_LINKRESET(snmp_syserr_p, NULL)
15050d63ce2bSvenki
15060d63ce2bSvenki if ((ret == 0) && p && *p) {
15070d63ce2bSvenki slott = p;
15080d63ce2bSvenki if ((p = strchr(slott, '\n')) != NULL)
15090d63ce2bSvenki *p = 0;
15100d63ce2bSvenki } else {
15110d63ce2bSvenki log_msg(LOG_WARNING, SNMPP_NO_SLOT_TYPE, row);
15120d63ce2bSvenki if (p) {
15130d63ce2bSvenki free(p);
15140d63ce2bSvenki }
15150d63ce2bSvenki }
15160d63ce2bSvenki
15170d63ce2bSvenki return (slott);
15180d63ce2bSvenki }
15190d63ce2bSvenki
15200d63ce2bSvenki /*
15210d63ce2bSvenki * Create and add the specified volatile property
15220d63ce2bSvenki */
15230d63ce2bSvenki static int
add_volatile_prop(picl_nodehdl_t node,char * name,int type,int access,int size,int (* rdfunc)(ptree_rarg_t *,void *),int (* wrfunc)(ptree_warg_t *,const void *),picl_prophdl_t * propp)15240d63ce2bSvenki add_volatile_prop(picl_nodehdl_t node, char *name, int type, int access,
15250d63ce2bSvenki int size, int (*rdfunc)(ptree_rarg_t *, void *),
15260d63ce2bSvenki int (*wrfunc)(ptree_warg_t *, const void *), picl_prophdl_t *propp)
15270d63ce2bSvenki {
15280d63ce2bSvenki ptree_propinfo_t propinfo;
15290d63ce2bSvenki picl_prophdl_t prop;
15300d63ce2bSvenki int err;
15310d63ce2bSvenki
15320d63ce2bSvenki err = ptree_init_propinfo(&propinfo, PTREE_PROPINFO_VERSION,
15330d63ce2bSvenki type, (access|PICL_VOLATILE), size, name, rdfunc, wrfunc);
15340d63ce2bSvenki if (err != PICL_SUCCESS) {
15350d63ce2bSvenki log_msg(LOG_ERR, SNMPP_CANT_INIT_PROPINFO, err);
15360d63ce2bSvenki return (err);
15370d63ce2bSvenki }
15380d63ce2bSvenki
15390d63ce2bSvenki err = ptree_create_and_add_prop(node, &propinfo, NULL, &prop);
15400d63ce2bSvenki if (err != PICL_SUCCESS) {
15410d63ce2bSvenki log_msg(LOG_ERR, SNMPP_CANT_ADD_PROP, err, node);
15420d63ce2bSvenki return (err);
15430d63ce2bSvenki }
15440d63ce2bSvenki
15450d63ce2bSvenki if (propp)
15460d63ce2bSvenki *propp = prop;
15470d63ce2bSvenki
15480d63ce2bSvenki return (PICL_SUCCESS);
15490d63ce2bSvenki }
15500d63ce2bSvenki
15510d63ce2bSvenki /*
15520d63ce2bSvenki * Add the specified string property to the node
15530d63ce2bSvenki */
15540d63ce2bSvenki static int
add_string_prop(picl_nodehdl_t node,char * propname,char * propval)15550d63ce2bSvenki add_string_prop(picl_nodehdl_t node, char *propname, char *propval)
15560d63ce2bSvenki {
15570d63ce2bSvenki ptree_propinfo_t propinfo;
15580d63ce2bSvenki int err;
15590d63ce2bSvenki
15602ea390f3SMichael Bergknoff if (*propval == '\0')
15612ea390f3SMichael Bergknoff return (PICL_SUCCESS);
15622ea390f3SMichael Bergknoff
15630d63ce2bSvenki err = ptree_init_propinfo(&propinfo, PTREE_PROPINFO_VERSION,
15640d63ce2bSvenki PICL_PTYPE_CHARSTRING, PICL_READ, strlen(propval) + 1,
15650d63ce2bSvenki propname, NULL, NULL);
15660d63ce2bSvenki if (err != PICL_SUCCESS) {
15670d63ce2bSvenki log_msg(LOG_ERR, SNMPP_CANT_INIT_STR_PROPINFO, err);
15680d63ce2bSvenki return (err);
15690d63ce2bSvenki }
15700d63ce2bSvenki
15710d63ce2bSvenki err = ptree_create_and_add_prop(node, &propinfo, propval, NULL);
15720d63ce2bSvenki if (err != PICL_SUCCESS) {
15730d63ce2bSvenki log_msg(LOG_ERR, SNMPP_CANT_ADD_STR_PROP, err, node);
15740d63ce2bSvenki return (err);
15750d63ce2bSvenki }
15760d63ce2bSvenki
15770d63ce2bSvenki return (PICL_SUCCESS);
15780d63ce2bSvenki }
15790d63ce2bSvenki
15800d63ce2bSvenki /*
15810d63ce2bSvenki * Add the specified void property to the node
15820d63ce2bSvenki */
15830d63ce2bSvenki static int
add_void_prop(picl_nodehdl_t node,char * propname)15840d63ce2bSvenki add_void_prop(picl_nodehdl_t node, char *propname)
15850d63ce2bSvenki {
15860d63ce2bSvenki ptree_propinfo_t propinfo;
15870d63ce2bSvenki int err;
15880d63ce2bSvenki
15890d63ce2bSvenki err = ptree_init_propinfo(&propinfo, PTREE_PROPINFO_VERSION,
15900d63ce2bSvenki PICL_PTYPE_VOID, PICL_READ, 0, propname, NULL, NULL);
15910d63ce2bSvenki if (err != PICL_SUCCESS) {
15920d63ce2bSvenki log_msg(LOG_ERR, SNMPP_CANT_INIT_VOID_PROPINFO, err);
15930d63ce2bSvenki return (err);
15940d63ce2bSvenki }
15950d63ce2bSvenki
15960d63ce2bSvenki err = ptree_create_and_add_prop(node, &propinfo, NULL, NULL);
15970d63ce2bSvenki if (err != PICL_SUCCESS) {
15980d63ce2bSvenki log_msg(LOG_ERR, SNMPP_CANT_ADD_VOID_PROP, err, node);
15990d63ce2bSvenki return (err);
16000d63ce2bSvenki }
16010d63ce2bSvenki
16020d63ce2bSvenki return (PICL_SUCCESS);
16030d63ce2bSvenki }
16040d63ce2bSvenki
16050d63ce2bSvenki static void
add_prop(picl_nodehdl_t nodeh,picl_prophdl_t * php,char * label,int row,sp_propid_t pp,int * snmp_syserr_p)16060d63ce2bSvenki add_prop(picl_nodehdl_t nodeh, picl_prophdl_t *php, char *label,
16070d63ce2bSvenki int row, sp_propid_t pp, int *snmp_syserr_p)
16080d63ce2bSvenki {
16090d63ce2bSvenki char *serial_num;
16100d63ce2bSvenki char *slot_type;
16110d63ce2bSvenki char *fw_revision, *hw_revision;
16120d63ce2bSvenki char *mfg_name, *model_name;
16130d63ce2bSvenki char *phys_descr;
16140d63ce2bSvenki int val;
16150d63ce2bSvenki int ret;
16160d63ce2bSvenki
16170d63ce2bSvenki switch (pp) {
16180d63ce2bSvenki case PP_SERIAL_NUM:
16190d63ce2bSvenki ret = snmp_get_str(hdl, OID_entPhysicalSerialNum,
16200d63ce2bSvenki row, &serial_num, snmp_syserr_p);
16210d63ce2bSvenki CHECK_LINKRESET_VOID(snmp_syserr_p)
16222ea390f3SMichael Bergknoff if ((ret == 0) && serial_num) {
16230d63ce2bSvenki (void) add_string_prop(nodeh,
16240d63ce2bSvenki PICL_PROP_SERIAL_NUMBER, serial_num);
16250d63ce2bSvenki free((void *) serial_num);
16260d63ce2bSvenki }
16271c60fca8Sfw157321 if (ret == -1)
16281c60fca8Sfw157321 log_msg(LOG_ERR, SNMPP_CANT_FETCH_OBJECT_VAL,
16291c60fca8Sfw157321 *snmp_syserr_p ? *snmp_syserr_p : ret,
16301c60fca8Sfw157321 OID_entPhysicalSerialNum, row);
16310d63ce2bSvenki break;
16320d63ce2bSvenki
16330d63ce2bSvenki case PP_SLOT_TYPE:
16340d63ce2bSvenki if ((slot_type = get_slot_type(row, snmp_syserr_p)) == NULL) {
16350d63ce2bSvenki CHECK_LINKRESET_VOID(snmp_syserr_p)
16360d63ce2bSvenki (void) add_string_prop(nodeh,
16370d63ce2bSvenki PICL_PROP_SLOT_TYPE, DEFAULT_SLOT_TYPE);
16380d63ce2bSvenki } else {
16390d63ce2bSvenki (void) add_string_prop(nodeh,
16400d63ce2bSvenki PICL_PROP_SLOT_TYPE, slot_type);
16410d63ce2bSvenki free((void *) slot_type);
16420d63ce2bSvenki }
16430d63ce2bSvenki break;
16440d63ce2bSvenki
16450d63ce2bSvenki case PP_STATE:
16460d63ce2bSvenki ret = add_volatile_prop(nodeh, PICL_PROP_STATE,
16470d63ce2bSvenki PICL_PTYPE_CHARSTRING, PICL_READ, MAX_ALARMSTATE_LEN,
16480d63ce2bSvenki read_volprop, NULL, php);
16490d63ce2bSvenki if (ret == PICL_SUCCESS) {
16500d63ce2bSvenki save_volprop(*php, OID_sunPlatAlarmState, row,
16510d63ce2bSvenki VPT_ALARMSTATE);
16520d63ce2bSvenki }
16530d63ce2bSvenki break;
16540d63ce2bSvenki
16550d63ce2bSvenki case PP_OPSTATUS:
16560d63ce2bSvenki ret = add_volatile_prop(nodeh, PICL_PROP_OPERATIONAL_STATUS,
16570d63ce2bSvenki PICL_PTYPE_CHARSTRING, PICL_READ, MAX_OPSTATE_LEN,
16580d63ce2bSvenki read_volprop, NULL, php);
16590d63ce2bSvenki if (ret == PICL_SUCCESS) {
16600d63ce2bSvenki save_volprop(*php,
16610d63ce2bSvenki OID_sunPlatEquipmentOperationalState, row,
16620d63ce2bSvenki VPT_PLATOPSTATE);
16630d63ce2bSvenki }
16640d63ce2bSvenki break;
16650d63ce2bSvenki
16660d63ce2bSvenki case PP_BATT_STATUS:
16670d63ce2bSvenki ret = add_volatile_prop(nodeh, PICL_PROP_BATTERY_STATUS,
16680d63ce2bSvenki PICL_PTYPE_CHARSTRING, PICL_READ, MAX_BATTERYSTATUS_LEN,
16690d63ce2bSvenki read_volprop, NULL, php);
16700d63ce2bSvenki if (ret == PICL_SUCCESS) {
16710d63ce2bSvenki save_volprop(*php, OID_sunPlatBatteryStatus, row,
16720d63ce2bSvenki VPT_BATTERYSTATUS);
16730d63ce2bSvenki }
16740d63ce2bSvenki break;
16750d63ce2bSvenki
16760d63ce2bSvenki case PP_TEMPERATURE:
16770d63ce2bSvenki ret = add_volatile_prop(nodeh, PICL_PROP_TEMPERATURE,
16780d63ce2bSvenki PICL_PTYPE_INT, PICL_READ, sizeof (int), read_volprop,
16790d63ce2bSvenki NULL, php);
16800d63ce2bSvenki if (ret == PICL_SUCCESS) {
16810d63ce2bSvenki save_volprop(*php, OID_sunPlatNumericSensorCurrent,
16820d63ce2bSvenki row, VPT_NUMSENSOR);
16830d63ce2bSvenki }
16840d63ce2bSvenki break;
16850d63ce2bSvenki
16860d63ce2bSvenki case PP_VOLTAGE:
16870d63ce2bSvenki ret = add_volatile_prop(nodeh, PICL_PROP_VOLTAGE,
16880d63ce2bSvenki PICL_PTYPE_INT, PICL_READ, sizeof (int), read_volprop,
16890d63ce2bSvenki NULL, php);
16900d63ce2bSvenki if (ret == PICL_SUCCESS) {
16910d63ce2bSvenki save_volprop(*php, OID_sunPlatNumericSensorCurrent,
16920d63ce2bSvenki row, VPT_NUMSENSOR);
16930d63ce2bSvenki }
16940d63ce2bSvenki break;
16950d63ce2bSvenki
16960d63ce2bSvenki case PP_CURRENT:
16970d63ce2bSvenki ret = add_volatile_prop(nodeh, PICL_PROP_CURRENT,
16980d63ce2bSvenki PICL_PTYPE_INT, PICL_READ, sizeof (int), read_volprop,
16990d63ce2bSvenki NULL, php);
17000d63ce2bSvenki if (ret == PICL_SUCCESS) {
17010d63ce2bSvenki save_volprop(*php, OID_sunPlatNumericSensorCurrent,
17020d63ce2bSvenki row, VPT_NUMSENSOR);
17030d63ce2bSvenki }
17040d63ce2bSvenki break;
17050d63ce2bSvenki
17060d63ce2bSvenki case PP_SPEED:
17070d63ce2bSvenki ret = add_volatile_prop(nodeh, PICL_PROP_SPEED, PICL_PTYPE_INT,
17080d63ce2bSvenki PICL_READ, sizeof (int), read_volprop, NULL, php);
17090d63ce2bSvenki if (ret == PICL_SUCCESS) {
17100d63ce2bSvenki save_volprop(*php, OID_sunPlatNumericSensorCurrent,
17110d63ce2bSvenki row, VPT_NUMSENSOR);
17120d63ce2bSvenki }
17130d63ce2bSvenki break;
17140d63ce2bSvenki
17150d63ce2bSvenki case PP_SENSOR_VALUE:
17160d63ce2bSvenki ret = add_volatile_prop(nodeh, PICL_PROP_SENSOR_VALUE,
17170d63ce2bSvenki PICL_PTYPE_INT, PICL_READ, sizeof (int), read_volprop,
17180d63ce2bSvenki NULL, php);
17190d63ce2bSvenki if (ret == PICL_SUCCESS) {
17200d63ce2bSvenki save_volprop(*php, OID_sunPlatNumericSensorCurrent,
17210d63ce2bSvenki row, VPT_NUMSENSOR);
17220d63ce2bSvenki }
17230d63ce2bSvenki break;
17240d63ce2bSvenki
17250d63ce2bSvenki case PP_CONDITION:
17260d63ce2bSvenki ret = add_volatile_prop(nodeh, PICL_PROP_CONDITION,
17270d63ce2bSvenki PICL_PTYPE_CHARSTRING, PICL_READ, MAX_TRUTHVAL_LEN,
17280d63ce2bSvenki read_volprop, NULL, php);
17290d63ce2bSvenki if (ret == PICL_SUCCESS) {
17300d63ce2bSvenki save_volprop(*php, OID_sunPlatBinarySensorCurrent,
17310d63ce2bSvenki row, VPT_BINSENSOR);
17320d63ce2bSvenki }
17330d63ce2bSvenki break;
17340d63ce2bSvenki
17350d63ce2bSvenki case PP_EXPECTED:
17360d63ce2bSvenki ret = add_volatile_prop(nodeh, PICL_PROP_EXPECTED,
17370d63ce2bSvenki PICL_PTYPE_CHARSTRING, PICL_READ, MAX_TRUTHVAL_LEN,
17380d63ce2bSvenki read_volprop, NULL, php);
17390d63ce2bSvenki if (ret == PICL_SUCCESS) {
17400d63ce2bSvenki save_volprop(*php, OID_sunPlatBinarySensorExpected,
17410d63ce2bSvenki row, VPT_BINSENSOR);
17420d63ce2bSvenki }
17430d63ce2bSvenki break;
17440d63ce2bSvenki
1745dc6ca969Sfw157321 case PP_EXPONENT:
1746dc6ca969Sfw157321 ret = add_volatile_prop(nodeh, PICL_PROP_EXPONENT,
1747dc6ca969Sfw157321 PICL_PTYPE_INT, PICL_READ, sizeof (int), read_volprop,
1748dc6ca969Sfw157321 NULL, php);
1749dc6ca969Sfw157321 if (ret == PICL_SUCCESS) {
1750dc6ca969Sfw157321 save_volprop(*php, OID_sunPlatNumericSensorExponent,
1751dc6ca969Sfw157321 row, VPT_NUMSENSOR);
1752dc6ca969Sfw157321 }
1753dc6ca969Sfw157321 break;
1754dc6ca969Sfw157321
17550d63ce2bSvenki case PP_REPLACEABLE:
17560d63ce2bSvenki ret = snmp_get_int(hdl, OID_sunPlatCircuitPackReplaceable,
17570d63ce2bSvenki row, &val, snmp_syserr_p);
17580d63ce2bSvenki CHECK_LINKRESET_VOID(snmp_syserr_p)
17590d63ce2bSvenki if ((ret == 0) && (val == ST_TRUE))
17600d63ce2bSvenki (void) add_void_prop(nodeh, PICL_PROP_IS_REPLACEABLE);
17611c60fca8Sfw157321 if (ret == -1)
17621c60fca8Sfw157321 log_msg(LOG_ERR, SNMPP_CANT_FETCH_OBJECT_VAL,
17631c60fca8Sfw157321 *snmp_syserr_p ? *snmp_syserr_p : ret,
17641c60fca8Sfw157321 OID_sunPlatCircuitPackReplaceable, row);
17650d63ce2bSvenki break;
17660d63ce2bSvenki
17670d63ce2bSvenki case PP_HOTSWAPPABLE:
17680d63ce2bSvenki ret = snmp_get_int(hdl, OID_sunPlatCircuitPackHotSwappable,
17690d63ce2bSvenki row, &val, snmp_syserr_p);
17700d63ce2bSvenki CHECK_LINKRESET_VOID(snmp_syserr_p)
17710d63ce2bSvenki if ((ret == 0) && (val == ST_TRUE))
17720d63ce2bSvenki (void) add_void_prop(nodeh, PICL_PROP_IS_HOT_SWAPPABLE);
17731c60fca8Sfw157321 if (ret == -1)
17741c60fca8Sfw157321 log_msg(LOG_ERR, SNMPP_CANT_FETCH_OBJECT_VAL,
17751c60fca8Sfw157321 *snmp_syserr_p ? *snmp_syserr_p : ret,
17761c60fca8Sfw157321 OID_sunPlatCircuitPackHotSwappable, row);
17770d63ce2bSvenki break;
17780d63ce2bSvenki
17790d63ce2bSvenki case PP_IS_FRU:
17800d63ce2bSvenki ret = snmp_get_int(hdl, OID_entPhysicalIsFRU, row,
17810d63ce2bSvenki &val, snmp_syserr_p);
17820d63ce2bSvenki CHECK_LINKRESET_VOID(snmp_syserr_p)
17830d63ce2bSvenki if ((ret == 0) && (val == ST_TRUE))
17840d63ce2bSvenki (void) add_void_prop(nodeh, PICL_PROP_IS_FRU);
17851c60fca8Sfw157321 if (ret == -1)
17861c60fca8Sfw157321 log_msg(LOG_ERR, SNMPP_CANT_FETCH_OBJECT_VAL,
17871c60fca8Sfw157321 *snmp_syserr_p ? *snmp_syserr_p : ret,
17881c60fca8Sfw157321 OID_entPhysicalIsFRU, row);
17890d63ce2bSvenki break;
17900d63ce2bSvenki
17910d63ce2bSvenki case PP_HW_REVISION:
17920d63ce2bSvenki ret = snmp_get_str(hdl, OID_entPhysicalHardwareRev,
17930d63ce2bSvenki row, &hw_revision, snmp_syserr_p);
17940d63ce2bSvenki CHECK_LINKRESET_VOID(snmp_syserr_p)
17952ea390f3SMichael Bergknoff if ((ret == 0) && hw_revision) {
17960d63ce2bSvenki (void) add_string_prop(nodeh,
17970d63ce2bSvenki PICL_PROP_HW_REVISION, hw_revision);
17980d63ce2bSvenki free((void *) hw_revision);
17990d63ce2bSvenki }
18001c60fca8Sfw157321 if (ret == -1)
18011c60fca8Sfw157321 log_msg(LOG_ERR, SNMPP_CANT_FETCH_OBJECT_VAL,
18021c60fca8Sfw157321 *snmp_syserr_p ? *snmp_syserr_p : ret,
18031c60fca8Sfw157321 OID_entPhysicalHardwareRev, row);
18040d63ce2bSvenki break;
18050d63ce2bSvenki
18060d63ce2bSvenki case PP_FW_REVISION:
18070d63ce2bSvenki ret = snmp_get_str(hdl, OID_entPhysicalFirmwareRev,
18080d63ce2bSvenki row, &fw_revision, snmp_syserr_p);
18090d63ce2bSvenki CHECK_LINKRESET_VOID(snmp_syserr_p)
18102ea390f3SMichael Bergknoff if ((ret == 0) && fw_revision) {
18110d63ce2bSvenki (void) add_string_prop(nodeh,
18120d63ce2bSvenki PICL_PROP_FW_REVISION, fw_revision);
18130d63ce2bSvenki free((void *) fw_revision);
18140d63ce2bSvenki }
18151c60fca8Sfw157321 if (ret == -1)
18161c60fca8Sfw157321 log_msg(LOG_ERR, SNMPP_CANT_FETCH_OBJECT_VAL,
18171c60fca8Sfw157321 *snmp_syserr_p ? *snmp_syserr_p : ret,
18181c60fca8Sfw157321 OID_entPhysicalFirmwareRev, row);
18190d63ce2bSvenki break;
18200d63ce2bSvenki
18210d63ce2bSvenki case PP_MFG_NAME:
18220d63ce2bSvenki ret = snmp_get_str(hdl, OID_entPhysicalMfgName,
18230d63ce2bSvenki row, &mfg_name, snmp_syserr_p);
18240d63ce2bSvenki CHECK_LINKRESET_VOID(snmp_syserr_p)
18252ea390f3SMichael Bergknoff if ((ret == 0) && mfg_name) {
18260d63ce2bSvenki (void) add_string_prop(nodeh,
18270d63ce2bSvenki PICL_PROP_MFG_NAME, mfg_name);
18280d63ce2bSvenki free((void *) mfg_name);
18290d63ce2bSvenki }
18301c60fca8Sfw157321 if (ret == -1)
18311c60fca8Sfw157321 log_msg(LOG_ERR, SNMPP_CANT_FETCH_OBJECT_VAL,
18321c60fca8Sfw157321 *snmp_syserr_p ? *snmp_syserr_p : ret,
18331c60fca8Sfw157321 OID_entPhysicalMfgName, row);
18340d63ce2bSvenki break;
18350d63ce2bSvenki
18360d63ce2bSvenki case PP_MODEL_NAME:
18370d63ce2bSvenki ret = snmp_get_str(hdl, OID_entPhysicalModelName,
18380d63ce2bSvenki row, &model_name, snmp_syserr_p);
18390d63ce2bSvenki CHECK_LINKRESET_VOID(snmp_syserr_p)
18402ea390f3SMichael Bergknoff if ((ret == 0) && model_name) {
18410d63ce2bSvenki (void) add_string_prop(nodeh,
18420d63ce2bSvenki PICL_PROP_MODEL_NAME, model_name);
18430d63ce2bSvenki free((void *) model_name);
18440d63ce2bSvenki }
18451c60fca8Sfw157321 if (ret == -1)
18461c60fca8Sfw157321 log_msg(LOG_ERR, SNMPP_CANT_FETCH_OBJECT_VAL,
18471c60fca8Sfw157321 *snmp_syserr_p ? *snmp_syserr_p : ret,
18481c60fca8Sfw157321 OID_entPhysicalModelName, row);
18490d63ce2bSvenki break;
18500d63ce2bSvenki
18510d63ce2bSvenki case PP_DESCRIPTION:
18520d63ce2bSvenki ret = snmp_get_str(hdl, OID_entPhysicalDescr,
18530d63ce2bSvenki row, &phys_descr, snmp_syserr_p);
18540d63ce2bSvenki CHECK_LINKRESET_VOID(snmp_syserr_p)
18552ea390f3SMichael Bergknoff if ((ret == 0) && phys_descr) {
18560d63ce2bSvenki (void) add_string_prop(nodeh,
18570d63ce2bSvenki PICL_PROP_PHYS_DESCRIPTION, phys_descr);
18580d63ce2bSvenki free((void *) phys_descr);
18590d63ce2bSvenki }
18601c60fca8Sfw157321 if (ret == -1)
18611c60fca8Sfw157321 log_msg(LOG_ERR, SNMPP_CANT_FETCH_OBJECT_VAL,
18621c60fca8Sfw157321 *snmp_syserr_p ? *snmp_syserr_p : ret,
18631c60fca8Sfw157321 OID_entPhysicalDescr, row);
18640d63ce2bSvenki break;
18650d63ce2bSvenki
18660d63ce2bSvenki case PP_LABEL:
18670d63ce2bSvenki if (label && *label)
18680d63ce2bSvenki (void) add_string_prop(nodeh, PICL_PROP_LABEL, label);
18690d63ce2bSvenki break;
18700d63ce2bSvenki
18710d63ce2bSvenki case PP_BASE_UNITS:
18720d63ce2bSvenki ret = snmp_get_int(hdl, OID_sunPlatNumericSensorBaseUnits,
18730d63ce2bSvenki row, &val, snmp_syserr_p);
18740d63ce2bSvenki CHECK_LINKRESET_VOID(snmp_syserr_p)
18750d63ce2bSvenki if ((ret == 0) && (val > 0) && (val < n_baseunits)) {
18760d63ce2bSvenki (void) add_string_prop(nodeh,
18770d63ce2bSvenki PICL_PROP_BASE_UNITS, sensor_baseunits[val]);
18780d63ce2bSvenki }
18791c60fca8Sfw157321 if (ret == -1)
18801c60fca8Sfw157321 log_msg(LOG_ERR, SNMPP_CANT_FETCH_OBJECT_VAL,
18811c60fca8Sfw157321 *snmp_syserr_p ? *snmp_syserr_p : ret,
18821c60fca8Sfw157321 OID_sunPlatNumericSensorBaseUnits, row);
18830d63ce2bSvenki break;
18840d63ce2bSvenki
18850d63ce2bSvenki case PP_RATE_UNITS:
18860d63ce2bSvenki ret = snmp_get_int(hdl, OID_sunPlatNumericSensorRateUnits,
18870d63ce2bSvenki row, &val, snmp_syserr_p);
18880d63ce2bSvenki CHECK_LINKRESET_VOID(snmp_syserr_p)
18890d63ce2bSvenki if ((ret == 0) && (val > 0) && (val < n_rateunits)) {
18900d63ce2bSvenki (void) add_string_prop(nodeh,
18910d63ce2bSvenki PICL_PROP_RATE_UNITS, sensor_rateunits[val]);
18920d63ce2bSvenki }
18931c60fca8Sfw157321 if (ret == -1)
18941c60fca8Sfw157321 log_msg(LOG_ERR, SNMPP_CANT_FETCH_OBJECT_VAL,
18951c60fca8Sfw157321 *snmp_syserr_p ? *snmp_syserr_p : ret,
18961c60fca8Sfw157321 OID_sunPlatNumericSensorRateUnits, row);
18970d63ce2bSvenki break;
18980d63ce2bSvenki }
18990d63ce2bSvenki }
19000d63ce2bSvenki
1901817697f4SKelly Moyer /*
1902817697f4SKelly Moyer * Initialize the SNMP library's cache refresh subsystem, then periodically
1903817697f4SKelly Moyer * process refresh job to prevent cache entries from expiring.
1904817697f4SKelly Moyer */
1905817697f4SKelly Moyer /*ARGSUSED*/
1906817697f4SKelly Moyer static void *
cache_refresher(void * arg)1907817697f4SKelly Moyer cache_refresher(void *arg)
1908817697f4SKelly Moyer {
1909817697f4SKelly Moyer int jobs;
1910817697f4SKelly Moyer int next_expiration;
1911817697f4SKelly Moyer timestruc_t to;
1912817697f4SKelly Moyer hrtime_t cycle_start, cycle_elapsed;
1913817697f4SKelly Moyer
1914817697f4SKelly Moyer /*
1915817697f4SKelly Moyer * Initialize refresh subsystem
1916817697f4SKelly Moyer */
1917817697f4SKelly Moyer LOGPRINTF("Initializing SNMP refresh subsystem.\n");
1918817697f4SKelly Moyer if (snmp_refresh_init() < 0) {
1919817697f4SKelly Moyer return ((void *)-1);
1920817697f4SKelly Moyer }
1921817697f4SKelly Moyer
1922817697f4SKelly Moyer (void) mutex_lock(&cache_refresh_lock);
1923817697f4SKelly Moyer
1924817697f4SKelly Moyer
1925817697f4SKelly Moyer for (;;) {
1926817697f4SKelly Moyer cycle_start = gethrtime();
1927817697f4SKelly Moyer
1928817697f4SKelly Moyer /*
1929817697f4SKelly Moyer * Process jobs from the snmp cache refresh work queue until one
1930817697f4SKelly Moyer * of the following conditions is true:
1931817697f4SKelly Moyer * 1) we are told to exit, or
1932817697f4SKelly Moyer * 2) we have processed at least as many jobs as recommended by
1933817697f4SKelly Moyer * the library, and the next job expiration is at least
1934817697f4SKelly Moyer * CACHE_REFRESH_MIN_WINDOW * seconds away.
1935817697f4SKelly Moyer */
1936817697f4SKelly Moyer jobs = snmp_refresh_get_cycle_hint(CACHE_REFRESH_CYCLE);
1937817697f4SKelly Moyer while ((cache_refresh_thr_exit == B_FALSE) && (jobs > 0)) {
1938817697f4SKelly Moyer (void) snmp_refresh_process_job();
1939817697f4SKelly Moyer jobs--;
1940817697f4SKelly Moyer }
1941817697f4SKelly Moyer
1942817697f4SKelly Moyer next_expiration = snmp_refresh_get_next_expiration();
1943817697f4SKelly Moyer while ((cache_refresh_thr_exit == B_FALSE) &&
1944817697f4SKelly Moyer ((next_expiration >= 0) &&
1945817697f4SKelly Moyer (next_expiration < CACHE_REFRESH_MIN_WINDOW))) {
1946817697f4SKelly Moyer (void) snmp_refresh_process_job();
1947817697f4SKelly Moyer next_expiration = snmp_refresh_get_next_expiration();
1948817697f4SKelly Moyer }
1949817697f4SKelly Moyer
1950817697f4SKelly Moyer /*
1951817697f4SKelly Moyer * As long as we haven't been told to exit, sleep for
1952817697f4SKelly Moyer * CACHE_REFRESH_CYCLE seconds minus the amount of time that has
1953817697f4SKelly Moyer * elapsed since this cycle started. If the elapsed time is
1954817697f4SKelly Moyer * equal to or greater than 60 seconds, skip sleeping entirely.
1955817697f4SKelly Moyer */
1956817697f4SKelly Moyer cycle_elapsed = (gethrtime() - cycle_start) / NANOSEC;
1957817697f4SKelly Moyer if ((cache_refresh_thr_exit == B_FALSE) &&
1958817697f4SKelly Moyer (cycle_elapsed < CACHE_REFRESH_CYCLE)) {
1959817697f4SKelly Moyer to.tv_sec = CACHE_REFRESH_CYCLE - cycle_elapsed;
1960817697f4SKelly Moyer to.tv_nsec = 0;
1961817697f4SKelly Moyer (void) cond_reltimedwait(&cache_refresh_cv,
1962817697f4SKelly Moyer &cache_refresh_lock, &to);
1963817697f4SKelly Moyer }
1964817697f4SKelly Moyer
1965817697f4SKelly Moyer /*
1966817697f4SKelly Moyer * If we have been told to exit, clean up and bail out.
1967817697f4SKelly Moyer */
1968817697f4SKelly Moyer if (cache_refresh_thr_exit == B_TRUE) {
1969817697f4SKelly Moyer snmp_refresh_fini();
1970817697f4SKelly Moyer (void) mutex_unlock(&cache_refresh_lock);
1971817697f4SKelly Moyer LOGPRINTF("cache_refresher: time to exit\n");
1972817697f4SKelly Moyer return (NULL);
1973817697f4SKelly Moyer }
1974817697f4SKelly Moyer
1975817697f4SKelly Moyer }
1976817697f4SKelly Moyer
1977817697f4SKelly Moyer /*NOTREACHED*/
1978817697f4SKelly Moyer return (NULL);
1979817697f4SKelly Moyer }
1980817697f4SKelly Moyer
1981817697f4SKelly Moyer /*
1982817697f4SKelly Moyer * Check to see if the cache_refresher thread is running. If it is, signal it
1983817697f4SKelly Moyer * to terminate and clean up associated data structures.
1984817697f4SKelly Moyer */
1985817697f4SKelly Moyer void
cache_refresher_fini(void)1986817697f4SKelly Moyer cache_refresher_fini(void)
1987817697f4SKelly Moyer {
1988817697f4SKelly Moyer /* if the thread isn't running, there is nothing to do */
1989817697f4SKelly Moyer if (cache_refresh_thr_exit == B_TRUE)
1990817697f4SKelly Moyer return;
1991817697f4SKelly Moyer
1992817697f4SKelly Moyer /* wake up the cache_refresher thread, tell it to exit */
1993817697f4SKelly Moyer (void) mutex_lock(&cache_refresh_lock);
1994817697f4SKelly Moyer cache_refresh_thr_exit = B_TRUE;
1995817697f4SKelly Moyer (void) cond_signal(&cache_refresh_cv);
1996817697f4SKelly Moyer (void) mutex_unlock(&cache_refresh_lock);
1997817697f4SKelly Moyer
1998817697f4SKelly Moyer /* reap the thread */
1999817697f4SKelly Moyer (void) thr_join(cache_refresh_thr_id, NULL, NULL);
2000817697f4SKelly Moyer
2001817697f4SKelly Moyer /* finish cleanup... */
2002817697f4SKelly Moyer (void) cond_destroy(&cache_refresh_cv);
2003817697f4SKelly Moyer (void) mutex_destroy(&cache_refresh_lock);
2004817697f4SKelly Moyer }
2005817697f4SKelly Moyer
20060d63ce2bSvenki /*VARARGS2*/
20070d63ce2bSvenki static void
log_msg(int pri,const char * fmt,...)20080d63ce2bSvenki log_msg(int pri, const char *fmt, ...)
20090d63ce2bSvenki {
20100d63ce2bSvenki va_list ap;
20110d63ce2bSvenki
20120d63ce2bSvenki va_start(ap, fmt);
20130d63ce2bSvenki vsyslog(pri, fmt, ap);
20140d63ce2bSvenki va_end(ap);
20150d63ce2bSvenki }
20160d63ce2bSvenki
20170d63ce2bSvenki #ifdef SNMPPLUGIN_DEBUG
20180d63ce2bSvenki
20190d63ce2bSvenki static void
snmpplugin_log_init(void)20200d63ce2bSvenki snmpplugin_log_init(void)
20210d63ce2bSvenki {
20220d63ce2bSvenki (void) mutex_init(&snmpplugin_dbuf_lock, USYNC_THREAD, NULL);
20230d63ce2bSvenki }
20240d63ce2bSvenki
20250d63ce2bSvenki static void
snmpplugin_log(const char * fmt,...)20260d63ce2bSvenki snmpplugin_log(const char *fmt, ...)
20270d63ce2bSvenki {
20280d63ce2bSvenki va_list ap;
20290d63ce2bSvenki
20300d63ce2bSvenki (void) mutex_lock(&snmpplugin_dbuf_lock);
20310d63ce2bSvenki
20320d63ce2bSvenki va_start(ap, fmt);
20330d63ce2bSvenki (void) vsnprintf(snmpplugin_lbuf, SNMPPLUGIN_DMAX_LINE, fmt, ap);
20340d63ce2bSvenki snmpplugin_log_append();
20350d63ce2bSvenki va_end(ap);
20360d63ce2bSvenki
20370d63ce2bSvenki (void) mutex_unlock(&snmpplugin_dbuf_lock);
20380d63ce2bSvenki }
20390d63ce2bSvenki
20400d63ce2bSvenki static void
snmpplugin_log_append(void)20410d63ce2bSvenki snmpplugin_log_append(void)
20420d63ce2bSvenki {
20430d63ce2bSvenki int len;
20440d63ce2bSvenki
20450d63ce2bSvenki len = strlen(snmpplugin_lbuf);
20460d63ce2bSvenki
20470d63ce2bSvenki if ((snmpplugin_dbuf_curp + len) >=
20480d63ce2bSvenki (snmpplugin_dbuf + snmpplugin_dbuf_sz)) {
20490d63ce2bSvenki snmpplugin_dbuf_realloc();
20500d63ce2bSvenki if (snmpplugin_dbuf == NULL) {
20510d63ce2bSvenki return;
20520d63ce2bSvenki }
20530d63ce2bSvenki }
20540d63ce2bSvenki
20550d63ce2bSvenki (void) strcpy(snmpplugin_dbuf_curp, snmpplugin_lbuf);
20560d63ce2bSvenki snmpplugin_dbuf_curp += len;
20570d63ce2bSvenki }
20580d63ce2bSvenki
20590d63ce2bSvenki static void
snmpplugin_dbuf_realloc(void)20600d63ce2bSvenki snmpplugin_dbuf_realloc(void)
20610d63ce2bSvenki {
20620d63ce2bSvenki char *p;
20630d63ce2bSvenki size_t offset = 0;
20640d63ce2bSvenki size_t count;
20650d63ce2bSvenki
20660d63ce2bSvenki count = snmpplugin_dbuf_sz + SNMPPLUGIN_DBLOCK_SZ;
20670d63ce2bSvenki if ((p = (char *)calloc(count, 1)) == NULL) {
20680d63ce2bSvenki snmpplugin_dbuf_overflow++;
20690d63ce2bSvenki snmpplugin_dbuf_curp = snmpplugin_dbuf;
20700d63ce2bSvenki return;
20710d63ce2bSvenki }
20720d63ce2bSvenki
20730d63ce2bSvenki if (snmpplugin_dbuf) {
20740d63ce2bSvenki offset = snmpplugin_dbuf_curp - snmpplugin_dbuf;
20750d63ce2bSvenki (void) memcpy(p, snmpplugin_dbuf, snmpplugin_dbuf_sz);
20760d63ce2bSvenki free(snmpplugin_dbuf);
20770d63ce2bSvenki }
20780d63ce2bSvenki
20790d63ce2bSvenki snmpplugin_dbuf = p;
20800d63ce2bSvenki snmpplugin_dbuf_sz += SNMPPLUGIN_DBLOCK_SZ;
20810d63ce2bSvenki
20820d63ce2bSvenki snmpplugin_dbuf_curp = snmpplugin_dbuf + offset;
20830d63ce2bSvenki }
20840d63ce2bSvenki #endif
2085