13941Svenki /* 23941Svenki * CDDL HEADER START 33941Svenki * 43941Svenki * The contents of this file are subject to the terms of the 53941Svenki * Common Development and Distribution License (the "License"). 63941Svenki * You may not use this file except in compliance with the License. 73941Svenki * 83941Svenki * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 93941Svenki * or http://www.opensolaris.org/os/licensing. 103941Svenki * See the License for the specific language governing permissions 113941Svenki * and limitations under the License. 123941Svenki * 133941Svenki * When distributing Covered Code, include this CDDL HEADER in each 143941Svenki * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 153941Svenki * If applicable, add the following below this CDDL HEADER, with the 163941Svenki * fields enclosed by brackets "[]" replaced with your own identifying 173941Svenki * information: Portions Copyright [yyyy] [name of copyright owner] 183941Svenki * 193941Svenki * CDDL HEADER END 203941Svenki */ 213941Svenki 223941Svenki /* 235995Sfw157321 * Copyright 2008 Sun Microsystems, Inc. All rights reserved. 243941Svenki * Use is subject to license terms. 253941Svenki */ 263941Svenki 273941Svenki /* 283941Svenki * The SNMP picl plugin connects to the agent on the SP and creates 293941Svenki * and populates the /physical-platform subtree in picl tree for use 303941Svenki * by picl consumers. 313941Svenki */ 323941Svenki 333941Svenki #include <stdio.h> 343941Svenki #include <stdlib.h> 353941Svenki #include <string.h> 363941Svenki #include <syslog.h> 373941Svenki #include <stdarg.h> 383941Svenki #include <libgen.h> 393941Svenki #include <libintl.h> 403941Svenki #include <thread.h> 413941Svenki #include <synch.h> 423941Svenki #include <errno.h> 437746SKelly.Moyer@Sun.COM #include <time.h> 443941Svenki 453941Svenki #include <picldefs.h> 463941Svenki #include <picl.h> 473941Svenki #include <picltree.h> 483941Svenki 493941Svenki #include "picloids.h" 503941Svenki #include "libpiclsnmp.h" 513941Svenki #include "snmpplugin.h" 523941Svenki 533941Svenki #pragma init(snmpplugin_register) /* place in .init section */ 543941Svenki 553941Svenki picld_plugin_reg_t snmpplugin_reg = { 563941Svenki PICLD_PLUGIN_VERSION_1, 573941Svenki PICLD_PLUGIN_NON_CRITICAL, 583941Svenki "snmp_plugin", 593941Svenki snmpplugin_init, 603941Svenki snmpplugin_fini 613941Svenki }; 623941Svenki 633941Svenki static picl_snmphdl_t hdl; 643941Svenki 653941Svenki /* 663941Svenki * The stale_tree_rwlp protects the stale_xxx vars. The 'stale_tree' flag 673941Svenki * and the 'rebuild_tree' flag below are both initialized to B_TRUE to 683941Svenki * let the tree_builder() thread build the initial tree without blocking. 693941Svenki */ 703941Svenki static rwlock_t stale_tree_rwlp; 713941Svenki static boolean_t stale_tree = B_TRUE; 723941Svenki 733941Svenki /* 743941Svenki * vol_props, volprop_ndx and n_vol_props are protected by the stale_tree 753941Svenki * flag. They are read only when the stale_tree flag is B_FALSE and written 763941Svenki * to only when the flag is B_TRUE. 773941Svenki * 783941Svenki * The change_time (last changed time) is read by only one thread at a 793941Svenki * time when stale_tree is B_FALSE (protected by stale_tree_rwlp). It is 803941Svenki * written by only one thread (the tree builder) when stale_tree is B_TRUE. 813941Svenki * 823941Svenki * Note that strictly speaking, change_time should be uint_t (timeticks32). 833941Svenki * But keeping it as int is fine, since we don't do any arithmetic on it 843941Svenki * except equality check. 853941Svenki */ 863941Svenki static vol_prophdl_t *vol_props = NULL; 873941Svenki static int volprop_ndx = 0, n_vol_props = 0; 883941Svenki static int change_time = 0; 895723Sfw157321 static time_t change_time_check; 903941Svenki 913941Svenki /* 923941Svenki * The rebuild_tree_lock and cv are used by the tree builder thread. 933941Svenki * rebuild_tree has to be initialized to B_TRUE to let the tree_builder 943941Svenki * do the first build without blocking. 953941Svenki */ 963941Svenki static mutex_t rebuild_tree_lock; 973941Svenki static cond_t rebuild_tree_cv; 983941Svenki static boolean_t rebuild_tree = B_TRUE; 995029Sfw157321 static boolean_t tree_builder_thr_exit = B_FALSE; 1005029Sfw157321 static thread_t tree_builder_thr_id; 1013941Svenki 1023941Svenki /* 1037746SKelly.Moyer@Sun.COM * The cache_refresh thread periodically queries the snmp cache refresh work 1047746SKelly.Moyer@Sun.COM * queue and processes jobs from it to keep cache entries from expiring. It 1057746SKelly.Moyer@Sun.COM * attempts to run in cycles of CACHE_REFRESH_CYCLE seconds each, first 1067746SKelly.Moyer@Sun.COM * processing cache refresh jobs and then sleeping for the remainder of the 1077746SKelly.Moyer@Sun.COM * cycle once the next refresh job expiration is at least 1087746SKelly.Moyer@Sun.COM * CACHE_REFRESH_MIN_WINDOW seconds in the future. 1097746SKelly.Moyer@Sun.COM * 1107746SKelly.Moyer@Sun.COM * NOTE: By using a thread to keep the SNMP cache refreshed in the background, 1117746SKelly.Moyer@Sun.COM * we are both adding load to the system and reducing the system's ability to 1127746SKelly.Moyer@Sun.COM * operate in power-saving mode when there is minimal load. While these 1137746SKelly.Moyer@Sun.COM * tradeoffs are acceptable at this time in light of customer concerns about 1147746SKelly.Moyer@Sun.COM * performance, it may be desirable in the future to move this work into the 1157746SKelly.Moyer@Sun.COM * firmware. Also, while the current cycle times performed well on the largest 1167746SKelly.Moyer@Sun.COM * sun4v config currently available (Batoka), they may need to be revisited for 1177746SKelly.Moyer@Sun.COM * future systems if the number of sensors increases significantly. 1187746SKelly.Moyer@Sun.COM */ 1197746SKelly.Moyer@Sun.COM #define CACHE_REFRESH_CYCLE 60 1207746SKelly.Moyer@Sun.COM #define CACHE_REFRESH_MIN_WINDOW 75 1217746SKelly.Moyer@Sun.COM static mutex_t cache_refresh_lock; 1227746SKelly.Moyer@Sun.COM static cond_t cache_refresh_cv; 1237746SKelly.Moyer@Sun.COM static boolean_t cache_refresh_thr_exit = B_FALSE; 1247746SKelly.Moyer@Sun.COM static thread_t cache_refresh_thr_id; 1257746SKelly.Moyer@Sun.COM 1267746SKelly.Moyer@Sun.COM /* 1273941Svenki * These two should really not be global 1283941Svenki */ 1293941Svenki static picl_nodehdl_t *physplat_nodes = NULL; 1303941Svenki static int n_physplat_nodes = 0; 1313941Svenki 1323941Svenki static char *group1[] = { 1333941Svenki OID_entPhysicalDescr, 1343941Svenki OID_entPhysicalContainedIn, 1353941Svenki OID_entPhysicalClass, 1363941Svenki OID_entPhysicalName, 1373941Svenki OID_entPhysicalHardwareRev, 1383941Svenki OID_entPhysicalFirmwareRev, 1393941Svenki OID_entPhysicalSerialNum, 1403941Svenki OID_entPhysicalMfgName, 1413941Svenki OID_entPhysicalModelName, 1423941Svenki OID_entPhysicalIsFRU, 1433941Svenki 0 1443941Svenki }; 1453941Svenki 1463941Svenki static char *group2[] = { 1473941Svenki OID_sunPlatEquipmentHolderAcceptableTypes, 1483941Svenki OID_sunPlatCircuitPackReplaceable, 1493941Svenki OID_sunPlatCircuitPackHotSwappable, 1503941Svenki OID_sunPlatPhysicalClass, 1513941Svenki OID_sunPlatSensorClass, 1523941Svenki OID_sunPlatSensorType, 1533941Svenki OID_sunPlatAlarmType, 1543941Svenki OID_sunPlatPowerSupplyClass, 1553941Svenki 0 1563941Svenki }; 1573941Svenki 1585723Sfw157321 static char *group3[] = { 1595723Sfw157321 OID_sunPlatNumericSensorEnabledThresholds, 1605723Sfw157321 OID_sunPlatNumericSensorBaseUnits, 1615723Sfw157321 OID_sunPlatNumericSensorRateUnits, 1625723Sfw157321 0 1635723Sfw157321 }; 1645723Sfw157321 1655723Sfw157321 static char *group4[] = { 1665723Sfw157321 OID_sunPlatBinarySensorInterpretTrue, 1675723Sfw157321 OID_sunPlatBinarySensorInterpretFalse, 1685723Sfw157321 }; 1695723Sfw157321 1703941Svenki static char *volgroup1[] = { 1713941Svenki OID_sunPlatBinarySensorCurrent, 1723941Svenki OID_sunPlatBinarySensorExpected, 1733941Svenki 0 1743941Svenki }; 1753941Svenki 1763941Svenki static char *volgroup2[] = { 1773941Svenki OID_sunPlatNumericSensorExponent, 1783941Svenki OID_sunPlatNumericSensorCurrent, 1793941Svenki OID_sunPlatNumericSensorLowerThresholdFatal, 1803941Svenki OID_sunPlatNumericSensorLowerThresholdCritical, 1813941Svenki OID_sunPlatNumericSensorLowerThresholdNonCritical, 1823941Svenki OID_sunPlatNumericSensorUpperThresholdNonCritical, 1833941Svenki OID_sunPlatNumericSensorUpperThresholdCritical, 1843941Svenki OID_sunPlatNumericSensorUpperThresholdFatal, 1853941Svenki 0 1863941Svenki }; 1873941Svenki 1885723Sfw157321 static char *volgroup3[] = { 1895723Sfw157321 OID_sunPlatEquipmentOperationalState, 1905723Sfw157321 0 1915723Sfw157321 }; 1925723Sfw157321 1935723Sfw157321 static char *volgroup4[] = { 1945723Sfw157321 OID_sunPlatAlarmState, 1955723Sfw157321 0 1965723Sfw157321 }; 1975723Sfw157321 1985723Sfw157321 static char *volgroup5[] = { 1995723Sfw157321 OID_sunPlatBatteryStatus, 2005723Sfw157321 0 2015723Sfw157321 }; 2025723Sfw157321 2033941Svenki /* 2043941Svenki * The following two items must match the Sun Platform MIB specification 2053941Svenki * in their indices and values. 2063941Svenki */ 2073941Svenki static char *sensor_baseunits[] = { 2083941Svenki "", "other", "unknown", "degC", "degF", "degK", "volts", "amps", 2093941Svenki "watts", "joules", "coulombs", "va", "nits", "lumens", "lux", 2103941Svenki "candelas", "kPa", "psi", "newtons", "cfm", "rpm", "hertz", 2113941Svenki "seconds", "minutes", "hours", "days", "weeks", "mils", "inches", 2123941Svenki "feet", "cubicInches", "cubicFeet", "meters", "cubicCentimeters", 2133941Svenki "cubicMeters", "liters", "fluidOunces", "radians", "steradians", 2143941Svenki "revolutions", "cycles", "gravities", "ounces", "pounds", "footPounds", 2153941Svenki "ounceInches", "gauss", "gilberts", "henries", "farads", "ohms", 2163941Svenki "siemens", "moles", "becquerels", "ppm", "decibels", "dBA", "dbC", 2173941Svenki "grays", "sieverts", "colorTemperatureDegK", "bits", "bytes", "words", 2183941Svenki "doubleWords", "quadWords", "percentage" 2193941Svenki }; 2203941Svenki static const int n_baseunits = sizeof (sensor_baseunits) / sizeof (char *); 2213941Svenki 2223941Svenki static char *sensor_rateunits[] = { 2233941Svenki "", 2243941Svenki "none", 2253941Svenki "perMicroSecond", 2263941Svenki "perMilliSecond", 2273941Svenki "perSecond", 2283941Svenki "perMinute", 2293941Svenki "perHour", 2303941Svenki "perDay", 2313941Svenki "perWeek", 2323941Svenki "perMonth", 2333941Svenki "perYear" 2343941Svenki }; 2353941Svenki static const int n_rateunits = sizeof (sensor_rateunits) / sizeof (char *); 2363941Svenki 2373941Svenki /* 2383941Svenki * Local declarations 2393941Svenki */ 2403941Svenki static void snmpplugin_register(void); 2413941Svenki static void register_group(char **g, int is_volatile); 2423941Svenki static void *tree_builder(void *arg); 2433941Svenki static int build_physplat(picl_nodehdl_t *subtree_rootp); 2443941Svenki static void free_resources(picl_nodehdl_t subtree_root); 2453941Svenki 2463941Svenki static picl_nodehdl_t make_node(picl_nodehdl_t subtree_root, int row, 2473941Svenki int *snmp_syserr_p); 2483941Svenki static void save_nodeh(picl_nodehdl_t nodeh, int row); 2493941Svenki static picl_nodehdl_t lookup_nodeh(int row); 2503941Svenki 2513941Svenki static void save_volprop(picl_prophdl_t prop, char *oidstr, int row, 2523941Svenki int proptype); 2535723Sfw157321 static void check_for_stale_data(boolean_t nocache); 2543941Svenki static int read_volprop(ptree_rarg_t *parg, void *buf); 2553941Svenki 2563941Svenki static void threshold(picl_nodehdl_t node, char *oidstr, int row, 2573941Svenki char *propname, int *snmp_syserr_p); 2583941Svenki static void add_thresholds(picl_nodehdl_t node, int row, int *snmp_syserr_p); 2593941Svenki 2603941Svenki static char *get_slot_type(int row, int *snmp_syserr_p); 2613941Svenki static int add_volatile_prop(picl_nodehdl_t nodeh, char *name, 2623941Svenki int type, int access, int size, int (*rdfunc)(ptree_rarg_t *, void *), 2633941Svenki int (*wrfunc)(ptree_warg_t *, const void *), picl_prophdl_t *propp); 2643941Svenki static int add_string_prop(picl_nodehdl_t node, char *propname, char *propval); 2653941Svenki static int add_void_prop(picl_nodehdl_t node, char *propname); 2663941Svenki static void add_prop(picl_nodehdl_t nodeh, picl_prophdl_t *php, char *label, 2673941Svenki int row, sp_propid_t pp, int *snmp_syserr_p); 2683941Svenki 2697746SKelly.Moyer@Sun.COM static void *cache_refresher(void *arg); 2707746SKelly.Moyer@Sun.COM static void cache_refresher_fini(void); 2717746SKelly.Moyer@Sun.COM 2723941Svenki static void log_msg(int pri, const char *fmt, ...); 2733941Svenki 2743941Svenki #ifdef SNMPPLUGIN_DEBUG 2753941Svenki static mutex_t snmpplugin_dbuf_lock; 2763941Svenki static char *snmpplugin_dbuf = NULL; 2773941Svenki static char *snmpplugin_dbuf_curp = NULL; 2783941Svenki static int snmpplugin_dbuf_sz = 0; 2793941Svenki static int snmpplugin_dbuf_overflow = 0; 2803941Svenki static char snmpplugin_lbuf[SNMPPLUGIN_DMAX_LINE]; 2813941Svenki 2823941Svenki static void snmpplugin_log_init(void); 2833941Svenki static void snmpplugin_log(const char *fmt, ...); 2843941Svenki static void snmpplugin_log_append(void); 2853941Svenki static void snmpplugin_dbuf_realloc(void); 2863941Svenki #endif 2873941Svenki 2883941Svenki static void 2893941Svenki snmpplugin_register(void) 2903941Svenki { 2913941Svenki (void) picld_plugin_register(&snmpplugin_reg); 2923941Svenki } 2933941Svenki 2943941Svenki static void 2953941Svenki register_group(char **g, int is_volatile) 2963941Svenki { 2973941Svenki int i, len = 0; 2983941Svenki int n_oids; 2993941Svenki char *p, *oidstrs; 3003941Svenki 3013941Svenki for (i = 0; g[i]; i++) 3023941Svenki len += strlen(g[i]) + 1; 3033941Svenki n_oids = i; 3043941Svenki 3053941Svenki if ((oidstrs = (char *)calloc(1, len)) == NULL) 3063941Svenki return; 3073941Svenki 3083941Svenki for (p = oidstrs, i = 0; g[i]; i++) { 3093941Svenki (void) strcpy(p, g[i]); 3103941Svenki p += strlen(g[i]) + 1; 3113941Svenki } 3123941Svenki 3133941Svenki snmp_register_group(hdl, oidstrs, n_oids, is_volatile); 3147382SMichael.Bergknoff@Sun.COM free(oidstrs); 3153941Svenki } 3163941Svenki 3173941Svenki void 3183941Svenki snmpplugin_init(void) 3193941Svenki { 3203941Svenki int ret; 3213941Svenki 3223941Svenki (void) mutex_init(&rebuild_tree_lock, USYNC_THREAD, NULL); 3233941Svenki (void) cond_init(&rebuild_tree_cv, USYNC_THREAD, NULL); 3243941Svenki (void) rwlock_init(&stale_tree_rwlp, USYNC_THREAD, NULL); 3255029Sfw157321 tree_builder_thr_exit = B_FALSE; 3265029Sfw157321 3273941Svenki LOGINIT(); 3283941Svenki 3293941Svenki /* 3303941Svenki * Create the tree-builder thread and let it take over 3313941Svenki */ 3323941Svenki LOGPRINTF("Tree-builder thread being created.\n"); 3333941Svenki if ((ret = thr_create(NULL, NULL, tree_builder, NULL, 3345029Sfw157321 THR_BOUND, &tree_builder_thr_id)) < 0) { 3353941Svenki log_msg(LOG_ERR, SNMPP_CANT_CREATE_TREE_BUILDER, ret); 3363941Svenki snmp_fini(hdl); 3375029Sfw157321 hdl = NULL; 3385029Sfw157321 (void) rwlock_destroy(&stale_tree_rwlp); 3395029Sfw157321 (void) cond_destroy(&rebuild_tree_cv); 3405029Sfw157321 (void) mutex_destroy(&rebuild_tree_lock); 3415029Sfw157321 tree_builder_thr_exit = B_TRUE; 3427746SKelly.Moyer@Sun.COM 3437746SKelly.Moyer@Sun.COM return; 3447746SKelly.Moyer@Sun.COM } 3457746SKelly.Moyer@Sun.COM 3467746SKelly.Moyer@Sun.COM /* 3477746SKelly.Moyer@Sun.COM * While the cache refresher thread does improve performance, it is not 3487746SKelly.Moyer@Sun.COM * integral to the proper function of the plugin. If we fail to create 3497746SKelly.Moyer@Sun.COM * the thread for some reason, we will simply continue without 3507746SKelly.Moyer@Sun.COM * refreshing. 3517746SKelly.Moyer@Sun.COM */ 3527746SKelly.Moyer@Sun.COM (void) mutex_init(&cache_refresh_lock, USYNC_THREAD, NULL); 3537746SKelly.Moyer@Sun.COM (void) cond_init(&cache_refresh_cv, USYNC_THREAD, NULL); 3547746SKelly.Moyer@Sun.COM cache_refresh_thr_exit = B_FALSE; 3557746SKelly.Moyer@Sun.COM 3567746SKelly.Moyer@Sun.COM LOGPRINTF("Cache refresher thread being created.\n"); 3577746SKelly.Moyer@Sun.COM if (thr_create(NULL, NULL, cache_refresher, NULL, THR_BOUND, 3587746SKelly.Moyer@Sun.COM &cache_refresh_thr_id) < 0) { 3597746SKelly.Moyer@Sun.COM (void) cond_destroy(&cache_refresh_cv); 3607746SKelly.Moyer@Sun.COM (void) mutex_destroy(&cache_refresh_lock); 3617746SKelly.Moyer@Sun.COM cache_refresh_thr_exit = B_TRUE; 3623941Svenki } 3633941Svenki } 3643941Svenki 3653941Svenki void 3663941Svenki snmpplugin_fini(void) 3673941Svenki { 3685029Sfw157321 3695029Sfw157321 if (tree_builder_thr_exit == B_TRUE) 3705029Sfw157321 return; 3713941Svenki 3725029Sfw157321 /* 3735029Sfw157321 * Make reads of volatile properties return PICL_PROPUNAVAILABLE 3745029Sfw157321 * since we're about to recycle the plug-in. No need to worry 3755029Sfw157321 * about removing /physical-platform since tree_builder() will 3765029Sfw157321 * take care of recycling it for us. 3775029Sfw157321 */ 3785029Sfw157321 (void) rw_wrlock(&stale_tree_rwlp); 3795029Sfw157321 stale_tree = B_TRUE; 3805029Sfw157321 if (vol_props) { 3815029Sfw157321 free(vol_props); 3825029Sfw157321 } 3835029Sfw157321 vol_props = NULL; 3845029Sfw157321 volprop_ndx = 0; 3855029Sfw157321 n_vol_props = 0; 3865029Sfw157321 (void) rw_unlock(&stale_tree_rwlp); 3875029Sfw157321 3887746SKelly.Moyer@Sun.COM /* clean up the cache_refresher thread and structures */ 3897746SKelly.Moyer@Sun.COM cache_refresher_fini(); 3907746SKelly.Moyer@Sun.COM 3915029Sfw157321 /* wake up the tree_builder thread, tell it to exit */ 3925029Sfw157321 (void) mutex_lock(&rebuild_tree_lock); 3935029Sfw157321 rebuild_tree = B_TRUE; 3945029Sfw157321 tree_builder_thr_exit = B_TRUE; 3955436Sfw157321 (void) cond_signal(&rebuild_tree_cv); 3965029Sfw157321 (void) mutex_unlock(&rebuild_tree_lock); 3975029Sfw157321 3985029Sfw157321 /* reap the thread */ 3995029Sfw157321 (void) thr_join(tree_builder_thr_id, NULL, NULL); 4005029Sfw157321 4015029Sfw157321 /* close the channel */ 4025029Sfw157321 if (hdl != NULL) { 4035029Sfw157321 snmp_fini(hdl); 4045029Sfw157321 hdl = NULL; 4055029Sfw157321 } 4065029Sfw157321 4075029Sfw157321 /* finish cleanup... */ 4083941Svenki (void) rwlock_destroy(&stale_tree_rwlp); 4093941Svenki (void) cond_destroy(&rebuild_tree_cv); 4103941Svenki (void) mutex_destroy(&rebuild_tree_lock); 4113941Svenki } 4123941Svenki 4133941Svenki /*ARGSUSED*/ 4143941Svenki static void * 4153941Svenki tree_builder(void *arg) 4163941Svenki { 4173941Svenki int ret, rv; 4183941Svenki picl_nodehdl_t root_node; 4193941Svenki picl_nodehdl_t physplat_root; 4203941Svenki picl_nodehdl_t old_physplat_root; 4213941Svenki 4223941Svenki /* 4233941Svenki * Initialize SNMP service 4243941Svenki */ 4253941Svenki LOGPRINTF("Initializing SNMP service.\n"); 4263941Svenki if ((hdl = snmp_init()) == NULL) { 4273941Svenki log_msg(LOG_ERR, SNMPP_CANT_INIT); 4283941Svenki return ((void *)-1); 4293941Svenki } 4303941Svenki 4313941Svenki /* 4323941Svenki * Register OID groupings for BULKGET optimizations 4333941Svenki */ 4343941Svenki LOGPRINTF("Registering OID groups.\n"); 4353941Svenki register_group(group1, 0); 4363941Svenki register_group(group2, 0); 4375723Sfw157321 register_group(group3, 0); 4385723Sfw157321 register_group(group4, 0); 4393941Svenki register_group(volgroup1, 1); 4403941Svenki register_group(volgroup2, 1); 4415723Sfw157321 register_group(volgroup3, 1); 4425723Sfw157321 register_group(volgroup4, 1); 4435723Sfw157321 register_group(volgroup5, 1); 4443941Svenki 4453941Svenki (void) mutex_lock(&rebuild_tree_lock); 4463941Svenki 4473941Svenki for (;;) { 4483941Svenki LOGPRINTF("tree_builder: check whether to rebuild subtree\n"); 4493941Svenki while (rebuild_tree == B_FALSE) 4503941Svenki (void) cond_wait(&rebuild_tree_cv, &rebuild_tree_lock); 4513941Svenki 4523941Svenki LOGPRINTF("tree_builder: woke up\n"); 4533941Svenki 4545029Sfw157321 if (tree_builder_thr_exit == B_TRUE) { 4555029Sfw157321 (void) mutex_unlock(&rebuild_tree_lock); 4565029Sfw157321 LOGPRINTF("tree_builder: time to exit\n"); 4575029Sfw157321 return (NULL); 4585029Sfw157321 } 4595029Sfw157321 4603941Svenki old_physplat_root = NULL; 4613941Svenki physplat_root = NULL; 4623941Svenki 4633941Svenki LOGPRINTF("tree_builder: getting root node\n"); 4643941Svenki if ((ret = ptree_get_root(&root_node)) != PICL_SUCCESS) { 4655029Sfw157321 (void) mutex_unlock(&rebuild_tree_lock); 4663941Svenki log_msg(LOG_ERR, SNMPP_NO_ROOT, ret); 4673941Svenki return ((void *)-2); 4683941Svenki } 4693941Svenki 4703941Svenki LOGPRINTF("tree_builder: getting existing physplat node\n"); 4713941Svenki rv = ptree_find_node(root_node, PICL_PROP_NAME, 4723941Svenki PICL_PTYPE_CHARSTRING, PICL_NODE_PHYSPLAT, 4733941Svenki sizeof (PICL_NODE_PHYSPLAT), &old_physplat_root); 4743941Svenki 4753941Svenki LOGPRINTF("tree_builder: building physical-platform\n"); 4763941Svenki if ((ret = build_physplat(&physplat_root)) < 0) { 4775029Sfw157321 (void) mutex_unlock(&rebuild_tree_lock); 4783941Svenki log_msg(LOG_ERR, SNMPP_CANT_CREATE_PHYSPLAT, ret); 4797746SKelly.Moyer@Sun.COM cache_refresher_fini(); 4803941Svenki snmp_fini(hdl); 4815029Sfw157321 hdl = NULL; 4823941Svenki return ((void *)-3); 4833941Svenki } 4843941Svenki 4853941Svenki if (rv == PICL_SUCCESS && old_physplat_root != NULL) { 4863941Svenki LOGPRINTF("tree_builder: destroying existing nodes\n"); 4873941Svenki ptree_delete_node(old_physplat_root); 4883941Svenki ptree_destroy_node(old_physplat_root); 4893941Svenki } 4903941Svenki 4913941Svenki LOGPRINTF("tree_builder: attaching new subtree\n"); 4923941Svenki if ((ret = ptree_add_node(root_node, physplat_root)) < 0) { 4935029Sfw157321 (void) mutex_unlock(&rebuild_tree_lock); 4943941Svenki free_resources(physplat_root); 4953941Svenki log_msg(LOG_ERR, SNMPP_CANT_CREATE_PHYSPLAT, ret); 4967746SKelly.Moyer@Sun.COM cache_refresher_fini(); 4973941Svenki snmp_fini(hdl); 4985029Sfw157321 hdl = NULL; 4993941Svenki return ((void *)-4); 5003941Svenki } 5013941Svenki 5023941Svenki LOGPRINTF("tree_builder: setting stale_tree to FALSE\n"); 5033941Svenki (void) rw_wrlock(&stale_tree_rwlp); 5043941Svenki stale_tree = B_FALSE; 5053941Svenki (void) rw_unlock(&stale_tree_rwlp); 5063941Svenki 5073941Svenki LOGPRINTF("tree_builder: setting rebuild_tree to FALSE\n"); 5083941Svenki rebuild_tree = B_FALSE; 5093941Svenki } 5103941Svenki 5113941Svenki /*NOTREACHED*/ 5123941Svenki return (NULL); 5133941Svenki } 5143941Svenki 5153941Svenki static int 5163941Svenki build_physplat(picl_nodehdl_t *subtree_rootp) 5173941Svenki { 5183941Svenki int change_time1; 5193941Svenki int row, nxtrow; 5203941Svenki int clr_linkreset = 0; 5213941Svenki int ret = 0; 5223941Svenki int snmp_syserr = 0; 5233941Svenki 5243941Svenki retry: 5253941Svenki (void) snmp_reinit(hdl, clr_linkreset); 5263941Svenki clr_linkreset = 0; 5273941Svenki 5283941Svenki /* 5293941Svenki * Record LastChangeTime before we start building the tree 5303941Svenki */ 5313941Svenki ret = snmp_get_int(hdl, OID_entLastChangeTime, 0, 5323941Svenki &change_time1, &snmp_syserr); 5333941Svenki if (ret < 0) { 5343941Svenki if (snmp_syserr == ECANCELED) { 5356751Sfw157321 LOGPRINTF(SNMPP_LINK_RESET); 5363941Svenki clr_linkreset = 1; 5373941Svenki goto retry; 5385723Sfw157321 } 5395723Sfw157321 log_msg(LOG_WARNING, SNMPP_CANT_FETCH_OBJECT_VAL, 5405723Sfw157321 snmp_syserr ? snmp_syserr : ret, OID_entLastChangeTime, 0); 5413941Svenki } 5423941Svenki 5433941Svenki /* 5443941Svenki * Create the physical-platform node 5453941Svenki */ 5463941Svenki ret = ptree_create_node(PICL_NODE_PHYSPLAT, PICL_CLASS_PICL, 5473941Svenki subtree_rootp); 5483941Svenki if (ret != PICL_SUCCESS) 5493941Svenki return (-1); 5503941Svenki 5513941Svenki /* 5523941Svenki * Scan entPhysicalTable and build the "physical-platform" subtree 5533941Svenki */ 5543941Svenki ret = 0; 5553941Svenki for (row = -1; ret == 0; row = nxtrow) { 5563941Svenki ret = snmp_get_nextrow(hdl, OID_entPhysicalDescr, 5573941Svenki row, &nxtrow, &snmp_syserr); 5585995Sfw157321 if (ret == 0) 5593941Svenki (void) make_node(*subtree_rootp, nxtrow, &snmp_syserr); 5605995Sfw157321 switch (snmp_syserr) { 5615995Sfw157321 case ECANCELED: 5623941Svenki /* 5633941Svenki * If we get this error, a link reset must've 5643941Svenki * happened and we need to throw away everything 5653941Svenki * we have now and rebuild the tree again. 5663941Svenki */ 5673941Svenki log_msg(LOG_WARNING, SNMPP_LINK_RESET); 5683941Svenki free_resources(*subtree_rootp); 5693941Svenki clr_linkreset = 1; 5703941Svenki goto retry; 5715995Sfw157321 /*NOTREACHED*/ 5725995Sfw157321 break; 5735995Sfw157321 case ENOSPC: /* end of MIB */ 5745995Sfw157321 LOGPRINTF("build_physplat: end of MIB\n"); 5755995Sfw157321 break; 5765995Sfw157321 case ENOENT: /* end of table */ 5775995Sfw157321 LOGPRINTF("build_physplat: end of table\n"); 5785995Sfw157321 break; 5795995Sfw157321 default: 5805995Sfw157321 /* 5815995Sfw157321 * make_node() will print messages so don't 5825995Sfw157321 * repeat that exercise here. 5835995Sfw157321 */ 5845995Sfw157321 if (ret == -1) { 5855995Sfw157321 log_msg(LOG_WARNING, 5865995Sfw157321 SNMPP_CANT_FETCH_OBJECT_VAL, 5875995Sfw157321 snmp_syserr ? snmp_syserr : ret, 5885995Sfw157321 OID_entPhysicalDescr, row); 5895995Sfw157321 } 5903941Svenki } 5913941Svenki } 5923941Svenki 5933941Svenki /* 5943941Svenki * Record LastChangeTime after we're done building the tree 5953941Svenki */ 5963941Svenki ret = snmp_get_int(hdl, OID_entLastChangeTime, 0, 5973941Svenki &change_time, &snmp_syserr); 5983941Svenki if (ret < 0) { 5993941Svenki if (snmp_syserr == ECANCELED) { 6003941Svenki log_msg(LOG_WARNING, SNMPP_LINK_RESET); 6013941Svenki free_resources(*subtree_rootp); 6023941Svenki clr_linkreset = 1; 6033941Svenki goto retry; 6043941Svenki } else 6055723Sfw157321 log_msg(LOG_WARNING, SNMPP_CANT_FETCH_OBJECT_VAL, 6065723Sfw157321 snmp_syserr ? snmp_syserr : ret, 6075723Sfw157321 OID_entLastChangeTime, row); 6083941Svenki } 6093941Svenki 6103941Svenki /* 6113941Svenki * If they don't match, some hotplugging must've happened, 6123941Svenki * free resources we've created and still holding, then go 6133941Svenki * back and retry 6143941Svenki */ 6153941Svenki if (change_time != change_time1) { 6163941Svenki LOGPRINTF("build_physplat: entLastChangeTime has changed!\n"); 6173941Svenki free_resources(*subtree_rootp); 6183941Svenki change_time1 = change_time; 6193941Svenki goto retry; 6203941Svenki } 6213941Svenki 6223941Svenki /* 6233941Svenki * The physplat_nodes table is no longer needed, free it 6243941Svenki */ 6253941Svenki if (physplat_nodes) { 6263941Svenki free(physplat_nodes); 6273941Svenki physplat_nodes = NULL; 6283941Svenki n_physplat_nodes = 0; 6293941Svenki } 6303941Svenki 6313941Svenki return (0); 6323941Svenki } 6333941Svenki 6343941Svenki /* 6353941Svenki * Destroy all resources that were created during the building 6363941Svenki * of the subtree 6373941Svenki */ 6383941Svenki static void 6393941Svenki free_resources(picl_nodehdl_t subtree_root) 6403941Svenki { 6413941Svenki if (physplat_nodes) { 6423941Svenki free(physplat_nodes); 6433941Svenki physplat_nodes = NULL; 6443941Svenki n_physplat_nodes = 0; 6453941Svenki } 6463941Svenki 6473941Svenki if (subtree_root) { 6483941Svenki (void) ptree_delete_node(subtree_root); 6493941Svenki (void) ptree_destroy_node(subtree_root); 6503941Svenki } 6513941Svenki 6523941Svenki if (vol_props) { 6533941Svenki free(vol_props); 6543941Svenki n_vol_props = 0; 6553941Svenki volprop_ndx = 0; 6563941Svenki } 6573941Svenki } 6583941Svenki 6593941Svenki static picl_nodehdl_t 6603941Svenki make_node(picl_nodehdl_t subtree_root, int row, int *snmp_syserr_p) 6613941Svenki { 6623941Svenki picl_nodehdl_t nodeh, parenth; 6633941Svenki picl_prophdl_t proph; 6643941Svenki char *phys_name, *node_name; 6653941Svenki int parent_row; 6663941Svenki int ent_physclass, sunplat_physclass; 6673941Svenki int sensor_class, sensor_type; 6683941Svenki int alarm_type; 6693941Svenki int ps_class; 6703941Svenki int ret; 6713941Svenki 6723941Svenki /* 6733941Svenki * If we've already created this picl node, just return it 6743941Svenki */ 6753941Svenki if ((nodeh = lookup_nodeh(row)) != NULL) 6763941Svenki return (nodeh); 6773941Svenki 6783941Svenki /* 6793941Svenki * If we are creating it only now, make sure we have the parent 6803941Svenki * created first; if there's no parent, then parent it to the 6813941Svenki * subtree's root node 6823941Svenki */ 6833941Svenki ret = snmp_get_int(hdl, OID_entPhysicalContainedIn, row, 6843941Svenki &parent_row, snmp_syserr_p); 6853941Svenki CHECK_LINKRESET(snmp_syserr_p, NULL) 6863941Svenki if (ret < 0 || parent_row <= 0) 6873941Svenki parenth = subtree_root; 6883941Svenki else { 6893941Svenki parenth = make_node(subtree_root, parent_row, snmp_syserr_p); 6903941Svenki CHECK_LINKRESET(snmp_syserr_p, NULL) 6913941Svenki if (parenth == NULL) 6923941Svenki parenth = subtree_root; 6933941Svenki } 6943941Svenki 6953941Svenki /* 6963941Svenki * Figure out the physical-platform node name from entPhysicalName; 6973941Svenki * all rows in the MIB that have a valid entPhysicalIndex should 6983941Svenki * have a physical name. 6993941Svenki */ 7003941Svenki ret = snmp_get_str(hdl, OID_entPhysicalName, row, 7013941Svenki &phys_name, snmp_syserr_p); 7023941Svenki CHECK_LINKRESET(snmp_syserr_p, NULL) 7033941Svenki if (ret < 0 || phys_name == NULL) { 7043941Svenki log_msg(LOG_WARNING, SNMPP_NO_ENTPHYSNAME, row); 7053941Svenki return (NULL); 7063941Svenki } 7073941Svenki 7083941Svenki node_name = basename(phys_name); 7093941Svenki 7103941Svenki ret = snmp_get_int(hdl, OID_entPhysicalClass, row, 7113941Svenki &ent_physclass, snmp_syserr_p); 7123941Svenki CHECK_LINKRESET(snmp_syserr_p, NULL) 7133941Svenki if (ret < 0) { 7145723Sfw157321 log_msg(LOG_WARNING, SNMPP_CANT_FETCH_OBJECT_VAL, 7155723Sfw157321 *snmp_syserr_p ? *snmp_syserr_p : ret, 7165723Sfw157321 OID_entPhysicalClass, row); 7173941Svenki free(phys_name); 7183941Svenki return (NULL); 7193941Svenki } 7203941Svenki 7213941Svenki switch (ent_physclass) { 7223941Svenki case SPC_OTHER: 7233941Svenki ret = snmp_get_int(hdl, OID_sunPlatPhysicalClass, row, 7243941Svenki &sunplat_physclass, snmp_syserr_p); 7253941Svenki CHECK_LINKRESET(snmp_syserr_p, NULL) 7263941Svenki if (ret < 0) { 7275723Sfw157321 log_msg(LOG_WARNING, SNMPP_CANT_FETCH_OBJECT_VAL, 7285723Sfw157321 *snmp_syserr_p ? *snmp_syserr_p : ret, 7295723Sfw157321 OID_sunPlatPhysicalClass, row); 7303941Svenki free(phys_name); 7313941Svenki return (NULL); 7323941Svenki } 7333941Svenki 7343941Svenki if (sunplat_physclass == SSPC_ALARM) { 7353941Svenki ret = snmp_get_int(hdl, OID_sunPlatAlarmType, 7363941Svenki row, &alarm_type, snmp_syserr_p); 7373941Svenki CHECK_LINKRESET(snmp_syserr_p, NULL) 7383941Svenki if (ret < 0) { 7393941Svenki log_msg(LOG_WARNING, 7405723Sfw157321 SNMPP_CANT_FETCH_OBJECT_VAL, 7415723Sfw157321 *snmp_syserr_p ? *snmp_syserr_p : ret, 7425723Sfw157321 OID_sunPlatAlarmType, row); 7433941Svenki free(phys_name); 7443941Svenki return (NULL); 7453941Svenki } 7463941Svenki 7473941Svenki if (alarm_type == SSAT_VISIBLE) { 7484802Sfw157321 ADD_NODE(PICL_CLASS_LED) 7493941Svenki } else { 7504802Sfw157321 ADD_NODE(PICL_CLASS_ALARM) 7513941Svenki } 7523941Svenki 7533941Svenki add_prop(nodeh, &proph, node_name, row, PP_STATE, 7543941Svenki snmp_syserr_p); 7553941Svenki CHECK_LINKRESET(snmp_syserr_p, NULL) 7563941Svenki } else { 7573941Svenki ADD_NODE(PICL_CLASS_OTHER) 7583941Svenki } 7593941Svenki 7603941Svenki add_prop(nodeh, &proph, node_name, row, PP_OPSTATUS, 7613941Svenki snmp_syserr_p); 7623941Svenki CHECK_LINKRESET(snmp_syserr_p, NULL) 7633941Svenki break; 7643941Svenki 7653941Svenki case SPC_UNKNOWN: 7663941Svenki ADD_NODE(PICL_CLASS_UNKNOWN) 7673941Svenki break; 7683941Svenki 7693941Svenki case SPC_CHASSIS: 7703941Svenki ADD_NODE(PICL_CLASS_CHASSIS) 7713941Svenki add_prop(nodeh, &proph, node_name, row, PP_OPSTATUS, 7723941Svenki snmp_syserr_p); 7733941Svenki CHECK_LINKRESET(snmp_syserr_p, NULL) 7743941Svenki break; 7753941Svenki 7763941Svenki case SPC_BACKPLANE: 7773941Svenki ADD_NODE(PICL_CLASS_BACKPLANE) 7783941Svenki add_prop(nodeh, &proph, node_name, row, PP_OPSTATUS, 7793941Svenki snmp_syserr_p); 7803941Svenki CHECK_LINKRESET(snmp_syserr_p, NULL) 7813941Svenki break; 7823941Svenki 7833941Svenki case SPC_CONTAINER: 7843941Svenki ADD_NODE(PICL_CLASS_CONTAINER) 7853941Svenki 7863941Svenki add_prop(nodeh, &proph, node_name, row, PP_OPSTATUS, 7873941Svenki snmp_syserr_p); 7883941Svenki CHECK_LINKRESET(snmp_syserr_p, NULL) 7893941Svenki 7903941Svenki add_prop(nodeh, &proph, node_name, row, PP_SLOT_TYPE, 7913941Svenki snmp_syserr_p); 7923941Svenki CHECK_LINKRESET(snmp_syserr_p, NULL) 7933941Svenki break; 7943941Svenki 7953941Svenki case SPC_POWERSUPPLY: 7963941Svenki ret = snmp_get_int(hdl, OID_sunPlatPowerSupplyClass, 7973941Svenki row, &ps_class, snmp_syserr_p); 7983941Svenki CHECK_LINKRESET(snmp_syserr_p, NULL) 7993941Svenki if (ret < 0) { 8005723Sfw157321 log_msg(LOG_WARNING, SNMPP_CANT_FETCH_OBJECT_VAL, 8015723Sfw157321 *snmp_syserr_p ? *snmp_syserr_p : ret, 8025723Sfw157321 OID_sunPlatPowerSupplyClass, row); 8033941Svenki free(phys_name); 8043941Svenki return (NULL); 8053941Svenki } 8063941Svenki 8073941Svenki if (ps_class == SSPSC_BATTERY) { 8083941Svenki ADD_NODE(PICL_CLASS_BATTERY) 8093941Svenki add_prop(nodeh, &proph, node_name, row, 8103941Svenki PP_BATT_STATUS, snmp_syserr_p); 8113941Svenki CHECK_LINKRESET(snmp_syserr_p, NULL) 8123941Svenki } else { 8133941Svenki ADD_NODE(PICL_CLASS_POWERSUPPLY) 8143941Svenki } 8153941Svenki add_prop(nodeh, &proph, node_name, row, PP_OPSTATUS, 8163941Svenki snmp_syserr_p); 8173941Svenki CHECK_LINKRESET(snmp_syserr_p, NULL) 8183941Svenki break; 8193941Svenki 8203941Svenki case SPC_FAN: 8213941Svenki ADD_NODE(PICL_CLASS_FAN) 8223941Svenki add_prop(nodeh, &proph, node_name, row, PP_OPSTATUS, 8233941Svenki snmp_syserr_p); 8243941Svenki CHECK_LINKRESET(snmp_syserr_p, NULL) 8253941Svenki break; 8263941Svenki 8273941Svenki case SPC_SENSOR: 8283941Svenki ret = snmp_get_int(hdl, OID_sunPlatSensorClass, 8293941Svenki row, &sensor_class, snmp_syserr_p); 8303941Svenki CHECK_LINKRESET(snmp_syserr_p, NULL) 8313941Svenki if (ret < 0) { 8325723Sfw157321 log_msg(LOG_WARNING, SNMPP_CANT_FETCH_OBJECT_VAL, 8335723Sfw157321 *snmp_syserr_p ? *snmp_syserr_p : ret, 8345723Sfw157321 OID_sunPlatSensorClass, row); 8353941Svenki free(phys_name); 8363941Svenki return (NULL); 8373941Svenki } 8383941Svenki 8393941Svenki ret = snmp_get_int(hdl, OID_sunPlatSensorType, 8403941Svenki row, &sensor_type, snmp_syserr_p); 8413941Svenki CHECK_LINKRESET(snmp_syserr_p, NULL) 8423941Svenki if (ret < 0) { 8435723Sfw157321 log_msg(LOG_WARNING, SNMPP_CANT_FETCH_OBJECT_VAL, 8445723Sfw157321 *snmp_syserr_p ? *snmp_syserr_p : ret, 8455723Sfw157321 OID_sunPlatSensorType, row); 8463941Svenki free(phys_name); 8473941Svenki return (NULL); 8483941Svenki } 8493941Svenki 8503941Svenki if (sensor_class == SSSC_NUMERIC) { 8513941Svenki if (sensor_type == SSST_TEMPERATURE) { 8523941Svenki ADD_NODE(PICL_CLASS_TEMPERATURE_SENSOR) 8533941Svenki add_prop(nodeh, &proph, node_name, row, 8543941Svenki PP_TEMPERATURE, snmp_syserr_p); 8553941Svenki } else if (sensor_type == SSST_VOLTAGE) { 8563941Svenki ADD_NODE(PICL_CLASS_VOLTAGE_SENSOR) 8573941Svenki add_prop(nodeh, &proph, node_name, row, 8583941Svenki PP_VOLTAGE, snmp_syserr_p); 8593941Svenki } else if (sensor_type == SSST_CURRENT) { 8603941Svenki ADD_NODE(PICL_CLASS_CURRENT_SENSOR) 8613941Svenki add_prop(nodeh, &proph, node_name, row, 8623941Svenki PP_CURRENT, snmp_syserr_p); 8633941Svenki } else if (sensor_type == SSST_TACHOMETER) { 8643941Svenki ADD_NODE(PICL_CLASS_RPM_SENSOR) 8653941Svenki add_prop(nodeh, &proph, node_name, row, 8663941Svenki PP_SPEED, snmp_syserr_p); 8673941Svenki } else { 8683941Svenki ADD_NODE(PICL_CLASS_SENSOR) 8693941Svenki add_prop(nodeh, &proph, node_name, row, 8703941Svenki PP_SENSOR_VALUE, snmp_syserr_p); 8713941Svenki } 8723941Svenki CHECK_LINKRESET(snmp_syserr_p, NULL) 8733941Svenki 8743941Svenki add_prop(nodeh, &proph, node_name, row, 8753941Svenki PP_OPSTATUS, snmp_syserr_p); 8763941Svenki CHECK_LINKRESET(snmp_syserr_p, NULL) 8773941Svenki 8783941Svenki add_prop(nodeh, &proph, node_name, row, 8793941Svenki PP_BASE_UNITS, snmp_syserr_p); 8803941Svenki CHECK_LINKRESET(snmp_syserr_p, NULL) 8813941Svenki 8823941Svenki add_prop(nodeh, &proph, node_name, row, 8833941Svenki PP_EXPONENT, snmp_syserr_p); 8843941Svenki CHECK_LINKRESET(snmp_syserr_p, NULL) 8853941Svenki 8863941Svenki add_prop(nodeh, &proph, node_name, row, 8873941Svenki PP_RATE_UNITS, snmp_syserr_p); 8883941Svenki CHECK_LINKRESET(snmp_syserr_p, NULL) 8893941Svenki 8903941Svenki add_thresholds(nodeh, row, snmp_syserr_p); 8913941Svenki CHECK_LINKRESET(snmp_syserr_p, NULL) 8923941Svenki 8933941Svenki } else if (sensor_class == SSSC_BINARY) { 8943941Svenki if (sensor_type == SSST_TEMPERATURE) { 8953941Svenki ADD_NODE(PICL_CLASS_TEMPERATURE_INDICATOR) 8963941Svenki } else if (sensor_type == SSST_VOLTAGE) { 8973941Svenki ADD_NODE(PICL_CLASS_VOLTAGE_INDICATOR) 8983941Svenki } else if (sensor_type == SSST_CURRENT) { 8993941Svenki ADD_NODE(PICL_CLASS_CURRENT_INDICATOR) 9003941Svenki } else if (sensor_type == SSST_TACHOMETER) { 9013941Svenki ADD_NODE(PICL_CLASS_RPM_INDICATOR) 9023941Svenki } else if (sensor_type == SSST_PRESENCE) { 9033941Svenki ADD_NODE(PICL_CLASS_PRESENCE_INDICATOR) 9043941Svenki } else { 9053941Svenki ADD_NODE(PICL_CLASS_INDICATOR) 9063941Svenki } 9073941Svenki 9083941Svenki add_prop(nodeh, &proph, node_name, row, PP_OPSTATUS, 9093941Svenki snmp_syserr_p); 9103941Svenki CHECK_LINKRESET(snmp_syserr_p, NULL) 9113941Svenki 9123941Svenki add_prop(nodeh, &proph, node_name, row, PP_CONDITION, 9133941Svenki snmp_syserr_p); 9143941Svenki CHECK_LINKRESET(snmp_syserr_p, NULL) 9153941Svenki 9163941Svenki add_prop(nodeh, &proph, node_name, row, PP_EXPECTED, 9173941Svenki snmp_syserr_p); 9183941Svenki CHECK_LINKRESET(snmp_syserr_p, NULL) 9193941Svenki } else { 9203941Svenki log_msg(LOG_ERR, 9213941Svenki SNMPP_UNSUPP_SENSOR_CLASS, sensor_class, row); 9223941Svenki return (NULL); 9233941Svenki } 9243941Svenki break; 9253941Svenki 9263941Svenki case SPC_MODULE: 9273941Svenki ADD_NODE(PICL_CLASS_MODULE) 9283941Svenki 9293941Svenki add_prop(nodeh, &proph, node_name, row, PP_OPSTATUS, 9303941Svenki snmp_syserr_p); 9313941Svenki CHECK_LINKRESET(snmp_syserr_p, NULL) 9323941Svenki 9333941Svenki add_prop(nodeh, &proph, node_name, row, PP_REPLACEABLE, 9343941Svenki snmp_syserr_p); 9353941Svenki CHECK_LINKRESET(snmp_syserr_p, NULL) 9363941Svenki 9373941Svenki add_prop(nodeh, &proph, node_name, row, PP_HOTSWAPPABLE, 9383941Svenki snmp_syserr_p); 9393941Svenki CHECK_LINKRESET(snmp_syserr_p, NULL) 9403941Svenki break; 9413941Svenki 9423941Svenki case SPC_PORT: 9433941Svenki ADD_NODE(PICL_CLASS_PORT) 9443941Svenki break; 9453941Svenki 9463941Svenki case SPC_STACK: 9473941Svenki ADD_NODE(PICL_CLASS_STACK) 9483941Svenki break; 9493941Svenki 9503941Svenki default: 9513941Svenki log_msg(LOG_WARNING, 9523941Svenki SNMPP_UNKNOWN_ENTPHYSCLASS, ent_physclass, row); 9533941Svenki free(phys_name); 9543941Svenki return (NULL); 9553941Svenki } 9563941Svenki 9573941Svenki add_prop(nodeh, &proph, node_name, row, PP_DESCRIPTION, snmp_syserr_p); 9583941Svenki CHECK_LINKRESET(snmp_syserr_p, NULL) 9593941Svenki 9603941Svenki add_prop(nodeh, &proph, node_name, row, PP_LABEL, snmp_syserr_p); 9613941Svenki CHECK_LINKRESET(snmp_syserr_p, NULL) 9623941Svenki 9633941Svenki add_prop(nodeh, &proph, node_name, row, PP_HW_REVISION, snmp_syserr_p); 9643941Svenki CHECK_LINKRESET(snmp_syserr_p, NULL) 9653941Svenki 9663941Svenki add_prop(nodeh, &proph, node_name, row, PP_FW_REVISION, snmp_syserr_p); 9673941Svenki CHECK_LINKRESET(snmp_syserr_p, NULL) 9683941Svenki 9693941Svenki add_prop(nodeh, &proph, node_name, row, PP_SERIAL_NUM, snmp_syserr_p); 9703941Svenki CHECK_LINKRESET(snmp_syserr_p, NULL) 9713941Svenki 9723941Svenki add_prop(nodeh, &proph, node_name, row, PP_MFG_NAME, snmp_syserr_p); 9733941Svenki CHECK_LINKRESET(snmp_syserr_p, NULL) 9743941Svenki 9753941Svenki add_prop(nodeh, &proph, node_name, row, PP_MODEL_NAME, snmp_syserr_p); 9763941Svenki CHECK_LINKRESET(snmp_syserr_p, NULL) 9773941Svenki 9783941Svenki add_prop(nodeh, &proph, node_name, row, PP_IS_FRU, snmp_syserr_p); 9793941Svenki CHECK_LINKRESET(snmp_syserr_p, NULL) 9803941Svenki 9813941Svenki free(phys_name); 9823941Svenki save_nodeh(nodeh, row); 9833941Svenki 9843941Svenki return (nodeh); 9853941Svenki } 9863941Svenki 9873941Svenki /* 9883941Svenki * Saves the node handle and the row id into physplat_nodes[]. If we're 9893941Svenki * doing this in response to a hotplug event, we should've freed the 9903941Svenki * old physplat_nodes before entering here to save the first node of the 9913941Svenki * new physplat subtree. 9923941Svenki */ 9933941Svenki static void 9943941Svenki save_nodeh(picl_nodehdl_t nodeh, int row) 9953941Svenki { 9963941Svenki size_t sz, count; 9973941Svenki picl_nodehdl_t *p; 9983941Svenki 9993941Svenki if (row >= n_physplat_nodes) { 10003941Svenki count = (((size_t)row >> NODE_BLOCK_SHIFT) + 1) * 10013941Svenki N_ELEMS_IN_NODE_BLOCK; 10023941Svenki sz = count * sizeof (picl_nodehdl_t); 10033941Svenki 10043941Svenki p = (picl_nodehdl_t *)calloc(count, sizeof (picl_nodehdl_t)); 10053941Svenki if (p == NULL) { 10063941Svenki log_msg(LOG_ERR, SNMPP_NO_MEM, sz); 10073941Svenki return; 10083941Svenki } 10093941Svenki 10103941Svenki if (physplat_nodes) { 10113941Svenki (void) memcpy((void *) p, (void *) physplat_nodes, 10123941Svenki n_physplat_nodes * sizeof (picl_nodehdl_t)); 10133941Svenki free((void *) physplat_nodes); 10143941Svenki } 10153941Svenki 10163941Svenki physplat_nodes = p; 10173941Svenki n_physplat_nodes = count; 10183941Svenki } 10193941Svenki 10203941Svenki physplat_nodes[row] = nodeh; 10213941Svenki } 10223941Svenki 10233941Svenki static picl_nodehdl_t 10243941Svenki lookup_nodeh(int row) 10253941Svenki { 10263941Svenki if (row >= n_physplat_nodes) 10273941Svenki return (NULL); 10283941Svenki 10293941Svenki return (physplat_nodes[row]); 10303941Svenki } 10313941Svenki 10323941Svenki /* 10333941Svenki * We enter this routine only when we are building the physical-platform 10343941Svenki * subtree, whether for the first time or in response to a hotplug event. 10353941Svenki * If we're here for rebuilding the tree, we have already set stale_tree 10363941Svenki * to be B_TRUE, so no one else would be accessing vol_props, n_vol_props 10373941Svenki * or volprop_ndx. If we're here to build the tree for the first time, 10383941Svenki * picld hasn't yet created doors and is running single-threaded, so no 10393941Svenki * one else would be accessing them anyway. 10403941Svenki */ 10413941Svenki static void 10423941Svenki save_volprop(picl_prophdl_t prop, char *oidstr, int row, int proptype) 10433941Svenki { 10443941Svenki vol_prophdl_t *p; 10453941Svenki int count; 10463941Svenki 10473941Svenki if (volprop_ndx == n_vol_props) { 10483941Svenki count = n_vol_props + N_ELEMS_IN_VOLPROP_BLOCK; 10493941Svenki p = (vol_prophdl_t *)calloc(count, sizeof (vol_prophdl_t)); 10503941Svenki if (p == NULL) { 10513941Svenki log_msg(LOG_ERR, SNMPP_NO_MEM, 10523941Svenki count * sizeof (vol_prophdl_t)); 10533941Svenki return; 10543941Svenki } 10553941Svenki 10563941Svenki if (vol_props) { 10573941Svenki (void) memcpy((void *) p, (void *) vol_props, 10583941Svenki n_vol_props * sizeof (vol_prophdl_t)); 10593941Svenki free((void *) vol_props); 10603941Svenki } 10613941Svenki 10623941Svenki vol_props = p; 10633941Svenki n_vol_props += N_ELEMS_IN_VOLPROP_BLOCK; 10643941Svenki } 10653941Svenki 10663941Svenki vol_props[volprop_ndx].prop = prop; 10673941Svenki vol_props[volprop_ndx].oidstr = oidstr; 10683941Svenki vol_props[volprop_ndx].row = row; 10693941Svenki vol_props[volprop_ndx].proptype = proptype; 10703941Svenki 10713941Svenki volprop_ndx++; 10723941Svenki } 10733941Svenki 10743941Svenki static void 10755723Sfw157321 check_for_stale_data(boolean_t nocache) 10763941Svenki { 10773941Svenki int cur_change_time; 10783941Svenki int ret; 10793941Svenki int snmp_syserr; 10803941Svenki 10813941Svenki (void) rw_wrlock(&stale_tree_rwlp); 10823941Svenki 10833941Svenki /* 10843941Svenki * Check if some other thread beat us to it 10853941Svenki */ 10863941Svenki if (stale_tree == B_TRUE) { 10873941Svenki (void) rw_unlock(&stale_tree_rwlp); 10883941Svenki return; 10893941Svenki } 10903941Svenki 10913941Svenki /* 10925723Sfw157321 * Cache OID_entLastChangeTime for up to 10 seconds before 10935723Sfw157321 * fetching it from ILOM again. This prevents us from fetching 10945723Sfw157321 * this value from ILOM when the we're filling or refreshing a 10955723Sfw157321 * whole bunch of items in the cache around the same time. 10965723Sfw157321 */ 10975723Sfw157321 if (nocache == B_FALSE && time(NULL) - change_time_check <= 10) { 10985723Sfw157321 (void) rw_unlock(&stale_tree_rwlp); 10995723Sfw157321 return; 11005723Sfw157321 } 11015723Sfw157321 11025723Sfw157321 /* 11033941Svenki * Check if mib data has changed (hotplug? link-reset?) 11043941Svenki */ 1105*7935SMichael.Bergknoff@Sun.COM do { 1106*7935SMichael.Bergknoff@Sun.COM snmp_syserr = 0; 1107*7935SMichael.Bergknoff@Sun.COM ret = snmp_get_int(hdl, OID_entLastChangeTime, 0, 1108*7935SMichael.Bergknoff@Sun.COM &cur_change_time, &snmp_syserr); 1109*7935SMichael.Bergknoff@Sun.COM (void) time(&change_time_check); 1110*7935SMichael.Bergknoff@Sun.COM if ((ret == 0) && (cur_change_time == change_time)) { 1111*7935SMichael.Bergknoff@Sun.COM (void) rw_unlock(&stale_tree_rwlp); 1112*7935SMichael.Bergknoff@Sun.COM return; 1113*7935SMichael.Bergknoff@Sun.COM } 1114*7935SMichael.Bergknoff@Sun.COM } while (ret != 0 && snmp_syserr == EINTR); 11153941Svenki 11163941Svenki /* 11173941Svenki * If we can't read entLastChangeTime we assume we need to rebuild 11183941Svenki * the tree. This will also cover the case when we need to rebuild 11193941Svenki * the tree because a link reset had happened. 11203941Svenki */ 11213941Svenki LOGPRINTF2("check_for_stale_data: LastChange times have changed, " 11223941Svenki "(%#x != %#x)\n", change_time, cur_change_time); 11233941Svenki 11243941Svenki /* 11253941Svenki * If the mib data has changed, we need to rebuild the physical-platform 11263941Svenki * subtree. To do this, we set a flag to mark the tree stale, 11273941Svenki * so that any future reads to get value of volatile properties will 11283941Svenki * return PICL_PROPVALUNAVAILABLE, until the stale_tree flag 11293941Svenki * is reset by the tree builder thread. 11303941Svenki */ 11313941Svenki stale_tree = B_TRUE; 11323941Svenki if (vol_props) { 11333941Svenki free(vol_props); 11343941Svenki } 11353941Svenki vol_props = NULL; 11363941Svenki volprop_ndx = 0; 11373941Svenki n_vol_props = 0; 11383941Svenki 11393941Svenki (void) rw_unlock(&stale_tree_rwlp); 11403941Svenki 11413941Svenki (void) mutex_lock(&rebuild_tree_lock); 11423941Svenki rebuild_tree = B_TRUE; 11433941Svenki (void) cond_signal(&rebuild_tree_cv); 11443941Svenki LOGPRINTF("check_for_stale_data: signalled tree builder\n"); 11453941Svenki (void) mutex_unlock(&rebuild_tree_lock); 11463941Svenki } 11473941Svenki 11483941Svenki /* 11493941Svenki * This is the critical routine. This callback is invoked by picl whenever 11503941Svenki * it needs to fetch the value of a volatile property. The first thing we 11513941Svenki * must do, however, is to see if there has been a hotplug or a link-reset 11523941Svenki * event since the last time we built the tree and whether we need to 11533941Svenki * rebuild the tree. If so, we do whatever is necessary to make that happen, 11543941Svenki * but return PICL_PROPVALUNAVAILABLE for now, without making any further 11553941Svenki * snmp requests or accessing any globals. 11563941Svenki */ 11573941Svenki static int 11583941Svenki read_volprop(ptree_rarg_t *parg, void *buf) 11593941Svenki { 11603941Svenki char *pstr; 11613941Svenki int propval; 11623941Svenki int i, ndx; 11633941Svenki int ret; 11643941Svenki int snmp_syserr = 0; 11653941Svenki 11663941Svenki /* 11673941Svenki * First check for any event that would make us throw away 11683941Svenki * the existing /physical-platform subtree and rebuild 11693941Svenki * another one. If we are rebuilding the subtree, we just 11703941Svenki * return the stale value until the tree is fully built. 11713941Svenki */ 11725723Sfw157321 check_for_stale_data(B_FALSE); 11733941Svenki 11743941Svenki (void) rw_rdlock(&stale_tree_rwlp); 11753941Svenki 11763941Svenki if (stale_tree == B_TRUE) { 11773941Svenki (void) rw_unlock(&stale_tree_rwlp); 11783941Svenki return (PICL_PROPVALUNAVAILABLE); 11793941Svenki } 11803941Svenki 11813941Svenki for (i = 0; i < volprop_ndx; i++) { 11823941Svenki if (vol_props[i].prop == parg->proph) { 11833941Svenki ndx = i; 11843941Svenki break; 11853941Svenki } 11863941Svenki } 11873941Svenki if (i == volprop_ndx) { 11885723Sfw157321 (void) rw_unlock(&stale_tree_rwlp); 11893941Svenki log_msg(LOG_ERR, SNMPP_CANT_FIND_VOLPROP, parg->proph); 11903941Svenki return (PICL_FAILURE); 11913941Svenki } 11923941Svenki 11933941Svenki /* 11943941Svenki * If we can't read the value, return failure. Even if this was 11953941Svenki * due to a link reset, between the check for stale data and now, 11963941Svenki * the next volatile callback by picl will initiate a tree-rebuild. 11973941Svenki */ 11983941Svenki ret = snmp_get_int(hdl, vol_props[ndx].oidstr, vol_props[ndx].row, 11993941Svenki &propval, &snmp_syserr); 12003941Svenki if (ret < 0) { 12015723Sfw157321 (void) rw_unlock(&stale_tree_rwlp); 12025723Sfw157321 check_for_stale_data(B_TRUE); 12035723Sfw157321 if (stale_tree == B_TRUE) { 12045723Sfw157321 return (PICL_PROPVALUNAVAILABLE); 12055723Sfw157321 } 12065723Sfw157321 log_msg(LOG_ERR, SNMPP_CANT_FETCH_OBJECT_VAL, 12075723Sfw157321 snmp_syserr ? snmp_syserr : ret, 12085723Sfw157321 vol_props[ndx].oidstr, vol_props[ndx].row); 12093941Svenki return (PICL_FAILURE); 12103941Svenki } 12113941Svenki 12123941Svenki switch (vol_props[ndx].proptype) { 12133941Svenki case VPT_PLATOPSTATE: 12143941Svenki if (propval == SSOS_DISABLED) { 12153941Svenki (void) strlcpy(buf, STR_SSOS_DISABLED, MAX_OPSTATE_LEN); 12163941Svenki } else if (propval == SSOS_ENABLED) { 12173941Svenki (void) strlcpy(buf, STR_SSOS_ENABLED, MAX_OPSTATE_LEN); 12183941Svenki } else { 12195723Sfw157321 (void) rw_unlock(&stale_tree_rwlp); 12203941Svenki log_msg(LOG_ERR, SNMPP_INV_PLAT_EQUIP_OPSTATE, 12213941Svenki propval, vol_props[ndx].row); 12223941Svenki return (PICL_FAILURE); 12233941Svenki } 12243941Svenki break; 12253941Svenki 12263941Svenki case VPT_NUMSENSOR: 12273941Svenki (void) memcpy(buf, &propval, sizeof (propval)); 12283941Svenki break; 12293941Svenki 12303941Svenki case VPT_BINSENSOR: 12313941Svenki if (propval == ST_TRUE) { 12323941Svenki ret = snmp_get_str(hdl, 12333941Svenki OID_sunPlatBinarySensorInterpretTrue, 12343941Svenki vol_props[ndx].row, &pstr, &snmp_syserr); 12355723Sfw157321 if (snmp_syserr == ECANCELED) { 12365723Sfw157321 (void) rw_unlock(&stale_tree_rwlp); 12375723Sfw157321 if (pstr) 12385723Sfw157321 free(pstr); 12393941Svenki return (PICL_FAILURE); 12405723Sfw157321 } 12413941Svenki if (ret < 0 || pstr == NULL) { 12425723Sfw157321 log_msg(LOG_ERR, SNMPP_CANT_FETCH_OBJECT_VAL, 12435723Sfw157321 snmp_syserr ? snmp_syserr : ret, 12445723Sfw157321 OID_sunPlatBinarySensorInterpretTrue, 12455723Sfw157321 vol_props[ndx].row); 12463941Svenki (void) strlcpy(buf, STR_ST_TRUE, 12473941Svenki MAX_TRUTHVAL_LEN); 12483941Svenki } else { 12493941Svenki (void) strlcpy(buf, pstr, MAX_TRUTHVAL_LEN); 12505723Sfw157321 } 12515723Sfw157321 if (pstr) 12523941Svenki free(pstr); 12533941Svenki } else if (propval == ST_FALSE) { 12543941Svenki ret = snmp_get_str(hdl, 12553941Svenki OID_sunPlatBinarySensorInterpretFalse, 12563941Svenki vol_props[ndx].row, &pstr, &snmp_syserr); 12575723Sfw157321 if (snmp_syserr == ECANCELED) { 12585723Sfw157321 (void) rw_unlock(&stale_tree_rwlp); 12595723Sfw157321 if (pstr) 12605723Sfw157321 free(pstr); 12613941Svenki return (PICL_FAILURE); 12625723Sfw157321 } 12633941Svenki if (ret < 0 || pstr == NULL) { 12645723Sfw157321 log_msg(LOG_ERR, SNMPP_CANT_FETCH_OBJECT_VAL, 12655723Sfw157321 snmp_syserr ? snmp_syserr : ret, 12665723Sfw157321 OID_sunPlatBinarySensorInterpretFalse, 12675723Sfw157321 vol_props[ndx].row); 12683941Svenki (void) strlcpy(buf, STR_ST_FALSE, 12693941Svenki MAX_TRUTHVAL_LEN); 12703941Svenki } else { 12713941Svenki (void) strlcpy(buf, pstr, MAX_TRUTHVAL_LEN); 12725723Sfw157321 } 12735723Sfw157321 if (pstr) 12743941Svenki free(pstr); 12753941Svenki } else { 12765723Sfw157321 (void) rw_unlock(&stale_tree_rwlp); 12773941Svenki log_msg(LOG_ERR, SNMPP_INV_PLAT_BINSNSR_CURRENT, 12783941Svenki propval, vol_props[ndx].row); 12793941Svenki return (PICL_FAILURE); 12803941Svenki } 12813941Svenki break; 12823941Svenki 12833941Svenki case VPT_ALARMSTATE: 12843941Svenki if (propval == SSAS_OFF) { 12853941Svenki (void) strlcpy(buf, STR_SSAS_OFF, MAX_ALARMSTATE_LEN); 12863941Svenki } else if (propval == SSAS_STEADY) { 12873941Svenki (void) strlcpy(buf, STR_SSAS_STEADY, 12883941Svenki MAX_ALARMSTATE_LEN); 12893941Svenki } else if (propval == SSAS_ALTERNATING) { 12903941Svenki (void) strlcpy(buf, STR_SSAS_ALTERNATING, 12913941Svenki MAX_ALARMSTATE_LEN); 12923941Svenki } else { 12933941Svenki (void) strlcpy(buf, STR_SSAS_UNKNOWN, 12943941Svenki MAX_ALARMSTATE_LEN); 12953941Svenki } 12963941Svenki break; 12973941Svenki 12983941Svenki case VPT_BATTERYSTATUS: 12993941Svenki switch (propval) { 13003941Svenki case SSBS_OTHER: 13013941Svenki (void) strlcpy(buf, STR_SSBS_OTHER, 13023941Svenki MAX_BATTERYSTATUS_LEN); 13033941Svenki break; 13043941Svenki case SSBS_FULLYCHARGED: 13053941Svenki (void) strlcpy(buf, STR_SSBS_FULLYCHARGED, 13063941Svenki MAX_BATTERYSTATUS_LEN); 13073941Svenki break; 13083941Svenki case SSBS_LOW: 13093941Svenki (void) strlcpy(buf, STR_SSBS_LOW, 13103941Svenki MAX_BATTERYSTATUS_LEN); 13113941Svenki break; 13123941Svenki case SSBS_CRITICAL: 13133941Svenki (void) strlcpy(buf, STR_SSBS_CRITICAL, 13143941Svenki MAX_BATTERYSTATUS_LEN); 13153941Svenki break; 13163941Svenki case SSBS_CHARGING: 13173941Svenki (void) strlcpy(buf, STR_SSBS_CHARGING, 13183941Svenki MAX_BATTERYSTATUS_LEN); 13193941Svenki break; 13203941Svenki case SSBS_CHARGING_AND_LOW: 13213941Svenki (void) strlcpy(buf, STR_SSBS_CHARGING_AND_LOW, 13223941Svenki MAX_BATTERYSTATUS_LEN); 13233941Svenki break; 13243941Svenki case SSBS_CHARGING_AND_HIGH: 13253941Svenki (void) strlcpy(buf, STR_SSBS_CHARGING_AND_HIGH, 13263941Svenki MAX_BATTERYSTATUS_LEN); 13273941Svenki break; 13283941Svenki case SSBS_CHARGING_AND_CRITICAL: 13293941Svenki (void) strlcpy(buf, STR_SSBS_CHARGING_AND_CRITICAL, 13303941Svenki MAX_BATTERYSTATUS_LEN); 13313941Svenki break; 13323941Svenki case SSBS_UNDEFINED: 13333941Svenki (void) strlcpy(buf, STR_SSBS_UNDEFINED, 13343941Svenki MAX_BATTERYSTATUS_LEN); 13353941Svenki break; 13363941Svenki case SSBS_PARTIALLY_CHARGED: 13373941Svenki (void) strlcpy(buf, STR_SSBS_PARTIALLY_CHARGED, 13383941Svenki MAX_BATTERYSTATUS_LEN); 13393941Svenki break; 13403941Svenki case SSBS_UNKNOWN: 13413941Svenki default: 13423941Svenki (void) strlcpy(buf, STR_SSBS_UNKNOWN, 13433941Svenki MAX_BATTERYSTATUS_LEN); 13443941Svenki break; 13453941Svenki } 13463941Svenki break; 13473941Svenki } 13483941Svenki 13493941Svenki (void) rw_unlock(&stale_tree_rwlp); 13503941Svenki 13513941Svenki return (PICL_SUCCESS); 13523941Svenki } 13533941Svenki 13543941Svenki static void 13553941Svenki threshold(picl_nodehdl_t node, char *oidstr, int row, char *propname, 13563941Svenki int *snmp_syserr_p) 13573941Svenki { 13583941Svenki picl_prophdl_t prop; 13593941Svenki int err; 13603941Svenki int val; 13613941Svenki 13625723Sfw157321 if ((err = snmp_get_int(hdl, oidstr, row, &val, snmp_syserr_p)) != -1) { 13633941Svenki err = add_volatile_prop(node, propname, PICL_PTYPE_INT, 13643941Svenki PICL_READ, sizeof (int), read_volprop, NULL, &prop); 13653941Svenki if (err == PICL_SUCCESS) 13663941Svenki save_volprop(prop, oidstr, row, VPT_NUMSENSOR); 13675723Sfw157321 } else 13685723Sfw157321 log_msg(LOG_ERR, SNMPP_CANT_FETCH_OBJECT_VAL, 13695723Sfw157321 *snmp_syserr_p ? *snmp_syserr_p : err, oidstr, row); 13703941Svenki } 13713941Svenki 13723941Svenki static void 13733941Svenki add_thresholds(picl_nodehdl_t node, int row, int *snmp_syserr_p) 13743941Svenki { 13753941Svenki uchar_t *bitstr = NULL; 13763941Svenki uchar_t enabled; 13773941Svenki uint_t nbytes; 13783941Svenki int ret; 13793941Svenki 13805723Sfw157321 ret = snmp_get_str(hdl, 13815723Sfw157321 OID_sunPlatNumericSensorEnabledThresholds, 13825723Sfw157321 row, (char **)&bitstr, snmp_syserr_p); 13835723Sfw157321 if (ret == -1) { 13845723Sfw157321 log_msg(LOG_ERR, SNMPP_CANT_FETCH_OBJECT_VAL, 13855723Sfw157321 *snmp_syserr_p ? *snmp_syserr_p : ret, 13865723Sfw157321 OID_sunPlatNumericSensorEnabledThresholds, row); 13875723Sfw157321 } else { 13885723Sfw157321 nbytes = strlen((const char *)bitstr); 13895723Sfw157321 } 13905723Sfw157321 13915723Sfw157321 CHECK_LINKRESET_VOID(snmp_syserr_p); 13923941Svenki 13935723Sfw157321 /* 13945723Sfw157321 * No bit string of threshold masks was returned, so we can't 13955723Sfw157321 * assume that any thresholds exist. 13965723Sfw157321 * 13975723Sfw157321 * This mask prevents us from attempting to fetch thresholds 13985723Sfw157321 * which don't apply to the sensor or that aren't there anyway, 13995723Sfw157321 * That speeds up the plug-in significantly since otherwise it 14005723Sfw157321 * takes several seconds to time out. 14015723Sfw157321 */ 14025723Sfw157321 if (ret < 0 || bitstr == NULL || nbytes == 0 || 2 < nbytes) { 14035723Sfw157321 if (bitstr) 14045723Sfw157321 free(bitstr); 14055723Sfw157321 return; 14065723Sfw157321 } else if (nbytes == 1) { 14073941Svenki /* 14083941Svenki * The ALOM snmp agent doesn't adhere to the BER rules for 14093941Svenki * encoding bit strings. While the BER states that bitstrings 14103941Svenki * must begin from the second octet after length, and the 14113941Svenki * first octet after length must indicate the number of unused 14123941Svenki * bits in the last octet, the snmp agent simply sends the 14133941Svenki * bitstring data as if it were octet string -- that is, the 14143941Svenki * "unused bits" octet is missing. 14153941Svenki */ 14163941Svenki enabled = bitstr[0]; 14173941Svenki } else if (nbytes == 2) 14183941Svenki enabled = bitstr[1]; 14193941Svenki 14203941Svenki if (bitstr) { 14213941Svenki free(bitstr); 14223941Svenki } 14233941Svenki 14243941Svenki if (enabled & LOWER_FATAL) { 14253941Svenki threshold(node, 14263941Svenki OID_sunPlatNumericSensorLowerThresholdFatal, row, 14273941Svenki PICL_PROP_LOW_POWER_OFF, snmp_syserr_p); 14283941Svenki CHECK_LINKRESET_VOID(snmp_syserr_p) 14293941Svenki } 14303941Svenki if (enabled & LOWER_CRITICAL) { 14313941Svenki threshold(node, 14323941Svenki OID_sunPlatNumericSensorLowerThresholdCritical, row, 14333941Svenki PICL_PROP_LOW_SHUTDOWN, snmp_syserr_p); 14343941Svenki CHECK_LINKRESET_VOID(snmp_syserr_p) 14353941Svenki } 14363941Svenki if (enabled & LOWER_NON_CRITICAL) { 14373941Svenki threshold(node, 14383941Svenki OID_sunPlatNumericSensorLowerThresholdNonCritical, row, 14393941Svenki PICL_PROP_LOW_WARNING, snmp_syserr_p); 14403941Svenki CHECK_LINKRESET_VOID(snmp_syserr_p) 14413941Svenki } 14423941Svenki if (enabled & UPPER_NON_CRITICAL) { 14433941Svenki threshold(node, 14443941Svenki OID_sunPlatNumericSensorUpperThresholdNonCritical, row, 14454802Sfw157321 PICL_PROP_HIGH_WARNING, snmp_syserr_p); 14463941Svenki CHECK_LINKRESET_VOID(snmp_syserr_p) 14473941Svenki } 14483941Svenki if (enabled & UPPER_CRITICAL) { 14493941Svenki threshold(node, 14503941Svenki OID_sunPlatNumericSensorUpperThresholdCritical, row, 14513941Svenki PICL_PROP_HIGH_SHUTDOWN, snmp_syserr_p); 14523941Svenki CHECK_LINKRESET_VOID(snmp_syserr_p) 14533941Svenki } 14543941Svenki if (enabled & UPPER_FATAL) { 14553941Svenki threshold(node, 14563941Svenki OID_sunPlatNumericSensorUpperThresholdFatal, row, 14574802Sfw157321 PICL_PROP_HIGH_POWER_OFF, snmp_syserr_p); 14583941Svenki CHECK_LINKRESET_VOID(snmp_syserr_p) 14593941Svenki } 14603941Svenki } 14613941Svenki 14623941Svenki static char * 14633941Svenki get_slot_type(int row, int *snmp_syserr_p) 14643941Svenki { 14653941Svenki char *p; 14663941Svenki char *slott = NULL; 14673941Svenki int ret; 14683941Svenki 14693941Svenki ret = snmp_get_str(hdl, OID_sunPlatEquipmentHolderAcceptableTypes, 14703941Svenki row, &p, snmp_syserr_p); 14713941Svenki CHECK_LINKRESET(snmp_syserr_p, NULL) 14723941Svenki 14733941Svenki if ((ret == 0) && p && *p) { 14743941Svenki slott = p; 14753941Svenki if ((p = strchr(slott, '\n')) != NULL) 14763941Svenki *p = 0; 14773941Svenki } else { 14783941Svenki log_msg(LOG_WARNING, SNMPP_NO_SLOT_TYPE, row); 14793941Svenki if (p) { 14803941Svenki free(p); 14813941Svenki } 14823941Svenki } 14833941Svenki 14843941Svenki return (slott); 14853941Svenki } 14863941Svenki 14873941Svenki /* 14883941Svenki * Create and add the specified volatile property 14893941Svenki */ 14903941Svenki static int 14913941Svenki add_volatile_prop(picl_nodehdl_t node, char *name, int type, int access, 14923941Svenki int size, int (*rdfunc)(ptree_rarg_t *, void *), 14933941Svenki int (*wrfunc)(ptree_warg_t *, const void *), picl_prophdl_t *propp) 14943941Svenki { 14953941Svenki ptree_propinfo_t propinfo; 14963941Svenki picl_prophdl_t prop; 14973941Svenki int err; 14983941Svenki 14993941Svenki err = ptree_init_propinfo(&propinfo, PTREE_PROPINFO_VERSION, 15003941Svenki type, (access|PICL_VOLATILE), size, name, rdfunc, wrfunc); 15013941Svenki if (err != PICL_SUCCESS) { 15023941Svenki log_msg(LOG_ERR, SNMPP_CANT_INIT_PROPINFO, err); 15033941Svenki return (err); 15043941Svenki } 15053941Svenki 15063941Svenki err = ptree_create_and_add_prop(node, &propinfo, NULL, &prop); 15073941Svenki if (err != PICL_SUCCESS) { 15083941Svenki log_msg(LOG_ERR, SNMPP_CANT_ADD_PROP, err, node); 15093941Svenki return (err); 15103941Svenki } 15113941Svenki 15123941Svenki if (propp) 15133941Svenki *propp = prop; 15143941Svenki 15153941Svenki return (PICL_SUCCESS); 15163941Svenki } 15173941Svenki 15183941Svenki /* 15193941Svenki * Add the specified string property to the node 15203941Svenki */ 15213941Svenki static int 15223941Svenki add_string_prop(picl_nodehdl_t node, char *propname, char *propval) 15233941Svenki { 15243941Svenki ptree_propinfo_t propinfo; 15253941Svenki int err; 15263941Svenki 15277382SMichael.Bergknoff@Sun.COM if (*propval == '\0') 15287382SMichael.Bergknoff@Sun.COM return (PICL_SUCCESS); 15297382SMichael.Bergknoff@Sun.COM 15303941Svenki err = ptree_init_propinfo(&propinfo, PTREE_PROPINFO_VERSION, 15313941Svenki PICL_PTYPE_CHARSTRING, PICL_READ, strlen(propval) + 1, 15323941Svenki propname, NULL, NULL); 15333941Svenki if (err != PICL_SUCCESS) { 15343941Svenki log_msg(LOG_ERR, SNMPP_CANT_INIT_STR_PROPINFO, err); 15353941Svenki return (err); 15363941Svenki } 15373941Svenki 15383941Svenki err = ptree_create_and_add_prop(node, &propinfo, propval, NULL); 15393941Svenki if (err != PICL_SUCCESS) { 15403941Svenki log_msg(LOG_ERR, SNMPP_CANT_ADD_STR_PROP, err, node); 15413941Svenki return (err); 15423941Svenki } 15433941Svenki 15443941Svenki return (PICL_SUCCESS); 15453941Svenki } 15463941Svenki 15473941Svenki /* 15483941Svenki * Add the specified void property to the node 15493941Svenki */ 15503941Svenki static int 15513941Svenki add_void_prop(picl_nodehdl_t node, char *propname) 15523941Svenki { 15533941Svenki ptree_propinfo_t propinfo; 15543941Svenki int err; 15553941Svenki 15563941Svenki err = ptree_init_propinfo(&propinfo, PTREE_PROPINFO_VERSION, 15573941Svenki PICL_PTYPE_VOID, PICL_READ, 0, propname, NULL, NULL); 15583941Svenki if (err != PICL_SUCCESS) { 15593941Svenki log_msg(LOG_ERR, SNMPP_CANT_INIT_VOID_PROPINFO, err); 15603941Svenki return (err); 15613941Svenki } 15623941Svenki 15633941Svenki err = ptree_create_and_add_prop(node, &propinfo, NULL, NULL); 15643941Svenki if (err != PICL_SUCCESS) { 15653941Svenki log_msg(LOG_ERR, SNMPP_CANT_ADD_VOID_PROP, err, node); 15663941Svenki return (err); 15673941Svenki } 15683941Svenki 15693941Svenki return (PICL_SUCCESS); 15703941Svenki } 15713941Svenki 15723941Svenki static void 15733941Svenki add_prop(picl_nodehdl_t nodeh, picl_prophdl_t *php, char *label, 15743941Svenki int row, sp_propid_t pp, int *snmp_syserr_p) 15753941Svenki { 15763941Svenki char *serial_num; 15773941Svenki char *slot_type; 15783941Svenki char *fw_revision, *hw_revision; 15793941Svenki char *mfg_name, *model_name; 15803941Svenki char *phys_descr; 15813941Svenki int val; 15823941Svenki int ret; 15833941Svenki 15843941Svenki switch (pp) { 15853941Svenki case PP_SERIAL_NUM: 15863941Svenki ret = snmp_get_str(hdl, OID_entPhysicalSerialNum, 15873941Svenki row, &serial_num, snmp_syserr_p); 15883941Svenki CHECK_LINKRESET_VOID(snmp_syserr_p) 15897382SMichael.Bergknoff@Sun.COM if ((ret == 0) && serial_num) { 15903941Svenki (void) add_string_prop(nodeh, 15913941Svenki PICL_PROP_SERIAL_NUMBER, serial_num); 15923941Svenki free((void *) serial_num); 15933941Svenki } 15945723Sfw157321 if (ret == -1) 15955723Sfw157321 log_msg(LOG_ERR, SNMPP_CANT_FETCH_OBJECT_VAL, 15965723Sfw157321 *snmp_syserr_p ? *snmp_syserr_p : ret, 15975723Sfw157321 OID_entPhysicalSerialNum, row); 15983941Svenki break; 15993941Svenki 16003941Svenki case PP_SLOT_TYPE: 16013941Svenki if ((slot_type = get_slot_type(row, snmp_syserr_p)) == NULL) { 16023941Svenki CHECK_LINKRESET_VOID(snmp_syserr_p) 16033941Svenki (void) add_string_prop(nodeh, 16043941Svenki PICL_PROP_SLOT_TYPE, DEFAULT_SLOT_TYPE); 16053941Svenki } else { 16063941Svenki (void) add_string_prop(nodeh, 16073941Svenki PICL_PROP_SLOT_TYPE, slot_type); 16083941Svenki free((void *) slot_type); 16093941Svenki } 16103941Svenki break; 16113941Svenki 16123941Svenki case PP_STATE: 16133941Svenki ret = add_volatile_prop(nodeh, PICL_PROP_STATE, 16143941Svenki PICL_PTYPE_CHARSTRING, PICL_READ, MAX_ALARMSTATE_LEN, 16153941Svenki read_volprop, NULL, php); 16163941Svenki if (ret == PICL_SUCCESS) { 16173941Svenki save_volprop(*php, OID_sunPlatAlarmState, row, 16183941Svenki VPT_ALARMSTATE); 16193941Svenki } 16203941Svenki break; 16213941Svenki 16223941Svenki case PP_OPSTATUS: 16233941Svenki ret = add_volatile_prop(nodeh, PICL_PROP_OPERATIONAL_STATUS, 16243941Svenki PICL_PTYPE_CHARSTRING, PICL_READ, MAX_OPSTATE_LEN, 16253941Svenki read_volprop, NULL, php); 16263941Svenki if (ret == PICL_SUCCESS) { 16273941Svenki save_volprop(*php, 16283941Svenki OID_sunPlatEquipmentOperationalState, row, 16293941Svenki VPT_PLATOPSTATE); 16303941Svenki } 16313941Svenki break; 16323941Svenki 16333941Svenki case PP_BATT_STATUS: 16343941Svenki ret = add_volatile_prop(nodeh, PICL_PROP_BATTERY_STATUS, 16354802Sfw157321 PICL_PTYPE_CHARSTRING, PICL_READ, MAX_BATTERYSTATUS_LEN, 16364802Sfw157321 read_volprop, NULL, php); 16373941Svenki if (ret == PICL_SUCCESS) { 16383941Svenki save_volprop(*php, OID_sunPlatBatteryStatus, row, 16393941Svenki VPT_BATTERYSTATUS); 16403941Svenki } 16413941Svenki break; 16423941Svenki 16433941Svenki case PP_TEMPERATURE: 16443941Svenki ret = add_volatile_prop(nodeh, PICL_PROP_TEMPERATURE, 16453941Svenki PICL_PTYPE_INT, PICL_READ, sizeof (int), read_volprop, 16463941Svenki NULL, php); 16473941Svenki if (ret == PICL_SUCCESS) { 16483941Svenki save_volprop(*php, OID_sunPlatNumericSensorCurrent, 16493941Svenki row, VPT_NUMSENSOR); 16503941Svenki } 16513941Svenki break; 16523941Svenki 16533941Svenki case PP_VOLTAGE: 16543941Svenki ret = add_volatile_prop(nodeh, PICL_PROP_VOLTAGE, 16553941Svenki PICL_PTYPE_INT, PICL_READ, sizeof (int), read_volprop, 16563941Svenki NULL, php); 16573941Svenki if (ret == PICL_SUCCESS) { 16583941Svenki save_volprop(*php, OID_sunPlatNumericSensorCurrent, 16593941Svenki row, VPT_NUMSENSOR); 16603941Svenki } 16613941Svenki break; 16623941Svenki 16633941Svenki case PP_CURRENT: 16643941Svenki ret = add_volatile_prop(nodeh, PICL_PROP_CURRENT, 16653941Svenki PICL_PTYPE_INT, PICL_READ, sizeof (int), read_volprop, 16663941Svenki NULL, php); 16673941Svenki if (ret == PICL_SUCCESS) { 16683941Svenki save_volprop(*php, OID_sunPlatNumericSensorCurrent, 16693941Svenki row, VPT_NUMSENSOR); 16703941Svenki } 16713941Svenki break; 16723941Svenki 16733941Svenki case PP_SPEED: 16743941Svenki ret = add_volatile_prop(nodeh, PICL_PROP_SPEED, PICL_PTYPE_INT, 16753941Svenki PICL_READ, sizeof (int), read_volprop, NULL, php); 16763941Svenki if (ret == PICL_SUCCESS) { 16773941Svenki save_volprop(*php, OID_sunPlatNumericSensorCurrent, 16783941Svenki row, VPT_NUMSENSOR); 16793941Svenki } 16803941Svenki break; 16813941Svenki 16823941Svenki case PP_SENSOR_VALUE: 16833941Svenki ret = add_volatile_prop(nodeh, PICL_PROP_SENSOR_VALUE, 16843941Svenki PICL_PTYPE_INT, PICL_READ, sizeof (int), read_volprop, 16853941Svenki NULL, php); 16863941Svenki if (ret == PICL_SUCCESS) { 16873941Svenki save_volprop(*php, OID_sunPlatNumericSensorCurrent, 16883941Svenki row, VPT_NUMSENSOR); 16893941Svenki } 16903941Svenki break; 16913941Svenki 16923941Svenki case PP_CONDITION: 16933941Svenki ret = add_volatile_prop(nodeh, PICL_PROP_CONDITION, 16943941Svenki PICL_PTYPE_CHARSTRING, PICL_READ, MAX_TRUTHVAL_LEN, 16953941Svenki read_volprop, NULL, php); 16963941Svenki if (ret == PICL_SUCCESS) { 16973941Svenki save_volprop(*php, OID_sunPlatBinarySensorCurrent, 16983941Svenki row, VPT_BINSENSOR); 16993941Svenki } 17003941Svenki break; 17013941Svenki 17023941Svenki case PP_EXPECTED: 17033941Svenki ret = add_volatile_prop(nodeh, PICL_PROP_EXPECTED, 17043941Svenki PICL_PTYPE_CHARSTRING, PICL_READ, MAX_TRUTHVAL_LEN, 17053941Svenki read_volprop, NULL, php); 17063941Svenki if (ret == PICL_SUCCESS) { 17073941Svenki save_volprop(*php, OID_sunPlatBinarySensorExpected, 17083941Svenki row, VPT_BINSENSOR); 17093941Svenki } 17103941Svenki break; 17113941Svenki 17125436Sfw157321 case PP_EXPONENT: 17135436Sfw157321 ret = add_volatile_prop(nodeh, PICL_PROP_EXPONENT, 17145436Sfw157321 PICL_PTYPE_INT, PICL_READ, sizeof (int), read_volprop, 17155436Sfw157321 NULL, php); 17165436Sfw157321 if (ret == PICL_SUCCESS) { 17175436Sfw157321 save_volprop(*php, OID_sunPlatNumericSensorExponent, 17185436Sfw157321 row, VPT_NUMSENSOR); 17195436Sfw157321 } 17205436Sfw157321 break; 17215436Sfw157321 17223941Svenki case PP_REPLACEABLE: 17233941Svenki ret = snmp_get_int(hdl, OID_sunPlatCircuitPackReplaceable, 17243941Svenki row, &val, snmp_syserr_p); 17253941Svenki CHECK_LINKRESET_VOID(snmp_syserr_p) 17263941Svenki if ((ret == 0) && (val == ST_TRUE)) 17273941Svenki (void) add_void_prop(nodeh, PICL_PROP_IS_REPLACEABLE); 17285723Sfw157321 if (ret == -1) 17295723Sfw157321 log_msg(LOG_ERR, SNMPP_CANT_FETCH_OBJECT_VAL, 17305723Sfw157321 *snmp_syserr_p ? *snmp_syserr_p : ret, 17315723Sfw157321 OID_sunPlatCircuitPackReplaceable, row); 17323941Svenki break; 17333941Svenki 17343941Svenki case PP_HOTSWAPPABLE: 17353941Svenki ret = snmp_get_int(hdl, OID_sunPlatCircuitPackHotSwappable, 17363941Svenki row, &val, snmp_syserr_p); 17373941Svenki CHECK_LINKRESET_VOID(snmp_syserr_p) 17383941Svenki if ((ret == 0) && (val == ST_TRUE)) 17393941Svenki (void) add_void_prop(nodeh, PICL_PROP_IS_HOT_SWAPPABLE); 17405723Sfw157321 if (ret == -1) 17415723Sfw157321 log_msg(LOG_ERR, SNMPP_CANT_FETCH_OBJECT_VAL, 17425723Sfw157321 *snmp_syserr_p ? *snmp_syserr_p : ret, 17435723Sfw157321 OID_sunPlatCircuitPackHotSwappable, row); 17443941Svenki break; 17453941Svenki 17463941Svenki case PP_IS_FRU: 17473941Svenki ret = snmp_get_int(hdl, OID_entPhysicalIsFRU, row, 17483941Svenki &val, snmp_syserr_p); 17493941Svenki CHECK_LINKRESET_VOID(snmp_syserr_p) 17503941Svenki if ((ret == 0) && (val == ST_TRUE)) 17513941Svenki (void) add_void_prop(nodeh, PICL_PROP_IS_FRU); 17525723Sfw157321 if (ret == -1) 17535723Sfw157321 log_msg(LOG_ERR, SNMPP_CANT_FETCH_OBJECT_VAL, 17545723Sfw157321 *snmp_syserr_p ? *snmp_syserr_p : ret, 17555723Sfw157321 OID_entPhysicalIsFRU, row); 17563941Svenki break; 17573941Svenki 17583941Svenki case PP_HW_REVISION: 17593941Svenki ret = snmp_get_str(hdl, OID_entPhysicalHardwareRev, 17603941Svenki row, &hw_revision, snmp_syserr_p); 17613941Svenki CHECK_LINKRESET_VOID(snmp_syserr_p) 17627382SMichael.Bergknoff@Sun.COM if ((ret == 0) && hw_revision) { 17633941Svenki (void) add_string_prop(nodeh, 17643941Svenki PICL_PROP_HW_REVISION, hw_revision); 17653941Svenki free((void *) hw_revision); 17663941Svenki } 17675723Sfw157321 if (ret == -1) 17685723Sfw157321 log_msg(LOG_ERR, SNMPP_CANT_FETCH_OBJECT_VAL, 17695723Sfw157321 *snmp_syserr_p ? *snmp_syserr_p : ret, 17705723Sfw157321 OID_entPhysicalHardwareRev, row); 17713941Svenki break; 17723941Svenki 17733941Svenki case PP_FW_REVISION: 17743941Svenki ret = snmp_get_str(hdl, OID_entPhysicalFirmwareRev, 17753941Svenki row, &fw_revision, snmp_syserr_p); 17763941Svenki CHECK_LINKRESET_VOID(snmp_syserr_p) 17777382SMichael.Bergknoff@Sun.COM if ((ret == 0) && fw_revision) { 17783941Svenki (void) add_string_prop(nodeh, 17793941Svenki PICL_PROP_FW_REVISION, fw_revision); 17803941Svenki free((void *) fw_revision); 17813941Svenki } 17825723Sfw157321 if (ret == -1) 17835723Sfw157321 log_msg(LOG_ERR, SNMPP_CANT_FETCH_OBJECT_VAL, 17845723Sfw157321 *snmp_syserr_p ? *snmp_syserr_p : ret, 17855723Sfw157321 OID_entPhysicalFirmwareRev, row); 17863941Svenki break; 17873941Svenki 17883941Svenki case PP_MFG_NAME: 17893941Svenki ret = snmp_get_str(hdl, OID_entPhysicalMfgName, 17903941Svenki row, &mfg_name, snmp_syserr_p); 17913941Svenki CHECK_LINKRESET_VOID(snmp_syserr_p) 17927382SMichael.Bergknoff@Sun.COM if ((ret == 0) && mfg_name) { 17933941Svenki (void) add_string_prop(nodeh, 17943941Svenki PICL_PROP_MFG_NAME, mfg_name); 17953941Svenki free((void *) mfg_name); 17963941Svenki } 17975723Sfw157321 if (ret == -1) 17985723Sfw157321 log_msg(LOG_ERR, SNMPP_CANT_FETCH_OBJECT_VAL, 17995723Sfw157321 *snmp_syserr_p ? *snmp_syserr_p : ret, 18005723Sfw157321 OID_entPhysicalMfgName, row); 18013941Svenki break; 18023941Svenki 18033941Svenki case PP_MODEL_NAME: 18043941Svenki ret = snmp_get_str(hdl, OID_entPhysicalModelName, 18053941Svenki row, &model_name, snmp_syserr_p); 18063941Svenki CHECK_LINKRESET_VOID(snmp_syserr_p) 18077382SMichael.Bergknoff@Sun.COM if ((ret == 0) && model_name) { 18083941Svenki (void) add_string_prop(nodeh, 18093941Svenki PICL_PROP_MODEL_NAME, model_name); 18103941Svenki free((void *) model_name); 18113941Svenki } 18125723Sfw157321 if (ret == -1) 18135723Sfw157321 log_msg(LOG_ERR, SNMPP_CANT_FETCH_OBJECT_VAL, 18145723Sfw157321 *snmp_syserr_p ? *snmp_syserr_p : ret, 18155723Sfw157321 OID_entPhysicalModelName, row); 18163941Svenki break; 18173941Svenki 18183941Svenki case PP_DESCRIPTION: 18193941Svenki ret = snmp_get_str(hdl, OID_entPhysicalDescr, 18203941Svenki row, &phys_descr, snmp_syserr_p); 18213941Svenki CHECK_LINKRESET_VOID(snmp_syserr_p) 18227382SMichael.Bergknoff@Sun.COM if ((ret == 0) && phys_descr) { 18234802Sfw157321 (void) add_string_prop(nodeh, 18244802Sfw157321 PICL_PROP_PHYS_DESCRIPTION, phys_descr); 18254802Sfw157321 free((void *) phys_descr); 18263941Svenki } 18275723Sfw157321 if (ret == -1) 18285723Sfw157321 log_msg(LOG_ERR, SNMPP_CANT_FETCH_OBJECT_VAL, 18295723Sfw157321 *snmp_syserr_p ? *snmp_syserr_p : ret, 18305723Sfw157321 OID_entPhysicalDescr, row); 18313941Svenki break; 18323941Svenki 18333941Svenki case PP_LABEL: 18343941Svenki if (label && *label) 18353941Svenki (void) add_string_prop(nodeh, PICL_PROP_LABEL, label); 18363941Svenki break; 18373941Svenki 18383941Svenki case PP_BASE_UNITS: 18393941Svenki ret = snmp_get_int(hdl, OID_sunPlatNumericSensorBaseUnits, 18403941Svenki row, &val, snmp_syserr_p); 18413941Svenki CHECK_LINKRESET_VOID(snmp_syserr_p) 18423941Svenki if ((ret == 0) && (val > 0) && (val < n_baseunits)) { 18433941Svenki (void) add_string_prop(nodeh, 18443941Svenki PICL_PROP_BASE_UNITS, sensor_baseunits[val]); 18453941Svenki } 18465723Sfw157321 if (ret == -1) 18475723Sfw157321 log_msg(LOG_ERR, SNMPP_CANT_FETCH_OBJECT_VAL, 18485723Sfw157321 *snmp_syserr_p ? *snmp_syserr_p : ret, 18495723Sfw157321 OID_sunPlatNumericSensorBaseUnits, row); 18503941Svenki break; 18513941Svenki 18523941Svenki case PP_RATE_UNITS: 18533941Svenki ret = snmp_get_int(hdl, OID_sunPlatNumericSensorRateUnits, 18543941Svenki row, &val, snmp_syserr_p); 18553941Svenki CHECK_LINKRESET_VOID(snmp_syserr_p) 18563941Svenki if ((ret == 0) && (val > 0) && (val < n_rateunits)) { 18573941Svenki (void) add_string_prop(nodeh, 18583941Svenki PICL_PROP_RATE_UNITS, sensor_rateunits[val]); 18593941Svenki } 18605723Sfw157321 if (ret == -1) 18615723Sfw157321 log_msg(LOG_ERR, SNMPP_CANT_FETCH_OBJECT_VAL, 18625723Sfw157321 *snmp_syserr_p ? *snmp_syserr_p : ret, 18635723Sfw157321 OID_sunPlatNumericSensorRateUnits, row); 18643941Svenki break; 18653941Svenki } 18663941Svenki } 18673941Svenki 18687746SKelly.Moyer@Sun.COM /* 18697746SKelly.Moyer@Sun.COM * Initialize the SNMP library's cache refresh subsystem, then periodically 18707746SKelly.Moyer@Sun.COM * process refresh job to prevent cache entries from expiring. 18717746SKelly.Moyer@Sun.COM */ 18727746SKelly.Moyer@Sun.COM /*ARGSUSED*/ 18737746SKelly.Moyer@Sun.COM static void * 18747746SKelly.Moyer@Sun.COM cache_refresher(void *arg) 18757746SKelly.Moyer@Sun.COM { 18767746SKelly.Moyer@Sun.COM int jobs; 18777746SKelly.Moyer@Sun.COM int next_expiration; 18787746SKelly.Moyer@Sun.COM timestruc_t to; 18797746SKelly.Moyer@Sun.COM hrtime_t cycle_start, cycle_elapsed; 18807746SKelly.Moyer@Sun.COM 18817746SKelly.Moyer@Sun.COM /* 18827746SKelly.Moyer@Sun.COM * Initialize refresh subsystem 18837746SKelly.Moyer@Sun.COM */ 18847746SKelly.Moyer@Sun.COM LOGPRINTF("Initializing SNMP refresh subsystem.\n"); 18857746SKelly.Moyer@Sun.COM if (snmp_refresh_init() < 0) { 18867746SKelly.Moyer@Sun.COM return ((void *)-1); 18877746SKelly.Moyer@Sun.COM } 18887746SKelly.Moyer@Sun.COM 18897746SKelly.Moyer@Sun.COM (void) mutex_lock(&cache_refresh_lock); 18907746SKelly.Moyer@Sun.COM 18917746SKelly.Moyer@Sun.COM 18927746SKelly.Moyer@Sun.COM for (;;) { 18937746SKelly.Moyer@Sun.COM cycle_start = gethrtime(); 18947746SKelly.Moyer@Sun.COM 18957746SKelly.Moyer@Sun.COM /* 18967746SKelly.Moyer@Sun.COM * Process jobs from the snmp cache refresh work queue until one 18977746SKelly.Moyer@Sun.COM * of the following conditions is true: 18987746SKelly.Moyer@Sun.COM * 1) we are told to exit, or 18997746SKelly.Moyer@Sun.COM * 2) we have processed at least as many jobs as recommended by 19007746SKelly.Moyer@Sun.COM * the library, and the next job expiration is at least 19017746SKelly.Moyer@Sun.COM * CACHE_REFRESH_MIN_WINDOW * seconds away. 19027746SKelly.Moyer@Sun.COM */ 19037746SKelly.Moyer@Sun.COM jobs = snmp_refresh_get_cycle_hint(CACHE_REFRESH_CYCLE); 19047746SKelly.Moyer@Sun.COM while ((cache_refresh_thr_exit == B_FALSE) && (jobs > 0)) { 19057746SKelly.Moyer@Sun.COM (void) snmp_refresh_process_job(); 19067746SKelly.Moyer@Sun.COM jobs--; 19077746SKelly.Moyer@Sun.COM } 19087746SKelly.Moyer@Sun.COM 19097746SKelly.Moyer@Sun.COM next_expiration = snmp_refresh_get_next_expiration(); 19107746SKelly.Moyer@Sun.COM while ((cache_refresh_thr_exit == B_FALSE) && 19117746SKelly.Moyer@Sun.COM ((next_expiration >= 0) && 19127746SKelly.Moyer@Sun.COM (next_expiration < CACHE_REFRESH_MIN_WINDOW))) { 19137746SKelly.Moyer@Sun.COM (void) snmp_refresh_process_job(); 19147746SKelly.Moyer@Sun.COM next_expiration = snmp_refresh_get_next_expiration(); 19157746SKelly.Moyer@Sun.COM } 19167746SKelly.Moyer@Sun.COM 19177746SKelly.Moyer@Sun.COM /* 19187746SKelly.Moyer@Sun.COM * As long as we haven't been told to exit, sleep for 19197746SKelly.Moyer@Sun.COM * CACHE_REFRESH_CYCLE seconds minus the amount of time that has 19207746SKelly.Moyer@Sun.COM * elapsed since this cycle started. If the elapsed time is 19217746SKelly.Moyer@Sun.COM * equal to or greater than 60 seconds, skip sleeping entirely. 19227746SKelly.Moyer@Sun.COM */ 19237746SKelly.Moyer@Sun.COM cycle_elapsed = (gethrtime() - cycle_start) / NANOSEC; 19247746SKelly.Moyer@Sun.COM if ((cache_refresh_thr_exit == B_FALSE) && 19257746SKelly.Moyer@Sun.COM (cycle_elapsed < CACHE_REFRESH_CYCLE)) { 19267746SKelly.Moyer@Sun.COM to.tv_sec = CACHE_REFRESH_CYCLE - cycle_elapsed; 19277746SKelly.Moyer@Sun.COM to.tv_nsec = 0; 19287746SKelly.Moyer@Sun.COM (void) cond_reltimedwait(&cache_refresh_cv, 19297746SKelly.Moyer@Sun.COM &cache_refresh_lock, &to); 19307746SKelly.Moyer@Sun.COM } 19317746SKelly.Moyer@Sun.COM 19327746SKelly.Moyer@Sun.COM /* 19337746SKelly.Moyer@Sun.COM * If we have been told to exit, clean up and bail out. 19347746SKelly.Moyer@Sun.COM */ 19357746SKelly.Moyer@Sun.COM if (cache_refresh_thr_exit == B_TRUE) { 19367746SKelly.Moyer@Sun.COM snmp_refresh_fini(); 19377746SKelly.Moyer@Sun.COM (void) mutex_unlock(&cache_refresh_lock); 19387746SKelly.Moyer@Sun.COM LOGPRINTF("cache_refresher: time to exit\n"); 19397746SKelly.Moyer@Sun.COM return (NULL); 19407746SKelly.Moyer@Sun.COM } 19417746SKelly.Moyer@Sun.COM 19427746SKelly.Moyer@Sun.COM } 19437746SKelly.Moyer@Sun.COM 19447746SKelly.Moyer@Sun.COM /*NOTREACHED*/ 19457746SKelly.Moyer@Sun.COM return (NULL); 19467746SKelly.Moyer@Sun.COM } 19477746SKelly.Moyer@Sun.COM 19487746SKelly.Moyer@Sun.COM /* 19497746SKelly.Moyer@Sun.COM * Check to see if the cache_refresher thread is running. If it is, signal it 19507746SKelly.Moyer@Sun.COM * to terminate and clean up associated data structures. 19517746SKelly.Moyer@Sun.COM */ 19527746SKelly.Moyer@Sun.COM void 19537746SKelly.Moyer@Sun.COM cache_refresher_fini(void) 19547746SKelly.Moyer@Sun.COM { 19557746SKelly.Moyer@Sun.COM /* if the thread isn't running, there is nothing to do */ 19567746SKelly.Moyer@Sun.COM if (cache_refresh_thr_exit == B_TRUE) 19577746SKelly.Moyer@Sun.COM return; 19587746SKelly.Moyer@Sun.COM 19597746SKelly.Moyer@Sun.COM /* wake up the cache_refresher thread, tell it to exit */ 19607746SKelly.Moyer@Sun.COM (void) mutex_lock(&cache_refresh_lock); 19617746SKelly.Moyer@Sun.COM cache_refresh_thr_exit = B_TRUE; 19627746SKelly.Moyer@Sun.COM (void) cond_signal(&cache_refresh_cv); 19637746SKelly.Moyer@Sun.COM (void) mutex_unlock(&cache_refresh_lock); 19647746SKelly.Moyer@Sun.COM 19657746SKelly.Moyer@Sun.COM /* reap the thread */ 19667746SKelly.Moyer@Sun.COM (void) thr_join(cache_refresh_thr_id, NULL, NULL); 19677746SKelly.Moyer@Sun.COM 19687746SKelly.Moyer@Sun.COM /* finish cleanup... */ 19697746SKelly.Moyer@Sun.COM (void) cond_destroy(&cache_refresh_cv); 19707746SKelly.Moyer@Sun.COM (void) mutex_destroy(&cache_refresh_lock); 19717746SKelly.Moyer@Sun.COM } 19727746SKelly.Moyer@Sun.COM 19733941Svenki /*VARARGS2*/ 19743941Svenki static void 19753941Svenki log_msg(int pri, const char *fmt, ...) 19763941Svenki { 19773941Svenki va_list ap; 19783941Svenki 19793941Svenki va_start(ap, fmt); 19803941Svenki vsyslog(pri, fmt, ap); 19813941Svenki va_end(ap); 19823941Svenki } 19833941Svenki 19843941Svenki #ifdef SNMPPLUGIN_DEBUG 19853941Svenki 19863941Svenki static void 19873941Svenki snmpplugin_log_init(void) 19883941Svenki { 19893941Svenki (void) mutex_init(&snmpplugin_dbuf_lock, USYNC_THREAD, NULL); 19903941Svenki } 19913941Svenki 19923941Svenki static void 19933941Svenki snmpplugin_log(const char *fmt, ...) 19943941Svenki { 19953941Svenki va_list ap; 19963941Svenki 19973941Svenki (void) mutex_lock(&snmpplugin_dbuf_lock); 19983941Svenki 19993941Svenki va_start(ap, fmt); 20003941Svenki (void) vsnprintf(snmpplugin_lbuf, SNMPPLUGIN_DMAX_LINE, fmt, ap); 20013941Svenki snmpplugin_log_append(); 20023941Svenki va_end(ap); 20033941Svenki 20043941Svenki (void) mutex_unlock(&snmpplugin_dbuf_lock); 20053941Svenki } 20063941Svenki 20073941Svenki static void 20083941Svenki snmpplugin_log_append(void) 20093941Svenki { 20103941Svenki int len; 20113941Svenki 20123941Svenki len = strlen(snmpplugin_lbuf); 20133941Svenki 20143941Svenki if ((snmpplugin_dbuf_curp + len) >= 20153941Svenki (snmpplugin_dbuf + snmpplugin_dbuf_sz)) { 20163941Svenki snmpplugin_dbuf_realloc(); 20173941Svenki if (snmpplugin_dbuf == NULL) { 20183941Svenki return; 20193941Svenki } 20203941Svenki } 20213941Svenki 20223941Svenki (void) strcpy(snmpplugin_dbuf_curp, snmpplugin_lbuf); 20233941Svenki snmpplugin_dbuf_curp += len; 20243941Svenki } 20253941Svenki 20263941Svenki static void 20273941Svenki snmpplugin_dbuf_realloc(void) 20283941Svenki { 20293941Svenki char *p; 20303941Svenki size_t offset = 0; 20313941Svenki size_t count; 20323941Svenki 20333941Svenki count = snmpplugin_dbuf_sz + SNMPPLUGIN_DBLOCK_SZ; 20343941Svenki if ((p = (char *)calloc(count, 1)) == NULL) { 20353941Svenki snmpplugin_dbuf_overflow++; 20363941Svenki snmpplugin_dbuf_curp = snmpplugin_dbuf; 20373941Svenki return; 20383941Svenki } 20393941Svenki 20403941Svenki if (snmpplugin_dbuf) { 20413941Svenki offset = snmpplugin_dbuf_curp - snmpplugin_dbuf; 20423941Svenki (void) memcpy(p, snmpplugin_dbuf, snmpplugin_dbuf_sz); 20433941Svenki free(snmpplugin_dbuf); 20443941Svenki } 20453941Svenki 20463941Svenki snmpplugin_dbuf = p; 20473941Svenki snmpplugin_dbuf_sz += SNMPPLUGIN_DBLOCK_SZ; 20483941Svenki 20493941Svenki snmpplugin_dbuf_curp = snmpplugin_dbuf + offset; 20503941Svenki } 20513941Svenki #endif 2052