source: examples/parallel/network_capture.c @ 0f5d4de

develop
Last change on this file since 0f5d4de was 0f5d4de, checked in by Shane Alcock <salcock@…>, 22 months ago

Fix bad global variable names in examples

The global names were clashing with names used for function
parameters.

  • Property mode set to 100644
File size: 7.5 KB
Line 
1/* Network Capture
2 *
3 * Creates a file per stream and writes the result to disk. These files can
4 * later be merged using tracemerge to create a single ordered trace file.
5 *
6 * An alternative approach if we want a single output file is to use the
7 * ordered combiner and publish the packets through to a reporter thread that
8 * does the writing to disk.
9 *
10 * Defaults to using 4 threads, but this can be changed using the -t option.
11 */
12/* Note we include libtrace_parallel.h rather then libtrace.h */
13#include "libtrace_parallel.h"
14#include <stdio.h>
15#include <assert.h>
16#include <pthread.h>
17#include <inttypes.h>
18#include <signal.h>
19#include <getopt.h>
20#include <stdlib.h>
21#include <string.h>
22
23static char *outputfile = NULL;
24
25static pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER;
26static int count = 0;
27static libtrace_t *inptrace = NULL;
28
29static int compress_level=-1;
30static trace_option_compresstype_t compress_type = TRACE_OPTION_COMPRESSTYPE_NONE;
31
32static void stop(int signal UNUSED)
33{
34        if (inptrace)
35                trace_pstop(inptrace);
36}
37
38static void usage(char *argv0)
39{
40        fprintf(stderr,"Usage:\n"
41        "%s [options] inputfile outputfile\n"
42        "-t --threads   The number of threads to use\n"
43        "-S --snaplen   The snap length\n"
44        "-H --libtrace-help     Print libtrace runtime documentation\n"
45        "-z --compress-level    Compress the output trace at the specified level\n"
46        "-Z --compress-type     Compress the output trace using the specified"
47        "                       compression algorithm\n"
48        ,argv0);
49        exit(1);
50}
51
52/* Creates an output trace and configures it according to our preferences */
53static libtrace_out_t *create_output(int my_id) {
54        libtrace_out_t *out = NULL;
55        char name[1024];
56        const char * file_index = NULL;
57        const char * first_extension = NULL;
58
59        file_index = strrchr(outputfile, '/');
60        if (file_index)
61                first_extension = strchr(file_index, '.');
62        else
63                first_extension = strchr(name, '.');
64
65        if (first_extension) {
66                snprintf(name, sizeof(name), "%.*s-%d%s", (int) (first_extension - outputfile), outputfile, my_id, first_extension);
67        } else {
68                snprintf(name, sizeof(name), "%s-%d", outputfile, my_id);
69        }
70
71        out = trace_create_output(name);
72        assert(out);
73
74        if (compress_level >= 0 && trace_config_output(out,
75                        TRACE_OPTION_OUTPUT_COMPRESS, &compress_level) == -1) {
76                trace_perror_output(out, "Configuring compression level");
77                trace_destroy_output(out);
78                exit(-1);
79        }
80
81        if (trace_config_output(out, TRACE_OPTION_OUTPUT_COMPRESSTYPE,
82                                &compress_type) == -1) {
83                trace_perror_output(out, "Configuring compression type");
84                trace_destroy_output(out);
85                exit(-1);
86        }
87
88        if (trace_start_output(out)==-1) {
89                trace_perror_output(out,"trace_start_output");
90                trace_destroy_output(out);
91                exit(-1);
92        }
93        return out;
94}
95
96
97static libtrace_packet_t *per_packet(libtrace_t *trace UNUSED,
98                libtrace_thread_t *t UNUSED,
99                void *global UNUSED, void *tls, libtrace_packet_t *packet) {
100
101        /* Retrieve our output trace from the thread local storage */
102        libtrace_out_t *output = (libtrace_out_t *)tls;
103
104        /* Write the packet to disk */
105        trace_write_packet(output, packet);
106
107        /* Return the packet as we are finished with it */
108        return packet;
109
110}
111
112/* Creates an output file for this thread */
113static void *init_process(libtrace_t *trace UNUSED, libtrace_thread_t *t UNUSED,
114                void *global UNUSED) {
115
116        int my_id = 0;
117        libtrace_out_t *out;
118
119        pthread_mutex_lock(&lock);
120        my_id = ++count;
121        pthread_mutex_unlock(&lock);
122        out = create_output(my_id);
123
124        return out;
125}
126
127/* Closes the output file for this thread */
128static void stop_process(libtrace_t *trace UNUSED, libtrace_thread_t *t UNUSED,
129                void *global UNUSED, void *tls) {
130
131        /* Retrieve our output trace from the thread local storage */
132        libtrace_out_t *output = (libtrace_out_t *)tls;
133
134        trace_destroy_output(output);
135}
136
137int main(int argc, char *argv[])
138{
139        struct sigaction sigact;
140        libtrace_stat_t *stats;
141        int snaplen = -1;
142        int nb_threads = 4;     
143        char *compress_type_str=NULL;
144        libtrace_callback_set_t *processing = NULL;
145
146        sigact.sa_handler = stop;
147        sigemptyset(&sigact.sa_mask);
148        sigact.sa_flags = SA_RESTART;
149
150        sigaction(SIGINT, &sigact, NULL);
151
152
153        if (argc<3) {
154                usage(argv[0]);
155                return 1;
156        }
157
158        /* Parse command line options */
159        while(1) {
160                int option_index;
161                struct option long_options[] = {
162                        { "libtrace-help", 0, 0, 'H' },
163                        { "threads",       1, 0, 't' },
164                        { "snaplen",       1, 0, 'S' },
165                        { "compress-level", 1, 0, 'z' },
166                        { "compress-type", 1, 0, 'Z' },
167                        { NULL,            0, 0, 0   },
168                };
169
170                int c=getopt_long(argc, argv, "t:S:Hz:Z:",
171                                  long_options, &option_index);
172
173                if (c==-1)
174                        break;
175
176                switch (c) {
177                case  't': nb_threads = atoi(optarg);
178                        break;
179                case 'S': snaplen=atoi(optarg);
180                        break;
181                case 'H':
182                        trace_help();
183                        exit(1);
184                        break;
185                case 'z':
186                        compress_level=atoi(optarg);
187                        if (compress_level<0 || compress_level>9) {
188                                usage(argv[0]);
189                                exit(1);
190                        }
191                        break;
192                case 'Z':
193                        compress_type_str=optarg;
194                        break;
195                default:
196                        fprintf(stderr,"Unknown option: %c\n",c);
197                        usage(argv[0]);
198                        return 1;
199                }
200        }
201
202        if (compress_type_str == NULL && compress_level >= 0) {
203                fprintf(stderr, "Compression level set, but no compression type was defined, setting to gzip\n");
204                compress_type = TRACE_OPTION_COMPRESSTYPE_ZLIB;
205        }
206
207        else if (compress_type_str == NULL) {
208                /* If a level or type is not specified, use the "none"
209                 * compression module */
210                compress_type = TRACE_OPTION_COMPRESSTYPE_NONE;
211        }
212
213        /* I decided to be fairly generous in what I accept for the
214         * compression type string */
215        else if (strncmp(compress_type_str, "gz", 2) == 0 ||
216                 strncmp(compress_type_str, "zlib", 4) == 0) {
217                compress_type = TRACE_OPTION_COMPRESSTYPE_ZLIB;
218        } else if (strncmp(compress_type_str, "bz", 2) == 0) {
219                compress_type = TRACE_OPTION_COMPRESSTYPE_BZ2;
220        } else if (strncmp(compress_type_str, "lzo", 3) == 0) {
221                compress_type = TRACE_OPTION_COMPRESSTYPE_LZO;
222        } else if (strncmp(compress_type_str, "no", 2) == 0) {
223                compress_type = TRACE_OPTION_COMPRESSTYPE_NONE;
224        } else {
225                fprintf(stderr, "Unknown compression type: %s\n",
226                        compress_type_str);
227                return 1;
228        }
229
230        if (argc-optind != 2) {
231                usage(argv[0]);
232                return 1;
233        }
234        inptrace = trace_create(argv[optind]);
235        outputfile = argv[optind+1];
236
237        if (trace_is_err(inptrace)) {
238                trace_perror(inptrace,"Opening trace file");
239                return 1;
240        }
241
242        /* Set up our callbacks */
243        processing = trace_create_callback_set();
244        trace_set_starting_cb(processing, init_process);
245        trace_set_stopping_cb(processing, stop_process);
246        trace_set_packet_cb(processing, per_packet);
247
248        if (snaplen != -1)
249                trace_set_snaplen(inptrace, snaplen);
250        if(nb_threads != -1)
251                trace_set_perpkt_threads(inptrace, nb_threads);
252
253        /* We use a new version of trace_start(), trace_pstart()
254         * The reporter function argument is optional and can be NULL */
255        if (trace_pstart(inptrace, NULL, processing, NULL)) {
256                trace_perror(inptrace,"Starting trace");
257                trace_destroy(inptrace);
258                trace_destroy_callback_set(processing);
259                return 1;
260        }
261
262        /* Wait for the trace to finish */
263        trace_join(inptrace);
264
265        if (trace_is_err(inptrace)) {
266                trace_perror(inptrace,"Reading packets");
267                trace_destroy(inptrace);
268                trace_destroy_callback_set(processing);
269                return 1;
270        }
271
272        /* Print stats before we destroy the trace */
273        stats = trace_get_statistics(inptrace, NULL);
274        fprintf(stderr, "Overall statistics\n");
275        trace_print_statistics(stats, stderr, "\t%s: %"PRIu64"\n");
276
277        trace_destroy_callback_set(processing);
278        trace_destroy(inptrace);
279        return 0;
280}
Note: See TracBrowser for help on using the repository browser.