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