1 /*****************************************************************************\
2 * $Id: ipmimonitoring-sensors.c,v 1.51 2016/11/02 23:46:24 chu11 Exp $
3 * $Id: ipmimonitoring-sel.c,v 1.51 2016/11/02 23:46:24 chu11 Exp $
4 *****************************************************************************
5 * Copyright (C) 2007-2015 Lawrence Livermore National Security, LLC.
6 * Copyright (C) 2006-2007 The Regents of the University of California.
7 * Produced at Lawrence Livermore National Laboratory (cf, DISCLAIMER).
8 * Written by Albert Chu <chu11@llnl.gov>
11 * This file is part of Ipmimonitoring, an IPMI sensor monitoring
12 * library. For details, see http://www.llnl.gov/linux/.
14 * Ipmimonitoring is free software; you can redistribute it and/or modify
15 * it under the terms of the GNU General Public License as published by the
16 * Free Software Foundation; either version 3 of the License, or (at your
17 * option) any later version.
19 * Ipmimonitoring is distributed in the hope that it will be useful, but
20 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
21 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
24 * You should have received a copy of the GNU General Public License along
25 * with Ipmimonitoring. If not, see <http://www.gnu.org/licenses/>.
26 \*****************************************************************************/
41 #include <ipmi_monitoring.h>
42 #include <ipmi_monitoring_bitmasks.h>
44 /* Communication Configuration - Initialize accordingly */
46 /* Hostname, NULL for In-band communication, non-null for a hostname */
47 char *hostname = NULL;
49 /* In-band Communication Configuration */
50 int driver_type = IPMI_MONITORING_DRIVER_TYPE_KCS; /* or -1 for default */
51 int disable_auto_probe = 0; /* probe for in-band device */
52 unsigned int driver_address = 0; /* not used if probing */
53 unsigned int register_spacing = 0; /* not used if probing */
54 char *driver_device = NULL; /* not used if probing */
56 /* Out-of-band Communication Configuration */
57 int protocol_version = IPMI_MONITORING_PROTOCOL_VERSION_1_5; /* or -1 for default */
58 char *username = "foousername";
59 char *password = "foopassword";
60 unsigned char *k_g = NULL;
61 unsigned int k_g_len = 0;
62 int privilege_level = IPMI_MONITORING_PRIVILEGE_LEVEL_USER; /* or -1 for default */
63 int authentication_type = IPMI_MONITORING_AUTHENTICATION_TYPE_MD5; /* or -1 for default */
64 int cipher_suite_id = 0; /* or -1 for default */
65 int session_timeout = 0; /* 0 for default */
66 int retransmission_timeout = 0; /* 0 for default */
68 /* Workarounds - specify workaround flags if necessary */
69 unsigned int workaround_flags = 0;
71 /* Initialize w/ record id numbers to only monitor specific record ids */
72 unsigned int record_ids[] = {0};
73 unsigned int record_ids_length = 0;
75 /* Initialize w/ sensor types to only monitor specific sensor types
76 * see ipmi_monitoring.h sensor types list.
78 unsigned int sensor_types[] = {0};
79 unsigned int sensor_types_length = 0;
81 /* Set to an appropriate alternate if desired */
82 char *sdr_cache_directory = "/tmp";
83 char *sensor_config_file = NULL;
85 /* Set to 1 or 0 to enable these sensor reading flags
86 * - See ipmi_monitoring.h for descriptions of these flags.
88 int reread_sdr_cache = 0;
89 int ignore_non_interpretable_sensors = 1;
90 int bridge_sensors = 0;
91 int interpret_oem_data = 0;
92 int shared_sensors = 0;
93 int discrete_reading = 0;
94 int ignore_scanning_disabled = 0;
95 int assume_bmc_owner = 0;
96 int entity_sensor_names = 0;
98 /* Initialization flags
100 * Most commonly bitwise OR IPMI_MONITORING_FLAGS_DEBUG and/or
101 * IPMI_MONITORING_FLAGS_DEBUG_IPMI_PACKETS for extra debugging
104 unsigned int ipmimonitoring_init_flags = 0;
108 // ----------------------------------------------------------------------------
109 // SEL only variables
111 /* Initialize w/ date range to only monitoring specific date range */
112 char *date_begin = NULL; /* use MM/DD/YYYY format */
113 char *date_end = NULL; /* use MM/DD/YYYY format */
115 int assume_system_event_record = 0;
117 char *sel_config_file = NULL;
120 // ----------------------------------------------------------------------------
121 // functions common to sensors and SEL
124 _init_ipmi_config (struct ipmi_monitoring_ipmi_config *ipmi_config)
126 assert (ipmi_config);
128 ipmi_config->driver_type = driver_type;
129 ipmi_config->disable_auto_probe = disable_auto_probe;
130 ipmi_config->driver_address = driver_address;
131 ipmi_config->register_spacing = register_spacing;
132 ipmi_config->driver_device = driver_device;
134 ipmi_config->protocol_version = protocol_version;
135 ipmi_config->username = username;
136 ipmi_config->password = password;
137 ipmi_config->k_g = k_g;
138 ipmi_config->k_g_len = k_g_len;
139 ipmi_config->privilege_level = privilege_level;
140 ipmi_config->authentication_type = authentication_type;
141 ipmi_config->cipher_suite_id = cipher_suite_id;
142 ipmi_config->session_timeout_len = session_timeout;
143 ipmi_config->retransmission_timeout_len = retransmission_timeout;
145 ipmi_config->workaround_flags = workaround_flags;
148 #ifdef NETDATA_COMMENTED
150 _get_sensor_type_string (int sensor_type)
154 case IPMI_MONITORING_SENSOR_TYPE_RESERVED:
156 case IPMI_MONITORING_SENSOR_TYPE_TEMPERATURE:
157 return ("Temperature");
158 case IPMI_MONITORING_SENSOR_TYPE_VOLTAGE:
160 case IPMI_MONITORING_SENSOR_TYPE_CURRENT:
162 case IPMI_MONITORING_SENSOR_TYPE_FAN:
164 case IPMI_MONITORING_SENSOR_TYPE_PHYSICAL_SECURITY:
165 return ("Physical Security");
166 case IPMI_MONITORING_SENSOR_TYPE_PLATFORM_SECURITY_VIOLATION_ATTEMPT:
167 return ("Platform Security Violation Attempt");
168 case IPMI_MONITORING_SENSOR_TYPE_PROCESSOR:
169 return ("Processor");
170 case IPMI_MONITORING_SENSOR_TYPE_POWER_SUPPLY:
171 return ("Power Supply");
172 case IPMI_MONITORING_SENSOR_TYPE_POWER_UNIT:
173 return ("Power Unit");
174 case IPMI_MONITORING_SENSOR_TYPE_COOLING_DEVICE:
175 return ("Cooling Device");
176 case IPMI_MONITORING_SENSOR_TYPE_OTHER_UNITS_BASED_SENSOR:
177 return ("Other Units Based Sensor");
178 case IPMI_MONITORING_SENSOR_TYPE_MEMORY:
180 case IPMI_MONITORING_SENSOR_TYPE_DRIVE_SLOT:
181 return ("Drive Slot");
182 case IPMI_MONITORING_SENSOR_TYPE_POST_MEMORY_RESIZE:
183 return ("POST Memory Resize");
184 case IPMI_MONITORING_SENSOR_TYPE_SYSTEM_FIRMWARE_PROGRESS:
185 return ("System Firmware Progress");
186 case IPMI_MONITORING_SENSOR_TYPE_EVENT_LOGGING_DISABLED:
187 return ("Event Logging Disabled");
188 case IPMI_MONITORING_SENSOR_TYPE_WATCHDOG1:
189 return ("Watchdog 1");
190 case IPMI_MONITORING_SENSOR_TYPE_SYSTEM_EVENT:
191 return ("System Event");
192 case IPMI_MONITORING_SENSOR_TYPE_CRITICAL_INTERRUPT:
193 return ("Critical Interrupt");
194 case IPMI_MONITORING_SENSOR_TYPE_BUTTON_SWITCH:
195 return ("Button/Switch");
196 case IPMI_MONITORING_SENSOR_TYPE_MODULE_BOARD:
197 return ("Module/Board");
198 case IPMI_MONITORING_SENSOR_TYPE_MICROCONTROLLER_COPROCESSOR:
199 return ("Microcontroller/Coprocessor");
200 case IPMI_MONITORING_SENSOR_TYPE_ADD_IN_CARD:
201 return ("Add In Card");
202 case IPMI_MONITORING_SENSOR_TYPE_CHASSIS:
204 case IPMI_MONITORING_SENSOR_TYPE_CHIP_SET:
206 case IPMI_MONITORING_SENSOR_TYPE_OTHER_FRU:
207 return ("Other Fru");
208 case IPMI_MONITORING_SENSOR_TYPE_CABLE_INTERCONNECT:
209 return ("Cable/Interconnect");
210 case IPMI_MONITORING_SENSOR_TYPE_TERMINATOR:
211 return ("Terminator");
212 case IPMI_MONITORING_SENSOR_TYPE_SYSTEM_BOOT_INITIATED:
213 return ("System Boot Initiated");
214 case IPMI_MONITORING_SENSOR_TYPE_BOOT_ERROR:
215 return ("Boot Error");
216 case IPMI_MONITORING_SENSOR_TYPE_OS_BOOT:
218 case IPMI_MONITORING_SENSOR_TYPE_OS_CRITICAL_STOP:
219 return ("OS Critical Stop");
220 case IPMI_MONITORING_SENSOR_TYPE_SLOT_CONNECTOR:
221 return ("Slot/Connector");
222 case IPMI_MONITORING_SENSOR_TYPE_SYSTEM_ACPI_POWER_STATE:
223 return ("System ACPI Power State");
224 case IPMI_MONITORING_SENSOR_TYPE_WATCHDOG2:
225 return ("Watchdog 2");
226 case IPMI_MONITORING_SENSOR_TYPE_PLATFORM_ALERT:
227 return ("Platform Alert");
228 case IPMI_MONITORING_SENSOR_TYPE_ENTITY_PRESENCE:
229 return ("Entity Presence");
230 case IPMI_MONITORING_SENSOR_TYPE_MONITOR_ASIC_IC:
231 return ("Monitor ASIC/IC");
232 case IPMI_MONITORING_SENSOR_TYPE_LAN:
234 case IPMI_MONITORING_SENSOR_TYPE_MANAGEMENT_SUBSYSTEM_HEALTH:
235 return ("Management Subsystem Health");
236 case IPMI_MONITORING_SENSOR_TYPE_BATTERY:
238 case IPMI_MONITORING_SENSOR_TYPE_SESSION_AUDIT:
239 return ("Session Audit");
240 case IPMI_MONITORING_SENSOR_TYPE_VERSION_CHANGE:
241 return ("Version Change");
242 case IPMI_MONITORING_SENSOR_TYPE_FRU_STATE:
243 return ("FRU State");
246 return ("Unrecognized");
248 #endif // NETDATA_COMMENTED
251 // ----------------------------------------------------------------------------
252 // BEGIN NETDATA CODE
254 static int debug = 0;
256 static int netdata_update_every = 5;
257 static int netdata_priority = 90000;
259 static size_t netdata_sensors_updated = 0;
260 static size_t netdata_sensors_collected = 0;
261 static size_t netdata_sel_events = 0;
271 int sensor_reading_type;
274 uint32_t uint32_value;
283 } *sensors_root = NULL;
285 static void netdata_mark_as_not_updated() {
287 for(sn = sensors_root; sn ;sn = sn->next)
288 sn->updated = sn->sent = 0;
290 netdata_sensors_updated = 0;
291 netdata_sensors_collected = 0;
292 netdata_sel_events = 0;
295 static void send_chart_to_netdata_for_units(int units) {
299 case IPMI_MONITORING_SENSOR_UNITS_CELSIUS:
300 printf("CHART ipmi.temperatures_c '' 'System Celcius Temperatures read by IPMI' 'Celcius' 'temperatures' 'ipmi.temperatures_c' 'line' %d %d\n"
302 , netdata_update_every
306 case IPMI_MONITORING_SENSOR_UNITS_FAHRENHEIT:
307 printf("CHART ipmi.temperatures_f '' 'System Fahrenheit Temperatures read by IPMI' 'Fahrenheit' 'temperatures' 'ipmi.temperatures_f' 'line' %d %d\n"
309 , netdata_update_every
313 case IPMI_MONITORING_SENSOR_UNITS_VOLTS:
314 printf("CHART ipmi.volts '' 'System Voltages read by IPMI' 'Volts' 'voltages' 'ipmi.voltages' 'line' %d %d\n"
316 , netdata_update_every
320 case IPMI_MONITORING_SENSOR_UNITS_AMPS:
321 printf("CHART ipmi.amps '' 'System Current read by IPMI' 'Amps' 'current' 'ipmi.amps' 'line' %d %d\n"
323 , netdata_update_every
327 case IPMI_MONITORING_SENSOR_UNITS_RPM:
328 printf("CHART ipmi.rpm '' 'System Fans read by IPMI' 'RPM' 'fans' 'ipmi.rpm' 'line' %d %d\n"
330 , netdata_update_every
334 case IPMI_MONITORING_SENSOR_UNITS_WATTS:
335 printf("CHART ipmi.watts '' 'System Power read by IPMI' 'Watts' 'power' 'ipmi.watts' 'line' %d %d\n"
337 , netdata_update_every
341 case IPMI_MONITORING_SENSOR_UNITS_PERCENT:
342 printf("CHART ipmi.percent '' 'System Metrics read by IPMI' '%%' 'other' 'ipmi.percent' 'line' %d %d\n"
344 , netdata_update_every
349 for(sn = sensors_root; sn; sn = sn->next)
350 if(sn->sensor_units == units)
355 for(sn = sensors_root; sn; sn = sn->next) {
356 if(sn->sensor_units == units && sn->updated && !sn->ignore) {
359 switch(sn->sensor_reading_type) {
360 case IPMI_MONITORING_SENSOR_READING_TYPE_UNSIGNED_INTEGER8_BOOL:
361 case IPMI_MONITORING_SENSOR_READING_TYPE_UNSIGNED_INTEGER32:
362 printf("DIMENSION i%d_n%d_r%d '%s i%d' absolute 1 1\n"
365 , sn->sensor_reading_type
371 case IPMI_MONITORING_SENSOR_READING_TYPE_DOUBLE:
372 printf("DIMENSION i%d_n%d_r%d '%s i%d' absolute 1 1000\n"
375 , sn->sensor_reading_type
389 static void send_metrics_to_netdata_for_units(int units) {
393 case IPMI_MONITORING_SENSOR_UNITS_CELSIUS:
394 printf("BEGIN ipmi.temperatures_c\n");
397 case IPMI_MONITORING_SENSOR_UNITS_FAHRENHEIT:
398 printf("BEGIN ipmi.temperatures_f\n");
401 case IPMI_MONITORING_SENSOR_UNITS_VOLTS:
402 printf("BEGIN ipmi.volts\n");
405 case IPMI_MONITORING_SENSOR_UNITS_AMPS:
406 printf("BEGIN ipmi.amps\n");
409 case IPMI_MONITORING_SENSOR_UNITS_RPM:
410 printf("BEGIN ipmi.rpm\n");
413 case IPMI_MONITORING_SENSOR_UNITS_WATTS:
414 printf("BEGIN ipmi.watts\n");
417 case IPMI_MONITORING_SENSOR_UNITS_PERCENT:
418 printf("BEGIN ipmi.percent\n");
422 for(sn = sensors_root; sn; sn = sn->next)
423 if(sn->sensor_units == units)
428 for(sn = sensors_root; sn; sn = sn->next) {
429 if(sn->sensor_units == units && sn->updated && !sn->sent && !sn->ignore) {
430 netdata_sensors_updated++;
434 switch(sn->sensor_reading_type) {
435 case IPMI_MONITORING_SENSOR_READING_TYPE_UNSIGNED_INTEGER8_BOOL:
436 printf("SET i%d_n%d_r%d = %u\n"
439 , sn->sensor_reading_type
440 , sn->sensor_reading.bool_value
444 case IPMI_MONITORING_SENSOR_READING_TYPE_UNSIGNED_INTEGER32:
445 printf("SET i%d_n%d_r%d = %u\n"
448 , sn->sensor_reading_type
449 , sn->sensor_reading.uint32_value
453 case IPMI_MONITORING_SENSOR_READING_TYPE_DOUBLE:
454 printf("SET i%d_n%d_r%d = %lld\n"
457 , sn->sensor_reading_type
458 , (long long int)(sn->sensor_reading.double_value * 1000)
472 static void send_metrics_to_netdata() {
473 static int sel_chart_generated = 0;
476 if(!sel_chart_generated) {
477 printf("CHART ipmi.events '' 'IPMI Events' 'events' 'events' 'ipmi.sel' 'area' %d %d\n"
479 , netdata_update_every
481 printf("DIMENSION events '' absolute 1 1\n");
484 // generate the CHART/DIMENSION lines, if we have to
485 for(sn = sensors_root; sn; sn = sn->next)
486 if(sn->updated && !sn->exposed && !sn->ignore)
487 send_chart_to_netdata_for_units(sn->sensor_units);
489 printf("BEGIN ipmi.events\nSET events = %zu\nEND\n", netdata_sel_events);
491 // send metrics to netdata
492 for(sn = sensors_root; sn; sn = sn->next)
493 if(sn->updated && sn->exposed && !sn->sent && !sn->ignore)
494 send_metrics_to_netdata_for_units(sn->sensor_units);
498 static void netdata_get_sensor(
504 , int sensor_reading_type
506 , void *sensor_reading
508 // find the sensor record
510 for(sn = sensors_root; sn ;sn = sn->next)
511 if( sn->record_id == record_id &&
512 sn->sensor_number == sensor_number &&
513 sn->sensor_reading_type == sensor_reading_type &&
514 sn->sensor_units == sensor_units &&
515 !strcmp(sn->sensor_name, sensor_name)
520 // not found, create it
522 sn = calloc(1, sizeof(struct sensor));
524 fprintf(stderr, "freeipmi.plugin: cannot allocate %zu bytes of memory.", sizeof(struct sensor));
528 sn->record_id = record_id;
529 sn->sensor_number = sensor_number;
530 sn->sensor_type = sensor_type;
531 sn->sensor_state = sensor_state;
532 sn->sensor_units = sensor_units;
533 sn->sensor_reading_type = sensor_reading_type;
534 sn->sensor_name = strdup(sensor_name);
535 if(!sn->sensor_name) {
536 fprintf(stderr, "freeipmi.plugin: cannot allocate %zu bytes of memory.", strlen(sensor_name));
540 sn->next = sensors_root;
544 switch(sensor_reading_type) {
545 case IPMI_MONITORING_SENSOR_READING_TYPE_UNSIGNED_INTEGER8_BOOL:
546 sn->sensor_reading.bool_value = *((uint8_t *)sensor_reading);
548 netdata_sensors_collected++;
551 case IPMI_MONITORING_SENSOR_READING_TYPE_UNSIGNED_INTEGER32:
552 sn->sensor_reading.uint32_value = *((uint32_t *)sensor_reading);
554 netdata_sensors_collected++;
557 case IPMI_MONITORING_SENSOR_READING_TYPE_DOUBLE:
558 sn->sensor_reading.double_value = *((double *)sensor_reading);
560 netdata_sensors_collected++;
568 /* switch(sensor_state) {
569 case IPMI_MONITORING_STATE_NOMINAL:
570 case IPMI_MONITORING_STATE_WARNING:
571 case IPMI_MONITORING_STATE_CRITICAL:
578 static void netdata_get_sel(
580 , int record_type_class
584 (void)record_type_class;
587 netdata_sel_events++;
591 static unsigned long long now_realtime_usec() {
593 gettimeofday(&tv, NULL);
594 return tv.tv_sec * 1000000ULL + tv.tv_usec;
598 // ----------------------------------------------------------------------------
601 /* This is an example of how to use the libipmimonitoring library to
602 * read and monitor sensors.
604 * At the top of this file, you'll find a number of variables for
605 * configuration of IPMI communication and what sensors you are
606 * interested in monitoring. Those variables are used in the
607 * libipmimonitoring calls below.
609 * Hopefully this example will be sufficient to help anyone program
610 * IPMI monitoring software for their environment.
612 * To compile, linking against the library should be sufficient for
613 * most environments. e.g.
615 * gcc -o freeipmi.plugin freeipmi_plugin.c -lipmimonitoring
619 _ipmimonitoring_sensors (struct ipmi_monitoring_ipmi_config *ipmi_config)
621 ipmi_monitoring_ctx_t ctx = NULL;
622 unsigned int sensor_reading_flags = 0;
627 if (!(ctx = ipmi_monitoring_ctx_create ()))
629 perror ("ipmi_monitoring_ctx_create:");
633 if (sdr_cache_directory)
635 if (ipmi_monitoring_ctx_sdr_cache_directory (ctx,
636 sdr_cache_directory) < 0)
639 "ipmi_monitoring_ctx_sdr_cache_directory: %s\n",
640 ipmi_monitoring_ctx_errormsg (ctx));
645 /* Must call otherwise only default interpretations ever used */
646 if (sensor_config_file)
648 if (ipmi_monitoring_ctx_sensor_config_file (ctx,
649 sensor_config_file) < 0)
652 "ipmi_monitoring_ctx_sensor_config_file: %s\n",
653 ipmi_monitoring_ctx_errormsg (ctx));
659 if (ipmi_monitoring_ctx_sensor_config_file (ctx, NULL) < 0)
662 "ipmi_monitoring_ctx_sensor_config_file: %s\n",
663 ipmi_monitoring_ctx_errormsg (ctx));
668 if (reread_sdr_cache)
669 sensor_reading_flags |= IPMI_MONITORING_SENSOR_READING_FLAGS_REREAD_SDR_CACHE;
671 if (ignore_non_interpretable_sensors)
672 sensor_reading_flags |= IPMI_MONITORING_SENSOR_READING_FLAGS_IGNORE_NON_INTERPRETABLE_SENSORS;
675 sensor_reading_flags |= IPMI_MONITORING_SENSOR_READING_FLAGS_BRIDGE_SENSORS;
677 if (interpret_oem_data)
678 sensor_reading_flags |= IPMI_MONITORING_SENSOR_READING_FLAGS_INTERPRET_OEM_DATA;
681 sensor_reading_flags |= IPMI_MONITORING_SENSOR_READING_FLAGS_SHARED_SENSORS;
683 if (discrete_reading)
684 sensor_reading_flags |= IPMI_MONITORING_SENSOR_READING_FLAGS_DISCRETE_READING;
686 if (ignore_scanning_disabled)
687 sensor_reading_flags |= IPMI_MONITORING_SENSOR_READING_FLAGS_IGNORE_SCANNING_DISABLED;
689 if (assume_bmc_owner)
690 sensor_reading_flags |= IPMI_MONITORING_SENSOR_READING_FLAGS_ASSUME_BMC_OWNER;
692 #ifdef IPMI_MONITORING_SENSOR_READING_FLAGS_ENTITY_SENSOR_NAMES
693 if (entity_sensor_names)
694 sensor_reading_flags |= IPMI_MONITORING_SENSOR_READING_FLAGS_ENTITY_SENSOR_NAMES;
695 #endif // IPMI_MONITORING_SENSOR_READING_FLAGS_ENTITY_SENSOR_NAMES
697 if (!record_ids_length && !sensor_types_length)
699 if ((sensor_count = ipmi_monitoring_sensor_readings_by_record_id (ctx,
702 sensor_reading_flags,
709 "ipmi_monitoring_sensor_readings_by_record_id: %s\n",
710 ipmi_monitoring_ctx_errormsg (ctx));
714 else if (record_ids_length)
716 if ((sensor_count = ipmi_monitoring_sensor_readings_by_record_id (ctx,
719 sensor_reading_flags,
726 "ipmi_monitoring_sensor_readings_by_record_id: %s\n",
727 ipmi_monitoring_ctx_errormsg (ctx));
733 if ((sensor_count = ipmi_monitoring_sensor_readings_by_sensor_type (ctx,
736 sensor_reading_flags,
743 "ipmi_monitoring_sensor_readings_by_sensor_type: %s\n",
744 ipmi_monitoring_ctx_errormsg (ctx));
749 #ifdef NETDATA_COMMENTED
750 printf ("%s, %s, %s, %s, %s, %s, %s, %s, %s, %s\n",
758 "Sensor Event/Reading Type Code",
759 "Sensor Event Bitmask",
760 "Sensor Event String");
761 #endif // NETDATA_COMMENTED
763 for (i = 0; i < sensor_count; i++, ipmi_monitoring_sensor_iterator_next (ctx))
765 int record_id, sensor_number, sensor_type, sensor_state, sensor_units,
768 #ifdef NETDATA_COMMENTED
769 int sensor_bitmask_type, sensor_bitmask, event_reading_type_code;
770 char **sensor_bitmask_strings = NULL;
771 const char *sensor_type_str;
772 const char *sensor_state_str;
773 #endif // NETDATA_COMMENTED
775 char *sensor_name = NULL;
776 void *sensor_reading;
778 if ((record_id = ipmi_monitoring_sensor_read_record_id (ctx)) < 0)
781 "ipmi_monitoring_sensor_read_record_id: %s\n",
782 ipmi_monitoring_ctx_errormsg (ctx));
786 if ((sensor_number = ipmi_monitoring_sensor_read_sensor_number (ctx)) < 0)
789 "ipmi_monitoring_sensor_read_sensor_number: %s\n",
790 ipmi_monitoring_ctx_errormsg (ctx));
794 if ((sensor_type = ipmi_monitoring_sensor_read_sensor_type (ctx)) < 0)
797 "ipmi_monitoring_sensor_read_sensor_type: %s\n",
798 ipmi_monitoring_ctx_errormsg (ctx));
802 if (!(sensor_name = ipmi_monitoring_sensor_read_sensor_name (ctx)))
805 "ipmi_monitoring_sensor_read_sensor_name: %s\n",
806 ipmi_monitoring_ctx_errormsg (ctx));
810 if ((sensor_state = ipmi_monitoring_sensor_read_sensor_state (ctx)) < 0)
813 "ipmi_monitoring_sensor_read_sensor_state: %s\n",
814 ipmi_monitoring_ctx_errormsg (ctx));
818 if ((sensor_units = ipmi_monitoring_sensor_read_sensor_units (ctx)) < 0)
821 "ipmi_monitoring_sensor_read_sensor_units: %s\n",
822 ipmi_monitoring_ctx_errormsg (ctx));
826 #ifdef NETDATA_COMMENTED
827 if ((sensor_bitmask_type = ipmi_monitoring_sensor_read_sensor_bitmask_type (ctx)) < 0)
830 "ipmi_monitoring_sensor_read_sensor_bitmask_type: %s\n",
831 ipmi_monitoring_ctx_errormsg (ctx));
834 if ((sensor_bitmask = ipmi_monitoring_sensor_read_sensor_bitmask (ctx)) < 0)
837 "ipmi_monitoring_sensor_read_sensor_bitmask: %s\n",
838 ipmi_monitoring_ctx_errormsg (ctx));
842 if (!(sensor_bitmask_strings = ipmi_monitoring_sensor_read_sensor_bitmask_strings (ctx)))
845 "ipmi_monitoring_sensor_read_sensor_bitmask_strings: %s\n",
846 ipmi_monitoring_ctx_errormsg (ctx));
849 #endif // NETDATA_COMMENTED
851 if ((sensor_reading_type = ipmi_monitoring_sensor_read_sensor_reading_type (ctx)) < 0)
854 "ipmi_monitoring_sensor_read_sensor_reading_type: %s\n",
855 ipmi_monitoring_ctx_errormsg (ctx));
859 sensor_reading = ipmi_monitoring_sensor_read_sensor_reading (ctx);
861 #ifdef NETDATA_COMMENTED
862 if ((event_reading_type_code = ipmi_monitoring_sensor_read_event_reading_type_code (ctx)) < 0)
865 "ipmi_monitoring_sensor_read_event_reading_type_code: %s\n",
866 ipmi_monitoring_ctx_errormsg (ctx));
869 #endif // NETDATA_COMMENTED
877 , sensor_reading_type
882 #ifdef NETDATA_COMMENTED
883 if (!strlen (sensor_name))
886 sensor_type_str = _get_sensor_type_string (sensor_type);
888 printf ("%u, %s, %u, %s",
894 if (sensor_state == IPMI_MONITORING_STATE_NOMINAL)
895 sensor_state_str = "Nominal";
896 else if (sensor_state == IPMI_MONITORING_STATE_WARNING)
897 sensor_state_str = "Warning";
898 else if (sensor_state == IPMI_MONITORING_STATE_CRITICAL)
899 sensor_state_str = "Critical";
901 sensor_state_str = "N/A";
903 printf (", %s", sensor_state_str);
907 const char *sensor_units_str;
909 if (sensor_reading_type == IPMI_MONITORING_SENSOR_READING_TYPE_UNSIGNED_INTEGER8_BOOL)
911 (*((uint8_t *)sensor_reading) ? "true" : "false"));
912 else if (sensor_reading_type == IPMI_MONITORING_SENSOR_READING_TYPE_UNSIGNED_INTEGER32)
914 *((uint32_t *)sensor_reading));
915 else if (sensor_reading_type == IPMI_MONITORING_SENSOR_READING_TYPE_DOUBLE)
917 *((double *)sensor_reading));
921 if (sensor_units == IPMI_MONITORING_SENSOR_UNITS_CELSIUS)
922 sensor_units_str = "C";
923 else if (sensor_units == IPMI_MONITORING_SENSOR_UNITS_FAHRENHEIT)
924 sensor_units_str = "F";
925 else if (sensor_units == IPMI_MONITORING_SENSOR_UNITS_VOLTS)
926 sensor_units_str = "V";
927 else if (sensor_units == IPMI_MONITORING_SENSOR_UNITS_AMPS)
928 sensor_units_str = "A";
929 else if (sensor_units == IPMI_MONITORING_SENSOR_UNITS_RPM)
930 sensor_units_str = "RPM";
931 else if (sensor_units == IPMI_MONITORING_SENSOR_UNITS_WATTS)
932 sensor_units_str = "W";
933 else if (sensor_units == IPMI_MONITORING_SENSOR_UNITS_PERCENT)
934 sensor_units_str = "%";
936 sensor_units_str = "N/A";
938 printf (", %s", sensor_units_str);
941 printf (", N/A, N/A");
943 printf (", %Xh", event_reading_type_code);
945 /* It is possible you may want to monitor specific event
946 * conditions that may occur. If that is the case, you may want
947 * to check out what specific bitmask type and bitmask events
948 * occurred. See ipmi_monitoring_bitmasks.h for a list of
949 * bitmasks and types.
952 if (sensor_bitmask_type != IPMI_MONITORING_SENSOR_BITMASK_TYPE_UNKNOWN)
953 printf (", %Xh", sensor_bitmask);
957 if (sensor_bitmask_type != IPMI_MONITORING_SENSOR_BITMASK_TYPE_UNKNOWN)
963 while (sensor_bitmask_strings[i])
968 sensor_bitmask_strings[i]);
977 #endif // NETDATA_COMMENTED
983 ipmi_monitoring_ctx_destroy (ctx);
988 /* This is an example of how to use the libipmimonitoring library to
989 * read and monitor the SEL.
991 * At the top of this file, you'll find a number of variables for
992 * configuration of IPMI communication and what SEL records you are
993 * interested in monitoring. Those variables are used in the
994 * libipmimonitoring calls below.
996 * Hopefully this example will be sufficient to help anyone program
997 * IPMI monitoring software for their environment.
999 * To compile, linking against the library should be sufficient for
1000 * most environments. e.g.
1002 * gcc -o ipmimonitoring-sel ipmimonitoring-sel.c -lipmimonitoring
1005 /* Communication Configuration - Initialize accordingly */
1008 _ipmimonitoring_sel (struct ipmi_monitoring_ipmi_config *ipmi_config)
1010 ipmi_monitoring_ctx_t ctx = NULL;
1011 unsigned int sel_flags = 0;
1016 if (!(ctx = ipmi_monitoring_ctx_create ()))
1018 perror ("ipmi_monitoring_ctx_create:");
1022 if (sdr_cache_directory)
1024 if (ipmi_monitoring_ctx_sdr_cache_directory (ctx,
1025 sdr_cache_directory) < 0)
1028 "ipmi_monitoring_ctx_sdr_cache_directory: %s\n",
1029 ipmi_monitoring_ctx_errormsg (ctx));
1034 /* Must call otherwise only default interpretations ever used */
1035 if (sel_config_file)
1037 if (ipmi_monitoring_ctx_sel_config_file (ctx,
1038 sel_config_file) < 0)
1041 "ipmi_monitoring_ctx_sel_config_file: %s\n",
1042 ipmi_monitoring_ctx_errormsg (ctx));
1048 if (ipmi_monitoring_ctx_sel_config_file (ctx, NULL) < 0)
1051 "ipmi_monitoring_ctx_sel_config_file: %s\n",
1052 ipmi_monitoring_ctx_errormsg (ctx));
1057 if (reread_sdr_cache)
1058 sel_flags |= IPMI_MONITORING_SEL_FLAGS_REREAD_SDR_CACHE;
1060 if (interpret_oem_data)
1061 sel_flags |= IPMI_MONITORING_SEL_FLAGS_INTERPRET_OEM_DATA;
1063 if (assume_system_event_record)
1064 sel_flags |= IPMI_MONITORING_SEL_FLAGS_ASSUME_SYSTEM_EVENT_RECORD;
1066 #ifdef IPMI_MONITORING_SEL_FLAGS_ENTITY_SENSOR_NAMES
1067 if (entity_sensor_names)
1068 sel_flags |= IPMI_MONITORING_SEL_FLAGS_ENTITY_SENSOR_NAMES;
1069 #endif // IPMI_MONITORING_SEL_FLAGS_ENTITY_SENSOR_NAMES
1071 if (record_ids_length)
1073 if ((sel_count = ipmi_monitoring_sel_by_record_id (ctx,
1083 "ipmi_monitoring_sel_by_record_id: %s\n",
1084 ipmi_monitoring_ctx_errormsg (ctx));
1088 else if (sensor_types_length)
1090 if ((sel_count = ipmi_monitoring_sel_by_sensor_type (ctx,
1095 sensor_types_length,
1100 "ipmi_monitoring_sel_by_sensor_type: %s\n",
1101 ipmi_monitoring_ctx_errormsg (ctx));
1108 if ((sel_count = ipmi_monitoring_sel_by_date_range (ctx,
1118 "ipmi_monitoring_sel_by_sensor_type: %s\n",
1119 ipmi_monitoring_ctx_errormsg (ctx));
1125 if ((sel_count = ipmi_monitoring_sel_by_record_id (ctx,
1135 "ipmi_monitoring_sel_by_record_id: %s\n",
1136 ipmi_monitoring_ctx_errormsg (ctx));
1141 #ifdef NETDATA_COMMENTED
1142 printf ("%s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s\n",
1153 "Event Offset String");
1154 #endif // NETDATA_COMMENTED
1156 for (i = 0; i < sel_count; i++, ipmi_monitoring_sel_iterator_next (ctx))
1158 int record_id, record_type, sel_state, record_type_class;
1159 #ifdef NETDATA_COMMENTED
1160 int sensor_type, sensor_number, event_direction,
1161 event_offset_type, event_offset, event_type_code, manufacturer_id;
1162 unsigned int timestamp, event_data1, event_data2, event_data3;
1163 char *event_offset_string = NULL;
1164 const char *sensor_type_str;
1165 const char *event_direction_str;
1166 const char *sel_state_str;
1167 char *sensor_name = NULL;
1168 unsigned char oem_data[64];
1171 #endif // NETDATA_COMMENTED
1173 if ((record_id = ipmi_monitoring_sel_read_record_id (ctx)) < 0)
1176 "ipmi_monitoring_sel_read_record_id: %s\n",
1177 ipmi_monitoring_ctx_errormsg (ctx));
1181 if ((record_type = ipmi_monitoring_sel_read_record_type (ctx)) < 0)
1184 "ipmi_monitoring_sel_read_record_type: %s\n",
1185 ipmi_monitoring_ctx_errormsg (ctx));
1189 if ((record_type_class = ipmi_monitoring_sel_read_record_type_class (ctx)) < 0)
1192 "ipmi_monitoring_sel_read_record_type_class: %s\n",
1193 ipmi_monitoring_ctx_errormsg (ctx));
1197 if ((sel_state = ipmi_monitoring_sel_read_sel_state (ctx)) < 0)
1200 "ipmi_monitoring_sel_read_sel_state: %s\n",
1201 ipmi_monitoring_ctx_errormsg (ctx));
1211 #ifdef NETDATA_COMMENTED
1212 if (sel_state == IPMI_MONITORING_STATE_NOMINAL)
1213 sel_state_str = "Nominal";
1214 else if (sel_state == IPMI_MONITORING_STATE_WARNING)
1215 sel_state_str = "Warning";
1216 else if (sel_state == IPMI_MONITORING_STATE_CRITICAL)
1217 sel_state_str = "Critical";
1219 sel_state_str = "N/A";
1221 printf ("%u, %u, %s",
1226 if (record_type_class == IPMI_MONITORING_SEL_RECORD_TYPE_CLASS_SYSTEM_EVENT_RECORD
1227 || record_type_class == IPMI_MONITORING_SEL_RECORD_TYPE_CLASS_TIMESTAMPED_OEM_RECORD)
1230 if (ipmi_monitoring_sel_read_timestamp (ctx, ×tamp) < 0)
1233 "ipmi_monitoring_sel_read_timestamp: %s\n",
1234 ipmi_monitoring_ctx_errormsg (ctx));
1238 /* XXX: This should be converted to a nice date output using
1239 * your favorite timestamp -> string conversion functions.
1241 printf (", %u", timestamp);
1246 if (record_type_class == IPMI_MONITORING_SEL_RECORD_TYPE_CLASS_SYSTEM_EVENT_RECORD)
1248 /* If you are integrating ipmimonitoring SEL into a monitoring application,
1249 * you may wish to count the number of times a specific error occurred
1250 * and report that to the monitoring application.
1252 * In this particular case, you'll probably want to check out
1253 * what sensor type each SEL event is reporting, the
1254 * event offset type, and the specific event offset that occurred.
1256 * See ipmi_monitoring_offsets.h for a list of event offsets
1260 if (!(sensor_name = ipmi_monitoring_sel_read_sensor_name (ctx)))
1263 "ipmi_monitoring_sel_read_sensor_name: %s\n",
1264 ipmi_monitoring_ctx_errormsg (ctx));
1268 if ((sensor_type = ipmi_monitoring_sel_read_sensor_type (ctx)) < 0)
1271 "ipmi_monitoring_sel_read_sensor_type: %s\n",
1272 ipmi_monitoring_ctx_errormsg (ctx));
1276 if ((sensor_number = ipmi_monitoring_sel_read_sensor_number (ctx)) < 0)
1279 "ipmi_monitoring_sel_read_sensor_number: %s\n",
1280 ipmi_monitoring_ctx_errormsg (ctx));
1284 if ((event_direction = ipmi_monitoring_sel_read_event_direction (ctx)) < 0)
1287 "ipmi_monitoring_sel_read_event_direction: %s\n",
1288 ipmi_monitoring_ctx_errormsg (ctx));
1292 if ((event_type_code = ipmi_monitoring_sel_read_event_type_code (ctx)) < 0)
1295 "ipmi_monitoring_sel_read_event_type_code: %s\n",
1296 ipmi_monitoring_ctx_errormsg (ctx));
1300 if (ipmi_monitoring_sel_read_event_data (ctx,
1306 "ipmi_monitoring_sel_read_event_data: %s\n",
1307 ipmi_monitoring_ctx_errormsg (ctx));
1311 if ((event_offset_type = ipmi_monitoring_sel_read_event_offset_type (ctx)) < 0)
1314 "ipmi_monitoring_sel_read_event_offset_type: %s\n",
1315 ipmi_monitoring_ctx_errormsg (ctx));
1319 if ((event_offset = ipmi_monitoring_sel_read_event_offset (ctx)) < 0)
1322 "ipmi_monitoring_sel_read_event_offset: %s\n",
1323 ipmi_monitoring_ctx_errormsg (ctx));
1327 if (!(event_offset_string = ipmi_monitoring_sel_read_event_offset_string (ctx)))
1330 "ipmi_monitoring_sel_read_event_offset_string: %s\n",
1331 ipmi_monitoring_ctx_errormsg (ctx));
1335 if (!strlen (sensor_name))
1336 sensor_name = "N/A";
1338 sensor_type_str = _get_sensor_type_string (sensor_type);
1340 if (event_direction == IPMI_MONITORING_SEL_EVENT_DIRECTION_ASSERTION)
1341 event_direction_str = "Assertion";
1343 event_direction_str = "Deassertion";
1345 printf (", %s, %s, %u, %s, %Xh, %Xh-%Xh-%Xh",
1349 event_direction_str,
1355 if (event_offset_type != IPMI_MONITORING_EVENT_OFFSET_TYPE_UNKNOWN)
1356 printf (", %Xh", event_offset);
1360 if (event_offset_type != IPMI_MONITORING_EVENT_OFFSET_TYPE_UNKNOWN)
1361 printf (", %s", event_offset_string);
1365 else if (record_type_class == IPMI_MONITORING_SEL_RECORD_TYPE_CLASS_TIMESTAMPED_OEM_RECORD
1366 || record_type_class == IPMI_MONITORING_SEL_RECORD_TYPE_CLASS_NON_TIMESTAMPED_OEM_RECORD)
1368 if (record_type_class == IPMI_MONITORING_SEL_RECORD_TYPE_CLASS_TIMESTAMPED_OEM_RECORD)
1370 if ((manufacturer_id = ipmi_monitoring_sel_read_manufacturer_id (ctx)) < 0)
1373 "ipmi_monitoring_sel_read_manufacturer_id: %s\n",
1374 ipmi_monitoring_ctx_errormsg (ctx));
1378 printf (", Manufacturer ID = %Xh", manufacturer_id);
1381 if ((oem_data_len = ipmi_monitoring_sel_read_oem_data (ctx, oem_data, 1024)) < 0)
1384 "ipmi_monitoring_sel_read_oem_data: %s\n",
1385 ipmi_monitoring_ctx_errormsg (ctx));
1389 printf (", OEM Data = ");
1391 for (j = 0; j < oem_data_len; j++)
1392 printf ("%02Xh ", oem_data[j]);
1395 printf (", N/A, N/A, N/A, N/A, N/A, N/A, N/A");
1398 #endif // NETDATA_COMMENTED
1404 ipmi_monitoring_ctx_destroy (ctx);
1408 // ----------------------------------------------------------------------------
1409 // MAIN PROGRAM FOR NETDATA PLUGIN
1411 int ipmi_collect_data(struct ipmi_monitoring_ipmi_config *ipmi_config) {
1413 if (_ipmimonitoring_sensors(ipmi_config) < 0) return -1;
1414 if (_ipmimonitoring_sel (ipmi_config) < 0) return -2;
1419 int ipmi_detect_speed_secs(struct ipmi_monitoring_ipmi_config *ipmi_config) {
1421 unsigned long long total = 0;
1423 for(i = 0 ; i < checks ; i++) {
1424 if(debug) fprintf(stderr, "freeipmi.plugin: checking data collection speed iteration %d of %d\n", i+1, checks);
1426 // measure the time a data collection needs
1427 unsigned long long start = now_realtime_usec();
1428 if(ipmi_collect_data(ipmi_config) < 0) {
1429 fprintf(stderr, "freeipmi.plugin: data collection failed.\n");
1432 unsigned long long end = now_realtime_usec();
1434 if(debug) fprintf(stderr, "freeipmi.plugin: data collection speed was %llu usec\n", end - start);
1436 // add it to our total
1437 total += end - start;
1439 // wait the same time
1440 // to avoid flooding the IPMI processor with requests
1441 usleep(end - start);
1444 // so, we assume it needed 3x the time
1445 // we find the average in microseconds
1446 // and we round-up to the closest second
1448 return (( total * 3 / checks / 1000000 ) + 1);
1451 int main (int argc, char **argv) {
1452 struct ipmi_monitoring_ipmi_config ipmi_config;
1454 // parse command line parameters
1457 for(i = 1; i < argc ; i++) {
1459 int n = atoi(argv[i]);
1466 if(strcmp("debug", argv[i]) == 0) {
1471 fprintf(stderr, "freeipmi.plugin: ignoring parameter '%s'\n", argv[i]);
1474 if(freq > 0 && freq < netdata_update_every)
1475 netdata_update_every = freq;
1478 fprintf(stderr, "freeipmi.plugin: update frequency %d seconds is too small for IPMI. Using %d", freq, netdata_update_every);
1483 if(debug) fprintf(stderr, "freeipmi.plugin: calling _init_ipmi_config()\n");
1485 _init_ipmi_config(&ipmi_config);
1487 if(debug) fprintf(stderr, "freeipmi.plugin: calling ipmi_monitoring_init()\n");
1489 if(ipmi_monitoring_init(ipmimonitoring_init_flags, &errnum) < 0) {
1490 fprintf(stderr, "ipmi_monitoring_init: %s\n", ipmi_monitoring_ctx_strerror(errnum));
1494 if(debug) fprintf(stderr, "freeipmi.plugin: detecting IPMI minimum update frequency...\n");
1495 freq = ipmi_detect_speed_secs(&ipmi_config);
1496 if(debug) fprintf(stderr, "freeipmi.plugin: IPMI minimum update frequency was calculated to %d seconds.\n", freq);
1498 if(netdata_update_every < freq) {
1499 fprintf(stderr, "freeipmi.plugin: enforcing minimum data collection frequency, calculated to %d seconds.\n", freq);
1500 netdata_update_every = freq;
1504 if(debug) fprintf(stderr, "freeipmi.plugin: starting data collection\n");
1506 size_t iteration = 0;
1507 unsigned long long step = netdata_update_every * 1000000ULL;
1508 unsigned long long now = now_realtime_usec();
1509 unsigned long long next = now - (now % step) + step;
1511 unsigned long long last = now;
1512 now = now_realtime_usec();
1513 if(debug && iteration)
1514 fprintf(stderr, "freeipmi.plugin: iteration %zu, dt %llu usec, sensors collected %zu, sensors sent to netdata %zu \n"
1517 , netdata_sensors_collected
1518 , netdata_sensors_updated
1522 if(debug) fprintf(stderr, "freeipmi.plugin: sleeping for %llu usec\n", next - now);
1524 now = now_realtime_usec();
1526 next = now - (now % step) + step;
1528 netdata_mark_as_not_updated();
1530 if(debug) fprintf(stderr, "freeipmi.plugin: calling ipmi_collect_data()\n");
1531 if(ipmi_collect_data(&ipmi_config) < 0) {
1532 fprintf(stderr, "freeipmi.plugin: data collection failed.\n");
1536 if(debug) fprintf(stderr, "freeipmi.plugin: calling send_metrics_to_netdata()\n");
1537 send_metrics_to_netdata();
1545 #else // !HAVE_FREEIPMI
1547 int main(int argc, char **argv) {
1548 fprintf(stderr, "freeipmi.plugin: not compiled.");