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

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