Blame agent/mibgroup/hardware/memory/memory_linux.c.memory-reporting

Packit a30ac4
#include <net-snmp/net-snmp-config.h>
Packit a30ac4
#include <net-snmp/net-snmp-includes.h>
Packit a30ac4
#include <net-snmp/agent/net-snmp-agent-includes.h>
Packit a30ac4
#include <net-snmp/agent/hardware/memory.h>
Packit a30ac4
Packit a30ac4
#include <unistd.h>
Packit a30ac4
#include <fcntl.h>
Packit a30ac4
Packit a30ac4
/*
Packit a30ac4
 * Try to use an initial size that will cover default cases. We aren't talking
Packit a30ac4
 * about huge files, so why fiddle about with reallocs?
Packit a30ac4
 * I checked /proc/meminfo sizes on 3 different systems: 598, 644, 654
Packit a30ac4
 * 
Packit a30ac4
 * On newer systems, the size is up to around 930 (2.6.27 kernel)
Packit a30ac4
 *   or 1160  (2.6.28 kernel)
Packit a30ac4
 */
Packit a30ac4
#define MEMINFO_INIT_SIZE   1279
Packit a30ac4
#define MEMINFO_STEP_SIZE   256
Packit a30ac4
#define MEMINFO_FILE   "/proc/meminfo"
Packit a30ac4
Packit a30ac4
    /*
Packit a30ac4
     * Load the latest memory usage statistics
Packit a30ac4
     */
