]>
git.saurik.com Git - apple/network_cmds.git/blob - netstat.tproj/mbuf.c
2 * Copyright (c) 2008 Apple Inc. All rights reserved.
4 * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
6 * This file contains Original Code and/or Modifications of Original Code
7 * as defined in and that are subject to the Apple Public Source License
8 * Version 2.0 (the 'License'). You may not use this file except in
9 * compliance with the License. The rights granted to you under the License
10 * may not be used to create, or enable the creation or redistribution of,
11 * unlawful or unlicensed copies of an Apple operating system, or to
12 * circumvent, violate, or enable the circumvention or violation of, any
13 * terms of an Apple operating system software license agreement.
15 * Please obtain a copy of the License at
16 * http://www.opensource.apple.com/apsl/ and read it before using this file.
18 * The Original Code and all software distributed under the License are
19 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
20 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
21 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
22 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
23 * Please see the License for the specific language governing rights and
24 * limitations under the License.
26 * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
29 * Copyright (c) 1983, 1988, 1993
30 * The Regents of the University of California. All rights reserved.
32 * Redistribution and use in source and binary forms, with or without
33 * modification, are permitted provided that the following conditions
35 * 1. Redistributions of source code must retain the above copyright
36 * notice, this list of conditions and the following disclaimer.
37 * 2. Redistributions in binary form must reproduce the above copyright
38 * notice, this list of conditions and the following disclaimer in the
39 * documentation and/or other materials provided with the distribution.
40 * 3. All advertising materials mentioning features or use of this software
41 * must display the following acknowledgement:
42 * This product includes software developed by the University of
43 * California, Berkeley and its contributors.
44 * 4. Neither the name of the University nor the names of its contributors
45 * may be used to endorse or promote products derived from this software
46 * without specific prior written permission.
48 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
49 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
50 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
51 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
52 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
53 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
54 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
55 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
56 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
57 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
62 #include <sys/param.h>
63 #include <sys/socket.h>
65 #include <sys/sysctl.h>
77 static struct mbtypes
{
82 { MT_OOBDATA
, "oob data" },
83 { MT_CONTROL
, "ancillary data" },
84 { MT_HEADER
, "packet headers" },
85 { MT_SOCKET
, "socket structures" }, /* XXX */
86 { MT_PCB
, "protocol control blocks" }, /* XXX */
87 { MT_RTABLE
, "routing table entries" }, /* XXX */
88 { MT_HTABLE
, "IMP host table entries" }, /* XXX */
89 { MT_ATABLE
, "address resolution tables" },
90 { MT_FTABLE
, "fragment reassembly queue headers" }, /* XXX */
91 { MT_SONAME
, "socket names and addresses" },
92 { MT_SOOPTS
, "socket options" },
93 { MT_RIGHTS
, "access rights" },
94 { MT_IFADDR
, "interface addresses" }, /* XXX */
95 { MT_TAG
, "packet tags" }, /* XXX */
99 int nmbtypes
= sizeof(mbstat
.m_mtypes
) / sizeof(short);
100 bool seen
[256]; /* "have we seen this type yet?" */
103 unsigned int njcl
, njclbytes
;
105 #define KERN_IPC_MB_STAT "kern.ipc.mb_stat"
106 #define KERN_IPC_NJCL "kern.ipc.njcl"
107 #define KERN_IPC_NJCL_BYTES "kern.ipc.njclbytes"
109 #define MB_STAT_HDR1 "\
110 class buf active ctotal total cache cached uncached memory\n\
111 name size bufs bufs bufs state bufs bufs usage\n\
112 ---------- ----- -------- -------- -------- ----- -------- -------- ---------\n\
115 #define MB_STAT_HDR2 "\n\
116 class waiter notify purge wretry nwretry failure\n\
117 name count count count count count count\n\
118 ---------- -------- -------- -------- -------- -------- --------\n\
121 static const char *mbpr_state(int);
122 static const char *mbpr_mem(u_int32_t
);
123 static int mbpr_getdata(void);
126 * Print mbuf statistics.
131 unsigned long totmem
= 0, totfree
= 0, totmbufs
, totused
;
133 u_int32_t m_msize
, m_mbufs
= 0, m_clfree
= 0, m_bigclfree
= 0;
134 u_int32_t m_mbufclfree
= 0, m_mbufbigclfree
= 0;
135 u_int32_t m_16kclusters
= 0, m_16kclfree
= 0, m_mbuf16kclfree
= 0;
140 if (mbpr_getdata() != 0)
143 m_msize
= mbstat
.m_msize
;
144 cp
= &mb_stat
->mbs_class
[0];
145 for (i
= 0; i
< mb_stat
->mbs_cnt
; i
++, cp
++) {
146 if (cp
->mbcl_size
== m_msize
) {
147 m_mbufs
= cp
->mbcl_active
;
148 } else if (cp
->mbcl_size
== mbstat
.m_mclbytes
) {
149 m_clfree
= cp
->mbcl_total
- cp
->mbcl_active
;
150 } else if (cp
->mbcl_size
== mbstat
.m_bigmclbytes
) {
151 m_bigclfree
= cp
->mbcl_total
- cp
->mbcl_active
;
152 } else if (njcl
> 0 && cp
->mbcl_size
== njclbytes
) {
153 m_16kclfree
= cp
->mbcl_total
- cp
->mbcl_active
;
154 m_16kclusters
= cp
->mbcl_total
;
155 } else if (cp
->mbcl_size
== (m_msize
+ mbstat
.m_mclbytes
)) {
156 m_mbufclfree
= cp
->mbcl_total
- cp
->mbcl_active
;
157 } else if (cp
->mbcl_size
== (m_msize
+ mbstat
.m_bigmclbytes
)) {
158 m_mbufbigclfree
= cp
->mbcl_total
- cp
->mbcl_active
;
159 } else if (njcl
> 0 && cp
->mbcl_size
== (m_msize
+ njclbytes
)) {
160 m_mbuf16kclfree
= cp
->mbcl_total
- cp
->mbcl_active
;
164 /* adjust free counts to include composite caches */
165 m_clfree
+= m_mbufclfree
;
166 m_bigclfree
+= m_mbufbigclfree
;
167 m_16kclfree
+= m_mbuf16kclfree
;
169 cp
= &mb_stat
->mbs_class
[0];
170 for (i
= 0; i
< mb_stat
->mbs_cnt
; i
++, cp
++) {
173 mem
= cp
->mbcl_ctotal
* cp
->mbcl_size
;
175 totfree
+= (cp
->mbcl_mc_cached
+ cp
->mbcl_infree
) *
179 printf(MB_STAT_HDR1
);
182 cp
->mbcl_size
> (m_msize
+ mbstat
.m_bigmclbytes
))
185 printf("%-10s %5u %8u %8u %8u %5s %8u %8u %9s\n",
186 cp
->mbcl_cname
, cp
->mbcl_size
, cp
->mbcl_active
,
187 cp
->mbcl_ctotal
, cp
->mbcl_total
,
188 mbpr_state(cp
->mbcl_mc_state
), cp
->mbcl_mc_cached
,
189 cp
->mbcl_infree
, mbpr_mem(mem
));
193 cp
= &mb_stat
->mbs_class
[0];
194 for (i
= 0; i
< mb_stat
->mbs_cnt
; i
++, cp
++) {
197 printf(MB_STAT_HDR2
);
200 cp
->mbcl_size
> (m_msize
+ mbstat
.m_bigmclbytes
))
203 printf("%-10s %8u %8llu %8llu %8u %8u %8llu\n",
204 cp
->mbcl_cname
, cp
->mbcl_mc_waiter_cnt
,
205 cp
->mbcl_notified
, cp
->mbcl_purge_cnt
,
206 cp
->mbcl_mc_wretry_cnt
, cp
->mbcl_mc_nwretry_cnt
,
215 for (mp
= mbtypes
; mp
->mt_name
; mp
++)
216 totmbufs
+= mbstat
.m_mtypes
[mp
->mt_type
];
218 * These stats are not updated atomically in the kernel;
219 * adjust the total as neeeded.
221 if (totmbufs
> m_mbufs
)
223 printf("%lu/%u mbufs in use:\n", totmbufs
, m_mbufs
);
224 for (mp
= mbtypes
; mp
->mt_name
; mp
++)
225 if (mbstat
.m_mtypes
[mp
->mt_type
]) {
226 seen
[mp
->mt_type
] = YES
;
227 printf("\t%u mbufs allocated to %s\n",
228 mbstat
.m_mtypes
[mp
->mt_type
], mp
->mt_name
);
231 for (i
= 0; i
< nmbtypes
; i
++)
232 if (!seen
[i
] && mbstat
.m_mtypes
[i
]) {
233 printf("\t%u mbufs allocated to <mbuf type %d>\n",
234 mbstat
.m_mtypes
[i
], i
);
236 if ((m_mbufs
- totmbufs
) > 0)
237 printf("\t%lu mbufs allocated to caches\n",
239 printf("%u/%u mbuf 2KB clusters in use\n",
240 (unsigned int)(mbstat
.m_clusters
- m_clfree
),
241 (unsigned int)mbstat
.m_clusters
);
242 printf("%u/%u mbuf 4KB clusters in use\n",
243 (unsigned int)(mbstat
.m_bigclusters
- m_bigclfree
),
244 (unsigned int)mbstat
.m_bigclusters
);
246 printf("%u/%u mbuf %uKB clusters in use\n",
247 m_16kclusters
- m_16kclfree
, m_16kclusters
,
250 totused
= totmem
- totfree
;
253 else if (totused
< (ULONG_MAX
/100))
254 totpct
= (totused
* 100)/(double)totmem
;
256 u_long totmem1
= totmem
/100;
257 u_long totused1
= totused
/100;
258 totpct
= (totused1
* 100)/(double)totmem1
;
260 printf("%lu KB allocated to network (%.1f%% in use)\n",
261 totmem
/ 1024, totpct
);
263 printf("%u requests for memory denied\n", (unsigned int)mbstat
.m_drops
);
264 printf("%u requests for memory delayed\n", (unsigned int)mbstat
.m_wait
);
265 printf("%u calls to drain routines\n", (unsigned int)mbstat
.m_drain
);
271 mbpr_state(int state
)
296 mbpr_mem(u_int32_t bytes
)
302 (void) snprintf(buf
, sizeof (buf
), "%d", (int)mem
);
303 } else if ((mem
/= 1024) < 1024) {
304 (void) snprintf(buf
, sizeof (buf
), "%.1f KB", mem
);
307 (void) snprintf(buf
, sizeof (buf
), "%.1f MB", mem
);
318 if (nmbtypes
!= 256) {
319 (void) fprintf(stderr
,
320 "netstat: unexpected change to mbstat; check source\n");
324 len
= sizeof(mbstat
);
325 if (sysctlbyname("kern.ipc.mbstat", &mbstat
, &len
, 0, 0) == -1)
328 if (sysctlbyname(KERN_IPC_MB_STAT
, NULL
, &len
, 0, 0) == -1) {
329 (void) fprintf(stderr
,
330 "Error retrieving length for %s\n", KERN_IPC_MB_STAT
);
334 mb_stat
= calloc(1, len
);
335 if (mb_stat
== NULL
) {
336 (void) fprintf(stderr
,
337 "Error allocating %lu bytes for sysctl data\n", len
);
341 if (sysctlbyname(KERN_IPC_MB_STAT
, mb_stat
, &len
, 0, 0) == -1) {
342 (void) fprintf(stderr
,
343 "Error %d getting %s\n", errno
, KERN_IPC_MB_STAT
);
347 if (mb_stat
->mbs_cnt
== 0) {
348 (void) fprintf(stderr
,
349 "Invalid mbuf class count (%d)\n", mb_stat
->mbs_cnt
);
354 (void) sysctlbyname(KERN_IPC_NJCL
, &njcl
, &len
, 0, 0);
355 len
= sizeof (njclbytes
);
356 (void) sysctlbyname(KERN_IPC_NJCL_BYTES
, &njclbytes
, &len
, 0, 0);
361 if (error
!= 0 && mb_stat
!= NULL
)