]>
git.saurik.com Git - apple/network_cmds.git/blob - netstat.tproj/mbuf.c
2 * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
4 * @APPLE_LICENSE_HEADER_START@
6 * "Portions Copyright (c) 1999 Apple Computer, Inc. All Rights
7 * Reserved. This file contains Original Code and/or Modifications of
8 * Original Code as defined in and that are subject to the Apple Public
9 * Source License Version 1.0 (the 'License'). You may not use this file
10 * except in compliance with the License. Please obtain a copy of the
11 * License at http://www.apple.com/publicsource and read it before using
14 * The Original Code and all software distributed under the License are
15 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
16 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
17 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the
19 * License for the specific language governing rights and limitations
22 * @APPLE_LICENSE_HEADER_END@
25 * Copyright (c) 1983, 1988, 1993
26 * The Regents of the University of California. All rights reserved.
28 * Redistribution and use in source and binary forms, with or without
29 * modification, are permitted provided that the following conditions
31 * 1. Redistributions of source code must retain the above copyright
32 * notice, this list of conditions and the following disclaimer.
33 * 2. Redistributions in binary form must reproduce the above copyright
34 * notice, this list of conditions and the following disclaimer in the
35 * documentation and/or other materials provided with the distribution.
36 * 3. All advertising materials mentioning features or use of this software
37 * must display the following acknowledgement:
38 * This product includes software developed by the University of
39 * California, Berkeley and its contributors.
40 * 4. Neither the name of the University nor the names of its contributors
41 * may be used to endorse or promote products derived from this software
42 * without specific prior written permission.
44 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
45 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
46 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
47 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
48 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
49 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
50 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
51 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
52 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
53 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
58 #include <sys/param.h>
59 #include <sys/socket.h>
61 #include <sys/sysctl.h>
67 #include <netat/sysglue.h> /* To get Appletalk message/mbuf types */
74 static struct mbtypes
{
79 { MT_OOBDATA
, "oob data" },
80 { MT_CONTROL
, "ancillary data" },
81 { MT_HEADER
, "packet headers" },
82 { MT_SOCKET
, "socket structures" }, /* XXX */
83 { MT_PCB
, "protocol control blocks" }, /* XXX */
84 { MT_RTABLE
, "routing table entries" }, /* XXX */
85 { MT_HTABLE
, "IMP host table entries" }, /* XXX */
86 { MT_ATABLE
, "address resolution tables" },
87 { MT_FTABLE
, "fragment reassembly queue headers" }, /* XXX */
88 { MT_SONAME
, "socket names and addresses" },
89 { MT_SOOPTS
, "socket options" },
90 { MT_RIGHTS
, "access rights" },
91 { MT_IFADDR
, "interface addresses" }, /* XXX */
92 { MT_TAG
, "packet tags" }, /* XXX */
93 { MSG_DATA
, "Appletalk data blocks"},
94 { MSG_PROTO
, "Appletalk internal msgs"},
95 { MSG_IOCTL
, "Appletalk ioctl requests"},
96 { MSG_ERROR
, "Appletalk error indicators"},
97 { MSG_HANGUP
, "Appletalk termination requests"},
98 { MSG_IOCACK
, "Appletalk ioctl acks"},
99 { MSG_IOCNAK
, "Appletalk ioctl failure indicators"},
100 { MSG_CTL
, "Appletalk control msgs"},
104 int nmbtypes
= sizeof(mbstat
.m_mtypes
) / sizeof(short);
105 bool seen
[256]; /* "have we seen this type yet?" */
108 unsigned int njcl
, njclbytes
;
110 #define KERN_IPC_MB_STAT "kern.ipc.mb_stat"
111 #define KERN_IPC_NJCL "kern.ipc.njcl"
112 #define KERN_IPC_NJCL_BYTES "kern.ipc.njclbytes"
114 #define MB_STAT_HDR1 "\
115 class buf active ctotal total cache cached uncached memory\n\
116 name size bufs bufs bufs state bufs bufs usage\n\
117 ---------- ----- -------- -------- -------- ----- -------- -------- ---------\n\
120 #define MB_STAT_HDR2 "\n\
121 class waiter notify purge wretry nwretry failure\n\
122 name count count count count count count\n\
123 ---------- -------- -------- -------- -------- -------- --------\n\
126 static const char *mbpr_state(int);
127 static const char *mbpr_mem(u_int32_t
);
128 static int mbpr_getdata(void);
131 * Print mbuf statistics.
136 unsigned long totmem
= 0, totfree
= 0, totmbufs
, totused
;
138 u_int32_t m_msize
, m_mbufs
= 0, m_clfree
= 0, m_bigclfree
= 0;
139 u_int32_t m_mbufclfree
= 0, m_mbufbigclfree
= 0;
140 u_int32_t m_16kclusters
= 0, m_16kclfree
= 0, m_mbuf16kclfree
= 0;
145 if (mbpr_getdata() != 0)
148 m_msize
= mbstat
.m_msize
;
149 cp
= &mb_stat
->mbs_class
[0];
150 for (i
= 0; i
< mb_stat
->mbs_cnt
; i
++, cp
++) {
151 if (cp
->mbcl_size
== m_msize
) {
152 m_mbufs
= cp
->mbcl_active
;
153 } else if (cp
->mbcl_size
== mbstat
.m_mclbytes
) {
154 m_clfree
= cp
->mbcl_total
- cp
->mbcl_active
;
155 } else if (cp
->mbcl_size
== mbstat
.m_bigmclbytes
) {
156 m_bigclfree
= cp
->mbcl_total
- cp
->mbcl_active
;
157 } else if (njcl
> 0 && cp
->mbcl_size
== njclbytes
) {
158 m_16kclfree
= cp
->mbcl_total
- cp
->mbcl_active
;
159 m_16kclusters
= cp
->mbcl_total
;
160 } else if (cp
->mbcl_size
== (m_msize
+ mbstat
.m_mclbytes
)) {
161 m_mbufclfree
= cp
->mbcl_total
- cp
->mbcl_active
;
162 } else if (cp
->mbcl_size
== (m_msize
+ mbstat
.m_bigmclbytes
)) {
163 m_mbufbigclfree
= cp
->mbcl_total
- cp
->mbcl_active
;
164 } else if (njcl
> 0 && cp
->mbcl_size
== (m_msize
+ njclbytes
)) {
165 m_mbuf16kclfree
= cp
->mbcl_total
- cp
->mbcl_active
;
169 /* adjust free counts to include composite caches */
170 m_clfree
+= m_mbufclfree
;
171 m_bigclfree
+= m_mbufbigclfree
;
172 m_16kclfree
+= m_mbuf16kclfree
;
174 cp
= &mb_stat
->mbs_class
[0];
175 for (i
= 0; i
< mb_stat
->mbs_cnt
; i
++, cp
++) {
178 mem
= cp
->mbcl_ctotal
* cp
->mbcl_size
;
180 totfree
+= (cp
->mbcl_mc_cached
+ cp
->mbcl_infree
) *
184 printf(MB_STAT_HDR1
);
187 cp
->mbcl_size
> (m_msize
+ mbstat
.m_bigmclbytes
))
190 printf("%-10s %5u %8u %8u %8u %5s %8u %8u %9s\n",
191 cp
->mbcl_cname
, cp
->mbcl_size
, cp
->mbcl_active
,
192 cp
->mbcl_ctotal
, cp
->mbcl_total
,
193 mbpr_state(cp
->mbcl_mc_state
), cp
->mbcl_mc_cached
,
194 cp
->mbcl_infree
, mbpr_mem(mem
));
198 cp
= &mb_stat
->mbs_class
[0];
199 for (i
= 0; i
< mb_stat
->mbs_cnt
; i
++, cp
++) {
202 printf(MB_STAT_HDR2
);
205 cp
->mbcl_size
> (m_msize
+ mbstat
.m_bigmclbytes
))
208 printf("%-10s %8u %8llu %8llu %8u %8u %8llu\n",
209 cp
->mbcl_cname
, cp
->mbcl_mc_waiter_cnt
,
210 cp
->mbcl_notified
, cp
->mbcl_purge_cnt
,
211 cp
->mbcl_mc_wretry_cnt
, cp
->mbcl_mc_nwretry_cnt
,
220 for (mp
= mbtypes
; mp
->mt_name
; mp
++)
221 totmbufs
+= mbstat
.m_mtypes
[mp
->mt_type
];
223 * These stats are not updated atomically in the kernel;
224 * adjust the total as neeeded.
226 if (totmbufs
> m_mbufs
)
228 printf("%lu/%u mbufs in use:\n", totmbufs
, m_mbufs
);
229 for (mp
= mbtypes
; mp
->mt_name
; mp
++)
230 if (mbstat
.m_mtypes
[mp
->mt_type
]) {
231 seen
[mp
->mt_type
] = YES
;
232 printf("\t%u mbufs allocated to %s\n",
233 mbstat
.m_mtypes
[mp
->mt_type
], mp
->mt_name
);
236 for (i
= 0; i
< nmbtypes
; i
++)
237 if (!seen
[i
] && mbstat
.m_mtypes
[i
]) {
238 printf("\t%u mbufs allocated to <mbuf type %d>\n",
239 mbstat
.m_mtypes
[i
], i
);
241 if ((m_mbufs
- totmbufs
) > 0)
242 printf("\t%lu mbufs allocated to caches\n",
244 printf("%u/%u mbuf 2KB clusters in use\n",
245 (unsigned int)(mbstat
.m_clusters
- m_clfree
),
246 (unsigned int)mbstat
.m_clusters
);
247 printf("%u/%u mbuf 4KB clusters in use\n",
248 (unsigned int)(mbstat
.m_bigclusters
- m_bigclfree
),
249 (unsigned int)mbstat
.m_bigclusters
);
251 printf("%u/%u mbuf %uKB clusters in use\n",
252 m_16kclusters
- m_16kclfree
, m_16kclusters
,
255 totused
= totmem
- totfree
;
258 else if (totused
< (ULONG_MAX
/100))
259 totpct
= (totused
* 100)/(double)totmem
;
261 u_long totmem1
= totmem
/100;
262 u_long totused1
= totused
/100;
263 totpct
= (totused1
* 100)/(double)totmem1
;
265 printf("%lu KB allocated to network (%.1f%% in use)\n",
266 totmem
/ 1024, totpct
);
268 printf("%u requests for memory denied\n", (unsigned int)mbstat
.m_drops
);
269 printf("%u requests for memory delayed\n", (unsigned int)mbstat
.m_wait
);
270 printf("%u calls to drain routines\n", (unsigned int)mbstat
.m_drain
);
276 mbpr_state(int state
)
301 mbpr_mem(u_int32_t bytes
)
307 (void) snprintf(buf
, sizeof (buf
), "%d", (int)mem
);
308 } else if ((mem
/= 1024) < 1024) {
309 (void) snprintf(buf
, sizeof (buf
), "%.1f KB", mem
);
312 (void) snprintf(buf
, sizeof (buf
), "%.1f MB", mem
);
323 if (nmbtypes
!= 256) {
324 (void) fprintf(stderr
,
325 "netstat: unexpected change to mbstat; check source\n");
329 len
= sizeof(mbstat
);
330 if (sysctlbyname("kern.ipc.mbstat", &mbstat
, &len
, 0, 0) == -1)
333 if (sysctlbyname(KERN_IPC_MB_STAT
, NULL
, &len
, 0, 0) == -1) {
334 (void) fprintf(stderr
,
335 "Error retrieving length for %s\n", KERN_IPC_MB_STAT
);
339 mb_stat
= calloc(1, len
);
340 if (mb_stat
== NULL
) {
341 (void) fprintf(stderr
,
342 "Error allocating %lu bytes for sysctl data\n", len
);
346 if (sysctlbyname(KERN_IPC_MB_STAT
, mb_stat
, &len
, 0, 0) == -1) {
347 (void) fprintf(stderr
,
348 "Error %d getting %s\n", errno
, KERN_IPC_MB_STAT
);
352 if (mb_stat
->mbs_cnt
== 0) {
353 (void) fprintf(stderr
,
354 "Invalid mbuf class count (%d)\n", mb_stat
->mbs_cnt
);
359 (void) sysctlbyname(KERN_IPC_NJCL
, &njcl
, &len
, 0, 0);
360 len
= sizeof (njclbytes
);
361 (void) sysctlbyname(KERN_IPC_NJCL_BYTES
, &njclbytes
, &len
, 0, 0);
366 if (error
!= 0 && mb_stat
!= NULL
)