Annotation of src/usr.bin/systat/mbufs.c, Revision 1.38
1.38 ! deraadt 1: /* $OpenBSD: mbufs.c,v 1.37 2014/11/06 12:50: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: */
1.38 ! deraadt 17:
! 18: #include <sys/param.h> /* MSIZE */
! 19: #include <sys/signal.h>
1.19 canacar 20: #include <sys/socket.h>
21: #include <sys/sysctl.h>
1.1 deraadt 22: #include <sys/mbuf.h>
1.28 blambert 23: #include <sys/pool.h>
1.19 canacar 24: #include <net/if.h>
1.35 dlg 25: #include <sys/sockio.h>
26: #include <sys/ioctl.h>
1.1 deraadt 27:
1.19 canacar 28: #include <err.h>
29: #include <errno.h>
30: #include <ifaddrs.h>
1.1 deraadt 31: #include <stdlib.h>
32: #include <string.h>
1.19 canacar 33:
1.1 deraadt 34: #include "systat.h"
1.18 canacar 35:
1.35 dlg 36: /* pool info */
37: int mbpool_index = -1;
38: int mclpools_index[MCLPOOLS];
1.19 canacar 39: int mclpool_count = 0;
1.34 dlg 40: struct kinfo_pool mbpool;
1.31 claudio 41: u_int mcllivelocks, mcllivelocks_cur, mcllivelocks_diff;
1.19 canacar 42:
43: /* interfaces */
1.35 dlg 44: static int num_ifs = 0;
1.19 canacar 45: struct if_info {
46: char name[16];
1.35 dlg 47: struct if_rxrinfo data;
1.19 canacar 48: } *interfaces = NULL;
49:
1.35 dlg 50: static int sock;
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:
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.32 jasper 71: #define FLD_MB_IFACE FIELD_ADDR(fields_mbuf,0)
72: #define FLD_MB_RXDELAY FIELD_ADDR(fields_mbuf,1)
73: #define FLD_MB_TXDELAY FIELD_ADDR(fields_mbuf,2)
74: #define FLD_MB_LLOCKS FIELD_ADDR(fields_mbuf,3)
75: #define FLD_MB_MSIZE FIELD_ADDR(fields_mbuf,4)
76: #define FLD_MB_MALIVE FIELD_ADDR(fields_mbuf,5)
77: #define FLD_MB_MLWM FIELD_ADDR(fields_mbuf,6)
78: #define FLD_MB_MHWM FIELD_ADDR(fields_mbuf,7)
79: #define FLD_MB_MCWM FIELD_ADDR(fields_mbuf,8)
1.18 canacar 80:
81:
82: /* Define views */
1.19 canacar 83: field_def *view_mbuf[] = {
84: FLD_MB_IFACE,
1.26 henning 85: FLD_MB_LLOCKS, FLD_MB_MSIZE, FLD_MB_MALIVE, FLD_MB_MLWM, FLD_MB_MHWM,
86: FLD_MB_MCWM, NULL
1.18 canacar 87: };
88:
1.19 canacar 89: /* Define view managers */
1.18 canacar 90:
91: struct view_manager mbuf_mgr = {
92: "Mbufs", select_mb, read_mb, NULL, print_header,
93: print_mb, keyboard_callback, NULL, NULL
94: };
95:
96: field_view views_mb[] = {
1.19 canacar 97: {view_mbuf, "mbufs", '4', &mbuf_mgr},
1.18 canacar 98: {NULL, NULL, 0, NULL}
99: };
100:
101:
102: int
1.19 canacar 103: initmembufs(void)
1.1 deraadt 104: {
1.35 dlg 105: struct if_rxring_info *ifr;
1.19 canacar 106: field_view *v;
107: int i, mib[4], npools;
1.34 dlg 108: struct kinfo_pool pool;
1.19 canacar 109: char pname[32];
110: size_t size;
111:
1.35 dlg 112: sock = socket(AF_INET, SOCK_DGRAM, 0);
113: if (sock == -1) {
114: err(1, "socket()");
115: /* NOTREACHED */
116: }
117:
118: /* set up the "System" interface */
119:
120: interfaces = calloc(1, sizeof(*interfaces));
121: if (interfaces == NULL)
122: err(1, "calloc: interfaces");
123:
124: ifr = calloc(MCLPOOLS, sizeof(*ifr));
125: if (ifr == NULL)
126: err(1, "calloc: system pools");
127:
128: strlcpy(interfaces[0].name, "System", sizeof(interfaces[0].name));
129: interfaces[0].data.ifri_total = MCLPOOLS;
130: interfaces[0].data.ifri_entries = ifr;
131: num_ifs = 1;
132:
1.19 canacar 133: /* go through all pools to identify mbuf and cluster pools */
1.18 canacar 134:
1.19 canacar 135: mib[0] = CTL_KERN;
136: mib[1] = KERN_POOL;
137: mib[2] = KERN_POOL_NPOOLS;
138: size = sizeof(npools);
139:
140: if (sysctl(mib, 3, &npools, &size, NULL, 0) < 0) {
141: err(1, "sysctl(KERN_POOL_NPOOLS)");
142: /* NOTREACHED */
143: }
144:
145: for (i = 1; i <= npools; i++) {
146: mib[0] = CTL_KERN;
147: mib[1] = KERN_POOL;
148: mib[2] = KERN_POOL_NAME;
149: mib[3] = i;
150: size = sizeof(pname);
151: if (sysctl(mib, 4, &pname, &size, NULL, 0) < 0) {
1.21 canacar 152: continue;
1.19 canacar 153: }
154:
1.37 dlg 155: if (strcmp(pname, "mbufpl") == 0) {
1.19 canacar 156: mbpool_index = i;
157: continue;
158: }
159:
160: if (strncmp(pname, "mcl", 3) != 0)
161: continue;
162:
163: if (mclpool_count == MCLPOOLS) {
1.24 chl 164: warnx("mbufs: Too many mcl* pools");
1.19 canacar 165: break;
166: }
167:
168: mib[2] = KERN_POOL_POOL;
1.34 dlg 169: size = sizeof(pool);
1.19 canacar 170:
171: if (sysctl(mib, 4, &pool, &size, NULL, 0) < 0) {
172: err(1, "sysctl(KERN_POOL_POOL, %d)", i);
173: /* NOTREACHED */
174: }
175:
1.35 dlg 176: snprintf(ifr[mclpool_count].ifr_name,
177: sizeof(ifr[mclpool_count].ifr_name), "%dk",
1.19 canacar 178: pool.pr_size / 1024);
1.35 dlg 179: ifr[mclpool_count].ifr_size = pool.pr_size;
1.19 canacar 180:
1.35 dlg 181: mclpools_index[mclpool_count++] = i;
1.19 canacar 182: }
183:
184: if (mclpool_count != MCLPOOLS)
185: warnx("mbufs: Unable to read all %d mcl* pools", MCLPOOLS);
186:
187: /* add view to the engine */
188: for (v = views_mb; v->name != NULL; v++)
189: add_view(v);
190:
191: /* finally read it once */
1.18 canacar 192: read_mb();
193:
1.19 canacar 194: return(1);
195: }
1.18 canacar 196:
1.19 canacar 197: int
198: select_mb(void)
199: {
200: num_disp = 0;
1.18 canacar 201: return (0);
1.1 deraadt 202: }
203:
1.18 canacar 204: int
205: read_mb(void)
1.1 deraadt 206: {
1.34 dlg 207: struct kinfo_pool pool;
1.19 canacar 208: struct ifaddrs *ifap, *ifa;
209: struct if_info *ifi;
1.35 dlg 210: struct if_rxring_info *ifr;
1.19 canacar 211: int mib[4];
1.35 dlg 212: int i, p, nif, ret = 1, rv;
213: u_int rings;
1.19 canacar 214: size_t size;
215:
1.30 dlg 216: mib[0] = CTL_KERN;
217: mib[1] = KERN_NETLIVELOCKS;
1.31 claudio 218: size = sizeof(mcllivelocks_cur);
219: if (sysctl(mib, 2, &mcllivelocks_cur, &size, NULL, 0) < 0 &&
1.30 dlg 220: errno != EOPNOTSUPP) {
221: error("sysctl(KERN_NETLIVELOCKS)");
222: goto exit;
223: }
1.31 claudio 224: mcllivelocks_diff = mcllivelocks_cur - mcllivelocks;
225: mcllivelocks = mcllivelocks_cur;
1.30 dlg 226:
1.19 canacar 227: num_disp = 0;
228: if (getifaddrs(&ifap)) {
229: error("getifaddrs: %s", strerror(errno));
230: return (1);
231: }
232:
233: nif = 1;
1.35 dlg 234: for (ifa = ifap; ifa != NULL; ifa = ifa->ifa_next) {
235: if (ifa->ifa_addr == NULL ||
236: ifa->ifa_addr->sa_family != AF_LINK)
237: continue;
238:
239: nif++;
240: }
1.19 canacar 241:
1.35 dlg 242: if (num_ifs < nif) {
243: ifi = reallocarray(interfaces, nif, sizeof(*interfaces));
1.19 canacar 244: if (ifi == NULL) {
1.35 dlg 245: error("reallocarray: %d interfaces", nif);
1.19 canacar 246: goto exit;
247: }
248:
249: interfaces = ifi;
1.35 dlg 250: while (num_ifs < nif)
251: memset(&interfaces[num_ifs++], 0, sizeof(*interfaces));
1.19 canacar 252: }
253:
254: /* Fill in the "real" interfaces */
255: ifi = interfaces + 1;
256:
257: for (ifa = ifap; ifa != NULL; ifa = ifa->ifa_next) {
258: if (ifa->ifa_addr == NULL ||
259: ifa->ifa_addr->sa_family != AF_LINK)
260: continue;
261:
262: strlcpy(ifi->name, ifa->ifa_name, sizeof(ifi->name));
1.35 dlg 263: for (;;) {
264: struct ifreq ifreq;
265: rings = ifi->data.ifri_total;
266:
267: memset(&ifreq, 0, sizeof(ifreq));
268: strlcpy(ifreq.ifr_name, ifa->ifa_name,
269: sizeof(ifreq.ifr_name));
270: ifreq.ifr_data = (caddr_t)&ifi->data;
271:
272: rv = ioctl(sock, SIOCGIFRXR, &ifreq);
273: if (rv == -1) {
274: if (errno == ENOTTY) {
275: free(ifi->data.ifri_entries);
276: ifi->data.ifri_total = 0;
277: ifi->data.ifri_entries = NULL;
278: break;
279: }
280:
281: error("ioctl(SIOCGIFRXR) %s", strerror(errno));
282: break;
283: }
284:
285: if (rings >= ifi->data.ifri_total)
286: break;
287:
288: ifr = reallocarray(ifi->data.ifri_entries,
289: ifi->data.ifri_total, sizeof(*ifr));
290: if (ifr == NULL) {
291: ifi->data.ifri_total = rings;
292: error("reallocarray: %u rings",
293: ifi->data.ifri_total);
294: goto exit;
295: }
296:
297: ifi->data.ifri_entries = ifr;
298: }
1.19 canacar 299:
300: ifi++;
301: }
302:
303: /* Fill in the "System" entry from pools */
1.18 canacar 304:
305: mib[0] = CTL_KERN;
1.19 canacar 306: mib[1] = KERN_POOL;
307: mib[2] = KERN_POOL_POOL;
308: mib[3] = mbpool_index;
1.34 dlg 309: size = sizeof(mbpool);
1.19 canacar 310:
311: if (sysctl(mib, 4, &mbpool, &size, NULL, 0) < 0) {
1.27 chl 312: error("sysctl(KERN_POOL_POOL, %d)", mib[3]);
1.19 canacar 313: goto exit;
314: }
315:
316: for (i = 0; i < mclpool_count; i++) {
1.35 dlg 317: ifr = &interfaces[0].data.ifri_entries[i];
1.19 canacar 318:
1.35 dlg 319: mib[3] = mclpools_index[i];
1.34 dlg 320: size = sizeof(pool);
1.18 canacar 321:
1.19 canacar 322: if (sysctl(mib, 4, &pool, &size, NULL, 0) < 0) {
323: error("sysctl(KERN_POOL_POOL, %d)", mib[3]);
324: continue;
325: }
326:
1.35 dlg 327: ifr->ifr_info.rxr_alive = pool.pr_nget - pool.pr_nput;
328: ifr->ifr_info.rxr_hwm = pool.pr_hiwat;
1.18 canacar 329: }
330:
1.19 canacar 331: num_disp = 1;
332: ret = 0;
1.18 canacar 333:
1.19 canacar 334: for (i = 0; i < num_ifs; i++) {
335: struct if_info *ifi = &interfaces[i];
336: int pnd = num_disp;
1.35 dlg 337: for (p = 0; p < ifi->data.ifri_total; p++) {
338: ifr = &ifi->data.ifri_entries[p];
1.36 jsg 339: if (ifr->ifr_info.rxr_alive == 0)
1.19 canacar 340: continue;
341: num_disp++;
342: }
343: if (i && pnd == num_disp)
344: num_disp++;
1.18 canacar 345: }
346:
1.19 canacar 347: exit:
348: freeifaddrs(ifap);
349: return (ret);
1.1 deraadt 350: }
351:
352: void
1.18 canacar 353: print_mb(void)
1.1 deraadt 354: {
1.19 canacar 355: int i, p, n, count = 0;
1.1 deraadt 356:
1.23 kettenis 357: showmbuf(interfaces, -1, 1);
1.19 canacar 358:
359: for (n = i = 0; i < num_ifs; i++) {
360: struct if_info *ifi = &interfaces[i];
361: int pcnt = count;
1.23 kettenis 362: int showif = i;
363:
1.18 canacar 364: if (maxprint > 0 && count >= maxprint)
1.19 canacar 365: return;
1.1 deraadt 366:
1.35 dlg 367: for (p = 0; p < ifi->data.ifri_total; p++) {
368: struct if_rxring_info *ifr = &ifi->data.ifri_entries[p];
369: if (ifr->ifr_info.rxr_alive == 0)
1.19 canacar 370: continue;
371: if (n++ >= dispstart) {
1.23 kettenis 372: showmbuf(ifi, p, showif);
373: showif = 0;
1.19 canacar 374: count++;
375: }
376: }
377:
378: if (i && pcnt == count) {
379: /* only print the first line */
380: if (n++ >= dispstart) {
1.23 kettenis 381: showmbuf(ifi, -1, 1);
1.19 canacar 382: count++;
383: }
384: }
385: }
1.1 deraadt 386: }
387:
1.18 canacar 388:
389: static void
1.23 kettenis 390: showmbuf(struct if_info *ifi, int p, int showif)
1.1 deraadt 391: {
1.23 kettenis 392: if (showif)
1.19 canacar 393: print_fld_str(FLD_MB_IFACE, ifi->name);
394:
395: if (p == -1 && ifi == interfaces) {
1.31 claudio 396: print_fld_uint(FLD_MB_LLOCKS, mcllivelocks_diff);
1.19 canacar 397: print_fld_size(FLD_MB_MSIZE, mbpool.pr_size);
398: print_fld_size(FLD_MB_MALIVE, mbpool.pr_nget - mbpool.pr_nput);
399: print_fld_size(FLD_MB_MHWM, mbpool.pr_hiwat);
400: }
401:
402: if (p >= 0 && p < mclpool_count) {
1.35 dlg 403: struct if_rxring_info *ifr = &ifi->data.ifri_entries[p];
404: struct if_rxring *rxr= &ifr->ifr_info;
405: print_fld_uint(FLD_MB_MSIZE, ifr->ifr_size);
406: print_fld_uint(FLD_MB_MALIVE, rxr->rxr_alive);
407: if (rxr->rxr_lwm)
408: print_fld_size(FLD_MB_MLWM, rxr->rxr_lwm);
409: if (rxr->rxr_hwm)
410: print_fld_size(FLD_MB_MHWM, rxr->rxr_hwm);
411: if (rxr->rxr_cwm)
412: print_fld_size(FLD_MB_MCWM, rxr->rxr_cwm);
1.19 canacar 413: }
1.18 canacar 414:
415: end_line();
1.1 deraadt 416: }