source: tools/tracesplit/tracesplit.c @ 0896e76

4.0.1-hotfixescachetimestampsdevelopdpdk-ndagetsilivegetfragoffhelplibtrace4ndag_formatpfringrc-4.0.1rc-4.0.2rc-4.0.3rc-4.0.4ringdecrementfixringperformanceringtimestampfixes
Last change on this file since 0896e76 was 0896e76, checked in by Scott Raynel <smr26@…>, 11 years ago

tracesplit.c: Always include the system <inttypes.h> to avoid incorrect
definition of the PRI types. All other tools follow this pattern.

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