X-Git-Url: http://git.onelab.eu/?p=iproute2.git;a=blobdiff_plain;f=misc%2Flnstat_util.c;fp=misc%2Flnstat_util.c;h=0000000000000000000000000000000000000000;hp=59c5e9648adb30ebfc090a060e4a0db45bff9fac;hb=3331a68859fd71047bb1f309048960b48eab2d83;hpb=2bd4a72f2100be7ad7d9518cb1d49bb2a5b71994 diff --git a/misc/lnstat_util.c b/misc/lnstat_util.c deleted file mode 100644 index 59c5e96..0000000 --- a/misc/lnstat_util.c +++ /dev/null @@ -1,329 +0,0 @@ -/* lnstat.c: Unified linux network statistics - * - * Copyright (C) 2004 by Harald Welte - * - * Development of this code was funded by Astaro AG, http://www.astaro.com/ - * - * Based on original concept and ideas from predecessor rtstat.c: - * - * Copyright 2001 by Robert Olsson - * Uppsala University, Sweden - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - */ - -#include -#include -#include -#include -#include -#include -#include - -#include -#include - -#include "lnstat.h" - -/* size of temp buffer used to read lines from procfiles */ -#define FGETS_BUF_SIZE 1024 - - -#define RTSTAT_COMPAT_LINE "entries in_hit in_slow_tot in_no_route in_brd in_martian_dst in_martian_src out_hit out_slow_tot out_slow_mc gc_total gc_ignored gc_goal_miss gc_dst_overflow in_hlist_search out_hlist_search\n" - -/* Read (and summarize for SMP) the different stats vars. */ -static int scan_lines(struct lnstat_file *lf, int i) -{ - int j, num_lines = 0; - - for (j = 0; j < lf->num_fields; j++) - lf->fields[j].values[i] = 0; - - while(!feof(lf->fp)) { - char buf[FGETS_BUF_SIZE]; - char *ptr = buf; - - num_lines++; - - fgets(buf, sizeof(buf)-1, lf->fp); - gettimeofday(&lf->last_read, NULL); - - for (j = 0; j < lf->num_fields; j++) { - unsigned long f = strtoul(ptr, &ptr, 16); - if (j == 0) - lf->fields[j].values[i] = f; - else - lf->fields[j].values[i] += f; - } - } - return num_lines; -} - -static int time_after(struct timeval *last, - struct timeval *tout, - struct timeval *now) -{ - if (now->tv_sec > last->tv_sec + tout->tv_sec) - return 1; - - if (now->tv_sec == last->tv_sec + tout->tv_sec) { - if (now->tv_usec > last->tv_usec + tout->tv_usec) - return 1; - } - - return 0; -} - -int lnstat_update(struct lnstat_file *lnstat_files) -{ - struct lnstat_file *lf; - char buf[FGETS_BUF_SIZE]; - struct timeval tv; - - gettimeofday(&tv, NULL); - - for (lf = lnstat_files; lf; lf = lf->next) { - if (time_after(&lf->last_read, &lf->interval, &tv)) { - int i; - struct lnstat_field *lfi; - - rewind(lf->fp); - if (!lf->compat) { - /* skip first line */ - fgets(buf, sizeof(buf)-1, lf->fp); - } - scan_lines(lf, 1); - - for (i = 0, lfi = &lf->fields[i]; - i < lf->num_fields; i++, lfi = &lf->fields[i]) { - if (i == 0) - lfi->result = lfi->values[1]; - else - lfi->result = (lfi->values[1]-lfi->values[0]) - / lf->interval.tv_sec; - } - - rewind(lf->fp); - fgets(buf, sizeof(buf)-1, lf->fp); - scan_lines(lf, 0); - } - } - - return 0; -} - -/* scan first template line and fill in per-field data structures */ -static int __lnstat_scan_fields(struct lnstat_file *lf, char *buf) -{ - char *tok; - int i; - - tok = strtok(buf, " \t\n"); - for (i = 0; i < LNSTAT_MAX_FIELDS_PER_LINE; i++) { - lf->fields[i].file = lf; - strncpy(lf->fields[i].name, tok, LNSTAT_MAX_FIELD_NAME_LEN); - /* has to be null-terminate since we initialize to zero - * and field size is NAME_LEN + 1 */ - tok = strtok(NULL, " \t\n"); - if (!tok) { - lf->num_fields = i+1; - return 0; - } - } - return 0; -} - -static int lnstat_scan_fields(struct lnstat_file *lf) -{ - char buf[FGETS_BUF_SIZE]; - - rewind(lf->fp); - fgets(buf, sizeof(buf)-1, lf->fp); - - return __lnstat_scan_fields(lf, buf); -} - -/* fake function emulating lnstat_scan_fields() for old kernels */ -static int lnstat_scan_compat_rtstat_fields(struct lnstat_file *lf) -{ - char buf[FGETS_BUF_SIZE]; - - strncpy(buf, RTSTAT_COMPAT_LINE, sizeof(buf)-1); - - return __lnstat_scan_fields(lf, buf); -} - -/* find out whether string 'name; is in given string array */ -static int name_in_array(const int num, const char **arr, const char *name) -{ - int i; - for (i = 0; i < num; i++) { - if (!strcmp(arr[i], name)) - return 1; - } - return 0; -} - -/* allocate lnstat_file and open given file */ -static struct lnstat_file *alloc_and_open(const char *path, const char *file) -{ - struct lnstat_file *lf; - - /* allocate */ - lf = malloc(sizeof(*lf)); - if (!lf) - return NULL; - - /* initialize */ - memset(lf, 0, sizeof(*lf)); - - /* de->d_name is guaranteed to be <= NAME_MAX */ - strcpy(lf->basename, file); - strcpy(lf->path, path); - strcat(lf->path, "/"); - strcat(lf->path, lf->basename); - - /* initialize to default */ - lf->interval.tv_sec = 1; - - /* open */ - lf->fp = fopen(lf->path, "r"); - if (!lf->fp) { - free(lf); - return NULL; - } - - return lf; -} - - -/* lnstat_scan_dir - find and parse all available statistics files/fields */ -struct lnstat_file *lnstat_scan_dir(const char *path, const int num_req_files, - const char **req_files) -{ - DIR *dir; - struct lnstat_file *lnstat_files = NULL; - struct dirent *de; - - if (!path) - path = PROC_NET_STAT; - - dir = opendir(path); - if (!dir) { - struct lnstat_file *lf; - /* Old kernel, before /proc/net/stat was introduced */ - fprintf(stderr, "Your kernel doesn't have lnstat support. "); - - /* we only support rtstat, not multiple files */ - if (num_req_files >= 2) { - fputc('\n', stderr); - return NULL; - } - - /* we really only accept rt_cache */ - if (num_req_files && !name_in_array(num_req_files, - req_files, "rt_cache")) { - fputc('\n', stderr); - return NULL; - } - - fprintf(stderr, "Fallback to old rtstat-only operation\n"); - - lf = alloc_and_open("/proc/net", "rt_cache_stat"); - if (!lf) - return NULL; - lf->compat = 1; - strncpy(lf->basename, "rt_cache", sizeof(lf->basename)); - - /* FIXME: support for old files */ - if (lnstat_scan_compat_rtstat_fields(lf) < 0) - return NULL; - - lf->next = lnstat_files; - lnstat_files = lf; - return lnstat_files; - } - - while ((de = readdir(dir))) { - struct lnstat_file *lf; - - if (de->d_type != DT_REG) - continue; - - if (num_req_files && !name_in_array(num_req_files, - req_files, de->d_name)) - continue; - - lf = alloc_and_open(path, de->d_name); - if (!lf) - return NULL; - - /* fill in field structure */ - if (lnstat_scan_fields(lf) < 0) - return NULL; - - /* prepend to global list */ - lf->next = lnstat_files; - lnstat_files = lf; - } - closedir(dir); - - return lnstat_files; -} - -int lnstat_dump(FILE *outfd, struct lnstat_file *lnstat_files) -{ - struct lnstat_file *lf; - - for (lf = lnstat_files; lf; lf = lf->next) { - int i; - - fprintf(outfd, "%s:\n", lf->path); - - for (i = 0; i < lf->num_fields; i++) - fprintf(outfd, "\t%2u: %s\n", i+1, lf->fields[i].name); - - } - return 0; -} - -struct lnstat_field *lnstat_find_field(struct lnstat_file *lnstat_files, - const char *name) -{ - struct lnstat_file *lf; - struct lnstat_field *ret = NULL; - const char *colon = strchr(name, ':'); - char *file; - const char *field; - - if (colon) { - file = strndup(name, colon-name); - field = colon+1; - } else { - file = NULL; - field = name; - } - - for (lf = lnstat_files; lf; lf = lf->next) { - int i; - - if (file && strcmp(file, lf->basename)) - continue; - - for (i = 0; i < lf->num_fields; i++) { - if (!strcmp(field, lf->fields[i].name)) { - ret = &lf->fields[i]; - goto out; - } - } - } -out: - if (file) - free(file); - - return ret; -}