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

1.25    ! henning     1: /*     $OpenBSD: mbufs.c,v 1.24 2009/04/20 20:30:41 chl 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:  */
                     17: #include <sys/param.h>
                     18: #include <sys/types.h>
1.19      canacar    19: #include <sys/socket.h>
                     20: #include <sys/sysctl.h>
1.1       deraadt    21: #include <sys/mbuf.h>
1.19      canacar    22: #include <net/if.h>
1.1       deraadt    23:
1.19      canacar    24: #include <err.h>
                     25: #include <errno.h>
                     26: #include <ifaddrs.h>
1.1       deraadt    27: #include <stdlib.h>
                     28: #include <string.h>
1.19      canacar    29:
1.1       deraadt    30: #include "systat.h"
1.18      canacar    31:
                     32:
1.19      canacar    33: /* pool info for mcl* pools */
                     34: struct mclpool_info {
                     35:        char title[16];
                     36:        int pool_offset;
                     37:        int size;
                     38: } mclpools[MCLPOOLS];
                     39:
                     40: int mclpool_count = 0;
                     41: int mbpool_index = -1;
                     42: struct pool mbpool;
                     43:
                     44: /* interfaces */
                     45: static int num_ifs;
                     46: struct if_info {
                     47:        char name[16];
                     48:        struct if_data data;
                     49: } *interfaces = NULL;
                     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:
                     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},
1.25    ! henning    62:        {"CURTX", 3, 5, 1, FLD_ALIGN_RIGHT, -1, 0, 0, 0},
1.19      canacar    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.19      canacar    72: #define FIELD_ADDR(x) (&fields_mbuf[x])
1.18      canacar    73:
1.19      canacar    74: #define FLD_MB_IFACE   FIELD_ADDR(0)
                     75: #define FLD_MB_RXDELAY FIELD_ADDR(1)
                     76: #define FLD_MB_TXDELAY FIELD_ADDR(2)
1.25    ! henning    77: #define FLD_MB_CURTX   FIELD_ADDR(3)
        !            78: #define FLD_MB_LLOCKS  FIELD_ADDR(4)
        !            79: #define FLD_MB_MSIZE   FIELD_ADDR(5)
        !            80: #define FLD_MB_MALIVE  FIELD_ADDR(6)
        !            81: #define FLD_MB_MLWM    FIELD_ADDR(7)
        !            82: #define FLD_MB_MHWM    FIELD_ADDR(8)
        !            83: #define FLD_MB_MCWM    FIELD_ADDR(9)
1.18      canacar    84:
                     85:
                     86: /* Define views */
1.19      canacar    87: field_def *view_mbuf[] = {
                     88:        FLD_MB_IFACE,
                     89: #if NOTYET
                     90:        FLD_MB_RXDELAY, FLD_MB_TXDELAY,
                     91: #endif
1.25    ! henning    92:        FLD_MB_CURTX, FLD_MB_LLOCKS, FLD_MB_MSIZE, FLD_MB_MALIVE, FLD_MB_MLWM,
        !            93:        FLD_MB_MHWM, FLD_MB_MCWM, NULL
1.18      canacar    94: };
                     95:
1.19      canacar    96: /* Define view managers */
1.18      canacar    97:
                     98: struct view_manager mbuf_mgr = {
                     99:        "Mbufs", select_mb, read_mb, NULL, print_header,
                    100:        print_mb, keyboard_callback, NULL, NULL
                    101: };
                    102:
                    103: field_view views_mb[] = {
1.19      canacar   104:        {view_mbuf, "mbufs", '4', &mbuf_mgr},
1.18      canacar   105:        {NULL, NULL, 0, NULL}
                    106: };
                    107:
                    108:
                    109: int
