1 1.36 mlelstv /* $NetBSD: mbuf.c,v 1.36 2024/02/24 09:53:26 mlelstv Exp $ */ 2 1.8 thorpej 3 1.1 cgd /* 4 1.5 mycroft * Copyright (c) 1983, 1988, 1993 5 1.5 mycroft * The Regents of the University of California. All rights reserved. 6 1.1 cgd * 7 1.1 cgd * Redistribution and use in source and binary forms, with or without 8 1.1 cgd * modification, are permitted provided that the following conditions 9 1.1 cgd * are met: 10 1.1 cgd * 1. Redistributions of source code must retain the above copyright 11 1.1 cgd * notice, this list of conditions and the following disclaimer. 12 1.1 cgd * 2. Redistributions in binary form must reproduce the above copyright 13 1.1 cgd * notice, this list of conditions and the following disclaimer in the 14 1.1 cgd * documentation and/or other materials provided with the distribution. 15 1.21 agc * 3. Neither the name of the University nor the names of its contributors 16 1.1 cgd * may be used to endorse or promote products derived from this software 17 1.1 cgd * without specific prior written permission. 18 1.1 cgd * 19 1.1 cgd * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 20 1.1 cgd * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 21 1.1 cgd * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 22 1.1 cgd * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 23 1.1 cgd * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 24 1.1 cgd * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 25 1.1 cgd * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 26 1.1 cgd * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 27 1.1 cgd * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 28 1.1 cgd * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 29 1.1 cgd * SUCH DAMAGE. 30 1.1 cgd */ 31 1.1 cgd 32 1.12 lukem #include <sys/cdefs.h> 33 1.1 cgd #ifndef lint 34 1.8 thorpej #if 0 35 1.8 thorpej static char sccsid[] = "from: @(#)mbuf.c 8.1 (Berkeley) 6/6/93"; 36 1.8 thorpej #else 37 1.36 mlelstv __RCSID("$NetBSD: mbuf.c,v 1.36 2024/02/24 09:53:26 mlelstv Exp $"); 38 1.8 thorpej #endif 39 1.1 cgd #endif /* not lint */ 40 1.14 thorpej 41 1.14 thorpej #define __POOL_EXPOSE 42 1.1 cgd 43 1.1 cgd #include <sys/param.h> 44 1.5 mycroft #include <sys/protosw.h> 45 1.5 mycroft #include <sys/socket.h> 46 1.1 cgd #include <sys/mbuf.h> 47 1.13 sommerfe #include <sys/pool.h> 48 1.19 matt #include <sys/sysctl.h> 49 1.5 mycroft 50 1.5 mycroft #include <stdio.h> 51 1.24 rpaulo #include <kvm.h> 52 1.16 cgd #include <stdlib.h> 53 1.18 martin #include <limits.h> 54 1.19 matt #include <errno.h> 55 1.19 matt #include <err.h> 56 1.5 mycroft #include "netstat.h" 57 1.30 pooka #include "prog_ops.h" 58 1.5 mycroft 59 1.1 cgd #define YES 1 60 1.1 cgd 61 1.1 cgd struct mbstat mbstat; 62 1.13 sommerfe struct pool mbpool, mclpool; 63 1.17 sommerfe struct pool_allocator mbpa, mclpa; 64 1.1 cgd 65 1.1 cgd static struct mbtypes { 66 1.29 lukem int mt_type; 67 1.29 lukem const char *mt_name; 68 1.1 cgd } mbtypes[] = { 69 1.1 cgd { MT_DATA, "data" }, 70 1.1 cgd { MT_OOBDATA, "oob data" }, 71 1.1 cgd { MT_CONTROL, "ancillary data" }, 72 1.1 cgd { MT_HEADER, "packet headers" }, 73 1.1 cgd { MT_FTABLE, "fragment reassembly queue headers" }, /* XXX */ 74 1.1 cgd { MT_SONAME, "socket names and addresses" }, 75 1.1 cgd { MT_SOOPTS, "socket options" }, 76 1.1 cgd { 0, 0 } 77 1.1 cgd }; 78 1.1 cgd 79 1.19 matt const int nmbtypes = sizeof(mbstat.m_mtypes) / sizeof(short); 80 1.1 cgd bool seen[256]; /* "have we seen this type yet?" */ 81 1.1 cgd 82 1.19 matt int mbstats_ctl[] = { CTL_KERN, KERN_MBUF, MBUF_STATS }; 83 1.19 matt int mowners_ctl[] = { CTL_KERN, KERN_MBUF, MBUF_MOWNERS }; 84 1.19 matt 85 1.1 cgd /* 86 1.1 cgd * Print mbuf statistics. 87 1.1 cgd */ 88 1.5 mycroft void 89 1.31 matt mbpr(u_long mbaddr, u_long msizeaddr, u_long mclbaddr, u_long mbpooladdr, 90 1.31 matt u_long mclpooladdr) 91 1.1 cgd { 92 1.18 martin u_long totmem, totused, totpct; 93 1.18 martin u_int totmbufs; 94 1.19 matt int i, lines; 95 1.12 lukem struct mbtypes *mp; 96 1.19 matt size_t len; 97 1.19 matt void *data; 98 1.28 yamt struct mowner_user *mo; 99 1.19 matt int mclbytes, msize; 100 1.10 jonathan 101 1.1 cgd if (nmbtypes != 256) { 102 1.5 mycroft fprintf(stderr, 103 1.9 thorpej "%s: unexpected change to mbstat; check source\n", 104 1.35 msaitoh getprogname()); 105 1.1 cgd return; 106 1.1 cgd } 107 1.19 matt 108 1.19 matt if (use_sysctl) { 109 1.19 matt size_t mbstatlen = sizeof(mbstat); 110 1.30 pooka if (prog_sysctl(mbstats_ctl, 111 1.19 matt sizeof(mbstats_ctl) / sizeof(mbstats_ctl[0]), 112 1.19 matt &mbstat, &mbstatlen, NULL, 0) < 0) { 113 1.19 matt warn("mbstat: sysctl failed"); 114 1.19 matt return; 115 1.19 matt } 116 1.19 matt goto printit; 117 1.19 matt } 118 1.19 matt 119 1.13 sommerfe if (mbaddr == 0) { 120 1.13 sommerfe fprintf(stderr, "%s: mbstat: symbol not in namelist\n", 121 1.16 cgd getprogname()); 122 1.13 sommerfe return; 123 1.13 sommerfe } 124 1.10 jonathan /*XXX*/ 125 1.10 jonathan if (msizeaddr != 0) 126 1.10 jonathan kread(msizeaddr, (char *)&msize, sizeof (msize)); 127 1.10 jonathan else 128 1.10 jonathan msize = MSIZE; 129 1.10 jonathan if (mclbaddr != 0) 130 1.10 jonathan kread(mclbaddr, (char *)&mclbytes, sizeof (mclbytes)); 131 1.10 jonathan else 132 1.10 jonathan mclbytes = MCLBYTES; 133 1.10 jonathan /*XXX*/ 134 1.10 jonathan 135 1.5 mycroft if (kread(mbaddr, (char *)&mbstat, sizeof (mbstat))) 136 1.1 cgd return; 137 1.13 sommerfe 138 1.13 sommerfe if (kread(mbpooladdr, (char *)&mbpool, sizeof (mbpool))) 139 1.13 sommerfe return; 140 1.13 sommerfe 141 1.13 sommerfe if (kread(mclpooladdr, (char *)&mclpool, sizeof (mclpool))) 142 1.13 sommerfe return; 143 1.13 sommerfe 144 1.17 sommerfe mbpooladdr = (u_long) mbpool.pr_alloc; 145 1.17 sommerfe mclpooladdr = (u_long) mclpool.pr_alloc; 146 1.17 sommerfe 147 1.17 sommerfe if (kread(mbpooladdr, (char *)&mbpa, sizeof (mbpa))) 148 1.17 sommerfe return; 149 1.17 sommerfe 150 1.17 sommerfe if (kread(mclpooladdr, (char *)&mclpa, sizeof (mclpa))) 151 1.17 sommerfe return; 152 1.17 sommerfe 153 1.19 matt printit: 154 1.1 cgd totmbufs = 0; 155 1.1 cgd for (mp = mbtypes; mp->mt_name; mp++) 156 1.1 cgd totmbufs += mbstat.m_mtypes[mp->mt_type]; 157 1.1 cgd printf("%u mbufs in use:\n", totmbufs); 158 1.1 cgd for (mp = mbtypes; mp->mt_name; mp++) 159 1.1 cgd if (mbstat.m_mtypes[mp->mt_type]) { 160 1.1 cgd seen[mp->mt_type] = YES; 161 1.1 cgd printf("\t%u mbufs allocated to %s\n", 162 1.1 cgd mbstat.m_mtypes[mp->mt_type], mp->mt_name); 163 1.1 cgd } 164 1.1 cgd seen[MT_FREE] = YES; 165 1.1 cgd for (i = 0; i < nmbtypes; i++) 166 1.1 cgd if (!seen[i] && mbstat.m_mtypes[i]) { 167 1.1 cgd printf("\t%u mbufs allocated to <mbuf type %d>\n", 168 1.1 cgd mbstat.m_mtypes[i], i); 169 1.1 cgd } 170 1.13 sommerfe 171 1.19 matt if (use_sysctl) /* XXX */ 172 1.22 enami goto dump_drain; 173 1.19 matt 174 1.11 christos printf("%lu/%lu mapped pages in use\n", 175 1.35 msaitoh (u_long)(mclpool.pr_nget - mclpool.pr_nput), 176 1.35 msaitoh ((u_long)mclpool.pr_npages * mclpool.pr_itemsperpage)); 177 1.17 sommerfe totmem = (mbpool.pr_npages << mbpa.pa_pageshift) + 178 1.17 sommerfe (mclpool.pr_npages << mclpa.pa_pageshift); 179 1.17 sommerfe totused = (mbpool.pr_nget - mbpool.pr_nput) * mbpool.pr_size + 180 1.13 sommerfe (mclpool.pr_nget - mclpool.pr_nput) * mclpool.pr_size; 181 1.18 martin if (totmem == 0) 182 1.18 martin totpct = 0; 183 1.35 msaitoh else if (totused < (ULONG_MAX / 100)) 184 1.18 martin totpct = (totused * 100)/totmem; 185 1.18 martin else { 186 1.35 msaitoh u_long totmem1 = totmem / 100; 187 1.35 msaitoh u_long totused1 = totused / 100; 188 1.35 msaitoh totpct = (totused1 * 100) / totmem1; 189 1.18 martin } 190 1.35 msaitoh 191 1.18 martin printf("%lu Kbytes allocated to network (%lu%% in use)\n", 192 1.13 sommerfe totmem / 1024, totpct); 193 1.22 enami 194 1.22 enami dump_drain: 195 1.11 christos printf("%lu calls to protocol drain routines\n", mbstat.m_drain); 196 1.19 matt 197 1.35 msaitoh if (sflag < 2) 198 1.19 matt return; 199 1.19 matt 200 1.19 matt if (!use_sysctl) 201 1.19 matt return; 202 1.19 matt 203 1.30 pooka if (prog_sysctl(mowners_ctl, 204 1.30 pooka sizeof(mowners_ctl)/sizeof(mowners_ctl[0]), 205 1.30 pooka NULL, &len, NULL, 0) < 0) { 206 1.23 atatat if (errno == ENOENT) 207 1.19 matt return; 208 1.19 matt warn("mowners: sysctl test"); 209 1.19 matt return; 210 1.19 matt } 211 1.27 yamt len += 10 * sizeof(*mo); /* add some slop */ 212 1.19 matt data = malloc(len); 213 1.19 matt if (data == NULL) { 214 1.19 matt warn("malloc(%lu)", (u_long)len); 215 1.19 matt return; 216 1.19 matt } 217 1.19 matt 218 1.30 pooka if (prog_sysctl(mowners_ctl, 219 1.30 pooka sizeof(mowners_ctl)/sizeof(mowners_ctl[0]), 220 1.30 pooka data, &len, NULL, 0) < 0) { 221 1.19 matt warn("mowners: sysctl get"); 222 1.19 matt free(data); 223 1.19 matt return; 224 1.19 matt } 225 1.19 matt 226 1.20 enami for (mo = (void *) data, lines = 0; len >= sizeof(*mo); 227 1.20 enami len -= sizeof(*mo), mo++) { 228 1.36 mlelstv char buf[34]; 229 1.19 matt if (vflag == 1 && 230 1.28 yamt mo->mo_counter[MOWNER_COUNTER_CLAIMS] == 0 && 231 1.28 yamt mo->mo_counter[MOWNER_COUNTER_EXT_CLAIMS] == 0 && 232 1.28 yamt mo->mo_counter[MOWNER_COUNTER_CLUSTER_CLAIMS] == 0) 233 1.19 matt continue; 234 1.19 matt if (vflag == 0 && 235 1.28 yamt mo->mo_counter[MOWNER_COUNTER_CLAIMS] == 236 1.28 yamt mo->mo_counter[MOWNER_COUNTER_RELEASES] && 237 1.28 yamt mo->mo_counter[MOWNER_COUNTER_EXT_CLAIMS] == 238 1.28 yamt mo->mo_counter[MOWNER_COUNTER_EXT_RELEASES] && 239 1.28 yamt mo->mo_counter[MOWNER_COUNTER_CLUSTER_CLAIMS] == 240 1.28 yamt mo->mo_counter[MOWNER_COUNTER_CLUSTER_RELEASES]) 241 1.19 matt continue; 242 1.36 mlelstv snprintf(buf, sizeof(buf), "%16.16s %-13.16s", 243 1.19 matt mo->mo_name, mo->mo_descr); 244 1.19 matt if ((lines % 24) == 0 || lines > 24) { 245 1.19 matt printf("%30s %-8s %10s %10s %10s\n", 246 1.19 matt "", "", "small", "ext", "cluster"); 247 1.19 matt lines = 1; 248 1.19 matt } 249 1.19 matt printf("%30s %-8s %10lu %10lu %10lu\n", 250 1.19 matt buf, "inuse", 251 1.28 yamt mo->mo_counter[MOWNER_COUNTER_CLAIMS] - 252 1.28 yamt mo->mo_counter[MOWNER_COUNTER_RELEASES], 253 1.28 yamt mo->mo_counter[MOWNER_COUNTER_EXT_CLAIMS] - 254 1.28 yamt mo->mo_counter[MOWNER_COUNTER_EXT_RELEASES], 255 1.28 yamt mo->mo_counter[MOWNER_COUNTER_CLUSTER_CLAIMS] - 256 1.28 yamt mo->mo_counter[MOWNER_COUNTER_CLUSTER_RELEASES]); 257 1.19 matt lines++; 258 1.19 matt if (vflag) { 259 1.19 matt printf("%30s %-8s %10lu %10lu %10lu\n", 260 1.19 matt "", "claims", 261 1.28 yamt mo->mo_counter[MOWNER_COUNTER_CLAIMS], 262 1.28 yamt mo->mo_counter[MOWNER_COUNTER_EXT_CLAIMS], 263 1.28 yamt mo->mo_counter[MOWNER_COUNTER_CLUSTER_CLAIMS]); 264 1.19 matt printf("%30s %-8s %10lu %10lu %10lu\n", 265 1.19 matt "", "releases", 266 1.28 yamt mo->mo_counter[MOWNER_COUNTER_RELEASES], 267 1.28 yamt mo->mo_counter[MOWNER_COUNTER_EXT_RELEASES], 268 1.28 yamt mo->mo_counter[MOWNER_COUNTER_CLUSTER_RELEASES]); 269 1.19 matt lines += 2; 270 1.19 matt } 271 1.19 matt } 272 1.19 matt free(data); 273 1.1 cgd } 274