source: tools/tracestats/tracestats.c @ 8e11beb

cachetimestampsdevelopdpdk-ndagetsilivendag_formatrc-4.0.2rc-4.0.3rc-4.0.4ringdecrementfixringperformance
Last change on this file since 8e11beb was 8e11beb, checked in by Shane Alcock <salcock@…>, 3 years ago

Update tools to properly ignore meta records and missing timestamps

pcapng introduces a lot of meta records that we should preserve as
long as possible. Since we aren't automatically discarding them,
we need to make sure that our tools do not try to treat them as
"real" packets, i.e. try to get a timestamp or capture length from
them.

Similarly, simple pcapng packet records do not have a timestamp
so we need to make sure the tools do the right thing when
trace_get_seconds() returns a timestamp of zero on a packet. For
starters, we don't want to set our "first" packet time to zero
in that case!

  • Property mode set to 100644
File size: 8.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/*
29 * This program takes a series of traces and bpf filters and outputs how many
30 * bytes/packets
31 */
32
33#include <stdio.h>
34#include <stdlib.h>
35#include <assert.h>
36#include <string.h>
37#include <sys/time.h>
38#include <sys/types.h>
39#include <time.h>
40
41#include <netinet/in.h>
42#include <netinet/in_systm.h>
43#include <netinet/tcp.h>
44#include <netinet/ip.h>
45#include <netinet/ip_icmp.h>
46#include <arpa/inet.h>
47#include <sys/socket.h>
48#include <getopt.h>
49#include <inttypes.h>
50#include <signal.h>
51
52#include "libtrace_parallel.h"
53#include "lt_inttypes.h"
54#include <pthread.h>
55
56struct libtrace_t *trace = NULL;
57
58static void cleanup_signal(int signal UNUSED)
59{
60        if (trace)
61                trace_pstop(trace);
62}
63
64struct filter_t {
65        char *expr;
66        struct libtrace_filter_t *filter;
67} *filters = NULL;
68
69int filter_count=0;
70
71
72typedef struct statistics {
73        uint64_t count;
74        uint64_t bytes;
75} statistics_t;
76
77volatile uint64_t totcount = 0;
78volatile uint64_t totbytes = 0;
79
80
81static void fn_result(libtrace_t *trace UNUSED,
82                libtrace_thread_t *sender UNUSED,
83                void *global UNUSED, void *tls,
84                libtrace_result_t *result) {
85        statistics_t *counters = (statistics_t *)tls;
86        int i;
87
88        assert(result->key == 0);
89        statistics_t * res = result->value.ptr;
90        counters[0].count += res[0].count;
91        counters[0].bytes += res[0].bytes;
92
93        for (i = 0; i < filter_count; i++) {
94                counters[i+1].count += res[i+1].count;
95                counters[i+1].bytes += res[i+1].bytes;
96        }
97        free(res);
98}
99
100static void fn_print_results(libtrace_t *trace, 
101                libtrace_thread_t *sender UNUSED, void *global UNUSED,
102                void *tls) {
103
104        statistics_t *counters = (statistics_t *)tls;
105        libtrace_stat_t *stats = NULL;
106        int i;
107
108        stats = trace_get_statistics(trace, NULL);
109        printf("%-30s\t%12s\t%12s\t%7s\n","filter","count","bytes","%");
110        for(i=0;i<filter_count;++i) {
111                printf("%30s:\t%12"PRIu64"\t%12"PRIu64"\t%7.03f\n",filters[i].expr,counters[i+1].count,counters[i+1].bytes,counters[i+1].count*100.0/counters[0].count);
112        }
113        if (stats->received_valid)
114                fprintf(stderr,"%30s:\t%12" PRIu64"\n",
115                                "Input packets", stats->received);
116        if (stats->filtered_valid)
117                fprintf(stderr,"%30s:\t%12" PRIu64"\n",
118                                "Filtered packets", stats->filtered);
119        if (stats->dropped_valid)
120                fprintf(stderr,"%30s:\t%12" PRIu64"\n",
121                                "Dropped packets",stats->dropped);
122        if (stats->accepted_valid)
123                fprintf(stderr,"%30s:\t%12" PRIu64 "\n",
124                                "Accepted packets", stats->accepted);
125        if (stats->errors_valid)
126                fprintf(stderr,"%30s:\t%12" PRIu64 "\n",
127                                "Erred packets", stats->errors);
128        printf("%30s:\t%12"PRIu64"\t%12" PRIu64 "\n","Total",counters[0].count,counters[0].bytes);
129        totcount+=counters[0].count;
130        totbytes+=counters[0].bytes;
131
132}
133
134
135static void* fn_starting(libtrace_t *trace UNUSED, libtrace_thread_t *t UNUSED, void *global UNUSED) {
136        /* Allocate space to hold a total count and one for each filter */
137        return calloc(1, sizeof(statistics_t) * (filter_count + 1));
138}
139
140
141static void fn_stopping(libtrace_t *trace, libtrace_thread_t *t UNUSED,
142                        void *global UNUSED, void*tls) {
143        statistics_t *results = (statistics_t *)tls;
144        libtrace_generic_t gen;
145        /* We only output one result per thread with the key 0 when the
146         * trace is over. */
147        gen.ptr = results;
148        trace_publish_result(trace, t, 0, gen, RESULT_USER);
149}
150
151static libtrace_packet_t* fn_packet(libtrace_t *trace,
152                libtrace_thread_t *t UNUSED,
153                void *global UNUSED, void*tls, libtrace_packet_t *pkt) {
154        statistics_t *results = (statistics_t *)tls;
155        int i, wlen;
156
157        if (IS_LIBTRACE_META_PACKET(pkt))
158                return pkt;
159
160        /* Apply filters to every packet note the result */
161        wlen = trace_get_wire_length(pkt);
162        for(i=0;i<filter_count;++i) {
163                if (filters[i].filter == NULL)
164                        continue;
165                if(trace_apply_filter(filters[i].filter,pkt) > 0) {
166                        results[i+1].count++;
167                        results[i+1].bytes+=wlen;
168                }
169                if (trace_is_err(trace)) {
170                        trace_perror(trace, "trace_apply_filter");
171                        fprintf(stderr, "Removing filter from filterlist\n");
172                        /* This is a race, but will be atomic */
173                        filters[i].filter = NULL;
174                }
175        }
176        results[0].count++;
177        results[0].bytes +=wlen;
178        return pkt;
179}
180
181/* Process a trace, counting packets that match filter(s) */
182static void run_trace(char *uri, int threadcount)
183{
184
185        fprintf(stderr,"%s:\n",uri);
186        libtrace_callback_set_t *pktcbs, *rescbs;
187
188        trace = trace_create(uri);
189
190        if (trace_is_err(trace)) {
191                trace_perror(trace,"Failed to create trace");
192                return;
193        }
194
195        pktcbs = trace_create_callback_set();
196        rescbs = trace_create_callback_set();
197
198        trace_set_packet_cb(pktcbs, fn_packet);
199        trace_set_starting_cb(pktcbs, fn_starting);
200        trace_set_stopping_cb(pktcbs, fn_stopping);
201        trace_set_starting_cb(rescbs, fn_starting);
202        trace_set_result_cb(rescbs, fn_result);
203        trace_set_stopping_cb(rescbs, fn_print_results);
204
205        if (threadcount != 0)
206                trace_set_perpkt_threads(trace, threadcount);
207
208        /* Start the trace as a parallel trace */
209        if (trace_pstart(trace, NULL, pktcbs, rescbs)==-1) {
210                trace_perror(trace,"Failed to start trace");
211                return;
212        }
213
214        /* Wait for all threads to stop */
215        trace_join(trace);
216
217        if (trace_is_err(trace))
218                trace_perror(trace,"%s",uri);
219
220        trace_destroy(trace);
221        trace_destroy_callback_set(pktcbs);
222        trace_destroy_callback_set(rescbs);
223}
224
225static void usage(char *argv0)
226{
227        fprintf(stderr,"Usage: %s [-h|--help] [--threads|-t threads] [--filter|-f bpf ]... libtraceuri...\n",argv0);
228}
229
230int main(int argc, char *argv[]) {
231
232        int i;
233        struct sigaction sigact;
234        int threadcount = 1;
235
236        while(1) {
237                int option_index;
238                struct option long_options[] = {
239                        { "filter",        1, 0, 'f' },
240                        { "help", 0, 0, 'h' },
241                        { "threads",            1, 0, 't' },
242                        { NULL,            0, 0, 0   },
243                };
244
245                int c=getopt_long(argc, argv, "f:ht:",
246                                long_options, &option_index);
247
248                if (c==-1)
249                        break;
250
251                switch (c) {
252                        case 'f':
253                                ++filter_count;
254                                filters=realloc(filters,filter_count*sizeof(struct filter_t));
255                                filters[filter_count-1].expr=strdup(optarg);
256                                filters[filter_count-1].filter=trace_create_filter(optarg);
257                                break;
258                        case 'h':
259                                usage(argv[0]);
260                                return 1;
261                        case 't':
262                                threadcount = atoi(optarg);
263                                if (threadcount <= 0)
264                                        threadcount = 1;
265                                break;
266                        default:
267                                fprintf(stderr,"Unknown option: %c\n",c);
268                                usage(argv[0]);
269                                return 1;
270                }
271        }
272
273        sigact.sa_handler = cleanup_signal;
274        sigemptyset(&sigact.sa_mask);
275        sigact.sa_flags = SA_RESTART;
276
277        sigaction(SIGINT, &sigact, NULL);
278        sigaction(SIGTERM, &sigact, NULL);
279
280        for(i=optind;i<argc;++i) {
281                run_trace(argv[i], threadcount);
282        }
283        if (optind+1<argc) {
284                printf("Grand total:\n");
285                printf("%30s:\t%12"PRIu64"\t%12" PRIu64 "\n","Total",totcount,totbytes);
286        }
287       
288        return 0;
289}
Note: See TracBrowser for help on using the repository browser.