diff options
Diffstat (limited to 'agent/mibgroup/hardware/cpu/cpu_pcp.c')
-rw-r--r-- | agent/mibgroup/hardware/cpu/cpu_pcp.c | 191 |
1 files changed, 191 insertions, 0 deletions
diff --git a/agent/mibgroup/hardware/cpu/cpu_pcp.c b/agent/mibgroup/hardware/cpu/cpu_pcp.c new file mode 100644 index 0000000..94c7b5c --- /dev/null +++ b/agent/mibgroup/hardware/cpu/cpu_pcp.c @@ -0,0 +1,191 @@ +/* + * pcp interface + * e.g. IRIX + */ +#include <net-snmp/net-snmp-config.h> +#include <net-snmp/net-snmp-includes.h> +#include <net-snmp/agent/net-snmp-agent-includes.h> +#include <net-snmp/agent/hardware/cpu.h> + +#include <unistd.h> +#include <pcp/pmapi.h> + +/* + * Performance Metrics Name Space Map + * Built by pmgenmap from the file irix_kernstats.pcp + */ +char *kernstats[] = { +#define NCPU 0 + "hinv.ncpu", +#define CPUTYPE 1 + "hinv.cputype", +#define CPUIDLE 2 + "kernel.all.cpu.idle", +#define CPUINTR 3 + "kernel.all.cpu.intr", +#define CPUSYS 4 + "kernel.all.cpu.sys", +#define CPUUSER 5 + "kernel.all.cpu.user", +#define CPUWAIT 6 + "kernel.all.cpu.wait.total", +#define PAGESIN 7 + "swap.pagesin", +#define PAGESOUT 8 + "swap.pagesout", +#define SWAPIN 9 + "swap.in", +#define SWAPOUT 10 + "swap.out", +#define INTR 11 + "kernel.all.intr.non_vme", +#define CTXT 12 + "kernel.all.kswitch" +}; + +# define MAX_MID 17 + +pmResult *resp; +pmID pmidlist[MAX_MID]; +int numpmid; +int pmInitDone = 0; + +/* initialize pcp if necessary */ +void init_pcp () { + int err; + + if (pmInitDone == 1) { + return; + } + + snmp_log_perror("Initializing pcp"); + numpmid = sizeof(kernstats)/sizeof(kernstats[0]); + + /* Load default namespace */ + if ((err=pmLoadNameSpace(PM_NS_DEFAULT)) < 0) { + snmp_log_perror("pmLoadNameSpace returned an error."); + snmp_log_perror(pmErrStr(err)); + exit (1); + } + + /* get mappings between internal IDs and external IDs */ + if ((err=pmLookupName(numpmid, kernstats, pmidlist)) < 0) { + snmp_log_perror("pmLookupName returned an error."); + snmp_log_perror(pmErrStr(err)); + exit (1); + } + + /* specify a context to use */ + /* a type of PM_CONTEXT_HOST lets you specify a hostname */ + /* a type of PM_CONTEXT_LOCAL should ignore the string param */ + if ((err=pmNewContext(PM_CONTEXT_LOCAL,"localhost")) < 0) { + snmp_log_perror("pmNewContext returned error opening a LOCAL Context"); + snmp_log_perror(pmErrStr(err)); + + if ((err=pmNewContext(PM_CONTEXT_HOST,"localhost")) < 0) { + snmp_log_perror("pmNewContext returned error opening a HOST Context"); + snmp_log_perror(pmErrStr(err)); + exit(1); + } + } + snmp_log_perror ("done initializing pcp"); + pmInitDone = 1; +} + + /* + * Initialise the list of CPUs on the system + * (including descriptions) + */ +void init_cpu_pcp( void ) { + int i, n = 0; + char tstr[1024]; + int err; + netsnmp_cpu_info *cpu; + + init_pcp(); + + /* At this stage, pmidlist contains the PMID for my metrics of interest */ + + cpu = netsnmp_cpu_get_byIdx( -1, 1 ); + strcpy(cpu->name, "Overall CPU statistics"); + + if ((err=pmFetch(numpmid, pmidlist, &resp)) < 0) { + snmp_log_perror ("init_cpu_pcp: pmFetch returned error"); + snmp_log_perror (pmErrStr(err)); + exit (1); + } + cpu_num = resp->vset[NCPU]->vlist[0].value.lval; + pmFreeResult(resp); + + for (i=0; i<cpu_num ; i++) { + cpu = netsnmp_cpu_get_byIdx( i, 1 ); + sprintf(tstr, "cpu%d",i); + strcpy(cpu->name, tstr); + strcpy(cpu->descr, "An electronic chip that makes the computer work"); + } +} + +/*void _cpu_load_swap_etc( char *buff, netsnmp_cpu_info *cpu );*/ + + /* + * Load the latest CPU usage statistics + */ +int netsnmp_cpu_arch_load( netsnmp_cache *cache, void *magic ) { + int err; + /*static char *buff = NULL;*/ + static int first = 1; + netsnmp_cpu_info* cpu; + + init_pcp(); + + /* + * CPU statistics (overall and per-CPU) + */ + if ((err=pmFetch(numpmid, pmidlist, &resp)) < 0) { + snmp_log_perror ("netsnmp_cpu_arch_load: pmFetch returned an error."); + snmp_log_perror (pmErrStr(err)); + exit (1); + } + + cpu = netsnmp_cpu_get_byIdx( -1, 0 ); + if (!cpu) { + snmp_log_perror ("netsnmp_cpu_arch_load: netsnmp_cpu_get_byIdx failed!"); + exit(1); + } + + cpu->wait_ticks = (unsigned long long)resp->vset[CPUWAIT]->vlist[0].value.lval / 10; + cpu->intrpt_ticks = (unsigned long long)resp->vset[CPUINTR]->vlist[0].value.lval / 10; + /*cpu->sirq_ticks = (unsigned long)csoftll / 10;*/ + cpu->user_ticks = (unsigned long long)resp->vset[CPUUSER]->vlist[0].value.lval / 10; + /*cpu->nice_ticks = (unsigned long)cicell / 10;*/ + cpu->sys_ticks = (unsigned long long)resp->vset[CPUSYS]->vlist[0].value.lval / 10; + cpu->idle_ticks = (unsigned long long)resp->vset[CPUIDLE]->vlist[0].value.lval / 10; + + + /* + * Interrupt/Context Switch statistics + * XXX - Do these really belong here ? + */ + /*cpu = netsnmp_cpu_get_byIdx( -1, 0 );*/ + /*_cpu_load_swap_etc( buff, cpu );*/ + cpu->pageIn = (unsigned long long)resp->vset[PAGESIN]->vlist[0].value.lval; + cpu->pageOut = (unsigned long long)resp->vset[PAGESOUT]->vlist[0].value.lval; + cpu->swapIn = (unsigned long long)resp->vset[SWAPIN]->vlist[0].value.lval; + cpu->swapOut = (unsigned long long)resp->vset[SWAPOUT]->vlist[0].value.lval; + cpu->nInterrupts = (unsigned long long)resp->vset[INTR]->vlist[0].value.lval; + cpu->nCtxSwitches = (unsigned long long)resp->vset[CTXT]->vlist[0].value.lval; + + /* + * XXX - TODO: extract per-CPU statistics + * (Into separate netsnmp_cpu_info data structures) + */ + + /* free pcp response */ + pmFreeResult(resp); + + first = 0; + return 0; +} + + + |