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) }, \