#include #include #include #include #include #include #include #include #include #include #include #if HAVE_SYS_VMPARAM_H #include #else #include #endif #define SUM_SYMBOL "cnt" #define BUFSPACE_SYMBOL "bufspace" quad_t swapTotal; quad_t swapUsed; quad_t swapFree; static int swapmode(long); /* * Load the latest memory usage statistics */ int netsnmp_mem_arch_load( netsnmp_cache *cache, void *magic ) { netsnmp_memory_info *mem; long pagesize; int nswap; #if !defined(VM_TOTAL) unsigned int free_mem; size_t free_size = sizeof(free_mem); unsigned int mem_pages; #else struct vmtotal total; size_t total_size = sizeof(total); int total_mib[] = { CTL_VM, VM_TOTAL }; #endif u_long phys_mem; u_long user_mem; unsigned int cache_count; unsigned int cache_max; unsigned int bufspace; unsigned int maxbufspace; unsigned int inact_count; size_t mem_size = sizeof(phys_mem); size_t cache_size = sizeof(cache_count); size_t buf_size = sizeof(bufspace); size_t inact_size = sizeof(inact_count); int phys_mem_mib[] = { CTL_HW, HW_PHYSMEM }; int user_mem_mib[] = { CTL_HW, HW_USERMEM }; /* * Retrieve the memory information from the underlying O/S... */ #if !defined(VM_TOTAL) sysctlbyname("vm.stats.vm.v_free_count", &free_mem, &free_size, NULL, 0); sysctlbyname("vm.stats.vm.v_page_count", &mem_pages, &free_size, NULL, 0); #else sysctl(total_mib, 2, &total, &total_size, NULL, 0); #endif sysctl(phys_mem_mib, 2, &phys_mem, &mem_size, NULL, 0); sysctl(user_mem_mib, 2, &user_mem, &mem_size, NULL, 0); sysctlbyname("vm.stats.vm.v_cache_count", &cache_count, &cache_size, NULL, 0); sysctlbyname("vm.stats.vm.v_cache_max", &cache_max, &cache_size, NULL, 0); sysctlbyname("vm.stats.vm.v_inactive_count", &inact_count, &inact_size, NULL, 0); sysctlbyname("vfs.bufspace", &bufspace, &buf_size, NULL, 0); sysctlbyname("vfs.maxbufspace", &maxbufspace, &buf_size, NULL, 0); #ifndef freebsd4 pagesize = 1024; #else pagesize = getpagesize(); #endif /* * ... 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 = pagesize; mem->size = phys_mem/pagesize; #if !defined(VM_TOTAL) mem->free = free_mem; #else mem->free = total.t_free; #endif } mem = netsnmp_memory_get_byIdx( NETSNMP_MEM_TYPE_USERMEM, 1 ); if (!mem) { snmp_log_perror("No (user) Memory info entry"); } else { if (!mem->descr) mem->descr = strdup("Real memory"); mem->units = pagesize; #if !defined(VM_TOTAL) mem->size = user_mem/pagesize; mem->free = free_mem; #else mem->size = total.t_rm; mem->free = total.t_rm - total.t_arm; #endif } 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 = pagesize; #if !defined(VM_TOTAL) mem->size = mem_pages+swapTotal; mem->free = free_mem+swapFree; #else mem->size = total.t_vm; mem->free = total.t_vm - total.t_avm; #endif } #if defined(VM_TOTAL) 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 virtual memory"); mem->units = pagesize; mem->size = total.t_vmshr; mem->free = total.t_vmshr - total.t_avmshr; } mem = netsnmp_memory_get_byIdx( NETSNMP_MEM_TYPE_SHARED2, 1 ); if (!mem) { snmp_log_perror("No Shared2 Memory info entry"); } else { if (!mem->descr) mem->descr = strdup("Shared real memory"); mem->units = pagesize; mem->size = total.t_rmshr; mem->free = total.t_rmshr - total.t_armshr; } #endif 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 = pagesize; mem->size = cache_count; mem->free = 0; } nswap = swapmode(pagesize); 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( (nswap>1) ? "Swap space (total)" : "Swap space"); mem->units = pagesize; mem->size = swapTotal; mem->free = swapFree; } 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 = maxbufspace / 1024; mem->free = (maxbufspace - bufspace)/1024; } return 0; } /* * Retained from UCD implementation */ #ifndef freebsd4 /* * Executes swapinfo and parses last line * This is just way too ugly ;) */ static int swapmode(long pagesize) { struct extensible ext; int fd; FILE *file; strcpy(ext.command, "/usr/sbin/swapinfo -k"); if ((fd = get_exec_output(&ext)) != -1) { file = fdopen(fd, "r"); while (fgets(ext.output, sizeof(ext.output), file) != NULL); fclose(file); wait_on_exec(&ext); sscanf(ext.output, "%*s%*d%qd%qd", &swapUsed, &swapFree); swapTotal = swapUsed + swapFree; } return 1; } #else /* * swapmode is based on a program called swapinfo written * by Kevin Lahey . */ #include extern kvm_t *kd; static int swapmode(long pagesize) { int i, n; struct kvm_swap kswap[16]; netsnmp_memory_info *mem; char buf[1024]; n = kvm_getswapinfo(kd, kswap, sizeof(kswap) / sizeof(kswap[0]), 0); swapUsed = swapTotal = swapFree = 0; if ( n > 0 ) { /* * If there are multiple swap devices, then record * the statistics for each one separately... */ for (i = 0; i < n; ++i) { mem = netsnmp_memory_get_byIdx( NETSNMP_MEM_TYPE_SWAP+1+i, 1 ); if (!mem) continue; if (!mem->descr) { sprintf(buf, "swap %s", kswap[i].ksw_devname); mem->descr = strdup( buf ); } mem->units = pagesize; mem->size = kswap[i].ksw_total; mem->free = kswap[i].ksw_total - kswap[i].ksw_used; /* * ... and keep a running total for the overall swap stats */ swapTotal += kswap[i].ksw_total; swapUsed += kswap[i].ksw_used; } } else { /* * If there's only one swap device, then don't bother * with individual statistics. */ swapTotal += kswap[0].ksw_total; swapUsed += kswap[0].ksw_used; } swapFree = swapTotal - swapUsed; return n; } #endif