source: tools/tracestats/tracestats.c @ 322c516

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

Port tracestats to new parallel API

Old single-threaded tracestats has been moved to tracestats_single.c, which
won't be built or distributed.

  • Property mode set to 100644
File size: 8.2 KB
RevLine 
[130a0e4]1/*
2 * This file is part of libtrace
3 *
[d5a27e8]4 * Copyright (c) 2007 The University of Waikato, Hamilton, New Zealand.
[130a0e4]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
[853603a]31/*
32 * This program takes a series of traces and bpf filters and outputs how many
33 * bytes/packets
34 */
[130a0e4]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>
[2cf30f6]53#include <signal.h>
[130a0e4]54
[322c516]55#include "libtrace_parallel.h"
[dd1217b]56#include "lt_inttypes.h"
[322c516]57#include <pthread.h>
[4e65f42]58
[322c516]59struct libtrace_t *trace = NULL;
[130a0e4]60
[322c516]61static void cleanup_signal(int signal UNUSED)
[2cf30f6]62{
[322c516]63        if (trace)
64                trace_pstop(trace);
[2cf30f6]65}
66
[130a0e4]67struct filter_t {
68        char *expr;
69        struct libtrace_filter_t *filter;
70} *filters = NULL;
[322c516]71
[130a0e4]72int filter_count=0;
[322c516]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}
[130a0e4]180
181/* Process a trace, counting packets that match filter(s) */
[322c516]182static void run_trace(char *uri, int threadcount)
[130a0e4]183{
184
185        fprintf(stderr,"%s:\n",uri);
[322c516]186        libtrace_callback_set_t *pktcbs, *rescbs;
[130a0e4]187
[322c516]188        trace = trace_create(uri);
[130a0e4]189
[e49ec63]190        if (trace_is_err(trace)) {
[a8f2692]191                trace_perror(trace,"Failed to create trace");
[e49ec63]192                return;
193        }
194
[322c516]195        pktcbs = trace_create_callback_set();
196        rescbs = trace_create_callback_set();
[e49ec63]197
[322c516]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);
[e49ec63]204
[322c516]205        if (threadcount != 0)
206                trace_set_perpkt_threads(trace, threadcount);
[130a0e4]207
[322c516]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;
[5ab626a]212        }
213
[322c516]214        /* Wait for all threads to stop */
215        trace_join(trace);
[130a0e4]216
[ec0f8f1]217        if (trace_is_err(trace))
[322c516]218                trace_perror(trace,"%s",uri);
[ec0f8f1]219
[322c516]220        trace_destroy(trace);
221        trace_destroy_callback_set(pktcbs);
222        trace_destroy_callback_set(rescbs);
[130a0e4]223}
224
[a7282fb]225static void usage(char *argv0)
[130a0e4]226{
[322c516]227        fprintf(stderr,"Usage: %s [-h|--help] [--threads|-t threads] [--filter|-f bpf ]... libtraceuri...\n",argv0);
[130a0e4]228}
229
230int main(int argc, char *argv[]) {
231
232        int i;
[2cf30f6]233        struct sigaction sigact;
[322c516]234        int threadcount = 4;
[130a0e4]235
236        while(1) {
237                int option_index;
238                struct option long_options[] = {
[66caf4b]239                        { "filter",        1, 0, 'f' },
[322c516]240                        { "help", 0, 0, 'h' },
241                        { "threads",            1, 0, 't' },
[66caf4b]242                        { NULL,            0, 0, 0   },
[130a0e4]243                };
244
[322c516]245                int c=getopt_long(argc, argv, "f:ht:",
[130a0e4]246                                long_options, &option_index);
247
248                if (c==-1)
249                        break;
250
251                switch (c) {
[322c516]252                        case 'f':
[130a0e4]253                                ++filter_count;
254                                filters=realloc(filters,filter_count*sizeof(struct filter_t));
255                                filters[filter_count-1].expr=strdup(optarg);
[853603a]256                                filters[filter_count-1].filter=trace_create_filter(optarg);
[66caf4b]257                                break;
[322c516]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:
[130a0e4]267                                fprintf(stderr,"Unknown option: %c\n",c);
268                                usage(argv[0]);
269                                return 1;
270                }
271        }
272
[2cf30f6]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
[130a0e4]280        for(i=optind;i<argc;++i) {
[322c516]281                run_trace(argv[i], threadcount);
[130a0e4]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        }
[322c516]287       
288        return 0;
[130a0e4]289}
Note: See TracBrowser for help on using the repository browser.