source: tools/traceends/traceends.cc @ a141264

4.0.1-hotfixescachetimestampsdevelopdpdk-ndagetsilivegetfragoffhelplibtrace4ndag_formatpfringrc-4.0.1rc-4.0.2rc-4.0.3rc-4.0.4ringdecrementfixringperformanceringtimestampfixes
Last change on this file since a141264 was a141264, checked in by Shane Alcock <salcock@…>, 10 years ago
  • Fixed warning on 32 bit machines when building traceends
  • 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}
86
87static end_counter_t *create_counter() {
88        end_counter_t *c = (end_counter_t *)malloc(sizeof(end_counter_t));
89
90        c->src_bytes = 0;
91        c->src_pbytes = 0;
92        c->src_pkts = 0;
93        c->dst_pkts = 0;
94        c->dst_bytes = 0;
95        c->dst_pbytes = 0;
96
97        c->last_active = 0.0;
98        return c;
99}
100
101static char *mac_string(mac_addr_t m, char *str) {
102       
103       
104        snprintf(str, 80, "%02x:%02x:%02x:%02x:%02x:%02x", 
105                m.addr[0], m.addr[1], m.addr[2], m.addr[3], m.addr[4],
106                m.addr[5]);
107        return str;
108}
109
110static void dump_mac_map() {
111        MacEndMap::iterator it;
112        char str[80];
113        char timestr[80];
114        struct tm *tm;
115        time_t t;
116       
117        for (it = mac.begin(); it != mac.end(); it++) {
118                t = (time_t)(it->second->last_active);
119                tm = localtime(&t);
120                strftime(timestr, 80, "%d/%m,%H:%M:%S", tm);
121                printf("%18s %16s %" PRIu64 " %" PRIu64 " %" PRIu64 " %" PRIu64 " %" PRIu64 " %" PRIu64 "\n", 
122                                mac_string(it->first, str),
123                                timestr,
124                                it->second->src_pkts,
125                                it->second->src_bytes,
126                                it->second->src_pbytes,
127                                it->second->dst_pkts,
128                                it->second->dst_bytes,
129                                it->second->dst_pbytes);
130        }
131}
132
133static void dump_ipv4_map() {
134        IP4EndMap::iterator it;
135        struct in_addr in;
136        char timestr[80];
137        struct tm *tm;
138        time_t t;
139        for (it = ipv4.begin(); it != ipv4.end(); it++) {
140                in.s_addr = it->first;
141                t = (time_t)(it->second->last_active);
142                tm = localtime(&t);
143                strftime(timestr, 80, "%d/%m,%H:%M:%S", tm);
144                printf("%16s %16s %" PRIu64 " %" PRIu64 " %" PRIu64 " %" PRIu64 " %" PRIu64 " %" PRIu64 "\n", 
145                                inet_ntoa(in),
146                                timestr,
147                                it->second->src_pkts,
148                                it->second->src_bytes,
149                                it->second->src_pbytes,
150                                it->second->dst_pkts,
151                                it->second->dst_bytes,
152                                it->second->dst_pbytes);
153        }
154}
155
156static void dump_ipv6_map() {
157        IP6EndMap::iterator it;
158        struct in6_addr in;
159        char ip6_addr[128];
160        char timestr[80];
161        struct tm *tm;
162        time_t t;
163
164        for (it = ipv6.begin(); it != ipv6.end(); it++) {
165                in = it->first;
166                t = (time_t)(it->second->last_active);
167                tm = localtime(&t);
168                strftime(timestr, 80, "%d/%m,%H:%M:%S", tm);
169                printf("%40s %16s %" PRIu64 " %" PRIu64 " %" PRIu64 " %" PRIu64 " %" PRIu64 " %" PRIu64 "\n", 
170                                inet_ntop(AF_INET6, &in, ip6_addr, 128),
171                                timestr,
172                                it->second->src_pkts,
173                                it->second->src_bytes,
174                                it->second->src_pbytes,
175                                it->second->dst_pkts,
176                                it->second->dst_bytes,
177                                it->second->dst_pbytes);
178        }
179}
180
181static void update_ipv6(libtrace_ip6_t *ip, uint16_t ip_len, uint32_t rem, 
182                uint32_t plen,  double ts) {
183
184        struct in6_addr key;
185        IP6EndMap::iterator it;
186        end_counter_t *c = NULL;
187
188        if (rem < sizeof(libtrace_ip6_t))
189                return;
190       
191        key = ip->ip_src;
192       
193        it = ipv6.find(key);
194        if (it == ipv6.end()) {
195                c = create_counter();
196                ipv6[key] = c;
197        } else {
198                c = it->second;
199        }
200
201        c->src_pkts ++;
202        c->src_pbytes += plen;
203        c->src_bytes += ip_len;
204        c->last_active = ts;
205       
206        key = ip->ip_dst;
207       
208        it = ipv6.find(key);
209        if (it == ipv6.end()) {
210                c = create_counter();
211                ipv6[key] = c;
212        } else {
213                c = it->second;
214        }
215
216        c->dst_pkts ++;
217        c->dst_pbytes += plen;
218        c->dst_bytes += ip_len;
219        c->last_active = ts;
220}
221
222static void update_mac(uint8_t *src, uint8_t *dst, uint16_t ip_len,
223                uint32_t plen, double ts) {
224
225        mac_addr_t key;
226        end_counter_t *c = NULL;
227        MacEndMap::iterator it;
228
229        memcpy(&(key.addr), src, sizeof(key.addr));
230        it = mac.find(key);
231       
232        if (it == mac.end()) {
233                c = create_counter();
234                mac[key] = c;
235        } else {
236                c = it->second;
237        }
238
239        c->src_pkts ++;
240        c->src_pbytes += plen;
241        c->src_bytes += ip_len;
242        c->last_active = ts;
243
244        memcpy(&key.addr, dst, sizeof(key.addr));
245        it = mac.find(key);
246       
247        if (it == mac.end()) {
248                c = create_counter();
249                mac[key] = c;
250        } else {
251                c = it->second;
252        }
253
254        c->dst_pkts ++;
255        c->dst_pbytes += plen;
256        c->dst_bytes += ip_len;
257        c->last_active = ts;
258}
259
260static void update_ipv4(libtrace_ip_t *ip, uint16_t ip_len, uint32_t rem, 
261                uint32_t plen,  double ts) {
262
263        uint32_t key;
264        IP4EndMap::iterator it;
265        end_counter_t *c = NULL;
266
267        if (rem < sizeof(libtrace_ip_t))
268                return;
269       
270        key = ip->ip_src.s_addr;
271       
272        it = ipv4.find(key);
273        if (it == ipv4.end()) {
274                c = create_counter();
275                ipv4[key] = c;
276        } else {
277                c = it->second;
278        }
279
280        c->src_pkts ++;
281        c->src_pbytes += plen;
282        c->src_bytes += ip->ip_len;
283        c->last_active = ts;
284       
285        key = ip->ip_dst.s_addr;
286       
287        it = ipv4.find(key);
288        if (it == ipv4.end()) {
289                c = create_counter();
290                ipv4[key] = c;
291        } else {
292                c = it->second;
293        }
294
295        c->dst_pkts ++;
296        c->dst_pbytes += plen;
297        c->dst_bytes += ip_len;
298        c->last_active = ts;
299}
300
301static int per_packet(libtrace_packet_t *packet) {
302
303        void *header;
304        uint16_t ethertype;
305        uint32_t rem;
306        uint16_t ip_len = 0;
307        uint32_t plen = trace_get_payload_length(packet);
308        double ts = trace_get_seconds(packet);
309        libtrace_ip_t *ip = NULL;
310        libtrace_ip6_t *ip6 = NULL;
311        uint8_t *src_mac, *dst_mac;
312
313        header = trace_get_layer3(packet, &ethertype, &rem);
314
315        if (header == NULL || rem == 0)
316                return 1;
317       
318        if (ethertype == TRACE_ETHERTYPE_IP) {
319                ip = (libtrace_ip_t *)header;
320                if (rem < sizeof(libtrace_ip_t))
321                        return 1;
322                ip_len = ntohs(ip->ip_len);
323                if (mode == MODE_IPV4 && ip) {
324                        update_ipv4(ip, ip_len, rem, plen, ts);
325                        return 1;
326                }
327        }
328
329        if (ethertype == TRACE_ETHERTYPE_IPV6) {
330                ip6 = (libtrace_ip6_t *)header;
331                if (rem < sizeof(libtrace_ip6_t))
332                        return 1;
333                ip_len = ntohs(ip6->plen) + sizeof(libtrace_ip6_t);
334                if (mode == MODE_IPV6 && ip6) {
335                        update_ipv6(ip6, ip_len, rem, plen, ts);
336                        return 1;
337                }
338        }
339
340        if (mode == MODE_MAC) {
341                src_mac = trace_get_source_mac(packet);
342                dst_mac = trace_get_destination_mac(packet);
343
344                if (src_mac == NULL || dst_mac == NULL)
345                        return 1;
346                update_mac(src_mac, dst_mac, ip_len, plen, ts);
347        }
348
349        return 1;
350}
351
352int main(int argc, char *argv[]) {
353
354        int i;
355        struct sigaction sigact;
356        struct libtrace_filter_t *filter=NULL;
357        struct libtrace_t *input = NULL;
358        struct libtrace_packet_t *packet = trace_create_packet();
359
360        while(1) {
361                int option_index;
362                struct option long_options[] = {
363                        { "filter",        1, 0, 'f' },
364                        { "help",          0, 0, 'H' },
365                        { "addresses",     1, 0, 'A' }, 
366                        { NULL,            0, 0, 0   },
367                };
368
369                int c=getopt_long(argc, argv, "A:f:H",
370                                long_options, &option_index);
371
372                if (c==-1)
373                        break;
374                switch (c) {
375                        case 'A':
376                                if (strncmp(optarg, "mac", 3) == 0)
377                                        mode = MODE_MAC;
378                                else if (strncmp(optarg, "v4", 2) == 0)
379                                        mode = MODE_IPV4;
380                                else if (strncmp(optarg, "v6", 2) == 0)
381                                        mode = MODE_IPV6;
382                                else {
383                                        fprintf(stderr, "Invalid address type, must be either mac, v4 or v6\n");
384                                        return 1;
385                                }
386                                break;
387
388                        case 'f': filter=trace_create_filter(optarg);
389                                break;
390                        case 'H':
391                                usage(argv[0]);
392                                break;
393                        default:
394                                fprintf(stderr,"Unknown option: %c\n",c);
395                                usage(argv[0]);
396                                return 1;
397                }
398
399        }
400        sigact.sa_handler = cleanup_signal;
401        sigemptyset(&sigact.sa_mask);
402        sigact.sa_flags = SA_RESTART;
403
404        sigaction(SIGINT, &sigact, NULL);
405        sigaction(SIGTERM, &sigact, NULL);
406        sigaction(SIGPIPE, &sigact, NULL);
407        sigaction(SIGHUP, &sigact, NULL);
408
409        for (i = optind; i < argc; i++) {
410                input = trace_create(argv[i]);
411
412                if (trace_is_err(input)) {
413                        trace_perror(input,"%s",argv[i]);
414                        return 1;
415                }
416
417                if (filter && trace_config(input, TRACE_OPTION_FILTER, filter) == 1) {
418                        trace_perror(input, "Configuring filter for %s",
419                                        argv[i]);
420                        return 1;
421                }
422
423                if (trace_start(input)==-1) {
424                        trace_perror(input,"%s",argv[i]);
425                        return 1;
426                }
427
428                while (trace_read_packet(input,packet)>0) {
429                        if (per_packet(packet) < 1)
430                                done = 1;
431                        if (done)
432                                break;
433                }
434
435                if (done)
436                        break;
437
438                if (trace_is_err(input)) {
439                        trace_perror(input,"Reading packets");
440                        trace_destroy(input);
441                        break;
442                }
443
444                trace_destroy(input);
445        }
446
447        /* Dump results */
448        if (mode == MODE_IPV4)
449                dump_ipv4_map();
450        if (mode == MODE_IPV6)
451                dump_ipv6_map();
452        if (mode == MODE_MAC)
453                dump_mac_map();
454        return 0;
455}
Note: See TracBrowser for help on using the repository browser.