Annotation of src/usr.bin/systat/mbufs.c, Revision 1.29
1.29 ! dlg 1: /* $OpenBSD: mbufs.c,v 1.28 2010/08/01 05:30:13 blambert 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.28 blambert 22: #include <sys/pool.h>
1.19 canacar 23: #include <net/if.h>
1.1 deraadt 24:
1.19 canacar 25: #include <err.h>
26: #include <errno.h>
27: #include <ifaddrs.h>
1.1 deraadt 28: #include <stdlib.h>
29: #include <string.h>
1.19 canacar 30:
1.1 deraadt 31: #include "systat.h"
1.18 canacar 32:
33:
1.19 canacar 34: /* pool info for mcl* pools */
35: struct mclpool_info {
36: char title[16];
37: int pool_offset;
38: int size;
39: } mclpools[MCLPOOLS];
40:
41: int mclpool_count = 0;
42: int mbpool_index = -1;
43: struct pool mbpool;
44:
45: /* interfaces */
46: static int num_ifs;
47: struct if_info {
48: char name[16];
49: struct if_data data;
50: } *interfaces = NULL;
51:
1.18 canacar 52: void print_mb(void);
53: int read_mb(void);
54: int select_mb(void);
1.23 kettenis 55: static void showmbuf(struct if_info *, int, 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)
1.26 henning 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)
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
1.26 henning 91: FLD_MB_LLOCKS, FLD_MB_MSIZE, FLD_MB_MALIVE, FLD_MB_MLWM, FLD_MB_MHWM,
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) {
1.24 chl 149: warnx("mbufs: Too many mcl* pools");
1.19 canacar 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) {
1.27 chl 258: error("sysctl(KERN_POOL_POOL, %d)", mib[3]);
1.19 canacar 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.23 kettenis 303: showmbuf(interfaces, -1, 1);
1.19 canacar 304:
305: for (n = i = 0; i < num_ifs; i++) {
306: struct if_info *ifi = &interfaces[i];
307: int pcnt = count;
1.23 kettenis 308: int showif = i;
309:
1.18 canacar 310: if (maxprint > 0 && count >= maxprint)
1.19 canacar 311: return;
1.1 deraadt 312:
1.19 canacar 313: for (p = 0; p < mclpool_count; p++) {
314: struct mclpool *mp = &ifi->data.ifi_mclpool[p];
315: if (mp->mcl_alive == 0)
316: continue;
317: if (n++ >= dispstart) {
1.23 kettenis 318: showmbuf(ifi, p, showif);
319: showif = 0;
1.19 canacar 320: count++;
321: }
322: }
323:
324: if (i && pcnt == count) {
325: /* only print the first line */
326: if (n++ >= dispstart) {
1.23 kettenis 327: showmbuf(ifi, -1, 1);
1.19 canacar 328: count++;
329: }
330: }
1.1 deraadt 331:
1.5 ericj 332:
1.19 canacar 333: }
1.1 deraadt 334: }
335:
1.18 canacar 336:
337: static void
1.23 kettenis 338: showmbuf(struct if_info *ifi, int p, int showif)
1.1 deraadt 339: {
1.23 kettenis 340: if (showif)
1.19 canacar 341: print_fld_str(FLD_MB_IFACE, ifi->name);
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: #if NOTYET
350: print_fld_uint(FLD_MB_RXDELAY, ifi->data.ifi_rxdelay);
351: print_fld_uint(FLD_MB_TXDELAY, ifi->data.ifi_txdelay);
1.20 canacar 352: if (ifi->data.ifi_livelocks)
353: print_fld_size(FLD_MB_LLOCKS, ifi->data.ifi_livelocks);
1.29 ! dlg 354: #endif
1.19 canacar 355:
356: if (p >= 0 && p < mclpool_count) {
357: struct mclpool *mp = &ifi->data.ifi_mclpool[p];
358:
359: print_fld_str(FLD_MB_MSIZE, mclpools[p].title);
360: print_fld_uint(FLD_MB_MALIVE, mp->mcl_alive);
361: if (mp->mcl_lwm)
362: print_fld_size(FLD_MB_MLWM, mp->mcl_lwm);
363: if (mp->mcl_hwm)
364: print_fld_size(FLD_MB_MHWM, mp->mcl_hwm);
1.22 dlg 365: if (mp->mcl_cwm)
366: print_fld_size(FLD_MB_MCWM, mp->mcl_cwm);
1.19 canacar 367: }
1.18 canacar 368:
369: end_line();
1.1 deraadt 370: }