| /* |
| * 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 */ } |
| } |
| |