1.19      canacar   110: initmembufs(void)
1.1       deraadt   111: {
1.19      canacar   112:        field_view *v;
                    113:        int i, mib[4], npools;
                    114:        struct pool pool;
                    115:        char pname[32];
                    116:        size_t size;
                    117:
                    118:        /* go through all pools to identify mbuf and cluster pools */
                    119:        bzero(mclpools, sizeof(mclpools));
1.18      canacar   120:
1.19      canacar   121:        mib[0] = CTL_KERN;
                    122:        mib[1] = KERN_POOL;
                    123:        mib[2] = KERN_POOL_NPOOLS;
                    124:        size = sizeof(npools);
                    125:
                    126:        if (sysctl(mib, 3, &npools, &size, NULL, 0) < 0) {
                    127:                err(1, "sysctl(KERN_POOL_NPOOLS)");
                    128:                /* NOTREACHED */
                    129:        }
                    130:
                    131:        for (i = 1; i <= npools; i++) {
                    132:                mib[0] = CTL_KERN;
                    133:                mib[1] = KERN_POOL;
                    134:                mib[2] = KERN_POOL_NAME;
                    135:                mib[3] = i;
                    136:                size = sizeof(pname);
                    137:                if (sysctl(mib, 4, &pname, &size, NULL, 0) < 0) {
1.21      canacar   138:                        continue;
1.19      canacar   139:                }
                    140:
                    141:                if (strcmp(pname, "mbpl") == 0) {
                    142:                        mbpool_index = i;
                    143:                        continue;
                    144:                }
                    145:
                    146:                if (strncmp(pname, "mcl", 3) != 0)
                    147:                        continue;
                    148:
                    149:                if (mclpool_count == MCLPOOLS) {
1.24      chl       150:                        warnx("mbufs: Too many mcl* pools");
1.19      canacar   151:                        break;
                    152:                }
                    153:
                    154:                mib[2] = KERN_POOL_POOL;
                    155:                size = sizeof(struct pool);
                    156:
                    157:                if (sysctl(mib, 4, &pool, &size, NULL, 0) < 0) {
                    158:                        err(1, "sysctl(KERN_POOL_POOL, %d)", i);
                    159:                        /* NOTREACHED */
                    160:                }
                    161:
                    162:                mclpools[mclpool_count].size = pool.pr_size;
                    163:                mclpools[mclpool_count].pool_offset = i;
                    164:                snprintf(mclpools[mclpool_count].title,
                    165:                    sizeof(mclpools[0].title), "%dk",
                    166:                    pool.pr_size / 1024);
                    167:
                    168:                mclpool_count++;
                    169:        }
                    170:
                    171:        if (mclpool_count != MCLPOOLS)
                    172:                warnx("mbufs: Unable to read all %d mcl* pools", MCLPOOLS);
                    173:
                    174:        /* add view to the engine */
                    175:        for (v = views_mb; v->name != NULL; v++)
                    176:                add_view(v);
                    177:
                    178:
                    179:        /* finally read it once */
1.18      canacar   180:        read_mb();
                    181:
1.19      canacar   182:        return(1);
                    183: }
1.18      canacar   184:
1.19      canacar   185: int
                    186: select_mb(void)
                    187: {
                    188:        num_disp = 0;
1.18      canacar   189:        return (0);
1.1       deraadt   190: }
                    191:
1.18      canacar   192: int
                    193: read_mb(void)
1.1       deraadt   194: {
1.19      canacar   195:        struct pool pool;
                    196:        struct ifaddrs *ifap, *ifa;
                    197:        struct if_info *ifi;
                    198:        int mib[4];
                    199:        int i, p, nif, ret = 1;
                    200:        size_t size;
                    201:
                    202:        num_disp = 0;
                    203:        if (getifaddrs(&ifap)) {
                    204:                error("getifaddrs: %s", strerror(errno));
                    205:                return (1);
                    206:        }
                    207:
                    208:        nif = 1;
                    209:        for (ifa = ifap; ifa != NULL; ifa = ifa->ifa_next)
                    210:                if (ifa->ifa_addr && ifa->ifa_addr->sa_family == AF_LINK)
                    211:                        nif++;
                    212:
                    213:        if (interfaces == NULL || num_ifs < nif) {
                    214:                size_t len = sizeof(*ifi) * nif;
                    215:                if (nif > SIZE_MAX / sizeof(*ifi)) {
                    216:                        error("overflow allocting %u interfaces", nif);
                    217:                        goto exit;
                    218:                }
                    219:
                    220:                ifi = realloc(interfaces, len);
                    221:                if (ifi == NULL) {
                    222:                        error("realloc: out of memory allocating %lld bytes",
                    223:                              (long long) len);
                    224:                        goto exit;
                    225:                }
                    226:
                    227:                interfaces = ifi;
                    228:                num_ifs = nif;
                    229:        }
                    230:
                    231:        /* Fill in the "real" interfaces */
                    232:        ifi = interfaces + 1;
                    233:
                    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:                strlcpy(ifi->name, ifa->ifa_name, sizeof(ifi->name));
                    240:
                    241:                if (ifa->ifa_data)
                    242:                        memcpy(&ifi->data, ifa->ifa_data, sizeof(ifi->data));
                    243:                else
                    244:                        bzero(&ifi->data, sizeof(ifi->data));
                    245:                ifi++;
                    246:        }
                    247:
                    248:        /* Fill in the "System" entry from pools */
                    249:        bzero(interfaces, sizeof(interfaces[0]));
                    250:        strlcpy(interfaces[0].name, "System", sizeof(interfaces[0].name));
1.18      canacar   251:
                    252:        mib[0] = CTL_KERN;
1.19      canacar   253:        mib[1] = KERN_POOL;
                    254:        mib[2] = KERN_POOL_POOL;
                    255:        mib[3] = mbpool_index;
                    256:        size = sizeof(struct pool);
                    257:
                    258:        if (sysctl(mib, 4, &mbpool, &size, NULL, 0) < 0) {
                    259:                error("sysctl(KERN_POOL_POOL, %d)", i);
                    260:                goto exit;
                    261:        }
                    262:
                    263:        for (i = 0; i < mclpool_count; i++) {
                    264:                struct mclpool *mp = &interfaces[0].data.ifi_mclpool[i];
                    265:
                    266:                mib[3] = mclpools[i].pool_offset;
                    267:                size = sizeof(struct pool);
1.18      canacar   268:
1.19      canacar   269:                if (sysctl(mib, 4, &pool, &size, NULL, 0) < 0) {
                    270:                        error("sysctl(KERN_POOL_POOL, %d)", mib[3]);
                    271:                        continue;
                    272:                }
                    273:
                    274:                mp->mcl_alive = pool.pr_nget - pool.pr_nput;
                    275:                mp->mcl_hwm = pool.pr_hiwat;
1.18      canacar   276:        }
                    277:
