| version 1.1, 2012/02/21 22:19:56 | version 1.1.1.3, 2019/10/21 14:58:35 | 
| Line 1 | Line 1 | 
 | /* | /* | 
 | * in_proc.c                   /proc/net/dev Input (Linux) | * in_proc.c                   /proc/net/dev Input (Linux) | 
 | * | * | 
| * Copyright (c) 2001-2004 Thomas Graf <tgraf@suug.ch> | * Copyright (c) 2001-2013 Thomas Graf <tgraf@suug.ch> | 
|  | * Copyright (c) 2013 Red Hat, Inc. | 
 | * | * | 
 | * Permission is hereby granted, free of charge, to any person obtaining a | * Permission is hereby granted, free of charge, to any person obtaining a | 
 | * copy of this software and associated documentation files (the "Software"), | * copy of this software and associated documentation files (the "Software"), | 
| Line 24 | Line 25 | 
 |  |  | 
 | #include <bmon/bmon.h> | #include <bmon/bmon.h> | 
 | #include <bmon/input.h> | #include <bmon/input.h> | 
| #include <bmon/node.h> | #include <bmon/element.h> | 
| #include <bmon/item.h> | #include <bmon/group.h> | 
|  | #include <bmon/attr.h> | 
 | #include <bmon/utils.h> | #include <bmon/utils.h> | 
 | #include <inttypes.h> |  | 
 |  |  | 
| static char *c_path = "/proc/net/dev"; | static const char *c_path = "/proc/net/dev"; | 
|  | static const char *c_group = DEFAULT_GROUP; | 
|  | static struct element_group *grp; | 
 |  |  | 
 |  | enum { | 
 |  | PROC_BYTES, | 
 |  | PROC_PACKETS, | 
 |  | PROC_ERRORS, | 
 |  | PROC_DROP, | 
 |  | PROC_COMPRESSED, | 
 |  | PROC_FIFO, | 
 |  | PROC_FRAME, | 
 |  | PROC_MCAST, | 
 |  | NUM_PROC_VALUE, | 
 |  | }; | 
 |  |  | 
 |  | static struct attr_map link_attrs[NUM_PROC_VALUE] = { | 
 |  | { | 
 |  | .name           = "bytes", | 
 |  | .type           = ATTR_TYPE_COUNTER, | 
 |  | .unit           = UNIT_BYTE, | 
 |  | .description    = "Bytes", | 
 |  | }, | 
 |  | { | 
 |  | .name           = "packets", | 
 |  | .type           = ATTR_TYPE_COUNTER, | 
 |  | .unit           = UNIT_NUMBER, | 
 |  | .description    = "Packets", | 
 |  | }, | 
 |  | { | 
 |  | .name           = "errors", | 
 |  | .type           = ATTR_TYPE_COUNTER, | 
 |  | .unit           = UNIT_NUMBER, | 
 |  | .description    = "Errors", | 
 |  | }, | 
 |  | { | 
 |  | .name           = "drop", | 
 |  | .type           = ATTR_TYPE_COUNTER, | 
 |  | .unit           = UNIT_NUMBER, | 
 |  | .description    = "Dropped", | 
 |  | }, | 
 |  | { | 
 |  | .name           = "compressed", | 
 |  | .type           = ATTR_TYPE_COUNTER, | 
 |  | .unit           = UNIT_NUMBER, | 
 |  | .description    = "Compressed", | 
 |  | }, | 
 |  | { | 
 |  | .name           = "fifoerr", | 
 |  | .type           = ATTR_TYPE_COUNTER, | 
 |  | .unit           = UNIT_NUMBER, | 
 |  | .description    = "FIFO Error", | 
 |  | }, | 
 |  | { | 
 |  | .name           = "frameerr", | 
 |  | .type           = ATTR_TYPE_COUNTER, | 
 |  | .unit           = UNIT_NUMBER, | 
 |  | .description    = "Frame Error", | 
 |  | }, | 
 |  | { | 
 |  | .name           = "mcast", | 
 |  | .type           = ATTR_TYPE_COUNTER, | 
 |  | .unit           = UNIT_NUMBER, | 
 |  | .description    = "Multicast", | 
 |  | } | 
 |  | }; | 
 |  |  | 
 | static void proc_read(void) | static void proc_read(void) | 
 | { | { | 
| FILE *  fd; | struct element *e; | 
| char    buf[512], *p, *s; | FILE *fd; | 
| int     w; | char buf[512], *p, *s, *unused __unused__; | 
| item_t *it; | int w; | 
 |  |  | 
 | if (!(fd = fopen(c_path, "r"))) | if (!(fd = fopen(c_path, "r"))) | 
 | quit("Unable to open file %s: %s\n", c_path, strerror(errno)); | quit("Unable to open file %s: %s\n", c_path, strerror(errno)); | 
 |  |  | 
 |  | /* Ignore header */ | 
 |  | unused = fgets(buf, sizeof(buf), fd); | 
 |  | unused = fgets(buf, sizeof(buf), fd); | 
 |  |  | 
 | fgets(buf, sizeof(buf), fd); |  | 
 | fgets(buf, sizeof(buf), fd); |  | 
 |  |  | 
 | for (; fgets(buf, sizeof(buf), fd);) { | for (; fgets(buf, sizeof(buf), fd);) { | 
| b_cnt_t rx_errors, rx_drop, rx_fifo, rx_frame, rx_compressed; | uint64_t data[NUM_PROC_VALUE][2]; | 
| b_cnt_t rx_multicast, tx_errors, tx_drop, tx_fifo, tx_frame; | int i; | 
| b_cnt_t tx_compressed, tx_multicast, rx_bytes, tx_bytes; |  | 
| b_cnt_t rx_packets, tx_packets; |  | 
 |  |  | 
 | if (buf[0] == '\r' || buf[0] == '\n') | if (buf[0] == '\r' || buf[0] == '\n') | 
 | continue; | continue; | 
|  |  | 
 | if (!(p = strchr(buf, ':'))) | if (!(p = strchr(buf, ':'))) | 
 | continue; | continue; | 
 | *p = '\0'; | *p = '\0'; | 
| Line 60  static void proc_read(void) | Line 125  static void proc_read(void) | 
 |  |  | 
 | for (p = &buf[0]; *p == ' '; p++); | for (p = &buf[0]; *p == ' '; p++); | 
 |  |  | 
 | /* |  | 
 | * XXX: get_show_only_running |  | 
 | */ |  | 
 |  |  | 
 | if ((it = lookup_item(get_local_node(), p, 0, 0)) == NULL) |  | 
 | continue; |  | 
 |  |  | 
 | w = sscanf(s, "%" SCNu64 " %" SCNu64 " %" SCNu64 " %" SCNu64 " " | w = sscanf(s, "%" SCNu64 " %" SCNu64 " %" SCNu64 " %" SCNu64 " " | 
 | "%" SCNu64 " %" SCNu64 " %" SCNu64 " %" SCNu64 " " | "%" SCNu64 " %" SCNu64 " %" SCNu64 " %" SCNu64 " " | 
 | "%" SCNu64 " %" SCNu64 " %" SCNu64 " %" SCNu64 " " | "%" SCNu64 " %" SCNu64 " %" SCNu64 " %" SCNu64 " " | 
| "%" SCNu64 " %" SCNu64 " %" SCNu64 " %" SCNu64 "\n", | "%" SCNu64 " %" SCNu64 " %" SCNu64 " %" SCNu64 | 
| &rx_bytes, &rx_packets, &rx_errors, &rx_drop, &rx_fifo, | "\n", | 
| &rx_frame, &rx_compressed, &rx_multicast, &tx_bytes, | &data[PROC_BYTES][0], | 
| &tx_packets, &tx_errors, &tx_drop, &tx_fifo, | &data[PROC_PACKETS][0], | 
| &tx_frame, &tx_compressed, &tx_multicast); | &data[PROC_ERRORS][0], | 
|  | &data[PROC_DROP][0], | 
|  | &data[PROC_FIFO][0], | 
|  | &data[PROC_FRAME][0], | 
|  | &data[PROC_COMPRESSED][0], | 
|  | &data[PROC_MCAST][0], | 
|  | &data[PROC_BYTES][1], | 
|  | &data[PROC_PACKETS][1], | 
|  | &data[PROC_ERRORS][1], | 
|  | &data[PROC_DROP][1], | 
|  | &data[PROC_FIFO][1], | 
|  | &data[PROC_FRAME][1], | 
|  | &data[PROC_COMPRESSED][1], | 
|  | &data[PROC_MCAST][1]); | 
|  |  | 
 | if (w != 16) | if (w != 16) | 
 | continue; | continue; | 
 |  |  | 
 | it->i_major_attr = BYTES; |  | 
 | it->i_minor_attr = PACKETS; |  | 
 |  |  | 
 | update_attr(it, BYTES, rx_bytes, tx_bytes, RX_PROVIDED|TX_PROVIDED); |  | 
 | update_attr(it, PACKETS, rx_packets, tx_packets, RX_PROVIDED|TX_PROVIDED); |  | 
 | update_attr(it, ERRORS, rx_errors, tx_errors, RX_PROVIDED|TX_PROVIDED); |  | 
 | update_attr(it, DROP, rx_drop, tx_drop, RX_PROVIDED|TX_PROVIDED); |  | 
 | update_attr(it, FIFO, rx_fifo, tx_fifo, RX_PROVIDED|TX_PROVIDED); |  | 
 | update_attr(it, FRAME, rx_frame, tx_frame, RX_PROVIDED|TX_PROVIDED); |  | 
 | update_attr(it, COMPRESSED, rx_compressed, tx_compressed, RX_PROVIDED|TX_PROVIDED); |  | 
 | update_attr(it, MULTICAST, rx_multicast, tx_multicast, RX_PROVIDED|TX_PROVIDED); |  | 
 |  |  | 
| notify_update(it, NULL); | if (!(e = element_lookup(grp, p, 0, NULL, ELEMENT_CREAT))) | 
| increase_lifetime(it, 1); | goto skip; | 
|  |  | 
|  | if (e->e_flags & ELEMENT_FLAG_CREATED) { | 
|  | if (element_set_key_attr(e, "bytes", "packets") || | 
|  | element_set_usage_attr(e, "bytes")) | 
|  | BUG(); | 
|  |  | 
|  | e->e_flags &= ~ELEMENT_FLAG_CREATED; | 
|  | } | 
|  |  | 
|  | for (i = 0; i < ARRAY_SIZE(link_attrs); i++) { | 
|  | struct attr_map *m = &link_attrs[i]; | 
|  |  | 
|  | attr_update(e, m->attrid, data[i][0], data[i][1], | 
|  | UPDATE_FLAG_RX | UPDATE_FLAG_TX); | 
|  | } | 
|  |  | 
|  | element_notify_update(e, NULL); | 
|  | element_lifesign(e, 1); | 
 | } | } | 
