source: tools/tracestats/tracestats.c @ 9a0e118

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

Update tracestats manpage to include -t option

Set default number of threads to 1 for tracestats, as it probably
isn't going to be doing enough work to warrant the extra thread overhead.

  • Property mode set to 100644
File size: 8.2 KB
Line 
1/*
2 * This file is part of libtrace
3 *
4 * Copyright (c) 2007 The University of Waikato, Hamilton, New Zealand.
5 * Authors: Daniel Lawson
6 *          Perry Lorier
7 *         
8 * All rights reserved.
9 *
10 * This code has been developed by the University of Waikato WAND
11 * research group. For further information please see http://www.wand.net.nz/
12 *
13 * libtrace is free software; you can redistribute it and/or modify
14 * it under the terms of the GNU General Public License as published by
15 * the Free Software Foundation; either version 2 of the License, or
16 * (at your option) any later version.
17 *
18 * libtrace is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
21 * GNU General Public License for more details.
22 *
23 * You should have received a copy of the GNU General Public License
24 * along with libtrace; if not, write to the Free Software
25 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
26 *
27 * $Id$
28 *
29 */
30
31/*
32 * This program takes a series of traces and bpf filters and outputs how many
33 * bytes/packets
34 */
35
36#include <stdio.h>
37#include <stdlib.h>
38#include <assert.h>
39#include <string.h>
40#include <sys/time.h>
41#include <sys/types.h>
42#include <time.h>
43
44#include <netinet/in.h>
45#include <netinet/in_systm.h>
46#include <netinet/tcp.h>
47#include <netinet/ip.h>
48#include <netinet/ip_icmp.h>
49#include <arpa/inet.h>
50#include <sys/socket.h>
51#include <getopt.h>
52#include <inttypes.h>
53#include <signal.h>
54
55#include "libtrace_parallel.h"
56#include "lt_inttypes.h"
57#include <pthread.h>
58
59struct libtrace_t *trace = NULL;
60
61static void cleanup_signal(int signal UNUSED)
62{
63        if (trace)
64                trace_pstop(trace);
65}
66
67struct filter_t {
68        char *expr;
69        struct libtrace_filter_t *filter;
70} *filters = NULL;
71
72int filter_count=0;
73
74
75typedef struct statistics {
76        uint64_t count;
77        uint64_t bytes;
78} statistics_t;
79
80volatile uint64_t totcount = 0;
81volatile uint64_t totbytes = 0;
82
83
84static void fn_result(libtrace_t *trace UNUSED,
85                libtrace_thread_t *sender UNUSED,
86                void *global UNUSED, void *tls,
87                libtrace_result_t *result) {
88        statistics_t *counters = (statistics_t *)tls;
89        int i;
90
91        assert(result->key == 0);
92        statistics_t * res = result->value.ptr;
93        counters[0].count += res[0].count;
94        counters[0].bytes += res[0].bytes;
95
96        for (i = 0; i < filter_count; i++) {
97                counters[i+1].count += res[i+1].count;
98                counters[i+1].bytes += res[i+1].bytes;
99        }
100        free(res);
101}
102
103static void fn_print_results(libtrace_t *trace, 
104                libtrace_thread_t *sender UNUSED, void *global UNUSED,
105                void *tls) {
106
107        statistics_t *counters = (statistics_t *)tls;
108        libtrace_stat_t *stats = NULL;
109        int i;
110
111        stats = trace_get_statistics(trace, NULL);
112        printf("%-30s\t%12s\t%12s\t%7s\n","filter","count","bytes","%");
113        for(i=0;i<filter_count;++i) {
114                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);
115        }
116        if (stats->received_valid)
117                fprintf(stderr,"%30s:\t%12" PRIu64"\n",
118                                "Input packets", stats->received);
119        if (stats->filtered_valid)
120                fprintf(stderr,"%30s:\t%12" PRIu64"\n",
121                                "Filtered packets", stats->filtered);
122        if (stats->dropped_valid)
123                fprintf(stderr,"%30s:\t%12" PRIu64"\n",
124                                "Dropped packets",stats->dropped);
125        if (stats->accepted_valid)
126                fprintf(stderr,"%30s:\t%12" PRIu64 "\n",
127                                "Accepted packets", stats->accepted);
128        if (stats->errors_valid)
129                fprintf(stderr,"%30s:\t%12" PRIu64 "\n",
130                                "Erred packets", stats->errors);
131        printf("%30s:\t%12"PRIu64"\t%12" PRIu64 "\n","Total",counters[0].count,counters[0].bytes);
132        totcount+=counters[0].count;
133        totbytes+=counters[0].bytes;
134
135}
136
137
138static void* fn_starting(libtrace_t *trace UNUSED, libtrace_thread_t *t UNUSED, void *global UNUSED) {
139        /* Allocate space to hold a total count and one for each filter */
140        return calloc(1, sizeof(statistics_t) * (filter_count + 1));
141}
142
143
144static void fn_stopping(libtrace_t *trace, libtrace_thread_t *t UNUSED,
145                        void *global UNUSED, void*tls) {
146        statistics_t *results = (statistics_t *)tls;
147        libtrace_generic_t gen;
148        /* We only output one result per thread with the key 0 when the
149         * trace is over. */
150        gen.ptr = results;
151        trace_publish_result(trace, t, 0, gen, RESULT_USER);
152}
153
154static libtrace_packet_t* fn_packet(libtrace_t *trace,
155                libtrace_thread_t *t UNUSED,
156                void *global UNUSED, void*tls, libtrace_packet_t *pkt) {
157        statistics_t *results = (statistics_t *)tls;
158        int i, wlen;
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.