source: tools/tracesplit/tracesplit.c @ 9672090

4.0.1-hotfixescachetimestampsdevelopdpdk-ndagetsilivegetfragoffhelplibtrace4ndag_formatpfringrc-4.0.1rc-4.0.2rc-4.0.3rc-4.0.4ringdecrementfixringperformanceringtimestampfixes
Last change on this file since 9672090 was 9672090, checked in by Shane Alcock <salcock@…>, 11 years ago
  • tracesplit now accepts multiple input uris, which are read in turn. The last uri provided is treated as the output uri.
  • Property mode set to 100644
File size: 9.3 KB
Line 
1#include <libtrace.h>
2#include <stdio.h>
3#include <stdlib.h>
4#include <inttypes.h>
5#include <lt_inttypes.h>
6#include <stdbool.h>
7#include <getopt.h>
8#include <string.h>
9#include <assert.h>
10#include <signal.h>
11#include <time.h>
12
13/* Global variables */
14struct libtrace_out_t *output = NULL;
15uint64_t count=UINT64_MAX;
16uint64_t bytes=UINT64_MAX;
17uint64_t starttime=0;
18uint64_t endtime=UINT64_MAX;
19uint64_t interval=UINT64_MAX;
20double firsttime=0;
21uint64_t pktcount=0;
22uint64_t totbytes=0;
23uint64_t totbyteslast=0;
24uint64_t maxfiles = UINT64_MAX;
25uint64_t filescreated = 0;
26uint16_t snaplen = 0;
27int verbose=0;
28int compress_level=-1;
29trace_option_compresstype_t compress_type = TRACE_OPTION_COMPRESSTYPE_NONE;
30char *output_base = NULL;
31
32
33static char *strdupcat(char *str,char *app)
34{
35        str=realloc(str,strlen(str)+strlen(app)+1);
36        strcat(str,app);
37        return str;
38}
39
40static char *strdupcati(char *str,uint64_t i)
41{
42        char buffer[64];
43        snprintf(buffer,sizeof(buffer),"%" PRIu64,i);
44        return strdupcat(str,buffer);
45}
46
47static int usage(char *argv0)
48{
49        printf("Usage:\n"
50        "%s flags inputuri [inputuri ... ] outputuri\n"
51        "-f --filter=bpf        only output packets that match filter\n"
52        "-c --count=n           split every n packets\n"
53        "-b --bytes=n           Split every n bytes received\n"
54        "-i --interval=n        Split every n seconds\n"
55        "-s --starttime=time    Start at time\n"
56        "-e --endtime=time      End at time\n"
57        "-m --maxfiles=n        Create a maximum of n trace files\n"
58        "-H --libtrace-help     Print libtrace runtime documentation\n"
59        "-S --snaplen           Snap packets at the specified length\n"
60        "-v --verbose           Output statistics\n"
61        "-z --compress-level    Set compression level\n"
62        "-Z --compress-type     Set compression type\n"
63        ,argv0);
64        exit(1);
65}
66
67volatile int done=0;
68
69static void cleanup_signal(int sig)
70{
71        (void)sig;
72        done=1;
73}
74
75
76/* Return values:
77 *  1 = continue reading packets
78 *  0 = stop reading packets, cos we're done
79 *  -1 = stop reading packets, we've got an error
80 */
81static int per_packet(libtrace_packet_t *packet) {
82
83        if (trace_get_link_type(packet) == ~0U) {
84                fprintf(stderr, "Halted due to being unable to determine linktype - input trace may be corrupt.\n");
85                return -1;
86        }
87
88        if (snaplen>0) {
89                trace_set_capture_length(packet,snaplen);
90        }
91
92        if (trace_get_seconds(packet)<starttime) {
93                return 1;
94        }
95
96        if (trace_get_seconds(packet)>endtime) {
97                return 0;
98        }
99
100        if (firsttime==0) {
101                time_t now = trace_get_seconds(packet);
102                if (starttime != 0) {
103                        firsttime=now-((now - starttime)%interval);
104                }
105                else {
106                        firsttime=now;
107                }
108        }
109
110        if (output && trace_get_seconds(packet)>firsttime+interval) {
111                trace_destroy_output(output);
112                output=NULL;
113                firsttime+=interval;
114        }
115
116        if (output && pktcount%count==0) {
117                trace_destroy_output(output);
118                output=NULL;
119        }
120
121        pktcount++;
122        totbytes+=trace_get_capture_length(packet);
123        if (output && totbytes-totbyteslast>=bytes) {
124                trace_destroy_output(output);
125                output=NULL;
126                totbyteslast=totbytes;
127        }
128        if (!output) {
129                char *buffer;
130                bool need_ext=false;
131                if (maxfiles <= filescreated) {
132                        return 0;
133                }
134                buffer=strdup(output_base);
135                if (interval!=UINT64_MAX && maxfiles>1) {
136                        buffer=strdupcat(buffer,"-");
137                        buffer=strdupcati(buffer,(uint64_t)firsttime);
138                        need_ext=true;
139                }
140                if (count!=UINT64_MAX && maxfiles>1) {
141                        buffer=strdupcat(buffer,"-");
142                        buffer=strdupcati(buffer,(uint64_t)pktcount);
143                        need_ext=true;
144                }
145                if (bytes!=UINT64_MAX && maxfiles>1) {
146                        static int filenum=0;
147                        buffer=strdupcat(buffer,"-");
148                        buffer=strdupcati(buffer,(uint64_t)++filenum);
149                        need_ext=true;
150                }
151                if (need_ext) {
152                        if (compress_level!=0)
153                                buffer=strdupcat(buffer,".gz");
154                }
155                if (verbose>1) {
156                        fprintf(stderr,"%s:",buffer);
157                        if (count!=UINT64_MAX)
158                                fprintf(stderr," count=%" PRIu64,pktcount);
159                        if (bytes!=UINT64_MAX)
160                                fprintf(stderr," bytes=%" PRIu64,bytes);
161                        if (interval!=UINT64_MAX) {
162                                time_t filetime = firsttime;
163                                fprintf(stderr," time=%s",ctime(&filetime));
164                        }
165                        else {
166                                fprintf(stderr,"\n");
167                        }
168                }
169                output=trace_create_output(buffer);
170                if (trace_is_err_output(output)) {
171                        trace_perror_output(output,"%s",buffer);
172                        free(buffer);
173                        return -1;
174                }
175                if (compress_level!=-1) {
176                        if (trace_config_output(output,
177                                                TRACE_OPTION_OUTPUT_COMPRESS,
178                                                &compress_level)==-1) {
179                                trace_perror_output(output,"Unable to set compression level");
180                        }
181                }
182
183                if (trace_config_output(output,
184                                        TRACE_OPTION_OUTPUT_COMPRESSTYPE,
185                                        &compress_type) == -1) {
186                        trace_perror_output(output, "Unable to set compression type");
187                }
188
189                trace_start_output(output);
190                if (trace_is_err_output(output)) {
191                        trace_perror_output(output,"%s",buffer);
192                        free(buffer);
193                        return -1;
194                }
195                free(buffer);
196                filescreated ++;
197        }
198
199        /* Some traces we have are padded (usually with 0x00), so
200         * lets sort that out now and truncate them properly
201         */
202
203        if (trace_get_capture_length(packet) 
204                        > trace_get_wire_length(packet)) {
205                trace_set_capture_length(packet,trace_get_wire_length(packet));
206        }
207
208        if (trace_write_packet(output,packet)==-1) {
209                trace_perror_output(output,"write_packet");
210                return -1;
211        }
212
213        return 1;
214
215}
216
217int main(int argc, char *argv[])
218{
219        char *compress_type_str=NULL;
220        struct libtrace_filter_t *filter=NULL;
221        struct libtrace_t *input;
222        struct libtrace_packet_t *packet = trace_create_packet();
223        struct sigaction sigact;
224        int i; 
225       
226        if (argc<2) {
227                usage(argv[0]);
228                return 1;
229        }
230
231        /* Parse command line options */
232        while(1) {
233                int option_index;
234                struct option long_options[] = {
235                        { "filter",        1, 0, 'f' },
236                        { "count",         1, 0, 'c' },
237                        { "bytes",         1, 0, 'b' },
238                        { "starttime",     1, 0, 's' },
239                        { "endtime",       1, 0, 'e' },
240                        { "interval",      1, 0, 'i' },
241                        { "libtrace-help", 0, 0, 'H' },
242                        { "maxfiles",      1, 0, 'm' },
243                        { "snaplen",       1, 0, 'S' },
244                        { "verbose",       0, 0, 'v' },
245                        { "compress-level", 1, 0, 'z' },
246                        { "compress-type", 1, 0, 'Z' },
247                        { NULL,            0, 0, 0   },
248                };
249
250                int c=getopt_long(argc, argv, "f:c:b:s:e:i:m:S:Hvz:Z:",
251                                long_options, &option_index);
252
253                if (c==-1)
254                        break;
255
256                switch (c) {
257                        case 'f': filter=trace_create_filter(optarg);
258                                break;
259                        case 'c': count=atoi(optarg);
260                                break;
261                        case 'b': bytes=atoi(optarg);
262                                break;
263                        case 's': starttime=atoi(optarg); /* FIXME: use getdate */
264                                  break;
265                        case 'e': endtime=atoi(optarg);
266                                  break;
267                        case 'i': interval=atoi(optarg);
268                                  break;
269                        case 'm': maxfiles=atoi(optarg);
270                                  break;
271                        case 'S': snaplen=atoi(optarg);
272                                  break;
273                        case 'H':
274                                  trace_help();
275                                  exit(1);
276                                  break;
277                        case 'v':
278                                  verbose++;
279                                  break;
280                        case 'z':
281                                  compress_level=atoi(optarg);
282                                  if (compress_level<0 || compress_level>9) {
283                                        usage(argv[0]);
284                                        exit(1);
285                                  }
286                                  break;
287                        case 'Z':
288                                  compress_type_str=optarg;
289                                  break;       
290                        default:
291                                fprintf(stderr,"Unknown option: %c\n",c);
292                                usage(argv[0]);
293                                return 1;
294                }
295        }
296
297        if (compress_type_str == NULL && compress_level >= 0) {
298                fprintf(stderr, "Compression level set, but no compression type was defined, setting to gzip\n");
299                compress_type = TRACE_OPTION_COMPRESSTYPE_ZLIB;
300        }
301
302        else if (compress_type_str == NULL) {
303                /* If a level or type is not specified, use the "none"
304                 * compression module */
305                compress_type = TRACE_OPTION_COMPRESSTYPE_NONE;
306        }
307
308        /* I decided to be fairly generous in what I accept for the
309         * compression type string */
310        else if (strncmp(compress_type_str, "gz", 2) == 0 ||
311                        strncmp(compress_type_str, "zlib", 4) == 0) {
312                compress_type = TRACE_OPTION_COMPRESSTYPE_ZLIB;
313        } else if (strncmp(compress_type_str, "bz", 2) == 0) {
314                compress_type = TRACE_OPTION_COMPRESSTYPE_BZ2;
315        } else if (strncmp(compress_type_str, "lzo", 3) == 0) {
316                compress_type = TRACE_OPTION_COMPRESSTYPE_LZO;
317        } else if (strncmp(compress_type_str, "no", 2) == 0) {
318                compress_type = TRACE_OPTION_COMPRESSTYPE_NONE;
319        } else {
320                fprintf(stderr, "Unknown compression type: %s\n", 
321                        compress_type_str);
322                return 1;
323        }
324
325        if (optind+2>argc) {
326                fprintf(stderr,"missing inputuri or outputuri\n");
327                usage(argv[0]);
328        }
329
330        output_base = argv[argc - 1];
331
332        sigact.sa_handler = cleanup_signal;
333        sigemptyset(&sigact.sa_mask);
334        sigact.sa_flags = SA_RESTART;
335
336        sigaction(SIGINT, &sigact, NULL);
337        sigaction(SIGTERM, &sigact, NULL);
338
339        output=NULL;
340
341        signal(SIGINT,&cleanup_signal);
342        signal(SIGTERM,&cleanup_signal);
343
344        for (i = optind; i < argc - 1; i++) {
345
346
347                input = trace_create(argv[i]); 
348               
349                if (trace_is_err(input)) {
350                        trace_perror(input,"%s",argv[i]);
351                        return 1;
352                }
353
354                if (filter && trace_config(input, TRACE_OPTION_FILTER, filter) == 1) {
355                        trace_perror(input, "Configuring filter for %s", 
356                                        argv[i]);
357                        return 1;
358                }
359
360                if (trace_start(input)==-1) {
361                        trace_perror(input,"%s",argv[i]);
362                        return 1;
363                }
364
365                while (trace_read_packet(input,packet)>0) {
366                        if (per_packet(packet) < 1)
367                                done = 1;
368                        if (done)
369                                break;
370                }
371
372                if (done)
373                        break;
374               
375                if (trace_is_err(input)) {
376                        trace_perror(input,"Reading packets");
377                        trace_destroy(input);
378                        break;
379                }
380
381                trace_destroy(input);
382        }
383
384        if (verbose) {
385                uint64_t f;
386                f=trace_get_received_packets(input);
387                if (f!=UINT64_MAX)
388                        fprintf(stderr,"%" PRIu64 " packets on input\n",f);
389                f=trace_get_filtered_packets(input);
390                if (f!=UINT64_MAX)
391                        fprintf(stderr,"%" PRIu64 " packets filtered\n",f);
392                f=trace_get_dropped_packets(input);
393                if (f!=UINT64_MAX)
394                        fprintf(stderr,"%" PRIu64 " packets dropped\n",f);
395                f=trace_get_accepted_packets(input);
396                if (f!=UINT64_MAX)
397                        fprintf(stderr,"%" PRIu64 " packets accepted\n",f);
398        }
399       
400        if (output)
401                trace_destroy_output(output);
402
403        trace_destroy_packet(packet);
404
405        return 0;
406}
Note: See TracBrowser for help on using the repository browser.