Hi, After some changes in the way mbuf cluster pool limits are set up, we have a situation where the "max" number doesn't reflect what it used to and is ambiguous most of the time. Right now I have:
36/144/64 mbuf 2048 byte clusters in use (current/peak/max) 0/45/120 mbuf 2112 byte clusters in use (current/peak/max) 256/312/64 mbuf 4096 byte clusters in use (current/peak/max) 0/40/64 mbuf 8192 byte clusters in use (current/peak/max) 0/14/112 mbuf 9216 byte clusters in use (current/peak/max) 0/30/80 mbuf 12288 byte clusters in use (current/peak/max) 0/40/64 mbuf 16384 byte clusters in use (current/peak/max) 0/40/64 mbuf 65536 byte clusters in use (current/peak/max) Several users expressed their concern regarding this and I agree that this was one of the important metrics that we used to look at. Now that kern.maxclusters defines how much memory (in 2k chunks) in total can be spent on (all) clusters, there's no well defined maximum value for each individual pool as they share this global limit. But we shouldn't provide values that are misinterpreted by users. Here's my take on how to improve the situation. One line in the "netstat -m" output talks about memory usage: 5748 Kbytes allocated to network (21% in use) This shows how much backing memory has been allocated by all cluster pools from the UVM and percentage of how much of it has been taken out by pool_get operations. I think we can extend this by adding an additional number for the upper boundary (kern.maxclusters), like so: saru:usr.bin/netstat% ./obj/netstat -m 539 mbufs in use: 385 mbufs allocated to data 13 mbufs allocated to packet headers 141 mbufs allocated to socket names and addresses 19/144 mbuf 2048 byte clusters in use (current/peak) 0/45 mbuf 2112 byte clusters in use (current/peak) 256/312 mbuf 4096 byte clusters in use (current/peak) 0/48 mbuf 8192 byte clusters in use (current/peak) 0/28 mbuf 9216 byte clusters in use (current/peak) 0/40 mbuf 12288 byte clusters in use (current/peak) 0/40 mbuf 16384 byte clusters in use (current/peak) 0/40 mbuf 65536 byte clusters in use (current/peak) 5876 out of 524288 Kbytes allocated to network (20% in use) 0 requests for memory denied 0 requests for memory delayed 0 calls to protocol drain routines I gather this isn't very friendly towards existing scripts parsing this output, but YMMV. diff --git usr.bin/netstat/mbuf.c usr.bin/netstat/mbuf.c index f7970a57c32..701385b2e6b 100644 --- usr.bin/netstat/mbuf.c +++ usr.bin/netstat/mbuf.c @@ -86,11 +86,11 @@ bool seen[256]; /* "have we seen this type yet?" */ */ void mbpr(void) { unsigned long totmem, totused, totmbufs; - int totpct; + int maxclusters, totpct; int i, mib[4], npools; struct kinfo_pool pool; struct mbtypes *mp; size_t size; @@ -99,10 +99,20 @@ mbpr(void) "%s: unexpected change to mbstat; check source\n", __progname); return; } + mib[0] = CTL_KERN; + mib[1] = KERN_MAXCLUSTERS; + size = sizeof(maxclusters); + + if (sysctl(mib, 2, &maxclusters, &size, NULL, 0) < 0) { + printf("Can't retrieve value of maxclusters from the " + "kernel: %s\n", strerror(errno)); + return; + } + mib[0] = CTL_KERN; mib[1] = KERN_MBSTAT; size = sizeof(mbstat); if (sysctl(mib, 2, &mbstat, &size, NULL, 0) < 0) { @@ -176,24 +186,23 @@ mbpr(void) plural(mbstat.m_mtypes[i]), i); } totmem = (mbpool.pr_npages * mbpool.pr_pgsize); totused = mbpool.pr_nout * mbpool.pr_size; for (i = 0; i < mclp; i++) { - printf("%u/%lu/%lu mbuf %d byte clusters in use" - " (current/peak/max)\n", + printf("%u/%lu mbuf %d byte clusters in use" + " (current/peak)\n", mclpools[i].pr_nout, (unsigned long) (mclpools[i].pr_hiwat * mclpools[i].pr_itemsperpage), - (unsigned long) - (mclpools[i].pr_maxpages * mclpools[i].pr_itemsperpage), mclpools[i].pr_size); totmem += (mclpools[i].pr_npages * mclpools[i].pr_pgsize); totused += mclpools[i].pr_nout * mclpools[i].pr_size; } totpct = (totmem == 0) ? 0 : (totused/(totmem / 100)); - printf("%lu Kbytes allocated to network (%d%% in use)\n", - totmem / 1024, totpct); + printf("%lu out of %lu Kbytes allocated to network (%d%% in use)\n", + totmem / 1024, (unsigned long)(maxclusters * MCLBYTES) / 1024, + totpct); printf("%lu requests for memory denied\n", mbstat.m_drops); printf("%lu requests for memory delayed\n", mbstat.m_wait); printf("%lu calls to protocol drain routines\n", mbstat.m_drain); }