Packit a30ac4
int netsnmp_mem_arch_load( netsnmp_cache *cache, void *magic ) {
Packit a30ac4
    int          statfd;
Packit a30ac4
    static char *buff  = NULL;
Packit a30ac4
    static int   bsize = 0;
Packit a30ac4
    static int   first = 1;
Packit a30ac4
    ssize_t      bytes_read;
Packit a30ac4
    char        *b;
Packit a30ac4
    unsigned long memtotal = 0,  memfree = 0, memshared = 0,
Packit a30ac4
                  buffers = 0,   cached = 0,
Packit a30ac4
                  swaptotal = 0, swapfree = 0;
Packit a30ac4
Packit a30ac4
    netsnmp_memory_info *mem;
Packit a30ac4
Packit a30ac4
    /*
Packit a30ac4
     * Retrieve the memory information from the underlying O/S...
Packit a30ac4
     */
Packit a30ac4
    if ((statfd = open(MEMINFO_FILE, O_RDONLY, 0)) == -1) {
Packit a30ac4
        snmp_log_perror(MEMINFO_FILE);
Packit a30ac4
        return -1;
Packit a30ac4
    }
Packit a30ac4
    if (bsize == 0) {
Packit a30ac4
        bsize = MEMINFO_INIT_SIZE;
Packit a30ac4
        buff = (char*)malloc(bsize+1);
Packit a30ac4
        if (NULL == buff) {
Packit a30ac4
            snmp_log(LOG_ERR, "malloc failed\n");
Packit a30ac4
            close(statfd);
Packit a30ac4
            return -1;
Packit a30ac4
        }
Packit a30ac4
    }
Packit a30ac4
    while ((bytes_read = read(statfd, buff, bsize)) == bsize) {
Packit a30ac4
        b = (char*)realloc(buff, bsize + MEMINFO_STEP_SIZE + 1);
Packit a30ac4
        if (NULL == b) {
Packit a30ac4
            snmp_log(LOG_ERR, "malloc failed\n");
Packit a30ac4
            close(statfd);
Packit a30ac4
            return -1;
Packit a30ac4
        }
Packit a30ac4
        buff = b;
Packit a30ac4
        bsize += MEMINFO_STEP_SIZE;
Packit a30ac4
        DEBUGMSGTL(("mem", "/proc/meminfo buffer increased to %d\n", bsize));
Packit a30ac4
        close(statfd);
Packit a30ac4
        statfd = open(MEMINFO_FILE, O_RDONLY, 0);
Packit a30ac4
        if (statfd == -1) {
Packit a30ac4
            snmp_log_perror(MEMINFO_FILE);
Packit a30ac4
            return -1;
Packit a30ac4
        }
Packit a30ac4
    }
Packit a30ac4
    close(statfd);
Packit a30ac4
    if (bytes_read <= 0) {
Packit a30ac4
        snmp_log_perror(MEMINFO_FILE);
Packit a30ac4
        buff[0] = '\0';
Packit a30ac4
    } else {
Packit a30ac4
        buff[bytes_read] = '\0';
Packit a30ac4
    }
Packit a30ac4
Packit a30ac4
    /*
Packit a30ac4
     * ... parse this into a more useable form...
Packit a30ac4
     */
Packit a30ac4
    b = strstr(buff, "MemTotal: ");
Packit a30ac4
    if (b) 
Packit a30ac4
        sscanf(b, "MemTotal: %lu", &memtotal);
Packit a30ac4
    else {
Packit a30ac4
        if (first)
Packit a30ac4
            snmp_log(LOG_ERR, "No MemTotal line in /proc/meminfo\n");
Packit a30ac4
    }
Packit a30ac4
    b = strstr(buff, "MemFree: ");
Packit a30ac4
    if (b) 
Packit a30ac4
        sscanf(b, "MemFree: %lu", &memfree);
Packit a30ac4
    else {
Packit a30ac4
        if (first)
Packit a30ac4
            snmp_log(LOG_ERR, "No MemFree line in /proc/meminfo\n");
Packit a30ac4
    }
Packit a30ac4
    if (0 == netsnmp_os_prematch("Linux","2.4")) {
Packit a30ac4
        b = strstr(buff, "MemShared: ");
Packit a30ac4
        if (b)
Packit a30ac4
            sscanf(b, "MemShared: %lu", &memshared);
Packit a30ac4
        else if (first)
Packit a30ac4
            snmp_log(LOG_ERR, "No MemShared line in /proc/meminfo\n");
Packit a30ac4
    }
Packit a30ac4
    else {
Packit a30ac4
        b = strstr(buff, "Shmem: ");
Packit a30ac4
        if (b)
Packit a30ac4
            sscanf(b, "Shmem: %lu", &memshared);
Packit a30ac4
        else if (first)
Packit a30ac4
            snmp_log(LOG_ERR, "No Shmem line in /proc/meminfo\n");
Packit a30ac4
    }
Packit a30ac4
    b = strstr(buff, "Buffers: ");
Packit a30ac4
    if (b)
Packit a30ac4
        sscanf(b, "Buffers: %lu", &buffers);
Packit a30ac4
    else {
Packit a30ac4
        if (first)
Packit a30ac4
            snmp_log(LOG_ERR, "No Buffers line in /proc/meminfo\n");
Packit a30ac4
    }
Packit a30ac4
    b = strstr(buff, "Cached: ");
Packit a30ac4
    if (b)
Packit a30ac4
        sscanf(b, "Cached: %lu", &cached);
Packit a30ac4
    else {
Packit a30ac4
        if (first)
Packit a30ac4
            snmp_log(LOG_ERR, "No Cached line in /proc/meminfo\n");
Packit a30ac4
    }
Packit a30ac4
    b = strstr(buff, "SwapTotal: ");
Packit a30ac4
    if (b)
Packit a30ac4
        sscanf(b, "SwapTotal: %lu", &swaptotal);
Packit a30ac4
    else {
Packit a30ac4
        if (first)
Packit a30ac4
            snmp_log(LOG_ERR, "No SwapTotal line in /proc/meminfo\n");
Packit a30ac4
    }
Packit a30ac4
    b = strstr(buff, "SwapFree: ");
Packit a30ac4
    if (b)
Packit a30ac4
        sscanf(b, "SwapFree: %lu", &swapfree);
Packit a30ac4
    else {
Packit a30ac4
        if (first)
Packit a30ac4
            snmp_log(LOG_ERR, "No SwapFree line in /proc/meminfo\n");
Packit a30ac4
    }
Packit a30ac4
    first = 0;
Packit a30ac4
Packit a30ac4
Packit a30ac4
    /*
Packit a30ac4
     * ... and save this in a standard form.
Packit a30ac4
     */
Packit a30ac4
    mem = netsnmp_memory_get_byIdx( NETSNMP_MEM_TYPE_PHYSMEM, 1 );
Packit a30ac4
    if (!mem) {
Packit a30ac4
        snmp_log_perror("No Physical Memory info entry");
Packit a30ac4
    } else {
Packit a30ac4
        if (!mem->descr)
Packit a30ac4
             mem->descr = strdup("Physical memory");
Packit a30ac4
        mem->units = 1024;
Packit a30ac4
        mem->size  = memtotal;
Packit a30ac4
        mem->free  = memfree;
Packit a30ac4
        mem->other = -1;
Packit a30ac4
    }
Packit a30ac4
Packit a30ac4
    mem = netsnmp_memory_get_byIdx( NETSNMP_MEM_TYPE_VIRTMEM, 1 );
Packit a30ac4
    if (!mem) {
Packit a30ac4
        snmp_log_perror("No Virtual Memory info entry");
Packit a30ac4
    } else {
Packit a30ac4
        if (!mem->descr)
Packit a30ac4
             mem->descr = strdup("Virtual memory");
Packit a30ac4
        mem->units = 1024;
Packit a30ac4
        mem->size  = memtotal+swaptotal;
Packit a30ac4
        mem->free  = memfree +swapfree;
Packit a30ac4
        mem->other = -1;
Packit a30ac4
    }
Packit a30ac4
Packit a30ac4
    mem = netsnmp_memory_get_byIdx( NETSNMP_MEM_TYPE_SHARED, 1 );
Packit a30ac4
    if (!mem) {
Packit a30ac4
        snmp_log_perror("No Shared Memory info entry");
Packit a30ac4
    } else {
Packit a30ac4
        if (!mem->descr)
Packit a30ac4
             mem->descr = strdup("Shared memory");
Packit a30ac4
        mem->units = 1024;
Packit a30ac4
        mem->size  = memshared;
Packit a30ac4
        mem->free  = 0;    /* All in use */
Packit a30ac4
        mem->other = -1;
Packit a30ac4
    }
Packit a30ac4
Packit a30ac4
    mem = netsnmp_memory_get_byIdx( NETSNMP_MEM_TYPE_CACHED, 1 );
Packit a30ac4
    if (!mem) {
Packit a30ac4
        snmp_log_perror("No Cached Memory info entry");
Packit a30ac4
    } else {
Packit a30ac4
        if (!mem->descr)
Packit a30ac4
             mem->descr = strdup("Cached memory");
Packit a30ac4
        mem->units = 1024;
Packit a30ac4
        mem->size  = cached;
Packit a30ac4
        mem->free  = 0;     /* Report cached size/used as equal */
Packit a30ac4
        mem->other = -1;
Packit a30ac4
    }
Packit a30ac4
Packit a30ac4
    mem = netsnmp_memory_get_byIdx( NETSNMP_MEM_TYPE_SWAP, 1 );
Packit a30ac4
    if (!mem) {
Packit a30ac4
        snmp_log_perror("No Swap info entry");
Packit a30ac4
    } else {
Packit a30ac4
        if (!mem->descr)
Packit a30ac4
             mem->descr = strdup("Swap space");
Packit a30ac4
        mem->units = 1024;
Packit a30ac4
        mem->size  = swaptotal;
Packit a30ac4
        mem->free  = swapfree;
Packit a30ac4
        mem->other = -1;
Packit a30ac4
    }
Packit a30ac4
Packit a30ac4
    mem = netsnmp_memory_get_byIdx( NETSNMP_MEM_TYPE_MBUF, 1 );
Packit a30ac4
    if (!mem) {
Packit a30ac4
        snmp_log_perror("No Buffer, etc info entry");
Packit a30ac4
    } else {
Packit a30ac4
        if (!mem->descr)
Packit a30ac4
             mem->descr = strdup("Memory buffers");
Packit a30ac4
        mem->units = 1024;
Packit a30ac4
        mem->size  = memtotal;  /* Traditionally we've always regarded
Packit a30ac4
                                   all memory as potentially available
Packit a30ac4
                                   for memory buffers. */
Packit a30ac4
        mem->free  = memtotal - buffers;
Packit a30ac4
        mem->other = -1;
Packit a30ac4
    }
Packit a30ac4
Packit a30ac4
    return 0;
Packit a30ac4
}