Matthew's UCD-DISKIO-MIB patch got me interested in adding support for
the UCD-SNMP-MIB in snmpd. This is a first pass and only covers the
mem* objects. I'd appreciate it if someone who knows more than me
about the uvm sysctls could check it over; specifically, the
memShared, memBuffers, and memCached objects. Net-SNMP doesn't define
those objects for NetBSD, but I wanted to take a stab and implementing
them if possible, so I did some research (and yes, a little guesswork)
and came up with something that seems to work. (Actually, the
memShared code came from the net-snmp code for FreeBSD.)
I've got this running on a Zenoss-monitored server right now and the
stats look right, but I'd appreciate it if other SNMP users could test
it out, too.
$ snmpwalk -v2c -c[...] it-mirror1 .1.3.6.1.4.1.2021.4
UCD-SNMP-MIB::memIndex.0 = INTEGER: 0
UCD-SNMP-MIB::memErrorName.0 = STRING: swap
UCD-SNMP-MIB::memTotalSwap.0 = INTEGER: 6851384
UCD-SNMP-MIB::memAvailSwap.0 = INTEGER: 6851384
UCD-SNMP-MIB::memTotalReal.0 = INTEGER: 20965696
UCD-SNMP-MIB::memAvailReal.0 = INTEGER: 16962728
UCD-SNMP-MIB::memTotalFree.0 = INTEGER: 23814112
UCD-SNMP-MIB::memMinimumSwap.0 = INTEGER: 16000
UCD-SNMP-MIB::memShared.0 = INTEGER: 0
UCD-SNMP-MIB::memBuffer.0 = INTEGER: 0
UCD-SNMP-MIB::memCached.0 = INTEGER: 2593976
UCD-SNMP-MIB::memSwapError.0 = INTEGER: 0
UCD-SNMP-MIB::memSwapErrorMsg.0 = STRING:
ok?
Index: mib.c
===================================================================
RCS file: /cvs/src/usr.sbin/snmpd/mib.c,v
retrieving revision 1.54
diff -u -p -r1.54 mib.c
--- mib.c 14 Jun 2012 17:31:32 -0000 1.54
+++ mib.c 16 Jun 2012 19:29:51 -0000
@@ -3364,6 +3364,131 @@ mib_ipfroute(struct oid *oid, struct ber
}
/*
+ * Defined in UCD-SNMP-MIB.txt
+ */
+
+int mib_ucdmemory(struct oid *oid, struct ber_oid *o, struct
ber_element **elm);
+
+static struct oid ucdmemory_mib[] = {
+ { MIB(ucdMemory), OID_MIB },
+ { MIB(memIndex), OID_RD, mib_ucdmemory },
+ { MIB(memErrorName), OID_RD, mib_ucdmemory },
+ { MIB(memTotalSwap), OID_RD, mib_ucdmemory },
+ { MIB(memAvailSwap), OID_RD, mib_ucdmemory },
+ { MIB(memTotalReal), OID_RD, mib_ucdmemory },
+ { MIB(memAvailReal), OID_RD, mib_ucdmemory },
+ { MIB(memTotalFree), OID_RD, mib_ucdmemory },
+ { MIB(memMinimumSwap), OID_RD, mib_ucdmemory },
+ { MIB(memShared), OID_RD, mib_ucdmemory },
+ { MIB(memBuffer), OID_RD, mib_ucdmemory },
+ { MIB(memCached), OID_RD, mib_ucdmemory },
+ { MIB(memSwapError), OID_RD, mib_ucdmemory },
+ { MIB(memSwapErrorMsg), OID_RD, mib_ucdmemory },
+ { MIBEND }
+};
+
+/* Taken from net-snmp */
+#define DEFAULTMINIMUMSWAP 16000
+
+int
+mib_ucdmemory(struct oid *oid, struct ber_oid *o, struct ber_element **elm)
+{
+ struct ber_element *ber = *elm;
+ struct bcachestats bcstats;
+ struct uvmexp uvm;
+ struct vmtotal vmmeter;
+ u_int64_t physmem;
+ size_t len;
+ int mib[] = { CTL_VM, VM_UVMEXP };
+ int bcstats_mib[] = { CTL_VFS, VFS_GENERIC,
VFS_BCACHESTAT };
+ int size, inuse, total;
+
+ len = sizeof(uvm);
+ if (sysctl(mib, sizeofa(mib), &uvm, &len, NULL, 0) == -1)
+ return (-1);
+
+ mib[1] = VM_METER;
+ len = sizeof(vmmeter);
+ if (sysctl(mib, sizeofa(mib), &vmmeter, &len, NULL, 0) == -1)
+ return (-1);
+
+ mib[0] = CTL_HW;
+ mib[1] = HW_PHYSMEM64;
+ len = sizeof(physmem);
+ if (sysctl(mib, sizeofa(mib), &physmem, &len, NULL, 0) == -1)
+ return (-1);
+
+ len = sizeof(bcstats);
+ if (sysctl(bcstats_mib, sizeofa(bcstats_mib), &bcstats, &len, NULL, 0)
== -1)
+ return (-1);
+
+#define ptok(p) ((p) * (uvm.pagesize >> 10))
+
+ switch (o->bo_id[OIDIDX_ucdMemory]) {
+ case 1: /* memIndex */
+ ber = ber_add_integer(ber, 0);
+ break;
+ case 2: /* memErrorName */
+ ber = ber_add_string(ber, "swap");
+ break;
+ case 3: /* memTotalSwap */
+ size = ptok(uvm.swpages);
+ ber = ber_add_integer(ber, size);
+ break;
+ case 4: /* memAvailSwap */
+ inuse = ptok(uvm.swpginuse);
+ total = ptok(uvm.swpages);
+ ber = ber_add_integer(ber, total - inuse);
+ break;
+ case 5: /* memTotalReal */
+ size = physmem >> 10;
+ ber = ber_add_integer(ber, size);
+ break;
+ case 6: /* memAvailReal */
+ ber = ber_add_integer(ber, ptok(uvm.free));
+ break;
+ case 11: /* memTotalFree */
+ total = ptok(uvm.free + uvm.swpages - uvm.swpginuse);
+ ber = ber_add_integer(ber, total);
+ break;
+ case 12: /* memMinimumSwap */
+ ber = ber_add_integer(ber, DEFAULTMINIMUMSWAP);
+ break;
+ case 13: /* memShared */
+ total = ptok(vmmeter.t_vmshr + vmmeter.t_avmshr +
+ vmmeter.t_rmshr + vmmeter.t_armshr);
+ ber = ber_add_integer(ber, total);
+ break;
+ case 14: /* memBuffer */
+ ber = ber_add_integer(ber, ptok(uvm.vnodepages));
+ break;
+ case 15: /* memCached */
+ ber = ber_add_integer(ber, ptok(bcstats.numbufpages));
+ break;
+ case 100: /* memSwapError */
+ inuse = ptok(uvm.swpginuse);
+ total = ptok(uvm.swpages);
+ if ((total - inuse) < DEFAULTMINIMUMSWAP)
+ ber = ber_add_integer(ber, 1);
+ else
+ ber = ber_add_integer(ber, 0);
+ break;
+ case 101: /* memSwapErrorMsg */
+ inuse = ptok(uvm.swpginuse);
+ total = ptok(uvm.swpages);
+ if ((total - inuse) < DEFAULTMINIMUMSWAP)
+ ber = ber_add_string(ber, "Running out of swap space");
+ else
+ ber = ber_add_string(ber, "");
+ break;
+ default:
+ return (-1);
+ }
+
+ return (0);
+}
+
+/*
* Defined in UCD-DISKIO-MIB.txt.
*/
@@ -3546,6 +3671,9 @@ mib_init(void)
/* BRIDGE-MIB */
smi_mibtree(bridge_mib);
+
+ /* UCD-SNMP-MIB */
+ smi_mibtree(ucdmemory_mib);
/* UCD-DISKIO-MIB */
smi_mibtree(diskio_mib);
Index: mib.h
===================================================================
RCS file: /cvs/src/usr.sbin/snmpd/mib.h,v
retrieving revision 1.26
diff -u -p -r1.26 mib.h
--- mib.h 14 Jun 2012 17:31:32 -0000 1.26
+++ mib.h 16 Jun 2012 19:29:51 -0000
@@ -397,6 +397,23 @@
#define MIB_vantronix MIB_enterprises, 26766
#define MIB_openBSD MIB_enterprises, 30155
+/* UCD-SNMP-MIB */
+#define MIB_ucdMemory MIB_ucDavis, 4
+#define OIDIDX_ucdMemory 8
+#define MIB_memIndex MIB_ucdMemory, 1
+#define MIB_memErrorName MIB_ucdMemory, 2
+#define MIB_memTotalSwap MIB_ucdMemory, 3
+#define MIB_memAvailSwap MIB_ucdMemory, 4
+#define MIB_memTotalReal MIB_ucdMemory, 5
+#define MIB_memAvailReal MIB_ucdMemory, 6
+#define MIB_memTotalFree MIB_ucdMemory, 11
+#define MIB_memMinimumSwap MIB_ucdMemory, 12
+#define MIB_memShared MIB_ucdMemory, 13
+#define MIB_memBuffer MIB_ucdMemory, 14
+#define MIB_memCached MIB_ucdMemory, 15
+#define MIB_memSwapError MIB_ucdMemory, 100
+#define MIB_memSwapErrorMsg MIB_ucdMemory, 101
+
/* UCD-DISKIO-MIB */
#define MIB_ucdExperimental MIB_ucDavis, 13
#define MIB_ucdDiskIOMIB MIB_ucdExperimental, 15
@@ -908,6 +925,21 @@
{ MIBDECL(microSystems) }, \
{ MIBDECL(vantronix) }, \
{ MIBDECL(openBSD) }, \
+ \
+ { MIBDECL(ucdMemory) }, \
+ { MIBDECL(memIndex) }, \
+ { MIBDECL(memErrorName) }, \
+ { MIBDECL(memTotalSwap) }, \
+ { MIBDECL(memAvailSwap) }, \
+ { MIBDECL(memTotalReal) }, \
+ { MIBDECL(memAvailReal) }, \
+ { MIBDECL(memTotalFree) }, \
+ { MIBDECL(memMinimumSwap) }, \
+ { MIBDECL(memShared) }, \
+ { MIBDECL(memBuffer) }, \
+ { MIBDECL(memCached) }, \
+ { MIBDECL(memSwapError) }, \
+ { MIBDECL(memSwapErrorMsg) }, \
\
{ MIBDECL(ucdExperimental) }, \
{ MIBDECL(ucdDiskIOMIB) }, \