19b50d902SRodney W. Grimes /* 29b50d902SRodney W. Grimes * Copyright (c) 1983, 1988, 1993 3c8e6b689SRobert Watson * The Regents of the University of California. 4c8e6b689SRobert Watson * Copyright (c) 2005 Robert N. M. Watson 5c8e6b689SRobert Watson * All rights reserved. 69b50d902SRodney W. Grimes * 79b50d902SRodney W. Grimes * Redistribution and use in source and binary forms, with or without 89b50d902SRodney W. Grimes * modification, are permitted provided that the following conditions 99b50d902SRodney W. Grimes * are met: 109b50d902SRodney W. Grimes * 1. Redistributions of source code must retain the above copyright 119b50d902SRodney W. Grimes * notice, this list of conditions and the following disclaimer. 129b50d902SRodney W. Grimes * 2. Redistributions in binary form must reproduce the above copyright 139b50d902SRodney W. Grimes * notice, this list of conditions and the following disclaimer in the 149b50d902SRodney W. Grimes * documentation and/or other materials provided with the distribution. 159b50d902SRodney W. Grimes * 3. All advertising materials mentioning features or use of this software 169b50d902SRodney W. Grimes * must display the following acknowledgement: 179b50d902SRodney W. Grimes * This product includes software developed by the University of 189b50d902SRodney W. Grimes * California, Berkeley and its contributors. 199b50d902SRodney W. Grimes * 4. Neither the name of the University nor the names of its contributors 209b50d902SRodney W. Grimes * may be used to endorse or promote products derived from this software 219b50d902SRodney W. Grimes * without specific prior written permission. 229b50d902SRodney W. Grimes * 239b50d902SRodney W. Grimes * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 249b50d902SRodney W. Grimes * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 259b50d902SRodney W. Grimes * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 269b50d902SRodney W. Grimes * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 279b50d902SRodney W. Grimes * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 289b50d902SRodney W. Grimes * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 299b50d902SRodney W. Grimes * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 309b50d902SRodney W. Grimes * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 319b50d902SRodney W. Grimes * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 329b50d902SRodney W. Grimes * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 339b50d902SRodney W. Grimes * SUCH DAMAGE. 349b50d902SRodney W. Grimes */ 359b50d902SRodney W. Grimes 365d422d6aSPhilippe Charnier #if 0 376cc6f122SPhilippe Charnier #ifndef lint 389b50d902SRodney W. Grimes static char sccsid[] = "@(#)mbuf.c 8.1 (Berkeley) 6/6/93"; 399b50d902SRodney W. Grimes #endif /* not lint */ 406cc6f122SPhilippe Charnier #endif 416cc6f122SPhilippe Charnier 426cc6f122SPhilippe Charnier #include <sys/cdefs.h> 436cc6f122SPhilippe Charnier __FBSDID("$FreeBSD$"); 449b50d902SRodney W. Grimes 459b50d902SRodney W. Grimes #include <sys/param.h> 4613ae2e2dSGarrett Wollman #include <sys/mbuf.h> 479b50d902SRodney W. Grimes #include <sys/protosw.h> 489b50d902SRodney W. Grimes #include <sys/socket.h> 4913ae2e2dSGarrett Wollman #include <sys/sysctl.h> 509b50d902SRodney W. Grimes 515d422d6aSPhilippe Charnier #include <err.h> 52d4426f28SRobert Watson #include <kvm.h> 53c8e6b689SRobert Watson #include <memstat.h> 549b50d902SRodney W. Grimes #include <stdio.h> 55af0e6bcdSAlfred Perlstein #include <stdlib.h> 5608442f8aSBosko Milekic #include <string.h> 579b50d902SRodney W. Grimes #include "netstat.h" 589b50d902SRodney W. Grimes 599b50d902SRodney W. Grimes /* 60d4426f28SRobert Watson * Print mbuf statistics. 619b50d902SRodney W. Grimes */ 629b50d902SRodney W. Grimes void 63d4426f28SRobert Watson mbpr(void *kvmd, u_long mbaddr) 64c8e6b689SRobert Watson { 65c8e6b689SRobert Watson struct memory_type_list *mtlp; 66c8e6b689SRobert Watson struct memory_type *mtp; 67c8e6b689SRobert Watson u_int64_t mbuf_count, mbuf_bytes, mbuf_free, mbuf_failures, mbuf_size; 68c8e6b689SRobert Watson u_int64_t cluster_count, cluster_bytes, cluster_limit, cluster_free; 69c8e6b689SRobert Watson u_int64_t cluster_failures, cluster_size; 70c8e6b689SRobert Watson u_int64_t packet_count, packet_bytes, packet_free, packet_failures; 71c8e6b689SRobert Watson u_int64_t tag_count, tag_bytes; 72c8e6b689SRobert Watson u_int64_t bytes_inuse, bytes_incache, bytes_total; 73c8e6b689SRobert Watson int nsfbufs, nsfbufspeak, nsfbufsused; 74c8e6b689SRobert Watson struct mbstat mbstat; 75c8e6b689SRobert Watson size_t mlen; 76d4426f28SRobert Watson int error, live; 77c8e6b689SRobert Watson 78d4426f28SRobert Watson live = (kvmd == NULL); 79c8e6b689SRobert Watson mtlp = memstat_mtl_alloc(); 80c8e6b689SRobert Watson if (mtlp == NULL) { 81c8e6b689SRobert Watson warn("memstat_mtl_alloc"); 82c8e6b689SRobert Watson return; 83c8e6b689SRobert Watson } 84c8e6b689SRobert Watson 85c8e6b689SRobert Watson /* 86d4426f28SRobert Watson * Use memstat_*_all() because some mbuf-related memory is in uma(9), 87d4426f28SRobert Watson * and some malloc(9). 88c8e6b689SRobert Watson */ 89d4426f28SRobert Watson if (live) { 90d4426f28SRobert Watson printf("live\n"); 91c8e6b689SRobert Watson if (memstat_sysctl_all(mtlp, 0) < 0) { 924f7ac59bSRobert Watson warnx("memstat_sysctl_all: %s", 934f7ac59bSRobert Watson memstat_strerror(memstat_mtl_geterror(mtlp))); 94c8e6b689SRobert Watson goto out; 95c8e6b689SRobert Watson } 96d4426f28SRobert Watson } else { 97d4426f28SRobert Watson printf("kvm\n"); 98d4426f28SRobert Watson if (memstat_kvm_all(mtlp, kvmd) < 0) { 99d4426f28SRobert Watson error = memstat_mtl_geterror(mtlp); 100d4426f28SRobert Watson if (error == MEMSTAT_ERROR_KVM) 101d4426f28SRobert Watson warnx("memstat_kvm_all: %s", 102d4426f28SRobert Watson kvm_geterr(kvmd)); 103d4426f28SRobert Watson else 104d4426f28SRobert Watson warnx("memstat_kvm_all: %s", 105d4426f28SRobert Watson memstat_strerror(error)); 106d4426f28SRobert Watson goto out; 107d4426f28SRobert Watson } 108d4426f28SRobert Watson } 109c8e6b689SRobert Watson 110c8e6b689SRobert Watson mtp = memstat_mtl_find(mtlp, ALLOCATOR_UMA, MBUF_MEM_NAME); 111c8e6b689SRobert Watson if (mtp == NULL) { 112c8e6b689SRobert Watson warnx("memstat_mtl_find: zone %s not found", MBUF_MEM_NAME); 113c8e6b689SRobert Watson goto out; 114c8e6b689SRobert Watson } 115c8e6b689SRobert Watson mbuf_count = memstat_get_count(mtp); 116c8e6b689SRobert Watson mbuf_bytes = memstat_get_bytes(mtp); 117c8e6b689SRobert Watson mbuf_free = memstat_get_free(mtp); 118c8e6b689SRobert Watson mbuf_failures = memstat_get_failures(mtp); 119c8e6b689SRobert Watson mbuf_size = memstat_get_size(mtp); 120c8e6b689SRobert Watson 121c8e6b689SRobert Watson mtp = memstat_mtl_find(mtlp, ALLOCATOR_UMA, MBUF_PACKET_MEM_NAME); 122c8e6b689SRobert Watson if (mtp == NULL) { 123c8e6b689SRobert Watson warnx("memstat_mtl_find: zone %s not found", 124c8e6b689SRobert Watson MBUF_PACKET_MEM_NAME); 125c8e6b689SRobert Watson goto out; 126c8e6b689SRobert Watson } 127c8e6b689SRobert Watson packet_count = memstat_get_count(mtp); 128c8e6b689SRobert Watson packet_bytes = memstat_get_bytes(mtp); 129c8e6b689SRobert Watson packet_free = memstat_get_free(mtp); 130c8e6b689SRobert Watson packet_failures = memstat_get_failures(mtp); 131c8e6b689SRobert Watson 132c8e6b689SRobert Watson mtp = memstat_mtl_find(mtlp, ALLOCATOR_UMA, MBUF_CLUSTER_MEM_NAME); 133c8e6b689SRobert Watson if (mtp == NULL) { 134c8e6b689SRobert Watson warnx("memstat_mtl_find: zone %s not found", 135c8e6b689SRobert Watson MBUF_CLUSTER_MEM_NAME); 136c8e6b689SRobert Watson goto out; 137c8e6b689SRobert Watson } 138c8e6b689SRobert Watson cluster_count = memstat_get_count(mtp); 139c8e6b689SRobert Watson cluster_bytes = memstat_get_bytes(mtp); 140c8e6b689SRobert Watson cluster_limit = memstat_get_countlimit(mtp); 141c8e6b689SRobert Watson cluster_free = memstat_get_free(mtp); 142c8e6b689SRobert Watson cluster_failures = memstat_get_failures(mtp); 143c8e6b689SRobert Watson cluster_size = memstat_get_size(mtp); 144c8e6b689SRobert Watson 145c8e6b689SRobert Watson mtp = memstat_mtl_find(mtlp, ALLOCATOR_MALLOC, MBUF_TAG_MEM_NAME); 146c8e6b689SRobert Watson if (mtp == NULL) { 147c8e6b689SRobert Watson warnx("memstat_mtl_find: malloc type %s not found", 148c8e6b689SRobert Watson MBUF_TAG_MEM_NAME); 149c8e6b689SRobert Watson goto out; 150c8e6b689SRobert Watson } 151c8e6b689SRobert Watson tag_count = memstat_get_count(mtp); 152c8e6b689SRobert Watson tag_bytes = memstat_get_bytes(mtp); 153c8e6b689SRobert Watson 154c8e6b689SRobert Watson printf("%llu/%llu/%llu mbufs in use (current/cache/total)\n", 155c8e6b689SRobert Watson mbuf_count + packet_count, mbuf_free + packet_free, 156c8e6b689SRobert Watson mbuf_count + packet_count + mbuf_free + packet_free); 157c8e6b689SRobert Watson 158c8e6b689SRobert Watson printf("%llu/%llu/%llu/%llu mbuf clusters in use " 159c8e6b689SRobert Watson "(current/cache/total/max)\n", 160c8e6b689SRobert Watson cluster_count - packet_free, cluster_free + packet_free, 161c8e6b689SRobert Watson cluster_count + cluster_free, cluster_limit); 162c8e6b689SRobert Watson 163c8e6b689SRobert Watson #if 0 164c8e6b689SRobert Watson printf("%llu mbuf tags in use\n", tag_count); 165c8e6b689SRobert Watson #endif 166c8e6b689SRobert Watson 167d4426f28SRobert Watson if (live) { 168c8e6b689SRobert Watson mlen = sizeof(nsfbufs); 169d4426f28SRobert Watson if (!sysctlbyname("kern.ipc.nsfbufs", &nsfbufs, &mlen, NULL, 170c8e6b689SRobert Watson 0) && 171d4426f28SRobert Watson !sysctlbyname("kern.ipc.nsfbufsused", &nsfbufsused, 172d4426f28SRobert Watson &mlen, NULL, 0) && 173d4426f28SRobert Watson !sysctlbyname("kern.ipc.nsfbufspeak", &nsfbufspeak, 174d4426f28SRobert Watson &mlen, NULL, 0)) { 175c8e6b689SRobert Watson printf("%d/%d/%d sfbufs in use (current/peak/max)\n", 176c8e6b689SRobert Watson nsfbufsused, nsfbufspeak, nsfbufs); 177c8e6b689SRobert Watson } 178d4426f28SRobert Watson } 179c8e6b689SRobert Watson 180c8e6b689SRobert Watson /*- 181c8e6b689SRobert Watson * Calculate in-use bytes as: 182c8e6b689SRobert Watson * - straight mbuf memory 183c8e6b689SRobert Watson * - mbuf memory in packets 184c8e6b689SRobert Watson * - the clusters attached to packets 185c8e6b689SRobert Watson * - and the rest of the non-packet-attached clusters. 186c8e6b689SRobert Watson * - m_tag memory 187c8e6b689SRobert Watson * This avoids counting the clusters attached to packets in the cache. 188c8e6b689SRobert Watson * This currently excludes sf_buf space. 189c8e6b689SRobert Watson */ 190c8e6b689SRobert Watson bytes_inuse = 191c8e6b689SRobert Watson mbuf_bytes + /* straight mbuf memory */ 192c8e6b689SRobert Watson packet_bytes + /* mbufs in packets */ 193c8e6b689SRobert Watson (packet_count * cluster_size) + /* clusters in packets */ 194c8e6b689SRobert Watson /* other clusters */ 195c8e6b689SRobert Watson ((cluster_count - packet_count - packet_free) * cluster_size) + 196c8e6b689SRobert Watson tag_bytes; 197c8e6b689SRobert Watson 198c8e6b689SRobert Watson /* 199c8e6b689SRobert Watson * Calculate in-cache bytes as: 200c8e6b689SRobert Watson * - cached straught mbufs 201c8e6b689SRobert Watson * - cached packet mbufs 202c8e6b689SRobert Watson * - cached packet clusters 203c8e6b689SRobert Watson * - cached straight clusters 204c8e6b689SRobert Watson * This currently excludes sf_buf space. 205c8e6b689SRobert Watson */ 206c8e6b689SRobert Watson bytes_incache = 207c8e6b689SRobert Watson (mbuf_free * mbuf_size) + /* straight free mbufs */ 208c8e6b689SRobert Watson (packet_free * mbuf_size) + /* mbufs in free packets */ 209c8e6b689SRobert Watson (packet_free * cluster_size) + /* clusters in free packets */ 210c8e6b689SRobert Watson (cluster_free * cluster_size); /* free clusters */ 211c8e6b689SRobert Watson 212c8e6b689SRobert Watson /* 213c8e6b689SRobert Watson * Total is bytes in use + bytes in cache. This doesn't take into 214c8e6b689SRobert Watson * account various other misc data structures, overhead, etc, but 215c8e6b689SRobert Watson * gives the user something useful despite that. 216c8e6b689SRobert Watson */ 217c8e6b689SRobert Watson bytes_total = bytes_inuse + bytes_incache; 218c8e6b689SRobert Watson 219c8e6b689SRobert Watson printf("%lluK/%lluK/%lluK bytes allocated to network " 220c8e6b689SRobert Watson "(current/cache/total)\n", bytes_inuse / 1024, 221c8e6b689SRobert Watson bytes_incache / 1024, bytes_total / 1024); 222c8e6b689SRobert Watson 223c8e6b689SRobert Watson #if 0 224c8e6b689SRobert Watson printf("%llu/%llu/%llu requests for mbufs denied (mbufs/clusters/" 225c8e6b689SRobert Watson "mbuf+clusters)\n", mbuf_failures, cluster_failures, 226c8e6b689SRobert Watson packet_failures); 227c8e6b689SRobert Watson #endif 228c8e6b689SRobert Watson 229d4426f28SRobert Watson if (live) { 230c8e6b689SRobert Watson mlen = sizeof(mbstat); 231d4426f28SRobert Watson if (sysctlbyname("kern.ipc.mbstat", &mbstat, &mlen, NULL, 0)) { 232d4426f28SRobert Watson warn("kern.ipc.mbstat"); 233d4426f28SRobert Watson goto out; 234d4426f28SRobert Watson } 235d4426f28SRobert Watson } else { 236d4426f28SRobert Watson if (kread(mbaddr, (char *)&mbstat, sizeof mbstat)) 237d4426f28SRobert Watson goto out; 238d4426f28SRobert Watson } 239d4426f28SRobert Watson printf("%lu requests for sfbufs denied\n", mbstat.sf_allocfail); 240d4426f28SRobert Watson printf("%lu requests for sfbufs delayed\n", mbstat.sf_allocwait); 241c8e6b689SRobert Watson printf("%lu requests for I/O initiated by sendfile\n", 242c8e6b689SRobert Watson mbstat.sf_iocnt); 243d4426f28SRobert Watson printf("%lu calls to protocol drain routines\n", mbstat.m_drain); 244c8e6b689SRobert Watson out: 245c8e6b689SRobert Watson memstat_mtl_free(mtlp); 246c8e6b689SRobert Watson } 247