|  | skip: | 
 | fclose(fd); | fclose(fd); | 
 | } | } | 
 |  |  | 
| Line 107  static void print_help(void) | Line 184  static void print_help(void) | 
 | "  Author: Thomas Graf <tgraf@suug.ch>\n" \ | "  Author: Thomas Graf <tgraf@suug.ch>\n" \ | 
 | "\n" \ | "\n" \ | 
 | "  Options:\n" \ | "  Options:\n" \ | 
| "    file=PATH      Path to statistics file (default: /proc/net/dev)\n"); | "    file=PATH      Path to statistics file (default: /proc/net/dev)\n" | 
|  | "    group=NAME     Name of group\n"); | 
 | } | } | 
 |  |  | 
| static void proc_set_opts(tv_t *attrs) | static void proc_parse_opt(const char *type, const char *value) | 
 | { | { | 
| while (attrs) { | if (!strcasecmp(type, "file") && value) | 
| if (!strcasecmp(attrs->type, "file") && attrs->value) | c_path = value; | 
| c_path = attrs->value; | else if (!strcasecmp(type, "group") && value) | 
| else if (!strcasecmp(attrs->type, "help")) { | c_group = value; | 
| print_help(); | else if (!strcasecmp(type, "help")) { | 
| exit(0); | print_help(); | 
| } | exit(0); | 
| attrs = attrs->next; |  | 
 | } | } | 
 | } | } | 
 |  |  | 
 |  | static int proc_do_init(void) | 
 |  | { | 
 |  | if (attr_map_load(link_attrs, ARRAY_SIZE(link_attrs)) || | 
 |  | !(grp = group_lookup(c_group, GROUP_CREATE))) | 
 |  | BUG(); | 
 |  |  | 
 |  | return 0; | 
 |  | } | 
 |  |  | 
 | static int proc_probe(void) | static int proc_probe(void) | 
 | { | { | 
 | FILE *fd = fopen(c_path, "r"); | FILE *fd = fopen(c_path, "r"); | 
| Line 134  static int proc_probe(void) | Line 220  static int proc_probe(void) | 
 | return 0; | return 0; | 
 | } | } | 
 |  |  | 
| static struct input_module proc_ops = { | static struct bmon_module proc_ops = { | 
| .im_name = "proc", | .m_name          = "proc", | 
| .im_read = proc_read, | .m_do                = proc_read, | 
| .im_set_opts = proc_set_opts, | .m_parse_opt    = proc_parse_opt, | 
| .im_probe = proc_probe, | .m_probe = proc_probe, | 
|  | .m_init         = proc_do_init, | 
 | }; | }; | 
 |  |  | 
 | static void __init proc_init(void) | static void __init proc_init(void) | 
 | { | { | 
| register_input_module(&proc_ops); | input_register(&proc_ops); | 
 | } | } |