From b814d3e00185ea46b83ffd51b97ab1e312d7eef6 Mon Sep 17 00:00:00 2001 From: Adam Wujek <adam.wujek@cern.ch> Date: Wed, 1 Apr 2015 14:24:41 +0200 Subject: [PATCH] userspace/snmpd: add boot count objects to wrsBootStatusGroup objects added: --wrsBootCnt (read from /proc/wrs-bootcount) --wrsRebootCnt (read from /proc/wrs-bootcount) --wrsRestartReason (read from CPU's register) --wrsFaultIP (not implemented in kernel) --wrsFaultLR (not implemented in kernel) Signed-off-by: Adam Wujek <adam.wujek@cern.ch> --- userspace/snmpd/WR-SWITCH-MIB.txt | 75 ++++++++++++++++++++------ userspace/snmpd/wrsBootStatusGroup.c | 81 ++++++++++++++++++++++++++++ userspace/snmpd/wrsBootStatusGroup.h | 2 + 3 files changed, 143 insertions(+), 15 deletions(-) diff --git a/userspace/snmpd/WR-SWITCH-MIB.txt b/userspace/snmpd/WR-SWITCH-MIB.txt index 90847c20c..782114e85 100644 --- a/userspace/snmpd/WR-SWITCH-MIB.txt +++ b/userspace/snmpd/WR-SWITCH-MIB.txt @@ -206,21 +206,66 @@ wrsDateTAIString OBJECT-TYPE --wrsBootStatusGroup (.7.1.2) wrsBootStatusGroup OBJECT IDENTIFIER ::= { wrsOperationStatus 2 } ---wrsBootCnt OBJECT-TYPE --- SYNTAX Counter32 --- MAX-ACCESS read-only --- STATUS current --- DESCRIPTION --- "Number of switch's boots" --- ::= { wrsBootStatusGroup 1 } - ---wrsRestartReason OBJECT-TYPE --- SYNTAX Integer32 --- MAX-ACCESS read-only --- STATUS current --- DESCRIPTION --- "Reason of last switch restart" --- ::= { wrsBootStatusGroup 3 } +wrsBootCnt OBJECT-TYPE + SYNTAX Counter32 + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "Number of switch's boots since power-on" + ::= { wrsBootStatusGroup 1 } + +wrsRebootCnt OBJECT-TYPE + SYNTAX Counter32 + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "The number of soft reboots. This is incremented by the + reboot system call. A healthy system should feature one + soft-reboot less than total boots." + ::= { wrsBootStatusGroup 2 } + +wrsRestartReason OBJECT-TYPE + SYNTAX INTEGER { + na(0), + error(1), + generalReset(2), + wakeUpReset(3), + watchdogReset(4), + softwareReset(5), + userReset(6) + } + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "Reason of last switch restart. + error(1) - unable to read restart reason or reset counters + generalReset(2) - Both VDDCORE and VDDBU rising (power-on) + wakeUpReset(3) - VDDCORE rising + watchdogReset(4) - Watchdog fault occurred + softwareReset(5) - Processor reset required by the software (system reboot) + userReset(6) - NRST pin detected low (reset button)" + ::= { wrsBootStatusGroup 3 } + +wrsFaultIP OBJECT-TYPE + SYNTAX OCTET STRING (SIZE(4)) + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "The fault address of the last panic. This is the instruction + pointer normally printed by the stack backtrace. The register + is zeroed at first boot and only modified within panic." + ::= { wrsBootStatusGroup 4 } + +wrsFaultLR OBJECT-TYPE + SYNTAX OCTET STRING (SIZE(4)) + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "The link register register at last panic. + This is usually the caller of the function that failed, + but it may be a local register if the failing function + saved lr to the stack and used it as a scratch register." + ::= { wrsBootStatusGroup 5 } wrsConfigSource OBJECT-TYPE SYNTAX INTEGER { diff --git a/userspace/snmpd/wrsBootStatusGroup.c b/userspace/snmpd/wrsBootStatusGroup.c index 01f343249..2442a9a32 100644 --- a/userspace/snmpd/wrsBootStatusGroup.c +++ b/userspace/snmpd/wrsBootStatusGroup.c @@ -1,6 +1,9 @@ #include "wrsSnmp.h" +#include "snmp_mmap.h" #include "wrsBootStatusGroup.h" +#define BOOTCOUNT_FILE "/proc/wrs-bootcount" + #define DOTCONFIGDIR "/tmp" #define DOTCONFIG_PROTO "dot-config_proto" #define DOTCONFIG_HOST "dot-config_host" @@ -10,6 +13,10 @@ * without new line. Macro expands to something like: "%10[^\n]" */ #define LINE_READ_LEN_HELPER(x) "%"#x"[^\n]" #define LINE_READ_LEN(x) LINE_READ_LEN_HELPER(x) +#define ARM_RCSR_ADDR 0xFFFFFD04 /* address of CPU's Reset Controller Status + * Register */ +#define ARM_RCSR_RESET_TYPE_MASK 0x00000700 /* reset type mast in CPU's Reset + * Controller Status Register */ static struct pickinfo wrsBootStatus_pickinfo[] = { FIELD(wrsBootStatus_s, ASN_COUNTER, wrsBootCnt), @@ -24,10 +31,82 @@ static struct pickinfo wrsBootStatus_pickinfo[] = { struct wrsBootStatus_s wrsBootStatus_s; +struct wrs_bc_item { + char *key; + uint32_t value; +}; + +/* items to be read from BOOTCOUNT_FILE */ +static struct wrs_bc_item boot_info[] = { + [0] = {.key = "boot_count:"}, + [1] = {"reboot_count:"}, + [2] = {"fault_ip:"}, + [3] = {"fault_lr:"}, +}; + +static void get_boot_info(void){ + static int run_once = 0; + FILE *f; + char s[80], key[40]; + uint32_t value; + int i; + uint32_t *rcsr_map; + if (run_once) { + /* boot info change only at restart */ + return; + } + run_once = 1; + + /* get restart reason */ + rcsr_map = create_map(ARM_RCSR_ADDR, sizeof(uint32_t)); + if (!rcsr_map) { + snmp_log(LOG_ERR, "SNMP: wrsBootStatusGroup unable to map " + "CPU's Reset Controller Status Register\n"); + /* pass error to SNMP, assign 1 */ + wrsBootStatus_s.wrsRestartReason = WRS_RESTART_REASON_ERROR; + } else { + /* reset reason values are from 0 to 4, SNMP enum is from + * 2 to 6, so "+ 2", 1 is reserved for error */ + wrsBootStatus_s.wrsRestartReason = 2 + + ((*rcsr_map & ARM_RCSR_RESET_TYPE_MASK) >> 8); + } + + f = fopen(BOOTCOUNT_FILE, "r"); + if (!f) { + snmp_log(LOG_ERR, "SNMP: wrsBootStatusGroup filed to open " + BOOTCOUNT_FILE"\n"); + /* notify snmp about error in restart reason */ + wrsBootStatus_s.wrsRestartReason = WRS_RESTART_REASON_ERROR; + return; + } + + while (fgets(s, sizeof(s), f)) { + if (sscanf(s, "%s %i", key, &value) != 2) + continue; /* error... */ + for (i = 0; i < ARRAY_SIZE(boot_info); i++) { + if (strncmp(key, boot_info[i].key, 40)) + continue; + boot_info[i].value = value; + } + } + fclose(f); + + wrsBootStatus_s.wrsBootCnt = boot_info[0].value; + wrsBootStatus_s.wrsRebootCnt = boot_info[1].value; + + snprintf(wrsBootStatus_s.wrsFaultIP, + sizeof(wrsBootStatus_s.wrsFaultIP), "0x%.8x", + boot_info[2].value); + snprintf(wrsBootStatus_s.wrsFaultLR, + sizeof(wrsBootStatus_s.wrsFaultLR), "0x%.8x", + boot_info[3].value); +} + static void get_dotconfig_source(void) { char buff[10]; FILE *f; + /* Check dotconfig source. * dotconfig source can change in runtime, i.e. from remote to local by * web-interface */ @@ -97,6 +176,8 @@ time_t wrsBootStatus_data_fill(void) } time_update = time_cur; + get_boot_info(); + /* get dotconfig source information */ get_dotconfig_source(); diff --git a/userspace/snmpd/wrsBootStatusGroup.h b/userspace/snmpd/wrsBootStatusGroup.h index b90c196e7..ed93cc77a 100644 --- a/userspace/snmpd/wrsBootStatusGroup.h +++ b/userspace/snmpd/wrsBootStatusGroup.h @@ -4,6 +4,8 @@ #define WRSBOOTSTATUS_CACHE_TIMEOUT 5 #define WRSBOOTSTATUS_OID WRS_OID, 7, 1, 2 +#define WRS_RESTART_REASON_ERROR 1 /* error */ + #define WRS_CONFIG_SOURCE_HOST_LEN 64 #define WRS_CONFIG_SOURCE_FILENAME_LEN 128 #define WRS_CONFIG_SOURCE_PROTO_ERROR 1 /* error */ -- GitLab