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