diff options
Diffstat (limited to 'package/wprobe/src/exporter/wprobe-export.c')
-rw-r--r-- | package/wprobe/src/exporter/wprobe-export.c | 295 |
1 files changed, 295 insertions, 0 deletions
diff --git a/package/wprobe/src/exporter/wprobe-export.c b/package/wprobe/src/exporter/wprobe-export.c new file mode 100644 index 0000000000..974f4a10f3 --- /dev/null +++ b/package/wprobe/src/exporter/wprobe-export.c @@ -0,0 +1,295 @@ +/* +** exporter.c - example exporter +** +** Copyright Fraunhofer FOKUS +** +*/ +#include <stdio.h> +#include <stdlib.h> +#include <unistd.h> +#include <string.h> +#include <errno.h> + +#include <ipfix_def.h> +#include <ipfix_def_fokus.h> +#include <ipfix_fields_fokus.h> + +#include <ipfix.h> +#include <mlog.h> +#include <wprobe.h> + +static ipfix_datarecord_t g_data = { NULL, NULL, 0 }; +static int do_close = 0; + +struct wprobe_mapping { + int id; + float scale; + const char *wprobe_id; + struct wprobe_value *val; +}; + +#ifndef ARRAY_SIZE +#define ARRAY_SIZE(_array) (sizeof(_array) / sizeof((_array)[0])) +#endif + +#define WMAP(_id, _name, ...) \ + { \ + .scale = 1.0f, \ + .id = IPFIX_FT_WPROBE_##_id##_AVG, \ + .wprobe_id = _name \ + , ## __VA_ARGS__ \ + } + +#define WPROBE_OFFSET 2 + +static struct wprobe_mapping map_globals[] = { + WMAP(NOISE, "noise"), + WMAP(PHY_BUSY, "phy_busy"), + WMAP(PHY_RX, "phy_rx"), + WMAP(PHY_TX, "phy_tx"), +}; + +static struct wprobe_mapping map_perlink[] = { + WMAP(IEEE_TX_RATE, "tx_rate", .scale = 10.0f), + WMAP(IEEE_RX_RATE, "rx_rate", .scale = 10.0f), + WMAP(RSSI, "rssi"), + WMAP(SIGNAL, "signal"), + WMAP(RETRANSMIT_200, "retransmit_200"), + WMAP(RETRANSMIT_400, "retransmit_400"), + WMAP(RETRANSMIT_800, "retransmit_800"), + WMAP(RETRANSMIT_1600, "retransmit_1600"), +}; + +static unsigned char link_local[6]; +static char link_default[6]; +static LIST_HEAD(global_attr); +static LIST_HEAD(link_attr); +static LIST_HEAD(links); +static int nfields = 0; + +#define FOKUS_USERID 12325 + +static void +match_template(struct wprobe_mapping *map, int n, struct list_head *list) +{ + struct wprobe_attribute *attr; + int i, j, last = -1; + + list_for_each_entry(attr, list, list) { + for (i = 0; i < n; i++) { + j = (last + 1 + i) % n; + if (!strcmp(attr->name, map[j].wprobe_id)) + goto found; + } + continue; +found: + last = j; + map[j].val = &attr->val; + memset(&attr->val, 0, sizeof(attr->val)); + nfields++; + } +} + +/* name: export_ipfix_get_template() + */ +static ipfix_template_t * +prepare_template(ipfix_t *handle) +{ + ipfix_template_t *t = NULL; + int size = 3 * nfields + WPROBE_OFFSET; + int i; + + if (ipfix_new_data_template( handle, &t, size) < 0) { + mlogf( 0, "ipfix_new_template() failed: %s\n", strerror(errno) ); + exit(1); + } + + ipfix_add_field(handle, t, 0, IPFIX_FT_SOURCEMACADDRESS, 6); + ipfix_add_field(handle, t, 0, IPFIX_FT_DESTINATIONMACADDRESS, 6); + + g_data.lens = calloc(size, sizeof(g_data.lens[0])); + g_data.lens[0] = 6; + g_data.lens[1] = 6; + for (i = WPROBE_OFFSET; i < size; i++) + g_data.lens[i] = 4; + + g_data.addrs = calloc(size, sizeof(g_data.addrs[0])); + g_data.addrs[0] = link_local; + g_data.maxfields = WPROBE_OFFSET; + return t; +} + +static void +add_template_fields(ipfix_t *handle, ipfix_template_t *t, struct wprobe_mapping *map, int n) +{ + int f = g_data.maxfields; + int i; + + for (i = 0; i < n; i++) { + if (!map[i].val) + continue; + + g_data.addrs[f++] = &map[i].val->avg; + g_data.addrs[f++] = &map[i].val->stdev; + g_data.addrs[f++] = &map[i].val->n; + + if (ipfix_add_field( handle, t, FOKUS_USERID, map[i].id + 0, 4) < 0) + exit(1); + if (ipfix_add_field( handle, t, FOKUS_USERID, map[i].id + 1, 4) < 0) + exit(1); + if (ipfix_add_field( handle, t, FOKUS_USERID, map[i].id + 2, 4) < 0) + exit(1); + } + g_data.maxfields = f; +} + +static void +wprobe_dump_data(ipfix_t *ipfixh, ipfix_template_t *ipfixt, const char *ifname, struct list_head *gl, struct list_head *ll, struct list_head *ls) +{ + struct wprobe_link *link; + + wprobe_update_links(ifname, ls); + wprobe_request_data(ifname, gl, NULL, 2); + if (list_empty(ls)) { + g_data.addrs[1] = link_default; + ipfix_export_array(ipfixh, ipfixt, g_data.maxfields, g_data.addrs, g_data.lens); + ipfix_export_flush(ipfixh); + } + list_for_each_entry(link, ls, list) { + g_data.addrs[1] = link->addr; + wprobe_request_data(ifname, ll, link->addr, 2); + ipfix_export_array(ipfixh, ipfixt, g_data.maxfields, g_data.addrs, g_data.lens); + ipfix_export_flush(ipfixh); + } +} + +int main ( int argc, char **argv ) +{ + ipfix_template_t *ipfixt = NULL; + ipfix_t *ipfixh = NULL; + int protocol = IPFIX_PROTO_TCP; + char *chost = NULL; + char *ifname = NULL; + int sourceid = 12345; + int port = IPFIX_PORTNO; + int verbose_level = 0; + int opt, i = 10; + + while ((opt = getopt(argc, argv, "hi:c:p:vstu")) != EOF) { + switch (opt) { + case 'p': + if ((port=atoi(optarg)) <0) { + fprintf( stderr, "Invalid -p argument!\n" ); + exit(1); + } + break; + case 'i': + ifname = optarg; + break; + case 'c': + chost = optarg; + break; + + case 's': + protocol = IPFIX_PROTO_SCTP; + break; + + case 't': + protocol = IPFIX_PROTO_TCP; + break; + + case 'u': + protocol = IPFIX_PROTO_UDP; + break; + + case 'v': + verbose_level ++; + break; + + case 'h': + default: + fprintf(stderr, "usage: %s [-hstuv] -i <interface> -c <collector> [-p portno]\n" + " -h this help\n" + " -i <interface> wprobe interface\n" + " -c <collector> collector address\n" + " -p <portno> collector port number (default=%d)\n" + " -s send data via SCTP\n" + " -t send data via TCP (default)\n" + " -u send data via UDP\n" + " -v increase verbose level\n\n", + argv[0], IPFIX_PORTNO ); + exit(1); + } + } + + if (!ifname) { + fprintf(stderr, "No interface specified\n"); + return -1; + } + + if (!chost) { + fprintf(stderr, "No collector specified\n"); + return -1; + } + + if (wprobe_init() != 0) { + fprintf(stderr, "wprobe init failed\n"); + return -1; + } + + wprobe_dump_attributes(ifname, false, &global_attr, (char *) link_local); + wprobe_dump_attributes(ifname, true, &link_attr, NULL); + if (list_empty(&global_attr) && list_empty(&link_attr)) { + fprintf(stderr, "Cannot connect to wprobe on interface '%s'\n", ifname); + return -1; + } + + match_template(map_globals, ARRAY_SIZE(map_globals), &global_attr); + match_template(map_perlink, ARRAY_SIZE(map_perlink), &link_attr); + if (nfields == 0) { + fprintf(stderr, "No usable attributes found\n"); + return -1; + } + + mlog_set_vlevel( verbose_level ); + if (ipfix_init() < 0) { + fprintf( stderr, "cannot init ipfix module: %s\n", strerror(errno) ); + exit(1); + } + + ipfix_add_vendor_information_elements(ipfix_ft_fokus); + if (ipfix_open(&ipfixh, sourceid, IPFIX_VERSION) < 0) { + fprintf( stderr, "ipfix_open() failed: %s\n", strerror(errno) ); + exit(1); + } + + if (ipfix_add_collector( ipfixh, chost, port, protocol ) < 0) { + fprintf( stderr, "ipfix_add_collector(%s,%d) failed: %s\n", + chost, port, strerror(errno)); + exit(1); + } + + fprintf(stderr, "Local link address: %02x:%02x:%02x:%02x:%02x:%02x\n", + link_local[0], link_local[1], link_local[2], + link_local[3], link_local[4], link_local[5]); + + ipfixt = prepare_template(ipfixh); + add_template_fields(ipfixh, ipfixt, map_globals, ARRAY_SIZE(map_globals)); + add_template_fields(ipfixh, ipfixt, map_perlink, ARRAY_SIZE(map_perlink)); + + while (!do_close) { + usleep(100 * 1000); + wprobe_measure(ifname); + + if (i-- > 0) + continue; + + i = 10; + wprobe_dump_data(ipfixh, ipfixt, ifname, &global_attr, &link_attr, &links); + } + + ipfix_delete_template( ipfixh, ipfixt ); + ipfix_close( ipfixh ); + ipfix_cleanup(); + exit(0); +} |