Annotation of src/usr.bin/systat/mbufs.c, Revision 1.30
1.30 ! dlg 1: /* $OpenBSD: mbufs.c,v 1.29 2010/09/23 10:49:55 dlg 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;
1.30 ! dlg 44: u_int mcllivelocks = 0;
1.19 canacar 45:
46: /* interfaces */
47: static int num_ifs;
48: struct if_info {
49: char name[16];
50: struct if_data data;
51: } *interfaces = NULL;
52:
1.18 canacar 53: void print_mb(void);
54: int read_mb(void);
55: int select_mb(void);
1.23 kettenis 56: static void showmbuf(struct if_info *, int, int);
1.1 deraadt 57:
58:
1.19 canacar 59: /* Define fields */
60: field_def fields_mbuf[] = {
61: {"IFACE", 8, 16, 1, FLD_ALIGN_LEFT, -1, 0, 0, 0},
62: {"RXDELAY", 5, 8, 1, FLD_ALIGN_RIGHT, -1, 0, 0, 0},
63: {"TXDELAY", 5, 8, 1, FLD_ALIGN_RIGHT, -1, 0, 0, 0},
64: {"LIVELOCKS", 5, 10, 1, FLD_ALIGN_RIGHT, -1, 0, 0, 0},
65: {"SIZE", 3, 5, 1, FLD_ALIGN_RIGHT, -1, 0, 0, 0},
66: {"ALIVE", 3, 5, 1, FLD_ALIGN_RIGHT, -1, 0, 0, 0},
67: {"LWM", 3, 5, 1, FLD_ALIGN_RIGHT, -1, 0, 0, 0},
68: {"HWM", 3, 5, 1, FLD_ALIGN_RIGHT, -1, 0, 0, 0},
1.22 dlg 69: {"CWM", 3, 5, 1, FLD_ALIGN_RIGHT, -1, 0, 0, 0},
1.1 deraadt 70: };
71:
72:
1.19 canacar 73: #define FIELD_ADDR(x) (&fields_mbuf[x])
1.18 canacar 74:
1.19 canacar 75: #define FLD_MB_IFACE FIELD_ADDR(0)
76: #define FLD_MB_RXDELAY FIELD_ADDR(1)
77: #define FLD_MB_TXDELAY FIELD_ADDR(2)
1.26 henning 78: #define FLD_MB_LLOCKS FIELD_ADDR(3)
79: #define FLD_MB_MSIZE FIELD_ADDR(4)
80: #define FLD_MB_MALIVE FIELD_ADDR(5)
81: #define FLD_MB_MLWM FIELD_ADDR(6)
82: #define FLD_MB_MHWM FIELD_ADDR(7)
83: #define FLD_MB_MCWM FIELD_ADDR(8)
1.18 canacar 84:
85:
86: /* Define views */
1.19 canacar 87: field_def *view_mbuf[] = {
88: FLD_MB_IFACE,
89: #if NOTYET
90: FLD_MB_RXDELAY, FLD_MB_TXDELAY,
91: #endif
1.26 henning 92: FLD_MB_LLOCKS, FLD_MB_MSIZE, FLD_MB_MALIVE, FLD_MB_MLWM, FLD_MB_MHWM,
93: FLD_MB_MCWM, NULL
1.18 canacar 94: };
95:
1.19 canacar 96: /* Define view managers */
1.18 canacar 97:
98: struct view_manager mbuf_mgr = {
99: "Mbufs", select_mb, read_mb, NULL, print_header,
100: print_mb, keyboard_callback, NULL, NULL
101: };
102:
103: field_view views_mb[] = {
1.19 canacar 104: {view_mbuf, "mbufs", '4', &mbuf_mgr},
1.18 canacar 105: {NULL, NULL, 0, NULL}
106: };
107:
108:
109: int
1.19 canacar 110: initmembufs(void)
1.1 deraadt 111: {
1.19 canacar 112: field_view *v;
113: int i, mib[4], npools;
114: struct pool pool;
115: char pname[32];
116: size_t size;
117:
118: /* go through all pools to identify mbuf and cluster pools */
119: bzero(mclpools, sizeof(mclpools));
1.18 canacar 120:
1.19 canacar 121: mib[0] = CTL_KERN;
122: mib[1] = KERN_POOL;
123: mib[2] = KERN_POOL_NPOOLS;
124: size = sizeof(npools);
125:
126: if (sysctl(mib, 3, &npools, &size, NULL, 0) < 0) {
127: err(1, "sysctl(KERN_POOL_NPOOLS)");
128: /* NOTREACHED */
129: }
130:
131: for (i = 1; i <= npools; i++) {
132: mib[0] = CTL_KERN;
133: mib[1] = KERN_POOL;
134: mib[2] = KERN_POOL_NAME;
135: mib[3] = i;
136: size = sizeof(pname);
137: if (sysctl(mib, 4, &pname, &size, NULL, 0) < 0) {
1.21 canacar 138: continue;
1.19 canacar 139: }
140:
141: if (strcmp(pname, "mbpl") == 0) {
142: mbpool_index = i;
143: continue;
144: }
145:
146: if (strncmp(pname, "mcl", 3) != 0)
147: continue;
148:
149: if (mclpool_count == MCLPOOLS) {
1.24 chl 150: warnx("mbufs: Too many mcl* pools");
1.19 canacar 151: break;
152: }
153:
154: mib[2] = KERN_POOL_POOL;
155: size = sizeof(struct pool);
156:
157: if (sysctl(mib, 4, &pool, &size, NULL, 0) < 0) {
158: err(1, "sysctl(KERN_POOL_POOL, %d)", i);
159: /* NOTREACHED */
160: }
161:
162: mclpools[mclpool_count].size = pool.pr_size;
163: mclpools[mclpool_count].pool_offset = i;
164: snprintf(mclpools[mclpool_count].title,
165: sizeof(mclpools[0].title), "%dk",
166: pool.pr_size / 1024);
167:
168: mclpool_count++;
169: }
170:
171: if (mclpool_count != MCLPOOLS)
172: warnx("mbufs: Unable to read all %d mcl* pools", MCLPOOLS);
173:
174: /* add view to the engine */
175: for (v = views_mb; v->name != NULL; v++)
176: add_view(v);
177:
178:
179: /* finally read it once */
1.18 canacar 180: read_mb();
181:
1.19 canacar 182: return(1);
183: }
1.18 canacar 184:
1.19 canacar 185: int
186: select_mb(void)
187: {
188: num_disp = 0;
1.18 canacar 189: return (0);
1.1 deraadt 190: }
191:
1.18 canacar 192: int
193: read_mb(void)
1.1 deraadt 194: {
1.19 canacar 195: struct pool pool;
196: struct ifaddrs *ifap, *ifa;
197: struct if_info *ifi;
198: int mib[4];
199: int i, p, nif, ret = 1;
200: size_t size;
201:
1.30 ! dlg 202: mib[0] = CTL_KERN;
! 203: mib[1] = KERN_NETLIVELOCKS;
! 204: size = sizeof(mcllivelocks);
! 205: if (sysctl(mib, 2, &mcllivelocks, &size, NULL, 0) < 0 &&
! 206: errno != EOPNOTSUPP) {
! 207: error("sysctl(KERN_NETLIVELOCKS)");
! 208: goto exit;
! 209: }
! 210:
1.19 canacar 211: num_disp = 0;
212: if (getifaddrs(&ifap)) {
213: error("getifaddrs: %s", strerror(errno));
214: return (1);
215: }
216:
217: nif = 1;
218: for (ifa = ifap; ifa != NULL; ifa = ifa->ifa_next)
219: if (ifa->ifa_addr && ifa->ifa_addr->sa_family == AF_LINK)
220: nif++;
221:
222: if (interfaces == NULL || num_ifs < nif) {
223: size_t len = sizeof(*ifi) * nif;
224: if (nif > SIZE_MAX / sizeof(*ifi)) {
225: error("overflow allocting %u interfaces", nif);
226: goto exit;
227: }
228:
229: ifi = realloc(interfaces, len);
230: if (ifi == NULL) {
231: error("realloc: out of memory allocating %lld bytes",
232: (long long) len);
233: goto exit;
234: }
235:
236: interfaces = ifi;
237: num_ifs = nif;
238: }
239:
240: /* Fill in the "real" interfaces */
241: ifi = interfaces + 1;
242:
243: for (ifa = ifap; ifa != NULL; ifa = ifa->ifa_next) {
244: if (ifa->ifa_addr == NULL ||
245: ifa->ifa_addr->sa_family != AF_LINK)
246: continue;
247:
248: strlcpy(ifi->name, ifa->ifa_name, sizeof(ifi->name));
249:
250: if (ifa->ifa_data)
251: memcpy(&ifi->data, ifa->ifa_data, sizeof(ifi->data));
252: else
253: bzero(&ifi->data, sizeof(ifi->data));
254: ifi++;
255: }
256:
257: /* Fill in the "System" entry from pools */
258: bzero(interfaces, sizeof(interfaces[0]));
259: strlcpy(interfaces[0].name, "System", sizeof(interfaces[0].name));
1.18 canacar 260:
261: mib[0] = CTL_KERN;
1.19 canacar 262: mib[1] = KERN_POOL;
263: mib[2] = KERN_POOL_POOL;
264: mib[3] = mbpool_index;
265: size = sizeof(struct pool);
266:
267: if (sysctl(mib, 4, &mbpool, &size, NULL, 0) < 0) {
1.27 chl 268: error("sysctl(KERN_POOL_POOL, %d)", mib[3]);
1.19 canacar 269: goto exit;
270: }
271:
272: for (i = 0; i < mclpool_count; i++) {
273: struct mclpool *mp = &interfaces[0].data.ifi_mclpool[i];
274:
275: mib[3] = mclpools[i].pool_offset;
276: size = sizeof(struct pool);
1.18 canacar 277:
1.19 canacar 278: if (sysctl(mib, 4, &pool, &size, NULL, 0) < 0) {
279: error("sysctl(KERN_POOL_POOL, %d)", mib[3]);
280: continue;
281: }
282:
283: mp->mcl_alive = pool.pr_nget - pool.pr_nput;
284: mp->mcl_hwm = pool.pr_hiwat;
1.18 canacar 285: }
286:
1.19 canacar 287: num_disp = 1;
288: ret = 0;
1.18 canacar 289:
1.19 canacar 290: for (i = 0; i < num_ifs; i++) {
291: struct if_info *ifi = &interfaces[i];
292: int pnd = num_disp;
293: for (p = 0; p < mclpool_count; p++) {
294: struct mclpool *mp = &ifi->data.ifi_mclpool[p];
295: if (mp->mcl_alive == 0)
296: continue;
297: num_disp++;
298: }
299: if (i && pnd == num_disp)
300: num_disp++;
1.18 canacar 301: }
302:
1.19 canacar 303: exit:
304: freeifaddrs(ifap);
305: return (ret);
1.1 deraadt 306: }
307:
308: void
1.18 canacar 309: print_mb(void)
1.1 deraadt 310: {
1.19 canacar 311: int i, p, n, count = 0;
1.1 deraadt 312:
1.23 kettenis 313: showmbuf(interfaces, -1, 1);
1.19 canacar 314:
315: for (n = i = 0; i < num_ifs; i++) {
316: struct if_info *ifi = &interfaces[i];
317: int pcnt = count;
1.23 kettenis 318: int showif = i;
319:
1.18 canacar 320: if (maxprint > 0 && count >= maxprint)
1.19 canacar 321: return;
1.1 deraadt 322:
1.19 canacar 323: for (p = 0; p < mclpool_count; p++) {
324: struct mclpool *mp = &ifi->data.ifi_mclpool[p];
325: if (mp->mcl_alive == 0)
326: continue;
327: if (n++ >= dispstart) {
1.23 kettenis 328: showmbuf(ifi, p, showif);
329: showif = 0;
1.19 canacar 330: count++;
331: }
332: }
333:
334: if (i && pcnt == count) {
335: /* only print the first line */
336: if (n++ >= dispstart) {
1.23 kettenis 337: showmbuf(ifi, -1, 1);
1.19 canacar 338: count++;
339: }
340: }
1.1 deraadt 341:
1.5 ericj 342:
1.19 canacar 343: }
1.1 deraadt 344: }
345:
1.18 canacar 346:
347: static void
1.23 kettenis 348: showmbuf(struct if_info *ifi, int p, int showif)
1.1 deraadt 349: {
1.23 kettenis 350: if (showif)
1.19 canacar 351: print_fld_str(FLD_MB_IFACE, ifi->name);
352:
353: if (p == -1 && ifi == interfaces) {
1.30 ! dlg 354: print_fld_uint(FLD_MB_LLOCKS, mcllivelocks);
1.19 canacar 355: print_fld_size(FLD_MB_MSIZE, mbpool.pr_size);
356: print_fld_size(FLD_MB_MALIVE, mbpool.pr_nget - mbpool.pr_nput);
357: print_fld_size(FLD_MB_MHWM, mbpool.pr_hiwat);
358: }
359:
360: #if NOTYET
361: print_fld_uint(FLD_MB_RXDELAY, ifi->data.ifi_rxdelay);
362: print_fld_uint(FLD_MB_TXDELAY, ifi->data.ifi_txdelay);
1.29 dlg 363: #endif
1.19 canacar 364:
365: if (p >= 0 && p < mclpool_count) {
366: struct mclpool *mp = &ifi->data.ifi_mclpool[p];
367:
368: print_fld_str(FLD_MB_MSIZE, mclpools[p].title);
369: print_fld_uint(FLD_MB_MALIVE, mp->mcl_alive);
370: if (mp->mcl_lwm)
371: print_fld_size(FLD_MB_MLWM, mp->mcl_lwm);
372: if (mp->mcl_hwm)
373: print_fld_size(FLD_MB_MHWM, mp->mcl_hwm);
1.22 dlg 374: if (mp->mcl_cwm)
375: print_fld_size(FLD_MB_MCWM, mp->mcl_cwm);
1.19 canacar 376: }
1.18 canacar 377:
378: end_line();
1.1 deraadt 379: }