source: tools/traceends/traceends.cc @ 97d170d

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