/* * vmstat_freebsd2.c */ #include /* * Ripped from /usr/scr/usr.bin/vmstat/vmstat.c (covering all bases) */ #include #include #if defined(dragonfly) #include #else #include #endif #if defined(freebsd5) && __FreeBSD_version >= 500101 #include #elif defined(dragonfly) #include #else #include #endif #ifdef freebsd5 #include #endif #include #include #include #include #include #include #include #include #include #if HAVE_SYS_VMPARAM_H #include #else #include #endif #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "util_funcs/header_generic.h" #include "vmstat.h" #include "vmstat_freebsd2.h" /* * nlist symbols */ #define CPTIME_SYMBOL "cp_time" #define SUM_SYMBOL "cnt" #define INTRCNT_SYMBOL "intrcnt" #define EINTRCNT_SYMBOL "eintrcnt" #define BOOTTIME_SYMBOL "boottime" /* * Number of interrupts */ #define INT_COUNT 10 /* * CPU percentage */ #define CPU_PRC 100 FindVarMethod var_extensible_vmstat; void init_vmstat_freebsd2(void) { struct variable2 extensible_vmstat_variables[] = { {MIBINDEX, ASN_INTEGER, NETSNMP_OLDAPI_RONLY, var_extensible_vmstat, 1, {MIBINDEX}}, {ERRORNAME, ASN_OCTET_STR, NETSNMP_OLDAPI_RONLY, var_extensible_vmstat, 1, {ERRORNAME}}, {SWAPIN, ASN_INTEGER, NETSNMP_OLDAPI_RONLY, var_extensible_vmstat, 1, {SWAPIN}}, {SWAPOUT, ASN_INTEGER, NETSNMP_OLDAPI_RONLY, var_extensible_vmstat, 1, {SWAPOUT}}, {IOSENT, ASN_INTEGER, NETSNMP_OLDAPI_RONLY, var_extensible_vmstat, 1, {IOSENT}}, {IORECEIVE, ASN_INTEGER, NETSNMP_OLDAPI_RONLY, var_extensible_vmstat, 1, {IORECEIVE}}, {SYSINTERRUPTS, ASN_INTEGER, NETSNMP_OLDAPI_RONLY, var_extensible_vmstat, 1, {SYSINTERRUPTS}}, {SYSCONTEXT, ASN_INTEGER, NETSNMP_OLDAPI_RONLY, var_extensible_vmstat, 1, {SYSCONTEXT}}, {CPUUSER, ASN_INTEGER, NETSNMP_OLDAPI_RONLY, var_extensible_vmstat, 1, {CPUUSER}}, {CPUSYSTEM, ASN_INTEGER, NETSNMP_OLDAPI_RONLY, var_extensible_vmstat, 1, {CPUSYSTEM}}, {CPUIDLE, ASN_INTEGER, NETSNMP_OLDAPI_RONLY, var_extensible_vmstat, 1, {CPUIDLE}}, {CPURAWUSER, ASN_COUNTER, NETSNMP_OLDAPI_RONLY, var_extensible_vmstat, 1, {CPURAWUSER}}, {CPURAWNICE, ASN_COUNTER, NETSNMP_OLDAPI_RONLY, var_extensible_vmstat, 1, {CPURAWNICE}}, {CPURAWSYSTEM, ASN_COUNTER, NETSNMP_OLDAPI_RONLY, var_extensible_vmstat, 1, {CPURAWSYSTEM}}, {CPURAWIDLE, ASN_COUNTER, NETSNMP_OLDAPI_RONLY, var_extensible_vmstat, 1, {CPURAWIDLE}}, {CPURAWKERNEL, ASN_COUNTER, NETSNMP_OLDAPI_RONLY, var_extensible_vmstat, 1, {CPURAWKERNEL}}, {CPURAWINTR, ASN_COUNTER, NETSNMP_OLDAPI_RONLY, var_extensible_vmstat, 1, {CPURAWINTR}}, {SYSRAWINTERRUPTS, ASN_COUNTER, NETSNMP_OLDAPI_RONLY, var_extensible_vmstat, 1, {SYSRAWINTERRUPTS}}, {SYSRAWCONTEXT, ASN_COUNTER, NETSNMP_OLDAPI_RONLY, var_extensible_vmstat, 1, {SYSRAWCONTEXT}}, /* * Future use: */ /* * {ERRORFLAG, ASN_INTEGER, NETSNMP_OLDAPI_RONLY, * var_extensible_vmstat, 1, {ERRORFLAG }}, * {ERRORMSG, ASN_OCTET_STR, NETSNMP_OLDAPI_RONLY, * var_extensible_vmstat, 1, {ERRORMSG }} */ }; /* * Define the OID pointer to the top of the mib tree that we're * registering underneath */ oid vmstat_variables_oid[] = { NETSNMP_UCDAVIS_MIB, 11 }; /* * register ourselves with the agent to handle our mib tree */ REGISTER_MIB("ucd-snmp/vmstat", extensible_vmstat_variables, variable2, vmstat_variables_oid); } long getuptime(void) { static time_t now, boottime; time_t uptime; if (boottime == 0) auto_nlist(BOOTTIME_SYMBOL, (char *) &boottime, sizeof(boottime)); time(&now); uptime = now - boottime; return (uptime); } unsigned char * var_extensible_vmstat(struct variable *vp, oid * name, size_t * length, int exact, size_t * var_len, WriteMethod ** write_method) { int loop; time_t time_new = getuptime(); static time_t time_old; static time_t time_diff; #if defined(dragonfly) static struct kinfo_cputime cpu_old, cpu_new, cpu_diff; static uint64_t cpu_total; uint64_t cpu_sum; static int pagesize; #else static long cpu_old[CPUSTATES]; static long cpu_new[CPUSTATES]; static long cpu_diff[CPUSTATES]; static long cpu_total; long cpu_sum; #endif double cpu_prc; static struct vmmeter mem_old, mem_new; static long long_ret; static char errmsg[300]; #if defined(dragonfly) if (pagesize == 0) pagesize = getpagesize() >> 10; #endif long_ret = 0; /* set to 0 as default */ if (header_generic(vp, name, length, exact, var_len, write_method)) return (NULL); /* * Update structures (only if time has passed) */ if (time_new != time_old) { time_diff = time_new - time_old; time_old = time_new; /* * CPU usage */ cpu_total = 0; #if defined(dragonfly) kinfo_get_sched_cputime(&cpu_new); #define CP_UPDATE(field) cpu_diff.field = cpu_new.field - cpu_old.field; cpu_total += cpu_diff.field; CP_UPDATE(cp_user); CP_UPDATE(cp_nice); CP_UPDATE(cp_sys); CP_UPDATE(cp_intr); CP_UPDATE(cp_idle); cpu_old = cpu_new; #undef CP_UPDATE #else auto_nlist(CPTIME_SYMBOL, (char *) cpu_new, sizeof(cpu_new)); for (loop = 0; loop < CPUSTATES; loop++) { cpu_diff[loop] = cpu_new[loop] - cpu_old[loop]; cpu_old[loop] = cpu_new[loop]; cpu_total += cpu_diff[loop]; } #endif if (cpu_total == 0) cpu_total = 1; /* * Memory info */ mem_old = mem_new; auto_nlist(SUM_SYMBOL, (char *) &mem_new, sizeof(mem_new)); } /* * Rate macro */ #define rate(x) (((x)+ time_diff/2) / time_diff) /* * Page-to-kb macro */ #if defined(dragonfly) #define ptok(p) ((p) * pagesize) #else #define ptok(p) ((p) * (mem_new.v_page_size >> 10)) #endif switch (vp->magic) { case MIBINDEX: long_ret = 1; return ((u_char *) (&long_ret)); case ERRORNAME: /* dummy name */ sprintf(errmsg, "systemStats"); *var_len = strlen(errmsg); return ((u_char *) (errmsg)); case SWAPIN: #if defined(openbsd2) || defined(darwin) long_ret = ptok(mem_new.v_swpin - mem_old.v_swpin); #else long_ret = ptok(mem_new.v_swappgsin - mem_old.v_swappgsin + mem_new.v_vnodepgsin - mem_old.v_vnodepgsin); #endif long_ret = rate(long_ret); return ((u_char *) (&long_ret)); case SWAPOUT: #if defined(openbsd2) || defined(darwin) long_ret = ptok(mem_new.v_swpout - mem_old.v_swpout); #else long_ret = ptok(mem_new.v_swappgsout - mem_old.v_swappgsout + mem_new.v_vnodepgsout - mem_old.v_vnodepgsout); #endif long_ret = rate(long_ret); return ((u_char *) (&long_ret)); case IOSENT: #if NETSNMP_NO_DUMMY_VALUES return NULL; #endif long_ret = -1; return ((u_char *) (&long_ret)); case IORECEIVE: #if NETSNMP_NO_DUMMY_VALUES return NULL; #endif long_ret = -1; return ((u_char *) (&long_ret)); case SYSINTERRUPTS: long_ret = rate(mem_new.v_intr - mem_old.v_intr); return ((u_char *) (&long_ret)); case SYSCONTEXT: long_ret = rate(mem_new.v_swtch - mem_old.v_swtch); return ((u_char *) (&long_ret)); case CPUUSER: #if defined(dragonfly) cpu_sum = cpu_diff.cp_user + cpu_diff.cp_nice; #else cpu_sum = cpu_diff[CP_USER] + cpu_diff[CP_NICE]; #endif cpu_prc = (float) cpu_sum / (float) cpu_total; long_ret = cpu_prc * CPU_PRC; return ((u_char *) (&long_ret)); case CPUSYSTEM: #if defined(dragonfly) cpu_sum = cpu_diff.cp_sys + cpu_diff.cp_intr; #else cpu_sum = cpu_diff[CP_SYS] + cpu_diff[CP_INTR]; #endif cpu_prc = (float) cpu_sum / (float) cpu_total; long_ret = cpu_prc * CPU_PRC; return ((u_char *) (&long_ret)); case CPUIDLE: #if defined(dragonfly) cpu_sum = cpu_diff.cp_idle; #else cpu_sum = cpu_diff[CP_IDLE]; #endif cpu_prc = (float) cpu_sum / (float) cpu_total; long_ret = cpu_prc * CPU_PRC; return ((u_char *) (&long_ret)); case CPURAWUSER: #if defined(dragonfly) long_ret = cpu_new.cp_user; #else long_ret = cpu_new[CP_USER]; #endif return ((u_char *) (&long_ret)); case CPURAWNICE: #if defined(dragonfly) long_ret = cpu_new.cp_nice; #else long_ret = cpu_new[CP_NICE]; #endif return ((u_char *) (&long_ret)); case CPURAWSYSTEM: #if defined(dragonfly) long_ret = cpu_new.cp_sys + cpu_new.cp_nice; #else long_ret = cpu_new[CP_SYS] + cpu_new[CP_INTR]; #endif return ((u_char *) (&long_ret)); case CPURAWIDLE: #if defined(dragonfly) long_ret = cpu_new.cp_idle; #else long_ret = cpu_new[CP_IDLE]; #endif return ((u_char *) (&long_ret)); case CPURAWKERNEL: #if defined(dragonfly) long_ret = cpu_new.cp_sys; #else long_ret = cpu_new[CP_SYS]; #endif return ((u_char *) (&long_ret)); case CPURAWINTR: #if defined(dragonfly) long_ret = cpu_new.cp_intr; #else long_ret = cpu_new[CP_INTR]; #endif return ((u_char *) (&long_ret)); case SYSRAWINTERRUPTS: long_ret = mem_new.v_intr; return ((u_char *) (&long_ret)); case SYSRAWCONTEXT: long_ret = mem_new.v_swtch; return ((u_char *) (&long_ret)); /* * reserved for future use */ /* * case ERRORFLAG: * return((u_char *) (&long_ret)); * case ERRORMSG: * return((u_char *) (&long_ret)); */ } return NULL; }