/** * load systemstats information in specified container * * @param container empty container, or NULL to have one created for you * @param load_flags flags to modify behaviour. * * @retval NULL error * @retval !NULL pointer to container */ netsnmp_container* netsnmp_access_systemstats_container_load(netsnmp_container* container, u_int load_flags) { int rc; DEBUGMSGTL(("access:systemstats:container", "load\n")); if (NULL == container) { container = netsnmp_access_systemstats_container_init(load_flags); if (NULL != container) container->container_name = strdup("systemstats_autocreate"); } if (NULL == container) { snmp_log(LOG_ERR, "no container specified/found for access_systemstats\n"); return NULL; } rc = netsnmp_access_systemstats_container_arch_load(container, load_flags); if (0 != rc) { netsnmp_access_systemstats_container_free(container, NETSNMP_ACCESS_SYSTEMSTATS_FREE_NOFLAGS); container = NULL; } return container; }
/* * initialization */ void netsnmp_access_systemstats_init(void) { netsnmp_container * ifcontainer; netsnmp_access_systemstats_arch_init(); /* * load once to set up ifIndexes */ ifcontainer = netsnmp_access_systemstats_container_load(NULL, 0); if(NULL != ifcontainer) netsnmp_access_systemstats_container_free(ifcontainer, 0); }
/** * load initial data * * TODO:350:M: Implement ipIfStatsTable data load * This function will also be called by the cache helper to load * the container again (after the container free function has been * called to free the previous contents). * * @param container container to which items should be inserted * * @retval MFD_SUCCESS : success. * @retval MFD_RESOURCE_UNAVAILABLE : Can't access data source * @retval MFD_ERROR : other error. * * This function is called to load the index(es) (and data, optionally) * for the every row in the data set. * * @remark * While loading the data, the only important thing is the indexes. * If access to your data is cheap/fast (e.g. you have a pointer to a * structure in memory), it would make sense to update the data here. * If, however, the accessing the data invovles more work (e.g. parsing * some other existing data, or peforming calculations to derive the data), * then you can limit yourself to setting the indexes and saving any * information you will need later. Then use the saved information in * ipIfStatsTable_row_prep() for populating data. * * @note * If you need consistency between rows (like you want statistics * for each row to be from the same time frame), you should set all * data here. * */ int ipIfStatsTable_container_load(netsnmp_container * container) { netsnmp_container *stats; DEBUGMSGTL(("verbose:ipIfStatsTable:ipIfStatsTable_container_load", "called\n")); netsnmp_assert(NULL != container); stats = netsnmp_access_systemstats_container_load(NULL, NETSNMP_ACCESS_SYSTEMSTATS_LOAD_IFTABLE); if (NULL == stats) return MFD_RESOURCE_UNAVAILABLE; /* msg already logged */ /* * TODO:351:M: |-> Load/update data in the ipIfStatsTable container. * loop over your ipIfStatsTable data, allocate a rowreq context, * set the index(es) [and data, optionally] and insert into * the container. */ /* * we just got a fresh copy of data. compare it to * what we've already got, and make any adjustements... */ CONTAINER_FOR_EACH(container, (netsnmp_container_obj_func *) _check_for_updates, stats); /* * now add any new entries */ CONTAINER_FOR_EACH(stats, (netsnmp_container_obj_func *) _add_new, container); /* * free the container. we've either claimed each ifentry, or released it, * so the dal function doesn't need to clear the container. */ netsnmp_access_systemstats_container_free(stats, NETSNMP_ACCESS_SYSTEMSTATS_FREE_DONT_CLEAR); DEBUGMSGT(("verbose:ipIfStatsTable:ipIfStatsTable_container_load", "%lu records\n", (unsigned long)CONTAINER_SIZE(container))); return MFD_SUCCESS; } /* ipIfStatsTable_container_load */
/* * Based on load_flags, load ipSystemStatsTable or ipIfStatsTable for ipv4 entries. */ static int _systemstats_v4(netsnmp_container* container, u_int load_flags) { FILE *devin; char line[1024]; netsnmp_systemstats_entry *entry = NULL; int scan_count; char *stats, *start = line; int len; unsigned long long scan_vals[19]; DEBUGMSGTL(("access:systemstats:container:arch", "load v4 (flags %x)\n", load_flags)); netsnmp_assert(container != NULL); /* load function shoulda checked this */ if (load_flags & NETSNMP_ACCESS_SYSTEMSTATS_LOAD_IFTABLE) { /* we do not support ipIfStatsTable for ipv4 */ return 0; } if (!(devin = fopen("/proc/net/snmp", "r"))) { DEBUGMSGTL(("access:systemstats", "Failed to load Systemstats Table (linux1)\n")); NETSNMP_LOGONCE((LOG_ERR, "cannot open /proc/net/snmp ...\n")); return -2; } /* * skip header, but make sure it's the length we expect... */ fgets(line, sizeof(line), devin); len = strlen(line); if (224 != len) { fclose(devin); snmp_log(LOG_ERR, "unexpected header length in /proc/net/snmp." " %d != 224\n", len); return -4; } /* * This file provides the statistics for each systemstats. * Read in each line in turn, isolate the systemstats name * and retrieve (or create) the corresponding data structure. */ start = fgets(line, sizeof(line), devin); fclose(devin); if (start) { len = strlen(line); if (line[len - 1] == '\n') line[len - 1] = '\0'; while (*start && *start == ' ') start++; if ((!*start) || ((stats = strrchr(start, ':')) == NULL)) { snmp_log(LOG_ERR, "systemstats data format error 1, line ==|%s|\n", line); return -4; } DEBUGMSGTL(("access:systemstats", "processing '%s'\n", start)); *stats++ = 0; /* null terminate name */ while (*stats == ' ') /* skip spaces before stats */ stats++; entry = netsnmp_access_systemstats_entry_create(1, 0, "ipSystemStatsTable.ipv4"); if(NULL == entry) { netsnmp_access_systemstats_container_free(container, NETSNMP_ACCESS_SYSTEMSTATS_FREE_NOFLAGS); return -3; } /* * OK - we've now got (or created) the data structure for * this systemstats, including any "static" information. * Now parse the rest of the line (i.e. starting from 'stats') * to extract the relevant statistics, and populate * data structure accordingly. */ memset(scan_vals, 0x0, sizeof(scan_vals)); scan_count = sscanf(stats, "%llu %llu %llu %llu %llu %llu %llu %llu %llu %llu" "%llu %llu %llu %llu %llu %llu %llu %llu %llu", &scan_vals[0],&scan_vals[1],&scan_vals[2], &scan_vals[3],&scan_vals[4],&scan_vals[5], &scan_vals[6],&scan_vals[7],&scan_vals[8], &scan_vals[9],&scan_vals[10],&scan_vals[11], &scan_vals[12],&scan_vals[13],&scan_vals[14], &scan_vals[15],&scan_vals[16],&scan_vals[17], &scan_vals[18]); DEBUGMSGTL(("access:systemstats", " read %d values\n", scan_count)); if(scan_count != 19) { snmp_log(LOG_ERR, "error scanning systemstats data (expected %d, got %d)\n", 19, scan_count); netsnmp_access_systemstats_entry_free(entry); return -4; } /* entry->stats. = scan_vals[0]; / * Forwarding */ /* entry->stats. = scan_vals[1]; / * DefaultTTL */ entry->stats.HCInReceives.low = scan_vals[2] & 0xffffffff; entry->stats.HCInReceives.high = scan_vals[2] >> 32; entry->stats.InHdrErrors = scan_vals[3]; entry->stats.InAddrErrors = scan_vals[4]; entry->stats.HCOutForwDatagrams.low = scan_vals[5] & 0xffffffff; entry->stats.HCOutForwDatagrams.high = scan_vals[5] >> 32; entry->stats.InUnknownProtos = scan_vals[6]; entry->stats.InDiscards = scan_vals[7]; entry->stats.HCInDelivers.low = scan_vals[8] & 0xffffffff; entry->stats.HCInDelivers.high = scan_vals[8] >> 32; entry->stats.HCOutRequests.low = scan_vals[9] & 0xffffffff; entry->stats.HCOutRequests.high = scan_vals[9] >> 32; entry->stats.HCOutDiscards.low = scan_vals[10] & 0xffffffff;; entry->stats.HCOutDiscards.high = scan_vals[10] >> 32; entry->stats.HCOutNoRoutes.low = scan_vals[11] & 0xffffffff;; entry->stats.HCOutNoRoutes.high = scan_vals[11] >> 32; /* entry->stats. = scan_vals[12]; / * ReasmTimeout */ entry->stats.ReasmReqds = scan_vals[13]; entry->stats.ReasmOKs = scan_vals[14]; entry->stats.ReasmFails = scan_vals[15]; entry->stats.HCOutFragOKs.low = scan_vals[16] & 0xffffffff;; entry->stats.HCOutFragOKs.high = scan_vals[16] >> 32; entry->stats.HCOutFragFails.low = scan_vals[17] & 0xffffffff;; entry->stats.HCOutFragFails.high = scan_vals[17] >> 32; entry->stats.HCOutFragCreates.low = scan_vals[18] & 0xffffffff;; entry->stats.HCOutFragCreates.high = scan_vals[18] >> 32; entry->stats.columnAvail[IPSYSTEMSTATSTABLE_HCINRECEIVES] = 1; entry->stats.columnAvail[IPSYSTEMSTATSTABLE_INHDRERRORS] = 1; entry->stats.columnAvail[IPSYSTEMSTATSTABLE_INADDRERRORS] = 1; entry->stats.columnAvail[IPSYSTEMSTATSTABLE_HCOUTFORWDATAGRAMS] = 1; entry->stats.columnAvail[IPSYSTEMSTATSTABLE_INUNKNOWNPROTOS] = 1; entry->stats.columnAvail[IPSYSTEMSTATSTABLE_INDISCARDS] = 1; entry->stats.columnAvail[IPSYSTEMSTATSTABLE_HCINDELIVERS] = 1; entry->stats.columnAvail[IPSYSTEMSTATSTABLE_HCOUTREQUESTS] = 1; entry->stats.columnAvail[IPSYSTEMSTATSTABLE_HCOUTDISCARDS] = 1; entry->stats.columnAvail[IPSYSTEMSTATSTABLE_HCOUTNOROUTES] = 1; entry->stats.columnAvail[IPSYSTEMSTATSTABLE_REASMREQDS] = 1; entry->stats.columnAvail[IPSYSTEMSTATSTABLE_REASMOKS] = 1; entry->stats.columnAvail[IPSYSTEMSTATSTABLE_REASMFAILS] = 1; entry->stats.columnAvail[IPSYSTEMSTATSTABLE_HCOUTFRAGOKS] = 1; entry->stats.columnAvail[IPSYSTEMSTATSTABLE_HCOUTFRAGFAILS] = 1; entry->stats.columnAvail[IPSYSTEMSTATSTABLE_HCOUTFRAGCREATES] = 1; entry->stats.columnAvail[IPSYSTEMSTATSTABLE_DISCONTINUITYTIME] = 1; entry->stats.columnAvail[IPSYSTEMSTATSTABLE_REFRESHRATE] = 1; /* * load addtional statistics defined by RFC 4293 * As these are supported linux 2.6.22 or later, it is no problem * if loading them are failed. */ _additional_systemstats_v4(entry, load_flags); /* * add to container */ if (CONTAINER_INSERT(container, entry) < 0) { DEBUGMSGTL(("access:systemstats:container","error with systemstats_entry: insert into container failed.\n")); netsnmp_access_systemstats_entry_free(entry); } } return 0; }