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);
 }

Reply via email to