[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.43

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