1 /*
2  * Copyright (c) 2003 Daniel Hartmeier
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  *
9  *    - Redistributions of source code must retain the above copyright
10  *      notice, this list of conditions and the following disclaimer.
11  *    - Redistributions in binary form must reproduce the above
12  *      copyright notice, this list of conditions and the following
13  *      disclaimer in the documentation and/or other materials provided
14  *      with the distribution.
15  *
16  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
19  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
20  * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
21  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
22  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
23  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
24  * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
26  * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
27  * POSSIBILITY OF SUCH DAMAGE.
28  *
29  */
30 
31 #include <sys/param.h>
32 #include <sys/mbuf.h>
33 #include <sys/sysctl.h>
34 #include <sys/errno.h>
35 
36 #include <errno.h>
37 #include <string.h>
38 #include <unistd.h>
39 
40 #include "conf.h"
41 #include "error.h"
42 #include "symon.h"
43 
44 #ifndef HAS_KERN_MBSTAT
45 void
init_mbuf(struct stream * st)46 init_mbuf(struct stream *st)
47 {
48     fatal("mbuf module requires system upgrade (sysctl.h/KERN_MBSTAT)");
49 }
50 int
get_mbuf(char * symon_buf,int maxlen,struct stream * st)51 get_mbuf(char *symon_buf, int maxlen, struct stream *st)
52 {
53     fatal("mbuf module requires system upgrade (sysctl.h/KERN_MBSTAT)");
54 }
55 #else
56 void
init_mbuf(struct stream * st)57 init_mbuf(struct stream *st)
58 {
59     info("started module mbuf(%.200s)", st->arg);
60 }
61 
62 int
get_mbuf(char * symon_buf,int maxlen,struct stream * st)63 get_mbuf(char *symon_buf, int maxlen, struct stream *st)
64 {
65     struct mbstat mbstat;
66     int npools;
67     struct pool pool, mbpool, mclpool;
68     int mib[4];
69     size_t size;
70     int i;
71     char name[32];
72     int flag = 0;
73     int nmbtypes = sizeof(mbstat.m_mtypes) / sizeof(short);
74     int page_size = getpagesize();
75     int totmem, totused, totmbufs, totpct;
76     u_int32_t stats[15];
77 
78     totmem = totused = 0;
79 
80     mib[0] = CTL_KERN;
81     mib[1] = KERN_MBSTAT;
82     size = sizeof(mbstat);
83     if (sysctl(mib, 2, &mbstat, &size, NULL, 0) < 0) {
84         warning("mbuf(%.200s) failed (sysctl() %.200s)", st->arg, strerror(errno));
85         return 0;
86     }
87 
88     mib[0] = CTL_KERN;
89     mib[1] = KERN_POOL;
90     mib[2] = KERN_POOL_NPOOLS;
91     size = sizeof(npools);
92     if (sysctl(mib, 3, &npools, &size, NULL, 0) < 0) {
93         warning("mbuf(%.200s) failed (sysctl() %.200s)", st->arg, strerror(errno));
94         return 0;
95     }
96 
97     for (i = 1; npools; ++i) {
98         mib[0] = CTL_KERN;
99         mib[1] = KERN_POOL;
100         mib[2] = KERN_POOL_POOL;
101         mib[3] = i;
102         size = sizeof(pool);
103         if (sysctl(mib, 4, &pool, &size, NULL, 0) < 0) {
104             warning("mbuf(%.200s) failed (sysctl() %.200s)", st->arg, strerror(errno));
105             return 0;
106         }
107         npools--;
108         mib[2] = KERN_POOL_NAME;
109         size = sizeof(name);
110         if (sysctl(mib, 4, name, &size, NULL, 0) < 0) {
111             warning("mbuf(%.200s) failed (sysctl() %.200s)", st->arg, strerror(errno));
112             return (0);
113         }
114         if (!strcmp(name, "mbpl")) {
115             bcopy(&pool, &mbpool, sizeof(pool));
116             flag |= (1 << 0);
117         } else if (!strcmp(name, "mclpl")) {
118             bcopy(&pool, &mclpool, sizeof(pool));
119             totmem += mclpool.pr_npages * page_size;
120             totused += (mclpool.pr_nget - mclpool.pr_nput) * mclpool.pr_size;
121             flag |= (1 << 1);
122         } else if (!strcmp(name, "mcl2k")) {
123             bcopy(&pool, &mclpool, sizeof(pool));
124             totmem += mclpool.pr_npages * page_size;
125             totused += (mclpool.pr_nget - mclpool.pr_nput) * mclpool.pr_size;
126             flag |= (1 << 2);
127         } else if (!strcmp(name, "mcl4k")) {
128             bcopy(&pool, &mclpool, sizeof(pool));
129             totmem += mclpool.pr_npages * page_size;
130             totused += (mclpool.pr_nget - mclpool.pr_nput) * mclpool.pr_size;
131             flag |= (1 << 3);
132         } else if (!strcmp(name, "mcl8k")) {
133             bcopy(&pool, &mclpool, sizeof(pool));
134             totmem += mclpool.pr_npages * page_size;
135             totused += (mclpool.pr_nget - mclpool.pr_nput) * mclpool.pr_size;
136             flag |= (1 << 4);
137         } else if (!strcmp(name, "mcl9k")) {
138             bcopy(&pool, &mclpool, sizeof(pool));
139             totmem += mclpool.pr_npages * page_size;
140             totused += (mclpool.pr_nget - mclpool.pr_nput) * mclpool.pr_size;
141             flag |= (1 << 5);
142         } else if (!strcmp(name, "mcl12k")) {
143             bcopy(&pool, &mclpool, sizeof(pool));
144             totmem += mclpool.pr_npages * page_size;
145             totused += (mclpool.pr_nget - mclpool.pr_nput) * mclpool.pr_size;
146             flag |= (1 << 6);
147         } else if (!strcmp(name, "mcl16k")) {
148             bcopy(&pool, &mclpool, sizeof(pool));
149             totmem += mclpool.pr_npages * page_size;
150             totused += (mclpool.pr_nget - mclpool.pr_nput) * mclpool.pr_size;
151             flag |= (1 << 7);
152         } else if (!strcmp(name, "mcl64k")) {
153             bcopy(&pool, &mclpool, sizeof(pool));
154             totmem += mclpool.pr_npages * page_size;
155             totused += (mclpool.pr_nget - mclpool.pr_nput) * mclpool.pr_size;
156             flag |= (1 << 8);
157         }
158         if (flag == 3 || flag == 509)
159             break;
160     }
161 
162     /* Check pre/post h2k8 mcpl */
163     if ((flag != 3) && (flag != 509)) {
164         warning("mbuf(%.200s) failed (%d)", st->arg, flag);
165         return 0;
166     }
167 
168     totmbufs = 0;
169     for (i = 0; i < nmbtypes; ++i)
170         totmbufs += mbstat.m_mtypes[i];
171     totmem += mbpool.pr_npages * page_size;
172     totused += (mbpool.pr_nget - mbpool.pr_nput) * mbpool.pr_size;
173     totpct = (totmem == 0) ? 0 : ((totused * 100) / totmem);
174 
175     stats[0] = totmbufs;
176     stats[1] = mbstat.m_mtypes[MT_DATA];
177     stats[2] = mbstat.m_mtypes[MT_OOBDATA];
178     stats[3] = mbstat.m_mtypes[MT_CONTROL];
179     stats[4] = mbstat.m_mtypes[MT_HEADER];
180     stats[5] = mbstat.m_mtypes[MT_FTABLE];
181     stats[6] = mbstat.m_mtypes[MT_SONAME];
182     stats[7] = mbstat.m_mtypes[MT_SOOPTS];
183     stats[8] = mclpool.pr_nget - mclpool.pr_nput;
184     stats[9] = mclpool.pr_npages * mclpool.pr_itemsperpage;
185     stats[10] = totmem;
186     stats[11] = totpct;
187     stats[12] = mbstat.m_drops;
188     stats[13] = mbstat.m_wait;
189     stats[14] = mbstat.m_drain;
190 
191     return snpack(symon_buf, maxlen, st->arg, MT_MBUF,
192                   stats[0],
193                   stats[1],
194                   stats[2],
195                   stats[3],
196                   stats[4],
197                   stats[5],
198                   stats[6],
199                   stats[7],
200                   stats[8],
201                   stats[9],
202                   stats[10],
203                   stats[11],
204                   stats[12],
205                   stats[13],
206                   stats[14]);
207 }
208 #endif /* HAS_KERN_MBSTAT */
209