source: tools/traceends/traceends.cc @ 8485d99

4.0.1-hotfixescachetimestampsdevelopdpdk-ndagetsilivendag_formatrc-4.0.1rc-4.0.2rc-4.0.3rc-4.0.4ringdecrementfixringperformanceringtimestampfixes
Last change on this file since 8485d99 was ee6e802, checked in by Shane Alcock <salcock@…>, 5 years ago

Updated copyright blurb on all source files

In some cases, this meant adding copyright blurbs to files that
had never had them before.

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