Annotation of src/usr.bin/systat/mbufs.c, Revision 1.22
1.21 canacar 1: /* $OpenBSD: mbufs.c,v 1.20 2008/12/18 19:46:39 canacar Exp $ */
1.19 canacar 2: /*
3: * Copyright (c) 2008 Can Erkin Acar <canacar@openbsd.org>
1.1 deraadt 4: *
1.19 canacar 5: * Permission to use, copy, modify, and distribute this software for any
6: * purpose with or without fee is hereby granted, provided that the above
7: * copyright notice and this permission notice appear in all copies.
1.1 deraadt 8: *
1.19 canacar 9: * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10: * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11: * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
12: * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13: * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14: * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
15: * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
1.1 deraadt 16: */
17: #include <sys/param.h>
18: #include <sys/types.h>
1.19 canacar 19: #include <sys/socket.h>
20: #include <sys/sysctl.h>
1.1 deraadt 21: #include <sys/mbuf.h>
1.19 canacar 22: #include <net/if.h>
1.1 deraadt 23:
1.19 canacar 24: #include <err.h>
25: #include <errno.h>
26: #include <ifaddrs.h>
1.1 deraadt 27: #include <stdlib.h>
28: #include <string.h>
1.19 canacar 29:
1.1 deraadt 30: #include "systat.h"
1.18 canacar 31:
32:
1.19 canacar 33: /* pool info for mcl* pools */
34: struct mclpool_info {
35: char title[16];
36: int pool_offset;
37: int size;
38: } mclpools[MCLPOOLS];
39:
40: int mclpool_count = 0;
41: int mbpool_index = -1;
42: struct pool mbpool;
43:
44: /* interfaces */
45: static int num_ifs;
46: struct if_info {
47: char name[16];
48: struct if_data data;
49: } *interfaces = NULL;
50:
1.18 canacar 51: void print_mb(void);
52: int read_mb(void);
53: int select_mb(void);
1.19 canacar 54: static void
55: showmbuf(struct if_info *, int);
1.1 deraadt 56:
57:
1.19 canacar 58: /* Define fields */
59: field_def fields_mbuf[] = {
60: {"IFACE", 8, 16, 1, FLD_ALIGN_LEFT, -1, 0, 0, 0},
61: {"RXDELAY", 5, 8, 1, FLD_ALIGN_RIGHT, -1, 0, 0, 0},
62: {"TXDELAY", 5, 8, 1, FLD_ALIGN_RIGHT, -1, 0, 0, 0},
63: {"LIVELOCKS", 5, 10, 1, FLD_ALIGN_RIGHT, -1, 0, 0, 0},
64: {"SIZE", 3, 5, 1, FLD_ALIGN_RIGHT, -1, 0, 0, 0},
65: {"ALIVE", 3, 5, 1, FLD_ALIGN_RIGHT, -1, 0, 0, 0},
66: {"LWM", 3, 5, 1, FLD_ALIGN_RIGHT, -1, 0, 0, 0},
67: {"HWM", 3, 5, 1, FLD_ALIGN_RIGHT, -1, 0, 0, 0},
1.22 ! dlg 68: {"CWM", 3, 5, 1, FLD_ALIGN_RIGHT, -1, 0, 0, 0},
1.1 deraadt 69: };
70:
71:
1.19 canacar 72: #define FIELD_ADDR(x) (&fields_mbuf[x])
1.18 canacar 73:
1.19 canacar 74: #define FLD_MB_IFACE FIELD_ADDR(0)
75: #define FLD_MB_RXDELAY FIELD_ADDR(1)
76: #define FLD_MB_TXDELAY FIELD_ADDR(2)
77: #define FLD_MB_LLOCKS FIELD_ADDR(3)
78: #define FLD_MB_MSIZE FIELD_ADDR(4)
79: #define FLD_MB_MALIVE FIELD_ADDR(5)
80: #define FLD_MB_MLWM FIELD_ADDR(6)
81: #define FLD_MB_MHWM FIELD_ADDR(7)
1.22 ! dlg 82: #define FLD_MB_MCWM FIELD_ADDR(8)
1.18 canacar 83:
84:
85: /* Define views */
1.19 canacar 86: field_def *view_mbuf[] = {
87: FLD_MB_IFACE,
88: #if NOTYET
89: FLD_MB_RXDELAY, FLD_MB_TXDELAY,
90: #endif
91: FLD_MB_LLOCKS, FLD_MB_MSIZE, FLD_MB_MALIVE, FLD_MB_MLWM, FLD_MB_MHWM,
1.22 ! dlg 92: FLD_MB_MCWM, NULL
1.18 canacar 93: };
94:
1.19 canacar 95: /* Define view managers */
1.18 canacar 96:
97: struct view_manager mbuf_mgr = {
98: "Mbufs", select_mb, read_mb, NULL, print_header,
99: print_mb, keyboard_callback, NULL, NULL
100: };
101:
102: field_view views_mb[] = {
1.19 canacar 103: {view_mbuf, "mbufs", '4', &mbuf_mgr},
1.18 canacar 104: {NULL, NULL, 0, NULL}
105: };
106:
107:
108: int
1.19 canacar 109: initmembufs(void)
1.1 deraadt 110: {
1.19 canacar 111: field_view *v;
112: int i, mib[4], npools;
113: struct pool pool;
114: char pname[32];
115: size_t size;
116:
117: /* go through all pools to identify mbuf and cluster pools */
118: bzero(mclpools, sizeof(mclpools));
1.18 canacar 119:
1.19 canacar 120: mib[0] = CTL_KERN;
121: mib[1] = KERN_POOL;
122: mib[2] = KERN_POOL_NPOOLS;
123: size = sizeof(npools);
124:
125: if (sysctl(mib, 3, &npools, &size, NULL, 0) < 0) {
126: err(1, "sysctl(KERN_POOL_NPOOLS)");
127: /* NOTREACHED */
128: }
129:
130: for (i = 1; i <= npools; i++) {
131: mib[0] = CTL_KERN;
132: mib[1] = KERN_POOL;
133: mib[2] = KERN_POOL_NAME;
134: mib[3] = i;
135: size = sizeof(pname);
136: if (sysctl(mib, 4, &pname, &size, NULL, 0) < 0) {
1.21 canacar 137: continue;
1.19 canacar 138: }
139:
140: if (strcmp(pname, "mbpl") == 0) {
141: mbpool_index = i;
142: continue;
143: }
144:
145: if (strncmp(pname, "mcl", 3) != 0)
146: continue;
147:
148: if (mclpool_count == MCLPOOLS) {
149: warnx("mbufs: Too many mcl* pools", i);
150: break;
151: }
152:
153: mib[2] = KERN_POOL_POOL;
154: size = sizeof(struct pool);
155:
156: if (sysctl(mib, 4, &pool, &size, NULL, 0) < 0) {
157: err(1, "sysctl(KERN_POOL_POOL, %d)", i);
158: /* NOTREACHED */
159: }
160:
161: mclpools[mclpool_count].size = pool.pr_size;
162: mclpools[mclpool_count].pool_offset = i;
163: snprintf(mclpools[mclpool_count].title,
164: sizeof(mclpools[0].title), "%dk",
165: pool.pr_size / 1024);
166:
167: mclpool_count++;
168: }
169:
170: if (mclpool_count != MCLPOOLS)
171: warnx("mbufs: Unable to read all %d mcl* pools", MCLPOOLS);
172:
173: /* add view to the engine */
174: for (v = views_mb; v->name != NULL; v++)
175: add_view(v);
176:
177:
178: /* finally read it once */
1.18 canacar 179: read_mb();
180:
1.19 canacar 181: return(1);
182: }
1.18 canacar 183:
1.19 canacar 184: int
185: select_mb(void)
186: {
187: num_disp = 0;
1.18 canacar 188: return (0);
1.1 deraadt 189: }
190:
1.18 canacar 191: int
192: read_mb(void)
1.1 deraadt 193: {
1.19 canacar 194: struct pool pool;
195: struct ifaddrs *ifap, *ifa;
196: struct if_info *ifi;
197: int mib[4];
198: int i, p, nif, ret = 1;
199: size_t size;
200:
201: num_disp = 0;
202: if (getifaddrs(&ifap)) {
203: error("getifaddrs: %s", strerror(errno));
204: return (1);
205: }
206:
207: nif = 1;
208: for (ifa = ifap; ifa != NULL; ifa = ifa->ifa_next)
209: if (ifa->ifa_addr && ifa->ifa_addr->sa_family == AF_LINK)
210: nif++;
211:
212: if (interfaces == NULL || num_ifs < nif) {
213: size_t len = sizeof(*ifi) * nif;
214: if (nif > SIZE_MAX / sizeof(*ifi)) {
215: error("overflow allocting %u interfaces", nif);
216: goto exit;
217: }
218:
219: ifi = realloc(interfaces, len);
220: if (ifi == NULL) {
221: error("realloc: out of memory allocating %lld bytes",
222: (long long) len);
223: goto exit;
224: }
225:
226: interfaces = ifi;
227: num_ifs = nif;
228: }
229:
230: /* Fill in the "real" interfaces */
231: ifi = interfaces + 1;
232:
233: for (ifa = ifap; ifa != NULL; ifa = ifa->ifa_next) {
234: if (ifa->ifa_addr == NULL ||
235: ifa->ifa_addr->sa_family != AF_LINK)
236: continue;
237:
238: strlcpy(ifi->name, ifa->ifa_name, sizeof(ifi->name));
239:
240: if (ifa->ifa_data)
241: memcpy(&ifi->data, ifa->ifa_data, sizeof(ifi->data));
242: else
243: bzero(&ifi->data, sizeof(ifi->data));
244: ifi++;
245: }
246:
247: /* Fill in the "System" entry from pools */
248: bzero(interfaces, sizeof(interfaces[0]));
249: strlcpy(interfaces[0].name, "System", sizeof(interfaces[0].name));
1.18 canacar 250:
251: mib[0] = CTL_KERN;
1.19 canacar 252: mib[1] = KERN_POOL;
253: mib[2] = KERN_POOL_POOL;
254: mib[3] = mbpool_index;
255: size = sizeof(struct pool);
256:
257: if (sysctl(mib, 4, &mbpool, &size, NULL, 0) < 0) {
258: error("sysctl(KERN_POOL_POOL, %d)", i);
259: goto exit;
260: }
261:
262: for (i = 0; i < mclpool_count; i++) {
263: struct mclpool *mp = &interfaces[0].data.ifi_mclpool[i];
264:
265: mib[3] = mclpools[i].pool_offset;
266: size = sizeof(struct pool);
1.18 canacar 267:
1.19 canacar 268: if (sysctl(mib, 4, &pool, &size, NULL, 0) < 0) {
269: error("sysctl(KERN_POOL_POOL, %d)", mib[3]);
270: continue;
271: }
272:
273: mp->mcl_alive = pool.pr_nget - pool.pr_nput;
274: mp->mcl_hwm = pool.pr_hiwat;
1.18 canacar 275: }
276:
1.19 canacar 277: num_disp = 1;
278: ret = 0;
1.18 canacar 279:
1.19 canacar 280: for (i = 0; i < num_ifs; i++) {
281: struct if_info *ifi = &interfaces[i];
282: int pnd = num_disp;
283: for (p = 0; p < mclpool_count; p++) {
284: struct mclpool *mp = &ifi->data.ifi_mclpool[p];
285: if (mp->mcl_alive == 0)
286: continue;
287: num_disp++;
288: }
289: if (i && pnd == num_disp)
290: num_disp++;
1.18 canacar 291: }
292:
1.19 canacar 293: exit:
294: freeifaddrs(ifap);
295: return (ret);
1.1 deraadt 296: }
297:
298: void
1.18 canacar 299: print_mb(void)
1.1 deraadt 300: {
1.19 canacar 301: int i, p, n, count = 0;
1.1 deraadt 302:
1.19 canacar 303: showmbuf(interfaces, -1);
304:
305: for (n = i = 0; i < num_ifs; i++) {
306: struct if_info *ifi = &interfaces[i];
307: int pcnt = count;
1.18 canacar 308: if (maxprint > 0 && count >= maxprint)
1.19 canacar 309: return;
1.1 deraadt 310:
1.19 canacar 311: for (p = 0; p < mclpool_count; p++) {
312: struct mclpool *mp = &ifi->data.ifi_mclpool[p];
313: if (mp->mcl_alive == 0)
314: continue;
315: if (n++ >= dispstart) {
316: showmbuf(ifi, p);
317: count++;
318: }
319: }
320:
321: if (i && pcnt == count) {
322: /* only print the first line */
323: if (n++ >= dispstart) {
324: showmbuf(ifi, -1);
325: count++;
326: }
327: }
1.1 deraadt 328:
1.5 ericj 329:
1.19 canacar 330: }
1.1 deraadt 331: }
332:
1.18 canacar 333:
334: static void
1.19 canacar 335: showmbuf(struct if_info *ifi, int p)
1.1 deraadt 336: {
1.18 canacar 337: int i;
338:
1.19 canacar 339: if (p == -1 || (p == 0 && ifi != interfaces)) {
340: print_fld_str(FLD_MB_IFACE, ifi->name);
341: }
342:
343: if (p == -1 && ifi == interfaces) {
344: print_fld_size(FLD_MB_MSIZE, mbpool.pr_size);
345: print_fld_size(FLD_MB_MALIVE, mbpool.pr_nget - mbpool.pr_nput);
346: print_fld_size(FLD_MB_MHWM, mbpool.pr_hiwat);
347: }
348:
349:
350:
351: #if NOTYET
352: print_fld_uint(FLD_MB_RXDELAY, ifi->data.ifi_rxdelay);
353: print_fld_uint(FLD_MB_TXDELAY, ifi->data.ifi_txdelay);
354: #endif
1.20 canacar 355: if (ifi->data.ifi_livelocks)
356: print_fld_size(FLD_MB_LLOCKS, ifi->data.ifi_livelocks);
1.19 canacar 357:
358: if (p >= 0 && p < mclpool_count) {
359: struct mclpool *mp = &ifi->data.ifi_mclpool[p];
360:
361: print_fld_str(FLD_MB_MSIZE, mclpools[p].title);
362: print_fld_uint(FLD_MB_MALIVE, mp->mcl_alive);
363: if (mp->mcl_lwm)
364: print_fld_size(FLD_MB_MLWM, mp->mcl_lwm);
365: if (mp->mcl_hwm)
366: print_fld_size(FLD_MB_MHWM, mp->mcl_hwm);
1.22 ! dlg 367: if (mp->mcl_cwm)
! 368: print_fld_size(FLD_MB_MCWM, mp->mcl_cwm);
1.19 canacar 369: }
1.18 canacar 370:
371: end_line();
1.1 deraadt 372: }
1.18 canacar 373:
374: