source: tools/tracemerge/tracemerge.c @ 8e11beb

cachetimestampsdevelopdpdk-ndagetsilivendag_formatrc-4.0.2rc-4.0.3rc-4.0.4ringdecrementfixringperformance
Last change on this file since 8e11beb was 8e11beb, checked in by Shane Alcock <salcock@…>, 3 years ago

Update tools to properly ignore meta records and missing timestamps

pcapng introduces a lot of meta records that we should preserve as
long as possible. Since we aren't automatically discarding them,
we need to make sure that our tools do not try to treat them as
"real" packets, i.e. try to get a timestamp or capture length from
them.

Similarly, simple pcapng packet records do not have a timestamp
so we need to make sure the tools do the right thing when
trace_get_seconds() returns a timestamp of zero on a packet. For
starters, we don't want to set our "first" packet time to zero
in that case!

  • Property mode set to 100644
File size: 7.4 KB
Line 
1/*
2 *
3 * Copyright (c) 2007-2016 The University of Waikato, Hamilton, New Zealand.
4 * All rights reserved.
5 *
6 * This file is part of libtrace.
7 *
8 * This code has been developed by the University of Waikato WAND
9 * research group. For further information please see http://www.wand.net.nz/
10 *
11 * libtrace is free software; you can redistribute it and/or modify
12 * it under the terms of the GNU Lesser General Public License as published by
13 * the Free Software Foundation; either version 3 of the License, or
14 * (at your option) any later version.
15 *
16 * libtrace is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19 * GNU Lesser General Public License for more details.
20 *
21 * You should have received a copy of the GNU Lesser General Public License
22 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
23 *
24 *
25 */
26
27
28#include <libtrace.h>
29#include <stdio.h>
30#include <stdlib.h>
31#include <inttypes.h>
32#include <stdbool.h>
33#include <getopt.h>
34#include <signal.h>
35#include <string.h>
36
37static void usage(char *argv0)
38{
39        fprintf(stderr,"Usage:\n"
40        "%s flags outputuri traceuri [traceuri...]\n"
41        "-i [interfaces_per_input] --set-interface [interfaces_per_input]\n"
42        "                       Each trace is allocated an interface. Default leaves this flag as\n"
43        "                       read from the original traces, if appropriate\n"
44        "-u --unique-packets    Discard duplicate packets\n"
45        "-z level --compress-level level\n"
46        "                       Compression level\n"
47        "-Z method --compress-type method\n"
48        "                       Compression method\n"
49        "-H --libtrace-help     Print libtrace runtime documentation\n"
50        ,argv0);
51        exit(1);
52}
53
54volatile int done=0;
55
56static void cleanup_signal(int sig UNUSED)
57{
58        done=1;
59        trace_interrupt();
60}
61
62int main(int argc, char *argv[])
63{
64       
65        struct libtrace_out_t *output;
66        struct libtrace_t **input;
67        struct libtrace_packet_t **packet;
68        bool *live;
69        int interfaces_per_input=0;
70        bool unique_packets=false;
71        int i=0;
72        uint64_t last_ts=0;
73        struct sigaction sigact;
74        int compression=-1;
75        char *compress_type_str = NULL;
76        trace_option_compresstype_t compress_type = TRACE_OPTION_COMPRESSTYPE_NONE;
77
78        while (1) {
79                int option_index;
80                struct option long_options[] = {
81                        { "set-interface",      2, 0, 'i' },
82                        { "unique-packets",     0, 0, 'u' },
83                        { "libtrace-help",      0, 0, 'H' },
84                        { "compress-level",     1, 0, 'z' },
85                        { "compress-type",      1, 0, 'Z' },
86                        { NULL,                 0, 0, 0   },
87                };
88
89                int c=getopt_long(argc, argv, "i::uHz:Z:",
90                                long_options, &option_index);
91
92                if (c==-1)
93                        break;
94
95                switch (c) {
96                        case 'i':
97                                if (optarg) 
98                                        interfaces_per_input=atoi(optarg);
99                                else
100                                        interfaces_per_input=1;
101                                break;
102                        case 'u': unique_packets=true; break;
103                        case 'H':
104                                  trace_help();
105                                  exit(1);
106                                  break;
107                        case 'z':
108                                compression = atoi(optarg);
109                                if (compression<0 || compression>9) {
110                                        fprintf(stderr,"Compression level must be between 0 and 9\n");
111                                        usage(argv[0]);
112                                }
113                                break;
114
115                        case 'Z':
116                                compress_type_str = optarg;
117                                break;
118                        default:
119                                fprintf(stderr,"unknown option: %c\n",c);
120                                usage(argv[0]);
121
122                }
123
124        }
125
126        if (optind+2>argc)
127                usage(argv[0]);
128
129        if (compress_type_str == NULL && compression >= 0) {
130                fprintf(stderr, "Compression level set, but no compression type was defined, setting to gzip\n");
131                compress_type = TRACE_OPTION_COMPRESSTYPE_ZLIB;
132        }
133
134        else if (compress_type_str == NULL) {
135                /* If a level or type is not specified, use the "none"
136                 * compression module */
137                compress_type = TRACE_OPTION_COMPRESSTYPE_NONE;
138        }
139
140        /* I decided to be fairly generous in what I accept for the
141         * compression type string */
142        else if (strncmp(compress_type_str, "gz", 2) == 0 ||
143                        strncmp(compress_type_str, "zlib", 4) == 0) {
144                compress_type = TRACE_OPTION_COMPRESSTYPE_ZLIB;
145        } else if (strncmp(compress_type_str, "bz", 2) == 0) {
146                compress_type = TRACE_OPTION_COMPRESSTYPE_BZ2;
147        } else if (strncmp(compress_type_str, "lzo", 3) == 0) {
148                compress_type = TRACE_OPTION_COMPRESSTYPE_LZO;
149        } else if (strncmp(compress_type_str, "xz", 2) == 0) {
150                compress_type = TRACE_OPTION_COMPRESSTYPE_LZMA;
151        } else if (strncmp(compress_type_str, "no", 2) == 0) {
152                compress_type = TRACE_OPTION_COMPRESSTYPE_NONE;
153        } else {
154                fprintf(stderr, "Unknown compression type: %s\n",
155                        compress_type_str);
156                return 1;
157        }
158
159
160        output=trace_create_output(argv[optind++]);
161        if (trace_is_err_output(output)) {
162                trace_perror_output(output,"trace_create_output");
163                return 1;
164        }
165
166        if (compression >= 0 && 
167                        trace_config_output(output, 
168                        TRACE_OPTION_OUTPUT_COMPRESS, &compression) == -1) {
169                trace_perror_output(output,"Unable to set compression level");
170                return 1;
171        }
172
173        if (trace_config_output(output, TRACE_OPTION_OUTPUT_COMPRESSTYPE,
174                        &compress_type) == -1) {
175                trace_perror_output(output, "Unable to set compression method");
176                return 1;
177        }
178
179        if (trace_start_output(output)==-1) {
180                trace_perror_output(output,"trace_start_output");
181                return 1;
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        input=calloc((size_t)(argc-optind),sizeof(struct libtrace_t *));
192        packet=calloc((size_t)(argc-optind),sizeof(struct libtrace_packet_t *));
193        live=calloc((size_t)(argc-optind),sizeof(bool));
194        for(i=0;i<argc-optind;++i) {
195                libtrace_t *f;
196                libtrace_packet_t *p;
197                f=trace_create(argv[i+optind]);
198                if (trace_is_err(f)) {
199                        trace_perror(f,"trace_create");
200                        return 1;
201                }
202                if (trace_start(f)==-1) {
203                        trace_perror(f,"trace_start");
204                        return 1;
205                }
206                p=trace_create_packet();
207                input[i]=f;
208                packet[i]=p;
209                if (trace_read_packet(f,packet[i])>0)
210                        live[i]=true;
211        }
212
213        while(1) {
214                uint64_t oldest_ts=0;
215                uint64_t this_ts = 0;
216                int oldest=-1;
217                int curr_dir;
218                if (done)
219                        break;
220                for(i=0;i<argc-optind;++i) {
221                        if (!live[i] && input[i]) {
222                                int ret=trace_read_packet(input[i],packet[i]);
223                                if (ret<0) {
224                                        /* Error */
225                                        trace_perror(input[i], "%s", argv[i+2]);
226                                        trace_destroy(input[i]);
227                                        input[i]=NULL;
228                                }
229                                else if (ret==0) {
230                                        /* EOF */
231                                        trace_destroy(input[i]);
232                                        input[i]=NULL;
233                                }
234                                else
235                                        live[i]=true;
236                        }
237                        if (live[i]) {
238                                this_ts = trace_get_erf_timestamp(packet[i]);
239                                if (this_ts != 0 && (oldest==-1 ||
240                                                oldest_ts>this_ts)) {
241                                        oldest=i;
242                                        oldest_ts=this_ts;
243                                }
244                        }
245                }
246                /* We have run out of packets! */
247                if (oldest==-1) {
248                        break;
249                }
250
251                live[oldest]=false;
252
253                curr_dir = trace_get_direction(packet[oldest]);
254                if (curr_dir != -1 && interfaces_per_input) {
255                        /* If there are more interfaces than
256                         * interfaces_per_input, then clamp at the
257                         * highest input.  This means things should
258                         * end up in "OTHER" or the unused 3rd bin if
259                         * we're lucky */
260                        curr_dir = curr_dir < interfaces_per_input
261                                ? curr_dir
262                                : interfaces_per_input-1;
263
264                        trace_set_direction(packet[oldest],
265                                        oldest*interfaces_per_input
266                                        +curr_dir);
267                }
268
269                if (unique_packets && oldest_ts == last_ts)
270                        continue;
271
272                if (trace_write_packet(output,packet[oldest]) < 0) {
273                        trace_perror_output(output, "trace_write_packet");
274                        break;
275                }
276
277                last_ts=oldest_ts;
278               
279        }
280        trace_destroy_output(output);
281
282        return 0;
283}
Note: See TracBrowser for help on using the repository browser.