/usr.bin/netstat/mbuf.c

https://bitbucket.org/freebsd/freebsd-head/ · C · 313 lines · 220 code · 28 blank · 65 comment · 28 complexity · 3e522ec694a15586f7899edabe4d0765 MD5 · raw file

  1. /*-
  2. * Copyright (c) 1983, 1988, 1993
  3. * The Regents of the University of California.
  4. * Copyright (c) 2005 Robert N. M. Watson
  5. * All rights reserved.
  6. *
  7. * Redistribution and use in source and binary forms, with or without
  8. * modification, are permitted provided that the following conditions
  9. * are met:
  10. * 1. Redistributions of source code must retain the above copyright
  11. * notice, this list of conditions and the following disclaimer.
  12. * 2. Redistributions in binary form must reproduce the above copyright
  13. * notice, this list of conditions and the following disclaimer in the
  14. * documentation and/or other materials provided with the distribution.
  15. * 3. All advertising materials mentioning features or use of this software
  16. * must display the following acknowledgement:
  17. * This product includes software developed by the University of
  18. * California, Berkeley and its contributors.
  19. * 4. Neither the name of the University nor the names of its contributors
  20. * may be used to endorse or promote products derived from this software
  21. * without specific prior written permission.
  22. *
  23. * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
  24. * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  25. * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  26. * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
  27. * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  28. * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  29. * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  30. * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  31. * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  32. * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  33. * SUCH DAMAGE.
  34. */
  35. #if 0
  36. #ifndef lint
  37. static char sccsid[] = "@(#)mbuf.c 8.1 (Berkeley) 6/6/93";
  38. #endif /* not lint */
  39. #endif
  40. #include <sys/cdefs.h>
  41. __FBSDID("$FreeBSD$");
  42. #include <sys/param.h>
  43. #include <sys/mbuf.h>
  44. #include <sys/protosw.h>
  45. #include <sys/socket.h>
  46. #include <sys/socketvar.h>
  47. #include <sys/sysctl.h>
  48. #include <err.h>
  49. #include <kvm.h>
  50. #include <memstat.h>
  51. #include <stdint.h>
  52. #include <stdio.h>
  53. #include <stdlib.h>
  54. #include <string.h>
  55. #include "netstat.h"
  56. /*
  57. * Print mbuf statistics.
  58. */
  59. void
  60. mbpr(void *kvmd, u_long mbaddr)
  61. {
  62. struct memory_type_list *mtlp;
  63. struct memory_type *mtp;
  64. uintmax_t mbuf_count, mbuf_bytes, mbuf_free, mbuf_failures, mbuf_size;
  65. uintmax_t cluster_count, cluster_bytes, cluster_limit, cluster_free;
  66. uintmax_t cluster_failures, cluster_size;
  67. uintmax_t packet_count, packet_bytes, packet_free, packet_failures;
  68. uintmax_t tag_count, tag_bytes;
  69. uintmax_t jumbop_count, jumbop_bytes, jumbop_limit, jumbop_free;
  70. uintmax_t jumbop_failures, jumbop_size;
  71. uintmax_t jumbo9_count, jumbo9_bytes, jumbo9_limit, jumbo9_free;
  72. uintmax_t jumbo9_failures, jumbo9_size;
  73. uintmax_t jumbo16_count, jumbo16_bytes, jumbo16_limit, jumbo16_free;
  74. uintmax_t jumbo16_failures, jumbo16_size;
  75. uintmax_t bytes_inuse, bytes_incache, bytes_total;
  76. int nsfbufs, nsfbufspeak, nsfbufsused;
  77. struct mbstat mbstat;
  78. size_t mlen;
  79. int error;
  80. mtlp = memstat_mtl_alloc();
  81. if (mtlp == NULL) {
  82. warn("memstat_mtl_alloc");
  83. return;
  84. }
  85. /*
  86. * Use memstat_*_all() because some mbuf-related memory is in uma(9),
  87. * and some malloc(9).
  88. */
  89. if (live) {
  90. if (memstat_sysctl_all(mtlp, 0) < 0) {
  91. warnx("memstat_sysctl_all: %s",
  92. memstat_strerror(memstat_mtl_geterror(mtlp)));
  93. goto out;
  94. }
  95. } else {
  96. if (memstat_kvm_all(mtlp, kvmd) < 0) {
  97. error = memstat_mtl_geterror(mtlp);
  98. if (error == MEMSTAT_ERROR_KVM)
  99. warnx("memstat_kvm_all: %s",
  100. kvm_geterr(kvmd));
  101. else
  102. warnx("memstat_kvm_all: %s",
  103. memstat_strerror(error));
  104. goto out;
  105. }
  106. }
  107. mtp = memstat_mtl_find(mtlp, ALLOCATOR_UMA, MBUF_MEM_NAME);
  108. if (mtp == NULL) {
  109. warnx("memstat_mtl_find: zone %s not found", MBUF_MEM_NAME);
  110. goto out;
  111. }
  112. mbuf_count = memstat_get_count(mtp);
  113. mbuf_bytes = memstat_get_bytes(mtp);
  114. mbuf_free = memstat_get_free(mtp);
  115. mbuf_failures = memstat_get_failures(mtp);
  116. mbuf_size = memstat_get_size(mtp);
  117. mtp = memstat_mtl_find(mtlp, ALLOCATOR_UMA, MBUF_PACKET_MEM_NAME);
  118. if (mtp == NULL) {
  119. warnx("memstat_mtl_find: zone %s not found",
  120. MBUF_PACKET_MEM_NAME);
  121. goto out;
  122. }
  123. packet_count = memstat_get_count(mtp);
  124. packet_bytes = memstat_get_bytes(mtp);
  125. packet_free = memstat_get_free(mtp);
  126. packet_failures = memstat_get_failures(mtp);
  127. mtp = memstat_mtl_find(mtlp, ALLOCATOR_UMA, MBUF_CLUSTER_MEM_NAME);
  128. if (mtp == NULL) {
  129. warnx("memstat_mtl_find: zone %s not found",
  130. MBUF_CLUSTER_MEM_NAME);
  131. goto out;
  132. }
  133. cluster_count = memstat_get_count(mtp);
  134. cluster_bytes = memstat_get_bytes(mtp);
  135. cluster_limit = memstat_get_countlimit(mtp);
  136. cluster_free = memstat_get_free(mtp);
  137. cluster_failures = memstat_get_failures(mtp);
  138. cluster_size = memstat_get_size(mtp);
  139. mtp = memstat_mtl_find(mtlp, ALLOCATOR_MALLOC, MBUF_TAG_MEM_NAME);
  140. if (mtp == NULL) {
  141. warnx("memstat_mtl_find: malloc type %s not found",
  142. MBUF_TAG_MEM_NAME);
  143. goto out;
  144. }
  145. tag_count = memstat_get_count(mtp);
  146. tag_bytes = memstat_get_bytes(mtp);
  147. mtp = memstat_mtl_find(mtlp, ALLOCATOR_UMA, MBUF_JUMBOP_MEM_NAME);
  148. if (mtp == NULL) {
  149. warnx("memstat_mtl_find: zone %s not found",
  150. MBUF_JUMBOP_MEM_NAME);
  151. goto out;
  152. }
  153. jumbop_count = memstat_get_count(mtp);
  154. jumbop_bytes = memstat_get_bytes(mtp);
  155. jumbop_limit = memstat_get_countlimit(mtp);
  156. jumbop_free = memstat_get_free(mtp);
  157. jumbop_failures = memstat_get_failures(mtp);
  158. jumbop_size = memstat_get_size(mtp);
  159. mtp = memstat_mtl_find(mtlp, ALLOCATOR_UMA, MBUF_JUMBO9_MEM_NAME);
  160. if (mtp == NULL) {
  161. warnx("memstat_mtl_find: zone %s not found",
  162. MBUF_JUMBO9_MEM_NAME);
  163. goto out;
  164. }
  165. jumbo9_count = memstat_get_count(mtp);
  166. jumbo9_bytes = memstat_get_bytes(mtp);
  167. jumbo9_limit = memstat_get_countlimit(mtp);
  168. jumbo9_free = memstat_get_free(mtp);
  169. jumbo9_failures = memstat_get_failures(mtp);
  170. jumbo9_size = memstat_get_size(mtp);
  171. mtp = memstat_mtl_find(mtlp, ALLOCATOR_UMA, MBUF_JUMBO16_MEM_NAME);
  172. if (mtp == NULL) {
  173. warnx("memstat_mtl_find: zone %s not found",
  174. MBUF_JUMBO16_MEM_NAME);
  175. goto out;
  176. }
  177. jumbo16_count = memstat_get_count(mtp);
  178. jumbo16_bytes = memstat_get_bytes(mtp);
  179. jumbo16_limit = memstat_get_countlimit(mtp);
  180. jumbo16_free = memstat_get_free(mtp);
  181. jumbo16_failures = memstat_get_failures(mtp);
  182. jumbo16_size = memstat_get_size(mtp);
  183. printf("%ju/%ju/%ju mbufs in use (current/cache/total)\n",
  184. mbuf_count + packet_count, mbuf_free + packet_free,
  185. mbuf_count + packet_count + mbuf_free + packet_free);
  186. printf("%ju/%ju/%ju/%ju mbuf clusters in use "
  187. "(current/cache/total/max)\n",
  188. cluster_count - packet_free, cluster_free + packet_free,
  189. cluster_count + cluster_free, cluster_limit);
  190. printf("%ju/%ju mbuf+clusters out of packet secondary zone in use "
  191. "(current/cache)\n",
  192. packet_count, packet_free);
  193. printf("%ju/%ju/%ju/%ju %juk (page size) jumbo clusters in use "
  194. "(current/cache/total/max)\n",
  195. jumbop_count, jumbop_free, jumbop_count + jumbop_free,
  196. jumbop_limit, jumbop_size / 1024);
  197. printf("%ju/%ju/%ju/%ju 9k jumbo clusters in use "
  198. "(current/cache/total/max)\n",
  199. jumbo9_count, jumbo9_free, jumbo9_count + jumbo9_free,
  200. jumbo9_limit);
  201. printf("%ju/%ju/%ju/%ju 16k jumbo clusters in use "
  202. "(current/cache/total/max)\n",
  203. jumbo16_count, jumbo16_free, jumbo16_count + jumbo16_free,
  204. jumbo16_limit);
  205. #if 0
  206. printf("%ju mbuf tags in use\n", tag_count);
  207. #endif
  208. /*-
  209. * Calculate in-use bytes as:
  210. * - straight mbuf memory
  211. * - mbuf memory in packets
  212. * - the clusters attached to packets
  213. * - and the rest of the non-packet-attached clusters.
  214. * - m_tag memory
  215. * This avoids counting the clusters attached to packets in the cache.
  216. * This currently excludes sf_buf space.
  217. */
  218. bytes_inuse =
  219. mbuf_bytes + /* straight mbuf memory */
  220. packet_bytes + /* mbufs in packets */
  221. (packet_count * cluster_size) + /* clusters in packets */
  222. /* other clusters */
  223. ((cluster_count - packet_count - packet_free) * cluster_size) +
  224. tag_bytes +
  225. (jumbop_count * jumbop_size) + /* jumbo clusters */
  226. (jumbo9_count * jumbo9_size) +
  227. (jumbo16_count * jumbo16_size);
  228. /*
  229. * Calculate in-cache bytes as:
  230. * - cached straught mbufs
  231. * - cached packet mbufs
  232. * - cached packet clusters
  233. * - cached straight clusters
  234. * This currently excludes sf_buf space.
  235. */
  236. bytes_incache =
  237. (mbuf_free * mbuf_size) + /* straight free mbufs */
  238. (packet_free * mbuf_size) + /* mbufs in free packets */
  239. (packet_free * cluster_size) + /* clusters in free packets */
  240. (cluster_free * cluster_size) + /* free clusters */
  241. (jumbop_free * jumbop_size) + /* jumbo clusters */
  242. (jumbo9_free * jumbo9_size) +
  243. (jumbo16_free * jumbo16_size);
  244. /*
  245. * Total is bytes in use + bytes in cache. This doesn't take into
  246. * account various other misc data structures, overhead, etc, but
  247. * gives the user something useful despite that.
  248. */
  249. bytes_total = bytes_inuse + bytes_incache;
  250. printf("%juK/%juK/%juK bytes allocated to network "
  251. "(current/cache/total)\n", bytes_inuse / 1024,
  252. bytes_incache / 1024, bytes_total / 1024);
  253. printf("%ju/%ju/%ju requests for mbufs denied (mbufs/clusters/"
  254. "mbuf+clusters)\n", mbuf_failures, cluster_failures,
  255. packet_failures);
  256. printf("%ju/%ju/%ju requests for jumbo clusters denied "
  257. "(%juk/9k/16k)\n", jumbop_failures, jumbo9_failures,
  258. jumbo16_failures, jumbop_size / 1024);
  259. if (live) {
  260. mlen = sizeof(nsfbufs);
  261. if (!sysctlbyname("kern.ipc.nsfbufs", &nsfbufs, &mlen, NULL,
  262. 0) &&
  263. !sysctlbyname("kern.ipc.nsfbufsused", &nsfbufsused,
  264. &mlen, NULL, 0) &&
  265. !sysctlbyname("kern.ipc.nsfbufspeak", &nsfbufspeak,
  266. &mlen, NULL, 0))
  267. printf("%d/%d/%d sfbufs in use (current/peak/max)\n",
  268. nsfbufsused, nsfbufspeak, nsfbufs);
  269. mlen = sizeof(mbstat);
  270. if (sysctlbyname("kern.ipc.mbstat", &mbstat, &mlen, NULL, 0)) {
  271. warn("kern.ipc.mbstat");
  272. goto out;
  273. }
  274. } else {
  275. if (kread(mbaddr, (char *)&mbstat, sizeof mbstat) != 0)
  276. goto out;
  277. }
  278. printf("%lu requests for sfbufs denied\n", mbstat.sf_allocfail);
  279. printf("%lu requests for sfbufs delayed\n", mbstat.sf_allocwait);
  280. printf("%lu requests for I/O initiated by sendfile\n",
  281. mbstat.sf_iocnt);
  282. printf("%lu calls to protocol drain routines\n", mbstat.m_drain);
  283. out:
  284. memstat_mtl_free(mtlp);
  285. }