[BACK]Return to mbufs.c CVS log [TXT][DIR] Up to [local] / src / usr.bin / systat

Annotation of src/usr.bin/systat/mbufs.c, Revision 1.42

1.42    ! deraadt     1: /*     $OpenBSD: mbufs.c,v 1.41 2016/04/04 16:26:00 sthen 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.41      sthen      21: #include <sys/queue.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:
1.42    ! deraadt   140:        if (sysctl(mib, 3, &npools, &size, NULL, 0) == -1) {
1.19      canacar   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);
1.42    ! deraadt   151:                if (sysctl(mib, 4, &pname, &size, NULL, 0) == -1) {
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:
1.42    ! deraadt   171:                if (sysctl(mib, 4, &pool, &size, NULL, 0) == -1) {
1.19      canacar   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.40      jsg       208:        struct ifaddrs *ifap = NULL, *ifa;
1.19      canacar   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);
1.42    ! deraadt   219:        if (sysctl(mib, 2, &mcllivelocks_cur, &size, NULL, 0) == -1 &&
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:
1.42    ! deraadt   311:        if (sysctl(mib, 4, &mbpool, &size, NULL, 0) == -1) {
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.42    ! deraadt   322:                if (sysctl(mib, 4, &pool, &size, NULL, 0) == -1) {
1.19      canacar   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:
1.40      jsg       348:        if (ifap)
                    349:                freeifaddrs(ifap);
1.19      canacar   350:        return (ret);
1.1       deraadt   351: }
                    352:
                    353: void
1.18      canacar   354: print_mb(void)
1.1       deraadt   355: {
1.19      canacar   356:        int i, p, n, count = 0;
1.1       deraadt   357:
1.23      kettenis  358:        showmbuf(interfaces, -1, 1);
1.19      canacar   359:
                    360:        for (n = i = 0; i < num_ifs; i++) {
                    361:                struct if_info *ifi = &interfaces[i];
                    362:                int pcnt = count;
1.23      kettenis  363:                int showif = i;
                    364:
1.18      canacar   365:                if (maxprint > 0 && count >= maxprint)
1.19      canacar   366:                        return;
1.1       deraadt   367:
1.35      dlg       368:                for (p = 0; p < ifi->data.ifri_total; p++) {
                    369:                        struct if_rxring_info *ifr = &ifi->data.ifri_entries[p];
                    370:                        if (ifr->ifr_info.rxr_alive == 0)
1.19      canacar   371:                                continue;
                    372:                        if (n++ >= dispstart) {
1.23      kettenis  373:                                showmbuf(ifi, p, showif);
                    374:                                showif = 0;
1.19      canacar   375:                                count++;
                    376:                        }
                    377:                }
                    378:
                    379:                if (i && pcnt == count) {
                    380:                        /* only print the first line */
                    381:                        if (n++ >= dispstart) {
1.23      kettenis  382:                                showmbuf(ifi, -1, 1);
1.19      canacar   383:                                count++;
                    384:                        }
                    385:                }
                    386:        }
1.1       deraadt   387: }
                    388:
1.18      canacar   389:
                    390: static void
1.23      kettenis  391: showmbuf(struct if_info *ifi, int p, int showif)
1.1       deraadt   392: {
1.23      kettenis  393:        if (showif)
1.19      canacar   394:                print_fld_str(FLD_MB_IFACE, ifi->name);
                    395:
                    396:        if (p == -1 && ifi == interfaces) {
1.31      claudio   397:                print_fld_uint(FLD_MB_LLOCKS, mcllivelocks_diff);
1.19      canacar   398:                print_fld_size(FLD_MB_MSIZE, mbpool.pr_size);
                    399:                print_fld_size(FLD_MB_MALIVE, mbpool.pr_nget - mbpool.pr_nput);
                    400:                print_fld_size(FLD_MB_MHWM, mbpool.pr_hiwat);
                    401:        }
                    402:
                    403:        if (p >= 0 && p < mclpool_count) {
1.35      dlg       404:                struct if_rxring_info *ifr = &ifi->data.ifri_entries[p];
                    405:                struct if_rxring *rxr= &ifr->ifr_info;
                    406:                print_fld_uint(FLD_MB_MSIZE, ifr->ifr_size);
                    407:                print_fld_uint(FLD_MB_MALIVE, rxr->rxr_alive);
                    408:                if (rxr->rxr_lwm)
                    409:                        print_fld_size(FLD_MB_MLWM, rxr->rxr_lwm);
                    410:                if (rxr->rxr_hwm)
                    411:                        print_fld_size(FLD_MB_MHWM, rxr->rxr_hwm);
                    412:                if (rxr->rxr_cwm)
                    413:                        print_fld_size(FLD_MB_MCWM, rxr->rxr_cwm);
1.19      canacar   414:        }
1.18      canacar   415:
                    416:        end_line();
1.1       deraadt   417: }