1.19      canacar   278:        num_disp = 1;
                    279:        ret = 0;
1.18      canacar   280:
1.19      canacar   281:        for (i = 0; i < num_ifs; i++) {
                    282:                struct if_info *ifi = &interfaces[i];
                    283:                int pnd = num_disp;
                    284:                for (p = 0; p < mclpool_count; p++) {
                    285:                        struct mclpool *mp = &ifi->data.ifi_mclpool[p];
                    286:                        if (mp->mcl_alive == 0)
                    287:                                continue;
                    288:                        num_disp++;
                    289:                }
                    290:                if (i && pnd == num_disp)
                    291:                        num_disp++;
1.18      canacar   292:        }
                    293:
1.19      canacar   294:  exit:
                    295:        freeifaddrs(ifap);
                    296:        return (ret);
1.1       deraadt   297: }
                    298:
                    299: void
1.18      canacar   300: print_mb(void)
1.1       deraadt   301: {
1.19      canacar   302:        int i, p, n, count = 0;
1.1       deraadt   303:
1.23      kettenis  304:        showmbuf(interfaces, -1, 1);
1.19      canacar   305:
                    306:        for (n = i = 0; i < num_ifs; i++) {
                    307:                struct if_info *ifi = &interfaces[i];
                    308:                int pcnt = count;
1.23      kettenis  309:                int showif = i;
                    310:
1.18      canacar   311:                if (maxprint > 0 && count >= maxprint)
1.19      canacar   312:                        return;
1.1       deraadt   313:
1.19      canacar   314:                for (p = 0; p < mclpool_count; p++) {
                    315:                        struct mclpool *mp = &ifi->data.ifi_mclpool[p];
                    316:                        if (mp->mcl_alive == 0)
                    317:                                continue;
                    318:                        if (n++ >= dispstart) {
1.23      kettenis  319:                                showmbuf(ifi, p, showif);
                    320:                                showif = 0;
1.19      canacar   321:                                count++;
                    322:                        }
                    323:                }
                    324:
                    325:                if (i && pcnt == count) {
                    326:                        /* only print the first line */
                    327:                        if (n++ >= dispstart) {
1.23      kettenis  328:                                showmbuf(ifi, -1, 1);
1.19      canacar   329:                                count++;
                    330:                        }
                    331:                }
1.1       deraadt   332:
1.5       ericj     333:
1.19      canacar   334:        }
1.1       deraadt   335: }
                    336:
1.18      canacar   337:
                    338: static void
1.23      kettenis  339: showmbuf(struct if_info *ifi, int p, int showif)
1.1       deraadt   340: {
1.23      kettenis  341:        if (showif)
1.19      canacar   342:                print_fld_str(FLD_MB_IFACE, ifi->name);
                    343:
                    344:        if (p == -1 && ifi == interfaces) {
                    345:                print_fld_size(FLD_MB_MSIZE, mbpool.pr_size);
                    346:                print_fld_size(FLD_MB_MALIVE, mbpool.pr_nget - mbpool.pr_nput);
                    347:                print_fld_size(FLD_MB_MHWM, mbpool.pr_hiwat);
                    348:        }
1.25    ! henning   349:        if (showif && p != -1)
        !           350:                print_fld_uint(FLD_MB_CURTX, ifi->data.ifi_maxtx);
1.19      canacar   351:
                    352: #if NOTYET
                    353:        print_fld_uint(FLD_MB_RXDELAY, ifi->data.ifi_rxdelay);
                    354:        print_fld_uint(FLD_MB_TXDELAY, ifi->data.ifi_txdelay);
                    355: #endif
1.20      canacar   356:        if (ifi->data.ifi_livelocks)
                    357:                print_fld_size(FLD_MB_LLOCKS, ifi->data.ifi_livelocks);
1.19      canacar   358:
                    359:        if (p >= 0 && p < mclpool_count) {
                    360:                struct mclpool *mp = &ifi->data.ifi_mclpool[p];
                    361:
                    362:                print_fld_str(FLD_MB_MSIZE, mclpools[p].title);
                    363:                print_fld_uint(FLD_MB_MALIVE, mp->mcl_alive);
                    364:                if (mp->mcl_lwm)
                    365:                        print_fld_size(FLD_MB_MLWM, mp->mcl_lwm);
                    366:                if (mp->mcl_hwm)
                    367:                        print_fld_size(FLD_MB_MHWM, mp->mcl_hwm);
1.22      dlg       368:                if (mp->mcl_cwm)
                    369:                        print_fld_size(FLD_MB_MCWM, mp->mcl_cwm);
1.19      canacar   370:        }
1.18      canacar   371:
                    372:        end_line();
1.1       deraadt   373: }