Root/package/wprobe/src/exporter/wprobe-export.c

1/*
2** exporter.c - example exporter
3**
4** Copyright Fraunhofer FOKUS
5**
6*/
7#include <stdio.h>
8#include <stdlib.h>
9#include <unistd.h>
10#include <string.h>
11#include <errno.h>
12
13#include <ipfix_def.h>
14#include <ipfix_def_fokus.h>
15#include <ipfix_fields_fokus.h>
16
17#include <ipfix.h>
18#include <mlog.h>
19#include <wprobe.h>
20#include <stdbool.h>
21
22static ipfix_datarecord_t g_data = { NULL, NULL, 0 };
23static int do_close = 0;
24
25struct wprobe_mapping {
26    int id;
27    bool counter;
28    const char *wprobe_id;
29    struct wprobe_value *val;
30};
31
32#ifndef ARRAY_SIZE
33#define ARRAY_SIZE(_array) (sizeof(_array) / sizeof((_array)[0]))
34#endif
35
36#define WMAP(_id, _name, ...) \
37    { \
38        .counter = false, \
39        .id = IPFIX_FT_WPROBE_##_id##_N, \
40        .wprobe_id = _name \
41        , ## __VA_ARGS__ \
42    }
43
44#define WMAP_COUNTER(_id, _name, ...) \
45    { \
46        .counter = true, \
47        .id = IPFIX_FT_WPROBE_##_id, \
48        .wprobe_id = _name \
49        , ## __VA_ARGS__ \
50    }
51
52
53#define WPROBE_OFFSET 2
54
55static struct wprobe_mapping map_globals[] = {
56    WMAP(NOISE, "noise"),
57    WMAP(PHY_BUSY, "phy_busy"),
58    WMAP(PHY_RX, "phy_rx"),
59    WMAP(PHY_TX, "phy_tx"),
60    WMAP_COUNTER(FRAMES, "frames"),
61    WMAP_COUNTER(PROBEREQ, "probereq"),
62};
63
64static struct wprobe_mapping map_perlink[] = {
65    WMAP(IEEE_TX_RATE, "tx_rate"),
66    WMAP(IEEE_RX_RATE, "rx_rate"),
67    WMAP(RSSI, "rssi"),
68    WMAP(SIGNAL, "signal"),
69    WMAP(RETRANSMIT_200, "retransmit_200"),
70    WMAP(RETRANSMIT_400, "retransmit_400"),
71    WMAP(RETRANSMIT_800, "retransmit_800"),
72    WMAP(RETRANSMIT_1600, "retransmit_1600"),
73};
74
75static unsigned char link_local[6];
76static char link_default[6];
77static int nfields = 0;
78
79#define FOKUS_USERID 12325
80
81static void
82match_template(struct wprobe_mapping *map, int n, struct list_head *list)
83{
84    struct wprobe_attribute *attr;
85    int i, j, last = -1;
86
87    list_for_each_entry(attr, list, list) {
88        for (i = 0; i < n; i++) {
89            j = (last + 1 + i) % n;
90            if (!strcmp(attr->name, map[j].wprobe_id))
91                goto found;
92        }
93        continue;
94found:
95        last = j;
96        map[j].val = &attr->val;
97        memset(&attr->val, 0, sizeof(attr->val));
98        nfields++;
99    }
100}
101
102/* name: export_ipfix_get_template()
103 */
104static ipfix_template_t *
105prepare_template(ipfix_t *handle)
106{
107    ipfix_template_t *t = NULL;
108    int size = 3 * nfields + WPROBE_OFFSET;
109    int i;
110
111    if (ipfix_new_data_template( handle, &t, size) < 0) {
112        mlogf( 0, "ipfix_new_template() failed: %s\n", strerror(errno) );
113        exit(1);
114    }
115
116    ipfix_add_field(handle, t, 0, IPFIX_FT_SOURCEMACADDRESS, 6);
117    ipfix_add_field(handle, t, 0, IPFIX_FT_DESTINATIONMACADDRESS, 6);
118
119    g_data.lens = calloc(size, sizeof(g_data.lens[0]));
120    g_data.lens[0] = 6;
121    g_data.lens[1] = 6;
122    for (i = WPROBE_OFFSET; i < size; i++)
123        g_data.lens[i] = 4;
124
125    g_data.addrs = calloc(size, sizeof(g_data.addrs[0]));
126    g_data.addrs[0] = link_local;
127    g_data.maxfields = WPROBE_OFFSET;
128    return t;
129}
130
131static void
132add_template_fields(ipfix_t *handle, ipfix_template_t *t, struct wprobe_mapping *map, int n)
133{
134    int f = g_data.maxfields;
135    int i;
136
137    for (i = 0; i < n; i++) {
138        if (!map[i].val)
139            continue;
140
141        if (map[i].counter)
142            g_data.addrs[f++] = &map[i].val->U32;
143        else
144            g_data.addrs[f++] = &map[i].val->n;
145
146        if (ipfix_add_field( handle, t, FOKUS_USERID, map[i].id + 0, 4) < 0)
147            exit(1);
148
149        if (map[i].counter)
150            continue;
151
152        g_data.lens[f] = 8;
153        g_data.addrs[f++] = &map[i].val->s;
154
155        g_data.lens[f] = 8;
156        g_data.addrs[f++] = &map[i].val->ss;
157        if (ipfix_add_field( handle, t, FOKUS_USERID, map[i].id + 1, 8) < 0)
158            exit(1);
159        if (ipfix_add_field( handle, t, FOKUS_USERID, map[i].id + 2, 8) < 0)
160            exit(1);
161    }
162    g_data.maxfields = f;
163}
164
165static void
166wprobe_dump_data(ipfix_t *ipfixh, ipfix_template_t *ipfixt, struct wprobe_iface *dev)
167{
168    struct wprobe_link *link;
169
170    wprobe_update_links(dev);
171    wprobe_request_data(dev, NULL);
172    if (list_empty(&dev->links)) {
173        g_data.addrs[1] = link_default;
174        ipfix_export_array(ipfixh, ipfixt, g_data.maxfields, g_data.addrs, g_data.lens);
175        ipfix_export_flush(ipfixh);
176    }
177    list_for_each_entry(link, &dev->links, list) {
178        g_data.addrs[1] = link->addr;
179        wprobe_request_data(dev, link->addr);
180        ipfix_export_array(ipfixh, ipfixt, g_data.maxfields, g_data.addrs, g_data.lens);
181        ipfix_export_flush(ipfixh);
182    }
183}
184
185int main ( int argc, char **argv )
186{
187    struct wprobe_iface *dev = NULL;
188    ipfix_template_t *ipfixt = NULL;
189    ipfix_t *ipfixh = NULL;
190    int protocol = IPFIX_PROTO_TCP;
191    char *chost = NULL;
192    char *ifname = NULL;
193    int sourceid = 12345;
194    int port = IPFIX_PORTNO;
195    int verbose_level = 0;
196    int opt, i = 10;
197    char *err = NULL;
198
199    while ((opt = getopt(argc, argv, "hi:c:p:vstu")) != EOF) {
200        switch (opt) {
201        case 'p':
202            if ((port=atoi(optarg)) <0) {
203                fprintf( stderr, "Invalid -p argument!\n" );
204                exit(1);
205            }
206            break;
207        case 'i':
208            ifname = optarg;
209            break;
210        case 'c':
211            chost = optarg;
212            break;
213
214        case 's':
215            protocol = IPFIX_PROTO_SCTP;
216            break;
217
218        case 't':
219            protocol = IPFIX_PROTO_TCP;
220            break;
221
222        case 'u':
223            protocol = IPFIX_PROTO_UDP;
224            break;
225
226        case 'v':
227            verbose_level ++;
228            break;
229
230        case 'h':
231        default:
232            fprintf(stderr, "usage: %s [-hstuv] -i <interface> -c <collector> [-p portno]\n"
233                     " -h this help\n"
234                     " -i <interface> wprobe interface\n"
235                     " -c <collector> collector address\n"
236                     " -p <portno> collector port number (default=%d)\n"
237                     " -s send data via SCTP\n"
238                     " -t send data via TCP (default)\n"
239                     " -u send data via UDP\n"
240                     " -v increase verbose level\n\n",
241                     argv[0], IPFIX_PORTNO );
242            exit(1);
243        }
244    }
245
246    if (!ifname) {
247        fprintf(stderr, "No interface specified\n");
248        return -1;
249    }
250
251    if (!chost) {
252        fprintf(stderr, "No collector specified\n");
253        return -1;
254    }
255
256    dev = wprobe_get_auto(ifname, &err);
257    if (!dev || (list_empty(&dev->global_attr) && list_empty(&dev->link_attr))) {
258        fprintf(stderr, "Cannot connect to wprobe on interface '%s': %s\n", ifname, (err ? err : "Unknown error"));
259        return -1;
260    }
261
262    match_template(map_globals, ARRAY_SIZE(map_globals), &dev->global_attr);
263    match_template(map_perlink, ARRAY_SIZE(map_perlink), &dev->link_attr);
264    if (nfields == 0) {
265        fprintf(stderr, "No usable attributes found\n");
266        return -1;
267    }
268
269    mlog_set_vlevel( verbose_level );
270    if (ipfix_init() < 0) {
271        fprintf( stderr, "cannot init ipfix module: %s\n", strerror(errno) );
272        exit(1);
273    }
274
275    ipfix_add_vendor_information_elements(ipfix_ft_fokus);
276    if (ipfix_open(&ipfixh, sourceid, IPFIX_VERSION) < 0) {
277        fprintf( stderr, "ipfix_open() failed: %s\n", strerror(errno) );
278        exit(1);
279    }
280
281    if (ipfix_add_collector( ipfixh, chost, port, protocol ) < 0) {
282        fprintf( stderr, "ipfix_add_collector(%s,%d) failed: %s\n",
283                 chost, port, strerror(errno));
284        exit(1);
285    }
286
287    fprintf(stderr, "Local link address: %02x:%02x:%02x:%02x:%02x:%02x\n",
288        link_local[0], link_local[1], link_local[2],
289        link_local[3], link_local[4], link_local[5]);
290
291    ipfixt = prepare_template(ipfixh);
292    add_template_fields(ipfixh, ipfixt, map_globals, ARRAY_SIZE(map_globals));
293    add_template_fields(ipfixh, ipfixt, map_perlink, ARRAY_SIZE(map_perlink));
294
295    while (!do_close) {
296        sleep(1);
297        wprobe_dump_data(ipfixh, ipfixt, dev);
298    }
299
300    ipfix_delete_template( ipfixh, ipfixt );
301    ipfix_close( ipfixh );
302    ipfix_cleanup();
303    exit(0);
304}
305

Archive Download this file



interactive