# BRCM_VERSION=3
[bcm963xx.git] / userapps / opensource / net-snmp / agent / mibgroup / ucd-snmp / vmstat.c
1 #include <net-snmp/net-snmp-config.h>
2
3 #if HAVE_LIMITS_H
4 #include <limits.h>
5 #endif
6 #if HAVE_STDLIB_H
7 #include <stdlib.h>
8 #endif
9 #if HAVE_UNISTD_H
10 #include <unistd.h>
11 #endif
12 #if HAVE_FCNTL_H
13 #include <fcntl.h>
14 #endif
15 #include <ctype.h>
16 #include <signal.h>
17 #if HAVE_MACHINE_PARAM_H
18 #include <machine/param.h>
19 #endif
20 #if HAVE_SYS_VMMETER_H
21 #if !defined(bsdi2) && !defined(netbsd1)
22 #include <sys/vmmeter.h>
23 #endif
24 #endif
25 #if HAVE_SYS_CONF_H
26 #include <sys/conf.h>
27 #endif
28 #if HAVE_SYS_FS_H
29 #include <sys/fs.h>
30 #else
31 #if HAVE_UFS_FS_H
32 #include <ufs/fs.h>
33 #else
34 #ifdef HAVE_SYS_STAT_H
35 #include <sys/stat.h>
36 #endif
37 #ifdef HAVE_SYS_VNODE_H
38 #include <sys/vnode.h>
39 #endif
40 #ifdef HAVE_UFS_UFS_QUOTA_H
41 #include <ufs/ufs/quota.h>
42 #endif
43 #ifdef HAVE_UFS_UFS_INODE_H
44 #include <ufs/ufs/inode.h>
45 #endif
46 #if HAVE_UFS_FFS_FS_H
47 #include <ufs/ffs/fs.h>
48 #endif
49 #endif
50 #endif
51 #if HAVE_MTAB_H
52 #include <mtab.h>
53 #endif
54 #include <sys/stat.h>
55 #include <errno.h>
56 #if HAVE_FSTAB_H
57 #include <fstab.h>
58 #endif
59 #if HAVE_SYS_STATVFS_H
60 #include <sys/statvfs.h>
61 #endif
62 #if HAVE_SYS_VFS_H
63 #include <sys/vfs.h>
64 #endif
65 #if (!defined(HAVE_STATVFS)) && defined(HAVE_STATFS)
66 #if HAVE_SYS_PARAM_H
67 #include <sys/param.h>
68 #endif
69 #if HAVE_SYS_MOUNT_H
70 #include <sys/mount.h>
71 #endif
72 #if HAVE_SYS_SYSCTL_H
73 #include <sys/sysctl.h>
74 #endif
75 #define statvfs statfs
76 #endif
77 #if HAVE_VM_SWAP_PAGER_H
78 #include <vm/swap_pager.h>
79 #endif
80 #if HAVE_SYS_FIXPOINT_H
81 #include <sys/fixpoint.h>
82 #endif
83 #if HAVE_MALLOC_H
84 #include <malloc.h>
85 #endif
86 #if HAVE_STRING_H
87 #include <string.h>
88 #else
89 #include <strings.h>
90 #endif
91 #if TIME_WITH_SYS_TIME
92 # include <sys/time.h>
93 # include <time.h>
94 #else
95 # if HAVE_SYS_TIME_H
96 #  include <sys/time.h>
97 # else
98 #  include <time.h>
99 # endif
100 #endif
101
102 #include <net-snmp/net-snmp-includes.h>
103 #include <net-snmp/agent/net-snmp-agent-includes.h>
104 #include <net-snmp/agent/auto_nlist.h>
105
106 #include "mibdefs.h"
107 #include "struct.h"
108 #include "util_funcs.h"
109 #include "vmstat.h"
110
111 FindVarMethod var_extensible_vmstat;
112
113 void
114 init_vmstat(void)
115 {
116     struct variable2 extensible_vmstat_variables[] = {
117         {MIBINDEX, ASN_INTEGER, RONLY, var_extensible_vmstat, 1,
118          {MIBINDEX}},
119         {ERRORNAME, ASN_OCTET_STR, RONLY, var_extensible_vmstat, 1,
120          {ERRORNAME}},
121         {SWAPIN, ASN_INTEGER, RONLY, var_extensible_vmstat, 1, {SWAPIN}},
122         {SWAPOUT, ASN_INTEGER, RONLY, var_extensible_vmstat, 1, {SWAPOUT}},
123         {IOSENT, ASN_INTEGER, RONLY, var_extensible_vmstat, 1, {IOSENT}},
124         {IORECEIVE, ASN_INTEGER, RONLY, var_extensible_vmstat, 1,
125          {IORECEIVE}},
126         {SYSINTERRUPTS, ASN_INTEGER, RONLY, var_extensible_vmstat, 1,
127          {SYSINTERRUPTS}},
128         {SYSCONTEXT, ASN_INTEGER, RONLY, var_extensible_vmstat, 1,
129          {SYSCONTEXT}},
130         {CPUUSER, ASN_INTEGER, RONLY, var_extensible_vmstat, 1, {CPUUSER}},
131         {CPUSYSTEM, ASN_INTEGER, RONLY, var_extensible_vmstat, 1,
132          {CPUSYSTEM}},
133         {CPUIDLE, ASN_INTEGER, RONLY, var_extensible_vmstat, 1, {CPUIDLE}},
134         {CPURAWUSER, ASN_COUNTER, RONLY, var_extensible_vmstat, 1,
135          {CPURAWUSER}},
136         {CPURAWNICE, ASN_COUNTER, RONLY, var_extensible_vmstat, 1,
137          {CPURAWNICE}},
138         {CPURAWSYSTEM, ASN_COUNTER, RONLY, var_extensible_vmstat, 1,
139          {CPURAWSYSTEM}},
140         {CPURAWIDLE, ASN_COUNTER, RONLY, var_extensible_vmstat, 1,
141          {CPURAWIDLE}},
142         {SYSRAWINTERRUPTS, ASN_COUNTER, RONLY, var_extensible_vmstat, 1,
143          {SYSRAWINTERRUPTS}},
144         {SYSRAWCONTEXT, ASN_COUNTER, RONLY, var_extensible_vmstat, 1,
145          {SYSRAWCONTEXT}},
146         /*
147          * Future use: 
148          */
149         /*
150          * {ERRORFLAG, ASN_INTEGER, RONLY, var_extensible_vmstat, 1, {ERRORFLAG }},
151          * {ERRORMSG, ASN_OCTET_STR, RONLY, var_extensible_vmstat, 1, {ERRORMSG }}
152          */
153     };
154
155     /*
156      * Define the OID pointer to the top of the mib tree that we're
157      * registering underneath 
158      */
159     oid             vmstat_variables_oid[] = { UCDAVIS_MIB, 11 };
160
161     /*
162      * register ourselves with the agent to handle our mib tree 
163      */
164     REGISTER_MIB("ucd-snmp/vmstat", extensible_vmstat_variables, variable2,
165                  vmstat_variables_oid);
166
167 }
168
169
170
171 #define VMSTAT_FILE "/proc/stat"
172
173 void
174 getstat(unsigned long *cuse, unsigned long *cice, unsigned long *csys,
175         unsigned long *cide, unsigned long *pin, unsigned long *pout,
176         unsigned long *swpin, unsigned long *swpout, unsigned long *itot,
177         unsigned long *i1, unsigned long *ct)
178 {
179     int             statfd;
180     int             first = 1;
181     static char    *buff = NULL;
182     static int      bsize = 0;
183
184     if ((statfd = open(VMSTAT_FILE, O_RDONLY, 0)) != -1) {
185         char           *b;
186         if (bsize == 0) {
187             bsize = 128;
188             buff = malloc(bsize);
189         }
190         while (read(statfd, buff, bsize) == bsize) {
191             bsize += 256;
192             buff = realloc(buff, bsize);
193             DEBUGMSGTL(("vmstat", "/proc/stat buffer increased to %d\n", bsize));
194             close(statfd);
195             statfd = open(VMSTAT_FILE, O_RDONLY, 0);
196         }
197         close(statfd);
198         *itot = 0;
199         *i1 = 1;                /* ensure assert below will fail if the sscanf bombs */
200         b = strstr(buff, "cpu ");
201         if (b)
202             sscanf(b, "cpu  %lu %lu %lu %lu", cuse, cice, csys, cide);
203         else {
204             if (first)
205                 snmp_log(LOG_ERR, "No cpu line in /proc/stat\n");
206             *cuse = *cice = *csys = *cide = 0;
207         }
208         b = strstr(buff, "page ");
209         if (b)
210             sscanf(b, "page %lu %lu", pin, pout);
211         else {
212             if (first)
213                 snmp_log(LOG_ERR, "No page line in /proc/stat\n");
214             *pin = *pout = 0;
215         }
216         b = strstr(buff, "swap ");
217         if (b)
218             sscanf(b, "swap %lu %lu", swpin, swpout);
219         else {
220             if (first)
221                 snmp_log(LOG_ERR, "No swap line in /proc/stat\n");
222             *swpin = *swpout = 0;
223         }
224         b = strstr(buff, "intr ");
225         if (b)
226             sscanf(b, "intr %lu %lu", itot, i1);
227         else {
228             if (first)
229                 snmp_log(LOG_ERR, "No intr line in /proc/stat\n");
230             *itot = 0;
231         }
232         b = strstr(buff, "ctxt ");
233         if (b)
234             sscanf(b, "ctxt %lu", ct);
235         else {
236             if (first)
237                 snmp_log(LOG_ERR, "No ctxt line in /proc/stat\n");
238             *ct = 0;
239         }
240         first = 0;
241     } else {
242         snmp_log_perror(VMSTAT_FILE);
243     }
244 }
245
246 enum vmstat_index { swapin = 0, swapout,
247     iosent, ioreceive,
248     sysinterrupts, syscontext,
249     cpuuser, cpusystem, cpuidle,
250     cpurawuser, cpurawnice,
251     cpurawsystem, cpurawidle,
252     sysrawinterrupts, sysrawcontext
253 };
254
255 unsigned
256 vmstat(int iindex)
257 {
258     unsigned long   cpu_use, cpu_nic, cpu_sys, cpu_idl;
259     double          duse, dsys, didl, ddiv, divo2;
260     unsigned long   pgpgin, pgpgout, pswpin, pswpout;
261     unsigned long   inter, ticks, ctxt;
262     unsigned int    hz;
263
264     getstat(&cpu_use, &cpu_nic, &cpu_sys, &cpu_idl,
265             &pgpgin, &pgpgout, &pswpin, &pswpout, &inter, &ticks, &ctxt);
266     duse = cpu_use + cpu_nic;
267     dsys = cpu_sys;
268     didl = cpu_idl;
269     ddiv = (duse + dsys + didl);
270     hz = sysconf(_SC_CLK_TCK);  /* get ticks/s from system */
271     divo2 = ddiv / 2;
272
273     switch (iindex) {
274     case swapin:
275         return (pswpin * 4 * hz + divo2) / ddiv;
276     case swapout:
277         return (pswpout * 4 * hz + divo2) / ddiv;
278     case iosent:
279         return (pgpgin * hz + divo2) / ddiv;
280     case ioreceive:
281         return (pgpgout * hz + divo2) / ddiv;
282     case sysinterrupts:
283         return (inter * hz + divo2) / ddiv;
284     case syscontext:
285         return (ctxt * hz + divo2) / ddiv;
286     case cpuuser:
287         return (100 * duse / ddiv);
288     case cpusystem:
289         return (100 * dsys / ddiv);
290     case cpuidle:
291         return (100 * didl / ddiv);
292     case cpurawuser:
293         return cpu_use;
294     case cpurawnice:
295         return cpu_nic;
296     case cpurawsystem:
297         return cpu_sys;
298     case cpurawidle:
299         return cpu_idl;
300     case sysrawinterrupts:
301         return inter;
302     case sysrawcontext:
303         return ctxt;
304     default:
305         return -1;
306     }
307 }
308
309 unsigned char  *
310 var_extensible_vmstat(struct variable *vp,
311                       oid * name,
312                       size_t * length,
313                       int exact,
314                       size_t * var_len, WriteMethod ** write_method)
315 {
316
317     static long     long_ret;
318     static char     errmsg[300];
319 #ifndef linux
320     struct vmtotal  total;
321 #endif
322
323     long_ret = 0;               /* set to 0 as default */
324
325     if (header_generic(vp, name, length, exact, var_len, write_method))
326         return (NULL);
327     switch (vp->magic) {
328     case MIBINDEX:
329         long_ret = 1;
330         return ((u_char *) (&long_ret));
331     case ERRORNAME:            /* dummy name */
332         sprintf(errmsg, "systemStats");
333         *var_len = strlen(errmsg);
334         return ((u_char *) (errmsg));
335     case SWAPIN:
336 #ifdef linux
337         long_ret = vmstat(swapin);
338 #endif
339         return ((u_char *) (&long_ret));
340     case SWAPOUT:
341 #ifdef linux
342         long_ret = vmstat(swapout);
343 #endif
344         return ((u_char *) (&long_ret));
345     case IOSENT:
346 #ifdef linux
347         long_ret = vmstat(iosent);
348 #endif
349         return ((u_char *) (&long_ret));
350     case IORECEIVE:
351 #ifdef linux
352         long_ret = vmstat(ioreceive);
353 #endif
354         return ((u_char *) (&long_ret));
355     case SYSINTERRUPTS:
356 #ifdef linux
357         long_ret = vmstat(sysinterrupts);
358 #endif
359         return ((u_char *) (&long_ret));
360     case SYSCONTEXT:
361 #ifdef linux
362         long_ret = vmstat(syscontext);
363 #endif
364         return ((u_char *) (&long_ret));
365     case CPUUSER:
366 #ifdef linux
367         long_ret = vmstat(cpuuser);
368 #endif
369         return ((u_char *) (&long_ret));
370     case CPUSYSTEM:
371 #ifdef linux
372         long_ret = vmstat(cpusystem);
373 #endif
374         return ((u_char *) (&long_ret));
375     case CPUIDLE:
376 #ifdef linux
377         long_ret = vmstat(cpuidle);
378 #endif
379         return ((u_char *) (&long_ret));
380     case CPURAWUSER:
381 #ifdef linux
382         long_ret = vmstat(cpurawuser);
383 #endif
384         return ((u_char *) (&long_ret));
385     case CPURAWNICE:
386 #ifdef linux
387         long_ret = vmstat(cpurawnice);
388 #endif
389         return ((u_char *) (&long_ret));
390     case CPURAWSYSTEM:
391 #ifdef linux
392         long_ret = vmstat(cpurawsystem);
393 #endif
394         return ((u_char *) (&long_ret));
395     case CPURAWIDLE:
396 #ifdef linux
397         long_ret = vmstat(cpurawidle);
398 #endif
399         return ((u_char *) (&long_ret));
400     case SYSRAWINTERRUPTS:
401 #ifdef linux
402         long_ret = vmstat(sysrawinterrupts);
403 #endif
404         return ((u_char *) (&long_ret));
405     case SYSRAWCONTEXT:
406 #ifdef linux
407         long_ret = vmstat(sysrawcontext);
408 #endif
409         return ((u_char *) (&long_ret));
410         /*
411          * reserved for future use 
412          */
413         /*
414          * case ERRORFLAG:
415          * return((u_char *) (&long_ret));
416          * case ERRORMSG:
417          * return((u_char *) (&long_ret));
418          */
419     }
420     return NULL;
421 }