=================================================================== RCS file: /cvsrepo/anoncvs/cvs/src/usr.bin/systat/mbufs.c,v retrieving revision 1.18 retrieving revision 1.19 diff -u -r1.18 -r1.19 --- src/usr.bin/systat/mbufs.c 2008/06/12 22:26:01 1.18 +++ src/usr.bin/systat/mbufs.c 2008/12/17 08:21:43 1.19 @@ -1,191 +1,375 @@ -/* $OpenBSD: mbufs.c,v 1.18 2008/06/12 22:26:01 canacar Exp $ */ -/* $NetBSD: mbufs.c,v 1.2 1995/01/20 08:52:02 jtc Exp $ */ - -/*- - * Copyright (c) 1980, 1992, 1993 - * The Regents of the University of California. All rights reserved. +/* $OpenBSD: mbufs.c,v 1.19 2008/12/17 08:21:43 canacar Exp $ */ +/* + * Copyright (c) 2008 Can Erkin Acar * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ - #include #include -#include +#include #include +#include +#include +#include +#include +#include #include #include -#include -#include + #include "systat.h" +/* pool info for mcl* pools */ +struct mclpool_info { + char title[16]; + int pool_offset; + int size; +} mclpools[MCLPOOLS]; + +int mclpool_count = 0; +int mbpool_index = -1; +struct pool mbpool; + +/* interfaces */ +static int num_ifs; +struct if_info { + char name[16]; + struct if_data data; +} *interfaces = NULL; + void print_mb(void); int read_mb(void); int select_mb(void); -static void showmbuf(int); +static void +showmbuf(struct if_info *, int); -static struct mbstat mb; -char *mtnames[] = { - "free", - "data", - "headers", - "sockets", - "pcbs", - "routes", - "hosts", - "arps", - "socknames", - "zombies", - "sockopts", - "frags", - "rights", - "ifaddrs", +/* Define fields */ +field_def fields_mbuf[] = { + {"IFACE", 8, 16, 1, FLD_ALIGN_LEFT, -1, 0, 0, 0}, + {"RXDELAY", 5, 8, 1, FLD_ALIGN_RIGHT, -1, 0, 0, 0}, + {"TXDELAY", 5, 8, 1, FLD_ALIGN_RIGHT, -1, 0, 0, 0}, + {"LIVELOCKS", 5, 10, 1, FLD_ALIGN_RIGHT, -1, 0, 0, 0}, + {"SIZE", 3, 5, 1, FLD_ALIGN_RIGHT, -1, 0, 0, 0}, + {"ALIVE", 3, 5, 1, FLD_ALIGN_RIGHT, -1, 0, 0, 0}, + {"LWM", 3, 5, 1, FLD_ALIGN_RIGHT, -1, 0, 0, 0}, + {"HWM", 3, 5, 1, FLD_ALIGN_RIGHT, -1, 0, 0, 0}, }; -#define NUM_TYPES (sizeof(mb.m_mtypes) / sizeof(mb.m_mtypes[0])) -#define NNAMES (sizeof (mtnames) / sizeof (mtnames[0])) -int mb_index[NUM_TYPES]; -int mbuf_cnt = 0; +#define FIELD_ADDR(x) (&fields_mbuf[x]) +#define FLD_MB_IFACE FIELD_ADDR(0) +#define FLD_MB_RXDELAY FIELD_ADDR(1) +#define FLD_MB_TXDELAY FIELD_ADDR(2) +#define FLD_MB_LLOCKS FIELD_ADDR(3) +#define FLD_MB_MSIZE FIELD_ADDR(4) +#define FLD_MB_MALIVE FIELD_ADDR(5) +#define FLD_MB_MLWM FIELD_ADDR(6) +#define FLD_MB_MHWM FIELD_ADDR(7) -field_def fields_mb[] = { - {"TYPE", 6, 16, 1, FLD_ALIGN_RIGHT, -1, 0, 0, 0}, - {"VALUE", 5, 8, 1, FLD_ALIGN_RIGHT, -1, 0, 0, 0}, - {"", 40, 80, 1, FLD_ALIGN_BAR, -1, 0, 0, 60}, -}; -#define FIELD_ADDR(x) (&fields_mb[x]) - -#define FLD_MB_NAME FIELD_ADDR(0) -#define FLD_MB_VALUE FIELD_ADDR(1) -#define FLD_MB_BAR FIELD_ADDR(2) - /* Define views */ -field_def *view_mb_0[] = { - FLD_MB_NAME, FLD_MB_VALUE, FLD_MB_BAR, NULL +field_def *view_mbuf[] = { + FLD_MB_IFACE, +#if NOTYET + FLD_MB_RXDELAY, FLD_MB_TXDELAY, +#endif + FLD_MB_LLOCKS, FLD_MB_MSIZE, FLD_MB_MALIVE, FLD_MB_MLWM, FLD_MB_MHWM, + NULL }; - /* Define view managers */ + struct view_manager mbuf_mgr = { "Mbufs", select_mb, read_mb, NULL, print_header, print_mb, keyboard_callback, NULL, NULL }; field_view views_mb[] = { - {view_mb_0, "mbufs", '4', &mbuf_mgr}, + {view_mbuf, "mbufs", '4', &mbuf_mgr}, {NULL, NULL, 0, NULL} }; int -select_mb(void) +initmembufs(void) { - int i, w = 50; + field_view *v; + int i, mib[4], npools; + struct pool pool; + char pname[32]; + size_t size; + /* go through all pools to identify mbuf and cluster pools */ + bzero(mclpools, sizeof(mclpools)); + + mib[0] = CTL_KERN; + mib[1] = KERN_POOL; + mib[2] = KERN_POOL_NPOOLS; + size = sizeof(npools); + + if (sysctl(mib, 3, &npools, &size, NULL, 0) < 0) { + err(1, "sysctl(KERN_POOL_NPOOLS)"); + /* NOTREACHED */ + } + + for (i = 1; i <= npools; i++) { + mib[0] = CTL_KERN; + mib[1] = KERN_POOL; + mib[2] = KERN_POOL_NAME; + mib[3] = i; + size = sizeof(pname); + if (sysctl(mib, 4, &pname, &size, NULL, 0) < 0) { + err(1, "sysctl(KERN_POOL_POOLNAME, %d)", i); + /* NOTREACHED */ + } + + if (strcmp(pname, "mbpl") == 0) { + mbpool_index = i; + continue; + } + + if (strncmp(pname, "mcl", 3) != 0) + continue; + + if (mclpool_count == MCLPOOLS) { + warnx("mbufs: Too many mcl* pools", i); + break; + } + + mib[2] = KERN_POOL_POOL; + size = sizeof(struct pool); + + if (sysctl(mib, 4, &pool, &size, NULL, 0) < 0) { + err(1, "sysctl(KERN_POOL_POOL, %d)", i); + /* NOTREACHED */ + } + + mclpools[mclpool_count].size = pool.pr_size; + mclpools[mclpool_count].pool_offset = i; + snprintf(mclpools[mclpool_count].title, + sizeof(mclpools[0].title), "%dk", + pool.pr_size / 1024); + + mclpool_count++; + } + + if (mclpool_count != MCLPOOLS) + warnx("mbufs: Unable to read all %d mcl* pools", MCLPOOLS); + + /* add view to the engine */ + for (v = views_mb; v->name != NULL; v++) + add_view(v); + + + /* finally read it once */ read_mb(); - for (i = 0; i < NUM_TYPES; i++) - if (w < (5 * mb.m_mtypes[i] / 4)) - w = 5 * mb.m_mtypes[i] / 4; - w -= w % 10; - FLD_MB_BAR->arg = w; + return(1); +} +int +select_mb(void) +{ + num_disp = 0; return (0); } int read_mb(void) { - int mib[2], i; - size_t size = sizeof (mb); + struct pool pool; + struct ifaddrs *ifap, *ifa; + struct if_info *ifi; + int mib[4]; + int i, p, nif, ret = 1; + size_t size; + num_disp = 0; + if (getifaddrs(&ifap)) { + error("getifaddrs: %s", strerror(errno)); + return (1); + } + + nif = 1; + for (ifa = ifap; ifa != NULL; ifa = ifa->ifa_next) + if (ifa->ifa_addr && ifa->ifa_addr->sa_family == AF_LINK) + nif++; + + if (interfaces == NULL || num_ifs < nif) { + size_t len = sizeof(*ifi) * nif; + if (nif > SIZE_MAX / sizeof(*ifi)) { + error("overflow allocting %u interfaces", nif); + goto exit; + } + + ifi = realloc(interfaces, len); + if (ifi == NULL) { + error("realloc: out of memory allocating %lld bytes", + (long long) len); + goto exit; + } + + interfaces = ifi; + num_ifs = nif; + } + + /* Fill in the "real" interfaces */ + ifi = interfaces + 1; + + for (ifa = ifap; ifa != NULL; ifa = ifa->ifa_next) { + if (ifa->ifa_addr == NULL || + ifa->ifa_addr->sa_family != AF_LINK) + continue; + + strlcpy(ifi->name, ifa->ifa_name, sizeof(ifi->name)); + + if (ifa->ifa_data) + memcpy(&ifi->data, ifa->ifa_data, sizeof(ifi->data)); + else + bzero(&ifi->data, sizeof(ifi->data)); + ifi++; + } + + /* Fill in the "System" entry from pools */ + bzero(interfaces, sizeof(interfaces[0])); + strlcpy(interfaces[0].name, "System", sizeof(interfaces[0].name)); + mib[0] = CTL_KERN; - mib[1] = KERN_MBSTAT; + mib[1] = KERN_POOL; + mib[2] = KERN_POOL_POOL; + mib[3] = mbpool_index; + size = sizeof(struct pool); - if (sysctl(mib, 2, &mb, &size, NULL, 0) < 0) { - error("sysctl(KERN_MBSTAT) failed"); - return 1; + if (sysctl(mib, 4, &mbpool, &size, NULL, 0) < 0) { + error("sysctl(KERN_POOL_POOL, %d)", i); + goto exit; } - mbuf_cnt = 0; - memset(mb_index, 0, sizeof(mb_index)); + for (i = 0; i < mclpool_count; i++) { + struct mclpool *mp = &interfaces[0].data.ifi_mclpool[i]; - for (i = 0; i < NUM_TYPES; i++) { - if (mb.m_mtypes[i]) - mb_index[mbuf_cnt++] = i; + mib[3] = mclpools[i].pool_offset; + size = sizeof(struct pool); + + if (sysctl(mib, 4, &pool, &size, NULL, 0) < 0) { + error("sysctl(KERN_POOL_POOL, %d)", mib[3]); + continue; + } + + mp->mcl_size = pool.pr_size; + mp->mcl_alive = pool.pr_nget - pool.pr_nput; + mp->mcl_hwm = pool.pr_hiwat; } - num_disp = mbuf_cnt; + num_disp = 1; + ret = 0; - return 0; + for (i = 0; i < num_ifs; i++) { + struct if_info *ifi = &interfaces[i]; + int pnd = num_disp; + for (p = 0; p < mclpool_count; p++) { + struct mclpool *mp = &ifi->data.ifi_mclpool[p]; + if (mp->mcl_size != (ushort)mclpools[p].size) + break; + if (mp->mcl_alive == 0) + continue; + num_disp++; + } + if (i && pnd == num_disp) + num_disp++; + } + + exit: + freeifaddrs(ifap); + return (ret); } - void print_mb(void) { - int n, count = 0; + int i, p, n, count = 0; - for (n = dispstart; n < num_disp; n++) { - showmbuf(n); - count++; + showmbuf(interfaces, -1); + + for (n = i = 0; i < num_ifs; i++) { + struct if_info *ifi = &interfaces[i]; + int pcnt = count; if (maxprint > 0 && count >= maxprint) - break; - } -} + return; -int -initmembufs(void) -{ - field_view *v; + for (p = 0; p < mclpool_count; p++) { + struct mclpool *mp = &ifi->data.ifi_mclpool[p]; + if (mp->mcl_size != (ushort)mclpools[p].size) + break; + if (mp->mcl_alive == 0) + continue; + if (n++ >= dispstart) { + showmbuf(ifi, p); + count++; + } + } - for (v = views_mb; v->name != NULL; v++) - add_view(v); + if (i && pcnt == count) { + /* only print the first line */ + if (n++ >= dispstart) { + showmbuf(ifi, -1); + count++; + } + } - return(1); + + } } static void -showmbuf(int m) +showmbuf(struct if_info *ifi, int p) { int i; - i = mb_index[m]; - if (i < NNAMES) - print_fld_str(FLD_MB_NAME, mtnames[i]); - else - print_fld_uint(FLD_MB_NAME, i); - print_fld_uint(FLD_MB_VALUE, mb.m_mtypes[i]); - print_fld_bar(FLD_MB_BAR, mb.m_mtypes[i]); + if (p == -1 || (p == 0 && ifi != interfaces)) { + print_fld_str(FLD_MB_IFACE, ifi->name); + } + + if (p == -1 && ifi == interfaces) { + print_fld_size(FLD_MB_MSIZE, mbpool.pr_size); + print_fld_size(FLD_MB_MALIVE, mbpool.pr_nget - mbpool.pr_nput); + print_fld_size(FLD_MB_MHWM, mbpool.pr_hiwat); + } + + + +#if NOTYET + print_fld_uint(FLD_MB_RXDELAY, ifi->data.ifi_rxdelay); + print_fld_uint(FLD_MB_TXDELAY, ifi->data.ifi_txdelay); + print_fld_size(FLD_MB_LLOCKS, ifi->data.ifi_txdelay); +#endif + + if (p >= 0 && p < mclpool_count) { + struct mclpool *mp = &ifi->data.ifi_mclpool[p]; + + print_fld_str(FLD_MB_MSIZE, mclpools[p].title); + print_fld_uint(FLD_MB_MALIVE, mp->mcl_alive); + if (mp->mcl_lwm) + print_fld_size(FLD_MB_MLWM, mp->mcl_lwm); + if (mp->mcl_hwm) + print_fld_size(FLD_MB_MHWM, mp->mcl_hwm); + } end_line(); }