blob: 33f188ea27dd0c0b3ee9348a34651c86ca647472 [file] [log] [blame]
/*
* kstat() interface
* e.g. Solaris
*/
#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 <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <kstat.h>
#include <sys/sysinfo.h>
extern kstat_ctl_t *kstat_fd;
extern int cpu_num;
int _cpu_status(char *state);
/*
* Initialise the list of CPUs on the system
* (including descriptions)
*/
void init_cpu_kstat( void ) {
int i = 0, n = 0, clock, state_begin;
char ctype[15], ftype[15], state[10];
kstat_t *ksp;
kstat_named_t *ks_data;
netsnmp_cpu_info *cpu = netsnmp_cpu_get_byIdx( -1, 1 );
strcpy(cpu->name, "Overall CPU statistics");
if (kstat_fd == NULL)
kstat_fd = kstat_open();
kstat_chain_update( kstat_fd );
DEBUGMSGTL(("cpu", "cpu_kstat init\n "));
for (ksp = kstat_fd->kc_chain; ksp != NULL; ksp = ksp->ks_next) {
if (ksp->ks_flags & KSTAT_FLAG_INVALID)
continue;
if ((strcmp(ksp->ks_module, "cpu_info") == 0) &&
(strcmp(ksp->ks_class, "misc" ) == 0)) {
kstat_read(kstat_fd, ksp, NULL );
n++;
clock = 999999;
memset(ctype, 0, sizeof(ctype));
memset(ftype, 0, sizeof(ftype));
memset(state, 0, sizeof(state));
for (i=0, ks_data = ksp->ks_data; i < ksp->ks_ndata; i++, ks_data++) {
if ( strcmp( ks_data->name, "state" ) == 0 ) {
strlcpy(state, ks_data->value.c, sizeof(state));
} else if ( strcmp( ks_data->name, "state_begin" ) == 0 ) {
state_begin = ks_data->value.i32;
} else if ( strcmp( ks_data->name, "cpu_type" ) == 0 ) {
strlcpy(ctype, ks_data->value.c, sizeof(ctype));
} else if ( strcmp( ks_data->name, "fpu_type" ) == 0 ) {
strlcpy(ftype, ks_data->value.c, sizeof(ftype));
} else if ( strcmp( ks_data->name, "clock_MHz" ) == 0 ) {
clock = ks_data->value.i32;
}
}
i = ksp->ks_instance;
cpu = netsnmp_cpu_get_byIdx( i, 1 );
sprintf( cpu->name, "cpu%d", i );
sprintf( cpu->descr, "CPU %d Sun %d MHz %s with %s FPU %s",
i, clock, ctype, ftype, state );
cpu->status = _cpu_status(state); /* XXX - or in 'n_c_a_load' ? */
}
}
cpu_num = i;
}
/*
* Load the latest CPU usage statistics
*/
int netsnmp_cpu_arch_load( netsnmp_cache *cache, void *magic ) {
int i=1;
kstat_t *ksp;
cpu_stat_t cs;
netsnmp_cpu_info *cpu = netsnmp_cpu_get_byIdx( -1, 0 );
netsnmp_cpu_info *cpu2;
/* Clear overall stats, ready for summing individual CPUs */
cpu->user_ticks = 0;
cpu->idle_ticks = 0;
cpu->kern_ticks = 0;
cpu->wait_ticks = 0;
cpu->sys2_ticks = 0;
cpu->swapIn = 0;
cpu->swapOut = 0;
cpu->nInterrupts = 0;
cpu->nCtxSwitches = 0;
kstat_chain_update( kstat_fd );
DEBUGMSGTL(("cpu", "cpu_kstat load\n "));
for (ksp = kstat_fd->kc_chain; ksp != NULL; ksp = ksp->ks_next) {
if (ksp->ks_flags & KSTAT_FLAG_INVALID)
continue;
if (strcmp(ksp->ks_module, "cpu_stat") == 0) {
i = ksp->ks_instance;
cpu2 = netsnmp_cpu_get_byIdx( i, 0 );
if ( !cpu2 )
break; /* or continue ? */ /* Skip new CPUs */
if ((ksp->ks_type != KSTAT_TYPE_RAW) ||
(ksp->ks_data_size != sizeof(cs))||
(kstat_read(kstat_fd, ksp, &cs) == -1)) {
DEBUGMSGTL(("cpu", "cpu_kstat load failed (%d)\n ", i));
break; /* or continue ? */
}
cpu2->user_ticks = (unsigned long long)cs.cpu_sysinfo.cpu[CPU_USER];
cpu2->idle_ticks = (unsigned long long)cs.cpu_sysinfo.cpu[CPU_IDLE];
cpu2->kern_ticks = (unsigned long long)cs.cpu_sysinfo.cpu[CPU_KERNEL];
cpu2->wait_ticks = (unsigned long long)cs.cpu_sysinfo.cpu[CPU_WAIT];
/* or cs.cpu_sysinfo.wait[W_IO]+cs.cpu_sysinfo.wait[W_PIO] */
cpu2->sys2_ticks = (unsigned long long)cpu2->kern_ticks+cpu2->wait_ticks;
/* nice_ticks, intrpt_ticks, sirq_ticks unused */
/* sum these for the overall stats */
cpu->user_ticks += (unsigned long long)cs.cpu_sysinfo.cpu[CPU_USER];
cpu->idle_ticks += (unsigned long long)cs.cpu_sysinfo.cpu[CPU_IDLE];
cpu->kern_ticks += (unsigned long long)cs.cpu_sysinfo.cpu[CPU_KERNEL];
cpu->wait_ticks += (unsigned long long)cs.cpu_sysinfo.cpu[CPU_WAIT];
/* or cs.cpu_sysinfo.wait[W_IO]+cs.cpu_sysinfo.wait[W_PIO] */
cpu->sys2_ticks += (unsigned long long)cpu2->kern_ticks+cpu2->wait_ticks;
/*
* Interrupt/Context Switch statistics
* XXX - Do these really belong here ?
*/
cpu->swapIn += (unsigned long long)cs.cpu_vminfo.swapin;
cpu->swapOut += (unsigned long long)cs.cpu_vminfo.swapout;
cpu->pageIn += (unsigned long long)cs.cpu_sysinfo.bread;
cpu->pageOut += (unsigned long long)cs.cpu_sysinfo.bwrite;
cpu->nInterrupts += (unsigned long long)cs.cpu_sysinfo.intr;
cpu->nCtxSwitches += (unsigned long long)cs.cpu_sysinfo.pswitch;
}
}
return 0;
}
int
_cpu_status( char *state)
{
/*
* hrDeviceStatus OBJECT-TYPE
* SYNTAX INTEGER {
* unknown(1), running(2), warning(3), testing(4), down(5)
* }
*/
if (strcmp(state,"on-line")==0)
{ return 2; /* running */ }
else if (strcmp(state,"off-line")==0)
{ return 5; /* down */ }
else if (strcmp(state,"missing")==0)
{ return 3; /* warning, went missing */ }
else if (strcmp(state,"testing")==0)
{ return 4; /* somebody must be testing code somewhere */ }
else
{ return 1; /* unknown */ }
}