mbuf.c revision 80399
160786Sps/* 2221715Sdelphij * Copyright (c) 1983, 1988, 1993 360786Sps * The Regents of the University of California. All rights reserved. 460786Sps * 560786Sps * Redistribution and use in source and binary forms, with or without 660786Sps * modification, are permitted provided that the following conditions 760786Sps * are met: 860786Sps * 1. Redistributions of source code must retain the above copyright 960786Sps * notice, this list of conditions and the following disclaimer. 1060786Sps * 2. Redistributions in binary form must reproduce the above copyright 1160786Sps * notice, this list of conditions and the following disclaimer in the 1260786Sps * documentation and/or other materials provided with the distribution. 1360786Sps * 3. All advertising materials mentioning features or use of this software 1460786Sps * must display the following acknowledgement: 1560786Sps * This product includes software developed by the University of 1660786Sps * California, Berkeley and its contributors. 1760786Sps * 4. Neither the name of the University nor the names of its contributors 1860786Sps * may be used to endorse or promote products derived from this software 1960786Sps * without specific prior written permission. 2060786Sps * 2160786Sps * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 2260786Sps * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 2360786Sps * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 24128345Stjr * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 2560786Sps * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 2660786Sps * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 2760786Sps * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 2860786Sps * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 2960786Sps * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 3060786Sps * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 31170256Sdelphij * SUCH DAMAGE. 32170256Sdelphij */ 3360786Sps 3460786Sps#ifndef lint 35221715Sdelphij#if 0 36221715Sdelphijstatic char sccsid[] = "@(#)mbuf.c 8.1 (Berkeley) 6/6/93"; 37221715Sdelphij#endif 38221715Sdelphijstatic const char rcsid[] = 39221715Sdelphij "$FreeBSD: head/usr.bin/netstat/mbuf.c 80399 2001-07-26 18:47:46Z bmilekic $"; 40221715Sdelphij#endif /* not lint */ 41221715Sdelphij 42221715Sdelphij#include <sys/param.h> 43221715Sdelphij#include <sys/mbuf.h> 44221715Sdelphij#include <sys/protosw.h> 45221715Sdelphij#include <sys/socket.h> 46221715Sdelphij#include <sys/sysctl.h> 47221715Sdelphij 48221715Sdelphij#include <err.h> 49221715Sdelphij#include <stdio.h> 50221715Sdelphij#include <stdlib.h> 51221715Sdelphij#include <string.h> 52221715Sdelphij#include "netstat.h" 53221715Sdelphij 54221715Sdelphij#define YES 1 55221715Sdelphijtypedef int bool; 56221715Sdelphij 57221715Sdelphij/* XXX: mbtypes stats temporarily disactivated. */ 58221715Sdelphij#if 0 59221715Sdelphijstatic struct mbtypenames { 60221715Sdelphij int mt_type; 61221715Sdelphij char *mt_name; 62221715Sdelphij} mbtypenames[] = { 63221715Sdelphij { MT_DATA, "data" }, 6460786Sps { MT_OOBDATA, "oob data" }, 6560786Sps { MT_CONTROL, "ancillary data" }, 6660786Sps { MT_HEADER, "packet headers" }, 6760786Sps#ifdef MT_SOCKET 6860786Sps { MT_SOCKET, "socket structures" }, /* XXX */ 6960786Sps#endif 7060786Sps#ifdef MT_PCB 7160786Sps { MT_PCB, "protocol control blocks" }, /* XXX */ 72128345Stjr#endif 7360786Sps#ifdef MT_RTABLE 7460786Sps { MT_RTABLE, "routing table entries" }, /* XXX */ 7560786Sps#endif 7660786Sps#ifdef MT_HTABLE 7760786Sps { MT_HTABLE, "IMP host table entries" }, /* XXX */ 7860786Sps#endif 7960786Sps#ifdef MT_ATABLE 8060786Sps { MT_ATABLE, "address resolution tables" }, 8160786Sps#endif 8260786Sps { MT_FTABLE, "fragment reassembly queue headers" }, /* XXX */ 8360786Sps { MT_SONAME, "socket names and addresses" }, 8460786Sps#ifdef MT_SOOPTS 8560786Sps { MT_SOOPTS, "socket options" }, 8660786Sps#endif 8760786Sps#ifdef MT_RIGHTS 8860786Sps { MT_RIGHTS, "access rights" }, 8960786Sps#endif 9060786Sps#ifdef MT_IFADDR 9160786Sps { MT_IFADDR, "interface addresses" }, /* XXX */ 9260786Sps#endif 9360786Sps { 0, 0 } 9460786Sps}; 9560786Sps#endif /* 0 */ 9660786Sps 9760786Sps/* 9860786Sps * Print mbuf statistics. 9960786Sps */ 100221715Sdelphijvoid 10160786Spsmbpr(u_long mbaddr, u_long mbtaddr, u_long nmbcaddr, u_long nmbufaddr, 10260786Sps u_long mblimaddr, u_long cllimaddr, u_long cpusaddr, u_long pgsaddr, 10360786Sps u_long mbpaddr) 10460786Sps{ 10560786Sps int i, nmbufs, nmbclusters, page_size, num_objs; 10660786Sps u_int mbuf_limit, clust_limit; 10760786Sps u_long totspace, totnum, totfree; 10860786Sps size_t mlen; 10960786Sps struct mbstat *mbstat = NULL; 11060786Sps struct mbpstat **mbpstat = NULL; 11160786Sps 11260786Sps/* XXX: mbtypes stats temporarily disabled. */ 11360786Sps#if 0 11460786Sps int nmbtypes; 11560786Sps size_t mbtypeslen; 11660786Sps struct mbtypenames *mp; 11760786Sps u_long *mbtypes = NULL; 11860786Sps bool *seen = NULL; 11960786Sps 12060786Sps /* 12160786Sps * XXX 12260786Sps * We can't kread() mbtypeslen from a core image so we'll 12360786Sps * bogusly assume it's the same as in the running kernel. 12460786Sps */ 12560786Sps if (sysctlbyname("kern.ipc.mbtypes", NULL, &mbtypeslen, NULL, 0) < 0) { 12660786Sps warn("sysctl: retrieving mbtypes length"); 12760786Sps goto err; 12860786Sps } 12960786Sps if ((mbtypes = malloc(mbtypeslen)) == NULL) { 13060786Sps warn("malloc: %lu bytes for mbtypes", (u_long)mbtypeslen); 13160786Sps goto err; 13260786Sps } 13360786Sps 13460786Sps nmbtypes = mbtypeslen / sizeof(*mbtypes); 13560786Sps if ((seen = calloc(nmbtypes, sizeof(*seen))) == NULL) { 13660786Sps warn("calloc"); 13760786Sps goto err; 13860786Sps } 13960786Sps#endif 14060786Sps 14160786Sps mlen = sizeof *mbstat; 14260786Sps if ((mbstat = malloc(mlen)) == NULL) { 14360786Sps warn("malloc: cannot allocate memory for mbstat"); 14460786Sps goto err; 14560786Sps } 14660786Sps 14760786Sps /* 14860786Sps * XXX: Unfortunately, for the time being, we have to fetch 149128345Stjr * the total length of the per-CPU stats area via sysctl 15089019Sps * (regardless of whether we're looking at a core or not. 15189019Sps */ 15260786Sps if (sysctlbyname("kern.ipc.mb_statpcpu", NULL, &mlen, NULL, 0) < 0) { 15389019Sps warn("sysctl: retrieving mb_statpcpu len"); 15460786Sps goto err; 15560786Sps } 15660786Sps num_objs = (int)(mlen / sizeof(struct mbpstat)); 15760786Sps if ((mbpstat = calloc(num_objs, sizeof(struct mbpstat *))) == NULL) { 15860786Sps warn("calloc: cannot allocate memory for mbpstats pointers"); 15960786Sps goto err; 16060786Sps } 16160786Sps if ((mbpstat[0] = calloc(num_objs, sizeof(struct mbpstat))) == NULL) { 16260786Sps warn("calloc: cannot allocate memory for mbpstats"); 16360786Sps goto err; 16460786Sps } 165170256Sdelphij 166170256Sdelphij if (mbaddr) { 167170256Sdelphij if (kread(mbpaddr, (char *)mbpstat[0], mlen)) 168170256Sdelphij goto err; 16960786Sps if (kread(mbaddr, (char *)mbstat, sizeof mbstat)) 17060786Sps goto err; 17160786Sps#if 0 17260786Sps if (kread(mbtaddr, (char *)mbtypes, mbtypeslen)) 17360786Sps goto err; 17460786Sps#endif 17560786Sps if (kread(nmbcaddr, (char *)&nmbclusters, sizeof(int))) 17660786Sps goto err; 17760786Sps if (kread(nmbufaddr, (char *)&nmbufs, sizeof(int))) 17860786Sps goto err; 179161475Sdelphij if (kread(mblimaddr, (char *)&mbuf_limit, sizeof(u_int))) 18060786Sps goto err; 18160786Sps if (kread(cllimaddr, (char *)&clust_limit, sizeof(u_int))) 18260786Sps goto err; 18360786Sps if (kread(pgsaddr, (char *)&page_size, sizeof(int))) 184161475Sdelphij goto err; 18560786Sps } else { 18660786Sps if (sysctlbyname("kern.ipc.mb_statpcpu", mbpstat[0], &mlen, 18760786Sps NULL, 0) < 0) { 18860786Sps warn("sysctl: retrieving mb_statpcpu"); 18960786Sps goto err; 19060786Sps } 19160786Sps mlen = sizeof *mbstat; 19260786Sps if (sysctlbyname("kern.ipc.mbstat", mbstat, &mlen, NULL, 0) 19360786Sps < 0) { 19460786Sps warn("sysctl: retrieving mbstat"); 19560786Sps goto err; 19660786Sps } 19760786Sps#if 0 19860786Sps if (sysctlbyname("kern.ipc.mbtypes", mbtypes, &mbtypeslen, NULL, 19960786Sps 0) < 0) { 20060786Sps warn("sysctl: retrieving mbtypes"); 20160786Sps goto err; 20260786Sps } 20360786Sps#endif 20460786Sps mlen = sizeof(int); 20560786Sps if (sysctlbyname("kern.ipc.nmbclusters", &nmbclusters, &mlen, 20660786Sps NULL, 0) < 0) { 20760786Sps warn("sysctl: retrieving nmbclusters"); 20860786Sps goto err; 20960786Sps } 21060786Sps mlen = sizeof(int); 21160786Sps if (sysctlbyname("kern.ipc.nmbufs", &nmbufs, &mlen, NULL, 0) 21260786Sps < 0) { 21360786Sps warn("sysctl: retrieving nmbufs"); 21460786Sps goto err; 21560786Sps } 21660786Sps mlen = sizeof(u_int); 21760786Sps if (sysctlbyname("kern.ipc.mbuf_limit", &mbuf_limit, &mlen, 21860786Sps NULL, 0) < 0) { 21960786Sps warn("sysctl: retrieving mbuf_limit"); 22060786Sps goto err; 22160786Sps } 22260786Sps mlen = sizeof(u_int); 22360786Sps if (sysctlbyname("kern.ipc.clust_limit", &clust_limit, &mlen, 22460786Sps NULL, 0) < 0) { 22560786Sps warn("sysctl: retrieving clust_limit"); 22660786Sps goto err; 22760786Sps } 22860786Sps mlen = sizeof(int); 22960786Sps if (sysctlbyname("hw.pagesize", &page_size, &mlen, NULL, 0) 23060786Sps < 0) { 23160786Sps warn("sysctl: retrieving hw.pagesize"); 23260786Sps goto err; 23360786Sps } 23460786Sps } 23560786Sps 23660786Sps for (i = 0; i < num_objs; i++) 23760786Sps mbpstat[i] = mbpstat[0] + i; 23860786Sps 23960786Sps#undef MSIZE 24060786Sps#define MSIZE (mbstat->m_msize) 24160786Sps#undef MCLBYTES 24260786Sps#define MCLBYTES (mbstat->m_mclbytes) 24360786Sps#define MBPERPG (page_size / MSIZE) 24460786Sps#define CLPERPG (page_size / MCLBYTES) 24560786Sps#define GENLST (num_objs - 1) 24660786Sps 24760786Sps printf("mbuf usage:\n"); 24860786Sps printf("\tGEN list:\t%lu/%lu (in use/in pool)\n", 24960786Sps (mbpstat[GENLST]->mb_mbpgs * MBPERPG - mbpstat[GENLST]->mb_mbfree), 25060786Sps (mbpstat[GENLST]->mb_mbpgs * MBPERPG)); 25160786Sps totnum = mbpstat[GENLST]->mb_mbpgs * MBPERPG; 25260786Sps totfree = mbpstat[GENLST]->mb_mbfree; 25360786Sps totspace = mbpstat[GENLST]->mb_mbpgs * page_size; 25460786Sps for (i = 0; i < (num_objs - 1); i++) { 25560786Sps if (mbpstat[i]->mb_active == 0) 25660786Sps continue; 25760786Sps printf("\tCPU #%d list:\t%lu/%lu (in use/in pool)\n", i, 25860786Sps (mbpstat[i]->mb_mbpgs * MBPERPG - mbpstat[i]->mb_mbfree), 25960786Sps (mbpstat[i]->mb_mbpgs * MBPERPG)); 26060786Sps totspace += mbpstat[i]->mb_mbpgs * page_size; 261128345Stjr totnum += mbpstat[i]->mb_mbpgs * MBPERPG; 262128345Stjr totfree += mbpstat[i]->mb_mbfree; 263128345Stjr } 26460786Sps printf("\tTotal:\t\t%lu/%lu (in use/in pool)\n", (totnum - totfree), 26560786Sps totnum); 26660786Sps printf("\tMaximum number allowed on each CPU list: %d\n", mbuf_limit); 26760786Sps printf("\tMaximum possible: %d\n", nmbufs); 26860786Sps printf("\t%lu%% of mbuf map consumed\n", ((totspace * 100) / (nmbufs 26960786Sps * MSIZE))); 27060786Sps 27160786Sps printf("mbuf cluster usage:\n"); 27260786Sps printf("\tGEN list:\t%lu/%lu (in use/in pool)\n", 27360786Sps (mbpstat[GENLST]->mb_clpgs * CLPERPG - mbpstat[GENLST]->mb_clfree), 27460786Sps (mbpstat[GENLST]->mb_clpgs * CLPERPG)); 27560786Sps totnum = mbpstat[GENLST]->mb_clpgs * CLPERPG; 27660786Sps totfree = mbpstat[GENLST]->mb_clfree; 27760786Sps totspace = mbpstat[GENLST]->mb_clpgs * page_size; 27860786Sps for (i = 0; i < (num_objs - 1); i++) { 27960786Sps if (mbpstat[i]->mb_active == 0) 28060786Sps continue; 28160786Sps printf("\tCPU #%d list:\t%lu/%lu (in use/in pool)\n", i, 28260786Sps (mbpstat[i]->mb_clpgs * CLPERPG - mbpstat[i]->mb_clfree), 28360786Sps (mbpstat[i]->mb_clpgs * CLPERPG)); 28460786Sps totspace += mbpstat[i]->mb_clpgs * page_size; 28560786Sps totnum += mbpstat[i]->mb_clpgs * CLPERPG; 28660786Sps totfree += mbpstat[i]->mb_clfree; 28760786Sps } 28860786Sps printf("\tTotal:\t\t%lu/%lu (in use/in pool)\n", (totnum - totfree), 28960786Sps totnum); 29060786Sps printf("\tMaximum number allowed on each CPU list: %d\n", clust_limit); 29160786Sps printf("\tMaximum possible: %d\n", nmbclusters); 292221715Sdelphij printf("\t%lu%% of cluster map consumed\n", ((totspace * 100) / 293221715Sdelphij (nmbclusters * MCLBYTES))); 294221715Sdelphij 29560786Sps printf("%lu requests for memory denied\n", mbstat->m_drops); 29660786Sps printf("%lu requests for memory delayed\n", mbstat->m_wait); 29760786Sps printf("%lu calls to protocol drain routines\n", mbstat->m_drain); 29860786Sps 29960786Spserr: 30060786Sps#if 0 30160786Sps if (mbtypes != NULL) 30260786Sps free(mbtypes); 30360786Sps if (seen != NULL) 30460786Sps free(seen); 30560786Sps#endif 30660786Sps if (mbstat != NULL) 30760786Sps free(mbstat); 308221715Sdelphij if (mbpstat != NULL) { 30960786Sps if (mbpstat[0] != NULL) 31060786Sps free(mbpstat[0]); 31160786Sps free(mbpstat); 31260786Sps } 31360786Sps 314221715Sdelphij return; 31560786Sps} 31660786Sps