diff --git a/doc/counter_ex.h b/doc/counter_ex.h new file mode 100644 index 0000000000000000000000000000000000000000..65fabf3756dddc1b41b3bb16d143b3158854c20f --- /dev/null +++ b/doc/counter_ex.h @@ -0,0 +1,26 @@ +/* + * Example of a basic counter: an accumulator +**/ + +unsigned int init_acc(char *, void **); +unsigned int get_acc(uint64_t *results, void *); +void clean_acc(void *); +void label_acc(char **labels, void *); + +Sensor rapl = { + .init = init_acc, + .get = get_acc, + .clean = clean_acc, + .label = label_acc, + .nb_opt = 1, +}; + +Optparse rapl_opt[1] = { + { + .longname = "accumulator", + .shortname = 'a', + .argtype = OPTPARSE_NONE, /* OPTPARSE_NONE / OPTPARSE_OPTIONAL / OPTPARSE_REQUIRED */ + .usage_arg = NULL, + .usage_msg = "dumb accumulator", + }, +}; diff --git a/doc/network.md b/doc/network.md new file mode 100644 index 0000000000000000000000000000000000000000..b5d1e68304a72a35da213a74dfab918321663247 --- /dev/null +++ b/doc/network.md @@ -0,0 +1,8 @@ +This sensor can autodetect interfaces in use by giving the special +interface name "X". But the total number of interfaces it can autodetect +is currently under a hard-limit. This hard-limit can be changed by +modifying this line in `src/network.c`: + +```c +#define NB_MAX_DEV 8 +``` diff --git a/src/network.c b/src/network.c index 37d237376be4c893e2c29de8d160b61ba3190628..a668725dcd51825c2245c34b7ae387cd7125b294 100644 --- a/src/network.c +++ b/src/network.c @@ -17,28 +17,40 @@ along with MojitO/S. If not, see <https://www.gnu.org/licenses/>. *******************************************************/ -#include <unistd.h> +#include <errno.h> #include <fcntl.h> -#include <stdlib.h> +#include <stdint.h> #include <stdio.h> +#include <stdlib.h> #include <string.h> -#include <stdint.h> +#include <unistd.h> + #include "util.h" +#define NB_MAX_DEV 8 #define NB_SENSOR 4 static char *route = "/proc/net/route"; +char *_labels_network[NB_SENSOR] = { + "%s:rxp", + "%s:rxb", + "%s:txp", + "%s:txb", +}; struct Network { - uint64_t values[NB_SENSOR]; - uint64_t tmp_values[NB_SENSOR]; - int sources[NB_SENSOR]; + uint64_t values[NB_MAX_DEV][NB_SENSOR]; + uint64_t tmp_values[NB_MAX_DEV][NB_SENSOR]; + int sources[NB_MAX_DEV][NB_SENSOR]; + char labels[NB_MAX_DEV][NB_SENSOR][128]; + char devs[NB_MAX_DEV][128]; + int ndev; }; typedef struct Network Network; -unsigned int _get_network(uint64_t *results, int *sources) +static void _get_network(uint64_t *results, int *sources) { if (sources == NULL) { - return 0; + return; } char buffer[128]; @@ -51,18 +63,51 @@ unsigned int _get_network(uint64_t *results, int *sources) results[i] = strtoull(buffer, NULL, 10); } - - return NB_SENSOR; } +/* + * read from fd len chars and store them into buf + * make *s points to the first occurence of c into buf +*/ +static int strchr_refill(int fd, char *buf, int len, char **s, char c) +{ + *s = strchr(*s, c); + + if (*s == NULL) { + int nbytes = read(fd, buf, len - 1); + if (nbytes < 0) { + perror("read"); + return -1; + } + buf[len - 1] = '\0'; + + /* whole file read */ + if (nbytes == 0) { + return 0; + } + *s = strchr(buf, c); + } + + return 1; +} unsigned int init_network(char *dev, void **ptr) { if (dev == NULL) { - return 0; + exit(1); } + char *filenames[] = { + "/sys/class/net/%s/statistics/rx_packets", + "/sys/class/net/%s/statistics/rx_bytes", + "/sys/class/net/%s/statistics/tx_packets", + "/sys/class/net/%s/statistics/tx_bytes", + }; + + struct Network *state = malloc(sizeof(struct Network)); + memset(state, '\0', sizeof(*state)); + if (strcmp(dev, "X") == 0) { int fd = open(route, O_RDONLY); @@ -74,50 +119,110 @@ unsigned int init_network(char *dev, void **ptr) char buffer[1000]; - if (read(fd, buffer, 999) < 0 ) { - perror("read"); + /* skip first line */ + char *s = buffer; + int ret = strchr_refill(fd, buffer, sizeof(buffer), &s, '\n'); + if (ret != 1) { close(fd); + free(state); exit(1); } + s++; - char *start_of_dev = index(buffer, '\n') + 1; - char *end_of_dev = index(start_of_dev, '\t'); - *end_of_dev = '\0'; - dev = start_of_dev; - close(fd); - } + char *start_of_dev = s; + /* jump to the end of the device name */ + ret = strchr_refill(fd, buffer, sizeof(buffer), &s, '\t'); + if (ret != 1) { + close(fd); + free(state); + exit(1); + } - char *filenames[] = {"/sys/class/net/%s/statistics/rx_packets", - "/sys/class/net/%s/statistics/rx_bytes", - "/sys/class/net/%s/statistics/tx_packets", - "/sys/class/net/%s/statistics/tx_bytes" - }; + state->ndev++; // ndev should be equal to 1 at this point + memcpy(&(state->devs[state->ndev - 1]), start_of_dev, + MIN((size_t)(sizeof(state->devs[0]) - 1), (size_t)(s - start_of_dev))); + + for (;;) { + /* jump to the next line */ + ret = strchr_refill(fd, buffer, sizeof(buffer), &s, '\n'); + if (ret != 1) { + break; + } + s++; + + start_of_dev = s; + ret = strchr_refill(fd, buffer, sizeof(buffer), &s, '\t'); + if (ret != 1) { + break; + } + + /* compare dev name to the previously saved one */ + int newdev = 1; + for (int i = 0; i < state->ndev && newdev; i++) { + if (strncmp(start_of_dev, state->devs[i], s - start_of_dev) == 0) { + newdev = 0; + } + } + if (newdev) { + if (state->ndev >= NB_MAX_DEV) { + fprintf(stderr, "Maximum amount of network devices exceeded (%d).\n", NB_MAX_DEV); + break; + } + state->ndev++; + memcpy(&(state->devs[state->ndev - 1]), start_of_dev, + MIN((size_t)(sizeof(state->devs[0]) - 1), (size_t)(s - start_of_dev))); + } + } - Network *state = malloc(sizeof(Network)); + close(fd); + } else { + state->ndev = 1; + memcpy(&(state->devs[0]), dev, strlen(dev) + 1); + } char buffer2[256]; - for (int i = 0; i < NB_SENSOR; i++) { - snprintf(buffer2, 256, filenames[i], dev); - state->sources[i] = open(buffer2, O_RDONLY); + for (int i = 0; i < state->ndev; i++) { + for (int j = 0; j < NB_SENSOR; j++) { + snprintf(buffer2, sizeof(buffer2), filenames[j], state->devs[i]); + errno = 0; + int fd = open(buffer2, O_RDONLY); + if (fd < 0) { + fprintf(stderr, "init_network: open: %s: %.*s\n", strerror(errno), + (int)sizeof(buffer2), buffer2); + free(state); + exit(1); + } + state->sources[i][j] = fd; + snprintf(state->labels[i][j], sizeof(state->labels[i][j]), _labels_network[j], + state->devs[i]); + } } *ptr = (void *) state; - _get_network(state->values, state->sources); - return NB_SENSOR; + for (int i = 0; i < state->ndev; i++) { + _get_network(state->values[i], state->sources[i]); + } + + return state->ndev * NB_SENSOR; } unsigned int get_network(uint64_t *results, void *ptr) { - Network *state = (Network *) ptr; - _get_network(state->tmp_values, state->sources); + struct Network *state = (struct Network *) ptr; - for (int i = 0; i < NB_SENSOR; i++) { - results[i] = modulo_substraction(state->tmp_values[i], state->values[i]); + for (int i = 0; i < state->ndev; i++) { + _get_network(state->tmp_values[i], state->sources[i]); + + for (int j = 0; j < NB_SENSOR; j++) { + results[i*NB_SENSOR + j] = modulo_substraction(state->tmp_values[i][j], state->values[i][j]); + } + + memcpy(&(state->values[i]), &(state->tmp_values[i]), + NB_SENSOR * sizeof(state->values[i][0])); } - memcpy(state->values, state->tmp_values, NB_SENSOR * sizeof(uint64_t)); - return NB_SENSOR; + return state->ndev * NB_SENSOR; } void clean_network(void *ptr) @@ -128,19 +233,22 @@ void clean_network(void *ptr) return; } - for (int i = 0; i < NB_SENSOR; i++) { - close(state->sources[i]); + for (int i = 0; i < state->ndev; i++) { + for (int j = 0; j < NB_SENSOR; j++) { + close(state->sources[i][j]); + } } free(state); } -char *_labels_network[NB_SENSOR] = {"rxp", "rxb", "txp", "txb"}; -void label_network(char **labels, void *none) +void label_network(char **labels, void *ptr) { - UNUSED(none); + struct Network *state = (struct Network *) ptr; - for (int i = 0; i < NB_SENSOR; i++) { - labels[i] = _labels_network[i]; + for (int i = 0; i < state->ndev; i++) { + for (int j = 0; j < NB_SENSOR; j++) { + labels[i*NB_SENSOR + j] = state->labels[i][j]; + } } } diff --git a/src/util.h b/src/util.h index e422d070693cd28af9613e77a5efdb917ce6b2f6..0015a9867452800633582cdbd9736ab5c11c145e 100644 --- a/src/util.h +++ b/src/util.h @@ -38,6 +38,8 @@ exit(code); \ } while (0) +#define MIN(a, b) ((a) < (b) ? (a) : (b)) +#define MAX(a, b) ((a) > (b) ? (a) : (b)) /** * @brief Substracts lhs by rhs, assuming that lhs is a cyclic increment from rhs,