source: tools/tracesplit/tracesplit.c @ 2e9df89

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

Fix all outstanding warnings

Implemented trace_get_statistics for formats that were missing it, so
we no longer need to use the deprecated trace_get_dropped_packets anywhere
within libtrace.

  • Property mode set to 100644
File size: 9.8 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        strncat(str,app,strlen(str) + strlen(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        trace_interrupt();
74}
75
76
77/* Return values:
78 *  1 = continue reading packets
79 *  0 = stop reading packets, cos we're done
80 *  -1 = stop reading packets, we've got an error
81 */
82static int per_packet(libtrace_packet_t *packet) {
83
84        if (trace_get_link_type(packet) == -1) {
85                fprintf(stderr, "Halted due to being unable to determine linktype - input trace may be corrupt.\n");
86                return -1;
87        }
88
89        if (snaplen>0) {
90                trace_set_capture_length(packet,snaplen);
91        }
92
93        if (trace_get_seconds(packet)<starttime) {
94                return 1;
95        }
96
97        if (trace_get_seconds(packet)>endtime) {
98                return 0;
99        }
100
101        if (firsttime==0) {
102                time_t now = trace_get_seconds(packet);
103                if (starttime != 0) {
104                        firsttime=now-((now - starttime)%interval);
105                }
106                else {
107                        firsttime=now;
108                }
109        }
110
111        if (output && trace_get_seconds(packet)>firsttime+interval) {
112                trace_destroy_output(output);
113                output=NULL;
114                firsttime+=interval;
115        }
116
117        if (output && pktcount%count==0) {
118                trace_destroy_output(output);
119                output=NULL;
120        }
121
122        pktcount++;
123        totbytes+=trace_get_capture_length(packet);
124        if (output && totbytes-totbyteslast>=bytes) {
125                trace_destroy_output(output);
126                output=NULL;
127                totbyteslast=totbytes;
128        }
129        if (!output) {
130                char *buffer;
131                bool need_ext=false;
132                if (maxfiles <= filescreated) {
133                        return 0;
134                }
135                buffer=strdup(output_base);
136                if (interval!=UINT64_MAX && maxfiles>1) {
137                        buffer=strdupcat(buffer,"-");
138                        buffer=strdupcati(buffer,(uint64_t)firsttime);
139                        need_ext=true;
140                }
141                if (count!=UINT64_MAX && maxfiles>1) {
142                        buffer=strdupcat(buffer,"-");
143                        buffer=strdupcati(buffer,(uint64_t)pktcount);
144                        need_ext=true;
145                }
146                if (bytes!=UINT64_MAX && maxfiles>1) {
147                        static int filenum=0;
148                        buffer=strdupcat(buffer,"-");
149                        buffer=strdupcati(buffer,(uint64_t)++filenum);
150                        need_ext=true;
151                }
152                if (need_ext) {
153                        if (compress_level!=0)
154                                buffer=strdupcat(buffer,".gz");
155                }
156                if (verbose>1) {
157                        fprintf(stderr,"%s:",buffer);
158                        if (count!=UINT64_MAX)
159                                fprintf(stderr," count=%" PRIu64,pktcount);
160                        if (bytes!=UINT64_MAX)
161                                fprintf(stderr," bytes=%" PRIu64,bytes);
162                        if (interval!=UINT64_MAX) {
163                                time_t filetime = firsttime;
164                                fprintf(stderr," time=%s",ctime(&filetime));
165                        }
166                        else {
167                                fprintf(stderr,"\n");
168                        }
169                }
170                output=trace_create_output(buffer);
171                if (trace_is_err_output(output)) {
172                        trace_perror_output(output,"%s",buffer);
173                        free(buffer);
174                        return -1;
175                }
176                if (compress_level!=-1) {
177                        if (trace_config_output(output,
178                                                TRACE_OPTION_OUTPUT_COMPRESS,
179                                                &compress_level)==-1) {
180                                trace_perror_output(output,"Unable to set compression level");
181                        }
182                }
183
184                if (trace_config_output(output,
185                                        TRACE_OPTION_OUTPUT_COMPRESSTYPE,
186                                        &compress_type) == -1) {
187                        trace_perror_output(output, "Unable to set compression type");
188                }
189
190                trace_start_output(output);
191                if (trace_is_err_output(output)) {
192                        trace_perror_output(output,"%s",buffer);
193                        free(buffer);
194                        return -1;
195                }
196                free(buffer);
197                filescreated ++;
198        }
199
200        /* Some traces we have are padded (usually with 0x00), so
201         * lets sort that out now and truncate them properly
202         */
203
204        if (trace_get_capture_length(packet) 
205                        > trace_get_wire_length(packet)) {
206                trace_set_capture_length(packet,trace_get_wire_length(packet));
207        }
208
209        if (trace_write_packet(output,packet)==-1) {
210                trace_perror_output(output,"write_packet");
211                return -1;
212        }
213
214        return 1;
215
216}
217
218int main(int argc, char *argv[])
219{
220        char *compress_type_str=NULL;
221        struct libtrace_filter_t *filter=NULL;
222        struct libtrace_t *input = NULL;
223        struct libtrace_packet_t *packet = trace_create_packet();
224        struct sigaction sigact;
225        int i; 
226       
227        if (argc<2) {
228                usage(argv[0]);
229                return 1;
230        }
231
232        /* Parse command line options */
233        while(1) {
234                int option_index;
235                struct option long_options[] = {
236                        { "filter",        1, 0, 'f' },
237                        { "count",         1, 0, 'c' },
238                        { "bytes",         1, 0, 'b' },
239                        { "starttime",     1, 0, 's' },
240                        { "endtime",       1, 0, 'e' },
241                        { "interval",      1, 0, 'i' },
242                        { "libtrace-help", 0, 0, 'H' },
243                        { "maxfiles",      1, 0, 'm' },
244                        { "snaplen",       1, 0, 'S' },
245                        { "verbose",       0, 0, 'v' },
246                        { "compress-level", 1, 0, 'z' },
247                        { "compress-type", 1, 0, 'Z' },
248                        { NULL,            0, 0, 0   },
249                };
250
251                int c=getopt_long(argc, argv, "f:c:b:s:e:i:m:S:Hvz:Z:",
252                                long_options, &option_index);
253
254                if (c==-1)
255                        break;
256
257                switch (c) {
258                        case 'f': filter=trace_create_filter(optarg);
259                                break;
260                        case 'c': count=atoi(optarg);
261                                break;
262                        case 'b': bytes=atoi(optarg);
263                                break;
264                        case 's': starttime=atoi(optarg); /* FIXME: use getdate */
265                                  break;
266                        case 'e': endtime=atoi(optarg);
267                                  break;
268                        case 'i': interval=atoi(optarg);
269                                  break;
270                        case 'm': maxfiles=atoi(optarg);
271                                  break;
272                        case 'S': snaplen=atoi(optarg);
273                                  break;
274                        case 'H':
275                                  trace_help();
276                                  exit(1);
277                                  break;
278                        case 'v':
279                                  verbose++;
280                                  break;
281                        case 'z':
282                                  compress_level=atoi(optarg);
283                                  if (compress_level<0 || compress_level>9) {
284                                        usage(argv[0]);
285                                        exit(1);
286                                  }
287                                  break;
288                        case 'Z':
289                                  compress_type_str=optarg;
290                                  break;       
291                        default:
292                                fprintf(stderr,"Unknown option: %c\n",c);
293                                usage(argv[0]);
294                                return 1;
295                }
296        }
297
298        if (compress_type_str == NULL && compress_level >= 0) {
299                fprintf(stderr, "Compression level set, but no compression type was defined, setting to gzip\n");
300                compress_type = TRACE_OPTION_COMPRESSTYPE_ZLIB;
301        }
302
303        else if (compress_type_str == NULL) {
304                /* If a level or type is not specified, use the "none"
305                 * compression module */
306                compress_type = TRACE_OPTION_COMPRESSTYPE_NONE;
307        }
308
309        /* I decided to be fairly generous in what I accept for the
310         * compression type string */
311        else if (strncmp(compress_type_str, "gz", 2) == 0 ||
312                        strncmp(compress_type_str, "zlib", 4) == 0) {
313                compress_type = TRACE_OPTION_COMPRESSTYPE_ZLIB;
314        } else if (strncmp(compress_type_str, "bz", 2) == 0) {
315                compress_type = TRACE_OPTION_COMPRESSTYPE_BZ2;
316        } else if (strncmp(compress_type_str, "lzo", 3) == 0) {
317                compress_type = TRACE_OPTION_COMPRESSTYPE_LZO;
318        } else if (strncmp(compress_type_str, "xz", 2) == 0) {
319                compress_type = TRACE_OPTION_COMPRESSTYPE_LZMA;
320        } else if (strncmp(compress_type_str, "no", 2) == 0) {
321                compress_type = TRACE_OPTION_COMPRESSTYPE_NONE;
322        } else {
323                fprintf(stderr, "Unknown compression type: %s\n", 
324                        compress_type_str);
325                return 1;
326        }
327
328        if (optind+2>argc) {
329                fprintf(stderr,"missing inputuri or outputuri\n");
330                usage(argv[0]);
331        }
332
333        output_base = argv[argc - 1];
334
335        sigact.sa_handler = cleanup_signal;
336        sigemptyset(&sigact.sa_mask);
337        sigact.sa_flags = SA_RESTART;
338
339        sigaction(SIGINT, &sigact, NULL);
340        sigaction(SIGTERM, &sigact, NULL);
341
342        output=NULL;
343
344        signal(SIGINT,&cleanup_signal);
345        signal(SIGTERM,&cleanup_signal);
346
347        for (i = optind; i < argc - 1; i++) {
348
349
350                input = trace_create(argv[i]); 
351               
352                if (trace_is_err(input)) {
353                        trace_perror(input,"%s",argv[i]);
354                        return 1;
355                }
356
357                if (filter && trace_config(input, TRACE_OPTION_FILTER, filter) == 1) {
358                        trace_perror(input, "Configuring filter for %s", 
359                                        argv[i]);
360                        return 1;
361                }
362
363                if (trace_start(input)==-1) {
364                        trace_perror(input,"%s",argv[i]);
365                        return 1;
366                }
367
368                while (trace_read_packet(input,packet)>0) {
369                        if (per_packet(packet) < 1)
370                                done = 1;
371                        if (done)
372                                break;
373                }
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                if (done)
384                        break;
385               
386        }
387
388        if (verbose) {
389                libtrace_stat_t *stat;
390               
391                stat = trace_create_statistics();
392                trace_get_statistics(input, stat);
393
394                if (stat->received_valid)
395                        fprintf(stderr,"%" PRIu64 " packets on input\n",
396                                        stat->received);
397                if (stat->filtered_valid)
398                        fprintf(stderr,"%" PRIu64 " packets filtered\n",
399                                        stat->filtered);
400                if (stat->dropped_valid)
401                        fprintf(stderr,"%" PRIu64 " packets dropped\n",
402                                        stat->dropped);
403                if (stat->accepted_valid)
404                        fprintf(stderr,"%" PRIu64 " packets accepted\n",
405                                        stat->accepted);
406                free(stat);
407        }
408       
409        if (output)
410                trace_destroy_output(output);
411
412        trace_destroy_packet(packet);
413
414        return 0;
415}
Note: See TracBrowser for help on using the repository browser.