source: tools/traceends/traceends.cc @ c29a0e0

4.0.1-hotfixescachetimestampsdevelopdpdk-ndagetsilivegetfragoffhelplibtrace4ndag_formatpfringrc-4.0.1rc-4.0.2rc-4.0.3rc-4.0.4ringdecrementfixringperformanceringtimestampfixes
Last change on this file since c29a0e0 was c29a0e0, checked in by Shane Alcock <salcock@…>, 9 years ago
  • Started adding a new libtrace tool (tracetopends) which can be used to easily find the endpoints that are contributing the most traffic in a network. An endpoint can be either an IPv4 address, IPv6 address or a MAC address and output can be sorted by packet count, byte count or payload byte count.

Hopefully this will make Chris happy... :)

NOTE: manpages are just copies from tracesplit - remember to update them before release!

  • Property mode set to 100644
File size: 9.9 KB
Line 
1#include <libtrace.h>
2#include <stdio.h>
3#include <stdlib.h>
4#include <inttypes.h>
5#include <lt_inttypes.h>
6#include <getopt.h>
7#include <string.h>
8#include <assert.h>
9#include <signal.h>
10#include <time.h>
11#include <sys/socket.h>
12#include <netinet/in.h>
13#include <arpa/inet.h>
14#include <time.h>
15
16#include <map>
17
18typedef struct end_counter {
19        uint64_t src_bytes;
20        uint64_t src_pbytes;
21        uint64_t src_pkts;
22        uint64_t dst_pkts;
23        uint64_t dst_bytes;
24        uint64_t dst_pbytes;
25
26        double last_active;
27
28} end_counter_t;
29
30typedef struct mac_addr {
31        uint8_t addr[6];
32} mac_addr_t;
33
34struct v6comp {
35        bool operator() (const struct in6_addr &a, const struct in6_addr &b) const {
36                if (memcmp(&a, &b, sizeof(struct in6_addr)) < 0)
37                        return true;
38                return false;
39        }
40};
41       
42struct maccomp {
43        bool operator() (const mac_addr_t &a, const mac_addr_t &b) const {
44                if (memcmp(&a, &b, sizeof(mac_addr_t)) < 0)
45                        return true;
46                return false;
47        }
48};
49
50typedef std::map<uint32_t, end_counter_t *> IP4EndMap;
51typedef std::map<struct in6_addr, end_counter_t *, v6comp> IP6EndMap;
52typedef std::map<mac_addr_t, end_counter_t *, maccomp> MacEndMap;
53
54enum {
55        MODE_MAC,
56        MODE_IPV4,
57        MODE_IPV6
58};
59
60int mode = MODE_IPV4;
61
62IP4EndMap ipv4;
63IP6EndMap ipv6;
64MacEndMap mac;
65
66static int usage(char *argv0)
67{
68        printf("Usage:\n"
69        "%s flags inputuri [inputuri ... ] \n"
70        "-f --filter=bpf        Only output packets that match filter\n"
71        "-H --libtrace-help     Print libtrace runtime documentation\n"
72        "-a --address           Specifies which address type to match (mac, v4, v6)\n"
73        ,argv0);
74        exit(1);
75}
76
77volatile int done=0;
78
79static void cleanup_signal(int sig)
80{
81        (void)sig;
82        done=1;
83}
84
85static end_counter_t *create_counter() {
86        end_counter_t *c = (end_counter_t *)malloc(sizeof(end_counter_t));
87
88        c->src_bytes = 0;
89        c->src_pbytes = 0;
90        c->src_pkts = 0;
91        c->dst_pkts = 0;
92        c->dst_bytes = 0;
93        c->dst_pbytes = 0;
94
95        c->last_active = 0.0;
96        return c;
97}
98
99static char *mac_string(mac_addr_t m, char *str) {
100       
101       
102        snprintf(str, 80, "%02x:%02x:%02x:%02x:%02x:%02x", 
103                m.addr[0], m.addr[1], m.addr[2], m.addr[3], m.addr[4],
104                m.addr[5]);
105        return str;
106}
107
108static void dump_mac_map() {
109        MacEndMap::iterator it;
110        char str[80];
111        char timestr[80];
112        struct tm *tm;
113        time_t t;
114       
115        for (it = mac.begin(); it != mac.end(); it++) {
116                t = (time_t)(it->second->last_active);
117                tm = localtime(&t);
118                strftime(timestr, 80, "%d/%m,%H:%M:%S", tm);
119                printf("%18s %16s %16lu %16lu %16lu %16lu %16lu %16lu\n", 
120                                mac_string(it->first, str),
121                                timestr,
122                                it->second->src_pkts,
123                                it->second->src_bytes,
124                                it->second->src_pbytes,
125                                it->second->dst_pkts,
126                                it->second->dst_bytes,
127                                it->second->dst_pbytes);
128        }
129}
130
131static void dump_ipv4_map() {
132        IP4EndMap::iterator it;
133        struct in_addr in;
134        char timestr[80];
135        struct tm *tm;
136        time_t t;
137        for (it = ipv4.begin(); it != ipv4.end(); it++) {
138                in.s_addr = it->first;
139                t = (time_t)(it->second->last_active);
140                tm = localtime(&t);
141                strftime(timestr, 80, "%d/%m,%H:%M:%S", tm);
142                printf("%16s %16s %16lu %16lu %16lu %16lu %16lu %16lu\n", 
143                                inet_ntoa(in),
144                                timestr,
145                                it->second->src_pkts,
146                                it->second->src_bytes,
147                                it->second->src_pbytes,
148                                it->second->dst_pkts,
149                                it->second->dst_bytes,
150                                it->second->dst_pbytes);
151        }
152}
153
154static void dump_ipv6_map() {
155        IP6EndMap::iterator it;
156        struct in6_addr in;
157        char ip6_addr[128];
158        char timestr[80];
159        struct tm *tm;
160        time_t t;
161
162        for (it = ipv6.begin(); it != ipv6.end(); it++) {
163                in = it->first;
164                t = (time_t)(it->second->last_active);
165                tm = localtime(&t);
166                strftime(timestr, 80, "%d/%m,%H:%M:%S", tm);
167                printf("%40s %16s %16lu %16lu %16lu %16lu %16lu %16lu\n", 
168                                inet_ntop(AF_INET6, &in, ip6_addr, 128),
169                                timestr,
170                                it->second->src_pkts,
171                                it->second->src_bytes,
172                                it->second->src_pbytes,
173                                it->second->dst_pkts,
174                                it->second->dst_bytes,
175                                it->second->dst_pbytes);
176        }
177}
178
179static void update_ipv6(libtrace_ip6_t *ip, uint16_t ip_len, uint32_t rem, 
180                uint32_t plen,  double ts) {
181
182        struct in6_addr key;
183        IP6EndMap::iterator it;
184        end_counter_t *c = NULL;
185
186        if (rem < sizeof(libtrace_ip6_t))
187                return;
188       
189        key = ip->ip_src;
190       
191        it = ipv6.find(key);
192        if (it == ipv6.end()) {
193                c = create_counter();
194                ipv6[key] = c;
195        } else {
196                c = it->second;
197        }
198
199        c->src_pkts ++;
200        c->src_pbytes += plen;
201        c->src_bytes += ip_len;
202        c->last_active = ts;
203       
204        key = ip->ip_dst;
205       
206        it = ipv6.find(key);
207        if (it == ipv6.end()) {
208                c = create_counter();
209                ipv6[key] = c;
210        } else {
211                c = it->second;
212        }
213
214        c->dst_pkts ++;
215        c->dst_pbytes += plen;
216        c->dst_bytes += ip_len;
217        c->last_active = ts;
218}
219
220static void update_mac(uint8_t *src, uint8_t *dst, uint16_t ip_len,
221                uint32_t plen, double ts) {
222
223        mac_addr_t key;
224        end_counter_t *c = NULL;
225        MacEndMap::iterator it;
226
227        memcpy(&(key.addr), src, sizeof(key.addr));
228        it = mac.find(key);
229       
230        if (it == mac.end()) {
231                c = create_counter();
232                mac[key] = c;
233        } else {
234                c = it->second;
235        }
236
237        c->src_pkts ++;
238        c->src_pbytes += plen;
239        c->src_bytes += ip_len;
240        c->last_active = ts;
241
242        memcpy(&key.addr, dst, sizeof(key.addr));
243        it = mac.find(key);
244       
245        if (it == mac.end()) {
246                c = create_counter();
247                mac[key] = c;
248        } else {
249                c = it->second;
250        }
251
252        c->dst_pkts ++;
253        c->dst_pbytes += plen;
254        c->dst_bytes += ip_len;
255        c->last_active = ts;
256}
257
258static void update_ipv4(libtrace_ip_t *ip, uint16_t ip_len, uint32_t rem, 
259                uint32_t plen,  double ts) {
260
261        uint32_t key;
262        IP4EndMap::iterator it;
263        end_counter_t *c = NULL;
264
265        if (rem < sizeof(libtrace_ip_t))
266                return;
267       
268        key = ip->ip_src.s_addr;
269       
270        it = ipv4.find(key);
271        if (it == ipv4.end()) {
272                c = create_counter();
273                ipv4[key] = c;
274        } else {
275                c = it->second;
276        }
277
278        c->src_pkts ++;
279        c->src_pbytes += plen;
280        c->src_bytes += ip->ip_len;
281        c->last_active = ts;
282       
283        key = ip->ip_dst.s_addr;
284       
285        it = ipv4.find(key);
286        if (it == ipv4.end()) {
287                c = create_counter();
288                ipv4[key] = c;
289        } else {
290                c = it->second;
291        }
292
293        c->dst_pkts ++;
294        c->dst_pbytes += plen;
295        c->dst_bytes += ip_len;
296        c->last_active = ts;
297}
298
299static int per_packet(libtrace_packet_t *packet) {
300
301        void *header;
302        uint16_t ethertype;
303        uint32_t rem;
304        uint16_t ip_len = 0;
305        uint32_t plen = trace_get_payload_length(packet);
306        double ts = trace_get_seconds(packet);
307        libtrace_ip_t *ip = NULL;
308        libtrace_ip6_t *ip6 = NULL;
309        uint8_t *src_mac, *dst_mac;
310
311        header = trace_get_layer3(packet, &ethertype, &rem);
312
313        if (header == NULL || rem == 0)
314                return 1;
315       
316        if (ethertype == TRACE_ETHERTYPE_IP) {
317                ip = (libtrace_ip_t *)header;
318                if (rem < sizeof(libtrace_ip_t))
319                        return 1;
320                ip_len = ntohs(ip->ip_len);
321                if (mode == MODE_IPV4 && ip) {
322                        update_ipv4(ip, ip_len, rem, plen, ts);
323                        return 1;
324                }
325        }
326
327        if (ethertype == TRACE_ETHERTYPE_IPV6) {
328                ip6 = (libtrace_ip6_t *)header;
329                if (rem < sizeof(libtrace_ip6_t))
330                        return 1;
331                ip_len = ntohs(ip6->plen) + sizeof(libtrace_ip6_t);
332                if (mode == MODE_IPV6 && ip6) {
333                        update_ipv6(ip6, ip_len, rem, plen, ts);
334                        return 1;
335                }
336        }
337
338        if (mode == MODE_MAC) {
339                src_mac = trace_get_source_mac(packet);
340                dst_mac = trace_get_destination_mac(packet);
341
342                if (src_mac == NULL || dst_mac == NULL)
343                        return 1;
344                update_mac(src_mac, dst_mac, ip_len, plen, ts);
345        }
346
347        return 1;
348}
349
350int main(int argc, char *argv[]) {
351
352        int i;
353        struct sigaction sigact;
354        struct libtrace_filter_t *filter=NULL;
355        struct libtrace_t *input = NULL;
356        struct libtrace_packet_t *packet = trace_create_packet();
357
358        while(1) {
359                int option_index;
360                struct option long_options[] = {
361                        { "filter",        1, 0, 'f' },
362                        { "libtrace-help", 0, 0, 'H' },
363                        { "addresses",     1, 0, 'a' }, 
364                        { NULL,            0, 0, 0   },
365                };
366
367                int c=getopt_long(argc, argv, "a:f:H",
368                                long_options, &option_index);
369
370                if (c==-1)
371                        break;
372                switch (c) {
373                        case 'a':
374                                if (strncmp(optarg, "mac", 3) == 0)
375                                        mode = MODE_MAC;
376                                if (strncmp(optarg, "v4", 2) == 0)
377                                        mode = MODE_IPV4;
378                                if (strncmp(optarg, "v6", 2) == 0)
379                                        mode = MODE_IPV6;
380                                break;
381
382                        case 'f': filter=trace_create_filter(optarg);
383                                break;
384                        case 'H':
385                                usage(argv[0]);
386                                break;
387                        default:
388                                fprintf(stderr,"Unknown option: %c\n",c);
389                                usage(argv[0]);
390                                return 1;
391                }
392
393        }
394        sigact.sa_handler = cleanup_signal;
395        sigemptyset(&sigact.sa_mask);
396        sigact.sa_flags = SA_RESTART;
397
398        sigaction(SIGINT, &sigact, NULL);
399        sigaction(SIGTERM, &sigact, NULL);
400        sigaction(SIGPIPE, &sigact, NULL);
401        sigaction(SIGHUP, &sigact, NULL);
402
403        for (i = optind; i < argc; i++) {
404                input = trace_create(argv[i]);
405
406                if (trace_is_err(input)) {
407                        trace_perror(input,"%s",argv[i]);
408                        return 1;
409                }
410
411                if (filter && trace_config(input, TRACE_OPTION_FILTER, filter) == 1) {
412                        trace_perror(input, "Configuring filter for %s",
413                                        argv[i]);
414                        return 1;
415                }
416
417                if (trace_start(input)==-1) {
418                        trace_perror(input,"%s",argv[i]);
419                        return 1;
420                }
421
422                while (trace_read_packet(input,packet)>0) {
423                        if (per_packet(packet) < 1)
424                                done = 1;
425                        if (done)
426                                break;
427                }
428
429                if (done)
430                        break;
431
432                if (trace_is_err(input)) {
433                        trace_perror(input,"Reading packets");
434                        trace_destroy(input);
435                        break;
436                }
437
438                trace_destroy(input);
439        }
440
441        /* Dump results */
442        if (mode == MODE_IPV4)
443                dump_ipv4_map();
444        if (mode == MODE_IPV6)
445                dump_ipv6_map();
446        if (mode == MODE_MAC)
447                dump_mac_map();
448        return 0;
449}
Note: See TracBrowser for help on using the repository browser.