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