1 351991: Port net-snmp to lm_sensors-3.x.x
2 Source: upstream, svn diff -r 16736:16739
3 Reviewed-By: Jan Safranek <jsafrane@redhat.com>
5 Index: include/net-snmp/agent/hardware/sensors.h
6 ===================================================================
7 --- include/net-snmp/agent/hardware/sensors.h (revision 0)
8 +++ include/net-snmp/agent/hardware/sensors.h (revision 16739)
11 + * Hardware Abstraction Layer - Sensors module
16 +#define NETSNMP_SENSOR_TYPE_OTHER 1
17 +#define NETSNMP_SENSOR_TYPE_VOLTAGE_AC 3
18 +#define NETSNMP_SENSOR_TYPE_VOLTAGE_DC 4
19 +#define NETSNMP_SENSOR_TYPE_CURRENT 5
20 +#define NETSNMP_SENSOR_TYPE_POWER 6
21 +#define NETSNMP_SENSOR_TYPE_FREQUENCY 7
22 +#define NETSNMP_SENSOR_TYPE_TEMPERATURE 8
23 +#define NETSNMP_SENSOR_TYPE_HUMIDITY 9
24 +#define NETSNMP_SENSOR_TYPE_RPM 10
25 +#define NETSNMP_SENSOR_TYPE_VOLUME 11
26 +#define NETSNMP_SENSOR_TYPE_BOOLEAN 12
29 +#define NETSNMP_SENSOR_FLAG_ACTIVE 0x01
30 +#define NETSNMP_SENSOR_FLAG_NAVAIL 0x02
31 +#define NETSNMP_SENSOR_FLAG_BROKEN 0x04
32 +#define NETSNMP_SENSOR_FLAG_DISABLE 0x08
34 +#define NETSNMP_SENSOR_MASK_STATUS 0x06 /* NAVAIL|BROKEN */
37 +#define NETSNMP_SENSOR_FIND_CREATE 1 /* or use one of the sensor type values */
38 +#define NETSNMP_SENSOR_FIND_EXIST 0
40 +typedef struct netsnmp_sensor_info_s netsnmp_sensor_info;
41 +struct netsnmp_sensor_info_s {
53 +netsnmp_container *get_sensor_container( void );
54 +netsnmp_cache *get_sensor_cache( void );
55 +netsnmp_sensor_info *sensor_by_name( char *, int );
56 +NetsnmpCacheLoad netsnmp_sensor_load;
57 +NetsnmpCacheFree netsnmp_sensor_free;
58 Index: agent/mibgroup/ucd-snmp/lmsensorsMib.c
59 ===================================================================
60 --- agent/mibgroup/ucd-snmp/lmsensorsMib.c (revision 0)
61 +++ agent/mibgroup/ucd-snmp/lmsensorsMib.c (revision 16739)
63 +#include <net-snmp/net-snmp-config.h>
64 +#include <net-snmp/net-snmp-includes.h>
65 +#include <net-snmp/agent/net-snmp-agent-includes.h>
66 +#include <net-snmp/agent/hardware/sensors.h>
67 +#include "ucd-snmp/lmsensorsMib.h"
69 +netsnmp_container *sensorContainer = NULL;
71 +void initialize_lmSensorsTable(const char *tableName, oid *tableOID,
72 + netsnmp_container_op *filter, int mult );
74 +int _sensor_filter_temp( netsnmp_container *c, const void *v );
75 +int _sensor_filter_fan( netsnmp_container *c, const void *v );
76 +int _sensor_filter_volt( netsnmp_container *c, const void *v );
77 +int _sensor_filter_misc( netsnmp_container *c, const void *v );
79 +static oid lmTempSensorsTable_oid[] = {1,3,6,1,4,1,2021,13,16,2};
80 +static oid lmFanSensorsTable_oid[] = {1,3,6,1,4,1,2021,13,16,3};
81 +static oid lmVoltSensorsTable_oid[] = {1,3,6,1,4,1,2021,13,16,4};
82 +static oid lmMiscSensorsTable_oid[] = {1,3,6,1,4,1,2021,13,16,5};
83 + /* All the tables have the same length root OID */
84 +size_t lmSensorsTables_oid_len = OID_LENGTH(lmMiscSensorsTable_oid);
87 +/* Initialise the LM Sensors MIB module */
89 +init_lmsensorsMib(void)
91 + DEBUGMSGTL(("ucd-snmp/lmsensorsMib","Initializing LM-SENSORS-MIB tables\n"));
94 + * Initialise the four LM-SENSORS-MIB tables
96 + * They are almost identical, so we can use the same registration code.
98 + initialize_lmSensorsTable( "lmTempSensorsTable", lmTempSensorsTable_oid,
99 + _sensor_filter_temp, 1000 ); /* MIB asks for mC */
100 + initialize_lmSensorsTable( "lmFanSensorsTable", lmFanSensorsTable_oid,
101 + _sensor_filter_fan, 1);
102 + initialize_lmSensorsTable( "lmVoltSensorsTable", lmVoltSensorsTable_oid,
103 + _sensor_filter_volt, 1000 ); /* MIB asks for mV */
104 + initialize_lmSensorsTable( "lmMiscSensorsTable", lmMiscSensorsTable_oid,
105 + _sensor_filter_misc, 1 );
109 + * Common initialisation code, used for setting up all four tables
112 +initialize_lmSensorsTable(const char *tableName, oid *tableOID,
113 + netsnmp_container_op *filter, int mult )
115 + netsnmp_handler_registration *reg;
116 + netsnmp_table_registration_info *table_info;
117 + netsnmp_cache *cache;
118 + netsnmp_container *container;
121 + * Ensure the HAL sensors module has been initialised,
122 + * and retrieve the main sensors container.
123 + * This table will then be registered using a filter on this container.
125 + sensorContainer = get_sensor_container();
126 + if ( !sensorContainer ) {
127 + init_hw_sensors( );
128 + sensorContainer = get_sensor_container();
130 + container = netsnmp_container_find("sensorTable:table_container");
131 + container->insert_filter = filter;
132 + netsnmp_container_add_index( sensorContainer, container );
136 + * Create a basic registration structure for the table
138 + reg = netsnmp_create_handler_registration(
139 + tableName, lmSensorsTables_handler,
140 + tableOID, lmSensorsTables_oid_len, HANDLER_CAN_RONLY
144 + * Register the table using the filtered container
145 + * Include an indicator of any scaling to be applied to the sensor value
147 + reg->my_reg_void = (void *)mult;
148 + table_info = SNMP_MALLOC_TYPEDEF( netsnmp_table_registration_info );
149 + netsnmp_table_helper_add_indexes(table_info, ASN_INTEGER, 0);
150 + table_info->min_column = COLUMN_LMSENSORS_INDEX;
151 + table_info->max_column = COLUMN_LMSENSORS_VALUE;
152 + netsnmp_container_table_register( reg, table_info, container, 0 );
155 + * If the HAL sensors module was configured as an on-demand caching
156 + * module (rather than being automatically loaded regularly),
157 + * then ensure this table makes use of that cache.
159 + cache = get_sensor_cache();
161 + netsnmp_inject_handler_before( reg, netsnmp_cache_handler_get( cache ),
162 + "table_container");
169 + * Container filters for the four tables
171 + * Used to ensure that sensor entries appear in the appropriate table.
173 +int _sensor_filter_temp( netsnmp_container *c, const void *v ) {
174 + const netsnmp_sensor_info *sp = (const netsnmp_sensor_info *)v;
175 + /* Only matches temperature sensors */
176 + return (( sp->type == NETSNMP_SENSOR_TYPE_TEMPERATURE ) ? 0 : 1 );
179 +int _sensor_filter_fan( netsnmp_container *c, const void *v ) {
180 + const netsnmp_sensor_info *sp = (const netsnmp_sensor_info *)v;
181 + /* Only matches fan sensors */
182 + return (( sp->type == NETSNMP_SENSOR_TYPE_RPM ) ? 0 : 1 );
185 +int _sensor_filter_volt( netsnmp_container *c, const void *v ) {
186 + const netsnmp_sensor_info *sp = (const netsnmp_sensor_info *)v;
187 + /* Only matches voltage sensors (AC or DC) */
188 + return ((( sp->type == NETSNMP_SENSOR_TYPE_VOLTAGE_DC ) ||
189 + ( sp->type == NETSNMP_SENSOR_TYPE_VOLTAGE_AC )) ? 0 : 1 );
192 +int _sensor_filter_misc( netsnmp_container *c, const void *v ) {
193 + const netsnmp_sensor_info *sp = (const netsnmp_sensor_info *)v;
194 + /* Matches everything except temperature, fan or voltage sensors */
195 + return ((( sp->type == NETSNMP_SENSOR_TYPE_TEMPERATURE ) ||
196 + ( sp->type == NETSNMP_SENSOR_TYPE_RPM ) ||
197 + ( sp->type == NETSNMP_SENSOR_TYPE_VOLTAGE_DC ) ||
198 + ( sp->type == NETSNMP_SENSOR_TYPE_VOLTAGE_AC )) ? 1 : 0 );
203 + * Handle requests for any of the four lmXxxxSensorsTables
205 + * This is possible because all the table share the
206 + * same structure and behaviour.
209 +lmSensorsTables_handler(
210 + netsnmp_mib_handler *handler,
211 + netsnmp_handler_registration *reginfo,
212 + netsnmp_agent_request_info *reqinfo,
213 + netsnmp_request_info *requests) {
215 + netsnmp_request_info *request;
216 + netsnmp_table_request_info *table_info;
217 + netsnmp_sensor_info *sensor_info;
218 + int mult = (int)reginfo->my_reg_void;
220 + DEBUGMSGTL(( "ucd-snmp/lmsensorsMib","lmSensorsTables_handler - root: "));
221 + DEBUGMSGOID(("ucd-snmp/lmsensorsMib", reginfo->rootoid, reginfo->rootoid_len));
222 + DEBUGMSG(( "ucd-snmp/lmsensorsMib",", mode %d\n", reqinfo->mode ));
224 + * This is a read-only table, so we only need to handle GET requests.
225 + * (The container helper converts GETNEXT->GET requests automatically).
227 + switch (reqinfo->mode) {
229 + for (request=requests; request; request=request->next) {
230 + sensor_info = (netsnmp_sensor_info *)
231 + netsnmp_container_table_extract_context(request);
232 + if ( !sensor_info ) {
233 + netsnmp_set_request_error(reqinfo, request, SNMP_NOSUCHINSTANCE);
237 + table_info = netsnmp_extract_table_info(request);
238 + switch (table_info->colnum) {
239 + case COLUMN_LMSENSORS_INDEX:
240 + snmp_set_var_typed_integer( request->requestvb, ASN_INTEGER,
241 + sensor_info->idx.oids[0]);
243 + case COLUMN_LMSENSORS_DEVICE:
244 + if ( sensor_info->descr[0] != '\0' ) {
245 + snmp_set_var_typed_value( request->requestvb, ASN_OCTET_STR,
246 + sensor_info->descr, strlen(sensor_info->descr));
248 + snmp_set_var_typed_value( request->requestvb, ASN_OCTET_STR,
249 + sensor_info->name, strlen(sensor_info->name));
252 + case COLUMN_LMSENSORS_VALUE:
253 + /* Multiply the value by the appropriate scaling factor for this table */
254 + snmp_set_var_typed_integer( request->requestvb, ASN_GAUGE,
255 + (int)(mult*sensor_info->value));
258 + netsnmp_set_request_error(reqinfo, request,
259 + SNMP_NOSUCHOBJECT);
266 + return SNMP_ERR_NOERROR;
268 Index: agent/mibgroup/ucd-snmp/lmsensorsMib.h
269 ===================================================================
270 --- agent/mibgroup/ucd-snmp/lmsensorsMib.h (revision 0)
271 +++ agent/mibgroup/ucd-snmp/lmsensorsMib.h (revision 16739)
273 +#ifndef LM_SENSORS_MIB_H
274 +#define LM_SENSORS_MIB_H
276 +config_require(hardware/sensors)
277 +config_add_mib(LM-SENSORS-MIB)
279 +/* function declarations */
280 +void init_lmsensorsMib(void);
283 + * Handler and Column definitions for lmXxxxSensorsTable
285 + * Note that the same handler (and hence the same
286 + * column identifiers) are used for all four tables.
287 + * This is possible because all the table share the
288 + * same structure and behaviour.
290 +Netsnmp_Node_Handler lmSensorsTables_handler;
291 +#define COLUMN_LMSENSORS_INDEX 1
292 +#define COLUMN_LMSENSORS_DEVICE 2
293 +#define COLUMN_LMSENSORS_VALUE 3
295 +#endif /* LM_SENSORS_MIB_H */
296 Index: agent/mibgroup/hardware/sensors.h
297 ===================================================================
298 --- agent/mibgroup/hardware/sensors.h (revision 0)
299 +++ agent/mibgroup/hardware/sensors.h (revision 16739)
301 +config_require(hardware/sensors/hw_sensors)
303 +#if defined(solaris)
304 +# if defined(HAVE_PICL_H)
305 +config_require(hardware/sensors/picld_sensors)
307 +config_require(hardware/sensors/kstat_sensors)
310 +config_require(hardware/sensors/lmsensors_v3)
313 +//config_require(hardware/sensors/dummy_sensors)
314 Index: agent/mibgroup/hardware/sensors/hw_sensors.h
315 ===================================================================
316 --- agent/mibgroup/hardware/sensors/hw_sensors.h (revision 0)
317 +++ agent/mibgroup/hardware/sensors/hw_sensors.h (revision 16739)
319 +void init_hw_sensors( void );
320 Index: agent/mibgroup/hardware/sensors/lmsensors_v2.h
321 ===================================================================
322 --- agent/mibgroup/hardware/sensors/lmsensors_v2.h (revision 0)
323 +++ agent/mibgroup/hardware/sensors/lmsensors_v2.h (revision 16739)
325 +config_require(hardware/sensors/hw_sensors)
326 Index: agent/mibgroup/hardware/sensors/kstat_sensors.c
327 ===================================================================
328 --- agent/mibgroup/hardware/sensors/kstat_sensors.c (revision 0)
329 +++ agent/mibgroup/hardware/sensors/kstat_sensors.c (revision 16739)
331 +#include <net-snmp/net-snmp-config.h>
332 +#include <net-snmp/net-snmp-includes.h>
333 +#include <net-snmp/agent/net-snmp-agent-includes.h>
334 +#include <net-snmp/agent/hardware/sensors.h>
336 +#include "util_funcs.h"
340 +#include </usr/platform/sun4u/include/sys/envctrl.h>
342 +void netsnmp_sensor_arch_init( void ) {
343 + DEBUGMSGTL(("sensors:arch", "Initialise KStat Sensors module\n"));
348 +netsnmp_sensor_arch_load(netsnmp_cache *cache, void *vp) {
349 + netsnmp_sensor_info *sp;
352 + const char *fantypes[]={"CPU","PWR","AFB"};
357 + envctrl_fan_t *fan_info;
358 + envctrl_ps_t *power_info;
359 + envctrl_encl_t *enc_info;
362 + DEBUGMSGTL(("sensors:arch", "Reload KStat Sensors module\n"));
366 + DEBUGMSGTL(("sensors:arch", "Couldn't open kstat\n"));
372 + * Retrieve fan information
374 + kp = kstat_lookup( kc, ENVCTRL_MODULE_NAME, 0, ENVCTRL_KSTAT_FANSTAT);
375 + if (( kp == 0 ) || (kstat_read( kc, kp, 0 ) == -1 )) {
376 + DEBUGMSGTL(("sensors:arch", "No fan information\n"));
378 + fan_info = (envctrl_fan_t *)kp->ks_data;
379 + for (i=0; i<kp->ks_ndata; i++) {
380 + memset( name, 0, 256 );
381 + snprintf( name, 255, "%s%d", fantypes[fan_info->type], fan_info->instance );
383 + sp = sensor_by_name( name, NETSNMP_SENSOR_TYPE_RPM );
385 + sp->value = fan_info->fanspeed;
386 + sp->flags|= NETSNMP_SENSOR_FLAG_ACTIVE;
387 + snprintf( sp->descr, 255, "fan type %s number %d",
388 + fantypes[fan_info->type], fan_info->instance );
397 + * Retrieve Power Supply information
399 + kp = kstat_lookup( kc, ENVCTRL_MODULE_NAME, 0, ENVCTRL_KSTAT_PSNAME);
400 + if (( kp == 0 ) || (kstat_read( kc, kp, 0 ) == -1 )) {
401 + DEBUGMSGTL(("sensors:arch", "No PSU information\n"));
403 + power_info = (envctrl_ps_t *)kp->ks_data;
404 + for (i=0; i<kp->ks_ndata; i++) {
405 + memset( name, 0, 256 );
406 + snprintf( name, 255, "PSU%d", power_info->instance );
408 + sp = sensor_by_name( name, NETSNMP_SENSOR_TYPE_TEMPERATURE);
410 + sp->value = power_info->ps_tempr;
411 + sp->flags|= NETSNMP_SENSOR_FLAG_ACTIVE;
412 + snprintf( sp->descr, 255, "power supply %d", power_info->instance );
421 + * Retrieve Enclosure information
423 + kp = kstat_lookup( kc, ENVCTRL_MODULE_NAME, 0, ENVCTRL_KSTAT_ENCL);
424 + if (( kp == 0 ) || (kstat_read( kc, kp, 0 ) == -1 )) {
425 + DEBUGMSGTL(("sensors:arch", "No enclosure information\n"));
427 + enc_info = (envctrl_encl_t *)kp->ks_data;
428 + for (i=0; i<kp->ks_ndata; i++) {
430 + * The enclosure information covers several different types of sensor
432 + switch ( enc_info->type ) {
433 + case ENVCTRL_ENCL_FSP:
434 + DEBUGMSGTL(("sensors:arch:detail", "Enclosure Front Panel\n"));
435 + sp = sensor_by_name( "FSP", NETSNMP_SENSOR_TYPE_OTHER);
437 + sp->value = enc_info->value;
438 + sp->flags|= NETSNMP_SENSOR_FLAG_ACTIVE;
442 + case ENVCTRL_ENCL_AMBTEMPR:
443 + DEBUGMSGTL(("sensors:arch:detail", "Enclosure Ambient Temperature\n"));
444 + sp = sensor_by_name( "Ambient", NETSNMP_SENSOR_TYPE_TEMPERATURE);
446 + sp->value = enc_info->value;
447 + sp->flags|= NETSNMP_SENSOR_FLAG_ACTIVE;
451 + case ENVCTRL_ENCL_CPUTEMPR:
452 + DEBUGMSGTL(("sensors:arch:detail", "Enclosure CPU Temperature\n"));
453 + memset( name, 0, 256 );
454 + snprintf( name, 255, "CPU%d", enc_info->instance );
455 + sp = sensor_by_name( name, NETSNMP_SENSOR_TYPE_TEMPERATURE);
457 + sp->value = enc_info->value;
458 + sp->flags|= NETSNMP_SENSOR_FLAG_ACTIVE;
459 + snprintf( sp->descr, 255, "CPU%d temperature", enc_info->instance );
463 + case ENVCTRL_ENCL_BACKPLANE4:
464 + DEBUGMSGTL(("sensors:arch:detail", "Enclosure Backplane4\n"));
465 + sp = sensor_by_name( "Backplane4", NETSNMP_SENSOR_TYPE_OTHER);
467 + sp->value = enc_info->value;
468 + sp->flags|= NETSNMP_SENSOR_FLAG_ACTIVE;
472 + case ENVCTRL_ENCL_BACKPLANE8:
473 + DEBUGMSGTL(("sensors:arch:detail", "Enclosure Backplane4\n"));
474 + sp = sensor_by_name( "Backplane4", NETSNMP_SENSOR_TYPE_OTHER);
476 + sp->value = enc_info->value;
477 + sp->flags|= NETSNMP_SENSOR_FLAG_ACTIVE;
482 + DEBUGMSGTL(("sensors:arch:detail", "Unrecognised Enclosure entry (%d)n",
492 Index: agent/mibgroup/hardware/sensors/lmsensors_v3.h
493 ===================================================================
494 --- agent/mibgroup/hardware/sensors/lmsensors_v3.h (revision 0)
495 +++ agent/mibgroup/hardware/sensors/lmsensors_v3.h (revision 16739)
497 +config_require(hardware/sensors/hw_sensors)
498 Index: agent/mibgroup/hardware/sensors/dummy_sensors.c
499 ===================================================================
500 --- agent/mibgroup/hardware/sensors/dummy_sensors.c (revision 0)
501 +++ agent/mibgroup/hardware/sensors/dummy_sensors.c (revision 16739)
503 +#include <net-snmp/net-snmp-config.h>
504 +#include <net-snmp/net-snmp-includes.h>
505 +#include <net-snmp/agent/net-snmp-agent-includes.h>
506 +#include <net-snmp/agent/hardware/sensors.h>
509 +void netsnmp_sensor_arch_init( void ) {
510 + /* Nothing to do */
511 + DEBUGMSGTL(("sensors:arch", "Initialise Dummy Sensors module\n"));
515 +netsnmp_sensor_arch_load(netsnmp_cache *cache, void *vp) {
518 + netsnmp_sensor_info *sp;
521 + tm = localtime(&now);
523 + DEBUGMSGTL(("sensors:arch", "Reload Dummy Sensors module\n"));
525 + /* First pseudo-sensor - slowly-rising temperature */
526 + sp = sensor_by_name( "minute", NETSNMP_SENSOR_TYPE_TEMPERATURE );
527 + sp->value = tm->tm_min;
528 + snprintf( sp->descr, 256, "Minute-based pseudo-sensor - slowly-rising temperature" );
529 + sp->flags|= NETSNMP_SENSOR_FLAG_ACTIVE;
531 + /* Second pseudo-sensor - quickly-rising temperature */
532 + sp = sensor_by_name( "second", NETSNMP_SENSOR_TYPE_TEMPERATURE );
533 + sp->value = tm->tm_sec;
534 + snprintf( sp->descr, 256, "Second-based pseudo-sensor - quickly-rising temperature" );
535 + sp->flags|= NETSNMP_SENSOR_FLAG_ACTIVE;
537 + /* Third pseudo-sensor - annual fan speed */
538 + sp = sensor_by_name( "year", NETSNMP_SENSOR_TYPE_RPM );
539 + sp->value = tm->tm_year + 1900;
540 + snprintf( sp->descr, 256, "RPM pseudo-sensor - annual fan speed" );
541 + sp->flags|= NETSNMP_SENSOR_FLAG_ACTIVE;
543 + /* Fourth pseudo-sensor - daily voltage */
544 + sp = sensor_by_name( "day", NETSNMP_SENSOR_TYPE_VOLTAGE_DC );
545 + sp->value = tm->tm_mday-20;
546 + snprintf( sp->descr, 256, "Day-based pseudo-sensor - positive or negative voltage" );
547 + sp->flags|= NETSNMP_SENSOR_FLAG_ACTIVE;
549 + /* Fifth pseudo-sensor - monthly voltage */
550 + sp = sensor_by_name( "month", NETSNMP_SENSOR_TYPE_VOLTAGE_DC );
551 + sp->value = tm->tm_mon;
552 + snprintf( sp->descr, 256, "Month-based pseudo-sensor - positive voltage" );
553 + sp->flags|= NETSNMP_SENSOR_FLAG_ACTIVE;
555 + /* Sixth pseudo-sensor - annual daily something */
556 + sp = sensor_by_name( "yday", NETSNMP_SENSOR_TYPE_OTHER );
557 + sp->value = tm->tm_yday;
558 + snprintf( sp->descr, 256, "Day-based pseudo-sensor - annual something" );
559 + sp->flags|= NETSNMP_SENSOR_FLAG_ACTIVE;
563 Index: agent/mibgroup/hardware/sensors/kstat_sensors.h
564 ===================================================================
565 --- agent/mibgroup/hardware/sensors/kstat_sensors.h (revision 0)
566 +++ agent/mibgroup/hardware/sensors/kstat_sensors.h (revision 16739)
568 +config_require(hardware/sensors/hw_sensors)
569 Index: agent/mibgroup/hardware/sensors/picld_sensors.c
570 ===================================================================
571 --- agent/mibgroup/hardware/sensors/picld_sensors.c (revision 0)
572 +++ agent/mibgroup/hardware/sensors/picld_sensors.c (revision 16739)
574 +#include <net-snmp/net-snmp-config.h>
575 +#include <net-snmp/net-snmp-includes.h>
576 +#include <net-snmp/agent/net-snmp-agent-includes.h>
577 +#include <net-snmp/agent/hardware/sensors.h>
579 +#include "util_funcs.h"
583 +#include </usr/platform/sun4u/include/sys/envctrl.h>
585 +void netsnmp_sensor_arch_init( void ) {
586 + DEBUGMSGTL(("sensors:arch", "Initialise PICLd Sensors module\n"));
592 + * Handle a numeric-valued sensor
595 +read_num_sensor( picl_nodehdl_t childh, char *propval, float *value )
597 + picl_nodehdl_t sensorh;
598 + picl_propinfo_t sensor_info;
599 + picl_errno_t error_code;
602 + char buf[PICL_PROPSIZE_MAX];
611 + * Retrieve the specified sensor information and value
613 + error_code = picl_get_propinfo_by_name(childh, propval, &sensor_info, &sensorh);
614 + if ( error_code != PICL_SUCCESS ) {
615 + DEBUGMSGTL(("sensors:arch:detail", "sensor info lookup failed (%d)\n",
617 + return( error_code );
620 + error_code = picl_get_propval(sensorh, &val.buf, sensor_info.size);
621 + if ( error_code != PICL_SUCCESS ) {
622 + DEBUGMSGTL(("sensors:arch:detail", "sensor value lookup failed (%d)\n",
624 + return( error_code );
628 + * Check the validity (type and size) of this value
630 + if ( sensor_info.type == PICL_PTYPE_FLOAT ) {
632 + } else if ( sensor_info.type == PICL_PTYPE_UNSIGNED_INT ) {
633 + /* 16-bit or 32-bit unsigned integers */
634 + if ( sensor_info.size == 2 ) {
636 + } else if ( sensor_info.size == 4 ) {
639 + DEBUGMSGTL(("sensors:arch:detail", "unsigned integer (%d bit)\n",
640 + sensor_info.size * 8));
641 + return PICL_FAILURE;
643 + } else if ( sensor_info.type == PICL_PTYPE_INT ) {
644 + /* 16-bit or 32-bit signed integers */
645 + if ( sensor_info.size == 2 ) {
647 + } else if ( sensor_info.size == 4 ) {
650 + DEBUGMSGTL(("sensors:arch:detail", "signed integer (%d bit)\n",
651 + sensor_info.size * 8));
652 + return PICL_FAILURE;
655 + DEBUGMSGTL(("sensors:arch:detail", "unrecognised type (%d)\n",
656 + sensor_info.type));
657 + return PICL_FAILURE;
664 +process_num_sensor( picl_nodehdl_t childh, char *propname, char *propval, int typ )
666 + netsnmp_sensor_info *sp;
668 + picl_errno_t error_code;
670 + sp = sensor_by_name( propname, typ );
675 + error_code = read_num_sensor( childh, propval, &value );
676 + if ( error_code == PICL_SUCCESS ) {
678 + sp->flags|= NETSNMP_SENSOR_FLAG_ACTIVE;
680 + DEBUGMSGTL(("sensors:arch:detail", "Failed to read %s sensor value (%d)\n",
681 + propname, error_code));
690 + * Handle an enumeration-valued sensor
692 +char *switch_settings[] = { "OFF","ON","NORMAL","LOCKED",
693 + "UNKNOWN","DIAG","SECURE",
695 +char *led_settings[] = { "OFF","ON","BLINK",
697 +char *i2c_settings[] = { "OK",
701 +read_enum_sensor( picl_nodehdl_t childh, float *value, char **options )
703 + picl_nodehdl_t sensorh;
704 + picl_propinfo_t sensor_info;
705 + picl_errno_t error_code;
706 + char state[PICL_PROPSIZE_MAX];
710 + * Retrieve the specified sensor information and value
712 + error_code = picl_get_propinfo_by_name(childh, "State", &sensor_info, &sensorh);
713 + if ( error_code != PICL_SUCCESS ) {
714 + DEBUGMSGTL(("sensors:arch:detail", "sensor info lookup failed (%d)\n",
716 + return( error_code );
719 + error_code = picl_get_propval(sensorh, state, sensor_info.size);
720 + if ( error_code != PICL_SUCCESS ) {
721 + DEBUGMSGTL(("sensors:arch:detail", "sensor value lookup failed (%d)\n",
723 + return( error_code );
727 + * Try to find a matching entry in the list of options.
728 + * Note that some platforms may use upper or lower case
729 + * versions of these enumeration values
730 + * (so the checks are case insensitive)
732 + *value = 99; /* Dummy value */
733 + for ( i=0; options[i] != NULL; i++ ) {
734 + if (strncasecmp(state, options[i], strlen(options[i])) == 0) {
740 + DEBUGMSGTL(("sensors:arch:detail", "Enumeration state %s not matched\n",
742 + return 0; /* Or an error ? */
746 +process_enum_sensor( picl_nodehdl_t childh, char *propname, int typ, char **options )
748 + netsnmp_sensor_info *sp;
750 + picl_errno_t error_code;
752 + sp = sensor_by_name( propname, typ );
757 + error_code = read_enum_sensor( childh, &value, options );
758 + if ( error_code == PICL_SUCCESS ) {
760 + sp->flags|= NETSNMP_SENSOR_FLAG_ACTIVE;
762 + DEBUGMSGTL(("sensors:arch:detail", "Failed to read %s sensor value (%d)\n",
763 + propname, error_code));
769 +process_enum_sensor( picl_nodehdl_t childh, char *propname, int typ, char **options )
777 + * Recursively walk through the tree of sensors
780 +process_sensors( int level, picl_nodehdl_t nodeh ) {
781 + picl_nodehdl_t childh, nexth;
782 + char propname[ PICL_PROPNAMELEN_MAX ];
783 + char propclass[ PICL_CLASSNAMELEN_MAX ];
784 + picl_errno_t error_code;
787 + DEBUGMSGTL(("sensors:arch:detail", "process_sensors - level %d\n", level));
789 + /* Look up the first child node at this level */
790 + error_code = pick_get_propval_by_name( nodeh, PICL_PROP_CHILD,
791 + &childh, sizeof(childh));
792 + if ( error_code != PICL_SUCCESS ) {
793 + DEBUGMSGTL(("sensors:arch:detail", "Failed to get first child node (%d)\n",
795 + return( error_code );
798 + /* Step through the child nodes, retrieving the name and class of each one */
799 + while ( error_code == PICL_SUCCESS ) {
800 + error_code = pick_get_propval_by_name( childh, PICL_PROP_NAME,
801 + propname, sizeof(propname)-1);
802 + if ( error_code != PICL_SUCCESS ) {
803 + /* The Node With No Name */
804 + DEBUGMSGTL(("sensors:arch:detail", "get property name failed (%d)\n",
806 + return( error_code );
809 + error_code = pick_get_propval_by_name( childh, PICL_PROP_CLASSNAME,
810 + propclass, sizeof(propclass)-1);
811 + if ( error_code != PICL_SUCCESS ) {
812 + /* The Classless Society */
813 + DEBUGMSGTL(("sensors:arch:detail", "get property class failed (%d)\n",
815 + return( error_code );
818 + DEBUGMSGTL(("sensors:arch:detail", "Name: %s, Class %s\n",
819 + propname, propclass ));
823 + * Three classes represent further groups of sensors, etc.
824 + * Call 'process_sensors' recursively to handle this next level
826 + if (( strstr( propclass, "picl" )) ||
827 + ( strstr( propclass, "frutree" )) ||
828 + ( strstr( propclass, "obp" ))) {
829 + process_sensors( level, childh );
832 + * Otherwise retrieve the value appropriately based on the
833 + * class of the sensor.
835 + * We need to specify the name of the PICL property to retrieve
836 + * for this class of sensor, and the Net-SNMP sensor type.
838 + else if ( strstr( propclass, "fan-tachometer" )) {
839 + process_num_sensor( childh, propname, "AtoDSensorValue",
840 + NETSNMP_SENSOR_TYPE_RPM );
841 + } else if ( strstr( propclass, "fan" )) {
842 + process_num_sensor( childh, propname, "Speed",
843 + NETSNMP_SENSOR_TYPE_RPM );
844 + } else if ( strstr( propclass, "temperature-sensor" )) {
845 + process_num_sensor( childh, propname, "Temperature",
846 + NETSNMP_SENSOR_TYPE_TEMPERATURE );
847 + } else if ( strstr( propclass, "voltage-sensor" )) {
848 + process_num_sensor( childh, propname, "Voltage",
849 + /* ?? */ NETSNMP_SENSOR_TYPE_VOLTAGE_DC );
850 + } else if ( strstr( propclass, "digital-sensor" )) {
851 + process_num_sensor( childh, propname, "AtoDSensorValue",
852 + /* ?? */ NETSNMP_SENSOR_TYPE_VOLTAGE_DC );
854 + * Enumeration-valued sensors use a fixed PICL property ("State"),
855 + * but take a list of the values appropriate for that sensor,
856 + * as well as the Net-SNMP sensor type.
858 + } else if ( strstr( propclass, "switch" )) {
859 + process_enum_sensor( childh, propname, NETSNMP_SENSOR_TYPE_OTHER,
861 + } else if ( strstr( propclass, "led" )) {
862 + process_enum_sensor( childh, propname, NETSNMP_SENSOR_TYPE_OTHER,
864 + } else if ( strstr( propclass, "i2c" )) {
865 + process_enum_sensor( childh, propname, NETSNMP_SENSOR_TYPE_BOOLEAN, /* ?? */
868 + /* Skip other classes of sensor */
869 + DEBUGMSGTL(("sensors:arch:detail", "Skipping class %s\n", propclass ));
873 + * Move on to the next child node at the current level (if any)
875 + error_code = pick_get_propval_by_name( childh, PICL_PROP_PEER,
876 + &nexth, sizeof(nexth));
877 + if ( error_code != PICL_SUCCESS ) {
878 + /* That's All Folks! */
879 + return (( error_code == PICL_PROPNOTFOUND )
880 + ? PICL_SUCCESS : error_code );
890 +netsnmp_sensor_arch_load(netsnmp_cache *cache, void *vp) {
892 + picl_nodehdl_t rooth;
894 + DEBUGMSGTL(("sensors:arch", "Reload PICLd Sensors module\n"));
896 + error_code = picl_get_root(&rooth);
897 + if ( error_code != PICL_SUCCESS) {
898 + DEBUGMSGTL(("sensors:arch", "Couldn't get root node (error %d)\n", error_code));
902 + error_code = process_sensors(0, rooth);
903 + if ( error_code != 255 )
904 + if ( error_code != 7 ) /* ignore PICL_PROPNOTFOUND error */
905 + DEBUGMSGTL(("sensors:arch", "Internal PICLd problem (error %d)\n", error_code));
910 +void netsnmp_sensor_arch_shutdown( void ) {
911 + DEBUGMSGTL(("sensors:arch", "Shutdown PicLD Sensors module\n"));
915 Index: agent/mibgroup/hardware/sensors/hw_sensors.c
916 ===================================================================
917 --- agent/mibgroup/hardware/sensors/hw_sensors.c (revision 0)
918 +++ agent/mibgroup/hardware/sensors/hw_sensors.c (revision 16739)
920 +#include <net-snmp/net-snmp-config.h>
921 +#include <net-snmp/net-snmp-includes.h>
922 +#include <net-snmp/agent/net-snmp-agent-includes.h>
923 +#include <net-snmp/agent/hardware/sensors.h>
926 +extern NetsnmpCacheLoad netsnmp_sensor_arch_load;
927 +extern void netsnmp_sensor_arch_init( void );
928 +static int _sensor_load( void );
929 +static void _sensor_free( void );
931 +static int _sensorAutoUpdate = 0; /* 0 means on-demand caching */
932 +static void _sensor_update_stats( unsigned int, void* );
934 +netsnmp_cache *_sensor_cache = NULL;
935 +netsnmp_container *_sensor_container = NULL;
936 +static int _sensor_idx = 0;
938 +void init_hw_sensors( void ) {
940 + if ( _sensor_container )
941 + return; /* Already initialised */
943 + DEBUGMSGTL(("sensors", "Initialise Hardware Sensors module\n"));
946 + * Define a container to hold the basic list of sensors
947 + * The four LM-SENSOR-MIB containers will be created in
948 + * the relevant initialisation routine(s)
950 + _sensor_container = netsnmp_container_find("sensorTable:table_container");
951 + if ( NULL == _sensor_container ) {
952 + snmp_log( LOG_ERR, "failed to create container for sensorTable");
955 + netsnmp_sensor_arch_init( );
958 + * If we're sampling the sensor information automatically,
959 + * then arrange for this to be triggered regularly.
961 + * If we're not sampling these values regularly,
962 + * create a suitable cache handler instead.
964 + if ( _sensorAutoUpdate ) {
965 + DEBUGMSGTL(("sensors", "Reloading Hardware Sensors automatically (%d)\n",
966 + _sensorAutoUpdate));
967 + snmp_alarm_register( _sensorAutoUpdate, SA_REPEAT,
968 + _sensor_update_stats, NULL );
971 + _sensor_cache = netsnmp_cache_create( 5, netsnmp_sensor_load,
972 + netsnmp_sensor_free, NULL, 0 );
973 + DEBUGMSGTL(("sensors", "Reloading Hardware Sensors on-demand (%p)\n",
978 +void shutdown_hw_sensors( void ) {
983 + * Return the main sensor container
985 +netsnmp_container *get_sensor_container( void ) { return _sensor_container; }
988 + * Return the main sensor cache control structure (if defined)
990 +netsnmp_cache *get_sensor_cache( void ) { return _sensor_cache; }
994 + * Wrapper routine for automatically updating sensor statistics
997 +_sensor_update_stats( unsigned int clientreg, void *data )
1004 + * Wrapper routine for re-loading sensor statistics on demand
1007 +netsnmp_sensor_load( netsnmp_cache *cache, void *data )
1009 + return _sensor_load();
1013 + * Wrapper routine for releasing expired sensor statistics
1016 +netsnmp_sensor_free( netsnmp_cache *cache, void *data )
1023 + * Architecture-independent processing of loading sensor statistics
1026 +_sensor_load( void )
1028 + netsnmp_sensor_arch_load( NULL, NULL );
1032 + * Architecture-independent release of sensor statistics
1035 +_sensor_free( void )
1037 + netsnmp_sensor_info *sp;
1039 + for (sp = CONTAINER_FIRST( _sensor_container );
1041 + sp = CONTAINER_NEXT( _sensor_container, sp )) {
1043 + sp->flags &= ~ NETSNMP_SENSOR_FLAG_ACTIVE;
1049 + * Retrieve a sensor entry by name,
1050 + * or (optionally) insert a new one into the container
1052 +netsnmp_sensor_info *
1053 +sensor_by_name( char *name, int create_type )
1055 + netsnmp_sensor_info *sp;
1057 + DEBUGMSGTL(("sensors:name", "Get sensor entry (%s)\n", name));
1060 + * Look through the list for a matching entry
1062 + /* .. or use a secondary index container ?? */
1063 + for (sp = CONTAINER_FIRST( _sensor_container );
1065 + sp = CONTAINER_NEXT( _sensor_container, sp )) {
1067 + if ( !strcmp( name, sp->name ))
1074 + if ( create_type == NETSNMP_SENSOR_FIND_EXIST ) {
1075 + DEBUGMSGTL(("sensors:name", "No such sensor entry\n"));
1080 + * ... so let's create a new one, using the type supplied
1082 + sp = SNMP_MALLOC_TYPEDEF( netsnmp_sensor_info );
1084 + strcpy( sp->name, name );
1085 + sp->type = create_type;
1087 + * Set up the index value.
1089 + * All this trouble, just for a simple integer.
1090 + * Surely there must be a better way?
1093 + sp->idx.oids = SNMP_MALLOC_TYPEDEF( oid );
1094 + sp->idx.oids[0] = ++_sensor_idx;
1097 + DEBUGMSGTL(("sensors:name", "Create sensor entry (type = %d, index = %d\n",
1098 + create_type, _sensor_idx));
1099 + CONTAINER_INSERT( _sensor_container, sp );
1103 Index: agent/mibgroup/hardware/sensors/dummy_sensors.h
1104 ===================================================================
1105 --- agent/mibgroup/hardware/sensors/dummy_sensors.h (revision 0)
1106 +++ agent/mibgroup/hardware/sensors/dummy_sensors.h (revision 16739)
1108 +config_require(hardware/sensors/hw_sensors)
1109 Index: agent/mibgroup/hardware/sensors/lmsensors_v2.c
1110 ===================================================================
1111 --- agent/mibgroup/hardware/sensors/lmsensors_v2.c (revision 0)
1112 +++ agent/mibgroup/hardware/sensors/lmsensors_v2.c (revision 16739)
1114 +#include <net-snmp/net-snmp-config.h>
1115 +#include <net-snmp/net-snmp-includes.h>
1116 +#include <net-snmp/agent/net-snmp-agent-includes.h>
1117 +#include <net-snmp/agent/hardware/sensors.h>
1119 +#include "util_funcs.h"
1121 +#include <sensors/sensors.h>
1123 +void netsnmp_sensor_arch_init( void ) {
1124 + FILE *fp = fopen("/etc/sensors.conf", "r");
1125 + DEBUGMSGTL(("sensors:arch", "Initialise LM Sensors module\n"));
1126 + sensors_init( fp );
1130 +netsnmp_sensor_arch_load(netsnmp_cache *cache, void *vp) {
1131 + netsnmp_sensor_info *sp;
1132 + const sensors_chip_name *chip;
1133 + const sensors_feature_data *data;
1136 + DEBUGMSGTL(("sensors:arch", "Reload LM Sensors module\n"));
1137 + while ((chip = sensors_get_detected_chips(&chip_nr))) {
1141 + while ((data = sensors_get_all_features(*chip, &a, &b))) {
1142 + DEBUGMSGTL(("sensors:arch:detail", "get_all_features (%d, %d)\n", a, b));
1143 + char *label = NULL;
1145 + int type = NETSNMP_SENSOR_TYPE_OTHER;
1147 + if ((data->mode & SENSORS_MODE_R) &&
1148 + (data->mapping == SENSORS_NO_MAPPING) &&
1149 + !sensors_get_label(*chip, data->number, &label) &&
1150 + !sensors_get_feature(*chip, data->number, &val)) {
1152 + DEBUGMSGTL(("sensors:arch:detail", "%s = %f\n", label, val));
1154 + * Determine the type of sensor from the description.
1156 + * If the text being looked for below is not in the label of a
1157 + * given sensor (e.g., the temp1 sensor has been labeled 'CPU'
1158 + * rather than 'CPU temp') it will be categorised as OTHER.
1160 + if (strstr(label, "V")) {
1161 + type = NETSNMP_SENSOR_TYPE_VOLTAGE_DC;
1163 + if (strstr(label, "fan") || strstr(label, "Fan")) {
1164 + type = NETSNMP_SENSOR_TYPE_RPM;
1166 + if (strstr(label, "temp") || strstr(label, "Temp")) {
1167 + type = NETSNMP_SENSOR_TYPE_TEMPERATURE;
1171 + * Use this type to create a new sensor entry
1172 + * (inserting it in the appropriate sub-containers)
1174 + sp = sensor_by_name( label, type );
1177 + sp->flags|= NETSNMP_SENSOR_FLAG_ACTIVE;
1184 + } /* end while data */
1185 + } /* end while chip */
1189 Index: agent/mibgroup/hardware/sensors/picld_sensors.h
1190 ===================================================================
1191 --- agent/mibgroup/hardware/sensors/picld_sensors.h (revision 0)
1192 +++ agent/mibgroup/hardware/sensors/picld_sensors.h (revision 16739)
1194 +config_require(hardware/sensors/hw_sensors)
1195 Index: agent/mibgroup/hardware/sensors/lmsensors_v3.c
1196 ===================================================================
1197 --- agent/mibgroup/hardware/sensors/lmsensors_v3.c (revision 0)
1198 +++ agent/mibgroup/hardware/sensors/lmsensors_v3.c (revision 16739)
1200 +#include <net-snmp/net-snmp-config.h>
1201 +#include <net-snmp/net-snmp-includes.h>
1202 +#include <net-snmp/agent/net-snmp-agent-includes.h>
1203 +#include <net-snmp/agent/hardware/sensors.h>
1205 +#include "util_funcs.h"
1207 +#include <sensors/sensors.h>
1210 +void netsnmp_sensor_arch_init( void ) {
1211 + FILE *fp = fopen("/etc/sensors.conf", "r");
1212 + DEBUGMSGTL(("sensors:arch", "Initialise v3 LM Sensors module\n"));
1213 + sensors_init( fp );
1217 +netsnmp_sensor_arch_load(netsnmp_cache *cache, void *vp) {
1218 + netsnmp_sensor_info *sp;
1219 + const sensors_chip_name *chip;
1220 + const sensors_feature *data;
1221 + const sensors_subfeature *data2;
1224 + DEBUGMSGTL(("sensors:arch", "Reload v3 LM Sensors module\n"));
1225 + while ((chip = sensors_get_detected_chips( NULL, &chip_nr))) {
1228 + while ((data = sensors_get_features( chip, &a))) {
1229 + DEBUGMSGTL(("sensors:arch:detail", "get_features (%s, %d)\n", data->name, data->number));
1233 + while ((data2 = sensors_get_all_subfeatures( chip, data, &b))) {
1234 + char *label = NULL;
1236 + int type = NETSNMP_SENSOR_TYPE_OTHER;
1238 + DEBUGMSGTL(("sensors:arch:detail", " get_subfeatures (%s, %d)\n", data2->name, data2->number));
1240 + * Check the type of this subfeature,
1241 + * concentrating on the main "input" measurements.
1243 + switch ( data2->type ) {
1244 + case SENSORS_SUBFEATURE_IN_INPUT:
1245 + type = NETSNMP_SENSOR_TYPE_VOLTAGE_DC;
1247 + case SENSORS_SUBFEATURE_FAN_INPUT:
1248 + type = NETSNMP_SENSOR_TYPE_RPM;
1250 + case SENSORS_SUBFEATURE_TEMP_INPUT:
1251 + type = NETSNMP_SENSOR_TYPE_TEMPERATURE;
1253 + case SENSORS_SUBFEATURE_VID:
1254 + type = NETSNMP_SENSOR_TYPE_VOLTAGE_DC;
1257 + /* Skip everything other than these basic sensor features - ??? */
1258 + DEBUGMSGTL(("sensors:arch:detail", " Skip type %x\n", data2->type));
1263 + * Get the name and value of this subfeature
1266 + if (!(label = sensors_get_label(chip, data))) {
1267 + DEBUGMSGTL(("sensors:arch:detail", " Can't get name (%s)\n", label));
1270 + if (sensors_get_value(chip, data2->number, &val) < 0) {
1271 + DEBUGMSGTL(("sensors:arch:detail", " Can't get value (%f)\n", val));
1275 + if (!(label = sensors_get_label(chip, data)) ||
1276 + (sensors_get_value(chip, data2->number, &val) < 0)) {
1277 + DEBUGMSGTL(("sensors:arch:detail", " Can't get name/value (%s, %f)\n", label, val));
1280 + DEBUGMSGTL(("sensors:arch:detail", "%s = %f\n", label, val));
1283 + * Use this type to create a new sensor entry
1284 + * (inserting it in the appropriate sub-containers)
1286 + sp = sensor_by_name( label, type );
1289 + sp->flags|= NETSNMP_SENSOR_FLAG_ACTIVE;
1295 + } /* end while data2 */
1296 + } /* end while data */
1297 + } /* end while chip */