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