Annotation of src/usr.bin/systat/mbufs.c, Revision 1.40
1.40 ! jsg 1: /* $OpenBSD: mbufs.c,v 1.39 2015/01/20 18:26:57 deraadt 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/signal.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.35 dlg 24: #include <sys/sockio.h>
25: #include <sys/ioctl.h>
1.1 deraadt 26:
1.19 canacar 27: #include <err.h>
28: #include <errno.h>
29: #include <ifaddrs.h>
1.1 deraadt 30: #include <stdlib.h>
31: #include <string.h>
1.19 canacar 32:
1.1 deraadt 33: #include "systat.h"
1.18 canacar 34:
1.35 dlg 35: /* pool info */
36: int mbpool_index = -1;
37: int mclpools_index[MCLPOOLS];
1.19 canacar 38: int mclpool_count = 0;
1.34 dlg 39: struct kinfo_pool mbpool;
1.31 claudio 40: u_int mcllivelocks, mcllivelocks_cur, mcllivelocks_diff;
1.19 canacar 41:
42: /* interfaces */
1.35 dlg 43: static int num_ifs = 0;
1.19 canacar 44: struct if_info {
45: char name[16];
1.35 dlg 46: struct if_rxrinfo data;
1.19 canacar 47: } *interfaces = NULL;
48:
1.35 dlg 49: static int sock;
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:
1.19 canacar 56: /* Define fields */
57: field_def fields_mbuf[] = {
58: {"IFACE", 8, 16, 1, FLD_ALIGN_LEFT, -1, 0, 0, 0},
59: {"RXDELAY", 5, 8, 1, FLD_ALIGN_RIGHT, -1, 0, 0, 0},
60: {"TXDELAY", 5, 8, 1, FLD_ALIGN_RIGHT, -1, 0, 0, 0},
61: {"LIVELOCKS", 5, 10, 1, FLD_ALIGN_RIGHT, -1, 0, 0, 0},
62: {"SIZE", 3, 5, 1, FLD_ALIGN_RIGHT, -1, 0, 0, 0},
63: {"ALIVE", 3, 5, 1, FLD_ALIGN_RIGHT, -1, 0, 0, 0},
64: {"LWM", 3, 5, 1, FLD_ALIGN_RIGHT, -1, 0, 0, 0},
65: {"HWM", 3, 5, 1, FLD_ALIGN_RIGHT, -1, 0, 0, 0},
1.22 dlg 66: {"CWM", 3, 5, 1, FLD_ALIGN_RIGHT, -1, 0, 0, 0},
1.1 deraadt 67: };
68:
69:
1.32 jasper 70: #define FLD_MB_IFACE FIELD_ADDR(fields_mbuf,0)
71: #define FLD_MB_RXDELAY FIELD_ADDR(fields_mbuf,1)
72: #define FLD_MB_TXDELAY FIELD_ADDR(fields_mbuf,2)
73: #define FLD_MB_LLOCKS FIELD_ADDR(fields_mbuf,3)
74: #define FLD_MB_MSIZE FIELD_ADDR(fields_mbuf,4)
75: #define FLD_MB_MALIVE FIELD_ADDR(fields_mbuf,5)
76: #define FLD_MB_MLWM FIELD_ADDR(fields_mbuf,6)
77: #define FLD_MB_MHWM FIELD_ADDR(fields_mbuf,7)
78: #define FLD_MB_MCWM FIELD_ADDR(fields_mbuf,8)
1.18 canacar 79:
80:
81: /* Define views */
1.19 canacar 82: field_def *view_mbuf[] = {
83: FLD_MB_IFACE,
1.26 henning 84: FLD_MB_LLOCKS, FLD_MB_MSIZE, FLD_MB_MALIVE, FLD_MB_MLWM, FLD_MB_MHWM,
85: FLD_MB_MCWM, NULL
1.18 canacar 86: };
87:
1.19 canacar 88: /* Define view managers */
1.18 canacar 89:
90: struct view_manager mbuf_mgr = {
91: "Mbufs", select_mb, read_mb, NULL, print_header,
92: print_mb, keyboard_callback, NULL, NULL
93: };
94:
95: field_view views_mb[] = {
1.19 canacar 96: {view_mbuf, "mbufs", '4', &mbuf_mgr},
1.18 canacar 97: {NULL, NULL, 0, NULL}
98: };
99:
100:
101: int
1.19 canacar 102: initmembufs(void)
1.1 deraadt 103: {
1.35 dlg 104: struct if_rxring_info *ifr;
1.19 canacar 105: field_view *v;
106: int i, mib[4], npools;
1.34 dlg 107: struct kinfo_pool pool;
1.19 canacar 108: char pname[32];
109: size_t size;
110:
1.35 dlg 111: sock = socket(AF_INET, SOCK_DGRAM, 0);
112: if (sock == -1) {
113: err(1, "socket()");
114: /* NOTREACHED */
115: }
116:
117: /* set up the "System" interface */
118:
119: interfaces = calloc(1, sizeof(*interfaces));
120: if (interfaces == NULL)
121: err(1, "calloc: interfaces");
122:
123: ifr = calloc(MCLPOOLS, sizeof(*ifr));
124: if (ifr == NULL)
125: err(1, "calloc: system pools");
126:
127: strlcpy(interfaces[0].name, "System", sizeof(interfaces[0].name));
128: interfaces[0].data.ifri_total = MCLPOOLS;
129: interfaces[0].data.ifri_entries = ifr;
130: num_ifs = 1;
131:
1.19 canacar 132: /* go through all pools to identify mbuf and cluster pools */
1.18 canacar 133:
1.19 canacar 134: mib[0] = CTL_KERN;
135: mib[1] = KERN_POOL;
136: mib[2] = KERN_POOL_NPOOLS;
137: size = sizeof(npools);
138:
139: if (sysctl(mib, 3, &npools, &size, NULL, 0) < 0) {
140: err(1, "sysctl(KERN_POOL_NPOOLS)");
141: /* NOTREACHED */
142: }
143:
144: for (i = 1; i <= npools; i++) {
145: mib[0] = CTL_KERN;
146: mib[1] = KERN_POOL;
147: mib[2] = KERN_POOL_NAME;
148: mib[3] = i;
149: size = sizeof(pname);
150: if (sysctl(mib, 4, &pname, &size, NULL, 0) < 0) {
1.21 canacar 151: continue;
1.19 canacar 152: }
153:
1.37 dlg 154: if (strcmp(pname, "mbufpl") == 0) {
1.19 canacar 155: mbpool_index = i;
156: continue;
157: }
158:
159: if (strncmp(pname, "mcl", 3) != 0)
160: continue;
161:
162: if (mclpool_count == MCLPOOLS) {
1.24 chl 163: warnx("mbufs: Too many mcl* pools");
1.19 canacar 164: break;
165: }
166:
167: mib[2] = KERN_POOL_POOL;
1.34 dlg 168: size = sizeof(pool);
1.19 canacar 169:
170: if (sysctl(mib, 4, &pool, &size, NULL, 0) < 0) {
171: err(1, "sysctl(KERN_POOL_POOL, %d)", i);
172: /* NOTREACHED */
173: }
174:
1.35 dlg 175: snprintf(ifr[mclpool_count].ifr_name,
176: sizeof(ifr[mclpool_count].ifr_name), "%dk",
1.19 canacar 177: pool.pr_size / 1024);
1.35 dlg 178: ifr[mclpool_count].ifr_size = pool.pr_size;
1.19 canacar 179:
1.35 dlg 180: mclpools_index[mclpool_count++] = i;
1.19 canacar 181: }
182:
183: if (mclpool_count != MCLPOOLS)
184: warnx("mbufs: Unable to read all %d mcl* pools", MCLPOOLS);
185:
186: /* add view to the engine */
187: for (v = views_mb; v->name != NULL; v++)
188: add_view(v);
189:
190: /* finally read it once */
1.18 canacar 191: read_mb();
192:
1.19 canacar 193: return(1);
194: }
1.18 canacar 195:
1.19 canacar 196: int
197: select_mb(void)
198: {
199: num_disp = 0;
1.18 canacar 200: return (0);
1.1 deraadt 201: }
202:
1.18 canacar 203: int
204: read_mb(void)
1.1 deraadt 205: {
1.34 dlg 206: struct kinfo_pool pool;
1.40 ! jsg 207: struct ifaddrs *ifap = NULL, *ifa;
1.19 canacar 208: struct if_info *ifi;
1.35 dlg 209: struct if_rxring_info *ifr;
1.19 canacar 210: int mib[4];
1.35 dlg 211: int i, p, nif, ret = 1, rv;
212: u_int rings;
1.19 canacar 213: size_t size;
214:
1.30 dlg 215: mib[0] = CTL_KERN;
216: mib[1] = KERN_NETLIVELOCKS;
1.31 claudio 217: size = sizeof(mcllivelocks_cur);
218: if (sysctl(mib, 2, &mcllivelocks_cur, &size, NULL, 0) < 0 &&
1.30 dlg 219: errno != EOPNOTSUPP) {
220: error("sysctl(KERN_NETLIVELOCKS)");
221: goto exit;
222: }
1.31 claudio 223: mcllivelocks_diff = mcllivelocks_cur - mcllivelocks;
224: mcllivelocks = mcllivelocks_cur;
1.30 dlg 225:
1.19 canacar 226: num_disp = 0;
227: if (getifaddrs(&ifap)) {
228: error("getifaddrs: %s", strerror(errno));
229: return (1);
230: }
231:
232: nif = 1;
1.35 dlg 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: nif++;
239: }
1.19 canacar 240:
1.35 dlg 241: if (num_ifs < nif) {
242: ifi = reallocarray(interfaces, nif, sizeof(*interfaces));
1.19 canacar 243: if (ifi == NULL) {
1.35 dlg 244: error("reallocarray: %d interfaces", nif);
1.19 canacar 245: goto exit;
246: }
247:
248: interfaces = ifi;
1.35 dlg 249: while (num_ifs < nif)
250: memset(&interfaces[num_ifs++], 0, sizeof(*interfaces));
1.19 canacar 251: }
252:
253: /* Fill in the "real" interfaces */
254: ifi = interfaces + 1;
255:
256: for (ifa = ifap; ifa != NULL; ifa = ifa->ifa_next) {
257: if (ifa->ifa_addr == NULL ||
258: ifa->ifa_addr->sa_family != AF_LINK)
259: continue;
260:
261: strlcpy(ifi->name, ifa->ifa_name, sizeof(ifi->name));
1.35 dlg 262: for (;;) {
263: struct ifreq ifreq;
264: rings = ifi->data.ifri_total;
265:
266: memset(&ifreq, 0, sizeof(ifreq));
267: strlcpy(ifreq.ifr_name, ifa->ifa_name,
268: sizeof(ifreq.ifr_name));
269: ifreq.ifr_data = (caddr_t)&ifi->data;
270:
271: rv = ioctl(sock, SIOCGIFRXR, &ifreq);
272: if (rv == -1) {
273: if (errno == ENOTTY) {
274: free(ifi->data.ifri_entries);
275: ifi->data.ifri_total = 0;
276: ifi->data.ifri_entries = NULL;
277: break;
278: }
279:
280: error("ioctl(SIOCGIFRXR) %s", strerror(errno));
281: break;
282: }
283:
284: if (rings >= ifi->data.ifri_total)
285: break;
286:
287: ifr = reallocarray(ifi->data.ifri_entries,
288: ifi->data.ifri_total, sizeof(*ifr));
289: if (ifr == NULL) {
290: ifi->data.ifri_total = rings;
291: error("reallocarray: %u rings",
292: ifi->data.ifri_total);
293: goto exit;
294: }
295:
296: ifi->data.ifri_entries = ifr;
297: }
1.19 canacar 298:
299: ifi++;
300: }
301:
302: /* Fill in the "System" entry from pools */
1.18 canacar 303:
304: mib[0] = CTL_KERN;
1.19 canacar 305: mib[1] = KERN_POOL;
306: mib[2] = KERN_POOL_POOL;
307: mib[3] = mbpool_index;
1.34 dlg 308: size = sizeof(mbpool);
1.19 canacar 309:
310: if (sysctl(mib, 4, &mbpool, &size, NULL, 0) < 0) {
1.27 chl 311: error("sysctl(KERN_POOL_POOL, %d)", mib[3]);
1.19 canacar 312: goto exit;
313: }
314:
315: for (i = 0; i < mclpool_count; i++) {
1.35 dlg 316: ifr = &interfaces[0].data.ifri_entries[i];
1.19 canacar 317:
1.35 dlg 318: mib[3] = mclpools_index[i];
1.34 dlg 319: size = sizeof(pool);
1.18 canacar 320:
1.19 canacar 321: if (sysctl(mib, 4, &pool, &size, NULL, 0) < 0) {
322: error("sysctl(KERN_POOL_POOL, %d)", mib[3]);
323: continue;
324: }
325:
1.35 dlg 326: ifr->ifr_info.rxr_alive = pool.pr_nget - pool.pr_nput;
327: ifr->ifr_info.rxr_hwm = pool.pr_hiwat;
1.18 canacar 328: }
329:
1.19 canacar 330: num_disp = 1;
331: ret = 0;
1.18 canacar 332:
1.19 canacar 333: for (i = 0; i < num_ifs; i++) {
334: struct if_info *ifi = &interfaces[i];
335: int pnd = num_disp;
1.35 dlg 336: for (p = 0; p < ifi->data.ifri_total; p++) {
337: ifr = &ifi->data.ifri_entries[p];
1.36 jsg 338: if (ifr->ifr_info.rxr_alive == 0)
1.19 canacar 339: continue;
340: num_disp++;
341: }
342: if (i && pnd == num_disp)
343: num_disp++;
1.18 canacar 344: }
345:
1.19 canacar 346: exit:
1.40 ! jsg 347: if (ifap)
! 348: freeifaddrs(ifap);
1.19 canacar 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: }